diff options
-rw-r--r-- | src/cmd/asm/internal/asm/asm.go | 6 | ||||
-rw-r--r-- | src/cmd/asm/internal/asm/endtoend_test.go | 77 | ||||
-rw-r--r-- | src/cmd/asm/internal/asm/operand_test.go | 11 | ||||
-rw-r--r-- | src/cmd/asm/internal/asm/testdata/arm.out | 54 | ||||
-rw-r--r-- | src/cmd/asm/internal/asm/testdata/arm.s | 276 | ||||
-rw-r--r-- | src/cmd/asm/internal/asm/testdata/ppc64.out | 110 | ||||
-rw-r--r-- | src/cmd/asm/internal/asm/testdata/ppc64.s | 709 | ||||
-rw-r--r-- | src/cmd/asm/internal/lex/lex.go | 5 |
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 |