misc/cgo/stdio/run.out
misc/cgo/testso/main
misc/dashboard/builder/builder
-src/cmd/?a/y.output
src/liblink/anames?.c
-src/cmd/cc/y.output
+src/cmd/*/y.output
src/cmd/cgo/zdefaultcc.go
src/cmd/dist/dist.dSYM
src/cmd/gc/mkbuiltin1
src/cmd/gc/opnames.h
-src/cmd/gc/y.output
src/cmd/go/zdefaultcc.go
+src/cmd/internal/obj/zbootstrap.go
src/go/doc/headscan
src/runtime/mkversion
src/runtime/zaexperiment.h
extern char* getgoarm(void);
extern char* getgo386(void);
extern char* getgoextlinkenabled(void);
+extern char* getgohostos(void);
+extern char* getgohostarch(void);
extern char* mktempdir(void);
extern void removeall(char*);
uchar ft; // oclass cache
uchar tt; // oclass cache
uchar isize; // amd64, 386
+ uchar printed;
char width; /* fake for DATA */
char mode; /* 16, 32, or 64 in 6l, 8l; internal use in 5g, 6g, 8g */
uchar localentry; // ppc64: instrs between global & local entry
uchar seenglobl;
uchar onlist; // on the textp or datap lists
+ uchar printed;
int16 symid; // for writing .5/.6/.8 files
int32 dynid;
int32 sig;
char* name;
int32 line;
int32 offset;
+ uchar printed;
};
struct Plist
char* getgoarm(void);
char* getgo386(void);
char* getgoextlinkenabled(void);
+char* getgohostos(void);
+char* getgohostarch(void);
+
+int runcmd(char**);
void flagcount(char*, char*, int*);
void flagint32(char*, char*, int32*);
--- /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.
+
+// Package addr holds the definition of an instruction address.
+package addr
+
+// Addr represents a parsed address.
+type Addr struct {
+ IsStatic bool // symbol<>
+ IsImmediateConstant bool // $3
+ IsImmediateAddress bool // $main·main(SB)
+ IsIndirect bool // (R1)
+ HasRegister bool // register is set
+ HasRegister2 bool // register2 is set
+ HasFloat bool // float is set
+ HasOffset bool // offset is set
+ HasString bool // string is set
+ Symbol string // "main·main"
+ Register int16 // R1
+ Register2 int16 // R1 in R0:R1
+ Offset int64 // 3
+ Float float64 // 1.0e2 (floating constant)
+ String string // "hi" (string constant)
+ Index int16 // R1 in (R1*8)
+ Scale int8 // 8 in (R1*8)
+}
+
+const (
+ // IsStatic does not appear here; Is and Has methods ignore it.
+ ImmediateConstant = 1 << iota
+ ImmediateAddress
+ Indirect
+ Symbol
+ Register
+ Register2
+ Offset
+ Float
+ String
+ Index
+ Scale
+)
+
+// Has reports whether the address has any of the specified elements.
+// Indirect and immediate are not checked.
+func (a *Addr) Has(mask int) bool {
+ if mask&Symbol != 0 && a.Symbol != "" {
+ return true
+ }
+ if mask&Register != 0 && a.HasRegister {
+ return true
+ }
+ if mask&Register2 != 0 && a.HasRegister2 {
+ return true
+ }
+ if mask&Offset != 0 && a.HasOffset {
+ return true
+ }
+ if mask&Float != 0 && a.HasFloat {
+ return true
+ }
+ if mask&String != 0 && a.HasString {
+ return true
+ }
+ if mask&Index != 0 && a.Index != 0 {
+ return true
+ }
+ if mask&Scale != 0 && a.Scale != 0 {
+ return true
+ }
+ return false
+}
+
+// Is reports whether the address has all the specified elements.
+// Indirect and immediate are checked.
+func (a *Addr) Is(mask int) bool {
+ if (mask&ImmediateConstant == 0) != !a.IsImmediateConstant {
+ return false
+ }
+ if (mask&ImmediateAddress == 0) != !a.IsImmediateAddress {
+ return false
+ }
+ if (mask&Indirect == 0) != !a.IsIndirect {
+ return false
+ }
+ if (mask&Symbol == 0) != (a.Symbol == "") {
+ return false
+ }
+ if (mask&Register == 0) != !a.HasRegister {
+ return false
+ }
+ if (mask&Register2 == 0) != !a.HasRegister2 {
+ return false
+ }
+ if (mask&Offset == 0) != !a.HasOffset {
+ // $0 has the immediate bit but value 0.
+ return false
+ }
+ if (mask&Float == 0) != !a.HasFloat {
+ return false
+ }
+ if (mask&String == 0) != !a.HasString {
+ return false
+ }
+ if (mask&Index == 0) != (a.Index == 0) {
+ return false
+ }
+ if (mask&Scale == 0) != (a.Scale == 0) {
+ return false
+ }
+ return true
+}
--- /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.
+
+package arch
+
+import (
+ "cmd/internal/obj"
+ "cmd/internal/obj/i386" // == 386
+ "cmd/internal/obj/x86" // == amd64
+)
+
+// Pseudo-registers whose names are the constant name without the leading R.
+const (
+ RFP = -(iota + 1)
+ RSB
+ RSP
+ RPC
+)
+
+// Arch wraps the link architecture object with more architecture-specific information.
+type Arch struct {
+ *obj.LinkArch
+ D_INDIR int // TODO: why not in LinkArch?
+ D_CONST2 int // TODO: why not in LinkArch?
+ // Register number of hardware stack pointer.
+ SP int
+ // Encoding of non-address.
+ NoAddr obj.Addr
+ // Map of instruction names to enumeration.
+ Instructions map[string]int
+ // Map of register names to enumeration.
+ Registers map[string]int
+ // Map of pseudo-instructions (TEXT, DATA etc.) to enumeration.
+ Pseudos map[string]int
+ // Instructions that take one operand whose result is a destination.
+ UnaryDestination map[int]bool
+}
+
+// Set configures the architecture specified by GOARCH and returns its representation.
+// It returns nil if GOARCH is not recognized.
+func Set(GOARCH string) *Arch {
+ // TODO: Is this how to set this up?
+ switch GOARCH {
+ case "386":
+ return arch386()
+ case "amd64":
+ return archAmd64()
+ }
+ return nil
+}
+
+func arch386() *Arch {
+ noAddr := obj.Addr{
+ Type: i386.D_NONE,
+ Index: i386.D_NONE,
+ }
+
+ registers := make(map[string]int)
+ // Create maps for easy lookup of instruction names etc.
+ // TODO: Should this be done in obj for us?
+ for i, s := range i386.Register {
+ registers[s] = i
+ }
+ // Pseudo-registers.
+ registers["SB"] = RSB
+ registers["FP"] = RFP
+ registers["SP"] = RSP
+ registers["PC"] = RPC
+
+ instructions := make(map[string]int)
+ for i, s := range i386.Anames {
+ instructions[s] = i
+ }
+ // Annoying aliases.
+ instructions["JA"] = i386.AJHI
+ instructions["JAE"] = i386.AJCC
+ instructions["JB"] = i386.AJCS
+ instructions["JBE"] = i386.AJLS
+ instructions["JC"] = i386.AJCS
+ instructions["JE"] = i386.AJEQ
+ instructions["JG"] = i386.AJGT
+ instructions["JHS"] = i386.AJCC
+ instructions["JL"] = i386.AJLT
+ instructions["JLO"] = i386.AJCS
+ instructions["JNA"] = i386.AJLS
+ instructions["JNAE"] = i386.AJCS
+ instructions["JNB"] = i386.AJCC
+ instructions["JNBE"] = i386.AJHI
+ instructions["JNC"] = i386.AJCC
+ instructions["JNG"] = i386.AJLE
+ instructions["JNGE"] = i386.AJLT
+ instructions["JNL"] = i386.AJGE
+ instructions["JNLE"] = i386.AJGT
+ instructions["JNO"] = i386.AJOC
+ instructions["JNP"] = i386.AJPC
+ instructions["JNS"] = i386.AJPL
+ instructions["JNZ"] = i386.AJNE
+ instructions["JO"] = i386.AJOS
+ instructions["JP"] = i386.AJPS
+ instructions["JPE"] = i386.AJPS
+ instructions["JPO"] = i386.AJPC
+ instructions["JS"] = i386.AJMI
+ instructions["JZ"] = i386.AJEQ
+ instructions["MASKMOVDQU"] = i386.AMASKMOVOU
+ instructions["MOVOA"] = i386.AMOVO
+ instructions["MOVNTDQ"] = i386.AMOVNTO
+
+ pseudos := make(map[string]int) // TEXT, DATA etc.
+ pseudos["DATA"] = i386.ADATA
+ pseudos["FUNCDATA"] = i386.AFUNCDATA
+ pseudos["GLOBL"] = i386.AGLOBL
+ pseudos["PCDATA"] = i386.APCDATA
+ pseudos["TEXT"] = i386.ATEXT
+
+ unaryDestination := make(map[int]bool) // Instruction takes one operand and result is a destination.
+ // These instructions write to prog.To.
+ unaryDestination[i386.ABSWAPL] = true
+ unaryDestination[i386.ACMPXCHG8B] = true
+ unaryDestination[i386.ADECB] = true
+ unaryDestination[i386.ADECL] = true
+ unaryDestination[i386.ADECW] = true
+ unaryDestination[i386.AINCB] = true
+ unaryDestination[i386.AINCL] = true
+ unaryDestination[i386.AINCW] = true
+ unaryDestination[i386.ANEGB] = true
+ unaryDestination[i386.ANEGL] = true
+ unaryDestination[i386.ANEGW] = true
+ unaryDestination[i386.ANOTB] = true
+ unaryDestination[i386.ANOTL] = true
+ unaryDestination[i386.ANOTW] = true
+ unaryDestination[i386.APOPL] = true
+ unaryDestination[i386.APOPW] = true
+ unaryDestination[i386.ASETCC] = true
+ unaryDestination[i386.ASETCS] = true
+ unaryDestination[i386.ASETEQ] = true
+ unaryDestination[i386.ASETGE] = true
+ unaryDestination[i386.ASETGT] = true
+ unaryDestination[i386.ASETHI] = true
+ unaryDestination[i386.ASETLE] = true
+ unaryDestination[i386.ASETLS] = true
+ unaryDestination[i386.ASETLT] = true
+ unaryDestination[i386.ASETMI] = true
+ unaryDestination[i386.ASETNE] = true
+ unaryDestination[i386.ASETOC] = true
+ unaryDestination[i386.ASETOS] = true
+ unaryDestination[i386.ASETPC] = true
+ unaryDestination[i386.ASETPL] = true
+ unaryDestination[i386.ASETPS] = true
+ unaryDestination[i386.AFFREE] = true
+ unaryDestination[i386.AFLDENV] = true
+ unaryDestination[i386.AFSAVE] = true
+ unaryDestination[i386.AFSTCW] = true
+ unaryDestination[i386.AFSTENV] = true
+ unaryDestination[i386.AFSTSW] = true
+
+ return &Arch{
+ LinkArch: &i386.Link386,
+ D_INDIR: i386.D_INDIR,
+ D_CONST2: i386.D_CONST2,
+ SP: i386.D_SP,
+ NoAddr: noAddr,
+ Instructions: instructions,
+ Registers: registers,
+ Pseudos: pseudos,
+ UnaryDestination: unaryDestination,
+ }
+}
+
+func archAmd64() *Arch {
+ noAddr := obj.Addr{
+ Type: x86.D_NONE,
+ Index: x86.D_NONE,
+ }
+
+ registers := make(map[string]int)
+ // Create maps for easy lookup of instruction names etc.
+ // TODO: Should this be done in obj for us?
+ for i, s := range x86.Register {
+ registers[s] = i
+ }
+ // Pseudo-registers.
+ registers["SB"] = RSB
+ registers["FP"] = RFP
+ registers["SP"] = RSP
+ registers["PC"] = RPC
+
+ instructions := make(map[string]int)
+ for i, s := range x86.Anames {
+ instructions[s] = i
+ }
+ // Annoying aliases.
+ instructions["JB"] = x86.AJCS
+ instructions["JC"] = x86.AJCS
+ instructions["JNAE"] = x86.AJCS
+ instructions["JLO"] = x86.AJCS
+ instructions["JAE"] = x86.AJCC
+ instructions["JNB"] = x86.AJCC
+ instructions["JNC"] = x86.AJCC
+ instructions["JHS"] = x86.AJCC
+ instructions["JE"] = x86.AJEQ
+ instructions["JZ"] = x86.AJEQ
+ instructions["JNZ"] = x86.AJNE
+ instructions["JBE"] = x86.AJLS
+ instructions["JNA"] = x86.AJLS
+ instructions["JA"] = x86.AJHI
+ instructions["JNBE"] = x86.AJHI
+ instructions["JS"] = x86.AJMI
+ instructions["JNS"] = x86.AJPL
+ instructions["JP"] = x86.AJPS
+ instructions["JPE"] = x86.AJPS
+ instructions["JNP"] = x86.AJPC
+ instructions["JPO"] = x86.AJPC
+ instructions["JL"] = x86.AJLT
+ instructions["JNGE"] = x86.AJLT
+ instructions["JNL"] = x86.AJGE
+ instructions["JNG"] = x86.AJLE
+ instructions["JG"] = x86.AJGT
+ instructions["JNLE"] = x86.AJGT
+ instructions["MASKMOVDQU"] = x86.AMASKMOVOU
+ instructions["MOVD"] = x86.AMOVQ
+ instructions["MOVDQ2Q"] = x86.AMOVQ
+
+ pseudos := make(map[string]int) // TEXT, DATA etc.
+ pseudos["DATA"] = x86.ADATA
+ pseudos["FUNCDATA"] = x86.AFUNCDATA
+ pseudos["GLOBL"] = x86.AGLOBL
+ pseudos["PCDATA"] = x86.APCDATA
+ pseudos["TEXT"] = x86.ATEXT
+
+ unaryDestination := make(map[int]bool) // Instruction takes one operand and result is a destination.
+ // These instructions write to prog.To.
+ unaryDestination[x86.ABSWAPL] = true
+ unaryDestination[x86.ABSWAPQ] = true
+ unaryDestination[x86.ACMPXCHG8B] = true
+ unaryDestination[x86.ADECB] = true
+ unaryDestination[x86.ADECL] = true
+ unaryDestination[x86.ADECQ] = true
+ unaryDestination[x86.ADECW] = true
+ unaryDestination[x86.AINCB] = true
+ unaryDestination[x86.AINCL] = true
+ unaryDestination[x86.AINCQ] = true
+ unaryDestination[x86.AINCW] = true
+ unaryDestination[x86.ANEGB] = true
+ unaryDestination[x86.ANEGL] = true
+ unaryDestination[x86.ANEGQ] = true
+ unaryDestination[x86.ANEGW] = true
+ unaryDestination[x86.ANOTB] = true
+ unaryDestination[x86.ANOTL] = true
+ unaryDestination[x86.ANOTQ] = true
+ unaryDestination[x86.ANOTW] = true
+ unaryDestination[x86.APOPL] = true
+ unaryDestination[x86.APOPQ] = true
+ unaryDestination[x86.APOPW] = true
+ unaryDestination[x86.ASETCC] = true
+ unaryDestination[x86.ASETCS] = true
+ unaryDestination[x86.ASETEQ] = true
+ unaryDestination[x86.ASETGE] = true
+ unaryDestination[x86.ASETGT] = true
+ unaryDestination[x86.ASETHI] = true
+ unaryDestination[x86.ASETLE] = true
+ unaryDestination[x86.ASETLS] = true
+ unaryDestination[x86.ASETLT] = true
+ unaryDestination[x86.ASETMI] = true
+ unaryDestination[x86.ASETNE] = true
+ unaryDestination[x86.ASETOC] = true
+ unaryDestination[x86.ASETOS] = true
+ unaryDestination[x86.ASETPC] = true
+ unaryDestination[x86.ASETPL] = true
+ unaryDestination[x86.ASETPS] = true
+ unaryDestination[x86.AFFREE] = true
+ unaryDestination[x86.AFLDENV] = true
+ unaryDestination[x86.AFSAVE] = true
+ unaryDestination[x86.AFSTCW] = true
+ unaryDestination[x86.AFSTENV] = true
+ unaryDestination[x86.AFSTSW] = true
+ unaryDestination[x86.AFXSAVE] = true
+ unaryDestination[x86.AFXSAVE64] = true
+ unaryDestination[x86.ASTMXCSR] = true
+
+ return &Arch{
+ LinkArch: &x86.Linkamd64,
+ D_INDIR: x86.D_INDIR,
+ D_CONST2: x86.D_NONE,
+ SP: x86.D_SP,
+ NoAddr: noAddr,
+ Instructions: instructions,
+ Registers: registers,
+ Pseudos: pseudos,
+ UnaryDestination: unaryDestination,
+ }
+}
--- /dev/null
+// Copyright 2014 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 (
+ "fmt"
+ "strings"
+ "text/scanner"
+
+ "cmd/asm/internal/addr"
+ "cmd/asm/internal/arch"
+ "cmd/asm/internal/flags"
+ "cmd/asm/internal/lex"
+ "cmd/internal/obj"
+)
+
+// TODO: This package has many numeric conversions that should be unnecessary.
+
+// symbolType returns the extern/static etc. type appropriate for the symbol.
+func (p *Parser) symbolType(a *addr.Addr) int {
+ switch a.Register {
+ case arch.RFP:
+ return p.arch.D_PARAM
+ case arch.RSP:
+ return p.arch.D_AUTO
+ case arch.RSB:
+ // See comment in addrToAddr.
+ if a.IsImmediateAddress {
+ return p.arch.D_ADDR
+ }
+ if a.IsStatic {
+ return p.arch.D_STATIC
+ }
+ return p.arch.D_EXTERN
+ }
+ p.errorf("invalid register for symbol %s", a.Symbol)
+ return 0
+}
+
+// staticVersion reports whether the data's Symbol has <>, as in data<>.
+// It returns 1 for static, 0 for non-static, because that's what obj wants.
+func staticVersion(a *addr.Addr) int {
+ if a.Symbol != "" && a.IsStatic {
+ return 1
+ }
+ return 0
+}
+
+// TODO: configure the architecture
+
+// TODO: This is hacky and irregular. When obj settles down, rewrite for simplicity.
+func (p *Parser) addrToAddr(a *addr.Addr) obj.Addr {
+ out := p.arch.NoAddr
+ if a.Has(addr.Symbol) {
+ // How to encode the symbols:
+ // syntax = Typ,Index
+ // $a(SB) = ADDR,EXTERN
+ // $a<>(SB) = ADDR,STATIC
+ // a(SB) = EXTERN,NONE
+ // a<>(SB) = STATIC,NONE
+ // The call to symbolType does the first column; we need to fix up Index here.
+ out.Type = int16(p.symbolType(a))
+ if a.IsImmediateAddress {
+ // Index field says whether it's a static.
+ switch a.Register {
+ case arch.RSB:
+ if a.IsStatic {
+ out.Index = uint8(p.arch.D_STATIC)
+ } else {
+ out.Index = uint8(p.arch.D_EXTERN)
+ }
+ default:
+ p.errorf("can't handle immediate address of %s not (SB)\n", a.Symbol)
+ }
+ }
+ out.Sym = obj.Linklookup(p.linkCtxt, a.Symbol, staticVersion(a))
+ } else if a.Has(addr.Register) {
+ // TODO: SP is tricky, and this isn't good enough.
+ // SP = D_SP
+ // 4(SP) = 4(D_SP)
+ // x+4(SP) = D_AUTO with sym=x TODO
+ out.Type = a.Register
+ if a.Register == arch.RSP {
+ out.Type = int16(p.arch.SP)
+ }
+ if a.IsIndirect {
+ out.Type += int16(p.arch.D_INDIR)
+ }
+ // a.Register2 handled in the instruction method; it's bizarre.
+ }
+ if a.Has(addr.Index) {
+ out.Index = uint8(a.Index) // TODO: out.Index == p.NoArch.Index should be same type as Register.
+ }
+ if a.Has(addr.Scale) {
+ out.Scale = a.Scale
+ }
+ if a.Has(addr.Offset) {
+ out.Offset = a.Offset
+ if a.Is(addr.Offset) {
+ // RHS of MOVL $0xf1, 0xf1 // crash
+ out.Type = int16(p.arch.D_INDIR + p.arch.D_NONE)
+ } else if a.IsImmediateConstant && out.Type == int16(p.arch.D_NONE) {
+ out.Type = int16(p.arch.D_CONST)
+ }
+ }
+ if a.Has(addr.Float) {
+ out.U.Dval = a.Float
+ out.Type = int16(p.arch.D_FCONST)
+ }
+ if a.Has(addr.String) {
+ out.U.Sval = a.String
+ out.Type = int16(p.arch.D_SCONST)
+ }
+ // TODO from https://go-review.googlesource.com/#/c/3196/ {
+ // There's a general rule underlying this special case and the one at line 91 (RHS OF MOVL $0xf1).
+ // Unless there's a $, it's an indirect.
+ // 4(R1)(R2*8)
+ // 4(R1)
+ // 4(R2*8)
+ // 4
+ // (R1)(R2*8)
+ // (R1)
+ // (R2*8)
+ // There should be a more general approach that doesn't just pick off cases.
+ // }
+ if a.IsIndirect && !a.Has(addr.Register) && a.Has(addr.Index) {
+ // LHS of LEAQ 0(BX*8), CX
+ out.Type = int16(p.arch.D_INDIR + p.arch.D_NONE)
+ }
+ return out
+}
+
+func (p *Parser) append(prog *obj.Prog, doLabel bool) {
+ if p.firstProg == nil {
+ p.firstProg = prog
+ } else {
+ p.lastProg.Link = prog
+ }
+ p.lastProg = prog
+ if doLabel {
+ p.pc++
+ for _, label := range p.pendingLabels {
+ if p.labels[label] != nil {
+ p.errorf("label %q multiply defined", label)
+ }
+ p.labels[label] = prog
+ }
+ p.pendingLabels = p.pendingLabels[0:0]
+ }
+ prog.Pc = int64(p.pc)
+ if *flags.Debug {
+ fmt.Println(p.histLineNum, prog)
+ }
+}
+
+// asmText assembles a TEXT pseudo-op.
+// TEXT runtime·sigtramp(SB),4,$0-0
+func (p *Parser) asmText(word string, operands [][]lex.Token) {
+ if len(operands) != 2 && len(operands) != 3 {
+ p.errorf("expect two or three operands for TEXT")
+ }
+
+ // Labels are function scoped. Patch existing labels and
+ // create a new label space for this TEXT.
+ p.patch()
+ p.labels = make(map[string]*obj.Prog)
+
+ // Operand 0 is the symbol name in the form foo(SB).
+ // That means symbol plus indirect on SB and no offset.
+ nameAddr := p.address(operands[0])
+ if !nameAddr.Is(addr.Symbol|addr.Register|addr.Indirect) || nameAddr.Register != arch.RSB {
+ p.errorf("TEXT symbol %q must be an offset from SB", nameAddr.Symbol)
+ }
+ name := nameAddr.Symbol
+ next := 1
+
+ // Next operand is the optional text flag, a literal integer.
+ flag := int8(0)
+ if len(operands) == 3 {
+ flagAddr := p.address(operands[next])
+ if !flagAddr.Is(addr.Offset) {
+ p.errorf("TEXT flag for %s must be an integer", name)
+ }
+ flag = int8(flagAddr.Offset)
+ next++
+ }
+
+ // Next operand is the frame and arg size.
+ // Bizarre syntax: $frameSize-argSize is two words, not subtraction.
+ // Both frameSize and argSize must be simple integers; only frameSize
+ // can be negative.
+ // The "-argSize" may be missing; if so, set it to obj.ArgsSizeUnknown.
+ // Parse left to right.
+ op := operands[next]
+ if len(op) < 2 || op[0].ScanToken != '$' {
+ p.errorf("TEXT %s: frame size must be an immediate constant", name)
+ }
+ op = op[1:]
+ negative := false
+ if op[0].ScanToken == '-' {
+ negative = true
+ op = op[1:]
+ }
+ if len(op) == 0 || op[0].ScanToken != scanner.Int {
+ p.errorf("TEXT %s: frame size must be an immediate constant", name)
+ }
+ frameSize := p.positiveAtoi(op[0].String())
+ if negative {
+ frameSize = -frameSize
+ }
+ op = op[1:]
+ argSize := int64(obj.ArgsSizeUnknown)
+ if len(op) > 0 {
+ // There is an argument size. It must be a minus sign followed by a non-negative integer literal.
+ if len(op) != 2 || op[0].ScanToken != '-' || op[1].ScanToken != scanner.Int {
+ p.errorf("TEXT %s: argument size must be of form -integer", name)
+ }
+ argSize = p.positiveAtoi(op[1].String())
+ }
+ prog := &obj.Prog{
+ Ctxt: p.linkCtxt,
+ As: int16(p.arch.ATEXT),
+ Lineno: int32(p.histLineNum),
+ From: obj.Addr{
+ Type: int16(p.symbolType(&nameAddr)),
+ Index: uint8(p.arch.D_NONE),
+ Sym: obj.Linklookup(p.linkCtxt, name, staticVersion(&nameAddr)),
+ Scale: flag,
+ },
+ To: obj.Addr{
+ Index: uint8(p.arch.D_NONE),
+ },
+ }
+
+ // Encoding of frameSize and argSize depends on architecture.
+ switch p.arch.Thechar {
+ case '6':
+ prog.To.Type = int16(p.arch.D_CONST)
+ prog.To.Offset = (argSize << 32) | frameSize
+ case '8':
+ prog.To.Type = int16(p.arch.D_CONST2)
+ prog.To.Offset = frameSize
+ prog.To.Offset2 = int32(argSize)
+ default:
+ p.errorf("internal error: can't encode TEXT $arg-frame")
+ }
+
+ p.append(prog, true)
+}
+
+// asmData assembles a DATA pseudo-op.
+// DATA masks<>+0x00(SB)/4, $0x00000000
+func (p *Parser) asmData(word string, operands [][]lex.Token) {
+ if len(operands) != 2 {
+ p.errorf("expect two operands for DATA")
+ }
+
+ // Operand 0 has the general form foo<>+0x04(SB)/4.
+ op := operands[0]
+ n := len(op)
+ if n < 3 || op[n-2].ScanToken != '/' || op[n-1].ScanToken != scanner.Int {
+ p.errorf("expect /size for DATA argument")
+ }
+ scale := p.scale(op[n-1].String())
+ op = op[:n-2]
+ nameAddr := p.address(op)
+ ok := nameAddr.Is(addr.Symbol|addr.Register|addr.Indirect) || nameAddr.Is(addr.Symbol|addr.Register|addr.Indirect|addr.Offset)
+ if !ok || nameAddr.Register != arch.RSB {
+ p.errorf("DATA symbol %q must be an offset from SB", nameAddr.Symbol)
+ }
+ name := strings.Replace(nameAddr.Symbol, "·", ".", 1)
+
+ // Operand 1 is an immediate constant or address.
+ valueAddr := p.address(operands[1])
+ if !valueAddr.IsImmediateConstant && !valueAddr.IsImmediateAddress {
+ p.errorf("DATA value must be an immediate constant or address")
+ }
+
+ // The addresses must not overlap. Easiest test: require monotonicity.
+ if lastAddr, ok := p.dataAddr[name]; ok && nameAddr.Offset < lastAddr {
+ p.errorf("overlapping DATA entry for %s", nameAddr.Symbol)
+ }
+ p.dataAddr[name] = nameAddr.Offset + int64(scale)
+
+ prog := &obj.Prog{
+ Ctxt: p.linkCtxt,
+ As: int16(p.arch.ADATA),
+ Lineno: int32(p.histLineNum),
+ From: obj.Addr{
+ Type: int16(p.symbolType(&nameAddr)),
+ Index: uint8(p.arch.D_NONE),
+ Sym: obj.Linklookup(p.linkCtxt, name, staticVersion(&nameAddr)),
+ Offset: nameAddr.Offset,
+ Scale: scale,
+ },
+ To: p.addrToAddr(&valueAddr),
+ }
+
+ p.append(prog, false)
+}
+
+// asmGlobl assembles a GLOBL pseudo-op.
+// GLOBL shifts<>(SB),8,$256
+// GLOBL shifts<>(SB),$256
+func (p *Parser) asmGlobl(word string, operands [][]lex.Token) {
+ if len(operands) != 2 && len(operands) != 3 {
+ p.errorf("expect two or three operands for GLOBL")
+ }
+
+ // Operand 0 has the general form foo<>+0x04(SB).
+ nameAddr := p.address(operands[0])
+ ok := nameAddr.Is(addr.Symbol|addr.Register|addr.Indirect) || nameAddr.Is(addr.Symbol|addr.Register|addr.Indirect|addr.Offset)
+ if !ok || nameAddr.Register != arch.RSB {
+ p.errorf("GLOBL symbol %q must be an offset from SB", nameAddr.Symbol)
+ }
+ name := strings.Replace(nameAddr.Symbol, "·", ".", 1)
+
+ // If three operands, middle operand is a scale.
+ scale := int8(0)
+ op := operands[1]
+ if len(operands) == 3 {
+ scaleAddr := p.address(op)
+ if !scaleAddr.Is(addr.Offset) {
+ p.errorf("GLOBL scale must be a constant")
+ }
+ scale = int8(scaleAddr.Offset)
+ op = operands[2]
+ }
+
+ // Final operand is an immediate constant.
+ sizeAddr := p.address(op)
+ if !sizeAddr.Is(addr.ImmediateConstant | addr.Offset) {
+ p.errorf("GLOBL size must be an immediate constant")
+ }
+ size := sizeAddr.Offset
+
+ // log.Printf("GLOBL %s %d, $%d", name, scale, size)
+ prog := &obj.Prog{
+ Ctxt: p.linkCtxt,
+ As: int16(p.arch.AGLOBL),
+ Lineno: int32(p.histLineNum),
+ From: obj.Addr{
+ Type: int16(p.symbolType(&nameAddr)),
+ Index: uint8(p.arch.D_NONE),
+ Sym: obj.Linklookup(p.linkCtxt, name, staticVersion(&nameAddr)),
+ Offset: nameAddr.Offset,
+ Scale: scale,
+ },
+ To: obj.Addr{
+ Type: int16(p.arch.D_CONST),
+ Index: uint8(p.arch.D_NONE),
+ Offset: size,
+ },
+ }
+ p.append(prog, false)
+}
+
+// asmPCData assembles a PCDATA pseudo-op.
+// PCDATA $2, $705
+func (p *Parser) asmPCData(word string, operands [][]lex.Token) {
+ if len(operands) != 2 {
+ p.errorf("expect two operands for PCDATA")
+ }
+
+ // Operand 0 must be an immediate constant.
+ addr0 := p.address(operands[0])
+ if !addr0.Is(addr.ImmediateConstant | addr.Offset) {
+ p.errorf("PCDATA value must be an immediate constant")
+ }
+ value0 := addr0.Offset
+
+ // Operand 1 must be an immediate constant.
+ addr1 := p.address(operands[1])
+ if !addr1.Is(addr.ImmediateConstant | addr.Offset) {
+ p.errorf("PCDATA value must be an immediate constant")
+ }
+ value1 := addr1.Offset
+
+ // log.Printf("PCDATA $%d, $%d", value0, value1)
+ prog := &obj.Prog{
+ Ctxt: p.linkCtxt,
+ As: int16(p.arch.APCDATA),
+ Lineno: int32(p.histLineNum),
+ From: obj.Addr{
+ Type: int16(p.arch.D_CONST),
+ Index: uint8(p.arch.D_NONE),
+ Offset: value0,
+ },
+ To: obj.Addr{
+ Type: int16(p.arch.D_CONST),
+ Index: uint8(p.arch.D_NONE),
+ Offset: value1,
+ },
+ }
+ p.append(prog, true)
+}
+
+// asmFuncData assembles a FUNCDATA pseudo-op.
+// FUNCDATA $1, funcdata<>+4(SB)
+func (p *Parser) asmFuncData(word string, operands [][]lex.Token) {
+ if len(operands) != 2 {
+ p.errorf("expect two operands for FUNCDATA")
+ }
+
+ // Operand 0 must be an immediate constant.
+ valueAddr := p.address(operands[0])
+ if !valueAddr.Is(addr.ImmediateConstant | addr.Offset) {
+ p.errorf("FUNCDATA value must be an immediate constant")
+ }
+ value0 := valueAddr.Offset
+
+ // Operand 1 is a symbol name in the form foo(SB).
+ // That means symbol plus indirect on SB and no offset.
+ nameAddr := p.address(operands[1])
+ ok := nameAddr.Is(addr.Symbol|addr.Register|addr.Indirect) || nameAddr.Is(addr.Symbol|addr.Register|addr.Indirect|addr.Offset)
+ if !ok || nameAddr.Register != arch.RSB {
+ p.errorf("FUNCDATA symbol %q must be an offset from SB", nameAddr.Symbol)
+ }
+ name := strings.Replace(nameAddr.Symbol, "·", ".", 1)
+ value1 := nameAddr.Offset
+
+ // log.Printf("FUNCDATA $%d, %d", value0, value1)
+ prog := &obj.Prog{
+ Ctxt: p.linkCtxt,
+ As: int16(p.arch.AFUNCDATA),
+ Lineno: int32(p.histLineNum),
+ From: obj.Addr{
+ Type: int16(p.arch.D_CONST),
+ Index: uint8(p.arch.D_NONE),
+ Offset: value0,
+ },
+ To: obj.Addr{
+ Type: int16(p.symbolType(&nameAddr)),
+ Index: uint8(p.arch.D_NONE),
+ Sym: obj.Linklookup(p.linkCtxt, name, staticVersion(&nameAddr)),
+ Offset: value1,
+ },
+ }
+ p.append(prog, true)
+}
+
+// asmJump assembles a jump instruction.
+// JMP R1
+// JMP exit
+// JMP 3(PC)
+func (p *Parser) asmJump(op int, a []addr.Addr) {
+ var target *addr.Addr
+ switch len(a) {
+ default:
+ p.errorf("jump must have one or two addresses")
+ case 1:
+ target = &a[0]
+ case 2:
+ if !a[0].Is(0) {
+ p.errorf("two-address jump must have empty first address")
+ }
+ target = &a[1]
+ }
+ prog := &obj.Prog{
+ Ctxt: p.linkCtxt,
+ Lineno: int32(p.histLineNum),
+ As: int16(op),
+ From: p.arch.NoAddr,
+ }
+ switch {
+ case target.Is(addr.Register):
+ // JMP R1
+ prog.To = p.addrToAddr(target)
+ case target.Is(addr.Symbol):
+ // JMP exit
+ targetProg := p.labels[target.Symbol]
+ if targetProg == nil {
+ p.toPatch = append(p.toPatch, Patch{prog, target.Symbol})
+ } else {
+ p.branch(prog, targetProg)
+ }
+ case target.Is(addr.Register | addr.Indirect), target.Is(addr.Register | addr.Indirect | addr.Offset):
+ // JMP 4(AX)
+ if target.Register == arch.RPC {
+ prog.To = obj.Addr{
+ Type: int16(p.arch.D_BRANCH),
+ Index: uint8(p.arch.D_NONE),
+ Offset: p.pc + 1 + target.Offset, // +1 because p.pc is incremented in link, below.
+ }
+ } else {
+ prog.To = p.addrToAddr(target)
+ }
+ case target.Is(addr.Symbol | addr.Indirect | addr.Register):
+ // JMP main·morestack(SB)
+ if target.Register != arch.RSB {
+ p.errorf("jmp to symbol must be SB-relative")
+ }
+ prog.To = obj.Addr{
+ Type: int16(p.arch.D_BRANCH),
+ Sym: obj.Linklookup(p.linkCtxt, target.Symbol, staticVersion(target)),
+ Index: uint8(p.arch.D_NONE),
+ Offset: target.Offset,
+ }
+ default:
+ p.errorf("cannot assemble jump %+v", target)
+ }
+ p.append(prog, true)
+}
+
+func (p *Parser) patch() {
+ for _, patch := range p.toPatch {
+ targetProg := p.labels[patch.label]
+ if targetProg == nil {
+ p.errorf("undefined label %s", patch.label)
+ } else {
+ p.branch(patch.prog, targetProg)
+ }
+ }
+ p.toPatch = p.toPatch[:0]
+}
+
+func (p *Parser) branch(jmp, target *obj.Prog) {
+ jmp.To = obj.Addr{
+ Type: int16(p.arch.D_BRANCH),
+ Index: uint8(p.arch.D_NONE),
+ }
+ jmp.To.U.Branch = target
+}
+
+// asmInstruction assembles an instruction.
+// MOVW R9, (R10)
+func (p *Parser) asmInstruction(op int, a []addr.Addr) {
+ prog := &obj.Prog{
+ Ctxt: p.linkCtxt,
+ Lineno: int32(p.histLineNum),
+ As: int16(op),
+ }
+ switch len(a) {
+ case 0:
+ prog.From = p.arch.NoAddr
+ prog.To = p.arch.NoAddr
+ case 1:
+ if p.arch.UnaryDestination[op] {
+ prog.From = p.arch.NoAddr
+ prog.To = p.addrToAddr(&a[0])
+ } else {
+ prog.From = p.addrToAddr(&a[0])
+ prog.To = p.arch.NoAddr
+ }
+ case 2:
+ prog.From = p.addrToAddr(&a[0])
+ prog.To = p.addrToAddr(&a[1])
+ // DX:AX as a register pair can only appear on the RHS.
+ // Bizarrely, to obj it's specified by setting index on the LHS.
+ // TODO: can we fix this?
+ if a[1].Has(addr.Register2) {
+ if int(prog.From.Index) != p.arch.D_NONE {
+ p.errorf("register pair operand on RHS must have register on LHS")
+ }
+ prog.From.Index = uint8(a[1].Register2)
+ }
+ case 3:
+ // CMPSD etc.; third operand is imm8, stored in offset, or a register.
+ prog.From = p.addrToAddr(&a[0])
+ prog.To = p.addrToAddr(&a[1])
+ switch {
+ case a[2].Is(addr.Offset):
+ prog.To.Offset = a[2].Offset
+ case a[2].Is(addr.Register):
+ // Strange reodering.
+ prog.To = p.addrToAddr(&a[2])
+ prog.From = p.addrToAddr(&a[1])
+ if !a[0].IsImmediateConstant {
+ p.errorf("expected $value for 1st operand")
+ }
+ prog.To.Offset = a[0].Offset
+ default:
+ p.errorf("expected offset or register for 3rd operand")
+ }
+ default:
+ p.errorf("can't handle instruction with %d operands", len(a))
+ }
+ p.append(prog, true)
+}
--- /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.
+
+package asm
+
+import (
+ "cmd/asm/internal/lex"
+ "testing"
+ "text/scanner"
+)
+
+type exprTest struct {
+ input string
+ output int64
+ atEOF bool
+}
+
+var exprTests = []exprTest{
+ // Simple
+ {"0", 0, true},
+ {"3", 3, true},
+ {"070", 8 * 7, true},
+ {"0x0f", 15, true},
+ {"0xFF", 255, true},
+ {"9223372036854775807", 9223372036854775807, true}, // max int64
+ // Unary
+ {"-0", 0, true},
+ {"~0", -1, true},
+ {"~0*0", 0, true},
+ {"+3", 3, true},
+ {"-3", -3, true},
+ {"-9223372036854775808", -9223372036854775808, true}, // min int64
+ // Binary
+ {"3+4", 3 + 4, true},
+ {"3-4", 3 - 4, true},
+ {"2|5", 2 | 5, true},
+ {"3^4", 3 ^ 4, true},
+ {"3*4", 3 * 4, true},
+ {"14/4", 14 / 4, true},
+ {"3<<4", 3 << 4, true},
+ {"48>>3", 48 >> 3, true},
+ {"3&9", 3 & 9, true},
+ // General
+ {"3*2+3", 3*2 + 3, true},
+ {"3+2*3", 3 + 2*3, true},
+ {"3*(2+3)", 3 * (2 + 3), true},
+ {"3*-(2+3)", 3 * -(2 + 3), true},
+ {"3<<2+4", 3<<2 + 4, true},
+ {"3<<2+4", 3<<2 + 4, true},
+ {"3<<(2+4)", 3 << (2 + 4), true},
+ // Junk at EOF.
+ {"3 x", 3, false},
+}
+
+func TestExpr(t *testing.T) {
+ 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())
+ if result != test.output {
+ t.Errorf("%d: %q evaluated to %d; expected %d", i, test.input, result, test.output)
+ }
+ tok := p.next()
+ if test.atEOF && tok.ScanToken != scanner.EOF {
+ t.Errorf("%d: %q: at EOF got %s", i, test.input, tok)
+ } else if !test.atEOF && tok.ScanToken == scanner.EOF {
+ t.Errorf("%d: %q: expected not EOF but at EOF", i, test.input)
+ }
+ }
+}
--- /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.
+
+// Package asm implements the parser and instruction generator for the assembler.
+// TODO: Split apart?
+package asm
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "strconv"
+ "text/scanner"
+
+ "cmd/asm/internal/addr"
+ "cmd/asm/internal/arch"
+ "cmd/asm/internal/lex"
+ "cmd/internal/obj"
+)
+
+type Parser struct {
+ lex lex.TokenReader
+ lineNum int // Line number in source file.
+ histLineNum int // Cumulative line number across source files.
+ errorLine int // (Cumulative) line number of last error.
+ errorCount int // Number of errors.
+ 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 []addr.Addr
+ arch *arch.Arch
+ linkCtxt *obj.Link
+ firstProg *obj.Prog
+ lastProg *obj.Prog
+ dataAddr map[string]int64 // Most recent address for DATA for this symbol.
+}
+
+type Patch struct {
+ prog *obj.Prog
+ label string
+}
+
+func NewParser(ctxt *obj.Link, ar *arch.Arch, lexer lex.TokenReader) *Parser {
+ return &Parser{
+ linkCtxt: ctxt,
+ arch: ar,
+ lex: lexer,
+ labels: make(map[string]*obj.Prog),
+ dataAddr: make(map[string]int64),
+ }
+}
+
+func (p *Parser) errorf(format string, args ...interface{}) {
+ if p.histLineNum == p.errorLine {
+ // Only one error per line.
+ return
+ }
+ p.errorLine = p.histLineNum
+ // Put file and line information on head of message.
+ format = "%s:%d: " + format + "\n"
+ args = append([]interface{}{p.lex.File(), p.lineNum}, args...)
+ fmt.Fprintf(os.Stderr, format, args...)
+ p.errorCount++
+ if p.errorCount > 10 {
+ log.Fatal("too many errors")
+ }
+}
+
+func (p *Parser) Parse() (*obj.Prog, bool) {
+ for p.line() {
+ }
+ if p.errorCount > 0 {
+ return nil, false
+ }
+ p.patch()
+ return p.firstProg, true
+}
+
+// WORD [ arg {, arg} ] (';' | '\n')
+func (p *Parser) line() bool {
+ // Skip newlines.
+ var tok lex.ScanToken
+ for {
+ tok = p.lex.Next()
+ // We save the line number here so error messages from this instruction
+ // are labeled with this line. Otherwise we complain after we've absorbed
+ // the terminating newline and the line numbers are off by one in errors.
+ p.lineNum = p.lex.Line()
+ p.histLineNum = lex.HistLine()
+ switch tok {
+ case '\n', ';':
+ continue
+ case scanner.EOF:
+ return false
+ }
+ break
+ }
+ // First item must be an identifier.
+ if tok != scanner.Ident {
+ p.errorf("expected identifier, found %q", p.lex.Text())
+ return false // Might as well stop now.
+ }
+ word := p.lex.Text()
+ operands := make([][]lex.Token, 0, 3)
+ // Zero or more comma-separated operands, one per loop.
+ for tok != '\n' && tok != ';' {
+ // Process one operand.
+ items := make([]lex.Token, 0, 3)
+ for {
+ tok = p.lex.Next()
+ if tok == ':' && len(operands) == 0 && len(items) == 0 { // First token.
+ p.pendingLabels = append(p.pendingLabels, word)
+ return true
+ }
+ if tok == scanner.EOF {
+ p.errorf("unexpected EOF")
+ return false
+ }
+ if tok == '\n' || tok == ';' || tok == ',' {
+ break
+ }
+ items = append(items, lex.Make(tok, p.lex.Text()))
+ }
+ if len(items) > 0 {
+ operands = append(operands, items)
+ } else if len(operands) > 0 || tok == ',' {
+ // Had a comma with nothing after.
+ p.errorf("missing operand")
+ }
+ }
+ i := p.arch.Pseudos[word]
+ if i != 0 {
+ p.pseudo(i, word, operands)
+ return true
+ }
+ i = p.arch.Instructions[word]
+ if i != 0 {
+ p.instruction(i, word, operands)
+ return true
+ }
+ p.errorf("unrecognized instruction %s", word)
+ return true
+}
+
+func (p *Parser) instruction(op int, word string, operands [][]lex.Token) {
+ p.addr = p.addr[0:0]
+ for _, op := range operands {
+ p.addr = append(p.addr, p.address(op))
+ }
+ // Is it a jump? TODO
+ if word[0] == 'J' || word == "CALL" {
+ p.asmJump(op, p.addr)
+ return
+ }
+ p.asmInstruction(op, p.addr)
+}
+
+func (p *Parser) pseudo(op int, word string, operands [][]lex.Token) {
+ switch op {
+ case p.arch.ATEXT:
+ p.asmText(word, operands)
+ case p.arch.ADATA:
+ p.asmData(word, operands)
+ case p.arch.AGLOBL:
+ p.asmGlobl(word, operands)
+ case p.arch.APCDATA:
+ p.asmPCData(word, operands)
+ case p.arch.AFUNCDATA:
+ p.asmFuncData(word, operands)
+ default:
+ p.errorf("unimplemented: %s", word)
+ }
+}
+
+func (p *Parser) start(operand []lex.Token) {
+ p.input = operand
+ p.inputPos = 0
+}
+
+// address parses the operand into a link address structure.
+func (p *Parser) address(operand []lex.Token) addr.Addr {
+ p.start(operand)
+ addr := addr.Addr{}
+ p.operand(&addr)
+ return addr
+}
+
+// parse (R). The opening paren is known to be there.
+// The return value states whether it was a scaled mode.
+func (p *Parser) parenRegister(a *addr.Addr) bool {
+ p.next()
+ tok := p.next()
+ if tok.ScanToken != scanner.Ident {
+ p.errorf("expected register, got %s", tok)
+ }
+ r, present := p.arch.Registers[tok.String()]
+ if !present {
+ p.errorf("expected register, found %s", tok.String())
+ }
+ a.IsIndirect = true
+ scaled := p.peek() == '*'
+ if scaled {
+ // (R*2)
+ p.next()
+ tok := p.get(scanner.Int)
+ a.Scale = p.scale(tok.String())
+ a.Index = int16(r) // TODO: r should have type int16 but is uint8.
+ } else {
+ if a.HasRegister {
+ p.errorf("multiple indirections")
+ }
+ a.HasRegister = true
+ a.Register = int16(r)
+ }
+ p.expect(')')
+ p.next()
+ return scaled
+}
+
+// scale converts a decimal string into a valid scale factor.
+func (p *Parser) scale(s string) int8 {
+ switch s {
+ case "1", "2", "4", "8":
+ return int8(s[0] - '0')
+ }
+ p.errorf("bad scale: %s", s)
+ return 0
+}
+
+// parse (R) or (R)(R*scale). The opening paren is known to be there.
+func (p *Parser) addressMode(a *addr.Addr) {
+ scaled := p.parenRegister(a)
+ if !scaled && p.peek() == '(' {
+ p.parenRegister(a)
+ }
+}
+
+// operand parses a general operand and stores the result in *a.
+func (p *Parser) operand(a *addr.Addr) bool {
+ if len(p.input) == 0 {
+ p.errorf("empty operand: cannot happen")
+ return false
+ }
+ switch p.peek() {
+ case '$':
+ p.next()
+ switch p.peek() {
+ case scanner.Ident:
+ a.IsImmediateAddress = true
+ p.operand(a) // TODO
+ case scanner.String:
+ a.IsImmediateConstant = true
+ a.HasString = true
+ a.String = p.atos(p.next().String())
+ case scanner.Int, scanner.Float, '+', '-', '~', '(':
+ a.IsImmediateConstant = true
+ if p.have(scanner.Float) {
+ a.HasFloat = true
+ a.Float = p.floatExpr()
+ } else {
+ a.HasOffset = true
+ a.Offset = int64(p.expr())
+ }
+ default:
+ p.errorf("illegal %s in immediate operand", p.next().String())
+ }
+ case '*':
+ p.next()
+ tok := p.next()
+ r, present := p.arch.Registers[tok.String()]
+ if !present {
+ p.errorf("expected register; got %s", tok.String())
+ }
+ a.HasRegister = true
+ a.Register = int16(r)
+ case '(':
+ p.next()
+ if p.peek() == scanner.Ident {
+ p.back()
+ p.addressMode(a)
+ break
+ }
+ p.back()
+ fallthrough
+ case '+', '-', '~', scanner.Int, scanner.Float:
+ if p.have(scanner.Float) {
+ a.HasFloat = true
+ a.Float = p.floatExpr()
+ } else {
+ a.HasOffset = true
+ a.Offset = int64(p.expr())
+ }
+ if p.peek() != scanner.EOF {
+ p.expect('(')
+ p.addressMode(a)
+ }
+ case scanner.Ident:
+ tok := p.next()
+ // Either R or (most general) ident<>+4(SB)(R*scale).
+ if r, present := p.arch.Registers[tok.String()]; present {
+ a.HasRegister = true
+ a.Register = int16(r)
+ // Possibly register pair: DX:AX.
+ if p.peek() == ':' {
+ p.next()
+ tok = p.get(scanner.Ident)
+ a.HasRegister2 = true
+ a.Register2 = int16(p.arch.Registers[tok.String()])
+ }
+ break
+ }
+ // Weirdness with statics: Might now have "<>".
+ if p.peek() == '<' {
+ p.next()
+ p.get('>')
+ a.IsStatic = true
+ }
+ if p.peek() == '+' || p.peek() == '-' {
+ a.HasOffset = true
+ a.Offset = int64(p.expr())
+ }
+ a.Symbol = tok.String()
+ if p.peek() == scanner.EOF {
+ break
+ }
+ // Expect (SB) or (FP)
+ p.expect('(')
+ p.parenRegister(a)
+ if a.Register != arch.RSB && a.Register != arch.RFP && a.Register != arch.RSP {
+ p.errorf("expected SB, FP, or SP offset for %s", tok)
+ }
+ // Possibly have scaled register (CX*8).
+ if p.peek() != scanner.EOF {
+ p.expect('(')
+ p.addressMode(a)
+ }
+ default:
+ p.errorf("unexpected %s in operand", p.next())
+ }
+ p.expect(scanner.EOF)
+ return true
+}
+
+// Note: There are two changes in the expression handling here
+// compared to the old yacc/C implemenatations. Neither has
+// much practical consequence because the expressions we
+// see in assembly code are simple, but for the record:
+//
+// 1) Evaluation uses uint64; the old one used int64.
+// 2) Precedence uses Go rules not C rules.
+
+// expr = term | term ('+' | '-' | '|' | '^') term.
+func (p *Parser) expr() uint64 {
+ value := p.term()
+ for {
+ switch p.peek() {
+ case '+':
+ p.next()
+ value += p.term()
+ case '-':
+ p.next()
+ value -= p.term()
+ case '|':
+ p.next()
+ value |= p.term()
+ case '^':
+ p.next()
+ value ^= p.term()
+ default:
+ return value
+ }
+ }
+}
+
+// floatExpr = fconst | '-' floatExpr | '+' floatExpr | '(' floatExpr ')'
+func (p *Parser) floatExpr() float64 {
+ tok := p.next()
+ switch tok.ScanToken {
+ case '(':
+ v := p.floatExpr()
+ if p.next().ScanToken != ')' {
+ p.errorf("missing closing paren")
+ }
+ return v
+ case '+':
+ return +p.floatExpr()
+ case '-':
+ return -p.floatExpr()
+ case scanner.Float:
+ return p.atof(tok.String())
+ }
+ p.errorf("unexpected %s evaluating float expression", tok)
+ return 0
+}
+
+// term = factor | factor ('*' | '/' | '%' | '>>' | '<<' | '&') factor
+func (p *Parser) term() uint64 {
+ value := p.factor()
+ for {
+ switch p.peek() {
+ case '*':
+ p.next()
+ value *= p.factor()
+ case '/':
+ p.next()
+ if value&(1<<63) != 0 {
+ p.errorf("divide with high bit set")
+ }
+ value /= p.factor()
+ case '%':
+ p.next()
+ value %= p.factor()
+ case lex.LSH:
+ p.next()
+ shift := p.factor()
+ if int64(shift) < 0 {
+ p.errorf("negative left shift %d", shift)
+ }
+ return value << shift
+ case lex.RSH:
+ p.next()
+ shift := p.term()
+ if shift < 0 {
+ p.errorf("negative right shift %d", shift)
+ }
+ if shift > 0 && value&(1<<63) != 0 {
+ p.errorf("right shift with high bit set")
+ }
+ value >>= uint(shift)
+ case '&':
+ p.next()
+ value &= p.factor()
+ default:
+ return value
+ }
+ }
+}
+
+// factor = const | '+' factor | '-' factor | '~' factor | '(' expr ')'
+func (p *Parser) factor() uint64 {
+ tok := p.next()
+ switch tok.ScanToken {
+ case scanner.Int:
+ return p.atoi(tok.String())
+ case '+':
+ return +p.factor()
+ case '-':
+ return -p.factor()
+ case '~':
+ return ^p.factor()
+ case '(':
+ v := p.expr()
+ if p.next().ScanToken != ')' {
+ p.errorf("missing closing paren")
+ }
+ return v
+ }
+ p.errorf("unexpected %s evaluating expression", tok)
+ return 0
+}
+
+// positiveAtoi returns an int64 that must be >= 0.
+func (p *Parser) positiveAtoi(str string) int64 {
+ value, err := strconv.ParseInt(str, 0, 64)
+ if err != nil {
+ p.errorf("%s", err)
+ }
+ if value < 0 {
+ p.errorf("%s overflows int64", str)
+ }
+ return value
+}
+
+func (p *Parser) atoi(str string) uint64 {
+ value, err := strconv.ParseUint(str, 0, 64)
+ if err != nil {
+ p.errorf("%s", err)
+ }
+ return value
+}
+
+func (p *Parser) atof(str string) float64 {
+ value, err := strconv.ParseFloat(str, 64)
+ if err != nil {
+ p.errorf("%s", err)
+ }
+ return value
+}
+
+func (p *Parser) atos(str string) string {
+ value, err := strconv.Unquote(str)
+ if err != nil {
+ p.errorf("%s", err)
+ }
+ return value
+}
+
+// EOF represents the end of input.
+var EOF = lex.Make(scanner.EOF, "EOF")
+
+func (p *Parser) next() lex.Token {
+ if !p.more() {
+ return EOF
+ }
+ tok := p.input[p.inputPos]
+ p.inputPos++
+ return tok
+}
+
+func (p *Parser) back() {
+ p.inputPos--
+}
+
+func (p *Parser) peek() lex.ScanToken {
+ if p.more() {
+ return p.input[p.inputPos].ScanToken
+ }
+ return scanner.EOF
+}
+
+func (p *Parser) more() bool {
+ return p.inputPos < len(p.input)
+}
+
+// get verifies that the next item has the expected type and returns it.
+func (p *Parser) get(expected lex.ScanToken) lex.Token {
+ p.expect(expected)
+ return p.next()
+}
+
+// expect verifies that the next item has the expected type. It does not consume it.
+func (p *Parser) expect(expected lex.ScanToken) {
+ if p.peek() != expected {
+ p.errorf("expected %s, found %s", expected, p.next())
+ }
+}
+
+// have reports whether the remaining tokens contain the specified token.
+func (p *Parser) have(token lex.ScanToken) bool {
+ for i := p.inputPos; i < len(p.input); i++ {
+ if p.input[i].ScanToken == token {
+ return true
+ }
+ }
+ return false
+}
--- /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.
+
+// Package flags implements top-level flags and the usage message for the assembler.
+package flags
+
+import (
+ "flag"
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+var (
+ Debug = flag.Bool("debug", false, "dump instructions as they are parsed")
+ OutputFile = flag.String("o", "", "output file; default foo.6 for /a/b/c/foo.s on amd64")
+ PrintOut = flag.Bool("S", false, "print assembly and machine code")
+ TrimPath = flag.String("trimpath", "", "remove prefix from recorded source file paths (unused TODO)")
+)
+
+var (
+ D MultiFlag
+ I MultiFlag
+)
+
+func init() {
+ flag.Var(&D, "D", "predefined symbol with optional simple value -D=identifer=value; can be set multiple times")
+ flag.Var(&I, "I", "include directory; can be set multiple times")
+}
+
+// MultiFlag allows setting a value multiple times to collect a list, as in -I=dir1 -I=dir2.
+type MultiFlag []string
+
+func (m *MultiFlag) String() string {
+ return fmt.Sprint(*m)
+}
+
+func (m *MultiFlag) Set(val string) error {
+ (*m) = append(*m, val)
+ return nil
+}
+
+func Usage() {
+ fmt.Fprintf(os.Stderr, "usage: asm [options] file.s\n")
+ fmt.Fprintf(os.Stderr, "Flags:\n")
+ flag.PrintDefaults()
+ os.Exit(2)
+}
+
+func Parse(theChar int) {
+ flag.Usage = Usage
+ flag.Parse()
+ if flag.NArg() != 1 {
+ flag.Usage()
+ }
+
+ // Flag refinement.
+ if *OutputFile == "" {
+ input := filepath.Base(flag.Arg(0))
+ if strings.HasSuffix(input, ".s") {
+ input = input[:len(input)-2]
+ }
+ *OutputFile = fmt.Sprintf("%s.%c", input, theChar)
+ }
+}
--- /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.
+
+package lex
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "strconv"
+ "strings"
+ "text/scanner"
+
+ "cmd/asm/internal/flags"
+ "cmd/internal/obj"
+)
+
+// Input is the main input: a stack of readers and some macro definitions.
+// It also handles #include processing (by pushing onto the input stack)
+// and parses and instantiates macro definitions.
+type Input struct {
+ Stack
+ includes []string
+ beginningOfLine bool
+ ifdefStack []bool
+ macros map[string]*Macro
+ text string // Text of last token returned by Next.
+ peek bool
+ peekToken ScanToken
+ peekText string
+}
+
+// NewInput returns a
+func NewInput(name string) *Input {
+ return &Input{
+ // include directories: look in source dir, then -I directories.
+ includes: append([]string{filepath.Dir(name)}, flags.I...),
+ beginningOfLine: true,
+ macros: predefine(flags.D),
+ }
+}
+
+// predefine installs the macros set by the -D flag on the command line.
+func predefine(defines flags.MultiFlag) map[string]*Macro {
+ macros := make(map[string]*Macro)
+ for _, name := range defines {
+ value := "1"
+ i := strings.IndexRune(name, '=')
+ if i > 0 {
+ name, value = name[:i], name[i+1:]
+ }
+ tokens := Tokenize(name)
+ if len(tokens) != 1 || tokens[0].ScanToken != scanner.Ident {
+ fmt.Fprintf(os.Stderr, "asm: parsing -D: %q is not a valid identifier name\n", tokens[0])
+ flags.Usage()
+ }
+ macros[name] = &Macro{
+ name: name,
+ args: nil,
+ tokens: Tokenize(value),
+ }
+ }
+ return macros
+}
+
+func (in *Input) Error(args ...interface{}) {
+ fmt.Fprintf(os.Stderr, "%s:%d: %s", in.File(), in.Line(), fmt.Sprintln(args...))
+ os.Exit(1)
+}
+
+// expectText is like Error but adds "got XXX" where XXX is a quoted representation of the most recent token.
+func (in *Input) expectText(args ...interface{}) {
+ in.Error(append(args, "; got", strconv.Quote(in.Stack.Text()))...)
+}
+
+// enabled reports whether the input is enabled by an ifdef, or is at the top level.
+func (in *Input) enabled() bool {
+ return len(in.ifdefStack) == 0 || in.ifdefStack[len(in.ifdefStack)-1]
+}
+
+func (in *Input) expectNewline(directive string) {
+ tok := in.Stack.Next()
+ if tok != '\n' {
+ in.expectText("expected newline after", directive)
+ }
+}
+
+func (in *Input) Next() ScanToken {
+ if in.peek {
+ in.peek = false
+ tok := in.peekToken
+ in.text = in.peekText
+ return tok
+ }
+ // If we cannot generate a token after 100 tries, we're in trouble.
+ // The usual case is caught by Push, below, but be safe.
+ for i := 0; i < 100; i++ {
+ tok := in.Stack.Next()
+ switch tok {
+ case '#':
+ if !in.beginningOfLine {
+ in.Error("'#' must be first item on line")
+ }
+ in.beginningOfLine = in.hash()
+ case scanner.Ident:
+ // Is it a macro name?
+ name := in.Stack.Text()
+ macro := in.macros[name]
+ if macro != nil {
+ in.invokeMacro(macro)
+ continue
+ }
+ fallthrough
+ default:
+ in.beginningOfLine = tok == '\n'
+ if in.enabled() {
+ in.text = in.Stack.Text()
+ return tok
+ }
+ }
+ }
+ in.Error("recursive macro invocation")
+ return 0
+}
+
+func (in *Input) Text() string {
+ return in.text
+}
+
+// hash processes a # preprocessor directive. It returns true iff it completes.
+func (in *Input) hash() bool {
+ // We have a '#'; it must be followed by a known word (define, include, etc.).
+ tok := in.Stack.Next()
+ if tok != scanner.Ident {
+ in.expectText("expected identifier after '#'")
+ }
+ if !in.enabled() {
+ // Can only start including again if we are at #else or #endif.
+ // We let #line through because it might affect errors.
+ switch in.Stack.Text() {
+ case "else", "endif", "line":
+ // Press on.
+ default:
+ return false
+ }
+ }
+ switch in.Stack.Text() {
+ case "define":
+ in.define()
+ case "else":
+ in.else_()
+ case "endif":
+ in.endif()
+ case "ifdef":
+ in.ifdef(true)
+ case "ifndef":
+ in.ifdef(false)
+ case "include":
+ in.include()
+ case "line":
+ in.line()
+ case "undef":
+ in.undef()
+ default:
+ in.Error("unexpected token after '#':", in.Stack.Text())
+ }
+ return true
+}
+
+// macroName returns the name for the macro being referenced.
+func (in *Input) macroName() string {
+ // We use the Stack's input method; no macro processing at this stage.
+ tok := in.Stack.Next()
+ if tok != scanner.Ident {
+ in.expectText("expected identifier after # directive")
+ }
+ // Name is alphanumeric by definition.
+ return in.Stack.Text()
+}
+
+// #define processing.
+func (in *Input) define() {
+ name := in.macroName()
+ args, tokens := in.macroDefinition(name)
+ in.defineMacro(name, args, tokens)
+}
+
+// defineMacro stores the macro definition in the Input.
+func (in *Input) defineMacro(name string, args []string, tokens []Token) {
+ if in.macros[name] != nil {
+ in.Error("redefinition of macro:", name)
+ }
+ in.macros[name] = &Macro{
+ name: name,
+ args: args,
+ tokens: tokens,
+ }
+}
+
+// macroDefinition returns the list of formals and the tokens of the definition.
+// The argument list is nil for no parens on the definition; otherwise a list of
+// formal argument names.
+func (in *Input) macroDefinition(name string) ([]string, []Token) {
+ tok := in.Stack.Next()
+ if tok == '\n' || tok == scanner.EOF {
+ in.Error("no definition for macro:", name)
+ }
+ var args []string
+ if tok == '(' {
+ // Macro has arguments. Scan list of formals.
+ acceptArg := true
+ args = []string{} // Zero length but not nil.
+ Loop:
+ for {
+ tok = in.Stack.Next()
+ switch tok {
+ case ')':
+ tok = in.Stack.Next() // First token of macro definition.
+ break Loop
+ case ',':
+ if acceptArg {
+ in.Error("bad syntax in definition for macro:", name)
+ }
+ acceptArg = true
+ case scanner.Ident:
+ if !acceptArg {
+ in.Error("bad syntax in definition for macro:", name)
+ }
+ arg := in.Stack.Text()
+ if i := lookup(args, arg); i >= 0 {
+ in.Error("duplicate argument", arg, "in definition for macro:", name)
+ }
+ args = append(args, arg)
+ acceptArg = false
+ default:
+ in.Error("bad definition for macro:", name)
+ }
+ }
+ }
+ var tokens []Token
+ // Scan to newline. Backslashes escape newlines.
+ for tok != '\n' {
+ if tok == '\\' {
+ tok = in.Stack.Next()
+ if tok != '\n' && tok != '\\' {
+ in.Error(`can only escape \ or \n in definition for macro:`, name)
+ }
+ }
+ tokens = append(tokens, Make(tok, in.Stack.Text()))
+ tok = in.Stack.Next()
+ }
+ return args, tokens
+}
+
+func lookup(args []string, arg string) int {
+ for i, a := range args {
+ if a == arg {
+ return i
+ }
+ }
+ return -1
+}
+
+// invokeMacro pushes onto the input Stack a Slice that holds the macro definition with the actual
+// parameters substituted for the formals.
+// Invoking a macro does not touch the PC/line history.
+func (in *Input) invokeMacro(macro *Macro) {
+ // If the macro has no arguments, just substitute the text.
+ if macro.args == nil {
+ in.Push(NewSlice(in.File(), in.Line(), macro.tokens))
+ return
+ }
+ tok := in.Stack.Next()
+ if tok != '(' {
+ // If the macro has arguments but is invoked without them, all we push is the macro name.
+ // First, put back the token.
+ in.peekToken = tok
+ in.peekText = in.text
+ in.peek = true
+ in.Push(NewSlice(in.File(), in.Line(), []Token{Make(macroName, macro.name)}))
+ return
+ }
+ actuals := in.argsFor(macro)
+ var tokens []Token
+ for _, tok := range macro.tokens {
+ if tok.ScanToken != scanner.Ident {
+ tokens = append(tokens, tok)
+ continue
+ }
+ substitution := actuals[tok.text]
+ if substitution == nil {
+ tokens = append(tokens, tok)
+ continue
+ }
+ tokens = append(tokens, substitution...)
+ }
+ in.Push(NewSlice(in.File(), in.Line(), tokens))
+}
+
+// argsFor returns a map from formal name to actual value for this argumented macro invocation.
+// The opening parenthesis has been absorbed.
+func (in *Input) argsFor(macro *Macro) map[string][]Token {
+ var args [][]Token
+ // One macro argument per iteration. Collect them all and check counts afterwards.
+ for argNum := 0; ; argNum++ {
+ tokens, tok := in.collectArgument(macro)
+ args = append(args, tokens)
+ if tok == ')' {
+ break
+ }
+ }
+ // Zero-argument macros are tricky.
+ if len(macro.args) == 0 && len(args) == 1 && args[0] == nil {
+ args = nil
+ } else if len(args) != len(macro.args) {
+ in.Error("wrong arg count for macro", macro.name)
+ }
+ argMap := make(map[string][]Token)
+ for i, arg := range args {
+ argMap[macro.args[i]] = arg
+ }
+ return argMap
+}
+
+// collectArgument returns the actual tokens for a single argument of a macro.
+// It also returns the token that terminated the argument, which will always
+// be either ',' or ')'. The starting '(' has been scanned.
+func (in *Input) collectArgument(macro *Macro) ([]Token, ScanToken) {
+ nesting := 0
+ var tokens []Token
+ for {
+ tok := in.Stack.Next()
+ if tok == scanner.EOF || tok == '\n' {
+ in.Error("unterminated arg list invoking macro:", macro.name)
+ }
+ if nesting == 0 && (tok == ')' || tok == ',') {
+ return tokens, tok
+ }
+ if tok == '(' {
+ nesting++
+ }
+ if tok == ')' {
+ nesting--
+ }
+ tokens = append(tokens, Make(tok, in.Stack.Text()))
+ }
+}
+
+// #ifdef and #ifndef processing.
+func (in *Input) ifdef(truth bool) {
+ name := in.macroName()
+ in.expectNewline("#if[n]def")
+ if _, defined := in.macros[name]; !defined {
+ truth = !truth
+ }
+ in.ifdefStack = append(in.ifdefStack, truth)
+}
+
+// #else processing
+func (in *Input) else_() {
+ in.expectNewline("#else")
+ if len(in.ifdefStack) == 0 {
+ in.Error("unmatched #else")
+ }
+ in.ifdefStack[len(in.ifdefStack)-1] = !in.ifdefStack[len(in.ifdefStack)-1]
+}
+
+// #endif processing.
+func (in *Input) endif() {
+ in.expectNewline("#endif")
+ if len(in.ifdefStack) == 0 {
+ in.Error("unmatched #endif")
+ }
+ in.ifdefStack = in.ifdefStack[:len(in.ifdefStack)-1]
+}
+
+// #include processing.
+func (in *Input) include() {
+ // Find and parse string.
+ tok := in.Stack.Next()
+ if tok != scanner.String {
+ in.expectText("expected string after #include")
+ }
+ name, err := strconv.Unquote(in.Stack.Text())
+ if err != nil {
+ in.Error("unquoting include file name: ", err)
+ }
+ in.expectNewline("#include")
+ // Push tokenizer for file onto stack.
+ fd, err := os.Open(name)
+ if err != nil {
+ for _, dir := range in.includes {
+ fd, err = os.Open(filepath.Join(dir, name))
+ if err == nil {
+ break
+ }
+ }
+ if err != nil {
+ in.Error("#include:", err)
+ }
+ }
+ in.Push(NewTokenizer(name, fd, fd))
+}
+
+// #line processing.
+func (in *Input) line() {
+ // Only need to handle Plan 9 format: #line 337 "filename"
+ tok := in.Stack.Next()
+ if tok != scanner.Int {
+ in.expectText("expected line number after #line")
+ }
+ line, err := strconv.Atoi(in.Stack.Text())
+ if err != nil {
+ in.Error("error parsing #line (cannot happen):", err)
+ }
+ tok = in.Stack.Next()
+ if tok != scanner.String {
+ in.expectText("expected file name in #line")
+ }
+ file, err := strconv.Unquote(in.Stack.Text())
+ if err != nil {
+ in.Error("unquoting #line file name: ", err)
+ }
+ tok = in.Stack.Next()
+ if tok != '\n' {
+ in.Error("unexpected token at end of #line: ", tok)
+ }
+ obj.Linklinehist(linkCtxt, histLine, file, line)
+ in.Stack.SetPos(line, file)
+}
+
+// #undef processing
+func (in *Input) undef() {
+ name := in.macroName()
+ if in.macros[name] == nil {
+ in.Error("#undef for undefined macro:", name)
+ }
+ // Newline must be next.
+ tok := in.Stack.Next()
+ if tok != '\n' {
+ in.Error("syntax error in #undef for macro:", name)
+ }
+ delete(in.macros, name)
+}
+
+func (in *Input) Push(r TokenReader) {
+ if len(in.tr) > 100 {
+ in.Error("input recursion")
+ }
+ in.Stack.Push(r)
+}
+
+func (in *Input) Close() {
+}
--- /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.
+
+// Package lex implements lexical analysis for the assembler.
+package lex
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "strings"
+ "text/scanner"
+
+ "cmd/internal/obj"
+)
+
+// A ScanToken represents an input item. It is a simple wrapping of rune, as
+// returned by text/scanner.Scanner, plus a couple of extra values.
+type ScanToken rune
+
+const (
+ // Asm defines some two-character lexemes. We make up
+ // a rune/ScanToken value for them - ugly but simple.
+ LSH ScanToken = -1000 - iota // << Left shift.
+ RSH // >> Logical right shift.
+ ARR // -> Used on ARM for shift type 3, arithmetic right shift.
+ ROT // @> Used on ARM for shift type 4, rotate right.
+ macroName // name of macro that should not be expanded
+)
+
+func (t ScanToken) String() string {
+ switch t {
+ case scanner.EOF:
+ return "EOF"
+ case scanner.Ident:
+ return "identifier"
+ case scanner.Int:
+ return "integer constant"
+ case scanner.Float:
+ return "float constant"
+ case scanner.Char:
+ return "rune constant"
+ case scanner.String:
+ return "string constant"
+ case scanner.RawString:
+ return "raw string constant"
+ case scanner.Comment:
+ return "comment"
+ default:
+ return fmt.Sprintf("%q", rune(t))
+ }
+}
+
+var (
+ // It might be nice if these weren't global.
+ linkCtxt *obj.Link // The link context for all instructions.
+ histLine int = 1 // The cumulative count of lines processed.
+)
+
+// HistLine reports the cumulative source line number of the token,
+// for use in the Prog structure for the linker. (It's always handling the
+// instruction from the current lex line.)
+func HistLine() int {
+ return histLine
+}
+
+// NewLexer returns a lexer for the named file and the given link context.
+func NewLexer(name string, ctxt *obj.Link) TokenReader {
+ linkCtxt = ctxt
+ input := NewInput(name)
+ fd, err := os.Open(name)
+ if err != nil {
+ log.Fatalf("asm: %s\n", err)
+ }
+ input.Push(NewTokenizer(name, fd, fd))
+ return input
+}
+
+// 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
+// the text of the most recently returned token is, and where it was found.
+// The underlying scanner elides all spaces except newline, so the input looks like a stream of
+// Tokens; original spacing is lost but we don't need it.
+type TokenReader interface {
+ // Next returns the next token.
+ Next() ScanToken
+ // The following methods all refer to the most recent token returned by Next.
+ // Text returns the original string representation of the token.
+ Text() string
+ // File reports the source file name of the token.
+ File() string
+ // Line reports the source line number of the token.
+ Line() int
+ // SetPos sets the file and line number.
+ SetPos(line int, file string)
+ // Close does any teardown required.
+ Close()
+}
+
+// A Token is a scan token plus its string value.
+// A macro is stored as a sequence of Tokens with spaces stripped.
+type Token struct {
+ ScanToken
+ text string
+}
+
+// Make returns a Token with the given rune (ScanToken) and text representation.
+func Make(token ScanToken, text string) Token {
+ // If the symbol starts with center dot, as in ·x, rewrite it as ""·x
+ if token == scanner.Ident && strings.HasPrefix(text, "\u00B7") {
+ text = `""` + text
+ }
+ // Substitute the substitutes for . and /.
+ text = strings.Replace(text, "\u00B7", ".", -1)
+ text = strings.Replace(text, "\u2215", "/", -1)
+ return Token{ScanToken: token, text: text}
+}
+
+func (l Token) String() string {
+ return l.text
+}
+
+// A Macro represents the definition of a #defined macro.
+type Macro struct {
+ name string // The #define name.
+ args []string // Formal arguments.
+ tokens []Token // Body of macro.
+}
+
+// Tokenize turns a string into a list of Tokens; used to parse the -D flag and in tests.
+func Tokenize(str string) []Token {
+ t := NewTokenizer("command line", strings.NewReader(str), nil)
+ var tokens []Token
+ for {
+ tok := t.Next()
+ if tok == scanner.EOF {
+ break
+ }
+ tokens = append(tokens, Make(tok, t.Text()))
+ }
+ return tokens
+}
--- /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.
+
+package lex
+
+import (
+ "bytes"
+ "strings"
+ "testing"
+ "text/scanner"
+)
+
+type lexTest struct {
+ name string
+ input string
+ output string
+}
+
+var lexTests = []lexTest{
+ {
+ "empty",
+ "",
+ "",
+ },
+ {
+ "simple",
+ "1 (a)",
+ "1.(.a.)",
+ },
+ {
+ "simple define",
+ lines(
+ "#define A 1234",
+ "A",
+ ),
+ "1234.\n",
+ },
+ {
+ "macro without arguments",
+ "#define A() 1234\n" + "A()\n",
+ "1234.\n",
+ },
+ {
+ "macro with arguments",
+ "#define A(x, y, z) x+z+y\n" + "A(1, 2, 3)\n",
+ "1.+.3.+.2.\n",
+ },
+ {
+ "argumented macro invoked without arguments",
+ lines(
+ "#define X() foo ",
+ "X()",
+ "X",
+ ),
+ "foo.\n.X.\n",
+ },
+ {
+ "multiline macro without arguments",
+ lines(
+ "#define A 1\\",
+ "\t2\\",
+ "\t3",
+ "before",
+ "A",
+ "after",
+ ),
+ "before.\n.1.\n.2.\n.3.\n.after.\n",
+ },
+ {
+ "multiline macro with arguments",
+ lines(
+ "#define A(a, b, c) a\\",
+ "\tb\\",
+ "\tc",
+ "before",
+ "A(1, 2, 3)",
+ "after",
+ ),
+ "before.\n.1.\n.2.\n.3.\n.after.\n",
+ },
+ {
+ "LOAD macro",
+ lines(
+ "#define LOAD(off, reg) \\",
+ "\tMOVBLZX (off*4)(R12), reg \\",
+ "\tADDB reg, DX",
+ "",
+ "LOAD(8, AX)",
+ ),
+ "\n.\n.MOVBLZX.(.8.*.4.).(.R12.).,.AX.\n.ADDB.AX.,.DX.\n",
+ },
+ {
+ "nested multiline macro",
+ lines(
+ "#define KEYROUND(xmm, load, off, r1, r2, index) \\",
+ "\tMOVBLZX (BP)(DX*4), R8 \\",
+ "\tload((off+1), r2) \\",
+ "\tMOVB R8, (off*4)(R12) \\",
+ "\tPINSRW $index, (BP)(R8*4), xmm",
+ "#define LOAD(off, reg) \\",
+ "\tMOVBLZX (off*4)(R12), reg \\",
+ "\tADDB reg, DX",
+ "KEYROUND(X0, LOAD, 8, AX, BX, 0)",
+ ),
+ "\n.MOVBLZX.(.BP.).(.DX.*.4.).,.R8.\n.\n.MOVBLZX.(.(.8.+.1.).*.4.).(.R12.).,.BX.\n.ADDB.BX.,.DX.\n.MOVB.R8.,.(.8.*.4.).(.R12.).\n.PINSRW.$.0.,.(.BP.).(.R8.*.4.).,.X0.\n",
+ },
+}
+
+func TestLex(t *testing.T) {
+ for _, test := range lexTests {
+ input := NewInput(test.name)
+ input.Push(NewTokenizer(test.name, strings.NewReader(test.input), nil))
+ result := drain(input)
+ if result != test.output {
+ t.Errorf("%s: got %q expected %q", test.name, result, test.output)
+ }
+ }
+}
+
+// lines joins the arguments together as complete lines.
+func lines(a ...string) string {
+ return strings.Join(a, "\n") + "\n"
+}
+
+// drain returns a single string representing the processed input tokens.
+func drain(input *Input) string {
+ var buf bytes.Buffer
+ for {
+ tok := input.Next()
+ if tok == scanner.EOF {
+ return buf.String()
+ }
+ if buf.Len() > 0 {
+ buf.WriteByte('.')
+ }
+ buf.WriteString(input.Text())
+ }
+}
--- /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.
+
+package lex
+
+import "text/scanner"
+
+// A Slice reads from a slice of Tokens.
+type Slice struct {
+ tokens []Token
+ fileName string
+ line int
+ pos int
+}
+
+func NewSlice(fileName string, line int, tokens []Token) *Slice {
+ return &Slice{
+ tokens: tokens,
+ fileName: fileName,
+ line: line,
+ pos: -1, // Next will advance to zero.
+ }
+}
+
+func (s *Slice) Next() ScanToken {
+ s.pos++
+ if s.pos >= len(s.tokens) {
+ return scanner.EOF
+ }
+ return s.tokens[s.pos].ScanToken
+}
+
+func (s *Slice) Text() string {
+ return s.tokens[s.pos].text
+}
+
+func (s *Slice) File() string {
+ return s.fileName
+}
+
+func (s *Slice) Line() int {
+ return s.line
+}
+
+func (s *Slice) SetPos(line int, file string) {
+ // Cannot happen because we only have slices of already-scanned
+ // text, but be prepared.
+ s.line = line
+ s.fileName = file
+}
+
+func (s *Slice) Close() {
+}
--- /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.
+
+package lex
+
+import "text/scanner"
+
+// A Stack is a stack of TokenReaders. As the top TokenReader hits EOF,
+// it resumes reading the next one down.
+type Stack struct {
+ tr []TokenReader
+}
+
+// Push adds tr to the top (end) of the input stack. (Popping happens automatically.)
+func (s *Stack) Push(tr TokenReader) {
+ s.tr = append(s.tr, tr)
+}
+
+func (s *Stack) Next() ScanToken {
+ tos := s.tr[len(s.tr)-1]
+ tok := tos.Next()
+ for tok == scanner.EOF && len(s.tr) > 1 {
+ tos.Close()
+ /*
+ // If it's not a macro (a Slice at this point), pop the line history stack and close the file descriptor.
+ if _, isMacro := tos.(*Slice); !isMacro {
+ // TODO: close file descriptor.
+ obj.Linklinehist(linkCtxt, histLine, "<pop>", 0)
+ }
+ */
+ // Pop the topmost item from the stack and resume with the next one down.
+ s.tr = s.tr[:len(s.tr)-1]
+ tok = s.Next()
+ }
+ return tok
+}
+
+func (s *Stack) Text() string {
+ return s.tr[len(s.tr)-1].Text()
+}
+
+func (s *Stack) File() string {
+ return s.tr[len(s.tr)-1].File()
+}
+
+func (s *Stack) Line() int {
+ return s.tr[len(s.tr)-1].Line()
+}
+
+func (s *Stack) SetPos(line int, file string) {
+ s.tr[len(s.tr)-1].SetPos(line, file)
+}
+
+func (s *Stack) Close() { // Unused.
+}
--- /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.
+
+package lex
+
+import (
+ "io"
+ "os"
+ "strings"
+ "text/scanner"
+ "unicode"
+
+ "cmd/internal/obj"
+)
+
+// A Tokenizer is a simple wrapping of text/scanner.Scanner, configured
+// for our purposes and made a TokenReader. It forms the lowest level,
+// turning text from readers into tokens.
+type Tokenizer struct {
+ tok ScanToken
+ s *scanner.Scanner
+ line int
+ fileName string
+ file *os.File // If non-nil, file descriptor to close.
+}
+
+func NewTokenizer(name string, r io.Reader, file *os.File) *Tokenizer {
+ var s scanner.Scanner
+ s.Init(r)
+ // Newline is like a semicolon; other space characters are fine.
+ s.Whitespace = 1<<'\t' | 1<<'\r' | 1<<' '
+ // Don't skip comments: we need to count newlines.
+ s.Mode = scanner.ScanChars |
+ scanner.ScanFloats |
+ scanner.ScanIdents |
+ scanner.ScanInts |
+ scanner.ScanStrings |
+ scanner.ScanComments
+ s.Position.Filename = name
+ s.IsIdentRune = isIdentRune
+ if file != nil {
+ obj.Linklinehist(linkCtxt, histLine, name, 0)
+ }
+ return &Tokenizer{
+ s: &s,
+ line: 1,
+ fileName: name,
+ file: file,
+ }
+}
+
+// We want center dot (·) and division slash (∕) to work as identifier characters.
+func isIdentRune(ch rune, i int) bool {
+ if unicode.IsLetter(ch) {
+ return true
+ }
+ switch ch {
+ case '_': // Underscore; traditional.
+ return true
+ case '\u00B7': // Represents the period in runtime.exit. U+00B7 '·' middle dot
+ return true
+ case '\u2215': // Represents the slash in runtime/debug.setGCPercent. U+2215 '∕' division slash
+ return true
+ }
+ // Digits are OK only after the first character.
+ return i > 0 && unicode.IsDigit(ch)
+}
+
+func (t *Tokenizer) Text() string {
+ switch t.tok {
+ case LSH:
+ return "<<"
+ case RSH:
+ return ">>"
+ case ARR:
+ return "->"
+ case ROT:
+ return "@>"
+ }
+ return t.s.TokenText()
+}
+
+func (t *Tokenizer) File() string {
+ return t.fileName
+}
+
+func (t *Tokenizer) Line() int {
+ return t.line
+}
+
+func (t *Tokenizer) SetPos(line int, file string) {
+ t.line = line
+ t.fileName = file
+}
+
+func (t *Tokenizer) Next() ScanToken {
+ s := t.s
+ for {
+ t.tok = ScanToken(s.Scan())
+ if t.tok != scanner.Comment {
+ break
+ }
+ length := strings.Count(s.TokenText(), "\n")
+ t.line += length
+ histLine += length
+ // TODO: If we ever have //go: comments in assembly, will need to keep them here.
+ // For now, just discard all comments.
+ }
+ switch t.tok {
+ case '\n':
+ if t.file != nil {
+ histLine++
+ }
+ t.line++
+ case '-':
+ if s.Peek() == '>' {
+ s.Next()
+ t.tok = ARR
+ return ARR
+ }
+ case '@':
+ if s.Peek() == '>' {
+ s.Next()
+ t.tok = ROT
+ return ROT
+ }
+ case '<':
+ if s.Peek() == '<' {
+ s.Next()
+ t.tok = LSH
+ return LSH
+ }
+ case '>':
+ if s.Peek() == '>' {
+ s.Next()
+ t.tok = RSH
+ return RSH
+ }
+ }
+ return t.tok
+}
+
+func (t *Tokenizer) Close() {
+ if t.file != nil {
+ t.file.Close()
+ // It's an open file, so pop the line history.
+ obj.Linklinehist(linkCtxt, histLine, "<pop>", 0)
+ }
+}
--- /dev/null
+// Copyright 2014 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 main
+
+import (
+ "flag"
+ "fmt"
+ "log"
+ "os"
+
+ "cmd/asm/internal/arch"
+ "cmd/asm/internal/asm"
+ "cmd/asm/internal/flags"
+ "cmd/asm/internal/lex"
+
+ "cmd/internal/obj"
+)
+
+func main() {
+ log.SetFlags(0)
+ log.SetPrefix("asm: ")
+
+ GOARCH := obj.Getgoarch()
+
+ architecture := arch.Set(GOARCH)
+ if architecture == nil {
+ log.Fatalf("asm: unrecognized architecture %s", GOARCH)
+ }
+
+ flags.Parse(architecture.Thechar)
+
+ // Create object file, write header.
+ fd, err := os.Create(*flags.OutputFile)
+ if err != nil {
+ log.Fatal(err)
+ }
+ ctxt := obj.Linknew(architecture.LinkArch)
+ if *flags.PrintOut {
+ ctxt.Debugasm = 1
+ }
+ ctxt.Bso = obj.Binitw(os.Stdout)
+ defer obj.Bflush(ctxt.Bso)
+ ctxt.Diag = log.Fatalf
+ output := obj.Binitw(fd)
+ fmt.Fprintf(output, "go object %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion())
+ fmt.Fprintf(output, "!\n")
+
+ lexer := lex.NewLexer(flag.Arg(0), ctxt)
+ parser := asm.NewParser(ctxt, architecture, lexer)
+ pList := obj.Linknewplist(ctxt)
+ var ok bool
+ pList.Firstpc, ok = parser.Parse()
+ if !ok {
+ log.Fatalf("asm: assembly of %s failed", flag.Arg(0))
+ os.Exit(1)
+ }
+ obj.Writeobjdirect(ctxt, output)
+ obj.Bflush(output)
+}
c = peekc;
if(c != IGN) {
peekc = IGN;
+ if(c == '\n')
+ lineno++;
return c;
}
c = GETC();
return l;
}
}
- peekc = c;
+ unget(c);
return l;
}
switch(c)
oldgoarch string
oldgochar string
slash string
+ exe string
defaultcc string
defaultcflags string
defaultldflags string
// not be in release branches.
var unreleased = []string{
"src/cmd/link",
+ "src/cmd/objwriter",
"src/debug/goobj",
"src/old",
}
ldargs = splitfields(defaultldflags)
}
- islib := strings.HasPrefix(dir, "lib") || dir == "cmd/gc"
- ispkg := !islib && !strings.HasPrefix(dir, "cmd/")
- isgo := ispkg || dir == "cmd/go" || dir == "cmd/cgo"
+ isgo := true
+ ispkg := !strings.HasPrefix(dir, "cmd/") || strings.HasPrefix(dir, "cmd/internal/")
+ islib := false
- exe := ""
- if gohostos == "windows" {
- exe = ".exe"
+ // Legacy C exceptions.
+ switch dir {
+ case "lib9", "libbio", "liblink", "cmd/gc":
+ islib = true
+ isgo = false
+ case "cmd/5a", "cmd/5g", "cmd/5l",
+ "cmd/6a", "cmd/6g", "cmd/6l",
+ "cmd/8a", "cmd/8g", "cmd/8l",
+ "cmd/9a", "cmd/9g", "cmd/9l":
+ isgo = false
}
// Start final link command line.
compile = append(compile,
"-D", fmt.Sprintf("GOOS=%q", goos),
"-D", fmt.Sprintf("GOARCH=%q", goarch),
+ "-D", fmt.Sprintf("GOHOSTOS=%q", gohostos),
+ "-D", fmt.Sprintf("GOHOSTARCH=%q", gohostarch),
"-D", fmt.Sprintf("GOROOT=%q", goroot_final),
"-D", fmt.Sprintf("GOVERSION=%q", goversion),
"-D", fmt.Sprintf("GOARM=%q", goarm),
}
// buildorder records the order of builds for the 'go bootstrap' command.
+// The Go packages and commands must be in dependency order,
+// maintained by hand, but the order doesn't change often.
var buildorder = []string{
+ // Legacy C programs.
"lib9",
"libbio",
"liblink",
"cmd/%sa",
"cmd/%sg",
- // The dependency order here was copied from a buildscript
- // back when there were build scripts. Will have to
- // be maintained by hand, but shouldn't change very
- // often.
+ // Go libraries and programs for bootstrap.
"runtime",
"errors",
"sync/atomic",
"reflect",
"fmt",
"encoding",
+ "encoding/binary",
"encoding/json",
"flag",
"path/filepath",
"text/template",
"go/doc",
"go/build",
+ "cmd/internal/obj",
+ "cmd/internal/obj/arm",
+ "cmd/internal/obj/i386",
+ "cmd/internal/obj/ppc64",
+ "cmd/internal/obj/x86",
+ "cmd/objwriter",
"cmd/go",
}
setup()
+ bootstrapBuildTools()
+
// For the main bootstrap, building for host os/arch.
oldgoos = goos
oldgoarch = goarch
os.Setenv("GOARCH", goarch)
os.Setenv("GOOS", goos)
+ // TODO(rsc): Enable when appropriate.
+ // This step is only needed if we believe that the Go compiler built from Go 1.4
+ // will produce different object files than the Go compiler built from itself.
+ // In the absence of bugs, that should not happen.
+ // And if there are bugs, they're more likely in the current development tree
+ // than in a standard release like Go 1.4, so don't do this rebuild by default.
+ if false {
+ xprintf("##### Building Go toolchain using itself.\n")
+ for _, pattern := range buildorder {
+ if pattern == "cmd/go" {
+ break
+ }
+ dir := pattern
+ if strings.Contains(pattern, "%s") {
+ dir = fmt.Sprintf(pattern, gohostchar)
+ }
+ install(dir)
+ if oldgochar != gohostchar && strings.Contains(pattern, "%s") {
+ install(fmt.Sprintf(pattern, oldgochar))
+ }
+ }
+ xprintf("\n")
+ }
+
+ xprintf("##### Building compilers and go_bootstrap for host, %s/%s.\n", gohostos, gohostarch)
for _, pattern := range buildorder {
dir := pattern
if strings.Contains(pattern, "%s") {
writefile(out, file, 0)
}
+
+// mkzbootstrap writes cmd/internal/obj/zbootstrap.go:
+//
+// package obj
+//
+// const defaultGOROOT = <goroot>
+// const defaultGOARM = <goarm>
+// const defaultGOOS = <goos>
+// const defaultGOARCH = <goarch>
+// const version = <version>
+// const goexperiment = <goexperiment>
+//
+func mkzbootstrap(file string) {
+ out := fmt.Sprintf(
+ "// auto generated by go tool dist\n"+
+ "\n"+
+ "package obj\n"+
+ "\n"+
+ "const defaultGOROOT = `%s`\n"+
+ "const defaultGOARM = `%s`\n"+
+ "const defaultGOOS = `%s`\n"+
+ "const defaultGOARCH = `%s`\n"+
+ "const version = `%s`\n"+
+ "const goexperiment = `%s`\n",
+ goroot_final, goarm, gohostos, gohostarch, goversion, os.Getenv("GOEXPERIMENT"))
+
+ writefile(out, file, 0)
+}
--- /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.
+
+// Build toolchain using Go 1.4.
+//
+// The general strategy is to copy the source files we need into
+// a new GOPATH workspace, adjust import paths appropriately,
+// invoke the Go 1.4 go command to build those sources,
+// and then copy the binaries back.
+
+package main
+
+import (
+ "os"
+ "strings"
+)
+
+// bootstrapDirs is a list of directories holding code that must be
+// compiled with a Go 1.4 toolchain to produce the bootstrapTargets.
+// All directories in this list are relative to and must be below $GOROOT/src/cmd.
+// The list is assumed to have two kinds of entries: names without slashes,
+// which are commands, and entries beginning with internal/, which are
+// packages supporting the commands.
+var bootstrapDirs = []string{
+ "internal/asm",
+ "internal/obj",
+ "internal/obj/arm",
+ "internal/obj/i386",
+ "internal/obj/ppc64",
+ "internal/obj/x86",
+ "new5a",
+ "new6a",
+ "new8a",
+ "new9a",
+ "objwriter",
+}
+
+func bootstrapBuildTools() {
+ goroot_bootstrap := os.Getenv("GOROOT_BOOTSTRAP")
+ if goroot_bootstrap == "" {
+ goroot_bootstrap = pathf("%s/go1.4", os.Getenv("HOME"))
+ }
+ xprintf("##### Building Go toolchain using %s.\n", goroot_bootstrap)
+
+ mkzbootstrap(pathf("%s/src/cmd/internal/obj/zbootstrap.go", goroot))
+
+ // Use $GOROOT/pkg/bootstrap as the bootstrap workspace root.
+ // We use a subdirectory of $GOROOT/pkg because that's the
+ // space within $GOROOT where we store all generated objects.
+ // We could use a temporary directory outside $GOROOT instead,
+ // but it is easier to debug on failure if the files are in a known location.
+ workspace := pathf("%s/pkg/bootstrap", goroot)
+ xremoveall(workspace)
+ base := pathf("%s/src/bootstrap", workspace)
+ xmkdirall(base)
+
+ // Copy source code into $GOROOT/pkg/bootstrap and rewrite import paths.
+ for _, dir := range bootstrapDirs {
+ src := pathf("%s/src/cmd/%s", goroot, dir)
+ dst := pathf("%s/%s", base, dir)
+ xmkdirall(dst)
+ for _, name := range xreaddirfiles(src) {
+ srcFile := pathf("%s/%s", src, name)
+ text := readfile(srcFile)
+ text = bootstrapFixImports(text, srcFile)
+ writefile(text, pathf("%s/%s", dst, name), 0)
+ }
+ }
+
+ // Set up environment for invoking Go 1.4 go command.
+ // GOROOT points at Go 1.4 GOROOT,
+ // GOPATH points at our bootstrap workspace,
+ // GOBIN is empty, so that binaries are installed to GOPATH/bin,
+ // and GOOS, GOHOSTOS, GOARCH, and GOHOSTOS are empty,
+ // so that Go 1.4 builds whatever kind of binary it knows how to build.
+ // Restore GOROOT, GOPATH, and GOBIN when done.
+ // Don't bother with GOOS, GOHOSTOS, GOARCH, and GOHOSTARCH,
+ // because setup will take care of those when bootstrapBuildTools returns.
+
+ defer os.Setenv("GOROOT", os.Getenv("GOROOT"))
+ os.Setenv("GOROOT", goroot_bootstrap)
+
+ defer os.Setenv("GOPATH", os.Getenv("GOPATH"))
+ os.Setenv("GOPATH", workspace)
+
+ defer os.Setenv("GOBIN", os.Getenv("GOBIN"))
+ os.Setenv("GOBIN", "")
+
+ os.Setenv("GOOS", "")
+ os.Setenv("GOHOSTOS", "")
+ os.Setenv("GOARCH", "")
+ os.Setenv("GOHOSTARCH", "")
+
+ // Run Go 1.4 to build binaries.
+ run(workspace, ShowOutput|CheckExit, pathf("%s/bin/go", goroot_bootstrap), "install", "-v", "bootstrap/...")
+
+ // Copy binaries into tool binary directory.
+ for _, name := range bootstrapDirs {
+ if !strings.Contains(name, "/") {
+ copyfile(pathf("%s/%s%s", tooldir, name, exe), pathf("%s/bin/%s%s", workspace, name, exe), 1)
+ }
+ }
+
+ xprintf("\n")
+}
+
+func bootstrapFixImports(text, srcFile string) string {
+ lines := strings.SplitAfter(text, "\n")
+ inBlock := false
+ for i, line := range lines {
+ if strings.HasPrefix(line, "import (") {
+ inBlock = true
+ continue
+ }
+ if inBlock && strings.HasPrefix(line, ")") {
+ inBlock = false
+ continue
+ }
+ if strings.HasPrefix(line, `import "`) || strings.HasPrefix(line, `import . "`) ||
+ inBlock && (strings.HasPrefix(line, "\t\"") || strings.HasPrefix(line, "\t. \"")) {
+ lines[i] = strings.Replace(line, `"cmd/internal/`, `"bootstrap/internal/`, -1)
+ }
+ }
+
+ lines[0] = "// Do not edit. Bootstrap copy of " + srcFile + "\n\n" + lines[0]
+
+ return strings.Join(lines, "")
+}
xcmd := exec.Command(cmd[0], cmd[1:]...)
xcmd.Dir = dir
+ var data []byte
var err error
- data, err := xcmd.CombinedOutput()
+
+ // If we want to show command output and this is not
+ // a background command, assume it's the only thing
+ // running, so we can just let it write directly stdout/stderr
+ // as it runs without fear of mixing the output with some
+ // other command's output. Not buffering lets the output
+ // appear as it is printed instead of once the command exits.
+ // This is most important for the invocation of 'go1.4 build -v bootstrap/...'.
+ if mode&(Background|ShowOutput) == ShowOutput {
+ xcmd.Stdout = os.Stdout
+ xcmd.Stderr = os.Stderr
+ err = xcmd.Run()
+ } else {
+ data, err = xcmd.CombinedOutput()
+ }
if err != nil && mode&CheckExit != 0 {
outputLock.Lock()
if len(data) > 0 {
os.RemoveAll(p)
}
-// xreaddir replaces dst with a list of the names of the files in dir.
+// xreaddir replaces dst with a list of the names of the files and subdirectories in dir.
// The names are relative to dir; they are not full paths.
func xreaddir(dir string) []string {
f, err := os.Open(dir)
return names
}
+// xreaddir replaces dst with a list of the names of the files in dir.
+// The names are relative to dir; they are not full paths.
+func xreaddirfiles(dir string) []string {
+ f, err := os.Open(dir)
+ if err != nil {
+ fatal("%v", err)
+ }
+ defer f.Close()
+ infos, err := f.Readdir(-1)
+ if err != nil {
+ fatal("reading %s: %v", dir, err)
+ }
+ var names []string
+ for _, fi := range infos {
+ if !fi.IsDir() {
+ names = append(names, fi.Name())
+ }
+ }
+ return names
+}
+
// xworkdir creates a new temporary directory to hold object files
// and returns the name of that directory.
func xworkdir() string {
if gohostarch == "" {
fatal("$objtype is unset")
}
+ case "windows":
+ exe = ".exe"
}
sysinit()
return ofile, output, err
}
+// verifyAsm specifies whether to check the assemblers written in Go
+// against the assemblers written in C. If set, asm will run both (say) 6a and new6a
+// and fail if the two produce different output files.
+const verifyAsm = false
+
func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
// Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files.
inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch))
sfile = mkAbs(p.Dir, sfile)
- return b.run(p.Dir, p.ImportPath, nil, stringList(buildToolExec, tool(archChar+"a"), "-trimpath", b.work, "-I", obj, "-I", inc, "-o", ofile, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, sfile))
+ args := []interface{}{buildToolExec, tool(archChar + "a"), "-o", ofile, "-trimpath", b.work, "-I", obj, "-I", inc, "-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch, sfile}
+ if err := b.run(p.Dir, p.ImportPath, nil, args...); err != nil {
+ return err
+ }
+ if verifyAsm {
+ newArgs := make([]interface{}, len(args))
+ copy(newArgs, args)
+ newArgs[0] = tool("new" + archChar + "a")
+ newArgs[2] = ofile + ".new" // x.6 becomes x.6.new
+ if err := b.run(p.Dir, p.ImportPath, nil, newArgs...); err != nil {
+ return err
+ }
+ data1, err := ioutil.ReadFile(ofile)
+ if err != nil {
+ return err
+ }
+ data2, err := ioutil.ReadFile(ofile + ".new")
+ if err != nil {
+ return err
+ }
+ if !bytes.Equal(data1, data2) {
+ return fmt.Errorf("%sa and n%sa produced different output files:\n%s\n%s", archChar, archChar, strings.Join(stringList(args...), " "), strings.Join(stringList(newArgs...), " "))
+ }
+ }
+ return nil
}
func (gcToolchain) pkgpath(basedir string, p *Package) string {
case string:
x = append(x, arg)
default:
- panic("stringList: invalid argument")
+ panic("stringList: invalid argument of type " + fmt.Sprintf("%T", arg))
}
}
return x
"cmd/addr2line": toTool,
"cmd/api": toTool,
"cmd/cgo": toTool,
+ "cmd/dist": toTool,
"cmd/fix": toTool,
"cmd/link": toTool,
+ "cmd/new5a": toTool,
+ "cmd/new6a": toTool,
+ "cmd/new8a": toTool,
+ "cmd/new9a": toTool,
"cmd/nm": toTool,
"cmd/objdump": toTool,
+ "cmd/objwriter": toTool,
"cmd/pack": toTool,
"cmd/pprof": toTool,
"cmd/yacc": toTool,
--- /dev/null
+// Inferno utils/6a/a.h and lex.c.
+// http://code.google.com/p/inferno-os/source/browse/utils/6a/a.h
+// http://code.google.com/p/inferno-os/source/browse/utils/6a/lex.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+// Package asm holds code shared among the assemblers.
+package asm
+
+import (
+ "flag"
+ "fmt"
+ "log"
+ "os"
+ "path/filepath"
+ "strconv"
+ "strings"
+
+ "cmd/internal/obj"
+)
+
+// Initialized by client.
+var (
+ LSCONST int
+ LCONST int
+ LFCONST int
+ LNAME int
+ LVAR int
+ LLAB int
+
+ Thechar rune
+ Thestring string
+ Thelinkarch *obj.LinkArch
+
+ Arches map[string]*obj.LinkArch
+
+ Cclean func()
+ Yyparse func()
+ Syminit func(*Sym)
+
+ Lexinit []Lextab
+)
+
+type Lextab struct {
+ Name string
+ Type int
+ Value int64
+}
+
+const (
+ MAXALIGN = 7
+ FPCHIP = 1
+ NSYMB = 500
+ BUFSIZ = 8192
+ HISTSZ = 20
+ EOF = -1
+ IGN = -2
+ NHASH = 503
+ STRINGSZ = 200
+ NMACRO = 10
+)
+
+const (
+ CLAST = iota
+ CMACARG
+ CMACRO
+ CPREPROC
+)
+
+type Macro struct {
+ Text string
+ Narg int
+ Dots bool
+}
+
+type Sym struct {
+ Link *Sym
+ Ref *Ref
+ Macro *Macro
+ Value int64
+ Type int
+ Name string
+ Labelname string
+ Sym int8
+}
+
+type Ref struct {
+ Class int
+}
+
+type Io struct {
+ Link *Io
+ P []byte
+ F *os.File
+ B [1024]byte
+}
+
+var fi struct {
+ P []byte
+}
+
+var (
+ debug [256]int
+ hash = map[string]*Sym{}
+ Dlist []string
+ newflag int
+ hunk string
+ include []string
+ iofree *Io
+ ionext *Io
+ iostack *Io
+ Lineno int32
+ nerrors int
+ nhunk int32
+ ninclude int
+ nsymb int32
+ nullgen obj.Addr
+ outfile string
+ Pass int
+ PC int32
+ peekc int = IGN
+ sym int
+ symb string
+ thunk int32
+ obuf obj.Biobuf
+ Ctxt *obj.Link
+ bstdout obj.Biobuf
+)
+
+func dodef(p string) {
+ Dlist = append(Dlist, p)
+}
+
+func usage() {
+ fmt.Printf("usage: %ca [options] file.c...\n", Thechar)
+ flag.PrintDefaults()
+ errorexit()
+}
+
+func Main() {
+ var p string
+
+ // Allow GOARCH=Thestring or GOARCH=Thestringsuffix,
+ // but not other values.
+ p = obj.Getgoarch()
+
+ if !strings.HasPrefix(p, Thestring) {
+ log.Fatalf("cannot use %cc with GOARCH=%s", Thechar, p)
+ }
+ if p != Thestring {
+ Thelinkarch = Arches[p]
+ if Thelinkarch == nil {
+ log.Fatalf("unknown arch %s", p)
+ }
+ }
+
+ Ctxt = obj.Linknew(Thelinkarch)
+ Ctxt.Diag = Yyerror
+ Ctxt.Bso = &bstdout
+ Ctxt.Enforce_data_order = 1
+ bstdout = *obj.Binitw(os.Stdout)
+
+ debug = [256]int{}
+ cinit()
+ outfile = ""
+ setinclude(".")
+
+ flag.Var(flagFn(dodef), "D", "name[=value]: add #define")
+ flag.Var(flagFn(setinclude), "I", "dir: add dir to include path")
+ flag.Var((*count)(&debug['S']), "S", "print assembly and machine code")
+ flag.Var((*count)(&debug['m']), "m", "debug preprocessor macros")
+ flag.StringVar(&outfile, "o", "", "file: set output file")
+ flag.StringVar(&Ctxt.Trimpath, "trimpath", "", "prefix: remove prefix from recorded source file paths")
+
+ flag.Parse()
+
+ Ctxt.Debugasm = int32(debug['S'])
+
+ if flag.NArg() < 1 {
+ usage()
+ }
+ if flag.NArg() > 1 {
+ fmt.Printf("can't assemble multiple files\n")
+ errorexit()
+ }
+
+ if assemble(flag.Arg(0)) != 0 {
+ errorexit()
+ }
+ obj.Bflush(&bstdout)
+ if nerrors > 0 {
+ errorexit()
+ }
+}
+
+func assemble(file string) int {
+ var i int
+
+ if outfile == "" {
+ outfile = strings.TrimSuffix(filepath.Base(file), ".s") + "." + string(Thechar)
+ }
+
+ of, err := os.Create(outfile)
+ if err != nil {
+ Yyerror("%ca: cannot create %s", Thechar, outfile)
+ errorexit()
+ }
+
+ obuf = *obj.Binitw(of)
+ fmt.Fprintf(&obuf, "go object %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion())
+ fmt.Fprintf(&obuf, "!\n")
+
+ for Pass = 1; Pass <= 2; Pass++ {
+ pinit(file)
+ for i = 0; i < len(Dlist); i++ {
+ dodefine(Dlist[i])
+ }
+ Yyparse()
+ Cclean()
+ if nerrors != 0 {
+ return nerrors
+ }
+ }
+
+ obj.Writeobjdirect(Ctxt, &obuf)
+ obj.Bflush(&obuf)
+ return 0
+}
+
+func cinit() {
+ for i := 0; i < len(Lexinit); i++ {
+ s := Lookup(Lexinit[i].Name)
+ if s.Type != LNAME {
+ Yyerror("double initialization %s", Lexinit[i].Name)
+ }
+ s.Type = Lexinit[i].Type
+ s.Value = Lexinit[i].Value
+ }
+}
+
+func syminit(s *Sym) {
+ s.Type = LNAME
+ s.Value = 0
+}
+
+type flagFn func(string)
+
+func (flagFn) String() string {
+ return "<arg>"
+}
+
+func (f flagFn) Set(s string) error {
+ f(s)
+ return nil
+}
+
+type yyImpl struct{}
+
+// count is a flag.Value that is like a flag.Bool and a flag.Int.
+// If used as -name, it increments the count, but -name=x sets the count.
+// Used for verbose flag -v.
+type count int
+
+func (c *count) String() string {
+ return fmt.Sprint(int(*c))
+}
+
+func (c *count) Set(s string) error {
+ switch s {
+ case "true":
+ *c++
+ case "false":
+ *c = 0
+ default:
+ n, err := strconv.Atoi(s)
+ if err != nil {
+ return fmt.Errorf("invalid count %q", s)
+ }
+ *c = count(n)
+ }
+ return nil
+}
+
+func (c *count) IsBoolFlag() bool {
+ return true
+}
--- /dev/null
+// Inferno utils/cc/lexbody
+// http://code.Google.Com/p/inferno-os/source/browse/utils/cc/lexbody
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.Net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.Vitanuova.Com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.Net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package asm
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+ "strconv"
+ "strings"
+ "unicode/utf8"
+
+ "cmd/internal/obj"
+)
+
+/*
+ * common code for all the assemblers
+ */
+func pragpack() {
+
+ for getnsc() != '\n' {
+
+ }
+}
+
+func pragvararg() {
+ for getnsc() != '\n' {
+
+ }
+}
+
+func pragcgo(name string) {
+ for getnsc() != '\n' {
+
+ }
+}
+
+func pragfpround() {
+ for getnsc() != '\n' {
+
+ }
+}
+
+func pragtextflag() {
+ for getnsc() != '\n' {
+
+ }
+}
+
+func pragdataflag() {
+ for getnsc() != '\n' {
+
+ }
+}
+
+func pragprofile() {
+ for getnsc() != '\n' {
+
+ }
+}
+
+func pragincomplete() {
+ for getnsc() != '\n' {
+
+ }
+}
+
+func setinclude(p string) {
+ var i int
+
+ if p == "" {
+ return
+ }
+ for i = 1; i < len(include); i++ {
+ if p == include[i] {
+ return
+ }
+ }
+
+ include = append(include, p)
+}
+
+func errorexit() {
+ obj.Bflush(&bstdout)
+ if outfile != "" {
+ os.Remove(outfile)
+ }
+ os.Exit(2)
+}
+
+func pushio() {
+ var i *Io
+
+ i = iostack
+ if i == nil {
+ Yyerror("botch in pushio")
+ errorexit()
+ }
+
+ i.P = fi.P
+}
+
+func newio() {
+ var i *Io
+ var pushdepth int = 0
+
+ i = iofree
+ if i == nil {
+ pushdepth++
+ if pushdepth > 1000 {
+ Yyerror("macro/io expansion too deep")
+ errorexit()
+ }
+ i = new(Io)
+ } else {
+ iofree = i.Link
+ }
+ i.F = nil
+ i.P = nil
+ ionext = i
+}
+
+func newfile(s string, f *os.File) {
+ var i *Io
+
+ i = ionext
+ i.Link = iostack
+ iostack = i
+ i.F = f
+ if f == nil {
+ var err error
+ i.F, err = os.Open(s)
+ if err != nil {
+ Yyerror("%ca: %v", Thechar, err)
+ errorexit()
+ }
+ }
+
+ fi.P = nil
+ obj.Linklinehist(Ctxt, int(Lineno), s, 0)
+}
+
+var thetext *obj.LSym
+
+func Settext(s *obj.LSym) {
+ thetext = s
+}
+
+func LabelLookup(s *Sym) *Sym {
+ var p string
+ var lab *Sym
+
+ if thetext == nil {
+ s.Labelname = s.Name
+ return s
+ }
+
+ p = string(fmt.Sprintf("%s.%s", thetext.Name, s.Name))
+ lab = Lookup(p)
+
+ lab.Labelname = s.Name
+ return lab
+}
+
+func Lookup(symb string) *Sym {
+ // turn leading · into ""·
+ if strings.HasPrefix(symb, "·") {
+ symb = `""` + symb
+ }
+
+ // turn · (U+00B7) into .
+ // turn ∕ (U+2215) into /
+ symb = strings.Replace(symb, "·", ".", -1)
+ symb = strings.Replace(symb, "∕", "/", -1)
+
+ s := hash[symb]
+ if s != nil {
+ return s
+ }
+
+ s = new(Sym)
+ s.Name = symb
+ syminit(s)
+ hash[symb] = s
+ return s
+}
+
+func isalnum(c int) bool {
+ return isalpha(c) || isdigit(c)
+}
+
+func isalpha(c int) bool {
+ return 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z'
+}
+
+func isspace(c int) bool {
+ return c == ' ' || c == '\t' || c == '\r' || c == '\n'
+}
+
+func ISALPHA(c int) bool {
+ if isalpha(c) {
+ return true
+ }
+ if c >= utf8.RuneSelf {
+ return true
+ }
+ return false
+}
+
+var yybuf bytes.Buffer
+
+func (yyImpl) Error(s string) {
+ Yyerror("%s", s)
+}
+
+type Yylval struct {
+ Sym *Sym
+ Lval int64
+ Sval string
+ Dval float64
+}
+
+func Yylex(yylval *Yylval) int {
+ var c int
+ var c1 int
+ var s *Sym
+
+ c = peekc
+ if c != IGN {
+ peekc = IGN
+ goto l1
+ }
+
+l0:
+ c = GETC()
+
+l1:
+ if c == EOF {
+ peekc = EOF
+ return -1
+ }
+
+ if isspace(c) {
+ if c == '\n' {
+ Lineno++
+ return ';'
+ }
+
+ goto l0
+ }
+
+ if ISALPHA(c) {
+ yybuf.Reset()
+ goto aloop
+ }
+ if isdigit(c) {
+ goto tnum
+ }
+ switch c {
+ case '\n':
+ Lineno++
+ return ';'
+
+ case '#':
+ domacro()
+ goto l0
+
+ case '.':
+ c = GETC()
+ if ISALPHA(c) {
+ yybuf.Reset()
+ yybuf.WriteByte('.')
+ goto aloop
+ }
+
+ if isdigit(c) {
+ yybuf.Reset()
+ yybuf.WriteByte('.')
+ goto casedot
+ }
+
+ peekc = c
+ return '.'
+
+ case '_',
+ '@':
+ yybuf.Reset()
+ goto aloop
+
+ case '"':
+ var buf bytes.Buffer
+ c1 = 0
+ for {
+ c = escchar('"')
+ if c == EOF {
+ break
+ }
+ buf.WriteByte(byte(c))
+ }
+ yylval.Sval = buf.String()
+ return LSCONST
+
+ case '\'':
+ c = escchar('\'')
+ if c == EOF {
+ c = '\''
+ }
+ if escchar('\'') != EOF {
+ Yyerror("missing '")
+ }
+ yylval.Lval = int64(c)
+ return LCONST
+
+ case '/':
+ c1 = GETC()
+ if c1 == '/' {
+ for {
+ c = GETC()
+ if c == '\n' {
+ goto l1
+ }
+ if c == EOF {
+ Yyerror("eof in comment")
+ errorexit()
+ }
+ }
+ }
+
+ if c1 == '*' {
+ for {
+ c = GETC()
+ for c == '*' {
+ c = GETC()
+ if c == '/' {
+ goto l0
+ }
+ }
+
+ if c == EOF {
+ Yyerror("eof in comment")
+ errorexit()
+ }
+
+ if c == '\n' {
+ Lineno++
+ }
+ }
+ }
+
+ default:
+ return int(c)
+ }
+
+ peekc = c1
+ return int(c)
+
+casedot:
+ for {
+ yybuf.WriteByte(byte(c))
+ c = GETC()
+ if !(isdigit(c)) {
+ break
+ }
+ }
+
+ if c == 'e' || c == 'E' {
+ goto casee
+ }
+ goto caseout
+
+casee:
+ yybuf.WriteByte('e')
+ c = GETC()
+ if c == '+' || c == '-' {
+ yybuf.WriteByte(byte(c))
+ c = GETC()
+ }
+
+ for isdigit(c) {
+ yybuf.WriteByte(byte(c))
+ c = GETC()
+ }
+
+caseout:
+ peekc = c
+ if FPCHIP != 0 /*TypeKind(100016)*/ {
+ last = yybuf.String()
+ yylval.Dval = atof(last)
+ return LFCONST
+ }
+
+ Yyerror("assembler cannot interpret fp constants")
+ yylval.Lval = 1
+ return LCONST
+
+aloop:
+ yybuf.WriteByte(byte(c))
+ c = GETC()
+ if ISALPHA(c) || isdigit(c) || c == '_' || c == '$' {
+ goto aloop
+ }
+ peekc = c
+ last = yybuf.String()
+ s = Lookup(last)
+ if s.Macro != nil {
+ newio()
+ ionext.P = macexpand(s)
+ pushio()
+ ionext.Link = iostack
+ iostack = ionext
+ fi.P = ionext.P
+ if peekc != IGN {
+ fi.P = append(fi.P, byte(peekc))
+ peekc = IGN
+ }
+
+ goto l0
+ }
+
+ if s.Type == 0 {
+ s.Type = LNAME
+ }
+ if s.Type == LNAME || s.Type == LVAR || s.Type == LLAB {
+ yylval.Sym = s
+ yylval.Sval = last
+ return int(s.Type)
+ }
+
+ yylval.Lval = s.Value
+ yylval.Sval = last
+ return int(s.Type)
+
+tnum:
+ yybuf.Reset()
+ if c != '0' {
+ goto dc
+ }
+ yybuf.WriteByte(byte(c))
+ c = GETC()
+ c1 = 3
+ if c == 'x' || c == 'X' {
+ c1 = 4
+ c = GETC()
+ } else if c < '0' || c > '7' {
+ goto dc
+ }
+ yylval.Lval = 0
+ for {
+ if c >= '0' && c <= '9' {
+ if c > '7' && c1 == 3 {
+ break
+ }
+ yylval.Lval = int64(uint64(yylval.Lval) << uint(c1))
+ yylval.Lval += int64(c) - '0'
+ c = GETC()
+ continue
+ }
+
+ if c1 == 3 {
+ break
+ }
+ if c >= 'A' && c <= 'F' {
+ c += 'a' - 'A'
+ }
+ if c >= 'a' && c <= 'f' {
+ yylval.Lval = int64(uint64(yylval.Lval) << uint(c1))
+ yylval.Lval += int64(c) - 'a' + 10
+ c = GETC()
+ continue
+ }
+
+ break
+ }
+
+ goto ncu
+
+dc:
+ for {
+ if !(isdigit(c)) {
+ break
+ }
+ yybuf.WriteByte(byte(c))
+ c = GETC()
+ }
+
+ if c == '.' {
+ goto casedot
+ }
+ if c == 'e' || c == 'E' {
+ goto casee
+ }
+ last = yybuf.String()
+ yylval.Lval = strtoll(last, nil, 10)
+
+ncu:
+ for c == 'U' || c == 'u' || c == 'l' || c == 'L' {
+ c = GETC()
+ }
+ peekc = c
+ return LCONST
+}
+
+func getc() int {
+ var c int
+
+ c = peekc
+ if c != IGN {
+ peekc = IGN
+ if c == '\n' {
+ Lineno++
+ }
+ return c
+ }
+
+ c = GETC()
+ if c == '\n' {
+ Lineno++
+ }
+ if c == EOF {
+ Yyerror("End of file")
+ errorexit()
+ }
+
+ return c
+}
+
+func getnsc() int {
+ var c int
+
+ for {
+ c = getc()
+ if !isspace(c) || c == '\n' {
+ return c
+ }
+ }
+}
+
+func unget(c int) {
+ peekc = c
+ if c == '\n' {
+ Lineno--
+ }
+}
+
+func escchar(e int) int {
+ var c int
+ var l int
+
+loop:
+ c = getc()
+ if c == '\n' {
+ Yyerror("newline in string")
+ return EOF
+ }
+
+ if c != '\\' {
+ if c == e {
+ return EOF
+ }
+ return c
+ }
+
+ c = getc()
+ if c >= '0' && c <= '7' {
+ l = c - '0'
+ c = getc()
+ if c >= '0' && c <= '7' {
+ l = l*8 + c - '0'
+ c = getc()
+ if c >= '0' && c <= '7' {
+ l = l*8 + c - '0'
+ return l
+ }
+ }
+
+ peekc = c
+ unget(c)
+ return l
+ }
+
+ switch c {
+ case '\n':
+ goto loop
+ case 'n':
+ return '\n'
+ case 't':
+ return '\t'
+ case 'b':
+ return '\b'
+ case 'r':
+ return '\r'
+ case 'f':
+ return '\f'
+ case 'a':
+ return 0x07
+ case 'v':
+ return 0x0b
+ case 'z':
+ return 0x00
+ }
+
+ return c
+}
+
+func pinit(f string) {
+ Lineno = 1
+ newio()
+ newfile(f, nil)
+ PC = 0
+ peekc = IGN
+ sym = 1
+ for _, s := range hash {
+ s.Macro = nil
+ }
+}
+
+func filbuf() int {
+ var i *Io
+ var n int
+
+loop:
+ i = iostack
+ if i == nil {
+ return EOF
+ }
+ if i.F == nil {
+ goto pop
+ }
+ n, _ = i.F.Read(i.B[:])
+ if n == 0 {
+ i.F.Close()
+ obj.Linklinehist(Ctxt, int(Lineno), "<pop>", 0)
+ goto pop
+ }
+ fi.P = i.B[1:n]
+ return int(i.B[0]) & 0xff
+
+pop:
+ iostack = i.Link
+ i.Link = iofree
+ iofree = i
+ i = iostack
+ if i == nil {
+ return EOF
+ }
+ fi.P = i.P
+ if len(fi.P) == 0 {
+ goto loop
+ }
+ tmp8 := fi.P
+ fi.P = fi.P[1:]
+ return int(tmp8[0]) & 0xff
+}
+
+var last string
+
+func Yyerror(a string, args ...interface{}) {
+ /*
+ * hack to intercept message from yaccpar
+ */
+ if a == "syntax error" || len(args) == 1 && a == "%s" && args[0] == "syntax error" {
+ Yyerror("syntax error, last name: %s", last)
+ return
+ }
+
+ prfile(Lineno)
+ fmt.Printf("%s\n", fmt.Sprintf(a, args...))
+ nerrors++
+ if nerrors > 10 {
+ fmt.Printf("too many errors\n")
+ errorexit()
+ }
+}
+
+func prfile(l int32) {
+ obj.Linkprfile(Ctxt, int(l))
+}
+
+func GETC() int {
+ var c int
+ if len(fi.P) == 0 {
+ return filbuf()
+ }
+ c = int(fi.P[0])
+ fi.P = fi.P[1:]
+ return c
+}
+
+func isdigit(c int) bool {
+ return '0' <= c && c <= '9'
+}
+
+func strtoll(s string, p *byte, base int) int64 {
+ if p != nil {
+ panic("strtoll")
+ }
+ n, err := strconv.ParseInt(s, base, 64)
+ if err != nil {
+ return 0
+ }
+ return n
+}
+
+func atof(s string) float64 {
+ f, err := strconv.ParseFloat(s, 64)
+ if err != nil {
+ return 0
+ }
+ return f
+}
--- /dev/null
+// Inferno utils/cc/macbody
+// http://code.Google.Com/p/inferno-os/source/browse/utils/cc/macbody
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.Net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.Vitanuova.Com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.Net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package asm
+
+import (
+ "bytes"
+ "cmd/internal/obj"
+ "fmt"
+ "os"
+ "strings"
+)
+
+const (
+ VARMAC = 0x80
+)
+
+func getnsn() int32 {
+ var n int32
+ var c int
+
+ c = getnsc()
+ if c < '0' || c > '9' {
+ return -1
+ }
+ n = 0
+ for c >= '0' && c <= '9' {
+ n = n*10 + int32(c) - '0'
+ c = getc()
+ }
+
+ unget(c)
+ return n
+}
+
+func getsym() *Sym {
+ var c int
+
+ c = getnsc()
+ if !isalpha(c) && c != '_' && c < 0x80 {
+ unget(c)
+ return nil
+ }
+
+ var buf bytes.Buffer
+ for {
+ buf.WriteByte(byte(c))
+ c = getc()
+ if isalnum(c) || c == '_' || c >= 0x80 {
+ continue
+ }
+ unget(c)
+ break
+ }
+ last = buf.String()
+ return Lookup(last)
+}
+
+func getsymdots(dots *int) *Sym {
+ var c int
+ var s *Sym
+
+ s = getsym()
+ if s != nil {
+ return s
+ }
+
+ c = getnsc()
+ if c != '.' {
+ unget(c)
+ return nil
+ }
+
+ if getc() != '.' || getc() != '.' {
+ Yyerror("bad dots in macro")
+ }
+ *dots = 1
+ return Lookup("__VA_ARGS__")
+}
+
+func getcom() int {
+ var c int
+
+ for {
+ c = getnsc()
+ if c != '/' {
+ break
+ }
+ c = getc()
+ if c == '/' {
+ for c != '\n' {
+ c = getc()
+ }
+ break
+ }
+
+ if c != '*' {
+ break
+ }
+ c = getc()
+ for {
+ if c == '*' {
+ c = getc()
+ if c != '/' {
+ continue
+ }
+ c = getc()
+ break
+ }
+
+ if c == '\n' {
+ Yyerror("comment across newline")
+ break
+ }
+
+ c = getc()
+ }
+
+ if c == '\n' {
+ break
+ }
+ }
+
+ return c
+}
+
+func dodefine(cp string) {
+ var s *Sym
+ var p string
+
+ if i := strings.Index(cp, "="); i >= 0 {
+ p = cp[i+1:]
+ cp = cp[:i]
+ s = Lookup(cp)
+ s.Macro = &Macro{Text: p}
+ } else {
+ s = Lookup(cp)
+ s.Macro = &Macro{Text: "1"}
+ }
+
+ if debug['m'] != 0 {
+ fmt.Printf("#define (-D) %s %s\n", s.Name, s.Macro.Text)
+ }
+}
+
+var mactab = []struct {
+ Macname string
+ Macf func()
+}{
+ {"ifdef", nil}, /* macif(0) */
+ {"ifndef", nil}, /* macif(1) */
+ {"else", nil}, /* macif(2) */
+ {"line", maclin},
+ {"define", macdef},
+ {"include", macinc},
+ {"undef", macund},
+ {"pragma", macprag},
+ {"endif", macend},
+}
+
+func domacro() {
+ var i int
+ var s *Sym
+
+ s = getsym()
+ if s == nil {
+ s = Lookup("endif")
+ }
+ for i = 0; i < len(mactab); i++ {
+ if s.Name == mactab[i].Macname {
+ if mactab[i].Macf != nil {
+ mactab[i].Macf()
+ } else {
+ macif(i)
+ }
+ return
+ }
+ }
+
+ Yyerror("unknown #: %s", s.Name)
+ macend()
+}
+
+func macund() {
+ var s *Sym
+
+ s = getsym()
+ macend()
+ if s == nil {
+ Yyerror("syntax in #undef")
+ return
+ }
+
+ s.Macro = nil
+}
+
+const (
+ NARG = 25
+)
+
+func macdef() {
+ var s *Sym
+ var a *Sym
+ var args [NARG]string
+ var n int
+ var i int
+ var c int
+ var dots int
+ var ischr int
+ var base bytes.Buffer
+
+ s = getsym()
+ if s == nil {
+ goto bad
+ }
+ if s.Macro != nil {
+ Yyerror("macro redefined: %s", s.Name)
+ }
+ c = getc()
+ n = -1
+ dots = 0
+ if c == '(' {
+ n++
+ c = getnsc()
+ if c != ')' {
+ unget(c)
+ for {
+ a = getsymdots(&dots)
+ if a == nil {
+ goto bad
+ }
+ if n >= NARG {
+ Yyerror("too many arguments in #define: %s", s.Name)
+ goto bad
+ }
+
+ args[n] = a.Name
+ n++
+ c = getnsc()
+ if c == ')' {
+ break
+ }
+ if c != ',' || dots != 0 {
+ goto bad
+ }
+ }
+ }
+
+ c = getc()
+ }
+
+ if isspace(c) {
+ if c != '\n' {
+ c = getnsc()
+ }
+ }
+ ischr = 0
+ for {
+ if isalpha(c) || c == '_' {
+ var buf bytes.Buffer
+ buf.WriteByte(byte(c))
+ c = getc()
+ for isalnum(c) || c == '_' {
+ buf.WriteByte(byte(c))
+ c = getc()
+ }
+
+ symb := buf.String()
+ for i = 0; i < n; i++ {
+ if symb == args[i] {
+ break
+ }
+ }
+ if i >= n {
+ base.WriteString(symb)
+ continue
+ }
+
+ base.WriteByte('#')
+ base.WriteByte(byte('a' + i))
+ continue
+ }
+
+ if ischr != 0 {
+ if c == '\\' {
+ base.WriteByte(byte(c))
+ c = getc()
+ } else if c == ischr {
+ ischr = 0
+ }
+ } else {
+
+ if c == '"' || c == '\'' {
+ base.WriteByte(byte(c))
+ ischr = c
+ c = getc()
+ continue
+ }
+
+ if c == '/' {
+ c = getc()
+ if c == '/' {
+ c = getc()
+ for {
+ if c == '\n' {
+ break
+ }
+ c = getc()
+ }
+
+ continue
+ }
+
+ if c == '*' {
+ c = getc()
+ for {
+ if c == '*' {
+ c = getc()
+ if c != '/' {
+ continue
+ }
+ c = getc()
+ break
+ }
+
+ if c == '\n' {
+ Yyerror("comment and newline in define: %s", s.Name)
+ break
+ }
+
+ c = getc()
+ }
+
+ continue
+ }
+
+ base.WriteByte('/')
+ continue
+ }
+ }
+
+ if c == '\\' {
+ c = getc()
+ if c == '\n' {
+ c = getc()
+ continue
+ } else if c == '\r' {
+ c = getc()
+ if c == '\n' {
+ c = getc()
+ continue
+ }
+ }
+
+ base.WriteByte('\\')
+ continue
+ }
+
+ if c == '\n' {
+ break
+ }
+ if c == '#' {
+ if n > 0 {
+ base.WriteByte(byte(c))
+ }
+ }
+
+ base.WriteByte(byte(c))
+ c = GETC()
+ if c == '\n' {
+ Lineno++
+ }
+ if c == -1 {
+ Yyerror("eof in a macro: %s", s.Name)
+ break
+ }
+ }
+
+ s.Macro = &Macro{
+ Text: base.String(),
+ Narg: n + 1,
+ Dots: dots != 0,
+ }
+ if debug['m'] != 0 {
+ fmt.Printf("#define %s %s\n", s.Name, s.Macro.Text)
+ }
+ return
+
+bad:
+ if s == nil {
+ Yyerror("syntax in #define")
+ } else {
+
+ Yyerror("syntax in #define: %s", s.Name)
+ }
+ macend()
+}
+
+func macexpand(s *Sym) []byte {
+ var l int
+ var c int
+ var arg []string
+ var out bytes.Buffer
+ var buf bytes.Buffer
+ var cp string
+
+ if s.Macro.Narg == 0 {
+ if debug['m'] != 0 {
+ fmt.Printf("#expand %s %s\n", s.Name, s.Macro.Text)
+ }
+ return []byte(s.Macro.Text)
+ }
+
+ nargs := s.Macro.Narg - 1
+ dots := s.Macro.Dots
+
+ c = getnsc()
+ if c != '(' {
+ goto bad
+ }
+ c = getc()
+ if c != ')' {
+ unget(c)
+ l = 0
+ for {
+ c = getc()
+ if c == '"' {
+ for {
+ buf.WriteByte(byte(c))
+ c = getc()
+ if c == '\\' {
+ buf.WriteByte(byte(c))
+ c = getc()
+ continue
+ }
+
+ if c == '\n' {
+ goto bad
+ }
+ if c == '"' {
+ break
+ }
+ }
+ }
+
+ if c == '\'' {
+ for {
+ buf.WriteByte(byte(c))
+ c = getc()
+ if c == '\\' {
+ buf.WriteByte(byte(c))
+ c = getc()
+ continue
+ }
+
+ if c == '\n' {
+ goto bad
+ }
+ if c == '\'' {
+ break
+ }
+ }
+ }
+
+ if c == '/' {
+ c = getc()
+ switch c {
+ case '*':
+ for {
+ c = getc()
+ if c == '*' {
+ c = getc()
+ if c == '/' {
+ break
+ }
+ }
+ }
+
+ buf.WriteByte(' ')
+ continue
+
+ case '/':
+ for {
+ c = getc()
+ if !(c != '\n') {
+ break
+ }
+ }
+
+ default:
+ unget(c)
+ c = '/'
+ }
+ }
+
+ if l == 0 {
+ if c == ',' {
+ if len(arg) == nargs-1 && dots {
+ buf.WriteByte(',')
+ continue
+ }
+
+ arg = append(arg, buf.String())
+ buf.Reset()
+ continue
+ }
+
+ if c == ')' {
+ arg = append(arg, buf.String())
+ break
+ }
+ }
+
+ if c == '\n' {
+ c = ' '
+ }
+ buf.WriteByte(byte(c))
+ if c == '(' {
+ l++
+ }
+ if c == ')' {
+ l--
+ }
+ }
+ }
+
+ if len(arg) != nargs {
+ Yyerror("argument mismatch expanding: %s", s.Name)
+ return nil
+ }
+
+ cp = s.Macro.Text
+ for i := 0; i < len(cp); i++ {
+ c = int(cp[i])
+ if c == '\n' {
+ c = ' '
+ }
+ if c != '#' {
+ out.WriteByte(byte(c))
+ continue
+ }
+
+ i++
+ if i >= len(cp) {
+ goto bad
+ }
+ c = int(cp[i])
+ if c == '#' {
+ out.WriteByte(byte(c))
+ continue
+ }
+
+ c -= 'a'
+ if c < 0 || c >= len(arg) {
+ continue
+ }
+ out.WriteString(arg[c])
+ }
+
+ if debug['m'] != 0 {
+ fmt.Printf("#expand %s %s\n", s.Name, out.String())
+ }
+ return out.Bytes()
+
+bad:
+ Yyerror("syntax in macro expansion: %s", s.Name)
+ return nil
+}
+
+func macinc() {
+ var c0 int
+ var c int
+ var i int
+ var buf bytes.Buffer
+ var f *os.File
+ var hp string
+ var str string
+ var symb string
+
+ c0 = getnsc()
+ if c0 != '"' {
+ c = c0
+ if c0 != '<' {
+ goto bad
+ }
+ c0 = '>'
+ }
+
+ for {
+ c = getc()
+ if c == c0 {
+ break
+ }
+ if c == '\n' {
+ goto bad
+ }
+ buf.WriteByte(byte(c))
+ }
+ str = buf.String()
+
+ c = getcom()
+ if c != '\n' {
+ goto bad
+ }
+
+ for i = 0; i < len(include); i++ {
+ if i == 0 && c0 == '>' {
+ continue
+ }
+ symb = include[i]
+ symb += "/"
+ if symb == "./" {
+ symb = ""
+ }
+ symb += str
+ var err error
+ f, err = os.Open(symb)
+ if err == nil {
+ break
+ }
+ }
+
+ if f == nil {
+ symb = str
+ }
+ hp = symb
+ newio()
+ pushio()
+ newfile(hp, f)
+ return
+
+bad:
+ unget(c)
+ Yyerror("syntax in #include")
+ macend()
+}
+
+func maclin() {
+ var c int
+ var n int32
+ var buf bytes.Buffer
+ var symb string
+
+ n = getnsn()
+ c = getc()
+ if n < 0 {
+ goto bad
+ }
+ for {
+ if c == ' ' || c == '\t' {
+ c = getc()
+ continue
+ }
+
+ if c == '"' {
+ break
+ }
+ if c == '\n' {
+ symb = "<noname>"
+ goto nn
+ }
+
+ goto bad
+ }
+
+ for {
+ c = getc()
+ if c == '"' {
+ break
+ }
+ buf.WriteByte(byte(c))
+ }
+ symb = buf.String()
+
+ c = getcom()
+ if c != '\n' {
+ goto bad
+ }
+
+nn:
+ obj.Linklinehist(Ctxt, int(Lineno), symb, int(n))
+ return
+
+bad:
+ unget(c)
+ Yyerror("syntax in #line")
+ macend()
+}
+
+func macif(f int) {
+ var c int
+ var l int
+ var bol int
+ var s *Sym
+
+ if f == 2 {
+ goto skip
+ }
+ s = getsym()
+ if s == nil {
+ goto bad
+ }
+ if getcom() != '\n' {
+ goto bad
+ }
+ if (s.Macro != nil) != (f != 0) {
+ return
+ }
+
+skip:
+ bol = 1
+ l = 0
+ for {
+ c = getc()
+ if c != '#' {
+ if !isspace(c) {
+ bol = 0
+ }
+ if c == '\n' {
+ bol = 1
+ }
+ continue
+ }
+
+ if !(bol != 0) {
+ continue
+ }
+ s = getsym()
+ if s == nil {
+ continue
+ }
+ if s.Name == "endif" {
+ if l != 0 {
+ l--
+ continue
+ }
+
+ macend()
+ return
+ }
+
+ if s.Name == "ifdef" || s.Name == "ifndef" {
+ l++
+ continue
+ }
+
+ if l == 0 && f != 2 && s.Name == "else" {
+ macend()
+ return
+ }
+ }
+
+bad:
+ Yyerror("syntax in #if(n)def")
+ macend()
+}
+
+func macprag() {
+ var s *Sym
+ var c0 int
+ var c int
+ var buf bytes.Buffer
+ var symb string
+
+ s = getsym()
+
+ if s != nil && s.Name == "lib" {
+ goto praglib
+ }
+ if s != nil && s.Name == "pack" {
+ pragpack()
+ return
+ }
+
+ if s != nil && s.Name == "fpround" {
+ pragfpround()
+ return
+ }
+
+ if s != nil && s.Name == "textflag" {
+ pragtextflag()
+ return
+ }
+
+ if s != nil && s.Name == "dataflag" {
+ pragdataflag()
+ return
+ }
+
+ if s != nil && s.Name == "varargck" {
+ pragvararg()
+ return
+ }
+
+ if s != nil && s.Name == "incomplete" {
+ pragincomplete()
+ return
+ }
+
+ if s != nil && (strings.HasPrefix(s.Name, "cgo_") || strings.HasPrefix(s.Name, "dyn")) {
+ pragcgo(s.Name)
+ return
+ }
+
+ for getnsc() != '\n' {
+
+ }
+ return
+
+praglib:
+ c0 = getnsc()
+ if c0 != '"' {
+ c = c0
+ if c0 != '<' {
+ goto bad
+ }
+ c0 = '>'
+ }
+
+ for {
+ c = getc()
+ if c == c0 {
+ break
+ }
+ if c == '\n' {
+ goto bad
+ }
+ buf.WriteByte(byte(c))
+ }
+ symb = buf.String()
+
+ c = getcom()
+ if c != '\n' {
+ goto bad
+ }
+
+ /*
+ * put pragma-line in as a funny history
+ */
+ obj.Linklinehist(Ctxt, int(Lineno), symb, -1)
+ return
+
+bad:
+ unget(c)
+ Yyerror("syntax in #pragma lib")
+ macend()
+}
+
+func macend() {
+ var c int
+
+ for {
+ c = getnsc()
+ if c < 0 || c == '\n' {
+ return
+ }
+ }
+}
--- /dev/null
+// Inferno utils/5c/5.out.h
+// http://code.google.com/p/inferno-os/source/browse/utils/5c/5.out.h
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package arm
+
+// list[5689].c
+
+// obj.c
+
+// objfile.c
+
+// pass.c
+
+// pcln.c
+
+// sym.c
+
+// TODO(ality): remove this workaround.
+// It's here because Pconv in liblink/list?.c references %L.
+
+const (
+ NSNAME = 8
+ NSYM = 50
+ NREG = 16
+)
+
+/* -1 disables use of REGARG */
+const (
+ REGARG = -1
+)
+
+const (
+ REGRET = 0
+ REGEXT = 10
+ REGG = REGEXT - 0
+ REGM = REGEXT - 1
+ REGTMP = 11
+ REGSP = 13
+ REGLINK = 14
+ REGPC = 15
+ NFREG = 16
+ FREGRET = 0
+ FREGEXT = 7
+ FREGTMP = 15
+)
+
+/* compiler allocates register variables F0 up */
+/* compiler allocates external registers F7 down */
+const (
+ C_NONE = iota
+ C_REG
+ C_REGREG
+ C_REGREG2
+ C_SHIFT
+ C_FREG
+ C_PSR
+ C_FCR
+ C_RCON
+ C_NCON
+ C_SCON
+ C_LCON
+ C_LCONADDR
+ C_ZFCON
+ C_SFCON
+ C_LFCON
+ C_RACON
+ C_LACON
+ C_SBRA
+ C_LBRA
+ C_HAUTO
+ C_FAUTO
+ C_HFAUTO
+ C_SAUTO
+ C_LAUTO
+ C_HOREG
+ C_FOREG
+ C_HFOREG
+ C_SOREG
+ C_ROREG
+ C_SROREG
+ C_LOREG
+ C_PC
+ C_SP
+ C_HREG
+ C_ADDR
+ C_GOK
+ C_NCLASS
+)
+
+const (
+ AXXX = iota
+ AAND
+ AEOR
+ ASUB
+ ARSB
+ AADD
+ AADC
+ ASBC
+ ARSC
+ ATST
+ ATEQ
+ ACMP
+ ACMN
+ AORR
+ ABIC
+ AMVN
+ AB
+ ABL
+ ABEQ
+ ABNE
+ ABCS
+ ABHS
+ ABCC
+ ABLO
+ ABMI
+ ABPL
+ ABVS
+ ABVC
+ ABHI
+ ABLS
+ ABGE
+ ABLT
+ ABGT
+ ABLE
+ AMOVWD
+ AMOVWF
+ AMOVDW
+ AMOVFW
+ AMOVFD
+ AMOVDF
+ AMOVF
+ AMOVD
+ ACMPF
+ ACMPD
+ AADDF
+ AADDD
+ ASUBF
+ ASUBD
+ AMULF
+ AMULD
+ ADIVF
+ ADIVD
+ ASQRTF
+ ASQRTD
+ AABSF
+ AABSD
+ ASRL
+ ASRA
+ ASLL
+ AMULU
+ ADIVU
+ AMUL
+ ADIV
+ AMOD
+ AMODU
+ AMOVB
+ AMOVBS
+ AMOVBU
+ AMOVH
+ AMOVHS
+ AMOVHU
+ AMOVW
+ AMOVM
+ ASWPBU
+ ASWPW
+ ANOP
+ ARFE
+ ASWI
+ AMULA
+ ADATA
+ AGLOBL
+ AGOK
+ AHISTORY
+ ANAME
+ ARET
+ ATEXT
+ AWORD
+ ADYNT_
+ AINIT_
+ ABCASE
+ ACASE
+ AEND
+ AMULL
+ AMULAL
+ AMULLU
+ AMULALU
+ ABX
+ ABXRET
+ ADWORD
+ ASIGNAME
+ ALDREX
+ ASTREX
+ ALDREXD
+ ASTREXD
+ APLD
+ AUNDEF
+ ACLZ
+ AMULWT
+ AMULWB
+ AMULAWT
+ AMULAWB
+ AUSEFIELD
+ ATYPE
+ AFUNCDATA
+ APCDATA
+ ACHECKNIL
+ AVARDEF
+ AVARKILL
+ ADUFFCOPY
+ ADUFFZERO
+ ADATABUNDLE
+ ADATABUNDLEEND
+ AMRC
+ ALAST
+)
+
+/* scond byte */
+const (
+ C_SCOND = (1 << 4) - 1
+ C_SBIT = 1 << 4
+ C_PBIT = 1 << 5
+ C_WBIT = 1 << 6
+ C_FBIT = 1 << 7
+ C_UBIT = 1 << 7
+ C_SCOND_EQ = 0
+ C_SCOND_NE = 1
+ C_SCOND_HS = 2
+ C_SCOND_LO = 3
+ C_SCOND_MI = 4
+ C_SCOND_PL = 5
+ C_SCOND_VS = 6
+ C_SCOND_VC = 7
+ C_SCOND_HI = 8
+ C_SCOND_LS = 9
+ C_SCOND_GE = 10
+ C_SCOND_LT = 11
+ C_SCOND_GT = 12
+ C_SCOND_LE = 13
+ C_SCOND_NONE = 14
+ C_SCOND_NV = 15
+ SHIFT_LL = 0 << 5
+ SHIFT_LR = 1 << 5
+ SHIFT_AR = 2 << 5
+ SHIFT_RR = 3 << 5
+)
+
+const (
+ D_GOK = 0
+ D_NONE = 1
+ D_BRANCH = D_NONE + 1
+ D_OREG = D_NONE + 2
+ D_CONST = D_NONE + 7
+ D_FCONST = D_NONE + 8
+ D_SCONST = D_NONE + 9
+ D_PSR = D_NONE + 10
+ D_REG = D_NONE + 12
+ D_FREG = D_NONE + 13
+ D_FILE = D_NONE + 16
+ D_OCONST = D_NONE + 17
+ D_FILE1 = D_NONE + 18
+ D_SHIFT = D_NONE + 19
+ D_FPCR = D_NONE + 20
+ D_REGREG = D_NONE + 21
+ D_ADDR = D_NONE + 22
+ D_SBIG = D_NONE + 23
+ D_CONST2 = D_NONE + 24
+ D_REGREG2 = D_NONE + 25
+ D_EXTERN = D_NONE + 3
+ D_STATIC = D_NONE + 4
+ D_AUTO = D_NONE + 5
+ D_PARAM = D_NONE + 6
+ D_LAST = D_NONE + 26
+)
+
+/*
+ * this is the ranlib header
+ */
+var SYMDEF string
--- /dev/null
+package arm
+
+var Anames = []string{
+ "XXX",
+ "AND",
+ "EOR",
+ "SUB",
+ "RSB",
+ "ADD",
+ "ADC",
+ "SBC",
+ "RSC",
+ "TST",
+ "TEQ",
+ "CMP",
+ "CMN",
+ "ORR",
+ "BIC",
+ "MVN",
+ "B",
+ "BL",
+ "BEQ",
+ "BNE",
+ "BCS",
+ "BHS",
+ "BCC",
+ "BLO",
+ "BMI",
+ "BPL",
+ "BVS",
+ "BVC",
+ "BHI",
+ "BLS",
+ "BGE",
+ "BLT",
+ "BGT",
+ "BLE",
+ "MOVWD",
+ "MOVWF",
+ "MOVDW",
+ "MOVFW",
+ "MOVFD",
+ "MOVDF",
+ "MOVF",
+ "MOVD",
+ "CMPF",
+ "CMPD",
+ "ADDF",
+ "ADDD",
+ "SUBF",
+ "SUBD",
+ "MULF",
+ "MULD",
+ "DIVF",
+ "DIVD",
+ "SQRTF",
+ "SQRTD",
+ "ABSF",
+ "ABSD",
+ "SRL",
+ "SRA",
+ "SLL",
+ "MULU",
+ "DIVU",
+ "MUL",
+ "DIV",
+ "MOD",
+ "MODU",
+ "MOVB",
+ "MOVBS",
+ "MOVBU",
+ "MOVH",
+ "MOVHS",
+ "MOVHU",
+ "MOVW",
+ "MOVM",
+ "SWPBU",
+ "SWPW",
+ "NOP",
+ "RFE",
+ "SWI",
+ "MULA",
+ "DATA",
+ "GLOBL",
+ "GOK",
+ "HISTORY",
+ "NAME",
+ "RET",
+ "TEXT",
+ "WORD",
+ "DYNT_",
+ "INIT_",
+ "BCASE",
+ "CASE",
+ "END",
+ "MULL",
+ "MULAL",
+ "MULLU",
+ "MULALU",
+ "BX",
+ "BXRET",
+ "DWORD",
+ "SIGNAME",
+ "LDREX",
+ "STREX",
+ "LDREXD",
+ "STREXD",
+ "PLD",
+ "UNDEF",
+ "CLZ",
+ "MULWT",
+ "MULWB",
+ "MULAWT",
+ "MULAWB",
+ "USEFIELD",
+ "TYPE",
+ "FUNCDATA",
+ "PCDATA",
+ "CHECKNIL",
+ "VARDEF",
+ "VARKILL",
+ "DUFFCOPY",
+ "DUFFZERO",
+ "DATABUNDLE",
+ "DATABUNDLEEND",
+ "MRC",
+ "LAST",
+}
+
+var cnames5 = []string{
+ "NONE",
+ "REG",
+ "REGREG",
+ "REGREG2",
+ "SHIFT",
+ "FREG",
+ "PSR",
+ "FCR",
+ "RCON",
+ "NCON",
+ "SCON",
+ "LCON",
+ "LCONADDR",
+ "ZFCON",
+ "SFCON",
+ "LFCON",
+ "RACON",
+ "LACON",
+ "SBRA",
+ "LBRA",
+ "HAUTO",
+ "FAUTO",
+ "HFAUTO",
+ "SAUTO",
+ "LAUTO",
+ "HOREG",
+ "FOREG",
+ "HFOREG",
+ "SOREG",
+ "ROREG",
+ "SROREG",
+ "LOREG",
+ "PC",
+ "SP",
+ "HREG",
+ "ADDR",
+ "GOK",
+ "NCLASS",
+ "SCOND = (1<<4)-1",
+ "SBIT = 1<<4",
+ "PBIT = 1<<5",
+ "WBIT = 1<<6",
+ "FBIT = 1<<7",
+ "UBIT = 1<<7",
+ "SCOND_EQ = 0",
+ "SCOND_NE = 1",
+ "SCOND_HS = 2",
+ "SCOND_LO = 3",
+ "SCOND_MI = 4",
+ "SCOND_PL = 5",
+ "SCOND_VS = 6",
+ "SCOND_VC = 7",
+ "SCOND_HI = 8",
+ "SCOND_LS = 9",
+ "SCOND_GE = 10",
+ "SCOND_LT = 11",
+ "SCOND_GT = 12",
+ "SCOND_LE = 13",
+ "SCOND_NONE = 14",
+ "SCOND_NV = 15",
+}
+
+var dnames5 = []string{
+ D_GOK: "GOK",
+ D_NONE: "NONE",
+}
--- /dev/null
+// Inferno utils/5l/span.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5l/span.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package arm
+
+import (
+ "cmd/internal/obj"
+ "fmt"
+ "log"
+ "math"
+ "sort"
+)
+
+type Optab struct {
+ as uint8
+ a1 uint8
+ a2 int8
+ a3 uint8
+ type_ uint8
+ size int8
+ param int8
+ flag int8
+ pcrelsiz uint8
+}
+
+type Oprang struct {
+ start []Optab
+ stop []Optab
+}
+
+type Opcross [32][2][32]uint8
+
+const (
+ LFROM = 1 << 0
+ LTO = 1 << 1
+ LPOOL = 1 << 2
+ LPCREL = 1 << 3
+)
+
+var optab = []Optab{
+ /* struct Optab:
+ OPCODE, from, prog->reg, to, type,size,param,flag */
+ Optab{ATEXT, C_ADDR, C_NONE, C_LCON, 0, 0, 0, 0, 0},
+ Optab{ATEXT, C_ADDR, C_REG, C_LCON, 0, 0, 0, 0, 0},
+ Optab{AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0},
+ Optab{AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
+ Optab{AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
+ Optab{AMVN, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
+ Optab{ACMP, C_REG, C_REG, C_NONE, 1, 4, 0, 0, 0},
+ Optab{AADD, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0},
+ Optab{AADD, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
+ Optab{AMOVW, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
+ Optab{AMVN, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
+ Optab{ACMP, C_RCON, C_REG, C_NONE, 2, 4, 0, 0, 0},
+ Optab{AADD, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0},
+ Optab{AADD, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
+ Optab{AMVN, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
+ Optab{ACMP, C_SHIFT, C_REG, C_NONE, 3, 4, 0, 0, 0},
+ Optab{AMOVW, C_RACON, C_NONE, C_REG, 4, 4, REGSP, 0, 0},
+ Optab{AB, C_NONE, C_NONE, C_SBRA, 5, 4, 0, LPOOL, 0},
+ Optab{ABL, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
+ Optab{ABX, C_NONE, C_NONE, C_SBRA, 74, 20, 0, 0, 0},
+ Optab{ABEQ, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
+ Optab{AB, C_NONE, C_NONE, C_ROREG, 6, 4, 0, LPOOL, 0},
+ Optab{ABL, C_NONE, C_NONE, C_ROREG, 7, 4, 0, 0, 0},
+ Optab{ABL, C_REG, C_NONE, C_ROREG, 7, 4, 0, 0, 0},
+ Optab{ABX, C_NONE, C_NONE, C_ROREG, 75, 12, 0, 0, 0},
+ Optab{ABXRET, C_NONE, C_NONE, C_ROREG, 76, 4, 0, 0, 0},
+ Optab{ASLL, C_RCON, C_REG, C_REG, 8, 4, 0, 0, 0},
+ Optab{ASLL, C_RCON, C_NONE, C_REG, 8, 4, 0, 0, 0},
+ Optab{ASLL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
+ Optab{ASLL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0},
+ Optab{ASWI, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
+ Optab{ASWI, C_NONE, C_NONE, C_LOREG, 10, 4, 0, 0, 0},
+ Optab{ASWI, C_NONE, C_NONE, C_LCON, 10, 4, 0, 0, 0},
+ Optab{AWORD, C_NONE, C_NONE, C_LCON, 11, 4, 0, 0, 0},
+ Optab{AWORD, C_NONE, C_NONE, C_LCONADDR, 11, 4, 0, 0, 0},
+ Optab{AWORD, C_NONE, C_NONE, C_ADDR, 11, 4, 0, 0, 0},
+ Optab{AMOVW, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0},
+ Optab{AMOVW, C_LCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0},
+ Optab{AMOVW, C_LCONADDR, C_NONE, C_REG, 12, 4, 0, LFROM | LPCREL, 4},
+ Optab{AADD, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0},
+ Optab{AADD, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
+ Optab{AMVN, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
+ Optab{ACMP, C_NCON, C_REG, C_NONE, 13, 8, 0, 0, 0},
+ Optab{AADD, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0},
+ Optab{AADD, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0},
+ Optab{AMVN, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0},
+ Optab{ACMP, C_LCON, C_REG, C_NONE, 13, 8, 0, LFROM, 0},
+ Optab{AMOVB, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
+ Optab{AMOVBS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0},
+ Optab{AMOVBU, C_REG, C_NONE, C_REG, 58, 4, 0, 0, 0},
+ Optab{AMOVH, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
+ Optab{AMOVHS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0},
+ Optab{AMOVHU, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0},
+ Optab{AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
+ Optab{AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0},
+ Optab{ADIV, C_REG, C_REG, C_REG, 16, 4, 0, 0, 0},
+ Optab{ADIV, C_REG, C_NONE, C_REG, 16, 4, 0, 0, 0},
+ Optab{AMULL, C_REG, C_REG, C_REGREG, 17, 4, 0, 0, 0},
+ Optab{AMULA, C_REG, C_REG, C_REGREG2, 17, 4, 0, 0, 0},
+ Optab{AMOVW, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
+ Optab{AMOVW, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
+ Optab{AMOVB, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
+ Optab{AMOVB, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
+ Optab{AMOVBS, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
+ Optab{AMOVBS, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
+ Optab{AMOVBU, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
+ Optab{AMOVBU, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
+ Optab{AMOVW, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
+ Optab{AMOVW, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0},
+ Optab{AMOVBU, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
+ Optab{AMOVBU, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0},
+ Optab{AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
+ Optab{AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
+ Optab{AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
+ Optab{AMOVB, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
+ Optab{AMOVB, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
+ Optab{AMOVB, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
+ Optab{AMOVBS, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
+ Optab{AMOVBS, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
+ Optab{AMOVBS, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
+ Optab{AMOVBU, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
+ Optab{AMOVBU, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
+ Optab{AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
+ Optab{AMOVW, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
+ Optab{AMOVW, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
+ Optab{AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4},
+ Optab{AMOVBU, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
+ Optab{AMOVBU, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
+ Optab{AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4},
+ Optab{AMOVW, C_LACON, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0},
+ Optab{AMOVW, C_PSR, C_NONE, C_REG, 35, 4, 0, 0, 0},
+ Optab{AMOVW, C_REG, C_NONE, C_PSR, 36, 4, 0, 0, 0},
+ Optab{AMOVW, C_RCON, C_NONE, C_PSR, 37, 4, 0, 0, 0},
+ Optab{AMOVM, C_LCON, C_NONE, C_SOREG, 38, 4, 0, 0, 0},
+ Optab{AMOVM, C_SOREG, C_NONE, C_LCON, 39, 4, 0, 0, 0},
+ Optab{ASWPW, C_SOREG, C_REG, C_REG, 40, 4, 0, 0, 0},
+ Optab{ARFE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0},
+ Optab{AMOVF, C_FREG, C_NONE, C_FAUTO, 50, 4, REGSP, 0, 0},
+ Optab{AMOVF, C_FREG, C_NONE, C_FOREG, 50, 4, 0, 0, 0},
+ Optab{AMOVF, C_FAUTO, C_NONE, C_FREG, 51, 4, REGSP, 0, 0},
+ Optab{AMOVF, C_FOREG, C_NONE, C_FREG, 51, 4, 0, 0, 0},
+ Optab{AMOVF, C_FREG, C_NONE, C_LAUTO, 52, 12, REGSP, LTO, 0},
+ Optab{AMOVF, C_FREG, C_NONE, C_LOREG, 52, 12, 0, LTO, 0},
+ Optab{AMOVF, C_LAUTO, C_NONE, C_FREG, 53, 12, REGSP, LFROM, 0},
+ Optab{AMOVF, C_LOREG, C_NONE, C_FREG, 53, 12, 0, LFROM, 0},
+ Optab{AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO | LPCREL, 4},
+ Optab{AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM | LPCREL, 4},
+ Optab{AADDF, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
+ Optab{AADDF, C_FREG, C_REG, C_FREG, 54, 4, 0, 0, 0},
+ Optab{AMOVF, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
+ Optab{AMOVW, C_REG, C_NONE, C_FCR, 56, 4, 0, 0, 0},
+ Optab{AMOVW, C_FCR, C_NONE, C_REG, 57, 4, 0, 0, 0},
+ Optab{AMOVW, C_SHIFT, C_NONE, C_REG, 59, 4, 0, 0, 0},
+ Optab{AMOVBU, C_SHIFT, C_NONE, C_REG, 59, 4, 0, 0, 0},
+ Optab{AMOVB, C_SHIFT, C_NONE, C_REG, 60, 4, 0, 0, 0},
+ Optab{AMOVBS, C_SHIFT, C_NONE, C_REG, 60, 4, 0, 0, 0},
+ Optab{AMOVW, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
+ Optab{AMOVB, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
+ Optab{AMOVBS, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
+ Optab{AMOVBU, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
+ Optab{ACASE, C_REG, C_NONE, C_NONE, 62, 4, 0, LPCREL, 8},
+ Optab{ABCASE, C_NONE, C_NONE, C_SBRA, 63, 4, 0, LPCREL, 0},
+ Optab{AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
+ Optab{AMOVH, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0},
+ Optab{AMOVHS, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
+ Optab{AMOVHS, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0},
+ Optab{AMOVHU, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
+ Optab{AMOVHU, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0},
+ Optab{AMOVB, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
+ Optab{AMOVB, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
+ Optab{AMOVBS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
+ Optab{AMOVBS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
+ Optab{AMOVH, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
+ Optab{AMOVH, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
+ Optab{AMOVHS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
+ Optab{AMOVHS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
+ Optab{AMOVHU, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
+ Optab{AMOVHU, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
+ Optab{AMOVH, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0},
+ Optab{AMOVH, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0},
+ Optab{AMOVH, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4},
+ Optab{AMOVHS, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0},
+ Optab{AMOVHS, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0},
+ Optab{AMOVHS, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4},
+ Optab{AMOVHU, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0},
+ Optab{AMOVHU, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0},
+ Optab{AMOVHU, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4},
+ Optab{AMOVB, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
+ Optab{AMOVB, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
+ Optab{AMOVB, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
+ Optab{AMOVBS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
+ Optab{AMOVBS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
+ Optab{AMOVBS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
+ Optab{AMOVH, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
+ Optab{AMOVH, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
+ Optab{AMOVH, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
+ Optab{AMOVHS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
+ Optab{AMOVHS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
+ Optab{AMOVHS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
+ Optab{AMOVHU, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
+ Optab{AMOVHU, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
+ Optab{AMOVHU, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
+ Optab{ALDREX, C_SOREG, C_NONE, C_REG, 77, 4, 0, 0, 0},
+ Optab{ASTREX, C_SOREG, C_REG, C_REG, 78, 4, 0, 0, 0},
+ Optab{AMOVF, C_ZFCON, C_NONE, C_FREG, 80, 8, 0, 0, 0},
+ Optab{AMOVF, C_SFCON, C_NONE, C_FREG, 81, 4, 0, 0, 0},
+ Optab{ACMPF, C_FREG, C_REG, C_NONE, 82, 8, 0, 0, 0},
+ Optab{ACMPF, C_FREG, C_NONE, C_NONE, 83, 8, 0, 0, 0},
+ Optab{AMOVFW, C_FREG, C_NONE, C_FREG, 84, 4, 0, 0, 0},
+ Optab{AMOVWF, C_FREG, C_NONE, C_FREG, 85, 4, 0, 0, 0},
+ Optab{AMOVFW, C_FREG, C_NONE, C_REG, 86, 8, 0, 0, 0},
+ Optab{AMOVWF, C_REG, C_NONE, C_FREG, 87, 8, 0, 0, 0},
+ Optab{AMOVW, C_REG, C_NONE, C_FREG, 88, 4, 0, 0, 0},
+ Optab{AMOVW, C_FREG, C_NONE, C_REG, 89, 4, 0, 0, 0},
+ Optab{ATST, C_REG, C_NONE, C_NONE, 90, 4, 0, 0, 0},
+ Optab{ALDREXD, C_SOREG, C_NONE, C_REG, 91, 4, 0, 0, 0},
+ Optab{ASTREXD, C_SOREG, C_REG, C_REG, 92, 4, 0, 0, 0},
+ Optab{APLD, C_SOREG, C_NONE, C_NONE, 95, 4, 0, 0, 0},
+ Optab{AUNDEF, C_NONE, C_NONE, C_NONE, 96, 4, 0, 0, 0},
+ Optab{ACLZ, C_REG, C_NONE, C_REG, 97, 4, 0, 0, 0},
+ Optab{AMULWT, C_REG, C_REG, C_REG, 98, 4, 0, 0, 0},
+ Optab{AMULAWT, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0},
+ Optab{AUSEFIELD, C_ADDR, C_NONE, C_NONE, 0, 0, 0, 0, 0},
+ Optab{APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0, 0, 0},
+ Optab{AFUNCDATA, C_LCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0},
+ Optab{ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
+ Optab{ADUFFZERO, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as ABL
+ Optab{ADUFFCOPY, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as ABL
+
+ Optab{ADATABUNDLE, C_NONE, C_NONE, C_NONE, 100, 4, 0, 0, 0},
+ Optab{ADATABUNDLEEND, C_NONE, C_NONE, C_NONE, 100, 0, 0, 0, 0},
+ Optab{AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0},
+}
+
+var pool struct {
+ start uint32
+ size uint32
+ extra uint32
+}
+
+var oprange [ALAST]Oprang
+
+var xcmp [C_GOK + 1][C_GOK + 1]uint8
+
+var zprg = obj.Prog{
+ As: AGOK,
+ Scond: C_SCOND_NONE,
+ Reg: NREG,
+ From: obj.Addr{
+ Name: D_NONE,
+ Type: D_NONE,
+ Reg: NREG,
+ },
+ To: obj.Addr{
+ Name: D_NONE,
+ Type: D_NONE,
+ Reg: NREG,
+ },
+}
+
+var deferreturn *obj.LSym
+
+func nocache(p *obj.Prog) {
+ p.Optab = 0
+ p.From.Class = 0
+ p.To.Class = 0
+}
+
+/* size of a case statement including jump table */
+func casesz(ctxt *obj.Link, p *obj.Prog) int32 {
+
+ var jt int = 0
+ var n int32 = 0
+ var o *Optab
+
+ for ; p != nil; p = p.Link {
+ if p.As == ABCASE {
+ jt = 1
+ } else if jt != 0 {
+ break
+ }
+ o = oplook(ctxt, p)
+ n += int32(o.size)
+ }
+
+ return n
+}
+
+// asmoutnacl assembles the instruction p. It replaces asmout for NaCl.
+// It returns the total number of bytes put in out, and it can change
+// p->pc if extra padding is necessary.
+// In rare cases, asmoutnacl might split p into two instructions.
+// origPC is the PC for this Prog (no padding is taken into account).
+func asmoutnacl(ctxt *obj.Link, origPC int32, p *obj.Prog, o *Optab, out []uint32) int {
+
+ var size int
+ var reg int
+ var q *obj.Prog
+ var a *obj.Addr
+ var a2 *obj.Addr
+
+ size = int(o.size)
+
+ // instruction specific
+ switch p.As {
+
+ default:
+ if out != nil {
+ asmout(ctxt, p, o, out)
+ }
+
+ case ADATABUNDLE, // align to 16-byte boundary
+ ADATABUNDLEEND: // zero width instruction, just to align next instruction to 16-byte boundary
+ p.Pc = (p.Pc + 15) &^ 15
+
+ if out != nil {
+ asmout(ctxt, p, o, out)
+ }
+
+ case AUNDEF,
+ APLD:
+ size = 4
+ if out != nil {
+ switch p.As {
+ case AUNDEF:
+ out[0] = 0xe7fedef0 // NACL_INSTR_ARM_ABORT_NOW (UDF #0xEDE0)
+
+ case APLD:
+ out[0] = 0xe1a01001 // (MOVW R1, R1)
+ break
+ }
+ }
+
+ case AB,
+ ABL:
+ if p.To.Type != D_OREG {
+ if out != nil {
+ asmout(ctxt, p, o, out)
+ }
+ } else {
+
+ if p.To.Offset != 0 || size != 4 || p.To.Reg >= 16 || p.To.Reg < 0 {
+ ctxt.Diag("unsupported instruction: %v", p)
+ }
+ if p.Pc&15 == 12 {
+ p.Pc += 4
+ }
+ if out != nil {
+ out[0] = (uint32(p.Scond)&C_SCOND)<<28 | 0x03c0013f | uint32(p.To.Reg)<<12 | uint32(p.To.Reg)<<16 // BIC $0xc000000f, Rx
+ if p.As == AB {
+ out[1] = (uint32(p.Scond)&C_SCOND)<<28 | 0x012fff10 | uint32(p.To.Reg) // BX Rx // ABL
+ } else {
+ out[1] = (uint32(p.Scond)&C_SCOND)<<28 | 0x012fff30 | uint32(p.To.Reg) // BLX Rx
+ }
+ }
+
+ size = 8
+ }
+
+ // align the last instruction (the actual BL) to the last instruction in a bundle
+ if p.As == ABL {
+
+ if deferreturn == nil {
+ deferreturn = obj.Linklookup(ctxt, "runtime.deferreturn", 0)
+ }
+ if p.To.Sym == deferreturn {
+ p.Pc = ((int64(origPC) + 15) &^ 15) + 16 - int64(size)
+ } else {
+
+ p.Pc += (16 - ((p.Pc + int64(size)) & 15)) & 15
+ }
+ }
+
+ case ALDREX,
+ ALDREXD,
+ AMOVB,
+ AMOVBS,
+ AMOVBU,
+ AMOVD,
+ AMOVF,
+ AMOVH,
+ AMOVHS,
+ AMOVHU,
+ AMOVM,
+ AMOVW,
+ ASTREX,
+ ASTREXD:
+ if p.To.Type == D_REG && p.To.Reg == 15 && p.From.Reg == 13 { // MOVW.W x(R13), PC
+ if out != nil {
+ asmout(ctxt, p, o, out)
+ }
+ if size == 4 {
+ if out != nil {
+ // Note: 5c and 5g reg.c know that DIV/MOD smashes R12
+ // so that this return instruction expansion is valid.
+ out[0] = out[0] &^ 0x3000 // change PC to R12
+ out[1] = (uint32(p.Scond)&C_SCOND)<<28 | 0x03ccc13f // BIC $0xc000000f, R12
+ out[2] = (uint32(p.Scond)&C_SCOND)<<28 | 0x012fff1c // BX R12
+ }
+
+ size += 8
+ if (p.Pc+int64(size))&15 == 4 {
+ p.Pc += 4
+ }
+ break
+ } else {
+
+ // if the instruction used more than 4 bytes, then it must have used a very large
+ // offset to update R13, so we need to additionally mask R13.
+ if out != nil {
+
+ out[size/4-1] &^= 0x3000 // change PC to R12
+ out[size/4] = (uint32(p.Scond)&C_SCOND)<<28 | 0x03cdd103 // BIC $0xc0000000, R13
+ out[size/4+1] = (uint32(p.Scond)&C_SCOND)<<28 | 0x03ccc13f // BIC $0xc000000f, R12
+ out[size/4+2] = (uint32(p.Scond)&C_SCOND)<<28 | 0x012fff1c // BX R12
+ }
+
+ // p->pc+size is only ok at 4 or 12 mod 16.
+ if (p.Pc+int64(size))%8 == 0 {
+
+ p.Pc += 4
+ }
+ size += 12
+ break
+ }
+ }
+
+ if p.To.Type == D_REG && p.To.Reg == 15 {
+ ctxt.Diag("unsupported instruction (move to another register and use indirect jump instead): %v", p)
+ }
+
+ if p.To.Type == D_OREG && p.To.Reg == 13 && (p.Scond&C_WBIT != 0) && size > 4 {
+ // function prolog with very large frame size: MOVW.W R14,-100004(R13)
+ // split it into two instructions:
+ // ADD $-100004, R13
+ // MOVW R14, 0(R13)
+ q = ctxt.NewProg()
+
+ p.Scond &^= C_WBIT
+ *q = *p
+ a = &p.To
+ if p.To.Type == D_OREG {
+ a2 = &q.To
+ } else {
+
+ a2 = &q.From
+ }
+ nocache(q)
+ nocache(p)
+
+ // insert q after p
+ q.Link = p.Link
+
+ p.Link = q
+ q.Pcond = nil
+
+ // make p into ADD $X, R13
+ p.As = AADD
+
+ p.From = *a
+ p.From.Reg = NREG
+ p.From.Type = D_CONST
+ p.To = zprg.To
+ p.To.Type = D_REG
+ p.To.Reg = 13
+
+ // make q into p but load/store from 0(R13)
+ q.Spadj = 0
+
+ *a2 = zprg.From
+ a2.Type = D_OREG
+ a2.Reg = 13
+ a2.Sym = nil
+ a2.Offset = 0
+ size = int(oplook(ctxt, p).size)
+ break
+ }
+
+ if (p.To.Type == D_OREG && p.To.Reg != 13 && p.To.Reg != 9) || (p.From.Type == D_OREG && p.From.Reg != 13 && p.From.Reg != 9) { // MOVW Rx, X(Ry), y != 13 && y != 9 // MOVW X(Rx), Ry, x != 13 && x != 9
+ if p.To.Type == D_OREG {
+ a = &p.To
+ } else {
+
+ a = &p.From
+ }
+ reg = int(a.Reg)
+ if size == 4 {
+ // if addr.reg == NREG, then it is probably load from x(FP) with small x, no need to modify.
+ if reg == NREG {
+
+ if out != nil {
+ asmout(ctxt, p, o, out)
+ }
+ } else {
+
+ if out != nil {
+ out[0] = (uint32(p.Scond)&C_SCOND)<<28 | 0x03c00103 | uint32(reg)<<16 | uint32(reg)<<12 // BIC $0xc0000000, Rx
+ }
+ if p.Pc&15 == 12 {
+ p.Pc += 4
+ }
+ size += 4
+ if out != nil {
+ asmout(ctxt, p, o, out[1:])
+ }
+ }
+
+ break
+ } else {
+
+ // if a load/store instruction takes more than 1 word to implement, then
+ // we need to seperate the instruction into two:
+ // 1. explicitly load the address into R11.
+ // 2. load/store from R11.
+ // This won't handle .W/.P, so we should reject such code.
+ if p.Scond&(C_PBIT|C_WBIT) != 0 {
+
+ ctxt.Diag("unsupported instruction (.P/.W): %v", p)
+ }
+ q = ctxt.NewProg()
+ *q = *p
+ if p.To.Type == D_OREG {
+ a2 = &q.To
+ } else {
+
+ a2 = &q.From
+ }
+ nocache(q)
+ nocache(p)
+
+ // insert q after p
+ q.Link = p.Link
+
+ p.Link = q
+ q.Pcond = nil
+
+ // make p into MOVW $X(R), R11
+ p.As = AMOVW
+
+ p.From = *a
+ p.From.Type = D_CONST
+ p.To = zprg.To
+ p.To.Type = D_REG
+ p.To.Reg = 11
+
+ // make q into p but load/store from 0(R11)
+ *a2 = zprg.From
+
+ a2.Type = D_OREG
+ a2.Reg = 11
+ a2.Sym = nil
+ a2.Offset = 0
+ size = int(oplook(ctxt, p).size)
+ break
+ }
+ } else if out != nil {
+ asmout(ctxt, p, o, out)
+ }
+ break
+ }
+
+ // destination register specific
+ if p.To.Type == D_REG {
+
+ switch p.To.Reg {
+ case 9:
+ ctxt.Diag("invalid instruction, cannot write to R9: %v", p)
+
+ case 13:
+ if out != nil {
+ out[size/4] = 0xe3cdd103 // BIC $0xc0000000, R13
+ }
+ if (p.Pc+int64(size))&15 == 0 {
+ p.Pc += 4
+ }
+ size += 4
+ break
+ }
+ }
+
+ return size
+}
+
+func span5(ctxt *obj.Link, cursym *obj.LSym) {
+ var p *obj.Prog
+ var op *obj.Prog
+ var o *Optab
+ var m int
+ var bflag int
+ var i int
+ var v int
+ var times int
+ var c int32
+ var opc int32
+ var out [6 + 3]uint32
+ var bp []byte
+
+ p = cursym.Text
+ if p == nil || p.Link == nil { // handle external functions and ELF section symbols
+ return
+ }
+
+ if oprange[AAND].start == nil {
+ buildop(ctxt)
+ }
+
+ ctxt.Cursym = cursym
+
+ ctxt.Autosize = int32(p.To.Offset + 4)
+ c = 0
+
+ op = p
+ p = p.Link
+ for ; p != nil || ctxt.Blitrl != nil; (func() { op = p; p = p.Link })() {
+ if p == nil {
+ if checkpool(ctxt, op, 0) != 0 {
+ p = op
+ continue
+ }
+
+ // can't happen: blitrl is not nil, but checkpool didn't flushpool
+ ctxt.Diag("internal inconsistency")
+
+ break
+ }
+
+ ctxt.Curp = p
+ p.Pc = int64(c)
+ o = oplook(ctxt, p)
+ if ctxt.Headtype != obj.Hnacl {
+ m = int(o.size)
+ } else {
+
+ m = asmoutnacl(ctxt, c, p, o, nil)
+ c = int32(p.Pc) // asmoutnacl might change pc for alignment
+ o = oplook(ctxt, p) // asmoutnacl might change p in rare cases
+ }
+
+ if m%4 != 0 || p.Pc%4 != 0 {
+ ctxt.Diag("!pc invalid: %v size=%d", p, m)
+ }
+
+ // must check literal pool here in case p generates many instructions
+ if ctxt.Blitrl != nil {
+
+ i = m
+ if p.As == ACASE {
+ i = int(casesz(ctxt, p))
+ }
+ if checkpool(ctxt, op, i) != 0 {
+ p = op
+ continue
+ }
+ }
+
+ if m == 0 && (p.As != AFUNCDATA && p.As != APCDATA && p.As != ADATABUNDLEEND && p.As != ANOP) {
+ ctxt.Diag("zero-width instruction\n%v", p)
+ continue
+ }
+
+ switch o.flag & (LFROM | LTO | LPOOL) {
+ case LFROM:
+ addpool(ctxt, p, &p.From)
+
+ case LTO:
+ addpool(ctxt, p, &p.To)
+
+ case LPOOL:
+ if p.Scond&C_SCOND == C_SCOND_NONE {
+ flushpool(ctxt, p, 0, 0)
+ }
+ break
+ }
+
+ if p.As == AMOVW && p.To.Type == D_REG && p.To.Reg == REGPC && p.Scond&C_SCOND == C_SCOND_NONE {
+ flushpool(ctxt, p, 0, 0)
+ }
+ c += int32(m)
+ }
+
+ cursym.Size = int64(c)
+
+ /*
+ * if any procedure is large enough to
+ * generate a large SBRA branch, then
+ * generate extra passes putting branches
+ * around jmps to fix. this is rare.
+ */
+ times = 0
+
+ for {
+ if ctxt.Debugvlog != 0 {
+ fmt.Fprintf(ctxt.Bso, "%5.2f span1\n", obj.Cputime())
+ }
+ bflag = 0
+ c = 0
+ times++
+ cursym.Text.Pc = 0 // force re-layout the code.
+ for p = cursym.Text; p != nil; p = p.Link {
+ ctxt.Curp = p
+ o = oplook(ctxt, p)
+ if int64(c) > p.Pc {
+ p.Pc = int64(c)
+ }
+
+ /* very large branches
+ if(o->type == 6 && p->pcond) {
+ otxt = p->pcond->pc - c;
+ if(otxt < 0)
+ otxt = -otxt;
+ if(otxt >= (1L<<17) - 10) {
+ q = ctxt->arch->prg();
+ q->link = p->link;
+ p->link = q;
+ q->as = AB;
+ q->to.type = D_BRANCH;
+ q->pcond = p->pcond;
+ p->pcond = q;
+ q = ctxt->arch->prg();
+ q->link = p->link;
+ p->link = q;
+ q->as = AB;
+ q->to.type = D_BRANCH;
+ q->pcond = q->link->link;
+ bflag = 1;
+ }
+ }
+ */
+ opc = int32(p.Pc)
+
+ if ctxt.Headtype != obj.Hnacl {
+ m = int(o.size)
+ } else {
+
+ m = asmoutnacl(ctxt, c, p, o, nil)
+ }
+ if p.Pc != int64(opc) {
+ bflag = 1
+ }
+
+ //print("%P pc changed %d to %d in iter. %d\n", p, opc, (int32)p->pc, times);
+ c = int32(p.Pc + int64(m))
+
+ if m%4 != 0 || p.Pc%4 != 0 {
+ ctxt.Diag("pc invalid: %v size=%d", p, m)
+ }
+
+ if m/4 > len(out) {
+ ctxt.Diag("instruction size too large: %d > %d", m/4, len(out))
+ }
+ if m == 0 && (p.As != AFUNCDATA && p.As != APCDATA && p.As != ADATABUNDLEEND && p.As != ANOP) {
+ if p.As == ATEXT {
+ ctxt.Autosize = int32(p.To.Offset + 4)
+ continue
+ }
+
+ ctxt.Diag("zero-width instruction\n%v", p)
+ continue
+ }
+ }
+
+ cursym.Size = int64(c)
+ if !(bflag != 0) {
+ break
+ }
+ }
+
+ if c%4 != 0 {
+ ctxt.Diag("sym->size=%d, invalid", c)
+ }
+
+ /*
+ * lay out the code. all the pc-relative code references,
+ * even cross-function, are resolved now;
+ * only data references need to be relocated.
+ * with more work we could leave cross-function
+ * code references to be relocated too, and then
+ * perhaps we'd be able to parallelize the span loop above.
+ */
+ if ctxt.Tlsg == nil {
+
+ ctxt.Tlsg = obj.Linklookup(ctxt, "runtime.tlsg", 0)
+ }
+
+ p = cursym.Text
+ ctxt.Autosize = int32(p.To.Offset + 4)
+ obj.Symgrow(ctxt, cursym, cursym.Size)
+
+ bp = cursym.P
+ c = int32(p.Pc) // even p->link might need extra padding
+ for p = p.Link; p != nil; p = p.Link {
+ ctxt.Pc = p.Pc
+ ctxt.Curp = p
+ o = oplook(ctxt, p)
+ opc = int32(p.Pc)
+ if ctxt.Headtype != obj.Hnacl {
+ asmout(ctxt, p, o, out[:])
+ m = int(o.size)
+ } else {
+
+ m = asmoutnacl(ctxt, c, p, o, out[:])
+ if int64(opc) != p.Pc {
+ ctxt.Diag("asmoutnacl broken: pc changed (%d->%d) in last stage: %v", opc, int32(p.Pc), p)
+ }
+ }
+
+ if m%4 != 0 || p.Pc%4 != 0 {
+ ctxt.Diag("final stage: pc invalid: %v size=%d", p, m)
+ }
+
+ if int64(c) > p.Pc {
+ ctxt.Diag("PC padding invalid: want %#d, has %#d: %v", p.Pc, c, p)
+ }
+ for int64(c) != p.Pc {
+ // emit 0xe1a00000 (MOVW R0, R0)
+ bp[0] = 0x00
+ bp = bp[1:]
+
+ bp[0] = 0x00
+ bp = bp[1:]
+ bp[0] = 0xa0
+ bp = bp[1:]
+ bp[0] = 0xe1
+ bp = bp[1:]
+ c += 4
+ }
+
+ for i = 0; i < m/4; i++ {
+ v = int(out[i])
+ bp[0] = byte(v)
+ bp = bp[1:]
+ bp[0] = byte(v >> 8)
+ bp = bp[1:]
+ bp[0] = byte(v >> 16)
+ bp = bp[1:]
+ bp[0] = byte(v >> 24)
+ bp = bp[1:]
+ }
+
+ c += int32(m)
+ }
+}
+
+/*
+ * when the first reference to the literal pool threatens
+ * to go out of range of a 12-bit PC-relative offset,
+ * drop the pool now, and branch round it.
+ * this happens only in extended basic blocks that exceed 4k.
+ */
+func checkpool(ctxt *obj.Link, p *obj.Prog, sz int) int {
+
+ if pool.size >= 0xff0 || immaddr(int32((p.Pc+int64(sz)+4)+4+int64(12+pool.size)-int64(pool.start+8))) == 0 {
+ return flushpool(ctxt, p, 1, 0)
+ } else if p.Link == nil {
+ return flushpool(ctxt, p, 2, 0)
+ }
+ return 0
+}
+
+func flushpool(ctxt *obj.Link, p *obj.Prog, skip int, force int) int {
+ var q *obj.Prog
+
+ if ctxt.Blitrl != nil {
+ if skip != 0 {
+ if false && skip == 1 {
+ fmt.Printf("note: flush literal pool at %x: len=%d ref=%x\n", uint64(p.Pc+4), pool.size, pool.start)
+ }
+ q = ctxt.NewProg()
+ q.As = AB
+ q.To.Type = D_BRANCH
+ q.Pcond = p.Link
+ q.Link = ctxt.Blitrl
+ q.Lineno = p.Lineno
+ ctxt.Blitrl = q
+ } else if !(force != 0) && (p.Pc+int64(12+pool.size)-int64(pool.start) < 2048) { // 12 take into account the maximum nacl literal pool alignment padding size
+ return 0
+ }
+ if ctxt.Headtype == obj.Hnacl && pool.size%16 != 0 {
+ // if pool is not multiple of 16 bytes, add an alignment marker
+ q = ctxt.NewProg()
+
+ q.As = ADATABUNDLEEND
+ ctxt.Elitrl.Link = q
+ ctxt.Elitrl = q
+ }
+
+ ctxt.Elitrl.Link = p.Link
+ p.Link = ctxt.Blitrl
+
+ // BUG(minux): how to correctly handle line number for constant pool entries?
+ // for now, we set line number to the last instruction preceding them at least
+ // this won't bloat the .debug_line tables
+ for ctxt.Blitrl != nil {
+
+ ctxt.Blitrl.Lineno = p.Lineno
+ ctxt.Blitrl = ctxt.Blitrl.Link
+ }
+
+ ctxt.Blitrl = nil /* BUG: should refer back to values until out-of-range */
+ ctxt.Elitrl = nil
+ pool.size = 0
+ pool.start = 0
+ pool.extra = 0
+ return 1
+ }
+
+ return 0
+}
+
+func addpool(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) {
+ var q *obj.Prog
+ var t obj.Prog
+ var c int
+
+ c = aclass(ctxt, a)
+
+ t = zprg
+ t.As = AWORD
+
+ switch c {
+ default:
+ t.To.Offset = a.Offset
+ t.To.Sym = a.Sym
+ t.To.Type = a.Type
+ t.To.Name = a.Name
+
+ if ctxt.Flag_shared != 0 && t.To.Sym != nil {
+ t.Pcrel = p
+ }
+
+ case C_SROREG,
+ C_LOREG,
+ C_ROREG,
+ C_FOREG,
+ C_SOREG,
+ C_HOREG,
+ C_FAUTO,
+ C_SAUTO,
+ C_LAUTO,
+ C_LACON:
+ t.To.Type = D_CONST
+ t.To.Offset = ctxt.Instoffset
+ break
+ }
+
+ if t.Pcrel == nil {
+ for q = ctxt.Blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */
+ if q.Pcrel == nil && q.To == t.To {
+ p.Pcond = q
+ return
+ }
+ }
+ }
+
+ if ctxt.Headtype == obj.Hnacl && pool.size%16 == 0 {
+ // start a new data bundle
+ q = ctxt.NewProg()
+
+ *q = zprg
+ q.As = ADATABUNDLE
+ q.Pc = int64(pool.size)
+ pool.size += 4
+ if ctxt.Blitrl == nil {
+ ctxt.Blitrl = q
+ pool.start = uint32(p.Pc)
+ } else {
+
+ ctxt.Elitrl.Link = q
+ }
+
+ ctxt.Elitrl = q
+ }
+
+ q = ctxt.NewProg()
+ *q = t
+ q.Pc = int64(pool.size)
+
+ if ctxt.Blitrl == nil {
+ ctxt.Blitrl = q
+ pool.start = uint32(p.Pc)
+ } else {
+
+ ctxt.Elitrl.Link = q
+ }
+ ctxt.Elitrl = q
+ pool.size += 4
+
+ p.Pcond = q
+}
+
+func regoff(ctxt *obj.Link, a *obj.Addr) int32 {
+ ctxt.Instoffset = 0
+ aclass(ctxt, a)
+ return int32(ctxt.Instoffset)
+}
+
+func immrot(v uint32) int32 {
+ var i int
+
+ for i = 0; i < 16; i++ {
+ if v&^0xff == 0 {
+ return int32(uint32(int32(i)<<8) | v | 1<<25)
+ }
+ v = v<<2 | v>>30
+ }
+
+ return 0
+}
+
+func immaddr(v int32) int32 {
+ if v >= 0 && v <= 0xfff {
+ return v&0xfff | 1<<24 | 1<<23 /* pre indexing */ /* pre indexing, up */
+ }
+ if v >= -0xfff && v < 0 {
+ return -v&0xfff | 1<<24 /* pre indexing */
+ }
+ return 0
+}
+
+func immfloat(v int32) bool {
+ return v&0xC03 == 0 /* offset will fit in floating-point load/store */
+}
+
+func immhalf(v int32) bool {
+ if v >= 0 && v <= 0xff {
+ return v|1<<24|1<<23 != 0 /* pre indexing */ /* pre indexing, up */
+ }
+ if v >= -0xff && v < 0 {
+ return -v&0xff|1<<24 != 0 /* pre indexing */
+ }
+ return false
+}
+
+func aclass(ctxt *obj.Link, a *obj.Addr) int {
+ var s *obj.LSym
+ var t int
+
+ switch a.Type {
+ case D_NONE:
+ return C_NONE
+
+ case D_REG:
+ return C_REG
+
+ case D_REGREG:
+ return C_REGREG
+
+ case D_REGREG2:
+ return C_REGREG2
+
+ case D_SHIFT:
+ return C_SHIFT
+
+ case D_FREG:
+ return C_FREG
+
+ case D_FPCR:
+ return C_FCR
+
+ case D_OREG:
+ switch a.Name {
+ case D_EXTERN,
+ D_STATIC:
+ if a.Sym == nil || a.Sym.Name == "" {
+ fmt.Printf("null sym external\n")
+ return C_GOK
+ }
+
+ ctxt.Instoffset = 0 // s.b. unused but just in case
+ return C_ADDR
+
+ case D_AUTO:
+ ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
+ t = int(immaddr(int32(ctxt.Instoffset)))
+ if t != 0 {
+ if immhalf(int32(ctxt.Instoffset)) {
+ if immfloat(int32(t)) {
+ return C_HFAUTO
+ }
+ return C_HAUTO
+ }
+
+ if immfloat(int32(t)) {
+ return C_FAUTO
+ }
+ return C_SAUTO
+ }
+
+ return C_LAUTO
+
+ case D_PARAM:
+ ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 4
+ t = int(immaddr(int32(ctxt.Instoffset)))
+ if t != 0 {
+ if immhalf(int32(ctxt.Instoffset)) {
+ if immfloat(int32(t)) {
+ return C_HFAUTO
+ }
+ return C_HAUTO
+ }
+
+ if immfloat(int32(t)) {
+ return C_FAUTO
+ }
+ return C_SAUTO
+ }
+
+ return C_LAUTO
+
+ case D_NONE:
+ ctxt.Instoffset = a.Offset
+ t = int(immaddr(int32(ctxt.Instoffset)))
+ if t != 0 {
+ if immhalf(int32(ctxt.Instoffset)) { /* n.b. that it will also satisfy immrot */
+ if immfloat(int32(t)) {
+ return C_HFOREG
+ }
+ return C_HOREG
+ }
+
+ if immfloat(int32(t)) {
+ return C_FOREG /* n.b. that it will also satisfy immrot */
+ }
+ t = int(immrot(uint32(ctxt.Instoffset)))
+ if t != 0 {
+ return C_SROREG
+ }
+ if immhalf(int32(ctxt.Instoffset)) {
+ return C_HOREG
+ }
+ return C_SOREG
+ }
+
+ t = int(immrot(uint32(ctxt.Instoffset)))
+ if t != 0 {
+ return C_ROREG
+ }
+ return C_LOREG
+ }
+
+ return C_GOK
+
+ case D_PSR:
+ return C_PSR
+
+ case D_OCONST:
+ switch a.Name {
+ case D_EXTERN,
+ D_STATIC:
+ ctxt.Instoffset = 0 // s.b. unused but just in case
+ return C_ADDR
+ }
+
+ return C_GOK
+
+ case D_FCONST:
+ if chipzero5(ctxt, a.U.Dval) >= 0 {
+ return C_ZFCON
+ }
+ if chipfloat5(ctxt, a.U.Dval) >= 0 {
+ return C_SFCON
+ }
+ return C_LFCON
+
+ case D_CONST,
+ D_CONST2:
+ switch a.Name {
+ case D_NONE:
+ ctxt.Instoffset = a.Offset
+ if a.Reg != NREG {
+ return aconsize(ctxt)
+ }
+
+ t = int(immrot(uint32(ctxt.Instoffset)))
+ if t != 0 {
+ return C_RCON
+ }
+ t = int(immrot(uint32(^ctxt.Instoffset)))
+ if t != 0 {
+ return C_NCON
+ }
+ return C_LCON
+
+ case D_EXTERN,
+ D_STATIC:
+ s = a.Sym
+ if s == nil {
+ break
+ }
+ ctxt.Instoffset = 0 // s.b. unused but just in case
+ return C_LCONADDR
+
+ case D_AUTO:
+ ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
+ return aconsize(ctxt)
+
+ case D_PARAM:
+ ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 4
+ return aconsize(ctxt)
+ }
+
+ return C_GOK
+
+ case D_BRANCH:
+ return C_SBRA
+ }
+
+ return C_GOK
+}
+
+func aconsize(ctxt *obj.Link) int {
+ var t int
+
+ t = int(immrot(uint32(ctxt.Instoffset)))
+ if t != 0 {
+ return C_RACON
+ }
+ return C_LACON
+}
+
+func prasm(p *obj.Prog) {
+ fmt.Printf("%v\n", p)
+}
+
+func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
+ var a1 int
+ var a2 int
+ var a3 int
+ var r int
+ var c1 []byte
+ var c3 []byte
+ var o []Optab
+ var e []Optab
+
+ a1 = int(p.Optab)
+ if a1 != 0 {
+ return &optab[a1-1:][0]
+ }
+ a1 = int(p.From.Class)
+ if a1 == 0 {
+ a1 = aclass(ctxt, &p.From) + 1
+ p.From.Class = int8(a1)
+ }
+
+ a1--
+ a3 = int(p.To.Class)
+ if a3 == 0 {
+ a3 = aclass(ctxt, &p.To) + 1
+ p.To.Class = int8(a3)
+ }
+
+ a3--
+ a2 = C_NONE
+ if p.Reg != NREG {
+ a2 = C_REG
+ }
+ r = int(p.As)
+ o = oprange[r].start
+ if o == nil {
+ o = oprange[r].stop /* just generate an error */
+ }
+
+ if false { /*debug['O']*/
+ fmt.Printf("oplook %v %v %v %v\n", Aconv(int(p.As)), DRconv(a1), DRconv(a2), DRconv(a3))
+ fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type)
+ }
+
+ e = oprange[r].stop
+ c1 = xcmp[a1][:]
+ c3 = xcmp[a3][:]
+ for ; -cap(o) < -cap(e); o = o[1:] {
+ if int(o[0].a2) == a2 {
+ if c1[o[0].a1] != 0 {
+ if c3[o[0].a3] != 0 {
+ p.Optab = uint16((-cap(o) + cap(optab)) + 1)
+ return &o[0]
+ }
+ }
+ }
+ }
+
+ ctxt.Diag("illegal combination %v; %v %v %v, %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), p.From.Type, p.To.Type)
+ ctxt.Diag("from %d %d to %d %d\n", p.From.Type, p.From.Name, p.To.Type, p.To.Name)
+ prasm(p)
+ if o == nil {
+ o = optab
+ }
+ return &o[0]
+}
+
+func cmp(a int, b int) bool {
+ if a == b {
+ return true
+ }
+ switch a {
+ case C_LCON:
+ if b == C_RCON || b == C_NCON {
+ return true
+ }
+
+ case C_LACON:
+ if b == C_RACON {
+ return true
+ }
+
+ case C_LFCON:
+ if b == C_ZFCON || b == C_SFCON {
+ return true
+ }
+
+ case C_HFAUTO:
+ return b == C_HAUTO || b == C_FAUTO
+
+ case C_FAUTO,
+ C_HAUTO:
+ return b == C_HFAUTO
+
+ case C_SAUTO:
+ return cmp(C_HFAUTO, b)
+
+ case C_LAUTO:
+ return cmp(C_SAUTO, b)
+
+ case C_HFOREG:
+ return b == C_HOREG || b == C_FOREG
+
+ case C_FOREG,
+ C_HOREG:
+ return b == C_HFOREG
+
+ case C_SROREG:
+ return cmp(C_SOREG, b) || cmp(C_ROREG, b)
+
+ case C_SOREG,
+ C_ROREG:
+ return b == C_SROREG || cmp(C_HFOREG, b)
+
+ case C_LOREG:
+ return cmp(C_SROREG, b)
+
+ case C_LBRA:
+ if b == C_SBRA {
+ return true
+ }
+
+ case C_HREG:
+ return cmp(C_SP, b) || cmp(C_PC, b)
+ }
+
+ return false
+}
+
+type ocmp []Optab
+
+func (x ocmp) Len() int {
+ return len(x)
+}
+
+func (x ocmp) Swap(i, j int) {
+ x[i], x[j] = x[j], x[i]
+}
+
+func (x ocmp) Less(i, j int) bool {
+ var p1 *Optab
+ var p2 *Optab
+ var n int
+
+ p1 = &x[i]
+ p2 = &x[j]
+ n = int(p1.as) - int(p2.as)
+ if n != 0 {
+ return n < 0
+ }
+ n = int(p1.a1) - int(p2.a1)
+ if n != 0 {
+ return n < 0
+ }
+ n = int(p1.a2) - int(p2.a2)
+ if n != 0 {
+ return n < 0
+ }
+ n = int(p1.a3) - int(p2.a3)
+ if n != 0 {
+ return n < 0
+ }
+ return false
+}
+
+func buildop(ctxt *obj.Link) {
+ var i int
+ var n int
+ var r int
+
+ for i = 0; i < C_GOK; i++ {
+ for n = 0; n < C_GOK; n++ {
+ if cmp(n, i) {
+ xcmp[i][n] = 1
+ }
+ }
+ }
+ for n = 0; optab[n].as != AXXX; n++ {
+ if optab[n].flag&LPCREL != 0 {
+ if ctxt.Flag_shared != 0 {
+ optab[n].size += int8(optab[n].pcrelsiz)
+ } else {
+
+ optab[n].flag &^= LPCREL
+ }
+ }
+ }
+
+ sort.Sort(ocmp(optab[:n]))
+ for i = 0; i < n; i++ {
+ r = int(optab[i].as)
+ oprange[r].start = optab[i:]
+ for int(optab[i].as) == r {
+ i++
+ }
+ oprange[r].stop = optab[i:]
+ i--
+
+ switch r {
+ default:
+ ctxt.Diag("unknown op in build: %v", Aconv(r))
+ log.Fatalf("bad code")
+
+ case AADD:
+ oprange[AAND] = oprange[r]
+ oprange[AEOR] = oprange[r]
+ oprange[ASUB] = oprange[r]
+ oprange[ARSB] = oprange[r]
+ oprange[AADC] = oprange[r]
+ oprange[ASBC] = oprange[r]
+ oprange[ARSC] = oprange[r]
+ oprange[AORR] = oprange[r]
+ oprange[ABIC] = oprange[r]
+
+ case ACMP:
+ oprange[ATEQ] = oprange[r]
+ oprange[ACMN] = oprange[r]
+
+ case AMVN:
+ break
+
+ case ABEQ:
+ oprange[ABNE] = oprange[r]
+ oprange[ABCS] = oprange[r]
+ oprange[ABHS] = oprange[r]
+ oprange[ABCC] = oprange[r]
+ oprange[ABLO] = oprange[r]
+ oprange[ABMI] = oprange[r]
+ oprange[ABPL] = oprange[r]
+ oprange[ABVS] = oprange[r]
+ oprange[ABVC] = oprange[r]
+ oprange[ABHI] = oprange[r]
+ oprange[ABLS] = oprange[r]
+ oprange[ABGE] = oprange[r]
+ oprange[ABLT] = oprange[r]
+ oprange[ABGT] = oprange[r]
+ oprange[ABLE] = oprange[r]
+
+ case ASLL:
+ oprange[ASRL] = oprange[r]
+ oprange[ASRA] = oprange[r]
+
+ case AMUL:
+ oprange[AMULU] = oprange[r]
+
+ case ADIV:
+ oprange[AMOD] = oprange[r]
+ oprange[AMODU] = oprange[r]
+ oprange[ADIVU] = oprange[r]
+
+ case AMOVW,
+ AMOVB,
+ AMOVBS,
+ AMOVBU,
+ AMOVH,
+ AMOVHS,
+ AMOVHU:
+ break
+
+ case ASWPW:
+ oprange[ASWPBU] = oprange[r]
+
+ case AB,
+ ABL,
+ ABX,
+ ABXRET,
+ ADUFFZERO,
+ ADUFFCOPY,
+ ASWI,
+ AWORD,
+ AMOVM,
+ ARFE,
+ ATEXT,
+ AUSEFIELD,
+ ACASE,
+ ABCASE,
+ ATYPE:
+ break
+
+ case AADDF:
+ oprange[AADDD] = oprange[r]
+ oprange[ASUBF] = oprange[r]
+ oprange[ASUBD] = oprange[r]
+ oprange[AMULF] = oprange[r]
+ oprange[AMULD] = oprange[r]
+ oprange[ADIVF] = oprange[r]
+ oprange[ADIVD] = oprange[r]
+ oprange[ASQRTF] = oprange[r]
+ oprange[ASQRTD] = oprange[r]
+ oprange[AMOVFD] = oprange[r]
+ oprange[AMOVDF] = oprange[r]
+ oprange[AABSF] = oprange[r]
+ oprange[AABSD] = oprange[r]
+
+ case ACMPF:
+ oprange[ACMPD] = oprange[r]
+
+ case AMOVF:
+ oprange[AMOVD] = oprange[r]
+
+ case AMOVFW:
+ oprange[AMOVDW] = oprange[r]
+
+ case AMOVWF:
+ oprange[AMOVWD] = oprange[r]
+
+ case AMULL:
+ oprange[AMULAL] = oprange[r]
+ oprange[AMULLU] = oprange[r]
+ oprange[AMULALU] = oprange[r]
+
+ case AMULWT:
+ oprange[AMULWB] = oprange[r]
+
+ case AMULAWT:
+ oprange[AMULAWB] = oprange[r]
+
+ case AMULA,
+ ALDREX,
+ ASTREX,
+ ALDREXD,
+ ASTREXD,
+ ATST,
+ APLD,
+ AUNDEF,
+ ACLZ,
+ AFUNCDATA,
+ APCDATA,
+ ANOP,
+ ADATABUNDLE,
+ ADATABUNDLEEND:
+ break
+ }
+ }
+}
+
+func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
+ var o1 uint32
+ var o2 uint32
+ var o3 uint32
+ var o4 uint32
+ var o5 uint32
+ var o6 uint32
+ var v int32
+ var r int
+ var rf int
+ var rt int
+ var rt2 int
+ var rel *obj.Reloc
+
+ ctxt.Printp = p
+ o1 = 0
+ o2 = 0
+ o3 = 0
+ o4 = 0
+ o5 = 0
+ o6 = 0
+ ctxt.Armsize += int32(o.size)
+ if false { /*debug['P']*/
+ fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_)
+ }
+ switch o.type_ {
+ default:
+ ctxt.Diag("unknown asm %d", o.type_)
+ prasm(p)
+
+ case 0: /* pseudo ops */
+ if false { /*debug['G']*/
+ fmt.Printf("%x: %s: arm %d\n", uint32(p.Pc), p.From.Sym.Name, p.From.Sym.Fnptr)
+ }
+
+ case 1: /* op R,[R],R */
+ o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+ rf = int(p.From.Reg)
+ rt = int(p.To.Reg)
+ r = int(p.Reg)
+ if p.To.Type == D_NONE {
+ rt = 0
+ }
+ if p.As == AMOVB || p.As == AMOVH || p.As == AMOVW || p.As == AMVN {
+ r = 0
+ } else if r == NREG {
+ r = rt
+ }
+ o1 |= uint32(rf) | uint32(r)<<16 | uint32(rt)<<12
+
+ case 2: /* movbu $I,[R],R */
+ aclass(ctxt, &p.From)
+
+ o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+ o1 |= uint32(immrot(uint32(ctxt.Instoffset)))
+ rt = int(p.To.Reg)
+ r = int(p.Reg)
+ if p.To.Type == D_NONE {
+ rt = 0
+ }
+ if p.As == AMOVW || p.As == AMVN {
+ r = 0
+ } else if r == NREG {
+ r = rt
+ }
+ o1 |= uint32(r)<<16 | uint32(rt)<<12
+
+ case 3: /* add R<<[IR],[R],R */
+ o1 = mov(ctxt, p)
+
+ case 4: /* add $I,[R],R */
+ aclass(ctxt, &p.From)
+
+ o1 = oprrr(ctxt, AADD, int(p.Scond))
+ o1 |= uint32(immrot(uint32(ctxt.Instoffset)))
+ r = int(p.From.Reg)
+ if r == NREG {
+ r = int(o.param)
+ }
+ o1 |= uint32(r) << 16
+ o1 |= uint32(p.To.Reg) << 12
+
+ case 5: /* bra s */
+ o1 = opbra(ctxt, int(p.As), int(p.Scond))
+
+ v = -8
+ if p.To.Sym != nil {
+ rel = obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 4
+ rel.Sym = p.To.Sym
+ v += int32(p.To.Offset)
+ rel.Add = int64(o1) | (int64(v)>>2)&0xffffff
+ rel.Type = obj.R_CALLARM
+ break
+ }
+
+ if p.Pcond != nil {
+ v = int32((p.Pcond.Pc - ctxt.Pc) - 8)
+ }
+ o1 |= (uint32(v) >> 2) & 0xffffff
+
+ case 6: /* b ,O(R) -> add $O,R,PC */
+ aclass(ctxt, &p.To)
+
+ o1 = oprrr(ctxt, AADD, int(p.Scond))
+ o1 |= uint32(immrot(uint32(ctxt.Instoffset)))
+ o1 |= uint32(p.To.Reg) << 16
+ o1 |= REGPC << 12
+
+ case 7: /* bl (R) -> blx R */
+ aclass(ctxt, &p.To)
+
+ if ctxt.Instoffset != 0 {
+ ctxt.Diag("%v: doesn't support BL offset(REG) where offset != 0", p)
+ }
+ o1 = oprrr(ctxt, ABL, int(p.Scond))
+ o1 |= uint32(p.To.Reg)
+ rel = obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 0
+ rel.Type = obj.R_CALLIND
+
+ case 8: /* sll $c,[R],R -> mov (R<<$c),R */
+ aclass(ctxt, &p.From)
+
+ o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+ r = int(p.Reg)
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+ o1 |= uint32(r)
+ o1 |= uint32((ctxt.Instoffset & 31) << 7)
+ o1 |= uint32(p.To.Reg) << 12
+
+ case 9: /* sll R,[R],R -> mov (R<<R),R */
+ o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+ r = int(p.Reg)
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+ o1 |= uint32(r)
+ o1 |= uint32(p.From.Reg)<<8 | 1<<4
+ o1 |= uint32(p.To.Reg) << 12
+
+ case 10: /* swi [$con] */
+ o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+ if p.To.Type != D_NONE {
+ aclass(ctxt, &p.To)
+ o1 |= uint32(ctxt.Instoffset & 0xffffff)
+ }
+
+ case 11: /* word */
+ aclass(ctxt, &p.To)
+
+ o1 = uint32(ctxt.Instoffset)
+ if p.To.Sym != nil {
+ // This case happens with words generated
+ // in the PC stream as part of the literal pool.
+ rel = obj.Addrel(ctxt.Cursym)
+
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 4
+ rel.Sym = p.To.Sym
+ rel.Add = p.To.Offset
+
+ // runtime.tlsg is special.
+ // Its "address" is the offset from the TLS thread pointer
+ // to the thread-local g and m pointers.
+ // Emit a TLS relocation instead of a standard one.
+ if rel.Sym == ctxt.Tlsg {
+
+ rel.Type = obj.R_TLS
+ if ctxt.Flag_shared != 0 {
+ rel.Add += ctxt.Pc - p.Pcrel.Pc - 8 - int64(rel.Siz)
+ }
+ rel.Xadd = rel.Add
+ rel.Xsym = rel.Sym
+ } else if ctxt.Flag_shared != 0 {
+ rel.Type = obj.R_PCREL
+ rel.Add += ctxt.Pc - p.Pcrel.Pc - 8
+ } else {
+
+ rel.Type = obj.R_ADDR
+ }
+ o1 = 0
+ }
+
+ case 12: /* movw $lcon, reg */
+ o1 = omvl(ctxt, p, &p.From, int(p.To.Reg))
+
+ if o.flag&LPCREL != 0 {
+ o2 = oprrr(ctxt, AADD, int(p.Scond)) | uint32(p.To.Reg) | REGPC<<16 | uint32(p.To.Reg)<<12
+ }
+
+ case 13: /* op $lcon, [R], R */
+ o1 = omvl(ctxt, p, &p.From, REGTMP)
+
+ if !(o1 != 0) {
+ break
+ }
+ o2 = oprrr(ctxt, int(p.As), int(p.Scond))
+ o2 |= REGTMP
+ r = int(p.Reg)
+ if p.As == AMOVW || p.As == AMVN {
+ r = 0
+ } else if r == NREG {
+ r = int(p.To.Reg)
+ }
+ o2 |= uint32(r) << 16
+ if p.To.Type != D_NONE {
+ o2 |= uint32(p.To.Reg) << 12
+ }
+
+ case 14: /* movb/movbu/movh/movhu R,R */
+ o1 = oprrr(ctxt, ASLL, int(p.Scond))
+
+ if p.As == AMOVBU || p.As == AMOVHU {
+ o2 = oprrr(ctxt, ASRL, int(p.Scond))
+ } else {
+
+ o2 = oprrr(ctxt, ASRA, int(p.Scond))
+ }
+
+ r = int(p.To.Reg)
+ o1 |= uint32(p.From.Reg) | uint32(r)<<12
+ o2 |= uint32(r) | uint32(r)<<12
+ if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU {
+ o1 |= 24 << 7
+ o2 |= 24 << 7
+ } else {
+
+ o1 |= 16 << 7
+ o2 |= 16 << 7
+ }
+
+ case 15: /* mul r,[r,]r */
+ o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+ rf = int(p.From.Reg)
+ rt = int(p.To.Reg)
+ r = int(p.Reg)
+ if r == NREG {
+ r = rt
+ }
+ if rt == r {
+ r = rf
+ rf = rt
+ }
+
+ if false {
+ if rt == r || rf == REGPC || r == REGPC || rt == REGPC {
+ ctxt.Diag("bad registers in MUL")
+ prasm(p)
+ }
+ }
+
+ o1 |= uint32(rf)<<8 | uint32(r) | uint32(rt)<<16
+
+ case 16: /* div r,[r,]r */
+ o1 = 0xf << 28
+
+ o2 = 0
+
+ case 17:
+ o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+ rf = int(p.From.Reg)
+ rt = int(p.To.Reg)
+ rt2 = int(p.To.Offset)
+ r = int(p.Reg)
+ o1 |= uint32(rf)<<8 | uint32(r) | uint32(rt)<<16 | uint32(rt2)<<12
+
+ case 20: /* mov/movb/movbu R,O(R) */
+ aclass(ctxt, &p.To)
+
+ r = int(p.To.Reg)
+ if r == NREG {
+ r = int(o.param)
+ }
+ o1 = osr(ctxt, int(p.As), int(p.From.Reg), int32(ctxt.Instoffset), r, int(p.Scond))
+
+ case 21: /* mov/movbu O(R),R -> lr */
+ aclass(ctxt, &p.From)
+
+ r = int(p.From.Reg)
+ if r == NREG {
+ r = int(o.param)
+ }
+ o1 = olr(ctxt, int32(ctxt.Instoffset), r, int(p.To.Reg), int(p.Scond))
+ if p.As != AMOVW {
+ o1 |= 1 << 22
+ }
+
+ case 30: /* mov/movb/movbu R,L(R) */
+ o1 = omvl(ctxt, p, &p.To, REGTMP)
+
+ if !(o1 != 0) {
+ break
+ }
+ r = int(p.To.Reg)
+ if r == NREG {
+ r = int(o.param)
+ }
+ o2 = osrr(ctxt, int(p.From.Reg), REGTMP, r, int(p.Scond))
+ if p.As != AMOVW {
+ o2 |= 1 << 22
+ }
+
+ case 31: /* mov/movbu L(R),R -> lr[b] */
+ o1 = omvl(ctxt, p, &p.From, REGTMP)
+
+ if !(o1 != 0) {
+ break
+ }
+ r = int(p.From.Reg)
+ if r == NREG {
+ r = int(o.param)
+ }
+ o2 = olrr(ctxt, REGTMP, r, int(p.To.Reg), int(p.Scond))
+ if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB {
+ o2 |= 1 << 22
+ }
+
+ case 34: /* mov $lacon,R */
+ o1 = omvl(ctxt, p, &p.From, REGTMP)
+
+ if !(o1 != 0) {
+ break
+ }
+
+ o2 = oprrr(ctxt, AADD, int(p.Scond))
+ o2 |= REGTMP
+ r = int(p.From.Reg)
+ if r == NREG {
+ r = int(o.param)
+ }
+ o2 |= uint32(r) << 16
+ if p.To.Type != D_NONE {
+ o2 |= uint32(p.To.Reg) << 12
+ }
+
+ case 35: /* mov PSR,R */
+ o1 = 2<<23 | 0xf<<16 | 0<<0
+
+ o1 |= (uint32(p.Scond) & C_SCOND) << 28
+ o1 |= (uint32(p.From.Reg) & 1) << 22
+ o1 |= uint32(p.To.Reg) << 12
+
+ case 36: /* mov R,PSR */
+ o1 = 2<<23 | 0x29f<<12 | 0<<4
+
+ if p.Scond&C_FBIT != 0 {
+ o1 ^= 0x010 << 12
+ }
+ o1 |= (uint32(p.Scond) & C_SCOND) << 28
+ o1 |= (uint32(p.To.Reg) & 1) << 22
+ o1 |= uint32(p.From.Reg) << 0
+
+ case 37: /* mov $con,PSR */
+ aclass(ctxt, &p.From)
+
+ o1 = 2<<23 | 0x29f<<12 | 0<<4
+ if p.Scond&C_FBIT != 0 {
+ o1 ^= 0x010 << 12
+ }
+ o1 |= (uint32(p.Scond) & C_SCOND) << 28
+ o1 |= uint32(immrot(uint32(ctxt.Instoffset)))
+ o1 |= (uint32(p.To.Reg) & 1) << 22
+ o1 |= uint32(p.From.Reg) << 0
+
+ case 38,
+ 39:
+ switch o.type_ {
+ case 38: /* movm $con,oreg -> stm */
+ o1 = 0x4 << 25
+
+ o1 |= uint32(p.From.Offset & 0xffff)
+ o1 |= uint32(p.To.Reg) << 16
+ aclass(ctxt, &p.To)
+
+ case 39: /* movm oreg,$con -> ldm */
+ o1 = 0x4<<25 | 1<<20
+
+ o1 |= uint32(p.To.Offset & 0xffff)
+ o1 |= uint32(p.From.Reg) << 16
+ aclass(ctxt, &p.From)
+ break
+ }
+
+ if ctxt.Instoffset != 0 {
+ ctxt.Diag("offset must be zero in MOVM; %v", p)
+ }
+ o1 |= (uint32(p.Scond) & C_SCOND) << 28
+ if p.Scond&C_PBIT != 0 {
+ o1 |= 1 << 24
+ }
+ if p.Scond&C_UBIT != 0 {
+ o1 |= 1 << 23
+ }
+ if p.Scond&C_SBIT != 0 {
+ o1 |= 1 << 22
+ }
+ if p.Scond&C_WBIT != 0 {
+ o1 |= 1 << 21
+ }
+
+ case 40: /* swp oreg,reg,reg */
+ aclass(ctxt, &p.From)
+
+ if ctxt.Instoffset != 0 {
+ ctxt.Diag("offset must be zero in SWP")
+ }
+ o1 = 0x2<<23 | 0x9<<4
+ if p.As != ASWPW {
+ o1 |= 1 << 22
+ }
+ o1 |= uint32(p.From.Reg) << 16
+ o1 |= uint32(p.Reg) << 0
+ o1 |= uint32(p.To.Reg) << 12
+ o1 |= (uint32(p.Scond) & C_SCOND) << 28
+
+ case 41: /* rfe -> movm.s.w.u 0(r13),[r15] */
+ o1 = 0xe8fd8000
+
+ case 50: /* floating point store */
+ v = regoff(ctxt, &p.To)
+
+ r = int(p.To.Reg)
+ if r == NREG {
+ r = int(o.param)
+ }
+ o1 = ofsr(ctxt, int(p.As), int(p.From.Reg), v, r, int(p.Scond), p)
+
+ case 51: /* floating point load */
+ v = regoff(ctxt, &p.From)
+
+ r = int(p.From.Reg)
+ if r == NREG {
+ r = int(o.param)
+ }
+ o1 = ofsr(ctxt, int(p.As), int(p.To.Reg), v, r, int(p.Scond), p) | 1<<20
+
+ case 52: /* floating point store, int32 offset UGLY */
+ o1 = omvl(ctxt, p, &p.To, REGTMP)
+
+ if !(o1 != 0) {
+ break
+ }
+ r = int(p.To.Reg)
+ if r == NREG {
+ r = int(o.param)
+ }
+ o2 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP<<12 | REGTMP<<16 | uint32(r)
+ o3 = ofsr(ctxt, int(p.As), int(p.From.Reg), 0, REGTMP, int(p.Scond), p)
+
+ case 53: /* floating point load, int32 offset UGLY */
+ o1 = omvl(ctxt, p, &p.From, REGTMP)
+
+ if !(o1 != 0) {
+ break
+ }
+ r = int(p.From.Reg)
+ if r == NREG {
+ r = int(o.param)
+ }
+ o2 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP<<12 | REGTMP<<16 | uint32(r)
+ o3 = ofsr(ctxt, int(p.As), int(p.To.Reg), 0, REGTMP, int(p.Scond), p) | 1<<20
+
+ case 54: /* floating point arith */
+ o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+ rf = int(p.From.Reg)
+ rt = int(p.To.Reg)
+ r = int(p.Reg)
+ if r == NREG {
+ r = rt
+ if p.As == AMOVF || p.As == AMOVD || p.As == AMOVFD || p.As == AMOVDF || p.As == ASQRTF || p.As == ASQRTD || p.As == AABSF || p.As == AABSD {
+ r = 0
+ }
+ }
+
+ o1 |= uint32(rf) | uint32(r)<<16 | uint32(rt)<<12
+
+ case 56: /* move to FP[CS]R */
+ o1 = (uint32(p.Scond)&C_SCOND)<<28 | 0xe<<24 | 1<<8 | 1<<4
+
+ o1 |= (uint32(p.To.Reg)+1)<<21 | uint32(p.From.Reg)<<12
+
+ case 57: /* move from FP[CS]R */
+ o1 = (uint32(p.Scond)&C_SCOND)<<28 | 0xe<<24 | 1<<8 | 1<<4
+
+ o1 |= (uint32(p.From.Reg)+1)<<21 | uint32(p.To.Reg)<<12 | 1<<20
+
+ case 58: /* movbu R,R */
+ o1 = oprrr(ctxt, AAND, int(p.Scond))
+
+ o1 |= uint32(immrot(0xff))
+ rt = int(p.To.Reg)
+ r = int(p.From.Reg)
+ if p.To.Type == D_NONE {
+ rt = 0
+ }
+ if r == NREG {
+ r = rt
+ }
+ o1 |= uint32(r)<<16 | uint32(rt)<<12
+
+ case 59: /* movw/bu R<<I(R),R -> ldr indexed */
+ if p.From.Reg == NREG {
+
+ if p.As != AMOVW {
+ ctxt.Diag("byte MOV from shifter operand")
+ }
+ o1 = mov(ctxt, p)
+ break
+ }
+
+ if p.From.Offset&(1<<4) != 0 {
+ ctxt.Diag("bad shift in LDR")
+ }
+ o1 = olrr(ctxt, int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
+ if p.As == AMOVBU {
+ o1 |= 1 << 22
+ }
+
+ case 60: /* movb R(R),R -> ldrsb indexed */
+ if p.From.Reg == NREG {
+
+ ctxt.Diag("byte MOV from shifter operand")
+ o1 = mov(ctxt, p)
+ break
+ }
+
+ if p.From.Offset&(^0xf) != 0 {
+ ctxt.Diag("bad shift in LDRSB")
+ }
+ o1 = olhrr(ctxt, int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
+ o1 ^= 1<<5 | 1<<6
+
+ case 61: /* movw/b/bu R,R<<[IR](R) -> str indexed */
+ if p.To.Reg == NREG {
+
+ ctxt.Diag("MOV to shifter operand")
+ }
+ o1 = osrr(ctxt, int(p.From.Reg), int(p.To.Offset), int(p.To.Reg), int(p.Scond))
+ if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU {
+ o1 |= 1 << 22
+ }
+
+ case 62: /* case R -> movw R<<2(PC),PC */
+ if o.flag&LPCREL != 0 {
+
+ o1 = oprrr(ctxt, AADD, int(p.Scond)) | uint32(immrot(1)) | uint32(p.From.Reg)<<16 | REGTMP<<12
+ o2 = olrr(ctxt, REGTMP, REGPC, REGTMP, int(p.Scond))
+ o2 |= 2 << 7
+ o3 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP | REGPC<<16 | REGPC<<12
+ } else {
+
+ o1 = olrr(ctxt, int(p.From.Reg), REGPC, REGPC, int(p.Scond))
+ o1 |= 2 << 7
+ }
+
+ case 63: /* bcase */
+ if p.Pcond != nil {
+
+ rel = obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 4
+ if p.To.Sym != nil && p.To.Sym.Type != 0 {
+ rel.Sym = p.To.Sym
+ rel.Add = p.To.Offset
+ } else {
+
+ rel.Sym = ctxt.Cursym
+ rel.Add = p.Pcond.Pc
+ }
+
+ if o.flag&LPCREL != 0 {
+ rel.Type = obj.R_PCREL
+ rel.Add += ctxt.Pc - p.Pcrel.Pc - 16 + int64(rel.Siz)
+ } else {
+
+ rel.Type = obj.R_ADDR
+ }
+ o1 = 0
+ }
+
+ /* reloc ops */
+ case 64: /* mov/movb/movbu R,addr */
+ o1 = omvl(ctxt, p, &p.To, REGTMP)
+
+ if !(o1 != 0) {
+ break
+ }
+ o2 = osr(ctxt, int(p.As), int(p.From.Reg), 0, REGTMP, int(p.Scond))
+ if o.flag&LPCREL != 0 {
+ o3 = o2
+ o2 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP | REGPC<<16 | REGTMP<<12
+ }
+
+ case 65: /* mov/movbu addr,R */
+ o1 = omvl(ctxt, p, &p.From, REGTMP)
+
+ if !(o1 != 0) {
+ break
+ }
+ o2 = olr(ctxt, 0, REGTMP, int(p.To.Reg), int(p.Scond))
+ if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB {
+ o2 |= 1 << 22
+ }
+ if o.flag&LPCREL != 0 {
+ o3 = o2
+ o2 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP | REGPC<<16 | REGTMP<<12
+ }
+
+ case 68: /* floating point store -> ADDR */
+ o1 = omvl(ctxt, p, &p.To, REGTMP)
+
+ if !(o1 != 0) {
+ break
+ }
+ o2 = ofsr(ctxt, int(p.As), int(p.From.Reg), 0, REGTMP, int(p.Scond), p)
+ if o.flag&LPCREL != 0 {
+ o3 = o2
+ o2 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP | REGPC<<16 | REGTMP<<12
+ }
+
+ case 69: /* floating point load <- ADDR */
+ o1 = omvl(ctxt, p, &p.From, REGTMP)
+
+ if !(o1 != 0) {
+ break
+ }
+ o2 = ofsr(ctxt, int(p.As), int(p.To.Reg), 0, REGTMP, int(p.Scond), p) | 1<<20
+ if o.flag&LPCREL != 0 {
+ o3 = o2
+ o2 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP | REGPC<<16 | REGTMP<<12
+ }
+
+ /* ArmV4 ops: */
+ case 70: /* movh/movhu R,O(R) -> strh */
+ aclass(ctxt, &p.To)
+
+ r = int(p.To.Reg)
+ if r == NREG {
+ r = int(o.param)
+ }
+ o1 = oshr(ctxt, int(p.From.Reg), int32(ctxt.Instoffset), r, int(p.Scond))
+
+ case 71: /* movb/movh/movhu O(R),R -> ldrsb/ldrsh/ldrh */
+ aclass(ctxt, &p.From)
+
+ r = int(p.From.Reg)
+ if r == NREG {
+ r = int(o.param)
+ }
+ o1 = olhr(ctxt, int32(ctxt.Instoffset), r, int(p.To.Reg), int(p.Scond))
+ if p.As == AMOVB || p.As == AMOVBS {
+ o1 ^= 1<<5 | 1<<6
+ } else if p.As == AMOVH || p.As == AMOVHS {
+ o1 ^= (1 << 6)
+ }
+
+ case 72: /* movh/movhu R,L(R) -> strh */
+ o1 = omvl(ctxt, p, &p.To, REGTMP)
+
+ if !(o1 != 0) {
+ break
+ }
+ r = int(p.To.Reg)
+ if r == NREG {
+ r = int(o.param)
+ }
+ o2 = oshrr(ctxt, int(p.From.Reg), REGTMP, r, int(p.Scond))
+
+ case 73: /* movb/movh/movhu L(R),R -> ldrsb/ldrsh/ldrh */
+ o1 = omvl(ctxt, p, &p.From, REGTMP)
+
+ if !(o1 != 0) {
+ break
+ }
+ r = int(p.From.Reg)
+ if r == NREG {
+ r = int(o.param)
+ }
+ o2 = olhrr(ctxt, REGTMP, r, int(p.To.Reg), int(p.Scond))
+ if p.As == AMOVB || p.As == AMOVBS {
+ o2 ^= 1<<5 | 1<<6
+ } else if p.As == AMOVH || p.As == AMOVHS {
+ o2 ^= (1 << 6)
+ }
+
+ case 74: /* bx $I */
+ ctxt.Diag("ABX $I")
+
+ case 75: /* bx O(R) */
+ aclass(ctxt, &p.To)
+
+ if ctxt.Instoffset != 0 {
+ ctxt.Diag("non-zero offset in ABX")
+ }
+
+ /*
+ o1 = oprrr(ctxt, AADD, p->scond) | immrot(0) | (REGPC<<16) | (REGLINK<<12); // mov PC, LR
+ o2 = ((p->scond&C_SCOND)<<28) | (0x12fff<<8) | (1<<4) | p->to.reg; // BX R
+ */
+ // p->to.reg may be REGLINK
+ o1 = oprrr(ctxt, AADD, int(p.Scond))
+
+ o1 |= uint32(immrot(uint32(ctxt.Instoffset)))
+ o1 |= uint32(p.To.Reg) << 16
+ o1 |= REGTMP << 12
+ o2 = oprrr(ctxt, AADD, int(p.Scond)) | uint32(immrot(0)) | REGPC<<16 | REGLINK<<12 // mov PC, LR
+ o3 = (uint32(p.Scond)&C_SCOND)<<28 | 0x12fff<<8 | 1<<4 | REGTMP // BX Rtmp
+
+ case 76: /* bx O(R) when returning from fn*/
+ ctxt.Diag("ABXRET")
+
+ case 77: /* ldrex oreg,reg */
+ aclass(ctxt, &p.From)
+
+ if ctxt.Instoffset != 0 {
+ ctxt.Diag("offset must be zero in LDREX")
+ }
+ o1 = 0x19<<20 | 0xf9f
+ o1 |= uint32(p.From.Reg) << 16
+ o1 |= uint32(p.To.Reg) << 12
+ o1 |= (uint32(p.Scond) & C_SCOND) << 28
+
+ case 78: /* strex reg,oreg,reg */
+ aclass(ctxt, &p.From)
+
+ if ctxt.Instoffset != 0 {
+ ctxt.Diag("offset must be zero in STREX")
+ }
+ o1 = 0x18<<20 | 0xf90
+ o1 |= uint32(p.From.Reg) << 16
+ o1 |= uint32(p.Reg) << 0
+ o1 |= uint32(p.To.Reg) << 12
+ o1 |= (uint32(p.Scond) & C_SCOND) << 28
+
+ case 80: /* fmov zfcon,freg */
+ if p.As == AMOVD {
+
+ o1 = 0xeeb00b00 // VMOV imm 64
+ o2 = oprrr(ctxt, ASUBD, int(p.Scond))
+ } else {
+
+ o1 = 0x0eb00a00 // VMOV imm 32
+ o2 = oprrr(ctxt, ASUBF, int(p.Scond))
+ }
+
+ v = 0x70 // 1.0
+ r = int(p.To.Reg)
+
+ // movf $1.0, r
+ o1 |= (uint32(p.Scond) & C_SCOND) << 28
+
+ o1 |= uint32(r) << 12
+ o1 |= (uint32(v) & 0xf) << 0
+ o1 |= (uint32(v) & 0xf0) << 12
+
+ // subf r,r,r
+ o2 |= uint32(r) | uint32(r)<<16 | uint32(r)<<12
+
+ case 81: /* fmov sfcon,freg */
+ o1 = 0x0eb00a00 // VMOV imm 32
+ if p.As == AMOVD {
+ o1 = 0xeeb00b00 // VMOV imm 64
+ }
+ o1 |= (uint32(p.Scond) & C_SCOND) << 28
+ o1 |= uint32(p.To.Reg) << 12
+ v = int32(chipfloat5(ctxt, p.From.U.Dval))
+ o1 |= (uint32(v) & 0xf) << 0
+ o1 |= (uint32(v) & 0xf0) << 12
+
+ case 82: /* fcmp freg,freg, */
+ o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+ o1 |= uint32(p.Reg)<<12 | uint32(p.From.Reg)<<0
+ o2 = 0x0ef1fa10 // VMRS R15
+ o2 |= (uint32(p.Scond) & C_SCOND) << 28
+
+ case 83: /* fcmp freg,, */
+ o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+ o1 |= uint32(p.From.Reg)<<12 | 1<<16
+ o2 = 0x0ef1fa10 // VMRS R15
+ o2 |= (uint32(p.Scond) & C_SCOND) << 28
+
+ case 84: /* movfw freg,freg - truncate float-to-fix */
+ o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+ o1 |= uint32(p.From.Reg) << 0
+ o1 |= uint32(p.To.Reg) << 12
+
+ case 85: /* movwf freg,freg - fix-to-float */
+ o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+ o1 |= uint32(p.From.Reg) << 0
+ o1 |= uint32(p.To.Reg) << 12
+
+ // macro for movfw freg,FTMP; movw FTMP,reg
+ case 86: /* movfw freg,reg - truncate float-to-fix */
+ o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+ o1 |= uint32(p.From.Reg) << 0
+ o1 |= FREGTMP << 12
+ o2 = oprrr(ctxt, AMOVFW+AEND, int(p.Scond))
+ o2 |= FREGTMP << 16
+ o2 |= uint32(p.To.Reg) << 12
+
+ // macro for movw reg,FTMP; movwf FTMP,freg
+ case 87: /* movwf reg,freg - fix-to-float */
+ o1 = oprrr(ctxt, AMOVWF+AEND, int(p.Scond))
+
+ o1 |= uint32(p.From.Reg) << 12
+ o1 |= FREGTMP << 16
+ o2 = oprrr(ctxt, int(p.As), int(p.Scond))
+ o2 |= FREGTMP << 0
+ o2 |= uint32(p.To.Reg) << 12
+
+ case 88: /* movw reg,freg */
+ o1 = oprrr(ctxt, AMOVWF+AEND, int(p.Scond))
+
+ o1 |= uint32(p.From.Reg) << 12
+ o1 |= uint32(p.To.Reg) << 16
+
+ case 89: /* movw freg,reg */
+ o1 = oprrr(ctxt, AMOVFW+AEND, int(p.Scond))
+
+ o1 |= uint32(p.From.Reg) << 16
+ o1 |= uint32(p.To.Reg) << 12
+
+ case 90: /* tst reg */
+ o1 = oprrr(ctxt, ACMP+AEND, int(p.Scond))
+
+ o1 |= uint32(p.From.Reg) << 16
+
+ case 91: /* ldrexd oreg,reg */
+ aclass(ctxt, &p.From)
+
+ if ctxt.Instoffset != 0 {
+ ctxt.Diag("offset must be zero in LDREX")
+ }
+ o1 = 0x1b<<20 | 0xf9f
+ o1 |= uint32(p.From.Reg) << 16
+ o1 |= uint32(p.To.Reg) << 12
+ o1 |= (uint32(p.Scond) & C_SCOND) << 28
+
+ case 92: /* strexd reg,oreg,reg */
+ aclass(ctxt, &p.From)
+
+ if ctxt.Instoffset != 0 {
+ ctxt.Diag("offset must be zero in STREX")
+ }
+ o1 = 0x1a<<20 | 0xf90
+ o1 |= uint32(p.From.Reg) << 16
+ o1 |= uint32(p.Reg) << 0
+ o1 |= uint32(p.To.Reg) << 12
+ o1 |= (uint32(p.Scond) & C_SCOND) << 28
+
+ case 93: /* movb/movh/movhu addr,R -> ldrsb/ldrsh/ldrh */
+ o1 = omvl(ctxt, p, &p.From, REGTMP)
+
+ if !(o1 != 0) {
+ break
+ }
+ o2 = olhr(ctxt, 0, REGTMP, int(p.To.Reg), int(p.Scond))
+ if p.As == AMOVB || p.As == AMOVBS {
+ o2 ^= 1<<5 | 1<<6
+ } else if p.As == AMOVH || p.As == AMOVHS {
+ o2 ^= (1 << 6)
+ }
+ if o.flag&LPCREL != 0 {
+ o3 = o2
+ o2 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP | REGPC<<16 | REGTMP<<12
+ }
+
+ case 94: /* movh/movhu R,addr -> strh */
+ o1 = omvl(ctxt, p, &p.To, REGTMP)
+
+ if !(o1 != 0) {
+ break
+ }
+ o2 = oshr(ctxt, int(p.From.Reg), 0, REGTMP, int(p.Scond))
+ if o.flag&LPCREL != 0 {
+ o3 = o2
+ o2 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP | REGPC<<16 | REGTMP<<12
+ }
+
+ case 95: /* PLD off(reg) */
+ o1 = 0xf5d0f000
+
+ o1 |= uint32(p.From.Reg) << 16
+ if p.From.Offset < 0 {
+ o1 &^= (1 << 23)
+ o1 |= uint32((-p.From.Offset) & 0xfff)
+ } else {
+
+ o1 |= uint32(p.From.Offset & 0xfff)
+ }
+
+ // This is supposed to be something that stops execution.
+ // It's not supposed to be reached, ever, but if it is, we'd
+ // like to be able to tell how we got there. Assemble as
+ // 0xf7fabcfd which is guaranteed to raise undefined instruction
+ // exception.
+ case 96: /* UNDEF */
+ o1 = 0xf7fabcfd
+
+ case 97: /* CLZ Rm, Rd */
+ o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+ o1 |= uint32(p.To.Reg) << 12
+ o1 |= uint32(p.From.Reg)
+
+ case 98: /* MULW{T,B} Rs, Rm, Rd */
+ o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+ o1 |= uint32(p.To.Reg) << 16
+ o1 |= uint32(p.From.Reg) << 8
+ o1 |= uint32(p.Reg)
+
+ case 99: /* MULAW{T,B} Rs, Rm, Rn, Rd */
+ o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+
+ o1 |= uint32(p.To.Reg) << 12
+ o1 |= uint32(p.From.Reg) << 8
+ o1 |= uint32(p.Reg)
+ o1 |= uint32(p.To.Offset << 16)
+
+ // DATABUNDLE: BKPT $0x5be0, signify the start of NaCl data bundle;
+ // DATABUNDLEEND: zero width alignment marker
+ case 100:
+ if p.As == ADATABUNDLE {
+
+ o1 = 0xe125be70
+ }
+ break
+ }
+
+ out[0] = o1
+ out[1] = o2
+ out[2] = o3
+ out[3] = o4
+ out[4] = o5
+ out[5] = o6
+ return
+}
+
+func mov(ctxt *obj.Link, p *obj.Prog) uint32 {
+ var o1 uint32
+ var rt int
+ var r int
+
+ aclass(ctxt, &p.From)
+ o1 = oprrr(ctxt, int(p.As), int(p.Scond))
+ o1 |= uint32(p.From.Offset)
+ rt = int(p.To.Reg)
+ r = int(p.Reg)
+ if p.To.Type == D_NONE {
+ rt = 0
+ }
+ if p.As == AMOVW || p.As == AMVN {
+ r = 0
+ } else if r == NREG {
+ r = rt
+ }
+ o1 |= uint32(r)<<16 | uint32(rt)<<12
+ return o1
+}
+
+func oprrr(ctxt *obj.Link, a int, sc int) uint32 {
+ var o uint32
+
+ o = (uint32(sc) & C_SCOND) << 28
+ if sc&C_SBIT != 0 {
+ o |= 1 << 20
+ }
+ if sc&(C_PBIT|C_WBIT) != 0 {
+ ctxt.Diag(".nil/.W on dp instruction")
+ }
+ switch a {
+ case AMULU,
+ AMUL:
+ return o | 0x0<<21 | 0x9<<4
+ case AMULA:
+ return o | 0x1<<21 | 0x9<<4
+ case AMULLU:
+ return o | 0x4<<21 | 0x9<<4
+ case AMULL:
+ return o | 0x6<<21 | 0x9<<4
+ case AMULALU:
+ return o | 0x5<<21 | 0x9<<4
+ case AMULAL:
+ return o | 0x7<<21 | 0x9<<4
+ case AAND:
+ return o | 0x0<<21
+ case AEOR:
+ return o | 0x1<<21
+ case ASUB:
+ return o | 0x2<<21
+ case ARSB:
+ return o | 0x3<<21
+ case AADD:
+ return o | 0x4<<21
+ case AADC:
+ return o | 0x5<<21
+ case ASBC:
+ return o | 0x6<<21
+ case ARSC:
+ return o | 0x7<<21
+ case ATST:
+ return o | 0x8<<21 | 1<<20
+ case ATEQ:
+ return o | 0x9<<21 | 1<<20
+ case ACMP:
+ return o | 0xa<<21 | 1<<20
+ case ACMN:
+ return o | 0xb<<21 | 1<<20
+ case AORR:
+ return o | 0xc<<21
+
+ case AMOVB,
+ AMOVH,
+ AMOVW:
+ return o | 0xd<<21
+ case ABIC:
+ return o | 0xe<<21
+ case AMVN:
+ return o | 0xf<<21
+ case ASLL:
+ return o | 0xd<<21 | 0<<5
+ case ASRL:
+ return o | 0xd<<21 | 1<<5
+ case ASRA:
+ return o | 0xd<<21 | 2<<5
+ case ASWI:
+ return o | 0xf<<24
+
+ case AADDD:
+ return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 0<<4
+ case AADDF:
+ return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 0<<4
+ case ASUBD:
+ return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 4<<4
+ case ASUBF:
+ return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 4<<4
+ case AMULD:
+ return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0<<4
+ case AMULF:
+ return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0<<4
+ case ADIVD:
+ return o | 0xe<<24 | 0x8<<20 | 0xb<<8 | 0<<4
+ case ADIVF:
+ return o | 0xe<<24 | 0x8<<20 | 0xa<<8 | 0<<4
+ case ASQRTD:
+ return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0xc<<4
+ case ASQRTF:
+ return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0xc<<4
+ case AABSD:
+ return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 0xc<<4
+ case AABSF:
+ return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 0xc<<4
+ case ACMPD:
+ return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xb<<8 | 0xc<<4
+ case ACMPF:
+ return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xa<<8 | 0xc<<4
+
+ case AMOVF:
+ return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 4<<4
+ case AMOVD:
+ return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 4<<4
+
+ case AMOVDF:
+ return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 1<<8 // dtof
+ case AMOVFD:
+ return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 0<<8 // dtof
+
+ case AMOVWF:
+ if sc&C_UBIT == 0 {
+
+ o |= 1 << 7 /* signed */
+ }
+ return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 0<<8 // toint, double
+
+ case AMOVWD:
+ if sc&C_UBIT == 0 {
+ o |= 1 << 7 /* signed */
+ }
+ return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 1<<8 // toint, double
+
+ case AMOVFW:
+ if sc&C_UBIT == 0 {
+
+ o |= 1 << 16 /* signed */
+ }
+ return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 0<<8 | 1<<7 // toint, double, trunc
+
+ case AMOVDW:
+ if sc&C_UBIT == 0 {
+ o |= 1 << 16 /* signed */
+ }
+ return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 1<<8 | 1<<7 // toint, double, trunc
+
+ case AMOVWF + AEND: // copy WtoF
+ return o | 0xe<<24 | 0x0<<20 | 0xb<<8 | 1<<4
+
+ case AMOVFW + AEND: // copy FtoW
+ return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 1<<4
+
+ case ACMP + AEND: // cmp imm
+ return o | 0x3<<24 | 0x5<<20
+
+ // CLZ doesn't support .nil
+ case ACLZ:
+ return o&(0xf<<28) | 0x16f<<16 | 0xf1<<4
+
+ case AMULWT:
+ return o&(0xf<<28) | 0x12<<20 | 0xe<<4
+
+ case AMULWB:
+ return o&(0xf<<28) | 0x12<<20 | 0xa<<4
+
+ case AMULAWT:
+ return o&(0xf<<28) | 0x12<<20 | 0xc<<4
+
+ case AMULAWB:
+ return o&(0xf<<28) | 0x12<<20 | 0x8<<4
+
+ case ABL: // BLX REG
+ return o&(0xf<<28) | 0x12fff3<<4
+ }
+
+ ctxt.Diag("bad rrr %d", a)
+ prasm(ctxt.Curp)
+ return 0
+}
+
+func opbra(ctxt *obj.Link, a int, sc int) uint32 {
+ if sc&(C_SBIT|C_PBIT|C_WBIT) != 0 {
+ ctxt.Diag(".nil/.nil/.W on bra instruction")
+ }
+ sc &= C_SCOND
+ if a == ABL || a == ADUFFZERO || a == ADUFFCOPY {
+ return uint32(sc)<<28 | 0x5<<25 | 0x1<<24
+ }
+ if sc != 0xe {
+ ctxt.Diag(".COND on bcond instruction")
+ }
+ switch a {
+ case ABEQ:
+ return 0x0<<28 | 0x5<<25
+ case ABNE:
+ return 0x1<<28 | 0x5<<25
+ case ABCS:
+ return 0x2<<28 | 0x5<<25
+ case ABHS:
+ return 0x2<<28 | 0x5<<25
+ case ABCC:
+ return 0x3<<28 | 0x5<<25
+ case ABLO:
+ return 0x3<<28 | 0x5<<25
+ case ABMI:
+ return 0x4<<28 | 0x5<<25
+ case ABPL:
+ return 0x5<<28 | 0x5<<25
+ case ABVS:
+ return 0x6<<28 | 0x5<<25
+ case ABVC:
+ return 0x7<<28 | 0x5<<25
+ case ABHI:
+ return 0x8<<28 | 0x5<<25
+ case ABLS:
+ return 0x9<<28 | 0x5<<25
+ case ABGE:
+ return 0xa<<28 | 0x5<<25
+ case ABLT:
+ return 0xb<<28 | 0x5<<25
+ case ABGT:
+ return 0xc<<28 | 0x5<<25
+ case ABLE:
+ return 0xd<<28 | 0x5<<25
+ case AB:
+ return 0xe<<28 | 0x5<<25
+ }
+
+ ctxt.Diag("bad bra %v", Aconv(a))
+ prasm(ctxt.Curp)
+ return 0
+}
+
+func olr(ctxt *obj.Link, v int32, b int, r int, sc int) uint32 {
+ var o uint32
+
+ if sc&C_SBIT != 0 {
+ ctxt.Diag(".nil on LDR/STR instruction")
+ }
+ o = (uint32(sc) & C_SCOND) << 28
+ if !(sc&C_PBIT != 0) {
+ o |= 1 << 24
+ }
+ if !(sc&C_UBIT != 0) {
+ o |= 1 << 23
+ }
+ if sc&C_WBIT != 0 {
+ o |= 1 << 21
+ }
+ o |= 1<<26 | 1<<20
+ if v < 0 {
+ if sc&C_UBIT != 0 {
+ ctxt.Diag(".U on neg offset")
+ }
+ v = -v
+ o ^= 1 << 23
+ }
+
+ if v >= 1<<12 || v < 0 {
+ ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, ctxt.Printp)
+ }
+ o |= uint32(v)
+ o |= uint32(b) << 16
+ o |= uint32(r) << 12
+ return o
+}
+
+func olhr(ctxt *obj.Link, v int32, b int, r int, sc int) uint32 {
+ var o uint32
+
+ if sc&C_SBIT != 0 {
+ ctxt.Diag(".nil on LDRH/STRH instruction")
+ }
+ o = (uint32(sc) & C_SCOND) << 28
+ if !(sc&C_PBIT != 0) {
+ o |= 1 << 24
+ }
+ if sc&C_WBIT != 0 {
+ o |= 1 << 21
+ }
+ o |= 1<<23 | 1<<20 | 0xb<<4
+ if v < 0 {
+ v = -v
+ o ^= 1 << 23
+ }
+
+ if v >= 1<<8 || v < 0 {
+ ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, ctxt.Printp)
+ }
+ o |= uint32(v)&0xf | (uint32(v)>>4)<<8 | 1<<22
+ o |= uint32(b) << 16
+ o |= uint32(r) << 12
+ return o
+}
+
+func osr(ctxt *obj.Link, a int, r int, v int32, b int, sc int) uint32 {
+ var o uint32
+
+ o = olr(ctxt, v, b, r, sc) ^ (1 << 20)
+ if a != AMOVW {
+ o |= 1 << 22
+ }
+ return o
+}
+
+func oshr(ctxt *obj.Link, r int, v int32, b int, sc int) uint32 {
+ var o uint32
+
+ o = olhr(ctxt, v, b, r, sc) ^ (1 << 20)
+ return o
+}
+
+func osrr(ctxt *obj.Link, r int, i int, b int, sc int) uint32 {
+ return olr(ctxt, int32(i), b, r, sc) ^ (1<<25 | 1<<20)
+}
+
+func oshrr(ctxt *obj.Link, r int, i int, b int, sc int) uint32 {
+ return olhr(ctxt, int32(i), b, r, sc) ^ (1<<22 | 1<<20)
+}
+
+func olrr(ctxt *obj.Link, i int, b int, r int, sc int) uint32 {
+ return olr(ctxt, int32(i), b, r, sc) ^ (1 << 25)
+}
+
+func olhrr(ctxt *obj.Link, i int, b int, r int, sc int) uint32 {
+ return olhr(ctxt, int32(i), b, r, sc) ^ (1 << 22)
+}
+
+func ofsr(ctxt *obj.Link, a int, r int, v int32, b int, sc int, p *obj.Prog) uint32 {
+ var o uint32
+
+ if sc&C_SBIT != 0 {
+ ctxt.Diag(".nil on FLDR/FSTR instruction")
+ }
+ o = (uint32(sc) & C_SCOND) << 28
+ if !(sc&C_PBIT != 0) {
+ o |= 1 << 24
+ }
+ if sc&C_WBIT != 0 {
+ o |= 1 << 21
+ }
+ o |= 6<<25 | 1<<24 | 1<<23 | 10<<8
+ if v < 0 {
+ v = -v
+ o ^= 1 << 23
+ }
+
+ if v&3 != 0 {
+ ctxt.Diag("odd offset for floating point op: %d\n%v", v, p)
+ } else if v >= 1<<10 || v < 0 {
+ ctxt.Diag("literal span too large: %d\n%v", v, p)
+ }
+ o |= (uint32(v) >> 2) & 0xFF
+ o |= uint32(b) << 16
+ o |= uint32(r) << 12
+
+ switch a {
+ default:
+ ctxt.Diag("bad fst %v", Aconv(a))
+ fallthrough
+
+ case AMOVD:
+ o |= 1 << 8
+ fallthrough
+
+ case AMOVF:
+ break
+ }
+
+ return o
+}
+
+func omvl(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, dr int) uint32 {
+ var v int32
+ var o1 uint32
+ if !(p.Pcond != nil) {
+ aclass(ctxt, a)
+ v = immrot(uint32(^ctxt.Instoffset))
+ if v == 0 {
+ ctxt.Diag("missing literal")
+ prasm(p)
+ return 0
+ }
+
+ o1 = oprrr(ctxt, AMVN, int(p.Scond)&C_SCOND)
+ o1 |= uint32(v)
+ o1 |= uint32(dr) << 12
+ } else {
+
+ v = int32(p.Pcond.Pc - p.Pc - 8)
+ o1 = olr(ctxt, v, REGPC, dr, int(p.Scond)&C_SCOND)
+ }
+
+ return o1
+}
+
+func chipzero5(ctxt *obj.Link, e float64) int {
+ // We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions.
+ if ctxt.Goarm < 7 || e != 0 {
+
+ return -1
+ }
+ return 0
+}
+
+func chipfloat5(ctxt *obj.Link, e float64) int {
+ var n int
+ var h1 uint32
+ var l uint32
+ var h uint32
+ var ei uint64
+
+ // We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions.
+ if ctxt.Goarm < 7 {
+
+ goto no
+ }
+
+ ei = math.Float64bits(e)
+ l = uint32(ei)
+ h = uint32(ei >> 32)
+
+ if l != 0 || h&0xffff != 0 {
+ goto no
+ }
+ h1 = h & 0x7fc00000
+ if h1 != 0x40000000 && h1 != 0x3fc00000 {
+ goto no
+ }
+ n = 0
+
+ // sign bit (a)
+ if h&0x80000000 != 0 {
+
+ n |= 1 << 7
+ }
+
+ // exp sign bit (b)
+ if h1 == 0x3fc00000 {
+
+ n |= 1 << 6
+ }
+
+ // rest of exp and mantissa (cd-efgh)
+ n |= int((h >> 16) & 0x3f)
+
+ //print("match %.8lux %.8lux %d\n", l, h, n);
+ return n
+
+no:
+ return -1
+}
--- /dev/null
+// Inferno utils/5c/list.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5c/list.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package arm
+
+import (
+ "cmd/internal/obj"
+ "fmt"
+)
+
+const (
+ STRINGSZ = 1000
+)
+
+var extra = []string{
+ ".EQ",
+ ".NE",
+ ".CS",
+ ".CC",
+ ".MI",
+ ".PL",
+ ".VS",
+ ".VC",
+ ".HI",
+ ".LS",
+ ".GE",
+ ".LT",
+ ".GT",
+ ".LE",
+ "",
+ ".NV",
+}
+
+var bigP *obj.Prog
+
+func Pconv(p *obj.Prog) string {
+ var str string
+ var sc string
+ var fp string
+
+ var a int
+ var s int
+
+ a = int(p.As)
+ s = int(p.Scond)
+ sc = extra[s&C_SCOND]
+ if s&C_SBIT != 0 {
+ sc += ".S"
+ }
+ if s&C_PBIT != 0 {
+ sc += ".P"
+ }
+ if s&C_WBIT != 0 {
+ sc += ".W"
+ }
+ if s&C_UBIT != 0 { /* ambiguous with FBIT */
+ sc += ".U"
+ }
+ if a == AMOVM {
+ if p.From.Type == D_CONST {
+ str = fmt.Sprintf("%.5d (%v)\t%v%s\t%v,%v", p.Pc, p.Line(), Aconv(a), sc, RAconv(&p.From), Dconv(p, 0, &p.To))
+ } else if p.To.Type == D_CONST {
+ str = fmt.Sprintf("%.5d (%v)\t%v%s\t%v,%v", p.Pc, p.Line(), Aconv(a), sc, Dconv(p, 0, &p.From), RAconv(&p.To))
+ } else {
+
+ str = fmt.Sprintf("%.5d (%v)\t%v%s\t%v,%v", p.Pc, p.Line(), Aconv(a), sc, Dconv(p, 0, &p.From), Dconv(p, 0, &p.To))
+ }
+ } else if a == ADATA {
+ str = fmt.Sprintf("%.5d (%v)\t%v\t%v/%d,%v", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From), p.Reg, Dconv(p, 0, &p.To))
+ } else if p.As == ATEXT {
+ str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%d,%v", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From), p.Reg, Dconv(p, 0, &p.To))
+ } else if p.Reg == NREG {
+ str = fmt.Sprintf("%.5d (%v)\t%v%s\t%v,%v", p.Pc, p.Line(), Aconv(a), sc, Dconv(p, 0, &p.From), Dconv(p, 0, &p.To))
+ } else if p.From.Type != D_FREG {
+ str = fmt.Sprintf("%.5d (%v)\t%v%s\t%v,R%d,%v", p.Pc, p.Line(), Aconv(a), sc, Dconv(p, 0, &p.From), p.Reg, Dconv(p, 0, &p.To))
+ } else {
+
+ str = fmt.Sprintf("%.5d (%v)\t%v%s\t%v,F%d,%v", p.Pc, p.Line(), Aconv(a), sc, Dconv(p, 0, &p.From), p.Reg, Dconv(p, 0, &p.To))
+ }
+
+ fp += str
+ return fp
+}
+
+func Aconv(a int) string {
+ var s string
+ var fp string
+
+ s = "???"
+ if a >= AXXX && a < ALAST {
+ s = Anames[a]
+ }
+ fp += s
+ return fp
+}
+
+func Dconv(p *obj.Prog, flag int, a *obj.Addr) string {
+ var str string
+ var fp string
+
+ var op string
+ var v int
+
+ switch a.Type {
+ default:
+ str = fmt.Sprintf("GOK-type(%d)", a.Type)
+
+ case D_NONE:
+ str = ""
+ if a.Name != D_NONE || a.Reg != NREG || a.Sym != nil {
+ str = fmt.Sprintf("%v(R%d)(NONE)", Mconv(a), a.Reg)
+ }
+
+ case D_CONST:
+ if a.Reg != NREG {
+ str = fmt.Sprintf("$%v(R%d)", Mconv(a), a.Reg)
+ } else {
+
+ str = fmt.Sprintf("$%v", Mconv(a))
+ }
+
+ case D_CONST2:
+ str = fmt.Sprintf("$%d-%d", a.Offset, a.Offset2)
+
+ case D_SHIFT:
+ v = int(a.Offset)
+ op = string("<<>>->@>"[((v>>5)&3)<<1:])
+ if v&(1<<4) != 0 {
+ str = fmt.Sprintf("R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15)
+ } else {
+
+ str = fmt.Sprintf("R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31)
+ }
+ if a.Reg != NREG {
+ str += fmt.Sprintf("(R%d)", a.Reg)
+ }
+
+ case D_OREG:
+ if a.Reg != NREG {
+ str = fmt.Sprintf("%v(R%d)", Mconv(a), a.Reg)
+ } else {
+
+ str = fmt.Sprintf("%v", Mconv(a))
+ }
+
+ case D_REG:
+ str = fmt.Sprintf("R%d", a.Reg)
+ if a.Name != D_NONE || a.Sym != nil {
+ str = fmt.Sprintf("%v(R%d)(REG)", Mconv(a), a.Reg)
+ }
+
+ case D_FREG:
+ str = fmt.Sprintf("F%d", a.Reg)
+ if a.Name != D_NONE || a.Sym != nil {
+ str = fmt.Sprintf("%v(R%d)(REG)", Mconv(a), a.Reg)
+ }
+
+ case D_PSR:
+ str = fmt.Sprintf("PSR")
+ if a.Name != D_NONE || a.Sym != nil {
+ str = fmt.Sprintf("%v(PSR)(REG)", Mconv(a))
+ }
+
+ case D_BRANCH:
+ if a.Sym != nil {
+ str = fmt.Sprintf("%s(SB)", a.Sym.Name)
+ } else if p != nil && p.Pcond != nil {
+ str = fmt.Sprintf("%d", p.Pcond.Pc)
+ } else if a.U.Branch != nil {
+ str = fmt.Sprintf("%d", a.U.Branch.Pc)
+ } else {
+
+ str = fmt.Sprintf("%d(PC)", a.Offset) /*-pc*/
+ }
+
+ case D_FCONST:
+ str = fmt.Sprintf("$%.17g", a.U.Dval)
+
+ case D_SCONST:
+ str = fmt.Sprintf("$\"%q\"", a.U.Sval)
+ break
+ }
+
+ fp += str
+ return fp
+}
+
+func RAconv(a *obj.Addr) string {
+ var str string
+ var fp string
+
+ var i int
+ var v int
+
+ str = fmt.Sprintf("GOK-reglist")
+ switch a.Type {
+ case D_CONST,
+ D_CONST2:
+ if a.Reg != NREG {
+ break
+ }
+ if a.Sym != nil {
+ break
+ }
+ v = int(a.Offset)
+ str = ""
+ for i = 0; i < NREG; i++ {
+ if v&(1<<uint(i)) != 0 {
+ if str[0] == 0 {
+ str += "[R"
+ } else {
+
+ str += ",R"
+ }
+ str += fmt.Sprintf("%d", i)
+ }
+ }
+
+ str += "]"
+ }
+
+ fp += str
+ return fp
+}
+
+func Rconv(r int) string {
+ var fp string
+
+ var str string
+
+ str = fmt.Sprintf("R%d", r)
+ fp += str
+ return fp
+}
+
+func DRconv(a int) string {
+ var s string
+ var fp string
+
+ s = "C_??"
+ if a >= C_NONE && a <= C_NCLASS {
+ s = cnames5[a]
+ }
+ fp += s
+ return fp
+}
+
+func Mconv(a *obj.Addr) string {
+ var str string
+ var fp string
+
+ var s *obj.LSym
+
+ s = a.Sym
+ if s == nil {
+ str = fmt.Sprintf("%d", int(a.Offset))
+ goto out
+ }
+
+ switch a.Name {
+ default:
+ str = fmt.Sprintf("GOK-name(%d)", a.Name)
+
+ case D_NONE:
+ str = fmt.Sprintf("%d", a.Offset)
+
+ case D_EXTERN:
+ str = fmt.Sprintf("%s+%d(SB)", s.Name, int(a.Offset))
+
+ case D_STATIC:
+ str = fmt.Sprintf("%s<>+%d(SB)", s.Name, int(a.Offset))
+
+ case D_AUTO:
+ str = fmt.Sprintf("%s-%d(SP)", s.Name, int(-a.Offset))
+
+ case D_PARAM:
+ str = fmt.Sprintf("%s+%d(FP)", s.Name, int(a.Offset))
+ break
+ }
+
+out:
+ fp += str
+ return fp
+}
--- /dev/null
+// Derived from Inferno utils/5c/swt.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5c/swt.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package arm
+
+import (
+ "cmd/internal/obj"
+ "encoding/binary"
+ "fmt"
+ "log"
+ "math"
+)
+
+var zprg5 = obj.Prog{
+ As: AGOK,
+ Scond: C_SCOND_NONE,
+ Reg: NREG,
+ From: obj.Addr{
+ Name: D_NONE,
+ Type: D_NONE,
+ Reg: NREG,
+ },
+ To: obj.Addr{
+ Name: D_NONE,
+ Type: D_NONE,
+ Reg: NREG,
+ },
+}
+
+func symtype(a *obj.Addr) int {
+ return int(a.Name)
+}
+
+func isdata(p *obj.Prog) bool {
+ return p.As == ADATA || p.As == AGLOBL
+}
+
+func iscall(p *obj.Prog) bool {
+ return p.As == ABL
+}
+
+func datasize(p *obj.Prog) int {
+ return int(p.Reg)
+}
+
+func textflag(p *obj.Prog) int {
+ return int(p.Reg)
+}
+
+func settextflag(p *obj.Prog, f int) {
+ p.Reg = uint8(f)
+}
+
+func progedit(ctxt *obj.Link, p *obj.Prog) {
+ var literal string
+ var s *obj.LSym
+ var tlsfallback *obj.LSym
+
+ p.From.Class = 0
+ p.To.Class = 0
+
+ // Rewrite B/BL to symbol as D_BRANCH.
+ switch p.As {
+
+ case AB,
+ ABL,
+ ADUFFZERO,
+ ADUFFCOPY:
+ if p.To.Type == D_OREG && (p.To.Name == D_EXTERN || p.To.Name == D_STATIC) && p.To.Sym != nil {
+ p.To.Type = D_BRANCH
+ }
+ break
+ }
+
+ // Replace TLS register fetches on older ARM procesors.
+ switch p.As {
+
+ // Treat MRC 15, 0, <reg>, C13, C0, 3 specially.
+ case AMRC:
+ if p.To.Offset&0xffff0fff == 0xee1d0f70 {
+
+ // Because the instruction might be rewriten to a BL which returns in R0
+ // the register must be zero.
+ if p.To.Offset&0xf000 != 0 {
+
+ ctxt.Diag("%v: TLS MRC instruction must write to R0 as it might get translated into a BL instruction", p.Line())
+ }
+
+ if ctxt.Goarm < 7 {
+ // Replace it with BL runtime.read_tls_fallback(SB) for ARM CPUs that lack the tls extension.
+ if tlsfallback == nil {
+
+ tlsfallback = obj.Linklookup(ctxt, "runtime.read_tls_fallback", 0)
+ }
+
+ // MOVW LR, R11
+ p.As = AMOVW
+
+ p.From.Type = D_REG
+ p.From.Reg = REGLINK
+ p.To.Type = D_REG
+ p.To.Reg = REGTMP
+
+ // BL runtime.read_tls_fallback(SB)
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ABL
+ p.To.Type = D_BRANCH
+ p.To.Sym = tlsfallback
+ p.To.Offset = 0
+
+ // MOVW R11, LR
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AMOVW
+ p.From.Type = D_REG
+ p.From.Reg = REGTMP
+ p.To.Type = D_REG
+ p.To.Reg = REGLINK
+ break
+ }
+ }
+
+ // Otherwise, MRC/MCR instructions need no further treatment.
+ p.As = AWORD
+
+ break
+ }
+
+ // Rewrite float constants to values stored in memory.
+ switch p.As {
+
+ case AMOVF:
+ if p.From.Type == D_FCONST && chipfloat5(ctxt, p.From.U.Dval) < 0 && (chipzero5(ctxt, p.From.U.Dval) < 0 || p.Scond&C_SCOND != C_SCOND_NONE) {
+ var i32 uint32
+ var f32 float32
+ f32 = float32(p.From.U.Dval)
+ i32 = math.Float32bits(f32)
+ literal = fmt.Sprintf("$f32.%08x", i32)
+ s = obj.Linklookup(ctxt, literal, 0)
+ if s.Type == 0 {
+ s.Type = obj.SRODATA
+ obj.Adduint32(ctxt, s, i32)
+ s.Reachable = 0
+ }
+
+ p.From.Type = D_OREG
+ p.From.Sym = s
+ p.From.Name = D_EXTERN
+ p.From.Offset = 0
+ }
+
+ case AMOVD:
+ if p.From.Type == D_FCONST && chipfloat5(ctxt, p.From.U.Dval) < 0 && (chipzero5(ctxt, p.From.U.Dval) < 0 || p.Scond&C_SCOND != C_SCOND_NONE) {
+ var i64 uint64
+ i64 = math.Float64bits(p.From.U.Dval)
+ literal = fmt.Sprintf("$f64.%016x", i64)
+ s = obj.Linklookup(ctxt, literal, 0)
+ if s.Type == 0 {
+ s.Type = obj.SRODATA
+ obj.Adduint64(ctxt, s, i64)
+ s.Reachable = 0
+ }
+
+ p.From.Type = D_OREG
+ p.From.Sym = s
+ p.From.Name = D_EXTERN
+ p.From.Offset = 0
+ }
+
+ break
+ }
+
+ if ctxt.Flag_shared != 0 {
+ // Shared libraries use R_ARM_TLS_IE32 instead of
+ // R_ARM_TLS_LE32, replacing the link time constant TLS offset in
+ // runtime.tlsg with an address to a GOT entry containing the
+ // offset. Rewrite $runtime.tlsg(SB) to runtime.tlsg(SB) to
+ // compensate.
+ if ctxt.Tlsg == nil {
+
+ ctxt.Tlsg = obj.Linklookup(ctxt, "runtime.tlsg", 0)
+ }
+
+ if p.From.Type == D_CONST && p.From.Name == D_EXTERN && p.From.Sym == ctxt.Tlsg {
+ p.From.Type = D_OREG
+ }
+ if p.To.Type == D_CONST && p.To.Name == D_EXTERN && p.To.Sym == ctxt.Tlsg {
+ p.To.Type = D_OREG
+ }
+ }
+}
+
+func prg() *obj.Prog {
+ p := zprg
+ return &p
+}
+
+// Prog.mark
+const (
+ FOLL = 1 << 0
+ LABEL = 1 << 1
+ LEAF = 1 << 2
+)
+
+func linkcase(casep *obj.Prog) {
+ var p *obj.Prog
+
+ for p = casep; p != nil; p = p.Link {
+ if p.As == ABCASE {
+ for ; p != nil && p.As == ABCASE; p = p.Link {
+ p.Pcrel = casep
+ }
+ break
+ }
+ }
+}
+
+func nocache5(p *obj.Prog) {
+ p.Optab = 0
+ p.From.Class = 0
+ p.To.Class = 0
+}
+
+func addstacksplit(ctxt *obj.Link, cursym *obj.LSym) {
+ var p *obj.Prog
+ var pl *obj.Prog
+ var p1 *obj.Prog
+ var p2 *obj.Prog
+ var q *obj.Prog
+ var q1 *obj.Prog
+ var q2 *obj.Prog
+ var o int
+ var autosize int32
+ var autoffset int32
+
+ autosize = 0
+
+ if ctxt.Symmorestack[0] == nil {
+ ctxt.Symmorestack[0] = obj.Linklookup(ctxt, "runtime.morestack", 0)
+ ctxt.Symmorestack[1] = obj.Linklookup(ctxt, "runtime.morestack_noctxt", 0)
+ }
+
+ q = nil
+
+ ctxt.Cursym = cursym
+
+ if cursym.Text == nil || cursym.Text.Link == nil {
+ return
+ }
+
+ softfloat(ctxt, cursym)
+
+ p = cursym.Text
+ autoffset = int32(p.To.Offset)
+ if autoffset < 0 {
+ autoffset = 0
+ }
+ cursym.Locals = autoffset
+ cursym.Args = p.To.Offset2
+
+ if ctxt.Debugzerostack != 0 {
+ if autoffset != 0 && !(p.Reg&obj.NOSPLIT != 0) {
+ // MOVW $4(R13), R1
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AMOVW
+ p.From.Type = D_CONST
+ p.From.Reg = 13
+ p.From.Offset = 4
+ p.To.Type = D_REG
+ p.To.Reg = 1
+
+ // MOVW $n(R13), R2
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AMOVW
+ p.From.Type = D_CONST
+ p.From.Reg = 13
+ p.From.Offset = 4 + int64(autoffset)
+ p.To.Type = D_REG
+ p.To.Reg = 2
+
+ // MOVW $0, R3
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AMOVW
+ p.From.Type = D_CONST
+ p.From.Offset = 0
+ p.To.Type = D_REG
+ p.To.Reg = 3
+
+ // L:
+ // MOVW.nil R3, 0(R1) +4
+ // CMP R1, R2
+ // BNE L
+ pl = obj.Appendp(ctxt, p)
+ p = pl
+
+ p.As = AMOVW
+ p.From.Type = D_REG
+ p.From.Reg = 3
+ p.To.Type = D_OREG
+ p.To.Reg = 1
+ p.To.Offset = 4
+ p.Scond |= C_PBIT
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ACMP
+ p.From.Type = D_REG
+ p.From.Reg = 1
+ p.Reg = 2
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ABNE
+ p.To.Type = D_BRANCH
+ p.Pcond = pl
+ }
+ }
+
+ /*
+ * find leaf subroutines
+ * strip NOPs
+ * expand RET
+ * expand BECOME pseudo
+ */
+ for p = cursym.Text; p != nil; p = p.Link {
+
+ switch p.As {
+ case ACASE:
+ if ctxt.Flag_shared != 0 {
+ linkcase(p)
+ }
+
+ case ATEXT:
+ p.Mark |= LEAF
+
+ case ARET:
+ break
+
+ case ADIV,
+ ADIVU,
+ AMOD,
+ AMODU:
+ q = p
+ if ctxt.Sym_div == nil {
+ initdiv(ctxt)
+ }
+ cursym.Text.Mark &^= LEAF
+ continue
+
+ case ANOP:
+ q1 = p.Link
+ q.Link = q1 /* q is non-nop */
+ if q1 != nil {
+ q1.Mark |= p.Mark
+ }
+ continue
+
+ case ABL,
+ ABX,
+ ADUFFZERO,
+ ADUFFCOPY:
+ cursym.Text.Mark &^= LEAF
+ fallthrough
+
+ case ABCASE,
+ AB,
+ ABEQ,
+ ABNE,
+ ABCS,
+ ABHS,
+ ABCC,
+ ABLO,
+ ABMI,
+ ABPL,
+ ABVS,
+ ABVC,
+ ABHI,
+ ABLS,
+ ABGE,
+ ABLT,
+ ABGT,
+ ABLE:
+ q1 = p.Pcond
+ if q1 != nil {
+ for q1.As == ANOP {
+ q1 = q1.Link
+ p.Pcond = q1
+ }
+ }
+
+ break
+ }
+
+ q = p
+ }
+
+ for p = cursym.Text; p != nil; p = p.Link {
+ o = int(p.As)
+ switch o {
+ case ATEXT:
+ autosize = int32(p.To.Offset + 4)
+ if autosize <= 4 {
+ if cursym.Text.Mark&LEAF != 0 {
+ p.To.Offset = -4
+ autosize = 0
+ }
+ }
+
+ if !(autosize != 0) && !(cursym.Text.Mark&LEAF != 0) {
+ if ctxt.Debugvlog != 0 {
+ fmt.Fprintf(ctxt.Bso, "save suppressed in: %s\n", cursym.Name)
+ obj.Bflush(ctxt.Bso)
+ }
+
+ cursym.Text.Mark |= LEAF
+ }
+
+ if cursym.Text.Mark&LEAF != 0 {
+ cursym.Leaf = 1
+ if !(autosize != 0) {
+ break
+ }
+ }
+
+ if !(p.Reg&obj.NOSPLIT != 0) {
+ p = stacksplit(ctxt, p, autosize, bool2int(!(cursym.Text.Reg&obj.NEEDCTXT != 0))) // emit split check
+ }
+
+ // MOVW.W R14,$-autosize(SP)
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AMOVW
+ p.Scond |= C_WBIT
+ p.From.Type = D_REG
+ p.From.Reg = REGLINK
+ p.To.Type = D_OREG
+ p.To.Offset = int64(-autosize)
+ p.To.Reg = REGSP
+ p.Spadj = autosize
+
+ if cursym.Text.Reg&obj.WRAPPER != 0 {
+ // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
+ //
+ // MOVW g_panic(g), R1
+ // CMP $0, R1
+ // B.EQ end
+ // MOVW panic_argp(R1), R2
+ // ADD $(autosize+4), R13, R3
+ // CMP R2, R3
+ // B.NE end
+ // ADD $4, R13, R4
+ // MOVW R4, panic_argp(R1)
+ // end:
+ // NOP
+ //
+ // The NOP is needed to give the jumps somewhere to land.
+ // It is a liblink NOP, not an ARM NOP: it encodes to 0 instruction bytes.
+
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AMOVW
+ p.From.Type = D_OREG
+ p.From.Reg = REGG
+ p.From.Offset = 4 * int64(ctxt.Arch.Ptrsize) // G.panic
+ p.To.Type = D_REG
+ p.To.Reg = 1
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ACMP
+ p.From.Type = D_CONST
+ p.From.Offset = 0
+ p.Reg = 1
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ABEQ
+ p.To.Type = D_BRANCH
+ p1 = p
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AMOVW
+ p.From.Type = D_OREG
+ p.From.Reg = 1
+ p.From.Offset = 0 // Panic.argp
+ p.To.Type = D_REG
+ p.To.Reg = 2
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AADD
+ p.From.Type = D_CONST
+ p.From.Offset = int64(autosize) + 4
+ p.Reg = 13
+ p.To.Type = D_REG
+ p.To.Reg = 3
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ACMP
+ p.From.Type = D_REG
+ p.From.Reg = 2
+ p.Reg = 3
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ABNE
+ p.To.Type = D_BRANCH
+ p2 = p
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AADD
+ p.From.Type = D_CONST
+ p.From.Offset = 4
+ p.Reg = 13
+ p.To.Type = D_REG
+ p.To.Reg = 4
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AMOVW
+ p.From.Type = D_REG
+ p.From.Reg = 4
+ p.To.Type = D_OREG
+ p.To.Reg = 1
+ p.To.Offset = 0 // Panic.argp
+
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ANOP
+ p1.Pcond = p
+ p2.Pcond = p
+ }
+
+ case ARET:
+ nocache5(p)
+ if cursym.Text.Mark&LEAF != 0 {
+ if !(autosize != 0) {
+ p.As = AB
+ p.From = zprg5.From
+ if p.To.Sym != nil { // retjmp
+ p.To.Type = D_BRANCH
+ } else {
+
+ p.To.Type = D_OREG
+ p.To.Offset = 0
+ p.To.Reg = REGLINK
+ }
+
+ break
+ }
+ }
+
+ p.As = AMOVW
+ p.Scond |= C_PBIT
+ p.From.Type = D_OREG
+ p.From.Offset = int64(autosize)
+ p.From.Reg = REGSP
+ p.To.Type = D_REG
+ p.To.Reg = REGPC
+
+ // If there are instructions following
+ // this ARET, they come from a branch
+ // with the same stackframe, so no spadj.
+ if p.To.Sym != nil { // retjmp
+ p.To.Reg = REGLINK
+ q2 = obj.Appendp(ctxt, p)
+ q2.As = AB
+ q2.To.Type = D_BRANCH
+ q2.To.Sym = p.To.Sym
+ p.To.Sym = nil
+ p = q2
+ }
+
+ case AADD:
+ if p.From.Type == D_CONST && p.From.Reg == NREG && p.To.Type == D_REG && p.To.Reg == REGSP {
+ p.Spadj = int32(-p.From.Offset)
+ }
+
+ case ASUB:
+ if p.From.Type == D_CONST && p.From.Reg == NREG && p.To.Type == D_REG && p.To.Reg == REGSP {
+ p.Spadj = int32(p.From.Offset)
+ }
+
+ case ADIV,
+ ADIVU,
+ AMOD,
+ AMODU:
+ if ctxt.Debugdivmod != 0 {
+ break
+ }
+ if p.From.Type != D_REG {
+ break
+ }
+ if p.To.Type != D_REG {
+ break
+ }
+ q1 = p
+
+ /* MOV a,4(SP) */
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AMOVW
+ p.Lineno = q1.Lineno
+ p.From.Type = D_REG
+ p.From.Reg = q1.From.Reg
+ p.To.Type = D_OREG
+ p.To.Reg = REGSP
+ p.To.Offset = 4
+
+ /* MOV b,REGTMP */
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AMOVW
+ p.Lineno = q1.Lineno
+ p.From.Type = D_REG
+ p.From.Reg = int8(q1.Reg)
+ if q1.Reg == NREG {
+ p.From.Reg = q1.To.Reg
+ }
+ p.To.Type = D_REG
+ p.To.Reg = REGTMP
+ p.To.Offset = 0
+
+ /* CALL appropriate */
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ABL
+ p.Lineno = q1.Lineno
+ p.To.Type = D_BRANCH
+ switch o {
+ case ADIV:
+ p.To.Sym = ctxt.Sym_div
+
+ case ADIVU:
+ p.To.Sym = ctxt.Sym_divu
+
+ case AMOD:
+ p.To.Sym = ctxt.Sym_mod
+
+ case AMODU:
+ p.To.Sym = ctxt.Sym_modu
+ break
+ }
+
+ /* MOV REGTMP, b */
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AMOVW
+ p.Lineno = q1.Lineno
+ p.From.Type = D_REG
+ p.From.Reg = REGTMP
+ p.From.Offset = 0
+ p.To.Type = D_REG
+ p.To.Reg = q1.To.Reg
+
+ /* ADD $8,SP */
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AADD
+ p.Lineno = q1.Lineno
+ p.From.Type = D_CONST
+ p.From.Reg = NREG
+ p.From.Offset = 8
+ p.Reg = NREG
+ p.To.Type = D_REG
+ p.To.Reg = REGSP
+ p.Spadj = -8
+
+ /* Keep saved LR at 0(SP) after SP change. */
+ /* MOVW 0(SP), REGTMP; MOVW REGTMP, -8!(SP) */
+ /* TODO: Remove SP adjustments; see issue 6699. */
+ q1.As = AMOVW
+
+ q1.From.Type = D_OREG
+ q1.From.Reg = REGSP
+ q1.From.Offset = 0
+ q1.Reg = NREG
+ q1.To.Type = D_REG
+ q1.To.Reg = REGTMP
+
+ /* SUB $8,SP */
+ q1 = obj.Appendp(ctxt, q1)
+
+ q1.As = AMOVW
+ q1.From.Type = D_REG
+ q1.From.Reg = REGTMP
+ q1.Reg = NREG
+ q1.To.Type = D_OREG
+ q1.To.Reg = REGSP
+ q1.To.Offset = -8
+ q1.Scond |= C_WBIT
+ q1.Spadj = 8
+
+ case AMOVW:
+ if (p.Scond&C_WBIT != 0) && p.To.Type == D_OREG && p.To.Reg == REGSP {
+ p.Spadj = int32(-p.To.Offset)
+ }
+ if (p.Scond&C_PBIT != 0) && p.From.Type == D_OREG && p.From.Reg == REGSP && p.To.Reg != REGPC {
+ p.Spadj = int32(-p.From.Offset)
+ }
+ if p.From.Type == D_CONST && p.From.Reg == REGSP && p.To.Type == D_REG && p.To.Reg == REGSP {
+ p.Spadj = int32(-p.From.Offset)
+ }
+ break
+ }
+ }
+}
+
+func softfloat(ctxt *obj.Link, cursym *obj.LSym) {
+ var p *obj.Prog
+ var next *obj.Prog
+ var symsfloat *obj.LSym
+ var wasfloat int
+
+ if ctxt.Goarm > 5 {
+ return
+ }
+
+ symsfloat = obj.Linklookup(ctxt, "_sfloat", 0)
+
+ wasfloat = 0
+ for p = cursym.Text; p != nil; p = p.Link {
+ if p.Pcond != nil {
+ p.Pcond.Mark |= LABEL
+ }
+ }
+ for p = cursym.Text; p != nil; p = p.Link {
+ switch p.As {
+ case AMOVW:
+ if p.To.Type == D_FREG || p.From.Type == D_FREG {
+ goto soft
+ }
+ goto notsoft
+
+ case AMOVWD,
+ AMOVWF,
+ AMOVDW,
+ AMOVFW,
+ AMOVFD,
+ AMOVDF,
+ AMOVF,
+ AMOVD,
+ ACMPF,
+ ACMPD,
+ AADDF,
+ AADDD,
+ ASUBF,
+ ASUBD,
+ AMULF,
+ AMULD,
+ ADIVF,
+ ADIVD,
+ ASQRTF,
+ ASQRTD,
+ AABSF,
+ AABSD:
+ goto soft
+
+ default:
+ goto notsoft
+ }
+
+ soft:
+ if !(wasfloat != 0) || (p.Mark&LABEL != 0) {
+ next = ctxt.NewProg()
+ *next = *p
+
+ // BL _sfloat(SB)
+ *p = zprg5
+
+ p.Link = next
+ p.As = ABL
+ p.To.Type = D_BRANCH
+ p.To.Sym = symsfloat
+ p.Lineno = next.Lineno
+
+ p = next
+ wasfloat = 1
+ }
+
+ continue
+
+ notsoft:
+ wasfloat = 0
+ }
+}
+
+func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32, noctxt int) *obj.Prog {
+ // MOVW g_stackguard(g), R1
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AMOVW
+ p.From.Type = D_OREG
+ p.From.Reg = REGG
+ p.From.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
+ if ctxt.Cursym.Cfunc != 0 {
+ p.From.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
+ }
+ p.To.Type = D_REG
+ p.To.Reg = 1
+
+ if framesize <= obj.StackSmall {
+ // small stack: SP < stackguard
+ // CMP stackguard, SP
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ACMP
+ p.From.Type = D_REG
+ p.From.Reg = 1
+ p.Reg = REGSP
+ } else if framesize <= obj.StackBig {
+ // large stack: SP-framesize < stackguard-StackSmall
+ // MOVW $-framesize(SP), R2
+ // CMP stackguard, R2
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AMOVW
+ p.From.Type = D_CONST
+ p.From.Reg = REGSP
+ p.From.Offset = int64(-framesize)
+ p.To.Type = D_REG
+ p.To.Reg = 2
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ACMP
+ p.From.Type = D_REG
+ p.From.Reg = 1
+ p.Reg = 2
+ } else {
+
+ // Such a large stack we need to protect against wraparound
+ // if SP is close to zero.
+ // SP-stackguard+StackGuard < framesize + (StackGuard-StackSmall)
+ // The +StackGuard on both sides is required to keep the left side positive:
+ // SP is allowed to be slightly below stackguard. See stack.h.
+ // CMP $StackPreempt, R1
+ // MOVW.NE $StackGuard(SP), R2
+ // SUB.NE R1, R2
+ // MOVW.NE $(framesize+(StackGuard-StackSmall)), R3
+ // CMP.NE R3, R2
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ACMP
+ p.From.Type = D_CONST
+ p.From.Offset = int64(uint32(obj.StackPreempt & (1<<32 - 1)))
+ p.Reg = 1
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AMOVW
+ p.From.Type = D_CONST
+ p.From.Reg = REGSP
+ p.From.Offset = obj.StackGuard
+ p.To.Type = D_REG
+ p.To.Reg = 2
+ p.Scond = C_SCOND_NE
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ASUB
+ p.From.Type = D_REG
+ p.From.Reg = 1
+ p.To.Type = D_REG
+ p.To.Reg = 2
+ p.Scond = C_SCOND_NE
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AMOVW
+ p.From.Type = D_CONST
+ p.From.Offset = int64(framesize) + (obj.StackGuard - obj.StackSmall)
+ p.To.Type = D_REG
+ p.To.Reg = 3
+ p.Scond = C_SCOND_NE
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ACMP
+ p.From.Type = D_REG
+ p.From.Reg = 3
+ p.Reg = 2
+ p.Scond = C_SCOND_NE
+ }
+
+ // MOVW.LS R14, R3
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AMOVW
+ p.Scond = C_SCOND_LS
+ p.From.Type = D_REG
+ p.From.Reg = REGLINK
+ p.To.Type = D_REG
+ p.To.Reg = 3
+
+ // BL.LS runtime.morestack(SB) // modifies LR, returns with LO still asserted
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ABL
+ p.Scond = C_SCOND_LS
+ p.To.Type = D_BRANCH
+ if ctxt.Cursym.Cfunc != 0 {
+ p.To.Sym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
+ } else {
+
+ p.To.Sym = ctxt.Symmorestack[noctxt]
+ }
+
+ // BLS start
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ABLS
+ p.To.Type = D_BRANCH
+ p.Pcond = ctxt.Cursym.Text.Link
+
+ return p
+}
+
+func initdiv(ctxt *obj.Link) {
+ if ctxt.Sym_div != nil {
+ return
+ }
+ ctxt.Sym_div = obj.Linklookup(ctxt, "_div", 0)
+ ctxt.Sym_divu = obj.Linklookup(ctxt, "_divu", 0)
+ ctxt.Sym_mod = obj.Linklookup(ctxt, "_mod", 0)
+ ctxt.Sym_modu = obj.Linklookup(ctxt, "_modu", 0)
+}
+
+func follow(ctxt *obj.Link, s *obj.LSym) {
+ var firstp *obj.Prog
+ var lastp *obj.Prog
+
+ ctxt.Cursym = s
+
+ firstp = ctxt.NewProg()
+ lastp = firstp
+ xfol(ctxt, s.Text, &lastp)
+ lastp.Link = nil
+ s.Text = firstp.Link
+}
+
+func relinv(a int) int {
+ switch a {
+ case ABEQ:
+ return ABNE
+ case ABNE:
+ return ABEQ
+ case ABCS:
+ return ABCC
+ case ABHS:
+ return ABLO
+ case ABCC:
+ return ABCS
+ case ABLO:
+ return ABHS
+ case ABMI:
+ return ABPL
+ case ABPL:
+ return ABMI
+ case ABVS:
+ return ABVC
+ case ABVC:
+ return ABVS
+ case ABHI:
+ return ABLS
+ case ABLS:
+ return ABHI
+ case ABGE:
+ return ABLT
+ case ABLT:
+ return ABGE
+ case ABGT:
+ return ABLE
+ case ABLE:
+ return ABGT
+ }
+
+ log.Fatalf("unknown relation: %s", Anames[a])
+ return 0
+}
+
+func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
+ var q *obj.Prog
+ var r *obj.Prog
+ var a int
+ var i int
+
+loop:
+ if p == nil {
+ return
+ }
+ a = int(p.As)
+ if a == AB {
+ q = p.Pcond
+ if q != nil && q.As != ATEXT {
+ p.Mark |= FOLL
+ p = q
+ if !(p.Mark&FOLL != 0) {
+ goto loop
+ }
+ }
+ }
+
+ if p.Mark&FOLL != 0 {
+ i = 0
+ q = p
+ for ; i < 4; (func() { i++; q = q.Link })() {
+ if q == *last || q == nil {
+ break
+ }
+ a = int(q.As)
+ if a == ANOP {
+ i--
+ continue
+ }
+
+ if a == AB || (a == ARET && q.Scond == C_SCOND_NONE) || a == ARFE || a == AUNDEF {
+ goto copy
+ }
+ if q.Pcond == nil || (q.Pcond.Mark&FOLL != 0) {
+ continue
+ }
+ if a != ABEQ && a != ABNE {
+ continue
+ }
+
+ copy:
+ for {
+ r = ctxt.NewProg()
+ *r = *p
+ if !(r.Mark&FOLL != 0) {
+ fmt.Printf("can't happen 1\n")
+ }
+ r.Mark |= FOLL
+ if p != q {
+ p = p.Link
+ (*last).Link = r
+ *last = r
+ continue
+ }
+
+ (*last).Link = r
+ *last = r
+ if a == AB || (a == ARET && q.Scond == C_SCOND_NONE) || a == ARFE || a == AUNDEF {
+ return
+ }
+ r.As = ABNE
+ if a == ABNE {
+ r.As = ABEQ
+ }
+ r.Pcond = p.Link
+ r.Link = p.Pcond
+ if !(r.Link.Mark&FOLL != 0) {
+ xfol(ctxt, r.Link, last)
+ }
+ if !(r.Pcond.Mark&FOLL != 0) {
+ fmt.Printf("can't happen 2\n")
+ }
+ return
+ }
+ }
+
+ a = AB
+ q = ctxt.NewProg()
+ q.As = int16(a)
+ q.Lineno = p.Lineno
+ q.To.Type = D_BRANCH
+ q.To.Offset = p.Pc
+ q.Pcond = p
+ p = q
+ }
+
+ p.Mark |= FOLL
+ (*last).Link = p
+ *last = p
+ if a == AB || (a == ARET && p.Scond == C_SCOND_NONE) || a == ARFE || a == AUNDEF {
+ return
+ }
+
+ if p.Pcond != nil {
+ if a != ABL && a != ABX && p.Link != nil {
+ q = obj.Brchain(ctxt, p.Link)
+ if a != ATEXT && a != ABCASE {
+ if q != nil && (q.Mark&FOLL != 0) {
+ p.As = int16(relinv(a))
+ p.Link = p.Pcond
+ p.Pcond = q
+ }
+ }
+
+ xfol(ctxt, p.Link, last)
+ q = obj.Brchain(ctxt, p.Pcond)
+ if q == nil {
+ q = p.Pcond
+ }
+ if q.Mark&FOLL != 0 {
+ p.Pcond = q
+ return
+ }
+
+ p = q
+ goto loop
+ }
+ }
+
+ p = p.Link
+ goto loop
+}
+
+var Linkarm = obj.LinkArch{
+ ByteOrder: binary.LittleEndian,
+ Pconv: Pconv,
+ Name: "arm",
+ Thechar: '5',
+ Endian: obj.LittleEndian,
+ Addstacksplit: addstacksplit,
+ Assemble: span5,
+ Datasize: datasize,
+ Follow: follow,
+ Iscall: iscall,
+ Isdata: isdata,
+ Prg: prg,
+ Progedit: progedit,
+ Settextflag: settextflag,
+ Symtype: symtype,
+ Textflag: textflag,
+ Minlc: 4,
+ Ptrsize: 4,
+ Regsize: 4,
+ D_ADDR: D_ADDR,
+ D_AUTO: D_AUTO,
+ D_BRANCH: D_BRANCH,
+ D_CONST: D_CONST,
+ D_EXTERN: D_EXTERN,
+ D_FCONST: D_FCONST,
+ D_NONE: D_NONE,
+ D_PARAM: D_PARAM,
+ D_SCONST: D_SCONST,
+ D_STATIC: D_STATIC,
+ D_OREG: D_OREG,
+ ACALL: ABL,
+ ADATA: ADATA,
+ AEND: AEND,
+ AFUNCDATA: AFUNCDATA,
+ AGLOBL: AGLOBL,
+ AJMP: AB,
+ ANOP: ANOP,
+ APCDATA: APCDATA,
+ ARET: ARET,
+ ATEXT: ATEXT,
+ ATYPE: ATYPE,
+ AUSEFIELD: AUSEFIELD,
+}
--- /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.
+
+package arm
+
+func bool2int(b bool) int {
+ if b {
+ return 1
+ }
+ return 0
+}
--- /dev/null
+// Derived from Inferno utils/6l/obj.c and utils/6l/span.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package obj
+
+import (
+ "log"
+ "math"
+)
+
+func mangle(file string) {
+
+ log.Fatalf("%s: mangled input file", file)
+}
+
+func Symgrow(ctxt *Link, s *LSym, lsiz int64) {
+ var siz int
+ siz = int(lsiz)
+ if int64(siz) != lsiz {
+ log.Fatal("Symgrow size %d too long", lsiz)
+ }
+ if len(s.P) >= siz {
+ return
+ }
+ for cap(s.P) < siz {
+ s.P = append(s.P[:cap(s.P)], 0)
+ }
+ s.P = s.P[:siz]
+}
+
+func savedata(ctxt *Link, s *LSym, p *Prog, pn string) {
+ off := int32(p.From.Offset)
+ siz := int32(ctxt.Arch.Datasize(p))
+ if off < 0 || siz < 0 || off >= 1<<30 || siz >= 100 {
+ mangle(pn)
+ }
+ if ctxt.Enforce_data_order != 0 && off < int32(len(s.P)) {
+ ctxt.Diag("data out of order (already have %d)\n%P", len(s.P), p)
+ }
+ Symgrow(ctxt, s, int64(off+siz))
+
+ switch int(p.To.Type) {
+ default:
+ ctxt.Diag("bad data: %P", p)
+
+ case ctxt.Arch.D_FCONST:
+ switch siz {
+ default:
+ ctxt.Diag("unexpected %d-byte floating point constant", siz)
+
+ case 4:
+ flt := math.Float32bits(float32(p.To.U.Dval))
+ ctxt.Arch.ByteOrder.PutUint32(s.P[off:], flt)
+
+ case 8:
+ flt := math.Float64bits(p.To.U.Dval)
+ ctxt.Arch.ByteOrder.PutUint64(s.P[off:], flt)
+ }
+
+ case ctxt.Arch.D_SCONST:
+ copy(s.P[off:off+siz], p.To.U.Sval)
+
+ case ctxt.Arch.D_CONST, ctxt.Arch.D_ADDR:
+ if p.To.Sym != nil || int(p.To.Type) == ctxt.Arch.D_ADDR {
+ r := Addrel(s)
+ r.Off = off
+ r.Siz = uint8(siz)
+ r.Sym = p.To.Sym
+ r.Type = R_ADDR
+ r.Add = p.To.Offset
+ break
+ }
+ o := p.To.Offset
+ switch siz {
+ default:
+ ctxt.Diag("unexpected %d-byte integer constant", siz)
+ case 1:
+ s.P[off] = byte(o)
+ case 2:
+ ctxt.Arch.ByteOrder.PutUint16(s.P[off:], uint16(o))
+ case 4:
+ ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(o))
+ case 8:
+ ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(o))
+ }
+ }
+}
+
+func Addrel(s *LSym) *Reloc {
+ s.R = append(s.R, Reloc{})
+ return &s.R[len(s.R)-1]
+}
+
+func setuintxx(ctxt *Link, s *LSym, off int64, v uint64, wid int64) int64 {
+ if s.Type == 0 {
+ s.Type = SDATA
+ }
+ s.Reachable = 1
+ if s.Size < off+wid {
+ s.Size = off + wid
+ Symgrow(ctxt, s, s.Size)
+ }
+
+ switch wid {
+ case 1:
+ s.P[off] = uint8(v)
+ case 2:
+ ctxt.Arch.ByteOrder.PutUint16(s.P[off:], uint16(v))
+ case 4:
+ ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(v))
+ case 8:
+ ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(v))
+ }
+
+ return off + wid
+}
+
+func adduintxx(ctxt *Link, s *LSym, v uint64, wid int) int64 {
+ var off int64
+
+ off = s.Size
+ setuintxx(ctxt, s, off, v, int64(wid))
+ return off
+}
+
+func adduint8(ctxt *Link, s *LSym, v uint8) int64 {
+ return adduintxx(ctxt, s, uint64(v), 1)
+}
+
+func adduint16(ctxt *Link, s *LSym, v uint16) int64 {
+ return adduintxx(ctxt, s, uint64(v), 2)
+}
+
+func Adduint32(ctxt *Link, s *LSym, v uint32) int64 {
+ return adduintxx(ctxt, s, uint64(v), 4)
+}
+
+func Adduint64(ctxt *Link, s *LSym, v uint64) int64 {
+ return adduintxx(ctxt, s, v, 8)
+}
+
+func setuint8(ctxt *Link, s *LSym, r int64, v uint8) int64 {
+ return setuintxx(ctxt, s, r, uint64(v), 1)
+}
+
+func setuint16(ctxt *Link, s *LSym, r int64, v uint16) int64 {
+ return setuintxx(ctxt, s, r, uint64(v), 2)
+}
+
+func setuint32(ctxt *Link, s *LSym, r int64, v uint32) int64 {
+ return setuintxx(ctxt, s, r, uint64(v), 4)
+}
+
+func setuint64(ctxt *Link, s *LSym, r int64, v uint64) int64 {
+ return setuintxx(ctxt, s, r, v, 8)
+}
+
+func addaddrplus(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
+ var i int64
+ var r *Reloc
+
+ if s.Type == 0 {
+ s.Type = SDATA
+ }
+ s.Reachable = 1
+ i = s.Size
+ s.Size += int64(ctxt.Arch.Ptrsize)
+ Symgrow(ctxt, s, s.Size)
+ r = Addrel(s)
+ r.Sym = t
+ r.Off = int32(i)
+ r.Siz = uint8(ctxt.Arch.Ptrsize)
+ r.Type = R_ADDR
+ r.Add = add
+ return i + int64(r.Siz)
+}
+
+func addpcrelplus(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
+ var i int64
+ var r *Reloc
+
+ if s.Type == 0 {
+ s.Type = SDATA
+ }
+ s.Reachable = 1
+ i = s.Size
+ s.Size += 4
+ Symgrow(ctxt, s, s.Size)
+ r = Addrel(s)
+ r.Sym = t
+ r.Off = int32(i)
+ r.Add = add
+ r.Type = R_PCREL
+ r.Siz = 4
+ return i + int64(r.Siz)
+}
+
+func addaddr(ctxt *Link, s *LSym, t *LSym) int64 {
+ return addaddrplus(ctxt, s, t, 0)
+}
+
+func setaddrplus(ctxt *Link, s *LSym, off int64, t *LSym, add int64) int64 {
+ var r *Reloc
+
+ if s.Type == 0 {
+ s.Type = SDATA
+ }
+ s.Reachable = 1
+ if off+int64(ctxt.Arch.Ptrsize) > s.Size {
+ s.Size = off + int64(ctxt.Arch.Ptrsize)
+ Symgrow(ctxt, s, s.Size)
+ }
+
+ r = Addrel(s)
+ r.Sym = t
+ r.Off = int32(off)
+ r.Siz = uint8(ctxt.Arch.Ptrsize)
+ r.Type = R_ADDR
+ r.Add = add
+ return off + int64(r.Siz)
+}
+
+func setaddr(ctxt *Link, s *LSym, off int64, t *LSym) int64 {
+ return setaddrplus(ctxt, s, off, t, 0)
+}
+
+func addsize(ctxt *Link, s *LSym, t *LSym) int64 {
+ var i int64
+ var r *Reloc
+
+ if s.Type == 0 {
+ s.Type = SDATA
+ }
+ s.Reachable = 1
+ i = s.Size
+ s.Size += int64(ctxt.Arch.Ptrsize)
+ Symgrow(ctxt, s, s.Size)
+ r = Addrel(s)
+ r.Sym = t
+ r.Off = int32(i)
+ r.Siz = uint8(ctxt.Arch.Ptrsize)
+ r.Type = R_SIZE
+ return i + int64(r.Siz)
+}
+
+func addaddrplus4(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
+ var i int64
+ var r *Reloc
+
+ if s.Type == 0 {
+ s.Type = SDATA
+ }
+ s.Reachable = 1
+ i = s.Size
+ s.Size += 4
+ Symgrow(ctxt, s, s.Size)
+ r = Addrel(s)
+ r.Sym = t
+ r.Off = int32(i)
+ r.Siz = 4
+ r.Type = R_ADDR
+ r.Add = add
+ return i + int64(r.Siz)
+}
--- /dev/null
+/*
+ * The authors of this software are Rob Pike and Ken Thompson.
+ * Copyright (c) 2002 by Lucent Technologies.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+package obj
+
+// (The comments in this file were copied from the manpage files rune.3,
+// isalpharune.3, and runestrcat.3. Some formatting changes were also made
+// to conform to Google style. /JRM 11/11/05)
+
+type Fmt struct {
+ runes uint8
+ start interface{}
+ to interface{}
+ stop interface{}
+ flush func(*Fmt) int
+ farg interface{}
+ nfmt int
+ args []interface{}
+ r uint
+ width int
+ prec int
+ flags uint32
+ decimal string
+ thousands string
+ grouping string
+}
+
+const (
+ FmtWidth = 1
+ FmtLeft = FmtWidth << 1
+ FmtPrec = FmtLeft << 1
+ FmtSharp = FmtPrec << 1
+ FmtSpace = FmtSharp << 1
+ FmtSign = FmtSpace << 1
+ FmtApost = FmtSign << 1
+ FmtZero = FmtApost << 1
+ FmtUnsigned = FmtZero << 1
+ FmtShort = FmtUnsigned << 1
+ FmtLong = FmtShort << 1
+ FmtVLong = FmtLong << 1
+ FmtComma = FmtVLong << 1
+ FmtByte = FmtComma << 1
+ FmtLDouble = FmtByte << 1
+ FmtFlag = FmtLDouble << 1
+)
+
+var fmtdoquote func(int) int
+
+/* Edit .+1,/^$/ | cfn $PLAN9/src/lib9/fmt/?*.c | grep -v static |grep -v __ */
--- /dev/null
+// cmd/9l/noop.c, cmd/9l/pass.c, cmd/9l/span.c from Vita Nuova.
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package obj
+
+// Copyright 2013 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 defines the IDs for PCDATA and FUNCDATA instructions
+// in Go binaries. It is included by assembly sources, so it must
+// be written using #defines.
+//
+// The Go compiler also #includes this file, for now.
+//
+// symtab.go also contains a copy of these constants.
+
+// Pseudo-assembly statements.
+
+// GO_ARGS, GO_RESULTS_INITIALIZED, and NO_LOCAL_POINTERS are macros
+// that communicate to the runtime information about the location and liveness
+// of pointers in an assembly function's arguments, results, and stack frame.
+// This communication is only required in assembly functions that make calls
+// to other functions that might be preempted or grow the stack.
+// NOSPLIT functions that make no calls do not need to use these macros.
+
+// GO_ARGS indicates that the Go prototype for this assembly function
+// defines the pointer map for the function's arguments.
+// GO_ARGS should be the first instruction in a function that uses it.
+// It can be omitted if there are no arguments at all.
+// GO_ARGS is inserted implicitly by the linker for any function
+// that also has a Go prototype and therefore is usually not necessary
+// to write explicitly.
+
+// GO_RESULTS_INITIALIZED indicates that the assembly function
+// has initialized the stack space for its results and that those results
+// should be considered live for the remainder of the function.
+
+// NO_LOCAL_POINTERS indicates that the assembly function stores
+// no pointers to heap objects in its local stack variables.
+
+// ArgsSizeUnknown is set in Func.argsize to mark all functions
+// whose argument size is unknown (C vararg functions, and
+// assembly code without an explicit specification).
+// This value is generated by the compiler, assembler, or linker.
+const (
+ PCDATA_StackMapIndex = 0
+ FUNCDATA_ArgsPointerMaps = 0
+ FUNCDATA_LocalsPointerMaps = 1
+ FUNCDATA_DeadValueMaps = 2
+ ArgsSizeUnknown = 0x80000000
+)
--- /dev/null
+// Copyright 2009 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 obj
+
+import (
+ "math"
+ "strings"
+)
+
+// go-specific code shared across loaders (5l, 6l, 8l).
+
+// replace all "". with pkg.
+func expandpkg(t0 string, pkg string) string {
+ return strings.Replace(t0, `"".`, pkg+".", -1)
+}
+
+func double2ieee(ieee *uint64, f float64) {
+ *ieee = math.Float64bits(f)
+}
--- /dev/null
+// Inferno utils/8c/8.out.h
+// http://code.google.com/p/inferno-os/source/browse/utils/8c/8.out.h
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package i386
+
+const (
+ AXXX = iota
+ AAAA
+ AAAD
+ AAAM
+ AAAS
+ AADCB
+ AADCL
+ AADCW
+ AADDB
+ AADDL
+ AADDW
+ AADJSP
+ AANDB
+ AANDL
+ AANDW
+ AARPL
+ ABOUNDL
+ ABOUNDW
+ ABSFL
+ ABSFW
+ ABSRL
+ ABSRW
+ ABTL
+ ABTW
+ ABTCL
+ ABTCW
+ ABTRL
+ ABTRW
+ ABTSL
+ ABTSW
+ ABYTE
+ ACALL
+ ACLC
+ ACLD
+ ACLI
+ ACLTS
+ ACMC
+ ACMPB
+ ACMPL
+ ACMPW
+ ACMPSB
+ ACMPSL
+ ACMPSW
+ ADAA
+ ADAS
+ ADATA
+ ADECB
+ ADECL
+ ADECW
+ ADIVB
+ ADIVL
+ ADIVW
+ AENTER
+ AGLOBL
+ AGOK
+ AHISTORY
+ AHLT
+ AIDIVB
+ AIDIVL
+ AIDIVW
+ AIMULB
+ AIMULL
+ AIMULW
+ AINB
+ AINL
+ AINW
+ AINCB
+ AINCL
+ AINCW
+ AINSB
+ AINSL
+ AINSW
+ AINT
+ AINTO
+ AIRETL
+ AIRETW
+ AJCC
+ AJCS
+ AJCXZL
+ AJCXZW
+ AJEQ
+ AJGE
+ AJGT
+ AJHI
+ AJLE
+ AJLS
+ AJLT
+ AJMI
+ AJMP
+ AJNE
+ AJOC
+ AJOS
+ AJPC
+ AJPL
+ AJPS
+ ALAHF
+ ALARL
+ ALARW
+ ALEAL
+ ALEAW
+ ALEAVEL
+ ALEAVEW
+ ALOCK
+ ALODSB
+ ALODSL
+ ALODSW
+ ALONG
+ ALOOP
+ ALOOPEQ
+ ALOOPNE
+ ALSLL
+ ALSLW
+ AMOVB
+ AMOVL
+ AMOVW
+ AMOVQ
+ AMOVBLSX
+ AMOVBLZX
+ AMOVBWSX
+ AMOVBWZX
+ AMOVWLSX
+ AMOVWLZX
+ AMOVSB
+ AMOVSL
+ AMOVSW
+ AMULB
+ AMULL
+ AMULW
+ ANAME
+ ANEGB
+ ANEGL
+ ANEGW
+ ANOP
+ ANOTB
+ ANOTL
+ ANOTW
+ AORB
+ AORL
+ AORW
+ AOUTB
+ AOUTL
+ AOUTW
+ AOUTSB
+ AOUTSL
+ AOUTSW
+ APAUSE
+ APOPAL
+ APOPAW
+ APOPFL
+ APOPFW
+ APOPL
+ APOPW
+ APUSHAL
+ APUSHAW
+ APUSHFL
+ APUSHFW
+ APUSHL
+ APUSHW
+ ARCLB
+ ARCLL
+ ARCLW
+ ARCRB
+ ARCRL
+ ARCRW
+ AREP
+ AREPN
+ ARET
+ AROLB
+ AROLL
+ AROLW
+ ARORB
+ ARORL
+ ARORW
+ ASAHF
+ ASALB
+ ASALL
+ ASALW
+ ASARB
+ ASARL
+ ASARW
+ ASBBB
+ ASBBL
+ ASBBW
+ ASCASB
+ ASCASL
+ ASCASW
+ ASETCC
+ ASETCS
+ ASETEQ
+ ASETGE
+ ASETGT
+ ASETHI
+ ASETLE
+ ASETLS
+ ASETLT
+ ASETMI
+ ASETNE
+ ASETOC
+ ASETOS
+ ASETPC
+ ASETPL
+ ASETPS
+ ACDQ
+ ACWD
+ ASHLB
+ ASHLL
+ ASHLW
+ ASHRB
+ ASHRL
+ ASHRW
+ ASTC
+ ASTD
+ ASTI
+ ASTOSB
+ ASTOSL
+ ASTOSW
+ ASUBB
+ ASUBL
+ ASUBW
+ ASYSCALL
+ ATESTB
+ ATESTL
+ ATESTW
+ ATEXT
+ AVERR
+ AVERW
+ AWAIT
+ AWORD
+ AXCHGB
+ AXCHGL
+ AXCHGW
+ AXLAT
+ AXORB
+ AXORL
+ AXORW
+ AFMOVB
+ AFMOVBP
+ AFMOVD
+ AFMOVDP
+ AFMOVF
+ AFMOVFP
+ AFMOVL
+ AFMOVLP
+ AFMOVV
+ AFMOVVP
+ AFMOVW
+ AFMOVWP
+ AFMOVX
+ AFMOVXP
+ AFCOMB
+ AFCOMBP
+ AFCOMD
+ AFCOMDP
+ AFCOMDPP
+ AFCOMF
+ AFCOMFP
+ AFCOMI
+ AFCOMIP
+ AFCOML
+ AFCOMLP
+ AFCOMW
+ AFCOMWP
+ AFUCOM
+ AFUCOMI
+ AFUCOMIP
+ AFUCOMP
+ AFUCOMPP
+ AFADDDP
+ AFADDW
+ AFADDL
+ AFADDF
+ AFADDD
+ AFMULDP
+ AFMULW
+ AFMULL
+ AFMULF
+ AFMULD
+ AFSUBDP
+ AFSUBW
+ AFSUBL
+ AFSUBF
+ AFSUBD
+ AFSUBRDP
+ AFSUBRW
+ AFSUBRL
+ AFSUBRF
+ AFSUBRD
+ AFDIVDP
+ AFDIVW
+ AFDIVL
+ AFDIVF
+ AFDIVD
+ AFDIVRDP
+ AFDIVRW
+ AFDIVRL
+ AFDIVRF
+ AFDIVRD
+ AFXCHD
+ AFFREE
+ AFLDCW
+ AFLDENV
+ AFRSTOR
+ AFSAVE
+ AFSTCW
+ AFSTENV
+ AFSTSW
+ AF2XM1
+ AFABS
+ AFCHS
+ AFCLEX
+ AFCOS
+ AFDECSTP
+ AFINCSTP
+ AFINIT
+ AFLD1
+ AFLDL2E
+ AFLDL2T
+ AFLDLG2
+ AFLDLN2
+ AFLDPI
+ AFLDZ
+ AFNOP
+ AFPATAN
+ AFPREM
+ AFPREM1
+ AFPTAN
+ AFRNDINT
+ AFSCALE
+ AFSIN
+ AFSINCOS
+ AFSQRT
+ AFTST
+ AFXAM
+ AFXTRACT
+ AFYL2X
+ AFYL2XP1
+ AEND
+ ADYNT_
+ AINIT_
+ ASIGNAME
+ ACMPXCHGB
+ ACMPXCHGL
+ ACMPXCHGW
+ ACMPXCHG8B
+ ACPUID
+ ARDTSC
+ AXADDB
+ AXADDL
+ AXADDW
+ ACMOVLCC
+ ACMOVLCS
+ ACMOVLEQ
+ ACMOVLGE
+ ACMOVLGT
+ ACMOVLHI
+ ACMOVLLE
+ ACMOVLLS
+ ACMOVLLT
+ ACMOVLMI
+ ACMOVLNE
+ ACMOVLOC
+ ACMOVLOS
+ ACMOVLPC
+ ACMOVLPL
+ ACMOVLPS
+ ACMOVWCC
+ ACMOVWCS
+ ACMOVWEQ
+ ACMOVWGE
+ ACMOVWGT
+ ACMOVWHI
+ ACMOVWLE
+ ACMOVWLS
+ ACMOVWLT
+ ACMOVWMI
+ ACMOVWNE
+ ACMOVWOC
+ ACMOVWOS
+ ACMOVWPC
+ ACMOVWPL
+ ACMOVWPS
+ AFCMOVCC
+ AFCMOVCS
+ AFCMOVEQ
+ AFCMOVHI
+ AFCMOVLS
+ AFCMOVNE
+ AFCMOVNU
+ AFCMOVUN
+ ALFENCE
+ AMFENCE
+ ASFENCE
+ AEMMS
+ APREFETCHT0
+ APREFETCHT1
+ APREFETCHT2
+ APREFETCHNTA
+ ABSWAPL
+ AUNDEF
+ AADDPD
+ AADDPS
+ AADDSD
+ AADDSS
+ AANDNPD
+ AANDNPS
+ AANDPD
+ AANDPS
+ ACMPPD
+ ACMPPS
+ ACMPSD
+ ACMPSS
+ ACOMISD
+ ACOMISS
+ ACVTPL2PD
+ ACVTPL2PS
+ ACVTPD2PL
+ ACVTPD2PS
+ ACVTPS2PL
+ ACVTPS2PD
+ ACVTSD2SL
+ ACVTSD2SS
+ ACVTSL2SD
+ ACVTSL2SS
+ ACVTSS2SD
+ ACVTSS2SL
+ ACVTTPD2PL
+ ACVTTPS2PL
+ ACVTTSD2SL
+ ACVTTSS2SL
+ ADIVPD
+ ADIVPS
+ ADIVSD
+ ADIVSS
+ AMASKMOVOU
+ AMAXPD
+ AMAXPS
+ AMAXSD
+ AMAXSS
+ AMINPD
+ AMINPS
+ AMINSD
+ AMINSS
+ AMOVAPD
+ AMOVAPS
+ AMOVO
+ AMOVOU
+ AMOVHLPS
+ AMOVHPD
+ AMOVHPS
+ AMOVLHPS
+ AMOVLPD
+ AMOVLPS
+ AMOVMSKPD
+ AMOVMSKPS
+ AMOVNTO
+ AMOVNTPD
+ AMOVNTPS
+ AMOVSD
+ AMOVSS
+ AMOVUPD
+ AMOVUPS
+ AMULPD
+ AMULPS
+ AMULSD
+ AMULSS
+ AORPD
+ AORPS
+ APADDQ
+ APAND
+ APCMPEQB
+ APMAXSW
+ APMAXUB
+ APMINSW
+ APMINUB
+ APMOVMSKB
+ APSADBW
+ APSUBB
+ APSUBL
+ APSUBQ
+ APSUBSB
+ APSUBSW
+ APSUBUSB
+ APSUBUSW
+ APSUBW
+ APUNPCKHQDQ
+ APUNPCKLQDQ
+ APXOR
+ ARCPPS
+ ARCPSS
+ ARSQRTPS
+ ARSQRTSS
+ ASQRTPD
+ ASQRTPS
+ ASQRTSD
+ ASQRTSS
+ ASUBPD
+ ASUBPS
+ ASUBSD
+ ASUBSS
+ AUCOMISD
+ AUCOMISS
+ AUNPCKHPD
+ AUNPCKHPS
+ AUNPCKLPD
+ AUNPCKLPS
+ AXORPD
+ AXORPS
+ APSHUFHW
+ APSHUFL
+ APSHUFLW
+ AAESENC
+ APINSRD
+ APSHUFB
+ AUSEFIELD
+ ATYPE
+ AFUNCDATA
+ APCDATA
+ ACHECKNIL
+ AVARDEF
+ AVARKILL
+ ADUFFCOPY
+ ADUFFZERO
+ ALAST
+)
+
+const (
+ D_AL = 0 + iota
+ D_CL
+ D_DL
+ D_BL
+ D_AH = 4 + iota - 4
+ D_CH
+ D_DH
+ D_BH
+ D_AX = 8 + iota - 8
+ D_CX
+ D_DX
+ D_BX
+ D_SP
+ D_BP
+ D_SI
+ D_DI
+ D_F0 = 16
+ D_F7 = D_F0 + 7
+ D_CS = 24 + iota - 18
+ D_SS
+ D_DS
+ D_ES
+ D_FS
+ D_GS
+ D_GDTR
+ D_IDTR
+ D_LDTR
+ D_MSW
+ D_TASK
+ D_CR = 35
+ D_DR = 43
+ D_TR = 51
+ D_X0 = 59 + iota - 32
+ D_X1
+ D_X2
+ D_X3
+ D_X4
+ D_X5
+ D_X6
+ D_X7
+ D_TLS = 67
+ D_NONE = 68
+ D_BRANCH = 69
+ D_EXTERN = 70
+ D_STATIC = 71
+ D_AUTO = 72
+ D_PARAM = 73
+ D_CONST = 74
+ D_FCONST = 75
+ D_SCONST = 76
+ D_ADDR = 77 + iota - 50
+ D_INDIR
+ D_CONST2 = D_INDIR + D_INDIR + iota - 52
+ D_LAST
+ T_TYPE = 1 << 0
+ T_INDEX = 1 << 1
+ T_OFFSET = 1 << 2
+ T_FCONST = 1 << 3
+ T_SYM = 1 << 4
+ T_SCONST = 1 << 5
+ T_OFFSET2 = 1 << 6
+ T_GOTYPE = 1 << 7
+ REGARG = -1
+ REGRET = D_AX
+ FREGRET = D_F0
+ REGSP = D_SP
+ REGTMP = D_DI
+)
--- /dev/null
+package i386
+
+/*
+ * this is the ranlib header
+ */
+var Anames = []string{
+ "XXX",
+ "AAA",
+ "AAD",
+ "AAM",
+ "AAS",
+ "ADCB",
+ "ADCL",
+ "ADCW",
+ "ADDB",
+ "ADDL",
+ "ADDW",
+ "ADJSP",
+ "ANDB",
+ "ANDL",
+ "ANDW",
+ "ARPL",
+ "BOUNDL",
+ "BOUNDW",
+ "BSFL",
+ "BSFW",
+ "BSRL",
+ "BSRW",
+ "BTL",
+ "BTW",
+ "BTCL",
+ "BTCW",
+ "BTRL",
+ "BTRW",
+ "BTSL",
+ "BTSW",
+ "BYTE",
+ "CALL",
+ "CLC",
+ "CLD",
+ "CLI",
+ "CLTS",
+ "CMC",
+ "CMPB",
+ "CMPL",
+ "CMPW",
+ "CMPSB",
+ "CMPSL",
+ "CMPSW",
+ "DAA",
+ "DAS",
+ "DATA",
+ "DECB",
+ "DECL",
+ "DECW",
+ "DIVB",
+ "DIVL",
+ "DIVW",
+ "ENTER",
+ "GLOBL",
+ "GOK",
+ "HISTORY",
+ "HLT",
+ "IDIVB",
+ "IDIVL",
+ "IDIVW",
+ "IMULB",
+ "IMULL",
+ "IMULW",
+ "INB",
+ "INL",
+ "INW",
+ "INCB",
+ "INCL",
+ "INCW",
+ "INSB",
+ "INSL",
+ "INSW",
+ "INT",
+ "INTO",
+ "IRETL",
+ "IRETW",
+ "JCC",
+ "JCS",
+ "JCXZL",
+ "JCXZW",
+ "JEQ",
+ "JGE",
+ "JGT",
+ "JHI",
+ "JLE",
+ "JLS",
+ "JLT",
+ "JMI",
+ "JMP",
+ "JNE",
+ "JOC",
+ "JOS",
+ "JPC",
+ "JPL",
+ "JPS",
+ "LAHF",
+ "LARL",
+ "LARW",
+ "LEAL",
+ "LEAW",
+ "LEAVEL",
+ "LEAVEW",
+ "LOCK",
+ "LODSB",
+ "LODSL",
+ "LODSW",
+ "LONG",
+ "LOOP",
+ "LOOPEQ",
+ "LOOPNE",
+ "LSLL",
+ "LSLW",
+ "MOVB",
+ "MOVL",
+ "MOVW",
+ "MOVQ",
+ "MOVBLSX",
+ "MOVBLZX",
+ "MOVBWSX",
+ "MOVBWZX",
+ "MOVWLSX",
+ "MOVWLZX",
+ "MOVSB",
+ "MOVSL",
+ "MOVSW",
+ "MULB",
+ "MULL",
+ "MULW",
+ "NAME",
+ "NEGB",
+ "NEGL",
+ "NEGW",
+ "NOP",
+ "NOTB",
+ "NOTL",
+ "NOTW",
+ "ORB",
+ "ORL",
+ "ORW",
+ "OUTB",
+ "OUTL",
+ "OUTW",
+ "OUTSB",
+ "OUTSL",
+ "OUTSW",
+ "PAUSE",
+ "POPAL",
+ "POPAW",
+ "POPFL",
+ "POPFW",
+ "POPL",
+ "POPW",
+ "PUSHAL",
+ "PUSHAW",
+ "PUSHFL",
+ "PUSHFW",
+ "PUSHL",
+ "PUSHW",
+ "RCLB",
+ "RCLL",
+ "RCLW",
+ "RCRB",
+ "RCRL",
+ "RCRW",
+ "REP",
+ "REPN",
+ "RET",
+ "ROLB",
+ "ROLL",
+ "ROLW",
+ "RORB",
+ "RORL",
+ "RORW",
+ "SAHF",
+ "SALB",
+ "SALL",
+ "SALW",
+ "SARB",
+ "SARL",
+ "SARW",
+ "SBBB",
+ "SBBL",
+ "SBBW",
+ "SCASB",
+ "SCASL",
+ "SCASW",
+ "SETCC",
+ "SETCS",
+ "SETEQ",
+ "SETGE",
+ "SETGT",
+ "SETHI",
+ "SETLE",
+ "SETLS",
+ "SETLT",
+ "SETMI",
+ "SETNE",
+ "SETOC",
+ "SETOS",
+ "SETPC",
+ "SETPL",
+ "SETPS",
+ "CDQ",
+ "CWD",
+ "SHLB",
+ "SHLL",
+ "SHLW",
+ "SHRB",
+ "SHRL",
+ "SHRW",
+ "STC",
+ "STD",
+ "STI",
+ "STOSB",
+ "STOSL",
+ "STOSW",
+ "SUBB",
+ "SUBL",
+ "SUBW",
+ "SYSCALL",
+ "TESTB",
+ "TESTL",
+ "TESTW",
+ "TEXT",
+ "VERR",
+ "VERW",
+ "WAIT",
+ "WORD",
+ "XCHGB",
+ "XCHGL",
+ "XCHGW",
+ "XLAT",
+ "XORB",
+ "XORL",
+ "XORW",
+ "FMOVB",
+ "FMOVBP",
+ "FMOVD",
+ "FMOVDP",
+ "FMOVF",
+ "FMOVFP",
+ "FMOVL",
+ "FMOVLP",
+ "FMOVV",
+ "FMOVVP",
+ "FMOVW",
+ "FMOVWP",
+ "FMOVX",
+ "FMOVXP",
+ "FCOMB",
+ "FCOMBP",
+ "FCOMD",
+ "FCOMDP",
+ "FCOMDPP",
+ "FCOMF",
+ "FCOMFP",
+ "FCOMI",
+ "FCOMIP",
+ "FCOML",
+ "FCOMLP",
+ "FCOMW",
+ "FCOMWP",
+ "FUCOM",
+ "FUCOMI",
+ "FUCOMIP",
+ "FUCOMP",
+ "FUCOMPP",
+ "FADDDP",
+ "FADDW",
+ "FADDL",
+ "FADDF",
+ "FADDD",
+ "FMULDP",
+ "FMULW",
+ "FMULL",
+ "FMULF",
+ "FMULD",
+ "FSUBDP",
+ "FSUBW",
+ "FSUBL",
+ "FSUBF",
+ "FSUBD",
+ "FSUBRDP",
+ "FSUBRW",
+ "FSUBRL",
+ "FSUBRF",
+ "FSUBRD",
+ "FDIVDP",
+ "FDIVW",
+ "FDIVL",
+ "FDIVF",
+ "FDIVD",
+ "FDIVRDP",
+ "FDIVRW",
+ "FDIVRL",
+ "FDIVRF",
+ "FDIVRD",
+ "FXCHD",
+ "FFREE",
+ "FLDCW",
+ "FLDENV",
+ "FRSTOR",
+ "FSAVE",
+ "FSTCW",
+ "FSTENV",
+ "FSTSW",
+ "F2XM1",
+ "FABS",
+ "FCHS",
+ "FCLEX",
+ "FCOS",
+ "FDECSTP",
+ "FINCSTP",
+ "FINIT",
+ "FLD1",
+ "FLDL2E",
+ "FLDL2T",
+ "FLDLG2",
+ "FLDLN2",
+ "FLDPI",
+ "FLDZ",
+ "FNOP",
+ "FPATAN",
+ "FPREM",
+ "FPREM1",
+ "FPTAN",
+ "FRNDINT",
+ "FSCALE",
+ "FSIN",
+ "FSINCOS",
+ "FSQRT",
+ "FTST",
+ "FXAM",
+ "FXTRACT",
+ "FYL2X",
+ "FYL2XP1",
+ "END",
+ "DYNT_",
+ "INIT_",
+ "SIGNAME",
+ "CMPXCHGB",
+ "CMPXCHGL",
+ "CMPXCHGW",
+ "CMPXCHG8B",
+ "CPUID",
+ "RDTSC",
+ "XADDB",
+ "XADDL",
+ "XADDW",
+ "CMOVLCC",
+ "CMOVLCS",
+ "CMOVLEQ",
+ "CMOVLGE",
+ "CMOVLGT",
+ "CMOVLHI",
+ "CMOVLLE",
+ "CMOVLLS",
+ "CMOVLLT",
+ "CMOVLMI",
+ "CMOVLNE",
+ "CMOVLOC",
+ "CMOVLOS",
+ "CMOVLPC",
+ "CMOVLPL",
+ "CMOVLPS",
+ "CMOVWCC",
+ "CMOVWCS",
+ "CMOVWEQ",
+ "CMOVWGE",
+ "CMOVWGT",
+ "CMOVWHI",
+ "CMOVWLE",
+ "CMOVWLS",
+ "CMOVWLT",
+ "CMOVWMI",
+ "CMOVWNE",
+ "CMOVWOC",
+ "CMOVWOS",
+ "CMOVWPC",
+ "CMOVWPL",
+ "CMOVWPS",
+ "FCMOVCC",
+ "FCMOVCS",
+ "FCMOVEQ",
+ "FCMOVHI",
+ "FCMOVLS",
+ "FCMOVNE",
+ "FCMOVNU",
+ "FCMOVUN",
+ "LFENCE",
+ "MFENCE",
+ "SFENCE",
+ "EMMS",
+ "PREFETCHT0",
+ "PREFETCHT1",
+ "PREFETCHT2",
+ "PREFETCHNTA",
+ "BSWAPL",
+ "UNDEF",
+ "ADDPD",
+ "ADDPS",
+ "ADDSD",
+ "ADDSS",
+ "ANDNPD",
+ "ANDNPS",
+ "ANDPD",
+ "ANDPS",
+ "CMPPD",
+ "CMPPS",
+ "CMPSD",
+ "CMPSS",
+ "COMISD",
+ "COMISS",
+ "CVTPL2PD",
+ "CVTPL2PS",
+ "CVTPD2PL",
+ "CVTPD2PS",
+ "CVTPS2PL",
+ "CVTPS2PD",
+ "CVTSD2SL",
+ "CVTSD2SS",
+ "CVTSL2SD",
+ "CVTSL2SS",
+ "CVTSS2SD",
+ "CVTSS2SL",
+ "CVTTPD2PL",
+ "CVTTPS2PL",
+ "CVTTSD2SL",
+ "CVTTSS2SL",
+ "DIVPD",
+ "DIVPS",
+ "DIVSD",
+ "DIVSS",
+ "MASKMOVOU",
+ "MAXPD",
+ "MAXPS",
+ "MAXSD",
+ "MAXSS",
+ "MINPD",
+ "MINPS",
+ "MINSD",
+ "MINSS",
+ "MOVAPD",
+ "MOVAPS",
+ "MOVO",
+ "MOVOU",
+ "MOVHLPS",
+ "MOVHPD",
+ "MOVHPS",
+ "MOVLHPS",
+ "MOVLPD",
+ "MOVLPS",
+ "MOVMSKPD",
+ "MOVMSKPS",
+ "MOVNTO",
+ "MOVNTPD",
+ "MOVNTPS",
+ "MOVSD",
+ "MOVSS",
+ "MOVUPD",
+ "MOVUPS",
+ "MULPD",
+ "MULPS",
+ "MULSD",
+ "MULSS",
+ "ORPD",
+ "ORPS",
+ "PADDQ",
+ "PAND",
+ "PCMPEQB",
+ "PMAXSW",
+ "PMAXUB",
+ "PMINSW",
+ "PMINUB",
+ "PMOVMSKB",
+ "PSADBW",
+ "PSUBB",
+ "PSUBL",
+ "PSUBQ",
+ "PSUBSB",
+ "PSUBSW",
+ "PSUBUSB",
+ "PSUBUSW",
+ "PSUBW",
+ "PUNPCKHQDQ",
+ "PUNPCKLQDQ",
+ "PXOR",
+ "RCPPS",
+ "RCPSS",
+ "RSQRTPS",
+ "RSQRTSS",
+ "SQRTPD",
+ "SQRTPS",
+ "SQRTSD",
+ "SQRTSS",
+ "SUBPD",
+ "SUBPS",
+ "SUBSD",
+ "SUBSS",
+ "UCOMISD",
+ "UCOMISS",
+ "UNPCKHPD",
+ "UNPCKHPS",
+ "UNPCKLPD",
+ "UNPCKLPS",
+ "XORPD",
+ "XORPS",
+ "PSHUFHW",
+ "PSHUFL",
+ "PSHUFLW",
+ "AESENC",
+ "PINSRD",
+ "PSHUFB",
+ "USEFIELD",
+ "TYPE",
+ "FUNCDATA",
+ "PCDATA",
+ "CHECKNIL",
+ "VARDEF",
+ "VARKILL",
+ "DUFFCOPY",
+ "DUFFZERO",
+ "LAST",
+}
+
+var dnames8 = []string{
+ D_AL: "AL",
+ D_CL: "CL",
+ D_DL: "DL",
+ D_BL: "BL",
+ D_AH: "AH",
+ D_CH: "CH",
+ D_DH: "DH",
+ D_BH: "BH",
+ D_AX: "AX",
+ D_CX: "CX",
+ D_DX: "DX",
+ D_BX: "BX",
+ D_SP: "SP",
+ D_BP: "BP",
+ D_SI: "SI",
+ D_DI: "DI",
+ D_F0: "F0",
+ D_CS: "CS",
+ D_SS: "SS",
+ D_DS: "DS",
+ D_ES: "ES",
+ D_FS: "FS",
+ D_GS: "GS",
+ D_GDTR: "GDTR",
+ D_IDTR: "IDTR",
+ D_LDTR: "LDTR",
+ D_MSW: "MSW",
+ D_TASK: "TASK",
+ D_CR: "CR",
+ D_DR: "DR",
+ D_TR: "TR",
+ D_X0: "X0",
+ D_X1: "X1",
+ D_X2: "X2",
+ D_X3: "X3",
+ D_X4: "X4",
+ D_X5: "X5",
+ D_X6: "X6",
+ D_X7: "X7",
+ D_TLS: "TLS",
+ D_NONE: "NONE",
+ D_BRANCH: "BRANCH",
+ D_EXTERN: "EXTERN",
+ D_STATIC: "STATIC",
+ D_AUTO: "AUTO",
+ D_PARAM: "PARAM",
+ D_CONST: "CONST",
+ D_FCONST: "FCONST",
+ D_SCONST: "SCONST",
+ D_ADDR: "ADDR",
+ D_INDIR: "INDIR",
+}
--- /dev/null
+// Inferno utils/8l/span.c
+// http://code.google.com/p/inferno-os/source/browse/utils/8l/span.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package i386
+
+import (
+ "cmd/internal/obj"
+ "fmt"
+ "log"
+)
+
+// Instruction layout.
+
+const (
+ MaxAlign = 32
+ FuncAlign = 16
+)
+
+type Optab struct {
+ as int16
+ ytab []byte
+ prefix uint8
+ op [13]uint8
+}
+
+const (
+ Yxxx = 0 + iota
+ Ynone
+ Yi0
+ Yi1
+ Yi8
+ Yi32
+ Yiauto
+ Yal
+ Ycl
+ Yax
+ Ycx
+ Yrb
+ Yrl
+ Yrf
+ Yf0
+ Yrx
+ Ymb
+ Yml
+ Ym
+ Ybr
+ Ycol
+ Ytls
+ Ycs
+ Yss
+ Yds
+ Yes
+ Yfs
+ Ygs
+ Ygdtr
+ Yidtr
+ Yldtr
+ Ymsw
+ Ytask
+ Ycr0
+ Ycr1
+ Ycr2
+ Ycr3
+ Ycr4
+ Ycr5
+ Ycr6
+ Ycr7
+ Ydr0
+ Ydr1
+ Ydr2
+ Ydr3
+ Ydr4
+ Ydr5
+ Ydr6
+ Ydr7
+ Ytr0
+ Ytr1
+ Ytr2
+ Ytr3
+ Ytr4
+ Ytr5
+ Ytr6
+ Ytr7
+ Ymr
+ Ymm
+ Yxr
+ Yxm
+ Ymax
+ Zxxx = 0 + iota - 62
+ Zlit
+ Zlitm_r
+ Z_rp
+ Zbr
+ Zcall
+ Zcallcon
+ Zcallind
+ Zcallindreg
+ Zib_
+ Zib_rp
+ Zibo_m
+ Zil_
+ Zil_rp
+ Zilo_m
+ Zjmp
+ Zjmpcon
+ Zloop
+ Zm_o
+ Zm_r
+ Zm2_r
+ Zm_r_xm
+ Zm_r_i_xm
+ Zaut_r
+ Zo_m
+ Zpseudo
+ Zr_m
+ Zr_m_xm
+ Zr_m_i_xm
+ Zrp_
+ Z_ib
+ Z_il
+ Zm_ibo
+ Zm_ilo
+ Zib_rr
+ Zil_rr
+ Zclr
+ Zibm_r
+ Zbyte
+ Zmov
+ Zmax
+ Px = 0
+ Pe = 0x66
+ Pm = 0x0f
+ Pq = 0xff
+ Pb = 0xfe
+ Pf2 = 0xf2
+ Pf3 = 0xf3
+)
+
+var ycover [Ymax * Ymax]uint8
+
+var reg [D_NONE]int
+
+var ynone = []uint8{
+ Ynone,
+ Ynone,
+ Zlit,
+ 1,
+ 0,
+}
+
+var ytext = []uint8{
+ Ymb,
+ Yi32,
+ Zpseudo,
+ 1,
+ 0,
+}
+
+var ynop = []uint8{
+ Ynone,
+ Ynone,
+ Zpseudo,
+ 0,
+ Ynone,
+ Yiauto,
+ Zpseudo,
+ 0,
+ Ynone,
+ Yml,
+ Zpseudo,
+ 0,
+ Ynone,
+ Yrf,
+ Zpseudo,
+ 0,
+ Yiauto,
+ Ynone,
+ Zpseudo,
+ 0,
+ Ynone,
+ Yxr,
+ Zpseudo,
+ 0,
+ Yml,
+ Ynone,
+ Zpseudo,
+ 0,
+ Yrf,
+ Ynone,
+ Zpseudo,
+ 0,
+ Yxr,
+ Ynone,
+ Zpseudo,
+ 1,
+ 0,
+}
+
+var yfuncdata = []uint8{
+ Yi32,
+ Ym,
+ Zpseudo,
+ 0,
+ 0,
+}
+
+var ypcdata = []uint8{
+ Yi32,
+ Yi32,
+ Zpseudo,
+ 0,
+ 0,
+}
+
+var yxorb = []uint8{
+ Yi32,
+ Yal,
+ Zib_,
+ 1,
+ Yi32,
+ Ymb,
+ Zibo_m,
+ 2,
+ Yrb,
+ Ymb,
+ Zr_m,
+ 1,
+ Ymb,
+ Yrb,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var yxorl = []uint8{
+ Yi8,
+ Yml,
+ Zibo_m,
+ 2,
+ Yi32,
+ Yax,
+ Zil_,
+ 1,
+ Yi32,
+ Yml,
+ Zilo_m,
+ 2,
+ Yrl,
+ Yml,
+ Zr_m,
+ 1,
+ Yml,
+ Yrl,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var yaddl = []uint8{
+ Yi8,
+ Yml,
+ Zibo_m,
+ 2,
+ Yi32,
+ Yax,
+ Zil_,
+ 1,
+ Yi32,
+ Yml,
+ Zilo_m,
+ 2,
+ Yrl,
+ Yml,
+ Zr_m,
+ 1,
+ Yml,
+ Yrl,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var yincb = []uint8{
+ Ynone,
+ Ymb,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var yincl = []uint8{
+ Ynone,
+ Yrl,
+ Z_rp,
+ 1,
+ Ynone,
+ Yml,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var ycmpb = []uint8{
+ Yal,
+ Yi32,
+ Z_ib,
+ 1,
+ Ymb,
+ Yi32,
+ Zm_ibo,
+ 2,
+ Ymb,
+ Yrb,
+ Zm_r,
+ 1,
+ Yrb,
+ Ymb,
+ Zr_m,
+ 1,
+ 0,
+}
+
+var ycmpl = []uint8{
+ Yml,
+ Yi8,
+ Zm_ibo,
+ 2,
+ Yax,
+ Yi32,
+ Z_il,
+ 1,
+ Yml,
+ Yi32,
+ Zm_ilo,
+ 2,
+ Yml,
+ Yrl,
+ Zm_r,
+ 1,
+ Yrl,
+ Yml,
+ Zr_m,
+ 1,
+ 0,
+}
+
+var yshb = []uint8{
+ Yi1,
+ Ymb,
+ Zo_m,
+ 2,
+ Yi32,
+ Ymb,
+ Zibo_m,
+ 2,
+ Ycx,
+ Ymb,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var yshl = []uint8{
+ Yi1,
+ Yml,
+ Zo_m,
+ 2,
+ Yi32,
+ Yml,
+ Zibo_m,
+ 2,
+ Ycl,
+ Yml,
+ Zo_m,
+ 2,
+ Ycx,
+ Yml,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var ytestb = []uint8{
+ Yi32,
+ Yal,
+ Zib_,
+ 1,
+ Yi32,
+ Ymb,
+ Zibo_m,
+ 2,
+ Yrb,
+ Ymb,
+ Zr_m,
+ 1,
+ Ymb,
+ Yrb,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var ytestl = []uint8{
+ Yi32,
+ Yax,
+ Zil_,
+ 1,
+ Yi32,
+ Yml,
+ Zilo_m,
+ 2,
+ Yrl,
+ Yml,
+ Zr_m,
+ 1,
+ Yml,
+ Yrl,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var ymovb = []uint8{
+ Yrb,
+ Ymb,
+ Zr_m,
+ 1,
+ Ymb,
+ Yrb,
+ Zm_r,
+ 1,
+ Yi32,
+ Yrb,
+ Zib_rp,
+ 1,
+ Yi32,
+ Ymb,
+ Zibo_m,
+ 2,
+ 0,
+}
+
+var ymovw = []uint8{
+ Yrl,
+ Yml,
+ Zr_m,
+ 1,
+ Yml,
+ Yrl,
+ Zm_r,
+ 1,
+ Yi0,
+ Yrl,
+ Zclr,
+ 1 + 2,
+ // Yi0, Yml, Zibo_m, 2, // shorter but slower AND $0,dst
+ Yi32,
+ Yrl,
+ Zil_rp,
+ 1,
+ Yi32,
+ Yml,
+ Zilo_m,
+ 2,
+ Yiauto,
+ Yrl,
+ Zaut_r,
+ 1,
+ 0,
+}
+
+var ymovl = []uint8{
+ Yrl,
+ Yml,
+ Zr_m,
+ 1,
+ Yml,
+ Yrl,
+ Zm_r,
+ 1,
+ Yi0,
+ Yrl,
+ Zclr,
+ 1 + 2,
+ // Yi0, Yml, Zibo_m, 2, // shorter but slower AND $0,dst
+ Yi32,
+ Yrl,
+ Zil_rp,
+ 1,
+ Yi32,
+ Yml,
+ Zilo_m,
+ 2,
+ Yml,
+ Yxr,
+ Zm_r_xm,
+ 2, // XMM MOVD (32 bit)
+ Yxr,
+ Yml,
+ Zr_m_xm,
+ 2, // XMM MOVD (32 bit)
+ Yiauto,
+ Yrl,
+ Zaut_r,
+ 1,
+ 0,
+}
+
+var ymovq = []uint8{
+ Yml,
+ Yxr,
+ Zm_r_xm,
+ 2,
+ 0,
+}
+
+var ym_rl = []uint8{
+ Ym,
+ Yrl,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var yrl_m = []uint8{
+ Yrl,
+ Ym,
+ Zr_m,
+ 1,
+ 0,
+}
+
+var ymb_rl = []uint8{
+ Ymb,
+ Yrl,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var yml_rl = []uint8{
+ Yml,
+ Yrl,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var yrb_mb = []uint8{
+ Yrb,
+ Ymb,
+ Zr_m,
+ 1,
+ 0,
+}
+
+var yrl_ml = []uint8{
+ Yrl,
+ Yml,
+ Zr_m,
+ 1,
+ 0,
+}
+
+var yml_mb = []uint8{
+ Yrb,
+ Ymb,
+ Zr_m,
+ 1,
+ Ymb,
+ Yrb,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var yxchg = []uint8{
+ Yax,
+ Yrl,
+ Z_rp,
+ 1,
+ Yrl,
+ Yax,
+ Zrp_,
+ 1,
+ Yrl,
+ Yml,
+ Zr_m,
+ 1,
+ Yml,
+ Yrl,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var ydivl = []uint8{
+ Yml,
+ Ynone,
+ Zm_o,
+ 2,
+ 0,
+}
+
+var ydivb = []uint8{
+ Ymb,
+ Ynone,
+ Zm_o,
+ 2,
+ 0,
+}
+
+var yimul = []uint8{
+ Yml,
+ Ynone,
+ Zm_o,
+ 2,
+ Yi8,
+ Yrl,
+ Zib_rr,
+ 1,
+ Yi32,
+ Yrl,
+ Zil_rr,
+ 1,
+ 0,
+}
+
+var ybyte = []uint8{
+ Yi32,
+ Ynone,
+ Zbyte,
+ 1,
+ 0,
+}
+
+var yin = []uint8{
+ Yi32,
+ Ynone,
+ Zib_,
+ 1,
+ Ynone,
+ Ynone,
+ Zlit,
+ 1,
+ 0,
+}
+
+var yint = []uint8{
+ Yi32,
+ Ynone,
+ Zib_,
+ 1,
+ 0,
+}
+
+var ypushl = []uint8{
+ Yrl,
+ Ynone,
+ Zrp_,
+ 1,
+ Ym,
+ Ynone,
+ Zm_o,
+ 2,
+ Yi8,
+ Ynone,
+ Zib_,
+ 1,
+ Yi32,
+ Ynone,
+ Zil_,
+ 1,
+ 0,
+}
+
+var ypopl = []uint8{
+ Ynone,
+ Yrl,
+ Z_rp,
+ 1,
+ Ynone,
+ Ym,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var ybswap = []uint8{
+ Ynone,
+ Yrl,
+ Z_rp,
+ 1,
+ 0,
+}
+
+var yscond = []uint8{
+ Ynone,
+ Ymb,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var yjcond = []uint8{
+ Ynone,
+ Ybr,
+ Zbr,
+ 0,
+ Yi0,
+ Ybr,
+ Zbr,
+ 0,
+ Yi1,
+ Ybr,
+ Zbr,
+ 1,
+ 0,
+}
+
+var yloop = []uint8{
+ Ynone,
+ Ybr,
+ Zloop,
+ 1,
+ 0,
+}
+
+var ycall = []uint8{
+ Ynone,
+ Yml,
+ Zcallindreg,
+ 0,
+ Yrx,
+ Yrx,
+ Zcallindreg,
+ 2,
+ Ynone,
+ Ycol,
+ Zcallind,
+ 2,
+ Ynone,
+ Ybr,
+ Zcall,
+ 0,
+ Ynone,
+ Yi32,
+ Zcallcon,
+ 1,
+ 0,
+}
+
+var yduff = []uint8{
+ Ynone,
+ Yi32,
+ Zcall,
+ 1,
+ 0,
+}
+
+var yjmp = []uint8{
+ Ynone,
+ Yml,
+ Zo_m,
+ 2,
+ Ynone,
+ Ybr,
+ Zjmp,
+ 0,
+ Ynone,
+ Yi32,
+ Zjmpcon,
+ 1,
+ 0,
+}
+
+var yfmvd = []uint8{
+ Ym,
+ Yf0,
+ Zm_o,
+ 2,
+ Yf0,
+ Ym,
+ Zo_m,
+ 2,
+ Yrf,
+ Yf0,
+ Zm_o,
+ 2,
+ Yf0,
+ Yrf,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var yfmvdp = []uint8{
+ Yf0,
+ Ym,
+ Zo_m,
+ 2,
+ Yf0,
+ Yrf,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var yfmvf = []uint8{
+ Ym,
+ Yf0,
+ Zm_o,
+ 2,
+ Yf0,
+ Ym,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var yfmvx = []uint8{
+ Ym,
+ Yf0,
+ Zm_o,
+ 2,
+ 0,
+}
+
+var yfmvp = []uint8{
+ Yf0,
+ Ym,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var yfcmv = []uint8{
+ Yrf,
+ Yf0,
+ Zm_o,
+ 2,
+ 0,
+}
+
+var yfadd = []uint8{
+ Ym,
+ Yf0,
+ Zm_o,
+ 2,
+ Yrf,
+ Yf0,
+ Zm_o,
+ 2,
+ Yf0,
+ Yrf,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var yfaddp = []uint8{
+ Yf0,
+ Yrf,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var yfxch = []uint8{
+ Yf0,
+ Yrf,
+ Zo_m,
+ 2,
+ Yrf,
+ Yf0,
+ Zm_o,
+ 2,
+ 0,
+}
+
+var ycompp = []uint8{
+ Yf0,
+ Yrf,
+ Zo_m,
+ 2, /* botch is really f0,f1 */
+ 0,
+}
+
+var ystsw = []uint8{
+ Ynone,
+ Ym,
+ Zo_m,
+ 2,
+ Ynone,
+ Yax,
+ Zlit,
+ 1,
+ 0,
+}
+
+var ystcw = []uint8{
+ Ynone,
+ Ym,
+ Zo_m,
+ 2,
+ Ym,
+ Ynone,
+ Zm_o,
+ 2,
+ 0,
+}
+
+var ysvrs = []uint8{
+ Ynone,
+ Ym,
+ Zo_m,
+ 2,
+ Ym,
+ Ynone,
+ Zm_o,
+ 2,
+ 0,
+}
+
+var ymskb = []uint8{
+ Yxr,
+ Yrl,
+ Zm_r_xm,
+ 2,
+ Ymr,
+ Yrl,
+ Zm_r_xm,
+ 1,
+ 0,
+}
+
+var yxm = []uint8{
+ Yxm,
+ Yxr,
+ Zm_r_xm,
+ 1,
+ 0,
+}
+
+var yxcvm1 = []uint8{
+ Yxm,
+ Yxr,
+ Zm_r_xm,
+ 2,
+ Yxm,
+ Ymr,
+ Zm_r_xm,
+ 2,
+ 0,
+}
+
+var yxcvm2 = []uint8{
+ Yxm,
+ Yxr,
+ Zm_r_xm,
+ 2,
+ Ymm,
+ Yxr,
+ Zm_r_xm,
+ 2,
+ 0,
+}
+
+var yxmq = []uint8{
+ Yxm,
+ Yxr,
+ Zm_r_xm,
+ 2,
+ 0,
+}
+
+var yxr = []uint8{
+ Yxr,
+ Yxr,
+ Zm_r_xm,
+ 1,
+ 0,
+}
+
+var yxr_ml = []uint8{
+ Yxr,
+ Yml,
+ Zr_m_xm,
+ 1,
+ 0,
+}
+
+var yxcmp = []uint8{
+ Yxm,
+ Yxr,
+ Zm_r_xm,
+ 1,
+ 0,
+}
+
+var yxcmpi = []uint8{
+ Yxm,
+ Yxr,
+ Zm_r_i_xm,
+ 2,
+ 0,
+}
+
+var yxmov = []uint8{
+ Yxm,
+ Yxr,
+ Zm_r_xm,
+ 1,
+ Yxr,
+ Yxm,
+ Zr_m_xm,
+ 1,
+ 0,
+}
+
+var yxcvfl = []uint8{
+ Yxm,
+ Yrl,
+ Zm_r_xm,
+ 1,
+ 0,
+}
+
+var yxcvlf = []uint8{
+ Yml,
+ Yxr,
+ Zm_r_xm,
+ 1,
+ 0,
+}
+
+/*
+static uchar yxcvfq[] =
+{
+ Yxm, Yrl, Zm_r_xm, 2,
+ 0
+};
+static uchar yxcvqf[] =
+{
+ Yml, Yxr, Zm_r_xm, 2,
+ 0
+};
+*/
+var yxrrl = []uint8{
+ Yxr,
+ Yrl,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var yprefetch = []uint8{
+ Ym,
+ Ynone,
+ Zm_o,
+ 2,
+ 0,
+}
+
+var yaes = []uint8{
+ Yxm,
+ Yxr,
+ Zlitm_r,
+ 2,
+ 0,
+}
+
+var yinsrd = []uint8{
+ Yml,
+ Yxr,
+ Zibm_r,
+ 2,
+ 0,
+}
+
+var ymshufb = []uint8{
+ Yxm,
+ Yxr,
+ Zm2_r,
+ 2,
+ 0,
+}
+
+var yxshuf = []uint8{
+ Yxm,
+ Yxr,
+ Zibm_r,
+ 2,
+ 0,
+}
+
+var optab = /* as, ytab, andproto, opcode */
+[]Optab{
+ Optab{AXXX, nil, 0, [13]uint8{}},
+ Optab{AAAA, ynone, Px, [13]uint8{0x37}},
+ Optab{AAAD, ynone, Px, [13]uint8{0xd5, 0x0a}},
+ Optab{AAAM, ynone, Px, [13]uint8{0xd4, 0x0a}},
+ Optab{AAAS, ynone, Px, [13]uint8{0x3f}},
+ Optab{AADCB, yxorb, Pb, [13]uint8{0x14, 0x80, 02, 0x10, 0x10}},
+ Optab{AADCL, yxorl, Px, [13]uint8{0x83, 02, 0x15, 0x81, 02, 0x11, 0x13}},
+ Optab{AADCW, yxorl, Pe, [13]uint8{0x83, 02, 0x15, 0x81, 02, 0x11, 0x13}},
+ Optab{AADDB, yxorb, Px, [13]uint8{0x04, 0x80, 00, 0x00, 0x02}},
+ Optab{AADDL, yaddl, Px, [13]uint8{0x83, 00, 0x05, 0x81, 00, 0x01, 0x03}},
+ Optab{AADDW, yaddl, Pe, [13]uint8{0x83, 00, 0x05, 0x81, 00, 0x01, 0x03}},
+ Optab{AADJSP, nil, 0, [13]uint8{}},
+ Optab{AANDB, yxorb, Pb, [13]uint8{0x24, 0x80, 04, 0x20, 0x22}},
+ Optab{AANDL, yxorl, Px, [13]uint8{0x83, 04, 0x25, 0x81, 04, 0x21, 0x23}},
+ Optab{AANDW, yxorl, Pe, [13]uint8{0x83, 04, 0x25, 0x81, 04, 0x21, 0x23}},
+ Optab{AARPL, yrl_ml, Px, [13]uint8{0x63}},
+ Optab{ABOUNDL, yrl_m, Px, [13]uint8{0x62}},
+ Optab{ABOUNDW, yrl_m, Pe, [13]uint8{0x62}},
+ Optab{ABSFL, yml_rl, Pm, [13]uint8{0xbc}},
+ Optab{ABSFW, yml_rl, Pq, [13]uint8{0xbc}},
+ Optab{ABSRL, yml_rl, Pm, [13]uint8{0xbd}},
+ Optab{ABSRW, yml_rl, Pq, [13]uint8{0xbd}},
+ Optab{ABTL, yml_rl, Pm, [13]uint8{0xa3}},
+ Optab{ABTW, yml_rl, Pq, [13]uint8{0xa3}},
+ Optab{ABTCL, yml_rl, Pm, [13]uint8{0xbb}},
+ Optab{ABTCW, yml_rl, Pq, [13]uint8{0xbb}},
+ Optab{ABTRL, yml_rl, Pm, [13]uint8{0xb3}},
+ Optab{ABTRW, yml_rl, Pq, [13]uint8{0xb3}},
+ Optab{ABTSL, yml_rl, Pm, [13]uint8{0xab}},
+ Optab{ABTSW, yml_rl, Pq, [13]uint8{0xab}},
+ Optab{ABYTE, ybyte, Px, [13]uint8{1}},
+ Optab{ACALL, ycall, Px, [13]uint8{0xff, 02, 0xff, 0x15, 0xe8}},
+ Optab{ACLC, ynone, Px, [13]uint8{0xf8}},
+ Optab{ACLD, ynone, Px, [13]uint8{0xfc}},
+ Optab{ACLI, ynone, Px, [13]uint8{0xfa}},
+ Optab{ACLTS, ynone, Pm, [13]uint8{0x06}},
+ Optab{ACMC, ynone, Px, [13]uint8{0xf5}},
+ Optab{ACMPB, ycmpb, Pb, [13]uint8{0x3c, 0x80, 07, 0x38, 0x3a}},
+ Optab{ACMPL, ycmpl, Px, [13]uint8{0x83, 07, 0x3d, 0x81, 07, 0x39, 0x3b}},
+ Optab{ACMPW, ycmpl, Pe, [13]uint8{0x83, 07, 0x3d, 0x81, 07, 0x39, 0x3b}},
+ Optab{ACMPSB, ynone, Pb, [13]uint8{0xa6}},
+ Optab{ACMPSL, ynone, Px, [13]uint8{0xa7}},
+ Optab{ACMPSW, ynone, Pe, [13]uint8{0xa7}},
+ Optab{ADAA, ynone, Px, [13]uint8{0x27}},
+ Optab{ADAS, ynone, Px, [13]uint8{0x2f}},
+ Optab{ADATA, nil, 0, [13]uint8{}},
+ Optab{ADECB, yincb, Pb, [13]uint8{0xfe, 01}},
+ Optab{ADECL, yincl, Px, [13]uint8{0x48, 0xff, 01}},
+ Optab{ADECW, yincl, Pe, [13]uint8{0x48, 0xff, 01}},
+ Optab{ADIVB, ydivb, Pb, [13]uint8{0xf6, 06}},
+ Optab{ADIVL, ydivl, Px, [13]uint8{0xf7, 06}},
+ Optab{ADIVW, ydivl, Pe, [13]uint8{0xf7, 06}},
+ Optab{AENTER, nil, 0, [13]uint8{}}, /* botch */
+ Optab{AGLOBL, nil, 0, [13]uint8{}},
+ Optab{AGOK, nil, 0, [13]uint8{}},
+ Optab{AHISTORY, nil, 0, [13]uint8{}},
+ Optab{AHLT, ynone, Px, [13]uint8{0xf4}},
+ Optab{AIDIVB, ydivb, Pb, [13]uint8{0xf6, 07}},
+ Optab{AIDIVL, ydivl, Px, [13]uint8{0xf7, 07}},
+ Optab{AIDIVW, ydivl, Pe, [13]uint8{0xf7, 07}},
+ Optab{AIMULB, ydivb, Pb, [13]uint8{0xf6, 05}},
+ Optab{AIMULL, yimul, Px, [13]uint8{0xf7, 05, 0x6b, 0x69}},
+ Optab{AIMULW, yimul, Pe, [13]uint8{0xf7, 05, 0x6b, 0x69}},
+ Optab{AINB, yin, Pb, [13]uint8{0xe4, 0xec}},
+ Optab{AINL, yin, Px, [13]uint8{0xe5, 0xed}},
+ Optab{AINW, yin, Pe, [13]uint8{0xe5, 0xed}},
+ Optab{AINCB, yincb, Pb, [13]uint8{0xfe, 00}},
+ Optab{AINCL, yincl, Px, [13]uint8{0x40, 0xff, 00}},
+ Optab{AINCW, yincl, Pe, [13]uint8{0x40, 0xff, 00}},
+ Optab{AINSB, ynone, Pb, [13]uint8{0x6c}},
+ Optab{AINSL, ynone, Px, [13]uint8{0x6d}},
+ Optab{AINSW, ynone, Pe, [13]uint8{0x6d}},
+ Optab{AINT, yint, Px, [13]uint8{0xcd}},
+ Optab{AINTO, ynone, Px, [13]uint8{0xce}},
+ Optab{AIRETL, ynone, Px, [13]uint8{0xcf}},
+ Optab{AIRETW, ynone, Pe, [13]uint8{0xcf}},
+ Optab{AJCC, yjcond, Px, [13]uint8{0x73, 0x83, 00}},
+ Optab{AJCS, yjcond, Px, [13]uint8{0x72, 0x82}},
+ Optab{AJCXZL, yloop, Px, [13]uint8{0xe3}},
+ Optab{AJCXZW, yloop, Px, [13]uint8{0xe3}},
+ Optab{AJEQ, yjcond, Px, [13]uint8{0x74, 0x84}},
+ Optab{AJGE, yjcond, Px, [13]uint8{0x7d, 0x8d}},
+ Optab{AJGT, yjcond, Px, [13]uint8{0x7f, 0x8f}},
+ Optab{AJHI, yjcond, Px, [13]uint8{0x77, 0x87}},
+ Optab{AJLE, yjcond, Px, [13]uint8{0x7e, 0x8e}},
+ Optab{AJLS, yjcond, Px, [13]uint8{0x76, 0x86}},
+ Optab{AJLT, yjcond, Px, [13]uint8{0x7c, 0x8c}},
+ Optab{AJMI, yjcond, Px, [13]uint8{0x78, 0x88}},
+ Optab{AJMP, yjmp, Px, [13]uint8{0xff, 04, 0xeb, 0xe9}},
+ Optab{AJNE, yjcond, Px, [13]uint8{0x75, 0x85}},
+ Optab{AJOC, yjcond, Px, [13]uint8{0x71, 0x81, 00}},
+ Optab{AJOS, yjcond, Px, [13]uint8{0x70, 0x80, 00}},
+ Optab{AJPC, yjcond, Px, [13]uint8{0x7b, 0x8b}},
+ Optab{AJPL, yjcond, Px, [13]uint8{0x79, 0x89}},
+ Optab{AJPS, yjcond, Px, [13]uint8{0x7a, 0x8a}},
+ Optab{ALAHF, ynone, Px, [13]uint8{0x9f}},
+ Optab{ALARL, yml_rl, Pm, [13]uint8{0x02}},
+ Optab{ALARW, yml_rl, Pq, [13]uint8{0x02}},
+ Optab{ALEAL, ym_rl, Px, [13]uint8{0x8d}},
+ Optab{ALEAW, ym_rl, Pe, [13]uint8{0x8d}},
+ Optab{ALEAVEL, ynone, Px, [13]uint8{0xc9}},
+ Optab{ALEAVEW, ynone, Pe, [13]uint8{0xc9}},
+ Optab{ALOCK, ynone, Px, [13]uint8{0xf0}},
+ Optab{ALODSB, ynone, Pb, [13]uint8{0xac}},
+ Optab{ALODSL, ynone, Px, [13]uint8{0xad}},
+ Optab{ALODSW, ynone, Pe, [13]uint8{0xad}},
+ Optab{ALONG, ybyte, Px, [13]uint8{4}},
+ Optab{ALOOP, yloop, Px, [13]uint8{0xe2}},
+ Optab{ALOOPEQ, yloop, Px, [13]uint8{0xe1}},
+ Optab{ALOOPNE, yloop, Px, [13]uint8{0xe0}},
+ Optab{ALSLL, yml_rl, Pm, [13]uint8{0x03}},
+ Optab{ALSLW, yml_rl, Pq, [13]uint8{0x03}},
+ Optab{AMOVB, ymovb, Pb, [13]uint8{0x88, 0x8a, 0xb0, 0xc6, 00}},
+ Optab{AMOVL, ymovl, Px, [13]uint8{0x89, 0x8b, 0x31, 0x83, 04, 0xb8, 0xc7, 00, Pe, 0x6e, Pe, 0x7e, 0}},
+ Optab{AMOVW, ymovw, Pe, [13]uint8{0x89, 0x8b, 0x31, 0x83, 04, 0xb8, 0xc7, 00, 0}},
+ Optab{AMOVQ, ymovq, Pf3, [13]uint8{0x7e}},
+ Optab{AMOVBLSX, ymb_rl, Pm, [13]uint8{0xbe}},
+ Optab{AMOVBLZX, ymb_rl, Pm, [13]uint8{0xb6}},
+ Optab{AMOVBWSX, ymb_rl, Pq, [13]uint8{0xbe}},
+ Optab{AMOVBWZX, ymb_rl, Pq, [13]uint8{0xb6}},
+ Optab{AMOVWLSX, yml_rl, Pm, [13]uint8{0xbf}},
+ Optab{AMOVWLZX, yml_rl, Pm, [13]uint8{0xb7}},
+ Optab{AMOVSB, ynone, Pb, [13]uint8{0xa4}},
+ Optab{AMOVSL, ynone, Px, [13]uint8{0xa5}},
+ Optab{AMOVSW, ynone, Pe, [13]uint8{0xa5}},
+ Optab{AMULB, ydivb, Pb, [13]uint8{0xf6, 04}},
+ Optab{AMULL, ydivl, Px, [13]uint8{0xf7, 04}},
+ Optab{AMULW, ydivl, Pe, [13]uint8{0xf7, 04}},
+ Optab{ANAME, nil, 0, [13]uint8{}},
+ Optab{ANEGB, yscond, Px, [13]uint8{0xf6, 03}},
+ Optab{ANEGL, yscond, Px, [13]uint8{0xf7, 03}},
+ Optab{ANEGW, yscond, Pe, [13]uint8{0xf7, 03}},
+ Optab{ANOP, ynop, Px, [13]uint8{0, 0}},
+ Optab{ANOTB, yscond, Px, [13]uint8{0xf6, 02}},
+ Optab{ANOTL, yscond, Px, [13]uint8{0xf7, 02}},
+ Optab{ANOTW, yscond, Pe, [13]uint8{0xf7, 02}},
+ Optab{AORB, yxorb, Pb, [13]uint8{0x0c, 0x80, 01, 0x08, 0x0a}},
+ Optab{AORL, yxorl, Px, [13]uint8{0x83, 01, 0x0d, 0x81, 01, 0x09, 0x0b}},
+ Optab{AORW, yxorl, Pe, [13]uint8{0x83, 01, 0x0d, 0x81, 01, 0x09, 0x0b}},
+ Optab{AOUTB, yin, Pb, [13]uint8{0xe6, 0xee}},
+ Optab{AOUTL, yin, Px, [13]uint8{0xe7, 0xef}},
+ Optab{AOUTW, yin, Pe, [13]uint8{0xe7, 0xef}},
+ Optab{AOUTSB, ynone, Pb, [13]uint8{0x6e}},
+ Optab{AOUTSL, ynone, Px, [13]uint8{0x6f}},
+ Optab{AOUTSW, ynone, Pe, [13]uint8{0x6f}},
+ Optab{APAUSE, ynone, Px, [13]uint8{0xf3, 0x90}},
+ Optab{APOPAL, ynone, Px, [13]uint8{0x61}},
+ Optab{APOPAW, ynone, Pe, [13]uint8{0x61}},
+ Optab{APOPFL, ynone, Px, [13]uint8{0x9d}},
+ Optab{APOPFW, ynone, Pe, [13]uint8{0x9d}},
+ Optab{APOPL, ypopl, Px, [13]uint8{0x58, 0x8f, 00}},
+ Optab{APOPW, ypopl, Pe, [13]uint8{0x58, 0x8f, 00}},
+ Optab{APUSHAL, ynone, Px, [13]uint8{0x60}},
+ Optab{APUSHAW, ynone, Pe, [13]uint8{0x60}},
+ Optab{APUSHFL, ynone, Px, [13]uint8{0x9c}},
+ Optab{APUSHFW, ynone, Pe, [13]uint8{0x9c}},
+ Optab{APUSHL, ypushl, Px, [13]uint8{0x50, 0xff, 06, 0x6a, 0x68}},
+ Optab{APUSHW, ypushl, Pe, [13]uint8{0x50, 0xff, 06, 0x6a, 0x68}},
+ Optab{ARCLB, yshb, Pb, [13]uint8{0xd0, 02, 0xc0, 02, 0xd2, 02}},
+ Optab{ARCLL, yshl, Px, [13]uint8{0xd1, 02, 0xc1, 02, 0xd3, 02, 0xd3, 02}},
+ Optab{ARCLW, yshl, Pe, [13]uint8{0xd1, 02, 0xc1, 02, 0xd3, 02, 0xd3, 02}},
+ Optab{ARCRB, yshb, Pb, [13]uint8{0xd0, 03, 0xc0, 03, 0xd2, 03}},
+ Optab{ARCRL, yshl, Px, [13]uint8{0xd1, 03, 0xc1, 03, 0xd3, 03, 0xd3, 03}},
+ Optab{ARCRW, yshl, Pe, [13]uint8{0xd1, 03, 0xc1, 03, 0xd3, 03, 0xd3, 03}},
+ Optab{AREP, ynone, Px, [13]uint8{0xf3}},
+ Optab{AREPN, ynone, Px, [13]uint8{0xf2}},
+ Optab{ARET, ynone, Px, [13]uint8{0xc3}},
+ Optab{AROLB, yshb, Pb, [13]uint8{0xd0, 00, 0xc0, 00, 0xd2, 00}},
+ Optab{AROLL, yshl, Px, [13]uint8{0xd1, 00, 0xc1, 00, 0xd3, 00, 0xd3, 00}},
+ Optab{AROLW, yshl, Pe, [13]uint8{0xd1, 00, 0xc1, 00, 0xd3, 00, 0xd3, 00}},
+ Optab{ARORB, yshb, Pb, [13]uint8{0xd0, 01, 0xc0, 01, 0xd2, 01}},
+ Optab{ARORL, yshl, Px, [13]uint8{0xd1, 01, 0xc1, 01, 0xd3, 01, 0xd3, 01}},
+ Optab{ARORW, yshl, Pe, [13]uint8{0xd1, 01, 0xc1, 01, 0xd3, 01, 0xd3, 01}},
+ Optab{ASAHF, ynone, Px, [13]uint8{0x9e}},
+ Optab{ASALB, yshb, Pb, [13]uint8{0xd0, 04, 0xc0, 04, 0xd2, 04}},
+ Optab{ASALL, yshl, Px, [13]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+ Optab{ASALW, yshl, Pe, [13]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+ Optab{ASARB, yshb, Pb, [13]uint8{0xd0, 07, 0xc0, 07, 0xd2, 07}},
+ Optab{ASARL, yshl, Px, [13]uint8{0xd1, 07, 0xc1, 07, 0xd3, 07, 0xd3, 07}},
+ Optab{ASARW, yshl, Pe, [13]uint8{0xd1, 07, 0xc1, 07, 0xd3, 07, 0xd3, 07}},
+ Optab{ASBBB, yxorb, Pb, [13]uint8{0x1c, 0x80, 03, 0x18, 0x1a}},
+ Optab{ASBBL, yxorl, Px, [13]uint8{0x83, 03, 0x1d, 0x81, 03, 0x19, 0x1b}},
+ Optab{ASBBW, yxorl, Pe, [13]uint8{0x83, 03, 0x1d, 0x81, 03, 0x19, 0x1b}},
+ Optab{ASCASB, ynone, Pb, [13]uint8{0xae}},
+ Optab{ASCASL, ynone, Px, [13]uint8{0xaf}},
+ Optab{ASCASW, ynone, Pe, [13]uint8{0xaf}},
+ Optab{ASETCC, yscond, Pm, [13]uint8{0x93, 00}},
+ Optab{ASETCS, yscond, Pm, [13]uint8{0x92, 00}},
+ Optab{ASETEQ, yscond, Pm, [13]uint8{0x94, 00}},
+ Optab{ASETGE, yscond, Pm, [13]uint8{0x9d, 00}},
+ Optab{ASETGT, yscond, Pm, [13]uint8{0x9f, 00}},
+ Optab{ASETHI, yscond, Pm, [13]uint8{0x97, 00}},
+ Optab{ASETLE, yscond, Pm, [13]uint8{0x9e, 00}},
+ Optab{ASETLS, yscond, Pm, [13]uint8{0x96, 00}},
+ Optab{ASETLT, yscond, Pm, [13]uint8{0x9c, 00}},
+ Optab{ASETMI, yscond, Pm, [13]uint8{0x98, 00}},
+ Optab{ASETNE, yscond, Pm, [13]uint8{0x95, 00}},
+ Optab{ASETOC, yscond, Pm, [13]uint8{0x91, 00}},
+ Optab{ASETOS, yscond, Pm, [13]uint8{0x90, 00}},
+ Optab{ASETPC, yscond, Pm, [13]uint8{0x9b, 00}},
+ Optab{ASETPL, yscond, Pm, [13]uint8{0x99, 00}},
+ Optab{ASETPS, yscond, Pm, [13]uint8{0x9a, 00}},
+ Optab{ACDQ, ynone, Px, [13]uint8{0x99}},
+ Optab{ACWD, ynone, Pe, [13]uint8{0x99}},
+ Optab{ASHLB, yshb, Pb, [13]uint8{0xd0, 04, 0xc0, 04, 0xd2, 04}},
+ Optab{ASHLL, yshl, Px, [13]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+ Optab{ASHLW, yshl, Pe, [13]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+ Optab{ASHRB, yshb, Pb, [13]uint8{0xd0, 05, 0xc0, 05, 0xd2, 05}},
+ Optab{ASHRL, yshl, Px, [13]uint8{0xd1, 05, 0xc1, 05, 0xd3, 05, 0xd3, 05}},
+ Optab{ASHRW, yshl, Pe, [13]uint8{0xd1, 05, 0xc1, 05, 0xd3, 05, 0xd3, 05}},
+ Optab{ASTC, ynone, Px, [13]uint8{0xf9}},
+ Optab{ASTD, ynone, Px, [13]uint8{0xfd}},
+ Optab{ASTI, ynone, Px, [13]uint8{0xfb}},
+ Optab{ASTOSB, ynone, Pb, [13]uint8{0xaa}},
+ Optab{ASTOSL, ynone, Px, [13]uint8{0xab}},
+ Optab{ASTOSW, ynone, Pe, [13]uint8{0xab}},
+ Optab{ASUBB, yxorb, Pb, [13]uint8{0x2c, 0x80, 05, 0x28, 0x2a}},
+ Optab{ASUBL, yaddl, Px, [13]uint8{0x83, 05, 0x2d, 0x81, 05, 0x29, 0x2b}},
+ Optab{ASUBW, yaddl, Pe, [13]uint8{0x83, 05, 0x2d, 0x81, 05, 0x29, 0x2b}},
+ Optab{ASYSCALL, ynone, Px, [13]uint8{0xcd, 100}},
+ Optab{ATESTB, ytestb, Pb, [13]uint8{0xa8, 0xf6, 00, 0x84, 0x84}},
+ Optab{ATESTL, ytestl, Px, [13]uint8{0xa9, 0xf7, 00, 0x85, 0x85}},
+ Optab{ATESTW, ytestl, Pe, [13]uint8{0xa9, 0xf7, 00, 0x85, 0x85}},
+ Optab{ATEXT, ytext, Px, [13]uint8{}},
+ Optab{AVERR, ydivl, Pm, [13]uint8{0x00, 04}},
+ Optab{AVERW, ydivl, Pm, [13]uint8{0x00, 05}},
+ Optab{AWAIT, ynone, Px, [13]uint8{0x9b}},
+ Optab{AWORD, ybyte, Px, [13]uint8{2}},
+ Optab{AXCHGB, yml_mb, Pb, [13]uint8{0x86, 0x86}},
+ Optab{AXCHGL, yxchg, Px, [13]uint8{0x90, 0x90, 0x87, 0x87}},
+ Optab{AXCHGW, yxchg, Pe, [13]uint8{0x90, 0x90, 0x87, 0x87}},
+ Optab{AXLAT, ynone, Px, [13]uint8{0xd7}},
+ Optab{AXORB, yxorb, Pb, [13]uint8{0x34, 0x80, 06, 0x30, 0x32}},
+ Optab{AXORL, yxorl, Px, [13]uint8{0x83, 06, 0x35, 0x81, 06, 0x31, 0x33}},
+ Optab{AXORW, yxorl, Pe, [13]uint8{0x83, 06, 0x35, 0x81, 06, 0x31, 0x33}},
+ Optab{AFMOVB, yfmvx, Px, [13]uint8{0xdf, 04}},
+ Optab{AFMOVBP, yfmvp, Px, [13]uint8{0xdf, 06}},
+ Optab{AFMOVD, yfmvd, Px, [13]uint8{0xdd, 00, 0xdd, 02, 0xd9, 00, 0xdd, 02}},
+ Optab{AFMOVDP, yfmvdp, Px, [13]uint8{0xdd, 03, 0xdd, 03}},
+ Optab{AFMOVF, yfmvf, Px, [13]uint8{0xd9, 00, 0xd9, 02}},
+ Optab{AFMOVFP, yfmvp, Px, [13]uint8{0xd9, 03}},
+ Optab{AFMOVL, yfmvf, Px, [13]uint8{0xdb, 00, 0xdb, 02}},
+ Optab{AFMOVLP, yfmvp, Px, [13]uint8{0xdb, 03}},
+ Optab{AFMOVV, yfmvx, Px, [13]uint8{0xdf, 05}},
+ Optab{AFMOVVP, yfmvp, Px, [13]uint8{0xdf, 07}},
+ Optab{AFMOVW, yfmvf, Px, [13]uint8{0xdf, 00, 0xdf, 02}},
+ Optab{AFMOVWP, yfmvp, Px, [13]uint8{0xdf, 03}},
+ Optab{AFMOVX, yfmvx, Px, [13]uint8{0xdb, 05}},
+ Optab{AFMOVXP, yfmvp, Px, [13]uint8{0xdb, 07}},
+ Optab{AFCOMB, nil, 0, [13]uint8{}},
+ Optab{AFCOMBP, nil, 0, [13]uint8{}},
+ Optab{AFCOMD, yfadd, Px, [13]uint8{0xdc, 02, 0xd8, 02, 0xdc, 02}}, /* botch */
+ Optab{AFCOMDP, yfadd, Px, [13]uint8{0xdc, 03, 0xd8, 03, 0xdc, 03}}, /* botch */
+ Optab{AFCOMDPP, ycompp, Px, [13]uint8{0xde, 03}},
+ Optab{AFCOMF, yfmvx, Px, [13]uint8{0xd8, 02}},
+ Optab{AFCOMFP, yfmvx, Px, [13]uint8{0xd8, 03}},
+ Optab{AFCOMI, yfmvx, Px, [13]uint8{0xdb, 06}},
+ Optab{AFCOMIP, yfmvx, Px, [13]uint8{0xdf, 06}},
+ Optab{AFCOML, yfmvx, Px, [13]uint8{0xda, 02}},
+ Optab{AFCOMLP, yfmvx, Px, [13]uint8{0xda, 03}},
+ Optab{AFCOMW, yfmvx, Px, [13]uint8{0xde, 02}},
+ Optab{AFCOMWP, yfmvx, Px, [13]uint8{0xde, 03}},
+ Optab{AFUCOM, ycompp, Px, [13]uint8{0xdd, 04}},
+ Optab{AFUCOMI, ycompp, Px, [13]uint8{0xdb, 05}},
+ Optab{AFUCOMIP, ycompp, Px, [13]uint8{0xdf, 05}},
+ Optab{AFUCOMP, ycompp, Px, [13]uint8{0xdd, 05}},
+ Optab{AFUCOMPP, ycompp, Px, [13]uint8{0xda, 13}},
+ Optab{AFADDDP, yfaddp, Px, [13]uint8{0xde, 00}},
+ Optab{AFADDW, yfmvx, Px, [13]uint8{0xde, 00}},
+ Optab{AFADDL, yfmvx, Px, [13]uint8{0xda, 00}},
+ Optab{AFADDF, yfmvx, Px, [13]uint8{0xd8, 00}},
+ Optab{AFADDD, yfadd, Px, [13]uint8{0xdc, 00, 0xd8, 00, 0xdc, 00}},
+ Optab{AFMULDP, yfaddp, Px, [13]uint8{0xde, 01}},
+ Optab{AFMULW, yfmvx, Px, [13]uint8{0xde, 01}},
+ Optab{AFMULL, yfmvx, Px, [13]uint8{0xda, 01}},
+ Optab{AFMULF, yfmvx, Px, [13]uint8{0xd8, 01}},
+ Optab{AFMULD, yfadd, Px, [13]uint8{0xdc, 01, 0xd8, 01, 0xdc, 01}},
+ Optab{AFSUBDP, yfaddp, Px, [13]uint8{0xde, 05}},
+ Optab{AFSUBW, yfmvx, Px, [13]uint8{0xde, 04}},
+ Optab{AFSUBL, yfmvx, Px, [13]uint8{0xda, 04}},
+ Optab{AFSUBF, yfmvx, Px, [13]uint8{0xd8, 04}},
+ Optab{AFSUBD, yfadd, Px, [13]uint8{0xdc, 04, 0xd8, 04, 0xdc, 05}},
+ Optab{AFSUBRDP, yfaddp, Px, [13]uint8{0xde, 04}},
+ Optab{AFSUBRW, yfmvx, Px, [13]uint8{0xde, 05}},
+ Optab{AFSUBRL, yfmvx, Px, [13]uint8{0xda, 05}},
+ Optab{AFSUBRF, yfmvx, Px, [13]uint8{0xd8, 05}},
+ Optab{AFSUBRD, yfadd, Px, [13]uint8{0xdc, 05, 0xd8, 05, 0xdc, 04}},
+ Optab{AFDIVDP, yfaddp, Px, [13]uint8{0xde, 07}},
+ Optab{AFDIVW, yfmvx, Px, [13]uint8{0xde, 06}},
+ Optab{AFDIVL, yfmvx, Px, [13]uint8{0xda, 06}},
+ Optab{AFDIVF, yfmvx, Px, [13]uint8{0xd8, 06}},
+ Optab{AFDIVD, yfadd, Px, [13]uint8{0xdc, 06, 0xd8, 06, 0xdc, 07}},
+ Optab{AFDIVRDP, yfaddp, Px, [13]uint8{0xde, 06}},
+ Optab{AFDIVRW, yfmvx, Px, [13]uint8{0xde, 07}},
+ Optab{AFDIVRL, yfmvx, Px, [13]uint8{0xda, 07}},
+ Optab{AFDIVRF, yfmvx, Px, [13]uint8{0xd8, 07}},
+ Optab{AFDIVRD, yfadd, Px, [13]uint8{0xdc, 07, 0xd8, 07, 0xdc, 06}},
+ Optab{AFXCHD, yfxch, Px, [13]uint8{0xd9, 01, 0xd9, 01}},
+ Optab{AFFREE, nil, 0, [13]uint8{}},
+ Optab{AFLDCW, ystcw, Px, [13]uint8{0xd9, 05, 0xd9, 05}},
+ Optab{AFLDENV, ystcw, Px, [13]uint8{0xd9, 04, 0xd9, 04}},
+ Optab{AFRSTOR, ysvrs, Px, [13]uint8{0xdd, 04, 0xdd, 04}},
+ Optab{AFSAVE, ysvrs, Px, [13]uint8{0xdd, 06, 0xdd, 06}},
+ Optab{AFSTCW, ystcw, Px, [13]uint8{0xd9, 07, 0xd9, 07}},
+ Optab{AFSTENV, ystcw, Px, [13]uint8{0xd9, 06, 0xd9, 06}},
+ Optab{AFSTSW, ystsw, Px, [13]uint8{0xdd, 07, 0xdf, 0xe0}},
+ Optab{AF2XM1, ynone, Px, [13]uint8{0xd9, 0xf0}},
+ Optab{AFABS, ynone, Px, [13]uint8{0xd9, 0xe1}},
+ Optab{AFCHS, ynone, Px, [13]uint8{0xd9, 0xe0}},
+ Optab{AFCLEX, ynone, Px, [13]uint8{0xdb, 0xe2}},
+ Optab{AFCOS, ynone, Px, [13]uint8{0xd9, 0xff}},
+ Optab{AFDECSTP, ynone, Px, [13]uint8{0xd9, 0xf6}},
+ Optab{AFINCSTP, ynone, Px, [13]uint8{0xd9, 0xf7}},
+ Optab{AFINIT, ynone, Px, [13]uint8{0xdb, 0xe3}},
+ Optab{AFLD1, ynone, Px, [13]uint8{0xd9, 0xe8}},
+ Optab{AFLDL2E, ynone, Px, [13]uint8{0xd9, 0xea}},
+ Optab{AFLDL2T, ynone, Px, [13]uint8{0xd9, 0xe9}},
+ Optab{AFLDLG2, ynone, Px, [13]uint8{0xd9, 0xec}},
+ Optab{AFLDLN2, ynone, Px, [13]uint8{0xd9, 0xed}},
+ Optab{AFLDPI, ynone, Px, [13]uint8{0xd9, 0xeb}},
+ Optab{AFLDZ, ynone, Px, [13]uint8{0xd9, 0xee}},
+ Optab{AFNOP, ynone, Px, [13]uint8{0xd9, 0xd0}},
+ Optab{AFPATAN, ynone, Px, [13]uint8{0xd9, 0xf3}},
+ Optab{AFPREM, ynone, Px, [13]uint8{0xd9, 0xf8}},
+ Optab{AFPREM1, ynone, Px, [13]uint8{0xd9, 0xf5}},
+ Optab{AFPTAN, ynone, Px, [13]uint8{0xd9, 0xf2}},
+ Optab{AFRNDINT, ynone, Px, [13]uint8{0xd9, 0xfc}},
+ Optab{AFSCALE, ynone, Px, [13]uint8{0xd9, 0xfd}},
+ Optab{AFSIN, ynone, Px, [13]uint8{0xd9, 0xfe}},
+ Optab{AFSINCOS, ynone, Px, [13]uint8{0xd9, 0xfb}},
+ Optab{AFSQRT, ynone, Px, [13]uint8{0xd9, 0xfa}},
+ Optab{AFTST, ynone, Px, [13]uint8{0xd9, 0xe4}},
+ Optab{AFXAM, ynone, Px, [13]uint8{0xd9, 0xe5}},
+ Optab{AFXTRACT, ynone, Px, [13]uint8{0xd9, 0xf4}},
+ Optab{AFYL2X, ynone, Px, [13]uint8{0xd9, 0xf1}},
+ Optab{AFYL2XP1, ynone, Px, [13]uint8{0xd9, 0xf9}},
+ Optab{AEND, nil, 0, [13]uint8{}},
+ Optab{ADYNT_, nil, 0, [13]uint8{}},
+ Optab{AINIT_, nil, 0, [13]uint8{}},
+ Optab{ASIGNAME, nil, 0, [13]uint8{}},
+ Optab{ACMPXCHGB, yrb_mb, Pm, [13]uint8{0xb0}},
+ Optab{ACMPXCHGL, yrl_ml, Pm, [13]uint8{0xb1}},
+ Optab{ACMPXCHGW, yrl_ml, Pm, [13]uint8{0xb1}},
+ Optab{ACMPXCHG8B, yscond, Pm, [13]uint8{0xc7, 01}},
+ Optab{ACPUID, ynone, Pm, [13]uint8{0xa2}},
+ Optab{ARDTSC, ynone, Pm, [13]uint8{0x31}},
+ Optab{AXADDB, yrb_mb, Pb, [13]uint8{0x0f, 0xc0}},
+ Optab{AXADDL, yrl_ml, Pm, [13]uint8{0xc1}},
+ Optab{AXADDW, yrl_ml, Pe, [13]uint8{0x0f, 0xc1}},
+ Optab{ACMOVLCC, yml_rl, Pm, [13]uint8{0x43}},
+ Optab{ACMOVLCS, yml_rl, Pm, [13]uint8{0x42}},
+ Optab{ACMOVLEQ, yml_rl, Pm, [13]uint8{0x44}},
+ Optab{ACMOVLGE, yml_rl, Pm, [13]uint8{0x4d}},
+ Optab{ACMOVLGT, yml_rl, Pm, [13]uint8{0x4f}},
+ Optab{ACMOVLHI, yml_rl, Pm, [13]uint8{0x47}},
+ Optab{ACMOVLLE, yml_rl, Pm, [13]uint8{0x4e}},
+ Optab{ACMOVLLS, yml_rl, Pm, [13]uint8{0x46}},
+ Optab{ACMOVLLT, yml_rl, Pm, [13]uint8{0x4c}},
+ Optab{ACMOVLMI, yml_rl, Pm, [13]uint8{0x48}},
+ Optab{ACMOVLNE, yml_rl, Pm, [13]uint8{0x45}},
+ Optab{ACMOVLOC, yml_rl, Pm, [13]uint8{0x41}},
+ Optab{ACMOVLOS, yml_rl, Pm, [13]uint8{0x40}},
+ Optab{ACMOVLPC, yml_rl, Pm, [13]uint8{0x4b}},
+ Optab{ACMOVLPL, yml_rl, Pm, [13]uint8{0x49}},
+ Optab{ACMOVLPS, yml_rl, Pm, [13]uint8{0x4a}},
+ Optab{ACMOVWCC, yml_rl, Pq, [13]uint8{0x43}},
+ Optab{ACMOVWCS, yml_rl, Pq, [13]uint8{0x42}},
+ Optab{ACMOVWEQ, yml_rl, Pq, [13]uint8{0x44}},
+ Optab{ACMOVWGE, yml_rl, Pq, [13]uint8{0x4d}},
+ Optab{ACMOVWGT, yml_rl, Pq, [13]uint8{0x4f}},
+ Optab{ACMOVWHI, yml_rl, Pq, [13]uint8{0x47}},
+ Optab{ACMOVWLE, yml_rl, Pq, [13]uint8{0x4e}},
+ Optab{ACMOVWLS, yml_rl, Pq, [13]uint8{0x46}},
+ Optab{ACMOVWLT, yml_rl, Pq, [13]uint8{0x4c}},
+ Optab{ACMOVWMI, yml_rl, Pq, [13]uint8{0x48}},
+ Optab{ACMOVWNE, yml_rl, Pq, [13]uint8{0x45}},
+ Optab{ACMOVWOC, yml_rl, Pq, [13]uint8{0x41}},
+ Optab{ACMOVWOS, yml_rl, Pq, [13]uint8{0x40}},
+ Optab{ACMOVWPC, yml_rl, Pq, [13]uint8{0x4b}},
+ Optab{ACMOVWPL, yml_rl, Pq, [13]uint8{0x49}},
+ Optab{ACMOVWPS, yml_rl, Pq, [13]uint8{0x4a}},
+ Optab{AFCMOVCC, yfcmv, Px, [13]uint8{0xdb, 00}},
+ Optab{AFCMOVCS, yfcmv, Px, [13]uint8{0xda, 00}},
+ Optab{AFCMOVEQ, yfcmv, Px, [13]uint8{0xda, 01}},
+ Optab{AFCMOVHI, yfcmv, Px, [13]uint8{0xdb, 02}},
+ Optab{AFCMOVLS, yfcmv, Px, [13]uint8{0xda, 02}},
+ Optab{AFCMOVNE, yfcmv, Px, [13]uint8{0xdb, 01}},
+ Optab{AFCMOVNU, yfcmv, Px, [13]uint8{0xdb, 03}},
+ Optab{AFCMOVUN, yfcmv, Px, [13]uint8{0xda, 03}},
+ Optab{ALFENCE, ynone, Pm, [13]uint8{0xae, 0xe8}},
+ Optab{AMFENCE, ynone, Pm, [13]uint8{0xae, 0xf0}},
+ Optab{ASFENCE, ynone, Pm, [13]uint8{0xae, 0xf8}},
+ Optab{AEMMS, ynone, Pm, [13]uint8{0x77}},
+ Optab{APREFETCHT0, yprefetch, Pm, [13]uint8{0x18, 01}},
+ Optab{APREFETCHT1, yprefetch, Pm, [13]uint8{0x18, 02}},
+ Optab{APREFETCHT2, yprefetch, Pm, [13]uint8{0x18, 03}},
+ Optab{APREFETCHNTA, yprefetch, Pm, [13]uint8{0x18, 00}},
+ Optab{ABSWAPL, ybswap, Pm, [13]uint8{0xc8}},
+ Optab{AUNDEF, ynone, Px, [13]uint8{0x0f, 0x0b}},
+ Optab{AADDPD, yxm, Pq, [13]uint8{0x58}},
+ Optab{AADDPS, yxm, Pm, [13]uint8{0x58}},
+ Optab{AADDSD, yxm, Pf2, [13]uint8{0x58}},
+ Optab{AADDSS, yxm, Pf3, [13]uint8{0x58}},
+ Optab{AANDNPD, yxm, Pq, [13]uint8{0x55}},
+ Optab{AANDNPS, yxm, Pm, [13]uint8{0x55}},
+ Optab{AANDPD, yxm, Pq, [13]uint8{0x54}},
+ Optab{AANDPS, yxm, Pq, [13]uint8{0x54}},
+ Optab{ACMPPD, yxcmpi, Px, [13]uint8{Pe, 0xc2}},
+ Optab{ACMPPS, yxcmpi, Pm, [13]uint8{0xc2, 0}},
+ Optab{ACMPSD, yxcmpi, Px, [13]uint8{Pf2, 0xc2}},
+ Optab{ACMPSS, yxcmpi, Px, [13]uint8{Pf3, 0xc2}},
+ Optab{ACOMISD, yxcmp, Pe, [13]uint8{0x2f}},
+ Optab{ACOMISS, yxcmp, Pm, [13]uint8{0x2f}},
+ Optab{ACVTPL2PD, yxcvm2, Px, [13]uint8{Pf3, 0xe6, Pe, 0x2a}},
+ Optab{ACVTPL2PS, yxcvm2, Pm, [13]uint8{0x5b, 0, 0x2a, 0}},
+ Optab{ACVTPD2PL, yxcvm1, Px, [13]uint8{Pf2, 0xe6, Pe, 0x2d}},
+ Optab{ACVTPD2PS, yxm, Pe, [13]uint8{0x5a}},
+ Optab{ACVTPS2PL, yxcvm1, Px, [13]uint8{Pe, 0x5b, Pm, 0x2d}},
+ Optab{ACVTPS2PD, yxm, Pm, [13]uint8{0x5a}},
+ Optab{ACVTSD2SL, yxcvfl, Pf2, [13]uint8{0x2d}},
+ Optab{ACVTSD2SS, yxm, Pf2, [13]uint8{0x5a}},
+ Optab{ACVTSL2SD, yxcvlf, Pf2, [13]uint8{0x2a}},
+ Optab{ACVTSL2SS, yxcvlf, Pf3, [13]uint8{0x2a}},
+ Optab{ACVTSS2SD, yxm, Pf3, [13]uint8{0x5a}},
+ Optab{ACVTSS2SL, yxcvfl, Pf3, [13]uint8{0x2d}},
+ Optab{ACVTTPD2PL, yxcvm1, Px, [13]uint8{Pe, 0xe6, Pe, 0x2c}},
+ Optab{ACVTTPS2PL, yxcvm1, Px, [13]uint8{Pf3, 0x5b, Pm, 0x2c}},
+ Optab{ACVTTSD2SL, yxcvfl, Pf2, [13]uint8{0x2c}},
+ Optab{ACVTTSS2SL, yxcvfl, Pf3, [13]uint8{0x2c}},
+ Optab{ADIVPD, yxm, Pe, [13]uint8{0x5e}},
+ Optab{ADIVPS, yxm, Pm, [13]uint8{0x5e}},
+ Optab{ADIVSD, yxm, Pf2, [13]uint8{0x5e}},
+ Optab{ADIVSS, yxm, Pf3, [13]uint8{0x5e}},
+ Optab{AMASKMOVOU, yxr, Pe, [13]uint8{0xf7}},
+ Optab{AMAXPD, yxm, Pe, [13]uint8{0x5f}},
+ Optab{AMAXPS, yxm, Pm, [13]uint8{0x5f}},
+ Optab{AMAXSD, yxm, Pf2, [13]uint8{0x5f}},
+ Optab{AMAXSS, yxm, Pf3, [13]uint8{0x5f}},
+ Optab{AMINPD, yxm, Pe, [13]uint8{0x5d}},
+ Optab{AMINPS, yxm, Pm, [13]uint8{0x5d}},
+ Optab{AMINSD, yxm, Pf2, [13]uint8{0x5d}},
+ Optab{AMINSS, yxm, Pf3, [13]uint8{0x5d}},
+ Optab{AMOVAPD, yxmov, Pe, [13]uint8{0x28, 0x29}},
+ Optab{AMOVAPS, yxmov, Pm, [13]uint8{0x28, 0x29}},
+ Optab{AMOVO, yxmov, Pe, [13]uint8{0x6f, 0x7f}},
+ Optab{AMOVOU, yxmov, Pf3, [13]uint8{0x6f, 0x7f}},
+ Optab{AMOVHLPS, yxr, Pm, [13]uint8{0x12}},
+ Optab{AMOVHPD, yxmov, Pe, [13]uint8{0x16, 0x17}},
+ Optab{AMOVHPS, yxmov, Pm, [13]uint8{0x16, 0x17}},
+ Optab{AMOVLHPS, yxr, Pm, [13]uint8{0x16}},
+ Optab{AMOVLPD, yxmov, Pe, [13]uint8{0x12, 0x13}},
+ Optab{AMOVLPS, yxmov, Pm, [13]uint8{0x12, 0x13}},
+ Optab{AMOVMSKPD, yxrrl, Pq, [13]uint8{0x50}},
+ Optab{AMOVMSKPS, yxrrl, Pm, [13]uint8{0x50}},
+ Optab{AMOVNTO, yxr_ml, Pe, [13]uint8{0xe7}},
+ Optab{AMOVNTPD, yxr_ml, Pe, [13]uint8{0x2b}},
+ Optab{AMOVNTPS, yxr_ml, Pm, [13]uint8{0x2b}},
+ Optab{AMOVSD, yxmov, Pf2, [13]uint8{0x10, 0x11}},
+ Optab{AMOVSS, yxmov, Pf3, [13]uint8{0x10, 0x11}},
+ Optab{AMOVUPD, yxmov, Pe, [13]uint8{0x10, 0x11}},
+ Optab{AMOVUPS, yxmov, Pm, [13]uint8{0x10, 0x11}},
+ Optab{AMULPD, yxm, Pe, [13]uint8{0x59}},
+ Optab{AMULPS, yxm, Ym, [13]uint8{0x59}},
+ Optab{AMULSD, yxm, Pf2, [13]uint8{0x59}},
+ Optab{AMULSS, yxm, Pf3, [13]uint8{0x59}},
+ Optab{AORPD, yxm, Pq, [13]uint8{0x56}},
+ Optab{AORPS, yxm, Pm, [13]uint8{0x56}},
+ Optab{APADDQ, yxm, Pe, [13]uint8{0xd4}},
+ Optab{APAND, yxm, Pe, [13]uint8{0xdb}},
+ Optab{APCMPEQB, yxmq, Pe, [13]uint8{0x74}},
+ Optab{APMAXSW, yxm, Pe, [13]uint8{0xee}},
+ Optab{APMAXUB, yxm, Pe, [13]uint8{0xde}},
+ Optab{APMINSW, yxm, Pe, [13]uint8{0xea}},
+ Optab{APMINUB, yxm, Pe, [13]uint8{0xda}},
+ Optab{APMOVMSKB, ymskb, Px, [13]uint8{Pe, 0xd7, 0xd7}},
+ Optab{APSADBW, yxm, Pq, [13]uint8{0xf6}},
+ Optab{APSUBB, yxm, Pe, [13]uint8{0xf8}},
+ Optab{APSUBL, yxm, Pe, [13]uint8{0xfa}},
+ Optab{APSUBQ, yxm, Pe, [13]uint8{0xfb}},
+ Optab{APSUBSB, yxm, Pe, [13]uint8{0xe8}},
+ Optab{APSUBSW, yxm, Pe, [13]uint8{0xe9}},
+ Optab{APSUBUSB, yxm, Pe, [13]uint8{0xd8}},
+ Optab{APSUBUSW, yxm, Pe, [13]uint8{0xd9}},
+ Optab{APSUBW, yxm, Pe, [13]uint8{0xf9}},
+ Optab{APUNPCKHQDQ, yxm, Pe, [13]uint8{0x6d}},
+ Optab{APUNPCKLQDQ, yxm, Pe, [13]uint8{0x6c}},
+ Optab{APXOR, yxm, Pe, [13]uint8{0xef}},
+ Optab{ARCPPS, yxm, Pm, [13]uint8{0x53}},
+ Optab{ARCPSS, yxm, Pf3, [13]uint8{0x53}},
+ Optab{ARSQRTPS, yxm, Pm, [13]uint8{0x52}},
+ Optab{ARSQRTSS, yxm, Pf3, [13]uint8{0x52}},
+ Optab{ASQRTPD, yxm, Pe, [13]uint8{0x51}},
+ Optab{ASQRTPS, yxm, Pm, [13]uint8{0x51}},
+ Optab{ASQRTSD, yxm, Pf2, [13]uint8{0x51}},
+ Optab{ASQRTSS, yxm, Pf3, [13]uint8{0x51}},
+ Optab{ASUBPD, yxm, Pe, [13]uint8{0x5c}},
+ Optab{ASUBPS, yxm, Pm, [13]uint8{0x5c}},
+ Optab{ASUBSD, yxm, Pf2, [13]uint8{0x5c}},
+ Optab{ASUBSS, yxm, Pf3, [13]uint8{0x5c}},
+ Optab{AUCOMISD, yxcmp, Pe, [13]uint8{0x2e}},
+ Optab{AUCOMISS, yxcmp, Pm, [13]uint8{0x2e}},
+ Optab{AUNPCKHPD, yxm, Pe, [13]uint8{0x15}},
+ Optab{AUNPCKHPS, yxm, Pm, [13]uint8{0x15}},
+ Optab{AUNPCKLPD, yxm, Pe, [13]uint8{0x14}},
+ Optab{AUNPCKLPS, yxm, Pm, [13]uint8{0x14}},
+ Optab{AXORPD, yxm, Pe, [13]uint8{0x57}},
+ Optab{AXORPS, yxm, Pm, [13]uint8{0x57}},
+ Optab{APSHUFHW, yxshuf, Pf3, [13]uint8{0x70, 00}},
+ Optab{APSHUFL, yxshuf, Pq, [13]uint8{0x70, 00}},
+ Optab{APSHUFLW, yxshuf, Pf2, [13]uint8{0x70, 00}},
+ Optab{AAESENC, yaes, Pq, [13]uint8{0x38, 0xdc, 0}},
+ Optab{APINSRD, yinsrd, Pq, [13]uint8{0x3a, 0x22, 00}},
+ Optab{APSHUFB, ymshufb, Pq, [13]uint8{0x38, 0x00}},
+ Optab{AUSEFIELD, ynop, Px, [13]uint8{0, 0}},
+ Optab{ATYPE, nil, 0, [13]uint8{}},
+ Optab{AFUNCDATA, yfuncdata, Px, [13]uint8{0, 0}},
+ Optab{APCDATA, ypcdata, Px, [13]uint8{0, 0}},
+ Optab{ACHECKNIL, nil, 0, [13]uint8{}},
+ Optab{AVARDEF, nil, 0, [13]uint8{}},
+ Optab{AVARKILL, nil, 0, [13]uint8{}},
+ Optab{ADUFFCOPY, yduff, Px, [13]uint8{0xe8}},
+ Optab{ADUFFZERO, yduff, Px, [13]uint8{0xe8}},
+ Optab{0, nil, 0, [13]uint8{}},
+}
+
+// single-instruction no-ops of various lengths.
+// constructed by hand and disassembled with gdb to verify.
+// see http://www.agner.org/optimize/optimizing_assembly.pdf for discussion.
+var nop = [][16]uint8{
+ [16]uint8{0x90},
+ [16]uint8{0x66, 0x90},
+ [16]uint8{0x0F, 0x1F, 0x00},
+ [16]uint8{0x0F, 0x1F, 0x40, 0x00},
+ [16]uint8{0x0F, 0x1F, 0x44, 0x00, 0x00},
+ [16]uint8{0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00},
+ [16]uint8{0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00},
+ [16]uint8{0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+ [16]uint8{0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+}
+
+// Native Client rejects the repeated 0x66 prefix.
+// {0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+func fillnop(p []byte, n int) {
+
+ var m int
+
+ for n > 0 {
+ m = n
+ if m > len(nop) {
+ m = len(nop)
+ }
+ copy(p[:m], nop[m-1][:m])
+ p = p[m:]
+ n -= m
+ }
+}
+
+func naclpad(ctxt *obj.Link, s *obj.LSym, c int32, pad int32) int32 {
+ obj.Symgrow(ctxt, s, int64(c)+int64(pad))
+ fillnop(s.P[c:], int(pad))
+ return c + pad
+}
+
+func span8(ctxt *obj.Link, s *obj.LSym) {
+ var p *obj.Prog
+ var q *obj.Prog
+ var c int32
+ var v int32
+ var loop int32
+ var bp []byte
+ var n int
+ var m int
+ var i int
+
+ ctxt.Cursym = s
+
+ if s.Text == nil || s.Text.Link == nil {
+ return
+ }
+
+ if ycover[0] == 0 {
+ instinit()
+ }
+
+ for p = s.Text; p != nil; p = p.Link {
+ n = 0
+ if p.To.Type == D_BRANCH {
+ if p.Pcond == nil {
+ p.Pcond = p
+ }
+ }
+ q = p.Pcond
+ if q != nil {
+ if q.Back != 2 {
+ n = 1
+ }
+ }
+ p.Back = uint8(n)
+ if p.As == AADJSP {
+ p.To.Type = D_SP
+ v = int32(-p.From.Offset)
+ p.From.Offset = int64(v)
+ p.As = AADDL
+ if v < 0 {
+ p.As = ASUBL
+ v = -v
+ p.From.Offset = int64(v)
+ }
+
+ if v == 0 {
+ p.As = ANOP
+ }
+ }
+ }
+
+ for p = s.Text; p != nil; p = p.Link {
+ p.Back = 2 // use short branches first time through
+ q = p.Pcond
+ if q != nil && (q.Back&2 != 0) {
+ p.Back |= 1 // backward jump
+ }
+
+ if p.As == AADJSP {
+
+ p.To.Type = D_SP
+ v = int32(-p.From.Offset)
+ p.From.Offset = int64(v)
+ p.As = AADDL
+ if v < 0 {
+ p.As = ASUBL
+ v = -v
+ p.From.Offset = int64(v)
+ }
+
+ if v == 0 {
+ p.As = ANOP
+ }
+ }
+ }
+
+ n = 0
+ for {
+ loop = 0
+ for i = 0; i < len(s.R); i++ {
+ s.R[i] = obj.Reloc{}
+ }
+ s.R = s.R[:0]
+ s.P = s.P[:0]
+ c = 0
+ for p = s.Text; p != nil; p = p.Link {
+ if ctxt.Headtype == obj.Hnacl && p.Isize > 0 {
+ var deferreturn *obj.LSym
+
+ if deferreturn == nil {
+ deferreturn = obj.Linklookup(ctxt, "runtime.deferreturn", 0)
+ }
+
+ // pad everything to avoid crossing 32-byte boundary
+ if c>>5 != (c+int32(p.Isize)-1)>>5 {
+
+ c = naclpad(ctxt, s, c, -c&31)
+ }
+
+ // pad call deferreturn to start at 32-byte boundary
+ // so that subtracting 5 in jmpdefer will jump back
+ // to that boundary and rerun the call.
+ if p.As == ACALL && p.To.Sym == deferreturn {
+
+ c = naclpad(ctxt, s, c, -c&31)
+ }
+
+ // pad call to end at 32-byte boundary
+ if p.As == ACALL {
+
+ c = naclpad(ctxt, s, c, -(c+int32(p.Isize))&31)
+ }
+
+ // the linker treats REP and STOSQ as different instructions
+ // but in fact the REP is a prefix on the STOSQ.
+ // make sure REP has room for 2 more bytes, so that
+ // padding will not be inserted before the next instruction.
+ if p.As == AREP && c>>5 != (c+3-1)>>5 {
+
+ c = naclpad(ctxt, s, c, -c&31)
+ }
+
+ // same for LOCK.
+ // various instructions follow; the longest is 4 bytes.
+ // give ourselves 8 bytes so as to avoid surprises.
+ if p.As == ALOCK && c>>5 != (c+8-1)>>5 {
+
+ c = naclpad(ctxt, s, c, -c&31)
+ }
+ }
+
+ p.Pc = int64(c)
+
+ // process forward jumps to p
+ for q = p.Comefrom; q != nil; q = q.Forwd {
+
+ v = int32(p.Pc - (q.Pc + int64(q.Mark)))
+ if q.Back&2 != 0 { // short
+ if v > 127 {
+ loop++
+ q.Back ^= 2
+ }
+
+ if q.As == AJCXZW {
+ s.P[q.Pc+2] = byte(v)
+ } else {
+
+ s.P[q.Pc+1] = byte(v)
+ }
+ } else {
+
+ bp = s.P[q.Pc+int64(q.Mark)-4:]
+ bp[0] = byte(v)
+ bp = bp[1:]
+ bp[0] = byte(v >> 8)
+ bp = bp[1:]
+ bp[0] = byte(v >> 16)
+ bp = bp[1:]
+ bp[0] = byte(v >> 24)
+ }
+ }
+
+ p.Comefrom = nil
+
+ p.Pc = int64(c)
+ asmins(ctxt, p)
+ m = -cap(ctxt.Andptr) + cap(ctxt.And[:])
+ if int(p.Isize) != m {
+ p.Isize = uint8(m)
+ loop++
+ }
+
+ obj.Symgrow(ctxt, s, p.Pc+int64(m))
+ copy(s.P[p.Pc:][:m], ctxt.And[:m])
+ p.Mark = uint16(m)
+ c += int32(m)
+ }
+
+ n++
+ if n > 20 {
+ ctxt.Diag("span must be looping")
+ log.Fatalf("bad code")
+ }
+ if !(loop != 0) {
+ break
+ }
+ }
+
+ if ctxt.Headtype == obj.Hnacl {
+ c = naclpad(ctxt, s, c, -c&31)
+ }
+ c += -c & (FuncAlign - 1)
+ s.Size = int64(c)
+
+ if false { /* debug['a'] > 1 */
+ fmt.Printf("span1 %s %d (%d tries)\n %.6x", s.Name, s.Size, n, 0)
+ for i = 0; i < len(s.P); i++ {
+ fmt.Printf(" %.2x", s.P[i])
+ if i%16 == 15 {
+ fmt.Printf("\n %.6x", uint(i+1))
+ }
+ }
+
+ if i%16 != 0 {
+ fmt.Printf("\n")
+ }
+
+ for i = 0; i < len(s.R); i++ {
+ var r *obj.Reloc
+
+ r = &s.R[i]
+ fmt.Printf(" rel %#.4x/%d %s%+d\n", uint32(r.Off), r.Siz, r.Sym.Name, r.Add)
+ }
+ }
+}
+
+func instinit() {
+ var i int
+
+ for i = 1; optab[i].as != 0; i++ {
+ if i != int(optab[i].as) {
+ log.Fatalf("phase error in optab: at %v found %v", Aconv(i), Aconv(int(optab[i].as)))
+ }
+ }
+
+ for i = 0; i < Ymax; i++ {
+ ycover[i*Ymax+i] = 1
+ }
+
+ ycover[Yi0*Ymax+Yi8] = 1
+ ycover[Yi1*Ymax+Yi8] = 1
+
+ ycover[Yi0*Ymax+Yi32] = 1
+ ycover[Yi1*Ymax+Yi32] = 1
+ ycover[Yi8*Ymax+Yi32] = 1
+
+ ycover[Yal*Ymax+Yrb] = 1
+ ycover[Ycl*Ymax+Yrb] = 1
+ ycover[Yax*Ymax+Yrb] = 1
+ ycover[Ycx*Ymax+Yrb] = 1
+ ycover[Yrx*Ymax+Yrb] = 1
+
+ ycover[Yax*Ymax+Yrx] = 1
+ ycover[Ycx*Ymax+Yrx] = 1
+
+ ycover[Yax*Ymax+Yrl] = 1
+ ycover[Ycx*Ymax+Yrl] = 1
+ ycover[Yrx*Ymax+Yrl] = 1
+
+ ycover[Yf0*Ymax+Yrf] = 1
+
+ ycover[Yal*Ymax+Ymb] = 1
+ ycover[Ycl*Ymax+Ymb] = 1
+ ycover[Yax*Ymax+Ymb] = 1
+ ycover[Ycx*Ymax+Ymb] = 1
+ ycover[Yrx*Ymax+Ymb] = 1
+ ycover[Yrb*Ymax+Ymb] = 1
+ ycover[Ym*Ymax+Ymb] = 1
+
+ ycover[Yax*Ymax+Yml] = 1
+ ycover[Ycx*Ymax+Yml] = 1
+ ycover[Yrx*Ymax+Yml] = 1
+ ycover[Yrl*Ymax+Yml] = 1
+ ycover[Ym*Ymax+Yml] = 1
+
+ ycover[Yax*Ymax+Ymm] = 1
+ ycover[Ycx*Ymax+Ymm] = 1
+ ycover[Yrx*Ymax+Ymm] = 1
+ ycover[Yrl*Ymax+Ymm] = 1
+ ycover[Ym*Ymax+Ymm] = 1
+ ycover[Ymr*Ymax+Ymm] = 1
+
+ ycover[Ym*Ymax+Yxm] = 1
+ ycover[Yxr*Ymax+Yxm] = 1
+
+ for i = 0; i < D_NONE; i++ {
+ reg[i] = -1
+ if i >= D_AL && i <= D_BH {
+ reg[i] = (i - D_AL) & 7
+ }
+ if i >= D_AX && i <= D_DI {
+ reg[i] = (i - D_AX) & 7
+ }
+ if i >= D_F0 && i <= D_F0+7 {
+ reg[i] = (i - D_F0) & 7
+ }
+ if i >= D_X0 && i <= D_X0+7 {
+ reg[i] = (i - D_X0) & 7
+ }
+ }
+}
+
+func prefixof(ctxt *obj.Link, a *obj.Addr) int {
+ switch a.Type {
+ case D_INDIR + D_CS:
+ return 0x2e
+
+ case D_INDIR + D_DS:
+ return 0x3e
+
+ case D_INDIR + D_ES:
+ return 0x26
+
+ case D_INDIR + D_FS:
+ return 0x64
+
+ case D_INDIR + D_GS:
+ return 0x65
+
+ // NOTE: Systems listed here should be only systems that
+ // support direct TLS references like 8(TLS) implemented as
+ // direct references from FS or GS. Systems that require
+ // the initial-exec model, where you load the TLS base into
+ // a register and then index from that register, do not reach
+ // this code and should not be listed.
+ case D_INDIR + D_TLS:
+ switch ctxt.Headtype {
+
+ default:
+ log.Fatalf("unknown TLS base register for %s", obj.Headstr(ctxt.Headtype))
+
+ case obj.Hdarwin,
+ obj.Hdragonfly,
+ obj.Hfreebsd,
+ obj.Hnetbsd,
+ obj.Hopenbsd:
+ return 0x65 // GS
+ }
+ }
+
+ return 0
+}
+
+func oclass(a *obj.Addr) int {
+ var v int32
+
+ if (a.Type >= D_INDIR && a.Type < 2*D_INDIR) || a.Index != D_NONE {
+ if a.Index != D_NONE && a.Scale == 0 {
+ if a.Type == D_ADDR {
+ switch a.Index {
+ case D_EXTERN,
+ D_STATIC:
+ return Yi32
+
+ case D_AUTO,
+ D_PARAM:
+ return Yiauto
+ }
+
+ return Yxxx
+ }
+
+ //if(a->type == D_INDIR+D_ADDR)
+ // print("*Ycol\n");
+ return Ycol
+ }
+
+ return Ym
+ }
+
+ switch a.Type {
+ case D_AL:
+ return Yal
+
+ case D_AX:
+ return Yax
+
+ case D_CL,
+ D_DL,
+ D_BL,
+ D_AH,
+ D_CH,
+ D_DH,
+ D_BH:
+ return Yrb
+
+ case D_CX:
+ return Ycx
+
+ case D_DX,
+ D_BX:
+ return Yrx
+
+ case D_SP,
+ D_BP,
+ D_SI,
+ D_DI:
+ return Yrl
+
+ case D_F0 + 0:
+ return Yf0
+
+ case D_F0 + 1,
+ D_F0 + 2,
+ D_F0 + 3,
+ D_F0 + 4,
+ D_F0 + 5,
+ D_F0 + 6,
+ D_F0 + 7:
+ return Yrf
+
+ case D_X0 + 0,
+ D_X0 + 1,
+ D_X0 + 2,
+ D_X0 + 3,
+ D_X0 + 4,
+ D_X0 + 5,
+ D_X0 + 6,
+ D_X0 + 7:
+ return Yxr
+
+ case D_NONE:
+ return Ynone
+
+ case D_CS:
+ return Ycs
+ case D_SS:
+ return Yss
+ case D_DS:
+ return Yds
+ case D_ES:
+ return Yes
+ case D_FS:
+ return Yfs
+ case D_GS:
+ return Ygs
+ case D_TLS:
+ return Ytls
+
+ case D_GDTR:
+ return Ygdtr
+ case D_IDTR:
+ return Yidtr
+ case D_LDTR:
+ return Yldtr
+ case D_MSW:
+ return Ymsw
+ case D_TASK:
+ return Ytask
+
+ case D_CR + 0:
+ return Ycr0
+ case D_CR + 1:
+ return Ycr1
+ case D_CR + 2:
+ return Ycr2
+ case D_CR + 3:
+ return Ycr3
+ case D_CR + 4:
+ return Ycr4
+ case D_CR + 5:
+ return Ycr5
+ case D_CR + 6:
+ return Ycr6
+ case D_CR + 7:
+ return Ycr7
+
+ case D_DR + 0:
+ return Ydr0
+ case D_DR + 1:
+ return Ydr1
+ case D_DR + 2:
+ return Ydr2
+ case D_DR + 3:
+ return Ydr3
+ case D_DR + 4:
+ return Ydr4
+ case D_DR + 5:
+ return Ydr5
+ case D_DR + 6:
+ return Ydr6
+ case D_DR + 7:
+ return Ydr7
+
+ case D_TR + 0:
+ return Ytr0
+ case D_TR + 1:
+ return Ytr1
+ case D_TR + 2:
+ return Ytr2
+ case D_TR + 3:
+ return Ytr3
+ case D_TR + 4:
+ return Ytr4
+ case D_TR + 5:
+ return Ytr5
+ case D_TR + 6:
+ return Ytr6
+ case D_TR + 7:
+ return Ytr7
+
+ case D_EXTERN,
+ D_STATIC,
+ D_AUTO,
+ D_PARAM:
+ return Ym
+
+ case D_CONST,
+ D_CONST2,
+ D_ADDR:
+ if a.Sym == nil {
+ v = int32(a.Offset)
+ if v == 0 {
+ return Yi0
+ }
+ if v == 1 {
+ return Yi1
+ }
+ if v >= -128 && v <= 127 {
+ return Yi8
+ }
+ }
+
+ return Yi32
+
+ case D_BRANCH:
+ return Ybr
+ }
+
+ return Yxxx
+}
+
+func asmidx(ctxt *obj.Link, scale int, index int, base int) {
+ var i int
+
+ switch index {
+ default:
+ goto bad
+
+ case D_NONE:
+ i = 4 << 3
+ goto bas
+
+ case D_AX,
+ D_CX,
+ D_DX,
+ D_BX,
+ D_BP,
+ D_SI,
+ D_DI:
+ i = reg[index] << 3
+ break
+ }
+
+ switch scale {
+ default:
+ goto bad
+
+ case 1:
+ break
+
+ case 2:
+ i |= 1 << 6
+
+ case 4:
+ i |= 2 << 6
+
+ case 8:
+ i |= 3 << 6
+ break
+ }
+
+bas:
+ switch base {
+ default:
+ goto bad
+
+ case D_NONE: /* must be mod=00 */
+ i |= 5
+
+ case D_AX,
+ D_CX,
+ D_DX,
+ D_BX,
+ D_SP,
+ D_BP,
+ D_SI,
+ D_DI:
+ i |= reg[base]
+ break
+ }
+
+ ctxt.Andptr[0] = byte(i)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ return
+
+bad:
+ ctxt.Diag("asmidx: bad address %d,%d,%d", scale, index, base)
+ ctxt.Andptr[0] = 0
+ ctxt.Andptr = ctxt.Andptr[1:]
+ return
+}
+
+func put4(ctxt *obj.Link, v int32) {
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr[1] = byte(v >> 8)
+ ctxt.Andptr[2] = byte(v >> 16)
+ ctxt.Andptr[3] = byte(v >> 24)
+ ctxt.Andptr = ctxt.Andptr[4:]
+}
+
+func relput4(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) {
+ var v int64
+ var rel obj.Reloc
+ var r *obj.Reloc
+
+ v = int64(vaddr(ctxt, p, a, &rel))
+ if rel.Siz != 0 {
+ if rel.Siz != 4 {
+ ctxt.Diag("bad reloc")
+ }
+ r = obj.Addrel(ctxt.Cursym)
+ *r = rel
+ r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+ }
+
+ put4(ctxt, int32(v))
+}
+
+func vaddr(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r *obj.Reloc) int32 {
+ var t int
+ var v int32
+ var s *obj.LSym
+
+ if r != nil {
+ *r = obj.Reloc{}
+ }
+
+ t = int(a.Type)
+ v = int32(a.Offset)
+ if t == D_ADDR {
+ t = int(a.Index)
+ }
+ switch t {
+ case D_STATIC,
+ D_EXTERN:
+ s = a.Sym
+ if s != nil {
+ if r == nil {
+ ctxt.Diag("need reloc for %v", Dconv(p, 0, a))
+ log.Fatalf("bad code")
+ }
+
+ r.Type = obj.R_ADDR
+ r.Siz = 4
+ r.Off = -1
+ r.Sym = s
+ r.Add = int64(v)
+ v = 0
+ }
+
+ case D_INDIR + D_TLS:
+ if r == nil {
+ ctxt.Diag("need reloc for %v", Dconv(p, 0, a))
+ log.Fatalf("bad code")
+ }
+
+ r.Type = obj.R_TLS_LE
+ r.Siz = 4
+ r.Off = -1 // caller must fill in
+ r.Add = int64(v)
+ v = 0
+ break
+ }
+
+ return v
+}
+
+func asmand(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int) {
+ var v int32
+ var t int
+ var scale int
+ var rel obj.Reloc
+
+ v = int32(a.Offset)
+ t = int(a.Type)
+ rel.Siz = 0
+ if a.Index != D_NONE && a.Index != D_TLS {
+ if t < D_INDIR || t >= 2*D_INDIR {
+ switch t {
+ default:
+ goto bad
+
+ case D_STATIC,
+ D_EXTERN:
+ t = D_NONE
+ v = vaddr(ctxt, p, a, &rel)
+
+ case D_AUTO,
+ D_PARAM:
+ t = D_SP
+ break
+ }
+ } else {
+
+ t -= D_INDIR
+ }
+
+ if t == D_NONE {
+ ctxt.Andptr[0] = byte(0<<6 | 4<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmidx(ctxt, int(a.Scale), int(a.Index), t)
+ goto putrelv
+ }
+
+ if v == 0 && rel.Siz == 0 && t != D_BP {
+ ctxt.Andptr[0] = byte(0<<6 | 4<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmidx(ctxt, int(a.Scale), int(a.Index), t)
+ return
+ }
+
+ if v >= -128 && v < 128 && rel.Siz == 0 {
+ ctxt.Andptr[0] = byte(1<<6 | 4<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmidx(ctxt, int(a.Scale), int(a.Index), t)
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ return
+ }
+
+ ctxt.Andptr[0] = byte(2<<6 | 4<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmidx(ctxt, int(a.Scale), int(a.Index), t)
+ goto putrelv
+ }
+
+ if t >= D_AL && t <= D_F7 || t >= D_X0 && t <= D_X7 {
+ if v != 0 {
+ goto bad
+ }
+ ctxt.Andptr[0] = byte(3<<6 | reg[t]<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ return
+ }
+
+ scale = int(a.Scale)
+ if t < D_INDIR || t >= 2*D_INDIR {
+ switch a.Type {
+ default:
+ goto bad
+
+ case D_STATIC,
+ D_EXTERN:
+ t = D_NONE
+ v = vaddr(ctxt, p, a, &rel)
+
+ case D_AUTO,
+ D_PARAM:
+ t = D_SP
+ break
+ }
+
+ scale = 1
+ } else {
+
+ t -= D_INDIR
+ }
+ if t == D_TLS {
+ v = vaddr(ctxt, p, a, &rel)
+ }
+
+ if t == D_NONE || (D_CS <= t && t <= D_GS) || t == D_TLS {
+ ctxt.Andptr[0] = byte(0<<6 | 5<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ goto putrelv
+ }
+
+ if t == D_SP {
+ if v == 0 && rel.Siz == 0 {
+ ctxt.Andptr[0] = byte(0<<6 | 4<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmidx(ctxt, scale, D_NONE, t)
+ return
+ }
+
+ if v >= -128 && v < 128 && rel.Siz == 0 {
+ ctxt.Andptr[0] = byte(1<<6 | 4<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmidx(ctxt, scale, D_NONE, t)
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ return
+ }
+
+ ctxt.Andptr[0] = byte(2<<6 | 4<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmidx(ctxt, scale, D_NONE, t)
+ goto putrelv
+ }
+
+ if t >= D_AX && t <= D_DI {
+ if a.Index == D_TLS {
+ rel = obj.Reloc{}
+ rel.Type = obj.R_TLS_IE
+ rel.Siz = 4
+ rel.Sym = nil
+ rel.Add = int64(v)
+ v = 0
+ }
+
+ if v == 0 && rel.Siz == 0 && t != D_BP {
+ ctxt.Andptr[0] = byte(0<<6 | reg[t]<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ return
+ }
+
+ if v >= -128 && v < 128 && rel.Siz == 0 {
+ ctxt.Andptr[0] = byte(1<<6 | reg[t]<<0 | r<<3)
+ ctxt.Andptr[1] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[2:]
+ return
+ }
+
+ ctxt.Andptr[0] = byte(2<<6 | reg[t]<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ goto putrelv
+ }
+
+ goto bad
+
+putrelv:
+ if rel.Siz != 0 {
+ var r *obj.Reloc
+
+ if rel.Siz != 4 {
+ ctxt.Diag("bad rel")
+ goto bad
+ }
+
+ r = obj.Addrel(ctxt.Cursym)
+ *r = rel
+ r.Off = int32(ctxt.Curp.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+ }
+
+ put4(ctxt, v)
+ return
+
+bad:
+ ctxt.Diag("asmand: bad address %v", Dconv(p, 0, a))
+ return
+}
+
+const (
+ E = 0xff
+)
+
+var ymovtab = []uint8{
+ /* push */
+ APUSHL,
+ Ycs,
+ Ynone,
+ 0,
+ 0x0e,
+ E,
+ 0,
+ 0,
+ APUSHL,
+ Yss,
+ Ynone,
+ 0,
+ 0x16,
+ E,
+ 0,
+ 0,
+ APUSHL,
+ Yds,
+ Ynone,
+ 0,
+ 0x1e,
+ E,
+ 0,
+ 0,
+ APUSHL,
+ Yes,
+ Ynone,
+ 0,
+ 0x06,
+ E,
+ 0,
+ 0,
+ APUSHL,
+ Yfs,
+ Ynone,
+ 0,
+ 0x0f,
+ 0xa0,
+ E,
+ 0,
+ APUSHL,
+ Ygs,
+ Ynone,
+ 0,
+ 0x0f,
+ 0xa8,
+ E,
+ 0,
+ APUSHW,
+ Ycs,
+ Ynone,
+ 0,
+ Pe,
+ 0x0e,
+ E,
+ 0,
+ APUSHW,
+ Yss,
+ Ynone,
+ 0,
+ Pe,
+ 0x16,
+ E,
+ 0,
+ APUSHW,
+ Yds,
+ Ynone,
+ 0,
+ Pe,
+ 0x1e,
+ E,
+ 0,
+ APUSHW,
+ Yes,
+ Ynone,
+ 0,
+ Pe,
+ 0x06,
+ E,
+ 0,
+ APUSHW,
+ Yfs,
+ Ynone,
+ 0,
+ Pe,
+ 0x0f,
+ 0xa0,
+ E,
+ APUSHW,
+ Ygs,
+ Ynone,
+ 0,
+ Pe,
+ 0x0f,
+ 0xa8,
+ E,
+
+ /* pop */
+ APOPL,
+ Ynone,
+ Yds,
+ 0,
+ 0x1f,
+ E,
+ 0,
+ 0,
+ APOPL,
+ Ynone,
+ Yes,
+ 0,
+ 0x07,
+ E,
+ 0,
+ 0,
+ APOPL,
+ Ynone,
+ Yss,
+ 0,
+ 0x17,
+ E,
+ 0,
+ 0,
+ APOPL,
+ Ynone,
+ Yfs,
+ 0,
+ 0x0f,
+ 0xa1,
+ E,
+ 0,
+ APOPL,
+ Ynone,
+ Ygs,
+ 0,
+ 0x0f,
+ 0xa9,
+ E,
+ 0,
+ APOPW,
+ Ynone,
+ Yds,
+ 0,
+ Pe,
+ 0x1f,
+ E,
+ 0,
+ APOPW,
+ Ynone,
+ Yes,
+ 0,
+ Pe,
+ 0x07,
+ E,
+ 0,
+ APOPW,
+ Ynone,
+ Yss,
+ 0,
+ Pe,
+ 0x17,
+ E,
+ 0,
+ APOPW,
+ Ynone,
+ Yfs,
+ 0,
+ Pe,
+ 0x0f,
+ 0xa1,
+ E,
+ APOPW,
+ Ynone,
+ Ygs,
+ 0,
+ Pe,
+ 0x0f,
+ 0xa9,
+ E,
+
+ /* mov seg */
+ AMOVW,
+ Yes,
+ Yml,
+ 1,
+ 0x8c,
+ 0,
+ 0,
+ 0,
+ AMOVW,
+ Ycs,
+ Yml,
+ 1,
+ 0x8c,
+ 1,
+ 0,
+ 0,
+ AMOVW,
+ Yss,
+ Yml,
+ 1,
+ 0x8c,
+ 2,
+ 0,
+ 0,
+ AMOVW,
+ Yds,
+ Yml,
+ 1,
+ 0x8c,
+ 3,
+ 0,
+ 0,
+ AMOVW,
+ Yfs,
+ Yml,
+ 1,
+ 0x8c,
+ 4,
+ 0,
+ 0,
+ AMOVW,
+ Ygs,
+ Yml,
+ 1,
+ 0x8c,
+ 5,
+ 0,
+ 0,
+ AMOVW,
+ Yml,
+ Yes,
+ 2,
+ 0x8e,
+ 0,
+ 0,
+ 0,
+ AMOVW,
+ Yml,
+ Ycs,
+ 2,
+ 0x8e,
+ 1,
+ 0,
+ 0,
+ AMOVW,
+ Yml,
+ Yss,
+ 2,
+ 0x8e,
+ 2,
+ 0,
+ 0,
+ AMOVW,
+ Yml,
+ Yds,
+ 2,
+ 0x8e,
+ 3,
+ 0,
+ 0,
+ AMOVW,
+ Yml,
+ Yfs,
+ 2,
+ 0x8e,
+ 4,
+ 0,
+ 0,
+ AMOVW,
+ Yml,
+ Ygs,
+ 2,
+ 0x8e,
+ 5,
+ 0,
+ 0,
+
+ /* mov cr */
+ AMOVL,
+ Ycr0,
+ Yml,
+ 3,
+ 0x0f,
+ 0x20,
+ 0,
+ 0,
+ AMOVL,
+ Ycr2,
+ Yml,
+ 3,
+ 0x0f,
+ 0x20,
+ 2,
+ 0,
+ AMOVL,
+ Ycr3,
+ Yml,
+ 3,
+ 0x0f,
+ 0x20,
+ 3,
+ 0,
+ AMOVL,
+ Ycr4,
+ Yml,
+ 3,
+ 0x0f,
+ 0x20,
+ 4,
+ 0,
+ AMOVL,
+ Yml,
+ Ycr0,
+ 4,
+ 0x0f,
+ 0x22,
+ 0,
+ 0,
+ AMOVL,
+ Yml,
+ Ycr2,
+ 4,
+ 0x0f,
+ 0x22,
+ 2,
+ 0,
+ AMOVL,
+ Yml,
+ Ycr3,
+ 4,
+ 0x0f,
+ 0x22,
+ 3,
+ 0,
+ AMOVL,
+ Yml,
+ Ycr4,
+ 4,
+ 0x0f,
+ 0x22,
+ 4,
+ 0,
+
+ /* mov dr */
+ AMOVL,
+ Ydr0,
+ Yml,
+ 3,
+ 0x0f,
+ 0x21,
+ 0,
+ 0,
+ AMOVL,
+ Ydr6,
+ Yml,
+ 3,
+ 0x0f,
+ 0x21,
+ 6,
+ 0,
+ AMOVL,
+ Ydr7,
+ Yml,
+ 3,
+ 0x0f,
+ 0x21,
+ 7,
+ 0,
+ AMOVL,
+ Yml,
+ Ydr0,
+ 4,
+ 0x0f,
+ 0x23,
+ 0,
+ 0,
+ AMOVL,
+ Yml,
+ Ydr6,
+ 4,
+ 0x0f,
+ 0x23,
+ 6,
+ 0,
+ AMOVL,
+ Yml,
+ Ydr7,
+ 4,
+ 0x0f,
+ 0x23,
+ 7,
+ 0,
+
+ /* mov tr */
+ AMOVL,
+ Ytr6,
+ Yml,
+ 3,
+ 0x0f,
+ 0x24,
+ 6,
+ 0,
+ AMOVL,
+ Ytr7,
+ Yml,
+ 3,
+ 0x0f,
+ 0x24,
+ 7,
+ 0,
+ AMOVL,
+ Yml,
+ Ytr6,
+ 4,
+ 0x0f,
+ 0x26,
+ 6,
+ E,
+ AMOVL,
+ Yml,
+ Ytr7,
+ 4,
+ 0x0f,
+ 0x26,
+ 7,
+ E,
+
+ /* lgdt, sgdt, lidt, sidt */
+ AMOVL,
+ Ym,
+ Ygdtr,
+ 4,
+ 0x0f,
+ 0x01,
+ 2,
+ 0,
+ AMOVL,
+ Ygdtr,
+ Ym,
+ 3,
+ 0x0f,
+ 0x01,
+ 0,
+ 0,
+ AMOVL,
+ Ym,
+ Yidtr,
+ 4,
+ 0x0f,
+ 0x01,
+ 3,
+ 0,
+ AMOVL,
+ Yidtr,
+ Ym,
+ 3,
+ 0x0f,
+ 0x01,
+ 1,
+ 0,
+
+ /* lldt, sldt */
+ AMOVW,
+ Yml,
+ Yldtr,
+ 4,
+ 0x0f,
+ 0x00,
+ 2,
+ 0,
+ AMOVW,
+ Yldtr,
+ Yml,
+ 3,
+ 0x0f,
+ 0x00,
+ 0,
+ 0,
+
+ /* lmsw, smsw */
+ AMOVW,
+ Yml,
+ Ymsw,
+ 4,
+ 0x0f,
+ 0x01,
+ 6,
+ 0,
+ AMOVW,
+ Ymsw,
+ Yml,
+ 3,
+ 0x0f,
+ 0x01,
+ 4,
+ 0,
+
+ /* ltr, str */
+ AMOVW,
+ Yml,
+ Ytask,
+ 4,
+ 0x0f,
+ 0x00,
+ 3,
+ 0,
+ AMOVW,
+ Ytask,
+ Yml,
+ 3,
+ 0x0f,
+ 0x00,
+ 1,
+ 0,
+
+ /* load full pointer */
+ AMOVL,
+ Yml,
+ Ycol,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ AMOVW,
+ Yml,
+ Ycol,
+ 5,
+ Pe,
+ 0,
+ 0,
+ 0,
+
+ /* double shift */
+ ASHLL,
+ Ycol,
+ Yml,
+ 6,
+ 0xa4,
+ 0xa5,
+ 0,
+ 0,
+ ASHRL,
+ Ycol,
+ Yml,
+ 6,
+ 0xac,
+ 0xad,
+ 0,
+ 0,
+
+ /* extra imul */
+ AIMULW,
+ Yml,
+ Yrl,
+ 7,
+ Pq,
+ 0xaf,
+ 0,
+ 0,
+ AIMULL,
+ Yml,
+ Yrl,
+ 7,
+ Pm,
+ 0xaf,
+ 0,
+ 0,
+
+ /* load TLS base pointer */
+ AMOVL,
+ Ytls,
+ Yrl,
+ 8,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+}
+
+// byteswapreg returns a byte-addressable register (AX, BX, CX, DX)
+// which is not referenced in a->type.
+// If a is empty, it returns BX to account for MULB-like instructions
+// that might use DX and AX.
+func byteswapreg(ctxt *obj.Link, a *obj.Addr) int {
+
+ var cana int
+ var canb int
+ var canc int
+ var cand int
+
+ cand = 1
+ canc = cand
+ canb = canc
+ cana = canb
+
+ switch a.Type {
+ case D_NONE:
+ cand = 0
+ cana = cand
+
+ case D_AX,
+ D_AL,
+ D_AH,
+ D_INDIR + D_AX:
+ cana = 0
+
+ case D_BX,
+ D_BL,
+ D_BH,
+ D_INDIR + D_BX:
+ canb = 0
+
+ case D_CX,
+ D_CL,
+ D_CH,
+ D_INDIR + D_CX:
+ canc = 0
+
+ case D_DX,
+ D_DL,
+ D_DH,
+ D_INDIR + D_DX:
+ cand = 0
+ break
+ }
+
+ switch a.Index {
+ case D_AX:
+ cana = 0
+
+ case D_BX:
+ canb = 0
+
+ case D_CX:
+ canc = 0
+
+ case D_DX:
+ cand = 0
+ break
+ }
+
+ if cana != 0 {
+ return D_AX
+ }
+ if canb != 0 {
+ return D_BX
+ }
+ if canc != 0 {
+ return D_CX
+ }
+ if cand != 0 {
+ return D_DX
+ }
+
+ ctxt.Diag("impossible byte register")
+ log.Fatalf("bad code")
+ return 0
+}
+
+func subreg(p *obj.Prog, from int, to int) {
+ if false { /* debug['Q'] */
+ fmt.Printf("\n%v\ts/%v/%v/\n", p, Rconv(from), Rconv(to))
+ }
+
+ if int(p.From.Type) == from {
+ p.From.Type = int16(to)
+ p.Ft = 0
+ }
+
+ if int(p.To.Type) == from {
+ p.To.Type = int16(to)
+ p.Tt = 0
+ }
+
+ if int(p.From.Index) == from {
+ p.From.Index = uint8(to)
+ p.Ft = 0
+ }
+
+ if int(p.To.Index) == from {
+ p.To.Index = uint8(to)
+ p.Tt = 0
+ }
+
+ from += D_INDIR
+ if int(p.From.Type) == from {
+ p.From.Type = int16(to + D_INDIR)
+ p.Ft = 0
+ }
+
+ if int(p.To.Type) == from {
+ p.To.Type = int16(to + D_INDIR)
+ p.Tt = 0
+ }
+
+ if false { /* debug['Q'] */
+ fmt.Printf("%v\n", p)
+ }
+}
+
+func mediaop(ctxt *obj.Link, o *Optab, op int, osize int, z int) int {
+ switch op {
+ case Pm,
+ Pe,
+ Pf2,
+ Pf3:
+ if osize != 1 {
+ if op != Pm {
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ ctxt.Andptr[0] = Pm
+ ctxt.Andptr = ctxt.Andptr[1:]
+ z++
+ op = int(o.op[z])
+ break
+ }
+ fallthrough
+
+ default:
+ if -cap(ctxt.Andptr) == -cap(ctxt.And) || ctxt.And[-cap(ctxt.Andptr)+cap(ctxt.And[:])-1] != Pm {
+ ctxt.Andptr[0] = Pm
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ break
+ }
+
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ return z
+}
+
+func doasm(ctxt *obj.Link, p *obj.Prog) {
+ var o *Optab
+ var q *obj.Prog
+ var pp obj.Prog
+ var t []byte
+ var z int
+ var op int
+ var ft int
+ var tt int
+ var breg int
+ var v int32
+ var pre int32
+ var rel obj.Reloc
+ var r *obj.Reloc
+ var a *obj.Addr
+
+ ctxt.Curp = p // TODO
+
+ pre = int32(prefixof(ctxt, &p.From))
+
+ if pre != 0 {
+ ctxt.Andptr[0] = byte(pre)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ pre = int32(prefixof(ctxt, &p.To))
+ if pre != 0 {
+ ctxt.Andptr[0] = byte(pre)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+
+ if p.Ft == 0 {
+ p.Ft = uint8(oclass(&p.From))
+ }
+ if p.Tt == 0 {
+ p.Tt = uint8(oclass(&p.To))
+ }
+
+ ft = int(p.Ft) * Ymax
+ tt = int(p.Tt) * Ymax
+ o = &optab[p.As]
+ t = o.ytab
+ if t == nil {
+ ctxt.Diag("asmins: noproto %v", p)
+ return
+ }
+
+ for z = 0; t[0] != 0; (func() { z += int(t[3]); t = t[4:] })() {
+ if ycover[ft+int(t[0])] != 0 {
+ if ycover[tt+int(t[1])] != 0 {
+ goto found
+ }
+ }
+ }
+ goto domov
+
+found:
+ switch o.prefix {
+ case Pq: /* 16 bit escape and opcode escape */
+ ctxt.Andptr[0] = Pe
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ ctxt.Andptr[0] = Pm
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Pf2, /* xmm opcode escape */
+ Pf3:
+ ctxt.Andptr[0] = byte(o.prefix)
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ ctxt.Andptr[0] = Pm
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Pm: /* opcode escape */
+ ctxt.Andptr[0] = Pm
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Pe: /* 16 bit escape */
+ ctxt.Andptr[0] = Pe
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Pb: /* botch */
+ break
+ }
+
+ op = int(o.op[z])
+ switch t[2] {
+ default:
+ ctxt.Diag("asmins: unknown z %d %v", t[2], p)
+ return
+
+ case Zpseudo:
+ break
+
+ case Zlit:
+ for ; ; z++ {
+ op = int(o.op[z])
+ if !(op != 0) {
+ break
+ }
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+
+ case Zlitm_r:
+ for ; ; z++ {
+ op = int(o.op[z])
+ if !(op != 0) {
+ break
+ }
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ asmand(ctxt, p, &p.From, reg[p.To.Type])
+
+ case Zm_r:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.From, reg[p.To.Type])
+
+ case Zm2_r:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(o.op[z+1])
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.From, reg[p.To.Type])
+
+ case Zm_r_xm:
+ mediaop(ctxt, o, op, int(t[3]), z)
+ asmand(ctxt, p, &p.From, reg[p.To.Type])
+
+ case Zm_r_i_xm:
+ mediaop(ctxt, o, op, int(t[3]), z)
+ asmand(ctxt, p, &p.From, reg[p.To.Type])
+ ctxt.Andptr[0] = byte(p.To.Offset)
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Zibm_r:
+ for {
+ tmp2 := z
+ z++
+ op = int(o.op[tmp2])
+ if !(op != 0) {
+ break
+ }
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ asmand(ctxt, p, &p.From, reg[p.To.Type])
+ ctxt.Andptr[0] = byte(p.To.Offset)
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Zaut_r:
+ ctxt.Andptr[0] = 0x8d
+ ctxt.Andptr = ctxt.Andptr[1:] /* leal */
+ if p.From.Type != D_ADDR {
+ ctxt.Diag("asmins: Zaut sb type ADDR")
+ }
+ p.From.Type = int16(p.From.Index)
+ p.From.Index = D_NONE
+ p.Ft = 0
+ asmand(ctxt, p, &p.From, reg[p.To.Type])
+ p.From.Index = uint8(p.From.Type)
+ p.From.Type = D_ADDR
+ p.Ft = 0
+
+ case Zm_o:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.From, int(o.op[z+1]))
+
+ case Zr_m:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.To, reg[p.From.Type])
+
+ case Zr_m_xm:
+ mediaop(ctxt, o, op, int(t[3]), z)
+ asmand(ctxt, p, &p.To, reg[p.From.Type])
+
+ case Zr_m_i_xm:
+ mediaop(ctxt, o, op, int(t[3]), z)
+ asmand(ctxt, p, &p.To, reg[p.From.Type])
+ ctxt.Andptr[0] = byte(p.From.Offset)
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Zcallindreg:
+ r = obj.Addrel(ctxt.Cursym)
+ r.Off = int32(p.Pc)
+ r.Type = obj.R_CALLIND
+ r.Siz = 0
+ fallthrough
+
+ // fallthrough
+ case Zo_m:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ asmand(ctxt, p, &p.To, int(o.op[z+1]))
+
+ case Zm_ibo:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.From, int(o.op[z+1]))
+ ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.To, nil))
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Zibo_m:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.To, int(o.op[z+1]))
+ ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.From, nil))
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Z_ib,
+ Zib_:
+ if t[2] == Zib_ {
+ a = &p.From
+ } else {
+
+ a = &p.To
+ }
+ v = vaddr(ctxt, p, a, nil)
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Zib_rp:
+ ctxt.Andptr[0] = byte(op + reg[p.To.Type])
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.From, nil))
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Zil_rp:
+ ctxt.Andptr[0] = byte(op + reg[p.To.Type])
+ ctxt.Andptr = ctxt.Andptr[1:]
+ if o.prefix == Pe {
+ v = vaddr(ctxt, p, &p.From, nil)
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 8)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ } else {
+
+ relput4(ctxt, p, &p.From)
+ }
+
+ case Zib_rr:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.To, reg[p.To.Type])
+ ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.From, nil))
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Z_il,
+ Zil_:
+ if t[2] == Zil_ {
+ a = &p.From
+ } else {
+
+ a = &p.To
+ }
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ if o.prefix == Pe {
+ v = vaddr(ctxt, p, a, nil)
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 8)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ } else {
+
+ relput4(ctxt, p, a)
+ }
+
+ case Zm_ilo,
+ Zilo_m:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ if t[2] == Zilo_m {
+ a = &p.From
+ asmand(ctxt, p, &p.To, int(o.op[z+1]))
+ } else {
+
+ a = &p.To
+ asmand(ctxt, p, &p.From, int(o.op[z+1]))
+ }
+
+ if o.prefix == Pe {
+ v = vaddr(ctxt, p, a, nil)
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 8)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ } else {
+
+ relput4(ctxt, p, a)
+ }
+
+ case Zil_rr:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.To, reg[p.To.Type])
+ if o.prefix == Pe {
+ v = vaddr(ctxt, p, &p.From, nil)
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 8)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ } else {
+
+ relput4(ctxt, p, &p.From)
+ }
+
+ case Z_rp:
+ ctxt.Andptr[0] = byte(op + reg[p.To.Type])
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Zrp_:
+ ctxt.Andptr[0] = byte(op + reg[p.From.Type])
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Zclr:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.To, reg[p.To.Type])
+
+ case Zcall:
+ if p.To.Sym == nil {
+ ctxt.Diag("call without target")
+ log.Fatalf("bad code")
+ }
+
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ r = obj.Addrel(ctxt.Cursym)
+ r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+ r.Type = obj.R_CALL
+ r.Siz = 4
+ r.Sym = p.To.Sym
+ r.Add = p.To.Offset
+ put4(ctxt, 0)
+
+ case Zbr,
+ Zjmp,
+ Zloop:
+ if p.To.Sym != nil {
+ if t[2] != Zjmp {
+ ctxt.Diag("branch to ATEXT")
+ log.Fatalf("bad code")
+ }
+
+ ctxt.Andptr[0] = byte(o.op[z+1])
+ ctxt.Andptr = ctxt.Andptr[1:]
+ r = obj.Addrel(ctxt.Cursym)
+ r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+ r.Sym = p.To.Sym
+ r.Type = obj.R_PCREL
+ r.Siz = 4
+ put4(ctxt, 0)
+ break
+ }
+
+ // Assumes q is in this function.
+ // Fill in backward jump now.
+ q = p.Pcond
+
+ if q == nil {
+ ctxt.Diag("jmp/branch/loop without target")
+ log.Fatalf("bad code")
+ }
+
+ if p.Back&1 != 0 {
+ v = int32(q.Pc - (p.Pc + 2))
+ if v >= -128 {
+ if p.As == AJCXZW {
+ ctxt.Andptr[0] = 0x67
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ } else if t[2] == Zloop {
+ ctxt.Diag("loop too far: %v", p)
+ } else {
+
+ v -= 5 - 2
+ if t[2] == Zbr {
+ ctxt.Andptr[0] = 0x0f
+ ctxt.Andptr = ctxt.Andptr[1:]
+ v--
+ }
+
+ ctxt.Andptr[0] = byte(o.op[z+1])
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 8)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 16)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 24)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+
+ break
+ }
+
+ // Annotate target; will fill in later.
+ p.Forwd = q.Comefrom
+
+ q.Comefrom = p
+ if p.Back&2 != 0 { // short
+ if p.As == AJCXZW {
+ ctxt.Andptr[0] = 0x67
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0
+ ctxt.Andptr = ctxt.Andptr[1:]
+ } else if t[2] == Zloop {
+ ctxt.Diag("loop too far: %v", p)
+ } else {
+
+ if t[2] == Zbr {
+ ctxt.Andptr[0] = 0x0f
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ ctxt.Andptr[0] = byte(o.op[z+1])
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+
+ case Zcallcon,
+ Zjmpcon:
+ if t[2] == Zcallcon {
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ } else {
+
+ ctxt.Andptr[0] = byte(o.op[z+1])
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ r = obj.Addrel(ctxt.Cursym)
+ r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+ r.Type = obj.R_PCREL
+ r.Siz = 4
+ r.Add = p.To.Offset
+ put4(ctxt, 0)
+
+ case Zcallind:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(o.op[z+1])
+ ctxt.Andptr = ctxt.Andptr[1:]
+ r = obj.Addrel(ctxt.Cursym)
+ r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+ r.Type = obj.R_ADDR
+ r.Siz = 4
+ r.Add = p.To.Offset
+ r.Sym = p.To.Sym
+ put4(ctxt, 0)
+
+ case Zbyte:
+ v = vaddr(ctxt, p, &p.From, &rel)
+ if rel.Siz != 0 {
+ rel.Siz = uint8(op)
+ r = obj.Addrel(ctxt.Cursym)
+ *r = rel
+ r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+ }
+
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ if op > 1 {
+ ctxt.Andptr[0] = byte(v >> 8)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ if op > 2 {
+ ctxt.Andptr[0] = byte(v >> 16)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 24)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ }
+
+ case Zmov:
+ goto domov
+ }
+
+ return
+
+domov:
+ for t = []byte(ymovtab); t[0] != 0; t = t[8:] {
+ if p.As == int16(t[0]) {
+ if ycover[ft+int(t[1])] != 0 {
+ if ycover[tt+int(t[2])] != 0 {
+ goto mfound
+ }
+ }
+ }
+ }
+
+ /*
+ * here, the assembly has failed.
+ * if its a byte instruction that has
+ * unaddressable registers, try to
+ * exchange registers and reissue the
+ * instruction with the operands renamed.
+ */
+bad:
+ pp = *p
+
+ z = int(p.From.Type)
+ if z >= D_BP && z <= D_DI {
+ breg = byteswapreg(ctxt, &p.To)
+ if breg != D_AX {
+ ctxt.Andptr[0] = 0x87
+ ctxt.Andptr = ctxt.Andptr[1:] /* xchg lhs,bx */
+ asmand(ctxt, p, &p.From, reg[breg])
+ subreg(&pp, z, breg)
+ doasm(ctxt, &pp)
+ ctxt.Andptr[0] = 0x87
+ ctxt.Andptr = ctxt.Andptr[1:] /* xchg lhs,bx */
+ asmand(ctxt, p, &p.From, reg[breg])
+ } else {
+
+ ctxt.Andptr[0] = byte(0x90 + reg[z])
+ ctxt.Andptr = ctxt.Andptr[1:] /* xchg lsh,ax */
+ subreg(&pp, z, D_AX)
+ doasm(ctxt, &pp)
+ ctxt.Andptr[0] = byte(0x90 + reg[z])
+ ctxt.Andptr = ctxt.Andptr[1:] /* xchg lsh,ax */
+ }
+
+ return
+ }
+
+ z = int(p.To.Type)
+ if z >= D_BP && z <= D_DI {
+ breg = byteswapreg(ctxt, &p.From)
+ if breg != D_AX {
+ ctxt.Andptr[0] = 0x87
+ ctxt.Andptr = ctxt.Andptr[1:] /* xchg rhs,bx */
+ asmand(ctxt, p, &p.To, reg[breg])
+ subreg(&pp, z, breg)
+ doasm(ctxt, &pp)
+ ctxt.Andptr[0] = 0x87
+ ctxt.Andptr = ctxt.Andptr[1:] /* xchg rhs,bx */
+ asmand(ctxt, p, &p.To, reg[breg])
+ } else {
+
+ ctxt.Andptr[0] = byte(0x90 + reg[z])
+ ctxt.Andptr = ctxt.Andptr[1:] /* xchg rsh,ax */
+ subreg(&pp, z, D_AX)
+ doasm(ctxt, &pp)
+ ctxt.Andptr[0] = byte(0x90 + reg[z])
+ ctxt.Andptr = ctxt.Andptr[1:] /* xchg rsh,ax */
+ }
+
+ return
+ }
+
+ ctxt.Diag("doasm: notfound t2=%x from=%x to=%x %v", t[2], uint16(p.From.Type), uint16(p.To.Type), p)
+ return
+
+mfound:
+ switch t[3] {
+ default:
+ ctxt.Diag("asmins: unknown mov %d %v", t[3], p)
+
+ case 0: /* lit */
+ for z = 4; t[z] != E; z++ {
+
+ ctxt.Andptr[0] = t[z]
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+
+ case 1: /* r,m */
+ ctxt.Andptr[0] = t[4]
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ asmand(ctxt, p, &p.To, int(t[5]))
+
+ case 2: /* m,r */
+ ctxt.Andptr[0] = t[4]
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ asmand(ctxt, p, &p.From, int(t[5]))
+
+ case 3: /* r,m - 2op */
+ ctxt.Andptr[0] = t[4]
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ ctxt.Andptr[0] = t[5]
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.To, int(t[6]))
+
+ case 4: /* m,r - 2op */
+ ctxt.Andptr[0] = t[4]
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ ctxt.Andptr[0] = t[5]
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.From, int(t[6]))
+
+ case 5: /* load full pointer, trash heap */
+ if t[4] != 0 {
+
+ ctxt.Andptr[0] = t[4]
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ switch p.To.Index {
+ default:
+ goto bad
+
+ case D_DS:
+ ctxt.Andptr[0] = 0xc5
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case D_SS:
+ ctxt.Andptr[0] = 0x0f
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0xb2
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case D_ES:
+ ctxt.Andptr[0] = 0xc4
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case D_FS:
+ ctxt.Andptr[0] = 0x0f
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0xb4
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case D_GS:
+ ctxt.Andptr[0] = 0x0f
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0xb5
+ ctxt.Andptr = ctxt.Andptr[1:]
+ break
+ }
+
+ asmand(ctxt, p, &p.From, reg[p.To.Type])
+
+ case 6: /* double shift */
+ z = int(p.From.Type)
+
+ switch z {
+ default:
+ goto bad
+
+ case D_CONST:
+ ctxt.Andptr[0] = 0x0f
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = t[4]
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.To, reg[p.From.Index])
+ ctxt.Andptr[0] = byte(p.From.Offset)
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case D_CL,
+ D_CX:
+ ctxt.Andptr[0] = 0x0f
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = t[5]
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.To, reg[p.From.Index])
+ break
+ }
+
+ case 7: /* imul rm,r */
+ if t[4] == Pq {
+
+ ctxt.Andptr[0] = Pe
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = Pm
+ ctxt.Andptr = ctxt.Andptr[1:]
+ } else {
+
+ ctxt.Andptr[0] = t[4]
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ ctxt.Andptr[0] = t[5]
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.From, reg[p.To.Type])
+
+ // NOTE: The systems listed here are the ones that use the "TLS initial exec" model,
+ // where you load the TLS base register into a register and then index off that
+ // register to access the actual TLS variables. Systems that allow direct TLS access
+ // are handled in prefixof above and should not be listed here.
+ case 8: /* mov tls, r */
+ switch ctxt.Headtype {
+
+ default:
+ log.Fatalf("unknown TLS base location for %s", obj.Headstr(ctxt.Headtype))
+
+ // ELF TLS base is 0(GS).
+ case obj.Hlinux,
+ obj.Hnacl:
+ pp.From = p.From
+
+ pp.From.Type = D_INDIR + D_GS
+ pp.From.Offset = 0
+ pp.From.Index = D_NONE
+ pp.From.Scale = 0
+ ctxt.Andptr[0] = 0x65
+ ctxt.Andptr = ctxt.Andptr[1:] // GS
+ ctxt.Andptr[0] = 0x8B
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &pp.From, reg[p.To.Type])
+
+ case obj.Hplan9:
+ if ctxt.Plan9privates == nil {
+ ctxt.Plan9privates = obj.Linklookup(ctxt, "_privates", 0)
+ }
+ pp.From = obj.Addr{}
+ pp.From.Type = D_EXTERN
+ pp.From.Sym = ctxt.Plan9privates
+ pp.From.Offset = 0
+ pp.From.Index = D_NONE
+ ctxt.Andptr[0] = 0x8B
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &pp.From, reg[p.To.Type])
+
+ // Windows TLS base is always 0x14(FS).
+ case obj.Hwindows:
+ pp.From = p.From
+
+ pp.From.Type = D_INDIR + D_FS
+ pp.From.Offset = 0x14
+ pp.From.Index = D_NONE
+ pp.From.Scale = 0
+ ctxt.Andptr[0] = 0x64
+ ctxt.Andptr = ctxt.Andptr[1:] // FS
+ ctxt.Andptr[0] = 0x8B
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &pp.From, reg[p.To.Type])
+ break
+ }
+
+ break
+ }
+}
+
+var naclret = []uint8{
+ 0x5d, // POPL BP
+ // 0x8b, 0x7d, 0x00, // MOVL (BP), DI - catch return to invalid address, for debugging
+ 0x83,
+ 0xe5,
+ 0xe0, // ANDL $~31, BP
+ 0xff,
+ 0xe5, // JMP BP
+}
+
+func asmins(ctxt *obj.Link, p *obj.Prog) {
+ var r *obj.Reloc
+
+ ctxt.Andptr = ctxt.And[:]
+
+ if p.As == AUSEFIELD {
+ r = obj.Addrel(ctxt.Cursym)
+ r.Off = 0
+ r.Sym = p.From.Sym
+ r.Type = obj.R_USEFIELD
+ r.Siz = 0
+ return
+ }
+
+ if ctxt.Headtype == obj.Hnacl {
+ switch p.As {
+ case ARET:
+ copy(ctxt.Andptr, naclret)
+ ctxt.Andptr = ctxt.Andptr[len(naclret):]
+ return
+
+ case ACALL,
+ AJMP:
+ if D_AX <= p.To.Type && p.To.Type <= D_DI {
+ ctxt.Andptr[0] = 0x83
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(0xe0 | (p.To.Type - D_AX))
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0xe0
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+
+ case AINT:
+ ctxt.Andptr[0] = 0xf4
+ ctxt.Andptr = ctxt.Andptr[1:]
+ return
+ }
+ }
+
+ doasm(ctxt, p)
+ if -cap(ctxt.Andptr) > -cap(ctxt.And[len(ctxt.And):]) {
+ fmt.Printf("and[] is too short - %d byte instruction\n", -cap(ctxt.Andptr)+cap(ctxt.And[:]))
+ log.Fatalf("bad code")
+ }
+}
--- /dev/null
+// Inferno utils/8c/list.c
+// http://code.google.com/p/inferno-os/source/browse/utils/8c/list.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package i386
+
+import (
+ "cmd/internal/obj"
+ "fmt"
+)
+
+const (
+ STRINGSZ = 1000
+)
+
+var bigP *obj.Prog
+
+func Pconv(p *obj.Prog) string {
+ var str string
+ var fp string
+
+ switch p.As {
+ case ADATA:
+ str = fmt.Sprintf("%.5d (%v)\t%v\t%v/%d,%v", p.Pc, p.Line(), Aconv(int(p.As)), Dconv(p, 0, &p.From), p.From.Scale, Dconv(p, 0, &p.To))
+
+ case ATEXT:
+ if p.From.Scale != 0 {
+ str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%d,%v", p.Pc, p.Line(), Aconv(int(p.As)), Dconv(p, 0, &p.From), p.From.Scale, Dconv(p, fmtLong, &p.To))
+ break
+ }
+
+ str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%v", p.Pc, p.Line(), Aconv(int(p.As)), Dconv(p, 0, &p.From), Dconv(p, fmtLong, &p.To))
+
+ default:
+ str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%v", p.Pc, p.Line(), Aconv(int(p.As)), Dconv(p, 0, &p.From), Dconv(p, 0, &p.To))
+ break
+ }
+
+ fp += str
+ return fp
+}
+
+func Aconv(i int) string {
+ var fp string
+
+ fp += Anames[i]
+ return fp
+}
+
+func Dconv(p *obj.Prog, flag int, a *obj.Addr) string {
+ var str string
+ var s string
+ var fp string
+
+ var i int
+
+ i = int(a.Type)
+
+ if flag&fmtLong != 0 /*untyped*/ {
+ if i == D_CONST2 {
+ str = fmt.Sprintf("$%d-%d", a.Offset, a.Offset2)
+ } else {
+
+ // ATEXT dst is not constant
+ str = fmt.Sprintf("!!%v", Dconv(p, 0, a))
+ }
+
+ goto brk
+ }
+
+ if i >= D_INDIR {
+ if a.Offset != 0 {
+ str = fmt.Sprintf("%d(%v)", a.Offset, Rconv(i-D_INDIR))
+ } else {
+
+ str = fmt.Sprintf("(%v)", Rconv(i-D_INDIR))
+ }
+ goto brk
+ }
+
+ switch i {
+ default:
+ if a.Offset != 0 {
+ str = fmt.Sprintf("$%d,%v", a.Offset, Rconv(i))
+ } else {
+
+ str = fmt.Sprintf("%v", Rconv(i))
+ }
+
+ case D_NONE:
+ str = ""
+
+ case D_BRANCH:
+ if a.Sym != nil {
+ str = fmt.Sprintf("%s(SB)", a.Sym.Name)
+ } else if p != nil && p.Pcond != nil {
+ str = fmt.Sprintf("%d", p.Pcond.Pc)
+ } else if a.U.Branch != nil {
+ str = fmt.Sprintf("%d", a.U.Branch.Pc)
+ } else {
+
+ str = fmt.Sprintf("%d(PC)", a.Offset)
+ }
+
+ case D_EXTERN:
+ str = fmt.Sprintf("%s+%d(SB)", a.Sym.Name, a.Offset)
+
+ case D_STATIC:
+ str = fmt.Sprintf("%s<>+%d(SB)", a.Sym.Name, a.Offset)
+
+ case D_AUTO:
+ if a.Sym != nil {
+ str = fmt.Sprintf("%s+%d(SP)", a.Sym.Name, a.Offset)
+ } else {
+
+ str = fmt.Sprintf("%d(SP)", a.Offset)
+ }
+
+ case D_PARAM:
+ if a.Sym != nil {
+ str = fmt.Sprintf("%s+%d(FP)", a.Sym.Name, a.Offset)
+ } else {
+
+ str = fmt.Sprintf("%d(FP)", a.Offset)
+ }
+
+ case D_CONST:
+ str = fmt.Sprintf("$%d", a.Offset)
+
+ case D_CONST2:
+ if !(flag&fmtLong != 0 /*untyped*/) {
+ // D_CONST2 outside of ATEXT should not happen
+ str = fmt.Sprintf("!!$%d-%d", a.Offset, a.Offset2)
+ }
+
+ case D_FCONST:
+ str = fmt.Sprintf("$(%.17g)", a.U.Dval)
+
+ case D_SCONST:
+ str = fmt.Sprintf("$\"%q\"", a.U.Sval)
+
+ case D_ADDR:
+ a.Type = int16(a.Index)
+ a.Index = D_NONE
+ str = fmt.Sprintf("$%v", Dconv(p, 0, a))
+ a.Index = uint8(a.Type)
+ a.Type = D_ADDR
+ goto conv
+ }
+
+brk:
+ if a.Index != D_NONE {
+ s = fmt.Sprintf("(%v*%d)", Rconv(int(a.Index)), int(a.Scale))
+ str += s
+ }
+
+conv:
+ fp += str
+ return fp
+}
+
+var Register = []string{
+ "AL", /* [D_AL] */
+ "CL",
+ "DL",
+ "BL",
+ "AH",
+ "CH",
+ "DH",
+ "BH",
+ "AX", /* [D_AX] */
+ "CX",
+ "DX",
+ "BX",
+ "SP",
+ "BP",
+ "SI",
+ "DI",
+ "F0", /* [D_F0] */
+ "F1",
+ "F2",
+ "F3",
+ "F4",
+ "F5",
+ "F6",
+ "F7",
+ "CS", /* [D_CS] */
+ "SS",
+ "DS",
+ "ES",
+ "FS",
+ "GS",
+ "GDTR", /* [D_GDTR] */
+ "IDTR", /* [D_IDTR] */
+ "LDTR", /* [D_LDTR] */
+ "MSW", /* [D_MSW] */
+ "TASK", /* [D_TASK] */
+ "CR0", /* [D_CR] */
+ "CR1",
+ "CR2",
+ "CR3",
+ "CR4",
+ "CR5",
+ "CR6",
+ "CR7",
+ "DR0", /* [D_DR] */
+ "DR1",
+ "DR2",
+ "DR3",
+ "DR4",
+ "DR5",
+ "DR6",
+ "DR7",
+ "TR0", /* [D_TR] */
+ "TR1",
+ "TR2",
+ "TR3",
+ "TR4",
+ "TR5",
+ "TR6",
+ "TR7",
+ "X0", /* [D_X0] */
+ "X1",
+ "X2",
+ "X3",
+ "X4",
+ "X5",
+ "X6",
+ "X7",
+ "TLS", /* [D_TLS] */
+ "NONE", /* [D_NONE] */
+}
+
+func Rconv(r int) string {
+ var str string
+ var fp string
+
+ if r >= D_AL && r <= D_NONE {
+ str = fmt.Sprintf("%s", Register[r-D_AL])
+ } else {
+
+ str = fmt.Sprintf("gok(%d)", r)
+ }
+
+ fp += str
+ return fp
+}
--- /dev/null
+// Inferno utils/8l/pass.c
+// http://code.google.com/p/inferno-os/source/browse/utils/8l/pass.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package i386
+
+import (
+ "cmd/internal/obj"
+ "encoding/binary"
+ "fmt"
+ "log"
+ "math"
+)
+
+var zprg = obj.Prog{
+ Back: 2,
+ As: AGOK,
+ From: obj.Addr{
+ Type: D_NONE,
+ Index: D_NONE,
+ Scale: 1,
+ },
+ To: obj.Addr{
+ Type: D_NONE,
+ Index: D_NONE,
+ Scale: 1,
+ },
+}
+
+func symtype(a *obj.Addr) int {
+ var t int
+
+ t = int(a.Type)
+ if t == D_ADDR {
+ t = int(a.Index)
+ }
+ return t
+}
+
+func isdata(p *obj.Prog) bool {
+ return p.As == ADATA || p.As == AGLOBL
+}
+
+func iscall(p *obj.Prog) bool {
+ return p.As == ACALL
+}
+
+func datasize(p *obj.Prog) int {
+ return int(p.From.Scale)
+}
+
+func textflag(p *obj.Prog) int {
+ return int(p.From.Scale)
+}
+
+func settextflag(p *obj.Prog, f int) {
+ p.From.Scale = int8(f)
+}
+
+func canuselocaltls(ctxt *obj.Link) int {
+ switch ctxt.Headtype {
+ case obj.Hlinux,
+ obj.Hnacl,
+ obj.Hplan9,
+ obj.Hwindows:
+ return 0
+ }
+
+ return 1
+}
+
+func progedit(ctxt *obj.Link, p *obj.Prog) {
+ var literal string
+ var s *obj.LSym
+ var q *obj.Prog
+
+ // See obj6.c for discussion of TLS.
+ if canuselocaltls(ctxt) != 0 {
+
+ // Reduce TLS initial exec model to TLS local exec model.
+ // Sequences like
+ // MOVL TLS, BX
+ // ... off(BX)(TLS*1) ...
+ // become
+ // NOP
+ // ... off(TLS) ...
+ if p.As == AMOVL && p.From.Type == D_TLS && D_AX <= p.To.Type && p.To.Type <= D_DI {
+
+ p.As = ANOP
+ p.From.Type = D_NONE
+ p.To.Type = D_NONE
+ }
+
+ if p.From.Index == D_TLS && D_INDIR+D_AX <= p.From.Type && p.From.Type <= D_INDIR+D_DI {
+ p.From.Type = D_INDIR + D_TLS
+ p.From.Scale = 0
+ p.From.Index = D_NONE
+ }
+
+ if p.To.Index == D_TLS && D_INDIR+D_AX <= p.To.Type && p.To.Type <= D_INDIR+D_DI {
+ p.To.Type = D_INDIR + D_TLS
+ p.To.Scale = 0
+ p.To.Index = D_NONE
+ }
+ } else {
+
+ // As a courtesy to the C compilers, rewrite TLS local exec load as TLS initial exec load.
+ // The instruction
+ // MOVL off(TLS), BX
+ // becomes the sequence
+ // MOVL TLS, BX
+ // MOVL off(BX)(TLS*1), BX
+ // This allows the C compilers to emit references to m and g using the direct off(TLS) form.
+ if p.As == AMOVL && p.From.Type == D_INDIR+D_TLS && D_AX <= p.To.Type && p.To.Type <= D_DI {
+
+ q = obj.Appendp(ctxt, p)
+ q.As = p.As
+ q.From = p.From
+ q.From.Type = D_INDIR + p.To.Type
+ q.From.Index = D_TLS
+ q.From.Scale = 2 // TODO: use 1
+ q.To = p.To
+ p.From.Type = D_TLS
+ p.From.Index = D_NONE
+ p.From.Offset = 0
+ }
+ }
+
+ // TODO: Remove.
+ if ctxt.Headtype == obj.Hplan9 {
+
+ if p.From.Scale == 1 && p.From.Index == D_TLS {
+ p.From.Scale = 2
+ }
+ if p.To.Scale == 1 && p.To.Index == D_TLS {
+ p.To.Scale = 2
+ }
+ }
+
+ // Rewrite CALL/JMP/RET to symbol as D_BRANCH.
+ switch p.As {
+
+ case ACALL,
+ AJMP,
+ ARET:
+ if (p.To.Type == D_EXTERN || p.To.Type == D_STATIC) && p.To.Sym != nil {
+ p.To.Type = D_BRANCH
+ }
+ break
+ }
+
+ // Rewrite float constants to values stored in memory.
+ switch p.As {
+
+ // Convert AMOVSS $(0), Xx to AXORPS Xx, Xx
+ case AMOVSS:
+ if p.From.Type == D_FCONST {
+
+ if p.From.U.Dval == 0 {
+ if p.To.Type >= D_X0 {
+ if p.To.Type <= D_X7 {
+ p.As = AXORPS
+ p.From.Type = p.To.Type
+ p.From.Index = p.To.Index
+ break
+ }
+ }
+ }
+ }
+ fallthrough
+
+ // fallthrough
+
+ case AFMOVF,
+ AFADDF,
+ AFSUBF,
+ AFSUBRF,
+ AFMULF,
+ AFDIVF,
+ AFDIVRF,
+ AFCOMF,
+ AFCOMFP,
+ AADDSS,
+ ASUBSS,
+ AMULSS,
+ ADIVSS,
+ ACOMISS,
+ AUCOMISS:
+ if p.From.Type == D_FCONST {
+
+ var i32 uint32
+ var f32 float32
+ f32 = float32(p.From.U.Dval)
+ i32 = math.Float32bits(f32)
+ literal = fmt.Sprintf("$f32.%08x", i32)
+ s = obj.Linklookup(ctxt, literal, 0)
+ if s.Type == 0 {
+ s.Type = obj.SRODATA
+ obj.Adduint32(ctxt, s, i32)
+ s.Reachable = 0
+ }
+
+ p.From.Type = D_EXTERN
+ p.From.Sym = s
+ p.From.Offset = 0
+ }
+
+ // Convert AMOVSD $(0), Xx to AXORPS Xx, Xx
+ case AMOVSD:
+ if p.From.Type == D_FCONST {
+
+ if p.From.U.Dval == 0 {
+ if p.To.Type >= D_X0 {
+ if p.To.Type <= D_X7 {
+ p.As = AXORPS
+ p.From.Type = p.To.Type
+ p.From.Index = p.To.Index
+ break
+ }
+ }
+ }
+ }
+ fallthrough
+
+ // fallthrough
+
+ case AFMOVD,
+ AFADDD,
+ AFSUBD,
+ AFSUBRD,
+ AFMULD,
+ AFDIVD,
+ AFDIVRD,
+ AFCOMD,
+ AFCOMDP,
+ AADDSD,
+ ASUBSD,
+ AMULSD,
+ ADIVSD,
+ ACOMISD,
+ AUCOMISD:
+ if p.From.Type == D_FCONST {
+
+ var i64 uint64
+ i64 = math.Float64bits(p.From.U.Dval)
+ literal = fmt.Sprintf("$f64.%016x", i64)
+ s = obj.Linklookup(ctxt, literal, 0)
+ if s.Type == 0 {
+ s.Type = obj.SRODATA
+ obj.Adduint64(ctxt, s, i64)
+ s.Reachable = 0
+ }
+
+ p.From.Type = D_EXTERN
+ p.From.Sym = s
+ p.From.Offset = 0
+ }
+
+ break
+ }
+}
+
+func prg() *obj.Prog {
+ p := zprg
+ return &p
+}
+
+func addstacksplit(ctxt *obj.Link, cursym *obj.LSym) {
+ var p *obj.Prog
+ var q *obj.Prog
+ var p1 *obj.Prog
+ var p2 *obj.Prog
+ var autoffset int32
+ var deltasp int32
+ var a int
+
+ if ctxt.Symmorestack[0] == nil {
+ ctxt.Symmorestack[0] = obj.Linklookup(ctxt, "runtime.morestack", 0)
+ ctxt.Symmorestack[1] = obj.Linklookup(ctxt, "runtime.morestack_noctxt", 0)
+ }
+
+ if ctxt.Headtype == obj.Hplan9 && ctxt.Plan9privates == nil {
+ ctxt.Plan9privates = obj.Linklookup(ctxt, "_privates", 0)
+ }
+
+ ctxt.Cursym = cursym
+
+ if cursym.Text == nil || cursym.Text.Link == nil {
+ return
+ }
+
+ p = cursym.Text
+ autoffset = int32(p.To.Offset)
+ if autoffset < 0 {
+ autoffset = 0
+ }
+
+ cursym.Locals = autoffset
+ cursym.Args = p.To.Offset2
+
+ q = nil
+
+ if !(p.From.Scale&obj.NOSPLIT != 0) || (p.From.Scale&obj.WRAPPER != 0) {
+ p = obj.Appendp(ctxt, p)
+ p = load_g_cx(ctxt, p) // load g into CX
+ }
+
+ if !(cursym.Text.From.Scale&obj.NOSPLIT != 0) {
+ p = stacksplit(ctxt, p, autoffset, bool2int(!(cursym.Text.From.Scale&obj.NEEDCTXT != 0)), &q) // emit split check
+ }
+
+ if autoffset != 0 {
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AADJSP
+ p.From.Type = D_CONST
+ p.From.Offset = int64(autoffset)
+ p.Spadj = autoffset
+ } else {
+
+ // zero-byte stack adjustment.
+ // Insert a fake non-zero adjustment so that stkcheck can
+ // recognize the end of the stack-splitting prolog.
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ANOP
+ p.Spadj = int32(-ctxt.Arch.Ptrsize)
+ p = obj.Appendp(ctxt, p)
+ p.As = ANOP
+ p.Spadj = int32(ctxt.Arch.Ptrsize)
+ }
+
+ if q != nil {
+ q.Pcond = p
+ }
+ deltasp = autoffset
+
+ if cursym.Text.From.Scale&obj.WRAPPER != 0 {
+ // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
+ //
+ // MOVL g_panic(CX), BX
+ // TESTL BX, BX
+ // JEQ end
+ // LEAL (autoffset+4)(SP), DI
+ // CMPL panic_argp(BX), DI
+ // JNE end
+ // MOVL SP, panic_argp(BX)
+ // end:
+ // NOP
+ //
+ // The NOP is needed to give the jumps somewhere to land.
+ // It is a liblink NOP, not an x86 NOP: it encodes to 0 instruction bytes.
+
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AMOVL
+ p.From.Type = D_INDIR + D_CX
+ p.From.Offset = 4 * int64(ctxt.Arch.Ptrsize) // G.panic
+ p.To.Type = D_BX
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ATESTL
+ p.From.Type = D_BX
+ p.To.Type = D_BX
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AJEQ
+ p.To.Type = D_BRANCH
+ p1 = p
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ALEAL
+ p.From.Type = D_INDIR + D_SP
+ p.From.Offset = int64(autoffset) + 4
+ p.To.Type = D_DI
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ACMPL
+ p.From.Type = D_INDIR + D_BX
+ p.From.Offset = 0 // Panic.argp
+ p.To.Type = D_DI
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AJNE
+ p.To.Type = D_BRANCH
+ p2 = p
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AMOVL
+ p.From.Type = D_SP
+ p.To.Type = D_INDIR + D_BX
+ p.To.Offset = 0 // Panic.argp
+
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ANOP
+ p1.Pcond = p
+ p2.Pcond = p
+ }
+
+ if ctxt.Debugzerostack != 0 && autoffset != 0 && !(cursym.Text.From.Scale&obj.NOSPLIT != 0) {
+ // 8l -Z means zero the stack frame on entry.
+ // This slows down function calls but can help avoid
+ // false positives in garbage collection.
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AMOVL
+ p.From.Type = D_SP
+ p.To.Type = D_DI
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AMOVL
+ p.From.Type = D_CONST
+ p.From.Offset = int64(autoffset) / 4
+ p.To.Type = D_CX
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AMOVL
+ p.From.Type = D_CONST
+ p.From.Offset = 0
+ p.To.Type = D_AX
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AREP
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ASTOSL
+ }
+
+ for ; p != nil; p = p.Link {
+ a = int(p.From.Type)
+ if a == D_AUTO {
+ p.From.Offset += int64(deltasp)
+ }
+ if a == D_PARAM {
+ p.From.Offset += int64(deltasp) + 4
+ }
+ a = int(p.To.Type)
+ if a == D_AUTO {
+ p.To.Offset += int64(deltasp)
+ }
+ if a == D_PARAM {
+ p.To.Offset += int64(deltasp) + 4
+ }
+
+ switch p.As {
+ default:
+ continue
+
+ case APUSHL,
+ APUSHFL:
+ deltasp += 4
+ p.Spadj = 4
+ continue
+
+ case APUSHW,
+ APUSHFW:
+ deltasp += 2
+ p.Spadj = 2
+ continue
+
+ case APOPL,
+ APOPFL:
+ deltasp -= 4
+ p.Spadj = -4
+ continue
+
+ case APOPW,
+ APOPFW:
+ deltasp -= 2
+ p.Spadj = -2
+ continue
+
+ case ARET:
+ break
+ }
+
+ if autoffset != deltasp {
+ ctxt.Diag("unbalanced PUSH/POP")
+ }
+
+ if autoffset != 0 {
+ p.As = AADJSP
+ p.From.Type = D_CONST
+ p.From.Offset = int64(-autoffset)
+ p.Spadj = -autoffset
+ p = obj.Appendp(ctxt, p)
+ p.As = ARET
+
+ // If there are instructions following
+ // this ARET, they come from a branch
+ // with the same stackframe, so undo
+ // the cleanup.
+ p.Spadj = +autoffset
+ }
+
+ if p.To.Sym != nil { // retjmp
+ p.As = AJMP
+ }
+ }
+}
+
+// Append code to p to load g into cx.
+// Overwrites p with the first instruction (no first appendp).
+// Overwriting p is unusual but it lets use this in both the
+// prologue (caller must call appendp first) and in the epilogue.
+// Returns last new instruction.
+func load_g_cx(ctxt *obj.Link, p *obj.Prog) *obj.Prog {
+
+ var next *obj.Prog
+
+ p.As = AMOVL
+ p.From.Type = D_INDIR + D_TLS
+ p.From.Offset = 0
+ p.To.Type = D_CX
+
+ next = p.Link
+ progedit(ctxt, p)
+ for p.Link != next {
+ p = p.Link
+ }
+
+ if p.From.Index == D_TLS {
+ p.From.Scale = 2
+ }
+
+ return p
+}
+
+// Append code to p to check for stack split.
+// Appends to (does not overwrite) p.
+// Assumes g is in CX.
+// Returns last new instruction.
+// On return, *jmpok is the instruction that should jump
+// to the stack frame allocation if no split is needed.
+func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32, noctxt int, jmpok **obj.Prog) *obj.Prog {
+
+ var q *obj.Prog
+ var q1 *obj.Prog
+
+ if ctxt.Debugstack != 0 {
+ // 8l -K means check not only for stack
+ // overflow but stack underflow.
+ // On underflow, INT 3 (breakpoint).
+ // Underflow itself is rare but this also
+ // catches out-of-sync stack guard info.
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ACMPL
+ p.From.Type = D_INDIR + D_CX
+ p.From.Offset = 4
+ p.To.Type = D_SP
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AJCC
+ p.To.Type = D_BRANCH
+ p.To.Offset = 4
+ q1 = p
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AINT
+ p.From.Type = D_CONST
+ p.From.Offset = 3
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ANOP
+ q1.Pcond = p
+ }
+
+ q1 = nil
+
+ if framesize <= obj.StackSmall {
+ // small stack: SP <= stackguard
+ // CMPL SP, stackguard
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ACMPL
+ p.From.Type = D_SP
+ p.To.Type = D_INDIR + D_CX
+ p.To.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
+ if ctxt.Cursym.Cfunc != 0 {
+ p.To.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
+ }
+ } else if framesize <= obj.StackBig {
+ // large stack: SP-framesize <= stackguard-StackSmall
+ // LEAL -(framesize-StackSmall)(SP), AX
+ // CMPL AX, stackguard
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ALEAL
+ p.From.Type = D_INDIR + D_SP
+ p.From.Offset = -(int64(framesize) - obj.StackSmall)
+ p.To.Type = D_AX
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ACMPL
+ p.From.Type = D_AX
+ p.To.Type = D_INDIR + D_CX
+ p.To.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
+ if ctxt.Cursym.Cfunc != 0 {
+ p.To.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
+ }
+ } else {
+
+ // Such a large stack we need to protect against wraparound
+ // if SP is close to zero.
+ // SP-stackguard+StackGuard <= framesize + (StackGuard-StackSmall)
+ // The +StackGuard on both sides is required to keep the left side positive:
+ // SP is allowed to be slightly below stackguard. See stack.h.
+ //
+ // Preemption sets stackguard to StackPreempt, a very large value.
+ // That breaks the math above, so we have to check for that explicitly.
+ // MOVL stackguard, CX
+ // CMPL CX, $StackPreempt
+ // JEQ label-of-call-to-morestack
+ // LEAL StackGuard(SP), AX
+ // SUBL stackguard, AX
+ // CMPL AX, $(framesize+(StackGuard-StackSmall))
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AMOVL
+ p.From.Type = D_INDIR + D_CX
+ p.From.Offset = 0
+ p.From.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
+ if ctxt.Cursym.Cfunc != 0 {
+ p.From.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
+ }
+ p.To.Type = D_SI
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ACMPL
+ p.From.Type = D_SI
+ p.To.Type = D_CONST
+ p.To.Offset = int64(uint32(obj.StackPreempt & (1<<32 - 1)))
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AJEQ
+ p.To.Type = D_BRANCH
+ q1 = p
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ALEAL
+ p.From.Type = D_INDIR + D_SP
+ p.From.Offset = obj.StackGuard
+ p.To.Type = D_AX
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ASUBL
+ p.From.Type = D_SI
+ p.From.Offset = 0
+ p.To.Type = D_AX
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ACMPL
+ p.From.Type = D_AX
+ p.To.Type = D_CONST
+ p.To.Offset = int64(framesize) + (obj.StackGuard - obj.StackSmall)
+ }
+
+ // common
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AJHI
+ p.To.Type = D_BRANCH
+ p.To.Offset = 4
+ q = p
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ACALL
+ p.To.Type = D_BRANCH
+ if ctxt.Cursym.Cfunc != 0 {
+ p.To.Sym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
+ } else {
+
+ p.To.Sym = ctxt.Symmorestack[noctxt]
+ }
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AJMP
+ p.To.Type = D_BRANCH
+ p.Pcond = ctxt.Cursym.Text.Link
+
+ if q != nil {
+ q.Pcond = p.Link
+ }
+ if q1 != nil {
+ q1.Pcond = q.Link
+ }
+
+ *jmpok = q
+ return p
+}
+
+func follow(ctxt *obj.Link, s *obj.LSym) {
+ var firstp *obj.Prog
+ var lastp *obj.Prog
+
+ ctxt.Cursym = s
+
+ firstp = ctxt.NewProg()
+ lastp = firstp
+ xfol(ctxt, s.Text, &lastp)
+ lastp.Link = nil
+ s.Text = firstp.Link
+}
+
+func nofollow(a int) int {
+ switch a {
+ case AJMP,
+ ARET,
+ AIRETL,
+ AIRETW,
+ AUNDEF:
+ return 1
+ }
+
+ return 0
+}
+
+func pushpop(a int) int {
+ switch a {
+ case APUSHL,
+ APUSHFL,
+ APUSHW,
+ APUSHFW,
+ APOPL,
+ APOPFL,
+ APOPW,
+ APOPFW:
+ return 1
+ }
+
+ return 0
+}
+
+func relinv(a int) int {
+ switch a {
+ case AJEQ:
+ return AJNE
+ case AJNE:
+ return AJEQ
+ case AJLE:
+ return AJGT
+ case AJLS:
+ return AJHI
+ case AJLT:
+ return AJGE
+ case AJMI:
+ return AJPL
+ case AJGE:
+ return AJLT
+ case AJPL:
+ return AJMI
+ case AJGT:
+ return AJLE
+ case AJHI:
+ return AJLS
+ case AJCS:
+ return AJCC
+ case AJCC:
+ return AJCS
+ case AJPS:
+ return AJPC
+ case AJPC:
+ return AJPS
+ case AJOS:
+ return AJOC
+ case AJOC:
+ return AJOS
+ }
+
+ log.Fatalf("unknown relation: %s", Anames[a])
+ return 0
+}
+
+func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
+ var q *obj.Prog
+ var i int
+ var a int
+
+loop:
+ if p == nil {
+ return
+ }
+ if p.As == AJMP {
+ q = p.Pcond
+ if q != nil && q.As != ATEXT {
+ /* mark instruction as done and continue layout at target of jump */
+ p.Mark = 1
+
+ p = q
+ if p.Mark == 0 {
+ goto loop
+ }
+ }
+ }
+
+ if p.Mark != 0 {
+ /*
+ * p goes here, but already used it elsewhere.
+ * copy up to 4 instructions or else branch to other copy.
+ */
+ i = 0
+ q = p
+ for ; i < 4; (func() { i++; q = q.Link })() {
+
+ if q == nil {
+ break
+ }
+ if q == *last {
+ break
+ }
+ a = int(q.As)
+ if a == ANOP {
+ i--
+ continue
+ }
+
+ if nofollow(a) != 0 || pushpop(a) != 0 {
+ break // NOTE(rsc): arm does goto copy
+ }
+ if q.Pcond == nil || q.Pcond.Mark != 0 {
+ continue
+ }
+ if a == ACALL || a == ALOOP {
+ continue
+ }
+ for {
+ if p.As == ANOP {
+ p = p.Link
+ continue
+ }
+
+ q = obj.Copyp(ctxt, p)
+ p = p.Link
+ q.Mark = 1
+ (*last).Link = q
+ *last = q
+ if int(q.As) != a || q.Pcond == nil || q.Pcond.Mark != 0 {
+ continue
+ }
+
+ q.As = int16(relinv(int(q.As)))
+ p = q.Pcond
+ q.Pcond = q.Link
+ q.Link = p
+ xfol(ctxt, q.Link, last)
+ p = q.Link
+ if p.Mark != 0 {
+ return
+ }
+ goto loop
+ /* */
+ }
+ }
+ q = ctxt.NewProg()
+ q.As = AJMP
+ q.Lineno = p.Lineno
+ q.To.Type = D_BRANCH
+ q.To.Offset = p.Pc
+ q.Pcond = p
+ p = q
+ }
+
+ /* emit p */
+ p.Mark = 1
+
+ (*last).Link = p
+ *last = p
+ a = int(p.As)
+
+ /* continue loop with what comes after p */
+ if nofollow(a) != 0 {
+
+ return
+ }
+ if p.Pcond != nil && a != ACALL {
+ /*
+ * some kind of conditional branch.
+ * recurse to follow one path.
+ * continue loop on the other.
+ */
+ q = obj.Brchain(ctxt, p.Pcond)
+ if q != nil {
+
+ p.Pcond = q
+ }
+ q = obj.Brchain(ctxt, p.Link)
+ if q != nil {
+ p.Link = q
+ }
+ if p.From.Type == D_CONST {
+ if p.From.Offset == 1 {
+ /*
+ * expect conditional jump to be taken.
+ * rewrite so that's the fall-through case.
+ */
+ p.As = int16(relinv(a))
+
+ q = p.Link
+ p.Link = p.Pcond
+ p.Pcond = q
+ }
+ } else {
+
+ q = p.Link
+ if q.Mark != 0 {
+ if a != ALOOP {
+ p.As = int16(relinv(a))
+ p.Link = p.Pcond
+ p.Pcond = q
+ }
+ }
+ }
+
+ xfol(ctxt, p.Link, last)
+ if p.Pcond.Mark != 0 {
+ return
+ }
+ p = p.Pcond
+ goto loop
+ }
+
+ p = p.Link
+ goto loop
+}
+
+var Link386 = obj.LinkArch{
+ ByteOrder: binary.LittleEndian,
+ Pconv: Pconv,
+ Name: "386",
+ Thechar: '8',
+ Endian: obj.LittleEndian,
+ Addstacksplit: addstacksplit,
+ Assemble: span8,
+ Datasize: datasize,
+ Follow: follow,
+ Iscall: iscall,
+ Isdata: isdata,
+ Prg: prg,
+ Progedit: progedit,
+ Settextflag: settextflag,
+ Symtype: symtype,
+ Textflag: textflag,
+ Minlc: 1,
+ Ptrsize: 4,
+ Regsize: 4,
+ D_ADDR: D_ADDR,
+ D_AUTO: D_AUTO,
+ D_BRANCH: D_BRANCH,
+ D_CONST: D_CONST,
+ D_EXTERN: D_EXTERN,
+ D_FCONST: D_FCONST,
+ D_NONE: D_NONE,
+ D_PARAM: D_PARAM,
+ D_SCONST: D_SCONST,
+ D_STATIC: D_STATIC,
+ ACALL: ACALL,
+ ADATA: ADATA,
+ AEND: AEND,
+ AFUNCDATA: AFUNCDATA,
+ AGLOBL: AGLOBL,
+ AJMP: AJMP,
+ ANOP: ANOP,
+ APCDATA: APCDATA,
+ ARET: ARET,
+ ATEXT: ATEXT,
+ ATYPE: ATYPE,
+ AUSEFIELD: AUSEFIELD,
+}
--- /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.
+
+package i386
+
+const (
+ fmtLong = 1 << iota
+)
+
+func bool2int(b bool) int {
+ if b {
+ return 1
+ }
+ return 0
+}
--- /dev/null
+// Derived from Inferno utils/6l/obj.c and utils/6l/span.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package obj
+
+import (
+ "fmt"
+ "os"
+ "path"
+ "strings"
+)
+
+func addlib(ctxt *Link, src, obj, pathname string) {
+ name := path.Clean(pathname)
+
+ // runtime.a -> runtime
+ short := strings.TrimSuffix(name, ".a")
+
+ // already loaded?
+ for i := range ctxt.Library {
+ if ctxt.Library[i].Pkg == short {
+ return
+ }
+ }
+
+ var pname string
+ // runtime -> runtime.a for search
+ if (!(ctxt.Windows != 0) && name[0] == '/') || (ctxt.Windows != 0 && name[1] == ':') {
+ pname = name
+ } else {
+ // try dot, -L "libdir", and then goroot.
+ for _, dir := range ctxt.Libdir {
+ pname = dir + "/" + name
+ if _, err := os.Stat(pname); !os.IsNotExist(err) {
+ break
+ }
+ }
+ }
+ pname = path.Clean(pname)
+
+ // runtime.a -> runtime
+ pname = strings.TrimSuffix(pname, ".a")
+
+ if ctxt.Debugvlog > 1 && ctxt.Bso != nil {
+ fmt.Fprintf(ctxt.Bso, "%5.2f addlib: %s %s pulls in %s\n", Cputime(), obj, src, pname)
+ }
+ addlibpath(ctxt, src, obj, pname, name)
+}
+
+/*
+ * add library to library list.
+ * srcref: src file referring to package
+ * objref: object file referring to package
+ * file: object file, e.g., /home/rsc/go/pkg/container/vector.a
+ * pkg: package import path, e.g. container/vector
+ */
+func addlibpath(ctxt *Link, srcref, objref, file, pkg string) {
+ for _, lib := range ctxt.Library {
+ if lib.File == file {
+ return
+ }
+ }
+
+ if ctxt.Debugvlog > 1 && ctxt.Bso != nil {
+ fmt.Fprintf(ctxt.Bso, "%5.2f addlibpath: srcref: %s objref: %s file: %s pkg: %s\n", Cputime(), srcref, objref, file, pkg)
+ }
+
+ ctxt.Library = append(ctxt.Library, Library{
+ Objref: objref,
+ Srcref: srcref,
+ File: file,
+ Pkg: pkg,
+ })
+}
+
+const (
+ LOG = 5
+)
+
+func mkfwd(sym *LSym) {
+ var p *Prog
+ var i int
+ var dwn [LOG]int32
+ var cnt [LOG]int32
+ var lst [LOG]*Prog
+
+ for i = 0; i < LOG; i++ {
+ if i == 0 {
+ cnt[i] = 1
+ } else {
+
+ cnt[i] = LOG * cnt[i-1]
+ }
+ dwn[i] = 1
+ lst[i] = nil
+ }
+
+ i = 0
+ for p = sym.Text; p != nil && p.Link != nil; p = p.Link {
+ i--
+ if i < 0 {
+ i = LOG - 1
+ }
+ p.Forwd = nil
+ dwn[i]--
+ if dwn[i] <= 0 {
+ dwn[i] = cnt[i]
+ if lst[i] != nil {
+ lst[i].Forwd = p
+ }
+ lst[i] = p
+ }
+ }
+}
+
+func Copyp(ctxt *Link, q *Prog) *Prog {
+ var p *Prog
+
+ p = ctxt.NewProg()
+ *p = *q
+ return p
+}
+
+func Appendp(ctxt *Link, q *Prog) *Prog {
+ var p *Prog
+
+ p = ctxt.NewProg()
+ p.Link = q.Link
+ q.Link = p
+ p.Lineno = q.Lineno
+ p.Mode = q.Mode
+ return p
+}
--- /dev/null
+// Derived from Inferno utils/6l/l.h and related files.
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/l.h
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package obj
+
+import "encoding/binary"
+
+type Addr struct {
+ Offset int64
+ U struct {
+ Sval string
+ Dval float64
+ Branch *Prog
+ }
+ Sym *LSym
+ Gotype *LSym
+ Type int16
+ Index uint8
+ Scale int8
+ Reg int8
+ Name int8
+ Class int8
+ Etype uint8
+ Offset2 int32
+ Node interface{}
+ Width int64
+}
+
+type Prog struct {
+ Ctxt *Link
+ Pc int64
+ Lineno int32
+ Link *Prog
+ As int16
+ Scond uint8
+ From Addr
+ Reg uint8
+ From3 Addr
+ To Addr
+ Opt interface{}
+ Forwd *Prog
+ Pcond *Prog
+ Comefrom *Prog
+ Pcrel *Prog
+ Spadj int32
+ Mark uint16
+ Optab uint16
+ Back uint8
+ Ft uint8
+ Tt uint8
+ Isize uint8
+ Printed uint8
+ Width int8
+ Mode int8
+ TEXTFLAG uint8
+}
+
+type LSym struct {
+ Name string
+ Extname string
+ Type int16
+ Version int16
+ Dupok uint8
+ Cfunc uint8
+ External uint8
+ Nosplit uint8
+ Reachable uint8
+ Cgoexport uint8
+ Special uint8
+ Stkcheck uint8
+ Hide uint8
+ Leaf uint8
+ Fnptr uint8
+ Localentry uint8
+ Seenglobl uint8
+ Onlist uint8
+ Printed uint8
+ Symid int16
+ Dynid int32
+ Sig int32
+ Plt int32
+ Got int32
+ Align int32
+ Elfsym int32
+ Args int32
+ Locals int32
+ Value int64
+ Size int64
+ Hash *LSym
+ Allsym *LSym
+ Next *LSym
+ Sub *LSym
+ Outer *LSym
+ Gotype *LSym
+ Reachparent *LSym
+ Queue *LSym
+ File string
+ Dynimplib string
+ Dynimpvers string
+ Sect *struct{}
+ Autom *Auto
+ Text *Prog
+ Etext *Prog
+ Pcln *Pcln
+ P []byte
+ R []Reloc
+}
+
+type Reloc struct {
+ Off int32
+ Siz uint8
+ Done uint8
+ Type int32
+ Variant int32
+ Add int64
+ Xadd int64
+ Sym *LSym
+ Xsym *LSym
+}
+
+type Auto struct {
+ Asym *LSym
+ Link *Auto
+ Aoffset int32
+ Type int16
+ Gotype *LSym
+}
+
+type Hist struct {
+ Link *Hist
+ Name string
+ Line int32
+ Offset int32
+ Printed uint8
+}
+
+type Link struct {
+ Thechar int32
+ Thestring string
+ Goarm int32
+ Headtype int
+ Arch *LinkArch
+ Ignore func(string) int32
+ Debugasm int32
+ Debugline int32
+ Debughist int32
+ Debugread int32
+ Debugvlog int32
+ Debugstack int32
+ Debugzerostack int32
+ Debugdivmod int32
+ Debugfloat int32
+ Debugpcln int32
+ Flag_shared int32
+ Iself int32
+ Bso *Biobuf
+ Pathname string
+ Windows int32
+ Trimpath string
+ Goroot string
+ Goroot_final string
+ Enforce_data_order int32
+ Hash [LINKHASH]*LSym
+ Allsym *LSym
+ Nsymbol int32
+ Hist *Hist
+ Ehist *Hist
+ Plist *Plist
+ Plast *Plist
+ Sym_div *LSym
+ Sym_divu *LSym
+ Sym_mod *LSym
+ Sym_modu *LSym
+ Symmorestack [2]*LSym
+ Tlsg *LSym
+ Plan9privates *LSym
+ Curp *Prog
+ Printp *Prog
+ Blitrl *Prog
+ Elitrl *Prog
+ Rexflag int
+ Rep int
+ Repn int
+ Lock int
+ Asmode int
+ Andptr []byte
+ And [100]uint8
+ Instoffset int64
+ Autosize int32
+ Armsize int32
+ Pc int64
+ Libdir []string
+ Library []Library
+ Tlsoffset int
+ Diag func(string, ...interface{})
+ Mode int
+ Curauto *Auto
+ Curhist *Auto
+ Cursym *LSym
+ Version int
+ Textp *LSym
+ Etextp *LSym
+ Histdepth int32
+ Nhistfile int32
+ Filesyms *LSym
+}
+
+type Plist struct {
+ Name *LSym
+ Firstpc *Prog
+ Recur int
+ Link *Plist
+}
+
+type LinkArch struct {
+ Pconv func(*Prog) string
+ Name string
+ Thechar int
+ Endian int32
+ ByteOrder binary.ByteOrder
+ Addstacksplit func(*Link, *LSym)
+ Assemble func(*Link, *LSym)
+ Datasize func(*Prog) int
+ Follow func(*Link, *LSym)
+ Iscall func(*Prog) bool
+ Isdata func(*Prog) bool
+ Prg func() *Prog
+ Progedit func(*Link, *Prog)
+ Settextflag func(*Prog, int)
+ Symtype func(*Addr) int
+ Textflag func(*Prog) int
+ Minlc int
+ Ptrsize int
+ Regsize int
+ D_ADDR int
+ D_AUTO int
+ D_BRANCH int
+ D_CONST int
+ D_EXTERN int
+ D_FCONST int
+ D_NONE int
+ D_PARAM int
+ D_SCONST int
+ D_STATIC int
+ D_OREG int
+ ACALL int
+ ADATA int
+ AEND int
+ AFUNCDATA int
+ AGLOBL int
+ AJMP int
+ ANOP int
+ APCDATA int
+ ARET int
+ ATEXT int
+ ATYPE int
+ AUSEFIELD int
+}
+
+type Library struct {
+ Objref string
+ Srcref string
+ File string
+ Pkg string
+}
+
+type Pcln struct {
+ Pcsp Pcdata
+ Pcfile Pcdata
+ Pcline Pcdata
+ Pcdata []Pcdata
+ Funcdata []*LSym
+ Funcdataoff []int64
+ File []*LSym
+ Lastfile *LSym
+ Lastindex int
+}
+
+type Pcdata struct {
+ P []byte
+}
+
+type Pciter struct {
+ d Pcdata
+ p []byte
+ pc uint32
+ nextpc uint32
+ pcscale uint32
+ value int32
+ start int
+ done int
+}
+
+// prevent incompatible type signatures between liblink and 8l on Plan 9
+
+// prevent incompatible type signatures between liblink and 8l on Plan 9
+
+// LSym.type
+const (
+ Sxxx = iota
+ STEXT
+ SELFRXSECT
+ STYPE
+ SSTRING
+ SGOSTRING
+ SGOFUNC
+ SRODATA
+ SFUNCTAB
+ STYPELINK
+ SSYMTAB
+ SPCLNTAB
+ SELFROSECT
+ SMACHOPLT
+ SELFSECT
+ SMACHO
+ SMACHOGOT
+ SWINDOWS
+ SELFGOT
+ SNOPTRDATA
+ SINITARR
+ SDATA
+ SBSS
+ SNOPTRBSS
+ STLSBSS
+ SXREF
+ SMACHOSYMSTR
+ SMACHOSYMTAB
+ SMACHOINDIRECTPLT
+ SMACHOINDIRECTGOT
+ SFILE
+ SFILEPATH
+ SCONST
+ SDYNIMPORT
+ SHOSTOBJ
+ SSUB = 1 << 8
+ SMASK = SSUB - 1
+ SHIDDEN = 1 << 9
+)
+
+// Reloc.type
+const (
+ R_ADDR = 1 + iota
+ R_ADDRPOWER
+ R_SIZE
+ R_CALL
+ R_CALLARM
+ R_CALLIND
+ R_CALLPOWER
+ R_CONST
+ R_PCREL
+ R_TLS
+ R_TLS_LE
+ R_TLS_IE
+ R_GOTOFF
+ R_PLT0
+ R_PLT1
+ R_PLT2
+ R_USEFIELD
+ R_POWER_TOC
+)
+
+// Reloc.variant
+const (
+ RV_NONE = iota
+ RV_POWER_LO
+ RV_POWER_HI
+ RV_POWER_HA
+ RV_POWER_DS
+ RV_CHECK_OVERFLOW = 1 << 8
+ RV_TYPE_MASK = RV_CHECK_OVERFLOW - 1
+)
+
+// Auto.type
+const (
+ A_AUTO = 1 + iota
+ A_PARAM
+)
+
+const (
+ LINKHASH = 100003
+)
+
+// Pcdata iterator.
+// for(pciterinit(ctxt, &it, &pcd); !it.done; pciternext(&it)) { it.value holds in [it.pc, it.nextpc) }
+
+// symbol version, incremented each time a file is loaded.
+// version==1 is reserved for savehist.
+const (
+ HistVersion = 1
+)
+
+// Link holds the context for writing object code from a compiler
+// to be linker input or for reading that input into the linker.
+
+const (
+ LittleEndian = 0x04030201
+ BigEndian = 0x01020304
+)
+
+// LinkArch is the definition of a single architecture.
+
+/* executable header types */
+const (
+ Hunknown = 0 + iota
+ Hdarwin
+ Hdragonfly
+ Helf
+ Hfreebsd
+ Hlinux
+ Hnacl
+ Hnetbsd
+ Hopenbsd
+ Hplan9
+ Hsolaris
+ Hwindows
+)
+
+const (
+ LinkAuto = 0 + iota
+ LinkInternal
+ LinkExternal
+)
+
+// asm5.c
+
+// asm6.c
+
+// asm8.c
+
+// asm9.c
+
+// data.c
+
+// go.c
+
+// ld.c
--- /dev/null
+// Copyright 2009 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 obj
+
+import (
+ "fmt"
+ "path/filepath"
+ "strings"
+)
+
+const (
+ HISTSZ = 10
+ NSYM = 50
+)
+
+func linklinefmt(ctxt *Link, lno0 int, showAll, showFullPath bool) string {
+ var a [HISTSZ]struct {
+ incl *Hist
+ idel int32
+ line *Hist
+ ldel int32
+ }
+ lno := int32(lno0)
+ lno1 := lno
+ var d int32
+ var i int
+ var n int
+ var h *Hist
+ n = 0
+ var fp string
+ for h = ctxt.Hist; h != nil; h = h.Link {
+ if h.Offset < 0 {
+ continue
+ }
+ if lno < h.Line {
+ break
+ }
+ if h.Name != "<pop>" {
+ if h.Offset > 0 {
+ // #line directive
+ if n > 0 && n < int(HISTSZ) {
+ a[n-1].line = h
+ a[n-1].ldel = h.Line - h.Offset + 1
+ }
+ } else {
+ // beginning of file
+ if n < int(HISTSZ) {
+ a[n].incl = h
+ a[n].idel = h.Line
+ a[n].line = nil
+ }
+ n++
+ }
+ continue
+ }
+ n--
+ if n > 0 && n < int(HISTSZ) {
+ d = h.Line - a[n].incl.Line
+ a[n-1].ldel += d
+ a[n-1].idel += d
+ }
+ }
+ if n > int(HISTSZ) {
+ n = int(HISTSZ)
+ }
+ for i = n - 1; i >= 0; i-- {
+ if i != n-1 {
+ if !showAll {
+ break
+ }
+ fp += " "
+ }
+ if ctxt.Debugline != 0 || showFullPath {
+ fp += fmt.Sprintf("%s/", ctxt.Pathname)
+ }
+ if a[i].line != nil {
+ fp += fmt.Sprintf("%s:%d[%s:%d]", a[i].line.Name, lno-a[i].ldel+1, a[i].incl.Name, lno-a[i].idel+1)
+ } else {
+ fp += fmt.Sprintf("%s:%d", a[i].incl.Name, lno-a[i].idel+1)
+ }
+ lno = a[i].incl.Line - 1 // now print out start of this file
+ }
+ if n == 0 {
+ fp += fmt.Sprintf("<unknown line number %d %d %d %s>", lno1, ctxt.Hist.Offset, ctxt.Hist.Line, ctxt.Hist.Name)
+ }
+ return fp
+}
+
+// Does s have t as a path prefix?
+// That is, does s == t or does s begin with t followed by a slash?
+// For portability, we allow ASCII case folding, so that haspathprefix("a/b/c", "A/B") is true.
+// Similarly, we allow slash folding, so that haspathprefix("a/b/c", "a\\b") is true.
+func haspathprefix(s string, t string) bool {
+ var i int
+ var cs int
+ var ct int
+ if len(t) > len(s) {
+ return false
+ }
+ for i = 0; i < len(t); i++ {
+ cs = int(s[i])
+ ct = int(t[i])
+ if 'A' <= cs && cs <= 'Z' {
+ cs += 'a' - 'A'
+ }
+ if 'A' <= ct && ct <= 'Z' {
+ ct += 'a' - 'A'
+ }
+ if cs == '\\' {
+ cs = '/'
+ }
+ if ct == '\\' {
+ ct = '/'
+ }
+ if cs != ct {
+ return false
+ }
+ }
+ return i >= len(s) || s[i] == '/' || s[i] == '\\'
+}
+
+// This is a simplified copy of linklinefmt above.
+// It doesn't allow printing the full stack, and it returns the file name and line number separately.
+// TODO: Unify with linklinefmt somehow.
+func linkgetline(ctxt *Link, line int32, f **LSym, l *int32) {
+ var a [HISTSZ]struct {
+ incl *Hist
+ idel int32
+ line *Hist
+ ldel int32
+ }
+ var lno int32
+ var d int32
+ var dlno int32
+ var n int
+ var h *Hist
+ var buf string
+ var buf1 string
+ var file string
+ lno = int32(line)
+ n = 0
+ for h = ctxt.Hist; h != nil; h = h.Link {
+ if h.Offset < 0 {
+ continue
+ }
+ if lno < h.Line {
+ break
+ }
+ if h.Name != "<pop>" {
+ if h.Offset > 0 {
+ // #line directive
+ if n > 0 && n < HISTSZ {
+ a[n-1].line = h
+ a[n-1].ldel = h.Line - h.Offset + 1
+ }
+ } else {
+ // beginning of file
+ if n < HISTSZ {
+ a[n].incl = h
+ a[n].idel = h.Line
+ a[n].line = nil
+ }
+ n++
+ }
+ continue
+ }
+ n--
+ if n > 0 && n < HISTSZ {
+ d = h.Line - a[n].incl.Line
+ a[n-1].ldel += d
+ a[n-1].idel += d
+ }
+ }
+ if n > HISTSZ {
+ n = HISTSZ
+ }
+ if n <= 0 {
+ *f = Linklookup(ctxt, "??", HistVersion)
+ *l = 0
+ return
+ }
+ n--
+ if a[n].line != nil {
+ file = a[n].line.Name
+ dlno = a[n].ldel - 1
+ } else {
+ file = a[n].incl.Name
+ dlno = a[n].idel - 1
+ }
+ if filepath.IsAbs(file) || strings.HasPrefix(file, "<") {
+ buf = fmt.Sprintf("%s", file)
+ } else {
+ buf = fmt.Sprintf("%s/%s", ctxt.Pathname, file)
+ }
+ // Remove leading ctxt->trimpath, or else rewrite $GOROOT to $GOROOT_FINAL.
+ if ctxt.Trimpath != "" && haspathprefix(buf, ctxt.Trimpath) {
+ if len(buf) == len(ctxt.Trimpath) {
+ buf = "??"
+ } else {
+ buf1 = fmt.Sprintf("%s", buf[len(ctxt.Trimpath)+1:])
+ if buf1[0] == '\x00' {
+ buf1 = "??"
+ }
+ buf = buf1
+ }
+ } else if ctxt.Goroot_final != "" && haspathprefix(buf, ctxt.Goroot) {
+ buf1 = fmt.Sprintf("%s%s", ctxt.Goroot_final, buf[len(ctxt.Goroot):])
+ buf = buf1
+ }
+ lno -= dlno
+ *f = Linklookup(ctxt, buf, HistVersion)
+ *l = lno
+}
+
+func Linklinehist(ctxt *Link, lineno int, f string, offset int) {
+ var h *Hist
+
+ if false { // debug['f']
+ if f != "" {
+ if offset != 0 {
+ fmt.Printf("%4d: %s (#line %d)\n", lineno, f, offset)
+ } else {
+
+ fmt.Printf("%4d: %s\n", lineno, f)
+ }
+ } else {
+
+ fmt.Printf("%4d: <pop>\n", lineno)
+ }
+ }
+
+ h = new(Hist)
+ *h = Hist{}
+ h.Name = f
+ h.Line = int32(lineno)
+ h.Offset = int32(offset)
+ h.Link = nil
+ if ctxt.Ehist == nil {
+ ctxt.Hist = h
+ ctxt.Ehist = h
+ return
+ }
+
+ ctxt.Ehist.Link = h
+ ctxt.Ehist = h
+}
+
+func Linkprfile(ctxt *Link, line int) {
+ l := int32(line)
+ var i int
+ var n int
+ var a [HISTSZ]Hist
+ var h *Hist
+ var d int32
+ n = 0
+ for h = ctxt.Hist; h != nil; h = h.Link {
+ if l < h.Line {
+ break
+ }
+ if h.Name != "<pop>" {
+ if h.Offset == 0 {
+ if n >= 0 && n < HISTSZ {
+ a[n] = *h
+ }
+ n++
+ continue
+ }
+ if n > 0 && n < HISTSZ {
+ if a[n-1].Offset == 0 {
+ a[n] = *h
+ n++
+ } else {
+ a[n-1] = *h
+ }
+ }
+ continue
+ }
+ n--
+ if n >= 0 && n < HISTSZ {
+ d = h.Line - a[n].Line
+ for i = 0; i < n; i++ {
+ a[i].Line += d
+ }
+ }
+ }
+ if n > HISTSZ {
+ n = HISTSZ
+ }
+ for i = 0; i < n; i++ {
+ fmt.Printf("%s:%d ", a[i].Name, int(l-a[i].Line+a[i].Offset+1))
+ }
+}
+
+/*
+ * start a new Prog list.
+ */
+func Linknewplist(ctxt *Link) *Plist {
+
+ var pl *Plist
+
+ pl = new(Plist)
+ *pl = Plist{}
+ if ctxt.Plist == nil {
+ ctxt.Plist = pl
+ } else {
+
+ ctxt.Plast.Link = pl
+ }
+ ctxt.Plast = pl
+
+ return pl
+}
--- /dev/null
+// Copyright 2013 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 obj
+
+import (
+ "fmt"
+ "log"
+ "path/filepath"
+ "strings"
+)
+
+var outfile string
+
+// The Go and C compilers, and the assembler, call writeobj to write
+// out a Go object file. The linker does not call this; the linker
+// does not write out object files.
+func Writeobjdirect(ctxt *Link, b *Biobuf) {
+
+ var flag int
+ var found int
+ var h *Hist
+ var s *LSym
+ var text *LSym
+ var etext *LSym
+ var curtext *LSym
+ var data *LSym
+ var edata *LSym
+ var pl *Plist
+ var p *Prog
+ var plink *Prog
+ var a *Auto
+
+ // Build list of symbols, and assign instructions to lists.
+ // Ignore ctxt->plist boundaries. There are no guarantees there,
+ // and the C compilers and assemblers just use one big list.
+ text = nil
+
+ curtext = nil
+ data = nil
+ etext = nil
+ edata = nil
+ for pl = ctxt.Plist; pl != nil; pl = pl.Link {
+ for p = pl.Firstpc; p != nil; p = plink {
+ if ctxt.Debugasm != 0 && ctxt.Debugvlog != 0 {
+ fmt.Printf("obj: %p %v\n", p, p)
+ }
+ plink = p.Link
+ p.Link = nil
+
+ if int(p.As) == ctxt.Arch.AEND {
+ continue
+ }
+
+ if int(p.As) == ctxt.Arch.ATYPE {
+ // Assume each TYPE instruction describes
+ // a different local variable or parameter,
+ // so no dedup.
+ // Using only the TYPE instructions means
+ // that we discard location information about local variables
+ // in C and assembly functions; that information is inferred
+ // from ordinary references, because there are no TYPE
+ // instructions there. Without the type information, gdb can't
+ // use the locations, so we don't bother to save them.
+ // If something else could use them, we could arrange to
+ // preserve them.
+ if curtext == nil {
+
+ continue
+ }
+ a = new(Auto)
+ a.Asym = p.From.Sym
+ a.Aoffset = int32(p.From.Offset)
+ a.Type = int16(ctxt.Arch.Symtype(&p.From))
+ a.Gotype = p.From.Gotype
+ a.Link = curtext.Autom
+ curtext.Autom = a
+ continue
+ }
+
+ if int(p.As) == ctxt.Arch.AGLOBL {
+ s = p.From.Sym
+ tmp6 := s.Seenglobl
+ s.Seenglobl++
+ if tmp6 != 0 {
+ fmt.Printf("duplicate %v\n", p)
+ }
+ if s.Onlist != 0 {
+ log.Fatalf("symbol %s listed multiple times", s.Name)
+ }
+ s.Onlist = 1
+ if data == nil {
+ data = s
+ } else {
+
+ edata.Next = s
+ }
+ s.Next = nil
+ s.Size = p.To.Offset
+ if s.Type == 0 || s.Type == SXREF {
+ s.Type = SBSS
+ }
+ flag = ctxt.Arch.Textflag(p)
+ if flag&DUPOK != 0 {
+ s.Dupok = 1
+ }
+ if flag&RODATA != 0 {
+ s.Type = SRODATA
+ } else if flag&NOPTR != 0 {
+ s.Type = SNOPTRBSS
+ }
+ edata = s
+ continue
+ }
+
+ if int(p.As) == ctxt.Arch.ADATA {
+ savedata(ctxt, p.From.Sym, p, "<input>")
+ continue
+ }
+
+ if int(p.As) == ctxt.Arch.ATEXT {
+ s = p.From.Sym
+ if s == nil {
+ // func _() { }
+ curtext = nil
+
+ continue
+ }
+
+ if s.Text != nil {
+ log.Fatalf("duplicate TEXT for %s", s.Name)
+ }
+ if s.Onlist != 0 {
+ log.Fatalf("symbol %s listed multiple times", s.Name)
+ }
+ s.Onlist = 1
+ if text == nil {
+ text = s
+ } else {
+
+ etext.Next = s
+ }
+ etext = s
+ flag = ctxt.Arch.Textflag(p)
+ if flag&DUPOK != 0 {
+ s.Dupok = 1
+ }
+ if flag&NOSPLIT != 0 {
+ s.Nosplit = 1
+ }
+ s.Next = nil
+ s.Type = STEXT
+ s.Text = p
+ s.Etext = p
+ curtext = s
+ continue
+ }
+
+ if int(p.As) == ctxt.Arch.AFUNCDATA {
+ // Rewrite reference to go_args_stackmap(SB) to the Go-provided declaration information.
+ if curtext == nil { // func _() {}
+ continue
+ }
+ if p.To.Sym.Name == "go_args_stackmap" {
+ if int(p.From.Type) != ctxt.Arch.D_CONST || p.From.Offset != FUNCDATA_ArgsPointerMaps {
+ ctxt.Diag("FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps")
+ }
+ p.To.Sym = Linklookup(ctxt, string(fmt.Sprintf("%s.args_stackmap", curtext.Name)), int(curtext.Version))
+ }
+ }
+
+ if curtext == nil {
+ continue
+ }
+ s = curtext
+ s.Etext.Link = p
+ s.Etext = p
+ }
+ }
+
+ // Add reference to Go arguments for C or assembly functions without them.
+ for s = text; s != nil; s = s.Next {
+
+ if !strings.HasPrefix(s.Name, "\"\".") {
+ continue
+ }
+ found = 0
+ for p = s.Text; p != nil; p = p.Link {
+ if int(p.As) == ctxt.Arch.AFUNCDATA && int(p.From.Type) == ctxt.Arch.D_CONST && p.From.Offset == FUNCDATA_ArgsPointerMaps {
+ found = 1
+ break
+ }
+ }
+
+ if !(found != 0) {
+ p = Appendp(ctxt, s.Text)
+ p.As = int16(ctxt.Arch.AFUNCDATA)
+ p.From.Type = int16(ctxt.Arch.D_CONST)
+ p.From.Offset = FUNCDATA_ArgsPointerMaps
+ if ctxt.Arch.Thechar == '6' || ctxt.Arch.Thechar == '8' {
+ p.To.Type = int16(ctxt.Arch.D_EXTERN)
+ } else {
+
+ p.To.Type = int16(ctxt.Arch.D_OREG)
+ p.To.Name = int8(ctxt.Arch.D_EXTERN)
+ }
+
+ p.To.Sym = Linklookup(ctxt, string(fmt.Sprintf("%s.args_stackmap", s.Name)), int(s.Version))
+ }
+ }
+
+ // Turn functions into machine code images.
+ for s = text; s != nil; s = s.Next {
+
+ mkfwd(s)
+ linkpatch(ctxt, s)
+ ctxt.Arch.Follow(ctxt, s)
+ ctxt.Arch.Addstacksplit(ctxt, s)
+ ctxt.Arch.Assemble(ctxt, s)
+ linkpcln(ctxt, s)
+ }
+
+ // Emit header.
+ Bputc(b, 0)
+
+ Bputc(b, 0)
+ fmt.Fprintf(b, "go13ld")
+ Bputc(b, 1) // version
+
+ // Emit autolib.
+ for h = ctxt.Hist; h != nil; h = h.Link {
+
+ if h.Offset < 0 {
+ wrstring(b, h.Name)
+ }
+ }
+ wrstring(b, "")
+
+ // Emit symbols.
+ for s = text; s != nil; s = s.Next {
+
+ writesym(ctxt, b, s)
+ }
+ for s = data; s != nil; s = s.Next {
+ writesym(ctxt, b, s)
+ }
+
+ // Emit footer.
+ Bputc(b, 0xff)
+
+ Bputc(b, 0xff)
+ fmt.Fprintf(b, "go13ld")
+}
+
+func writesym(ctxt *Link, b *Biobuf, s *LSym) {
+ var r *Reloc
+ var i int
+ var j int
+ var c int
+ var n int
+ var pc *Pcln
+ var p *Prog
+ var a *Auto
+ var name string
+
+ if ctxt.Debugasm != 0 {
+ fmt.Fprintf(ctxt.Bso, "%s ", s.Name)
+ if s.Version != 0 {
+ fmt.Fprintf(ctxt.Bso, "v=%d ", s.Version)
+ }
+ if s.Type != 0 {
+ fmt.Fprintf(ctxt.Bso, "t=%d ", s.Type)
+ }
+ if s.Dupok != 0 {
+ fmt.Fprintf(ctxt.Bso, "dupok ")
+ }
+ if s.Cfunc != 0 {
+ fmt.Fprintf(ctxt.Bso, "cfunc ")
+ }
+ if s.Nosplit != 0 {
+ fmt.Fprintf(ctxt.Bso, "nosplit ")
+ }
+ fmt.Fprintf(ctxt.Bso, "size=%d value=%d", int64(s.Size), int64(s.Value))
+ if s.Type == STEXT {
+ fmt.Fprintf(ctxt.Bso, " args=%#x locals=%#x", uint64(s.Args), uint64(s.Locals))
+ if s.Leaf != 0 {
+ fmt.Fprintf(ctxt.Bso, " leaf")
+ }
+ }
+
+ fmt.Fprintf(ctxt.Bso, "\n")
+ for p = s.Text; p != nil; p = p.Link {
+ fmt.Fprintf(ctxt.Bso, "\t%#04x %v\n", uint(int(p.Pc)), p)
+ }
+ for i = 0; i < len(s.P); {
+ fmt.Fprintf(ctxt.Bso, "\t%#04x", uint(i))
+ for j = i; j < i+16 && j < len(s.P); j++ {
+ fmt.Fprintf(ctxt.Bso, " %02x", s.P[j])
+ }
+ for ; j < i+16; j++ {
+ fmt.Fprintf(ctxt.Bso, " ")
+ }
+ fmt.Fprintf(ctxt.Bso, " ")
+ for j = i; j < i+16 && j < len(s.P); j++ {
+ c = int(s.P[j])
+ if ' ' <= c && c <= 0x7e {
+ fmt.Fprintf(ctxt.Bso, "%c", c)
+ } else {
+
+ fmt.Fprintf(ctxt.Bso, ".")
+ }
+ }
+
+ fmt.Fprintf(ctxt.Bso, "\n")
+ i += 16
+ }
+
+ for i = 0; i < len(s.R); i++ {
+ r = &s.R[i]
+ name = ""
+ if r.Sym != nil {
+ name = r.Sym.Name
+ }
+ if ctxt.Arch.Thechar == '5' || ctxt.Arch.Thechar == '9' {
+ fmt.Fprintf(ctxt.Bso, "\trel %d+%d t=%d %s+%x\n", int(r.Off), r.Siz, r.Type, name, uint64(int64(r.Add)))
+ } else {
+
+ fmt.Fprintf(ctxt.Bso, "\trel %d+%d t=%d %s+%d\n", int(r.Off), r.Siz, r.Type, name, int64(r.Add))
+ }
+ }
+ }
+
+ Bputc(b, 0xfe)
+ wrint(b, int64(s.Type))
+ wrstring(b, s.Name)
+ wrint(b, int64(s.Version))
+ wrint(b, int64(s.Dupok))
+ wrint(b, s.Size)
+ wrsym(b, s.Gotype)
+ wrdata(b, s.P)
+
+ wrint(b, int64(len(s.R)))
+ for i = 0; i < len(s.R); i++ {
+ r = &s.R[i]
+ wrint(b, int64(r.Off))
+ wrint(b, int64(r.Siz))
+ wrint(b, int64(r.Type))
+ wrint(b, r.Add)
+ wrint(b, r.Xadd)
+ wrsym(b, r.Sym)
+ wrsym(b, r.Xsym)
+ }
+
+ if s.Type == STEXT {
+ wrint(b, int64(s.Args))
+ wrint(b, int64(s.Locals))
+ wrint(b, int64(s.Nosplit))
+ wrint(b, int64(s.Leaf)|int64(s.Cfunc)<<1)
+ n = 0
+ for a = s.Autom; a != nil; a = a.Link {
+ n++
+ }
+ wrint(b, int64(n))
+ for a = s.Autom; a != nil; a = a.Link {
+ wrsym(b, a.Asym)
+ wrint(b, int64(a.Aoffset))
+ if int(a.Type) == ctxt.Arch.D_AUTO {
+ wrint(b, A_AUTO)
+ } else if int(a.Type) == ctxt.Arch.D_PARAM {
+ wrint(b, A_PARAM)
+ } else {
+
+ log.Fatalf("%s: invalid local variable type %d", s.Name, a.Type)
+ }
+ wrsym(b, a.Gotype)
+ }
+
+ pc = s.Pcln
+ wrdata(b, pc.Pcsp.P)
+ wrdata(b, pc.Pcfile.P)
+ wrdata(b, pc.Pcline.P)
+ wrint(b, int64(len(pc.Pcdata)))
+ for i = 0; i < len(pc.Pcdata); i++ {
+ wrdata(b, pc.Pcdata[i].P)
+ }
+ wrint(b, int64(len(pc.Funcdataoff)))
+ for i = 0; i < len(pc.Funcdataoff); i++ {
+ wrsym(b, pc.Funcdata[i])
+ }
+ for i = 0; i < len(pc.Funcdataoff); i++ {
+ wrint(b, pc.Funcdataoff[i])
+ }
+ wrint(b, int64(len(pc.File)))
+ for i = 0; i < len(pc.File); i++ {
+ wrpathsym(ctxt, b, pc.File[i])
+ }
+ }
+}
+
+func wrint(b *Biobuf, sval int64) {
+ var uv uint64
+ var v uint64
+ var buf [10]uint8
+ var p []uint8
+ uv = (uint64(sval) << 1) ^ uint64(int64(sval>>63))
+ p = buf[:]
+ for v = uv; v >= 0x80; v >>= 7 {
+ p[0] = uint8(v | 0x80)
+ p = p[1:]
+ }
+ p[0] = uint8(v)
+ p = p[1:]
+ Bwrite(b, buf[:len(buf)-len(p)])
+}
+
+func wrstring(b *Biobuf, s string) {
+ wrint(b, int64(len(s)))
+ b.w.WriteString(s)
+}
+
+// wrpath writes a path just like a string, but on windows, it
+// translates '\\' to '/' in the process.
+func wrpath(ctxt *Link, b *Biobuf, p string) {
+ wrstring(b, filepath.ToSlash(p))
+}
+
+func wrdata(b *Biobuf, v []byte) {
+ wrint(b, int64(len(v)))
+ Bwrite(b, v)
+}
+
+func wrpathsym(ctxt *Link, b *Biobuf, s *LSym) {
+ if s == nil {
+ wrint(b, 0)
+ wrint(b, 0)
+ return
+ }
+
+ wrpath(ctxt, b, s.Name)
+ wrint(b, int64(s.Version))
+}
+
+func wrsym(b *Biobuf, s *LSym) {
+ if s == nil {
+ wrint(b, 0)
+ wrint(b, 0)
+ return
+ }
+
+ wrstring(b, s.Name)
+ wrint(b, int64(s.Version))
+}
+
+var startmagic string = "\x00\x00go13ld"
+
+var endmagic string = "\xff\xffgo13ld"
--- /dev/null
+// Inferno utils/6l/pass.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/pass.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package obj
+
+// Code and data passes.
+
+func Brchain(ctxt *Link, p *Prog) *Prog {
+
+ var i int
+
+ for i = 0; i < 20; i++ {
+ if p == nil || int(p.As) != ctxt.Arch.AJMP || p.Pcond == nil {
+ return p
+ }
+ p = p.Pcond
+ }
+
+ return nil
+}
+
+func brloop(ctxt *Link, p *Prog) *Prog {
+ var c int
+ var q *Prog
+
+ c = 0
+ for q = p; q != nil; q = q.Pcond {
+ if int(q.As) != ctxt.Arch.AJMP || q.Pcond == nil {
+ break
+ }
+ c++
+ if c >= 5000 {
+ return nil
+ }
+ }
+
+ return q
+}
+
+func linkpatch(ctxt *Link, sym *LSym) {
+ var c int32
+ var name string
+ var p *Prog
+ var q *Prog
+
+ ctxt.Cursym = sym
+
+ for p = sym.Text; p != nil; p = p.Link {
+ if ctxt.Arch.Progedit != nil {
+ ctxt.Arch.Progedit(ctxt, p)
+ }
+ if int(p.To.Type) != ctxt.Arch.D_BRANCH {
+ continue
+ }
+ if p.To.U.Branch != nil {
+ // TODO: Remove to.u.branch in favor of p->pcond.
+ p.Pcond = p.To.U.Branch
+
+ continue
+ }
+
+ if p.To.Sym != nil {
+ continue
+ }
+ c = int32(p.To.Offset)
+ for q = sym.Text; q != nil; {
+ if int64(c) == q.Pc {
+ break
+ }
+ if q.Forwd != nil && int64(c) >= q.Forwd.Pc {
+ q = q.Forwd
+ } else {
+
+ q = q.Link
+ }
+ }
+
+ if q == nil {
+ name = "<nil>"
+ if p.To.Sym != nil {
+ name = p.To.Sym.Name
+ }
+ ctxt.Diag("branch out of range (%#x)\n%v [%s]", uint32(c), p, name)
+ p.To.Type = int16(ctxt.Arch.D_NONE)
+ }
+
+ p.To.U.Branch = q
+ p.Pcond = q
+ }
+
+ for p = sym.Text; p != nil; p = p.Link {
+ p.Mark = 0 /* initialization for follow */
+ if p.Pcond != nil {
+ p.Pcond = brloop(ctxt, p.Pcond)
+ if p.Pcond != nil {
+ if int(p.To.Type) == ctxt.Arch.D_BRANCH {
+ p.To.Offset = p.Pcond.Pc
+ }
+ }
+ }
+ }
+}
--- /dev/null
+// Copyright 2013 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 obj
+
+import (
+ "fmt"
+ "log"
+)
+
+func addvarint(ctxt *Link, d *Pcdata, val uint32) {
+ var v uint32
+ for v = val; v >= 0x80; v >>= 7 {
+ d.P = append(d.P, uint8(v|0x80))
+ }
+ d.P = append(d.P, uint8(v))
+}
+
+// funcpctab writes to dst a pc-value table mapping the code in func to the values
+// returned by valfunc parameterized by arg. The invocation of valfunc to update the
+// current value is, for each p,
+//
+// val = valfunc(func, val, p, 0, arg);
+// record val as value at p->pc;
+// val = valfunc(func, val, p, 1, arg);
+//
+// where func is the function, val is the current value, p is the instruction being
+// considered, and arg can be used to further parameterize valfunc.
+func funcpctab(ctxt *Link, dst *Pcdata, func_ *LSym, desc string, valfunc func(*Link, *LSym, int32, *Prog, int32, interface{}) int32, arg interface{}) {
+
+ var dbg int
+ var i int
+ var oldval int32
+ var val int32
+ var started int32
+ var delta uint32
+ var pc int64
+ var p *Prog
+
+ // To debug a specific function, uncomment second line and change name.
+ dbg = 0
+
+ //dbg = strcmp(func->name, "main.main") == 0;
+ //dbg = strcmp(desc, "pctofile") == 0;
+
+ ctxt.Debugpcln += int32(dbg)
+
+ dst.P = dst.P[:0]
+
+ if ctxt.Debugpcln != 0 {
+ fmt.Fprintf(ctxt.Bso, "funcpctab %s [valfunc=%s]\n", func_.Name, desc)
+ }
+
+ val = -1
+ oldval = val
+ if func_.Text == nil {
+ ctxt.Debugpcln -= int32(dbg)
+ return
+ }
+
+ pc = func_.Text.Pc
+
+ if ctxt.Debugpcln != 0 {
+ fmt.Fprintf(ctxt.Bso, "%6x %6d %v\n", uint64(pc), val, func_.Text)
+ }
+
+ started = 0
+ for p = func_.Text; p != nil; p = p.Link {
+ // Update val. If it's not changing, keep going.
+ val = valfunc(ctxt, func_, val, p, 0, arg)
+
+ if val == oldval && started != 0 {
+ val = valfunc(ctxt, func_, val, p, 1, arg)
+ if ctxt.Debugpcln != 0 {
+ fmt.Fprintf(ctxt.Bso, "%6x %6s %v\n", uint64(int64(p.Pc)), "", p)
+ }
+ continue
+ }
+
+ // If the pc of the next instruction is the same as the
+ // pc of this instruction, this instruction is not a real
+ // instruction. Keep going, so that we only emit a delta
+ // for a true instruction boundary in the program.
+ if p.Link != nil && p.Link.Pc == p.Pc {
+
+ val = valfunc(ctxt, func_, val, p, 1, arg)
+ if ctxt.Debugpcln != 0 {
+ fmt.Fprintf(ctxt.Bso, "%6x %6s %v\n", uint64(int64(p.Pc)), "", p)
+ }
+ continue
+ }
+
+ // The table is a sequence of (value, pc) pairs, where each
+ // pair states that the given value is in effect from the current position
+ // up to the given pc, which becomes the new current position.
+ // To generate the table as we scan over the program instructions,
+ // we emit a "(value" when pc == func->value, and then
+ // each time we observe a change in value we emit ", pc) (value".
+ // When the scan is over, we emit the closing ", pc)".
+ //
+ // The table is delta-encoded. The value deltas are signed and
+ // transmitted in zig-zag form, where a complement bit is placed in bit 0,
+ // and the pc deltas are unsigned. Both kinds of deltas are sent
+ // as variable-length little-endian base-128 integers,
+ // where the 0x80 bit indicates that the integer continues.
+
+ if ctxt.Debugpcln != 0 {
+
+ fmt.Fprintf(ctxt.Bso, "%6x %6d %v\n", uint64(int64(p.Pc)), val, p)
+ }
+
+ if started != 0 {
+ addvarint(ctxt, dst, uint32((p.Pc-pc)/int64(ctxt.Arch.Minlc)))
+ pc = p.Pc
+ }
+
+ delta = uint32(val) - uint32(oldval)
+ if delta>>31 != 0 {
+ delta = 1 | ^(delta << 1)
+ } else {
+
+ delta <<= 1
+ }
+ addvarint(ctxt, dst, delta)
+ oldval = val
+ started = 1
+ val = valfunc(ctxt, func_, val, p, 1, arg)
+ }
+
+ if started != 0 {
+ if ctxt.Debugpcln != 0 {
+ fmt.Fprintf(ctxt.Bso, "%6x done\n", uint64(int64(func_.Text.Pc)+func_.Size))
+ }
+ addvarint(ctxt, dst, uint32((func_.Value+func_.Size-pc)/int64(ctxt.Arch.Minlc)))
+ addvarint(ctxt, dst, 0) // terminator
+ }
+
+ if ctxt.Debugpcln != 0 {
+ fmt.Fprintf(ctxt.Bso, "wrote %d bytes to %p\n", len(dst.P), dst)
+ for i = 0; i < len(dst.P); i++ {
+ fmt.Fprintf(ctxt.Bso, " %02x", dst.P[i])
+ }
+ fmt.Fprintf(ctxt.Bso, "\n")
+ }
+
+ ctxt.Debugpcln -= int32(dbg)
+}
+
+// pctofileline computes either the file number (arg == 0)
+// or the line number (arg == 1) to use at p.
+// Because p->lineno applies to p, phase == 0 (before p)
+// takes care of the update.
+func pctofileline(ctxt *Link, sym *LSym, oldval int32, p *Prog, phase int32, arg interface{}) int32 {
+
+ var i int32
+ var l int32
+ var f *LSym
+ var pcln *Pcln
+
+ if int(p.As) == ctxt.Arch.ATEXT || int(p.As) == ctxt.Arch.ANOP || int(p.As) == ctxt.Arch.AUSEFIELD || p.Lineno == 0 || phase == 1 {
+ return oldval
+ }
+ linkgetline(ctxt, p.Lineno, &f, &l)
+ if f == nil {
+ // print("getline failed for %s %P\n", ctxt->cursym->name, p);
+ return oldval
+ }
+
+ if arg == nil {
+ return l
+ }
+ pcln = arg.(*Pcln)
+
+ if f == pcln.Lastfile {
+ return int32(pcln.Lastindex)
+ }
+
+ for i = 0; i < int32(len(pcln.File)); i++ {
+ file := pcln.File[i]
+ if file == f {
+ pcln.Lastfile = f
+ pcln.Lastindex = int(i)
+ return int32(i)
+ }
+ }
+ pcln.File = append(pcln.File, f)
+ pcln.Lastfile = f
+ pcln.Lastindex = int(i)
+ return i
+}
+
+// pctospadj computes the sp adjustment in effect.
+// It is oldval plus any adjustment made by p itself.
+// The adjustment by p takes effect only after p, so we
+// apply the change during phase == 1.
+func pctospadj(ctxt *Link, sym *LSym, oldval int32, p *Prog, phase int32, arg interface{}) int32 {
+
+ if oldval == -1 { // starting
+ oldval = 0
+ }
+ if phase == 0 {
+ return oldval
+ }
+ if oldval+p.Spadj < -10000 || oldval+p.Spadj > 1100000000 {
+ ctxt.Diag("overflow in spadj: %d + %d = %d", oldval, p.Spadj, oldval+p.Spadj)
+ log.Fatalf("bad code")
+ }
+
+ return oldval + p.Spadj
+}
+
+// pctopcdata computes the pcdata value in effect at p.
+// A PCDATA instruction sets the value in effect at future
+// non-PCDATA instructions.
+// Since PCDATA instructions have no width in the final code,
+// it does not matter which phase we use for the update.
+func pctopcdata(ctxt *Link, sym *LSym, oldval int32, p *Prog, phase int32, arg interface{}) int32 {
+
+ if phase == 0 || int(p.As) != ctxt.Arch.APCDATA || p.From.Offset != int64(arg.(uint32)) {
+ return oldval
+ }
+ if int64(int32(p.To.Offset)) != p.To.Offset {
+ ctxt.Diag("overflow in PCDATA instruction: %v", p)
+ log.Fatalf("bad code")
+ }
+
+ return int32(p.To.Offset)
+}
+
+func linkpcln(ctxt *Link, cursym *LSym) {
+ var p *Prog
+ var pcln *Pcln
+ var i int
+ var npcdata int
+ var nfuncdata int
+
+ ctxt.Cursym = cursym
+
+ pcln = new(Pcln)
+ cursym.Pcln = pcln
+
+ npcdata = 0
+ nfuncdata = 0
+ for p = cursym.Text; p != nil; p = p.Link {
+ if int(p.As) == ctxt.Arch.APCDATA && p.From.Offset >= int64(npcdata) {
+ npcdata = int(p.From.Offset + 1)
+ }
+ if int(p.As) == ctxt.Arch.AFUNCDATA && p.From.Offset >= int64(nfuncdata) {
+ nfuncdata = int(p.From.Offset + 1)
+ }
+ }
+
+ pcln.Pcdata = make([]Pcdata, npcdata)
+ pcln.Pcdata = pcln.Pcdata[:npcdata]
+ pcln.Funcdata = make([]*LSym, nfuncdata)
+ pcln.Funcdataoff = make([]int64, nfuncdata)
+ pcln.Funcdataoff = pcln.Funcdataoff[:nfuncdata]
+
+ funcpctab(ctxt, &pcln.Pcsp, cursym, "pctospadj", pctospadj, nil)
+ funcpctab(ctxt, &pcln.Pcfile, cursym, "pctofile", pctofileline, pcln)
+ funcpctab(ctxt, &pcln.Pcline, cursym, "pctoline", pctofileline, nil)
+
+ // tabulate which pc and func data we have.
+ havepc := make([]uint32, (npcdata+31)/32)
+ havefunc := make([]uint32, (nfuncdata+31)/32)
+ for p = cursym.Text; p != nil; p = p.Link {
+ if int(p.As) == ctxt.Arch.AFUNCDATA {
+ if (havefunc[p.From.Offset/32]>>uint64(p.From.Offset%32))&1 != 0 {
+ ctxt.Diag("multiple definitions for FUNCDATA $%d", p.From.Offset)
+ }
+ havefunc[p.From.Offset/32] |= 1 << uint64(p.From.Offset%32)
+ }
+
+ if int(p.As) == ctxt.Arch.APCDATA {
+ havepc[p.From.Offset/32] |= 1 << uint64(p.From.Offset%32)
+ }
+ }
+
+ // pcdata.
+ for i = 0; i < npcdata; i++ {
+
+ if (havepc[i/32]>>uint(i%32))&1 == 0 {
+ continue
+ }
+ funcpctab(ctxt, &pcln.Pcdata[i], cursym, "pctopcdata", pctopcdata, interface{}(uint32(i)))
+ }
+
+ // funcdata
+ if nfuncdata > 0 {
+
+ for p = cursym.Text; p != nil; p = p.Link {
+ if int(p.As) == ctxt.Arch.AFUNCDATA {
+ i = int(p.From.Offset)
+ pcln.Funcdataoff[i] = p.To.Offset
+ if int(p.To.Type) != ctxt.Arch.D_CONST {
+ // TODO: Dedup.
+ //funcdata_bytes += p->to.sym->size;
+ pcln.Funcdata[i] = p.To.Sym
+ }
+ }
+ }
+ }
+}
+
+// iteration over encoded pcdata tables.
+
+func getvarint(pp *[]byte) uint32 {
+
+ var p []byte
+ var shift int
+ var v uint32
+
+ v = 0
+ p = *pp
+ for shift = 0; ; shift += 7 {
+ v |= uint32(p[0]&0x7F) << uint(shift)
+ tmp7 := p
+ p = p[1:]
+ if !(tmp7[0]&0x80 != 0) {
+ break
+ }
+ }
+
+ *pp = p
+ return v
+}
+
+func pciternext(it *Pciter) {
+ var v uint32
+ var dv int32
+
+ it.pc = it.nextpc
+ if it.done != 0 {
+ return
+ }
+ if -cap(it.p) >= -cap(it.d.P[len(it.d.P):]) {
+ it.done = 1
+ return
+ }
+
+ // value delta
+ v = getvarint(&it.p)
+
+ if v == 0 && !(it.start != 0) {
+ it.done = 1
+ return
+ }
+
+ it.start = 0
+ dv = int32(v>>1) ^ (int32(v<<31) >> 31)
+ it.value += dv
+
+ // pc delta
+ v = getvarint(&it.p)
+
+ it.nextpc = it.pc + v*it.pcscale
+}
+
+func pciterinit(ctxt *Link, it *Pciter, d *Pcdata) {
+ it.d = *d
+ it.p = it.d.P
+ it.pc = 0
+ it.nextpc = 0
+ it.value = -1
+ it.start = 1
+ it.done = 0
+ it.pcscale = uint32(ctxt.Arch.Minlc)
+ pciternext(it)
+}
--- /dev/null
+// cmd/9c/9.out.h from Vita Nuova.
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package ppc64
+
+// auto generated by go tool dist
+
+/*
+ * powerpc 64
+ */
+const (
+ NSNAME = 8
+ NSYM = 50
+ NREG = 32
+ NFREG = 32
+)
+
+const (
+ REGZERO = 0
+ REGSP = 1
+ REGSB = 2
+ REGRET = 3
+ REGARG = -1
+ REGRT1 = 3
+ REGRT2 = 4
+ REGMIN = 7
+ REGENV = 11
+ REGTLS = 13
+ REGMAX = 27
+ REGEXT = 30
+ REGG = 30
+ REGTMP = 31
+ FREGRET = 0
+ FREGMIN = 17
+ FREGMAX = 26
+ FREGEXT = 26
+ FREGCVI = 27
+ FREGZERO = 28
+ FREGHALF = 29
+ FREGONE = 30
+ FREGTWO = 31
+)
+
+/*
+ * GENERAL:
+ *
+ * compiler allocates R3 up as temps
+ * compiler allocates register variables R7-R27
+ * compiler allocates external registers R30 down
+ *
+ * compiler allocates register variables F17-F26
+ * compiler allocates external registers F26 down
+ */
+const (
+ BIG = 32768 - 8
+)
+
+const (
+ LABEL = 1 << 0
+ LEAF = 1 << 1
+ FLOAT = 1 << 2
+ BRANCH = 1 << 3
+ LOAD = 1 << 4
+ FCMP = 1 << 5
+ SYNC = 1 << 6
+ LIST = 1 << 7
+ FOLL = 1 << 8
+ NOSCHED = 1 << 9
+)
+
+const (
+ C_NONE = iota
+ C_REG
+ C_FREG
+ C_CREG
+ C_SPR
+ C_ZCON
+ C_SCON
+ C_UCON
+ C_ADDCON
+ C_ANDCON
+ C_LCON
+ C_DCON
+ C_SACON
+ C_SECON
+ C_LACON
+ C_LECON
+ C_DACON
+ C_SBRA
+ C_LBRA
+ C_SAUTO
+ C_LAUTO
+ C_SEXT
+ C_LEXT
+ C_ZOREG
+ C_SOREG
+ C_LOREG
+ C_FPSCR
+ C_MSR
+ C_XER
+ C_LR
+ C_CTR
+ C_ANY
+ C_GOK
+ C_ADDR
+ C_NCLASS
+)
+
+const (
+ AXXX = iota
+ AADD
+ AADDCC
+ AADDV
+ AADDVCC
+ AADDC
+ AADDCCC
+ AADDCV
+ AADDCVCC
+ AADDME
+ AADDMECC
+ AADDMEVCC
+ AADDMEV
+ AADDE
+ AADDECC
+ AADDEVCC
+ AADDEV
+ AADDZE
+ AADDZECC
+ AADDZEVCC
+ AADDZEV
+ AAND
+ AANDCC
+ AANDN
+ AANDNCC
+ ABC
+ ABCL
+ ABEQ
+ ABGE
+ ABGT
+ ABL
+ ABLE
+ ABLT
+ ABNE
+ ABR
+ ABVC
+ ABVS
+ ACMP
+ ACMPU
+ ACNTLZW
+ ACNTLZWCC
+ ACRAND
+ ACRANDN
+ ACREQV
+ ACRNAND
+ ACRNOR
+ ACROR
+ ACRORN
+ ACRXOR
+ ADIVW
+ ADIVWCC
+ ADIVWVCC
+ ADIVWV
+ ADIVWU
+ ADIVWUCC
+ ADIVWUVCC
+ ADIVWUV
+ AEQV
+ AEQVCC
+ AEXTSB
+ AEXTSBCC
+ AEXTSH
+ AEXTSHCC
+ AFABS
+ AFABSCC
+ AFADD
+ AFADDCC
+ AFADDS
+ AFADDSCC
+ AFCMPO
+ AFCMPU
+ AFCTIW
+ AFCTIWCC
+ AFCTIWZ
+ AFCTIWZCC
+ AFDIV
+ AFDIVCC
+ AFDIVS
+ AFDIVSCC
+ AFMADD
+ AFMADDCC
+ AFMADDS
+ AFMADDSCC
+ AFMOVD
+ AFMOVDCC
+ AFMOVDU
+ AFMOVS
+ AFMOVSU
+ AFMSUB
+ AFMSUBCC
+ AFMSUBS
+ AFMSUBSCC
+ AFMUL
+ AFMULCC
+ AFMULS
+ AFMULSCC
+ AFNABS
+ AFNABSCC
+ AFNEG
+ AFNEGCC
+ AFNMADD
+ AFNMADDCC
+ AFNMADDS
+ AFNMADDSCC
+ AFNMSUB
+ AFNMSUBCC
+ AFNMSUBS
+ AFNMSUBSCC
+ AFRSP
+ AFRSPCC
+ AFSUB
+ AFSUBCC
+ AFSUBS
+ AFSUBSCC
+ AMOVMW
+ ALSW
+ ALWAR
+ AMOVWBR
+ AMOVB
+ AMOVBU
+ AMOVBZ
+ AMOVBZU
+ AMOVH
+ AMOVHBR
+ AMOVHU
+ AMOVHZ
+ AMOVHZU
+ AMOVW
+ AMOVWU
+ AMOVFL
+ AMOVCRFS
+ AMTFSB0
+ AMTFSB0CC
+ AMTFSB1
+ AMTFSB1CC
+ AMULHW
+ AMULHWCC
+ AMULHWU
+ AMULHWUCC
+ AMULLW
+ AMULLWCC
+ AMULLWVCC
+ AMULLWV
+ ANAND
+ ANANDCC
+ ANEG
+ ANEGCC
+ ANEGVCC
+ ANEGV
+ ANOR
+ ANORCC
+ AOR
+ AORCC
+ AORN
+ AORNCC
+ AREM
+ AREMCC
+ AREMV
+ AREMVCC
+ AREMU
+ AREMUCC
+ AREMUV
+ AREMUVCC
+ ARFI
+ ARLWMI
+ ARLWMICC
+ ARLWNM
+ ARLWNMCC
+ ASLW
+ ASLWCC
+ ASRW
+ ASRAW
+ ASRAWCC
+ ASRWCC
+ ASTSW
+ ASTWCCC
+ ASUB
+ ASUBCC
+ ASUBVCC
+ ASUBC
+ ASUBCCC
+ ASUBCV
+ ASUBCVCC
+ ASUBME
+ ASUBMECC
+ ASUBMEVCC
+ ASUBMEV
+ ASUBV
+ ASUBE
+ ASUBECC
+ ASUBEV
+ ASUBEVCC
+ ASUBZE
+ ASUBZECC
+ ASUBZEVCC
+ ASUBZEV
+ ASYNC
+ AXOR
+ AXORCC
+ ADCBF
+ ADCBI
+ ADCBST
+ ADCBT
+ ADCBTST
+ ADCBZ
+ AECIWX
+ AECOWX
+ AEIEIO
+ AICBI
+ AISYNC
+ APTESYNC
+ ATLBIE
+ ATLBIEL
+ ATLBSYNC
+ ATW
+ ASYSCALL
+ ADATA
+ AGLOBL
+ AGOK
+ AHISTORY
+ ANAME
+ ANOP
+ ARETURN
+ ATEXT
+ AWORD
+ AEND
+ ADYNT
+ AINIT
+ ASIGNAME
+ ARFCI
+ AFRES
+ AFRESCC
+ AFRSQRTE
+ AFRSQRTECC
+ AFSEL
+ AFSELCC
+ AFSQRT
+ AFSQRTCC
+ AFSQRTS
+ AFSQRTSCC
+ ACNTLZD
+ ACNTLZDCC
+ ACMPW
+ ACMPWU
+ ADIVD
+ ADIVDCC
+ ADIVDVCC
+ ADIVDV
+ ADIVDU
+ ADIVDUCC
+ ADIVDUVCC
+ ADIVDUV
+ AEXTSW
+ AEXTSWCC
+ AFCFID
+ AFCFIDCC
+ AFCTID
+ AFCTIDCC
+ AFCTIDZ
+ AFCTIDZCC
+ ALDAR
+ AMOVD
+ AMOVDU
+ AMOVWZ
+ AMOVWZU
+ AMULHD
+ AMULHDCC
+ AMULHDU
+ AMULHDUCC
+ AMULLD
+ AMULLDCC
+ AMULLDVCC
+ AMULLDV
+ ARFID
+ ARLDMI
+ ARLDMICC
+ ARLDC
+ ARLDCCC
+ ARLDCR
+ ARLDCRCC
+ ARLDCL
+ ARLDCLCC
+ ASLBIA
+ ASLBIE
+ ASLBMFEE
+ ASLBMFEV
+ ASLBMTE
+ ASLD
+ ASLDCC
+ ASRD
+ ASRAD
+ ASRADCC
+ ASRDCC
+ ASTDCCC
+ ATD
+ ADWORD
+ AREMD
+ AREMDCC
+ AREMDV
+ AREMDVCC
+ AREMDU
+ AREMDUCC
+ AREMDUV
+ AREMDUVCC
+ AHRFID
+ AUNDEF
+ AUSEFIELD
+ ATYPE
+ AFUNCDATA
+ APCDATA
+ ACHECKNIL
+ AVARDEF
+ AVARKILL
+ ADUFFCOPY
+ ADUFFZERO
+ ALAST
+)
+
+/* type/name */
+const (
+ D_GOK = 0 + iota
+ D_NONE
+ D_EXTERN
+ D_STATIC
+ D_AUTO
+ D_PARAM
+ D_BRANCH
+ D_OREG
+ D_CONST
+ D_FCONST
+ D_SCONST
+ D_REG
+ D_FPSCR
+ D_MSR
+ D_FREG
+ D_CREG
+ D_SPR
+ D_OPT
+ D_FILE
+ D_FILE1
+ D_DCR
+ D_DCONST
+ D_ADDR
+ D_LAST
+ D_R0 = 0
+ D_F0 = D_R0 + NREG
+ D_XER = 1
+ D_LR = 8
+ D_CTR = 9
+)
--- /dev/null
+package ppc64
+
+/* and many supervisor level registers */
+
+/*
+ * this is the ranlib header
+ */
+var Anames = []string{
+ "XXX",
+ "ADD",
+ "ADDCC",
+ "ADDV",
+ "ADDVCC",
+ "ADDC",
+ "ADDCCC",
+ "ADDCV",
+ "ADDCVCC",
+ "ADDME",
+ "ADDMECC",
+ "ADDMEVCC",
+ "ADDMEV",
+ "ADDE",
+ "ADDECC",
+ "ADDEVCC",
+ "ADDEV",
+ "ADDZE",
+ "ADDZECC",
+ "ADDZEVCC",
+ "ADDZEV",
+ "AND",
+ "ANDCC",
+ "ANDN",
+ "ANDNCC",
+ "BC",
+ "BCL",
+ "BEQ",
+ "BGE",
+ "BGT",
+ "BL",
+ "BLE",
+ "BLT",
+ "BNE",
+ "BR",
+ "BVC",
+ "BVS",
+ "CMP",
+ "CMPU",
+ "CNTLZW",
+ "CNTLZWCC",
+ "CRAND",
+ "CRANDN",
+ "CREQV",
+ "CRNAND",
+ "CRNOR",
+ "CROR",
+ "CRORN",
+ "CRXOR",
+ "DIVW",
+ "DIVWCC",
+ "DIVWVCC",
+ "DIVWV",
+ "DIVWU",
+ "DIVWUCC",
+ "DIVWUVCC",
+ "DIVWUV",
+ "EQV",
+ "EQVCC",
+ "EXTSB",
+ "EXTSBCC",
+ "EXTSH",
+ "EXTSHCC",
+ "FABS",
+ "FABSCC",
+ "FADD",
+ "FADDCC",
+ "FADDS",
+ "FADDSCC",
+ "FCMPO",
+ "FCMPU",
+ "FCTIW",
+ "FCTIWCC",
+ "FCTIWZ",
+ "FCTIWZCC",
+ "FDIV",
+ "FDIVCC",
+ "FDIVS",
+ "FDIVSCC",
+ "FMADD",
+ "FMADDCC",
+ "FMADDS",
+ "FMADDSCC",
+ "FMOVD",
+ "FMOVDCC",
+ "FMOVDU",
+ "FMOVS",
+ "FMOVSU",
+ "FMSUB",
+ "FMSUBCC",
+ "FMSUBS",
+ "FMSUBSCC",
+ "FMUL",
+ "FMULCC",
+ "FMULS",
+ "FMULSCC",
+ "FNABS",
+ "FNABSCC",
+ "FNEG",
+ "FNEGCC",
+ "FNMADD",
+ "FNMADDCC",
+ "FNMADDS",
+ "FNMADDSCC",
+ "FNMSUB",
+ "FNMSUBCC",
+ "FNMSUBS",
+ "FNMSUBSCC",
+ "FRSP",
+ "FRSPCC",
+ "FSUB",
+ "FSUBCC",
+ "FSUBS",
+ "FSUBSCC",
+ "MOVMW",
+ "LSW",
+ "LWAR",
+ "MOVWBR",
+ "MOVB",
+ "MOVBU",
+ "MOVBZ",
+ "MOVBZU",
+ "MOVH",
+ "MOVHBR",
+ "MOVHU",
+ "MOVHZ",
+ "MOVHZU",
+ "MOVW",
+ "MOVWU",
+ "MOVFL",
+ "MOVCRFS",
+ "MTFSB0",
+ "MTFSB0CC",
+ "MTFSB1",
+ "MTFSB1CC",
+ "MULHW",
+ "MULHWCC",
+ "MULHWU",
+ "MULHWUCC",
+ "MULLW",
+ "MULLWCC",
+ "MULLWVCC",
+ "MULLWV",
+ "NAND",
+ "NANDCC",
+ "NEG",
+ "NEGCC",
+ "NEGVCC",
+ "NEGV",
+ "NOR",
+ "NORCC",
+ "OR",
+ "ORCC",
+ "ORN",
+ "ORNCC",
+ "REM",
+ "REMCC",
+ "REMV",
+ "REMVCC",
+ "REMU",
+ "REMUCC",
+ "REMUV",
+ "REMUVCC",
+ "RFI",
+ "RLWMI",
+ "RLWMICC",
+ "RLWNM",
+ "RLWNMCC",
+ "SLW",
+ "SLWCC",
+ "SRW",
+ "SRAW",
+ "SRAWCC",
+ "SRWCC",
+ "STSW",
+ "STWCCC",
+ "SUB",
+ "SUBCC",
+ "SUBVCC",
+ "SUBC",
+ "SUBCCC",
+ "SUBCV",
+ "SUBCVCC",
+ "SUBME",
+ "SUBMECC",
+ "SUBMEVCC",
+ "SUBMEV",
+ "SUBV",
+ "SUBE",
+ "SUBECC",
+ "SUBEV",
+ "SUBEVCC",
+ "SUBZE",
+ "SUBZECC",
+ "SUBZEVCC",
+ "SUBZEV",
+ "SYNC",
+ "XOR",
+ "XORCC",
+ "DCBF",
+ "DCBI",
+ "DCBST",
+ "DCBT",
+ "DCBTST",
+ "DCBZ",
+ "ECIWX",
+ "ECOWX",
+ "EIEIO",
+ "ICBI",
+ "ISYNC",
+ "PTESYNC",
+ "TLBIE",
+ "TLBIEL",
+ "TLBSYNC",
+ "TW",
+ "SYSCALL",
+ "DATA",
+ "GLOBL",
+ "GOK",
+ "HISTORY",
+ "NAME",
+ "NOP",
+ "RETURN",
+ "TEXT",
+ "WORD",
+ "END",
+ "DYNT",
+ "INIT",
+ "SIGNAME",
+ "RFCI",
+ "FRES",
+ "FRESCC",
+ "FRSQRTE",
+ "FRSQRTECC",
+ "FSEL",
+ "FSELCC",
+ "FSQRT",
+ "FSQRTCC",
+ "FSQRTS",
+ "FSQRTSCC",
+ "CNTLZD",
+ "CNTLZDCC",
+ "CMPW",
+ "CMPWU",
+ "DIVD",
+ "DIVDCC",
+ "DIVDVCC",
+ "DIVDV",
+ "DIVDU",
+ "DIVDUCC",
+ "DIVDUVCC",
+ "DIVDUV",
+ "EXTSW",
+ "EXTSWCC",
+ "FCFID",
+ "FCFIDCC",
+ "FCTID",
+ "FCTIDCC",
+ "FCTIDZ",
+ "FCTIDZCC",
+ "LDAR",
+ "MOVD",
+ "MOVDU",
+ "MOVWZ",
+ "MOVWZU",
+ "MULHD",
+ "MULHDCC",
+ "MULHDU",
+ "MULHDUCC",
+ "MULLD",
+ "MULLDCC",
+ "MULLDVCC",
+ "MULLDV",
+ "RFID",
+ "RLDMI",
+ "RLDMICC",
+ "RLDC",
+ "RLDCCC",
+ "RLDCR",
+ "RLDCRCC",
+ "RLDCL",
+ "RLDCLCC",
+ "SLBIA",
+ "SLBIE",
+ "SLBMFEE",
+ "SLBMFEV",
+ "SLBMTE",
+ "SLD",
+ "SLDCC",
+ "SRD",
+ "SRAD",
+ "SRADCC",
+ "SRDCC",
+ "STDCCC",
+ "TD",
+ "DWORD",
+ "REMD",
+ "REMDCC",
+ "REMDV",
+ "REMDVCC",
+ "REMDU",
+ "REMDUCC",
+ "REMDUV",
+ "REMDUVCC",
+ "HRFID",
+ "UNDEF",
+ "USEFIELD",
+ "TYPE",
+ "FUNCDATA",
+ "PCDATA",
+ "CHECKNIL",
+ "VARDEF",
+ "VARKILL",
+ "DUFFCOPY",
+ "DUFFZERO",
+ "LAST",
+}
+
+var cnames9 = []string{
+ "NONE",
+ "REG",
+ "FREG",
+ "CREG",
+ "SPR",
+ "ZCON",
+ "SCON",
+ "UCON",
+ "ADDCON",
+ "ANDCON",
+ "LCON",
+ "DCON",
+ "SACON",
+ "SECON",
+ "LACON",
+ "LECON",
+ "DACON",
+ "SBRA",
+ "LBRA",
+ "SAUTO",
+ "LAUTO",
+ "SEXT",
+ "LEXT",
+ "ZOREG",
+ "SOREG",
+ "LOREG",
+ "FPSCR",
+ "MSR",
+ "XER",
+ "LR",
+ "CTR",
+ "ANY",
+ "GOK",
+ "ADDR",
+ "NCLASS",
+}
+
+var dnames9 = []string{
+ D_GOK: "GOK/R0",
+ D_NONE: "NONE/XER",
+ D_EXTERN: "EXTERN",
+ D_STATIC: "STATIC",
+ D_AUTO: "AUTO",
+ D_PARAM: "PARAM",
+ D_BRANCH: "BRANCH",
+ D_OREG: "OREG",
+ D_CONST: "CONST/LR",
+ D_FCONST: "FCONST/CTR",
+ D_SCONST: "SCONST",
+ D_REG: "REG",
+ D_FPSCR: "FPSCR",
+ D_MSR: "MSR",
+ D_FREG: "FREG",
+ D_CREG: "CREG",
+ D_SPR: "SPR",
+ D_OPT: "OPT",
+ D_FILE: "FILE",
+ D_FILE1: "FILE1",
+ D_DCR: "DCR",
+ D_DCONST: "DCONST",
+ D_ADDR: "ADDR",
+}
--- /dev/null
+// cmd/9l/optab.c, cmd/9l/asmout.c from Vita Nuova.
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package ppc64
+
+import (
+ "cmd/internal/obj"
+ "fmt"
+ "log"
+ "sort"
+)
+
+// Instruction layout.
+
+const (
+ FuncAlign = 8
+)
+
+const (
+ r0iszero = 1
+)
+
+type Optab struct {
+ as int16
+ a1 uint8
+ a2 uint8
+ a3 uint8
+ a4 uint8
+ type_ int8
+ size int8
+ param int8
+}
+
+var optab = []Optab{
+ Optab{ATEXT, C_LEXT, C_NONE, C_NONE, C_LCON, 0, 0, 0},
+ Optab{ATEXT, C_LEXT, C_REG, C_NONE, C_LCON, 0, 0, 0},
+ Optab{ATEXT, C_LEXT, C_NONE, C_LCON, C_LCON, 0, 0, 0},
+ Optab{ATEXT, C_LEXT, C_REG, C_LCON, C_LCON, 0, 0, 0},
+ Optab{ATEXT, C_ADDR, C_NONE, C_NONE, C_LCON, 0, 0, 0},
+ Optab{ATEXT, C_ADDR, C_REG, C_NONE, C_LCON, 0, 0, 0},
+ Optab{ATEXT, C_ADDR, C_NONE, C_LCON, C_LCON, 0, 0, 0},
+ Optab{ATEXT, C_ADDR, C_REG, C_LCON, C_LCON, 0, 0, 0},
+ /* move register */
+ Optab{AMOVD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0},
+ Optab{AMOVB, C_REG, C_NONE, C_NONE, C_REG, 12, 4, 0},
+ Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_REG, 13, 4, 0},
+ Optab{AMOVW, C_REG, C_NONE, C_NONE, C_REG, 12, 4, 0},
+ Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_REG, 13, 4, 0},
+ Optab{AADD, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
+ Optab{AADD, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
+ Optab{AADD, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
+ Optab{AADD, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
+ Optab{AADD, C_UCON, C_REG, C_NONE, C_REG, 20, 4, 0},
+ Optab{AADD, C_UCON, C_NONE, C_NONE, C_REG, 20, 4, 0},
+ Optab{AADD, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
+ Optab{AADD, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
+ Optab{AADDC, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
+ Optab{AADDC, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
+ Optab{AADDC, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
+ Optab{AADDC, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
+ Optab{AADDC, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
+ Optab{AADDC, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
+ Optab{AAND, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, /* logical, no literal */
+ Optab{AAND, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+ Optab{AANDCC, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
+ Optab{AANDCC, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+ Optab{AANDCC, C_ANDCON, C_NONE, C_NONE, C_REG, 58, 4, 0},
+ Optab{AANDCC, C_ANDCON, C_REG, C_NONE, C_REG, 58, 4, 0},
+ Optab{AANDCC, C_UCON, C_NONE, C_NONE, C_REG, 59, 4, 0},
+ Optab{AANDCC, C_UCON, C_REG, C_NONE, C_REG, 59, 4, 0},
+ Optab{AANDCC, C_LCON, C_NONE, C_NONE, C_REG, 23, 12, 0},
+ Optab{AANDCC, C_LCON, C_REG, C_NONE, C_REG, 23, 12, 0},
+ Optab{AMULLW, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
+ Optab{AMULLW, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
+ Optab{AMULLW, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
+ Optab{AMULLW, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
+ Optab{AMULLW, C_ANDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
+ Optab{AMULLW, C_ANDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
+ Optab{AMULLW, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
+ Optab{AMULLW, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
+ Optab{ASUBC, C_REG, C_REG, C_NONE, C_REG, 10, 4, 0},
+ Optab{ASUBC, C_REG, C_NONE, C_NONE, C_REG, 10, 4, 0},
+ Optab{ASUBC, C_REG, C_NONE, C_ADDCON, C_REG, 27, 4, 0},
+ Optab{ASUBC, C_REG, C_NONE, C_LCON, C_REG, 28, 12, 0},
+ Optab{AOR, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, /* logical, literal not cc (or/xor) */
+ Optab{AOR, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+ Optab{AOR, C_ANDCON, C_NONE, C_NONE, C_REG, 58, 4, 0},
+ Optab{AOR, C_ANDCON, C_REG, C_NONE, C_REG, 58, 4, 0},
+ Optab{AOR, C_UCON, C_NONE, C_NONE, C_REG, 59, 4, 0},
+ Optab{AOR, C_UCON, C_REG, C_NONE, C_REG, 59, 4, 0},
+ Optab{AOR, C_LCON, C_NONE, C_NONE, C_REG, 23, 12, 0},
+ Optab{AOR, C_LCON, C_REG, C_NONE, C_REG, 23, 12, 0},
+ Optab{ADIVW, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0}, /* op r1[,r2],r3 */
+ Optab{ADIVW, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
+ Optab{ASUB, C_REG, C_REG, C_NONE, C_REG, 10, 4, 0}, /* op r2[,r1],r3 */
+ Optab{ASUB, C_REG, C_NONE, C_NONE, C_REG, 10, 4, 0},
+ Optab{ASLW, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+ Optab{ASLW, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
+ Optab{ASLD, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+ Optab{ASLD, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
+ Optab{ASLD, C_SCON, C_REG, C_NONE, C_REG, 25, 4, 0},
+ Optab{ASLD, C_SCON, C_NONE, C_NONE, C_REG, 25, 4, 0},
+ Optab{ASLW, C_SCON, C_REG, C_NONE, C_REG, 57, 4, 0},
+ Optab{ASLW, C_SCON, C_NONE, C_NONE, C_REG, 57, 4, 0},
+ Optab{ASRAW, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+ Optab{ASRAW, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
+ Optab{ASRAW, C_SCON, C_REG, C_NONE, C_REG, 56, 4, 0},
+ Optab{ASRAW, C_SCON, C_NONE, C_NONE, C_REG, 56, 4, 0},
+ Optab{ASRAD, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+ Optab{ASRAD, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
+ Optab{ASRAD, C_SCON, C_REG, C_NONE, C_REG, 56, 4, 0},
+ Optab{ASRAD, C_SCON, C_NONE, C_NONE, C_REG, 56, 4, 0},
+ Optab{ARLWMI, C_SCON, C_REG, C_LCON, C_REG, 62, 4, 0},
+ Optab{ARLWMI, C_REG, C_REG, C_LCON, C_REG, 63, 4, 0},
+ Optab{ARLDMI, C_SCON, C_REG, C_LCON, C_REG, 30, 4, 0},
+ Optab{ARLDC, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0},
+ Optab{ARLDCL, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0},
+ Optab{ARLDCL, C_REG, C_REG, C_LCON, C_REG, 14, 4, 0},
+ Optab{ARLDCL, C_REG, C_NONE, C_LCON, C_REG, 14, 4, 0},
+ Optab{AFADD, C_FREG, C_NONE, C_NONE, C_FREG, 2, 4, 0},
+ Optab{AFADD, C_FREG, C_REG, C_NONE, C_FREG, 2, 4, 0},
+ Optab{AFABS, C_FREG, C_NONE, C_NONE, C_FREG, 33, 4, 0},
+ Optab{AFABS, C_NONE, C_NONE, C_NONE, C_FREG, 33, 4, 0},
+ Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 33, 4, 0},
+ Optab{AFMADD, C_FREG, C_REG, C_FREG, C_FREG, 34, 4, 0},
+ Optab{AFMUL, C_FREG, C_NONE, C_NONE, C_FREG, 32, 4, 0},
+ Optab{AFMUL, C_FREG, C_REG, C_NONE, C_FREG, 32, 4, 0},
+
+ /* store, short offset */
+ Optab{AMOVD, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+ Optab{AMOVW, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+ Optab{AMOVWZ, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+ Optab{AMOVBZ, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+ Optab{AMOVBZU, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+ Optab{AMOVB, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+ Optab{AMOVBU, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+ Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
+ Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
+ Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
+ Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
+ Optab{AMOVB, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
+ Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
+ Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
+ Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
+ Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
+ Optab{AMOVB, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
+ Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+ Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+ Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+ Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+ Optab{AMOVBZU, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+ Optab{AMOVB, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+ Optab{AMOVBU, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+
+ /* load, short offset */
+ Optab{AMOVD, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
+ Optab{AMOVW, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
+ Optab{AMOVWZ, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
+ Optab{AMOVBZ, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
+ Optab{AMOVBZU, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
+ Optab{AMOVB, C_ZOREG, C_REG, C_NONE, C_REG, 9, 8, REGZERO},
+ Optab{AMOVBU, C_ZOREG, C_REG, C_NONE, C_REG, 9, 8, REGZERO},
+ Optab{AMOVD, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
+ Optab{AMOVW, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
+ Optab{AMOVWZ, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
+ Optab{AMOVBZ, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
+ Optab{AMOVB, C_SEXT, C_NONE, C_NONE, C_REG, 9, 8, REGSB},
+ Optab{AMOVD, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
+ Optab{AMOVW, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
+ Optab{AMOVWZ, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
+ Optab{AMOVBZ, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
+ Optab{AMOVB, C_SAUTO, C_NONE, C_NONE, C_REG, 9, 8, REGSP},
+ Optab{AMOVD, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
+ Optab{AMOVW, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
+ Optab{AMOVWZ, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
+ Optab{AMOVBZ, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
+ Optab{AMOVBZU, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
+ Optab{AMOVB, C_SOREG, C_NONE, C_NONE, C_REG, 9, 8, REGZERO},
+ Optab{AMOVBU, C_SOREG, C_NONE, C_NONE, C_REG, 9, 8, REGZERO},
+
+ /* store, long offset */
+ Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
+ Optab{AMOVW, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
+ Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
+ Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
+ Optab{AMOVB, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
+ Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
+ Optab{AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
+ Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
+ Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
+ Optab{AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
+ Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
+ Optab{AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
+ Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
+ Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
+ Optab{AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
+ Optab{AMOVD, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
+ Optab{AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
+ Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
+ Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
+ Optab{AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
+
+ /* load, long offset */
+ Optab{AMOVD, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
+ Optab{AMOVW, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
+ Optab{AMOVWZ, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
+ Optab{AMOVBZ, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
+ Optab{AMOVB, C_LEXT, C_NONE, C_NONE, C_REG, 37, 12, REGSB},
+ Optab{AMOVD, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
+ Optab{AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
+ Optab{AMOVWZ, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
+ Optab{AMOVBZ, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
+ Optab{AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, 37, 12, REGSP},
+ Optab{AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
+ Optab{AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
+ Optab{AMOVWZ, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
+ Optab{AMOVBZ, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
+ Optab{AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 37, 12, REGZERO},
+ Optab{AMOVD, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
+ Optab{AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
+ Optab{AMOVWZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
+ Optab{AMOVBZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
+ Optab{AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 76, 12, 0},
+
+ /* load constant */
+ Optab{AMOVD, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB},
+ Optab{AMOVD, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
+ Optab{AMOVD, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
+ Optab{AMOVD, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
+ Optab{AMOVD, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
+ Optab{AMOVW, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB}, /* TO DO: check */
+ Optab{AMOVW, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
+ Optab{AMOVW, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
+ Optab{AMOVW, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
+ Optab{AMOVW, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
+ Optab{AMOVWZ, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB}, /* TO DO: check */
+ Optab{AMOVWZ, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
+ Optab{AMOVWZ, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
+ Optab{AMOVWZ, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
+ Optab{AMOVWZ, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
+
+ /* load unsigned/long constants (TO DO: check) */
+ Optab{AMOVD, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
+ Optab{AMOVD, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
+ Optab{AMOVW, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
+ Optab{AMOVW, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
+ Optab{AMOVWZ, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
+ Optab{AMOVWZ, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
+ Optab{AMOVHBR, C_ZOREG, C_REG, C_NONE, C_REG, 45, 4, 0},
+ Optab{AMOVHBR, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
+ Optab{AMOVHBR, C_REG, C_REG, C_NONE, C_ZOREG, 44, 4, 0},
+ Optab{AMOVHBR, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
+ Optab{ASYSCALL, C_NONE, C_NONE, C_NONE, C_NONE, 5, 4, 0},
+ Optab{ASYSCALL, C_REG, C_NONE, C_NONE, C_NONE, 77, 12, 0},
+ Optab{ASYSCALL, C_SCON, C_NONE, C_NONE, C_NONE, 77, 12, 0},
+ Optab{ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, 16, 4, 0},
+ Optab{ABEQ, C_CREG, C_NONE, C_NONE, C_SBRA, 16, 4, 0},
+ Optab{ABR, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0},
+ Optab{ABC, C_SCON, C_REG, C_NONE, C_SBRA, 16, 4, 0},
+ Optab{ABC, C_SCON, C_REG, C_NONE, C_LBRA, 17, 4, 0},
+ Optab{ABR, C_NONE, C_NONE, C_NONE, C_LR, 18, 4, 0},
+ Optab{ABR, C_NONE, C_NONE, C_NONE, C_CTR, 18, 4, 0},
+ Optab{ABR, C_REG, C_NONE, C_NONE, C_CTR, 18, 4, 0},
+ Optab{ABR, C_NONE, C_NONE, C_NONE, C_ZOREG, 15, 8, 0},
+ Optab{ABC, C_NONE, C_REG, C_NONE, C_LR, 18, 4, 0},
+ Optab{ABC, C_NONE, C_REG, C_NONE, C_CTR, 18, 4, 0},
+ Optab{ABC, C_SCON, C_REG, C_NONE, C_LR, 18, 4, 0},
+ Optab{ABC, C_SCON, C_REG, C_NONE, C_CTR, 18, 4, 0},
+ Optab{ABC, C_NONE, C_NONE, C_NONE, C_ZOREG, 15, 8, 0},
+ Optab{AFMOVD, C_SEXT, C_NONE, C_NONE, C_FREG, 8, 4, REGSB},
+ Optab{AFMOVD, C_SAUTO, C_NONE, C_NONE, C_FREG, 8, 4, REGSP},
+ Optab{AFMOVD, C_SOREG, C_NONE, C_NONE, C_FREG, 8, 4, REGZERO},
+ Optab{AFMOVD, C_LEXT, C_NONE, C_NONE, C_FREG, 36, 8, REGSB},
+ Optab{AFMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, 36, 8, REGSP},
+ Optab{AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 36, 8, REGZERO},
+ Optab{AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, 75, 8, 0},
+ Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
+ Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
+ Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+ Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
+ Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
+ Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
+ Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
+ Optab{ASYNC, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0},
+ Optab{AWORD, C_LCON, C_NONE, C_NONE, C_NONE, 40, 4, 0},
+ Optab{ADWORD, C_LCON, C_NONE, C_NONE, C_NONE, 31, 8, 0},
+ Optab{ADWORD, C_DCON, C_NONE, C_NONE, C_NONE, 31, 8, 0},
+ Optab{AADDME, C_REG, C_NONE, C_NONE, C_REG, 47, 4, 0},
+ Optab{AEXTSB, C_REG, C_NONE, C_NONE, C_REG, 48, 4, 0},
+ Optab{AEXTSB, C_NONE, C_NONE, C_NONE, C_REG, 48, 4, 0},
+ Optab{ANEG, C_REG, C_NONE, C_NONE, C_REG, 47, 4, 0},
+ Optab{ANEG, C_NONE, C_NONE, C_NONE, C_REG, 47, 4, 0},
+ Optab{AREM, C_REG, C_NONE, C_NONE, C_REG, 50, 12, 0},
+ Optab{AREM, C_REG, C_REG, C_NONE, C_REG, 50, 12, 0},
+ Optab{AREMU, C_REG, C_NONE, C_NONE, C_REG, 50, 16, 0},
+ Optab{AREMU, C_REG, C_REG, C_NONE, C_REG, 50, 16, 0},
+ Optab{AREMD, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0},
+ Optab{AREMD, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0},
+ Optab{AREMDU, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0},
+ Optab{AREMDU, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0},
+ Optab{AMTFSB0, C_SCON, C_NONE, C_NONE, C_NONE, 52, 4, 0},
+ Optab{AMOVFL, C_FPSCR, C_NONE, C_NONE, C_FREG, 53, 4, 0},
+ Optab{AMOVFL, C_FREG, C_NONE, C_NONE, C_FPSCR, 64, 4, 0},
+ Optab{AMOVFL, C_FREG, C_NONE, C_LCON, C_FPSCR, 64, 4, 0},
+ Optab{AMOVFL, C_LCON, C_NONE, C_NONE, C_FPSCR, 65, 4, 0},
+ Optab{AMOVD, C_MSR, C_NONE, C_NONE, C_REG, 54, 4, 0}, /* mfmsr */
+ Optab{AMOVD, C_REG, C_NONE, C_NONE, C_MSR, 54, 4, 0}, /* mtmsrd */
+ Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_MSR, 54, 4, 0}, /* mtmsr */
+
+ /* 64-bit special registers */
+ Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
+ Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LR, 66, 4, 0},
+ Optab{AMOVD, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
+ Optab{AMOVD, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
+ Optab{AMOVD, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
+ Optab{AMOVD, C_LR, C_NONE, C_NONE, C_REG, 66, 4, 0},
+ Optab{AMOVD, C_CTR, C_NONE, C_NONE, C_REG, 66, 4, 0},
+ Optab{AMOVD, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
+
+ /* 32-bit special registers (gloss over sign-extension or not?) */
+ Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
+ Optab{AMOVW, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
+ Optab{AMOVW, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
+ Optab{AMOVW, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
+ Optab{AMOVW, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
+ Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
+ Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
+ Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
+ Optab{AMOVWZ, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
+ Optab{AMOVWZ, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
+ Optab{AMOVFL, C_FPSCR, C_NONE, C_NONE, C_CREG, 73, 4, 0},
+ Optab{AMOVFL, C_CREG, C_NONE, C_NONE, C_CREG, 67, 4, 0},
+ Optab{AMOVW, C_CREG, C_NONE, C_NONE, C_REG, 68, 4, 0},
+ Optab{AMOVWZ, C_CREG, C_NONE, C_NONE, C_REG, 68, 4, 0},
+ Optab{AMOVFL, C_REG, C_NONE, C_LCON, C_CREG, 69, 4, 0},
+ Optab{AMOVFL, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
+ Optab{AMOVW, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
+ Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
+ Optab{ACMP, C_REG, C_NONE, C_NONE, C_REG, 70, 4, 0},
+ Optab{ACMP, C_REG, C_REG, C_NONE, C_REG, 70, 4, 0},
+ Optab{ACMP, C_REG, C_NONE, C_NONE, C_ADDCON, 71, 4, 0},
+ Optab{ACMP, C_REG, C_REG, C_NONE, C_ADDCON, 71, 4, 0},
+ Optab{ACMPU, C_REG, C_NONE, C_NONE, C_REG, 70, 4, 0},
+ Optab{ACMPU, C_REG, C_REG, C_NONE, C_REG, 70, 4, 0},
+ Optab{ACMPU, C_REG, C_NONE, C_NONE, C_ANDCON, 71, 4, 0},
+ Optab{ACMPU, C_REG, C_REG, C_NONE, C_ANDCON, 71, 4, 0},
+ Optab{AFCMPO, C_FREG, C_NONE, C_NONE, C_FREG, 70, 4, 0},
+ Optab{AFCMPO, C_FREG, C_REG, C_NONE, C_FREG, 70, 4, 0},
+ Optab{ATW, C_LCON, C_REG, C_NONE, C_REG, 60, 4, 0},
+ Optab{ATW, C_LCON, C_REG, C_NONE, C_ADDCON, 61, 4, 0},
+ Optab{ADCBF, C_ZOREG, C_NONE, C_NONE, C_NONE, 43, 4, 0},
+ Optab{ADCBF, C_ZOREG, C_REG, C_NONE, C_NONE, 43, 4, 0},
+ Optab{AECOWX, C_REG, C_REG, C_NONE, C_ZOREG, 44, 4, 0},
+ Optab{AECIWX, C_ZOREG, C_REG, C_NONE, C_REG, 45, 4, 0},
+ Optab{AECOWX, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
+ Optab{AECIWX, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
+ Optab{AEIEIO, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0},
+ Optab{ATLBIE, C_REG, C_NONE, C_NONE, C_NONE, 49, 4, 0},
+ Optab{ATLBIE, C_SCON, C_NONE, C_NONE, C_REG, 49, 4, 0},
+ Optab{ASLBMFEE, C_REG, C_NONE, C_NONE, C_REG, 55, 4, 0},
+ Optab{ASLBMTE, C_REG, C_NONE, C_NONE, C_REG, 55, 4, 0},
+ Optab{ASTSW, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
+ Optab{ASTSW, C_REG, C_NONE, C_LCON, C_ZOREG, 41, 4, 0},
+ Optab{ALSW, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
+ Optab{ALSW, C_ZOREG, C_NONE, C_LCON, C_REG, 42, 4, 0},
+ Optab{AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 78, 4, 0},
+ Optab{AUSEFIELD, C_ADDR, C_NONE, C_NONE, C_NONE, 0, 0, 0},
+ Optab{APCDATA, C_LCON, C_NONE, C_NONE, C_LCON, 0, 0, 0},
+ Optab{AFUNCDATA, C_SCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0},
+ Optab{ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0},
+ Optab{ADUFFZERO, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as ABR/ABL
+ Optab{ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as ABR/ABL
+
+ Optab{AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0},
+}
+
+type Oprang struct {
+ start []Optab
+ stop []Optab
+}
+
+var oprange [ALAST]Oprang
+
+var xcmp [C_NCLASS][C_NCLASS]uint8
+
+func span9(ctxt *obj.Link, cursym *obj.LSym) {
+ var p *obj.Prog
+ var q *obj.Prog
+ var o *Optab
+ var m int
+ var bflag int
+ var c int64
+ var otxt int64
+ var out [6]uint32
+ var i int32
+ var bp []byte
+
+ p = cursym.Text
+ if p == nil || p.Link == nil { // handle external functions and ELF section symbols
+ return
+ }
+ ctxt.Cursym = cursym
+ ctxt.Autosize = int32(p.To.Offset&0xffffffff) + 8
+
+ if oprange[AANDN].start == nil {
+ buildop(ctxt)
+ }
+
+ c = 0
+ p.Pc = c
+
+ for p = p.Link; p != nil; p = p.Link {
+ ctxt.Curp = p
+ p.Pc = c
+ o = oplook(ctxt, p)
+ m = int(o.size)
+ if m == 0 {
+ if p.As != ANOP && p.As != AFUNCDATA && p.As != APCDATA {
+ ctxt.Diag("zero-width instruction\n%v", p)
+ }
+ continue
+ }
+
+ c += int64(m)
+ }
+
+ cursym.Size = c
+
+ /*
+ * if any procedure is large enough to
+ * generate a large SBRA branch, then
+ * generate extra passes putting branches
+ * around jmps to fix. this is rare.
+ */
+ bflag = 1
+
+ for bflag != 0 {
+ if ctxt.Debugvlog != 0 {
+ fmt.Fprintf(ctxt.Bso, "%5.2f span1\n", obj.Cputime())
+ }
+ bflag = 0
+ c = 0
+ for p = cursym.Text.Link; p != nil; p = p.Link {
+ p.Pc = c
+ o = oplook(ctxt, p)
+
+ // very large conditional branches
+ if (o.type_ == 16 || o.type_ == 17) && p.Pcond != nil {
+
+ otxt = p.Pcond.Pc - c
+ if otxt < -(1<<15)+10 || otxt >= (1<<15)-10 {
+ q = ctxt.NewProg()
+ q.Link = p.Link
+ p.Link = q
+ q.As = ABR
+ q.To.Type = D_BRANCH
+ q.Pcond = p.Pcond
+ p.Pcond = q
+ q = ctxt.NewProg()
+ q.Link = p.Link
+ p.Link = q
+ q.As = ABR
+ q.To.Type = D_BRANCH
+ q.Pcond = q.Link.Link
+
+ //addnop(p->link);
+ //addnop(p);
+ bflag = 1
+ }
+ }
+
+ m = int(o.size)
+ if m == 0 {
+ if p.As != ANOP && p.As != AFUNCDATA && p.As != APCDATA {
+ ctxt.Diag("zero-width instruction\n%v", p)
+ }
+ continue
+ }
+
+ c += int64(m)
+ }
+
+ cursym.Size = c
+ }
+
+ c += -c & (FuncAlign - 1)
+ cursym.Size = c
+
+ /*
+ * lay out the code, emitting code and data relocations.
+ */
+ if ctxt.Tlsg == nil {
+
+ ctxt.Tlsg = obj.Linklookup(ctxt, "runtime.tlsg", 0)
+ }
+
+ obj.Symgrow(ctxt, cursym, cursym.Size)
+
+ bp = cursym.P
+ for p = cursym.Text.Link; p != nil; p = p.Link {
+ ctxt.Pc = p.Pc
+ ctxt.Curp = p
+ o = oplook(ctxt, p)
+ if int(o.size) > 4*len(out) {
+ log.Fatalf("out array in span9 is too small, need at least %d for %v", o.size/4, p)
+ }
+ asmout(ctxt, p, o, out[:])
+ for i = 0; i < int32(o.size/4); i++ {
+ ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
+ bp = bp[4:]
+ }
+ }
+}
+
+func isint32(v int64) int {
+ return bool2int(int64(int32(v)) == v)
+}
+
+func isuint32(v uint64) int {
+ return bool2int(uint64(uint32(v)) == v)
+}
+
+func aclass(ctxt *obj.Link, a *obj.Addr) int {
+ var s *obj.LSym
+
+ switch a.Type {
+ case D_NONE:
+ return C_NONE
+
+ case D_REG:
+ return C_REG
+
+ case D_FREG:
+ return C_FREG
+
+ case D_CREG:
+ return C_CREG
+
+ case D_SPR:
+ if a.Offset == D_LR {
+ return C_LR
+ }
+ if a.Offset == D_XER {
+ return C_XER
+ }
+ if a.Offset == D_CTR {
+ return C_CTR
+ }
+ return C_SPR
+
+ case D_DCR:
+ return C_SPR
+
+ case D_FPSCR:
+ return C_FPSCR
+
+ case D_MSR:
+ return C_MSR
+
+ case D_OREG:
+ switch a.Name {
+ case D_EXTERN,
+ D_STATIC:
+ if a.Sym == nil {
+ break
+ }
+ ctxt.Instoffset = a.Offset
+ if a.Sym != nil { // use relocation
+ return C_ADDR
+ }
+ return C_LEXT
+
+ case D_AUTO:
+ ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
+ if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+ return C_SAUTO
+ }
+ return C_LAUTO
+
+ case D_PARAM:
+ ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8
+ if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+ return C_SAUTO
+ }
+ return C_LAUTO
+
+ case D_NONE:
+ ctxt.Instoffset = a.Offset
+ if ctxt.Instoffset == 0 {
+ return C_ZOREG
+ }
+ if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+ return C_SOREG
+ }
+ return C_LOREG
+ }
+
+ return C_GOK
+
+ case D_OPT:
+ ctxt.Instoffset = a.Offset & 31
+ if a.Name == D_NONE {
+ return C_SCON
+ }
+ return C_GOK
+
+ case D_CONST:
+ switch a.Name {
+ case D_NONE:
+ ctxt.Instoffset = a.Offset
+ if a.Reg != NREG {
+ if -BIG <= ctxt.Instoffset && ctxt.Instoffset <= BIG {
+ return C_SACON
+ }
+ if isint32(ctxt.Instoffset) != 0 {
+ return C_LACON
+ }
+ return C_DACON
+ }
+
+ goto consize
+
+ case D_EXTERN,
+ D_STATIC:
+ s = a.Sym
+ if s == nil {
+ break
+ }
+ if s.Type == obj.SCONST {
+ ctxt.Instoffset = s.Value + a.Offset
+ goto consize
+ }
+
+ ctxt.Instoffset = s.Value + a.Offset
+
+ /* not sure why this barfs */
+ return C_LCON
+
+ case D_AUTO:
+ ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
+ if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+ return C_SACON
+ }
+ return C_LACON
+
+ case D_PARAM:
+ ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8
+ if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+ return C_SACON
+ }
+ return C_LACON
+ }
+
+ return C_GOK
+
+ consize:
+ if ctxt.Instoffset >= 0 {
+ if ctxt.Instoffset == 0 {
+ return C_ZCON
+ }
+ if ctxt.Instoffset <= 0x7fff {
+ return C_SCON
+ }
+ if ctxt.Instoffset <= 0xffff {
+ return C_ANDCON
+ }
+ if ctxt.Instoffset&0xffff == 0 && isuint32(uint64(ctxt.Instoffset)) != 0 { /* && (instoffset & (1<<31)) == 0) */
+ return C_UCON
+ }
+ if isint32(ctxt.Instoffset) != 0 || isuint32(uint64(ctxt.Instoffset)) != 0 {
+ return C_LCON
+ }
+ return C_DCON
+ }
+
+ if ctxt.Instoffset >= -0x8000 {
+ return C_ADDCON
+ }
+ if ctxt.Instoffset&0xffff == 0 && isint32(ctxt.Instoffset) != 0 {
+ return C_UCON
+ }
+ if isint32(ctxt.Instoffset) != 0 {
+ return C_LCON
+ }
+ return C_DCON
+
+ case D_BRANCH:
+ return C_SBRA
+ }
+
+ return C_GOK
+}
+
+func prasm(p *obj.Prog) {
+ fmt.Printf("%v\n", p)
+}
+
+func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
+ var a1 int
+ var a2 int
+ var a3 int
+ var a4 int
+ var r int
+ var c1 []byte
+ var c3 []byte
+ var c4 []byte
+ var o []Optab
+ var e []Optab
+
+ a1 = int(p.Optab)
+ if a1 != 0 {
+ return &optab[a1-1:][0]
+ }
+ a1 = int(p.From.Class)
+ if a1 == 0 {
+ a1 = aclass(ctxt, &p.From) + 1
+ p.From.Class = int8(a1)
+ }
+
+ a1--
+ a3 = int(p.From3.Class)
+ if a3 == 0 {
+ a3 = aclass(ctxt, &p.From3) + 1
+ p.From3.Class = int8(a3)
+ }
+
+ a3--
+ a4 = int(p.To.Class)
+ if a4 == 0 {
+ a4 = aclass(ctxt, &p.To) + 1
+ p.To.Class = int8(a4)
+ }
+
+ a4--
+ a2 = C_NONE
+ if p.Reg != NREG {
+ a2 = C_REG
+ }
+
+ //print("oplook %P %d %d %d %d\n", p, a1, a2, a3, a4);
+ r = int(p.As)
+
+ o = oprange[r].start
+ if o == nil {
+ o = oprange[r].stop /* just generate an error */
+ }
+ e = oprange[r].stop
+ c1 = xcmp[a1][:]
+ c3 = xcmp[a3][:]
+ c4 = xcmp[a4][:]
+ for ; -cap(o) < -cap(e); o = o[1:] {
+ if int(o[0].a2) == a2 {
+ if c1[o[0].a1] != 0 {
+ if c3[o[0].a3] != 0 {
+ if c4[o[0].a4] != 0 {
+ p.Optab = uint16((-cap(o) + cap(optab)) + 1)
+ return &o[0]
+ }
+ }
+ }
+ }
+ }
+
+ ctxt.Diag("illegal combination %v %v %v %v %v", Aconv(int(p.As)), DRconv(a1), DRconv(a2), DRconv(a3), DRconv(a4))
+ prasm(p)
+ if o == nil {
+ o = optab
+ }
+ return &o[0]
+}
+
+func cmp(a int, b int) bool {
+ if a == b {
+ return true
+ }
+ switch a {
+ case C_LCON:
+ if b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON {
+ return true
+ }
+
+ case C_ADDCON:
+ if b == C_ZCON || b == C_SCON {
+ return true
+ }
+
+ case C_ANDCON:
+ if b == C_ZCON || b == C_SCON {
+ return true
+ }
+
+ case C_SPR:
+ if b == C_LR || b == C_XER || b == C_CTR {
+ return true
+ }
+
+ case C_UCON:
+ if b == C_ZCON {
+ return true
+ }
+
+ case C_SCON:
+ if b == C_ZCON {
+ return true
+ }
+
+ case C_LACON:
+ if b == C_SACON {
+ return true
+ }
+
+ case C_LBRA:
+ if b == C_SBRA {
+ return true
+ }
+
+ case C_LEXT:
+ if b == C_SEXT {
+ return true
+ }
+
+ case C_LAUTO:
+ if b == C_SAUTO {
+ return true
+ }
+
+ case C_REG:
+ if b == C_ZCON {
+ return r0iszero != 0 /*TypeKind(100016)*/
+ }
+
+ case C_LOREG:
+ if b == C_ZOREG || b == C_SOREG {
+ return true
+ }
+
+ case C_SOREG:
+ if b == C_ZOREG {
+ return true
+ }
+
+ case C_ANY:
+ return true
+ }
+
+ return false
+}
+
+type ocmp []Optab
+
+func (x ocmp) Len() int {
+ return len(x)
+}
+
+func (x ocmp) Swap(i, j int) {
+ x[i], x[j] = x[j], x[i]
+}
+
+func (x ocmp) Less(i, j int) bool {
+ var p1 *Optab
+ var p2 *Optab
+ var n int
+
+ p1 = &x[i]
+ p2 = &x[j]
+ n = int(p1.as) - int(p2.as)
+ if n != 0 {
+ return n < 0
+ }
+ n = int(p1.a1) - int(p2.a1)
+ if n != 0 {
+ return n < 0
+ }
+ n = int(p1.a2) - int(p2.a2)
+ if n != 0 {
+ return n < 0
+ }
+ n = int(p1.a3) - int(p2.a3)
+ if n != 0 {
+ return n < 0
+ }
+ n = int(p1.a4) - int(p2.a4)
+ if n != 0 {
+ return n < 0
+ }
+ return false
+}
+
+func buildop(ctxt *obj.Link) {
+ var i int
+ var n int
+ var r int
+
+ for i = 0; i < C_NCLASS; i++ {
+ for n = 0; n < C_NCLASS; n++ {
+ if cmp(n, i) {
+ xcmp[i][n] = 1
+ }
+ }
+ }
+ for n = 0; optab[n].as != AXXX; n++ {
+
+ }
+ sort.Sort(ocmp(optab[:n]))
+ for i = 0; i < n; i++ {
+ r = int(optab[i].as)
+ oprange[r].start = optab[i:]
+ for int(optab[i].as) == r {
+ i++
+ }
+ oprange[r].stop = optab[i:]
+ i--
+
+ switch r {
+ default:
+ ctxt.Diag("unknown op in build: %v", Aconv(r))
+ log.Fatalf("bad code")
+
+ case ADCBF: /* unary indexed: op (b+a); op (b) */
+ oprange[ADCBI] = oprange[r]
+
+ oprange[ADCBST] = oprange[r]
+ oprange[ADCBT] = oprange[r]
+ oprange[ADCBTST] = oprange[r]
+ oprange[ADCBZ] = oprange[r]
+ oprange[AICBI] = oprange[r]
+
+ case AECOWX: /* indexed store: op s,(b+a); op s,(b) */
+ oprange[ASTWCCC] = oprange[r]
+
+ oprange[ASTDCCC] = oprange[r]
+
+ case AREM: /* macro */
+ oprange[AREMCC] = oprange[r]
+
+ oprange[AREMV] = oprange[r]
+ oprange[AREMVCC] = oprange[r]
+
+ case AREMU:
+ oprange[AREMU] = oprange[r]
+ oprange[AREMUCC] = oprange[r]
+ oprange[AREMUV] = oprange[r]
+ oprange[AREMUVCC] = oprange[r]
+
+ case AREMD:
+ oprange[AREMDCC] = oprange[r]
+ oprange[AREMDV] = oprange[r]
+ oprange[AREMDVCC] = oprange[r]
+
+ case AREMDU:
+ oprange[AREMDU] = oprange[r]
+ oprange[AREMDUCC] = oprange[r]
+ oprange[AREMDUV] = oprange[r]
+ oprange[AREMDUVCC] = oprange[r]
+
+ case ADIVW: /* op Rb[,Ra],Rd */
+ oprange[AMULHW] = oprange[r]
+
+ oprange[AMULHWCC] = oprange[r]
+ oprange[AMULHWU] = oprange[r]
+ oprange[AMULHWUCC] = oprange[r]
+ oprange[AMULLWCC] = oprange[r]
+ oprange[AMULLWVCC] = oprange[r]
+ oprange[AMULLWV] = oprange[r]
+ oprange[ADIVWCC] = oprange[r]
+ oprange[ADIVWV] = oprange[r]
+ oprange[ADIVWVCC] = oprange[r]
+ oprange[ADIVWU] = oprange[r]
+ oprange[ADIVWUCC] = oprange[r]
+ oprange[ADIVWUV] = oprange[r]
+ oprange[ADIVWUVCC] = oprange[r]
+ oprange[AADDCC] = oprange[r]
+ oprange[AADDCV] = oprange[r]
+ oprange[AADDCVCC] = oprange[r]
+ oprange[AADDV] = oprange[r]
+ oprange[AADDVCC] = oprange[r]
+ oprange[AADDE] = oprange[r]
+ oprange[AADDECC] = oprange[r]
+ oprange[AADDEV] = oprange[r]
+ oprange[AADDEVCC] = oprange[r]
+ oprange[ACRAND] = oprange[r]
+ oprange[ACRANDN] = oprange[r]
+ oprange[ACREQV] = oprange[r]
+ oprange[ACRNAND] = oprange[r]
+ oprange[ACRNOR] = oprange[r]
+ oprange[ACROR] = oprange[r]
+ oprange[ACRORN] = oprange[r]
+ oprange[ACRXOR] = oprange[r]
+ oprange[AMULHD] = oprange[r]
+ oprange[AMULHDCC] = oprange[r]
+ oprange[AMULHDU] = oprange[r]
+ oprange[AMULHDUCC] = oprange[r]
+ oprange[AMULLD] = oprange[r]
+ oprange[AMULLDCC] = oprange[r]
+ oprange[AMULLDVCC] = oprange[r]
+ oprange[AMULLDV] = oprange[r]
+ oprange[ADIVD] = oprange[r]
+ oprange[ADIVDCC] = oprange[r]
+ oprange[ADIVDVCC] = oprange[r]
+ oprange[ADIVDV] = oprange[r]
+ oprange[ADIVDU] = oprange[r]
+ oprange[ADIVDUCC] = oprange[r]
+ oprange[ADIVDUVCC] = oprange[r]
+ oprange[ADIVDUCC] = oprange[r]
+
+ case AMOVBZ: /* lbz, stz, rlwm(r/r), lhz, lha, stz, and x variants */
+ oprange[AMOVH] = oprange[r]
+
+ oprange[AMOVHZ] = oprange[r]
+
+ case AMOVBZU: /* lbz[x]u, stb[x]u, lhz[x]u, lha[x]u, sth[u]x, ld[x]u, std[u]x */
+ oprange[AMOVHU] = oprange[r]
+
+ oprange[AMOVHZU] = oprange[r]
+ oprange[AMOVWU] = oprange[r]
+ oprange[AMOVWZU] = oprange[r]
+ oprange[AMOVDU] = oprange[r]
+ oprange[AMOVMW] = oprange[r]
+
+ case AAND: /* logical op Rb,Rs,Ra; no literal */
+ oprange[AANDN] = oprange[r]
+
+ oprange[AANDNCC] = oprange[r]
+ oprange[AEQV] = oprange[r]
+ oprange[AEQVCC] = oprange[r]
+ oprange[ANAND] = oprange[r]
+ oprange[ANANDCC] = oprange[r]
+ oprange[ANOR] = oprange[r]
+ oprange[ANORCC] = oprange[r]
+ oprange[AORCC] = oprange[r]
+ oprange[AORN] = oprange[r]
+ oprange[AORNCC] = oprange[r]
+ oprange[AXORCC] = oprange[r]
+
+ case AADDME: /* op Ra, Rd */
+ oprange[AADDMECC] = oprange[r]
+
+ oprange[AADDMEV] = oprange[r]
+ oprange[AADDMEVCC] = oprange[r]
+ oprange[AADDZE] = oprange[r]
+ oprange[AADDZECC] = oprange[r]
+ oprange[AADDZEV] = oprange[r]
+ oprange[AADDZEVCC] = oprange[r]
+ oprange[ASUBME] = oprange[r]
+ oprange[ASUBMECC] = oprange[r]
+ oprange[ASUBMEV] = oprange[r]
+ oprange[ASUBMEVCC] = oprange[r]
+ oprange[ASUBZE] = oprange[r]
+ oprange[ASUBZECC] = oprange[r]
+ oprange[ASUBZEV] = oprange[r]
+ oprange[ASUBZEVCC] = oprange[r]
+
+ case AADDC:
+ oprange[AADDCCC] = oprange[r]
+
+ case ABEQ:
+ oprange[ABGE] = oprange[r]
+ oprange[ABGT] = oprange[r]
+ oprange[ABLE] = oprange[r]
+ oprange[ABLT] = oprange[r]
+ oprange[ABNE] = oprange[r]
+ oprange[ABVC] = oprange[r]
+ oprange[ABVS] = oprange[r]
+
+ case ABR:
+ oprange[ABL] = oprange[r]
+
+ case ABC:
+ oprange[ABCL] = oprange[r]
+
+ case AEXTSB: /* op Rs, Ra */
+ oprange[AEXTSBCC] = oprange[r]
+
+ oprange[AEXTSH] = oprange[r]
+ oprange[AEXTSHCC] = oprange[r]
+ oprange[ACNTLZW] = oprange[r]
+ oprange[ACNTLZWCC] = oprange[r]
+ oprange[ACNTLZD] = oprange[r]
+ oprange[AEXTSW] = oprange[r]
+ oprange[AEXTSWCC] = oprange[r]
+ oprange[ACNTLZDCC] = oprange[r]
+
+ case AFABS: /* fop [s,]d */
+ oprange[AFABSCC] = oprange[r]
+
+ oprange[AFNABS] = oprange[r]
+ oprange[AFNABSCC] = oprange[r]
+ oprange[AFNEG] = oprange[r]
+ oprange[AFNEGCC] = oprange[r]
+ oprange[AFRSP] = oprange[r]
+ oprange[AFRSPCC] = oprange[r]
+ oprange[AFCTIW] = oprange[r]
+ oprange[AFCTIWCC] = oprange[r]
+ oprange[AFCTIWZ] = oprange[r]
+ oprange[AFCTIWZCC] = oprange[r]
+ oprange[AFCTID] = oprange[r]
+ oprange[AFCTIDCC] = oprange[r]
+ oprange[AFCTIDZ] = oprange[r]
+ oprange[AFCTIDZCC] = oprange[r]
+ oprange[AFCFID] = oprange[r]
+ oprange[AFCFIDCC] = oprange[r]
+ oprange[AFRES] = oprange[r]
+ oprange[AFRESCC] = oprange[r]
+ oprange[AFRSQRTE] = oprange[r]
+ oprange[AFRSQRTECC] = oprange[r]
+ oprange[AFSQRT] = oprange[r]
+ oprange[AFSQRTCC] = oprange[r]
+ oprange[AFSQRTS] = oprange[r]
+ oprange[AFSQRTSCC] = oprange[r]
+
+ case AFADD:
+ oprange[AFADDS] = oprange[r]
+ oprange[AFADDCC] = oprange[r]
+ oprange[AFADDSCC] = oprange[r]
+ oprange[AFDIV] = oprange[r]
+ oprange[AFDIVS] = oprange[r]
+ oprange[AFDIVCC] = oprange[r]
+ oprange[AFDIVSCC] = oprange[r]
+ oprange[AFSUB] = oprange[r]
+ oprange[AFSUBS] = oprange[r]
+ oprange[AFSUBCC] = oprange[r]
+ oprange[AFSUBSCC] = oprange[r]
+
+ case AFMADD:
+ oprange[AFMADDCC] = oprange[r]
+ oprange[AFMADDS] = oprange[r]
+ oprange[AFMADDSCC] = oprange[r]
+ oprange[AFMSUB] = oprange[r]
+ oprange[AFMSUBCC] = oprange[r]
+ oprange[AFMSUBS] = oprange[r]
+ oprange[AFMSUBSCC] = oprange[r]
+ oprange[AFNMADD] = oprange[r]
+ oprange[AFNMADDCC] = oprange[r]
+ oprange[AFNMADDS] = oprange[r]
+ oprange[AFNMADDSCC] = oprange[r]
+ oprange[AFNMSUB] = oprange[r]
+ oprange[AFNMSUBCC] = oprange[r]
+ oprange[AFNMSUBS] = oprange[r]
+ oprange[AFNMSUBSCC] = oprange[r]
+ oprange[AFSEL] = oprange[r]
+ oprange[AFSELCC] = oprange[r]
+
+ case AFMUL:
+ oprange[AFMULS] = oprange[r]
+ oprange[AFMULCC] = oprange[r]
+ oprange[AFMULSCC] = oprange[r]
+
+ case AFCMPO:
+ oprange[AFCMPU] = oprange[r]
+
+ case AMTFSB0:
+ oprange[AMTFSB0CC] = oprange[r]
+ oprange[AMTFSB1] = oprange[r]
+ oprange[AMTFSB1CC] = oprange[r]
+
+ case ANEG: /* op [Ra,] Rd */
+ oprange[ANEGCC] = oprange[r]
+
+ oprange[ANEGV] = oprange[r]
+ oprange[ANEGVCC] = oprange[r]
+
+ case AOR: /* or/xor Rb,Rs,Ra; ori/xori $uimm,Rs,Ra; oris/xoris $uimm,Rs,Ra */
+ oprange[AXOR] = oprange[r]
+
+ case ASLW:
+ oprange[ASLWCC] = oprange[r]
+ oprange[ASRW] = oprange[r]
+ oprange[ASRWCC] = oprange[r]
+
+ case ASLD:
+ oprange[ASLDCC] = oprange[r]
+ oprange[ASRD] = oprange[r]
+ oprange[ASRDCC] = oprange[r]
+
+ case ASRAW: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
+ oprange[ASRAWCC] = oprange[r]
+
+ case ASRAD: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
+ oprange[ASRADCC] = oprange[r]
+
+ case ASUB: /* SUB Ra,Rb,Rd => subf Rd,ra,rb */
+ oprange[ASUB] = oprange[r]
+
+ oprange[ASUBCC] = oprange[r]
+ oprange[ASUBV] = oprange[r]
+ oprange[ASUBVCC] = oprange[r]
+ oprange[ASUBCCC] = oprange[r]
+ oprange[ASUBCV] = oprange[r]
+ oprange[ASUBCVCC] = oprange[r]
+ oprange[ASUBE] = oprange[r]
+ oprange[ASUBECC] = oprange[r]
+ oprange[ASUBEV] = oprange[r]
+ oprange[ASUBEVCC] = oprange[r]
+
+ case ASYNC:
+ oprange[AISYNC] = oprange[r]
+ oprange[APTESYNC] = oprange[r]
+ oprange[ATLBSYNC] = oprange[r]
+
+ case ARLWMI:
+ oprange[ARLWMICC] = oprange[r]
+ oprange[ARLWNM] = oprange[r]
+ oprange[ARLWNMCC] = oprange[r]
+
+ case ARLDMI:
+ oprange[ARLDMICC] = oprange[r]
+
+ case ARLDC:
+ oprange[ARLDCCC] = oprange[r]
+
+ case ARLDCL:
+ oprange[ARLDCR] = oprange[r]
+ oprange[ARLDCLCC] = oprange[r]
+ oprange[ARLDCRCC] = oprange[r]
+
+ case AFMOVD:
+ oprange[AFMOVDCC] = oprange[r]
+ oprange[AFMOVDU] = oprange[r]
+ oprange[AFMOVS] = oprange[r]
+ oprange[AFMOVSU] = oprange[r]
+
+ case AECIWX:
+ oprange[ALWAR] = oprange[r]
+ oprange[ALDAR] = oprange[r]
+
+ case ASYSCALL: /* just the op; flow of control */
+ oprange[ARFI] = oprange[r]
+
+ oprange[ARFCI] = oprange[r]
+ oprange[ARFID] = oprange[r]
+ oprange[AHRFID] = oprange[r]
+
+ case AMOVHBR:
+ oprange[AMOVWBR] = oprange[r]
+
+ case ASLBMFEE:
+ oprange[ASLBMFEV] = oprange[r]
+
+ case ATW:
+ oprange[ATD] = oprange[r]
+
+ case ATLBIE:
+ oprange[ASLBIE] = oprange[r]
+ oprange[ATLBIEL] = oprange[r]
+
+ case AEIEIO:
+ oprange[ASLBIA] = oprange[r]
+
+ case ACMP:
+ oprange[ACMPW] = oprange[r]
+
+ case ACMPU:
+ oprange[ACMPWU] = oprange[r]
+
+ case AADD,
+ AANDCC, /* and. Rb,Rs,Ra; andi. $uimm,Rs,Ra; andis. $uimm,Rs,Ra */
+ ALSW,
+ AMOVW,
+ /* load/store/move word with sign extension; special 32-bit move; move 32-bit literals */
+ AMOVWZ, /* load/store/move word with zero extension; move 32-bit literals */
+ AMOVD, /* load/store/move 64-bit values, including 32-bit literals with/without sign-extension */
+ AMOVB, /* macro: move byte with sign extension */
+ AMOVBU, /* macro: move byte with sign extension & update */
+ AMOVFL,
+ AMULLW,
+ /* op $s[,r2],r3; op r1[,r2],r3; no cc/v */
+ ASUBC, /* op r1,$s,r3; op r1[,r2],r3 */
+ ASTSW,
+ ASLBMTE,
+ AWORD,
+ ADWORD,
+ ANOP,
+ ATEXT,
+ AUNDEF,
+ AUSEFIELD,
+ AFUNCDATA,
+ APCDATA,
+ ADUFFZERO,
+ ADUFFCOPY:
+ break
+ }
+ }
+}
+
+func OPVCC(o uint32, xo uint32, oe uint32, rc uint32) uint32 {
+ return o<<26 | xo<<1 | oe<<10 | rc&1
+}
+
+func OPCC(o uint32, xo uint32, rc uint32) uint32 {
+ return OPVCC(o, xo, 0, rc)
+}
+
+func OP(o uint32, xo uint32) uint32 {
+ return OPVCC(o, xo, 0, 0)
+}
+
+/* the order is dest, a/s, b/imm for both arithmetic and logical operations */
+func AOP_RRR(op uint32, d uint32, a uint32, b uint32) uint32 {
+
+ return op | (d&31)<<21 | (a&31)<<16 | (b&31)<<11
+}
+
+func AOP_IRR(op uint32, d uint32, a uint32, simm uint32) uint32 {
+ return op | (d&31)<<21 | (a&31)<<16 | simm&0xFFFF
+}
+
+func LOP_RRR(op uint32, a uint32, s uint32, b uint32) uint32 {
+ return op | (s&31)<<21 | (a&31)<<16 | (b&31)<<11
+}
+
+func LOP_IRR(op uint32, a uint32, s uint32, uimm uint32) uint32 {
+ return op | (s&31)<<21 | (a&31)<<16 | uimm&0xFFFF
+}
+
+func OP_BR(op uint32, li uint32, aa uint32) uint32 {
+ return op | li&0x03FFFFFC | aa<<1
+}
+
+func OP_BC(op uint32, bo uint32, bi uint32, bd uint32, aa uint32) uint32 {
+ return op | (bo&0x1F)<<21 | (bi&0x1F)<<16 | bd&0xFFFC | aa<<1
+}
+
+func OP_BCR(op uint32, bo uint32, bi uint32) uint32 {
+ return op | (bo&0x1F)<<21 | (bi&0x1F)<<16
+}
+
+func OP_RLW(op uint32, a uint32, s uint32, sh uint32, mb uint32, me uint32) uint32 {
+ return op | (s&31)<<21 | (a&31)<<16 | (sh&31)<<11 | (mb&31)<<6 | (me&31)<<1
+}
+
+const (
+ OP_ADD = 31<<26 | 266<<1 | 0<<10 | 0
+ OP_ADDI = 14<<26 | 0<<1 | 0<<10 | 0
+ OP_ADDIS = 15<<26 | 0<<1 | 0<<10 | 0
+ OP_ANDI = 28<<26 | 0<<1 | 0<<10 | 0
+ OP_EXTSB = 31<<26 | 954<<1 | 0<<10 | 0
+ OP_EXTSH = 31<<26 | 922<<1 | 0<<10 | 0
+ OP_EXTSW = 31<<26 | 986<<1 | 0<<10 | 0
+ OP_MCRF = 19<<26 | 0<<1 | 0<<10 | 0
+ OP_MCRFS = 63<<26 | 64<<1 | 0<<10 | 0
+ OP_MCRXR = 31<<26 | 512<<1 | 0<<10 | 0
+ OP_MFCR = 31<<26 | 19<<1 | 0<<10 | 0
+ OP_MFFS = 63<<26 | 583<<1 | 0<<10 | 0
+ OP_MFMSR = 31<<26 | 83<<1 | 0<<10 | 0
+ OP_MFSPR = 31<<26 | 339<<1 | 0<<10 | 0
+ OP_MFSR = 31<<26 | 595<<1 | 0<<10 | 0
+ OP_MFSRIN = 31<<26 | 659<<1 | 0<<10 | 0
+ OP_MTCRF = 31<<26 | 144<<1 | 0<<10 | 0
+ OP_MTFSF = 63<<26 | 711<<1 | 0<<10 | 0
+ OP_MTFSFI = 63<<26 | 134<<1 | 0<<10 | 0
+ OP_MTMSR = 31<<26 | 146<<1 | 0<<10 | 0
+ OP_MTMSRD = 31<<26 | 178<<1 | 0<<10 | 0
+ OP_MTSPR = 31<<26 | 467<<1 | 0<<10 | 0
+ OP_MTSR = 31<<26 | 210<<1 | 0<<10 | 0
+ OP_MTSRIN = 31<<26 | 242<<1 | 0<<10 | 0
+ OP_MULLW = 31<<26 | 235<<1 | 0<<10 | 0
+ OP_MULLD = 31<<26 | 233<<1 | 0<<10 | 0
+ OP_OR = 31<<26 | 444<<1 | 0<<10 | 0
+ OP_ORI = 24<<26 | 0<<1 | 0<<10 | 0
+ OP_ORIS = 25<<26 | 0<<1 | 0<<10 | 0
+ OP_RLWINM = 21<<26 | 0<<1 | 0<<10 | 0
+ OP_SUBF = 31<<26 | 40<<1 | 0<<10 | 0
+ OP_RLDIC = 30<<26 | 4<<1 | 0<<10 | 0
+ OP_RLDICR = 30<<26 | 2<<1 | 0<<10 | 0
+ OP_RLDICL = 30<<26 | 0<<1 | 0<<10 | 0
+)
+
+func oclass(a *obj.Addr) int {
+ return int(a.Class) - 1
+}
+
+// add R_ADDRPOWER relocation to symbol s for the two instructions o1 and o2.
+func addaddrreloc(ctxt *obj.Link, s *obj.LSym, o1 *uint32, o2 *uint32) {
+
+ var rel *obj.Reloc
+
+ rel = obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 8
+ rel.Sym = s
+ rel.Add = int64(uint64(*o1)<<32 | uint64(uint32(*o2)))
+ rel.Type = obj.R_ADDRPOWER
+}
+
+/*
+ * 32-bit masks
+ */
+func getmask(m []byte, v uint32) int {
+
+ var i int
+
+ m[1] = 0
+ m[0] = m[1]
+ if v != ^uint32(0) && v&(1<<31) != 0 && v&1 != 0 { /* MB > ME */
+ if getmask(m, ^v) != 0 {
+ i = int(m[0])
+ m[0] = m[1] + 1
+ m[1] = byte(i - 1)
+ return 1
+ }
+
+ return 0
+ }
+
+ for i = 0; i < 32; i++ {
+ if v&(1<<uint(31-i)) != 0 {
+ m[0] = byte(i)
+ for {
+ m[1] = byte(i)
+ i++
+ if !(i < 32 && v&(1<<uint(31-i)) != 0) {
+ break
+ }
+ }
+
+ for ; i < 32; i++ {
+ if v&(1<<uint(31-i)) != 0 {
+ return 0
+ }
+ }
+ return 1
+ }
+ }
+
+ return 0
+}
+
+func maskgen(ctxt *obj.Link, p *obj.Prog, m []byte, v uint32) {
+ if !(getmask(m, v) != 0) {
+ ctxt.Diag("cannot generate mask #%x\n%v", v, p)
+ }
+}
+
+/*
+ * 64-bit masks (rldic etc)
+ */
+func getmask64(m []byte, v uint64) int {
+
+ var i int
+
+ m[1] = 0
+ m[0] = m[1]
+ for i = 0; i < 64; i++ {
+ if v&(uint64(1)<<uint(63-i)) != 0 {
+ m[0] = byte(i)
+ for {
+ m[1] = byte(i)
+ i++
+ if !(i < 64 && v&(uint64(1)<<uint(63-i)) != 0) {
+ break
+ }
+ }
+
+ for ; i < 64; i++ {
+ if v&(uint64(1)<<uint(63-i)) != 0 {
+ return 0
+ }
+ }
+ return 1
+ }
+ }
+
+ return 0
+}
+
+func maskgen64(ctxt *obj.Link, p *obj.Prog, m []byte, v uint64) {
+ if !(getmask64(m, v) != 0) {
+ ctxt.Diag("cannot generate mask #%x\n%v", v, p)
+ }
+}
+
+func loadu32(r int, d int64) uint32 {
+ var v int32
+
+ v = int32(d >> 16)
+ if isuint32(uint64(d)) != 0 {
+ return LOP_IRR(OP_ORIS, uint32(r), REGZERO, uint32(v))
+ }
+ return AOP_IRR(OP_ADDIS, uint32(r), REGZERO, uint32(v))
+}
+
+func high16adjusted(d int32) uint16 {
+ if d&0x8000 != 0 {
+ return uint16((d >> 16) + 1)
+ }
+ return uint16(d >> 16)
+}
+
+func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
+ var o1 uint32
+ var o2 uint32
+ var o3 uint32
+ var o4 uint32
+ var o5 uint32
+ var v int32
+ var t int32
+ var d int64
+ var r int
+ var a int
+ var mask [2]uint8
+ var rel *obj.Reloc
+
+ o1 = 0
+ o2 = 0
+ o3 = 0
+ o4 = 0
+ o5 = 0
+
+ //print("%P => case %d\n", p, o->type);
+ switch o.type_ {
+
+ default:
+ ctxt.Diag("unknown type %d", o.type_)
+ prasm(p)
+
+ case 0: /* pseudo ops */
+ break
+
+ case 1: /* mov r1,r2 ==> OR Rs,Rs,Ra */
+ if p.To.Reg == REGZERO && p.From.Type == D_CONST {
+
+ v = regoff(ctxt, &p.From)
+ if r0iszero != 0 /*TypeKind(100016)*/ && v != 0 {
+ //nerrors--;
+ ctxt.Diag("literal operation on R0\n%v", p)
+ }
+
+ o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, uint32(v))
+ break
+ }
+
+ o1 = LOP_RRR(OP_OR, uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.From.Reg))
+
+ case 2: /* int/cr/fp op Rb,[Ra],Rd */
+ r = int(p.Reg)
+
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+ o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg))
+
+ case 3: /* mov $soreg/addcon/ucon, r ==> addis/addi $i,reg',r */
+ d = vregoff(ctxt, &p.From)
+
+ v = int32(d)
+ r = int(p.From.Reg)
+ if r == NREG {
+ r = int(o.param)
+ }
+ if r0iszero != 0 /*TypeKind(100016)*/ && p.To.Reg == 0 && (r != 0 || v != 0) {
+ ctxt.Diag("literal operation on R0\n%v", p)
+ }
+ a = OP_ADDI
+ if o.a1 == C_UCON {
+ if d&0xffff != 0 {
+ log.Fatalf("invalid handling of %v", p)
+ }
+ v >>= 16
+ if r == REGZERO && isuint32(uint64(d)) != 0 {
+ o1 = LOP_IRR(OP_ORIS, uint32(p.To.Reg), REGZERO, uint32(v))
+ break
+ }
+
+ a = OP_ADDIS
+ } else {
+
+ if int64(int16(d)) != d {
+ log.Fatalf("invalid handling of %v", p)
+ }
+ }
+
+ o1 = AOP_IRR(uint32(a), uint32(p.To.Reg), uint32(r), uint32(v))
+
+ case 4: /* add/mul $scon,[r1],r2 */
+ v = regoff(ctxt, &p.From)
+
+ r = int(p.Reg)
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+ if r0iszero != 0 /*TypeKind(100016)*/ && p.To.Reg == 0 {
+ ctxt.Diag("literal operation on R0\n%v", p)
+ }
+ if int32(int16(v)) != v {
+ log.Fatalf("mishandled instruction %v", p)
+ }
+ o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
+
+ case 5: /* syscall */
+ o1 = uint32(oprrr(ctxt, int(p.As)))
+
+ case 6: /* logical op Rb,[Rs,]Ra; no literal */
+ r = int(p.Reg)
+
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+ o1 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg))
+
+ case 7: /* mov r, soreg ==> stw o(r) */
+ r = int(p.To.Reg)
+
+ if r == NREG {
+ r = int(o.param)
+ }
+ v = regoff(ctxt, &p.To)
+ if p.To.Type == D_OREG && p.Reg != NREG {
+ if v != 0 {
+ ctxt.Diag("illegal indexed instruction\n%v", p)
+ }
+ o1 = AOP_RRR(uint32(opstorex(ctxt, int(p.As))), uint32(p.From.Reg), uint32(p.Reg), uint32(r))
+ } else {
+
+ if int32(int16(v)) != v {
+ log.Fatalf("mishandled instruction %v", p)
+ }
+ o1 = AOP_IRR(uint32(opstore(ctxt, int(p.As))), uint32(p.From.Reg), uint32(r), uint32(v))
+ }
+
+ case 8: /* mov soreg, r ==> lbz/lhz/lwz o(r) */
+ r = int(p.From.Reg)
+
+ if r == NREG {
+ r = int(o.param)
+ }
+ v = regoff(ctxt, &p.From)
+ if p.From.Type == D_OREG && p.Reg != NREG {
+ if v != 0 {
+ ctxt.Diag("illegal indexed instruction\n%v", p)
+ }
+ o1 = AOP_RRR(uint32(oploadx(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.Reg), uint32(r))
+ } else {
+
+ if int32(int16(v)) != v {
+ log.Fatalf("mishandled instruction %v", p)
+ }
+ o1 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
+ }
+
+ case 9: /* movb soreg, r ==> lbz o(r),r2; extsb r2,r2 */
+ r = int(p.From.Reg)
+
+ if r == NREG {
+ r = int(o.param)
+ }
+ v = regoff(ctxt, &p.From)
+ if p.From.Type == D_OREG && p.Reg != NREG {
+ if v != 0 {
+ ctxt.Diag("illegal indexed instruction\n%v", p)
+ }
+ o1 = AOP_RRR(uint32(oploadx(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.Reg), uint32(r))
+ } else {
+
+ o1 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
+ }
+ o2 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
+
+ case 10: /* sub Ra,[Rb],Rd => subf Rd,Ra,Rb */
+ r = int(p.Reg)
+
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+ o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), uint32(r))
+
+ case 11: /* br/bl lbra */
+ v = 0
+
+ if p.Pcond != nil {
+ v = int32(p.Pcond.Pc - p.Pc)
+ if v&03 != 0 {
+ ctxt.Diag("odd branch target address\n%v", p)
+ v &^= 03
+ }
+
+ if v < -(1<<25) || v >= 1<<24 {
+ ctxt.Diag("branch too far\n%v", p)
+ }
+ }
+
+ o1 = OP_BR(uint32(opirr(ctxt, int(p.As))), uint32(v), 0)
+ if p.To.Sym != nil {
+ rel = obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 4
+ rel.Sym = p.To.Sym
+ v += int32(p.To.Offset)
+ if v&03 != 0 {
+ ctxt.Diag("odd branch target address\n%v", p)
+ v &^= 03
+ }
+
+ rel.Add = int64(v)
+ rel.Type = obj.R_CALLPOWER
+ }
+
+ case 12: /* movb r,r (extsb); movw r,r (extsw) */
+ if p.To.Reg == REGZERO && p.From.Type == D_CONST {
+
+ v = regoff(ctxt, &p.From)
+ if r0iszero != 0 /*TypeKind(100016)*/ && v != 0 {
+ ctxt.Diag("literal operation on R0\n%v", p)
+ }
+
+ o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, uint32(v))
+ break
+ }
+
+ if p.As == AMOVW {
+ o1 = LOP_RRR(OP_EXTSW, uint32(p.To.Reg), uint32(p.From.Reg), 0)
+ } else {
+
+ o1 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.From.Reg), 0)
+ }
+
+ case 13: /* mov[bhw]z r,r; uses rlwinm not andi. to avoid changing CC */
+ if p.As == AMOVBZ {
+
+ o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(p.From.Reg), 0, 24, 31)
+ } else if p.As == AMOVH {
+ o1 = LOP_RRR(OP_EXTSH, uint32(p.To.Reg), uint32(p.From.Reg), 0)
+ } else if p.As == AMOVHZ {
+ o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(p.From.Reg), 0, 16, 31)
+ } else if p.As == AMOVWZ {
+ o1 = OP_RLW(OP_RLDIC, uint32(p.To.Reg), uint32(p.From.Reg), 0, 0, 0) | 1<<5 /* MB=32 */
+ } else {
+
+ ctxt.Diag("internal: bad mov[bhw]z\n%v", p)
+ }
+
+ case 14: /* rldc[lr] Rb,Rs,$mask,Ra -- left, right give different masks */
+ r = int(p.Reg)
+
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+ d = vregoff(ctxt, &p.From3)
+ maskgen64(ctxt, p, mask[:], uint64(d))
+ switch p.As {
+ case ARLDCL,
+ ARLDCLCC:
+ a = int(mask[0]) /* MB */
+ if mask[1] != 63 {
+ ctxt.Diag("invalid mask for rotate: %x (end != bit 63)\n%v", uint64(d), p)
+ }
+
+ case ARLDCR,
+ ARLDCRCC:
+ a = int(mask[1]) /* ME */
+ if mask[0] != 0 {
+ ctxt.Diag("invalid mask for rotate: %x (start != 0)\n%v", uint64(d), p)
+ }
+
+ default:
+ ctxt.Diag("unexpected op in rldc case\n%v", p)
+ a = 0
+ }
+
+ o1 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg))
+ o1 |= (uint32(a) & 31) << 6
+ if a&0x20 != 0 {
+ o1 |= 1 << 5 /* mb[5] is top bit */
+ }
+
+ case 17, /* bc bo,bi,lbra (same for now) */
+ 16: /* bc bo,bi,sbra */
+ a = 0
+
+ if p.From.Type == D_CONST {
+ a = int(regoff(ctxt, &p.From))
+ }
+ r = int(p.Reg)
+ if r == NREG {
+ r = 0
+ }
+ v = 0
+ if p.Pcond != nil {
+ v = int32(p.Pcond.Pc - p.Pc)
+ }
+ if v&03 != 0 {
+ ctxt.Diag("odd branch target address\n%v", p)
+ v &^= 03
+ }
+
+ if v < -(1<<16) || v >= 1<<15 {
+ ctxt.Diag("branch too far\n%v", p)
+ }
+ o1 = OP_BC(uint32(opirr(ctxt, int(p.As))), uint32(a), uint32(r), uint32(v), 0)
+
+ case 15: /* br/bl (r) => mov r,lr; br/bl (lr) */
+ if p.As == ABC || p.As == ABCL {
+
+ v = regoff(ctxt, &p.To) & 31
+ } else {
+
+ v = 20 /* unconditional */
+ }
+ r = int(p.Reg)
+ if r == NREG {
+ r = 0
+ }
+ o1 = AOP_RRR(OP_MTSPR, uint32(p.To.Reg), 0, 0) | (D_LR&0x1f)<<16 | ((D_LR>>5)&0x1f)<<11
+ o2 = OPVCC(19, 16, 0, 0)
+ if p.As == ABL || p.As == ABCL {
+ o2 |= 1
+ }
+ o2 = OP_BCR(o2, uint32(v), uint32(r))
+
+ case 18: /* br/bl (lr/ctr); bc/bcl bo,bi,(lr/ctr) */
+ if p.As == ABC || p.As == ABCL {
+
+ v = regoff(ctxt, &p.From) & 31
+ } else {
+
+ v = 20 /* unconditional */
+ }
+ r = int(p.Reg)
+ if r == NREG {
+ r = 0
+ }
+ switch oclass(&p.To) {
+ case C_CTR:
+ o1 = OPVCC(19, 528, 0, 0)
+
+ case C_LR:
+ o1 = OPVCC(19, 16, 0, 0)
+
+ default:
+ ctxt.Diag("bad optab entry (18): %d\n%v", p.To.Class, p)
+ v = 0
+ }
+
+ if p.As == ABL || p.As == ABCL {
+ o1 |= 1
+ }
+ o1 = OP_BCR(o1, uint32(v), uint32(r))
+
+ case 19: /* mov $lcon,r ==> cau+or */
+ d = vregoff(ctxt, &p.From)
+
+ if p.From.Sym == nil {
+ o1 = loadu32(int(p.To.Reg), d)
+ o2 = LOP_IRR(OP_ORI, uint32(p.To.Reg), uint32(p.To.Reg), uint32(int32(d)))
+ } else {
+
+ o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(int32(d))))
+ o2 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), REGTMP, uint32(d))
+ addaddrreloc(ctxt, p.From.Sym, &o1, &o2)
+ }
+
+ //if(dlm) reloc(&p->from, p->pc, 0);
+
+ case 20: /* add $ucon,,r */
+ v = regoff(ctxt, &p.From)
+
+ r = int(p.Reg)
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+ if p.As == AADD && (!(r0iszero != 0 /*TypeKind(100016)*/) && p.Reg == 0 || r0iszero != 0 /*TypeKind(100016)*/ && p.To.Reg == 0) {
+ ctxt.Diag("literal operation on R0\n%v", p)
+ }
+ o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As)+AEND)), uint32(p.To.Reg), uint32(r), uint32(v)>>16)
+
+ case 22: /* add $lcon,r1,r2 ==> cau+or+add */ /* could do add/sub more efficiently */
+ if p.To.Reg == REGTMP || p.Reg == REGTMP {
+
+ ctxt.Diag("cant synthesize large constant\n%v", p)
+ }
+ d = vregoff(ctxt, &p.From)
+ o1 = loadu32(REGTMP, d)
+ o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, uint32(int32(d)))
+ r = int(p.Reg)
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+ o3 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(r))
+ if p.From.Sym != nil {
+ ctxt.Diag("%v is not supported", p)
+ }
+
+ //if(dlm) reloc(&p->from, p->pc, 0);
+
+ case 23: /* and $lcon,r1,r2 ==> cau+or+and */ /* masks could be done using rlnm etc. */
+ if p.To.Reg == REGTMP || p.Reg == REGTMP {
+
+ ctxt.Diag("cant synthesize large constant\n%v", p)
+ }
+ d = vregoff(ctxt, &p.From)
+ o1 = loadu32(REGTMP, d)
+ o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, uint32(int32(d)))
+ r = int(p.Reg)
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+ o3 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(r))
+ if p.From.Sym != nil {
+ ctxt.Diag("%v is not supported", p)
+ }
+
+ //if(dlm) reloc(&p->from, p->pc, 0);
+
+ /*24*/
+ case 25:
+ /* sld[.] $sh,rS,rA -> rldicr[.] $sh,rS,mask(0,63-sh),rA; srd[.] -> rldicl */
+ v = regoff(ctxt, &p.From)
+
+ if v < 0 {
+ v = 0
+ } else if v > 63 {
+ v = 63
+ }
+ r = int(p.Reg)
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+ switch p.As {
+ case ASLD,
+ ASLDCC:
+ a = int(63 - v)
+ o1 = OP_RLDICR
+
+ case ASRD,
+ ASRDCC:
+ a = int(v)
+ v = 64 - v
+ o1 = OP_RLDICL
+
+ default:
+ ctxt.Diag("unexpected op in sldi case\n%v", p)
+ a = 0
+ o1 = 0
+ }
+
+ o1 = AOP_RRR(o1, uint32(r), uint32(p.To.Reg), (uint32(v) & 0x1F))
+ o1 |= (uint32(a) & 31) << 6
+ if v&0x20 != 0 {
+ o1 |= 1 << 1
+ }
+ if a&0x20 != 0 {
+ o1 |= 1 << 5 /* mb[5] is top bit */
+ }
+ if p.As == ASLDCC || p.As == ASRDCC {
+ o1 |= 1 /* Rc */
+ }
+
+ case 26: /* mov $lsext/auto/oreg,,r2 ==> addis+addi */
+ if p.To.Reg == REGTMP {
+
+ ctxt.Diag("can't synthesize large constant\n%v", p)
+ }
+ v = regoff(ctxt, &p.From)
+ r = int(p.From.Reg)
+ if r == NREG {
+ r = int(o.param)
+ }
+ o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
+ o2 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), REGTMP, uint32(v))
+
+ case 27: /* subc ra,$simm,rd => subfic rd,ra,$simm */
+ v = regoff(ctxt, &p.From3)
+
+ r = int(p.From.Reg)
+ o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
+
+ case 28: /* subc r1,$lcon,r2 ==> cau+or+subfc */
+ if p.To.Reg == REGTMP || p.From.Reg == REGTMP {
+
+ ctxt.Diag("can't synthesize large constant\n%v", p)
+ }
+ v = regoff(ctxt, &p.From3)
+ o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(v)>>16)
+ o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, uint32(v))
+ o3 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), REGTMP)
+ if p.From.Sym != nil {
+ ctxt.Diag("%v is not supported", p)
+ }
+
+ //if(dlm) reloc(&p->from3, p->pc, 0);
+
+ case 29: /* rldic[lr]? $sh,s,$mask,a -- left, right, plain give different masks */
+ v = regoff(ctxt, &p.From)
+
+ d = vregoff(ctxt, &p.From3)
+ maskgen64(ctxt, p, mask[:], uint64(d))
+ switch p.As {
+ case ARLDC,
+ ARLDCCC:
+ a = int(mask[0]) /* MB */
+ if int32(mask[1]) != (63 - v) {
+ ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
+ }
+
+ case ARLDCL,
+ ARLDCLCC:
+ a = int(mask[0]) /* MB */
+ if mask[1] != 63 {
+ ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
+ }
+
+ case ARLDCR,
+ ARLDCRCC:
+ a = int(mask[1]) /* ME */
+ if mask[0] != 0 {
+ ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
+ }
+
+ default:
+ ctxt.Diag("unexpected op in rldic case\n%v", p)
+ a = 0
+ }
+
+ o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), (uint32(v) & 0x1F))
+ o1 |= (uint32(a) & 31) << 6
+ if v&0x20 != 0 {
+ o1 |= 1 << 1
+ }
+ if a&0x20 != 0 {
+ o1 |= 1 << 5 /* mb[5] is top bit */
+ }
+
+ case 30: /* rldimi $sh,s,$mask,a */
+ v = regoff(ctxt, &p.From)
+
+ d = vregoff(ctxt, &p.From3)
+ maskgen64(ctxt, p, mask[:], uint64(d))
+ if int32(mask[1]) != (63 - v) {
+ ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
+ }
+ o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), (uint32(v) & 0x1F))
+ o1 |= (uint32(mask[0]) & 31) << 6
+ if v&0x20 != 0 {
+ o1 |= 1 << 1
+ }
+ if mask[0]&0x20 != 0 {
+ o1 |= 1 << 5 /* mb[5] is top bit */
+ }
+
+ case 31: /* dword */
+ d = vregoff(ctxt, &p.From)
+
+ if ctxt.Arch.Endian == obj.BigEndian {
+ o1 = uint32(d >> 32)
+ o2 = uint32(d)
+ } else {
+
+ o1 = uint32(d)
+ o2 = uint32(d >> 32)
+ }
+
+ if p.From.Sym != nil {
+ rel = obj.Addrel(ctxt.Cursym)
+ rel.Off = int32(ctxt.Pc)
+ rel.Siz = 8
+ rel.Sym = p.From.Sym
+ rel.Add = p.From.Offset
+ rel.Type = obj.R_ADDR
+ o2 = 0
+ o1 = o2
+ }
+
+ case 32: /* fmul frc,fra,frd */
+ r = int(p.Reg)
+
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+ o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), 0) | (uint32(p.From.Reg)&31)<<6
+
+ case 33: /* fabs [frb,]frd; fmr. frb,frd */
+ r = int(p.From.Reg)
+
+ if oclass(&p.From) == C_NONE {
+ r = int(p.To.Reg)
+ }
+ o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), 0, uint32(r))
+
+ case 34: /* FMADDx fra,frb,frc,frd (d=a*b+c); FSELx a<0? (d=b): (d=c) */
+ o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)) | (uint32(p.From3.Reg)&31)<<6
+
+ case 35: /* mov r,lext/lauto/loreg ==> cau $(v>>16),sb,r'; store o(r') */
+ v = regoff(ctxt, &p.To)
+
+ r = int(p.To.Reg)
+ if r == NREG {
+ r = int(o.param)
+ }
+ o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
+ o2 = AOP_IRR(uint32(opstore(ctxt, int(p.As))), uint32(p.From.Reg), REGTMP, uint32(v))
+
+ case 36: /* mov bz/h/hz lext/lauto/lreg,r ==> lbz/lha/lhz etc */
+ v = regoff(ctxt, &p.From)
+
+ r = int(p.From.Reg)
+ if r == NREG {
+ r = int(o.param)
+ }
+ o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
+ o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
+
+ case 37: /* movb lext/lauto/lreg,r ==> lbz o(reg),r; extsb r */
+ v = regoff(ctxt, &p.From)
+
+ r = int(p.From.Reg)
+ if r == NREG {
+ r = int(o.param)
+ }
+ o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
+ o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
+ o3 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
+
+ case 40: /* word */
+ o1 = uint32(regoff(ctxt, &p.From))
+
+ case 41: /* stswi */
+ o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.From.Reg), uint32(p.To.Reg), 0) | (uint32(regoff(ctxt, &p.From3))&0x7F)<<11
+
+ case 42: /* lswi */
+ o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), 0) | (uint32(regoff(ctxt, &p.From3))&0x7F)<<11
+
+ case 43: /* unary indexed source: dcbf (b); dcbf (a+b) */
+ r = int(p.Reg)
+
+ if r == NREG {
+ r = 0
+ }
+ o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), 0, uint32(r), uint32(p.From.Reg))
+
+ case 44: /* indexed store */
+ r = int(p.Reg)
+
+ if r == NREG {
+ r = 0
+ }
+ o1 = AOP_RRR(uint32(opstorex(ctxt, int(p.As))), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
+
+ case 45: /* indexed load */
+ r = int(p.Reg)
+
+ if r == NREG {
+ r = 0
+ }
+ o1 = AOP_RRR(uint32(oploadx(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg))
+
+ case 46: /* plain op */
+ o1 = uint32(oprrr(ctxt, int(p.As)))
+
+ case 47: /* op Ra, Rd; also op [Ra,] Rd */
+ r = int(p.From.Reg)
+
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+ o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), 0)
+
+ case 48: /* op Rs, Ra */
+ r = int(p.From.Reg)
+
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+ o1 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), 0)
+
+ case 49: /* op Rb; op $n, Rb */
+ if p.From.Type != D_REG { /* tlbie $L, rB */
+ v = regoff(ctxt, &p.From) & 1
+ o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), 0, 0, uint32(p.To.Reg)) | uint32(v)<<21
+ } else {
+
+ o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), 0, 0, uint32(p.From.Reg))
+ }
+
+ case 50: /* rem[u] r1[,r2],r3 */
+ r = int(p.Reg)
+
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+ v = oprrr(ctxt, int(p.As))
+ t = v & (1<<10 | 1) /* OE|Rc */
+ o1 = AOP_RRR(uint32(v)&^uint32(t), REGTMP, uint32(r), uint32(p.From.Reg))
+ o2 = AOP_RRR(OP_MULLW, REGTMP, REGTMP, uint32(p.From.Reg))
+ o3 = AOP_RRR(OP_SUBF|uint32(t), uint32(p.To.Reg), REGTMP, uint32(r))
+ if p.As == AREMU {
+ o4 = o3
+
+ /* Clear top 32 bits */
+ o3 = OP_RLW(OP_RLDIC, REGTMP, REGTMP, 0, 0, 0) | 1<<5
+ }
+
+ case 51: /* remd[u] r1[,r2],r3 */
+ r = int(p.Reg)
+
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+ v = oprrr(ctxt, int(p.As))
+ t = v & (1<<10 | 1) /* OE|Rc */
+ o1 = AOP_RRR(uint32(v)&^uint32(t), REGTMP, uint32(r), uint32(p.From.Reg))
+ o2 = AOP_RRR(OP_MULLD, REGTMP, REGTMP, uint32(p.From.Reg))
+ o3 = AOP_RRR(OP_SUBF|uint32(t), uint32(p.To.Reg), REGTMP, uint32(r))
+
+ case 52: /* mtfsbNx cr(n) */
+ v = regoff(ctxt, &p.From) & 31
+
+ o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(v), 0, 0)
+
+ case 53: /* mffsX ,fr1 */
+ o1 = AOP_RRR(OP_MFFS, uint32(p.To.Reg), 0, 0)
+
+ case 54: /* mov msr,r1; mov r1, msr*/
+ if oclass(&p.From) == C_REG {
+
+ if p.As == AMOVD {
+ o1 = AOP_RRR(OP_MTMSRD, uint32(p.From.Reg), 0, 0)
+ } else {
+
+ o1 = AOP_RRR(OP_MTMSR, uint32(p.From.Reg), 0, 0)
+ }
+ } else {
+
+ o1 = AOP_RRR(OP_MFMSR, uint32(p.To.Reg), 0, 0)
+ }
+
+ case 55: /* op Rb, Rd */
+ o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), 0, uint32(p.From.Reg))
+
+ case 56: /* sra $sh,[s,]a; srd $sh,[s,]a */
+ v = regoff(ctxt, &p.From)
+
+ r = int(p.Reg)
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+ o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(r), uint32(p.To.Reg), uint32(v)&31)
+ if p.As == ASRAD && (v&0x20 != 0) {
+ o1 |= 1 << 1 /* mb[5] */
+ }
+
+ case 57: /* slw $sh,[s,]a -> rlwinm ... */
+ v = regoff(ctxt, &p.From)
+
+ r = int(p.Reg)
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+
+ /*
+ * Let user (gs) shoot himself in the foot.
+ * qc has already complained.
+ *
+ if(v < 0 || v > 31)
+ ctxt->diag("illegal shift %ld\n%P", v, p);
+ */
+ if v < 0 {
+
+ v = 0
+ } else if v > 32 {
+ v = 32
+ }
+ if p.As == ASRW || p.As == ASRWCC { /* shift right */
+ mask[0] = uint8(v)
+ mask[1] = 31
+ v = 32 - v
+ } else {
+
+ mask[0] = 0
+ mask[1] = uint8(31 - v)
+ }
+
+ o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(r), uint32(v), uint32(mask[0]), uint32(mask[1]))
+ if p.As == ASLWCC || p.As == ASRWCC {
+ o1 |= 1 /* Rc */
+ }
+
+ case 58: /* logical $andcon,[s],a */
+ v = regoff(ctxt, &p.From)
+
+ r = int(p.Reg)
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+ o1 = LOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
+
+ case 59: /* or/and $ucon,,r */
+ v = regoff(ctxt, &p.From)
+
+ r = int(p.Reg)
+ if r == NREG {
+ r = int(p.To.Reg)
+ }
+ o1 = LOP_IRR(uint32(opirr(ctxt, int(p.As)+AEND)), uint32(p.To.Reg), uint32(r), uint32(v)>>16) /* oris, xoris, andis */
+
+ case 60: /* tw to,a,b */
+ r = int(regoff(ctxt, &p.From) & 31)
+
+ o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(r), uint32(p.Reg), uint32(p.To.Reg))
+
+ case 61: /* tw to,a,$simm */
+ r = int(regoff(ctxt, &p.From) & 31)
+
+ v = regoff(ctxt, &p.To)
+ o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(r), uint32(p.Reg), uint32(v))
+
+ case 62: /* rlwmi $sh,s,$mask,a */
+ v = regoff(ctxt, &p.From)
+
+ maskgen(ctxt, p, mask[:], uint32(regoff(ctxt, &p.From3)))
+ o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), uint32(v))
+ o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1
+
+ case 63: /* rlwmi b,s,$mask,a */
+ maskgen(ctxt, p, mask[:], uint32(regoff(ctxt, &p.From3)))
+
+ o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), uint32(p.From.Reg))
+ o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1
+
+ case 64: /* mtfsf fr[, $m] {,fpcsr} */
+ if p.From3.Type != D_NONE {
+
+ v = regoff(ctxt, &p.From3) & 255
+ } else {
+
+ v = 255
+ }
+ o1 = OP_MTFSF | uint32(v)<<17 | uint32(p.From.Reg)<<11
+
+ case 65: /* MOVFL $imm,FPSCR(n) => mtfsfi crfd,imm */
+ if p.To.Reg == NREG {
+
+ ctxt.Diag("must specify FPSCR(n)\n%v", p)
+ }
+ o1 = OP_MTFSFI | (uint32(p.To.Reg)&15)<<23 | (uint32(regoff(ctxt, &p.From))&31)<<12
+
+ case 66: /* mov spr,r1; mov r1,spr, also dcr */
+ if p.From.Type == D_REG {
+
+ r = int(p.From.Reg)
+ v = int32(p.To.Offset)
+ if p.To.Type == D_DCR {
+ o1 = OPVCC(31, 451, 0, 0) /* mtdcr */
+ } else {
+
+ o1 = OPVCC(31, 467, 0, 0) /* mtspr */
+ }
+ } else {
+
+ r = int(p.To.Reg)
+ v = int32(p.From.Offset)
+ if p.From.Type == D_DCR {
+ o1 = OPVCC(31, 323, 0, 0) /* mfdcr */
+ } else {
+
+ o1 = OPVCC(31, 339, 0, 0) /* mfspr */
+ }
+ }
+
+ o1 = AOP_RRR(o1, uint32(r), 0, 0) | (uint32(v)&0x1f)<<16 | ((uint32(v)>>5)&0x1f)<<11
+
+ case 67: /* mcrf crfD,crfS */
+ if p.From.Type != D_CREG || p.From.Reg == NREG || p.To.Type != D_CREG || p.To.Reg == NREG {
+
+ ctxt.Diag("illegal CR field number\n%v", p)
+ }
+ o1 = AOP_RRR(OP_MCRF, ((uint32(p.To.Reg) & 7) << 2), ((uint32(p.From.Reg) & 7) << 2), 0)
+
+ case 68: /* mfcr rD; mfocrf CRM,rD */
+ if p.From.Type == D_CREG && p.From.Reg != NREG {
+
+ v = 1 << uint(7-(p.To.Reg&7)) /* CR(n) */
+ o1 = AOP_RRR(OP_MFCR, uint32(p.To.Reg), 0, 0) | 1<<20 | uint32(v)<<12 /* new form, mfocrf */
+ } else {
+
+ o1 = AOP_RRR(OP_MFCR, uint32(p.To.Reg), 0, 0) /* old form, whole register */
+ }
+
+ case 69: /* mtcrf CRM,rS */
+ if p.From3.Type != D_NONE {
+
+ if p.To.Reg != NREG {
+ ctxt.Diag("can't use both mask and CR(n)\n%v", p)
+ }
+ v = regoff(ctxt, &p.From3) & 0xff
+ } else {
+
+ if p.To.Reg == NREG {
+ v = 0xff /* CR */
+ } else {
+
+ v = 1 << uint(7-(p.To.Reg&7)) /* CR(n) */
+ }
+ }
+
+ o1 = AOP_RRR(OP_MTCRF, uint32(p.From.Reg), 0, 0) | uint32(v)<<12
+
+ case 70: /* [f]cmp r,r,cr*/
+ if p.Reg == NREG {
+
+ r = 0
+ } else {
+
+ r = (int(p.Reg) & 7) << 2
+ }
+ o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg))
+
+ case 71: /* cmp[l] r,i,cr*/
+ if p.Reg == NREG {
+
+ r = 0
+ } else {
+
+ r = (int(p.Reg) & 7) << 2
+ }
+ o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(r), uint32(p.From.Reg), 0) | uint32(regoff(ctxt, &p.To))&0xffff
+
+ case 72: /* slbmte (Rb+Rs -> slb[Rb]) -> Rs, Rb */
+ o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.From.Reg), 0, uint32(p.To.Reg))
+
+ case 73: /* mcrfs crfD,crfS */
+ if p.From.Type != D_FPSCR || p.From.Reg == NREG || p.To.Type != D_CREG || p.To.Reg == NREG {
+
+ ctxt.Diag("illegal FPSCR/CR field number\n%v", p)
+ }
+ o1 = AOP_RRR(OP_MCRFS, ((uint32(p.To.Reg) & 7) << 2), ((uint32(p.From.Reg) & 7) << 2), 0)
+
+ case 77: /* syscall $scon, syscall Rx */
+ if p.From.Type == D_CONST {
+
+ if p.From.Offset > BIG || p.From.Offset < -BIG {
+ ctxt.Diag("illegal syscall, sysnum too large: %v", p)
+ }
+ o1 = AOP_IRR(OP_ADDI, REGZERO, REGZERO, uint32(p.From.Offset))
+ } else if p.From.Type == D_REG {
+ o1 = LOP_RRR(OP_OR, REGZERO, uint32(p.From.Reg), uint32(p.From.Reg))
+ } else {
+
+ ctxt.Diag("illegal syscall: %v", p)
+ o1 = 0x7fe00008 // trap always
+ }
+
+ o2 = uint32(oprrr(ctxt, int(p.As)))
+ o3 = AOP_RRR(uint32(oprrr(ctxt, AXOR)), REGZERO, REGZERO, REGZERO) // XOR R0, R0
+
+ case 78: /* undef */
+ o1 = 0 /* "An instruction consisting entirely of binary 0s is guaranteed
+ always to be an illegal instruction." */
+
+ /* relocation operations */
+ case 74:
+ v = regoff(ctxt, &p.To)
+
+ o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v)))
+ o2 = AOP_IRR(uint32(opstore(ctxt, int(p.As))), uint32(p.From.Reg), REGTMP, uint32(v))
+ addaddrreloc(ctxt, p.To.Sym, &o1, &o2)
+
+ //if(dlm) reloc(&p->to, p->pc, 1);
+
+ case 75:
+ v = regoff(ctxt, &p.From)
+ o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v)))
+ o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
+ addaddrreloc(ctxt, p.From.Sym, &o1, &o2)
+
+ //if(dlm) reloc(&p->from, p->pc, 1);
+
+ case 76:
+ v = regoff(ctxt, &p.From)
+ o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v)))
+ o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
+ addaddrreloc(ctxt, p.From.Sym, &o1, &o2)
+ o3 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
+
+ //if(dlm) reloc(&p->from, p->pc, 1);
+ break
+ }
+
+ out[0] = o1
+ out[1] = o2
+ out[2] = o3
+ out[3] = o4
+ out[4] = o5
+ return
+}
+
+func vregoff(ctxt *obj.Link, a *obj.Addr) int64 {
+ ctxt.Instoffset = 0
+ aclass(ctxt, a)
+ return ctxt.Instoffset
+}
+
+func regoff(ctxt *obj.Link, a *obj.Addr) int32 {
+ return int32(vregoff(ctxt, a))
+}
+
+func oprrr(ctxt *obj.Link, a int) int32 {
+ switch a {
+ case AADD:
+ return int32(OPVCC(31, 266, 0, 0))
+ case AADDCC:
+ return int32(OPVCC(31, 266, 0, 1))
+ case AADDV:
+ return int32(OPVCC(31, 266, 1, 0))
+ case AADDVCC:
+ return int32(OPVCC(31, 266, 1, 1))
+ case AADDC:
+ return int32(OPVCC(31, 10, 0, 0))
+ case AADDCCC:
+ return int32(OPVCC(31, 10, 0, 1))
+ case AADDCV:
+ return int32(OPVCC(31, 10, 1, 0))
+ case AADDCVCC:
+ return int32(OPVCC(31, 10, 1, 1))
+ case AADDE:
+ return int32(OPVCC(31, 138, 0, 0))
+ case AADDECC:
+ return int32(OPVCC(31, 138, 0, 1))
+ case AADDEV:
+ return int32(OPVCC(31, 138, 1, 0))
+ case AADDEVCC:
+ return int32(OPVCC(31, 138, 1, 1))
+ case AADDME:
+ return int32(OPVCC(31, 234, 0, 0))
+ case AADDMECC:
+ return int32(OPVCC(31, 234, 0, 1))
+ case AADDMEV:
+ return int32(OPVCC(31, 234, 1, 0))
+ case AADDMEVCC:
+ return int32(OPVCC(31, 234, 1, 1))
+ case AADDZE:
+ return int32(OPVCC(31, 202, 0, 0))
+ case AADDZECC:
+ return int32(OPVCC(31, 202, 0, 1))
+ case AADDZEV:
+ return int32(OPVCC(31, 202, 1, 0))
+ case AADDZEVCC:
+ return int32(OPVCC(31, 202, 1, 1))
+
+ case AAND:
+ return int32(OPVCC(31, 28, 0, 0))
+ case AANDCC:
+ return int32(OPVCC(31, 28, 0, 1))
+ case AANDN:
+ return int32(OPVCC(31, 60, 0, 0))
+ case AANDNCC:
+ return int32(OPVCC(31, 60, 0, 1))
+
+ case ACMP:
+ return int32(OPVCC(31, 0, 0, 0) | 1<<21) /* L=1 */
+ case ACMPU:
+ return int32(OPVCC(31, 32, 0, 0) | 1<<21)
+ case ACMPW:
+ return int32(OPVCC(31, 0, 0, 0)) /* L=0 */
+ case ACMPWU:
+ return int32(OPVCC(31, 32, 0, 0))
+
+ case ACNTLZW:
+ return int32(OPVCC(31, 26, 0, 0))
+ case ACNTLZWCC:
+ return int32(OPVCC(31, 26, 0, 1))
+ case ACNTLZD:
+ return int32(OPVCC(31, 58, 0, 0))
+ case ACNTLZDCC:
+ return int32(OPVCC(31, 58, 0, 1))
+
+ case ACRAND:
+ return int32(OPVCC(19, 257, 0, 0))
+ case ACRANDN:
+ return int32(OPVCC(19, 129, 0, 0))
+ case ACREQV:
+ return int32(OPVCC(19, 289, 0, 0))
+ case ACRNAND:
+ return int32(OPVCC(19, 225, 0, 0))
+ case ACRNOR:
+ return int32(OPVCC(19, 33, 0, 0))
+ case ACROR:
+ return int32(OPVCC(19, 449, 0, 0))
+ case ACRORN:
+ return int32(OPVCC(19, 417, 0, 0))
+ case ACRXOR:
+ return int32(OPVCC(19, 193, 0, 0))
+
+ case ADCBF:
+ return int32(OPVCC(31, 86, 0, 0))
+ case ADCBI:
+ return int32(OPVCC(31, 470, 0, 0))
+ case ADCBST:
+ return int32(OPVCC(31, 54, 0, 0))
+ case ADCBT:
+ return int32(OPVCC(31, 278, 0, 0))
+ case ADCBTST:
+ return int32(OPVCC(31, 246, 0, 0))
+ case ADCBZ:
+ return int32(OPVCC(31, 1014, 0, 0))
+
+ case AREM,
+ ADIVW:
+ return int32(OPVCC(31, 491, 0, 0))
+
+ case AREMCC,
+ ADIVWCC:
+ return int32(OPVCC(31, 491, 0, 1))
+
+ case AREMV,
+ ADIVWV:
+ return int32(OPVCC(31, 491, 1, 0))
+
+ case AREMVCC,
+ ADIVWVCC:
+ return int32(OPVCC(31, 491, 1, 1))
+
+ case AREMU,
+ ADIVWU:
+ return int32(OPVCC(31, 459, 0, 0))
+
+ case AREMUCC,
+ ADIVWUCC:
+ return int32(OPVCC(31, 459, 0, 1))
+
+ case AREMUV,
+ ADIVWUV:
+ return int32(OPVCC(31, 459, 1, 0))
+
+ case AREMUVCC,
+ ADIVWUVCC:
+ return int32(OPVCC(31, 459, 1, 1))
+
+ case AREMD,
+ ADIVD:
+ return int32(OPVCC(31, 489, 0, 0))
+
+ case AREMDCC,
+ ADIVDCC:
+ return int32(OPVCC(31, 489, 0, 1))
+
+ case AREMDV,
+ ADIVDV:
+ return int32(OPVCC(31, 489, 1, 0))
+
+ case AREMDVCC,
+ ADIVDVCC:
+ return int32(OPVCC(31, 489, 1, 1))
+
+ case AREMDU,
+ ADIVDU:
+ return int32(OPVCC(31, 457, 0, 0))
+
+ case AREMDUCC,
+ ADIVDUCC:
+ return int32(OPVCC(31, 457, 0, 1))
+
+ case AREMDUV,
+ ADIVDUV:
+ return int32(OPVCC(31, 457, 1, 0))
+
+ case AREMDUVCC,
+ ADIVDUVCC:
+ return int32(OPVCC(31, 457, 1, 1))
+
+ case AEIEIO:
+ return int32(OPVCC(31, 854, 0, 0))
+
+ case AEQV:
+ return int32(OPVCC(31, 284, 0, 0))
+ case AEQVCC:
+ return int32(OPVCC(31, 284, 0, 1))
+
+ case AEXTSB:
+ return int32(OPVCC(31, 954, 0, 0))
+ case AEXTSBCC:
+ return int32(OPVCC(31, 954, 0, 1))
+ case AEXTSH:
+ return int32(OPVCC(31, 922, 0, 0))
+ case AEXTSHCC:
+ return int32(OPVCC(31, 922, 0, 1))
+ case AEXTSW:
+ return int32(OPVCC(31, 986, 0, 0))
+ case AEXTSWCC:
+ return int32(OPVCC(31, 986, 0, 1))
+
+ case AFABS:
+ return int32(OPVCC(63, 264, 0, 0))
+ case AFABSCC:
+ return int32(OPVCC(63, 264, 0, 1))
+ case AFADD:
+ return int32(OPVCC(63, 21, 0, 0))
+ case AFADDCC:
+ return int32(OPVCC(63, 21, 0, 1))
+ case AFADDS:
+ return int32(OPVCC(59, 21, 0, 0))
+ case AFADDSCC:
+ return int32(OPVCC(59, 21, 0, 1))
+ case AFCMPO:
+ return int32(OPVCC(63, 32, 0, 0))
+ case AFCMPU:
+ return int32(OPVCC(63, 0, 0, 0))
+ case AFCFID:
+ return int32(OPVCC(63, 846, 0, 0))
+ case AFCFIDCC:
+ return int32(OPVCC(63, 846, 0, 1))
+ case AFCTIW:
+ return int32(OPVCC(63, 14, 0, 0))
+ case AFCTIWCC:
+ return int32(OPVCC(63, 14, 0, 1))
+ case AFCTIWZ:
+ return int32(OPVCC(63, 15, 0, 0))
+ case AFCTIWZCC:
+ return int32(OPVCC(63, 15, 0, 1))
+ case AFCTID:
+ return int32(OPVCC(63, 814, 0, 0))
+ case AFCTIDCC:
+ return int32(OPVCC(63, 814, 0, 1))
+ case AFCTIDZ:
+ return int32(OPVCC(63, 815, 0, 0))
+ case AFCTIDZCC:
+ return int32(OPVCC(63, 815, 0, 1))
+ case AFDIV:
+ return int32(OPVCC(63, 18, 0, 0))
+ case AFDIVCC:
+ return int32(OPVCC(63, 18, 0, 1))
+ case AFDIVS:
+ return int32(OPVCC(59, 18, 0, 0))
+ case AFDIVSCC:
+ return int32(OPVCC(59, 18, 0, 1))
+ case AFMADD:
+ return int32(OPVCC(63, 29, 0, 0))
+ case AFMADDCC:
+ return int32(OPVCC(63, 29, 0, 1))
+ case AFMADDS:
+ return int32(OPVCC(59, 29, 0, 0))
+ case AFMADDSCC:
+ return int32(OPVCC(59, 29, 0, 1))
+
+ case AFMOVS,
+ AFMOVD:
+ return int32(OPVCC(63, 72, 0, 0)) /* load */
+ case AFMOVDCC:
+ return int32(OPVCC(63, 72, 0, 1))
+ case AFMSUB:
+ return int32(OPVCC(63, 28, 0, 0))
+ case AFMSUBCC:
+ return int32(OPVCC(63, 28, 0, 1))
+ case AFMSUBS:
+ return int32(OPVCC(59, 28, 0, 0))
+ case AFMSUBSCC:
+ return int32(OPVCC(59, 28, 0, 1))
+ case AFMUL:
+ return int32(OPVCC(63, 25, 0, 0))
+ case AFMULCC:
+ return int32(OPVCC(63, 25, 0, 1))
+ case AFMULS:
+ return int32(OPVCC(59, 25, 0, 0))
+ case AFMULSCC:
+ return int32(OPVCC(59, 25, 0, 1))
+ case AFNABS:
+ return int32(OPVCC(63, 136, 0, 0))
+ case AFNABSCC:
+ return int32(OPVCC(63, 136, 0, 1))
+ case AFNEG:
+ return int32(OPVCC(63, 40, 0, 0))
+ case AFNEGCC:
+ return int32(OPVCC(63, 40, 0, 1))
+ case AFNMADD:
+ return int32(OPVCC(63, 31, 0, 0))
+ case AFNMADDCC:
+ return int32(OPVCC(63, 31, 0, 1))
+ case AFNMADDS:
+ return int32(OPVCC(59, 31, 0, 0))
+ case AFNMADDSCC:
+ return int32(OPVCC(59, 31, 0, 1))
+ case AFNMSUB:
+ return int32(OPVCC(63, 30, 0, 0))
+ case AFNMSUBCC:
+ return int32(OPVCC(63, 30, 0, 1))
+ case AFNMSUBS:
+ return int32(OPVCC(59, 30, 0, 0))
+ case AFNMSUBSCC:
+ return int32(OPVCC(59, 30, 0, 1))
+ case AFRES:
+ return int32(OPVCC(59, 24, 0, 0))
+ case AFRESCC:
+ return int32(OPVCC(59, 24, 0, 1))
+ case AFRSP:
+ return int32(OPVCC(63, 12, 0, 0))
+ case AFRSPCC:
+ return int32(OPVCC(63, 12, 0, 1))
+ case AFRSQRTE:
+ return int32(OPVCC(63, 26, 0, 0))
+ case AFRSQRTECC:
+ return int32(OPVCC(63, 26, 0, 1))
+ case AFSEL:
+ return int32(OPVCC(63, 23, 0, 0))
+ case AFSELCC:
+ return int32(OPVCC(63, 23, 0, 1))
+ case AFSQRT:
+ return int32(OPVCC(63, 22, 0, 0))
+ case AFSQRTCC:
+ return int32(OPVCC(63, 22, 0, 1))
+ case AFSQRTS:
+ return int32(OPVCC(59, 22, 0, 0))
+ case AFSQRTSCC:
+ return int32(OPVCC(59, 22, 0, 1))
+ case AFSUB:
+ return int32(OPVCC(63, 20, 0, 0))
+ case AFSUBCC:
+ return int32(OPVCC(63, 20, 0, 1))
+ case AFSUBS:
+ return int32(OPVCC(59, 20, 0, 0))
+ case AFSUBSCC:
+ return int32(OPVCC(59, 20, 0, 1))
+
+ case AICBI:
+ return int32(OPVCC(31, 982, 0, 0))
+ case AISYNC:
+ return int32(OPVCC(19, 150, 0, 0))
+
+ case AMTFSB0:
+ return int32(OPVCC(63, 70, 0, 0))
+ case AMTFSB0CC:
+ return int32(OPVCC(63, 70, 0, 1))
+ case AMTFSB1:
+ return int32(OPVCC(63, 38, 0, 0))
+ case AMTFSB1CC:
+ return int32(OPVCC(63, 38, 0, 1))
+
+ case AMULHW:
+ return int32(OPVCC(31, 75, 0, 0))
+ case AMULHWCC:
+ return int32(OPVCC(31, 75, 0, 1))
+ case AMULHWU:
+ return int32(OPVCC(31, 11, 0, 0))
+ case AMULHWUCC:
+ return int32(OPVCC(31, 11, 0, 1))
+ case AMULLW:
+ return int32(OPVCC(31, 235, 0, 0))
+ case AMULLWCC:
+ return int32(OPVCC(31, 235, 0, 1))
+ case AMULLWV:
+ return int32(OPVCC(31, 235, 1, 0))
+ case AMULLWVCC:
+ return int32(OPVCC(31, 235, 1, 1))
+
+ case AMULHD:
+ return int32(OPVCC(31, 73, 0, 0))
+ case AMULHDCC:
+ return int32(OPVCC(31, 73, 0, 1))
+ case AMULHDU:
+ return int32(OPVCC(31, 9, 0, 0))
+ case AMULHDUCC:
+ return int32(OPVCC(31, 9, 0, 1))
+ case AMULLD:
+ return int32(OPVCC(31, 233, 0, 0))
+ case AMULLDCC:
+ return int32(OPVCC(31, 233, 0, 1))
+ case AMULLDV:
+ return int32(OPVCC(31, 233, 1, 0))
+ case AMULLDVCC:
+ return int32(OPVCC(31, 233, 1, 1))
+
+ case ANAND:
+ return int32(OPVCC(31, 476, 0, 0))
+ case ANANDCC:
+ return int32(OPVCC(31, 476, 0, 1))
+ case ANEG:
+ return int32(OPVCC(31, 104, 0, 0))
+ case ANEGCC:
+ return int32(OPVCC(31, 104, 0, 1))
+ case ANEGV:
+ return int32(OPVCC(31, 104, 1, 0))
+ case ANEGVCC:
+ return int32(OPVCC(31, 104, 1, 1))
+ case ANOR:
+ return int32(OPVCC(31, 124, 0, 0))
+ case ANORCC:
+ return int32(OPVCC(31, 124, 0, 1))
+ case AOR:
+ return int32(OPVCC(31, 444, 0, 0))
+ case AORCC:
+ return int32(OPVCC(31, 444, 0, 1))
+ case AORN:
+ return int32(OPVCC(31, 412, 0, 0))
+ case AORNCC:
+ return int32(OPVCC(31, 412, 0, 1))
+
+ case ARFI:
+ return int32(OPVCC(19, 50, 0, 0))
+ case ARFCI:
+ return int32(OPVCC(19, 51, 0, 0))
+ case ARFID:
+ return int32(OPVCC(19, 18, 0, 0))
+ case AHRFID:
+ return int32(OPVCC(19, 274, 0, 0))
+
+ case ARLWMI:
+ return int32(OPVCC(20, 0, 0, 0))
+ case ARLWMICC:
+ return int32(OPVCC(20, 0, 0, 1))
+ case ARLWNM:
+ return int32(OPVCC(23, 0, 0, 0))
+ case ARLWNMCC:
+ return int32(OPVCC(23, 0, 0, 1))
+
+ case ARLDCL:
+ return int32(OPVCC(30, 8, 0, 0))
+ case ARLDCR:
+ return int32(OPVCC(30, 9, 0, 0))
+
+ case ASYSCALL:
+ return int32(OPVCC(17, 1, 0, 0))
+
+ case ASLW:
+ return int32(OPVCC(31, 24, 0, 0))
+ case ASLWCC:
+ return int32(OPVCC(31, 24, 0, 1))
+ case ASLD:
+ return int32(OPVCC(31, 27, 0, 0))
+ case ASLDCC:
+ return int32(OPVCC(31, 27, 0, 1))
+
+ case ASRAW:
+ return int32(OPVCC(31, 792, 0, 0))
+ case ASRAWCC:
+ return int32(OPVCC(31, 792, 0, 1))
+ case ASRAD:
+ return int32(OPVCC(31, 794, 0, 0))
+ case ASRADCC:
+ return int32(OPVCC(31, 794, 0, 1))
+
+ case ASRW:
+ return int32(OPVCC(31, 536, 0, 0))
+ case ASRWCC:
+ return int32(OPVCC(31, 536, 0, 1))
+ case ASRD:
+ return int32(OPVCC(31, 539, 0, 0))
+ case ASRDCC:
+ return int32(OPVCC(31, 539, 0, 1))
+
+ case ASUB:
+ return int32(OPVCC(31, 40, 0, 0))
+ case ASUBCC:
+ return int32(OPVCC(31, 40, 0, 1))
+ case ASUBV:
+ return int32(OPVCC(31, 40, 1, 0))
+ case ASUBVCC:
+ return int32(OPVCC(31, 40, 1, 1))
+ case ASUBC:
+ return int32(OPVCC(31, 8, 0, 0))
+ case ASUBCCC:
+ return int32(OPVCC(31, 8, 0, 1))
+ case ASUBCV:
+ return int32(OPVCC(31, 8, 1, 0))
+ case ASUBCVCC:
+ return int32(OPVCC(31, 8, 1, 1))
+ case ASUBE:
+ return int32(OPVCC(31, 136, 0, 0))
+ case ASUBECC:
+ return int32(OPVCC(31, 136, 0, 1))
+ case ASUBEV:
+ return int32(OPVCC(31, 136, 1, 0))
+ case ASUBEVCC:
+ return int32(OPVCC(31, 136, 1, 1))
+ case ASUBME:
+ return int32(OPVCC(31, 232, 0, 0))
+ case ASUBMECC:
+ return int32(OPVCC(31, 232, 0, 1))
+ case ASUBMEV:
+ return int32(OPVCC(31, 232, 1, 0))
+ case ASUBMEVCC:
+ return int32(OPVCC(31, 232, 1, 1))
+ case ASUBZE:
+ return int32(OPVCC(31, 200, 0, 0))
+ case ASUBZECC:
+ return int32(OPVCC(31, 200, 0, 1))
+ case ASUBZEV:
+ return int32(OPVCC(31, 200, 1, 0))
+ case ASUBZEVCC:
+ return int32(OPVCC(31, 200, 1, 1))
+
+ case ASYNC:
+ return int32(OPVCC(31, 598, 0, 0))
+ case APTESYNC:
+ return int32(OPVCC(31, 598, 0, 0) | 2<<21)
+
+ case ATLBIE:
+ return int32(OPVCC(31, 306, 0, 0))
+ case ATLBIEL:
+ return int32(OPVCC(31, 274, 0, 0))
+ case ATLBSYNC:
+ return int32(OPVCC(31, 566, 0, 0))
+ case ASLBIA:
+ return int32(OPVCC(31, 498, 0, 0))
+ case ASLBIE:
+ return int32(OPVCC(31, 434, 0, 0))
+ case ASLBMFEE:
+ return int32(OPVCC(31, 915, 0, 0))
+ case ASLBMFEV:
+ return int32(OPVCC(31, 851, 0, 0))
+ case ASLBMTE:
+ return int32(OPVCC(31, 402, 0, 0))
+
+ case ATW:
+ return int32(OPVCC(31, 4, 0, 0))
+ case ATD:
+ return int32(OPVCC(31, 68, 0, 0))
+
+ case AXOR:
+ return int32(OPVCC(31, 316, 0, 0))
+ case AXORCC:
+ return int32(OPVCC(31, 316, 0, 1))
+ }
+
+ ctxt.Diag("bad r/r opcode %v", Aconv(a))
+ return 0
+}
+
+func opirr(ctxt *obj.Link, a int) int32 {
+ switch a {
+ case AADD:
+ return int32(OPVCC(14, 0, 0, 0))
+ case AADDC:
+ return int32(OPVCC(12, 0, 0, 0))
+ case AADDCCC:
+ return int32(OPVCC(13, 0, 0, 0))
+ case AADD + AEND:
+ return int32(OPVCC(15, 0, 0, 0)) /* ADDIS/CAU */
+
+ case AANDCC:
+ return int32(OPVCC(28, 0, 0, 0))
+ case AANDCC + AEND:
+ return int32(OPVCC(29, 0, 0, 0)) /* ANDIS./ANDIU. */
+
+ case ABR:
+ return int32(OPVCC(18, 0, 0, 0))
+ case ABL:
+ return int32(OPVCC(18, 0, 0, 0) | 1)
+ case ADUFFZERO:
+ return int32(OPVCC(18, 0, 0, 0) | 1)
+ case ADUFFCOPY:
+ return int32(OPVCC(18, 0, 0, 0) | 1)
+ case ABC:
+ return int32(OPVCC(16, 0, 0, 0))
+ case ABCL:
+ return int32(OPVCC(16, 0, 0, 0) | 1)
+
+ case ABEQ:
+ return int32(AOP_RRR(16<<26, 12, 2, 0))
+ case ABGE:
+ return int32(AOP_RRR(16<<26, 4, 0, 0))
+ case ABGT:
+ return int32(AOP_RRR(16<<26, 12, 1, 0))
+ case ABLE:
+ return int32(AOP_RRR(16<<26, 4, 1, 0))
+ case ABLT:
+ return int32(AOP_RRR(16<<26, 12, 0, 0))
+ case ABNE:
+ return int32(AOP_RRR(16<<26, 4, 2, 0))
+ case ABVC:
+ return int32(AOP_RRR(16<<26, 4, 3, 0))
+ case ABVS:
+ return int32(AOP_RRR(16<<26, 12, 3, 0))
+
+ case ACMP:
+ return int32(OPVCC(11, 0, 0, 0) | 1<<21) /* L=1 */
+ case ACMPU:
+ return int32(OPVCC(10, 0, 0, 0) | 1<<21)
+ case ACMPW:
+ return int32(OPVCC(11, 0, 0, 0)) /* L=0 */
+ case ACMPWU:
+ return int32(OPVCC(10, 0, 0, 0))
+ case ALSW:
+ return int32(OPVCC(31, 597, 0, 0))
+
+ case AMULLW:
+ return int32(OPVCC(7, 0, 0, 0))
+
+ case AOR:
+ return int32(OPVCC(24, 0, 0, 0))
+ case AOR + AEND:
+ return int32(OPVCC(25, 0, 0, 0)) /* ORIS/ORIU */
+
+ case ARLWMI:
+ return int32(OPVCC(20, 0, 0, 0)) /* rlwimi */
+ case ARLWMICC:
+ return int32(OPVCC(20, 0, 0, 1))
+ case ARLDMI:
+ return int32(OPVCC(30, 0, 0, 0) | 3<<2) /* rldimi */
+ case ARLDMICC:
+ return int32(OPVCC(30, 0, 0, 1) | 3<<2)
+
+ case ARLWNM:
+ return int32(OPVCC(21, 0, 0, 0)) /* rlwinm */
+ case ARLWNMCC:
+ return int32(OPVCC(21, 0, 0, 1))
+
+ case ARLDCL:
+ return int32(OPVCC(30, 0, 0, 0)) /* rldicl */
+ case ARLDCLCC:
+ return int32(OPVCC(30, 0, 0, 1))
+ case ARLDCR:
+ return int32(OPVCC(30, 1, 0, 0)) /* rldicr */
+ case ARLDCRCC:
+ return int32(OPVCC(30, 1, 0, 1))
+ case ARLDC:
+ return int32(OPVCC(30, 0, 0, 0) | 2<<2)
+ case ARLDCCC:
+ return int32(OPVCC(30, 0, 0, 1) | 2<<2)
+
+ case ASRAW:
+ return int32(OPVCC(31, 824, 0, 0))
+ case ASRAWCC:
+ return int32(OPVCC(31, 824, 0, 1))
+ case ASRAD:
+ return int32(OPVCC(31, (413 << 1), 0, 0))
+ case ASRADCC:
+ return int32(OPVCC(31, (413 << 1), 0, 1))
+
+ case ASTSW:
+ return int32(OPVCC(31, 725, 0, 0))
+
+ case ASUBC:
+ return int32(OPVCC(8, 0, 0, 0))
+
+ case ATW:
+ return int32(OPVCC(3, 0, 0, 0))
+ case ATD:
+ return int32(OPVCC(2, 0, 0, 0))
+
+ case AXOR:
+ return int32(OPVCC(26, 0, 0, 0)) /* XORIL */
+ case AXOR + AEND:
+ return int32(OPVCC(27, 0, 0, 0)) /* XORIU */
+ }
+
+ ctxt.Diag("bad opcode i/r %v", Aconv(a))
+ return 0
+}
+
+/*
+ * load o(a),d
+ */
+func opload(ctxt *obj.Link, a int) int32 {
+
+ switch a {
+ case AMOVD:
+ return int32(OPVCC(58, 0, 0, 0)) /* ld */
+ case AMOVDU:
+ return int32(OPVCC(58, 0, 0, 1)) /* ldu */
+ case AMOVWZ:
+ return int32(OPVCC(32, 0, 0, 0)) /* lwz */
+ case AMOVWZU:
+ return int32(OPVCC(33, 0, 0, 0)) /* lwzu */
+ case AMOVW:
+ return int32(OPVCC(58, 0, 0, 0) | 1<<1) /* lwa */
+
+ /* no AMOVWU */
+ case AMOVB,
+ AMOVBZ:
+ return int32(OPVCC(34, 0, 0, 0))
+ /* load */
+
+ case AMOVBU,
+ AMOVBZU:
+ return int32(OPVCC(35, 0, 0, 0))
+ case AFMOVD:
+ return int32(OPVCC(50, 0, 0, 0))
+ case AFMOVDU:
+ return int32(OPVCC(51, 0, 0, 0))
+ case AFMOVS:
+ return int32(OPVCC(48, 0, 0, 0))
+ case AFMOVSU:
+ return int32(OPVCC(49, 0, 0, 0))
+ case AMOVH:
+ return int32(OPVCC(42, 0, 0, 0))
+ case AMOVHU:
+ return int32(OPVCC(43, 0, 0, 0))
+ case AMOVHZ:
+ return int32(OPVCC(40, 0, 0, 0))
+ case AMOVHZU:
+ return int32(OPVCC(41, 0, 0, 0))
+ case AMOVMW:
+ return int32(OPVCC(46, 0, 0, 0)) /* lmw */
+ }
+
+ ctxt.Diag("bad load opcode %v", Aconv(a))
+ return 0
+}
+
+/*
+ * indexed load a(b),d
+ */
+func oploadx(ctxt *obj.Link, a int) int32 {
+
+ switch a {
+ case AMOVWZ:
+ return int32(OPVCC(31, 23, 0, 0)) /* lwzx */
+ case AMOVWZU:
+ return int32(OPVCC(31, 55, 0, 0)) /* lwzux */
+ case AMOVW:
+ return int32(OPVCC(31, 341, 0, 0)) /* lwax */
+ case AMOVWU:
+ return int32(OPVCC(31, 373, 0, 0)) /* lwaux */
+
+ case AMOVB,
+ AMOVBZ:
+ return int32(OPVCC(31, 87, 0, 0)) /* lbzx */
+
+ case AMOVBU,
+ AMOVBZU:
+ return int32(OPVCC(31, 119, 0, 0)) /* lbzux */
+ case AFMOVD:
+ return int32(OPVCC(31, 599, 0, 0)) /* lfdx */
+ case AFMOVDU:
+ return int32(OPVCC(31, 631, 0, 0)) /* lfdux */
+ case AFMOVS:
+ return int32(OPVCC(31, 535, 0, 0)) /* lfsx */
+ case AFMOVSU:
+ return int32(OPVCC(31, 567, 0, 0)) /* lfsux */
+ case AMOVH:
+ return int32(OPVCC(31, 343, 0, 0)) /* lhax */
+ case AMOVHU:
+ return int32(OPVCC(31, 375, 0, 0)) /* lhaux */
+ case AMOVHBR:
+ return int32(OPVCC(31, 790, 0, 0)) /* lhbrx */
+ case AMOVWBR:
+ return int32(OPVCC(31, 534, 0, 0)) /* lwbrx */
+ case AMOVHZ:
+ return int32(OPVCC(31, 279, 0, 0)) /* lhzx */
+ case AMOVHZU:
+ return int32(OPVCC(31, 311, 0, 0)) /* lhzux */
+ case AECIWX:
+ return int32(OPVCC(31, 310, 0, 0)) /* eciwx */
+ case ALWAR:
+ return int32(OPVCC(31, 20, 0, 0)) /* lwarx */
+ case ALDAR:
+ return int32(OPVCC(31, 84, 0, 0))
+ case ALSW:
+ return int32(OPVCC(31, 533, 0, 0)) /* lswx */
+ case AMOVD:
+ return int32(OPVCC(31, 21, 0, 0)) /* ldx */
+ case AMOVDU:
+ return int32(OPVCC(31, 53, 0, 0)) /* ldux */
+ }
+
+ ctxt.Diag("bad loadx opcode %v", Aconv(a))
+ return 0
+}
+
+/*
+ * store s,o(d)
+ */
+func opstore(ctxt *obj.Link, a int) int32 {
+
+ switch a {
+ case AMOVB,
+ AMOVBZ:
+ return int32(OPVCC(38, 0, 0, 0)) /* stb */
+
+ case AMOVBU,
+ AMOVBZU:
+ return int32(OPVCC(39, 0, 0, 0)) /* stbu */
+ case AFMOVD:
+ return int32(OPVCC(54, 0, 0, 0)) /* stfd */
+ case AFMOVDU:
+ return int32(OPVCC(55, 0, 0, 0)) /* stfdu */
+ case AFMOVS:
+ return int32(OPVCC(52, 0, 0, 0)) /* stfs */
+ case AFMOVSU:
+ return int32(OPVCC(53, 0, 0, 0)) /* stfsu */
+
+ case AMOVHZ,
+ AMOVH:
+ return int32(OPVCC(44, 0, 0, 0)) /* sth */
+
+ case AMOVHZU,
+ AMOVHU:
+ return int32(OPVCC(45, 0, 0, 0)) /* sthu */
+ case AMOVMW:
+ return int32(OPVCC(47, 0, 0, 0)) /* stmw */
+ case ASTSW:
+ return int32(OPVCC(31, 725, 0, 0)) /* stswi */
+
+ case AMOVWZ,
+ AMOVW:
+ return int32(OPVCC(36, 0, 0, 0)) /* stw */
+
+ case AMOVWZU,
+ AMOVWU:
+ return int32(OPVCC(37, 0, 0, 0)) /* stwu */
+ case AMOVD:
+ return int32(OPVCC(62, 0, 0, 0)) /* std */
+ case AMOVDU:
+ return int32(OPVCC(62, 0, 0, 1)) /* stdu */
+ }
+
+ ctxt.Diag("unknown store opcode %v", Aconv(a))
+ return 0
+}
+
+/*
+ * indexed store s,a(b)
+ */
+func opstorex(ctxt *obj.Link, a int) int32 {
+
+ switch a {
+ case AMOVB,
+ AMOVBZ:
+ return int32(OPVCC(31, 215, 0, 0)) /* stbx */
+
+ case AMOVBU,
+ AMOVBZU:
+ return int32(OPVCC(31, 247, 0, 0)) /* stbux */
+ case AFMOVD:
+ return int32(OPVCC(31, 727, 0, 0)) /* stfdx */
+ case AFMOVDU:
+ return int32(OPVCC(31, 759, 0, 0)) /* stfdux */
+ case AFMOVS:
+ return int32(OPVCC(31, 663, 0, 0)) /* stfsx */
+ case AFMOVSU:
+ return int32(OPVCC(31, 695, 0, 0)) /* stfsux */
+
+ case AMOVHZ,
+ AMOVH:
+ return int32(OPVCC(31, 407, 0, 0)) /* sthx */
+ case AMOVHBR:
+ return int32(OPVCC(31, 918, 0, 0)) /* sthbrx */
+
+ case AMOVHZU,
+ AMOVHU:
+ return int32(OPVCC(31, 439, 0, 0)) /* sthux */
+
+ case AMOVWZ,
+ AMOVW:
+ return int32(OPVCC(31, 151, 0, 0)) /* stwx */
+
+ case AMOVWZU,
+ AMOVWU:
+ return int32(OPVCC(31, 183, 0, 0)) /* stwux */
+ case ASTSW:
+ return int32(OPVCC(31, 661, 0, 0)) /* stswx */
+ case AMOVWBR:
+ return int32(OPVCC(31, 662, 0, 0)) /* stwbrx */
+ case ASTWCCC:
+ return int32(OPVCC(31, 150, 0, 1)) /* stwcx. */
+ case ASTDCCC:
+ return int32(OPVCC(31, 214, 0, 1)) /* stwdx. */
+ case AECOWX:
+ return int32(OPVCC(31, 438, 0, 0)) /* ecowx */
+ case AMOVD:
+ return int32(OPVCC(31, 149, 0, 0)) /* stdx */
+ case AMOVDU:
+ return int32(OPVCC(31, 181, 0, 0)) /* stdux */
+ }
+
+ ctxt.Diag("unknown storex opcode %v", Aconv(a))
+ return 0
+}
--- /dev/null
+// cmd/9l/list.c from Vita Nuova.
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package ppc64
+
+import (
+ "cmd/internal/obj"
+ "fmt"
+)
+
+const (
+ STRINGSZ = 1000
+)
+
+//
+// Format conversions
+// %A int Opcodes (instruction mnemonics)
+//
+// %D Addr* Addresses (instruction operands)
+// Flags: "%lD": seperate the high and low words of a constant by "-"
+//
+// %P Prog* Instructions
+//
+// %R int Registers
+//
+// %$ char* String constant addresses (for internal use only)
+// %^ int C_* classes (for liblink internal use)
+
+var bigP *obj.Prog
+
+func Pconv(p *obj.Prog) string {
+ var str string
+ var fp string
+
+ var a int
+ var ch int
+
+ a = int(p.As)
+
+ if a == ADATA || a == AINIT || a == ADYNT {
+ str = fmt.Sprintf("%.5d (%v)\t%v\t%v/%d,%v", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From), p.Reg, Dconv(p, 0, &p.To))
+ } else if a == ATEXT {
+ if p.Reg != 0 {
+ str = fmt.Sprintf("%.5d (%v) %v %v,%d,%v", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From), p.Reg, Dconv(p, fmtLong, &p.To))
+ } else {
+
+ str = fmt.Sprintf("%.5d (%v) %v %v,%v", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From), Dconv(p, fmtLong, &p.To))
+ }
+ } else if a == AGLOBL {
+ if p.Reg != 0 {
+ str = fmt.Sprintf("%.5d (%v) %v %v,%d,%v", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From), p.Reg, Dconv(p, 0, &p.To))
+ } else {
+
+ str = fmt.Sprintf("%.5d (%v) %v %v,%v", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From), Dconv(p, 0, &p.To))
+ }
+ } else {
+
+ if p.Mark&NOSCHED != 0 {
+ str += fmt.Sprintf("*")
+ }
+ if p.Reg == NREG && p.From3.Type == D_NONE {
+ str += fmt.Sprintf("%.5d (%v)\t%v\t%v,%v", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From), Dconv(p, 0, &p.To))
+ } else if a != ATEXT && p.From.Type == D_OREG {
+ str += fmt.Sprintf("%.5d (%v)\t%v\t%d(R%d+R%d),%v", p.Pc, p.Line(), Aconv(a), p.From.Offset, p.From.Reg, p.Reg, Dconv(p, 0, &p.To))
+ } else if p.To.Type == D_OREG {
+ str += fmt.Sprintf("%.5d (%v)\t%v\t%v,%d(R%d+R%d)", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From), p.To.Offset, p.To.Reg, p.Reg)
+ } else {
+
+ str += fmt.Sprintf("%.5d (%v)\t%v\t%v", p.Pc, p.Line(), Aconv(a), Dconv(p, 0, &p.From))
+ if p.Reg != NREG {
+ ch = 'R'
+ if p.From.Type == D_FREG {
+ ch = 'F'
+ }
+ str += fmt.Sprintf(",%c%d", ch, p.Reg)
+ }
+
+ if p.From3.Type != D_NONE {
+ str += fmt.Sprintf(",%v", Dconv(p, 0, &p.From3))
+ }
+ str += fmt.Sprintf(",%v", Dconv(p, 0, &p.To))
+ }
+
+ if p.Spadj != 0 {
+ fp += fmt.Sprintf("%s # spadj=%d", str, p.Spadj)
+ return fp
+ }
+ }
+
+ fp += str
+ return fp
+}
+
+func Aconv(a int) string {
+ var s string
+ var fp string
+
+ s = "???"
+ if a >= AXXX && a < ALAST {
+ s = Anames[a]
+ }
+ fp += s
+ return fp
+}
+
+func Dconv(p *obj.Prog, flag int, a *obj.Addr) string {
+ var str string
+ var fp string
+
+ var v int32
+
+ if flag&fmtLong != 0 /*untyped*/ {
+ if a.Type == D_CONST {
+ str = fmt.Sprintf("$%d-%d", int32(a.Offset), int32(a.Offset>>32))
+ } else {
+
+ // ATEXT dst is not constant
+ str = fmt.Sprintf("!!%v", Dconv(p, 0, a))
+ }
+
+ goto ret
+ }
+
+ switch a.Type {
+ default:
+ str = fmt.Sprintf("GOK-type(%d)", a.Type)
+
+ case D_NONE:
+ str = ""
+ if a.Name != D_NONE || a.Reg != NREG || a.Sym != nil {
+ str = fmt.Sprintf("%v(R%d)(NONE)", Mconv(a), a.Reg)
+ }
+
+ case D_CONST,
+ D_DCONST:
+ if a.Reg != NREG {
+ str = fmt.Sprintf("$%v(R%d)", Mconv(a), a.Reg)
+ } else {
+
+ str = fmt.Sprintf("$%v", Mconv(a))
+ }
+
+ case D_OREG:
+ if a.Reg != NREG {
+ str = fmt.Sprintf("%v(R%d)", Mconv(a), a.Reg)
+ } else {
+
+ str = fmt.Sprintf("%v", Mconv(a))
+ }
+
+ case D_REG:
+ str = fmt.Sprintf("R%d", a.Reg)
+ if a.Name != D_NONE || a.Sym != nil {
+ str = fmt.Sprintf("%v(R%d)(REG)", Mconv(a), a.Reg)
+ }
+
+ case D_FREG:
+ str = fmt.Sprintf("F%d", a.Reg)
+ if a.Name != D_NONE || a.Sym != nil {
+ str = fmt.Sprintf("%v(F%d)(REG)", Mconv(a), a.Reg)
+ }
+
+ case D_CREG:
+ if a.Reg == NREG {
+ str = "CR"
+ } else {
+
+ str = fmt.Sprintf("CR%d", a.Reg)
+ }
+ if a.Name != D_NONE || a.Sym != nil {
+ str = fmt.Sprintf("%v(C%d)(REG)", Mconv(a), a.Reg)
+ }
+
+ case D_SPR:
+ if a.Name == D_NONE && a.Sym == nil {
+ switch uint32(a.Offset) {
+ case D_XER:
+ str = fmt.Sprintf("XER")
+ case D_LR:
+ str = fmt.Sprintf("LR")
+ case D_CTR:
+ str = fmt.Sprintf("CTR")
+ default:
+ str = fmt.Sprintf("SPR(%d)", a.Offset)
+ break
+ }
+
+ break
+ }
+
+ str = fmt.Sprintf("SPR-GOK(%d)", a.Reg)
+ if a.Name != D_NONE || a.Sym != nil {
+ str = fmt.Sprintf("%v(SPR-GOK%d)(REG)", Mconv(a), a.Reg)
+ }
+
+ case D_DCR:
+ if a.Name == D_NONE && a.Sym == nil {
+ str = fmt.Sprintf("DCR(%d)", a.Offset)
+ break
+ }
+
+ str = fmt.Sprintf("DCR-GOK(%d)", a.Reg)
+ if a.Name != D_NONE || a.Sym != nil {
+ str = fmt.Sprintf("%v(DCR-GOK%d)(REG)", Mconv(a), a.Reg)
+ }
+
+ case D_OPT:
+ str = fmt.Sprintf("OPT(%d)", a.Reg)
+
+ case D_FPSCR:
+ if a.Reg == NREG {
+ str = "FPSCR"
+ } else {
+
+ str = fmt.Sprintf("FPSCR(%d)", a.Reg)
+ }
+
+ case D_MSR:
+ str = fmt.Sprintf("MSR")
+
+ case D_BRANCH:
+ if p.Pcond != nil {
+ v = int32(p.Pcond.Pc)
+
+ //if(v >= INITTEXT)
+ // v -= INITTEXT-HEADR;
+ if a.Sym != nil {
+
+ str = fmt.Sprintf("%s+%.5x(BRANCH)", a.Sym.Name, uint32(v))
+ } else {
+
+ str = fmt.Sprintf("%.5x(BRANCH)", uint32(v))
+ }
+ } else if a.U.Branch != nil {
+ str = fmt.Sprintf("%d", a.U.Branch.Pc)
+ } else if a.Sym != nil {
+ str = fmt.Sprintf("%s+%d(APC)", a.Sym.Name, a.Offset)
+ } else {
+
+ str = fmt.Sprintf("%d(APC)", a.Offset)
+ }
+
+ //sprint(str, "$%lux-%lux", a->ieee.h, a->ieee.l);
+ case D_FCONST:
+ str = fmt.Sprintf("$%.17g", a.U.Dval)
+
+ case D_SCONST:
+ str = fmt.Sprintf("$\"%q\"", a.U.Sval)
+ break
+ }
+
+ret:
+ fp += str
+ return fp
+}
+
+func Mconv(a *obj.Addr) string {
+ var str string
+ var fp string
+
+ var s *obj.LSym
+ var l int32
+
+ s = a.Sym
+
+ //if(s == nil) {
+ // l = a->offset;
+ // if((vlong)l != a->offset)
+ // sprint(str, "0x%llux", a->offset);
+ // else
+ // sprint(str, "%lld", a->offset);
+ // goto out;
+ //}
+ switch a.Name {
+
+ default:
+ str = fmt.Sprintf("GOK-name(%d)", a.Name)
+
+ case D_NONE:
+ l = int32(a.Offset)
+ if int64(l) != a.Offset {
+ str = fmt.Sprintf("0x%x", uint64(a.Offset))
+ } else {
+
+ str = fmt.Sprintf("%d", a.Offset)
+ }
+
+ case D_EXTERN:
+ if a.Offset != 0 {
+ str = fmt.Sprintf("%s+%d(SB)", s.Name, a.Offset)
+ } else {
+
+ str = fmt.Sprintf("%s(SB)", s.Name)
+ }
+
+ case D_STATIC:
+ str = fmt.Sprintf("%s<>+%d(SB)", s.Name, a.Offset)
+
+ case D_AUTO:
+ if s == nil {
+ str = fmt.Sprintf("%d(SP)", -a.Offset)
+ } else {
+
+ str = fmt.Sprintf("%s-%d(SP)", s.Name, -a.Offset)
+ }
+
+ case D_PARAM:
+ if s == nil {
+ str = fmt.Sprintf("%d(FP)", a.Offset)
+ } else {
+
+ str = fmt.Sprintf("%s+%d(FP)", s.Name, a.Offset)
+ }
+ break
+ }
+
+ //out:
+ fp += str
+ return fp
+}
+
+func Rconv(r int) string {
+ var str string
+ var fp string
+
+ if r < NREG {
+ str = fmt.Sprintf("r%d", r)
+ } else {
+
+ str = fmt.Sprintf("f%d", r-NREG)
+ }
+ fp += str
+ return fp
+}
+
+func DRconv(a int) string {
+ var s string
+ var fp string
+
+ s = "C_??"
+ if a >= C_NONE && a <= C_NCLASS {
+ s = cnames9[a]
+ }
+ fp += s
+ return fp
+}
--- /dev/null
+// cmd/9l/noop.c, cmd/9l/pass.c, cmd/9l/span.c from Vita Nuova.
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package ppc64
+
+import (
+ "cmd/internal/obj"
+ "encoding/binary"
+ "fmt"
+ "math"
+)
+
+var zprg = obj.Prog{
+ As: AGOK,
+ Reg: NREG,
+ From: obj.Addr{
+ Name: D_NONE,
+ Type: D_NONE,
+ Reg: NREG,
+ },
+ From3: obj.Addr{
+ Name: D_NONE,
+ Type: D_NONE,
+ Reg: NREG,
+ },
+ To: obj.Addr{
+ Name: D_NONE,
+ Type: D_NONE,
+ Reg: NREG,
+ },
+}
+
+func symtype(a *obj.Addr) int {
+ return int(a.Name)
+}
+
+func isdata(p *obj.Prog) bool {
+ return p.As == ADATA || p.As == AGLOBL
+}
+
+func iscall(p *obj.Prog) bool {
+ return p.As == ABL
+}
+
+func datasize(p *obj.Prog) int {
+ return int(p.Reg)
+}
+
+func textflag(p *obj.Prog) int {
+ return int(p.Reg)
+}
+
+func settextflag(p *obj.Prog, f int) {
+ p.Reg = uint8(f)
+}
+
+func progedit(ctxt *obj.Link, p *obj.Prog) {
+ var literal string
+ var s *obj.LSym
+
+ p.From.Class = 0
+ p.To.Class = 0
+
+ // Rewrite BR/BL to symbol as D_BRANCH.
+ switch p.As {
+
+ case ABR,
+ ABL,
+ ARETURN,
+ ADUFFZERO,
+ ADUFFCOPY:
+ if p.To.Sym != nil {
+ p.To.Type = D_BRANCH
+ }
+ break
+ }
+
+ // Rewrite float constants to values stored in memory.
+ switch p.As {
+
+ case AFMOVS:
+ if p.From.Type == D_FCONST {
+ var i32 uint32
+ var f32 float32
+ f32 = float32(p.From.U.Dval)
+ i32 = math.Float32bits(f32)
+ literal = fmt.Sprintf("$f32.%08x", i32)
+ s = obj.Linklookup(ctxt, literal, 0)
+ s.Size = 4
+ p.From.Type = D_OREG
+ p.From.Sym = s
+ p.From.Name = D_EXTERN
+ p.From.Offset = 0
+ }
+
+ case AFMOVD:
+ if p.From.Type == D_FCONST {
+ var i64 uint64
+ i64 = math.Float64bits(p.From.U.Dval)
+ literal = fmt.Sprintf("$f64.%016x", i64)
+ s = obj.Linklookup(ctxt, literal, 0)
+ s.Size = 8
+ p.From.Type = D_OREG
+ p.From.Sym = s
+ p.From.Name = D_EXTERN
+ p.From.Offset = 0
+ }
+
+ // Put >32-bit constants in memory and load them
+ case AMOVD:
+ if p.From.Type == D_CONST && p.From.Name == D_NONE && p.From.Reg == NREG && int64(int32(p.From.Offset)) != p.From.Offset {
+
+ literal = fmt.Sprintf("$i64.%016x", uint64(p.From.Offset))
+ s = obj.Linklookup(ctxt, literal, 0)
+ s.Size = 8
+ p.From.Type = D_OREG
+ p.From.Sym = s
+ p.From.Name = D_EXTERN
+ p.From.Offset = 0
+ }
+ }
+
+ // Rewrite SUB constants into ADD.
+ switch p.As {
+
+ case ASUBC:
+ if p.From.Type == D_CONST {
+ p.From.Offset = -p.From.Offset
+ p.As = AADDC
+ }
+
+ case ASUBCCC:
+ if p.From.Type == D_CONST {
+ p.From.Offset = -p.From.Offset
+ p.As = AADDCCC
+ }
+
+ case ASUB:
+ if p.From.Type == D_CONST {
+ p.From.Offset = -p.From.Offset
+ p.As = AADD
+ }
+
+ break
+ }
+}
+
+func parsetextconst(arg int64, textstksiz *int64, textarg *int64) {
+ *textstksiz = arg & 0xffffffff
+ if *textstksiz&0x80000000 != 0 {
+ *textstksiz = -(-*textstksiz & 0xffffffff)
+ }
+
+ *textarg = (arg >> 32) & 0xffffffff
+ if *textarg&0x80000000 != 0 {
+ *textarg = 0
+ }
+ *textarg = (*textarg + 7) &^ 7
+}
+
+func addstacksplit(ctxt *obj.Link, cursym *obj.LSym) {
+ var p *obj.Prog
+ var q *obj.Prog
+ var p1 *obj.Prog
+ var p2 *obj.Prog
+ var q1 *obj.Prog
+ var o int
+ var mov int
+ var aoffset int
+ var textstksiz int64
+ var textarg int64
+ var autosize int32
+
+ if ctxt.Symmorestack[0] == nil {
+ ctxt.Symmorestack[0] = obj.Linklookup(ctxt, "runtime.morestack", 0)
+ ctxt.Symmorestack[1] = obj.Linklookup(ctxt, "runtime.morestack_noctxt", 0)
+ }
+
+ // TODO(minux): add morestack short-cuts with small fixed frame-size.
+ ctxt.Cursym = cursym
+
+ if cursym.Text == nil || cursym.Text.Link == nil {
+ return
+ }
+
+ p = cursym.Text
+ parsetextconst(p.To.Offset, &textstksiz, &textarg)
+
+ cursym.Args = int32(p.To.Offset >> 32)
+ cursym.Locals = int32(textstksiz)
+
+ /*
+ * find leaf subroutines
+ * strip NOPs
+ * expand RET
+ * expand BECOME pseudo
+ */
+ if ctxt.Debugvlog != 0 {
+
+ fmt.Fprintf(ctxt.Bso, "%5.2f noops\n", obj.Cputime())
+ }
+ obj.Bflush(ctxt.Bso)
+
+ q = nil
+ for p = cursym.Text; p != nil; p = p.Link {
+ switch p.As {
+ /* too hard, just leave alone */
+ case ATEXT:
+ q = p
+
+ p.Mark |= LABEL | LEAF | SYNC
+ if p.Link != nil {
+ p.Link.Mark |= LABEL
+ }
+
+ case ANOR:
+ q = p
+ if p.To.Type == D_REG {
+ if p.To.Reg == REGZERO {
+ p.Mark |= LABEL | SYNC
+ }
+ }
+
+ case ALWAR,
+ ASTWCCC,
+ AECIWX,
+ AECOWX,
+ AEIEIO,
+ AICBI,
+ AISYNC,
+ ATLBIE,
+ ATLBIEL,
+ ASLBIA,
+ ASLBIE,
+ ASLBMFEE,
+ ASLBMFEV,
+ ASLBMTE,
+ ADCBF,
+ ADCBI,
+ ADCBST,
+ ADCBT,
+ ADCBTST,
+ ADCBZ,
+ ASYNC,
+ ATLBSYNC,
+ APTESYNC,
+ ATW,
+ AWORD,
+ ARFI,
+ ARFCI,
+ ARFID,
+ AHRFID:
+ q = p
+ p.Mark |= LABEL | SYNC
+ continue
+
+ case AMOVW,
+ AMOVWZ,
+ AMOVD:
+ q = p
+ switch p.From.Type {
+ case D_MSR,
+ D_SPR,
+ D_FPSCR,
+ D_CREG,
+ D_DCR:
+ p.Mark |= LABEL | SYNC
+ }
+
+ switch p.To.Type {
+ case D_MSR,
+ D_SPR,
+ D_FPSCR,
+ D_CREG,
+ D_DCR:
+ p.Mark |= LABEL | SYNC
+ }
+
+ continue
+
+ case AFABS,
+ AFABSCC,
+ AFADD,
+ AFADDCC,
+ AFCTIW,
+ AFCTIWCC,
+ AFCTIWZ,
+ AFCTIWZCC,
+ AFDIV,
+ AFDIVCC,
+ AFMADD,
+ AFMADDCC,
+ AFMOVD,
+ AFMOVDU,
+ /* case AFMOVDS: */
+ AFMOVS,
+ AFMOVSU,
+
+ /* case AFMOVSD: */
+ AFMSUB,
+ AFMSUBCC,
+ AFMUL,
+ AFMULCC,
+ AFNABS,
+ AFNABSCC,
+ AFNEG,
+ AFNEGCC,
+ AFNMADD,
+ AFNMADDCC,
+ AFNMSUB,
+ AFNMSUBCC,
+ AFRSP,
+ AFRSPCC,
+ AFSUB,
+ AFSUBCC:
+ q = p
+
+ p.Mark |= FLOAT
+ continue
+
+ case ABL,
+ ABCL,
+ ADUFFZERO,
+ ADUFFCOPY:
+ cursym.Text.Mark &^= LEAF
+ fallthrough
+
+ case ABC,
+ ABEQ,
+ ABGE,
+ ABGT,
+ ABLE,
+ ABLT,
+ ABNE,
+ ABR,
+ ABVC,
+ ABVS:
+ p.Mark |= BRANCH
+ q = p
+ q1 = p.Pcond
+ if q1 != nil {
+ for q1.As == ANOP {
+ q1 = q1.Link
+ p.Pcond = q1
+ }
+
+ if !(q1.Mark&LEAF != 0) {
+ q1.Mark |= LABEL
+ }
+ } else {
+
+ p.Mark |= LABEL
+ }
+ q1 = p.Link
+ if q1 != nil {
+ q1.Mark |= LABEL
+ }
+ continue
+
+ case AFCMPO,
+ AFCMPU:
+ q = p
+ p.Mark |= FCMP | FLOAT
+ continue
+
+ case ARETURN:
+ q = p
+ if p.Link != nil {
+ p.Link.Mark |= LABEL
+ }
+ continue
+
+ case ANOP:
+ q1 = p.Link
+ q.Link = q1 /* q is non-nop */
+ q1.Mark |= p.Mark
+ continue
+
+ default:
+ q = p
+ continue
+ }
+ }
+
+ autosize = 0
+ for p = cursym.Text; p != nil; p = p.Link {
+ o = int(p.As)
+ switch o {
+ case ATEXT:
+ mov = AMOVD
+ aoffset = 0
+ autosize = int32(textstksiz + 8)
+ if (p.Mark&LEAF != 0) && autosize <= 8 {
+ autosize = 0
+ } else if autosize&4 != 0 {
+ autosize += 4
+ }
+ p.To.Offset = int64(uint64(p.To.Offset)&(0xffffffff<<32) | uint64(uint32(autosize-8)))
+
+ if !(p.Reg&obj.NOSPLIT != 0) {
+ p = stacksplit(ctxt, p, autosize, bool2int(!(cursym.Text.Reg&obj.NEEDCTXT != 0))) // emit split check
+ }
+
+ q = p
+
+ if autosize != 0 {
+ /* use MOVDU to adjust R1 when saving R31, if autosize is small */
+ if !(cursym.Text.Mark&LEAF != 0) && autosize >= -BIG && autosize <= BIG {
+
+ mov = AMOVDU
+ aoffset = int(-autosize)
+ } else {
+
+ q = obj.Appendp(ctxt, p)
+ q.As = AADD
+ q.Lineno = p.Lineno
+ q.From.Type = D_CONST
+ q.From.Offset = int64(-autosize)
+ q.To.Type = D_REG
+ q.To.Reg = REGSP
+ q.Spadj = +autosize
+ }
+ } else if !(cursym.Text.Mark&LEAF != 0) {
+ if ctxt.Debugvlog != 0 {
+ fmt.Fprintf(ctxt.Bso, "save suppressed in: %s\n", cursym.Name)
+ obj.Bflush(ctxt.Bso)
+ }
+
+ cursym.Text.Mark |= LEAF
+ }
+
+ if cursym.Text.Mark&LEAF != 0 {
+ cursym.Leaf = 1
+ break
+ }
+
+ q = obj.Appendp(ctxt, q)
+ q.As = AMOVD
+ q.Lineno = p.Lineno
+ q.From.Type = D_SPR
+ q.From.Offset = D_LR
+ q.To.Type = D_REG
+ q.To.Reg = REGTMP
+
+ q = obj.Appendp(ctxt, q)
+ q.As = int16(mov)
+ q.Lineno = p.Lineno
+ q.From.Type = D_REG
+ q.From.Reg = REGTMP
+ q.To.Type = D_OREG
+ q.To.Offset = int64(aoffset)
+ q.To.Reg = REGSP
+ if q.As == AMOVDU {
+ q.Spadj = int32(-aoffset)
+ }
+
+ if cursym.Text.Reg&obj.WRAPPER != 0 {
+ // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
+ //
+ // MOVD g_panic(g), R3
+ // CMP R0, R3
+ // BEQ end
+ // MOVD panic_argp(R3), R4
+ // ADD $(autosize+8), R1, R5
+ // CMP R4, R5
+ // BNE end
+ // ADD $8, R1, R6
+ // MOVD R6, panic_argp(R3)
+ // end:
+ // NOP
+ //
+ // The NOP is needed to give the jumps somewhere to land.
+ // It is a liblink NOP, not a ppc64 NOP: it encodes to 0 instruction bytes.
+
+ q = obj.Appendp(ctxt, q)
+
+ q.As = AMOVD
+ q.From.Type = D_OREG
+ q.From.Reg = REGG
+ q.From.Offset = 4 * int64(ctxt.Arch.Ptrsize) // G.panic
+ q.To.Type = D_REG
+ q.To.Reg = 3
+
+ q = obj.Appendp(ctxt, q)
+ q.As = ACMP
+ q.From.Type = D_REG
+ q.From.Reg = 0
+ q.To.Type = D_REG
+ q.To.Reg = 3
+
+ q = obj.Appendp(ctxt, q)
+ q.As = ABEQ
+ q.To.Type = D_BRANCH
+ p1 = q
+
+ q = obj.Appendp(ctxt, q)
+ q.As = AMOVD
+ q.From.Type = D_OREG
+ q.From.Reg = 3
+ q.From.Offset = 0 // Panic.argp
+ q.To.Type = D_REG
+ q.To.Reg = 4
+
+ q = obj.Appendp(ctxt, q)
+ q.As = AADD
+ q.From.Type = D_CONST
+ q.From.Offset = int64(autosize) + 8
+ q.Reg = REGSP
+ q.To.Type = D_REG
+ q.To.Reg = 5
+
+ q = obj.Appendp(ctxt, q)
+ q.As = ACMP
+ q.From.Type = D_REG
+ q.From.Reg = 4
+ q.To.Type = D_REG
+ q.To.Reg = 5
+
+ q = obj.Appendp(ctxt, q)
+ q.As = ABNE
+ q.To.Type = D_BRANCH
+ p2 = q
+
+ q = obj.Appendp(ctxt, q)
+ q.As = AADD
+ q.From.Type = D_CONST
+ q.From.Offset = 8
+ q.Reg = REGSP
+ q.To.Type = D_REG
+ q.To.Reg = 6
+
+ q = obj.Appendp(ctxt, q)
+ q.As = AMOVD
+ q.From.Type = D_REG
+ q.From.Reg = 6
+ q.To.Type = D_OREG
+ q.To.Reg = 3
+ q.To.Offset = 0 // Panic.argp
+
+ q = obj.Appendp(ctxt, q)
+
+ q.As = ANOP
+ p1.Pcond = q
+ p2.Pcond = q
+ }
+
+ case ARETURN:
+ if p.From.Type == D_CONST {
+ ctxt.Diag("using BECOME (%v) is not supported!", p)
+ break
+ }
+
+ if p.To.Sym != nil { // retjmp
+ p.As = ABR
+ p.To.Type = D_BRANCH
+ break
+ }
+
+ if cursym.Text.Mark&LEAF != 0 {
+ if !(autosize != 0) {
+ p.As = ABR
+ p.From = zprg.From
+ p.To.Type = D_SPR
+ p.To.Offset = D_LR
+ p.Mark |= BRANCH
+ break
+ }
+
+ p.As = AADD
+ p.From.Type = D_CONST
+ p.From.Offset = int64(autosize)
+ p.To.Type = D_REG
+ p.To.Reg = REGSP
+ p.Spadj = -autosize
+
+ q = ctxt.NewProg()
+ q.As = ABR
+ q.Lineno = p.Lineno
+ q.To.Type = D_SPR
+ q.To.Offset = D_LR
+ q.Mark |= BRANCH
+ q.Spadj = +autosize
+
+ q.Link = p.Link
+ p.Link = q
+ break
+ }
+
+ p.As = AMOVD
+ p.From.Type = D_OREG
+ p.From.Offset = 0
+ p.From.Reg = REGSP
+ p.To.Type = D_REG
+ p.To.Reg = REGTMP
+
+ q = ctxt.NewProg()
+ q.As = AMOVD
+ q.Lineno = p.Lineno
+ q.From.Type = D_REG
+ q.From.Reg = REGTMP
+ q.To.Type = D_SPR
+ q.To.Offset = D_LR
+
+ q.Link = p.Link
+ p.Link = q
+ p = q
+
+ if false {
+ // Debug bad returns
+ q = ctxt.NewProg()
+
+ q.As = AMOVD
+ q.Lineno = p.Lineno
+ q.From.Type = D_OREG
+ q.From.Offset = 0
+ q.From.Reg = REGTMP
+ q.To.Type = D_REG
+ q.To.Reg = REGTMP
+
+ q.Link = p.Link
+ p.Link = q
+ p = q
+ }
+
+ if autosize != 0 {
+ q = ctxt.NewProg()
+ q.As = AADD
+ q.Lineno = p.Lineno
+ q.From.Type = D_CONST
+ q.From.Offset = int64(autosize)
+ q.To.Type = D_REG
+ q.To.Reg = REGSP
+ q.Spadj = -autosize
+
+ q.Link = p.Link
+ p.Link = q
+ }
+
+ q1 = ctxt.NewProg()
+ q1.As = ABR
+ q1.Lineno = p.Lineno
+ q1.To.Type = D_SPR
+ q1.To.Offset = D_LR
+ q1.Mark |= BRANCH
+ q1.Spadj = +autosize
+
+ q1.Link = q.Link
+ q.Link = q1
+
+ case AADD:
+ if p.To.Type == D_REG && p.To.Reg == REGSP && p.From.Type == D_CONST {
+ p.Spadj = int32(-p.From.Offset)
+ }
+ break
+ }
+ }
+}
+
+/*
+// instruction scheduling
+ if(debug['Q'] == 0)
+ return;
+
+ curtext = nil;
+ q = nil; // p - 1
+ q1 = firstp; // top of block
+ o = 0; // count of instructions
+ for(p = firstp; p != nil; p = p1) {
+ p1 = p->link;
+ o++;
+ if(p->mark & NOSCHED){
+ if(q1 != p){
+ sched(q1, q);
+ }
+ for(; p != nil; p = p->link){
+ if(!(p->mark & NOSCHED))
+ break;
+ q = p;
+ }
+ p1 = p;
+ q1 = p;
+ o = 0;
+ continue;
+ }
+ if(p->mark & (LABEL|SYNC)) {
+ if(q1 != p)
+ sched(q1, q);
+ q1 = p;
+ o = 1;
+ }
+ if(p->mark & (BRANCH|SYNC)) {
+ sched(q1, p);
+ q1 = p1;
+ o = 0;
+ }
+ if(o >= NSCHED) {
+ sched(q1, p);
+ q1 = p1;
+ o = 0;
+ }
+ q = p;
+ }
+*/
+func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32, noctxt int) *obj.Prog {
+
+ var q *obj.Prog
+ var q1 *obj.Prog
+
+ // MOVD g_stackguard(g), R3
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AMOVD
+ p.From.Type = D_OREG
+ p.From.Reg = REGG
+ p.From.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
+ if ctxt.Cursym.Cfunc != 0 {
+ p.From.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
+ }
+ p.To.Type = D_REG
+ p.To.Reg = 3
+
+ q = nil
+ if framesize <= obj.StackSmall {
+ // small stack: SP < stackguard
+ // CMP stackguard, SP
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ACMPU
+ p.From.Type = D_REG
+ p.From.Reg = 3
+ p.To.Type = D_REG
+ p.To.Reg = REGSP
+ } else if framesize <= obj.StackBig {
+ // large stack: SP-framesize < stackguard-StackSmall
+ // ADD $-framesize, SP, R4
+ // CMP stackguard, R4
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AADD
+ p.From.Type = D_CONST
+ p.From.Offset = int64(-framesize)
+ p.Reg = REGSP
+ p.To.Type = D_REG
+ p.To.Reg = 4
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ACMPU
+ p.From.Type = D_REG
+ p.From.Reg = 3
+ p.To.Type = D_REG
+ p.To.Reg = 4
+ } else {
+
+ // Such a large stack we need to protect against wraparound.
+ // If SP is close to zero:
+ // SP-stackguard+StackGuard <= framesize + (StackGuard-StackSmall)
+ // The +StackGuard on both sides is required to keep the left side positive:
+ // SP is allowed to be slightly below stackguard. See stack.h.
+ //
+ // Preemption sets stackguard to StackPreempt, a very large value.
+ // That breaks the math above, so we have to check for that explicitly.
+ // // stackguard is R3
+ // CMP R3, $StackPreempt
+ // BEQ label-of-call-to-morestack
+ // ADD $StackGuard, SP, R4
+ // SUB R3, R4
+ // MOVD $(framesize+(StackGuard-StackSmall)), R31
+ // CMPU R31, R4
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ACMP
+ p.From.Type = D_REG
+ p.From.Reg = 3
+ p.To.Type = D_CONST
+ p.To.Offset = obj.StackPreempt
+
+ p = obj.Appendp(ctxt, p)
+ q = p
+ p.As = ABEQ
+ p.To.Type = D_BRANCH
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AADD
+ p.From.Type = D_CONST
+ p.From.Offset = obj.StackGuard
+ p.Reg = REGSP
+ p.To.Type = D_REG
+ p.To.Reg = 4
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ASUB
+ p.From.Type = D_REG
+ p.From.Reg = 3
+ p.To.Type = D_REG
+ p.To.Reg = 4
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AMOVD
+ p.From.Type = D_CONST
+ p.From.Offset = int64(framesize) + obj.StackGuard - obj.StackSmall
+ p.To.Type = D_REG
+ p.To.Reg = REGTMP
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ACMPU
+ p.From.Type = D_REG
+ p.From.Reg = REGTMP
+ p.To.Type = D_REG
+ p.To.Reg = 4
+ }
+
+ // q1: BLT done
+ p = obj.Appendp(ctxt, p)
+ q1 = p
+
+ p.As = ABLT
+ p.To.Type = D_BRANCH
+
+ // MOVD LR, R5
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AMOVD
+ p.From.Type = D_SPR
+ p.From.Offset = D_LR
+ p.To.Type = D_REG
+ p.To.Reg = 5
+ if q != nil {
+ q.Pcond = p
+ }
+
+ // BL runtime.morestack(SB)
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ABL
+ p.To.Type = D_BRANCH
+ if ctxt.Cursym.Cfunc != 0 {
+ p.To.Sym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
+ } else {
+
+ p.To.Sym = ctxt.Symmorestack[noctxt]
+ }
+
+ // BR start
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ABR
+ p.To.Type = D_BRANCH
+ p.Pcond = ctxt.Cursym.Text.Link
+
+ // placeholder for q1's jump target
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ANOP // zero-width place holder
+ q1.Pcond = p
+
+ return p
+}
+
+func follow(ctxt *obj.Link, s *obj.LSym) {
+ var firstp *obj.Prog
+ var lastp *obj.Prog
+
+ ctxt.Cursym = s
+
+ firstp = ctxt.NewProg()
+ lastp = firstp
+ xfol(ctxt, s.Text, &lastp)
+ lastp.Link = nil
+ s.Text = firstp.Link
+}
+
+func relinv(a int) int {
+ switch a {
+ case ABEQ:
+ return ABNE
+ case ABNE:
+ return ABEQ
+
+ case ABGE:
+ return ABLT
+ case ABLT:
+ return ABGE
+
+ case ABGT:
+ return ABLE
+ case ABLE:
+ return ABGT
+
+ case ABVC:
+ return ABVS
+ case ABVS:
+ return ABVC
+ }
+
+ return 0
+}
+
+func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
+ var q *obj.Prog
+ var r *obj.Prog
+ var a int
+ var b int
+ var i int
+
+loop:
+ if p == nil {
+ return
+ }
+ a = int(p.As)
+ if a == ABR {
+ q = p.Pcond
+ if (p.Mark&NOSCHED != 0) || q != nil && (q.Mark&NOSCHED != 0) {
+ p.Mark |= FOLL
+ (*last).Link = p
+ *last = p
+ p = p.Link
+ xfol(ctxt, p, last)
+ p = q
+ if p != nil && !(p.Mark&FOLL != 0) {
+ goto loop
+ }
+ return
+ }
+
+ if q != nil {
+ p.Mark |= FOLL
+ p = q
+ if !(p.Mark&FOLL != 0) {
+ goto loop
+ }
+ }
+ }
+
+ if p.Mark&FOLL != 0 {
+ i = 0
+ q = p
+ for ; i < 4; (func() { i++; q = q.Link })() {
+ if q == *last || (q.Mark&NOSCHED != 0) {
+ break
+ }
+ b = 0 /* set */
+ a = int(q.As)
+ if a == ANOP {
+ i--
+ continue
+ }
+
+ if a == ABR || a == ARETURN || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID {
+ goto copy
+ }
+ if !(q.Pcond != nil) || (q.Pcond.Mark&FOLL != 0) {
+ continue
+ }
+ b = relinv(a)
+ if !(b != 0) {
+ continue
+ }
+
+ copy:
+ for {
+ r = ctxt.NewProg()
+ *r = *p
+ if !(r.Mark&FOLL != 0) {
+ fmt.Printf("cant happen 1\n")
+ }
+ r.Mark |= FOLL
+ if p != q {
+ p = p.Link
+ (*last).Link = r
+ *last = r
+ continue
+ }
+
+ (*last).Link = r
+ *last = r
+ if a == ABR || a == ARETURN || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID {
+ return
+ }
+ r.As = int16(b)
+ r.Pcond = p.Link
+ r.Link = p.Pcond
+ if !(r.Link.Mark&FOLL != 0) {
+ xfol(ctxt, r.Link, last)
+ }
+ if !(r.Pcond.Mark&FOLL != 0) {
+ fmt.Printf("cant happen 2\n")
+ }
+ return
+ }
+ }
+
+ a = ABR
+ q = ctxt.NewProg()
+ q.As = int16(a)
+ q.Lineno = p.Lineno
+ q.To.Type = D_BRANCH
+ q.To.Offset = p.Pc
+ q.Pcond = p
+ p = q
+ }
+
+ p.Mark |= FOLL
+ (*last).Link = p
+ *last = p
+ if a == ABR || a == ARETURN || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID {
+ if p.Mark&NOSCHED != 0 {
+ p = p.Link
+ goto loop
+ }
+
+ return
+ }
+
+ if p.Pcond != nil {
+ if a != ABL && p.Link != nil {
+ xfol(ctxt, p.Link, last)
+ p = p.Pcond
+ if p == nil || (p.Mark&FOLL != 0) {
+ return
+ }
+ goto loop
+ }
+ }
+
+ p = p.Link
+ goto loop
+}
+
+func prg() *obj.Prog {
+ p := zprg
+ return &p
+}
+
+var Linkppc64 = obj.LinkArch{
+ ByteOrder: binary.BigEndian,
+ Pconv: Pconv,
+ Name: "ppc64",
+ Thechar: '9',
+ Endian: obj.BigEndian,
+ Addstacksplit: addstacksplit,
+ Assemble: span9,
+ Datasize: datasize,
+ Follow: follow,
+ Iscall: iscall,
+ Isdata: isdata,
+ Prg: prg,
+ Progedit: progedit,
+ Settextflag: settextflag,
+ Symtype: symtype,
+ Textflag: textflag,
+ Minlc: 4,
+ Ptrsize: 8,
+ Regsize: 8,
+ D_ADDR: D_ADDR,
+ D_AUTO: D_AUTO,
+ D_BRANCH: D_BRANCH,
+ D_CONST: D_CONST,
+ D_EXTERN: D_EXTERN,
+ D_FCONST: D_FCONST,
+ D_NONE: D_NONE,
+ D_PARAM: D_PARAM,
+ D_SCONST: D_SCONST,
+ D_STATIC: D_STATIC,
+ D_OREG: D_OREG,
+ ACALL: ABL,
+ ADATA: ADATA,
+ AEND: AEND,
+ AFUNCDATA: AFUNCDATA,
+ AGLOBL: AGLOBL,
+ AJMP: ABR,
+ ANOP: ANOP,
+ APCDATA: APCDATA,
+ ARET: ARETURN,
+ ATEXT: ATEXT,
+ ATYPE: ATYPE,
+ AUSEFIELD: AUSEFIELD,
+}
+
+var Linkppc64le = obj.LinkArch{
+ ByteOrder: binary.LittleEndian,
+ Pconv: Pconv,
+ Name: "ppc64le",
+ Thechar: '9',
+ Endian: obj.LittleEndian,
+ Addstacksplit: addstacksplit,
+ Assemble: span9,
+ Datasize: datasize,
+ Follow: follow,
+ Iscall: iscall,
+ Isdata: isdata,
+ Prg: prg,
+ Progedit: progedit,
+ Settextflag: settextflag,
+ Symtype: symtype,
+ Textflag: textflag,
+ Minlc: 4,
+ Ptrsize: 8,
+ Regsize: 8,
+ D_ADDR: D_ADDR,
+ D_AUTO: D_AUTO,
+ D_BRANCH: D_BRANCH,
+ D_CONST: D_CONST,
+ D_EXTERN: D_EXTERN,
+ D_FCONST: D_FCONST,
+ D_NONE: D_NONE,
+ D_PARAM: D_PARAM,
+ D_SCONST: D_SCONST,
+ D_STATIC: D_STATIC,
+ D_OREG: D_OREG,
+ ACALL: ABL,
+ ADATA: ADATA,
+ AEND: AEND,
+ AFUNCDATA: AFUNCDATA,
+ AGLOBL: AGLOBL,
+ AJMP: ABR,
+ ANOP: ANOP,
+ APCDATA: APCDATA,
+ ARET: ARETURN,
+ ATEXT: ATEXT,
+ ATYPE: ATYPE,
+ AUSEFIELD: AUSEFIELD,
+}
--- /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.
+
+package ppc64
+
+const (
+ fmtLong = 1 << iota
+)
+
+func bool2int(b bool) int {
+ if b {
+ return 1
+ }
+ return 0
+}
--- /dev/null
+// Inferno utils/5l/span.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5l/span.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package obj
+
+// Instruction layout.
+
+// Copyright 2011 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.
+
+// For the linkers. Must match Go definitions.
+// TODO(rsc): Share Go definitions with linkers directly.
+
+const (
+ StackSystem = 0
+ StackBig = 4096
+ StackGuard = 640 + StackSystem
+ StackSmall = 128
+ StackLimit = StackGuard - StackSystem - StackSmall
+)
+
+const (
+ StackPreempt = -1314 // 0xfff...fade
+)
--- /dev/null
+// Derived from Inferno utils/6l/obj.c and utils/6l/span.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package obj
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "path/filepath"
+)
+
+func yy_isalpha(c int) bool {
+ return 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z'
+}
+
+var headers = []struct {
+ name string
+ val int
+}{
+ struct {
+ name string
+ val int
+ }{"android", Hlinux},
+ struct {
+ name string
+ val int
+ }{"darwin", Hdarwin},
+ struct {
+ name string
+ val int
+ }{"dragonfly", Hdragonfly},
+ struct {
+ name string
+ val int
+ }{"elf", Helf},
+ struct {
+ name string
+ val int
+ }{"freebsd", Hfreebsd},
+ struct {
+ name string
+ val int
+ }{"linux", Hlinux},
+ struct {
+ name string
+ val int
+ }{"nacl", Hnacl},
+ struct {
+ name string
+ val int
+ }{"netbsd", Hnetbsd},
+ struct {
+ name string
+ val int
+ }{"openbsd", Hopenbsd},
+ struct {
+ name string
+ val int
+ }{"plan9", Hplan9},
+ struct {
+ name string
+ val int
+ }{"solaris", Hsolaris},
+ struct {
+ name string
+ val int
+ }{"windows", Hwindows},
+ struct {
+ name string
+ val int
+ }{"windowsgui", Hwindows},
+}
+
+func headtype(name string) int {
+ var i int
+
+ for i = 0; i < len(headers); i++ {
+ if name == headers[i].name {
+ return headers[i].val
+ }
+ }
+ return -1
+}
+
+func Headstr(v int) string {
+ var buf string
+ var i int
+
+ for i = 0; i < len(headers); i++ {
+ if v == headers[i].val {
+ return headers[i].name
+ }
+ }
+ buf = fmt.Sprintf("%d", v)
+ return buf
+}
+
+func Linknew(arch *LinkArch) *Link {
+ var ctxt *Link
+ var p string
+ var buf string
+
+ ctxt = new(Link)
+ ctxt.Arch = arch
+ ctxt.Version = HistVersion
+ ctxt.Goroot = Getgoroot()
+ ctxt.Goroot_final = os.Getenv("GOROOT_FINAL")
+
+ buf, _ = os.Getwd()
+ if buf == "" {
+ buf = "/???"
+ }
+ buf = filepath.ToSlash(buf)
+
+ ctxt.Pathname = buf
+
+ ctxt.Headtype = headtype(Getgoos())
+ if ctxt.Headtype < 0 {
+ log.Fatalf("unknown goos %s", Getgoos())
+ }
+
+ // Record thread-local storage offset.
+ // TODO(rsc): Move tlsoffset back into the linker.
+ switch ctxt.Headtype {
+
+ default:
+ log.Fatalf("unknown thread-local storage offset for %s", Headstr(ctxt.Headtype))
+
+ case Hplan9,
+ Hwindows:
+ break
+
+ /*
+ * ELF uses TLS offset negative from FS.
+ * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS).
+ * Known to low-level assembly in package runtime and runtime/cgo.
+ */
+ case Hlinux,
+ Hfreebsd,
+ Hnetbsd,
+ Hopenbsd,
+ Hdragonfly,
+ Hsolaris:
+ ctxt.Tlsoffset = -2 * ctxt.Arch.Ptrsize
+
+ case Hnacl:
+ switch ctxt.Arch.Thechar {
+ default:
+ log.Fatalf("unknown thread-local storage offset for nacl/%s", ctxt.Arch.Name)
+
+ case '6':
+ ctxt.Tlsoffset = 0
+
+ case '8':
+ ctxt.Tlsoffset = -8
+
+ case '5':
+ ctxt.Tlsoffset = 0
+ break
+ }
+
+ /*
+ * OS X system constants - offset from 0(GS) to our TLS.
+ * Explained in ../../runtime/cgo/gcc_darwin_*.c.
+ */
+ case Hdarwin:
+ switch ctxt.Arch.Thechar {
+
+ default:
+ log.Fatalf("unknown thread-local storage offset for darwin/%s", ctxt.Arch.Name)
+
+ case '6':
+ ctxt.Tlsoffset = 0x8a0
+
+ case '8':
+ ctxt.Tlsoffset = 0x468
+ break
+ }
+
+ break
+ }
+
+ // On arm, record goarm.
+ if ctxt.Arch.Thechar == '5' {
+
+ p = Getgoarm()
+ if p != "" {
+ ctxt.Goarm = int32(Atoi(p))
+ } else {
+
+ ctxt.Goarm = 6
+ }
+ }
+
+ return ctxt
+}
+
+func linknewsym(ctxt *Link, symb string, v int) *LSym {
+ var s *LSym
+
+ s = new(LSym)
+ *s = LSym{}
+
+ s.Dynid = -1
+ s.Plt = -1
+ s.Got = -1
+ s.Name = symb
+ s.Type = 0
+ s.Version = int16(v)
+ s.Value = 0
+ s.Sig = 0
+ s.Size = 0
+ ctxt.Nsymbol++
+
+ s.Allsym = ctxt.Allsym
+ ctxt.Allsym = s
+
+ return s
+}
+
+func _lookup(ctxt *Link, symb string, v int, creat int) *LSym {
+ var s *LSym
+ var h uint32
+
+ h = uint32(v)
+ for i := 0; i < len(symb); i++ {
+ c := int(symb[i])
+ h = h + h + h + uint32(c)
+ }
+ h &= 0xffffff
+ h %= LINKHASH
+ for s = ctxt.Hash[h]; s != nil; s = s.Hash {
+ if int(s.Version) == v && s.Name == symb {
+ return s
+ }
+ }
+ if !(creat != 0) {
+ return nil
+ }
+
+ s = linknewsym(ctxt, symb, v)
+ s.Extname = s.Name
+ s.Hash = ctxt.Hash[h]
+ ctxt.Hash[h] = s
+
+ return s
+}
+
+func Linklookup(ctxt *Link, name string, v int) *LSym {
+ return _lookup(ctxt, name, v, 1)
+}
+
+// read-only lookup
+func linkrlookup(ctxt *Link, name string, v int) *LSym {
+
+ return _lookup(ctxt, name, v, 0)
+}
--- /dev/null
+// Copyright 2013 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 defines flags attached to various functions
+// and data objects. The compilers, assemblers, and linker must
+// all agree on these values.
+
+package obj
+
+const (
+ // Don't profile the marked routine. This flag is deprecated.
+ NOPROF = 1
+
+ // It is ok for the linker to get multiple of these symbols. It will
+ // pick one of the duplicates to use.
+ DUPOK = 2
+
+ // Don't insert stack check preamble.
+ NOSPLIT = 4
+
+ // Put this data in a read-only section.
+ RODATA = 8
+
+ // This data contains no pointers.
+ NOPTR = 16
+
+ // This is a wrapper function and should not count as disabling 'recover'.
+ WRAPPER = 32
+
+ // This function uses its incoming context register.
+ NEEDCTXT = 64
+)
--- /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.
+
+package obj
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "os"
+ "strconv"
+ "time"
+)
+
+var start time.Time
+
+func Cputime() float64 {
+ if start.IsZero() {
+ start = time.Now()
+ }
+ return time.Since(start).Seconds()
+}
+
+type Biobuf struct {
+ unget int
+ haveUnget bool
+ r *bufio.Reader
+ w *bufio.Writer
+}
+
+func Binitw(w io.Writer) *Biobuf {
+ return &Biobuf{w: bufio.NewWriter(w)}
+}
+
+func (b *Biobuf) Write(p []byte) (int, error) {
+ return b.w.Write(p)
+}
+
+func (b *Biobuf) Flush() error {
+ return b.w.Flush()
+}
+
+func Bwrite(b *Biobuf, p []byte) (int, error) {
+ return b.w.Write(p)
+}
+
+func Bputc(b *Biobuf, c byte) {
+ b.w.WriteByte(c)
+}
+
+func Bgetc(b *Biobuf) int {
+ if b.haveUnget {
+ b.haveUnget = false
+ return int(b.unget)
+ }
+ c, err := b.r.ReadByte()
+ if err != nil {
+ b.unget = -1
+ return -1
+ }
+ b.unget = int(c)
+ return int(c)
+}
+
+func Bungetc(b *Biobuf) {
+ b.haveUnget = true
+}
+
+func Boffset(b *Biobuf) int64 {
+ panic("Boffset")
+}
+
+func Bflush(b *Biobuf) error {
+ return b.w.Flush()
+}
+
+func envOr(key, value string) string {
+ if x := os.Getenv(key); x != "" {
+ return x
+ }
+ return value
+}
+
+func Getgoroot() string {
+ return envOr("GOROOT", defaultGOROOT)
+}
+
+func Getgoarch() string {
+ return envOr("GOARCH", defaultGOARCH)
+}
+
+func Getgoos() string {
+ return envOr("GOOS", defaultGOOS)
+}
+
+func Getgoarm() string {
+ return envOr("GOARM", defaultGOARM)
+}
+
+func Getgoversion() string {
+ return version
+}
+
+func Atoi(s string) int {
+ i, _ := strconv.Atoi(s)
+ return i
+}
+
+func (p *Prog) Line() string {
+ return linklinefmt(p.Ctxt, int(p.Lineno), false, false)
+}
+
+func (p *Prog) String() string {
+ if p.Ctxt == nil {
+ return fmt.Sprintf("<Prog without ctxt>")
+ }
+ return p.Ctxt.Arch.Pconv(p)
+}
+
+func (ctxt *Link) NewProg() *Prog {
+ p := ctxt.Arch.Prg() // should be the only call to this; all others should use ctxt.NewProg
+ p.Ctxt = ctxt
+ return p
+}
--- /dev/null
+// Inferno utils/6c/6.out.h
+// http://code.google.com/p/inferno-os/source/browse/utils/6c/6.out.h
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package x86
+
+/*
+ * amd64
+ */
+const (
+ AXXX = iota
+ AAAA
+ AAAD
+ AAAM
+ AAAS
+ AADCB
+ AADCL
+ AADCW
+ AADDB
+ AADDL
+ AADDW
+ AADJSP
+ AANDB
+ AANDL
+ AANDW
+ AARPL
+ ABOUNDL
+ ABOUNDW
+ ABSFL
+ ABSFW
+ ABSRL
+ ABSRW
+ ABTL
+ ABTW
+ ABTCL
+ ABTCW
+ ABTRL
+ ABTRW
+ ABTSL
+ ABTSW
+ ABYTE
+ ACALL
+ ACLC
+ ACLD
+ ACLI
+ ACLTS
+ ACMC
+ ACMPB
+ ACMPL
+ ACMPW
+ ACMPSB
+ ACMPSL
+ ACMPSW
+ ADAA
+ ADAS
+ ADATA
+ ADECB
+ ADECL
+ ADECQ
+ ADECW
+ ADIVB
+ ADIVL
+ ADIVW
+ AENTER
+ AGLOBL
+ AGOK
+ AHISTORY
+ AHLT
+ AIDIVB
+ AIDIVL
+ AIDIVW
+ AIMULB
+ AIMULL
+ AIMULW
+ AINB
+ AINL
+ AINW
+ AINCB
+ AINCL
+ AINCQ
+ AINCW
+ AINSB
+ AINSL
+ AINSW
+ AINT
+ AINTO
+ AIRETL
+ AIRETW
+ AJCC
+ AJCS
+ AJCXZL
+ AJEQ
+ AJGE
+ AJGT
+ AJHI
+ AJLE
+ AJLS
+ AJLT
+ AJMI
+ AJMP
+ AJNE
+ AJOC
+ AJOS
+ AJPC
+ AJPL
+ AJPS
+ ALAHF
+ ALARL
+ ALARW
+ ALEAL
+ ALEAW
+ ALEAVEL
+ ALEAVEW
+ ALOCK
+ ALODSB
+ ALODSL
+ ALODSW
+ ALONG
+ ALOOP
+ ALOOPEQ
+ ALOOPNE
+ ALSLL
+ ALSLW
+ AMOVB
+ AMOVL
+ AMOVW
+ AMOVBLSX
+ AMOVBLZX
+ AMOVBQSX
+ AMOVBQZX
+ AMOVBWSX
+ AMOVBWZX
+ AMOVWLSX
+ AMOVWLZX
+ AMOVWQSX
+ AMOVWQZX
+ AMOVSB
+ AMOVSL
+ AMOVSW
+ AMULB
+ AMULL
+ AMULW
+ ANAME
+ ANEGB
+ ANEGL
+ ANEGW
+ ANOP
+ ANOTB
+ ANOTL
+ ANOTW
+ AORB
+ AORL
+ AORW
+ AOUTB
+ AOUTL
+ AOUTW
+ AOUTSB
+ AOUTSL
+ AOUTSW
+ APAUSE
+ APOPAL
+ APOPAW
+ APOPFL
+ APOPFW
+ APOPL
+ APOPW
+ APUSHAL
+ APUSHAW
+ APUSHFL
+ APUSHFW
+ APUSHL
+ APUSHW
+ ARCLB
+ ARCLL
+ ARCLW
+ ARCRB
+ ARCRL
+ ARCRW
+ AREP
+ AREPN
+ ARET
+ AROLB
+ AROLL
+ AROLW
+ ARORB
+ ARORL
+ ARORW
+ ASAHF
+ ASALB
+ ASALL
+ ASALW
+ ASARB
+ ASARL
+ ASARW
+ ASBBB
+ ASBBL
+ ASBBW
+ ASCASB
+ ASCASL
+ ASCASW
+ ASETCC
+ ASETCS
+ ASETEQ
+ ASETGE
+ ASETGT
+ ASETHI
+ ASETLE
+ ASETLS
+ ASETLT
+ ASETMI
+ ASETNE
+ ASETOC
+ ASETOS
+ ASETPC
+ ASETPL
+ ASETPS
+ ACDQ
+ ACWD
+ ASHLB
+ ASHLL
+ ASHLW
+ ASHRB
+ ASHRL
+ ASHRW
+ ASTC
+ ASTD
+ ASTI
+ ASTOSB
+ ASTOSL
+ ASTOSW
+ ASUBB
+ ASUBL
+ ASUBW
+ ASYSCALL
+ ATESTB
+ ATESTL
+ ATESTW
+ ATEXT
+ AVERR
+ AVERW
+ AWAIT
+ AWORD
+ AXCHGB
+ AXCHGL
+ AXCHGW
+ AXLAT
+ AXORB
+ AXORL
+ AXORW
+ AFMOVB
+ AFMOVBP
+ AFMOVD
+ AFMOVDP
+ AFMOVF
+ AFMOVFP
+ AFMOVL
+ AFMOVLP
+ AFMOVV
+ AFMOVVP
+ AFMOVW
+ AFMOVWP
+ AFMOVX
+ AFMOVXP
+ AFCOMB
+ AFCOMBP
+ AFCOMD
+ AFCOMDP
+ AFCOMDPP
+ AFCOMF
+ AFCOMFP
+ AFCOML
+ AFCOMLP
+ AFCOMW
+ AFCOMWP
+ AFUCOM
+ AFUCOMP
+ AFUCOMPP
+ AFADDDP
+ AFADDW
+ AFADDL
+ AFADDF
+ AFADDD
+ AFMULDP
+ AFMULW
+ AFMULL
+ AFMULF
+ AFMULD
+ AFSUBDP
+ AFSUBW
+ AFSUBL
+ AFSUBF
+ AFSUBD
+ AFSUBRDP
+ AFSUBRW
+ AFSUBRL
+ AFSUBRF
+ AFSUBRD
+ AFDIVDP
+ AFDIVW
+ AFDIVL
+ AFDIVF
+ AFDIVD
+ AFDIVRDP
+ AFDIVRW
+ AFDIVRL
+ AFDIVRF
+ AFDIVRD
+ AFXCHD
+ AFFREE
+ AFLDCW
+ AFLDENV
+ AFRSTOR
+ AFSAVE
+ AFSTCW
+ AFSTENV
+ AFSTSW
+ AF2XM1
+ AFABS
+ AFCHS
+ AFCLEX
+ AFCOS
+ AFDECSTP
+ AFINCSTP
+ AFINIT
+ AFLD1
+ AFLDL2E
+ AFLDL2T
+ AFLDLG2
+ AFLDLN2
+ AFLDPI
+ AFLDZ
+ AFNOP
+ AFPATAN
+ AFPREM
+ AFPREM1
+ AFPTAN
+ AFRNDINT
+ AFSCALE
+ AFSIN
+ AFSINCOS
+ AFSQRT
+ AFTST
+ AFXAM
+ AFXTRACT
+ AFYL2X
+ AFYL2XP1
+ AEND
+ ADYNT_
+ AINIT_
+ ASIGNAME
+ ACMPXCHGB
+ ACMPXCHGL
+ ACMPXCHGW
+ ACMPXCHG8B
+ ACPUID
+ AINVD
+ AINVLPG
+ ALFENCE
+ AMFENCE
+ AMOVNTIL
+ ARDMSR
+ ARDPMC
+ ARDTSC
+ ARSM
+ ASFENCE
+ ASYSRET
+ AWBINVD
+ AWRMSR
+ AXADDB
+ AXADDL
+ AXADDW
+ ACMOVLCC
+ ACMOVLCS
+ ACMOVLEQ
+ ACMOVLGE
+ ACMOVLGT
+ ACMOVLHI
+ ACMOVLLE
+ ACMOVLLS
+ ACMOVLLT
+ ACMOVLMI
+ ACMOVLNE
+ ACMOVLOC
+ ACMOVLOS
+ ACMOVLPC
+ ACMOVLPL
+ ACMOVLPS
+ ACMOVQCC
+ ACMOVQCS
+ ACMOVQEQ
+ ACMOVQGE
+ ACMOVQGT
+ ACMOVQHI
+ ACMOVQLE
+ ACMOVQLS
+ ACMOVQLT
+ ACMOVQMI
+ ACMOVQNE
+ ACMOVQOC
+ ACMOVQOS
+ ACMOVQPC
+ ACMOVQPL
+ ACMOVQPS
+ ACMOVWCC
+ ACMOVWCS
+ ACMOVWEQ
+ ACMOVWGE
+ ACMOVWGT
+ ACMOVWHI
+ ACMOVWLE
+ ACMOVWLS
+ ACMOVWLT
+ ACMOVWMI
+ ACMOVWNE
+ ACMOVWOC
+ ACMOVWOS
+ ACMOVWPC
+ ACMOVWPL
+ ACMOVWPS
+ AADCQ
+ AADDQ
+ AANDQ
+ ABSFQ
+ ABSRQ
+ ABTCQ
+ ABTQ
+ ABTRQ
+ ABTSQ
+ ACMPQ
+ ACMPSQ
+ ACMPXCHGQ
+ ACQO
+ ADIVQ
+ AIDIVQ
+ AIMULQ
+ AIRETQ
+ AJCXZQ
+ ALEAQ
+ ALEAVEQ
+ ALODSQ
+ AMOVQ
+ AMOVLQSX
+ AMOVLQZX
+ AMOVNTIQ
+ AMOVSQ
+ AMULQ
+ ANEGQ
+ ANOTQ
+ AORQ
+ APOPFQ
+ APOPQ
+ APUSHFQ
+ APUSHQ
+ ARCLQ
+ ARCRQ
+ AROLQ
+ ARORQ
+ AQUAD
+ ASALQ
+ ASARQ
+ ASBBQ
+ ASCASQ
+ ASHLQ
+ ASHRQ
+ ASTOSQ
+ ASUBQ
+ ATESTQ
+ AXADDQ
+ AXCHGQ
+ AXORQ
+ AADDPD
+ AADDPS
+ AADDSD
+ AADDSS
+ AANDNPD
+ AANDNPS
+ AANDPD
+ AANDPS
+ ACMPPD
+ ACMPPS
+ ACMPSD
+ ACMPSS
+ ACOMISD
+ ACOMISS
+ ACVTPD2PL
+ ACVTPD2PS
+ ACVTPL2PD
+ ACVTPL2PS
+ ACVTPS2PD
+ ACVTPS2PL
+ ACVTSD2SL
+ ACVTSD2SQ
+ ACVTSD2SS
+ ACVTSL2SD
+ ACVTSL2SS
+ ACVTSQ2SD
+ ACVTSQ2SS
+ ACVTSS2SD
+ ACVTSS2SL
+ ACVTSS2SQ
+ ACVTTPD2PL
+ ACVTTPS2PL
+ ACVTTSD2SL
+ ACVTTSD2SQ
+ ACVTTSS2SL
+ ACVTTSS2SQ
+ ADIVPD
+ ADIVPS
+ ADIVSD
+ ADIVSS
+ AEMMS
+ AFXRSTOR
+ AFXRSTOR64
+ AFXSAVE
+ AFXSAVE64
+ ALDMXCSR
+ AMASKMOVOU
+ AMASKMOVQ
+ AMAXPD
+ AMAXPS
+ AMAXSD
+ AMAXSS
+ AMINPD
+ AMINPS
+ AMINSD
+ AMINSS
+ AMOVAPD
+ AMOVAPS
+ AMOVOU
+ AMOVHLPS
+ AMOVHPD
+ AMOVHPS
+ AMOVLHPS
+ AMOVLPD
+ AMOVLPS
+ AMOVMSKPD
+ AMOVMSKPS
+ AMOVNTO
+ AMOVNTPD
+ AMOVNTPS
+ AMOVNTQ
+ AMOVO
+ AMOVQOZX
+ AMOVSD
+ AMOVSS
+ AMOVUPD
+ AMOVUPS
+ AMULPD
+ AMULPS
+ AMULSD
+ AMULSS
+ AORPD
+ AORPS
+ APACKSSLW
+ APACKSSWB
+ APACKUSWB
+ APADDB
+ APADDL
+ APADDQ
+ APADDSB
+ APADDSW
+ APADDUSB
+ APADDUSW
+ APADDW
+ APANDB
+ APANDL
+ APANDSB
+ APANDSW
+ APANDUSB
+ APANDUSW
+ APANDW
+ APAND
+ APANDN
+ APAVGB
+ APAVGW
+ APCMPEQB
+ APCMPEQL
+ APCMPEQW
+ APCMPGTB
+ APCMPGTL
+ APCMPGTW
+ APEXTRW
+ APFACC
+ APFADD
+ APFCMPEQ
+ APFCMPGE
+ APFCMPGT
+ APFMAX
+ APFMIN
+ APFMUL
+ APFNACC
+ APFPNACC
+ APFRCP
+ APFRCPIT1
+ APFRCPI2T
+ APFRSQIT1
+ APFRSQRT
+ APFSUB
+ APFSUBR
+ APINSRW
+ APINSRD
+ APINSRQ
+ APMADDWL
+ APMAXSW
+ APMAXUB
+ APMINSW
+ APMINUB
+ APMOVMSKB
+ APMULHRW
+ APMULHUW
+ APMULHW
+ APMULLW
+ APMULULQ
+ APOR
+ APSADBW
+ APSHUFHW
+ APSHUFL
+ APSHUFLW
+ APSHUFW
+ APSHUFB
+ APSLLO
+ APSLLL
+ APSLLQ
+ APSLLW
+ APSRAL
+ APSRAW
+ APSRLO
+ APSRLL
+ APSRLQ
+ APSRLW
+ APSUBB
+ APSUBL
+ APSUBQ
+ APSUBSB
+ APSUBSW
+ APSUBUSB
+ APSUBUSW
+ APSUBW
+ APSWAPL
+ APUNPCKHBW
+ APUNPCKHLQ
+ APUNPCKHQDQ
+ APUNPCKHWL
+ APUNPCKLBW
+ APUNPCKLLQ
+ APUNPCKLQDQ
+ APUNPCKLWL
+ APXOR
+ ARCPPS
+ ARCPSS
+ ARSQRTPS
+ ARSQRTSS
+ ASHUFPD
+ ASHUFPS
+ ASQRTPD
+ ASQRTPS
+ ASQRTSD
+ ASQRTSS
+ ASTMXCSR
+ ASUBPD
+ ASUBPS
+ ASUBSD
+ ASUBSS
+ AUCOMISD
+ AUCOMISS
+ AUNPCKHPD
+ AUNPCKHPS
+ AUNPCKLPD
+ AUNPCKLPS
+ AXORPD
+ AXORPS
+ APF2IW
+ APF2IL
+ API2FW
+ API2FL
+ ARETFW
+ ARETFL
+ ARETFQ
+ ASWAPGS
+ AMODE
+ ACRC32B
+ ACRC32Q
+ AIMUL3Q
+ APREFETCHT0
+ APREFETCHT1
+ APREFETCHT2
+ APREFETCHNTA
+ AMOVQL
+ ABSWAPL
+ ABSWAPQ
+ AUNDEF
+ AAESENC
+ AAESENCLAST
+ AAESDEC
+ AAESDECLAST
+ AAESIMC
+ AAESKEYGENASSIST
+ APSHUFD
+ APCLMULQDQ
+ AUSEFIELD
+ ATYPE
+ AFUNCDATA
+ APCDATA
+ ACHECKNIL
+ AVARDEF
+ AVARKILL
+ ADUFFCOPY
+ ADUFFZERO
+ ALAST
+)
+
+const (
+ D_AL = 0 + iota
+ D_CL
+ D_DL
+ D_BL
+ D_SPB
+ D_BPB
+ D_SIB
+ D_DIB
+ D_R8B
+ D_R9B
+ D_R10B
+ D_R11B
+ D_R12B
+ D_R13B
+ D_R14B
+ D_R15B
+ D_AX = 16 + iota - 16
+ D_CX
+ D_DX
+ D_BX
+ D_SP
+ D_BP
+ D_SI
+ D_DI
+ D_R8
+ D_R9
+ D_R10
+ D_R11
+ D_R12
+ D_R13
+ D_R14
+ D_R15
+ D_AH = 32 + iota - 32
+ D_CH
+ D_DH
+ D_BH
+ D_F0 = 36
+ D_M0 = 44
+ D_X0 = 52 + iota - 38
+ D_X1
+ D_X2
+ D_X3
+ D_X4
+ D_X5
+ D_X6
+ D_X7
+ D_X8
+ D_X9
+ D_X10
+ D_X11
+ D_X12
+ D_X13
+ D_X14
+ D_X15
+ D_CS = 68 + iota - 54
+ D_SS
+ D_DS
+ D_ES
+ D_FS
+ D_GS
+ D_GDTR
+ D_IDTR
+ D_LDTR
+ D_MSW
+ D_TASK
+ D_CR = 79
+ D_DR = 95
+ D_TR = 103
+ D_TLS = 111
+ D_NONE = 112
+ D_BRANCH = 113
+ D_EXTERN = 114
+ D_STATIC = 115
+ D_AUTO = 116
+ D_PARAM = 117
+ D_CONST = 118
+ D_FCONST = 119
+ D_SCONST = 120
+ D_ADDR = 121 + iota - 78
+ D_INDIR
+ D_LAST
+ T_TYPE = 1 << 0
+ T_INDEX = 1 << 1
+ T_OFFSET = 1 << 2
+ T_FCONST = 1 << 3
+ T_SYM = 1 << 4
+ T_SCONST = 1 << 5
+ T_64 = 1 << 6
+ T_GOTYPE = 1 << 7
+ REGARG = -1
+ REGRET = D_AX
+ FREGRET = D_X0
+ REGSP = D_SP
+ REGTMP = D_DI
+ REGEXT = D_R15
+ FREGMIN = D_X0 + 5
+ FREGEXT = D_X0 + 15
+)
--- /dev/null
+package x86
+
+/*
+ * this is the ranlib header
+ */
+var Anames = []string{
+ "XXX",
+ "AAA",
+ "AAD",
+ "AAM",
+ "AAS",
+ "ADCB",
+ "ADCL",
+ "ADCW",
+ "ADDB",
+ "ADDL",
+ "ADDW",
+ "ADJSP",
+ "ANDB",
+ "ANDL",
+ "ANDW",
+ "ARPL",
+ "BOUNDL",
+ "BOUNDW",
+ "BSFL",
+ "BSFW",
+ "BSRL",
+ "BSRW",
+ "BTL",
+ "BTW",
+ "BTCL",
+ "BTCW",
+ "BTRL",
+ "BTRW",
+ "BTSL",
+ "BTSW",
+ "BYTE",
+ "CALL",
+ "CLC",
+ "CLD",
+ "CLI",
+ "CLTS",
+ "CMC",
+ "CMPB",
+ "CMPL",
+ "CMPW",
+ "CMPSB",
+ "CMPSL",
+ "CMPSW",
+ "DAA",
+ "DAS",
+ "DATA",
+ "DECB",
+ "DECL",
+ "DECQ",
+ "DECW",
+ "DIVB",
+ "DIVL",
+ "DIVW",
+ "ENTER",
+ "GLOBL",
+ "GOK",
+ "HISTORY",
+ "HLT",
+ "IDIVB",
+ "IDIVL",
+ "IDIVW",
+ "IMULB",
+ "IMULL",
+ "IMULW",
+ "INB",
+ "INL",
+ "INW",
+ "INCB",
+ "INCL",
+ "INCQ",
+ "INCW",
+ "INSB",
+ "INSL",
+ "INSW",
+ "INT",
+ "INTO",
+ "IRETL",
+ "IRETW",
+ "JCC",
+ "JCS",
+ "JCXZL",
+ "JEQ",
+ "JGE",
+ "JGT",
+ "JHI",
+ "JLE",
+ "JLS",
+ "JLT",
+ "JMI",
+ "JMP",
+ "JNE",
+ "JOC",
+ "JOS",
+ "JPC",
+ "JPL",
+ "JPS",
+ "LAHF",
+ "LARL",
+ "LARW",
+ "LEAL",
+ "LEAW",
+ "LEAVEL",
+ "LEAVEW",
+ "LOCK",
+ "LODSB",
+ "LODSL",
+ "LODSW",
+ "LONG",
+ "LOOP",
+ "LOOPEQ",
+ "LOOPNE",
+ "LSLL",
+ "LSLW",
+ "MOVB",
+ "MOVL",
+ "MOVW",
+ "MOVBLSX",
+ "MOVBLZX",
+ "MOVBQSX",
+ "MOVBQZX",
+ "MOVBWSX",
+ "MOVBWZX",
+ "MOVWLSX",
+ "MOVWLZX",
+ "MOVWQSX",
+ "MOVWQZX",
+ "MOVSB",
+ "MOVSL",
+ "MOVSW",
+ "MULB",
+ "MULL",
+ "MULW",
+ "NAME",
+ "NEGB",
+ "NEGL",
+ "NEGW",
+ "NOP",
+ "NOTB",
+ "NOTL",
+ "NOTW",
+ "ORB",
+ "ORL",
+ "ORW",
+ "OUTB",
+ "OUTL",
+ "OUTW",
+ "OUTSB",
+ "OUTSL",
+ "OUTSW",
+ "PAUSE",
+ "POPAL",
+ "POPAW",
+ "POPFL",
+ "POPFW",
+ "POPL",
+ "POPW",
+ "PUSHAL",
+ "PUSHAW",
+ "PUSHFL",
+ "PUSHFW",
+ "PUSHL",
+ "PUSHW",
+ "RCLB",
+ "RCLL",
+ "RCLW",
+ "RCRB",
+ "RCRL",
+ "RCRW",
+ "REP",
+ "REPN",
+ "RET",
+ "ROLB",
+ "ROLL",
+ "ROLW",
+ "RORB",
+ "RORL",
+ "RORW",
+ "SAHF",
+ "SALB",
+ "SALL",
+ "SALW",
+ "SARB",
+ "SARL",
+ "SARW",
+ "SBBB",
+ "SBBL",
+ "SBBW",
+ "SCASB",
+ "SCASL",
+ "SCASW",
+ "SETCC",
+ "SETCS",
+ "SETEQ",
+ "SETGE",
+ "SETGT",
+ "SETHI",
+ "SETLE",
+ "SETLS",
+ "SETLT",
+ "SETMI",
+ "SETNE",
+ "SETOC",
+ "SETOS",
+ "SETPC",
+ "SETPL",
+ "SETPS",
+ "CDQ",
+ "CWD",
+ "SHLB",
+ "SHLL",
+ "SHLW",
+ "SHRB",
+ "SHRL",
+ "SHRW",
+ "STC",
+ "STD",
+ "STI",
+ "STOSB",
+ "STOSL",
+ "STOSW",
+ "SUBB",
+ "SUBL",
+ "SUBW",
+ "SYSCALL",
+ "TESTB",
+ "TESTL",
+ "TESTW",
+ "TEXT",
+ "VERR",
+ "VERW",
+ "WAIT",
+ "WORD",
+ "XCHGB",
+ "XCHGL",
+ "XCHGW",
+ "XLAT",
+ "XORB",
+ "XORL",
+ "XORW",
+ "FMOVB",
+ "FMOVBP",
+ "FMOVD",
+ "FMOVDP",
+ "FMOVF",
+ "FMOVFP",
+ "FMOVL",
+ "FMOVLP",
+ "FMOVV",
+ "FMOVVP",
+ "FMOVW",
+ "FMOVWP",
+ "FMOVX",
+ "FMOVXP",
+ "FCOMB",
+ "FCOMBP",
+ "FCOMD",
+ "FCOMDP",
+ "FCOMDPP",
+ "FCOMF",
+ "FCOMFP",
+ "FCOML",
+ "FCOMLP",
+ "FCOMW",
+ "FCOMWP",
+ "FUCOM",
+ "FUCOMP",
+ "FUCOMPP",
+ "FADDDP",
+ "FADDW",
+ "FADDL",
+ "FADDF",
+ "FADDD",
+ "FMULDP",
+ "FMULW",
+ "FMULL",
+ "FMULF",
+ "FMULD",
+ "FSUBDP",
+ "FSUBW",
+ "FSUBL",
+ "FSUBF",
+ "FSUBD",
+ "FSUBRDP",
+ "FSUBRW",
+ "FSUBRL",
+ "FSUBRF",
+ "FSUBRD",
+ "FDIVDP",
+ "FDIVW",
+ "FDIVL",
+ "FDIVF",
+ "FDIVD",
+ "FDIVRDP",
+ "FDIVRW",
+ "FDIVRL",
+ "FDIVRF",
+ "FDIVRD",
+ "FXCHD",
+ "FFREE",
+ "FLDCW",
+ "FLDENV",
+ "FRSTOR",
+ "FSAVE",
+ "FSTCW",
+ "FSTENV",
+ "FSTSW",
+ "F2XM1",
+ "FABS",
+ "FCHS",
+ "FCLEX",
+ "FCOS",
+ "FDECSTP",
+ "FINCSTP",
+ "FINIT",
+ "FLD1",
+ "FLDL2E",
+ "FLDL2T",
+ "FLDLG2",
+ "FLDLN2",
+ "FLDPI",
+ "FLDZ",
+ "FNOP",
+ "FPATAN",
+ "FPREM",
+ "FPREM1",
+ "FPTAN",
+ "FRNDINT",
+ "FSCALE",
+ "FSIN",
+ "FSINCOS",
+ "FSQRT",
+ "FTST",
+ "FXAM",
+ "FXTRACT",
+ "FYL2X",
+ "FYL2XP1",
+ "END",
+ "DYNT_",
+ "INIT_",
+ "SIGNAME",
+ "CMPXCHGB",
+ "CMPXCHGL",
+ "CMPXCHGW",
+ "CMPXCHG8B",
+ "CPUID",
+ "INVD",
+ "INVLPG",
+ "LFENCE",
+ "MFENCE",
+ "MOVNTIL",
+ "RDMSR",
+ "RDPMC",
+ "RDTSC",
+ "RSM",
+ "SFENCE",
+ "SYSRET",
+ "WBINVD",
+ "WRMSR",
+ "XADDB",
+ "XADDL",
+ "XADDW",
+ "CMOVLCC",
+ "CMOVLCS",
+ "CMOVLEQ",
+ "CMOVLGE",
+ "CMOVLGT",
+ "CMOVLHI",
+ "CMOVLLE",
+ "CMOVLLS",
+ "CMOVLLT",
+ "CMOVLMI",
+ "CMOVLNE",
+ "CMOVLOC",
+ "CMOVLOS",
+ "CMOVLPC",
+ "CMOVLPL",
+ "CMOVLPS",
+ "CMOVQCC",
+ "CMOVQCS",
+ "CMOVQEQ",
+ "CMOVQGE",
+ "CMOVQGT",
+ "CMOVQHI",
+ "CMOVQLE",
+ "CMOVQLS",
+ "CMOVQLT",
+ "CMOVQMI",
+ "CMOVQNE",
+ "CMOVQOC",
+ "CMOVQOS",
+ "CMOVQPC",
+ "CMOVQPL",
+ "CMOVQPS",
+ "CMOVWCC",
+ "CMOVWCS",
+ "CMOVWEQ",
+ "CMOVWGE",
+ "CMOVWGT",
+ "CMOVWHI",
+ "CMOVWLE",
+ "CMOVWLS",
+ "CMOVWLT",
+ "CMOVWMI",
+ "CMOVWNE",
+ "CMOVWOC",
+ "CMOVWOS",
+ "CMOVWPC",
+ "CMOVWPL",
+ "CMOVWPS",
+ "ADCQ",
+ "ADDQ",
+ "ANDQ",
+ "BSFQ",
+ "BSRQ",
+ "BTCQ",
+ "BTQ",
+ "BTRQ",
+ "BTSQ",
+ "CMPQ",
+ "CMPSQ",
+ "CMPXCHGQ",
+ "CQO",
+ "DIVQ",
+ "IDIVQ",
+ "IMULQ",
+ "IRETQ",
+ "JCXZQ",
+ "LEAQ",
+ "LEAVEQ",
+ "LODSQ",
+ "MOVQ",
+ "MOVLQSX",
+ "MOVLQZX",
+ "MOVNTIQ",
+ "MOVSQ",
+ "MULQ",
+ "NEGQ",
+ "NOTQ",
+ "ORQ",
+ "POPFQ",
+ "POPQ",
+ "PUSHFQ",
+ "PUSHQ",
+ "RCLQ",
+ "RCRQ",
+ "ROLQ",
+ "RORQ",
+ "QUAD",
+ "SALQ",
+ "SARQ",
+ "SBBQ",
+ "SCASQ",
+ "SHLQ",
+ "SHRQ",
+ "STOSQ",
+ "SUBQ",
+ "TESTQ",
+ "XADDQ",
+ "XCHGQ",
+ "XORQ",
+ "ADDPD",
+ "ADDPS",
+ "ADDSD",
+ "ADDSS",
+ "ANDNPD",
+ "ANDNPS",
+ "ANDPD",
+ "ANDPS",
+ "CMPPD",
+ "CMPPS",
+ "CMPSD",
+ "CMPSS",
+ "COMISD",
+ "COMISS",
+ "CVTPD2PL",
+ "CVTPD2PS",
+ "CVTPL2PD",
+ "CVTPL2PS",
+ "CVTPS2PD",
+ "CVTPS2PL",
+ "CVTSD2SL",
+ "CVTSD2SQ",
+ "CVTSD2SS",
+ "CVTSL2SD",
+ "CVTSL2SS",
+ "CVTSQ2SD",
+ "CVTSQ2SS",
+ "CVTSS2SD",
+ "CVTSS2SL",
+ "CVTSS2SQ",
+ "CVTTPD2PL",
+ "CVTTPS2PL",
+ "CVTTSD2SL",
+ "CVTTSD2SQ",
+ "CVTTSS2SL",
+ "CVTTSS2SQ",
+ "DIVPD",
+ "DIVPS",
+ "DIVSD",
+ "DIVSS",
+ "EMMS",
+ "FXRSTOR",
+ "FXRSTOR64",
+ "FXSAVE",
+ "FXSAVE64",
+ "LDMXCSR",
+ "MASKMOVOU",
+ "MASKMOVQ",
+ "MAXPD",
+ "MAXPS",
+ "MAXSD",
+ "MAXSS",
+ "MINPD",
+ "MINPS",
+ "MINSD",
+ "MINSS",
+ "MOVAPD",
+ "MOVAPS",
+ "MOVOU",
+ "MOVHLPS",
+ "MOVHPD",
+ "MOVHPS",
+ "MOVLHPS",
+ "MOVLPD",
+ "MOVLPS",
+ "MOVMSKPD",
+ "MOVMSKPS",
+ "MOVNTO",
+ "MOVNTPD",
+ "MOVNTPS",
+ "MOVNTQ",
+ "MOVO",
+ "MOVQOZX",
+ "MOVSD",
+ "MOVSS",
+ "MOVUPD",
+ "MOVUPS",
+ "MULPD",
+ "MULPS",
+ "MULSD",
+ "MULSS",
+ "ORPD",
+ "ORPS",
+ "PACKSSLW",
+ "PACKSSWB",
+ "PACKUSWB",
+ "PADDB",
+ "PADDL",
+ "PADDQ",
+ "PADDSB",
+ "PADDSW",
+ "PADDUSB",
+ "PADDUSW",
+ "PADDW",
+ "PANDB",
+ "PANDL",
+ "PANDSB",
+ "PANDSW",
+ "PANDUSB",
+ "PANDUSW",
+ "PANDW",
+ "PAND",
+ "PANDN",
+ "PAVGB",
+ "PAVGW",
+ "PCMPEQB",
+ "PCMPEQL",
+ "PCMPEQW",
+ "PCMPGTB",
+ "PCMPGTL",
+ "PCMPGTW",
+ "PEXTRW",
+ "PFACC",
+ "PFADD",
+ "PFCMPEQ",
+ "PFCMPGE",
+ "PFCMPGT",
+ "PFMAX",
+ "PFMIN",
+ "PFMUL",
+ "PFNACC",
+ "PFPNACC",
+ "PFRCP",
+ "PFRCPIT1",
+ "PFRCPI2T",
+ "PFRSQIT1",
+ "PFRSQRT",
+ "PFSUB",
+ "PFSUBR",
+ "PINSRW",
+ "PINSRD",
+ "PINSRQ",
+ "PMADDWL",
+ "PMAXSW",
+ "PMAXUB",
+ "PMINSW",
+ "PMINUB",
+ "PMOVMSKB",
+ "PMULHRW",
+ "PMULHUW",
+ "PMULHW",
+ "PMULLW",
+ "PMULULQ",
+ "POR",
+ "PSADBW",
+ "PSHUFHW",
+ "PSHUFL",
+ "PSHUFLW",
+ "PSHUFW",
+ "PSHUFB",
+ "PSLLO",
+ "PSLLL",
+ "PSLLQ",
+ "PSLLW",
+ "PSRAL",
+ "PSRAW",
+ "PSRLO",
+ "PSRLL",
+ "PSRLQ",
+ "PSRLW",
+ "PSUBB",
+ "PSUBL",
+ "PSUBQ",
+ "PSUBSB",
+ "PSUBSW",
+ "PSUBUSB",
+ "PSUBUSW",
+ "PSUBW",
+ "PSWAPL",
+ "PUNPCKHBW",
+ "PUNPCKHLQ",
+ "PUNPCKHQDQ",
+ "PUNPCKHWL",
+ "PUNPCKLBW",
+ "PUNPCKLLQ",
+ "PUNPCKLQDQ",
+ "PUNPCKLWL",
+ "PXOR",
+ "RCPPS",
+ "RCPSS",
+ "RSQRTPS",
+ "RSQRTSS",
+ "SHUFPD",
+ "SHUFPS",
+ "SQRTPD",
+ "SQRTPS",
+ "SQRTSD",
+ "SQRTSS",
+ "STMXCSR",
+ "SUBPD",
+ "SUBPS",
+ "SUBSD",
+ "SUBSS",
+ "UCOMISD",
+ "UCOMISS",
+ "UNPCKHPD",
+ "UNPCKHPS",
+ "UNPCKLPD",
+ "UNPCKLPS",
+ "XORPD",
+ "XORPS",
+ "PF2IW",
+ "PF2IL",
+ "PI2FW",
+ "PI2FL",
+ "RETFW",
+ "RETFL",
+ "RETFQ",
+ "SWAPGS",
+ "MODE",
+ "CRC32B",
+ "CRC32Q",
+ "IMUL3Q",
+ "PREFETCHT0",
+ "PREFETCHT1",
+ "PREFETCHT2",
+ "PREFETCHNTA",
+ "MOVQL",
+ "BSWAPL",
+ "BSWAPQ",
+ "UNDEF",
+ "AESENC",
+ "AESENCLAST",
+ "AESDEC",
+ "AESDECLAST",
+ "AESIMC",
+ "AESKEYGENASSIST",
+ "PSHUFD",
+ "PCLMULQDQ",
+ "USEFIELD",
+ "TYPE",
+ "FUNCDATA",
+ "PCDATA",
+ "CHECKNIL",
+ "VARDEF",
+ "VARKILL",
+ "DUFFCOPY",
+ "DUFFZERO",
+ "LAST",
+}
+
+var dnames6 = []string{
+ D_AL: "AL",
+ D_CL: "CL",
+ D_DL: "DL",
+ D_BL: "BL",
+ D_SPB: "SPB",
+ D_BPB: "BPB",
+ D_SIB: "SIB",
+ D_DIB: "DIB",
+ D_R8B: "R8B",
+ D_R9B: "R9B",
+ D_R10B: "R10B",
+ D_R11B: "R11B",
+ D_R12B: "R12B",
+ D_R13B: "R13B",
+ D_R14B: "R14B",
+ D_R15B: "R15B",
+ D_AX: "AX",
+ D_CX: "CX",
+ D_DX: "DX",
+ D_BX: "BX",
+ D_SP: "SP",
+ D_BP: "BP",
+ D_SI: "SI",
+ D_DI: "DI",
+ D_R8: "R8",
+ D_R9: "R9",
+ D_R10: "R10",
+ D_R11: "R11",
+ D_R12: "R12",
+ D_R13: "R13",
+ D_R14: "R14",
+ D_R15: "R15",
+ D_AH: "AH",
+ D_CH: "CH",
+ D_DH: "DH",
+ D_BH: "BH",
+ D_F0: "F0",
+ D_M0: "M0",
+ D_X0: "X0",
+ D_X1: "X1",
+ D_X2: "X2",
+ D_X3: "X3",
+ D_X4: "X4",
+ D_X5: "X5",
+ D_X6: "X6",
+ D_X7: "X7",
+ D_X8: "X8",
+ D_X9: "X9",
+ D_X10: "X10",
+ D_X11: "X11",
+ D_X12: "X12",
+ D_X13: "X13",
+ D_X14: "X14",
+ D_X15: "X15",
+ D_CS: "CS",
+ D_SS: "SS",
+ D_DS: "DS",
+ D_ES: "ES",
+ D_FS: "FS",
+ D_GS: "GS",
+ D_GDTR: "GDTR",
+ D_IDTR: "IDTR",
+ D_LDTR: "LDTR",
+ D_MSW: "MSW",
+ D_TASK: "TASK",
+ D_CR: "CR",
+ D_DR: "DR",
+ D_TR: "TR",
+ D_TLS: "TLS",
+ D_NONE: "NONE",
+ D_BRANCH: "BRANCH",
+ D_EXTERN: "EXTERN",
+ D_STATIC: "STATIC",
+ D_AUTO: "AUTO",
+ D_PARAM: "PARAM",
+ D_CONST: "CONST",
+ D_FCONST: "FCONST",
+ D_SCONST: "SCONST",
+ D_ADDR: "ADDR",
+ D_INDIR: "INDIR",
+}
--- /dev/null
+// Inferno utils/6l/span.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package x86
+
+import (
+ "cmd/internal/obj"
+ "fmt"
+ "log"
+ "strings"
+)
+
+// Instruction layout.
+
+const (
+ MaxAlign = 32
+ LoopAlign = 16
+ MaxLoopPad = 0
+ FuncAlign = 16
+)
+
+type Optab struct {
+ as int16
+ ytab []byte
+ prefix uint8
+ op [23]uint8
+}
+
+type Movtab struct {
+ as int16
+ ft uint8
+ tt uint8
+ code uint8
+ op [4]uint8
+}
+
+const (
+ Yxxx = 0 + iota
+ Ynone
+ Yi0
+ Yi1
+ Yi8
+ Ys32
+ Yi32
+ Yi64
+ Yiauto
+ Yal
+ Ycl
+ Yax
+ Ycx
+ Yrb
+ Yrl
+ Yrf
+ Yf0
+ Yrx
+ Ymb
+ Yml
+ Ym
+ Ybr
+ Ycol
+ Ycs
+ Yss
+ Yds
+ Yes
+ Yfs
+ Ygs
+ Ygdtr
+ Yidtr
+ Yldtr
+ Ymsw
+ Ytask
+ Ycr0
+ Ycr1
+ Ycr2
+ Ycr3
+ Ycr4
+ Ycr5
+ Ycr6
+ Ycr7
+ Ycr8
+ Ydr0
+ Ydr1
+ Ydr2
+ Ydr3
+ Ydr4
+ Ydr5
+ Ydr6
+ Ydr7
+ Ytr0
+ Ytr1
+ Ytr2
+ Ytr3
+ Ytr4
+ Ytr5
+ Ytr6
+ Ytr7
+ Yrl32
+ Yrl64
+ Ymr
+ Ymm
+ Yxr
+ Yxm
+ Ytls
+ Ymax
+ Zxxx = 0 + iota - 67
+ Zlit
+ Zlitm_r
+ Z_rp
+ Zbr
+ Zcall
+ Zcallindreg
+ Zib_
+ Zib_rp
+ Zibo_m
+ Zibo_m_xm
+ Zil_
+ Zil_rp
+ Ziq_rp
+ Zilo_m
+ Ziqo_m
+ Zjmp
+ Zloop
+ Zo_iw
+ Zm_o
+ Zm_r
+ Zm2_r
+ Zm_r_xm
+ Zm_r_i_xm
+ Zm_r_3d
+ Zm_r_xm_nr
+ Zr_m_xm_nr
+ Zibm_r
+ Zmb_r
+ Zaut_r
+ Zo_m
+ Zo_m64
+ Zpseudo
+ Zr_m
+ Zr_m_xm
+ Zr_m_i_xm
+ Zrp_
+ Z_ib
+ Z_il
+ Zm_ibo
+ Zm_ilo
+ Zib_rr
+ Zil_rr
+ Zclr
+ Zbyte
+ Zmax
+ Px = 0
+ P32 = 0x32
+ Pe = 0x66
+ Pm = 0x0f
+ Pq = 0xff
+ Pb = 0xfe
+ Pf2 = 0xf2
+ Pf3 = 0xf3
+ Pq3 = 0x67
+ Pw = 0x48
+ Py = 0x80
+ Rxf = 1 << 9
+ Rxt = 1 << 8
+ Rxw = 1 << 3
+ Rxr = 1 << 2
+ Rxx = 1 << 1
+ Rxb = 1 << 0
+ Maxand = 10
+)
+
+var ycover [Ymax * Ymax]uint8
+
+var reg [D_NONE]int
+
+var regrex [D_NONE + 1]int
+
+var ynone = []uint8{
+ Ynone,
+ Ynone,
+ Zlit,
+ 1,
+ 0,
+}
+
+var ytext = []uint8{
+ Ymb,
+ Yi64,
+ Zpseudo,
+ 1,
+ 0,
+}
+
+var ynop = []uint8{
+ Ynone,
+ Ynone,
+ Zpseudo,
+ 0,
+ Ynone,
+ Yiauto,
+ Zpseudo,
+ 0,
+ Ynone,
+ Yml,
+ Zpseudo,
+ 0,
+ Ynone,
+ Yrf,
+ Zpseudo,
+ 0,
+ Ynone,
+ Yxr,
+ Zpseudo,
+ 0,
+ Yiauto,
+ Ynone,
+ Zpseudo,
+ 0,
+ Yml,
+ Ynone,
+ Zpseudo,
+ 0,
+ Yrf,
+ Ynone,
+ Zpseudo,
+ 0,
+ Yxr,
+ Ynone,
+ Zpseudo,
+ 1,
+ 0,
+}
+
+var yfuncdata = []uint8{
+ Yi32,
+ Ym,
+ Zpseudo,
+ 0,
+ 0,
+}
+
+var ypcdata = []uint8{
+ Yi32,
+ Yi32,
+ Zpseudo,
+ 0,
+ 0,
+}
+
+var yxorb = []uint8{
+ Yi32,
+ Yal,
+ Zib_,
+ 1,
+ Yi32,
+ Ymb,
+ Zibo_m,
+ 2,
+ Yrb,
+ Ymb,
+ Zr_m,
+ 1,
+ Ymb,
+ Yrb,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var yxorl = []uint8{
+ Yi8,
+ Yml,
+ Zibo_m,
+ 2,
+ Yi32,
+ Yax,
+ Zil_,
+ 1,
+ Yi32,
+ Yml,
+ Zilo_m,
+ 2,
+ Yrl,
+ Yml,
+ Zr_m,
+ 1,
+ Yml,
+ Yrl,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var yaddl = []uint8{
+ Yi8,
+ Yml,
+ Zibo_m,
+ 2,
+ Yi32,
+ Yax,
+ Zil_,
+ 1,
+ Yi32,
+ Yml,
+ Zilo_m,
+ 2,
+ Yrl,
+ Yml,
+ Zr_m,
+ 1,
+ Yml,
+ Yrl,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var yincb = []uint8{
+ Ynone,
+ Ymb,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var yincw = []uint8{
+ Ynone,
+ Yml,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var yincl = []uint8{
+ Ynone,
+ Yml,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var ycmpb = []uint8{
+ Yal,
+ Yi32,
+ Z_ib,
+ 1,
+ Ymb,
+ Yi32,
+ Zm_ibo,
+ 2,
+ Ymb,
+ Yrb,
+ Zm_r,
+ 1,
+ Yrb,
+ Ymb,
+ Zr_m,
+ 1,
+ 0,
+}
+
+var ycmpl = []uint8{
+ Yml,
+ Yi8,
+ Zm_ibo,
+ 2,
+ Yax,
+ Yi32,
+ Z_il,
+ 1,
+ Yml,
+ Yi32,
+ Zm_ilo,
+ 2,
+ Yml,
+ Yrl,
+ Zm_r,
+ 1,
+ Yrl,
+ Yml,
+ Zr_m,
+ 1,
+ 0,
+}
+
+var yshb = []uint8{
+ Yi1,
+ Ymb,
+ Zo_m,
+ 2,
+ Yi32,
+ Ymb,
+ Zibo_m,
+ 2,
+ Ycx,
+ Ymb,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var yshl = []uint8{
+ Yi1,
+ Yml,
+ Zo_m,
+ 2,
+ Yi32,
+ Yml,
+ Zibo_m,
+ 2,
+ Ycl,
+ Yml,
+ Zo_m,
+ 2,
+ Ycx,
+ Yml,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var ytestb = []uint8{
+ Yi32,
+ Yal,
+ Zib_,
+ 1,
+ Yi32,
+ Ymb,
+ Zibo_m,
+ 2,
+ Yrb,
+ Ymb,
+ Zr_m,
+ 1,
+ Ymb,
+ Yrb,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var ytestl = []uint8{
+ Yi32,
+ Yax,
+ Zil_,
+ 1,
+ Yi32,
+ Yml,
+ Zilo_m,
+ 2,
+ Yrl,
+ Yml,
+ Zr_m,
+ 1,
+ Yml,
+ Yrl,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var ymovb = []uint8{
+ Yrb,
+ Ymb,
+ Zr_m,
+ 1,
+ Ymb,
+ Yrb,
+ Zm_r,
+ 1,
+ Yi32,
+ Yrb,
+ Zib_rp,
+ 1,
+ Yi32,
+ Ymb,
+ Zibo_m,
+ 2,
+ 0,
+}
+
+var ymbs = []uint8{
+ Ymb,
+ Ynone,
+ Zm_o,
+ 2,
+ 0,
+}
+
+var ybtl = []uint8{
+ Yi8,
+ Yml,
+ Zibo_m,
+ 2,
+ Yrl,
+ Yml,
+ Zr_m,
+ 1,
+ 0,
+}
+
+var ymovw = []uint8{
+ Yrl,
+ Yml,
+ Zr_m,
+ 1,
+ Yml,
+ Yrl,
+ Zm_r,
+ 1,
+ Yi0,
+ Yrl,
+ Zclr,
+ 1,
+ Yi32,
+ Yrl,
+ Zil_rp,
+ 1,
+ Yi32,
+ Yml,
+ Zilo_m,
+ 2,
+ Yiauto,
+ Yrl,
+ Zaut_r,
+ 2,
+ 0,
+}
+
+var ymovl = []uint8{
+ Yrl,
+ Yml,
+ Zr_m,
+ 1,
+ Yml,
+ Yrl,
+ Zm_r,
+ 1,
+ Yi0,
+ Yrl,
+ Zclr,
+ 1,
+ Yi32,
+ Yrl,
+ Zil_rp,
+ 1,
+ Yi32,
+ Yml,
+ Zilo_m,
+ 2,
+ Yml,
+ Ymr,
+ Zm_r_xm,
+ 1, // MMX MOVD
+ Ymr,
+ Yml,
+ Zr_m_xm,
+ 1, // MMX MOVD
+ Yml,
+ Yxr,
+ Zm_r_xm,
+ 2, // XMM MOVD (32 bit)
+ Yxr,
+ Yml,
+ Zr_m_xm,
+ 2, // XMM MOVD (32 bit)
+ Yiauto,
+ Yrl,
+ Zaut_r,
+ 2,
+ 0,
+}
+
+var yret = []uint8{
+ Ynone,
+ Ynone,
+ Zo_iw,
+ 1,
+ Yi32,
+ Ynone,
+ Zo_iw,
+ 1,
+ 0,
+}
+
+var ymovq = []uint8{
+ Yrl,
+ Yml,
+ Zr_m,
+ 1, // 0x89
+ Yml,
+ Yrl,
+ Zm_r,
+ 1, // 0x8b
+ Yi0,
+ Yrl,
+ Zclr,
+ 1, // 0x31
+ Ys32,
+ Yrl,
+ Zilo_m,
+ 2, // 32 bit signed 0xc7,(0)
+ Yi64,
+ Yrl,
+ Ziq_rp,
+ 1, // 0xb8 -- 32/64 bit immediate
+ Yi32,
+ Yml,
+ Zilo_m,
+ 2, // 0xc7,(0)
+ Ym,
+ Ymr,
+ Zm_r_xm_nr,
+ 1, // MMX MOVQ (shorter encoding)
+ Ymr,
+ Ym,
+ Zr_m_xm_nr,
+ 1, // MMX MOVQ
+ Ymm,
+ Ymr,
+ Zm_r_xm,
+ 1, // MMX MOVD
+ Ymr,
+ Ymm,
+ Zr_m_xm,
+ 1, // MMX MOVD
+ Yxr,
+ Ymr,
+ Zm_r_xm_nr,
+ 2, // MOVDQ2Q
+ Yxm,
+ Yxr,
+ Zm_r_xm_nr,
+ 2, // MOVQ xmm1/m64 -> xmm2
+ Yxr,
+ Yxm,
+ Zr_m_xm_nr,
+ 2, // MOVQ xmm1 -> xmm2/m64
+ Yml,
+ Yxr,
+ Zm_r_xm,
+ 2, // MOVD xmm load
+ Yxr,
+ Yml,
+ Zr_m_xm,
+ 2, // MOVD xmm store
+ Yiauto,
+ Yrl,
+ Zaut_r,
+ 2, // built-in LEAQ
+ 0,
+}
+
+var ym_rl = []uint8{
+ Ym,
+ Yrl,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var yrl_m = []uint8{
+ Yrl,
+ Ym,
+ Zr_m,
+ 1,
+ 0,
+}
+
+var ymb_rl = []uint8{
+ Ymb,
+ Yrl,
+ Zmb_r,
+ 1,
+ 0,
+}
+
+var yml_rl = []uint8{
+ Yml,
+ Yrl,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var yrl_ml = []uint8{
+ Yrl,
+ Yml,
+ Zr_m,
+ 1,
+ 0,
+}
+
+var yml_mb = []uint8{
+ Yrb,
+ Ymb,
+ Zr_m,
+ 1,
+ Ymb,
+ Yrb,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var yrb_mb = []uint8{
+ Yrb,
+ Ymb,
+ Zr_m,
+ 1,
+ 0,
+}
+
+var yxchg = []uint8{
+ Yax,
+ Yrl,
+ Z_rp,
+ 1,
+ Yrl,
+ Yax,
+ Zrp_,
+ 1,
+ Yrl,
+ Yml,
+ Zr_m,
+ 1,
+ Yml,
+ Yrl,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var ydivl = []uint8{
+ Yml,
+ Ynone,
+ Zm_o,
+ 2,
+ 0,
+}
+
+var ydivb = []uint8{
+ Ymb,
+ Ynone,
+ Zm_o,
+ 2,
+ 0,
+}
+
+var yimul = []uint8{
+ Yml,
+ Ynone,
+ Zm_o,
+ 2,
+ Yi8,
+ Yrl,
+ Zib_rr,
+ 1,
+ Yi32,
+ Yrl,
+ Zil_rr,
+ 1,
+ Yml,
+ Yrl,
+ Zm_r,
+ 2,
+ 0,
+}
+
+var yimul3 = []uint8{
+ Yml,
+ Yrl,
+ Zibm_r,
+ 2,
+ 0,
+}
+
+var ybyte = []uint8{
+ Yi64,
+ Ynone,
+ Zbyte,
+ 1,
+ 0,
+}
+
+var yin = []uint8{
+ Yi32,
+ Ynone,
+ Zib_,
+ 1,
+ Ynone,
+ Ynone,
+ Zlit,
+ 1,
+ 0,
+}
+
+var yint = []uint8{
+ Yi32,
+ Ynone,
+ Zib_,
+ 1,
+ 0,
+}
+
+var ypushl = []uint8{
+ Yrl,
+ Ynone,
+ Zrp_,
+ 1,
+ Ym,
+ Ynone,
+ Zm_o,
+ 2,
+ Yi8,
+ Ynone,
+ Zib_,
+ 1,
+ Yi32,
+ Ynone,
+ Zil_,
+ 1,
+ 0,
+}
+
+var ypopl = []uint8{
+ Ynone,
+ Yrl,
+ Z_rp,
+ 1,
+ Ynone,
+ Ym,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var ybswap = []uint8{
+ Ynone,
+ Yrl,
+ Z_rp,
+ 2,
+ 0,
+}
+
+var yscond = []uint8{
+ Ynone,
+ Ymb,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var yjcond = []uint8{
+ Ynone,
+ Ybr,
+ Zbr,
+ 0,
+ Yi0,
+ Ybr,
+ Zbr,
+ 0,
+ Yi1,
+ Ybr,
+ Zbr,
+ 1,
+ 0,
+}
+
+var yloop = []uint8{
+ Ynone,
+ Ybr,
+ Zloop,
+ 1,
+ 0,
+}
+
+var ycall = []uint8{
+ Ynone,
+ Yml,
+ Zcallindreg,
+ 0,
+ Yrx,
+ Yrx,
+ Zcallindreg,
+ 2,
+ Ynone,
+ Ybr,
+ Zcall,
+ 1,
+ 0,
+}
+
+var yduff = []uint8{
+ Ynone,
+ Yi32,
+ Zcall,
+ 1,
+ 0,
+}
+
+var yjmp = []uint8{
+ Ynone,
+ Yml,
+ Zo_m64,
+ 2,
+ Ynone,
+ Ybr,
+ Zjmp,
+ 1,
+ 0,
+}
+
+var yfmvd = []uint8{
+ Ym,
+ Yf0,
+ Zm_o,
+ 2,
+ Yf0,
+ Ym,
+ Zo_m,
+ 2,
+ Yrf,
+ Yf0,
+ Zm_o,
+ 2,
+ Yf0,
+ Yrf,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var yfmvdp = []uint8{
+ Yf0,
+ Ym,
+ Zo_m,
+ 2,
+ Yf0,
+ Yrf,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var yfmvf = []uint8{
+ Ym,
+ Yf0,
+ Zm_o,
+ 2,
+ Yf0,
+ Ym,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var yfmvx = []uint8{
+ Ym,
+ Yf0,
+ Zm_o,
+ 2,
+ 0,
+}
+
+var yfmvp = []uint8{
+ Yf0,
+ Ym,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var yfadd = []uint8{
+ Ym,
+ Yf0,
+ Zm_o,
+ 2,
+ Yrf,
+ Yf0,
+ Zm_o,
+ 2,
+ Yf0,
+ Yrf,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var yfaddp = []uint8{
+ Yf0,
+ Yrf,
+ Zo_m,
+ 2,
+ 0,
+}
+
+var yfxch = []uint8{
+ Yf0,
+ Yrf,
+ Zo_m,
+ 2,
+ Yrf,
+ Yf0,
+ Zm_o,
+ 2,
+ 0,
+}
+
+var ycompp = []uint8{
+ Yf0,
+ Yrf,
+ Zo_m,
+ 2, /* botch is really f0,f1 */
+ 0,
+}
+
+var ystsw = []uint8{
+ Ynone,
+ Ym,
+ Zo_m,
+ 2,
+ Ynone,
+ Yax,
+ Zlit,
+ 1,
+ 0,
+}
+
+var ystcw = []uint8{
+ Ynone,
+ Ym,
+ Zo_m,
+ 2,
+ Ym,
+ Ynone,
+ Zm_o,
+ 2,
+ 0,
+}
+
+var ysvrs = []uint8{
+ Ynone,
+ Ym,
+ Zo_m,
+ 2,
+ Ym,
+ Ynone,
+ Zm_o,
+ 2,
+ 0,
+}
+
+var ymm = []uint8{
+ Ymm,
+ Ymr,
+ Zm_r_xm,
+ 1,
+ Yxm,
+ Yxr,
+ Zm_r_xm,
+ 2,
+ 0,
+}
+
+var yxm = []uint8{
+ Yxm,
+ Yxr,
+ Zm_r_xm,
+ 1,
+ 0,
+}
+
+var yxcvm1 = []uint8{
+ Yxm,
+ Yxr,
+ Zm_r_xm,
+ 2,
+ Yxm,
+ Ymr,
+ Zm_r_xm,
+ 2,
+ 0,
+}
+
+var yxcvm2 = []uint8{
+ Yxm,
+ Yxr,
+ Zm_r_xm,
+ 2,
+ Ymm,
+ Yxr,
+ Zm_r_xm,
+ 2,
+ 0,
+}
+
+/*
+static uchar yxmq[] =
+{
+ Yxm, Yxr, Zm_r_xm, 2,
+ 0
+};
+*/
+var yxr = []uint8{
+ Yxr,
+ Yxr,
+ Zm_r_xm,
+ 1,
+ 0,
+}
+
+var yxr_ml = []uint8{
+ Yxr,
+ Yml,
+ Zr_m_xm,
+ 1,
+ 0,
+}
+
+var ymr = []uint8{
+ Ymr,
+ Ymr,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var ymr_ml = []uint8{
+ Ymr,
+ Yml,
+ Zr_m_xm,
+ 1,
+ 0,
+}
+
+var yxcmp = []uint8{
+ Yxm,
+ Yxr,
+ Zm_r_xm,
+ 1,
+ 0,
+}
+
+var yxcmpi = []uint8{
+ Yxm,
+ Yxr,
+ Zm_r_i_xm,
+ 2,
+ 0,
+}
+
+var yxmov = []uint8{
+ Yxm,
+ Yxr,
+ Zm_r_xm,
+ 1,
+ Yxr,
+ Yxm,
+ Zr_m_xm,
+ 1,
+ 0,
+}
+
+var yxcvfl = []uint8{
+ Yxm,
+ Yrl,
+ Zm_r_xm,
+ 1,
+ 0,
+}
+
+var yxcvlf = []uint8{
+ Yml,
+ Yxr,
+ Zm_r_xm,
+ 1,
+ 0,
+}
+
+var yxcvfq = []uint8{
+ Yxm,
+ Yrl,
+ Zm_r_xm,
+ 2,
+ 0,
+}
+
+var yxcvqf = []uint8{
+ Yml,
+ Yxr,
+ Zm_r_xm,
+ 2,
+ 0,
+}
+
+var yps = []uint8{
+ Ymm,
+ Ymr,
+ Zm_r_xm,
+ 1,
+ Yi8,
+ Ymr,
+ Zibo_m_xm,
+ 2,
+ Yxm,
+ Yxr,
+ Zm_r_xm,
+ 2,
+ Yi8,
+ Yxr,
+ Zibo_m_xm,
+ 3,
+ 0,
+}
+
+var yxrrl = []uint8{
+ Yxr,
+ Yrl,
+ Zm_r,
+ 1,
+ 0,
+}
+
+var ymfp = []uint8{
+ Ymm,
+ Ymr,
+ Zm_r_3d,
+ 1,
+ 0,
+}
+
+var ymrxr = []uint8{
+ Ymr,
+ Yxr,
+ Zm_r,
+ 1,
+ Yxm,
+ Yxr,
+ Zm_r_xm,
+ 1,
+ 0,
+}
+
+var ymshuf = []uint8{
+ Ymm,
+ Ymr,
+ Zibm_r,
+ 2,
+ 0,
+}
+
+var ymshufb = []uint8{
+ Yxm,
+ Yxr,
+ Zm2_r,
+ 2,
+ 0,
+}
+
+var yxshuf = []uint8{
+ Yxm,
+ Yxr,
+ Zibm_r,
+ 2,
+ 0,
+}
+
+var yextrw = []uint8{
+ Yxr,
+ Yrl,
+ Zibm_r,
+ 2,
+ 0,
+}
+
+var yinsrw = []uint8{
+ Yml,
+ Yxr,
+ Zibm_r,
+ 2,
+ 0,
+}
+
+var yinsr = []uint8{
+ Ymm,
+ Yxr,
+ Zibm_r,
+ 3,
+ 0,
+}
+
+var ypsdq = []uint8{
+ Yi8,
+ Yxr,
+ Zibo_m,
+ 2,
+ 0,
+}
+
+var ymskb = []uint8{
+ Yxr,
+ Yrl,
+ Zm_r_xm,
+ 2,
+ Ymr,
+ Yrl,
+ Zm_r_xm,
+ 1,
+ 0,
+}
+
+var ycrc32l = []uint8{Yml, Yrl, Zlitm_r, 0}
+
+var yprefetch = []uint8{
+ Ym,
+ Ynone,
+ Zm_o,
+ 2,
+ 0,
+}
+
+var yaes = []uint8{
+ Yxm,
+ Yxr,
+ Zlitm_r,
+ 2,
+ 0,
+}
+
+var yaes2 = []uint8{
+ Yxm,
+ Yxr,
+ Zibm_r,
+ 2,
+ 0,
+}
+
+/*
+ * You are doasm, holding in your hand a Prog* with p->as set to, say, ACRC32,
+ * and p->from and p->to as operands (Addr*). The linker scans optab to find
+ * the entry with the given p->as and then looks through the ytable for that
+ * instruction (the second field in the optab struct) for a line whose first
+ * two values match the Ytypes of the p->from and p->to operands. The function
+ * oclass in span.c computes the specific Ytype of an operand and then the set
+ * of more general Ytypes that it satisfies is implied by the ycover table, set
+ * up in instinit. For example, oclass distinguishes the constants 0 and 1
+ * from the more general 8-bit constants, but instinit says
+ *
+ * ycover[Yi0*Ymax + Ys32] = 1;
+ * ycover[Yi1*Ymax + Ys32] = 1;
+ * ycover[Yi8*Ymax + Ys32] = 1;
+ *
+ * which means that Yi0, Yi1, and Yi8 all count as Ys32 (signed 32)
+ * if that's what an instruction can handle.
+ *
+ * In parallel with the scan through the ytable for the appropriate line, there
+ * is a z pointer that starts out pointing at the strange magic byte list in
+ * the Optab struct. With each step past a non-matching ytable line, z
+ * advances by the 4th entry in the line. When a matching line is found, that
+ * z pointer has the extra data to use in laying down the instruction bytes.
+ * The actual bytes laid down are a function of the 3rd entry in the line (that
+ * is, the Ztype) and the z bytes.
+ *
+ * For example, let's look at AADDL. The optab line says:
+ * { AADDL, yaddl, Px, 0x83,(00),0x05,0x81,(00),0x01,0x03 },
+ *
+ * and yaddl says
+ * uchar yaddl[] =
+ * {
+ * Yi8, Yml, Zibo_m, 2,
+ * Yi32, Yax, Zil_, 1,
+ * Yi32, Yml, Zilo_m, 2,
+ * Yrl, Yml, Zr_m, 1,
+ * Yml, Yrl, Zm_r, 1,
+ * 0
+ * };
+ *
+ * so there are 5 possible types of ADDL instruction that can be laid down, and
+ * possible states used to lay them down (Ztype and z pointer, assuming z
+ * points at {0x83,(00),0x05,0x81,(00),0x01,0x03}) are:
+ *
+ * Yi8, Yml -> Zibo_m, z (0x83, 00)
+ * Yi32, Yax -> Zil_, z+2 (0x05)
+ * Yi32, Yml -> Zilo_m, z+2+1 (0x81, 0x00)
+ * Yrl, Yml -> Zr_m, z+2+1+2 (0x01)
+ * Yml, Yrl -> Zm_r, z+2+1+2+1 (0x03)
+ *
+ * The Pconstant in the optab line controls the prefix bytes to emit. That's
+ * relatively straightforward as this program goes.
+ *
+ * The switch on t[2] in doasm implements the various Z cases. Zibo_m, for
+ * example, is an opcode byte (z[0]) then an asmando (which is some kind of
+ * encoded addressing mode for the Yml arg), and then a single immediate byte.
+ * Zilo_m is the same but a long (32-bit) immediate.
+ */
+var optab =
+/* as, ytab, andproto, opcode */
+[]Optab{
+ Optab{AXXX, nil, 0, [23]uint8{}},
+ Optab{AAAA, ynone, P32, [23]uint8{0x37}},
+ Optab{AAAD, ynone, P32, [23]uint8{0xd5, 0x0a}},
+ Optab{AAAM, ynone, P32, [23]uint8{0xd4, 0x0a}},
+ Optab{AAAS, ynone, P32, [23]uint8{0x3f}},
+ Optab{AADCB, yxorb, Pb, [23]uint8{0x14, 0x80, 02, 0x10, 0x10}},
+ Optab{AADCL, yxorl, Px, [23]uint8{0x83, 02, 0x15, 0x81, 02, 0x11, 0x13}},
+ Optab{AADCQ, yxorl, Pw, [23]uint8{0x83, 02, 0x15, 0x81, 02, 0x11, 0x13}},
+ Optab{AADCW, yxorl, Pe, [23]uint8{0x83, 02, 0x15, 0x81, 02, 0x11, 0x13}},
+ Optab{AADDB, yxorb, Pb, [23]uint8{0x04, 0x80, 00, 0x00, 0x02}},
+ Optab{AADDL, yaddl, Px, [23]uint8{0x83, 00, 0x05, 0x81, 00, 0x01, 0x03}},
+ Optab{AADDPD, yxm, Pq, [23]uint8{0x58}},
+ Optab{AADDPS, yxm, Pm, [23]uint8{0x58}},
+ Optab{AADDQ, yaddl, Pw, [23]uint8{0x83, 00, 0x05, 0x81, 00, 0x01, 0x03}},
+ Optab{AADDSD, yxm, Pf2, [23]uint8{0x58}},
+ Optab{AADDSS, yxm, Pf3, [23]uint8{0x58}},
+ Optab{AADDW, yaddl, Pe, [23]uint8{0x83, 00, 0x05, 0x81, 00, 0x01, 0x03}},
+ Optab{AADJSP, nil, 0, [23]uint8{}},
+ Optab{AANDB, yxorb, Pb, [23]uint8{0x24, 0x80, 04, 0x20, 0x22}},
+ Optab{AANDL, yxorl, Px, [23]uint8{0x83, 04, 0x25, 0x81, 04, 0x21, 0x23}},
+ Optab{AANDNPD, yxm, Pq, [23]uint8{0x55}},
+ Optab{AANDNPS, yxm, Pm, [23]uint8{0x55}},
+ Optab{AANDPD, yxm, Pq, [23]uint8{0x54}},
+ Optab{AANDPS, yxm, Pq, [23]uint8{0x54}},
+ Optab{AANDQ, yxorl, Pw, [23]uint8{0x83, 04, 0x25, 0x81, 04, 0x21, 0x23}},
+ Optab{AANDW, yxorl, Pe, [23]uint8{0x83, 04, 0x25, 0x81, 04, 0x21, 0x23}},
+ Optab{AARPL, yrl_ml, P32, [23]uint8{0x63}},
+ Optab{ABOUNDL, yrl_m, P32, [23]uint8{0x62}},
+ Optab{ABOUNDW, yrl_m, Pe, [23]uint8{0x62}},
+ Optab{ABSFL, yml_rl, Pm, [23]uint8{0xbc}},
+ Optab{ABSFQ, yml_rl, Pw, [23]uint8{0x0f, 0xbc}},
+ Optab{ABSFW, yml_rl, Pq, [23]uint8{0xbc}},
+ Optab{ABSRL, yml_rl, Pm, [23]uint8{0xbd}},
+ Optab{ABSRQ, yml_rl, Pw, [23]uint8{0x0f, 0xbd}},
+ Optab{ABSRW, yml_rl, Pq, [23]uint8{0xbd}},
+ Optab{ABSWAPL, ybswap, Px, [23]uint8{0x0f, 0xc8}},
+ Optab{ABSWAPQ, ybswap, Pw, [23]uint8{0x0f, 0xc8}},
+ Optab{ABTCL, ybtl, Pm, [23]uint8{0xba, 07, 0xbb}},
+ Optab{ABTCQ, ybtl, Pw, [23]uint8{0x0f, 0xba, 07, 0x0f, 0xbb}},
+ Optab{ABTCW, ybtl, Pq, [23]uint8{0xba, 07, 0xbb}},
+ Optab{ABTL, ybtl, Pm, [23]uint8{0xba, 04, 0xa3}},
+ Optab{ABTQ, ybtl, Pw, [23]uint8{0x0f, 0xba, 04, 0x0f, 0xa3}},
+ Optab{ABTRL, ybtl, Pm, [23]uint8{0xba, 06, 0xb3}},
+ Optab{ABTRQ, ybtl, Pw, [23]uint8{0x0f, 0xba, 06, 0x0f, 0xb3}},
+ Optab{ABTRW, ybtl, Pq, [23]uint8{0xba, 06, 0xb3}},
+ Optab{ABTSL, ybtl, Pm, [23]uint8{0xba, 05, 0xab}},
+ Optab{ABTSQ, ybtl, Pw, [23]uint8{0x0f, 0xba, 05, 0x0f, 0xab}},
+ Optab{ABTSW, ybtl, Pq, [23]uint8{0xba, 05, 0xab}},
+ Optab{ABTW, ybtl, Pq, [23]uint8{0xba, 04, 0xa3}},
+ Optab{ABYTE, ybyte, Px, [23]uint8{1}},
+ Optab{ACALL, ycall, Px, [23]uint8{0xff, 02, 0xe8}},
+ Optab{ACDQ, ynone, Px, [23]uint8{0x99}},
+ Optab{ACLC, ynone, Px, [23]uint8{0xf8}},
+ Optab{ACLD, ynone, Px, [23]uint8{0xfc}},
+ Optab{ACLI, ynone, Px, [23]uint8{0xfa}},
+ Optab{ACLTS, ynone, Pm, [23]uint8{0x06}},
+ Optab{ACMC, ynone, Px, [23]uint8{0xf5}},
+ Optab{ACMOVLCC, yml_rl, Pm, [23]uint8{0x43}},
+ Optab{ACMOVLCS, yml_rl, Pm, [23]uint8{0x42}},
+ Optab{ACMOVLEQ, yml_rl, Pm, [23]uint8{0x44}},
+ Optab{ACMOVLGE, yml_rl, Pm, [23]uint8{0x4d}},
+ Optab{ACMOVLGT, yml_rl, Pm, [23]uint8{0x4f}},
+ Optab{ACMOVLHI, yml_rl, Pm, [23]uint8{0x47}},
+ Optab{ACMOVLLE, yml_rl, Pm, [23]uint8{0x4e}},
+ Optab{ACMOVLLS, yml_rl, Pm, [23]uint8{0x46}},
+ Optab{ACMOVLLT, yml_rl, Pm, [23]uint8{0x4c}},
+ Optab{ACMOVLMI, yml_rl, Pm, [23]uint8{0x48}},
+ Optab{ACMOVLNE, yml_rl, Pm, [23]uint8{0x45}},
+ Optab{ACMOVLOC, yml_rl, Pm, [23]uint8{0x41}},
+ Optab{ACMOVLOS, yml_rl, Pm, [23]uint8{0x40}},
+ Optab{ACMOVLPC, yml_rl, Pm, [23]uint8{0x4b}},
+ Optab{ACMOVLPL, yml_rl, Pm, [23]uint8{0x49}},
+ Optab{ACMOVLPS, yml_rl, Pm, [23]uint8{0x4a}},
+ Optab{ACMOVQCC, yml_rl, Pw, [23]uint8{0x0f, 0x43}},
+ Optab{ACMOVQCS, yml_rl, Pw, [23]uint8{0x0f, 0x42}},
+ Optab{ACMOVQEQ, yml_rl, Pw, [23]uint8{0x0f, 0x44}},
+ Optab{ACMOVQGE, yml_rl, Pw, [23]uint8{0x0f, 0x4d}},
+ Optab{ACMOVQGT, yml_rl, Pw, [23]uint8{0x0f, 0x4f}},
+ Optab{ACMOVQHI, yml_rl, Pw, [23]uint8{0x0f, 0x47}},
+ Optab{ACMOVQLE, yml_rl, Pw, [23]uint8{0x0f, 0x4e}},
+ Optab{ACMOVQLS, yml_rl, Pw, [23]uint8{0x0f, 0x46}},
+ Optab{ACMOVQLT, yml_rl, Pw, [23]uint8{0x0f, 0x4c}},
+ Optab{ACMOVQMI, yml_rl, Pw, [23]uint8{0x0f, 0x48}},
+ Optab{ACMOVQNE, yml_rl, Pw, [23]uint8{0x0f, 0x45}},
+ Optab{ACMOVQOC, yml_rl, Pw, [23]uint8{0x0f, 0x41}},
+ Optab{ACMOVQOS, yml_rl, Pw, [23]uint8{0x0f, 0x40}},
+ Optab{ACMOVQPC, yml_rl, Pw, [23]uint8{0x0f, 0x4b}},
+ Optab{ACMOVQPL, yml_rl, Pw, [23]uint8{0x0f, 0x49}},
+ Optab{ACMOVQPS, yml_rl, Pw, [23]uint8{0x0f, 0x4a}},
+ Optab{ACMOVWCC, yml_rl, Pq, [23]uint8{0x43}},
+ Optab{ACMOVWCS, yml_rl, Pq, [23]uint8{0x42}},
+ Optab{ACMOVWEQ, yml_rl, Pq, [23]uint8{0x44}},
+ Optab{ACMOVWGE, yml_rl, Pq, [23]uint8{0x4d}},
+ Optab{ACMOVWGT, yml_rl, Pq, [23]uint8{0x4f}},
+ Optab{ACMOVWHI, yml_rl, Pq, [23]uint8{0x47}},
+ Optab{ACMOVWLE, yml_rl, Pq, [23]uint8{0x4e}},
+ Optab{ACMOVWLS, yml_rl, Pq, [23]uint8{0x46}},
+ Optab{ACMOVWLT, yml_rl, Pq, [23]uint8{0x4c}},
+ Optab{ACMOVWMI, yml_rl, Pq, [23]uint8{0x48}},
+ Optab{ACMOVWNE, yml_rl, Pq, [23]uint8{0x45}},
+ Optab{ACMOVWOC, yml_rl, Pq, [23]uint8{0x41}},
+ Optab{ACMOVWOS, yml_rl, Pq, [23]uint8{0x40}},
+ Optab{ACMOVWPC, yml_rl, Pq, [23]uint8{0x4b}},
+ Optab{ACMOVWPL, yml_rl, Pq, [23]uint8{0x49}},
+ Optab{ACMOVWPS, yml_rl, Pq, [23]uint8{0x4a}},
+ Optab{ACMPB, ycmpb, Pb, [23]uint8{0x3c, 0x80, 07, 0x38, 0x3a}},
+ Optab{ACMPL, ycmpl, Px, [23]uint8{0x83, 07, 0x3d, 0x81, 07, 0x39, 0x3b}},
+ Optab{ACMPPD, yxcmpi, Px, [23]uint8{Pe, 0xc2}},
+ Optab{ACMPPS, yxcmpi, Pm, [23]uint8{0xc2, 0}},
+ Optab{ACMPQ, ycmpl, Pw, [23]uint8{0x83, 07, 0x3d, 0x81, 07, 0x39, 0x3b}},
+ Optab{ACMPSB, ynone, Pb, [23]uint8{0xa6}},
+ Optab{ACMPSD, yxcmpi, Px, [23]uint8{Pf2, 0xc2}},
+ Optab{ACMPSL, ynone, Px, [23]uint8{0xa7}},
+ Optab{ACMPSQ, ynone, Pw, [23]uint8{0xa7}},
+ Optab{ACMPSS, yxcmpi, Px, [23]uint8{Pf3, 0xc2}},
+ Optab{ACMPSW, ynone, Pe, [23]uint8{0xa7}},
+ Optab{ACMPW, ycmpl, Pe, [23]uint8{0x83, 07, 0x3d, 0x81, 07, 0x39, 0x3b}},
+ Optab{ACOMISD, yxcmp, Pe, [23]uint8{0x2f}},
+ Optab{ACOMISS, yxcmp, Pm, [23]uint8{0x2f}},
+ Optab{ACPUID, ynone, Pm, [23]uint8{0xa2}},
+ Optab{ACVTPL2PD, yxcvm2, Px, [23]uint8{Pf3, 0xe6, Pe, 0x2a}},
+ Optab{ACVTPL2PS, yxcvm2, Pm, [23]uint8{0x5b, 0, 0x2a, 0}},
+ Optab{ACVTPD2PL, yxcvm1, Px, [23]uint8{Pf2, 0xe6, Pe, 0x2d}},
+ Optab{ACVTPD2PS, yxm, Pe, [23]uint8{0x5a}},
+ Optab{ACVTPS2PL, yxcvm1, Px, [23]uint8{Pe, 0x5b, Pm, 0x2d}},
+ Optab{ACVTPS2PD, yxm, Pm, [23]uint8{0x5a}},
+ Optab{API2FW, ymfp, Px, [23]uint8{0x0c}},
+ Optab{ACVTSD2SL, yxcvfl, Pf2, [23]uint8{0x2d}},
+ Optab{ACVTSD2SQ, yxcvfq, Pw, [23]uint8{Pf2, 0x2d}},
+ Optab{ACVTSD2SS, yxm, Pf2, [23]uint8{0x5a}},
+ Optab{ACVTSL2SD, yxcvlf, Pf2, [23]uint8{0x2a}},
+ Optab{ACVTSQ2SD, yxcvqf, Pw, [23]uint8{Pf2, 0x2a}},
+ Optab{ACVTSL2SS, yxcvlf, Pf3, [23]uint8{0x2a}},
+ Optab{ACVTSQ2SS, yxcvqf, Pw, [23]uint8{Pf3, 0x2a}},
+ Optab{ACVTSS2SD, yxm, Pf3, [23]uint8{0x5a}},
+ Optab{ACVTSS2SL, yxcvfl, Pf3, [23]uint8{0x2d}},
+ Optab{ACVTSS2SQ, yxcvfq, Pw, [23]uint8{Pf3, 0x2d}},
+ Optab{ACVTTPD2PL, yxcvm1, Px, [23]uint8{Pe, 0xe6, Pe, 0x2c}},
+ Optab{ACVTTPS2PL, yxcvm1, Px, [23]uint8{Pf3, 0x5b, Pm, 0x2c}},
+ Optab{ACVTTSD2SL, yxcvfl, Pf2, [23]uint8{0x2c}},
+ Optab{ACVTTSD2SQ, yxcvfq, Pw, [23]uint8{Pf2, 0x2c}},
+ Optab{ACVTTSS2SL, yxcvfl, Pf3, [23]uint8{0x2c}},
+ Optab{ACVTTSS2SQ, yxcvfq, Pw, [23]uint8{Pf3, 0x2c}},
+ Optab{ACWD, ynone, Pe, [23]uint8{0x99}},
+ Optab{ACQO, ynone, Pw, [23]uint8{0x99}},
+ Optab{ADAA, ynone, P32, [23]uint8{0x27}},
+ Optab{ADAS, ynone, P32, [23]uint8{0x2f}},
+ Optab{ADATA, nil, 0, [23]uint8{}},
+ Optab{ADECB, yincb, Pb, [23]uint8{0xfe, 01}},
+ Optab{ADECL, yincl, Px, [23]uint8{0xff, 01}},
+ Optab{ADECQ, yincl, Pw, [23]uint8{0xff, 01}},
+ Optab{ADECW, yincw, Pe, [23]uint8{0xff, 01}},
+ Optab{ADIVB, ydivb, Pb, [23]uint8{0xf6, 06}},
+ Optab{ADIVL, ydivl, Px, [23]uint8{0xf7, 06}},
+ Optab{ADIVPD, yxm, Pe, [23]uint8{0x5e}},
+ Optab{ADIVPS, yxm, Pm, [23]uint8{0x5e}},
+ Optab{ADIVQ, ydivl, Pw, [23]uint8{0xf7, 06}},
+ Optab{ADIVSD, yxm, Pf2, [23]uint8{0x5e}},
+ Optab{ADIVSS, yxm, Pf3, [23]uint8{0x5e}},
+ Optab{ADIVW, ydivl, Pe, [23]uint8{0xf7, 06}},
+ Optab{AEMMS, ynone, Pm, [23]uint8{0x77}},
+ Optab{AENTER, nil, 0, [23]uint8{}}, /* botch */
+ Optab{AFXRSTOR, ysvrs, Pm, [23]uint8{0xae, 01, 0xae, 01}},
+ Optab{AFXSAVE, ysvrs, Pm, [23]uint8{0xae, 00, 0xae, 00}},
+ Optab{AFXRSTOR64, ysvrs, Pw, [23]uint8{0x0f, 0xae, 01, 0x0f, 0xae, 01}},
+ Optab{AFXSAVE64, ysvrs, Pw, [23]uint8{0x0f, 0xae, 00, 0x0f, 0xae, 00}},
+ Optab{AGLOBL, nil, 0, [23]uint8{}},
+ Optab{AGOK, nil, 0, [23]uint8{}},
+ Optab{AHISTORY, nil, 0, [23]uint8{}},
+ Optab{AHLT, ynone, Px, [23]uint8{0xf4}},
+ Optab{AIDIVB, ydivb, Pb, [23]uint8{0xf6, 07}},
+ Optab{AIDIVL, ydivl, Px, [23]uint8{0xf7, 07}},
+ Optab{AIDIVQ, ydivl, Pw, [23]uint8{0xf7, 07}},
+ Optab{AIDIVW, ydivl, Pe, [23]uint8{0xf7, 07}},
+ Optab{AIMULB, ydivb, Pb, [23]uint8{0xf6, 05}},
+ Optab{AIMULL, yimul, Px, [23]uint8{0xf7, 05, 0x6b, 0x69, Pm, 0xaf}},
+ Optab{AIMULQ, yimul, Pw, [23]uint8{0xf7, 05, 0x6b, 0x69, Pm, 0xaf}},
+ Optab{AIMULW, yimul, Pe, [23]uint8{0xf7, 05, 0x6b, 0x69, Pm, 0xaf}},
+ Optab{AIMUL3Q, yimul3, Pw, [23]uint8{0x6b, 00}},
+ Optab{AINB, yin, Pb, [23]uint8{0xe4, 0xec}},
+ Optab{AINCB, yincb, Pb, [23]uint8{0xfe, 00}},
+ Optab{AINCL, yincl, Px, [23]uint8{0xff, 00}},
+ Optab{AINCQ, yincl, Pw, [23]uint8{0xff, 00}},
+ Optab{AINCW, yincw, Pe, [23]uint8{0xff, 00}},
+ Optab{AINL, yin, Px, [23]uint8{0xe5, 0xed}},
+ Optab{AINSB, ynone, Pb, [23]uint8{0x6c}},
+ Optab{AINSL, ynone, Px, [23]uint8{0x6d}},
+ Optab{AINSW, ynone, Pe, [23]uint8{0x6d}},
+ Optab{AINT, yint, Px, [23]uint8{0xcd}},
+ Optab{AINTO, ynone, P32, [23]uint8{0xce}},
+ Optab{AINW, yin, Pe, [23]uint8{0xe5, 0xed}},
+ Optab{AIRETL, ynone, Px, [23]uint8{0xcf}},
+ Optab{AIRETQ, ynone, Pw, [23]uint8{0xcf}},
+ Optab{AIRETW, ynone, Pe, [23]uint8{0xcf}},
+ Optab{AJCC, yjcond, Px, [23]uint8{0x73, 0x83, 00}},
+ Optab{AJCS, yjcond, Px, [23]uint8{0x72, 0x82}},
+ Optab{AJCXZL, yloop, Px, [23]uint8{0xe3}},
+ Optab{AJCXZQ, yloop, Px, [23]uint8{0xe3}},
+ Optab{AJEQ, yjcond, Px, [23]uint8{0x74, 0x84}},
+ Optab{AJGE, yjcond, Px, [23]uint8{0x7d, 0x8d}},
+ Optab{AJGT, yjcond, Px, [23]uint8{0x7f, 0x8f}},
+ Optab{AJHI, yjcond, Px, [23]uint8{0x77, 0x87}},
+ Optab{AJLE, yjcond, Px, [23]uint8{0x7e, 0x8e}},
+ Optab{AJLS, yjcond, Px, [23]uint8{0x76, 0x86}},
+ Optab{AJLT, yjcond, Px, [23]uint8{0x7c, 0x8c}},
+ Optab{AJMI, yjcond, Px, [23]uint8{0x78, 0x88}},
+ Optab{AJMP, yjmp, Px, [23]uint8{0xff, 04, 0xeb, 0xe9}},
+ Optab{AJNE, yjcond, Px, [23]uint8{0x75, 0x85}},
+ Optab{AJOC, yjcond, Px, [23]uint8{0x71, 0x81, 00}},
+ Optab{AJOS, yjcond, Px, [23]uint8{0x70, 0x80, 00}},
+ Optab{AJPC, yjcond, Px, [23]uint8{0x7b, 0x8b}},
+ Optab{AJPL, yjcond, Px, [23]uint8{0x79, 0x89}},
+ Optab{AJPS, yjcond, Px, [23]uint8{0x7a, 0x8a}},
+ Optab{ALAHF, ynone, Px, [23]uint8{0x9f}},
+ Optab{ALARL, yml_rl, Pm, [23]uint8{0x02}},
+ Optab{ALARW, yml_rl, Pq, [23]uint8{0x02}},
+ Optab{ALDMXCSR, ysvrs, Pm, [23]uint8{0xae, 02, 0xae, 02}},
+ Optab{ALEAL, ym_rl, Px, [23]uint8{0x8d}},
+ Optab{ALEAQ, ym_rl, Pw, [23]uint8{0x8d}},
+ Optab{ALEAVEL, ynone, P32, [23]uint8{0xc9}},
+ Optab{ALEAVEQ, ynone, Py, [23]uint8{0xc9}},
+ Optab{ALEAVEW, ynone, Pe, [23]uint8{0xc9}},
+ Optab{ALEAW, ym_rl, Pe, [23]uint8{0x8d}},
+ Optab{ALOCK, ynone, Px, [23]uint8{0xf0}},
+ Optab{ALODSB, ynone, Pb, [23]uint8{0xac}},
+ Optab{ALODSL, ynone, Px, [23]uint8{0xad}},
+ Optab{ALODSQ, ynone, Pw, [23]uint8{0xad}},
+ Optab{ALODSW, ynone, Pe, [23]uint8{0xad}},
+ Optab{ALONG, ybyte, Px, [23]uint8{4}},
+ Optab{ALOOP, yloop, Px, [23]uint8{0xe2}},
+ Optab{ALOOPEQ, yloop, Px, [23]uint8{0xe1}},
+ Optab{ALOOPNE, yloop, Px, [23]uint8{0xe0}},
+ Optab{ALSLL, yml_rl, Pm, [23]uint8{0x03}},
+ Optab{ALSLW, yml_rl, Pq, [23]uint8{0x03}},
+ Optab{AMASKMOVOU, yxr, Pe, [23]uint8{0xf7}},
+ Optab{AMASKMOVQ, ymr, Pm, [23]uint8{0xf7}},
+ Optab{AMAXPD, yxm, Pe, [23]uint8{0x5f}},
+ Optab{AMAXPS, yxm, Pm, [23]uint8{0x5f}},
+ Optab{AMAXSD, yxm, Pf2, [23]uint8{0x5f}},
+ Optab{AMAXSS, yxm, Pf3, [23]uint8{0x5f}},
+ Optab{AMINPD, yxm, Pe, [23]uint8{0x5d}},
+ Optab{AMINPS, yxm, Pm, [23]uint8{0x5d}},
+ Optab{AMINSD, yxm, Pf2, [23]uint8{0x5d}},
+ Optab{AMINSS, yxm, Pf3, [23]uint8{0x5d}},
+ Optab{AMOVAPD, yxmov, Pe, [23]uint8{0x28, 0x29}},
+ Optab{AMOVAPS, yxmov, Pm, [23]uint8{0x28, 0x29}},
+ Optab{AMOVB, ymovb, Pb, [23]uint8{0x88, 0x8a, 0xb0, 0xc6, 00}},
+ Optab{AMOVBLSX, ymb_rl, Pm, [23]uint8{0xbe}},
+ Optab{AMOVBLZX, ymb_rl, Pm, [23]uint8{0xb6}},
+ Optab{AMOVBQSX, ymb_rl, Pw, [23]uint8{0x0f, 0xbe}},
+ Optab{AMOVBQZX, ymb_rl, Pm, [23]uint8{0xb6}},
+ Optab{AMOVBWSX, ymb_rl, Pq, [23]uint8{0xbe}},
+ Optab{AMOVBWZX, ymb_rl, Pq, [23]uint8{0xb6}},
+ Optab{AMOVO, yxmov, Pe, [23]uint8{0x6f, 0x7f}},
+ Optab{AMOVOU, yxmov, Pf3, [23]uint8{0x6f, 0x7f}},
+ Optab{AMOVHLPS, yxr, Pm, [23]uint8{0x12}},
+ Optab{AMOVHPD, yxmov, Pe, [23]uint8{0x16, 0x17}},
+ Optab{AMOVHPS, yxmov, Pm, [23]uint8{0x16, 0x17}},
+ Optab{AMOVL, ymovl, Px, [23]uint8{0x89, 0x8b, 0x31, 0xb8, 0xc7, 00, 0x6e, 0x7e, Pe, 0x6e, Pe, 0x7e, 0}},
+ Optab{AMOVLHPS, yxr, Pm, [23]uint8{0x16}},
+ Optab{AMOVLPD, yxmov, Pe, [23]uint8{0x12, 0x13}},
+ Optab{AMOVLPS, yxmov, Pm, [23]uint8{0x12, 0x13}},
+ Optab{AMOVLQSX, yml_rl, Pw, [23]uint8{0x63}},
+ Optab{AMOVLQZX, yml_rl, Px, [23]uint8{0x8b}},
+ Optab{AMOVMSKPD, yxrrl, Pq, [23]uint8{0x50}},
+ Optab{AMOVMSKPS, yxrrl, Pm, [23]uint8{0x50}},
+ Optab{AMOVNTO, yxr_ml, Pe, [23]uint8{0xe7}},
+ Optab{AMOVNTPD, yxr_ml, Pe, [23]uint8{0x2b}},
+ Optab{AMOVNTPS, yxr_ml, Pm, [23]uint8{0x2b}},
+ Optab{AMOVNTQ, ymr_ml, Pm, [23]uint8{0xe7}},
+ Optab{AMOVQ, ymovq, Pw, [23]uint8{0x89, 0x8b, 0x31, 0xc7, 00, 0xb8, 0xc7, 00, 0x6f, 0x7f, 0x6e, 0x7e, Pf2, 0xd6, Pf3, 0x7e, Pe, 0xd6, Pe, 0x6e, Pe, 0x7e, 0}},
+ Optab{AMOVQOZX, ymrxr, Pf3, [23]uint8{0xd6, 0x7e}},
+ Optab{AMOVSB, ynone, Pb, [23]uint8{0xa4}},
+ Optab{AMOVSD, yxmov, Pf2, [23]uint8{0x10, 0x11}},
+ Optab{AMOVSL, ynone, Px, [23]uint8{0xa5}},
+ Optab{AMOVSQ, ynone, Pw, [23]uint8{0xa5}},
+ Optab{AMOVSS, yxmov, Pf3, [23]uint8{0x10, 0x11}},
+ Optab{AMOVSW, ynone, Pe, [23]uint8{0xa5}},
+ Optab{AMOVUPD, yxmov, Pe, [23]uint8{0x10, 0x11}},
+ Optab{AMOVUPS, yxmov, Pm, [23]uint8{0x10, 0x11}},
+ Optab{AMOVW, ymovw, Pe, [23]uint8{0x89, 0x8b, 0x31, 0xb8, 0xc7, 00, 0}},
+ Optab{AMOVWLSX, yml_rl, Pm, [23]uint8{0xbf}},
+ Optab{AMOVWLZX, yml_rl, Pm, [23]uint8{0xb7}},
+ Optab{AMOVWQSX, yml_rl, Pw, [23]uint8{0x0f, 0xbf}},
+ Optab{AMOVWQZX, yml_rl, Pw, [23]uint8{0x0f, 0xb7}},
+ Optab{AMULB, ydivb, Pb, [23]uint8{0xf6, 04}},
+ Optab{AMULL, ydivl, Px, [23]uint8{0xf7, 04}},
+ Optab{AMULPD, yxm, Pe, [23]uint8{0x59}},
+ Optab{AMULPS, yxm, Ym, [23]uint8{0x59}},
+ Optab{AMULQ, ydivl, Pw, [23]uint8{0xf7, 04}},
+ Optab{AMULSD, yxm, Pf2, [23]uint8{0x59}},
+ Optab{AMULSS, yxm, Pf3, [23]uint8{0x59}},
+ Optab{AMULW, ydivl, Pe, [23]uint8{0xf7, 04}},
+ Optab{ANAME, nil, 0, [23]uint8{}},
+ Optab{ANEGB, yscond, Pb, [23]uint8{0xf6, 03}},
+ Optab{ANEGL, yscond, Px, [23]uint8{0xf7, 03}},
+ Optab{ANEGQ, yscond, Pw, [23]uint8{0xf7, 03}},
+ Optab{ANEGW, yscond, Pe, [23]uint8{0xf7, 03}},
+ Optab{ANOP, ynop, Px, [23]uint8{0, 0}},
+ Optab{ANOTB, yscond, Pb, [23]uint8{0xf6, 02}},
+ Optab{ANOTL, yscond, Px, [23]uint8{0xf7, 02}},
+ Optab{ANOTQ, yscond, Pw, [23]uint8{0xf7, 02}},
+ Optab{ANOTW, yscond, Pe, [23]uint8{0xf7, 02}},
+ Optab{AORB, yxorb, Pb, [23]uint8{0x0c, 0x80, 01, 0x08, 0x0a}},
+ Optab{AORL, yxorl, Px, [23]uint8{0x83, 01, 0x0d, 0x81, 01, 0x09, 0x0b}},
+ Optab{AORPD, yxm, Pq, [23]uint8{0x56}},
+ Optab{AORPS, yxm, Pm, [23]uint8{0x56}},
+ Optab{AORQ, yxorl, Pw, [23]uint8{0x83, 01, 0x0d, 0x81, 01, 0x09, 0x0b}},
+ Optab{AORW, yxorl, Pe, [23]uint8{0x83, 01, 0x0d, 0x81, 01, 0x09, 0x0b}},
+ Optab{AOUTB, yin, Pb, [23]uint8{0xe6, 0xee}},
+ Optab{AOUTL, yin, Px, [23]uint8{0xe7, 0xef}},
+ Optab{AOUTSB, ynone, Pb, [23]uint8{0x6e}},
+ Optab{AOUTSL, ynone, Px, [23]uint8{0x6f}},
+ Optab{AOUTSW, ynone, Pe, [23]uint8{0x6f}},
+ Optab{AOUTW, yin, Pe, [23]uint8{0xe7, 0xef}},
+ Optab{APACKSSLW, ymm, Py, [23]uint8{0x6b, Pe, 0x6b}},
+ Optab{APACKSSWB, ymm, Py, [23]uint8{0x63, Pe, 0x63}},
+ Optab{APACKUSWB, ymm, Py, [23]uint8{0x67, Pe, 0x67}},
+ Optab{APADDB, ymm, Py, [23]uint8{0xfc, Pe, 0xfc}},
+ Optab{APADDL, ymm, Py, [23]uint8{0xfe, Pe, 0xfe}},
+ Optab{APADDQ, yxm, Pe, [23]uint8{0xd4}},
+ Optab{APADDSB, ymm, Py, [23]uint8{0xec, Pe, 0xec}},
+ Optab{APADDSW, ymm, Py, [23]uint8{0xed, Pe, 0xed}},
+ Optab{APADDUSB, ymm, Py, [23]uint8{0xdc, Pe, 0xdc}},
+ Optab{APADDUSW, ymm, Py, [23]uint8{0xdd, Pe, 0xdd}},
+ Optab{APADDW, ymm, Py, [23]uint8{0xfd, Pe, 0xfd}},
+ Optab{APAND, ymm, Py, [23]uint8{0xdb, Pe, 0xdb}},
+ Optab{APANDN, ymm, Py, [23]uint8{0xdf, Pe, 0xdf}},
+ Optab{APAUSE, ynone, Px, [23]uint8{0xf3, 0x90}},
+ Optab{APAVGB, ymm, Py, [23]uint8{0xe0, Pe, 0xe0}},
+ Optab{APAVGW, ymm, Py, [23]uint8{0xe3, Pe, 0xe3}},
+ Optab{APCMPEQB, ymm, Py, [23]uint8{0x74, Pe, 0x74}},
+ Optab{APCMPEQL, ymm, Py, [23]uint8{0x76, Pe, 0x76}},
+ Optab{APCMPEQW, ymm, Py, [23]uint8{0x75, Pe, 0x75}},
+ Optab{APCMPGTB, ymm, Py, [23]uint8{0x64, Pe, 0x64}},
+ Optab{APCMPGTL, ymm, Py, [23]uint8{0x66, Pe, 0x66}},
+ Optab{APCMPGTW, ymm, Py, [23]uint8{0x65, Pe, 0x65}},
+ Optab{APEXTRW, yextrw, Pq, [23]uint8{0xc5, 00}},
+ Optab{APF2IL, ymfp, Px, [23]uint8{0x1d}},
+ Optab{APF2IW, ymfp, Px, [23]uint8{0x1c}},
+ Optab{API2FL, ymfp, Px, [23]uint8{0x0d}},
+ Optab{APFACC, ymfp, Px, [23]uint8{0xae}},
+ Optab{APFADD, ymfp, Px, [23]uint8{0x9e}},
+ Optab{APFCMPEQ, ymfp, Px, [23]uint8{0xb0}},
+ Optab{APFCMPGE, ymfp, Px, [23]uint8{0x90}},
+ Optab{APFCMPGT, ymfp, Px, [23]uint8{0xa0}},
+ Optab{APFMAX, ymfp, Px, [23]uint8{0xa4}},
+ Optab{APFMIN, ymfp, Px, [23]uint8{0x94}},
+ Optab{APFMUL, ymfp, Px, [23]uint8{0xb4}},
+ Optab{APFNACC, ymfp, Px, [23]uint8{0x8a}},
+ Optab{APFPNACC, ymfp, Px, [23]uint8{0x8e}},
+ Optab{APFRCP, ymfp, Px, [23]uint8{0x96}},
+ Optab{APFRCPIT1, ymfp, Px, [23]uint8{0xa6}},
+ Optab{APFRCPI2T, ymfp, Px, [23]uint8{0xb6}},
+ Optab{APFRSQIT1, ymfp, Px, [23]uint8{0xa7}},
+ Optab{APFRSQRT, ymfp, Px, [23]uint8{0x97}},
+ Optab{APFSUB, ymfp, Px, [23]uint8{0x9a}},
+ Optab{APFSUBR, ymfp, Px, [23]uint8{0xaa}},
+ Optab{APINSRW, yinsrw, Pq, [23]uint8{0xc4, 00}},
+ Optab{APINSRD, yinsr, Pq, [23]uint8{0x3a, 0x22, 00}},
+ Optab{APINSRQ, yinsr, Pq3, [23]uint8{0x3a, 0x22, 00}},
+ Optab{APMADDWL, ymm, Py, [23]uint8{0xf5, Pe, 0xf5}},
+ Optab{APMAXSW, yxm, Pe, [23]uint8{0xee}},
+ Optab{APMAXUB, yxm, Pe, [23]uint8{0xde}},
+ Optab{APMINSW, yxm, Pe, [23]uint8{0xea}},
+ Optab{APMINUB, yxm, Pe, [23]uint8{0xda}},
+ Optab{APMOVMSKB, ymskb, Px, [23]uint8{Pe, 0xd7, 0xd7}},
+ Optab{APMULHRW, ymfp, Px, [23]uint8{0xb7}},
+ Optab{APMULHUW, ymm, Py, [23]uint8{0xe4, Pe, 0xe4}},
+ Optab{APMULHW, ymm, Py, [23]uint8{0xe5, Pe, 0xe5}},
+ Optab{APMULLW, ymm, Py, [23]uint8{0xd5, Pe, 0xd5}},
+ Optab{APMULULQ, ymm, Py, [23]uint8{0xf4, Pe, 0xf4}},
+ Optab{APOPAL, ynone, P32, [23]uint8{0x61}},
+ Optab{APOPAW, ynone, Pe, [23]uint8{0x61}},
+ Optab{APOPFL, ynone, P32, [23]uint8{0x9d}},
+ Optab{APOPFQ, ynone, Py, [23]uint8{0x9d}},
+ Optab{APOPFW, ynone, Pe, [23]uint8{0x9d}},
+ Optab{APOPL, ypopl, P32, [23]uint8{0x58, 0x8f, 00}},
+ Optab{APOPQ, ypopl, Py, [23]uint8{0x58, 0x8f, 00}},
+ Optab{APOPW, ypopl, Pe, [23]uint8{0x58, 0x8f, 00}},
+ Optab{APOR, ymm, Py, [23]uint8{0xeb, Pe, 0xeb}},
+ Optab{APSADBW, yxm, Pq, [23]uint8{0xf6}},
+ Optab{APSHUFHW, yxshuf, Pf3, [23]uint8{0x70, 00}},
+ Optab{APSHUFL, yxshuf, Pq, [23]uint8{0x70, 00}},
+ Optab{APSHUFLW, yxshuf, Pf2, [23]uint8{0x70, 00}},
+ Optab{APSHUFW, ymshuf, Pm, [23]uint8{0x70, 00}},
+ Optab{APSHUFB, ymshufb, Pq, [23]uint8{0x38, 0x00}},
+ Optab{APSLLO, ypsdq, Pq, [23]uint8{0x73, 07}},
+ Optab{APSLLL, yps, Py, [23]uint8{0xf2, 0x72, 06, Pe, 0xf2, Pe, 0x72, 06}},
+ Optab{APSLLQ, yps, Py, [23]uint8{0xf3, 0x73, 06, Pe, 0xf3, Pe, 0x73, 06}},
+ Optab{APSLLW, yps, Py, [23]uint8{0xf1, 0x71, 06, Pe, 0xf1, Pe, 0x71, 06}},
+ Optab{APSRAL, yps, Py, [23]uint8{0xe2, 0x72, 04, Pe, 0xe2, Pe, 0x72, 04}},
+ Optab{APSRAW, yps, Py, [23]uint8{0xe1, 0x71, 04, Pe, 0xe1, Pe, 0x71, 04}},
+ Optab{APSRLO, ypsdq, Pq, [23]uint8{0x73, 03}},
+ Optab{APSRLL, yps, Py, [23]uint8{0xd2, 0x72, 02, Pe, 0xd2, Pe, 0x72, 02}},
+ Optab{APSRLQ, yps, Py, [23]uint8{0xd3, 0x73, 02, Pe, 0xd3, Pe, 0x73, 02}},
+ Optab{APSRLW, yps, Py, [23]uint8{0xd1, 0x71, 02, Pe, 0xe1, Pe, 0x71, 02}},
+ Optab{APSUBB, yxm, Pe, [23]uint8{0xf8}},
+ Optab{APSUBL, yxm, Pe, [23]uint8{0xfa}},
+ Optab{APSUBQ, yxm, Pe, [23]uint8{0xfb}},
+ Optab{APSUBSB, yxm, Pe, [23]uint8{0xe8}},
+ Optab{APSUBSW, yxm, Pe, [23]uint8{0xe9}},
+ Optab{APSUBUSB, yxm, Pe, [23]uint8{0xd8}},
+ Optab{APSUBUSW, yxm, Pe, [23]uint8{0xd9}},
+ Optab{APSUBW, yxm, Pe, [23]uint8{0xf9}},
+ Optab{APSWAPL, ymfp, Px, [23]uint8{0xbb}},
+ Optab{APUNPCKHBW, ymm, Py, [23]uint8{0x68, Pe, 0x68}},
+ Optab{APUNPCKHLQ, ymm, Py, [23]uint8{0x6a, Pe, 0x6a}},
+ Optab{APUNPCKHQDQ, yxm, Pe, [23]uint8{0x6d}},
+ Optab{APUNPCKHWL, ymm, Py, [23]uint8{0x69, Pe, 0x69}},
+ Optab{APUNPCKLBW, ymm, Py, [23]uint8{0x60, Pe, 0x60}},
+ Optab{APUNPCKLLQ, ymm, Py, [23]uint8{0x62, Pe, 0x62}},
+ Optab{APUNPCKLQDQ, yxm, Pe, [23]uint8{0x6c}},
+ Optab{APUNPCKLWL, ymm, Py, [23]uint8{0x61, Pe, 0x61}},
+ Optab{APUSHAL, ynone, P32, [23]uint8{0x60}},
+ Optab{APUSHAW, ynone, Pe, [23]uint8{0x60}},
+ Optab{APUSHFL, ynone, P32, [23]uint8{0x9c}},
+ Optab{APUSHFQ, ynone, Py, [23]uint8{0x9c}},
+ Optab{APUSHFW, ynone, Pe, [23]uint8{0x9c}},
+ Optab{APUSHL, ypushl, P32, [23]uint8{0x50, 0xff, 06, 0x6a, 0x68}},
+ Optab{APUSHQ, ypushl, Py, [23]uint8{0x50, 0xff, 06, 0x6a, 0x68}},
+ Optab{APUSHW, ypushl, Pe, [23]uint8{0x50, 0xff, 06, 0x6a, 0x68}},
+ Optab{APXOR, ymm, Py, [23]uint8{0xef, Pe, 0xef}},
+ Optab{AQUAD, ybyte, Px, [23]uint8{8}},
+ Optab{ARCLB, yshb, Pb, [23]uint8{0xd0, 02, 0xc0, 02, 0xd2, 02}},
+ Optab{ARCLL, yshl, Px, [23]uint8{0xd1, 02, 0xc1, 02, 0xd3, 02, 0xd3, 02}},
+ Optab{ARCLQ, yshl, Pw, [23]uint8{0xd1, 02, 0xc1, 02, 0xd3, 02, 0xd3, 02}},
+ Optab{ARCLW, yshl, Pe, [23]uint8{0xd1, 02, 0xc1, 02, 0xd3, 02, 0xd3, 02}},
+ Optab{ARCPPS, yxm, Pm, [23]uint8{0x53}},
+ Optab{ARCPSS, yxm, Pf3, [23]uint8{0x53}},
+ Optab{ARCRB, yshb, Pb, [23]uint8{0xd0, 03, 0xc0, 03, 0xd2, 03}},
+ Optab{ARCRL, yshl, Px, [23]uint8{0xd1, 03, 0xc1, 03, 0xd3, 03, 0xd3, 03}},
+ Optab{ARCRQ, yshl, Pw, [23]uint8{0xd1, 03, 0xc1, 03, 0xd3, 03, 0xd3, 03}},
+ Optab{ARCRW, yshl, Pe, [23]uint8{0xd1, 03, 0xc1, 03, 0xd3, 03, 0xd3, 03}},
+ Optab{AREP, ynone, Px, [23]uint8{0xf3}},
+ Optab{AREPN, ynone, Px, [23]uint8{0xf2}},
+ Optab{ARET, ynone, Px, [23]uint8{0xc3}},
+ Optab{ARETFW, yret, Pe, [23]uint8{0xcb, 0xca}},
+ Optab{ARETFL, yret, Px, [23]uint8{0xcb, 0xca}},
+ Optab{ARETFQ, yret, Pw, [23]uint8{0xcb, 0xca}},
+ Optab{AROLB, yshb, Pb, [23]uint8{0xd0, 00, 0xc0, 00, 0xd2, 00}},
+ Optab{AROLL, yshl, Px, [23]uint8{0xd1, 00, 0xc1, 00, 0xd3, 00, 0xd3, 00}},
+ Optab{AROLQ, yshl, Pw, [23]uint8{0xd1, 00, 0xc1, 00, 0xd3, 00, 0xd3, 00}},
+ Optab{AROLW, yshl, Pe, [23]uint8{0xd1, 00, 0xc1, 00, 0xd3, 00, 0xd3, 00}},
+ Optab{ARORB, yshb, Pb, [23]uint8{0xd0, 01, 0xc0, 01, 0xd2, 01}},
+ Optab{ARORL, yshl, Px, [23]uint8{0xd1, 01, 0xc1, 01, 0xd3, 01, 0xd3, 01}},
+ Optab{ARORQ, yshl, Pw, [23]uint8{0xd1, 01, 0xc1, 01, 0xd3, 01, 0xd3, 01}},
+ Optab{ARORW, yshl, Pe, [23]uint8{0xd1, 01, 0xc1, 01, 0xd3, 01, 0xd3, 01}},
+ Optab{ARSQRTPS, yxm, Pm, [23]uint8{0x52}},
+ Optab{ARSQRTSS, yxm, Pf3, [23]uint8{0x52}},
+ Optab{ASAHF, ynone, Px, [23]uint8{0x86, 0xe0, 0x50, 0x9d}}, /* XCHGB AH,AL; PUSH AX; POPFL */
+ Optab{ASALB, yshb, Pb, [23]uint8{0xd0, 04, 0xc0, 04, 0xd2, 04}},
+ Optab{ASALL, yshl, Px, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+ Optab{ASALQ, yshl, Pw, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+ Optab{ASALW, yshl, Pe, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+ Optab{ASARB, yshb, Pb, [23]uint8{0xd0, 07, 0xc0, 07, 0xd2, 07}},
+ Optab{ASARL, yshl, Px, [23]uint8{0xd1, 07, 0xc1, 07, 0xd3, 07, 0xd3, 07}},
+ Optab{ASARQ, yshl, Pw, [23]uint8{0xd1, 07, 0xc1, 07, 0xd3, 07, 0xd3, 07}},
+ Optab{ASARW, yshl, Pe, [23]uint8{0xd1, 07, 0xc1, 07, 0xd3, 07, 0xd3, 07}},
+ Optab{ASBBB, yxorb, Pb, [23]uint8{0x1c, 0x80, 03, 0x18, 0x1a}},
+ Optab{ASBBL, yxorl, Px, [23]uint8{0x83, 03, 0x1d, 0x81, 03, 0x19, 0x1b}},
+ Optab{ASBBQ, yxorl, Pw, [23]uint8{0x83, 03, 0x1d, 0x81, 03, 0x19, 0x1b}},
+ Optab{ASBBW, yxorl, Pe, [23]uint8{0x83, 03, 0x1d, 0x81, 03, 0x19, 0x1b}},
+ Optab{ASCASB, ynone, Pb, [23]uint8{0xae}},
+ Optab{ASCASL, ynone, Px, [23]uint8{0xaf}},
+ Optab{ASCASQ, ynone, Pw, [23]uint8{0xaf}},
+ Optab{ASCASW, ynone, Pe, [23]uint8{0xaf}},
+ Optab{ASETCC, yscond, Pb, [23]uint8{0x0f, 0x93, 00}},
+ Optab{ASETCS, yscond, Pb, [23]uint8{0x0f, 0x92, 00}},
+ Optab{ASETEQ, yscond, Pb, [23]uint8{0x0f, 0x94, 00}},
+ Optab{ASETGE, yscond, Pb, [23]uint8{0x0f, 0x9d, 00}},
+ Optab{ASETGT, yscond, Pb, [23]uint8{0x0f, 0x9f, 00}},
+ Optab{ASETHI, yscond, Pb, [23]uint8{0x0f, 0x97, 00}},
+ Optab{ASETLE, yscond, Pb, [23]uint8{0x0f, 0x9e, 00}},
+ Optab{ASETLS, yscond, Pb, [23]uint8{0x0f, 0x96, 00}},
+ Optab{ASETLT, yscond, Pb, [23]uint8{0x0f, 0x9c, 00}},
+ Optab{ASETMI, yscond, Pb, [23]uint8{0x0f, 0x98, 00}},
+ Optab{ASETNE, yscond, Pb, [23]uint8{0x0f, 0x95, 00}},
+ Optab{ASETOC, yscond, Pb, [23]uint8{0x0f, 0x91, 00}},
+ Optab{ASETOS, yscond, Pb, [23]uint8{0x0f, 0x90, 00}},
+ Optab{ASETPC, yscond, Pb, [23]uint8{0x0f, 0x9b, 00}},
+ Optab{ASETPL, yscond, Pb, [23]uint8{0x0f, 0x99, 00}},
+ Optab{ASETPS, yscond, Pb, [23]uint8{0x0f, 0x9a, 00}},
+ Optab{ASHLB, yshb, Pb, [23]uint8{0xd0, 04, 0xc0, 04, 0xd2, 04}},
+ Optab{ASHLL, yshl, Px, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+ Optab{ASHLQ, yshl, Pw, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+ Optab{ASHLW, yshl, Pe, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+ Optab{ASHRB, yshb, Pb, [23]uint8{0xd0, 05, 0xc0, 05, 0xd2, 05}},
+ Optab{ASHRL, yshl, Px, [23]uint8{0xd1, 05, 0xc1, 05, 0xd3, 05, 0xd3, 05}},
+ Optab{ASHRQ, yshl, Pw, [23]uint8{0xd1, 05, 0xc1, 05, 0xd3, 05, 0xd3, 05}},
+ Optab{ASHRW, yshl, Pe, [23]uint8{0xd1, 05, 0xc1, 05, 0xd3, 05, 0xd3, 05}},
+ Optab{ASHUFPD, yxshuf, Pq, [23]uint8{0xc6, 00}},
+ Optab{ASHUFPS, yxshuf, Pm, [23]uint8{0xc6, 00}},
+ Optab{ASQRTPD, yxm, Pe, [23]uint8{0x51}},
+ Optab{ASQRTPS, yxm, Pm, [23]uint8{0x51}},
+ Optab{ASQRTSD, yxm, Pf2, [23]uint8{0x51}},
+ Optab{ASQRTSS, yxm, Pf3, [23]uint8{0x51}},
+ Optab{ASTC, ynone, Px, [23]uint8{0xf9}},
+ Optab{ASTD, ynone, Px, [23]uint8{0xfd}},
+ Optab{ASTI, ynone, Px, [23]uint8{0xfb}},
+ Optab{ASTMXCSR, ysvrs, Pm, [23]uint8{0xae, 03, 0xae, 03}},
+ Optab{ASTOSB, ynone, Pb, [23]uint8{0xaa}},
+ Optab{ASTOSL, ynone, Px, [23]uint8{0xab}},
+ Optab{ASTOSQ, ynone, Pw, [23]uint8{0xab}},
+ Optab{ASTOSW, ynone, Pe, [23]uint8{0xab}},
+ Optab{ASUBB, yxorb, Pb, [23]uint8{0x2c, 0x80, 05, 0x28, 0x2a}},
+ Optab{ASUBL, yaddl, Px, [23]uint8{0x83, 05, 0x2d, 0x81, 05, 0x29, 0x2b}},
+ Optab{ASUBPD, yxm, Pe, [23]uint8{0x5c}},
+ Optab{ASUBPS, yxm, Pm, [23]uint8{0x5c}},
+ Optab{ASUBQ, yaddl, Pw, [23]uint8{0x83, 05, 0x2d, 0x81, 05, 0x29, 0x2b}},
+ Optab{ASUBSD, yxm, Pf2, [23]uint8{0x5c}},
+ Optab{ASUBSS, yxm, Pf3, [23]uint8{0x5c}},
+ Optab{ASUBW, yaddl, Pe, [23]uint8{0x83, 05, 0x2d, 0x81, 05, 0x29, 0x2b}},
+ Optab{ASWAPGS, ynone, Pm, [23]uint8{0x01, 0xf8}},
+ Optab{ASYSCALL, ynone, Px, [23]uint8{0x0f, 0x05}}, /* fast syscall */
+ Optab{ATESTB, ytestb, Pb, [23]uint8{0xa8, 0xf6, 00, 0x84, 0x84}},
+ Optab{ATESTL, ytestl, Px, [23]uint8{0xa9, 0xf7, 00, 0x85, 0x85}},
+ Optab{ATESTQ, ytestl, Pw, [23]uint8{0xa9, 0xf7, 00, 0x85, 0x85}},
+ Optab{ATESTW, ytestl, Pe, [23]uint8{0xa9, 0xf7, 00, 0x85, 0x85}},
+ Optab{ATEXT, ytext, Px, [23]uint8{}},
+ Optab{AUCOMISD, yxcmp, Pe, [23]uint8{0x2e}},
+ Optab{AUCOMISS, yxcmp, Pm, [23]uint8{0x2e}},
+ Optab{AUNPCKHPD, yxm, Pe, [23]uint8{0x15}},
+ Optab{AUNPCKHPS, yxm, Pm, [23]uint8{0x15}},
+ Optab{AUNPCKLPD, yxm, Pe, [23]uint8{0x14}},
+ Optab{AUNPCKLPS, yxm, Pm, [23]uint8{0x14}},
+ Optab{AVERR, ydivl, Pm, [23]uint8{0x00, 04}},
+ Optab{AVERW, ydivl, Pm, [23]uint8{0x00, 05}},
+ Optab{AWAIT, ynone, Px, [23]uint8{0x9b}},
+ Optab{AWORD, ybyte, Px, [23]uint8{2}},
+ Optab{AXCHGB, yml_mb, Pb, [23]uint8{0x86, 0x86}},
+ Optab{AXCHGL, yxchg, Px, [23]uint8{0x90, 0x90, 0x87, 0x87}},
+ Optab{AXCHGQ, yxchg, Pw, [23]uint8{0x90, 0x90, 0x87, 0x87}},
+ Optab{AXCHGW, yxchg, Pe, [23]uint8{0x90, 0x90, 0x87, 0x87}},
+ Optab{AXLAT, ynone, Px, [23]uint8{0xd7}},
+ Optab{AXORB, yxorb, Pb, [23]uint8{0x34, 0x80, 06, 0x30, 0x32}},
+ Optab{AXORL, yxorl, Px, [23]uint8{0x83, 06, 0x35, 0x81, 06, 0x31, 0x33}},
+ Optab{AXORPD, yxm, Pe, [23]uint8{0x57}},
+ Optab{AXORPS, yxm, Pm, [23]uint8{0x57}},
+ Optab{AXORQ, yxorl, Pw, [23]uint8{0x83, 06, 0x35, 0x81, 06, 0x31, 0x33}},
+ Optab{AXORW, yxorl, Pe, [23]uint8{0x83, 06, 0x35, 0x81, 06, 0x31, 0x33}},
+ Optab{AFMOVB, yfmvx, Px, [23]uint8{0xdf, 04}},
+ Optab{AFMOVBP, yfmvp, Px, [23]uint8{0xdf, 06}},
+ Optab{AFMOVD, yfmvd, Px, [23]uint8{0xdd, 00, 0xdd, 02, 0xd9, 00, 0xdd, 02}},
+ Optab{AFMOVDP, yfmvdp, Px, [23]uint8{0xdd, 03, 0xdd, 03}},
+ Optab{AFMOVF, yfmvf, Px, [23]uint8{0xd9, 00, 0xd9, 02}},
+ Optab{AFMOVFP, yfmvp, Px, [23]uint8{0xd9, 03}},
+ Optab{AFMOVL, yfmvf, Px, [23]uint8{0xdb, 00, 0xdb, 02}},
+ Optab{AFMOVLP, yfmvp, Px, [23]uint8{0xdb, 03}},
+ Optab{AFMOVV, yfmvx, Px, [23]uint8{0xdf, 05}},
+ Optab{AFMOVVP, yfmvp, Px, [23]uint8{0xdf, 07}},
+ Optab{AFMOVW, yfmvf, Px, [23]uint8{0xdf, 00, 0xdf, 02}},
+ Optab{AFMOVWP, yfmvp, Px, [23]uint8{0xdf, 03}},
+ Optab{AFMOVX, yfmvx, Px, [23]uint8{0xdb, 05}},
+ Optab{AFMOVXP, yfmvp, Px, [23]uint8{0xdb, 07}},
+ Optab{AFCOMB, nil, 0, [23]uint8{}},
+ Optab{AFCOMBP, nil, 0, [23]uint8{}},
+ Optab{AFCOMD, yfadd, Px, [23]uint8{0xdc, 02, 0xd8, 02, 0xdc, 02}}, /* botch */
+ Optab{AFCOMDP, yfadd, Px, [23]uint8{0xdc, 03, 0xd8, 03, 0xdc, 03}}, /* botch */
+ Optab{AFCOMDPP, ycompp, Px, [23]uint8{0xde, 03}},
+ Optab{AFCOMF, yfmvx, Px, [23]uint8{0xd8, 02}},
+ Optab{AFCOMFP, yfmvx, Px, [23]uint8{0xd8, 03}},
+ Optab{AFCOML, yfmvx, Px, [23]uint8{0xda, 02}},
+ Optab{AFCOMLP, yfmvx, Px, [23]uint8{0xda, 03}},
+ Optab{AFCOMW, yfmvx, Px, [23]uint8{0xde, 02}},
+ Optab{AFCOMWP, yfmvx, Px, [23]uint8{0xde, 03}},
+ Optab{AFUCOM, ycompp, Px, [23]uint8{0xdd, 04}},
+ Optab{AFUCOMP, ycompp, Px, [23]uint8{0xdd, 05}},
+ Optab{AFUCOMPP, ycompp, Px, [23]uint8{0xda, 13}},
+ Optab{AFADDDP, yfaddp, Px, [23]uint8{0xde, 00}},
+ Optab{AFADDW, yfmvx, Px, [23]uint8{0xde, 00}},
+ Optab{AFADDL, yfmvx, Px, [23]uint8{0xda, 00}},
+ Optab{AFADDF, yfmvx, Px, [23]uint8{0xd8, 00}},
+ Optab{AFADDD, yfadd, Px, [23]uint8{0xdc, 00, 0xd8, 00, 0xdc, 00}},
+ Optab{AFMULDP, yfaddp, Px, [23]uint8{0xde, 01}},
+ Optab{AFMULW, yfmvx, Px, [23]uint8{0xde, 01}},
+ Optab{AFMULL, yfmvx, Px, [23]uint8{0xda, 01}},
+ Optab{AFMULF, yfmvx, Px, [23]uint8{0xd8, 01}},
+ Optab{AFMULD, yfadd, Px, [23]uint8{0xdc, 01, 0xd8, 01, 0xdc, 01}},
+ Optab{AFSUBDP, yfaddp, Px, [23]uint8{0xde, 05}},
+ Optab{AFSUBW, yfmvx, Px, [23]uint8{0xde, 04}},
+ Optab{AFSUBL, yfmvx, Px, [23]uint8{0xda, 04}},
+ Optab{AFSUBF, yfmvx, Px, [23]uint8{0xd8, 04}},
+ Optab{AFSUBD, yfadd, Px, [23]uint8{0xdc, 04, 0xd8, 04, 0xdc, 05}},
+ Optab{AFSUBRDP, yfaddp, Px, [23]uint8{0xde, 04}},
+ Optab{AFSUBRW, yfmvx, Px, [23]uint8{0xde, 05}},
+ Optab{AFSUBRL, yfmvx, Px, [23]uint8{0xda, 05}},
+ Optab{AFSUBRF, yfmvx, Px, [23]uint8{0xd8, 05}},
+ Optab{AFSUBRD, yfadd, Px, [23]uint8{0xdc, 05, 0xd8, 05, 0xdc, 04}},
+ Optab{AFDIVDP, yfaddp, Px, [23]uint8{0xde, 07}},
+ Optab{AFDIVW, yfmvx, Px, [23]uint8{0xde, 06}},
+ Optab{AFDIVL, yfmvx, Px, [23]uint8{0xda, 06}},
+ Optab{AFDIVF, yfmvx, Px, [23]uint8{0xd8, 06}},
+ Optab{AFDIVD, yfadd, Px, [23]uint8{0xdc, 06, 0xd8, 06, 0xdc, 07}},
+ Optab{AFDIVRDP, yfaddp, Px, [23]uint8{0xde, 06}},
+ Optab{AFDIVRW, yfmvx, Px, [23]uint8{0xde, 07}},
+ Optab{AFDIVRL, yfmvx, Px, [23]uint8{0xda, 07}},
+ Optab{AFDIVRF, yfmvx, Px, [23]uint8{0xd8, 07}},
+ Optab{AFDIVRD, yfadd, Px, [23]uint8{0xdc, 07, 0xd8, 07, 0xdc, 06}},
+ Optab{AFXCHD, yfxch, Px, [23]uint8{0xd9, 01, 0xd9, 01}},
+ Optab{AFFREE, nil, 0, [23]uint8{}},
+ Optab{AFLDCW, ystcw, Px, [23]uint8{0xd9, 05, 0xd9, 05}},
+ Optab{AFLDENV, ystcw, Px, [23]uint8{0xd9, 04, 0xd9, 04}},
+ Optab{AFRSTOR, ysvrs, Px, [23]uint8{0xdd, 04, 0xdd, 04}},
+ Optab{AFSAVE, ysvrs, Px, [23]uint8{0xdd, 06, 0xdd, 06}},
+ Optab{AFSTCW, ystcw, Px, [23]uint8{0xd9, 07, 0xd9, 07}},
+ Optab{AFSTENV, ystcw, Px, [23]uint8{0xd9, 06, 0xd9, 06}},
+ Optab{AFSTSW, ystsw, Px, [23]uint8{0xdd, 07, 0xdf, 0xe0}},
+ Optab{AF2XM1, ynone, Px, [23]uint8{0xd9, 0xf0}},
+ Optab{AFABS, ynone, Px, [23]uint8{0xd9, 0xe1}},
+ Optab{AFCHS, ynone, Px, [23]uint8{0xd9, 0xe0}},
+ Optab{AFCLEX, ynone, Px, [23]uint8{0xdb, 0xe2}},
+ Optab{AFCOS, ynone, Px, [23]uint8{0xd9, 0xff}},
+ Optab{AFDECSTP, ynone, Px, [23]uint8{0xd9, 0xf6}},
+ Optab{AFINCSTP, ynone, Px, [23]uint8{0xd9, 0xf7}},
+ Optab{AFINIT, ynone, Px, [23]uint8{0xdb, 0xe3}},
+ Optab{AFLD1, ynone, Px, [23]uint8{0xd9, 0xe8}},
+ Optab{AFLDL2E, ynone, Px, [23]uint8{0xd9, 0xea}},
+ Optab{AFLDL2T, ynone, Px, [23]uint8{0xd9, 0xe9}},
+ Optab{AFLDLG2, ynone, Px, [23]uint8{0xd9, 0xec}},
+ Optab{AFLDLN2, ynone, Px, [23]uint8{0xd9, 0xed}},
+ Optab{AFLDPI, ynone, Px, [23]uint8{0xd9, 0xeb}},
+ Optab{AFLDZ, ynone, Px, [23]uint8{0xd9, 0xee}},
+ Optab{AFNOP, ynone, Px, [23]uint8{0xd9, 0xd0}},
+ Optab{AFPATAN, ynone, Px, [23]uint8{0xd9, 0xf3}},
+ Optab{AFPREM, ynone, Px, [23]uint8{0xd9, 0xf8}},
+ Optab{AFPREM1, ynone, Px, [23]uint8{0xd9, 0xf5}},
+ Optab{AFPTAN, ynone, Px, [23]uint8{0xd9, 0xf2}},
+ Optab{AFRNDINT, ynone, Px, [23]uint8{0xd9, 0xfc}},
+ Optab{AFSCALE, ynone, Px, [23]uint8{0xd9, 0xfd}},
+ Optab{AFSIN, ynone, Px, [23]uint8{0xd9, 0xfe}},
+ Optab{AFSINCOS, ynone, Px, [23]uint8{0xd9, 0xfb}},
+ Optab{AFSQRT, ynone, Px, [23]uint8{0xd9, 0xfa}},
+ Optab{AFTST, ynone, Px, [23]uint8{0xd9, 0xe4}},
+ Optab{AFXAM, ynone, Px, [23]uint8{0xd9, 0xe5}},
+ Optab{AFXTRACT, ynone, Px, [23]uint8{0xd9, 0xf4}},
+ Optab{AFYL2X, ynone, Px, [23]uint8{0xd9, 0xf1}},
+ Optab{AFYL2XP1, ynone, Px, [23]uint8{0xd9, 0xf9}},
+ Optab{ACMPXCHGB, yrb_mb, Pb, [23]uint8{0x0f, 0xb0}},
+ Optab{ACMPXCHGL, yrl_ml, Px, [23]uint8{0x0f, 0xb1}},
+ Optab{ACMPXCHGW, yrl_ml, Pe, [23]uint8{0x0f, 0xb1}},
+ Optab{ACMPXCHGQ, yrl_ml, Pw, [23]uint8{0x0f, 0xb1}},
+ Optab{ACMPXCHG8B, yscond, Pm, [23]uint8{0xc7, 01}},
+ Optab{AINVD, ynone, Pm, [23]uint8{0x08}},
+ Optab{AINVLPG, ymbs, Pm, [23]uint8{0x01, 07}},
+ Optab{ALFENCE, ynone, Pm, [23]uint8{0xae, 0xe8}},
+ Optab{AMFENCE, ynone, Pm, [23]uint8{0xae, 0xf0}},
+ Optab{AMOVNTIL, yrl_ml, Pm, [23]uint8{0xc3}},
+ Optab{AMOVNTIQ, yrl_ml, Pw, [23]uint8{0x0f, 0xc3}},
+ Optab{ARDMSR, ynone, Pm, [23]uint8{0x32}},
+ Optab{ARDPMC, ynone, Pm, [23]uint8{0x33}},
+ Optab{ARDTSC, ynone, Pm, [23]uint8{0x31}},
+ Optab{ARSM, ynone, Pm, [23]uint8{0xaa}},
+ Optab{ASFENCE, ynone, Pm, [23]uint8{0xae, 0xf8}},
+ Optab{ASYSRET, ynone, Pm, [23]uint8{0x07}},
+ Optab{AWBINVD, ynone, Pm, [23]uint8{0x09}},
+ Optab{AWRMSR, ynone, Pm, [23]uint8{0x30}},
+ Optab{AXADDB, yrb_mb, Pb, [23]uint8{0x0f, 0xc0}},
+ Optab{AXADDL, yrl_ml, Px, [23]uint8{0x0f, 0xc1}},
+ Optab{AXADDQ, yrl_ml, Pw, [23]uint8{0x0f, 0xc1}},
+ Optab{AXADDW, yrl_ml, Pe, [23]uint8{0x0f, 0xc1}},
+ Optab{ACRC32B, ycrc32l, Px, [23]uint8{0xf2, 0x0f, 0x38, 0xf0, 0}},
+ Optab{ACRC32Q, ycrc32l, Pw, [23]uint8{0xf2, 0x0f, 0x38, 0xf1, 0}},
+ Optab{APREFETCHT0, yprefetch, Pm, [23]uint8{0x18, 01}},
+ Optab{APREFETCHT1, yprefetch, Pm, [23]uint8{0x18, 02}},
+ Optab{APREFETCHT2, yprefetch, Pm, [23]uint8{0x18, 03}},
+ Optab{APREFETCHNTA, yprefetch, Pm, [23]uint8{0x18, 00}},
+ Optab{AMOVQL, yrl_ml, Px, [23]uint8{0x89}},
+ Optab{AUNDEF, ynone, Px, [23]uint8{0x0f, 0x0b}},
+ Optab{AAESENC, yaes, Pq, [23]uint8{0x38, 0xdc, 0}},
+ Optab{AAESENCLAST, yaes, Pq, [23]uint8{0x38, 0xdd, 0}},
+ Optab{AAESDEC, yaes, Pq, [23]uint8{0x38, 0xde, 0}},
+ Optab{AAESDECLAST, yaes, Pq, [23]uint8{0x38, 0xdf, 0}},
+ Optab{AAESIMC, yaes, Pq, [23]uint8{0x38, 0xdb, 0}},
+ Optab{AAESKEYGENASSIST, yaes2, Pq, [23]uint8{0x3a, 0xdf, 0}},
+ Optab{APSHUFD, yaes2, Pq, [23]uint8{0x70, 0}},
+ Optab{APCLMULQDQ, yxshuf, Pq, [23]uint8{0x3a, 0x44, 0}},
+ Optab{AUSEFIELD, ynop, Px, [23]uint8{0, 0}},
+ Optab{ATYPE, nil, 0, [23]uint8{}},
+ Optab{AFUNCDATA, yfuncdata, Px, [23]uint8{0, 0}},
+ Optab{APCDATA, ypcdata, Px, [23]uint8{0, 0}},
+ Optab{ACHECKNIL, nil, 0, [23]uint8{}},
+ Optab{AVARDEF, nil, 0, [23]uint8{}},
+ Optab{AVARKILL, nil, 0, [23]uint8{}},
+ Optab{ADUFFCOPY, yduff, Px, [23]uint8{0xe8}},
+ Optab{ADUFFZERO, yduff, Px, [23]uint8{0xe8}},
+ Optab{AEND, nil, 0, [23]uint8{}},
+ Optab{0, nil, 0, [23]uint8{}},
+}
+
+var opindex [ALAST + 1]*Optab
+
+// isextern reports whether s describes an external symbol that must avoid pc-relative addressing.
+// This happens on systems like Solaris that call .so functions instead of system calls.
+// It does not seem to be necessary for any other systems. This is probably working
+// around a Solaris-specific bug that should be fixed differently, but we don't know
+// what that bug is. And this does fix it.
+func isextern(s *obj.LSym) int {
+
+ // All the Solaris dynamic imports from libc.so begin with "libc_".
+ return bool2int(strings.HasPrefix(s.Name, "libc_"))
+}
+
+// single-instruction no-ops of various lengths.
+// constructed by hand and disassembled with gdb to verify.
+// see http://www.agner.org/optimize/optimizing_assembly.pdf for discussion.
+var nop = [][16]uint8{
+ [16]uint8{0x90},
+ [16]uint8{0x66, 0x90},
+ [16]uint8{0x0F, 0x1F, 0x00},
+ [16]uint8{0x0F, 0x1F, 0x40, 0x00},
+ [16]uint8{0x0F, 0x1F, 0x44, 0x00, 0x00},
+ [16]uint8{0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00},
+ [16]uint8{0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00},
+ [16]uint8{0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+ [16]uint8{0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+}
+
+// Native Client rejects the repeated 0x66 prefix.
+// {0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+func fillnop(p []byte, n int) {
+
+ var m int
+
+ for n > 0 {
+ m = n
+ if m > len(nop) {
+ m = len(nop)
+ }
+ copy(p[:m], nop[m-1][:m])
+ p = p[m:]
+ n -= m
+ }
+}
+
+func naclpad(ctxt *obj.Link, s *obj.LSym, c int32, pad int32) int32 {
+ obj.Symgrow(ctxt, s, int64(c)+int64(pad))
+ fillnop(s.P[c:], int(pad))
+ return c + pad
+}
+
+func spadjop(ctxt *obj.Link, p *obj.Prog, l int, q int) int {
+ if p.Mode != 64 || ctxt.Arch.Ptrsize == 4 {
+ return l
+ }
+ return q
+}
+
+func span6(ctxt *obj.Link, s *obj.LSym) {
+ var p *obj.Prog
+ var q *obj.Prog
+ var c int32
+ var v int32
+ var loop int32
+ var bp []byte
+ var n int
+ var m int
+ var i int
+
+ ctxt.Cursym = s
+
+ if s.P != nil {
+ return
+ }
+
+ if ycover[0] == 0 {
+ instinit()
+ }
+
+ for p = ctxt.Cursym.Text; p != nil; p = p.Link {
+ n = 0
+ if p.To.Type == D_BRANCH {
+ if p.Pcond == nil {
+ p.Pcond = p
+ }
+ }
+ q = p.Pcond
+ if q != nil {
+ if q.Back != 2 {
+ n = 1
+ }
+ }
+ p.Back = uint8(n)
+ if p.As == AADJSP {
+ p.To.Type = D_SP
+ v = int32(-p.From.Offset)
+ p.From.Offset = int64(v)
+ p.As = int16(spadjop(ctxt, p, AADDL, AADDQ))
+ if v < 0 {
+ p.As = int16(spadjop(ctxt, p, ASUBL, ASUBQ))
+ v = -v
+ p.From.Offset = int64(v)
+ }
+
+ if v == 0 {
+ p.As = ANOP
+ }
+ }
+ }
+
+ for p = s.Text; p != nil; p = p.Link {
+ p.Back = 2 // use short branches first time through
+ q = p.Pcond
+ if q != nil && (q.Back&2 != 0) {
+ p.Back |= 1 // backward jump
+ q.Back |= 4 // loop head
+ }
+
+ if p.As == AADJSP {
+ p.To.Type = D_SP
+ v = int32(-p.From.Offset)
+ p.From.Offset = int64(v)
+ p.As = int16(spadjop(ctxt, p, AADDL, AADDQ))
+ if v < 0 {
+ p.As = int16(spadjop(ctxt, p, ASUBL, ASUBQ))
+ v = -v
+ p.From.Offset = int64(v)
+ }
+
+ if v == 0 {
+ p.As = ANOP
+ }
+ }
+ }
+
+ n = 0
+ for {
+ loop = 0
+ for i = 0; i < len(s.R); i++ {
+ s.R[i] = obj.Reloc{}
+ }
+ s.R = s.R[:0]
+ s.P = s.P[:0]
+ c = 0
+ for p = s.Text; p != nil; p = p.Link {
+ if ctxt.Headtype == obj.Hnacl && p.Isize > 0 {
+ var deferreturn *obj.LSym
+
+ if deferreturn == nil {
+ deferreturn = obj.Linklookup(ctxt, "runtime.deferreturn", 0)
+ }
+
+ // pad everything to avoid crossing 32-byte boundary
+ if c>>5 != (c+int32(p.Isize)-1)>>5 {
+
+ c = naclpad(ctxt, s, c, -c&31)
+ }
+
+ // pad call deferreturn to start at 32-byte boundary
+ // so that subtracting 5 in jmpdefer will jump back
+ // to that boundary and rerun the call.
+ if p.As == ACALL && p.To.Sym == deferreturn {
+
+ c = naclpad(ctxt, s, c, -c&31)
+ }
+
+ // pad call to end at 32-byte boundary
+ if p.As == ACALL {
+
+ c = naclpad(ctxt, s, c, -(c+int32(p.Isize))&31)
+ }
+
+ // the linker treats REP and STOSQ as different instructions
+ // but in fact the REP is a prefix on the STOSQ.
+ // make sure REP has room for 2 more bytes, so that
+ // padding will not be inserted before the next instruction.
+ if (p.As == AREP || p.As == AREPN) && c>>5 != (c+3-1)>>5 {
+
+ c = naclpad(ctxt, s, c, -c&31)
+ }
+
+ // same for LOCK.
+ // various instructions follow; the longest is 4 bytes.
+ // give ourselves 8 bytes so as to avoid surprises.
+ if p.As == ALOCK && c>>5 != (c+8-1)>>5 {
+
+ c = naclpad(ctxt, s, c, -c&31)
+ }
+ }
+
+ if (p.Back&4 != 0) && c&(LoopAlign-1) != 0 {
+ // pad with NOPs
+ v = -c & (LoopAlign - 1)
+
+ if v <= MaxLoopPad {
+ obj.Symgrow(ctxt, s, int64(c)+int64(v))
+ fillnop(s.P[c:], int(v))
+ c += v
+ }
+ }
+
+ p.Pc = int64(c)
+
+ // process forward jumps to p
+ for q = p.Comefrom; q != nil; q = q.Forwd {
+
+ v = int32(p.Pc - (q.Pc + int64(q.Mark)))
+ if q.Back&2 != 0 { // short
+ if v > 127 {
+ loop++
+ q.Back ^= 2
+ }
+
+ if q.As == AJCXZL {
+ s.P[q.Pc+2] = byte(v)
+ } else {
+
+ s.P[q.Pc+1] = byte(v)
+ }
+ } else {
+
+ bp = s.P[q.Pc+int64(q.Mark)-4:]
+ bp[0] = byte(v)
+ bp = bp[1:]
+ bp[0] = byte(v >> 8)
+ bp = bp[1:]
+ bp[0] = byte(v >> 16)
+ bp = bp[1:]
+ bp[0] = byte(v >> 24)
+ }
+ }
+
+ p.Comefrom = nil
+
+ p.Pc = int64(c)
+ asmins(ctxt, p)
+ m = -cap(ctxt.Andptr) + cap(ctxt.And[:])
+ if int(p.Isize) != m {
+ p.Isize = uint8(m)
+ loop++
+ }
+
+ obj.Symgrow(ctxt, s, p.Pc+int64(m))
+ copy(s.P[p.Pc:][:m], ctxt.And[:m])
+ p.Mark = uint16(m)
+ c += int32(m)
+ }
+
+ n++
+ if n > 20 {
+ ctxt.Diag("span must be looping")
+ log.Fatalf("loop")
+ }
+ if !(loop != 0) {
+ break
+ }
+ }
+
+ if ctxt.Headtype == obj.Hnacl {
+ c = naclpad(ctxt, s, c, -c&31)
+ }
+
+ c += -c & (FuncAlign - 1)
+ s.Size = int64(c)
+
+ if false { /* debug['a'] > 1 */
+ fmt.Printf("span1 %s %d (%d tries)\n %.6x", s.Name, s.Size, n, 0)
+ for i = 0; i < len(s.P); i++ {
+ fmt.Printf(" %.2x", s.P[i])
+ if i%16 == 15 {
+ fmt.Printf("\n %.6x", uint(i+1))
+ }
+ }
+
+ if i%16 != 0 {
+ fmt.Printf("\n")
+ }
+
+ for i = 0; i < len(s.R); i++ {
+ var r *obj.Reloc
+
+ r = &s.R[i]
+ fmt.Printf(" rel %#.4x/%d %s%+d\n", uint32(r.Off), r.Siz, r.Sym.Name, r.Add)
+ }
+ }
+}
+
+func instinit() {
+ var c int
+ var i int
+
+ for i = 1; optab[i].as != 0; i++ {
+ c = int(optab[i].as)
+ if opindex[c] != nil {
+ log.Fatalf("phase error in optab: %d (%v)", i, Aconv(c))
+ }
+ opindex[c] = &optab[i]
+ }
+
+ for i = 0; i < Ymax; i++ {
+ ycover[i*Ymax+i] = 1
+ }
+
+ ycover[Yi0*Ymax+Yi8] = 1
+ ycover[Yi1*Ymax+Yi8] = 1
+
+ ycover[Yi0*Ymax+Ys32] = 1
+ ycover[Yi1*Ymax+Ys32] = 1
+ ycover[Yi8*Ymax+Ys32] = 1
+
+ ycover[Yi0*Ymax+Yi32] = 1
+ ycover[Yi1*Ymax+Yi32] = 1
+ ycover[Yi8*Ymax+Yi32] = 1
+ ycover[Ys32*Ymax+Yi32] = 1
+
+ ycover[Yi0*Ymax+Yi64] = 1
+ ycover[Yi1*Ymax+Yi64] = 1
+ ycover[Yi8*Ymax+Yi64] = 1
+ ycover[Ys32*Ymax+Yi64] = 1
+ ycover[Yi32*Ymax+Yi64] = 1
+
+ ycover[Yal*Ymax+Yrb] = 1
+ ycover[Ycl*Ymax+Yrb] = 1
+ ycover[Yax*Ymax+Yrb] = 1
+ ycover[Ycx*Ymax+Yrb] = 1
+ ycover[Yrx*Ymax+Yrb] = 1
+ ycover[Yrl*Ymax+Yrb] = 1
+
+ ycover[Ycl*Ymax+Ycx] = 1
+
+ ycover[Yax*Ymax+Yrx] = 1
+ ycover[Ycx*Ymax+Yrx] = 1
+
+ ycover[Yax*Ymax+Yrl] = 1
+ ycover[Ycx*Ymax+Yrl] = 1
+ ycover[Yrx*Ymax+Yrl] = 1
+
+ ycover[Yf0*Ymax+Yrf] = 1
+
+ ycover[Yal*Ymax+Ymb] = 1
+ ycover[Ycl*Ymax+Ymb] = 1
+ ycover[Yax*Ymax+Ymb] = 1
+ ycover[Ycx*Ymax+Ymb] = 1
+ ycover[Yrx*Ymax+Ymb] = 1
+ ycover[Yrb*Ymax+Ymb] = 1
+ ycover[Yrl*Ymax+Ymb] = 1
+ ycover[Ym*Ymax+Ymb] = 1
+
+ ycover[Yax*Ymax+Yml] = 1
+ ycover[Ycx*Ymax+Yml] = 1
+ ycover[Yrx*Ymax+Yml] = 1
+ ycover[Yrl*Ymax+Yml] = 1
+ ycover[Ym*Ymax+Yml] = 1
+
+ ycover[Yax*Ymax+Ymm] = 1
+ ycover[Ycx*Ymax+Ymm] = 1
+ ycover[Yrx*Ymax+Ymm] = 1
+ ycover[Yrl*Ymax+Ymm] = 1
+ ycover[Ym*Ymax+Ymm] = 1
+ ycover[Ymr*Ymax+Ymm] = 1
+
+ ycover[Ym*Ymax+Yxm] = 1
+ ycover[Yxr*Ymax+Yxm] = 1
+
+ for i = 0; i < D_NONE; i++ {
+ reg[i] = -1
+ if i >= D_AL && i <= D_R15B {
+ reg[i] = (i - D_AL) & 7
+ if i >= D_SPB && i <= D_DIB {
+ regrex[i] = 0x40
+ }
+ if i >= D_R8B && i <= D_R15B {
+ regrex[i] = Rxr | Rxx | Rxb
+ }
+ }
+
+ if i >= D_AH && i <= D_BH {
+ reg[i] = 4 + ((i - D_AH) & 7)
+ }
+ if i >= D_AX && i <= D_R15 {
+ reg[i] = (i - D_AX) & 7
+ if i >= D_R8 {
+ regrex[i] = Rxr | Rxx | Rxb
+ }
+ }
+
+ if i >= D_F0 && i <= D_F0+7 {
+ reg[i] = (i - D_F0) & 7
+ }
+ if i >= D_M0 && i <= D_M0+7 {
+ reg[i] = (i - D_M0) & 7
+ }
+ if i >= D_X0 && i <= D_X0+15 {
+ reg[i] = (i - D_X0) & 7
+ if i >= D_X0+8 {
+ regrex[i] = Rxr | Rxx | Rxb
+ }
+ }
+
+ if i >= D_CR+8 && i <= D_CR+15 {
+ regrex[i] = Rxr
+ }
+ }
+}
+
+func prefixof(ctxt *obj.Link, a *obj.Addr) int {
+ switch a.Type {
+ case D_INDIR + D_CS:
+ return 0x2e
+
+ case D_INDIR + D_DS:
+ return 0x3e
+
+ case D_INDIR + D_ES:
+ return 0x26
+
+ case D_INDIR + D_FS:
+ return 0x64
+
+ case D_INDIR + D_GS:
+ return 0x65
+
+ // NOTE: Systems listed here should be only systems that
+ // support direct TLS references like 8(TLS) implemented as
+ // direct references from FS or GS. Systems that require
+ // the initial-exec model, where you load the TLS base into
+ // a register and then index from that register, do not reach
+ // this code and should not be listed.
+ case D_INDIR + D_TLS:
+ switch ctxt.Headtype {
+
+ default:
+ log.Fatalf("unknown TLS base register for %s", obj.Headstr(ctxt.Headtype))
+
+ case obj.Hdragonfly,
+ obj.Hfreebsd,
+ obj.Hlinux,
+ obj.Hnetbsd,
+ obj.Hopenbsd,
+ obj.Hsolaris:
+ return 0x64 // FS
+
+ case obj.Hdarwin:
+ return 0x65 // GS
+ }
+ }
+
+ switch a.Index {
+ case D_CS:
+ return 0x2e
+
+ case D_DS:
+ return 0x3e
+
+ case D_ES:
+ return 0x26
+
+ case D_FS:
+ return 0x64
+
+ case D_GS:
+ return 0x65
+ }
+
+ return 0
+}
+
+func oclass(ctxt *obj.Link, a *obj.Addr) int {
+ var v int64
+ var l int32
+
+ if a.Type >= D_INDIR || a.Index != D_NONE {
+ if a.Index != D_NONE && a.Scale == 0 {
+ if a.Type == D_ADDR {
+ switch a.Index {
+ case D_EXTERN,
+ D_STATIC:
+ if a.Sym != nil && isextern(a.Sym) != 0 {
+ return Yi32
+ }
+ return Yiauto // use pc-relative addressing
+
+ case D_AUTO,
+ D_PARAM:
+ return Yiauto
+ }
+
+ return Yxxx
+ }
+
+ return Ycol
+ }
+
+ return Ym
+ }
+
+ switch a.Type {
+ case D_AL:
+ return Yal
+
+ case D_AX:
+ return Yax
+
+ /*
+ case D_SPB:
+ */
+ case D_BPB,
+ D_SIB,
+ D_DIB,
+ D_R8B,
+ D_R9B,
+ D_R10B,
+ D_R11B,
+ D_R12B,
+ D_R13B,
+ D_R14B,
+ D_R15B:
+ if ctxt.Asmode != 64 {
+
+ return Yxxx
+ }
+ fallthrough
+
+ case D_DL,
+ D_BL,
+ D_AH,
+ D_CH,
+ D_DH,
+ D_BH:
+ return Yrb
+
+ case D_CL:
+ return Ycl
+
+ case D_CX:
+ return Ycx
+
+ case D_DX,
+ D_BX:
+ return Yrx
+
+ case D_R8, /* not really Yrl */
+ D_R9,
+ D_R10,
+ D_R11,
+ D_R12,
+ D_R13,
+ D_R14,
+ D_R15:
+ if ctxt.Asmode != 64 {
+
+ return Yxxx
+ }
+ fallthrough
+
+ case D_SP,
+ D_BP,
+ D_SI,
+ D_DI:
+ return Yrl
+
+ case D_F0 + 0:
+ return Yf0
+
+ case D_F0 + 1,
+ D_F0 + 2,
+ D_F0 + 3,
+ D_F0 + 4,
+ D_F0 + 5,
+ D_F0 + 6,
+ D_F0 + 7:
+ return Yrf
+
+ case D_M0 + 0,
+ D_M0 + 1,
+ D_M0 + 2,
+ D_M0 + 3,
+ D_M0 + 4,
+ D_M0 + 5,
+ D_M0 + 6,
+ D_M0 + 7:
+ return Ymr
+
+ case D_X0 + 0,
+ D_X0 + 1,
+ D_X0 + 2,
+ D_X0 + 3,
+ D_X0 + 4,
+ D_X0 + 5,
+ D_X0 + 6,
+ D_X0 + 7,
+ D_X0 + 8,
+ D_X0 + 9,
+ D_X0 + 10,
+ D_X0 + 11,
+ D_X0 + 12,
+ D_X0 + 13,
+ D_X0 + 14,
+ D_X0 + 15:
+ return Yxr
+
+ case D_NONE:
+ return Ynone
+
+ case D_CS:
+ return Ycs
+ case D_SS:
+ return Yss
+ case D_DS:
+ return Yds
+ case D_ES:
+ return Yes
+ case D_FS:
+ return Yfs
+ case D_GS:
+ return Ygs
+ case D_TLS:
+ return Ytls
+
+ case D_GDTR:
+ return Ygdtr
+ case D_IDTR:
+ return Yidtr
+ case D_LDTR:
+ return Yldtr
+ case D_MSW:
+ return Ymsw
+ case D_TASK:
+ return Ytask
+
+ case D_CR + 0:
+ return Ycr0
+ case D_CR + 1:
+ return Ycr1
+ case D_CR + 2:
+ return Ycr2
+ case D_CR + 3:
+ return Ycr3
+ case D_CR + 4:
+ return Ycr4
+ case D_CR + 5:
+ return Ycr5
+ case D_CR + 6:
+ return Ycr6
+ case D_CR + 7:
+ return Ycr7
+ case D_CR + 8:
+ return Ycr8
+
+ case D_DR + 0:
+ return Ydr0
+ case D_DR + 1:
+ return Ydr1
+ case D_DR + 2:
+ return Ydr2
+ case D_DR + 3:
+ return Ydr3
+ case D_DR + 4:
+ return Ydr4
+ case D_DR + 5:
+ return Ydr5
+ case D_DR + 6:
+ return Ydr6
+ case D_DR + 7:
+ return Ydr7
+
+ case D_TR + 0:
+ return Ytr0
+ case D_TR + 1:
+ return Ytr1
+ case D_TR + 2:
+ return Ytr2
+ case D_TR + 3:
+ return Ytr3
+ case D_TR + 4:
+ return Ytr4
+ case D_TR + 5:
+ return Ytr5
+ case D_TR + 6:
+ return Ytr6
+ case D_TR + 7:
+ return Ytr7
+
+ case D_EXTERN,
+ D_STATIC,
+ D_AUTO,
+ D_PARAM:
+ return Ym
+
+ case D_CONST,
+ D_ADDR:
+ if a.Sym == nil {
+ v = a.Offset
+ if v == 0 {
+ return Yi0
+ }
+ if v == 1 {
+ return Yi1
+ }
+ if v >= -128 && v <= 127 {
+ return Yi8
+ }
+ l = int32(v)
+ if int64(l) == v {
+ return Ys32 /* can sign extend */
+ }
+ if v>>32 == 0 {
+ return Yi32 /* unsigned */
+ }
+ return Yi64
+ }
+
+ return Yi32
+
+ case D_BRANCH:
+ return Ybr
+ }
+
+ return Yxxx
+}
+
+func asmidx(ctxt *obj.Link, scale int, index int, base int) {
+ var i int
+
+ switch index {
+ default:
+ goto bad
+
+ case D_NONE:
+ i = 4 << 3
+ goto bas
+
+ case D_R8,
+ D_R9,
+ D_R10,
+ D_R11,
+ D_R12,
+ D_R13,
+ D_R14,
+ D_R15:
+ if ctxt.Asmode != 64 {
+ goto bad
+ }
+ fallthrough
+
+ case D_AX,
+ D_CX,
+ D_DX,
+ D_BX,
+ D_BP,
+ D_SI,
+ D_DI:
+ i = reg[index] << 3
+ break
+ }
+
+ switch scale {
+ default:
+ goto bad
+
+ case 1:
+ break
+
+ case 2:
+ i |= 1 << 6
+
+ case 4:
+ i |= 2 << 6
+
+ case 8:
+ i |= 3 << 6
+ break
+ }
+
+bas:
+ switch base {
+ default:
+ goto bad
+
+ case D_NONE: /* must be mod=00 */
+ i |= 5
+
+ case D_R8,
+ D_R9,
+ D_R10,
+ D_R11,
+ D_R12,
+ D_R13,
+ D_R14,
+ D_R15:
+ if ctxt.Asmode != 64 {
+ goto bad
+ }
+ fallthrough
+
+ case D_AX,
+ D_CX,
+ D_DX,
+ D_BX,
+ D_SP,
+ D_BP,
+ D_SI,
+ D_DI:
+ i |= reg[base]
+ break
+ }
+
+ ctxt.Andptr[0] = byte(i)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ return
+
+bad:
+ ctxt.Diag("asmidx: bad address %d/%d/%d", scale, index, base)
+ ctxt.Andptr[0] = 0
+ ctxt.Andptr = ctxt.Andptr[1:]
+ return
+}
+
+func put4(ctxt *obj.Link, v int32) {
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr[1] = byte(v >> 8)
+ ctxt.Andptr[2] = byte(v >> 16)
+ ctxt.Andptr[3] = byte(v >> 24)
+ ctxt.Andptr = ctxt.Andptr[4:]
+}
+
+func relput4(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) {
+ var v int64
+ var rel obj.Reloc
+ var r *obj.Reloc
+
+ v = vaddr(ctxt, p, a, &rel)
+ if rel.Siz != 0 {
+ if rel.Siz != 4 {
+ ctxt.Diag("bad reloc")
+ }
+ r = obj.Addrel(ctxt.Cursym)
+ *r = rel
+ r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+ }
+
+ put4(ctxt, int32(v))
+}
+
+func put8(ctxt *obj.Link, v int64) {
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr[1] = byte(v >> 8)
+ ctxt.Andptr[2] = byte(v >> 16)
+ ctxt.Andptr[3] = byte(v >> 24)
+ ctxt.Andptr[4] = byte(v >> 32)
+ ctxt.Andptr[5] = byte(v >> 40)
+ ctxt.Andptr[6] = byte(v >> 48)
+ ctxt.Andptr[7] = byte(v >> 56)
+ ctxt.Andptr = ctxt.Andptr[8:]
+}
+
+/*
+static void
+relput8(Prog *p, Addr *a)
+{
+ vlong v;
+ Reloc rel, *r;
+
+ v = vaddr(ctxt, p, a, &rel);
+ if(rel.siz != 0) {
+ r = addrel(ctxt->cursym);
+ *r = rel;
+ r->siz = 8;
+ r->off = p->pc + ctxt->andptr - ctxt->and;
+ }
+ put8(ctxt, v);
+}
+*/
+func vaddr(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r *obj.Reloc) int64 {
+
+ var t int
+ var v int64
+ var s *obj.LSym
+
+ if r != nil {
+ *r = obj.Reloc{}
+ }
+
+ t = int(a.Type)
+ v = a.Offset
+ if t == D_ADDR {
+ t = int(a.Index)
+ }
+ switch t {
+ case D_STATIC,
+ D_EXTERN:
+ s = a.Sym
+ if r == nil {
+ ctxt.Diag("need reloc for %v", Dconv(p, 0, a))
+ log.Fatalf("reloc")
+ }
+
+ if isextern(s) != 0 {
+ r.Siz = 4
+ r.Type = obj.R_ADDR
+ } else {
+
+ r.Siz = 4
+ r.Type = obj.R_PCREL
+ }
+
+ r.Off = -1 // caller must fill in
+ r.Sym = s
+ r.Add = v
+ v = 0
+ if s.Type == obj.STLSBSS {
+ r.Xadd = r.Add - int64(r.Siz)
+ r.Type = obj.R_TLS
+ r.Xsym = s
+ }
+
+ case D_INDIR + D_TLS:
+ if r == nil {
+ ctxt.Diag("need reloc for %v", Dconv(p, 0, a))
+ log.Fatalf("reloc")
+ }
+
+ r.Type = obj.R_TLS_LE
+ r.Siz = 4
+ r.Off = -1 // caller must fill in
+ r.Add = v
+ v = 0
+ break
+ }
+
+ return v
+}
+
+func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int) {
+ var v int32
+ var t int
+ var scale int
+ var rel obj.Reloc
+
+ rex &= 0x40 | Rxr
+ v = int32(a.Offset)
+ t = int(a.Type)
+ rel.Siz = 0
+ if a.Index != D_NONE && a.Index != D_TLS {
+ if t < D_INDIR {
+ switch t {
+ default:
+ goto bad
+
+ case D_EXTERN,
+ D_STATIC:
+ if !(isextern(a.Sym) != 0) {
+ goto bad
+ }
+ t = D_NONE
+ v = int32(vaddr(ctxt, p, a, &rel))
+
+ case D_AUTO,
+ D_PARAM:
+ t = D_SP
+ break
+ }
+ } else {
+
+ t -= D_INDIR
+ }
+ ctxt.Rexflag |= regrex[int(a.Index)]&Rxx | regrex[t]&Rxb | rex
+ if t == D_NONE {
+ ctxt.Andptr[0] = byte(0<<6 | 4<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmidx(ctxt, int(a.Scale), int(a.Index), t)
+ goto putrelv
+ }
+
+ if v == 0 && rel.Siz == 0 && t != D_BP && t != D_R13 {
+ ctxt.Andptr[0] = byte(0<<6 | 4<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmidx(ctxt, int(a.Scale), int(a.Index), t)
+ return
+ }
+
+ if v >= -128 && v < 128 && rel.Siz == 0 {
+ ctxt.Andptr[0] = byte(1<<6 | 4<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmidx(ctxt, int(a.Scale), int(a.Index), t)
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ return
+ }
+
+ ctxt.Andptr[0] = byte(2<<6 | 4<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmidx(ctxt, int(a.Scale), int(a.Index), t)
+ goto putrelv
+ }
+
+ if t >= D_AL && t <= D_X0+15 {
+ if v != 0 {
+ goto bad
+ }
+ ctxt.Andptr[0] = byte(3<<6 | reg[t]<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Rexflag |= regrex[t]&(0x40|Rxb) | rex
+ return
+ }
+
+ scale = int(a.Scale)
+ if t < D_INDIR {
+ switch a.Type {
+ default:
+ goto bad
+
+ case D_STATIC,
+ D_EXTERN:
+ t = D_NONE
+ v = int32(vaddr(ctxt, p, a, &rel))
+
+ case D_AUTO,
+ D_PARAM:
+ t = D_SP
+ break
+ }
+
+ scale = 1
+ } else {
+
+ t -= D_INDIR
+ }
+ if t == D_TLS {
+ v = int32(vaddr(ctxt, p, a, &rel))
+ }
+
+ ctxt.Rexflag |= regrex[t]&Rxb | rex
+ if t == D_NONE || (D_CS <= t && t <= D_GS) || t == D_TLS {
+ if (a.Sym == nil || !(isextern(a.Sym) != 0)) && t == D_NONE && (a.Type == D_STATIC || a.Type == D_EXTERN) || ctxt.Asmode != 64 {
+ ctxt.Andptr[0] = byte(0<<6 | 5<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ goto putrelv
+ }
+
+ /* temporary */
+ ctxt.Andptr[0] = byte(0<<6 | 4<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:] /* sib present */
+ ctxt.Andptr[0] = 0<<6 | 4<<3 | 5<<0
+ ctxt.Andptr = ctxt.Andptr[1:] /* DS:d32 */
+ goto putrelv
+ }
+
+ if t == D_SP || t == D_R12 {
+ if v == 0 {
+ ctxt.Andptr[0] = byte(0<<6 | reg[t]<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmidx(ctxt, scale, D_NONE, t)
+ return
+ }
+
+ if v >= -128 && v < 128 {
+ ctxt.Andptr[0] = byte(1<<6 | reg[t]<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmidx(ctxt, scale, D_NONE, t)
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ return
+ }
+
+ ctxt.Andptr[0] = byte(2<<6 | reg[t]<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmidx(ctxt, scale, D_NONE, t)
+ goto putrelv
+ }
+
+ if t >= D_AX && t <= D_R15 {
+ if a.Index == D_TLS {
+ rel = obj.Reloc{}
+ rel.Type = obj.R_TLS_IE
+ rel.Siz = 4
+ rel.Sym = nil
+ rel.Add = int64(v)
+ v = 0
+ }
+
+ if v == 0 && rel.Siz == 0 && t != D_BP && t != D_R13 {
+ ctxt.Andptr[0] = byte(0<<6 | reg[t]<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ return
+ }
+
+ if v >= -128 && v < 128 && rel.Siz == 0 {
+ ctxt.Andptr[0] = byte(1<<6 | reg[t]<<0 | r<<3)
+ ctxt.Andptr[1] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[2:]
+ return
+ }
+
+ ctxt.Andptr[0] = byte(2<<6 | reg[t]<<0 | r<<3)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ goto putrelv
+ }
+
+ goto bad
+
+putrelv:
+ if rel.Siz != 0 {
+ var r *obj.Reloc
+
+ if rel.Siz != 4 {
+ ctxt.Diag("bad rel")
+ goto bad
+ }
+
+ r = obj.Addrel(ctxt.Cursym)
+ *r = rel
+ r.Off = int32(ctxt.Curp.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+ }
+
+ put4(ctxt, v)
+ return
+
+bad:
+ ctxt.Diag("asmand: bad address %v", Dconv(p, 0, a))
+ return
+}
+
+func asmand(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, ra *obj.Addr) {
+ asmandsz(ctxt, p, a, reg[ra.Type], regrex[ra.Type], 0)
+}
+
+func asmando(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, o int) {
+ asmandsz(ctxt, p, a, o, 0, 0)
+}
+
+func bytereg(a *obj.Addr, t *uint8) {
+ if a.Index == D_NONE && (a.Type >= D_AX && a.Type <= D_R15) {
+ a.Type = D_AL + (a.Type - D_AX)
+ *t = 0
+ }
+}
+
+const (
+ E = 0xff
+)
+
+var ymovtab = []Movtab{
+ /* push */
+ Movtab{APUSHL, Ycs, Ynone, 0, [4]uint8{0x0e, E, 0, 0}},
+ Movtab{APUSHL, Yss, Ynone, 0, [4]uint8{0x16, E, 0, 0}},
+ Movtab{APUSHL, Yds, Ynone, 0, [4]uint8{0x1e, E, 0, 0}},
+ Movtab{APUSHL, Yes, Ynone, 0, [4]uint8{0x06, E, 0, 0}},
+ Movtab{APUSHL, Yfs, Ynone, 0, [4]uint8{0x0f, 0xa0, E, 0}},
+ Movtab{APUSHL, Ygs, Ynone, 0, [4]uint8{0x0f, 0xa8, E, 0}},
+ Movtab{APUSHQ, Yfs, Ynone, 0, [4]uint8{0x0f, 0xa0, E, 0}},
+ Movtab{APUSHQ, Ygs, Ynone, 0, [4]uint8{0x0f, 0xa8, E, 0}},
+ Movtab{APUSHW, Ycs, Ynone, 0, [4]uint8{Pe, 0x0e, E, 0}},
+ Movtab{APUSHW, Yss, Ynone, 0, [4]uint8{Pe, 0x16, E, 0}},
+ Movtab{APUSHW, Yds, Ynone, 0, [4]uint8{Pe, 0x1e, E, 0}},
+ Movtab{APUSHW, Yes, Ynone, 0, [4]uint8{Pe, 0x06, E, 0}},
+ Movtab{APUSHW, Yfs, Ynone, 0, [4]uint8{Pe, 0x0f, 0xa0, E}},
+ Movtab{APUSHW, Ygs, Ynone, 0, [4]uint8{Pe, 0x0f, 0xa8, E}},
+
+ /* pop */
+ Movtab{APOPL, Ynone, Yds, 0, [4]uint8{0x1f, E, 0, 0}},
+ Movtab{APOPL, Ynone, Yes, 0, [4]uint8{0x07, E, 0, 0}},
+ Movtab{APOPL, Ynone, Yss, 0, [4]uint8{0x17, E, 0, 0}},
+ Movtab{APOPL, Ynone, Yfs, 0, [4]uint8{0x0f, 0xa1, E, 0}},
+ Movtab{APOPL, Ynone, Ygs, 0, [4]uint8{0x0f, 0xa9, E, 0}},
+ Movtab{APOPQ, Ynone, Yfs, 0, [4]uint8{0x0f, 0xa1, E, 0}},
+ Movtab{APOPQ, Ynone, Ygs, 0, [4]uint8{0x0f, 0xa9, E, 0}},
+ Movtab{APOPW, Ynone, Yds, 0, [4]uint8{Pe, 0x1f, E, 0}},
+ Movtab{APOPW, Ynone, Yes, 0, [4]uint8{Pe, 0x07, E, 0}},
+ Movtab{APOPW, Ynone, Yss, 0, [4]uint8{Pe, 0x17, E, 0}},
+ Movtab{APOPW, Ynone, Yfs, 0, [4]uint8{Pe, 0x0f, 0xa1, E}},
+ Movtab{APOPW, Ynone, Ygs, 0, [4]uint8{Pe, 0x0f, 0xa9, E}},
+
+ /* mov seg */
+ Movtab{AMOVW, Yes, Yml, 1, [4]uint8{0x8c, 0, 0, 0}},
+ Movtab{AMOVW, Ycs, Yml, 1, [4]uint8{0x8c, 1, 0, 0}},
+ Movtab{AMOVW, Yss, Yml, 1, [4]uint8{0x8c, 2, 0, 0}},
+ Movtab{AMOVW, Yds, Yml, 1, [4]uint8{0x8c, 3, 0, 0}},
+ Movtab{AMOVW, Yfs, Yml, 1, [4]uint8{0x8c, 4, 0, 0}},
+ Movtab{AMOVW, Ygs, Yml, 1, [4]uint8{0x8c, 5, 0, 0}},
+ Movtab{AMOVW, Yml, Yes, 2, [4]uint8{0x8e, 0, 0, 0}},
+ Movtab{AMOVW, Yml, Ycs, 2, [4]uint8{0x8e, 1, 0, 0}},
+ Movtab{AMOVW, Yml, Yss, 2, [4]uint8{0x8e, 2, 0, 0}},
+ Movtab{AMOVW, Yml, Yds, 2, [4]uint8{0x8e, 3, 0, 0}},
+ Movtab{AMOVW, Yml, Yfs, 2, [4]uint8{0x8e, 4, 0, 0}},
+ Movtab{AMOVW, Yml, Ygs, 2, [4]uint8{0x8e, 5, 0, 0}},
+
+ /* mov cr */
+ Movtab{AMOVL, Ycr0, Yml, 3, [4]uint8{0x0f, 0x20, 0, 0}},
+ Movtab{AMOVL, Ycr2, Yml, 3, [4]uint8{0x0f, 0x20, 2, 0}},
+ Movtab{AMOVL, Ycr3, Yml, 3, [4]uint8{0x0f, 0x20, 3, 0}},
+ Movtab{AMOVL, Ycr4, Yml, 3, [4]uint8{0x0f, 0x20, 4, 0}},
+ Movtab{AMOVL, Ycr8, Yml, 3, [4]uint8{0x0f, 0x20, 8, 0}},
+ Movtab{AMOVQ, Ycr0, Yml, 3, [4]uint8{0x0f, 0x20, 0, 0}},
+ Movtab{AMOVQ, Ycr2, Yml, 3, [4]uint8{0x0f, 0x20, 2, 0}},
+ Movtab{AMOVQ, Ycr3, Yml, 3, [4]uint8{0x0f, 0x20, 3, 0}},
+ Movtab{AMOVQ, Ycr4, Yml, 3, [4]uint8{0x0f, 0x20, 4, 0}},
+ Movtab{AMOVQ, Ycr8, Yml, 3, [4]uint8{0x0f, 0x20, 8, 0}},
+ Movtab{AMOVL, Yml, Ycr0, 4, [4]uint8{0x0f, 0x22, 0, 0}},
+ Movtab{AMOVL, Yml, Ycr2, 4, [4]uint8{0x0f, 0x22, 2, 0}},
+ Movtab{AMOVL, Yml, Ycr3, 4, [4]uint8{0x0f, 0x22, 3, 0}},
+ Movtab{AMOVL, Yml, Ycr4, 4, [4]uint8{0x0f, 0x22, 4, 0}},
+ Movtab{AMOVL, Yml, Ycr8, 4, [4]uint8{0x0f, 0x22, 8, 0}},
+ Movtab{AMOVQ, Yml, Ycr0, 4, [4]uint8{0x0f, 0x22, 0, 0}},
+ Movtab{AMOVQ, Yml, Ycr2, 4, [4]uint8{0x0f, 0x22, 2, 0}},
+ Movtab{AMOVQ, Yml, Ycr3, 4, [4]uint8{0x0f, 0x22, 3, 0}},
+ Movtab{AMOVQ, Yml, Ycr4, 4, [4]uint8{0x0f, 0x22, 4, 0}},
+ Movtab{AMOVQ, Yml, Ycr8, 4, [4]uint8{0x0f, 0x22, 8, 0}},
+
+ /* mov dr */
+ Movtab{AMOVL, Ydr0, Yml, 3, [4]uint8{0x0f, 0x21, 0, 0}},
+ Movtab{AMOVL, Ydr6, Yml, 3, [4]uint8{0x0f, 0x21, 6, 0}},
+ Movtab{AMOVL, Ydr7, Yml, 3, [4]uint8{0x0f, 0x21, 7, 0}},
+ Movtab{AMOVQ, Ydr0, Yml, 3, [4]uint8{0x0f, 0x21, 0, 0}},
+ Movtab{AMOVQ, Ydr6, Yml, 3, [4]uint8{0x0f, 0x21, 6, 0}},
+ Movtab{AMOVQ, Ydr7, Yml, 3, [4]uint8{0x0f, 0x21, 7, 0}},
+ Movtab{AMOVL, Yml, Ydr0, 4, [4]uint8{0x0f, 0x23, 0, 0}},
+ Movtab{AMOVL, Yml, Ydr6, 4, [4]uint8{0x0f, 0x23, 6, 0}},
+ Movtab{AMOVL, Yml, Ydr7, 4, [4]uint8{0x0f, 0x23, 7, 0}},
+ Movtab{AMOVQ, Yml, Ydr0, 4, [4]uint8{0x0f, 0x23, 0, 0}},
+ Movtab{AMOVQ, Yml, Ydr6, 4, [4]uint8{0x0f, 0x23, 6, 0}},
+ Movtab{AMOVQ, Yml, Ydr7, 4, [4]uint8{0x0f, 0x23, 7, 0}},
+
+ /* mov tr */
+ Movtab{AMOVL, Ytr6, Yml, 3, [4]uint8{0x0f, 0x24, 6, 0}},
+ Movtab{AMOVL, Ytr7, Yml, 3, [4]uint8{0x0f, 0x24, 7, 0}},
+ Movtab{AMOVL, Yml, Ytr6, 4, [4]uint8{0x0f, 0x26, 6, E}},
+ Movtab{AMOVL, Yml, Ytr7, 4, [4]uint8{0x0f, 0x26, 7, E}},
+
+ /* lgdt, sgdt, lidt, sidt */
+ Movtab{AMOVL, Ym, Ygdtr, 4, [4]uint8{0x0f, 0x01, 2, 0}},
+ Movtab{AMOVL, Ygdtr, Ym, 3, [4]uint8{0x0f, 0x01, 0, 0}},
+ Movtab{AMOVL, Ym, Yidtr, 4, [4]uint8{0x0f, 0x01, 3, 0}},
+ Movtab{AMOVL, Yidtr, Ym, 3, [4]uint8{0x0f, 0x01, 1, 0}},
+ Movtab{AMOVQ, Ym, Ygdtr, 4, [4]uint8{0x0f, 0x01, 2, 0}},
+ Movtab{AMOVQ, Ygdtr, Ym, 3, [4]uint8{0x0f, 0x01, 0, 0}},
+ Movtab{AMOVQ, Ym, Yidtr, 4, [4]uint8{0x0f, 0x01, 3, 0}},
+ Movtab{AMOVQ, Yidtr, Ym, 3, [4]uint8{0x0f, 0x01, 1, 0}},
+
+ /* lldt, sldt */
+ Movtab{AMOVW, Yml, Yldtr, 4, [4]uint8{0x0f, 0x00, 2, 0}},
+ Movtab{AMOVW, Yldtr, Yml, 3, [4]uint8{0x0f, 0x00, 0, 0}},
+
+ /* lmsw, smsw */
+ Movtab{AMOVW, Yml, Ymsw, 4, [4]uint8{0x0f, 0x01, 6, 0}},
+ Movtab{AMOVW, Ymsw, Yml, 3, [4]uint8{0x0f, 0x01, 4, 0}},
+
+ /* ltr, str */
+ Movtab{AMOVW, Yml, Ytask, 4, [4]uint8{0x0f, 0x00, 3, 0}},
+ Movtab{AMOVW, Ytask, Yml, 3, [4]uint8{0x0f, 0x00, 1, 0}},
+
+ /* load full pointer */
+ Movtab{AMOVL, Yml, Ycol, 5, [4]uint8{0, 0, 0, 0}},
+ Movtab{AMOVW, Yml, Ycol, 5, [4]uint8{Pe, 0, 0, 0}},
+
+ /* double shift */
+ Movtab{ASHLL, Ycol, Yml, 6, [4]uint8{0xa4, 0xa5, 0, 0}},
+ Movtab{ASHRL, Ycol, Yml, 6, [4]uint8{0xac, 0xad, 0, 0}},
+ Movtab{ASHLQ, Ycol, Yml, 6, [4]uint8{Pw, 0xa4, 0xa5, 0}},
+ Movtab{ASHRQ, Ycol, Yml, 6, [4]uint8{Pw, 0xac, 0xad, 0}},
+ Movtab{ASHLW, Ycol, Yml, 6, [4]uint8{Pe, 0xa4, 0xa5, 0}},
+ Movtab{ASHRW, Ycol, Yml, 6, [4]uint8{Pe, 0xac, 0xad, 0}},
+
+ /* load TLS base */
+ Movtab{AMOVQ, Ytls, Yrl, 7, [4]uint8{0, 0, 0, 0}},
+ Movtab{0, 0, 0, 0, [4]uint8{}},
+}
+
+func isax(a *obj.Addr) int {
+ switch a.Type {
+ case D_AX,
+ D_AL,
+ D_AH,
+ D_INDIR + D_AX:
+ return 1
+ }
+
+ if a.Index == D_AX {
+ return 1
+ }
+ return 0
+}
+
+func subreg(p *obj.Prog, from int, to int) {
+ if false { /*debug['Q']*/
+ fmt.Printf("\n%v\ts/%v/%v/\n", p, Rconv(from), Rconv(to))
+ }
+
+ if int(p.From.Type) == from {
+ p.From.Type = int16(to)
+ }
+ if int(p.To.Type) == from {
+ p.To.Type = int16(to)
+ }
+
+ if int(p.From.Index) == from {
+ p.From.Index = uint8(to)
+ }
+ if int(p.To.Index) == from {
+ p.To.Index = uint8(to)
+ }
+
+ from += D_INDIR
+ if int(p.From.Type) == from {
+ p.From.Type = int16(to + D_INDIR)
+ }
+ if int(p.To.Type) == from {
+ p.To.Type = int16(to + D_INDIR)
+ }
+
+ if false { /*debug['Q']*/
+ fmt.Printf("%v\n", p)
+ }
+}
+
+func mediaop(ctxt *obj.Link, o *Optab, op int, osize int, z int) int {
+ switch op {
+ case Pm,
+ Pe,
+ Pf2,
+ Pf3:
+ if osize != 1 {
+ if op != Pm {
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ ctxt.Andptr[0] = Pm
+ ctxt.Andptr = ctxt.Andptr[1:]
+ z++
+ op = int(o.op[z])
+ break
+ }
+ fallthrough
+
+ default:
+ if -cap(ctxt.Andptr) == -cap(ctxt.And) || ctxt.And[-cap(ctxt.Andptr)+cap(ctxt.And[:])-1] != Pm {
+ ctxt.Andptr[0] = Pm
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ break
+ }
+
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ return z
+}
+
+func doasm(ctxt *obj.Link, p *obj.Prog) {
+ var o *Optab
+ var q *obj.Prog
+ var pp obj.Prog
+ var t []byte
+ var mo []Movtab
+ var z int
+ var op int
+ var ft int
+ var tt int
+ var xo int
+ var l int
+ var pre int
+ var v int64
+ var rel obj.Reloc
+ var r *obj.Reloc
+ var a *obj.Addr
+
+ ctxt.Curp = p // TODO
+
+ o = opindex[p.As]
+
+ if o == nil {
+ ctxt.Diag("asmins: missing op %v", p)
+ return
+ }
+
+ pre = prefixof(ctxt, &p.From)
+ if pre != 0 {
+ ctxt.Andptr[0] = byte(pre)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ pre = prefixof(ctxt, &p.To)
+ if pre != 0 {
+ ctxt.Andptr[0] = byte(pre)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+
+ if p.Ft == 0 {
+ p.Ft = uint8(oclass(ctxt, &p.From))
+ }
+ if p.Tt == 0 {
+ p.Tt = uint8(oclass(ctxt, &p.To))
+ }
+
+ ft = int(p.Ft) * Ymax
+ tt = int(p.Tt) * Ymax
+
+ t = o.ytab
+ if t == nil {
+ ctxt.Diag("asmins: noproto %v", p)
+ return
+ }
+
+ xo = bool2int(o.op[0] == 0x0f)
+ for z = 0; t[0] != 0; (func() { z += int(t[3]) + xo; t = t[4:] })() {
+ if ycover[ft+int(t[0])] != 0 {
+ if ycover[tt+int(t[1])] != 0 {
+ goto found
+ }
+ }
+ }
+ goto domov
+
+found:
+ switch o.prefix {
+ case Pq: /* 16 bit escape and opcode escape */
+ ctxt.Andptr[0] = Pe
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ ctxt.Andptr[0] = Pm
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Pq3: /* 16 bit escape, Rex.w, and opcode escape */
+ ctxt.Andptr[0] = Pe
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ ctxt.Andptr[0] = Pw
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = Pm
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Pf2, /* xmm opcode escape */
+ Pf3:
+ ctxt.Andptr[0] = byte(o.prefix)
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ ctxt.Andptr[0] = Pm
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Pm: /* opcode escape */
+ ctxt.Andptr[0] = Pm
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Pe: /* 16 bit escape */
+ ctxt.Andptr[0] = Pe
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Pw: /* 64-bit escape */
+ if p.Mode != 64 {
+
+ ctxt.Diag("asmins: illegal 64: %v", p)
+ }
+ ctxt.Rexflag |= Pw
+
+ case Pb: /* botch */
+ bytereg(&p.From, &p.Ft)
+
+ bytereg(&p.To, &p.Tt)
+
+ case P32: /* 32 bit but illegal if 64-bit mode */
+ if p.Mode == 64 {
+
+ ctxt.Diag("asmins: illegal in 64-bit mode: %v", p)
+ }
+
+ case Py: /* 64-bit only, no prefix */
+ if p.Mode != 64 {
+
+ ctxt.Diag("asmins: illegal in %d-bit mode: %v", p.Mode, p)
+ }
+ break
+ }
+
+ if z >= len(o.op) {
+ log.Fatalf("asmins bad table %v", p)
+ }
+ op = int(o.op[z])
+ if op == 0x0f {
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ z++
+ op = int(o.op[z])
+ }
+
+ switch t[2] {
+ default:
+ ctxt.Diag("asmins: unknown z %d %v", t[2], p)
+ return
+
+ case Zpseudo:
+ break
+
+ case Zlit:
+ for ; ; z++ {
+ op = int(o.op[z])
+ if !(op != 0) {
+ break
+ }
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+
+ case Zlitm_r:
+ for ; ; z++ {
+ op = int(o.op[z])
+ if !(op != 0) {
+ break
+ }
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ asmand(ctxt, p, &p.From, &p.To)
+
+ case Zmb_r:
+ bytereg(&p.From, &p.Ft)
+ fallthrough
+
+ /* fall through */
+ case Zm_r:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ asmand(ctxt, p, &p.From, &p.To)
+
+ case Zm2_r:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(o.op[z+1])
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.From, &p.To)
+
+ case Zm_r_xm:
+ mediaop(ctxt, o, op, int(t[3]), z)
+ asmand(ctxt, p, &p.From, &p.To)
+
+ case Zm_r_xm_nr:
+ ctxt.Rexflag = 0
+ mediaop(ctxt, o, op, int(t[3]), z)
+ asmand(ctxt, p, &p.From, &p.To)
+
+ case Zm_r_i_xm:
+ mediaop(ctxt, o, op, int(t[3]), z)
+ asmand(ctxt, p, &p.From, &p.To)
+ ctxt.Andptr[0] = byte(p.To.Offset)
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Zm_r_3d:
+ ctxt.Andptr[0] = 0x0f
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0x0f
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.From, &p.To)
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Zibm_r:
+ for {
+ tmp1 := z
+ z++
+ op = int(o.op[tmp1])
+ if !(op != 0) {
+ break
+ }
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ asmand(ctxt, p, &p.From, &p.To)
+ ctxt.Andptr[0] = byte(p.To.Offset)
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Zaut_r:
+ ctxt.Andptr[0] = 0x8d
+ ctxt.Andptr = ctxt.Andptr[1:] /* leal */
+ if p.From.Type != D_ADDR {
+ ctxt.Diag("asmins: Zaut sb type ADDR")
+ }
+ p.From.Type = int16(p.From.Index)
+ p.From.Index = D_NONE
+ asmand(ctxt, p, &p.From, &p.To)
+ p.From.Index = uint8(p.From.Type)
+ p.From.Type = D_ADDR
+
+ case Zm_o:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmando(ctxt, p, &p.From, int(o.op[z+1]))
+
+ case Zr_m:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.To, &p.From)
+
+ case Zr_m_xm:
+ mediaop(ctxt, o, op, int(t[3]), z)
+ asmand(ctxt, p, &p.To, &p.From)
+
+ case Zr_m_xm_nr:
+ ctxt.Rexflag = 0
+ mediaop(ctxt, o, op, int(t[3]), z)
+ asmand(ctxt, p, &p.To, &p.From)
+
+ case Zr_m_i_xm:
+ mediaop(ctxt, o, op, int(t[3]), z)
+ asmand(ctxt, p, &p.To, &p.From)
+ ctxt.Andptr[0] = byte(p.From.Offset)
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Zo_m:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmando(ctxt, p, &p.To, int(o.op[z+1]))
+
+ case Zcallindreg:
+ r = obj.Addrel(ctxt.Cursym)
+ r.Off = int32(p.Pc)
+ r.Type = obj.R_CALLIND
+ r.Siz = 0
+ fallthrough
+
+ // fallthrough
+ case Zo_m64:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ asmandsz(ctxt, p, &p.To, int(o.op[z+1]), 0, 1)
+
+ case Zm_ibo:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmando(ctxt, p, &p.From, int(o.op[z+1]))
+ ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.To, nil))
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Zibo_m:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmando(ctxt, p, &p.To, int(o.op[z+1]))
+ ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.From, nil))
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Zibo_m_xm:
+ z = mediaop(ctxt, o, op, int(t[3]), z)
+ asmando(ctxt, p, &p.To, int(o.op[z+1]))
+ ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.From, nil))
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Z_ib,
+ Zib_:
+ if t[2] == Zib_ {
+ a = &p.From
+ } else {
+
+ a = &p.To
+ }
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(vaddr(ctxt, p, a, nil))
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Zib_rp:
+ ctxt.Rexflag |= regrex[p.To.Type] & (Rxb | 0x40)
+ ctxt.Andptr[0] = byte(op + reg[p.To.Type])
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.From, nil))
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Zil_rp:
+ ctxt.Rexflag |= regrex[p.To.Type] & Rxb
+ ctxt.Andptr[0] = byte(op + reg[p.To.Type])
+ ctxt.Andptr = ctxt.Andptr[1:]
+ if o.prefix == Pe {
+ v = vaddr(ctxt, p, &p.From, nil)
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 8)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ } else {
+
+ relput4(ctxt, p, &p.From)
+ }
+
+ case Zo_iw:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ if p.From.Type != D_NONE {
+ v = vaddr(ctxt, p, &p.From, nil)
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 8)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+
+ case Ziq_rp:
+ v = vaddr(ctxt, p, &p.From, &rel)
+ l = int(v >> 32)
+ if l == 0 && rel.Siz != 8 {
+ //p->mark |= 0100;
+ //print("zero: %llux %P\n", v, p);
+ ctxt.Rexflag &^= (0x40 | Rxw)
+
+ ctxt.Rexflag |= regrex[p.To.Type] & Rxb
+ ctxt.Andptr[0] = byte(0xb8 + reg[p.To.Type])
+ ctxt.Andptr = ctxt.Andptr[1:]
+ if rel.Type != 0 {
+ r = obj.Addrel(ctxt.Cursym)
+ *r = rel
+ r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+ }
+
+ put4(ctxt, int32(v))
+ } else if l == -1 && uint64(v)&(uint64(1)<<31) != 0 { /* sign extend */
+
+ //p->mark |= 0100;
+ //print("sign: %llux %P\n", v, p);
+ ctxt.Andptr[0] = 0xc7
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ asmando(ctxt, p, &p.To, 0)
+ put4(ctxt, int32(v)) /* need all 8 */
+ } else {
+
+ //print("all: %llux %P\n", v, p);
+ ctxt.Rexflag |= regrex[p.To.Type] & Rxb
+
+ ctxt.Andptr[0] = byte(op + reg[p.To.Type])
+ ctxt.Andptr = ctxt.Andptr[1:]
+ if rel.Type != 0 {
+ r = obj.Addrel(ctxt.Cursym)
+ *r = rel
+ r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+ }
+
+ put8(ctxt, v)
+ }
+
+ case Zib_rr:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.To, &p.To)
+ ctxt.Andptr[0] = byte(vaddr(ctxt, p, &p.From, nil))
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Z_il,
+ Zil_:
+ if t[2] == Zil_ {
+ a = &p.From
+ } else {
+
+ a = &p.To
+ }
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ if o.prefix == Pe {
+ v = vaddr(ctxt, p, a, nil)
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 8)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ } else {
+
+ relput4(ctxt, p, a)
+ }
+
+ case Zm_ilo,
+ Zilo_m:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ if t[2] == Zilo_m {
+ a = &p.From
+ asmando(ctxt, p, &p.To, int(o.op[z+1]))
+ } else {
+
+ a = &p.To
+ asmando(ctxt, p, &p.From, int(o.op[z+1]))
+ }
+
+ if o.prefix == Pe {
+ v = vaddr(ctxt, p, a, nil)
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 8)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ } else {
+
+ relput4(ctxt, p, a)
+ }
+
+ case Zil_rr:
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.To, &p.To)
+ if o.prefix == Pe {
+ v = vaddr(ctxt, p, &p.From, nil)
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 8)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ } else {
+
+ relput4(ctxt, p, &p.From)
+ }
+
+ case Z_rp:
+ ctxt.Rexflag |= regrex[p.To.Type] & (Rxb | 0x40)
+ ctxt.Andptr[0] = byte(op + reg[p.To.Type])
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Zrp_:
+ ctxt.Rexflag |= regrex[p.From.Type] & (Rxb | 0x40)
+ ctxt.Andptr[0] = byte(op + reg[p.From.Type])
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case Zclr:
+ ctxt.Rexflag &^= Pw
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &p.To, &p.To)
+
+ case Zcall:
+ if p.To.Sym == nil {
+ ctxt.Diag("call without target")
+ log.Fatalf("bad code")
+ }
+
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ r = obj.Addrel(ctxt.Cursym)
+ r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+ r.Sym = p.To.Sym
+ r.Add = p.To.Offset
+ r.Type = obj.R_CALL
+ r.Siz = 4
+ put4(ctxt, 0)
+
+ // TODO: jump across functions needs reloc
+ case Zbr,
+ Zjmp,
+ Zloop:
+ if p.To.Sym != nil {
+
+ if t[2] != Zjmp {
+ ctxt.Diag("branch to ATEXT")
+ log.Fatalf("bad code")
+ }
+
+ ctxt.Andptr[0] = byte(o.op[z+1])
+ ctxt.Andptr = ctxt.Andptr[1:]
+ r = obj.Addrel(ctxt.Cursym)
+ r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+ r.Sym = p.To.Sym
+ r.Type = obj.R_PCREL
+ r.Siz = 4
+ put4(ctxt, 0)
+ break
+ }
+
+ // Assumes q is in this function.
+ // TODO: Check in input, preserve in brchain.
+
+ // Fill in backward jump now.
+ q = p.Pcond
+
+ if q == nil {
+ ctxt.Diag("jmp/branch/loop without target")
+ log.Fatalf("bad code")
+ }
+
+ if p.Back&1 != 0 {
+ v = q.Pc - (p.Pc + 2)
+ if v >= -128 {
+ if p.As == AJCXZL {
+ ctxt.Andptr[0] = 0x67
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ } else if t[2] == Zloop {
+ ctxt.Diag("loop too far: %v", p)
+ } else {
+
+ v -= 5 - 2
+ if t[2] == Zbr {
+ ctxt.Andptr[0] = 0x0f
+ ctxt.Andptr = ctxt.Andptr[1:]
+ v--
+ }
+
+ ctxt.Andptr[0] = byte(o.op[z+1])
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 8)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 16)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 24)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+
+ break
+ }
+
+ // Annotate target; will fill in later.
+ p.Forwd = q.Comefrom
+
+ q.Comefrom = p
+ if p.Back&2 != 0 { // short
+ if p.As == AJCXZL {
+ ctxt.Andptr[0] = 0x67
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ ctxt.Andptr[0] = byte(op)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0
+ ctxt.Andptr = ctxt.Andptr[1:]
+ } else if t[2] == Zloop {
+ ctxt.Diag("loop too far: %v", p)
+ } else {
+
+ if t[2] == Zbr {
+ ctxt.Andptr[0] = 0x0f
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ ctxt.Andptr[0] = byte(o.op[z+1])
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+
+ break
+
+ /*
+ v = q->pc - p->pc - 2;
+ if((v >= -128 && v <= 127) || p->pc == -1 || q->pc == -1) {
+ *ctxt->andptr++ = op;
+ *ctxt->andptr++ = v;
+ } else {
+ v -= 5-2;
+ if(t[2] == Zbr) {
+ *ctxt->andptr++ = 0x0f;
+ v--;
+ }
+ *ctxt->andptr++ = o->op[z+1];
+ *ctxt->andptr++ = v;
+ *ctxt->andptr++ = v>>8;
+ *ctxt->andptr++ = v>>16;
+ *ctxt->andptr++ = v>>24;
+ }
+ */
+
+ case Zbyte:
+ v = vaddr(ctxt, p, &p.From, &rel)
+ if rel.Siz != 0 {
+ rel.Siz = uint8(op)
+ r = obj.Addrel(ctxt.Cursym)
+ *r = rel
+ r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+ }
+
+ ctxt.Andptr[0] = byte(v)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ if op > 1 {
+ ctxt.Andptr[0] = byte(v >> 8)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ if op > 2 {
+ ctxt.Andptr[0] = byte(v >> 16)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 24)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ if op > 4 {
+ ctxt.Andptr[0] = byte(v >> 32)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 40)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 48)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(v >> 56)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ }
+ }
+
+ break
+ }
+
+ return
+
+domov:
+ for mo = ymovtab; mo[0].as != 0; mo = mo[1:] {
+ if p.As == mo[0].as {
+ if ycover[ft+int(mo[0].ft)] != 0 {
+ if ycover[tt+int(mo[0].tt)] != 0 {
+ t = mo[0].op[:]
+ goto mfound
+ }
+ }
+ }
+ }
+
+bad:
+ if p.Mode != 64 {
+ /*
+ * here, the assembly has failed.
+ * if its a byte instruction that has
+ * unaddressable registers, try to
+ * exchange registers and reissue the
+ * instruction with the operands renamed.
+ */
+ pp = *p
+
+ z = int(p.From.Type)
+ if z >= D_BP && z <= D_DI {
+ if isax(&p.To) != 0 || p.To.Type == D_NONE {
+ // We certainly don't want to exchange
+ // with AX if the op is MUL or DIV.
+ ctxt.Andptr[0] = 0x87
+ ctxt.Andptr = ctxt.Andptr[1:] /* xchg lhs,bx */
+ asmando(ctxt, p, &p.From, reg[D_BX])
+ subreg(&pp, z, D_BX)
+ doasm(ctxt, &pp)
+ ctxt.Andptr[0] = 0x87
+ ctxt.Andptr = ctxt.Andptr[1:] /* xchg lhs,bx */
+ asmando(ctxt, p, &p.From, reg[D_BX])
+ } else {
+
+ ctxt.Andptr[0] = byte(0x90 + reg[z])
+ ctxt.Andptr = ctxt.Andptr[1:] /* xchg lsh,ax */
+ subreg(&pp, z, D_AX)
+ doasm(ctxt, &pp)
+ ctxt.Andptr[0] = byte(0x90 + reg[z])
+ ctxt.Andptr = ctxt.Andptr[1:] /* xchg lsh,ax */
+ }
+
+ return
+ }
+
+ z = int(p.To.Type)
+ if z >= D_BP && z <= D_DI {
+ if isax(&p.From) != 0 {
+ ctxt.Andptr[0] = 0x87
+ ctxt.Andptr = ctxt.Andptr[1:] /* xchg rhs,bx */
+ asmando(ctxt, p, &p.To, reg[D_BX])
+ subreg(&pp, z, D_BX)
+ doasm(ctxt, &pp)
+ ctxt.Andptr[0] = 0x87
+ ctxt.Andptr = ctxt.Andptr[1:] /* xchg rhs,bx */
+ asmando(ctxt, p, &p.To, reg[D_BX])
+ } else {
+
+ ctxt.Andptr[0] = byte(0x90 + reg[z])
+ ctxt.Andptr = ctxt.Andptr[1:] /* xchg rsh,ax */
+ subreg(&pp, z, D_AX)
+ doasm(ctxt, &pp)
+ ctxt.Andptr[0] = byte(0x90 + reg[z])
+ ctxt.Andptr = ctxt.Andptr[1:] /* xchg rsh,ax */
+ }
+
+ return
+ }
+ }
+
+ ctxt.Diag("doasm: notfound from=%x to=%x %v", uint16(p.From.Type), uint16(p.To.Type), p)
+ return
+
+mfound:
+ switch mo[0].code {
+ default:
+ ctxt.Diag("asmins: unknown mov %d %v", mo[0].code, p)
+
+ case 0: /* lit */
+ for z = 0; t[z] != E; z++ {
+
+ ctxt.Andptr[0] = t[z]
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+
+ case 1: /* r,m */
+ ctxt.Andptr[0] = t[0]
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ asmando(ctxt, p, &p.To, int(t[1]))
+
+ case 2: /* m,r */
+ ctxt.Andptr[0] = t[0]
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ asmando(ctxt, p, &p.From, int(t[1]))
+
+ case 3: /* r,m - 2op */
+ ctxt.Andptr[0] = t[0]
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ ctxt.Andptr[0] = t[1]
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmando(ctxt, p, &p.To, int(t[2]))
+ ctxt.Rexflag |= regrex[p.From.Type] & (Rxr | 0x40)
+
+ case 4: /* m,r - 2op */
+ ctxt.Andptr[0] = t[0]
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ ctxt.Andptr[0] = t[1]
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmando(ctxt, p, &p.From, int(t[2]))
+ ctxt.Rexflag |= regrex[p.To.Type] & (Rxr | 0x40)
+
+ case 5: /* load full pointer, trash heap */
+ if t[0] != 0 {
+
+ ctxt.Andptr[0] = t[0]
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ switch p.To.Index {
+ default:
+ goto bad
+
+ case D_DS:
+ ctxt.Andptr[0] = 0xc5
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case D_SS:
+ ctxt.Andptr[0] = 0x0f
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0xb2
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case D_ES:
+ ctxt.Andptr[0] = 0xc4
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case D_FS:
+ ctxt.Andptr[0] = 0x0f
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0xb4
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case D_GS:
+ ctxt.Andptr[0] = 0x0f
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0xb5
+ ctxt.Andptr = ctxt.Andptr[1:]
+ break
+ }
+
+ asmand(ctxt, p, &p.From, &p.To)
+
+ case 6: /* double shift */
+ if t[0] == Pw {
+
+ if p.Mode != 64 {
+ ctxt.Diag("asmins: illegal 64: %v", p)
+ }
+ ctxt.Rexflag |= Pw
+ t = t[1:]
+ } else if t[0] == Pe {
+ ctxt.Andptr[0] = Pe
+ ctxt.Andptr = ctxt.Andptr[1:]
+ t = t[1:]
+ }
+
+ z = int(p.From.Type)
+ switch z {
+ default:
+ goto bad
+
+ case D_CONST:
+ ctxt.Andptr[0] = 0x0f
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = t[0]
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmandsz(ctxt, p, &p.To, reg[int(p.From.Index)], regrex[int(p.From.Index)], 0)
+ ctxt.Andptr[0] = byte(p.From.Offset)
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ case D_CL,
+ D_CX:
+ ctxt.Andptr[0] = 0x0f
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = t[1]
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmandsz(ctxt, p, &p.To, reg[int(p.From.Index)], regrex[int(p.From.Index)], 0)
+ break
+ }
+
+ // NOTE: The systems listed here are the ones that use the "TLS initial exec" model,
+ // where you load the TLS base register into a register and then index off that
+ // register to access the actual TLS variables. Systems that allow direct TLS access
+ // are handled in prefixof above and should not be listed here.
+ case 7: /* mov tls, r */
+ switch ctxt.Headtype {
+
+ default:
+ log.Fatalf("unknown TLS base location for %s", obj.Headstr(ctxt.Headtype))
+
+ case obj.Hplan9:
+ if ctxt.Plan9privates == nil {
+ ctxt.Plan9privates = obj.Linklookup(ctxt, "_privates", 0)
+ }
+ pp.From = obj.Addr{}
+ pp.From.Type = D_EXTERN
+ pp.From.Sym = ctxt.Plan9privates
+ pp.From.Offset = 0
+ pp.From.Index = D_NONE
+ ctxt.Rexflag |= Pw
+ ctxt.Andptr[0] = 0x8B
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &pp.From, &p.To)
+
+ // TLS base is 0(FS).
+ case obj.Hsolaris: // TODO(rsc): Delete Hsolaris from list. Should not use this code. See progedit in obj6.c.
+ pp.From = p.From
+
+ pp.From.Type = D_INDIR + D_NONE
+ pp.From.Offset = 0
+ pp.From.Index = D_NONE
+ pp.From.Scale = 0
+ ctxt.Rexflag |= Pw
+ ctxt.Andptr[0] = 0x64
+ ctxt.Andptr = ctxt.Andptr[1:] // FS
+ ctxt.Andptr[0] = 0x8B
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &pp.From, &p.To)
+
+ // Windows TLS base is always 0x28(GS).
+ case obj.Hwindows:
+ pp.From = p.From
+
+ pp.From.Type = D_INDIR + D_GS
+ pp.From.Offset = 0x28
+ pp.From.Index = D_NONE
+ pp.From.Scale = 0
+ ctxt.Rexflag |= Pw
+ ctxt.Andptr[0] = 0x65
+ ctxt.Andptr = ctxt.Andptr[1:] // GS
+ ctxt.Andptr[0] = 0x8B
+ ctxt.Andptr = ctxt.Andptr[1:]
+ asmand(ctxt, p, &pp.From, &p.To)
+ break
+ }
+
+ break
+ }
+}
+
+var naclret = []uint8{
+ 0x5e, // POPL SI
+ // 0x8b, 0x7d, 0x00, // MOVL (BP), DI - catch return to invalid address, for debugging
+ 0x83,
+ 0xe6,
+ 0xe0, // ANDL $~31, SI
+ 0x4c,
+ 0x01,
+ 0xfe, // ADDQ R15, SI
+ 0xff,
+ 0xe6, // JMP SI
+}
+
+var naclspfix = []uint8{0x4c, 0x01, 0xfc} // ADDQ R15, SP
+
+var naclbpfix = []uint8{0x4c, 0x01, 0xfd} // ADDQ R15, BP
+
+var naclmovs = []uint8{
+ 0x89,
+ 0xf6, // MOVL SI, SI
+ 0x49,
+ 0x8d,
+ 0x34,
+ 0x37, // LEAQ (R15)(SI*1), SI
+ 0x89,
+ 0xff, // MOVL DI, DI
+ 0x49,
+ 0x8d,
+ 0x3c,
+ 0x3f, // LEAQ (R15)(DI*1), DI
+}
+
+var naclstos = []uint8{
+ 0x89,
+ 0xff, // MOVL DI, DI
+ 0x49,
+ 0x8d,
+ 0x3c,
+ 0x3f, // LEAQ (R15)(DI*1), DI
+}
+
+func nacltrunc(ctxt *obj.Link, reg int) {
+ if reg >= D_R8 {
+ ctxt.Andptr[0] = 0x45
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+ reg = (reg - D_AX) & 7
+ ctxt.Andptr[0] = 0x89
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(3<<6 | reg<<3 | reg)
+ ctxt.Andptr = ctxt.Andptr[1:]
+}
+
+func asmins(ctxt *obj.Link, p *obj.Prog) {
+ var i int
+ var n int
+ var np int
+ var c int
+ var and0 []byte
+ var r *obj.Reloc
+
+ ctxt.Andptr = ctxt.And[:]
+ ctxt.Asmode = int(p.Mode)
+
+ if p.As == AUSEFIELD {
+ r = obj.Addrel(ctxt.Cursym)
+ r.Off = 0
+ r.Siz = 0
+ r.Sym = p.From.Sym
+ r.Type = obj.R_USEFIELD
+ return
+ }
+
+ if ctxt.Headtype == obj.Hnacl {
+ if p.As == AREP {
+ ctxt.Rep++
+ return
+ }
+
+ if p.As == AREPN {
+ ctxt.Repn++
+ return
+ }
+
+ if p.As == ALOCK {
+ ctxt.Lock++
+ return
+ }
+
+ if p.As != ALEAQ && p.As != ALEAL {
+ if p.From.Index != D_NONE && p.From.Scale > 0 {
+ nacltrunc(ctxt, int(p.From.Index))
+ }
+ if p.To.Index != D_NONE && p.To.Scale > 0 {
+ nacltrunc(ctxt, int(p.To.Index))
+ }
+ }
+
+ switch p.As {
+ case ARET:
+ copy(ctxt.Andptr, naclret)
+ ctxt.Andptr = ctxt.Andptr[len(naclret):]
+ return
+
+ case ACALL,
+ AJMP:
+ if D_AX <= p.To.Type && p.To.Type <= D_DI {
+ // ANDL $~31, reg
+ ctxt.Andptr[0] = 0x83
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ ctxt.Andptr[0] = byte(0xe0 | (p.To.Type - D_AX))
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0xe0
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ // ADDQ R15, reg
+ ctxt.Andptr[0] = 0x4c
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ ctxt.Andptr[0] = 0x01
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(0xf8 | (p.To.Type - D_AX))
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+
+ if D_R8 <= p.To.Type && p.To.Type <= D_R15 {
+ // ANDL $~31, reg
+ ctxt.Andptr[0] = 0x41
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ ctxt.Andptr[0] = 0x83
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(0xe0 | (p.To.Type - D_R8))
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = 0xe0
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ // ADDQ R15, reg
+ ctxt.Andptr[0] = 0x4d
+ ctxt.Andptr = ctxt.Andptr[1:]
+
+ ctxt.Andptr[0] = 0x01
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Andptr[0] = byte(0xf8 | (p.To.Type - D_R8))
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+
+ case AINT:
+ ctxt.Andptr[0] = 0xf4
+ ctxt.Andptr = ctxt.Andptr[1:]
+ return
+
+ case ASCASB,
+ ASCASW,
+ ASCASL,
+ ASCASQ,
+ ASTOSB,
+ ASTOSW,
+ ASTOSL,
+ ASTOSQ:
+ copy(ctxt.Andptr, naclstos)
+ ctxt.Andptr = ctxt.Andptr[len(naclstos):]
+
+ case AMOVSB,
+ AMOVSW,
+ AMOVSL,
+ AMOVSQ:
+ copy(ctxt.Andptr, naclmovs)
+ ctxt.Andptr = ctxt.Andptr[len(naclmovs):]
+ break
+ }
+
+ if ctxt.Rep != 0 {
+ ctxt.Andptr[0] = 0xf3
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Rep = 0
+ }
+
+ if ctxt.Repn != 0 {
+ ctxt.Andptr[0] = 0xf2
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Repn = 0
+ }
+
+ if ctxt.Lock != 0 {
+ ctxt.Andptr[0] = 0xf0
+ ctxt.Andptr = ctxt.Andptr[1:]
+ ctxt.Lock = 0
+ }
+ }
+
+ ctxt.Rexflag = 0
+ and0 = ctxt.Andptr
+ ctxt.Asmode = int(p.Mode)
+ doasm(ctxt, p)
+ if ctxt.Rexflag != 0 {
+ /*
+ * as befits the whole approach of the architecture,
+ * the rex prefix must appear before the first opcode byte
+ * (and thus after any 66/67/f2/f3/26/2e/3e prefix bytes, but
+ * before the 0f opcode escape!), or it might be ignored.
+ * note that the handbook often misleadingly shows 66/f2/f3 in `opcode'.
+ */
+ if p.Mode != 64 {
+
+ ctxt.Diag("asmins: illegal in mode %d: %v", p.Mode, p)
+ }
+ n = -cap(ctxt.Andptr) + cap(and0)
+ for np = 0; np < n; np++ {
+ c = int(and0[np])
+ if c != 0xf2 && c != 0xf3 && (c < 0x64 || c > 0x67) && c != 0x2e && c != 0x3e && c != 0x26 {
+ break
+ }
+ }
+
+ copy(and0[np+1:], and0[np:n])
+ and0[np] = byte(0x40 | ctxt.Rexflag)
+ ctxt.Andptr = ctxt.Andptr[1:]
+ }
+
+ n = -cap(ctxt.Andptr) + cap(ctxt.And[:])
+ for i = len(ctxt.Cursym.R) - 1; i >= 0; i-- {
+ r = &ctxt.Cursym.R[i:][0]
+ if int64(r.Off) < p.Pc {
+ break
+ }
+ if ctxt.Rexflag != 0 {
+ r.Off++
+ }
+ if r.Type == obj.R_PCREL || r.Type == obj.R_CALL {
+ r.Add -= p.Pc + int64(n) - (int64(r.Off) + int64(r.Siz))
+ }
+ }
+
+ if ctxt.Headtype == obj.Hnacl && p.As != ACMPL && p.As != ACMPQ {
+ switch p.To.Type {
+ case D_SP:
+ copy(ctxt.Andptr, naclspfix)
+ ctxt.Andptr = ctxt.Andptr[len(naclspfix):]
+
+ case D_BP:
+ copy(ctxt.Andptr, naclbpfix)
+ ctxt.Andptr = ctxt.Andptr[len(naclbpfix):]
+ break
+ }
+ }
+}
--- /dev/null
+// Inferno utils/6c/list.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6c/list.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package x86
+
+import (
+ "cmd/internal/obj"
+ "fmt"
+)
+
+//
+// Format conversions
+// %A int Opcodes (instruction mnemonics)
+//
+// %D Addr* Addresses (instruction operands)
+// Flags: "%lD": seperate the high and low words of a constant by "-"
+//
+// %P Prog* Instructions
+//
+// %R int Registers
+//
+// %$ char* String constant addresses (for internal use only)
+
+const (
+ STRINGSZ = 1000
+)
+
+var bigP *obj.Prog
+
+func Pconv(p *obj.Prog) string {
+ var str string
+ var fp string
+
+ switch p.As {
+ case ADATA:
+ str = fmt.Sprintf("%.5d (%v)\t%v\t%v/%d,%v", p.Pc, p.Line(), Aconv(int(p.As)), Dconv(p, 0, &p.From), p.From.Scale, Dconv(p, 0, &p.To))
+
+ case ATEXT:
+ if p.From.Scale != 0 {
+ str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%d,%v", p.Pc, p.Line(), Aconv(int(p.As)), Dconv(p, 0, &p.From), p.From.Scale, Dconv(p, fmtLong, &p.To))
+ break
+ }
+
+ str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%v", p.Pc, p.Line(), Aconv(int(p.As)), Dconv(p, 0, &p.From), Dconv(p, fmtLong, &p.To))
+
+ default:
+ str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%v", p.Pc, p.Line(), Aconv(int(p.As)), Dconv(p, 0, &p.From), Dconv(p, 0, &p.To))
+ break
+ }
+
+ fp += str
+ return fp
+}
+
+func Aconv(i int) string {
+ var fp string
+
+ fp += Anames[i]
+ return fp
+}
+
+func Dconv(p *obj.Prog, flag int, a *obj.Addr) string {
+ var str string
+ var s string
+ var fp string
+
+ var i int
+
+ i = int(a.Type)
+
+ if flag&fmtLong != 0 /*untyped*/ {
+ if i == D_CONST {
+ str = fmt.Sprintf("$%d-%d", a.Offset&0xffffffff, a.Offset>>32)
+ } else {
+
+ // ATEXT dst is not constant
+ str = fmt.Sprintf("!!%v", Dconv(p, 0, a))
+ }
+
+ goto brk
+ }
+
+ if i >= D_INDIR {
+ if a.Offset != 0 {
+ str = fmt.Sprintf("%d(%v)", a.Offset, Rconv(i-D_INDIR))
+ } else {
+
+ str = fmt.Sprintf("(%v)", Rconv(i-D_INDIR))
+ }
+ goto brk
+ }
+
+ switch i {
+ default:
+ if a.Offset != 0 {
+ str = fmt.Sprintf("$%d,%v", a.Offset, Rconv(i))
+ } else {
+
+ str = fmt.Sprintf("%v", Rconv(i))
+ }
+
+ case D_NONE:
+ str = ""
+
+ case D_BRANCH:
+ if a.Sym != nil {
+ str = fmt.Sprintf("%s(SB)", a.Sym.Name)
+ } else if p != nil && p.Pcond != nil {
+ str = fmt.Sprintf("%d", p.Pcond.Pc)
+ } else if a.U.Branch != nil {
+ str = fmt.Sprintf("%d", a.U.Branch.Pc)
+ } else {
+
+ str = fmt.Sprintf("%d(PC)", a.Offset)
+ }
+
+ case D_EXTERN:
+ str = fmt.Sprintf("%s+%d(SB)", a.Sym.Name, a.Offset)
+
+ case D_STATIC:
+ str = fmt.Sprintf("%s<>+%d(SB)", a.Sym.Name, a.Offset)
+
+ case D_AUTO:
+ if a.Sym != nil {
+ str = fmt.Sprintf("%s+%d(SP)", a.Sym.Name, a.Offset)
+ } else {
+
+ str = fmt.Sprintf("%d(SP)", a.Offset)
+ }
+
+ case D_PARAM:
+ if a.Sym != nil {
+ str = fmt.Sprintf("%s+%d(FP)", a.Sym.Name, a.Offset)
+ } else {
+
+ str = fmt.Sprintf("%d(FP)", a.Offset)
+ }
+
+ case D_CONST:
+ str = fmt.Sprintf("$%d", a.Offset)
+
+ case D_FCONST:
+ str = fmt.Sprintf("$(%.17g)", a.U.Dval)
+
+ case D_SCONST:
+ str = fmt.Sprintf("$\"%q\"", a.U.Sval)
+
+ case D_ADDR:
+ a.Type = int16(a.Index)
+ a.Index = D_NONE
+ str = fmt.Sprintf("$%v", Dconv(p, 0, a))
+ a.Index = uint8(a.Type)
+ a.Type = D_ADDR
+ goto conv
+ }
+
+brk:
+ if a.Index != D_NONE {
+ s = fmt.Sprintf("(%v*%d)", Rconv(int(a.Index)), int(a.Scale))
+ str += s
+ }
+
+conv:
+ fp += str
+ return fp
+}
+
+var Register = []string{
+ "AL", /* [D_AL] */
+ "CL",
+ "DL",
+ "BL",
+ "SPB",
+ "BPB",
+ "SIB",
+ "DIB",
+ "R8B",
+ "R9B",
+ "R10B",
+ "R11B",
+ "R12B",
+ "R13B",
+ "R14B",
+ "R15B",
+ "AX", /* [D_AX] */
+ "CX",
+ "DX",
+ "BX",
+ "SP",
+ "BP",
+ "SI",
+ "DI",
+ "R8",
+ "R9",
+ "R10",
+ "R11",
+ "R12",
+ "R13",
+ "R14",
+ "R15",
+ "AH",
+ "CH",
+ "DH",
+ "BH",
+ "F0", /* [D_F0] */
+ "F1",
+ "F2",
+ "F3",
+ "F4",
+ "F5",
+ "F6",
+ "F7",
+ "M0",
+ "M1",
+ "M2",
+ "M3",
+ "M4",
+ "M5",
+ "M6",
+ "M7",
+ "X0",
+ "X1",
+ "X2",
+ "X3",
+ "X4",
+ "X5",
+ "X6",
+ "X7",
+ "X8",
+ "X9",
+ "X10",
+ "X11",
+ "X12",
+ "X13",
+ "X14",
+ "X15",
+ "CS", /* [D_CS] */
+ "SS",
+ "DS",
+ "ES",
+ "FS",
+ "GS",
+ "GDTR", /* [D_GDTR] */
+ "IDTR", /* [D_IDTR] */
+ "LDTR", /* [D_LDTR] */
+ "MSW", /* [D_MSW] */
+ "TASK", /* [D_TASK] */
+ "CR0", /* [D_CR] */
+ "CR1",
+ "CR2",
+ "CR3",
+ "CR4",
+ "CR5",
+ "CR6",
+ "CR7",
+ "CR8",
+ "CR9",
+ "CR10",
+ "CR11",
+ "CR12",
+ "CR13",
+ "CR14",
+ "CR15",
+ "DR0", /* [D_DR] */
+ "DR1",
+ "DR2",
+ "DR3",
+ "DR4",
+ "DR5",
+ "DR6",
+ "DR7",
+ "TR0", /* [D_TR] */
+ "TR1",
+ "TR2",
+ "TR3",
+ "TR4",
+ "TR5",
+ "TR6",
+ "TR7",
+ "TLS", /* [D_TLS] */
+ "NONE", /* [D_NONE] */
+}
+
+func Rconv(r int) string {
+ var str string
+ var fp string
+
+ if r >= D_AL && r <= D_NONE {
+ str = fmt.Sprintf("%s", Register[r-D_AL])
+ } else {
+
+ str = fmt.Sprintf("gok(%d)", r)
+ }
+
+ fp += str
+ return fp
+}
--- /dev/null
+// Inferno utils/6l/pass.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6l/pass.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package x86
+
+import (
+ "cmd/internal/obj"
+ "encoding/binary"
+ "fmt"
+ "log"
+ "math"
+)
+
+var zprg = obj.Prog{
+ Back: 2,
+ As: AGOK,
+ From: obj.Addr{
+ Type: D_NONE,
+ Index: D_NONE,
+ },
+ To: obj.Addr{
+ Type: D_NONE,
+ Index: D_NONE,
+ },
+}
+
+func nopout(p *obj.Prog) {
+ p.As = ANOP
+ p.From.Type = D_NONE
+ p.To.Type = D_NONE
+}
+
+func symtype(a *obj.Addr) int {
+ var t int
+
+ t = int(a.Type)
+ if t == D_ADDR {
+ t = int(a.Index)
+ }
+ return t
+}
+
+func isdata(p *obj.Prog) bool {
+ return p.As == ADATA || p.As == AGLOBL
+}
+
+func iscall(p *obj.Prog) bool {
+ return p.As == ACALL
+}
+
+func datasize(p *obj.Prog) int {
+ return int(p.From.Scale)
+}
+
+func textflag(p *obj.Prog) int {
+ return int(p.From.Scale)
+}
+
+func settextflag(p *obj.Prog, f int) {
+ p.From.Scale = int8(f)
+}
+
+func canuselocaltls(ctxt *obj.Link) int {
+ switch ctxt.Headtype {
+ case obj.Hplan9,
+ obj.Hwindows:
+ return 0
+ }
+
+ return 1
+}
+
+func progedit(ctxt *obj.Link, p *obj.Prog) {
+ var literal string
+ var s *obj.LSym
+ var q *obj.Prog
+
+ // Thread-local storage references use the TLS pseudo-register.
+ // As a register, TLS refers to the thread-local storage base, and it
+ // can only be loaded into another register:
+ //
+ // MOVQ TLS, AX
+ //
+ // An offset from the thread-local storage base is written off(reg)(TLS*1).
+ // Semantically it is off(reg), but the (TLS*1) annotation marks this as
+ // indexing from the loaded TLS base. This emits a relocation so that
+ // if the linker needs to adjust the offset, it can. For example:
+ //
+ // MOVQ TLS, AX
+ // MOVQ 8(AX)(TLS*1), CX // load m into CX
+ //
+ // On systems that support direct access to the TLS memory, this
+ // pair of instructions can be reduced to a direct TLS memory reference:
+ //
+ // MOVQ 8(TLS), CX // load m into CX
+ //
+ // The 2-instruction and 1-instruction forms correspond roughly to
+ // ELF TLS initial exec mode and ELF TLS local exec mode, respectively.
+ //
+ // We applies this rewrite on systems that support the 1-instruction form.
+ // The decision is made using only the operating system (and probably
+ // the -shared flag, eventually), not the link mode. If some link modes
+ // on a particular operating system require the 2-instruction form,
+ // then all builds for that operating system will use the 2-instruction
+ // form, so that the link mode decision can be delayed to link time.
+ //
+ // In this way, all supported systems use identical instructions to
+ // access TLS, and they are rewritten appropriately first here in
+ // liblink and then finally using relocations in the linker.
+
+ if canuselocaltls(ctxt) != 0 {
+
+ // Reduce TLS initial exec model to TLS local exec model.
+ // Sequences like
+ // MOVQ TLS, BX
+ // ... off(BX)(TLS*1) ...
+ // become
+ // NOP
+ // ... off(TLS) ...
+ //
+ // TODO(rsc): Remove the Hsolaris special case. It exists only to
+ // guarantee we are producing byte-identical binaries as before this code.
+ // But it should be unnecessary.
+ if (p.As == AMOVQ || p.As == AMOVL) && p.From.Type == D_TLS && D_AX <= p.To.Type && p.To.Type <= D_R15 && ctxt.Headtype != obj.Hsolaris {
+
+ nopout(p)
+ }
+ if p.From.Index == D_TLS && D_INDIR+D_AX <= p.From.Type && p.From.Type <= D_INDIR+D_R15 {
+ p.From.Type = D_INDIR + D_TLS
+ p.From.Scale = 0
+ p.From.Index = D_NONE
+ }
+
+ if p.To.Index == D_TLS && D_INDIR+D_AX <= p.To.Type && p.To.Type <= D_INDIR+D_R15 {
+ p.To.Type = D_INDIR + D_TLS
+ p.To.Scale = 0
+ p.To.Index = D_NONE
+ }
+ } else {
+
+ // As a courtesy to the C compilers, rewrite TLS local exec load as TLS initial exec load.
+ // The instruction
+ // MOVQ off(TLS), BX
+ // becomes the sequence
+ // MOVQ TLS, BX
+ // MOVQ off(BX)(TLS*1), BX
+ // This allows the C compilers to emit references to m and g using the direct off(TLS) form.
+ if (p.As == AMOVQ || p.As == AMOVL) && p.From.Type == D_INDIR+D_TLS && D_AX <= p.To.Type && p.To.Type <= D_R15 {
+
+ q = obj.Appendp(ctxt, p)
+ q.As = p.As
+ q.From = p.From
+ q.From.Type = D_INDIR + p.To.Type
+ q.From.Index = D_TLS
+ q.From.Scale = 2 // TODO: use 1
+ q.To = p.To
+ p.From.Type = D_TLS
+ p.From.Index = D_NONE
+ p.From.Offset = 0
+ }
+ }
+
+ // TODO: Remove.
+ if ctxt.Headtype == obj.Hwindows || ctxt.Headtype == obj.Hplan9 {
+
+ if p.From.Scale == 1 && p.From.Index == D_TLS {
+ p.From.Scale = 2
+ }
+ if p.To.Scale == 1 && p.To.Index == D_TLS {
+ p.To.Scale = 2
+ }
+ }
+
+ if ctxt.Headtype == obj.Hnacl {
+ nacladdr(ctxt, p, &p.From)
+ nacladdr(ctxt, p, &p.To)
+ }
+
+ // Maintain information about code generation mode.
+ if ctxt.Mode == 0 {
+
+ ctxt.Mode = 64
+ }
+ p.Mode = int8(ctxt.Mode)
+
+ switch p.As {
+ case AMODE:
+ if p.From.Type == D_CONST || p.From.Type == D_INDIR+D_NONE {
+ switch int(p.From.Offset) {
+ case 16,
+ 32,
+ 64:
+ ctxt.Mode = int(p.From.Offset)
+ break
+ }
+ }
+
+ nopout(p)
+ break
+ }
+
+ // Rewrite CALL/JMP/RET to symbol as D_BRANCH.
+ switch p.As {
+
+ case ACALL,
+ AJMP,
+ ARET:
+ if (p.To.Type == D_EXTERN || p.To.Type == D_STATIC) && p.To.Sym != nil {
+ p.To.Type = D_BRANCH
+ }
+ break
+ }
+
+ // Rewrite float constants to values stored in memory.
+ switch p.As {
+
+ // Convert AMOVSS $(0), Xx to AXORPS Xx, Xx
+ case AMOVSS:
+ if p.From.Type == D_FCONST {
+
+ if p.From.U.Dval == 0 {
+ if p.To.Type >= D_X0 {
+ if p.To.Type <= D_X15 {
+ p.As = AXORPS
+ p.From.Type = p.To.Type
+ p.From.Index = p.To.Index
+ break
+ }
+ }
+ }
+ }
+ fallthrough
+
+ // fallthrough
+
+ case AFMOVF,
+ AFADDF,
+ AFSUBF,
+ AFSUBRF,
+ AFMULF,
+ AFDIVF,
+ AFDIVRF,
+ AFCOMF,
+ AFCOMFP,
+ AADDSS,
+ ASUBSS,
+ AMULSS,
+ ADIVSS,
+ ACOMISS,
+ AUCOMISS:
+ if p.From.Type == D_FCONST {
+
+ var i32 uint32
+ var f32 float32
+ f32 = float32(p.From.U.Dval)
+ i32 = math.Float32bits(f32)
+ literal = fmt.Sprintf("$f32.%08x", i32)
+ s = obj.Linklookup(ctxt, literal, 0)
+ if s.Type == 0 {
+ s.Type = obj.SRODATA
+ obj.Adduint32(ctxt, s, i32)
+ s.Reachable = 0
+ }
+
+ p.From.Type = D_EXTERN
+ p.From.Sym = s
+ p.From.Offset = 0
+ }
+
+ // Convert AMOVSD $(0), Xx to AXORPS Xx, Xx
+ case AMOVSD:
+ if p.From.Type == D_FCONST {
+
+ if p.From.U.Dval == 0 {
+ if p.To.Type >= D_X0 {
+ if p.To.Type <= D_X15 {
+ p.As = AXORPS
+ p.From.Type = p.To.Type
+ p.From.Index = p.To.Index
+ break
+ }
+ }
+ }
+ }
+ fallthrough
+
+ // fallthrough
+ case AFMOVD,
+ AFADDD,
+ AFSUBD,
+ AFSUBRD,
+ AFMULD,
+ AFDIVD,
+ AFDIVRD,
+ AFCOMD,
+ AFCOMDP,
+ AADDSD,
+ ASUBSD,
+ AMULSD,
+ ADIVSD,
+ ACOMISD,
+ AUCOMISD:
+ if p.From.Type == D_FCONST {
+
+ var i64 uint64
+ i64 = math.Float64bits(p.From.U.Dval)
+ literal = fmt.Sprintf("$f64.%016x", i64)
+ s = obj.Linklookup(ctxt, literal, 0)
+ if s.Type == 0 {
+ s.Type = obj.SRODATA
+ obj.Adduint64(ctxt, s, i64)
+ s.Reachable = 0
+ }
+
+ p.From.Type = D_EXTERN
+ p.From.Sym = s
+ p.From.Offset = 0
+ }
+
+ break
+ }
+}
+
+func nacladdr(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) {
+ if p.As == ALEAL || p.As == ALEAQ {
+ return
+ }
+
+ if a.Type == D_BP || a.Type == D_INDIR+D_BP {
+ ctxt.Diag("invalid address: %v", p)
+ return
+ }
+
+ if a.Type == D_INDIR+D_TLS {
+ a.Type = D_INDIR + D_BP
+ } else if a.Type == D_TLS {
+ a.Type = D_BP
+ }
+ if D_INDIR <= a.Type && a.Type <= D_INDIR+D_INDIR {
+ switch a.Type {
+ // all ok
+ case D_INDIR + D_BP,
+ D_INDIR + D_SP,
+ D_INDIR + D_R15:
+ break
+
+ default:
+ if a.Index != D_NONE {
+ ctxt.Diag("invalid address %v", p)
+ }
+ a.Index = uint8(a.Type - D_INDIR)
+ if a.Index != D_NONE {
+ a.Scale = 1
+ }
+ a.Type = D_INDIR + D_R15
+ break
+ }
+ }
+}
+
+func parsetextconst(arg int64, textstksiz *int64, textarg *int64) {
+ *textstksiz = arg & 0xffffffff
+ if *textstksiz&0x80000000 != 0 {
+ *textstksiz = -(-*textstksiz & 0xffffffff)
+ }
+
+ *textarg = (arg >> 32) & 0xffffffff
+ if *textarg&0x80000000 != 0 {
+ *textarg = 0
+ }
+ *textarg = (*textarg + 7) &^ 7
+}
+
+func addstacksplit(ctxt *obj.Link, cursym *obj.LSym) {
+ var p *obj.Prog
+ var q *obj.Prog
+ var p1 *obj.Prog
+ var p2 *obj.Prog
+ var autoffset int32
+ var deltasp int32
+ var a int
+ var pcsize int
+ var textstksiz int64
+ var textarg int64
+
+ if ctxt.Tlsg == nil {
+ ctxt.Tlsg = obj.Linklookup(ctxt, "runtime.tlsg", 0)
+ }
+ if ctxt.Symmorestack[0] == nil {
+ ctxt.Symmorestack[0] = obj.Linklookup(ctxt, "runtime.morestack", 0)
+ ctxt.Symmorestack[1] = obj.Linklookup(ctxt, "runtime.morestack_noctxt", 0)
+ }
+
+ if ctxt.Headtype == obj.Hplan9 && ctxt.Plan9privates == nil {
+ ctxt.Plan9privates = obj.Linklookup(ctxt, "_privates", 0)
+ }
+
+ ctxt.Cursym = cursym
+
+ if cursym.Text == nil || cursym.Text.Link == nil {
+ return
+ }
+
+ p = cursym.Text
+ parsetextconst(p.To.Offset, &textstksiz, &textarg)
+ autoffset = int32(textstksiz)
+ if autoffset < 0 {
+ autoffset = 0
+ }
+
+ cursym.Args = int32(p.To.Offset >> 32)
+ cursym.Locals = int32(textstksiz)
+
+ if autoffset < obj.StackSmall && !(p.From.Scale&obj.NOSPLIT != 0) {
+ for q = p; q != nil; q = q.Link {
+ if q.As == ACALL {
+ goto noleaf
+ }
+ if (q.As == ADUFFCOPY || q.As == ADUFFZERO) && autoffset >= obj.StackSmall-8 {
+ goto noleaf
+ }
+ }
+
+ p.From.Scale |= obj.NOSPLIT
+ noleaf:
+ }
+
+ q = nil
+ if !(p.From.Scale&obj.NOSPLIT != 0) || (p.From.Scale&obj.WRAPPER != 0) {
+ p = obj.Appendp(ctxt, p)
+ p = load_g_cx(ctxt, p) // load g into CX
+ }
+
+ if !(cursym.Text.From.Scale&obj.NOSPLIT != 0) {
+ p = stacksplit(ctxt, p, autoffset, int32(textarg), bool2int(!(cursym.Text.From.Scale&obj.NEEDCTXT != 0)), &q) // emit split check
+ }
+
+ if autoffset != 0 {
+
+ if autoffset%int32(ctxt.Arch.Regsize) != 0 {
+ ctxt.Diag("unaligned stack size %d", autoffset)
+ }
+ p = obj.Appendp(ctxt, p)
+ p.As = AADJSP
+ p.From.Type = D_CONST
+ p.From.Offset = int64(autoffset)
+ p.Spadj = autoffset
+ } else {
+
+ // zero-byte stack adjustment.
+ // Insert a fake non-zero adjustment so that stkcheck can
+ // recognize the end of the stack-splitting prolog.
+ p = obj.Appendp(ctxt, p)
+
+ p.As = ANOP
+ p.Spadj = int32(-ctxt.Arch.Ptrsize)
+ p = obj.Appendp(ctxt, p)
+ p.As = ANOP
+ p.Spadj = int32(ctxt.Arch.Ptrsize)
+ }
+
+ if q != nil {
+ q.Pcond = p
+ }
+ deltasp = autoffset
+
+ if cursym.Text.From.Scale&obj.WRAPPER != 0 {
+ // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
+ //
+ // MOVQ g_panic(CX), BX
+ // TESTQ BX, BX
+ // JEQ end
+ // LEAQ (autoffset+8)(SP), DI
+ // CMPQ panic_argp(BX), DI
+ // JNE end
+ // MOVQ SP, panic_argp(BX)
+ // end:
+ // NOP
+ //
+ // The NOP is needed to give the jumps somewhere to land.
+ // It is a liblink NOP, not an x86 NOP: it encodes to 0 instruction bytes.
+
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AMOVQ
+ p.From.Type = D_INDIR + D_CX
+ p.From.Offset = 4 * int64(ctxt.Arch.Ptrsize) // G.panic
+ p.To.Type = D_BX
+ if ctxt.Headtype == obj.Hnacl {
+ p.As = AMOVL
+ p.From.Type = D_INDIR + D_R15
+ p.From.Scale = 1
+ p.From.Index = D_CX
+ }
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ATESTQ
+ p.From.Type = D_BX
+ p.To.Type = D_BX
+ if ctxt.Headtype == obj.Hnacl {
+ p.As = ATESTL
+ }
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AJEQ
+ p.To.Type = D_BRANCH
+ p1 = p
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ALEAQ
+ p.From.Type = D_INDIR + D_SP
+ p.From.Offset = int64(autoffset) + 8
+ p.To.Type = D_DI
+ if ctxt.Headtype == obj.Hnacl {
+ p.As = ALEAL
+ }
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ACMPQ
+ p.From.Type = D_INDIR + D_BX
+ p.From.Offset = 0 // Panic.argp
+ p.To.Type = D_DI
+ if ctxt.Headtype == obj.Hnacl {
+ p.As = ACMPL
+ p.From.Type = D_INDIR + D_R15
+ p.From.Scale = 1
+ p.From.Index = D_BX
+ }
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AJNE
+ p.To.Type = D_BRANCH
+ p2 = p
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AMOVQ
+ p.From.Type = D_SP
+ p.To.Type = D_INDIR + D_BX
+ p.To.Offset = 0 // Panic.argp
+ if ctxt.Headtype == obj.Hnacl {
+ p.As = AMOVL
+ p.To.Type = D_INDIR + D_R15
+ p.To.Scale = 1
+ p.To.Index = D_BX
+ }
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ANOP
+ p1.Pcond = p
+ p2.Pcond = p
+ }
+
+ if ctxt.Debugzerostack != 0 && autoffset != 0 && !(cursym.Text.From.Scale&obj.NOSPLIT != 0) {
+ // 6l -Z means zero the stack frame on entry.
+ // This slows down function calls but can help avoid
+ // false positives in garbage collection.
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AMOVQ
+ p.From.Type = D_SP
+ p.To.Type = D_DI
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AMOVQ
+ p.From.Type = D_CONST
+ p.From.Offset = int64(autoffset) / 8
+ p.To.Type = D_CX
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AMOVQ
+ p.From.Type = D_CONST
+ p.From.Offset = 0
+ p.To.Type = D_AX
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AREP
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ASTOSQ
+ }
+
+ for ; p != nil; p = p.Link {
+ pcsize = int(p.Mode) / 8
+ a = int(p.From.Type)
+ if a == D_AUTO {
+ p.From.Offset += int64(deltasp)
+ }
+ if a == D_PARAM {
+ p.From.Offset += int64(deltasp) + int64(pcsize)
+ }
+ a = int(p.To.Type)
+ if a == D_AUTO {
+ p.To.Offset += int64(deltasp)
+ }
+ if a == D_PARAM {
+ p.To.Offset += int64(deltasp) + int64(pcsize)
+ }
+
+ switch p.As {
+ default:
+ continue
+
+ case APUSHL,
+ APUSHFL:
+ deltasp += 4
+ p.Spadj = 4
+ continue
+
+ case APUSHQ,
+ APUSHFQ:
+ deltasp += 8
+ p.Spadj = 8
+ continue
+
+ case APUSHW,
+ APUSHFW:
+ deltasp += 2
+ p.Spadj = 2
+ continue
+
+ case APOPL,
+ APOPFL:
+ deltasp -= 4
+ p.Spadj = -4
+ continue
+
+ case APOPQ,
+ APOPFQ:
+ deltasp -= 8
+ p.Spadj = -8
+ continue
+
+ case APOPW,
+ APOPFW:
+ deltasp -= 2
+ p.Spadj = -2
+ continue
+
+ case ARET:
+ break
+ }
+
+ if autoffset != deltasp {
+ ctxt.Diag("unbalanced PUSH/POP")
+ }
+
+ if autoffset != 0 {
+ p.As = AADJSP
+ p.From.Type = D_CONST
+ p.From.Offset = int64(-autoffset)
+ p.Spadj = -autoffset
+ p = obj.Appendp(ctxt, p)
+ p.As = ARET
+
+ // If there are instructions following
+ // this ARET, they come from a branch
+ // with the same stackframe, so undo
+ // the cleanup.
+ p.Spadj = +autoffset
+ }
+
+ if p.To.Sym != nil { // retjmp
+ p.As = AJMP
+ }
+ }
+}
+
+func indir_cx(ctxt *obj.Link, a *obj.Addr) {
+ if ctxt.Headtype == obj.Hnacl {
+ a.Type = D_INDIR + D_R15
+ a.Index = D_CX
+ a.Scale = 1
+ return
+ }
+
+ a.Type = D_INDIR + D_CX
+}
+
+// Append code to p to load g into cx.
+// Overwrites p with the first instruction (no first appendp).
+// Overwriting p is unusual but it lets use this in both the
+// prologue (caller must call appendp first) and in the epilogue.
+// Returns last new instruction.
+func load_g_cx(ctxt *obj.Link, p *obj.Prog) *obj.Prog {
+
+ var next *obj.Prog
+
+ p.As = AMOVQ
+ if ctxt.Arch.Ptrsize == 4 {
+ p.As = AMOVL
+ }
+ p.From.Type = D_INDIR + D_TLS
+ p.From.Offset = 0
+ p.To.Type = D_CX
+
+ next = p.Link
+ progedit(ctxt, p)
+ for p.Link != next {
+ p = p.Link
+ }
+
+ if p.From.Index == D_TLS {
+ p.From.Scale = 2
+ }
+
+ return p
+}
+
+// Append code to p to check for stack split.
+// Appends to (does not overwrite) p.
+// Assumes g is in CX.
+// Returns last new instruction.
+// On return, *jmpok is the instruction that should jump
+// to the stack frame allocation if no split is needed.
+func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32, textarg int32, noctxt int, jmpok **obj.Prog) *obj.Prog {
+
+ var q *obj.Prog
+ var q1 *obj.Prog
+ var cmp int
+ var lea int
+ var mov int
+ var sub int
+
+ cmp = ACMPQ
+ lea = ALEAQ
+ mov = AMOVQ
+ sub = ASUBQ
+
+ if ctxt.Headtype == obj.Hnacl {
+ cmp = ACMPL
+ lea = ALEAL
+ mov = AMOVL
+ sub = ASUBL
+ }
+
+ q1 = nil
+ if framesize <= obj.StackSmall {
+ // small stack: SP <= stackguard
+ // CMPQ SP, stackguard
+ p = obj.Appendp(ctxt, p)
+
+ p.As = int16(cmp)
+ p.From.Type = D_SP
+ indir_cx(ctxt, &p.To)
+ p.To.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
+ if ctxt.Cursym.Cfunc != 0 {
+ p.To.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
+ }
+ } else if framesize <= obj.StackBig {
+ // large stack: SP-framesize <= stackguard-StackSmall
+ // LEAQ -xxx(SP), AX
+ // CMPQ AX, stackguard
+ p = obj.Appendp(ctxt, p)
+
+ p.As = int16(lea)
+ p.From.Type = D_INDIR + D_SP
+ p.From.Offset = -(int64(framesize) - obj.StackSmall)
+ p.To.Type = D_AX
+
+ p = obj.Appendp(ctxt, p)
+ p.As = int16(cmp)
+ p.From.Type = D_AX
+ indir_cx(ctxt, &p.To)
+ p.To.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
+ if ctxt.Cursym.Cfunc != 0 {
+ p.To.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
+ }
+ } else {
+
+ // Such a large stack we need to protect against wraparound.
+ // If SP is close to zero:
+ // SP-stackguard+StackGuard <= framesize + (StackGuard-StackSmall)
+ // The +StackGuard on both sides is required to keep the left side positive:
+ // SP is allowed to be slightly below stackguard. See stack.h.
+ //
+ // Preemption sets stackguard to StackPreempt, a very large value.
+ // That breaks the math above, so we have to check for that explicitly.
+ // MOVQ stackguard, CX
+ // CMPQ CX, $StackPreempt
+ // JEQ label-of-call-to-morestack
+ // LEAQ StackGuard(SP), AX
+ // SUBQ CX, AX
+ // CMPQ AX, $(framesize+(StackGuard-StackSmall))
+
+ p = obj.Appendp(ctxt, p)
+
+ p.As = int16(mov)
+ indir_cx(ctxt, &p.From)
+ p.From.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
+ if ctxt.Cursym.Cfunc != 0 {
+ p.From.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
+ }
+ p.To.Type = D_SI
+
+ p = obj.Appendp(ctxt, p)
+ p.As = int16(cmp)
+ p.From.Type = D_SI
+ p.To.Type = D_CONST
+ p.To.Offset = obj.StackPreempt
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AJEQ
+ p.To.Type = D_BRANCH
+ q1 = p
+
+ p = obj.Appendp(ctxt, p)
+ p.As = int16(lea)
+ p.From.Type = D_INDIR + D_SP
+ p.From.Offset = obj.StackGuard
+ p.To.Type = D_AX
+
+ p = obj.Appendp(ctxt, p)
+ p.As = int16(sub)
+ p.From.Type = D_SI
+ p.To.Type = D_AX
+
+ p = obj.Appendp(ctxt, p)
+ p.As = int16(cmp)
+ p.From.Type = D_AX
+ p.To.Type = D_CONST
+ p.To.Offset = int64(framesize) + (obj.StackGuard - obj.StackSmall)
+ }
+
+ // common
+ p = obj.Appendp(ctxt, p)
+
+ p.As = AJHI
+ p.To.Type = D_BRANCH
+ q = p
+
+ p = obj.Appendp(ctxt, p)
+ p.As = ACALL
+ p.To.Type = D_BRANCH
+ if ctxt.Cursym.Cfunc != 0 {
+ p.To.Sym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
+ } else {
+
+ p.To.Sym = ctxt.Symmorestack[noctxt]
+ }
+
+ p = obj.Appendp(ctxt, p)
+ p.As = AJMP
+ p.To.Type = D_BRANCH
+ p.Pcond = ctxt.Cursym.Text.Link
+
+ if q != nil {
+ q.Pcond = p.Link
+ }
+ if q1 != nil {
+ q1.Pcond = q.Link
+ }
+
+ *jmpok = q
+ return p
+}
+
+func follow(ctxt *obj.Link, s *obj.LSym) {
+ var firstp *obj.Prog
+ var lastp *obj.Prog
+
+ ctxt.Cursym = s
+
+ firstp = ctxt.NewProg()
+ lastp = firstp
+ xfol(ctxt, s.Text, &lastp)
+ lastp.Link = nil
+ s.Text = firstp.Link
+}
+
+func nofollow(a int) int {
+ switch a {
+ case AJMP,
+ ARET,
+ AIRETL,
+ AIRETQ,
+ AIRETW,
+ ARETFL,
+ ARETFQ,
+ ARETFW,
+ AUNDEF:
+ return 1
+ }
+
+ return 0
+}
+
+func pushpop(a int) int {
+ switch a {
+ case APUSHL,
+ APUSHFL,
+ APUSHQ,
+ APUSHFQ,
+ APUSHW,
+ APUSHFW,
+ APOPL,
+ APOPFL,
+ APOPQ,
+ APOPFQ,
+ APOPW,
+ APOPFW:
+ return 1
+ }
+
+ return 0
+}
+
+func relinv(a int) int {
+ switch a {
+ case AJEQ:
+ return AJNE
+ case AJNE:
+ return AJEQ
+ case AJLE:
+ return AJGT
+ case AJLS:
+ return AJHI
+ case AJLT:
+ return AJGE
+ case AJMI:
+ return AJPL
+ case AJGE:
+ return AJLT
+ case AJPL:
+ return AJMI
+ case AJGT:
+ return AJLE
+ case AJHI:
+ return AJLS
+ case AJCS:
+ return AJCC
+ case AJCC:
+ return AJCS
+ case AJPS:
+ return AJPC
+ case AJPC:
+ return AJPS
+ case AJOS:
+ return AJOC
+ case AJOC:
+ return AJOS
+ }
+
+ log.Fatalf("unknown relation: %s", Anames[a])
+ return 0
+}
+
+func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
+ var q *obj.Prog
+ var i int
+ var a int
+
+loop:
+ if p == nil {
+ return
+ }
+ if p.As == AJMP {
+ q = p.Pcond
+ if q != nil && q.As != ATEXT {
+ /* mark instruction as done and continue layout at target of jump */
+ p.Mark = 1
+
+ p = q
+ if p.Mark == 0 {
+ goto loop
+ }
+ }
+ }
+
+ if p.Mark != 0 {
+ /*
+ * p goes here, but already used it elsewhere.
+ * copy up to 4 instructions or else branch to other copy.
+ */
+ i = 0
+ q = p
+ for ; i < 4; (func() { i++; q = q.Link })() {
+
+ if q == nil {
+ break
+ }
+ if q == *last {
+ break
+ }
+ a = int(q.As)
+ if a == ANOP {
+ i--
+ continue
+ }
+
+ if nofollow(a) != 0 || pushpop(a) != 0 {
+ break // NOTE(rsc): arm does goto copy
+ }
+ if q.Pcond == nil || q.Pcond.Mark != 0 {
+ continue
+ }
+ if a == ACALL || a == ALOOP {
+ continue
+ }
+ for {
+ if p.As == ANOP {
+ p = p.Link
+ continue
+ }
+
+ q = obj.Copyp(ctxt, p)
+ p = p.Link
+ q.Mark = 1
+ (*last).Link = q
+ *last = q
+ if int(q.As) != a || q.Pcond == nil || q.Pcond.Mark != 0 {
+ continue
+ }
+
+ q.As = int16(relinv(int(q.As)))
+ p = q.Pcond
+ q.Pcond = q.Link
+ q.Link = p
+ xfol(ctxt, q.Link, last)
+ p = q.Link
+ if p.Mark != 0 {
+ return
+ }
+ goto loop
+ /* */
+ }
+ }
+ q = ctxt.NewProg()
+ q.As = AJMP
+ q.Lineno = p.Lineno
+ q.To.Type = D_BRANCH
+ q.To.Offset = p.Pc
+ q.Pcond = p
+ p = q
+ }
+
+ /* emit p */
+ p.Mark = 1
+
+ (*last).Link = p
+ *last = p
+ a = int(p.As)
+
+ /* continue loop with what comes after p */
+ if nofollow(a) != 0 {
+
+ return
+ }
+ if p.Pcond != nil && a != ACALL {
+ /*
+ * some kind of conditional branch.
+ * recurse to follow one path.
+ * continue loop on the other.
+ */
+ q = obj.Brchain(ctxt, p.Pcond)
+ if q != nil {
+
+ p.Pcond = q
+ }
+ q = obj.Brchain(ctxt, p.Link)
+ if q != nil {
+ p.Link = q
+ }
+ if p.From.Type == D_CONST {
+ if p.From.Offset == 1 {
+ /*
+ * expect conditional jump to be taken.
+ * rewrite so that's the fall-through case.
+ */
+ p.As = int16(relinv(a))
+
+ q = p.Link
+ p.Link = p.Pcond
+ p.Pcond = q
+ }
+ } else {
+
+ q = p.Link
+ if q.Mark != 0 {
+ if a != ALOOP {
+ p.As = int16(relinv(a))
+ p.Link = p.Pcond
+ p.Pcond = q
+ }
+ }
+ }
+
+ xfol(ctxt, p.Link, last)
+ if p.Pcond.Mark != 0 {
+ return
+ }
+ p = p.Pcond
+ goto loop
+ }
+
+ p = p.Link
+ goto loop
+}
+
+func prg() *obj.Prog {
+ p := zprg
+ return &p
+}
+
+var Linkamd64 = obj.LinkArch{
+ ByteOrder: binary.LittleEndian,
+ Pconv: Pconv,
+ Name: "amd64",
+ Thechar: '6',
+ Endian: obj.LittleEndian,
+ Addstacksplit: addstacksplit,
+ Assemble: span6,
+ Datasize: datasize,
+ Follow: follow,
+ Iscall: iscall,
+ Isdata: isdata,
+ Prg: prg,
+ Progedit: progedit,
+ Settextflag: settextflag,
+ Symtype: symtype,
+ Textflag: textflag,
+ Minlc: 1,
+ Ptrsize: 8,
+ Regsize: 8,
+ D_ADDR: D_ADDR,
+ D_AUTO: D_AUTO,
+ D_BRANCH: D_BRANCH,
+ D_CONST: D_CONST,
+ D_EXTERN: D_EXTERN,
+ D_FCONST: D_FCONST,
+ D_NONE: D_NONE,
+ D_PARAM: D_PARAM,
+ D_SCONST: D_SCONST,
+ D_STATIC: D_STATIC,
+ ACALL: ACALL,
+ ADATA: ADATA,
+ AEND: AEND,
+ AFUNCDATA: AFUNCDATA,
+ AGLOBL: AGLOBL,
+ AJMP: AJMP,
+ ANOP: ANOP,
+ APCDATA: APCDATA,
+ ARET: ARET,
+ ATEXT: ATEXT,
+ ATYPE: ATYPE,
+ AUSEFIELD: AUSEFIELD,
+}
+
+var Linkamd64p32 = obj.LinkArch{
+ ByteOrder: binary.LittleEndian,
+ Pconv: Pconv,
+ Name: "amd64p32",
+ Thechar: '6',
+ Endian: obj.LittleEndian,
+ Addstacksplit: addstacksplit,
+ Assemble: span6,
+ Datasize: datasize,
+ Follow: follow,
+ Iscall: iscall,
+ Isdata: isdata,
+ Prg: prg,
+ Progedit: progedit,
+ Settextflag: settextflag,
+ Symtype: symtype,
+ Textflag: textflag,
+ Minlc: 1,
+ Ptrsize: 4,
+ Regsize: 8,
+ D_ADDR: D_ADDR,
+ D_AUTO: D_AUTO,
+ D_BRANCH: D_BRANCH,
+ D_CONST: D_CONST,
+ D_EXTERN: D_EXTERN,
+ D_FCONST: D_FCONST,
+ D_NONE: D_NONE,
+ D_PARAM: D_PARAM,
+ D_SCONST: D_SCONST,
+ D_STATIC: D_STATIC,
+ ACALL: ACALL,
+ ADATA: ADATA,
+ AEND: AEND,
+ AFUNCDATA: AFUNCDATA,
+ AGLOBL: AGLOBL,
+ AJMP: AJMP,
+ ANOP: ANOP,
+ APCDATA: APCDATA,
+ ARET: ARET,
+ ATEXT: ATEXT,
+ ATYPE: ATYPE,
+ AUSEFIELD: AUSEFIELD,
+}
--- /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.
+
+package x86
+
+const (
+ fmtLong = 1 << iota
+)
+
+func bool2int(b bool) int {
+ if b {
+ return 1
+ }
+ return 0
+}
--- /dev/null
+// Inferno utils/5a/a.y
+// http://code.google.com/p/inferno-os/source/browse/utils/5a/a.y
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+%{
+package main
+
+import (
+ "cmd/internal/asm"
+ "cmd/internal/obj"
+ . "cmd/internal/obj/arm"
+)
+%}
+
+%union {
+ sym *asm.Sym
+ lval int32
+ dval float64
+ sval string
+ addr obj.Addr
+}
+
+%left '|'
+%left '^'
+%left '&'
+%left '<' '>'
+%left '+' '-'
+%left '*' '/' '%'
+%token <lval> LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5
+%token <lval> LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA
+%token <lval> LTYPEB LTYPEC LTYPED LTYPEE
+%token <lval> LTYPEG LTYPEH LTYPEI LTYPEJ LTYPEK
+%token <lval> LTYPEL LTYPEM LTYPEN LTYPEBX LTYPEPLD
+%token <lval> LCONST LSP LSB LFP LPC
+%token <lval> LTYPEX LTYPEPC LTYPEF LR LREG LF LFREG LC LCREG LPSR LFCR
+%token <lval> LCOND LS LAT
+%token <dval> LFCONST
+%token <sval> LSCONST
+%token <sym> LNAME LLAB LVAR
+%type <lval> con expr oexpr pointer offset sreg spreg creg
+%type <lval> rcon cond reglist
+%type <addr> gen rel reg regreg freg shift fcon frcon
+%type <addr> imm ximm name oreg ireg nireg ioreg imsr
+%%
+prog:
+| prog
+ {
+ stmtline = asm.Lineno;
+ }
+ line
+
+line:
+ LNAME ':'
+ {
+ $1 = asm.LabelLookup($1);
+ if $1.Type == LLAB && $1.Value != int64(asm.PC) {
+ yyerror("redeclaration of %s", $1.Labelname)
+ }
+ $1.Type = LLAB;
+ $1.Value = int64(asm.PC)
+ }
+ line
+| LNAME '=' expr ';'
+ {
+ $1.Type = LVAR;
+ $1.Value = int64($3);
+ }
+| LVAR '=' expr ';'
+ {
+ if $1.Value != int64($3) {
+ yyerror("redeclaration of %s", $1.Name)
+ }
+ $1.Value = int64($3);
+ }
+| ';'
+| inst ';'
+| error ';'
+
+inst:
+/*
+ * ADD
+ */
+ LTYPE1 cond imsr ',' spreg ',' reg
+ {
+ outcode($1, $2, &$3, $5, &$7);
+ }
+| LTYPE1 cond imsr ',' spreg ','
+ {
+ outcode($1, $2, &$3, $5, &nullgen);
+ }
+| LTYPE1 cond imsr ',' reg
+ {
+ outcode($1, $2, &$3, NREG, &$5);
+ }
+/*
+ * MVN
+ */
+| LTYPE2 cond imsr ',' reg
+ {
+ outcode($1, $2, &$3, NREG, &$5);
+ }
+/*
+ * MOVW
+ */
+| LTYPE3 cond gen ',' gen
+ {
+ outcode($1, $2, &$3, NREG, &$5);
+ }
+/*
+ * B/BL
+ */
+| LTYPE4 cond comma rel
+ {
+ outcode($1, $2, &nullgen, NREG, &$4);
+ }
+| LTYPE4 cond comma nireg
+ {
+ outcode($1, $2, &nullgen, NREG, &$4);
+ }
+/*
+ * BX
+ */
+| LTYPEBX comma ireg
+ {
+ outcode($1, Always, &nullgen, NREG, &$3);
+ }
+/*
+ * BEQ
+ */
+| LTYPE5 comma rel
+ {
+ outcode($1, Always, &nullgen, NREG, &$3);
+ }
+/*
+ * SWI
+ */
+| LTYPE6 cond comma gen
+ {
+ outcode($1, $2, &nullgen, NREG, &$4);
+ }
+/*
+ * CMP
+ */
+| LTYPE7 cond imsr ',' spreg comma
+ {
+ outcode($1, $2, &$3, $5, &nullgen);
+ }
+/*
+ * MOVM
+ */
+| LTYPE8 cond ioreg ',' '[' reglist ']'
+ {
+ var g obj.Addr
+
+ g = nullgen;
+ g.Type = D_CONST;
+ g.Offset = int64($6);
+ outcode($1, $2, &$3, NREG, &g);
+ }
+| LTYPE8 cond '[' reglist ']' ',' ioreg
+ {
+ var g obj.Addr
+
+ g = nullgen;
+ g.Type = D_CONST;
+ g.Offset = int64($4);
+ outcode($1, $2, &g, NREG, &$7);
+ }
+/*
+ * SWAP
+ */
+| LTYPE9 cond reg ',' ireg ',' reg
+ {
+ outcode($1, $2, &$5, int32($3.Reg), &$7);
+ }
+| LTYPE9 cond reg ',' ireg comma
+ {
+ outcode($1, $2, &$5, int32($3.Reg), &$3);
+ }
+| LTYPE9 cond comma ireg ',' reg
+ {
+ outcode($1, $2, &$4, int32($6.Reg), &$6);
+ }
+/*
+ * RET
+ */
+| LTYPEA cond comma
+ {
+ outcode($1, $2, &nullgen, NREG, &nullgen);
+ }
+/*
+ * TEXT/GLOBL
+ */
+| LTYPEB name ',' imm
+ {
+ asm.Settext($2.Sym);
+ $4.Type = D_CONST2;
+ $4.Offset2 = -obj.ArgsSizeUnknown;
+ outcode($1, Always, &$2, 0, &$4);
+ }
+| LTYPEB name ',' con ',' imm
+ {
+ asm.Settext($2.Sym);
+ $6.Type = D_CONST2;
+ $6.Offset2 = -obj.ArgsSizeUnknown;
+ outcode($1, Always, &$2, $4, &$6);
+ }
+| LTYPEB name ',' con ',' imm '-' con
+ {
+ asm.Settext($2.Sym);
+ $6.Type = D_CONST2;
+ $6.Offset2 = $8;
+ outcode($1, Always, &$2, $4, &$6);
+ }
+/*
+ * DATA
+ */
+| LTYPEC name '/' con ',' ximm
+ {
+ outcode($1, Always, &$2, $4, &$6);
+ }
+/*
+ * CASE
+ */
+| LTYPED cond reg comma
+ {
+ outcode($1, $2, &$3, NREG, &nullgen);
+ }
+/*
+ * word
+ */
+| LTYPEH comma ximm
+ {
+ outcode($1, Always, &nullgen, NREG, &$3);
+ }
+/*
+ * floating-point coprocessor
+ */
+| LTYPEI cond freg ',' freg
+ {
+ outcode($1, $2, &$3, NREG, &$5);
+ }
+| LTYPEK cond frcon ',' freg
+ {
+ outcode($1, $2, &$3, NREG, &$5);
+ }
+| LTYPEK cond frcon ',' LFREG ',' freg
+ {
+ outcode($1, $2, &$3, $5, &$7);
+ }
+| LTYPEL cond freg ',' freg comma
+ {
+ outcode($1, $2, &$3, int32($5.Reg), &nullgen);
+ }
+/*
+ * MCR MRC
+ */
+| LTYPEJ cond con ',' expr ',' spreg ',' creg ',' creg oexpr
+ {
+ var g obj.Addr
+
+ g = nullgen;
+ g.Type = D_CONST;
+ g.Offset = int64(
+ (0xe << 24) | /* opcode */
+ ($1 << 20) | /* MCR/MRC */
+ ($2 << 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, NREG, &g);
+ }
+/*
+ * MULL r1,r2,(hi,lo)
+ */
+| LTYPEM cond reg ',' reg ',' regreg
+ {
+ outcode($1, $2, &$3, int32($5.Reg), &$7);
+ }
+/*
+ * 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 = D_REGREG2;
+ $7.Offset = int64($9);
+ outcode($1, $2, &$3, int32($5.Reg), &$7);
+ }
+/*
+ * PLD
+ */
+| LTYPEPLD oreg
+ {
+ outcode($1, Always, &$2, NREG, &nullgen);
+ }
+/*
+ * PCDATA
+ */
+| LTYPEPC gen ',' gen
+ {
+ if $2.Type != D_CONST || $4.Type != D_CONST {
+ yyerror("arguments to PCDATA must be integer constants")
+ }
+ outcode($1, Always, &$2, NREG, &$4);
+ }
+/*
+ * FUNCDATA
+ */
+| LTYPEF gen ',' gen
+ {
+ if $2.Type != D_CONST {
+ yyerror("index for FUNCDATA must be integer constant")
+ }
+ if $4.Type != D_EXTERN && $4.Type != D_STATIC && $4.Type != D_OREG {
+ yyerror("value for FUNCDATA must be symbol reference")
+ }
+ outcode($1, Always, &$2, NREG, &$4);
+ }
+/*
+ * END
+ */
+| LTYPEE comma
+ {
+ outcode($1, Always, &nullgen, NREG, &nullgen);
+ }
+
+cond:
+ {
+ $$ = Always;
+ }
+| cond LCOND
+ {
+ $$ = ($1 & ^ C_SCOND) | $2;
+ }
+| cond LS
+ {
+ $$ = $1 | $2;
+ }
+
+comma:
+| ',' comma
+
+rel:
+ con '(' LPC ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_BRANCH;
+ $$.Offset = int64($1) + int64(asm.PC);
+ }
+| LNAME offset
+ {
+ $1 = asm.LabelLookup($1);
+ $$ = nullgen;
+ if asm.Pass == 2 && $1.Type != LLAB {
+ yyerror("undefined label: %s", $1.Labelname)
+ }
+ $$.Type = D_BRANCH;
+ $$.Offset = $1.Value + int64($2);
+ }
+
+ximm: '$' con
+ {
+ $$ = nullgen;
+ $$.Type = D_CONST;
+ $$.Offset = int64($2);
+ }
+| '$' oreg
+ {
+ $$ = $2;
+ $$.Type = D_CONST;
+ }
+| '$' '*' '$' oreg
+ {
+ $$ = $4;
+ $$.Type = D_OCONST;
+ }
+| '$' LSCONST
+ {
+ $$ = nullgen;
+ $$.Type = D_SCONST;
+ $$.U.Sval = $2
+ }
+| fcon
+
+fcon:
+ '$' LFCONST
+ {
+ $$ = nullgen;
+ $$.Type = D_FCONST;
+ $$.U.Dval = $2;
+ }
+| '$' '-' LFCONST
+ {
+ $$ = nullgen;
+ $$.Type = D_FCONST;
+ $$.U.Dval = -$3;
+ }
+
+reglist:
+ spreg
+ {
+ $$ = 1 << uint($1);
+ }
+| spreg '-' spreg
+ {
+ $$=0;
+ for i:=$1; i<=$3; i++ {
+ $$ |= 1<<uint(i)
+ }
+ for i:=$3; i<=$1; i++ {
+ $$ |= 1<<uint(i)
+ }
+ }
+| spreg comma reglist
+ {
+ $$ = (1<<uint($1)) | $3;
+ }
+
+gen:
+ reg
+| ximm
+| shift
+| shift '(' spreg ')'
+ {
+ $$ = $1;
+ $$.Reg = int8($3);
+ }
+| LPSR
+ {
+ $$ = nullgen;
+ $$.Type = D_PSR;
+ $$.Reg = int8($1);
+ }
+| LFCR
+ {
+ $$ = nullgen;
+ $$.Type = D_FPCR;
+ $$.Reg = int8($1);
+ }
+| con
+ {
+ $$ = nullgen;
+ $$.Type = D_OREG;
+ $$.Offset = int64($1);
+ }
+| oreg
+| freg
+
+nireg:
+ ireg
+| name
+ {
+ $$ = $1;
+ if($1.Name != D_EXTERN && $1.Name != D_STATIC) {
+ }
+ }
+
+ireg:
+ '(' spreg ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_OREG;
+ $$.Reg = int8($2);
+ $$.Offset = 0;
+ }
+
+ioreg:
+ ireg
+| con '(' sreg ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_OREG;
+ $$.Reg = int8($3);
+ $$.Offset = int64($1);
+ }
+
+oreg:
+ name
+| name '(' sreg ')'
+ {
+ $$ = $1;
+ $$.Type = D_OREG;
+ $$.Reg = int8($3);
+ }
+| ioreg
+
+imsr:
+ reg
+| imm
+| shift
+
+imm: '$' con
+ {
+ $$ = nullgen;
+ $$.Type = D_CONST;
+ $$.Offset = int64($2);
+ }
+
+reg:
+ spreg
+ {
+ $$ = nullgen;
+ $$.Type = D_REG;
+ $$.Reg = int8($1);
+ }
+
+regreg:
+ '(' spreg ',' spreg ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_REGREG;
+ $$.Reg = int8($2);
+ $$.Offset = int64($4);
+ }
+
+shift:
+ spreg '<' '<' rcon
+ {
+ $$ = nullgen;
+ $$.Type = D_SHIFT;
+ $$.Offset = int64($1) | int64($4) | (0 << 5);
+ }
+| spreg '>' '>' rcon
+ {
+ $$ = nullgen;
+ $$.Type = D_SHIFT;
+ $$.Offset = int64($1) | int64($4) | (1 << 5);
+ }
+| spreg '-' '>' rcon
+ {
+ $$ = nullgen;
+ $$.Type = D_SHIFT;
+ $$.Offset = int64($1) | int64($4) | (2 << 5);
+ }
+| spreg LAT '>' rcon
+ {
+ $$ = nullgen;
+ $$.Type = D_SHIFT;
+ $$.Offset = int64($1) | int64($4) | (3 << 5);
+ }
+
+rcon:
+ spreg
+ {
+ if $$ < 0 || $$ >= 16 {
+ print("register value out of range\n")
+ }
+ $$ = (($1&15) << 8) | (1 << 4);
+ }
+| con
+ {
+ if $$ < 0 || $$ >= 32 {
+ print("shift value out of range\n")
+ }
+ $$ = ($1&31) << 7;
+ }
+
+sreg:
+ LREG
+| LPC
+ {
+ $$ = REGPC;
+ }
+| LR '(' expr ')'
+ {
+ if $3 < 0 || $3 >= NREG {
+ print("register value out of range\n")
+ }
+ $$ = $3;
+ }
+
+spreg:
+ sreg
+| LSP
+ {
+ $$ = REGSP;
+ }
+
+creg:
+ LCREG
+| LC '(' expr ')'
+ {
+ if $3 < 0 || $3 >= NREG {
+ print("register value out of range\n")
+ }
+ $$ = $3;
+ }
+
+frcon:
+ freg
+| fcon
+
+freg:
+ LFREG
+ {
+ $$ = nullgen;
+ $$.Type = D_FREG;
+ $$.Reg = int8($1);
+ }
+| LF '(' con ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_FREG;
+ $$.Reg = int8($3);
+ }
+
+name:
+ con '(' pointer ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_OREG;
+ $$.Name = int8($3);
+ $$.Sym = nil;
+ $$.Offset = int64($1);
+ }
+| LNAME offset '(' pointer ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_OREG;
+ $$.Name = int8($4);
+ $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
+ $$.Offset = int64($2);
+ }
+| LNAME '<' '>' offset '(' LSB ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_OREG;
+ $$.Name = D_STATIC;
+ $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
+ $$.Offset = int64($4);
+ }
+
+offset:
+ {
+ $$ = 0;
+ }
+| '+' con
+ {
+ $$ = $2;
+ }
+| '-' con
+ {
+ $$ = -$2;
+ }
+
+pointer:
+ LSB
+| LSP
+| LFP
+
+con:
+ LCONST
+| LVAR
+ {
+ $$ = int32($1.Value);
+ }
+| '-' con
+ {
+ $$ = -$2;
+ }
+| '+' con
+ {
+ $$ = $2;
+ }
+| '~' con
+ {
+ $$ = ^$2;
+ }
+| '(' expr ')'
+ {
+ $$ = $2;
+ }
+
+oexpr:
+ {
+ $$ = 0;
+ }
+| ',' expr
+ {
+ $$ = $2;
+ }
+
+expr:
+ con
+| expr '+' expr
+ {
+ $$ = $1 + $3;
+ }
+| expr '-' expr
+ {
+ $$ = $1 - $3;
+ }
+| expr '*' expr
+ {
+ $$ = $1 * $3;
+ }
+| expr '/' expr
+ {
+ $$ = $1 / $3;
+ }
+| expr '%' expr
+ {
+ $$ = $1 % $3;
+ }
+| expr '<' '<' expr
+ {
+ $$ = $1 << uint($4);
+ }
+| expr '>' '>' expr
+ {
+ $$ = $1 >> uint($4);
+ }
+| expr '&' expr
+ {
+ $$ = $1 & $3;
+ }
+| expr '^' expr
+ {
+ $$ = $1 ^ $3;
+ }
+| expr '|' expr
+ {
+ $$ = $1 | $3;
+ }
--- /dev/null
+// Inferno utils/5a/lex.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5a/lex.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+//go:generate go tool yacc a.y
+
+package main
+
+import (
+ "cmd/internal/asm"
+ "cmd/internal/obj"
+ "cmd/internal/obj/arm"
+)
+
+var (
+ yyerror = asm.Yyerror
+ nullgen obj.Addr
+ stmtline int32
+)
+
+const Always = 14
+
+func main() {
+ cinit()
+
+ asm.LSCONST = LSCONST
+ asm.LCONST = LCONST
+ asm.LFCONST = LFCONST
+ asm.LNAME = LNAME
+ asm.LVAR = LVAR
+ asm.LLAB = LLAB
+
+ asm.Lexinit = lexinit
+ asm.Cclean = cclean
+ asm.Yyparse = yyparse
+
+ asm.Thechar = '5'
+ asm.Thestring = "arm"
+ asm.Thelinkarch = &arm.Linkarm
+
+ asm.Main()
+}
+
+type yy struct{}
+
+func (yy) Lex(v *yySymType) int {
+ var av asm.Yylval
+ tok := asm.Yylex(&av)
+ v.sym = av.Sym
+ v.lval = int32(av.Lval)
+ v.sval = av.Sval
+ v.dval = av.Dval
+ return tok
+}
+
+func (yy) Error(msg string) {
+ asm.Yyerror("%s", msg)
+}
+
+func yyparse() {
+ yyParse(yy{})
+}
+
+var lexinit = []asm.Lextab{
+ {"SP", LSP, arm.D_AUTO},
+ {"SB", LSB, arm.D_EXTERN},
+ {"FP", LFP, arm.D_PARAM},
+ {"PC", LPC, arm.D_BRANCH},
+ {"R", LR, 0},
+ {"R0", LREG, 0},
+ {"R1", LREG, 1},
+ {"R2", LREG, 2},
+ {"R3", LREG, 3},
+ {"R4", LREG, 4},
+ {"R5", LREG, 5},
+ {"R6", LREG, 6},
+ {"R7", LREG, 7},
+ {"R8", LREG, 8},
+ {"R9", LREG, 9},
+ {"g", LREG, 10}, // avoid unintentionally clobber g using R10
+ {"R11", LREG, 11},
+ {"R12", LREG, 12},
+ {"R13", LREG, 13},
+ {"R14", LREG, 14},
+ {"R15", LREG, 15},
+ {"F", LF, 0},
+ {"F0", LFREG, 0},
+ {"F1", LFREG, 1},
+ {"F2", LFREG, 2},
+ {"F3", LFREG, 3},
+ {"F4", LFREG, 4},
+ {"F5", LFREG, 5},
+ {"F6", LFREG, 6},
+ {"F7", LFREG, 7},
+ {"F8", LFREG, 8},
+ {"F9", LFREG, 9},
+ {"F10", LFREG, 10},
+ {"F11", LFREG, 11},
+ {"F12", LFREG, 12},
+ {"F13", LFREG, 13},
+ {"F14", LFREG, 14},
+ {"F15", LFREG, 15},
+ {"C", LC, 0},
+ {"C0", LCREG, 0},
+ {"C1", LCREG, 1},
+ {"C2", LCREG, 2},
+ {"C3", LCREG, 3},
+ {"C4", LCREG, 4},
+ {"C5", LCREG, 5},
+ {"C6", LCREG, 6},
+ {"C7", LCREG, 7},
+ {"C8", LCREG, 8},
+ {"C9", LCREG, 9},
+ {"C10", LCREG, 10},
+ {"C11", LCREG, 11},
+ {"C12", LCREG, 12},
+ {"C13", LCREG, 13},
+ {"C14", LCREG, 14},
+ {"C15", LCREG, 15},
+ {"CPSR", LPSR, 0},
+ {"SPSR", LPSR, 1},
+ {"FPSR", LFCR, 0},
+ {"FPCR", LFCR, 1},
+ {".EQ", LCOND, 0},
+ {".NE", LCOND, 1},
+ {".CS", LCOND, 2},
+ {".HS", LCOND, 2},
+ {".CC", LCOND, 3},
+ {".LO", LCOND, 3},
+ {".MI", LCOND, 4},
+ {".PL", LCOND, 5},
+ {".VS", LCOND, 6},
+ {".VC", LCOND, 7},
+ {".HI", LCOND, 8},
+ {".LS", LCOND, 9},
+ {".GE", LCOND, 10},
+ {".LT", LCOND, 11},
+ {".GT", LCOND, 12},
+ {".LE", LCOND, 13},
+ {".AL", LCOND, Always},
+ {".U", LS, arm.C_UBIT},
+ {".S", LS, arm.C_SBIT},
+ {".W", LS, arm.C_WBIT},
+ {".P", LS, arm.C_PBIT},
+ {".PW", LS, arm.C_WBIT | arm.C_PBIT},
+ {".WP", LS, arm.C_WBIT | arm.C_PBIT},
+ {".F", LS, arm.C_FBIT},
+ {".IBW", LS, arm.C_WBIT | arm.C_PBIT | arm.C_UBIT},
+ {".IAW", LS, arm.C_WBIT | arm.C_UBIT},
+ {".DBW", LS, arm.C_WBIT | arm.C_PBIT},
+ {".DAW", LS, arm.C_WBIT},
+ {".IB", LS, arm.C_PBIT | arm.C_UBIT},
+ {".IA", LS, arm.C_UBIT},
+ {".DB", LS, arm.C_PBIT},
+ {".DA", LS, 0},
+ {"@", LAT, 0},
+ {"AND", LTYPE1, arm.AAND},
+ {"EOR", LTYPE1, arm.AEOR},
+ {"SUB", LTYPE1, arm.ASUB},
+ {"RSB", LTYPE1, arm.ARSB},
+ {"ADD", LTYPE1, arm.AADD},
+ {"ADC", LTYPE1, arm.AADC},
+ {"SBC", LTYPE1, arm.ASBC},
+ {"RSC", LTYPE1, arm.ARSC},
+ {"ORR", LTYPE1, arm.AORR},
+ {"BIC", LTYPE1, arm.ABIC},
+ {"SLL", LTYPE1, arm.ASLL},
+ {"SRL", LTYPE1, arm.ASRL},
+ {"SRA", LTYPE1, arm.ASRA},
+ {"MUL", LTYPE1, arm.AMUL},
+ {"MULA", LTYPEN, arm.AMULA},
+ {"DIV", LTYPE1, arm.ADIV},
+ {"MOD", LTYPE1, arm.AMOD},
+ {"MULL", LTYPEM, arm.AMULL},
+ {"MULAL", LTYPEM, arm.AMULAL},
+ {"MULLU", LTYPEM, arm.AMULLU},
+ {"MULALU", LTYPEM, arm.AMULALU},
+ {"MVN", LTYPE2, arm.AMVN}, /* op2 ignored */
+ {"MOVB", LTYPE3, arm.AMOVB},
+ {"MOVBU", LTYPE3, arm.AMOVBU},
+ {"MOVH", LTYPE3, arm.AMOVH},
+ {"MOVHU", LTYPE3, arm.AMOVHU},
+ {"MOVW", LTYPE3, arm.AMOVW},
+ {"MOVD", LTYPE3, arm.AMOVD},
+ {"MOVDF", LTYPE3, arm.AMOVDF},
+ {"MOVDW", LTYPE3, arm.AMOVDW},
+ {"MOVF", LTYPE3, arm.AMOVF},
+ {"MOVFD", LTYPE3, arm.AMOVFD},
+ {"MOVFW", LTYPE3, arm.AMOVFW},
+ {"MOVWD", LTYPE3, arm.AMOVWD},
+ {"MOVWF", LTYPE3, arm.AMOVWF},
+ {"LDREX", LTYPE3, arm.ALDREX},
+ {"LDREXD", LTYPE3, arm.ALDREXD},
+ {"STREX", LTYPE9, arm.ASTREX},
+ {"STREXD", LTYPE9, arm.ASTREXD},
+
+ /*
+ {"NEGF", LTYPEI, ANEGF},
+ {"NEGD", LTYPEI, ANEGD},
+ {"SQTF", LTYPEI, ASQTF},
+ {"SQTD", LTYPEI, ASQTD},
+ {"RNDF", LTYPEI, ARNDF},
+ {"RNDD", LTYPEI, ARNDD},
+ {"URDF", LTYPEI, AURDF},
+ {"URDD", LTYPEI, AURDD},
+ {"NRMF", LTYPEI, ANRMF},
+ {"NRMD", LTYPEI, ANRMD},
+ */
+ {"ABSF", LTYPEI, arm.AABSF},
+ {"ABSD", LTYPEI, arm.AABSD},
+ {"SQRTF", LTYPEI, arm.ASQRTF},
+ {"SQRTD", LTYPEI, arm.ASQRTD},
+ {"CMPF", LTYPEL, arm.ACMPF},
+ {"CMPD", LTYPEL, arm.ACMPD},
+ {"ADDF", LTYPEK, arm.AADDF},
+ {"ADDD", LTYPEK, arm.AADDD},
+ {"SUBF", LTYPEK, arm.ASUBF},
+ {"SUBD", LTYPEK, arm.ASUBD},
+ {"MULF", LTYPEK, arm.AMULF},
+ {"MULD", LTYPEK, arm.AMULD},
+ {"DIVF", LTYPEK, arm.ADIVF},
+ {"DIVD", LTYPEK, arm.ADIVD},
+ {"B", LTYPE4, arm.AB},
+ {"BL", LTYPE4, arm.ABL},
+ {"BX", LTYPEBX, arm.ABX},
+ {"BEQ", LTYPE5, arm.ABEQ},
+ {"BNE", LTYPE5, arm.ABNE},
+ {"BCS", LTYPE5, arm.ABCS},
+ {"BHS", LTYPE5, arm.ABHS},
+ {"BCC", LTYPE5, arm.ABCC},
+ {"BLO", LTYPE5, arm.ABLO},
+ {"BMI", LTYPE5, arm.ABMI},
+ {"BPL", LTYPE5, arm.ABPL},
+ {"BVS", LTYPE5, arm.ABVS},
+ {"BVC", LTYPE5, arm.ABVC},
+ {"BHI", LTYPE5, arm.ABHI},
+ {"BLS", LTYPE5, arm.ABLS},
+ {"BGE", LTYPE5, arm.ABGE},
+ {"BLT", LTYPE5, arm.ABLT},
+ {"BGT", LTYPE5, arm.ABGT},
+ {"BLE", LTYPE5, arm.ABLE},
+ {"BCASE", LTYPE5, arm.ABCASE},
+ {"SWI", LTYPE6, arm.ASWI},
+ {"CMP", LTYPE7, arm.ACMP},
+ {"TST", LTYPE7, arm.ATST},
+ {"TEQ", LTYPE7, arm.ATEQ},
+ {"CMN", LTYPE7, arm.ACMN},
+ {"MOVM", LTYPE8, arm.AMOVM},
+ {"SWPBU", LTYPE9, arm.ASWPBU},
+ {"SWPW", LTYPE9, arm.ASWPW},
+ {"RET", LTYPEA, arm.ARET},
+ {"RFE", LTYPEA, arm.ARFE},
+ {"TEXT", LTYPEB, arm.ATEXT},
+ {"GLOBL", LTYPEB, arm.AGLOBL},
+ {"DATA", LTYPEC, arm.ADATA},
+ {"CASE", LTYPED, arm.ACASE},
+ {"END", LTYPEE, arm.AEND},
+ {"WORD", LTYPEH, arm.AWORD},
+ {"NOP", LTYPEI, arm.ANOP},
+ {"MCR", LTYPEJ, 0},
+ {"MRC", LTYPEJ, 1},
+ {"PLD", LTYPEPLD, arm.APLD},
+ {"UNDEF", LTYPEE, arm.AUNDEF},
+ {"CLZ", LTYPE2, arm.ACLZ},
+ {"MULWT", LTYPE1, arm.AMULWT},
+ {"MULWB", LTYPE1, arm.AMULWB},
+ {"MULAWT", LTYPEN, arm.AMULAWT},
+ {"MULAWB", LTYPEN, arm.AMULAWB},
+ {"USEFIELD", LTYPEN, arm.AUSEFIELD},
+ {"PCDATA", LTYPEPC, arm.APCDATA},
+ {"FUNCDATA", LTYPEF, arm.AFUNCDATA},
+}
+
+func cinit() {
+ nullgen.Type = arm.D_NONE
+ nullgen.Name = arm.D_NONE
+ nullgen.Reg = arm.NREG
+}
+
+func isreg(g *obj.Addr) bool {
+ return true
+}
+
+func cclean() {
+ outcode(arm.AEND, Always, &nullgen, arm.NREG, &nullgen)
+}
+
+var bcode = []int{
+ arm.ABEQ,
+ arm.ABNE,
+ arm.ABCS,
+ arm.ABCC,
+ arm.ABMI,
+ arm.ABPL,
+ arm.ABVS,
+ arm.ABVC,
+ arm.ABHI,
+ arm.ABLS,
+ arm.ABGE,
+ arm.ABLT,
+ arm.ABGT,
+ arm.ABLE,
+ arm.AB,
+ arm.ANOP,
+}
+
+var lastpc *obj.Prog
+
+func outcode(a, scond int32, g1 *obj.Addr, reg int32, g2 *obj.Addr) {
+ var p *obj.Prog
+ var pl *obj.Plist
+
+ /* hack to make B.NE etc. work: turn it into the corresponding conditional */
+ if a == arm.AB {
+ a = int32(bcode[scond&0xf])
+ scond = (scond &^ 0xf) | Always
+ }
+
+ if asm.Pass == 1 {
+ goto out
+ }
+
+ p = new(obj.Prog)
+ *p = obj.Prog{}
+ p.Ctxt = asm.Ctxt
+ p.As = int16(a)
+ p.Lineno = stmtline
+ p.Scond = uint8(scond)
+ p.From = *g1
+ p.Reg = uint8(reg)
+ p.To = *g2
+ p.Pc = int64(asm.PC)
+
+ if lastpc == nil {
+ pl = obj.Linknewplist(asm.Ctxt)
+ pl.Firstpc = p
+ } else {
+ lastpc.Link = p
+ }
+ lastpc = p
+
+out:
+ if a != arm.AGLOBL && a != arm.ADATA {
+ asm.PC++
+ }
+}
--- /dev/null
+//line a.y:32
+package main
+
+import __yyfmt__ "fmt"
+
+//line a.y:32
+import (
+ "cmd/internal/asm"
+ "cmd/internal/obj"
+ . "cmd/internal/obj/arm"
+)
+
+//line a.y:41
+type yySymType struct {
+ yys int
+ sym *asm.Sym
+ lval int32
+ dval float64
+ sval string
+ addr obj.Addr
+}
+
+const LTYPE1 = 57346
+const LTYPE2 = 57347
+const LTYPE3 = 57348
+const LTYPE4 = 57349
+const LTYPE5 = 57350
+const LTYPE6 = 57351
+const LTYPE7 = 57352
+const LTYPE8 = 57353
+const LTYPE9 = 57354
+const LTYPEA = 57355
+const LTYPEB = 57356
+const LTYPEC = 57357
+const LTYPED = 57358
+const LTYPEE = 57359
+const LTYPEG = 57360
+const LTYPEH = 57361
+const LTYPEI = 57362
+const LTYPEJ = 57363
+const LTYPEK = 57364
+const LTYPEL = 57365
+const LTYPEM = 57366
+const LTYPEN = 57367
+const LTYPEBX = 57368
+const LTYPEPLD = 57369
+const LCONST = 57370
+const LSP = 57371
+const LSB = 57372
+const LFP = 57373
+const LPC = 57374
+const LTYPEX = 57375
+const LTYPEPC = 57376
+const LTYPEF = 57377
+const LR = 57378
+const LREG = 57379
+const LF = 57380
+const LFREG = 57381
+const LC = 57382
+const LCREG = 57383
+const LPSR = 57384
+const LFCR = 57385
+const LCOND = 57386
+const LS = 57387
+const LAT = 57388
+const LFCONST = 57389
+const LSCONST = 57390
+const LNAME = 57391
+const LLAB = 57392
+const LVAR = 57393
+
+var yyToknames = []string{
+ "'|'",
+ "'^'",
+ "'&'",
+ "'<'",
+ "'>'",
+ "'+'",
+ "'-'",
+ "'*'",
+ "'/'",
+ "'%'",
+ "LTYPE1",
+ "LTYPE2",
+ "LTYPE3",
+ "LTYPE4",
+ "LTYPE5",
+ "LTYPE6",
+ "LTYPE7",
+ "LTYPE8",
+ "LTYPE9",
+ "LTYPEA",
+ "LTYPEB",
+ "LTYPEC",
+ "LTYPED",
+ "LTYPEE",
+ "LTYPEG",
+ "LTYPEH",
+ "LTYPEI",
+ "LTYPEJ",
+ "LTYPEK",
+ "LTYPEL",
+ "LTYPEM",
+ "LTYPEN",
+ "LTYPEBX",
+ "LTYPEPLD",
+ "LCONST",
+ "LSP",
+ "LSB",
+ "LFP",
+ "LPC",
+ "LTYPEX",
+ "LTYPEPC",
+ "LTYPEF",
+ "LR",
+ "LREG",
+ "LF",
+ "LFREG",
+ "LC",
+ "LCREG",
+ "LPSR",
+ "LFCR",
+ "LCOND",
+ "LS",
+ "LAT",
+ "LFCONST",
+ "LSCONST",
+ "LNAME",
+ "LLAB",
+ "LVAR",
+}
+var yyStatenames = []string{}
+
+const yyEofCode = 1
+const yyErrCode = 2
+const yyMaxDepth = 200
+
+//line yacctab:1
+var yyExca = []int{
+ -1, 1,
+ 1, -1,
+ -2, 2,
+ -1, 194,
+ 67, 59,
+ -2, 48,
+}
+
+const yyNprod = 130
+const yyPrivate = 57344
+
+var yyTokenNames []string
+var yyStates []string
+
+const yyLast = 694
+
+var yyAct = []int{
+
+ 123, 317, 71, 83, 98, 104, 200, 77, 82, 193,
+ 89, 127, 271, 73, 113, 85, 3, 106, 227, 134,
+ 327, 88, 87, 313, 76, 52, 52, 101, 102, 293,
+ 283, 278, 84, 84, 270, 72, 81, 81, 70, 69,
+ 84, 84, 84, 142, 269, 268, 81, 257, 84, 220,
+ 114, 118, 323, 120, 310, 97, 99, 110, 75, 51,
+ 60, 131, 132, 133, 103, 103, 294, 138, 140, 143,
+ 137, 144, 103, 90, 121, 149, 92, 204, 111, 246,
+ 93, 91, 112, 148, 195, 188, 136, 163, 101, 102,
+ 156, 94, 145, 146, 157, 162, 43, 45, 151, 147,
+ 108, 126, 302, 251, 106, 252, 62, 101, 102, 57,
+ 56, 179, 149, 165, 184, 250, 95, 84, 44, 329,
+ 194, 81, 322, 186, 182, 109, 320, 189, 316, 116,
+ 199, 198, 122, 124, 206, 207, 197, 314, 54, 90,
+ 209, 300, 92, 299, 44, 296, 93, 91, 187, 289,
+ 286, 84, 222, 282, 260, 81, 256, 255, 218, 219,
+ 44, 55, 217, 216, 215, 84, 131, 229, 59, 81,
+ 214, 58, 212, 90, 211, 190, 92, 196, 192, 242,
+ 93, 91, 84, 230, 191, 181, 81, 232, 233, 234,
+ 235, 236, 249, 180, 239, 240, 241, 247, 178, 44,
+ 164, 150, 125, 243, 86, 244, 219, 38, 37, 221,
+ 254, 258, 34, 35, 36, 261, 262, 259, 264, 210,
+ 57, 56, 228, 231, 272, 272, 272, 272, 273, 273,
+ 273, 273, 72, 248, 213, 265, 277, 274, 275, 276,
+ 245, 266, 267, 306, 57, 161, 158, 319, 318, 54,
+ 135, 194, 305, 287, 194, 88, 87, 280, 281, 238,
+ 285, 78, 292, 288, 226, 101, 102, 90, 295, 141,
+ 92, 225, 55, 54, 93, 91, 224, 253, 100, 59,
+ 291, 160, 58, 57, 56, 152, 153, 205, 154, 303,
+ 237, 120, 160, 159, 53, 223, 55, 88, 263, 308,
+ 307, 105, 105, 74, 129, 130, 58, 301, 7, 105,
+ 312, 315, 54, 96, 304, 90, 2, 321, 92, 107,
+ 1, 324, 93, 91, 325, 311, 117, 183, 101, 102,
+ 101, 102, 284, 139, 155, 55, 309, 290, 8, 328,
+ 119, 44, 74, 326, 0, 58, 0, 297, 0, 331,
+ 9, 10, 11, 12, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 33, 0, 23, 24, 27, 25, 26,
+ 28, 29, 13, 30, 57, 56, 202, 201, 203, 248,
+ 31, 32, 176, 175, 174, 172, 173, 167, 168, 169,
+ 170, 171, 88, 87, 0, 4, 0, 5, 101, 102,
+ 6, 57, 56, 54, 90, 92, 0, 92, 0, 93,
+ 91, 93, 91, 88, 87, 0, 0, 79, 80, 101,
+ 102, 202, 201, 203, 53, 0, 55, 169, 170, 171,
+ 54, 90, 0, 74, 92, 85, 58, 0, 93, 91,
+ 88, 87, 0, 0, 79, 80, 128, 330, 129, 130,
+ 0, 53, 0, 55, 0, 57, 56, 0, 0, 0,
+ 74, 0, 85, 58, 176, 175, 174, 172, 173, 167,
+ 168, 169, 170, 171, 176, 175, 174, 172, 173, 167,
+ 168, 169, 170, 171, 54, 0, 57, 56, 0, 0,
+ 57, 56, 0, 0, 57, 56, 202, 201, 203, 92,
+ 0, 0, 0, 93, 91, 53, 0, 55, 57, 56,
+ 0, 0, 57, 56, 74, 54, 0, 58, 0, 54,
+ 0, 57, 56, 54, 0, 57, 56, 0, 0, 279,
+ 0, 0, 0, 0, 228, 0, 0, 54, 55, 208,
+ 0, 54, 55, 0, 185, 59, 55, 0, 58, 59,
+ 54, 106, 58, 74, 54, 0, 58, 0, 115, 0,
+ 55, 0, 53, 0, 55, 0, 0, 59, 0, 0,
+ 58, 59, 0, 55, 58, 0, 0, 55, 0, 0,
+ 59, 0, 0, 58, 74, 0, 0, 58, 176, 175,
+ 174, 172, 173, 167, 168, 169, 170, 171, 176, 175,
+ 174, 172, 173, 167, 168, 169, 170, 171, 176, 175,
+ 174, 172, 173, 167, 168, 169, 170, 171, 90, 0,
+ 0, 92, 0, 0, 0, 93, 91, 39, 167, 168,
+ 169, 170, 171, 101, 102, 0, 0, 0, 40, 41,
+ 42, 0, 0, 46, 47, 48, 49, 50, 0, 298,
+ 61, 0, 63, 64, 65, 66, 67, 68, 177, 175,
+ 174, 172, 173, 167, 168, 169, 170, 171, 166, 176,
+ 175, 174, 172, 173, 167, 168, 169, 170, 171, 174,
+ 172, 173, 167, 168, 169, 170, 171, 172, 173, 167,
+ 168, 169, 170, 171,
+}
+var yyPact = []int{
+
+ -1000, -1000, 336, -1000, 150, 151, -1000, 144, 143, -1000,
+ -1000, -1000, -1000, 79, 79, -1000, -1000, -1000, -1000, -1000,
+ 503, 503, -1000, 79, -1000, -1000, -1000, -1000, -1000, -1000,
+ 446, 392, 392, 79, -1000, 512, 512, -1000, -1000, 34,
+ 34, 365, 53, 10, 79, 499, 53, 34, 274, 276,
+ 53, 137, 33, 439, -1000, -1000, 512, 512, 512, 512,
+ 238, 579, -55, 344, -27, 344, 211, 579, 579, -1000,
+ 31, -1000, 15, -1000, 100, 136, -1000, -1000, 30, -1000,
+ -1000, 15, -1000, -1000, 278, 235, -1000, -1000, 27, -1000,
+ -1000, -1000, -1000, 19, 135, -1000, 336, 604, -1000, 594,
+ 133, -1000, -1000, -1000, -1000, -1000, 512, 128, 120, 485,
+ -1000, 228, -1000, -1000, 17, 295, 392, 119, 113, 228,
+ 16, 112, 10, -1000, -1000, 481, 382, 9, 279, 512,
+ 512, -1000, -1000, -1000, 470, 512, 79, -1000, 109, 107,
+ -1000, -1000, 224, 105, 99, 98, 97, 363, 457, -20,
+ 392, 228, 288, 268, 263, 256, 15, -1000, -52, -1000,
+ -1000, 477, 512, 512, 392, -1000, -1000, 512, 512, 512,
+ 512, 512, 283, 251, 512, 512, 512, -1000, 228, -1000,
+ 228, 392, -1000, -1000, 11, 439, -1000, -1000, 191, -1000,
+ -1000, 228, 49, 36, 95, 363, 10, 92, -1000, 91,
+ -22, -1000, -1000, -1000, 382, 295, -1000, -1000, -1000, 89,
+ -1000, 207, 249, 165, 207, 512, 228, 228, -24, -25,
+ -1000, -1000, -35, 100, 100, 100, 100, 446, -1000, -38,
+ 460, -1000, 416, 416, -1000, -1000, -1000, 512, 512, 680,
+ 673, 654, 88, -1000, -1000, -1000, 337, 9, -39, 79,
+ 228, 85, 228, 228, 84, 228, -53, -1000, -40, -2,
+ -55, -1000, -1000, 80, 79, 584, 78, 76, -1000, -1000,
+ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
+ 619, 619, 228, -1000, -1000, 35, 516, -1000, -1000, 134,
+ -1000, -1000, 242, -1000, 203, -1000, 207, -1000, 228, -14,
+ 228, -1000, -1000, -1000, -1000, 512, -46, -1000, 72, -1000,
+ 228, 63, -1000, -1000, 197, 61, 228, 57, -1000, -16,
+ 228, -1000, 197, 512, -49, 54, 378, -1000, -1000, 512,
+ -1000, 665,
+}
+var yyPgo = []int{
+
+ 0, 4, 19, 339, 6, 11, 10, 0, 1, 12,
+ 627, 9, 58, 14, 24, 336, 3, 261, 204, 333,
+ 5, 7, 38, 8, 13, 327, 2, 278, 320, 316,
+ 16, 313, 308, 82,
+}
+var yyR1 = []int{
+
+ 0, 28, 29, 28, 31, 30, 30, 30, 30, 30,
+ 30, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 10, 10, 10, 33, 33,
+ 13, 13, 21, 21, 21, 21, 21, 18, 18, 11,
+ 11, 11, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 25, 25, 24, 26, 26, 23, 23, 23, 27,
+ 27, 27, 20, 14, 15, 17, 17, 17, 17, 9,
+ 9, 6, 6, 6, 7, 7, 8, 8, 19, 19,
+ 16, 16, 22, 22, 22, 5, 5, 5, 4, 4,
+ 4, 1, 1, 1, 1, 1, 1, 3, 3, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+}
+var yyR2 = []int{
+
+ 0, 0, 0, 3, 0, 4, 4, 4, 1, 2,
+ 2, 7, 6, 5, 5, 5, 4, 4, 3, 3,
+ 4, 6, 7, 7, 7, 6, 6, 3, 4, 6,
+ 8, 6, 4, 3, 5, 5, 7, 6, 12, 7,
+ 9, 2, 4, 4, 2, 0, 2, 2, 0, 2,
+ 4, 2, 2, 2, 4, 2, 1, 2, 3, 1,
+ 3, 3, 1, 1, 1, 4, 1, 1, 1, 1,
+ 1, 1, 1, 3, 1, 4, 1, 4, 1, 1,
+ 1, 1, 2, 1, 5, 4, 4, 4, 4, 1,
+ 1, 1, 1, 4, 1, 1, 1, 4, 1, 1,
+ 1, 4, 4, 5, 7, 0, 2, 2, 1, 1,
+ 1, 1, 1, 2, 2, 2, 3, 0, 2, 1,
+ 3, 3, 3, 3, 3, 4, 4, 3, 3, 3,
+}
+var yyChk = []int{
+
+ -1000, -28, -29, -30, 59, 61, 64, -32, 2, 14,
+ 15, 16, 17, 36, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 29, 30, 32, 33, 31, 34, 35,
+ 37, 44, 45, 27, 62, 63, 63, 64, 64, -10,
+ -10, -10, -10, -33, 65, -33, -10, -10, -10, -10,
+ -10, -22, -1, 59, 38, 61, 10, 9, 71, 68,
+ -22, -10, -33, -10, -10, -10, -10, -10, -10, -23,
+ -22, -26, -1, -24, 68, -12, -14, -21, -17, 52,
+ 53, -1, -23, -16, -7, 70, -18, 49, 48, -6,
+ 39, 47, 42, 46, -12, -33, -31, -2, -1, -2,
+ -27, 54, 55, -14, -20, -17, 70, -27, -12, -33,
+ -24, 68, -33, -13, -1, 59, -33, -27, -26, 66,
+ -1, -14, -33, -7, -33, 65, 68, -5, 7, 9,
+ 10, -1, -1, -1, -2, 12, -14, -21, -16, -19,
+ -16, -18, 70, -16, -1, -14, -14, 68, 68, -7,
+ 65, 68, 7, 8, 10, 56, -1, -23, 11, 58,
+ 57, 10, 68, 68, 65, -30, 64, 9, 10, 11,
+ 12, 13, 7, 8, 6, 5, 4, 64, 65, -1,
+ 65, 65, -13, -25, -1, 59, -24, -22, 68, -5,
+ -12, 65, 65, -11, -7, 68, 65, -24, -20, -1,
+ -4, 40, 39, 41, 68, 8, -1, -1, 69, -1,
+ -33, 65, 65, 10, 65, 65, 65, 65, -6, -6,
+ 69, -12, -7, 7, 8, 8, 8, 70, 57, -1,
+ -2, -12, -2, -2, -2, -2, -2, 7, 8, -2,
+ -2, -2, -7, -14, -14, -12, 68, -5, 42, -7,
+ 66, 67, 10, -33, -24, 65, 65, 69, -4, -5,
+ 65, -16, -16, 49, -16, -2, -14, -14, 69, 69,
+ 69, -9, -7, -1, -9, -9, -9, -23, 69, 69,
+ -2, -2, 65, 69, -33, -11, 65, -7, -11, 65,
+ -33, -14, -20, 69, 68, -21, 65, -33, 65, 65,
+ 65, -14, 67, -26, -14, 10, 40, -16, -7, -15,
+ 68, -14, -1, 69, 65, -7, 65, -8, 51, 50,
+ 65, -7, 65, 68, -7, -8, -2, 69, -3, 65,
+ 69, -2,
+}
+var yyDef = []int{
+
+ 1, -2, 0, 3, 0, 0, 8, 0, 0, 45,
+ 45, 45, 45, 48, 48, 45, 45, 45, 45, 45,
+ 0, 0, 45, 48, 45, 45, 45, 45, 45, 45,
+ 0, 0, 0, 48, 4, 0, 0, 9, 10, 0,
+ 0, 0, 48, 0, 48, 0, 48, 0, 0, 48,
+ 48, 0, 0, 105, 111, 112, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 41,
+ 76, 78, 0, 74, 0, 0, 62, 63, 64, 66,
+ 67, 68, 69, 70, 83, 0, 56, 100, 0, 94,
+ 95, 91, 92, 0, 0, 44, 0, 0, 119, 0,
+ 0, 46, 47, 79, 80, 81, 0, 0, 0, 0,
+ 18, 0, 49, 19, 0, 105, 0, 0, 0, 0,
+ 0, 0, 0, 83, 27, 0, 0, 0, 0, 0,
+ 0, 113, 114, 115, 0, 0, 48, 33, 0, 0,
+ 98, 99, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 52, 53, 0, 55,
+ 57, 0, 0, 0, 0, 5, 6, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 7, 0, 82,
+ 0, 0, 16, 17, 0, 105, 71, 72, 0, 51,
+ 20, 0, 0, 0, -2, 0, 0, 0, 28, 0,
+ 0, 108, 109, 110, 0, 105, 106, 107, 116, 0,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 73, 42, 0, 0, 0, 0, 0, 0, 58, 0,
+ 0, 43, 120, 121, 122, 123, 124, 0, 0, 127,
+ 128, 129, 83, 13, 14, 15, 0, 51, 0, 48,
+ 0, 0, 0, 0, 48, 0, 0, 102, 0, 0,
+ 0, 34, 35, 100, 48, 0, 0, 0, 77, 75,
+ 65, 85, 89, 90, 86, 87, 88, 54, 101, 93,
+ 125, 126, 12, 50, 21, 0, 0, 60, 61, 48,
+ 25, 26, 29, 103, 0, 31, 0, 37, 0, 0,
+ 0, 11, 22, 23, 24, 0, 0, 36, 0, 39,
+ 0, 0, 30, 104, 0, 0, 0, 0, 96, 0,
+ 0, 40, 0, 0, 0, 117, 0, 84, 38, 0,
+ 97, 118,
+}
+var yyTok1 = []int{
+
+ 1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 70, 13, 6, 3,
+ 68, 69, 11, 9, 65, 10, 3, 12, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 62, 64,
+ 7, 63, 8, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 66, 3, 67, 5, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 4, 3, 71,
+}
+var yyTok2 = []int{
+
+ 2, 3, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+}
+var yyTok3 = []int{
+ 0,
+}
+
+//line yaccpar:1
+
+/* parser for yacc output */
+
+var yyDebug = 0
+
+type yyLexer interface {
+ Lex(lval *yySymType) int
+ Error(s string)
+}
+
+const yyFlag = -1000
+
+func yyTokname(c int) string {
+ // 4 is TOKSTART above
+ if c >= 4 && c-4 < len(yyToknames) {
+ if yyToknames[c-4] != "" {
+ return yyToknames[c-4]
+ }
+ }
+ return __yyfmt__.Sprintf("tok-%v", c)
+}
+
+func yyStatname(s int) string {
+ if s >= 0 && s < len(yyStatenames) {
+ if yyStatenames[s] != "" {
+ return yyStatenames[s]
+ }
+ }
+ return __yyfmt__.Sprintf("state-%v", s)
+}
+
+func yylex1(lex yyLexer, lval *yySymType) int {
+ c := 0
+ char := lex.Lex(lval)
+ if char <= 0 {
+ c = yyTok1[0]
+ goto out
+ }
+ if char < len(yyTok1) {
+ c = yyTok1[char]
+ goto out
+ }
+ if char >= yyPrivate {
+ if char < yyPrivate+len(yyTok2) {
+ c = yyTok2[char-yyPrivate]
+ goto out
+ }
+ }
+ for i := 0; i < len(yyTok3); i += 2 {
+ c = yyTok3[i+0]
+ if c == char {
+ c = yyTok3[i+1]
+ goto out
+ }
+ }
+
+out:
+ if c == 0 {
+ c = yyTok2[1] /* unknown char */
+ }
+ if yyDebug >= 3 {
+ __yyfmt__.Printf("lex %s(%d)\n", yyTokname(c), uint(char))
+ }
+ return c
+}
+
+func yyParse(yylex yyLexer) int {
+ var yyn int
+ var yylval yySymType
+ var yyVAL yySymType
+ yyS := make([]yySymType, yyMaxDepth)
+
+ Nerrs := 0 /* number of errors */
+ Errflag := 0 /* error recovery flag */
+ yystate := 0
+ yychar := -1
+ yyp := -1
+ goto yystack
+
+ret0:
+ return 0
+
+ret1:
+ return 1
+
+yystack:
+ /* put a state and value onto the stack */
+ if yyDebug >= 4 {
+ __yyfmt__.Printf("char %v in %v\n", yyTokname(yychar), yyStatname(yystate))
+ }
+
+ yyp++
+ if yyp >= len(yyS) {
+ nyys := make([]yySymType, len(yyS)*2)
+ copy(nyys, yyS)
+ yyS = nyys
+ }
+ yyS[yyp] = yyVAL
+ yyS[yyp].yys = yystate
+
+yynewstate:
+ yyn = yyPact[yystate]
+ if yyn <= yyFlag {
+ goto yydefault /* simple state */
+ }
+ if yychar < 0 {
+ yychar = yylex1(yylex, &yylval)
+ }
+ yyn += yychar
+ if yyn < 0 || yyn >= yyLast {
+ goto yydefault
+ }
+ yyn = yyAct[yyn]
+ if yyChk[yyn] == yychar { /* valid shift */
+ yychar = -1
+ yyVAL = yylval
+ yystate = yyn
+ if Errflag > 0 {
+ Errflag--
+ }
+ goto yystack
+ }
+
+yydefault:
+ /* default state action */
+ yyn = yyDef[yystate]
+ if yyn == -2 {
+ if yychar < 0 {
+ yychar = yylex1(yylex, &yylval)
+ }
+
+ /* look through exception table */
+ xi := 0
+ for {
+ if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate {
+ break
+ }
+ xi += 2
+ }
+ for xi += 2; ; xi += 2 {
+ yyn = yyExca[xi+0]
+ if yyn < 0 || yyn == yychar {
+ break
+ }
+ }
+ yyn = yyExca[xi+1]
+ if yyn < 0 {
+ goto ret0
+ }
+ }
+ if yyn == 0 {
+ /* error ... attempt to resume parsing */
+ switch Errflag {
+ case 0: /* brand new error */
+ yylex.Error("syntax error")
+ Nerrs++
+ if yyDebug >= 1 {
+ __yyfmt__.Printf("%s", yyStatname(yystate))
+ __yyfmt__.Printf(" saw %s\n", yyTokname(yychar))
+ }
+ fallthrough
+
+ case 1, 2: /* incompletely recovered error ... try again */
+ Errflag = 3
+
+ /* find a state where "error" is a legal shift action */
+ for yyp >= 0 {
+ yyn = yyPact[yyS[yyp].yys] + yyErrCode
+ if yyn >= 0 && yyn < yyLast {
+ yystate = yyAct[yyn] /* simulate a shift of "error" */
+ if yyChk[yystate] == yyErrCode {
+ goto yystack
+ }
+ }
+
+ /* the current p has no shift on "error", pop stack */
+ if yyDebug >= 2 {
+ __yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys)
+ }
+ yyp--
+ }
+ /* there is no state on the stack with an error shift ... abort */
+ goto ret1
+
+ case 3: /* no shift yet; clobber input char */
+ if yyDebug >= 2 {
+ __yyfmt__.Printf("error recovery discards %s\n", yyTokname(yychar))
+ }
+ if yychar == yyEofCode {
+ goto ret1
+ }
+ yychar = -1
+ goto yynewstate /* try again in the same state */
+ }
+ }
+
+ /* reduction by production yyn */
+ if yyDebug >= 2 {
+ __yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate))
+ }
+
+ yynt := yyn
+ yypt := yyp
+ _ = yypt // guard against "declared and not used"
+
+ yyp -= yyR2[yyn]
+ // yyp is now the index of $0. Perform the default action. Iff the
+ // reduced production is ε, $1 is possibly out of range.
+ if yyp+1 >= len(yyS) {
+ nyys := make([]yySymType, len(yyS)*2)
+ copy(nyys, yyS)
+ yyS = nyys
+ }
+ yyVAL = yyS[yyp+1]
+
+ /* consult goto table to find next state */
+ yyn = yyR1[yyn]
+ yyg := yyPgo[yyn]
+ yyj := yyg + yyS[yyp].yys + 1
+
+ if yyj >= yyLast {
+ yystate = yyAct[yyg]
+ } else {
+ yystate = yyAct[yyj]
+ if yyChk[yystate] != -yyn {
+ yystate = yyAct[yyg]
+ }
+ }
+ // dummy call; replaced with literal code
+ switch yynt {
+
+ case 2:
+ //line a.y:73
+ {
+ stmtline = asm.Lineno
+ }
+ case 4:
+ //line a.y:80
+ {
+ yyS[yypt-1].sym = asm.LabelLookup(yyS[yypt-1].sym)
+ if yyS[yypt-1].sym.Type == LLAB && yyS[yypt-1].sym.Value != int64(asm.PC) {
+ yyerror("redeclaration of %s", yyS[yypt-1].sym.Labelname)
+ }
+ yyS[yypt-1].sym.Type = LLAB
+ yyS[yypt-1].sym.Value = int64(asm.PC)
+ }
+ case 6:
+ //line a.y:90
+ {
+ yyS[yypt-3].sym.Type = LVAR
+ yyS[yypt-3].sym.Value = int64(yyS[yypt-1].lval)
+ }
+ case 7:
+ //line a.y:95
+ {
+ if yyS[yypt-3].sym.Value != int64(yyS[yypt-1].lval) {
+ yyerror("redeclaration of %s", yyS[yypt-3].sym.Name)
+ }
+ yyS[yypt-3].sym.Value = int64(yyS[yypt-1].lval)
+ }
+ case 11:
+ //line a.y:110
+ {
+ outcode(yyS[yypt-6].lval, yyS[yypt-5].lval, &yyS[yypt-4].addr, yyS[yypt-2].lval, &yyS[yypt-0].addr)
+ }
+ case 12:
+ //line a.y:114
+ {
+ outcode(yyS[yypt-5].lval, yyS[yypt-4].lval, &yyS[yypt-3].addr, yyS[yypt-1].lval, &nullgen)
+ }
+ case 13:
+ //line a.y:118
+ {
+ outcode(yyS[yypt-4].lval, yyS[yypt-3].lval, &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 14:
+ //line a.y:125
+ {
+ outcode(yyS[yypt-4].lval, yyS[yypt-3].lval, &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 15:
+ //line a.y:132
+ {
+ outcode(yyS[yypt-4].lval, yyS[yypt-3].lval, &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 16:
+ //line a.y:139
+ {
+ outcode(yyS[yypt-3].lval, yyS[yypt-2].lval, &nullgen, NREG, &yyS[yypt-0].addr)
+ }
+ case 17:
+ //line a.y:143
+ {
+ outcode(yyS[yypt-3].lval, yyS[yypt-2].lval, &nullgen, NREG, &yyS[yypt-0].addr)
+ }
+ case 18:
+ //line a.y:150
+ {
+ outcode(yyS[yypt-2].lval, Always, &nullgen, NREG, &yyS[yypt-0].addr)
+ }
+ case 19:
+ //line a.y:157
+ {
+ outcode(yyS[yypt-2].lval, Always, &nullgen, NREG, &yyS[yypt-0].addr)
+ }
+ case 20:
+ //line a.y:164
+ {
+ outcode(yyS[yypt-3].lval, yyS[yypt-2].lval, &nullgen, NREG, &yyS[yypt-0].addr)
+ }
+ case 21:
+ //line a.y:171
+ {
+ outcode(yyS[yypt-5].lval, yyS[yypt-4].lval, &yyS[yypt-3].addr, yyS[yypt-1].lval, &nullgen)
+ }
+ case 22:
+ //line a.y:178
+ {
+ var g obj.Addr
+
+ g = nullgen
+ g.Type = D_CONST
+ g.Offset = int64(yyS[yypt-1].lval)
+ outcode(yyS[yypt-6].lval, yyS[yypt-5].lval, &yyS[yypt-4].addr, NREG, &g)
+ }
+ case 23:
+ //line a.y:187
+ {
+ var g obj.Addr
+
+ g = nullgen
+ g.Type = D_CONST
+ g.Offset = int64(yyS[yypt-3].lval)
+ outcode(yyS[yypt-6].lval, yyS[yypt-5].lval, &g, NREG, &yyS[yypt-0].addr)
+ }
+ case 24:
+ //line a.y:199
+ {
+ outcode(yyS[yypt-6].lval, yyS[yypt-5].lval, &yyS[yypt-2].addr, int32(yyS[yypt-4].addr.Reg), &yyS[yypt-0].addr)
+ }
+ case 25:
+ //line a.y:203
+ {
+ outcode(yyS[yypt-5].lval, yyS[yypt-4].lval, &yyS[yypt-1].addr, int32(yyS[yypt-3].addr.Reg), &yyS[yypt-3].addr)
+ }
+ case 26:
+ //line a.y:207
+ {
+ outcode(yyS[yypt-5].lval, yyS[yypt-4].lval, &yyS[yypt-2].addr, int32(yyS[yypt-0].addr.Reg), &yyS[yypt-0].addr)
+ }
+ case 27:
+ //line a.y:214
+ {
+ outcode(yyS[yypt-2].lval, yyS[yypt-1].lval, &nullgen, NREG, &nullgen)
+ }
+ case 28:
+ //line a.y:221
+ {
+ asm.Settext(yyS[yypt-2].addr.Sym)
+ yyS[yypt-0].addr.Type = D_CONST2
+ yyS[yypt-0].addr.Offset2 = -obj.ArgsSizeUnknown
+ outcode(yyS[yypt-3].lval, Always, &yyS[yypt-2].addr, 0, &yyS[yypt-0].addr)
+ }
+ case 29:
+ //line a.y:228
+ {
+ asm.Settext(yyS[yypt-4].addr.Sym)
+ yyS[yypt-0].addr.Type = D_CONST2
+ yyS[yypt-0].addr.Offset2 = -obj.ArgsSizeUnknown
+ outcode(yyS[yypt-5].lval, Always, &yyS[yypt-4].addr, yyS[yypt-2].lval, &yyS[yypt-0].addr)
+ }
+ case 30:
+ //line a.y:235
+ {
+ asm.Settext(yyS[yypt-6].addr.Sym)
+ yyS[yypt-2].addr.Type = D_CONST2
+ yyS[yypt-2].addr.Offset2 = yyS[yypt-0].lval
+ outcode(yyS[yypt-7].lval, Always, &yyS[yypt-6].addr, yyS[yypt-4].lval, &yyS[yypt-2].addr)
+ }
+ case 31:
+ //line a.y:245
+ {
+ outcode(yyS[yypt-5].lval, Always, &yyS[yypt-4].addr, yyS[yypt-2].lval, &yyS[yypt-0].addr)
+ }
+ case 32:
+ //line a.y:252
+ {
+ outcode(yyS[yypt-3].lval, yyS[yypt-2].lval, &yyS[yypt-1].addr, NREG, &nullgen)
+ }
+ case 33:
+ //line a.y:259
+ {
+ outcode(yyS[yypt-2].lval, Always, &nullgen, NREG, &yyS[yypt-0].addr)
+ }
+ case 34:
+ //line a.y:266
+ {
+ outcode(yyS[yypt-4].lval, yyS[yypt-3].lval, &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 35:
+ //line a.y:270
+ {
+ outcode(yyS[yypt-4].lval, yyS[yypt-3].lval, &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 36:
+ //line a.y:274
+ {
+ outcode(yyS[yypt-6].lval, yyS[yypt-5].lval, &yyS[yypt-4].addr, yyS[yypt-2].lval, &yyS[yypt-0].addr)
+ }
+ case 37:
+ //line a.y:278
+ {
+ outcode(yyS[yypt-5].lval, yyS[yypt-4].lval, &yyS[yypt-3].addr, int32(yyS[yypt-1].addr.Reg), &nullgen)
+ }
+ case 38:
+ //line a.y:285
+ {
+ var g obj.Addr
+
+ g = nullgen
+ g.Type = D_CONST
+ g.Offset = int64(
+ (0xe << 24) | /* opcode */
+ (yyS[yypt-11].lval << 20) | /* MCR/MRC */
+ (yyS[yypt-10].lval << 28) | /* scond */
+ ((yyS[yypt-9].lval & 15) << 8) | /* coprocessor number */
+ ((yyS[yypt-7].lval & 7) << 21) | /* coprocessor operation */
+ ((yyS[yypt-5].lval & 15) << 12) | /* arm register */
+ ((yyS[yypt-3].lval & 15) << 16) | /* Crn */
+ ((yyS[yypt-1].lval & 15) << 0) | /* Crm */
+ ((yyS[yypt-0].lval & 7) << 5) | /* coprocessor information */
+ (1 << 4)) /* must be set */
+ outcode(AMRC, Always, &nullgen, NREG, &g)
+ }
+ case 39:
+ //line a.y:297
+ {
+ outcode(yyS[yypt-6].lval, yyS[yypt-5].lval, &yyS[yypt-4].addr, int32(yyS[yypt-2].addr.Reg), &yyS[yypt-0].addr)
+ }
+ case 40:
+ //line a.y:305
+ {
+ yyS[yypt-2].addr.Type = D_REGREG2
+ yyS[yypt-2].addr.Offset = int64(yyS[yypt-0].lval)
+ outcode(yyS[yypt-8].lval, yyS[yypt-7].lval, &yyS[yypt-6].addr, int32(yyS[yypt-4].addr.Reg), &yyS[yypt-2].addr)
+ }
+ case 41:
+ //line a.y:314
+ {
+ outcode(yyS[yypt-1].lval, Always, &yyS[yypt-0].addr, NREG, &nullgen)
+ }
+ case 42:
+ //line a.y:321
+ {
+ if yyS[yypt-2].addr.Type != D_CONST || yyS[yypt-0].addr.Type != D_CONST {
+ yyerror("arguments to PCDATA must be integer constants")
+ }
+ outcode(yyS[yypt-3].lval, Always, &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 43:
+ //line a.y:331
+ {
+ if yyS[yypt-2].addr.Type != D_CONST {
+ yyerror("index for FUNCDATA must be integer constant")
+ }
+ if yyS[yypt-0].addr.Type != D_EXTERN && yyS[yypt-0].addr.Type != D_STATIC && yyS[yypt-0].addr.Type != D_OREG {
+ yyerror("value for FUNCDATA must be symbol reference")
+ }
+ outcode(yyS[yypt-3].lval, Always, &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 44:
+ //line a.y:344
+ {
+ outcode(yyS[yypt-1].lval, Always, &nullgen, NREG, &nullgen)
+ }
+ case 45:
+ //line a.y:349
+ {
+ yyVAL.lval = Always
+ }
+ case 46:
+ //line a.y:353
+ {
+ yyVAL.lval = (yyS[yypt-1].lval & ^C_SCOND) | yyS[yypt-0].lval
+ }
+ case 47:
+ //line a.y:357
+ {
+ yyVAL.lval = yyS[yypt-1].lval | yyS[yypt-0].lval
+ }
+ case 50:
+ //line a.y:366
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_BRANCH
+ yyVAL.addr.Offset = int64(yyS[yypt-3].lval) + int64(asm.PC)
+ }
+ case 51:
+ //line a.y:372
+ {
+ yyS[yypt-1].sym = asm.LabelLookup(yyS[yypt-1].sym)
+ yyVAL.addr = nullgen
+ if asm.Pass == 2 && yyS[yypt-1].sym.Type != LLAB {
+ yyerror("undefined label: %s", yyS[yypt-1].sym.Labelname)
+ }
+ yyVAL.addr.Type = D_BRANCH
+ yyVAL.addr.Offset = yyS[yypt-1].sym.Value + int64(yyS[yypt-0].lval)
+ }
+ case 52:
+ //line a.y:383
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_CONST
+ yyVAL.addr.Offset = int64(yyS[yypt-0].lval)
+ }
+ case 53:
+ //line a.y:389
+ {
+ yyVAL.addr = yyS[yypt-0].addr
+ yyVAL.addr.Type = D_CONST
+ }
+ case 54:
+ //line a.y:394
+ {
+ yyVAL.addr = yyS[yypt-0].addr
+ yyVAL.addr.Type = D_OCONST
+ }
+ case 55:
+ //line a.y:399
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_SCONST
+ yyVAL.addr.U.Sval = yyS[yypt-0].sval
+ }
+ case 56:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 57:
+ //line a.y:408
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_FCONST
+ yyVAL.addr.U.Dval = yyS[yypt-0].dval
+ }
+ case 58:
+ //line a.y:414
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_FCONST
+ yyVAL.addr.U.Dval = -yyS[yypt-0].dval
+ }
+ case 59:
+ //line a.y:422
+ {
+ yyVAL.lval = 1 << uint(yyS[yypt-0].lval)
+ }
+ case 60:
+ //line a.y:426
+ {
+ yyVAL.lval = 0
+ for i := yyS[yypt-2].lval; i <= yyS[yypt-0].lval; i++ {
+ yyVAL.lval |= 1 << uint(i)
+ }
+ for i := yyS[yypt-0].lval; i <= yyS[yypt-2].lval; i++ {
+ yyVAL.lval |= 1 << uint(i)
+ }
+ }
+ case 61:
+ //line a.y:436
+ {
+ yyVAL.lval = (1 << uint(yyS[yypt-2].lval)) | yyS[yypt-0].lval
+ }
+ case 62:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 63:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 64:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 65:
+ //line a.y:445
+ {
+ yyVAL.addr = yyS[yypt-3].addr
+ yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+ }
+ case 66:
+ //line a.y:450
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_PSR
+ yyVAL.addr.Reg = int8(yyS[yypt-0].lval)
+ }
+ case 67:
+ //line a.y:456
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_FPCR
+ yyVAL.addr.Reg = int8(yyS[yypt-0].lval)
+ }
+ case 68:
+ //line a.y:462
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_OREG
+ yyVAL.addr.Offset = int64(yyS[yypt-0].lval)
+ }
+ case 69:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 70:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 71:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 72:
+ //line a.y:473
+ {
+ yyVAL.addr = yyS[yypt-0].addr
+ if yyS[yypt-0].addr.Name != D_EXTERN && yyS[yypt-0].addr.Name != D_STATIC {
+ }
+ }
+ case 73:
+ //line a.y:481
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_OREG
+ yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+ yyVAL.addr.Offset = 0
+ }
+ case 74:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 75:
+ //line a.y:491
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_OREG
+ yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+ yyVAL.addr.Offset = int64(yyS[yypt-3].lval)
+ }
+ case 76:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 77:
+ //line a.y:501
+ {
+ yyVAL.addr = yyS[yypt-3].addr
+ yyVAL.addr.Type = D_OREG
+ yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+ }
+ case 78:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 79:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 80:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 81:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 82:
+ //line a.y:514
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_CONST
+ yyVAL.addr.Offset = int64(yyS[yypt-0].lval)
+ }
+ case 83:
+ //line a.y:522
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_REG
+ yyVAL.addr.Reg = int8(yyS[yypt-0].lval)
+ }
+ case 84:
+ //line a.y:530
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_REGREG
+ yyVAL.addr.Reg = int8(yyS[yypt-3].lval)
+ yyVAL.addr.Offset = int64(yyS[yypt-1].lval)
+ }
+ case 85:
+ //line a.y:539
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_SHIFT
+ yyVAL.addr.Offset = int64(yyS[yypt-3].lval) | int64(yyS[yypt-0].lval) | (0 << 5)
+ }
+ case 86:
+ //line a.y:545
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_SHIFT
+ yyVAL.addr.Offset = int64(yyS[yypt-3].lval) | int64(yyS[yypt-0].lval) | (1 << 5)
+ }
+ case 87:
+ //line a.y:551
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_SHIFT
+ yyVAL.addr.Offset = int64(yyS[yypt-3].lval) | int64(yyS[yypt-0].lval) | (2 << 5)
+ }
+ case 88:
+ //line a.y:557
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_SHIFT
+ yyVAL.addr.Offset = int64(yyS[yypt-3].lval) | int64(yyS[yypt-0].lval) | (3 << 5)
+ }
+ case 89:
+ //line a.y:565
+ {
+ if yyVAL.lval < 0 || yyVAL.lval >= 16 {
+ print("register value out of range\n")
+ }
+ yyVAL.lval = ((yyS[yypt-0].lval & 15) << 8) | (1 << 4)
+ }
+ case 90:
+ //line a.y:572
+ {
+ if yyVAL.lval < 0 || yyVAL.lval >= 32 {
+ print("shift value out of range\n")
+ }
+ yyVAL.lval = (yyS[yypt-0].lval & 31) << 7
+ }
+ case 91:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 92:
+ //line a.y:582
+ {
+ yyVAL.lval = REGPC
+ }
+ case 93:
+ //line a.y:586
+ {
+ if yyS[yypt-1].lval < 0 || yyS[yypt-1].lval >= NREG {
+ print("register value out of range\n")
+ }
+ yyVAL.lval = yyS[yypt-1].lval
+ }
+ case 94:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 95:
+ //line a.y:596
+ {
+ yyVAL.lval = REGSP
+ }
+ case 96:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 97:
+ //line a.y:603
+ {
+ if yyS[yypt-1].lval < 0 || yyS[yypt-1].lval >= NREG {
+ print("register value out of range\n")
+ }
+ yyVAL.lval = yyS[yypt-1].lval
+ }
+ case 98:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 99:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 100:
+ //line a.y:616
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_FREG
+ yyVAL.addr.Reg = int8(yyS[yypt-0].lval)
+ }
+ case 101:
+ //line a.y:622
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_FREG
+ yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+ }
+ case 102:
+ //line a.y:630
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_OREG
+ yyVAL.addr.Name = int8(yyS[yypt-1].lval)
+ yyVAL.addr.Sym = nil
+ yyVAL.addr.Offset = int64(yyS[yypt-3].lval)
+ }
+ case 103:
+ //line a.y:638
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_OREG
+ yyVAL.addr.Name = int8(yyS[yypt-1].lval)
+ yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyS[yypt-4].sym.Name, 0)
+ yyVAL.addr.Offset = int64(yyS[yypt-3].lval)
+ }
+ case 104:
+ //line a.y:646
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_OREG
+ yyVAL.addr.Name = D_STATIC
+ yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyS[yypt-6].sym.Name, 1)
+ yyVAL.addr.Offset = int64(yyS[yypt-3].lval)
+ }
+ case 105:
+ //line a.y:655
+ {
+ yyVAL.lval = 0
+ }
+ case 106:
+ //line a.y:659
+ {
+ yyVAL.lval = yyS[yypt-0].lval
+ }
+ case 107:
+ //line a.y:663
+ {
+ yyVAL.lval = -yyS[yypt-0].lval
+ }
+ case 108:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 109:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 110:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 111:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 112:
+ //line a.y:675
+ {
+ yyVAL.lval = int32(yyS[yypt-0].sym.Value)
+ }
+ case 113:
+ //line a.y:679
+ {
+ yyVAL.lval = -yyS[yypt-0].lval
+ }
+ case 114:
+ //line a.y:683
+ {
+ yyVAL.lval = yyS[yypt-0].lval
+ }
+ case 115:
+ //line a.y:687
+ {
+ yyVAL.lval = ^yyS[yypt-0].lval
+ }
+ case 116:
+ //line a.y:691
+ {
+ yyVAL.lval = yyS[yypt-1].lval
+ }
+ case 117:
+ //line a.y:696
+ {
+ yyVAL.lval = 0
+ }
+ case 118:
+ //line a.y:700
+ {
+ yyVAL.lval = yyS[yypt-0].lval
+ }
+ case 119:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 120:
+ //line a.y:707
+ {
+ yyVAL.lval = yyS[yypt-2].lval + yyS[yypt-0].lval
+ }
+ case 121:
+ //line a.y:711
+ {
+ yyVAL.lval = yyS[yypt-2].lval - yyS[yypt-0].lval
+ }
+ case 122:
+ //line a.y:715
+ {
+ yyVAL.lval = yyS[yypt-2].lval * yyS[yypt-0].lval
+ }
+ case 123:
+ //line a.y:719
+ {
+ yyVAL.lval = yyS[yypt-2].lval / yyS[yypt-0].lval
+ }
+ case 124:
+ //line a.y:723
+ {
+ yyVAL.lval = yyS[yypt-2].lval % yyS[yypt-0].lval
+ }
+ case 125:
+ //line a.y:727
+ {
+ yyVAL.lval = yyS[yypt-3].lval << uint(yyS[yypt-0].lval)
+ }
+ case 126:
+ //line a.y:731
+ {
+ yyVAL.lval = yyS[yypt-3].lval >> uint(yyS[yypt-0].lval)
+ }
+ case 127:
+ //line a.y:735
+ {
+ yyVAL.lval = yyS[yypt-2].lval & yyS[yypt-0].lval
+ }
+ case 128:
+ //line a.y:739
+ {
+ yyVAL.lval = yyS[yypt-2].lval ^ yyS[yypt-0].lval
+ }
+ case 129:
+ //line a.y:743
+ {
+ yyVAL.lval = yyS[yypt-2].lval | yyS[yypt-0].lval
+ }
+ }
+ goto yystack /* stack new state and value */
+}
--- /dev/null
+// Inferno utils/6a/a.y
+// http://code.google.com/p/inferno-os/source/browse/utils/6a/a.y
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+%{
+package main
+
+import (
+ "cmd/internal/asm"
+ "cmd/internal/obj"
+ "cmd/internal/obj/x86"
+)
+%}
+
+%union {
+ sym *asm.Sym
+ lval int64
+ dval float64
+ sval string
+ addr obj.Addr
+ addr2 Addr2
+}
+
+%left '|'
+%left '^'
+%left '&'
+%left '<' '>'
+%left '+' '-'
+%left '*' '/' '%'
+%token <lval> LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4
+%token <lval> LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPEG LTYPEPC
+%token <lval> LTYPES LTYPEM LTYPEI LTYPEXC LTYPEX LTYPERT LTYPEF
+%token <lval> LCONST LFP LPC LSB
+%token <lval> LBREG LLREG LSREG LFREG LMREG LXREG
+%token <dval> LFCONST
+%token <sval> LSCONST LSP
+%token <sym> LNAME LLAB LVAR
+%type <lval> con con2 expr pointer offset
+%type <addr> mem imm imm2 reg nam rel rem rim rom omem nmem
+%type <addr2> nonnon nonrel nonrem rimnon rimrem remrim
+%type <addr2> spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9
+%type <addr2> spec10 spec11 spec12 spec13
+%%
+prog:
+| prog
+ {
+ stmtline = asm.Lineno;
+ }
+ line
+
+line:
+ LNAME ':'
+ {
+ $1 = asm.LabelLookup($1);
+ if $1.Type == LLAB && $1.Value != int64(asm.PC) {
+ yyerror("redeclaration of %s (%s)", $1.Labelname, $1.Name);
+ }
+ $1.Type = LLAB;
+ $1.Value = int64(asm.PC)
+ }
+ line
+| ';'
+| inst ';'
+| error ';'
+
+inst:
+ LNAME '=' expr
+ {
+ $1.Type = LVAR;
+ $1.Value = $3;
+ }
+| LVAR '=' expr
+ {
+ if $1.Value != $3 {
+ yyerror("redeclaration of %s", $1.Name);
+ }
+ $1.Value = $3;
+ }
+| LTYPE0 nonnon { outcode(int($1), &$2); }
+| LTYPE1 nonrem { outcode(int($1), &$2); }
+| LTYPE2 rimnon { outcode(int($1), &$2); }
+| LTYPE3 rimrem { outcode(int($1), &$2); }
+| LTYPE4 remrim { outcode(int($1), &$2); }
+| LTYPER nonrel { outcode(int($1), &$2); }
+| LTYPED spec1 { outcode(int($1), &$2); }
+| LTYPET spec2 { outcode(int($1), &$2); }
+| LTYPEC spec3 { outcode(int($1), &$2); }
+| LTYPEN spec4 { outcode(int($1), &$2); }
+| LTYPES spec5 { outcode(int($1), &$2); }
+| LTYPEM spec6 { outcode(int($1), &$2); }
+| LTYPEI spec7 { outcode(int($1), &$2); }
+| LTYPEXC spec8 { outcode(int($1), &$2); }
+| LTYPEX spec9 { outcode(int($1), &$2); }
+| LTYPERT spec10 { outcode(int($1), &$2); }
+| LTYPEG spec11 { outcode(int($1), &$2); }
+| LTYPEPC spec12 { outcode(int($1), &$2); }
+| LTYPEF spec13 { outcode(int($1), &$2); }
+
+nonnon:
+ {
+ $$.from = nullgen;
+ $$.to = nullgen;
+ }
+| ','
+ {
+ $$.from = nullgen;
+ $$.to = nullgen;
+ }
+
+rimrem:
+ rim ',' rem
+ {
+ $$.from = $1;
+ $$.to = $3;
+ }
+
+remrim:
+ rem ',' rim
+ {
+ $$.from = $1;
+ $$.to = $3;
+ }
+
+rimnon:
+ rim ','
+ {
+ $$.from = $1;
+ $$.to = nullgen;
+ }
+| rim
+ {
+ $$.from = $1;
+ $$.to = nullgen;
+ }
+
+nonrem:
+ ',' rem
+ {
+ $$.from = nullgen;
+ $$.to = $2;
+ }
+| rem
+ {
+ $$.from = nullgen;
+ $$.to = $1;
+ }
+
+nonrel:
+ ',' rel
+ {
+ $$.from = nullgen;
+ $$.to = $2;
+ }
+| rel
+ {
+ $$.from = nullgen;
+ $$.to = $1;
+ }
+| imm ',' rel
+ {
+ $$.from = $1;
+ $$.to = $3;
+ }
+
+spec1: /* DATA */
+ nam '/' con ',' imm
+ {
+ $$.from = $1;
+ $$.from.Scale = int8($3);
+ $$.to = $5;
+ }
+
+spec2: /* TEXT */
+ mem ',' imm2
+ {
+ asm.Settext($1.Sym);
+ $$.from = $1;
+ $$.to = $3;
+ }
+| mem ',' con ',' imm2
+ {
+ asm.Settext($1.Sym);
+ $$.from = $1;
+ $$.from.Scale = int8($3);
+ $$.to = $5;
+ }
+
+spec3: /* JMP/CALL */
+ ',' rom
+ {
+ $$.from = nullgen;
+ $$.to = $2;
+ }
+| rom
+ {
+ $$.from = nullgen;
+ $$.to = $1;
+ }
+
+spec4: /* NOP */
+ nonnon
+| nonrem
+
+spec5: /* SHL/SHR */
+ rim ',' rem
+ {
+ $$.from = $1;
+ $$.to = $3;
+ }
+| rim ',' rem ':' LLREG
+ {
+ $$.from = $1;
+ $$.to = $3;
+ if $$.from.Index != x86.D_NONE {
+ yyerror("dp shift with lhs index");
+ }
+ $$.from.Index = uint8($5);
+ }
+
+spec6: /* MOVW/MOVL */
+ rim ',' rem
+ {
+ $$.from = $1;
+ $$.to = $3;
+ }
+| rim ',' rem ':' LSREG
+ {
+ $$.from = $1;
+ $$.to = $3;
+ if $$.to.Index != x86.D_NONE {
+ yyerror("dp move with lhs index");
+ }
+ $$.to.Index = uint8($5);
+ }
+
+spec7:
+ rim ','
+ {
+ $$.from = $1;
+ $$.to = nullgen;
+ }
+| rim
+ {
+ $$.from = $1;
+ $$.to = nullgen;
+ }
+| rim ',' rem
+ {
+ $$.from = $1;
+ $$.to = $3;
+ }
+
+spec8: /* CMPPS/CMPPD */
+ reg ',' rem ',' con
+ {
+ $$.from = $1;
+ $$.to = $3;
+ $$.to.Offset = $5;
+ }
+
+spec9: /* shufl */
+ imm ',' rem ',' reg
+ {
+ $$.from = $3;
+ $$.to = $5;
+ if $1.Type != x86.D_CONST {
+ yyerror("illegal constant");
+ }
+ $$.to.Offset = $1.Offset;
+ }
+
+spec10: /* RET/RETF */
+ {
+ $$.from = nullgen;
+ $$.to = nullgen;
+ }
+| imm
+ {
+ $$.from = $1;
+ $$.to = nullgen;
+ }
+
+spec11: /* GLOBL */
+ mem ',' imm
+ {
+ $$.from = $1;
+ $$.to = $3;
+ }
+| mem ',' con ',' imm
+ {
+ $$.from = $1;
+ $$.from.Scale = int8($3);
+ $$.to = $5;
+ }
+
+spec12: /* asm.PCDATA */
+ rim ',' rim
+ {
+ if $1.Type != x86.D_CONST || $3.Type != x86.D_CONST {
+ yyerror("arguments to asm.PCDATA must be integer constants");
+ }
+ $$.from = $1;
+ $$.to = $3;
+ }
+
+spec13: /* FUNCDATA */
+ rim ',' rim
+ {
+ if $1.Type != x86.D_CONST {
+ yyerror("index for FUNCDATA must be integer constant");
+ }
+ if $3.Type != x86.D_EXTERN && $3.Type != x86.D_STATIC {
+ yyerror("value for FUNCDATA must be symbol reference");
+ }
+ $$.from = $1;
+ $$.to = $3;
+ }
+
+rem:
+ reg
+| mem
+
+rom:
+ rel
+| nmem
+| '*' reg
+ {
+ $$ = $2;
+ }
+| '*' omem
+ {
+ $$ = $2;
+ }
+| reg
+| omem
+
+rim:
+ rem
+| imm
+
+rel:
+ con '(' LPC ')'
+ {
+ $$ = nullgen;
+ $$.Type = x86.D_BRANCH;
+ $$.Offset = $1 + int64(asm.PC);
+ }
+| LNAME offset
+ {
+ $1 = asm.LabelLookup($1);
+ $$ = nullgen;
+ if asm.Pass == 2 && $1.Type != LLAB {
+ yyerror("undefined label: %s", $1.Labelname);
+ }
+ $$.Type = x86.D_BRANCH;
+ $$.Offset = $1.Value + $2;
+ }
+
+reg:
+ LBREG
+ {
+ $$ = nullgen;
+ $$.Type = int16($1);
+ }
+| LFREG
+ {
+ $$ = nullgen;
+ $$.Type = int16($1);
+ }
+| LLREG
+ {
+ $$ = nullgen;
+ $$.Type = int16($1);
+ }
+| LMREG
+ {
+ $$ = nullgen;
+ $$.Type = int16($1);
+ }
+| LSP
+ {
+ $$ = nullgen;
+ $$.Type = x86.D_SP;
+ }
+| LSREG
+ {
+ $$ = nullgen;
+ $$.Type = int16($1);
+ }
+| LXREG
+ {
+ $$ = nullgen;
+ $$.Type = int16($1);
+ }
+imm2:
+ '$' con2
+ {
+ $$ = nullgen;
+ $$.Type = x86.D_CONST;
+ $$.Offset = $2;
+ }
+
+imm:
+ '$' con
+ {
+ $$ = nullgen;
+ $$.Type = x86.D_CONST;
+ $$.Offset = $2;
+ }
+| '$' nam
+ {
+ $$ = $2;
+ $$.Index = uint8($2.Type);
+ $$.Type = x86.D_ADDR;
+ /*
+ if($2.Type == x86.D_AUTO || $2.Type == x86.D_PARAM)
+ yyerror("constant cannot be automatic: %s",
+ $2.sym.Name);
+ */
+ }
+| '$' LSCONST
+ {
+ $$ = nullgen;
+ $$.Type = x86.D_SCONST;
+ $$.U.Sval = ($2+"\x00\x00\x00\x00\x00\x00\x00\x00")[:8]
+ }
+| '$' LFCONST
+ {
+ $$ = nullgen;
+ $$.Type = x86.D_FCONST;
+ $$.U.Dval = $2;
+ }
+| '$' '(' LFCONST ')'
+ {
+ $$ = nullgen;
+ $$.Type = x86.D_FCONST;
+ $$.U.Dval = $3;
+ }
+| '$' '(' '-' LFCONST ')'
+ {
+ $$ = nullgen;
+ $$.Type = x86.D_FCONST;
+ $$.U.Dval = -$4;
+ }
+| '$' '-' LFCONST
+ {
+ $$ = nullgen;
+ $$.Type = x86.D_FCONST;
+ $$.U.Dval = -$3;
+ }
+
+mem:
+ omem
+| nmem
+
+omem:
+ con
+ {
+ $$ = nullgen;
+ $$.Type = x86.D_INDIR+x86.D_NONE;
+ $$.Offset = $1;
+ }
+| con '(' LLREG ')'
+ {
+ $$ = nullgen;
+ $$.Type = int16(x86.D_INDIR+$3);
+ $$.Offset = $1;
+ }
+| con '(' LSP ')'
+ {
+ $$ = nullgen;
+ $$.Type = int16(x86.D_INDIR+x86.D_SP);
+ $$.Offset = $1;
+ }
+| con '(' LSREG ')'
+ {
+ $$ = nullgen;
+ $$.Type = int16(x86.D_INDIR+$3);
+ $$.Offset = $1;
+ }
+| con '(' LLREG '*' con ')'
+ {
+ $$ = nullgen;
+ $$.Type = int16(x86.D_INDIR+x86.D_NONE);
+ $$.Offset = $1;
+ $$.Index = uint8($3);
+ $$.Scale = int8($5);
+ checkscale($$.Scale);
+ }
+| con '(' LLREG ')' '(' LLREG '*' con ')'
+ {
+ $$ = nullgen;
+ $$.Type = int16(x86.D_INDIR+$3);
+ $$.Offset = $1;
+ $$.Index = uint8($6);
+ $$.Scale = int8($8);
+ checkscale($$.Scale);
+ }
+| con '(' LLREG ')' '(' LSREG '*' con ')'
+ {
+ $$ = nullgen;
+ $$.Type = int16(x86.D_INDIR+$3);
+ $$.Offset = $1;
+ $$.Index = uint8($6);
+ $$.Scale = int8($8);
+ checkscale($$.Scale);
+ }
+| '(' LLREG ')'
+ {
+ $$ = nullgen;
+ $$.Type = int16(x86.D_INDIR+$2);
+ }
+| '(' LSP ')'
+ {
+ $$ = nullgen;
+ $$.Type = int16(x86.D_INDIR+x86.D_SP);
+ }
+| '(' LLREG '*' con ')'
+ {
+ $$ = nullgen;
+ $$.Type = int16(x86.D_INDIR+x86.D_NONE);
+ $$.Index = uint8($2);
+ $$.Scale = int8($4);
+ checkscale($$.Scale);
+ }
+| '(' LLREG ')' '(' LLREG '*' con ')'
+ {
+ $$ = nullgen;
+ $$.Type = int16(x86.D_INDIR+$2);
+ $$.Index = uint8($5);
+ $$.Scale = int8($7);
+ checkscale($$.Scale);
+ }
+
+nmem:
+ nam
+ {
+ $$ = $1;
+ }
+| nam '(' LLREG '*' con ')'
+ {
+ $$ = $1;
+ $$.Index = uint8($3);
+ $$.Scale = int8($5);
+ checkscale($$.Scale);
+ }
+
+nam:
+ LNAME offset '(' pointer ')'
+ {
+ $$ = nullgen;
+ $$.Type = int16($4);
+ $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
+ $$.Offset = $2;
+ }
+| LNAME '<' '>' offset '(' LSB ')'
+ {
+ $$ = nullgen;
+ $$.Type = x86.D_STATIC;
+ $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
+ $$.Offset = $4;
+ }
+
+offset:
+ {
+ $$ = 0;
+ }
+| '+' con
+ {
+ $$ = $2;
+ }
+| '-' con
+ {
+ $$ = -$2;
+ }
+
+pointer:
+ LSB
+| LSP
+ {
+ $$ = x86.D_AUTO;
+ }
+| LFP
+
+con:
+ LCONST
+| LVAR
+ {
+ $$ = $1.Value;
+ }
+| '-' con
+ {
+ $$ = -$2;
+ }
+| '+' con
+ {
+ $$ = $2;
+ }
+| '~' con
+ {
+ $$ = ^$2;
+ }
+| '(' expr ')'
+ {
+ $$ = $2;
+ }
+
+con2:
+ LCONST
+ {
+ $$ = int64(uint64($1 & 0xffffffff) + (obj.ArgsSizeUnknown<<32))
+ }
+| '-' LCONST
+ {
+ $$ = int64(uint64(-$2 & 0xffffffff) + (obj.ArgsSizeUnknown<<32))
+ }
+| LCONST '-' LCONST
+ {
+ $$ = ($1 & 0xffffffff) + (($3 & 0xffff) << 32);
+ }
+| '-' LCONST '-' LCONST
+ {
+ $$ = (-$2 & 0xffffffff) + (($4 & 0xffff) << 32);
+ }
+
+expr:
+ con
+| expr '+' expr
+ {
+ $$ = $1 + $3;
+ }
+| expr '-' expr
+ {
+ $$ = $1 - $3;
+ }
+| expr '*' expr
+ {
+ $$ = $1 * $3;
+ }
+| expr '/' expr
+ {
+ $$ = $1 / $3;
+ }
+| expr '%' expr
+ {
+ $$ = $1 % $3;
+ }
+| expr '<' '<' expr
+ {
+ $$ = $1 << uint($4);
+ }
+| expr '>' '>' expr
+ {
+ $$ = $1 >> uint($4);
+ }
+| expr '&' expr
+ {
+ $$ = $1 & $3;
+ }
+| expr '^' expr
+ {
+ $$ = $1 ^ $3;
+ }
+| expr '|' expr
+ {
+ $$ = $1 | $3;
+ }
--- /dev/null
+// Inferno utils/6a/lex.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6a/lex.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+//go:generate go tool yacc a.y
+
+package main
+
+import (
+ "cmd/internal/asm"
+ "cmd/internal/obj"
+ "cmd/internal/obj/x86"
+)
+
+var (
+ yyerror = asm.Yyerror
+ nullgen obj.Addr
+ stmtline int32
+)
+
+func main() {
+ cinit()
+
+ asm.LSCONST = LSCONST
+ asm.LCONST = LCONST
+ asm.LFCONST = LFCONST
+ asm.LNAME = LNAME
+ asm.LVAR = LVAR
+ asm.LLAB = LLAB
+
+ asm.Thechar = '6'
+ asm.Thestring = "amd64"
+ asm.Thelinkarch = &x86.Linkamd64
+ asm.Arches = map[string]*obj.LinkArch{
+ "amd64p32": &x86.Linkamd64p32,
+ }
+
+ asm.Lexinit = lexinit
+ asm.Cclean = cclean
+ asm.Yyparse = yyparse
+
+ asm.Main()
+}
+
+type yy struct{}
+
+func (yy) Lex(v *yySymType) int {
+ var av asm.Yylval
+ tok := asm.Yylex(&av)
+ v.sym = av.Sym
+ v.lval = av.Lval
+ v.sval = av.Sval
+ v.dval = av.Dval
+ return tok
+}
+
+func (yy) Error(msg string) {
+ asm.Yyerror("%s", msg)
+}
+
+func yyparse() {
+ yyParse(yy{})
+}
+
+var lexinit = []asm.Lextab{
+ {"SP", LSP, x86.D_AUTO},
+ {"SB", LSB, x86.D_EXTERN},
+ {"FP", LFP, x86.D_PARAM},
+ {"PC", LPC, x86.D_BRANCH},
+ {"AL", LBREG, x86.D_AL},
+ {"CL", LBREG, x86.D_CL},
+ {"DL", LBREG, x86.D_DL},
+ {"BL", LBREG, x86.D_BL},
+ /* "SPB", LBREG, D_SPB, */
+ {"SIB", LBREG, x86.D_SIB},
+ {"DIB", LBREG, x86.D_DIB},
+ {"BPB", LBREG, x86.D_BPB},
+ {"R8B", LBREG, x86.D_R8B},
+ {"R9B", LBREG, x86.D_R9B},
+ {"R10B", LBREG, x86.D_R10B},
+ {"R11B", LBREG, x86.D_R11B},
+ {"R12B", LBREG, x86.D_R12B},
+ {"R13B", LBREG, x86.D_R13B},
+ {"R14B", LBREG, x86.D_R14B},
+ {"R15B", LBREG, x86.D_R15B},
+ {"AH", LBREG, x86.D_AH},
+ {"CH", LBREG, x86.D_CH},
+ {"DH", LBREG, x86.D_DH},
+ {"BH", LBREG, x86.D_BH},
+ {"AX", LLREG, x86.D_AX},
+ {"CX", LLREG, x86.D_CX},
+ {"DX", LLREG, x86.D_DX},
+ {"BX", LLREG, x86.D_BX},
+
+ /* "SP", LLREG, D_SP, */
+ {"BP", LLREG, x86.D_BP},
+ {"SI", LLREG, x86.D_SI},
+ {"DI", LLREG, x86.D_DI},
+ {"R8", LLREG, x86.D_R8},
+ {"R9", LLREG, x86.D_R9},
+ {"R10", LLREG, x86.D_R10},
+ {"R11", LLREG, x86.D_R11},
+ {"R12", LLREG, x86.D_R12},
+ {"R13", LLREG, x86.D_R13},
+ {"R14", LLREG, x86.D_R14},
+ {"R15", LLREG, x86.D_R15},
+ {"RARG", LLREG, x86.REGARG},
+ {"F0", LFREG, x86.D_F0 + 0},
+ {"F1", LFREG, x86.D_F0 + 1},
+ {"F2", LFREG, x86.D_F0 + 2},
+ {"F3", LFREG, x86.D_F0 + 3},
+ {"F4", LFREG, x86.D_F0 + 4},
+ {"F5", LFREG, x86.D_F0 + 5},
+ {"F6", LFREG, x86.D_F0 + 6},
+ {"F7", LFREG, x86.D_F0 + 7},
+ {"M0", LMREG, x86.D_M0 + 0},
+ {"M1", LMREG, x86.D_M0 + 1},
+ {"M2", LMREG, x86.D_M0 + 2},
+ {"M3", LMREG, x86.D_M0 + 3},
+ {"M4", LMREG, x86.D_M0 + 4},
+ {"M5", LMREG, x86.D_M0 + 5},
+ {"M6", LMREG, x86.D_M0 + 6},
+ {"M7", LMREG, x86.D_M0 + 7},
+ {"X0", LXREG, x86.D_X0 + 0},
+ {"X1", LXREG, x86.D_X0 + 1},
+ {"X2", LXREG, x86.D_X0 + 2},
+ {"X3", LXREG, x86.D_X0 + 3},
+ {"X4", LXREG, x86.D_X0 + 4},
+ {"X5", LXREG, x86.D_X0 + 5},
+ {"X6", LXREG, x86.D_X0 + 6},
+ {"X7", LXREG, x86.D_X0 + 7},
+ {"X8", LXREG, x86.D_X0 + 8},
+ {"X9", LXREG, x86.D_X0 + 9},
+ {"X10", LXREG, x86.D_X0 + 10},
+ {"X11", LXREG, x86.D_X0 + 11},
+ {"X12", LXREG, x86.D_X0 + 12},
+ {"X13", LXREG, x86.D_X0 + 13},
+ {"X14", LXREG, x86.D_X0 + 14},
+ {"X15", LXREG, x86.D_X0 + 15},
+ {"CS", LSREG, x86.D_CS},
+ {"SS", LSREG, x86.D_SS},
+ {"DS", LSREG, x86.D_DS},
+ {"ES", LSREG, x86.D_ES},
+ {"FS", LSREG, x86.D_FS},
+ {"GS", LSREG, x86.D_GS},
+ {"GDTR", LBREG, x86.D_GDTR},
+ {"IDTR", LBREG, x86.D_IDTR},
+ {"LDTR", LBREG, x86.D_LDTR},
+ {"MSW", LBREG, x86.D_MSW},
+ {"TASK", LBREG, x86.D_TASK},
+ {"CR0", LBREG, x86.D_CR + 0},
+ {"CR1", LBREG, x86.D_CR + 1},
+ {"CR2", LBREG, x86.D_CR + 2},
+ {"CR3", LBREG, x86.D_CR + 3},
+ {"CR4", LBREG, x86.D_CR + 4},
+ {"CR5", LBREG, x86.D_CR + 5},
+ {"CR6", LBREG, x86.D_CR + 6},
+ {"CR7", LBREG, x86.D_CR + 7},
+ {"CR8", LBREG, x86.D_CR + 8},
+ {"CR9", LBREG, x86.D_CR + 9},
+ {"CR10", LBREG, x86.D_CR + 10},
+ {"CR11", LBREG, x86.D_CR + 11},
+ {"CR12", LBREG, x86.D_CR + 12},
+ {"CR13", LBREG, x86.D_CR + 13},
+ {"CR14", LBREG, x86.D_CR + 14},
+ {"CR15", LBREG, x86.D_CR + 15},
+ {"DR0", LBREG, x86.D_DR + 0},
+ {"DR1", LBREG, x86.D_DR + 1},
+ {"DR2", LBREG, x86.D_DR + 2},
+ {"DR3", LBREG, x86.D_DR + 3},
+ {"DR4", LBREG, x86.D_DR + 4},
+ {"DR5", LBREG, x86.D_DR + 5},
+ {"DR6", LBREG, x86.D_DR + 6},
+ {"DR7", LBREG, x86.D_DR + 7},
+ {"TR0", LBREG, x86.D_TR + 0},
+ {"TR1", LBREG, x86.D_TR + 1},
+ {"TR2", LBREG, x86.D_TR + 2},
+ {"TR3", LBREG, x86.D_TR + 3},
+ {"TR4", LBREG, x86.D_TR + 4},
+ {"TR5", LBREG, x86.D_TR + 5},
+ {"TR6", LBREG, x86.D_TR + 6},
+ {"TR7", LBREG, x86.D_TR + 7},
+ {"TLS", LSREG, x86.D_TLS},
+ {"AAA", LTYPE0, x86.AAAA},
+ {"AAD", LTYPE0, x86.AAAD},
+ {"AAM", LTYPE0, x86.AAAM},
+ {"AAS", LTYPE0, x86.AAAS},
+ {"ADCB", LTYPE3, x86.AADCB},
+ {"ADCL", LTYPE3, x86.AADCL},
+ {"ADCQ", LTYPE3, x86.AADCQ},
+ {"ADCW", LTYPE3, x86.AADCW},
+ {"ADDB", LTYPE3, x86.AADDB},
+ {"ADDL", LTYPE3, x86.AADDL},
+ {"ADDQ", LTYPE3, x86.AADDQ},
+ {"ADDW", LTYPE3, x86.AADDW},
+ {"ADJSP", LTYPE2, x86.AADJSP},
+ {"ANDB", LTYPE3, x86.AANDB},
+ {"ANDL", LTYPE3, x86.AANDL},
+ {"ANDQ", LTYPE3, x86.AANDQ},
+ {"ANDW", LTYPE3, x86.AANDW},
+ {"ARPL", LTYPE3, x86.AARPL},
+ {"BOUNDL", LTYPE3, x86.ABOUNDL},
+ {"BOUNDW", LTYPE3, x86.ABOUNDW},
+ {"BSFL", LTYPE3, x86.ABSFL},
+ {"BSFQ", LTYPE3, x86.ABSFQ},
+ {"BSFW", LTYPE3, x86.ABSFW},
+ {"BSRL", LTYPE3, x86.ABSRL},
+ {"BSRQ", LTYPE3, x86.ABSRQ},
+ {"BSRW", LTYPE3, x86.ABSRW},
+ {"BSWAPL", LTYPE1, x86.ABSWAPL},
+ {"BSWAPQ", LTYPE1, x86.ABSWAPQ},
+ {"BTCL", LTYPE3, x86.ABTCL},
+ {"BTCQ", LTYPE3, x86.ABTCQ},
+ {"BTCW", LTYPE3, x86.ABTCW},
+ {"BTL", LTYPE3, x86.ABTL},
+ {"BTQ", LTYPE3, x86.ABTQ},
+ {"BTRL", LTYPE3, x86.ABTRL},
+ {"BTRQ", LTYPE3, x86.ABTRQ},
+ {"BTRW", LTYPE3, x86.ABTRW},
+ {"BTSL", LTYPE3, x86.ABTSL},
+ {"BTSQ", LTYPE3, x86.ABTSQ},
+ {"BTSW", LTYPE3, x86.ABTSW},
+ {"BTW", LTYPE3, x86.ABTW},
+ {"BYTE", LTYPE2, x86.ABYTE},
+ {"CALL", LTYPEC, x86.ACALL},
+ {"CLC", LTYPE0, x86.ACLC},
+ {"CLD", LTYPE0, x86.ACLD},
+ {"CLI", LTYPE0, x86.ACLI},
+ {"CLTS", LTYPE0, x86.ACLTS},
+ {"CMC", LTYPE0, x86.ACMC},
+ {"CMPB", LTYPE4, x86.ACMPB},
+ {"CMPL", LTYPE4, x86.ACMPL},
+ {"CMPQ", LTYPE4, x86.ACMPQ},
+ {"CMPW", LTYPE4, x86.ACMPW},
+ {"CMPSB", LTYPE0, x86.ACMPSB},
+ {"CMPSL", LTYPE0, x86.ACMPSL},
+ {"CMPSQ", LTYPE0, x86.ACMPSQ},
+ {"CMPSW", LTYPE0, x86.ACMPSW},
+ {"CMPXCHG8B", LTYPE1, x86.ACMPXCHG8B},
+ {"CMPXCHGB", LTYPE3, x86.ACMPXCHGB}, /* LTYPE3? */
+ {"CMPXCHGL", LTYPE3, x86.ACMPXCHGL},
+ {"CMPXCHGQ", LTYPE3, x86.ACMPXCHGQ},
+ {"CMPXCHGW", LTYPE3, x86.ACMPXCHGW},
+ {"CPUID", LTYPE0, x86.ACPUID},
+ {"DAA", LTYPE0, x86.ADAA},
+ {"DAS", LTYPE0, x86.ADAS},
+ {"DATA", LTYPED, x86.ADATA},
+ {"DECB", LTYPE1, x86.ADECB},
+ {"DECL", LTYPE1, x86.ADECL},
+ {"DECQ", LTYPE1, x86.ADECQ},
+ {"DECW", LTYPE1, x86.ADECW},
+ {"DIVB", LTYPE2, x86.ADIVB},
+ {"DIVL", LTYPE2, x86.ADIVL},
+ {"DIVQ", LTYPE2, x86.ADIVQ},
+ {"DIVW", LTYPE2, x86.ADIVW},
+ {"EMMS", LTYPE0, x86.AEMMS},
+ {"END", LTYPE0, x86.AEND},
+ {"ENTER", LTYPE2, x86.AENTER},
+ {"GLOBL", LTYPEG, x86.AGLOBL},
+ {"HLT", LTYPE0, x86.AHLT},
+ {"IDIVB", LTYPE2, x86.AIDIVB},
+ {"IDIVL", LTYPE2, x86.AIDIVL},
+ {"IDIVQ", LTYPE2, x86.AIDIVQ},
+ {"IDIVW", LTYPE2, x86.AIDIVW},
+ {"IMULB", LTYPEI, x86.AIMULB},
+ {"IMULL", LTYPEI, x86.AIMULL},
+ {"IMULQ", LTYPEI, x86.AIMULQ},
+ {"IMUL3Q", LTYPEX, x86.AIMUL3Q},
+ {"IMULW", LTYPEI, x86.AIMULW},
+ {"INB", LTYPE0, x86.AINB},
+ {"INL", LTYPE0, x86.AINL},
+ {"INW", LTYPE0, x86.AINW},
+ {"INCB", LTYPE1, x86.AINCB},
+ {"INCL", LTYPE1, x86.AINCL},
+ {"INCQ", LTYPE1, x86.AINCQ},
+ {"INCW", LTYPE1, x86.AINCW},
+ {"INSB", LTYPE0, x86.AINSB},
+ {"INSL", LTYPE0, x86.AINSL},
+ {"INSW", LTYPE0, x86.AINSW},
+ {"INT", LTYPE2, x86.AINT},
+ {"INTO", LTYPE0, x86.AINTO},
+ {"INVD", LTYPE0, x86.AINVD},
+ {"INVLPG", LTYPE2, x86.AINVLPG},
+ {"IRETL", LTYPE0, x86.AIRETL},
+ {"IRETQ", LTYPE0, x86.AIRETQ},
+ {"IRETW", LTYPE0, x86.AIRETW},
+ {"JOS", LTYPER, x86.AJOS}, /* overflow set (OF = 1) */
+ {"JO", LTYPER, x86.AJOS}, /* alternate */
+ {"JOC", LTYPER, x86.AJOC}, /* overflow clear (OF = 0) */
+ {"JNO", LTYPER, x86.AJOC}, /* alternate */
+ {"JCS", LTYPER, x86.AJCS}, /* carry set (CF = 1) */
+ {"JB", LTYPER, x86.AJCS}, /* alternate */
+ {"JC", LTYPER, x86.AJCS}, /* alternate */
+ {"JNAE", LTYPER, x86.AJCS}, /* alternate */
+ {"JLO", LTYPER, x86.AJCS}, /* alternate */
+ {"JCC", LTYPER, x86.AJCC}, /* carry clear (CF = 0) */
+ {"JAE", LTYPER, x86.AJCC}, /* alternate */
+ {"JNB", LTYPER, x86.AJCC}, /* alternate */
+ {"JNC", LTYPER, x86.AJCC}, /* alternate */
+ {"JHS", LTYPER, x86.AJCC}, /* alternate */
+ {"JEQ", LTYPER, x86.AJEQ}, /* equal (ZF = 1) */
+ {"JE", LTYPER, x86.AJEQ}, /* alternate */
+ {"JZ", LTYPER, x86.AJEQ}, /* alternate */
+ {"JNE", LTYPER, x86.AJNE}, /* not equal (ZF = 0) */
+ {"JNZ", LTYPER, x86.AJNE}, /* alternate */
+ {"JLS", LTYPER, x86.AJLS}, /* lower or same (unsigned) (CF = 1 || ZF = 1) */
+ {"JBE", LTYPER, x86.AJLS}, /* alternate */
+ {"JNA", LTYPER, x86.AJLS}, /* alternate */
+ {"JHI", LTYPER, x86.AJHI}, /* higher (unsigned) (CF = 0 && ZF = 0) */
+ {"JA", LTYPER, x86.AJHI}, /* alternate */
+ {"JNBE", LTYPER, x86.AJHI}, /* alternate */
+ {"JMI", LTYPER, x86.AJMI}, /* negative (minus) (SF = 1) */
+ {"JS", LTYPER, x86.AJMI}, /* alternate */
+ {"JPL", LTYPER, x86.AJPL}, /* non-negative (plus) (SF = 0) */
+ {"JNS", LTYPER, x86.AJPL}, /* alternate */
+ {"JPS", LTYPER, x86.AJPS}, /* parity set (PF = 1) */
+ {"JP", LTYPER, x86.AJPS}, /* alternate */
+ {"JPE", LTYPER, x86.AJPS}, /* alternate */
+ {"JPC", LTYPER, x86.AJPC}, /* parity clear (PF = 0) */
+ {"JNP", LTYPER, x86.AJPC}, /* alternate */
+ {"JPO", LTYPER, x86.AJPC}, /* alternate */
+ {"JLT", LTYPER, x86.AJLT}, /* less than (signed) (SF != OF) */
+ {"JL", LTYPER, x86.AJLT}, /* alternate */
+ {"JNGE", LTYPER, x86.AJLT}, /* alternate */
+ {"JGE", LTYPER, x86.AJGE}, /* greater than or equal (signed) (SF = OF) */
+ {"JNL", LTYPER, x86.AJGE}, /* alternate */
+ {"JLE", LTYPER, x86.AJLE}, /* less than or equal (signed) (ZF = 1 || SF != OF) */
+ {"JNG", LTYPER, x86.AJLE}, /* alternate */
+ {"JGT", LTYPER, x86.AJGT}, /* greater than (signed) (ZF = 0 && SF = OF) */
+ {"JG", LTYPER, x86.AJGT}, /* alternate */
+ {"JNLE", LTYPER, x86.AJGT}, /* alternate */
+ {"JCXZL", LTYPER, x86.AJCXZL},
+ {"JCXZQ", LTYPER, x86.AJCXZQ},
+ {"JMP", LTYPEC, x86.AJMP},
+ {"LAHF", LTYPE0, x86.ALAHF},
+ {"LARL", LTYPE3, x86.ALARL},
+ {"LARW", LTYPE3, x86.ALARW},
+ {"LEAL", LTYPE3, x86.ALEAL},
+ {"LEAQ", LTYPE3, x86.ALEAQ},
+ {"LEAW", LTYPE3, x86.ALEAW},
+ {"LEAVEL", LTYPE0, x86.ALEAVEL},
+ {"LEAVEQ", LTYPE0, x86.ALEAVEQ},
+ {"LEAVEW", LTYPE0, x86.ALEAVEW},
+ {"LFENCE", LTYPE0, x86.ALFENCE},
+ {"LOCK", LTYPE0, x86.ALOCK},
+ {"LODSB", LTYPE0, x86.ALODSB},
+ {"LODSL", LTYPE0, x86.ALODSL},
+ {"LODSQ", LTYPE0, x86.ALODSQ},
+ {"LODSW", LTYPE0, x86.ALODSW},
+ {"LONG", LTYPE2, x86.ALONG},
+ {"LOOP", LTYPER, x86.ALOOP},
+ {"LOOPEQ", LTYPER, x86.ALOOPEQ},
+ {"LOOPNE", LTYPER, x86.ALOOPNE},
+ {"LSLL", LTYPE3, x86.ALSLL},
+ {"LSLW", LTYPE3, x86.ALSLW},
+ {"MFENCE", LTYPE0, x86.AMFENCE},
+ {"MODE", LTYPE2, x86.AMODE},
+ {"MOVB", LTYPE3, x86.AMOVB},
+ {"MOVL", LTYPEM, x86.AMOVL},
+ {"MOVQ", LTYPEM, x86.AMOVQ},
+ {"MOVW", LTYPEM, x86.AMOVW},
+ {"MOVBLSX", LTYPE3, x86.AMOVBLSX},
+ {"MOVBLZX", LTYPE3, x86.AMOVBLZX},
+ {"MOVBQSX", LTYPE3, x86.AMOVBQSX},
+ {"MOVBQZX", LTYPE3, x86.AMOVBQZX},
+ {"MOVBWSX", LTYPE3, x86.AMOVBWSX},
+ {"MOVBWZX", LTYPE3, x86.AMOVBWZX},
+ {"MOVLQSX", LTYPE3, x86.AMOVLQSX},
+ {"MOVLQZX", LTYPE3, x86.AMOVLQZX},
+ {"MOVNTIL", LTYPE3, x86.AMOVNTIL},
+ {"MOVNTIQ", LTYPE3, x86.AMOVNTIQ},
+ {"MOVQL", LTYPE3, x86.AMOVQL},
+ {"MOVWLSX", LTYPE3, x86.AMOVWLSX},
+ {"MOVWLZX", LTYPE3, x86.AMOVWLZX},
+ {"MOVWQSX", LTYPE3, x86.AMOVWQSX},
+ {"MOVWQZX", LTYPE3, x86.AMOVWQZX},
+ {"MOVSB", LTYPE0, x86.AMOVSB},
+ {"MOVSL", LTYPE0, x86.AMOVSL},
+ {"MOVSQ", LTYPE0, x86.AMOVSQ},
+ {"MOVSW", LTYPE0, x86.AMOVSW},
+ {"MULB", LTYPE2, x86.AMULB},
+ {"MULL", LTYPE2, x86.AMULL},
+ {"MULQ", LTYPE2, x86.AMULQ},
+ {"MULW", LTYPE2, x86.AMULW},
+ {"NEGB", LTYPE1, x86.ANEGB},
+ {"NEGL", LTYPE1, x86.ANEGL},
+ {"NEGQ", LTYPE1, x86.ANEGQ},
+ {"NEGW", LTYPE1, x86.ANEGW},
+ {"NOP", LTYPEN, x86.ANOP},
+ {"NOTB", LTYPE1, x86.ANOTB},
+ {"NOTL", LTYPE1, x86.ANOTL},
+ {"NOTQ", LTYPE1, x86.ANOTQ},
+ {"NOTW", LTYPE1, x86.ANOTW},
+ {"ORB", LTYPE3, x86.AORB},
+ {"ORL", LTYPE3, x86.AORL},
+ {"ORQ", LTYPE3, x86.AORQ},
+ {"ORW", LTYPE3, x86.AORW},
+ {"OUTB", LTYPE0, x86.AOUTB},
+ {"OUTL", LTYPE0, x86.AOUTL},
+ {"OUTW", LTYPE0, x86.AOUTW},
+ {"OUTSB", LTYPE0, x86.AOUTSB},
+ {"OUTSL", LTYPE0, x86.AOUTSL},
+ {"OUTSW", LTYPE0, x86.AOUTSW},
+ {"PAUSE", LTYPEN, x86.APAUSE},
+ {"POPAL", LTYPE0, x86.APOPAL},
+ {"POPAW", LTYPE0, x86.APOPAW},
+ {"POPFL", LTYPE0, x86.APOPFL},
+ {"POPFQ", LTYPE0, x86.APOPFQ},
+ {"POPFW", LTYPE0, x86.APOPFW},
+ {"POPL", LTYPE1, x86.APOPL},
+ {"POPQ", LTYPE1, x86.APOPQ},
+ {"POPW", LTYPE1, x86.APOPW},
+ {"PUSHAL", LTYPE0, x86.APUSHAL},
+ {"PUSHAW", LTYPE0, x86.APUSHAW},
+ {"PUSHFL", LTYPE0, x86.APUSHFL},
+ {"PUSHFQ", LTYPE0, x86.APUSHFQ},
+ {"PUSHFW", LTYPE0, x86.APUSHFW},
+ {"PUSHL", LTYPE2, x86.APUSHL},
+ {"PUSHQ", LTYPE2, x86.APUSHQ},
+ {"PUSHW", LTYPE2, x86.APUSHW},
+ {"RCLB", LTYPE3, x86.ARCLB},
+ {"RCLL", LTYPE3, x86.ARCLL},
+ {"RCLQ", LTYPE3, x86.ARCLQ},
+ {"RCLW", LTYPE3, x86.ARCLW},
+ {"RCRB", LTYPE3, x86.ARCRB},
+ {"RCRL", LTYPE3, x86.ARCRL},
+ {"RCRQ", LTYPE3, x86.ARCRQ},
+ {"RCRW", LTYPE3, x86.ARCRW},
+ {"RDMSR", LTYPE0, x86.ARDMSR},
+ {"RDPMC", LTYPE0, x86.ARDPMC},
+ {"RDTSC", LTYPE0, x86.ARDTSC},
+ {"REP", LTYPE0, x86.AREP},
+ {"REPN", LTYPE0, x86.AREPN},
+ {"RET", LTYPE0, x86.ARET},
+ {"RETFL", LTYPERT, x86.ARETFL},
+ {"RETFW", LTYPERT, x86.ARETFW},
+ {"RETFQ", LTYPERT, x86.ARETFQ},
+ {"ROLB", LTYPE3, x86.AROLB},
+ {"ROLL", LTYPE3, x86.AROLL},
+ {"ROLQ", LTYPE3, x86.AROLQ},
+ {"ROLW", LTYPE3, x86.AROLW},
+ {"RORB", LTYPE3, x86.ARORB},
+ {"RORL", LTYPE3, x86.ARORL},
+ {"RORQ", LTYPE3, x86.ARORQ},
+ {"RORW", LTYPE3, x86.ARORW},
+ {"RSM", LTYPE0, x86.ARSM},
+ {"SAHF", LTYPE0, x86.ASAHF},
+ {"SALB", LTYPE3, x86.ASALB},
+ {"SALL", LTYPE3, x86.ASALL},
+ {"SALQ", LTYPE3, x86.ASALQ},
+ {"SALW", LTYPE3, x86.ASALW},
+ {"SARB", LTYPE3, x86.ASARB},
+ {"SARL", LTYPE3, x86.ASARL},
+ {"SARQ", LTYPE3, x86.ASARQ},
+ {"SARW", LTYPE3, x86.ASARW},
+ {"SBBB", LTYPE3, x86.ASBBB},
+ {"SBBL", LTYPE3, x86.ASBBL},
+ {"SBBQ", LTYPE3, x86.ASBBQ},
+ {"SBBW", LTYPE3, x86.ASBBW},
+ {"SCASB", LTYPE0, x86.ASCASB},
+ {"SCASL", LTYPE0, x86.ASCASL},
+ {"SCASQ", LTYPE0, x86.ASCASQ},
+ {"SCASW", LTYPE0, x86.ASCASW},
+ {"SETCC", LTYPE1, x86.ASETCC}, /* see JCC etc above for condition codes */
+ {"SETCS", LTYPE1, x86.ASETCS},
+ {"SETEQ", LTYPE1, x86.ASETEQ},
+ {"SETGE", LTYPE1, x86.ASETGE},
+ {"SETGT", LTYPE1, x86.ASETGT},
+ {"SETHI", LTYPE1, x86.ASETHI},
+ {"SETLE", LTYPE1, x86.ASETLE},
+ {"SETLS", LTYPE1, x86.ASETLS},
+ {"SETLT", LTYPE1, x86.ASETLT},
+ {"SETMI", LTYPE1, x86.ASETMI},
+ {"SETNE", LTYPE1, x86.ASETNE},
+ {"SETOC", LTYPE1, x86.ASETOC},
+ {"SETOS", LTYPE1, x86.ASETOS},
+ {"SETPC", LTYPE1, x86.ASETPC},
+ {"SETPL", LTYPE1, x86.ASETPL},
+ {"SETPS", LTYPE1, x86.ASETPS},
+ {"SFENCE", LTYPE0, x86.ASFENCE},
+ {"CDQ", LTYPE0, x86.ACDQ},
+ {"CWD", LTYPE0, x86.ACWD},
+ {"CQO", LTYPE0, x86.ACQO},
+ {"SHLB", LTYPE3, x86.ASHLB},
+ {"SHLL", LTYPES, x86.ASHLL},
+ {"SHLQ", LTYPES, x86.ASHLQ},
+ {"SHLW", LTYPES, x86.ASHLW},
+ {"SHRB", LTYPE3, x86.ASHRB},
+ {"SHRL", LTYPES, x86.ASHRL},
+ {"SHRQ", LTYPES, x86.ASHRQ},
+ {"SHRW", LTYPES, x86.ASHRW},
+ {"STC", LTYPE0, x86.ASTC},
+ {"STD", LTYPE0, x86.ASTD},
+ {"STI", LTYPE0, x86.ASTI},
+ {"STOSB", LTYPE0, x86.ASTOSB},
+ {"STOSL", LTYPE0, x86.ASTOSL},
+ {"STOSQ", LTYPE0, x86.ASTOSQ},
+ {"STOSW", LTYPE0, x86.ASTOSW},
+ {"SUBB", LTYPE3, x86.ASUBB},
+ {"SUBL", LTYPE3, x86.ASUBL},
+ {"SUBQ", LTYPE3, x86.ASUBQ},
+ {"SUBW", LTYPE3, x86.ASUBW},
+ {"SYSCALL", LTYPE0, x86.ASYSCALL},
+ {"SYSRET", LTYPE0, x86.ASYSRET},
+ {"SWAPGS", LTYPE0, x86.ASWAPGS},
+ {"TESTB", LTYPE3, x86.ATESTB},
+ {"TESTL", LTYPE3, x86.ATESTL},
+ {"TESTQ", LTYPE3, x86.ATESTQ},
+ {"TESTW", LTYPE3, x86.ATESTW},
+ {"TEXT", LTYPET, x86.ATEXT},
+ {"VERR", LTYPE2, x86.AVERR},
+ {"VERW", LTYPE2, x86.AVERW},
+ {"QUAD", LTYPE2, x86.AQUAD},
+ {"WAIT", LTYPE0, x86.AWAIT},
+ {"WBINVD", LTYPE0, x86.AWBINVD},
+ {"WRMSR", LTYPE0, x86.AWRMSR},
+ {"WORD", LTYPE2, x86.AWORD},
+ {"XADDB", LTYPE3, x86.AXADDB},
+ {"XADDL", LTYPE3, x86.AXADDL},
+ {"XADDQ", LTYPE3, x86.AXADDQ},
+ {"XADDW", LTYPE3, x86.AXADDW},
+ {"XCHGB", LTYPE3, x86.AXCHGB},
+ {"XCHGL", LTYPE3, x86.AXCHGL},
+ {"XCHGQ", LTYPE3, x86.AXCHGQ},
+ {"XCHGW", LTYPE3, x86.AXCHGW},
+ {"XLAT", LTYPE2, x86.AXLAT},
+ {"XORB", LTYPE3, x86.AXORB},
+ {"XORL", LTYPE3, x86.AXORL},
+ {"XORQ", LTYPE3, x86.AXORQ},
+ {"XORW", LTYPE3, x86.AXORW},
+ {"CMOVLCC", LTYPE3, x86.ACMOVLCC},
+ {"CMOVLCS", LTYPE3, x86.ACMOVLCS},
+ {"CMOVLEQ", LTYPE3, x86.ACMOVLEQ},
+ {"CMOVLGE", LTYPE3, x86.ACMOVLGE},
+ {"CMOVLGT", LTYPE3, x86.ACMOVLGT},
+ {"CMOVLHI", LTYPE3, x86.ACMOVLHI},
+ {"CMOVLLE", LTYPE3, x86.ACMOVLLE},
+ {"CMOVLLS", LTYPE3, x86.ACMOVLLS},
+ {"CMOVLLT", LTYPE3, x86.ACMOVLLT},
+ {"CMOVLMI", LTYPE3, x86.ACMOVLMI},
+ {"CMOVLNE", LTYPE3, x86.ACMOVLNE},
+ {"CMOVLOC", LTYPE3, x86.ACMOVLOC},
+ {"CMOVLOS", LTYPE3, x86.ACMOVLOS},
+ {"CMOVLPC", LTYPE3, x86.ACMOVLPC},
+ {"CMOVLPL", LTYPE3, x86.ACMOVLPL},
+ {"CMOVLPS", LTYPE3, x86.ACMOVLPS},
+ {"CMOVQCC", LTYPE3, x86.ACMOVQCC},
+ {"CMOVQCS", LTYPE3, x86.ACMOVQCS},
+ {"CMOVQEQ", LTYPE3, x86.ACMOVQEQ},
+ {"CMOVQGE", LTYPE3, x86.ACMOVQGE},
+ {"CMOVQGT", LTYPE3, x86.ACMOVQGT},
+ {"CMOVQHI", LTYPE3, x86.ACMOVQHI},
+ {"CMOVQLE", LTYPE3, x86.ACMOVQLE},
+ {"CMOVQLS", LTYPE3, x86.ACMOVQLS},
+ {"CMOVQLT", LTYPE3, x86.ACMOVQLT},
+ {"CMOVQMI", LTYPE3, x86.ACMOVQMI},
+ {"CMOVQNE", LTYPE3, x86.ACMOVQNE},
+ {"CMOVQOC", LTYPE3, x86.ACMOVQOC},
+ {"CMOVQOS", LTYPE3, x86.ACMOVQOS},
+ {"CMOVQPC", LTYPE3, x86.ACMOVQPC},
+ {"CMOVQPL", LTYPE3, x86.ACMOVQPL},
+ {"CMOVQPS", LTYPE3, x86.ACMOVQPS},
+ {"CMOVWCC", LTYPE3, x86.ACMOVWCC},
+ {"CMOVWCS", LTYPE3, x86.ACMOVWCS},
+ {"CMOVWEQ", LTYPE3, x86.ACMOVWEQ},
+ {"CMOVWGE", LTYPE3, x86.ACMOVWGE},
+ {"CMOVWGT", LTYPE3, x86.ACMOVWGT},
+ {"CMOVWHI", LTYPE3, x86.ACMOVWHI},
+ {"CMOVWLE", LTYPE3, x86.ACMOVWLE},
+ {"CMOVWLS", LTYPE3, x86.ACMOVWLS},
+ {"CMOVWLT", LTYPE3, x86.ACMOVWLT},
+ {"CMOVWMI", LTYPE3, x86.ACMOVWMI},
+ {"CMOVWNE", LTYPE3, x86.ACMOVWNE},
+ {"CMOVWOC", LTYPE3, x86.ACMOVWOC},
+ {"CMOVWOS", LTYPE3, x86.ACMOVWOS},
+ {"CMOVWPC", LTYPE3, x86.ACMOVWPC},
+ {"CMOVWPL", LTYPE3, x86.ACMOVWPL},
+ {"CMOVWPS", LTYPE3, x86.ACMOVWPS},
+ {"FMOVB", LTYPE3, x86.AFMOVB},
+ {"FMOVBP", LTYPE3, x86.AFMOVBP},
+ {"FMOVD", LTYPE3, x86.AFMOVD},
+ {"FMOVDP", LTYPE3, x86.AFMOVDP},
+ {"FMOVF", LTYPE3, x86.AFMOVF},
+ {"FMOVFP", LTYPE3, x86.AFMOVFP},
+ {"FMOVL", LTYPE3, x86.AFMOVL},
+ {"FMOVLP", LTYPE3, x86.AFMOVLP},
+ {"FMOVV", LTYPE3, x86.AFMOVV},
+ {"FMOVVP", LTYPE3, x86.AFMOVVP},
+ {"FMOVW", LTYPE3, x86.AFMOVW},
+ {"FMOVWP", LTYPE3, x86.AFMOVWP},
+ {"FMOVX", LTYPE3, x86.AFMOVX},
+ {"FMOVXP", LTYPE3, x86.AFMOVXP},
+ {"FCOMB", LTYPE3, x86.AFCOMB},
+ {"FCOMBP", LTYPE3, x86.AFCOMBP},
+ {"FCOMD", LTYPE3, x86.AFCOMD},
+ {"FCOMDP", LTYPE3, x86.AFCOMDP},
+ {"FCOMDPP", LTYPE3, x86.AFCOMDPP},
+ {"FCOMF", LTYPE3, x86.AFCOMF},
+ {"FCOMFP", LTYPE3, x86.AFCOMFP},
+ {"FCOML", LTYPE3, x86.AFCOML},
+ {"FCOMLP", LTYPE3, x86.AFCOMLP},
+ {"FCOMW", LTYPE3, x86.AFCOMW},
+ {"FCOMWP", LTYPE3, x86.AFCOMWP},
+ {"FUCOM", LTYPE3, x86.AFUCOM},
+ {"FUCOMP", LTYPE3, x86.AFUCOMP},
+ {"FUCOMPP", LTYPE3, x86.AFUCOMPP},
+ {"FADDW", LTYPE3, x86.AFADDW},
+ {"FADDL", LTYPE3, x86.AFADDL},
+ {"FADDF", LTYPE3, x86.AFADDF},
+ {"FADDD", LTYPE3, x86.AFADDD},
+ {"FADDDP", LTYPE3, x86.AFADDDP},
+ {"FSUBDP", LTYPE3, x86.AFSUBDP},
+ {"FSUBW", LTYPE3, x86.AFSUBW},
+ {"FSUBL", LTYPE3, x86.AFSUBL},
+ {"FSUBF", LTYPE3, x86.AFSUBF},
+ {"FSUBD", LTYPE3, x86.AFSUBD},
+ {"FSUBRDP", LTYPE3, x86.AFSUBRDP},
+ {"FSUBRW", LTYPE3, x86.AFSUBRW},
+ {"FSUBRL", LTYPE3, x86.AFSUBRL},
+ {"FSUBRF", LTYPE3, x86.AFSUBRF},
+ {"FSUBRD", LTYPE3, x86.AFSUBRD},
+ {"FMULDP", LTYPE3, x86.AFMULDP},
+ {"FMULW", LTYPE3, x86.AFMULW},
+ {"FMULL", LTYPE3, x86.AFMULL},
+ {"FMULF", LTYPE3, x86.AFMULF},
+ {"FMULD", LTYPE3, x86.AFMULD},
+ {"FDIVDP", LTYPE3, x86.AFDIVDP},
+ {"FDIVW", LTYPE3, x86.AFDIVW},
+ {"FDIVL", LTYPE3, x86.AFDIVL},
+ {"FDIVF", LTYPE3, x86.AFDIVF},
+ {"FDIVD", LTYPE3, x86.AFDIVD},
+ {"FDIVRDP", LTYPE3, x86.AFDIVRDP},
+ {"FDIVRW", LTYPE3, x86.AFDIVRW},
+ {"FDIVRL", LTYPE3, x86.AFDIVRL},
+ {"FDIVRF", LTYPE3, x86.AFDIVRF},
+ {"FDIVRD", LTYPE3, x86.AFDIVRD},
+ {"FXCHD", LTYPE3, x86.AFXCHD},
+ {"FFREE", LTYPE1, x86.AFFREE},
+ {"FLDCW", LTYPE2, x86.AFLDCW},
+ {"FLDENV", LTYPE1, x86.AFLDENV},
+ {"FRSTOR", LTYPE2, x86.AFRSTOR},
+ {"FSAVE", LTYPE1, x86.AFSAVE},
+ {"FSTCW", LTYPE1, x86.AFSTCW},
+ {"FSTENV", LTYPE1, x86.AFSTENV},
+ {"FSTSW", LTYPE1, x86.AFSTSW},
+ {"F2XM1", LTYPE0, x86.AF2XM1},
+ {"FABS", LTYPE0, x86.AFABS},
+ {"FCHS", LTYPE0, x86.AFCHS},
+ {"FCLEX", LTYPE0, x86.AFCLEX},
+ {"FCOS", LTYPE0, x86.AFCOS},
+ {"FDECSTP", LTYPE0, x86.AFDECSTP},
+ {"FINCSTP", LTYPE0, x86.AFINCSTP},
+ {"FINIT", LTYPE0, x86.AFINIT},
+ {"FLD1", LTYPE0, x86.AFLD1},
+ {"FLDL2E", LTYPE0, x86.AFLDL2E},
+ {"FLDL2T", LTYPE0, x86.AFLDL2T},
+ {"FLDLG2", LTYPE0, x86.AFLDLG2},
+ {"FLDLN2", LTYPE0, x86.AFLDLN2},
+ {"FLDPI", LTYPE0, x86.AFLDPI},
+ {"FLDZ", LTYPE0, x86.AFLDZ},
+ {"FNOP", LTYPE0, x86.AFNOP},
+ {"FPATAN", LTYPE0, x86.AFPATAN},
+ {"FPREM", LTYPE0, x86.AFPREM},
+ {"FPREM1", LTYPE0, x86.AFPREM1},
+ {"FPTAN", LTYPE0, x86.AFPTAN},
+ {"FRNDINT", LTYPE0, x86.AFRNDINT},
+ {"FSCALE", LTYPE0, x86.AFSCALE},
+ {"FSIN", LTYPE0, x86.AFSIN},
+ {"FSINCOS", LTYPE0, x86.AFSINCOS},
+ {"FSQRT", LTYPE0, x86.AFSQRT},
+ {"FTST", LTYPE0, x86.AFTST},
+ {"FXAM", LTYPE0, x86.AFXAM},
+ {"FXTRACT", LTYPE0, x86.AFXTRACT},
+ {"FYL2X", LTYPE0, x86.AFYL2X},
+ {"FYL2XP1", LTYPE0, x86.AFYL2XP1},
+ {"ADDPD", LTYPE3, x86.AADDPD},
+ {"ADDPS", LTYPE3, x86.AADDPS},
+ {"ADDSD", LTYPE3, x86.AADDSD},
+ {"ADDSS", LTYPE3, x86.AADDSS},
+ {"ANDNPD", LTYPE3, x86.AANDNPD},
+ {"ANDNPS", LTYPE3, x86.AANDNPS},
+ {"ANDPD", LTYPE3, x86.AANDPD},
+ {"ANDPS", LTYPE3, x86.AANDPS},
+ {"CMPPD", LTYPEXC, x86.ACMPPD},
+ {"CMPPS", LTYPEXC, x86.ACMPPS},
+ {"CMPSD", LTYPEXC, x86.ACMPSD},
+ {"CMPSS", LTYPEXC, x86.ACMPSS},
+ {"COMISD", LTYPE3, x86.ACOMISD},
+ {"COMISS", LTYPE3, x86.ACOMISS},
+ {"CVTPL2PD", LTYPE3, x86.ACVTPL2PD},
+ {"CVTPL2PS", LTYPE3, x86.ACVTPL2PS},
+ {"CVTPD2PL", LTYPE3, x86.ACVTPD2PL},
+ {"CVTPD2PS", LTYPE3, x86.ACVTPD2PS},
+ {"CVTPS2PL", LTYPE3, x86.ACVTPS2PL},
+ {"PF2IW", LTYPE3, x86.APF2IW},
+ {"PF2IL", LTYPE3, x86.APF2IL},
+ {"PF2ID", LTYPE3, x86.APF2IL}, /* syn */
+ {"PI2FL", LTYPE3, x86.API2FL},
+ {"PI2FD", LTYPE3, x86.API2FL}, /* syn */
+ {"PI2FW", LTYPE3, x86.API2FW},
+ {"CVTPS2PD", LTYPE3, x86.ACVTPS2PD},
+ {"CVTSD2SL", LTYPE3, x86.ACVTSD2SL},
+ {"CVTSD2SQ", LTYPE3, x86.ACVTSD2SQ},
+ {"CVTSD2SS", LTYPE3, x86.ACVTSD2SS},
+ {"CVTSL2SD", LTYPE3, x86.ACVTSL2SD},
+ {"CVTSQ2SD", LTYPE3, x86.ACVTSQ2SD},
+ {"CVTSL2SS", LTYPE3, x86.ACVTSL2SS},
+ {"CVTSQ2SS", LTYPE3, x86.ACVTSQ2SS},
+ {"CVTSS2SD", LTYPE3, x86.ACVTSS2SD},
+ {"CVTSS2SL", LTYPE3, x86.ACVTSS2SL},
+ {"CVTSS2SQ", LTYPE3, x86.ACVTSS2SQ},
+ {"CVTTPD2PL", LTYPE3, x86.ACVTTPD2PL},
+ {"CVTTPS2PL", LTYPE3, x86.ACVTTPS2PL},
+ {"CVTTSD2SL", LTYPE3, x86.ACVTTSD2SL},
+ {"CVTTSD2SQ", LTYPE3, x86.ACVTTSD2SQ},
+ {"CVTTSS2SL", LTYPE3, x86.ACVTTSS2SL},
+ {"CVTTSS2SQ", LTYPE3, x86.ACVTTSS2SQ},
+ {"DIVPD", LTYPE3, x86.ADIVPD},
+ {"DIVPS", LTYPE3, x86.ADIVPS},
+ {"DIVSD", LTYPE3, x86.ADIVSD},
+ {"DIVSS", LTYPE3, x86.ADIVSS},
+ {"FXRSTOR", LTYPE2, x86.AFXRSTOR},
+ {"FXRSTOR64", LTYPE2, x86.AFXRSTOR64},
+ {"FXSAVE", LTYPE1, x86.AFXSAVE},
+ {"FXSAVE64", LTYPE1, x86.AFXSAVE64},
+ {"LDMXCSR", LTYPE2, x86.ALDMXCSR},
+ {"MASKMOVOU", LTYPE3, x86.AMASKMOVOU},
+ {"MASKMOVDQU", LTYPE3, x86.AMASKMOVOU}, /* syn */
+ {"MASKMOVQ", LTYPE3, x86.AMASKMOVQ},
+ {"MAXPD", LTYPE3, x86.AMAXPD},
+ {"MAXPS", LTYPE3, x86.AMAXPS},
+ {"MAXSD", LTYPE3, x86.AMAXSD},
+ {"MAXSS", LTYPE3, x86.AMAXSS},
+ {"MINPD", LTYPE3, x86.AMINPD},
+ {"MINPS", LTYPE3, x86.AMINPS},
+ {"MINSD", LTYPE3, x86.AMINSD},
+ {"MINSS", LTYPE3, x86.AMINSS},
+ {"MOVAPD", LTYPE3, x86.AMOVAPD},
+ {"MOVAPS", LTYPE3, x86.AMOVAPS},
+ {"MOVD", LTYPE3, x86.AMOVQ}, /* syn */
+ {"MOVDQ2Q", LTYPE3, x86.AMOVQ}, /* syn */
+ {"MOVO", LTYPE3, x86.AMOVO},
+ {"MOVOA", LTYPE3, x86.AMOVO}, /* syn */
+ {"MOVOU", LTYPE3, x86.AMOVOU},
+ {"MOVHLPS", LTYPE3, x86.AMOVHLPS},
+ {"MOVHPD", LTYPE3, x86.AMOVHPD},
+ {"MOVHPS", LTYPE3, x86.AMOVHPS},
+ {"MOVLHPS", LTYPE3, x86.AMOVLHPS},
+ {"MOVLPD", LTYPE3, x86.AMOVLPD},
+ {"MOVLPS", LTYPE3, x86.AMOVLPS},
+ {"MOVMSKPD", LTYPE3, x86.AMOVMSKPD},
+ {"MOVMSKPS", LTYPE3, x86.AMOVMSKPS},
+ {"MOVNTO", LTYPE3, x86.AMOVNTO},
+ {"MOVNTDQ", LTYPE3, x86.AMOVNTO}, /* syn */
+ {"MOVNTPD", LTYPE3, x86.AMOVNTPD},
+ {"MOVNTPS", LTYPE3, x86.AMOVNTPS},
+ {"MOVNTQ", LTYPE3, x86.AMOVNTQ},
+ {"MOVQOZX", LTYPE3, x86.AMOVQOZX},
+ {"MOVSD", LTYPE3, x86.AMOVSD},
+ {"MOVSS", LTYPE3, x86.AMOVSS},
+ {"MOVUPD", LTYPE3, x86.AMOVUPD},
+ {"MOVUPS", LTYPE3, x86.AMOVUPS},
+ {"MULPD", LTYPE3, x86.AMULPD},
+ {"MULPS", LTYPE3, x86.AMULPS},
+ {"MULSD", LTYPE3, x86.AMULSD},
+ {"MULSS", LTYPE3, x86.AMULSS},
+ {"ORPD", LTYPE3, x86.AORPD},
+ {"ORPS", LTYPE3, x86.AORPS},
+ {"PACKSSLW", LTYPE3, x86.APACKSSLW},
+ {"PACKSSWB", LTYPE3, x86.APACKSSWB},
+ {"PACKUSWB", LTYPE3, x86.APACKUSWB},
+ {"PADDB", LTYPE3, x86.APADDB},
+ {"PADDL", LTYPE3, x86.APADDL},
+ {"PADDQ", LTYPE3, x86.APADDQ},
+ {"PADDSB", LTYPE3, x86.APADDSB},
+ {"PADDSW", LTYPE3, x86.APADDSW},
+ {"PADDUSB", LTYPE3, x86.APADDUSB},
+ {"PADDUSW", LTYPE3, x86.APADDUSW},
+ {"PADDW", LTYPE3, x86.APADDW},
+ {"PAND", LTYPE3, x86.APAND},
+ {"PANDB", LTYPE3, x86.APANDB},
+ {"PANDL", LTYPE3, x86.APANDL},
+ {"PANDSB", LTYPE3, x86.APANDSB},
+ {"PANDSW", LTYPE3, x86.APANDSW},
+ {"PANDUSB", LTYPE3, x86.APANDUSB},
+ {"PANDUSW", LTYPE3, x86.APANDUSW},
+ {"PANDW", LTYPE3, x86.APANDW},
+ {"PANDN", LTYPE3, x86.APANDN},
+ {"PAVGB", LTYPE3, x86.APAVGB},
+ {"PAVGW", LTYPE3, x86.APAVGW},
+ {"PCMPEQB", LTYPE3, x86.APCMPEQB},
+ {"PCMPEQL", LTYPE3, x86.APCMPEQL},
+ {"PCMPEQW", LTYPE3, x86.APCMPEQW},
+ {"PCMPGTB", LTYPE3, x86.APCMPGTB},
+ {"PCMPGTL", LTYPE3, x86.APCMPGTL},
+ {"PCMPGTW", LTYPE3, x86.APCMPGTW},
+ {"PEXTRW", LTYPEX, x86.APEXTRW},
+ {"PINSRW", LTYPEX, x86.APINSRW},
+ {"PINSRD", LTYPEX, x86.APINSRD},
+ {"PINSRQ", LTYPEX, x86.APINSRQ},
+ {"PMADDWL", LTYPE3, x86.APMADDWL},
+ {"PMAXSW", LTYPE3, x86.APMAXSW},
+ {"PMAXUB", LTYPE3, x86.APMAXUB},
+ {"PMINSW", LTYPE3, x86.APMINSW},
+ {"PMINUB", LTYPE3, x86.APMINUB},
+ {"PMOVMSKB", LTYPE3, x86.APMOVMSKB},
+ {"PMULHRW", LTYPE3, x86.APMULHRW},
+ {"PMULHUW", LTYPE3, x86.APMULHUW},
+ {"PMULHW", LTYPE3, x86.APMULHW},
+ {"PMULLW", LTYPE3, x86.APMULLW},
+ {"PMULULQ", LTYPE3, x86.APMULULQ},
+ {"POR", LTYPE3, x86.APOR},
+ {"PSADBW", LTYPE3, x86.APSADBW},
+ {"PSHUFHW", LTYPEX, x86.APSHUFHW},
+ {"PSHUFL", LTYPEX, x86.APSHUFL},
+ {"PSHUFLW", LTYPEX, x86.APSHUFLW},
+ {"PSHUFW", LTYPEX, x86.APSHUFW},
+ {"PSHUFB", LTYPEM, x86.APSHUFB},
+ {"PSLLO", LTYPE3, x86.APSLLO},
+ {"PSLLDQ", LTYPE3, x86.APSLLO}, /* syn */
+ {"PSLLL", LTYPE3, x86.APSLLL},
+ {"PSLLQ", LTYPE3, x86.APSLLQ},
+ {"PSLLW", LTYPE3, x86.APSLLW},
+ {"PSRAL", LTYPE3, x86.APSRAL},
+ {"PSRAW", LTYPE3, x86.APSRAW},
+ {"PSRLO", LTYPE3, x86.APSRLO},
+ {"PSRLDQ", LTYPE3, x86.APSRLO}, /* syn */
+ {"PSRLL", LTYPE3, x86.APSRLL},
+ {"PSRLQ", LTYPE3, x86.APSRLQ},
+ {"PSRLW", LTYPE3, x86.APSRLW},
+ {"PSUBB", LTYPE3, x86.APSUBB},
+ {"PSUBL", LTYPE3, x86.APSUBL},
+ {"PSUBQ", LTYPE3, x86.APSUBQ},
+ {"PSUBSB", LTYPE3, x86.APSUBSB},
+ {"PSUBSW", LTYPE3, x86.APSUBSW},
+ {"PSUBUSB", LTYPE3, x86.APSUBUSB},
+ {"PSUBUSW", LTYPE3, x86.APSUBUSW},
+ {"PSUBW", LTYPE3, x86.APSUBW},
+ {"PUNPCKHBW", LTYPE3, x86.APUNPCKHBW},
+ {"PUNPCKHLQ", LTYPE3, x86.APUNPCKHLQ},
+ {"PUNPCKHQDQ", LTYPE3, x86.APUNPCKHQDQ},
+ {"PUNPCKHWL", LTYPE3, x86.APUNPCKHWL},
+ {"PUNPCKLBW", LTYPE3, x86.APUNPCKLBW},
+ {"PUNPCKLLQ", LTYPE3, x86.APUNPCKLLQ},
+ {"PUNPCKLQDQ", LTYPE3, x86.APUNPCKLQDQ},
+ {"PUNPCKLWL", LTYPE3, x86.APUNPCKLWL},
+ {"PXOR", LTYPE3, x86.APXOR},
+ {"RCPPS", LTYPE3, x86.ARCPPS},
+ {"RCPSS", LTYPE3, x86.ARCPSS},
+ {"RSQRTPS", LTYPE3, x86.ARSQRTPS},
+ {"RSQRTSS", LTYPE3, x86.ARSQRTSS},
+ {"SHUFPD", LTYPEX, x86.ASHUFPD},
+ {"SHUFPS", LTYPEX, x86.ASHUFPS},
+ {"SQRTPD", LTYPE3, x86.ASQRTPD},
+ {"SQRTPS", LTYPE3, x86.ASQRTPS},
+ {"SQRTSD", LTYPE3, x86.ASQRTSD},
+ {"SQRTSS", LTYPE3, x86.ASQRTSS},
+ {"STMXCSR", LTYPE1, x86.ASTMXCSR},
+ {"SUBPD", LTYPE3, x86.ASUBPD},
+ {"SUBPS", LTYPE3, x86.ASUBPS},
+ {"SUBSD", LTYPE3, x86.ASUBSD},
+ {"SUBSS", LTYPE3, x86.ASUBSS},
+ {"UCOMISD", LTYPE3, x86.AUCOMISD},
+ {"UCOMISS", LTYPE3, x86.AUCOMISS},
+ {"UNPCKHPD", LTYPE3, x86.AUNPCKHPD},
+ {"UNPCKHPS", LTYPE3, x86.AUNPCKHPS},
+ {"UNPCKLPD", LTYPE3, x86.AUNPCKLPD},
+ {"UNPCKLPS", LTYPE3, x86.AUNPCKLPS},
+ {"XORPD", LTYPE3, x86.AXORPD},
+ {"XORPS", LTYPE3, x86.AXORPS},
+ {"CRC32B", LTYPE4, x86.ACRC32B},
+ {"CRC32Q", LTYPE4, x86.ACRC32Q},
+ {"PREFETCHT0", LTYPE2, x86.APREFETCHT0},
+ {"PREFETCHT1", LTYPE2, x86.APREFETCHT1},
+ {"PREFETCHT2", LTYPE2, x86.APREFETCHT2},
+ {"PREFETCHNTA", LTYPE2, x86.APREFETCHNTA},
+ {"UNDEF", LTYPE0, x86.AUNDEF},
+ {"AESENC", LTYPE3, x86.AAESENC},
+ {"AESENCLAST", LTYPE3, x86.AAESENCLAST},
+ {"AESDEC", LTYPE3, x86.AAESDEC},
+ {"AESDECLAST", LTYPE3, x86.AAESDECLAST},
+ {"AESIMC", LTYPE3, x86.AAESIMC},
+ {"AESKEYGENASSIST", LTYPEX, x86.AAESKEYGENASSIST},
+ {"PSHUFD", LTYPEX, x86.APSHUFD},
+ {"USEFIELD", LTYPEN, x86.AUSEFIELD},
+ {"PCLMULQDQ", LTYPEX, x86.APCLMULQDQ},
+ {"PCDATA", LTYPEPC, x86.APCDATA},
+ {"FUNCDATA", LTYPEF, x86.AFUNCDATA},
+}
+
+func cinit() {
+ nullgen.Type = x86.D_NONE
+ nullgen.Index = x86.D_NONE
+}
+
+func checkscale(scale int8) {
+ switch scale {
+ case 1,
+ 2,
+ 4,
+ 8:
+ return
+ }
+
+ yyerror("scale must be 1248: %d", scale)
+}
+
+func cclean() {
+ var g2 Addr2
+
+ g2.from = nullgen
+ g2.to = nullgen
+ outcode(x86.AEND, &g2)
+}
+
+var lastpc *obj.Prog
+
+type Addr2 struct {
+ from obj.Addr
+ to obj.Addr
+}
+
+func outcode(a int, g2 *Addr2) {
+ var p *obj.Prog
+ var pl *obj.Plist
+
+ if asm.Pass == 1 {
+ goto out
+ }
+
+ p = new(obj.Prog)
+ *p = obj.Prog{}
+ p.Ctxt = asm.Ctxt
+ p.As = int16(a)
+ p.Lineno = stmtline
+ p.From = g2.from
+ p.To = g2.to
+ p.Pc = int64(asm.PC)
+
+ if lastpc == nil {
+ pl = obj.Linknewplist(asm.Ctxt)
+ pl.Firstpc = p
+ } else {
+
+ lastpc.Link = p
+ }
+ lastpc = p
+
+out:
+ if a != x86.AGLOBL && a != x86.ADATA {
+ asm.PC++
+ }
+}
--- /dev/null
+//line a.y:32
+package main
+
+import __yyfmt__ "fmt"
+
+//line a.y:32
+import (
+ "cmd/internal/asm"
+ "cmd/internal/obj"
+ "cmd/internal/obj/x86"
+)
+
+//line a.y:41
+type yySymType struct {
+ yys int
+ sym *asm.Sym
+ lval int64
+ dval float64
+ sval string
+ addr obj.Addr
+ addr2 Addr2
+}
+
+const LTYPE0 = 57346
+const LTYPE1 = 57347
+const LTYPE2 = 57348
+const LTYPE3 = 57349
+const LTYPE4 = 57350
+const LTYPEC = 57351
+const LTYPED = 57352
+const LTYPEN = 57353
+const LTYPER = 57354
+const LTYPET = 57355
+const LTYPEG = 57356
+const LTYPEPC = 57357
+const LTYPES = 57358
+const LTYPEM = 57359
+const LTYPEI = 57360
+const LTYPEXC = 57361
+const LTYPEX = 57362
+const LTYPERT = 57363
+const LTYPEF = 57364
+const LCONST = 57365
+const LFP = 57366
+const LPC = 57367
+const LSB = 57368
+const LBREG = 57369
+const LLREG = 57370
+const LSREG = 57371
+const LFREG = 57372
+const LMREG = 57373
+const LXREG = 57374
+const LFCONST = 57375
+const LSCONST = 57376
+const LSP = 57377
+const LNAME = 57378
+const LLAB = 57379
+const LVAR = 57380
+
+var yyToknames = []string{
+ "'|'",
+ "'^'",
+ "'&'",
+ "'<'",
+ "'>'",
+ "'+'",
+ "'-'",
+ "'*'",
+ "'/'",
+ "'%'",
+ "LTYPE0",
+ "LTYPE1",
+ "LTYPE2",
+ "LTYPE3",
+ "LTYPE4",
+ "LTYPEC",
+ "LTYPED",
+ "LTYPEN",
+ "LTYPER",
+ "LTYPET",
+ "LTYPEG",
+ "LTYPEPC",
+ "LTYPES",
+ "LTYPEM",
+ "LTYPEI",
+ "LTYPEXC",
+ "LTYPEX",
+ "LTYPERT",
+ "LTYPEF",
+ "LCONST",
+ "LFP",
+ "LPC",
+ "LSB",
+ "LBREG",
+ "LLREG",
+ "LSREG",
+ "LFREG",
+ "LMREG",
+ "LXREG",
+ "LFCONST",
+ "LSCONST",
+ "LSP",
+ "LNAME",
+ "LLAB",
+ "LVAR",
+}
+var yyStatenames = []string{}
+
+const yyEofCode = 1
+const yyErrCode = 2
+const yyMaxDepth = 200
+
+//line yacctab:1
+var yyExca = []int{
+ -1, 1,
+ 1, -1,
+ -2, 2,
+}
+
+const yyNprod = 134
+const yyPrivate = 57344
+
+var yyTokenNames []string
+var yyStates []string
+
+const yyLast = 565
+
+var yyAct = []int{
+
+ 49, 61, 186, 123, 38, 3, 81, 80, 51, 62,
+ 47, 188, 269, 268, 267, 71, 70, 118, 86, 48,
+ 263, 69, 84, 256, 75, 101, 103, 99, 85, 209,
+ 112, 254, 59, 112, 170, 242, 240, 82, 238, 222,
+ 220, 211, 55, 54, 210, 64, 171, 111, 241, 235,
+ 113, 112, 93, 95, 97, 120, 121, 122, 212, 107,
+ 109, 55, 133, 128, 174, 145, 52, 138, 119, 71,
+ 115, 129, 208, 232, 112, 136, 139, 169, 55, 54,
+ 86, 53, 231, 230, 84, 52, 73, 142, 143, 56,
+ 85, 146, 224, 60, 144, 131, 130, 223, 57, 82,
+ 53, 154, 52, 153, 37, 132, 152, 66, 56, 151,
+ 150, 149, 37, 148, 147, 72, 155, 53, 141, 137,
+ 135, 68, 73, 134, 62, 56, 176, 177, 127, 34,
+ 114, 32, 31, 112, 120, 28, 229, 29, 71, 30,
+ 228, 185, 187, 57, 183, 252, 253, 40, 42, 45,
+ 41, 43, 46, 195, 194, 44, 248, 112, 112, 112,
+ 112, 112, 166, 168, 112, 112, 112, 247, 182, 167,
+ 237, 213, 173, 257, 198, 199, 200, 201, 202, 219,
+ 120, 205, 206, 207, 184, 114, 196, 197, 165, 164,
+ 163, 161, 162, 156, 157, 158, 159, 160, 184, 264,
+ 227, 166, 168, 258, 112, 112, 140, 218, 167, 216,
+ 236, 55, 54, 55, 54, 239, 246, 261, 217, 260,
+ 35, 233, 234, 226, 255, 243, 214, 244, 181, 33,
+ 124, 249, 125, 126, 251, 52, 250, 52, 172, 90,
+ 116, 189, 190, 191, 192, 193, 259, 117, 89, 245,
+ 53, 7, 53, 125, 126, 73, 262, 73, 56, 62,
+ 56, 265, 266, 9, 10, 11, 12, 13, 17, 15,
+ 18, 14, 16, 25, 26, 19, 20, 21, 22, 23,
+ 24, 27, 55, 54, 83, 156, 157, 158, 159, 160,
+ 39, 158, 159, 160, 204, 4, 175, 8, 203, 5,
+ 6, 110, 2, 55, 54, 1, 52, 77, 108, 106,
+ 40, 42, 45, 41, 43, 46, 105, 104, 44, 87,
+ 102, 53, 55, 54, 100, 79, 50, 52, 98, 56,
+ 96, 40, 42, 45, 41, 43, 46, 94, 92, 44,
+ 57, 88, 53, 55, 54, 83, 52, 50, 78, 62,
+ 56, 76, 74, 65, 63, 58, 221, 67, 215, 225,
+ 0, 53, 0, 0, 55, 54, 73, 52, 0, 56,
+ 0, 40, 42, 45, 41, 43, 46, 0, 0, 44,
+ 87, 0, 53, 0, 0, 55, 54, 50, 52, 0,
+ 56, 0, 40, 42, 45, 41, 43, 46, 0, 0,
+ 44, 57, 0, 53, 0, 0, 0, 91, 50, 52,
+ 0, 56, 0, 40, 42, 45, 41, 43, 46, 55,
+ 54, 44, 57, 0, 53, 0, 0, 0, 36, 50,
+ 0, 0, 56, 0, 0, 0, 55, 54, 0, 0,
+ 55, 54, 0, 52, 0, 0, 0, 40, 42, 45,
+ 41, 43, 46, 55, 54, 44, 57, 0, 53, 0,
+ 52, 0, 0, 50, 52, 0, 56, 0, 40, 42,
+ 45, 41, 43, 46, 0, 53, 44, 52, 0, 53,
+ 73, 0, 188, 56, 50, 55, 54, 56, 0, 0,
+ 72, 0, 53, 0, 55, 179, 0, 73, 55, 54,
+ 56, 163, 161, 162, 156, 157, 158, 159, 160, 52,
+ 161, 162, 156, 157, 158, 159, 160, 0, 52, 180,
+ 0, 0, 52, 0, 53, 0, 0, 0, 178, 73,
+ 0, 0, 56, 53, 0, 57, 0, 53, 73, 0,
+ 0, 56, 50, 0, 0, 56, 165, 164, 163, 161,
+ 162, 156, 157, 158, 159, 160, 164, 163, 161, 162,
+ 156, 157, 158, 159, 160,
+}
+var yyPact = []int{
+
+ -1000, -1000, 249, -1000, 86, -1000, 89, 82, 80, 77,
+ 376, 294, 294, 410, 69, 97, 489, 273, 355, 294,
+ 294, 294, 110, -46, -46, 489, 294, 294, -1000, 33,
+ -1000, -1000, 33, -1000, -1000, -1000, 410, -1000, -1000, -1000,
+ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 17,
+ 202, 15, -1000, -1000, 33, 33, 33, 223, -1000, 76,
+ -1000, -1000, 52, -1000, 71, -1000, 68, -1000, 444, -1000,
+ 67, 14, 244, 33, -1000, 194, -1000, 66, -1000, 334,
+ -1000, -1000, -1000, 431, -1000, -1000, 12, 223, -1000, -1000,
+ -1000, 410, -1000, 62, -1000, 61, -1000, 59, -1000, 58,
+ -1000, 57, -1000, -1000, -1000, 54, -1000, 51, -1000, 49,
+ 249, 542, -1000, 542, -1000, 124, 23, -8, 184, 134,
+ -1000, -1000, -1000, 11, 288, 33, 33, -1000, -1000, -1000,
+ -1000, -1000, 485, 476, 410, 294, -1000, 444, 149, -1000,
+ 33, 427, -1000, -1000, -1000, 163, 11, 410, 410, 410,
+ 410, 410, 204, 294, 294, -1000, 33, 33, 33, 33,
+ 33, 291, 286, 33, 33, 33, 18, -10, -13, 5,
+ 33, -1000, -1000, 215, 173, 244, -1000, -1000, -14, 313,
+ -1000, -1000, -1000, -1000, -15, 45, -1000, 40, 190, 91,
+ 87, -1000, 31, 30, -1000, 21, -1000, -1000, 280, 280,
+ -1000, -1000, -1000, 33, 33, 503, 495, 551, -4, 33,
+ -1000, -1000, 132, -16, 33, -18, -1000, -1000, -1000, -5,
+ -1000, -19, -1000, -46, -44, -1000, 239, 183, 129, 117,
+ 33, 110, -46, 276, 276, 107, -23, 213, -1000, -31,
+ -1000, 137, -1000, -1000, -1000, 170, 236, -1000, -1000, -1000,
+ -1000, -1000, 208, 206, -1000, 33, -1000, -34, -1000, 166,
+ 33, 33, -40, -1000, -1000, -41, -42, -1000, -1000, -1000,
+}
+var yyPgo = []int{
+
+ 0, 0, 359, 17, 358, 3, 290, 1, 2, 4,
+ 8, 6, 93, 32, 7, 10, 19, 229, 357, 220,
+ 355, 354, 353, 352, 351, 348, 341, 338, 337, 330,
+ 328, 324, 320, 317, 309, 308, 305, 302, 5, 301,
+ 300,
+}
+var yyR1 = []int{
+
+ 0, 36, 37, 36, 39, 38, 38, 38, 38, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 17, 17, 21, 22, 20, 20, 19, 19, 18, 18,
+ 18, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+ 28, 28, 29, 29, 29, 30, 31, 32, 32, 33,
+ 33, 34, 35, 12, 12, 14, 14, 14, 14, 14,
+ 14, 13, 13, 11, 11, 9, 9, 9, 9, 9,
+ 9, 9, 8, 7, 7, 7, 7, 7, 7, 7,
+ 6, 6, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 16, 16, 10, 10, 5, 5, 5,
+ 4, 4, 4, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3,
+}
+var yyR2 = []int{
+
+ 0, 0, 0, 3, 0, 4, 1, 2, 2, 3,
+ 3, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 0, 1, 3, 3, 2, 1, 2, 1, 2, 1,
+ 3, 5, 3, 5, 2, 1, 1, 1, 3, 5,
+ 3, 5, 2, 1, 3, 5, 5, 0, 1, 3,
+ 5, 3, 3, 1, 1, 1, 1, 2, 2, 1,
+ 1, 1, 1, 4, 2, 1, 1, 1, 1, 1,
+ 1, 1, 2, 2, 2, 2, 2, 4, 5, 3,
+ 1, 1, 1, 4, 4, 4, 6, 9, 9, 3,
+ 3, 5, 8, 1, 6, 5, 7, 0, 2, 2,
+ 1, 1, 1, 1, 1, 2, 2, 2, 3, 1,
+ 2, 3, 4, 1, 3, 3, 3, 3, 3, 4,
+ 4, 3, 3, 3,
+}
+var yyChk = []int{
+
+ -1000, -36, -37, -38, 46, 50, -40, 2, 48, 14,
+ 15, 16, 17, 18, 22, 20, 23, 19, 21, 26,
+ 27, 28, 29, 30, 31, 24, 25, 32, 49, 51,
+ 50, 50, 51, -17, 52, -19, 52, -12, -9, -6,
+ 37, 40, 38, 41, 45, 39, 42, -15, -16, -1,
+ 53, -10, 33, 48, 10, 9, 56, 46, -20, -13,
+ -12, -7, 55, -21, -13, -22, -12, -18, 52, -11,
+ -7, -1, 46, 53, -23, -10, -24, -6, -25, 52,
+ -14, -11, -16, 11, -9, -15, -1, 46, -26, -17,
+ -19, 52, -27, -13, -28, -13, -29, -13, -30, -9,
+ -31, -7, -32, -7, -33, -6, -34, -13, -35, -13,
+ -39, -3, -1, -3, -12, 53, 38, 45, -3, 53,
+ -1, -1, -1, -5, 7, 9, 10, 52, -1, -10,
+ 44, 43, 53, 10, 52, 52, -11, 52, 53, -5,
+ 12, 52, -14, -9, -15, 53, -5, 52, 52, 52,
+ 52, 52, 52, 52, 52, -38, 9, 10, 11, 12,
+ 13, 7, 8, 6, 5, 4, 38, 45, 39, 54,
+ 11, 54, 54, 38, 53, 8, -1, -1, 43, 10,
+ 43, -12, -13, -11, 35, -1, -8, -1, 55, -12,
+ -12, -12, -12, -12, -7, -1, -13, -13, -3, -3,
+ -3, -3, -3, 7, 8, -3, -3, -3, 54, 11,
+ 54, 54, 53, -1, 11, -4, 36, 45, 34, -5,
+ 54, 43, 54, 52, 52, -2, 33, 10, 49, 49,
+ 52, 52, 52, -3, -3, 53, -1, 38, 54, -1,
+ 54, 53, 54, -7, -8, 10, 33, 38, 39, -1,
+ -9, -7, 38, 39, 54, 11, 54, 36, 33, 10,
+ 11, 11, -1, 54, 33, -1, -1, 54, 54, 54,
+}
+var yyDef = []int{
+
+ 1, -2, 0, 3, 0, 6, 0, 0, 0, 30,
+ 0, 0, 0, 0, 0, 0, 0, 0, 30, 0,
+ 0, 0, 0, 0, 57, 0, 0, 0, 4, 0,
+ 7, 8, 0, 11, 31, 12, 0, 37, 63, 64,
+ 75, 76, 77, 78, 79, 80, 81, 90, 91, 92,
+ 0, 103, 113, 114, 0, 0, 0, 107, 13, 35,
+ 71, 72, 0, 14, 0, 15, 0, 16, 0, 39,
+ 0, 0, 107, 0, 17, 0, 18, 0, 19, 0,
+ 45, 65, 66, 0, 69, 70, 92, 107, 20, 46,
+ 47, 31, 21, 0, 22, 0, 23, 53, 24, 0,
+ 25, 0, 26, 58, 27, 0, 28, 0, 29, 0,
+ 0, 9, 123, 10, 36, 0, 0, 0, 0, 0,
+ 115, 116, 117, 0, 0, 0, 0, 34, 83, 84,
+ 85, 86, 0, 0, 0, 0, 38, 0, 0, 74,
+ 0, 0, 44, 67, 68, 0, 74, 0, 0, 52,
+ 0, 0, 0, 0, 0, 5, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 99,
+ 0, 100, 118, 0, 0, 107, 108, 109, 0, 0,
+ 89, 32, 33, 40, 0, 0, 42, 0, 0, 48,
+ 50, 54, 0, 0, 59, 0, 61, 62, 124, 125,
+ 126, 127, 128, 0, 0, 131, 132, 133, 93, 0,
+ 94, 95, 0, 0, 0, 0, 110, 111, 112, 0,
+ 87, 0, 73, 0, 0, 82, 119, 0, 0, 0,
+ 0, 0, 0, 129, 130, 0, 0, 0, 101, 0,
+ 105, 0, 88, 41, 43, 0, 120, 49, 51, 55,
+ 56, 60, 0, 0, 96, 0, 104, 0, 121, 0,
+ 0, 0, 0, 106, 122, 0, 0, 102, 97, 98,
+}
+var yyTok1 = []int{
+
+ 1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 55, 13, 6, 3,
+ 53, 54, 11, 9, 52, 10, 3, 12, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 49, 50,
+ 7, 51, 8, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 5, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 4, 3, 56,
+}
+var yyTok2 = []int{
+
+ 2, 3, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48,
+}
+var yyTok3 = []int{
+ 0,
+}
+
+//line yaccpar:1
+
+/* parser for yacc output */
+
+var yyDebug = 0
+
+type yyLexer interface {
+ Lex(lval *yySymType) int
+ Error(s string)
+}
+
+const yyFlag = -1000
+
+func yyTokname(c int) string {
+ // 4 is TOKSTART above
+ if c >= 4 && c-4 < len(yyToknames) {
+ if yyToknames[c-4] != "" {
+ return yyToknames[c-4]
+ }
+ }
+ return __yyfmt__.Sprintf("tok-%v", c)
+}
+
+func yyStatname(s int) string {
+ if s >= 0 && s < len(yyStatenames) {
+ if yyStatenames[s] != "" {
+ return yyStatenames[s]
+ }
+ }
+ return __yyfmt__.Sprintf("state-%v", s)
+}
+
+func yylex1(lex yyLexer, lval *yySymType) int {
+ c := 0
+ char := lex.Lex(lval)
+ if char <= 0 {
+ c = yyTok1[0]
+ goto out
+ }
+ if char < len(yyTok1) {
+ c = yyTok1[char]
+ goto out
+ }
+ if char >= yyPrivate {
+ if char < yyPrivate+len(yyTok2) {
+ c = yyTok2[char-yyPrivate]
+ goto out
+ }
+ }
+ for i := 0; i < len(yyTok3); i += 2 {
+ c = yyTok3[i+0]
+ if c == char {
+ c = yyTok3[i+1]
+ goto out
+ }
+ }
+
+out:
+ if c == 0 {
+ c = yyTok2[1] /* unknown char */
+ }
+ if yyDebug >= 3 {
+ __yyfmt__.Printf("lex %s(%d)\n", yyTokname(c), uint(char))
+ }
+ return c
+}
+
+func yyParse(yylex yyLexer) int {
+ var yyn int
+ var yylval yySymType
+ var yyVAL yySymType
+ yyS := make([]yySymType, yyMaxDepth)
+
+ Nerrs := 0 /* number of errors */
+ Errflag := 0 /* error recovery flag */
+ yystate := 0
+ yychar := -1
+ yyp := -1
+ goto yystack
+
+ret0:
+ return 0
+
+ret1:
+ return 1
+
+yystack:
+ /* put a state and value onto the stack */
+ if yyDebug >= 4 {
+ __yyfmt__.Printf("char %v in %v\n", yyTokname(yychar), yyStatname(yystate))
+ }
+
+ yyp++
+ if yyp >= len(yyS) {
+ nyys := make([]yySymType, len(yyS)*2)
+ copy(nyys, yyS)
+ yyS = nyys
+ }
+ yyS[yyp] = yyVAL
+ yyS[yyp].yys = yystate
+
+yynewstate:
+ yyn = yyPact[yystate]
+ if yyn <= yyFlag {
+ goto yydefault /* simple state */
+ }
+ if yychar < 0 {
+ yychar = yylex1(yylex, &yylval)
+ }
+ yyn += yychar
+ if yyn < 0 || yyn >= yyLast {
+ goto yydefault
+ }
+ yyn = yyAct[yyn]
+ if yyChk[yyn] == yychar { /* valid shift */
+ yychar = -1
+ yyVAL = yylval
+ yystate = yyn
+ if Errflag > 0 {
+ Errflag--
+ }
+ goto yystack
+ }
+
+yydefault:
+ /* default state action */
+ yyn = yyDef[yystate]
+ if yyn == -2 {
+ if yychar < 0 {
+ yychar = yylex1(yylex, &yylval)
+ }
+
+ /* look through exception table */
+ xi := 0
+ for {
+ if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate {
+ break
+ }
+ xi += 2
+ }
+ for xi += 2; ; xi += 2 {
+ yyn = yyExca[xi+0]
+ if yyn < 0 || yyn == yychar {
+ break
+ }
+ }
+ yyn = yyExca[xi+1]
+ if yyn < 0 {
+ goto ret0
+ }
+ }
+ if yyn == 0 {
+ /* error ... attempt to resume parsing */
+ switch Errflag {
+ case 0: /* brand new error */
+ yylex.Error("syntax error")
+ Nerrs++
+ if yyDebug >= 1 {
+ __yyfmt__.Printf("%s", yyStatname(yystate))
+ __yyfmt__.Printf(" saw %s\n", yyTokname(yychar))
+ }
+ fallthrough
+
+ case 1, 2: /* incompletely recovered error ... try again */
+ Errflag = 3
+
+ /* find a state where "error" is a legal shift action */
+ for yyp >= 0 {
+ yyn = yyPact[yyS[yyp].yys] + yyErrCode
+ if yyn >= 0 && yyn < yyLast {
+ yystate = yyAct[yyn] /* simulate a shift of "error" */
+ if yyChk[yystate] == yyErrCode {
+ goto yystack
+ }
+ }
+
+ /* the current p has no shift on "error", pop stack */
+ if yyDebug >= 2 {
+ __yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys)
+ }
+ yyp--
+ }
+ /* there is no state on the stack with an error shift ... abort */
+ goto ret1
+
+ case 3: /* no shift yet; clobber input char */
+ if yyDebug >= 2 {
+ __yyfmt__.Printf("error recovery discards %s\n", yyTokname(yychar))
+ }
+ if yychar == yyEofCode {
+ goto ret1
+ }
+ yychar = -1
+ goto yynewstate /* try again in the same state */
+ }
+ }
+
+ /* reduction by production yyn */
+ if yyDebug >= 2 {
+ __yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate))
+ }
+
+ yynt := yyn
+ yypt := yyp
+ _ = yypt // guard against "declared and not used"
+
+ yyp -= yyR2[yyn]
+ // yyp is now the index of $0. Perform the default action. Iff the
+ // reduced production is ε, $1 is possibly out of range.
+ if yyp+1 >= len(yyS) {
+ nyys := make([]yySymType, len(yyS)*2)
+ copy(nyys, yyS)
+ yyS = nyys
+ }
+ yyVAL = yyS[yyp+1]
+
+ /* consult goto table to find next state */
+ yyn = yyR1[yyn]
+ yyg := yyPgo[yyn]
+ yyj := yyg + yyS[yyp].yys + 1
+
+ if yyj >= yyLast {
+ yystate = yyAct[yyg]
+ } else {
+ yystate = yyAct[yyj]
+ if yyChk[yystate] != -yyn {
+ yystate = yyAct[yyg]
+ }
+ }
+ // dummy call; replaced with literal code
+ switch yynt {
+
+ case 2:
+ //line a.y:72
+ {
+ stmtline = asm.Lineno
+ }
+ case 4:
+ //line a.y:79
+ {
+ yyS[yypt-1].sym = asm.LabelLookup(yyS[yypt-1].sym)
+ if yyS[yypt-1].sym.Type == LLAB && yyS[yypt-1].sym.Value != int64(asm.PC) {
+ yyerror("redeclaration of %s (%s)", yyS[yypt-1].sym.Labelname, yyS[yypt-1].sym.Name)
+ }
+ yyS[yypt-1].sym.Type = LLAB
+ yyS[yypt-1].sym.Value = int64(asm.PC)
+ }
+ case 9:
+ //line a.y:94
+ {
+ yyS[yypt-2].sym.Type = LVAR
+ yyS[yypt-2].sym.Value = yyS[yypt-0].lval
+ }
+ case 10:
+ //line a.y:99
+ {
+ if yyS[yypt-2].sym.Value != yyS[yypt-0].lval {
+ yyerror("redeclaration of %s", yyS[yypt-2].sym.Name)
+ }
+ yyS[yypt-2].sym.Value = yyS[yypt-0].lval
+ }
+ case 11:
+ //line a.y:105
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 12:
+ //line a.y:106
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 13:
+ //line a.y:107
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 14:
+ //line a.y:108
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 15:
+ //line a.y:109
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 16:
+ //line a.y:110
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 17:
+ //line a.y:111
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 18:
+ //line a.y:112
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 19:
+ //line a.y:113
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 20:
+ //line a.y:114
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 21:
+ //line a.y:115
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 22:
+ //line a.y:116
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 23:
+ //line a.y:117
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 24:
+ //line a.y:118
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 25:
+ //line a.y:119
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 26:
+ //line a.y:120
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 27:
+ //line a.y:121
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 28:
+ //line a.y:122
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 29:
+ //line a.y:123
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 30:
+ //line a.y:126
+ {
+ yyVAL.addr2.from = nullgen
+ yyVAL.addr2.to = nullgen
+ }
+ case 31:
+ //line a.y:131
+ {
+ yyVAL.addr2.from = nullgen
+ yyVAL.addr2.to = nullgen
+ }
+ case 32:
+ //line a.y:138
+ {
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 33:
+ //line a.y:145
+ {
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 34:
+ //line a.y:152
+ {
+ yyVAL.addr2.from = yyS[yypt-1].addr
+ yyVAL.addr2.to = nullgen
+ }
+ case 35:
+ //line a.y:157
+ {
+ yyVAL.addr2.from = yyS[yypt-0].addr
+ yyVAL.addr2.to = nullgen
+ }
+ case 36:
+ //line a.y:164
+ {
+ yyVAL.addr2.from = nullgen
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 37:
+ //line a.y:169
+ {
+ yyVAL.addr2.from = nullgen
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 38:
+ //line a.y:176
+ {
+ yyVAL.addr2.from = nullgen
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 39:
+ //line a.y:181
+ {
+ yyVAL.addr2.from = nullgen
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 40:
+ //line a.y:186
+ {
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 41:
+ //line a.y:193
+ {
+ yyVAL.addr2.from = yyS[yypt-4].addr
+ yyVAL.addr2.from.Scale = int8(yyS[yypt-2].lval)
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 42:
+ //line a.y:201
+ {
+ asm.Settext(yyS[yypt-2].addr.Sym)
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 43:
+ //line a.y:207
+ {
+ asm.Settext(yyS[yypt-4].addr.Sym)
+ yyVAL.addr2.from = yyS[yypt-4].addr
+ yyVAL.addr2.from.Scale = int8(yyS[yypt-2].lval)
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 44:
+ //line a.y:216
+ {
+ yyVAL.addr2.from = nullgen
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 45:
+ //line a.y:221
+ {
+ yyVAL.addr2.from = nullgen
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 46:
+ yyVAL.addr2 = yyS[yypt-0].addr2
+ case 47:
+ yyVAL.addr2 = yyS[yypt-0].addr2
+ case 48:
+ //line a.y:232
+ {
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 49:
+ //line a.y:237
+ {
+ yyVAL.addr2.from = yyS[yypt-4].addr
+ yyVAL.addr2.to = yyS[yypt-2].addr
+ if yyVAL.addr2.from.Index != x86.D_NONE {
+ yyerror("dp shift with lhs index")
+ }
+ yyVAL.addr2.from.Index = uint8(yyS[yypt-0].lval)
+ }
+ case 50:
+ //line a.y:248
+ {
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 51:
+ //line a.y:253
+ {
+ yyVAL.addr2.from = yyS[yypt-4].addr
+ yyVAL.addr2.to = yyS[yypt-2].addr
+ if yyVAL.addr2.to.Index != x86.D_NONE {
+ yyerror("dp move with lhs index")
+ }
+ yyVAL.addr2.to.Index = uint8(yyS[yypt-0].lval)
+ }
+ case 52:
+ //line a.y:264
+ {
+ yyVAL.addr2.from = yyS[yypt-1].addr
+ yyVAL.addr2.to = nullgen
+ }
+ case 53:
+ //line a.y:269
+ {
+ yyVAL.addr2.from = yyS[yypt-0].addr
+ yyVAL.addr2.to = nullgen
+ }
+ case 54:
+ //line a.y:274
+ {
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 55:
+ //line a.y:281
+ {
+ yyVAL.addr2.from = yyS[yypt-4].addr
+ yyVAL.addr2.to = yyS[yypt-2].addr
+ yyVAL.addr2.to.Offset = yyS[yypt-0].lval
+ }
+ case 56:
+ //line a.y:289
+ {
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ if yyS[yypt-4].addr.Type != x86.D_CONST {
+ yyerror("illegal constant")
+ }
+ yyVAL.addr2.to.Offset = yyS[yypt-4].addr.Offset
+ }
+ case 57:
+ //line a.y:299
+ {
+ yyVAL.addr2.from = nullgen
+ yyVAL.addr2.to = nullgen
+ }
+ case 58:
+ //line a.y:304
+ {
+ yyVAL.addr2.from = yyS[yypt-0].addr
+ yyVAL.addr2.to = nullgen
+ }
+ case 59:
+ //line a.y:311
+ {
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 60:
+ //line a.y:316
+ {
+ yyVAL.addr2.from = yyS[yypt-4].addr
+ yyVAL.addr2.from.Scale = int8(yyS[yypt-2].lval)
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 61:
+ //line a.y:324
+ {
+ if yyS[yypt-2].addr.Type != x86.D_CONST || yyS[yypt-0].addr.Type != x86.D_CONST {
+ yyerror("arguments to asm.PCDATA must be integer constants")
+ }
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 62:
+ //line a.y:334
+ {
+ if yyS[yypt-2].addr.Type != x86.D_CONST {
+ yyerror("index for FUNCDATA must be integer constant")
+ }
+ if yyS[yypt-0].addr.Type != x86.D_EXTERN && yyS[yypt-0].addr.Type != x86.D_STATIC {
+ yyerror("value for FUNCDATA must be symbol reference")
+ }
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 63:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 64:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 65:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 66:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 67:
+ //line a.y:353
+ {
+ yyVAL.addr = yyS[yypt-0].addr
+ }
+ case 68:
+ //line a.y:357
+ {
+ yyVAL.addr = yyS[yypt-0].addr
+ }
+ case 69:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 70:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 71:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 72:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 73:
+ //line a.y:369
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = x86.D_BRANCH
+ yyVAL.addr.Offset = yyS[yypt-3].lval + int64(asm.PC)
+ }
+ case 74:
+ //line a.y:375
+ {
+ yyS[yypt-1].sym = asm.LabelLookup(yyS[yypt-1].sym)
+ yyVAL.addr = nullgen
+ if asm.Pass == 2 && yyS[yypt-1].sym.Type != LLAB {
+ yyerror("undefined label: %s", yyS[yypt-1].sym.Labelname)
+ }
+ yyVAL.addr.Type = x86.D_BRANCH
+ yyVAL.addr.Offset = yyS[yypt-1].sym.Value + yyS[yypt-0].lval
+ }
+ case 75:
+ //line a.y:387
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+ }
+ case 76:
+ //line a.y:392
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+ }
+ case 77:
+ //line a.y:397
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+ }
+ case 78:
+ //line a.y:402
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+ }
+ case 79:
+ //line a.y:407
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = x86.D_SP
+ }
+ case 80:
+ //line a.y:412
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+ }
+ case 81:
+ //line a.y:417
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+ }
+ case 82:
+ //line a.y:423
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = x86.D_CONST
+ yyVAL.addr.Offset = yyS[yypt-0].lval
+ }
+ case 83:
+ //line a.y:431
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = x86.D_CONST
+ yyVAL.addr.Offset = yyS[yypt-0].lval
+ }
+ case 84:
+ //line a.y:437
+ {
+ yyVAL.addr = yyS[yypt-0].addr
+ yyVAL.addr.Index = uint8(yyS[yypt-0].addr.Type)
+ yyVAL.addr.Type = x86.D_ADDR
+ /*
+ if($2.Type == x86.D_AUTO || $2.Type == x86.D_PARAM)
+ yyerror("constant cannot be automatic: %s",
+ $2.sym.Name);
+ */
+ }
+ case 85:
+ //line a.y:447
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = x86.D_SCONST
+ yyVAL.addr.U.Sval = (yyS[yypt-0].sval + "\x00\x00\x00\x00\x00\x00\x00\x00")[:8]
+ }
+ case 86:
+ //line a.y:453
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = x86.D_FCONST
+ yyVAL.addr.U.Dval = yyS[yypt-0].dval
+ }
+ case 87:
+ //line a.y:459
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = x86.D_FCONST
+ yyVAL.addr.U.Dval = yyS[yypt-1].dval
+ }
+ case 88:
+ //line a.y:465
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = x86.D_FCONST
+ yyVAL.addr.U.Dval = -yyS[yypt-1].dval
+ }
+ case 89:
+ //line a.y:471
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = x86.D_FCONST
+ yyVAL.addr.U.Dval = -yyS[yypt-0].dval
+ }
+ case 90:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 91:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 92:
+ //line a.y:483
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = x86.D_INDIR + x86.D_NONE
+ yyVAL.addr.Offset = yyS[yypt-0].lval
+ }
+ case 93:
+ //line a.y:489
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(x86.D_INDIR + yyS[yypt-1].lval)
+ yyVAL.addr.Offset = yyS[yypt-3].lval
+ }
+ case 94:
+ //line a.y:495
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(x86.D_INDIR + x86.D_SP)
+ yyVAL.addr.Offset = yyS[yypt-3].lval
+ }
+ case 95:
+ //line a.y:501
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(x86.D_INDIR + yyS[yypt-1].lval)
+ yyVAL.addr.Offset = yyS[yypt-3].lval
+ }
+ case 96:
+ //line a.y:507
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(x86.D_INDIR + x86.D_NONE)
+ yyVAL.addr.Offset = yyS[yypt-5].lval
+ yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+ yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+ checkscale(yyVAL.addr.Scale)
+ }
+ case 97:
+ //line a.y:516
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(x86.D_INDIR + yyS[yypt-6].lval)
+ yyVAL.addr.Offset = yyS[yypt-8].lval
+ yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+ yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+ checkscale(yyVAL.addr.Scale)
+ }
+ case 98:
+ //line a.y:525
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(x86.D_INDIR + yyS[yypt-6].lval)
+ yyVAL.addr.Offset = yyS[yypt-8].lval
+ yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+ yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+ checkscale(yyVAL.addr.Scale)
+ }
+ case 99:
+ //line a.y:534
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(x86.D_INDIR + yyS[yypt-1].lval)
+ }
+ case 100:
+ //line a.y:539
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(x86.D_INDIR + x86.D_SP)
+ }
+ case 101:
+ //line a.y:544
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(x86.D_INDIR + x86.D_NONE)
+ yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+ yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+ checkscale(yyVAL.addr.Scale)
+ }
+ case 102:
+ //line a.y:552
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(x86.D_INDIR + yyS[yypt-6].lval)
+ yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+ yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+ checkscale(yyVAL.addr.Scale)
+ }
+ case 103:
+ //line a.y:562
+ {
+ yyVAL.addr = yyS[yypt-0].addr
+ }
+ case 104:
+ //line a.y:566
+ {
+ yyVAL.addr = yyS[yypt-5].addr
+ yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+ yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+ checkscale(yyVAL.addr.Scale)
+ }
+ case 105:
+ //line a.y:575
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(yyS[yypt-1].lval)
+ yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyS[yypt-4].sym.Name, 0)
+ yyVAL.addr.Offset = yyS[yypt-3].lval
+ }
+ case 106:
+ //line a.y:582
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = x86.D_STATIC
+ yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyS[yypt-6].sym.Name, 1)
+ yyVAL.addr.Offset = yyS[yypt-3].lval
+ }
+ case 107:
+ //line a.y:590
+ {
+ yyVAL.lval = 0
+ }
+ case 108:
+ //line a.y:594
+ {
+ yyVAL.lval = yyS[yypt-0].lval
+ }
+ case 109:
+ //line a.y:598
+ {
+ yyVAL.lval = -yyS[yypt-0].lval
+ }
+ case 110:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 111:
+ //line a.y:605
+ {
+ yyVAL.lval = x86.D_AUTO
+ }
+ case 112:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 113:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 114:
+ //line a.y:613
+ {
+ yyVAL.lval = yyS[yypt-0].sym.Value
+ }
+ case 115:
+ //line a.y:617
+ {
+ yyVAL.lval = -yyS[yypt-0].lval
+ }
+ case 116:
+ //line a.y:621
+ {
+ yyVAL.lval = yyS[yypt-0].lval
+ }
+ case 117:
+ //line a.y:625
+ {
+ yyVAL.lval = ^yyS[yypt-0].lval
+ }
+ case 118:
+ //line a.y:629
+ {
+ yyVAL.lval = yyS[yypt-1].lval
+ }
+ case 119:
+ //line a.y:635
+ {
+ yyVAL.lval = int64(uint64(yyS[yypt-0].lval&0xffffffff) + (obj.ArgsSizeUnknown << 32))
+ }
+ case 120:
+ //line a.y:639
+ {
+ yyVAL.lval = int64(uint64(-yyS[yypt-0].lval&0xffffffff) + (obj.ArgsSizeUnknown << 32))
+ }
+ case 121:
+ //line a.y:643
+ {
+ yyVAL.lval = (yyS[yypt-2].lval & 0xffffffff) + ((yyS[yypt-0].lval & 0xffff) << 32)
+ }
+ case 122:
+ //line a.y:647
+ {
+ yyVAL.lval = (-yyS[yypt-2].lval & 0xffffffff) + ((yyS[yypt-0].lval & 0xffff) << 32)
+ }
+ case 123:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 124:
+ //line a.y:654
+ {
+ yyVAL.lval = yyS[yypt-2].lval + yyS[yypt-0].lval
+ }
+ case 125:
+ //line a.y:658
+ {
+ yyVAL.lval = yyS[yypt-2].lval - yyS[yypt-0].lval
+ }
+ case 126:
+ //line a.y:662
+ {
+ yyVAL.lval = yyS[yypt-2].lval * yyS[yypt-0].lval
+ }
+ case 127:
+ //line a.y:666
+ {
+ yyVAL.lval = yyS[yypt-2].lval / yyS[yypt-0].lval
+ }
+ case 128:
+ //line a.y:670
+ {
+ yyVAL.lval = yyS[yypt-2].lval % yyS[yypt-0].lval
+ }
+ case 129:
+ //line a.y:674
+ {
+ yyVAL.lval = yyS[yypt-3].lval << uint(yyS[yypt-0].lval)
+ }
+ case 130:
+ //line a.y:678
+ {
+ yyVAL.lval = yyS[yypt-3].lval >> uint(yyS[yypt-0].lval)
+ }
+ case 131:
+ //line a.y:682
+ {
+ yyVAL.lval = yyS[yypt-2].lval & yyS[yypt-0].lval
+ }
+ case 132:
+ //line a.y:686
+ {
+ yyVAL.lval = yyS[yypt-2].lval ^ yyS[yypt-0].lval
+ }
+ case 133:
+ //line a.y:690
+ {
+ yyVAL.lval = yyS[yypt-2].lval | yyS[yypt-0].lval
+ }
+ }
+ goto yystack /* stack new state and value */
+}
--- /dev/null
+// Inferno utils/8a/a.y
+// http://code.google.com/p/inferno-os/source/browse/utils/8a/a.y
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+%{
+package main
+
+import (
+ "cmd/internal/asm"
+ "cmd/internal/obj"
+ . "cmd/internal/obj/i386"
+)
+%}
+
+%union {
+ sym *asm.Sym
+ lval int64
+ con2 struct {
+ v1 int32
+ v2 int32
+ }
+ dval float64
+ sval string
+ addr obj.Addr
+ addr2 Addr2
+}
+
+%left '|'
+%left '^'
+%left '&'
+%left '<' '>'
+%left '+' '-'
+%left '*' '/' '%'
+%token <lval> LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4
+%token <lval> LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPES LTYPEM LTYPEI LTYPEG LTYPEXC
+%token <lval> LTYPEX LTYPEPC LTYPEF LCONST LFP LPC LSB
+%token <lval> LBREG LLREG LSREG LFREG LXREG
+%token <dval> LFCONST
+%token <sval> LSCONST LSP
+%token <sym> LNAME LLAB LVAR
+%type <lval> con expr pointer offset
+%type <con2> con2
+%type <addr> mem imm imm2 reg nam rel rem rim rom omem nmem
+%type <addr2> nonnon nonrel nonrem rimnon rimrem remrim
+%type <addr2> spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9 spec10 spec11 spec12
+%%
+prog:
+| prog
+ {
+ stmtline = asm.Lineno;
+ }
+ line
+
+line:
+ LNAME ':'
+ {
+ $1 = asm.LabelLookup($1);
+ if $1.Type == LLAB && $1.Value != int64(asm.PC) {
+ yyerror("redeclaration of %s", $1.Labelname)
+ }
+ $1.Type = LLAB;
+ $1.Value = int64(asm.PC)
+ }
+ line
+| ';'
+| inst ';'
+| error ';'
+
+inst:
+ LNAME '=' expr
+ {
+ $1.Type = LVAR;
+ $1.Value = $3;
+ }
+| LVAR '=' expr
+ {
+ if $1.Value != int64($3) {
+ yyerror("redeclaration of %s", $1.Name);
+ }
+ $1.Value = $3;
+ }
+| LTYPE0 nonnon { outcode(int($1), &$2); }
+| LTYPE1 nonrem { outcode(int($1), &$2); }
+| LTYPE2 rimnon { outcode(int($1), &$2); }
+| LTYPE3 rimrem { outcode(int($1), &$2); }
+| LTYPE4 remrim { outcode(int($1), &$2); }
+| LTYPER nonrel { outcode(int($1), &$2); }
+| LTYPED spec1 { outcode(int($1), &$2); }
+| LTYPET spec2 { outcode(int($1), &$2); }
+| LTYPEC spec3 { outcode(int($1), &$2); }
+| LTYPEN spec4 { outcode(int($1), &$2); }
+| LTYPES spec5 { outcode(int($1), &$2); }
+| LTYPEM spec6 { outcode(int($1), &$2); }
+| LTYPEI spec7 { outcode(int($1), &$2); }
+| LTYPEG spec8 { outcode(int($1), &$2); }
+| LTYPEXC spec9 { outcode(int($1), &$2); }
+| LTYPEX spec10 { outcode(int($1), &$2); }
+| LTYPEPC spec11 { outcode(int($1), &$2); }
+| LTYPEF spec12 { outcode(int($1), &$2); }
+
+nonnon:
+ {
+ $$.from = nullgen;
+ $$.to = nullgen;
+ }
+| ','
+ {
+ $$.from = nullgen;
+ $$.to = nullgen;
+ }
+
+rimrem:
+ rim ',' rem
+ {
+ $$.from = $1;
+ $$.to = $3;
+ }
+
+remrim:
+ rem ',' rim
+ {
+ $$.from = $1;
+ $$.to = $3;
+ }
+
+rimnon:
+ rim ','
+ {
+ $$.from = $1;
+ $$.to = nullgen;
+ }
+| rim
+ {
+ $$.from = $1;
+ $$.to = nullgen;
+ }
+
+nonrem:
+ ',' rem
+ {
+ $$.from = nullgen;
+ $$.to = $2;
+ }
+| rem
+ {
+ $$.from = nullgen;
+ $$.to = $1;
+ }
+
+nonrel:
+ ',' rel
+ {
+ $$.from = nullgen;
+ $$.to = $2;
+ }
+| rel
+ {
+ $$.from = nullgen;
+ $$.to = $1;
+ }
+| imm ',' rel
+ {
+ $$.from = $1;
+ $$.to = $3;
+ }
+
+spec1: /* DATA */
+ nam '/' con ',' imm
+ {
+ $$.from = $1;
+ $$.from.Scale = int8($3);
+ $$.to = $5;
+ }
+
+spec2: /* TEXT */
+ mem ',' imm2
+ {
+ asm.Settext($1.Sym);
+ $$.from = $1;
+ $$.to = $3;
+ }
+| mem ',' con ',' imm2
+ {
+ asm.Settext($1.Sym);
+ $$.from = $1;
+ $$.from.Scale = int8($3);
+ $$.to = $5;
+ }
+
+spec3: /* JMP/CALL */
+ ',' rom
+ {
+ $$.from = nullgen;
+ $$.to = $2;
+ }
+| rom
+ {
+ $$.from = nullgen;
+ $$.to = $1;
+ }
+| '*' nam
+ {
+ $$.from = nullgen;
+ $$.to = $2;
+ $$.to.Index = uint8($2.Type)
+ $$.to.Type = D_INDIR+D_ADDR;
+ }
+
+spec4: /* NOP */
+ nonnon
+| nonrem
+
+spec5: /* SHL/SHR */
+ rim ',' rem
+ {
+ $$.from = $1;
+ $$.to = $3;
+ }
+| rim ',' rem ':' LLREG
+ {
+ $$.from = $1;
+ $$.to = $3;
+ if $$.from.Index != D_NONE {
+ yyerror("dp shift with lhs index");
+ }
+ $$.from.Index = uint8($5);
+ }
+
+spec6: /* MOVW/MOVL */
+ rim ',' rem
+ {
+ $$.from = $1;
+ $$.to = $3;
+ }
+| rim ',' rem ':' LSREG
+ {
+ $$.from = $1;
+ $$.to = $3;
+ if $$.to.Index != D_NONE {
+ yyerror("dp move with lhs index");
+ }
+ $$.to.Index = uint8($5);
+ }
+
+spec7:
+ rim ','
+ {
+ $$.from = $1;
+ $$.to = nullgen;
+ }
+| rim
+ {
+ $$.from = $1;
+ $$.to = nullgen;
+ }
+| rim ',' rem
+ {
+ $$.from = $1;
+ $$.to = $3;
+ }
+
+spec8: /* GLOBL */
+ mem ',' imm
+ {
+ $$.from = $1;
+ $$.to = $3;
+ }
+| mem ',' con ',' imm
+ {
+ $$.from = $1;
+ $$.from.Scale = int8($3);
+ $$.to = $5;
+ }
+
+spec9: /* CMPPS/CMPPD */
+ reg ',' rem ',' con
+ {
+ $$.from = $1;
+ $$.to = $3;
+ $$.to.Offset = $5;
+ }
+
+spec10: /* PINSRD */
+ imm ',' rem ',' reg
+ {
+ $$.from = $3;
+ $$.to = $5;
+ if $1.Type != D_CONST {
+ yyerror("illegal constant")
+ }
+ $$.to.Offset = $1.Offset;
+ }
+
+spec11: /* PCDATA */
+ rim ',' rim
+ {
+ if $1.Type != D_CONST || $3.Type != D_CONST {
+ yyerror("arguments to PCDATA must be integer constants");
+ }
+ $$.from = $1;
+ $$.to = $3;
+ }
+
+spec12: /* FUNCDATA */
+ rim ',' rim
+ {
+ if $1.Type != D_CONST {
+ yyerror("index for FUNCDATA must be integer constant");
+ }
+ if $3.Type != D_EXTERN && $3.Type != D_STATIC {
+ yyerror("value for FUNCDATA must be symbol reference");
+ }
+ $$.from = $1;
+ $$.to = $3;
+ }
+
+rem:
+ reg
+| mem
+
+rom:
+ rel
+| nmem
+| '*' reg
+ {
+ $$ = $2;
+ }
+| '*' omem
+ {
+ $$ = $2;
+ }
+| reg
+| omem
+| imm
+
+rim:
+ rem
+| imm
+
+rel:
+ con '(' LPC ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_BRANCH;
+ $$.Offset = $1 + int64(asm.PC);
+ }
+| LNAME offset
+ {
+ $1 = asm.LabelLookup($1);
+ $$ = nullgen;
+ if asm.Pass == 2 && $1.Type != LLAB {
+ yyerror("undefined label: %s", $1.Labelname);
+ }
+ $$.Type = D_BRANCH;
+ $$.Offset = $1.Value + $2;
+ }
+
+reg:
+ LBREG
+ {
+ $$ = nullgen;
+ $$.Type = int16($1);
+ }
+| LFREG
+ {
+ $$ = nullgen;
+ $$.Type = int16($1);
+ }
+| LLREG
+ {
+ $$ = nullgen;
+ $$.Type = int16($1);
+ }
+| LXREG
+ {
+ $$ = nullgen;
+ $$.Type = int16($1);
+ }
+| LSP
+ {
+ $$ = nullgen;
+ $$.Type = D_SP;
+ }
+| LSREG
+ {
+ $$ = nullgen;
+ $$.Type = int16($1);
+ }
+
+imm:
+ '$' con
+ {
+ $$ = nullgen;
+ $$.Type = D_CONST;
+ $$.Offset = $2;
+ }
+| '$' nam
+ {
+ $$ = $2;
+ $$.Index = uint8($2.Type);
+ $$.Type = D_ADDR;
+ /*
+ if($2.Type == D_AUTO || $2.Type == D_PARAM)
+ yyerror("constant cannot be automatic: %s",
+ $2.Sym.name);
+ */
+ }
+| '$' LSCONST
+ {
+ $$ = nullgen;
+ $$.Type = D_SCONST;
+ $$.U.Sval = $2
+ }
+| '$' LFCONST
+ {
+ $$ = nullgen;
+ $$.Type = D_FCONST;
+ $$.U.Dval = $2;
+ }
+| '$' '(' LFCONST ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_FCONST;
+ $$.U.Dval = $3;
+ }
+| '$' '(' '-' LFCONST ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_FCONST;
+ $$.U.Dval = -$4;
+ }
+| '$' '-' LFCONST
+ {
+ $$ = nullgen;
+ $$.Type = D_FCONST;
+ $$.U.Dval = -$3;
+ }
+
+imm2:
+ '$' con2
+ {
+ $$ = nullgen;
+ $$.Type = D_CONST2;
+ $$.Offset = int64($2.v1);
+ $$.Offset2 = int32($2.v2);
+ }
+
+con2:
+ LCONST
+ {
+ $$.v1 = int32($1);
+ $$.v2 = -obj.ArgsSizeUnknown
+ }
+| '-' LCONST
+ {
+ $$.v1 = int32(-$2);
+ $$.v2 = -obj.ArgsSizeUnknown;
+ }
+| LCONST '-' LCONST
+ {
+ $$.v1 = int32($1);
+ $$.v2 = int32($3);
+ }
+| '-' LCONST '-' LCONST
+ {
+ $$.v1 = int32(-$2);
+ $$.v2 = int32($4);
+ }
+
+mem:
+ omem
+| nmem
+
+omem:
+ con
+ {
+ $$ = nullgen;
+ $$.Type = D_INDIR+D_NONE;
+ $$.Offset = $1;
+ }
+| con '(' LLREG ')'
+ {
+ $$ = nullgen;
+ $$.Type = int16(D_INDIR+$3);
+ $$.Offset = $1;
+ }
+| con '(' LSP ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_INDIR+D_SP;
+ $$.Offset = $1;
+ }
+| con '(' LLREG '*' con ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_INDIR+D_NONE;
+ $$.Offset = $1;
+ $$.Index = uint8($3);
+ $$.Scale = int8($5);
+ checkscale($$.Scale);
+ }
+| con '(' LLREG ')' '(' LLREG '*' con ')'
+ {
+ $$ = nullgen;
+ $$.Type = int16(D_INDIR+$3);
+ $$.Offset = $1;
+ $$.Index = uint8($6);
+ $$.Scale = int8($8);
+ checkscale($$.Scale);
+ }
+| con '(' LLREG ')' '(' LSREG '*' con ')'
+ {
+ $$ = nullgen;
+ $$.Type = int16(D_INDIR+$3);
+ $$.Offset = $1;
+ $$.Index = uint8($6);
+ $$.Scale = int8($8);
+ checkscale($$.Scale);
+ }
+| '(' LLREG ')'
+ {
+ $$ = nullgen;
+ $$.Type = int16(D_INDIR+$2);
+ }
+| '(' LSP ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_INDIR+D_SP;
+ }
+| con '(' LSREG ')'
+ {
+ $$ = nullgen;
+ $$.Type = int16(D_INDIR+$3);
+ $$.Offset = $1;
+ }
+| '(' LLREG '*' con ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_INDIR+D_NONE;
+ $$.Index = uint8($2);
+ $$.Scale = int8($4);
+ checkscale($$.Scale);
+ }
+| '(' LLREG ')' '(' LLREG '*' con ')'
+ {
+ $$ = nullgen;
+ $$.Type = int16(D_INDIR+$2);
+ $$.Index = uint8($5);
+ $$.Scale = int8($7);
+ checkscale($$.Scale);
+ }
+
+nmem:
+ nam
+ {
+ $$ = $1;
+ }
+| nam '(' LLREG '*' con ')'
+ {
+ $$ = $1;
+ $$.Index = uint8($3);
+ $$.Scale = int8($5);
+ checkscale($$.Scale);
+ }
+
+nam:
+ LNAME offset '(' pointer ')'
+ {
+ $$ = nullgen;
+ $$.Type = int16($4);
+ $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
+ $$.Offset = $2;
+ }
+| LNAME '<' '>' offset '(' LSB ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_STATIC;
+ $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
+ $$.Offset = $4;
+ }
+
+offset:
+ {
+ $$ = 0;
+ }
+| '+' con
+ {
+ $$ = $2;
+ }
+| '-' con
+ {
+ $$ = -$2;
+ }
+
+pointer:
+ LSB
+| LSP
+ {
+ $$ = D_AUTO;
+ }
+| LFP
+
+con:
+ LCONST
+| LVAR
+ {
+ $$ = $1.Value;
+ }
+| '-' con
+ {
+ $$ = -$2;
+ }
+| '+' con
+ {
+ $$ = $2;
+ }
+| '~' con
+ {
+ $$ = ^$2;
+ }
+| '(' expr ')'
+ {
+ $$ = $2;
+ }
+
+expr:
+ con
+| expr '+' expr
+ {
+ $$ = $1 + $3;
+ }
+| expr '-' expr
+ {
+ $$ = $1 - $3;
+ }
+| expr '*' expr
+ {
+ $$ = $1 * $3;
+ }
+| expr '/' expr
+ {
+ $$ = $1 / $3;
+ }
+| expr '%' expr
+ {
+ $$ = $1 % $3;
+ }
+| expr '<' '<' expr
+ {
+ $$ = $1 << uint($4);
+ }
+| expr '>' '>' expr
+ {
+ $$ = $1 >> uint($4);
+ }
+| expr '&' expr
+ {
+ $$ = $1 & $3;
+ }
+| expr '^' expr
+ {
+ $$ = $1 ^ $3;
+ }
+| expr '|' expr
+ {
+ $$ = $1 | $3;
+ }
--- /dev/null
+// Inferno utils/8a/lex.c
+// http://code.google.com/p/inferno-os/source/browse/utils/8a/lex.c
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+//go:generate go tool yacc a.y
+
+package main
+
+import (
+ "cmd/internal/asm"
+ "cmd/internal/obj"
+ "cmd/internal/obj/i386"
+)
+
+var (
+ yyerror = asm.Yyerror
+ nullgen obj.Addr
+ stmtline int32
+)
+
+func main() {
+ cinit()
+
+ asm.LSCONST = LSCONST
+ asm.LCONST = LCONST
+ asm.LFCONST = LFCONST
+ asm.LNAME = LNAME
+ asm.LVAR = LVAR
+ asm.LLAB = LLAB
+
+ asm.Lexinit = lexinit
+ asm.Cclean = cclean
+ asm.Yyparse = yyparse
+
+ asm.Thechar = '8'
+ asm.Thestring = "386"
+ asm.Thelinkarch = &i386.Link386
+
+ asm.Main()
+}
+
+type yy struct{}
+
+func (yy) Lex(v *yySymType) int {
+ var av asm.Yylval
+ tok := asm.Yylex(&av)
+ v.sym = av.Sym
+ v.lval = av.Lval
+ v.sval = av.Sval
+ v.dval = av.Dval
+ return tok
+}
+
+func (yy) Error(msg string) {
+ asm.Yyerror("%s", msg)
+}
+
+func yyparse() {
+ yyParse(yy{})
+}
+
+var lexinit = []asm.Lextab{
+ {"SP", LSP, i386.D_AUTO},
+ {"SB", LSB, i386.D_EXTERN},
+ {"FP", LFP, i386.D_PARAM},
+ {"PC", LPC, i386.D_BRANCH},
+ {"AL", LBREG, i386.D_AL},
+ {"CL", LBREG, i386.D_CL},
+ {"DL", LBREG, i386.D_DL},
+ {"BL", LBREG, i386.D_BL},
+ {"AH", LBREG, i386.D_AH},
+ {"CH", LBREG, i386.D_CH},
+ {"DH", LBREG, i386.D_DH},
+ {"BH", LBREG, i386.D_BH},
+ {"AX", LLREG, i386.D_AX},
+ {"CX", LLREG, i386.D_CX},
+ {"DX", LLREG, i386.D_DX},
+ {"BX", LLREG, i386.D_BX},
+ /* "SP", LLREG, D_SP, */
+ {"BP", LLREG, i386.D_BP},
+ {"SI", LLREG, i386.D_SI},
+ {"DI", LLREG, i386.D_DI},
+ {"F0", LFREG, i386.D_F0 + 0},
+ {"F1", LFREG, i386.D_F0 + 1},
+ {"F2", LFREG, i386.D_F0 + 2},
+ {"F3", LFREG, i386.D_F0 + 3},
+ {"F4", LFREG, i386.D_F0 + 4},
+ {"F5", LFREG, i386.D_F0 + 5},
+ {"F6", LFREG, i386.D_F0 + 6},
+ {"F7", LFREG, i386.D_F0 + 7},
+ {"X0", LXREG, i386.D_X0 + 0},
+ {"X1", LXREG, i386.D_X0 + 1},
+ {"X2", LXREG, i386.D_X0 + 2},
+ {"X3", LXREG, i386.D_X0 + 3},
+ {"X4", LXREG, i386.D_X0 + 4},
+ {"X5", LXREG, i386.D_X0 + 5},
+ {"X6", LXREG, i386.D_X0 + 6},
+ {"X7", LXREG, i386.D_X0 + 7},
+ {"CS", LSREG, i386.D_CS},
+ {"SS", LSREG, i386.D_SS},
+ {"DS", LSREG, i386.D_DS},
+ {"ES", LSREG, i386.D_ES},
+ {"FS", LSREG, i386.D_FS},
+ {"GS", LSREG, i386.D_GS},
+ {"TLS", LSREG, i386.D_TLS},
+ {"GDTR", LBREG, i386.D_GDTR},
+ {"IDTR", LBREG, i386.D_IDTR},
+ {"LDTR", LBREG, i386.D_LDTR},
+ {"MSW", LBREG, i386.D_MSW},
+ {"TASK", LBREG, i386.D_TASK},
+ {"CR0", LBREG, i386.D_CR + 0},
+ {"CR1", LBREG, i386.D_CR + 1},
+ {"CR2", LBREG, i386.D_CR + 2},
+ {"CR3", LBREG, i386.D_CR + 3},
+ {"CR4", LBREG, i386.D_CR + 4},
+ {"CR5", LBREG, i386.D_CR + 5},
+ {"CR6", LBREG, i386.D_CR + 6},
+ {"CR7", LBREG, i386.D_CR + 7},
+ {"DR0", LBREG, i386.D_DR + 0},
+ {"DR1", LBREG, i386.D_DR + 1},
+ {"DR2", LBREG, i386.D_DR + 2},
+ {"DR3", LBREG, i386.D_DR + 3},
+ {"DR4", LBREG, i386.D_DR + 4},
+ {"DR5", LBREG, i386.D_DR + 5},
+ {"DR6", LBREG, i386.D_DR + 6},
+ {"DR7", LBREG, i386.D_DR + 7},
+ {"TR0", LBREG, i386.D_TR + 0},
+ {"TR1", LBREG, i386.D_TR + 1},
+ {"TR2", LBREG, i386.D_TR + 2},
+ {"TR3", LBREG, i386.D_TR + 3},
+ {"TR4", LBREG, i386.D_TR + 4},
+ {"TR5", LBREG, i386.D_TR + 5},
+ {"TR6", LBREG, i386.D_TR + 6},
+ {"TR7", LBREG, i386.D_TR + 7},
+ {"AAA", LTYPE0, i386.AAAA},
+ {"AAD", LTYPE0, i386.AAAD},
+ {"AAM", LTYPE0, i386.AAAM},
+ {"AAS", LTYPE0, i386.AAAS},
+ {"ADCB", LTYPE3, i386.AADCB},
+ {"ADCL", LTYPE3, i386.AADCL},
+ {"ADCW", LTYPE3, i386.AADCW},
+ {"ADDB", LTYPE3, i386.AADDB},
+ {"ADDL", LTYPE3, i386.AADDL},
+ {"ADDW", LTYPE3, i386.AADDW},
+ {"ADJSP", LTYPE2, i386.AADJSP},
+ {"ANDB", LTYPE3, i386.AANDB},
+ {"ANDL", LTYPE3, i386.AANDL},
+ {"ANDW", LTYPE3, i386.AANDW},
+ {"ARPL", LTYPE3, i386.AARPL},
+ {"BOUNDL", LTYPE3, i386.ABOUNDL},
+ {"BOUNDW", LTYPE3, i386.ABOUNDW},
+ {"BSFL", LTYPE3, i386.ABSFL},
+ {"BSFW", LTYPE3, i386.ABSFW},
+ {"BSRL", LTYPE3, i386.ABSRL},
+ {"BSRW", LTYPE3, i386.ABSRW},
+ {"BSWAPL", LTYPE1, i386.ABSWAPL},
+ {"BTCL", LTYPE3, i386.ABTCL},
+ {"BTCW", LTYPE3, i386.ABTCW},
+ {"BTL", LTYPE3, i386.ABTL},
+ {"BTRL", LTYPE3, i386.ABTRL},
+ {"BTRW", LTYPE3, i386.ABTRW},
+ {"BTSL", LTYPE3, i386.ABTSL},
+ {"BTSW", LTYPE3, i386.ABTSW},
+ {"BTW", LTYPE3, i386.ABTW},
+ {"BYTE", LTYPE2, i386.ABYTE},
+ {"CALL", LTYPEC, i386.ACALL},
+ {"CLC", LTYPE0, i386.ACLC},
+ {"CLD", LTYPE0, i386.ACLD},
+ {"CLI", LTYPE0, i386.ACLI},
+ {"CLTS", LTYPE0, i386.ACLTS},
+ {"CMC", LTYPE0, i386.ACMC},
+ {"CMPB", LTYPE4, i386.ACMPB},
+ {"CMPL", LTYPE4, i386.ACMPL},
+ {"CMPW", LTYPE4, i386.ACMPW},
+ {"CMPSB", LTYPE0, i386.ACMPSB},
+ {"CMPSL", LTYPE0, i386.ACMPSL},
+ {"CMPSW", LTYPE0, i386.ACMPSW},
+ {"CMPXCHG8B", LTYPE1, i386.ACMPXCHG8B},
+ {"CMPXCHGB", LTYPE3, i386.ACMPXCHGB},
+ {"CMPXCHGL", LTYPE3, i386.ACMPXCHGL},
+ {"CMPXCHGW", LTYPE3, i386.ACMPXCHGW},
+ {"CPUID", LTYPE0, i386.ACPUID},
+ {"DAA", LTYPE0, i386.ADAA},
+ {"DAS", LTYPE0, i386.ADAS},
+ {"DATA", LTYPED, i386.ADATA},
+ {"DECB", LTYPE1, i386.ADECB},
+ {"DECL", LTYPE1, i386.ADECL},
+ {"DECW", LTYPE1, i386.ADECW},
+ {"DIVB", LTYPE2, i386.ADIVB},
+ {"DIVL", LTYPE2, i386.ADIVL},
+ {"DIVW", LTYPE2, i386.ADIVW},
+ {"END", LTYPE0, i386.AEND},
+ {"ENTER", LTYPE2, i386.AENTER},
+ {"GLOBL", LTYPEG, i386.AGLOBL},
+ {"HLT", LTYPE0, i386.AHLT},
+ {"IDIVB", LTYPE2, i386.AIDIVB},
+ {"IDIVL", LTYPE2, i386.AIDIVL},
+ {"IDIVW", LTYPE2, i386.AIDIVW},
+ {"IMULB", LTYPE2, i386.AIMULB},
+ {"IMULL", LTYPEI, i386.AIMULL},
+ {"IMULW", LTYPEI, i386.AIMULW},
+ {"INB", LTYPE0, i386.AINB},
+ {"INL", LTYPE0, i386.AINL},
+ {"INW", LTYPE0, i386.AINW},
+ {"INCB", LTYPE1, i386.AINCB},
+ {"INCL", LTYPE1, i386.AINCL},
+ {"INCW", LTYPE1, i386.AINCW},
+ {"INSB", LTYPE0, i386.AINSB},
+ {"INSL", LTYPE0, i386.AINSL},
+ {"INSW", LTYPE0, i386.AINSW},
+ {"INT", LTYPE2, i386.AINT},
+ {"INTO", LTYPE0, i386.AINTO},
+ {"IRETL", LTYPE0, i386.AIRETL},
+ {"IRETW", LTYPE0, i386.AIRETW},
+ {"JOS", LTYPER, i386.AJOS}, /* overflow set (OF = 1) */
+ {"JO", LTYPER, i386.AJOS}, /* alternate */
+ {"JOC", LTYPER, i386.AJOC}, /* overflow clear (OF = 0) */
+ {"JNO", LTYPER, i386.AJOC}, /* alternate */
+ {"JCS", LTYPER, i386.AJCS}, /* carry set (CF = 1) */
+ {"JB", LTYPER, i386.AJCS}, /* alternate */
+ {"JC", LTYPER, i386.AJCS}, /* alternate */
+ {"JNAE", LTYPER, i386.AJCS}, /* alternate */
+ {"JLO", LTYPER, i386.AJCS}, /* alternate */
+ {"JCC", LTYPER, i386.AJCC}, /* carry clear (CF = 0) */
+ {"JAE", LTYPER, i386.AJCC}, /* alternate */
+ {"JNB", LTYPER, i386.AJCC}, /* alternate */
+ {"JNC", LTYPER, i386.AJCC}, /* alternate */
+ {"JHS", LTYPER, i386.AJCC}, /* alternate */
+ {"JEQ", LTYPER, i386.AJEQ}, /* equal (ZF = 1) */
+ {"JE", LTYPER, i386.AJEQ}, /* alternate */
+ {"JZ", LTYPER, i386.AJEQ}, /* alternate */
+ {"JNE", LTYPER, i386.AJNE}, /* not equal (ZF = 0) */
+ {"JNZ", LTYPER, i386.AJNE}, /* alternate */
+ {"JLS", LTYPER, i386.AJLS}, /* lower or same (unsigned) (CF = 1 || ZF = 1) */
+ {"JBE", LTYPER, i386.AJLS}, /* alternate */
+ {"JNA", LTYPER, i386.AJLS}, /* alternate */
+ {"JHI", LTYPER, i386.AJHI}, /* higher (unsigned) (CF = 0 && ZF = 0) */
+ {"JA", LTYPER, i386.AJHI}, /* alternate */
+ {"JNBE", LTYPER, i386.AJHI}, /* alternate */
+ {"JMI", LTYPER, i386.AJMI}, /* negative (minus) (SF = 1) */
+ {"JS", LTYPER, i386.AJMI}, /* alternate */
+ {"JPL", LTYPER, i386.AJPL}, /* non-negative (plus) (SF = 0) */
+ {"JNS", LTYPER, i386.AJPL}, /* alternate */
+ {"JPS", LTYPER, i386.AJPS}, /* parity set (PF = 1) */
+ {"JP", LTYPER, i386.AJPS}, /* alternate */
+ {"JPE", LTYPER, i386.AJPS}, /* alternate */
+ {"JPC", LTYPER, i386.AJPC}, /* parity clear (PF = 0) */
+ {"JNP", LTYPER, i386.AJPC}, /* alternate */
+ {"JPO", LTYPER, i386.AJPC}, /* alternate */
+ {"JLT", LTYPER, i386.AJLT}, /* less than (signed) (SF != OF) */
+ {"JL", LTYPER, i386.AJLT}, /* alternate */
+ {"JNGE", LTYPER, i386.AJLT}, /* alternate */
+ {"JGE", LTYPER, i386.AJGE}, /* greater than or equal (signed) (SF = OF) */
+ {"JNL", LTYPER, i386.AJGE}, /* alternate */
+ {"JLE", LTYPER, i386.AJLE}, /* less than or equal (signed) (ZF = 1 || SF != OF) */
+ {"JNG", LTYPER, i386.AJLE}, /* alternate */
+ {"JGT", LTYPER, i386.AJGT}, /* greater than (signed) (ZF = 0 && SF = OF) */
+ {"JG", LTYPER, i386.AJGT}, /* alternate */
+ {"JNLE", LTYPER, i386.AJGT}, /* alternate */
+ {"JCXZL", LTYPER, i386.AJCXZL},
+ {"JCXZW", LTYPER, i386.AJCXZW},
+ {"JMP", LTYPEC, i386.AJMP},
+ {"LAHF", LTYPE0, i386.ALAHF},
+ {"LARL", LTYPE3, i386.ALARL},
+ {"LARW", LTYPE3, i386.ALARW},
+ {"LEAL", LTYPE3, i386.ALEAL},
+ {"LEAW", LTYPE3, i386.ALEAW},
+ {"LEAVEL", LTYPE0, i386.ALEAVEL},
+ {"LEAVEW", LTYPE0, i386.ALEAVEW},
+ {"LOCK", LTYPE0, i386.ALOCK},
+ {"LODSB", LTYPE0, i386.ALODSB},
+ {"LODSL", LTYPE0, i386.ALODSL},
+ {"LODSW", LTYPE0, i386.ALODSW},
+ {"LONG", LTYPE2, i386.ALONG},
+ {"LOOP", LTYPER, i386.ALOOP},
+ {"LOOPEQ", LTYPER, i386.ALOOPEQ},
+ {"LOOPNE", LTYPER, i386.ALOOPNE},
+ {"LSLL", LTYPE3, i386.ALSLL},
+ {"LSLW", LTYPE3, i386.ALSLW},
+ {"MOVB", LTYPE3, i386.AMOVB},
+ {"MOVL", LTYPEM, i386.AMOVL},
+ {"MOVW", LTYPEM, i386.AMOVW},
+ {"MOVQ", LTYPEM, i386.AMOVQ},
+ {"MOVBLSX", LTYPE3, i386.AMOVBLSX},
+ {"MOVBLZX", LTYPE3, i386.AMOVBLZX},
+ {"MOVBWSX", LTYPE3, i386.AMOVBWSX},
+ {"MOVBWZX", LTYPE3, i386.AMOVBWZX},
+ {"MOVWLSX", LTYPE3, i386.AMOVWLSX},
+ {"MOVWLZX", LTYPE3, i386.AMOVWLZX},
+ {"MOVSB", LTYPE0, i386.AMOVSB},
+ {"MOVSL", LTYPE0, i386.AMOVSL},
+ {"MOVSW", LTYPE0, i386.AMOVSW},
+ {"MULB", LTYPE2, i386.AMULB},
+ {"MULL", LTYPE2, i386.AMULL},
+ {"MULW", LTYPE2, i386.AMULW},
+ {"NEGB", LTYPE1, i386.ANEGB},
+ {"NEGL", LTYPE1, i386.ANEGL},
+ {"NEGW", LTYPE1, i386.ANEGW},
+ {"NOP", LTYPEN, i386.ANOP},
+ {"NOTB", LTYPE1, i386.ANOTB},
+ {"NOTL", LTYPE1, i386.ANOTL},
+ {"NOTW", LTYPE1, i386.ANOTW},
+ {"ORB", LTYPE3, i386.AORB},
+ {"ORL", LTYPE3, i386.AORL},
+ {"ORW", LTYPE3, i386.AORW},
+ {"OUTB", LTYPE0, i386.AOUTB},
+ {"OUTL", LTYPE0, i386.AOUTL},
+ {"OUTW", LTYPE0, i386.AOUTW},
+ {"OUTSB", LTYPE0, i386.AOUTSB},
+ {"OUTSL", LTYPE0, i386.AOUTSL},
+ {"OUTSW", LTYPE0, i386.AOUTSW},
+ {"PAUSE", LTYPEN, i386.APAUSE},
+ {"PINSRD", LTYPEX, i386.APINSRD},
+ {"POPAL", LTYPE0, i386.APOPAL},
+ {"POPAW", LTYPE0, i386.APOPAW},
+ {"POPFL", LTYPE0, i386.APOPFL},
+ {"POPFW", LTYPE0, i386.APOPFW},
+ {"POPL", LTYPE1, i386.APOPL},
+ {"POPW", LTYPE1, i386.APOPW},
+ {"PUSHAL", LTYPE0, i386.APUSHAL},
+ {"PUSHAW", LTYPE0, i386.APUSHAW},
+ {"PUSHFL", LTYPE0, i386.APUSHFL},
+ {"PUSHFW", LTYPE0, i386.APUSHFW},
+ {"PUSHL", LTYPE2, i386.APUSHL},
+ {"PUSHW", LTYPE2, i386.APUSHW},
+ {"RCLB", LTYPE3, i386.ARCLB},
+ {"RCLL", LTYPE3, i386.ARCLL},
+ {"RCLW", LTYPE3, i386.ARCLW},
+ {"RCRB", LTYPE3, i386.ARCRB},
+ {"RCRL", LTYPE3, i386.ARCRL},
+ {"RCRW", LTYPE3, i386.ARCRW},
+ {"RDTSC", LTYPE0, i386.ARDTSC},
+ {"REP", LTYPE0, i386.AREP},
+ {"REPN", LTYPE0, i386.AREPN},
+ {"RET", LTYPE0, i386.ARET},
+ {"ROLB", LTYPE3, i386.AROLB},
+ {"ROLL", LTYPE3, i386.AROLL},
+ {"ROLW", LTYPE3, i386.AROLW},
+ {"RORB", LTYPE3, i386.ARORB},
+ {"RORL", LTYPE3, i386.ARORL},
+ {"RORW", LTYPE3, i386.ARORW},
+ {"SAHF", LTYPE0, i386.ASAHF},
+ {"SALB", LTYPE3, i386.ASALB},
+ {"SALL", LTYPE3, i386.ASALL},
+ {"SALW", LTYPE3, i386.ASALW},
+ {"SARB", LTYPE3, i386.ASARB},
+ {"SARL", LTYPE3, i386.ASARL},
+ {"SARW", LTYPE3, i386.ASARW},
+ {"SBBB", LTYPE3, i386.ASBBB},
+ {"SBBL", LTYPE3, i386.ASBBL},
+ {"SBBW", LTYPE3, i386.ASBBW},
+ {"SCASB", LTYPE0, i386.ASCASB},
+ {"SCASL", LTYPE0, i386.ASCASL},
+ {"SCASW", LTYPE0, i386.ASCASW},
+ {"SETCC", LTYPE1, i386.ASETCC}, /* see JCC etc above for condition codes */
+ {"SETCS", LTYPE1, i386.ASETCS},
+ {"SETEQ", LTYPE1, i386.ASETEQ},
+ {"SETGE", LTYPE1, i386.ASETGE},
+ {"SETGT", LTYPE1, i386.ASETGT},
+ {"SETHI", LTYPE1, i386.ASETHI},
+ {"SETLE", LTYPE1, i386.ASETLE},
+ {"SETLS", LTYPE1, i386.ASETLS},
+ {"SETLT", LTYPE1, i386.ASETLT},
+ {"SETMI", LTYPE1, i386.ASETMI},
+ {"SETNE", LTYPE1, i386.ASETNE},
+ {"SETOC", LTYPE1, i386.ASETOC},
+ {"SETOS", LTYPE1, i386.ASETOS},
+ {"SETPC", LTYPE1, i386.ASETPC},
+ {"SETPL", LTYPE1, i386.ASETPL},
+ {"SETPS", LTYPE1, i386.ASETPS},
+ {"CDQ", LTYPE0, i386.ACDQ},
+ {"CWD", LTYPE0, i386.ACWD},
+ {"SHLB", LTYPE3, i386.ASHLB},
+ {"SHLL", LTYPES, i386.ASHLL},
+ {"SHLW", LTYPES, i386.ASHLW},
+ {"SHRB", LTYPE3, i386.ASHRB},
+ {"SHRL", LTYPES, i386.ASHRL},
+ {"SHRW", LTYPES, i386.ASHRW},
+ {"STC", LTYPE0, i386.ASTC},
+ {"STD", LTYPE0, i386.ASTD},
+ {"STI", LTYPE0, i386.ASTI},
+ {"STOSB", LTYPE0, i386.ASTOSB},
+ {"STOSL", LTYPE0, i386.ASTOSL},
+ {"STOSW", LTYPE0, i386.ASTOSW},
+ {"SUBB", LTYPE3, i386.ASUBB},
+ {"SUBL", LTYPE3, i386.ASUBL},
+ {"SUBW", LTYPE3, i386.ASUBW},
+ {"SYSCALL", LTYPE0, i386.ASYSCALL},
+ {"TESTB", LTYPE3, i386.ATESTB},
+ {"TESTL", LTYPE3, i386.ATESTL},
+ {"TESTW", LTYPE3, i386.ATESTW},
+ {"TEXT", LTYPET, i386.ATEXT},
+ {"VERR", LTYPE2, i386.AVERR},
+ {"VERW", LTYPE2, i386.AVERW},
+ {"WAIT", LTYPE0, i386.AWAIT},
+ {"WORD", LTYPE2, i386.AWORD},
+ {"XADDB", LTYPE3, i386.AXADDB},
+ {"XADDL", LTYPE3, i386.AXADDL},
+ {"XADDW", LTYPE3, i386.AXADDW},
+ {"XCHGB", LTYPE3, i386.AXCHGB},
+ {"XCHGL", LTYPE3, i386.AXCHGL},
+ {"XCHGW", LTYPE3, i386.AXCHGW},
+ {"XLAT", LTYPE2, i386.AXLAT},
+ {"XORB", LTYPE3, i386.AXORB},
+ {"XORL", LTYPE3, i386.AXORL},
+ {"XORW", LTYPE3, i386.AXORW},
+ {"CMOVLCC", LTYPE3, i386.ACMOVLCC},
+ {"CMOVLCS", LTYPE3, i386.ACMOVLCS},
+ {"CMOVLEQ", LTYPE3, i386.ACMOVLEQ},
+ {"CMOVLGE", LTYPE3, i386.ACMOVLGE},
+ {"CMOVLGT", LTYPE3, i386.ACMOVLGT},
+ {"CMOVLHI", LTYPE3, i386.ACMOVLHI},
+ {"CMOVLLE", LTYPE3, i386.ACMOVLLE},
+ {"CMOVLLS", LTYPE3, i386.ACMOVLLS},
+ {"CMOVLLT", LTYPE3, i386.ACMOVLLT},
+ {"CMOVLMI", LTYPE3, i386.ACMOVLMI},
+ {"CMOVLNE", LTYPE3, i386.ACMOVLNE},
+ {"CMOVLOC", LTYPE3, i386.ACMOVLOC},
+ {"CMOVLOS", LTYPE3, i386.ACMOVLOS},
+ {"CMOVLPC", LTYPE3, i386.ACMOVLPC},
+ {"CMOVLPL", LTYPE3, i386.ACMOVLPL},
+ {"CMOVLPS", LTYPE3, i386.ACMOVLPS},
+ {"CMOVWCC", LTYPE3, i386.ACMOVWCC},
+ {"CMOVWCS", LTYPE3, i386.ACMOVWCS},
+ {"CMOVWEQ", LTYPE3, i386.ACMOVWEQ},
+ {"CMOVWGE", LTYPE3, i386.ACMOVWGE},
+ {"CMOVWGT", LTYPE3, i386.ACMOVWGT},
+ {"CMOVWHI", LTYPE3, i386.ACMOVWHI},
+ {"CMOVWLE", LTYPE3, i386.ACMOVWLE},
+ {"CMOVWLS", LTYPE3, i386.ACMOVWLS},
+ {"CMOVWLT", LTYPE3, i386.ACMOVWLT},
+ {"CMOVWMI", LTYPE3, i386.ACMOVWMI},
+ {"CMOVWNE", LTYPE3, i386.ACMOVWNE},
+ {"CMOVWOC", LTYPE3, i386.ACMOVWOC},
+ {"CMOVWOS", LTYPE3, i386.ACMOVWOS},
+ {"CMOVWPC", LTYPE3, i386.ACMOVWPC},
+ {"CMOVWPL", LTYPE3, i386.ACMOVWPL},
+ {"CMOVWPS", LTYPE3, i386.ACMOVWPS},
+ {"FMOVB", LTYPE3, i386.AFMOVB},
+ {"FMOVBP", LTYPE3, i386.AFMOVBP},
+ {"FMOVD", LTYPE3, i386.AFMOVD},
+ {"FMOVDP", LTYPE3, i386.AFMOVDP},
+ {"FMOVF", LTYPE3, i386.AFMOVF},
+ {"FMOVFP", LTYPE3, i386.AFMOVFP},
+ {"FMOVL", LTYPE3, i386.AFMOVL},
+ {"FMOVLP", LTYPE3, i386.AFMOVLP},
+ {"FMOVV", LTYPE3, i386.AFMOVV},
+ {"FMOVVP", LTYPE3, i386.AFMOVVP},
+ {"FMOVW", LTYPE3, i386.AFMOVW},
+ {"FMOVWP", LTYPE3, i386.AFMOVWP},
+ {"FMOVX", LTYPE3, i386.AFMOVX},
+ {"FMOVXP", LTYPE3, i386.AFMOVXP},
+ {"FCMOVCC", LTYPE3, i386.AFCMOVCC},
+ {"FCMOVCS", LTYPE3, i386.AFCMOVCS},
+ {"FCMOVEQ", LTYPE3, i386.AFCMOVEQ},
+ {"FCMOVHI", LTYPE3, i386.AFCMOVHI},
+ {"FCMOVLS", LTYPE3, i386.AFCMOVLS},
+ {"FCMOVNE", LTYPE3, i386.AFCMOVNE},
+ {"FCMOVNU", LTYPE3, i386.AFCMOVNU},
+ {"FCMOVUN", LTYPE3, i386.AFCMOVUN},
+ {"FCOMB", LTYPE3, i386.AFCOMB},
+ {"FCOMBP", LTYPE3, i386.AFCOMBP},
+ {"FCOMD", LTYPE3, i386.AFCOMD},
+ {"FCOMDP", LTYPE3, i386.AFCOMDP},
+ {"FCOMDPP", LTYPE3, i386.AFCOMDPP},
+ {"FCOMF", LTYPE3, i386.AFCOMF},
+ {"FCOMFP", LTYPE3, i386.AFCOMFP},
+ {"FCOMI", LTYPE3, i386.AFCOMI},
+ {"FCOMIP", LTYPE3, i386.AFCOMIP},
+ {"FCOML", LTYPE3, i386.AFCOML},
+ {"FCOMLP", LTYPE3, i386.AFCOMLP},
+ {"FCOMW", LTYPE3, i386.AFCOMW},
+ {"FCOMWP", LTYPE3, i386.AFCOMWP},
+ {"FUCOM", LTYPE3, i386.AFUCOM},
+ {"FUCOMI", LTYPE3, i386.AFUCOMI},
+ {"FUCOMIP", LTYPE3, i386.AFUCOMIP},
+ {"FUCOMP", LTYPE3, i386.AFUCOMP},
+ {"FUCOMPP", LTYPE3, i386.AFUCOMPP},
+ {"FADDW", LTYPE3, i386.AFADDW},
+ {"FADDL", LTYPE3, i386.AFADDL},
+ {"FADDF", LTYPE3, i386.AFADDF},
+ {"FADDD", LTYPE3, i386.AFADDD},
+ {"FADDDP", LTYPE3, i386.AFADDDP},
+ {"FSUBDP", LTYPE3, i386.AFSUBDP},
+ {"FSUBW", LTYPE3, i386.AFSUBW},
+ {"FSUBL", LTYPE3, i386.AFSUBL},
+ {"FSUBF", LTYPE3, i386.AFSUBF},
+ {"FSUBD", LTYPE3, i386.AFSUBD},
+ {"FSUBRDP", LTYPE3, i386.AFSUBRDP},
+ {"FSUBRW", LTYPE3, i386.AFSUBRW},
+ {"FSUBRL", LTYPE3, i386.AFSUBRL},
+ {"FSUBRF", LTYPE3, i386.AFSUBRF},
+ {"FSUBRD", LTYPE3, i386.AFSUBRD},
+ {"FMULDP", LTYPE3, i386.AFMULDP},
+ {"FMULW", LTYPE3, i386.AFMULW},
+ {"FMULL", LTYPE3, i386.AFMULL},
+ {"FMULF", LTYPE3, i386.AFMULF},
+ {"FMULD", LTYPE3, i386.AFMULD},
+ {"FDIVDP", LTYPE3, i386.AFDIVDP},
+ {"FDIVW", LTYPE3, i386.AFDIVW},
+ {"FDIVL", LTYPE3, i386.AFDIVL},
+ {"FDIVF", LTYPE3, i386.AFDIVF},
+ {"FDIVD", LTYPE3, i386.AFDIVD},
+ {"FDIVRDP", LTYPE3, i386.AFDIVRDP},
+ {"FDIVRW", LTYPE3, i386.AFDIVRW},
+ {"FDIVRL", LTYPE3, i386.AFDIVRL},
+ {"FDIVRF", LTYPE3, i386.AFDIVRF},
+ {"FDIVRD", LTYPE3, i386.AFDIVRD},
+ {"FXCHD", LTYPE3, i386.AFXCHD},
+ {"FFREE", LTYPE1, i386.AFFREE},
+ {"FLDCW", LTYPE2, i386.AFLDCW},
+ {"FLDENV", LTYPE1, i386.AFLDENV},
+ {"FRSTOR", LTYPE2, i386.AFRSTOR},
+ {"FSAVE", LTYPE1, i386.AFSAVE},
+ {"FSTCW", LTYPE1, i386.AFSTCW},
+ {"FSTENV", LTYPE1, i386.AFSTENV},
+ {"FSTSW", LTYPE1, i386.AFSTSW},
+ {"F2XM1", LTYPE0, i386.AF2XM1},
+ {"FABS", LTYPE0, i386.AFABS},
+ {"FCHS", LTYPE0, i386.AFCHS},
+ {"FCLEX", LTYPE0, i386.AFCLEX},
+ {"FCOS", LTYPE0, i386.AFCOS},
+ {"FDECSTP", LTYPE0, i386.AFDECSTP},
+ {"FINCSTP", LTYPE0, i386.AFINCSTP},
+ {"FINIT", LTYPE0, i386.AFINIT},
+ {"FLD1", LTYPE0, i386.AFLD1},
+ {"FLDL2E", LTYPE0, i386.AFLDL2E},
+ {"FLDL2T", LTYPE0, i386.AFLDL2T},
+ {"FLDLG2", LTYPE0, i386.AFLDLG2},
+ {"FLDLN2", LTYPE0, i386.AFLDLN2},
+ {"FLDPI", LTYPE0, i386.AFLDPI},
+ {"FLDZ", LTYPE0, i386.AFLDZ},
+ {"FNOP", LTYPE0, i386.AFNOP},
+ {"FPATAN", LTYPE0, i386.AFPATAN},
+ {"FPREM", LTYPE0, i386.AFPREM},
+ {"FPREM1", LTYPE0, i386.AFPREM1},
+ {"FPTAN", LTYPE0, i386.AFPTAN},
+ {"FRNDINT", LTYPE0, i386.AFRNDINT},
+ {"FSCALE", LTYPE0, i386.AFSCALE},
+ {"FSIN", LTYPE0, i386.AFSIN},
+ {"FSINCOS", LTYPE0, i386.AFSINCOS},
+ {"FSQRT", LTYPE0, i386.AFSQRT},
+ {"FTST", LTYPE0, i386.AFTST},
+ {"FXAM", LTYPE0, i386.AFXAM},
+ {"FXTRACT", LTYPE0, i386.AFXTRACT},
+ {"FYL2X", LTYPE0, i386.AFYL2X},
+ {"FYL2XP1", LTYPE0, i386.AFYL2XP1},
+ {"LFENCE", LTYPE0, i386.ALFENCE},
+ {"MFENCE", LTYPE0, i386.AMFENCE},
+ {"SFENCE", LTYPE0, i386.ASFENCE},
+ {"EMMS", LTYPE0, i386.AEMMS},
+ {"PREFETCHT0", LTYPE2, i386.APREFETCHT0},
+ {"PREFETCHT1", LTYPE2, i386.APREFETCHT1},
+ {"PREFETCHT2", LTYPE2, i386.APREFETCHT2},
+ {"PREFETCHNTA", LTYPE2, i386.APREFETCHNTA},
+ {"UNDEF", LTYPE0, i386.AUNDEF},
+ {"ADDPD", LTYPE3, i386.AADDPD},
+ {"ADDPS", LTYPE3, i386.AADDPS},
+ {"ADDSD", LTYPE3, i386.AADDSD},
+ {"ADDSS", LTYPE3, i386.AADDSS},
+ {"AESENC", LTYPE3, i386.AAESENC},
+ {"ANDNPD", LTYPE3, i386.AANDNPD},
+ {"ANDNPS", LTYPE3, i386.AANDNPS},
+ {"ANDPD", LTYPE3, i386.AANDPD},
+ {"ANDPS", LTYPE3, i386.AANDPS},
+ {"CMPPD", LTYPEXC, i386.ACMPPD},
+ {"CMPPS", LTYPEXC, i386.ACMPPS},
+ {"CMPSD", LTYPEXC, i386.ACMPSD},
+ {"CMPSS", LTYPEXC, i386.ACMPSS},
+ {"COMISD", LTYPE3, i386.ACOMISD},
+ {"COMISS", LTYPE3, i386.ACOMISS},
+ {"CVTPL2PD", LTYPE3, i386.ACVTPL2PD},
+ {"CVTPL2PS", LTYPE3, i386.ACVTPL2PS},
+ {"CVTPD2PL", LTYPE3, i386.ACVTPD2PL},
+ {"CVTPD2PS", LTYPE3, i386.ACVTPD2PS},
+ {"CVTPS2PL", LTYPE3, i386.ACVTPS2PL},
+ {"CVTPS2PD", LTYPE3, i386.ACVTPS2PD},
+ {"CVTSD2SL", LTYPE3, i386.ACVTSD2SL},
+ {"CVTSD2SS", LTYPE3, i386.ACVTSD2SS},
+ {"CVTSL2SD", LTYPE3, i386.ACVTSL2SD},
+ {"CVTSL2SS", LTYPE3, i386.ACVTSL2SS},
+ {"CVTSS2SD", LTYPE3, i386.ACVTSS2SD},
+ {"CVTSS2SL", LTYPE3, i386.ACVTSS2SL},
+ {"CVTTPD2PL", LTYPE3, i386.ACVTTPD2PL},
+ {"CVTTPS2PL", LTYPE3, i386.ACVTTPS2PL},
+ {"CVTTSD2SL", LTYPE3, i386.ACVTTSD2SL},
+ {"CVTTSS2SL", LTYPE3, i386.ACVTTSS2SL},
+ {"DIVPD", LTYPE3, i386.ADIVPD},
+ {"DIVPS", LTYPE3, i386.ADIVPS},
+ {"DIVSD", LTYPE3, i386.ADIVSD},
+ {"DIVSS", LTYPE3, i386.ADIVSS},
+ {"MASKMOVOU", LTYPE3, i386.AMASKMOVOU},
+ {"MASKMOVDQU", LTYPE3, i386.AMASKMOVOU}, /* syn */
+ {"MAXPD", LTYPE3, i386.AMAXPD},
+ {"MAXPS", LTYPE3, i386.AMAXPS},
+ {"MAXSD", LTYPE3, i386.AMAXSD},
+ {"MAXSS", LTYPE3, i386.AMAXSS},
+ {"MINPD", LTYPE3, i386.AMINPD},
+ {"MINPS", LTYPE3, i386.AMINPS},
+ {"MINSD", LTYPE3, i386.AMINSD},
+ {"MINSS", LTYPE3, i386.AMINSS},
+ {"MOVAPD", LTYPE3, i386.AMOVAPD},
+ {"MOVAPS", LTYPE3, i386.AMOVAPS},
+ {"MOVO", LTYPE3, i386.AMOVO},
+ {"MOVOA", LTYPE3, i386.AMOVO}, /* syn */
+ {"MOVOU", LTYPE3, i386.AMOVOU},
+ {"MOVHLPS", LTYPE3, i386.AMOVHLPS},
+ {"MOVHPD", LTYPE3, i386.AMOVHPD},
+ {"MOVHPS", LTYPE3, i386.AMOVHPS},
+ {"MOVLHPS", LTYPE3, i386.AMOVLHPS},
+ {"MOVLPD", LTYPE3, i386.AMOVLPD},
+ {"MOVLPS", LTYPE3, i386.AMOVLPS},
+ {"MOVMSKPD", LTYPE3, i386.AMOVMSKPD},
+ {"MOVMSKPS", LTYPE3, i386.AMOVMSKPS},
+ {"MOVNTO", LTYPE3, i386.AMOVNTO},
+ {"MOVNTDQ", LTYPE3, i386.AMOVNTO}, /* syn */
+ {"MOVNTPD", LTYPE3, i386.AMOVNTPD},
+ {"MOVNTPS", LTYPE3, i386.AMOVNTPS},
+ {"MOVSD", LTYPE3, i386.AMOVSD},
+ {"MOVSS", LTYPE3, i386.AMOVSS},
+ {"MOVUPD", LTYPE3, i386.AMOVUPD},
+ {"MOVUPS", LTYPE3, i386.AMOVUPS},
+ {"MULPD", LTYPE3, i386.AMULPD},
+ {"MULPS", LTYPE3, i386.AMULPS},
+ {"MULSD", LTYPE3, i386.AMULSD},
+ {"MULSS", LTYPE3, i386.AMULSS},
+ {"ORPD", LTYPE3, i386.AORPD},
+ {"ORPS", LTYPE3, i386.AORPS},
+ {"PADDQ", LTYPE3, i386.APADDQ},
+ {"PAND", LTYPE3, i386.APAND},
+ {"PCMPEQB", LTYPE3, i386.APCMPEQB},
+ {"PMAXSW", LTYPE3, i386.APMAXSW},
+ {"PMAXUB", LTYPE3, i386.APMAXUB},
+ {"PMINSW", LTYPE3, i386.APMINSW},
+ {"PMINUB", LTYPE3, i386.APMINUB},
+ {"PMOVMSKB", LTYPE3, i386.APMOVMSKB},
+ {"PSADBW", LTYPE3, i386.APSADBW},
+ {"PSHUFB", LTYPE3, i386.APSHUFB},
+ {"PSHUFHW", LTYPEX, i386.APSHUFHW},
+ {"PSHUFL", LTYPEX, i386.APSHUFL},
+ {"PSHUFLW", LTYPEX, i386.APSHUFLW},
+ {"PSUBB", LTYPE3, i386.APSUBB},
+ {"PSUBL", LTYPE3, i386.APSUBL},
+ {"PSUBQ", LTYPE3, i386.APSUBQ},
+ {"PSUBSB", LTYPE3, i386.APSUBSB},
+ {"PSUBSW", LTYPE3, i386.APSUBSW},
+ {"PSUBUSB", LTYPE3, i386.APSUBUSB},
+ {"PSUBUSW", LTYPE3, i386.APSUBUSW},
+ {"PSUBW", LTYPE3, i386.APSUBW},
+ {"PUNPCKHQDQ", LTYPE3, i386.APUNPCKHQDQ},
+ {"PUNPCKLQDQ", LTYPE3, i386.APUNPCKLQDQ},
+ {"PXOR", LTYPE3, i386.APXOR},
+ {"RCPPS", LTYPE3, i386.ARCPPS},
+ {"RCPSS", LTYPE3, i386.ARCPSS},
+ {"RSQRTPS", LTYPE3, i386.ARSQRTPS},
+ {"RSQRTSS", LTYPE3, i386.ARSQRTSS},
+ {"SQRTPD", LTYPE3, i386.ASQRTPD},
+ {"SQRTPS", LTYPE3, i386.ASQRTPS},
+ {"SQRTSD", LTYPE3, i386.ASQRTSD},
+ {"SQRTSS", LTYPE3, i386.ASQRTSS},
+ {"SUBPD", LTYPE3, i386.ASUBPD},
+ {"SUBPS", LTYPE3, i386.ASUBPS},
+ {"SUBSD", LTYPE3, i386.ASUBSD},
+ {"SUBSS", LTYPE3, i386.ASUBSS},
+ {"UCOMISD", LTYPE3, i386.AUCOMISD},
+ {"UCOMISS", LTYPE3, i386.AUCOMISS},
+ {"UNPCKHPD", LTYPE3, i386.AUNPCKHPD},
+ {"UNPCKHPS", LTYPE3, i386.AUNPCKHPS},
+ {"UNPCKLPD", LTYPE3, i386.AUNPCKLPD},
+ {"UNPCKLPS", LTYPE3, i386.AUNPCKLPS},
+ {"XORPD", LTYPE3, i386.AXORPD},
+ {"XORPS", LTYPE3, i386.AXORPS},
+ {"USEFIELD", LTYPEN, i386.AUSEFIELD},
+ {"PCDATA", LTYPEPC, i386.APCDATA},
+ {"FUNCDATA", LTYPEF, i386.AFUNCDATA},
+}
+
+func cinit() {
+ nullgen.Type = i386.D_NONE
+ nullgen.Index = i386.D_NONE
+}
+
+func checkscale(scale int8) {
+ switch scale {
+ case 1,
+ 2,
+ 4,
+ 8:
+ return
+ }
+
+ yyerror("scale must be 1248: %d", scale)
+}
+
+func syminit(s *asm.Sym) {
+ s.Type = LNAME
+ s.Value = 0
+}
+
+func cclean() {
+ var g2 Addr2
+
+ g2.from = nullgen
+ g2.to = nullgen
+ outcode(i386.AEND, &g2)
+}
+
+var lastpc *obj.Prog
+
+type Addr2 struct {
+ from obj.Addr
+ to obj.Addr
+}
+
+func outcode(a int, g2 *Addr2) {
+ var p *obj.Prog
+ var pl *obj.Plist
+
+ if asm.Pass == 1 {
+ goto out
+ }
+
+ p = new(obj.Prog)
+ *p = obj.Prog{}
+ p.Ctxt = asm.Ctxt
+ p.As = int16(a)
+ p.Lineno = stmtline
+ p.From = g2.from
+ p.To = g2.to
+ p.Pc = int64(asm.PC)
+
+ if lastpc == nil {
+ pl = obj.Linknewplist(asm.Ctxt)
+ pl.Firstpc = p
+ } else {
+
+ lastpc.Link = p
+ }
+ lastpc = p
+
+out:
+ if a != i386.AGLOBL && a != i386.ADATA {
+ asm.PC++
+ }
+}
--- /dev/null
+//line a.y:32
+package main
+
+import __yyfmt__ "fmt"
+
+//line a.y:32
+import (
+ "cmd/internal/asm"
+ "cmd/internal/obj"
+ . "cmd/internal/obj/i386"
+)
+
+//line a.y:41
+type yySymType struct {
+ yys int
+ sym *asm.Sym
+ lval int64
+ con2 struct {
+ v1 int32
+ v2 int32
+ }
+ dval float64
+ sval string
+ addr obj.Addr
+ addr2 Addr2
+}
+
+const LTYPE0 = 57346
+const LTYPE1 = 57347
+const LTYPE2 = 57348
+const LTYPE3 = 57349
+const LTYPE4 = 57350
+const LTYPEC = 57351
+const LTYPED = 57352
+const LTYPEN = 57353
+const LTYPER = 57354
+const LTYPET = 57355
+const LTYPES = 57356
+const LTYPEM = 57357
+const LTYPEI = 57358
+const LTYPEG = 57359
+const LTYPEXC = 57360
+const LTYPEX = 57361
+const LTYPEPC = 57362
+const LTYPEF = 57363
+const LCONST = 57364
+const LFP = 57365
+const LPC = 57366
+const LSB = 57367
+const LBREG = 57368
+const LLREG = 57369
+const LSREG = 57370
+const LFREG = 57371
+const LXREG = 57372
+const LFCONST = 57373
+const LSCONST = 57374
+const LSP = 57375
+const LNAME = 57376
+const LLAB = 57377
+const LVAR = 57378
+
+var yyToknames = []string{
+ "'|'",
+ "'^'",
+ "'&'",
+ "'<'",
+ "'>'",
+ "'+'",
+ "'-'",
+ "'*'",
+ "'/'",
+ "'%'",
+ "LTYPE0",
+ "LTYPE1",
+ "LTYPE2",
+ "LTYPE3",
+ "LTYPE4",
+ "LTYPEC",
+ "LTYPED",
+ "LTYPEN",
+ "LTYPER",
+ "LTYPET",
+ "LTYPES",
+ "LTYPEM",
+ "LTYPEI",
+ "LTYPEG",
+ "LTYPEXC",
+ "LTYPEX",
+ "LTYPEPC",
+ "LTYPEF",
+ "LCONST",
+ "LFP",
+ "LPC",
+ "LSB",
+ "LBREG",
+ "LLREG",
+ "LSREG",
+ "LFREG",
+ "LXREG",
+ "LFCONST",
+ "LSCONST",
+ "LSP",
+ "LNAME",
+ "LLAB",
+ "LVAR",
+}
+var yyStatenames = []string{}
+
+const yyEofCode = 1
+const yyErrCode = 2
+const yyMaxDepth = 200
+
+//line yacctab:1
+var yyExca = []int{
+ -1, 1,
+ 1, -1,
+ -2, 2,
+}
+
+const yyNprod = 132
+const yyPrivate = 57344
+
+var yyTokenNames []string
+var yyStates []string
+
+const yyLast = 586
+
+var yyAct = []int{
+
+ 47, 37, 59, 185, 45, 120, 80, 3, 49, 78,
+ 60, 187, 268, 57, 267, 69, 208, 68, 85, 82,
+ 84, 67, 83, 169, 73, 100, 62, 102, 46, 109,
+ 266, 115, 109, 92, 94, 96, 262, 255, 253, 104,
+ 106, 241, 239, 237, 221, 219, 81, 210, 209, 109,
+ 170, 240, 234, 117, 118, 119, 231, 207, 211, 173,
+ 108, 125, 144, 110, 168, 135, 116, 69, 112, 126,
+ 230, 229, 109, 133, 53, 52, 136, 223, 85, 82,
+ 84, 142, 83, 222, 143, 153, 152, 139, 141, 151,
+ 58, 150, 145, 149, 148, 53, 52, 50, 147, 146,
+ 138, 36, 113, 134, 64, 132, 81, 131, 114, 36,
+ 124, 51, 33, 31, 30, 154, 71, 29, 50, 54,
+ 27, 228, 28, 175, 176, 227, 111, 220, 165, 167,
+ 109, 117, 51, 55, 166, 69, 247, 71, 184, 186,
+ 54, 182, 142, 246, 183, 143, 181, 165, 167, 236,
+ 192, 172, 191, 166, 251, 252, 109, 109, 109, 109,
+ 109, 256, 183, 109, 109, 109, 195, 196, 263, 257,
+ 212, 226, 217, 245, 215, 53, 130, 137, 34, 117,
+ 218, 111, 216, 38, 260, 259, 32, 197, 198, 199,
+ 200, 201, 254, 225, 204, 205, 206, 89, 50, 121,
+ 75, 122, 123, 109, 109, 88, 98, 128, 127, 235,
+ 55, 213, 51, 258, 238, 122, 123, 129, 203, 244,
+ 54, 174, 180, 202, 6, 242, 107, 243, 157, 158,
+ 159, 249, 248, 250, 232, 233, 2, 188, 189, 190,
+ 1, 193, 194, 105, 39, 41, 44, 40, 42, 103,
+ 7, 43, 101, 99, 97, 261, 95, 93, 91, 87,
+ 264, 265, 9, 10, 11, 12, 13, 17, 15, 18,
+ 14, 16, 19, 20, 21, 22, 23, 24, 25, 26,
+ 53, 52, 79, 163, 162, 160, 161, 155, 156, 157,
+ 158, 159, 4, 76, 8, 74, 5, 72, 63, 61,
+ 53, 52, 140, 50, 56, 65, 224, 39, 41, 44,
+ 40, 42, 214, 0, 43, 86, 0, 51, 0, 0,
+ 0, 77, 48, 50, 60, 54, 0, 39, 41, 44,
+ 40, 42, 53, 52, 43, 86, 0, 51, 0, 0,
+ 0, 0, 48, 0, 60, 54, 155, 156, 157, 158,
+ 159, 0, 53, 52, 0, 50, 0, 0, 0, 39,
+ 41, 44, 40, 42, 0, 0, 43, 55, 0, 51,
+ 0, 0, 53, 52, 48, 50, 60, 54, 0, 39,
+ 41, 44, 40, 42, 0, 0, 43, 55, 0, 51,
+ 0, 0, 0, 90, 48, 50, 0, 54, 0, 39,
+ 41, 44, 40, 42, 53, 52, 43, 55, 0, 51,
+ 0, 0, 0, 35, 48, 0, 0, 54, 0, 0,
+ 53, 52, 0, 0, 53, 52, 0, 50, 0, 0,
+ 0, 39, 41, 44, 40, 42, 0, 0, 43, 55,
+ 0, 51, 0, 50, 53, 52, 48, 50, 0, 54,
+ 0, 39, 41, 44, 40, 42, 0, 51, 43, 53,
+ 52, 51, 71, 0, 60, 54, 48, 50, 0, 54,
+ 164, 163, 162, 160, 161, 155, 156, 157, 158, 159,
+ 0, 51, 50, 0, 53, 52, 71, 0, 187, 54,
+ 53, 52, 0, 0, 70, 0, 51, 0, 0, 0,
+ 66, 71, 0, 60, 54, 53, 178, 50, 0, 0,
+ 0, 53, 52, 50, 0, 53, 52, 0, 171, 70,
+ 0, 51, 179, 0, 0, 0, 71, 51, 50, 54,
+ 0, 0, 71, 0, 50, 54, 0, 177, 50, 0,
+ 0, 0, 51, 0, 0, 0, 55, 71, 51, 0,
+ 54, 0, 51, 48, 0, 0, 54, 71, 0, 0,
+ 54, 164, 163, 162, 160, 161, 155, 156, 157, 158,
+ 159, 162, 160, 161, 155, 156, 157, 158, 159, 160,
+ 161, 155, 156, 157, 158, 159,
+}
+var yyPact = []int{
+
+ -1000, -1000, 248, -1000, 73, -1000, 69, 66, 64, 62,
+ 363, 323, 323, 395, 450, 89, 502, 271, 343, 323,
+ 323, 323, 502, 208, -43, 323, 323, -1000, 506, -1000,
+ -1000, 506, -1000, -1000, -1000, 395, -1000, -1000, -1000, -1000,
+ -1000, -1000, -1000, -1000, -1000, -1000, -1000, 17, 65, 15,
+ -1000, -1000, 506, 506, 506, 192, -1000, 60, -1000, -1000,
+ 166, -1000, 57, -1000, 55, -1000, 475, -1000, 53, 14,
+ 206, 506, -1000, 165, -1000, 50, -1000, 291, -1000, 395,
+ -1000, -1000, -1000, -1000, -1000, 11, 192, -1000, -1000, -1000,
+ 395, -1000, 49, -1000, 48, -1000, 44, -1000, 43, -1000,
+ 41, -1000, 39, -1000, 36, -1000, 35, 248, 557, -1000,
+ 557, -1000, 91, 12, -2, 466, 114, -1000, -1000, -1000,
+ 8, 213, 506, 506, -1000, -1000, -1000, -1000, -1000, 496,
+ 481, 395, 323, -1000, 475, 128, -1000, 506, 435, -1000,
+ 415, -1000, -1000, -1000, 110, 8, 395, 395, 395, 411,
+ 395, 395, 323, 323, -1000, 506, 506, 506, 506, 506,
+ 216, 210, 506, 506, 506, 5, -4, -5, 7, 506,
+ -1000, -1000, 200, 139, 206, -1000, -1000, -7, 86, -1000,
+ -1000, -1000, -1000, -8, 33, -1000, 27, 161, 78, 74,
+ -1000, -1000, 21, 20, 6, -1000, -1000, 217, 217, -1000,
+ -1000, -1000, 506, 506, 572, 565, 278, 1, 506, -1000,
+ -1000, 112, -9, 506, -10, -1000, -1000, -1000, 0, -1000,
+ -11, -1000, -43, -42, -1000, 209, 141, 106, 98, -43,
+ 506, 208, 337, 337, 117, -14, 181, -1000, -15, -1000,
+ 126, -1000, -1000, -1000, 137, 203, -1000, -1000, -1000, -1000,
+ -1000, 174, 173, -1000, 506, -1000, -16, -1000, 136, 506,
+ 506, -22, -1000, -1000, -38, -40, -1000, -1000, -1000,
+}
+var yyPgo = []int{
+
+ 0, 0, 31, 312, 5, 306, 183, 2, 3, 1,
+ 8, 6, 90, 13, 9, 4, 28, 186, 305, 178,
+ 304, 299, 298, 297, 295, 293, 259, 258, 257, 256,
+ 254, 253, 252, 249, 243, 240, 236, 7, 226, 224,
+}
+var yyR1 = []int{
+
+ 0, 35, 36, 35, 38, 37, 37, 37, 37, 39,
+ 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
+ 39, 39, 39, 39, 39, 39, 39, 39, 39, 17,
+ 17, 21, 22, 20, 20, 19, 19, 18, 18, 18,
+ 23, 24, 24, 25, 25, 25, 26, 26, 27, 27,
+ 28, 28, 29, 29, 29, 30, 30, 31, 32, 33,
+ 34, 12, 12, 14, 14, 14, 14, 14, 14, 14,
+ 13, 13, 11, 11, 9, 9, 9, 9, 9, 9,
+ 7, 7, 7, 7, 7, 7, 7, 8, 5, 5,
+ 5, 5, 6, 6, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 16, 16, 10, 10, 4,
+ 4, 4, 3, 3, 3, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2,
+}
+var yyR2 = []int{
+
+ 0, 0, 0, 3, 0, 4, 1, 2, 2, 3,
+ 3, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
+ 1, 3, 3, 2, 1, 2, 1, 2, 1, 3,
+ 5, 3, 5, 2, 1, 2, 1, 1, 3, 5,
+ 3, 5, 2, 1, 3, 3, 5, 5, 5, 3,
+ 3, 1, 1, 1, 1, 2, 2, 1, 1, 1,
+ 1, 1, 4, 2, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 4, 5, 3, 2, 1, 2,
+ 3, 4, 1, 1, 1, 4, 4, 6, 9, 9,
+ 3, 3, 4, 5, 8, 1, 6, 5, 7, 0,
+ 2, 2, 1, 1, 1, 1, 1, 2, 2, 2,
+ 3, 1, 3, 3, 3, 3, 3, 4, 4, 3,
+ 3, 3,
+}
+var yyChk = []int{
+
+ -1000, -35, -36, -37, 44, 48, -39, 2, 46, 14,
+ 15, 16, 17, 18, 22, 20, 23, 19, 21, 24,
+ 25, 26, 27, 28, 29, 30, 31, 47, 49, 48,
+ 48, 49, -17, 50, -19, 50, -12, -9, -6, 36,
+ 39, 37, 40, 43, 38, -15, -16, -1, 51, -10,
+ 32, 46, 10, 9, 54, 44, -20, -13, -12, -7,
+ 53, -21, -13, -22, -12, -18, 50, -11, -7, -1,
+ 44, 51, -23, -10, -24, -6, -25, 50, -14, 11,
+ -11, -16, -9, -15, -7, -1, 44, -26, -17, -19,
+ 50, -27, -13, -28, -13, -29, -13, -30, -6, -31,
+ -9, -32, -7, -33, -13, -34, -13, -38, -2, -1,
+ -2, -12, 51, 37, 43, -2, 51, -1, -1, -1,
+ -4, 7, 9, 10, 50, -1, -10, 42, 41, 51,
+ 10, 50, 50, -11, 50, 51, -4, 12, 50, -14,
+ 11, -10, -9, -15, 51, -4, 50, 50, 50, 50,
+ 50, 50, 50, 50, -37, 9, 10, 11, 12, 13,
+ 7, 8, 6, 5, 4, 37, 43, 38, 52, 11,
+ 52, 52, 37, 51, 8, -1, -1, 41, 10, 41,
+ -12, -13, -11, 34, -1, -8, -1, 53, -12, -12,
+ -12, -7, -1, -12, -12, -13, -13, -2, -2, -2,
+ -2, -2, 7, 8, -2, -2, -2, 52, 11, 52,
+ 52, 51, -1, 11, -3, 35, 43, 33, -4, 52,
+ 41, 52, 50, 50, -5, 32, 10, 47, 47, 50,
+ 50, 50, -2, -2, 51, -1, 37, 52, -1, 52,
+ 51, 52, -7, -8, 10, 32, 37, 38, -7, -1,
+ -9, 37, 38, 52, 11, 52, 35, 32, 10, 11,
+ 11, -1, 52, 32, -1, -1, 52, 52, 52,
+}
+var yyDef = []int{
+
+ 1, -2, 0, 3, 0, 6, 0, 0, 0, 29,
+ 0, 0, 0, 0, 0, 0, 0, 0, 29, 0,
+ 0, 0, 0, 0, 0, 0, 0, 4, 0, 7,
+ 8, 0, 11, 30, 12, 0, 36, 61, 62, 74,
+ 75, 76, 77, 78, 79, 92, 93, 94, 0, 105,
+ 115, 116, 0, 0, 0, 109, 13, 34, 70, 71,
+ 0, 14, 0, 15, 0, 16, 0, 38, 0, 0,
+ 109, 0, 17, 0, 18, 0, 19, 0, 44, 0,
+ 63, 64, 67, 68, 69, 94, 109, 20, 46, 47,
+ 30, 21, 0, 22, 0, 23, 53, 24, 0, 25,
+ 0, 26, 0, 27, 0, 28, 0, 0, 9, 121,
+ 10, 35, 0, 0, 0, 0, 0, 117, 118, 119,
+ 0, 0, 0, 0, 33, 80, 81, 82, 83, 0,
+ 0, 0, 0, 37, 0, 0, 73, 0, 0, 43,
+ 0, 45, 65, 66, 0, 73, 0, 0, 52, 0,
+ 0, 0, 0, 0, 5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 100, 0,
+ 101, 120, 0, 0, 109, 110, 111, 0, 0, 86,
+ 31, 32, 39, 0, 0, 41, 0, 0, 48, 50,
+ 54, 55, 0, 0, 0, 59, 60, 122, 123, 124,
+ 125, 126, 0, 0, 129, 130, 131, 95, 0, 96,
+ 102, 0, 0, 0, 0, 112, 113, 114, 0, 84,
+ 0, 72, 0, 0, 87, 88, 0, 0, 0, 0,
+ 0, 0, 127, 128, 0, 0, 0, 103, 0, 107,
+ 0, 85, 40, 42, 0, 89, 49, 51, 56, 57,
+ 58, 0, 0, 97, 0, 106, 0, 90, 0, 0,
+ 0, 0, 108, 91, 0, 0, 104, 98, 99,
+}
+var yyTok1 = []int{
+
+ 1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 53, 13, 6, 3,
+ 51, 52, 11, 9, 50, 10, 3, 12, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 47, 48,
+ 7, 49, 8, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 5, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 4, 3, 54,
+}
+var yyTok2 = []int{
+
+ 2, 3, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46,
+}
+var yyTok3 = []int{
+ 0,
+}
+
+//line yaccpar:1
+
+/* parser for yacc output */
+
+var yyDebug = 0
+
+type yyLexer interface {
+ Lex(lval *yySymType) int
+ Error(s string)
+}
+
+const yyFlag = -1000
+
+func yyTokname(c int) string {
+ // 4 is TOKSTART above
+ if c >= 4 && c-4 < len(yyToknames) {
+ if yyToknames[c-4] != "" {
+ return yyToknames[c-4]
+ }
+ }
+ return __yyfmt__.Sprintf("tok-%v", c)
+}
+
+func yyStatname(s int) string {
+ if s >= 0 && s < len(yyStatenames) {
+ if yyStatenames[s] != "" {
+ return yyStatenames[s]
+ }
+ }
+ return __yyfmt__.Sprintf("state-%v", s)
+}
+
+func yylex1(lex yyLexer, lval *yySymType) int {
+ c := 0
+ char := lex.Lex(lval)
+ if char <= 0 {
+ c = yyTok1[0]
+ goto out
+ }
+ if char < len(yyTok1) {
+ c = yyTok1[char]
+ goto out
+ }
+ if char >= yyPrivate {
+ if char < yyPrivate+len(yyTok2) {
+ c = yyTok2[char-yyPrivate]
+ goto out
+ }
+ }
+ for i := 0; i < len(yyTok3); i += 2 {
+ c = yyTok3[i+0]
+ if c == char {
+ c = yyTok3[i+1]
+ goto out
+ }
+ }
+
+out:
+ if c == 0 {
+ c = yyTok2[1] /* unknown char */
+ }
+ if yyDebug >= 3 {
+ __yyfmt__.Printf("lex %s(%d)\n", yyTokname(c), uint(char))
+ }
+ return c
+}
+
+func yyParse(yylex yyLexer) int {
+ var yyn int
+ var yylval yySymType
+ var yyVAL yySymType
+ yyS := make([]yySymType, yyMaxDepth)
+
+ Nerrs := 0 /* number of errors */
+ Errflag := 0 /* error recovery flag */
+ yystate := 0
+ yychar := -1
+ yyp := -1
+ goto yystack
+
+ret0:
+ return 0
+
+ret1:
+ return 1
+
+yystack:
+ /* put a state and value onto the stack */
+ if yyDebug >= 4 {
+ __yyfmt__.Printf("char %v in %v\n", yyTokname(yychar), yyStatname(yystate))
+ }
+
+ yyp++
+ if yyp >= len(yyS) {
+ nyys := make([]yySymType, len(yyS)*2)
+ copy(nyys, yyS)
+ yyS = nyys
+ }
+ yyS[yyp] = yyVAL
+ yyS[yyp].yys = yystate
+
+yynewstate:
+ yyn = yyPact[yystate]
+ if yyn <= yyFlag {
+ goto yydefault /* simple state */
+ }
+ if yychar < 0 {
+ yychar = yylex1(yylex, &yylval)
+ }
+ yyn += yychar
+ if yyn < 0 || yyn >= yyLast {
+ goto yydefault
+ }
+ yyn = yyAct[yyn]
+ if yyChk[yyn] == yychar { /* valid shift */
+ yychar = -1
+ yyVAL = yylval
+ yystate = yyn
+ if Errflag > 0 {
+ Errflag--
+ }
+ goto yystack
+ }
+
+yydefault:
+ /* default state action */
+ yyn = yyDef[yystate]
+ if yyn == -2 {
+ if yychar < 0 {
+ yychar = yylex1(yylex, &yylval)
+ }
+
+ /* look through exception table */
+ xi := 0
+ for {
+ if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate {
+ break
+ }
+ xi += 2
+ }
+ for xi += 2; ; xi += 2 {
+ yyn = yyExca[xi+0]
+ if yyn < 0 || yyn == yychar {
+ break
+ }
+ }
+ yyn = yyExca[xi+1]
+ if yyn < 0 {
+ goto ret0
+ }
+ }
+ if yyn == 0 {
+ /* error ... attempt to resume parsing */
+ switch Errflag {
+ case 0: /* brand new error */
+ yylex.Error("syntax error")
+ Nerrs++
+ if yyDebug >= 1 {
+ __yyfmt__.Printf("%s", yyStatname(yystate))
+ __yyfmt__.Printf(" saw %s\n", yyTokname(yychar))
+ }
+ fallthrough
+
+ case 1, 2: /* incompletely recovered error ... try again */
+ Errflag = 3
+
+ /* find a state where "error" is a legal shift action */
+ for yyp >= 0 {
+ yyn = yyPact[yyS[yyp].yys] + yyErrCode
+ if yyn >= 0 && yyn < yyLast {
+ yystate = yyAct[yyn] /* simulate a shift of "error" */
+ if yyChk[yystate] == yyErrCode {
+ goto yystack
+ }
+ }
+
+ /* the current p has no shift on "error", pop stack */
+ if yyDebug >= 2 {
+ __yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys)
+ }
+ yyp--
+ }
+ /* there is no state on the stack with an error shift ... abort */
+ goto ret1
+
+ case 3: /* no shift yet; clobber input char */
+ if yyDebug >= 2 {
+ __yyfmt__.Printf("error recovery discards %s\n", yyTokname(yychar))
+ }
+ if yychar == yyEofCode {
+ goto ret1
+ }
+ yychar = -1
+ goto yynewstate /* try again in the same state */
+ }
+ }
+
+ /* reduction by production yyn */
+ if yyDebug >= 2 {
+ __yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate))
+ }
+
+ yynt := yyn
+ yypt := yyp
+ _ = yypt // guard against "declared and not used"
+
+ yyp -= yyR2[yyn]
+ // yyp is now the index of $0. Perform the default action. Iff the
+ // reduced production is ε, $1 is possibly out of range.
+ if yyp+1 >= len(yyS) {
+ nyys := make([]yySymType, len(yyS)*2)
+ copy(nyys, yyS)
+ yyS = nyys
+ }
+ yyVAL = yyS[yyp+1]
+
+ /* consult goto table to find next state */
+ yyn = yyR1[yyn]
+ yyg := yyPgo[yyn]
+ yyj := yyg + yyS[yyp].yys + 1
+
+ if yyj >= yyLast {
+ yystate = yyAct[yyg]
+ } else {
+ yystate = yyAct[yyj]
+ if yyChk[yystate] != -yyn {
+ yystate = yyAct[yyg]
+ }
+ }
+ // dummy call; replaced with literal code
+ switch yynt {
+
+ case 2:
+ //line a.y:75
+ {
+ stmtline = asm.Lineno
+ }
+ case 4:
+ //line a.y:82
+ {
+ yyS[yypt-1].sym = asm.LabelLookup(yyS[yypt-1].sym)
+ if yyS[yypt-1].sym.Type == LLAB && yyS[yypt-1].sym.Value != int64(asm.PC) {
+ yyerror("redeclaration of %s", yyS[yypt-1].sym.Labelname)
+ }
+ yyS[yypt-1].sym.Type = LLAB
+ yyS[yypt-1].sym.Value = int64(asm.PC)
+ }
+ case 9:
+ //line a.y:97
+ {
+ yyS[yypt-2].sym.Type = LVAR
+ yyS[yypt-2].sym.Value = yyS[yypt-0].lval
+ }
+ case 10:
+ //line a.y:102
+ {
+ if yyS[yypt-2].sym.Value != int64(yyS[yypt-0].lval) {
+ yyerror("redeclaration of %s", yyS[yypt-2].sym.Name)
+ }
+ yyS[yypt-2].sym.Value = yyS[yypt-0].lval
+ }
+ case 11:
+ //line a.y:108
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 12:
+ //line a.y:109
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 13:
+ //line a.y:110
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 14:
+ //line a.y:111
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 15:
+ //line a.y:112
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 16:
+ //line a.y:113
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 17:
+ //line a.y:114
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 18:
+ //line a.y:115
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 19:
+ //line a.y:116
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 20:
+ //line a.y:117
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 21:
+ //line a.y:118
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 22:
+ //line a.y:119
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 23:
+ //line a.y:120
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 24:
+ //line a.y:121
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 25:
+ //line a.y:122
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 26:
+ //line a.y:123
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 27:
+ //line a.y:124
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 28:
+ //line a.y:125
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr2)
+ }
+ case 29:
+ //line a.y:128
+ {
+ yyVAL.addr2.from = nullgen
+ yyVAL.addr2.to = nullgen
+ }
+ case 30:
+ //line a.y:133
+ {
+ yyVAL.addr2.from = nullgen
+ yyVAL.addr2.to = nullgen
+ }
+ case 31:
+ //line a.y:140
+ {
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 32:
+ //line a.y:147
+ {
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 33:
+ //line a.y:154
+ {
+ yyVAL.addr2.from = yyS[yypt-1].addr
+ yyVAL.addr2.to = nullgen
+ }
+ case 34:
+ //line a.y:159
+ {
+ yyVAL.addr2.from = yyS[yypt-0].addr
+ yyVAL.addr2.to = nullgen
+ }
+ case 35:
+ //line a.y:166
+ {
+ yyVAL.addr2.from = nullgen
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 36:
+ //line a.y:171
+ {
+ yyVAL.addr2.from = nullgen
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 37:
+ //line a.y:178
+ {
+ yyVAL.addr2.from = nullgen
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 38:
+ //line a.y:183
+ {
+ yyVAL.addr2.from = nullgen
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 39:
+ //line a.y:188
+ {
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 40:
+ //line a.y:195
+ {
+ yyVAL.addr2.from = yyS[yypt-4].addr
+ yyVAL.addr2.from.Scale = int8(yyS[yypt-2].lval)
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 41:
+ //line a.y:203
+ {
+ asm.Settext(yyS[yypt-2].addr.Sym)
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 42:
+ //line a.y:209
+ {
+ asm.Settext(yyS[yypt-4].addr.Sym)
+ yyVAL.addr2.from = yyS[yypt-4].addr
+ yyVAL.addr2.from.Scale = int8(yyS[yypt-2].lval)
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 43:
+ //line a.y:218
+ {
+ yyVAL.addr2.from = nullgen
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 44:
+ //line a.y:223
+ {
+ yyVAL.addr2.from = nullgen
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 45:
+ //line a.y:228
+ {
+ yyVAL.addr2.from = nullgen
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ yyVAL.addr2.to.Index = uint8(yyS[yypt-0].addr.Type)
+ yyVAL.addr2.to.Type = D_INDIR + D_ADDR
+ }
+ case 46:
+ yyVAL.addr2 = yyS[yypt-0].addr2
+ case 47:
+ yyVAL.addr2 = yyS[yypt-0].addr2
+ case 48:
+ //line a.y:241
+ {
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 49:
+ //line a.y:246
+ {
+ yyVAL.addr2.from = yyS[yypt-4].addr
+ yyVAL.addr2.to = yyS[yypt-2].addr
+ if yyVAL.addr2.from.Index != D_NONE {
+ yyerror("dp shift with lhs index")
+ }
+ yyVAL.addr2.from.Index = uint8(yyS[yypt-0].lval)
+ }
+ case 50:
+ //line a.y:257
+ {
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 51:
+ //line a.y:262
+ {
+ yyVAL.addr2.from = yyS[yypt-4].addr
+ yyVAL.addr2.to = yyS[yypt-2].addr
+ if yyVAL.addr2.to.Index != D_NONE {
+ yyerror("dp move with lhs index")
+ }
+ yyVAL.addr2.to.Index = uint8(yyS[yypt-0].lval)
+ }
+ case 52:
+ //line a.y:273
+ {
+ yyVAL.addr2.from = yyS[yypt-1].addr
+ yyVAL.addr2.to = nullgen
+ }
+ case 53:
+ //line a.y:278
+ {
+ yyVAL.addr2.from = yyS[yypt-0].addr
+ yyVAL.addr2.to = nullgen
+ }
+ case 54:
+ //line a.y:283
+ {
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 55:
+ //line a.y:290
+ {
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 56:
+ //line a.y:295
+ {
+ yyVAL.addr2.from = yyS[yypt-4].addr
+ yyVAL.addr2.from.Scale = int8(yyS[yypt-2].lval)
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 57:
+ //line a.y:303
+ {
+ yyVAL.addr2.from = yyS[yypt-4].addr
+ yyVAL.addr2.to = yyS[yypt-2].addr
+ yyVAL.addr2.to.Offset = yyS[yypt-0].lval
+ }
+ case 58:
+ //line a.y:311
+ {
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ if yyS[yypt-4].addr.Type != D_CONST {
+ yyerror("illegal constant")
+ }
+ yyVAL.addr2.to.Offset = yyS[yypt-4].addr.Offset
+ }
+ case 59:
+ //line a.y:322
+ {
+ if yyS[yypt-2].addr.Type != D_CONST || yyS[yypt-0].addr.Type != D_CONST {
+ yyerror("arguments to PCDATA must be integer constants")
+ }
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 60:
+ //line a.y:332
+ {
+ if yyS[yypt-2].addr.Type != D_CONST {
+ yyerror("index for FUNCDATA must be integer constant")
+ }
+ if yyS[yypt-0].addr.Type != D_EXTERN && yyS[yypt-0].addr.Type != D_STATIC {
+ yyerror("value for FUNCDATA must be symbol reference")
+ }
+ yyVAL.addr2.from = yyS[yypt-2].addr
+ yyVAL.addr2.to = yyS[yypt-0].addr
+ }
+ case 61:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 62:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 63:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 64:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 65:
+ //line a.y:351
+ {
+ yyVAL.addr = yyS[yypt-0].addr
+ }
+ case 66:
+ //line a.y:355
+ {
+ yyVAL.addr = yyS[yypt-0].addr
+ }
+ case 67:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 68:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 69:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 70:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 71:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 72:
+ //line a.y:368
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_BRANCH
+ yyVAL.addr.Offset = yyS[yypt-3].lval + int64(asm.PC)
+ }
+ case 73:
+ //line a.y:374
+ {
+ yyS[yypt-1].sym = asm.LabelLookup(yyS[yypt-1].sym)
+ yyVAL.addr = nullgen
+ if asm.Pass == 2 && yyS[yypt-1].sym.Type != LLAB {
+ yyerror("undefined label: %s", yyS[yypt-1].sym.Labelname)
+ }
+ yyVAL.addr.Type = D_BRANCH
+ yyVAL.addr.Offset = yyS[yypt-1].sym.Value + yyS[yypt-0].lval
+ }
+ case 74:
+ //line a.y:386
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+ }
+ case 75:
+ //line a.y:391
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+ }
+ case 76:
+ //line a.y:396
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+ }
+ case 77:
+ //line a.y:401
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+ }
+ case 78:
+ //line a.y:406
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_SP
+ }
+ case 79:
+ //line a.y:411
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(yyS[yypt-0].lval)
+ }
+ case 80:
+ //line a.y:418
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_CONST
+ yyVAL.addr.Offset = yyS[yypt-0].lval
+ }
+ case 81:
+ //line a.y:424
+ {
+ yyVAL.addr = yyS[yypt-0].addr
+ yyVAL.addr.Index = uint8(yyS[yypt-0].addr.Type)
+ yyVAL.addr.Type = D_ADDR
+ /*
+ if($2.Type == D_AUTO || $2.Type == D_PARAM)
+ yyerror("constant cannot be automatic: %s",
+ $2.Sym.name);
+ */
+ }
+ case 82:
+ //line a.y:434
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_SCONST
+ yyVAL.addr.U.Sval = yyS[yypt-0].sval
+ }
+ case 83:
+ //line a.y:440
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_FCONST
+ yyVAL.addr.U.Dval = yyS[yypt-0].dval
+ }
+ case 84:
+ //line a.y:446
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_FCONST
+ yyVAL.addr.U.Dval = yyS[yypt-1].dval
+ }
+ case 85:
+ //line a.y:452
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_FCONST
+ yyVAL.addr.U.Dval = -yyS[yypt-1].dval
+ }
+ case 86:
+ //line a.y:458
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_FCONST
+ yyVAL.addr.U.Dval = -yyS[yypt-0].dval
+ }
+ case 87:
+ //line a.y:466
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_CONST2
+ yyVAL.addr.Offset = int64(yyS[yypt-0].con2.v1)
+ yyVAL.addr.Offset2 = int32(yyS[yypt-0].con2.v2)
+ }
+ case 88:
+ //line a.y:475
+ {
+ yyVAL.con2.v1 = int32(yyS[yypt-0].lval)
+ yyVAL.con2.v2 = -obj.ArgsSizeUnknown
+ }
+ case 89:
+ //line a.y:480
+ {
+ yyVAL.con2.v1 = int32(-yyS[yypt-0].lval)
+ yyVAL.con2.v2 = -obj.ArgsSizeUnknown
+ }
+ case 90:
+ //line a.y:485
+ {
+ yyVAL.con2.v1 = int32(yyS[yypt-2].lval)
+ yyVAL.con2.v2 = int32(yyS[yypt-0].lval)
+ }
+ case 91:
+ //line a.y:490
+ {
+ yyVAL.con2.v1 = int32(-yyS[yypt-2].lval)
+ yyVAL.con2.v2 = int32(yyS[yypt-0].lval)
+ }
+ case 92:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 93:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 94:
+ //line a.y:501
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_INDIR + D_NONE
+ yyVAL.addr.Offset = yyS[yypt-0].lval
+ }
+ case 95:
+ //line a.y:507
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(D_INDIR + yyS[yypt-1].lval)
+ yyVAL.addr.Offset = yyS[yypt-3].lval
+ }
+ case 96:
+ //line a.y:513
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_INDIR + D_SP
+ yyVAL.addr.Offset = yyS[yypt-3].lval
+ }
+ case 97:
+ //line a.y:519
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_INDIR + D_NONE
+ yyVAL.addr.Offset = yyS[yypt-5].lval
+ yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+ yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+ checkscale(yyVAL.addr.Scale)
+ }
+ case 98:
+ //line a.y:528
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(D_INDIR + yyS[yypt-6].lval)
+ yyVAL.addr.Offset = yyS[yypt-8].lval
+ yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+ yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+ checkscale(yyVAL.addr.Scale)
+ }
+ case 99:
+ //line a.y:537
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(D_INDIR + yyS[yypt-6].lval)
+ yyVAL.addr.Offset = yyS[yypt-8].lval
+ yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+ yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+ checkscale(yyVAL.addr.Scale)
+ }
+ case 100:
+ //line a.y:546
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(D_INDIR + yyS[yypt-1].lval)
+ }
+ case 101:
+ //line a.y:551
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_INDIR + D_SP
+ }
+ case 102:
+ //line a.y:556
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(D_INDIR + yyS[yypt-1].lval)
+ yyVAL.addr.Offset = yyS[yypt-3].lval
+ }
+ case 103:
+ //line a.y:562
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_INDIR + D_NONE
+ yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+ yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+ checkscale(yyVAL.addr.Scale)
+ }
+ case 104:
+ //line a.y:570
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(D_INDIR + yyS[yypt-6].lval)
+ yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+ yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+ checkscale(yyVAL.addr.Scale)
+ }
+ case 105:
+ //line a.y:580
+ {
+ yyVAL.addr = yyS[yypt-0].addr
+ }
+ case 106:
+ //line a.y:584
+ {
+ yyVAL.addr = yyS[yypt-5].addr
+ yyVAL.addr.Index = uint8(yyS[yypt-3].lval)
+ yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+ checkscale(yyVAL.addr.Scale)
+ }
+ case 107:
+ //line a.y:593
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(yyS[yypt-1].lval)
+ yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyS[yypt-4].sym.Name, 0)
+ yyVAL.addr.Offset = yyS[yypt-3].lval
+ }
+ case 108:
+ //line a.y:600
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_STATIC
+ yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyS[yypt-6].sym.Name, 1)
+ yyVAL.addr.Offset = yyS[yypt-3].lval
+ }
+ case 109:
+ //line a.y:608
+ {
+ yyVAL.lval = 0
+ }
+ case 110:
+ //line a.y:612
+ {
+ yyVAL.lval = yyS[yypt-0].lval
+ }
+ case 111:
+ //line a.y:616
+ {
+ yyVAL.lval = -yyS[yypt-0].lval
+ }
+ case 112:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 113:
+ //line a.y:623
+ {
+ yyVAL.lval = D_AUTO
+ }
+ case 114:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 115:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 116:
+ //line a.y:631
+ {
+ yyVAL.lval = yyS[yypt-0].sym.Value
+ }
+ case 117:
+ //line a.y:635
+ {
+ yyVAL.lval = -yyS[yypt-0].lval
+ }
+ case 118:
+ //line a.y:639
+ {
+ yyVAL.lval = yyS[yypt-0].lval
+ }
+ case 119:
+ //line a.y:643
+ {
+ yyVAL.lval = ^yyS[yypt-0].lval
+ }
+ case 120:
+ //line a.y:647
+ {
+ yyVAL.lval = yyS[yypt-1].lval
+ }
+ case 121:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 122:
+ //line a.y:654
+ {
+ yyVAL.lval = yyS[yypt-2].lval + yyS[yypt-0].lval
+ }
+ case 123:
+ //line a.y:658
+ {
+ yyVAL.lval = yyS[yypt-2].lval - yyS[yypt-0].lval
+ }
+ case 124:
+ //line a.y:662
+ {
+ yyVAL.lval = yyS[yypt-2].lval * yyS[yypt-0].lval
+ }
+ case 125:
+ //line a.y:666
+ {
+ yyVAL.lval = yyS[yypt-2].lval / yyS[yypt-0].lval
+ }
+ case 126:
+ //line a.y:670
+ {
+ yyVAL.lval = yyS[yypt-2].lval % yyS[yypt-0].lval
+ }
+ case 127:
+ //line a.y:674
+ {
+ yyVAL.lval = yyS[yypt-3].lval << uint(yyS[yypt-0].lval)
+ }
+ case 128:
+ //line a.y:678
+ {
+ yyVAL.lval = yyS[yypt-3].lval >> uint(yyS[yypt-0].lval)
+ }
+ case 129:
+ //line a.y:682
+ {
+ yyVAL.lval = yyS[yypt-2].lval & yyS[yypt-0].lval
+ }
+ case 130:
+ //line a.y:686
+ {
+ yyVAL.lval = yyS[yypt-2].lval ^ yyS[yypt-0].lval
+ }
+ case 131:
+ //line a.y:690
+ {
+ yyVAL.lval = yyS[yypt-2].lval | yyS[yypt-0].lval
+ }
+ }
+ goto yystack /* stack new state and value */
+}
--- /dev/null
+// cmd/9a/a.y from Vita Nuova.
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+%{
+package main
+
+import (
+ "cmd/internal/asm"
+ "cmd/internal/obj"
+ . "cmd/internal/obj/ppc64"
+)
+%}
+
+%union
+{
+ sym *asm.Sym
+ lval int64
+ dval float64
+ sval string
+ addr obj.Addr
+}
+
+%left '|'
+%left '^'
+%left '&'
+%left '<' '>'
+%left '+' '-'
+%left '*' '/' '%'
+%token <lval> LMOVW LMOVB LABS LLOGW LSHW LADDW LCMP LCROP
+%token <lval> LBRA LFMOV LFCONV LFCMP LFADD LFMA LTRAP LXORW
+%token <lval> LNOP LEND LRETT LWORD LTEXT LDATA LRETRN
+%token <lval> LCONST LSP LSB LFP LPC LCREG LFLUSH
+%token <lval> LREG LFREG LR LCR LF LFPSCR
+%token <lval> LLR LCTR LSPR LSPREG LSEG LMSR
+%token <lval> LPCDAT LFUNCDAT LSCHED LXLD LXST LXOP LXMV
+%token <lval> LRLWM LMOVMW LMOVEM LMOVFL LMTFSB LMA
+%token <dval> LFCONST
+%token <sval> LSCONST
+%token <sym> LNAME LLAB LVAR
+%type <lval> con expr pointer offset sreg
+%type <addr> addr rreg regaddr name creg freg xlreg lr ctr
+%type <addr> imm ximm fimm rel psr lcr cbit fpscr fpscrf msr mask
+%%
+prog:
+| prog line
+
+line:
+ LNAME ':'
+ {
+ $1 = asm.LabelLookup($1);
+ if $1.Type == LLAB && $1.Value != int64(asm.PC) {
+ yyerror("redeclaration of %s", $1.Labelname)
+ }
+ $1.Type = LLAB;
+ $1.Value = int64(asm.PC);
+ }
+ line
+| LNAME '=' expr ';'
+ {
+ $1.Type = LVAR;
+ $1.Value = $3;
+ }
+| LVAR '=' expr ';'
+ {
+ if $1.Value != $3 {
+ yyerror("redeclaration of %s", $1.Name)
+ }
+ $1.Value = $3;
+ }
+| LSCHED ';'
+ {
+ nosched = int($1);
+ }
+| ';'
+| inst ';'
+| error ';'
+
+inst:
+/*
+ * load ints and bytes
+ */
+ LMOVW rreg ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVW addr ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVW regaddr ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVB rreg ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVB addr ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVB regaddr ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+/*
+ * load floats
+ */
+| LFMOV addr ',' freg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LFMOV regaddr ',' freg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LFMOV fimm ',' freg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LFMOV freg ',' freg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LFMOV freg ',' addr
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LFMOV freg ',' regaddr
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+/*
+ * store ints and bytes
+ */
+| LMOVW rreg ',' addr
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVW rreg ',' regaddr
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVB rreg ',' addr
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVB rreg ',' regaddr
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+/*
+ * store floats
+ */
+| LMOVW freg ',' addr
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVW freg ',' regaddr
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+/*
+ * floating point status
+ */
+| LMOVW fpscr ',' freg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVW freg ',' fpscr
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVW freg ',' imm ',' fpscr
+ {
+ outgcode(int($1), &$2, NREG, &$4, &$6);
+ }
+| LMOVW fpscr ',' creg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVW imm ',' fpscrf
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMTFSB imm ',' con
+ {
+ outcode(int($1), &$2, int($4), &nullgen);
+ }
+/*
+ * field moves (mtcrf)
+ */
+| LMOVW rreg ',' imm ',' lcr
+ {
+ outgcode(int($1), &$2, NREG, &$4, &$6);
+ }
+| LMOVW rreg ',' creg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVW rreg ',' lcr
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+/*
+ * integer operations
+ * logical instructions
+ * shift instructions
+ * unary instructions
+ */
+| LADDW rreg ',' sreg ',' rreg
+ {
+ outcode(int($1), &$2, int($4), &$6);
+ }
+| LADDW imm ',' sreg ',' rreg
+ {
+ outcode(int($1), &$2, int($4), &$6);
+ }
+| LADDW rreg ',' imm ',' rreg
+ {
+ outgcode(int($1), &$2, NREG, &$4, &$6);
+ }
+| LADDW rreg ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LADDW imm ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LLOGW rreg ',' sreg ',' rreg
+ {
+ outcode(int($1), &$2, int($4), &$6);
+ }
+| LLOGW rreg ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LSHW rreg ',' sreg ',' rreg
+ {
+ outcode(int($1), &$2, int($4), &$6);
+ }
+| LSHW rreg ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LSHW imm ',' sreg ',' rreg
+ {
+ outcode(int($1), &$2, int($4), &$6);
+ }
+| LSHW imm ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LABS rreg ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LABS rreg
+ {
+ outcode(int($1), &$2, NREG, &$2);
+ }
+/*
+ * multiply-accumulate
+ */
+| LMA rreg ',' sreg ',' rreg
+ {
+ outcode(int($1), &$2, int($4), &$6);
+ }
+/*
+ * move immediate: macro for cau+or, addi, addis, and other combinations
+ */
+| LMOVW imm ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVW ximm ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+/*
+ * condition register operations
+ */
+| LCROP cbit ',' cbit
+ {
+ outcode(int($1), &$2, int($4.Reg), &$4);
+ }
+| LCROP cbit ',' con ',' cbit
+ {
+ outcode(int($1), &$2, int($4), &$6);
+ }
+/*
+ * condition register moves
+ * move from machine state register
+ */
+| LMOVW creg ',' creg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVW psr ',' creg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVW lcr ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVW psr ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVW xlreg ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVW rreg ',' xlreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVW creg ',' psr
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVW rreg ',' psr
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+/*
+ * branch, branch conditional
+ * branch conditional register
+ * branch conditional to count register
+ */
+| LBRA rel
+ {
+ outcode(int($1), &nullgen, NREG, &$2);
+ }
+| LBRA addr
+ {
+ outcode(int($1), &nullgen, NREG, &$2);
+ }
+| LBRA '(' xlreg ')'
+ {
+ outcode(int($1), &nullgen, NREG, &$3);
+ }
+| LBRA ',' rel
+ {
+ outcode(int($1), &nullgen, NREG, &$3);
+ }
+| LBRA ',' addr
+ {
+ outcode(int($1), &nullgen, NREG, &$3);
+ }
+| LBRA ',' '(' xlreg ')'
+ {
+ outcode(int($1), &nullgen, NREG, &$4);
+ }
+| LBRA creg ',' rel
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LBRA creg ',' addr
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LBRA creg ',' '(' xlreg ')'
+ {
+ outcode(int($1), &$2, NREG, &$5);
+ }
+| LBRA con ',' rel
+ {
+ outcode(int($1), &nullgen, int($2), &$4);
+ }
+| LBRA con ',' addr
+ {
+ outcode(int($1), &nullgen, int($2), &$4);
+ }
+| LBRA con ',' '(' xlreg ')'
+ {
+ outcode(int($1), &nullgen, int($2), &$5);
+ }
+| LBRA con ',' con ',' rel
+ {
+ var g obj.Addr
+ g = nullgen;
+ g.Type = D_CONST;
+ g.Offset = $2;
+ outcode(int($1), &g, int($4), &$6);
+ }
+| LBRA con ',' con ',' addr
+ {
+ var g obj.Addr
+ g = nullgen;
+ g.Type = D_CONST;
+ g.Offset = $2;
+ outcode(int($1), &g, int($4), &$6);
+ }
+| LBRA con ',' con ',' '(' xlreg ')'
+ {
+ var g obj.Addr
+ g = nullgen;
+ g.Type = D_CONST;
+ g.Offset = $2;
+ outcode(int($1), &g, int($4), &$7);
+ }
+/*
+ * conditional trap
+ */
+| 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, NREG, &nullgen);
+ }
+| LTRAP comma
+ {
+ outcode(int($1), &nullgen, NREG, &nullgen);
+ }
+/*
+ * floating point operate
+ */
+| LFCONV freg ',' freg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LFADD freg ',' freg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LFADD freg ',' freg ',' freg
+ {
+ outcode(int($1), &$2, int($4.Reg), &$6);
+ }
+| LFMA freg ',' freg ',' freg ',' freg
+ {
+ outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
+ }
+| LFCMP freg ',' freg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LFCMP freg ',' freg ',' creg
+ {
+ outcode(int($1), &$2, int($6.Reg), &$4);
+ }
+/*
+ * CMP
+ */
+| LCMP rreg ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LCMP rreg ',' imm
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LCMP rreg ',' rreg ',' creg
+ {
+ outcode(int($1), &$2, int($6.Reg), &$4);
+ }
+| LCMP rreg ',' imm ',' creg
+ {
+ outcode(int($1), &$2, int($6.Reg), &$4);
+ }
+/*
+ * rotate and mask
+ */
+| LRLWM imm ',' rreg ',' imm ',' rreg
+ {
+ outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
+ }
+| LRLWM imm ',' rreg ',' mask ',' rreg
+ {
+ outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
+ }
+| LRLWM rreg ',' rreg ',' imm ',' rreg
+ {
+ outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
+ }
+| LRLWM rreg ',' rreg ',' mask ',' rreg
+ {
+ outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
+ }
+/*
+ * load/store multiple
+ */
+| LMOVMW addr ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LMOVMW rreg ',' addr
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+/*
+ * various indexed load/store
+ * indexed unary (eg, cache clear)
+ */
+| LXLD regaddr ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LXLD regaddr ',' imm ',' rreg
+ {
+ outgcode(int($1), &$2, NREG, &$4, &$6);
+ }
+| LXST rreg ',' regaddr
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LXST rreg ',' imm ',' regaddr
+ {
+ outgcode(int($1), &$2, NREG, &$4, &$6);
+ }
+| LXMV regaddr ',' rreg
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LXMV rreg ',' regaddr
+ {
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LXOP regaddr
+ {
+ outcode(int($1), &$2, NREG, &nullgen);
+ }
+/*
+ * NOP
+ */
+| LNOP comma
+ {
+ outcode(int($1), &nullgen, NREG, &nullgen);
+ }
+| LNOP rreg comma
+ {
+ outcode(int($1), &$2, NREG, &nullgen);
+ }
+| LNOP freg comma
+ {
+ outcode(int($1), &$2, NREG, &nullgen);
+ }
+| LNOP ',' rreg
+ {
+ outcode(int($1), &nullgen, NREG, &$3);
+ }
+| LNOP ',' freg
+ {
+ outcode(int($1), &nullgen, NREG, &$3);
+ }
+| LNOP imm /* SYSCALL $num: load $num to R0 before syscall and restore R0 to 0 afterwards. */
+ {
+ outcode(int($1), &$2, NREG, &nullgen);
+ }
+/*
+ * word
+ */
+| LWORD imm comma
+ {
+ outcode(int($1), &$2, NREG, &nullgen);
+ }
+| LWORD ximm comma
+ {
+ outcode(int($1), &$2, NREG, &nullgen);
+ }
+/*
+ * PCDATA
+ */
+| LPCDAT imm ',' imm
+ {
+ if $2.Type != D_CONST || $4.Type != D_CONST {
+ yyerror("arguments to PCDATA must be integer constants")
+ }
+ outcode(int($1), &$2, NREG, &$4);
+ }
+/*
+ * FUNCDATA
+ */
+| LFUNCDAT imm ',' addr
+ {
+ if $2.Type != D_CONST {
+ yyerror("index for FUNCDATA must be integer constant")
+ }
+ if $4.Type != D_EXTERN && $4.Type != D_STATIC && $4.Type != D_OREG {
+ yyerror("value for FUNCDATA must be symbol reference")
+ }
+ outcode(int($1), &$2, NREG, &$4);
+ }
+/*
+ * END
+ */
+| LEND comma
+ {
+ outcode(int($1), &nullgen, NREG, &nullgen);
+ }
+/*
+ * TEXT/GLOBL
+ */
+| LTEXT name ',' imm
+ {
+ asm.Settext($2.Sym);
+ outcode(int($1), &$2, NREG, &$4);
+ }
+| LTEXT name ',' con ',' imm
+ {
+ asm.Settext($2.Sym);
+ $6.Offset &= 0xffffffff;
+ $6.Offset |= -obj.ArgsSizeUnknown << 32;
+ outcode(int($1), &$2, int($4), &$6);
+ }
+| LTEXT name ',' con ',' imm '-' con
+ {
+ asm.Settext($2.Sym);
+ $6.Offset &= 0xffffffff;
+ $6.Offset |= ($8 & 0xffffffff) << 32;
+ outcode(int($1), &$2, int($4), &$6);
+ }
+/*
+ * DATA
+ */
+| LDATA name '/' con ',' imm
+ {
+ outcode(int($1), &$2, int($4), &$6);
+ }
+| LDATA name '/' con ',' ximm
+ {
+ outcode(int($1), &$2, int($4), &$6);
+ }
+| LDATA name '/' con ',' fimm
+ {
+ outcode(int($1), &$2, int($4), &$6);
+ }
+/*
+ * RETURN
+ */
+| LRETRN comma
+ {
+ outcode(int($1), &nullgen, NREG, &nullgen);
+ }
+
+rel:
+ con '(' LPC ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_BRANCH;
+ $$.Offset = $1 + int64(asm.PC);
+ }
+| LNAME offset
+ {
+ $1 = asm.LabelLookup($1);
+ $$ = nullgen;
+ if asm.Pass == 2 && $1.Type != LLAB {
+ yyerror("undefined label: %s", $1.Labelname)
+ }
+ $$.Type = D_BRANCH;
+ $$.Offset = $1.Value + $2;
+ }
+
+rreg:
+ sreg
+ {
+ $$ = nullgen;
+ $$.Type = D_REG;
+ $$.Reg = int8($1);
+ }
+
+xlreg:
+ lr
+| ctr
+
+lr:
+ LLR
+ {
+ $$ = nullgen;
+ $$.Type = D_SPR;
+ $$.Offset = $1;
+ }
+
+lcr:
+ LCR
+ {
+ $$ = nullgen;
+ $$.Type = D_CREG;
+ $$.Reg = NREG; /* whole register */
+ }
+
+ctr:
+ LCTR
+ {
+ $$ = nullgen;
+ $$.Type = D_SPR;
+ $$.Offset = $1;
+ }
+
+msr:
+ LMSR
+ {
+ $$ = nullgen;
+ $$.Type = D_MSR;
+ }
+
+psr:
+ LSPREG
+ {
+ $$ = nullgen;
+ $$.Type = D_SPR;
+ $$.Offset = $1;
+ }
+| LSPR '(' con ')'
+ {
+ $$ = nullgen;
+ $$.Type = int16($1);
+ $$.Offset = $3;
+ }
+| msr
+
+fpscr:
+ LFPSCR
+ {
+ $$ = nullgen;
+ $$.Type = D_FPSCR;
+ $$.Reg = NREG;
+ }
+
+fpscrf:
+ LFPSCR '(' con ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_FPSCR;
+ $$.Reg = int8($3);
+ }
+
+freg:
+ LFREG
+ {
+ $$ = nullgen;
+ $$.Type = D_FREG;
+ $$.Reg = int8($1);
+ }
+| LF '(' con ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_FREG;
+ $$.Reg = int8($3);
+ }
+
+creg:
+ LCREG
+ {
+ $$ = nullgen;
+ $$.Type = D_CREG;
+ $$.Reg = int8($1);
+ }
+| LCR '(' con ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_CREG;
+ $$.Reg = int8($3);
+ }
+
+
+cbit: con
+ {
+ $$ = nullgen;
+ $$.Type = D_REG;
+ $$.Reg = int8($1);
+ }
+
+mask:
+ con ',' con
+ {
+ var mb, me int
+ var v uint32
+
+ $$ = nullgen;
+ $$.Type = D_CONST;
+ mb = int($1);
+ me = int($3);
+ if(mb < 0 || mb > 31 || me < 0 || me > 31){
+ yyerror("illegal mask start/end value(s)");
+ mb = 0
+ me = 0;
+ }
+ if mb <= me {
+ v = (^uint32(0)>>uint(mb)) & (^uint32(0)<<uint(31-me))
+ } else {
+ v = (^uint32(0)>>uint(me+1)) & (^uint32(0)<<uint(31-(mb-1)))
+ }
+ $$.Offset = int64(v);
+ }
+
+ximm:
+ '$' addr
+ {
+ $$ = $2;
+ $$.Type = D_CONST;
+ }
+| '$' LSCONST
+ {
+ $$ = nullgen;
+ $$.Type = D_SCONST;
+ $$.U.Sval = $2
+ }
+
+fimm:
+ '$' LFCONST
+ {
+ $$ = nullgen;
+ $$.Type = D_FCONST;
+ $$.U.Dval = $2;
+ }
+| '$' '-' LFCONST
+ {
+ $$ = nullgen;
+ $$.Type = D_FCONST;
+ $$.U.Dval = -$3;
+ }
+
+imm: '$' con
+ {
+ $$ = nullgen;
+ $$.Type = D_CONST;
+ $$.Offset = $2;
+ }
+
+sreg:
+ LREG
+| LR '(' con ')'
+ {
+ if $$ < 0 || $$ >= NREG {
+ print("register value out of range\n")
+ }
+ $$ = $3;
+ }
+
+regaddr:
+ '(' sreg ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_OREG;
+ $$.Reg = int8($2);
+ $$.Offset = 0;
+ }
+| '(' sreg '+' sreg ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_OREG;
+ $$.Reg = int8($2);
+ $$.Scale = int8($4);
+ $$.Offset = 0;
+ }
+
+addr:
+ name
+| con '(' sreg ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_OREG;
+ $$.Reg = int8($3);
+ $$.Offset = $1;
+ }
+
+name:
+ con '(' pointer ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_OREG;
+ $$.Name = int8($3);
+ $$.Sym = nil;
+ $$.Offset = $1;
+ }
+| LNAME offset '(' pointer ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_OREG;
+ $$.Name = int8($4);
+ $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
+ $$.Offset = $2;
+ }
+| LNAME '<' '>' offset '(' LSB ')'
+ {
+ $$ = nullgen;
+ $$.Type = D_OREG;
+ $$.Name = D_STATIC;
+ $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
+ $$.Offset = $4;
+ }
+
+comma:
+| ','
+
+offset:
+ {
+ $$ = 0;
+ }
+| '+' con
+ {
+ $$ = $2;
+ }
+| '-' con
+ {
+ $$ = -$2;
+ }
+
+pointer:
+ LSB
+| LSP
+| LFP
+
+con:
+ LCONST
+| LVAR
+ {
+ $$ = $1.Value;
+ }
+| '-' con
+ {
+ $$ = -$2;
+ }
+| '+' con
+ {
+ $$ = $2;
+ }
+| '~' con
+ {
+ $$ = ^$2;
+ }
+| '(' expr ')'
+ {
+ $$ = $2;
+ }
+
+expr:
+ con
+| expr '+' expr
+ {
+ $$ = $1 + $3;
+ }
+| expr '-' expr
+ {
+ $$ = $1 - $3;
+ }
+| expr '*' expr
+ {
+ $$ = $1 * $3;
+ }
+| expr '/' expr
+ {
+ $$ = $1 / $3;
+ }
+| expr '%' expr
+ {
+ $$ = $1 % $3;
+ }
+| expr '<' '<' expr
+ {
+ $$ = $1 << uint($4);
+ }
+| expr '>' '>' expr
+ {
+ $$ = $1 >> uint($4);
+ }
+| expr '&' expr
+ {
+ $$ = $1 & $3;
+ }
+| expr '^' expr
+ {
+ $$ = $1 ^ $3;
+ }
+| expr '|' expr
+ {
+ $$ = $1 | $3;
+ }
--- /dev/null
+// cmd/9a/lex.c from Vita Nuova.
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+//go:generate go tool yacc a.y
+
+package main
+
+import (
+ "cmd/internal/asm"
+ "cmd/internal/obj"
+ "cmd/internal/obj/ppc64"
+)
+
+var (
+ yyerror = asm.Yyerror
+ nullgen obj.Addr
+)
+
+func main() {
+ cinit()
+
+ asm.LSCONST = LSCONST
+ asm.LCONST = LCONST
+ asm.LFCONST = LFCONST
+ asm.LNAME = LNAME
+ asm.LVAR = LVAR
+ asm.LLAB = LLAB
+
+ asm.Lexinit = lexinit
+ asm.Cclean = cclean
+ asm.Yyparse = yyparse
+
+ asm.Thechar = '9'
+ asm.Thestring = "ppc64"
+ asm.Thelinkarch = &ppc64.Linkppc64
+ asm.Arches = map[string]*obj.LinkArch{
+ "ppc64le": &ppc64.Linkppc64le,
+ }
+
+ asm.Main()
+}
+
+type yy struct{}
+
+func (yy) Lex(v *yySymType) int {
+ var av asm.Yylval
+ tok := asm.Yylex(&av)
+ v.sym = av.Sym
+ v.lval = av.Lval
+ v.sval = av.Sval
+ v.dval = av.Dval
+ return tok
+}
+
+func (yy) Error(msg string) {
+ asm.Yyerror("%s", msg)
+}
+
+func yyparse() {
+ nosched = 0
+ yyParse(yy{})
+}
+
+var lexinit = []asm.Lextab{
+ {"SP", LSP, ppc64.D_AUTO},
+ {"SB", LSB, ppc64.D_EXTERN},
+ {"FP", LFP, ppc64.D_PARAM},
+ {"PC", LPC, ppc64.D_BRANCH},
+ {"LR", LLR, ppc64.D_LR},
+ {"CTR", LCTR, ppc64.D_CTR},
+ {"XER", LSPREG, ppc64.D_XER},
+ {"MSR", LMSR, ppc64.D_MSR},
+ {"FPSCR", LFPSCR, ppc64.D_FPSCR},
+ {"SPR", LSPR, ppc64.D_SPR},
+ {"DCR", LSPR, ppc64.D_DCR},
+ {"CR", LCR, 0},
+ {"CR0", LCREG, 0},
+ {"CR1", LCREG, 1},
+ {"CR2", LCREG, 2},
+ {"CR3", LCREG, 3},
+ {"CR4", LCREG, 4},
+ {"CR5", LCREG, 5},
+ {"CR6", LCREG, 6},
+ {"CR7", LCREG, 7},
+ {"R", LR, 0},
+ {"R0", LREG, 0},
+ {"R1", LREG, 1},
+ {"R2", LREG, 2},
+ {"R3", LREG, 3},
+ {"R4", LREG, 4},
+ {"R5", LREG, 5},
+ {"R6", LREG, 6},
+ {"R7", LREG, 7},
+ {"R8", LREG, 8},
+ {"R9", LREG, 9},
+ {"R10", LREG, 10},
+ {"R11", LREG, 11},
+ {"R12", LREG, 12},
+ {"R13", LREG, 13},
+ {"R14", LREG, 14},
+ {"R15", LREG, 15},
+ {"R16", LREG, 16},
+ {"R17", LREG, 17},
+ {"R18", LREG, 18},
+ {"R19", LREG, 19},
+ {"R20", LREG, 20},
+ {"R21", LREG, 21},
+ {"R22", LREG, 22},
+ {"R23", LREG, 23},
+ {"R24", LREG, 24},
+ {"R25", LREG, 25},
+ {"R26", LREG, 26},
+ {"R27", LREG, 27},
+ {"R28", LREG, 28},
+ {"R29", LREG, 29},
+ {"g", LREG, 30}, // avoid unintentionally clobbering g using R30
+ {"R31", LREG, 31},
+ {"F", LF, 0},
+ {"F0", LFREG, 0},
+ {"F1", LFREG, 1},
+ {"F2", LFREG, 2},
+ {"F3", LFREG, 3},
+ {"F4", LFREG, 4},
+ {"F5", LFREG, 5},
+ {"F6", LFREG, 6},
+ {"F7", LFREG, 7},
+ {"F8", LFREG, 8},
+ {"F9", LFREG, 9},
+ {"F10", LFREG, 10},
+ {"F11", LFREG, 11},
+ {"F12", LFREG, 12},
+ {"F13", LFREG, 13},
+ {"F14", LFREG, 14},
+ {"F15", LFREG, 15},
+ {"F16", LFREG, 16},
+ {"F17", LFREG, 17},
+ {"F18", LFREG, 18},
+ {"F19", LFREG, 19},
+ {"F20", LFREG, 20},
+ {"F21", LFREG, 21},
+ {"F22", LFREG, 22},
+ {"F23", LFREG, 23},
+ {"F24", LFREG, 24},
+ {"F25", LFREG, 25},
+ {"F26", LFREG, 26},
+ {"F27", LFREG, 27},
+ {"F28", LFREG, 28},
+ {"F29", LFREG, 29},
+ {"F30", LFREG, 30},
+ {"F31", LFREG, 31},
+ {"CREQV", LCROP, ppc64.ACREQV},
+ {"CRXOR", LCROP, ppc64.ACRXOR},
+ {"CRAND", LCROP, ppc64.ACRAND},
+ {"CROR", LCROP, ppc64.ACROR},
+ {"CRANDN", LCROP, ppc64.ACRANDN},
+ {"CRORN", LCROP, ppc64.ACRORN},
+ {"CRNAND", LCROP, ppc64.ACRNAND},
+ {"CRNOR", LCROP, ppc64.ACRNOR},
+ {"ADD", LADDW, ppc64.AADD},
+ {"ADDV", LADDW, ppc64.AADDV},
+ {"ADDCC", LADDW, ppc64.AADDCC},
+ {"ADDVCC", LADDW, ppc64.AADDVCC},
+ {"ADDC", LADDW, ppc64.AADDC},
+ {"ADDCV", LADDW, ppc64.AADDCV},
+ {"ADDCCC", LADDW, ppc64.AADDCCC},
+ {"ADDCVCC", LADDW, ppc64.AADDCVCC},
+ {"ADDE", LLOGW, ppc64.AADDE},
+ {"ADDEV", LLOGW, ppc64.AADDEV},
+ {"ADDECC", LLOGW, ppc64.AADDECC},
+ {"ADDEVCC", LLOGW, ppc64.AADDEVCC},
+ {"ADDME", LABS, ppc64.AADDME},
+ {"ADDMEV", LABS, ppc64.AADDMEV},
+ {"ADDMECC", LABS, ppc64.AADDMECC},
+ {"ADDMEVCC", LABS, ppc64.AADDMEVCC},
+ {"ADDZE", LABS, ppc64.AADDZE},
+ {"ADDZEV", LABS, ppc64.AADDZEV},
+ {"ADDZECC", LABS, ppc64.AADDZECC},
+ {"ADDZEVCC", LABS, ppc64.AADDZEVCC},
+ {"SUB", LADDW, ppc64.ASUB},
+ {"SUBV", LADDW, ppc64.ASUBV},
+ {"SUBCC", LADDW, ppc64.ASUBCC},
+ {"SUBVCC", LADDW, ppc64.ASUBVCC},
+ {"SUBE", LLOGW, ppc64.ASUBE},
+ {"SUBECC", LLOGW, ppc64.ASUBECC},
+ {"SUBEV", LLOGW, ppc64.ASUBEV},
+ {"SUBEVCC", LLOGW, ppc64.ASUBEVCC},
+ {"SUBC", LADDW, ppc64.ASUBC},
+ {"SUBCCC", LADDW, ppc64.ASUBCCC},
+ {"SUBCV", LADDW, ppc64.ASUBCV},
+ {"SUBCVCC", LADDW, ppc64.ASUBCVCC},
+ {"SUBME", LABS, ppc64.ASUBME},
+ {"SUBMEV", LABS, ppc64.ASUBMEV},
+ {"SUBMECC", LABS, ppc64.ASUBMECC},
+ {"SUBMEVCC", LABS, ppc64.ASUBMEVCC},
+ {"SUBZE", LABS, ppc64.ASUBZE},
+ {"SUBZEV", LABS, ppc64.ASUBZEV},
+ {"SUBZECC", LABS, ppc64.ASUBZECC},
+ {"SUBZEVCC", LABS, ppc64.ASUBZEVCC},
+ {"AND", LADDW, ppc64.AAND},
+ {"ANDCC", LADDW, ppc64.AANDCC}, /* includes andil & andiu */
+ {"ANDN", LLOGW, ppc64.AANDN},
+ {"ANDNCC", LLOGW, ppc64.AANDNCC},
+ {"EQV", LLOGW, ppc64.AEQV},
+ {"EQVCC", LLOGW, ppc64.AEQVCC},
+ {"NAND", LLOGW, ppc64.ANAND},
+ {"NANDCC", LLOGW, ppc64.ANANDCC},
+ {"NOR", LLOGW, ppc64.ANOR},
+ {"NORCC", LLOGW, ppc64.ANORCC},
+ {"OR", LADDW, ppc64.AOR}, /* includes oril & oriu */
+ {"ORCC", LADDW, ppc64.AORCC},
+ {"ORN", LLOGW, ppc64.AORN},
+ {"ORNCC", LLOGW, ppc64.AORNCC},
+ {"XOR", LADDW, ppc64.AXOR}, /* includes xoril & xoriu */
+ {"XORCC", LLOGW, ppc64.AXORCC},
+ {"EXTSB", LABS, ppc64.AEXTSB},
+ {"EXTSBCC", LABS, ppc64.AEXTSBCC},
+ {"EXTSH", LABS, ppc64.AEXTSH},
+ {"EXTSHCC", LABS, ppc64.AEXTSHCC},
+ {"CNTLZW", LABS, ppc64.ACNTLZW},
+ {"CNTLZWCC", LABS, ppc64.ACNTLZWCC},
+ {"RLWMI", LRLWM, ppc64.ARLWMI},
+ {"RLWMICC", LRLWM, ppc64.ARLWMICC},
+ {"RLWNM", LRLWM, ppc64.ARLWNM},
+ {"RLWNMCC", LRLWM, ppc64.ARLWNMCC},
+ {"SLW", LSHW, ppc64.ASLW},
+ {"SLWCC", LSHW, ppc64.ASLWCC},
+ {"SRW", LSHW, ppc64.ASRW},
+ {"SRWCC", LSHW, ppc64.ASRWCC},
+ {"SRAW", LSHW, ppc64.ASRAW},
+ {"SRAWCC", LSHW, ppc64.ASRAWCC},
+ {"BR", LBRA, ppc64.ABR},
+ {"BC", LBRA, ppc64.ABC},
+ {"BCL", LBRA, ppc64.ABC},
+ {"BL", LBRA, ppc64.ABL},
+ {"BEQ", LBRA, ppc64.ABEQ},
+ {"BNE", LBRA, ppc64.ABNE},
+ {"BGT", LBRA, ppc64.ABGT},
+ {"BGE", LBRA, ppc64.ABGE},
+ {"BLT", LBRA, ppc64.ABLT},
+ {"BLE", LBRA, ppc64.ABLE},
+ {"BVC", LBRA, ppc64.ABVC},
+ {"BVS", LBRA, ppc64.ABVS},
+ {"CMP", LCMP, ppc64.ACMP},
+ {"CMPU", LCMP, ppc64.ACMPU},
+ {"CMPW", LCMP, ppc64.ACMPW},
+ {"CMPWU", LCMP, ppc64.ACMPWU},
+ {"DIVW", LLOGW, ppc64.ADIVW},
+ {"DIVWV", LLOGW, ppc64.ADIVWV},
+ {"DIVWCC", LLOGW, ppc64.ADIVWCC},
+ {"DIVWVCC", LLOGW, ppc64.ADIVWVCC},
+ {"DIVWU", LLOGW, ppc64.ADIVWU},
+ {"DIVWUV", LLOGW, ppc64.ADIVWUV},
+ {"DIVWUCC", LLOGW, ppc64.ADIVWUCC},
+ {"DIVWUVCC", LLOGW, ppc64.ADIVWUVCC},
+ {"FABS", LFCONV, ppc64.AFABS},
+ {"FABSCC", LFCONV, ppc64.AFABSCC},
+ {"FNEG", LFCONV, ppc64.AFNEG},
+ {"FNEGCC", LFCONV, ppc64.AFNEGCC},
+ {"FNABS", LFCONV, ppc64.AFNABS},
+ {"FNABSCC", LFCONV, ppc64.AFNABSCC},
+ {"FADD", LFADD, ppc64.AFADD},
+ {"FADDCC", LFADD, ppc64.AFADDCC},
+ {"FSUB", LFADD, ppc64.AFSUB},
+ {"FSUBCC", LFADD, ppc64.AFSUBCC},
+ {"FMUL", LFADD, ppc64.AFMUL},
+ {"FMULCC", LFADD, ppc64.AFMULCC},
+ {"FDIV", LFADD, ppc64.AFDIV},
+ {"FDIVCC", LFADD, ppc64.AFDIVCC},
+ {"FRSP", LFCONV, ppc64.AFRSP},
+ {"FRSPCC", LFCONV, ppc64.AFRSPCC},
+ {"FCTIW", LFCONV, ppc64.AFCTIW},
+ {"FCTIWCC", LFCONV, ppc64.AFCTIWCC},
+ {"FCTIWZ", LFCONV, ppc64.AFCTIWZ},
+ {"FCTIWZCC", LFCONV, ppc64.AFCTIWZCC},
+ {"FMADD", LFMA, ppc64.AFMADD},
+ {"FMADDCC", LFMA, ppc64.AFMADDCC},
+ {"FMSUB", LFMA, ppc64.AFMSUB},
+ {"FMSUBCC", LFMA, ppc64.AFMSUBCC},
+ {"FNMADD", LFMA, ppc64.AFNMADD},
+ {"FNMADDCC", LFMA, ppc64.AFNMADDCC},
+ {"FNMSUB", LFMA, ppc64.AFNMSUB},
+ {"FNMSUBCC", LFMA, ppc64.AFNMSUBCC},
+ {"FMADDS", LFMA, ppc64.AFMADDS},
+ {"FMADDSCC", LFMA, ppc64.AFMADDSCC},
+ {"FMSUBS", LFMA, ppc64.AFMSUBS},
+ {"FMSUBSCC", LFMA, ppc64.AFMSUBSCC},
+ {"FNMADDS", LFMA, ppc64.AFNMADDS},
+ {"FNMADDSCC", LFMA, ppc64.AFNMADDSCC},
+ {"FNMSUBS", LFMA, ppc64.AFNMSUBS},
+ {"FNMSUBSCC", LFMA, ppc64.AFNMSUBSCC},
+ {"FCMPU", LFCMP, ppc64.AFCMPU},
+ {"FCMPO", LFCMP, ppc64.AFCMPO},
+ {"MTFSB0", LMTFSB, ppc64.AMTFSB0},
+ {"MTFSB1", LMTFSB, ppc64.AMTFSB1},
+ {"FMOVD", LFMOV, ppc64.AFMOVD},
+ {"FMOVS", LFMOV, ppc64.AFMOVS},
+ {"FMOVDCC", LFCONV, ppc64.AFMOVDCC}, /* fmr. */
+ {"GLOBL", LTEXT, ppc64.AGLOBL},
+ {"MOVB", LMOVB, ppc64.AMOVB},
+ {"MOVBZ", LMOVB, ppc64.AMOVBZ},
+ {"MOVBU", LMOVB, ppc64.AMOVBU},
+ {"MOVBZU", LMOVB, ppc64.AMOVBZU},
+ {"MOVH", LMOVB, ppc64.AMOVH},
+ {"MOVHZ", LMOVB, ppc64.AMOVHZ},
+ {"MOVHU", LMOVB, ppc64.AMOVHU},
+ {"MOVHZU", LMOVB, ppc64.AMOVHZU},
+ {"MOVHBR", LXMV, ppc64.AMOVHBR},
+ {"MOVWBR", LXMV, ppc64.AMOVWBR},
+ {"MOVW", LMOVW, ppc64.AMOVW},
+ {"MOVWU", LMOVW, ppc64.AMOVWU},
+ {"MOVMW", LMOVMW, ppc64.AMOVMW},
+ {"MOVFL", LMOVW, ppc64.AMOVFL},
+ {"MULLW", LADDW, ppc64.AMULLW}, /* includes multiply immediate 10-139 */
+ {"MULLWV", LLOGW, ppc64.AMULLWV},
+ {"MULLWCC", LLOGW, ppc64.AMULLWCC},
+ {"MULLWVCC", LLOGW, ppc64.AMULLWVCC},
+ {"MULHW", LLOGW, ppc64.AMULHW},
+ {"MULHWCC", LLOGW, ppc64.AMULHWCC},
+ {"MULHWU", LLOGW, ppc64.AMULHWU},
+ {"MULHWUCC", LLOGW, ppc64.AMULHWUCC},
+ {"NEG", LABS, ppc64.ANEG},
+ {"NEGV", LABS, ppc64.ANEGV},
+ {"NEGCC", LABS, ppc64.ANEGCC},
+ {"NEGVCC", LABS, ppc64.ANEGVCC},
+ {"NOP", LNOP, ppc64.ANOP}, /* ori 0,0,0 */
+ {"SYSCALL", LNOP, ppc64.ASYSCALL},
+ {"UNDEF", LNOP, ppc64.AUNDEF},
+ {"RET", LRETRN, ppc64.ARETURN},
+ {"RETURN", LRETRN, ppc64.ARETURN},
+ {"RFI", LRETRN, ppc64.ARFI},
+ {"RFCI", LRETRN, ppc64.ARFCI},
+ {"DATA", LDATA, ppc64.ADATA},
+ {"END", LEND, ppc64.AEND},
+ {"TEXT", LTEXT, ppc64.ATEXT},
+
+ /* 64-bit instructions */
+ {"CNTLZD", LABS, ppc64.ACNTLZD},
+ {"CNTLZDCC", LABS, ppc64.ACNTLZDCC},
+ {"DIVD", LLOGW, ppc64.ADIVD},
+ {"DIVDCC", LLOGW, ppc64.ADIVDCC},
+ {"DIVDVCC", LLOGW, ppc64.ADIVDVCC},
+ {"DIVDV", LLOGW, ppc64.ADIVDV},
+ {"DIVDU", LLOGW, ppc64.ADIVDU},
+ {"DIVDUCC", LLOGW, ppc64.ADIVDUCC},
+ {"DIVDUVCC", LLOGW, ppc64.ADIVDUVCC},
+ {"DIVDUV", LLOGW, ppc64.ADIVDUV},
+ {"EXTSW", LABS, ppc64.AEXTSW},
+ {"EXTSWCC", LABS, ppc64.AEXTSWCC},
+ {"FCTID", LFCONV, ppc64.AFCTID},
+ {"FCTIDCC", LFCONV, ppc64.AFCTIDCC},
+ {"FCTIDZ", LFCONV, ppc64.AFCTIDZ},
+ {"FCTIDZCC", LFCONV, ppc64.AFCTIDZCC},
+ {"FCFID", LFCONV, ppc64.AFCFID},
+ {"FCFIDCC", LFCONV, ppc64.AFCFIDCC},
+ {"LDAR", LXLD, ppc64.ALDAR},
+ {"MOVD", LMOVW, ppc64.AMOVD},
+ {"MOVDU", LMOVW, ppc64.AMOVDU},
+ {"MOVWZ", LMOVW, ppc64.AMOVWZ},
+ {"MOVWZU", LMOVW, ppc64.AMOVWZU},
+ {"MULHD", LLOGW, ppc64.AMULHD},
+ {"MULHDCC", LLOGW, ppc64.AMULHDCC},
+ {"MULHDU", LLOGW, ppc64.AMULHDU},
+ {"MULHDUCC", LLOGW, ppc64.AMULHDUCC},
+ {"MULLD", LADDW, ppc64.AMULLD}, /* includes multiply immediate? */
+ {"MULLDCC", LLOGW, ppc64.AMULLDCC},
+ {"MULLDVCC", LLOGW, ppc64.AMULLDVCC},
+ {"MULLDV", LLOGW, ppc64.AMULLDV},
+ {"RFID", LRETRN, ppc64.ARFID},
+ {"HRFID", LRETRN, ppc64.AHRFID},
+ {"RLDMI", LRLWM, ppc64.ARLDMI},
+ {"RLDMICC", LRLWM, ppc64.ARLDMICC},
+ {"RLDC", LRLWM, ppc64.ARLDC},
+ {"RLDCCC", LRLWM, ppc64.ARLDCCC},
+ {"RLDCR", LRLWM, ppc64.ARLDCR},
+ {"RLDCRCC", LRLWM, ppc64.ARLDCRCC},
+ {"RLDCL", LRLWM, ppc64.ARLDCL},
+ {"RLDCLCC", LRLWM, ppc64.ARLDCLCC},
+ {"SLBIA", LNOP, ppc64.ASLBIA},
+ {"SLBIE", LNOP, ppc64.ASLBIE},
+ {"SLBMFEE", LABS, ppc64.ASLBMFEE},
+ {"SLBMFEV", LABS, ppc64.ASLBMFEV},
+ {"SLBMTE", LABS, ppc64.ASLBMTE},
+ {"SLD", LSHW, ppc64.ASLD},
+ {"SLDCC", LSHW, ppc64.ASLDCC},
+ {"SRD", LSHW, ppc64.ASRD},
+ {"SRAD", LSHW, ppc64.ASRAD},
+ {"SRADCC", LSHW, ppc64.ASRADCC},
+ {"SRDCC", LSHW, ppc64.ASRDCC},
+ {"STDCCC", LXST, ppc64.ASTDCCC},
+ {"TD", LADDW, ppc64.ATD},
+
+ /* pseudo instructions */
+ {"REM", LLOGW, ppc64.AREM},
+ {"REMCC", LLOGW, ppc64.AREMCC},
+ {"REMV", LLOGW, ppc64.AREMV},
+ {"REMVCC", LLOGW, ppc64.AREMVCC},
+ {"REMU", LLOGW, ppc64.AREMU},
+ {"REMUCC", LLOGW, ppc64.AREMUCC},
+ {"REMUV", LLOGW, ppc64.AREMUV},
+ {"REMUVCC", LLOGW, ppc64.AREMUVCC},
+ {"REMD", LLOGW, ppc64.AREMD},
+ {"REMDCC", LLOGW, ppc64.AREMDCC},
+ {"REMDV", LLOGW, ppc64.AREMDV},
+ {"REMDVCC", LLOGW, ppc64.AREMDVCC},
+ {"REMDU", LLOGW, ppc64.AREMDU},
+ {"REMDUCC", LLOGW, ppc64.AREMDUCC},
+ {"REMDUV", LLOGW, ppc64.AREMDUV},
+ {"REMDUVCC", LLOGW, ppc64.AREMDUVCC},
+
+ /* special instructions */
+ {"DCBF", LXOP, ppc64.ADCBF},
+ {"DCBI", LXOP, ppc64.ADCBI},
+ {"DCBST", LXOP, ppc64.ADCBST},
+ {"DCBT", LXOP, ppc64.ADCBT},
+ {"DCBTST", LXOP, ppc64.ADCBTST},
+ {"DCBZ", LXOP, ppc64.ADCBZ},
+ {"ICBI", LXOP, ppc64.AICBI},
+ {"ECIWX", LXLD, ppc64.AECIWX},
+ {"ECOWX", LXST, ppc64.AECOWX},
+ {"LWAR", LXLD, ppc64.ALWAR},
+ {"STWCCC", LXST, ppc64.ASTWCCC},
+ {"EIEIO", LRETRN, ppc64.AEIEIO},
+ {"TLBIE", LNOP, ppc64.ATLBIE},
+ {"TLBIEL", LNOP, ppc64.ATLBIEL},
+ {"LSW", LXLD, ppc64.ALSW},
+ {"STSW", LXST, ppc64.ASTSW},
+ {"ISYNC", LRETRN, ppc64.AISYNC},
+ {"SYNC", LRETRN, ppc64.ASYNC},
+ {"TLBSYNC", LRETRN, ppc64.ATLBSYNC},
+ {"PTESYNC", LRETRN, ppc64.APTESYNC},
+
+ /* "TW", LADDW, ATW,*/
+ {"WORD", LWORD, ppc64.AWORD},
+ {"DWORD", LWORD, ppc64.ADWORD},
+ {"SCHED", LSCHED, 0},
+ {"NOSCHED", LSCHED, 0x80},
+ {"PCDATA", LPCDAT, ppc64.APCDATA},
+ {"FUNCDATA", LFUNCDAT, ppc64.AFUNCDATA},
+}
+
+func cinit() {
+ nullgen.Type = ppc64.D_NONE
+ nullgen.Name = ppc64.D_NONE
+ nullgen.Reg = ppc64.NREG
+ nullgen.Scale = ppc64.NREG // replaced Gen.xreg with Prog.scale
+}
+
+func cclean() {
+ outcode(ppc64.AEND, &nullgen, ppc64.NREG, &nullgen)
+}
+
+var lastpc *obj.Prog
+var nosched int
+
+func outcode(a int, g1 *obj.Addr, reg int, g2 *obj.Addr) {
+ var p *obj.Prog
+ var pl *obj.Plist
+
+ if asm.Pass == 1 {
+ goto out
+ }
+
+ if g1.Scale != ppc64.NREG {
+ if reg != ppc64.NREG || g2.Scale != ppc64.NREG {
+ yyerror("bad addressing modes")
+ }
+ reg = int(g1.Scale)
+ } else if g2.Scale != ppc64.NREG {
+ if reg != ppc64.NREG {
+ yyerror("bad addressing modes")
+ }
+ reg = int(g2.Scale)
+ }
+
+ p = asm.Ctxt.NewProg()
+ p.As = int16(a)
+ p.Lineno = asm.Lineno
+ if nosched != 0 {
+ p.Mark |= ppc64.NOSCHED
+ }
+ p.From = *g1
+ p.Reg = uint8(reg)
+ p.To = *g2
+ p.Pc = int64(asm.PC)
+
+ if lastpc == nil {
+ pl = obj.Linknewplist(asm.Ctxt)
+ pl.Firstpc = p
+ } else {
+ lastpc.Link = p
+ }
+ lastpc = p
+
+out:
+ if a != ppc64.AGLOBL && a != ppc64.ADATA {
+ asm.PC++
+ }
+}
+
+func outgcode(a int, g1 *obj.Addr, reg int, g2, g3 *obj.Addr) {
+ var p *obj.Prog
+ var pl *obj.Plist
+
+ if asm.Pass == 1 {
+ goto out
+ }
+
+ p = asm.Ctxt.NewProg()
+ p.As = int16(a)
+ p.Lineno = asm.Lineno
+ if nosched != 0 {
+ p.Mark |= ppc64.NOSCHED
+ }
+ p.From = *g1
+ p.Reg = uint8(reg)
+ p.From3 = *g2
+ p.To = *g3
+ p.Pc = int64(asm.PC)
+
+ if lastpc == nil {
+ pl = obj.Linknewplist(asm.Ctxt)
+ pl.Firstpc = p
+ } else {
+ lastpc.Link = p
+ }
+ lastpc = p
+
+out:
+ if a != ppc64.AGLOBL && a != ppc64.ADATA {
+ asm.PC++
+ }
+}
--- /dev/null
+//line a.y:31
+package main
+
+import __yyfmt__ "fmt"
+
+//line a.y:31
+import (
+ "cmd/internal/asm"
+ "cmd/internal/obj"
+ . "cmd/internal/obj/ppc64"
+)
+
+//line a.y:40
+type yySymType struct {
+ yys int
+ sym *asm.Sym
+ lval int64
+ dval float64
+ sval string
+ addr obj.Addr
+}
+
+const LMOVW = 57346
+const LMOVB = 57347
+const LABS = 57348
+const LLOGW = 57349
+const LSHW = 57350
+const LADDW = 57351
+const LCMP = 57352
+const LCROP = 57353
+const LBRA = 57354
+const LFMOV = 57355
+const LFCONV = 57356
+const LFCMP = 57357
+const LFADD = 57358
+const LFMA = 57359
+const LTRAP = 57360
+const LXORW = 57361
+const LNOP = 57362
+const LEND = 57363
+const LRETT = 57364
+const LWORD = 57365
+const LTEXT = 57366
+const LDATA = 57367
+const LRETRN = 57368
+const LCONST = 57369
+const LSP = 57370
+const LSB = 57371
+const LFP = 57372
+const LPC = 57373
+const LCREG = 57374
+const LFLUSH = 57375
+const LREG = 57376
+const LFREG = 57377
+const LR = 57378
+const LCR = 57379
+const LF = 57380
+const LFPSCR = 57381
+const LLR = 57382
+const LCTR = 57383
+const LSPR = 57384
+const LSPREG = 57385
+const LSEG = 57386
+const LMSR = 57387
+const LPCDAT = 57388
+const LFUNCDAT = 57389
+const LSCHED = 57390
+const LXLD = 57391
+const LXST = 57392
+const LXOP = 57393
+const LXMV = 57394
+const LRLWM = 57395
+const LMOVMW = 57396
+const LMOVEM = 57397
+const LMOVFL = 57398
+const LMTFSB = 57399
+const LMA = 57400
+const LFCONST = 57401
+const LSCONST = 57402
+const LNAME = 57403
+const LLAB = 57404
+const LVAR = 57405
+
+var yyToknames = []string{
+ "'|'",
+ "'^'",
+ "'&'",
+ "'<'",
+ "'>'",
+ "'+'",
+ "'-'",
+ "'*'",
+ "'/'",
+ "'%'",
+ "LMOVW",
+ "LMOVB",
+ "LABS",
+ "LLOGW",
+ "LSHW",
+ "LADDW",
+ "LCMP",
+ "LCROP",
+ "LBRA",
+ "LFMOV",
+ "LFCONV",
+ "LFCMP",
+ "LFADD",
+ "LFMA",
+ "LTRAP",
+ "LXORW",
+ "LNOP",
+ "LEND",
+ "LRETT",
+ "LWORD",
+ "LTEXT",
+ "LDATA",
+ "LRETRN",
+ "LCONST",
+ "LSP",
+ "LSB",
+ "LFP",
+ "LPC",
+ "LCREG",
+ "LFLUSH",
+ "LREG",
+ "LFREG",
+ "LR",
+ "LCR",
+ "LF",
+ "LFPSCR",
+ "LLR",
+ "LCTR",
+ "LSPR",
+ "LSPREG",
+ "LSEG",
+ "LMSR",
+ "LPCDAT",
+ "LFUNCDAT",
+ "LSCHED",
+ "LXLD",
+ "LXST",
+ "LXOP",
+ "LXMV",
+ "LRLWM",
+ "LMOVMW",
+ "LMOVEM",
+ "LMOVFL",
+ "LMTFSB",
+ "LMA",
+ "LFCONST",
+ "LSCONST",
+ "LNAME",
+ "LLAB",
+ "LVAR",
+}
+var yyStatenames = []string{}
+
+const yyEofCode = 1
+const yyErrCode = 2
+const yyMaxDepth = 200
+
+//line yacctab:1
+var yyExca = []int{
+ -1, 1,
+ 1, -1,
+ -2, 0,
+}
+
+const yyNprod = 183
+const yyPrivate = 57344
+
+var yyTokenNames []string
+var yyStates []string
+
+const yyLast = 885
+
+var yyAct = []int{
+
+ 46, 52, 88, 421, 100, 431, 103, 169, 2, 92,
+ 64, 83, 56, 276, 93, 95, 96, 98, 99, 50,
+ 54, 111, 49, 271, 55, 444, 119, 121, 123, 443,
+ 126, 128, 432, 131, 89, 136, 72, 411, 73, 78,
+ 77, 125, 125, 92, 115, 116, 117, 118, 410, 72,
+ 61, 73, 72, 62, 73, 132, 400, 51, 161, 399,
+ 78, 442, 381, 380, 202, 440, 377, 75, 366, 53,
+ 91, 94, 92, 97, 365, 364, 78, 77, 112, 363,
+ 81, 82, 133, 275, 120, 92, 125, 146, 75, 107,
+ 134, 135, 137, 138, 72, 361, 73, 59, 59, 59,
+ 145, 147, 360, 76, 75, 314, 101, 108, 102, 65,
+ 401, 79, 359, 196, 110, 59, 282, 203, 195, 202,
+ 183, 164, 74, 159, 76, 141, 141, 114, 45, 102,
+ 92, 48, 79, 229, 222, 201, 202, 166, 109, 168,
+ 76, 167, 85, 87, 106, 105, 162, 439, 79, 244,
+ 252, 253, 165, 231, 261, 263, 223, 267, 268, 269,
+ 124, 250, 127, 129, 438, 173, 174, 175, 437, 251,
+ 436, 256, 435, 249, 392, 258, 265, 286, 289, 290,
+ 186, 391, 390, 389, 388, 387, 386, 385, 301, 303,
+ 305, 307, 309, 310, 199, 384, 383, 382, 376, 312,
+ 375, 374, 291, 292, 293, 294, 247, 316, 319, 257,
+ 373, 315, 330, 332, 333, 334, 372, 336, 248, 340,
+ 371, 370, 259, 369, 358, 264, 266, 357, 228, 227,
+ 326, 327, 328, 329, 226, 114, 59, 219, 218, 59,
+ 217, 216, 215, 214, 213, 300, 212, 211, 210, 209,
+ 278, 163, 208, 207, 279, 280, 281, 206, 204, 284,
+ 285, 47, 84, 86, 59, 200, 194, 193, 192, 331,
+ 59, 104, 191, 298, 337, 339, 78, 77, 190, 122,
+ 246, 189, 313, 255, 342, 188, 344, 113, 199, 322,
+ 187, 368, 347, 348, 349, 350, 351, 185, 182, 354,
+ 355, 356, 181, 59, 75, 57, 367, 180, 288, 179,
+ 178, 72, 177, 73, 296, 59, 345, 176, 346, 158,
+ 130, 157, 156, 155, 139, 154, 153, 143, 152, 78,
+ 77, 378, 151, 150, 379, 149, 148, 44, 74, 43,
+ 76, 42, 40, 41, 297, 60, 63, 396, 79, 338,
+ 72, 341, 73, 61, 184, 262, 62, 75, 197, 65,
+ 433, 78, 77, 230, 110, 61, 160, 72, 62, 73,
+ 402, 403, 404, 405, 406, 407, 408, 441, 397, 353,
+ 65, 409, 395, 61, 283, 110, 62, 412, 352, 75,
+ 425, 74, 424, 76, 429, 430, 171, 172, 60, 205,
+ 245, 79, 7, 254, 144, 415, 416, 1, 78, 77,
+ 69, 393, 394, 183, 72, 61, 73, 260, 62, 220,
+ 221, 297, 71, 224, 225, 76, 70, 434, 287, 0,
+ 102, 160, 0, 79, 295, 58, 75, 446, 447, 0,
+ 449, 450, 78, 77, 0, 420, 423, 398, 0, 427,
+ 428, 0, 317, 320, 417, 418, 419, 65, 445, 72,
+ 0, 73, 110, 0, 101, 270, 0, 335, 199, 0,
+ 75, 0, 76, 140, 142, 422, 422, 102, 61, 343,
+ 79, 62, 0, 242, 241, 240, 238, 239, 233, 234,
+ 235, 236, 237, 299, 302, 304, 306, 308, 0, 311,
+ 0, 273, 272, 274, 74, 0, 76, 72, 270, 73,
+ 324, 60, 325, 90, 79, 273, 272, 274, 170, 165,
+ 171, 172, 426, 65, 0, 0, 448, 0, 110, 451,
+ 173, 8, 0, 68, 67, 0, 80, 233, 234, 235,
+ 236, 237, 0, 9, 10, 16, 14, 15, 13, 25,
+ 18, 19, 11, 21, 24, 22, 23, 20, 277, 32,
+ 36, 0, 33, 37, 38, 39, 0, 78, 77, 0,
+ 0, 78, 77, 273, 272, 274, 323, 0, 0, 72,
+ 0, 73, 362, 0, 0, 34, 35, 5, 28, 29,
+ 31, 30, 26, 27, 0, 75, 12, 17, 0, 75,
+ 3, 0, 4, 0, 65, 6, 72, 61, 73, 66,
+ 62, 63, 81, 82, 68, 67, 0, 80, 78, 77,
+ 241, 240, 238, 239, 233, 234, 235, 236, 237, 78,
+ 77, 76, 413, 74, 0, 76, 102, 0, 92, 79,
+ 60, 0, 64, 79, 78, 77, 75, 0, 78, 77,
+ 0, 65, 0, 72, 0, 73, 66, 75, 0, 81,
+ 82, 68, 67, 0, 80, 0, 0, 78, 77, 63,
+ 0, 0, 75, 235, 236, 237, 75, 0, 0, 72,
+ 74, 73, 76, 78, 77, 0, 0, 60, 0, 92,
+ 79, 74, 0, 76, 0, 75, 78, 77, 60, 0,
+ 92, 79, 72, 0, 73, 0, 74, 0, 76, 164,
+ 74, 75, 76, 102, 78, 77, 79, 102, 78, 77,
+ 79, 0, 0, 0, 75, 0, 0, 0, 0, 78,
+ 77, 76, 0, 0, 0, 0, 102, 0, 0, 79,
+ 0, 0, 75, 0, 0, 109, 75, 76, 0, 0,
+ 0, 0, 414, 0, 0, 79, 0, 75, 74, 0,
+ 76, 0, 0, 0, 0, 102, 0, 0, 79, 238,
+ 239, 233, 234, 235, 236, 237, 109, 0, 76, 0,
+ 109, 0, 76, 321, 0, 0, 79, 318, 0, 0,
+ 79, 109, 0, 76, 0, 0, 0, 0, 198, 0,
+ 0, 79, 242, 241, 240, 238, 239, 233, 234, 235,
+ 236, 237, 242, 241, 240, 238, 239, 233, 234, 235,
+ 236, 237, 240, 238, 239, 233, 234, 235, 236, 237,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 243, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 232,
+}
+var yyPact = []int{
+
+ -1000, 529, -1000, 268, 266, 263, -1000, 261, 52, 562,
+ 267, 433, -71, -8, 323, -8, 323, 323, 399, 67,
+ 50, 308, 308, 308, 308, 323, -8, 635, -36, 323,
+ 8, -36, 5, -70, -71, -71, 158, 687, 687, 158,
+ -1000, 399, 399, -1000, -1000, -1000, 259, 258, 256, 255,
+ 251, 249, 248, 246, 245, 244, 242, -1000, -1000, 45,
+ 658, -1000, 68, -1000, 639, -1000, 59, -1000, 63, -1000,
+ -1000, -1000, -1000, 61, 511, -1000, -1000, 399, 399, 399,
+ -1000, -1000, -1000, 240, 235, 233, 232, 230, 225, 221,
+ 344, 220, 399, 213, 208, 204, 201, 195, 191, 190,
+ 189, -1000, 399, -1000, -1000, 30, 720, 188, 58, 511,
+ 59, 181, 180, -1000, -1000, 176, 175, 172, 171, 170,
+ 169, 167, 166, 165, 164, 323, 163, 161, 160, -1000,
+ -1000, 158, 158, 370, -1000, 158, 158, 157, 152, -1000,
+ 151, 55, 351, -1000, 529, 808, -1000, 798, 609, 323,
+ 323, 620, 338, 306, 323, 481, 415, 323, 323, 463,
+ 4, 479, 399, -1000, -1000, 45, 399, 399, 399, 38,
+ 376, 399, 399, -1000, -1000, -1000, 267, 323, 323, 308,
+ 308, 308, 320, -1000, 275, 399, -1000, -8, 323, 323,
+ 323, 323, 323, 323, 399, 26, -1000, -1000, 30, 41,
+ 709, 705, 535, 38, 323, -1000, 323, 308, 308, 308,
+ 308, -8, 323, 323, 323, 687, -8, -37, 323, -36,
+ -1000, -1000, -1000, -1000, -1000, -1000, -71, 687, 558, 477,
+ 399, -1000, -1000, 399, 399, 399, 399, 399, 381, 371,
+ 399, 399, 399, -1000, -1000, -1000, -1000, 150, -1000, -1000,
+ -1000, -1000, -1000, -1000, -1000, -1000, -1000, 147, -1000, -1000,
+ -1000, -1000, 34, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
+ 23, 16, -1000, -1000, -1000, -1000, 323, -1000, 0, -4,
+ -5, -11, 477, 387, -1000, -1000, -1000, -1000, -1000, -1000,
+ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 146,
+ 144, -1000, 143, -1000, 139, -1000, 133, -1000, 124, -1000,
+ -1000, 123, -1000, 121, -1000, -13, -1000, -1000, 30, -1000,
+ -1000, 30, -14, -17, -1000, -1000, -1000, 120, 119, 118,
+ 110, 109, 108, 107, -1000, -1000, -1000, 106, -1000, 105,
+ -1000, -1000, -1000, -1000, -1000, 104, 97, 662, 662, -1000,
+ -1000, -1000, 399, 399, 762, 816, 615, 300, 297, 399,
+ -1000, -1000, -20, -1000, -1000, -1000, -1000, -23, 32, 323,
+ 323, 323, 323, 323, 323, 323, 399, -1000, -31, -42,
+ 674, -1000, 308, 308, 317, 317, 317, 558, 558, 323,
+ -36, -71, -75, 528, 528, -1000, -1000, -1000, -47, -1000,
+ -1000, 321, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
+ -1000, -1000, -1000, -1000, 30, -1000, 95, -1000, -1000, -1000,
+ 93, 91, 87, 70, -12, -1000, -1000, 367, -1000, -1000,
+ -1000, 51, -1000, -50, -54, 308, 323, 323, 399, 323,
+ 323, 399, 352, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
+ -1000, -1000,
+}
+var yyPgo = []int{
+
+ 0, 87, 58, 23, 7, 305, 251, 0, 131, 435,
+ 69, 22, 12, 426, 422, 57, 1, 2, 6, 20,
+ 24, 4, 19, 417, 410, 3, 407, 8, 404, 402,
+ 287,
+}
+var yyR1 = []int{
+
+ 0, 26, 26, 28, 27, 27, 27, 27, 27, 27,
+ 27, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 18, 18, 7, 12, 12, 13,
+ 20, 14, 24, 19, 19, 19, 22, 23, 11, 11,
+ 10, 10, 21, 25, 16, 16, 17, 17, 15, 5,
+ 5, 8, 8, 6, 6, 9, 9, 9, 30, 30,
+ 4, 4, 4, 3, 3, 3, 1, 1, 1, 1,
+ 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2,
+}
+var yyR2 = []int{
+
+ 0, 0, 2, 0, 4, 4, 4, 2, 1, 2,
+ 2, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 6, 4, 4, 4, 6, 4, 4, 6, 6,
+ 6, 4, 4, 6, 4, 6, 4, 6, 4, 4,
+ 2, 6, 4, 4, 4, 6, 4, 4, 4, 4,
+ 4, 4, 4, 4, 2, 2, 4, 3, 3, 5,
+ 4, 4, 6, 4, 4, 6, 6, 6, 8, 4,
+ 4, 3, 2, 4, 4, 6, 8, 4, 6, 4,
+ 4, 6, 6, 8, 8, 8, 8, 4, 4, 4,
+ 6, 4, 6, 4, 4, 2, 2, 3, 3, 3,
+ 3, 2, 3, 3, 4, 4, 2, 4, 6, 8,
+ 6, 6, 6, 2, 4, 2, 1, 1, 1, 1,
+ 1, 1, 1, 1, 4, 1, 1, 4, 1, 4,
+ 1, 4, 1, 3, 2, 2, 2, 3, 2, 1,
+ 4, 3, 5, 1, 4, 4, 5, 7, 0, 1,
+ 0, 2, 2, 1, 1, 1, 1, 1, 2, 2,
+ 2, 3, 1, 3, 3, 3, 3, 3, 4, 4,
+ 3, 3, 3,
+}
+var yyChk = []int{
+
+ -1000, -26, -27, 71, 73, 58, 76, -29, 2, 14,
+ 15, 23, 67, 19, 17, 18, 16, 68, 21, 22,
+ 28, 24, 26, 27, 25, 20, 63, 64, 59, 60,
+ 62, 61, 30, 33, 56, 57, 31, 34, 35, 36,
+ 74, 75, 75, 76, 76, 76, -7, -6, -8, -11,
+ -22, -15, -16, -10, -19, -20, -12, -5, -9, -1,
+ 78, 45, 48, 49, 80, 42, 47, 53, 52, -24,
+ -13, -14, 44, 46, 71, 37, 73, 10, 9, 81,
+ 55, 50, 51, -7, -6, -8, -6, -8, -17, -11,
+ 80, -15, 80, -7, -15, -7, -7, -15, -7, -7,
+ -21, -1, 78, -18, -6, 78, 77, -10, -1, 71,
+ 47, -7, -15, -30, 77, -11, -11, -11, -11, -7,
+ -15, -7, -6, -7, -8, 78, -7, -8, -7, -8,
+ -30, -7, -11, 77, -15, -15, -16, -15, -15, -30,
+ -9, -1, -9, -30, -28, -2, -1, -2, 77, 77,
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 78,
+ -5, -2, 78, -6, 70, -1, 78, 78, 78, -4,
+ 7, 9, 10, -1, -1, -1, 77, 77, 77, 77,
+ 77, 77, 77, 69, 10, 77, -1, 77, 77, 77,
+ 77, 77, 77, 77, 77, -12, -18, -6, 78, -1,
+ 77, 77, 78, -4, 77, -30, 77, 77, 77, 77,
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+ -30, -30, -7, -11, -30, -30, 77, 77, 77, 78,
+ 12, -27, 76, 9, 10, 11, 12, 13, 7, 8,
+ 6, 5, 4, 76, -7, -6, -8, -15, -10, -20,
+ -12, -19, -7, -7, -6, -8, -22, -15, -11, -10,
+ -23, -7, 49, -7, -10, -19, -10, -7, -7, -7,
+ -5, -3, 39, 38, 40, 79, 9, 79, -1, -1,
+ -1, -1, 78, 8, -1, -1, -7, -6, -8, -7,
+ -7, -11, -11, -11, -11, -6, -8, 69, -1, -5,
+ -15, -7, -5, -7, -5, -7, -5, -7, -5, -7,
+ -7, -5, -21, -1, 79, -12, -18, -6, 78, -18,
+ -6, 78, -1, 41, -5, -5, -11, -11, -11, -11,
+ -7, -15, -7, -7, -7, -6, -7, -15, -8, -15,
+ -7, -8, -15, -6, -15, -1, -1, -2, -2, -2,
+ -2, -2, 7, 8, -2, -2, -2, 77, 77, 78,
+ 79, 79, -5, 79, 79, 79, 79, -3, -4, 77,
+ 77, 77, 77, 77, 77, 77, 77, 79, -12, -12,
+ 77, 79, 77, 77, 77, 77, 77, 77, 77, 77,
+ 77, 77, 77, -2, -2, -20, 47, -22, -1, 79,
+ 79, 78, -7, -7, -7, -7, -7, -7, -7, -21,
+ 79, 79, -18, -6, 78, -11, -11, -10, -10, -10,
+ -15, -25, -1, -15, -25, -7, -8, -15, -15, -16,
+ -17, 80, 79, 39, -12, 77, 77, 77, 77, 77,
+ 77, 10, 10, 79, 79, -11, -7, -7, -1, -7,
+ -7, -1,
+}
+var yyDef = []int{
+
+ 1, -2, 2, 0, 0, 0, 8, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 158, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 158, 0, 0, 0, 158, 0, 0, 158,
+ 3, 0, 0, 7, 9, 10, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 126, 153, 0,
+ 0, 138, 0, 136, 0, 140, 130, 133, 0, 135,
+ 127, 128, 149, 0, 160, 166, 167, 0, 0, 0,
+ 132, 129, 131, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 50, 0,
+ 0, 142, 0, 64, 65, 0, 0, 0, 0, 160,
+ 0, 158, 0, 82, 159, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 105,
+ 106, 158, 158, 159, 111, 158, 158, 0, 0, 116,
+ 0, 0, 0, 123, 0, 0, 172, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 144, 145, 148, 0, 0, 0, 0,
+ 0, 0, 0, 168, 169, 170, 0, 0, 0, 0,
+ 0, 0, 0, 146, 0, 0, 148, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 67, 68, 0, 0,
+ 0, 0, 0, 125, 159, 81, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 107, 108, 109, 110, 112, 113, 0, 0, 0, 0,
+ 0, 4, 5, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 6, 11, 23, 24, 0, 36, 37,
+ 61, 63, 12, 13, 27, 28, 30, 0, 29, 32,
+ 33, 52, 0, 53, 56, 62, 57, 59, 58, 60,
+ 0, 0, 163, 164, 165, 151, 0, 171, 0, 0,
+ 0, 0, 0, 160, 161, 162, 14, 25, 26, 15,
+ 16, 17, 18, 19, 20, 21, 22, 147, 34, 126,
+ 0, 41, 126, 42, 126, 44, 126, 46, 126, 48,
+ 49, 0, 54, 142, 66, 0, 70, 71, 0, 73,
+ 74, 0, 0, 0, 79, 80, 83, 84, 0, 87,
+ 89, 90, 0, 0, 97, 98, 99, 0, 101, 0,
+ 103, 104, 114, 115, 117, 0, 0, 173, 174, 175,
+ 176, 177, 0, 0, 180, 181, 182, 0, 0, 0,
+ 154, 155, 0, 139, 141, 134, 150, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 69, 0, 0,
+ 0, 124, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 178, 179, 35, 130, 31, 0, 152,
+ 156, 0, 38, 40, 39, 43, 45, 47, 51, 55,
+ 72, 75, 76, 77, 0, 85, 0, 88, 91, 92,
+ 0, 0, 0, 0, 0, 100, 102, 118, 120, 121,
+ 122, 0, 137, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 157, 78, 86, 93, 94, 143, 95,
+ 96, 119,
+}
+var yyTok1 = []int{
+
+ 1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 80, 13, 6, 3,
+ 78, 79, 11, 9, 77, 10, 3, 12, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 74, 76,
+ 7, 75, 8, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 5, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 4, 3, 81,
+}
+var yyTok2 = []int{
+
+ 2, 3, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73,
+}
+var yyTok3 = []int{
+ 0,
+}
+
+//line yaccpar:1
+
+/* parser for yacc output */
+
+var yyDebug = 0
+
+type yyLexer interface {
+ Lex(lval *yySymType) int
+ Error(s string)
+}
+
+const yyFlag = -1000
+
+func yyTokname(c int) string {
+ // 4 is TOKSTART above
+ if c >= 4 && c-4 < len(yyToknames) {
+ if yyToknames[c-4] != "" {
+ return yyToknames[c-4]
+ }
+ }
+ return __yyfmt__.Sprintf("tok-%v", c)
+}
+
+func yyStatname(s int) string {
+ if s >= 0 && s < len(yyStatenames) {
+ if yyStatenames[s] != "" {
+ return yyStatenames[s]
+ }
+ }
+ return __yyfmt__.Sprintf("state-%v", s)
+}
+
+func yylex1(lex yyLexer, lval *yySymType) int {
+ c := 0
+ char := lex.Lex(lval)
+ if char <= 0 {
+ c = yyTok1[0]
+ goto out
+ }
+ if char < len(yyTok1) {
+ c = yyTok1[char]
+ goto out
+ }
+ if char >= yyPrivate {
+ if char < yyPrivate+len(yyTok2) {
+ c = yyTok2[char-yyPrivate]
+ goto out
+ }
+ }
+ for i := 0; i < len(yyTok3); i += 2 {
+ c = yyTok3[i+0]
+ if c == char {
+ c = yyTok3[i+1]
+ goto out
+ }
+ }
+
+out:
+ if c == 0 {
+ c = yyTok2[1] /* unknown char */
+ }
+ if yyDebug >= 3 {
+ __yyfmt__.Printf("lex %s(%d)\n", yyTokname(c), uint(char))
+ }
+ return c
+}
+
+func yyParse(yylex yyLexer) int {
+ var yyn int
+ var yylval yySymType
+ var yyVAL yySymType
+ yyS := make([]yySymType, yyMaxDepth)
+
+ Nerrs := 0 /* number of errors */
+ Errflag := 0 /* error recovery flag */
+ yystate := 0
+ yychar := -1
+ yyp := -1
+ goto yystack
+
+ret0:
+ return 0
+
+ret1:
+ return 1
+
+yystack:
+ /* put a state and value onto the stack */
+ if yyDebug >= 4 {
+ __yyfmt__.Printf("char %v in %v\n", yyTokname(yychar), yyStatname(yystate))
+ }
+
+ yyp++
+ if yyp >= len(yyS) {
+ nyys := make([]yySymType, len(yyS)*2)
+ copy(nyys, yyS)
+ yyS = nyys
+ }
+ yyS[yyp] = yyVAL
+ yyS[yyp].yys = yystate
+
+yynewstate:
+ yyn = yyPact[yystate]
+ if yyn <= yyFlag {
+ goto yydefault /* simple state */
+ }
+ if yychar < 0 {
+ yychar = yylex1(yylex, &yylval)
+ }
+ yyn += yychar
+ if yyn < 0 || yyn >= yyLast {
+ goto yydefault
+ }
+ yyn = yyAct[yyn]
+ if yyChk[yyn] == yychar { /* valid shift */
+ yychar = -1
+ yyVAL = yylval
+ yystate = yyn
+ if Errflag > 0 {
+ Errflag--
+ }
+ goto yystack
+ }
+
+yydefault:
+ /* default state action */
+ yyn = yyDef[yystate]
+ if yyn == -2 {
+ if yychar < 0 {
+ yychar = yylex1(yylex, &yylval)
+ }
+
+ /* look through exception table */
+ xi := 0
+ for {
+ if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate {
+ break
+ }
+ xi += 2
+ }
+ for xi += 2; ; xi += 2 {
+ yyn = yyExca[xi+0]
+ if yyn < 0 || yyn == yychar {
+ break
+ }
+ }
+ yyn = yyExca[xi+1]
+ if yyn < 0 {
+ goto ret0
+ }
+ }
+ if yyn == 0 {
+ /* error ... attempt to resume parsing */
+ switch Errflag {
+ case 0: /* brand new error */
+ yylex.Error("syntax error")
+ Nerrs++
+ if yyDebug >= 1 {
+ __yyfmt__.Printf("%s", yyStatname(yystate))
+ __yyfmt__.Printf(" saw %s\n", yyTokname(yychar))
+ }
+ fallthrough
+
+ case 1, 2: /* incompletely recovered error ... try again */
+ Errflag = 3
+
+ /* find a state where "error" is a legal shift action */
+ for yyp >= 0 {
+ yyn = yyPact[yyS[yyp].yys] + yyErrCode
+ if yyn >= 0 && yyn < yyLast {
+ yystate = yyAct[yyn] /* simulate a shift of "error" */
+ if yyChk[yystate] == yyErrCode {
+ goto yystack
+ }
+ }
+
+ /* the current p has no shift on "error", pop stack */
+ if yyDebug >= 2 {
+ __yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys)
+ }
+ yyp--
+ }
+ /* there is no state on the stack with an error shift ... abort */
+ goto ret1
+
+ case 3: /* no shift yet; clobber input char */
+ if yyDebug >= 2 {
+ __yyfmt__.Printf("error recovery discards %s\n", yyTokname(yychar))
+ }
+ if yychar == yyEofCode {
+ goto ret1
+ }
+ yychar = -1
+ goto yynewstate /* try again in the same state */
+ }
+ }
+
+ /* reduction by production yyn */
+ if yyDebug >= 2 {
+ __yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate))
+ }
+
+ yynt := yyn
+ yypt := yyp
+ _ = yypt // guard against "declared and not used"
+
+ yyp -= yyR2[yyn]
+ // yyp is now the index of $0. Perform the default action. Iff the
+ // reduced production is ε, $1 is possibly out of range.
+ if yyp+1 >= len(yyS) {
+ nyys := make([]yySymType, len(yyS)*2)
+ copy(nyys, yyS)
+ yyS = nyys
+ }
+ yyVAL = yyS[yyp+1]
+
+ /* consult goto table to find next state */
+ yyn = yyR1[yyn]
+ yyg := yyPgo[yyn]
+ yyj := yyg + yyS[yyp].yys + 1
+
+ if yyj >= yyLast {
+ yystate = yyAct[yyg]
+ } else {
+ yystate = yyAct[yyj]
+ if yyChk[yystate] != -yyn {
+ yystate = yyAct[yyg]
+ }
+ }
+ // dummy call; replaced with literal code
+ switch yynt {
+
+ case 3:
+ //line a.y:75
+ {
+ yyS[yypt-1].sym = asm.LabelLookup(yyS[yypt-1].sym)
+ if yyS[yypt-1].sym.Type == LLAB && yyS[yypt-1].sym.Value != int64(asm.PC) {
+ yyerror("redeclaration of %s", yyS[yypt-1].sym.Labelname)
+ }
+ yyS[yypt-1].sym.Type = LLAB
+ yyS[yypt-1].sym.Value = int64(asm.PC)
+ }
+ case 5:
+ //line a.y:85
+ {
+ yyS[yypt-3].sym.Type = LVAR
+ yyS[yypt-3].sym.Value = yyS[yypt-1].lval
+ }
+ case 6:
+ //line a.y:90
+ {
+ if yyS[yypt-3].sym.Value != yyS[yypt-1].lval {
+ yyerror("redeclaration of %s", yyS[yypt-3].sym.Name)
+ }
+ yyS[yypt-3].sym.Value = yyS[yypt-1].lval
+ }
+ case 7:
+ //line a.y:97
+ {
+ nosched = int(yyS[yypt-1].lval)
+ }
+ case 11:
+ //line a.y:109
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 12:
+ //line a.y:113
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 13:
+ //line a.y:117
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 14:
+ //line a.y:121
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 15:
+ //line a.y:125
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 16:
+ //line a.y:129
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 17:
+ //line a.y:136
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 18:
+ //line a.y:140
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 19:
+ //line a.y:144
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 20:
+ //line a.y:148
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 21:
+ //line a.y:152
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 22:
+ //line a.y:156
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 23:
+ //line a.y:163
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 24:
+ //line a.y:167
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 25:
+ //line a.y:171
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 26:
+ //line a.y:175
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 27:
+ //line a.y:182
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 28:
+ //line a.y:186
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 29:
+ //line a.y:193
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 30:
+ //line a.y:197
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 31:
+ //line a.y:201
+ {
+ outgcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, NREG, &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+ }
+ case 32:
+ //line a.y:205
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 33:
+ //line a.y:209
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 34:
+ //line a.y:213
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, int(yyS[yypt-0].lval), &nullgen)
+ }
+ case 35:
+ //line a.y:220
+ {
+ outgcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, NREG, &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+ }
+ case 36:
+ //line a.y:224
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 37:
+ //line a.y:228
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 38:
+ //line a.y:238
+ {
+ outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+ }
+ case 39:
+ //line a.y:242
+ {
+ outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+ }
+ case 40:
+ //line a.y:246
+ {
+ outgcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, NREG, &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+ }
+ case 41:
+ //line a.y:250
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 42:
+ //line a.y:254
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 43:
+ //line a.y:258
+ {
+ outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+ }
+ case 44:
+ //line a.y:262
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 45:
+ //line a.y:266
+ {
+ outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+ }
+ case 46:
+ //line a.y:270
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 47:
+ //line a.y:274
+ {
+ outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+ }
+ case 48:
+ //line a.y:278
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 49:
+ //line a.y:282
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 50:
+ //line a.y:286
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 51:
+ //line a.y:293
+ {
+ outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+ }
+ case 52:
+ //line a.y:300
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 53:
+ //line a.y:304
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 54:
+ //line a.y:311
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, int(yyS[yypt-0].addr.Reg), &yyS[yypt-0].addr)
+ }
+ case 55:
+ //line a.y:315
+ {
+ outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+ }
+ case 56:
+ //line a.y:323
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 57:
+ //line a.y:327
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 58:
+ //line a.y:331
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 59:
+ //line a.y:335
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 60:
+ //line a.y:339
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 61:
+ //line a.y:343
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 62:
+ //line a.y:347
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 63:
+ //line a.y:351
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 64:
+ //line a.y:360
+ {
+ outcode(int(yyS[yypt-1].lval), &nullgen, NREG, &yyS[yypt-0].addr)
+ }
+ case 65:
+ //line a.y:364
+ {
+ outcode(int(yyS[yypt-1].lval), &nullgen, NREG, &yyS[yypt-0].addr)
+ }
+ case 66:
+ //line a.y:368
+ {
+ outcode(int(yyS[yypt-3].lval), &nullgen, NREG, &yyS[yypt-1].addr)
+ }
+ case 67:
+ //line a.y:372
+ {
+ outcode(int(yyS[yypt-2].lval), &nullgen, NREG, &yyS[yypt-0].addr)
+ }
+ case 68:
+ //line a.y:376
+ {
+ outcode(int(yyS[yypt-2].lval), &nullgen, NREG, &yyS[yypt-0].addr)
+ }
+ case 69:
+ //line a.y:380
+ {
+ outcode(int(yyS[yypt-4].lval), &nullgen, NREG, &yyS[yypt-1].addr)
+ }
+ case 70:
+ //line a.y:384
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 71:
+ //line a.y:388
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 72:
+ //line a.y:392
+ {
+ outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, NREG, &yyS[yypt-1].addr)
+ }
+ case 73:
+ //line a.y:396
+ {
+ outcode(int(yyS[yypt-3].lval), &nullgen, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+ }
+ case 74:
+ //line a.y:400
+ {
+ outcode(int(yyS[yypt-3].lval), &nullgen, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+ }
+ case 75:
+ //line a.y:404
+ {
+ outcode(int(yyS[yypt-5].lval), &nullgen, int(yyS[yypt-4].lval), &yyS[yypt-1].addr)
+ }
+ case 76:
+ //line a.y:408
+ {
+ var g obj.Addr
+ g = nullgen
+ g.Type = D_CONST
+ g.Offset = yyS[yypt-4].lval
+ outcode(int(yyS[yypt-5].lval), &g, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+ }
+ case 77:
+ //line a.y:416
+ {
+ var g obj.Addr
+ g = nullgen
+ g.Type = D_CONST
+ g.Offset = yyS[yypt-4].lval
+ outcode(int(yyS[yypt-5].lval), &g, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+ }
+ case 78:
+ //line a.y:424
+ {
+ var g obj.Addr
+ g = nullgen
+ g.Type = D_CONST
+ g.Offset = yyS[yypt-6].lval
+ outcode(int(yyS[yypt-7].lval), &g, int(yyS[yypt-4].lval), &yyS[yypt-1].addr)
+ }
+ case 79:
+ //line a.y:435
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, int(yyS[yypt-0].lval), &nullgen)
+ }
+ case 80:
+ //line a.y:439
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, int(yyS[yypt-0].lval), &nullgen)
+ }
+ case 81:
+ //line a.y:443
+ {
+ outcode(int(yyS[yypt-2].lval), &yyS[yypt-1].addr, NREG, &nullgen)
+ }
+ case 82:
+ //line a.y:447
+ {
+ outcode(int(yyS[yypt-1].lval), &nullgen, NREG, &nullgen)
+ }
+ case 83:
+ //line a.y:454
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 84:
+ //line a.y:458
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 85:
+ //line a.y:462
+ {
+ outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].addr.Reg), &yyS[yypt-0].addr)
+ }
+ case 86:
+ //line a.y:466
+ {
+ outgcode(int(yyS[yypt-7].lval), &yyS[yypt-6].addr, int(yyS[yypt-4].addr.Reg), &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+ }
+ case 87:
+ //line a.y:470
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 88:
+ //line a.y:474
+ {
+ outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-0].addr.Reg), &yyS[yypt-2].addr)
+ }
+ case 89:
+ //line a.y:481
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 90:
+ //line a.y:485
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 91:
+ //line a.y:489
+ {
+ outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-0].addr.Reg), &yyS[yypt-2].addr)
+ }
+ case 92:
+ //line a.y:493
+ {
+ outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-0].addr.Reg), &yyS[yypt-2].addr)
+ }
+ case 93:
+ //line a.y:500
+ {
+ outgcode(int(yyS[yypt-7].lval), &yyS[yypt-6].addr, int(yyS[yypt-4].addr.Reg), &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+ }
+ case 94:
+ //line a.y:504
+ {
+ outgcode(int(yyS[yypt-7].lval), &yyS[yypt-6].addr, int(yyS[yypt-4].addr.Reg), &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+ }
+ case 95:
+ //line a.y:508
+ {
+ outgcode(int(yyS[yypt-7].lval), &yyS[yypt-6].addr, int(yyS[yypt-4].addr.Reg), &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+ }
+ case 96:
+ //line a.y:512
+ {
+ outgcode(int(yyS[yypt-7].lval), &yyS[yypt-6].addr, int(yyS[yypt-4].addr.Reg), &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+ }
+ case 97:
+ //line a.y:519
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 98:
+ //line a.y:523
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 99:
+ //line a.y:531
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 100:
+ //line a.y:535
+ {
+ outgcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, NREG, &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+ }
+ case 101:
+ //line a.y:539
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 102:
+ //line a.y:543
+ {
+ outgcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, NREG, &yyS[yypt-2].addr, &yyS[yypt-0].addr)
+ }
+ case 103:
+ //line a.y:547
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 104:
+ //line a.y:551
+ {
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 105:
+ //line a.y:555
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr, NREG, &nullgen)
+ }
+ case 106:
+ //line a.y:562
+ {
+ outcode(int(yyS[yypt-1].lval), &nullgen, NREG, &nullgen)
+ }
+ case 107:
+ //line a.y:566
+ {
+ outcode(int(yyS[yypt-2].lval), &yyS[yypt-1].addr, NREG, &nullgen)
+ }
+ case 108:
+ //line a.y:570
+ {
+ outcode(int(yyS[yypt-2].lval), &yyS[yypt-1].addr, NREG, &nullgen)
+ }
+ case 109:
+ //line a.y:574
+ {
+ outcode(int(yyS[yypt-2].lval), &nullgen, NREG, &yyS[yypt-0].addr)
+ }
+ case 110:
+ //line a.y:578
+ {
+ outcode(int(yyS[yypt-2].lval), &nullgen, NREG, &yyS[yypt-0].addr)
+ }
+ case 111:
+ //line a.y:582
+ {
+ outcode(int(yyS[yypt-1].lval), &yyS[yypt-0].addr, NREG, &nullgen)
+ }
+ case 112:
+ //line a.y:589
+ {
+ outcode(int(yyS[yypt-2].lval), &yyS[yypt-1].addr, NREG, &nullgen)
+ }
+ case 113:
+ //line a.y:593
+ {
+ outcode(int(yyS[yypt-2].lval), &yyS[yypt-1].addr, NREG, &nullgen)
+ }
+ case 114:
+ //line a.y:600
+ {
+ if yyS[yypt-2].addr.Type != D_CONST || yyS[yypt-0].addr.Type != D_CONST {
+ yyerror("arguments to PCDATA must be integer constants")
+ }
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 115:
+ //line a.y:610
+ {
+ if yyS[yypt-2].addr.Type != D_CONST {
+ yyerror("index for FUNCDATA must be integer constant")
+ }
+ if yyS[yypt-0].addr.Type != D_EXTERN && yyS[yypt-0].addr.Type != D_STATIC && yyS[yypt-0].addr.Type != D_OREG {
+ yyerror("value for FUNCDATA must be symbol reference")
+ }
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 116:
+ //line a.y:623
+ {
+ outcode(int(yyS[yypt-1].lval), &nullgen, NREG, &nullgen)
+ }
+ case 117:
+ //line a.y:630
+ {
+ asm.Settext(yyS[yypt-2].addr.Sym)
+ outcode(int(yyS[yypt-3].lval), &yyS[yypt-2].addr, NREG, &yyS[yypt-0].addr)
+ }
+ case 118:
+ //line a.y:635
+ {
+ asm.Settext(yyS[yypt-4].addr.Sym)
+ yyS[yypt-0].addr.Offset &= 0xffffffff
+ yyS[yypt-0].addr.Offset |= -obj.ArgsSizeUnknown << 32
+ outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+ }
+ case 119:
+ //line a.y:642
+ {
+ asm.Settext(yyS[yypt-6].addr.Sym)
+ yyS[yypt-2].addr.Offset &= 0xffffffff
+ yyS[yypt-2].addr.Offset |= (yyS[yypt-0].lval & 0xffffffff) << 32
+ outcode(int(yyS[yypt-7].lval), &yyS[yypt-6].addr, int(yyS[yypt-4].lval), &yyS[yypt-2].addr)
+ }
+ case 120:
+ //line a.y:652
+ {
+ outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+ }
+ case 121:
+ //line a.y:656
+ {
+ outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+ }
+ case 122:
+ //line a.y:660
+ {
+ outcode(int(yyS[yypt-5].lval), &yyS[yypt-4].addr, int(yyS[yypt-2].lval), &yyS[yypt-0].addr)
+ }
+ case 123:
+ //line a.y:667
+ {
+ outcode(int(yyS[yypt-1].lval), &nullgen, NREG, &nullgen)
+ }
+ case 124:
+ //line a.y:673
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_BRANCH
+ yyVAL.addr.Offset = yyS[yypt-3].lval + int64(asm.PC)
+ }
+ case 125:
+ //line a.y:679
+ {
+ yyS[yypt-1].sym = asm.LabelLookup(yyS[yypt-1].sym)
+ yyVAL.addr = nullgen
+ if asm.Pass == 2 && yyS[yypt-1].sym.Type != LLAB {
+ yyerror("undefined label: %s", yyS[yypt-1].sym.Labelname)
+ }
+ yyVAL.addr.Type = D_BRANCH
+ yyVAL.addr.Offset = yyS[yypt-1].sym.Value + yyS[yypt-0].lval
+ }
+ case 126:
+ //line a.y:691
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_REG
+ yyVAL.addr.Reg = int8(yyS[yypt-0].lval)
+ }
+ case 127:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 128:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 129:
+ //line a.y:703
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_SPR
+ yyVAL.addr.Offset = yyS[yypt-0].lval
+ }
+ case 130:
+ //line a.y:711
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_CREG
+ yyVAL.addr.Reg = NREG /* whole register */
+ }
+ case 131:
+ //line a.y:718
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_SPR
+ yyVAL.addr.Offset = yyS[yypt-0].lval
+ }
+ case 132:
+ //line a.y:726
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_MSR
+ }
+ case 133:
+ //line a.y:733
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_SPR
+ yyVAL.addr.Offset = yyS[yypt-0].lval
+ }
+ case 134:
+ //line a.y:739
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = int16(yyS[yypt-3].lval)
+ yyVAL.addr.Offset = yyS[yypt-1].lval
+ }
+ case 135:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 136:
+ //line a.y:748
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_FPSCR
+ yyVAL.addr.Reg = NREG
+ }
+ case 137:
+ //line a.y:756
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_FPSCR
+ yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+ }
+ case 138:
+ //line a.y:764
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_FREG
+ yyVAL.addr.Reg = int8(yyS[yypt-0].lval)
+ }
+ case 139:
+ //line a.y:770
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_FREG
+ yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+ }
+ case 140:
+ //line a.y:778
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_CREG
+ yyVAL.addr.Reg = int8(yyS[yypt-0].lval)
+ }
+ case 141:
+ //line a.y:784
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_CREG
+ yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+ }
+ case 142:
+ //line a.y:792
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_REG
+ yyVAL.addr.Reg = int8(yyS[yypt-0].lval)
+ }
+ case 143:
+ //line a.y:800
+ {
+ var mb, me int
+ var v uint32
+
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_CONST
+ mb = int(yyS[yypt-2].lval)
+ me = int(yyS[yypt-0].lval)
+ if mb < 0 || mb > 31 || me < 0 || me > 31 {
+ yyerror("illegal mask start/end value(s)")
+ mb = 0
+ me = 0
+ }
+ if mb <= me {
+ v = (^uint32(0) >> uint(mb)) & (^uint32(0) << uint(31-me))
+ } else {
+ v = (^uint32(0) >> uint(me+1)) & (^uint32(0) << uint(31-(mb-1)))
+ }
+ yyVAL.addr.Offset = int64(v)
+ }
+ case 144:
+ //line a.y:823
+ {
+ yyVAL.addr = yyS[yypt-0].addr
+ yyVAL.addr.Type = D_CONST
+ }
+ case 145:
+ //line a.y:828
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_SCONST
+ yyVAL.addr.U.Sval = yyS[yypt-0].sval
+ }
+ case 146:
+ //line a.y:836
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_FCONST
+ yyVAL.addr.U.Dval = yyS[yypt-0].dval
+ }
+ case 147:
+ //line a.y:842
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_FCONST
+ yyVAL.addr.U.Dval = -yyS[yypt-0].dval
+ }
+ case 148:
+ //line a.y:849
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_CONST
+ yyVAL.addr.Offset = yyS[yypt-0].lval
+ }
+ case 149:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 150:
+ //line a.y:858
+ {
+ if yyVAL.lval < 0 || yyVAL.lval >= NREG {
+ print("register value out of range\n")
+ }
+ yyVAL.lval = yyS[yypt-1].lval
+ }
+ case 151:
+ //line a.y:867
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_OREG
+ yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+ yyVAL.addr.Offset = 0
+ }
+ case 152:
+ //line a.y:874
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_OREG
+ yyVAL.addr.Reg = int8(yyS[yypt-3].lval)
+ yyVAL.addr.Scale = int8(yyS[yypt-1].lval)
+ yyVAL.addr.Offset = 0
+ }
+ case 153:
+ yyVAL.addr = yyS[yypt-0].addr
+ case 154:
+ //line a.y:885
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_OREG
+ yyVAL.addr.Reg = int8(yyS[yypt-1].lval)
+ yyVAL.addr.Offset = yyS[yypt-3].lval
+ }
+ case 155:
+ //line a.y:894
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_OREG
+ yyVAL.addr.Name = int8(yyS[yypt-1].lval)
+ yyVAL.addr.Sym = nil
+ yyVAL.addr.Offset = yyS[yypt-3].lval
+ }
+ case 156:
+ //line a.y:902
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_OREG
+ yyVAL.addr.Name = int8(yyS[yypt-1].lval)
+ yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyS[yypt-4].sym.Name, 0)
+ yyVAL.addr.Offset = yyS[yypt-3].lval
+ }
+ case 157:
+ //line a.y:910
+ {
+ yyVAL.addr = nullgen
+ yyVAL.addr.Type = D_OREG
+ yyVAL.addr.Name = D_STATIC
+ yyVAL.addr.Sym = obj.Linklookup(asm.Ctxt, yyS[yypt-6].sym.Name, 0)
+ yyVAL.addr.Offset = yyS[yypt-3].lval
+ }
+ case 160:
+ //line a.y:922
+ {
+ yyVAL.lval = 0
+ }
+ case 161:
+ //line a.y:926
+ {
+ yyVAL.lval = yyS[yypt-0].lval
+ }
+ case 162:
+ //line a.y:930
+ {
+ yyVAL.lval = -yyS[yypt-0].lval
+ }
+ case 163:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 164:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 165:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 166:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 167:
+ //line a.y:942
+ {
+ yyVAL.lval = yyS[yypt-0].sym.Value
+ }
+ case 168:
+ //line a.y:946
+ {
+ yyVAL.lval = -yyS[yypt-0].lval
+ }
+ case 169:
+ //line a.y:950
+ {
+ yyVAL.lval = yyS[yypt-0].lval
+ }
+ case 170:
+ //line a.y:954
+ {
+ yyVAL.lval = ^yyS[yypt-0].lval
+ }
+ case 171:
+ //line a.y:958
+ {
+ yyVAL.lval = yyS[yypt-1].lval
+ }
+ case 172:
+ yyVAL.lval = yyS[yypt-0].lval
+ case 173:
+ //line a.y:965
+ {
+ yyVAL.lval = yyS[yypt-2].lval + yyS[yypt-0].lval
+ }
+ case 174:
+ //line a.y:969
+ {
+ yyVAL.lval = yyS[yypt-2].lval - yyS[yypt-0].lval
+ }
+ case 175:
+ //line a.y:973
+ {
+ yyVAL.lval = yyS[yypt-2].lval * yyS[yypt-0].lval
+ }
+ case 176:
+ //line a.y:977
+ {
+ yyVAL.lval = yyS[yypt-2].lval / yyS[yypt-0].lval
+ }
+ case 177:
+ //line a.y:981
+ {
+ yyVAL.lval = yyS[yypt-2].lval % yyS[yypt-0].lval
+ }
+ case 178:
+ //line a.y:985
+ {
+ yyVAL.lval = yyS[yypt-3].lval << uint(yyS[yypt-0].lval)
+ }
+ case 179:
+ //line a.y:989
+ {
+ yyVAL.lval = yyS[yypt-3].lval >> uint(yyS[yypt-0].lval)
+ }
+ case 180:
+ //line a.y:993
+ {
+ yyVAL.lval = yyS[yypt-2].lval & yyS[yypt-0].lval
+ }
+ case 181:
+ //line a.y:997
+ {
+ yyVAL.lval = yyS[yypt-2].lval ^ yyS[yypt-0].lval
+ }
+ case 182:
+ //line a.y:1001
+ {
+ yyVAL.lval = yyS[yypt-2].lval | yyS[yypt-0].lval
+ }
+ }
+ goto yystack /* stack new state and value */
+}
--- /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.
+
+// Objwriter reads an object file description in an unspecified format
+// and writes a Go object file. It is invoked by parts of the toolchain
+// that have not yet been converted from C to Go and should not be
+// used otherwise.
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "math"
+ "os"
+ "runtime/pprof"
+ "strconv"
+ "strings"
+
+ "cmd/internal/obj"
+ "cmd/internal/obj/arm"
+ "cmd/internal/obj/i386"
+ "cmd/internal/obj/ppc64"
+ "cmd/internal/obj/x86"
+)
+
+var arch *obj.LinkArch
+var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file")
+var memprofile = flag.String("memprofile", "", "write memory profile to this file")
+
+func main() {
+ log.SetPrefix("goobj: ")
+ log.SetFlags(0)
+ flag.Parse()
+
+ if flag.NArg() == 1 && flag.Arg(0) == "ping" {
+ // old invocation from liblink, just testing that objwriter exists
+ return
+ }
+
+ if flag.NArg() != 4 {
+ fmt.Fprintf(os.Stderr, "usage: goobj infile objfile offset goarch\n")
+ os.Exit(2)
+ }
+
+ if *cpuprofile != "" {
+ f, err := os.Create(*cpuprofile)
+ if err != nil {
+ log.Fatal(err)
+ }
+ pprof.StartCPUProfile(f)
+ defer pprof.StopCPUProfile()
+ }
+ if *memprofile != "" {
+ f, err := os.Create(*memprofile)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer pprof.WriteHeapProfile(f)
+ }
+
+ switch flag.Arg(3) {
+ case "amd64":
+ arch = &x86.Linkamd64
+ case "amd64p32":
+ arch = &x86.Linkamd64p32
+ case "386":
+ // TODO(rsc): Move Link386 to package x86.
+ arch = &i386.Link386
+ case "arm":
+ arch = &arm.Linkarm
+ case "ppc64":
+ arch = &ppc64.Linkppc64
+ case "ppc64le":
+ arch = &ppc64.Linkppc64le
+ }
+
+ input()
+}
+
+const (
+ // must match liblink/objfilego.c
+ TypeEnd = iota
+ TypeCtxt
+ TypePlist
+ TypeSym
+ TypeProg
+ TypeAddr
+ TypeHist
+)
+
+var (
+ ctxt *obj.Link
+ plists = map[int64]*obj.Plist{}
+ syms = map[int64]*obj.LSym{}
+ progs = map[int64]*obj.Prog{}
+ hists = map[int64]*obj.Hist{}
+ undef = map[interface{}]bool{}
+)
+
+func input() {
+ args := flag.Args()
+ ctxt = obj.Linknew(arch)
+ ctxt.Debugasm = 1
+ ctxt.Bso = obj.Binitw(os.Stdout)
+ defer obj.Bflush(ctxt.Bso)
+ ctxt.Diag = log.Fatalf
+ f, err := os.Open(args[0])
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ b := bufio.NewReaderSize(f, 1<<20)
+ if v := rdint(b); v != TypeCtxt {
+ log.Fatalf("invalid input - missing ctxt - got %d", v)
+ }
+ name := rdstring(b)
+ if name != ctxt.Arch.Name {
+ log.Fatalf("bad arch %s - want %s", name, ctxt.Arch.Name)
+ }
+
+ ctxt.Goarm = int32(rdint(b))
+ ctxt.Debugasm = int32(rdint(b))
+ ctxt.Trimpath = rdstring(b)
+ ctxt.Plist = rdplist(b)
+ ctxt.Plast = rdplist(b)
+ ctxt.Hist = rdhist(b)
+ ctxt.Ehist = rdhist(b)
+ for {
+ i := rdint(b)
+ if i < 0 {
+ break
+ }
+ ctxt.Hash[i] = rdsym(b)
+ }
+ last := int64(TypeCtxt)
+
+Loop:
+ for {
+ t := rdint(b)
+ switch t {
+ default:
+ log.Fatalf("unexpected input after type %d: %v", last, t)
+ case TypeEnd:
+ break Loop
+ case TypePlist:
+ readplist(b, rdplist(b))
+ case TypeSym:
+ readsym(b, rdsym(b))
+ case TypeProg:
+ readprog(b, rdprog(b))
+ case TypeHist:
+ readhist(b, rdhist(b))
+ }
+ last = t
+ }
+
+ if len(undef) > 0 {
+ panic("missing definitions")
+ }
+
+ var buf bytes.Buffer
+ obuf := obj.Binitw(&buf)
+ obj.Writeobjdirect(ctxt, obuf)
+ obj.Bflush(obuf)
+
+ data, err := ioutil.ReadFile(args[1])
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ offset, err := strconv.Atoi(args[2])
+ if err != nil {
+ log.Fatalf("bad offset: %v", err)
+ }
+ if offset > len(data) {
+ log.Fatalf("offset too large: %v > %v", offset, len(data))
+ }
+
+ old := data[offset:]
+ if len(old) > 0 && !bytes.Equal(old, buf.Bytes()) {
+ out := strings.TrimSuffix(args[0], ".in") + ".out"
+ if err := ioutil.WriteFile(out, append(data[:offset:offset], buf.Bytes()...), 0666); err != nil {
+ log.Fatal(err)
+ }
+ log.Fatalf("goobj produced different output:\n\toriginal: %s\n\tgoobj: %s", args[1], out)
+ }
+
+ if len(old) == 0 {
+ data = append(data, buf.Bytes()...)
+ if err := ioutil.WriteFile(args[1], data, 0666); err != nil {
+ log.Fatal(err)
+ }
+ }
+}
+
+func rdstring(b *bufio.Reader) string {
+ v := rdint(b)
+ buf := make([]byte, v)
+ io.ReadFull(b, buf)
+ return string(buf)
+}
+
+func rdint(b *bufio.Reader) int64 {
+ var v uint64
+ shift := uint(0)
+ for {
+ b, err := b.ReadByte()
+ if err != nil {
+ log.Fatal(err)
+ }
+ v |= uint64(b&0x7F) << shift
+ shift += 7
+ if b&0x80 == 0 {
+ break
+ }
+ }
+ return int64(v>>1) ^ int64(v<<63)>>63
+}
+
+func rdplist(b *bufio.Reader) *obj.Plist {
+ id := rdint(b)
+ if id == 0 {
+ return nil
+ }
+ pl := plists[id]
+ if pl == nil {
+ pl = new(obj.Plist)
+ plists[id] = pl
+ undef[pl] = true
+ }
+ return pl
+}
+
+func rdsym(b *bufio.Reader) *obj.LSym {
+ id := rdint(b)
+ if id == 0 {
+ return nil
+ }
+ sym := syms[id]
+ if sym == nil {
+ sym = new(obj.LSym)
+ syms[id] = sym
+ undef[sym] = true
+ }
+ return sym
+}
+
+func rdprog(b *bufio.Reader) *obj.Prog {
+ id := rdint(b)
+ if id == 0 {
+ return nil
+ }
+ prog := progs[id]
+ if prog == nil {
+ prog = new(obj.Prog)
+ prog.Ctxt = ctxt
+ progs[id] = prog
+ undef[prog] = true
+ }
+ return prog
+}
+
+func rdhist(b *bufio.Reader) *obj.Hist {
+ id := rdint(b)
+ if id == 0 {
+ return nil
+ }
+ h := hists[id]
+ if h == nil {
+ h = new(obj.Hist)
+ hists[id] = h
+ undef[h] = true
+ }
+ return h
+}
+
+func readplist(b *bufio.Reader, pl *obj.Plist) {
+ if !undef[pl] {
+ panic("double-def")
+ }
+ delete(undef, pl)
+ pl.Recur = int(rdint(b))
+ pl.Name = rdsym(b)
+ pl.Firstpc = rdprog(b)
+ pl.Link = rdplist(b)
+}
+
+func readsym(b *bufio.Reader, s *obj.LSym) {
+ if !undef[s] {
+ panic("double-def")
+ }
+ delete(undef, s)
+ s.Name = rdstring(b)
+ s.Extname = rdstring(b)
+ s.Type = int16(rdint(b))
+ s.Version = int16(rdint(b))
+ s.Dupok = uint8(rdint(b))
+ s.External = uint8(rdint(b))
+ s.Nosplit = uint8(rdint(b))
+ s.Reachable = uint8(rdint(b))
+ s.Cgoexport = uint8(rdint(b))
+ s.Special = uint8(rdint(b))
+ s.Stkcheck = uint8(rdint(b))
+ s.Hide = uint8(rdint(b))
+ s.Leaf = uint8(rdint(b))
+ s.Fnptr = uint8(rdint(b))
+ s.Seenglobl = uint8(rdint(b))
+ s.Onlist = uint8(rdint(b))
+ s.Symid = int16(rdint(b))
+ s.Dynid = int32(rdint(b))
+ s.Sig = int32(rdint(b))
+ s.Plt = int32(rdint(b))
+ s.Got = int32(rdint(b))
+ s.Align = int32(rdint(b))
+ s.Elfsym = int32(rdint(b))
+ s.Args = int32(rdint(b))
+ s.Locals = int32(rdint(b))
+ s.Value = rdint(b)
+ s.Size = rdint(b)
+ s.Hash = rdsym(b)
+ s.Allsym = rdsym(b)
+ s.Next = rdsym(b)
+ s.Sub = rdsym(b)
+ s.Outer = rdsym(b)
+ s.Gotype = rdsym(b)
+ s.Reachparent = rdsym(b)
+ s.Queue = rdsym(b)
+ s.File = rdstring(b)
+ s.Dynimplib = rdstring(b)
+ s.Dynimpvers = rdstring(b)
+ s.Text = rdprog(b)
+ s.Etext = rdprog(b)
+ n := int(rdint(b))
+ if n > 0 {
+ s.P = make([]byte, n)
+ io.ReadFull(b, s.P)
+ }
+ s.R = make([]obj.Reloc, int(rdint(b)))
+ for i := range s.R {
+ r := &s.R[i]
+ r.Off = int32(rdint(b))
+ r.Siz = uint8(rdint(b))
+ r.Done = uint8(rdint(b))
+ r.Type = int32(rdint(b))
+ r.Add = rdint(b)
+ r.Xadd = rdint(b)
+ r.Sym = rdsym(b)
+ r.Xsym = rdsym(b)
+ }
+}
+
+func readprog(b *bufio.Reader, p *obj.Prog) {
+ if !undef[p] {
+ panic("double-def")
+ }
+ delete(undef, p)
+ p.Pc = rdint(b)
+ p.Lineno = int32(rdint(b))
+ p.Link = rdprog(b)
+ p.As = int16(rdint(b))
+ p.Reg = uint8(rdint(b))
+ p.Scond = uint8(rdint(b))
+ p.Width = int8(rdint(b))
+ readaddr(b, &p.From)
+ readaddr(b, &p.From3)
+ readaddr(b, &p.To)
+}
+
+func readaddr(b *bufio.Reader, a *obj.Addr) {
+ if rdint(b) != TypeAddr {
+ log.Fatal("out of sync")
+ }
+ a.Offset = rdint(b)
+ a.U.Dval = rdfloat(b)
+ buf := make([]byte, 8)
+ io.ReadFull(b, buf)
+ a.U.Sval = string(buf)
+ a.U.Branch = rdprog(b)
+ a.Sym = rdsym(b)
+ a.Gotype = rdsym(b)
+ a.Type = int16(rdint(b))
+ a.Index = uint8(rdint(b))
+ a.Scale = int8(rdint(b))
+ a.Reg = int8(rdint(b))
+ a.Name = int8(rdint(b))
+ a.Class = int8(rdint(b))
+ a.Etype = uint8(rdint(b))
+ a.Offset2 = int32(rdint(b))
+ a.Width = rdint(b)
+}
+
+func readhist(b *bufio.Reader, h *obj.Hist) {
+ if !undef[h] {
+ panic("double-def")
+ }
+ delete(undef, h)
+ h.Link = rdhist(b)
+ h.Name = rdstring(b)
+ h.Line = int32(rdint(b))
+ h.Offset = int32(rdint(b))
+}
+
+func rdfloat(b *bufio.Reader) float64 {
+ return math.Float64frombits(uint64(rdint(b)))
+}
return defgetenv("GO386", GO386);
}
-char *
+char*
getgoextlinkenabled(void)
{
return GO_EXTLINK_ENABLED;
}
+
+char*
+getgohostarch(void)
+{
+ return GOHOSTARCH;
+}
+
+char*
+getgohostos(void)
+{
+ return GOHOSTOS;
+}
WinRune *r;
STARTUPINFOW si;
PROCESS_INFORMATION pi;
- DWORD code;
+ DWORD code, lasterr;
fmtstrinit(&fmt);
for(i=0; argv[i]; i++) {
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
if(!CreateProcessW(nil, r, nil, nil, TRUE, 0, nil, nil, &si, &pi)) {
+ werrstr("CreateProcess failed: errno=%d", (int)GetLastError());
free(r);
return -1;
}
free(r);
- if(WaitForMultipleObjects(1, &pi.hProcess, FALSE, INFINITE) != 0)
+ if(WaitForMultipleObjects(1, &pi.hProcess, FALSE, INFINITE) != 0) {
+ werrstr("WaitForMultipleObjects failed: errno=%d", (int)GetLastError());
return -1;
+ }
i = GetExitCodeProcess(pi.hProcess, &code);
+ lasterr = GetLastError();
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
- if(!i)
+ if(!i) {
+ werrstr("GetExitCodeProcess failed: errno=%d", (int)lasterr);
return -1;
+ }
if(code != 0) {
werrstr("unsuccessful exit status: %d", (int)code);
return -1;
static void rddata(Biobuf*, uchar**, int*);
static LSym *rdsym(Link*, Biobuf*, char*);
+void writeobjdirect(Link *ctxt, Biobuf *b);
+
+void writeobjgo1(Link*, char*);
+void writeobjgo2(Link*, char*, int64);
+
+extern char *outfile;
+
+void
+writeobj(Link *ctxt, Biobuf *b)
+{
+ vlong start;
+ char *env;
+
+ // If $GOOBJ > 0, invoke the Go version of the liblink
+ // output routines via a subprocess.
+ // If $GOOBJ == 1, copy that subprocess's output to
+ // the actual output file.
+ // If $GOOBJ >= 2, generate output using the usual C version
+ // but then check that the subprocess wrote the same bytes.
+ // $GOOBJ is a temporary setting for the transition to a
+ // Go liblink back end. Once the C liblink back ends are deleted,
+ // we will hard code the GOOBJ=1 behavior.
+ env = getenv("GOOBJ");
+ if(env == nil)
+ env = "0";
+ if(atoi(env) == 0) {
+ writeobjdirect(ctxt, b);
+ return;
+ }
+
+ Bflush(b);
+ start = Boffset(b);
+ writeobjgo1(ctxt, outfile);
+ if(atoi(env) > 1) {
+ writeobjdirect(ctxt, b);
+ Bflush(b);
+ }
+ writeobjgo2(ctxt, outfile, start);
+ Bseek(b, 0, 2);
+}
+
// The Go and C compilers, and the assembler, call writeobj to write
// out a Go object file. The linker does not call this; the linker
// does not write out object files.
void
-writeobj(Link *ctxt, Biobuf *b)
+writeobjdirect(Link *ctxt, Biobuf *b)
{
int flag, found;
Hist *h;
--- /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.
+
+// Writing of internal program representation to a serialized form
+// so that the Go translation of these routines can do the actual
+// program layout.
+// The serialized form and this code support the piecewise transition
+// from C to Go and will be removed along with the rest of the C code
+// when it is no longer needed.
+// There has been no attempt to make it particularly efficient, nor will there be.
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <link.h>
+
+/*c2go
+
+char *mktempdir(void);
+int runcmd(char**);
+void removeall(char*);
+*/
+
+static void printtype(Link*, Biobuf*, int);
+static void printsym(Link*, Biobuf*, LSym*);
+static void printprog(Link*, Biobuf*, Prog*);
+static void printaddr(Link*, Biobuf*, Addr*);
+static void printhist(Link*, Biobuf*, Hist*);
+static void printint(Link*, Biobuf*, int64);
+static void printstr(Link*, Biobuf*, char*);
+static void printptr(Link*, Biobuf*, void*);
+
+#undef waitpid
+
+enum
+{
+ TypeEnd = 0,
+ TypeCtxt,
+ TypePlist,
+ TypeSym,
+ TypeProg,
+ TypeAddr,
+ TypeHist,
+};
+
+void
+writeobjgo1(Link *ctxt, char *outfile)
+{
+ int i;
+ char *p;
+ Biobuf *bw;
+ Plist *pl;
+
+ p = smprint("%s.goliblink.in", outfile);
+ bw = Bopen(p, OWRITE);
+ if(bw == nil)
+ sysfatal("writing liblinktest input: %r");
+
+ printtype(ctxt, bw, TypeCtxt);
+ printstr(ctxt, bw, ctxt->arch->name);
+ printint(ctxt, bw, ctxt->goarm);
+ printint(ctxt, bw, ctxt->debugasm);
+ printstr(ctxt, bw, ctxt->trimpath);
+ printptr(ctxt, bw, ctxt->plist);
+ printptr(ctxt, bw, ctxt->plast);
+ printptr(ctxt, bw, ctxt->hist);
+ printptr(ctxt, bw, ctxt->ehist);
+ for(i = 0; i < LINKHASH; i++) {
+ if(ctxt->hash[i] != nil) {
+ printint(ctxt, bw, i);
+ printptr(ctxt, bw, ctxt->hash[i]);
+ }
+ }
+ printint(ctxt, bw, -1);
+
+ printhist(ctxt, bw, ctxt->hist);
+ printhist(ctxt, bw, ctxt->ehist);
+
+ for(pl=ctxt->plist; pl != nil; pl = pl->link) {
+ printtype(ctxt, bw, TypePlist);
+ printptr(ctxt, bw, pl);
+ printint(ctxt, bw, pl->recur);
+ printptr(ctxt, bw, pl->name);
+ printptr(ctxt, bw, pl->firstpc);
+ printptr(ctxt, bw, pl->link);
+ printsym(ctxt, bw, pl->name);
+ printprog(ctxt, bw, pl->firstpc);
+ }
+
+ for(i = 0; i < LINKHASH; i++)
+ printsym(ctxt, bw, ctxt->hash[i]);
+
+ printtype(ctxt, bw, TypeEnd);
+ Bterm(bw);
+}
+
+void
+writeobjgo2(Link *ctxt, char *outfile, int64 offset)
+{
+ char *p, *env, *prog, *cmd[10];
+ char offsetbuf[20];
+
+ USED(ctxt);
+
+ env = getenv("GOOBJWRITER");
+ if(env != nil && env[0] != '\0')
+ prog = env;
+ else
+ prog = smprint("%s/pkg/tool/%s_%s/objwriter", getgoroot(), getgohostos(), getgohostarch());
+
+ p = smprint("%s.goliblink.in", outfile);
+
+ snprint(offsetbuf, sizeof offsetbuf, "%lld", offset);
+
+ cmd[0] = prog;
+ cmd[1] = p;
+ cmd[2] = outfile;
+ cmd[3] = offsetbuf;
+ cmd[4] = ctxt->arch->name;
+ cmd[5] = nil;
+ if(runcmd(cmd) < 0)
+ sysfatal("running %s: %r", prog);
+
+ env = getenv("GOOBJ");
+ if(env == nil || atoi(env) <= 2)
+ remove(p);
+}
+
+static void
+printtype(Link *ctxt, Biobuf *bw, int t)
+{
+ printint(ctxt, bw, t);
+}
+
+static void
+printint(Link *ctxt, Biobuf *bw, int64 v)
+{
+ uint64 u;
+
+ USED(ctxt);
+
+ u = (uint64)(v<<1) ^ (uint64)(v>>63);
+ while(u >= 0x80) {
+ Bputc(bw, u&0x7F | 0x80);
+ u >>= 7;
+ }
+ Bputc(bw, u);
+}
+
+static void
+printstr(Link *ctxt, Biobuf *bw, char *s)
+{
+ if(s == nil)
+ s = "";
+ printint(ctxt, bw, strlen(s));
+ Bwrite(bw, s, strlen(s));
+}
+
+static void
+printptr(Link *ctxt, Biobuf *bw, void *v)
+{
+ printint(ctxt, bw, (int64)(uintptr)v);
+}
+
+static void
+printsym(Link *ctxt, Biobuf *bw, LSym *s)
+{
+ int i;
+ Reloc *r;
+
+ if(s == nil || s->printed)
+ return;
+ s->printed = 1;
+ printtype(ctxt, bw, TypeSym);
+ printptr(ctxt, bw, s);
+ printstr(ctxt, bw, s->name);
+ printstr(ctxt, bw, s->extname);
+ printint(ctxt, bw, s->type);
+ printint(ctxt, bw, s->version);
+ printint(ctxt, bw, s->dupok);
+ printint(ctxt, bw, s->external);
+ printint(ctxt, bw, s->nosplit);
+ printint(ctxt, bw, s->reachable);
+ printint(ctxt, bw, s->cgoexport);
+ printint(ctxt, bw, s->special);
+ printint(ctxt, bw, s->stkcheck);
+ printint(ctxt, bw, s->hide);
+ printint(ctxt, bw, s->leaf);
+ printint(ctxt, bw, s->fnptr);
+ printint(ctxt, bw, s->seenglobl);
+ printint(ctxt, bw, s->onlist);
+ printint(ctxt, bw, s->symid);
+ printint(ctxt, bw, s->dynid);
+ printint(ctxt, bw, s->sig);
+ printint(ctxt, bw, s->plt);
+ printint(ctxt, bw, s->got);
+ printint(ctxt, bw, s->align);
+ printint(ctxt, bw, s->elfsym);
+ printint(ctxt, bw, s->args);
+ printint(ctxt, bw, s->locals);
+ printint(ctxt, bw, s->value);
+ printint(ctxt, bw, s->size);
+ printptr(ctxt, bw, s->hash);
+ printptr(ctxt, bw, s->allsym);
+ printptr(ctxt, bw, s->next);
+ printptr(ctxt, bw, s->sub);
+ printptr(ctxt, bw, s->outer);
+ printptr(ctxt, bw, s->gotype);
+ printptr(ctxt, bw, s->reachparent);
+ printptr(ctxt, bw, s->queue);
+ printstr(ctxt, bw, s->file);
+ printstr(ctxt, bw, s->dynimplib);
+ printstr(ctxt, bw, s->dynimpvers);
+ printptr(ctxt, bw, s->text);
+ printptr(ctxt, bw, s->etext);
+ printint(ctxt, bw, s->np);
+ Bwrite(bw, s->p, s->np);
+ printint(ctxt, bw, s->nr);
+ for(i=0; i<s->nr; i++) {
+ r = s->r+i;
+ printint(ctxt, bw, r->off);
+ printint(ctxt, bw, r->siz);
+ printint(ctxt, bw, r->done);
+ printint(ctxt, bw, r->type);
+ printint(ctxt, bw, r->add);
+ printint(ctxt, bw, r->xadd);
+ printptr(ctxt, bw, r->sym);
+ printptr(ctxt, bw, r->xsym);
+ }
+
+ printsym(ctxt, bw, s->hash);
+ printsym(ctxt, bw, s->allsym);
+ printsym(ctxt, bw, s->next);
+ printsym(ctxt, bw, s->sub);
+ printsym(ctxt, bw, s->outer);
+ printsym(ctxt, bw, s->gotype);
+ printsym(ctxt, bw, s->reachparent);
+ printsym(ctxt, bw, s->queue);
+ printprog(ctxt, bw, s->text);
+ printprog(ctxt, bw, s->etext);
+ for(i=0; i<s->nr; i++) {
+ r = s->r+i;
+ printsym(ctxt, bw, r->sym);
+ printsym(ctxt, bw, r->xsym);
+ }
+}
+
+static void
+printprog(Link *ctxt, Biobuf *bw, Prog *p0)
+{
+ Prog *p, *q;
+
+ for(p = p0; p != nil && !p->printed; p=p->link) {
+ p->printed = 1;
+
+ printtype(ctxt, bw, TypeProg);
+ printptr(ctxt, bw, p);
+ printint(ctxt, bw, p->pc);
+ printint(ctxt, bw, p->lineno);
+ printptr(ctxt, bw, p->link);
+ printint(ctxt, bw, p->as);
+ printint(ctxt, bw, p->reg);
+ printint(ctxt, bw, p->scond);
+ printint(ctxt, bw, p->width);
+ printaddr(ctxt, bw, &p->from);
+ printaddr(ctxt, bw, &p->from3);
+ printaddr(ctxt, bw, &p->to);
+ printsym(ctxt, bw, p->from.sym);
+ printsym(ctxt, bw, p->from.gotype);
+ printsym(ctxt, bw, p->to.sym);
+ printsym(ctxt, bw, p->to.gotype);
+ }
+
+ q = p;
+ for(p=p0; p!=q; p=p->link) {
+ if(p->from.type == TYPE_BRANCH)
+ printprog(ctxt, bw, p->from.u.branch);
+ if(p->to.type == TYPE_BRANCH)
+ printprog(ctxt, bw, p->to.u.branch);
+ }
+}
+
+static void
+printaddr(Link *ctxt, Biobuf *bw, Addr *a)
+{
+ static char zero[8];
+
+ printtype(ctxt, bw, TypeAddr);
+ printint(ctxt, bw, a->offset);
+ if(a->type == TYPE_FCONST) {
+ uint64 u;
+ float64 f;
+ f = a->u.dval;
+ memmove(&u, &f, 8);
+ printint(ctxt, bw, u);
+ } else
+ printint(ctxt, bw, 0);
+ if(a->type == TYPE_SCONST)
+ Bwrite(bw, a->u.sval, 8);
+ else
+ Bwrite(bw, zero, 8);
+ if(a->type == TYPE_BRANCH)
+ printptr(ctxt, bw, a->u.branch);
+ else
+ printptr(ctxt, bw, nil);
+ printptr(ctxt, bw, a->sym);
+ printptr(ctxt, bw, a->gotype);
+ printint(ctxt, bw, a->type);
+ printint(ctxt, bw, a->index);
+ printint(ctxt, bw, a->scale);
+ printint(ctxt, bw, a->reg);
+ printint(ctxt, bw, a->name);
+ printint(ctxt, bw, a->class);
+ printint(ctxt, bw, a->etype);
+ if(a->type == TYPE_TEXTSIZE)
+ printint(ctxt, bw, a->u.argsize);
+ else
+ printint(ctxt, bw, 0);
+ printint(ctxt, bw, a->width);
+}
+
+static void
+printhist(Link *ctxt, Biobuf *bw, Hist *h)
+{
+ if(h == nil || h->printed)
+ return;
+ h->printed = 1;
+
+ printtype(ctxt, bw, TypeHist);
+ printptr(ctxt, bw, h);
+ printptr(ctxt, bw, h->link);
+ if(h->name == nil)
+ printstr(ctxt, bw, "<pop>");
+ else
+ printstr(ctxt, bw, h->name);
+ printint(ctxt, bw, h->line);
+ printint(ctxt, bw, h->offset);
+ printhist(ctxt, bw, h->link);
+}
exit 0
fi
-echo "##### Building compilers and Go bootstrap tool for host, $GOHOSTOS/$GOHOSTARCH."
buildall="-a"
if [ "$1" = "--no-clean" ]; then
buildall=""
./cmd/dist/dist bootstrap $buildall $GO_DISTFLAGS -v # builds go_bootstrap
# Delay move of dist tool to now, because bootstrap may clear tool directory.
mv cmd/dist/dist "$GOTOOLDIR"/dist
-"$GOTOOLDIR"/go_bootstrap clean -i std
echo
if [ "$GOHOSTARCH" != "$GOARCH" -o "$GOHOSTOS" != "$GOOS" ]; then
if x%1==x--dist-tool goto copydist
if x%2==x--dist-tool goto copydist
-echo ##### Building compilers and Go bootstrap tool.
set buildall=-a
if x%1==x--no-clean set buildall=
.\cmd\dist\dist bootstrap %buildall% -v
if errorlevel 1 goto fail
:: Delay move of dist tool to now, because bootstrap cleared tool directory.
move .\cmd\dist\dist.exe "%GOTOOLDIR%\dist.exe"
-"%GOTOOLDIR%\go_bootstrap" clean -i std
echo.
if not %GOHOSTARCH% == %GOARCH% goto localbuild
exit
}
-echo '# Building compilers and Go bootstrap tool for host,' $GOHOSTOS/$GOHOSTARCH^.
buildall = -a
if(~ $1 --no-clean)
buildall = ()
./cmd/dist/dist bootstrap $buildall -v # builds go_bootstrap
# Delay move of dist tool to now, because bootstrap may clear tool directory.
mv cmd/dist/dist $GOTOOLDIR/dist
-$GOTOOLDIR/go_bootstrap clean -i std
echo
# Run only one process at a time on 9vx.