aboutsummaryrefslogtreecommitdiff
path: root/target-sparc
diff options
context:
space:
mode:
Diffstat (limited to 'target-sparc')
-rw-r--r--target-sparc/cpu.h1
-rw-r--r--target-sparc/op.c24
-rw-r--r--target-sparc/translate.c47
3 files changed, 69 insertions, 3 deletions
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index d0bcd40674..8cbf0b2e30 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -210,6 +210,7 @@ typedef struct CPUSPARCState {
uint64_t version;
uint64_t fprs;
uint64_t tick_cmpr, stick_cmpr;
+ uint64_t gsr;
#endif
#if !defined(TARGET_SPARC64) && !defined(reg_T2)
target_ulong t2;
diff --git a/target-sparc/op.c b/target-sparc/op.c
index f6d417f475..7ea209ea86 100644
--- a/target-sparc/op.c
+++ b/target-sparc/op.c
@@ -1514,6 +1514,9 @@ void OPPROTO op_saved(void)
env->cansave++;
if (env->otherwin == 0)
env->canrestore--;
+ else
+ env->otherwin--;
+ FORCE_RET();
}
void OPPROTO op_restored(void)
@@ -1525,6 +1528,7 @@ void OPPROTO op_restored(void)
env->cansave--;
else
env->otherwin--;
+ FORCE_RET();
}
void OPPROTO op_popc(void)
@@ -1571,3 +1575,23 @@ void OPPROTO op_st_asi()
helper_st_asi(PARAM1, PARAM2, PARAM3);
}
+#ifdef TARGET_SPARC64
+void OPPROTO op_alignaddr()
+{
+ uint64_t tmp;
+
+ tmp = T0 + T1;
+ env->gsr &= ~7ULL;
+ env->gsr |= tmp & 7ULL;
+ T0 = tmp & ~7ULL;
+}
+
+void OPPROTO op_faligndata()
+{
+ uint64_t tmp;
+
+ tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
+ tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
+ (*((uint64_t *)&DT0)) = tmp;
+}
+#endif
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 26c81454a1..4a8ad7061b 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -364,6 +364,9 @@ GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);
case 0x80: /* Primary address space */ \
gen_op_##width##_raw(); \
break; \
+ case 0x82: /* Primary address space, non-faulting load */ \
+ gen_op_##width##_raw(); \
+ break; \
default: \
break; \
} \
@@ -1151,6 +1154,12 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_movl_T0_env(offsetof(CPUSPARCState, fprs));
gen_movl_T0_reg(rd);
break;
+ case 0x13: /* Graphics Status */
+ if (gen_trap_ifnofpu(dc))
+ goto jmp_insn;
+ gen_op_movtl_T0_env(offsetof(CPUSPARCState, gsr));
+ gen_movl_T0_reg(rd);
+ break;
case 0x17: /* Tick compare */
gen_op_movtl_T0_env(offsetof(CPUSPARCState, tick_cmpr));
gen_movl_T0_reg(rd);
@@ -1166,7 +1175,6 @@ static void disas_sparc_insn(DisasContext * dc)
case 0x10: /* Performance Control */
case 0x11: /* Performance Instrumentation Counter */
case 0x12: /* Dispatch Control */
- case 0x13: /* Graphics Status */
case 0x14: /* Softint set, WO */
case 0x15: /* Softint clear, WO */
case 0x16: /* Softint write */
@@ -1870,6 +1878,11 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_sir();
#endif
break;
+ case 0x13: /* Graphics Status */
+ if (gen_trap_ifnofpu(dc))
+ goto jmp_insn;
+ gen_op_movtl_env_T0(offsetof(CPUSPARCState, gsr));
+ break;
case 0x17: /* Tick compare */
#if !defined(CONFIG_USER_ONLY)
if (!supervisor(dc))
@@ -1895,7 +1908,6 @@ static void disas_sparc_insn(DisasContext * dc)
case 0x10: /* Performance Control */
case 0x11: /* Performance Instrumentation Counter */
case 0x12: /* Dispatch Control */
- case 0x13: /* Graphics Status */
case 0x14: /* Softint set */
case 0x15: /* Softint clear */
case 0x16: /* Softint write */
@@ -2077,7 +2089,36 @@ static void disas_sparc_insn(DisasContext * dc)
}
case 0x36: /* UltraSparc shutdown, VIS */
{
- // XXX
+ int opf = GET_FIELD_SP(insn, 5, 13);
+ rs1 = GET_FIELD(insn, 13, 17);
+ rs2 = GET_FIELD(insn, 27, 31);
+
+ switch (opf) {
+ case 0x018: /* VIS I alignaddr */
+ if (gen_trap_ifnofpu(dc))
+ goto jmp_insn;
+ gen_movl_reg_T0(rs1);
+ gen_movl_reg_T1(rs2);
+ gen_op_alignaddr();
+ gen_movl_T0_reg(rd);
+ break;
+ case 0x01a: /* VIS I alignaddrl */
+ if (gen_trap_ifnofpu(dc))
+ goto jmp_insn;
+ // XXX
+ break;
+ case 0x048: /* VIS I faligndata */
+ if (gen_trap_ifnofpu(dc))
+ goto jmp_insn;
+ gen_op_load_fpr_DT0(rs1);
+ gen_op_load_fpr_DT1(rs2);
+ gen_op_faligndata();
+ gen_op_store_DT0_fpr(rd);
+ break;
+ default:
+ goto illegal_insn;
+ }
+ break;
}
#endif
default: