aboutsummaryrefslogtreecommitdiff
path: root/target/arm/helper.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2021-07-30 16:16:36 +0100
committerPeter Maydell <peter.maydell@linaro.org>2021-08-25 10:48:50 +0100
commite5346292966f5348cd36668f2451ca0e44d820b2 (patch)
tree8edd319248d5af1846e528cc6c98f0342a00cdf3 /target/arm/helper.c
parentfc7a5038a6b70a3e474e58a5ed9845e4f5eed6dd (diff)
target/arm: Implement M-profile trapping on division by zero
Unlike A-profile, for M-profile the UDIV and SDIV insns can be configured to raise an exception on division by zero, using the CCR DIV_0_TRP bit. Implement support for setting this bit by making the helper functions raise the appropriate exception. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210730151636.17254-3-peter.maydell@linaro.org
Diffstat (limited to 'target/arm/helper.c')
-rw-r--r--target/arm/helper.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 8e9c2a2cf8..56c520cf8e 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -9345,6 +9345,18 @@ uint32_t HELPER(sxtb16)(uint32_t x)
return res;
}
+static void handle_possible_div0_trap(CPUARMState *env, uintptr_t ra)
+{
+ /*
+ * Take a division-by-zero exception if necessary; otherwise return
+ * to get the usual non-trapping division behaviour (result of 0)
+ */
+ if (arm_feature(env, ARM_FEATURE_M)
+ && (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_DIV_0_TRP_MASK)) {
+ raise_exception_ra(env, EXCP_DIVBYZERO, 0, 1, ra);
+ }
+}
+
uint32_t HELPER(uxtb16)(uint32_t x)
{
uint32_t res;
@@ -9353,9 +9365,10 @@ uint32_t HELPER(uxtb16)(uint32_t x)
return res;
}
-int32_t HELPER(sdiv)(int32_t num, int32_t den)
+int32_t HELPER(sdiv)(CPUARMState *env, int32_t num, int32_t den)
{
if (den == 0) {
+ handle_possible_div0_trap(env, GETPC());
return 0;
}
if (num == INT_MIN && den == -1) {
@@ -9364,9 +9377,10 @@ int32_t HELPER(sdiv)(int32_t num, int32_t den)
return num / den;
}
-uint32_t HELPER(udiv)(uint32_t num, uint32_t den)
+uint32_t HELPER(udiv)(CPUARMState *env, uint32_t num, uint32_t den)
{
if (den == 0) {
+ handle_possible_div0_trap(env, GETPC());
return 0;
}
return num / den;
@@ -9567,6 +9581,7 @@ void arm_log_exception(int idx)
[EXCP_LAZYFP] = "v7M exception during lazy FP stacking",
[EXCP_LSERR] = "v8M LSERR UsageFault",
[EXCP_UNALIGNED] = "v7M UNALIGNED UsageFault",
+ [EXCP_DIVBYZERO] = "v7M DIVBYZERO UsageFault",
};
if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {