Skip to content

Commit

Permalink
target/sparc: Move simple fp load/store to decodetree
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
rth7680 committed Oct 25, 2023
1 parent 3259b9e commit 06c060d
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 100 deletions.
19 changes: 19 additions & 0 deletions target/sparc/insns.decode
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,16 @@ NCP 10 ----- 110111 ----- --------- ----- # v8 CPop2
## Major Opcode 11 -- load and store instructions
##

%dfp_rd 25:5 !function=extract_dfpreg
%qfp_rd 25:5 !function=extract_qfpreg

&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
@d_r_ri_na .. ..... ...... rs1:5 imm:1 rs2_or_imm:s13 \
&r_r_ri_asi rd=%dfp_rd asi=-1
@q_r_ri_na .. ..... ...... rs1:5 imm:1 rs2_or_imm:s13 \
&r_r_ri_asi rd=%qfp_rd asi=-1

@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
Expand Down Expand Up @@ -289,6 +297,17 @@ STD 11 ..... 010111 ..... . ............. @r_r_i_asi # STDA
STX 11 ..... 011110 ..... . ............. @r_r_r_asi # STXA
STX 11 ..... 011110 ..... . ............. @r_r_i_asi # STXA

LDF 11 ..... 100000 ..... . ............. @r_r_ri_na
LDQF 11 ..... 100010 ..... . ............. @q_r_ri_na
LDDF 11 ..... 100011 ..... . ............. @d_r_ri_na

STF 11 ..... 100100 ..... . ............. @r_r_ri_na
{
STQF 11 ..... 100110 ..... . ............. @q_r_ri_na
STDFQ 11 ----- 100110 ----- - -------------
}
STDF 11 ..... 100111 ..... . ............. @d_r_ri_na

LDSTUB 11 ..... 001101 ..... . ............. @r_r_ri_na
LDSTUB 11 ..... 011101 ..... . ............. @r_r_r_asi # LDSTUBA
LDSTUB 11 ..... 011101 ..... . ............. @r_r_i_asi # LDSTUBA
Expand Down
194 changes: 94 additions & 100 deletions target/sparc/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,29 +254,7 @@ static void gen_op_store_QT0_fpr(unsigned int dst)
offsetof(CPU_QuadU, ll.lower));
}

static void gen_store_fpr_Q(DisasContext *dc, unsigned int dst,
TCGv_i64 v1, TCGv_i64 v2)
{
dst = QFPREG(dst);

tcg_gen_mov_i64(cpu_fpr[dst / 2], v1);
tcg_gen_mov_i64(cpu_fpr[dst / 2 + 1], v2);
gen_update_fprs_dirty(dc, dst);
}

#ifdef TARGET_SPARC64
static TCGv_i64 gen_load_fpr_Q0(DisasContext *dc, unsigned int src)
{
src = QFPREG(src);
return cpu_fpr[src / 2];
}

static TCGv_i64 gen_load_fpr_Q1(DisasContext *dc, unsigned int src)
{
src = QFPREG(src);
return cpu_fpr[src / 2 + 1];
}

static void gen_move_Q(DisasContext *dc, unsigned int rd, unsigned int rs)
{
rd = QFPREG(rd);
Expand Down Expand Up @@ -2900,6 +2878,16 @@ static void gen_faligndata(TCGv dst, TCGv gsr, TCGv s1, TCGv s2)
}
#endif

static int extract_dfpreg(DisasContext *dc, int x)
{
return DFPREG(x);
}

static int extract_qfpreg(DisasContext *dc, int x)
{
return QFPREG(x);
}

/* Include the auto-generated decoder. */
#include "decode-insns.c.inc"

Expand Down Expand Up @@ -3035,6 +3023,20 @@ static bool raise_priv(DisasContext *dc)
return true;
}

static bool raise_unimpfpop(DisasContext *dc)
{
gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP);
return true;
}

static bool gen_trap_float128(DisasContext *dc)
{
if (dc->def->features & CPU_FEATURE_FLOAT128) {
return false;
}
return raise_unimpfpop(dc);
}

static bool do_bpcc(DisasContext *dc, arg_bcc *a)
{
target_long target = address_mask_i(dc, dc->pc + a->i * 4);
Expand Down Expand Up @@ -4633,6 +4635,68 @@ static bool do_casa(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
TRANS(CASA, CASA, do_casa, a, MO_TEUL)
TRANS(CASXA, 64, do_casa, a, MO_TEUQ)

static bool do_ld_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);
DisasASI da;

if (addr == NULL) {
return false;
}
if (gen_trap_ifnofpu(dc)) {
return true;
}
if (sz == MO_128 && gen_trap_float128(dc)) {
return true;
}
da = resolve_asi(dc, a->asi, MO_TE | sz);
gen_ldf_asi0(dc, &da, sz, addr, a->rd);
gen_update_fprs_dirty(dc, a->rd);
return advance_pc(dc);
}

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)

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);
DisasASI da;

if (addr == NULL) {
return false;
}
if (gen_trap_ifnofpu(dc)) {
return true;
}
if (sz == MO_128 && gen_trap_float128(dc)) {
return true;
}
da = resolve_asi(dc, a->asi, MO_TE | sz);
gen_stf_asi0(dc, &da, sz, addr, a->rd);
return advance_pc(dc);
}

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)

static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a)
{
if (!avail_32(dc)) {
return false;
}
if (!supervisor(dc)) {
return raise_priv(dc);
}
if (gen_trap_ifnofpu(dc)) {
return true;
}
gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR);
return true;
}

