From: Archana R Date: Wed, 11 May 2022 15:48:48 +0000 (-0500) Subject: cmd/asm: add new classification for index memory operands on PPC64 X-Git-Tag: go1.20rc1~1345 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=67d85ad00f9d9be0cc2bb1bb96d01c3d40dcb376;p=gostls13.git 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 TryBot-Result: Gopher Robot Reviewed-by: Heschi Kreinick Reviewed-by: Cherry Mui Run-TryBot: Archana Ravindar --- diff --git a/src/cmd/asm/internal/asm/operand_test.go b/src/cmd/asm/internal/asm/operand_test.go index b47c7e10a5..29371d6199 100644 --- a/src/cmd/asm/internal/asm/operand_test.go +++ b/src/cmd/asm/internal/asm/operand_test.go @@ -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)"}, diff --git a/src/cmd/asm/internal/asm/parse.go b/src/cmd/asm/internal/asm/parse.go index 6445e01bde..b42178798e 100644 --- a/src/cmd/asm/internal/asm/parse.go +++ b/src/cmd/asm/internal/asm/parse.go @@ -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) } diff --git a/src/cmd/asm/internal/asm/testdata/ppc64.s b/src/cmd/asm/internal/asm/testdata/ppc64.s index f307db30da..8f03a3afa6 100644 --- a/src/cmd/asm/internal/asm/testdata/ppc64.s +++ b/src/cmd/asm/internal/asm/testdata/ppc64.s @@ -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 diff --git a/src/cmd/internal/obj/ppc64/a.out.go b/src/cmd/internal/obj/ppc64/a.out.go index 30eba4339a..6b6e498fd2 100644 --- a/src/cmd/internal/obj/ppc64/a.out.go +++ b/src/cmd/internal/obj/ppc64/a.out.go @@ -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 */ diff --git a/src/cmd/internal/obj/ppc64/anames9.go b/src/cmd/internal/obj/ppc64/anames9.go index 05bfd944d1..c6cc923b80 100644 --- a/src/cmd/internal/obj/ppc64/anames9.go +++ b/src/cmd/internal/obj/ppc64/anames9.go @@ -39,6 +39,7 @@ var cnames9 = []string{ "ZOREG", "SOREG", "LOREG", + "XOREG", "FPSCR", "XER", "LR", diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index 94ad7a173b..ecd108e117 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -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 diff --git a/src/cmd/internal/obj/ppc64/asm_test.go b/src/cmd/internal/obj/ppc64/asm_test.go index c16d4a6e73..15dde3a952 100644 --- a/src/cmd/internal/obj/ppc64/asm_test.go +++ b/src/cmd/internal/obj/ppc64/asm_test.go @@ -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},