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},