diff options
Diffstat (limited to 'tcg/arm')
-rw-r--r-- | tcg/arm/tcg-target.c | 72 | ||||
-rw-r--r-- | tcg/arm/tcg-target.h | 8 |
2 files changed, 53 insertions, 27 deletions
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index dee1ebc..8139da1 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -21,7 +21,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -const char *tcg_target_reg_names[TCG_TARGET_NB_REGS] = { + +#ifndef NDEBUG +static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { "%r0", "%r1", "%r2", @@ -38,8 +40,9 @@ const char *tcg_target_reg_names[TCG_TARGET_NB_REGS] = { "%r13", "%r14", }; +#endif -int tcg_target_reg_alloc_order[] = { +static const int tcg_target_reg_alloc_order[] = { TCG_REG_R0, TCG_REG_R1, TCG_REG_R2, @@ -57,10 +60,10 @@ int tcg_target_reg_alloc_order[] = { TCG_REG_R14, }; -const int tcg_target_call_iarg_regs[4] = { +static const int tcg_target_call_iarg_regs[4] = { TCG_REG_R0, TCG_REG_R1, TCG_REG_R2, TCG_REG_R3 }; -const int tcg_target_call_oarg_regs[2] = { +static const int tcg_target_call_oarg_regs[2] = { TCG_REG_R0, TCG_REG_R1 }; @@ -91,7 +94,7 @@ static inline int tcg_target_get_call_iarg_regs_count(int flags) } /* parse target specific constraints */ -int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) +static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) { const char *ct_str; @@ -292,10 +295,19 @@ static inline void tcg_out_dat_reg2(TCGContext *s, int cond, int opc0, int opc1, int rd0, int rd1, int rn0, int rn1, int rm0, int rm1, int shift) { - tcg_out32(s, (cond << 28) | (0 << 25) | (opc0 << 21) | (1 << 20) | - (rn0 << 16) | (rd0 << 12) | shift | rm0); - tcg_out32(s, (cond << 28) | (0 << 25) | (opc1 << 21) | - (rn1 << 16) | (rd1 << 12) | shift | rm1); + if (rd0 == rn1 || rd0 == rm1) { + tcg_out32(s, (cond << 28) | (0 << 25) | (opc0 << 21) | (1 << 20) | + (rn0 << 16) | (8 << 12) | shift | rm0); + tcg_out32(s, (cond << 28) | (0 << 25) | (opc1 << 21) | + (rn1 << 16) | (rd1 << 12) | shift | rm1); + tcg_out_dat_reg(s, cond, ARITH_MOV, + rd0, 0, TCG_REG_R8, SHIFT_IMM_LSL(0)); + } else { + tcg_out32(s, (cond << 28) | (0 << 25) | (opc0 << 21) | (1 << 20) | + (rn0 << 16) | (rd0 << 12) | shift | rm0); + tcg_out32(s, (cond << 28) | (0 << 25) | (opc1 << 21) | + (rn1 << 16) | (rd1 << 12) | shift | rm1); + } } static inline void tcg_out_dat_imm(TCGContext *s, @@ -846,10 +858,10 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond, else data_reg2 = 0; /* surpress warning */ addr_reg = *args++; -#if TARGET_LONG_BITS == 64 - addr_reg2 = *args++; -#endif #ifdef CONFIG_SOFTMMU +# if TARGET_LONG_BITS == 64 + addr_reg2 = *args++; +# endif mem_index = *args; s_bits = opc & 3; @@ -999,8 +1011,13 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond, case 3: /* TODO: use block load - * check that data_reg2 > data_reg or the other way */ - tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0); - tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, 4); + if (data_reg == addr_reg) { + tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, 4); + tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0); + } else { + tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0); + tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, 4); + } break; } #endif @@ -1024,10 +1041,10 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond, else data_reg2 = 0; /* surpress warning */ addr_reg = *args++; -#if TARGET_LONG_BITS == 64 - addr_reg2 = *args++; -#endif #ifdef CONFIG_SOFTMMU +# if TARGET_LONG_BITS == 64 + addr_reg2 = *args++; +# endif mem_index = *args; s_bits = opc & 3; @@ -1229,19 +1246,24 @@ static inline void tcg_out_op(TCGContext *s, int opc, if (args[0] >> 8) tcg_out32(s, args[0]); #else - if (args[0] >> 8) - tcg_out_ld32_12(s, COND_AL, 0, 15, 0); - else - tcg_out_dat_imm(s, COND_AL, ARITH_MOV, 0, 0, args[0]); - tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr); - if (args[0] >> 8) - tcg_out32(s, args[0]); + { + uint8_t *ld_ptr = s->code_ptr; + if (args[0] >> 8) + tcg_out_ld32_12(s, COND_AL, 0, 15, 0); + else + tcg_out_dat_imm(s, COND_AL, ARITH_MOV, 0, 0, args[0]); + tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr); + if (args[0] >> 8) { + *ld_ptr = (uint8_t) (s->code_ptr - ld_ptr) - 8; + tcg_out32(s, args[0]); + } + } #endif break; case INDEX_op_goto_tb: if (s->tb_jmp_offset) { /* Direct jump method */ -#if 1 +#if defined(USE_DIRECT_JUMP) s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; tcg_out_b(s, COND_AL, 8); #else diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index 6c180af..8f5016f 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -28,7 +28,7 @@ #undef TCG_TARGET_WORDS_BIGENDIAN #undef TCG_TARGET_HAS_div_i32 #undef TCG_TARGET_HAS_div_i64 -#undef TCG_TARGET_HAS_bswap_i32 +#undef TCG_TARGET_HAS_bswap32_i32 #define TCG_TARGET_HAS_ext8s_i32 #define TCG_TARGET_HAS_ext16s_i32 #define TCG_TARGET_HAS_neg_i32 @@ -64,13 +64,17 @@ enum { TCG_AREG0 = TCG_REG_R7, TCG_AREG1 = TCG_REG_R4, TCG_AREG2 = TCG_REG_R5, - TCG_AREG3 = TCG_REG_R6, }; static inline void flush_icache_range(unsigned long start, unsigned long stop) { +#if QEMU_GNUC_PREREQ(4, 1) + void __clear_cache(char *beg, char *end); + __clear_cache((char *) start, (char *) stop); +#else register unsigned long _beg __asm ("a1") = start; register unsigned long _end __asm ("a2") = stop; register unsigned long _flg __asm ("a3") = 0; __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg)); +#endif } |