MSP430: Implement 64-bit shifts in assembly code
authorJozef Lawrynowicz <jozef.l@mittosystems.com>
Sun, 16 Jun 2019 21:24:56 +0000 (21:24 +0000)
committerJozef Lawrynowicz <jozefl@gcc.gnu.org>
Sun, 16 Jun 2019 21:24:56 +0000 (21:24 +0000)
gcc/ChangeLog:

2019-06-16  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

* config/msp430/msp430.c (msp430_expand_helper): Setup arguments which
describe how to perform MSPABI compliant 64-bit shift.
* config/msp430/msp430.md (ashldi3): New define_expand.
(ashrdi3): New define_expand.
(lshrdi3): New define_expand.

libgcc/ChangeLog:

2019-06-16  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

* config/msp430/slli.S (__mspabi_sllll): New library function for
performing a logical left shift of a 64-bit value.
* config/msp430/srai.S (__mspabi_srall): New library function for
performing a arithmetic right shift of a 64-bit value.
* config/msp430/srll.S (__mspabi_srlll): New library function for
performing a logical right shift of a 64-bit value.

gcc/testsuite/ChangeLog:

2019-06-16  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

* gcc.target/msp430/mspabi_sllll.c: New test.
* gcc.target/msp430/mspabi_srall.c: New test.
* gcc.target/msp430/mspabi_srlll.c: New test.
* gcc.c-torture/execute/shiftdi-2.c: New test.

From-SVN: r272360

12 files changed:
gcc/ChangeLog
gcc/config/msp430/msp430.c
gcc/config/msp430/msp430.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/shiftdi-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/msp430/mspabi_sllll.c [new file with mode: 0644]
gcc/testsuite/gcc.target/msp430/mspabi_srall.c [new file with mode: 0644]
gcc/testsuite/gcc.target/msp430/mspabi_srlll.c [new file with mode: 0644]
libgcc/ChangeLog
libgcc/config/msp430/slli.S
libgcc/config/msp430/srai.S
libgcc/config/msp430/srli.S

index 92ee5ea7a64c6c162e0f41ea71159941e9b7b736..1b7528b41673e9e4e910963804a902a971fbd228 100644 (file)
@@ -1,3 +1,11 @@
+2019-06-16  Jozef Lawrynowicz  <jozef.l@mittosystems.com>
+
+       * config/msp430/msp430.c (msp430_expand_helper): Setup arguments which
+       describe how to perform MSPABI compliant 64-bit shift.
+       * config/msp430/msp430.md (ashldi3): New define_expand.
+       (ashrdi3): New define_expand.
+       (lshrdi3): New define_expand.
+
 2019-06-16  Jozef Lawrynowicz  <jozef.l@mittosystems.com>
 
        * doc/sourcebuild.texi: Document new effective target keyword
index 020e980b8cc152446e9d5eaef71996a3f6ffdf54..365e9eba747f94d2af35da30b6bd8d229c0fbac3 100644 (file)
@@ -3046,6 +3046,7 @@ msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variant
 {
   rtx c, f;
   char *helper_const = NULL;
+  int arg1 = 12;
   int arg2 = 13;
   int arg1sz = 1;
   machine_mode arg0mode = GET_MODE (operands[0]);
@@ -3079,6 +3080,13 @@ msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variant
       arg2 = 14;
       arg1sz = 2;
     }
+  else if (arg1mode == DImode)
+    {
+      /* Shift value in R8:R11, shift amount in R12.  */
+      arg1 = 8;
+      arg1sz = 4;
+      arg2 = 12;
+    }
 
   if (const_variants
       && CONST_INT_P (operands[2])
@@ -3091,7 +3099,7 @@ msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variant
       snprintf (helper_const, len, "%s_%d", helper_name, (int) INTVAL (operands[2]));
     }
 
