aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/asm/internal/asm
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/asm/internal/asm')
-rw-r--r--src/cmd/asm/internal/asm/asm.go4
-rw-r--r--src/cmd/asm/internal/asm/endtoend_test.go32
-rw-r--r--src/cmd/asm/internal/asm/expr_test.go4
-rw-r--r--src/cmd/asm/internal/asm/line_test.go2
-rw-r--r--src/cmd/asm/internal/asm/operand_test.go42
-rw-r--r--src/cmd/asm/internal/asm/parse.go83
-rw-r--r--src/cmd/asm/internal/asm/pseudo_test.go14
-rw-r--r--src/cmd/asm/internal/asm/testdata/arm.s22
-rw-r--r--src/cmd/asm/internal/asm/testdata/arm64.s119
-rw-r--r--src/cmd/asm/internal/asm/testdata/arm64enc.s2
-rw-r--r--src/cmd/asm/internal/asm/testdata/arm64error.s177
-rw-r--r--src/cmd/asm/internal/asm/testdata/mips.s5
-rw-r--r--src/cmd/asm/internal/asm/testdata/mips64.s9
-rw-r--r--src/cmd/asm/internal/asm/testdata/ppc64.s55
-rw-r--r--src/cmd/asm/internal/asm/testdata/riscv64.s17
-rw-r--r--src/cmd/asm/internal/asm/testdata/riscv64error.s5
-rw-r--r--src/cmd/asm/internal/asm/testdata/s390x.s8
17 files changed, 402 insertions, 198 deletions
diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go
index 563e794706..375ef803bb 100644
--- a/src/cmd/asm/internal/asm/asm.go
+++ b/src/cmd/asm/internal/asm/asm.go
@@ -445,7 +445,7 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
// BC x,CR0EQ,...
// BC x,CR1LT,...
// BC x,CR1GT,...
- // The first and second case demonstrate a symbol name which is
+ // The first and second cases demonstrate a symbol name which is
// effectively discarded. In these cases, the offset determines
// the CR bit.
prog.Reg = a[1].Reg
@@ -909,7 +909,7 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
p.append(prog, cond, true)
}
-// symbolName returns the symbol name, or an error string if none if available.
+// symbolName returns the symbol name, or an error string if none is available.
func symbolName(addr *obj.Addr) string {
if addr.Sym != nil {
return addr.Sym.Name
diff --git a/src/cmd/asm/internal/asm/endtoend_test.go b/src/cmd/asm/internal/asm/endtoend_test.go
index ef41667c8e..6e1aa1cd95 100644
--- a/src/cmd/asm/internal/asm/endtoend_test.go
+++ b/src/cmd/asm/internal/asm/endtoend_test.go
@@ -30,7 +30,7 @@ func testEndToEnd(t *testing.T, goarch, file string) {
architecture, ctxt := setArch(goarch)
architecture.Init(ctxt)
lexer := lex.NewLexer(input)
- parser := NewParser(ctxt, architecture, lexer, false)
+ parser := NewParser(ctxt, architecture, lexer)
pList := new(obj.Plist)
var ok bool
testOut = new(strings.Builder) // The assembler writes test output to this buffer.
@@ -68,6 +68,11 @@ Diff:
continue
}
+ // Ignore GLOBL.
+ if strings.HasPrefix(line, "GLOBL ") {
+ continue
+ }
+
// The general form of a test input line is:
// // comment
// INST args [// printed form] [// hex encoding]
@@ -136,11 +141,17 @@ Diff:
// Turn relative (PC) into absolute (PC) automatically,
// so that most branch instructions don't need comments
// giving the absolute form.
- if len(f) > 0 && strings.HasSuffix(printed, "(PC)") {
- last := f[len(f)-1]
- n, err := strconv.Atoi(last[:len(last)-len("(PC)")])
+ if len(f) > 0 && strings.Contains(printed, "(PC)") {
+ index := len(f) - 1
+ suf := "(PC)"
+ for !strings.HasSuffix(f[index], suf) {
+ index--
+ suf = "(PC),"
+ }
+ str := f[index]
+ n, err := strconv.Atoi(str[:len(str)-len(suf)])
if err == nil {
- f[len(f)-1] = fmt.Sprintf("%d(PC)", seq+n)
+ f[index] = fmt.Sprintf("%d%s", seq+n, suf)
}
}
@@ -186,7 +197,7 @@ Diff:
t.Errorf(format, args...)
ok = false
}
- obj.Flushplist(ctxt, pList, nil, "")
+ obj.Flushplist(ctxt, pList, nil)
for p := top; p != nil; p = p.Link {
if p.As == obj.ATEXT {
@@ -272,8 +283,9 @@ var (
func testErrors(t *testing.T, goarch, file string, flags ...string) {
input := filepath.Join("testdata", file+".s")
architecture, ctxt := setArch(goarch)
+ architecture.Init(ctxt)
lexer := lex.NewLexer(input)
- parser := NewParser(ctxt, architecture, lexer, false)
+ parser := NewParser(ctxt, architecture, lexer)
pList := new(obj.Plist)
var ok bool
ctxt.Bso = bufio.NewWriter(os.Stdout)
@@ -299,7 +311,7 @@ func testErrors(t *testing.T, goarch, file string, flags ...string) {
}
}
pList.Firstpc, ok = parser.Parse()
- obj.Flushplist(ctxt, pList, nil, "")
+ obj.Flushplist(ctxt, pList, nil)
if ok && !failed {
t.Errorf("asm: %s had no errors", file)
}
@@ -366,10 +378,10 @@ func Test386EndToEnd(t *testing.T) {
}
func TestARMEndToEnd(t *testing.T) {
- defer func(old int) { buildcfg.GOARM = old }(buildcfg.GOARM)
+ defer func(old int) { buildcfg.GOARM.Version = old }(buildcfg.GOARM.Version)
for _, goarm := range []int{5, 6, 7} {
t.Logf("GOARM=%d", goarm)
- buildcfg.GOARM = goarm
+ buildcfg.GOARM.Version = goarm
testEndToEnd(t, "arm", "arm")
if goarm == 6 {
testEndToEnd(t, "arm", "armv6")
diff --git a/src/cmd/asm/internal/asm/expr_test.go b/src/cmd/asm/internal/asm/expr_test.go
index e9c92df1f3..1251594349 100644
--- a/src/cmd/asm/internal/asm/expr_test.go
+++ b/src/cmd/asm/internal/asm/expr_test.go
@@ -57,7 +57,7 @@ var exprTests = []exprTest{
}
func TestExpr(t *testing.T) {
- p := NewParser(nil, nil, nil, false) // Expression evaluation uses none of these fields of the parser.
+ p := NewParser(nil, nil, nil) // Expression evaluation uses none of these fields of the parser.
for i, test := range exprTests {
p.start(lex.Tokenize(test.input))
result := int64(p.expr())
@@ -113,7 +113,7 @@ func TestBadExpr(t *testing.T) {
}
func runBadTest(i int, test badExprTest, t *testing.T) (err error) {
- p := NewParser(nil, nil, nil, false) // Expression evaluation uses none of these fields of the parser.
+ p := NewParser(nil, nil, nil) // Expression evaluation uses none of these fields of the parser.
p.start(lex.Tokenize(test.input))
return tryParse(t, func() {
p.expr()
diff --git a/src/cmd/asm/internal/asm/line_test.go b/src/cmd/asm/internal/asm/line_test.go
index da857ced3a..01b058bd95 100644
--- a/src/cmd/asm/internal/asm/line_test.go
+++ b/src/cmd/asm/internal/asm/line_test.go
@@ -39,7 +39,7 @@ func testBadInstParser(t *testing.T, goarch string, tests []badInstTest) {
for i, test := range tests {
arch, ctxt := setArch(goarch)
tokenizer := lex.NewTokenizer("", strings.NewReader(test.input+"\n"), nil)
- parser := NewParser(ctxt, arch, tokenizer, false)
+ parser := NewParser(ctxt, arch, tokenizer)
err := tryParse(t, func() {
parser.Parse()
diff --git a/src/cmd/asm/internal/asm/operand_test.go b/src/cmd/asm/internal/asm/operand_test.go
index c7e251f50f..579f533223 100644
--- a/src/cmd/asm/internal/asm/operand_test.go
+++ b/src/cmd/asm/internal/asm/operand_test.go
@@ -23,12 +23,14 @@ func setArch(goarch string) (*arch.Arch, *obj.Link) {
if architecture == nil {
panic("asm: unrecognized architecture " + goarch)
}
- return architecture, obj.Linknew(architecture.LinkArch)
+ ctxt := obj.Linknew(architecture.LinkArch)
+ ctxt.Pkgpath = "pkg"
+ return architecture, ctxt
}
func newParser(goarch string) *Parser {
architecture, ctxt := setArch(goarch)
- return NewParser(ctxt, architecture, nil, false)
+ return NewParser(ctxt, architecture, nil)
}
// tryParse executes parse func in panicOnError=true context.
@@ -76,7 +78,7 @@ func testOperandParser(t *testing.T, parser *Parser, tests []operandTest) {
addr := obj.Addr{}
parser.operand(&addr)
var result string
- if parser.compilingRuntime {
+ if parser.allowABI {
result = obj.DconvWithABIDetail(&emptyProg, &addr)
} else {
result = obj.Dconv(&emptyProg, &addr)
@@ -91,7 +93,7 @@ func TestAMD64OperandParser(t *testing.T) {
parser := newParser("amd64")
testOperandParser(t, parser, amd64OperandTests)
testBadOperandParser(t, parser, amd64BadOperandTests)
- parser.compilingRuntime = true
+ parser.allowABI = true
testOperandParser(t, parser, amd64RuntimeOperandTests)
testBadOperandParser(t, parser, amd64BadOperandRuntimeTests)
}
@@ -304,8 +306,8 @@ var amd64OperandTests = []operandTest{
{"x·y+8(SB)", "x.y+8(SB)"},
{"x·y+8(SP)", "x.y+8(SP)"},
{"y+56(FP)", "y+56(FP)"},
- {"·AddUint32(SB)", "\"\".AddUint32(SB)"},
- {"·callReflect(SB)", "\"\".callReflect(SB)"},
+ {"·AddUint32(SB)", "pkg.AddUint32(SB)"},
+ {"·callReflect(SB)", "pkg.callReflect(SB)"},
{"[X0-X0]", "[X0-X0]"},
{"[ Z9 - Z12 ]", "[Z9-Z12]"},
{"[X0-AX]", "[X0-AX]"},
@@ -391,8 +393,8 @@ var x86OperandTests = []operandTest{
{"sec+4(FP)", "sec+4(FP)"},
{"shifts<>(SB)(CX*8)", "shifts<>(SB)(CX*8)"},
{"x+4(FP)", "x+4(FP)"},
- {"·AddUint32(SB)", "\"\".AddUint32(SB)"},
- {"·reflectcall(SB)", "\"\".reflectcall(SB)"},
+ {"·AddUint32(SB)", "pkg.AddUint32(SB)"},
+ {"·reflectcall(SB)", "pkg.reflectcall(SB)"},
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
}
@@ -440,7 +442,7 @@ var armOperandTests = []operandTest{
{"gosave<>(SB)", "gosave<>(SB)"},
{"retlo+12(FP)", "retlo+12(FP)"},
{"runtime·gogo(SB)", "runtime.gogo(SB)"},
- {"·AddUint32(SB)", "\"\".AddUint32(SB)"},
+ {"·AddUint32(SB)", "pkg.AddUint32(SB)"},
{"(R1, R3)", "(R1, R3)"},
{"[R0,R1,g,R15", ""}, // Issue 11764 - asm hung parsing ']' missing register lists.
{"[):[o-FP", ""}, // Issue 12469 - there was no infinite loop for ARM; these are just sanity checks.
@@ -629,8 +631,8 @@ var ppc64OperandTests = []operandTest{
{"g", "g"},
{"ret+8(FP)", "ret+8(FP)"},
{"runtime·abort(SB)", "runtime.abort(SB)"},
- {"·AddUint32(SB)", "\"\".AddUint32(SB)"},
- {"·trunc(SB)", "\"\".trunc(SB)"},
+ {"·AddUint32(SB)", "pkg.AddUint32(SB)"},
+ {"·trunc(SB)", "pkg.trunc(SB)"},
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
}
@@ -662,7 +664,7 @@ var arm64OperandTests = []operandTest{
{"$(8-1)", "$7"},
{"a+0(FP)", "a(FP)"},
{"a1+8(FP)", "a1+8(FP)"},
- {"·AddInt32(SB)", `"".AddInt32(SB)`},
+ {"·AddInt32(SB)", `pkg.AddInt32(SB)`},
{"runtime·divWVW(SB)", "runtime.divWVW(SB)"},
{"$argframe+0(FP)", "$argframe(FP)"},
{"$asmcgocall<>(SB)", "$asmcgocall<>(SB)"},
@@ -763,8 +765,8 @@ var mips64OperandTests = []operandTest{
{"RSB", "R28"},
{"ret+8(FP)", "ret+8(FP)"},
{"runtime·abort(SB)", "runtime.abort(SB)"},
- {"·AddUint32(SB)", "\"\".AddUint32(SB)"},
- {"·trunc(SB)", "\"\".trunc(SB)"},
+ {"·AddUint32(SB)", "pkg.AddUint32(SB)"},
+ {"·trunc(SB)", "pkg.trunc(SB)"},
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
}
@@ -846,8 +848,8 @@ var mipsOperandTests = []operandTest{
{"g", "g"},
{"ret+8(FP)", "ret+8(FP)"},
{"runtime·abort(SB)", "runtime.abort(SB)"},
- {"·AddUint32(SB)", "\"\".AddUint32(SB)"},
- {"·trunc(SB)", "\"\".trunc(SB)"},
+ {"·AddUint32(SB)", "pkg.AddUint32(SB)"},
+ {"·trunc(SB)", "pkg.trunc(SB)"},
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
}
@@ -928,8 +930,8 @@ var loong64OperandTests = []operandTest{
{"g", "g"},
{"ret+8(FP)", "ret+8(FP)"},
{"runtime·abort(SB)", "runtime.abort(SB)"},
- {"·AddUint32(SB)", "\"\".AddUint32(SB)"},
- {"·trunc(SB)", "\"\".trunc(SB)"},
+ {"·AddUint32(SB)", "pkg.AddUint32(SB)"},
+ {"·trunc(SB)", "pkg.trunc(SB)"},
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
}
@@ -1026,7 +1028,7 @@ var s390xOperandTests = []operandTest{
{"g", "g"},
{"ret+8(FP)", "ret+8(FP)"},
{"runtime·abort(SB)", "runtime.abort(SB)"},
- {"·AddUint32(SB)", "\"\".AddUint32(SB)"},
- {"·trunc(SB)", "\"\".trunc(SB)"},
+ {"·AddUint32(SB)", "pkg.AddUint32(SB)"},
+ {"·trunc(SB)", "pkg.trunc(SB)"},
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
}
diff --git a/src/cmd/asm/internal/asm/parse.go b/src/cmd/asm/internal/asm/parse.go
index 37f8e6c0bc..ef6c840dc2 100644
--- a/src/cmd/asm/internal/asm/parse.go
+++ b/src/cmd/asm/internal/asm/parse.go
@@ -12,6 +12,7 @@ import (
"log"
"os"
"strconv"
+ "strings"
"text/scanner"
"unicode/utf8"
@@ -21,31 +22,33 @@ import (
"cmd/internal/obj"
"cmd/internal/obj/arm64"
"cmd/internal/obj/x86"
+ "cmd/internal/objabi"
"cmd/internal/src"
"cmd/internal/sys"
)
type Parser struct {
- lex lex.TokenReader
- lineNum int // Line number in source file.
- errorLine int // Line number of last error.
- errorCount int // Number of errors.
- sawCode bool // saw code in this file (as opposed to comments and blank lines)
- pc int64 // virtual PC; count of Progs; doesn't advance for GLOBL or DATA.
- input []lex.Token
- inputPos int
- pendingLabels []string // Labels to attach to next instruction.
- labels map[string]*obj.Prog
- toPatch []Patch
- addr []obj.Addr
- arch *arch.Arch
- ctxt *obj.Link
- firstProg *obj.Prog
- lastProg *obj.Prog
- dataAddr map[string]int64 // Most recent address for DATA for this symbol.
- isJump bool // Instruction being assembled is a jump.
- compilingRuntime bool
- errorWriter io.Writer
+ lex lex.TokenReader
+ lineNum int // Line number in source file.
+ errorLine int // Line number of last error.
+ errorCount int // Number of errors.
+ sawCode bool // saw code in this file (as opposed to comments and blank lines)
+ pc int64 // virtual PC; count of Progs; doesn't advance for GLOBL or DATA.
+ input []lex.Token
+ inputPos int
+ pendingLabels []string // Labels to attach to next instruction.
+ labels map[string]*obj.Prog
+ toPatch []Patch
+ addr []obj.Addr
+ arch *arch.Arch
+ ctxt *obj.Link
+ firstProg *obj.Prog
+ lastProg *obj.Prog
+ dataAddr map[string]int64 // Most recent address for DATA for this symbol.
+ isJump bool // Instruction being assembled is a jump.
+ allowABI bool // Whether ABI selectors are allowed.
+ pkgPrefix string // Prefix to add to local symbols.
+ errorWriter io.Writer
}
type Patch struct {
@@ -53,15 +56,20 @@ type Patch struct {
label string
}
-func NewParser(ctxt *obj.Link, ar *arch.Arch, lexer lex.TokenReader, compilingRuntime bool) *Parser {
+func NewParser(ctxt *obj.Link, ar *arch.Arch, lexer lex.TokenReader) *Parser {
+ pkgPrefix := obj.UnlinkablePkg
+ if ctxt != nil {
+ pkgPrefix = objabi.PathToPrefix(ctxt.Pkgpath)
+ }
return &Parser{
- ctxt: ctxt,
- arch: ar,
- lex: lexer,
- labels: make(map[string]*obj.Prog),
- dataAddr: make(map[string]int64),
- errorWriter: os.Stderr,
- compilingRuntime: compilingRuntime,
+ ctxt: ctxt,
+ arch: ar,
+ lex: lexer,
+ labels: make(map[string]*obj.Prog),
+ dataAddr: make(map[string]int64),
+ errorWriter: os.Stderr,
+ allowABI: ctxt != nil && objabi.LookupPkgSpecial(ctxt.Pkgpath).AllowAsmABI,
+ pkgPrefix: pkgPrefix,
}
}
@@ -401,7 +409,7 @@ func (p *Parser) operand(a *obj.Addr) {
fallthrough
default:
// We have a symbol. Parse $sym±offset(symkind)
- p.symbolReference(a, name, prefix)
+ p.symbolReference(a, p.qualifySymbol(name), prefix)
}
// fmt.Printf("SYM %s\n", obj.Dconv(&emptyProg, 0, a))
if p.peek() == scanner.EOF {
@@ -769,6 +777,16 @@ func (p *Parser) registerExtension(a *obj.Addr, name string, prefix rune) {
}
}
+// qualifySymbol returns name as a package-qualified symbol name. If
+// name starts with a period, qualifySymbol prepends the package
+// prefix. Otherwise it returns name unchanged.
+func (p *Parser) qualifySymbol(name string) string {
+ if strings.HasPrefix(name, ".") {
+ name = p.pkgPrefix + name
+ }
+ return name
+}
+
// symbolReference parses a symbol that is known not to be a register.
func (p *Parser) symbolReference(a *obj.Addr, name string, prefix rune) {
// Identifier is a name.
@@ -864,7 +882,7 @@ func (p *Parser) symRefAttrs(name string, issueError bool) (bool, obj.ABI) {
isStatic = true
} else if tok == scanner.Ident {
abistr := p.get(scanner.Ident).String()
- if !p.compilingRuntime {
+ if !p.allowABI {
if issueError {
p.errorf("ABI selector only permitted when compiling runtime, reference was to %q", name)
}
@@ -901,6 +919,7 @@ func (p *Parser) funcAddress() (string, obj.ABI, bool) {
if tok.ScanToken != scanner.Ident || p.atStartOfRegister(name) {
return "", obj.ABI0, false
}
+ name = p.qualifySymbol(name)
// Parse optional <> (indicates a static symbol) or
// <ABIxxx> (selecting text symbol with specific ABI).
noErrMsg := false
@@ -928,7 +947,7 @@ func (p *Parser) funcAddress() (string, obj.ABI, bool) {
}
// registerIndirect parses the general form of a register indirection.
-// It is can be (R1), (R2*scale), (R1)(R2*scale), (R1)(R2.SXTX<<3) or (R1)(R2<<3)
+// It can be (R1), (R2*scale), (R1)(R2*scale), (R1)(R2.SXTX<<3) or (R1)(R2<<3)
// where R1 may be a simple register or register pair R:R or (R, R) or (R+R).
// Or it might be a pseudo-indirection like (FP).
// We are sitting on the opening parenthesis.
@@ -1186,7 +1205,7 @@ func (p *Parser) registerListX86(a *obj.Addr) {
a.Offset = x86.EncodeRegisterRange(lo, hi)
}
-// register number is ARM-specific. It returns the number of the specified register.
+// registerNumber is ARM-specific. It returns the number of the specified register.
func (p *Parser) registerNumber(name string) uint16 {
if p.arch.Family == sys.ARM && name == "g" {
return 10
diff --git a/src/cmd/asm/internal/asm/pseudo_test.go b/src/cmd/asm/internal/asm/pseudo_test.go
index 5e6fcf8dfe..b9be6a7b2d 100644
--- a/src/cmd/asm/internal/asm/pseudo_test.go
+++ b/src/cmd/asm/internal/asm/pseudo_test.go
@@ -64,16 +64,16 @@ func TestErroneous(t *testing.T) {
}
testcats := []struct {
- compilingRuntime bool
- tests []errtest
+ allowABI bool
+ tests []errtest
}{
{
- compilingRuntime: false,
- tests: nonRuntimeTests,
+ allowABI: false,
+ tests: nonRuntimeTests,
},
{
- compilingRuntime: true,
- tests: runtimeTests,
+ allowABI: true,
+ tests: runtimeTests,
},
}
@@ -85,7 +85,7 @@ func TestErroneous(t *testing.T) {
for _, cat := range testcats {
for _, test := range cat.tests {
- parser.compilingRuntime = cat.compilingRuntime
+ parser.allowABI = cat.allowABI
parser.errorCount = 0
parser.lineNum++
if !parser.pseudo(test.pseudo, tokenize(test.operands)) {
diff --git a/src/cmd/asm/internal/asm/testdata/arm.s b/src/cmd/asm/internal/asm/testdata/arm.s
index 2ba22c71de..93edc8854e 100644
--- a/src/cmd/asm/internal/asm/testdata/arm.s
+++ b/src/cmd/asm/internal/asm/testdata/arm.s
@@ -870,10 +870,13 @@ jmp_label_3:
BIC.S R0@>R1, R2 // 7021d2e1
// SRL
+ SRL $0, R5, R6 // 0560a0e1
+ SRL $1, R5, R6 // a560a0e1
SRL $14, R5, R6 // 2567a0e1
SRL $15, R5, R6 // a567a0e1
SRL $30, R5, R6 // 256fa0e1
SRL $31, R5, R6 // a56fa0e1
+ SRL $32, R5, R6 // 2560a0e1
SRL.S $14, R5, R6 // 2567b0e1
SRL.S $15, R5, R6 // a567b0e1
SRL.S $30, R5, R6 // 256fb0e1
@@ -892,10 +895,13 @@ jmp_label_3:
SRL.S R5, R7 // 3775b0e1
// SRA
+ SRA $0, R5, R6 // 0560a0e1
+ SRA $1, R5, R6 // c560a0e1
SRA $14, R5, R6 // 4567a0e1
SRA $15, R5, R6 // c567a0e1
SRA $30, R5, R6 // 456fa0e1
SRA $31, R5, R6 // c56fa0e1
+ SRA $32, R5, R6 // 4560a0e1
SRA.S $14, R5, R6 // 4567b0e1
SRA.S $15, R5, R6 // c567b0e1
SRA.S $30, R5, R6 // 456fb0e1
@@ -914,6 +920,8 @@ jmp_label_3:
SRA.S R5, R7 // 5775b0e1
// SLL
+ SLL $0, R5, R6 // 0560a0e1
+ SLL $1, R5, R6 // 8560a0e1
SLL $14, R5, R6 // 0567a0e1
SLL $15, R5, R6 // 8567a0e1
SLL $30, R5, R6 // 056fa0e1
@@ -935,6 +943,20 @@ jmp_label_3:
SLL R5, R7 // 1775a0e1
SLL.S R5, R7 // 1775b0e1
+// Ops with zero shifts should encode as left shifts
+ ADD R0<<0, R1, R2 // 002081e0
+ ADD R0>>0, R1, R2 // 002081e0
+ ADD R0->0, R1, R2 // 002081e0
+ ADD R0@>0, R1, R2 // 002081e0
+ MOVW R0<<0(R1), R2 // 002091e7
+ MOVW R0>>0(R1), R2 // 002091e7
+ MOVW R0->0(R1), R2 // 002091e7
+ MOVW R0@>0(R1), R2 // 002091e7
+ MOVW R0, R1<<0(R2) // 010082e7
+ MOVW R0, R1>>0(R2) // 010082e7
+ MOVW R0, R1->0(R2) // 010082e7
+ MOVW R0, R1@>0(R2) // 010082e7
+
// MULA / MULS
MULAWT R1, R2, R3, R4 // c23124e1
MULAWB R1, R2, R3, R4 // 823124e1
diff --git a/src/cmd/asm/internal/asm/testdata/arm64.s b/src/cmd/asm/internal/asm/testdata/arm64.s
index 11bd678552..ecad08b37a 100644
--- a/src/cmd/asm/internal/asm/testdata/arm64.s
+++ b/src/cmd/asm/internal/asm/testdata/arm64.s
@@ -557,37 +557,92 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
FMOVQ 65520(R10), F10 // 4afdff3d
FMOVQ 64(RSP), F11 // eb13c03d
-// large aligned offset, use two instructions(add+ldr/store).
- MOVB R1, 0x1001(R2) // MOVB R1, 4097(R2) // 5b04409161070039
- MOVH R1, 0x2002(R2) // MOVH R1, 8194(R2) // 5b08409161070079
- MOVW R1, 0x4004(R2) // MOVW R1, 16388(R2) // 5b104091610700b9
- MOVD R1, 0x8008(R2) // MOVD R1, 32776(R2) // 5b204091610700f9
- FMOVS F1, 0x4004(R2) // FMOVS F1, 16388(R2) // 5b104091610700bd
- FMOVD F1, 0x8008(R2) // FMOVD F1, 32776(R2) // 5b204091610700fd
+// medium offsets that either fit a single instruction or can use add+ldr/str
+ MOVD -4095(R17), R3 // 3bfe3fd1630340f9
+ MOVD -391(R17), R3 // 3b1e06d1630340f9
+ MOVD -257(R17), R3 // 3b0604d1630340f9
+ MOVD -256(R17), R3 // 230250f8
+ MOVD 255(R17), R3 // 23f24ff8
+ MOVD 256(R17), R3 // 238240f9
+ MOVD 257(R17), R3 // 3b060491630340f9
+ MOVD 391(R17), R3 // 3b1e0691630340f9
+ MOVD 4095(R17), R3 // 3bfe3f91630340f9
- MOVB 0x1001(R1), R2 // MOVB 4097(R1), R2 // 3b04409162078039
- MOVH 0x2002(R1), R2 // MOVH 8194(R1), R2 // 3b08409162078079
- MOVW 0x4004(R1), R2 // MOVW 16388(R1), R2 // 3b104091620780b9
- MOVD 0x8008(R1), R2 // MOVD 32776(R1), R2 // 3b204091620740f9
- FMOVS 0x4004(R1), F2 // FMOVS 16388(R1), F2 // 3b104091620740bd
- FMOVD 0x8008(R1), F2 // FMOVD 32776(R1), F2 // 3b204091620740fd
+ MOVD R0, -4095(R17) // 3bfe3fd1600300f9
+ MOVD R0, -391(R17) // 3b1e06d1600300f9
+ MOVD R0, -257(R17) // 3b0604d1600300f9
+ MOVD R0, -256(R17) // 200210f8
+ MOVD R0, 255(R17) // 20f20ff8
+ MOVD R0, 256(R17) // 208200f9
+ MOVD R0, 257(R17) // 3b060491600300f9
+ MOVD R0, 391(R17) // 3b1e0691600300f9
+ MOVD R0, 4095(R17) // 3bfe3f91600300f9
+ MOVD R0, 4096(R17) // 200208f9
+ MOVD R3, -4095(R17) // 3bfe3fd1630300f9
+ MOVD R3, -391(R17) // 3b1e06d1630300f9
+ MOVD R3, -257(R17) // 3b0604d1630300f9
+ MOVD R3, -256(R17) // 230210f8
+ MOVD R3, 255(R17) // 23f20ff8
+ MOVD R3, 256(R17) // 238200f9
+ MOVD R3, 257(R17) // 3b060491630300f9
+ MOVD R3, 391(R17) // 3b1e0691630300f9
+ MOVD R3, 4095(R17) // 3bfe3f91630300f9
+
+// large aligned offset, use two instructions(add+ldr/str).
+ MOVB R1, 0x1001(R2) // MOVB R1, 4097(R2) // 5b04409161070039
+ MOVB R1, 0xffffff(R2) // MOVB R1, 16777215(R2) // 5bfc7f9161ff3f39
+ MOVH R1, 0x2002(R2) // MOVH R1, 8194(R2) // 5b08409161070079
+ MOVH R1, 0x1000ffe(R2) // MOVH R1, 16781310(R2) // 5bfc7f9161ff3f79
+ MOVW R1, 0x4004(R2) // MOVW R1, 16388(R2) // 5b104091610700b9
+ MOVW R1, 0x1002ffc(R2) // MOVW R1, 16789500(R2) // 5bfc7f9161ff3fb9
+ MOVD R1, 0x8008(R2) // MOVD R1, 32776(R2) // 5b204091610700f9
+ MOVD R1, 0x1006ff8(R2) // MOVD R1, 16805880(R2) // 5bfc7f9161ff3ff9
+ FMOVS F1, 0x4004(R2) // FMOVS F1, 16388(R2) // 5b104091610700bd
+ FMOVS F1, 0x1002ffc(R2) // FMOVS F1, 16789500(R2) // 5bfc7f9161ff3fbd
+ FMOVD F1, 0x8008(R2) // FMOVD F1, 32776(R2) // 5b204091610700fd
+ FMOVD F1, 0x1006ff8(R2) // FMOVD F1, 16805880(R2) // 5bfc7f9161ff3ffd
+
+ MOVB 0x1001(R1), R2 // MOVB 4097(R1), R2 // 3b04409162078039
+ MOVB 0xffffff(R1), R2 // MOVB 16777215(R1), R2 // 3bfc7f9162ffbf39
+ MOVH 0x2002(R1), R2 // MOVH 8194(R1), R2 // 3b08409162078079
+ MOVH 0x1000ffe(R1), R2 // MOVH 16781310(R1), R2 // 3bfc7f9162ffbf79
+ MOVW 0x4004(R1), R2 // MOVW 16388(R1), R2 // 3b104091620780b9
+ MOVW 0x1002ffc(R1), R2 // MOVW 16789500(R1), R2 // 3bfc7f9162ffbfb9
+ MOVD 0x8008(R1), R2 // MOVD 32776(R1), R2 // 3b204091620740f9
+ MOVD 0x1006ff8(R1), R2 // MOVD 16805880(R1), R2 // 3bfc7f9162ff7ff9
+ FMOVS 0x4004(R1), F2 // FMOVS 16388(R1), F2 // 3b104091620740bd
+ FMOVS 0x1002ffc(R1), F2 // FMOVS 16789500(R1), F2 // 3bfc7f9162ff7fbd
+ FMOVD 0x8008(R1), F2 // FMOVD 32776(R1), F2 // 3b204091620740fd
+ FMOVD 0x1006ff8(R1), F2 // FMOVD 16805880(R1), F2 // 3bfc7f9162ff7ffd
// very large or unaligned offset uses constant pool.
// the encoding cannot be checked as the address of the constant pool is unknown.
// here we only test that they can be assembled.
- MOVB R1, 0x44332211(R2) // MOVB R1, 1144201745(R2)
- MOVH R1, 0x44332211(R2) // MOVH R1, 1144201745(R2)
- MOVW R1, 0x44332211(R2) // MOVW R1, 1144201745(R2)
- MOVD R1, 0x44332211(R2) // MOVD R1, 1144201745(R2)
- FMOVS F1, 0x44332211(R2) // FMOVS F1, 1144201745(R2)
- FMOVD F1, 0x44332211(R2) // FMOVD F1, 1144201745(R2)
+ MOVB R1, 0x1000000(R2) // MOVB R1, 16777216(R2)
+ MOVB R1, 0x44332211(R2) // MOVB R1, 1144201745(R2)
+ MOVH R1, 0x1001000(R2) // MOVH R1, 16781312(R2)
+ MOVH R1, 0x44332211(R2) // MOVH R1, 1144201745(R2)
+ MOVW R1, 0x1003000(R2) // MOVW R1, 16789504(R2)
+ MOVW R1, 0x44332211(R2) // MOVW R1, 1144201745(R2)
+ MOVD R1, 0x1007000(R2) // MOVD R1, 16805888(R2)
+ MOVD R1, 0x44332211(R2) // MOVD R1, 1144201745(R2)
+ FMOVS F1, 0x1003000(R2) // FMOVS F1, 16789504(R2)
+ FMOVS F1, 0x44332211(R2) // FMOVS F1, 1144201745(R2)
+ FMOVD F1, 0x1007000(R2) // FMOVD F1, 16805888(R2)
+ FMOVD F1, 0x44332211(R2) // FMOVD F1, 1144201745(R2)
- MOVB 0x44332211(R1), R2 // MOVB 1144201745(R1), R2
- MOVH 0x44332211(R1), R2 // MOVH 1144201745(R1), R2
- MOVW 0x44332211(R1), R2 // MOVW 1144201745(R1), R2
- MOVD 0x44332211(R1), R2 // MOVD 1144201745(R1), R2
- FMOVS 0x44332211(R1), F2 // FMOVS 1144201745(R1), F2
- FMOVD 0x44332211(R1), F2 // FMOVD 1144201745(R1), F2
+ MOVB 0x1000000(R1), R2 // MOVB 16777216(R1), R2
+ MOVB 0x44332211(R1), R2 // MOVB 1144201745(R1), R2
+ MOVH 0x1000000(R1), R2 // MOVH 16777216(R1), R2
+ MOVH 0x44332211(R1), R2 // MOVH 1144201745(R1), R2
+ MOVW 0x1000000(R1), R2 // MOVW 16777216(R1), R2
+ MOVW 0x44332211(R1), R2 // MOVW 1144201745(R1), R2
+ MOVD 0x1000000(R1), R2 // MOVD 16777216(R1), R2
+ MOVD 0x44332211(R1), R2 // MOVD 1144201745(R1), R2
+ FMOVS 0x1000000(R1), F2 // FMOVS 16777216(R1), F2
+ FMOVS 0x44332211(R1), F2 // FMOVS 1144201745(R1), F2
+ FMOVD 0x1000000(R1), F2 // FMOVD 16777216(R1), F2
+ FMOVD 0x44332211(R1), F2 // FMOVD 1144201745(R1), F2
// shifted or extended register offset.
MOVD (R2)(R6.SXTW), R4 // 44c866f8
@@ -595,6 +650,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
MOVD (R3)(R6*1), R5 // 656866f8
MOVD (R2)(R6), R4 // 446866f8
MOVWU (R19)(R20<<2), R20 // 747a74b8
+ MOVD (R2)(R3<<0), R1 // 416863f8
MOVD (R2)(R6<<3), R4 // 447866f8
MOVD (R3)(R7.SXTX<<3), R8 // 68f867f8
MOVWU (R5)(R4.UXTW), R10 // aa4864b8
@@ -604,7 +660,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
MOVHU (R1)(R2<<1), R5 // 25786278
MOVB (R9)(R3.UXTW), R6 // 2649a338
MOVB (R10)(R6), R15 // 4f69a638
- MOVB (R29)(R30<<0), R14 // ae7bbe38
+ MOVB (R29)(R30<<0), R14 // ae6bbe38
MOVB (R29)(R30), R14 // ae6bbe38
MOVH (R5)(R7.SXTX<<1), R19 // b3f8a778
MOVH (R8)(R4<<1), R10 // 0a79a478
@@ -925,6 +981,14 @@ again:
ADR next, R11 // ADR R11 // 2b000010
next:
NOP
+ ADR -2(PC), R10 // 0a000010
+ ADR 2(PC), R16 // 10000010
+ ADR -26(PC), R1 // 01000010
+ ADR 12(PC), R2 // 02000010
+ ADRP -2(PC), R10 // 0a000090
+ ADRP 2(PC), R16 // 10000090
+ ADRP -26(PC), R1 // 01000090
+ ADRP 12(PC), R2 // 02000090
// LDP/STP
LDP (R0), (R0, R1) // 000440a9
@@ -947,6 +1011,7 @@ next:
LDP -8(R0), (R1, R2) // 01887fa9
LDP x(SB), (R1, R2)
LDP x+8(SB), (R1, R2)
+ LDP 8(R1), (ZR, R2) // 3f8840a9
LDPW -5(R0), (R1, R2) // 1b1400d1610b4029
LDPW (R0), (R1, R2) // 01084029
LDPW 4(R0), (R1, R2) // 01884029
@@ -964,6 +1029,7 @@ next:
LDPW 1024(RSP), (R1, R2) // fb031091610b4029
LDPW x(SB), (R1, R2)
LDPW x+8(SB), (R1, R2)
+ LDPW 8(R1), (ZR, R2) // 3f084129
LDPSW (R0), (R1, R2) // 01084069
LDPSW 4(R0), (R1, R2) // 01884069
LDPSW -4(R0), (R1, R2) // 01887f69
@@ -980,6 +1046,7 @@ next:
LDPSW 1024(RSP), (R1, R2) // fb031091610b4069
LDPSW x(SB), (R1, R2)
LDPSW x+8(SB), (R1, R2)
+ LDPSW 8(R1), (ZR, R2) // 3f084169
STP (R3, R4), (R5) // a31000a9
STP (R3, R4), 8(R5) // a39000a9
STP.W (R3, R4), 8(R5) // a39080a9
diff --git a/src/cmd/asm/internal/asm/testdata/arm64enc.s b/src/cmd/asm/internal/asm/testdata/arm64enc.s
index 7ef3a7f5f0..cc002a1584 100644
--- a/src/cmd/asm/internal/asm/testdata/arm64enc.s
+++ b/src/cmd/asm/internal/asm/testdata/arm64enc.s
@@ -186,7 +186,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
MOVBU.P 42(R2), R12 // 4ca44238
MOVBU.W -27(R2), R14 // 4e5c5e38
MOVBU 2916(R24), R3 // 03936d39
- MOVBU (R19)(R14<<0), R23 // 777a6e38
+ MOVBU (R19)(R14<<0), R23 // 776a6e38
MOVBU (R2)(R8.SXTX), R19 // 53e86838
MOVBU (R27)(R23), R14 // 6e6b7738
MOVHU.P 107(R14), R13 // cdb54678
diff --git a/src/cmd/asm/internal/asm/testdata/arm64error.s b/src/cmd/asm/internal/asm/testdata/arm64error.s
index 354b64df02..3ac8788424 100644
--- a/src/cmd/asm/internal/asm/testdata/arm64error.s
+++ b/src/cmd/asm/internal/asm/testdata/arm64error.s
@@ -66,7 +66,6 @@ TEXT errors(SB),$0
LDP.W 8(R3), (R2, R3) // ERROR "constrained unpredictable behavior"
LDP (R1), (R2, R2) // ERROR "constrained unpredictable behavior"
LDP (R0), (F0, F1) // ERROR "invalid register pair"
- LDP (R0), (R3, ZR) // ERROR "invalid register pair"
LDXPW (RSP), (R2, R2) // ERROR "constrained unpredictable behavior"
LDAXPW (R5), (R2, R2) // ERROR "constrained unpredictable behavior"
MOVD.P 300(R2), R3 // ERROR "offset out of range [-256,255]"
@@ -166,94 +165,94 @@ TEXT errors(SB),$0
FSTPD (R1, R2), (R0) // ERROR "invalid register pair"
FMOVS (F2), F0 // ERROR "illegal combination"
FMOVD F0, (F1) // ERROR "illegal combination"
- LDADDAD R5, (R6), RSP // ERROR "illegal destination register"
- LDADDAW R5, (R6), RSP // ERROR "illegal destination register"
- LDADDAH R5, (R6), RSP // ERROR "illegal destination register"
- LDADDAB R5, (R6), RSP // ERROR "illegal destination register"
- LDADDALD R5, (R6), RSP // ERROR "illegal destination register"
- LDADDALW R5, (R6), RSP // ERROR "illegal destination register"
- LDADDALH R5, (R6), RSP // ERROR "illegal destination register"
- LDADDALB R5, (R6), RSP // ERROR "illegal destination register"
- LDADDD R5, (R6), RSP // ERROR "illegal destination register"
- LDADDW R5, (R6), RSP // ERROR "illegal destination register"
- LDADDH R5, (R6), RSP // ERROR "illegal destination register"
- LDADDB R5, (R6), RSP // ERROR "illegal destination register"
- LDADDLD R5, (R6), RSP // ERROR "illegal destination register"
- LDADDLW R5, (R6), RSP // ERROR "illegal destination register"
- LDADDLH R5, (R6), RSP // ERROR "illegal destination register"
- LDADDLB R5, (R6), RSP // ERROR "illegal destination register"
- LDCLRAD R5, (R6), RSP // ERROR "illegal destination register"
- LDCLRAW R5, (R6), RSP // ERROR "illegal destination register"
- LDCLRAH R5, (R6), RSP // ERROR "illegal destination register"
- LDCLRAB R5, (R6), RSP // ERROR "illegal destination register"
- LDCLRALD R5, (R6), RSP // ERROR "illegal destination register"
- LDCLRALW R5, (R6), RSP // ERROR "illegal destination register"
- LDCLRALH R5, (R6), RSP // ERROR "illegal destination register"
- LDCLRALB R5, (R6), RSP // ERROR "illegal destination register"
- LDCLRD R5, (R6), RSP // ERROR "illegal destination register"
- LDCLRW R5, (R6), RSP // ERROR "illegal destination register"
- LDCLRH R5, (R6), RSP // ERROR "illegal destination register"
- LDCLRB R5, (R6), RSP // ERROR "illegal destination register"
- LDCLRLD R5, (R6), RSP // ERROR "illegal destination register"
- LDCLRLW R5, (R6), RSP // ERROR "illegal destination register"
- LDCLRLH R5, (R6), RSP // ERROR "illegal destination register"
- LDCLRLB R5, (R6), RSP // ERROR "illegal destination register"
- LDEORAD R5, (R6), RSP // ERROR "illegal destination register"
- LDEORAW R5, (R6), RSP // ERROR "illegal destination register"
- LDEORAH R5, (R6), RSP // ERROR "illegal destination register"
- LDEORAB R5, (R6), RSP // ERROR "illegal destination register"
- LDEORALD R5, (R6), RSP // ERROR "illegal destination register"
- LDEORALW R5, (R6), RSP // ERROR "illegal destination register"
- LDEORALH R5, (R6), RSP // ERROR "illegal destination register"
- LDEORALB R5, (R6), RSP // ERROR "illegal destination register"
- LDEORD R5, (R6), RSP // ERROR "illegal destination register"
- LDEORW R5, (R6), RSP // ERROR "illegal destination register"
- LDEORH R5, (R6), RSP // ERROR "illegal destination register"
- LDEORB R5, (R6), RSP // ERROR "illegal destination register"
- LDEORLD R5, (R6), RSP // ERROR "illegal destination register"
- LDEORLW R5, (R6), RSP // ERROR "illegal destination register"
- LDEORLH R5, (R6), RSP // ERROR "illegal destination register"
- LDEORLB R5, (R6), RSP // ERROR "illegal destination register"
- LDORAD R5, (R6), RSP // ERROR "illegal destination register"
- LDORAW R5, (R6), RSP // ERROR "illegal destination register"
- LDORAH R5, (R6), RSP // ERROR "illegal destination register"
- LDORAB R5, (R6), RSP // ERROR "illegal destination register"
- LDORALD R5, (R6), RSP // ERROR "illegal destination register"
- LDORALW R5, (R6), RSP // ERROR "illegal destination register"
- LDORALH R5, (R6), RSP // ERROR "illegal destination register"
- LDORALB R5, (R6), RSP // ERROR "illegal destination register"
- LDORD R5, (R6), RSP // ERROR "illegal destination register"
- LDORW R5, (R6), RSP // ERROR "illegal destination register"
- LDORH R5, (R6), RSP // ERROR "illegal destination register"
- LDORB R5, (R6), RSP // ERROR "illegal destination register"
- LDORLD R5, (R6), RSP // ERROR "illegal destination register"
- LDORLW R5, (R6), RSP // ERROR "illegal destination register"
- LDORLH R5, (R6), RSP // ERROR "illegal destination register"
- LDORLB R5, (R6), RSP // ERROR "illegal destination register"
- SWPAD R5, (R6), RSP // ERROR "illegal destination register"
- SWPAW R5, (R6), RSP // ERROR "illegal destination register"
- SWPAH R5, (R6), RSP // ERROR "illegal destination register"
- SWPAB R5, (R6), RSP // ERROR "illegal destination register"
- SWPALD R5, (R6), RSP // ERROR "illegal destination register"
- SWPALW R5, (R6), RSP // ERROR "illegal destination register"
- SWPALH R5, (R6), RSP // ERROR "illegal destination register"
- SWPALB R5, (R6), RSP // ERROR "illegal destination register"
- SWPD R5, (R6), RSP // ERROR "illegal destination register"
- SWPW R5, (R6), RSP // ERROR "illegal destination register"
- SWPH R5, (R6), RSP // ERROR "illegal destination register"
- SWPB R5, (R6), RSP // ERROR "illegal destination register"
- SWPLD R5, (R6), RSP // ERROR "illegal destination register"
- SWPLW R5, (R6), RSP // ERROR "illegal destination register"
- SWPLH R5, (R6), RSP // ERROR "illegal destination register"
- SWPLB R5, (R6), RSP // ERROR "illegal destination register"
- STXR R5, (R6), RSP // ERROR "illegal destination register"
- STXRW R5, (R6), RSP // ERROR "illegal destination register"
- STLXR R5, (R6), RSP // ERROR "illegal destination register"
- STLXRW R5, (R6), RSP // ERROR "illegal destination register"
- STXP (R5, R7), (R6), RSP // ERROR "illegal destination register"
- STXPW (R5, R7), (R6), RSP // ERROR "illegal destination register"
- STLXP (R5, R7), (R6), RSP // ERROR "illegal destination register"
- STLXP (R5, R7), (R6), RSP // ERROR "illegal destination register"
+ LDADDAD R5, (R6), RSP // ERROR "illegal combination"
+ LDADDAW R5, (R6), RSP // ERROR "illegal combination"
+ LDADDAH R5, (R6), RSP // ERROR "illegal combination"
+ LDADDAB R5, (R6), RSP // ERROR "illegal combination"
+ LDADDALD R5, (R6), RSP // ERROR "illegal combination"
+ LDADDALW R5, (R6), RSP // ERROR "illegal combination"
+ LDADDALH R5, (R6), RSP // ERROR "illegal combination"
+ LDADDALB R5, (R6), RSP // ERROR "illegal combination"
+ LDADDD R5, (R6), RSP // ERROR "illegal combination"
+ LDADDW R5, (R6), RSP // ERROR "illegal combination"
+ LDADDH R5, (R6), RSP // ERROR "illegal combination"
+ LDADDB R5, (R6), RSP // ERROR "illegal combination"
+ LDADDLD R5, (R6), RSP // ERROR "illegal combination"
+ LDADDLW R5, (R6), RSP // ERROR "illegal combination"
+ LDADDLH R5, (R6), RSP // ERROR "illegal combination"
+ LDADDLB R5, (R6), RSP // ERROR "illegal combination"
+ LDCLRAD R5, (R6), RSP // ERROR "illegal combination"
+ LDCLRAW R5, (R6), RSP // ERROR "illegal combination"
+ LDCLRAH R5, (R6), RSP // ERROR "illegal combination"
+ LDCLRAB R5, (R6), RSP // ERROR "illegal combination"
+ LDCLRALD R5, (R6), RSP // ERROR "illegal combination"
+ LDCLRALW R5, (R6), RSP // ERROR "illegal combination"
+ LDCLRALH R5, (R6), RSP // ERROR "illegal combination"
+ LDCLRALB R5, (R6), RSP // ERROR "illegal combination"
+ LDCLRD R5, (R6), RSP // ERROR "illegal combination"
+ LDCLRW R5, (R6), RSP // ERROR "illegal combination"
+ LDCLRH R5, (R6), RSP // ERROR "illegal combination"
+ LDCLRB R5, (R6), RSP // ERROR "illegal combination"
+ LDCLRLD R5, (R6), RSP // ERROR "illegal combination"
+ LDCLRLW R5, (R6), RSP // ERROR "illegal combination"
+ LDCLRLH R5, (R6), RSP // ERROR "illegal combination"
+ LDCLRLB R5, (R6), RSP // ERROR "illegal combination"
+ LDEORAD R5, (R6), RSP // ERROR "illegal combination"
+ LDEORAW R5, (R6), RSP // ERROR "illegal combination"
+ LDEORAH R5, (R6), RSP // ERROR "illegal combination"
+ LDEORAB R5, (R6), RSP // ERROR "illegal combination"
+ LDEORALD R5, (R6), RSP // ERROR "illegal combination"
+ LDEORALW R5, (R6), RSP // ERROR "illegal combination"
+ LDEORALH R5, (R6), RSP // ERROR "illegal combination"
+ LDEORALB R5, (R6), RSP // ERROR "illegal combination"
+ LDEORD R5, (R6), RSP // ERROR "illegal combination"
+ LDEORW R5, (R6), RSP // ERROR "illegal combination"
+ LDEORH R5, (R6), RSP // ERROR "illegal combination"
+ LDEORB R5, (R6), RSP // ERROR "illegal combination"
+ LDEORLD R5, (R6), RSP // ERROR "illegal combination"
+ LDEORLW R5, (R6), RSP // ERROR "illegal combination"
+ LDEORLH R5, (R6), RSP // ERROR "illegal combination"
+ LDEORLB R5, (R6), RSP // ERROR "illegal combination"
+ LDORAD R5, (R6), RSP // ERROR "illegal combination"
+ LDORAW R5, (R6), RSP // ERROR "illegal combination"
+ LDORAH R5, (R6), RSP // ERROR "illegal combination"
+ LDORAB R5, (R6), RSP // ERROR "illegal combination"
+ LDORALD R5, (R6), RSP // ERROR "illegal combination"
+ LDORALW R5, (R6), RSP // ERROR "illegal combination"
+ LDORALH R5, (R6), RSP // ERROR "illegal combination"
+ LDORALB R5, (R6), RSP // ERROR "illegal combination"
+ LDORD R5, (R6), RSP // ERROR "illegal combination"
+ LDORW R5, (R6), RSP // ERROR "illegal combination"
+ LDORH R5, (R6), RSP // ERROR "illegal combination"
+ LDORB R5, (R6), RSP // ERROR "illegal combination"
+ LDORLD R5, (R6), RSP // ERROR "illegal combination"
+ LDORLW R5, (R6), RSP // ERROR "illegal combination"
+ LDORLH R5, (R6), RSP // ERROR "illegal combination"
+ LDORLB R5, (R6), RSP // ERROR "illegal combination"
+ SWPAD R5, (R6), RSP // ERROR "illegal combination"
+ SWPAW R5, (R6), RSP // ERROR "illegal combination"
+ SWPAH R5, (R6), RSP // ERROR "illegal combination"
+ SWPAB R5, (R6), RSP // ERROR "illegal combination"
+ SWPALD R5, (R6), RSP // ERROR "illegal combination"
+ SWPALW R5, (R6), RSP // ERROR "illegal combination"
+ SWPALH R5, (R6), RSP // ERROR "illegal combination"
+ SWPALB R5, (R6), RSP // ERROR "illegal combination"
+ SWPD R5, (R6), RSP // ERROR "illegal combination"
+ SWPW R5, (R6), RSP // ERROR "illegal combination"
+ SWPH R5, (R6), RSP // ERROR "illegal combination"
+ SWPB R5, (R6), RSP // ERROR "illegal combination"
+ SWPLD R5, (R6), RSP // ERROR "illegal combination"
+ SWPLW R5, (R6), RSP // ERROR "illegal combination"
+ SWPLH R5, (R6), RSP // ERROR "illegal combination"
+ SWPLB R5, (R6), RSP // ERROR "illegal combination"
+ STXR R5, (R6), RSP // ERROR "illegal combination"
+ STXRW R5, (R6), RSP // ERROR "illegal combination"
+ STLXR R5, (R6), RSP // ERROR "illegal combination"
+ STLXRW R5, (R6), RSP // ERROR "illegal combination"
+ STXP (R5, R7), (R6), RSP // ERROR "illegal combination"
+ STXPW (R5, R7), (R6), RSP // ERROR "illegal combination"
+ STLXP (R5, R7), (R6), RSP // ERROR "illegal combination"
+ STLXP (R5, R7), (R6), RSP // ERROR "illegal combination"
MSR OSLAR_EL1, R5 // ERROR "illegal combination"
MRS R11, AIDR_EL1 // ERROR "illegal combination"
MSR R6, AIDR_EL1 // ERROR "system register is not writable"
diff --git a/src/cmd/asm/internal/asm/testdata/mips.s b/src/cmd/asm/internal/asm/testdata/mips.s
index 7136d686d7..f65eba07ba 100644
--- a/src/cmd/asm/internal/asm/testdata/mips.s
+++ b/src/cmd/asm/internal/asm/testdata/mips.s
@@ -429,6 +429,11 @@ label4:
CLZ R1, R2 // 70221020
CLO R1, R2 // 70221021
+ WSBH R1, R2 // 7c0110a0
+
+ SEB R1, R2 // 7c011420
+ SEH R1, R2 // 7c011620
+
// to (Hi, Lo)
MADD R2, R1 // 70220000
MSUB R2, R1 // 70220004
diff --git a/src/cmd/asm/internal/asm/testdata/mips64.s b/src/cmd/asm/internal/asm/testdata/mips64.s
index 8f628e26c9..ea4bb80aec 100644
--- a/src/cmd/asm/internal/asm/testdata/mips64.s
+++ b/src/cmd/asm/internal/asm/testdata/mips64.s
@@ -587,8 +587,17 @@ label4:
CALL foo(SB)
RET foo(SB)
+ // unary operation
NEGW R1, R2 // 00011023
NEGV R1, R2 // 0001102f
+
+ WSBH R1, R2 // 7c0110a0
+ DSBH R1, R2 // 7c0110a4
+ DSHD R1, R2 // 7c011164
+
+ SEB R1, R2 // 7c011420
+ SEH R1, R2 // 7c011620
+
RET
// MSA VMOVI
diff --git a/src/cmd/asm/internal/asm/testdata/ppc64.s b/src/cmd/asm/internal/asm/testdata/ppc64.s
index a0f1276aa1..01052b49e7 100644
--- a/src/cmd/asm/internal/asm/testdata/ppc64.s
+++ b/src/cmd/asm/internal/asm/testdata/ppc64.s
@@ -17,14 +17,14 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
MOVD $1, R3 // 38600001
MOVD $-1, R4 // 3880ffff
MOVD $65535, R5 // 6005ffff
- MOVD $65536, R6 // 64060001
+ MOVD $65536, R6 // 3cc00001
MOVD $-32767, R5 // 38a08001
MOVD $-32768, R6 // 38c08000
MOVD $1234567, R5 // 6405001260a5d687 or 0600001238a0d687
MOVW $1, R3 // 38600001
MOVW $-1, R4 // 3880ffff
MOVW $65535, R5 // 6005ffff
- MOVW $65536, R6 // 64060001
+ MOVW $65536, R6 // 3cc00001
MOVW $-32767, R5 // 38a08001
MOVW $-32768, R6 // 38c08000
MOVW $1234567, R5 // 6405001260a5d687 or 0600001238a0d687
@@ -32,7 +32,26 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
MOVW $2147483649, R5 // 6405800060a50001 or 0600800038a00001
MOVD $2147483649, R5 // 6405800060a50001 or 0600800038a00001
// Hex constant 0xFFFFFFFF80000001
- MOVD $-2147483647, R5 // 3ca0800060a50001 or 0603800038a00001
+ MOVD $-2147483647, R5 // 3ca0800060a50001 or 0603800038a00001
+ // Hex constant 0xFFFFFFFE00000002 (load of constant on < power10, pli on >= power10
+ MOVD $-8589934590, R5 // 3ca00000e8a50000 or 0602000038a00002
+
+ // For backwards compatibility, MOVW $const,Rx and MOVWZ $const,Rx assemble identically
+ // and accept the same constants.
+ MOVW $2147483648, R5 // 64058000
+ MOVWZ $-2147483648, R5 // 3ca08000
+
+ // TODO: These are preprocessed by the assembler into MOVD $const>>shift, R5; SLD $shift, R5.
+ // This only captures the MOVD. Should the SLD be appended to the encoding by the test?
+ // Hex constant 0x20004000000
+ MOVD $2199090364416, R5 // 60058001
+ // Hex constant 0xFFFFFE0004000000
+ MOVD $-2198956146688, R5 // 38a08001
+ // TODO: On GOPPC64={power8,power9}, this is preprocessed into MOVD $-1, R5; RLDC R5, $33, $63, R5.
+ // This only captures the MOVD. Should the RLDC be appended to the encoding by the test?
+ // Hex constant 0xFFFFFFFE00000001
+ MOVD $-8589934591, R5 // 38a0ffff or 0602000038a00001
+
MOVD 8(R3), R4 // e8830008
MOVD (R3)(R4), R5 // 7ca4182a
MOVD (R3)(R0), R5 // 7ca0182a
@@ -164,6 +183,10 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
ADD $-32767, R5, R4 // 38858001
ADD $-32768, R6 // 38c68000
ADD $-32768, R6, R5 // 38a68000
+ // Hex constant 0xFFFFFFFE00000000
+ ADD $-8589934592, R5 // 3fe0fffe600000007bff83e4600000007cbf2a14 or 0602000038a50000
+ // Hex constant 0xFFFFFFFE00010001
+ ADD $-8589869055, R5 // 3fe0fffe63ff00017bff83e463ff00017cbf2a14 or 0602000138a50001
//TODO: this compiles to add r5,r6,r0. It should be addi r5,r6,0.
// this is OK since r0 == $0, but the latter is preferred.
@@ -174,6 +197,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
ADDEX R3, R5, $3, R6 // 7cc32f54
ADDEX R3, $3, R5, R6 // 7cc32f54
ADDIS $8, R3 // 3c630008
+ ADD $524288, R3 // 3c630008
ADDIS $1000, R3, R4 // 3c8303e8
ANDCC $1, R3 // 70630001
@@ -192,6 +216,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
ANDCC $1234567, R5, R6 // 641f001263ffd6877fe62839
ANDISCC $1, R3 // 74630001
ANDISCC $1000, R3, R4 // 746403e8
+ ANDCC $65536000, R3, R4 // 746403e8
OR $1, R3 // 60630001
OR $1, R3, R4 // 60640001
@@ -207,7 +232,10 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
OR $-32768, R6, R7 // 3be080007fe73378
OR $1234567, R5 // 641f001263ffd6877fe52b78
OR $1234567, R5, R3 // 641f001263ffd6877fe32b78
- ORIS $255, R3, R4
+ OR $2147483648, R5, R3 // 64a38000
+ OR $2147483649, R5, R3 // 641f800063ff00017fe32b78
+ ORIS $255, R3, R4 // 646400ff
+ OR $16711680, R3, R4 // 646400ff
XOR $1, R3 // 68630001
XOR $1, R3, R4 // 68640001
@@ -223,7 +251,8 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
XOR $-32768, R6, R7 // 3be080007fe73278
XOR $1234567, R5 // 641f001263ffd6877fe52a78
XOR $1234567, R5, R3 // 641f001263ffd6877fe32a78
- XORIS $15, R3, R4
+ XORIS $15, R3, R4 // 6c64000f
+ XOR $983040, R3, R4 // 6c64000f
// TODO: the order of CR operands don't match
CMP R3, R4 // 7c232000
@@ -233,7 +262,6 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
CMPB R3,R4,R4 // 7c6423f8
CMPEQB R3,R4,CR6 // 7f0321c0
- // TODO: constants for ADDC?
ADD R3, R4 // 7c841a14
ADD R3, R4, R5 // 7ca41a14
ADDC R3, R4 // 7c841814
@@ -246,6 +274,8 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
ADDV R3, R4 // 7c841e14
ADDVCC R3, R4 // 7c841e15
ADDCCC R3, R4, R5 // 7ca41815
+ ADDCCC $65536, R4, R5 // 641f0001600000007cbf2015
+ ADDCCC $65537, R4, R5 // 641f000163ff00017cbf2015
ADDME R3, R4 // 7c8301d4
ADDMECC R3, R4 // 7c8301d5
ADDMEV R3, R4 // 7c8305d4
@@ -299,6 +329,8 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
SUBECC R3, R4, R5 // 7ca32111
SUBEV R3, R4, R5 // 7ca32510
SUBEVCC R3, R4, R5 // 7ca32511
+ SUBC R3, $65536, R4 // 3fe00001600000007c83f810
+ SUBC R3, $65537, R4 // 3fe0000163ff00017c83f810
MULLW R3, R4 // 7c8419d6
MULLW R3, R4, R5 // 7ca419d6
@@ -393,12 +425,19 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
EXTSHCC R3, R4 // 7c640735
EXTSW R3, R4 // 7c6407b4
EXTSWCC R3, R4 // 7c6407b5
+ RLWMI $7, R3, $4026531855, R6 // 50663f06
+ RLWMI $7, R3, $1, R6 // 50663ffe
+ RLWMI $7, R3, $2147483648, R6 // 50663800
RLWMI $7, R3, $65535, R6 // 50663c3e
RLWMI $7, R3, $16, $31, R6 // 50663c3e
RLWMICC $7, R3, $65535, R6 // 50663c3f
RLWMICC $7, R3, $16, $31, R6 // 50663c3f
RLWNM $3, R4, $7, R6 // 54861f7e
+ RLWNM $0, R4, $7, R6 // 5486077e
+ RLWNM R0, R4, $7, R6 // 5c86077e
RLWNM $3, R4, $29, $31, R6 // 54861f7e
+ RLWNM $0, R4, $29, $31, R6 // 5486077e
+ RLWNM R0, R4, $29, $31, R6 // 5c86077e
RLWNM R3, R4, $7, R6 // 5c861f7e
RLWNM R3, R4, $29, $31, R6 // 5c861f7e
RLWNMCC $3, R4, $7, R6 // 54861f7f
@@ -410,6 +449,10 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
RLDIMI $0, R4, $7, R6 // 788601cc
RLDIMICC $0, R4, $7, R6 // 788601cd
RLDC $0, R4, $15, R6 // 78860728
+ RLDC R3, $32, $12, R4 // 7864030a
+ RLDC R3, $8, $32, R4 // 78644028
+ RLDCCC R3, $32, $12, R4 // 7864030b
+ RLDCCC R3, $8, $32, R4 // 78644029
RLDCCC $0, R4, $15, R6 // 78860729
RLDCL $0, R4, $7, R6 // 78860770
RLDCLCC $0, R4, $15, R6 // 78860721
diff --git a/src/cmd/asm/internal/asm/testdata/riscv64.s b/src/cmd/asm/internal/asm/testdata/riscv64.s
index 53538320f0..072302b225 100644
--- a/src/cmd/asm/internal/asm/testdata/riscv64.s
+++ b/src/cmd/asm/internal/asm/testdata/riscv64.s
@@ -94,6 +94,10 @@ start:
SUB X6, X5, X7 // b3836240
SUB X5, X6 // 33035340
+ SUB $-2047, X5, X6 // 1383f27f
+ SUB $2048, X5, X6 // 13830280
+ SUB $-2047, X5 // 9382f27f
+ SUB $2048, X5 // 93820280
SRA X6, X5, X7 // b3d36240
SRA X5, X6 // 33535340
@@ -157,6 +161,7 @@ start:
ADDW $1, X6 // 1b031300
SLLW $1, X6 // 1b131300
SRLW $1, X6 // 1b531300
+ SUBW $1, X6 // 1b03f3ff
SRAW $1, X6 // 1b531340
// 5.3: Load and Store Instructions (RV64I)
@@ -354,6 +359,14 @@ start:
MOVD F0, 4(X5) // 27b20200
MOVD F0, F1 // d3000022
+ // TLS load with local-exec (LUI + ADDIW + ADD of TP + load)
+ MOV tls(SB), X5 // b70f00009b8f0f00b38f4f0083b20f00
+ MOVB tls(SB), X5 // b70f00009b8f0f00b38f4f0083820f00
+
+ // TLS store with local-exec (LUI + ADDIW + ADD of TP + store)
+ MOV X5, tls(SB) // b70f00009b8f0f00b38f4f0023b05f00
+ MOVB X5, tls(SB) // b70f00009b8f0f00b38f4f0023805f00
+
// NOT pseudo-instruction
NOT X5 // 93c2f2ff
NOT X5, X6 // 13c3f2ff
@@ -373,7 +386,7 @@ start:
JMP 4(X5) // 67804200
// CALL and JMP to symbol are encoded as JAL (using LR or ZERO
- // respectively), with a R_RISCV_CALL relocation. The linker resolves
+ // respectively), with a R_RISCV_JAL relocation. The linker resolves
// the real address and updates the immediate, using a trampoline in
// the case where the address is not directly reachable.
CALL asmtest(SB) // ef000000
@@ -407,3 +420,5 @@ start:
FLTD F0, F1, X5 // d39200a2
FLED F0, F1, X5 // d38200a2
FEQD F0, F1, X5 // d3a200a2
+
+GLOBL tls(SB), TLSBSS, $8
diff --git a/src/cmd/asm/internal/asm/testdata/riscv64error.s b/src/cmd/asm/internal/asm/testdata/riscv64error.s
index cdb8a028bd..2dc9db3fb1 100644
--- a/src/cmd/asm/internal/asm/testdata/riscv64error.s
+++ b/src/cmd/asm/internal/asm/testdata/riscv64error.s
@@ -38,5 +38,8 @@ TEXT errors(SB),$0
SLLIW $-1, X5, X6 // ERROR "shift amount out of range 0 to 31"
SRLIW $-1, X5, X6 // ERROR "shift amount out of range 0 to 31"
SRAIW $-1, X5, X6 // ERROR "shift amount out of range 0 to 31"
-
+ SD X5, 4294967296(X6) // ERROR "constant 4294967296 too large"
+ SRLI $1, X5, F1 // ERROR "expected integer register in rd position but got non-integer register F1"
+ SRLI $1, F1, X5 // ERROR "expected integer register in rs1 position but got non-integer register F1"
+ FNES F1, (X5) // ERROR "needs an integer register output"
RET
diff --git a/src/cmd/asm/internal/asm/testdata/s390x.s b/src/cmd/asm/internal/asm/testdata/s390x.s
index 78ccb96fc1..977190678f 100644
--- a/src/cmd/asm/internal/asm/testdata/s390x.s
+++ b/src/cmd/asm/internal/asm/testdata/s390x.s
@@ -415,6 +415,14 @@ TEXT main·foo(SB),DUPOK|NOSPLIT,$16-0 // TEXT main.foo(SB), DUPOK|NOSPLIT, $16-
SYNC // 07e0
+ KM R2, R4 // b92e0024
+ KMC R2, R6 // b92f0026
+ KLMD R2, R8 // b93f0028
+ KIMD R0, R4 // b93e0004
+ KDSA R0, R8 // b93a0008
+ KMA R2, R6, R4 // b9296024
+ KMCTR R2, R6, R4 // b92d6024
+
// vector add and sub instructions
VAB V3, V4, V4 // e743400000f3
VAH V3, V4, V4 // e743400010f3