@@ -183,6 +183,20 @@ TSUBcc 10 ..... 100001 ..... . ............. @r_r_ri_cc1
TADDccTV 10 ..... 100010 ..... . ............. @r_r_ri_cc1
TSUBccTV 10 ..... 100011 ..... . ............. @r_r_ri_cc1
+&shiftr rd rs1 rs2 x:bool
+@shiftr .. rd:5 ...... rs1:5 . x:1 ....... rs2:5 &shiftr
+
+SLL_r 10 ..... 100101 ..... 0 . 0000000 ..... @shiftr
+SRL_r 10 ..... 100110 ..... 0 . 0000000 ..... @shiftr
+SRA_r 10 ..... 100111 ..... 0 . 0000000 ..... @shiftr
+
+&shifti rd rs1 i x:bool
+@shifti .. rd:5 ...... rs1:5 . x:1 ...... i:6 &shifti
+
+SLL_i 10 ..... 100101 ..... 1 . 000000 ...... @shifti
+SRL_i 10 ..... 100110 ..... 1 . 000000 ...... @shifti
+SRA_i 10 ..... 100111 ..... 1 . 000000 ...... @shifti
+
Tcc_r 10 0 cond:4 111010 rs1:5 0 cc:1 0000000 rs2:5
{
# For v7, the entire simm13 field is present, but masked to 7 bits.
@@ -4244,6 +4244,83 @@ static bool trans_MULScc(DisasContext *dc, arg_r_r_ri_cc *a)
return do_arith(dc, a, CC_OP_ADD, NULL, NULL, gen_op_mulscc);
}
+static bool do_shift_r(DisasContext *dc, arg_shiftr *a, bool l, bool u)
+{
+ TCGv dst, src1, src2;
+
+ /* Reject 64-bit shifts for sparc32. */
+ if (avail_32(dc) && a->x) {
+ return false;
+ }
+
+ src2 = tcg_temp_new();
+ tcg_gen_andi_tl(src2, gen_load_gpr(dc, a->rs2), a->x ? 63 : 31);
+ src1 = gen_load_gpr(dc, a->rs1);
+ dst = gen_dest_gpr(dc, a->rd);
+
+ if (l) {
+ tcg_gen_shl_tl(dst, src1, src2);
+ if (!a->x) {
+ tcg_gen_ext32u_tl(dst, dst);
+ }
+ } else if (u) {
+ if (!a->x) {
+ tcg_gen_ext32u_tl(dst, src1);
+ src1 = dst;
+ }
+ tcg_gen_shr_tl(dst, src1, src2);
+ } else {
+ if (!a->x) {
+ tcg_gen_ext32s_tl(dst, src1);
+ src1 = dst;
+ }
+ tcg_gen_sar_tl(dst, src1, src2);
+ }
+ gen_store_gpr(dc, a->rd, dst);
+ return advance_pc(dc);
+}
+
+TRANS(SLL_r, ALL, do_shift_r, a, true, true)
+TRANS(SRL_r, ALL, do_shift_r, a, false, true)
+TRANS(SRA_r, ALL, do_shift_r, a, false, false)
+
+static bool do_shift_i(DisasContext *dc, arg_shifti *a, bool l, bool u)
+{
+ TCGv dst, src1;
+
+ /* Reject 64-bit shifts for sparc32. */
+ if (avail_32(dc) && (a->x || a->i >= 32)) {
+ return false;
+ }
+
+ src1 = gen_load_gpr(dc, a->rs1);
+ dst = gen_dest_gpr(dc, a->rd);
+
+ if (avail_32(dc) || a->x) {
+ if (l) {
+ tcg_gen_shli_tl(dst, src1, a->i);
+ } else if (u) {
+ tcg_gen_shri_tl(dst, src1, a->i);
+ } else {
+ tcg_gen_sari_tl(dst, src1, a->i);
+ }
+ } else {
+ if (l) {
+ tcg_gen_deposit_z_tl(dst, src1, a->i, 32 - a->i);
+ } else if (u) {
+ tcg_gen_extract_tl(dst, src1, a->i, 32 - a->i);
+ } else {
+ tcg_gen_sextract_tl(dst, src1, a->i, 32 - a->i);
+ }
+ }
+ gen_store_gpr(dc, a->rd, dst);
+ return advance_pc(dc);
+}
+
+TRANS(SLL_i, ALL, do_shift_i, a, true, true)
+TRANS(SRL_i, ALL, do_shift_i, a, false, true)
+TRANS(SRA_i, ALL, do_shift_i, a, false, false)
+
#define CHECK_IU_FEATURE(dc, FEATURE) \
if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
goto illegal_insn;
@@ -4592,77 +4669,6 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
default:
goto illegal_insn;
}
-#ifdef TARGET_SPARC64
- } else if (xop == 0x25) { /* sll, V9 sllx */
- cpu_src1 = get_src1(dc, insn);
- if (IS_IMM) { /* immediate */
- simm = GET_FIELDs(insn, 20, 31);
- if (insn & (1 << 12)) {
- tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x3f);
- } else {
- tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x1f);
- }
- } else { /* register */
- rs2 = GET_FIELD(insn, 27, 31);
- cpu_src2 = gen_load_gpr(dc, rs2);
- cpu_tmp0 = tcg_temp_new();
- if (insn & (1 << 12)) {
- tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
- } else {
- tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
- }
- tcg_gen_shl_i64(cpu_dst, cpu_src1, cpu_tmp0);
- }
- gen_store_gpr(dc, rd, cpu_dst);
- } else if (xop == 0x26) { /* srl, V9 srlx */
- cpu_src1 = get_src1(dc, insn);
- if (IS_IMM) { /* immediate */
- simm = GET_FIELDs(insn, 20, 31);
- if (insn & (1 << 12)) {
- tcg_gen_shri_i64(cpu_dst, cpu_src1, simm & 0x3f);
- } else {
- tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
- tcg_gen_shri_i64(cpu_dst, cpu_dst, simm & 0x1f);
- }
- } else { /* register */
- rs2 = GET_FIELD(insn, 27, 31);
- cpu_src2 = gen_load_gpr(dc, rs2);
- cpu_tmp0 = tcg_temp_new();
- if (insn & (1 << 12)) {
- tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
- tcg_gen_shr_i64(cpu_dst, cpu_src1, cpu_tmp0);
- } else {
- tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
- tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL);
- tcg_gen_shr_i64(cpu_dst, cpu_dst, cpu_tmp0);
- }
- }
- gen_store_gpr(dc, rd, cpu_dst);
- } else if (xop == 0x27) { /* sra, V9 srax */
- cpu_src1 = get_src1(dc, insn);
- if (IS_IMM) { /* immediate */
- simm = GET_FIELDs(insn, 20, 31);
- if (insn & (1 << 12)) {
- tcg_gen_sari_i64(cpu_dst, cpu_src1, simm & 0x3f);
- } else {
- tcg_gen_ext32s_i64(cpu_dst, cpu_src1);
- tcg_gen_sari_i64(cpu_dst, cpu_dst, simm & 0x1f);
- }
- } else { /* register */
- rs2 = GET_FIELD(insn, 27, 31);
- cpu_src2 = gen_load_gpr(dc, rs2);
- cpu_tmp0 = tcg_temp_new();
- if (insn & (1 << 12)) {
- tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f);
- tcg_gen_sar_i64(cpu_dst, cpu_src1, cpu_tmp0);
- } else {
- tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f);
- tcg_gen_ext32s_i64(cpu_dst, cpu_src1);
- tcg_gen_sar_i64(cpu_dst, cpu_dst, cpu_tmp0);
- }
- }
- gen_store_gpr(dc, rd, cpu_dst);
-#endif
} else if (xop < 0x36) {
if (xop < 0x20) {
goto illegal_insn;
@@ -4675,42 +4681,10 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
case 0x22: /* taddcctv */
case 0x23: /* tsubcctv */
case 0x24: /* mulscc */
- goto illegal_insn; /* in decodetree */
-#ifndef TARGET_SPARC64
case 0x25: /* sll */
- if (IS_IMM) { /* immediate */
- simm = GET_FIELDs(insn, 20, 31);
- tcg_gen_shli_tl(cpu_dst, cpu_src1, simm & 0x1f);
- } else { /* register */
- cpu_tmp0 = tcg_temp_new();
- tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
- tcg_gen_shl_tl(cpu_dst, cpu_src1, cpu_tmp0);
- }
- gen_store_gpr(dc, rd, cpu_dst);
- break;
case 0x26: /* srl */
- if (IS_IMM) { /* immediate */
- simm = GET_FIELDs(insn, 20, 31);
- tcg_gen_shri_tl(cpu_dst, cpu_src1, simm & 0x1f);
- } else { /* register */
- cpu_tmp0 = tcg_temp_new();
- tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
- tcg_gen_shr_tl(cpu_dst, cpu_src1, cpu_tmp0);
- }
- gen_store_gpr(dc, rd, cpu_dst);
- break;
case 0x27: /* sra */
- if (IS_IMM) { /* immediate */
- simm = GET_FIELDs(insn, 20, 31);
- tcg_gen_sari_tl(cpu_dst, cpu_src1, simm & 0x1f);
- } else { /* register */
- cpu_tmp0 = tcg_temp_new();
- tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
- tcg_gen_sar_tl(cpu_dst, cpu_src1, cpu_tmp0);
- }
- gen_store_gpr(dc, rd, cpu_dst);
- break;
-#endif
+ goto illegal_insn; /* in decodetree */
case 0x30:
goto illegal_insn; /* WRASR in decodetree */
case 0x32: