From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com [IPv6:2a00:1450:4864:20::32c]) by sourceware.org (Postfix) with ESMTPS id 81ED33857806 for ; Thu, 10 Sep 2020 09:45:00 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 81ED33857806 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=mittosystems.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=jozef.l@mittosystems.com Received: by mail-wm1-x32c.google.com with SMTP id e11so1493755wme.0 for ; Thu, 10 Sep 2020 02:45:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mittosystems.com; s=google; h=date:from:to:subject:message-id:mail-followup-to:mime-version :content-disposition; bh=mZkJfmpB0YoDfdv9cYFVMpQF5BaO1uTqe7yIVANb6gs=; b=U6Md5yJqBe6df6WGxklmVqm5EpSzER+NooN/mfaimAJGUaDmE6GRilAZ3iGmYH4iHs tocKDQNy7UBVKcG5XqqijskxYWmLYeNyLw1rYbFixY8ni4GQuFcVceHr2Gzke1xk3U3j QbkCWpOIHHXD/XD7B0FdrcYaYHGeEuIUz2TqZgjcdV5s5/79b5DjA7WQHd2PaZ+NBWoo UpwRokdgpwJqqDKjuwjBSQUAW9ojR816lCjEqRCFULJBo3HeNrTOEVb3grSuOW4t5ZLu Mq2jzi3Jzmp7vp1N+U1olm8vJLr33qdnKZ2GjwQesBcFxlmNI3aVs1/9KjdsgmsovytF 8xsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:subject:message-id:mail-followup-to :mime-version:content-disposition; bh=mZkJfmpB0YoDfdv9cYFVMpQF5BaO1uTqe7yIVANb6gs=; b=SshFOn/bG3p8fGY5yOoAph6hvxNmEUnRfQRBhoxTAef5XKDVUrq2AL7aN0SnCB1d4b nzCIc0oPFjJ+x+W7Ez5Pooqvg5UGzbvZS0n6naIVTMgkIXzsDikasl6ViTnRnWMDstjX d0unlENzgxO7wvws7R2rUYSoH+c0j0ZxaNm6jUJzg4Jpu6CKlgKI3jTtmKUmI0J5mU4L 18YfYTjLbcKTkoV//S2e1ApJHI5ZDvBxRlr2M7trRA8vO4ZyITY5CywbqP2v1Ngy9UNi DyTxHMUP05FD/b8MusOunqJE7EBhTq7xbAITSniVDicYtLMxzVt5r8/gcW4d9t/LgXC6 sZyA== X-Gm-Message-State: AOAM532HHEbY639TZFpBdGBe/KZaM9T6gnV1MKMa6EtWRMBn+Z65f8E1 RkGcg95cU/9fyqJUS3HMWW9fxKGiuEV1iw== X-Google-Smtp-Source: ABdhPJzN9rHMmFlB4L3of/GgmhGMu9egKf7uC3N8ZD1qxgtOvVa2rByiNlt9UqLKQ8gj+FTp0ahlrg== X-Received: by 2002:a1c:35c5:: with SMTP id c188mr5844338wma.11.1599731099293; Thu, 10 Sep 2020 02:44:59 -0700 (PDT) Received: from jozef-acer-manjaro ([2a01:4b00:87fd:900:5e1d:5c99:56da:76e8]) by smtp.gmail.com with ESMTPSA id r15sm2822372wmn.24.2020.09.10.02.44.58 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Sep 2020 02:44:58 -0700 (PDT) Date: Thu, 10 Sep 2020 10:44:57 +0100 From: Jozef Lawrynowicz To: gcc-patches@gcc.gnu.org Subject: [PATCH] MSP430: Add 'd', 'e', 'f' and 'g' asm operand modifiers Message-ID: <20200910094457.aold5r3hokd6x54p@jozef-acer-manjaro> Mail-Followup-To: gcc-patches@gcc.gnu.org MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="ka2jofwxtxs3yuwr" Content-Disposition: inline X-Spam-Status: No, score=-10.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 10 Sep 2020 09:45:07 -0000 --ka2jofwxtxs3yuwr Content-Type: text/plain; charset=us-ascii Content-Disposition: inline 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 --ka2jofwxtxs3yuwr Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="0001-MSP430-Add-d-e-f-and-g-asm-operand-modifiers.patch" >From c48ad2ae243a101afe8d021e847c56a482a60f20 Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz 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 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 + +/* 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; } -- 2.28.0 --ka2jofwxtxs3yuwr--