-  emit_move_insn (gen_rtx_REG (arg1mode, 12),
+  emit_move_insn (gen_rtx_REG (arg1mode, arg1),
                  operands[1]);
   if (!helper_const)
     emit_move_insn (gen_rtx_REG (arg2mode, arg2),
@@ -3104,12 +3112,13 @@ msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variant
   RTL_CONST_CALL_P (c) = 1;
 
   f = 0;
-  use_regs (&f, 12, arg1sz);
+  use_regs (&f, arg1, arg1sz);
   if (!helper_const)
     use_regs (&f, arg2, 1);
   add_function_usage_to (c, f);
 
   emit_move_insn (operands[0],
+                 /* Return value will always start in R12.  */
                  gen_rtx_REG (arg0mode, 12));
 }
 
index 76296a2f317f31169723abae01017043569d9c0d..f6d688950cb38dcbc657e620e1671d4558e27d62 100644 (file)
    DONE;"
 )
 
+(define_expand "ashldi3"
+  [(set (match_operand:DI           0 "nonimmediate_operand")
+       (ashift:DI (match_operand:DI 1 "general_operand")
+                  (match_operand:DI 2 "general_operand")))]
+  ""
+  {
+    /* No const_variant for 64-bit shifts.  */
+    msp430_expand_helper (operands, \"__mspabi_sllll\", false);
+    DONE;
+  }
+)
+
 ;;----------
 
 ;; signed A >> C
    DONE;"
 )
 
+(define_expand "ashrdi3"
+  [(set (match_operand:DI           0 "nonimmediate_operand")
+       (ashift:DI (match_operand:DI 1 "general_operand")
+                  (match_operand:DI 2 "general_operand")))]
+  ""
+  {
+    /* No const_variant for 64-bit shifts.  */
+    msp430_expand_helper (operands, \"__mspabi_srall\", false);
+    DONE;
+  }
+)
+
 ;;----------
 
 ;; unsigned A >> C
    DONE;"
 )
 
