File m68k.patch of Package qemu

Index: qemu-9.1.0/include/user/thunk.h
===================================================================
--- qemu-9.1.0.orig/include/user/thunk.h
+++ qemu-9.1.0/include/user/thunk.h
@@ -95,20 +95,32 @@ static inline int thunk_type_size(const
     case TYPE_CHAR:
         return 1;
     case TYPE_SHORT:
-        return 2;
+        if (is_host) {
+            return __alignof__(short);
+        } else {
+            return ABI_SHORT_ALIGNMENT;
+        }
     case TYPE_INT:
-        return 4;
+        if (is_host) {
+            return __alignof__(int);
+        } else {
+            return ABI_INT_ALIGNMENT;
+        }
     case TYPE_LONGLONG:
     case TYPE_ULONGLONG:
-        return 8;
+        if (is_host) {
+            return __alignof__(long long);
+        } else {
+            return ABI_LLONG_ALIGNMENT;
+        }
     case TYPE_LONG:
     case TYPE_ULONG:
     case TYPE_PTRVOID:
     case TYPE_PTR:
         if (is_host) {
-            return sizeof(void *);
+            return __alignof__(long);
         } else {
-            return TARGET_ABI_BITS / 8;
+            return ABI_LONG_ALIGNMENT;
         }
         break;
     case TYPE_OLDDEVT:
Index: qemu-9.1.0/linux-user/m68k/signal.c
===================================================================
--- qemu-9.1.0.orig/linux-user/m68k/signal.c
+++ qemu-9.1.0/linux-user/m68k/signal.c
@@ -215,11 +215,12 @@ static inline void target_rt_restore_fpu
 {
     int i;
     target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
-    uint32_t fpcr;
+    uint32_t fpcr, fpsr;
 
     __get_user(fpcr, &fpregs->f_fpcntl[0]);
     cpu_m68k_set_fpcr(env, fpcr);
-    __get_user(env->fpsr, &fpregs->f_fpcntl[1]);
+    __get_user(fpsr, &fpregs->f_fpcntl[1]);
+    cpu_m68k_set_fpsr(env, fpsr);
     /* fpiar is not emulated */
 
     for (i = 0; i < 8; i++) {
Index: qemu-9.1.0/target/m68k/cpu.h
===================================================================
--- qemu-9.1.0.orig/target/m68k/cpu.h
+++ qemu-9.1.0/target/m68k/cpu.h
@@ -435,6 +435,25 @@ typedef enum {
 #define FPSR_CC_Z     0x04000000 /* Zero */
 #define FPSR_CC_N     0x08000000 /* Negative */
 
+/* Exception Status */
+#define FPSR_ES_MASK  0x0000ff00
+#define FPSR_ES_BSUN  0x00008000 /* Branch Set on Unordered */
+#define FPSR_ES_SNAN  0x00004000 /* Signaling Not-A-Number */
+#define FPSR_ES_OPERR 0x00002000 /* Operand Error */
+#define FPSR_ES_OVFL  0x00001000 /* Overflow */
+#define FPSR_ES_UNFL  0x00000800 /* Underflow */
+#define FPSR_ES_DZ    0x00000400 /* Divide by Zero */
+#define FPSR_ES_INEX2 0x00000200 /* Inexact operation */
+#define FPSR_ES_INEX  0x00000100 /* Inexact decimal input */
+
+/* Accrued Exception */
+#define FPSR_AE_MASK  0x000000ff
+#define FPSR_AE_IOP   0x00000080 /* Invalid Operation */
+#define FPSR_AE_OVFL  0x00000040 /* Overflow */
+#define FPSR_AE_UNFL  0x00000020 /* Underflow */
+#define FPSR_AE_DZ    0x00000010 /* Divide by Zero */
+#define FPSR_AE_INEX  0x00000008 /* Inexact */
+
 /* Quotient */
 
 #define FPSR_QT_MASK  0x00ff0000
Index: qemu-9.1.0/target/m68k/fpu_helper.c
===================================================================
--- qemu-9.1.0.orig/target/m68k/fpu_helper.c
+++ qemu-9.1.0/target/m68k/fpu_helper.c
@@ -145,6 +145,70 @@ void cpu_m68k_restore_fp_status(CPUM68KS
     restore_rounding_mode(env);
 }
 
+static uint32_t set_fpsr_exception(CPUM68KState *env, uint32_t fpsr)
+{
+    uint32_t ae = 0;
+    int flags;
+
+    flags = get_float_exception_flags(&env->fp_status);
+    if (flags == 0) {
+        return fpsr;
+    }
+    set_float_exception_flags(0, &env->fp_status);
+
+    if (flags & float_flag_invalid) {
+        ae |= FPSR_AE_IOP;
+    }
+    if (flags & float_flag_divbyzero) {
+        ae |= FPSR_AE_DZ;
+    }
+    if (flags & float_flag_overflow) {
+        ae |= FPSR_AE_OVFL;
+    }
+    if (flags & float_flag_underflow) {
+        ae |= FPSR_AE_UNFL;
+    }
+    if (flags & float_flag_inexact) {
+        ae |= FPSR_AE_INEX;
+    }
+
+    return (fpsr & ~FPSR_AE_MASK) | ae;
+}
+
+static void fpu_exception(CPUM68KState *env, uint32_t exception)
+{
+    CPUState *cs = CPU(env_cpu(env));
+
+    env->fpsr = (env->fpsr & ~FPSR_ES_MASK) | exception;
+    if (env->fpcr & exception) {
+        switch (exception) {
+        case FPSR_ES_BSUN:
+            cs->exception_index = EXCP_FP_BSUN;
+            break;
+        case FPSR_ES_SNAN:
+            cs->exception_index = EXCP_FP_SNAN;
+            break;
+        case FPSR_ES_OPERR:
+            cs->exception_index = EXCP_FP_OPERR;
+            break;
+        case FPSR_ES_OVFL:
+            cs->exception_index = EXCP_FP_OVFL;
+            break;
+        case FPSR_ES_UNFL:
+            cs->exception_index = EXCP_FP_UNFL;
+            break;
+        case FPSR_ES_DZ:
+            cs->exception_index = EXCP_FP_DZ;
+            break;
+        case FPSR_ES_INEX:
+        case FPSR_ES_INEX2:
+            cs->exception_index = EXCP_FP_INEX;
+            break;
+        }
+        cpu_loop_exit_restore(cs, GETPC());
+    }
+}
+
 void cpu_m68k_set_fpcr(CPUM68KState *env, uint32_t val)
 {
     env->fpcr = val & 0xffff;
@@ -440,9 +504,17 @@ static int float_comp_to_cc(FloatRelatio
 void HELPER(fcmp)(CPUM68KState *env, FPReg *val0, FPReg *val1)
 {
     FloatRelation float_compare;
+    int flags;
+    uint32_t fpsr;
 
     float_compare = floatx80_compare(val1->d, val0->d, &env->fp_status);
-    env->fpsr = (env->fpsr & ~FPSR_CC_MASK) | float_comp_to_cc(float_compare);
+    fpsr = (env->fpsr & ~FPSR_CC_MASK) | float_comp_to_cc(float_compare);
+
+    flags = get_float_exception_flags(&env->fp_status);
+    if (flags & float_flag_invalid) {
+        fpu_exception(env, FPSR_ES_OPERR);
+    }
+    env->fpsr = set_fpsr_exception(env, fpsr);
 }
 
 void HELPER(ftst)(CPUM68KState *env, FPReg *val)
@@ -460,7 +532,8 @@ void HELPER(ftst)(CPUM68KState *env, FPR
     } else if (floatx80_is_zero(val->d)) {
         cc |= FPSR_CC_Z;
     }
-    env->fpsr = (env->fpsr & ~FPSR_CC_MASK) | cc;
+
+    env->fpsr = set_fpsr_exception(env, (env->fpsr & ~FPSR_CC_MASK) | cc);
 }
 
 void HELPER(fconst)(CPUM68KState *env, FPReg *val, uint32_t offset)
Index: qemu-9.1.0/target/m68k/translate.c
===================================================================
--- qemu-9.1.0.orig/target/m68k/translate.c
+++ qemu-9.1.0/target/m68k/translate.c
@@ -6157,8 +6157,22 @@ void m68k_cpu_dump_state(CPUState *cs, F
                  (env->fpsr & FPSR_CC_I) ? 'I' : '-',
                  (env->fpsr & FPSR_CC_Z) ? 'Z' : '-',
                  (env->fpsr & FPSR_CC_N) ? 'N' : '-');
-    qemu_fprintf(f, "\n                                "
-                 "FPCR =     %04x ", env->fpcr);
+    qemu_fprintf(f, "%c%c%c%c%c%c%c%c ",
+                 (env->fpsr & FPSR_ES_BSUN) ? 'B' : '-',
+                 (env->fpsr & FPSR_ES_SNAN) ? 'A' : '-',
+                 (env->fpsr & FPSR_ES_OPERR) ? 'O' : '-',
+                 (env->fpsr & FPSR_ES_OVFL) ? 'V' : '-',
+                 (env->fpsr & FPSR_ES_UNFL) ? 'U' : '-',
+                 (env->fpsr & FPSR_ES_DZ) ? 'Z' : '-',
+                 (env->fpsr & FPSR_ES_INEX2) ? '2' : '-',
+                 (env->fpcr & FPSR_ES_INEX) ? 'I' : '-');
+    qemu_fprintf(f, "%c%c%c%c%c  ",
+                 (env->fpsr & FPSR_AE_IOP) ? 'O' : '-',
+                 (env->fpsr & FPSR_AE_OVFL) ? 'V' : '-',
+                 (env->fpsr & FPSR_AE_UNFL) ? 'U' : '-',
+                 (env->fpsr & FPSR_AE_DZ) ? 'Z' : '-',
+                 (env->fpcr & FPSR_ES_INEX) ? 'I' : '-');
+    qemu_fprintf(f, "FPCR = %04x ", env->fpcr);
     switch (env->fpcr & FPCR_PREC_MASK) {
     case FPCR_PREC_X:
         qemu_fprintf(f, "X ");
@@ -6184,7 +6198,16 @@ void m68k_cpu_dump_state(CPUState *cs, F
         qemu_fprintf(f, "RP ");
         break;
     }
-    qemu_fprintf(f, "\n");
+    /* FPCR exception mask uses the same bitmask as FPSR */
+    qemu_fprintf(f, "%c%c%c%c%c%c%c%c\n",
+                 (env->fpcr & FPSR_ES_BSUN) ? 'B' : '-',
+                 (env->fpcr & FPSR_ES_SNAN) ? 'A' : '-',
+                 (env->fpcr & FPSR_ES_OPERR) ? 'O' : '-',
+                 (env->fpcr & FPSR_ES_OVFL) ? 'V' : '-',
+                 (env->fpcr & FPSR_ES_UNFL) ? 'U' : '-',
+                 (env->fpcr & FPSR_ES_DZ) ? 'Z' : '-',
+                 (env->fpcr & FPSR_ES_INEX2) ? '2' : '-',
+                 (env->fpcr & FPSR_ES_INEX) ? 'I' : '-');
 #ifndef CONFIG_USER_ONLY
     qemu_fprintf(f, "%sA7(MSP) = %08x %sA7(USP) = %08x %sA7(ISP) = %08x\n",
                  env->current_sp == M68K_SSP ? "->" : "  ", env->sp[M68K_SSP],
openSUSE Build Service is sponsored by