]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.cc] cmd/asm: add end-to-end test
authorRob Pike <r@golang.org>
Fri, 20 Feb 2015 18:06:44 +0000 (10:06 -0800)
committerRob Pike <r@golang.org>
Sat, 21 Feb 2015 02:02:23 +0000 (02:02 +0000)
Add trivial golden test that verifies output matches expectation.
The input is based on the old grammar and is intended to cover
the space of the input language.

PPC64 and ARM only for now; others to follow.

Change-Id: Ib5957822bcafd5b9d4c1dea1c03cc6ee1238f7ef
Reviewed-on: https://go-review.googlesource.com/5421
Reviewed-by: Russ Cox <rsc@golang.org>
src/cmd/asm/internal/asm/asm.go
src/cmd/asm/internal/asm/endtoend_test.go [new file with mode: 0644]
src/cmd/asm/internal/asm/operand_test.go
src/cmd/asm/internal/asm/testdata/arm.out [new file with mode: 0644]
src/cmd/asm/internal/asm/testdata/arm.s [new file with mode: 0644]
src/cmd/asm/internal/asm/testdata/ppc64.out [new file with mode: 0644]
src/cmd/asm/internal/asm/testdata/ppc64.s [new file with mode: 0644]
src/cmd/asm/internal/lex/lex.go

index 5d0d0801902cba1fa0a9427aea972ac723416be2..f0cf117f05a484ed0bf30e65029ad118e2cd50f0 100644 (file)
@@ -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 (file)
index 0000000..270f80d
--- /dev/null
@@ -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")
+}
index 4437b7d5a6050ef0ee7dd6ddf551e9c2d787feeb..1c4d983cf92fe5dac2dfdeca3189e5e3fb05d702 100644 (file)
@@ -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 (file)
index 0000000..af0b463
--- /dev/null
@@ -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 (file)
index 0000000..184ed9f
--- /dev/null
@@ -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 (file)
index 0000000..50bca55
--- /dev/null
@@ -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 (file)
index 0000000..1fb5398
--- /dev/null
@@ -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
index c48b74a101cb68b36fbd1717082d543d1653157e..6fce55f7f4041f4349b71b0d57533be5f71f7d3e 100644 (file)
@@ -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