]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/arm: better solution of .S/.P/.U/.W suffix check
authorBen Shi <powerman1st@163.com>
Sat, 14 Oct 2017 14:02:05 +0000 (14:02 +0000)
committerCherry Zhang <cherryyz@google.com>
Tue, 17 Oct 2017 15:18:12 +0000 (15:18 +0000)
Current suffix check is based on instruction, which is not very
accurate. For example, "MOVW.S R1, R2" is valid, but
"MOVW.S $0xaaaaaaaa, R1" and "MOVW.P CPSR, R9" are not.

This patch fixes the above kinds of issues by checking suffix
based on []optab. And also more test cases are added.

fixes #20509

Change-Id: Ibad91be72c78eefa719412a83b4d44370d2202a8
Reviewed-on: https://go-review.googlesource.com/70910
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/asm/internal/asm/testdata/arm.s
src/cmd/asm/internal/asm/testdata/armerror.s
src/cmd/internal/obj/arm/asm5.go

index 13fde445042d0f6acebd22f057fb0bbead76caac..319e07c21c3dc3f9ee79e20553c114d0f7af0db9 100644 (file)
@@ -57,7 +57,7 @@ TEXT  foo(SB), DUPOK|NOSPLIT, $0
 //             outcode($1, $2, &$3, 0, &$5);
 //     }
        MOVW.S  R1, R2
-       MOVW.S  $1, R2
+       MOVW    $1, R2
        MOVW.S  R1<<R2, R3
 
 //
@@ -1116,8 +1116,6 @@ jmp_label_3:
 // MVN
        MVN     $0xff, R1        // MVN $255, R1          // ff10e0e3
        MVN     $0xff000000, R1  // MVN $4278190080, R1   // ff14e0e3
-       MVN.S   $0xff, R1        // MVN.S $255, R1        // ff10f0e3
-       MVN.S   $0xff000000, R1  // MVN.S $4278190080, R1 // ff14f0e3
        MVN     R9<<30, R7       // 097fe0e1
        MVN     R9>>30, R7       // 297fe0e1
        MVN     R9->30, R7       // 497fe0e1
@@ -1135,7 +1133,6 @@ jmp_label_3:
        MVN.S   R9->R8, R7       // 5978f0e1
        MVN.S   R9@>R8, R7       // 7978f0e1
        MVN     $0xffffffbe, R5  // MVN $4294967230, R5   // 4150a0e3
-       MVN.S   $0xffffffbf, R5  // MVN.S $4294967231, R5 // 4050b0e3
 
 // MOVM
        MOVM.IA   [R0,R2,R4,R6], (R1)        // MOVM.U [R0,R2,R4,R6], (R1)                      // 550081e8
@@ -1173,15 +1170,23 @@ jmp_label_3:
 
 // MOVW
        MOVW    R3, R4                                            // 0340a0e1
+       MOVW.S  R3, R4                                            // 0340b0e1
        MOVW    R9, R2                                            // 0920a0e1
+       MOVW.S  R9, R2                                            // 0920b0e1
        MOVW    R5>>1, R2                                         // a520a0e1
+       MOVW.S  R5>>1, R2                                         // a520b0e1
        MOVW    R5<<1, R2                                         // 8520a0e1
+       MOVW.S  R5<<1, R2                                         // 8520b0e1
        MOVW    R5->1, R2                                         // c520a0e1
+       MOVW.S  R5->1, R2                                         // c520b0e1
        MOVW    R5@>1, R2                                         // e520a0e1
+       MOVW.S  R5@>1, R2                                         // e520b0e1
        MOVW    $0xff, R9            // MOVW $255, R9             // ff90a0e3
        MOVW    $0xff000000, R9      // MOVW $4278190080, R9      // ff94a0e3
        MOVW    $0xff(R0), R1        // MOVW $255(R0), R1         // ff1080e2
+       MOVW.S  $0xff(R0), R1        // MOVW.S $255(R0), R1       // ff1090e2
        MOVW    $-0xff(R0), R1       // MOVW $-255(R0), R1        // ff1040e2
+       MOVW.S  $-0xff(R0), R1       // MOVW.S $-255(R0), R1      // ff1050e2
        MOVW    $0xffffffae, R1      // MOVW $4294967214, R1      // 5110e0e3
        MOVW    $0xaaaaaaaa, R1      // MOVW $2863311530, R1
        MOVW    R1, (R2)                                          // 001082e5
index 34c2b2a9860bc39133f7b69bd19b978708f7285f..6ded33d8e43d4d072f10d1f1017266be0bd33667 100644 (file)
@@ -79,6 +79,8 @@ TEXT errors(SB),$0
        MOVW    errors(SB), F0     // ERROR "illegal combination"
        MOVW    $20, errors(SB)    // ERROR "illegal combination"
        MOVW    errors(SB), $20    // ERROR "illegal combination"
+       MOVW    (R1), [R0-R4]      // ERROR "illegal combination"
+       MOVW    [R0-R4], (R1)      // ERROR "illegal combination"
        MOVB    $245, R1           // ERROR "illegal combination"
        MOVH    $245, R1           // ERROR "illegal combination"
        MOVB    $0xff000000, R1    // ERROR "illegal combination"
@@ -101,10 +103,10 @@ TEXT errors(SB),$0
        MOVH    $0xffffff00, CPSR  // ERROR "illegal combination"
        MOVB    $0xfffffff0, FPSR  // ERROR "illegal combination"
        MOVH    $0xfffffff0, FPSR  // ERROR "illegal combination"
