]> Cypherpunks repositories - gostls13.git/commitdiff
cmd: fix the order that s390x operands are printed in
authorMichael Munday <munday@ca.ibm.com>
Tue, 11 Apr 2017 18:30:18 +0000 (14:30 -0400)
committerMichael Munday <munday@ca.ibm.com>
Tue, 25 Apr 2017 15:16:56 +0000 (15:16 +0000)
The assembler reordered the operands of some instructions to put the
first operand into From3. Unfortunately this meant that when the
instructions were printed the operands were in a different order than
the assembler would expect as input. For example, 'MVC $8, (R1), (R2)'
would be printed as 'MVC (R1), $8, (R2)'.

Originally this was done to ensure that From contained the source
memory operand. The current compiler no longer requires this and so
this CL simply makes all instructions use the standard order for
operands: From, Reg, From3 and finally To.

Fixes #18295

Change-Id: Ib2b5ec29c647ca7a995eb03dc78f82d99618b092
Reviewed-on: https://go-review.googlesource.com/40299
Run-TryBot: Michael Munday <munday@ca.ibm.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/asm/internal/arch/s390x.go
src/cmd/asm/internal/asm/asm.go
src/cmd/asm/internal/asm/testdata/s390x.s
src/cmd/compile/internal/s390x/ggen.go
src/cmd/compile/internal/s390x/ssa.go
src/cmd/internal/obj/s390x/asmz.go

index 115f7e06d8f8af028e0adcc98d6d3340cb052c2f..d6d46f86f2ab8956f08264abd862f650f9dbecb6 100644 (file)
@@ -68,38 +68,6 @@ func IsS390xNEG(op obj.As) bool {
        return false
 }
 
-// IsS390xWithLength reports whether the op (as defined by an s390x.A* constant)
-// refers to an instruction which takes a length as its first argument.
-func IsS390xWithLength(op obj.As) bool {
-       switch op {
-       case s390x.AMVC, s390x.ACLC, s390x.AXC, s390x.AOC, s390x.ANC:
-               return true
-       case s390x.AVLL, s390x.AVSTL:
-               return true
-       }
-       return false
-}
-
-// IsS390xWithIndex reports whether the op (as defined by an s390x.A* constant)
-// refers to an instruction which takes an index as its first argument.
-func IsS390xWithIndex(op obj.As) bool {
-       switch op {
-       case s390x.AVSCEG, s390x.AVSCEF, s390x.AVGEG, s390x.AVGEF:
-               return true
-       case s390x.AVGMG, s390x.AVGMF, s390x.AVGMH, s390x.AVGMB:
-               return true
-       case s390x.AVLEIG, s390x.AVLEIF, s390x.AVLEIH, s390x.AVLEIB:
-               return true
-       case s390x.AVLEG, s390x.AVLEF, s390x.AVLEH, s390x.AVLEB:
-               return true
-       case s390x.AVSTEG, s390x.AVSTEF, s390x.AVSTEH, s390x.AVSTEB:
-               return true
-       case s390x.AVPDI:
-               return true
-       }
-       return false
-}
-
 func s390xRegisterNumber(name string, n int16) (int16, bool) {
        switch name {
        case "AR":
index b0df24099783594c74dc1120a59260411b8ef3ac..fa32e76f330ee5f585553dc68efab028727c9d44 100644 (file)
@@ -623,12 +623,11 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
                                return
                        }
                case sys.S390X:
-                       if arch.IsS390xWithLength(op) || arch.IsS390xWithIndex(op) {
-                               prog.From = a[1]
-                               prog.From3 = newAddr(a[0])
-                       } else {
+                       prog.From = a[0]
+                       if a[1].Type == obj.TYPE_REG {
                                prog.Reg = p.getRegister(prog, op, &a[1])
-                               prog.From = a[0]
+                       } else {
+                               prog.From3 = newAddr(a[1])
                        }
                        prog.To = a[2]
                default:
@@ -711,9 +710,13 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
                        }
                }
                if p.arch.Family == sys.S390X {
-                       prog.From = a[1]
-                       prog.Reg = p.getRegister(prog, op, &a[2])
-                       prog.From3 = newAddr(a[0])
+                       if a[1].Type != obj.TYPE_REG {
+                               p.errorf("second operand must be a register in %s instruction", op)
+                               return
+                       }
+                       prog.From = a[0]
+                       prog.Reg = p.getRegister(prog, op, &a[1])
+                       prog.From3 = newAddr(a[2])
                        prog.To = a[3]
                        break
                }
