├── go.mod ├── bio ├── buf_nommap.go ├── must.go ├── buf_mmap.go └── buf.go ├── obj ├── go.go ├── abi_string.go ├── addrtype_string.go ├── s390x │ ├── anamesz.go │ ├── rotate.go │ ├── listz.go │ └── condition_code.go ├── mips │ ├── anames0.go │ ├── anames.go │ └── list0.go ├── riscv │ ├── list.go │ ├── testdata │ │ └── testbranch │ │ │ └── branch_test.s │ └── anames.go ├── ppc64 │ ├── anames9.go │ └── list9.go ├── line.go ├── x86 │ ├── ytab.go │ ├── list6.go │ └── a.out.go ├── arm │ ├── anames5.go │ ├── anames.go │ ├── list5.go │ └── a.out.go ├── textflag.go ├── arm64 │ ├── anames7.go │ ├── anames.go │ └── list7.go ├── stringer.go ├── ld.go ├── wasm │ ├── anames.go │ └── a.out.go ├── inl.go ├── pass.go └── data.go ├── objabi ├── typekind.go ├── stack.go ├── path.go ├── reloctype_string.go ├── symkind_string.go ├── autotype.go ├── funcdata.go ├── symkind.go ├── funcid.go ├── head.go ├── line.go ├── flag.go └── util.go ├── asm └── arch │ ├── riscv64.go │ ├── s390x.go │ ├── mips.go │ ├── ppc64.go │ └── arm.go ├── goobj ├── builtin.go ├── mkbuiltin.go ├── funcinfo.go └── builtinlist.go ├── unsafeheader ├── unsafeheader.go └── unsafeheader │ └── unsafeheader.go ├── LICENSE ├── .github └── workflows │ └── test.yml ├── README.md ├── sys ├── supported.go └── arch.go ├── src └── xpos.go └── gen.sh /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/twitchyliquid64/golang-asm 2 | 3 | go 1.13 4 | -------------------------------------------------------------------------------- /bio/buf_nommap.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd 6 | 7 | package bio 8 | 9 | func (r *Reader) sliceOS(length uint64) ([]byte, bool) { 10 | return nil, false 11 | } 12 | -------------------------------------------------------------------------------- /obj/go.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package obj 6 | 7 | // go-specific code shared across loaders (5l, 6l, 8l). 8 | 9 | func Nopout(p *Prog) { 10 | p.As = ANOP 11 | p.Scond = 0 12 | p.From = Addr{} 13 | p.RestArgs = nil 14 | p.Reg = 0 15 | p.To = Addr{} 16 | } 17 | -------------------------------------------------------------------------------- /obj/abi_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type ABI"; DO NOT EDIT. 2 | 3 | package obj 4 | 5 | import "strconv" 6 | 7 | const _ABI_name = "ABI0ABIInternalABICount" 8 | 9 | var _ABI_index = [...]uint8{0, 4, 15, 23} 10 | 11 | func (i ABI) String() string { 12 | if i >= ABI(len(_ABI_index)-1) { 13 | return "ABI(" + strconv.FormatInt(int64(i), 10) + ")" 14 | } 15 | return _ABI_name[_ABI_index[i]:_ABI_index[i+1]] 16 | } 17 | -------------------------------------------------------------------------------- /obj/addrtype_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type AddrType"; DO NOT EDIT. 2 | 3 | package obj 4 | 5 | import "strconv" 6 | 7 | const _AddrType_name = "TYPE_NONETYPE_BRANCHTYPE_TEXTSIZETYPE_MEMTYPE_CONSTTYPE_FCONSTTYPE_SCONSTTYPE_REGTYPE_ADDRTYPE_SHIFTTYPE_REGREGTYPE_REGREG2TYPE_INDIRTYPE_REGLIST" 8 | 9 | var _AddrType_index = [...]uint8{0, 9, 20, 33, 41, 51, 62, 73, 81, 90, 100, 111, 123, 133, 145} 10 | 11 | func (i AddrType) String() string { 12 | if i >= AddrType(len(_AddrType_index)-1) { 13 | return "AddrType(" + strconv.FormatInt(int64(i), 10) + ")" 14 | } 15 | return _AddrType_name[_AddrType_index[i]:_AddrType_index[i+1]] 16 | } 17 | -------------------------------------------------------------------------------- /obj/s390x/anamesz.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package s390x 6 | 7 | var cnamesz = []string{ 8 | "NONE", 9 | "REG", 10 | "FREG", 11 | "VREG", 12 | "AREG", 13 | "ZCON", 14 | "SCON", 15 | "UCON", 16 | "ADDCON", 17 | "ANDCON", 18 | "LCON", 19 | "DCON", 20 | "SACON", 21 | "LACON", 22 | "DACON", 23 | "SBRA", 24 | "LBRA", 25 | "SAUTO", 26 | "LAUTO", 27 | "ZOREG", 28 | "SOREG", 29 | "LOREG", 30 | "TLS_LE", 31 | "TLS_IE", 32 | "GOK", 33 | "ADDR", 34 | "SYMADDR", 35 | "GOTADDR", 36 | "TEXTSIZE", 37 | "ANY", 38 | "NCLASS", 39 | } 40 | -------------------------------------------------------------------------------- /obj/mips/anames0.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package mips 6 | 7 | var cnames0 = []string{ 8 | "NONE", 9 | "REG", 10 | "FREG", 11 | "FCREG", 12 | "MREG", 13 | "WREG", 14 | "HI", 15 | "LO", 16 | "ZCON", 17 | "SCON", 18 | "UCON", 19 | "ADD0CON", 20 | "AND0CON", 21 | "ADDCON", 22 | "ANDCON", 23 | "LCON", 24 | "DCON", 25 | "SACON", 26 | "SECON", 27 | "LACON", 28 | "LECON", 29 | "DACON", 30 | "STCON", 31 | "SBRA", 32 | "LBRA", 33 | "SAUTO", 34 | "LAUTO", 35 | "SEXT", 36 | "LEXT", 37 | "ZOREG", 38 | "SOREG", 39 | "LOREG", 40 | "GOK", 41 | "ADDR", 42 | "TLS", 43 | "TEXTSIZE", 44 | "NCLASS", 45 | } 46 | -------------------------------------------------------------------------------- /objabi/typekind.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package objabi 6 | 7 | // Must match runtime and reflect. 8 | // Included by cmd/gc. 9 | 10 | const ( 11 | KindBool = 1 + iota 12 | KindInt 13 | KindInt8 14 | KindInt16 15 | KindInt32 16 | KindInt64 17 | KindUint 18 | KindUint8 19 | KindUint16 20 | KindUint32 21 | KindUint64 22 | KindUintptr 23 | KindFloat32 24 | KindFloat64 25 | KindComplex64 26 | KindComplex128 27 | KindArray 28 | KindChan 29 | KindFunc 30 | KindInterface 31 | KindMap 32 | KindPtr 33 | KindSlice 34 | KindString 35 | KindStruct 36 | KindUnsafePointer 37 | KindDirectIface = 1 << 5 38 | KindGCProg = 1 << 6 39 | KindMask = (1 << 5) - 1 40 | ) 41 | -------------------------------------------------------------------------------- /obj/riscv/list.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package riscv 6 | 7 | import ( 8 | "fmt" 9 | 10 | "github.com/twitchyliquid64/golang-asm/obj" 11 | ) 12 | 13 | func init() { 14 | obj.RegisterRegister(obj.RBaseRISCV, REG_END, RegName) 15 | obj.RegisterOpcode(obj.ABaseRISCV, Anames) 16 | } 17 | 18 | func RegName(r int) string { 19 | switch { 20 | case r == 0: 21 | return "NONE" 22 | case r == REG_G: 23 | return "g" 24 | case r == REG_SP: 25 | return "SP" 26 | case REG_X0 <= r && r <= REG_X31: 27 | return fmt.Sprintf("X%d", r-REG_X0) 28 | case REG_F0 <= r && r <= REG_F31: 29 | return fmt.Sprintf("F%d", r-REG_F0) 30 | default: 31 | return fmt.Sprintf("Rgok(%d)", r-obj.RBaseRISCV) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /obj/ppc64/anames9.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package ppc64 6 | 7 | var cnames9 = []string{ 8 | "NONE", 9 | "REG", 10 | "FREG", 11 | "VREG", 12 | "VSREG", 13 | "CREG", 14 | "SPR", 15 | "ZCON", 16 | "SCON", 17 | "UCON", 18 | "ADDCON", 19 | "ANDCON", 20 | "LCON", 21 | "DCON", 22 | "SACON", 23 | "SECON", 24 | "LACON", 25 | "LECON", 26 | "DACON", 27 | "SBRA", 28 | "LBRA", 29 | "LBRAPIC", 30 | "SAUTO", 31 | "LAUTO", 32 | "SEXT", 33 | "LEXT", 34 | "ZOREG", 35 | "SOREG", 36 | "LOREG", 37 | "FPSCR", 38 | "MSR", 39 | "XER", 40 | "LR", 41 | "CTR", 42 | "ANY", 43 | "GOK", 44 | "ADDR", 45 | "GOTADDR", 46 | "TOCADDR", 47 | "TLS_LE", 48 | "TLS_IE", 49 | "TEXTSIZE", 50 | "NCLASS", 51 | } 52 | -------------------------------------------------------------------------------- /objabi/stack.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package objabi 6 | 7 | // For the linkers. Must match Go definitions. 8 | 9 | const ( 10 | STACKSYSTEM = 0 11 | StackSystem = STACKSYSTEM 12 | StackBig = 4096 13 | StackSmall = 128 14 | ) 15 | 16 | const ( 17 | StackPreempt = -1314 // 0xfff...fade 18 | ) 19 | 20 | // Initialize StackGuard and StackLimit according to target system. 21 | var StackGuard = 928*stackGuardMultiplier() + StackSystem 22 | var StackLimit = StackGuard - StackSystem - StackSmall 23 | 24 | // stackGuardMultiplier returns a multiplier to apply to the default 25 | // stack guard size. Larger multipliers are used for non-optimized 26 | // builds that have larger stack frames or for specific targets. 27 | func stackGuardMultiplier() int { 28 | // On AIX, a larger stack is needed for syscalls. 29 | if GOOS == "aix" { 30 | return 2 31 | } 32 | return 1 33 | } 34 | -------------------------------------------------------------------------------- /bio/must.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package bio 6 | 7 | import ( 8 | "io" 9 | "log" 10 | ) 11 | 12 | // MustClose closes Closer c and calls log.Fatal if it returns a non-nil error. 13 | func MustClose(c io.Closer) { 14 | if err := c.Close(); err != nil { 15 | log.Fatal(err) 16 | } 17 | } 18 | 19 | // MustWriter returns a Writer that wraps the provided Writer, 20 | // except that it calls log.Fatal instead of returning a non-nil error. 21 | func MustWriter(w io.Writer) io.Writer { 22 | return mustWriter{w} 23 | } 24 | 25 | type mustWriter struct { 26 | w io.Writer 27 | } 28 | 29 | func (w mustWriter) Write(b []byte) (int, error) { 30 | n, err := w.w.Write(b) 31 | if err != nil { 32 | log.Fatal(err) 33 | } 34 | return n, nil 35 | } 36 | 37 | func (w mustWriter) WriteString(s string) (int, error) { 38 | n, err := io.WriteString(w.w, s) 39 | if err != nil { 40 | log.Fatal(err) 41 | } 42 | return n, nil 43 | } 44 | -------------------------------------------------------------------------------- /asm/arch/riscv64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file encapsulates some of the odd characteristics of the RISCV64 6 | // instruction set, to minimize its interaction with the core of the 7 | // assembler. 8 | 9 | package arch 10 | 11 | import ( 12 | "github.com/twitchyliquid64/golang-asm/obj" 13 | "github.com/twitchyliquid64/golang-asm/obj/riscv" 14 | ) 15 | 16 | // IsRISCV64AMO reports whether the op (as defined by a riscv.A* 17 | // constant) is one of the AMO instructions that requires special 18 | // handling. 19 | func IsRISCV64AMO(op obj.As) bool { 20 | switch op { 21 | case riscv.ASCW, riscv.ASCD, riscv.AAMOSWAPW, riscv.AAMOSWAPD, riscv.AAMOADDW, riscv.AAMOADDD, 22 | riscv.AAMOANDW, riscv.AAMOANDD, riscv.AAMOORW, riscv.AAMOORD, riscv.AAMOXORW, riscv.AAMOXORD, 23 | riscv.AAMOMINW, riscv.AAMOMIND, riscv.AAMOMINUW, riscv.AAMOMINUD, 24 | riscv.AAMOMAXW, riscv.AAMOMAXD, riscv.AAMOMAXUW, riscv.AAMOMAXUD: 25 | return true 26 | } 27 | return false 28 | } 29 | -------------------------------------------------------------------------------- /obj/line.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package obj 6 | 7 | import ( 8 | "github.com/twitchyliquid64/golang-asm/goobj" 9 | "github.com/twitchyliquid64/golang-asm/src" 10 | ) 11 | 12 | // AddImport adds a package to the list of imported packages. 13 | func (ctxt *Link) AddImport(pkg string, fingerprint goobj.FingerprintType) { 14 | ctxt.Imports = append(ctxt.Imports, goobj.ImportedPkg{Pkg: pkg, Fingerprint: fingerprint}) 15 | } 16 | 17 | func linkgetlineFromPos(ctxt *Link, xpos src.XPos) (f string, l int32) { 18 | pos := ctxt.PosTable.Pos(xpos) 19 | if !pos.IsKnown() { 20 | pos = src.Pos{} 21 | } 22 | // TODO(gri) Should this use relative or absolute line number? 23 | return pos.SymFilename(), int32(pos.RelLine()) 24 | } 25 | 26 | // getFileIndexAndLine returns the file index (local to the CU), and the line number for a position. 27 | func getFileIndexAndLine(ctxt *Link, xpos src.XPos) (int, int32) { 28 | f, l := linkgetlineFromPos(ctxt, xpos) 29 | return ctxt.PosTable.FileIndex(f), l 30 | } 31 | -------------------------------------------------------------------------------- /goobj/builtin.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goobj 6 | 7 | // Builtin (compiler-generated) function references appear 8 | // frequently. We assign special indices for them, so they 9 | // don't need to be referenced by name. 10 | 11 | // NBuiltin returns the number of listed builtin 12 | // symbols. 13 | func NBuiltin() int { 14 | return len(builtins) 15 | } 16 | 17 | // BuiltinName returns the name and ABI of the i-th 18 | // builtin symbol. 19 | func BuiltinName(i int) (string, int) { 20 | return builtins[i].name, builtins[i].abi 21 | } 22 | 23 | // BuiltinIdx returns the index of the builtin with the 24 | // given name and abi, or -1 if it is not a builtin. 25 | func BuiltinIdx(name string, abi int) int { 26 | i, ok := builtinMap[name] 27 | if !ok { 28 | return -1 29 | } 30 | if builtins[i].abi != abi { 31 | return -1 32 | } 33 | return i 34 | } 35 | 36 | //go:generate go run mkbuiltin.go 37 | 38 | var builtinMap map[string]int 39 | 40 | func init() { 41 | builtinMap = make(map[string]int, len(builtins)) 42 | for i, b := range builtins { 43 | builtinMap[b.name] = i 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /objabi/path.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package objabi 6 | 7 | import "strings" 8 | 9 | // PathToPrefix converts raw string to the prefix that will be used in the 10 | // symbol table. All control characters, space, '%' and '"', as well as 11 | // non-7-bit clean bytes turn into %xx. The period needs escaping only in the 12 | // last segment of the path, and it makes for happier users if we escape that as 13 | // little as possible. 14 | func PathToPrefix(s string) string { 15 | slash := strings.LastIndex(s, "/") 16 | // check for chars that need escaping 17 | n := 0 18 | for r := 0; r < len(s); r++ { 19 | if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F { 20 | n++ 21 | } 22 | } 23 | 24 | // quick exit 25 | if n == 0 { 26 | return s 27 | } 28 | 29 | // escape 30 | const hex = "0123456789abcdef" 31 | p := make([]byte, 0, len(s)+2*n) 32 | for r := 0; r < len(s); r++ { 33 | if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F { 34 | p = append(p, '%', hex[c>>4], hex[c&0xF]) 35 | } else { 36 | p = append(p, c) 37 | } 38 | } 39 | 40 | return string(p) 41 | } 42 | -------------------------------------------------------------------------------- /unsafeheader/unsafeheader.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package unsafeheader contains header declarations for the Go runtime's slice 6 | // and string implementations. 7 | // 8 | // This package allows packages that cannot import "reflect" to use types that 9 | // are tested to be equivalent to reflect.SliceHeader and reflect.StringHeader. 10 | package unsafeheader 11 | 12 | import ( 13 | "unsafe" 14 | ) 15 | 16 | // Slice is the runtime representation of a slice. 17 | // It cannot be used safely or portably and its representation may 18 | // change in a later release. 19 | // 20 | // Unlike reflect.SliceHeader, its Data field is sufficient to guarantee the 21 | // data it references will not be garbage collected. 22 | type Slice struct { 23 | Data unsafe.Pointer 24 | Len int 25 | Cap int 26 | } 27 | 28 | // String is the runtime representation of a string. 29 | // It cannot be used safely or portably and its representation may 30 | // change in a later release. 31 | // 32 | // Unlike reflect.StringHeader, its Data field is sufficient to guarantee the 33 | // data it references will not be garbage collected. 34 | type String struct { 35 | Data unsafe.Pointer 36 | Len int 37 | } 38 | -------------------------------------------------------------------------------- /unsafeheader/unsafeheader/unsafeheader.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package unsafeheader contains header declarations for the Go runtime's slice 6 | // and string implementations. 7 | // 8 | // This package allows packages that cannot import "reflect" to use types that 9 | // are tested to be equivalent to reflect.SliceHeader and reflect.StringHeader. 10 | package unsafeheader 11 | 12 | import ( 13 | "unsafe" 14 | ) 15 | 16 | // Slice is the runtime representation of a slice. 17 | // It cannot be used safely or portably and its representation may 18 | // change in a later release. 19 | // 20 | // Unlike reflect.SliceHeader, its Data field is sufficient to guarantee the 21 | // data it references will not be garbage collected. 22 | type Slice struct { 23 | Data unsafe.Pointer 24 | Len int 25 | Cap int 26 | } 27 | 28 | // String is the runtime representation of a string. 29 | // It cannot be used safely or portably and its representation may 30 | // change in a later release. 31 | // 32 | // Unlike reflect.StringHeader, its Data field is sufficient to guarantee the 33 | // data it references will not be garbage collected. 34 | type String struct { 35 | Data unsafe.Pointer 36 | Len int 37 | } 38 | -------------------------------------------------------------------------------- /objabi/reloctype_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=RelocType"; DO NOT EDIT. 2 | 3 | package objabi 4 | 5 | import "strconv" 6 | 7 | const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_WEAKADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CALLRISCVR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_METHODOFFR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_LDST8R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREF" 8 | 9 | var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 60, 66, 72, 81, 92, 101, 112, 122, 133, 140, 147, 155, 163, 171, 177, 183, 189, 199, 208, 219, 230, 240, 249, 262, 276, 290, 304, 320, 331, 344, 357, 371, 385, 400, 414, 428, 439, 453, 468, 485, 503, 524, 543, 562, 572, 583, 596, 607, 619, 629} 10 | 11 | func (i RelocType) String() string { 12 | i -= 1 13 | if i < 0 || i >= RelocType(len(_RelocType_index)-1) { 14 | return "RelocType(" + strconv.FormatInt(int64(i+1), 10) + ")" 15 | } 16 | return _RelocType_name[_RelocType_index[i]:_RelocType_index[i+1]] 17 | } 18 | -------------------------------------------------------------------------------- /objabi/symkind_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=SymKind"; DO NOT EDIT. 2 | 3 | package objabi 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[Sxxx-0] 12 | _ = x[STEXT-1] 13 | _ = x[SRODATA-2] 14 | _ = x[SNOPTRDATA-3] 15 | _ = x[SDATA-4] 16 | _ = x[SBSS-5] 17 | _ = x[SNOPTRBSS-6] 18 | _ = x[STLSBSS-7] 19 | _ = x[SDWARFCUINFO-8] 20 | _ = x[SDWARFCONST-9] 21 | _ = x[SDWARFFCN-10] 22 | _ = x[SDWARFABSFCN-11] 23 | _ = x[SDWARFTYPE-12] 24 | _ = x[SDWARFVAR-13] 25 | _ = x[SDWARFRANGE-14] 26 | _ = x[SDWARFLOC-15] 27 | _ = x[SDWARFLINES-16] 28 | _ = x[SABIALIAS-17] 29 | _ = x[SLIBFUZZER_EXTRA_COUNTER-18] 30 | } 31 | 32 | const _SymKind_name = "SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFCUINFOSDWARFCONSTSDWARFFCNSDWARFABSFCNSDWARFTYPESDWARFVARSDWARFRANGESDWARFLOCSDWARFLINESSABIALIASSLIBFUZZER_EXTRA_COUNTER" 33 | 34 | var _SymKind_index = [...]uint8{0, 4, 9, 16, 26, 31, 35, 44, 51, 63, 74, 83, 95, 105, 114, 125, 134, 145, 154, 178} 35 | 36 | func (i SymKind) String() string { 37 | if i >= SymKind(len(_SymKind_index)-1) { 38 | return "SymKind(" + strconv.FormatInt(int64(i), 10) + ")" 39 | } 40 | return _SymKind_name[_SymKind_index[i]:_SymKind_index[i+1]] 41 | } 42 | -------------------------------------------------------------------------------- /obj/x86/ytab.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package x86 6 | 7 | // argListMax specifies upper arg count limit expected to be carried by obj.Prog. 8 | // Max len(obj.Prog.RestArgs) can be inferred from this to be 4. 9 | const argListMax int = 6 10 | 11 | type argList [argListMax]uint8 12 | 13 | type ytab struct { 14 | zcase uint8 15 | zoffset uint8 16 | 17 | // Last arg is usually destination. 18 | // For unary instructions unaryDst is used to determine 19 | // if single argument is a source or destination. 20 | args argList 21 | } 22 | 23 | // Returns true if yt is compatible with args. 24 | // 25 | // Elements from args and yt.args are used 26 | // to index ycover table like `ycover[args[i]+yt.args[i]]`. 27 | // This means that args should contain values that already 28 | // multiplied by Ymax. 29 | func (yt *ytab) match(args []int) bool { 30 | // Trailing Yxxx check is required to avoid a case 31 | // where shorter arg list is matched. 32 | // If we had exact yt.args length, it could be `yt.argc != len(args)`. 33 | if len(args) < len(yt.args) && yt.args[len(args)] != Yxxx { 34 | return false 35 | } 36 | 37 | for i := range args { 38 | if ycover[args[i]+int(yt.args[i])] == 0 { 39 | return false 40 | } 41 | } 42 | 43 | return true 44 | } 45 | -------------------------------------------------------------------------------- /obj/s390x/rotate.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package s390x 6 | 7 | // RotateParams represents the immediates required for a "rotate 8 | // then ... selected bits instruction". 9 | // 10 | // The Start and End values are the indexes that represent 11 | // the masked region. They are inclusive and are in big- 12 | // endian order (bit 0 is the MSB, bit 63 is the LSB). They 13 | // may wrap around. 14 | // 15 | // Some examples: 16 | // 17 | // Masked region | Start | End 18 | // --------------------------+-------+---- 19 | // 0x00_00_00_00_00_00_00_0f | 60 | 63 20 | // 0xf0_00_00_00_00_00_00_00 | 0 | 3 21 | // 0xf0_00_00_00_00_00_00_0f | 60 | 3 22 | // 23 | // The Amount value represents the amount to rotate the 24 | // input left by. Note that this rotation is performed 25 | // before the masked region is used. 26 | type RotateParams struct { 27 | Start uint8 // big-endian start bit index [0..63] 28 | End uint8 // big-endian end bit index [0..63] 29 | Amount uint8 // amount to rotate left 30 | } 31 | 32 | func NewRotateParams(start, end, amount int64) RotateParams { 33 | if start&^63 != 0 { 34 | panic("start out of bounds") 35 | } 36 | if end&^63 != 0 { 37 | panic("end out of bounds") 38 | } 39 | if amount&^63 != 0 { 40 | panic("amount out of bounds") 41 | } 42 | return RotateParams{ 43 | Start: uint8(start), 44 | End: uint8(end), 45 | Amount: uint8(amount), 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /obj/arm/anames5.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package arm 6 | 7 | var cnames5 = []string{ 8 | "NONE", 9 | "REG", 10 | "REGREG", 11 | "REGREG2", 12 | "REGLIST", 13 | "SHIFT", 14 | "SHIFTADDR", 15 | "FREG", 16 | "PSR", 17 | "FCR", 18 | "SPR", 19 | "RCON", 20 | "NCON", 21 | "RCON2A", 22 | "RCON2S", 23 | "SCON", 24 | "LCON", 25 | "LCONADDR", 26 | "ZFCON", 27 | "SFCON", 28 | "LFCON", 29 | "RACON", 30 | "LACON", 31 | "SBRA", 32 | "LBRA", 33 | "HAUTO", 34 | "FAUTO", 35 | "HFAUTO", 36 | "SAUTO", 37 | "LAUTO", 38 | "HOREG", 39 | "FOREG", 40 | "HFOREG", 41 | "SOREG", 42 | "ROREG", 43 | "SROREG", 44 | "LOREG", 45 | "PC", 46 | "SP", 47 | "HREG", 48 | "ADDR", 49 | "C_TLS_LE", 50 | "C_TLS_IE", 51 | "TEXTSIZE", 52 | "GOK", 53 | "NCLASS", 54 | "SCOND = (1<<4)-1", 55 | "SBIT = 1<<4", 56 | "PBIT = 1<<5", 57 | "WBIT = 1<<6", 58 | "FBIT = 1<<7", 59 | "UBIT = 1<<7", 60 | "SCOND_XOR = 14", 61 | "SCOND_EQ = 0 ^ C_SCOND_XOR", 62 | "SCOND_NE = 1 ^ C_SCOND_XOR", 63 | "SCOND_HS = 2 ^ C_SCOND_XOR", 64 | "SCOND_LO = 3 ^ C_SCOND_XOR", 65 | "SCOND_MI = 4 ^ C_SCOND_XOR", 66 | "SCOND_PL = 5 ^ C_SCOND_XOR", 67 | "SCOND_VS = 6 ^ C_SCOND_XOR", 68 | "SCOND_VC = 7 ^ C_SCOND_XOR", 69 | "SCOND_HI = 8 ^ C_SCOND_XOR", 70 | "SCOND_LS = 9 ^ C_SCOND_XOR", 71 | "SCOND_GE = 10 ^ C_SCOND_XOR", 72 | "SCOND_LT = 11 ^ C_SCOND_XOR", 73 | "SCOND_GT = 12 ^ C_SCOND_XOR", 74 | "SCOND_LE = 13 ^ C_SCOND_XOR", 75 | "SCOND_NONE = 14 ^ C_SCOND_XOR", 76 | "SCOND_NV = 15 ^ C_SCOND_XOR", 77 | } 78 | -------------------------------------------------------------------------------- /asm/arch/s390x.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file encapsulates some of the odd characteristics of the 6 | // s390x instruction set, to minimize its interaction 7 | // with the core of the assembler. 8 | 9 | package arch 10 | 11 | import ( 12 | "github.com/twitchyliquid64/golang-asm/obj/s390x" 13 | ) 14 | 15 | func jumpS390x(word string) bool { 16 | switch word { 17 | case "BRC", 18 | "BC", 19 | "BCL", 20 | "BEQ", 21 | "BGE", 22 | "BGT", 23 | "BL", 24 | "BLE", 25 | "BLEU", 26 | "BLT", 27 | "BLTU", 28 | "BNE", 29 | "BR", 30 | "BVC", 31 | "BVS", 32 | "BRCT", 33 | "BRCTG", 34 | "CMPBEQ", 35 | "CMPBGE", 36 | "CMPBGT", 37 | "CMPBLE", 38 | "CMPBLT", 39 | "CMPBNE", 40 | "CMPUBEQ", 41 | "CMPUBGE", 42 | "CMPUBGT", 43 | "CMPUBLE", 44 | "CMPUBLT", 45 | "CMPUBNE", 46 | "CRJ", 47 | "CGRJ", 48 | "CLRJ", 49 | "CLGRJ", 50 | "CIJ", 51 | "CGIJ", 52 | "CLIJ", 53 | "CLGIJ", 54 | "CALL", 55 | "JMP": 56 | return true 57 | } 58 | return false 59 | } 60 | 61 | func s390xRegisterNumber(name string, n int16) (int16, bool) { 62 | switch name { 63 | case "AR": 64 | if 0 <= n && n <= 15 { 65 | return s390x.REG_AR0 + n, true 66 | } 67 | case "F": 68 | if 0 <= n && n <= 15 { 69 | return s390x.REG_F0 + n, true 70 | } 71 | case "R": 72 | if 0 <= n && n <= 15 { 73 | return s390x.REG_R0 + n, true 74 | } 75 | case "V": 76 | if 0 <= n && n <= 31 { 77 | return s390x.REG_V0 + n, true 78 | } 79 | } 80 | return 0, false 81 | } 82 | -------------------------------------------------------------------------------- /obj/textflag.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file defines flags attached to various functions 6 | // and data objects. The compilers, assemblers, and linker must 7 | // all agree on these values. 8 | 9 | package obj 10 | 11 | const ( 12 | // Don't profile the marked routine. 13 | // 14 | // Deprecated: Not implemented, do not use. 15 | NOPROF = 1 16 | 17 | // It is ok for the linker to get multiple of these symbols. It will 18 | // pick one of the duplicates to use. 19 | DUPOK = 2 20 | 21 | // Don't insert stack check preamble. 22 | NOSPLIT = 4 23 | 24 | // Put this data in a read-only section. 25 | RODATA = 8 26 | 27 | // This data contains no pointers. 28 | NOPTR = 16 29 | 30 | // This is a wrapper function and should not count as disabling 'recover'. 31 | WRAPPER = 32 32 | 33 | // This function uses its incoming context register. 34 | NEEDCTXT = 64 35 | 36 | // When passed to ggloblsym, causes Local to be set to true on the LSym it creates. 37 | LOCAL = 128 38 | 39 | // Allocate a word of thread local storage and store the offset from the 40 | // thread local base to the thread local storage in this variable. 41 | TLSBSS = 256 42 | 43 | // Do not insert instructions to allocate a stack frame for this function. 44 | // Only valid on functions that declare a frame size of 0. 45 | // TODO(mwhudson): only implemented for ppc64x at present. 46 | NOFRAME = 512 47 | 48 | // Function can call reflect.Type.Method or reflect.Type.MethodByName. 49 | REFLECTMETHOD = 1024 50 | 51 | // Function is the top of the call stack. Call stack unwinders should stop 52 | // at this function. 53 | TOPFRAME = 2048 54 | ) 55 | -------------------------------------------------------------------------------- /obj/arm64/anames7.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package arm64 6 | 7 | // This order should be strictly consistent to that in a.out.go 8 | var cnames7 = []string{ 9 | "NONE", 10 | "REG", 11 | "RSP", 12 | "FREG", 13 | "VREG", 14 | "PAIR", 15 | "SHIFT", 16 | "EXTREG", 17 | "SPR", 18 | "COND", 19 | "ARNG", 20 | "ELEM", 21 | "LIST", 22 | "ZCON", 23 | "ABCON0", 24 | "ADDCON0", 25 | "ABCON", 26 | "AMCON", 27 | "ADDCON", 28 | "MBCON", 29 | "MOVCON", 30 | "BITCON", 31 | "ADDCON2", 32 | "LCON", 33 | "MOVCON2", 34 | "MOVCON3", 35 | "VCON", 36 | "FCON", 37 | "VCONADDR", 38 | "AACON", 39 | "AACON2", 40 | "LACON", 41 | "AECON", 42 | "SBRA", 43 | "LBRA", 44 | "ZAUTO", 45 | "NSAUTO_8", 46 | "NSAUTO_4", 47 | "NSAUTO", 48 | "NPAUTO", 49 | "NAUTO4K", 50 | "PSAUTO_8", 51 | "PSAUTO_4", 52 | "PSAUTO", 53 | "PPAUTO", 54 | "UAUTO4K_8", 55 | "UAUTO4K_4", 56 | "UAUTO4K_2", 57 | "UAUTO4K", 58 | "UAUTO8K_8", 59 | "UAUTO8K_4", 60 | "UAUTO8K", 61 | "UAUTO16K_8", 62 | "UAUTO16K", 63 | "UAUTO32K", 64 | "LAUTO", 65 | "SEXT1", 66 | "SEXT2", 67 | "SEXT4", 68 | "SEXT8", 69 | "SEXT16", 70 | "LEXT", 71 | "ZOREG", 72 | "NSOREG_8", 73 | "NSOREG_4", 74 | "NSOREG", 75 | "NPOREG", 76 | "NOREG4K", 77 | "PSOREG_8", 78 | "PSOREG_4", 79 | "PSOREG", 80 | "PPOREG", 81 | "UOREG4K_8", 82 | "UOREG4K_4", 83 | "UOREG4K_2", 84 | "UOREG4K", 85 | "UOREG8K_8", 86 | "UOREG8K_4", 87 | "UOREG8K", 88 | "UOREG16K_8", 89 | "UOREG16K", 90 | "UOREG32K", 91 | "LOREG", 92 | "ADDR", 93 | "GOTADDR", 94 | "TLS_LE", 95 | "TLS_IE", 96 | "ROFF", 97 | "GOK", 98 | "TEXTSIZE", 99 | "NCLASS", 100 | } 101 | -------------------------------------------------------------------------------- /bio/buf_mmap.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build darwin dragonfly freebsd linux netbsd openbsd 6 | 7 | package bio 8 | 9 | import ( 10 | "runtime" 11 | "sync/atomic" 12 | "syscall" 13 | ) 14 | 15 | // mmapLimit is the maximum number of mmaped regions to create before 16 | // falling back to reading into a heap-allocated slice. This exists 17 | // because some operating systems place a limit on the number of 18 | // distinct mapped regions per process. As of this writing: 19 | // 20 | // Darwin unlimited 21 | // DragonFly 1000000 (vm.max_proc_mmap) 22 | // FreeBSD unlimited 23 | // Linux 65530 (vm.max_map_count) // TODO: query /proc/sys/vm/max_map_count? 24 | // NetBSD unlimited 25 | // OpenBSD unlimited 26 | var mmapLimit int32 = 1<<31 - 1 27 | 28 | func init() { 29 | // Linux is the only practically concerning OS. 30 | if runtime.GOOS == "linux" { 31 | mmapLimit = 30000 32 | } 33 | } 34 | 35 | func (r *Reader) sliceOS(length uint64) ([]byte, bool) { 36 | // For small slices, don't bother with the overhead of a 37 | // mapping, especially since we have no way to unmap it. 38 | const threshold = 16 << 10 39 | if length < threshold { 40 | return nil, false 41 | } 42 | 43 | // Have we reached the mmap limit? 44 | if atomic.AddInt32(&mmapLimit, -1) < 0 { 45 | atomic.AddInt32(&mmapLimit, 1) 46 | return nil, false 47 | } 48 | 49 | // Page-align the offset. 50 | off := r.Offset() 51 | align := syscall.Getpagesize() 52 | aoff := off &^ int64(align-1) 53 | 54 | data, err := syscall.Mmap(int(r.f.Fd()), aoff, int(length+uint64(off-aoff)), syscall.PROT_READ, syscall.MAP_SHARED|syscall.MAP_FILE) 55 | if err != nil { 56 | return nil, false 57 | } 58 | 59 | data = data[off-aoff:] 60 | r.MustSeek(int64(length), 1) 61 | return data, true 62 | } 63 | -------------------------------------------------------------------------------- /objabi/autotype.go: -------------------------------------------------------------------------------- 1 | // Derived from Inferno utils/6l/l.h and related files. 2 | // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/l.h 3 | // 4 | // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 | // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 | // Portions Copyright © 1997-1999 Vita Nuova Limited 7 | // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 | // Portions Copyright © 2004,2006 Bruce Ellis 9 | // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 | // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 | // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 | // 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy 14 | // of this software and associated documentation files (the "Software"), to deal 15 | // in the Software without restriction, including without limitation the rights 16 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | // copies of the Software, and to permit persons to whom the Software is 18 | // furnished to do so, subject to the following conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be included in 21 | // all copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 | // THE SOFTWARE. 30 | 31 | package objabi 32 | 33 | // Auto.name 34 | const ( 35 | A_AUTO = 1 + iota 36 | A_PARAM 37 | A_DELETED_AUTO 38 | ) 39 | -------------------------------------------------------------------------------- /objabi/funcdata.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package objabi 6 | 7 | // This file defines the IDs for PCDATA and FUNCDATA instructions 8 | // in Go binaries. 9 | // 10 | // These must agree with ../../../runtime/funcdata.h and 11 | // ../../../runtime/symtab.go. 12 | 13 | const ( 14 | PCDATA_RegMapIndex = 0 // if !go115ReduceLiveness 15 | PCDATA_UnsafePoint = 0 // if go115ReduceLiveness 16 | PCDATA_StackMapIndex = 1 17 | PCDATA_InlTreeIndex = 2 18 | 19 | FUNCDATA_ArgsPointerMaps = 0 20 | FUNCDATA_LocalsPointerMaps = 1 21 | FUNCDATA_RegPointerMaps = 2 // if !go115ReduceLiveness 22 | FUNCDATA_StackObjects = 3 23 | FUNCDATA_InlTree = 4 24 | FUNCDATA_OpenCodedDeferInfo = 5 25 | 26 | // ArgsSizeUnknown is set in Func.argsize to mark all functions 27 | // whose argument size is unknown (C vararg functions, and 28 | // assembly code without an explicit specification). 29 | // This value is generated by the compiler, assembler, or linker. 30 | ArgsSizeUnknown = -0x80000000 31 | ) 32 | 33 | // Special PCDATA values. 34 | const ( 35 | // PCDATA_RegMapIndex values. 36 | // 37 | // Only if !go115ReduceLiveness. 38 | PCDATA_RegMapUnsafe = PCDATA_UnsafePointUnsafe // Unsafe for async preemption 39 | 40 | // PCDATA_UnsafePoint values. 41 | PCDATA_UnsafePointSafe = -1 // Safe for async preemption 42 | PCDATA_UnsafePointUnsafe = -2 // Unsafe for async preemption 43 | 44 | // PCDATA_Restart1(2) apply on a sequence of instructions, within 45 | // which if an async preemption happens, we should back off the PC 46 | // to the start of the sequence when resuming. 47 | // We need two so we can distinguish the start/end of the sequence 48 | // in case that two sequences are next to each other. 49 | PCDATA_Restart1 = -3 50 | PCDATA_Restart2 = -4 51 | 52 | // Like PCDATA_Restart1, but back to function entry if async preempted. 53 | PCDATA_RestartAtEntry = -5 54 | ) 55 | -------------------------------------------------------------------------------- /asm/arch/mips.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file encapsulates some of the odd characteristics of the 6 | // MIPS (MIPS64) instruction set, to minimize its interaction 7 | // with the core of the assembler. 8 | 9 | package arch 10 | 11 | import ( 12 | "github.com/twitchyliquid64/golang-asm/obj" 13 | "github.com/twitchyliquid64/golang-asm/obj/mips" 14 | ) 15 | 16 | func jumpMIPS(word string) bool { 17 | switch word { 18 | case "BEQ", "BFPF", "BFPT", "BGEZ", "BGEZAL", "BGTZ", "BLEZ", "BLTZ", "BLTZAL", "BNE", "JMP", "JAL", "CALL": 19 | return true 20 | } 21 | return false 22 | } 23 | 24 | // IsMIPSCMP reports whether the op (as defined by an mips.A* constant) is 25 | // one of the CMP instructions that require special handling. 26 | func IsMIPSCMP(op obj.As) bool { 27 | switch op { 28 | case mips.ACMPEQF, mips.ACMPEQD, mips.ACMPGEF, mips.ACMPGED, 29 | mips.ACMPGTF, mips.ACMPGTD: 30 | return true 31 | } 32 | return false 33 | } 34 | 35 | // IsMIPSMUL reports whether the op (as defined by an mips.A* constant) is 36 | // one of the MUL/DIV/REM/MADD/MSUB instructions that require special handling. 37 | func IsMIPSMUL(op obj.As) bool { 38 | switch op { 39 | case mips.AMUL, mips.AMULU, mips.AMULV, mips.AMULVU, 40 | mips.ADIV, mips.ADIVU, mips.ADIVV, mips.ADIVVU, 41 | mips.AREM, mips.AREMU, mips.AREMV, mips.AREMVU, 42 | mips.AMADD, mips.AMSUB: 43 | return true 44 | } 45 | return false 46 | } 47 | 48 | func mipsRegisterNumber(name string, n int16) (int16, bool) { 49 | switch name { 50 | case "F": 51 | if 0 <= n && n <= 31 { 52 | return mips.REG_F0 + n, true 53 | } 54 | case "FCR": 55 | if 0 <= n && n <= 31 { 56 | return mips.REG_FCR0 + n, true 57 | } 58 | case "M": 59 | if 0 <= n && n <= 31 { 60 | return mips.REG_M0 + n, true 61 | } 62 | case "R": 63 | if 0 <= n && n <= 31 { 64 | return mips.REG_R0 + n, true 65 | } 66 | case "W": 67 | if 0 <= n && n <= 31 { 68 | return mips.REG_W0 + n, true 69 | } 70 | } 71 | return 0, false 72 | } 73 | -------------------------------------------------------------------------------- /obj/mips/anames.go: -------------------------------------------------------------------------------- 1 | // Code generated by stringer -i a.out.go -o anames.go -p mips; DO NOT EDIT. 2 | 3 | package mips 4 | 5 | import "github.com/twitchyliquid64/golang-asm/obj" 6 | 7 | var Anames = []string{ 8 | obj.A_ARCHSPECIFIC: "ABSD", 9 | "ABSF", 10 | "ABSW", 11 | "ADD", 12 | "ADDD", 13 | "ADDF", 14 | "ADDU", 15 | "ADDW", 16 | "AND", 17 | "BEQ", 18 | "BFPF", 19 | "BFPT", 20 | "BGEZ", 21 | "BGEZAL", 22 | "BGTZ", 23 | "BLEZ", 24 | "BLTZ", 25 | "BLTZAL", 26 | "BNE", 27 | "BREAK", 28 | "CLO", 29 | "CLZ", 30 | "CMOVF", 31 | "CMOVN", 32 | "CMOVT", 33 | "CMOVZ", 34 | "CMPEQD", 35 | "CMPEQF", 36 | "CMPGED", 37 | "CMPGEF", 38 | "CMPGTD", 39 | "CMPGTF", 40 | "DIV", 41 | "DIVD", 42 | "DIVF", 43 | "DIVU", 44 | "DIVW", 45 | "GOK", 46 | "LL", 47 | "LLV", 48 | "LUI", 49 | "MADD", 50 | "MOVB", 51 | "MOVBU", 52 | "MOVD", 53 | "MOVDF", 54 | "MOVDW", 55 | "MOVF", 56 | "MOVFD", 57 | "MOVFW", 58 | "MOVH", 59 | "MOVHU", 60 | "MOVW", 61 | "MOVWD", 62 | "MOVWF", 63 | "MOVWL", 64 | "MOVWR", 65 | "MSUB", 66 | "MUL", 67 | "MULD", 68 | "MULF", 69 | "MULU", 70 | "MULW", 71 | "NEGD", 72 | "NEGF", 73 | "NEGW", 74 | "NEGV", 75 | "NOOP", 76 | "NOR", 77 | "OR", 78 | "REM", 79 | "REMU", 80 | "RFE", 81 | "SC", 82 | "SCV", 83 | "SGT", 84 | "SGTU", 85 | "SLL", 86 | "SQRTD", 87 | "SQRTF", 88 | "SRA", 89 | "SRL", 90 | "SUB", 91 | "SUBD", 92 | "SUBF", 93 | "SUBU", 94 | "SUBW", 95 | "SYNC", 96 | "SYSCALL", 97 | "TEQ", 98 | "TLBP", 99 | "TLBR", 100 | "TLBWI", 101 | "TLBWR", 102 | "TNE", 103 | "WORD", 104 | "XOR", 105 | "MOVV", 106 | "MOVVL", 107 | "MOVVR", 108 | "SLLV", 109 | "SRAV", 110 | "SRLV", 111 | "DIVV", 112 | "DIVVU", 113 | "REMV", 114 | "REMVU", 115 | "MULV", 116 | "MULVU", 117 | "ADDV", 118 | "ADDVU", 119 | "SUBV", 120 | "SUBVU", 121 | "TRUNCFV", 122 | "TRUNCDV", 123 | "TRUNCFW", 124 | "TRUNCDW", 125 | "MOVWU", 126 | "MOVFV", 127 | "MOVDV", 128 | "MOVVF", 129 | "MOVVD", 130 | "VMOVB", 131 | "VMOVH", 132 | "VMOVW", 133 | "VMOVD", 134 | "LAST", 135 | } 136 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | name: Test 3 | jobs: 4 | test: 5 | strategy: 6 | matrix: 7 | go-version: [1.14.x, 1.15.x] 8 | os: [ubuntu-latest, macos-latest, windows-latest] 9 | runs-on: ${{ matrix.os }} 10 | steps: 11 | - name: Install Go 12 | uses: actions/setup-go@v2 13 | with: 14 | go-version: ${{ matrix.go-version }} 15 | - name: Checkout code 16 | uses: actions/checkout@v2 17 | - name: Test 18 | run: go test ./... 19 | 20 | # Copyright (c) 2019, Daniel Martí. All rights reserved. 21 | # 22 | # Redistribution and use in source and binary forms, with or without 23 | # modification, are permitted provided that the following conditions are 24 | # met: 25 | # 26 | # * Redistributions of source code must retain the above copyright 27 | # notice, this list of conditions and the following disclaimer. 28 | # * Redistributions in binary form must reproduce the above 29 | # copyright notice, this list of conditions and the following disclaimer 30 | # in the documentation and/or other materials provided with the 31 | # distribution. 32 | # * Neither the name of the copyright holder nor the names of its 33 | # contributors may be used to endorse or promote products derived from 34 | # this software without specific prior written permission. 35 | # 36 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 37 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 38 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 39 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 40 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 42 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 43 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 44 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 45 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 46 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 47 | -------------------------------------------------------------------------------- /obj/arm/anames.go: -------------------------------------------------------------------------------- 1 | // Code generated by stringer -i a.out.go -o anames.go -p arm; DO NOT EDIT. 2 | 3 | package arm 4 | 5 | import "github.com/twitchyliquid64/golang-asm/obj" 6 | 7 | var Anames = []string{ 8 | obj.A_ARCHSPECIFIC: "AND", 9 | "EOR", 10 | "SUB", 11 | "RSB", 12 | "ADD", 13 | "ADC", 14 | "SBC", 15 | "RSC", 16 | "TST", 17 | "TEQ", 18 | "CMP", 19 | "CMN", 20 | "ORR", 21 | "BIC", 22 | "MVN", 23 | "BEQ", 24 | "BNE", 25 | "BCS", 26 | "BHS", 27 | "BCC", 28 | "BLO", 29 | "BMI", 30 | "BPL", 31 | "BVS", 32 | "BVC", 33 | "BHI", 34 | "BLS", 35 | "BGE", 36 | "BLT", 37 | "BGT", 38 | "BLE", 39 | "MOVWD", 40 | "MOVWF", 41 | "MOVDW", 42 | "MOVFW", 43 | "MOVFD", 44 | "MOVDF", 45 | "MOVF", 46 | "MOVD", 47 | "CMPF", 48 | "CMPD", 49 | "ADDF", 50 | "ADDD", 51 | "SUBF", 52 | "SUBD", 53 | "MULF", 54 | "MULD", 55 | "NMULF", 56 | "NMULD", 57 | "MULAF", 58 | "MULAD", 59 | "NMULAF", 60 | "NMULAD", 61 | "MULSF", 62 | "MULSD", 63 | "NMULSF", 64 | "NMULSD", 65 | "FMULAF", 66 | "FMULAD", 67 | "FNMULAF", 68 | "FNMULAD", 69 | "FMULSF", 70 | "FMULSD", 71 | "FNMULSF", 72 | "FNMULSD", 73 | "DIVF", 74 | "DIVD", 75 | "SQRTF", 76 | "SQRTD", 77 | "ABSF", 78 | "ABSD", 79 | "NEGF", 80 | "NEGD", 81 | "SRL", 82 | "SRA", 83 | "SLL", 84 | "MULU", 85 | "DIVU", 86 | "MUL", 87 | "MMUL", 88 | "DIV", 89 | "MOD", 90 | "MODU", 91 | "DIVHW", 92 | "DIVUHW", 93 | "MOVB", 94 | "MOVBS", 95 | "MOVBU", 96 | "MOVH", 97 | "MOVHS", 98 | "MOVHU", 99 | "MOVW", 100 | "MOVM", 101 | "SWPBU", 102 | "SWPW", 103 | "RFE", 104 | "SWI", 105 | "MULA", 106 | "MULS", 107 | "MMULA", 108 | "MMULS", 109 | "WORD", 110 | "MULL", 111 | "MULAL", 112 | "MULLU", 113 | "MULALU", 114 | "BX", 115 | "BXRET", 116 | "DWORD", 117 | "LDREX", 118 | "STREX", 119 | "LDREXD", 120 | "STREXD", 121 | "DMB", 122 | "PLD", 123 | "CLZ", 124 | "REV", 125 | "REV16", 126 | "REVSH", 127 | "RBIT", 128 | "XTAB", 129 | "XTAH", 130 | "XTABU", 131 | "XTAHU", 132 | "BFX", 133 | "BFXU", 134 | "BFC", 135 | "BFI", 136 | "MULWT", 137 | "MULWB", 138 | "MULBB", 139 | "MULAWT", 140 | "MULAWB", 141 | "MULABB", 142 | "MRC", 143 | "LAST", 144 | } 145 | -------------------------------------------------------------------------------- /obj/riscv/testdata/testbranch/branch_test.s: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build riscv64 6 | 7 | #include "textflag.h" 8 | 9 | // func testBEQZ(a int64) (r bool) 10 | TEXT ·testBEQZ(SB),NOSPLIT,$0-0 11 | MOV a+0(FP), X5 12 | MOV $1, X6 13 | BEQZ X5, b 14 | MOV $0, X6 15 | b: 16 | MOV X6, r+8(FP) 17 | RET 18 | 19 | // func testBGEZ(a int64) (r bool) 20 | TEXT ·testBGEZ(SB),NOSPLIT,$0-0 21 | MOV a+0(FP), X5 22 | MOV $1, X6 23 | BGEZ X5, b 24 | MOV $0, X6 25 | b: 26 | MOV X6, r+8(FP) 27 | RET 28 | 29 | // func testBGT(a, b int64) (r bool) 30 | TEXT ·testBGT(SB),NOSPLIT,$0-0 31 | MOV a+0(FP), X5 32 | MOV b+8(FP), X6 33 | MOV $1, X7 34 | BGT X5, X6, b 35 | MOV $0, X7 36 | b: 37 | MOV X7, r+16(FP) 38 | RET 39 | 40 | // func testBGTU(a, b int64) (r bool) 41 | TEXT ·testBGTU(SB),NOSPLIT,$0-0 42 | MOV a+0(FP), X5 43 | MOV b+8(FP), X6 44 | MOV $1, X7 45 | BGTU X5, X6, b 46 | MOV $0, X7 47 | b: 48 | MOV X7, r+16(FP) 49 | RET 50 | 51 | // func testBGTZ(a int64) (r bool) 52 | TEXT ·testBGTZ(SB),NOSPLIT,$0-0 53 | MOV a+0(FP), X5 54 | MOV $1, X6 55 | BGTZ X5, b 56 | MOV $0, X6 57 | b: 58 | MOV X6, r+8(FP) 59 | RET 60 | 61 | // func testBLE(a, b int64) (r bool) 62 | TEXT ·testBLE(SB),NOSPLIT,$0-0 63 | MOV a+0(FP), X5 64 | MOV b+8(FP), X6 65 | MOV $1, X7 66 | BLE X5, X6, b 67 | MOV $0, X7 68 | b: 69 | MOV X7, r+16(FP) 70 | RET 71 | 72 | // func testBLEU(a, b int64) (r bool) 73 | TEXT ·testBLEU(SB),NOSPLIT,$0-0 74 | MOV a+0(FP), X5 75 | MOV b+8(FP), X6 76 | MOV $1, X7 77 | BLEU X5, X6, b 78 | MOV $0, X7 79 | b: 80 | MOV X7, r+16(FP) 81 | RET 82 | 83 | // func testBLEZ(a int64) (r bool) 84 | TEXT ·testBLEZ(SB),NOSPLIT,$0-0 85 | MOV a+0(FP), X5 86 | MOV $1, X6 87 | BLEZ X5, b 88 | MOV $0, X6 89 | b: 90 | MOV X6, r+8(FP) 91 | RET 92 | 93 | // func testBLTZ(a int64) (r bool) 94 | TEXT ·testBLTZ(SB),NOSPLIT,$0-0 95 | MOV a+0(FP), X5 96 | MOV $1, X6 97 | BLTZ X5, b 98 | MOV $0, X6 99 | b: 100 | MOV X6, r+8(FP) 101 | RET 102 | 103 | // func testBNEZ(a int64) (r bool) 104 | TEXT ·testBNEZ(SB),NOSPLIT,$0-0 105 | MOV a+0(FP), X5 106 | MOV $1, X6 107 | BNEZ X5, b 108 | MOV $0, X6 109 | b: 110 | MOV X6, r+8(FP) 111 | RET 112 | -------------------------------------------------------------------------------- /obj/s390x/listz.go: -------------------------------------------------------------------------------- 1 | // Based on cmd/internal/obj/ppc64/list9.go. 2 | // 3 | // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 4 | // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 5 | // Portions Copyright © 1997-1999 Vita Nuova Limited 6 | // Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com) 7 | // Portions Copyright © 2004,2006 Bruce Ellis 8 | // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 9 | // Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others 10 | // Portions Copyright © 2009 The Go Authors. All rights reserved. 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining a copy 13 | // of this software and associated documentation files (the "Software"), to deal 14 | // in the Software without restriction, including without limitation the rights 15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the Software is 17 | // furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in 20 | // all copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | // THE SOFTWARE. 29 | 30 | package s390x 31 | 32 | import ( 33 | "github.com/twitchyliquid64/golang-asm/obj" 34 | "fmt" 35 | ) 36 | 37 | func init() { 38 | obj.RegisterRegister(obj.RBaseS390X, REG_R0+1024, rconv) 39 | obj.RegisterOpcode(obj.ABaseS390X, Anames) 40 | } 41 | 42 | func rconv(r int) string { 43 | if r == 0 { 44 | return "NONE" 45 | } 46 | if r == REGG { 47 | // Special case. 48 | return "g" 49 | } 50 | if REG_R0 <= r && r <= REG_R15 { 51 | return fmt.Sprintf("R%d", r-REG_R0) 52 | } 53 | if REG_F0 <= r && r <= REG_F15 { 54 | return fmt.Sprintf("F%d", r-REG_F0) 55 | } 56 | if REG_AR0 <= r && r <= REG_AR15 { 57 | return fmt.Sprintf("AR%d", r-REG_AR0) 58 | } 59 | if REG_V0 <= r && r <= REG_V31 { 60 | return fmt.Sprintf("V%d", r-REG_V0) 61 | } 62 | return fmt.Sprintf("Rgok(%d)", r-obj.RBaseS390X) 63 | } 64 | 65 | func DRconv(a int) string { 66 | s := "C_??" 67 | if a >= C_NONE && a <= C_NCLASS { 68 | s = cnamesz[a] 69 | } 70 | var fp string 71 | fp += s 72 | return fp 73 | } 74 | -------------------------------------------------------------------------------- /obj/stringer.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build ignore 6 | 7 | // This is a mini version of the stringer tool customized for the Anames table 8 | // in the architecture support for obj. 9 | // This version just generates the slice of strings, not the String method. 10 | 11 | package main 12 | 13 | import ( 14 | "bufio" 15 | "flag" 16 | "fmt" 17 | "log" 18 | "os" 19 | "regexp" 20 | "strings" 21 | ) 22 | 23 | var ( 24 | input = flag.String("i", "", "input file name") 25 | output = flag.String("o", "", "output file name") 26 | pkg = flag.String("p", "", "package name") 27 | ) 28 | 29 | var Are = regexp.MustCompile(`^\tA([A-Za-z0-9]+)`) 30 | 31 | func main() { 32 | flag.Parse() 33 | if *input == "" || *output == "" || *pkg == "" { 34 | flag.Usage() 35 | os.Exit(2) 36 | } 37 | in, err := os.Open(*input) 38 | if err != nil { 39 | log.Fatal(err) 40 | } 41 | fd, err := os.Create(*output) 42 | if err != nil { 43 | log.Fatal(err) 44 | } 45 | out := bufio.NewWriter(fd) 46 | defer out.Flush() 47 | var on = false 48 | s := bufio.NewScanner(in) 49 | first := true 50 | for s.Scan() { 51 | line := s.Text() 52 | if !on { 53 | // First relevant line contains "= obj.ABase". 54 | // If we find it, delete the = so we don't stop immediately. 55 | const prefix = "= obj.ABase" 56 | index := strings.Index(line, prefix) 57 | if index < 0 { 58 | continue 59 | } 60 | // It's on. Start with the header. 61 | fmt.Fprintf(out, header, *input, *output, *pkg, *pkg) 62 | on = true 63 | line = line[:index] 64 | } 65 | // Strip comments so their text won't defeat our heuristic. 66 | index := strings.Index(line, "//") 67 | if index > 0 { 68 | line = line[:index] 69 | } 70 | index = strings.Index(line, "/*") 71 | if index > 0 { 72 | line = line[:index] 73 | } 74 | // Termination condition: Any line with an = changes the sequence, 75 | // so stop there, and stop at a closing brace. 76 | if strings.HasPrefix(line, "}") || strings.ContainsRune(line, '=') { 77 | break 78 | } 79 | sub := Are.FindStringSubmatch(line) 80 | if len(sub) < 2 { 81 | continue 82 | } 83 | if first { 84 | fmt.Fprintf(out, "\tobj.A_ARCHSPECIFIC: %q,\n", sub[1]) 85 | first = false 86 | } else { 87 | fmt.Fprintf(out, "\t%q,\n", sub[1]) 88 | } 89 | } 90 | fmt.Fprintln(out, "}") 91 | if s.Err() != nil { 92 | log.Fatal(err) 93 | } 94 | } 95 | 96 | const header = `// Code generated by stringer -i %s -o %s -p %s; DO NOT EDIT. 97 | 98 | package %s 99 | 100 | import "github.com/twitchyliquid64/golang-asm/obj" 101 | 102 | var Anames = []string{ 103 | ` 104 | -------------------------------------------------------------------------------- /obj/mips/list0.go: -------------------------------------------------------------------------------- 1 | // cmd/9l/list.c from Vita Nuova. 2 | // 3 | // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 4 | // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 5 | // Portions Copyright © 1997-1999 Vita Nuova Limited 6 | // Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com) 7 | // Portions Copyright © 2004,2006 Bruce Ellis 8 | // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 9 | // Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others 10 | // Portions Copyright © 2009 The Go Authors. All rights reserved. 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining a copy 13 | // of this software and associated documentation files (the "Software"), to deal 14 | // in the Software without restriction, including without limitation the rights 15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the Software is 17 | // furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in 20 | // all copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | // THE SOFTWARE. 29 | 30 | package mips 31 | 32 | import ( 33 | "github.com/twitchyliquid64/golang-asm/obj" 34 | "fmt" 35 | ) 36 | 37 | func init() { 38 | obj.RegisterRegister(obj.RBaseMIPS, REG_LAST+1, rconv) 39 | obj.RegisterOpcode(obj.ABaseMIPS, Anames) 40 | } 41 | 42 | func rconv(r int) string { 43 | if r == 0 { 44 | return "NONE" 45 | } 46 | if r == REGG { 47 | // Special case. 48 | return "g" 49 | } 50 | if REG_R0 <= r && r <= REG_R31 { 51 | return fmt.Sprintf("R%d", r-REG_R0) 52 | } 53 | if REG_F0 <= r && r <= REG_F31 { 54 | return fmt.Sprintf("F%d", r-REG_F0) 55 | } 56 | if REG_M0 <= r && r <= REG_M31 { 57 | return fmt.Sprintf("M%d", r-REG_M0) 58 | } 59 | if REG_FCR0 <= r && r <= REG_FCR31 { 60 | return fmt.Sprintf("FCR%d", r-REG_FCR0) 61 | } 62 | if REG_W0 <= r && r <= REG_W31 { 63 | return fmt.Sprintf("W%d", r-REG_W0) 64 | } 65 | if r == REG_HI { 66 | return "HI" 67 | } 68 | if r == REG_LO { 69 | return "LO" 70 | } 71 | 72 | return fmt.Sprintf("Rgok(%d)", r-obj.RBaseMIPS) 73 | } 74 | 75 | func DRconv(a int) string { 76 | s := "C_??" 77 | if a >= C_NONE && a <= C_NCLASS { 78 | s = cnames0[a] 79 | } 80 | var fp string 81 | fp += s 82 | return fp 83 | } 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # golang-asm 2 | 3 | A mirror of the assembler from the Go compiler, with import paths re-written for the assembler to be functional as a standalone library. 4 | 5 | License as per the Go project. 6 | 7 | # Status 8 | 9 | Works, but expect to dig into the assembler godoc's to work out what to set different parameters of `obj.Prog` to get it to generate specific instructions. 10 | 11 | # Example 12 | 13 | Demonstrates assembly of a NOP & an ADD instruction on x86-64. 14 | 15 | ```go 16 | 17 | package main 18 | 19 | import ( 20 | "fmt" 21 | 22 | asm "github.com/twitchyliquid64/golang-asm" 23 | "github.com/twitchyliquid64/golang-asm/obj" 24 | "github.com/twitchyliquid64/golang-asm/obj/x86" 25 | ) 26 | 27 | func noop(builder *asm.Builder) *obj.Prog { 28 | prog := builder.NewProg() 29 | prog.As = x86.ANOPL 30 | prog.From.Type = obj.TYPE_REG 31 | prog.From.Reg = x86.REG_AX 32 | return prog 33 | } 34 | 35 | func addImmediateByte(builder *asm.Builder, in int32) *obj.Prog { 36 | prog := builder.NewProg() 37 | prog.As = x86.AADDB 38 | prog.To.Type = obj.TYPE_REG 39 | prog.To.Reg = x86.REG_AL 40 | prog.From.Type = obj.TYPE_CONST 41 | prog.From.Offset = int64(in) 42 | return prog 43 | } 44 | 45 | func movImmediateByte(builder *asm.Builder, reg int16, in int32) *obj.Prog { 46 | prog := builder.NewProg() 47 | prog.As = x86.AMOVB 48 | prog.To.Type = obj.TYPE_REG 49 | prog.To.Reg = reg 50 | prog.From.Type = obj.TYPE_CONST 51 | prog.From.Offset = int64(in) 52 | return prog 53 | } 54 | 55 | func main() { 56 | b, _ := asm.NewBuilder("amd64", 64) 57 | b.AddInstruction(noop(b)) 58 | b.AddInstruction(movImmediateByte(b, x86.REG_AL, 16)) 59 | b.AddInstruction(addImmediateByte(b, 16)) 60 | fmt.Printf("Bin: %x\n", b.Assemble()) 61 | } 62 | 63 | ``` 64 | 65 | # Working out the parameters of `obj.Prog` 66 | 67 | This took me some time to work out, so I'll write a bit here. 68 | 69 | ## Use these references 70 | 71 | * `obj.Prog` - [godoc](https://godoc.org/github.com/golang/go/src/cmd/internal/obj#Prog) 72 | * Some instructions (like NOP, JMP) are abstract per-platform & can be found [here](https://godoc.org/github.com/golang/go/src/cmd/internal/obj#As) 73 | 74 | * (for amd64) `x86 pkg-constants` - [registers & instructions](https://godoc.org/github.com/golang/go/src/cmd/internal/obj/x86#pkg-constant) 75 | 76 | ## Instruction constants have a naming scheme 77 | 78 | Instructions are defined as constants in the package for the relavant architecture, and have an 'A' prefix and a size suffix. 79 | 80 | For example, the MOV instruction for 64 bits of data is `AMOVQ` (well, at least in amd64). 81 | 82 | ## Search the go source for usage of a given instruction 83 | 84 | For example, if I wanted to work out how to emit the MOV instruction for 64bits, I would search the go source on github for `AMOVQ` or `x86.AMOVQ`. Normally, you see find a few examples where the compiler backend fills in a `obj.Prog` structure, and you follow it's lead. 85 | -------------------------------------------------------------------------------- /obj/ld.go: -------------------------------------------------------------------------------- 1 | // Derived from Inferno utils/6l/obj.c and utils/6l/span.c 2 | // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/obj.c 3 | // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/span.c 4 | // 5 | // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 6 | // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 7 | // Portions Copyright © 1997-1999 Vita Nuova Limited 8 | // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 9 | // Portions Copyright © 2004,2006 Bruce Ellis 10 | // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 11 | // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 12 | // Portions Copyright © 2009 The Go Authors. All rights reserved. 13 | // 14 | // Permission is hereby granted, free of charge, to any person obtaining a copy 15 | // of this software and associated documentation files (the "Software"), to deal 16 | // in the Software without restriction, including without limitation the rights 17 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | // copies of the Software, and to permit persons to whom the Software is 19 | // furnished to do so, subject to the following conditions: 20 | // 21 | // The above copyright notice and this permission notice shall be included in 22 | // all copies or substantial portions of the Software. 23 | // 24 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 30 | // THE SOFTWARE. 31 | 32 | package obj 33 | 34 | /* 35 | * add library to library list. 36 | * srcref: src file referring to package 37 | * objref: object file referring to package 38 | * file: object file, e.g., /home/rsc/go/pkg/container/vector.a 39 | * pkg: package import path, e.g. container/vector 40 | */ 41 | 42 | const ( 43 | LOG = 5 44 | ) 45 | 46 | func mkfwd(sym *LSym) { 47 | var dwn [LOG]int32 48 | var cnt [LOG]int32 49 | var lst [LOG]*Prog 50 | 51 | for i := 0; i < LOG; i++ { 52 | if i == 0 { 53 | cnt[i] = 1 54 | } else { 55 | cnt[i] = LOG * cnt[i-1] 56 | } 57 | dwn[i] = 1 58 | lst[i] = nil 59 | } 60 | 61 | i := 0 62 | for p := sym.Func.Text; p != nil && p.Link != nil; p = p.Link { 63 | i-- 64 | if i < 0 { 65 | i = LOG - 1 66 | } 67 | p.Forwd = nil 68 | dwn[i]-- 69 | if dwn[i] <= 0 { 70 | dwn[i] = cnt[i] 71 | if lst[i] != nil { 72 | lst[i].Forwd = p 73 | } 74 | lst[i] = p 75 | } 76 | } 77 | } 78 | 79 | func Appendp(q *Prog, newprog ProgAlloc) *Prog { 80 | p := newprog() 81 | p.Link = q.Link 82 | q.Link = p 83 | p.Pos = q.Pos 84 | return p 85 | } 86 | -------------------------------------------------------------------------------- /objabi/symkind.go: -------------------------------------------------------------------------------- 1 | // Derived from Inferno utils/6l/l.h and related files. 2 | // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/l.h 3 | // 4 | // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 | // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 | // Portions Copyright © 1997-1999 Vita Nuova Limited 7 | // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 | // Portions Copyright © 2004,2006 Bruce Ellis 9 | // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 | // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 | // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 | // 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy 14 | // of this software and associated documentation files (the "Software"), to deal 15 | // in the Software without restriction, including without limitation the rights 16 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | // copies of the Software, and to permit persons to whom the Software is 18 | // furnished to do so, subject to the following conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be included in 21 | // all copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 | // THE SOFTWARE. 30 | 31 | package objabi 32 | 33 | // A SymKind describes the kind of memory represented by a symbol. 34 | type SymKind uint8 35 | 36 | // Defined SymKind values. 37 | // These are used to index into cmd/link/internal/sym/AbiSymKindToSymKind 38 | // 39 | // TODO(rsc): Give idiomatic Go names. 40 | //go:generate stringer -type=SymKind 41 | const ( 42 | // An otherwise invalid zero value for the type 43 | Sxxx SymKind = iota 44 | // Executable instructions 45 | STEXT 46 | // Read only static data 47 | SRODATA 48 | // Static data that does not contain any pointers 49 | SNOPTRDATA 50 | // Static data 51 | SDATA 52 | // Statically data that is initially all 0s 53 | SBSS 54 | // Statically data that is initially all 0s and does not contain pointers 55 | SNOPTRBSS 56 | // Thread-local data that is initially all 0s 57 | STLSBSS 58 | // Debugging data 59 | SDWARFCUINFO 60 | SDWARFCONST 61 | SDWARFFCN 62 | SDWARFABSFCN 63 | SDWARFTYPE 64 | SDWARFVAR 65 | SDWARFRANGE 66 | SDWARFLOC 67 | SDWARFLINES 68 | // ABI alias. An ABI alias symbol is an empty symbol with a 69 | // single relocation with 0 size that references the native 70 | // function implementation symbol. 71 | // 72 | // TODO(austin): Remove this and all uses once the compiler 73 | // generates real ABI wrappers rather than symbol aliases. 74 | SABIALIAS 75 | // Coverage instrumentation counter for libfuzzer. 76 | SLIBFUZZER_EXTRA_COUNTER 77 | // Update cmd/link/internal/sym/AbiSymKindToSymKind for new SymKind values. 78 | 79 | ) 80 | -------------------------------------------------------------------------------- /objabi/funcid.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package objabi 6 | 7 | // A FuncID identifies particular functions that need to be treated 8 | // specially by the runtime. 9 | // Note that in some situations involving plugins, there may be multiple 10 | // copies of a particular special runtime function. 11 | // Note: this list must match the list in runtime/symtab.go. 12 | type FuncID uint8 13 | 14 | const ( 15 | FuncID_normal FuncID = iota // not a special function 16 | FuncID_runtime_main 17 | FuncID_goexit 18 | FuncID_jmpdefer 19 | FuncID_mcall 20 | FuncID_morestack 21 | FuncID_mstart 22 | FuncID_rt0_go 23 | FuncID_asmcgocall 24 | FuncID_sigpanic 25 | FuncID_runfinq 26 | FuncID_gcBgMarkWorker 27 | FuncID_systemstack_switch 28 | FuncID_systemstack 29 | FuncID_cgocallback_gofunc 30 | FuncID_gogo 31 | FuncID_externalthreadhandler 32 | FuncID_debugCallV1 33 | FuncID_gopanic 34 | FuncID_panicwrap 35 | FuncID_handleAsyncEvent 36 | FuncID_asyncPreempt 37 | FuncID_wrapper // any autogenerated code (hash/eq algorithms, method wrappers, etc.) 38 | ) 39 | 40 | // Get the function ID for the named function in the named file. 41 | // The function should be package-qualified. 42 | func GetFuncID(name string, isWrapper bool) FuncID { 43 | if isWrapper { 44 | return FuncID_wrapper 45 | } 46 | switch name { 47 | case "runtime.main": 48 | return FuncID_runtime_main 49 | case "runtime.goexit": 50 | return FuncID_goexit 51 | case "runtime.jmpdefer": 52 | return FuncID_jmpdefer 53 | case "runtime.mcall": 54 | return FuncID_mcall 55 | case "runtime.morestack": 56 | return FuncID_morestack 57 | case "runtime.mstart": 58 | return FuncID_mstart 59 | case "runtime.rt0_go": 60 | return FuncID_rt0_go 61 | case "runtime.asmcgocall": 62 | return FuncID_asmcgocall 63 | case "runtime.sigpanic": 64 | return FuncID_sigpanic 65 | case "runtime.runfinq": 66 | return FuncID_runfinq 67 | case "runtime.gcBgMarkWorker": 68 | return FuncID_gcBgMarkWorker 69 | case "runtime.systemstack_switch": 70 | return FuncID_systemstack_switch 71 | case "runtime.systemstack": 72 | return FuncID_systemstack 73 | case "runtime.cgocallback_gofunc": 74 | return FuncID_cgocallback_gofunc 75 | case "runtime.gogo": 76 | return FuncID_gogo 77 | case "runtime.externalthreadhandler": 78 | return FuncID_externalthreadhandler 79 | case "runtime.debugCallV1": 80 | return FuncID_debugCallV1 81 | case "runtime.gopanic": 82 | return FuncID_gopanic 83 | case "runtime.panicwrap": 84 | return FuncID_panicwrap 85 | case "runtime.handleAsyncEvent": 86 | return FuncID_handleAsyncEvent 87 | case "runtime.asyncPreempt": 88 | return FuncID_asyncPreempt 89 | case "runtime.deferreturn": 90 | // Don't show in the call stack (used when invoking defer functions) 91 | return FuncID_wrapper 92 | case "runtime.runOpenDeferFrame": 93 | // Don't show in the call stack (used when invoking defer functions) 94 | return FuncID_wrapper 95 | case "runtime.reflectcallSave": 96 | // Don't show in the call stack (used when invoking defer functions) 97 | return FuncID_wrapper 98 | } 99 | return FuncID_normal 100 | } 101 | -------------------------------------------------------------------------------- /obj/ppc64/list9.go: -------------------------------------------------------------------------------- 1 | // cmd/9l/list.c from Vita Nuova. 2 | // 3 | // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 4 | // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 5 | // Portions Copyright © 1997-1999 Vita Nuova Limited 6 | // Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com) 7 | // Portions Copyright © 2004,2006 Bruce Ellis 8 | // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 9 | // Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others 10 | // Portions Copyright © 2009 The Go Authors. All rights reserved. 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining a copy 13 | // of this software and associated documentation files (the "Software"), to deal 14 | // in the Software without restriction, including without limitation the rights 15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the Software is 17 | // furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in 20 | // all copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | // THE SOFTWARE. 29 | 30 | package ppc64 31 | 32 | import ( 33 | "github.com/twitchyliquid64/golang-asm/obj" 34 | "fmt" 35 | ) 36 | 37 | func init() { 38 | obj.RegisterRegister(obj.RBasePPC64, REG_DCR0+1024, rconv) 39 | obj.RegisterOpcode(obj.ABasePPC64, Anames) 40 | } 41 | 42 | func rconv(r int) string { 43 | if r == 0 { 44 | return "NONE" 45 | } 46 | if r == REGG { 47 | // Special case. 48 | return "g" 49 | } 50 | if REG_R0 <= r && r <= REG_R31 { 51 | return fmt.Sprintf("R%d", r-REG_R0) 52 | } 53 | if REG_F0 <= r && r <= REG_F31 { 54 | return fmt.Sprintf("F%d", r-REG_F0) 55 | } 56 | if REG_V0 <= r && r <= REG_V31 { 57 | return fmt.Sprintf("V%d", r-REG_V0) 58 | } 59 | if REG_VS0 <= r && r <= REG_VS63 { 60 | return fmt.Sprintf("VS%d", r-REG_VS0) 61 | } 62 | if REG_CR0 <= r && r <= REG_CR7 { 63 | return fmt.Sprintf("CR%d", r-REG_CR0) 64 | } 65 | if r == REG_CR { 66 | return "CR" 67 | } 68 | if REG_SPR0 <= r && r <= REG_SPR0+1023 { 69 | switch r { 70 | case REG_XER: 71 | return "XER" 72 | 73 | case REG_LR: 74 | return "LR" 75 | 76 | case REG_CTR: 77 | return "CTR" 78 | } 79 | 80 | return fmt.Sprintf("SPR(%d)", r-REG_SPR0) 81 | } 82 | 83 | if REG_DCR0 <= r && r <= REG_DCR0+1023 { 84 | return fmt.Sprintf("DCR(%d)", r-REG_DCR0) 85 | } 86 | if r == REG_FPSCR { 87 | return "FPSCR" 88 | } 89 | if r == REG_MSR { 90 | return "MSR" 91 | } 92 | 93 | return fmt.Sprintf("Rgok(%d)", r-obj.RBasePPC64) 94 | } 95 | 96 | func DRconv(a int) string { 97 | s := "C_??" 98 | if a >= C_NONE && a <= C_NCLASS { 99 | s = cnames9[a] 100 | } 101 | var fp string 102 | fp += s 103 | return fp 104 | } 105 | -------------------------------------------------------------------------------- /objabi/head.go: -------------------------------------------------------------------------------- 1 | // Derived from Inferno utils/6l/l.h and related files. 2 | // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/l.h 3 | // 4 | // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 | // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 | // Portions Copyright © 1997-1999 Vita Nuova Limited 7 | // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 | // Portions Copyright © 2004,2006 Bruce Ellis 9 | // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 | // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 | // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 | // 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy 14 | // of this software and associated documentation files (the "Software"), to deal 15 | // in the Software without restriction, including without limitation the rights 16 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | // copies of the Software, and to permit persons to whom the Software is 18 | // furnished to do so, subject to the following conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be included in 21 | // all copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 | // THE SOFTWARE. 30 | 31 | package objabi 32 | 33 | import "fmt" 34 | 35 | // HeadType is the executable header type. 36 | type HeadType uint8 37 | 38 | const ( 39 | Hunknown HeadType = iota 40 | Hdarwin 41 | Hdragonfly 42 | Hfreebsd 43 | Hjs 44 | Hlinux 45 | Hnetbsd 46 | Hopenbsd 47 | Hplan9 48 | Hsolaris 49 | Hwindows 50 | Haix 51 | ) 52 | 53 | func (h *HeadType) Set(s string) error { 54 | switch s { 55 | case "aix": 56 | *h = Haix 57 | case "darwin": 58 | *h = Hdarwin 59 | case "dragonfly": 60 | *h = Hdragonfly 61 | case "freebsd": 62 | *h = Hfreebsd 63 | case "js": 64 | *h = Hjs 65 | case "linux", "android": 66 | *h = Hlinux 67 | case "netbsd": 68 | *h = Hnetbsd 69 | case "openbsd": 70 | *h = Hopenbsd 71 | case "plan9": 72 | *h = Hplan9 73 | case "illumos", "solaris": 74 | *h = Hsolaris 75 | case "windows": 76 | *h = Hwindows 77 | default: 78 | return fmt.Errorf("invalid headtype: %q", s) 79 | } 80 | return nil 81 | } 82 | 83 | func (h *HeadType) String() string { 84 | switch *h { 85 | case Haix: 86 | return "aix" 87 | case Hdarwin: 88 | return "darwin" 89 | case Hdragonfly: 90 | return "dragonfly" 91 | case Hfreebsd: 92 | return "freebsd" 93 | case Hjs: 94 | return "js" 95 | case Hlinux: 96 | return "linux" 97 | case Hnetbsd: 98 | return "netbsd" 99 | case Hopenbsd: 100 | return "openbsd" 101 | case Hplan9: 102 | return "plan9" 103 | case Hsolaris: 104 | return "solaris" 105 | case Hwindows: 106 | return "windows" 107 | } 108 | return fmt.Sprintf("HeadType(%d)", *h) 109 | } 110 | -------------------------------------------------------------------------------- /asm/arch/ppc64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file encapsulates some of the odd characteristics of the 6 | // 64-bit PowerPC (PPC64) instruction set, to minimize its interaction 7 | // with the core of the assembler. 8 | 9 | package arch 10 | 11 | import ( 12 | "github.com/twitchyliquid64/golang-asm/obj" 13 | "github.com/twitchyliquid64/golang-asm/obj/ppc64" 14 | ) 15 | 16 | func jumpPPC64(word string) bool { 17 | switch word { 18 | case "BC", "BCL", "BEQ", "BGE", "BGT", "BL", "BLE", "BLT", "BNE", "BR", "BVC", "BVS", "CALL", "JMP": 19 | return true 20 | } 21 | return false 22 | } 23 | 24 | // IsPPC64RLD reports whether the op (as defined by an ppc64.A* constant) is 25 | // one of the RLD-like instructions that require special handling. 26 | // The FMADD-like instructions behave similarly. 27 | func IsPPC64RLD(op obj.As) bool { 28 | switch op { 29 | case ppc64.ARLDC, ppc64.ARLDCCC, ppc64.ARLDCL, ppc64.ARLDCLCC, 30 | ppc64.ARLDCR, ppc64.ARLDCRCC, ppc64.ARLDMI, ppc64.ARLDMICC, 31 | ppc64.ARLWMI, ppc64.ARLWMICC, ppc64.ARLWNM, ppc64.ARLWNMCC: 32 | return true 33 | case ppc64.AFMADD, ppc64.AFMADDCC, ppc64.AFMADDS, ppc64.AFMADDSCC, 34 | ppc64.AFMSUB, ppc64.AFMSUBCC, ppc64.AFMSUBS, ppc64.AFMSUBSCC, 35 | ppc64.AFNMADD, ppc64.AFNMADDCC, ppc64.AFNMADDS, ppc64.AFNMADDSCC, 36 | ppc64.AFNMSUB, ppc64.AFNMSUBCC, ppc64.AFNMSUBS, ppc64.AFNMSUBSCC: 37 | return true 38 | } 39 | return false 40 | } 41 | 42 | func IsPPC64ISEL(op obj.As) bool { 43 | return op == ppc64.AISEL 44 | } 45 | 46 | // IsPPC64CMP reports whether the op (as defined by an ppc64.A* constant) is 47 | // one of the CMP instructions that require special handling. 48 | func IsPPC64CMP(op obj.As) bool { 49 | switch op { 50 | case ppc64.ACMP, ppc64.ACMPU, ppc64.ACMPW, ppc64.ACMPWU, ppc64.AFCMPU: 51 | return true 52 | } 53 | return false 54 | } 55 | 56 | // IsPPC64NEG reports whether the op (as defined by an ppc64.A* constant) is 57 | // one of the NEG-like instructions that require special handling. 58 | func IsPPC64NEG(op obj.As) bool { 59 | switch op { 60 | case ppc64.AADDMECC, ppc64.AADDMEVCC, ppc64.AADDMEV, ppc64.AADDME, 61 | ppc64.AADDZECC, ppc64.AADDZEVCC, ppc64.AADDZEV, ppc64.AADDZE, 62 | ppc64.ACNTLZDCC, ppc64.ACNTLZD, ppc64.ACNTLZWCC, ppc64.ACNTLZW, 63 | ppc64.AEXTSBCC, ppc64.AEXTSB, ppc64.AEXTSHCC, ppc64.AEXTSH, 64 | ppc64.AEXTSWCC, ppc64.AEXTSW, ppc64.ANEGCC, ppc64.ANEGVCC, 65 | ppc64.ANEGV, ppc64.ANEG, ppc64.ASLBMFEE, ppc64.ASLBMFEV, 66 | ppc64.ASLBMTE, ppc64.ASUBMECC, ppc64.ASUBMEVCC, ppc64.ASUBMEV, 67 | ppc64.ASUBME, ppc64.ASUBZECC, ppc64.ASUBZEVCC, ppc64.ASUBZEV, 68 | ppc64.ASUBZE: 69 | return true 70 | } 71 | return false 72 | } 73 | 74 | func ppc64RegisterNumber(name string, n int16) (int16, bool) { 75 | switch name { 76 | case "CR": 77 | if 0 <= n && n <= 7 { 78 | return ppc64.REG_CR0 + n, true 79 | } 80 | case "VS": 81 | if 0 <= n && n <= 63 { 82 | return ppc64.REG_VS0 + n, true 83 | } 84 | case "V": 85 | if 0 <= n && n <= 31 { 86 | return ppc64.REG_V0 + n, true 87 | } 88 | case "F": 89 | if 0 <= n && n <= 31 { 90 | return ppc64.REG_F0 + n, true 91 | } 92 | case "R": 93 | if 0 <= n && n <= 31 { 94 | return ppc64.REG_R0 + n, true 95 | } 96 | case "SPR": 97 | if 0 <= n && n <= 1024 { 98 | return ppc64.REG_SPR0 + n, true 99 | } 100 | } 101 | return 0, false 102 | } 103 | -------------------------------------------------------------------------------- /sys/supported.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package sys 6 | 7 | // RaceDetectorSupported reports whether goos/goarch supports the race 8 | // detector. There is a copy of this function in cmd/dist/test.go. 9 | // Race detector only supports 48-bit VMA on arm64. But it will always 10 | // return true for arm64, because we don't have VMA size information during 11 | // the compile time. 12 | func RaceDetectorSupported(goos, goarch string) bool { 13 | switch goos { 14 | case "linux": 15 | return goarch == "amd64" || goarch == "ppc64le" || goarch == "arm64" 16 | case "darwin", "freebsd", "netbsd", "windows": 17 | return goarch == "amd64" 18 | default: 19 | return false 20 | } 21 | } 22 | 23 | // MSanSupported reports whether goos/goarch supports the memory 24 | // sanitizer option. There is a copy of this function in cmd/dist/test.go. 25 | func MSanSupported(goos, goarch string) bool { 26 | switch goos { 27 | case "linux": 28 | return goarch == "amd64" || goarch == "arm64" 29 | default: 30 | return false 31 | } 32 | } 33 | 34 | // MustLinkExternal reports whether goos/goarch requires external linking. 35 | func MustLinkExternal(goos, goarch string) bool { 36 | switch goos { 37 | case "android": 38 | if goarch != "arm64" { 39 | return true 40 | } 41 | case "darwin": 42 | if goarch == "arm64" { 43 | return true 44 | } 45 | } 46 | return false 47 | } 48 | 49 | // BuildModeSupported reports whether goos/goarch supports the given build mode 50 | // using the given compiler. 51 | func BuildModeSupported(compiler, buildmode, goos, goarch string) bool { 52 | if compiler == "gccgo" { 53 | return true 54 | } 55 | 56 | platform := goos + "/" + goarch 57 | 58 | switch buildmode { 59 | case "archive": 60 | return true 61 | 62 | case "c-archive": 63 | // TODO(bcmills): This seems dubious. 64 | // Do we really support c-archive mode on js/wasm‽ 65 | return platform != "linux/ppc64" 66 | 67 | case "c-shared": 68 | switch platform { 69 | case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/ppc64le", "linux/s390x", 70 | "android/amd64", "android/arm", "android/arm64", "android/386", 71 | "freebsd/amd64", 72 | "darwin/amd64", 73 | "windows/amd64", "windows/386": 74 | return true 75 | } 76 | return false 77 | 78 | case "default": 79 | return true 80 | 81 | case "exe": 82 | return true 83 | 84 | case "pie": 85 | switch platform { 86 | case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x", 87 | "android/amd64", "android/arm", "android/arm64", "android/386", 88 | "freebsd/amd64", 89 | "darwin/amd64", 90 | "aix/ppc64", 91 | "windows/386", "windows/amd64", "windows/arm": 92 | return true 93 | } 94 | return false 95 | 96 | case "shared": 97 | switch platform { 98 | case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x": 99 | return true 100 | } 101 | return false 102 | 103 | case "plugin": 104 | switch platform { 105 | case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/s390x", "linux/ppc64le", 106 | "android/amd64", "android/arm", "android/arm64", "android/386", 107 | "darwin/amd64", 108 | "freebsd/amd64": 109 | return true 110 | } 111 | return false 112 | 113 | default: 114 | return false 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /objabi/line.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package objabi 6 | 7 | import ( 8 | "os" 9 | "path/filepath" 10 | "strings" 11 | ) 12 | 13 | // WorkingDir returns the current working directory 14 | // (or "/???" if the directory cannot be identified), 15 | // with "/" as separator. 16 | func WorkingDir() string { 17 | var path string 18 | path, _ = os.Getwd() 19 | if path == "" { 20 | path = "/???" 21 | } 22 | return filepath.ToSlash(path) 23 | } 24 | 25 | // AbsFile returns the absolute filename for file in the given directory, 26 | // as rewritten by the rewrites argument. 27 | // For unrewritten paths, AbsFile rewrites a leading $GOROOT prefix to the literal "$GOROOT". 28 | // If the resulting path is the empty string, the result is "??". 29 | // 30 | // The rewrites argument is a ;-separated list of rewrites. 31 | // Each rewrite is of the form "prefix" or "prefix=>replace", 32 | // where prefix must match a leading sequence of path elements 33 | // and is either removed entirely or replaced by the replacement. 34 | func AbsFile(dir, file, rewrites string) string { 35 | abs := file 36 | if dir != "" && !filepath.IsAbs(file) { 37 | abs = filepath.Join(dir, file) 38 | } 39 | 40 | start := 0 41 | for i := 0; i <= len(rewrites); i++ { 42 | if i == len(rewrites) || rewrites[i] == ';' { 43 | if new, ok := applyRewrite(abs, rewrites[start:i]); ok { 44 | abs = new 45 | goto Rewritten 46 | } 47 | start = i + 1 48 | } 49 | } 50 | if hasPathPrefix(abs, GOROOT) { 51 | abs = "$GOROOT" + abs[len(GOROOT):] 52 | } 53 | 54 | Rewritten: 55 | if abs == "" { 56 | abs = "??" 57 | } 58 | return abs 59 | } 60 | 61 | // applyRewrite applies the rewrite to the path, 62 | // returning the rewritten path and a boolean 63 | // indicating whether the rewrite applied at all. 64 | func applyRewrite(path, rewrite string) (string, bool) { 65 | prefix, replace := rewrite, "" 66 | if j := strings.LastIndex(rewrite, "=>"); j >= 0 { 67 | prefix, replace = rewrite[:j], rewrite[j+len("=>"):] 68 | } 69 | 70 | if prefix == "" || !hasPathPrefix(path, prefix) { 71 | return path, false 72 | } 73 | if len(path) == len(prefix) { 74 | return replace, true 75 | } 76 | if replace == "" { 77 | return path[len(prefix)+1:], true 78 | } 79 | return replace + path[len(prefix):], true 80 | } 81 | 82 | // Does s have t as a path prefix? 83 | // That is, does s == t or does s begin with t followed by a slash? 84 | // For portability, we allow ASCII case folding, so that hasPathPrefix("a/b/c", "A/B") is true. 85 | // Similarly, we allow slash folding, so that hasPathPrefix("a/b/c", "a\\b") is true. 86 | // We do not allow full Unicode case folding, for fear of causing more confusion 87 | // or harm than good. (For an example of the kinds of things that can go wrong, 88 | // see http://article.gmane.org/gmane.linux.kernel/1853266.) 89 | func hasPathPrefix(s string, t string) bool { 90 | if len(t) > len(s) { 91 | return false 92 | } 93 | var i int 94 | for i = 0; i < len(t); i++ { 95 | cs := int(s[i]) 96 | ct := int(t[i]) 97 | if 'A' <= cs && cs <= 'Z' { 98 | cs += 'a' - 'A' 99 | } 100 | if 'A' <= ct && ct <= 'Z' { 101 | ct += 'a' - 'A' 102 | } 103 | if cs == '\\' { 104 | cs = '/' 105 | } 106 | if ct == '\\' { 107 | ct = '/' 108 | } 109 | if cs != ct { 110 | return false 111 | } 112 | } 113 | return i >= len(s) || s[i] == '/' || s[i] == '\\' 114 | } 115 | -------------------------------------------------------------------------------- /obj/arm/list5.go: -------------------------------------------------------------------------------- 1 | // Inferno utils/5c/list.c 2 | // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5c/list.c 3 | // 4 | // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 | // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 | // Portions Copyright © 1997-1999 Vita Nuova Limited 7 | // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 | // Portions Copyright © 2004,2006 Bruce Ellis 9 | // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 | // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 | // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 | // 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy 14 | // of this software and associated documentation files (the "Software"), to deal 15 | // in the Software without restriction, including without limitation the rights 16 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | // copies of the Software, and to permit persons to whom the Software is 18 | // furnished to do so, subject to the following conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be included in 21 | // all copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 | // THE SOFTWARE. 30 | 31 | package arm 32 | 33 | import ( 34 | "github.com/twitchyliquid64/golang-asm/obj" 35 | "fmt" 36 | ) 37 | 38 | func init() { 39 | obj.RegisterRegister(obj.RBaseARM, MAXREG, rconv) 40 | obj.RegisterOpcode(obj.ABaseARM, Anames) 41 | obj.RegisterRegisterList(obj.RegListARMLo, obj.RegListARMHi, rlconv) 42 | obj.RegisterOpSuffix("arm", obj.CConvARM) 43 | } 44 | 45 | func rconv(r int) string { 46 | if r == 0 { 47 | return "NONE" 48 | } 49 | if r == REGG { 50 | // Special case. 51 | return "g" 52 | } 53 | if REG_R0 <= r && r <= REG_R15 { 54 | return fmt.Sprintf("R%d", r-REG_R0) 55 | } 56 | if REG_F0 <= r && r <= REG_F15 { 57 | return fmt.Sprintf("F%d", r-REG_F0) 58 | } 59 | 60 | switch r { 61 | case REG_FPSR: 62 | return "FPSR" 63 | 64 | case REG_FPCR: 65 | return "FPCR" 66 | 67 | case REG_CPSR: 68 | return "CPSR" 69 | 70 | case REG_SPSR: 71 | return "SPSR" 72 | 73 | case REG_MB_SY: 74 | return "MB_SY" 75 | case REG_MB_ST: 76 | return "MB_ST" 77 | case REG_MB_ISH: 78 | return "MB_ISH" 79 | case REG_MB_ISHST: 80 | return "MB_ISHST" 81 | case REG_MB_NSH: 82 | return "MB_NSH" 83 | case REG_MB_NSHST: 84 | return "MB_NSHST" 85 | case REG_MB_OSH: 86 | return "MB_OSH" 87 | case REG_MB_OSHST: 88 | return "MB_OSHST" 89 | } 90 | 91 | return fmt.Sprintf("Rgok(%d)", r-obj.RBaseARM) 92 | } 93 | 94 | func DRconv(a int) string { 95 | s := "C_??" 96 | if a >= C_NONE && a <= C_NCLASS { 97 | s = cnames5[a] 98 | } 99 | var fp string 100 | fp += s 101 | return fp 102 | } 103 | 104 | func rlconv(list int64) string { 105 | str := "" 106 | for i := 0; i < 16; i++ { 107 | if list&(1<}, 35 | // {Parent: 0, Func: "g", Pos: }, 36 | // {Parent: 1, Func: "h", Pos: }, 37 | // {Parent: 1, Func: "h", Pos: }, 38 | // } 39 | // 40 | // The nodes of h inlined into main will have inlining indexes 2 and 3. 41 | // 42 | // Eventually, the compiler extracts a per-function inlining tree from 43 | // the global inlining tree (see pcln.go). 44 | type InlTree struct { 45 | nodes []InlinedCall 46 | } 47 | 48 | // InlinedCall is a node in an InlTree. 49 | type InlinedCall struct { 50 | Parent int // index of the parent in the InlTree or < 0 if outermost call 51 | Pos src.XPos // position of the inlined call 52 | Func *LSym // function that was inlined 53 | ParentPC int32 // PC of instruction just before inlined body. Only valid in local trees. 54 | } 55 | 56 | // Add adds a new call to the tree, returning its index. 57 | func (tree *InlTree) Add(parent int, pos src.XPos, func_ *LSym) int { 58 | r := len(tree.nodes) 59 | call := InlinedCall{ 60 | Parent: parent, 61 | Pos: pos, 62 | Func: func_, 63 | } 64 | tree.nodes = append(tree.nodes, call) 65 | return r 66 | } 67 | 68 | func (tree *InlTree) Parent(inlIndex int) int { 69 | return tree.nodes[inlIndex].Parent 70 | } 71 | 72 | func (tree *InlTree) InlinedFunction(inlIndex int) *LSym { 73 | return tree.nodes[inlIndex].Func 74 | } 75 | 76 | func (tree *InlTree) CallPos(inlIndex int) src.XPos { 77 | return tree.nodes[inlIndex].Pos 78 | } 79 | 80 | func (tree *InlTree) setParentPC(inlIndex int, pc int32) { 81 | tree.nodes[inlIndex].ParentPC = pc 82 | } 83 | 84 | // OutermostPos returns the outermost position corresponding to xpos, 85 | // which is where xpos was ultimately inlined to. In the example for 86 | // InlTree, main() contains inlined AST nodes from h(), but the 87 | // outermost position for those nodes is line 2. 88 | func (ctxt *Link) OutermostPos(xpos src.XPos) src.Pos { 89 | pos := ctxt.InnermostPos(xpos) 90 | 91 | outerxpos := xpos 92 | for ix := pos.Base().InliningIndex(); ix >= 0; { 93 | call := ctxt.InlTree.nodes[ix] 94 | ix = call.Parent 95 | outerxpos = call.Pos 96 | } 97 | return ctxt.PosTable.Pos(outerxpos) 98 | } 99 | 100 | // InnermostPos returns the innermost position corresponding to xpos, 101 | // that is, the code that is inlined and that inlines nothing else. 102 | // In the example for InlTree above, the code for println within h 103 | // would have an innermost position with line number 12, whether 104 | // h was not inlined, inlined into g, g-then-f, or g-then-f-then-main. 105 | // This corresponds to what someone debugging main, f, g, or h might 106 | // expect to see while single-stepping. 107 | func (ctxt *Link) InnermostPos(xpos src.XPos) src.Pos { 108 | return ctxt.PosTable.Pos(xpos) 109 | } 110 | 111 | // AllPos returns a slice of the positions inlined at xpos, from 112 | // innermost (index zero) to outermost. To avoid gratuitous allocation 113 | // the result is passed in and extended if necessary. 114 | func (ctxt *Link) AllPos(xpos src.XPos, result []src.Pos) []src.Pos { 115 | pos := ctxt.InnermostPos(xpos) 116 | result = result[:0] 117 | result = append(result, ctxt.PosTable.Pos(xpos)) 118 | for ix := pos.Base().InliningIndex(); ix >= 0; { 119 | call := ctxt.InlTree.nodes[ix] 120 | ix = call.Parent 121 | result = append(result, ctxt.PosTable.Pos(call.Pos)) 122 | } 123 | return result 124 | } 125 | 126 | func dumpInlTree(ctxt *Link, tree InlTree) { 127 | for i, call := range tree.nodes { 128 | pos := ctxt.PosTable.Pos(call.Pos) 129 | ctxt.Logf("%0d | %0d | %s (%s) pc=%d\n", i, call.Parent, call.Func, pos, call.ParentPC) 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /objabi/util.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package objabi 6 | 7 | import ( 8 | "fmt" 9 | "log" 10 | "os" 11 | "strings" 12 | ) 13 | 14 | func envOr(key, value string) string { 15 | if x := os.Getenv(key); x != "" { 16 | return x 17 | } 18 | return value 19 | } 20 | 21 | var ( 22 | defaultGOROOT string // set by linker 23 | 24 | GOROOT = envOr("GOROOT", defaultGOROOT) 25 | GOARCH = envOr("GOARCH", "amd64") 26 | GOOS = envOr("GOOS", "linux") 27 | GO386 = envOr("GO386", "") 28 | GOAMD64 = goamd64() 29 | GOARM = goarm() 30 | GOMIPS = gomips() 31 | GOMIPS64 = gomips64() 32 | GOPPC64 = goppc64() 33 | GOWASM = gowasm() 34 | GO_LDSO = "" 35 | Version = "" 36 | ) 37 | 38 | const ( 39 | ElfRelocOffset = 256 40 | MachoRelocOffset = 2048 // reserve enough space for ELF relocations 41 | Go115AMD64 = "alignedjumps" // Should be "alignedjumps" or "normaljumps"; this replaces environment variable introduced in CL 219357. 42 | ) 43 | 44 | // TODO(1.16): assuming no issues in 1.15 release, remove this and related constant. 45 | func goamd64() string { 46 | return Go115AMD64 47 | } 48 | 49 | func goarm() int { 50 | switch v := envOr("GOARM", "7"); v { 51 | case "5": 52 | return 5 53 | case "6": 54 | return 6 55 | case "7": 56 | return 7 57 | } 58 | // Fail here, rather than validate at multiple call sites. 59 | log.Fatalf("Invalid GOARM value. Must be 5, 6, or 7.") 60 | panic("unreachable") 61 | } 62 | 63 | func gomips() string { 64 | switch v := envOr("GOMIPS", "hardfloat"); v { 65 | case "hardfloat", "softfloat": 66 | return v 67 | } 68 | log.Fatalf("Invalid GOMIPS value. Must be hardfloat or softfloat.") 69 | panic("unreachable") 70 | } 71 | 72 | func gomips64() string { 73 | switch v := envOr("GOMIPS64", "hardfloat"); v { 74 | case "hardfloat", "softfloat": 75 | return v 76 | } 77 | log.Fatalf("Invalid GOMIPS64 value. Must be hardfloat or softfloat.") 78 | panic("unreachable") 79 | } 80 | 81 | func goppc64() int { 82 | switch v := envOr("GOPPC64", "power8"); v { 83 | case "power8": 84 | return 8 85 | case "power9": 86 | return 9 87 | } 88 | log.Fatalf("Invalid GOPPC64 value. Must be power8 or power9.") 89 | panic("unreachable") 90 | } 91 | 92 | type gowasmFeatures struct { 93 | SignExt bool 94 | SatConv bool 95 | } 96 | 97 | func (f gowasmFeatures) String() string { 98 | var flags []string 99 | if f.SatConv { 100 | flags = append(flags, "satconv") 101 | } 102 | if f.SignExt { 103 | flags = append(flags, "signext") 104 | } 105 | return strings.Join(flags, ",") 106 | } 107 | 108 | func gowasm() (f gowasmFeatures) { 109 | for _, opt := range strings.Split(envOr("GOWASM", ""), ",") { 110 | switch opt { 111 | case "satconv": 112 | f.SatConv = true 113 | case "signext": 114 | f.SignExt = true 115 | case "": 116 | // ignore 117 | default: 118 | log.Fatalf("Invalid GOWASM value. No such feature: " + opt) 119 | } 120 | } 121 | return 122 | } 123 | 124 | func Getgoextlinkenabled() string { 125 | return envOr("GO_EXTLINK_ENABLED", "") 126 | } 127 | 128 | func init() { 129 | for _, f := range strings.Split("", ",") { 130 | if f != "" { 131 | addexp(f) 132 | } 133 | } 134 | 135 | // regabi is only supported on amd64. 136 | if GOARCH != "amd64" { 137 | Regabi_enabled = 0 138 | } 139 | } 140 | 141 | // Note: must agree with runtime.framepointer_enabled. 142 | var Framepointer_enabled = GOARCH == "amd64" || GOARCH == "arm64" && (GOOS == "linux" || GOOS == "darwin") 143 | 144 | func addexp(s string) { 145 | // Could do general integer parsing here, but the runtime copy doesn't yet. 146 | v := 1 147 | name := s 148 | if len(name) > 2 && name[:2] == "no" { 149 | v = 0 150 | name = name[2:] 151 | } 152 | for i := 0; i < len(exper); i++ { 153 | if exper[i].name == name { 154 | if exper[i].val != nil { 155 | *exper[i].val = v 156 | } 157 | return 158 | } 159 | } 160 | 161 | fmt.Printf("unknown experiment %s\n", s) 162 | os.Exit(2) 163 | } 164 | 165 | var ( 166 | Fieldtrack_enabled int 167 | Preemptibleloops_enabled int 168 | Staticlockranking_enabled int 169 | Regabi_enabled int 170 | ) 171 | 172 | // Toolchain experiments. 173 | // These are controlled by the GOEXPERIMENT environment 174 | // variable recorded when the toolchain is built. 175 | // This list is also known to cmd/gc. 176 | var exper = []struct { 177 | name string 178 | val *int 179 | }{ 180 | {"fieldtrack", &Fieldtrack_enabled}, 181 | {"preemptibleloops", &Preemptibleloops_enabled}, 182 | {"staticlockranking", &Staticlockranking_enabled}, 183 | {"regabi", &Regabi_enabled}, 184 | } 185 | 186 | var defaultExpstring = Expstring() 187 | 188 | func DefaultExpstring() string { 189 | return defaultExpstring 190 | } 191 | 192 | func Expstring() string { 193 | buf := "X" 194 | for i := range exper { 195 | if *exper[i].val != 0 { 196 | buf += "," + exper[i].name 197 | } 198 | } 199 | if buf == "X" { 200 | buf += ",none" 201 | } 202 | return "X:" + buf[2:] 203 | } 204 | -------------------------------------------------------------------------------- /obj/x86/list6.go: -------------------------------------------------------------------------------- 1 | // Inferno utils/6c/list.c 2 | // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6c/list.c 3 | // 4 | // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 | // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 | // Portions Copyright © 1997-1999 Vita Nuova Limited 7 | // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 | // Portions Copyright © 2004,2006 Bruce Ellis 9 | // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 | // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 | // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 | // 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy 14 | // of this software and associated documentation files (the "Software"), to deal 15 | // in the Software without restriction, including without limitation the rights 16 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | // copies of the Software, and to permit persons to whom the Software is 18 | // furnished to do so, subject to the following conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be included in 21 | // all copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 | // THE SOFTWARE. 30 | 31 | package x86 32 | 33 | import ( 34 | "github.com/twitchyliquid64/golang-asm/obj" 35 | "fmt" 36 | ) 37 | 38 | var Register = []string{ 39 | "AL", // [D_AL] 40 | "CL", 41 | "DL", 42 | "BL", 43 | "SPB", 44 | "BPB", 45 | "SIB", 46 | "DIB", 47 | "R8B", 48 | "R9B", 49 | "R10B", 50 | "R11B", 51 | "R12B", 52 | "R13B", 53 | "R14B", 54 | "R15B", 55 | "AX", // [D_AX] 56 | "CX", 57 | "DX", 58 | "BX", 59 | "SP", 60 | "BP", 61 | "SI", 62 | "DI", 63 | "R8", 64 | "R9", 65 | "R10", 66 | "R11", 67 | "R12", 68 | "R13", 69 | "R14", 70 | "R15", 71 | "AH", 72 | "CH", 73 | "DH", 74 | "BH", 75 | "F0", // [D_F0] 76 | "F1", 77 | "F2", 78 | "F3", 79 | "F4", 80 | "F5", 81 | "F6", 82 | "F7", 83 | "M0", 84 | "M1", 85 | "M2", 86 | "M3", 87 | "M4", 88 | "M5", 89 | "M6", 90 | "M7", 91 | "K0", 92 | "K1", 93 | "K2", 94 | "K3", 95 | "K4", 96 | "K5", 97 | "K6", 98 | "K7", 99 | "X0", 100 | "X1", 101 | "X2", 102 | "X3", 103 | "X4", 104 | "X5", 105 | "X6", 106 | "X7", 107 | "X8", 108 | "X9", 109 | "X10", 110 | "X11", 111 | "X12", 112 | "X13", 113 | "X14", 114 | "X15", 115 | "X16", 116 | "X17", 117 | "X18", 118 | "X19", 119 | "X20", 120 | "X21", 121 | "X22", 122 | "X23", 123 | "X24", 124 | "X25", 125 | "X26", 126 | "X27", 127 | "X28", 128 | "X29", 129 | "X30", 130 | "X31", 131 | "Y0", 132 | "Y1", 133 | "Y2", 134 | "Y3", 135 | "Y4", 136 | "Y5", 137 | "Y6", 138 | "Y7", 139 | "Y8", 140 | "Y9", 141 | "Y10", 142 | "Y11", 143 | "Y12", 144 | "Y13", 145 | "Y14", 146 | "Y15", 147 | "Y16", 148 | "Y17", 149 | "Y18", 150 | "Y19", 151 | "Y20", 152 | "Y21", 153 | "Y22", 154 | "Y23", 155 | "Y24", 156 | "Y25", 157 | "Y26", 158 | "Y27", 159 | "Y28", 160 | "Y29", 161 | "Y30", 162 | "Y31", 163 | "Z0", 164 | "Z1", 165 | "Z2", 166 | "Z3", 167 | "Z4", 168 | "Z5", 169 | "Z6", 170 | "Z7", 171 | "Z8", 172 | "Z9", 173 | "Z10", 174 | "Z11", 175 | "Z12", 176 | "Z13", 177 | "Z14", 178 | "Z15", 179 | "Z16", 180 | "Z17", 181 | "Z18", 182 | "Z19", 183 | "Z20", 184 | "Z21", 185 | "Z22", 186 | "Z23", 187 | "Z24", 188 | "Z25", 189 | "Z26", 190 | "Z27", 191 | "Z28", 192 | "Z29", 193 | "Z30", 194 | "Z31", 195 | "CS", // [D_CS] 196 | "SS", 197 | "DS", 198 | "ES", 199 | "FS", 200 | "GS", 201 | "GDTR", // [D_GDTR] 202 | "IDTR", // [D_IDTR] 203 | "LDTR", // [D_LDTR] 204 | "MSW", // [D_MSW] 205 | "TASK", // [D_TASK] 206 | "CR0", // [D_CR] 207 | "CR1", 208 | "CR2", 209 | "CR3", 210 | "CR4", 211 | "CR5", 212 | "CR6", 213 | "CR7", 214 | "CR8", 215 | "CR9", 216 | "CR10", 217 | "CR11", 218 | "CR12", 219 | "CR13", 220 | "CR14", 221 | "CR15", 222 | "DR0", // [D_DR] 223 | "DR1", 224 | "DR2", 225 | "DR3", 226 | "DR4", 227 | "DR5", 228 | "DR6", 229 | "DR7", 230 | "TR0", // [D_TR] 231 | "TR1", 232 | "TR2", 233 | "TR3", 234 | "TR4", 235 | "TR5", 236 | "TR6", 237 | "TR7", 238 | "TLS", // [D_TLS] 239 | "MAXREG", // [MAXREG] 240 | } 241 | 242 | func init() { 243 | obj.RegisterRegister(REG_AL, REG_AL+len(Register), rconv) 244 | obj.RegisterOpcode(obj.ABaseAMD64, Anames) 245 | obj.RegisterRegisterList(obj.RegListX86Lo, obj.RegListX86Hi, rlconv) 246 | obj.RegisterOpSuffix("386", opSuffixString) 247 | obj.RegisterOpSuffix("amd64", opSuffixString) 248 | } 249 | 250 | func rconv(r int) string { 251 | if REG_AL <= r && r-REG_AL < len(Register) { 252 | return Register[r-REG_AL] 253 | } 254 | return fmt.Sprintf("Rgok(%d)", r-obj.RBaseAMD64) 255 | } 256 | 257 | func rlconv(bits int64) string { 258 | reg0, reg1 := decodeRegisterRange(bits) 259 | return fmt.Sprintf("[%s-%s]", rconv(reg0), rconv(reg1)) 260 | } 261 | 262 | func opSuffixString(s uint8) string { 263 | return "." + opSuffix(s).String() 264 | } 265 | -------------------------------------------------------------------------------- /obj/pass.go: -------------------------------------------------------------------------------- 1 | // Inferno utils/6l/pass.c 2 | // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/pass.c 3 | // 4 | // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 | // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 | // Portions Copyright © 1997-1999 Vita Nuova Limited 7 | // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 | // Portions Copyright © 2004,2006 Bruce Ellis 9 | // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 | // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 | // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 | // 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy 14 | // of this software and associated documentation files (the "Software"), to deal 15 | // in the Software without restriction, including without limitation the rights 16 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | // copies of the Software, and to permit persons to whom the Software is 18 | // furnished to do so, subject to the following conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be included in 21 | // all copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 | // THE SOFTWARE. 30 | 31 | package obj 32 | 33 | // Code and data passes. 34 | 35 | // brloop returns the ultimate destination of the series of unconditional jumps beginning at p. 36 | // In the case of an infinite loop, brloop returns nil. 37 | func brloop(p *Prog) *Prog { 38 | c := 0 39 | for q := p; q != nil; q = q.To.Target() { 40 | if q.As != AJMP || q.To.Target() == nil { 41 | return q 42 | } 43 | c++ 44 | if c >= 5000 { 45 | // infinite loop 46 | return nil 47 | } 48 | } 49 | panic("unreachable") 50 | } 51 | 52 | // checkaddr checks that a has an expected encoding, especially TYPE_CONST vs TYPE_ADDR. 53 | func checkaddr(ctxt *Link, p *Prog, a *Addr) { 54 | switch a.Type { 55 | case TYPE_NONE, TYPE_REGREG2, TYPE_REGLIST: 56 | return 57 | 58 | case TYPE_BRANCH, TYPE_TEXTSIZE: 59 | if a.Reg != 0 || a.Index != 0 || a.Scale != 0 || a.Name != 0 { 60 | break 61 | } 62 | return 63 | 64 | case TYPE_MEM: 65 | return 66 | 67 | case TYPE_CONST: 68 | // TODO(rsc): After fixing SHRQ, check a.Index != 0 too. 69 | if a.Name != 0 || a.Sym != nil || a.Reg != 0 { 70 | ctxt.Diag("argument is TYPE_CONST, should be TYPE_ADDR, in %v", p) 71 | return 72 | } 73 | 74 | if a.Reg != 0 || a.Scale != 0 || a.Name != 0 || a.Sym != nil || a.Val != nil { 75 | break 76 | } 77 | return 78 | 79 | case TYPE_FCONST, TYPE_SCONST: 80 | if a.Reg != 0 || a.Index != 0 || a.Scale != 0 || a.Name != 0 || a.Offset != 0 || a.Sym != nil { 81 | break 82 | } 83 | return 84 | 85 | case TYPE_REG: 86 | // TODO(rsc): After fixing PINSRQ, check a.Offset != 0 too. 87 | // TODO(rsc): After fixing SHRQ, check a.Index != 0 too. 88 | if a.Scale != 0 || a.Name != 0 || a.Sym != nil { 89 | break 90 | } 91 | return 92 | 93 | case TYPE_ADDR: 94 | if a.Val != nil { 95 | break 96 | } 97 | if a.Reg == 0 && a.Index == 0 && a.Scale == 0 && a.Name == 0 && a.Sym == nil { 98 | ctxt.Diag("argument is TYPE_ADDR, should be TYPE_CONST, in %v", p) 99 | } 100 | return 101 | 102 | case TYPE_SHIFT, TYPE_REGREG: 103 | if a.Index != 0 || a.Scale != 0 || a.Name != 0 || a.Sym != nil || a.Val != nil { 104 | break 105 | } 106 | return 107 | 108 | case TYPE_INDIR: 109 | // Expect sym and name to be set, nothing else. 110 | // Technically more is allowed, but this is only used for *name(SB). 111 | if a.Reg != 0 || a.Index != 0 || a.Scale != 0 || a.Name == 0 || a.Offset != 0 || a.Sym == nil || a.Val != nil { 112 | break 113 | } 114 | return 115 | } 116 | 117 | ctxt.Diag("invalid encoding for argument %v", p) 118 | } 119 | 120 | func linkpatch(ctxt *Link, sym *LSym, newprog ProgAlloc) { 121 | for p := sym.Func.Text; p != nil; p = p.Link { 122 | checkaddr(ctxt, p, &p.From) 123 | if p.GetFrom3() != nil { 124 | checkaddr(ctxt, p, p.GetFrom3()) 125 | } 126 | checkaddr(ctxt, p, &p.To) 127 | 128 | if ctxt.Arch.Progedit != nil { 129 | ctxt.Arch.Progedit(ctxt, p, newprog) 130 | } 131 | if p.To.Type != TYPE_BRANCH { 132 | continue 133 | } 134 | if p.To.Val != nil { 135 | continue 136 | } 137 | 138 | if p.To.Sym != nil { 139 | continue 140 | } 141 | q := sym.Func.Text 142 | for q != nil && p.To.Offset != q.Pc { 143 | if q.Forwd != nil && p.To.Offset >= q.Forwd.Pc { 144 | q = q.Forwd 145 | } else { 146 | q = q.Link 147 | } 148 | } 149 | 150 | if q == nil { 151 | name := "" 152 | if p.To.Sym != nil { 153 | name = p.To.Sym.Name 154 | } 155 | ctxt.Diag("branch out of range (%#x)\n%v [%s]", uint32(p.To.Offset), p, name) 156 | p.To.Type = TYPE_NONE 157 | } 158 | 159 | p.To.SetTarget(q) 160 | } 161 | 162 | if !ctxt.Flag_optimize { 163 | return 164 | } 165 | 166 | // Collapse series of jumps to jumps. 167 | for p := sym.Func.Text; p != nil; p = p.Link { 168 | if p.To.Target() == nil { 169 | continue 170 | } 171 | p.To.SetTarget(brloop(p.To.Target())) 172 | if p.To.Target() != nil && p.To.Type == TYPE_BRANCH { 173 | p.To.Offset = p.To.Target().Pc 174 | } 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /src/xpos.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file implements the compressed encoding of source 6 | // positions using a lookup table. 7 | 8 | package src 9 | 10 | // XPos is a more compact representation of Pos. 11 | type XPos struct { 12 | index int32 13 | lico 14 | } 15 | 16 | // NoXPos is a valid unknown position. 17 | var NoXPos XPos 18 | 19 | // IsKnown reports whether the position p is known. 20 | // XPos.IsKnown() matches Pos.IsKnown() for corresponding 21 | // positions. 22 | func (p XPos) IsKnown() bool { 23 | return p.index != 0 || p.Line() != 0 24 | } 25 | 26 | // Before reports whether the position p comes before q in the source. 27 | // For positions with different bases, ordering is by base index. 28 | func (p XPos) Before(q XPos) bool { 29 | n, m := p.index, q.index 30 | return n < m || n == m && p.lico < q.lico 31 | } 32 | 33 | // SameFile reports whether p and q are positions in the same file. 34 | func (p XPos) SameFile(q XPos) bool { 35 | return p.index == q.index 36 | } 37 | 38 | // SameFileAndLine reports whether p and q are positions on the same line in the same file. 39 | func (p XPos) SameFileAndLine(q XPos) bool { 40 | return p.index == q.index && p.lico.SameLine(q.lico) 41 | } 42 | 43 | // After reports whether the position p comes after q in the source. 44 | // For positions with different bases, ordering is by base index. 45 | func (p XPos) After(q XPos) bool { 46 | n, m := p.index, q.index 47 | return n > m || n == m && p.lico > q.lico 48 | } 49 | 50 | // WithNotStmt returns the same location to be marked with DWARF is_stmt=0 51 | func (p XPos) WithNotStmt() XPos { 52 | p.lico = p.lico.withNotStmt() 53 | return p 54 | } 55 | 56 | // WithDefaultStmt returns the same location with undetermined is_stmt 57 | func (p XPos) WithDefaultStmt() XPos { 58 | p.lico = p.lico.withDefaultStmt() 59 | return p 60 | } 61 | 62 | // WithIsStmt returns the same location to be marked with DWARF is_stmt=1 63 | func (p XPos) WithIsStmt() XPos { 64 | p.lico = p.lico.withIsStmt() 65 | return p 66 | } 67 | 68 | // WithBogusLine returns a bogus line that won't match any recorded for the source code. 69 | // Its use is to disrupt the statements within an infinite loop so that the debugger 70 | // will not itself loop infinitely waiting for the line number to change. 71 | // gdb chooses not to display the bogus line; delve shows it with a complaint, but the 72 | // alternative behavior is to hang. 73 | func (p XPos) WithBogusLine() XPos { 74 | if p.index == 0 { 75 | // See #35652 76 | panic("Assigning a bogus line to XPos with no file will cause mysterious downstream failures.") 77 | } 78 | p.lico = makeBogusLico() 79 | return p 80 | } 81 | 82 | // WithXlogue returns the same location but marked with DWARF function prologue/epilogue 83 | func (p XPos) WithXlogue(x PosXlogue) XPos { 84 | p.lico = p.lico.withXlogue(x) 85 | return p 86 | } 87 | 88 | // LineNumber returns a string for the line number, "?" if it is not known. 89 | func (p XPos) LineNumber() string { 90 | if !p.IsKnown() { 91 | return "?" 92 | } 93 | return p.lico.lineNumber() 94 | } 95 | 96 | // FileIndex returns a smallish non-negative integer corresponding to the 97 | // file for this source position. Smallish is relative; it can be thousands 98 | // large, but not millions. 99 | func (p XPos) FileIndex() int32 { 100 | return p.index 101 | } 102 | 103 | func (p XPos) LineNumberHTML() string { 104 | if !p.IsKnown() { 105 | return "?" 106 | } 107 | return p.lico.lineNumberHTML() 108 | } 109 | 110 | // AtColumn1 returns the same location but shifted to column 1. 111 | func (p XPos) AtColumn1() XPos { 112 | p.lico = p.lico.atColumn1() 113 | return p 114 | } 115 | 116 | // A PosTable tracks Pos -> XPos conversions and vice versa. 117 | // Its zero value is a ready-to-use PosTable. 118 | type PosTable struct { 119 | baseList []*PosBase 120 | indexMap map[*PosBase]int 121 | nameMap map[string]int // Maps file symbol name to index for debug information. 122 | } 123 | 124 | // XPos returns the corresponding XPos for the given pos, 125 | // adding pos to t if necessary. 126 | func (t *PosTable) XPos(pos Pos) XPos { 127 | m := t.indexMap 128 | if m == nil { 129 | // Create new list and map and populate with nil 130 | // base so that NoPos always gets index 0. 131 | t.baseList = append(t.baseList, nil) 132 | m = map[*PosBase]int{nil: 0} 133 | t.indexMap = m 134 | t.nameMap = make(map[string]int) 135 | } 136 | i, ok := m[pos.base] 137 | if !ok { 138 | i = len(t.baseList) 139 | t.baseList = append(t.baseList, pos.base) 140 | t.indexMap[pos.base] = i 141 | if _, ok := t.nameMap[pos.base.symFilename]; !ok { 142 | t.nameMap[pos.base.symFilename] = len(t.nameMap) 143 | } 144 | } 145 | return XPos{int32(i), pos.lico} 146 | } 147 | 148 | // Pos returns the corresponding Pos for the given p. 149 | // If p cannot be translated via t, the function panics. 150 | func (t *PosTable) Pos(p XPos) Pos { 151 | var base *PosBase 152 | if p.index != 0 { 153 | base = t.baseList[p.index] 154 | } 155 | return Pos{base, p.lico} 156 | } 157 | 158 | // FileIndex returns the index of the given filename(symbol) in the PosTable, or -1 if not found. 159 | func (t *PosTable) FileIndex(filename string) int { 160 | if v, ok := t.nameMap[filename]; ok { 161 | return v 162 | } 163 | return -1 164 | } 165 | 166 | // FileTable returns a slice of all files used to build this package. 167 | func (t *PosTable) FileTable() []string { 168 | // Create a LUT of the global package level file indices. This table is what 169 | // is written in the debug_lines header, the file[N] will be referenced as 170 | // N+1 in the debug_lines table. 171 | fileLUT := make([]string, len(t.nameMap)) 172 | for str, i := range t.nameMap { 173 | fileLUT[i] = str 174 | } 175 | return fileLUT 176 | } 177 | -------------------------------------------------------------------------------- /obj/wasm/a.out.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package wasm 6 | 7 | import "github.com/twitchyliquid64/golang-asm/obj" 8 | 9 | //go:generate go run ../stringer.go -i $GOFILE -o anames.go -p wasm 10 | 11 | const ( 12 | /* mark flags */ 13 | DONE = 1 << iota 14 | PRESERVEFLAGS // not allowed to clobber flags 15 | ) 16 | 17 | /* 18 | * wasm 19 | */ 20 | const ( 21 | ACallImport = obj.ABaseWasm + obj.A_ARCHSPECIFIC + iota 22 | AGet 23 | ASet 24 | ATee 25 | ANot // alias for I32Eqz 26 | 27 | // The following are low-level WebAssembly instructions. 28 | // Their order matters, since it matches the opcode encoding. 29 | // Gaps in the encoding are indicated by comments. 30 | 31 | AUnreachable // opcode 0x00 32 | ANop 33 | ABlock 34 | ALoop 35 | AIf 36 | AElse 37 | 38 | AEnd // opcode 0x0B 39 | ABr 40 | ABrIf 41 | ABrTable 42 | // ACall and AReturn are WebAssembly instructions. obj.ACALL and obj.ARET are higher level instructions 43 | // with Go semantics, e.g. they manipulate the Go stack on the linear memory. 44 | AReturn 45 | ACall 46 | ACallIndirect 47 | 48 | ADrop // opcode 0x1A 49 | ASelect 50 | 51 | ALocalGet // opcode 0x20 52 | ALocalSet 53 | ALocalTee 54 | AGlobalGet 55 | AGlobalSet 56 | 57 | AI32Load // opcode 0x28 58 | AI64Load 59 | AF32Load 60 | AF64Load 61 | AI32Load8S 62 | AI32Load8U 63 | AI32Load16S 64 | AI32Load16U 65 | AI64Load8S 66 | AI64Load8U 67 | AI64Load16S 68 | AI64Load16U 69 | AI64Load32S 70 | AI64Load32U 71 | AI32Store 72 | AI64Store 73 | AF32Store 74 | AF64Store 75 | AI32Store8 76 | AI32Store16 77 | AI64Store8 78 | AI64Store16 79 | AI64Store32 80 | ACurrentMemory 81 | AGrowMemory 82 | 83 | AI32Const 84 | AI64Const 85 | AF32Const 86 | AF64Const 87 | 88 | AI32Eqz 89 | AI32Eq 90 | AI32Ne 91 | AI32LtS 92 | AI32LtU 93 | AI32GtS 94 | AI32GtU 95 | AI32LeS 96 | AI32LeU 97 | AI32GeS 98 | AI32GeU 99 | 100 | AI64Eqz 101 | AI64Eq 102 | AI64Ne 103 | AI64LtS 104 | AI64LtU 105 | AI64GtS 106 | AI64GtU 107 | AI64LeS 108 | AI64LeU 109 | AI64GeS 110 | AI64GeU 111 | 112 | AF32Eq 113 | AF32Ne 114 | AF32Lt 115 | AF32Gt 116 | AF32Le 117 | AF32Ge 118 | 119 | AF64Eq 120 | AF64Ne 121 | AF64Lt 122 | AF64Gt 123 | AF64Le 124 | AF64Ge 125 | 126 | AI32Clz 127 | AI32Ctz 128 | AI32Popcnt 129 | AI32Add 130 | AI32Sub 131 | AI32Mul 132 | AI32DivS 133 | AI32DivU 134 | AI32RemS 135 | AI32RemU 136 | AI32And 137 | AI32Or 138 | AI32Xor 139 | AI32Shl 140 | AI32ShrS 141 | AI32ShrU 142 | AI32Rotl 143 | AI32Rotr 144 | 145 | AI64Clz 146 | AI64Ctz 147 | AI64Popcnt 148 | AI64Add 149 | AI64Sub 150 | AI64Mul 151 | AI64DivS 152 | AI64DivU 153 | AI64RemS 154 | AI64RemU 155 | AI64And 156 | AI64Or 157 | AI64Xor 158 | AI64Shl 159 | AI64ShrS 160 | AI64ShrU 161 | AI64Rotl 162 | AI64Rotr 163 | 164 | AF32Abs 165 | AF32Neg 166 | AF32Ceil 167 | AF32Floor 168 | AF32Trunc 169 | AF32Nearest 170 | AF32Sqrt 171 | AF32Add 172 | AF32Sub 173 | AF32Mul 174 | AF32Div 175 | AF32Min 176 | AF32Max 177 | AF32Copysign 178 | 179 | AF64Abs 180 | AF64Neg 181 | AF64Ceil 182 | AF64Floor 183 | AF64Trunc 184 | AF64Nearest 185 | AF64Sqrt 186 | AF64Add 187 | AF64Sub 188 | AF64Mul 189 | AF64Div 190 | AF64Min 191 | AF64Max 192 | AF64Copysign 193 | 194 | AI32WrapI64 195 | AI32TruncF32S 196 | AI32TruncF32U 197 | AI32TruncF64S 198 | AI32TruncF64U 199 | AI64ExtendI32S 200 | AI64ExtendI32U 201 | AI64TruncF32S 202 | AI64TruncF32U 203 | AI64TruncF64S 204 | AI64TruncF64U 205 | AF32ConvertI32S 206 | AF32ConvertI32U 207 | AF32ConvertI64S 208 | AF32ConvertI64U 209 | AF32DemoteF64 210 | AF64ConvertI32S 211 | AF64ConvertI32U 212 | AF64ConvertI64S 213 | AF64ConvertI64U 214 | AF64PromoteF32 215 | AI32ReinterpretF32 216 | AI64ReinterpretF64 217 | AF32ReinterpretI32 218 | AF64ReinterpretI64 219 | AI32Extend8S 220 | AI32Extend16S 221 | AI64Extend8S 222 | AI64Extend16S 223 | AI64Extend32S 224 | 225 | AI32TruncSatF32S // opcode 0xFC 0x00 226 | AI32TruncSatF32U 227 | AI32TruncSatF64S 228 | AI32TruncSatF64U 229 | AI64TruncSatF32S 230 | AI64TruncSatF32U 231 | AI64TruncSatF64S 232 | AI64TruncSatF64U 233 | 234 | ALast // Sentinel: End of low-level WebAssembly instructions. 235 | 236 | ARESUMEPOINT 237 | // ACALLNORESUME is a call which is not followed by a resume point. 238 | // It is allowed inside of WebAssembly blocks, whereas obj.ACALL is not. 239 | // However, it is not allowed to switch goroutines while inside of an ACALLNORESUME call. 240 | ACALLNORESUME 241 | 242 | ARETUNWIND 243 | 244 | AMOVB 245 | AMOVH 246 | AMOVW 247 | AMOVD 248 | 249 | AWORD 250 | ALAST 251 | ) 252 | 253 | const ( 254 | REG_NONE = 0 255 | ) 256 | 257 | const ( 258 | // globals 259 | REG_SP = obj.RBaseWasm + iota // SP is currently 32-bit, until 64-bit memory operations are available 260 | REG_CTXT 261 | REG_g 262 | // RET* are used by runtime.return0 and runtime.reflectcall. These functions pass return values in registers. 263 | REG_RET0 264 | REG_RET1 265 | REG_RET2 266 | REG_RET3 267 | REG_PAUSE 268 | 269 | // i32 locals 270 | REG_R0 271 | REG_R1 272 | REG_R2 273 | REG_R3 274 | REG_R4 275 | REG_R5 276 | REG_R6 277 | REG_R7 278 | REG_R8 279 | REG_R9 280 | REG_R10 281 | REG_R11 282 | REG_R12 283 | REG_R13 284 | REG_R14 285 | REG_R15 286 | 287 | // f32 locals 288 | REG_F0 289 | REG_F1 290 | REG_F2 291 | REG_F3 292 | REG_F4 293 | REG_F5 294 | REG_F6 295 | REG_F7 296 | REG_F8 297 | REG_F9 298 | REG_F10 299 | REG_F11 300 | REG_F12 301 | REG_F13 302 | REG_F14 303 | REG_F15 304 | 305 | // f64 locals 306 | REG_F16 307 | REG_F17 308 | REG_F18 309 | REG_F19 310 | REG_F20 311 | REG_F21 312 | REG_F22 313 | REG_F23 314 | REG_F24 315 | REG_F25 316 | REG_F26 317 | REG_F27 318 | REG_F28 319 | REG_F29 320 | REG_F30 321 | REG_F31 322 | 323 | REG_PC_B // also first parameter, i32 324 | 325 | MAXREG 326 | 327 | MINREG = REG_SP 328 | REGSP = REG_SP 329 | REGCTXT = REG_CTXT 330 | REGG = REG_g 331 | ) 332 | -------------------------------------------------------------------------------- /obj/data.go: -------------------------------------------------------------------------------- 1 | // Derived from Inferno utils/6l/obj.c and utils/6l/span.c 2 | // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/obj.c 3 | // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/span.c 4 | // 5 | // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 6 | // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 7 | // Portions Copyright © 1997-1999 Vita Nuova Limited 8 | // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 9 | // Portions Copyright © 2004,2006 Bruce Ellis 10 | // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 11 | // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 12 | // Portions Copyright © 2009 The Go Authors. All rights reserved. 13 | // 14 | // Permission is hereby granted, free of charge, to any person obtaining a copy 15 | // of this software and associated documentation files (the "Software"), to deal 16 | // in the Software without restriction, including without limitation the rights 17 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | // copies of the Software, and to permit persons to whom the Software is 19 | // furnished to do so, subject to the following conditions: 20 | // 21 | // The above copyright notice and this permission notice shall be included in 22 | // all copies or substantial portions of the Software. 23 | // 24 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 30 | // THE SOFTWARE. 31 | 32 | package obj 33 | 34 | import ( 35 | "github.com/twitchyliquid64/golang-asm/objabi" 36 | "log" 37 | "math" 38 | ) 39 | 40 | // Grow increases the length of s.P to lsiz. 41 | func (s *LSym) Grow(lsiz int64) { 42 | siz := int(lsiz) 43 | if int64(siz) != lsiz { 44 | log.Fatalf("LSym.Grow size %d too long", lsiz) 45 | } 46 | if len(s.P) >= siz { 47 | return 48 | } 49 | s.P = append(s.P, make([]byte, siz-len(s.P))...) 50 | } 51 | 52 | // GrowCap increases the capacity of s.P to c. 53 | func (s *LSym) GrowCap(c int64) { 54 | if int64(cap(s.P)) >= c { 55 | return 56 | } 57 | if s.P == nil { 58 | s.P = make([]byte, 0, c) 59 | return 60 | } 61 | b := make([]byte, len(s.P), c) 62 | copy(b, s.P) 63 | s.P = b 64 | } 65 | 66 | // prepwrite prepares to write data of size siz into s at offset off. 67 | func (s *LSym) prepwrite(ctxt *Link, off int64, siz int) { 68 | if off < 0 || siz < 0 || off >= 1<<30 { 69 | ctxt.Diag("prepwrite: bad off=%d siz=%d s=%v", off, siz, s) 70 | } 71 | switch s.Type { 72 | case objabi.Sxxx, objabi.SBSS: 73 | s.Type = objabi.SDATA 74 | case objabi.SNOPTRBSS: 75 | s.Type = objabi.SNOPTRDATA 76 | case objabi.STLSBSS: 77 | ctxt.Diag("cannot supply data for %v var %v", s.Type, s.Name) 78 | } 79 | l := off + int64(siz) 80 | s.Grow(l) 81 | if l > s.Size { 82 | s.Size = l 83 | } 84 | } 85 | 86 | // WriteFloat32 writes f into s at offset off. 87 | func (s *LSym) WriteFloat32(ctxt *Link, off int64, f float32) { 88 | s.prepwrite(ctxt, off, 4) 89 | ctxt.Arch.ByteOrder.PutUint32(s.P[off:], math.Float32bits(f)) 90 | } 91 | 92 | // WriteFloat64 writes f into s at offset off. 93 | func (s *LSym) WriteFloat64(ctxt *Link, off int64, f float64) { 94 | s.prepwrite(ctxt, off, 8) 95 | ctxt.Arch.ByteOrder.PutUint64(s.P[off:], math.Float64bits(f)) 96 | } 97 | 98 | // WriteInt writes an integer i of size siz into s at offset off. 99 | func (s *LSym) WriteInt(ctxt *Link, off int64, siz int, i int64) { 100 | s.prepwrite(ctxt, off, siz) 101 | switch siz { 102 | default: 103 | ctxt.Diag("WriteInt: bad integer size: %d", siz) 104 | case 1: 105 | s.P[off] = byte(i) 106 | case 2: 107 | ctxt.Arch.ByteOrder.PutUint16(s.P[off:], uint16(i)) 108 | case 4: 109 | ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(i)) 110 | case 8: 111 | ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(i)) 112 | } 113 | } 114 | 115 | func (s *LSym) writeAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64, rtype objabi.RelocType) { 116 | // Allow 4-byte addresses for DWARF. 117 | if siz != ctxt.Arch.PtrSize && siz != 4 { 118 | ctxt.Diag("WriteAddr: bad address size %d in %s", siz, s.Name) 119 | } 120 | s.prepwrite(ctxt, off, siz) 121 | r := Addrel(s) 122 | r.Off = int32(off) 123 | if int64(r.Off) != off { 124 | ctxt.Diag("WriteAddr: off overflow %d in %s", off, s.Name) 125 | } 126 | r.Siz = uint8(siz) 127 | r.Sym = rsym 128 | r.Type = rtype 129 | r.Add = roff 130 | } 131 | 132 | // WriteAddr writes an address of size siz into s at offset off. 133 | // rsym and roff specify the relocation for the address. 134 | func (s *LSym) WriteAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64) { 135 | s.writeAddr(ctxt, off, siz, rsym, roff, objabi.R_ADDR) 136 | } 137 | 138 | // WriteCURelativeAddr writes a pointer-sized address into s at offset off. 139 | // rsym and roff specify the relocation for the address which will be 140 | // resolved by the linker to an offset from the DW_AT_low_pc attribute of 141 | // the DWARF Compile Unit of rsym. 142 | func (s *LSym) WriteCURelativeAddr(ctxt *Link, off int64, rsym *LSym, roff int64) { 143 | s.writeAddr(ctxt, off, ctxt.Arch.PtrSize, rsym, roff, objabi.R_ADDRCUOFF) 144 | } 145 | 146 | // WriteOff writes a 4 byte offset to rsym+roff into s at offset off. 147 | // After linking the 4 bytes stored at s+off will be 148 | // rsym+roff-(start of section that s is in). 149 | func (s *LSym) WriteOff(ctxt *Link, off int64, rsym *LSym, roff int64) { 150 | s.prepwrite(ctxt, off, 4) 151 | r := Addrel(s) 152 | r.Off = int32(off) 153 | if int64(r.Off) != off { 154 | ctxt.Diag("WriteOff: off overflow %d in %s", off, s.Name) 155 | } 156 | r.Siz = 4 157 | r.Sym = rsym 158 | r.Type = objabi.R_ADDROFF 159 | r.Add = roff 160 | } 161 | 162 | // WriteWeakOff writes a weak 4 byte offset to rsym+roff into s at offset off. 163 | // After linking the 4 bytes stored at s+off will be 164 | // rsym+roff-(start of section that s is in). 165 | func (s *LSym) WriteWeakOff(ctxt *Link, off int64, rsym *LSym, roff int64) { 166 | s.prepwrite(ctxt, off, 4) 167 | r := Addrel(s) 168 | r.Off = int32(off) 169 | if int64(r.Off) != off { 170 | ctxt.Diag("WriteOff: off overflow %d in %s", off, s.Name) 171 | } 172 | r.Siz = 4 173 | r.Sym = rsym 174 | r.Type = objabi.R_WEAKADDROFF 175 | r.Add = roff 176 | } 177 | 178 | // WriteString writes a string of size siz into s at offset off. 179 | func (s *LSym) WriteString(ctxt *Link, off int64, siz int, str string) { 180 | if siz < len(str) { 181 | ctxt.Diag("WriteString: bad string size: %d < %d", siz, len(str)) 182 | } 183 | s.prepwrite(ctxt, off, siz) 184 | copy(s.P[off:off+int64(siz)], str) 185 | } 186 | 187 | // WriteBytes writes a slice of bytes into s at offset off. 188 | func (s *LSym) WriteBytes(ctxt *Link, off int64, b []byte) int64 { 189 | s.prepwrite(ctxt, off, len(b)) 190 | copy(s.P[off:], b) 191 | return off + int64(len(b)) 192 | } 193 | 194 | func Addrel(s *LSym) *Reloc { 195 | if s.R == nil { 196 | s.R = make([]Reloc, 0, 4) 197 | } 198 | s.R = append(s.R, Reloc{}) 199 | return &s.R[len(s.R)-1] 200 | } 201 | -------------------------------------------------------------------------------- /goobj/funcinfo.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goobj 6 | 7 | import ( 8 | "bytes" 9 | "github.com/twitchyliquid64/golang-asm/objabi" 10 | "encoding/binary" 11 | ) 12 | 13 | // CUFileIndex is used to index the filenames that are stored in the 14 | // per-package/per-CU FileList. 15 | type CUFileIndex uint32 16 | 17 | // FuncInfo is serialized as a symbol (aux symbol). The symbol data is 18 | // the binary encoding of the struct below. 19 | // 20 | // TODO: make each pcdata a separate symbol? 21 | type FuncInfo struct { 22 | Args uint32 23 | Locals uint32 24 | FuncID objabi.FuncID 25 | 26 | Pcsp uint32 27 | Pcfile uint32 28 | Pcline uint32 29 | Pcinline uint32 30 | Pcdata []uint32 31 | PcdataEnd uint32 32 | Funcdataoff []uint32 33 | File []CUFileIndex 34 | 35 | InlTree []InlTreeNode 36 | } 37 | 38 | func (a *FuncInfo) Write(w *bytes.Buffer) { 39 | var b [4]byte 40 | writeUint32 := func(x uint32) { 41 | binary.LittleEndian.PutUint32(b[:], x) 42 | w.Write(b[:]) 43 | } 44 | 45 | writeUint32(a.Args) 46 | writeUint32(a.Locals) 47 | writeUint32(uint32(a.FuncID)) 48 | 49 | writeUint32(a.Pcsp) 50 | writeUint32(a.Pcfile) 51 | writeUint32(a.Pcline) 52 | writeUint32(a.Pcinline) 53 | writeUint32(uint32(len(a.Pcdata))) 54 | for _, x := range a.Pcdata { 55 | writeUint32(x) 56 | } 57 | writeUint32(a.PcdataEnd) 58 | writeUint32(uint32(len(a.Funcdataoff))) 59 | for _, x := range a.Funcdataoff { 60 | writeUint32(x) 61 | } 62 | writeUint32(uint32(len(a.File))) 63 | for _, f := range a.File { 64 | writeUint32(uint32(f)) 65 | } 66 | writeUint32(uint32(len(a.InlTree))) 67 | for i := range a.InlTree { 68 | a.InlTree[i].Write(w) 69 | } 70 | } 71 | 72 | func (a *FuncInfo) Read(b []byte) { 73 | readUint32 := func() uint32 { 74 | x := binary.LittleEndian.Uint32(b) 75 | b = b[4:] 76 | return x 77 | } 78 | 79 | a.Args = readUint32() 80 | a.Locals = readUint32() 81 | a.FuncID = objabi.FuncID(readUint32()) 82 | 83 | a.Pcsp = readUint32() 84 | a.Pcfile = readUint32() 85 | a.Pcline = readUint32() 86 | a.Pcinline = readUint32() 87 | pcdatalen := readUint32() 88 | a.Pcdata = make([]uint32, pcdatalen) 89 | for i := range a.Pcdata { 90 | a.Pcdata[i] = readUint32() 91 | } 92 | a.PcdataEnd = readUint32() 93 | funcdataofflen := readUint32() 94 | a.Funcdataoff = make([]uint32, funcdataofflen) 95 | for i := range a.Funcdataoff { 96 | a.Funcdataoff[i] = readUint32() 97 | } 98 | filelen := readUint32() 99 | a.File = make([]CUFileIndex, filelen) 100 | for i := range a.File { 101 | a.File[i] = CUFileIndex(readUint32()) 102 | } 103 | inltreelen := readUint32() 104 | a.InlTree = make([]InlTreeNode, inltreelen) 105 | for i := range a.InlTree { 106 | b = a.InlTree[i].Read(b) 107 | } 108 | } 109 | 110 | // FuncInfoLengths is a cache containing a roadmap of offsets and 111 | // lengths for things within a serialized FuncInfo. Each length field 112 | // stores the number of items (e.g. files, inltree nodes, etc), and the 113 | // corresponding "off" field stores the byte offset of the start of 114 | // the items in question. 115 | type FuncInfoLengths struct { 116 | NumPcdata uint32 117 | PcdataOff uint32 118 | NumFuncdataoff uint32 119 | FuncdataoffOff uint32 120 | NumFile uint32 121 | FileOff uint32 122 | NumInlTree uint32 123 | InlTreeOff uint32 124 | Initialized bool 125 | } 126 | 127 | func (*FuncInfo) ReadFuncInfoLengths(b []byte) FuncInfoLengths { 128 | var result FuncInfoLengths 129 | 130 | const numpcdataOff = 28 131 | result.NumPcdata = binary.LittleEndian.Uint32(b[numpcdataOff:]) 132 | result.PcdataOff = numpcdataOff + 4 133 | 134 | numfuncdataoffOff := result.PcdataOff + 4*(result.NumPcdata+1) 135 | result.NumFuncdataoff = binary.LittleEndian.Uint32(b[numfuncdataoffOff:]) 136 | result.FuncdataoffOff = numfuncdataoffOff + 4 137 | 138 | numfileOff := result.FuncdataoffOff + 4*result.NumFuncdataoff 139 | result.NumFile = binary.LittleEndian.Uint32(b[numfileOff:]) 140 | result.FileOff = numfileOff + 4 141 | 142 | numinltreeOff := result.FileOff + 4*result.NumFile 143 | result.NumInlTree = binary.LittleEndian.Uint32(b[numinltreeOff:]) 144 | result.InlTreeOff = numinltreeOff + 4 145 | 146 | result.Initialized = true 147 | 148 | return result 149 | } 150 | 151 | func (*FuncInfo) ReadArgs(b []byte) uint32 { return binary.LittleEndian.Uint32(b) } 152 | 153 | func (*FuncInfo) ReadLocals(b []byte) uint32 { return binary.LittleEndian.Uint32(b[4:]) } 154 | 155 | func (*FuncInfo) ReadFuncID(b []byte) uint32 { return binary.LittleEndian.Uint32(b[8:]) } 156 | 157 | // return start and end offsets. 158 | func (*FuncInfo) ReadPcsp(b []byte) (uint32, uint32) { 159 | return binary.LittleEndian.Uint32(b[12:]), binary.LittleEndian.Uint32(b[16:]) 160 | } 161 | 162 | // return start and end offsets. 163 | func (*FuncInfo) ReadPcfile(b []byte) (uint32, uint32) { 164 | return binary.LittleEndian.Uint32(b[16:]), binary.LittleEndian.Uint32(b[20:]) 165 | } 166 | 167 | // return start and end offsets. 168 | func (*FuncInfo) ReadPcline(b []byte) (uint32, uint32) { 169 | return binary.LittleEndian.Uint32(b[20:]), binary.LittleEndian.Uint32(b[24:]) 170 | } 171 | 172 | // return start and end offsets. 173 | func (*FuncInfo) ReadPcinline(b []byte, pcdataoffset uint32) (uint32, uint32) { 174 | return binary.LittleEndian.Uint32(b[24:]), binary.LittleEndian.Uint32(b[pcdataoffset:]) 175 | } 176 | 177 | // return start and end offsets. 178 | func (*FuncInfo) ReadPcdata(b []byte, pcdataoffset uint32, k uint32) (uint32, uint32) { 179 | return binary.LittleEndian.Uint32(b[pcdataoffset+4*k:]), binary.LittleEndian.Uint32(b[pcdataoffset+4+4*k:]) 180 | } 181 | 182 | func (*FuncInfo) ReadFuncdataoff(b []byte, funcdataofffoff uint32, k uint32) int64 { 183 | return int64(binary.LittleEndian.Uint32(b[funcdataofffoff+4*k:])) 184 | } 185 | 186 | func (*FuncInfo) ReadFile(b []byte, filesoff uint32, k uint32) CUFileIndex { 187 | return CUFileIndex(binary.LittleEndian.Uint32(b[filesoff+4*k:])) 188 | } 189 | 190 | func (*FuncInfo) ReadInlTree(b []byte, inltreeoff uint32, k uint32) InlTreeNode { 191 | const inlTreeNodeSize = 4 * 6 192 | var result InlTreeNode 193 | result.Read(b[inltreeoff+k*inlTreeNodeSize:]) 194 | return result 195 | } 196 | 197 | // InlTreeNode is the serialized form of FileInfo.InlTree. 198 | type InlTreeNode struct { 199 | Parent int32 200 | File CUFileIndex 201 | Line int32 202 | Func SymRef 203 | ParentPC int32 204 | } 205 | 206 | func (inl *InlTreeNode) Write(w *bytes.Buffer) { 207 | var b [4]byte 208 | writeUint32 := func(x uint32) { 209 | binary.LittleEndian.PutUint32(b[:], x) 210 | w.Write(b[:]) 211 | } 212 | writeUint32(uint32(inl.Parent)) 213 | writeUint32(uint32(inl.File)) 214 | writeUint32(uint32(inl.Line)) 215 | writeUint32(inl.Func.PkgIdx) 216 | writeUint32(inl.Func.SymIdx) 217 | writeUint32(uint32(inl.ParentPC)) 218 | } 219 | 220 | // Read an InlTreeNode from b, return the remaining bytes. 221 | func (inl *InlTreeNode) Read(b []byte) []byte { 222 | readUint32 := func() uint32 { 223 | x := binary.LittleEndian.Uint32(b) 224 | b = b[4:] 225 | return x 226 | } 227 | inl.Parent = int32(readUint32()) 228 | inl.File = CUFileIndex(readUint32()) 229 | inl.Line = int32(readUint32()) 230 | inl.Func = SymRef{readUint32(), readUint32()} 231 | inl.ParentPC = int32(readUint32()) 232 | return b 233 | } 234 | -------------------------------------------------------------------------------- /asm/arch/arm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file encapsulates some of the odd characteristics of the ARM 6 | // instruction set, to minimize its interaction with the core of the 7 | // assembler. 8 | 9 | package arch 10 | 11 | import ( 12 | "strings" 13 | 14 | "github.com/twitchyliquid64/golang-asm/obj" 15 | "github.com/twitchyliquid64/golang-asm/obj/arm" 16 | ) 17 | 18 | var armLS = map[string]uint8{ 19 | "U": arm.C_UBIT, 20 | "S": arm.C_SBIT, 21 | "W": arm.C_WBIT, 22 | "P": arm.C_PBIT, 23 | "PW": arm.C_WBIT | arm.C_PBIT, 24 | "WP": arm.C_WBIT | arm.C_PBIT, 25 | } 26 | 27 | var armSCOND = map[string]uint8{ 28 | "EQ": arm.C_SCOND_EQ, 29 | "NE": arm.C_SCOND_NE, 30 | "CS": arm.C_SCOND_HS, 31 | "HS": arm.C_SCOND_HS, 32 | "CC": arm.C_SCOND_LO, 33 | "LO": arm.C_SCOND_LO, 34 | "MI": arm.C_SCOND_MI, 35 | "PL": arm.C_SCOND_PL, 36 | "VS": arm.C_SCOND_VS, 37 | "VC": arm.C_SCOND_VC, 38 | "HI": arm.C_SCOND_HI, 39 | "LS": arm.C_SCOND_LS, 40 | "GE": arm.C_SCOND_GE, 41 | "LT": arm.C_SCOND_LT, 42 | "GT": arm.C_SCOND_GT, 43 | "LE": arm.C_SCOND_LE, 44 | "AL": arm.C_SCOND_NONE, 45 | "U": arm.C_UBIT, 46 | "S": arm.C_SBIT, 47 | "W": arm.C_WBIT, 48 | "P": arm.C_PBIT, 49 | "PW": arm.C_WBIT | arm.C_PBIT, 50 | "WP": arm.C_WBIT | arm.C_PBIT, 51 | "F": arm.C_FBIT, 52 | "IBW": arm.C_WBIT | arm.C_PBIT | arm.C_UBIT, 53 | "IAW": arm.C_WBIT | arm.C_UBIT, 54 | "DBW": arm.C_WBIT | arm.C_PBIT, 55 | "DAW": arm.C_WBIT, 56 | "IB": arm.C_PBIT | arm.C_UBIT, 57 | "IA": arm.C_UBIT, 58 | "DB": arm.C_PBIT, 59 | "DA": 0, 60 | } 61 | 62 | var armJump = map[string]bool{ 63 | "B": true, 64 | "BL": true, 65 | "BX": true, 66 | "BEQ": true, 67 | "BNE": true, 68 | "BCS": true, 69 | "BHS": true, 70 | "BCC": true, 71 | "BLO": true, 72 | "BMI": true, 73 | "BPL": true, 74 | "BVS": true, 75 | "BVC": true, 76 | "BHI": true, 77 | "BLS": true, 78 | "BGE": true, 79 | "BLT": true, 80 | "BGT": true, 81 | "BLE": true, 82 | "CALL": true, 83 | "JMP": true, 84 | } 85 | 86 | func jumpArm(word string) bool { 87 | return armJump[word] 88 | } 89 | 90 | // IsARMCMP reports whether the op (as defined by an arm.A* constant) is 91 | // one of the comparison instructions that require special handling. 92 | func IsARMCMP(op obj.As) bool { 93 | switch op { 94 | case arm.ACMN, arm.ACMP, arm.ATEQ, arm.ATST: 95 | return true 96 | } 97 | return false 98 | } 99 | 100 | // IsARMSTREX reports whether the op (as defined by an arm.A* constant) is 101 | // one of the STREX-like instructions that require special handling. 102 | func IsARMSTREX(op obj.As) bool { 103 | switch op { 104 | case arm.ASTREX, arm.ASTREXD, arm.ASWPW, arm.ASWPBU: 105 | return true 106 | } 107 | return false 108 | } 109 | 110 | // MCR is not defined by the obj/arm; instead we define it privately here. 111 | // It is encoded as an MRC with a bit inside the instruction word, 112 | // passed to arch.ARMMRCOffset. 113 | const aMCR = arm.ALAST + 1 114 | 115 | // IsARMMRC reports whether the op (as defined by an arm.A* constant) is 116 | // MRC or MCR 117 | func IsARMMRC(op obj.As) bool { 118 | switch op { 119 | case arm.AMRC, aMCR: // Note: aMCR is defined in this package. 120 | return true 121 | } 122 | return false 123 | } 124 | 125 | // IsARMBFX reports whether the op (as defined by an arm.A* constant) is one the 126 | // BFX-like instructions which are in the form of "op $width, $LSB, (Reg,) Reg". 127 | func IsARMBFX(op obj.As) bool { 128 | switch op { 129 | case arm.ABFX, arm.ABFXU, arm.ABFC, arm.ABFI: 130 | return true 131 | } 132 | return false 133 | } 134 | 135 | // IsARMFloatCmp reports whether the op is a floating comparison instruction. 136 | func IsARMFloatCmp(op obj.As) bool { 137 | switch op { 138 | case arm.ACMPF, arm.ACMPD: 139 | return true 140 | } 141 | return false 142 | } 143 | 144 | // ARMMRCOffset implements the peculiar encoding of the MRC and MCR instructions. 145 | // The difference between MRC and MCR is represented by a bit high in the word, not 146 | // in the usual way by the opcode itself. Asm must use AMRC for both instructions, so 147 | // we return the opcode for MRC so that asm doesn't need to import obj/arm. 148 | func ARMMRCOffset(op obj.As, cond string, x0, x1, x2, x3, x4, x5 int64) (offset int64, op0 obj.As, ok bool) { 149 | op1 := int64(0) 150 | if op == arm.AMRC { 151 | op1 = 1 152 | } 153 | bits, ok := ParseARMCondition(cond) 154 | if !ok { 155 | return 156 | } 157 | offset = (0xe << 24) | // opcode 158 | (op1 << 20) | // MCR/MRC 159 | ((int64(bits) ^ arm.C_SCOND_XOR) << 28) | // scond 160 | ((x0 & 15) << 8) | //coprocessor number 161 | ((x1 & 7) << 21) | // coprocessor operation 162 | ((x2 & 15) << 12) | // ARM register 163 | ((x3 & 15) << 16) | // Crn 164 | ((x4 & 15) << 0) | // Crm 165 | ((x5 & 7) << 5) | // coprocessor information 166 | (1 << 4) /* must be set */ 167 | return offset, arm.AMRC, true 168 | } 169 | 170 | // IsARMMULA reports whether the op (as defined by an arm.A* constant) is 171 | // MULA, MULS, MMULA, MMULS, MULABB, MULAWB or MULAWT, the 4-operand instructions. 172 | func IsARMMULA(op obj.As) bool { 173 | switch op { 174 | case arm.AMULA, arm.AMULS, arm.AMMULA, arm.AMMULS, arm.AMULABB, arm.AMULAWB, arm.AMULAWT: 175 | return true 176 | } 177 | return false 178 | } 179 | 180 | var bcode = []obj.As{ 181 | arm.ABEQ, 182 | arm.ABNE, 183 | arm.ABCS, 184 | arm.ABCC, 185 | arm.ABMI, 186 | arm.ABPL, 187 | arm.ABVS, 188 | arm.ABVC, 189 | arm.ABHI, 190 | arm.ABLS, 191 | arm.ABGE, 192 | arm.ABLT, 193 | arm.ABGT, 194 | arm.ABLE, 195 | arm.AB, 196 | obj.ANOP, 197 | } 198 | 199 | // ARMConditionCodes handles the special condition code situation for the ARM. 200 | // It returns a boolean to indicate success; failure means cond was unrecognized. 201 | func ARMConditionCodes(prog *obj.Prog, cond string) bool { 202 | if cond == "" { 203 | return true 204 | } 205 | bits, ok := ParseARMCondition(cond) 206 | if !ok { 207 | return false 208 | } 209 | /* hack to make B.NE etc. work: turn it into the corresponding conditional */ 210 | if prog.As == arm.AB { 211 | prog.As = bcode[(bits^arm.C_SCOND_XOR)&0xf] 212 | bits = (bits &^ 0xf) | arm.C_SCOND_NONE 213 | } 214 | prog.Scond = bits 215 | return true 216 | } 217 | 218 | // ParseARMCondition parses the conditions attached to an ARM instruction. 219 | // The input is a single string consisting of period-separated condition 220 | // codes, such as ".P.W". An initial period is ignored. 221 | func ParseARMCondition(cond string) (uint8, bool) { 222 | return parseARMCondition(cond, armLS, armSCOND) 223 | } 224 | 225 | func parseARMCondition(cond string, ls, scond map[string]uint8) (uint8, bool) { 226 | cond = strings.TrimPrefix(cond, ".") 227 | if cond == "" { 228 | return arm.C_SCOND_NONE, true 229 | } 230 | names := strings.Split(cond, ".") 231 | bits := uint8(0) 232 | for _, name := range names { 233 | if b, present := ls[name]; present { 234 | bits |= b 235 | continue 236 | } 237 | if b, present := scond[name]; present { 238 | bits = (bits &^ arm.C_SCOND) | b 239 | continue 240 | } 241 | return 0, false 242 | } 243 | return bits, true 244 | } 245 | 246 | func armRegisterNumber(name string, n int16) (int16, bool) { 247 | if n < 0 || 15 < n { 248 | return 0, false 249 | } 250 | switch name { 251 | case "R": 252 | return arm.REG_R0 + n, true 253 | case "F": 254 | return arm.REG_F0 + n, true 255 | } 256 | return 0, false 257 | } 258 | -------------------------------------------------------------------------------- /obj/arm64/anames.go: -------------------------------------------------------------------------------- 1 | // Code generated by stringer -i a.out.go -o anames.go -p arm64; DO NOT EDIT. 2 | 3 | package arm64 4 | 5 | import "github.com/twitchyliquid64/golang-asm/obj" 6 | 7 | var Anames = []string{ 8 | obj.A_ARCHSPECIFIC: "ADC", 9 | "ADCS", 10 | "ADCSW", 11 | "ADCW", 12 | "ADD", 13 | "ADDS", 14 | "ADDSW", 15 | "ADDW", 16 | "ADR", 17 | "ADRP", 18 | "AND", 19 | "ANDS", 20 | "ANDSW", 21 | "ANDW", 22 | "ASR", 23 | "ASRW", 24 | "AT", 25 | "BFI", 26 | "BFIW", 27 | "BFM", 28 | "BFMW", 29 | "BFXIL", 30 | "BFXILW", 31 | "BIC", 32 | "BICS", 33 | "BICSW", 34 | "BICW", 35 | "BRK", 36 | "CBNZ", 37 | "CBNZW", 38 | "CBZ", 39 | "CBZW", 40 | "CCMN", 41 | "CCMNW", 42 | "CCMP", 43 | "CCMPW", 44 | "CINC", 45 | "CINCW", 46 | "CINV", 47 | "CINVW", 48 | "CLREX", 49 | "CLS", 50 | "CLSW", 51 | "CLZ", 52 | "CLZW", 53 | "CMN", 54 | "CMNW", 55 | "CMP", 56 | "CMPW", 57 | "CNEG", 58 | "CNEGW", 59 | "CRC32B", 60 | "CRC32CB", 61 | "CRC32CH", 62 | "CRC32CW", 63 | "CRC32CX", 64 | "CRC32H", 65 | "CRC32W", 66 | "CRC32X", 67 | "CSEL", 68 | "CSELW", 69 | "CSET", 70 | "CSETM", 71 | "CSETMW", 72 | "CSETW", 73 | "CSINC", 74 | "CSINCW", 75 | "CSINV", 76 | "CSINVW", 77 | "CSNEG", 78 | "CSNEGW", 79 | "DC", 80 | "DCPS1", 81 | "DCPS2", 82 | "DCPS3", 83 | "DMB", 84 | "DRPS", 85 | "DSB", 86 | "EON", 87 | "EONW", 88 | "EOR", 89 | "EORW", 90 | "ERET", 91 | "EXTR", 92 | "EXTRW", 93 | "HINT", 94 | "HLT", 95 | "HVC", 96 | "IC", 97 | "ISB", 98 | "LDADDAB", 99 | "LDADDAD", 100 | "LDADDAH", 101 | "LDADDAW", 102 | "LDADDALB", 103 | "LDADDALD", 104 | "LDADDALH", 105 | "LDADDALW", 106 | "LDADDB", 107 | "LDADDD", 108 | "LDADDH", 109 | "LDADDW", 110 | "LDADDLB", 111 | "LDADDLD", 112 | "LDADDLH", 113 | "LDADDLW", 114 | "LDANDAB", 115 | "LDANDAD", 116 | "LDANDAH", 117 | "LDANDAW", 118 | "LDANDALB", 119 | "LDANDALD", 120 | "LDANDALH", 121 | "LDANDALW", 122 | "LDANDB", 123 | "LDANDD", 124 | "LDANDH", 125 | "LDANDW", 126 | "LDANDLB", 127 | "LDANDLD", 128 | "LDANDLH", 129 | "LDANDLW", 130 | "LDAR", 131 | "LDARB", 132 | "LDARH", 133 | "LDARW", 134 | "LDAXP", 135 | "LDAXPW", 136 | "LDAXR", 137 | "LDAXRB", 138 | "LDAXRH", 139 | "LDAXRW", 140 | "LDEORAB", 141 | "LDEORAD", 142 | "LDEORAH", 143 | "LDEORAW", 144 | "LDEORALB", 145 | "LDEORALD", 146 | "LDEORALH", 147 | "LDEORALW", 148 | "LDEORB", 149 | "LDEORD", 150 | "LDEORH", 151 | "LDEORW", 152 | "LDEORLB", 153 | "LDEORLD", 154 | "LDEORLH", 155 | "LDEORLW", 156 | "LDORAB", 157 | "LDORAD", 158 | "LDORAH", 159 | "LDORAW", 160 | "LDORALB", 161 | "LDORALD", 162 | "LDORALH", 163 | "LDORALW", 164 | "LDORB", 165 | "LDORD", 166 | "LDORH", 167 | "LDORW", 168 | "LDORLB", 169 | "LDORLD", 170 | "LDORLH", 171 | "LDORLW", 172 | "LDP", 173 | "LDPW", 174 | "LDPSW", 175 | "LDXR", 176 | "LDXRB", 177 | "LDXRH", 178 | "LDXRW", 179 | "LDXP", 180 | "LDXPW", 181 | "LSL", 182 | "LSLW", 183 | "LSR", 184 | "LSRW", 185 | "MADD", 186 | "MADDW", 187 | "MNEG", 188 | "MNEGW", 189 | "MOVK", 190 | "MOVKW", 191 | "MOVN", 192 | "MOVNW", 193 | "MOVZ", 194 | "MOVZW", 195 | "MRS", 196 | "MSR", 197 | "MSUB", 198 | "MSUBW", 199 | "MUL", 200 | "MULW", 201 | "MVN", 202 | "MVNW", 203 | "NEG", 204 | "NEGS", 205 | "NEGSW", 206 | "NEGW", 207 | "NGC", 208 | "NGCS", 209 | "NGCSW", 210 | "NGCW", 211 | "NOOP", 212 | "ORN", 213 | "ORNW", 214 | "ORR", 215 | "ORRW", 216 | "PRFM", 217 | "PRFUM", 218 | "RBIT", 219 | "RBITW", 220 | "REM", 221 | "REMW", 222 | "REV", 223 | "REV16", 224 | "REV16W", 225 | "REV32", 226 | "REVW", 227 | "ROR", 228 | "RORW", 229 | "SBC", 230 | "SBCS", 231 | "SBCSW", 232 | "SBCW", 233 | "SBFIZ", 234 | "SBFIZW", 235 | "SBFM", 236 | "SBFMW", 237 | "SBFX", 238 | "SBFXW", 239 | "SDIV", 240 | "SDIVW", 241 | "SEV", 242 | "SEVL", 243 | "SMADDL", 244 | "SMC", 245 | "SMNEGL", 246 | "SMSUBL", 247 | "SMULH", 248 | "SMULL", 249 | "STXR", 250 | "STXRB", 251 | "STXRH", 252 | "STXP", 253 | "STXPW", 254 | "STXRW", 255 | "STLP", 256 | "STLPW", 257 | "STLR", 258 | "STLRB", 259 | "STLRH", 260 | "STLRW", 261 | "STLXP", 262 | "STLXPW", 263 | "STLXR", 264 | "STLXRB", 265 | "STLXRH", 266 | "STLXRW", 267 | "STP", 268 | "STPW", 269 | "SUB", 270 | "SUBS", 271 | "SUBSW", 272 | "SUBW", 273 | "SVC", 274 | "SXTB", 275 | "SXTBW", 276 | "SXTH", 277 | "SXTHW", 278 | "SXTW", 279 | "SYS", 280 | "SYSL", 281 | "TBNZ", 282 | "TBZ", 283 | "TLBI", 284 | "TST", 285 | "TSTW", 286 | "UBFIZ", 287 | "UBFIZW", 288 | "UBFM", 289 | "UBFMW", 290 | "UBFX", 291 | "UBFXW", 292 | "UDIV", 293 | "UDIVW", 294 | "UMADDL", 295 | "UMNEGL", 296 | "UMSUBL", 297 | "UMULH", 298 | "UMULL", 299 | "UREM", 300 | "UREMW", 301 | "UXTB", 302 | "UXTH", 303 | "UXTW", 304 | "UXTBW", 305 | "UXTHW", 306 | "WFE", 307 | "WFI", 308 | "YIELD", 309 | "MOVB", 310 | "MOVBU", 311 | "MOVH", 312 | "MOVHU", 313 | "MOVW", 314 | "MOVWU", 315 | "MOVD", 316 | "MOVNP", 317 | "MOVNPW", 318 | "MOVP", 319 | "MOVPD", 320 | "MOVPQ", 321 | "MOVPS", 322 | "MOVPSW", 323 | "MOVPW", 324 | "SWPAD", 325 | "SWPAW", 326 | "SWPAH", 327 | "SWPAB", 328 | "SWPALD", 329 | "SWPALW", 330 | "SWPALH", 331 | "SWPALB", 332 | "SWPD", 333 | "SWPW", 334 | "SWPH", 335 | "SWPB", 336 | "SWPLD", 337 | "SWPLW", 338 | "SWPLH", 339 | "SWPLB", 340 | "BEQ", 341 | "BNE", 342 | "BCS", 343 | "BHS", 344 | "BCC", 345 | "BLO", 346 | "BMI", 347 | "BPL", 348 | "BVS", 349 | "BVC", 350 | "BHI", 351 | "BLS", 352 | "BGE", 353 | "BLT", 354 | "BGT", 355 | "BLE", 356 | "FABSD", 357 | "FABSS", 358 | "FADDD", 359 | "FADDS", 360 | "FCCMPD", 361 | "FCCMPED", 362 | "FCCMPS", 363 | "FCCMPES", 364 | "FCMPD", 365 | "FCMPED", 366 | "FCMPES", 367 | "FCMPS", 368 | "FCVTSD", 369 | "FCVTDS", 370 | "FCVTZSD", 371 | "FCVTZSDW", 372 | "FCVTZSS", 373 | "FCVTZSSW", 374 | "FCVTZUD", 375 | "FCVTZUDW", 376 | "FCVTZUS", 377 | "FCVTZUSW", 378 | "FDIVD", 379 | "FDIVS", 380 | "FLDPD", 381 | "FLDPS", 382 | "FMOVD", 383 | "FMOVS", 384 | "FMOVQ", 385 | "FMULD", 386 | "FMULS", 387 | "FNEGD", 388 | "FNEGS", 389 | "FSQRTD", 390 | "FSQRTS", 391 | "FSTPD", 392 | "FSTPS", 393 | "FSUBD", 394 | "FSUBS", 395 | "SCVTFD", 396 | "SCVTFS", 397 | "SCVTFWD", 398 | "SCVTFWS", 399 | "UCVTFD", 400 | "UCVTFS", 401 | "UCVTFWD", 402 | "UCVTFWS", 403 | "WORD", 404 | "DWORD", 405 | "FCSELS", 406 | "FCSELD", 407 | "FMAXS", 408 | "FMINS", 409 | "FMAXD", 410 | "FMIND", 411 | "FMAXNMS", 412 | "FMAXNMD", 413 | "FNMULS", 414 | "FNMULD", 415 | "FRINTNS", 416 | "FRINTND", 417 | "FRINTPS", 418 | "FRINTPD", 419 | "FRINTMS", 420 | "FRINTMD", 421 | "FRINTZS", 422 | "FRINTZD", 423 | "FRINTAS", 424 | "FRINTAD", 425 | "FRINTXS", 426 | "FRINTXD", 427 | "FRINTIS", 428 | "FRINTID", 429 | "FMADDS", 430 | "FMADDD", 431 | "FMSUBS", 432 | "FMSUBD", 433 | "FNMADDS", 434 | "FNMADDD", 435 | "FNMSUBS", 436 | "FNMSUBD", 437 | "FMINNMS", 438 | "FMINNMD", 439 | "FCVTDH", 440 | "FCVTHS", 441 | "FCVTHD", 442 | "FCVTSH", 443 | "AESD", 444 | "AESE", 445 | "AESIMC", 446 | "AESMC", 447 | "SHA1C", 448 | "SHA1H", 449 | "SHA1M", 450 | "SHA1P", 451 | "SHA1SU0", 452 | "SHA1SU1", 453 | "SHA256H", 454 | "SHA256H2", 455 | "SHA256SU0", 456 | "SHA256SU1", 457 | "SHA512H", 458 | "SHA512H2", 459 | "SHA512SU0", 460 | "SHA512SU1", 461 | "VADD", 462 | "VADDP", 463 | "VAND", 464 | "VBIF", 465 | "VCMEQ", 466 | "VCNT", 467 | "VEOR", 468 | "VMOV", 469 | "VLD1", 470 | "VLD2", 471 | "VLD3", 472 | "VLD4", 473 | "VLD1R", 474 | "VLD2R", 475 | "VLD3R", 476 | "VLD4R", 477 | "VORR", 478 | "VREV16", 479 | "VREV32", 480 | "VREV64", 481 | "VST1", 482 | "VST2", 483 | "VST3", 484 | "VST4", 485 | "VDUP", 486 | "VADDV", 487 | "VMOVI", 488 | "VUADDLV", 489 | "VSUB", 490 | "VFMLA", 491 | "VFMLS", 492 | "VPMULL", 493 | "VPMULL2", 494 | "VEXT", 495 | "VRBIT", 496 | "VUSHR", 497 | "VUSHLL", 498 | "VUSHLL2", 499 | "VUXTL", 500 | "VUXTL2", 501 | "VUZP1", 502 | "VUZP2", 503 | "VSHL", 504 | "VSRI", 505 | "VBSL", 506 | "VBIT", 507 | "VTBL", 508 | "VZIP1", 509 | "VZIP2", 510 | "VCMTST", 511 | "LAST", 512 | } 513 | -------------------------------------------------------------------------------- /goobj/builtinlist.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkbuiltin.go. DO NOT EDIT. 2 | 3 | package goobj 4 | 5 | var builtins = [...]struct { 6 | name string 7 | abi int 8 | }{ 9 | {"runtime.newobject", 1}, 10 | {"runtime.mallocgc", 1}, 11 | {"runtime.panicdivide", 1}, 12 | {"runtime.panicshift", 1}, 13 | {"runtime.panicmakeslicelen", 1}, 14 | {"runtime.panicmakeslicecap", 1}, 15 | {"runtime.throwinit", 1}, 16 | {"runtime.panicwrap", 1}, 17 | {"runtime.gopanic", 1}, 18 | {"runtime.gorecover", 1}, 19 | {"runtime.goschedguarded", 1}, 20 | {"runtime.goPanicIndex", 1}, 21 | {"runtime.goPanicIndexU", 1}, 22 | {"runtime.goPanicSliceAlen", 1}, 23 | {"runtime.goPanicSliceAlenU", 1}, 24 | {"runtime.goPanicSliceAcap", 1}, 25 | {"runtime.goPanicSliceAcapU", 1}, 26 | {"runtime.goPanicSliceB", 1}, 27 | {"runtime.goPanicSliceBU", 1}, 28 | {"runtime.goPanicSlice3Alen", 1}, 29 | {"runtime.goPanicSlice3AlenU", 1}, 30 | {"runtime.goPanicSlice3Acap", 1}, 31 | {"runtime.goPanicSlice3AcapU", 1}, 32 | {"runtime.goPanicSlice3B", 1}, 33 | {"runtime.goPanicSlice3BU", 1}, 34 | {"runtime.goPanicSlice3C", 1}, 35 | {"runtime.goPanicSlice3CU", 1}, 36 | {"runtime.printbool", 1}, 37 | {"runtime.printfloat", 1}, 38 | {"runtime.printint", 1}, 39 | {"runtime.printhex", 1}, 40 | {"runtime.printuint", 1}, 41 | {"runtime.printcomplex", 1}, 42 | {"runtime.printstring", 1}, 43 | {"runtime.printpointer", 1}, 44 | {"runtime.printiface", 1}, 45 | {"runtime.printeface", 1}, 46 | {"runtime.printslice", 1}, 47 | {"runtime.printnl", 1}, 48 | {"runtime.printsp", 1}, 49 | {"runtime.printlock", 1}, 50 | {"runtime.printunlock", 1}, 51 | {"runtime.concatstring2", 1}, 52 | {"runtime.concatstring3", 1}, 53 | {"runtime.concatstring4", 1}, 54 | {"runtime.concatstring5", 1}, 55 | {"runtime.concatstrings", 1}, 56 | {"runtime.cmpstring", 1}, 57 | {"runtime.intstring", 1}, 58 | {"runtime.slicebytetostring", 1}, 59 | {"runtime.slicebytetostringtmp", 1}, 60 | {"runtime.slicerunetostring", 1}, 61 | {"runtime.stringtoslicebyte", 1}, 62 | {"runtime.stringtoslicerune", 1}, 63 | {"runtime.slicecopy", 1}, 64 | {"runtime.slicestringcopy", 1}, 65 | {"runtime.decoderune", 1}, 66 | {"runtime.countrunes", 1}, 67 | {"runtime.convI2I", 1}, 68 | {"runtime.convT16", 1}, 69 | {"runtime.convT32", 1}, 70 | {"runtime.convT64", 1}, 71 | {"runtime.convTstring", 1}, 72 | {"runtime.convTslice", 1}, 73 | {"runtime.convT2E", 1}, 74 | {"runtime.convT2Enoptr", 1}, 75 | {"runtime.convT2I", 1}, 76 | {"runtime.convT2Inoptr", 1}, 77 | {"runtime.assertE2I", 1}, 78 | {"runtime.assertE2I2", 1}, 79 | {"runtime.assertI2I", 1}, 80 | {"runtime.assertI2I2", 1}, 81 | {"runtime.panicdottypeE", 1}, 82 | {"runtime.panicdottypeI", 1}, 83 | {"runtime.panicnildottype", 1}, 84 | {"runtime.ifaceeq", 1}, 85 | {"runtime.efaceeq", 1}, 86 | {"runtime.fastrand", 1}, 87 | {"runtime.makemap64", 1}, 88 | {"runtime.makemap", 1}, 89 | {"runtime.makemap_small", 1}, 90 | {"runtime.mapaccess1", 1}, 91 | {"runtime.mapaccess1_fast32", 1}, 92 | {"runtime.mapaccess1_fast64", 1}, 93 | {"runtime.mapaccess1_faststr", 1}, 94 | {"runtime.mapaccess1_fat", 1}, 95 | {"runtime.mapaccess2", 1}, 96 | {"runtime.mapaccess2_fast32", 1}, 97 | {"runtime.mapaccess2_fast64", 1}, 98 | {"runtime.mapaccess2_faststr", 1}, 99 | {"runtime.mapaccess2_fat", 1}, 100 | {"runtime.mapassign", 1}, 101 | {"runtime.mapassign_fast32", 1}, 102 | {"runtime.mapassign_fast32ptr", 1}, 103 | {"runtime.mapassign_fast64", 1}, 104 | {"runtime.mapassign_fast64ptr", 1}, 105 | {"runtime.mapassign_faststr", 1}, 106 | {"runtime.mapiterinit", 1}, 107 | {"runtime.mapdelete", 1}, 108 | {"runtime.mapdelete_fast32", 1}, 109 | {"runtime.mapdelete_fast64", 1}, 110 | {"runtime.mapdelete_faststr", 1}, 111 | {"runtime.mapiternext", 1}, 112 | {"runtime.mapclear", 1}, 113 | {"runtime.makechan64", 1}, 114 | {"runtime.makechan", 1}, 115 | {"runtime.chanrecv1", 1}, 116 | {"runtime.chanrecv2", 1}, 117 | {"runtime.chansend1", 1}, 118 | {"runtime.closechan", 1}, 119 | {"runtime.writeBarrier", 0}, 120 | {"runtime.typedmemmove", 1}, 121 | {"runtime.typedmemclr", 1}, 122 | {"runtime.typedslicecopy", 1}, 123 | {"runtime.selectnbsend", 1}, 124 | {"runtime.selectnbrecv", 1}, 125 | {"runtime.selectnbrecv2", 1}, 126 | {"runtime.selectsetpc", 1}, 127 | {"runtime.selectgo", 1}, 128 | {"runtime.block", 1}, 129 | {"runtime.makeslice", 1}, 130 | {"runtime.makeslice64", 1}, 131 | {"runtime.makeslicecopy", 1}, 132 | {"runtime.growslice", 1}, 133 | {"runtime.memmove", 1}, 134 | {"runtime.memclrNoHeapPointers", 1}, 135 | {"runtime.memclrHasPointers", 1}, 136 | {"runtime.memequal", 1}, 137 | {"runtime.memequal0", 1}, 138 | {"runtime.memequal8", 1}, 139 | {"runtime.memequal16", 1}, 140 | {"runtime.memequal32", 1}, 141 | {"runtime.memequal64", 1}, 142 | {"runtime.memequal128", 1}, 143 | {"runtime.f32equal", 1}, 144 | {"runtime.f64equal", 1}, 145 | {"runtime.c64equal", 1}, 146 | {"runtime.c128equal", 1}, 147 | {"runtime.strequal", 1}, 148 | {"runtime.interequal", 1}, 149 | {"runtime.nilinterequal", 1}, 150 | {"runtime.memhash", 1}, 151 | {"runtime.memhash0", 1}, 152 | {"runtime.memhash8", 1}, 153 | {"runtime.memhash16", 1}, 154 | {"runtime.memhash32", 1}, 155 | {"runtime.memhash64", 1}, 156 | {"runtime.memhash128", 1}, 157 | {"runtime.f32hash", 1}, 158 | {"runtime.f64hash", 1}, 159 | {"runtime.c64hash", 1}, 160 | {"runtime.c128hash", 1}, 161 | {"runtime.strhash", 1}, 162 | {"runtime.interhash", 1}, 163 | {"runtime.nilinterhash", 1}, 164 | {"runtime.int64div", 1}, 165 | {"runtime.uint64div", 1}, 166 | {"runtime.int64mod", 1}, 167 | {"runtime.uint64mod", 1}, 168 | {"runtime.float64toint64", 1}, 169 | {"runtime.float64touint64", 1}, 170 | {"runtime.float64touint32", 1}, 171 | {"runtime.int64tofloat64", 1}, 172 | {"runtime.uint64tofloat64", 1}, 173 | {"runtime.uint32tofloat64", 1}, 174 | {"runtime.complex128div", 1}, 175 | {"runtime.racefuncenter", 1}, 176 | {"runtime.racefuncenterfp", 1}, 177 | {"runtime.racefuncexit", 1}, 178 | {"runtime.raceread", 1}, 179 | {"runtime.racewrite", 1}, 180 | {"runtime.racereadrange", 1}, 181 | {"runtime.racewriterange", 1}, 182 | {"runtime.msanread", 1}, 183 | {"runtime.msanwrite", 1}, 184 | {"runtime.checkptrAlignment", 1}, 185 | {"runtime.checkptrArithmetic", 1}, 186 | {"runtime.libfuzzerTraceCmp1", 1}, 187 | {"runtime.libfuzzerTraceCmp2", 1}, 188 | {"runtime.libfuzzerTraceCmp4", 1}, 189 | {"runtime.libfuzzerTraceCmp8", 1}, 190 | {"runtime.libfuzzerTraceConstCmp1", 1}, 191 | {"runtime.libfuzzerTraceConstCmp2", 1}, 192 | {"runtime.libfuzzerTraceConstCmp4", 1}, 193 | {"runtime.libfuzzerTraceConstCmp8", 1}, 194 | {"runtime.x86HasPOPCNT", 0}, 195 | {"runtime.x86HasSSE41", 0}, 196 | {"runtime.x86HasFMA", 0}, 197 | {"runtime.armHasVFPv4", 0}, 198 | {"runtime.arm64HasATOMICS", 0}, 199 | {"runtime.deferproc", 1}, 200 | {"runtime.deferprocStack", 1}, 201 | {"runtime.deferreturn", 1}, 202 | {"runtime.newproc", 1}, 203 | {"runtime.panicoverflow", 1}, 204 | {"runtime.sigpanic", 1}, 205 | {"runtime.gcWriteBarrier", 0}, 206 | {"runtime.morestack", 0}, 207 | {"runtime.morestackc", 0}, 208 | {"runtime.morestack_noctxt", 0}, 209 | {"type.int8", 0}, 210 | {"type.*int8", 0}, 211 | {"type.uint8", 0}, 212 | {"type.*uint8", 0}, 213 | {"type.int16", 0}, 214 | {"type.*int16", 0}, 215 | {"type.uint16", 0}, 216 | {"type.*uint16", 0}, 217 | {"type.int32", 0}, 218 | {"type.*int32", 0}, 219 | {"type.uint32", 0}, 220 | {"type.*uint32", 0}, 221 | {"type.int64", 0}, 222 | {"type.*int64", 0}, 223 | {"type.uint64", 0}, 224 | {"type.*uint64", 0}, 225 | {"type.float32", 0}, 226 | {"type.*float32", 0}, 227 | {"type.float64", 0}, 228 | {"type.*float64", 0}, 229 | {"type.complex64", 0}, 230 | {"type.*complex64", 0}, 231 | {"type.complex128", 0}, 232 | {"type.*complex128", 0}, 233 | {"type.unsafe.Pointer", 0}, 234 | {"type.*unsafe.Pointer", 0}, 235 | {"type.uintptr", 0}, 236 | {"type.*uintptr", 0}, 237 | {"type.bool", 0}, 238 | {"type.*bool", 0}, 239 | {"type.string", 0}, 240 | {"type.*string", 0}, 241 | {"type.error", 0}, 242 | {"type.*error", 0}, 243 | {"type.func(error) string", 0}, 244 | {"type.*func(error) string", 0}, 245 | } 246 | -------------------------------------------------------------------------------- /obj/arm64/list7.go: -------------------------------------------------------------------------------- 1 | // cmd/7l/list.c and cmd/7l/sub.c from Vita Nuova. 2 | // https://code.google.com/p/ken-cc/source/browse/ 3 | // 4 | // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 | // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 | // Portions Copyright © 1997-1999 Vita Nuova Limited 7 | // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 | // Portions Copyright © 2004,2006 Bruce Ellis 9 | // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 | // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 | // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 | // 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy 14 | // of this software and associated documentation files (the "Software"), to deal 15 | // in the Software without restriction, including without limitation the rights 16 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | // copies of the Software, and to permit persons to whom the Software is 18 | // furnished to do so, subject to the following conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be included in 21 | // all copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 | // THE SOFTWARE. 30 | 31 | package arm64 32 | 33 | import ( 34 | "github.com/twitchyliquid64/golang-asm/obj" 35 | "fmt" 36 | ) 37 | 38 | var strcond = [16]string{ 39 | "EQ", 40 | "NE", 41 | "HS", 42 | "LO", 43 | "MI", 44 | "PL", 45 | "VS", 46 | "VC", 47 | "HI", 48 | "LS", 49 | "GE", 50 | "LT", 51 | "GT", 52 | "LE", 53 | "AL", 54 | "NV", 55 | } 56 | 57 | func init() { 58 | obj.RegisterRegister(obj.RBaseARM64, REG_SPECIAL+1024, rconv) 59 | obj.RegisterOpcode(obj.ABaseARM64, Anames) 60 | obj.RegisterRegisterList(obj.RegListARM64Lo, obj.RegListARM64Hi, rlconv) 61 | obj.RegisterOpSuffix("arm64", obj.CConvARM) 62 | } 63 | 64 | func arrange(a int) string { 65 | switch a { 66 | case ARNG_8B: 67 | return "B8" 68 | case ARNG_16B: 69 | return "B16" 70 | case ARNG_4H: 71 | return "H4" 72 | case ARNG_8H: 73 | return "H8" 74 | case ARNG_2S: 75 | return "S2" 76 | case ARNG_4S: 77 | return "S4" 78 | case ARNG_1D: 79 | return "D1" 80 | case ARNG_2D: 81 | return "D2" 82 | case ARNG_B: 83 | return "B" 84 | case ARNG_H: 85 | return "H" 86 | case ARNG_S: 87 | return "S" 88 | case ARNG_D: 89 | return "D" 90 | case ARNG_1Q: 91 | return "Q1" 92 | default: 93 | return "" 94 | } 95 | } 96 | 97 | func rconv(r int) string { 98 | ext := (r >> 5) & 7 99 | if r == REGG { 100 | return "g" 101 | } 102 | switch { 103 | case REG_R0 <= r && r <= REG_R30: 104 | return fmt.Sprintf("R%d", r-REG_R0) 105 | case r == REG_R31: 106 | return "ZR" 107 | case REG_F0 <= r && r <= REG_F31: 108 | return fmt.Sprintf("F%d", r-REG_F0) 109 | case REG_V0 <= r && r <= REG_V31: 110 | return fmt.Sprintf("V%d", r-REG_V0) 111 | case COND_EQ <= r && r <= COND_NV: 112 | return strcond[r-COND_EQ] 113 | case r == REGSP: 114 | return "RSP" 115 | case r == REG_DAIFSet: 116 | return "DAIFSet" 117 | case r == REG_DAIFClr: 118 | return "DAIFClr" 119 | case r == REG_PLDL1KEEP: 120 | return "PLDL1KEEP" 121 | case r == REG_PLDL1STRM: 122 | return "PLDL1STRM" 123 | case r == REG_PLDL2KEEP: 124 | return "PLDL2KEEP" 125 | case r == REG_PLDL2STRM: 126 | return "PLDL2STRM" 127 | case r == REG_PLDL3KEEP: 128 | return "PLDL3KEEP" 129 | case r == REG_PLDL3STRM: 130 | return "PLDL3STRM" 131 | case r == REG_PLIL1KEEP: 132 | return "PLIL1KEEP" 133 | case r == REG_PLIL1STRM: 134 | return "PLIL1STRM" 135 | case r == REG_PLIL2KEEP: 136 | return "PLIL2KEEP" 137 | case r == REG_PLIL2STRM: 138 | return "PLIL2STRM" 139 | case r == REG_PLIL3KEEP: 140 | return "PLIL3KEEP" 141 | case r == REG_PLIL3STRM: 142 | return "PLIL3STRM" 143 | case r == REG_PSTL1KEEP: 144 | return "PSTL1KEEP" 145 | case r == REG_PSTL1STRM: 146 | return "PSTL1STRM" 147 | case r == REG_PSTL2KEEP: 148 | return "PSTL2KEEP" 149 | case r == REG_PSTL2STRM: 150 | return "PSTL2STRM" 151 | case r == REG_PSTL3KEEP: 152 | return "PSTL3KEEP" 153 | case r == REG_PSTL3STRM: 154 | return "PSTL3STRM" 155 | case REG_UXTB <= r && r < REG_UXTH: 156 | if ext != 0 { 157 | return fmt.Sprintf("%s.UXTB<<%d", regname(r), ext) 158 | } else { 159 | return fmt.Sprintf("%s.UXTB", regname(r)) 160 | } 161 | case REG_UXTH <= r && r < REG_UXTW: 162 | if ext != 0 { 163 | return fmt.Sprintf("%s.UXTH<<%d", regname(r), ext) 164 | } else { 165 | return fmt.Sprintf("%s.UXTH", regname(r)) 166 | } 167 | case REG_UXTW <= r && r < REG_UXTX: 168 | if ext != 0 { 169 | return fmt.Sprintf("%s.UXTW<<%d", regname(r), ext) 170 | } else { 171 | return fmt.Sprintf("%s.UXTW", regname(r)) 172 | } 173 | case REG_UXTX <= r && r < REG_SXTB: 174 | if ext != 0 { 175 | return fmt.Sprintf("%s.UXTX<<%d", regname(r), ext) 176 | } else { 177 | return fmt.Sprintf("%s.UXTX", regname(r)) 178 | } 179 | case REG_SXTB <= r && r < REG_SXTH: 180 | if ext != 0 { 181 | return fmt.Sprintf("%s.SXTB<<%d", regname(r), ext) 182 | } else { 183 | return fmt.Sprintf("%s.SXTB", regname(r)) 184 | } 185 | case REG_SXTH <= r && r < REG_SXTW: 186 | if ext != 0 { 187 | return fmt.Sprintf("%s.SXTH<<%d", regname(r), ext) 188 | } else { 189 | return fmt.Sprintf("%s.SXTH", regname(r)) 190 | } 191 | case REG_SXTW <= r && r < REG_SXTX: 192 | if ext != 0 { 193 | return fmt.Sprintf("%s.SXTW<<%d", regname(r), ext) 194 | } else { 195 | return fmt.Sprintf("%s.SXTW", regname(r)) 196 | } 197 | case REG_SXTX <= r && r < REG_SPECIAL: 198 | if ext != 0 { 199 | return fmt.Sprintf("%s.SXTX<<%d", regname(r), ext) 200 | } else { 201 | return fmt.Sprintf("%s.SXTX", regname(r)) 202 | } 203 | // bits 0-4 indicate register, bits 5-7 indicate shift amount, bit 8 equals to 0. 204 | case REG_LSL <= r && r < (REG_LSL+1<<8): 205 | return fmt.Sprintf("R%d<<%d", r&31, (r>>5)&7) 206 | case REG_ARNG <= r && r < REG_ELEM: 207 | return fmt.Sprintf("V%d.%s", r&31, arrange((r>>5)&15)) 208 | case REG_ELEM <= r && r < REG_ELEM_END: 209 | return fmt.Sprintf("V%d.%s", r&31, arrange((r>>5)&15)) 210 | } 211 | // Return system register name. 212 | name, _, _ := SysRegEnc(int16(r)) 213 | if name != "" { 214 | return name 215 | } 216 | return fmt.Sprintf("badreg(%d)", r) 217 | } 218 | 219 | func DRconv(a int) string { 220 | if a >= C_NONE && a <= C_NCLASS { 221 | return cnames7[a] 222 | } 223 | return "C_??" 224 | } 225 | 226 | func rlconv(list int64) string { 227 | str := "" 228 | 229 | // ARM64 register list follows ARM64 instruction decode schema 230 | // | 31 | 30 | ... | 15 - 12 | 11 - 10 | ... | 231 | // +----+----+-----+---------+---------+-----+ 232 | // | | Q | ... | opcode | size | ... | 233 | 234 | firstReg := int(list & 31) 235 | opcode := (list >> 12) & 15 236 | var regCnt int 237 | var t string 238 | switch opcode { 239 | case 0x7: 240 | regCnt = 1 241 | case 0xa: 242 | regCnt = 2 243 | case 0x6: 244 | regCnt = 3 245 | case 0x2: 246 | regCnt = 4 247 | default: 248 | regCnt = -1 249 | } 250 | // Q:size 251 | arng := ((list>>30)&1)<<2 | (list>>10)&3 252 | switch arng { 253 | case 0: 254 | t = "B8" 255 | case 4: 256 | t = "B16" 257 | case 1: 258 | t = "H4" 259 | case 5: 260 | t = "H8" 261 | case 2: 262 | t = "S2" 263 | case 6: 264 | t = "S4" 265 | case 3: 266 | t = "D1" 267 | case 7: 268 | t = "D2" 269 | } 270 | for i := 0; i < regCnt; i++ { 271 | if str == "" { 272 | str += "[" 273 | } else { 274 | str += "," 275 | } 276 | str += fmt.Sprintf("V%d.", (firstReg+i)&31) 277 | str += t 278 | } 279 | str += "]" 280 | return str 281 | } 282 | 283 | func regname(r int) string { 284 | if r&31 == 31 { 285 | return "ZR" 286 | } 287 | return fmt.Sprintf("R%d", r&31) 288 | } 289 | -------------------------------------------------------------------------------- /obj/x86/a.out.go: -------------------------------------------------------------------------------- 1 | // Inferno utils/6c/6.out.h 2 | // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6c/6.out.h 3 | // 4 | // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 | // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 | // Portions Copyright © 1997-1999 Vita Nuova Limited 7 | // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 | // Portions Copyright © 2004,2006 Bruce Ellis 9 | // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 | // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 | // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 | // 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy 14 | // of this software and associated documentation files (the "Software"), to deal 15 | // in the Software without restriction, including without limitation the rights 16 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | // copies of the Software, and to permit persons to whom the Software is 18 | // furnished to do so, subject to the following conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be included in 21 | // all copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 | // THE SOFTWARE. 30 | 31 | package x86 32 | 33 | import "github.com/twitchyliquid64/golang-asm/obj" 34 | 35 | const ( 36 | REG_NONE = 0 37 | ) 38 | 39 | const ( 40 | REG_AL = obj.RBaseAMD64 + iota 41 | REG_CL 42 | REG_DL 43 | REG_BL 44 | REG_SPB 45 | REG_BPB 46 | REG_SIB 47 | REG_DIB 48 | REG_R8B 49 | REG_R9B 50 | REG_R10B 51 | REG_R11B 52 | REG_R12B 53 | REG_R13B 54 | REG_R14B 55 | REG_R15B 56 | 57 | REG_AX 58 | REG_CX 59 | REG_DX 60 | REG_BX 61 | REG_SP 62 | REG_BP 63 | REG_SI 64 | REG_DI 65 | REG_R8 66 | REG_R9 67 | REG_R10 68 | REG_R11 69 | REG_R12 70 | REG_R13 71 | REG_R14 72 | REG_R15 73 | 74 | REG_AH 75 | REG_CH 76 | REG_DH 77 | REG_BH 78 | 79 | REG_F0 80 | REG_F1 81 | REG_F2 82 | REG_F3 83 | REG_F4 84 | REG_F5 85 | REG_F6 86 | REG_F7 87 | 88 | REG_M0 89 | REG_M1 90 | REG_M2 91 | REG_M3 92 | REG_M4 93 | REG_M5 94 | REG_M6 95 | REG_M7 96 | 97 | REG_K0 98 | REG_K1 99 | REG_K2 100 | REG_K3 101 | REG_K4 102 | REG_K5 103 | REG_K6 104 | REG_K7 105 | 106 | REG_X0 107 | REG_X1 108 | REG_X2 109 | REG_X3 110 | REG_X4 111 | REG_X5 112 | REG_X6 113 | REG_X7 114 | REG_X8 115 | REG_X9 116 | REG_X10 117 | REG_X11 118 | REG_X12 119 | REG_X13 120 | REG_X14 121 | REG_X15 122 | REG_X16 123 | REG_X17 124 | REG_X18 125 | REG_X19 126 | REG_X20 127 | REG_X21 128 | REG_X22 129 | REG_X23 130 | REG_X24 131 | REG_X25 132 | REG_X26 133 | REG_X27 134 | REG_X28 135 | REG_X29 136 | REG_X30 137 | REG_X31 138 | 139 | REG_Y0 140 | REG_Y1 141 | REG_Y2 142 | REG_Y3 143 | REG_Y4 144 | REG_Y5 145 | REG_Y6 146 | REG_Y7 147 | REG_Y8 148 | REG_Y9 149 | REG_Y10 150 | REG_Y11 151 | REG_Y12 152 | REG_Y13 153 | REG_Y14 154 | REG_Y15 155 | REG_Y16 156 | REG_Y17 157 | REG_Y18 158 | REG_Y19 159 | REG_Y20 160 | REG_Y21 161 | REG_Y22 162 | REG_Y23 163 | REG_Y24 164 | REG_Y25 165 | REG_Y26 166 | REG_Y27 167 | REG_Y28 168 | REG_Y29 169 | REG_Y30 170 | REG_Y31 171 | 172 | REG_Z0 173 | REG_Z1 174 | REG_Z2 175 | REG_Z3 176 | REG_Z4 177 | REG_Z5 178 | REG_Z6 179 | REG_Z7 180 | REG_Z8 181 | REG_Z9 182 | REG_Z10 183 | REG_Z11 184 | REG_Z12 185 | REG_Z13 186 | REG_Z14 187 | REG_Z15 188 | REG_Z16 189 | REG_Z17 190 | REG_Z18 191 | REG_Z19 192 | REG_Z20 193 | REG_Z21 194 | REG_Z22 195 | REG_Z23 196 | REG_Z24 197 | REG_Z25 198 | REG_Z26 199 | REG_Z27 200 | REG_Z28 201 | REG_Z29 202 | REG_Z30 203 | REG_Z31 204 | 205 | REG_CS 206 | REG_SS 207 | REG_DS 208 | REG_ES 209 | REG_FS 210 | REG_GS 211 | 212 | REG_GDTR // global descriptor table register 213 | REG_IDTR // interrupt descriptor table register 214 | REG_LDTR // local descriptor table register 215 | REG_MSW // machine status word 216 | REG_TASK // task register 217 | 218 | REG_CR0 219 | REG_CR1 220 | REG_CR2 221 | REG_CR3 222 | REG_CR4 223 | REG_CR5 224 | REG_CR6 225 | REG_CR7 226 | REG_CR8 227 | REG_CR9 228 | REG_CR10 229 | REG_CR11 230 | REG_CR12 231 | REG_CR13 232 | REG_CR14 233 | REG_CR15 234 | 235 | REG_DR0 236 | REG_DR1 237 | REG_DR2 238 | REG_DR3 239 | REG_DR4 240 | REG_DR5 241 | REG_DR6 242 | REG_DR7 243 | 244 | REG_TR0 245 | REG_TR1 246 | REG_TR2 247 | REG_TR3 248 | REG_TR4 249 | REG_TR5 250 | REG_TR6 251 | REG_TR7 252 | 253 | REG_TLS 254 | 255 | MAXREG 256 | 257 | REG_CR = REG_CR0 258 | REG_DR = REG_DR0 259 | REG_TR = REG_TR0 260 | 261 | REGARG = -1 262 | REGRET = REG_AX 263 | FREGRET = REG_X0 264 | REGSP = REG_SP 265 | REGCTXT = REG_DX 266 | REGEXT = REG_R15 // compiler allocates external registers R15 down 267 | FREGMIN = REG_X0 + 5 // first register variable 268 | FREGEXT = REG_X0 + 15 // first external register 269 | T_TYPE = 1 << 0 270 | T_INDEX = 1 << 1 271 | T_OFFSET = 1 << 2 272 | T_FCONST = 1 << 3 273 | T_SYM = 1 << 4 274 | T_SCONST = 1 << 5 275 | T_64 = 1 << 6 276 | T_GOTYPE = 1 << 7 277 | ) 278 | 279 | // https://www.uclibc.org/docs/psABI-x86_64.pdf, figure 3.36 280 | var AMD64DWARFRegisters = map[int16]int16{ 281 | REG_AX: 0, 282 | REG_DX: 1, 283 | REG_CX: 2, 284 | REG_BX: 3, 285 | REG_SI: 4, 286 | REG_DI: 5, 287 | REG_BP: 6, 288 | REG_SP: 7, 289 | REG_R8: 8, 290 | REG_R9: 9, 291 | REG_R10: 10, 292 | REG_R11: 11, 293 | REG_R12: 12, 294 | REG_R13: 13, 295 | REG_R14: 14, 296 | REG_R15: 15, 297 | // 16 is "Return Address RA", whatever that is. 298 | // 17-24 vector registers (X/Y/Z). 299 | REG_X0: 17, 300 | REG_X1: 18, 301 | REG_X2: 19, 302 | REG_X3: 20, 303 | REG_X4: 21, 304 | REG_X5: 22, 305 | REG_X6: 23, 306 | REG_X7: 24, 307 | // 25-32 extended vector registers (X/Y/Z). 308 | REG_X8: 25, 309 | REG_X9: 26, 310 | REG_X10: 27, 311 | REG_X11: 28, 312 | REG_X12: 29, 313 | REG_X13: 30, 314 | REG_X14: 31, 315 | REG_X15: 32, 316 | // ST registers. %stN => FN. 317 | REG_F0: 33, 318 | REG_F1: 34, 319 | REG_F2: 35, 320 | REG_F3: 36, 321 | REG_F4: 37, 322 | REG_F5: 38, 323 | REG_F6: 39, 324 | REG_F7: 40, 325 | // MMX registers. %mmN => MN. 326 | REG_M0: 41, 327 | REG_M1: 42, 328 | REG_M2: 43, 329 | REG_M3: 44, 330 | REG_M4: 45, 331 | REG_M5: 46, 332 | REG_M6: 47, 333 | REG_M7: 48, 334 | // 48 is flags, which doesn't have a name. 335 | REG_ES: 50, 336 | REG_CS: 51, 337 | REG_SS: 52, 338 | REG_DS: 53, 339 | REG_FS: 54, 340 | REG_GS: 55, 341 | // 58 and 59 are {fs,gs}base, which don't have names. 342 | REG_TR: 62, 343 | REG_LDTR: 63, 344 | // 64-66 are mxcsr, fcw, fsw, which don't have names. 345 | 346 | // 67-82 upper vector registers (X/Y/Z). 347 | REG_X16: 67, 348 | REG_X17: 68, 349 | REG_X18: 69, 350 | REG_X19: 70, 351 | REG_X20: 71, 352 | REG_X21: 72, 353 | REG_X22: 73, 354 | REG_X23: 74, 355 | REG_X24: 75, 356 | REG_X25: 76, 357 | REG_X26: 77, 358 | REG_X27: 78, 359 | REG_X28: 79, 360 | REG_X29: 80, 361 | REG_X30: 81, 362 | REG_X31: 82, 363 | 364 | // 118-125 vector mask registers. %kN => KN. 365 | REG_K0: 118, 366 | REG_K1: 119, 367 | REG_K2: 120, 368 | REG_K3: 121, 369 | REG_K4: 122, 370 | REG_K5: 123, 371 | REG_K6: 124, 372 | REG_K7: 125, 373 | } 374 | 375 | // https://www.uclibc.org/docs/psABI-i386.pdf, table 2.14 376 | var X86DWARFRegisters = map[int16]int16{ 377 | REG_AX: 0, 378 | REG_CX: 1, 379 | REG_DX: 2, 380 | REG_BX: 3, 381 | REG_SP: 4, 382 | REG_BP: 5, 383 | REG_SI: 6, 384 | REG_DI: 7, 385 | // 8 is "Return Address RA", whatever that is. 386 | // 9 is flags, which doesn't have a name. 387 | // ST registers. %stN => FN. 388 | REG_F0: 11, 389 | REG_F1: 12, 390 | REG_F2: 13, 391 | REG_F3: 14, 392 | REG_F4: 15, 393 | REG_F5: 16, 394 | REG_F6: 17, 395 | REG_F7: 18, 396 | // XMM registers. %xmmN => XN. 397 | REG_X0: 21, 398 | REG_X1: 22, 399 | REG_X2: 23, 400 | REG_X3: 24, 401 | REG_X4: 25, 402 | REG_X5: 26, 403 | REG_X6: 27, 404 | REG_X7: 28, 405 | // MMX registers. %mmN => MN. 406 | REG_M0: 29, 407 | REG_M1: 30, 408 | REG_M2: 31, 409 | REG_M3: 32, 410 | REG_M4: 33, 411 | REG_M5: 34, 412 | REG_M6: 35, 413 | REG_M7: 36, 414 | // 39 is mxcsr, which doesn't have a name. 415 | REG_ES: 40, 416 | REG_CS: 41, 417 | REG_SS: 42, 418 | REG_DS: 43, 419 | REG_FS: 44, 420 | REG_GS: 45, 421 | REG_TR: 48, 422 | REG_LDTR: 49, 423 | } 424 | -------------------------------------------------------------------------------- /obj/arm/a.out.go: -------------------------------------------------------------------------------- 1 | // Inferno utils/5c/5.out.h 2 | // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5c/5.out.h 3 | // 4 | // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 | // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 | // Portions Copyright © 1997-1999 Vita Nuova Limited 7 | // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 | // Portions Copyright © 2004,2006 Bruce Ellis 9 | // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 | // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 | // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 | // 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy 14 | // of this software and associated documentation files (the "Software"), to deal 15 | // in the Software without restriction, including without limitation the rights 16 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | // copies of the Software, and to permit persons to whom the Software is 18 | // furnished to do so, subject to the following conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be included in 21 | // all copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 | // THE SOFTWARE. 30 | 31 | package arm 32 | 33 | import "github.com/twitchyliquid64/golang-asm/obj" 34 | 35 | //go:generate go run ../stringer.go -i $GOFILE -o anames.go -p arm 36 | 37 | const ( 38 | NSNAME = 8 39 | NSYM = 50 40 | NREG = 16 41 | ) 42 | 43 | /* -1 disables use of REGARG */ 44 | const ( 45 | REGARG = -1 46 | ) 47 | 48 | const ( 49 | REG_R0 = obj.RBaseARM + iota // must be 16-aligned 50 | REG_R1 51 | REG_R2 52 | REG_R3 53 | REG_R4 54 | REG_R5 55 | REG_R6 56 | REG_R7 57 | REG_R8 58 | REG_R9 59 | REG_R10 60 | REG_R11 61 | REG_R12 62 | REG_R13 63 | REG_R14 64 | REG_R15 65 | 66 | REG_F0 // must be 16-aligned 67 | REG_F1 68 | REG_F2 69 | REG_F3 70 | REG_F4 71 | REG_F5 72 | REG_F6 73 | REG_F7 74 | REG_F8 75 | REG_F9 76 | REG_F10 77 | REG_F11 78 | REG_F12 79 | REG_F13 80 | REG_F14 81 | REG_F15 82 | 83 | REG_FPSR // must be 2-aligned 84 | REG_FPCR 85 | 86 | REG_CPSR // must be 2-aligned 87 | REG_SPSR 88 | 89 | REGRET = REG_R0 90 | /* compiler allocates R1 up as temps */ 91 | /* compiler allocates register variables R3 up */ 92 | /* compiler allocates external registers R10 down */ 93 | REGEXT = REG_R10 94 | /* these two registers are declared in runtime.h */ 95 | REGG = REGEXT - 0 96 | REGM = REGEXT - 1 97 | 98 | REGCTXT = REG_R7 99 | REGTMP = REG_R11 100 | REGSP = REG_R13 101 | REGLINK = REG_R14 102 | REGPC = REG_R15 103 | 104 | NFREG = 16 105 | /* compiler allocates register variables F0 up */ 106 | /* compiler allocates external registers F7 down */ 107 | FREGRET = REG_F0 108 | FREGEXT = REG_F7 109 | FREGTMP = REG_F15 110 | ) 111 | 112 | // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0040b/IHI0040B_aadwarf.pdf 113 | var ARMDWARFRegisters = map[int16]int16{} 114 | 115 | func init() { 116 | // f assigns dwarfregisters[from:to] = (base):(step*(to-from)+base) 117 | f := func(from, to, base, step int16) { 118 | for r := int16(from); r <= to; r++ { 119 | ARMDWARFRegisters[r] = step*(r-from) + base 120 | } 121 | } 122 | f(REG_R0, REG_R15, 0, 1) 123 | f(REG_F0, REG_F15, 64, 2) // Use d0 through D15, aka S0, S2, ..., S30 124 | } 125 | 126 | // Special registers, after subtracting obj.RBaseARM, bit 9 indicates 127 | // a special register and the low bits select the register. 128 | const ( 129 | REG_SPECIAL = obj.RBaseARM + 1<<9 + iota 130 | REG_MB_SY 131 | REG_MB_ST 132 | REG_MB_ISH 133 | REG_MB_ISHST 134 | REG_MB_NSH 135 | REG_MB_NSHST 136 | REG_MB_OSH 137 | REG_MB_OSHST 138 | 139 | MAXREG 140 | ) 141 | 142 | const ( 143 | C_NONE = iota 144 | C_REG 145 | C_REGREG 146 | C_REGREG2 147 | C_REGLIST 148 | C_SHIFT /* register shift R>>x */ 149 | C_SHIFTADDR /* memory address with shifted offset R>>x(R) */ 150 | C_FREG 151 | C_PSR 152 | C_FCR 153 | C_SPR /* REG_MB_SY */ 154 | 155 | C_RCON /* 0xff rotated */ 156 | C_NCON /* ~RCON */ 157 | C_RCON2A /* OR of two disjoint C_RCON constants */ 158 | C_RCON2S /* subtraction of two disjoint C_RCON constants */ 159 | C_SCON /* 0xffff */ 160 | C_LCON 161 | C_LCONADDR 162 | C_ZFCON 163 | C_SFCON 164 | C_LFCON 165 | 166 | C_RACON 167 | C_LACON 168 | 169 | C_SBRA 170 | C_LBRA 171 | 172 | C_HAUTO /* halfword insn offset (-0xff to 0xff) */ 173 | C_FAUTO /* float insn offset (0 to 0x3fc, word aligned) */ 174 | C_HFAUTO /* both H and F */ 175 | C_SAUTO /* -0xfff to 0xfff */ 176 | C_LAUTO 177 | 178 | C_HOREG 179 | C_FOREG 180 | C_HFOREG 181 | C_SOREG 182 | C_ROREG 183 | C_SROREG /* both nil and R */ 184 | C_LOREG 185 | 186 | C_PC 187 | C_SP 188 | C_HREG 189 | 190 | C_ADDR /* reference to relocatable address */ 191 | 192 | // TLS "var" in local exec mode: will become a constant offset from 193 | // thread local base that is ultimately chosen by the program linker. 194 | C_TLS_LE 195 | 196 | // TLS "var" in initial exec mode: will become a memory address (chosen 197 | // by the program linker) that the dynamic linker will fill with the 198 | // offset from the thread local base. 199 | C_TLS_IE 200 | 201 | C_TEXTSIZE 202 | 203 | C_GOK 204 | 205 | C_NCLASS /* must be the last */ 206 | ) 207 | 208 | const ( 209 | AAND = obj.ABaseARM + obj.A_ARCHSPECIFIC + iota 210 | AEOR 211 | ASUB 212 | ARSB 213 | AADD 214 | AADC 215 | ASBC 216 | ARSC 217 | ATST 218 | ATEQ 219 | ACMP 220 | ACMN 221 | AORR 222 | ABIC 223 | 224 | AMVN 225 | 226 | /* 227 | * Do not reorder or fragment the conditional branch 228 | * opcodes, or the predication code will break 229 | */ 230 | ABEQ 231 | ABNE 232 | ABCS 233 | ABHS 234 | ABCC 235 | ABLO 236 | ABMI 237 | ABPL 238 | ABVS 239 | ABVC 240 | ABHI 241 | ABLS 242 | ABGE 243 | ABLT 244 | ABGT 245 | ABLE 246 | 247 | AMOVWD 248 | AMOVWF 249 | AMOVDW 250 | AMOVFW 251 | AMOVFD 252 | AMOVDF 253 | AMOVF 254 | AMOVD 255 | 256 | ACMPF 257 | ACMPD 258 | AADDF 259 | AADDD 260 | ASUBF 261 | ASUBD 262 | AMULF 263 | AMULD 264 | ANMULF 265 | ANMULD 266 | AMULAF 267 | AMULAD 268 | ANMULAF 269 | ANMULAD 270 | AMULSF 271 | AMULSD 272 | ANMULSF 273 | ANMULSD 274 | AFMULAF 275 | AFMULAD 276 | AFNMULAF 277 | AFNMULAD 278 | AFMULSF 279 | AFMULSD 280 | AFNMULSF 281 | AFNMULSD 282 | ADIVF 283 | ADIVD 284 | ASQRTF 285 | ASQRTD 286 | AABSF 287 | AABSD 288 | ANEGF 289 | ANEGD 290 | 291 | ASRL 292 | ASRA 293 | ASLL 294 | AMULU 295 | ADIVU 296 | AMUL 297 | AMMUL 298 | ADIV 299 | AMOD 300 | AMODU 301 | ADIVHW 302 | ADIVUHW 303 | 304 | AMOVB 305 | AMOVBS 306 | AMOVBU 307 | AMOVH 308 | AMOVHS 309 | AMOVHU 310 | AMOVW 311 | AMOVM 312 | ASWPBU 313 | ASWPW 314 | 315 | ARFE 316 | ASWI 317 | AMULA 318 | AMULS 319 | AMMULA 320 | AMMULS 321 | 322 | AWORD 323 | 324 | AMULL 325 | AMULAL 326 | AMULLU 327 | AMULALU 328 | 329 | ABX 330 | ABXRET 331 | ADWORD 332 | 333 | ALDREX 334 | ASTREX 335 | ALDREXD 336 | ASTREXD 337 | 338 | ADMB 339 | 340 | APLD 341 | 342 | ACLZ 343 | AREV 344 | AREV16 345 | AREVSH 346 | ARBIT 347 | 348 | AXTAB 349 | AXTAH 350 | AXTABU 351 | AXTAHU 352 | 353 | ABFX 354 | ABFXU 355 | ABFC 356 | ABFI 357 | 358 | AMULWT 359 | AMULWB 360 | AMULBB 361 | AMULAWT 362 | AMULAWB 363 | AMULABB 364 | 365 | AMRC // MRC/MCR 366 | 367 | ALAST 368 | 369 | // aliases 370 | AB = obj.AJMP 371 | ABL = obj.ACALL 372 | ) 373 | 374 | /* scond byte */ 375 | const ( 376 | C_SCOND = (1 << 4) - 1 377 | C_SBIT = 1 << 4 378 | C_PBIT = 1 << 5 379 | C_WBIT = 1 << 6 380 | C_FBIT = 1 << 7 /* psr flags-only */ 381 | C_UBIT = 1 << 7 /* up bit, unsigned bit */ 382 | 383 | // These constants are the ARM condition codes encodings, 384 | // XORed with 14 so that C_SCOND_NONE has value 0, 385 | // so that a zeroed Prog.scond means "always execute". 386 | C_SCOND_XOR = 14 387 | 388 | C_SCOND_EQ = 0 ^ C_SCOND_XOR 389 | C_SCOND_NE = 1 ^ C_SCOND_XOR 390 | C_SCOND_HS = 2 ^ C_SCOND_XOR 391 | C_SCOND_LO = 3 ^ C_SCOND_XOR 392 | C_SCOND_MI = 4 ^ C_SCOND_XOR 393 | C_SCOND_PL = 5 ^ C_SCOND_XOR 394 | C_SCOND_VS = 6 ^ C_SCOND_XOR 395 | C_SCOND_VC = 7 ^ C_SCOND_XOR 396 | C_SCOND_HI = 8 ^ C_SCOND_XOR 397 | C_SCOND_LS = 9 ^ C_SCOND_XOR 398 | C_SCOND_GE = 10 ^ C_SCOND_XOR 399 | C_SCOND_LT = 11 ^ C_SCOND_XOR 400 | C_SCOND_GT = 12 ^ C_SCOND_XOR 401 | C_SCOND_LE = 13 ^ C_SCOND_XOR 402 | C_SCOND_NONE = 14 ^ C_SCOND_XOR 403 | C_SCOND_NV = 15 ^ C_SCOND_XOR 404 | 405 | /* D_SHIFT type */ 406 | SHIFT_LL = 0 << 5 407 | SHIFT_LR = 1 << 5 408 | SHIFT_AR = 2 << 5 409 | SHIFT_RR = 3 << 5 410 | ) 411 | -------------------------------------------------------------------------------- /gen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Downloads the Go sources, building the assembler into a standalone package. 3 | 4 | OUT_DIR=$(pwd) 5 | BASE_PKG_PATH='github.com/twitchyliquid64/golang-asm' 6 | 7 | TMP_PATH=$(mktemp -d) 8 | cleanup () { 9 | if [[ "${TMP_PATH}" != "" ]]; then 10 | rm -rf "${TMP_PATH}" 11 | TMP_PATH="" 12 | fi 13 | } 14 | trap 'cleanup $LINENO' ERR EXIT 15 | 16 | cd $TMP_PATH 17 | git clone --depth 1 https://github.com/golang/go 18 | 19 | rm -rfv ${OUT_DIR}/{asm,dwarf,obj,objabi,src,sys,bio,goobj} 20 | 21 | # Move obj. 22 | cp -rv ${TMP_PATH}/go/src/cmd/internal/obj ${OUT_DIR}/obj 23 | find ${OUT_DIR}/obj -type f -exec sed -i "s_\"cmd/internal/obj_\"${BASE_PKG_PATH}/obj_g" {} \; 24 | find ${OUT_DIR}/obj -type f -exec sed -i "s_\"cmd/internal/dwarf_\"${BASE_PKG_PATH}/dwarf_g" {} \; 25 | find ${OUT_DIR}/obj -type f -exec sed -i "s_\"cmd/internal/src_\"${BASE_PKG_PATH}/src_g" {} \; 26 | find ${OUT_DIR}/obj -type f -exec sed -i "s_\"cmd/internal/sys_\"${BASE_PKG_PATH}/sys_g" {} \; 27 | find ${OUT_DIR}/obj -type f -exec sed -i "s_\"cmd/internal/bio_\"${BASE_PKG_PATH}/bio_g" {} \; 28 | find ${OUT_DIR}/obj -type f -exec sed -i "s_\"cmd/internal/goobj_\"${BASE_PKG_PATH}/goobj_g" {} \; 29 | # Move objabi. 30 | cp -rv ${TMP_PATH}/go/src/cmd/internal/objabi ${OUT_DIR}/objabi 31 | find ${OUT_DIR}/objabi -type f -exec sed -i "s_\"cmd/internal/obj_\"${BASE_PKG_PATH}/obj_g" {} \; 32 | find ${OUT_DIR}/objabi -type f -exec sed -i "s_\"cmd/internal/dwarf_\"${BASE_PKG_PATH}/dwarf_g" {} \; 33 | find ${OUT_DIR}/objabi -type f -exec sed -i "s_\"cmd/internal/src_\"${BASE_PKG_PATH}/src_g" {} \; 34 | find ${OUT_DIR}/objabi -type f -exec sed -i "s_\"cmd/internal/sys_\"${BASE_PKG_PATH}/sys_g" {} \; 35 | find ${OUT_DIR}/objabi -type f -exec sed -i "s_\"cmd/internal/bio_\"${BASE_PKG_PATH}/bio_g" {} \; 36 | find ${OUT_DIR}/objabi -type f -exec sed -i "s_\"cmd/internal/goobj_\"${BASE_PKG_PATH}/goobj_g" {} \; 37 | # Move arch. 38 | mkdir -pv ${OUT_DIR}/asm 39 | cp -rv ${TMP_PATH}/go/src/cmd/asm/internal/arch ${OUT_DIR}/asm/arch 40 | find ${OUT_DIR}/asm/arch -type f -exec sed -i "s_\"cmd/internal/obj_\"${BASE_PKG_PATH}/obj_g" {} \; 41 | find ${OUT_DIR}/asm/arch -type f -exec sed -i "s_\"cmd/internal/dwarf_\"${BASE_PKG_PATH}/dwarf_g" {} \; 42 | find ${OUT_DIR}/asm/arch -type f -exec sed -i "s_\"cmd/internal/src_\"${BASE_PKG_PATH}/src_g" {} \; 43 | find ${OUT_DIR}/asm/arch -type f -exec sed -i "s_\"cmd/internal/sys_\"${BASE_PKG_PATH}/sys_g" {} \; 44 | find ${OUT_DIR}/asm/arch -type f -exec sed -i "s_\"cmd/internal/bio_\"${BASE_PKG_PATH}/bio_g" {} \; 45 | find ${OUT_DIR}/asm/arch -type f -exec sed -i "s_\"cmd/internal/goobj_\"${BASE_PKG_PATH}/goobj_g" {} \; 46 | # Move goobj. 47 | cp -rv ${TMP_PATH}/go/src/cmd/internal/goobj ${OUT_DIR}/goobj 48 | find ${OUT_DIR}/goobj -type f -exec sed -i "s_\"cmd/internal/obj_\"${BASE_PKG_PATH}/obj_g" {} \; 49 | find ${OUT_DIR}/goobj -type f -exec sed -i "s_\"cmd/internal/bio_\"${BASE_PKG_PATH}/bio_g" {} \; 50 | find ${OUT_DIR}/goobj -type f -exec sed -i "s_\"internal/unsafeheader_\"${BASE_PKG_PATH}/unsafeheader_g" {} \; 51 | 52 | # Move bio. 53 | cp -rv ${TMP_PATH}/go/src/cmd/internal/bio ${OUT_DIR}/bio 54 | # Move unsafeheader. 55 | cp -rv ${TMP_PATH}/go/src/internal/unsafeheader ${OUT_DIR}/unsafeheader 56 | # Move dwarf. 57 | cp -rv ${TMP_PATH}/go/src/cmd/internal/dwarf ${OUT_DIR}/dwarf 58 | find ${OUT_DIR}/dwarf -type f -exec sed -i "s_\"cmd/internal/obj_\"${BASE_PKG_PATH}/obj_g" {} \; 59 | # Move src. 60 | cp -rv ${TMP_PATH}/go/src/cmd/internal/src ${OUT_DIR}/src 61 | # Move sys. 62 | cp -rv ${TMP_PATH}/go/src/cmd/internal/sys ${OUT_DIR}/sys 63 | 64 | 65 | # Rewrite identifiers for generated (at build time) constants. 66 | find ${OUT_DIR}/objabi -type f -exec sed -i "s/stackGuardMultiplierDefault/1/g" {} \; 67 | find ${OUT_DIR}/objabi -type f -exec sed -i "s/defaultGOOS/\"linux\"/g" {} \; 68 | find ${OUT_DIR}/objabi -type f -exec sed -i "s/defaultGOARCH/\"$(go env GOARCH)\"/g" {} \; 69 | 70 | find ${OUT_DIR}/objabi -type f -exec sed -i "s/defaultGO386/\"\"/g" {} \; 71 | find ${OUT_DIR}/objabi -type f -exec sed -i "s/defaultGOARM/\"7\"/g" {} \; 72 | find ${OUT_DIR}/objabi -type f -exec sed -i "s/defaultGOMIPS64/\"hardfloat\"/g" {} \; 73 | find ${OUT_DIR}/objabi -type f -exec sed -i "s/defaultGOMIPS/\"hardfloat\"/g" {} \; 74 | find ${OUT_DIR}/objabi -type f -exec sed -i "s/defaultGOPPC64/\"power8\"/g" {} \; 75 | find ${OUT_DIR}/objabi -type f -exec sed -i "s/defaultGO_LDSO/\"\"/g" {} \; 76 | find ${OUT_DIR}/objabi -type f -exec sed -i "s/= version/= \"\"/g" {} \; 77 | find ${OUT_DIR}/objabi -type f -exec sed -i "s/defaultGO_EXTLINK_ENABLED/\"\"/g" {} \; 78 | find ${OUT_DIR}/objabi -type f -exec sed -i "s/goexperiment/\"\"/g" {} \; 79 | 80 | 81 | # Remove tests (they have package dependencies we could do without). 82 | find ${OUT_DIR} -name "*_test.go" -type f -delete 83 | 84 | # Write README. 85 | cat > ${OUT_DIR}/README.md << "EOF" 86 | # golang-asm 87 | 88 | A mirror of the assembler from the Go compiler, with import paths re-written for the assembler to be functional as a standalone library. 89 | 90 | License as per the Go project. 91 | 92 | # Status 93 | 94 | Works, but expect to dig into the assembler godoc's to work out what to set different parameters of `obj.Prog` to get it to generate specific instructions. 95 | 96 | # Example 97 | 98 | Demonstrates assembly of a NOP & an ADD instruction on x86-64. 99 | 100 | ```go 101 | 102 | package main 103 | 104 | import ( 105 | "fmt" 106 | 107 | asm "github.com/twitchyliquid64/golang-asm" 108 | "github.com/twitchyliquid64/golang-asm/obj" 109 | "github.com/twitchyliquid64/golang-asm/obj/x86" 110 | ) 111 | 112 | func noop(builder *asm.Builder) *obj.Prog { 113 | prog := builder.NewProg() 114 | prog.As = x86.ANOPL 115 | prog.From.Type = obj.TYPE_REG 116 | prog.From.Reg = x86.REG_AX 117 | return prog 118 | } 119 | 120 | func addImmediateByte(builder *asm.Builder, in int32) *obj.Prog { 121 | prog := builder.NewProg() 122 | prog.As = x86.AADDB 123 | prog.To.Type = obj.TYPE_REG 124 | prog.To.Reg = x86.REG_AL 125 | prog.From.Type = obj.TYPE_CONST 126 | prog.From.Offset = int64(in) 127 | return prog 128 | } 129 | 130 | func movImmediateByte(builder *asm.Builder, reg int16, in int32) *obj.Prog { 131 | prog := builder.NewProg() 132 | prog.As = x86.AMOVB 133 | prog.To.Type = obj.TYPE_REG 134 | prog.To.Reg = reg 135 | prog.From.Type = obj.TYPE_CONST 136 | prog.From.Offset = int64(in) 137 | return prog 138 | } 139 | 140 | func main() { 141 | b, _ := asm.NewBuilder("amd64", 64) 142 | b.AddInstruction(noop(b)) 143 | b.AddInstruction(movImmediateByte(b, x86.REG_AL, 16)) 144 | b.AddInstruction(addImmediateByte(b, 16)) 145 | fmt.Printf("Bin: %x\n", b.Assemble()) 146 | } 147 | 148 | ``` 149 | 150 | # Working out the parameters of `obj.Prog` 151 | 152 | This took me some time to work out, so I'll write a bit here. 153 | 154 | ## Use these references 155 | 156 | * `obj.Prog` - [godoc](https://godoc.org/github.com/golang/go/src/cmd/internal/obj#Prog) 157 | * Some instructions (like NOP, JMP) are abstract per-platform & can be found [here](https://godoc.org/github.com/golang/go/src/cmd/internal/obj#As) 158 | 159 | * (for amd64) `x86 pkg-constants` - [registers & instructions](https://godoc.org/github.com/golang/go/src/cmd/internal/obj/x86#pkg-constant) 160 | 161 | ## Instruction constants have a naming scheme 162 | 163 | Instructions are defined as constants in the package for the relavant architecture, and have an 'A' prefix and a size suffix. 164 | 165 | For example, the MOV instruction for 64 bits of data is `AMOVQ` (well, at least in amd64). 166 | 167 | ## Search the go source for usage of a given instruction 168 | 169 | For example, if I wanted to work out how to emit the MOV instruction for 64bits, I would search the go source on github for `AMOVQ` or `x86.AMOVQ`. Normally, you see find a few examples where the compiler backend fills in a `obj.Prog` structure, and you follow it's lead. 170 | EOF 171 | 172 | # Write license file. 173 | cat > ${OUT_DIR}/LICENSE << "EOF" 174 | Copyright (c) 2009 The Go Authors. All rights reserved. 175 | 176 | Redistribution and use in source and binary forms, with or without 177 | modification, are permitted provided that the following conditions are 178 | met: 179 | 180 | * Redistributions of source code must retain the above copyright 181 | notice, this list of conditions and the following disclaimer. 182 | * Redistributions in binary form must reproduce the above 183 | copyright notice, this list of conditions and the following disclaimer 184 | in the documentation and/or other materials provided with the 185 | distribution. 186 | * Neither the name of Google Inc. nor the names of its 187 | contributors may be used to endorse or promote products derived from 188 | this software without specific prior written permission. 189 | 190 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 191 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 192 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 194 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 195 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOTto be standalone 196 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 197 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 198 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 199 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 200 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 201 | EOF 202 | --------------------------------------------------------------------------------