target/sparc: Move simple integer load/store to decodetree

Move LDUW, LDUB, LDUH, LDD, LDSW, LDSB, LDSH, LDX,
STW, STB, STH, STD, STX.

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>
This commit is contained in:
Richard Henderson 2023-10-04 19:50:47 -07:00
parent ebbbec9216
commit 0880d20b2e
2 changed files with 142 additions and 76 deletions

View File

@ -231,6 +231,28 @@ RESTORE 10 ..... 111101 ..... . ............. @r_r_ri
DONE 10 00000 111110 00000 0 0000000000000
RETRY 10 00001 111110 00000 0 0000000000000
##
## Major Opcode 11 -- load and store instructions
##
&r_r_ri_asi rd rs1 rs2_or_imm asi imm:bool
@r_r_ri_na .. rd:5 ...... rs1:5 imm:1 rs2_or_imm:s13 &r_r_ri_asi asi=-1
LDUW 11 ..... 000000 ..... . ............. @r_r_ri_na
LDUB 11 ..... 000001 ..... . ............. @r_r_ri_na
LDUH 11 ..... 000010 ..... . ............. @r_r_ri_na
LDD 11 ..... 000011 ..... . ............. @r_r_ri_na
LDSW 11 ..... 001000 ..... . ............. @r_r_ri_na
LDSB 11 ..... 001001 ..... . ............. @r_r_ri_na
LDSH 11 ..... 001010 ..... . ............. @r_r_ri_na
LDX 11 ..... 001011 ..... . ............. @r_r_ri_na
STW 11 ..... 000100 ..... . ............. @r_r_ri_na
STB 11 ..... 000101 ..... . ............. @r_r_ri_na
STH 11 ..... 000110 ..... . ............. @r_r_ri_na
STD 11 ..... 000111 ..... . ............. @r_r_ri_na
STX 11 ..... 001110 ..... . ............. @r_r_ri_na
NCP 10 ----- 110110 ----- --------- ----- # v8 CPop1
NCP 10 ----- 110111 ----- --------- ----- # v8 CPop2

View File

