aboutsummaryrefslogtreecommitdiff
path: root/target/sparc/translate.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/sparc/translate.c')
-rw-r--r--target/sparc/translate.c83
1 files changed, 47 insertions, 36 deletions
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index b922e53..d6b599b 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -363,15 +363,15 @@ static bool use_goto_tb(DisasContext *s, target_ulong pc, target_ulong npc)
translator_use_goto_tb(&s->base, npc);
}
-static void gen_goto_tb(DisasContext *s, int tb_num,
+static void gen_goto_tb(DisasContext *s, unsigned tb_slot_idx,
target_ulong pc, target_ulong npc)
{
if (use_goto_tb(s, pc, npc)) {
/* jump to same page: we can use a direct jump */
- tcg_gen_goto_tb(tb_num);
+ tcg_gen_goto_tb(tb_slot_idx);
tcg_gen_movi_tl(cpu_pc, pc);
tcg_gen_movi_tl(cpu_npc, npc);
- tcg_gen_exit_tb(s->base.tb, tb_num);
+ tcg_gen_exit_tb(s->base.tb, tb_slot_idx);
} else {
/* jump to another page: we can use an indirect jump */
tcg_gen_movi_tl(cpu_pc, pc);
@@ -2487,7 +2487,7 @@ static int extract_qfpreg(DisasContext *dc, int x)
#define TRANS(NAME, AVAIL, FUNC, ...) \
static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \
- { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); }
+ { return avail_##AVAIL(dc) && FUNC(dc, ## __VA_ARGS__); }
#define avail_ALL(C) true
#ifdef TARGET_SPARC64
@@ -2526,6 +2526,32 @@ static int extract_qfpreg(DisasContext *dc, int x)
# define avail_VIS4(C) false
#endif
+/*
+ * We decoded bit 13 as imm, and bits [12:0] as rs2_or_imm.
+ * For v9, if !imm, then the unused bits [12:5] must be zero.
+ * For v7 and v8, the unused bits are ignored; clear them here.
+ */
+static bool check_rs2(DisasContext *dc, int *rs2)
+{
+ if (unlikely(*rs2 & ~0x1f)) {
+ if (avail_64(dc)) {
+ return false;
+ }
+ *rs2 &= 0x1f;
+ }
+ return true;
+}
+
+static bool check_r_r_ri(DisasContext *dc, arg_r_r_ri *a)
+{
+ return a->imm || check_rs2(dc, &a->rs2_or_imm);
+}
+
+static bool check_r_r_ri_cc(DisasContext *dc, arg_r_r_ri_cc *a)
+{
+ return a->imm || check_rs2(dc, &a->rs2_or_imm);
+}
+
/* Default case for non jump instructions. */
static bool advance_pc(DisasContext *dc)
{
@@ -2823,12 +2849,15 @@ static bool trans_Tcc_i_v9(DisasContext *dc, arg_Tcc_i_v9 *a)
return do_tcc(dc, a->cond, a->cc, a->rs1, true, a->i);
}
-static bool trans_STBAR(DisasContext *dc, arg_STBAR *a)
+static bool do_stbar(DisasContext *dc)
{
tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
return advance_pc(dc);
}
+TRANS(STBAR_v8, 32, do_stbar)
+TRANS(STBAR_v9, 64, do_stbar)
+
static bool trans_MEMBAR(DisasContext *dc, arg_MEMBAR *a)
{
if (avail_32(dc)) {
@@ -2860,18 +2889,8 @@ static TCGv do_rdy(DisasContext *dc, TCGv dst)
return cpu_y;
}
-static bool trans_RDY(DisasContext *dc, arg_RDY *a)
-{
- /*
- * TODO: Need a feature bit for sparcv8. In the meantime, treat all
- * 32-bit cpus like sparcv7, which ignores the rs1 field.
- * This matches after all other ASR, so Leon3 Asr17 is handled first.
- */
- if (avail_64(dc) && a->rs1 != 0) {
- return false;
- }
- return do_rd_special(dc, true, a->rd, do_rdy);
-}
+TRANS(RDY_v7, 32, do_rd_special, true, a->rd, do_rdy)
+TRANS(RDY_v9, 64, do_rd_special, true, a->rd, do_rdy)
static TCGv do_rd_leon3_config(DisasContext *dc, TCGv dst)
{
@@ -3256,8 +3275,7 @@ static bool do_wr_special(DisasContext *dc, arg_r_r_ri *a, bool priv,
{
TCGv src;
- /* For simplicity, we under-decoded the rs2 form. */
- if (!a->imm && (a->rs2_or_imm & ~0x1f)) {
+ if (!check_r_r_ri(dc, a)) {
return false;
}
if (!priv) {
@@ -3700,8 +3718,7 @@ static bool do_arith_int(DisasContext *dc, arg_r_r_ri_cc *a,
{
TCGv dst, src1;
- /* For simplicity, we under-decoded the rs2 form. */
- if (!a->imm && a->rs2_or_imm & ~0x1f) {
+ if (!check_r_r_ri_cc(dc, a)) {
return false;
}
@@ -3785,11 +3802,11 @@ static bool trans_OR(DisasContext *dc, arg_r_r_ri_cc *a)
{
/* OR with %g0 is the canonical alias for MOV. */
if (!a->cc && a->rs1 == 0) {
+ if (!check_r_r_ri_cc(dc, a)) {
+ return false;
+ }
if (a->imm || a->rs2_or_imm == 0) {
gen_store_gpr(dc, a->rd, tcg_constant_tl(a->rs2_or_imm));
- } else if (a->rs2_or_imm & ~0x1f) {
- /* For simplicity, we under-decoded the rs2 form. */
- return false;
} else {
gen_store_gpr(dc, a->rd, cpu_regs[a->rs2_or_imm]);
}
@@ -3806,8 +3823,7 @@ static bool trans_UDIV(DisasContext *dc, arg_r_r_ri *a)
if (!avail_DIV(dc)) {
return false;
}
- /* For simplicity, we under-decoded the rs2 form. */
- if (!a->imm && a->rs2_or_imm & ~0x1f) {
+ if (!check_r_r_ri(dc, a)) {
return false;
}
@@ -3858,8 +3874,7 @@ static bool trans_UDIVX(DisasContext *dc, arg_r_r_ri *a)
if (!avail_64(dc)) {
return false;
}
- /* For simplicity, we under-decoded the rs2 form. */
- if (!a->imm && a->rs2_or_imm & ~0x1f) {
+ if (!check_r_r_ri(dc, a)) {
return false;
}
@@ -3896,8 +3911,7 @@ static bool trans_SDIVX(DisasContext *dc, arg_r_r_ri *a)
if (!avail_64(dc)) {
return false;
}
- /* For simplicity, we under-decoded the rs2 form. */
- if (!a->imm && a->rs2_or_imm & ~0x1f) {
+ if (!check_r_r_ri(dc, a)) {
return false;
}
@@ -4193,8 +4207,7 @@ TRANS(SRA_i, ALL, do_shift_i, a, false, false)
static TCGv gen_rs2_or_imm(DisasContext *dc, bool imm, int rs2_or_imm)
{
- /* For simplicity, we under-decoded the rs2 form. */
- if (!imm && rs2_or_imm & ~0x1f) {
+ if (!imm && !check_rs2(dc, &rs2_or_imm)) {
return NULL;
}
if (imm || rs2_or_imm == 0) {
@@ -4257,8 +4270,7 @@ static bool do_add_special(DisasContext *dc, arg_r_r_ri *a,
{
TCGv src1, sum;
- /* For simplicity, we under-decoded the rs2 form. */
- if (!a->imm && a->rs2_or_imm & ~0x1f) {
+ if (!check_r_r_ri(dc, a)) {
return false;
}
@@ -4376,8 +4388,7 @@ 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) {
+ if (!imm && !check_rs2(dc, &rs2_or_imm)) {
return NULL;
}