From 74e88dfdeebef392d52d3f792e2071b058c1e231 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Mon, 2 Mar 2015 20:17:20 -0800 Subject: [PATCH] cmd/internal/obj: switch to one global Aconv Aconv is the pretty-printer for instruction opcodes like AMOVQ. There was one for each architecture. Make the space of A names have a different region for each architecture, much as we did for the registers, so a single global Aconv function can do the work. Each architecture registers its region as a slice of names at a given offset. The global names like CALL and JMP are now defined only once. The A values are used for indexing tables, so make it easy to do the indexing by making the offset maskable. Remove a bunch of now-duplicated architecture-specific code. Change-Id: Ib15647b7145a1c089e21e36543691a19e146b60e Reviewed-on: https://go-review.googlesource.com/6620 Reviewed-by: Russ Cox Run-TryBot: Rob Pike TryBot-Result: Gobot Gobot --- src/cmd/5g/peep.go | 4 +- src/cmd/9g/peep.go | 2 +- src/cmd/9g/prog.go | 2 +- src/cmd/asm/internal/arch/arch.go | 34 +- src/cmd/asm/internal/asm/asm.go | 22 +- src/cmd/internal/obj/arm/5.out.go | 2 +- src/cmd/internal/obj/arm/anames5.go | 23 +- src/cmd/internal/obj/arm/asm5.go | 141 +++---- src/cmd/internal/obj/arm/list5.go | 50 +-- src/cmd/internal/obj/i386/8.out.go | 2 +- src/cmd/internal/obj/i386/anames8.go | 23 +- src/cmd/internal/obj/i386/asm8.go | 149 ++++---- src/cmd/internal/obj/i386/list8.go | 13 +- src/cmd/internal/obj/link.go | 30 +- src/cmd/internal/obj/ppc64/9.out.go | 2 +- src/cmd/internal/obj/ppc64/anames9.go | 26 +- src/cmd/internal/obj/ppc64/asm9.go | 512 +++++++++++++------------- src/cmd/internal/obj/ppc64/list9.go | 25 +- src/cmd/internal/obj/util.go | 65 ++++ src/cmd/internal/obj/x86/6.out.go | 2 +- src/cmd/internal/obj/x86/anames6.go | 23 +- src/cmd/internal/obj/x86/asm6.go | 10 +- src/cmd/internal/obj/x86/list6.go | 13 +- src/cmd/internal/obj/x86/obj6.go | 10 +- 24 files changed, 560 insertions(+), 625 deletions(-) diff --git a/src/cmd/5g/peep.go b/src/cmd/5g/peep.go index 280cfb7fdcc..28977e268a9 100644 --- a/src/cmd/5g/peep.go +++ b/src/cmd/5g/peep.go @@ -544,7 +544,7 @@ gotit: } if gc.Debug['P'] != 0 { - fmt.Printf(" => %v\n", arm.Aconv(int(p.As))) + fmt.Printf(" => %v\n", obj.Aconv(int(p.As))) } return true } @@ -1043,7 +1043,7 @@ func xtramodes(g *gc.Graph, r *gc.Flow, a *obj.Addr) bool { func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int { switch p.As { default: - fmt.Printf("copyu: can't find %v\n", arm.Aconv(int(p.As))) + fmt.Printf("copyu: can't find %v\n", obj.Aconv(int(p.As))) return 2 case arm.AMOVM: diff --git a/src/cmd/9g/peep.go b/src/cmd/9g/peep.go index ecb8fb5d926..a71d8d25548 100644 --- a/src/cmd/9g/peep.go +++ b/src/cmd/9g/peep.go @@ -615,7 +615,7 @@ func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int { switch p.As { default: - fmt.Printf("copyu: can't find %v\n", ppc64.Aconv(int(p.As))) + fmt.Printf("copyu: can't find %v\n", obj.Aconv(int(p.As))) return 2 case obj.ANOP, /* read p->from, write p->to */ diff --git a/src/cmd/9g/prog.go b/src/cmd/9g/prog.go index b97125604a8..12c2304c73f 100644 --- a/src/cmd/9g/prog.go +++ b/src/cmd/9g/prog.go @@ -302,7 +302,7 @@ func as2variant(as int) int { return i } } - gc.Fatal("as2variant: instruction %v is not a variant of itself", ppc64.Aconv(as)) + gc.Fatal("as2variant: instruction %v is not a variant of itself", obj.Aconv(as)) return 0 } diff --git a/src/cmd/asm/internal/arch/arch.go b/src/cmd/asm/internal/arch/arch.go index 1ec8e0c12b2..79e2f722ac1 100644 --- a/src/cmd/asm/internal/arch/arch.go +++ b/src/cmd/asm/internal/arch/arch.go @@ -34,8 +34,6 @@ type Arch struct { RegisterNumber func(string, int16) (int16, bool) // Instruction is a jump. IsJump func(word string) bool - // Aconv pretty-prints an instruction opcode for this architecture. - Aconv func(int) string } // nilRegisterNumber is the register number function for architectures @@ -96,9 +94,14 @@ func arch386() *Arch { // Prefixes not used on this architecture. instructions := make(map[string]int) - for i, s := range i386.Anames { + for i, s := range obj.Anames { instructions[s] = i } + for i, s := range i386.Anames { + if i >= obj.A_ARCHSPECIFIC { + instructions[s] = i + obj.ABase386 + } + } // Annoying aliases. instructions["JA"] = i386.AJHI instructions["JAE"] = i386.AJCC @@ -140,7 +143,6 @@ func arch386() *Arch { RegisterPrefix: nil, RegisterNumber: nilRegisterNumber, IsJump: jump386, - Aconv: i386.Aconv, } } @@ -158,9 +160,14 @@ func archAmd64() *Arch { // Register prefix not used on this architecture. instructions := make(map[string]int) - for i, s := range x86.Anames { + for i, s := range obj.Anames { instructions[s] = i } + for i, s := range x86.Anames { + if i >= obj.A_ARCHSPECIFIC { + instructions[s] = i + obj.ABaseAMD64 + } + } // Annoying aliases. instructions["JA"] = x86.AJHI instructions["JAE"] = x86.AJCC @@ -209,7 +216,6 @@ func archAmd64() *Arch { RegisterPrefix: nil, RegisterNumber: nilRegisterNumber, IsJump: jump386, - Aconv: x86.Aconv, } } @@ -240,9 +246,14 @@ func archArm() *Arch { } instructions := make(map[string]int) - for i, s := range arm.Anames { + for i, s := range obj.Anames { instructions[s] = i } + for i, s := range arm.Anames { + if i >= obj.A_ARCHSPECIFIC { + instructions[s] = i + obj.ABaseARM + } + } // Annoying aliases. instructions["B"] = obj.AJMP instructions["BL"] = obj.ACALL @@ -254,7 +265,6 @@ func archArm() *Arch { RegisterPrefix: registerPrefix, RegisterNumber: armRegisterNumber, IsJump: jumpArm, - Aconv: arm.Aconv, } } @@ -296,9 +306,14 @@ func archPPC64() *Arch { } instructions := make(map[string]int) - for i, s := range ppc64.Anames { + for i, s := range obj.Anames { instructions[s] = i } + for i, s := range ppc64.Anames { + if i >= obj.A_ARCHSPECIFIC { + instructions[s] = i + obj.ABasePPC64 + } + } // Annoying aliases. instructions["BR"] = ppc64.ABR instructions["BL"] = ppc64.ABL @@ -311,6 +326,5 @@ func archPPC64() *Arch { RegisterPrefix: registerPrefix, RegisterNumber: ppc64RegisterNumber, IsJump: jumpPPC64, - Aconv: ppc64.Aconv, } } diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go index 1c583de4f10..526b81f8bad 100644 --- a/src/cmd/asm/internal/asm/asm.go +++ b/src/cmd/asm/internal/asm/asm.go @@ -314,7 +314,7 @@ func (p *Parser) asmJump(op int, cond string, a []obj.Addr) { prog.From = a[0] break } - p.errorf("wrong number of arguments to %s instruction", p.arch.Aconv(op)) + p.errorf("wrong number of arguments to %s instruction", obj.Aconv(op)) return case 3: if p.arch.Thechar == '9' { @@ -330,7 +330,7 @@ func (p *Parser) asmJump(op int, cond string, a []obj.Addr) { } fallthrough default: - p.errorf("wrong number of arguments to %s instruction", p.arch.Aconv(op)) + p.errorf("wrong number of arguments to %s instruction", obj.Aconv(op)) return } switch { @@ -402,7 +402,7 @@ func (p *Parser) branch(jmp, target *obj.Prog) { // asmInstruction assembles an instruction. // MOVW R9, (R10) func (p *Parser) asmInstruction(op int, cond string, a []obj.Addr) { - // fmt.Printf("%s %+v\n", p.arch.Aconv(op), a) + // fmt.Printf("%s %+v\n", obj.Aconv(op), a) prog := &obj.Prog{ Ctxt: p.ctxt, Lineno: p.histLineNum, @@ -451,7 +451,7 @@ func (p *Parser) asmInstruction(op int, cond string, a []obj.Addr) { prog.To = a[1] break } - p.errorf("unrecognized addressing for %s", p.arch.Aconv(op)) + p.errorf("unrecognized addressing for %s", obj.Aconv(op)) } } prog.From = a[0] @@ -538,7 +538,7 @@ func (p *Parser) asmInstruction(op int, cond string, a []obj.Addr) { prog.From3 = a[1] prog.To = a[2] default: - p.errorf("invalid addressing modes for %s instruction", p.arch.Aconv(op)) + p.errorf("invalid addressing modes for %s instruction", obj.Aconv(op)) } default: p.errorf("TODO: implement three-operand instructions for this architecture") @@ -567,7 +567,7 @@ func (p *Parser) asmInstruction(op int, cond string, a []obj.Addr) { prog.To = a[3] break } - p.errorf("can't handle %s instruction with 4 operands", p.arch.Aconv(op)) + p.errorf("can't handle %s instruction with 4 operands", obj.Aconv(op)) case 5: if p.arch.Thechar == '9' && arch.IsPPC64RLD(op) { // Always reg, reg, con, con, reg. (con, con is a 'mask'). @@ -588,7 +588,7 @@ func (p *Parser) asmInstruction(op int, cond string, a []obj.Addr) { prog.To = a[4] break } - p.errorf("can't handle %s instruction with 5 operands", p.arch.Aconv(op)) + p.errorf("can't handle %s instruction with 5 operands", obj.Aconv(op)) case 6: // MCR and MRC on ARM if p.arch.Thechar == '5' && arch.IsARMMRC(op) { @@ -631,7 +631,7 @@ func (p *Parser) asmInstruction(op int, cond string, a []obj.Addr) { } fallthrough default: - p.errorf("can't handle %s instruction with %d operands", p.arch.Aconv(op), len(a)) + p.errorf("can't handle %s instruction with %d operands", obj.Aconv(op), len(a)) } p.append(prog, cond, true) @@ -650,7 +650,7 @@ func (p *Parser) getConstantPseudo(pseudo string, addr *obj.Addr) int64 { // getConstant checks that addr represents a plain constant and returns its value. func (p *Parser) getConstant(prog *obj.Prog, op int, addr *obj.Addr) int64 { if addr.Type != obj.TYPE_MEM || addr.Name != 0 || addr.Reg != 0 || addr.Index != 0 { - p.errorf("%s: expected integer constant; found %s", p.arch.Aconv(op), obj.Dconv(prog, addr)) + p.errorf("%s: expected integer constant; found %s", obj.Aconv(op), obj.Dconv(prog, addr)) } return addr.Offset } @@ -658,7 +658,7 @@ func (p *Parser) getConstant(prog *obj.Prog, op int, addr *obj.Addr) int64 { // getImmediate checks that addr represents an immediate constant and returns its value. func (p *Parser) getImmediate(prog *obj.Prog, op int, addr *obj.Addr) int64 { if addr.Type != obj.TYPE_CONST || addr.Name != 0 || addr.Reg != 0 || addr.Index != 0 { - p.errorf("%s: expected immediate constant; found %s", p.arch.Aconv(op), obj.Dconv(prog, addr)) + p.errorf("%s: expected immediate constant; found %s", obj.Aconv(op), obj.Dconv(prog, addr)) } return addr.Offset } @@ -666,7 +666,7 @@ func (p *Parser) getImmediate(prog *obj.Prog, op int, addr *obj.Addr) int64 { // getRegister checks that addr represents a register and returns its value. func (p *Parser) getRegister(prog *obj.Prog, op int, addr *obj.Addr) int16 { if addr.Type != obj.TYPE_REG || addr.Offset != 0 || addr.Name != 0 || addr.Index != 0 { - p.errorf("%s: expected register; found %s", p.arch.Aconv(op), obj.Dconv(prog, addr)) + p.errorf("%s: expected register; found %s", obj.Aconv(op), obj.Dconv(prog, addr)) } return addr.Reg } diff --git a/src/cmd/internal/obj/arm/5.out.go b/src/cmd/internal/obj/arm/5.out.go index d4b0170e583..91e96874f0c 100644 --- a/src/cmd/internal/obj/arm/5.out.go +++ b/src/cmd/internal/obj/arm/5.out.go @@ -145,7 +145,7 @@ const ( ) const ( - AAND = obj.A_ARCHSPECIFIC + iota + AAND = obj.ABaseARM + obj.A_ARCHSPECIFIC + iota AEOR ASUB ARSB diff --git a/src/cmd/internal/obj/arm/anames5.go b/src/cmd/internal/obj/arm/anames5.go index f00cf177603..9f50df32398 100644 --- a/src/cmd/internal/obj/arm/anames5.go +++ b/src/cmd/internal/obj/arm/anames5.go @@ -1,26 +1,9 @@ package arm +import "cmd/internal/obj" + var Anames = []string{ - "XXX", - "CALL", - "CHECKNIL", - "DATA", - "DUFFCOPY", - "DUFFZERO", - "END", - "FUNCDATA", - "GLOBL", - "JMP", - "NOP", - "PCDATA", - "RET", - "TEXT", - "TYPE", - "UNDEF", - "USEFIELD", - "VARDEF", - "VARKILL", - "AND", + obj.A_ARCHSPECIFIC: "AND", "EOR", "SUB", "RSB", diff --git a/src/cmd/internal/obj/arm/asm5.go b/src/cmd/internal/obj/arm/asm5.go index 064cbe26f1d..10cca251725 100644 --- a/src/cmd/internal/obj/arm/asm5.go +++ b/src/cmd/internal/obj/arm/asm5.go @@ -39,7 +39,7 @@ import ( ) type Optab struct { - as uint8 + as uint16 a1 uint8 a2 int8 a3 uint8 @@ -268,7 +268,7 @@ var pool struct { extra uint32 } -var oprange [ALAST]Oprang +var oprange [ALAST & obj.AMask]Oprang var xcmp [C_GOK + 1][C_GOK + 1]uint8 @@ -580,7 +580,7 @@ func span5(ctxt *obj.Link, cursym *obj.LSym) { return } - if oprange[AAND].start == nil { + if oprange[AAND&obj.AMask].start == nil { buildop(ctxt) } @@ -1207,14 +1207,14 @@ func oplook(ctxt *obj.Link, p *obj.Prog) *Optab { if p.Reg != 0 { a2 = C_REG } - r := int(p.As) + r := p.As & obj.AMask 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("oplook %v %v %v %v\n", obj.Aconv(int(p.As)), DRconv(a1), DRconv(a2), DRconv(a3)) fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type) } @@ -1335,6 +1335,10 @@ func (x ocmp) Less(i, j int) bool { return false } +func opset(a, b0 uint16) { + oprange[a&obj.AMask] = oprange[b0] +} + func buildop(ctxt *obj.Link) { var n int @@ -1356,67 +1360,66 @@ func buildop(ctxt *obj.Link) { } sort.Sort(ocmp(optab[:n])) - var r int for i := 0; i < n; i++ { - r = int(optab[i].as) - oprange[r].start = optab[i:] - for int(optab[i].as) == r { + r0 := optab[i].as & obj.AMask + oprange[r0].start = optab[i:] + for optab[i].as&obj.AMask == r0 { i++ } - oprange[r].stop = optab[i:] + oprange[r0].stop = optab[i:] i-- - switch r { + switch r0 { default: - ctxt.Diag("unknown op in build: %v", Aconv(r)) + ctxt.Diag("unknown op in build: %v", obj.Aconv(int(optab[i].as))) 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] + opset(AAND, r0) + opset(AEOR, r0) + opset(ASUB, r0) + opset(ARSB, r0) + opset(AADC, r0) + opset(ASBC, r0) + opset(ARSC, r0) + opset(AORR, r0) + opset(ABIC, r0) case ACMP: - oprange[ATEQ] = oprange[r] - oprange[ACMN] = oprange[r] + opset(ATEQ, r0) + opset(ACMN, r0) 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] + opset(ABNE, r0) + opset(ABCS, r0) + opset(ABHS, r0) + opset(ABCC, r0) + opset(ABLO, r0) + opset(ABMI, r0) + opset(ABPL, r0) + opset(ABVS, r0) + opset(ABVC, r0) + opset(ABHI, r0) + opset(ABLS, r0) + opset(ABGE, r0) + opset(ABLT, r0) + opset(ABGT, r0) + opset(ABLE, r0) case ASLL: - oprange[ASRL] = oprange[r] - oprange[ASRA] = oprange[r] + opset(ASRL, r0) + opset(ASRA, r0) case AMUL: - oprange[AMULU] = oprange[r] + opset(AMULU, r0) case ADIV: - oprange[AMOD] = oprange[r] - oprange[AMODU] = oprange[r] - oprange[ADIVU] = oprange[r] + opset(AMOD, r0) + opset(AMODU, r0) + opset(ADIVU, r0) case AMOVW, AMOVB, @@ -1428,7 +1431,7 @@ func buildop(ctxt *obj.Link) { break case ASWPW: - oprange[ASWPBU] = oprange[r] + opset(ASWPBU, r0) case AB, ABL, @@ -1448,42 +1451,42 @@ func buildop(ctxt *obj.Link) { 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] + opset(AADDD, r0) + opset(ASUBF, r0) + opset(ASUBD, r0) + opset(AMULF, r0) + opset(AMULD, r0) + opset(ADIVF, r0) + opset(ADIVD, r0) + opset(ASQRTF, r0) + opset(ASQRTD, r0) + opset(AMOVFD, r0) + opset(AMOVDF, r0) + opset(AABSF, r0) + opset(AABSD, r0) case ACMPF: - oprange[ACMPD] = oprange[r] + opset(ACMPD, r0) case AMOVF: - oprange[AMOVD] = oprange[r] + opset(AMOVD, r0) case AMOVFW: - oprange[AMOVDW] = oprange[r] + opset(AMOVDW, r0) case AMOVWF: - oprange[AMOVWD] = oprange[r] + opset(AMOVWD, r0) case AMULL: - oprange[AMULAL] = oprange[r] - oprange[AMULLU] = oprange[r] - oprange[AMULALU] = oprange[r] + opset(AMULAL, r0) + opset(AMULLU, r0) + opset(AMULALU, r0) case AMULWT: - oprange[AMULWB] = oprange[r] + opset(AMULWB, r0) case AMULAWT: - oprange[AMULAWB] = oprange[r] + opset(AMULAWB, r0) case AMULA, ALDREX, @@ -2660,7 +2663,7 @@ func opbra(ctxt *obj.Link, a int, sc int) uint32 { return 0xe<<28 | 0x5<<25 } - ctxt.Diag("bad bra %v", Aconv(a)) + ctxt.Diag("bad bra %v", obj.Aconv(a)) prasm(ctxt.Curp) return 0 } @@ -2780,7 +2783,7 @@ func ofsr(ctxt *obj.Link, a int, r int, v int32, b int, sc int, p *obj.Prog) uin switch a { default: - ctxt.Diag("bad fst %v", Aconv(a)) + ctxt.Diag("bad fst %v", obj.Aconv(a)) fallthrough case AMOVD: diff --git a/src/cmd/internal/obj/arm/list5.go b/src/cmd/internal/obj/arm/list5.go index 60caedebc1f..0625cffcf91 100644 --- a/src/cmd/internal/obj/arm/list5.go +++ b/src/cmd/internal/obj/arm/list5.go @@ -79,57 +79,16 @@ func Pconv(p *obj.Prog) string { var str string if a == obj.ADATA { str = fmt.Sprintf("%.5d (%v)\t%v\t%v/%d,%v", - p.Pc, p.Line(), Aconv(a), obj.Dconv(p, &p.From), p.From3.Offset, obj.Dconv(p, &p.To)) + p.Pc, p.Line(), obj.Aconv(a), obj.Dconv(p, &p.From), p.From3.Offset, obj.Dconv(p, &p.To)) } else if p.As == obj.ATEXT { str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%d,%v", - p.Pc, p.Line(), Aconv(a), obj.Dconv(p, &p.From), p.From3.Offset, obj.Dconv(p, &p.To)) + p.Pc, p.Line(), obj.Aconv(a), obj.Dconv(p, &p.From), p.From3.Offset, obj.Dconv(p, &p.To)) } else if p.Reg == 0 { str = fmt.Sprintf("%.5d (%v)\t%v%s\t%v,%v", - p.Pc, p.Line(), Aconv(a), sc, obj.Dconv(p, &p.From), obj.Dconv(p, &p.To)) + p.Pc, p.Line(), obj.Aconv(a), sc, obj.Dconv(p, &p.From), obj.Dconv(p, &p.To)) } else { str = fmt.Sprintf("%.5d (%v)\t%v%s\t%v,%v,%v", - p.Pc, p.Line(), Aconv(a), sc, obj.Dconv(p, &p.From), Rconv(int(p.Reg)), obj.Dconv(p, &p.To)) - } - - var fp string - fp += str - return fp -} - -func Aconv(a int) string { - s := "???" - if a >= obj.AXXX && a < ALAST { - s = Anames[a] - } - var fp string - fp += s - return fp -} - -func RAconv(a *obj.Addr) string { - str := fmt.Sprintf("GOK-reglist") - switch a.Type { - case obj.TYPE_CONST: - if a.Reg != 0 { - break - } - if a.Sym != nil { - break - } - v := int(a.Offset) - str = "" - for i := 0; i < NREG; i++ { - if v&(1< subf Rd,ra,rb */ - oprange[ASUB] = oprange[r] + opset(ASUB, r0) - 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] + opset(ASUBCC, r0) + opset(ASUBV, r0) + opset(ASUBVCC, r0) + opset(ASUBCCC, r0) + opset(ASUBCV, r0) + opset(ASUBCVCC, r0) + opset(ASUBE, r0) + opset(ASUBECC, r0) + opset(ASUBEV, r0) + opset(ASUBEVCC, r0) case ASYNC: - oprange[AISYNC] = oprange[r] - oprange[APTESYNC] = oprange[r] - oprange[ATLBSYNC] = oprange[r] + opset(AISYNC, r0) + opset(APTESYNC, r0) + opset(ATLBSYNC, r0) case ARLWMI: - oprange[ARLWMICC] = oprange[r] - oprange[ARLWNM] = oprange[r] - oprange[ARLWNMCC] = oprange[r] + opset(ARLWMICC, r0) + opset(ARLWNM, r0) + opset(ARLWNMCC, r0) case ARLDMI: - oprange[ARLDMICC] = oprange[r] + opset(ARLDMICC, r0) case ARLDC: - oprange[ARLDCCC] = oprange[r] + opset(ARLDCCC, r0) case ARLDCL: - oprange[ARLDCR] = oprange[r] - oprange[ARLDCLCC] = oprange[r] - oprange[ARLDCRCC] = oprange[r] + opset(ARLDCR, r0) + opset(ARLDCLCC, r0) + opset(ARLDCRCC, r0) case AFMOVD: - oprange[AFMOVDCC] = oprange[r] - oprange[AFMOVDU] = oprange[r] - oprange[AFMOVS] = oprange[r] - oprange[AFMOVSU] = oprange[r] + opset(AFMOVDCC, r0) + opset(AFMOVDU, r0) + opset(AFMOVS, r0) + opset(AFMOVSU, r0) case AECIWX: - oprange[ALWAR] = oprange[r] - oprange[ALDAR] = oprange[r] + opset(ALWAR, r0) + opset(ALDAR, r0) case ASYSCALL: /* just the op; flow of control */ - oprange[ARFI] = oprange[r] + opset(ARFI, r0) - oprange[ARFCI] = oprange[r] - oprange[ARFID] = oprange[r] - oprange[AHRFID] = oprange[r] + opset(ARFCI, r0) + opset(ARFID, r0) + opset(AHRFID, r0) case AMOVHBR: - oprange[AMOVWBR] = oprange[r] + opset(AMOVWBR, r0) case ASLBMFEE: - oprange[ASLBMFEV] = oprange[r] + opset(ASLBMFEV, r0) case ATW: - oprange[ATD] = oprange[r] + opset(ATD, r0) case ATLBIE: - oprange[ASLBIE] = oprange[r] - oprange[ATLBIEL] = oprange[r] + opset(ASLBIE, r0) + opset(ATLBIEL, r0) case AEIEIO: - oprange[ASLBIA] = oprange[r] + opset(ASLBIA, r0) case ACMP: - oprange[ACMPW] = oprange[r] + opset(ACMPW, r0) case ACMPU: - oprange[ACMPWU] = oprange[r] + opset(ACMPWU, r0) case AADD, AANDCC, /* and. Rb,Rs,Ra; andi. $uimm,Rs,Ra; andis. $uimm,Rs,Ra */ @@ -2954,7 +2956,7 @@ func oprrr(ctxt *obj.Link, a int) int32 { return int32(OPVCC(31, 316, 0, 1)) } - ctxt.Diag("bad r/r opcode %v", Aconv(a)) + ctxt.Diag("bad r/r opcode %v", obj.Aconv(a)) return 0 } @@ -3076,7 +3078,7 @@ func opirr(ctxt *obj.Link, a int) int32 { return int32(OPVCC(27, 0, 0, 0)) /* XORIU */ } - ctxt.Diag("bad opcode i/r %v", Aconv(a)) + ctxt.Diag("bad opcode i/r %v", obj.Aconv(a)) return 0 } @@ -3125,7 +3127,7 @@ func opload(ctxt *obj.Link, a int) int32 { return int32(OPVCC(46, 0, 0, 0)) /* lmw */ } - ctxt.Diag("bad load opcode %v", Aconv(a)) + ctxt.Diag("bad load opcode %v", obj.Aconv(a)) return 0 } @@ -3184,7 +3186,7 @@ func oploadx(ctxt *obj.Link, a int) int32 { return int32(OPVCC(31, 53, 0, 0)) /* ldux */ } - ctxt.Diag("bad loadx opcode %v", Aconv(a)) + ctxt.Diag("bad loadx opcode %v", obj.Aconv(a)) return 0 } @@ -3234,7 +3236,7 @@ func opstore(ctxt *obj.Link, a int) int32 { return int32(OPVCC(62, 0, 0, 1)) /* stdu */ } - ctxt.Diag("unknown store opcode %v", Aconv(a)) + ctxt.Diag("unknown store opcode %v", obj.Aconv(a)) return 0 } @@ -3292,6 +3294,6 @@ func opstorex(ctxt *obj.Link, a int) int32 { return int32(OPVCC(31, 181, 0, 0)) /* stdux */ } - ctxt.Diag("unknown storex opcode %v", Aconv(a)) + ctxt.Diag("unknown storex opcode %v", obj.Aconv(a)) return 0 } diff --git a/src/cmd/internal/obj/ppc64/list9.go b/src/cmd/internal/obj/ppc64/list9.go index 6c62fad7a31..f9de6f34a63 100644 --- a/src/cmd/internal/obj/ppc64/list9.go +++ b/src/cmd/internal/obj/ppc64/list9.go @@ -59,14 +59,14 @@ func Pconv(p *obj.Prog) string { str := "" if a == obj.ADATA { str = fmt.Sprintf("%.5d (%v)\t%v\t%v/%d,%v", - p.Pc, p.Line(), Aconv(a), obj.Dconv(p, &p.From), p.From3.Offset, obj.Dconv(p, &p.To)) + p.Pc, p.Line(), obj.Aconv(a), obj.Dconv(p, &p.From), p.From3.Offset, obj.Dconv(p, &p.To)) } else if a == obj.ATEXT || a == obj.AGLOBL { if p.From3.Offset != 0 { str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%d,%v", - p.Pc, p.Line(), Aconv(a), obj.Dconv(p, &p.From), p.From3.Offset, obj.Dconv(p, &p.To)) + p.Pc, p.Line(), obj.Aconv(a), obj.Dconv(p, &p.From), p.From3.Offset, obj.Dconv(p, &p.To)) } else { str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%v", - p.Pc, p.Line(), Aconv(a), obj.Dconv(p, &p.From), obj.Dconv(p, &p.To)) + p.Pc, p.Line(), obj.Aconv(a), obj.Dconv(p, &p.From), obj.Dconv(p, &p.To)) } } else { if p.Mark&NOSCHED != 0 { @@ -74,24 +74,24 @@ func Pconv(p *obj.Prog) string { } if p.Reg == 0 && p.From3.Type == obj.TYPE_NONE { str += fmt.Sprintf("%.5d (%v)\t%v\t%v,%v", - p.Pc, p.Line(), Aconv(a), obj.Dconv(p, &p.From), obj.Dconv(p, &p.To)) + p.Pc, p.Line(), obj.Aconv(a), obj.Dconv(p, &p.From), obj.Dconv(p, &p.To)) } else if a != obj.ATEXT && p.From.Type == obj.TYPE_MEM { off := "" if p.From.Offset != 0 { off = fmt.Sprintf("%d", p.From.Offset) } str += fmt.Sprintf("%.5d (%v)\t%v\t%s(%v+%v),%v", - p.Pc, p.Line(), Aconv(a), off, Rconv(int(p.From.Reg)), Rconv(int(p.Reg)), obj.Dconv(p, &p.To)) + p.Pc, p.Line(), obj.Aconv(a), off, Rconv(int(p.From.Reg)), Rconv(int(p.Reg)), obj.Dconv(p, &p.To)) } else if p.To.Type == obj.TYPE_MEM { off := "" if p.From.Offset != 0 { off = fmt.Sprintf("%d", p.From.Offset) } str += fmt.Sprintf("%.5d (%v)\t%v\t%v,%s(%v+%v)", - p.Pc, p.Line(), Aconv(a), obj.Dconv(p, &p.From), off, Rconv(int(p.To.Reg)), Rconv(int(p.Reg))) + p.Pc, p.Line(), obj.Aconv(a), obj.Dconv(p, &p.From), off, Rconv(int(p.To.Reg)), Rconv(int(p.Reg))) } else { str += fmt.Sprintf("%.5d (%v)\t%v\t%v", - p.Pc, p.Line(), Aconv(a), obj.Dconv(p, &p.From)) + p.Pc, p.Line(), obj.Aconv(a), obj.Dconv(p, &p.From)) if p.Reg != 0 { str += fmt.Sprintf(",%v", Rconv(int(p.Reg))) } @@ -113,18 +113,9 @@ func Pconv(p *obj.Prog) string { return fp } -func Aconv(a int) string { - s := "???" - if a >= obj.AXXX && a < ALAST { - s = Anames[a] - } - var fp string - fp += s - return fp -} - func init() { obj.RegisterRegister(obj.RBasePPC64, REG_DCR0+1024, Rconv) + obj.RegisterOpcode(obj.ABasePPC64, Anames) } func Rconv(r int) string { diff --git a/src/cmd/internal/obj/util.go b/src/cmd/internal/obj/util.go index a3c88a2b8a5..d6267934752 100644 --- a/src/cmd/internal/obj/util.go +++ b/src/cmd/internal/obj/util.go @@ -491,3 +491,68 @@ func regListConv(list int) string { str += "]" return str } + +/* + Each architecture defines an instruction (A*) space as a unique + integer range. + Global opcodes like CALL start at 0; the architecture-specific ones + start at a distinct, big-maskable offsets. + Here is the list of architectures and the base of their opcode spaces. +*/ + +const ( + ABase386 = (1 + iota) << 12 + ABaseARM + ABaseAMD64 + ABasePPC64 + AMask = 1<<12 - 1 // AND with this to use the opcode as an array index. +) + +type opSet struct { + lo int + names []string +} + +// Not even worth sorting +var aSpace []opSet + +// RegisterOpcode binds a list of instruction names +// to a given instruction number range. +func RegisterOpcode(lo int, Anames []string) { + aSpace = append(aSpace, opSet{lo, Anames}) +} + +func Aconv(a int) string { + if a < A_ARCHSPECIFIC { + return Anames[a] + } + for i := range aSpace { + as := &aSpace[i] + if as.lo <= a && a < as.lo+len(as.names) { + return as.names[a-as.lo] + } + } + return fmt.Sprintf("A???%d", a) +} + +var Anames = []string{ + "XXX", + "CALL", + "CHECKNIL", + "DATA", + "DUFFCOPY", + "DUFFZERO", + "END", + "FUNCDATA", + "GLOBL", + "JMP", + "NOP", + "PCDATA", + "RET", + "TEXT", + "TYPE", + "UNDEF", + "USEFIELD", + "VARDEF", + "VARKILL", +} diff --git a/src/cmd/internal/obj/x86/6.out.go b/src/cmd/internal/obj/x86/6.out.go index 82f9291d61b..45af1d65cc2 100644 --- a/src/cmd/internal/obj/x86/6.out.go +++ b/src/cmd/internal/obj/x86/6.out.go @@ -36,7 +36,7 @@ import "cmd/internal/obj" * amd64 */ const ( - AAAA = obj.A_ARCHSPECIFIC + iota + AAAA = obj.ABaseAMD64 + obj.A_ARCHSPECIFIC + iota AAAD AAAM AAAS diff --git a/src/cmd/internal/obj/x86/anames6.go b/src/cmd/internal/obj/x86/anames6.go index fca730bf9d3..5839b23112f 100644 --- a/src/cmd/internal/obj/x86/anames6.go +++ b/src/cmd/internal/obj/x86/anames6.go @@ -1,29 +1,12 @@ package x86 +import "cmd/internal/obj" + /* * this is the ranlib header */ var Anames = []string{ - "XXX", - "CALL", - "CHECKNIL", - "DATA", - "DUFFCOPY", - "DUFFZERO", - "END", - "FUNCDATA", - "GLOBL", - "JMP", - "NOP", - "PCDATA", - "RET", - "TEXT", - "TYPE", - "UNDEF", - "USEFIELD", - "VARDEF", - "VARKILL", - "AAA", + obj.A_ARCHSPECIFIC: "AAA", "AAD", "AAM", "AAS", diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go index cb7d524c639..07ae72f3f0e 100644 --- a/src/cmd/internal/obj/x86/asm6.go +++ b/src/cmd/internal/obj/x86/asm6.go @@ -1435,7 +1435,7 @@ var optab = Optab{0, nil, 0, [23]uint8{}}, } -var opindex [ALAST + 1]*Optab +var opindex [(ALAST + 1) & obj.AMask]*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. @@ -1708,10 +1708,10 @@ func instinit() { 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)) + if opindex[c&obj.AMask] != nil { + log.Fatalf("phase error in optab: %d (%v)", i, obj.Aconv(c)) } - opindex[c] = &optab[i] + opindex[c&obj.AMask] = &optab[i] } for i := 0; i < Ymax; i++ { @@ -2758,7 +2758,7 @@ func mediaop(ctxt *obj.Link, o *Optab, op int, osize int, z int) int { func doasm(ctxt *obj.Link, p *obj.Prog) { ctxt.Curp = p // TODO - o := opindex[p.As] + o := opindex[p.As&obj.AMask] if o == nil { ctxt.Diag("asmins: missing op %v", p) diff --git a/src/cmd/internal/obj/x86/list6.go b/src/cmd/internal/obj/x86/list6.go index b2a7a7a24ae..6b7d65cbae5 100644 --- a/src/cmd/internal/obj/x86/list6.go +++ b/src/cmd/internal/obj/x86/list6.go @@ -59,21 +59,21 @@ func Pconv(p *obj.Prog) string { switch p.As { case obj.ADATA: str = fmt.Sprintf("%.5d (%v)\t%v\t%v/%d,%v", - p.Pc, p.Line(), Aconv(int(p.As)), obj.Dconv(p, &p.From), p.From3.Offset, obj.Dconv(p, &p.To)) + p.Pc, p.Line(), obj.Aconv(int(p.As)), obj.Dconv(p, &p.From), p.From3.Offset, obj.Dconv(p, &p.To)) case obj.ATEXT: if p.From3.Offset != 0 { str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%d,%v", - p.Pc, p.Line(), Aconv(int(p.As)), obj.Dconv(p, &p.From), p.From3.Offset, obj.Dconv(p, &p.To)) + p.Pc, p.Line(), obj.Aconv(int(p.As)), obj.Dconv(p, &p.From), p.From3.Offset, obj.Dconv(p, &p.To)) break } str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%v", - p.Pc, p.Line(), Aconv(int(p.As)), obj.Dconv(p, &p.From), obj.Dconv(p, &p.To)) + p.Pc, p.Line(), obj.Aconv(int(p.As)), obj.Dconv(p, &p.From), obj.Dconv(p, &p.To)) default: str = fmt.Sprintf("%.5d (%v)\t%v\t%v,%v", - p.Pc, p.Line(), Aconv(int(p.As)), obj.Dconv(p, &p.From), obj.Dconv(p, &p.To)) + p.Pc, p.Line(), obj.Aconv(int(p.As)), obj.Dconv(p, &p.From), obj.Dconv(p, &p.To)) // TODO(rsc): This special case is for SHRQ $32, AX:DX, which encodes as // SHRQ $32(DX*0), AX @@ -88,10 +88,6 @@ func Pconv(p *obj.Prog) string { return fp } -func Aconv(i int) string { - return Anames[i] -} - var Register = []string{ "AL", /* [D_AL] */ "CL", @@ -210,6 +206,7 @@ var Register = []string{ func init() { obj.RegisterRegister(REG_AL, REG_AL+len(Register), Rconv) + obj.RegisterOpcode(obj.ABaseAMD64, Anames) } func Rconv(r int) string { diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go index 434a120bd6b..2b1c3a2cc11 100644 --- a/src/cmd/internal/obj/x86/obj6.go +++ b/src/cmd/internal/obj/x86/obj6.go @@ -895,7 +895,7 @@ func pushpop(a int) bool { return false } -func relinv(a int) int { +func relinv(a int16) int16 { switch a { case AJEQ: return AJNE @@ -931,7 +931,7 @@ func relinv(a int) int { return AJOS } - log.Fatalf("unknown relation: %s", Anames[a]) + log.Fatalf("unknown relation: %s", obj.Aconv(int(a))) return 0 } @@ -1001,7 +1001,7 @@ loop: continue } - q.As = int16(relinv(int(q.As))) + q.As = relinv(q.As) p = q.Pcond q.Pcond = q.Link q.Link = p @@ -1054,7 +1054,7 @@ loop: * expect conditional jump to be taken. * rewrite so that's the fall-through case. */ - p.As = int16(relinv(a)) + p.As = relinv(int16(a)) q = p.Link p.Link = p.Pcond @@ -1064,7 +1064,7 @@ loop: q = p.Link if q.Mark != 0 { if a != ALOOP { - p.As = int16(relinv(a)) + p.As = relinv(int16(a)) p.Link = p.Pcond p.Pcond = q }