cmd/asm: add new classification for index memory operands on PPC64

When a base+displacement kind of operand is given in an index-mode
instruction, the assembler does not flag it as an invalid instruction
causing the user to get an incorrect encoding of that instruction
leading to incorrect execution of the program.
Enable assembler to recognize valid and invalid operands used in index
mode instructions by classifying SOREG type into two further types
XOREG (used uniquely in index addressing mode instructions) and SOREG
for instructions working on base+displacement operands.
Also cleaned up usage of obj.Addr.Scale on PPC64.

Change-Id: Ib4d84343ae57477c6c074f44c4c2749496e11b91
Reviewed-on: https://go-review.googlesource.com/c/go/+/405542
Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Archana Ravindar <aravind5@in.ibm.com>
This commit is contained in:
Archana R 2022-05-11 10:48:48 -05:00 committed by Lynn Boger
parent 4381c61c58
commit 67d85ad00f
7 changed files with 268 additions and 68 deletions

View File

@ -473,7 +473,7 @@ var ppc64OperandTests = []operandTest{
{"(R4)", "(R4)"},
{"(R5)", "(R5)"},
{"(R5)(R6*1)", "(R5)(R6*1)"},
{"(R5+R6)", "(R5)(R6*1)"}, // Old syntax.
{"(R5+R6)", "(R5)(R6)"},
{"-1(R4)", "-1(R4)"},
{"-1(R5)", "-1(R5)"},
{"6(PC)", "6(PC)"},

View File

@ -975,13 +975,13 @@ func (p *Parser) registerIndirect(a *obj.Addr, prefix rune) {
return
}
if p.arch.Family == sys.PPC64 {
// Special form for PPC64: (R1+R2); alias for (R1)(R2*1).
// Special form for PPC64: (R1+R2); alias for (R1)(R2).
if prefix != 0 || scale != 0 {
p.errorf("illegal address mode for register+register")
return
}
a.Type = obj.TYPE_MEM
a.Scale = 1
a.Scale = 0
a.Index = r2
// Nothing may follow.
return
@ -1014,9 +1014,12 @@ func (p *Parser) registerIndirect(a *obj.Addr, prefix rune) {
p.errorf("unimplemented two-register form")
}
a.Index = r1
if scale != 0 && scale != 1 && p.arch.Family == sys.ARM64 {
if scale != 0 && scale != 1 && (p.arch.Family == sys.ARM64 ||
p.arch.Family == sys.PPC64) {
// Support (R1)(R2) (no scaling) and (R1)(R2*1).
p.errorf("arm64 doesn't support scaled register format")
if p.arch.Family != sys.PPC64 {
p.errorf("%s doesn't support scaled register format", p.arch.Name)
}
} else {
a.Scale = int16(scale)
}

View File

@ -8,6 +8,10 @@
#include "../../../../../runtime/textflag.h"
// In case of index mode instructions, usage of
// (Rx)(R0) is equivalent to (Rx+R0)
// In case of base+displacement mode instructions if
// the offset is 0, usage of (Rx) is equivalent to 0(Rx)
TEXT asmtest(SB),DUPOK|NOSPLIT,$0
// move constants
MOVD $1, R3 // 38600001
@ -26,58 +30,113 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
MOVW $1234567, R5 // 6405001260a5d687
MOVD 8(R3), R4 // e8830008
MOVD (R3)(R4), R5 // 7ca4182a
MOVD (R3)(R0), R5 // 7ca0182a
MOVD (R3), R5 // e8a30000
MOVW 4(R3), R4 // e8830006
MOVW (R3)(R4), R5 // 7ca41aaa
MOVW (R3)(R0), R5 // 7ca01aaa
MOVW (R3), R5 // e8a30002
MOVWZ 4(R3), R4 // 80830004
MOVWZ (R3)(R4), R5 // 7ca4182e
MOVWZ (R3)(R0), R5 // 7ca0182e
MOVWZ (R3), R5 // 80a30000
MOVH 4(R3), R4 // a8830004
MOVH (R3)(R4), R5 // 7ca41aae
MOVH (R3)(R0), R5 // 7ca01aae
MOVH (R3), R5 // a8a30000
MOVHZ 2(R3), R4 // a0830002
MOVHZ (R3)(R4), R5 // 7ca41a2e
MOVHZ (R3)(R0), R5 // 7ca01a2e
MOVHZ (R3), R5 // a0a30000
MOVB 1(R3), R4 // 888300017c840774
MOVB (R3)(R4), R5 // 7ca418ae7ca50774
MOVB (R3)(R0), R5 // 7ca018ae7ca50774
MOVB (R3), R5 // 88a300007ca50774
MOVBZ 1(R3), R4 // 88830001
MOVBZ (R3)(R4), R5 // 7ca418ae
MOVBZ (R3)(R0), R5 // 7ca018ae
MOVBZ (R3), R5 // 88a30000
MOVDBR (R3)(R4), R5 // 7ca41c28
MOVDBR (R3)(R0), R5 // 7ca01c28
MOVDBR (R3), R5 // 7ca01c28
MOVWBR (R3)(R4), R5 // 7ca41c2c
MOVWBR (R3)(R0), R5 // 7ca01c2c
MOVWBR (R3), R5 // 7ca01c2c
MOVHBR (R3)(R4), R5 // 7ca41e2c
MOVHBR (R3)(R0), R5 // 7ca01e2c
MOVHBR (R3), R5 // 7ca01e2c
MOVD $foo+4009806848(FP), R5 // 3ca1ef0138a5cc40
MOVD $foo(SB), R5 // 3ca0000038a50000
MOVDU 8(R3), R4 // e8830009
MOVDU (R3)(R4), R5 // 7ca4186a
MOVDU (R3)(R0), R5 // 7ca0186a
MOVDU (R3), R5 // e8a30001
MOVWU (R3)(R4), R5 // 7ca41aea
MOVWU (R3)(R0), R5 // 7ca01aea
MOVWZU 4(R3), R4 // 84830004
MOVWZU (R3)(R4), R5 // 7ca4186e
MOVWZU (R3)(R0), R5 // 7ca0186e
MOVWZU (R3), R5 // 84a30000
MOVHU 2(R3), R4 // ac830002
MOVHU (R3)(R4), R5 // 7ca41aee
MOVHU (R3)(R0), R5 // 7ca01aee
MOVHU (R3), R5 // aca30000
MOVHZU 2(R3), R4 // a4830002
MOVHZU (R3)(R4), R5 // 7ca41a6e
MOVHZU (R3)(R0), R5 // 7ca01a6e
MOVHZU (R3), R5 // a4a30000
MOVBU 1(R3), R4 // 8c8300017c840774
MOVBU (R3)(R4), R5 // 7ca418ee7ca50774
MOVBU (R3)(R0), R5 // 7ca018ee7ca50774
MOVBU (R3), R5 // 8ca300007ca50774
MOVBZU 1(R3), R4 // 8c830001
MOVBZU (R3)(R4), R5 // 7ca418ee
MOVBZU (R3)(R0), R5 // 7ca018ee
MOVBZU (R3), R5 // 8ca30000
MOVD R4, 8(R3) // f8830008
MOVD R5, (R3)(R4) // 7ca4192a
MOVD R5, (R3)(R0) // 7ca0192a
MOVD R5, (R3) // f8a30000
MOVW R4, 4(R3) // 90830004
MOVW R5, (R3)(R4) // 7ca4192e
MOVW R5, (R3)(R0) // 7ca0192e
MOVW R5, (R3) // 90a30000
MOVH R4, 2(R3) // b0830002
MOVH R5, (R3)(R4) // 7ca41b2e
MOVH R5, (R3)(R0) // 7ca01b2e
MOVH R5, (R3) // b0a30000
MOVB R4, 1(R3) // 98830001
MOVB R5, (R3)(R4) // 7ca419ae
MOVB R5, (R3)(R0) // 7ca019ae
MOVB R5, (R3) // 98a30000
MOVDBR R5, (R3)(R4) // 7ca41d28
MOVDBR R5, (R3)(R0) // 7ca01d28
MOVDBR R5, (R3) // 7ca01d28
MOVWBR R5, (R3)(R4) // 7ca41d2c
MOVWBR R5, (R3)(R0) // 7ca01d2c
MOVWBR R5, (R3) // 7ca01d2c
MOVHBR R5, (R3)(R4) // 7ca41f2c
MOVHBR R5, (R3)(R0) // 7ca01f2c
MOVHBR R5, (R3) // 7ca01f2c
MOVDU R4, 8(R3) // f8830009
MOVDU R5, (R3)(R4) // 7ca4196a
MOVDU R5, (R3)(R0) // 7ca0196a
MOVDU R5, (R3) // f8a30001
MOVWU R4, 4(R3) // 94830004
MOVWU R5, (R3)(R4) // 7ca4196e
MOVWU R5, (R3)(R0) // 7ca0196e
MOVHU R4, 2(R3) // b4830002
MOVHU R5, (R3)(R4) // 7ca41b6e
MOVHU R5, (R3)(R0) // 7ca01b6e
MOVHU R5, (R3) // b4a30000
MOVBU R4, 1(R3) // 9c830001
MOVBU R5, (R3)(R4) // 7ca419ee
MOVBU R5, (R3)(R0) // 7ca019ee
MOVBU R5, (R3) // 9ca30000
MOVB $0, R4 // 38800000
MOVBZ $0, R4 // 38800000
@ -372,23 +431,41 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
// load-and-reserve
LBAR (R4)(R3*1),$1,R5 // 7ca32069
LBAR (R4)(R0),$1,R5 // 7ca02069
LBAR (R4),$0,R5 // 7ca02068
LBAR (R3),R5 // 7ca01868
LHAR (R4)(R3*1),$1,R5 // 7ca320e9
LHAR (R4)(R0),$1,R5 // 7ca020e9
LHAR (R4),$0,R5 // 7ca020e8
LHAR (R3),R5 // 7ca018e8
LWAR (R4)(R3*1),$1,R5 // 7ca32029
LWAR (R4)(R0),$1,R5 // 7ca02029
LWAR (R4),$0,R5 // 7ca02028
LWAR (R3),R5 // 7ca01828
LDAR (R4)(R3*1),$1,R5 // 7ca320a9
LDAR (R4)(R0),$1,R5 // 7ca020a9
LDAR (R4),$0,R5 // 7ca020a8
LDAR (R3),R5 // 7ca018a8
LSW (R3)(R4), R5 // 7ca41c2a
LSW (R3)(R0), R5 // 7ca01c2a
LSW (R3), R5 // 7ca01c2a
STBCCC R3, (R4)(R5) // 7c65256d
STBCCC R3, (R4)(R0) // 7c60256d
STBCCC R3, (R4) // 7c60256d
STWCCC R3, (R4)(R5) // 7c65212d
STWCCC R3, (R4)(R0) // 7c60212d
STWCCC R3, (R4) // 7c60212d
STDCCC R3, (R4)(R5) // 7c6521ad
STHCCC R3, (R4)(R5)
STSW R3, (R4)(R5)
STDCCC R3, (R4)(R0) // 7c6021ad
STDCCC R3, (R4) // 7c6021ad
STHCCC R3, (R4)(R5) // 7c6525ad
STHCCC R3, (R4)(R0) // 7c6025ad
STHCCC R3, (R4) // 7c6025ad
STSW R3, (R4)(R5) // 7c65252a
STSW R3, (R4)(R0) // 7c60252a
STSW R3, (R4) // 7c60252a
SYNC // 7c0004ac
ISYNC // 4c00012c
@ -397,11 +474,21 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
DARN $1, R5 // 7ca105e6
DCBF (R3)(R4) // 7c0418ac
DCBI (R3)(R4) // 7c041bac
DCBF (R3)(R0) // 7c0018ac
DCBF (R3) // 7c0018ac
DCBST (R3)(R4) // 7c04186c
DCBST (R3)(R0) // 7c00186c
DCBST (R3) // 7c00186c
DCBZ (R3)(R4) // 7c041fec
DCBZ (R3)(R0) // 7c001fec
DCBZ (R3) // 7c001fec
DCBT (R3)(R4) // 7c041a2c
DCBT (R3)(R0) // 7c001a2c
DCBT (R3) // 7c001a2c
ICBI (R3)(R4) // 7c041fac
ICBI (R3)(R0) // 7c001fac
ICBI (R3) // 7c001fac
// float constants
FMOVD $(0.0), F1 // f0210cd0
@ -409,21 +496,46 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
FMOVD 8(R3), F1 // c8230008
FMOVD (R3)(R4), F1 // 7c241cae
FMOVD (R3)(R0), F1 // 7c201cae
FMOVD (R3), F1 // c8230000
FMOVDU 8(R3), F1 // cc230008
FMOVDU (R3)(R4), F1 // 7c241cee
FMOVDU (R3)(R0), F1 // 7c201cee
FMOVDU (R3), F1 // cc230000
FMOVS 4(R3), F1 // c0230004
FMOVS (R3)(R4), F1 // 7c241c2e
FMOVS (R3)(R0), F1 // 7c201c2e
FMOVS (R3), F1 // c0230000
FMOVSU 4(R3), F1 // c4230004
FMOVSU (R3)(R4), F1 // 7c241c6e
FMOVSU (R3)(R0), F1 // 7c201c6e
FMOVSU (R3), F1 // c4230000
FMOVSX (R3)(R4), F1 // 7c241eae
FMOVSX (R3)(R0), F1 // 7c201eae
FMOVSX (R3), F1 // 7c201eae
FMOVSZ (R3)(R4), F1 // 7c241eee
FMOVSZ (R3)(R0), F1 // 7c201eee
FMOVSZ (R3), F1 // 7c201eee
FMOVD F1, 8(R3) // d8230008
FMOVD F1, (R3)(R4) // 7c241dae
FMOVD F1, (R3)(R0) // 7c201dae
FMOVD F1, (R3) // d8230000
FMOVDU F1, 8(R3) // dc230008
FMOVDU F1, (R3)(R4) // 7c241dee
FMOVDU F1, (R3)(R0) // 7c201dee
FMOVDU F1, (R3) // dc230000
FMOVS F1, 4(R3) // d0230004
FMOVS F1, (R3)(R4) // 7c241d2e
FMOVS F1, (R3)(R0) // 7c201d2e
FMOVS F1, (R3) // d0230000
FMOVSU F1, 4(R3) // d4230004
FMOVSU F1, (R3)(R4) // 7c241d6e
FMOVSU F1, (R3)(R0) // 7c201d6e
FMOVSU F1, (R3) // d4230000
FMOVSX F1, (R3)(R4) // 7c241fae
FMOVSX F1, (R3)(R0) // 7c201fae
FMOVSX F1, (R3) // 7c201fae
FADD F1, F2 // fc42082a
FADD F1, F2, F3 // fc62082a
FADDCC F1, F2, F3 // fc62082b
@ -507,17 +619,41 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
FCMPO F1, F2 // fc011040
FCMPU F1, F2 // fc011000
LVX (R3)(R4), V1 // 7c2418ce
LVX (R3)(R0), V1 // 7c2018ce
LVX (R3), V1 // 7c2018ce
LVXL (R3)(R4), V1 // 7c241ace
LVXL (R3)(R0), V1 // 7c201ace
LVXL (R3), V1 // 7c201ace
LVSL (R3)(R4), V1 // 7c24180c
LVSL (R3)(R0), V1 // 7c20180c
LVSL (R3), V1 // 7c20180c
LVSR (R3)(R4), V1 // 7c24184c
LVSR (R3)(R0), V1 // 7c20184c
LVSR (R3), V1 // 7c20184c
LVEBX (R3)(R4), V1 // 7c24180e
LVEBX (R3)(R0), V1 // 7c20180e
LVEBX (R3), V1 // 7c20180e
LVEHX (R3)(R4), V1 // 7c24184e
LVEHX (R3)(R0), V1 // 7c20184e
LVEHX (R3), V1 // 7c20184e
LVEWX (R3)(R4), V1 // 7c24188e
LVEWX (R3)(R0), V1 // 7c20188e
LVEWX (R3), V1 // 7c20188e
STVX V1, (R3)(R4) // 7c2419ce
STVX V1, (R3)(R0) // 7c2019ce
STVX V1, (R3) // 7c2019ce
STVXL V1, (R3)(R4) // 7c241bce
STVXL V1, (R3)(R0) // 7c201bce
STVXL V1, (R3) // 7c201bce
STVEBX V1, (R3)(R4) // 7c24190e
STVEBX V1, (R3)(R0) // 7c20190e
STVEBX V1, (R3) // 7c20190e
STVEHX V1, (R3)(R4) // 7c24194e
STVEHX V1, (R3)(R0) // 7c20194e
STVEHX V1, (R3) // 7c20194e
STVEWX V1, (R3)(R4) // 7c24198e
STVEWX V1, (R3)(R0) // 7c20198e
STVEWX V1, (R3) // 7c20198e
VAND V1, V2, V3 // 10611404
VANDC V1, V2, V3 // 10611444
@ -651,28 +787,55 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
VSHASIGMAD $2, V1, $15, V2 // 104196c2
LXVD2X (R3)(R4), VS1 // 7c241e98
LXVD2X (R3)(R0), VS1 // 7c201e98
LXVD2X (R3), VS1 // 7c201e98
LXVDSX (R3)(R4), VS1 // 7c241a98
LXVDSX (R3)(R0), VS1 // 7c201a98
LXVDSX (R3), VS1 // 7c201a98
LXVH8X (R3)(R4), VS1 // 7c241e58
LXVH8X (R3)(R0), VS1 // 7c201e58
LXVH8X (R3), VS1 // 7c201e58
LXVB16X (R3)(R4), VS1 // 7c241ed8
LXVB16X (R3)(R0), VS1 // 7c201ed8
LXVB16X (R3), VS1 // 7c201ed8
LXVW4X (R3)(R4), VS1 // 7c241e18
LXVW4X (R3)(R0), VS1 // 7c201e18
LXVW4X (R3), VS1 // 7c201e18
LXV 16(R3), VS1 // f4230011
LXV (R3), VS1 // f4230001
LXV 16(R3), VS33 // f4230019
LXV (R3), VS33 // f4230009
LXV 16(R3), V1 // f4230019
LXV (R3), V1 // f4230009
LXVL R3, R4, VS1 // 7c23221a
LXVLL R3, R4, VS1 // 7c23225a
LXVX R3, R4, VS1 // 7c232218
LXSDX (R3)(R4), VS1 // 7c241c98
LXSDX (R3)(R0), VS1 // 7c201c98
LXSDX (R3), VS1 // 7c201c98
STXVD2X VS1, (R3)(R4) // 7c241f98
STXVD2X VS1, (R3)(R0) // 7c201f98
STXVD2X VS1, (R3) // 7c201f98
STXV VS1,16(R3) // f4230015
STXV VS1,(R3) // f4230005
STXVL VS1, R3, R4 // 7c23231a
STXVLL VS1, R3, R4 // 7c23235a
STXVX VS1, R3, R4 // 7c232318
STXVB16X VS1, (R4)(R5) // 7c2527d8
STXVB16X VS1, (R4)(R0) // 7c2027d8
STXVB16X VS1, (R4) // 7c2027d8
STXVH8X VS1, (R4)(R5) // 7c252758
STXVH8X VS1, (R4)(R0) // 7c202758
STXVH8X VS1, (R4) // 7c202758
STXSDX VS1, (R3)(R4) // 7c241d98
STXSDX VS1, (R4)(R0) // 7c202598
STXSDX VS1, (R4) // 7c202598
LXSIWAX (R3)(R4), VS1 // 7c241898
LXSIWAX (R3)(R0), VS1 // 7c201898
LXSIWAX (R3), VS1 // 7c201898
STXSIWX VS1, (R3)(R4) // 7c241918
STXSIWX VS1, (R3)(R0) // 7c201918
STXSIWX VS1, (R3) // 7c201918
MFVSRD VS1, R3 // 7c230066
MTFPRD R3, F0 // 7c030166
MFVRD V0, R3 // 7c030067

View File

@ -419,9 +419,10 @@ const (
C_SBRA /* A short offset argument to a branching instruction */
C_LBRA /* A long offset argument to a branching instruction */
C_LBRAPIC /* Like C_LBRA, but requires an extra NOP for potential TOC restore by the linker. */
C_ZOREG /* An reg+reg memory arg, or a $0+reg memory op */
C_ZOREG /* An $0+reg memory op */
C_SOREG /* An $n+reg memory arg where n is a 16 bit signed offset */
C_LOREG /* An $n+reg memory arg where n is a 32 bit signed offset */
C_XOREG /* An reg+reg memory arg */
C_FPSCR /* The fpscr register */
C_XER /* The xer, holds the carry bit */
C_LR /* The link register */

View File

@ -39,6 +39,7 @@ var cnames9 = []string{
"ZOREG",
"SOREG",
"LOREG",
"XOREG",
"FPSCR",
"XER",
"LR",

View File

@ -197,28 +197,36 @@ var optab = []Optab{
{as: AFMUL, a1: C_FREG, a2: C_FREG, a6: C_FREG, type_: 32, size: 4},
{as: AMOVBU, a1: C_REG, a6: C_SOREG, type_: 7, size: 4},
{as: AMOVBU, a1: C_REG, a6: C_XOREG, type_: 108, size: 4},
{as: AMOVBU, a1: C_SOREG, a6: C_REG, type_: 8, size: 8},
{as: AMOVBU, a1: C_XOREG, a6: C_REG, type_: 109, size: 8},
{as: AMOVBZU, a1: C_REG, a6: C_SOREG, type_: 7, size: 4},
{as: AMOVBZU, a1: C_REG, a6: C_XOREG, type_: 108, size: 4},
{as: AMOVBZU, a1: C_SOREG, a6: C_REG, type_: 8, size: 4},
{as: AMOVBZU, a1: C_XOREG, a6: C_REG, type_: 109, size: 4},
{as: AMOVHBR, a1: C_REG, a6: C_ZOREG, type_: 44, size: 4},
{as: AMOVHBR, a1: C_ZOREG, a6: C_REG, type_: 45, size: 4},
{as: AMOVHBR, a1: C_REG, a6: C_XOREG, type_: 44, size: 4},
{as: AMOVHBR, a1: C_XOREG, a6: C_REG, type_: 45, size: 4},
{as: AMOVB, a1: C_ADDR, a6: C_REG, type_: 75, size: 12},
{as: AMOVB, a1: C_LOREG, a6: C_REG, type_: 36, size: 12},
{as: AMOVB, a1: C_SOREG, a6: C_REG, type_: 8, size: 8},
{as: AMOVB, a1: C_XOREG, a6: C_REG, type_: 109, size: 8},
{as: AMOVB, a1: C_REG, a6: C_ADDR, type_: 74, size: 8},
{as: AMOVB, a1: C_REG, a6: C_SOREG, type_: 7, size: 4},
{as: AMOVB, a1: C_REG, a6: C_LOREG, type_: 35, size: 8},
{as: AMOVB, a1: C_REG, a6: C_XOREG, type_: 108, size: 4},
{as: AMOVB, a1: C_REG, a6: C_REG, type_: 13, size: 4},
{as: AMOVBZ, a1: C_ADDR, a6: C_REG, type_: 75, size: 8},
{as: AMOVBZ, a1: C_LOREG, a6: C_REG, type_: 36, size: 8},
{as: AMOVBZ, a1: C_SOREG, a6: C_REG, type_: 8, size: 4},
{as: AMOVBZ, a1: C_XOREG, a6: C_REG, type_: 109, size: 4},
{as: AMOVBZ, a1: C_REG, a6: C_ADDR, type_: 74, size: 8},
{as: AMOVBZ, a1: C_REG, a6: C_SOREG, type_: 7, size: 4},
{as: AMOVBZ, a1: C_REG, a6: C_LOREG, type_: 35, size: 8},
{as: AMOVBZ, a1: C_REG, a6: C_XOREG, type_: 108, size: 4},
{as: AMOVBZ, a1: C_REG, a6: C_REG, type_: 13, size: 4},
{as: AMOVD, a1: C_ADDCON, a6: C_REG, type_: 3, size: 4},
@ -229,6 +237,7 @@ var optab = []Optab{
{as: AMOVD, a1: C_LACON, a6: C_REG, type_: 26, size: 8},
{as: AMOVD, a1: C_ADDR, a6: C_REG, type_: 75, size: 8},
{as: AMOVD, a1: C_SOREG, a6: C_REG, type_: 8, size: 4},
{as: AMOVD, a1: C_XOREG, a6: C_REG, type_: 109, size: 4},
{as: AMOVD, a1: C_SOREG, a6: C_SPR, type_: 107, size: 8},
{as: AMOVD, a1: C_LOREG, a6: C_REG, type_: 36, size: 8},
{as: AMOVD, a1: C_TLS_LE, a6: C_REG, type_: 79, size: 8},
@ -236,6 +245,7 @@ var optab = []Optab{
{as: AMOVD, a1: C_SPR, a6: C_REG, type_: 66, size: 4},
{as: AMOVD, a1: C_REG, a6: C_ADDR, type_: 74, size: 8},
{as: AMOVD, a1: C_REG, a6: C_SOREG, type_: 7, size: 4},
{as: AMOVD, a1: C_REG, a6: C_XOREG, type_: 108, size: 4},
{as: AMOVD, a1: C_SPR, a6: C_SOREG, type_: 106, size: 8},
{as: AMOVD, a1: C_REG, a6: C_LOREG, type_: 35, size: 8},
{as: AMOVD, a1: C_REG, a6: C_SPR, type_: 66, size: 4},
@ -251,28 +261,33 @@ var optab = []Optab{
{as: AMOVW, a1: C_CREG, a6: C_REG, type_: 68, size: 4},
{as: AMOVW, a1: C_SOREG, a6: C_REG, type_: 8, size: 4},
{as: AMOVW, a1: C_LOREG, a6: C_REG, type_: 36, size: 8},
{as: AMOVW, a1: C_XOREG, a6: C_REG, type_: 109, size: 4},
{as: AMOVW, a1: C_SPR, a6: C_REG, type_: 66, size: 4},
{as: AMOVW, a1: C_REG, a6: C_ADDR, type_: 74, size: 8},
{as: AMOVW, a1: C_REG, a6: C_CREG, type_: 69, size: 4},
{as: AMOVW, a1: C_REG, a6: C_SOREG, type_: 7, size: 4},
{as: AMOVW, a1: C_REG, a6: C_LOREG, type_: 35, size: 8},
{as: AMOVW, a1: C_REG, a6: C_XOREG, type_: 108, size: 4},
{as: AMOVW, a1: C_REG, a6: C_SPR, type_: 66, size: 4},
{as: AMOVW, a1: C_REG, a6: C_REG, type_: 13, size: 4},
{as: AFMOVD, a1: C_ADDCON, a6: C_FREG, type_: 24, size: 8},
{as: AFMOVD, a1: C_SOREG, a6: C_FREG, type_: 8, size: 4},
{as: AFMOVD, a1: C_XOREG, a6: C_FREG, type_: 109, size: 4},
{as: AFMOVD, a1: C_LOREG, a6: C_FREG, type_: 36, size: 8},
{as: AFMOVD, a1: C_ZCON, a6: C_FREG, type_: 24, size: 4},
{as: AFMOVD, a1: C_ADDR, a6: C_FREG, type_: 75, size: 8},
{as: AFMOVD, a1: C_FREG, a6: C_FREG, type_: 33, size: 4},
{as: AFMOVD, a1: C_FREG, a6: C_SOREG, type_: 7, size: 4},
{as: AFMOVD, a1: C_FREG, a6: C_XOREG, type_: 108, size: 4},
{as: AFMOVD, a1: C_FREG, a6: C_LOREG, type_: 35, size: 8},
{as: AFMOVD, a1: C_FREG, a6: C_ADDR, type_: 74, size: 8},
{as: AFMOVSX, a1: C_ZOREG, a6: C_FREG, type_: 45, size: 4},
{as: AFMOVSX, a1: C_FREG, a6: C_ZOREG, type_: 44, size: 4},
{as: AFMOVSX, a1: C_XOREG, a6: C_FREG, type_: 45, size: 4},
{as: AFMOVSX, a1: C_FREG, a6: C_XOREG, type_: 44, size: 4},
{as: AFMOVSZ, a1: C_ZOREG, a6: C_FREG, type_: 45, size: 4},
{as: AFMOVSZ, a1: C_XOREG, a6: C_FREG, type_: 45, size: 4},
{as: AMOVFL, a1: C_CREG, a6: C_CREG, type_: 67, size: 4},
{as: AMOVFL, a1: C_FPSCR, a6: C_CREG, type_: 73, size: 4},
@ -325,7 +340,7 @@ var optab = []Optab{
{as: AFTSQRT, a1: C_FREG, a6: C_SCON, type_: 93, size: 4}, /* floating test for sw square root, x-form */
{as: ACOPY, a1: C_REG, a6: C_REG, type_: 92, size: 4}, /* copy/paste facility, x-form */
{as: ADARN, a1: C_SCON, a6: C_REG, type_: 92, size: 4}, /* deliver random number, x-form */
{as: ALDMX, a1: C_SOREG, a6: C_REG, type_: 45, size: 4}, /* load doubleword monitored, x-form */
{as: ALDMX, a1: C_XOREG, a6: C_REG, type_: 45, size: 4}, /* load doubleword monitored, x-form */
{as: AMADDHD, a1: C_REG, a2: C_REG, a3: C_REG, a6: C_REG, type_: 83, size: 4}, /* multiply-add high/low doubleword, va-form */
{as: AADDEX, a1: C_REG, a2: C_REG, a3: C_SCON, a6: C_REG, type_: 94, size: 4}, /* add extended using alternate carry, z23-form */
{as: ACRAND, a1: C_CRBIT, a2: C_CRBIT, a6: C_CRBIT, type_: 2, size: 4}, /* logical ops for condition register bits xl-form */
@ -333,10 +348,10 @@ var optab = []Optab{
/* Vector instructions */
/* Vector load */
{as: ALV, a1: C_SOREG, a6: C_VREG, type_: 45, size: 4}, /* vector load, x-form */
{as: ALV, a1: C_XOREG, a6: C_VREG, type_: 45, size: 4}, /* vector load, x-form */
/* Vector store */
{as: ASTV, a1: C_VREG, a6: C_SOREG, type_: 44, size: 4}, /* vector store, x-form */
{as: ASTV, a1: C_VREG, a6: C_XOREG, type_: 44, size: 4}, /* vector store, x-form */
/* Vector logical */
{as: AVAND, a1: C_VREG, a2: C_VREG, a6: C_VREG, type_: 82, size: 4}, /* vector and, vx-form */
@ -405,26 +420,26 @@ var optab = []Optab{
{as: AVSHASIGMA, a1: C_ANDCON, a2: C_VREG, a3: C_ANDCON, a6: C_VREG, type_: 82, size: 4}, /* vector SHA sigma, vx-form */
/* VSX vector load */
{as: ALXVD2X, a1: C_SOREG, a6: C_VSREG, type_: 87, size: 4}, /* vsx vector load, xx1-form */
{as: ALXVD2X, a1: C_XOREG, a6: C_VSREG, type_: 87, size: 4}, /* vsx vector load, xx1-form */
{as: ALXV, a1: C_SOREG, a6: C_VSREG, type_: 96, size: 4}, /* vsx vector load, dq-form */
{as: ALXVL, a1: C_REG, a2: C_REG, a6: C_VSREG, type_: 98, size: 4}, /* vsx vector load length */
/* VSX vector store */
{as: ASTXVD2X, a1: C_VSREG, a6: C_SOREG, type_: 86, size: 4}, /* vsx vector store, xx1-form */
{as: ASTXVD2X, a1: C_VSREG, a6: C_XOREG, type_: 86, size: 4}, /* vsx vector store, xx1-form */
{as: ASTXV, a1: C_VSREG, a6: C_SOREG, type_: 97, size: 4}, /* vsx vector store, dq-form */
{as: ASTXVL, a1: C_VSREG, a2: C_REG, a6: C_REG, type_: 99, size: 4}, /* vsx vector store with length x-form */
/* VSX scalar load */
{as: ALXSDX, a1: C_SOREG, a6: C_VSREG, type_: 87, size: 4}, /* vsx scalar load, xx1-form */
{as: ALXSDX, a1: C_XOREG, a6: C_VSREG, type_: 87, size: 4}, /* vsx scalar load, xx1-form */
/* VSX scalar store */
{as: ASTXSDX, a1: C_VSREG, a6: C_SOREG, type_: 86, size: 4}, /* vsx scalar store, xx1-form */
{as: ASTXSDX, a1: C_VSREG, a6: C_XOREG, type_: 86, size: 4}, /* vsx scalar store, xx1-form */
/* VSX scalar as integer load */
{as: ALXSIWAX, a1: C_SOREG, a6: C_VSREG, type_: 87, size: 4}, /* vsx scalar as integer load, xx1-form */
{as: ALXSIWAX, a1: C_XOREG, a6: C_VSREG, type_: 87, size: 4}, /* vsx scalar as integer load, xx1-form */
/* VSX scalar store as integer */
{as: ASTXSIWX, a1: C_VSREG, a6: C_SOREG, type_: 86, size: 4}, /* vsx scalar as integer store, xx1-form */
{as: ASTXSIWX, a1: C_VSREG, a6: C_XOREG, type_: 86, size: 4}, /* vsx scalar as integer store, xx1-form */
/* VSX move from VSR */
{as: AMFVSRD, a1: C_VSREG, a6: C_REG, type_: 88, size: 4},
@ -488,24 +503,25 @@ var optab = []Optab{
{as: AFCMPO, a1: C_FREG, a2: C_CREG, a6: C_FREG, type_: 70, size: 4},
{as: ATW, a1: C_LCON, a2: C_REG, a6: C_REG, type_: 60, size: 4},
{as: ATW, a1: C_LCON, a2: C_REG, a6: C_ADDCON, type_: 61, size: 4},
{as: ADCBF, a1: C_ZOREG, type_: 43, size: 4},
{as: ADCBF, a1: C_SOREG, type_: 43, size: 4},
{as: ADCBF, a1: C_ZOREG, a2: C_REG, a6: C_SCON, type_: 43, size: 4},
{as: ADCBF, a1: C_XOREG, type_: 43, size: 4},
{as: ADCBF, a1: C_XOREG, a2: C_REG, a6: C_SCON, type_: 43, size: 4},
{as: ADCBF, a1: C_SOREG, a6: C_SCON, type_: 43, size: 4},
{as: AECOWX, a1: C_REG, a2: C_REG, a6: C_ZOREG, type_: 44, size: 4},
{as: AECIWX, a1: C_ZOREG, a2: C_REG, a6: C_REG, type_: 45, size: 4},
{as: AECOWX, a1: C_REG, a6: C_ZOREG, type_: 44, size: 4},
{as: AECIWX, a1: C_ZOREG, a6: C_REG, type_: 45, size: 4},
{as: ALDAR, a1: C_ZOREG, a6: C_REG, type_: 45, size: 4},
{as: ALDAR, a1: C_ZOREG, a3: C_ANDCON, a6: C_REG, type_: 45, size: 4},
{as: ADCBF, a1: C_XOREG, a6: C_SCON, type_: 43, size: 4},
{as: AECOWX, a1: C_REG, a2: C_REG, a6: C_XOREG, type_: 44, size: 4},
{as: AECIWX, a1: C_XOREG, a2: C_REG, a6: C_REG, type_: 45, size: 4},
{as: AECOWX, a1: C_REG, a6: C_XOREG, type_: 44, size: 4},
{as: AECIWX, a1: C_XOREG, a6: C_REG, type_: 45, size: 4},
{as: ALDAR, a1: C_XOREG, a6: C_REG, type_: 45, size: 4},
{as: ALDAR, a1: C_XOREG, a3: C_ANDCON, a6: C_REG, type_: 45, size: 4},
{as: AEIEIO, type_: 46, size: 4},
{as: ATLBIE, a1: C_REG, type_: 49, size: 4},
{as: ATLBIE, a1: C_SCON, a6: C_REG, type_: 49, size: 4},
{as: ASLBMFEE, a1: C_REG, a6: C_REG, type_: 55, size: 4},
{as: ASLBMTE, a1: C_REG, a6: C_REG, type_: 55, size: 4},
{as: ASTSW, a1: C_REG, a6: C_ZOREG, type_: 44, size: 4},
{as: ASTSW, a1: C_REG, a6: C_XOREG, type_: 44, size: 4},
{as: ASTSW, a1: C_REG, a3: C_LCON, a6: C_ZOREG, type_: 41, size: 4},
{as: ALSW, a1: C_ZOREG, a6: C_REG, type_: 45, size: 4},
{as: ALSW, a1: C_XOREG, a6: C_REG, type_: 45, size: 4},
{as: ALSW, a1: C_ZOREG, a3: C_LCON, a6: C_REG, type_: 42, size: 4},
{as: APNOP, type_: 105, size: 8, ispfx: true},
@ -583,7 +599,7 @@ func (c *ctxt9) getimpliedreg(a *obj.Addr, p *obj.Prog) int {
switch class {
case C_SACON, C_LACON:
return REGSP
case C_LOREG, C_SOREG, C_ZOREG:
case C_LOREG, C_SOREG, C_ZOREG, C_XOREG:
switch a.Name {
case obj.NAME_EXTERN, obj.NAME_STATIC:
return REGSB
@ -881,6 +897,13 @@ func (c *ctxt9) aclass(a *obj.Addr) int {
return c.aclassreg(a.Reg)
case obj.TYPE_MEM:
if a.Index != 0 {
if a.Name != obj.NAME_NONE || a.Offset != 0 {
c.ctxt.Logf("Unexpected Instruction operand index %d offset %d class %d \n", a.Index, a.Offset, a.Class)
}
return C_XOREG
}
switch a.Name {
case obj.NAME_GOTREF, obj.NAME_TOCREF:
return C_ADDR
@ -903,6 +926,7 @@ func (c *ctxt9) aclass(a *obj.Addr) int {
case obj.NAME_AUTO:
c.instoffset = int64(c.autosize) + a.Offset
if c.instoffset >= -BIG && c.instoffset < BIG {
return C_SOREG
}
@ -917,13 +941,13 @@ func (c *ctxt9) aclass(a *obj.Addr) int {
case obj.NAME_NONE:
c.instoffset = a.Offset
if c.instoffset == 0 {
if a.Offset == 0 && a.Index == 0 {
return C_ZOREG
}
if c.instoffset >= -BIG && c.instoffset < BIG {
} else if c.instoffset >= -BIG && c.instoffset < BIG {
return C_SOREG
} else {
return C_LOREG
}
return C_LOREG
}
return C_GOK
@ -1160,6 +1184,9 @@ func cmp(a int, b int) bool {
case C_LOREG:
return cmp(C_SOREG, b)
case C_XOREG:
return cmp(C_REG, b) || cmp(C_ZOREG, b)
// An even/odd register input always matches the regular register types.
case C_REG:
return cmp(C_REGP, b) || (b == C_ZCON && r0iszero != 0)
@ -2562,22 +2589,15 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
r = c.getimpliedreg(&p.To, p)
}
v := c.regoff(&p.To)
if p.To.Type == obj.TYPE_MEM && p.To.Index != 0 {
if v != 0 {
c.ctxt.Diag("illegal indexed instruction\n%v", p)
}
o1 = AOP_RRR(c.opstorex(p.As), uint32(p.From.Reg), uint32(p.To.Index), uint32(r))
} else {
if int32(int16(v)) != v {
log.Fatalf("mishandled instruction %v", p)
}
// Offsets in DS form stores must be a multiple of 4
inst := c.opstore(p.As)
if c.opform(inst) == DS_FORM && v&0x3 != 0 {
log.Fatalf("invalid offset for DS form load/store %v", p)
}
o1 = AOP_IRR(inst, uint32(p.From.Reg), uint32(r), uint32(v))
if int32(int16(v)) != v {
log.Fatalf("mishandled instruction %v", p)
}
// Offsets in DS form stores must be a multiple of 4
inst := c.opstore(p.As)
if c.opform(inst) == DS_FORM && v&0x3 != 0 {
log.Fatalf("invalid offset for DS form load/store %v", p)
}
o1 = AOP_IRR(inst, uint32(p.From.Reg), uint32(r), uint32(v))
case 8: /* mov soreg, r ==> lbz/lhz/lwz o(r), lbz o(r) + extsb r,r */
r := int(p.From.Reg)
@ -2586,22 +2606,15 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
r = c.getimpliedreg(&p.From, p)
}
v := c.regoff(&p.From)
if p.From.Type == obj.TYPE_MEM && p.From.Index != 0 {
if v != 0 {
c.ctxt.Diag("illegal indexed instruction\n%v", p)
}
o1 = AOP_RRR(c.oploadx(p.As), uint32(p.To.Reg), uint32(p.From.Index), uint32(r))
} else {
if int32(int16(v)) != v {
log.Fatalf("mishandled instruction %v", p)
}
// Offsets in DS form loads must be a multiple of 4
inst := c.opload(p.As)
if c.opform(inst) == DS_FORM && v&0x3 != 0 {
log.Fatalf("invalid offset for DS form load/store %v", p)
}
o1 = AOP_IRR(inst, uint32(p.To.Reg), uint32(r), uint32(v))
if int32(int16(v)) != v {
log.Fatalf("mishandled instruction %v", p)
}
// Offsets in DS form loads must be a multiple of 4
inst := c.opload(p.As)
if c.opform(inst) == DS_FORM && v&0x3 != 0 {
log.Fatalf("invalid offset for DS form load/store %v", p)
}
o1 = AOP_IRR(inst, uint32(p.To.Reg), uint32(r), uint32(v))
// Sign extend MOVB operations. This is ignored for other cases (o.size == 4).
o2 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
@ -3141,9 +3154,16 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 = uint32(c.regoff(&p.From))
case 41: /* stswi */
if p.To.Type == obj.TYPE_MEM && p.To.Index == 0 && p.To.Offset != 0 {
c.ctxt.Diag("Invalid addressing mode used in index type instruction: %v", p.As)
}
o1 = AOP_RRR(c.opirr(p.As), uint32(p.From.Reg), uint32(p.To.Reg), 0) | (uint32(c.regoff(p.GetFrom3()))&0x7F)<<11
case 42: /* lswi */
if p.From.Type == obj.TYPE_MEM && p.From.Index == 0 && p.From.Offset != 0 {
c.ctxt.Diag("Invalid addressing mode used in index type instruction: %v", p.As)
}
o1 = AOP_RRR(c.opirr(p.As), uint32(p.To.Reg), uint32(p.From.Reg), 0) | (uint32(c.regoff(p.GetFrom3()))&0x7F)<<11
case 43: /* data cache instructions: op (Ra+[Rb]), [th|l] */
@ -3772,6 +3792,17 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
if so&0x3 != 0 {
log.Fatalf("invalid offset for DS form load/store %v", p)
}
case 108: /* mov r, xoreg ==> stwx rx,ry */
r := int(p.To.Reg)
o1 = AOP_RRR(c.opstorex(p.As), uint32(p.From.Reg), uint32(p.To.Index), uint32(r))
case 109: /* mov xoreg, r ==> lbzx/lhzx/lwzx rx,ry, lbzx rx,ry + extsb r,r */
r := int(p.From.Reg)
o1 = AOP_RRR(c.oploadx(p.As), uint32(p.To.Reg), uint32(p.From.Index), uint32(r))
// Sign extend MOVB operations. This is ignored for other cases (o.size == 4).
o2 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
}
out[0] = o1

View File

@ -482,6 +482,7 @@ func TestAddrClassifier(t *testing.T) {
{obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_PARAM, Offset: BIG}, C_LOREG},
{obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_PARAM, Offset: -BIG - 33}, C_LOREG}, // 33 is FixedFrameSize-1
{obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_NONE}, C_ZOREG},
{obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_NONE, Index: REG_R4}, C_XOREG},
{obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_NONE, Offset: 1}, C_SOREG},
{obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_NONE, Offset: BIG}, C_LOREG},
{obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_NONE, Offset: -BIG - 33}, C_LOREG},