#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)
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)
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:
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
-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;
}