diff options
Diffstat (limited to 'tcg/arm')
-rw-r--r-- | tcg/arm/tcg-target.c | 34 | ||||
-rw-r--r-- | tcg/arm/tcg-target.h | 2 |
2 files changed, 34 insertions, 2 deletions
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index 1edcd103f3..6cfe1d6670 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -990,7 +990,22 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond, # endif *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2; -#else +#else /* !CONFIG_SOFTMMU */ + if (GUEST_BASE) { + uint32_t offset = GUEST_BASE; + int i; + int rot; + + while (offset) { + i = ctz32(offset) & ~1; + rot = ((32 - i) << 7) & 0xf00; + + tcg_out_dat_imm(s, COND_AL, ARITH_ADD, 8, addr_reg, + ((offset >> i) & 0xff) | rot); + addr_reg = 8; + offset &= ~(0xff << i); + } + } switch (opc) { case 0: tcg_out_ld8_12(s, COND_AL, data_reg, addr_reg, 0); @@ -1200,7 +1215,22 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond, # endif *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2; -#else +#else /* !CONFIG_SOFTMMU */ + if (GUEST_BASE) { + uint32_t offset = GUEST_BASE; + int i; + int rot; + + while (offset) { + i = ctz32(offset) & ~1; + rot = ((32 - i) << 7) & 0xf00; + + tcg_out_dat_imm(s, COND_AL, ARITH_ADD, 8, addr_reg, + ((offset >> i) & 0xff) | rot); + addr_reg = 8; + offset &= ~(0xff << i); + } + } switch (opc) { case 0: tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0); diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index 78ab8fd3e5..ffa9ceeca0 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -60,6 +60,8 @@ enum { #define TCG_TARGET_STACK_ALIGN 8 #define TCG_TARGET_CALL_STACK_OFFSET 0 +#define TCG_TARGET_HAS_GUEST_BASE + enum { /* Note: must be synced with dyngen-exec.h */ TCG_AREG0 = TCG_REG_R7, |