]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj, cmd/asm: reclassify the offset of memory access operations on loong64
authorXiaolin Zhao <zhaoxiaolin@loongson.cn>
Wed, 24 Sep 2025 09:21:40 +0000 (17:21 +0800)
committerabner chenc <chenguoqi@loongson.cn>
Tue, 28 Oct 2025 01:21:57 +0000 (18:21 -0700)
This CL also fixes the encoding error of LL/SC[V] instruction and
adds the handling of offset greater than 16 bits in MOV{W/V}P instructions.

Change-Id: I7a8fab4b68a6839da81c5e59af1f42289d00ef61
Reviewed-on: https://go-review.googlesource.com/c/go/+/706435
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Meidan Li <limeidan@loongson.cn>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: abner chenc <chenguoqi@loongson.cn>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
src/cmd/asm/internal/asm/endtoend_test.go
src/cmd/asm/internal/asm/testdata/loong64enc1.s
src/cmd/asm/internal/asm/testdata/loong64enc3.s
src/cmd/asm/internal/asm/testdata/loong64enc6.s [new file with mode: 0644]
src/cmd/asm/internal/asm/testdata/loong64error.s
src/cmd/internal/obj/loong64/a.out.go
src/cmd/internal/obj/loong64/asm.go

index afaf02815f94a28f097a873deae0c056b15efbb6..9571afc3260cb88a01073fcf2a597b6198d307af 100644 (file)
@@ -467,6 +467,7 @@ func TestLOONG64Encoder(t *testing.T) {
        testEndToEnd(t, "loong64", "loong64enc3")
        testEndToEnd(t, "loong64", "loong64enc4")
        testEndToEnd(t, "loong64", "loong64enc5")
+       testEndToEnd(t, "loong64", "loong64enc6")
        testEndToEnd(t, "loong64", "loong64")
 }
 
index fd86db7a4fc18415959dc952c78916742b00104b..6e2a86969d54cbf055753adbea3aff9e1d21c3f1 100644 (file)
@@ -93,8 +93,8 @@ lable2:
        MOVV    R4, 1(R5)               // a404c029
        MOVB    R4, 1(R5)               // a4040029
        MOVBU   R4, 1(R5)               // a4040029
-       SC      R4, 1(R5)               // a4040021
-       SCV     R4, 1(R5)               // a4040023
+       SC      R4, 4096(R5)            // a4001021
+       SCV     R4, 4096(R5)            // a4001023
        MOVW    y+8(FP), R4             // 64408028
        MOVWU   y+8(FP), R4             // 6440802a
        MOVV    y+8(FP), R4             // 6440c028
@@ -105,8 +105,8 @@ lable2:
        MOVV    1(R5), R4               // a404c028
        MOVB    1(R5), R4               // a4040028
        MOVBU   1(R5), R4               // a404002a
-       LL      1(R5), R4               // a4040020
-       LLV     1(R5), R4               // a4040022
+       LL      4096(R5), R4            // a4001020
+       LLV     4096(R5), R4            // a4001022
        MOVW    $4(R4), R5              // 8510c002
        MOVV    $4(R4), R5              // 8510c002
        MOVW    $-1, R4                 // 04fcff02
@@ -261,22 +261,18 @@ lable2:
        MOVV    R4, FCC0                // 80d81401
 
        // LDPTR.{W/D} and STPTR.{W/D} instructions
-       MOVWP   R5, -32768(R4)          // 85008025
        MOVWP   R5, 32764(R4)           // 85fc7f25
        MOVWP   R5, 32(R4)              // 85200025
        MOVWP   R5, 4(R4)               // 85040025
        MOVWP   R5, (R4)                // 85000025
-       MOVVP   R5, -32768(R4)          // 85008027
        MOVVP   R5, 32764(R4)           // 85fc7f27
        MOVVP   R5, 32(R4)              // 85200027
        MOVVP   R5, 4(R4)               // 85040027
        MOVVP   R5, (R4)                // 85000027
