1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
11 "cmd/asm/internal/arch"
12 "cmd/asm/internal/lex"
16 // A simple in-out test: Do we print what we parse?
18 func setArch(goarch string) (*arch.Arch, *obj.Link) {
19 os.Setenv("GOOS", "linux") // obj can handle this OS for all architectures.
20 architecture := arch.Set(goarch)
21 if architecture == nil {
22 panic("asm: unrecognized architecture " + goarch)
24 return architecture, obj.Linknew(architecture.LinkArch)
27 func newParser(goarch string) *Parser {
28 architecture, ctxt := setArch(goarch)
29 return NewParser(ctxt, architecture, nil)
32 func testOperandParser(t *testing.T, parser *Parser, tests []operandTest) {
33 for _, test := range tests {
34 parser.start(lex.Tokenize(test.input))
37 result := obj.Dconv(&emptyProg, &addr)
38 if result != test.output {
39 t.Errorf("fail at %s: got %s; expected %s\n", test.input, result, test.output)
44 func TestAMD64OperandParser(t *testing.T) {
45 parser := newParser("amd64")
46 testOperandParser(t, parser, amd64OperandTests)
49 func Test386OperandParser(t *testing.T) {
50 parser := newParser("386")
51 testOperandParser(t, parser, x86OperandTests)
54 func TestARMOperandParser(t *testing.T) {
55 parser := newParser("arm")
56 testOperandParser(t, parser, armOperandTests)
58 func TestARM64OperandParser(t *testing.T) {
59 parser := newParser("arm64")
60 testOperandParser(t, parser, arm64OperandTests)
63 func TestPPC64OperandParser(t *testing.T) {
64 parser := newParser("ppc64")
65 testOperandParser(t, parser, ppc64OperandTests)
68 func TestMIPS64OperandParser(t *testing.T) {
69 parser := newParser("mips64")
70 testOperandParser(t, parser, mips64OperandTests)
73 type operandTest struct {
77 // Examples collected by scanning all the assembly in the standard repo.
79 var amd64OperandTests = []operandTest{
80 {"$(-1.0)", "$(-1.0)"},
82 {"$(0x2000000+116)", "$33554548"},
83 {"$(0x3F<<7)", "$8064"},
85 {"$(1<<63)", "$-9223372036854775808"},
90 {"$0x000FFFFFFFFFFFFF", "$4503599627370495"},
95 {"$0x7fffffe00000", "$140737486258176"},
96 {"$0xfffffffffffff001", "$-4095"},
101 {"$1000000", "$1000000"},
102 {"$1000000000", "$1000000000"},
103 {"$__tsan_func_enter(SB)", "$__tsan_func_enter(SB)"},
104 {"$main(SB)", "$main(SB)"},
105 {"$masks<>(SB)", "$masks<>(SB)"},
106 {"$setg_gcc<>(SB)", "$setg_gcc<>(SB)"},
107 {"$shifts<>(SB)", "$shifts<>(SB)"},
108 {"$~(1<<63)", "$9223372036854775807"},
111 {"(((8)&0xf)*4)(SP)", "32(SP)"},
112 {"(((8-14)&0xf)*4)(SP)", "40(SP)"},
113 {"(6+8)(AX)", "14(AX)"},
114 {"(8*4)(BP)", "32(BP)"},
116 {"(AX)(CX*8)", "(AX)(CX*8)"},
117 {"(BP)(CX*4)", "(BP)(CX*4)"},
118 {"(BP)(DX*4)", "(BP)(DX*4)"},
119 {"(BP)(R8*4)", "(BP)(R8*4)"},
122 {"(DI)(BX*1)", "(DI)(BX*1)"},
125 {"(R9)(BX*8)", "(R9)(BX*8)"},
127 {"(SI)(BX*1)", "(SI)(BX*1)"},
128 {"(SI)(DX*1)", "(SI)(DX*1)"},
130 {"(SP)(AX*4)", "(SP)(AX*4)"},
131 {"32(SP)(BX*2)", "32(SP)(BX*2)"},
132 {"32323(SP)(R8*4)", "32323(SP)(R8*4)"},
134 {"-1(DI)(BX*1)", "-1(DI)(BX*1)"},
135 {"-3(PC)", "-3(PC)"},
136 {"-64(SI)(BX*1)", "-64(SI)(BX*1)"},
137 {"-96(SI)(BX*1)", "-96(SI)(BX*1)"},
172 {"_expand_key_128<>(SB)", "_expand_key_128<>(SB)"},
173 {"_seek<>(SB)", "_seek<>(SB)"},
174 {"a2+16(FP)", "a2+16(FP)"},
175 {"addr2+24(FP)", "addr2+24(FP)"},
176 {"asmcgocall<>(SB)", "asmcgocall<>(SB)"},
177 {"b+24(FP)", "b+24(FP)"},
178 {"b_len+32(FP)", "b_len+32(FP)"},
179 {"racecall<>(SB)", "racecall<>(SB)"},
180 {"rcv_name+20(FP)", "rcv_name+20(FP)"},
181 {"retoffset+28(FP)", "retoffset+28(FP)"},
182 {"runtime·_GetStdHandle(SB)", "runtime._GetStdHandle(SB)"},
183 {"sync\u2215atomic·AddInt64(SB)", "sync/atomic.AddInt64(SB)"},
184 {"timeout+20(FP)", "timeout+20(FP)"},
185 {"ts+16(FP)", "ts+16(FP)"},
186 {"x+24(FP)", "x+24(FP)"},
187 {"x·y(SB)", "x.y(SB)"},
188 {"x·y(SP)", "x.y(SP)"},
189 {"x·y+8(SB)", "x.y+8(SB)"},
190 {"x·y+8(SP)", "x.y+8(SP)"},
191 {"y+56(FP)", "y+56(FP)"},
192 {"·AddUint32(SB)", "\"\".AddUint32(SB)"},
193 {"·callReflect(SB)", "\"\".callReflect(SB)"},
194 {"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
197 var x86OperandTests = []operandTest{
198 {"$(2.928932188134524e-01)", "$(0.29289321881345243)"},
201 {"$0x00000000", "$0"},
202 {"$runtime·badmcall(SB)", "$runtime.badmcall(SB)"},
203 {"$setg_gcc<>(SB)", "$setg_gcc<>(SB)"},
205 {"(-64*1024+104)(SP)", "-65432(SP)"},
206 {"(0*4)(BP)", "(BP)"},
207 {"(1*4)(DI)", "4(DI)"},
208 {"(4*4)(BP)", "16(BP)"},
210 {"(BP)(CX*4)", "(BP)(CX*4)"},
211 {"(BP*8)", "0(BP*8)"},
214 {"*AX", "AX"}, // TODO: Should make * illegal here; a simple alias for JMP AX.
215 {"*runtime·_GetStdHandle(SB)", "*runtime._GetStdHandle(SB)"},
216 {"-(4+12)(DI)", "-16(DI)"},
217 {"-1(DI)(BX*1)", "-1(DI)(BX*1)"},
218 {"-96(DI)(BX*1)", "-96(DI)(BX*1)"},
242 {"asmcgocall<>(SB)", "asmcgocall<>(SB)"},
243 {"ax+4(FP)", "ax+4(FP)"},
244 {"ptime-12(SP)", "ptime-12(SP)"},
245 {"runtime·_NtWaitForSingleObject(SB)", "runtime._NtWaitForSingleObject(SB)"},
247 {"sec+4(FP)", "sec+4(FP)"},
248 {"shifts<>(SB)(CX*8)", "shifts<>(SB)(CX*8)"},
249 {"x+4(FP)", "x+4(FP)"},
250 {"·AddUint32(SB)", "\"\".AddUint32(SB)"},
251 {"·reflectcall(SB)", "\"\".reflectcall(SB)"},
252 {"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
255 var armOperandTests = []operandTest{
261 {"-12(R4)", "-12(R4)"},
264 {"12(R(1))", "12(R1)"},
265 {"12(R13)", "12(R13)"},
267 {"R0->(32-1)", "R0->31"},
268 {"R0<<R1", "R0<<R1"},
269 {"R0>>R(1)", "R0>>R1"},
270 {"R0@>(32-1)", "R0@>31"},
277 {"R1<<2(R3)", "R1<<2(R3)"},
278 {"R(1)<<2(R(3))", "R1<<2(R3)"},
287 {"[R0,R1,g,R15]", "[R0,R1,g,R15]"},
288 {"[R0-R7]", "[R0,R1,R2,R3,R4,R5,R6,R7]"},
289 {"[R(0)-R(7)]", "[R0,R1,R2,R3,R4,R5,R6,R7]"},
291 {"[R1-R12]", "[R1,R2,R3,R4,R5,R6,R7,R8,R9,g,R11,R12]"},
292 {"armCAS64(SB)", "armCAS64(SB)"},
293 {"asmcgocall<>(SB)", "asmcgocall<>(SB)"},
294 {"c+28(FP)", "c+28(FP)"},
296 {"gosave<>(SB)", "gosave<>(SB)"},
297 {"retlo+12(FP)", "retlo+12(FP)"},
298 {"runtime·_sfloat2(SB)", "runtime._sfloat2(SB)"},
299 {"·AddUint32(SB)", "\"\".AddUint32(SB)"},
300 {"(R1, R3)", "(R1, R3)"},
301 {"[R0,R1,g,R15", ""}, // Issue 11764 - asm hung parsing ']' missing register lists.
302 {"[):[o-FP", ""}, // Issue 12469 - there was no infinite loop for ARM; these are just sanity checks.
304 {"(", ""}, // Issue 12466 - backed up before beginning of line.
307 var ppc64OperandTests = []operandTest{
308 {"$((1<<63)-1)", "$9223372036854775807"},
309 {"$(-64*1024)", "$-65536"},
310 {"$(1024 * 8)", "$8192"},
312 {"$-24(R4)", "$-24(R4)"},
316 {"$0x7000", "$28672"},
317 {"$0x88888eef", "$2290650863"},
319 {"$_main<>(SB)", "$_main<>(SB)"},
320 {"$argframe(FP)", "$argframe(FP)"},
321 {"$runtime·tlsg(SB)", "$runtime.tlsg(SB)"},
323 {"(-288-3*8)(R1)", "-312(R1)"},
324 {"(16)(R7)", "16(R7)"},
331 {"(R5)(R6*1)", "(R5)(R6*1)"},
332 {"(R5+R6)", "(R5)(R6*1)"}, // Old syntax.
333 {"-1(R4)", "-1(R4)"},
334 {"-1(R5)", "-1(R5)"},
387 {"SPR(269)", "SPR(269)"},
390 {"ret+8(FP)", "ret+8(FP)"},
391 {"runtime·abort(SB)", "runtime.abort(SB)"},
392 {"·AddUint32(SB)", "\"\".AddUint32(SB)"},
393 {"·trunc(SB)", "\"\".trunc(SB)"},
394 {"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
397 var arm64OperandTests = []operandTest{
405 {"$1000000000", "$1000000000"},
406 {"$0x7fff3c000", "$34358935552"},
410 {"-16(RSP)", "-16(RSP)"},
411 {"16(RSP)", "16(RSP)"},
413 {"-1(R4)", "-1(R4)"},
414 {"18740(R5)", "18740(R5)"},
416 {"$-24(R4)", "$-24(R4)"},
417 {"-24(RSP)", "-24(RSP)"},
418 {"$24(RSP)", "$24(RSP)"},
419 {"-32(RSP)", "-32(RSP)"},
421 {"$(-64*1024)(R7)", "$-65536(R7)"},
423 {"a+0(FP)", "a(FP)"},
424 {"a1+8(FP)", "a1+8(FP)"},
425 {"·AddInt32(SB)", `"".AddInt32(SB)`},
426 {"runtime·divWVW(SB)", "runtime.divWVW(SB)"},
427 {"$argframe+0(FP)", "$argframe(FP)"},
428 {"$asmcgocall<>(SB)", "$asmcgocall<>(SB)"},
439 {"$4503601774854144.0", "$(4503601774854144.0)"},
440 {"$runtime·badsystemstack(SB)", "$runtime.badsystemstack(SB)"},
443 {"(R29, RSP)", "(R29, RSP)"},
444 {"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
447 var mips64OperandTests = []operandTest{
448 {"$((1<<63)-1)", "$9223372036854775807"},
449 {"$(-64*1024)", "$-65536"},
450 {"$(1024 * 8)", "$8192"},
452 {"$-24(R4)", "$-24(R4)"},
456 {"$0x7000", "$28672"},
457 {"$0x88888eef", "$2290650863"},
459 {"$_main<>(SB)", "$_main<>(SB)"},
460 {"$argframe(FP)", "$argframe(FP)"},
462 {"(-288-3*8)(R1)", "-312(R1)"},
463 {"(16)(R7)", "16(R7)"},
469 {"-1(R4)", "-1(R4)"},
470 {"-1(R5)", "-1(R5)"},
523 {"ret+8(FP)", "ret+8(FP)"},
524 {"runtime·abort(SB)", "runtime.abort(SB)"},
525 {"·AddUint32(SB)", "\"\".AddUint32(SB)"},
526 {"·trunc(SB)", "\"\".trunc(SB)"},
527 {"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.