index 0bc06f137fd9208ccf2261dd393205dc36a1e444..d8688e7ba6a594d0625ee5cfb1c1434e49ed521a 100644 (file)
@@ -186,13 +186,13 @@ TEXT main·foo(SB),DUPOK|NOSPLIT,$16-0 // TEXT main.foo(SB), DUPOK|NOSPLIT, $16-
        LAO     R1, R2, (R3)          // eb21300000f6
        LAOG    R4, R5, (R6)          // eb54600000e6
 
-       XC      $8, (R15), n-8(SP)       // XC  (R15), $8, n-8(SP)       // d707f010f000
-       NC      $8, (R15), n-8(SP)       // NC  (R15), $8, n-8(SP)       // d407f010f000
-       OC      $8, (R15), n-8(SP)       // OC  (R15), $8, n-8(SP)       // d607f010f000
-       MVC     $8, (R15), n-8(SP)       // MVC (R15), $8, n-8(SP)       // d207f010f000
-       CLC     $8, (R15), n-8(SP)       // CLC (R15), $8, n-8(SP)       // d507f000f010
-       XC      $256, -8(R15), -8(R15)   // XC  -8(R15), $256, -8(R15)   // b90400afc2a8fffffff8d7ffa000a000
-       MVC     $256, 8192(R1), 8192(R2) // MVC 8192(R1), $256, 8192(R2) // b90400a2c2a800002000b90400b1c2b800002000d2ffa000b000
+       XC      $8, (R15), n-8(SP)       // d707f010f000
+       NC      $8, (R15), n-8(SP)       // d407f010f000
+       OC      $8, (R15), n-8(SP)       // d607f010f000
+       MVC     $8, (R15), n-8(SP)       // d207f010f000
+       CLC     $8, (R15), n-8(SP)       // d507f000f010
+       XC      $256, -8(R15), -8(R15)   // b90400afc2a8fffffff8d7ffa000a000
+       MVC     $256, 8192(R1), 8192(R2) // b90400a2c2a800002000b90400b1c2b800002000d2ffa000b000
 
        CMP     R1, R2                 // b9200012
        CMP     R3, $32767             // a73f7fff
@@ -291,67 +291,64 @@ TEXT main·foo(SB),DUPOK|NOSPLIT,$16-0 // TEXT main.foo(SB), DUPOK|NOSPLIT, $16-
        FMSUB   F4, F5, F5             // b31f5045
        FMSUBS  F6, F6, F7             // b30f7066
 
