gen_exception(dc, TT_FP_EXCP);
}
-static int gen_trap_ifnofpu(DisasContext *dc)
+static bool gen_trap_ifnofpu(DisasContext *dc)
{
#if !defined(CONFIG_USER_ONLY)
if (!dc->fpu_enabled) {
gen_exception(dc, TT_NFPU_INSN);
- return 1;
+ return true;
}
#endif
- return 0;
+ return false;
+}
+
+static bool gen_trap_iffpexception(DisasContext *dc)
+{
+#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
+ /*
+ * There are 3 states for the sparc32 fpu:
+ * Normally the fpu is in fp_execute, and all insns are allowed.
+ * When an exception is signaled, it moves to fp_exception_pending state.
+ * Upon seeing the next FPop, the fpu moves to fp_exception state,
+ * populates the FQ, and generates an fp_exception trap.
+ * The fpu remains in fp_exception state until FQ becomes empty
+ * after execution of a STDFQ instruction. While the fpu is in
+ * fp_exception state, and FPop, fp load or fp branch insn will
+ * return to fp_exception_pending state, set FSR.FTT to sequence_error,
+ * and the insn will not be entered into the FQ.
+ *
+ * In QEMU, we do not model the fp_exception_pending state and
+ * instead populate FQ and raise the exception immediately.
+ * But we can still honor fp_exception state by noticing when
+ * the FQ is not empty.
+ */
+ if (dc->fsr_qne) {
+ gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR);
+ return true;
+ }
+#endif
+ return false;
+}
+
+static bool gen_trap_if_nofpu_fpexception(DisasContext *dc)
+{
+ return gen_trap_ifnofpu(dc) || gen_trap_iffpexception(dc);
}
/* asi moves */
{
DisasCompare cmp;
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
gen_fcompare(&cmp, a->cc, a->cond);
if (addr == NULL) {
return false;
}
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
if (sz == MO_128 && gen_trap_float128(dc)) {
if (addr == NULL) {
return false;
}
+ /* Store insns are ok in fp_exception_pending state. */
if (gen_trap_ifnofpu(dc)) {
return true;
}
if (addr == NULL) {
return false;
}
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
if (addr == NULL) {
return false;
}
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
if (addr == NULL) {
return false;
}
+ /* Store insns are ok in fp_exception_pending state. */
if (gen_trap_ifnofpu(dc)) {
return true;
}
{
TCGv_i32 tmp;
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
{
TCGv_i32 tmp;
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
TCGv_i32 dst;
TCGv_i64 src;
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
{
TCGv_i64 dst, src;
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
{
TCGv_i64 dst, src;
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
TCGv_i64 dst;
TCGv_i32 src;
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
{
TCGv_i128 t;
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
if (gen_trap_float128(dc)) {
TCGv_i128 src;
TCGv_i32 dst;
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
if (gen_trap_float128(dc)) {
TCGv_i128 src;
TCGv_i64 dst;
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
if (gen_trap_float128(dc)) {
TCGv_i32 src;
TCGv_i128 dst;
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
if (gen_trap_float128(dc)) {
TCGv_i64 src;
TCGv_i128 dst;
- if (gen_trap_ifnofpu(dc)) {
- return true;
- }
- if (gen_trap_float128(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
{
TCGv_i32 src1, src2;
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
{
TCGv_i64 dst, src1, src2;
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
TCGv_i64 dst;
TCGv_i32 src1, src2;
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
if (!(dc->def->features & CPU_FEATURE_FSMULD)) {
{
TCGv_i128 src1, src2;
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
if (gen_trap_float128(dc)) {
TCGv_i64 src1, src2;
TCGv_i128 dst;
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
if (gen_trap_float128(dc)) {
if (avail_32(dc) && a->cc != 0) {
return false;
}
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
if (avail_32(dc) && a->cc != 0) {
return false;
}
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
if (avail_32(dc) && a->cc != 0) {
return false;
}
- if (gen_trap_ifnofpu(dc)) {
+ if (gen_trap_if_nofpu_fpexception(dc)) {
return true;
}
if (gen_trap_float128(dc)) {