diff options
author | Richard Henderson <rth@twiddle.net> | 2013-03-12 10:34:18 -0700 |
---|---|---|
committer | Aurelien Jarno <aurelien@aurel32.net> | 2013-04-27 02:16:44 +0200 |
commit | 34358a12c8a8f2f85a1420fa0a1112de1c6a55af (patch) | |
tree | b71d71e6820aaafc5088246215e037394386fbe6 | |
parent | 13dd6fb962930a4b1d74f9b22342d1eb15e9194e (diff) |
tcg-arm: Cleanup multiply subroutines
Make the code more readable by only having one copy of the magic
numbers, swapping registers as needed prior to that. Speed the
compiler by not applying the rd == rn avoidance for v6 or later.
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Richard Henderson <rth@twiddle.net>
-rw-r--r-- | tcg/arm/tcg-target.c | 85 |
1 files changed, 45 insertions, 40 deletions
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index ff75379f55..4c9a9dc980 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -548,55 +548,60 @@ static void tcg_out_dat_rIN(TCGContext *s, int cond, int opc, int opneg, } } -static inline void tcg_out_mul32(TCGContext *s, - int cond, int rd, int rs, int rm) -{ - if (rd != rm) - tcg_out32(s, (cond << 28) | (rd << 16) | (0 << 12) | - (rs << 8) | 0x90 | rm); - else if (rd != rs) - tcg_out32(s, (cond << 28) | (rd << 16) | (0 << 12) | - (rm << 8) | 0x90 | rs); - else { - tcg_out32(s, (cond << 28) | (TCG_REG_TMP << 16) | (0 << 12) | - (rs << 8) | 0x90 | rm); - tcg_out_dat_reg(s, cond, ARITH_MOV, - rd, 0, TCG_REG_TMP, SHIFT_IMM_LSL(0)); +static inline void tcg_out_mul32(TCGContext *s, int cond, TCGReg rd, + TCGReg rn, TCGReg rm) +{ + /* if ArchVersion() < 6 && d == n then UNPREDICTABLE; */ + if (!use_armv6_instructions && rd == rn) { + if (rd == rm) { + /* rd == rn == rm; copy an input to tmp first. */ + tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn); + rm = rn = TCG_REG_TMP; + } else { + rn = rm; + rm = rd; + } } + /* mul */ + tcg_out32(s, (cond << 28) | 0x90 | (rd << 16) | (rm << 8) | rn); } -static inline void tcg_out_umull32(TCGContext *s, - int cond, int rd0, int rd1, int rs, int rm) +static inline void tcg_out_umull32(TCGContext *s, int cond, TCGReg rd0, + TCGReg rd1, TCGReg rn, TCGReg rm) { - if (rd0 != rm && rd1 != rm) - tcg_out32(s, (cond << 28) | 0x800090 | - (rd1 << 16) | (rd0 << 12) | (rs << 8) | rm); - else if (rd0 != rs && rd1 != rs) - tcg_out32(s, (cond << 28) | 0x800090 | - (rd1 << 16) | (rd0 << 12) | (rm << 8) | rs); - else { - tcg_out_dat_reg(s, cond, ARITH_MOV, - TCG_REG_TMP, 0, rm, SHIFT_IMM_LSL(0)); - tcg_out32(s, (cond << 28) | 0x800090 | TCG_REG_TMP | - (rd1 << 16) | (rd0 << 12) | (rs << 8)); + /* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE; */ + if (!use_armv6_instructions && (rd0 == rn || rd1 == rn)) { + if (rd0 == rm || rd1 == rm) { + tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn); + rn = TCG_REG_TMP; + } else { + TCGReg t = rn; + rn = rm; + rm = t; + } } + /* umull */ + tcg_out32(s, (cond << 28) | 0x00800090 | + (rd1 << 16) | (rd0 << 12) | (rm << 8) | rn); } -static inline void tcg_out_smull32(TCGContext *s, - int cond, int rd0, int rd1, int rs, int rm) +static inline void tcg_out_smull32(TCGContext *s, int cond, TCGReg rd0, + TCGReg rd1, TCGReg rn, TCGReg rm) { - if (rd0 != rm && rd1 != rm) - tcg_out32(s, (cond << 28) | 0xc00090 | - (rd1 << 16) | (rd0 << 12) | (rs << 8) | rm); - else if (rd0 != rs && rd1 != rs) - tcg_out32(s, (cond << 28) | 0xc00090 | - (rd1 << 16) | (rd0 << 12) | (rm << 8) | rs); - else { - tcg_out_dat_reg(s, cond, ARITH_MOV, - TCG_REG_TMP, 0, rm, SHIFT_IMM_LSL(0)); - tcg_out32(s, (cond << 28) | 0xc00090 | TCG_REG_TMP | - (rd1 << 16) | (rd0 << 12) | (rs << 8)); + /* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE; */ + if (!use_armv6_instructions && (rd0 == rn || rd1 == rn)) { + if (rd0 == rm || rd1 == rm) { + tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn); + rn = TCG_REG_TMP; + } else { + TCGReg t = rn; + rn = rm; + rm = t; + } } + /* smull */ + tcg_out32(s, (cond << 28) | 0x00c00090 | + (rd1 << 16) | (rd0 << 12) | (rm << 8) | rn); } static inline void tcg_out_sdiv(TCGContext *s, int cond, int rd, int rn, int rm) |