Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/sparc/insns.decode | 51 +++++++++--
target/sparc/translate.c | 173 ++++++++------------------------------
2 files changed, 81 insertions(+), 143 deletions(-)
diff --git a/target/sparc/insns.decode b/target/sparc/insns.decode
index 1150890e44..45eb6a967f 100644
--- a/target/sparc/insns.decode
+++ b/target/sparc/insns.decode
@@ -251,6 +251,14 @@ NCP 10 ----- 110111 ----- --------- ----- # v8 CPop2
@r_r_r_asi .. rd:5 ...... rs1:5 0 asi:8 rs2_or_imm:5 &r_r_ri_asi imm=0
@r_r_i_asi .. rd:5 ...... rs1:5 1 rs2_or_imm:s13 \
&r_r_ri_asi imm=1 asi=-2
+@d_r_r_asi .. ..... ...... rs1:5 0 asi:8 rs2_or_imm:5 \
+ &r_r_ri_asi rd=%dfp_rd imm=0
+@d_r_i_asi .. ..... ...... rs1:5 1 rs2_or_imm:s13 \
+ &r_r_ri_asi rd=%dfp_rd imm=1 asi=-2
+@q_r_r_asi .. ..... ...... rs1:5 0 asi:8 rs2_or_imm:5 \
+ &r_r_ri_asi rd=%qfp_rd imm=0
+@q_r_i_asi .. ..... ...... rs1:5 1 rs2_or_imm:s13 \
+ &r_r_ri_asi rd=%qfp_rd imm=1 asi=-2
@casa_imm .. rd:5 ...... rs1:5 1 00000000 rs2_or_imm:5 \
&r_r_ri_asi imm=1 asi=-2
@@ -325,10 +333,43 @@ NOP_v9 11 ----- 101101 ----- 0 00000000 ----- # PREFETCH
NOP_v9 11 ----- 101101 ----- 1 ------------- # PREFETCH
NOP_v9 11 ----- 111101 ----- - ------------- # PREFETCHA
-NCP 11 ----- 110000 ----- --------- ----- # v8 LDC
+{
+ [
+ LDFA 11 ..... 110000 ..... . ............. @r_r_r_asi
+ LDFA 11 ..... 110000 ..... . ............. @r_r_i_asi
+ ]
+ NCP 11 ----- 110000 ----- --------- ----- # v8 LDC
+}
NCP 11 ----- 110001 ----- --------- ----- # v8 LDCSR
-NCP 11 ----- 110011 ----- --------- ----- # v8 LDDC
-NCP 11 ----- 110100 ----- --------- ----- # v8 STC
+LDQFA 11 ..... 110010 ..... . ............. @q_r_r_asi
+LDQFA 11 ..... 110010 ..... . ............. @q_r_i_asi
+{
+ [
+ LDDFA 11 ..... 110011 ..... . ............. @d_r_r_asi
+ LDDFA 11 ..... 110011 ..... . ............. @d_r_i_asi
+ ]
+ NCP 11 ----- 110011 ----- --------- ----- # v8 LDDC
+}
+
+{
+ [
+ STFA 11 ..... 110100 ..... . ............. @r_r_r_asi
+ STFA 11 ..... 110100 ..... . ............. @r_r_i_asi
+ ]
+ NCP 11 ----- 110100 ----- --------- ----- # v8 STC
+}
NCP 11 ----- 110101 ----- --------- ----- # v8 STCSR
-NCP 11 ----- 110110 ----- --------- ----- # v8 STDCQ
-NCP 11 ----- 110111 ----- --------- ----- # v8 STDC
+{
+ [
+ STQFA 11 ..... 110110 ..... . ............. @q_r_r_asi
+ STQFA 11 ..... 110110 ..... . ............. @q_r_i_asi
+ ]
+ NCP 11 ----- 110110 ----- --------- ----- # v8 STDCQ
+}
+{
+ [
+ STDFA 11 ..... 110111 ..... . ............. @d_r_r_asi
+ STDFA 11 ..... 110111 ..... . ............. @d_r_i_asi
+ ]
+ NCP 11 ----- 110111 ----- --------- ----- # v8 STDC
+}
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index dab3dfd09c..ebffcd7393 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -2106,12 +2106,6 @@ static DisasASI resolve_asi(DisasContext *dc, int asi, MemOp memop)
return (DisasASI){ type, asi, mem_idx, memop };
}
-static DisasASI get_asi(DisasContext *dc, int insn, MemOp memop)
-{
- int asi = IS_IMM ? -2 : GET_FIELD(insn, 19, 26);
- return resolve_asi(dc, asi, memop);
-}
-
#if defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
static void gen_helper_ld_asi(TCGv_i64 r, TCGv_env e, TCGv a,
TCGv_i32 asi, TCGv_i32 mop)
@@ -2298,13 +2292,14 @@ static void gen_ldstub_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr)
}
}
-static void gen_ldf_asi0(DisasContext *dc, DisasASI *da, MemOp orig_size,
- TCGv addr, int rd)
+static void gen_ldf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size,
+ TCGv addr, int rd)
{
MemOp memop = da->memop;
MemOp size = memop & MO_SIZE;
TCGv_i32 d32;
TCGv_i64 d64;
+ TCGv addr_tmp;
/* TODO: Use 128-bit load/store below. */
if (size == MO_128) {
@@ -2331,8 +2326,9 @@ static void gen_ldf_asi0(DisasContext *dc, DisasASI *da, MemOp orig_size,
case MO_128:
d64 = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop);
- tcg_gen_addi_tl(addr, addr, 8);
- tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + 1], addr, da->mem_idx, memop);
+ addr_tmp = tcg_temp_new();
+ tcg_gen_addi_tl(addr_tmp, addr, 8);
+ tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + 1], addr_tmp, da->mem_idx, memop);
tcg_gen_mov_i64(cpu_fpr[rd / 2], d64);
break;
default:
@@ -2343,18 +2339,16 @@ static void gen_ldf_asi0(DisasContext *dc, DisasASI *da, MemOp orig_size,
case GET_ASI_BLOCK:
/* Valid for lddfa on aligned registers only. */
if (orig_size == MO_64 && (rd & 7) == 0) {
- TCGv eight;
- int i;
-
/* The first operation checks required alignment. */
- eight = tcg_constant_tl(8);
- for (i = 0; ; ++i) {
+ addr_tmp = tcg_temp_new();
+ for (int i = 0; ; ++i) {
tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + i], addr, da->mem_idx,
memop | (i == 0 ? MO_ALIGN_64 : 0));
if (i == 7) {
break;
}
- tcg_gen_add_tl(addr, addr, eight);
+ tcg_gen_addi_tl(addr_tmp, addr, 8);
+ addr = addr_tmp;
}
} else {
gen_exception(dc, TT_ILL_INSN);
@@ -2396,8 +2390,9 @@ static void gen_ldf_asi0(DisasContext *dc, DisasASI *da, MemOp orig_size,
case MO_128:
d64 = tcg_temp_new_i64();
gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
- tcg_gen_addi_tl(addr, addr, 8);
- gen_helper_ld_asi(cpu_fpr[rd / 2 + 1], tcg_env, addr,
+ addr_tmp = tcg_temp_new();
+ tcg_gen_addi_tl(addr_tmp, addr, 8);
+ gen_helper_ld_asi(cpu_fpr[rd / 2 + 1], tcg_env, addr_tmp,
r_asi, r_mop);
tcg_gen_mov_i64(cpu_fpr[rd / 2], d64);
break;
@@ -2409,22 +2404,13 @@ static void gen_ldf_asi0(DisasContext *dc, DisasASI *da, MemOp orig_size,
}
}
-static void __attribute__((unused))
-gen_ldf_asi(DisasContext *dc, TCGv addr, int insn, int size, int rd)
-{
- MemOp sz = ctz32(size);
- DisasASI da = get_asi(dc, insn, MO_TE | sz);
-
- gen_address_mask(dc, addr);
- gen_ldf_asi0(dc, &da, sz, addr, rd);
-}
-
-static void gen_stf_asi0(DisasContext *dc, DisasASI *da, MemOp orig_size,
- TCGv addr, int rd)
+static void gen_stf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size,
+ TCGv addr, int rd)
{
MemOp memop = da->memop;
MemOp size = memop & MO_SIZE;
TCGv_i32 d32;
+ TCGv addr_tmp;
/* TODO: Use 128-bit load/store below. */
if (size == MO_128) {
@@ -2454,8 +2440,9 @@ static void gen_stf_asi0(DisasContext *dc, DisasASI *da, MemOp orig_size,
write. */
tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx,
memop | MO_ALIGN_16);
- tcg_gen_addi_tl(addr, addr, 8);
- tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + 1], addr, da->mem_idx, memop);
+ addr_tmp = tcg_temp_new();
+ tcg_gen_addi_tl(addr_tmp, addr, 8);
+ tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + 1], addr_tmp, da->mem_idx, memop);
break;
default:
g_assert_not_reached();
@@ -2465,18 +2452,16 @@ static void gen_stf_asi0(DisasContext *dc, DisasASI *da, MemOp orig_size,
case GET_ASI_BLOCK:
/* Valid for stdfa on aligned registers only. */
if (orig_size == MO_64 && (rd & 7) == 0) {
- TCGv eight;
- int i;
-
/* The first operation checks required alignment. */
- eight = tcg_constant_tl(8);
- for (i = 0; ; ++i) {
+ addr_tmp = tcg_temp_new();
+ for (int i = 0; ; ++i) {
tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + i], addr, da->mem_idx,
memop | (i == 0 ? MO_ALIGN_64 : 0));
if (i == 7) {
break;
}
- tcg_gen_add_tl(addr, addr, eight);
+ tcg_gen_addi_tl(addr_tmp, addr, 8);
+ addr = addr_tmp;
}
} else {
gen_exception(dc, TT_ILL_INSN);
@@ -2502,16 +2487,6 @@ static void gen_stf_asi0(DisasContext *dc, DisasASI *da, MemOp orig_size,
}
}
-static void __attribute__((unused))
-gen_stf_asi(DisasContext *dc, TCGv addr, int insn, int size, int rd)
-{
- MemOp sz = ctz32(size);
- DisasASI da = get_asi(dc, insn, MO_TE | sz);
-
- gen_address_mask(dc, addr);
- gen_stf_asi0(dc, &da, sz, addr, rd);
-}
-
static void gen_ldda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd)
{
TCGv hi = gen_dest_gpr(dc, rd);
@@ -4650,7 +4625,7 @@ static bool do_ld_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz)
return true;
}
da = resolve_asi(dc, a->asi, MO_TE | sz);
- gen_ldf_asi0(dc, &da, sz, addr, a->rd);
+ gen_ldf_asi(dc, &da, sz, addr, a->rd);
gen_update_fprs_dirty(dc, a->rd);
return advance_pc(dc);
}
@@ -4659,6 +4634,10 @@ TRANS(LDF, ALL, do_ld_fpr, a, MO_32)
TRANS(LDDF, ALL, do_ld_fpr, a, MO_64)
TRANS(LDQF, ALL, do_ld_fpr, a, MO_128)
+TRANS(LDFA, 64, do_ld_fpr, a, MO_32)
+TRANS(LDDFA, 64, do_ld_fpr, a, MO_64)
+TRANS(LDQFA, 64, do_ld_fpr, a, MO_128)
+
static bool do_st_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz)
{
TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
@@ -4674,7 +4653,7 @@ static bool do_st_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz)
return true;
}
da = resolve_asi(dc, a->asi, MO_TE | sz);
- gen_stf_asi0(dc, &da, sz, addr, a->rd);
+ gen_stf_asi(dc, &da, sz, addr, a->rd);
return advance_pc(dc);
}
@@ -4682,6 +4661,10 @@ TRANS(STF, ALL, do_st_fpr, a, MO_32)
TRANS(STDF, ALL, do_st_fpr, a, MO_64)
TRANS(STQF, ALL, do_st_fpr, a, MO_128)
+TRANS(STFA, 64, do_st_fpr, a, MO_32)
+TRANS(STDFA, 64, do_st_fpr, a, MO_64)
+TRANS(STQFA, 64, do_st_fpr, a, MO_128)
+
static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a)
{
if (!avail_32(dc)) {
@@ -5515,64 +5498,7 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) ||
(xop > 0x17 && xop <= 0x1d ) ||
(xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
- TCGv cpu_val = gen_dest_gpr(dc, rd);
-
- switch (xop) {
- case 0x0: /* ld, V9 lduw, load unsigned word */
- case 0x1: /* ldub, load unsigned byte */
- case 0x2: /* lduh, load unsigned halfword */
- case 0x3: /* ldd, load double word */
- case 0x9: /* ldsb, load signed byte */
- case 0xa: /* ldsh, load signed halfword */
- case 0xd: /* ldstub */
- case 0x0f: /* swap */
- case 0x10: /* lda, V9 lduwa, load word alternate */
- case 0x11: /* lduba, load unsigned byte alternate */
- case 0x12: /* lduha, load unsigned halfword alternate */
- case 0x13: /* ldda, load double word alternate */
- case 0x19: /* ldsba, load signed byte alternate */
- case 0x1a: /* ldsha, load signed halfword alternate */
- case 0x1d: /* ldstuba */
- case 0x1f: /* swapa */
- g_assert_not_reached(); /* in decodetree */
- case 0x08: /* V9 ldsw */
- case 0x0b: /* V9 ldx */
- case 0x18: /* V9 ldswa */
- case 0x1b: /* V9 ldxa */
- case 0x2d: /* V9 prefetch */
- case 0x3d: /* V9 prefetcha */
- goto illegal_insn; /* in decodetree */
-#ifdef TARGET_SPARC64
- case 0x30: /* V9 ldfa */
- if (gen_trap_ifnofpu(dc)) {
- goto jmp_insn;
- }
- gen_ldf_asi(dc, cpu_addr, insn, 4, rd);
- gen_update_fprs_dirty(dc, rd);
- goto skip_move;
- case 0x33: /* V9 lddfa */
- if (gen_trap_ifnofpu(dc)) {
- goto jmp_insn;
- }
- gen_ldf_asi(dc, cpu_addr, insn, 8, DFPREG(rd));
- gen_update_fprs_dirty(dc, DFPREG(rd));
- goto skip_move;
- case 0x32: /* V9 ldqfa */
- CHECK_FPU_FEATURE(dc, FLOAT128);
- if (gen_trap_ifnofpu(dc)) {
- goto jmp_insn;
- }
- gen_ldf_asi(dc, cpu_addr, insn, 16, QFPREG(rd));
- gen_update_fprs_dirty(dc, QFPREG(rd));
- goto skip_move;
-#endif
- default:
- goto illegal_insn;
- }
- gen_store_gpr(dc, rd, cpu_val);
-#if defined(TARGET_SPARC64)
- skip_move: ;
-#endif
+ goto illegal_insn; /* in decodetree */
} else if (xop >= 0x20 && xop < 0x24) {
if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
@@ -5628,36 +5554,7 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
goto illegal_insn;
}
} else if (xop > 0x33 && xop < 0x3f) {
- switch (xop) {
-#ifdef TARGET_SPARC64
- case 0x34: /* V9 stfa */
- if (gen_trap_ifnofpu(dc)) {
- goto jmp_insn;
- }
- gen_stf_asi(dc, cpu_addr, insn, 4, rd);
- break;
- case 0x36: /* V9 stqfa */
- {
- CHECK_FPU_FEATURE(dc, FLOAT128);
- if (gen_trap_ifnofpu(dc)) {
- goto jmp_insn;
- }
- gen_stf_asi(dc, cpu_addr, insn, 16, QFPREG(rd));
- }
- break;
- case 0x37: /* V9 stdfa */
- if (gen_trap_ifnofpu(dc)) {
- goto jmp_insn;
- }
- gen_stf_asi(dc, cpu_addr, insn, 8, DFPREG(rd));
- break;
-#endif
- case 0x3e: /* V9 casxa */
- case 0x3c: /* V9 or LEON3 casa */
- goto illegal_insn; /* in decodetree */
- default:
- goto illegal_insn;
- }
+ goto illegal_insn; /* in decodetree */
} else {
goto illegal_insn;
}
--
2.34.1