]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
target/microblaze: Handle signed division overflows
authorEdgar E. Iglesias <edgar.iglesias@amd.com>
Sun, 24 Aug 2025 19:37:32 +0000 (21:37 +0200)
committerEdgar E. Iglesias <edgar.iglesias@amd.com>
Wed, 29 Oct 2025 12:37:44 +0000 (13:37 +0100)
Handle signed division overflows as specified in UG984:
https://docs.amd.com/r/en-US/ug984-vivado-microblaze-ref/idiv

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
target/microblaze/cpu.h
target/microblaze/op_helper.c

index 14b107876a432ff2bb77a195a8b525f53fd22987..d26b933b6d00374d08b2fa231dcfde450325c829 100644 (file)
@@ -87,6 +87,7 @@ typedef struct CPUArchState CPUMBState;
 #define          ESR_ESS_FSL_OFFSET     5
 
 #define          ESR_ESS_MASK  (0x7f << 5)
+#define          ESR_ESS_DEC_OF  (1 << 11) /* DEC: 0=DBZ, 1=OF */
 
 #define          ESR_EC_FSL             0
 #define          ESR_EC_UNALIGNED_DATA  1
index d3f688e3755ea8b29e1fb93bafc4279ef49c5f23..31da2c7c3ae2fc0a6ea5eb5b7bb06cc0ace9cedc 100644 (file)
@@ -89,6 +89,21 @@ uint32_t helper_divs(CPUMBState *env, uint32_t ra, uint32_t rb)
         raise_divzero(env, ESR_EC_DIVZERO, GETPC());
         return 0;
     }
+
+    /*
+     * Check for division overflows.
+     *
+     * Spec: https://docs.amd.com/r/en-US/ug984-vivado-microblaze-ref/idiv
+     * UG984, Chapter 5 MicroBlaze Instruction Set Architecture, idiv.
+     *
+     * If the U bit is clear, the value of rA is -1, and the value of rB is
+     * -2147483648 (divide overflow), the DZO bit in MSR will be set and
+     * the value in rD will be -2147483648, unless an exception is generated.
+     */
+    if ((int32_t)ra == -1 && (int32_t)rb == INT32_MIN) {
+        raise_divzero(env, ESR_EC_DIVZERO | ESR_ESS_DEC_OF, GETPC());
+        return INT32_MIN;
+    }
     return (int32_t)rb / (int32_t)ra;
 }