-       MOVB.IA 4(R1), [R0-R4]     // ERROR "illegal combination"
-       MOVB.DA 4(R1), [R0-R4]     // ERROR "illegal combination"
-       MOVH.IA 4(R1), [R0-R4]     // ERROR "illegal combination"
-       MOVH.DA 4(R1), [R0-R4]     // ERROR "illegal combination"
+       MOVB    (R1), [R0-R4]      // ERROR "illegal combination"
+       MOVB    [R0-R4], (R1)      // ERROR "illegal combination"
+       MOVH    (R1), [R0-R4]      // ERROR "illegal combination"
+       MOVH    [R0-R4], (R1)      // ERROR "illegal combination"
        MOVB    $0xff(R0), R1      // ERROR "illegal combination"
        MOVH    $0xff(R0), R1      // ERROR "illegal combination"
        MOVB    $errors(SB), R2    // ERROR "illegal combination"
@@ -161,6 +163,93 @@ TEXT errors(SB),$0
        XTAH    R0<<16, R5, R2     // ERROR "illegal shift"
        XTABU   R0->24, R5, R2     // ERROR "illegal shift"
        XTAHU   R0@>1, R5, R2      // ERROR "illegal shift"
+       AND.W   R0, R1             // ERROR "invalid .W suffix"
+       ORR.P   R2, R3, R4         // ERROR "invalid .P suffix"
+       CMP.S   R1, R2             // ERROR "invalid .S suffix"
+       BIC.P   $124, R1, R2       // ERROR "invalid .P suffix"
+       MOVW.S  $124, R1           // ERROR "invalid .S suffix"
+       MVN.S   $123, g            // ERROR "invalid .S suffix"
+       RSB.U   $0, R9             // ERROR "invalid .U suffix"
+       CMP.S   $29, g             // ERROR "invalid .S suffix"
+       ADD.W   R1<<R2, R3         // ERROR "invalid .W suffix"
+       SUB.U   R1<<R2, R3, R9     // ERROR "invalid .U suffix"
+       CMN.S   R5->R2, R1         // ERROR "invalid .S suffix"
+       SLL.P   R1, R2, R3         // ERROR "invalid .P suffix"
+       SRA.U   R2, R8             // ERROR "invalid .U suffix"
+       SWI.S                      // ERROR "invalid .S suffix"
+       SWI.P   $0                 // ERROR "invalid .P suffix"
+       MOVW.S  $0xaaaaaaaa, R7    // ERROR "invalid .S suffix"
+       MOVW.P  $0xffffff44, R1    // ERROR "invalid .P suffix"
+       MOVW.S  $0xffffff77, R1    // ERROR "invalid .S suffix"
+       MVN.S   $0xffffffaa, R8    // ERROR "invalid .S suffix"
+       MVN.S   $0xaaaaaaaa, R8    // ERROR "invalid .S suffix"
+       ADD.U   $0xaaaaaaaa, R4    // ERROR "invalid .U suffix"
+       ORR.P   $0x555555, R7, R3  // ERROR "invalid .P suffix"
+       TST.S   $0xabcd1234, R2    // ERROR "invalid .S suffix"
+       MOVB.S  R1, R2             // ERROR "invalid .S suffix"
+       MOVBU.P R1, R2             // ERROR "invalid .P suffix"
+       MOVBS.U R1, R2             // ERROR "invalid .U suffix"
+       MOVH.S  R1, R2             // ERROR "invalid .S suffix"
+       MOVHU.P R1, R2             // ERROR "invalid .P suffix"
+       MOVHS.U R1, R2             // ERROR "invalid .U suffix"
+       MUL.P   R0, R1, R2         // ERROR "invalid .P suffix"
+       MULU.W  R1, R2             // ERROR "invalid .W suffix"
+       DIVHW.S R0, R1, R2         // ERROR "invalid .S suffix"
+       DIVHW.W R1, R2             // ERROR "invalid .W suffix"
+       MULL.W  R2, R0, (R5, R8)   // ERROR "invalid .W suffix"
+       MULLU.U R2, R0, (R5, R8)   // ERROR "invalid .U suffix"
+       BFX.S   $2, $4, R3         // ERROR "invalid .S suffix"
+       BFXU.W  $2, $4, R3, R0     // ERROR "invalid .W suffix"
+       MOVB.S  R1, 4(R2)          // ERROR "invalid .S suffix"
+       MOVHU.S R1, 4(R2)          // ERROR "invalid .S suffix"
+       MOVW.S  R1, 4(R2)          // ERROR "invalid .S suffix"
+       MOVBU.S 4(R2), R3          // ERROR "invalid .S suffix"
+       MOVH.S  4(R2), R3          // ERROR "invalid .S suffix"
+       MOVW.S  4(R2), R3          // ERROR "invalid .S suffix"
+       XTAB.S  R0@>0, R2          // ERROR "invalid .S suffix"
+       XTAB.W  R0@>8, R2, R9      // ERROR "invalid .W suffix"
+       MOVBU.S R0@>24, R1         // ERROR "invalid .S suffix"
+       MOVHS.S R0@>16, R1         // ERROR "invalid .S suffix"
+       MOVB.S  R1, 0xaaaa(R2)     // ERROR "invalid .S suffix"
+       MOVHU.S R1, 0xaaaa(R2)     // ERROR "invalid .S suffix"
+       MOVW.S  R1, 0xaaaa(R2)     // ERROR "invalid .S suffix"
+       MOVBU.S 0xaaaa(R2), R3     // ERROR "invalid .S suffix"
+       MOVH.S  0xaaaa(R2), R3     // ERROR "invalid .S suffix"
+       MOVW.S  0xaaaa(R2), R3     // ERROR "invalid .S suffix"
+       MOVW.S  CPSR, R1           // ERROR "invalid .S suffix"
+       MOVW.S  R3, CPSR           // ERROR "invalid .S suffix"
+       MOVW.S  $0, CPSR           // ERROR "invalid .S suffix"
+       MOVM.S  (R0), [R2-R4]      // ERROR "invalid .S suffix"
+       MOVM.S  [R1-R6], (R9)      // ERROR "invalid .S suffix"
+       SWPW.S  R1, (R2), R3       // ERROR "invalid .S suffix"
+       MOVF.S  (R0), F1           // ERROR "invalid .S suffix"
+       MOVF.S  F9, (R4)           // ERROR "invalid .S suffix"
+       MOVF.S  0xfff0(R0), F1     // ERROR "invalid .S suffix"
+       MOVF.S  F9, 0xfff0(R4)     // ERROR "invalid .S suffix"
+       ADDF.S  F1, F2, F3         // ERROR "invalid .S suffix"
+       SUBD.U  F1, F2             // ERROR "invalid .U suffix"
+       NEGF.W  F9, F10            // ERROR "invalid .W suffix"
+       ABSD.P  F9, F10            // ERROR "invalid .P suffix"
+       MOVW.S  FPSR, R0           // ERROR "invalid .S suffix"
+       MOVW.P  g, FPSR            // ERROR "invalid .P suffix"
+       MOVW.S  R1->4(R6), R2      // ERROR "invalid .S suffix"
+       MOVB.S  R9, R2<<8(R4)      // ERROR "invalid .S suffix"
+       MOVHU.S R9, R2<<0(R4)      // ERROR "invalid .S suffix"
+       STREX.S R0, (R1), R2       // ERROR "invalid .S suffix"
+       LDREX.S (R2), R8           // ERROR "invalid .S suffix"
+       MOVF.S  $0.0, F3           // ERROR "invalid .S suffix"
+       CMPF.S  F1, F2             // ERROR "invalid .S suffix"
+       MOVFW.S F0, F9             // ERROR "invalid .S suffix"
+       MOVWF.W F3, F1             // ERROR "invalid .W suffix"
+       MOVFW.P F0, R9             // ERROR "invalid .P suffix"
+       MOVWF.W R3, F1             // ERROR "invalid .W suffix"
+       MOVW.S  F0, R9             // ERROR "invalid .S suffix"
+       MOVW.U  R3, F1             // ERROR "invalid .U suffix"
+       PLD.S   4(R1)              // ERROR "invalid .S suffix"
+       CLZ.S   R1, R2             // ERROR "invalid .S suffix"
+       MULBB.S R0, R1, R2         // ERROR "invalid .S suffix"
+       MULA.W  R9, R6, R1, g      // ERROR "invalid .W suffix"
+       MULS.S  R2, R3, R4, g      // ERROR "invalid .S suffix"
 
        STREX   R1, (R0)           // ERROR "illegal combination"
        STREX   (R1), R0           // ERROR "illegal combination"