-       VL      (R15), V1              // e710f0000006
-       VST     V1, (R15)              // e710f000000e
-       VL      (R15), V31             // e7f0f0000806
-       VST     V31, (R15)             // e7f0f000080e
-       VESLB   $5, V14                // e7ee00050030
-       VESRAG  $0, V15, V16           // e70f0000383a
-       VLM     (R15), V8, V23         // e787f0000436
-       VSTM    V8, V23, (R15)         // e787f000043e
-       VONE    V1                     // e710ffff0044
-       VZERO   V16                    // e70000000844
-       VGBM    $52428, V31            // e7f0cccc0844
-       VREPIB  $255, V4               // e74000ff0045
-       VREPIH  $-1, V16               // e700ffff1845
-       VREPIF  $-32768, V0            // e70080002045
-       VREPIG  $32767, V31            // e7f07fff3845
-       VREPG   $1, V4, V16            // e7040001384d
-       VREPB   $4, V31, V1            // e71f0004044d
-       VFTCIDB $4095, V1, V2          // e721fff0304a
-       WFTCIDB $3276, V15, V16        // e70fccc8384a
-       VPOPCT  V8, V19                // e73800000850
-       VFEEZBS V1, V2, V31            // e7f120300880
-       WFCHDBS V22, V23, V4           // e746701836eb
-       VMNH    V1, V2, V30            // e7e1200018fe
-       VO      V2, V1, V0             // e7021000006a
-       VERLLVF V2, V30, V27           // e7be20002c73
-       VSCBIB  V0, V23, V24           // e78700000cf5
-       VNOT    V16, V1                // e7101000046b
-       VCLZF   V16, V17               // e71000002c53
-       VLVGP   R3, R4, V8             // e78340000062
-
-       // Some vector instructions have their inputs reordered.
-       // Typically the reordering puts the length/index input into From3.
-       VGEG    $1, 8(R15)(V30*1), V31  // VGEG    8(R15)(V30*1), $1, V31  // e7fef0081c12
-       VSCEG   $1, V31, 16(R15)(V30*1) // VSCEG   V31, $1, 16(R15)(V30*1) // e7fef0101c1a
-       VGEF    $0, 2048(R15)(V1*1), V2 // VGEF    2048(R15)(V1*1), $0, V2 // e721f8000013
-       VSCEF   $0, V2, 4095(R15)(V1*1) // VSCEF   V2, $0, 4095(R15)(V1*1) // e721ffff001b
-       VLL     R0, (R15), V1           // VLL     (R15), R0, V1           // e710f0000037
-       VSTL    R0, V16, (R15)          // VSTL    V16, R0, (R15)          // e700f000083f
-       VGMH    $8, $16, V12            // VGMH    $16, $8, V12            // e7c008101046
-       VLEIB   $15, $255, V0           // VLEIB   $255, $15, V0           // e70000fff040
-       VLEIH   $7, $-32768, V15        // VLEIH   $-32768, $7, V15        // e7f080007041
-       VLEIF   $2, $-43, V16           // VLEIF   $-43, $2, V16           // e700ffd52843
-       VLEIG   $1, $32767, V31         // VLEIG   $32767, $1, V31         // e7f07fff1842
-       VSLDB   $3, V1, V16, V18        // VSLDB   V1, V16, $3, V18        // e72100030a77
-       VERIMB  $2, V31, V1, V2         // VERIMB  V31, V1, $2, V2         // e72f10020472
-       VSEL    V1, V2, V3, V4          // VSEL    V2, V3, V1, V4          // e7412000308d
-       VGFMAH  V21, V31, V24, V0       // VGFMAH  V31, V24, V21, V0       // e705f10087bc
-       VFMADB  V16, V8, V9, V10        // VFMADB  V8, V9, V16, V10        // e7a08300948f
-       WFMADB  V17, V18, V19, V20      // WFMADB  V18, V19, V17, V20      // e74123083f8f
-       VFMSDB  V2, V25, V24, V31       // VFMSDB  V25, V24, V2, V31       // e7f293008b8e
-       WFMSDB  V31, V2, V3, V4         // WFMSDB  V2, V3, V31, V4         // e74f2308348e
-       VPERM   V31, V0, V2, V3         // VPERM   V0, V2, V31, V3         // e73f0000248c
-       VPDI    $1, V2, V31, V1         // VPDI    V2, V31, $1, V1         // e712f0001284
-       VLEG    $1, (R3), V1            // VLEG    (R3), $1, V1            // e71030001002
-       VLEF    $2, (R0), V31           // VLEF    (R0), $2, V31           // e7f000002803
-       VLEH    $3, (R12), V16          // VLEH    (R12), $3, V16          // e700c0003801
-       VLEB    $15, 4095(R9), V15      // VLEB    4095(R9), $15, V15      // e7f09ffff000
-       VSTEG   $1, V30, (R1)(R2*1)     // VSTEG   V30, $1, (R1)(R2*1)     // e7e21000180a
-       VSTEF   $3, V2, (R9)            // VSTEF   V2, $3, (R9)            // e7209000300b
-       VSTEH   $7, V31, (R2)           // VSTEH   V31, $7, (R2)           // e7f020007809
-       VSTEB   $15, V29, 4094(R12)     // VSTEB   V29, $15, 4094(R12)     // e7d0cffef808
+       VL      (R15), V1               // e710f0000006
+       VST     V1, (R15)               // e710f000000e
+       VL      (R15), V31              // e7f0f0000806
+       VST     V31, (R15)              // e7f0f000080e
+       VESLB   $5, V14                 // e7ee00050030
+       VESRAG  $0, V15, V16            // e70f0000383a
+       VLM     (R15), V8, V23          // e787f0000436
+       VSTM    V8, V23, (R15)          // e787f000043e
+       VONE    V1                      // e710ffff0044
+       VZERO   V16                     // e70000000844
+       VGBM    $52428, V31             // e7f0cccc0844
+       VREPIB  $255, V4                // e74000ff0045
+       VREPIH  $-1, V16                // e700ffff1845
+       VREPIF  $-32768, V0             // e70080002045
+       VREPIG  $32767, V31             // e7f07fff3845
+       VREPG   $1, V4, V16             // e7040001384d
+       VREPB   $4, V31, V1             // e71f0004044d
+       VFTCIDB $4095, V1, V2           // e721fff0304a
+       WFTCIDB $3276, V15, V16         // e70fccc8384a
+       VPOPCT  V8, V19                 // e73800000850
+       VFEEZBS V1, V2, V31             // e7f120300880
+       WFCHDBS V22, V23, V4            // e746701836eb
+       VMNH    V1, V2, V30             // e7e1200018fe
+       VO      V2, V1, V0              // e7021000006a
+       VERLLVF V2, V30, V27            // e7be20002c73
+       VSCBIB  V0, V23, V24            // e78700000cf5
+       VNOT    V16, V1                 // e7101000046b
+       VCLZF   V16, V17                // e71000002c53
+       VLVGP   R3, R4, V8              // e78340000062
+       VGEG    $1, 8(R15)(V30*1), V31  // e7fef0081c12
+       VSCEG   $1, V31, 16(R15)(V30*1) // e7fef0101c1a
+       VGEF    $0, 2048(R15)(V1*1), V2 // e721f8000013
+       VSCEF   $0, V2, 4095(R15)(V1*1) // e721ffff001b
+       VLL     R0, (R15), V1           // e710f0000037
+       VSTL    R0, V16, (R15)          // e700f000083f
+       VGMH    $8, $16, V12            // e7c008101046
+       VLEIB   $15, $255, V0           // e70000fff040
+       VLEIH   $7, $-32768, V15        // e7f080007041
+       VLEIF   $2, $-43, V16           // e700ffd52843
+       VLEIG   $1, $32767, V31         // e7f07fff1842
+       VSLDB   $3, V1, V16, V18        // e72100030a77
+       VERIMB  $2, V31, V1, V2         // e72f10020472
+       VSEL    V1, V2, V3, V4          // e7412000308d
+       VGFMAH  V21, V31, V24, V0       // e705f10087bc
+       VFMADB  V16, V8, V9, V10        // e7a08300948f
+       WFMADB  V17, V18, V19, V20      // e74123083f8f
+       VFMSDB  V2, V25, V24, V31       // e7f293008b8e
+       WFMSDB  V31, V2, V3, V4         // e74f2308348e
+       VPERM   V31, V0, V2, V3         // e73f0000248c
+       VPDI    $1, V2, V31, V1         // e712f0001284
+       VLEG    $1, (R3), V1            // e71030001002
+       VLEF    $2, (R0), V31           // e7f000002803
+       VLEH    $3, (R12), V16          // e700c0003801
+       VLEB    $15, 4095(R9), V15      // e7f09ffff000
+       VSTEG   $1, V30, (R1)(R2*1)     // e7e21000180a
+       VSTEF   $3, V2, (R9)            // e7209000300b
+       VSTEH   $7, V31, (R2)           // e7f020007809
+       VSTEB   $15, V29, 4094(R12)     // e7d0cffef808
 
        RET
 
