aboutsummaryrefslogtreecommitdiff
path: root/target-arm/op_helper.c
diff options
context:
space:
mode:
authorpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2008-03-31 03:46:33 +0000
committerpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2008-03-31 03:46:33 +0000
commit6ddbc6e4cfbfa0937fdebd8aa7b518d8b7fd118b (patch)
treef1a5af853e58f91106f2eb90338cc795ae036fa2 /target-arm/op_helper.c
parent3670669ce25ef337a6e5e99b7a97b83997c06721 (diff)
ARM TCG conversion 7/16.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4144 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-arm/op_helper.c')
-rw-r--r--target-arm/op_helper.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 1b90f58296..2d3abfd79b 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -369,3 +369,70 @@ uint32_t HELPER(sub_usaturate)(uint32_t a, uint32_t b)
return res;
}
+/* Signed saturation. */
+static inline uint32_t do_ssat(int32_t val, int shift)
+{
+ int32_t top;
+ uint32_t mask;
+
+ shift = PARAM1;
+ top = val >> shift;
+ mask = (1u << shift) - 1;
+ if (top > 0) {
+ env->QF = 1;
+ return mask;
+ } else if (top < -1) {
+ env->QF = 1;
+ return ~mask;
+ }
+ return val;
+}
+
+/* Unsigned saturation. */
+static inline uint32_t do_usat(int32_t val, int shift)
+{
+ uint32_t max;
+
+ shift = PARAM1;
+ max = (1u << shift) - 1;
+ if (val < 0) {
+ env->QF = 1;
+ return 0;
+ } else if (val > max) {
+ env->QF = 1;
+ return max;
+ }
+ return val;
+}
+
+/* Signed saturate. */
+uint32_t HELPER(ssat)(uint32_t x, uint32_t shift)
+{
+ return do_ssat(x, shift);
+}
+
+/* Dual halfword signed saturate. */
+uint32_t HELPER(ssat16)(uint32_t x, uint32_t shift)
+{
+ uint32_t res;
+
+ res = (uint16_t)do_ssat((int16_t)x, shift);
+ res |= do_ssat(((int32_t)x) >> 16, shift) << 16;
+ return res;
+}
+
+/* Unsigned saturate. */
+uint32_t HELPER(usat)(uint32_t x, uint32_t shift)
+{
+ return do_usat(x, shift);
+}
+
+/* Dual halfword unsigned saturate. */
+uint32_t HELPER(usat16)(uint32_t x, uint32_t shift)
+{
+ uint32_t res;
+
+ res = (uint16_t)do_usat((int16_t)x, shift);
+ res |= do_usat(((int32_t)x) >> 16, shift) << 16;
+ return res;
+}