+(define_expand "lshrdi3"
+  [(set (match_operand:DI           0 "nonimmediate_operand")
+       (ashift:DI (match_operand:DI 1 "general_operand")
+                  (match_operand:DI 2 "general_operand")))]
+  ""
+  {
+    /* No const_variant for 64-bit shifts.  */
+    msp430_expand_helper (operands, \"__mspabi_srlll\", false);
+    DONE;
+  }
+)
+
 ;;------------------------------------------------------------
 ;; Function Entry/Exit
 
index 2dceffb0399d3d7b68a0d12ad25c6b385e5fcdf8..55693dc8ac265b217fb6cfbcb508ea4be93a8d53 100644 (file)
@@ -1,3 +1,10 @@
+2019-06-16  Jozef Lawrynowicz  <jozef.l@mittosystems.com>
+
+       * gcc.target/msp430/mspabi_sllll.c: New test.
+       * gcc.target/msp430/mspabi_srall.c: New test.
+       * gcc.target/msp430/mspabi_srlll.c: New test.
+       * gcc.c-torture/execute/shiftdi-2.c: New test.
+
 2019-06-16  Jozef Lawrynowicz  <jozef.l@mittosystems.com>
 
        * lib/target-supports.exp: Add check_effective_target_longlong64. 
diff --git a/gcc/testsuite/gcc.c-torture/execute/shiftdi-2.c b/gcc/testsuite/gcc.c-torture/execute/shiftdi-2.c
new file mode 100644 (file)
index 0000000..812946f
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-require-effective-target longlong64 } */
+
+long long a = 568513516876543756;
+long long b = -754324895235774564;
+unsigned long long c = 156789543257562457;
+
+long long expected_a[64] = {568513516876543756, 1137027033753087512, 2274054067506175024, 4548108135012350048, 9096216270024700096, -254311533660151424, -508623067320302848, -1017246134640605696, -2034492269281211392, -4068984538562422784, -8137969077124845568, 2170805919459860480, 4341611838919720960, 8683223677839441920, -1080296718030667776, -2160593436061335552, -4321186872122671104, -8642373744245342208, 1161996585218867200, 2323993170437734400, 4647986340875468800, -9150771391958614016, 145201289792323584, 290402579584647168, 580805159169294336, 1161610318338588672, 2323220636677177344, 4646441273354354688, -9153861527000842240, 139021019707867136, 278042039415734272, 556084078831468544, 1112168157662937088, 2224336315325874176, 4448672630651748352, 8897345261303496704, -652053551102558208, -1304107102205116416, -2608214204410232832, -5216428408820465664, 8013887256068620288, -2418969561572311040, -4837939123144622080, 8770865827420307456, -905012418868936704, -1810024837737873408, -3620049675475746816, -7240099350951493632, 3966545371806564352, 7933090743613128704, -2580562586483294208, -5161125172966588416, 8124493727776374784, -2197756618156802048, -4395513236313604096, -8791026472627208192, 864691128455135232, 1729382256910270464, 3458764513820540928, 6917529027641081856, -4611686018427387904, -9223372036854775808ULL, 0, 0};
+long long expected_b[64] = {-754324895235774564, -377162447617887282, -188581223808943641, -94290611904471821, -47145305952235911, -23572652976117956, -11786326488058978, -5893163244029489, -2946581622014745, -1473290811007373, -736645405503687, -368322702751844, -184161351375922, -92080675687961, -46040337843981, -23020168921991, -11510084460996, -5755042230498, -2877521115249, -1438760557625, -719380278813, -359690139407, -179845069704, -89922534852, -44961267426, -22480633713, -11240316857, -5620158429, -2810079215, -1405039608, -702519804, -351259902, -175629951, -87814976, -43907488, -21953744, -10976872, -5488436, -2744218, -1372109, -686055, -343028, -171514, -85757, -42879, -21440, -10720, -5360, -2680, -1340, -670, -335, -168, -84, -42, -21, -11, -6, -3, -2, -1, -1, -1, -1};
+unsigned long long expected_c[64] = {156789543257562457, 78394771628781228, 39197385814390614, 19598692907195307, 9799346453597653, 4899673226798826, 2449836613399413, 1224918306699706, 612459153349853, 306229576674926, 153114788337463, 76557394168731, 38278697084365, 19139348542182, 9569674271091, 4784837135545, 2392418567772, 1196209283886, 598104641943, 299052320971, 149526160485, 74763080242, 37381540121, 18690770060, 9345385030, 4672692515, 2336346257, 1168173128, 584086564, 292043282, 146021641, 73010820, 36505410, 18252705, 9126352, 4563176, 2281588, 1140794, 570397, 285198, 142599, 71299, 35649, 17824, 8912, 4456, 2228, 1114, 557, 278, 139, 69, 34, 17, 8, 4, 2, 1, 0, 0, 0, 0, 0, 0};
+
+int
+main (void)
+{
+  int i;
+
+  for (i = 0; i < 64; i++)
+  {
+    if ((a << i) != expected_a[i]
+       || (b >> i) != expected_b[i]
+       || (c >> i) != expected_c[i])
+      __builtin_abort ();
+  }
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/msp430/mspabi_sllll.c b/gcc/testsuite/gcc.target/msp430/mspabi_sllll.c
new file mode 100644 (file)
index 0000000..b88a8be
--- /dev/null
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-final { scan-assembler-not "ashldi3" } } */
+/* { dg-final { scan-assembler "__mspabi_sllll" } } */
+
+long long
+foo (long long a)
+{
+  return a << 4;
+}
+
diff --git a/gcc/testsuite/gcc.target/msp430/mspabi_srall.c b/gcc/testsuite/gcc.target/msp430/mspabi_srall.c
new file mode 100644 (file)
index 0000000..a0aba3d
--- /dev/null
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-final { scan-assembler-not "ashrdi3" } } */
+/* { dg-final { scan-assembler "__mspabi_srall" } } */
+
+long long
+foo (long long a)
+{
+  return a >> 4;
+}
+
diff --git a/gcc/testsuite/gcc.target/msp430/mspabi_srlll.c b/gcc/testsuite/gcc.target/msp430/mspabi_srlll.c
new file mode 100644 (file)
index 0000000..cb9a374
--- /dev/null
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-final { scan-assembler-not "lshrdi3" } } */
+/* { dg-final { scan-assembler "__mspabi_srlll" } } */
+
+unsigned long long
+foo (unsigned long long a)
+{
+  return a >> 4;
+}
+
index 959776da959788cf2aedaf77d17b70b20884588d..fee8b3811a36e79df31b089fd946e0ccd379c6dc 100644 (file)
@@ -1,3 +1,12 @@
+2019-06-16  Jozef Lawrynowicz  <jozef.l@mittosystems.com>
+
+       * config/msp430/slli.S (__mspabi_sllll): New library function for
+       performing a logical left shift of a 64-bit value.
+       * config/msp430/srai.S (__mspabi_srall): New library function for
+       performing a arithmetic right shift of a 64-bit value.
+       * config/msp430/srll.S (__mspabi_srlll): New library function for
+       performing a logical right shift of a 64-bit value.
+
 2019-06-14  Matt Thomas  <matt@3am-software.com>
            Matthew Green  <mrg@eterna.com.au>
            Nick Hudson  <skrll@netbsd.org>