index 36e30a5fee7526d83be66d7261afddcaba61643a..f1ab5b0ddc68d5731ce1a7d67f6c98258721d42c 100644 (file)
@@ -42,10 +42,7 @@ func zerorange(pp *gc.Progs, p *obj.Prog, off, cnt int64, _ *uint32) *obj.Prog {
                end := int16(s390x.REGRT2)
                p = pp.Appendpp(p, s390x.AADD, obj.TYPE_CONST, 0, off+n, obj.TYPE_REG, end, 0)
                p.Reg = reg
-               p = pp.Appendpp(p, s390x.AXC, obj.TYPE_MEM, reg, off, obj.TYPE_MEM, reg, off)
-               p.From3 = new(obj.Addr)
-               p.From3.Type = obj.TYPE_CONST
-               p.From3.Offset = 256
+               p = pp.Appendpp(p, s390x.ACLEAR, obj.TYPE_CONST, 0, 256, obj.TYPE_MEM, reg, off)
                pl := p
                p = pp.Appendpp(p, s390x.AADD, obj.TYPE_CONST, 0, 256, obj.TYPE_REG, reg, 0)
                p = pp.Appendpp(p, s390x.ACMP, obj.TYPE_REG, reg, 0, obj.TYPE_REG, end, 0)
@@ -78,12 +75,9 @@ func zerorange(pp *gc.Progs, p *obj.Prog, off, cnt int64, _ *uint32) *obj.Prog {
                        }
                        p = pp.Appendpp(p, ins, obj.TYPE_CONST, 0, 0, obj.TYPE_MEM, reg, off)
 
-               // Handle clears that would require multiple move instructions with XC.
+               // Handle clears that would require multiple move instructions with CLEAR (assembled as XC).
                default:
-                       p = pp.Appendpp(p, s390x.AXC, obj.TYPE_MEM, reg, off, obj.TYPE_MEM, reg, off)
-                       p.From3 = new(obj.Addr)
-                       p.From3.Type = obj.TYPE_CONST
-                       p.From3.Offset = n
+                       p = pp.Appendpp(p, s390x.ACLEAR, obj.TYPE_CONST, 0, n, obj.TYPE_MEM, reg, off)
                }
 
                cnt -= n
index 9ccd3c762cdb8304a8256ff5ae152abfc23370a9..d755859dcfbccbb9692d4b0ca17904f1353bde67 100644 (file)
@@ -531,15 +531,15 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
        case ssa.OpS390XMVC:
                vo := v.AuxValAndOff()
                p := s.Prog(s390x.AMVC)
-               p.From.Type = obj.TYPE_MEM
-               p.From.Reg = v.Args[1].Reg()
-               p.From.Offset = vo.Off()
+               p.From.Type = obj.TYPE_CONST
+               p.From.Offset = vo.Val()
+               p.From3 = new(obj.Addr)
+               p.From3.Type = obj.TYPE_MEM
+               p.From3.Reg = v.Args[1].Reg()
+               p.From3.Offset = vo.Off()
                p.To.Type = obj.TYPE_MEM
                p.To.Reg = v.Args[0].Reg()
                p.To.Offset = vo.Off()
-               p.From3 = new(obj.Addr)
-               p.From3.Type = obj.TYPE_CONST
-               p.From3.Offset = vo.Val()
        case ssa.OpS390XSTMG2, ssa.OpS390XSTMG3, ssa.OpS390XSTMG4,
                ssa.OpS390XSTM2, ssa.OpS390XSTM3, ssa.OpS390XSTM4:
                for i := 2; i < len(v.Args)-1; i++ {
@@ -567,13 +567,13 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
                //      MVC  $rem, 0(R2), 0(R1) // if rem > 0
                // arg2 is the last address to move in the loop + 256
                mvc := s.Prog(s390x.AMVC)
-               mvc.From.Type = obj.TYPE_MEM
-               mvc.From.Reg = v.Args[1].Reg()
+               mvc.From.Type = obj.TYPE_CONST
+               mvc.From.Offset = 256
+               mvc.From3 = new(obj.Addr)
+               mvc.From3.Type = obj.TYPE_MEM
+               mvc.From3.Reg = v.Args[1].Reg()
                mvc.To.Type = obj.TYPE_MEM
                mvc.To.Reg = v.Args[0].Reg()
-               mvc.From3 = new(obj.Addr)
-               mvc.From3.Type = obj.TYPE_CONST
-               mvc.From3.Offset = 256
 
                for i := 0; i < 2; i++ {
                        movd := s.Prog(s390x.AMOVD)
@@ -596,13 +596,13 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
 
                if v.AuxInt > 0 {
                        mvc := s.Prog(s390x.AMVC)
-                       mvc.From.Type = obj.TYPE_MEM
-                       mvc.From.Reg = v.Args[1].Reg()
+                       mvc.From.Type = obj.TYPE_CONST
+                       mvc.From.Offset = v.AuxInt
+                       mvc.From3 = new(obj.Addr)
+                       mvc.From3.Type = obj.TYPE_MEM
+                       mvc.From3.Reg = v.Args[1].Reg()
                        mvc.To.Type = obj.TYPE_MEM
                        mvc.To.Reg = v.Args[0].Reg()
-                       mvc.From3 = new(obj.Addr)
-                       mvc.From3.Type = obj.TYPE_CONST
-                       mvc.From3.Offset = v.AuxInt
                }
        case ssa.OpS390XLoweredZero:
                // Input must be valid pointers to memory,
index 7b25b88fa85a7f422b01b63d20a965dd5785f45d..df466d6d920fb6d9e5daae45969aa5daedb7b6c8 100644 (file)
@@ -276,9 +276,9 @@ var optab = []Optab{
        Optab{ASTCK, C_NONE, C_NONE, C_NONE, C_SOREG, 88, 0},
 
        // storage and storage
-       Optab{AMVC, C_LOREG, C_NONE, C_SCON, C_LOREG, 84, 0},
-       Optab{AMVC, C_LOREG, C_NONE, C_SCON, C_LAUTO, 84, REGSP},
-       Optab{AMVC, C_LAUTO, C_NONE, C_SCON, C_LAUTO, 84, REGSP},
+       Optab{AMVC, C_SCON, C_NONE, C_LOREG, C_LOREG, 84, 0},
+       Optab{AMVC, C_SCON, C_NONE, C_LOREG, C_LAUTO, 84, REGSP},
+       Optab{AMVC, C_SCON, C_NONE, C_LAUTO, C_LAUTO, 84, REGSP},
 
        // address
        Optab{ALARL, C_LCON, C_NONE, C_NONE, C_REG, 85, 0},
@@ -299,22 +299,22 @@ var optab = []Optab{
        // VRX store
        Optab{AVST, C_VREG, C_NONE, C_NONE, C_SOREG, 100, 0},
        Optab{AVST, C_VREG, C_NONE, C_NONE, C_SAUTO, 100, REGSP},
-       Optab{AVSTEG, C_VREG, C_NONE, C_SCON, C_SOREG, 100, 0},
-       Optab{AVSTEG, C_VREG, C_NONE, C_SCON, C_SAUTO, 100, REGSP},
+       Optab{AVSTEG, C_SCON, C_VREG, C_NONE, C_SOREG, 100, 0},
+       Optab{AVSTEG, C_SCON, C_VREG, C_NONE, C_SAUTO, 100, REGSP},
 
        // VRX load
        Optab{AVL, C_SOREG, C_NONE, C_NONE, C_VREG, 101, 0},
        Optab{AVL, C_SAUTO, C_NONE, C_NONE, C_VREG, 101, REGSP},
-       Optab{AVLEG, C_SOREG, C_NONE, C_SCON, C_VREG, 101, 0},
-       Optab{AVLEG, C_SAUTO, C_NONE, C_SCON, C_VREG, 101, REGSP},
+       Optab{AVLEG, C_SCON, C_NONE, C_SOREG, C_VREG, 101, 0},
+       Optab{AVLEG, C_SCON, C_NONE, C_SAUTO, C_VREG, 101, REGSP},
 
        // VRV scatter
-       Optab{AVSCEG, C_VREG, C_NONE, C_SCON, C_SOREG, 102, 0},
-       Optab{AVSCEG, C_VREG, C_NONE, C_SCON, C_SAUTO, 102, REGSP},
+       Optab{AVSCEG, C_SCON, C_VREG, C_NONE, C_SOREG, 102, 0},
+       Optab{AVSCEG, C_SCON, C_VREG, C_NONE, C_SAUTO, 102, REGSP},
 
        // VRV gather
-       Optab{AVGEG, C_SOREG, C_NONE, C_SCON, C_VREG, 103, 0},
-       Optab{AVGEG, C_SAUTO, C_NONE, C_SCON, C_VREG, 103, REGSP},
+       Optab{AVGEG, C_SCON, C_NONE, C_SOREG, C_VREG, 103, 0},
+       Optab{AVGEG, C_SCON, C_NONE, C_SAUTO, C_VREG, 103, REGSP},
 
        // VRS element shift/rotate and load gr to/from vr element
        Optab{AVESLG, C_SCON, C_VREG, C_NONE, C_VREG, 104, 0},
@@ -335,19 +335,19 @@ var optab = []Optab{
        Optab{AVLM, C_SAUTO, C_VREG, C_NONE, C_VREG, 106, REGSP},
 
        // VRS store with length
-       Optab{AVSTL, C_VREG, C_NONE, C_REG, C_SOREG, 107, 0},
-       Optab{AVSTL, C_VREG, C_NONE, C_REG, C_SAUTO, 107, REGSP},
+       Optab{AVSTL, C_REG, C_VREG, C_NONE, C_SOREG, 107, 0},
+       Optab{AVSTL, C_REG, C_VREG, C_NONE, C_SAUTO, 107, REGSP},
 
        // VRS load with length
-       Optab{AVLL, C_SOREG, C_NONE, C_REG, C_VREG, 108, 0},
-       Optab{AVLL, C_SAUTO, C_NONE, C_REG, C_VREG, 108, REGSP},
+       Optab{AVLL, C_REG, C_NONE, C_SOREG, C_VREG, 108, 0},
+       Optab{AVLL, C_REG, C_NONE, C_SAUTO, C_VREG, 108, REGSP},
 
        // VRI-a
        Optab{AVGBM, C_ANDCON, C_NONE, C_NONE, C_VREG, 109, 0},
        Optab{AVZERO, C_NONE, C_NONE, C_NONE, C_VREG, 109, 0},
        Optab{AVREPIG, C_ADDCON, C_NONE, C_NONE, C_VREG, 109, 0},
        Optab{AVREPIG, C_SCON, C_NONE, C_NONE, C_VREG, 109, 0},
-       Optab{AVLEIG, C_ADDCON, C_NONE, C_SCON, C_VREG, 109, 0},
+       Optab{AVLEIG, C_SCON, C_NONE, C_ADDCON, C_VREG, 109, 0},
        Optab{AVLEIG, C_SCON, C_NONE, C_SCON, C_VREG, 109, 0},
 
        // VRI-b generate mask
@@ -358,8 +358,8 @@ var optab = []Optab{
 
        // VRI-d element rotate and insert under mask and
        // shift left double by byte
-       Optab{AVERIMG, C_VREG, C_VREG, C_SCON, C_VREG, 112, 0},
-       Optab{AVSLDB, C_VREG, C_VREG, C_SCON, C_VREG, 112, 0},
+       Optab{AVERIMG, C_SCON, C_VREG, C_VREG, C_VREG, 112, 0},
+       Optab{AVSLDB, C_SCON, C_VREG, C_VREG, C_VREG, 112, 0},
 
        // VRI-d fp test data class immediate
        Optab{AVFTCIDB, C_SCON, C_VREG, C_NONE, C_VREG, 113, 0},
@@ -379,7 +379,7 @@ var optab = []Optab{
        Optab{AVAQ, C_VREG, C_VREG, C_NONE, C_VREG, 118, 0},
        Optab{AVAQ, C_VREG, C_NONE, C_NONE, C_VREG, 118, 0},
        Optab{AVNOT, C_VREG, C_NONE, C_NONE, C_VREG, 118, 0},
-       Optab{AVPDI, C_VREG, C_VREG, C_SCON, C_VREG, 123, 0},
+       Optab{AVPDI, C_SCON, C_VREG, C_VREG, C_VREG, 123, 0},
 
        // VRR-c shifts
        Optab{AVERLLVG, C_VREG, C_VREG, C_NONE, C_VREG, 119, 0},
@@ -3542,16 +3542,16 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
                // M4 is reserved and must be 0
                zRRF(opcode, 5, 0, uint32(p.To.Reg), uint32(p.From.Reg), asm)
 
-       case 84: // storage-and-storage operations $length mem mem (length in From3)
-               l := c.regoff(p.From3)
+       case 84: // storage-and-storage operations $length mem mem
+               l := c.regoff(&p.From)
                if l < 1 || l > 256 {
                        c.ctxt.Diag("number of bytes (%v) not in range [1,256]", l)
                }
-               if p.From.Index != 0 || p.To.Index != 0 {
+               if p.From3.Index != 0 || p.To.Index != 0 {
                        c.ctxt.Diag("cannot use index reg")
                }
                b1 := p.To.Reg
-               b2 := p.From.Reg
+               b2 := p.From3.Reg
                if b1 == 0 {
                        b1 = o.param
                }
@@ -3559,7 +3559,7 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
                        b2 = o.param
                }
                d1 := c.regoff(&p.To)
-               d2 := c.regoff(&p.From)
+               d2 := c.regoff(p.From3)
                if d1 < 0 || d1 >= DISP12 {
                        if b2 == REGTMP {
                                c.ctxt.Diag("REGTMP conflict")
@@ -3891,51 +3891,51 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
 
        case 100: // VRX STORE
                op, m3, _ := vop(p.As)
-               if p.From3 != nil {
-                       m3 = uint32(c.vregoff(p.From3))
+               v1 := p.From.Reg
+               if p.Reg != 0 {
+                       m3 = uint32(c.vregoff(&p.From))
+                       v1 = p.Reg
                }
                b2 := p.To.Reg
                if b2 == 0 {
                        b2 = o.param
                }
                d2 := uint32(c.vregoff(&p.To))
-               zVRX(op, uint32(p.From.Reg), uint32(p.To.Index), uint32(b2), d2, m3, asm)
+               zVRX(op, uint32(v1), uint32(p.To.Index), uint32(b2), d2, m3, asm)
 
        case 101: // VRX LOAD
                op, m3, _ := vop(p.As)
+               src := &p.From
                if p.From3 != nil {
-                       m3 = uint32(c.vregoff(p.From3))
+                       m3 = uint32(c.vregoff(&p.From))
+                       src = p.From3
                }
-               b2 := p.From.Reg
+               b2 := src.Reg
                if b2 == 0 {
                        b2 = o.param
                }
-               d2 := uint32(c.vregoff(&p.From))
-               zVRX(op, uint32(p.To.Reg), uint32(p.From.Index), uint32(b2), d2, m3, asm)
+               d2 := uint32(c.vregoff(src))
+               zVRX(op, uint32(p.To.Reg), uint32(src.Index), uint32(b2), d2, m3, asm)
 
        case 102: // VRV SCATTER
-               op, m3, _ := vop(p.As)
-               if p.From3 != nil {
-                       m3 = uint32(c.vregoff(p.From3))
-               }
+               op, _, _ := vop(p.As)
+               m3 := uint32(c.vregoff(&p.From))
                b2 := p.To.Reg
                if b2 == 0 {
                        b2 = o.param
                }
                d2 := uint32(c.vregoff(&p.To))
-               zVRV(op, uint32(p.From.Reg), uint32(p.To.Index), uint32(b2), d2, m3, asm)
+               zVRV(op, uint32(p.Reg), uint32(p.To.Index), uint32(b2), d2, m3, asm)
 
        case 103: // VRV GATHER
-               op, m3, _ := vop(p.As)
-               if p.From3 != nil {
-                       m3 = uint32(c.vregoff(p.From3))
-               }
-               b2 := p.From.Reg
+               op, _, _ := vop(p.As)
+               m3 := uint32(c.vregoff(&p.From))
+               b2 := p.From3.Reg
                if b2 == 0 {
                        b2 = o.param
                }
-               d2 := uint32(c.vregoff(&p.From))
-               zVRV(op, uint32(p.To.Reg), uint32(p.From.Index), uint32(b2), d2, m3, asm)
+               d2 := uint32(c.vregoff(p.From3))
+               zVRV(op, uint32(p.To.Reg), uint32(p.From3.Index), uint32(b2), d2, m3, asm)
 
        case 104: // VRS SHIFT/ROTATE and LOAD GR FROM VR ELEMENT
                op, m4, _ := vop(p.As)
@@ -3971,35 +3971,36 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
                if reg == 0 {
                        reg = o.param
                }
-               zVRS(op, uint32(p.From.Reg), uint32(p.From3.Reg), uint32(reg), offset, 0, asm)
+               zVRS(op, uint32(p.Reg), uint32(p.From.Reg), uint32(reg), offset, 0, asm)
 
        case 108: // VRS LOAD WITH LENGTH
                op, _, _ := vop(p.As)
-               offset := uint32(c.vregoff(&p.From))
-               reg := p.From.Reg
+               offset := uint32(c.vregoff(p.From3))
+               reg := p.From3.Reg
                if reg == 0 {
                        reg = o.param
                }
-               zVRS(op, uint32(p.To.Reg), uint32(p.From3.Reg), uint32(reg), offset, 0, asm)
+               zVRS(op, uint32(p.To.Reg), uint32(p.From.Reg), uint32(reg), offset, 0, asm)
 
        case 109: // VRI-a
                op, m3, _ := vop(p.As)
                i2 := uint32(c.vregoff(&p.From))
+               if p.From3 != nil {
+                       m3 = uint32(c.vregoff(&p.From))
+                       i2 = uint32(c.vregoff(p.From3))
+               }
                switch p.As {
                case AVZERO:
                        i2 = 0
                case AVONE:
                        i2 = 0xffff
                }
-               if p.From3 != nil {
-                       m3 = uint32(c.vregoff(p.From3))
-               }
                zVRIa(op, uint32(p.To.Reg), i2, m3, asm)
 
        case 110:
                op, m4, _ := vop(p.As)
-               i2 := uint32(c.vregoff(p.From3))
-               i3 := uint32(c.vregoff(&p.From))
+               i2 := uint32(c.vregoff(&p.From))
+               i3 := uint32(c.vregoff(p.From3))
                zVRIb(op, uint32(p.To.Reg), i2, i3, m4, asm)
 
        case 111:
@@ -4009,8 +4010,8 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
 
        case 112:
                op, m5, _ := vop(p.As)
-               i4 := uint32(c.vregoff(p.From3))
-               zVRId(op, uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), i4, m5, asm)
+               i4 := uint32(c.vregoff(&p.From))
+               zVRId(op, uint32(p.To.Reg), uint32(p.Reg), uint32(p.From3.Reg), i4, m5, asm)
 
        case 113:
                op, m4, _ := vop(p.As)
@@ -4028,8 +4029,6 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
                m4 := singleElementMask(p.As)
                zVRRa(op, uint32(p.From.Reg), uint32(p.To.Reg), m5, m4, m3, asm)
 
-       case 116: // VRR-a
-
        case 117: // VRR-b
                op, m4, m5 := vop(p.As)
                zVRRb(op, uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), m5, m4, asm)
@@ -4056,18 +4055,18 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
                op, m6, _ := vop(p.As)
                m5 := singleElementMask(p.As)
                v1 := uint32(p.To.Reg)
-               v2 := uint32(p.From3.Reg)
-               v3 := uint32(p.From.Reg)
-               v4 := uint32(p.Reg)
+               v2 := uint32(p.From.Reg)
+               v3 := uint32(p.Reg)
+               v4 := uint32(p.From3.Reg)
                zVRRd(op, v1, v2, v3, m6, m5, v4, asm)
 
        case 121: // VRR-e
                op, m6, _ := vop(p.As)
                m5 := singleElementMask(p.As)
                v1 := uint32(p.To.Reg)
-               v2 := uint32(p.From3.Reg)
-               v3 := uint32(p.From.Reg)
-               v4 := uint32(p.Reg)
+               v2 := uint32(p.From.Reg)
+               v3 := uint32(p.Reg)
+               v4 := uint32(p.From3.Reg)
                zVRRe(op, v1, v2, v3, m6, m5, v4, asm)
 
        case 122: // VRR-f LOAD VRS FROM GRS DISJOINT
@@ -4076,8 +4075,8 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
 
        case 123: // VPDI $m4, V2, V3, V1
                op, _, _ := vop(p.As)
-               m4 := c.regoff(p.From3)
-               zVRRc(op, uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), 0, 0, uint32(m4), asm)
+               m4 := c.regoff(&p.From)
+               zVRRc(op, uint32(p.To.Reg), uint32(p.Reg), uint32(p.From3.Reg), 0, 0, uint32(m4), asm)
        }
 }