@ -4536,6 +4536,117 @@ static bool do_done_retry(DisasContext *dc, bool done)
TRANS(DONE, 64, do_done_retry, true)
TRANS(RETRY, 64, do_done_retry, false)
/*
* Major opcode 11 -- load and store instructions
*/
static TCGv gen_ldst_addr(DisasContext *dc, int rs1, bool imm, int rs2_or_imm)
{
TCGv addr, tmp = NULL;
/* For simplicity, we under-decoded the rs2 form. */
if (!imm && rs2_or_imm & ~0x1f) {
return NULL;
}
addr = gen_load_gpr(dc, rs1);
if (rs2_or_imm) {
tmp = tcg_temp_new();
if (imm) {
tcg_gen_addi_tl(tmp, addr, rs2_or_imm);
} else {
tcg_gen_add_tl(tmp, addr, cpu_regs[rs2_or_imm]);
}
addr = tmp;
}
if (AM_CHECK(dc)) {
if (!tmp) {
tmp = tcg_temp_new();
}
tcg_gen_ext32u_tl(tmp, addr);
addr = tmp;
}
return addr;
}
static bool do_ld_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
{
TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
DisasASI da;
if (addr == NULL) {
return false;
}
da = resolve_asi(dc, a->asi, mop);
reg = gen_dest_gpr(dc, a->rd);
gen_ld_asi0(dc, &da, reg, addr);
gen_store_gpr(dc, a->rd, reg);
return advance_pc(dc);
}
TRANS(LDUW, ALL, do_ld_gpr, a, MO_TEUL)
TRANS(LDUB, ALL, do_ld_gpr, a, MO_UB)
TRANS(LDUH, ALL, do_ld_gpr, a, MO_TEUW)
TRANS(LDSB, ALL, do_ld_gpr, a, MO_SB)
TRANS(LDSH, ALL, do_ld_gpr, a, MO_TESW)
TRANS(LDSW, 64, do_ld_gpr, a, MO_TESL)
TRANS(LDX, 64, do_ld_gpr, a, MO_TEUQ)
static bool do_st_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
{
TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
DisasASI da;
if (addr == NULL) {
return false;
}
da = resolve_asi(dc, a->asi, mop);
reg = gen_load_gpr(dc, a->rd);
gen_st_asi0(dc, &da, reg, addr);
return advance_pc(dc);
}
TRANS(STW, ALL, do_st_gpr, a, MO_TEUL)
TRANS(STB, ALL, do_st_gpr, a, MO_UB)
TRANS(STH, ALL, do_st_gpr, a, MO_TEUW)
TRANS(STX, 64, do_st_gpr, a, MO_TEUQ)
static bool trans_LDD(DisasContext *dc, arg_r_r_ri_asi *a)
{
TCGv addr;
DisasASI da;
if (a->rd & 1) {
return false;
}
addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
if (addr == NULL) {
return false;
}
da = resolve_asi(dc, a->asi, MO_TEUQ);
gen_ldda_asi0(dc, &da, addr, a->rd);
return advance_pc(dc);
}
static bool trans_STD(DisasContext *dc, arg_r_r_ri_asi *a)
{
TCGv addr;
DisasASI da;
if (a->rd & 1) {
return false;
}
addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
if (addr == NULL) {
return false;
}
da = resolve_asi(dc, a->asi, MO_TEUQ);
gen_stda_asi0(dc, &da, addr, a->rd);
return advance_pc(dc);
}
#define CHECK_IU_FEATURE(dc, FEATURE) \
if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
goto illegal_insn;
@ -5359,47 +5470,15 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
switch (xop) {
case 0x0: /* ld, V9 lduw, load unsigned word */
gen_address_mask(dc, cpu_addr);
tcg_gen_qemu_ld_tl(cpu_val, cpu_addr,
dc->mem_idx, MO_TEUL | MO_ALIGN);
break;
case 0x1: /* ldub, load unsigned byte */
gen_address_mask(dc, cpu_addr);
tcg_gen_qemu_ld_tl(cpu_val, cpu_addr,
dc->mem_idx, MO_UB);
break;
case 0x2: /* lduh, load unsigned halfword */
gen_address_mask(dc, cpu_addr);
tcg_gen_qemu_ld_tl(cpu_val, cpu_addr,
dc->mem_idx, MO_TEUW | MO_ALIGN);
break;
case 0x3: /* ldd, load double word */
if (rd & 1)
goto illegal_insn;
else {
TCGv_i64 t64;
gen_address_mask(dc, cpu_addr);
t64 = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(t64, cpu_addr,
dc->mem_idx, MO_TEUQ | MO_ALIGN);
tcg_gen_trunc_i64_tl(cpu_val, t64);
tcg_gen_ext32u_tl(cpu_val, cpu_val);
gen_store_gpr(dc, rd + 1, cpu_val);
tcg_gen_shri_i64(t64, t64, 32);
tcg_gen_trunc_i64_tl(cpu_val, t64);
tcg_gen_ext32u_tl(cpu_val, cpu_val);
}
break;
case 0x9: /* ldsb, load signed byte */
gen_address_mask(dc, cpu_addr);
tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, dc->mem_idx, MO_SB);
break;
case 0xa: /* ldsh, load signed halfword */
gen_address_mask(dc, cpu_addr);
tcg_gen_qemu_ld_tl(cpu_val, cpu_addr,
dc->mem_idx, MO_TESW | MO_ALIGN);
break;
g_assert_not_reached(); /* in decodetree */
case 0x08: /* V9 ldsw */
case 0x0b: /* V9 ldx */
goto illegal_insn; /* in decodetree */
case 0xd: /* ldstub */
gen_ldstub(dc, cpu_val, cpu_addr, dc->mem_idx);
break;
@ -5441,16 +5520,6 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
break;
#endif
#ifdef TARGET_SPARC64
case 0x08: /* V9 ldsw */
gen_address_mask(dc, cpu_addr);
tcg_gen_qemu_ld_tl(cpu_val, cpu_addr,
dc->mem_idx, MO_TESL | MO_ALIGN);
break;
case 0x0b: /* V9 ldx */
gen_address_mask(dc, cpu_addr);
tcg_gen_qemu_ld_tl(cpu_val, cpu_addr,
dc->mem_idx, MO_TEUQ | MO_ALIGN);
break;
case 0x18: /* V9 ldswa */
gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TESL);
break;
@ -5543,38 +5612,18 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
}
} else if (xop < 8 || (xop >= 0x14 && xop < 0x18) ||
xop == 0xe || xop == 0x1e) {
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
TCGv cpu_val = gen_load_gpr(dc, rd);
#endif
switch (xop) {
case 0x4: /* st, store word */
gen_address_mask(dc, cpu_addr);
tcg_gen_qemu_st_tl(cpu_val, cpu_addr,
dc->mem_idx, MO_TEUL | MO_ALIGN);
break;
case 0x5: /* stb, store byte */
gen_address_mask(dc, cpu_addr);
tcg_gen_qemu_st_tl(cpu_val, cpu_addr, dc->mem_idx, MO_UB);
break;
case 0x6: /* sth, store halfword */
gen_address_mask(dc, cpu_addr);
tcg_gen_qemu_st_tl(cpu_val, cpu_addr,
dc->mem_idx, MO_TEUW | MO_ALIGN);
break;
case 0x7: /* std, store double word */
if (rd & 1)
goto illegal_insn;
else {
TCGv_i64 t64;
TCGv lo;
gen_address_mask(dc, cpu_addr);
lo = gen_load_gpr(dc, rd + 1);
t64 = tcg_temp_new_i64();
tcg_gen_concat_tl_i64(t64, lo, cpu_val);
tcg_gen_qemu_st_i64(t64, cpu_addr,
dc->mem_idx, MO_TEUQ | MO_ALIGN);
}
break;
g_assert_not_reached(); /* in decodetree */
case 0x0e: /* V9 stx */
goto illegal_insn; /* in decodetree */
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
case 0x14: /* sta, V9 stwa, store word alternate */
gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEUL);
@ -5593,11 +5642,6 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
break;
#endif
#ifdef TARGET_SPARC64
case 0x0e: /* V9 stx */
gen_address_mask(dc, cpu_addr);
tcg_gen_qemu_st_tl(cpu_val, cpu_addr,
dc->mem_idx, MO_TEUQ | MO_ALIGN);
break;
case 0x1e: /* V9 stxa */
gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEUQ);
break;