index fc74919a7fe21c5ca01eeafec3610557a35445da..67be8d720a4364a107489ac078ef48182cbff671 100644 (file)
@@ -69,6 +69,7 @@ type Optab struct {
        param    int16
        flag     int8
        pcrelsiz uint8
+       scond    uint8  // optional flags accepted by the instruction
 }
 
 type Opcross [32][2][32]uint8
@@ -82,253 +83,252 @@ const (
 
 var optab = []Optab{
        /* struct Optab:
-       OPCODE, from, prog->reg, to,             type,size,param,flag */
-       {obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0},
-       {AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0},
-       {AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
-       {AAND, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0},
-       {AAND, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
-       {AORR, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0},
-       {AORR, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
-       {AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
-       {AMVN, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
-       {ACMP, C_REG, C_REG, C_NONE, 1, 4, 0, 0, 0},
-       {AADD, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0},
-       {AADD, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
-       {AAND, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0},
-       {AAND, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
-       {AORR, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0},
-       {AORR, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
-       {AMOVW, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
-       {AMVN, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
-       {ACMP, C_RCON, C_REG, C_NONE, 2, 4, 0, 0, 0},
-       {AADD, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0},
-       {AADD, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
-       {AAND, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0},
-       {AAND, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
-       {AORR, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0},
-       {AORR, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
-       {AMVN, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
-       {ACMP, C_SHIFT, C_REG, C_NONE, 3, 4, 0, 0, 0},
-       {AMOVW, C_RACON, C_NONE, C_REG, 4, 4, REGSP, 0, 0},
-       {AB, C_NONE, C_NONE, C_SBRA, 5, 4, 0, LPOOL, 0},
-       {ABL, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
-       {ABX, C_NONE, C_NONE, C_SBRA, 74, 20, 0, 0, 0},
-       {ABEQ, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
-       {ABEQ, C_RCON, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // prediction hinted form, hint ignored
-
-       {AB, C_NONE, C_NONE, C_ROREG, 6, 4, 0, LPOOL, 0},
-       {ABL, C_NONE, C_NONE, C_ROREG, 7, 4, 0, 0, 0},
-       {ABL, C_REG, C_NONE, C_ROREG, 7, 4, 0, 0, 0},
-       {ABX, C_NONE, C_NONE, C_ROREG, 75, 12, 0, 0, 0},
-       {ABXRET, C_NONE, C_NONE, C_ROREG, 76, 4, 0, 0, 0},
-       {ASLL, C_RCON, C_REG, C_REG, 8, 4, 0, 0, 0},
-       {ASLL, C_RCON, C_NONE, C_REG, 8, 4, 0, 0, 0},
-       {ASLL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
-       {ASLL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0},
-       {ASWI, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
-       {ASWI, C_NONE, C_NONE, C_LCON, 10, 4, 0, 0, 0},
-       {AWORD, C_NONE, C_NONE, C_LCON, 11, 4, 0, 0, 0},
-       {AWORD, C_NONE, C_NONE, C_LCONADDR, 11, 4, 0, 0, 0},
-       {AWORD, C_NONE, C_NONE, C_ADDR, 11, 4, 0, 0, 0},
-       {AWORD, C_NONE, C_NONE, C_TLS_LE, 103, 4, 0, 0, 0},
-       {AWORD, C_NONE, C_NONE, C_TLS_IE, 104, 4, 0, 0, 0},
-       {AMOVW, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0},
-       {AMOVW, C_SCON, C_NONE, C_REG, 12, 4, 0, 0, 0},
-       {AMOVW, C_LCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0},
-       {AMOVW, C_LCONADDR, C_NONE, C_REG, 12, 4, 0, LFROM | LPCREL, 4},
-       {AMVN, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0},
-       {AADD, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0},
-       {AADD, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
-       {AAND, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0},
-       {AAND, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
-       {AORR, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0},
-       {AORR, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
-       {ACMP, C_NCON, C_REG, C_NONE, 13, 8, 0, 0, 0},
-       {AADD, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0},
-       {AADD, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
-       {AAND, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0},
-       {AAND, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
-       {AORR, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0},
-       {AORR, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
-       {AMVN, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
-       {ACMP, C_SCON, C_REG, C_NONE, 13, 8, 0, 0, 0},
-       {AADD, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0},
-       {AADD, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0},
-       {AORR, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0},
-       {AORR, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0},
-       {AADD, C_RCON2S, C_REG, C_REG, 107, 8, 0, 0, 0},
-       {AADD, C_RCON2S, C_NONE, C_REG, 107, 8, 0, 0, 0},
-       {AADD, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0},
-       {AADD, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0},
-       {AAND, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0},
-       {AAND, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0},
-       {AORR, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0},
-       {AORR, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0},
-       {AMVN, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0},
-       {ACMP, C_LCON, C_REG, C_NONE, 13, 8, 0, LFROM, 0},
-       {AMOVB, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
-       {AMOVBS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0},
-       {AMOVBU, C_REG, C_NONE, C_REG, 58, 4, 0, 0, 0},
-       {AMOVH, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
-       {AMOVHS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0},
-       {AMOVHU, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0},
-       {AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
-       {AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0},
-       {ADIV, C_REG, C_REG, C_REG, 16, 4, 0, 0, 0},
-       {ADIV, C_REG, C_NONE, C_REG, 16, 4, 0, 0, 0},
-       {ADIVHW, C_REG, C_REG, C_REG, 105, 4, 0, 0, 0},
-       {ADIVHW, C_REG, C_NONE, C_REG, 105, 4, 0, 0, 0},
-       {AMULL, C_REG, C_REG, C_REGREG, 17, 4, 0, 0, 0},
-       {ABFX, C_LCON, C_REG, C_REG, 18, 4, 0, 0, 0},  // width in From, LSB in From3
-       {ABFX, C_LCON, C_NONE, C_REG, 18, 4, 0, 0, 0}, // width in From, LSB in From3
-       {AMOVW, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
-       {AMOVW, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
-       {AMOVB, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
-       {AMOVB, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
-       {AMOVBS, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
-       {AMOVBS, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
-       {AMOVBU, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
-       {AMOVBU, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
-       {AMOVW, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
-       {AMOVW, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0},
-       {AMOVBU, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
-       {AMOVBU, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0},
-       {AXTAB, C_SHIFT, C_REG, C_REG, 22, 4, 0, 0, 0},
-       {AXTAB, C_SHIFT, C_NONE, C_REG, 22, 4, 0, 0, 0},
-       {AMOVW, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
-       {AMOVB, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
-       {AMOVBS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
-       {AMOVBU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
-       {AMOVH, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
-       {AMOVHS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
-       {AMOVHU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
-       {AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
-       {AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
-       {AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
-       {AMOVB, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
-       {AMOVB, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
-       {AMOVB, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
-       {AMOVBS, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
-       {AMOVBS, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
-       {AMOVBS, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
-       {AMOVBU, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
-       {AMOVBU, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
-       {AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
-       {AMOVW, C_TLS_LE, C_NONE, C_REG, 101, 4, 0, LFROM, 0},
-       {AMOVW, C_TLS_IE, C_NONE, C_REG, 102, 8, 0, LFROM, 0},
-       {AMOVW, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
-       {AMOVW, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
-       {AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4},
-       {AMOVBU, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
-       {AMOVBU, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
-       {AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4},
-       {AMOVW, C_LACON, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0},
-       {AMOVW, C_PSR, C_NONE, C_REG, 35, 4, 0, 0, 0},
-       {AMOVW, C_REG, C_NONE, C_PSR, 36, 4, 0, 0, 0},
-       {AMOVW, C_RCON, C_NONE, C_PSR, 37, 4, 0, 0, 0},
-       {AMOVM, C_REGLIST, C_NONE, C_SOREG, 38, 4, 0, 0, 0},
-       {AMOVM, C_SOREG, C_NONE, C_REGLIST, 39, 4, 0, 0, 0},
-       {ASWPW, C_SOREG, C_REG, C_REG, 40, 4, 0, 0, 0},
-       {ARFE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0},
-       {AMOVF, C_FREG, C_NONE, C_FAUTO, 50, 4, REGSP, 0, 0},
-       {AMOVF, C_FREG, C_NONE, C_FOREG, 50, 4, 0, 0, 0},
-       {AMOVF, C_FAUTO, C_NONE, C_FREG, 51, 4, REGSP, 0, 0},
-       {AMOVF, C_FOREG, C_NONE, C_FREG, 51, 4, 0, 0, 0},
-       {AMOVF, C_FREG, C_NONE, C_LAUTO, 52, 12, REGSP, LTO, 0},
-       {AMOVF, C_FREG, C_NONE, C_LOREG, 52, 12, 0, LTO, 0},
-       {AMOVF, C_LAUTO, C_NONE, C_FREG, 53, 12, REGSP, LFROM, 0},
-       {AMOVF, C_LOREG, C_NONE, C_FREG, 53, 12, 0, LFROM, 0},
-       {AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO | LPCREL, 4},
-       {AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM | LPCREL, 4},
-       {AADDF, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
-       {AADDF, C_FREG, C_FREG, C_FREG, 54, 4, 0, 0, 0},
-       {AMOVF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0},
-       {ANEGF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0},
-       {AMOVW, C_REG, C_NONE, C_FCR, 56, 4, 0, 0, 0},
-       {AMOVW, C_FCR, C_NONE, C_REG, 57, 4, 0, 0, 0},
-       {AMOVW, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0},
-       {AMOVBU, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0},
-       {AMOVB, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0},
-       {AMOVBS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0},
-       {AMOVH, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0},
-       {AMOVHS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0},
-       {AMOVHU, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0},
-       {AMOVW, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0},
-       {AMOVB, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0},
-       {AMOVBS, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0},
-       {AMOVBU, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0},
-       {AMOVH, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0},
-       {AMOVHS, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0},
-       {AMOVHU, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0},
-       {AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
-       {AMOVH, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0},
-       {AMOVHS, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
-       {AMOVHS, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0},
-       {AMOVHU, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
-       {AMOVHU, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0},
-       {AMOVB, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
-       {AMOVB, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
-       {AMOVBS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
-       {AMOVBS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
-       {AMOVH, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
-       {AMOVH, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
-       {AMOVHS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
-       {AMOVHS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
-       {AMOVHU, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
-       {AMOVHU, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
-       {AMOVH, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0},
-       {AMOVH, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0},
-       {AMOVH, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4},
-       {AMOVHS, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0},
-       {AMOVHS, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0},
-       {AMOVHS, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4},
-       {AMOVHU, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0},
-       {AMOVHU, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0},
-       {AMOVHU, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4},
-       {AMOVB, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
-       {AMOVB, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
-       {AMOVB, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
-       {AMOVBS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
-       {AMOVBS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
-       {AMOVBS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
-       {AMOVH, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
-       {AMOVH, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
-       {AMOVH, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
-       {AMOVHS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
-       {AMOVHS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
-       {AMOVHS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
-       {AMOVHU, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
-       {AMOVHU, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
-       {AMOVHU, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
-       {ALDREX, C_SOREG, C_NONE, C_REG, 77, 4, 0, 0, 0},
-       {ASTREX, C_SOREG, C_REG, C_REG, 78, 4, 0, 0, 0},
-       {AMOVF, C_ZFCON, C_NONE, C_FREG, 80, 8, 0, 0, 0},
-       {AMOVF, C_SFCON, C_NONE, C_FREG, 81, 4, 0, 0, 0},
-       {ACMPF, C_FREG, C_FREG, C_NONE, 82, 8, 0, 0, 0},
-       {ACMPF, C_FREG, C_NONE, C_NONE, 83, 8, 0, 0, 0},
-       {AMOVFW, C_FREG, C_NONE, C_FREG, 84, 4, 0, 0, 0},
-       {AMOVWF, C_FREG, C_NONE, C_FREG, 85, 4, 0, 0, 0},
-       {AMOVFW, C_FREG, C_NONE, C_REG, 86, 8, 0, 0, 0},
-       {AMOVWF, C_REG, C_NONE, C_FREG, 87, 8, 0, 0, 0},
-       {AMOVW, C_REG, C_NONE, C_FREG, 88, 4, 0, 0, 0},
-       {AMOVW, C_FREG, C_NONE, C_REG, 89, 4, 0, 0, 0},
-       {ALDREXD, C_SOREG, C_NONE, C_REG, 91, 4, 0, 0, 0},
-       {ASTREXD, C_SOREG, C_REG, C_REG, 92, 4, 0, 0, 0},
-       {APLD, C_SOREG, C_NONE, C_NONE, 95, 4, 0, 0, 0},
-       {obj.AUNDEF, C_NONE, C_NONE, C_NONE, 96, 4, 0, 0, 0},
-       {ACLZ, C_REG, C_NONE, C_REG, 97, 4, 0, 0, 0},
-       {AMULWT, C_REG, C_REG, C_REG, 98, 4, 0, 0, 0},
-       {AMULAWT, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0},
-       {obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0, 0, 0},
-       {obj.AFUNCDATA, C_LCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0},
-       {obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
-       {obj.ADUFFZERO, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as ABL
-       {obj.ADUFFCOPY, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as ABL
-
-       {ADATABUNDLE, C_NONE, C_NONE, C_NONE, 100, 4, 0, 0, 0},
-       {ADATABUNDLEEND, C_NONE, C_NONE, C_NONE, 100, 0, 0, 0, 0},
-       {obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0},
+       OPCODE, from, prog->reg, to, type, size, param, flag, extra data size, optional suffix */
+       {obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0, 0},
+       {AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT},
+       {AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
+       {AAND, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT},
+       {AAND, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
+       {AORR, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT},
+       {AORR, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
+       {AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
+       {AMVN, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
+       {ACMP, C_REG, C_REG, C_NONE, 1, 4, 0, 0, 0, 0},
+       {AADD, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT},
+       {AADD, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT},
+       {AAND, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT},
+       {AAND, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT},
+       {AORR, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT},
+       {AORR, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT},
+       {AMOVW, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, 0},
+       {AMVN, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, 0},
+       {ACMP, C_RCON, C_REG, C_NONE, 2, 4, 0, 0, 0, 0},
+       {AADD, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT},
+       {AADD, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
+       {AAND, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT},
+       {AAND, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
+       {AORR, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT},
+       {AORR, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
+       {AMVN, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
+       {ACMP, C_SHIFT, C_REG, C_NONE, 3, 4, 0, 0, 0, 0},
+       {AMOVW, C_RACON, C_NONE, C_REG, 4, 4, REGSP, 0, 0, C_SBIT},
+       {AB, C_NONE, C_NONE, C_SBRA, 5, 4, 0, LPOOL, 0, 0},
+       {ABL, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0},
+       {ABX, C_NONE, C_NONE, C_SBRA, 74, 20, 0, 0, 0, 0},
+       {ABEQ, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0},
+       {ABEQ, C_RCON, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, // prediction hinted form, hint ignored
+       {AB, C_NONE, C_NONE, C_ROREG, 6, 4, 0, LPOOL, 0, 0},
+       {ABL, C_NONE, C_NONE, C_ROREG, 7, 4, 0, 0, 0, 0},
+       {ABL, C_REG, C_NONE, C_ROREG, 7, 4, 0, 0, 0, 0},
+       {ABX, C_NONE, C_NONE, C_ROREG, 75, 12, 0, 0, 0, 0},
+       {ABXRET, C_NONE, C_NONE, C_ROREG, 76, 4, 0, 0, 0, 0},
+       {ASLL, C_RCON, C_REG, C_REG, 8, 4, 0, 0, 0, C_SBIT},
+       {ASLL, C_RCON, C_NONE, C_REG, 8, 4, 0, 0, 0, C_SBIT},
+       {ASLL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0, C_SBIT},
+       {ASLL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0, C_SBIT},
+       {ASWI, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0, 0},
+       {ASWI, C_NONE, C_NONE, C_LCON, 10, 4, 0, 0, 0, 0},
+       {AWORD, C_NONE, C_NONE, C_LCON, 11, 4, 0, 0, 0, 0},
+       {AWORD, C_NONE, C_NONE, C_LCONADDR, 11, 4, 0, 0, 0, 0},
+       {AWORD, C_NONE, C_NONE, C_ADDR, 11, 4, 0, 0, 0, 0},
+       {AWORD, C_NONE, C_NONE, C_TLS_LE, 103, 4, 0, 0, 0, 0},
+       {AWORD, C_NONE, C_NONE, C_TLS_IE, 104, 4, 0, 0, 0, 0},
+       {AMOVW, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0},
+       {AMOVW, C_SCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0},
+       {AMOVW, C_LCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0, 0},
+       {AMOVW, C_LCONADDR, C_NONE, C_REG, 12, 4, 0, LFROM | LPCREL, 4, 0},
+       {AMVN, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0},
+       {AADD, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
+       {AADD, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
+       {AAND, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
+       {AAND, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
+       {AORR, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
+       {AORR, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
+       {ACMP, C_NCON, C_REG, C_NONE, 13, 8, 0, 0, 0, 0},
+       {AADD, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
+       {AADD, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
+       {AAND, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
+       {AAND, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
+       {AORR, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
+       {AORR, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
+       {AMVN, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, 0},
+       {ACMP, C_SCON, C_REG, C_NONE, 13, 8, 0, 0, 0, 0},
+       {AADD, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0, 0},
+       {AADD, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0, 0},
+       {AORR, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0, 0},
+       {AORR, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0, 0},
+       {AADD, C_RCON2S, C_REG, C_REG, 107, 8, 0, 0, 0, 0},
+       {AADD, C_RCON2S, C_NONE, C_REG, 107, 8, 0, 0, 0, 0},
+       {AADD, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
+       {AADD, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
+       {AAND, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
+       {AAND, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
+       {AORR, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
+       {AORR, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
+       {AMVN, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, 0},
+       {ACMP, C_LCON, C_REG, C_NONE, 13, 8, 0, LFROM, 0, 0},
+       {AMOVB, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, 0},
+       {AMOVBS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0},
+       {AMOVBU, C_REG, C_NONE, C_REG, 58, 4, 0, 0, 0, 0},
+       {AMOVH, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, 0},
+       {AMOVHS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0},
+       {AMOVHU, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0},
+       {AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0, C_SBIT},
+       {AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0, C_SBIT},
+       {ADIV, C_REG, C_REG, C_REG, 16, 4, 0, 0, 0, 0},
+       {ADIV, C_REG, C_NONE, C_REG, 16, 4, 0, 0, 0, 0},
+       {ADIVHW, C_REG, C_REG, C_REG, 105, 4, 0, 0, 0, 0},
+       {ADIVHW, C_REG, C_NONE, C_REG, 105, 4, 0, 0, 0, 0},
+       {AMULL, C_REG, C_REG, C_REGREG, 17, 4, 0, 0, 0, C_SBIT},
+       {ABFX, C_LCON, C_REG, C_REG, 18, 4, 0, 0, 0, 0},  // width in From, LSB in From3
+       {ABFX, C_LCON, C_NONE, C_REG, 18, 4, 0, 0, 0, 0}, // width in From, LSB in From3
+       {AMOVW, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVW, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVB, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVB, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBS, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBS, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBU, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBU, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVW, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVW, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBU, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBU, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AXTAB, C_SHIFT, C_REG, C_REG, 22, 4, 0, 0, 0, 0},
+       {AXTAB, C_SHIFT, C_NONE, C_REG, 22, 4, 0, 0, 0, 0},
+       {AMOVW, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, C_SBIT},
+       {AMOVB, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
+       {AMOVBS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
+       {AMOVBU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
+       {AMOVH, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
+       {AMOVHS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
+       {AMOVHU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
+       {AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVB, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVB, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVB, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBS, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBS, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBS, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBU, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBU, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVW, C_TLS_LE, C_NONE, C_REG, 101, 4, 0, LFROM, 0, 0},
+       {AMOVW, C_TLS_IE, C_NONE, C_REG, 102, 8, 0, LFROM, 0, 0},
+       {AMOVW, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVW, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBU, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBU, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVW, C_LACON, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0, C_SBIT},
+       {AMOVW, C_PSR, C_NONE, C_REG, 35, 4, 0, 0, 0, 0},
+       {AMOVW, C_REG, C_NONE, C_PSR, 36, 4, 0, 0, 0, 0},
+       {AMOVW, C_RCON, C_NONE, C_PSR, 37, 4, 0, 0, 0, 0},
+       {AMOVM, C_REGLIST, C_NONE, C_SOREG, 38, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVM, C_SOREG, C_NONE, C_REGLIST, 39, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {ASWPW, C_SOREG, C_REG, C_REG, 40, 4, 0, 0, 0, 0},
+       {ARFE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0, 0},
+       {AMOVF, C_FREG, C_NONE, C_FAUTO, 50, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVF, C_FREG, C_NONE, C_FOREG, 50, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVF, C_FAUTO, C_NONE, C_FREG, 51, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVF, C_FOREG, C_NONE, C_FREG, 51, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVF, C_FREG, C_NONE, C_LAUTO, 52, 12, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVF, C_FREG, C_NONE, C_LOREG, 52, 12, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVF, C_LAUTO, C_NONE, C_FREG, 53, 12, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVF, C_LOREG, C_NONE, C_FREG, 53, 12, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
+       {AADDF, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0, 0},
+       {AADDF, C_FREG, C_FREG, C_FREG, 54, 4, 0, 0, 0, 0},
+       {AMOVF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0, 0},
+       {ANEGF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0, 0},
+       {AMOVW, C_REG, C_NONE, C_FCR, 56, 4, 0, 0, 0, 0},
+       {AMOVW, C_FCR, C_NONE, C_REG, 57, 4, 0, 0, 0, 0},
+       {AMOVW, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBU, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVB, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVH, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHU, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVW, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVB, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBS, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBU, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVH, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHS, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHU, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVH, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHS, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHS, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHU, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHU, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVB, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVB, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVH, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVH, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHU, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHU, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVH, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVH, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVH, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHS, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHS, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHS, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHU, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHU, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHU, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVB, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVB, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVB, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVBS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVH, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVH, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVH, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHU, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHU, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
+       {AMOVHU, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
+       {ALDREX, C_SOREG, C_NONE, C_REG, 77, 4, 0, 0, 0, 0},
+       {ASTREX, C_SOREG, C_REG, C_REG, 78, 4, 0, 0, 0, 0},
+       {AMOVF, C_ZFCON, C_NONE, C_FREG, 80, 8, 0, 0, 0, 0},
+       {AMOVF, C_SFCON, C_NONE, C_FREG, 81, 4, 0, 0, 0, 0},
+       {ACMPF, C_FREG, C_FREG, C_NONE, 82, 8, 0, 0, 0, 0},
+       {ACMPF, C_FREG, C_NONE, C_NONE, 83, 8, 0, 0, 0, 0},
+       {AMOVFW, C_FREG, C_NONE, C_FREG, 84, 4, 0, 0, 0, C_UBIT},
+       {AMOVWF, C_FREG, C_NONE, C_FREG, 85, 4, 0, 0, 0, C_UBIT},
+       {AMOVFW, C_FREG, C_NONE, C_REG, 86, 8, 0, 0, 0, C_UBIT},
+       {AMOVWF, C_REG, C_NONE, C_FREG, 87, 8, 0, 0, 0, C_UBIT},
+       {AMOVW, C_REG, C_NONE, C_FREG, 88, 4, 0, 0, 0, 0},
+       {AMOVW, C_FREG, C_NONE, C_REG, 89, 4, 0, 0, 0, 0},
+       {ALDREXD, C_SOREG, C_NONE, C_REG, 91, 4, 0, 0, 0, 0},
+       {ASTREXD, C_SOREG, C_REG, C_REG, 92, 4, 0, 0, 0, 0},
+       {APLD, C_SOREG, C_NONE, C_NONE, 95, 4, 0, 0, 0, 0},
+       {obj.AUNDEF, C_NONE, C_NONE, C_NONE, 96, 4, 0, 0, 0, 0},
+       {ACLZ, C_REG, C_NONE, C_REG, 97, 4, 0, 0, 0, 0},
+       {AMULWT, C_REG, C_REG, C_REG, 98, 4, 0, 0, 0, 0},
+       {AMULA, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0, C_SBIT},
+       {AMULAWT, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0, 0},
+       {obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0, 0, 0, 0},
+       {obj.AFUNCDATA, C_LCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0, 0},
+       {obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0},
+       {obj.ADUFFZERO, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, // same as ABL
+       {obj.ADUFFCOPY, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, // same as ABL
+       {ADATABUNDLE, C_NONE, C_NONE, C_NONE, 100, 4, 0, 0, 0, 0},
+       {ADATABUNDLEEND, C_NONE, C_NONE, C_NONE, 100, 0, 0, 0, 0, 0},
+       {obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0, 0},
 }
 
 var oprange [ALAST & obj.AMask][]Optab
@@ -618,61 +618,18 @@ func (c *ctxt5) asmoutnacl(origPC int32, p *obj.Prog, o *Optab, out []uint32) in
        return size
 }
 
-const (
-       T_SBIT = 1 << 0
-       T_PBIT = 1 << 1
-       T_WBIT = 1 << 2
-)
-
-var mayHaveSuffix = map[obj.As]uint8{
-       // bit logic
-       AAND: T_SBIT,
-       AEOR: T_SBIT,
-       AORR: T_SBIT,
-       ABIC: T_SBIT,
-       // arithmatic
-       ASUB: T_SBIT,
-       AADD: T_SBIT,
-       ASBC: T_SBIT,
-       AADC: T_SBIT,
-       ARSB: T_SBIT,
-       ARSC: T_SBIT,
-       // mov
-       AMVN:   T_SBIT,
-       AMOVW:  T_SBIT | T_PBIT | T_WBIT,
-       AMOVB:  T_SBIT | T_PBIT | T_WBIT,
-       AMOVBS: T_SBIT | T_PBIT | T_WBIT,
-       AMOVBU: T_SBIT | T_PBIT | T_WBIT,
-       AMOVH:  T_SBIT | T_PBIT | T_WBIT,
-       AMOVHS: T_SBIT | T_PBIT | T_WBIT,
-       AMOVHU: T_SBIT | T_PBIT | T_WBIT,
-       AMOVM:  T_PBIT | T_WBIT,
-       // shift
-       ASRL: T_SBIT,
-       ASRA: T_SBIT,
-       ASLL: T_SBIT,
-       // mul
-       AMUL:   T_SBIT,
-       AMULU:  T_SBIT,
-       AMULL:  T_SBIT,
-       AMULLU: T_SBIT,
-       // mula
-       AMULA:   T_SBIT,
-       AMULAL:  T_SBIT,
-       AMULALU: T_SBIT,
-       // MRC/MCR
-       AMRC: T_SBIT,
-}
-
-func checkBits(ctxt *obj.Link, p *obj.Prog) {
-       if p.Scond&C_SBIT != 0 && mayHaveSuffix[p.As]&T_SBIT == 0 {
-               ctxt.Diag("invalid .S suffix: %v", p)
+func checkSuffix(c *ctxt5, p *obj.Prog, o *Optab) {
+       if p.Scond&C_SBIT != 0 && o.scond&C_SBIT == 0 {
+               c.ctxt.Diag("invalid .S suffix: %v", p)
+       }
+       if p.Scond&C_PBIT != 0 && o.scond&C_PBIT == 0 {
+               c.ctxt.Diag("invalid .P suffix: %v", p)
        }
-       if p.Scond&C_PBIT != 0 && mayHaveSuffix[p.As]&T_PBIT == 0 {
-               ctxt.Diag("invalid .P suffix: %v", p)
+       if p.Scond&C_WBIT != 0 && o.scond&C_WBIT == 0 {
+               c.ctxt.Diag("invalid .W suffix: %v", p)
        }
-       if p.Scond&C_WBIT != 0 && mayHaveSuffix[p.As]&T_WBIT == 0 {
-               ctxt.Diag("invalid .W suffix: %v", p)
+       if p.Scond&C_UBIT != 0 && o.scond&C_UBIT == 0 {
+               c.ctxt.Diag("invalid .U suffix: %v", p)
        }
 }
 
@@ -755,8 +712,6 @@ func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                        c.flushpool(p, 0, 0)
                }
 
-               checkBits(ctxt, p)
-
                pc += int32(m)
        }
 
@@ -1423,6 +1378,7 @@ func (c *ctxt5) oplook(p *obj.Prog) *Optab {
                op := &ops[i]
                if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] {
                        p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
+                       checkSuffix(c, p, op)
                        return op
                }
        }
@@ -1717,7 +1673,6 @@ func buildop(ctxt *obj.Link) {
                case AMULAWT:
                        opset(AMULAWB, r0)
                        opset(AMULABB, r0)
-                       opset(AMULA, r0)
                        opset(AMULS, r0)
                        opset(AMMULA, r0)
                        opset(AMMULS, r0)
@@ -1742,6 +1697,7 @@ func buildop(ctxt *obj.Link) {
                        ASTREXD,
                        APLD,
                        AAND,
+                       AMULA,
                        obj.AUNDEF,
                        obj.AFUNCDATA,
                        obj.APCDATA,
@@ -2448,15 +2404,9 @@ func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) {
                }
 
        case 101: /* movw tlsvar,R, local exec*/
-               if p.Scond&C_SCOND != C_SCOND_NONE {
-                       c.ctxt.Diag("conditional tls")
-               }
                o1 = c.omvl(p, &p.From, int(p.To.Reg))
 
        case 102: /* movw tlsvar,R, initial exec*/
-               if p.Scond&C_SCOND != C_SCOND_NONE {
-                       c.ctxt.Diag("conditional tls")
-               }
                o1 = c.omvl(p, &p.From, int(p.To.Reg))
                o2 = c.olrr(int(p.To.Reg)&15, (REGPC & 15), int(p.To.Reg), int(p.Scond))
 
@@ -3177,9 +3127,6 @@ func (c *ctxt5) opbra(p *obj.Prog, a obj.As, sc int) uint32 {
 }
 
 func (c *ctxt5) olr(v int32, b int, r int, sc int) uint32 {
-       if sc&C_SBIT != 0 {
-               c.ctxt.Diag(".nil on LDR/STR instruction")
-       }
        o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
        if sc&C_PBIT == 0 {
                o |= 1 << 24
@@ -3209,9 +3156,6 @@ func (c *ctxt5) olr(v int32, b int, r int, sc int) uint32 {
 }
 
 func (c *ctxt5) olhr(v int32, b int, r int, sc int) uint32 {
-       if sc&C_SBIT != 0 {
-               c.ctxt.Diag(".nil on LDRH/STRH instruction")
-       }
        o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
        if sc&C_PBIT == 0 {
                o |= 1 << 24