-       MOVWP   -32768(R5), R4          // a4008024
        MOVWP   32764(R5), R4           // a4fc7f24
        MOVWP   32(R5), R4              // a4200024
        MOVWP   4(R5), R4               // a4040024
        MOVWP   (R5), R4                // a4000024
-       MOVVP   -32768(R5), R4          // a4008026
        MOVVP   32764(R5), R4           // a4fc7f26
        MOVVP   32(R5), R4              // a4200026
        MOVVP   4(R5), R4               // a4040026
index 2d83bd719a584e903076805968a62945af1b0208..2dc6529dcb0131b8ae374f0b8368df7793f7a730 100644 (file)
@@ -42,8 +42,10 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
        MOVB    R4, 4096(R5)                    // 3e000014de971000c4030029
        MOVBU   R4, 65536(R5)                   // 1e020014de971000c4030029
        MOVBU   R4, 4096(R5)                    // 3e000014de971000c4030029
-       SC      R4, 65536(R5)                   // 1e020014de971000c4030021
-       SC      R4, 4096(R5)                    // 3e000014de971000c4030021
+       SC      R4, 65536(R5)                   // 1e040010de971000c4030021
+       SCV     R4, 65536(R5)                   // 1e040010de971000c4030023
+       LL      65536(R5), R4                   // 1e040010de971000c4030020
+       LLV     65536(R5), R4                   // 1e040010de971000c4030022
        MOVW    y+65540(FP), R4                 // 1e020014de8f1000c4338028
        MOVWU   y+65540(FP), R4                 // 1e020014de8f1000c433802a
        MOVV    y+65540(FP), R4                 // 1e020014de8f1000c433c028
@@ -122,6 +124,21 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
        XOR     $4097, R4                       // 3e000014de07800384f81500
        XOR     $4097, R4, R5                   // 3e000014de07800385f81500
 
+       MOVWP   R5, -32768(R4)                  // 1efcff13de931000c5038025
+       MOVWP   R5, 32768(R4)                   // 1e000010de931000c5038025
+       MOVWP   R5, 65536(R4)                   // 1e040010de931000c5030025
+       MOVWP   R5, 1048576(R4)                 // 1e400010de931000c5030025
+       MOVVP   R5, -32768(R4)                  // 1efcff13de931000c5038027
+       MOVVP   R5, 65536(R4)                   // 1e040010de931000c5030027
+       MOVVP   R5, 1048576(R4)                 // 1e400010de931000c5030027
+       MOVWP   -32768(R5), R4                  // 1efcff13de971000c4038024
+       MOVWP   2229248(R5), R4                 // 1e880010de971000c4030424
+       MOVWP   -2145518592(R5), R4             // 1e740012de971000c403fc24
+       MOVVP   -32768(R5), R4                  // 1efcff13de971000c4038026
+       MOVVP   2229248(R5), R4                 // 1e880010de971000c4030426
+       MOVVP   -2145518592(R5), R4             // 1e740012de971000c403fc26
+
+
        // MOVV C_DCON32_12S, r
        MOVV    $0x27312345fffff800, R4         // MOVV $2824077224892692480, R4        // 0400a002a468241684cc0903
        MOVV    $0xf7312345fffff800, R4         // MOVV $-634687288927848448, R4        // 0400a002a468241684cc3d03
