Skip to content

Commit 43ea305

Browse files
cherrymuiminux
authored andcommitted
cmd/asm: added support for GOARCH=mips64{,le}
Change-Id: I951387f88993715e86b6ab9f18d38ed5c691ee0f Reviewed-on: https://go-review.googlesource.com/14443 Reviewed-by: Minux Ma <[email protected]>
1 parent fa6a1ec commit 43ea305

7 files changed

Lines changed: 728 additions & 0 deletions

File tree

src/cmd/asm/internal/arch/arch.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"cmd/internal/obj"
99
"cmd/internal/obj/arm"
1010
"cmd/internal/obj/arm64"
11+
"cmd/internal/obj/mips"
1112
"cmd/internal/obj/ppc64"
1213
"cmd/internal/obj/x86"
1314
"fmt"
@@ -65,6 +66,14 @@ func Set(GOARCH string) *Arch {
6566
return archArm()
6667
case "arm64":
6768
return archArm64()
69+
case "mips64":
70+
a := archMips64()
71+
a.LinkArch = &mips.Linkmips64
72+
return a
73+
case "mips64le":
74+
a := archMips64()
75+
a.LinkArch = &mips.Linkmips64le
76+
return a
6877
case "ppc64":
6978
a := archPPC64()
7079
a.LinkArch = &ppc64.Linkppc64
@@ -363,3 +372,57 @@ func archPPC64() *Arch {
363372
IsJump: jumpPPC64,
364373
}
365374
}
375+
376+
func archMips64() *Arch {
377+
register := make(map[string]int16)
378+
// Create maps for easy lookup of instruction names etc.
379+
// Note that there is no list of names as there is for x86.
380+
for i := mips.REG_R0; i <= mips.REG_R31; i++ {
381+
register[obj.Rconv(i)] = int16(i)
382+
}
383+
for i := mips.REG_F0; i <= mips.REG_F31; i++ {
384+
register[obj.Rconv(i)] = int16(i)
385+
}
386+
for i := mips.REG_M0; i <= mips.REG_M31; i++ {
387+
register[obj.Rconv(i)] = int16(i)
388+
}
389+
for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ {
390+
register[obj.Rconv(i)] = int16(i)
391+
}
392+
register["HI"] = mips.REG_HI
393+
register["LO"] = mips.REG_LO
394+
// Pseudo-registers.
395+
register["SB"] = RSB
396+
register["FP"] = RFP
397+
register["PC"] = RPC
398+
// Avoid unintentionally clobbering g using R30.
399+
delete(register, "R30")
400+
register["g"] = mips.REG_R30
401+
registerPrefix := map[string]bool{
402+
"F": true,
403+
"FCR": true,
404+
"M": true,
405+
"R": true,
406+
}
407+
408+
instructions := make(map[string]int)
409+
for i, s := range obj.Anames {
410+
instructions[s] = i
411+
}
412+
for i, s := range mips.Anames {
413+
if i >= obj.A_ARCHSPECIFIC {
414+
instructions[s] = i + obj.ABaseMIPS64
415+
}
416+
}
417+
// Annoying alias.
418+
instructions["JAL"] = mips.AJAL
419+
420+
return &Arch{
421+
LinkArch: &mips.Linkmips64,
422+
Instructions: instructions,
423+
Register: register,
424+
RegisterPrefix: registerPrefix,
425+
RegisterNumber: mipsRegisterNumber,
426+
IsJump: jumpMIPS64,
427+
}
428+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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.
4+
5+
// This file encapsulates some of the odd characteristics of the
6+
// 64-bit MIPS (MIPS64) instruction set, to minimize its interaction
7+
// with the core of the assembler.
8+
9+
package arch
10+
11+
import "cmd/internal/obj/mips"
12+
13+
func jumpMIPS64(word string) bool {
14+
switch word {
15+
case "BEQ", "BFPF", "BFPT", "BGEZ", "BGEZAL", "BGTZ", "BLEZ", "BLTZ", "BLTZAL", "BNE", "JMP", "JAL", "CALL":
16+
return true
17+
}
18+
return false
19+
}
20+
21+
// IsMIPS64CMP reports whether the op (as defined by an mips.A* constant) is
22+
// one of the CMP instructions that require special handling.
23+
func IsMIPS64CMP(op int) bool {
24+
switch op {
25+
case mips.ACMPEQF, mips.ACMPEQD, mips.ACMPGEF, mips.ACMPGED,
26+
mips.ACMPGTF, mips.ACMPGTD:
27+
return true
28+
}
29+
return false
30+
}
31+
32+
// IsMIPS64MUL reports whether the op (as defined by an mips.A* constant) is
33+
// one of the MUL/DIV/REM instructions that require special handling.
34+
func IsMIPS64MUL(op int) bool {
35+
switch op {
36+
case mips.AMUL, mips.AMULU, mips.AMULV, mips.AMULVU,
37+
mips.ADIV, mips.ADIVU, mips.ADIVV, mips.ADIVVU,
38+
mips.AREM, mips.AREMU, mips.AREMV, mips.AREMVU:
39+
return true
40+
}
41+
return false
42+
}
43+
44+
func mipsRegisterNumber(name string, n int16) (int16, bool) {
45+
switch name {
46+
case "F":
47+
if 0 <= n && n <= 31 {
48+
return mips.REG_F0 + n, true
49+
}
50+
case "FCR":
51+
if 0 <= n && n <= 31 {
52+
return mips.REG_FCR0 + n, true
53+
}
54+
case "M":
55+
if 0 <= n && n <= 31 {
56+
return mips.REG_M0 + n, true
57+
}
58+
case "R":
59+
if 0 <= n && n <= 31 {
60+
return mips.REG_R0 + n, true
61+
}
62+
}
63+
return 0, false
64+
}

src/cmd/asm/internal/asm/asm.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,14 @@ func (p *Parser) asmJump(op int, cond string, a []obj.Addr) {
373373
prog.Reg = reg
374374
break
375375
}
376+
if p.arch.Thechar == '0' {
377+
// 3-operand jumps.
378+
// First two must be registers
379+
target = &a[2]
380+
prog.From = a[0]
381+
prog.Reg = p.getRegister(prog, op, &a[1])
382+
break
383+
}
376384
fallthrough
377385
default:
378386
p.errorf("wrong number of arguments to %s instruction", obj.Aconv(op))
@@ -509,11 +517,21 @@ func (p *Parser) asmInstruction(op int, cond string, a []obj.Addr) {
509517
prog.From = a[0]
510518
prog.Reg = p.getRegister(prog, op, &a[1])
511519
break
520+
} else if p.arch.Thechar == '0' {
521+
if arch.IsMIPS64CMP(op) || arch.IsMIPS64MUL(op) {
522+
prog.From = a[0]
523+
prog.Reg = p.getRegister(prog, op, &a[1])
524+
break
525+
}
512526
}
513527
prog.From = a[0]
514528
prog.To = a[1]
515529
case 3:
516530
switch p.arch.Thechar {
531+
case '0':
532+
prog.From = a[0]
533+
prog.Reg = p.getRegister(prog, op, &a[1])
534+
prog.To = a[2]
517535
case '5':
518536
// Special cases.
519537
if arch.IsARMSTREX(op) {

src/cmd/asm/internal/asm/endtoend_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,7 @@ func TestAMD64EndToEnd(t *testing.T) {
8989
func Test386EndToEnd(t *testing.T) {
9090
testEndToEnd(t, "386")
9191
}
92+
93+
func TestMIPS64EndToEnd(t *testing.T) {
94+
testEndToEnd(t, "mips64")
95+
}

src/cmd/asm/internal/asm/operand_test.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ func TestPPC64OperandParser(t *testing.T) {
6565
testOperandParser(t, parser, ppc64OperandTests)
6666
}
6767

68+
func TestMIPS64OperandParser(t *testing.T) {
69+
parser := newParser("mips64")
70+
testOperandParser(t, parser, mips64OperandTests)
71+
}
72+
6873
type operandTest struct {
6974
input, output string
7075
}
@@ -435,3 +440,86 @@ var arm64OperandTests = []operandTest{
435440
{"(R29, RSP)", "(R29, RSP)"},
436441
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
437442
}
443+
444+
var mips64OperandTests = []operandTest{
445+
{"$((1<<63)-1)", "$9223372036854775807"},
446+
{"$(-64*1024)", "$-65536"},
447+
{"$(1024 * 8)", "$8192"},
448+
{"$-1", "$-1"},
449+
{"$-24(R4)", "$-24(R4)"},
450+
{"$0", "$0"},
451+
{"$0(R1)", "$(R1)"},
452+
{"$0.5", "$(0.5)"},
453+
{"$0x7000", "$28672"},
454+
{"$0x88888eef", "$2290650863"},
455+
{"$1", "$1"},
456+
{"$_main<>(SB)", "$_main<>(SB)"},
457+
{"$argframe(FP)", "$argframe(FP)"},
458+
{"$~3", "$-4"},
459+
{"(-288-3*8)(R1)", "-312(R1)"},
460+
{"(16)(R7)", "16(R7)"},
461+
{"(8)(g)", "8(g)"},
462+
{"(R0)", "(R0)"},
463+
{"(R3)", "(R3)"},
464+
{"(R4)", "(R4)"},
465+
{"(R5)", "(R5)"},
466+
{"-1(R4)", "-1(R4)"},
467+
{"-1(R5)", "-1(R5)"},
468+
{"6(PC)", "6(PC)"},
469+
{"F14", "F14"},
470+
{"F15", "F15"},
471+
{"F16", "F16"},
472+
{"F17", "F17"},
473+
{"F18", "F18"},
474+
{"F19", "F19"},
475+
{"F20", "F20"},
476+
{"F21", "F21"},
477+
{"F22", "F22"},
478+
{"F23", "F23"},
479+
{"F24", "F24"},
480+
{"F25", "F25"},
481+
{"F26", "F26"},
482+
{"F27", "F27"},
483+
{"F28", "F28"},
484+
{"F29", "F29"},
485+
{"F30", "F30"},
486+
{"F31", "F31"},
487+
{"R0", "R0"},
488+
{"R1", "R1"},
489+
{"R11", "R11"},
490+
{"R12", "R12"},
491+
{"R13", "R13"},
492+
{"R14", "R14"},
493+
{"R15", "R15"},
494+
{"R16", "R16"},
495+
{"R17", "R17"},
496+
{"R18", "R18"},
497+
{"R19", "R19"},
498+
{"R2", "R2"},
499+
{"R20", "R20"},
500+
{"R21", "R21"},
501+
{"R22", "R22"},
502+
{"R23", "R23"},
503+
{"R24", "R24"},
504+
{"R25", "R25"},
505+
{"R26", "R26"},
506+
{"R27", "R27"},
507+
{"R28", "R28"},
508+
{"R29", "R29"},
509+
{"R3", "R3"},
510+
{"R31", "R31"},
511+
{"R4", "R4"},
512+
{"R5", "R5"},
513+
{"R6", "R6"},
514+
{"R7", "R7"},
515+
{"R8", "R8"},
516+
{"R9", "R9"},
517+
{"LO", "LO"},
518+
{"a(FP)", "a(FP)"},
519+
{"g", "g"},
520+
{"ret+8(FP)", "ret+8(FP)"},
521+
{"runtime·abort(SB)", "runtime.abort(SB)"},
522+
{"·AddUint32(SB)", "\"\".AddUint32(SB)"},
523+
{"·trunc(SB)", "\"\".trunc(SB)"},
524+
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
525+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
8 00001 (testdata/mips64.s:8) TEXT foo(SB), 0, $0
2+
18 00002 (testdata/mips64.s:18) MOVW R1, R2
3+
19 00003 (testdata/mips64.s:19) MOVW LO, R1
4+
20 00004 (testdata/mips64.s:20) MOVW HI, R1
5+
21 00005 (testdata/mips64.s:21) MOVW R1, LO
6+
22 00006 (testdata/mips64.s:22) MOVW R1, HI
7+
23 00007 (testdata/mips64.s:23) MOVV R1, R2
8+
24 00008 (testdata/mips64.s:24) MOVV LO, R1
9+
25 00009 (testdata/mips64.s:25) MOVV HI, R1
10+
26 00010 (testdata/mips64.s:26) MOVV R1, LO
11+
27 00011 (testdata/mips64.s:27) MOVV R1, HI
12+
33 00012 (testdata/mips64.s:33) MOVW foo<>+3(SB), R2
13+
34 00013 (testdata/mips64.s:34) MOVW 16(R1), R2
14+
35 00014 (testdata/mips64.s:35) MOVW (R1), R2
15+
36 00015 (testdata/mips64.s:36) MOVV foo<>+3(SB), R2
16+
37 00016 (testdata/mips64.s:37) MOVV 16(R1), R2
17+
38 00017 (testdata/mips64.s:38) MOVV (R1), R2
18+
44 00018 (testdata/mips64.s:44) MOVB R1, R2
19+
50 00019 (testdata/mips64.s:50) MOVB foo<>+3(SB), R2
20+
51 00020 (testdata/mips64.s:51) MOVB 16(R1), R2
21+
52 00021 (testdata/mips64.s:52) MOVB (R1), R2
22+
61 00022 (testdata/mips64.s:61) MOVD foo<>+3(SB), F2
23+
62 00023 (testdata/mips64.s:62) MOVD 16(R1), F2
24+
63 00024 (testdata/mips64.s:63) MOVD (R1), F2
25+
69 00025 (testdata/mips64.s:69) MOVD $(0.10000000000000001), F2
26+
75 00026 (testdata/mips64.s:75) MOVD F1, F2
27+
81 00027 (testdata/mips64.s:81) MOVD F2, foo<>+3(SB)
28+
82 00028 (testdata/mips64.s:82) MOVD F2, 16(R1)
29+
83 00029 (testdata/mips64.s:83) MOVD F2, (R1)
30+
92 00030 (testdata/mips64.s:92) MOVW R1, foo<>+3(SB)
31+
93 00031 (testdata/mips64.s:93) MOVW R1, 16(R2)
32+
94 00032 (testdata/mips64.s:94) MOVW R1, (R2)
33+
95 00033 (testdata/mips64.s:95) MOVV R1, foo<>+3(SB)
34+
96 00034 (testdata/mips64.s:96) MOVV R1, 16(R2)
35+
97 00035 (testdata/mips64.s:97) MOVV R1, (R2)
36+
103 00036 (testdata/mips64.s:103) MOVB R1, foo<>+3(SB)
37+
104 00037 (testdata/mips64.s:104) MOVB R1, 16(R2)
38+
105 00038 (testdata/mips64.s:105) MOVB R1, (R2)
39+
114 00039 (testdata/mips64.s:114) MOVD F1, foo<>+3(SB)
40+
115 00040 (testdata/mips64.s:115) MOVD F1, 16(R2)
41+
116 00041 (testdata/mips64.s:116) MOVD F1, (R2)
42+
125 00042 (testdata/mips64.s:125) MOVW FCR0, R1
43+
131 00043 (testdata/mips64.s:131) MOVW R1, FCR0
44+
137 00044 (testdata/mips64.s:137) MOVW R1, M1
45+
138 00045 (testdata/mips64.s:138) MOVV R1, M1
46+
144 00046 (testdata/mips64.s:144) MOVW M1, R1
47+
145 00047 (testdata/mips64.s:145) MOVV M1, R1
48+
158 00048 (testdata/mips64.s:158) ADD R1, R2, R3
49+
164 00049 (testdata/mips64.s:164) ADD $1, R2, R3
50+
170 00050 (testdata/mips64.s:170) ADD R1, R2
51+
176 00051 (testdata/mips64.s:176) ADD $4, R1
52+
182 00052 (testdata/mips64.s:182) MUL R1, R2
53+
188 00053 (testdata/mips64.s:188) SLL R1, R2, R3
54+
194 00054 (testdata/mips64.s:194) SLL R1, R2
55+
200 00055 (testdata/mips64.s:200) SLL $4, R1, R2
56+
206 00056 (testdata/mips64.s:206) SLL $4, R1
57+
215 00057 (testdata/mips64.s:215) MOVW $1, R1
58+
216 00058 (testdata/mips64.s:216) MOVV $1, R1
59+
222 00059 (testdata/mips64.s:222) MOVW $1, R1
60+
223 00060 (testdata/mips64.s:223) MOVW $foo(SB), R1
61+
224 00061 (testdata/mips64.s:224) MOVV $1, R1
62+
225 00062 (testdata/mips64.s:225) MOVV $foo(SB), R1
63+
236 00063 (testdata/mips64.s:236) JMP 64(PC)
64+
237 00064 (testdata/mips64.s:237) JMP 63
65+
238 00065 (testdata/mips64.s:238) CALL 66(PC)
66+
239 00066 (testdata/mips64.s:239) CALL 63
67+
245 00067 (testdata/mips64.s:245) JMP 4(R1)
68+
246 00068 (testdata/mips64.s:246) JMP foo(SB)
69+
247 00069 (testdata/mips64.s:247) CALL 4(R1)
70+
248 00070 (testdata/mips64.s:248) CALL foo(SB)
71+
258 00071 (testdata/mips64.s:258) BEQ R1, 72(PC)
72+
259 00072 (testdata/mips64.s:259) BEQ R1, 71
73+
266 00073 (testdata/mips64.s:266) BEQ R1, R2, 74(PC)
74+
267 00074 (testdata/mips64.s:267) BEQ R1, R2, 73
75+
277 00075 (testdata/mips64.s:277) BLTZ R1, 76(PC)
76+
278 00076 (testdata/mips64.s:278) BLTZ R1, 75
77+
285 00077 (testdata/mips64.s:285) BFPT 78(PC)
78+
286 00078 (testdata/mips64.s:286) BFPT 77
79+
296 00079 (testdata/mips64.s:296) ABSD F1, F2
80+
302 00080 (testdata/mips64.s:302) ADDD F1, F2
81+
308 00081 (testdata/mips64.s:308) ADDD F1, F2, F3
82+
314 00082 (testdata/mips64.s:314) CMPEQD F1, F2
83+
320 00083 (testdata/mips64.s:320) WORD $1
84+
321 00084 (testdata/mips64.s:321) WORD $foo(SB)
85+
330 00085 (testdata/mips64.s:330) NOP
86+
336 00086 (testdata/mips64.s:336) NOP R2
87+
342 00087 (testdata/mips64.s:342) NOP F2
88+
348 00088 (testdata/mips64.s:348) NOP R2
89+
354 00089 (testdata/mips64.s:354) NOP F2
90+
360 00090 (testdata/mips64.s:360) NOP $4
91+
365 00091 (testdata/mips64.s:365) SYSCALL
92+
366 00092 (testdata/mips64.s:366) BREAK
93+
367 00093 (testdata/mips64.s:367) BREAK $1, (R1)
94+
376 00094 (testdata/mips64.s:376) SYSCALL
95+
377 00095 (testdata/mips64.s:377) RET
96+
382 00096 (testdata/mips64.s:382) CALL foo(SB)
97+
383 00097 (testdata/mips64.s:383) JMP foo(SB)
98+
384 00098 (testdata/mips64.s:384) CALL foo(SB)
99+
392 00099 (testdata/mips64.s:392) END

0 commit comments

Comments
 (0)