MSP430: Add 'd', 'e', 'f' and 'g' asm operand modifiers

Message ID 20200910094457.aold5r3hokd6x54p@jozef-acer-manjaro
State New
Headers show
Series
  • MSP430: Add 'd', 'e', 'f' and 'g' asm operand modifiers
Related show

Commit Message

Jozef Lawrynowicz Sept. 10, 2020, 9:44 a.m.
The new operand modifiers can be used to select odd-numbered bytes of a memory
reference or constant value.

Successfully regtested on trunk for msp430-elf in the default, -mlarge,
-mcpu=msp430 and -mlarge/-mcode-region=either/-mdata-region=either
configurations.

Ok for trunk?

Thanks,
Jozef
From c48ad2ae243a101afe8d021e847c56a482a60f20 Mon Sep 17 00:00:00 2001
From: Jozef Lawrynowicz <jozef.l@mittosystems.com>

Date: Wed, 9 Sep 2020 13:06:46 +0100
Subject: [PATCH] MSP430: Add 'd', 'e', 'f' and 'g' asm operand modifiers

The new operand modifiers can be used to select odd-numbered bytes of a memory
reference or constant value.

gcc/ChangeLog:

	* config/msp430/msp430.c (msp430_print_operand): Update comment.
	Cast to long when printing values formatted as long.
	Support 'd', 'e', 'f' and 'g' modifiers.
	Extract operand value with a single operation for all modifiers.
	* doc/extend.texi (msp430Operandmodifiers): New.

gcc/testsuite/ChangeLog:

	* gcc.target/msp430/operand-modifiers.c: Extend test to handle new
	modifiers.
	* gcc.target/msp430/operand-modifiers-bad.c: New test.
---
 gcc/config/msp430/msp430.c                    | 152 ++++++++--------
 gcc/doc/extend.texi                           |  36 ++++
 .../gcc.target/msp430/operand-modifiers-bad.c |  15 ++
 .../gcc.target/msp430/operand-modifiers.c     | 167 +++++++++++++++---
 4 files changed, 277 insertions(+), 93 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/msp430/operand-modifiers-bad.c

-- 
2.28.0

Comments

H.J. Lu via Gcc-patches Sept. 17, 2020, 9:44 p.m. | #1
On 9/10/20 3:44 AM, Jozef Lawrynowicz wrote:
> The new operand modifiers can be used to select odd-numbered bytes of a memory

> reference or constant value.

>

> Successfully regtested on trunk for msp430-elf in the default, -mlarge,

> -mcpu=msp430 and -mlarge/-mcode-region=either/-mdata-region=either

> configurations.

>

> Ok for trunk?

>

> Thanks,

> Jozef

>

> 0001-MSP430-Add-d-e-f-and-g-asm-operand-modifiers.patch

>

> From c48ad2ae243a101afe8d021e847c56a482a60f20 Mon Sep 17 00:00:00 2001

> From: Jozef Lawrynowicz <jozef.l@mittosystems.com>

> Date: Wed, 9 Sep 2020 13:06:46 +0100

> Subject: [PATCH] MSP430: Add 'd', 'e', 'f' and 'g' asm operand modifiers

>

> The new operand modifiers can be used to select odd-numbered bytes of a memory

> reference or constant value.

>

> gcc/ChangeLog:

>

> 	* config/msp430/msp430.c (msp430_print_operand): Update comment.

> 	Cast to long when printing values formatted as long.

> 	Support 'd', 'e', 'f' and 'g' modifiers.

> 	Extract operand value with a single operation for all modifiers.

> 	* doc/extend.texi (msp430Operandmodifiers): New.

>

> gcc/testsuite/ChangeLog:

>

> 	* gcc.target/msp430/operand-modifiers.c: Extend test to handle new

> 	modifiers.

> 	* gcc.target/msp430/operand-modifiers-bad.c: New test.


OK

jeff

Patch

diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index a299ed7f9d1..e46a8d23bc7 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -3475,30 +3475,43 @@  msp430_op_not_in_high_mem (rtx op)
 #undef  TARGET_PRINT_OPERAND
 #define TARGET_PRINT_OPERAND		msp430_print_operand
 
-/* A   low 16-bits of int/lower of register pair
-   B   high 16-bits of int/higher of register pair
-   C   bits 32-47 of a 64-bit value/reg 3 of a DImode value
-   D   bits 48-63 of a 64-bit value/reg 4 of a DImode value
-   H   like %B (for backwards compatibility)
-   I   inverse of value
-   J   an integer without a # prefix
-   L   like %A (for backwards compatibility)
-   O   offset of the top of the stack
-   Q   like X but generates an A postfix
-   R   inverse of condition code, unsigned.
-   W   value - 16
-   X   X instruction postfix in large mode
-   Y   value - 4
-   Z   value - 1
-   b   .B or .W or .A, depending upon the mode
-   p   bit position
-   r   inverse of condition code
-   x   like X but only for pointers.  */
+/* A   Select low 16-bits of the constant/register/memory operand.
+   B   Select high 16-bits of the constant/register/memory
+       operand.
+   C   Select bits 32-47 of the constant/register/memory operand.
+   D   Select bits 48-63 of the constant/register/memory operand.
+   H   Equivalent to @code{B} (for backwards compatibility).
+   I   Print the inverse (logical @code{NOT}) of the constant
+       value.
+   J   Print an integer without a @code{#} prefix.
+   L   Equivalent to @code{A} (for backwards compatibility).
+   O   Offset of the current frame from the top of the stack.
+   Q   Use the @code{A} instruction postfix.
+   R   Inverse of condition code, for unsigned comparisons.
+   W   Subtract 16 from the constant value.
+   X   Use the @code{X} instruction postfix.
+   Y   Subtract 4 from the constant value.
+   Z   Subtract 1 from the constant value.
+   b   Append @code{.B}, @code{.W} or @code{.A} to the
+       instruction, depending on the mode.
+   d   Offset 1 byte of a memory reference or constant value.
+   e   Offset 3 bytes of a memory reference or constant value.
+   f   Offset 5 bytes of a memory reference or constant value.
+   g   Offset 7 bytes of a memory reference or constant value.
+   p   Print the value of 2, raised to the power of the given
+       constant.  Used to select the specified bit position.
+   r   Inverse of condition code, for signed comparisons.
+   x   Equivialent to @code{X}, but only for pointers.  */
 
 static void
 msp430_print_operand (FILE * file, rtx op, int letter)
 {
   rtx addr;
+  /* These are used by the 'A', 'B', 'C', 'D', 'd', 'e', 'f' and 'g' modifiers
+     to describe how to process the operand to get the requested value.  */
+  int mem_off = 0;
+  int reg_off = 0;
+  int const_shift = 0;
 
   /* We can't use c, n, a, or l.  */
   switch (letter)
@@ -3506,17 +3519,17 @@  msp430_print_operand (FILE * file, rtx op, int letter)
     case 'Z':
       gcc_assert (CONST_INT_P (op));
       /* Print the constant value, less one.  */
-      fprintf (file, "#%ld", INTVAL (op) - 1);
+      fprintf (file, "#%ld", (long) (INTVAL (op) - 1));
       return;
     case 'Y':
       gcc_assert (CONST_INT_P (op));
       /* Print the constant value, less four.  */
-      fprintf (file, "#%ld", INTVAL (op) - 4);
+      fprintf (file, "#%ld", (long) (INTVAL (op) - 4));
       return;
     case 'W':
       gcc_assert (CONST_INT_P (op));
       /* Print the constant value, less 16.  */
-      fprintf (file, "#%ld", INTVAL (op) - 16);
+      fprintf (file, "#%ld", (long) (INTVAL (op) - 16));
       return;
     case 'I':
       if (GET_CODE (op) == CONST_INT)
@@ -3573,76 +3586,71 @@  msp430_print_operand (FILE * file, rtx op, int letter)
 	default:
 	  return;
 	}