diff --git a/src/cmd/asm/internal/asm/testdata/loong64enc6.s b/src/cmd/asm/internal/asm/testdata/loong64enc6.s
new file mode 100644 (file)
index 0000000..bd19ea7
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "../../../../../runtime/textflag.h"
+
+TEXT asmtest(SB),DUPOK|NOSPLIT,$0
+       // MOVWP LOREG_64(Rx), Ry
+       MOVWP   81985529216486896(R4), R5       // 9e571315dec3b703feac6816de4b000384f8100085000025
+       MOVWP   -81985529216486896(R4), R5      // 7ea8ec14de4388031e539717deb73f0384f8100085000025
+       MOVWP   R4, 81985529216486896(R5)       // 9e571315dec3b703feac6816de4b0003a5f81000a4000025
+       MOVWP   R4, -81985529216486896(R5)      // 7ea8ec14de4388031e539717deb73f03a5f81000a4000025
index 2dcd34bf61c676abf1660c62f8fb74c2e089a516..1bc0ddea5571928b661cd4f6cc89f19b1add0ea9 100644 (file)
@@ -7,3 +7,8 @@ TEXT errors(SB),$0
        XVSHUF4IV       $16, X1, X2     // ERROR "operand out of range 0 to 15"
        ADDV16          $1, R4, R5      // ERROR "the constant must be a multiple of 65536."
        ADDV16          $65535, R4, R5  // ERROR "the constant must be a multiple of 65536."
