From 30c7183b676076c940538b838c330c854a7995a9 Mon Sep 17 00:00:00 2001 From: aurel32 Date: Tue, 16 Sep 2008 22:44:10 +0000 Subject: [PATCH] target-alpha: convert some arith3 instructions to TCG Replace gen_arith3 generic macro and dyngen ops by instruction specific optimized TCG code. Signed-off-by: Aurelien Jarno git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5236 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-alpha/op.c | 90 ------- target-alpha/translate.c | 491 ++++++++++++++++++++++++++++++++------- 2 files changed, 408 insertions(+), 173 deletions(-) diff --git a/target-alpha/op.c b/target-alpha/op.c index 651900fbab..b07b3d969c 100644 --- a/target-alpha/op.c +++ b/target-alpha/op.c @@ -198,72 +198,36 @@ void OPPROTO op_clear_irf (void) } /* Arithmetic */ -void OPPROTO op_addq (void) -{ - T0 += T1; - RETURN(); -} - void OPPROTO op_addqv (void) { helper_addqv(); RETURN(); } -void OPPROTO op_addl (void) -{ - T0 = (int64_t)((int32_t)(T0 + T1)); - RETURN(); -} - void OPPROTO op_addlv (void) { helper_addlv(); RETURN(); } -void OPPROTO op_subq (void) -{ - T0 -= T1; - RETURN(); -} - void OPPROTO op_subqv (void) { helper_subqv(); RETURN(); } -void OPPROTO op_subl (void) -{ - T0 = (int64_t)((int32_t)(T0 - T1)); - RETURN(); -} - void OPPROTO op_sublv (void) { helper_sublv(); RETURN(); } -void OPPROTO op_mull (void) -{ - T0 = (int64_t)((int32_t)T0 * (int32_t)T1); - RETURN(); -} - void OPPROTO op_mullv (void) { helper_mullv(); RETURN(); } -void OPPROTO op_mulq (void) -{ - T0 = (int64_t)T0 * (int64_t)T1; - RETURN(); -} - void OPPROTO op_mulqv (void) { helper_mulqv(); @@ -280,60 +244,6 @@ void OPPROTO op_umulh (void) } /* Logical */ -void OPPROTO op_and (void) -{ - T0 &= T1; - RETURN(); -} - -void OPPROTO op_bic (void) -{ - T0 &= ~T1; - RETURN(); -} - -void OPPROTO op_bis (void) -{ - T0 |= T1; - RETURN(); -} - -void OPPROTO op_eqv (void) -{ - T0 ^= ~T1; - RETURN(); -} - -void OPPROTO op_ornot (void) -{ - T0 |= ~T1; - RETURN(); -} - -void OPPROTO op_xor (void) -{ - T0 ^= T1; - RETURN(); -} - -void OPPROTO op_sll (void) -{ - T0 <<= T1; - RETURN(); -} - -void OPPROTO op_srl (void) -{ - T0 >>= T1; - RETURN(); -} - -void OPPROTO op_sra (void) -{ - T0 = (int64_t)T0 >> T1; - RETURN(); -} - void OPPROTO op_mskbl (void) { helper_mskbl(); diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 804cfcc3b1..54fe986ce0 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -440,54 +440,6 @@ static always_inline void gen_itf (DisasContext *ctx, gen_store_fir(ctx, rc, 0); } -static always_inline void gen_s4addl (void) -{ - tcg_gen_shli_i64(cpu_T[0], cpu_T[0], 2); - gen_op_addl(); -} - -static always_inline void gen_s4subl (void) -{ - tcg_gen_shli_i64(cpu_T[0], cpu_T[0], 2); - gen_op_subl(); -} - -static always_inline void gen_s8addl (void) -{ - tcg_gen_shli_i64(cpu_T[0], cpu_T[0], 3); - gen_op_addl(); -} - -static always_inline void gen_s8subl (void) -{ - tcg_gen_shli_i64(cpu_T[0], cpu_T[0], 3); - gen_op_subl(); -} - -static always_inline void gen_s4addq (void) -{ - tcg_gen_shli_i64(cpu_T[0], cpu_T[0], 2); - tcg_gen_add_i64(cpu_T[0], cpu_T[0], cpu_T[1]); -} - -static always_inline void gen_s4subq (void) -{ - tcg_gen_shli_i64(cpu_T[0], cpu_T[0], 2); - tcg_gen_sub_i64(cpu_T[0], cpu_T[0], cpu_T[1]); -} - -static always_inline void gen_s8addq (void) -{ - tcg_gen_shli_i64(cpu_T[0], cpu_T[0], 3); - tcg_gen_add_i64(cpu_T[0], cpu_T[0], cpu_T[1]); -} - -static always_inline void gen_s8subq (void) -{ - tcg_gen_shli_i64(cpu_T[0], cpu_T[0], 3); - tcg_gen_sub_i64(cpu_T[0], cpu_T[0], cpu_T[1]); -} - static always_inline int translate_one (DisasContext *ctx, uint32_t insn) { uint32_t palcode; @@ -616,19 +568,103 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn) switch (fn7) { case 0x00: /* ADDL */ - gen_arith3(ctx, &gen_op_addl, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra != 31) { + if (islit) { + tcg_gen_addi_i64(cpu_ir[rc], cpu_ir[ra], lit); + tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]); + } else if (rb != 31) { + tcg_gen_add_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]); + tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]); + } else + tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[ra]); + } else { + if (islit) + tcg_gen_movi_i64(cpu_ir[rc], (int32_t)lit); + else if (rb != 31) + tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]); + else + tcg_gen_movi_i64(cpu_ir[rc], 0); + } + } break; case 0x02: /* S4ADDL */ - gen_arith3(ctx, &gen_s4addl, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra != 31) { + if (islit || rb != 31) { + TCGv tmp = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_shli_i64(tmp, cpu_ir[ra], 2); + if (islit) + tcg_gen_addi_i64(tmp, tmp, lit); + else + tcg_gen_add_i64(tmp, tmp, cpu_ir[rb]); + tcg_gen_ext32s_i64(cpu_ir[rc], tmp); + tcg_temp_free(tmp); + } else { + tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], 2); + tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]); + } + } else { + if (islit) + tcg_gen_movi_i64(cpu_ir[rc], lit); + else if (rb != 31) + tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]); + else + tcg_gen_movi_i64(cpu_ir[rc], 0); + } + } break; case 0x09: /* SUBL */ - gen_arith3(ctx, &gen_op_subl, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra != 31) { + if (islit) { + tcg_gen_subi_i64(cpu_ir[rc], cpu_ir[ra], lit); + tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]); + } else if (rb != 31) { + tcg_gen_sub_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]); + tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]); + } else + tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[ra]); + } else { + if (islit) + tcg_gen_movi_i64(cpu_ir[rc], -lit); + else if (rb != 31) { + tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]); + tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]); + } else + tcg_gen_movi_i64(cpu_ir[rc], 0); + } + } break; case 0x0B: /* S4SUBL */ - gen_arith3(ctx, &gen_s4subl, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra != 31) { + if (islit || rb != 31) { + TCGv tmp = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_shli_i64(tmp, cpu_ir[ra], 2); + if (islit) + tcg_gen_subi_i64(tmp, tmp, lit); + else + tcg_gen_sub_i64(tmp, tmp, cpu_ir[rb]); + tcg_gen_ext32s_i64(cpu_ir[rc], tmp); + tcg_temp_free(tmp); + } else { + tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], 2); + tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]); + } + } else { + if (islit) + tcg_gen_movi_i64(cpu_ir[rc], -lit); + else if (rb != 31) { + tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]); + tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]); + } else + tcg_gen_movi_i64(cpu_ir[rc], 0); + } + } break; case 0x0F: /* CMPBGE */ @@ -636,11 +672,58 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn) break; case 0x12: /* S8ADDL */ - gen_arith3(ctx, &gen_s8addl, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra != 31) { + if (islit || rb != 31) { + TCGv tmp = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_shli_i64(tmp, cpu_ir[ra], 3); + if (islit) + tcg_gen_addi_i64(tmp, tmp, lit); + else + tcg_gen_add_i64(tmp, tmp, cpu_ir[rb]); + tcg_gen_ext32s_i64(cpu_ir[rc], tmp); + tcg_temp_free(tmp); + } else { + tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], 3); + tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]); + } + } else { + if (islit) + tcg_gen_movi_i64(cpu_ir[rc], lit); + else if (rb != 31) + tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rb]); + else + tcg_gen_movi_i64(cpu_ir[rc], 0); + } + } break; case 0x1B: /* S8SUBL */ - gen_arith3(ctx, &gen_s8subl, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra != 31) { + if (islit || rb != 31) { + TCGv tmp = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_shli_i64(tmp, cpu_ir[ra], 3); + if (islit) + tcg_gen_subi_i64(tmp, tmp, lit); + else + tcg_gen_sub_i64(tmp, tmp, cpu_ir[rb]); + tcg_gen_ext32s_i64(cpu_ir[rc], tmp); + tcg_temp_free(tmp); + } else { + tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], 3); + tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]); + } + } else { + if (islit) + tcg_gen_movi_i64(cpu_ir[rc], -lit); + else if (rb != 31) { + tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]); + tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]); + } else + tcg_gen_movi_i64(cpu_ir[rc], 0); + } + } break; case 0x1D: /* CMPULT */ @@ -648,19 +731,91 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn) break; case 0x20: /* ADDQ */ - gen_arith3(ctx, &gen_op_addq, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra != 31) { + if (islit) + tcg_gen_addi_i64(cpu_ir[rc], cpu_ir[ra], lit); + else if (rb != 31) + tcg_gen_add_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]); + else + tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[ra]); + } else { + if (islit) + tcg_gen_movi_i64(cpu_ir[rc], lit); + else if (rb != 31) + tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]); + else + tcg_gen_movi_i64(cpu_ir[rc], 0); + } + } break; case 0x22: /* S4ADDQ */ - gen_arith3(ctx, &gen_s4addq, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra != 31) { + if (islit || rb != 31) { + TCGv tmp = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_shli_i64(tmp, cpu_ir[ra], 2); + if (islit) + tcg_gen_addi_i64(cpu_ir[rc], tmp, lit); + else + tcg_gen_add_i64(cpu_ir[rc], tmp, cpu_ir[rb]); + tcg_temp_free(tmp); + } else + tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], 2); + } else { + if (islit) + tcg_gen_movi_i64(cpu_ir[rc], lit); + else if (rb != 31) + tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]); + else + tcg_gen_movi_i64(cpu_ir[rc], 0); + } + } break; case 0x29: /* SUBQ */ - gen_arith3(ctx, &gen_op_subq, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra != 31) { + if (islit) + tcg_gen_subi_i64(cpu_ir[rc], cpu_ir[ra], lit); + else if (rb != 31) + tcg_gen_sub_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]); + else + tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[ra]); + } else { + if (islit) + tcg_gen_movi_i64(cpu_ir[rc], -lit); + else if (rb != 31) + tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]); + else + tcg_gen_movi_i64(cpu_ir[rc], 0); + } + } break; case 0x2B: /* S4SUBQ */ - gen_arith3(ctx, &gen_s4subq, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra != 31) { + if (islit || rb != 31) { + TCGv tmp = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_shli_i64(tmp, cpu_ir[ra], 2); + if (islit) + tcg_gen_subi_i64(cpu_ir[rc], tmp, lit); + else + tcg_gen_sub_i64(cpu_ir[rc], tmp, cpu_ir[rb]); + tcg_temp_free(tmp); + } else + tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], 2); + } else { + if (islit) + tcg_gen_movi_i64(cpu_ir[rc], -lit); + else if (rb != 31) + tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]); + else + tcg_gen_movi_i64(cpu_ir[rc], 0); + } + } break; case 0x2D: /* CMPEQ */ @@ -668,11 +823,51 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn) break; case 0x32: /* S8ADDQ */ - gen_arith3(ctx, &gen_s8addq, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra != 31) { + if (islit || rb != 31) { + TCGv tmp = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_shli_i64(tmp, cpu_ir[ra], 3); + if (islit) + tcg_gen_addi_i64(cpu_ir[rc], tmp, lit); + else + tcg_gen_add_i64(cpu_ir[rc], tmp, cpu_ir[rb]); + tcg_temp_free(tmp); + } else + tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], 3); + } else { + if (islit) + tcg_gen_movi_i64(cpu_ir[rc], lit); + else if (rb != 31) + tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]); + else + tcg_gen_movi_i64(cpu_ir[rc], 0); + } + } break; case 0x3B: /* S8SUBQ */ - gen_arith3(ctx, &gen_s8subq, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra != 31) { + if (islit || rb != 31) { + TCGv tmp = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_shli_i64(tmp, cpu_ir[ra], 3); + if (islit) + tcg_gen_subi_i64(cpu_ir[rc], tmp, lit); + else + tcg_gen_sub_i64(cpu_ir[rc], tmp, cpu_ir[rb]); + tcg_temp_free(tmp); + } else + tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], 3); + } else { + if (islit) + tcg_gen_movi_i64(cpu_ir[rc], -lit); + else if (rb != 31) + tcg_gen_neg_i64(cpu_ir[rc], cpu_ir[rb]); + else + tcg_gen_movi_i64(cpu_ir[rc], 0); + } + } break; case 0x3D: /* CMPULE */ @@ -710,11 +905,31 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn) switch (fn7) { case 0x00: /* AND */ - gen_arith3(ctx, &gen_op_and, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra == 31 || (rb == 31 && !islit)) + tcg_gen_movi_i64(cpu_ir[rc], 0); + else if (islit) + tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[ra], lit); + else + tcg_gen_and_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]); + } break; case 0x08: /* BIC */ - gen_arith3(ctx, &gen_op_bic, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra != 31) { + if (islit) + tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[ra], ~lit); + else if (rb != 31) { + TCGv tmp = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_not_i64(tmp, cpu_ir[rb]); + tcg_gen_and_i64(cpu_ir[rc], cpu_ir[ra], tmp); + tcg_temp_free(tmp); + } else + tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[ra]); + } else + tcg_gen_movi_i64(cpu_ir[rc], 0); + } break; case 0x14: /* CMOVLBS */ @@ -726,21 +941,22 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn) break; case 0x20: /* BIS */ - if (ra == rb || ra == 31 || rb == 31) { - if (ra == 31 && rc == 31) { - /* NOP */ - gen_op_nop(); + if (likely(rc != 31)) { + if (ra != 31) { + if (islit) + tcg_gen_ori_i64(cpu_ir[rc], cpu_ir[ra], lit); + else if (rb != 31) + tcg_gen_or_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]); + else + tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[ra]); } else { - /* MOV */ - if (rc != 31) { - if (rb != 31) - tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]); - else - tcg_gen_movi_i64(cpu_ir[rc], 0); - } + if (islit) + tcg_gen_movi_i64(cpu_ir[rc], lit); + else if (rb != 31) + tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]); + else + tcg_gen_movi_i64(cpu_ir[rc], 0); } - } else { - gen_arith3(ctx, &gen_op_bis, ra, rb, rc, islit, lit); } break; case 0x24: @@ -753,11 +969,45 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn) break; case 0x28: /* ORNOT */ - gen_arith3(ctx, &gen_op_ornot, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (rb == 31 && !islit) + tcg_gen_movi_i64(cpu_ir[rc], ~0); + else if (ra != 31) { + if (islit) + tcg_gen_ori_i64(cpu_ir[rc], cpu_ir[ra], ~lit); + else { + TCGv tmp = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_not_i64(tmp, cpu_ir[rb]); + tcg_gen_or_i64(cpu_ir[rc], cpu_ir[ra], tmp); + tcg_temp_free(tmp); + } + } else { + if (islit) + tcg_gen_movi_i64(cpu_ir[rc], ~lit); + else + tcg_gen_not_i64(cpu_ir[rc], cpu_ir[rb]); + } + } break; case 0x40: /* XOR */ - gen_arith3(ctx, &gen_op_xor, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra != 31) { + if (islit) + tcg_gen_xori_i64(cpu_ir[rc], cpu_ir[ra], lit); + else if (rb != 31) + tcg_gen_xor_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]); + else + tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[ra]); + } else { + if (islit) + tcg_gen_movi_i64(cpu_ir[rc], lit); + else if (rb != 31) + tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]); + else + tcg_gen_movi_i64(cpu_ir[rc], 0); + } + } break; case 0x44: /* CMOVLT */ @@ -769,7 +1019,26 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn) break; case 0x48: /* EQV */ - gen_arith3(ctx, &gen_op_eqv, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra != 31) { + if (islit) + tcg_gen_xori_i64(cpu_ir[rc], cpu_ir[ra], ~lit); + else if (rb != 31) { + TCGv tmp = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_not_i64(tmp, cpu_ir[rb]); + tcg_gen_xor_i64(cpu_ir[rc], cpu_ir[ra], tmp); + tcg_temp_free(tmp); + } else + tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[ra]); + } else { + if (islit) + tcg_gen_movi_i64(cpu_ir[rc], ~lit); + else if (rb != 31) + tcg_gen_not_i64(cpu_ir[rc], cpu_ir[rb]); + else + tcg_gen_movi_i64(cpu_ir[rc], ~0); + } + } break; case 0x61: /* AMASK */ @@ -852,7 +1121,20 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn) break; case 0x34: /* SRL */ - gen_arith3(ctx, &gen_op_srl, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra != 31) { + if (islit) + tcg_gen_shri_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f); + else if (rb != 31) { + TCGv shift = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f); + tcg_gen_shr_i64(cpu_ir[rc], cpu_ir[ra], shift); + tcg_temp_free(shift); + } else + tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[ra]); + } else + tcg_gen_movi_i64(cpu_ir[rc], 0); + } break; case 0x36: /* EXTQL */ @@ -860,7 +1142,20 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn) break; case 0x39: /* SLL */ - gen_arith3(ctx, &gen_op_sll, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra != 31) { + if (islit) + tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f); + else if (rb != 31) { + TCGv shift = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f); + tcg_gen_shl_i64(cpu_ir[rc], cpu_ir[ra], shift); + tcg_temp_free(shift); + } else + tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[ra]); + } else + tcg_gen_movi_i64(cpu_ir[rc], 0); + } break; case 0x3B: /* INSQL */ @@ -868,7 +1163,20 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn) break; case 0x3C: /* SRA */ - gen_arith3(ctx, &gen_op_sra, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra != 31) { + if (islit) + tcg_gen_sari_i64(cpu_ir[rc], cpu_ir[ra], lit & 0x3f); + else if (rb != 31) { + TCGv shift = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_andi_i64(shift, cpu_ir[rb], 0x3f); + tcg_gen_sar_i64(cpu_ir[rc], cpu_ir[ra], shift); + tcg_temp_free(shift); + } else + tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[ra]); + } else + tcg_gen_movi_i64(cpu_ir[rc], 0); + } break; case 0x52: /* MSKWH */ @@ -914,11 +1222,28 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn) switch (fn7) { case 0x00: /* MULL */ - gen_arith3(ctx, &gen_op_mull, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra == 31 || (rb == 31 && !islit)) + tcg_gen_movi_i64(cpu_ir[rc], 0); + else { + if (islit) + tcg_gen_muli_i64(cpu_ir[rc], cpu_ir[ra], lit); + else + tcg_gen_mul_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]); + tcg_gen_ext32s_i64(cpu_ir[rc], cpu_ir[rc]); + } + } break; case 0x20: /* MULQ */ - gen_arith3(ctx, &gen_op_mulq, ra, rb, rc, islit, lit); + if (likely(rc != 31)) { + if (ra == 31 || (rb == 31 && !islit)) + tcg_gen_movi_i64(cpu_ir[rc], 0); + else if (islit) + tcg_gen_muli_i64(cpu_ir[rc], cpu_ir[ra], lit); + else + tcg_gen_mul_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]); + } break; case 0x30: /* UMULH */