aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/asm/internal/asm/asm.go6
-rw-r--r--src/cmd/asm/internal/asm/endtoend_test.go77
-rw-r--r--src/cmd/asm/internal/asm/operand_test.go11
-rw-r--r--src/cmd/asm/internal/asm/testdata/arm.out54
-rw-r--r--src/cmd/asm/internal/asm/testdata/arm.s276
-rw-r--r--src/cmd/asm/internal/asm/testdata/ppc64.out110
-rw-r--r--src/cmd/asm/internal/asm/testdata/ppc64.s709
-rw-r--r--src/cmd/asm/internal/lex/lex.go5
8 files changed, 1246 insertions, 2 deletions
diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go
index 5d0d080190..f0cf117f05 100644
--- a/src/cmd/asm/internal/asm/asm.go
+++ b/src/cmd/asm/internal/asm/asm.go
@@ -5,6 +5,7 @@
package asm
import (
+ "bytes"
"fmt"
"text/scanner"
@@ -18,6 +19,8 @@ import (
// TODO: configure the architecture
+var testOut *bytes.Buffer // Gathers output when testing.
+
// append adds the Prog to the end of the program-thus-far.
// If doLabel is set, it also defines the labels collect for this Prog.
func (p *Parser) append(prog *obj.Prog, cond string, doLabel bool) {
@@ -46,6 +49,9 @@ func (p *Parser) append(prog *obj.Prog, cond string, doLabel bool) {
if *flags.Debug {
fmt.Println(p.histLineNum, prog)
}
+ if testOut != nil {
+ fmt.Fprintln(testOut, p.histLineNum, prog)
+ }
}
// validateSymbol checks that addr represents a valid name for a pseudo-op.
diff --git a/src/cmd/asm/internal/asm/endtoend_test.go b/src/cmd/asm/internal/asm/endtoend_test.go
new file mode 100644
index 0000000000..270f80d0f6
--- /dev/null
+++ b/src/cmd/asm/internal/asm/endtoend_test.go
@@ -0,0 +1,77 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package asm
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "cmd/asm/internal/lex"
+ "cmd/internal/obj"
+)
+
+// An end-to-end test for the assembler: Do we print what we parse?
+// Output is generated by, in effect, turning on -S and comparing the
+// result against a golden file.
+
+func testEndToEnd(t *testing.T, goarch string) {
+ lex.InitHist()
+ input := filepath.Join("testdata", goarch+".s")
+ output := filepath.Join("testdata", goarch+".out")
+ architecture, ctxt := setArch(goarch)
+ lexer := lex.NewLexer(input, ctxt)
+ parser := NewParser(ctxt, architecture, lexer)
+ pList := obj.Linknewplist(ctxt)
+ var ok bool
+ testOut = new(bytes.Buffer) // The assembler writes -S output to this buffer.
+ ctxt.Bso = obj.Binitw(os.Stdout)
+ defer obj.Bflush(ctxt.Bso)
+ ctxt.Diag = log.Fatalf
+ obj.Binitw(ioutil.Discard)
+ pList.Firstpc, ok = parser.Parse()
+ if !ok {
+ t.Fatalf("asm: ppc64 assembly failed")
+ }
+ result := string(testOut.Bytes())
+ expect, err := ioutil.ReadFile(output)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if result != string(expect) {
+ if false { // Enable to capture output.
+ fmt.Printf("%s", result)
+ os.Exit(1)
+ }
+ t.Errorf("%s failed: output differs", goarch)
+ r := strings.Split(result, "\n")
+ e := strings.Split(string(expect), "\n")
+ if len(r) != len(e) {
+ t.Errorf("%s: expected %d lines, got %d", len(e), len(r))
+ }
+ n := len(e)
+ if n > len(r) {
+ n = len(r)
+ }
+ for i := 0; i < n; i++ {
+ if r[i] != e[i] {
+ t.Errorf("%s:%d:\nexpected\n\t%s\ngot\n\t%s", output, i, e[i], r[i])
+ }
+ }
+ }
+}
+
+func TestPPC64EndToEnd(t *testing.T) {
+ testEndToEnd(t, "ppc64")
+}
+
+func TestARMEndToEnd(t *testing.T) {
+ testEndToEnd(t, "arm")
+}
diff --git a/src/cmd/asm/internal/asm/operand_test.go b/src/cmd/asm/internal/asm/operand_test.go
index 4437b7d5a6..1c4d983cf9 100644
--- a/src/cmd/asm/internal/asm/operand_test.go
+++ b/src/cmd/asm/internal/asm/operand_test.go
@@ -15,10 +15,17 @@ import (
// A simple in-out test: Do we print what we parse?
-func newParser(goarch string) *Parser {
+func setArch(goarch string) (*arch.Arch, *obj.Link) {
os.Setenv("GOOS", "linux") // obj can handle this OS for all architectures.
architecture := arch.Set(goarch)
- ctxt := obj.Linknew(architecture.LinkArch)
+ if architecture == nil {
+ panic("asm: unrecognized architecture " + goarch)
+ }
+ return architecture, obj.Linknew(architecture.LinkArch)
+}
+
+func newParser(goarch string) *Parser {
+ architecture, ctxt := setArch(goarch)
return NewParser(ctxt, architecture, nil)
}
diff --git a/src/cmd/asm/internal/asm/testdata/arm.out b/src/cmd/asm/internal/asm/testdata/arm.out
new file mode 100644
index 0000000000..af0b4638e5
--- /dev/null
+++ b/src/cmd/asm/internal/asm/testdata/arm.out
@@ -0,0 +1,54 @@
+1 00001 (testdata/arm.s:1) TEXT foo+0(SB),0,$0
+10 00002 (testdata/arm.s:10) ADD $1,R2,R3
+11 00003 (testdata/arm.s:11) ADD R1<<R2,R3,R4
+12 00004 (testdata/arm.s:12) ADD R1>>R2,R3,R4
+13 00005 (testdata/arm.s:13) ADD R1@>R2,R3,R4
+14 00006 (testdata/arm.s:14) ADD R1->R2,R3,R4
+15 00007 (testdata/arm.s:15) ADD R1,R2,R3
+16 00008 (testdata/arm.s:16) ADD R1<<R2,R3,R4
+26 00009 (testdata/arm.s:26) ADD $1,R2
+27 00010 (testdata/arm.s:27) ADD R1<<R2,R3
+28 00011 (testdata/arm.s:28) ADD R1>>R2,R3
+29 00012 (testdata/arm.s:29) ADD R1@>R2,R3
+30 00013 (testdata/arm.s:30) ADD R1->R2,R3
+31 00014 (testdata/arm.s:31) ADD R1,R2
+40 00015 (testdata/arm.s:40) CLZ.S R1,R2
+49 00016 (testdata/arm.s:49) MOVW.S R1,R2
+50 00017 (testdata/arm.s:50) MOVW.S $1,R2
+51 00018 (testdata/arm.s:51) MOVW.S R1<<R2,R3
+60 00019 (testdata/arm.s:60) JMP.S ,20(PC)
+66 00020 (testdata/arm.s:66) JMP.S ,0(R2)
+67 00021 (testdata/arm.s:67) JMP.S ,foo+0(SB)
+68 00022 (testdata/arm.s:68) JMP.S ,bar<>+0(SB)
+77 00023 (testdata/arm.s:77) BX 0(R2),
+86 00024 (testdata/arm.s:86) BEQ ,25(PC)
+95 00025 (testdata/arm.s:95) SWI.S ,R1
+96 00026 (testdata/arm.s:96) SWI.S ,0(R1)
+97 00027 (testdata/arm.s:97) SWI.S ,foo+0(SB)
+106 00028 (testdata/arm.s:106) CMP.S $1,R2,
+107 00029 (testdata/arm.s:107) CMP.S R1<<R2,R3,
+108 00030 (testdata/arm.s:108) CMP.S R1,R2,
+122 00031 (testdata/arm.s:122) MOVM 0(R1),[R2,R5,R8,R10]
+123 00032 (testdata/arm.s:123) MOVM 0(R1),[R2,R3,R4,R5]
+124 00033 (testdata/arm.s:124) MOVM.S 0(R1),[R2]
+135 00034 (testdata/arm.s:135) MOVM [R2,R5,R8,R10],0(R1)
+136 00035 (testdata/arm.s:136) MOVM [R2,R3,R4,R5],0(R1)
+137 00036 (testdata/arm.s:137) MOVM.S [R2],0(R1)
+146 00037 (testdata/arm.s:146) STREX.S 0(R2),R1,R3
+152 00038 (testdata/arm.s:152) STREX.S 0(R2),R1,R1
+158 00039 (testdata/arm.s:158) STREX.S 0(R2),R3,R3
+166 00040 (testdata/arm.s:166) CASE.S R1,
+175 00041 (testdata/arm.s:175) WORD ,$1234
+184 00042 (testdata/arm.s:184) ABSF.S F1,F2
+190 00043 (testdata/arm.s:190) ADDD.S F1,F2
+191 00044 (testdata/arm.s:191) ADDD.S $0.5,F2
+197 00045 (testdata/arm.s:197) ADDD.S F1,F2,F3
+198 00046 (testdata/arm.s:198) ADDD.S $0.5,F2,F3
+204 00047 (testdata/arm.s:204) CMPD.S F1,F2
+228 00048 (testdata/arm.s:228) MRC ,$8301712627
+237 00049 (testdata/arm.s:237) MULL R1,R2,(R3, R4)
+249 00050 (testdata/arm.s:249) MULAWT R1,R2,R3, R4
+257 00051 (testdata/arm.s:257) PLD 0(R1),
+258 00052 (testdata/arm.s:258) PLD 4(R1),
+267 00053 (testdata/arm.s:267) RET ,
+276 00054 (testdata/arm.s:276) END ,
diff --git a/src/cmd/asm/internal/asm/testdata/arm.s b/src/cmd/asm/internal/asm/testdata/arm.s
new file mode 100644
index 0000000000..184ed9fc3c
--- /dev/null
+++ b/src/cmd/asm/internal/asm/testdata/arm.s
@@ -0,0 +1,276 @@
+TEXT foo(SB), 0, $0
+
+// ADD
+//
+// LTYPE1 cond imsr ',' spreg ',' reg
+// {
+// outcode($1, $2, &$3, $5, &$7);
+// }
+// Cover some operand space here too.
+ ADD $1, R2, R3
+ ADD R1<<R2, R3, R4
+ ADD R1>>R2, R3, R4
+ ADD R1@>R2, R3, R4
+ ADD R1->R2, R3, R4
+ ADD R1, R2, R3
+ ADD R(1)<<R(2), R(3), R(4)
+
+// LTYPE1 cond imsr ',' spreg ',' // asm doesn't support trailing comma.
+// {
+// outcode($1, $2, &$3, $5, &nullgen);
+// }
+// LTYPE1 cond imsr ',' reg
+// {
+// outcode($1, $2, &$3, 0, &$5);
+// }
+ ADD $1, R2
+ ADD R1<<R2, R3
+ ADD R1>>R2, R3
+ ADD R1@>R2, R3
+ ADD R1->R2, R3
+ ADD R1, R2
+
+//
+// MVN
+//
+// LTYPE2 cond imsr ',' reg
+// {
+// outcode($1, $2, &$3, 0, &$5);
+// }
+ CLZ.S R1, R2
+
+//
+// MOVW
+//
+// LTYPE3 cond gen ',' gen
+// {
+// outcode($1, $2, &$3, 0, &$5);
+// }
+ MOVW.S R1, R2
+ MOVW.S $1, R2
+ MOVW.S R1<<R2, R3
+
+//
+// B/BL
+//
+// LTYPE4 cond comma rel
+// {
+// outcode($1, $2, &nullgen, 0, &$4);
+// }
+ B.S 1(PC)
+
+// LTYPE4 cond comma nireg
+// {
+// outcode($1, $2, &nullgen, 0, &$4);
+// }
+ B.S (R2)
+ B.S foo(SB)
+ B.S bar<>(SB)
+
+//
+// BX
+//
+// LTYPEBX comma ireg
+// {
+// outcode($1, Always, &nullgen, 0, &$3);
+// }
+ BX (R2)
+
+//
+// BEQ
+//
+// LTYPE5 comma rel
+// {
+// outcode($1, Always, &nullgen, 0, &$3);
+// }
+ BEQ 1(PC)
+
+//
+// SWI
+//
+// LTYPE6 cond comma gen
+// {
+// outcode($1, $2, &nullgen, 0, &$4);
+// }
+ SWI.S R1
+ SWI.S (R1)
+ SWI.S foo(SB)
+
+//
+// CMP
+//
+// LTYPE7 cond imsr ',' spreg
+// {
+// outcode($1, $2, &$3, $5, &nullgen);
+// }
+ CMP.S $1, R2
+ CMP.S R1<<R2, R3
+ CMP.S R1, R2
+
+//
+// MOVM
+//
+// LTYPE8 cond ioreg ',' '[' reglist ']'
+// {
+// var g obj.Addr
+//
+// g = nullgen;
+// g.Type = obj.TYPE_CONST;
+// g.Offset = int64($6);
+// outcode($1, $2, &$3, 0, &g);
+// }
+ MOVM 0(R1), [R2,R5,R8,g]
+ MOVM 0(R1), [R2-R5]
+ MOVM.S (R1), [R2]
+
+// LTYPE8 cond '[' reglist ']' ',' ioreg
+// {
+// var g obj.Addr
+//
+// g = nullgen;
+// g.Type = obj.TYPE_CONST;
+// g.Offset = int64($4);
+// outcode($1, $2, &g, 0, &$7);
+// }
+ MOVM [R2,R5,R8,g], 0(R1)
+ MOVM [R2-R5], 0(R1)
+ MOVM.S [R2], (R1)
+
+//
+// SWAP
+//
+// LTYPE9 cond reg ',' ireg ',' reg
+// {
+// outcode($1, $2, &$5, int32($3.Reg), &$7);
+// }
+ STREX.S R1, (R2), R3
+
+// LTYPE9 cond reg ',' ireg
+// {
+// outcode($1, $2, &$5, int32($3.Reg), &$3);
+// }
+ STREX.S R1, (R2)
+
+// LTYPE9 cond comma ireg ',' reg
+// {
+// outcode($1, $2, &$4, int32($6.Reg), &$6);
+// }
+ STREX.S (R2), R3
+
+// CASE
+//
+// LTYPED cond reg
+// {
+// outcode($1, $2, &$3, 0, &nullgen);
+// }
+ CASE.S R1
+
+//
+// word
+//
+// LTYPEH comma ximm
+// {
+// outcode($1, Always, &nullgen, 0, &$3);
+// }
+ WORD $1234
+
+//
+// floating-point coprocessor
+//
+// LTYPEI cond freg ',' freg
+// {
+// outcode($1, $2, &$3, 0, &$5);
+// }
+ ABSF.S F1, F2
+
+// LTYPEK cond frcon ',' freg
+// {
+// outcode($1, $2, &$3, 0, &$5);
+// }
+ ADDD.S F1, F2
+ ADDD.S $0.5, F2
+
+// LTYPEK cond frcon ',' LFREG ',' freg
+// {
+// outcode($1, $2, &$3, $5, &$7);
+// }
+ ADDD.S F1, F2, F3
+ ADDD.S $0.5, F2, F3
+
+// LTYPEL cond freg ',' freg
+// {
+// outcode($1, $2, &$3, int32($5.Reg), &nullgen);
+// }
+ CMPD.S F1, F2
+
+//
+// MCR MRC
+//
+// LTYPEJ cond con ',' expr ',' spreg ',' creg ',' creg oexpr
+// {
+// var g obj.Addr
+//
+// g = nullgen;
+// g.Type = obj.TYPE_CONST;
+// g.Offset = int64(
+// (0xe << 24) | /* opcode */
+// ($1 << 20) | /* MCR/MRC */
+// (($2^C_SCOND_XOR) << 28) | /* scond */
+// (($3 & 15) << 8) | /* coprocessor number */
+// (($5 & 7) << 21) | /* coprocessor operation */
+// (($7 & 15) << 12) | /* arm register */
+// (($9 & 15) << 16) | /* Crn */
+// (($11 & 15) << 0) | /* Crm */
+// (($12 & 7) << 5) | /* coprocessor information */
+// (1<<4)); /* must be set */
+// outcode(AMRC, Always, &nullgen, 0, &g);
+// }
+ MRC.S 4, 6, R1, C2, C3, 7
+
+//
+// MULL r1,r2,(hi,lo)
+//
+// LTYPEM cond reg ',' reg ',' regreg
+// {
+// outcode($1, $2, &$3, int32($5.Reg), &$7);
+// }
+ MULL R1, R2, (R3,R4)
+
+//
+// MULA r1,r2,r3,r4: (r1*r2+r3) & 0xffffffff . r4
+// MULAW{T,B} r1,r2,r3,r4
+//
+// LTYPEN cond reg ',' reg ',' reg ',' spreg
+// {
+// $7.Type = obj.TYPE_REGREG2;
+// $7.Offset = int64($9);
+// outcode($1, $2, &$3, int32($5.Reg), &$7);
+// }
+ MULAWT R1, R2, R3, R4
+//
+// PLD
+//
+// LTYPEPLD oreg
+// {
+// outcode($1, Always, &$2, 0, &nullgen);
+// }
+ PLD (R1)
+ PLD 4(R1)
+
+//
+// RET
+//
+// LTYPEA cond
+// {
+// outcode($1, $2, &nullgen, 0, &nullgen);
+// }
+ RET
+
+//
+// END
+//
+// LTYPEE
+// {
+// outcode($1, Always, &nullgen, 0, &nullgen);
+// }
+ END
diff --git a/src/cmd/asm/internal/asm/testdata/ppc64.out b/src/cmd/asm/internal/asm/testdata/ppc64.out
new file mode 100644
index 0000000000..50bca559e5
--- /dev/null
+++ b/src/cmd/asm/internal/asm/testdata/ppc64.out
@@ -0,0 +1,110 @@
+5 00001 (testdata/ppc64.s:5) TEXT foo(SB),$0
+15 00002 (testdata/ppc64.s:15) MOVW R1,R2
+21 00003 (testdata/ppc64.s:21) MOVW foo<>+3(SB),R2
+22 00004 (testdata/ppc64.s:22) MOVW 16(R1),R2
+28 00005 (testdata/ppc64.s:28) MOVW 0(R1),R2
+29 00006 (testdata/ppc64.s:29) MOVW 0(R1+R2),R3
+35 00007 (testdata/ppc64.s:35) MOVW R1,R2
+41 00008 (testdata/ppc64.s:41) MOVB foo<>+3(SB),R2
+42 00009 (testdata/ppc64.s:42) MOVB 16(R1),R2
+48 00010 (testdata/ppc64.s:48) MOVB 0(R1),R2
+49 00011 (testdata/ppc64.s:49) MOVB 0(R1+R2),R3
+58 00012 (testdata/ppc64.s:58) FMOVD foo<>+3(SB),F2
+59 00013 (testdata/ppc64.s:59) FMOVD 16(R1),F2
+65 00014 (testdata/ppc64.s:65) FMOVD 0(R1),F2
+71 00015 (testdata/ppc64.s:71) FMOVD $0.10000000000000001,F2
+77 00016 (testdata/ppc64.s:77) FMOVD F1,F2
+83 00017 (testdata/ppc64.s:83) FMOVD F2,foo<>+3(SB)
+84 00018 (testdata/ppc64.s:84) FMOVD F2,16(R1)
+90 00019 (testdata/ppc64.s:90) FMOVD F2,0(R1)
+99 00020 (testdata/ppc64.s:99) MOVW R1,foo<>+3(SB)
+100 00021 (testdata/ppc64.s:100) MOVW R1,16(R2)
+106 00022 (testdata/ppc64.s:106) MOVW R1,0(R1)
+107 00023 (testdata/ppc64.s:107) MOVW R1,0(R2+R3)
+113 00024 (testdata/ppc64.s:113) MOVB R1,foo<>+3(SB)
+114 00025 (testdata/ppc64.s:114) MOVB R1,16(R2)
+120 00026 (testdata/ppc64.s:120) MOVB R1,0(R1)
+121 00027 (testdata/ppc64.s:121) MOVB R1,0(R2+R3)
+129 00028 (testdata/ppc64.s:129) FMOVD F1,foo<>+3(SB)
+130 00029 (testdata/ppc64.s:130) FMOVD F1,16(R2)
+136 00030 (testdata/ppc64.s:136) FMOVD F1,0(R1)
+145 00031 (testdata/ppc64.s:145) MOVFL FPSCR,F1
+151 00032 (testdata/ppc64.s:151) MOVFL F1,FPSCR
+157 00033 (testdata/ppc64.s:157) MOVFL F1,$4,FPSCR
+163 00034 (testdata/ppc64.s:163) MOVFL FPSCR,C0
+184 00035 (testdata/ppc64.s:184) MOVW R1,C1
+190 00036 (testdata/ppc64.s:190) MOVW R1,CR
+202 00037 (testdata/ppc64.s:202) ADD R1,R2,R3
+208 00038 (testdata/ppc64.s:208) ADD $1,R2,R3
+220 00039 (testdata/ppc64.s:220) ADD R1,R2
+226 00040 (testdata/ppc64.s:226) ADD $4,R1
+232 00041 (testdata/ppc64.s:232) ADDE R1,R2,R3
+238 00042 (testdata/ppc64.s:238) ADDE R1,R2
+244 00043 (testdata/ppc64.s:244) SLW R1,R2,R3
+250 00044 (testdata/ppc64.s:250) SLW R1,R2
+256 00045 (testdata/ppc64.s:256) SLW $4,R1,R2
+262 00046 (testdata/ppc64.s:262) SLW $4,R1
+268 00047 (testdata/ppc64.s:268) SLW $4,R1
+274 00048 (testdata/ppc64.s:274) SUBME R1,R1
+292 00049 (testdata/ppc64.s:292) MOVW $1,R1
+298 00050 (testdata/ppc64.s:298) MOVW $1,R1
+299 00051 (testdata/ppc64.s:299) MOVW $foo(SB),R1
+323 00052 (testdata/ppc64.s:323) MOVFL C0,C1
+335 00053 (testdata/ppc64.s:335) MOVW CR,R1
+341 00054 (testdata/ppc64.s:341) MOVW SPR(0),R1
+342 00055 (testdata/ppc64.s:342) MOVW SPR(7),R1
+348 00056 (testdata/ppc64.s:348) MOVW LR,R1
+349 00057 (testdata/ppc64.s:349) MOVW CTR,R1
+355 00058 (testdata/ppc64.s:355) MOVW R1,LR
+356 00059 (testdata/ppc64.s:356) MOVW R1,CTR
+368 00060 (testdata/ppc64.s:368) MOVW R1,SPR(7)
+380 00061 (testdata/ppc64.s:380) JMP ,62(APC)
+381 00062 (testdata/ppc64.s:381) JMP ,61
+387 00063 (testdata/ppc64.s:387) JMP ,4(R1)
+388 00064 (testdata/ppc64.s:388) JMP ,foo(SB)
+394 00065 (testdata/ppc64.s:394) JMP ,CTR
+413 00066 (testdata/ppc64.s:413) BEQ C1,67(APC)
+414 00067 (testdata/ppc64.s:414) BEQ C1,66
+440 00068 (testdata/ppc64.s:440) BC 4,CTR
+450 00069 (testdata/ppc64.s:450) BC $3,R4,66
+470 00070 (testdata/ppc64.s:470) BC $3,R3,LR
+500 00071 (testdata/ppc64.s:500) FABS F1,F2
+506 00072 (testdata/ppc64.s:506) FADD F1,F2
+512 00073 (testdata/ppc64.s:512) FADD F1,F2,F3
+518 00074 (testdata/ppc64.s:518) FMADD F1,F2,F3,F4
+524 00075 (testdata/ppc64.s:524) FCMPU F1,F2
+530 00076 (testdata/ppc64.s:530) FCMPU F1,F2,C0
+539 00077 (testdata/ppc64.s:539) CMP R1,R2
+545 00078 (testdata/ppc64.s:545) CMP R1,$4
+551 00079 (testdata/ppc64.s:551) CMP R1,C0,R2
+557 00080 (testdata/ppc64.s:557) CMP R1,C0,$4
+566 00081 (testdata/ppc64.s:566) RLDC $4,R1,$5,R2
+572 00082 (testdata/ppc64.s:572) RLDC $26,R1,$201326592,R2
+578 00083 (testdata/ppc64.s:578) RLDC R1,R2,$4,R3
+584 00084 (testdata/ppc64.s:584) RLWMI R1,R2,$201326592,R3
+593 00085 (testdata/ppc64.s:593) MOVMW foo(SB),R2
+594 00086 (testdata/ppc64.s:594) MOVMW 4(R1),R2
+600 00087 (testdata/ppc64.s:600) MOVMW R1,foo(SB)
+601 00088 (testdata/ppc64.s:601) MOVMW R1,4(R2)
+611 00089 (testdata/ppc64.s:611) LSW 0(R1),R2
+612 00090 (testdata/ppc64.s:612) LSW 0(R1+R2),R3
+618 00091 (testdata/ppc64.s:618) LSW 0(R1+NONE),R2
+619 00092 (testdata/ppc64.s:619) LSW 0(R1+NONE),R3
+625 00093 (testdata/ppc64.s:625) STSW R1,0(R2)
+626 00094 (testdata/ppc64.s:626) STSW R1,0(R2+R3)
+632 00095 (testdata/ppc64.s:632) STSW R1,0(R2+NONE)
+633 00096 (testdata/ppc64.s:633) STSW R1,0(R2+NONE)
+639 00097 (testdata/ppc64.s:639) MOVHBR 0(R1),R2
+640 00098 (testdata/ppc64.s:640) MOVHBR 0(R1+R2),R3
+646 00099 (testdata/ppc64.s:646) MOVHBR R1,0(R2)
+647 00100 (testdata/ppc64.s:647) MOVHBR R1,0(R2+R3)
+653 00101 (testdata/ppc64.s:653) DCBF 0(R1),
+654 00102 (testdata/ppc64.s:654) DCBF 0(R1),
+663 00103 (testdata/ppc64.s:663) NOP ,
+669 00104 (testdata/ppc64.s:669) NOP R2,
+675 00105 (testdata/ppc64.s:675) NOP F2,
+681 00106 (testdata/ppc64.s:681) NOP R2,
+687 00107 (testdata/ppc64.s:687) NOP F2,
+693 00108 (testdata/ppc64.s:693) NOP $4,
+701 00109 (testdata/ppc64.s:701) RET ,
+709 00110 (testdata/ppc64.s:709) END ,
diff --git a/src/cmd/asm/internal/asm/testdata/ppc64.s b/src/cmd/asm/internal/asm/testdata/ppc64.s
new file mode 100644
index 0000000000..1fb53982c1
--- /dev/null
+++ b/src/cmd/asm/internal/asm/testdata/ppc64.s
@@ -0,0 +1,709 @@
+// This input was created by taking the instruction productions in
+// the old assembler's (9a's) grammar and hand-writing one complete
+// instruction for each rule, to guarantee we cover the same space.
+
+TEXT foo(SB),0,$0
+
+//inst:
+//
+// load ints and bytes
+//
+// LMOVW rreg ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW R1, R2
+
+// LMOVW addr ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW foo<>+3(SB), R2
+ MOVW 16(R1), R2
+
+// LMOVW regaddr ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW (R1), R2
+ MOVW (R1+R2), R3
+
+// LMOVB rreg ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW R1, R2
+
+// LMOVB addr ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVB foo<>+3(SB), R2
+ MOVB 16(R1), R2
+
+// LMOVB regaddr ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVB (R1), R2
+ MOVB (R1+R2), R3
+
+//
+// load floats
+//
+// LFMOV addr ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ FMOVD foo<>+3(SB), F2
+ FMOVD 16(R1), F2
+
+// LFMOV regaddr ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ FMOVD (R1), F2
+
+// LFMOV fimm ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ FMOVD $0.1, F2
+
+// LFMOV freg ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ FMOVD F1, F2
+
+// LFMOV freg ',' addr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ FMOVD F2, foo<>+3(SB)
+ FMOVD F2, 16(R1)
+
+// LFMOV freg ',' regaddr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ FMOVD F2, (R1)
+
+//
+// store ints and bytes
+//
+// LMOVW rreg ',' addr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW R1, foo<>+3(SB)
+ MOVW R1, 16(R2)
+
+// LMOVW rreg ',' regaddr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW R1, (R1)
+ MOVW R1, (R2+R3)
+
+// LMOVB rreg ',' addr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVB R1, foo<>+3(SB)
+ MOVB R1, 16(R2)
+
+// LMOVB rreg ',' regaddr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVB R1, (R1)
+ MOVB R1, (R2+R3)
+//
+// store floats
+//
+// LMOVW freg ',' addr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ FMOVD F1, foo<>+3(SB)
+ FMOVD F1, 16(R2)
+
+// LMOVW freg ',' regaddr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ FMOVD F1, (R1)
+
+//
+// floating point status
+//
+// LMOVW fpscr ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVFL FPSCR, F1
+
+// LMOVW freg ',' fpscr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVFL F1, FPSCR
+
+// LMOVW freg ',' imm ',' fpscr
+// {
+// outgcode(int($1), &$2, 0, &$4, &$6);
+// }
+ MOVFL F1, $4, FPSCR
+
+// LMOVW fpscr ',' creg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVFL FPSCR, CR0
+
+// LMTFSB imm ',' con
+// {
+// outcode(int($1), &$2, int($4), &nullgen);
+// }
+//TODO 9a doesn't work MTFSB0 $4, 4
+
+//
+// field moves (mtcrf)
+//
+// LMOVW rreg ',' imm ',' lcr
+// {
+// outgcode(int($1), &$2, 0, &$4, &$6);
+// }
+// TODO 9a doesn't work MOVFL R1,$4,CR
+
+// LMOVW rreg ',' creg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW R1, CR1
+
+// LMOVW rreg ',' lcr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW R1, CR
+
+//
+// integer operations
+// logical instructions
+// shift instructions
+// unary instructions
+//
+// LADDW rreg ',' sreg ',' rreg
+// {
+// outcode(int($1), &$2, int($4), &$6);
+// }
+ ADD R1, R2, R3
+
+// LADDW imm ',' sreg ',' rreg
+// {
+// outcode(int($1), &$2, int($4), &$6);
+// }
+ ADD $1, R2, R3
+
+// LADDW rreg ',' imm ',' rreg
+// {
+// outgcode(int($1), &$2, 0, &$4, &$6);
+// }
+//TODO 9a trouble ADD R1, $2, R3 maybe swap rreg and imm
+
+// LADDW rreg ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ ADD R1, R2
+
+// LADDW imm ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ ADD $4, R1
+
+// LLOGW rreg ',' sreg ',' rreg
+// {
+// outcode(int($1), &$2, int($4), &$6);
+// }
+ ADDE R1, R2, R3
+
+// LLOGW rreg ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ ADDE R1, R2
+
+// LSHW rreg ',' sreg ',' rreg
+// {
+// outcode(int($1), &$2, int($4), &$6);
+// }
+ SLW R1, R2, R3
+
+// LSHW rreg ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ SLW R1, R2
+
+// LSHW imm ',' sreg ',' rreg
+// {
+// outcode(int($1), &$2, int($4), &$6);
+// }
+ SLW $4, R1, R2
+
+// LSHW imm ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ SLW $4, R1
+
+// LABS rreg ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ SLW $4, R1
+
+// LABS rreg
+// {
+// outcode(int($1), &$2, 0, &$2);
+// }
+ SUBME R1
+
+//
+// multiply-accumulate
+//
+// LMA rreg ',' sreg ',' rreg
+// {
+// outcode(int($1), &$2, int($4), &$6);
+// }
+//TODO this instruction is undefined in lex.go LMA R1, R2, R3 NOT SUPPORTED (called MAC)
+
+//
+// move immediate: macro for cau+or, addi, addis, and other combinations
+//
+// LMOVW imm ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW $1, R1
+
+// LMOVW ximm ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW $1, R1
+ MOVW $foo(SB), R1
+
+// condition register operations
+//
+// LCROP cbit ',' cbit
+// {
+// outcode(int($1), &$2, int($4.Reg), &$4);
+// }
+//TODO 9a trouble CREQV 1, 2 delete? liblink encodes like a divide (maybe wrong too)
+
+// LCROP cbit ',' con ',' cbit
+// {
+// outcode(int($1), &$2, int($4), &$6);
+// }
+//TODO 9a trouble CREQV 1, 2, 3
+
+//
+// condition register moves
+// move from machine state register
+//
+// LMOVW creg ',' creg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVFL CR0, CR1
+
+// LMOVW psr ',' creg // TODO: should psr should be fpscr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+//TODO 9a trouble MOVW FPSCR, CR1
+
+// LMOVW lcr ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW CR, R1
+
+// LMOVW psr ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW SPR(0), R1
+ MOVW SPR(7), R1
+
+// LMOVW xlreg ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW LR, R1
+ MOVW CTR, R1
+
+// LMOVW rreg ',' xlreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW R1, LR
+ MOVW R1, CTR
+
+// LMOVW creg ',' psr // TODO doesn't exist
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+//TODO 9a trouble MOVW CR1, SPR(7)
+
+// LMOVW rreg ',' psr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW R1, SPR(7)
+
+//
+// branch, branch conditional
+// branch conditional register
+// branch conditional to count register
+//
+// LBRA rel
+// {
+// outcode(int($1), &nullgen, 0, &$2);
+// }
+label0:
+ BR 1(PC)
+ BR label0+0
+
+// LBRA addr
+// {
+// outcode(int($1), &nullgen, 0, &$2);
+// }
+ BR 4(R1)
+ BR foo+0(SB)
+
+// LBRA '(' xlreg ')'
+// {
+// outcode(int($1), &nullgen, 0, &$3);
+// }
+ BR (CTR)
+
+// LBRA ',' rel // asm doesn't support the leading comma
+// {
+// outcode(int($1), &nullgen, 0, &$3);
+// }
+// LBRA ',' addr // asm doesn't support the leading comma
+// {
+// outcode(int($1), &nullgen, 0, &$3);
+// }
+// LBRA ',' '(' xlreg ')' // asm doesn't support the leading comma
+// {
+// outcode(int($1), &nullgen, 0, &$4);
+// }
+// LBRA creg ',' rel
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+label1:
+ BEQ CR1, 1(PC)
+ BEQ CR1, label1
+
+// LBRA creg ',' addr // TODO DOES NOT WORK in 9a
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+
+// LBRA creg ',' '(' xlreg ')' // TODO DOES NOT WORK in 9a
+// {
+// outcode(int($1), &$2, 0, &$5);
+// }
+
+// LBRA con ',' rel // TODO DOES NOT WORK in 9a
+// {
+// outcode(int($1), &nullgen, int($2), &$4);
+// }
+
+// LBRA con ',' addr // TODO DOES NOT WORK in 9a
+// {
+// outcode(int($1), &nullgen, int($2), &$4);
+// }
+
+// LBRA con ',' '(' xlreg ')'
+// {
+// outcode(int($1), &nullgen, int($2), &$5);
+// }
+ BC 4, (CTR)
+
+// LBRA con ',' con ',' rel
+// {
+// var g obj.Addr
+// g = nullgen;
+// g.Type = obj.TYPE_CONST;
+// g.Offset = $2;
+// outcode(int($1), &g, int(REG_R0+$4), &$6);
+// }
+ BC 3, 4, label1
+
+// LBRA con ',' con ',' addr // TODO mystery
+// {
+// var g obj.Addr
+// g = nullgen;
+// g.Type = obj.TYPE_CONST;
+// g.Offset = $2;
+// outcode(int($1), &g, int(REG_R0+$4), &$6);
+// }
+//TODO 9a trouble BC 3, 3, 4(R1)
+
+// LBRA con ',' con ',' '(' xlreg ')'
+// {
+// var g obj.Addr
+// g = nullgen;
+// g.Type = obj.TYPE_CONST;
+// g.Offset = $2;
+// outcode(int($1), &g, int(REG_R0+$4), &$7);
+// }
+ BC 3, 3, (LR)
+
+//
+// conditional trap // TODO NOT DEFINED
+// TODO these instructions are not in lex.go
+//
+// LTRAP rreg ',' sreg
+// {
+// outcode(int($1), &$2, int($4), &nullgen);
+// }
+// LTRAP imm ',' sreg
+// {
+// outcode(int($1), &$2, int($4), &nullgen);
+// }
+// LTRAP rreg comma
+// {
+// outcode(int($1), &$2, 0, &nullgen);
+// }
+// LTRAP comma
+// {
+// outcode(int($1), &nullgen, 0, &nullgen);
+// }
+
+//
+// floating point operate
+//
+// LFCONV freg ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ FABS F1, F2
+
+// LFADD freg ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ FADD F1, F2
+
+// LFADD freg ',' freg ',' freg
+// {
+// outcode(int($1), &$2, int($4.Reg), &$6);
+// }
+ FADD F1, F2, F3
+
+// LFMA freg ',' freg ',' freg ',' freg
+// {
+// outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
+// }
+ FMADD F1, F2, F3, F4
+
+// LFCMP freg ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ FCMPU F1, F2
+
+// LFCMP freg ',' freg ',' creg
+// {
+// outcode(int($1), &$2, int($6.Reg), &$4);
+// }
+ FCMPU F1, F2, CR0
+
+//
+// CMP
+//
+// LCMP rreg ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ CMP R1, R2
+
+// LCMP rreg ',' imm
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ CMP R1, $4
+
+// LCMP rreg ',' rreg ',' creg
+// {
+// outcode(int($1), &$2, int($6.Reg), &$4);
+// }
+ CMP R1, R2, CR0
+
+// LCMP rreg ',' imm ',' creg
+// {
+// outcode(int($1), &$2, int($6.Reg), &$4);
+// }
+ CMP R1, $4, CR0
+
+//
+// rotate and mask
+//
+// LRLWM imm ',' rreg ',' imm ',' rreg
+// {
+// outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
+// }
+ RLDC $4, R1, $5, R2
+
+// LRLWM imm ',' rreg ',' mask ',' rreg
+// {
+// outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
+// }
+ RLDC $26, R1, 4, 5, R2
+
+// LRLWM rreg ',' rreg ',' imm ',' rreg
+// {
+// outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
+// }
+ RLDC R1, R2, $4, R3
+
+// LRLWM rreg ',' rreg ',' mask ',' rreg
+// {
+// outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
+// }
+ RLWMI R1, R2, 4, 5, R3
+
+//
+// load/store multiple
+//
+// LMOVMW addr ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVMW foo+0(SB), R2
+ MOVMW 4(R1), R2
+
+// LMOVMW rreg ',' addr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVMW R1, foo+0(SB)
+ MOVMW R1, 4(R2)
+
+//
+// various indexed load/store
+// indexed unary (eg, cache clear)
+//
+// LXLD regaddr ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ LSW (R1), R2
+ LSW (R1+R2), R3
+
+// LXLD regaddr ',' imm ',' rreg
+// {
+// outgcode(int($1), &$2, 0, &$4, &$6);
+// }
+ LSW (R1), $1, R2
+ LSW (R1+R2), $1, R3
+
+// LXST rreg ',' regaddr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ STSW R1, (R2)
+ STSW R1, (R2+R3)
+
+// LXST rreg ',' imm ',' regaddr
+// {
+// outgcode(int($1), &$2, 0, &$4, &$6);
+// }
+ STSW R1, $1, (R2)
+ STSW R1, $1, (R2+R3)
+
+// LXMV regaddr ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVHBR (R1), R2
+ MOVHBR (R1+R2), R3
+
+// LXMV rreg ',' regaddr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVHBR R1, (R2)
+ MOVHBR R1, (R2+R3)
+
+// LXOP regaddr
+// {
+// outcode(int($1), &$2, 0, &nullgen);
+// }
+ DCBF (R1)
+ DCBF (R1+R2)
+
+//
+// NOP
+//
+// LNOP comma // asm doesn't support the trailing comma.
+// {
+// outcode(int($1), &nullgen, 0, &nullgen);
+// }
+ NOP
+
+// LNOP rreg comma // asm doesn't support the trailing comma.
+// {
+// outcode(int($1), &$2, 0, &nullgen);
+// }
+ NOP R2
+
+// LNOP freg comma // asm doesn't support the trailing comma.
+// {
+// outcode(int($1), &$2, 0, &nullgen);
+// }
+ NOP F2
+
+// LNOP ',' rreg // asm doesn't support the leading comma.
+// {
+// outcode(int($1), &nullgen, 0, &$3);
+// }
+ NOP R2
+
+// LNOP ',' freg // asm doesn't support the leading comma.
+// {
+// outcode(int($1), &nullgen, 0, &$3);
+// }
+ NOP F2
+
+// LNOP imm // SYSCALL $num: load $num to R0 before syscall and restore R0 to 0 afterwards.
+// {
+// outcode(int($1), &$2, 0, &nullgen);
+// }
+ NOP $4
+
+// RETURN
+//
+// LRETRN comma // asm doesn't support the trailing comma.
+// {
+// outcode(int($1), &nullgen, 0, &nullgen);
+// }
+ RETURN
+
+// END
+//
+// LEND comma // asm doesn't support the trailing comma.
+// {
+// outcode(int($1), &nullgen, 0, &nullgen);
+// }
+ END
diff --git a/src/cmd/asm/internal/lex/lex.go b/src/cmd/asm/internal/lex/lex.go
index c48b74a101..6fce55f7f4 100644
--- a/src/cmd/asm/internal/lex/lex.go
+++ b/src/cmd/asm/internal/lex/lex.go
@@ -83,6 +83,11 @@ func NewLexer(name string, ctxt *obj.Link) TokenReader {
return input
}
+// InitHist sets the line count to 1, for reproducible testing.
+func InitHist() {
+ histLine = 1
+}
+
// The other files in this directory each contain an implementation of TokenReader.
// A TokenReader is like a reader, but returns lex tokens of type Token. It also can tell you what