+       SC              R4, 1(R5)       // ERROR "offset must be a multiple of 4."
+       SCV             R4, 1(R5)       // ERROR "offset must be a multiple of 4."
+       LL              1(R5), R4       // ERROR "offset must be a multiple of 4."
+       LLV             1(R5), R4       // ERROR "offset must be a multiple of 4."
+
index 3cdbeb12a37395cbf16231d1052b445a3d79bc07..3a676db922ca71ea38a5e362043a7916232cd0bd 100644 (file)
@@ -249,7 +249,13 @@ func init() {
 }
 
 const (
-       BIG = 2046
+       BIG_8  = 128 - 2 // FIXME (not sure if -2 is appropriate)
+       BIG_9  = 256 - 2
+       BIG_10 = 512 - 2
+       BIG_11 = 1024 - 2
+       BIG_12 = 2046
+       BIG_16 = 32768 - 2
+       BIG_32 = 2147483648 - 2
 )
 
 const (
@@ -397,10 +403,16 @@ const (
        C_BRAN
        C_SAUTO
        C_LAUTO
-       C_ZOREG
-       C_SOREG
-       C_LOREG
-       C_ROFF // register offset
+       C_ZOREG    // An $0+reg memory op
+       C_SOREG_8  // An $n+reg memory arg where n is a 8 bit signed offset
+       C_SOREG_9  // An $n+reg memory arg where n is a 9 bit signed offset
+       C_SOREG_10 // An $n+reg memory arg where n is a 10 bit signed offset
+       C_SOREG_11 // An $n+reg memory arg where n is a 11 bit signed offset
+       C_SOREG_12 // An $n+reg memory arg where n is a 12 bit signed offset
+       C_SOREG_16 // An $n+reg memory arg where n is a 16 bit signed offset
+       C_LOREG_32 // An $n+reg memory arg where n is a 32 bit signed offset
+       C_LOREG_64 // An $n+reg memory arg where n is a 64 bit signed offset
+       C_ROFF     // register offset
        C_ADDR
        C_TLS_LE
        C_TLS_IE
index 5a61acac8741d633804f160ea86705519de03078..7eb5668d82e2316c4864d5b0f955b11706377623 100644 (file)
@@ -162,46 +162,41 @@ var optab = []Optab{
        {AMOVV, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
        {AMOVB, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
        {AMOVBU, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
-       {AMOVW, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
-       {AMOVWU, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
-       {AMOVV, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
-       {AMOVB, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
-       {AMOVBU, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
-       {AVMOVQ, C_VREG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
-       {AXVMOVQ, C_XREG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
+       {AMOVW, C_REG, C_NONE, C_NONE, C_SOREG_12, C_NONE, 7, 4, REGZERO, 0},
+       {AMOVWU, C_REG, C_NONE, C_NONE, C_SOREG_12, C_NONE, 7, 4, REGZERO, 0},
+       {AMOVV, C_REG, C_NONE, C_NONE, C_SOREG_12, C_NONE, 7, 4, REGZERO, 0},
+       {AMOVB, C_REG, C_NONE, C_NONE, C_SOREG_12, C_NONE, 7, 4, REGZERO, 0},
+       {AMOVBU, C_REG, C_NONE, C_NONE, C_SOREG_12, C_NONE, 7, 4, REGZERO, 0},
+       {AVMOVQ, C_VREG, C_NONE, C_NONE, C_SOREG_12, C_NONE, 7, 4, REGZERO, 0},
+       {AXVMOVQ, C_XREG, C_NONE, C_NONE, C_SOREG_12, C_NONE, 7, 4, REGZERO, 0},
        {AVMOVQ, C_VREG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGZERO, 0},
        {AXVMOVQ, C_XREG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGZERO, 0},
-       {ASC, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
-       {ASCV, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
 
        {AMOVW, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
        {AMOVWU, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
        {AMOVV, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
        {AMOVB, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
        {AMOVBU, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
-       {AMOVW, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
-       {AMOVWU, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
-       {AMOVV, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
-       {AMOVB, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
-       {AMOVBU, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
-       {AVMOVQ, C_SOREG, C_NONE, C_NONE, C_VREG, C_NONE, 8, 4, REGZERO, 0},
-       {AXVMOVQ, C_SOREG, C_NONE, C_NONE, C_XREG, C_NONE, 8, 4, REGZERO, 0},
+       {AMOVW, C_SOREG_12, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
+       {AMOVWU, C_SOREG_12, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
+       {AMOVV, C_SOREG_12, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
+       {AMOVB, C_SOREG_12, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
+       {AMOVBU, C_SOREG_12, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
+       {AVMOVQ, C_SOREG_12, C_NONE, C_NONE, C_VREG, C_NONE, 8, 4, REGZERO, 0},
+       {AXVMOVQ, C_SOREG_12, C_NONE, C_NONE, C_XREG, C_NONE, 8, 4, REGZERO, 0},
        {AVMOVQ, C_SAUTO, C_NONE, C_NONE, C_VREG, C_NONE, 8, 4, REGZERO, 0},
        {AXVMOVQ, C_SAUTO, C_NONE, C_NONE, C_XREG, C_NONE, 8, 4, REGZERO, 0},
-       {ALL, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
-       {ALLV, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
 
        {AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, C_NONE, 35, 12, REGSP, 0},
        {AMOVWU, C_REG, C_NONE, C_NONE, C_LAUTO, C_NONE, 35, 12, REGSP, 0},
        {AMOVV, C_REG, C_NONE, C_NONE, C_LAUTO, C_NONE, 35, 12, REGSP, 0},
        {AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, C_NONE, 35, 12, REGSP, 0},
        {AMOVBU, C_REG, C_NONE, C_NONE, C_LAUTO, C_NONE, 35, 12, REGSP, 0},
-       {AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 35, 12, REGZERO, 0},
-       {AMOVWU, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 35, 12, REGZERO, 0},
-       {AMOVV, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 35, 12, REGZERO, 0},
-       {AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 35, 12, REGZERO, 0},
-       {AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 35, 12, REGZERO, 0},
-       {ASC, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 35, 12, REGZERO, 0},
+       {AMOVW, C_REG, C_NONE, C_NONE, C_LOREG_32, C_NONE, 35, 12, REGZERO, 0},
+       {AMOVWU, C_REG, C_NONE, C_NONE, C_LOREG_32, C_NONE, 35, 12, REGZERO, 0},
+       {AMOVV, C_REG, C_NONE, C_NONE, C_LOREG_32, C_NONE, 35, 12, REGZERO, 0},
+       {AMOVB, C_REG, C_NONE, C_NONE, C_LOREG_32, C_NONE, 35, 12, REGZERO, 0},
+       {AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG_32, C_NONE, 35, 12, REGZERO, 0},
        {AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
        {AMOVWU, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
        {AMOVV, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
@@ -212,19 +207,20 @@ var optab = []Optab{
        {AMOVV, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
        {AMOVB, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
        {AMOVBU, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
-       {AMOVWP, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 73, 4, 0, 0},
-       {AMOVWP, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 73, 4, 0, 0},
+       {AMOVWP, C_REG, C_NONE, C_NONE, C_SOREG_16, C_NONE, 73, 4, 0, 0},
+       {AMOVWP, C_REG, C_NONE, C_NONE, C_LOREG_32, C_NONE, 73, 12, 0, 0},
+       {AMOVWP, C_REG, C_NONE, C_NONE, C_LOREG_64, C_NONE, 73, 24, 0, 0},
 
        {AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
        {AMOVWU, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
        {AMOVV, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
        {AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
        {AMOVBU, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
-       {AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
-       {AMOVWU, C_LOREG, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
-       {AMOVV, C_LOREG, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
-       {AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
-       {AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
+       {AMOVW, C_LOREG_32, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
+       {AMOVWU, C_LOREG_32, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
+       {AMOVV, C_LOREG_32, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
+       {AMOVB, C_LOREG_32, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
+       {AMOVBU, C_LOREG_32, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
        {AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
        {AMOVWU, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
        {AMOVV, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
@@ -235,8 +231,9 @@ var optab = []Optab{
        {AMOVV, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
        {AMOVB, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
        {AMOVBU, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
-       {AMOVWP, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 74, 4, 0, 0},
-       {AMOVWP, C_LOREG, C_NONE, C_NONE, C_REG, C_NONE, 74, 4, 0, 0},
+       {AMOVWP, C_SOREG_16, C_NONE, C_NONE, C_REG, C_NONE, 74, 4, 0, 0},
+       {AMOVWP, C_LOREG_32, C_NONE, C_NONE, C_REG, C_NONE, 74, 12, 0, 0},
+       {AMOVWP, C_LOREG_64, C_NONE, C_NONE, C_REG, C_NONE, 74, 24, 0, 0},
 
        {AMOVW, C_SACON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGSP, 0},
        {AMOVV, C_SACON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGSP, 0},
@@ -333,25 +330,25 @@ var optab = []Optab{
 
        {AMOVF, C_SAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 28, 4, REGSP, 0},
        {AMOVD, C_SAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 28, 4, REGSP, 0},
-       {AMOVF, C_SOREG, C_NONE, C_NONE, C_FREG, C_NONE, 28, 4, REGZERO, 0},
-       {AMOVD, C_SOREG, C_NONE, C_NONE, C_FREG, C_NONE, 28, 4, REGZERO, 0},
+       {AMOVF, C_SOREG_12, C_NONE, C_NONE, C_FREG, C_NONE, 28, 4, REGZERO, 0},
+       {AMOVD, C_SOREG_12, C_NONE, C_NONE, C_FREG, C_NONE, 28, 4, REGZERO, 0},
 
        {AMOVF, C_LAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 28, 12, REGSP, 0},
        {AMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 28, 12, REGSP, 0},
-       {AMOVF, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 28, 12, REGZERO, 0},
-       {AMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 28, 12, REGZERO, 0},
+       {AMOVF, C_LOREG_32, C_NONE, C_NONE, C_FREG, C_NONE, 28, 12, REGZERO, 0},
+       {AMOVD, C_LOREG_32, C_NONE, C_NONE, C_FREG, C_NONE, 28, 12, REGZERO, 0},
        {AMOVF, C_ADDR, C_NONE, C_NONE, C_FREG, C_NONE, 51, 8, 0, 0},
        {AMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, C_NONE, 51, 8, 0, 0},
 
        {AMOVF, C_FREG, C_NONE, C_NONE, C_SAUTO, C_NONE, 29, 4, REGSP, 0},
        {AMOVD, C_FREG, C_NONE, C_NONE, C_SAUTO, C_NONE, 29, 4, REGSP, 0},
-       {AMOVF, C_FREG, C_NONE, C_NONE, C_SOREG, C_NONE, 29, 4, REGZERO, 0},
-       {AMOVD, C_FREG, C_NONE, C_NONE, C_SOREG, C_NONE, 29, 4, REGZERO, 0},
+       {AMOVF, C_FREG, C_NONE, C_NONE, C_SOREG_12, C_NONE, 29, 4, REGZERO, 0},
+       {AMOVD, C_FREG, C_NONE, C_NONE, C_SOREG_12, C_NONE, 29, 4, REGZERO, 0},
 
        {AMOVF, C_FREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 29, 12, REGSP, 0},
        {AMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 29, 12, REGSP, 0},
-       {AMOVF, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 29, 12, REGZERO, 0},
-       {AMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 29, 12, REGZERO, 0},
+       {AMOVF, C_FREG, C_NONE, C_NONE, C_LOREG_32, C_NONE, 29, 12, REGZERO, 0},
+       {AMOVD, C_FREG, C_NONE, C_NONE, C_LOREG_32, C_NONE, 29, 12, REGZERO, 0},
        {AMOVF, C_FREG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
        {AMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
 
@@ -426,11 +423,11 @@ var optab = []Optab{
 
        {AVMOVQ, C_ELEM, C_NONE, C_NONE, C_ARNG, C_NONE, 45, 4, 0, 0},
 
-       {AVMOVQ, C_SOREG, C_NONE, C_NONE, C_ARNG, C_NONE, 46, 4, 0, 0},
-       {AXVMOVQ, C_SOREG, C_NONE, C_NONE, C_ARNG, C_NONE, 46, 4, 0, 0},
+       {AVMOVQ, C_SOREG_12, C_NONE, C_NONE, C_ARNG, C_NONE, 46, 4, 0, 0},
+       {AXVMOVQ, C_SOREG_12, C_NONE, C_NONE, C_ARNG, C_NONE, 46, 4, 0, 0},
 
-       {APRELD, C_SOREG, C_U5CON, C_NONE, C_NONE, C_NONE, 47, 4, 0, 0},
-       {APRELDX, C_SOREG, C_DCON, C_U5CON, C_NONE, C_NONE, 48, 20, 0, 0},
+       {APRELD, C_SOREG_12, C_U5CON, C_NONE, C_NONE, C_NONE, 47, 4, 0, 0},
+       {APRELDX, C_SOREG_16, C_DCON, C_U5CON, C_NONE, C_NONE, 48, 20, 0, 0},
 
        {AALSLV, C_U3CON, C_REG, C_REG, C_REG, C_NONE, 64, 4, 0, 0},
 
@@ -678,7 +675,7 @@ func span0(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
 
        bp := c.cursym.P
        var i int32
-       var out [5]uint32
+       var out [6]uint32
        for p := c.cursym.Func().Text.Link; p != nil; p = p.Link {
                c.pc = p.Pc
                o = c.oplook(p)
@@ -778,7 +775,7 @@ func (c *ctxt0) aclass(a *obj.Addr) int {
                                a.Reg = obj.REG_NONE
                        }
                        c.instoffset = int64(c.autosize) + a.Offset
-                       if c.instoffset >= -BIG && c.instoffset < BIG {
+                       if c.instoffset >= -BIG_12 && c.instoffset < BIG_12 {
                                return C_SAUTO
                        }
                        return C_LAUTO
@@ -790,7 +787,7 @@ func (c *ctxt0) aclass(a *obj.Addr) int {
                                a.Reg = obj.REG_NONE
                        }
                        c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.Arch.FixedFrameSize
-                       if c.instoffset >= -BIG && c.instoffset < BIG {
+                       if c.instoffset >= -BIG_12 && c.instoffset < BIG_12 {
                                return C_SAUTO
                        }
                        return C_LAUTO
@@ -808,10 +805,23 @@ func (c *ctxt0) aclass(a *obj.Addr) int {
                        if c.instoffset == 0 {
                                return C_ZOREG
                        }
-                       if c.instoffset >= -BIG && c.instoffset < BIG {
-                               return C_SOREG
+                       if c.instoffset >= -BIG_8 && c.instoffset < BIG_8 {
+                               return C_SOREG_8
+                       } else if c.instoffset >= -BIG_9 && c.instoffset < BIG_9 {
+                               return C_SOREG_9
+                       } else if c.instoffset >= -BIG_10 && c.instoffset < BIG_10 {
+                               return C_SOREG_10
+                       } else if c.instoffset >= -BIG_11 && c.instoffset < BIG_11 {
+                               return C_SOREG_11
+                       } else if c.instoffset >= -BIG_12 && c.instoffset < BIG_12 {
+                               return C_SOREG_12
+                       } else if c.instoffset >= -BIG_16 && c.instoffset < BIG_16 {
+                               return C_SOREG_16
+                       } else if c.instoffset >= -BIG_32 && c.instoffset < BIG_32 {
+                               return C_LOREG_32
+                       } else {
+                               return C_LOREG_64
                        }
-                       return C_LOREG
 
                case obj.NAME_GOTREF:
                        return C_GOTADDR
@@ -828,7 +838,7 @@ func (c *ctxt0) aclass(a *obj.Addr) int {
                case obj.NAME_NONE:
                        c.instoffset = a.Offset
                        if a.Reg != 0 {
-                               if -BIG <= c.instoffset && c.instoffset <= BIG {
+                               if -BIG_12 <= c.instoffset && c.instoffset <= BIG_12 {
                                        return C_SACON
                                }
                                if isint32(c.instoffset) {
@@ -857,7 +867,7 @@ func (c *ctxt0) aclass(a *obj.Addr) int {
                                a.Reg = obj.REG_NONE
                        }
                        c.instoffset = int64(c.autosize) + a.Offset
-                       if c.instoffset >= -BIG && c.instoffset < BIG {
+                       if c.instoffset >= -BIG_12 && c.instoffset < BIG_12 {
                                return C_SACON
                        }
                        return C_LACON
@@ -869,7 +879,7 @@ func (c *ctxt0) aclass(a *obj.Addr) int {
                                a.Reg = obj.REG_NONE
                        }
                        c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.Arch.FixedFrameSize
-                       if c.instoffset >= -BIG && c.instoffset < BIG {
+                       if c.instoffset >= -BIG_12 && c.instoffset < BIG_12 {
                                return C_SACON
                        }
                        return C_LACON
@@ -1271,10 +1281,33 @@ func cmp(a int, b int) bool {
        case C_REG:
                return b == C_ZCON
 
-       case C_LOREG:
-               return b == C_ZOREG || b == C_SOREG
+       case C_LOREG_64:
+               if b == C_ZOREG || b == C_SOREG_8 ||
+                       b == C_SOREG_9 || b == C_SOREG_10 ||
+                       b == C_SOREG_11 || b == C_SOREG_12 ||
+                       b == C_SOREG_16 || b == C_LOREG_32 {
+                       return true
+               }
+
+       case C_LOREG_32:
+               return cmp(C_SOREG_16, b)
+
+       case C_SOREG_16:
+               return cmp(C_SOREG_12, b)
+
+       case C_SOREG_12:
+               return cmp(C_SOREG_11, b)
+
+       case C_SOREG_11:
+               return cmp(C_SOREG_10, b)
+
+       case C_SOREG_10:
+               return cmp(C_SOREG_9, b)
 
-       case C_SOREG:
+       case C_SOREG_9:
+               return cmp(C_SOREG_8, b)
+
+       case C_SOREG_8:
                return b == C_ZOREG
        }
 
@@ -1453,6 +1486,10 @@ func buildop(ctxt *obj.Link) {
 
                case AMOVWP:
                        opset(AMOVVP, r0)
+                       opset(ASC, r0)
+                       opset(ASCV, r0)
+                       opset(ALL, r0)
+                       opset(ALLV, r0)
 
                case AMUL:
                        opset(AMULU, r0)
@@ -1522,10 +1559,6 @@ func buildop(ctxt *obj.Link) {
                        AMOVWU,
                        AVMOVQ,
                        AXVMOVQ,
-                       ALL,
-                       ALLV,
-                       ASC,
-                       ASCV,
                        ANEGW,
                        ANEGV,
                        AWORD,
@@ -2051,6 +2084,7 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
        o3 := uint32(0)
        o4 := uint32(0)
        o5 := uint32(0)
+       o6 := uint32(0)
 
        add := AADDU
        add = AADDVU
@@ -2955,18 +2989,51 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
                o4 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
 
        case 73:
-               v := c.regoff(&p.To)
+               v := c.vregoff(&p.To)
+               r := p.To.Reg
                if v&3 != 0 {
                        c.ctxt.Diag("%v: offset must be a multiple of 4.\n", p)
                }
-               o1 = OP_14IRR(c.opirr(p.As), uint32(v>>2), uint32(p.To.Reg), uint32(p.From.Reg))
+
+               switch o.size {
+               case 4: // 16 bit
+                       o1 = OP_14IRR(c.opirr(p.As), uint32(v>>2), uint32(r), uint32(p.From.Reg))
+               case 12: // 32 bit
+                       o1 = OP_16IRR(c.opirr(AADDV16), uint32(v>>16), uint32(REG_R0), uint32(REGTMP))
+                       o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
+                       o3 = OP_14IRR(c.opirr(p.As), uint32(v>>2), uint32(REGTMP), uint32(p.From.Reg))
+               case 24: // 64 bit
+                       o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
+                       o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
+                       o3 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(REGTMP))
+                       o4 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(REGTMP), uint32(REGTMP))
+                       o5 = OP_RRR(c.oprrr(add), uint32(REGTMP), uint32(r), uint32(r))
+                       o6 = OP_14IRR(c.opirr(p.As), uint32(0), uint32(r), uint32(p.From.Reg))
+               }
 
        case 74:
-               v := c.regoff(&p.From)
+               v := c.vregoff(&p.From)
+               r := p.From.Reg
                if v&3 != 0 {
                        c.ctxt.Diag("%v: offset must be a multiple of 4.\n", p)
                }
-               o1 = OP_14IRR(c.opirr(-p.As), uint32(v>>2), uint32(p.From.Reg), uint32(p.To.Reg))
+
+               switch o.size {
+               case 4: // 16 bit
+                       o1 = OP_14IRR(c.opirr(-p.As), uint32(v>>2), uint32(r), uint32(p.To.Reg))
+               case 12: // 32 bit
+                       o1 = OP_16IRR(c.opirr(AADDV16), uint32(v>>16), uint32(REG_R0), uint32(REGTMP))
+                       o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
+                       o3 = OP_14IRR(c.opirr(-p.As), uint32(v>>2), uint32(REGTMP), uint32(p.To.Reg))
+               case 24: // 64 bit
+                       o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
+                       o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
+                       o3 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(REGTMP))
+                       o4 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(REGTMP), uint32(REGTMP))
+                       o5 = OP_RRR(c.oprrr(add), uint32(REGTMP), uint32(r), uint32(r))
+                       o6 = OP_14IRR(c.opirr(p.As), uint32(0), uint32(r), uint32(p.To.Reg))
+               }
+
        }
 
        out[0] = o1
@@ -2974,6 +3041,7 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
        out[2] = o3
        out[3] = o4
        out[4] = o5
+       out[5] = o6
 }
 
 // checkoperand checks if operand >= 0 && operand <= maxoperand
@@ -4143,13 +4211,13 @@ func (c *ctxt0) opirr(a obj.As) uint32 {
        case AROTRV:
                return 0x004d << 16
        case -ALL:
-               return 0x020 << 24
+               return 0x020 << 24 // ll.w
        case -ALLV:
-               return 0x022 << 24
+               return 0x022 << 24 // ll.d
        case ASC:
-               return 0x021 << 24
+               return 0x021 << 24 // sc.w
        case ASCV:
-               return 0x023 << 24
+               return 0x023 << 24 // sc.d
        case AVANDB:
                return 0x1CF4 << 18 // vandi.b
        case AVORB: