"cmd/internal/obj"
"cmd/internal/obj/arm"
"cmd/internal/obj/arm64"
+ "cmd/internal/obj/mips"
"cmd/internal/obj/ppc64"
"cmd/internal/obj/x86"
"fmt"
return archArm()
case "arm64":
return archArm64()
+ case "mips64":
+ a := archMips64()
+ a.LinkArch = &mips.Linkmips64
+ return a
+ case "mips64le":
+ a := archMips64()
+ a.LinkArch = &mips.Linkmips64le
+ return a
case "ppc64":
a := archPPC64()
a.LinkArch = &ppc64.Linkppc64
IsJump: jumpPPC64,
}
}
+
+func archMips64() *Arch {
+ register := make(map[string]int16)
+ // Create maps for easy lookup of instruction names etc.
+ // Note that there is no list of names as there is for x86.
+ for i := mips.REG_R0; i <= mips.REG_R31; i++ {
+ register[obj.Rconv(i)] = int16(i)
+ }
+ for i := mips.REG_F0; i <= mips.REG_F31; i++ {
+ register[obj.Rconv(i)] = int16(i)
+ }
+ for i := mips.REG_M0; i <= mips.REG_M31; i++ {
+ register[obj.Rconv(i)] = int16(i)
+ }
+ for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ {
+ register[obj.Rconv(i)] = int16(i)
+ }
+ register["HI"] = mips.REG_HI
+ register["LO"] = mips.REG_LO
+ // Pseudo-registers.
+ register["SB"] = RSB
+ register["FP"] = RFP
+ register["PC"] = RPC
+ // Avoid unintentionally clobbering g using R30.
+ delete(register, "R30")
+ register["g"] = mips.REG_R30
+ registerPrefix := map[string]bool{
+ "F": true,
+ "FCR": true,
+ "M": true,
+ "R": true,
+ }
+
+ instructions := make(map[string]int)
+ for i, s := range obj.Anames {
+ instructions[s] = i
+ }
+ for i, s := range mips.Anames {
+ if i >= obj.A_ARCHSPECIFIC {
+ instructions[s] = i + obj.ABaseMIPS64
+ }
+ }
+ // Annoying alias.
+ instructions["JAL"] = mips.AJAL
+
+ return &Arch{
+ LinkArch: &mips.Linkmips64,
+ Instructions: instructions,
+ Register: register,
+ RegisterPrefix: registerPrefix,
+ RegisterNumber: mipsRegisterNumber,
+ IsJump: jumpMIPS64,
+ }
+}
--- /dev/null
+// 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.
+
+// This file encapsulates some of the odd characteristics of the
+// 64-bit MIPS (MIPS64) instruction set, to minimize its interaction
+// with the core of the assembler.
+
+package arch
+
+import "cmd/internal/obj/mips"
+
+func jumpMIPS64(word string) bool {
+ switch word {
+ case "BEQ", "BFPF", "BFPT", "BGEZ", "BGEZAL", "BGTZ", "BLEZ", "BLTZ", "BLTZAL", "BNE", "JMP", "JAL", "CALL":
+ return true
+ }
+ return false
+}
+
+// IsMIPS64CMP reports whether the op (as defined by an mips.A* constant) is
+// one of the CMP instructions that require special handling.
+func IsMIPS64CMP(op int) bool {
+ switch op {
+ case mips.ACMPEQF, mips.ACMPEQD, mips.ACMPGEF, mips.ACMPGED,
+ mips.ACMPGTF, mips.ACMPGTD:
+ return true
+ }
+ return false
+}
+
+// IsMIPS64MUL reports whether the op (as defined by an mips.A* constant) is
+// one of the MUL/DIV/REM instructions that require special handling.
+func IsMIPS64MUL(op int) bool {
+ switch op {
+ case mips.AMUL, mips.AMULU, mips.AMULV, mips.AMULVU,
+ mips.ADIV, mips.ADIVU, mips.ADIVV, mips.ADIVVU,
+ mips.AREM, mips.AREMU, mips.AREMV, mips.AREMVU:
+ return true
+ }
+ return false
+}
+
+func mipsRegisterNumber(name string, n int16) (int16, bool) {
+ switch name {
+ case "F":
+ if 0 <= n && n <= 31 {
+ return mips.REG_F0 + n, true
+ }
+ case "FCR":
+ if 0 <= n && n <= 31 {
+ return mips.REG_FCR0 + n, true
+ }
+ case "M":
+ if 0 <= n && n <= 31 {
+ return mips.REG_M0 + n, true
+ }
+ case "R":
+ if 0 <= n && n <= 31 {
+ return mips.REG_R0 + n, true
+ }
+ }
+ return 0, false
+}
prog.Reg = reg
break
}
+ if p.arch.Thechar == '0' {
+ // 3-operand jumps.
+ // First two must be registers
+ target = &a[2]
+ prog.From = a[0]
+ prog.Reg = p.getRegister(prog, op, &a[1])
+ break
+ }
fallthrough
default:
p.errorf("wrong number of arguments to %s instruction", obj.Aconv(op))
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
break
+ } else if p.arch.Thechar == '0' {
+ if arch.IsMIPS64CMP(op) || arch.IsMIPS64MUL(op) {
+ prog.From = a[0]
+ prog.Reg = p.getRegister(prog, op, &a[1])
+ break
+ }
}
prog.From = a[0]
prog.To = a[1]
case 3:
switch p.arch.Thechar {
+ case '0':
+ prog.From = a[0]
+ prog.Reg = p.getRegister(prog, op, &a[1])
+ prog.To = a[2]
case '5':
// Special cases.
if arch.IsARMSTREX(op) {
func Test386EndToEnd(t *testing.T) {
testEndToEnd(t, "386")
}
+
+func TestMIPS64EndToEnd(t *testing.T) {
+ testEndToEnd(t, "mips64")
+}
testOperandParser(t, parser, ppc64OperandTests)
}
+func TestMIPS64OperandParser(t *testing.T) {
+ parser := newParser("mips64")
+ testOperandParser(t, parser, mips64OperandTests)
+}
+
type operandTest struct {
input, output string
}
{"(R29, RSP)", "(R29, RSP)"},
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
}
+
+var mips64OperandTests = []operandTest{
+ {"$((1<<63)-1)", "$9223372036854775807"},
+ {"$(-64*1024)", "$-65536"},
+ {"$(1024 * 8)", "$8192"},
+ {"$-1", "$-1"},
+ {"$-24(R4)", "$-24(R4)"},
+ {"$0", "$0"},
+ {"$0(R1)", "$(R1)"},
+ {"$0.5", "$(0.5)"},
+ {"$0x7000", "$28672"},
+ {"$0x88888eef", "$2290650863"},
+ {"$1", "$1"},
+ {"$_main<>(SB)", "$_main<>(SB)"},
+ {"$argframe(FP)", "$argframe(FP)"},
+ {"$~3", "$-4"},
+ {"(-288-3*8)(R1)", "-312(R1)"},
+ {"(16)(R7)", "16(R7)"},
+ {"(8)(g)", "8(g)"},
+ {"(R0)", "(R0)"},
+ {"(R3)", "(R3)"},
+ {"(R4)", "(R4)"},
+ {"(R5)", "(R5)"},
+ {"-1(R4)", "-1(R4)"},
+ {"-1(R5)", "-1(R5)"},
+ {"6(PC)", "6(PC)"},
+ {"F14", "F14"},
+ {"F15", "F15"},
+ {"F16", "F16"},
+ {"F17", "F17"},
+ {"F18", "F18"},
+ {"F19", "F19"},
+ {"F20", "F20"},
+ {"F21", "F21"},
+ {"F22", "F22"},
+ {"F23", "F23"},
+ {"F24", "F24"},
+ {"F25", "F25"},
+ {"F26", "F26"},
+ {"F27", "F27"},
+ {"F28", "F28"},
+ {"F29", "F29"},
+ {"F30", "F30"},
+ {"F31", "F31"},
+ {"R0", "R0"},
+ {"R1", "R1"},
+ {"R11", "R11"},
+ {"R12", "R12"},
+ {"R13", "R13"},
+ {"R14", "R14"},
+ {"R15", "R15"},
+ {"R16", "R16"},
+ {"R17", "R17"},
+ {"R18", "R18"},
+ {"R19", "R19"},
+ {"R2", "R2"},
+ {"R20", "R20"},
+ {"R21", "R21"},
+ {"R22", "R22"},
+ {"R23", "R23"},
+ {"R24", "R24"},
+ {"R25", "R25"},
+ {"R26", "R26"},
+ {"R27", "R27"},
+ {"R28", "R28"},
+ {"R29", "R29"},
+ {"R3", "R3"},
+ {"R31", "R31"},
+ {"R4", "R4"},
+ {"R5", "R5"},
+ {"R6", "R6"},
+ {"R7", "R7"},
+ {"R8", "R8"},
+ {"R9", "R9"},
+ {"LO", "LO"},
+ {"a(FP)", "a(FP)"},
+ {"g", "g"},
+ {"ret+8(FP)", "ret+8(FP)"},
+ {"runtime·abort(SB)", "runtime.abort(SB)"},
+ {"·AddUint32(SB)", "\"\".AddUint32(SB)"},
+ {"·trunc(SB)", "\"\".trunc(SB)"},
+ {"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
+}
--- /dev/null
+8 00001 (testdata/mips64.s:8) TEXT foo(SB), 0, $0
+18 00002 (testdata/mips64.s:18) MOVW R1, R2
+19 00003 (testdata/mips64.s:19) MOVW LO, R1
+20 00004 (testdata/mips64.s:20) MOVW HI, R1
+21 00005 (testdata/mips64.s:21) MOVW R1, LO
+22 00006 (testdata/mips64.s:22) MOVW R1, HI
+23 00007 (testdata/mips64.s:23) MOVV R1, R2
+24 00008 (testdata/mips64.s:24) MOVV LO, R1
+25 00009 (testdata/mips64.s:25) MOVV HI, R1
+26 00010 (testdata/mips64.s:26) MOVV R1, LO
+27 00011 (testdata/mips64.s:27) MOVV R1, HI
+33 00012 (testdata/mips64.s:33) MOVW foo<>+3(SB), R2
+34 00013 (testdata/mips64.s:34) MOVW 16(R1), R2
+35 00014 (testdata/mips64.s:35) MOVW (R1), R2
+36 00015 (testdata/mips64.s:36) MOVV foo<>+3(SB), R2
+37 00016 (testdata/mips64.s:37) MOVV 16(R1), R2
+38 00017 (testdata/mips64.s:38) MOVV (R1), R2
+44 00018 (testdata/mips64.s:44) MOVB R1, R2
+50 00019 (testdata/mips64.s:50) MOVB foo<>+3(SB), R2
+51 00020 (testdata/mips64.s:51) MOVB 16(R1), R2
+52 00021 (testdata/mips64.s:52) MOVB (R1), R2
+61 00022 (testdata/mips64.s:61) MOVD foo<>+3(SB), F2
+62 00023 (testdata/mips64.s:62) MOVD 16(R1), F2
+63 00024 (testdata/mips64.s:63) MOVD (R1), F2
+69 00025 (testdata/mips64.s:69) MOVD $(0.10000000000000001), F2
+75 00026 (testdata/mips64.s:75) MOVD F1, F2
+81 00027 (testdata/mips64.s:81) MOVD F2, foo<>+3(SB)
+82 00028 (testdata/mips64.s:82) MOVD F2, 16(R1)
+83 00029 (testdata/mips64.s:83) MOVD F2, (R1)
+92 00030 (testdata/mips64.s:92) MOVW R1, foo<>+3(SB)
+93 00031 (testdata/mips64.s:93) MOVW R1, 16(R2)
+94 00032 (testdata/mips64.s:94) MOVW R1, (R2)
+95 00033 (testdata/mips64.s:95) MOVV R1, foo<>+3(SB)
+96 00034 (testdata/mips64.s:96) MOVV R1, 16(R2)
+97 00035 (testdata/mips64.s:97) MOVV R1, (R2)
+103 00036 (testdata/mips64.s:103) MOVB R1, foo<>+3(SB)
+104 00037 (testdata/mips64.s:104) MOVB R1, 16(R2)
+105 00038 (testdata/mips64.s:105) MOVB R1, (R2)
+114 00039 (testdata/mips64.s:114) MOVD F1, foo<>+3(SB)
+115 00040 (testdata/mips64.s:115) MOVD F1, 16(R2)
+116 00041 (testdata/mips64.s:116) MOVD F1, (R2)
+125 00042 (testdata/mips64.s:125) MOVW FCR0, R1
+131 00043 (testdata/mips64.s:131) MOVW R1, FCR0
+137 00044 (testdata/mips64.s:137) MOVW R1, M1
+138 00045 (testdata/mips64.s:138) MOVV R1, M1
+144 00046 (testdata/mips64.s:144) MOVW M1, R1
+145 00047 (testdata/mips64.s:145) MOVV M1, R1
+158 00048 (testdata/mips64.s:158) ADD R1, R2, R3
+164 00049 (testdata/mips64.s:164) ADD $1, R2, R3
+170 00050 (testdata/mips64.s:170) ADD R1, R2
+176 00051 (testdata/mips64.s:176) ADD $4, R1
+182 00052 (testdata/mips64.s:182) MUL R1, R2
+188 00053 (testdata/mips64.s:188) SLL R1, R2, R3
+194 00054 (testdata/mips64.s:194) SLL R1, R2
+200 00055 (testdata/mips64.s:200) SLL $4, R1, R2
+206 00056 (testdata/mips64.s:206) SLL $4, R1
+215 00057 (testdata/mips64.s:215) MOVW $1, R1
+216 00058 (testdata/mips64.s:216) MOVV $1, R1
+222 00059 (testdata/mips64.s:222) MOVW $1, R1
+223 00060 (testdata/mips64.s:223) MOVW $foo(SB), R1
+224 00061 (testdata/mips64.s:224) MOVV $1, R1
+225 00062 (testdata/mips64.s:225) MOVV $foo(SB), R1
+236 00063 (testdata/mips64.s:236) JMP 64(PC)
+237 00064 (testdata/mips64.s:237) JMP 63
+238 00065 (testdata/mips64.s:238) CALL 66(PC)
+239 00066 (testdata/mips64.s:239) CALL 63
+245 00067 (testdata/mips64.s:245) JMP 4(R1)
+246 00068 (testdata/mips64.s:246) JMP foo(SB)
+247 00069 (testdata/mips64.s:247) CALL 4(R1)
+248 00070 (testdata/mips64.s:248) CALL foo(SB)
+258 00071 (testdata/mips64.s:258) BEQ R1, 72(PC)
+259 00072 (testdata/mips64.s:259) BEQ R1, 71
+266 00073 (testdata/mips64.s:266) BEQ R1, R2, 74(PC)
+267 00074 (testdata/mips64.s:267) BEQ R1, R2, 73
+277 00075 (testdata/mips64.s:277) BLTZ R1, 76(PC)
+278 00076 (testdata/mips64.s:278) BLTZ R1, 75
+285 00077 (testdata/mips64.s:285) BFPT 78(PC)
+286 00078 (testdata/mips64.s:286) BFPT 77
+296 00079 (testdata/mips64.s:296) ABSD F1, F2
+302 00080 (testdata/mips64.s:302) ADDD F1, F2
+308 00081 (testdata/mips64.s:308) ADDD F1, F2, F3
+314 00082 (testdata/mips64.s:314) CMPEQD F1, F2
+320 00083 (testdata/mips64.s:320) WORD $1
+321 00084 (testdata/mips64.s:321) WORD $foo(SB)
+330 00085 (testdata/mips64.s:330) NOP
+336 00086 (testdata/mips64.s:336) NOP R2
+342 00087 (testdata/mips64.s:342) NOP F2
+348 00088 (testdata/mips64.s:348) NOP R2
+354 00089 (testdata/mips64.s:354) NOP F2
+360 00090 (testdata/mips64.s:360) NOP $4
+365 00091 (testdata/mips64.s:365) SYSCALL
+366 00092 (testdata/mips64.s:366) BREAK
+367 00093 (testdata/mips64.s:367) BREAK $1, (R1)
+376 00094 (testdata/mips64.s:376) SYSCALL
+377 00095 (testdata/mips64.s:377) RET
+382 00096 (testdata/mips64.s:382) CALL foo(SB)
+383 00097 (testdata/mips64.s:383) JMP foo(SB)
+384 00098 (testdata/mips64.s:384) CALL foo(SB)
+392 00099 (testdata/mips64.s:392) END
--- /dev/null
+// 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.
+
+// This input was created by taking the ppc64 testcase and modified
+// by hand.
+
+TEXT foo(SB),0,$0
+
+//inst:
+//
+// load ints and bytes
+//
+// LMOVW rreg ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW R1, R2
+ MOVW LO, R1
+ MOVW HI, R1
+ MOVW R1, LO
+ MOVW R1, HI
+ MOVV R1, R2
+ MOVV LO, R1
+ MOVV HI, R1
+ MOVV R1, LO
+ MOVV R1, HI
+
+// LMOVW addr ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW foo<>+3(SB), R2
+ MOVW 16(R1), R2
+ MOVW (R1), R2
+ MOVV foo<>+3(SB), R2
+ MOVV 16(R1), R2
+ MOVV (R1), R2
+
+// LMOVB rreg ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVB R1, R2
+
+// LMOVB addr ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVB foo<>+3(SB), R2
+ MOVB 16(R1), R2
+ MOVB (R1), R2
+
+//
+// load floats
+//
+// LFMOV addr ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVD foo<>+3(SB), F2
+ MOVD 16(R1), F2
+ MOVD (R1), F2
+
+// LFMOV fimm ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVD $0.1, F2
+
+// LFMOV freg ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVD F1, F2
+
+// LFMOV freg ',' addr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVD F2, foo<>+3(SB)
+ MOVD F2, 16(R1)
+ MOVD F2, (R1)
+
+//
+// store ints and bytes
+//
+// LMOVW rreg ',' addr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW R1, foo<>+3(SB)
+ MOVW R1, 16(R2)
+ MOVW R1, (R2)
+ MOVV R1, foo<>+3(SB)
+ MOVV R1, 16(R2)
+ MOVV R1, (R2)
+
+// LMOVB rreg ',' addr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVB R1, foo<>+3(SB)
+ MOVB R1, 16(R2)
+ MOVB R1, (R2)
+
+//
+// store floats
+//
+// LMOVW freg ',' addr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVD F1, foo<>+3(SB)
+ MOVD F1, 16(R2)
+ MOVD F1, (R2)
+
+//
+// floating point status
+//
+// LMOVW fpscr ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW FCR0, R1
+
+// LMOVW freg ',' fpscr
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW R1, FCR0
+
+// LMOVW rreg ',' mreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW R1, M1
+ MOVV R1, M1
+
+// LMOVW mreg ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW M1, R1
+ MOVV M1, R1
+
+
+//
+// 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 ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ ADD R1, R2
+
+// LADDW imm ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ ADD $4, R1
+
+// LMUL rreg ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MUL R1, R2
+
+// LSHW rreg ',' sreg ',' rreg
+// {
+// outcode(int($1), &$2, int($4), &$6);
+// }
+ SLL R1, R2, R3
+
+// LSHW rreg ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ SLL R1, R2
+
+// LSHW imm ',' sreg ',' rreg
+// {
+// outcode(int($1), &$2, int($4), &$6);
+// }
+ SLL $4, R1, R2
+
+// LSHW imm ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ SLL $4, R1
+
+//
+// move immediate: macro for lui+or, addi, addis, and other combinations
+//
+// LMOVW imm ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW $1, R1
+ MOVV $1, R1
+
+// LMOVW ximm ',' rreg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ MOVW $1, R1
+ MOVW $foo(SB), R1
+ MOVV $1, R1
+ MOVV $foo(SB), R1
+
+
+//
+// branch
+//
+// LBRA rel
+// {
+// outcode(int($1), &nullgen, 0, &$2);
+// }
+label0:
+ JMP 1(PC)
+ JMP label0+0
+ JAL 1(PC)
+ JAL label0+0
+
+// LBRA addr
+// {
+// outcode(int($1), &nullgen, 0, &$2);
+// }
+ JMP 4(R1)
+ JMP foo+0(SB)
+ JAL 4(R1)
+ JAL foo+0(SB)
+
+//
+// BEQ/BNE
+//
+// LBRA rreg ',' rel
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+label1:
+ BEQ R1, 1(PC)
+ BEQ R1, label1
+
+// LBRA rreg ',' sreg ',' rel
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+label2:
+ BEQ R1, R2, 1(PC)
+ BEQ R1, R2, label2
+
+//
+// other integer conditional branch
+//
+// LBRA rreg ',' rel
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+label3:
+ BLTZ R1, 1(PC)
+ BLTZ R1, label3
+
+//
+// floating point conditional branch
+//
+// LBRA rel
+label4:
+ BFPT 1(PC)
+ BFPT label4
+
+
+//
+// floating point operate
+//
+// LFCONV freg ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ ABSD F1, F2
+
+// LFADD freg ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ ADDD F1, F2
+
+// LFADD freg ',' freg ',' freg
+// {
+// outcode(int($1), &$2, int($4.Reg), &$6);
+// }
+ ADDD F1, F2, F3
+
+// LFCMP freg ',' freg
+// {
+// outcode(int($1), &$2, 0, &$4);
+// }
+ CMPEQD F1, F2
+
+
+//
+// WORD
+//
+ WORD $1
+ WORD $foo(SB)
+
+//
+// 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
+// {
+// outcode(int($1), &$2, 0, &nullgen);
+// }
+ NOP $4
+
+//
+// special
+//
+ SYSCALL
+ BREAK
+ BREAK $1, (R1) // overloaded CACHE opcode
+
+//
+// RET
+//
+// LRETRN comma // asm doesn't support the trailing comma.
+// {
+// outcode(int($1), &nullgen, 0, &nullgen);
+// }
+ SYSCALL
+ RET
+
+
+// More JMP/JAL cases, and canonical names JMP, CALL.
+
+ JAL foo(SB)
+ JMP foo(SB)
+ CALL foo(SB)
+
+// END
+//
+// LEND comma // asm doesn't support the trailing comma.
+// {
+// outcode(int($1), &nullgen, 0, &nullgen);
+// }
+ END