index 89ca35a9304b7ce5e82f1f03a0470817ec076963..9210fe6e9343f49fae2966adb1b9df415b05f86f 100644 (file)
@@ -110,3 +110,36 @@ __mspabi_slll:
        RET
 #endif
 
+/* Logical Left Shift - R8:R11 -> R12:R15
+   A 64-bit argument would normally be passed in R12:R15, but __mspabi_sllll has
+   special conventions, so the 64-bit value to shift is passed in R8:R11.
+   According to the MSPABI, the shift amount is a 64-bit value in R12:R15, but
+   we only use the low word in R12.  */
+
+       .section        .text.__mspabi_sllll
+       .global __mspabi_sllll
+__mspabi_sllll:
+       MOV R11, R15 ; Free up R11 first
+       MOV R12, R11 ; Save the shift amount in R11
+       MOV R10, R14
+       MOV R9, R13
+       MOV R8, R12
+       CMP #0,R11
+       JNZ 1f
+#ifdef __MSP430X_LARGE__
+       RETA
+#else
+       RET
+#endif
+1:
+       RLA R12
+       RLC R13
+       RLC R14
+       RLC R15
+       ADD #-1,R11
+       JNZ 1b
+#ifdef __MSP430X_LARGE__
+       RETA
+#else
+       RET
+#endif
index 564f7989a8ce6c073dd865931fcfa557068396e2..ed5c6a5ad7cd78f983c66e9c306e589c62cab70a 100644 (file)
@@ -108,3 +108,37 @@ __mspabi_sral:
 #else
        RET
 #endif
+
+/* Arithmetic Right Shift - R8:R11 -> R12:R15
+   A 64-bit argument would normally be passed in R12:R15, but __mspabi_srall has
+   special conventions, so the 64-bit value to shift is passed in R8:R11.
+   According to the MSPABI, the shift amount is a 64-bit value in R12:R15, but
+   we only use the low word in R12.  */
+
+       .section        .text.__mspabi_srall
+       .global __mspabi_srall
+__mspabi_srall:
+       MOV R11, R15 ; Free up R11 first
+       MOV R12, R11 ; Save the shift amount in R11
+       MOV R10, R14
+       MOV R9, R13
+       MOV R8, R12
+       CMP #0, R11
+       JNZ 1f
+#ifdef __MSP430X_LARGE__
+       RETA
+#else
+       RET
+#endif
+1:
+       RRA R15
+       RRC R14
+       RRC R13
+       RRC R12
+       ADD #-1,R11
+       JNZ 1b
+#ifdef __MSP430X_LARGE__
+       RETA
+#else
+       RET
+#endif
index 4dd32ea4002f4db55a89a84ac23b760be98950c5..bc1b034e4b9831f68efcd644deaa3a80a911fc76 100644 (file)
@@ -112,3 +112,38 @@ __mspabi_srll:
 #else
        RET
 #endif
+
+/* Logical Right Shift - R8:R11 -> R12:R15
+   A 64-bit argument would normally be passed in R12:R15, but __mspabi_srlll has
+   special conventions, so the 64-bit value to shift is passed in R8:R11.
+   According to the MSPABI, the shift amount is a 64-bit value in R12:R15, but
+   we only use the low word in R12.  */
+
+       .section        .text.__mspabi_srlll
+       .global __mspabi_srlll
+__mspabi_srlll:
+       MOV R11, R15 ; Free up R11 first
+       MOV R12, R11 ; Save the shift amount in R11
+       MOV R10, R14
+       MOV R9, R13
+       MOV R8, R12
+       CMP #0,R11
+       JNZ 1f
+#ifdef __MSP430X_LARGE__
+       RETA
+#else
+       RET
+#endif
+1:
+       CLRC
+       RRC R15
+       RRC R14
+       RRC R13
+       RRC R12
+       ADD #-1,R11
+       JNZ 1b
+#ifdef __MSP430X_LARGE__
+       RETA
+#else
+       RET
+#endif