#define CHECK_IU_FEATURE(dc, FEATURE) \
if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
goto illegal_insn;
Expand All @@ -4647,7 +4711,8 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
TCGv cpu_src1 __attribute__((unused));
TCGv cpu_src2 __attribute__((unused));
TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32;
TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64;
TCGv_i64 cpu_src1_64, cpu_src2_64;
TCGv_i64 cpu_dst_64 __attribute__((unused));
target_long simm;

opc = GET_FIELD(insn, 0, 1);
Expand Down Expand Up @@ -5514,12 +5579,9 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
}
switch (xop) {
case 0x20: /* ldf, load fpreg */
gen_address_mask(dc, cpu_addr);
cpu_dst_32 = gen_dest_fpr_F(dc);
tcg_gen_qemu_ld_i32(cpu_dst_32, cpu_addr,
dc->mem_idx, MO_TEUL | MO_ALIGN);
gen_store_fpr_F(dc, rd, cpu_dst_32);
break;
case 0x22: /* ldqf, load quad fpreg */
case 0x23: /* lddf, load double fpreg */
g_assert_not_reached(); /* in decodetree */
case 0x21: /* ldfsr, V9 ldxfsr */
#ifdef TARGET_SPARC64
gen_address_mask(dc, cpu_addr);
Expand All @@ -5536,25 +5598,6 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
dc->mem_idx, MO_TEUL | MO_ALIGN);
gen_helper_ldfsr(cpu_fsr, tcg_env, cpu_fsr, cpu_dst_32);
break;
case 0x22: /* ldqf, load quad fpreg */
CHECK_FPU_FEATURE(dc, FLOAT128);
gen_address_mask(dc, cpu_addr);
cpu_src1_64 = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(cpu_src1_64, cpu_addr, dc->mem_idx,
MO_TEUQ | MO_ALIGN_4);
tcg_gen_addi_tl(cpu_addr, cpu_addr, 8);
cpu_src2_64 = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(cpu_src2_64, cpu_addr, dc->mem_idx,
MO_TEUQ | MO_ALIGN_4);
gen_store_fpr_Q(dc, rd, cpu_src1_64, cpu_src2_64);
break;
case 0x23: /* lddf, load double fpreg */
gen_address_mask(dc, cpu_addr);
cpu_dst_64 = gen_dest_fpr_D(dc, rd);
tcg_gen_qemu_ld_i64(cpu_dst_64, cpu_addr, dc->mem_idx,
MO_TEUQ | MO_ALIGN_4);
gen_store_fpr_D(dc, rd, cpu_dst_64);
break;
default:
goto illegal_insn;
}
Expand All @@ -5564,11 +5607,9 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
}
switch (xop) {
case 0x24: /* stf, store fpreg */
gen_address_mask(dc, cpu_addr);
cpu_src1_32 = gen_load_fpr_F(dc, rd);
tcg_gen_qemu_st_i32(cpu_src1_32, cpu_addr,
dc->mem_idx, MO_TEUL | MO_ALIGN);
break;
case 0x26: /* v9 stqf, v8 stdfq */
case 0x27: /* stdf, store double fpreg */
g_assert_not_reached();
case 0x25: /* stfsr, V9 stxfsr */
{
#ifdef TARGET_SPARC64
Expand All @@ -5583,43 +5624,6 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
dc->mem_idx, MO_TEUL | MO_ALIGN);
}
break;
case 0x26:
#ifdef TARGET_SPARC64
/* V9 stqf, store quad fpreg */
CHECK_FPU_FEATURE(dc, FLOAT128);
gen_address_mask(dc, cpu_addr);
/* ??? While stqf only requires 4-byte alignment, it is
legal for the cpu to signal the unaligned exception.
The OS trap handler is then required to fix it up.
For qemu, this avoids having to probe the second page
before performing the first write. */
cpu_src1_64 = gen_load_fpr_Q0(dc, rd);
tcg_gen_qemu_st_i64(cpu_src1_64, cpu_addr,
dc->mem_idx, MO_TEUQ | MO_ALIGN_16);
tcg_gen_addi_tl(cpu_addr, cpu_addr, 8);
cpu_src2_64 = gen_load_fpr_Q1(dc, rd);
tcg_gen_qemu_st_i64(cpu_src1_64, cpu_addr,
dc->mem_idx, MO_TEUQ);
break;
#else /* !TARGET_SPARC64 */
/* stdfq, store floating point queue */
#if defined(CONFIG_USER_ONLY)
goto illegal_insn;
#else
if (!supervisor(dc))
goto priv_insn;
if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
goto nfq_insn;
#endif
#endif
case 0x27: /* stdf, store double fpreg */
gen_address_mask(dc, cpu_addr);
cpu_src1_64 = gen_load_fpr_D(dc, rd);
tcg_gen_qemu_st_i64(cpu_src1_64, cpu_addr, dc->mem_idx,
MO_TEUQ | MO_ALIGN_4);
break;
default:
goto illegal_insn;
}
Expand Down Expand Up @@ -5666,19 +5670,9 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
illegal_insn:
gen_exception(dc, TT_ILL_INSN);
return;
#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
priv_insn:
gen_exception(dc, TT_PRIV_INSN);
return;
#endif
nfpu_insn:
gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP);
return;
#if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
nfq_insn:
gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR);
return;
#endif
}

static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
Expand Down

0 comments on commit 06c060d

Please sign in to comment.