-    case 'A':
-    case 'L': /* Low half.  */
-      switch (GET_CODE (op))
+    case 'd': case 'e': case 'f': case 'g':
+      if (REG_P (op))
 	{
-	case MEM:
-	  op = adjust_address (op, Pmode, 0);
-	  break;
-	case REG:
-	  break;
-	case CONST_INT:
-	  op = GEN_INT (INTVAL (op) & 0xffff);
-	  letter = 0;
-	  break;
-	default:
-	  /* If you get here, figure out a test case :-) */
-	  gcc_unreachable ();
+	  output_operand_lossage ("%%d, %%e, %%f, %%g operand modifiers are "
+				  "for memory references or constant values "
+				  "only");
+	  return;
 	}
-      break;
-    case 'B':
-    case 'H': /* high half */
-      switch (GET_CODE (op))
+      /* fallthru */
+    case 'B': case 'H': /* high half */
+    case 'C':
+    case 'D':
+      switch (letter)
 	{
-	case MEM:
-	  /* We don't need to adjust the address for post_inc.  */
-	  op = adjust_address (op, Pmode,
-			       (GET_CODE (XEXP (op, 0)) == POST_INC) ? 0 : 2);
+	case 'd':
+	  mem_off = 1;
+	  const_shift = 8;
 	  break;
-	case REG:
-	  op = gen_rtx_REG (Pmode, REGNO (op) + 1);
+	case 'B':
+	case 'H':
+	  mem_off = 2;
+	  reg_off = 1;
+	  const_shift = 16;
 	  break;
-	case CONST_INT:
-	  op = GEN_INT (INTVAL (op) >> 16);
-	  letter = 0;
+	case 'e':
+	  mem_off = 3;
+	  const_shift = 24;
 	  break;
-	default:
-	  /* If you get here, figure out a test case :-) */
-	  gcc_unreachable ();
-	}
-      break;
-    case 'C':
-      switch (GET_CODE (op))
-	{
-	case MEM:
-	  op = adjust_address (op, Pmode,
-			       (GET_CODE (XEXP (op, 0)) == POST_INC) ? 0 : 4);
+	case 'C':
+	  mem_off = 4;
+	  reg_off = 2;
+	  const_shift = 32;
 	  break;
-	case REG:
-	  op = gen_rtx_REG (Pmode, REGNO (op) + 2);
+	case 'f':
+	  mem_off = 5;
+	  const_shift = 40;
 	  break;
-	case CONST_INT:
-	  op = GEN_INT ((long long) INTVAL (op) >> 32);
-	  letter = 0;
+	case 'D':
+	  mem_off = 6;
+	  reg_off = 3;
+	  const_shift = 48;
+	  break;
+	case 'g':
+	  mem_off = 7;
+	  const_shift = 56;
 	  break;
 	default:
-	  /* If you get here, figure out a test case :-) */
 	  gcc_unreachable ();
+	  break;
 	}
-      break;
-    case 'D':
+      /* fallthru */
+    case 'A': case 'L': /* Low half.  */
       switch (GET_CODE (op))
 	{
 	case MEM:
+	  /* We don't need to adjust the address for post_inc.  */
 	  op = adjust_address (op, Pmode,
-			       (GET_CODE (XEXP (op, 0)) == POST_INC) ? 0 : 6);
+			       (GET_CODE (XEXP (op, 0)) == POST_INC)
+			       ? 0 : mem_off);
 	  break;
 	case REG:
-	  op = gen_rtx_REG (Pmode, REGNO (op) + 3);
+	  op = gen_rtx_REG (Pmode, REGNO (op) + reg_off);
 	  break;
 	case CONST_INT:
-	  op = GEN_INT ((long long) INTVAL (op) >> 48);
+	  op = GEN_INT (((long long) INTVAL (op) >> const_shift) & 0xffff);
 	  letter = 0;
 	  break;
 	default:
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 3b37aba5795..5571c4f2ff2 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -10737,6 +10737,42 @@  for the compiler to know that @code{fyl2xp1} pops both inputs.
 asm ("fyl2xp1" : "=t" (result) : "0" (x), "u" (y) : "st(1)");
 @end smallexample
 
+@anchor{msp430Operandmodifiers}
+@subsubsection MSP430 Operand Modifiers
+
+The list below describes the supported modifiers and their effects for MSP430.
+
+@multitable @columnfractions .10 .90
+@headitem Modifier @tab Description
+@item @code{A} @tab Select low 16-bits of the constant/register/memory operand.
+@item @code{B} @tab Select high 16-bits of the constant/register/memory
+operand.
+@item @code{C} @tab Select bits 32-47 of the constant/register/memory operand.
+@item @code{D} @tab Select bits 48-63 of the constant/register/memory operand.
+@item @code{H} @tab Equivalent to @code{B} (for backwards compatibility).
+@item @code{I} @tab Print the inverse (logical @code{NOT}) of the constant
+value.
+@item @code{J} @tab Print an integer without a @code{#} prefix.
+@item @code{L} @tab Equivalent to @code{A} (for backwards compatibility).
+@item @code{O} @tab Offset of the current frame from the top of the stack.
+@item @code{Q} @tab Use the @code{A} instruction postfix.
+@item @code{R} @tab Inverse of condition code, for unsigned comparisons.
+@item @code{W} @tab Subtract 16 from the constant value.
+@item @code{X} @tab Use the @code{X} instruction postfix.
+@item @code{Y} @tab Subtract 4 from the constant value.
+@item @code{Z} @tab Subtract 1 from the constant value.
+@item @code{b} @tab Append @code{.B}, @code{.W} or @code{.A} to the
+instruction, depending on the mode.
+@item @code{d} @tab Offset 1 byte of a memory reference or constant value.
+@item @code{e} @tab Offset 3 bytes of a memory reference or constant value.
+@item @code{f} @tab Offset 5 bytes of a memory reference or constant value.
+@item @code{g} @tab Offset 7 bytes of a memory reference or constant value.
+@item @code{p} @tab Print the value of 2, raised to the power of the given
+constant.  Used to select the specified bit position.
+@item @code{r} @tab Inverse of condition code, for signed comparisons.
+@item @code{x} @tab Equivialent to @code{X}, but only for pointers.
+@end multitable
+
 @lowersections
 @include md.texi
 @raisesections
diff --git a/gcc/testsuite/gcc.target/msp430/operand-modifiers-bad.c b/gcc/testsuite/gcc.target/msp430/operand-modifiers-bad.c
new file mode 100644
index 00000000000..3ff47931329
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/operand-modifiers-bad.c
@@ -0,0 +1,15 @@ 
+/* { dg-do compile } */
+
+void
+foo (void)
+{
+  char reg = 10;
+  __asm__ ("mov.b %d1, %0\n" : "=r" (reg) : "r" (reg));
+  /* { dg-error "invalid 'asm': %d, %e, %f, %g operand modifiers are for memory references or constant values only" "" { target *-*-* } .-1 } */
+  __asm__ ("mov.b %e1, %0\n" : "=r" (reg) : "r" (reg));
+  /* { dg-error "invalid 'asm': %d, %e, %f, %g operand modifiers are for memory references or constant values only" "" { target *-*-* } .-1 } */
+  __asm__ ("mov.b %f1, %0\n" : "=r" (reg) : "r" (reg));
+  /* { dg-error "invalid 'asm': %d, %e, %f, %g operand modifiers are for memory references or constant values only" "" { target *-*-* } .-1 } */
+  __asm__ ("mov.b %g1, %0\n" : "=r" (reg) : "r" (reg));
+  /* { dg-error "invalid 'asm': %d, %e, %f, %g operand modifiers are for memory references or constant values only" "" { target *-*-* } .-1 } */
+}
diff --git a/gcc/testsuite/gcc.target/msp430/operand-modifiers.c b/gcc/testsuite/gcc.target/msp430/operand-modifiers.c
index ad0a5310839..76e453df2c9 100644
--- a/gcc/testsuite/gcc.target/msp430/operand-modifiers.c
+++ b/gcc/testsuite/gcc.target/msp430/operand-modifiers.c
@@ -1,30 +1,155 @@ 
-volatile unsigned long si = 0x89abcdef;
-volatile unsigned long long di = 0xfedcba9876543210;
+/* { dg-do run } */
 
-unsigned int a, b, c, d;
+#include <stdio.h>
+
+/* Test A/L, B/H, C, D, d, e, f, g operand modifiers on 32-bit, 64-bit and,
+   where appropriate, 16-bit values.  */
+
+#define MEM16_VAL 0x2345
+#define MEM32_VAL 0x89abcdef
+#define MEM64_VAL 0xfedcba9876543210
+
+#define CONST16_VAL 0xbcde
+#define CONST32_VAL 0x99aabbcc
+#define CONST64_VAL 0x8899aabbccddeeff
+
+#define REG32_VAL 0x12345678
+#define REG64_VAL 0x123456789abcdef
+
+volatile unsigned long mem16 = MEM16_VAL;
+volatile unsigned long mem32 = MEM32_VAL;
+volatile unsigned long long mem64 = MEM64_VAL;
+
+unsigned int word0, word1, word2, word3;
+unsigned char byte0, byte1, byte2, byte3, byte4, byte5, byte6, byte7;
+
+#define CHECK_BYTES_IN_16BIT_VAL(VAL)		\
+  if (byte0 != ((unsigned char)VAL)			\
+      || byte1 != ((unsigned char)(VAL >> 8)))	\
+    return 1;
+
+#define CHECK_WORDS_IN_32BIT_VAL(VAL)		\
+  if (word0 != ((unsigned)VAL)			\
+      || word1 != ((unsigned)(VAL >> 16)))	\
+    return 1;
+
+#define CHECK_WORDS_IN_64BIT_VAL(VAL)		\
+  if (word0 != ((unsigned)VAL)		\
+      || word1 != ((unsigned)(VAL >> 16))	\
+      || word2 != ((unsigned)(VAL >> 32))	\
+      || word3 != ((unsigned)(VAL >> 48)))	\
+    return 1;
+
+#define CHECK_BYTES_IN_32BIT_VAL(VAL)		\
+  if (byte0 != ((unsigned char)VAL)		\
+      || byte1 != ((unsigned char)(VAL >> 8))	\
+      || byte2 != ((unsigned char)(VAL >> 16))	\
+      || byte3 != ((unsigned char)(VAL >> 24)))	\
+    return 1;
+
+#define CHECK_BYTES_IN_64BIT_VAL(VAL)		\
+  if (byte0 != ((unsigned char)VAL)		\
+      || byte1 != ((unsigned char)(VAL >> 8))	\
+      || byte2 != ((unsigned char)(VAL >> 16))	\
+      || byte3 != ((unsigned char)(VAL >> 24))	\
+      || byte4 != ((unsigned char)(VAL >> 32))	\
+      || byte5 != ((unsigned char)(VAL >> 40))	\
+      || byte6 != ((unsigned char)(VAL >> 48))	\
+      || byte7 != ((unsigned char)(VAL >> 56)))	\
+    return 1;
 
 int
 main (void)
 {
-  /* Check that %A and %B extract the low and high words of a 32-bit value,
-     respectively.  */
-  __asm__("mov %A1, %0\n" : "=m" (a) : "m" (si));
-  __asm__("mov %B1, %0\n" : "=m" (b) : "m" (si));
-  if (a != ((unsigned)si)
-      || b != ((unsigned)(si >> 16)))
-    return 1;
+  unsigned long register reg32 = REG32_VAL;
+  unsigned long long register reg64 = REG64_VAL;
 
-  /* Check that %A, %B, %C and %D extract the 1st, 2nd, 3rd and 4th words of a
-     64-bit value, respectively.  */
-  __asm__("mov %A1, %0\n" : "=m" (a) : "m" (di));
-  __asm__("mov %B1, %0\n" : "=m" (b) : "m" (di));
-  __asm__("mov %C1, %0\n" : "=m" (c) : "m" (di));
-  __asm__("mov %D1, %0\n" : "=m" (d) : "m" (di));
-  if (a != ((unsigned)di)
-      || b != ((unsigned)(di >> 16))
-      || c != ((unsigned)(di >> 32))
-      || d != ((unsigned)(di >> 48)))
-    return 1;
+  /* *** MEMORY OPERAND TESTS *** */
+  /* Test byte extraction of a 16-bit value.  */
+  __asm__("mov.b %A1, %0\n" : "=m" (byte0) : "m" (mem16));
+  __asm__("mov.b %d1, %0\n" : "=m" (byte1) : "m" (mem16));
+  CHECK_BYTES_IN_16BIT_VAL (MEM16_VAL);
+
+  /* Test extraction of high and low words from 32-bit value.  */
+  __asm__("mov %A1, %0\n" : "=m" (word0) : "m" (mem32));
+  __asm__("mov %B1, %0\n" : "=m" (word1) : "m" (mem32));
+  CHECK_WORDS_IN_32BIT_VAL (MEM32_VAL);
+
+  /* Test extraction of each word of a 64-bit value.  */
+  __asm__("mov %A1, %0\n" : "=m" (word0) : "m" (mem64));
+  __asm__("mov %B1, %0\n" : "=m" (word1) : "m" (mem64));
+  __asm__("mov %C1, %0\n" : "=m" (word2) : "m" (mem64));
+  __asm__("mov %D1, %0\n" : "=m" (word3) : "m" (mem64));
+  CHECK_WORDS_IN_64BIT_VAL (MEM64_VAL);
+
+  /* Test extraction of each byte of a 32-bit value.  */
+  __asm__("mov.b %A1, %0\n" : "=m" (byte0) : "m" (mem32));
+  __asm__("mov.b %d1, %0\n" : "=m" (byte1) : "m" (mem32));
+  __asm__("mov.b %B1, %0\n" : "=m" (byte2) : "m" (mem32));
+  __asm__("mov.b %e1, %0\n" : "=m" (byte3) : "m" (mem32));
+  CHECK_BYTES_IN_32BIT_VAL (MEM32_VAL);
+
+  /* Test extraction of each byte of a 64-bit value.  */
+  __asm__("mov.b %A1, %0\n" : "=m" (byte0) : "m" (mem64));
+  __asm__("mov.b %d1, %0\n" : "=m" (byte1) : "m" (mem64));
+  __asm__("mov.b %B1, %0\n" : "=m" (byte2) : "m" (mem64));
+  __asm__("mov.b %e1, %0\n" : "=m" (byte3) : "m" (mem64));
+  __asm__("mov.b %C1, %0\n" : "=m" (byte4) : "m" (mem64));
+  __asm__("mov.b %f1, %0\n" : "=m" (byte5) : "m" (mem64));
+  __asm__("mov.b %D1, %0\n" : "=m" (byte6) : "m" (mem64));
+  __asm__("mov.b %g1, %0\n" : "=m" (byte7) : "m" (mem64));
+  CHECK_BYTES_IN_64BIT_VAL (MEM64_VAL);
+
+  /* *** IMMEDIATE OPERAND TESTS *** */
+  /* Test byte extraction of a 16-bit value.  */
+  __asm__("mov.b %A1, %0\n" : "=m" (byte0) : "i" (CONST16_VAL));
+  __asm__("mov.b %d1, %0\n" : "=m" (byte1) : "i" (CONST16_VAL));
+  CHECK_BYTES_IN_16BIT_VAL (CONST16_VAL);
+
+  /* Test extraction of high and low words from 32-bit value.  */
+  __asm__("mov %A1, %0\n" : "=m" (word0) : "i" (CONST32_VAL));
+  __asm__("mov %B1, %0\n" : "=m" (word1) : "i" (CONST32_VAL));
+  CHECK_WORDS_IN_32BIT_VAL (CONST32_VAL);
+
+  /* Test extraction of each word of a 64-bit value.  */
+  __asm__("mov %A1, %0\n" : "=m" (word0) : "i" (CONST64_VAL));
+  __asm__("mov %B1, %0\n" : "=m" (word1) : "i" (CONST64_VAL));
+  __asm__("mov %C1, %0\n" : "=m" (word2) : "i" (CONST64_VAL));
+  __asm__("mov %D1, %0\n" : "=m" (word3) : "i" (CONST64_VAL));
+  CHECK_WORDS_IN_64BIT_VAL (CONST64_VAL);
+
+  /* Test extraction of each byte of a 32-bit value.  */
+  __asm__("mov.b %A1, %0\n" : "=m" (byte0) : "i" (CONST32_VAL));
+  __asm__("mov.b %d1, %0\n" : "=m" (byte1) : "i" (CONST32_VAL));
+  __asm__("mov.b %B1, %0\n" : "=m" (byte2) : "i" (CONST32_VAL));
+  __asm__("mov.b %e1, %0\n" : "=m" (byte3) : "i" (CONST32_VAL));
+  CHECK_BYTES_IN_32BIT_VAL (CONST32_VAL);
+
+  /* Test extraction of each byte of a 64-bit value.  */
+  __asm__("mov.b %A1, %0\n" : "=m" (byte0) : "i" (CONST64_VAL));
+  __asm__("mov.b %d1, %0\n" : "=m" (byte1) : "i" (CONST64_VAL));
+  __asm__("mov.b %B1, %0\n" : "=m" (byte2) : "i" (CONST64_VAL));
+  __asm__("mov.b %e1, %0\n" : "=m" (byte3) : "i" (CONST64_VAL));
+  __asm__("mov.b %C1, %0\n" : "=m" (byte4) : "i" (CONST64_VAL));
+  __asm__("mov.b %f1, %0\n" : "=m" (byte5) : "i" (CONST64_VAL));
+  __asm__("mov.b %D1, %0\n" : "=m" (byte6) : "i" (CONST64_VAL));
+  __asm__("mov.b %g1, %0\n" : "=m" (byte7) : "i" (CONST64_VAL));
+  CHECK_BYTES_IN_64BIT_VAL (CONST64_VAL);
+
+  /* *** REGISTER OPERAND TESTS *** */
+  /* No extraction of bytes from a single register.  */
+
+  /* Test extraction of high and low words from 32-bit value.  */
+  __asm__("mov %A1, %0\n" : "=m" (word0) : "r" (reg32));
+  __asm__("mov %B1, %0\n" : "=m" (word1) : "r" (reg32));
+  CHECK_WORDS_IN_32BIT_VAL (REG32_VAL);
+
+  /* Test extraction of each word of a 64-bit value.  */
+  __asm__("mov %A1, %0\n" : "=m" (word0) : "r" (reg64));
+  __asm__("mov %B1, %0\n" : "=m" (word1) : "r" (reg64));
+  __asm__("mov %C1, %0\n" : "=m" (word2) : "r" (reg64));
+  __asm__("mov %D1, %0\n" : "=m" (word3) : "r" (reg64));
+  CHECK_WORDS_IN_64BIT_VAL (REG64_VAL);
 
   return 0;
 }