forked from apps/featurer
Add vendor to improve building speed.
This also adds ability to be built in network-constrained environment.
This commit is contained in:
16
vendor/github.com/twitchyliquid64/golang-asm/obj/abi_string.go
generated
vendored
Normal file
16
vendor/github.com/twitchyliquid64/golang-asm/obj/abi_string.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Code generated by "stringer -type ABI"; DO NOT EDIT.
|
||||
|
||||
package obj
|
||||
|
||||
import "strconv"
|
||||
|
||||
const _ABI_name = "ABI0ABIInternalABICount"
|
||||
|
||||
var _ABI_index = [...]uint8{0, 4, 15, 23}
|
||||
|
||||
func (i ABI) String() string {
|
||||
if i >= ABI(len(_ABI_index)-1) {
|
||||
return "ABI(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _ABI_name[_ABI_index[i]:_ABI_index[i+1]]
|
||||
}
|
||||
16
vendor/github.com/twitchyliquid64/golang-asm/obj/addrtype_string.go
generated
vendored
Normal file
16
vendor/github.com/twitchyliquid64/golang-asm/obj/addrtype_string.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Code generated by "stringer -type AddrType"; DO NOT EDIT.
|
||||
|
||||
package obj
|
||||
|
||||
import "strconv"
|
||||
|
||||
const _AddrType_name = "TYPE_NONETYPE_BRANCHTYPE_TEXTSIZETYPE_MEMTYPE_CONSTTYPE_FCONSTTYPE_SCONSTTYPE_REGTYPE_ADDRTYPE_SHIFTTYPE_REGREGTYPE_REGREG2TYPE_INDIRTYPE_REGLIST"
|
||||
|
||||
var _AddrType_index = [...]uint8{0, 9, 20, 33, 41, 51, 62, 73, 81, 90, 100, 111, 123, 133, 145}
|
||||
|
||||
func (i AddrType) String() string {
|
||||
if i >= AddrType(len(_AddrType_index)-1) {
|
||||
return "AddrType(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _AddrType_name[_AddrType_index[i]:_AddrType_index[i+1]]
|
||||
}
|
||||
410
vendor/github.com/twitchyliquid64/golang-asm/obj/arm/a.out.go
generated
vendored
Normal file
410
vendor/github.com/twitchyliquid64/golang-asm/obj/arm/a.out.go
generated
vendored
Normal file
@@ -0,0 +1,410 @@
|
||||
// Inferno utils/5c/5.out.h
|
||||
// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5c/5.out.h
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package arm
|
||||
|
||||
import "github.com/twitchyliquid64/golang-asm/obj"
|
||||
|
||||
//go:generate go run ../stringer.go -i $GOFILE -o anames.go -p arm
|
||||
|
||||
const (
|
||||
NSNAME = 8
|
||||
NSYM = 50
|
||||
NREG = 16
|
||||
)
|
||||
|
||||
/* -1 disables use of REGARG */
|
||||
const (
|
||||
REGARG = -1
|
||||
)
|
||||
|
||||
const (
|
||||
REG_R0 = obj.RBaseARM + iota // must be 16-aligned
|
||||
REG_R1
|
||||
REG_R2
|
||||
REG_R3
|
||||
REG_R4
|
||||
REG_R5
|
||||
REG_R6
|
||||
REG_R7
|
||||
REG_R8
|
||||
REG_R9
|
||||
REG_R10
|
||||
REG_R11
|
||||
REG_R12
|
||||
REG_R13
|
||||
REG_R14
|
||||
REG_R15
|
||||
|
||||
REG_F0 // must be 16-aligned
|
||||
REG_F1
|
||||
REG_F2
|
||||
REG_F3
|
||||
REG_F4
|
||||
REG_F5
|
||||
REG_F6
|
||||
REG_F7
|
||||
REG_F8
|
||||
REG_F9
|
||||
REG_F10
|
||||
REG_F11
|
||||
REG_F12
|
||||
REG_F13
|
||||
REG_F14
|
||||
REG_F15
|
||||
|
||||
REG_FPSR // must be 2-aligned
|
||||
REG_FPCR
|
||||
|
||||
REG_CPSR // must be 2-aligned
|
||||
REG_SPSR
|
||||
|
||||
REGRET = REG_R0
|
||||
/* compiler allocates R1 up as temps */
|
||||
/* compiler allocates register variables R3 up */
|
||||
/* compiler allocates external registers R10 down */
|
||||
REGEXT = REG_R10
|
||||
/* these two registers are declared in runtime.h */
|
||||
REGG = REGEXT - 0
|
||||
REGM = REGEXT - 1
|
||||
|
||||
REGCTXT = REG_R7
|
||||
REGTMP = REG_R11
|
||||
REGSP = REG_R13
|
||||
REGLINK = REG_R14
|
||||
REGPC = REG_R15
|
||||
|
||||
NFREG = 16
|
||||
/* compiler allocates register variables F0 up */
|
||||
/* compiler allocates external registers F7 down */
|
||||
FREGRET = REG_F0
|
||||
FREGEXT = REG_F7
|
||||
FREGTMP = REG_F15
|
||||
)
|
||||
|
||||
// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0040b/IHI0040B_aadwarf.pdf
|
||||
var ARMDWARFRegisters = map[int16]int16{}
|
||||
|
||||
func init() {
|
||||
// f assigns dwarfregisters[from:to] = (base):(step*(to-from)+base)
|
||||
f := func(from, to, base, step int16) {
|
||||
for r := int16(from); r <= to; r++ {
|
||||
ARMDWARFRegisters[r] = step*(r-from) + base
|
||||
}
|
||||
}
|
||||
f(REG_R0, REG_R15, 0, 1)
|
||||
f(REG_F0, REG_F15, 64, 2) // Use d0 through D15, aka S0, S2, ..., S30
|
||||
}
|
||||
|
||||
// Special registers, after subtracting obj.RBaseARM, bit 9 indicates
|
||||
// a special register and the low bits select the register.
|
||||
const (
|
||||
REG_SPECIAL = obj.RBaseARM + 1<<9 + iota
|
||||
REG_MB_SY
|
||||
REG_MB_ST
|
||||
REG_MB_ISH
|
||||
REG_MB_ISHST
|
||||
REG_MB_NSH
|
||||
REG_MB_NSHST
|
||||
REG_MB_OSH
|
||||
REG_MB_OSHST
|
||||
|
||||
MAXREG
|
||||
)
|
||||
|
||||
const (
|
||||
C_NONE = iota
|
||||
C_REG
|
||||
C_REGREG
|
||||
C_REGREG2
|
||||
C_REGLIST
|
||||
C_SHIFT /* register shift R>>x */
|
||||
C_SHIFTADDR /* memory address with shifted offset R>>x(R) */
|
||||
C_FREG
|
||||
C_PSR
|
||||
C_FCR
|
||||
C_SPR /* REG_MB_SY */
|
||||
|
||||
C_RCON /* 0xff rotated */
|
||||
C_NCON /* ~RCON */
|
||||
C_RCON2A /* OR of two disjoint C_RCON constants */
|
||||
C_RCON2S /* subtraction of two disjoint C_RCON constants */
|
||||
C_SCON /* 0xffff */
|
||||
C_LCON
|
||||
C_LCONADDR
|
||||
C_ZFCON
|
||||
C_SFCON
|
||||
C_LFCON
|
||||
|
||||
C_RACON
|
||||
C_LACON
|
||||
|
||||
C_SBRA
|
||||
C_LBRA
|
||||
|
||||
C_HAUTO /* halfword insn offset (-0xff to 0xff) */
|
||||
C_FAUTO /* float insn offset (0 to 0x3fc, word aligned) */
|
||||
C_HFAUTO /* both H and F */
|
||||
C_SAUTO /* -0xfff to 0xfff */
|
||||
C_LAUTO
|
||||
|
||||
C_HOREG
|
||||
C_FOREG
|
||||
C_HFOREG
|
||||
C_SOREG
|
||||
C_ROREG
|
||||
C_SROREG /* both nil and R */
|
||||
C_LOREG
|
||||
|
||||
C_PC
|
||||
C_SP
|
||||
C_HREG
|
||||
|
||||
C_ADDR /* reference to relocatable address */
|
||||
|
||||
// TLS "var" in local exec mode: will become a constant offset from
|
||||
// thread local base that is ultimately chosen by the program linker.
|
||||
C_TLS_LE
|
||||
|
||||
// TLS "var" in initial exec mode: will become a memory address (chosen
|
||||
// by the program linker) that the dynamic linker will fill with the
|
||||
// offset from the thread local base.
|
||||
C_TLS_IE
|
||||
|
||||
C_TEXTSIZE
|
||||
|
||||
C_GOK
|
||||
|
||||
C_NCLASS /* must be the last */
|
||||
)
|
||||
|
||||
const (
|
||||
AAND = obj.ABaseARM + obj.A_ARCHSPECIFIC + iota
|
||||
AEOR
|
||||
ASUB
|
||||
ARSB
|
||||
AADD
|
||||
AADC
|
||||
ASBC
|
||||
ARSC
|
||||
ATST
|
||||
ATEQ
|
||||
ACMP
|
||||
ACMN
|
||||
AORR
|
||||
ABIC
|
||||
|
||||
AMVN
|
||||
|
||||
/*
|
||||
* Do not reorder or fragment the conditional branch
|
||||
* opcodes, or the predication code will break
|
||||
*/
|
||||
ABEQ
|
||||
ABNE
|
||||
ABCS
|
||||
ABHS
|
||||
ABCC
|
||||
ABLO
|
||||
ABMI
|
||||
ABPL
|
||||
ABVS
|
||||
ABVC
|
||||
ABHI
|
||||
ABLS
|
||||
ABGE
|
||||
ABLT
|
||||
ABGT
|
||||
ABLE
|
||||
|
||||
AMOVWD
|
||||
AMOVWF
|
||||
AMOVDW
|
||||
AMOVFW
|
||||
AMOVFD
|
||||
AMOVDF
|
||||
AMOVF
|
||||
AMOVD
|
||||
|
||||
ACMPF
|
||||
ACMPD
|
||||
AADDF
|
||||
AADDD
|
||||
ASUBF
|
||||
ASUBD
|
||||
AMULF
|
||||
AMULD
|
||||
ANMULF
|
||||
ANMULD
|
||||
AMULAF
|
||||
AMULAD
|
||||
ANMULAF
|
||||
ANMULAD
|
||||
AMULSF
|
||||
AMULSD
|
||||
ANMULSF
|
||||
ANMULSD
|
||||
AFMULAF
|
||||
AFMULAD
|
||||
AFNMULAF
|
||||
AFNMULAD
|
||||
AFMULSF
|
||||
AFMULSD
|
||||
AFNMULSF
|
||||
AFNMULSD
|
||||
ADIVF
|
||||
ADIVD
|
||||
ASQRTF
|
||||
ASQRTD
|
||||
AABSF
|
||||
AABSD
|
||||
ANEGF
|
||||
ANEGD
|
||||
|
||||
ASRL
|
||||
ASRA
|
||||
ASLL
|
||||
AMULU
|
||||
ADIVU
|
||||
AMUL
|
||||
AMMUL
|
||||
ADIV
|
||||
AMOD
|
||||
AMODU
|
||||
ADIVHW
|
||||
ADIVUHW
|
||||
|
||||
AMOVB
|
||||
AMOVBS
|
||||
AMOVBU
|
||||
AMOVH
|
||||
AMOVHS
|
||||
AMOVHU
|
||||
AMOVW
|
||||
AMOVM
|
||||
ASWPBU
|
||||
ASWPW
|
||||
|
||||
ARFE
|
||||
ASWI
|
||||
AMULA
|
||||
AMULS
|
||||
AMMULA
|
||||
AMMULS
|
||||
|
||||
AWORD
|
||||
|
||||
AMULL
|
||||
AMULAL
|
||||
AMULLU
|
||||
AMULALU
|
||||
|
||||
ABX
|
||||
ABXRET
|
||||
ADWORD
|
||||
|
||||
ALDREX
|
||||
ASTREX
|
||||
ALDREXD
|
||||
ASTREXD
|
||||
|
||||
ADMB
|
||||
|
||||
APLD
|
||||
|
||||
ACLZ
|
||||
AREV
|
||||
AREV16
|
||||
AREVSH
|
||||
ARBIT
|
||||
|
||||
AXTAB
|
||||
AXTAH
|
||||
AXTABU
|
||||
AXTAHU
|
||||
|
||||
ABFX
|
||||
ABFXU
|
||||
ABFC
|
||||
ABFI
|
||||
|
||||
AMULWT
|
||||
AMULWB
|
||||
AMULBB
|
||||
AMULAWT
|
||||
AMULAWB
|
||||
AMULABB
|
||||
|
||||
AMRC // MRC/MCR
|
||||
|
||||
ALAST
|
||||
|
||||
// aliases
|
||||
AB = obj.AJMP
|
||||
ABL = obj.ACALL
|
||||
)
|
||||
|
||||
/* scond byte */
|
||||
const (
|
||||
C_SCOND = (1 << 4) - 1
|
||||
C_SBIT = 1 << 4
|
||||
C_PBIT = 1 << 5
|
||||
C_WBIT = 1 << 6
|
||||
C_FBIT = 1 << 7 /* psr flags-only */
|
||||
C_UBIT = 1 << 7 /* up bit, unsigned bit */
|
||||
|
||||
// These constants are the ARM condition codes encodings,
|
||||
// XORed with 14 so that C_SCOND_NONE has value 0,
|
||||
// so that a zeroed Prog.scond means "always execute".
|
||||
C_SCOND_XOR = 14
|
||||
|
||||
C_SCOND_EQ = 0 ^ C_SCOND_XOR
|
||||
C_SCOND_NE = 1 ^ C_SCOND_XOR
|
||||
C_SCOND_HS = 2 ^ C_SCOND_XOR
|
||||
C_SCOND_LO = 3 ^ C_SCOND_XOR
|
||||
C_SCOND_MI = 4 ^ C_SCOND_XOR
|
||||
C_SCOND_PL = 5 ^ C_SCOND_XOR
|
||||
C_SCOND_VS = 6 ^ C_SCOND_XOR
|
||||
C_SCOND_VC = 7 ^ C_SCOND_XOR
|
||||
C_SCOND_HI = 8 ^ C_SCOND_XOR
|
||||
C_SCOND_LS = 9 ^ C_SCOND_XOR
|
||||
C_SCOND_GE = 10 ^ C_SCOND_XOR
|
||||
C_SCOND_LT = 11 ^ C_SCOND_XOR
|
||||
C_SCOND_GT = 12 ^ C_SCOND_XOR
|
||||
C_SCOND_LE = 13 ^ C_SCOND_XOR
|
||||
C_SCOND_NONE = 14 ^ C_SCOND_XOR
|
||||
C_SCOND_NV = 15 ^ C_SCOND_XOR
|
||||
|
||||
/* D_SHIFT type */
|
||||
SHIFT_LL = 0 << 5
|
||||
SHIFT_LR = 1 << 5
|
||||
SHIFT_AR = 2 << 5
|
||||
SHIFT_RR = 3 << 5
|
||||
)
|
||||
144
vendor/github.com/twitchyliquid64/golang-asm/obj/arm/anames.go
generated
vendored
Normal file
144
vendor/github.com/twitchyliquid64/golang-asm/obj/arm/anames.go
generated
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
// Code generated by stringer -i a.out.go -o anames.go -p arm; DO NOT EDIT.
|
||||
|
||||
package arm
|
||||
|
||||
import "github.com/twitchyliquid64/golang-asm/obj"
|
||||
|
||||
var Anames = []string{
|
||||
obj.A_ARCHSPECIFIC: "AND",
|
||||
"EOR",
|
||||
"SUB",
|
||||
"RSB",
|
||||
"ADD",
|
||||
"ADC",
|
||||
"SBC",
|
||||
"RSC",
|
||||
"TST",
|
||||
"TEQ",
|
||||
"CMP",
|
||||
"CMN",
|
||||
"ORR",
|
||||
"BIC",
|
||||
"MVN",
|
||||
"BEQ",
|
||||
"BNE",
|
||||
"BCS",
|
||||
"BHS",
|
||||
"BCC",
|
||||
"BLO",
|
||||
"BMI",
|
||||
"BPL",
|
||||
"BVS",
|
||||
"BVC",
|
||||
"BHI",
|
||||
"BLS",
|
||||
"BGE",
|
||||
"BLT",
|
||||
"BGT",
|
||||
"BLE",
|
||||
"MOVWD",
|
||||
"MOVWF",
|
||||
"MOVDW",
|
||||
"MOVFW",
|
||||
"MOVFD",
|
||||
"MOVDF",
|
||||
"MOVF",
|
||||
"MOVD",
|
||||
"CMPF",
|
||||
"CMPD",
|
||||
"ADDF",
|
||||
"ADDD",
|
||||
"SUBF",
|
||||
"SUBD",
|
||||
"MULF",
|
||||
"MULD",
|
||||
"NMULF",
|
||||
"NMULD",
|
||||
"MULAF",
|
||||
"MULAD",
|
||||
"NMULAF",
|
||||
"NMULAD",
|
||||
"MULSF",
|
||||
"MULSD",
|
||||
"NMULSF",
|
||||
"NMULSD",
|
||||
"FMULAF",
|
||||
"FMULAD",
|
||||
"FNMULAF",
|
||||
"FNMULAD",
|
||||
"FMULSF",
|
||||
"FMULSD",
|
||||
"FNMULSF",
|
||||
"FNMULSD",
|
||||
"DIVF",
|
||||
"DIVD",
|
||||
"SQRTF",
|
||||
"SQRTD",
|
||||
"ABSF",
|
||||
"ABSD",
|
||||
"NEGF",
|
||||
"NEGD",
|
||||
"SRL",
|
||||
"SRA",
|
||||
"SLL",
|
||||
"MULU",
|
||||
"DIVU",
|
||||
"MUL",
|
||||
"MMUL",
|
||||
"DIV",
|
||||
"MOD",
|
||||
"MODU",
|
||||
"DIVHW",
|
||||
"DIVUHW",
|
||||
"MOVB",
|
||||
"MOVBS",
|
||||
"MOVBU",
|
||||
"MOVH",
|
||||
"MOVHS",
|
||||
"MOVHU",
|
||||
"MOVW",
|
||||
"MOVM",
|
||||
"SWPBU",
|
||||
"SWPW",
|
||||
"RFE",
|
||||
"SWI",
|
||||
"MULA",
|
||||
"MULS",
|
||||
"MMULA",
|
||||
"MMULS",
|
||||
"WORD",
|
||||
"MULL",
|
||||
"MULAL",
|
||||
"MULLU",
|
||||
"MULALU",
|
||||
"BX",
|
||||
"BXRET",
|
||||
"DWORD",
|
||||
"LDREX",
|
||||
"STREX",
|
||||
"LDREXD",
|
||||
"STREXD",
|
||||
"DMB",
|
||||
"PLD",
|
||||
"CLZ",
|
||||
"REV",
|
||||
"REV16",
|
||||
"REVSH",
|
||||
"RBIT",
|
||||
"XTAB",
|
||||
"XTAH",
|
||||
"XTABU",
|
||||
"XTAHU",
|
||||
"BFX",
|
||||
"BFXU",
|
||||
"BFC",
|
||||
"BFI",
|
||||
"MULWT",
|
||||
"MULWB",
|
||||
"MULBB",
|
||||
"MULAWT",
|
||||
"MULAWB",
|
||||
"MULABB",
|
||||
"MRC",
|
||||
"LAST",
|
||||
}
|
||||
77
vendor/github.com/twitchyliquid64/golang-asm/obj/arm/anames5.go
generated
vendored
Normal file
77
vendor/github.com/twitchyliquid64/golang-asm/obj/arm/anames5.go
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package arm
|
||||
|
||||
var cnames5 = []string{
|
||||
"NONE",
|
||||
"REG",
|
||||
"REGREG",
|
||||
"REGREG2",
|
||||
"REGLIST",
|
||||
"SHIFT",
|
||||
"SHIFTADDR",
|
||||
"FREG",
|
||||
"PSR",
|
||||
"FCR",
|
||||
"SPR",
|
||||
"RCON",
|
||||
"NCON",
|
||||
"RCON2A",
|
||||
"RCON2S",
|
||||
"SCON",
|
||||
"LCON",
|
||||
"LCONADDR",
|
||||
"ZFCON",
|
||||
"SFCON",
|
||||
"LFCON",
|
||||
"RACON",
|
||||
"LACON",
|
||||
"SBRA",
|
||||
"LBRA",
|
||||
"HAUTO",
|
||||
"FAUTO",
|
||||
"HFAUTO",
|
||||
"SAUTO",
|
||||
"LAUTO",
|
||||
"HOREG",
|
||||
"FOREG",
|
||||
"HFOREG",
|
||||
"SOREG",
|
||||
"ROREG",
|
||||
"SROREG",
|
||||
"LOREG",
|
||||
"PC",
|
||||
"SP",
|
||||
"HREG",
|
||||
"ADDR",
|
||||
"C_TLS_LE",
|
||||
"C_TLS_IE",
|
||||
"TEXTSIZE",
|
||||
"GOK",
|
||||
"NCLASS",
|
||||
"SCOND = (1<<4)-1",
|
||||
"SBIT = 1<<4",
|
||||
"PBIT = 1<<5",
|
||||
"WBIT = 1<<6",
|
||||
"FBIT = 1<<7",
|
||||
"UBIT = 1<<7",
|
||||
"SCOND_XOR = 14",
|
||||
"SCOND_EQ = 0 ^ C_SCOND_XOR",
|
||||
"SCOND_NE = 1 ^ C_SCOND_XOR",
|
||||
"SCOND_HS = 2 ^ C_SCOND_XOR",
|
||||
"SCOND_LO = 3 ^ C_SCOND_XOR",
|
||||
"SCOND_MI = 4 ^ C_SCOND_XOR",
|
||||
"SCOND_PL = 5 ^ C_SCOND_XOR",
|
||||
"SCOND_VS = 6 ^ C_SCOND_XOR",
|
||||
"SCOND_VC = 7 ^ C_SCOND_XOR",
|
||||
"SCOND_HI = 8 ^ C_SCOND_XOR",
|
||||
"SCOND_LS = 9 ^ C_SCOND_XOR",
|
||||
"SCOND_GE = 10 ^ C_SCOND_XOR",
|
||||
"SCOND_LT = 11 ^ C_SCOND_XOR",
|
||||
"SCOND_GT = 12 ^ C_SCOND_XOR",
|
||||
"SCOND_LE = 13 ^ C_SCOND_XOR",
|
||||
"SCOND_NONE = 14 ^ C_SCOND_XOR",
|
||||
"SCOND_NV = 15 ^ C_SCOND_XOR",
|
||||
}
|
||||
3096
vendor/github.com/twitchyliquid64/golang-asm/obj/arm/asm5.go
generated
vendored
Normal file
3096
vendor/github.com/twitchyliquid64/golang-asm/obj/arm/asm5.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
124
vendor/github.com/twitchyliquid64/golang-asm/obj/arm/list5.go
generated
vendored
Normal file
124
vendor/github.com/twitchyliquid64/golang-asm/obj/arm/list5.go
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
// Inferno utils/5c/list.c
|
||||
// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5c/list.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package arm
|
||||
|
||||
import (
|
||||
"github.com/twitchyliquid64/golang-asm/obj"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func init() {
|
||||
obj.RegisterRegister(obj.RBaseARM, MAXREG, rconv)
|
||||
obj.RegisterOpcode(obj.ABaseARM, Anames)
|
||||
obj.RegisterRegisterList(obj.RegListARMLo, obj.RegListARMHi, rlconv)
|
||||
obj.RegisterOpSuffix("arm", obj.CConvARM)
|
||||
}
|
||||
|
||||
func rconv(r int) string {
|
||||
if r == 0 {
|
||||
return "NONE"
|
||||
}
|
||||
if r == REGG {
|
||||
// Special case.
|
||||
return "g"
|
||||
}
|
||||
if REG_R0 <= r && r <= REG_R15 {
|
||||
return fmt.Sprintf("R%d", r-REG_R0)
|
||||
}
|
||||
if REG_F0 <= r && r <= REG_F15 {
|
||||
return fmt.Sprintf("F%d", r-REG_F0)
|
||||
}
|
||||
|
||||
switch r {
|
||||
case REG_FPSR:
|
||||
return "FPSR"
|
||||
|
||||
case REG_FPCR:
|
||||
return "FPCR"
|
||||
|
||||
case REG_CPSR:
|
||||
return "CPSR"
|
||||
|
||||
case REG_SPSR:
|
||||
return "SPSR"
|
||||
|
||||
case REG_MB_SY:
|
||||
return "MB_SY"
|
||||
case REG_MB_ST:
|
||||
return "MB_ST"
|
||||
case REG_MB_ISH:
|
||||
return "MB_ISH"
|
||||
case REG_MB_ISHST:
|
||||
return "MB_ISHST"
|
||||
case REG_MB_NSH:
|
||||
return "MB_NSH"
|
||||
case REG_MB_NSHST:
|
||||
return "MB_NSHST"
|
||||
case REG_MB_OSH:
|
||||
return "MB_OSH"
|
||||
case REG_MB_OSHST:
|
||||
return "MB_OSHST"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Rgok(%d)", r-obj.RBaseARM)
|
||||
}
|
||||
|
||||
func DRconv(a int) string {
|
||||
s := "C_??"
|
||||
if a >= C_NONE && a <= C_NCLASS {
|
||||
s = cnames5[a]
|
||||
}
|
||||
var fp string
|
||||
fp += s
|
||||
return fp
|
||||
}
|
||||
|
||||
func rlconv(list int64) string {
|
||||
str := ""
|
||||
for i := 0; i < 16; i++ {
|
||||
if list&(1<<uint(i)) != 0 {
|
||||
if str == "" {
|
||||
str += "["
|
||||
} else {
|
||||
str += ","
|
||||
}
|
||||
// This is ARM-specific; R10 is g.
|
||||
if i == REGG-REG_R0 {
|
||||
str += "g"
|
||||
} else {
|
||||
str += fmt.Sprintf("R%d", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
str += "]"
|
||||
return str
|
||||
}
|
||||
784
vendor/github.com/twitchyliquid64/golang-asm/obj/arm/obj5.go
generated
vendored
Normal file
784
vendor/github.com/twitchyliquid64/golang-asm/obj/arm/obj5.go
generated
vendored
Normal file
@@ -0,0 +1,784 @@
|
||||
// Derived from Inferno utils/5c/swt.c
|
||||
// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5c/swt.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package arm
|
||||
|
||||
import (
|
||||
"github.com/twitchyliquid64/golang-asm/obj"
|
||||
"github.com/twitchyliquid64/golang-asm/objabi"
|
||||
"github.com/twitchyliquid64/golang-asm/sys"
|
||||
)
|
||||
|
||||
var progedit_tlsfallback *obj.LSym
|
||||
|
||||
func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
||||
p.From.Class = 0
|
||||
p.To.Class = 0
|
||||
|
||||
c := ctxt5{ctxt: ctxt, newprog: newprog}
|
||||
|
||||
// Rewrite B/BL to symbol as TYPE_BRANCH.
|
||||
switch p.As {
|
||||
case AB, ABL, obj.ADUFFZERO, obj.ADUFFCOPY:
|
||||
if p.To.Type == obj.TYPE_MEM && (p.To.Name == obj.NAME_EXTERN || p.To.Name == obj.NAME_STATIC) && p.To.Sym != nil {
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
}
|
||||
}
|
||||
|
||||
// Replace TLS register fetches on older ARM processors.
|
||||
switch p.As {
|
||||
// Treat MRC 15, 0, <reg>, C13, C0, 3 specially.
|
||||
case AMRC:
|
||||
if p.To.Offset&0xffff0fff == 0xee1d0f70 {
|
||||
// Because the instruction might be rewritten to a BL which returns in R0
|
||||
// the register must be zero.
|
||||
if p.To.Offset&0xf000 != 0 {
|
||||
ctxt.Diag("%v: TLS MRC instruction must write to R0 as it might get translated into a BL instruction", p.Line())
|
||||
}
|
||||
|
||||
if objabi.GOARM < 7 {
|
||||
// Replace it with BL runtime.read_tls_fallback(SB) for ARM CPUs that lack the tls extension.
|
||||
if progedit_tlsfallback == nil {
|
||||
progedit_tlsfallback = ctxt.Lookup("runtime.read_tls_fallback")
|
||||
}
|
||||
|
||||
// MOVW LR, R11
|
||||
p.As = AMOVW
|
||||
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REGLINK
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGTMP
|
||||
|
||||
// BL runtime.read_tls_fallback(SB)
|
||||
p = obj.Appendp(p, newprog)
|
||||
|
||||
p.As = ABL
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
p.To.Sym = progedit_tlsfallback
|
||||
p.To.Offset = 0
|
||||
|
||||
// MOVW R11, LR
|
||||
p = obj.Appendp(p, newprog)
|
||||
|
||||
p.As = AMOVW
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REGTMP
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGLINK
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, MRC/MCR instructions need no further treatment.
|
||||
p.As = AWORD
|
||||
}
|
||||
|
||||
// Rewrite float constants to values stored in memory.
|
||||
switch p.As {
|
||||
case AMOVF:
|
||||
if p.From.Type == obj.TYPE_FCONST && c.chipfloat5(p.From.Val.(float64)) < 0 && (c.chipzero5(p.From.Val.(float64)) < 0 || p.Scond&C_SCOND != C_SCOND_NONE) {
|
||||
f32 := float32(p.From.Val.(float64))
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Sym = ctxt.Float32Sym(f32)
|
||||
p.From.Name = obj.NAME_EXTERN
|
||||
p.From.Offset = 0
|
||||
}
|
||||
|
||||
case AMOVD:
|
||||
if p.From.Type == obj.TYPE_FCONST && c.chipfloat5(p.From.Val.(float64)) < 0 && (c.chipzero5(p.From.Val.(float64)) < 0 || p.Scond&C_SCOND != C_SCOND_NONE) {
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Sym = ctxt.Float64Sym(p.From.Val.(float64))
|
||||
p.From.Name = obj.NAME_EXTERN
|
||||
p.From.Offset = 0
|
||||
}
|
||||
}
|
||||
|
||||
if ctxt.Flag_dynlink {
|
||||
c.rewriteToUseGot(p)
|
||||
}
|
||||
}
|
||||
|
||||
// Rewrite p, if necessary, to access global data via the global offset table.
|
||||
func (c *ctxt5) rewriteToUseGot(p *obj.Prog) {
|
||||
if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
|
||||
// ADUFFxxx $offset
|
||||
// becomes
|
||||
// MOVW runtime.duffxxx@GOT, R9
|
||||
// ADD $offset, R9
|
||||
// CALL (R9)
|
||||
var sym *obj.LSym
|
||||
if p.As == obj.ADUFFZERO {
|
||||
sym = c.ctxt.Lookup("runtime.duffzero")
|
||||
} else {
|
||||
sym = c.ctxt.Lookup("runtime.duffcopy")
|
||||
}
|
||||
offset := p.To.Offset
|
||||
p.As = AMOVW
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Name = obj.NAME_GOTREF
|
||||
p.From.Sym = sym
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R9
|
||||
p.To.Name = obj.NAME_NONE
|
||||
p.To.Offset = 0
|
||||
p.To.Sym = nil
|
||||
p1 := obj.Appendp(p, c.newprog)
|
||||
p1.As = AADD
|
||||
p1.From.Type = obj.TYPE_CONST
|
||||
p1.From.Offset = offset
|
||||
p1.To.Type = obj.TYPE_REG
|
||||
p1.To.Reg = REG_R9
|
||||
p2 := obj.Appendp(p1, c.newprog)
|
||||
p2.As = obj.ACALL
|
||||
p2.To.Type = obj.TYPE_MEM
|
||||
p2.To.Reg = REG_R9
|
||||
return
|
||||
}
|
||||
|
||||
// We only care about global data: NAME_EXTERN means a global
|
||||
// symbol in the Go sense, and p.Sym.Local is true for a few
|
||||
// internally defined symbols.
|
||||
if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
|
||||
// MOVW $sym, Rx becomes MOVW sym@GOT, Rx
|
||||
// MOVW $sym+<off>, Rx becomes MOVW sym@GOT, Rx; ADD <off>, Rx
|
||||
if p.As != AMOVW {
|
||||
c.ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p)
|
||||
}
|
||||
if p.To.Type != obj.TYPE_REG {
|
||||
c.ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v with -dynlink", p)
|
||||
}
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Name = obj.NAME_GOTREF
|
||||
if p.From.Offset != 0 {
|
||||
q := obj.Appendp(p, c.newprog)
|
||||
q.As = AADD
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = p.From.Offset
|
||||
q.To = p.To
|
||||
p.From.Offset = 0
|
||||
}
|
||||
}
|
||||
if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN {
|
||||
c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
|
||||
}
|
||||
var source *obj.Addr
|
||||
// MOVx sym, Ry becomes MOVW sym@GOT, R9; MOVx (R9), Ry
|
||||
// MOVx Ry, sym becomes MOVW sym@GOT, R9; MOVx Ry, (R9)
|
||||
// An addition may be inserted between the two MOVs if there is an offset.
|
||||
if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
|
||||
if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
|
||||
c.ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
|
||||
}
|
||||
source = &p.From
|
||||
} else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
|
||||
source = &p.To
|
||||
} else {
|
||||
return
|
||||
}
|
||||
if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
|
||||
return
|
||||
}
|
||||
if source.Sym.Type == objabi.STLSBSS {
|
||||
return
|
||||
}
|
||||
if source.Type != obj.TYPE_MEM {
|
||||
c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
|
||||
}
|
||||
p1 := obj.Appendp(p, c.newprog)
|
||||
p2 := obj.Appendp(p1, c.newprog)
|
||||
|
||||
p1.As = AMOVW
|
||||
p1.From.Type = obj.TYPE_MEM
|
||||
p1.From.Sym = source.Sym
|
||||
p1.From.Name = obj.NAME_GOTREF
|
||||
p1.To.Type = obj.TYPE_REG
|
||||
p1.To.Reg = REG_R9
|
||||
|
||||
p2.As = p.As
|
||||
p2.From = p.From
|
||||
p2.To = p.To
|
||||
if p.From.Name == obj.NAME_EXTERN {
|
||||
p2.From.Reg = REG_R9
|
||||
p2.From.Name = obj.NAME_NONE
|
||||
p2.From.Sym = nil
|
||||
} else if p.To.Name == obj.NAME_EXTERN {
|
||||
p2.To.Reg = REG_R9
|
||||
p2.To.Name = obj.NAME_NONE
|
||||
p2.To.Sym = nil
|
||||
} else {
|
||||
return
|
||||
}
|
||||
obj.Nopout(p)
|
||||
}
|
||||
|
||||
// Prog.mark
|
||||
const (
|
||||
FOLL = 1 << 0
|
||||
LABEL = 1 << 1
|
||||
LEAF = 1 << 2
|
||||
)
|
||||
|
||||
func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
||||
autosize := int32(0)
|
||||
|
||||
if cursym.Func.Text == nil || cursym.Func.Text.Link == nil {
|
||||
return
|
||||
}
|
||||
|
||||
c := ctxt5{ctxt: ctxt, cursym: cursym, newprog: newprog}
|
||||
|
||||
p := c.cursym.Func.Text
|
||||
autoffset := int32(p.To.Offset)
|
||||
if autoffset == -4 {
|
||||
// Historical way to mark NOFRAME.
|
||||
p.From.Sym.Set(obj.AttrNoFrame, true)
|
||||
autoffset = 0
|
||||
}
|
||||
if autoffset < 0 || autoffset%4 != 0 {
|
||||
c.ctxt.Diag("frame size %d not 0 or a positive multiple of 4", autoffset)
|
||||
}
|
||||
if p.From.Sym.NoFrame() {
|
||||
if autoffset != 0 {
|
||||
c.ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", autoffset)
|
||||
}
|
||||
}
|
||||
|
||||
cursym.Func.Locals = autoffset
|
||||
cursym.Func.Args = p.To.Val.(int32)
|
||||
|
||||
/*
|
||||
* find leaf subroutines
|
||||
*/
|
||||
for p := cursym.Func.Text; p != nil; p = p.Link {
|
||||
switch p.As {
|
||||
case obj.ATEXT:
|
||||
p.Mark |= LEAF
|
||||
|
||||
case ADIV, ADIVU, AMOD, AMODU:
|
||||
cursym.Func.Text.Mark &^= LEAF
|
||||
|
||||
case ABL,
|
||||
ABX,
|
||||
obj.ADUFFZERO,
|
||||
obj.ADUFFCOPY:
|
||||
cursym.Func.Text.Mark &^= LEAF
|
||||
}
|
||||
}
|
||||
|
||||
var q2 *obj.Prog
|
||||
for p := cursym.Func.Text; p != nil; p = p.Link {
|
||||
o := p.As
|
||||
switch o {
|
||||
case obj.ATEXT:
|
||||
autosize = autoffset
|
||||
|
||||
if p.Mark&LEAF != 0 && autosize == 0 {
|
||||
// A leaf function with no locals has no frame.
|
||||
p.From.Sym.Set(obj.AttrNoFrame, true)
|
||||
}
|
||||
|
||||
if !p.From.Sym.NoFrame() {
|
||||
// If there is a stack frame at all, it includes
|
||||
// space to save the LR.
|
||||
autosize += 4
|
||||
}
|
||||
|
||||
if autosize == 0 && cursym.Func.Text.Mark&LEAF == 0 {
|
||||
// A very few functions that do not return to their caller
|
||||
// are not identified as leaves but still have no frame.
|
||||
if ctxt.Debugvlog {
|
||||
ctxt.Logf("save suppressed in: %s\n", cursym.Name)
|
||||
}
|
||||
|
||||
cursym.Func.Text.Mark |= LEAF
|
||||
}
|
||||
|
||||
// FP offsets need an updated p.To.Offset.
|
||||
p.To.Offset = int64(autosize) - 4
|
||||
|
||||
if cursym.Func.Text.Mark&LEAF != 0 {
|
||||
cursym.Set(obj.AttrLeaf, true)
|
||||
if p.From.Sym.NoFrame() {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !p.From.Sym.NoSplit() {
|
||||
p = c.stacksplit(p, autosize) // emit split check
|
||||
}
|
||||
|
||||
// MOVW.W R14,$-autosize(SP)
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = AMOVW
|
||||
p.Scond |= C_WBIT
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REGLINK
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Offset = int64(-autosize)
|
||||
p.To.Reg = REGSP
|
||||
p.Spadj = autosize
|
||||
|
||||
if cursym.Func.Text.From.Sym.Wrapper() {
|
||||
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
|
||||
//
|
||||
// MOVW g_panic(g), R1
|
||||
// CMP $0, R1
|
||||
// B.NE checkargp
|
||||
// end:
|
||||
// NOP
|
||||
// ... function ...
|
||||
// checkargp:
|
||||
// MOVW panic_argp(R1), R2
|
||||
// ADD $(autosize+4), R13, R3
|
||||
// CMP R2, R3
|
||||
// B.NE end
|
||||
// ADD $4, R13, R4
|
||||
// MOVW R4, panic_argp(R1)
|
||||
// B end
|
||||
//
|
||||
// The NOP is needed to give the jumps somewhere to land.
|
||||
// It is a liblink NOP, not an ARM NOP: it encodes to 0 instruction bytes.
|
||||
|
||||
p = obj.Appendp(p, newprog)
|
||||
p.As = AMOVW
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = REGG
|
||||
p.From.Offset = 4 * int64(ctxt.Arch.PtrSize) // G.panic
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R1
|
||||
|
||||
p = obj.Appendp(p, newprog)
|
||||
p.As = ACMP
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = 0
|
||||
p.Reg = REG_R1
|
||||
|
||||
// B.NE checkargp
|
||||
bne := obj.Appendp(p, newprog)
|
||||
bne.As = ABNE
|
||||
bne.To.Type = obj.TYPE_BRANCH
|
||||
|
||||
// end: NOP
|
||||
end := obj.Appendp(bne, newprog)
|
||||
end.As = obj.ANOP
|
||||
|
||||
// find end of function
|
||||
var last *obj.Prog
|
||||
for last = end; last.Link != nil; last = last.Link {
|
||||
}
|
||||
|
||||
// MOVW panic_argp(R1), R2
|
||||
mov := obj.Appendp(last, newprog)
|
||||
mov.As = AMOVW
|
||||
mov.From.Type = obj.TYPE_MEM
|
||||
mov.From.Reg = REG_R1
|
||||
mov.From.Offset = 0 // Panic.argp
|
||||
mov.To.Type = obj.TYPE_REG
|
||||
mov.To.Reg = REG_R2
|
||||
|
||||
// B.NE branch target is MOVW above
|
||||
bne.To.SetTarget(mov)
|
||||
|
||||
// ADD $(autosize+4), R13, R3
|
||||
p = obj.Appendp(mov, newprog)
|
||||
p.As = AADD
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = int64(autosize) + 4
|
||||
p.Reg = REG_R13
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R3
|
||||
|
||||
// CMP R2, R3
|
||||
p = obj.Appendp(p, newprog)
|
||||
p.As = ACMP
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_R2
|
||||
p.Reg = REG_R3
|
||||
|
||||
// B.NE end
|
||||
p = obj.Appendp(p, newprog)
|
||||
p.As = ABNE
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
p.To.SetTarget(end)
|
||||
|
||||
// ADD $4, R13, R4
|
||||
p = obj.Appendp(p, newprog)
|
||||
p.As = AADD
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = 4
|
||||
p.Reg = REG_R13
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R4
|
||||
|
||||
// MOVW R4, panic_argp(R1)
|
||||
p = obj.Appendp(p, newprog)
|
||||
p.As = AMOVW
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_R4
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Reg = REG_R1
|
||||
p.To.Offset = 0 // Panic.argp
|
||||
|
||||
// B end
|
||||
p = obj.Appendp(p, newprog)
|
||||
p.As = AB
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
p.To.SetTarget(end)
|
||||
|
||||
// reset for subsequent passes
|
||||
p = end
|
||||
}
|
||||
|
||||
case obj.ARET:
|
||||
nocache(p)
|
||||
if cursym.Func.Text.Mark&LEAF != 0 {
|
||||
if autosize == 0 {
|
||||
p.As = AB
|
||||
p.From = obj.Addr{}
|
||||
if p.To.Sym != nil { // retjmp
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
} else {
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Offset = 0
|
||||
p.To.Reg = REGLINK
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
p.As = AMOVW
|
||||
p.Scond |= C_PBIT
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Offset = int64(autosize)
|
||||
p.From.Reg = REGSP
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGPC
|
||||
|
||||
// If there are instructions following
|
||||
// this ARET, they come from a branch
|
||||
// with the same stackframe, so no spadj.
|
||||
if p.To.Sym != nil { // retjmp
|
||||
p.To.Reg = REGLINK
|
||||
q2 = obj.Appendp(p, newprog)
|
||||
q2.As = AB
|
||||
q2.To.Type = obj.TYPE_BRANCH
|
||||
q2.To.Sym = p.To.Sym
|
||||
p.To.Sym = nil
|
||||
p = q2
|
||||
}
|
||||
|
||||
case AADD:
|
||||
if p.From.Type == obj.TYPE_CONST && p.From.Reg == 0 && p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP {
|
||||
p.Spadj = int32(-p.From.Offset)
|
||||
}
|
||||
|
||||
case ASUB:
|
||||
if p.From.Type == obj.TYPE_CONST && p.From.Reg == 0 && p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP {
|
||||
p.Spadj = int32(p.From.Offset)
|
||||
}
|
||||
|
||||
case ADIV, ADIVU, AMOD, AMODU:
|
||||
if cursym.Func.Text.From.Sym.NoSplit() {
|
||||
ctxt.Diag("cannot divide in NOSPLIT function")
|
||||
}
|
||||
const debugdivmod = false
|
||||
if debugdivmod {
|
||||
break
|
||||
}
|
||||
if p.From.Type != obj.TYPE_REG {
|
||||
break
|
||||
}
|
||||
if p.To.Type != obj.TYPE_REG {
|
||||
break
|
||||
}
|
||||
|
||||
// Make copy because we overwrite p below.
|
||||
q1 := *p
|
||||
if q1.Reg == REGTMP || q1.Reg == 0 && q1.To.Reg == REGTMP {
|
||||
ctxt.Diag("div already using REGTMP: %v", p)
|
||||
}
|
||||
|
||||
/* MOV m(g),REGTMP */
|
||||
p.As = AMOVW
|
||||
p.Pos = q1.Pos
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = REGG
|
||||
p.From.Offset = 6 * 4 // offset of g.m
|
||||
p.Reg = 0
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGTMP
|
||||
|
||||
/* MOV a,m_divmod(REGTMP) */
|
||||
p = obj.Appendp(p, newprog)
|
||||
p.As = AMOVW
|
||||
p.Pos = q1.Pos
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = q1.From.Reg
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Reg = REGTMP
|
||||
p.To.Offset = 8 * 4 // offset of m.divmod
|
||||
|
||||
/* MOV b, R8 */
|
||||
p = obj.Appendp(p, newprog)
|
||||
p.As = AMOVW
|
||||
p.Pos = q1.Pos
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = q1.Reg
|
||||
if q1.Reg == 0 {
|
||||
p.From.Reg = q1.To.Reg
|
||||
}
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R8
|
||||
p.To.Offset = 0
|
||||
|
||||
/* CALL appropriate */
|
||||
p = obj.Appendp(p, newprog)
|
||||
p.As = ABL
|
||||
p.Pos = q1.Pos
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
switch o {
|
||||
case ADIV:
|
||||
p.To.Sym = symdiv
|
||||
case ADIVU:
|
||||
p.To.Sym = symdivu
|
||||
case AMOD:
|
||||
p.To.Sym = symmod
|
||||
case AMODU:
|
||||
p.To.Sym = symmodu
|
||||
}
|
||||
|
||||
/* MOV REGTMP, b */
|
||||
p = obj.Appendp(p, newprog)
|
||||
p.As = AMOVW
|
||||
p.Pos = q1.Pos
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REGTMP
|
||||
p.From.Offset = 0
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = q1.To.Reg
|
||||
|
||||
case AMOVW:
|
||||
if (p.Scond&C_WBIT != 0) && p.To.Type == obj.TYPE_MEM && p.To.Reg == REGSP {
|
||||
p.Spadj = int32(-p.To.Offset)
|
||||
}
|
||||
if (p.Scond&C_PBIT != 0) && p.From.Type == obj.TYPE_MEM && p.From.Reg == REGSP && p.To.Reg != REGPC {
|
||||
p.Spadj = int32(-p.From.Offset)
|
||||
}
|
||||
if p.From.Type == obj.TYPE_ADDR && p.From.Reg == REGSP && p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP {
|
||||
p.Spadj = int32(-p.From.Offset)
|
||||
}
|
||||
|
||||
case obj.AGETCALLERPC:
|
||||
if cursym.Leaf() {
|
||||
/* MOVW LR, Rd */
|
||||
p.As = AMOVW
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REGLINK
|
||||
} else {
|
||||
/* MOVW (RSP), Rd */
|
||||
p.As = AMOVW
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = REGSP
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ctxt5) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
|
||||
// MOVW g_stackguard(g), R1
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = AMOVW
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = REGG
|
||||
p.From.Offset = 2 * int64(c.ctxt.Arch.PtrSize) // G.stackguard0
|
||||
if c.cursym.CFunc() {
|
||||
p.From.Offset = 3 * int64(c.ctxt.Arch.PtrSize) // G.stackguard1
|
||||
}
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R1
|
||||
|
||||
// Mark the stack bound check and morestack call async nonpreemptible.
|
||||
// If we get preempted here, when resumed the preemption request is
|
||||
// cleared, but we'll still call morestack, which will double the stack
|
||||
// unnecessarily. See issue #35470.
|
||||
p = c.ctxt.StartUnsafePoint(p, c.newprog)
|
||||
|
||||
if framesize <= objabi.StackSmall {
|
||||
// small stack: SP < stackguard
|
||||
// CMP stackguard, SP
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = ACMP
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_R1
|
||||
p.Reg = REGSP
|
||||
} else if framesize <= objabi.StackBig {
|
||||
// large stack: SP-framesize < stackguard-StackSmall
|
||||
// MOVW $-(framesize-StackSmall)(SP), R2
|
||||
// CMP stackguard, R2
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = AMOVW
|
||||
p.From.Type = obj.TYPE_ADDR
|
||||
p.From.Reg = REGSP
|
||||
p.From.Offset = -(int64(framesize) - objabi.StackSmall)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R2
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = ACMP
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_R1
|
||||
p.Reg = REG_R2
|
||||
} else {
|
||||
// Such a large stack we need to protect against wraparound
|
||||
// if SP is close to zero.
|
||||
// SP-stackguard+StackGuard < framesize + (StackGuard-StackSmall)
|
||||
// The +StackGuard on both sides is required to keep the left side positive:
|
||||
// SP is allowed to be slightly below stackguard. See stack.h.
|
||||
// CMP $StackPreempt, R1
|
||||
// MOVW.NE $StackGuard(SP), R2
|
||||
// SUB.NE R1, R2
|
||||
// MOVW.NE $(framesize+(StackGuard-StackSmall)), R3
|
||||
// CMP.NE R3, R2
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = ACMP
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = int64(uint32(objabi.StackPreempt & (1<<32 - 1)))
|
||||
p.Reg = REG_R1
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = AMOVW
|
||||
p.From.Type = obj.TYPE_ADDR
|
||||
p.From.Reg = REGSP
|
||||
p.From.Offset = int64(objabi.StackGuard)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R2
|
||||
p.Scond = C_SCOND_NE
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = ASUB
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_R1
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R2
|
||||
p.Scond = C_SCOND_NE
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = AMOVW
|
||||
p.From.Type = obj.TYPE_ADDR
|
||||
p.From.Offset = int64(framesize) + (int64(objabi.StackGuard) - objabi.StackSmall)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R3
|
||||
p.Scond = C_SCOND_NE
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = ACMP
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_R3
|
||||
p.Reg = REG_R2
|
||||
p.Scond = C_SCOND_NE
|
||||
}
|
||||
|
||||
// BLS call-to-morestack
|
||||
bls := obj.Appendp(p, c.newprog)
|
||||
bls.As = ABLS
|
||||
bls.To.Type = obj.TYPE_BRANCH
|
||||
|
||||
end := c.ctxt.EndUnsafePoint(bls, c.newprog, -1)
|
||||
|
||||
var last *obj.Prog
|
||||
for last = c.cursym.Func.Text; last.Link != nil; last = last.Link {
|
||||
}
|
||||
|
||||
// Now we are at the end of the function, but logically
|
||||
// we are still in function prologue. We need to fix the
|
||||
// SP data and PCDATA.
|
||||
spfix := obj.Appendp(last, c.newprog)
|
||||
spfix.As = obj.ANOP
|
||||
spfix.Spadj = -framesize
|
||||
|
||||
pcdata := c.ctxt.EmitEntryStackMap(c.cursym, spfix, c.newprog)
|
||||
pcdata = c.ctxt.StartUnsafePoint(pcdata, c.newprog)
|
||||
|
||||
// MOVW LR, R3
|
||||
movw := obj.Appendp(pcdata, c.newprog)
|
||||
movw.As = AMOVW
|
||||
movw.From.Type = obj.TYPE_REG
|
||||
movw.From.Reg = REGLINK
|
||||
movw.To.Type = obj.TYPE_REG
|
||||
movw.To.Reg = REG_R3
|
||||
|
||||
bls.To.SetTarget(movw)
|
||||
|
||||
// BL runtime.morestack
|
||||
call := obj.Appendp(movw, c.newprog)
|
||||
call.As = obj.ACALL
|
||||
call.To.Type = obj.TYPE_BRANCH
|
||||
morestack := "runtime.morestack"
|
||||
switch {
|
||||
case c.cursym.CFunc():
|
||||
morestack = "runtime.morestackc"
|
||||
case !c.cursym.Func.Text.From.Sym.NeedCtxt():
|
||||
morestack = "runtime.morestack_noctxt"
|
||||
}
|
||||
call.To.Sym = c.ctxt.Lookup(morestack)
|
||||
|
||||
pcdata = c.ctxt.EndUnsafePoint(call, c.newprog, -1)
|
||||
|
||||
// B start
|
||||
b := obj.Appendp(pcdata, c.newprog)
|
||||
b.As = obj.AJMP
|
||||
b.To.Type = obj.TYPE_BRANCH
|
||||
b.To.SetTarget(c.cursym.Func.Text.Link)
|
||||
b.Spadj = +framesize
|
||||
|
||||
return end
|
||||
}
|
||||
|
||||
var unaryDst = map[obj.As]bool{
|
||||
ASWI: true,
|
||||
AWORD: true,
|
||||
}
|
||||
|
||||
var Linkarm = obj.LinkArch{
|
||||
Arch: sys.ArchARM,
|
||||
Init: buildop,
|
||||
Preprocess: preprocess,
|
||||
Assemble: span5,
|
||||
Progedit: progedit,
|
||||
UnaryDst: unaryDst,
|
||||
DWARFRegisters: ARMDWARFRegisters,
|
||||
}
|
||||
1033
vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/a.out.go
generated
vendored
Normal file
1033
vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/a.out.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
512
vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/anames.go
generated
vendored
Normal file
512
vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/anames.go
generated
vendored
Normal file
@@ -0,0 +1,512 @@
|
||||
// Code generated by stringer -i a.out.go -o anames.go -p arm64; DO NOT EDIT.
|
||||
|
||||
package arm64
|
||||
|
||||
import "github.com/twitchyliquid64/golang-asm/obj"
|
||||
|
||||
var Anames = []string{
|
||||
obj.A_ARCHSPECIFIC: "ADC",
|
||||
"ADCS",
|
||||
"ADCSW",
|
||||
"ADCW",
|
||||
"ADD",
|
||||
"ADDS",
|
||||
"ADDSW",
|
||||
"ADDW",
|
||||
"ADR",
|
||||
"ADRP",
|
||||
"AND",
|
||||
"ANDS",
|
||||
"ANDSW",
|
||||
"ANDW",
|
||||
"ASR",
|
||||
"ASRW",
|
||||
"AT",
|
||||
"BFI",
|
||||
"BFIW",
|
||||
"BFM",
|
||||
"BFMW",
|
||||
"BFXIL",
|
||||
"BFXILW",
|
||||
"BIC",
|
||||
"BICS",
|
||||
"BICSW",
|
||||
"BICW",
|
||||
"BRK",
|
||||
"CBNZ",
|
||||
"CBNZW",
|
||||
"CBZ",
|
||||
"CBZW",
|
||||
"CCMN",
|
||||
"CCMNW",
|
||||
"CCMP",
|
||||
"CCMPW",
|
||||
"CINC",
|
||||
"CINCW",
|
||||
"CINV",
|
||||
"CINVW",
|
||||
"CLREX",
|
||||
"CLS",
|
||||
"CLSW",
|
||||
"CLZ",
|
||||
"CLZW",
|
||||
"CMN",
|
||||
"CMNW",
|
||||
"CMP",
|
||||
"CMPW",
|
||||
"CNEG",
|
||||
"CNEGW",
|
||||
"CRC32B",
|
||||
"CRC32CB",
|
||||
"CRC32CH",
|
||||
"CRC32CW",
|
||||
"CRC32CX",
|
||||
"CRC32H",
|
||||
"CRC32W",
|
||||
"CRC32X",
|
||||
"CSEL",
|
||||
"CSELW",
|
||||
"CSET",
|
||||
"CSETM",
|
||||
"CSETMW",
|
||||
"CSETW",
|
||||
"CSINC",
|
||||
"CSINCW",
|
||||
"CSINV",
|
||||
"CSINVW",
|
||||
"CSNEG",
|
||||
"CSNEGW",
|
||||
"DC",
|
||||
"DCPS1",
|
||||
"DCPS2",
|
||||
"DCPS3",
|
||||
"DMB",
|
||||
"DRPS",
|
||||
"DSB",
|
||||
"EON",
|
||||
"EONW",
|
||||
"EOR",
|
||||
"EORW",
|
||||
"ERET",
|
||||
"EXTR",
|
||||
"EXTRW",
|
||||
"HINT",
|
||||
"HLT",
|
||||
"HVC",
|
||||
"IC",
|
||||
"ISB",
|
||||
"LDADDAB",
|
||||
"LDADDAD",
|
||||
"LDADDAH",
|
||||
"LDADDAW",
|
||||
"LDADDALB",
|
||||
"LDADDALD",
|
||||
"LDADDALH",
|
||||
"LDADDALW",
|
||||
"LDADDB",
|
||||
"LDADDD",
|
||||
"LDADDH",
|
||||
"LDADDW",
|
||||
"LDADDLB",
|
||||
"LDADDLD",
|
||||
"LDADDLH",
|
||||
"LDADDLW",
|
||||
"LDANDAB",
|
||||
"LDANDAD",
|
||||
"LDANDAH",
|
||||
"LDANDAW",
|
||||
"LDANDALB",
|
||||
"LDANDALD",
|
||||
"LDANDALH",
|
||||
"LDANDALW",
|
||||
"LDANDB",
|
||||
"LDANDD",
|
||||
"LDANDH",
|
||||
"LDANDW",
|
||||
"LDANDLB",
|
||||
"LDANDLD",
|
||||
"LDANDLH",
|
||||
"LDANDLW",
|
||||
"LDAR",
|
||||
"LDARB",
|
||||
"LDARH",
|
||||
"LDARW",
|
||||
"LDAXP",
|
||||
"LDAXPW",
|
||||
"LDAXR",
|
||||
"LDAXRB",
|
||||
"LDAXRH",
|
||||
"LDAXRW",
|
||||
"LDEORAB",
|
||||
"LDEORAD",
|
||||
"LDEORAH",
|
||||
"LDEORAW",
|
||||
"LDEORALB",
|
||||
"LDEORALD",
|
||||
"LDEORALH",
|
||||
"LDEORALW",
|
||||
"LDEORB",
|
||||
"LDEORD",
|
||||
"LDEORH",
|
||||
"LDEORW",
|
||||
"LDEORLB",
|
||||
"LDEORLD",
|
||||
"LDEORLH",
|
||||
"LDEORLW",
|
||||
"LDORAB",
|
||||
"LDORAD",
|
||||
"LDORAH",
|
||||
"LDORAW",
|
||||
"LDORALB",
|
||||
"LDORALD",
|
||||
"LDORALH",
|
||||
"LDORALW",
|
||||
"LDORB",
|
||||
"LDORD",
|
||||
"LDORH",
|
||||
"LDORW",
|
||||
"LDORLB",
|
||||
"LDORLD",
|
||||
"LDORLH",
|
||||
"LDORLW",
|
||||
"LDP",
|
||||
"LDPW",
|
||||
"LDPSW",
|
||||
"LDXR",
|
||||
"LDXRB",
|
||||
"LDXRH",
|
||||
"LDXRW",
|
||||
"LDXP",
|
||||
"LDXPW",
|
||||
"LSL",
|
||||
"LSLW",
|
||||
"LSR",
|
||||
"LSRW",
|
||||
"MADD",
|
||||
"MADDW",
|
||||
"MNEG",
|
||||
"MNEGW",
|
||||
"MOVK",
|
||||
"MOVKW",
|
||||
"MOVN",
|
||||
"MOVNW",
|
||||
"MOVZ",
|
||||
"MOVZW",
|
||||
"MRS",
|
||||
"MSR",
|
||||
"MSUB",
|
||||
"MSUBW",
|
||||
"MUL",
|
||||
"MULW",
|
||||
"MVN",
|
||||
"MVNW",
|
||||
"NEG",
|
||||
"NEGS",
|
||||
"NEGSW",
|
||||
"NEGW",
|
||||
"NGC",
|
||||
"NGCS",
|
||||
"NGCSW",
|
||||
"NGCW",
|
||||
"NOOP",
|
||||
"ORN",
|
||||
"ORNW",
|
||||
"ORR",
|
||||
"ORRW",
|
||||
"PRFM",
|
||||
"PRFUM",
|
||||
"RBIT",
|
||||
"RBITW",
|
||||
"REM",
|
||||
"REMW",
|
||||
"REV",
|
||||
"REV16",
|
||||
"REV16W",
|
||||
"REV32",
|
||||
"REVW",
|
||||
"ROR",
|
||||
"RORW",
|
||||
"SBC",
|
||||
"SBCS",
|
||||
"SBCSW",
|
||||
"SBCW",
|
||||
"SBFIZ",
|
||||
"SBFIZW",
|
||||
"SBFM",
|
||||
"SBFMW",
|
||||
"SBFX",
|
||||
"SBFXW",
|
||||
"SDIV",
|
||||
"SDIVW",
|
||||
"SEV",
|
||||
"SEVL",
|
||||
"SMADDL",
|
||||
"SMC",
|
||||
"SMNEGL",
|
||||
"SMSUBL",
|
||||
"SMULH",
|
||||
"SMULL",
|
||||
"STXR",
|
||||
"STXRB",
|
||||
"STXRH",
|
||||
"STXP",
|
||||
"STXPW",
|
||||
"STXRW",
|
||||
"STLP",
|
||||
"STLPW",
|
||||
"STLR",
|
||||
"STLRB",
|
||||
"STLRH",
|
||||
"STLRW",
|
||||
"STLXP",
|
||||
"STLXPW",
|
||||
"STLXR",
|
||||
"STLXRB",
|
||||
"STLXRH",
|
||||
"STLXRW",
|
||||
"STP",
|
||||
"STPW",
|
||||
"SUB",
|
||||
"SUBS",
|
||||
"SUBSW",
|
||||
"SUBW",
|
||||
"SVC",
|
||||
"SXTB",
|
||||
"SXTBW",
|
||||
"SXTH",
|
||||
"SXTHW",
|
||||
"SXTW",
|
||||
"SYS",
|
||||
"SYSL",
|
||||
"TBNZ",
|
||||
"TBZ",
|
||||
"TLBI",
|
||||
"TST",
|
||||
"TSTW",
|
||||
"UBFIZ",
|
||||
"UBFIZW",
|
||||
"UBFM",
|
||||
"UBFMW",
|
||||
"UBFX",
|
||||
"UBFXW",
|
||||
"UDIV",
|
||||
"UDIVW",
|
||||
"UMADDL",
|
||||
"UMNEGL",
|
||||
"UMSUBL",
|
||||
"UMULH",
|
||||
"UMULL",
|
||||
"UREM",
|
||||
"UREMW",
|
||||
"UXTB",
|
||||
"UXTH",
|
||||
"UXTW",
|
||||
"UXTBW",
|
||||
"UXTHW",
|
||||
"WFE",
|
||||
"WFI",
|
||||
"YIELD",
|
||||
"MOVB",
|
||||
"MOVBU",
|
||||
"MOVH",
|
||||
"MOVHU",
|
||||
"MOVW",
|
||||
"MOVWU",
|
||||
"MOVD",
|
||||
"MOVNP",
|
||||
"MOVNPW",
|
||||
"MOVP",
|
||||
"MOVPD",
|
||||
"MOVPQ",
|
||||
"MOVPS",
|
||||
"MOVPSW",
|
||||
"MOVPW",
|
||||
"SWPAD",
|
||||
"SWPAW",
|
||||
"SWPAH",
|
||||
"SWPAB",
|
||||
"SWPALD",
|
||||
"SWPALW",
|
||||
"SWPALH",
|
||||
"SWPALB",
|
||||
"SWPD",
|
||||
"SWPW",
|
||||
"SWPH",
|
||||
"SWPB",
|
||||
"SWPLD",
|
||||
"SWPLW",
|
||||
"SWPLH",
|
||||
"SWPLB",
|
||||
"BEQ",
|
||||
"BNE",
|
||||
"BCS",
|
||||
"BHS",
|
||||
"BCC",
|
||||
"BLO",
|
||||
"BMI",
|
||||
"BPL",
|
||||
"BVS",
|
||||
"BVC",
|
||||
"BHI",
|
||||
"BLS",
|
||||
"BGE",
|
||||
"BLT",
|
||||
"BGT",
|
||||
"BLE",
|
||||
"FABSD",
|
||||
"FABSS",
|
||||
"FADDD",
|
||||
"FADDS",
|
||||
"FCCMPD",
|
||||
"FCCMPED",
|
||||
"FCCMPS",
|
||||
"FCCMPES",
|
||||
"FCMPD",
|
||||
"FCMPED",
|
||||
"FCMPES",
|
||||
"FCMPS",
|
||||
"FCVTSD",
|
||||
"FCVTDS",
|
||||
"FCVTZSD",
|
||||
"FCVTZSDW",
|
||||
"FCVTZSS",
|
||||
"FCVTZSSW",
|
||||
"FCVTZUD",
|
||||
"FCVTZUDW",
|
||||
"FCVTZUS",
|
||||
"FCVTZUSW",
|
||||
"FDIVD",
|
||||
"FDIVS",
|
||||
"FLDPD",
|
||||
"FLDPS",
|
||||
"FMOVD",
|
||||
"FMOVS",
|
||||
"FMOVQ",
|
||||
"FMULD",
|
||||
"FMULS",
|
||||
"FNEGD",
|
||||
"FNEGS",
|
||||
"FSQRTD",
|
||||
"FSQRTS",
|
||||
"FSTPD",
|
||||
"FSTPS",
|
||||
"FSUBD",
|
||||
"FSUBS",
|
||||
"SCVTFD",
|
||||
"SCVTFS",
|
||||
"SCVTFWD",
|
||||
"SCVTFWS",
|
||||
"UCVTFD",
|
||||
"UCVTFS",
|
||||
"UCVTFWD",
|
||||
"UCVTFWS",
|
||||
"WORD",
|
||||
"DWORD",
|
||||
"FCSELS",
|
||||
"FCSELD",
|
||||
"FMAXS",
|
||||
"FMINS",
|
||||
"FMAXD",
|
||||
"FMIND",
|
||||
"FMAXNMS",
|
||||
"FMAXNMD",
|
||||
"FNMULS",
|
||||
"FNMULD",
|
||||
"FRINTNS",
|
||||
"FRINTND",
|
||||
"FRINTPS",
|
||||
"FRINTPD",
|
||||
"FRINTMS",
|
||||
"FRINTMD",
|
||||
"FRINTZS",
|
||||
"FRINTZD",
|
||||
"FRINTAS",
|
||||
"FRINTAD",
|
||||
"FRINTXS",
|
||||
"FRINTXD",
|
||||
"FRINTIS",
|
||||
"FRINTID",
|
||||
"FMADDS",
|
||||
"FMADDD",
|
||||
"FMSUBS",
|
||||
"FMSUBD",
|
||||
"FNMADDS",
|
||||
"FNMADDD",
|
||||
"FNMSUBS",
|
||||
"FNMSUBD",
|
||||
"FMINNMS",
|
||||
"FMINNMD",
|
||||
"FCVTDH",
|
||||
"FCVTHS",
|
||||
"FCVTHD",
|
||||
"FCVTSH",
|
||||
"AESD",
|
||||
"AESE",
|
||||
"AESIMC",
|
||||
"AESMC",
|
||||
"SHA1C",
|
||||
"SHA1H",
|
||||
"SHA1M",
|
||||
"SHA1P",
|
||||
"SHA1SU0",
|
||||
"SHA1SU1",
|
||||
"SHA256H",
|
||||
"SHA256H2",
|
||||
"SHA256SU0",
|
||||
"SHA256SU1",
|
||||
"SHA512H",
|
||||
"SHA512H2",
|
||||
"SHA512SU0",
|
||||
"SHA512SU1",
|
||||
"VADD",
|
||||
"VADDP",
|
||||
"VAND",
|
||||
"VBIF",
|
||||
"VCMEQ",
|
||||
"VCNT",
|
||||
"VEOR",
|
||||
"VMOV",
|
||||
"VLD1",
|
||||
"VLD2",
|
||||
"VLD3",
|
||||
"VLD4",
|
||||
"VLD1R",
|
||||
"VLD2R",
|
||||
"VLD3R",
|
||||
"VLD4R",
|
||||
"VORR",
|
||||
"VREV16",
|
||||
"VREV32",
|
||||
"VREV64",
|
||||
"VST1",
|
||||
"VST2",
|
||||
"VST3",
|
||||
"VST4",
|
||||
"VDUP",
|
||||
"VADDV",
|
||||
"VMOVI",
|
||||
"VUADDLV",
|
||||
"VSUB",
|
||||
"VFMLA",
|
||||
"VFMLS",
|
||||
"VPMULL",
|
||||
"VPMULL2",
|
||||
"VEXT",
|
||||
"VRBIT",
|
||||
"VUSHR",
|
||||
"VUSHLL",
|
||||
"VUSHLL2",
|
||||
"VUXTL",
|
||||
"VUXTL2",
|
||||
"VUZP1",
|
||||
"VUZP2",
|
||||
"VSHL",
|
||||
"VSRI",
|
||||
"VBSL",
|
||||
"VBIT",
|
||||
"VTBL",
|
||||
"VZIP1",
|
||||
"VZIP2",
|
||||
"VCMTST",
|
||||
"LAST",
|
||||
}
|
||||
100
vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/anames7.go
generated
vendored
Normal file
100
vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/anames7.go
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package arm64
|
||||
|
||||
// This order should be strictly consistent to that in a.out.go
|
||||
var cnames7 = []string{
|
||||
"NONE",
|
||||
"REG",
|
||||
"RSP",
|
||||
"FREG",
|
||||
"VREG",
|
||||
"PAIR",
|
||||
"SHIFT",
|
||||
"EXTREG",
|
||||
"SPR",
|
||||
"COND",
|
||||
"ARNG",
|
||||
"ELEM",
|
||||
"LIST",
|
||||
"ZCON",
|
||||
"ABCON0",
|
||||
"ADDCON0",
|
||||
"ABCON",
|
||||
"AMCON",
|
||||
"ADDCON",
|
||||
"MBCON",
|
||||
"MOVCON",
|
||||
"BITCON",
|
||||
"ADDCON2",
|
||||
"LCON",
|
||||
"MOVCON2",
|
||||
"MOVCON3",
|
||||
"VCON",
|
||||
"FCON",
|
||||
"VCONADDR",
|
||||
"AACON",
|
||||
"AACON2",
|
||||
"LACON",
|
||||
"AECON",
|
||||
"SBRA",
|
||||
"LBRA",
|
||||
"ZAUTO",
|
||||
"NSAUTO_8",
|
||||
"NSAUTO_4",
|
||||
"NSAUTO",
|
||||
"NPAUTO",
|
||||
"NAUTO4K",
|
||||
"PSAUTO_8",
|
||||
"PSAUTO_4",
|
||||
"PSAUTO",
|
||||
"PPAUTO",
|
||||
"UAUTO4K_8",
|
||||
"UAUTO4K_4",
|
||||
"UAUTO4K_2",
|
||||
"UAUTO4K",
|
||||
"UAUTO8K_8",
|
||||
"UAUTO8K_4",
|
||||
"UAUTO8K",
|
||||
"UAUTO16K_8",
|
||||
"UAUTO16K",
|
||||
"UAUTO32K",
|
||||
"LAUTO",
|
||||
"SEXT1",
|
||||
"SEXT2",
|
||||
"SEXT4",
|
||||
"SEXT8",
|
||||
"SEXT16",
|
||||
"LEXT",
|
||||
"ZOREG",
|
||||
"NSOREG_8",
|
||||
"NSOREG_4",
|
||||
"NSOREG",
|
||||
"NPOREG",
|
||||
"NOREG4K",
|
||||
"PSOREG_8",
|
||||
"PSOREG_4",
|
||||
"PSOREG",
|
||||
"PPOREG",
|
||||
"UOREG4K_8",
|
||||
"UOREG4K_4",
|
||||
"UOREG4K_2",
|
||||
"UOREG4K",
|
||||
"UOREG8K_8",
|
||||
"UOREG8K_4",
|
||||
"UOREG8K",
|
||||
"UOREG16K_8",
|
||||
"UOREG16K",
|
||||
"UOREG32K",
|
||||
"LOREG",
|
||||
"ADDR",
|
||||
"GOTADDR",
|
||||
"TLS_LE",
|
||||
"TLS_IE",
|
||||
"ROFF",
|
||||
"GOK",
|
||||
"TEXTSIZE",
|
||||
"NCLASS",
|
||||
}
|
||||
7140
vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/asm7.go
generated
vendored
Normal file
7140
vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/asm7.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
249
vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/doc.go
generated
vendored
Normal file
249
vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/doc.go
generated
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package arm64 implements an ARM64 assembler. Go assembly syntax is different from GNU ARM64
|
||||
syntax, but we can still follow the general rules to map between them.
|
||||
|
||||
Instructions mnemonics mapping rules
|
||||
|
||||
1. Most instructions use width suffixes of instruction names to indicate operand width rather than
|
||||
using different register names.
|
||||
|
||||
Examples:
|
||||
ADC R24, R14, R12 <=> adc x12, x24
|
||||
ADDW R26->24, R21, R15 <=> add w15, w21, w26, asr #24
|
||||
FCMPS F2, F3 <=> fcmp s3, s2
|
||||
FCMPD F2, F3 <=> fcmp d3, d2
|
||||
FCVTDH F2, F3 <=> fcvt h3, d2
|
||||
|
||||
2. Go uses .P and .W suffixes to indicate post-increment and pre-increment.
|
||||
|
||||
Examples:
|
||||
MOVD.P -8(R10), R8 <=> ldr x8, [x10],#-8
|
||||
MOVB.W 16(R16), R10 <=> ldrsb x10, [x16,#16]!
|
||||
MOVBU.W 16(R16), R10 <=> ldrb x10, [x16,#16]!
|
||||
|
||||
3. Go uses a series of MOV instructions as load and store.
|
||||
|
||||
64-bit variant ldr, str, stur => MOVD;
|
||||
32-bit variant str, stur, ldrsw => MOVW;
|
||||
32-bit variant ldr => MOVWU;
|
||||
ldrb => MOVBU; ldrh => MOVHU;
|
||||
ldrsb, sturb, strb => MOVB;
|
||||
ldrsh, sturh, strh => MOVH.
|
||||
|
||||
4. Go moves conditions into opcode suffix, like BLT.
|
||||
|
||||
5. Go adds a V prefix for most floating-point and SIMD instructions, except cryptographic extension
|
||||
instructions and floating-point(scalar) instructions.
|
||||
|
||||
Examples:
|
||||
VADD V5.H8, V18.H8, V9.H8 <=> add v9.8h, v18.8h, v5.8h
|
||||
VLD1.P (R6)(R11), [V31.D1] <=> ld1 {v31.1d}, [x6], x11
|
||||
VFMLA V29.S2, V20.S2, V14.S2 <=> fmla v14.2s, v20.2s, v29.2s
|
||||
AESD V22.B16, V19.B16 <=> aesd v19.16b, v22.16b
|
||||
SCVTFWS R3, F16 <=> scvtf s17, w6
|
||||
|
||||
6. Align directive
|
||||
|
||||
Go asm supports the PCALIGN directive, which indicates that the next instruction should be aligned
|
||||
to a specified boundary by padding with NOOP instruction. The alignment value supported on arm64
|
||||
must be a power of 2 and in the range of [8, 2048].
|
||||
|
||||
Examples:
|
||||
PCALIGN $16
|
||||
MOVD $2, R0 // This instruction is aligned with 16 bytes.
|
||||
PCALIGN $1024
|
||||
MOVD $3, R1 // This instruction is aligned with 1024 bytes.
|
||||
|
||||
PCALIGN also changes the function alignment. If a function has one or more PCALIGN directives,
|
||||
its address will be aligned to the same or coarser boundary, which is the maximum of all the
|
||||
alignment values.
|
||||
|
||||
In the following example, the function Add is aligned with 128 bytes.
|
||||
Examples:
|
||||
TEXT ·Add(SB),$40-16
|
||||
MOVD $2, R0
|
||||
PCALIGN $32
|
||||
MOVD $4, R1
|
||||
PCALIGN $128
|
||||
MOVD $8, R2
|
||||
RET
|
||||
|
||||
On arm64, functions in Go are aligned to 16 bytes by default, we can also use PCALGIN to set the
|
||||
function alignment. The functions that need to be aligned are preferably using NOFRAME and NOSPLIT
|
||||
to avoid the impact of the prologues inserted by the assembler, so that the function address will
|
||||
have the same alignment as the first hand-written instruction.
|
||||
|
||||
In the following example, PCALIGN at the entry of the function Add will align its address to 2048 bytes.
|
||||
|
||||
Examples:
|
||||
TEXT ·Add(SB),NOSPLIT|NOFRAME,$0
|
||||
PCALIGN $2048
|
||||
MOVD $1, R0
|
||||
MOVD $1, R1
|
||||
RET
|
||||
|
||||
Special Cases.
|
||||
|
||||
(1) umov is written as VMOV.
|
||||
|
||||
(2) br is renamed JMP, blr is renamed CALL.
|
||||
|
||||
(3) No need to add "W" suffix: LDARB, LDARH, LDAXRB, LDAXRH, LDTRH, LDXRB, LDXRH.
|
||||
|
||||
(4) In Go assembly syntax, NOP is a zero-width pseudo-instruction serves generic purpose, nothing
|
||||
related to real ARM64 instruction. NOOP serves for the hardware nop instruction. NOOP is an alias of
|
||||
HINT $0.
|
||||
|
||||
Examples:
|
||||
VMOV V13.B[1], R20 <=> mov x20, v13.b[1]
|
||||
VMOV V13.H[1], R20 <=> mov w20, v13.h[1]
|
||||
JMP (R3) <=> br x3
|
||||
CALL (R17) <=> blr x17
|
||||
LDAXRB (R19), R16 <=> ldaxrb w16, [x19]
|
||||
NOOP <=> nop
|
||||
|
||||
|
||||
Register mapping rules
|
||||
|
||||
1. All basic register names are written as Rn.
|
||||
|
||||
2. Go uses ZR as the zero register and RSP as the stack pointer.
|
||||
|
||||
3. Bn, Hn, Dn, Sn and Qn instructions are written as Fn in floating-point instructions and as Vn
|
||||
in SIMD instructions.
|
||||
|
||||
|
||||
Argument mapping rules
|
||||
|
||||
1. The operands appear in left-to-right assignment order.
|
||||
|
||||
Go reverses the arguments of most instructions.
|
||||
|
||||
Examples:
|
||||
ADD R11.SXTB<<1, RSP, R25 <=> add x25, sp, w11, sxtb #1
|
||||
VADD V16, V19, V14 <=> add d14, d19, d16
|
||||
|
||||
Special Cases.
|
||||
|
||||
(1) Argument order is the same as in the GNU ARM64 syntax: cbz, cbnz and some store instructions,
|
||||
such as str, stur, strb, sturb, strh, sturh stlr, stlrb. stlrh, st1.
|
||||
|
||||
Examples:
|
||||
MOVD R29, 384(R19) <=> str x29, [x19,#384]
|
||||
MOVB.P R30, 30(R4) <=> strb w30, [x4],#30
|
||||
STLRH R21, (R19) <=> stlrh w21, [x19]
|
||||
|
||||
(2) MADD, MADDW, MSUB, MSUBW, SMADDL, SMSUBL, UMADDL, UMSUBL <Rm>, <Ra>, <Rn>, <Rd>
|
||||
|
||||
Examples:
|
||||
MADD R2, R30, R22, R6 <=> madd x6, x22, x2, x30
|
||||
SMSUBL R10, R3, R17, R27 <=> smsubl x27, w17, w10, x3
|
||||
|
||||
(3) FMADDD, FMADDS, FMSUBD, FMSUBS, FNMADDD, FNMADDS, FNMSUBD, FNMSUBS <Fm>, <Fa>, <Fn>, <Fd>
|
||||
|
||||
Examples:
|
||||
FMADDD F30, F20, F3, F29 <=> fmadd d29, d3, d30, d20
|
||||
FNMSUBS F7, F25, F7, F22 <=> fnmsub s22, s7, s7, s25
|
||||
|
||||
(4) BFI, BFXIL, SBFIZ, SBFX, UBFIZ, UBFX $<lsb>, <Rn>, $<width>, <Rd>
|
||||
|
||||
Examples:
|
||||
BFIW $16, R20, $6, R0 <=> bfi w0, w20, #16, #6
|
||||
UBFIZ $34, R26, $5, R20 <=> ubfiz x20, x26, #34, #5
|
||||
|
||||
(5) FCCMPD, FCCMPS, FCCMPED, FCCMPES <cond>, Fm. Fn, $<nzcv>
|
||||
|
||||
Examples:
|
||||
FCCMPD AL, F8, F26, $0 <=> fccmp d26, d8, #0x0, al
|
||||
FCCMPS VS, F29, F4, $4 <=> fccmp s4, s29, #0x4, vs
|
||||
FCCMPED LE, F20, F5, $13 <=> fccmpe d5, d20, #0xd, le
|
||||
FCCMPES NE, F26, F10, $0 <=> fccmpe s10, s26, #0x0, ne
|
||||
|
||||
(6) CCMN, CCMNW, CCMP, CCMPW <cond>, <Rn>, $<imm>, $<nzcv>
|
||||
|
||||
Examples:
|
||||
CCMP MI, R22, $12, $13 <=> ccmp x22, #0xc, #0xd, mi
|
||||
CCMNW AL, R1, $11, $8 <=> ccmn w1, #0xb, #0x8, al
|
||||
|
||||
(7) CCMN, CCMNW, CCMP, CCMPW <cond>, <Rn>, <Rm>, $<nzcv>
|
||||
|
||||
Examples:
|
||||
CCMN VS, R13, R22, $10 <=> ccmn x13, x22, #0xa, vs
|
||||
CCMPW HS, R19, R14, $11 <=> ccmp w19, w14, #0xb, cs
|
||||
|
||||
(9) CSEL, CSELW, CSNEG, CSNEGW, CSINC, CSINCW <cond>, <Rn>, <Rm>, <Rd> ;
|
||||
FCSELD, FCSELS <cond>, <Fn>, <Fm>, <Fd>
|
||||
|
||||
Examples:
|
||||
CSEL GT, R0, R19, R1 <=> csel x1, x0, x19, gt
|
||||
CSNEGW GT, R7, R17, R8 <=> csneg w8, w7, w17, gt
|
||||
FCSELD EQ, F15, F18, F16 <=> fcsel d16, d15, d18, eq
|
||||
|
||||
(10) TBNZ, TBZ $<imm>, <Rt>, <label>
|
||||
|
||||
|
||||
(11) STLXR, STLXRW, STXR, STXRW, STLXRB, STLXRH, STXRB, STXRH <Rf>, (<Rn|RSP>), <Rs>
|
||||
|
||||
Examples:
|
||||
STLXR ZR, (R15), R16 <=> stlxr w16, xzr, [x15]
|
||||
STXRB R9, (R21), R19 <=> stxrb w19, w9, [x21]
|
||||
|
||||
(12) STLXP, STLXPW, STXP, STXPW (<Rf1>, <Rf2>), (<Rn|RSP>), <Rs>
|
||||
|
||||
Examples:
|
||||
STLXP (R17, R19), (R4), R5 <=> stlxp w5, x17, x19, [x4]
|
||||
STXPW (R30, R25), (R22), R13 <=> stxp w13, w30, w25, [x22]
|
||||
|
||||
2. Expressions for special arguments.
|
||||
|
||||
#<immediate> is written as $<immediate>.
|
||||
|
||||
Optionally-shifted immediate.
|
||||
|
||||
Examples:
|
||||
ADD $(3151<<12), R14, R20 <=> add x20, x14, #0xc4f, lsl #12
|
||||
ADDW $1864, R25, R6 <=> add w6, w25, #0x748
|
||||
|
||||
Optionally-shifted registers are written as <Rm>{<shift><amount>}.
|
||||
The <shift> can be <<(lsl), >>(lsr), ->(asr), @>(ror).
|
||||
|
||||
Examples:
|
||||
ADD R19>>30, R10, R24 <=> add x24, x10, x19, lsr #30
|
||||
ADDW R26->24, R21, R15 <=> add w15, w21, w26, asr #24
|
||||
|
||||
Extended registers are written as <Rm>{.<extend>{<<<amount>}}.
|
||||
<extend> can be UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW or SXTX.
|
||||
|
||||
Examples:
|
||||
ADDS R19.UXTB<<4, R9, R26 <=> adds x26, x9, w19, uxtb #4
|
||||
ADDSW R14.SXTX, R14, R6 <=> adds w6, w14, w14, sxtx
|
||||
|
||||
Memory references: [<Xn|SP>{,#0}] is written as (Rn|RSP), a base register and an immediate
|
||||
offset is written as imm(Rn|RSP), a base register and an offset register is written as (Rn|RSP)(Rm).
|
||||
|
||||
Examples:
|
||||
LDAR (R22), R9 <=> ldar x9, [x22]
|
||||
LDP 28(R17), (R15, R23) <=> ldp x15, x23, [x17,#28]
|
||||
MOVWU (R4)(R12<<2), R8 <=> ldr w8, [x4, x12, lsl #2]
|
||||
MOVD (R7)(R11.UXTW<<3), R25 <=> ldr x25, [x7,w11,uxtw #3]
|
||||
MOVBU (R27)(R23), R14 <=> ldrb w14, [x27,x23]
|
||||
|
||||
Register pairs are written as (Rt1, Rt2).
|
||||
|
||||
Examples:
|
||||
LDP.P -240(R11), (R12, R26) <=> ldp x12, x26, [x11],#-240
|
||||
|
||||
Register with arrangement and register with arrangement and index.
|
||||
|
||||
Examples:
|
||||
VADD V5.H8, V18.H8, V9.H8 <=> add v9.8h, v18.8h, v5.8h
|
||||
VLD1 (R2), [V21.B16] <=> ld1 {v21.16b}, [x2]
|
||||
VST1.P V9.S[1], (R16)(R21) <=> st1 {v9.s}[1], [x16], x28
|
||||
VST1.P [V13.H8, V14.H8, V15.H8], (R3)(R14) <=> st1 {v13.8h-v15.8h}, [x3], x14
|
||||
VST1.P [V14.D1, V15.D1], (R7)(R23) <=> st1 {v14.1d, v15.1d}, [x7], x23
|
||||
*/
|
||||
package arm64
|
||||
288
vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/list7.go
generated
vendored
Normal file
288
vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/list7.go
generated
vendored
Normal file
@@ -0,0 +1,288 @@
|
||||
// cmd/7l/list.c and cmd/7l/sub.c from Vita Nuova.
|
||||
// https://code.google.com/p/ken-cc/source/browse/
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package arm64
|
||||
|
||||
import (
|
||||
"github.com/twitchyliquid64/golang-asm/obj"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var strcond = [16]string{
|
||||
"EQ",
|
||||
"NE",
|
||||
"HS",
|
||||
"LO",
|
||||
"MI",
|
||||
"PL",
|
||||
"VS",
|
||||
"VC",
|
||||
"HI",
|
||||
"LS",
|
||||
"GE",
|
||||
"LT",
|
||||
"GT",
|
||||
"LE",
|
||||
"AL",
|
||||
"NV",
|
||||
}
|
||||
|
||||
func init() {
|
||||
obj.RegisterRegister(obj.RBaseARM64, REG_SPECIAL+1024, rconv)
|
||||
obj.RegisterOpcode(obj.ABaseARM64, Anames)
|
||||
obj.RegisterRegisterList(obj.RegListARM64Lo, obj.RegListARM64Hi, rlconv)
|
||||
obj.RegisterOpSuffix("arm64", obj.CConvARM)
|
||||
}
|
||||
|
||||
func arrange(a int) string {
|
||||
switch a {
|
||||
case ARNG_8B:
|
||||
return "B8"
|
||||
case ARNG_16B:
|
||||
return "B16"
|
||||
case ARNG_4H:
|
||||
return "H4"
|
||||
case ARNG_8H:
|
||||
return "H8"
|
||||
case ARNG_2S:
|
||||
return "S2"
|
||||
case ARNG_4S:
|
||||
return "S4"
|
||||
case ARNG_1D:
|
||||
return "D1"
|
||||
case ARNG_2D:
|
||||
return "D2"
|
||||
case ARNG_B:
|
||||
return "B"
|
||||
case ARNG_H:
|
||||
return "H"
|
||||
case ARNG_S:
|
||||
return "S"
|
||||
case ARNG_D:
|
||||
return "D"
|
||||
case ARNG_1Q:
|
||||
return "Q1"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func rconv(r int) string {
|
||||
ext := (r >> 5) & 7
|
||||
if r == REGG {
|
||||
return "g"
|
||||
}
|
||||
switch {
|
||||
case REG_R0 <= r && r <= REG_R30:
|
||||
return fmt.Sprintf("R%d", r-REG_R0)
|
||||
case r == REG_R31:
|
||||
return "ZR"
|
||||
case REG_F0 <= r && r <= REG_F31:
|
||||
return fmt.Sprintf("F%d", r-REG_F0)
|
||||
case REG_V0 <= r && r <= REG_V31:
|
||||
return fmt.Sprintf("V%d", r-REG_V0)
|
||||
case COND_EQ <= r && r <= COND_NV:
|
||||
return strcond[r-COND_EQ]
|
||||
case r == REGSP:
|
||||
return "RSP"
|
||||
case r == REG_DAIFSet:
|
||||
return "DAIFSet"
|
||||
case r == REG_DAIFClr:
|
||||
return "DAIFClr"
|
||||
case r == REG_PLDL1KEEP:
|
||||
return "PLDL1KEEP"
|
||||
case r == REG_PLDL1STRM:
|
||||
return "PLDL1STRM"
|
||||
case r == REG_PLDL2KEEP:
|
||||
return "PLDL2KEEP"
|
||||
case r == REG_PLDL2STRM:
|
||||
return "PLDL2STRM"
|
||||
case r == REG_PLDL3KEEP:
|
||||
return "PLDL3KEEP"
|
||||
case r == REG_PLDL3STRM:
|
||||
return "PLDL3STRM"
|
||||
case r == REG_PLIL1KEEP:
|
||||
return "PLIL1KEEP"
|
||||
case r == REG_PLIL1STRM:
|
||||
return "PLIL1STRM"
|
||||
case r == REG_PLIL2KEEP:
|
||||
return "PLIL2KEEP"
|
||||
case r == REG_PLIL2STRM:
|
||||
return "PLIL2STRM"
|
||||
case r == REG_PLIL3KEEP:
|
||||
return "PLIL3KEEP"
|
||||
case r == REG_PLIL3STRM:
|
||||
return "PLIL3STRM"
|
||||
case r == REG_PSTL1KEEP:
|
||||
return "PSTL1KEEP"
|
||||
case r == REG_PSTL1STRM:
|
||||
return "PSTL1STRM"
|
||||
case r == REG_PSTL2KEEP:
|
||||
return "PSTL2KEEP"
|
||||
case r == REG_PSTL2STRM:
|
||||
return "PSTL2STRM"
|
||||
case r == REG_PSTL3KEEP:
|
||||
return "PSTL3KEEP"
|
||||
case r == REG_PSTL3STRM:
|
||||
return "PSTL3STRM"
|
||||
case REG_UXTB <= r && r < REG_UXTH:
|
||||
if ext != 0 {
|
||||
return fmt.Sprintf("%s.UXTB<<%d", regname(r), ext)
|
||||
} else {
|
||||
return fmt.Sprintf("%s.UXTB", regname(r))
|
||||
}
|
||||
case REG_UXTH <= r && r < REG_UXTW:
|
||||
if ext != 0 {
|
||||
return fmt.Sprintf("%s.UXTH<<%d", regname(r), ext)
|
||||
} else {
|
||||
return fmt.Sprintf("%s.UXTH", regname(r))
|
||||
}
|
||||
case REG_UXTW <= r && r < REG_UXTX:
|
||||
if ext != 0 {
|
||||
return fmt.Sprintf("%s.UXTW<<%d", regname(r), ext)
|
||||
} else {
|
||||
return fmt.Sprintf("%s.UXTW", regname(r))
|
||||
}
|
||||
case REG_UXTX <= r && r < REG_SXTB:
|
||||
if ext != 0 {
|
||||
return fmt.Sprintf("%s.UXTX<<%d", regname(r), ext)
|
||||
} else {
|
||||
return fmt.Sprintf("%s.UXTX", regname(r))
|
||||
}
|
||||
case REG_SXTB <= r && r < REG_SXTH:
|
||||
if ext != 0 {
|
||||
return fmt.Sprintf("%s.SXTB<<%d", regname(r), ext)
|
||||
} else {
|
||||
return fmt.Sprintf("%s.SXTB", regname(r))
|
||||
}
|
||||
case REG_SXTH <= r && r < REG_SXTW:
|
||||
if ext != 0 {
|
||||
return fmt.Sprintf("%s.SXTH<<%d", regname(r), ext)
|
||||
} else {
|
||||
return fmt.Sprintf("%s.SXTH", regname(r))
|
||||
}
|
||||
case REG_SXTW <= r && r < REG_SXTX:
|
||||
if ext != 0 {
|
||||
return fmt.Sprintf("%s.SXTW<<%d", regname(r), ext)
|
||||
} else {
|
||||
return fmt.Sprintf("%s.SXTW", regname(r))
|
||||
}
|
||||
case REG_SXTX <= r && r < REG_SPECIAL:
|
||||
if ext != 0 {
|
||||
return fmt.Sprintf("%s.SXTX<<%d", regname(r), ext)
|
||||
} else {
|
||||
return fmt.Sprintf("%s.SXTX", regname(r))
|
||||
}
|
||||
// bits 0-4 indicate register, bits 5-7 indicate shift amount, bit 8 equals to 0.
|
||||
case REG_LSL <= r && r < (REG_LSL+1<<8):
|
||||
return fmt.Sprintf("R%d<<%d", r&31, (r>>5)&7)
|
||||
case REG_ARNG <= r && r < REG_ELEM:
|
||||
return fmt.Sprintf("V%d.%s", r&31, arrange((r>>5)&15))
|
||||
case REG_ELEM <= r && r < REG_ELEM_END:
|
||||
return fmt.Sprintf("V%d.%s", r&31, arrange((r>>5)&15))
|
||||
}
|
||||
// Return system register name.
|
||||
name, _, _ := SysRegEnc(int16(r))
|
||||
if name != "" {
|
||||
return name
|
||||
}
|
||||
return fmt.Sprintf("badreg(%d)", r)
|
||||
}
|
||||
|
||||
func DRconv(a int) string {
|
||||
if a >= C_NONE && a <= C_NCLASS {
|
||||
return cnames7[a]
|
||||
}
|
||||
return "C_??"
|
||||
}
|
||||
|
||||
func rlconv(list int64) string {
|
||||
str := ""
|
||||
|
||||
// ARM64 register list follows ARM64 instruction decode schema
|
||||
// | 31 | 30 | ... | 15 - 12 | 11 - 10 | ... |
|
||||
// +----+----+-----+---------+---------+-----+
|
||||
// | | Q | ... | opcode | size | ... |
|
||||
|
||||
firstReg := int(list & 31)
|
||||
opcode := (list >> 12) & 15
|
||||
var regCnt int
|
||||
var t string
|
||||
switch opcode {
|
||||
case 0x7:
|
||||
regCnt = 1
|
||||
case 0xa:
|
||||
regCnt = 2
|
||||
case 0x6:
|
||||
regCnt = 3
|
||||
case 0x2:
|
||||
regCnt = 4
|
||||
default:
|
||||
regCnt = -1
|
||||
}
|
||||
// Q:size
|
||||
arng := ((list>>30)&1)<<2 | (list>>10)&3
|
||||
switch arng {
|
||||
case 0:
|
||||
t = "B8"
|
||||
case 4:
|
||||
t = "B16"
|
||||
case 1:
|
||||
t = "H4"
|
||||
case 5:
|
||||
t = "H8"
|
||||
case 2:
|
||||
t = "S2"
|
||||
case 6:
|
||||
t = "S4"
|
||||
case 3:
|
||||
t = "D1"
|
||||
case 7:
|
||||
t = "D2"
|
||||
}
|
||||
for i := 0; i < regCnt; i++ {
|
||||
if str == "" {
|
||||
str += "["
|
||||
} else {
|
||||
str += ","
|
||||
}
|
||||
str += fmt.Sprintf("V%d.", (firstReg+i)&31)
|
||||
str += t
|
||||
}
|
||||
str += "]"
|
||||
return str
|
||||
}
|
||||
|
||||
func regname(r int) string {
|
||||
if r&31 == 31 {
|
||||
return "ZR"
|
||||
}
|
||||
return fmt.Sprintf("R%d", r&31)
|
||||
}
|
||||
998
vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/obj7.go
generated
vendored
Normal file
998
vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/obj7.go
generated
vendored
Normal file
@@ -0,0 +1,998 @@
|
||||
// cmd/7l/noop.c, cmd/7l/obj.c, cmd/ld/pass.c from Vita Nuova.
|
||||
// https://code.google.com/p/ken-cc/source/browse/
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package arm64
|
||||
|
||||
import (
|
||||
"github.com/twitchyliquid64/golang-asm/obj"
|
||||
"github.com/twitchyliquid64/golang-asm/objabi"
|
||||
"github.com/twitchyliquid64/golang-asm/src"
|
||||
"github.com/twitchyliquid64/golang-asm/sys"
|
||||
"math"
|
||||
)
|
||||
|
||||
var complements = []obj.As{
|
||||
AADD: ASUB,
|
||||
AADDW: ASUBW,
|
||||
ASUB: AADD,
|
||||
ASUBW: AADDW,
|
||||
ACMP: ACMN,
|
||||
ACMPW: ACMNW,
|
||||
ACMN: ACMP,
|
||||
ACMNW: ACMPW,
|
||||
}
|
||||
|
||||
func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
|
||||
// MOV g_stackguard(g), R1
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = AMOVD
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = REGG
|
||||
p.From.Offset = 2 * int64(c.ctxt.Arch.PtrSize) // G.stackguard0
|
||||
if c.cursym.CFunc() {
|
||||
p.From.Offset = 3 * int64(c.ctxt.Arch.PtrSize) // G.stackguard1
|
||||
}
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R1
|
||||
|
||||
// Mark the stack bound check and morestack call async nonpreemptible.
|
||||
// If we get preempted here, when resumed the preemption request is
|
||||
// cleared, but we'll still call morestack, which will double the stack
|
||||
// unnecessarily. See issue #35470.
|
||||
p = c.ctxt.StartUnsafePoint(p, c.newprog)
|
||||
|
||||
q := (*obj.Prog)(nil)
|
||||
if framesize <= objabi.StackSmall {
|
||||
// small stack: SP < stackguard
|
||||
// MOV SP, R2
|
||||
// CMP stackguard, R2
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = AMOVD
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REGSP
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R2
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = ACMP
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_R1
|
||||
p.Reg = REG_R2
|
||||
} else if framesize <= objabi.StackBig {
|
||||
// large stack: SP-framesize < stackguard-StackSmall
|
||||
// SUB $(framesize-StackSmall), SP, R2
|
||||
// CMP stackguard, R2
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = ASUB
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = int64(framesize) - objabi.StackSmall
|
||||
p.Reg = REGSP
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R2
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = ACMP
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_R1
|
||||
p.Reg = REG_R2
|
||||
} else {
|
||||
// Such a large stack we need to protect against wraparound
|
||||
// if SP is close to zero.
|
||||
// SP-stackguard+StackGuard < framesize + (StackGuard-StackSmall)
|
||||
// The +StackGuard on both sides is required to keep the left side positive:
|
||||
// SP is allowed to be slightly below stackguard. See stack.h.
|
||||
// CMP $StackPreempt, R1
|
||||
// BEQ label_of_call_to_morestack
|
||||
// ADD $StackGuard, SP, R2
|
||||
// SUB R1, R2
|
||||
// MOV $(framesize+(StackGuard-StackSmall)), R3
|
||||
// CMP R3, R2
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = ACMP
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = objabi.StackPreempt
|
||||
p.Reg = REG_R1
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
q = p
|
||||
p.As = ABEQ
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = AADD
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = int64(objabi.StackGuard)
|
||||
p.Reg = REGSP
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R2
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = ASUB
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_R1
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R2
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = AMOVD
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = int64(framesize) + (int64(objabi.StackGuard) - objabi.StackSmall)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R3
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = ACMP
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_R3
|
||||
p.Reg = REG_R2
|
||||
}
|
||||
|
||||
// BLS do-morestack
|
||||
bls := obj.Appendp(p, c.newprog)
|
||||
bls.As = ABLS
|
||||
bls.To.Type = obj.TYPE_BRANCH
|
||||
|
||||
end := c.ctxt.EndUnsafePoint(bls, c.newprog, -1)
|
||||
|
||||
var last *obj.Prog
|
||||
for last = c.cursym.Func.Text; last.Link != nil; last = last.Link {
|
||||
}
|
||||
|
||||
// Now we are at the end of the function, but logically
|
||||
// we are still in function prologue. We need to fix the
|
||||
// SP data and PCDATA.
|
||||
spfix := obj.Appendp(last, c.newprog)
|
||||
spfix.As = obj.ANOP
|
||||
spfix.Spadj = -framesize
|
||||
|
||||
pcdata := c.ctxt.EmitEntryStackMap(c.cursym, spfix, c.newprog)
|
||||
pcdata = c.ctxt.StartUnsafePoint(pcdata, c.newprog)
|
||||
|
||||
// MOV LR, R3
|
||||
movlr := obj.Appendp(pcdata, c.newprog)
|
||||
movlr.As = AMOVD
|
||||
movlr.From.Type = obj.TYPE_REG
|
||||
movlr.From.Reg = REGLINK
|
||||
movlr.To.Type = obj.TYPE_REG
|
||||
movlr.To.Reg = REG_R3
|
||||
if q != nil {
|
||||
q.To.SetTarget(movlr)
|
||||
}
|
||||
bls.To.SetTarget(movlr)
|
||||
|
||||
debug := movlr
|
||||
if false {
|
||||
debug = obj.Appendp(debug, c.newprog)
|
||||
debug.As = AMOVD
|
||||
debug.From.Type = obj.TYPE_CONST
|
||||
debug.From.Offset = int64(framesize)
|
||||
debug.To.Type = obj.TYPE_REG
|
||||
debug.To.Reg = REGTMP
|
||||
}
|
||||
|
||||
// BL runtime.morestack(SB)
|
||||
call := obj.Appendp(debug, c.newprog)
|
||||
call.As = ABL
|
||||
call.To.Type = obj.TYPE_BRANCH
|
||||
morestack := "runtime.morestack"
|
||||
switch {
|
||||
case c.cursym.CFunc():
|
||||
morestack = "runtime.morestackc"
|
||||
case !c.cursym.Func.Text.From.Sym.NeedCtxt():
|
||||
morestack = "runtime.morestack_noctxt"
|
||||
}
|
||||
call.To.Sym = c.ctxt.Lookup(morestack)
|
||||
|
||||
pcdata = c.ctxt.EndUnsafePoint(call, c.newprog, -1)
|
||||
|
||||
// B start
|
||||
jmp := obj.Appendp(pcdata, c.newprog)
|
||||
jmp.As = AB
|
||||
jmp.To.Type = obj.TYPE_BRANCH
|
||||
jmp.To.SetTarget(c.cursym.Func.Text.Link)
|
||||
jmp.Spadj = +framesize
|
||||
|
||||
return end
|
||||
}
|
||||
|
||||
func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
||||
c := ctxt7{ctxt: ctxt, newprog: newprog}
|
||||
|
||||
p.From.Class = 0
|
||||
p.To.Class = 0
|
||||
|
||||
// $0 results in C_ZCON, which matches both C_REG and various
|
||||
// C_xCON, however the C_REG cases in asmout don't expect a
|
||||
// constant, so they will use the register fields and assemble
|
||||
// a R0. To prevent that, rewrite $0 as ZR.
|
||||
if p.From.Type == obj.TYPE_CONST && p.From.Offset == 0 {
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REGZERO
|
||||
}
|
||||
if p.To.Type == obj.TYPE_CONST && p.To.Offset == 0 {
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGZERO
|
||||
}
|
||||
|
||||
// Rewrite BR/BL to symbol as TYPE_BRANCH.
|
||||
switch p.As {
|
||||
case AB,
|
||||
ABL,
|
||||
obj.ARET,
|
||||
obj.ADUFFZERO,
|
||||
obj.ADUFFCOPY:
|
||||
if p.To.Sym != nil {
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// Rewrite float constants to values stored in memory.
|
||||
switch p.As {
|
||||
case AFMOVS:
|
||||
if p.From.Type == obj.TYPE_FCONST {
|
||||
f64 := p.From.Val.(float64)
|
||||
f32 := float32(f64)
|
||||
if c.chipfloat7(f64) > 0 {
|
||||
break
|
||||
}
|
||||
if math.Float32bits(f32) == 0 {
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REGZERO
|
||||
break
|
||||
}
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Sym = c.ctxt.Float32Sym(f32)
|
||||
p.From.Name = obj.NAME_EXTERN
|
||||
p.From.Offset = 0
|
||||
}
|
||||
|
||||
case AFMOVD:
|
||||
if p.From.Type == obj.TYPE_FCONST {
|
||||
f64 := p.From.Val.(float64)
|
||||
if c.chipfloat7(f64) > 0 {
|
||||
break
|
||||
}
|
||||
if math.Float64bits(f64) == 0 {
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REGZERO
|
||||
break
|
||||
}
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Sym = c.ctxt.Float64Sym(f64)
|
||||
p.From.Name = obj.NAME_EXTERN
|
||||
p.From.Offset = 0
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
// Rewrite negative immediates as positive immediates with
|
||||
// complementary instruction.
|
||||
switch p.As {
|
||||
case AADD, ASUB, ACMP, ACMN:
|
||||
if p.From.Type == obj.TYPE_CONST && p.From.Offset < 0 && p.From.Offset != -1<<63 {
|
||||
p.From.Offset = -p.From.Offset
|
||||
p.As = complements[p.As]
|
||||
}
|
||||
case AADDW, ASUBW, ACMPW, ACMNW:
|
||||
if p.From.Type == obj.TYPE_CONST && p.From.Offset < 0 && int32(p.From.Offset) != -1<<31 {
|
||||
p.From.Offset = -p.From.Offset
|
||||
p.As = complements[p.As]
|
||||
}
|
||||
}
|
||||
|
||||
// For 32-bit logical instruction with constant,
|
||||
// rewrite the high 32-bit to be a repetition of
|
||||
// the low 32-bit, so that the BITCON test can be
|
||||
// shared for both 32-bit and 64-bit. 32-bit ops
|
||||
// will zero the high 32-bit of the destination
|
||||
// register anyway.
|
||||
if isANDWop(p.As) && p.From.Type == obj.TYPE_CONST {
|
||||
v := p.From.Offset & 0xffffffff
|
||||
p.From.Offset = v | v<<32
|
||||
}
|
||||
|
||||
if c.ctxt.Flag_dynlink {
|
||||
c.rewriteToUseGot(p)
|
||||
}
|
||||
}
|
||||
|
||||
// Rewrite p, if necessary, to access global data via the global offset table.
|
||||
func (c *ctxt7) rewriteToUseGot(p *obj.Prog) {
|
||||
if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
|
||||
// ADUFFxxx $offset
|
||||
// becomes
|
||||
// MOVD runtime.duffxxx@GOT, REGTMP
|
||||
// ADD $offset, REGTMP
|
||||
// CALL REGTMP
|
||||
var sym *obj.LSym
|
||||
if p.As == obj.ADUFFZERO {
|
||||
sym = c.ctxt.Lookup("runtime.duffzero")
|
||||
} else {
|
||||
sym = c.ctxt.Lookup("runtime.duffcopy")
|
||||
}
|
||||
offset := p.To.Offset
|
||||
p.As = AMOVD
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Name = obj.NAME_GOTREF
|
||||
p.From.Sym = sym
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGTMP
|
||||
p.To.Name = obj.NAME_NONE
|
||||
p.To.Offset = 0
|
||||
p.To.Sym = nil
|
||||
p1 := obj.Appendp(p, c.newprog)
|
||||
p1.As = AADD
|
||||
p1.From.Type = obj.TYPE_CONST
|
||||
p1.From.Offset = offset
|
||||
p1.To.Type = obj.TYPE_REG
|
||||
p1.To.Reg = REGTMP
|
||||
p2 := obj.Appendp(p1, c.newprog)
|
||||
p2.As = obj.ACALL
|
||||
p2.To.Type = obj.TYPE_REG
|
||||
p2.To.Reg = REGTMP
|
||||
}
|
||||
|
||||
// We only care about global data: NAME_EXTERN means a global
|
||||
// symbol in the Go sense, and p.Sym.Local is true for a few
|
||||
// internally defined symbols.
|
||||
if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
|
||||
// MOVD $sym, Rx becomes MOVD sym@GOT, Rx
|
||||
// MOVD $sym+<off>, Rx becomes MOVD sym@GOT, Rx; ADD <off>, Rx
|
||||
if p.As != AMOVD {
|
||||
c.ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p)
|
||||
}
|
||||
if p.To.Type != obj.TYPE_REG {
|
||||
c.ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v with -dynlink", p)
|
||||
}
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Name = obj.NAME_GOTREF
|
||||
if p.From.Offset != 0 {
|
||||
q := obj.Appendp(p, c.newprog)
|
||||
q.As = AADD
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = p.From.Offset
|
||||
q.To = p.To
|
||||
p.From.Offset = 0
|
||||
}
|
||||
}
|
||||
if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN {
|
||||
c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
|
||||
}
|
||||
var source *obj.Addr
|
||||
// MOVx sym, Ry becomes MOVD sym@GOT, REGTMP; MOVx (REGTMP), Ry
|
||||
// MOVx Ry, sym becomes MOVD sym@GOT, REGTMP; MOVD Ry, (REGTMP)
|
||||
// An addition may be inserted between the two MOVs if there is an offset.
|
||||
if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
|
||||
if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
|
||||
c.ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
|
||||
}
|
||||
source = &p.From
|
||||
} else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
|
||||
source = &p.To
|
||||
} else {
|
||||
return
|
||||
}
|
||||
if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
|
||||
return
|
||||
}
|
||||
if source.Sym.Type == objabi.STLSBSS {
|
||||
return
|
||||
}
|
||||
if source.Type != obj.TYPE_MEM {
|
||||
c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
|
||||
}
|
||||
p1 := obj.Appendp(p, c.newprog)
|
||||
p2 := obj.Appendp(p1, c.newprog)
|
||||
p1.As = AMOVD
|
||||
p1.From.Type = obj.TYPE_MEM
|
||||
p1.From.Sym = source.Sym
|
||||
p1.From.Name = obj.NAME_GOTREF
|
||||
p1.To.Type = obj.TYPE_REG
|
||||
p1.To.Reg = REGTMP
|
||||
|
||||
p2.As = p.As
|
||||
p2.From = p.From
|
||||
p2.To = p.To
|
||||
if p.From.Name == obj.NAME_EXTERN {
|
||||
p2.From.Reg = REGTMP
|
||||
p2.From.Name = obj.NAME_NONE
|
||||
p2.From.Sym = nil
|
||||
} else if p.To.Name == obj.NAME_EXTERN {
|
||||
p2.To.Reg = REGTMP
|
||||
p2.To.Name = obj.NAME_NONE
|
||||
p2.To.Sym = nil
|
||||
} else {
|
||||
return
|
||||
}
|
||||
obj.Nopout(p)
|
||||
}
|
||||
|
||||
func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
||||
if cursym.Func.Text == nil || cursym.Func.Text.Link == nil {
|
||||
return
|
||||
}
|
||||
|
||||
c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym}
|
||||
|
||||
p := c.cursym.Func.Text
|
||||
textstksiz := p.To.Offset
|
||||
if textstksiz == -8 {
|
||||
// Historical way to mark NOFRAME.
|
||||
p.From.Sym.Set(obj.AttrNoFrame, true)
|
||||
textstksiz = 0
|
||||
}
|
||||
if textstksiz < 0 {
|
||||
c.ctxt.Diag("negative frame size %d - did you mean NOFRAME?", textstksiz)
|
||||
}
|
||||
if p.From.Sym.NoFrame() {
|
||||
if textstksiz != 0 {
|
||||
c.ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", textstksiz)
|
||||
}
|
||||
}
|
||||
|
||||
c.cursym.Func.Args = p.To.Val.(int32)
|
||||
c.cursym.Func.Locals = int32(textstksiz)
|
||||
|
||||
/*
|
||||
* find leaf subroutines
|
||||
*/
|
||||
for p := c.cursym.Func.Text; p != nil; p = p.Link {
|
||||
switch p.As {
|
||||
case obj.ATEXT:
|
||||
p.Mark |= LEAF
|
||||
|
||||
case ABL,
|
||||
obj.ADUFFZERO,
|
||||
obj.ADUFFCOPY:
|
||||
c.cursym.Func.Text.Mark &^= LEAF
|
||||
}
|
||||
}
|
||||
|
||||
var q *obj.Prog
|
||||
var q1 *obj.Prog
|
||||
var retjmp *obj.LSym
|
||||
for p := c.cursym.Func.Text; p != nil; p = p.Link {
|
||||
o := p.As
|
||||
switch o {
|
||||
case obj.ATEXT:
|
||||
c.cursym.Func.Text = p
|
||||
c.autosize = int32(textstksiz)
|
||||
|
||||
if p.Mark&LEAF != 0 && c.autosize == 0 {
|
||||
// A leaf function with no locals has no frame.
|
||||
p.From.Sym.Set(obj.AttrNoFrame, true)
|
||||
}
|
||||
|
||||
if !p.From.Sym.NoFrame() {
|
||||
// If there is a stack frame at all, it includes
|
||||
// space to save the LR.
|
||||
c.autosize += 8
|
||||
}
|
||||
|
||||
if c.autosize != 0 {
|
||||
extrasize := int32(0)
|
||||
if c.autosize%16 == 8 {
|
||||
// Allocate extra 8 bytes on the frame top to save FP
|
||||
extrasize = 8
|
||||
} else if c.autosize&(16-1) == 0 {
|
||||
// Allocate extra 16 bytes to save FP for the old frame whose size is 8 mod 16
|
||||
extrasize = 16
|
||||
} else {
|
||||
c.ctxt.Diag("%v: unaligned frame size %d - must be 16 aligned", p, c.autosize-8)
|
||||
}
|
||||
c.autosize += extrasize
|
||||
c.cursym.Func.Locals += extrasize
|
||||
|
||||
// low 32 bits for autosize
|
||||
// high 32 bits for extrasize
|
||||
p.To.Offset = int64(c.autosize) | int64(extrasize)<<32
|
||||
} else {
|
||||
// NOFRAME
|
||||
p.To.Offset = 0
|
||||
}
|
||||
|
||||
if c.autosize == 0 && c.cursym.Func.Text.Mark&LEAF == 0 {
|
||||
if c.ctxt.Debugvlog {
|
||||
c.ctxt.Logf("save suppressed in: %s\n", c.cursym.Func.Text.From.Sym.Name)
|
||||
}
|
||||
c.cursym.Func.Text.Mark |= LEAF
|
||||
}
|
||||
|
||||
if cursym.Func.Text.Mark&LEAF != 0 {
|
||||
cursym.Set(obj.AttrLeaf, true)
|
||||
if p.From.Sym.NoFrame() {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !p.From.Sym.NoSplit() {
|
||||
p = c.stacksplit(p, c.autosize) // emit split check
|
||||
}
|
||||
|
||||
var prologueEnd *obj.Prog
|
||||
|
||||
aoffset := c.autosize
|
||||
if aoffset > 0xF0 {
|
||||
aoffset = 0xF0
|
||||
}
|
||||
|
||||
// Frame is non-empty. Make sure to save link register, even if
|
||||
// it is a leaf function, so that traceback works.
|
||||
q = p
|
||||
if c.autosize > aoffset {
|
||||
// Frame size is too large for a MOVD.W instruction.
|
||||
// Store link register before decrementing SP, so if a signal comes
|
||||
// during the execution of the function prologue, the traceback
|
||||
// code will not see a half-updated stack frame.
|
||||
// This sequence is not async preemptible, as if we open a frame
|
||||
// at the current SP, it will clobber the saved LR.
|
||||
q = c.ctxt.StartUnsafePoint(q, c.newprog)
|
||||
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.Pos = p.Pos
|
||||
q.As = ASUB
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = int64(c.autosize)
|
||||
q.Reg = REGSP
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REGTMP
|
||||
|
||||
prologueEnd = q
|
||||
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.Pos = p.Pos
|
||||
q.As = AMOVD
|
||||
q.From.Type = obj.TYPE_REG
|
||||
q.From.Reg = REGLINK
|
||||
q.To.Type = obj.TYPE_MEM
|
||||
q.To.Reg = REGTMP
|
||||
|
||||
q1 = obj.Appendp(q, c.newprog)
|
||||
q1.Pos = p.Pos
|
||||
q1.As = AMOVD
|
||||
q1.From.Type = obj.TYPE_REG
|
||||
q1.From.Reg = REGTMP
|
||||
q1.To.Type = obj.TYPE_REG
|
||||
q1.To.Reg = REGSP
|
||||
q1.Spadj = c.autosize
|
||||
|
||||
if c.ctxt.Headtype == objabi.Hdarwin {
|
||||
// iOS does not support SA_ONSTACK. We will run the signal handler
|
||||
// on the G stack. If we write below SP, it may be clobbered by
|
||||
// the signal handler. So we save LR after decrementing SP.
|
||||
q1 = obj.Appendp(q1, c.newprog)
|
||||
q1.Pos = p.Pos
|
||||
q1.As = AMOVD
|
||||
q1.From.Type = obj.TYPE_REG
|
||||
q1.From.Reg = REGLINK
|
||||
q1.To.Type = obj.TYPE_MEM
|
||||
q1.To.Reg = REGSP
|
||||
}
|
||||
|
||||
q1 = c.ctxt.EndUnsafePoint(q1, c.newprog, -1)
|
||||
} else {
|
||||
// small frame, update SP and save LR in a single MOVD.W instruction
|
||||
q1 = obj.Appendp(q, c.newprog)
|
||||
q1.As = AMOVD
|
||||
q1.Pos = p.Pos
|
||||
q1.From.Type = obj.TYPE_REG
|
||||
q1.From.Reg = REGLINK
|
||||
q1.To.Type = obj.TYPE_MEM
|
||||
q1.Scond = C_XPRE
|
||||
q1.To.Offset = int64(-aoffset)
|
||||
q1.To.Reg = REGSP
|
||||
q1.Spadj = aoffset
|
||||
|
||||
prologueEnd = q1
|
||||
}
|
||||
|
||||
prologueEnd.Pos = prologueEnd.Pos.WithXlogue(src.PosPrologueEnd)
|
||||
|
||||
if objabi.Framepointer_enabled {
|
||||
q1 = obj.Appendp(q1, c.newprog)
|
||||
q1.Pos = p.Pos
|
||||
q1.As = AMOVD
|
||||
q1.From.Type = obj.TYPE_REG
|
||||
q1.From.Reg = REGFP
|
||||
q1.To.Type = obj.TYPE_MEM
|
||||
q1.To.Reg = REGSP
|
||||
q1.To.Offset = -8
|
||||
|
||||
q1 = obj.Appendp(q1, c.newprog)
|
||||
q1.Pos = p.Pos
|
||||
q1.As = ASUB
|
||||
q1.From.Type = obj.TYPE_CONST
|
||||
q1.From.Offset = 8
|
||||
q1.Reg = REGSP
|
||||
q1.To.Type = obj.TYPE_REG
|
||||
q1.To.Reg = REGFP
|
||||
}
|
||||
|
||||
if c.cursym.Func.Text.From.Sym.Wrapper() {
|
||||
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
|
||||
//
|
||||
// MOV g_panic(g), R1
|
||||
// CBNZ checkargp
|
||||
// end:
|
||||
// NOP
|
||||
// ... function body ...
|
||||
// checkargp:
|
||||
// MOV panic_argp(R1), R2
|
||||
// ADD $(autosize+8), RSP, R3
|
||||
// CMP R2, R3
|
||||
// BNE end
|
||||
// ADD $8, RSP, R4
|
||||
// MOVD R4, panic_argp(R1)
|
||||
// B end
|
||||
//
|
||||
// The NOP is needed to give the jumps somewhere to land.
|
||||
// It is a liblink NOP, not an ARM64 NOP: it encodes to 0 instruction bytes.
|
||||
q = q1
|
||||
|
||||
// MOV g_panic(g), R1
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = AMOVD
|
||||
q.From.Type = obj.TYPE_MEM
|
||||
q.From.Reg = REGG
|
||||
q.From.Offset = 4 * int64(c.ctxt.Arch.PtrSize) // G.panic
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REG_R1
|
||||
|
||||
// CBNZ R1, checkargp
|
||||
cbnz := obj.Appendp(q, c.newprog)
|
||||
cbnz.As = ACBNZ
|
||||
cbnz.From.Type = obj.TYPE_REG
|
||||
cbnz.From.Reg = REG_R1
|
||||
cbnz.To.Type = obj.TYPE_BRANCH
|
||||
|
||||
// Empty branch target at the top of the function body
|
||||
end := obj.Appendp(cbnz, c.newprog)
|
||||
end.As = obj.ANOP
|
||||
|
||||
// find the end of the function
|
||||
var last *obj.Prog
|
||||
for last = end; last.Link != nil; last = last.Link {
|
||||
}
|
||||
|
||||
// MOV panic_argp(R1), R2
|
||||
mov := obj.Appendp(last, c.newprog)
|
||||
mov.As = AMOVD
|
||||
mov.From.Type = obj.TYPE_MEM
|
||||
mov.From.Reg = REG_R1
|
||||
mov.From.Offset = 0 // Panic.argp
|
||||
mov.To.Type = obj.TYPE_REG
|
||||
mov.To.Reg = REG_R2
|
||||
|
||||
// CBNZ branches to the MOV above
|
||||
cbnz.To.SetTarget(mov)
|
||||
|
||||
// ADD $(autosize+8), SP, R3
|
||||
q = obj.Appendp(mov, c.newprog)
|
||||
q.As = AADD
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = int64(c.autosize) + 8
|
||||
q.Reg = REGSP
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REG_R3
|
||||
|
||||
// CMP R2, R3
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = ACMP
|
||||
q.From.Type = obj.TYPE_REG
|
||||
q.From.Reg = REG_R2
|
||||
q.Reg = REG_R3
|
||||
|
||||
// BNE end
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = ABNE
|
||||
q.To.Type = obj.TYPE_BRANCH
|
||||
q.To.SetTarget(end)
|
||||
|
||||
// ADD $8, SP, R4
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = AADD
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = 8
|
||||
q.Reg = REGSP
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REG_R4
|
||||
|
||||
// MOV R4, panic_argp(R1)
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = AMOVD
|
||||
q.From.Type = obj.TYPE_REG
|
||||
q.From.Reg = REG_R4
|
||||
q.To.Type = obj.TYPE_MEM
|
||||
q.To.Reg = REG_R1
|
||||
q.To.Offset = 0 // Panic.argp
|
||||
|
||||
// B end
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = AB
|
||||
q.To.Type = obj.TYPE_BRANCH
|
||||
q.To.SetTarget(end)
|
||||
}
|
||||
|
||||
case obj.ARET:
|
||||
nocache(p)
|
||||
if p.From.Type == obj.TYPE_CONST {
|
||||
c.ctxt.Diag("using BECOME (%v) is not supported!", p)
|
||||
break
|
||||
}
|
||||
|
||||
retjmp = p.To.Sym
|
||||
p.To = obj.Addr{}
|
||||
if c.cursym.Func.Text.Mark&LEAF != 0 {
|
||||
if c.autosize != 0 {
|
||||
p.As = AADD
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = int64(c.autosize)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGSP
|
||||
p.Spadj = -c.autosize
|
||||
|
||||
if objabi.Framepointer_enabled {
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = ASUB
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = 8
|
||||
p.Reg = REGSP
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGFP
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* want write-back pre-indexed SP+autosize -> SP, loading REGLINK*/
|
||||
|
||||
if objabi.Framepointer_enabled {
|
||||
p.As = AMOVD
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = REGSP
|
||||
p.From.Offset = -8
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGFP
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
}
|
||||
|
||||
aoffset := c.autosize
|
||||
|
||||
if aoffset <= 0xF0 {
|
||||
p.As = AMOVD
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.Scond = C_XPOST
|
||||
p.From.Offset = int64(aoffset)
|
||||
p.From.Reg = REGSP
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGLINK
|
||||
p.Spadj = -aoffset
|
||||
} else {
|
||||
p.As = AMOVD
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Offset = 0
|
||||
p.From.Reg = REGSP
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGLINK
|
||||
|
||||
q = newprog()
|
||||
q.As = AADD
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = int64(aoffset)
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REGSP
|
||||
q.Link = p.Link
|
||||
q.Spadj = int32(-q.From.Offset)
|
||||
q.Pos = p.Pos
|
||||
p.Link = q
|
||||
p = q
|
||||
}
|
||||
}
|
||||
|
||||
if p.As != obj.ARET {
|
||||
q = newprog()
|
||||
q.Pos = p.Pos
|
||||
q.Link = p.Link
|
||||
p.Link = q
|
||||
p = q
|
||||
}
|
||||
|
||||
if retjmp != nil { // retjmp
|
||||
p.As = AB
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
p.To.Sym = retjmp
|
||||
p.Spadj = +c.autosize
|
||||
break
|
||||
}
|
||||
|
||||
p.As = obj.ARET
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Offset = 0
|
||||
p.To.Reg = REGLINK
|
||||
p.Spadj = +c.autosize
|
||||
|
||||
case AADD, ASUB:
|
||||
if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
|
||||
if p.As == AADD {
|
||||
p.Spadj = int32(-p.From.Offset)
|
||||
} else {
|
||||
p.Spadj = int32(+p.From.Offset)
|
||||
}
|
||||
}
|
||||
|
||||
case obj.AGETCALLERPC:
|
||||
if cursym.Leaf() {
|
||||
/* MOVD LR, Rd */
|
||||
p.As = AMOVD
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REGLINK
|
||||
} else {
|
||||
/* MOVD (RSP), Rd */
|
||||
p.As = AMOVD
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = REGSP
|
||||
}
|
||||
|
||||
case obj.ADUFFCOPY:
|
||||
if objabi.Framepointer_enabled {
|
||||
// ADR ret_addr, R27
|
||||
// STP (FP, R27), -24(SP)
|
||||
// SUB 24, SP, FP
|
||||
// DUFFCOPY
|
||||
// ret_addr:
|
||||
// SUB 8, SP, FP
|
||||
|
||||
q1 := p
|
||||
// copy DUFFCOPY from q1 to q4
|
||||
q4 := obj.Appendp(p, c.newprog)
|
||||
q4.Pos = p.Pos
|
||||
q4.As = obj.ADUFFCOPY
|
||||
q4.To = p.To
|
||||
|
||||
q1.As = AADR
|
||||
q1.From.Type = obj.TYPE_BRANCH
|
||||
q1.To.Type = obj.TYPE_REG
|
||||
q1.To.Reg = REG_R27
|
||||
|
||||
q2 := obj.Appendp(q1, c.newprog)
|
||||
q2.Pos = p.Pos
|
||||
q2.As = ASTP
|
||||
q2.From.Type = obj.TYPE_REGREG
|
||||
q2.From.Reg = REGFP
|
||||
q2.From.Offset = int64(REG_R27)
|
||||
q2.To.Type = obj.TYPE_MEM
|
||||
q2.To.Reg = REGSP
|
||||
q2.To.Offset = -24
|
||||
|
||||
// maintaine FP for DUFFCOPY
|
||||
q3 := obj.Appendp(q2, c.newprog)
|
||||
q3.Pos = p.Pos
|
||||
q3.As = ASUB
|
||||
q3.From.Type = obj.TYPE_CONST
|
||||
q3.From.Offset = 24
|
||||
q3.Reg = REGSP
|
||||
q3.To.Type = obj.TYPE_REG
|
||||
q3.To.Reg = REGFP
|
||||
|
||||
q5 := obj.Appendp(q4, c.newprog)
|
||||
q5.Pos = p.Pos
|
||||
q5.As = ASUB
|
||||
q5.From.Type = obj.TYPE_CONST
|
||||
q5.From.Offset = 8
|
||||
q5.Reg = REGSP
|
||||
q5.To.Type = obj.TYPE_REG
|
||||
q5.To.Reg = REGFP
|
||||
q1.From.SetTarget(q5)
|
||||
p = q5
|
||||
}
|
||||
|
||||
case obj.ADUFFZERO:
|
||||
if objabi.Framepointer_enabled {
|
||||
// ADR ret_addr, R27
|
||||
// STP (FP, R27), -24(SP)
|
||||
// SUB 24, SP, FP
|
||||
// DUFFZERO
|
||||
// ret_addr:
|
||||
// SUB 8, SP, FP
|
||||
|
||||
q1 := p
|
||||
// copy DUFFZERO from q1 to q4
|
||||
q4 := obj.Appendp(p, c.newprog)
|
||||
q4.Pos = p.Pos
|
||||
q4.As = obj.ADUFFZERO
|
||||
q4.To = p.To
|
||||
|
||||
q1.As = AADR
|
||||
q1.From.Type = obj.TYPE_BRANCH
|
||||
q1.To.Type = obj.TYPE_REG
|
||||
q1.To.Reg = REG_R27
|
||||
|
||||
q2 := obj.Appendp(q1, c.newprog)
|
||||
q2.Pos = p.Pos
|
||||
q2.As = ASTP
|
||||
q2.From.Type = obj.TYPE_REGREG
|
||||
q2.From.Reg = REGFP
|
||||
q2.From.Offset = int64(REG_R27)
|
||||
q2.To.Type = obj.TYPE_MEM
|
||||
q2.To.Reg = REGSP
|
||||
q2.To.Offset = -24
|
||||
|
||||
// maintaine FP for DUFFZERO
|
||||
q3 := obj.Appendp(q2, c.newprog)
|
||||
q3.Pos = p.Pos
|
||||
q3.As = ASUB
|
||||
q3.From.Type = obj.TYPE_CONST
|
||||
q3.From.Offset = 24
|
||||
q3.Reg = REGSP
|
||||
q3.To.Type = obj.TYPE_REG
|
||||
q3.To.Reg = REGFP
|
||||
|
||||
q5 := obj.Appendp(q4, c.newprog)
|
||||
q5.Pos = p.Pos
|
||||
q5.As = ASUB
|
||||
q5.From.Type = obj.TYPE_CONST
|
||||
q5.From.Offset = 8
|
||||
q5.Reg = REGSP
|
||||
q5.To.Type = obj.TYPE_REG
|
||||
q5.To.Reg = REGFP
|
||||
q1.From.SetTarget(q5)
|
||||
p = q5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func nocache(p *obj.Prog) {
|
||||
p.Optab = 0
|
||||
p.From.Class = 0
|
||||
p.To.Class = 0
|
||||
}
|
||||
|
||||
var unaryDst = map[obj.As]bool{
|
||||
AWORD: true,
|
||||
ADWORD: true,
|
||||
ABL: true,
|
||||
AB: true,
|
||||
ACLREX: true,
|
||||
}
|
||||
|
||||
var Linkarm64 = obj.LinkArch{
|
||||
Arch: sys.ArchARM64,
|
||||
Init: buildop,
|
||||
Preprocess: preprocess,
|
||||
Assemble: span7,
|
||||
Progedit: progedit,
|
||||
UnaryDst: unaryDst,
|
||||
DWARFRegisters: ARM64DWARFRegisters,
|
||||
}
|
||||
895
vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/sysRegEnc.go
generated
vendored
Normal file
895
vendor/github.com/twitchyliquid64/golang-asm/obj/arm64/sysRegEnc.go
generated
vendored
Normal file
@@ -0,0 +1,895 @@
|
||||
// Code generated by arm64gen -i ./files -o sysRegEnc.go. DO NOT EDIT.
|
||||
|
||||
package arm64
|
||||
|
||||
const (
|
||||
SYSREG_BEGIN = REG_SPECIAL + iota
|
||||
REG_ACTLR_EL1
|
||||
REG_AFSR0_EL1
|
||||
REG_AFSR1_EL1
|
||||
REG_AIDR_EL1
|
||||
REG_AMAIR_EL1
|
||||
REG_AMCFGR_EL0
|
||||
REG_AMCGCR_EL0
|
||||
REG_AMCNTENCLR0_EL0
|
||||
REG_AMCNTENCLR1_EL0
|
||||
REG_AMCNTENSET0_EL0
|
||||
REG_AMCNTENSET1_EL0
|
||||
REG_AMCR_EL0
|
||||
REG_AMEVCNTR00_EL0
|
||||
REG_AMEVCNTR01_EL0
|
||||
REG_AMEVCNTR02_EL0
|
||||
REG_AMEVCNTR03_EL0
|
||||
REG_AMEVCNTR04_EL0
|
||||
REG_AMEVCNTR05_EL0
|
||||
REG_AMEVCNTR06_EL0
|
||||
REG_AMEVCNTR07_EL0
|
||||
REG_AMEVCNTR08_EL0
|
||||
REG_AMEVCNTR09_EL0
|
||||
REG_AMEVCNTR010_EL0
|
||||
REG_AMEVCNTR011_EL0
|
||||
REG_AMEVCNTR012_EL0
|
||||
REG_AMEVCNTR013_EL0
|
||||
REG_AMEVCNTR014_EL0
|
||||
REG_AMEVCNTR015_EL0
|
||||
REG_AMEVCNTR10_EL0
|
||||
REG_AMEVCNTR11_EL0
|
||||
REG_AMEVCNTR12_EL0
|
||||
REG_AMEVCNTR13_EL0
|
||||
REG_AMEVCNTR14_EL0
|
||||
REG_AMEVCNTR15_EL0
|
||||
REG_AMEVCNTR16_EL0
|
||||
REG_AMEVCNTR17_EL0
|
||||
REG_AMEVCNTR18_EL0
|
||||
REG_AMEVCNTR19_EL0
|
||||
REG_AMEVCNTR110_EL0
|
||||
REG_AMEVCNTR111_EL0
|
||||
REG_AMEVCNTR112_EL0
|
||||
REG_AMEVCNTR113_EL0
|
||||
REG_AMEVCNTR114_EL0
|
||||
REG_AMEVCNTR115_EL0
|
||||
REG_AMEVTYPER00_EL0
|
||||
REG_AMEVTYPER01_EL0
|
||||
REG_AMEVTYPER02_EL0
|
||||
REG_AMEVTYPER03_EL0
|
||||
REG_AMEVTYPER04_EL0
|
||||
REG_AMEVTYPER05_EL0
|
||||
REG_AMEVTYPER06_EL0
|
||||
REG_AMEVTYPER07_EL0
|
||||
REG_AMEVTYPER08_EL0
|
||||
REG_AMEVTYPER09_EL0
|
||||
REG_AMEVTYPER010_EL0
|
||||
REG_AMEVTYPER011_EL0
|
||||
REG_AMEVTYPER012_EL0
|
||||
REG_AMEVTYPER013_EL0
|
||||
REG_AMEVTYPER014_EL0
|
||||
REG_AMEVTYPER015_EL0
|
||||
REG_AMEVTYPER10_EL0
|
||||
REG_AMEVTYPER11_EL0
|
||||
REG_AMEVTYPER12_EL0
|
||||
REG_AMEVTYPER13_EL0
|
||||
REG_AMEVTYPER14_EL0
|
||||
REG_AMEVTYPER15_EL0
|
||||
REG_AMEVTYPER16_EL0
|
||||
REG_AMEVTYPER17_EL0
|
||||
REG_AMEVTYPER18_EL0
|
||||
REG_AMEVTYPER19_EL0
|
||||
REG_AMEVTYPER110_EL0
|
||||
REG_AMEVTYPER111_EL0
|
||||
REG_AMEVTYPER112_EL0
|
||||
REG_AMEVTYPER113_EL0
|
||||
REG_AMEVTYPER114_EL0
|
||||
REG_AMEVTYPER115_EL0
|
||||
REG_AMUSERENR_EL0
|
||||
REG_APDAKeyHi_EL1
|
||||
REG_APDAKeyLo_EL1
|
||||
REG_APDBKeyHi_EL1
|
||||
REG_APDBKeyLo_EL1
|
||||
REG_APGAKeyHi_EL1
|
||||
REG_APGAKeyLo_EL1
|
||||
REG_APIAKeyHi_EL1
|
||||
REG_APIAKeyLo_EL1
|
||||
REG_APIBKeyHi_EL1
|
||||
REG_APIBKeyLo_EL1
|
||||
REG_CCSIDR2_EL1
|
||||
REG_CCSIDR_EL1
|
||||
REG_CLIDR_EL1
|
||||
REG_CNTFRQ_EL0
|
||||
REG_CNTKCTL_EL1
|
||||
REG_CNTP_CTL_EL0
|
||||
REG_CNTP_CVAL_EL0
|
||||
REG_CNTP_TVAL_EL0
|
||||
REG_CNTPCT_EL0
|
||||
REG_CNTPS_CTL_EL1
|
||||
REG_CNTPS_CVAL_EL1
|
||||
REG_CNTPS_TVAL_EL1
|
||||
REG_CNTV_CTL_EL0
|
||||
REG_CNTV_CVAL_EL0
|
||||
REG_CNTV_TVAL_EL0
|
||||
REG_CNTVCT_EL0
|
||||
REG_CONTEXTIDR_EL1
|
||||
REG_CPACR_EL1
|
||||
REG_CSSELR_EL1
|
||||
REG_CTR_EL0
|
||||
REG_CurrentEL
|
||||
REG_DAIF
|
||||
REG_DBGAUTHSTATUS_EL1
|
||||
REG_DBGBCR0_EL1
|
||||
REG_DBGBCR1_EL1
|
||||
REG_DBGBCR2_EL1
|
||||
REG_DBGBCR3_EL1
|
||||
REG_DBGBCR4_EL1
|
||||
REG_DBGBCR5_EL1
|
||||
REG_DBGBCR6_EL1
|
||||
REG_DBGBCR7_EL1
|
||||
REG_DBGBCR8_EL1
|
||||
REG_DBGBCR9_EL1
|
||||
REG_DBGBCR10_EL1
|
||||
REG_DBGBCR11_EL1
|
||||
REG_DBGBCR12_EL1
|
||||
REG_DBGBCR13_EL1
|
||||
REG_DBGBCR14_EL1
|
||||
REG_DBGBCR15_EL1
|
||||
REG_DBGBVR0_EL1
|
||||
REG_DBGBVR1_EL1
|
||||
REG_DBGBVR2_EL1
|
||||
REG_DBGBVR3_EL1
|
||||
REG_DBGBVR4_EL1
|
||||
REG_DBGBVR5_EL1
|
||||
REG_DBGBVR6_EL1
|
||||
REG_DBGBVR7_EL1
|
||||
REG_DBGBVR8_EL1
|
||||
REG_DBGBVR9_EL1
|
||||
REG_DBGBVR10_EL1
|
||||
REG_DBGBVR11_EL1
|
||||
REG_DBGBVR12_EL1
|
||||
REG_DBGBVR13_EL1
|
||||
REG_DBGBVR14_EL1
|
||||
REG_DBGBVR15_EL1
|
||||
REG_DBGCLAIMCLR_EL1
|
||||
REG_DBGCLAIMSET_EL1
|
||||
REG_DBGDTR_EL0
|
||||
REG_DBGDTRRX_EL0
|
||||
REG_DBGDTRTX_EL0
|
||||
REG_DBGPRCR_EL1
|
||||
REG_DBGWCR0_EL1
|
||||
REG_DBGWCR1_EL1
|
||||
REG_DBGWCR2_EL1
|
||||
REG_DBGWCR3_EL1
|
||||
REG_DBGWCR4_EL1
|
||||
REG_DBGWCR5_EL1
|
||||
REG_DBGWCR6_EL1
|
||||
REG_DBGWCR7_EL1
|
||||
REG_DBGWCR8_EL1
|
||||
REG_DBGWCR9_EL1
|
||||
REG_DBGWCR10_EL1
|
||||
REG_DBGWCR11_EL1
|
||||
REG_DBGWCR12_EL1
|
||||
REG_DBGWCR13_EL1
|
||||
REG_DBGWCR14_EL1
|
||||
REG_DBGWCR15_EL1
|
||||
REG_DBGWVR0_EL1
|
||||
REG_DBGWVR1_EL1
|
||||
REG_DBGWVR2_EL1
|
||||
REG_DBGWVR3_EL1
|
||||
REG_DBGWVR4_EL1
|
||||
REG_DBGWVR5_EL1
|
||||
REG_DBGWVR6_EL1
|
||||
REG_DBGWVR7_EL1
|
||||
REG_DBGWVR8_EL1
|
||||
REG_DBGWVR9_EL1
|
||||
REG_DBGWVR10_EL1
|
||||
REG_DBGWVR11_EL1
|
||||
REG_DBGWVR12_EL1
|
||||
REG_DBGWVR13_EL1
|
||||
REG_DBGWVR14_EL1
|
||||
REG_DBGWVR15_EL1
|
||||
REG_DCZID_EL0
|
||||
REG_DISR_EL1
|
||||
REG_DIT
|
||||
REG_DLR_EL0
|
||||
REG_DSPSR_EL0
|
||||
REG_ELR_EL1
|
||||
REG_ERRIDR_EL1
|
||||
REG_ERRSELR_EL1
|
||||
REG_ERXADDR_EL1
|
||||
REG_ERXCTLR_EL1
|
||||
REG_ERXFR_EL1
|
||||
REG_ERXMISC0_EL1
|
||||
REG_ERXMISC1_EL1
|
||||
REG_ERXMISC2_EL1
|
||||
REG_ERXMISC3_EL1
|
||||
REG_ERXPFGCDN_EL1
|
||||
REG_ERXPFGCTL_EL1
|
||||
REG_ERXPFGF_EL1
|
||||
REG_ERXSTATUS_EL1
|
||||
REG_ESR_EL1
|
||||
REG_FAR_EL1
|
||||
REG_FPCR
|
||||
REG_FPSR
|
||||
REG_GCR_EL1
|
||||
REG_GMID_EL1
|
||||
REG_ICC_AP0R0_EL1
|
||||
REG_ICC_AP0R1_EL1
|
||||
REG_ICC_AP0R2_EL1
|
||||
REG_ICC_AP0R3_EL1
|
||||
REG_ICC_AP1R0_EL1
|
||||
REG_ICC_AP1R1_EL1
|
||||
REG_ICC_AP1R2_EL1
|
||||
REG_ICC_AP1R3_EL1
|
||||
REG_ICC_ASGI1R_EL1
|
||||
REG_ICC_BPR0_EL1
|
||||
REG_ICC_BPR1_EL1
|
||||
REG_ICC_CTLR_EL1
|
||||
REG_ICC_DIR_EL1
|
||||
REG_ICC_EOIR0_EL1
|
||||
REG_ICC_EOIR1_EL1
|
||||
REG_ICC_HPPIR0_EL1
|
||||
REG_ICC_HPPIR1_EL1
|
||||
REG_ICC_IAR0_EL1
|
||||
REG_ICC_IAR1_EL1
|
||||
REG_ICC_IGRPEN0_EL1
|
||||
REG_ICC_IGRPEN1_EL1
|
||||
REG_ICC_PMR_EL1
|
||||
REG_ICC_RPR_EL1
|
||||
REG_ICC_SGI0R_EL1
|
||||
REG_ICC_SGI1R_EL1
|
||||
REG_ICC_SRE_EL1
|
||||
REG_ICV_AP0R0_EL1
|
||||
REG_ICV_AP0R1_EL1
|
||||
REG_ICV_AP0R2_EL1
|
||||
REG_ICV_AP0R3_EL1
|
||||
REG_ICV_AP1R0_EL1
|
||||
REG_ICV_AP1R1_EL1
|
||||
REG_ICV_AP1R2_EL1
|
||||
REG_ICV_AP1R3_EL1
|
||||
REG_ICV_BPR0_EL1
|
||||
REG_ICV_BPR1_EL1
|
||||
REG_ICV_CTLR_EL1
|
||||
REG_ICV_DIR_EL1
|
||||
REG_ICV_EOIR0_EL1
|
||||
REG_ICV_EOIR1_EL1
|
||||
REG_ICV_HPPIR0_EL1
|
||||
REG_ICV_HPPIR1_EL1
|
||||
REG_ICV_IAR0_EL1
|
||||
REG_ICV_IAR1_EL1
|
||||
REG_ICV_IGRPEN0_EL1
|
||||
REG_ICV_IGRPEN1_EL1
|
||||
REG_ICV_PMR_EL1
|
||||
REG_ICV_RPR_EL1
|
||||
REG_ID_AA64AFR0_EL1
|
||||
REG_ID_AA64AFR1_EL1
|
||||
REG_ID_AA64DFR0_EL1
|
||||
REG_ID_AA64DFR1_EL1
|
||||
REG_ID_AA64ISAR0_EL1
|
||||
REG_ID_AA64ISAR1_EL1
|
||||
REG_ID_AA64MMFR0_EL1
|
||||
REG_ID_AA64MMFR1_EL1
|
||||
REG_ID_AA64MMFR2_EL1
|
||||
REG_ID_AA64PFR0_EL1
|
||||
REG_ID_AA64PFR1_EL1
|
||||
REG_ID_AA64ZFR0_EL1
|
||||
REG_ID_AFR0_EL1
|
||||
REG_ID_DFR0_EL1
|
||||
REG_ID_ISAR0_EL1
|
||||
REG_ID_ISAR1_EL1
|
||||
REG_ID_ISAR2_EL1
|
||||
REG_ID_ISAR3_EL1
|
||||
REG_ID_ISAR4_EL1
|
||||
REG_ID_ISAR5_EL1
|
||||
REG_ID_ISAR6_EL1
|
||||
REG_ID_MMFR0_EL1
|
||||
REG_ID_MMFR1_EL1
|
||||
REG_ID_MMFR2_EL1
|
||||
REG_ID_MMFR3_EL1
|
||||
REG_ID_MMFR4_EL1
|
||||
REG_ID_PFR0_EL1
|
||||
REG_ID_PFR1_EL1
|
||||
REG_ID_PFR2_EL1
|
||||
REG_ISR_EL1
|
||||
REG_LORC_EL1
|
||||
REG_LOREA_EL1
|
||||
REG_LORID_EL1
|
||||
REG_LORN_EL1
|
||||
REG_LORSA_EL1
|
||||
REG_MAIR_EL1
|
||||
REG_MDCCINT_EL1
|
||||
REG_MDCCSR_EL0
|
||||
REG_MDRAR_EL1
|
||||
REG_MDSCR_EL1
|
||||
REG_MIDR_EL1
|
||||
REG_MPAM0_EL1
|
||||
REG_MPAM1_EL1
|
||||
REG_MPAMIDR_EL1
|
||||
REG_MPIDR_EL1
|
||||
REG_MVFR0_EL1
|
||||
REG_MVFR1_EL1
|
||||
REG_MVFR2_EL1
|
||||
REG_NZCV
|
||||
REG_OSDLR_EL1
|
||||
REG_OSDTRRX_EL1
|
||||
REG_OSDTRTX_EL1
|
||||
REG_OSECCR_EL1
|
||||
REG_OSLAR_EL1
|
||||
REG_OSLSR_EL1
|
||||
REG_PAN
|
||||
REG_PAR_EL1
|
||||
REG_PMBIDR_EL1
|
||||
REG_PMBLIMITR_EL1
|
||||
REG_PMBPTR_EL1
|
||||
REG_PMBSR_EL1
|
||||
REG_PMCCFILTR_EL0
|
||||
REG_PMCCNTR_EL0
|
||||
REG_PMCEID0_EL0
|
||||
REG_PMCEID1_EL0
|
||||
REG_PMCNTENCLR_EL0
|
||||
REG_PMCNTENSET_EL0
|
||||
REG_PMCR_EL0
|
||||
REG_PMEVCNTR0_EL0
|
||||
REG_PMEVCNTR1_EL0
|
||||
REG_PMEVCNTR2_EL0
|
||||
REG_PMEVCNTR3_EL0
|
||||
REG_PMEVCNTR4_EL0
|
||||
REG_PMEVCNTR5_EL0
|
||||
REG_PMEVCNTR6_EL0
|
||||
REG_PMEVCNTR7_EL0
|
||||
REG_PMEVCNTR8_EL0
|
||||
REG_PMEVCNTR9_EL0
|
||||
REG_PMEVCNTR10_EL0
|
||||
REG_PMEVCNTR11_EL0
|
||||
REG_PMEVCNTR12_EL0
|
||||
REG_PMEVCNTR13_EL0
|
||||
REG_PMEVCNTR14_EL0
|
||||
REG_PMEVCNTR15_EL0
|
||||
REG_PMEVCNTR16_EL0
|
||||
REG_PMEVCNTR17_EL0
|
||||
REG_PMEVCNTR18_EL0
|
||||
REG_PMEVCNTR19_EL0
|
||||
REG_PMEVCNTR20_EL0
|
||||
REG_PMEVCNTR21_EL0
|
||||
REG_PMEVCNTR22_EL0
|
||||
REG_PMEVCNTR23_EL0
|
||||
REG_PMEVCNTR24_EL0
|
||||
REG_PMEVCNTR25_EL0
|
||||
REG_PMEVCNTR26_EL0
|
||||
REG_PMEVCNTR27_EL0
|
||||
REG_PMEVCNTR28_EL0
|
||||
REG_PMEVCNTR29_EL0
|
||||
REG_PMEVCNTR30_EL0
|
||||
REG_PMEVTYPER0_EL0
|
||||
REG_PMEVTYPER1_EL0
|
||||
REG_PMEVTYPER2_EL0
|
||||
REG_PMEVTYPER3_EL0
|
||||
REG_PMEVTYPER4_EL0
|
||||
REG_PMEVTYPER5_EL0
|
||||
REG_PMEVTYPER6_EL0
|
||||
REG_PMEVTYPER7_EL0
|
||||
REG_PMEVTYPER8_EL0
|
||||
REG_PMEVTYPER9_EL0
|
||||
REG_PMEVTYPER10_EL0
|
||||
REG_PMEVTYPER11_EL0
|
||||
REG_PMEVTYPER12_EL0
|
||||
REG_PMEVTYPER13_EL0
|
||||
REG_PMEVTYPER14_EL0
|
||||
REG_PMEVTYPER15_EL0
|
||||
REG_PMEVTYPER16_EL0
|
||||
REG_PMEVTYPER17_EL0
|
||||
REG_PMEVTYPER18_EL0
|
||||
REG_PMEVTYPER19_EL0
|
||||
REG_PMEVTYPER20_EL0
|
||||
REG_PMEVTYPER21_EL0
|
||||
REG_PMEVTYPER22_EL0
|
||||
REG_PMEVTYPER23_EL0
|
||||
REG_PMEVTYPER24_EL0
|
||||
REG_PMEVTYPER25_EL0
|
||||
REG_PMEVTYPER26_EL0
|
||||
REG_PMEVTYPER27_EL0
|
||||
REG_PMEVTYPER28_EL0
|
||||
REG_PMEVTYPER29_EL0
|
||||
REG_PMEVTYPER30_EL0
|
||||
REG_PMINTENCLR_EL1
|
||||
REG_PMINTENSET_EL1
|
||||
REG_PMMIR_EL1
|
||||
REG_PMOVSCLR_EL0
|
||||
REG_PMOVSSET_EL0
|
||||
REG_PMSCR_EL1
|
||||
REG_PMSELR_EL0
|
||||
REG_PMSEVFR_EL1
|
||||
REG_PMSFCR_EL1
|
||||
REG_PMSICR_EL1
|
||||
REG_PMSIDR_EL1
|
||||
REG_PMSIRR_EL1
|
||||
REG_PMSLATFR_EL1
|
||||
REG_PMSWINC_EL0
|
||||
REG_PMUSERENR_EL0
|
||||
REG_PMXEVCNTR_EL0
|
||||
REG_PMXEVTYPER_EL0
|
||||
REG_REVIDR_EL1
|
||||
REG_RGSR_EL1
|
||||
REG_RMR_EL1
|
||||
REG_RNDR
|
||||
REG_RNDRRS
|
||||
REG_RVBAR_EL1
|
||||
REG_SCTLR_EL1
|
||||
REG_SCXTNUM_EL0
|
||||
REG_SCXTNUM_EL1
|
||||
REG_SP_EL0
|
||||
REG_SP_EL1
|
||||
REG_SPSel
|
||||
REG_SPSR_abt
|
||||
REG_SPSR_EL1
|
||||
REG_SPSR_fiq
|
||||
REG_SPSR_irq
|
||||
REG_SPSR_und
|
||||
REG_SSBS
|
||||
REG_TCO
|
||||
REG_TCR_EL1
|
||||
REG_TFSR_EL1
|
||||
REG_TFSRE0_EL1
|
||||
REG_TPIDR_EL0
|
||||
REG_TPIDR_EL1
|
||||
REG_TPIDRRO_EL0
|
||||
REG_TRFCR_EL1
|
||||
REG_TTBR0_EL1
|
||||
REG_TTBR1_EL1
|
||||
REG_UAO
|
||||
REG_VBAR_EL1
|
||||
REG_ZCR_EL1
|
||||
SYSREG_END
|
||||
)
|
||||
|
||||
const (
|
||||
SR_READ = 1 << iota
|
||||
SR_WRITE
|
||||
)
|
||||
|
||||
var SystemReg = []struct {
|
||||
Name string
|
||||
Reg int16
|
||||
Enc uint32
|
||||
// AccessFlags is the readable and writeable property of system register.
|
||||
AccessFlags uint8
|
||||
}{
|
||||
{"ACTLR_EL1", REG_ACTLR_EL1, 0x181020, SR_READ | SR_WRITE},
|
||||
{"AFSR0_EL1", REG_AFSR0_EL1, 0x185100, SR_READ | SR_WRITE},
|
||||
{"AFSR1_EL1", REG_AFSR1_EL1, 0x185120, SR_READ | SR_WRITE},
|
||||
{"AIDR_EL1", REG_AIDR_EL1, 0x1900e0, SR_READ},
|
||||
{"AMAIR_EL1", REG_AMAIR_EL1, 0x18a300, SR_READ | SR_WRITE},
|
||||
{"AMCFGR_EL0", REG_AMCFGR_EL0, 0x1bd220, SR_READ},
|
||||
{"AMCGCR_EL0", REG_AMCGCR_EL0, 0x1bd240, SR_READ},
|
||||
{"AMCNTENCLR0_EL0", REG_AMCNTENCLR0_EL0, 0x1bd280, SR_READ | SR_WRITE},
|
||||
{"AMCNTENCLR1_EL0", REG_AMCNTENCLR1_EL0, 0x1bd300, SR_READ | SR_WRITE},
|
||||
{"AMCNTENSET0_EL0", REG_AMCNTENSET0_EL0, 0x1bd2a0, SR_READ | SR_WRITE},
|
||||
{"AMCNTENSET1_EL0", REG_AMCNTENSET1_EL0, 0x1bd320, SR_READ | SR_WRITE},
|
||||
{"AMCR_EL0", REG_AMCR_EL0, 0x1bd200, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR00_EL0", REG_AMEVCNTR00_EL0, 0x1bd400, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR01_EL0", REG_AMEVCNTR01_EL0, 0x1bd420, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR02_EL0", REG_AMEVCNTR02_EL0, 0x1bd440, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR03_EL0", REG_AMEVCNTR03_EL0, 0x1bd460, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR04_EL0", REG_AMEVCNTR04_EL0, 0x1bd480, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR05_EL0", REG_AMEVCNTR05_EL0, 0x1bd4a0, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR06_EL0", REG_AMEVCNTR06_EL0, 0x1bd4c0, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR07_EL0", REG_AMEVCNTR07_EL0, 0x1bd4e0, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR08_EL0", REG_AMEVCNTR08_EL0, 0x1bd500, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR09_EL0", REG_AMEVCNTR09_EL0, 0x1bd520, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR010_EL0", REG_AMEVCNTR010_EL0, 0x1bd540, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR011_EL0", REG_AMEVCNTR011_EL0, 0x1bd560, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR012_EL0", REG_AMEVCNTR012_EL0, 0x1bd580, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR013_EL0", REG_AMEVCNTR013_EL0, 0x1bd5a0, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR014_EL0", REG_AMEVCNTR014_EL0, 0x1bd5c0, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR015_EL0", REG_AMEVCNTR015_EL0, 0x1bd5e0, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR10_EL0", REG_AMEVCNTR10_EL0, 0x1bdc00, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR11_EL0", REG_AMEVCNTR11_EL0, 0x1bdc20, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR12_EL0", REG_AMEVCNTR12_EL0, 0x1bdc40, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR13_EL0", REG_AMEVCNTR13_EL0, 0x1bdc60, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR14_EL0", REG_AMEVCNTR14_EL0, 0x1bdc80, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR15_EL0", REG_AMEVCNTR15_EL0, 0x1bdca0, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR16_EL0", REG_AMEVCNTR16_EL0, 0x1bdcc0, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR17_EL0", REG_AMEVCNTR17_EL0, 0x1bdce0, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR18_EL0", REG_AMEVCNTR18_EL0, 0x1bdd00, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR19_EL0", REG_AMEVCNTR19_EL0, 0x1bdd20, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR110_EL0", REG_AMEVCNTR110_EL0, 0x1bdd40, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR111_EL0", REG_AMEVCNTR111_EL0, 0x1bdd60, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR112_EL0", REG_AMEVCNTR112_EL0, 0x1bdd80, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR113_EL0", REG_AMEVCNTR113_EL0, 0x1bdda0, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR114_EL0", REG_AMEVCNTR114_EL0, 0x1bddc0, SR_READ | SR_WRITE},
|
||||
{"AMEVCNTR115_EL0", REG_AMEVCNTR115_EL0, 0x1bdde0, SR_READ | SR_WRITE},
|
||||
{"AMEVTYPER00_EL0", REG_AMEVTYPER00_EL0, 0x1bd600, SR_READ},
|
||||
{"AMEVTYPER01_EL0", REG_AMEVTYPER01_EL0, 0x1bd620, SR_READ},
|
||||
{"AMEVTYPER02_EL0", REG_AMEVTYPER02_EL0, 0x1bd640, SR_READ},
|
||||
{"AMEVTYPER03_EL0", REG_AMEVTYPER03_EL0, 0x1bd660, SR_READ},
|
||||
{"AMEVTYPER04_EL0", REG_AMEVTYPER04_EL0, 0x1bd680, SR_READ},
|
||||
{"AMEVTYPER05_EL0", REG_AMEVTYPER05_EL0, 0x1bd6a0, SR_READ},
|
||||
{"AMEVTYPER06_EL0", REG_AMEVTYPER06_EL0, 0x1bd6c0, SR_READ},
|
||||
{"AMEVTYPER07_EL0", REG_AMEVTYPER07_EL0, 0x1bd6e0, SR_READ},
|
||||
{"AMEVTYPER08_EL0", REG_AMEVTYPER08_EL0, 0x1bd700, SR_READ},
|
||||
{"AMEVTYPER09_EL0", REG_AMEVTYPER09_EL0, 0x1bd720, SR_READ},
|
||||
{"AMEVTYPER010_EL0", REG_AMEVTYPER010_EL0, 0x1bd740, SR_READ},
|
||||
{"AMEVTYPER011_EL0", REG_AMEVTYPER011_EL0, 0x1bd760, SR_READ},
|
||||
{"AMEVTYPER012_EL0", REG_AMEVTYPER012_EL0, 0x1bd780, SR_READ},
|
||||
{"AMEVTYPER013_EL0", REG_AMEVTYPER013_EL0, 0x1bd7a0, SR_READ},
|
||||
{"AMEVTYPER014_EL0", REG_AMEVTYPER014_EL0, 0x1bd7c0, SR_READ},
|
||||
{"AMEVTYPER015_EL0", REG_AMEVTYPER015_EL0, 0x1bd7e0, SR_READ},
|
||||
{"AMEVTYPER10_EL0", REG_AMEVTYPER10_EL0, 0x1bde00, SR_READ | SR_WRITE},
|
||||
{"AMEVTYPER11_EL0", REG_AMEVTYPER11_EL0, 0x1bde20, SR_READ | SR_WRITE},
|
||||
{"AMEVTYPER12_EL0", REG_AMEVTYPER12_EL0, 0x1bde40, SR_READ | SR_WRITE},
|
||||
{"AMEVTYPER13_EL0", REG_AMEVTYPER13_EL0, 0x1bde60, SR_READ | SR_WRITE},
|
||||
{"AMEVTYPER14_EL0", REG_AMEVTYPER14_EL0, 0x1bde80, SR_READ | SR_WRITE},
|
||||
{"AMEVTYPER15_EL0", REG_AMEVTYPER15_EL0, 0x1bdea0, SR_READ | SR_WRITE},
|
||||
{"AMEVTYPER16_EL0", REG_AMEVTYPER16_EL0, 0x1bdec0, SR_READ | SR_WRITE},
|
||||
{"AMEVTYPER17_EL0", REG_AMEVTYPER17_EL0, 0x1bdee0, SR_READ | SR_WRITE},
|
||||
{"AMEVTYPER18_EL0", REG_AMEVTYPER18_EL0, 0x1bdf00, SR_READ | SR_WRITE},
|
||||
{"AMEVTYPER19_EL0", REG_AMEVTYPER19_EL0, 0x1bdf20, SR_READ | SR_WRITE},
|
||||
{"AMEVTYPER110_EL0", REG_AMEVTYPER110_EL0, 0x1bdf40, SR_READ | SR_WRITE},
|
||||
{"AMEVTYPER111_EL0", REG_AMEVTYPER111_EL0, 0x1bdf60, SR_READ | SR_WRITE},
|
||||
{"AMEVTYPER112_EL0", REG_AMEVTYPER112_EL0, 0x1bdf80, SR_READ | SR_WRITE},
|
||||
{"AMEVTYPER113_EL0", REG_AMEVTYPER113_EL0, 0x1bdfa0, SR_READ | SR_WRITE},
|
||||
{"AMEVTYPER114_EL0", REG_AMEVTYPER114_EL0, 0x1bdfc0, SR_READ | SR_WRITE},
|
||||
{"AMEVTYPER115_EL0", REG_AMEVTYPER115_EL0, 0x1bdfe0, SR_READ | SR_WRITE},
|
||||
{"AMUSERENR_EL0", REG_AMUSERENR_EL0, 0x1bd260, SR_READ | SR_WRITE},
|
||||
{"APDAKeyHi_EL1", REG_APDAKeyHi_EL1, 0x182220, SR_READ | SR_WRITE},
|
||||
{"APDAKeyLo_EL1", REG_APDAKeyLo_EL1, 0x182200, SR_READ | SR_WRITE},
|
||||
{"APDBKeyHi_EL1", REG_APDBKeyHi_EL1, 0x182260, SR_READ | SR_WRITE},
|
||||
{"APDBKeyLo_EL1", REG_APDBKeyLo_EL1, 0x182240, SR_READ | SR_WRITE},
|
||||
{"APGAKeyHi_EL1", REG_APGAKeyHi_EL1, 0x182320, SR_READ | SR_WRITE},
|
||||
{"APGAKeyLo_EL1", REG_APGAKeyLo_EL1, 0x182300, SR_READ | SR_WRITE},
|
||||
{"APIAKeyHi_EL1", REG_APIAKeyHi_EL1, 0x182120, SR_READ | SR_WRITE},
|
||||
{"APIAKeyLo_EL1", REG_APIAKeyLo_EL1, 0x182100, SR_READ | SR_WRITE},
|
||||
{"APIBKeyHi_EL1", REG_APIBKeyHi_EL1, 0x182160, SR_READ | SR_WRITE},
|
||||
{"APIBKeyLo_EL1", REG_APIBKeyLo_EL1, 0x182140, SR_READ | SR_WRITE},
|
||||
{"CCSIDR2_EL1", REG_CCSIDR2_EL1, 0x190040, SR_READ},
|
||||
{"CCSIDR_EL1", REG_CCSIDR_EL1, 0x190000, SR_READ},
|
||||
{"CLIDR_EL1", REG_CLIDR_EL1, 0x190020, SR_READ},
|
||||
{"CNTFRQ_EL0", REG_CNTFRQ_EL0, 0x1be000, SR_READ | SR_WRITE},
|
||||
{"CNTKCTL_EL1", REG_CNTKCTL_EL1, 0x18e100, SR_READ | SR_WRITE},
|
||||
{"CNTP_CTL_EL0", REG_CNTP_CTL_EL0, 0x1be220, SR_READ | SR_WRITE},
|
||||
{"CNTP_CVAL_EL0", REG_CNTP_CVAL_EL0, 0x1be240, SR_READ | SR_WRITE},
|
||||
{"CNTP_TVAL_EL0", REG_CNTP_TVAL_EL0, 0x1be200, SR_READ | SR_WRITE},
|
||||
{"CNTPCT_EL0", REG_CNTPCT_EL0, 0x1be020, SR_READ},
|
||||
{"CNTPS_CTL_EL1", REG_CNTPS_CTL_EL1, 0x1fe220, SR_READ | SR_WRITE},
|
||||
{"CNTPS_CVAL_EL1", REG_CNTPS_CVAL_EL1, 0x1fe240, SR_READ | SR_WRITE},
|
||||
{"CNTPS_TVAL_EL1", REG_CNTPS_TVAL_EL1, 0x1fe200, SR_READ | SR_WRITE},
|
||||
{"CNTV_CTL_EL0", REG_CNTV_CTL_EL0, 0x1be320, SR_READ | SR_WRITE},
|
||||
{"CNTV_CVAL_EL0", REG_CNTV_CVAL_EL0, 0x1be340, SR_READ | SR_WRITE},
|
||||
{"CNTV_TVAL_EL0", REG_CNTV_TVAL_EL0, 0x1be300, SR_READ | SR_WRITE},
|
||||
{"CNTVCT_EL0", REG_CNTVCT_EL0, 0x1be040, SR_READ},
|
||||
{"CONTEXTIDR_EL1", REG_CONTEXTIDR_EL1, 0x18d020, SR_READ | SR_WRITE},
|
||||
{"CPACR_EL1", REG_CPACR_EL1, 0x181040, SR_READ | SR_WRITE},
|
||||
{"CSSELR_EL1", REG_CSSELR_EL1, 0x1a0000, SR_READ | SR_WRITE},
|
||||
{"CTR_EL0", REG_CTR_EL0, 0x1b0020, SR_READ},
|
||||
{"CurrentEL", REG_CurrentEL, 0x184240, SR_READ},
|
||||
{"DAIF", REG_DAIF, 0x1b4220, SR_READ | SR_WRITE},
|
||||
{"DBGAUTHSTATUS_EL1", REG_DBGAUTHSTATUS_EL1, 0x107ec0, SR_READ},
|
||||
{"DBGBCR0_EL1", REG_DBGBCR0_EL1, 0x1000a0, SR_READ | SR_WRITE},
|
||||
{"DBGBCR1_EL1", REG_DBGBCR1_EL1, 0x1001a0, SR_READ | SR_WRITE},
|
||||
{"DBGBCR2_EL1", REG_DBGBCR2_EL1, 0x1002a0, SR_READ | SR_WRITE},
|
||||
{"DBGBCR3_EL1", REG_DBGBCR3_EL1, 0x1003a0, SR_READ | SR_WRITE},
|
||||
{"DBGBCR4_EL1", REG_DBGBCR4_EL1, 0x1004a0, SR_READ | SR_WRITE},
|
||||
{"DBGBCR5_EL1", REG_DBGBCR5_EL1, 0x1005a0, SR_READ | SR_WRITE},
|
||||
{"DBGBCR6_EL1", REG_DBGBCR6_EL1, 0x1006a0, SR_READ | SR_WRITE},
|
||||
{"DBGBCR7_EL1", REG_DBGBCR7_EL1, 0x1007a0, SR_READ | SR_WRITE},
|
||||
{"DBGBCR8_EL1", REG_DBGBCR8_EL1, 0x1008a0, SR_READ | SR_WRITE},
|
||||
{"DBGBCR9_EL1", REG_DBGBCR9_EL1, 0x1009a0, SR_READ | SR_WRITE},
|
||||
{"DBGBCR10_EL1", REG_DBGBCR10_EL1, 0x100aa0, SR_READ | SR_WRITE},
|
||||
{"DBGBCR11_EL1", REG_DBGBCR11_EL1, 0x100ba0, SR_READ | SR_WRITE},
|
||||
{"DBGBCR12_EL1", REG_DBGBCR12_EL1, 0x100ca0, SR_READ | SR_WRITE},
|
||||
{"DBGBCR13_EL1", REG_DBGBCR13_EL1, 0x100da0, SR_READ | SR_WRITE},
|
||||
{"DBGBCR14_EL1", REG_DBGBCR14_EL1, 0x100ea0, SR_READ | SR_WRITE},
|
||||
{"DBGBCR15_EL1", REG_DBGBCR15_EL1, 0x100fa0, SR_READ | SR_WRITE},
|
||||
{"DBGBVR0_EL1", REG_DBGBVR0_EL1, 0x100080, SR_READ | SR_WRITE},
|
||||
{"DBGBVR1_EL1", REG_DBGBVR1_EL1, 0x100180, SR_READ | SR_WRITE},
|
||||
{"DBGBVR2_EL1", REG_DBGBVR2_EL1, 0x100280, SR_READ | SR_WRITE},
|
||||
{"DBGBVR3_EL1", REG_DBGBVR3_EL1, 0x100380, SR_READ | SR_WRITE},
|
||||
{"DBGBVR4_EL1", REG_DBGBVR4_EL1, 0x100480, SR_READ | SR_WRITE},
|
||||
{"DBGBVR5_EL1", REG_DBGBVR5_EL1, 0x100580, SR_READ | SR_WRITE},
|
||||
{"DBGBVR6_EL1", REG_DBGBVR6_EL1, 0x100680, SR_READ | SR_WRITE},
|
||||
{"DBGBVR7_EL1", REG_DBGBVR7_EL1, 0x100780, SR_READ | SR_WRITE},
|
||||
{"DBGBVR8_EL1", REG_DBGBVR8_EL1, 0x100880, SR_READ | SR_WRITE},
|
||||
{"DBGBVR9_EL1", REG_DBGBVR9_EL1, 0x100980, SR_READ | SR_WRITE},
|
||||
{"DBGBVR10_EL1", REG_DBGBVR10_EL1, 0x100a80, SR_READ | SR_WRITE},
|
||||
{"DBGBVR11_EL1", REG_DBGBVR11_EL1, 0x100b80, SR_READ | SR_WRITE},
|
||||
{"DBGBVR12_EL1", REG_DBGBVR12_EL1, 0x100c80, SR_READ | SR_WRITE},
|
||||
{"DBGBVR13_EL1", REG_DBGBVR13_EL1, 0x100d80, SR_READ | SR_WRITE},
|
||||
{"DBGBVR14_EL1", REG_DBGBVR14_EL1, 0x100e80, SR_READ | SR_WRITE},
|
||||
{"DBGBVR15_EL1", REG_DBGBVR15_EL1, 0x100f80, SR_READ | SR_WRITE},
|
||||
{"DBGCLAIMCLR_EL1", REG_DBGCLAIMCLR_EL1, 0x1079c0, SR_READ | SR_WRITE},
|
||||
{"DBGCLAIMSET_EL1", REG_DBGCLAIMSET_EL1, 0x1078c0, SR_READ | SR_WRITE},
|
||||
{"DBGDTR_EL0", REG_DBGDTR_EL0, 0x130400, SR_READ | SR_WRITE},
|
||||
{"DBGDTRRX_EL0", REG_DBGDTRRX_EL0, 0x130500, SR_READ},
|
||||
{"DBGDTRTX_EL0", REG_DBGDTRTX_EL0, 0x130500, SR_WRITE},
|
||||
{"DBGPRCR_EL1", REG_DBGPRCR_EL1, 0x101480, SR_READ | SR_WRITE},
|
||||
{"DBGWCR0_EL1", REG_DBGWCR0_EL1, 0x1000e0, SR_READ | SR_WRITE},
|
||||
{"DBGWCR1_EL1", REG_DBGWCR1_EL1, 0x1001e0, SR_READ | SR_WRITE},
|
||||
{"DBGWCR2_EL1", REG_DBGWCR2_EL1, 0x1002e0, SR_READ | SR_WRITE},
|
||||
{"DBGWCR3_EL1", REG_DBGWCR3_EL1, 0x1003e0, SR_READ | SR_WRITE},
|
||||
{"DBGWCR4_EL1", REG_DBGWCR4_EL1, 0x1004e0, SR_READ | SR_WRITE},
|
||||
{"DBGWCR5_EL1", REG_DBGWCR5_EL1, 0x1005e0, SR_READ | SR_WRITE},
|
||||
{"DBGWCR6_EL1", REG_DBGWCR6_EL1, 0x1006e0, SR_READ | SR_WRITE},
|
||||
{"DBGWCR7_EL1", REG_DBGWCR7_EL1, 0x1007e0, SR_READ | SR_WRITE},
|
||||
{"DBGWCR8_EL1", REG_DBGWCR8_EL1, 0x1008e0, SR_READ | SR_WRITE},
|
||||
{"DBGWCR9_EL1", REG_DBGWCR9_EL1, 0x1009e0, SR_READ | SR_WRITE},
|
||||
{"DBGWCR10_EL1", REG_DBGWCR10_EL1, 0x100ae0, SR_READ | SR_WRITE},
|
||||
{"DBGWCR11_EL1", REG_DBGWCR11_EL1, 0x100be0, SR_READ | SR_WRITE},
|
||||
{"DBGWCR12_EL1", REG_DBGWCR12_EL1, 0x100ce0, SR_READ | SR_WRITE},
|
||||
{"DBGWCR13_EL1", REG_DBGWCR13_EL1, 0x100de0, SR_READ | SR_WRITE},
|
||||
{"DBGWCR14_EL1", REG_DBGWCR14_EL1, 0x100ee0, SR_READ | SR_WRITE},
|
||||
{"DBGWCR15_EL1", REG_DBGWCR15_EL1, 0x100fe0, SR_READ | SR_WRITE},
|
||||
{"DBGWVR0_EL1", REG_DBGWVR0_EL1, 0x1000c0, SR_READ | SR_WRITE},
|
||||
{"DBGWVR1_EL1", REG_DBGWVR1_EL1, 0x1001c0, SR_READ | SR_WRITE},
|
||||
{"DBGWVR2_EL1", REG_DBGWVR2_EL1, 0x1002c0, SR_READ | SR_WRITE},
|
||||
{"DBGWVR3_EL1", REG_DBGWVR3_EL1, 0x1003c0, SR_READ | SR_WRITE},
|
||||
{"DBGWVR4_EL1", REG_DBGWVR4_EL1, 0x1004c0, SR_READ | SR_WRITE},
|
||||
{"DBGWVR5_EL1", REG_DBGWVR5_EL1, 0x1005c0, SR_READ | SR_WRITE},
|
||||
{"DBGWVR6_EL1", REG_DBGWVR6_EL1, 0x1006c0, SR_READ | SR_WRITE},
|
||||
{"DBGWVR7_EL1", REG_DBGWVR7_EL1, 0x1007c0, SR_READ | SR_WRITE},
|
||||
{"DBGWVR8_EL1", REG_DBGWVR8_EL1, 0x1008c0, SR_READ | SR_WRITE},
|
||||
{"DBGWVR9_EL1", REG_DBGWVR9_EL1, 0x1009c0, SR_READ | SR_WRITE},
|
||||
{"DBGWVR10_EL1", REG_DBGWVR10_EL1, 0x100ac0, SR_READ | SR_WRITE},
|
||||
{"DBGWVR11_EL1", REG_DBGWVR11_EL1, 0x100bc0, SR_READ | SR_WRITE},
|
||||
{"DBGWVR12_EL1", REG_DBGWVR12_EL1, 0x100cc0, SR_READ | SR_WRITE},
|
||||
{"DBGWVR13_EL1", REG_DBGWVR13_EL1, 0x100dc0, SR_READ | SR_WRITE},
|
||||
{"DBGWVR14_EL1", REG_DBGWVR14_EL1, 0x100ec0, SR_READ | SR_WRITE},
|
||||
{"DBGWVR15_EL1", REG_DBGWVR15_EL1, 0x100fc0, SR_READ | SR_WRITE},
|
||||
{"DCZID_EL0", REG_DCZID_EL0, 0x1b00e0, SR_READ},
|
||||
{"DISR_EL1", REG_DISR_EL1, 0x18c120, SR_READ | SR_WRITE},
|
||||
{"DIT", REG_DIT, 0x1b42a0, SR_READ | SR_WRITE},
|
||||
{"DLR_EL0", REG_DLR_EL0, 0x1b4520, SR_READ | SR_WRITE},
|
||||
{"DSPSR_EL0", REG_DSPSR_EL0, 0x1b4500, SR_READ | SR_WRITE},
|
||||
{"ELR_EL1", REG_ELR_EL1, 0x184020, SR_READ | SR_WRITE},
|
||||
{"ERRIDR_EL1", REG_ERRIDR_EL1, 0x185300, SR_READ},
|
||||
{"ERRSELR_EL1", REG_ERRSELR_EL1, 0x185320, SR_READ | SR_WRITE},
|
||||
{"ERXADDR_EL1", REG_ERXADDR_EL1, 0x185460, SR_READ | SR_WRITE},
|
||||
{"ERXCTLR_EL1", REG_ERXCTLR_EL1, 0x185420, SR_READ | SR_WRITE},
|
||||
{"ERXFR_EL1", REG_ERXFR_EL1, 0x185400, SR_READ},
|
||||
{"ERXMISC0_EL1", REG_ERXMISC0_EL1, 0x185500, SR_READ | SR_WRITE},
|
||||
{"ERXMISC1_EL1", REG_ERXMISC1_EL1, 0x185520, SR_READ | SR_WRITE},
|
||||
{"ERXMISC2_EL1", REG_ERXMISC2_EL1, 0x185540, SR_READ | SR_WRITE},
|
||||
{"ERXMISC3_EL1", REG_ERXMISC3_EL1, 0x185560, SR_READ | SR_WRITE},
|
||||
{"ERXPFGCDN_EL1", REG_ERXPFGCDN_EL1, 0x1854c0, SR_READ | SR_WRITE},
|
||||
{"ERXPFGCTL_EL1", REG_ERXPFGCTL_EL1, 0x1854a0, SR_READ | SR_WRITE},
|
||||
{"ERXPFGF_EL1", REG_ERXPFGF_EL1, 0x185480, SR_READ},
|
||||
{"ERXSTATUS_EL1", REG_ERXSTATUS_EL1, 0x185440, SR_READ | SR_WRITE},
|
||||
{"ESR_EL1", REG_ESR_EL1, 0x185200, SR_READ | SR_WRITE},
|
||||
{"FAR_EL1", REG_FAR_EL1, 0x186000, SR_READ | SR_WRITE},
|
||||
{"FPCR", REG_FPCR, 0x1b4400, SR_READ | SR_WRITE},
|
||||
{"FPSR", REG_FPSR, 0x1b4420, SR_READ | SR_WRITE},
|
||||
{"GCR_EL1", REG_GCR_EL1, 0x1810c0, SR_READ | SR_WRITE},
|
||||
{"GMID_EL1", REG_GMID_EL1, 0x31400, SR_READ},
|
||||
{"ICC_AP0R0_EL1", REG_ICC_AP0R0_EL1, 0x18c880, SR_READ | SR_WRITE},
|
||||
{"ICC_AP0R1_EL1", REG_ICC_AP0R1_EL1, 0x18c8a0, SR_READ | SR_WRITE},
|
||||
{"ICC_AP0R2_EL1", REG_ICC_AP0R2_EL1, 0x18c8c0, SR_READ | SR_WRITE},
|
||||
{"ICC_AP0R3_EL1", REG_ICC_AP0R3_EL1, 0x18c8e0, SR_READ | SR_WRITE},
|
||||
{"ICC_AP1R0_EL1", REG_ICC_AP1R0_EL1, 0x18c900, SR_READ | SR_WRITE},
|
||||
{"ICC_AP1R1_EL1", REG_ICC_AP1R1_EL1, 0x18c920, SR_READ | SR_WRITE},
|
||||
{"ICC_AP1R2_EL1", REG_ICC_AP1R2_EL1, 0x18c940, SR_READ | SR_WRITE},
|
||||
{"ICC_AP1R3_EL1", REG_ICC_AP1R3_EL1, 0x18c960, SR_READ | SR_WRITE},
|
||||
{"ICC_ASGI1R_EL1", REG_ICC_ASGI1R_EL1, 0x18cbc0, SR_WRITE},
|
||||
{"ICC_BPR0_EL1", REG_ICC_BPR0_EL1, 0x18c860, SR_READ | SR_WRITE},
|
||||
{"ICC_BPR1_EL1", REG_ICC_BPR1_EL1, 0x18cc60, SR_READ | SR_WRITE},
|
||||
{"ICC_CTLR_EL1", REG_ICC_CTLR_EL1, 0x18cc80, SR_READ | SR_WRITE},
|
||||
{"ICC_DIR_EL1", REG_ICC_DIR_EL1, 0x18cb20, SR_WRITE},
|
||||
{"ICC_EOIR0_EL1", REG_ICC_EOIR0_EL1, 0x18c820, SR_WRITE},
|
||||
{"ICC_EOIR1_EL1", REG_ICC_EOIR1_EL1, 0x18cc20, SR_WRITE},
|
||||
{"ICC_HPPIR0_EL1", REG_ICC_HPPIR0_EL1, 0x18c840, SR_READ},
|
||||
{"ICC_HPPIR1_EL1", REG_ICC_HPPIR1_EL1, 0x18cc40, SR_READ},
|
||||
{"ICC_IAR0_EL1", REG_ICC_IAR0_EL1, 0x18c800, SR_READ},
|
||||
{"ICC_IAR1_EL1", REG_ICC_IAR1_EL1, 0x18cc00, SR_READ},
|
||||
{"ICC_IGRPEN0_EL1", REG_ICC_IGRPEN0_EL1, 0x18ccc0, SR_READ | SR_WRITE},
|
||||
{"ICC_IGRPEN1_EL1", REG_ICC_IGRPEN1_EL1, 0x18cce0, SR_READ | SR_WRITE},
|
||||
{"ICC_PMR_EL1", REG_ICC_PMR_EL1, 0x184600, SR_READ | SR_WRITE},
|
||||
{"ICC_RPR_EL1", REG_ICC_RPR_EL1, 0x18cb60, SR_READ},
|
||||
{"ICC_SGI0R_EL1", REG_ICC_SGI0R_EL1, 0x18cbe0, SR_WRITE},
|
||||
{"ICC_SGI1R_EL1", REG_ICC_SGI1R_EL1, 0x18cba0, SR_WRITE},
|
||||
{"ICC_SRE_EL1", REG_ICC_SRE_EL1, 0x18cca0, SR_READ | SR_WRITE},
|
||||
{"ICV_AP0R0_EL1", REG_ICV_AP0R0_EL1, 0x18c880, SR_READ | SR_WRITE},
|
||||
{"ICV_AP0R1_EL1", REG_ICV_AP0R1_EL1, 0x18c8a0, SR_READ | SR_WRITE},
|
||||
{"ICV_AP0R2_EL1", REG_ICV_AP0R2_EL1, 0x18c8c0, SR_READ | SR_WRITE},
|
||||
{"ICV_AP0R3_EL1", REG_ICV_AP0R3_EL1, 0x18c8e0, SR_READ | SR_WRITE},
|
||||
{"ICV_AP1R0_EL1", REG_ICV_AP1R0_EL1, 0x18c900, SR_READ | SR_WRITE},
|
||||
{"ICV_AP1R1_EL1", REG_ICV_AP1R1_EL1, 0x18c920, SR_READ | SR_WRITE},
|
||||
{"ICV_AP1R2_EL1", REG_ICV_AP1R2_EL1, 0x18c940, SR_READ | SR_WRITE},
|
||||
{"ICV_AP1R3_EL1", REG_ICV_AP1R3_EL1, 0x18c960, SR_READ | SR_WRITE},
|
||||
{"ICV_BPR0_EL1", REG_ICV_BPR0_EL1, 0x18c860, SR_READ | SR_WRITE},
|
||||
{"ICV_BPR1_EL1", REG_ICV_BPR1_EL1, 0x18cc60, SR_READ | SR_WRITE},
|
||||
{"ICV_CTLR_EL1", REG_ICV_CTLR_EL1, 0x18cc80, SR_READ | SR_WRITE},
|
||||
{"ICV_DIR_EL1", REG_ICV_DIR_EL1, 0x18cb20, SR_WRITE},
|
||||
{"ICV_EOIR0_EL1", REG_ICV_EOIR0_EL1, 0x18c820, SR_WRITE},
|
||||
{"ICV_EOIR1_EL1", REG_ICV_EOIR1_EL1, 0x18cc20, SR_WRITE},
|
||||
{"ICV_HPPIR0_EL1", REG_ICV_HPPIR0_EL1, 0x18c840, SR_READ},
|
||||
{"ICV_HPPIR1_EL1", REG_ICV_HPPIR1_EL1, 0x18cc40, SR_READ},
|
||||
{"ICV_IAR0_EL1", REG_ICV_IAR0_EL1, 0x18c800, SR_READ},
|
||||
{"ICV_IAR1_EL1", REG_ICV_IAR1_EL1, 0x18cc00, SR_READ},
|
||||
{"ICV_IGRPEN0_EL1", REG_ICV_IGRPEN0_EL1, 0x18ccc0, SR_READ | SR_WRITE},
|
||||
{"ICV_IGRPEN1_EL1", REG_ICV_IGRPEN1_EL1, 0x18cce0, SR_READ | SR_WRITE},
|
||||
{"ICV_PMR_EL1", REG_ICV_PMR_EL1, 0x184600, SR_READ | SR_WRITE},
|
||||
{"ICV_RPR_EL1", REG_ICV_RPR_EL1, 0x18cb60, SR_READ},
|
||||
{"ID_AA64AFR0_EL1", REG_ID_AA64AFR0_EL1, 0x180580, SR_READ},
|
||||
{"ID_AA64AFR1_EL1", REG_ID_AA64AFR1_EL1, 0x1805a0, SR_READ},
|
||||
{"ID_AA64DFR0_EL1", REG_ID_AA64DFR0_EL1, 0x180500, SR_READ},
|
||||
{"ID_AA64DFR1_EL1", REG_ID_AA64DFR1_EL1, 0x180520, SR_READ},
|
||||
{"ID_AA64ISAR0_EL1", REG_ID_AA64ISAR0_EL1, 0x180600, SR_READ},
|
||||
{"ID_AA64ISAR1_EL1", REG_ID_AA64ISAR1_EL1, 0x180620, SR_READ},
|
||||
{"ID_AA64MMFR0_EL1", REG_ID_AA64MMFR0_EL1, 0x180700, SR_READ},
|
||||
{"ID_AA64MMFR1_EL1", REG_ID_AA64MMFR1_EL1, 0x180720, SR_READ},
|
||||
{"ID_AA64MMFR2_EL1", REG_ID_AA64MMFR2_EL1, 0x180740, SR_READ},
|
||||
{"ID_AA64PFR0_EL1", REG_ID_AA64PFR0_EL1, 0x180400, SR_READ},
|
||||
{"ID_AA64PFR1_EL1", REG_ID_AA64PFR1_EL1, 0x180420, SR_READ},
|
||||
{"ID_AA64ZFR0_EL1", REG_ID_AA64ZFR0_EL1, 0x180480, SR_READ},
|
||||
{"ID_AFR0_EL1", REG_ID_AFR0_EL1, 0x180160, SR_READ},
|
||||
{"ID_DFR0_EL1", REG_ID_DFR0_EL1, 0x180140, SR_READ},
|
||||
{"ID_ISAR0_EL1", REG_ID_ISAR0_EL1, 0x180200, SR_READ},
|
||||
{"ID_ISAR1_EL1", REG_ID_ISAR1_EL1, 0x180220, SR_READ},
|
||||
{"ID_ISAR2_EL1", REG_ID_ISAR2_EL1, 0x180240, SR_READ},
|
||||
{"ID_ISAR3_EL1", REG_ID_ISAR3_EL1, 0x180260, SR_READ},
|
||||
{"ID_ISAR4_EL1", REG_ID_ISAR4_EL1, 0x180280, SR_READ},
|
||||
{"ID_ISAR5_EL1", REG_ID_ISAR5_EL1, 0x1802a0, SR_READ},
|
||||
{"ID_ISAR6_EL1", REG_ID_ISAR6_EL1, 0x1802e0, SR_READ},
|
||||
{"ID_MMFR0_EL1", REG_ID_MMFR0_EL1, 0x180180, SR_READ},
|
||||
{"ID_MMFR1_EL1", REG_ID_MMFR1_EL1, 0x1801a0, SR_READ},
|
||||
{"ID_MMFR2_EL1", REG_ID_MMFR2_EL1, 0x1801c0, SR_READ},
|
||||
{"ID_MMFR3_EL1", REG_ID_MMFR3_EL1, 0x1801e0, SR_READ},
|
||||
{"ID_MMFR4_EL1", REG_ID_MMFR4_EL1, 0x1802c0, SR_READ},
|
||||
{"ID_PFR0_EL1", REG_ID_PFR0_EL1, 0x180100, SR_READ},
|
||||
{"ID_PFR1_EL1", REG_ID_PFR1_EL1, 0x180120, SR_READ},
|
||||
{"ID_PFR2_EL1", REG_ID_PFR2_EL1, 0x180380, SR_READ},
|
||||
{"ISR_EL1", REG_ISR_EL1, 0x18c100, SR_READ},
|
||||
{"LORC_EL1", REG_LORC_EL1, 0x18a460, SR_READ | SR_WRITE},
|
||||
{"LOREA_EL1", REG_LOREA_EL1, 0x18a420, SR_READ | SR_WRITE},
|
||||
{"LORID_EL1", REG_LORID_EL1, 0x18a4e0, SR_READ},
|
||||
{"LORN_EL1", REG_LORN_EL1, 0x18a440, SR_READ | SR_WRITE},
|
||||
{"LORSA_EL1", REG_LORSA_EL1, 0x18a400, SR_READ | SR_WRITE},
|
||||
{"MAIR_EL1", REG_MAIR_EL1, 0x18a200, SR_READ | SR_WRITE},
|
||||
{"MDCCINT_EL1", REG_MDCCINT_EL1, 0x100200, SR_READ | SR_WRITE},
|
||||
{"MDCCSR_EL0", REG_MDCCSR_EL0, 0x130100, SR_READ},
|
||||
{"MDRAR_EL1", REG_MDRAR_EL1, 0x101000, SR_READ},
|
||||
{"MDSCR_EL1", REG_MDSCR_EL1, 0x100240, SR_READ | SR_WRITE},
|
||||
{"MIDR_EL1", REG_MIDR_EL1, 0x180000, SR_READ},
|
||||
{"MPAM0_EL1", REG_MPAM0_EL1, 0x18a520, SR_READ | SR_WRITE},
|
||||
{"MPAM1_EL1", REG_MPAM1_EL1, 0x18a500, SR_READ | SR_WRITE},
|
||||
{"MPAMIDR_EL1", REG_MPAMIDR_EL1, 0x18a480, SR_READ},
|
||||
{"MPIDR_EL1", REG_MPIDR_EL1, 0x1800a0, SR_READ},
|
||||
{"MVFR0_EL1", REG_MVFR0_EL1, 0x180300, SR_READ},
|
||||
{"MVFR1_EL1", REG_MVFR1_EL1, 0x180320, SR_READ},
|
||||
{"MVFR2_EL1", REG_MVFR2_EL1, 0x180340, SR_READ},
|
||||
{"NZCV", REG_NZCV, 0x1b4200, SR_READ | SR_WRITE},
|
||||
{"OSDLR_EL1", REG_OSDLR_EL1, 0x101380, SR_READ | SR_WRITE},
|
||||
{"OSDTRRX_EL1", REG_OSDTRRX_EL1, 0x100040, SR_READ | SR_WRITE},
|
||||
{"OSDTRTX_EL1", REG_OSDTRTX_EL1, 0x100340, SR_READ | SR_WRITE},
|
||||
{"OSECCR_EL1", REG_OSECCR_EL1, 0x100640, SR_READ | SR_WRITE},
|
||||
{"OSLAR_EL1", REG_OSLAR_EL1, 0x101080, SR_WRITE},
|
||||
{"OSLSR_EL1", REG_OSLSR_EL1, 0x101180, SR_READ},
|
||||
{"PAN", REG_PAN, 0x184260, SR_READ | SR_WRITE},
|
||||
{"PAR_EL1", REG_PAR_EL1, 0x187400, SR_READ | SR_WRITE},
|
||||
{"PMBIDR_EL1", REG_PMBIDR_EL1, 0x189ae0, SR_READ},
|
||||
{"PMBLIMITR_EL1", REG_PMBLIMITR_EL1, 0x189a00, SR_READ | SR_WRITE},
|
||||
{"PMBPTR_EL1", REG_PMBPTR_EL1, 0x189a20, SR_READ | SR_WRITE},
|
||||
{"PMBSR_EL1", REG_PMBSR_EL1, 0x189a60, SR_READ | SR_WRITE},
|
||||
{"PMCCFILTR_EL0", REG_PMCCFILTR_EL0, 0x1befe0, SR_READ | SR_WRITE},
|
||||
{"PMCCNTR_EL0", REG_PMCCNTR_EL0, 0x1b9d00, SR_READ | SR_WRITE},
|
||||
{"PMCEID0_EL0", REG_PMCEID0_EL0, 0x1b9cc0, SR_READ},
|
||||
{"PMCEID1_EL0", REG_PMCEID1_EL0, 0x1b9ce0, SR_READ},
|
||||
{"PMCNTENCLR_EL0", REG_PMCNTENCLR_EL0, 0x1b9c40, SR_READ | SR_WRITE},
|
||||
{"PMCNTENSET_EL0", REG_PMCNTENSET_EL0, 0x1b9c20, SR_READ | SR_WRITE},
|
||||
{"PMCR_EL0", REG_PMCR_EL0, 0x1b9c00, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR0_EL0", REG_PMEVCNTR0_EL0, 0x1be800, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR1_EL0", REG_PMEVCNTR1_EL0, 0x1be820, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR2_EL0", REG_PMEVCNTR2_EL0, 0x1be840, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR3_EL0", REG_PMEVCNTR3_EL0, 0x1be860, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR4_EL0", REG_PMEVCNTR4_EL0, 0x1be880, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR5_EL0", REG_PMEVCNTR5_EL0, 0x1be8a0, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR6_EL0", REG_PMEVCNTR6_EL0, 0x1be8c0, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR7_EL0", REG_PMEVCNTR7_EL0, 0x1be8e0, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR8_EL0", REG_PMEVCNTR8_EL0, 0x1be900, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR9_EL0", REG_PMEVCNTR9_EL0, 0x1be920, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR10_EL0", REG_PMEVCNTR10_EL0, 0x1be940, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR11_EL0", REG_PMEVCNTR11_EL0, 0x1be960, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR12_EL0", REG_PMEVCNTR12_EL0, 0x1be980, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR13_EL0", REG_PMEVCNTR13_EL0, 0x1be9a0, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR14_EL0", REG_PMEVCNTR14_EL0, 0x1be9c0, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR15_EL0", REG_PMEVCNTR15_EL0, 0x1be9e0, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR16_EL0", REG_PMEVCNTR16_EL0, 0x1bea00, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR17_EL0", REG_PMEVCNTR17_EL0, 0x1bea20, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR18_EL0", REG_PMEVCNTR18_EL0, 0x1bea40, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR19_EL0", REG_PMEVCNTR19_EL0, 0x1bea60, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR20_EL0", REG_PMEVCNTR20_EL0, 0x1bea80, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR21_EL0", REG_PMEVCNTR21_EL0, 0x1beaa0, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR22_EL0", REG_PMEVCNTR22_EL0, 0x1beac0, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR23_EL0", REG_PMEVCNTR23_EL0, 0x1beae0, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR24_EL0", REG_PMEVCNTR24_EL0, 0x1beb00, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR25_EL0", REG_PMEVCNTR25_EL0, 0x1beb20, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR26_EL0", REG_PMEVCNTR26_EL0, 0x1beb40, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR27_EL0", REG_PMEVCNTR27_EL0, 0x1beb60, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR28_EL0", REG_PMEVCNTR28_EL0, 0x1beb80, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR29_EL0", REG_PMEVCNTR29_EL0, 0x1beba0, SR_READ | SR_WRITE},
|
||||
{"PMEVCNTR30_EL0", REG_PMEVCNTR30_EL0, 0x1bebc0, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER0_EL0", REG_PMEVTYPER0_EL0, 0x1bec00, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER1_EL0", REG_PMEVTYPER1_EL0, 0x1bec20, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER2_EL0", REG_PMEVTYPER2_EL0, 0x1bec40, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER3_EL0", REG_PMEVTYPER3_EL0, 0x1bec60, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER4_EL0", REG_PMEVTYPER4_EL0, 0x1bec80, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER5_EL0", REG_PMEVTYPER5_EL0, 0x1beca0, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER6_EL0", REG_PMEVTYPER6_EL0, 0x1becc0, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER7_EL0", REG_PMEVTYPER7_EL0, 0x1bece0, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER8_EL0", REG_PMEVTYPER8_EL0, 0x1bed00, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER9_EL0", REG_PMEVTYPER9_EL0, 0x1bed20, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER10_EL0", REG_PMEVTYPER10_EL0, 0x1bed40, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER11_EL0", REG_PMEVTYPER11_EL0, 0x1bed60, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER12_EL0", REG_PMEVTYPER12_EL0, 0x1bed80, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER13_EL0", REG_PMEVTYPER13_EL0, 0x1beda0, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER14_EL0", REG_PMEVTYPER14_EL0, 0x1bedc0, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER15_EL0", REG_PMEVTYPER15_EL0, 0x1bede0, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER16_EL0", REG_PMEVTYPER16_EL0, 0x1bee00, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER17_EL0", REG_PMEVTYPER17_EL0, 0x1bee20, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER18_EL0", REG_PMEVTYPER18_EL0, 0x1bee40, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER19_EL0", REG_PMEVTYPER19_EL0, 0x1bee60, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER20_EL0", REG_PMEVTYPER20_EL0, 0x1bee80, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER21_EL0", REG_PMEVTYPER21_EL0, 0x1beea0, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER22_EL0", REG_PMEVTYPER22_EL0, 0x1beec0, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER23_EL0", REG_PMEVTYPER23_EL0, 0x1beee0, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER24_EL0", REG_PMEVTYPER24_EL0, 0x1bef00, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER25_EL0", REG_PMEVTYPER25_EL0, 0x1bef20, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER26_EL0", REG_PMEVTYPER26_EL0, 0x1bef40, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER27_EL0", REG_PMEVTYPER27_EL0, 0x1bef60, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER28_EL0", REG_PMEVTYPER28_EL0, 0x1bef80, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER29_EL0", REG_PMEVTYPER29_EL0, 0x1befa0, SR_READ | SR_WRITE},
|
||||
{"PMEVTYPER30_EL0", REG_PMEVTYPER30_EL0, 0x1befc0, SR_READ | SR_WRITE},
|
||||
{"PMINTENCLR_EL1", REG_PMINTENCLR_EL1, 0x189e40, SR_READ | SR_WRITE},
|
||||
{"PMINTENSET_EL1", REG_PMINTENSET_EL1, 0x189e20, SR_READ | SR_WRITE},
|
||||
{"PMMIR_EL1", REG_PMMIR_EL1, 0x189ec0, SR_READ},
|
||||
{"PMOVSCLR_EL0", REG_PMOVSCLR_EL0, 0x1b9c60, SR_READ | SR_WRITE},
|
||||
{"PMOVSSET_EL0", REG_PMOVSSET_EL0, 0x1b9e60, SR_READ | SR_WRITE},
|
||||
{"PMSCR_EL1", REG_PMSCR_EL1, 0x189900, SR_READ | SR_WRITE},
|
||||
{"PMSELR_EL0", REG_PMSELR_EL0, 0x1b9ca0, SR_READ | SR_WRITE},
|
||||
{"PMSEVFR_EL1", REG_PMSEVFR_EL1, 0x1899a0, SR_READ | SR_WRITE},
|
||||
{"PMSFCR_EL1", REG_PMSFCR_EL1, 0x189980, SR_READ | SR_WRITE},
|
||||
{"PMSICR_EL1", REG_PMSICR_EL1, 0x189940, SR_READ | SR_WRITE},
|
||||
{"PMSIDR_EL1", REG_PMSIDR_EL1, 0x1899e0, SR_READ},
|
||||
{"PMSIRR_EL1", REG_PMSIRR_EL1, 0x189960, SR_READ | SR_WRITE},
|
||||
{"PMSLATFR_EL1", REG_PMSLATFR_EL1, 0x1899c0, SR_READ | SR_WRITE},
|
||||
{"PMSWINC_EL0", REG_PMSWINC_EL0, 0x1b9c80, SR_WRITE},
|
||||
{"PMUSERENR_EL0", REG_PMUSERENR_EL0, 0x1b9e00, SR_READ | SR_WRITE},
|
||||
{"PMXEVCNTR_EL0", REG_PMXEVCNTR_EL0, 0x1b9d40, SR_READ | SR_WRITE},
|
||||
{"PMXEVTYPER_EL0", REG_PMXEVTYPER_EL0, 0x1b9d20, SR_READ | SR_WRITE},
|
||||
{"REVIDR_EL1", REG_REVIDR_EL1, 0x1800c0, SR_READ},
|
||||
{"RGSR_EL1", REG_RGSR_EL1, 0x1810a0, SR_READ | SR_WRITE},
|
||||
{"RMR_EL1", REG_RMR_EL1, 0x18c040, SR_READ | SR_WRITE},
|
||||
{"RNDR", REG_RNDR, 0x1b2400, SR_READ},
|
||||
{"RNDRRS", REG_RNDRRS, 0x1b2420, SR_READ},
|
||||
{"RVBAR_EL1", REG_RVBAR_EL1, 0x18c020, SR_READ},
|
||||
{"SCTLR_EL1", REG_SCTLR_EL1, 0x181000, SR_READ | SR_WRITE},
|
||||
{"SCXTNUM_EL0", REG_SCXTNUM_EL0, 0x1bd0e0, SR_READ | SR_WRITE},
|
||||
{"SCXTNUM_EL1", REG_SCXTNUM_EL1, 0x18d0e0, SR_READ | SR_WRITE},
|
||||
{"SP_EL0", REG_SP_EL0, 0x184100, SR_READ | SR_WRITE},
|
||||
{"SP_EL1", REG_SP_EL1, 0x1c4100, SR_READ | SR_WRITE},
|
||||
{"SPSel", REG_SPSel, 0x184200, SR_READ | SR_WRITE},
|
||||
{"SPSR_abt", REG_SPSR_abt, 0x1c4320, SR_READ | SR_WRITE},
|
||||
{"SPSR_EL1", REG_SPSR_EL1, 0x184000, SR_READ | SR_WRITE},
|
||||
{"SPSR_fiq", REG_SPSR_fiq, 0x1c4360, SR_READ | SR_WRITE},
|
||||
{"SPSR_irq", REG_SPSR_irq, 0x1c4300, SR_READ | SR_WRITE},
|
||||
{"SPSR_und", REG_SPSR_und, 0x1c4340, SR_READ | SR_WRITE},
|
||||
{"SSBS", REG_SSBS, 0x1b42c0, SR_READ | SR_WRITE},
|
||||
{"TCO", REG_TCO, 0x1b42e0, SR_READ | SR_WRITE},
|
||||
{"TCR_EL1", REG_TCR_EL1, 0x182040, SR_READ | SR_WRITE},
|
||||
{"TFSR_EL1", REG_TFSR_EL1, 0x185600, SR_READ | SR_WRITE},
|
||||
{"TFSRE0_EL1", REG_TFSRE0_EL1, 0x185620, SR_READ | SR_WRITE},
|
||||
{"TPIDR_EL0", REG_TPIDR_EL0, 0x1bd040, SR_READ | SR_WRITE},
|
||||
{"TPIDR_EL1", REG_TPIDR_EL1, 0x18d080, SR_READ | SR_WRITE},
|
||||
{"TPIDRRO_EL0", REG_TPIDRRO_EL0, 0x1bd060, SR_READ | SR_WRITE},
|
||||
{"TRFCR_EL1", REG_TRFCR_EL1, 0x181220, SR_READ | SR_WRITE},
|
||||
{"TTBR0_EL1", REG_TTBR0_EL1, 0x182000, SR_READ | SR_WRITE},
|
||||
{"TTBR1_EL1", REG_TTBR1_EL1, 0x182020, SR_READ | SR_WRITE},
|
||||
{"UAO", REG_UAO, 0x184280, SR_READ | SR_WRITE},
|
||||
{"VBAR_EL1", REG_VBAR_EL1, 0x18c000, SR_READ | SR_WRITE},
|
||||
{"ZCR_EL1", REG_ZCR_EL1, 0x181200, SR_READ | SR_WRITE},
|
||||
}
|
||||
|
||||
func SysRegEnc(r int16) (string, uint32, uint8) {
|
||||
// The automatic generator guarantees that the order
|
||||
// of Reg in SystemReg struct is consistent with the
|
||||
// order of system register declarations
|
||||
if r <= SYSREG_BEGIN || r >= SYSREG_END {
|
||||
return "", 0, 0
|
||||
}
|
||||
v := SystemReg[r-SYSREG_BEGIN-1]
|
||||
return v.Name, v.Enc, v.AccessFlags
|
||||
}
|
||||
200
vendor/github.com/twitchyliquid64/golang-asm/obj/data.go
generated
vendored
Normal file
200
vendor/github.com/twitchyliquid64/golang-asm/obj/data.go
generated
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
// Derived from Inferno utils/6l/obj.c and utils/6l/span.c
|
||||
// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/obj.c
|
||||
// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/span.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package obj
|
||||
|
||||
import (
|
||||
"github.com/twitchyliquid64/golang-asm/objabi"
|
||||
"log"
|
||||
"math"
|
||||
)
|
||||
|
||||
// Grow increases the length of s.P to lsiz.
|
||||
func (s *LSym) Grow(lsiz int64) {
|
||||
siz := int(lsiz)
|
||||
if int64(siz) != lsiz {
|
||||
log.Fatalf("LSym.Grow size %d too long", lsiz)
|
||||
}
|
||||
if len(s.P) >= siz {
|
||||
return
|
||||
}
|
||||
s.P = append(s.P, make([]byte, siz-len(s.P))...)
|
||||
}
|
||||
|
||||
// GrowCap increases the capacity of s.P to c.
|
||||
func (s *LSym) GrowCap(c int64) {
|
||||
if int64(cap(s.P)) >= c {
|
||||
return
|
||||
}
|
||||
if s.P == nil {
|
||||
s.P = make([]byte, 0, c)
|
||||
return
|
||||
}
|
||||
b := make([]byte, len(s.P), c)
|
||||
copy(b, s.P)
|
||||
s.P = b
|
||||
}
|
||||
|
||||
// prepwrite prepares to write data of size siz into s at offset off.
|
||||
func (s *LSym) prepwrite(ctxt *Link, off int64, siz int) {
|
||||
if off < 0 || siz < 0 || off >= 1<<30 {
|
||||
ctxt.Diag("prepwrite: bad off=%d siz=%d s=%v", off, siz, s)
|
||||
}
|
||||
switch s.Type {
|
||||
case objabi.Sxxx, objabi.SBSS:
|
||||
s.Type = objabi.SDATA
|
||||
case objabi.SNOPTRBSS:
|
||||
s.Type = objabi.SNOPTRDATA
|
||||
case objabi.STLSBSS:
|
||||
ctxt.Diag("cannot supply data for %v var %v", s.Type, s.Name)
|
||||
}
|
||||
l := off + int64(siz)
|
||||
s.Grow(l)
|
||||
if l > s.Size {
|
||||
s.Size = l
|
||||
}
|
||||
}
|
||||
|
||||
// WriteFloat32 writes f into s at offset off.
|
||||
func (s *LSym) WriteFloat32(ctxt *Link, off int64, f float32) {
|
||||
s.prepwrite(ctxt, off, 4)
|
||||
ctxt.Arch.ByteOrder.PutUint32(s.P[off:], math.Float32bits(f))
|
||||
}
|
||||
|
||||
// WriteFloat64 writes f into s at offset off.
|
||||
func (s *LSym) WriteFloat64(ctxt *Link, off int64, f float64) {
|
||||
s.prepwrite(ctxt, off, 8)
|
||||
ctxt.Arch.ByteOrder.PutUint64(s.P[off:], math.Float64bits(f))
|
||||
}
|
||||
|
||||
// WriteInt writes an integer i of size siz into s at offset off.
|
||||
func (s *LSym) WriteInt(ctxt *Link, off int64, siz int, i int64) {
|
||||
s.prepwrite(ctxt, off, siz)
|
||||
switch siz {
|
||||
default:
|
||||
ctxt.Diag("WriteInt: bad integer size: %d", siz)
|
||||
case 1:
|
||||
s.P[off] = byte(i)
|
||||
case 2:
|
||||
ctxt.Arch.ByteOrder.PutUint16(s.P[off:], uint16(i))
|
||||
case 4:
|
||||
ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(i))
|
||||
case 8:
|
||||
ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(i))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *LSym) writeAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64, rtype objabi.RelocType) {
|
||||
// Allow 4-byte addresses for DWARF.
|
||||
if siz != ctxt.Arch.PtrSize && siz != 4 {
|
||||
ctxt.Diag("WriteAddr: bad address size %d in %s", siz, s.Name)
|
||||
}
|
||||
s.prepwrite(ctxt, off, siz)
|
||||
r := Addrel(s)
|
||||
r.Off = int32(off)
|
||||
if int64(r.Off) != off {
|
||||
ctxt.Diag("WriteAddr: off overflow %d in %s", off, s.Name)
|
||||
}
|
||||
r.Siz = uint8(siz)
|
||||
r.Sym = rsym
|
||||
r.Type = rtype
|
||||
r.Add = roff
|
||||
}
|
||||
|
||||
// WriteAddr writes an address of size siz into s at offset off.
|
||||
// rsym and roff specify the relocation for the address.
|
||||
func (s *LSym) WriteAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64) {
|
||||
s.writeAddr(ctxt, off, siz, rsym, roff, objabi.R_ADDR)
|
||||
}
|
||||
|
||||
// WriteCURelativeAddr writes a pointer-sized address into s at offset off.
|
||||
// rsym and roff specify the relocation for the address which will be
|
||||
// resolved by the linker to an offset from the DW_AT_low_pc attribute of
|
||||
// the DWARF Compile Unit of rsym.
|
||||
func (s *LSym) WriteCURelativeAddr(ctxt *Link, off int64, rsym *LSym, roff int64) {
|
||||
s.writeAddr(ctxt, off, ctxt.Arch.PtrSize, rsym, roff, objabi.R_ADDRCUOFF)
|
||||
}
|
||||
|
||||
// WriteOff writes a 4 byte offset to rsym+roff into s at offset off.
|
||||
// After linking the 4 bytes stored at s+off will be
|
||||
// rsym+roff-(start of section that s is in).
|
||||
func (s *LSym) WriteOff(ctxt *Link, off int64, rsym *LSym, roff int64) {
|
||||
s.prepwrite(ctxt, off, 4)
|
||||
r := Addrel(s)
|
||||
r.Off = int32(off)
|
||||
if int64(r.Off) != off {
|
||||
ctxt.Diag("WriteOff: off overflow %d in %s", off, s.Name)
|
||||
}
|
||||
r.Siz = 4
|
||||
r.Sym = rsym
|
||||
r.Type = objabi.R_ADDROFF
|
||||
r.Add = roff
|
||||
}
|
||||
|
||||
// WriteWeakOff writes a weak 4 byte offset to rsym+roff into s at offset off.
|
||||
// After linking the 4 bytes stored at s+off will be
|
||||
// rsym+roff-(start of section that s is in).
|
||||
func (s *LSym) WriteWeakOff(ctxt *Link, off int64, rsym *LSym, roff int64) {
|
||||
s.prepwrite(ctxt, off, 4)
|
||||
r := Addrel(s)
|
||||
r.Off = int32(off)
|
||||
if int64(r.Off) != off {
|
||||
ctxt.Diag("WriteOff: off overflow %d in %s", off, s.Name)
|
||||
}
|
||||
r.Siz = 4
|
||||
r.Sym = rsym
|
||||
r.Type = objabi.R_WEAKADDROFF
|
||||
r.Add = roff
|
||||
}
|
||||
|
||||
// WriteString writes a string of size siz into s at offset off.
|
||||
func (s *LSym) WriteString(ctxt *Link, off int64, siz int, str string) {
|
||||
if siz < len(str) {
|
||||
ctxt.Diag("WriteString: bad string size: %d < %d", siz, len(str))
|
||||
}
|
||||
s.prepwrite(ctxt, off, siz)
|
||||
copy(s.P[off:off+int64(siz)], str)
|
||||
}
|
||||
|
||||
// WriteBytes writes a slice of bytes into s at offset off.
|
||||
func (s *LSym) WriteBytes(ctxt *Link, off int64, b []byte) int64 {
|
||||
s.prepwrite(ctxt, off, len(b))
|
||||
copy(s.P[off:], b)
|
||||
return off + int64(len(b))
|
||||
}
|
||||
|
||||
func Addrel(s *LSym) *Reloc {
|
||||
if s.R == nil {
|
||||
s.R = make([]Reloc, 0, 4)
|
||||
}
|
||||
s.R = append(s.R, Reloc{})
|
||||
return &s.R[len(s.R)-1]
|
||||
}
|
||||
690
vendor/github.com/twitchyliquid64/golang-asm/obj/dwarf.go
generated
vendored
Normal file
690
vendor/github.com/twitchyliquid64/golang-asm/obj/dwarf.go
generated
vendored
Normal file
@@ -0,0 +1,690 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Writes dwarf information to object files.
|
||||
|
||||
package obj
|
||||
|
||||
import (
|
||||
"github.com/twitchyliquid64/golang-asm/dwarf"
|
||||
"github.com/twitchyliquid64/golang-asm/objabi"
|
||||
"github.com/twitchyliquid64/golang-asm/src"
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Generate a sequence of opcodes that is as short as possible.
|
||||
// See section 6.2.5
|
||||
const (
|
||||
LINE_BASE = -4
|
||||
LINE_RANGE = 10
|
||||
PC_RANGE = (255 - OPCODE_BASE) / LINE_RANGE
|
||||
OPCODE_BASE = 11
|
||||
)
|
||||
|
||||
// generateDebugLinesSymbol fills the debug lines symbol of a given function.
|
||||
//
|
||||
// It's worth noting that this function doesn't generate the full debug_lines
|
||||
// DWARF section, saving that for the linker. This function just generates the
|
||||
// state machine part of debug_lines. The full table is generated by the
|
||||
// linker. Also, we use the file numbers from the full package (not just the
|
||||
// function in question) when generating the state machine. We do this so we
|
||||
// don't have to do a fixup on the indices when writing the full section.
|
||||
func (ctxt *Link) generateDebugLinesSymbol(s, lines *LSym) {
|
||||
dctxt := dwCtxt{ctxt}
|
||||
|
||||
// Emit a LNE_set_address extended opcode, so as to establish the
|
||||
// starting text address of this function.
|
||||
dctxt.AddUint8(lines, 0)
|
||||
dwarf.Uleb128put(dctxt, lines, 1+int64(ctxt.Arch.PtrSize))
|
||||
dctxt.AddUint8(lines, dwarf.DW_LNE_set_address)
|
||||
dctxt.AddAddress(lines, s, 0)
|
||||
|
||||
// Set up the debug_lines state machine to the default values
|
||||
// we expect at the start of a new sequence.
|
||||
stmt := true
|
||||
line := int64(1)
|
||||
pc := s.Func.Text.Pc
|
||||
var lastpc int64 // last PC written to line table, not last PC in func
|
||||
name := ""
|
||||
prologue, wrotePrologue := false, false
|
||||
// Walk the progs, generating the DWARF table.
|
||||
for p := s.Func.Text; p != nil; p = p.Link {
|
||||
prologue = prologue || (p.Pos.Xlogue() == src.PosPrologueEnd)
|
||||
// If we're not at a real instruction, keep looping!
|
||||
if p.Pos.Line() == 0 || (p.Link != nil && p.Link.Pc == p.Pc) {
|
||||
continue
|
||||
}
|
||||
newStmt := p.Pos.IsStmt() != src.PosNotStmt
|
||||
newName, newLine := linkgetlineFromPos(ctxt, p.Pos)
|
||||
|
||||
// Output debug info.
|
||||
wrote := false
|
||||
if name != newName {
|
||||
newFile := ctxt.PosTable.FileIndex(newName) + 1 // 1 indexing for the table.
|
||||
dctxt.AddUint8(lines, dwarf.DW_LNS_set_file)
|
||||
dwarf.Uleb128put(dctxt, lines, int64(newFile))
|
||||
name = newName
|
||||
wrote = true
|
||||
}
|
||||
if prologue && !wrotePrologue {
|
||||
dctxt.AddUint8(lines, uint8(dwarf.DW_LNS_set_prologue_end))
|
||||
wrotePrologue = true
|
||||
wrote = true
|
||||
}
|
||||
if stmt != newStmt {
|
||||
dctxt.AddUint8(lines, uint8(dwarf.DW_LNS_negate_stmt))
|
||||
stmt = newStmt
|
||||
wrote = true
|
||||
}
|
||||
|
||||
if line != int64(newLine) || wrote {
|
||||
pcdelta := p.Pc - pc
|
||||
lastpc = p.Pc
|
||||
putpclcdelta(ctxt, dctxt, lines, uint64(pcdelta), int64(newLine)-line)
|
||||
line, pc = int64(newLine), p.Pc
|
||||
}
|
||||
}
|
||||
|
||||
// Because these symbols will be concatenated together by the
|
||||
// linker, we need to reset the state machine that controls the
|
||||
// debug symbols. Do this using an end-of-sequence operator.
|
||||
//
|
||||
// Note: at one point in time, Delve did not support multiple end
|
||||
// sequence ops within a compilation unit (bug for this:
|
||||
// https://github.com/go-delve/delve/issues/1694), however the bug
|
||||
// has since been fixed (Oct 2019).
|
||||
//
|
||||
// Issue 38192: the DWARF standard specifies that when you issue
|
||||
// an end-sequence op, the PC value should be one past the last
|
||||
// text address in the translation unit, so apply a delta to the
|
||||
// text address before the end sequence op. If this isn't done,
|
||||
// GDB will assign a line number of zero the last row in the line
|
||||
// table, which we don't want.
|
||||
lastlen := uint64(s.Size - (lastpc - s.Func.Text.Pc))
|
||||
putpclcdelta(ctxt, dctxt, lines, lastlen, 0)
|
||||
dctxt.AddUint8(lines, 0) // start extended opcode
|
||||
dwarf.Uleb128put(dctxt, lines, 1)
|
||||
dctxt.AddUint8(lines, dwarf.DW_LNE_end_sequence)
|
||||
}
|
||||
|
||||
func putpclcdelta(linkctxt *Link, dctxt dwCtxt, s *LSym, deltaPC uint64, deltaLC int64) {
|
||||
// Choose a special opcode that minimizes the number of bytes needed to
|
||||
// encode the remaining PC delta and LC delta.
|
||||
var opcode int64
|
||||
if deltaLC < LINE_BASE {
|
||||
if deltaPC >= PC_RANGE {
|
||||
opcode = OPCODE_BASE + (LINE_RANGE * PC_RANGE)
|
||||
} else {
|
||||
opcode = OPCODE_BASE + (LINE_RANGE * int64(deltaPC))
|
||||
}
|
||||
} else if deltaLC < LINE_BASE+LINE_RANGE {
|
||||
if deltaPC >= PC_RANGE {
|
||||
opcode = OPCODE_BASE + (deltaLC - LINE_BASE) + (LINE_RANGE * PC_RANGE)
|
||||
if opcode > 255 {
|
||||
opcode -= LINE_RANGE
|
||||
}
|
||||
} else {
|
||||
opcode = OPCODE_BASE + (deltaLC - LINE_BASE) + (LINE_RANGE * int64(deltaPC))
|
||||
}
|
||||
} else {
|
||||
if deltaPC <= PC_RANGE {
|
||||
opcode = OPCODE_BASE + (LINE_RANGE - 1) + (LINE_RANGE * int64(deltaPC))
|
||||
if opcode > 255 {
|
||||
opcode = 255
|
||||
}
|
||||
} else {
|
||||
// Use opcode 249 (pc+=23, lc+=5) or 255 (pc+=24, lc+=1).
|
||||
//
|
||||
// Let x=deltaPC-PC_RANGE. If we use opcode 255, x will be the remaining
|
||||
// deltaPC that we need to encode separately before emitting 255. If we
|
||||
// use opcode 249, we will need to encode x+1. If x+1 takes one more
|
||||
// byte to encode than x, then we use opcode 255.
|
||||
//
|
||||
// In all other cases x and x+1 take the same number of bytes to encode,
|
||||
// so we use opcode 249, which may save us a byte in encoding deltaLC,
|
||||
// for similar reasons.
|
||||
switch deltaPC - PC_RANGE {
|
||||
// PC_RANGE is the largest deltaPC we can encode in one byte, using
|
||||
// DW_LNS_const_add_pc.
|
||||
//
|
||||
// (1<<16)-1 is the largest deltaPC we can encode in three bytes, using
|
||||
// DW_LNS_fixed_advance_pc.
|
||||
//
|
||||
// (1<<(7n))-1 is the largest deltaPC we can encode in n+1 bytes for
|
||||
// n=1,3,4,5,..., using DW_LNS_advance_pc.
|
||||
case PC_RANGE, (1 << 7) - 1, (1 << 16) - 1, (1 << 21) - 1, (1 << 28) - 1,
|
||||
(1 << 35) - 1, (1 << 42) - 1, (1 << 49) - 1, (1 << 56) - 1, (1 << 63) - 1:
|
||||
opcode = 255
|
||||
default:
|
||||
opcode = OPCODE_BASE + LINE_RANGE*PC_RANGE - 1 // 249
|
||||
}
|
||||
}
|
||||
}
|
||||
if opcode < OPCODE_BASE || opcode > 255 {
|
||||
panic(fmt.Sprintf("produced invalid special opcode %d", opcode))
|
||||
}
|
||||
|
||||
// Subtract from deltaPC and deltaLC the amounts that the opcode will add.
|
||||
deltaPC -= uint64((opcode - OPCODE_BASE) / LINE_RANGE)
|
||||
deltaLC -= (opcode-OPCODE_BASE)%LINE_RANGE + LINE_BASE
|
||||
|
||||
// Encode deltaPC.
|
||||
if deltaPC != 0 {
|
||||
if deltaPC <= PC_RANGE {
|
||||
// Adjust the opcode so that we can use the 1-byte DW_LNS_const_add_pc
|
||||
// instruction.
|
||||
opcode -= LINE_RANGE * int64(PC_RANGE-deltaPC)
|
||||
if opcode < OPCODE_BASE {
|
||||
panic(fmt.Sprintf("produced invalid special opcode %d", opcode))
|
||||
}
|
||||
dctxt.AddUint8(s, dwarf.DW_LNS_const_add_pc)
|
||||
} else if (1<<14) <= deltaPC && deltaPC < (1<<16) {
|
||||
dctxt.AddUint8(s, dwarf.DW_LNS_fixed_advance_pc)
|
||||
dctxt.AddUint16(s, uint16(deltaPC))
|
||||
} else {
|
||||
dctxt.AddUint8(s, dwarf.DW_LNS_advance_pc)
|
||||
dwarf.Uleb128put(dctxt, s, int64(deltaPC))
|
||||
}
|
||||
}
|
||||
|
||||
// Encode deltaLC.
|
||||
if deltaLC != 0 {
|
||||
dctxt.AddUint8(s, dwarf.DW_LNS_advance_line)
|
||||
dwarf.Sleb128put(dctxt, s, deltaLC)
|
||||
}
|
||||
|
||||
// Output the special opcode.
|
||||
dctxt.AddUint8(s, uint8(opcode))
|
||||
}
|
||||
|
||||
// implement dwarf.Context
|
||||
type dwCtxt struct{ *Link }
|
||||
|
||||
func (c dwCtxt) PtrSize() int {
|
||||
return c.Arch.PtrSize
|
||||
}
|
||||
func (c dwCtxt) AddInt(s dwarf.Sym, size int, i int64) {
|
||||
ls := s.(*LSym)
|
||||
ls.WriteInt(c.Link, ls.Size, size, i)
|
||||
}
|
||||
func (c dwCtxt) AddUint16(s dwarf.Sym, i uint16) {
|
||||
c.AddInt(s, 2, int64(i))
|
||||
}
|
||||
func (c dwCtxt) AddUint8(s dwarf.Sym, i uint8) {
|
||||
b := []byte{byte(i)}
|
||||
c.AddBytes(s, b)
|
||||
}
|
||||
func (c dwCtxt) AddBytes(s dwarf.Sym, b []byte) {
|
||||
ls := s.(*LSym)
|
||||
ls.WriteBytes(c.Link, ls.Size, b)
|
||||
}
|
||||
func (c dwCtxt) AddString(s dwarf.Sym, v string) {
|
||||
ls := s.(*LSym)
|
||||
ls.WriteString(c.Link, ls.Size, len(v), v)
|
||||
ls.WriteInt(c.Link, ls.Size, 1, 0)
|
||||
}
|
||||
func (c dwCtxt) AddAddress(s dwarf.Sym, data interface{}, value int64) {
|
||||
ls := s.(*LSym)
|
||||
size := c.PtrSize()
|
||||
if data != nil {
|
||||
rsym := data.(*LSym)
|
||||
ls.WriteAddr(c.Link, ls.Size, size, rsym, value)
|
||||
} else {
|
||||
ls.WriteInt(c.Link, ls.Size, size, value)
|
||||
}
|
||||
}
|
||||
func (c dwCtxt) AddCURelativeAddress(s dwarf.Sym, data interface{}, value int64) {
|
||||
ls := s.(*LSym)
|
||||
rsym := data.(*LSym)
|
||||
ls.WriteCURelativeAddr(c.Link, ls.Size, rsym, value)
|
||||
}
|
||||
func (c dwCtxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) {
|
||||
panic("should be used only in the linker")
|
||||
}
|
||||
func (c dwCtxt) AddDWARFAddrSectionOffset(s dwarf.Sym, t interface{}, ofs int64) {
|
||||
size := 4
|
||||
if isDwarf64(c.Link) {
|
||||
size = 8
|
||||
}
|
||||
|
||||
ls := s.(*LSym)
|
||||
rsym := t.(*LSym)
|
||||
ls.WriteAddr(c.Link, ls.Size, size, rsym, ofs)
|
||||
r := &ls.R[len(ls.R)-1]
|
||||
r.Type = objabi.R_DWARFSECREF
|
||||
}
|
||||
|
||||
func (c dwCtxt) AddFileRef(s dwarf.Sym, f interface{}) {
|
||||
ls := s.(*LSym)
|
||||
rsym := f.(*LSym)
|
||||
fidx := c.Link.PosTable.FileIndex(rsym.Name)
|
||||
// Note the +1 here -- the value we're writing is going to be an
|
||||
// index into the DWARF line table file section, whose entries
|
||||
// are numbered starting at 1, not 0.
|
||||
ls.WriteInt(c.Link, ls.Size, 4, int64(fidx+1))
|
||||
}
|
||||
|
||||
func (c dwCtxt) CurrentOffset(s dwarf.Sym) int64 {
|
||||
ls := s.(*LSym)
|
||||
return ls.Size
|
||||
}
|
||||
|
||||
// Here "from" is a symbol corresponding to an inlined or concrete
|
||||
// function, "to" is the symbol for the corresponding abstract
|
||||
// function, and "dclIdx" is the index of the symbol of interest with
|
||||
// respect to the Dcl slice of the original pre-optimization version
|
||||
// of the inlined function.
|
||||
func (c dwCtxt) RecordDclReference(from dwarf.Sym, to dwarf.Sym, dclIdx int, inlIndex int) {
|
||||
ls := from.(*LSym)
|
||||
tls := to.(*LSym)
|
||||
ridx := len(ls.R) - 1
|
||||
c.Link.DwFixups.ReferenceChildDIE(ls, ridx, tls, dclIdx, inlIndex)
|
||||
}
|
||||
|
||||
func (c dwCtxt) RecordChildDieOffsets(s dwarf.Sym, vars []*dwarf.Var, offsets []int32) {
|
||||
ls := s.(*LSym)
|
||||
c.Link.DwFixups.RegisterChildDIEOffsets(ls, vars, offsets)
|
||||
}
|
||||
|
||||
func (c dwCtxt) Logf(format string, args ...interface{}) {
|
||||
c.Link.Logf(format, args...)
|
||||
}
|
||||
|
||||
func isDwarf64(ctxt *Link) bool {
|
||||
return ctxt.Headtype == objabi.Haix
|
||||
}
|
||||
|
||||
func (ctxt *Link) dwarfSym(s *LSym) (dwarfInfoSym, dwarfLocSym, dwarfRangesSym, dwarfAbsFnSym, dwarfDebugLines *LSym) {
|
||||
if s.Type != objabi.STEXT {
|
||||
ctxt.Diag("dwarfSym of non-TEXT %v", s)
|
||||
}
|
||||
if s.Func.dwarfInfoSym == nil {
|
||||
s.Func.dwarfInfoSym = &LSym{
|
||||
Type: objabi.SDWARFFCN,
|
||||
}
|
||||
if ctxt.Flag_locationlists {
|
||||
s.Func.dwarfLocSym = &LSym{
|
||||
Type: objabi.SDWARFLOC,
|
||||
}
|
||||
}
|
||||
s.Func.dwarfRangesSym = &LSym{
|
||||
Type: objabi.SDWARFRANGE,
|
||||
}
|
||||
s.Func.dwarfDebugLinesSym = &LSym{
|
||||
Type: objabi.SDWARFLINES,
|
||||
}
|
||||
if s.WasInlined() {
|
||||
s.Func.dwarfAbsFnSym = ctxt.DwFixups.AbsFuncDwarfSym(s)
|
||||
}
|
||||
}
|
||||
return s.Func.dwarfInfoSym, s.Func.dwarfLocSym, s.Func.dwarfRangesSym, s.Func.dwarfAbsFnSym, s.Func.dwarfDebugLinesSym
|
||||
}
|
||||
|
||||
func (s *LSym) Length(dwarfContext interface{}) int64 {
|
||||
return s.Size
|
||||
}
|
||||
|
||||
// fileSymbol returns a symbol corresponding to the source file of the
|
||||
// first instruction (prog) of the specified function. This will
|
||||
// presumably be the file in which the function is defined.
|
||||
func (ctxt *Link) fileSymbol(fn *LSym) *LSym {
|
||||
p := fn.Func.Text
|
||||
if p != nil {
|
||||
f, _ := linkgetlineFromPos(ctxt, p.Pos)
|
||||
fsym := ctxt.Lookup(f)
|
||||
return fsym
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// populateDWARF fills in the DWARF Debugging Information Entries for
|
||||
// TEXT symbol 's'. The various DWARF symbols must already have been
|
||||
// initialized in InitTextSym.
|
||||
func (ctxt *Link) populateDWARF(curfn interface{}, s *LSym, myimportpath string) {
|
||||
info, loc, ranges, absfunc, lines := ctxt.dwarfSym(s)
|
||||
if info.Size != 0 {
|
||||
ctxt.Diag("makeFuncDebugEntry double process %v", s)
|
||||
}
|
||||
var scopes []dwarf.Scope
|
||||
var inlcalls dwarf.InlCalls
|
||||
if ctxt.DebugInfo != nil {
|
||||
scopes, inlcalls = ctxt.DebugInfo(s, info, curfn)
|
||||
}
|
||||
var err error
|
||||
dwctxt := dwCtxt{ctxt}
|
||||
filesym := ctxt.fileSymbol(s)
|
||||
fnstate := &dwarf.FnState{
|
||||
Name: s.Name,
|
||||
Importpath: myimportpath,
|
||||
Info: info,
|
||||
Filesym: filesym,
|
||||
Loc: loc,
|
||||
Ranges: ranges,
|
||||
Absfn: absfunc,
|
||||
StartPC: s,
|
||||
Size: s.Size,
|
||||
External: !s.Static(),
|
||||
Scopes: scopes,
|
||||
InlCalls: inlcalls,
|
||||
UseBASEntries: ctxt.UseBASEntries,
|
||||
}
|
||||
if absfunc != nil {
|
||||
err = dwarf.PutAbstractFunc(dwctxt, fnstate)
|
||||
if err != nil {
|
||||
ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)
|
||||
}
|
||||
err = dwarf.PutConcreteFunc(dwctxt, fnstate)
|
||||
} else {
|
||||
err = dwarf.PutDefaultFunc(dwctxt, fnstate)
|
||||
}
|
||||
if err != nil {
|
||||
ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)
|
||||
}
|
||||
// Fill in the debug lines symbol.
|
||||
ctxt.generateDebugLinesSymbol(s, lines)
|
||||
}
|
||||
|
||||
// DwarfIntConst creates a link symbol for an integer constant with the
|
||||
// given name, type and value.
|
||||
func (ctxt *Link) DwarfIntConst(myimportpath, name, typename string, val int64) {
|
||||
if myimportpath == "" {
|
||||
return
|
||||
}
|
||||
s := ctxt.LookupInit(dwarf.ConstInfoPrefix+myimportpath, func(s *LSym) {
|
||||
s.Type = objabi.SDWARFCONST
|
||||
ctxt.Data = append(ctxt.Data, s)
|
||||
})
|
||||
dwarf.PutIntConst(dwCtxt{ctxt}, s, ctxt.Lookup(dwarf.InfoPrefix+typename), myimportpath+"."+name, val)
|
||||
}
|
||||
|
||||
func (ctxt *Link) DwarfAbstractFunc(curfn interface{}, s *LSym, myimportpath string) {
|
||||
absfn := ctxt.DwFixups.AbsFuncDwarfSym(s)
|
||||
if absfn.Size != 0 {
|
||||
ctxt.Diag("internal error: DwarfAbstractFunc double process %v", s)
|
||||
}
|
||||
if s.Func == nil {
|
||||
s.Func = new(FuncInfo)
|
||||
}
|
||||
scopes, _ := ctxt.DebugInfo(s, absfn, curfn)
|
||||
dwctxt := dwCtxt{ctxt}
|
||||
filesym := ctxt.fileSymbol(s)
|
||||
fnstate := dwarf.FnState{
|
||||
Name: s.Name,
|
||||
Importpath: myimportpath,
|
||||
Info: absfn,
|
||||
Filesym: filesym,
|
||||
Absfn: absfn,
|
||||
External: !s.Static(),
|
||||
Scopes: scopes,
|
||||
UseBASEntries: ctxt.UseBASEntries,
|
||||
}
|
||||
if err := dwarf.PutAbstractFunc(dwctxt, &fnstate); err != nil {
|
||||
ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
// This table is designed to aid in the creation of references between
|
||||
// DWARF subprogram DIEs.
|
||||
//
|
||||
// In most cases when one DWARF DIE has to refer to another DWARF DIE,
|
||||
// the target of the reference has an LSym, which makes it easy to use
|
||||
// the existing relocation mechanism. For DWARF inlined routine DIEs,
|
||||
// however, the subprogram DIE has to refer to a child
|
||||
// parameter/variable DIE of the abstract subprogram. This child DIE
|
||||
// doesn't have an LSym, and also of interest is the fact that when
|
||||
// DWARF generation is happening for inlined function F within caller
|
||||
// G, it's possible that DWARF generation hasn't happened yet for F,
|
||||
// so there is no way to know the offset of a child DIE within F's
|
||||
// abstract function. Making matters more complex, each inlined
|
||||
// instance of F may refer to a subset of the original F's variables
|
||||
// (depending on what happens with optimization, some vars may be
|
||||
// eliminated).
|
||||
//
|
||||
// The fixup table below helps overcome this hurdle. At the point
|
||||
// where a parameter/variable reference is made (via a call to
|
||||
// "ReferenceChildDIE"), a fixup record is generate that records
|
||||
// the relocation that is targeting that child variable. At a later
|
||||
// point when the abstract function DIE is emitted, there will be
|
||||
// a call to "RegisterChildDIEOffsets", at which point the offsets
|
||||
// needed to apply fixups are captured. Finally, once the parallel
|
||||
// portion of the compilation is done, fixups can actually be applied
|
||||
// during the "Finalize" method (this can't be done during the
|
||||
// parallel portion of the compile due to the possibility of data
|
||||
// races).
|
||||
//
|
||||
// This table is also used to record the "precursor" function node for
|
||||
// each function that is the target of an inline -- child DIE references
|
||||
// have to be made with respect to the original pre-optimization
|
||||
// version of the function (to allow for the fact that each inlined
|
||||
// body may be optimized differently).
|
||||
type DwarfFixupTable struct {
|
||||
ctxt *Link
|
||||
mu sync.Mutex
|
||||
symtab map[*LSym]int // maps abstract fn LSYM to index in svec
|
||||
svec []symFixups
|
||||
precursor map[*LSym]fnState // maps fn Lsym to precursor Node, absfn sym
|
||||
}
|
||||
|
||||
type symFixups struct {
|
||||
fixups []relFixup
|
||||
doffsets []declOffset
|
||||
inlIndex int32
|
||||
defseen bool
|
||||
}
|
||||
|
||||
type declOffset struct {
|
||||
// Index of variable within DCL list of pre-optimization function
|
||||
dclIdx int32
|
||||
// Offset of var's child DIE with respect to containing subprogram DIE
|
||||
offset int32
|
||||
}
|
||||
|
||||
type relFixup struct {
|
||||
refsym *LSym
|
||||
relidx int32
|
||||
dclidx int32
|
||||
}
|
||||
|
||||
type fnState struct {
|
||||
// precursor function (really *gc.Node)
|
||||
precursor interface{}
|
||||
// abstract function symbol
|
||||
absfn *LSym
|
||||
}
|
||||
|
||||
func NewDwarfFixupTable(ctxt *Link) *DwarfFixupTable {
|
||||
return &DwarfFixupTable{
|
||||
ctxt: ctxt,
|
||||
symtab: make(map[*LSym]int),
|
||||
precursor: make(map[*LSym]fnState),
|
||||
}
|
||||
}
|
||||
|
||||
func (ft *DwarfFixupTable) GetPrecursorFunc(s *LSym) interface{} {
|
||||
if fnstate, found := ft.precursor[s]; found {
|
||||
return fnstate.precursor
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ft *DwarfFixupTable) SetPrecursorFunc(s *LSym, fn interface{}) {
|
||||
if _, found := ft.precursor[s]; found {
|
||||
ft.ctxt.Diag("internal error: DwarfFixupTable.SetPrecursorFunc double call on %v", s)
|
||||
}
|
||||
|
||||
// initialize abstract function symbol now. This is done here so
|
||||
// as to avoid data races later on during the parallel portion of
|
||||
// the back end.
|
||||
absfn := ft.ctxt.LookupDerived(s, dwarf.InfoPrefix+s.Name+dwarf.AbstractFuncSuffix)
|
||||
absfn.Set(AttrDuplicateOK, true)
|
||||
absfn.Type = objabi.SDWARFABSFCN
|
||||
ft.ctxt.Data = append(ft.ctxt.Data, absfn)
|
||||
|
||||
// In the case of "late" inlining (inlines that happen during
|
||||
// wrapper generation as opposed to the main inlining phase) it's
|
||||
// possible that we didn't cache the abstract function sym for the
|
||||
// text symbol -- do so now if needed. See issue 38068.
|
||||
if s.Func != nil && s.Func.dwarfAbsFnSym == nil {
|
||||
s.Func.dwarfAbsFnSym = absfn
|
||||
}
|
||||
|
||||
ft.precursor[s] = fnState{precursor: fn, absfn: absfn}
|
||||
}
|
||||
|
||||
// Make a note of a child DIE reference: relocation 'ridx' within symbol 's'
|
||||
// is targeting child 'c' of DIE with symbol 'tgt'.
|
||||
func (ft *DwarfFixupTable) ReferenceChildDIE(s *LSym, ridx int, tgt *LSym, dclidx int, inlIndex int) {
|
||||
// Protect against concurrent access if multiple backend workers
|
||||
ft.mu.Lock()
|
||||
defer ft.mu.Unlock()
|
||||
|
||||
// Create entry for symbol if not already present.
|
||||
idx, found := ft.symtab[tgt]
|
||||
if !found {
|
||||
ft.svec = append(ft.svec, symFixups{inlIndex: int32(inlIndex)})
|
||||
idx = len(ft.svec) - 1
|
||||
ft.symtab[tgt] = idx
|
||||
}
|
||||
|
||||
// Do we have child DIE offsets available? If so, then apply them,
|
||||
// otherwise create a fixup record.
|
||||
sf := &ft.svec[idx]
|
||||
if len(sf.doffsets) > 0 {
|
||||
found := false
|
||||
for _, do := range sf.doffsets {
|
||||
if do.dclIdx == int32(dclidx) {
|
||||
off := do.offset
|
||||
s.R[ridx].Add += int64(off)
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
ft.ctxt.Diag("internal error: DwarfFixupTable.ReferenceChildDIE unable to locate child DIE offset for dclIdx=%d src=%v tgt=%v", dclidx, s, tgt)
|
||||
}
|
||||
} else {
|
||||
sf.fixups = append(sf.fixups, relFixup{s, int32(ridx), int32(dclidx)})
|
||||
}
|
||||
}
|
||||
|
||||
// Called once DWARF generation is complete for a given abstract function,
|
||||
// whose children might have been referenced via a call above. Stores
|
||||
// the offsets for any child DIEs (vars, params) so that they can be
|
||||
// consumed later in on DwarfFixupTable.Finalize, which applies any
|
||||
// outstanding fixups.
|
||||
func (ft *DwarfFixupTable) RegisterChildDIEOffsets(s *LSym, vars []*dwarf.Var, coffsets []int32) {
|
||||
// Length of these two slices should agree
|
||||
if len(vars) != len(coffsets) {
|
||||
ft.ctxt.Diag("internal error: RegisterChildDIEOffsets vars/offsets length mismatch")
|
||||
return
|
||||
}
|
||||
|
||||
// Generate the slice of declOffset's based in vars/coffsets
|
||||
doffsets := make([]declOffset, len(coffsets))
|
||||
for i := range coffsets {
|
||||
doffsets[i].dclIdx = vars[i].ChildIndex
|
||||
doffsets[i].offset = coffsets[i]
|
||||
}
|
||||
|
||||
ft.mu.Lock()
|
||||
defer ft.mu.Unlock()
|
||||
|
||||
// Store offsets for this symbol.
|
||||
idx, found := ft.symtab[s]
|
||||
if !found {
|
||||
sf := symFixups{inlIndex: -1, defseen: true, doffsets: doffsets}
|
||||
ft.svec = append(ft.svec, sf)
|
||||
ft.symtab[s] = len(ft.svec) - 1
|
||||
} else {
|
||||
sf := &ft.svec[idx]
|
||||
sf.doffsets = doffsets
|
||||
sf.defseen = true
|
||||
}
|
||||
}
|
||||
|
||||
func (ft *DwarfFixupTable) processFixups(slot int, s *LSym) {
|
||||
sf := &ft.svec[slot]
|
||||
for _, f := range sf.fixups {
|
||||
dfound := false
|
||||
for _, doffset := range sf.doffsets {
|
||||
if doffset.dclIdx == f.dclidx {
|
||||
f.refsym.R[f.relidx].Add += int64(doffset.offset)
|
||||
dfound = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !dfound {
|
||||
ft.ctxt.Diag("internal error: DwarfFixupTable has orphaned fixup on %v targeting %v relidx=%d dclidx=%d", f.refsym, s, f.relidx, f.dclidx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return the LSym corresponding to the 'abstract subprogram' DWARF
|
||||
// info entry for a function.
|
||||
func (ft *DwarfFixupTable) AbsFuncDwarfSym(fnsym *LSym) *LSym {
|
||||
// Protect against concurrent access if multiple backend workers
|
||||
ft.mu.Lock()
|
||||
defer ft.mu.Unlock()
|
||||
|
||||
if fnstate, found := ft.precursor[fnsym]; found {
|
||||
return fnstate.absfn
|
||||
}
|
||||
ft.ctxt.Diag("internal error: AbsFuncDwarfSym requested for %v, not seen during inlining", fnsym)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Called after all functions have been compiled; the main job of this
|
||||
// function is to identify cases where there are outstanding fixups.
|
||||
// This scenario crops up when we have references to variables of an
|
||||
// inlined routine, but that routine is defined in some other package.
|
||||
// This helper walks through and locate these fixups, then invokes a
|
||||
// helper to create an abstract subprogram DIE for each one.
|
||||
func (ft *DwarfFixupTable) Finalize(myimportpath string, trace bool) {
|
||||
if trace {
|
||||
ft.ctxt.Logf("DwarfFixupTable.Finalize invoked for %s\n", myimportpath)
|
||||
}
|
||||
|
||||
// Collect up the keys from the precursor map, then sort the
|
||||
// resulting list (don't want to rely on map ordering here).
|
||||
fns := make([]*LSym, len(ft.precursor))
|
||||
idx := 0
|
||||
for fn := range ft.precursor {
|
||||
fns[idx] = fn
|
||||
idx++
|
||||
}
|
||||
sort.Sort(BySymName(fns))
|
||||
|
||||
// Should not be called during parallel portion of compilation.
|
||||
if ft.ctxt.InParallel {
|
||||
ft.ctxt.Diag("internal error: DwarfFixupTable.Finalize call during parallel backend")
|
||||
}
|
||||
|
||||
// Generate any missing abstract functions.
|
||||
for _, s := range fns {
|
||||
absfn := ft.AbsFuncDwarfSym(s)
|
||||
slot, found := ft.symtab[absfn]
|
||||
if !found || !ft.svec[slot].defseen {
|
||||
ft.ctxt.GenAbstractFunc(s)
|
||||
}
|
||||
}
|
||||
|
||||
// Apply fixups.
|
||||
for _, s := range fns {
|
||||
absfn := ft.AbsFuncDwarfSym(s)
|
||||
slot, found := ft.symtab[absfn]
|
||||
if !found {
|
||||
ft.ctxt.Diag("internal error: DwarfFixupTable.Finalize orphan abstract function for %v", s)
|
||||
} else {
|
||||
ft.processFixups(slot, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type BySymName []*LSym
|
||||
|
||||
func (s BySymName) Len() int { return len(s) }
|
||||
func (s BySymName) Less(i, j int) bool { return s[i].Name < s[j].Name }
|
||||
func (s BySymName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
16
vendor/github.com/twitchyliquid64/golang-asm/obj/go.go
generated
vendored
Normal file
16
vendor/github.com/twitchyliquid64/golang-asm/obj/go.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package obj
|
||||
|
||||
// go-specific code shared across loaders (5l, 6l, 8l).
|
||||
|
||||
func Nopout(p *Prog) {
|
||||
p.As = ANOP
|
||||
p.Scond = 0
|
||||
p.From = Addr{}
|
||||
p.RestArgs = nil
|
||||
p.Reg = 0
|
||||
p.To = Addr{}
|
||||
}
|
||||
131
vendor/github.com/twitchyliquid64/golang-asm/obj/inl.go
generated
vendored
Normal file
131
vendor/github.com/twitchyliquid64/golang-asm/obj/inl.go
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package obj
|
||||
|
||||
import "github.com/twitchyliquid64/golang-asm/src"
|
||||
|
||||
// InlTree is a collection of inlined calls. The Parent field of an
|
||||
// InlinedCall is the index of another InlinedCall in InlTree.
|
||||
//
|
||||
// The compiler maintains a global inlining tree and adds a node to it
|
||||
// every time a function is inlined. For example, suppose f() calls g()
|
||||
// and g has two calls to h(), and that f, g, and h are inlineable:
|
||||
//
|
||||
// 1 func main() {
|
||||
// 2 f()
|
||||
// 3 }
|
||||
// 4 func f() {
|
||||
// 5 g()
|
||||
// 6 }
|
||||
// 7 func g() {
|
||||
// 8 h()
|
||||
// 9 h()
|
||||
// 10 }
|
||||
// 11 func h() {
|
||||
// 12 println("H")
|
||||
// 13 }
|
||||
//
|
||||
// Assuming the global tree starts empty, inlining will produce the
|
||||
// following tree:
|
||||
//
|
||||
// []InlinedCall{
|
||||
// {Parent: -1, Func: "f", Pos: <line 2>},
|
||||
// {Parent: 0, Func: "g", Pos: <line 5>},
|
||||
// {Parent: 1, Func: "h", Pos: <line 8>},
|
||||
// {Parent: 1, Func: "h", Pos: <line 9>},
|
||||
// }
|
||||
//
|
||||
// The nodes of h inlined into main will have inlining indexes 2 and 3.
|
||||
//
|
||||
// Eventually, the compiler extracts a per-function inlining tree from
|
||||
// the global inlining tree (see pcln.go).
|
||||
type InlTree struct {
|
||||
nodes []InlinedCall
|
||||
}
|
||||
|
||||
// InlinedCall is a node in an InlTree.
|
||||
type InlinedCall struct {
|
||||
Parent int // index of the parent in the InlTree or < 0 if outermost call
|
||||
Pos src.XPos // position of the inlined call
|
||||
Func *LSym // function that was inlined
|
||||
ParentPC int32 // PC of instruction just before inlined body. Only valid in local trees.
|
||||
}
|
||||
|
||||
// Add adds a new call to the tree, returning its index.
|
||||
func (tree *InlTree) Add(parent int, pos src.XPos, func_ *LSym) int {
|
||||
r := len(tree.nodes)
|
||||
call := InlinedCall{
|
||||
Parent: parent,
|
||||
Pos: pos,
|
||||
Func: func_,
|
||||
}
|
||||
tree.nodes = append(tree.nodes, call)
|
||||
return r
|
||||
}
|
||||
|
||||
func (tree *InlTree) Parent(inlIndex int) int {
|
||||
return tree.nodes[inlIndex].Parent
|
||||
}
|
||||
|
||||
func (tree *InlTree) InlinedFunction(inlIndex int) *LSym {
|
||||
return tree.nodes[inlIndex].Func
|
||||
}
|
||||
|
||||
func (tree *InlTree) CallPos(inlIndex int) src.XPos {
|
||||
return tree.nodes[inlIndex].Pos
|
||||
}
|
||||
|
||||
func (tree *InlTree) setParentPC(inlIndex int, pc int32) {
|
||||
tree.nodes[inlIndex].ParentPC = pc
|
||||
}
|
||||
|
||||
// OutermostPos returns the outermost position corresponding to xpos,
|
||||
// which is where xpos was ultimately inlined to. In the example for
|
||||
// InlTree, main() contains inlined AST nodes from h(), but the
|
||||
// outermost position for those nodes is line 2.
|
||||
func (ctxt *Link) OutermostPos(xpos src.XPos) src.Pos {
|
||||
pos := ctxt.InnermostPos(xpos)
|
||||
|
||||
outerxpos := xpos
|
||||
for ix := pos.Base().InliningIndex(); ix >= 0; {
|
||||
call := ctxt.InlTree.nodes[ix]
|
||||
ix = call.Parent
|
||||
outerxpos = call.Pos
|
||||
}
|
||||
return ctxt.PosTable.Pos(outerxpos)
|
||||
}
|
||||
|
||||
// InnermostPos returns the innermost position corresponding to xpos,
|
||||
// that is, the code that is inlined and that inlines nothing else.
|
||||
// In the example for InlTree above, the code for println within h
|
||||
// would have an innermost position with line number 12, whether
|
||||
// h was not inlined, inlined into g, g-then-f, or g-then-f-then-main.
|
||||
// This corresponds to what someone debugging main, f, g, or h might
|
||||
// expect to see while single-stepping.
|
||||
func (ctxt *Link) InnermostPos(xpos src.XPos) src.Pos {
|
||||
return ctxt.PosTable.Pos(xpos)
|
||||
}
|
||||
|
||||
// AllPos returns a slice of the positions inlined at xpos, from
|
||||
// innermost (index zero) to outermost. To avoid gratuitous allocation
|
||||
// the result is passed in and extended if necessary.
|
||||
func (ctxt *Link) AllPos(xpos src.XPos, result []src.Pos) []src.Pos {
|
||||
pos := ctxt.InnermostPos(xpos)
|
||||
result = result[:0]
|
||||
result = append(result, ctxt.PosTable.Pos(xpos))
|
||||
for ix := pos.Base().InliningIndex(); ix >= 0; {
|
||||
call := ctxt.InlTree.nodes[ix]
|
||||
ix = call.Parent
|
||||
result = append(result, ctxt.PosTable.Pos(call.Pos))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func dumpInlTree(ctxt *Link, tree InlTree) {
|
||||
for i, call := range tree.nodes {
|
||||
pos := ctxt.PosTable.Pos(call.Pos)
|
||||
ctxt.Logf("%0d | %0d | %s (%s) pc=%d\n", i, call.Parent, call.Func, pos, call.ParentPC)
|
||||
}
|
||||
}
|
||||
85
vendor/github.com/twitchyliquid64/golang-asm/obj/ld.go
generated
vendored
Normal file
85
vendor/github.com/twitchyliquid64/golang-asm/obj/ld.go
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
// Derived from Inferno utils/6l/obj.c and utils/6l/span.c
|
||||
// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/obj.c
|
||||
// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/span.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package obj
|
||||
|
||||
/*
|
||||
* add library to library list.
|
||||
* srcref: src file referring to package
|
||||
* objref: object file referring to package
|
||||
* file: object file, e.g., /home/rsc/go/pkg/container/vector.a
|
||||
* pkg: package import path, e.g. container/vector
|
||||
*/
|
||||
|
||||
const (
|
||||
LOG = 5
|
||||
)
|
||||
|
||||
func mkfwd(sym *LSym) {
|
||||
var dwn [LOG]int32
|
||||
var cnt [LOG]int32
|
||||
var lst [LOG]*Prog
|
||||
|
||||
for i := 0; i < LOG; i++ {
|
||||
if i == 0 {
|
||||
cnt[i] = 1
|
||||
} else {
|
||||
cnt[i] = LOG * cnt[i-1]
|
||||
}
|
||||
dwn[i] = 1
|
||||
lst[i] = nil
|
||||
}
|
||||
|
||||
i := 0
|
||||
for p := sym.Func.Text; p != nil && p.Link != nil; p = p.Link {
|
||||
i--
|
||||
if i < 0 {
|
||||
i = LOG - 1
|
||||
}
|
||||
p.Forwd = nil
|
||||
dwn[i]--
|
||||
if dwn[i] <= 0 {
|
||||
dwn[i] = cnt[i]
|
||||
if lst[i] != nil {
|
||||
lst[i].Forwd = p
|
||||
}
|
||||
lst[i] = p
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Appendp(q *Prog, newprog ProgAlloc) *Prog {
|
||||
p := newprog()
|
||||
p.Link = q.Link
|
||||
q.Link = p
|
||||
p.Pos = q.Pos
|
||||
return p
|
||||
}
|
||||
30
vendor/github.com/twitchyliquid64/golang-asm/obj/line.go
generated
vendored
Normal file
30
vendor/github.com/twitchyliquid64/golang-asm/obj/line.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package obj
|
||||
|
||||
import (
|
||||
"github.com/twitchyliquid64/golang-asm/goobj"
|
||||
"github.com/twitchyliquid64/golang-asm/src"
|
||||
)
|
||||
|
||||
// AddImport adds a package to the list of imported packages.
|
||||
func (ctxt *Link) AddImport(pkg string, fingerprint goobj.FingerprintType) {
|
||||
ctxt.Imports = append(ctxt.Imports, goobj.ImportedPkg{Pkg: pkg, Fingerprint: fingerprint})
|
||||
}
|
||||
|
||||
func linkgetlineFromPos(ctxt *Link, xpos src.XPos) (f string, l int32) {
|
||||
pos := ctxt.PosTable.Pos(xpos)
|
||||
if !pos.IsKnown() {
|
||||
pos = src.Pos{}
|
||||
}
|
||||
// TODO(gri) Should this use relative or absolute line number?
|
||||
return pos.SymFilename(), int32(pos.RelLine())
|
||||
}
|
||||
|
||||
// getFileIndexAndLine returns the file index (local to the CU), and the line number for a position.
|
||||
func getFileIndexAndLine(ctxt *Link, xpos src.XPos) (int, int32) {
|
||||
f, l := linkgetlineFromPos(ctxt, xpos)
|
||||
return ctxt.PosTable.FileIndex(f), l
|
||||
}
|
||||
771
vendor/github.com/twitchyliquid64/golang-asm/obj/link.go
generated
vendored
Normal file
771
vendor/github.com/twitchyliquid64/golang-asm/obj/link.go
generated
vendored
Normal file
@@ -0,0 +1,771 @@
|
||||
// Derived from Inferno utils/6l/l.h and related files.
|
||||
// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/l.h
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package obj
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"github.com/twitchyliquid64/golang-asm/dwarf"
|
||||
"github.com/twitchyliquid64/golang-asm/goobj"
|
||||
"github.com/twitchyliquid64/golang-asm/objabi"
|
||||
"github.com/twitchyliquid64/golang-asm/src"
|
||||
"github.com/twitchyliquid64/golang-asm/sys"
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// An Addr is an argument to an instruction.
|
||||
// The general forms and their encodings are:
|
||||
//
|
||||
// sym±offset(symkind)(reg)(index*scale)
|
||||
// Memory reference at address &sym(symkind) + offset + reg + index*scale.
|
||||
// Any of sym(symkind), ±offset, (reg), (index*scale), and *scale can be omitted.
|
||||
// If (reg) and *scale are both omitted, the resulting expression (index) is parsed as (reg).
|
||||
// To force a parsing as index*scale, write (index*1).
|
||||
// Encoding:
|
||||
// type = TYPE_MEM
|
||||
// name = symkind (NAME_AUTO, ...) or 0 (NAME_NONE)
|
||||
// sym = sym
|
||||
// offset = ±offset
|
||||
// reg = reg (REG_*)
|
||||
// index = index (REG_*)
|
||||
// scale = scale (1, 2, 4, 8)
|
||||
//
|
||||
// $<mem>
|
||||
// Effective address of memory reference <mem>, defined above.
|
||||
// Encoding: same as memory reference, but type = TYPE_ADDR.
|
||||
//
|
||||
// $<±integer value>
|
||||
// This is a special case of $<mem>, in which only ±offset is present.
|
||||
// It has a separate type for easy recognition.
|
||||
// Encoding:
|
||||
// type = TYPE_CONST
|
||||
// offset = ±integer value
|
||||
//
|
||||
// *<mem>
|
||||
// Indirect reference through memory reference <mem>, defined above.
|
||||
// Only used on x86 for CALL/JMP *sym(SB), which calls/jumps to a function
|
||||
// pointer stored in the data word sym(SB), not a function named sym(SB).
|
||||
// Encoding: same as above, but type = TYPE_INDIR.
|
||||
//
|
||||
// $*$<mem>
|
||||
// No longer used.
|
||||
// On machines with actual SB registers, $*$<mem> forced the
|
||||
// instruction encoding to use a full 32-bit constant, never a
|
||||
// reference relative to SB.
|
||||
//
|
||||
// $<floating point literal>
|
||||
// Floating point constant value.
|
||||
// Encoding:
|
||||
// type = TYPE_FCONST
|
||||
// val = floating point value
|
||||
//
|
||||
// $<string literal, up to 8 chars>
|
||||
// String literal value (raw bytes used for DATA instruction).
|
||||
// Encoding:
|
||||
// type = TYPE_SCONST
|
||||
// val = string
|
||||
//
|
||||
// <register name>
|
||||
// Any register: integer, floating point, control, segment, and so on.
|
||||
// If looking for specific register kind, must check type and reg value range.
|
||||
// Encoding:
|
||||
// type = TYPE_REG
|
||||
// reg = reg (REG_*)
|
||||
//
|
||||
// x(PC)
|
||||
// Encoding:
|
||||
// type = TYPE_BRANCH
|
||||
// val = Prog* reference OR ELSE offset = target pc (branch takes priority)
|
||||
//
|
||||
// $±x-±y
|
||||
// Final argument to TEXT, specifying local frame size x and argument size y.
|
||||
// In this form, x and y are integer literals only, not arbitrary expressions.
|
||||
// This avoids parsing ambiguities due to the use of - as a separator.
|
||||
// The ± are optional.
|
||||
// If the final argument to TEXT omits the -±y, the encoding should still
|
||||
// use TYPE_TEXTSIZE (not TYPE_CONST), with u.argsize = ArgsSizeUnknown.
|
||||
// Encoding:
|
||||
// type = TYPE_TEXTSIZE
|
||||
// offset = x
|
||||
// val = int32(y)
|
||||
//
|
||||
// reg<<shift, reg>>shift, reg->shift, reg@>shift
|
||||
// Shifted register value, for ARM and ARM64.
|
||||
// In this form, reg must be a register and shift can be a register or an integer constant.
|
||||
// Encoding:
|
||||
// type = TYPE_SHIFT
|
||||
// On ARM:
|
||||
// offset = (reg&15) | shifttype<<5 | count
|
||||
// shifttype = 0, 1, 2, 3 for <<, >>, ->, @>
|
||||
// count = (reg&15)<<8 | 1<<4 for a register shift count, (n&31)<<7 for an integer constant.
|
||||
// On ARM64:
|
||||
// offset = (reg&31)<<16 | shifttype<<22 | (count&63)<<10
|
||||
// shifttype = 0, 1, 2 for <<, >>, ->
|
||||
//
|
||||
// (reg, reg)
|
||||
// A destination register pair. When used as the last argument of an instruction,
|
||||
// this form makes clear that both registers are destinations.
|
||||
// Encoding:
|
||||
// type = TYPE_REGREG
|
||||
// reg = first register
|
||||
// offset = second register
|
||||
//
|
||||
// [reg, reg, reg-reg]
|
||||
// Register list for ARM, ARM64, 386/AMD64.
|
||||
// Encoding:
|
||||
// type = TYPE_REGLIST
|
||||
// On ARM:
|
||||
// offset = bit mask of registers in list; R0 is low bit.
|
||||
// On ARM64:
|
||||
// offset = register count (Q:size) | arrangement (opcode) | first register
|
||||
// On 386/AMD64:
|
||||
// reg = range low register
|
||||
// offset = 2 packed registers + kind tag (see x86.EncodeRegisterRange)
|
||||
//
|
||||
// reg, reg
|
||||
// Register pair for ARM.
|
||||
// TYPE_REGREG2
|
||||
//
|
||||
// (reg+reg)
|
||||
// Register pair for PPC64.
|
||||
// Encoding:
|
||||
// type = TYPE_MEM
|
||||
// reg = first register
|
||||
// index = second register
|
||||
// scale = 1
|
||||
//
|
||||
// reg.[US]XT[BHWX]
|
||||
// Register extension for ARM64
|
||||
// Encoding:
|
||||
// type = TYPE_REG
|
||||
// reg = REG_[US]XT[BHWX] + register + shift amount
|
||||
// offset = ((reg&31) << 16) | (exttype << 13) | (amount<<10)
|
||||
//
|
||||
// reg.<T>
|
||||
// Register arrangement for ARM64 SIMD register
|
||||
// e.g.: V1.S4, V2.S2, V7.D2, V2.H4, V6.B16
|
||||
// Encoding:
|
||||
// type = TYPE_REG
|
||||
// reg = REG_ARNG + register + arrangement
|
||||
//
|
||||
// reg.<T>[index]
|
||||
// Register element for ARM64
|
||||
// Encoding:
|
||||
// type = TYPE_REG
|
||||
// reg = REG_ELEM + register + arrangement
|
||||
// index = element index
|
||||
|
||||
type Addr struct {
|
||||
Reg int16
|
||||
Index int16
|
||||
Scale int16 // Sometimes holds a register.
|
||||
Type AddrType
|
||||
Name AddrName
|
||||
Class int8
|
||||
Offset int64
|
||||
Sym *LSym
|
||||
|
||||
// argument value:
|
||||
// for TYPE_SCONST, a string
|
||||
// for TYPE_FCONST, a float64
|
||||
// for TYPE_BRANCH, a *Prog (optional)
|
||||
// for TYPE_TEXTSIZE, an int32 (optional)
|
||||
Val interface{}
|
||||
}
|
||||
|
||||
type AddrName int8
|
||||
|
||||
const (
|
||||
NAME_NONE AddrName = iota
|
||||
NAME_EXTERN
|
||||
NAME_STATIC
|
||||
NAME_AUTO
|
||||
NAME_PARAM
|
||||
// A reference to name@GOT(SB) is a reference to the entry in the global offset
|
||||
// table for 'name'.
|
||||
NAME_GOTREF
|
||||
// Indicates that this is a reference to a TOC anchor.
|
||||
NAME_TOCREF
|
||||
)
|
||||
|
||||
//go:generate stringer -type AddrType
|
||||
|
||||
type AddrType uint8
|
||||
|
||||
const (
|
||||
TYPE_NONE AddrType = iota
|
||||
TYPE_BRANCH
|
||||
TYPE_TEXTSIZE
|
||||
TYPE_MEM
|
||||
TYPE_CONST
|
||||
TYPE_FCONST
|
||||
TYPE_SCONST
|
||||
TYPE_REG
|
||||
TYPE_ADDR
|
||||
TYPE_SHIFT
|
||||
TYPE_REGREG
|
||||
TYPE_REGREG2
|
||||
TYPE_INDIR
|
||||
TYPE_REGLIST
|
||||
)
|
||||
|
||||
func (a *Addr) Target() *Prog {
|
||||
if a.Type == TYPE_BRANCH && a.Val != nil {
|
||||
return a.Val.(*Prog)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (a *Addr) SetTarget(t *Prog) {
|
||||
if a.Type != TYPE_BRANCH {
|
||||
panic("setting branch target when type is not TYPE_BRANCH")
|
||||
}
|
||||
a.Val = t
|
||||
}
|
||||
|
||||
// Prog describes a single machine instruction.
|
||||
//
|
||||
// The general instruction form is:
|
||||
//
|
||||
// (1) As.Scond From [, ...RestArgs], To
|
||||
// (2) As.Scond From, Reg [, ...RestArgs], To, RegTo2
|
||||
//
|
||||
// where As is an opcode and the others are arguments:
|
||||
// From, Reg are sources, and To, RegTo2 are destinations.
|
||||
// RestArgs can hold additional sources and destinations.
|
||||
// Usually, not all arguments are present.
|
||||
// For example, MOVL R1, R2 encodes using only As=MOVL, From=R1, To=R2.
|
||||
// The Scond field holds additional condition bits for systems (like arm)
|
||||
// that have generalized conditional execution.
|
||||
// (2) form is present for compatibility with older code,
|
||||
// to avoid too much changes in a single swing.
|
||||
// (1) scheme is enough to express any kind of operand combination.
|
||||
//
|
||||
// Jump instructions use the To.Val field to point to the target *Prog,
|
||||
// which must be in the same linked list as the jump instruction.
|
||||
//
|
||||
// The Progs for a given function are arranged in a list linked through the Link field.
|
||||
//
|
||||
// Each Prog is charged to a specific source line in the debug information,
|
||||
// specified by Pos.Line().
|
||||
// Every Prog has a Ctxt field that defines its context.
|
||||
// For performance reasons, Progs usually are usually bulk allocated, cached, and reused;
|
||||
// those bulk allocators should always be used, rather than new(Prog).
|
||||
//
|
||||
// The other fields not yet mentioned are for use by the back ends and should
|
||||
// be left zeroed by creators of Prog lists.
|
||||
type Prog struct {
|
||||
Ctxt *Link // linker context
|
||||
Link *Prog // next Prog in linked list
|
||||
From Addr // first source operand
|
||||
RestArgs []Addr // can pack any operands that not fit into {Prog.From, Prog.To}
|
||||
To Addr // destination operand (second is RegTo2 below)
|
||||
Pool *Prog // constant pool entry, for arm,arm64 back ends
|
||||
Forwd *Prog // for x86 back end
|
||||
Rel *Prog // for x86, arm back ends
|
||||
Pc int64 // for back ends or assembler: virtual or actual program counter, depending on phase
|
||||
Pos src.XPos // source position of this instruction
|
||||
Spadj int32 // effect of instruction on stack pointer (increment or decrement amount)
|
||||
As As // assembler opcode
|
||||
Reg int16 // 2nd source operand
|
||||
RegTo2 int16 // 2nd destination operand
|
||||
Mark uint16 // bitmask of arch-specific items
|
||||
Optab uint16 // arch-specific opcode index
|
||||
Scond uint8 // bits that describe instruction suffixes (e.g. ARM conditions)
|
||||
Back uint8 // for x86 back end: backwards branch state
|
||||
Ft uint8 // for x86 back end: type index of Prog.From
|
||||
Tt uint8 // for x86 back end: type index of Prog.To
|
||||
Isize uint8 // for x86 back end: size of the instruction in bytes
|
||||
}
|
||||
|
||||
// From3Type returns p.GetFrom3().Type, or TYPE_NONE when
|
||||
// p.GetFrom3() returns nil.
|
||||
//
|
||||
// Deprecated: for the same reasons as Prog.GetFrom3.
|
||||
func (p *Prog) From3Type() AddrType {
|
||||
if p.RestArgs == nil {
|
||||
return TYPE_NONE
|
||||
}
|
||||
return p.RestArgs[0].Type
|
||||
}
|
||||
|
||||
// GetFrom3 returns second source operand (the first is Prog.From).
|
||||
// In combination with Prog.From and Prog.To it makes common 3 operand
|
||||
// case easier to use.
|
||||
//
|
||||
// Should be used only when RestArgs is set with SetFrom3.
|
||||
//
|
||||
// Deprecated: better use RestArgs directly or define backend-specific getters.
|
||||
// Introduced to simplify transition to []Addr.
|
||||
// Usage of this is discouraged due to fragility and lack of guarantees.
|
||||
func (p *Prog) GetFrom3() *Addr {
|
||||
if p.RestArgs == nil {
|
||||
return nil
|
||||
}
|
||||
return &p.RestArgs[0]
|
||||
}
|
||||
|
||||
// SetFrom3 assigns []Addr{a} to p.RestArgs.
|
||||
// In pair with Prog.GetFrom3 it can help in emulation of Prog.From3.
|
||||
//
|
||||
// Deprecated: for the same reasons as Prog.GetFrom3.
|
||||
func (p *Prog) SetFrom3(a Addr) {
|
||||
p.RestArgs = []Addr{a}
|
||||
}
|
||||
|
||||
// An As denotes an assembler opcode.
|
||||
// There are some portable opcodes, declared here in package obj,
|
||||
// that are common to all architectures.
|
||||
// However, the majority of opcodes are arch-specific
|
||||
// and are declared in their respective architecture's subpackage.
|
||||
type As int16
|
||||
|
||||
// These are the portable opcodes.
|
||||
const (
|
||||
AXXX As = iota
|
||||
ACALL
|
||||
ADUFFCOPY
|
||||
ADUFFZERO
|
||||
AEND
|
||||
AFUNCDATA
|
||||
AJMP
|
||||
ANOP
|
||||
APCALIGN
|
||||
APCDATA
|
||||
ARET
|
||||
AGETCALLERPC
|
||||
ATEXT
|
||||
AUNDEF
|
||||
A_ARCHSPECIFIC
|
||||
)
|
||||
|
||||
// Each architecture is allotted a distinct subspace of opcode values
|
||||
// for declaring its arch-specific opcodes.
|
||||
// Within this subspace, the first arch-specific opcode should be
|
||||
// at offset A_ARCHSPECIFIC.
|
||||
//
|
||||
// Subspaces are aligned to a power of two so opcodes can be masked
|
||||
// with AMask and used as compact array indices.
|
||||
const (
|
||||
ABase386 = (1 + iota) << 11
|
||||
ABaseARM
|
||||
ABaseAMD64
|
||||
ABasePPC64
|
||||
ABaseARM64
|
||||
ABaseMIPS
|
||||
ABaseRISCV
|
||||
ABaseS390X
|
||||
ABaseWasm
|
||||
|
||||
AllowedOpCodes = 1 << 11 // The number of opcodes available for any given architecture.
|
||||
AMask = AllowedOpCodes - 1 // AND with this to use the opcode as an array index.
|
||||
)
|
||||
|
||||
// An LSym is the sort of symbol that is written to an object file.
|
||||
// It represents Go symbols in a flat pkg+"."+name namespace.
|
||||
type LSym struct {
|
||||
Name string
|
||||
Type objabi.SymKind
|
||||
Attribute
|
||||
|
||||
RefIdx int // Index of this symbol in the symbol reference list.
|
||||
Size int64
|
||||
Gotype *LSym
|
||||
P []byte
|
||||
R []Reloc
|
||||
|
||||
Func *FuncInfo
|
||||
|
||||
Pkg string
|
||||
PkgIdx int32
|
||||
SymIdx int32 // TODO: replace RefIdx
|
||||
}
|
||||
|
||||
// A FuncInfo contains extra fields for STEXT symbols.
|
||||
type FuncInfo struct {
|
||||
Args int32
|
||||
Locals int32
|
||||
Align int32
|
||||
FuncID objabi.FuncID
|
||||
Text *Prog
|
||||
Autot map[*LSym]struct{}
|
||||
Pcln Pcln
|
||||
InlMarks []InlMark
|
||||
|
||||
dwarfInfoSym *LSym
|
||||
dwarfLocSym *LSym
|
||||
dwarfRangesSym *LSym
|
||||
dwarfAbsFnSym *LSym
|
||||
dwarfDebugLinesSym *LSym
|
||||
|
||||
GCArgs *LSym
|
||||
GCLocals *LSym
|
||||
GCRegs *LSym // Only if !go115ReduceLiveness
|
||||
StackObjects *LSym
|
||||
OpenCodedDeferInfo *LSym
|
||||
|
||||
FuncInfoSym *LSym
|
||||
}
|
||||
|
||||
type InlMark struct {
|
||||
// When unwinding from an instruction in an inlined body, mark
|
||||
// where we should unwind to.
|
||||
// id records the global inlining id of the inlined body.
|
||||
// p records the location of an instruction in the parent (inliner) frame.
|
||||
p *Prog
|
||||
id int32
|
||||
}
|
||||
|
||||
// Mark p as the instruction to set as the pc when
|
||||
// "unwinding" the inlining global frame id. Usually it should be
|
||||
// instruction with a file:line at the callsite, and occur
|
||||
// just before the body of the inlined function.
|
||||
func (fi *FuncInfo) AddInlMark(p *Prog, id int32) {
|
||||
fi.InlMarks = append(fi.InlMarks, InlMark{p: p, id: id})
|
||||
}
|
||||
|
||||
// Record the type symbol for an auto variable so that the linker
|
||||
// an emit DWARF type information for the type.
|
||||
func (fi *FuncInfo) RecordAutoType(gotype *LSym) {
|
||||
if fi.Autot == nil {
|
||||
fi.Autot = make(map[*LSym]struct{})
|
||||
}
|
||||
fi.Autot[gotype] = struct{}{}
|
||||
}
|
||||
|
||||
//go:generate stringer -type ABI
|
||||
|
||||
// ABI is the calling convention of a text symbol.
|
||||
type ABI uint8
|
||||
|
||||
const (
|
||||
// ABI0 is the stable stack-based ABI. It's important that the
|
||||
// value of this is "0": we can't distinguish between
|
||||
// references to data and ABI0 text symbols in assembly code,
|
||||
// and hence this doesn't distinguish between symbols without
|
||||
// an ABI and text symbols with ABI0.
|
||||
ABI0 ABI = iota
|
||||
|
||||
// ABIInternal is the internal ABI that may change between Go
|
||||
// versions. All Go functions use the internal ABI and the
|
||||
// compiler generates wrappers for calls to and from other
|
||||
// ABIs.
|
||||
ABIInternal
|
||||
|
||||
ABICount
|
||||
)
|
||||
|
||||
// Attribute is a set of symbol attributes.
|
||||
type Attribute uint32
|
||||
|
||||
const (
|
||||
AttrDuplicateOK Attribute = 1 << iota
|
||||
AttrCFunc
|
||||
AttrNoSplit
|
||||
AttrLeaf
|
||||
AttrWrapper
|
||||
AttrNeedCtxt
|
||||
AttrNoFrame
|
||||
AttrOnList
|
||||
AttrStatic
|
||||
|
||||
// MakeTypelink means that the type should have an entry in the typelink table.
|
||||
AttrMakeTypelink
|
||||
|
||||
// ReflectMethod means the function may call reflect.Type.Method or
|
||||
// reflect.Type.MethodByName. Matching is imprecise (as reflect.Type
|
||||
// can be used through a custom interface), so ReflectMethod may be
|
||||
// set in some cases when the reflect package is not called.
|
||||
//
|
||||
// Used by the linker to determine what methods can be pruned.
|
||||
AttrReflectMethod
|
||||
|
||||
// Local means make the symbol local even when compiling Go code to reference Go
|
||||
// symbols in other shared libraries, as in this mode symbols are global by
|
||||
// default. "local" here means in the sense of the dynamic linker, i.e. not
|
||||
// visible outside of the module (shared library or executable) that contains its
|
||||
// definition. (When not compiling to support Go shared libraries, all symbols are
|
||||
// local in this sense unless there is a cgo_export_* directive).
|
||||
AttrLocal
|
||||
|
||||
// For function symbols; indicates that the specified function was the
|
||||
// target of an inline during compilation
|
||||
AttrWasInlined
|
||||
|
||||
// TopFrame means that this function is an entry point and unwinders should not
|
||||
// keep unwinding beyond this frame.
|
||||
AttrTopFrame
|
||||
|
||||
// Indexed indicates this symbol has been assigned with an index (when using the
|
||||
// new object file format).
|
||||
AttrIndexed
|
||||
|
||||
// Only applied on type descriptor symbols, UsedInIface indicates this type is
|
||||
// converted to an interface.
|
||||
//
|
||||
// Used by the linker to determine what methods can be pruned.
|
||||
AttrUsedInIface
|
||||
|
||||
// ContentAddressable indicates this is a content-addressable symbol.
|
||||
AttrContentAddressable
|
||||
|
||||
// attrABIBase is the value at which the ABI is encoded in
|
||||
// Attribute. This must be last; all bits after this are
|
||||
// assumed to be an ABI value.
|
||||
//
|
||||
// MUST BE LAST since all bits above this comprise the ABI.
|
||||
attrABIBase
|
||||
)
|
||||
|
||||
func (a Attribute) DuplicateOK() bool { return a&AttrDuplicateOK != 0 }
|
||||
func (a Attribute) MakeTypelink() bool { return a&AttrMakeTypelink != 0 }
|
||||
func (a Attribute) CFunc() bool { return a&AttrCFunc != 0 }
|
||||
func (a Attribute) NoSplit() bool { return a&AttrNoSplit != 0 }
|
||||
func (a Attribute) Leaf() bool { return a&AttrLeaf != 0 }
|
||||
func (a Attribute) OnList() bool { return a&AttrOnList != 0 }
|
||||
func (a Attribute) ReflectMethod() bool { return a&AttrReflectMethod != 0 }
|
||||
func (a Attribute) Local() bool { return a&AttrLocal != 0 }
|
||||
func (a Attribute) Wrapper() bool { return a&AttrWrapper != 0 }
|
||||
func (a Attribute) NeedCtxt() bool { return a&AttrNeedCtxt != 0 }
|
||||
func (a Attribute) NoFrame() bool { return a&AttrNoFrame != 0 }
|
||||
func (a Attribute) Static() bool { return a&AttrStatic != 0 }
|
||||
func (a Attribute) WasInlined() bool { return a&AttrWasInlined != 0 }
|
||||
func (a Attribute) TopFrame() bool { return a&AttrTopFrame != 0 }
|
||||
func (a Attribute) Indexed() bool { return a&AttrIndexed != 0 }
|
||||
func (a Attribute) UsedInIface() bool { return a&AttrUsedInIface != 0 }
|
||||
func (a Attribute) ContentAddressable() bool { return a&AttrContentAddressable != 0 }
|
||||
|
||||
func (a *Attribute) Set(flag Attribute, value bool) {
|
||||
if value {
|
||||
*a |= flag
|
||||
} else {
|
||||
*a &^= flag
|
||||
}
|
||||
}
|
||||
|
||||
func (a Attribute) ABI() ABI { return ABI(a / attrABIBase) }
|
||||
func (a *Attribute) SetABI(abi ABI) {
|
||||
const mask = 1 // Only one ABI bit for now.
|
||||
*a = (*a &^ (mask * attrABIBase)) | Attribute(abi)*attrABIBase
|
||||
}
|
||||
|
||||
var textAttrStrings = [...]struct {
|
||||
bit Attribute
|
||||
s string
|
||||
}{
|
||||
{bit: AttrDuplicateOK, s: "DUPOK"},
|
||||
{bit: AttrMakeTypelink, s: ""},
|
||||
{bit: AttrCFunc, s: "CFUNC"},
|
||||
{bit: AttrNoSplit, s: "NOSPLIT"},
|
||||
{bit: AttrLeaf, s: "LEAF"},
|
||||
{bit: AttrOnList, s: ""},
|
||||
{bit: AttrReflectMethod, s: "REFLECTMETHOD"},
|
||||
{bit: AttrLocal, s: "LOCAL"},
|
||||
{bit: AttrWrapper, s: "WRAPPER"},
|
||||
{bit: AttrNeedCtxt, s: "NEEDCTXT"},
|
||||
{bit: AttrNoFrame, s: "NOFRAME"},
|
||||
{bit: AttrStatic, s: "STATIC"},
|
||||
{bit: AttrWasInlined, s: ""},
|
||||
{bit: AttrTopFrame, s: "TOPFRAME"},
|
||||
{bit: AttrIndexed, s: ""},
|
||||
{bit: AttrContentAddressable, s: ""},
|
||||
}
|
||||
|
||||
// TextAttrString formats a for printing in as part of a TEXT prog.
|
||||
func (a Attribute) TextAttrString() string {
|
||||
var s string
|
||||
for _, x := range textAttrStrings {
|
||||
if a&x.bit != 0 {
|
||||
if x.s != "" {
|
||||
s += x.s + "|"
|
||||
}
|
||||
a &^= x.bit
|
||||
}
|
||||
}
|
||||
switch a.ABI() {
|
||||
case ABI0:
|
||||
case ABIInternal:
|
||||
s += "ABIInternal|"
|
||||
a.SetABI(0) // Clear ABI so we don't print below.
|
||||
}
|
||||
if a != 0 {
|
||||
s += fmt.Sprintf("UnknownAttribute(%d)|", a)
|
||||
}
|
||||
// Chop off trailing |, if present.
|
||||
if len(s) > 0 {
|
||||
s = s[:len(s)-1]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *LSym) String() string {
|
||||
return s.Name
|
||||
}
|
||||
|
||||
// The compiler needs *LSym to be assignable to cmd/compile/internal/ssa.Sym.
|
||||
func (s *LSym) CanBeAnSSASym() {
|
||||
}
|
||||
|
||||
type Pcln struct {
|
||||
Pcsp Pcdata
|
||||
Pcfile Pcdata
|
||||
Pcline Pcdata
|
||||
Pcinline Pcdata
|
||||
Pcdata []Pcdata
|
||||
Funcdata []*LSym
|
||||
Funcdataoff []int64
|
||||
UsedFiles map[goobj.CUFileIndex]struct{} // file indices used while generating pcfile
|
||||
InlTree InlTree // per-function inlining tree extracted from the global tree
|
||||
}
|
||||
|
||||
type Reloc struct {
|
||||
Off int32
|
||||
Siz uint8
|
||||
Type objabi.RelocType
|
||||
Add int64
|
||||
Sym *LSym
|
||||
}
|
||||
|
||||
type Auto struct {
|
||||
Asym *LSym
|
||||
Aoffset int32
|
||||
Name AddrName
|
||||
Gotype *LSym
|
||||
}
|
||||
|
||||
type Pcdata struct {
|
||||
P []byte
|
||||
}
|
||||
|
||||
// Link holds the context for writing object code from a compiler
|
||||
// to be linker input or for reading that input into the linker.
|
||||
type Link struct {
|
||||
Headtype objabi.HeadType
|
||||
Arch *LinkArch
|
||||
Debugasm int
|
||||
Debugvlog bool
|
||||
Debugpcln string
|
||||
Flag_shared bool
|
||||
Flag_dynlink bool
|
||||
Flag_linkshared bool
|
||||
Flag_optimize bool
|
||||
Flag_locationlists bool
|
||||
Retpoline bool // emit use of retpoline stubs for indirect jmp/call
|
||||
Bso *bufio.Writer
|
||||
Pathname string
|
||||
Pkgpath string // the current package's import path, "" if unknown
|
||||
hashmu sync.Mutex // protects hash, funchash
|
||||
hash map[string]*LSym // name -> sym mapping
|
||||
funchash map[string]*LSym // name -> sym mapping for ABIInternal syms
|
||||
statichash map[string]*LSym // name -> sym mapping for static syms
|
||||
PosTable src.PosTable
|
||||
InlTree InlTree // global inlining tree used by gc/inl.go
|
||||
DwFixups *DwarfFixupTable
|
||||
Imports []goobj.ImportedPkg
|
||||
DiagFunc func(string, ...interface{})
|
||||
DiagFlush func()
|
||||
DebugInfo func(fn *LSym, info *LSym, curfn interface{}) ([]dwarf.Scope, dwarf.InlCalls) // if non-nil, curfn is a *gc.Node
|
||||
GenAbstractFunc func(fn *LSym)
|
||||
Errors int
|
||||
|
||||
InParallel bool // parallel backend phase in effect
|
||||
UseBASEntries bool // use Base Address Selection Entries in location lists and PC ranges
|
||||
IsAsm bool // is the source assembly language, which may contain surprising idioms (e.g., call tables)
|
||||
|
||||
// state for writing objects
|
||||
Text []*LSym
|
||||
Data []*LSym
|
||||
|
||||
// ABIAliases are text symbols that should be aliased to all
|
||||
// ABIs. These symbols may only be referenced and not defined
|
||||
// by this object, since the need for an alias may appear in a
|
||||
// different object than the definition. Hence, this
|
||||
// information can't be carried in the symbol definition.
|
||||
//
|
||||
// TODO(austin): Replace this with ABI wrappers once the ABIs
|
||||
// actually diverge.
|
||||
ABIAliases []*LSym
|
||||
|
||||
// Constant symbols (e.g. $i64.*) are data symbols created late
|
||||
// in the concurrent phase. To ensure a deterministic order, we
|
||||
// add them to a separate list, sort at the end, and append it
|
||||
// to Data.
|
||||
constSyms []*LSym
|
||||
|
||||
// pkgIdx maps package path to index. The index is used for
|
||||
// symbol reference in the object file.
|
||||
pkgIdx map[string]int32
|
||||
|
||||
defs []*LSym // list of defined symbols in the current package
|
||||
hashed64defs []*LSym // list of defined short (64-bit or less) hashed (content-addressable) symbols
|
||||
hasheddefs []*LSym // list of defined hashed (content-addressable) symbols
|
||||
nonpkgdefs []*LSym // list of defined non-package symbols
|
||||
nonpkgrefs []*LSym // list of referenced non-package symbols
|
||||
|
||||
Fingerprint goobj.FingerprintType // fingerprint of symbol indices, to catch index mismatch
|
||||
}
|
||||
|
||||
func (ctxt *Link) Diag(format string, args ...interface{}) {
|
||||
ctxt.Errors++
|
||||
ctxt.DiagFunc(format, args...)
|
||||
}
|
||||
|
||||
func (ctxt *Link) Logf(format string, args ...interface{}) {
|
||||
fmt.Fprintf(ctxt.Bso, format, args...)
|
||||
ctxt.Bso.Flush()
|
||||
}
|
||||
|
||||
// The smallest possible offset from the hardware stack pointer to a local
|
||||
// variable on the stack. Architectures that use a link register save its value
|
||||
// on the stack in the function prologue and so always have a pointer between
|
||||
// the hardware stack pointer and the local variable area.
|
||||
func (ctxt *Link) FixedFrameSize() int64 {
|
||||
switch ctxt.Arch.Family {
|
||||
case sys.AMD64, sys.I386, sys.Wasm:
|
||||
return 0
|
||||
case sys.PPC64:
|
||||
// PIC code on ppc64le requires 32 bytes of stack, and it's easier to
|
||||
// just use that much stack always on ppc64x.
|
||||
return int64(4 * ctxt.Arch.PtrSize)
|
||||
default:
|
||||
return int64(ctxt.Arch.PtrSize)
|
||||
}
|
||||
}
|
||||
|
||||
// LinkArch is the definition of a single architecture.
|
||||
type LinkArch struct {
|
||||
*sys.Arch
|
||||
Init func(*Link)
|
||||
Preprocess func(*Link, *LSym, ProgAlloc)
|
||||
Assemble func(*Link, *LSym, ProgAlloc)
|
||||
Progedit func(*Link, *Prog, ProgAlloc)
|
||||
UnaryDst map[As]bool // Instruction takes one operand, a destination.
|
||||
DWARFRegisters map[int16]int16
|
||||
}
|
||||
481
vendor/github.com/twitchyliquid64/golang-asm/obj/mips/a.out.go
generated
vendored
Normal file
481
vendor/github.com/twitchyliquid64/golang-asm/obj/mips/a.out.go
generated
vendored
Normal file
@@ -0,0 +1,481 @@
|
||||
// cmd/9c/9.out.h from Vita Nuova.
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package mips
|
||||
|
||||
import (
|
||||
"github.com/twitchyliquid64/golang-asm/obj"
|
||||
)
|
||||
|
||||
//go:generate go run ../stringer.go -i $GOFILE -o anames.go -p mips
|
||||
|
||||
/*
|
||||
* mips 64
|
||||
*/
|
||||
const (
|
||||
NSNAME = 8
|
||||
NSYM = 50
|
||||
NREG = 32 /* number of general registers */
|
||||
NFREG = 32 /* number of floating point registers */
|
||||
NWREG = 32 /* number of MSA registers */
|
||||
)
|
||||
|
||||
const (
|
||||
REG_R0 = obj.RBaseMIPS + iota // must be a multiple of 32
|
||||
REG_R1
|
||||
REG_R2
|
||||
REG_R3
|
||||
REG_R4
|
||||
REG_R5
|
||||
REG_R6
|
||||
REG_R7
|
||||
REG_R8
|
||||
REG_R9
|
||||
REG_R10
|
||||
REG_R11
|
||||
REG_R12
|
||||
REG_R13
|
||||
REG_R14
|
||||
REG_R15
|
||||
REG_R16
|
||||
REG_R17
|
||||
REG_R18
|
||||
REG_R19
|
||||
REG_R20
|
||||
REG_R21
|
||||
REG_R22
|
||||
REG_R23
|
||||
REG_R24
|
||||
REG_R25
|
||||
REG_R26
|
||||
REG_R27
|
||||
REG_R28
|
||||
REG_R29
|
||||
REG_R30
|
||||
REG_R31
|
||||
|
||||
REG_F0 // must be a multiple of 32
|
||||
REG_F1
|
||||
REG_F2
|
||||
REG_F3
|
||||
REG_F4
|
||||
REG_F5
|
||||
REG_F6
|
||||
REG_F7
|
||||
REG_F8
|
||||
REG_F9
|
||||
REG_F10
|
||||
REG_F11
|
||||
REG_F12
|
||||
REG_F13
|
||||
REG_F14
|
||||
REG_F15
|
||||
REG_F16
|
||||
REG_F17
|
||||
REG_F18
|
||||
REG_F19
|
||||
REG_F20
|
||||
REG_F21
|
||||
REG_F22
|
||||
REG_F23
|
||||
REG_F24
|
||||
REG_F25
|
||||
REG_F26
|
||||
REG_F27
|
||||
REG_F28
|
||||
REG_F29
|
||||
REG_F30
|
||||
REG_F31
|
||||
|
||||
// co-processor 0 control registers
|
||||
REG_M0 // must be a multiple of 32
|
||||
REG_M1
|
||||
REG_M2
|
||||
REG_M3
|
||||
REG_M4
|
||||
REG_M5
|
||||
REG_M6
|
||||
REG_M7
|
||||
REG_M8
|
||||
REG_M9
|
||||
REG_M10
|
||||
REG_M11
|
||||
REG_M12
|
||||
REG_M13
|
||||
REG_M14
|
||||
REG_M15
|
||||
REG_M16
|
||||
REG_M17
|
||||
REG_M18
|
||||
REG_M19
|
||||
REG_M20
|
||||
REG_M21
|
||||
REG_M22
|
||||
REG_M23
|
||||
REG_M24
|
||||
REG_M25
|
||||
REG_M26
|
||||
REG_M27
|
||||
REG_M28
|
||||
REG_M29
|
||||
REG_M30
|
||||
REG_M31
|
||||
|
||||
// FPU control registers
|
||||
REG_FCR0 // must be a multiple of 32
|
||||
REG_FCR1
|
||||
REG_FCR2
|
||||
REG_FCR3
|
||||
REG_FCR4
|
||||
REG_FCR5
|
||||
REG_FCR6
|
||||
REG_FCR7
|
||||
REG_FCR8
|
||||
REG_FCR9
|
||||
REG_FCR10
|
||||
REG_FCR11
|
||||
REG_FCR12
|
||||
REG_FCR13
|
||||
REG_FCR14
|
||||
REG_FCR15
|
||||
REG_FCR16
|
||||
REG_FCR17
|
||||
REG_FCR18
|
||||
REG_FCR19
|
||||
REG_FCR20
|
||||
REG_FCR21
|
||||
REG_FCR22
|
||||
REG_FCR23
|
||||
REG_FCR24
|
||||
REG_FCR25
|
||||
REG_FCR26
|
||||
REG_FCR27
|
||||
REG_FCR28
|
||||
REG_FCR29
|
||||
REG_FCR30
|
||||
REG_FCR31
|
||||
|
||||
// MSA registers
|
||||
// The lower bits of W registers are alias to F registers
|
||||
REG_W0 // must be a multiple of 32
|
||||
REG_W1
|
||||
REG_W2
|
||||
REG_W3
|
||||
REG_W4
|
||||
REG_W5
|
||||
REG_W6
|
||||
REG_W7
|
||||
REG_W8
|
||||
REG_W9
|
||||
REG_W10
|
||||
REG_W11
|
||||
REG_W12
|
||||
REG_W13
|
||||
REG_W14
|
||||
REG_W15
|
||||
REG_W16
|
||||
REG_W17
|
||||
REG_W18
|
||||
REG_W19
|
||||
REG_W20
|
||||
REG_W21
|
||||
REG_W22
|
||||
REG_W23
|
||||
REG_W24
|
||||
REG_W25
|
||||
REG_W26
|
||||
REG_W27
|
||||
REG_W28
|
||||
REG_W29
|
||||
REG_W30
|
||||
REG_W31
|
||||
|
||||
REG_HI
|
||||
REG_LO
|
||||
|
||||
REG_LAST = REG_LO // the last defined register
|
||||
|
||||
REG_SPECIAL = REG_M0
|
||||
|
||||
REGZERO = REG_R0 /* set to zero */
|
||||
REGSP = REG_R29
|
||||
REGSB = REG_R28
|
||||
REGLINK = REG_R31
|
||||
REGRET = REG_R1
|
||||
REGARG = -1 /* -1 disables passing the first argument in register */
|
||||
REGRT1 = REG_R1 /* reserved for runtime, duffzero and duffcopy */
|
||||
REGRT2 = REG_R2 /* reserved for runtime, duffcopy */
|
||||
REGCTXT = REG_R22 /* context for closures */
|
||||
REGG = REG_R30 /* G */
|
||||
REGTMP = REG_R23 /* used by the linker */
|
||||
FREGRET = REG_F0
|
||||
)
|
||||
|
||||
// https://llvm.org/svn/llvm-project/llvm/trunk/lib/Target/Mips/MipsRegisterInfo.td search for DwarfRegNum
|
||||
// https://gcc.gnu.org/viewcvs/gcc/trunk/gcc/config/mips/mips.c?view=co&revision=258099&content-type=text%2Fplain search for mips_dwarf_regno
|
||||
// For now, this is adequate for both 32 and 64 bit.
|
||||
var MIPSDWARFRegisters = map[int16]int16{}
|
||||
|
||||
func init() {
|
||||
// f assigns dwarfregisters[from:to] = (base):(to-from+base)
|
||||
f := func(from, to, base int16) {
|
||||
for r := int16(from); r <= to; r++ {
|
||||
MIPSDWARFRegisters[r] = (r - from) + base
|
||||
}
|
||||
}
|
||||
f(REG_R0, REG_R31, 0)
|
||||
f(REG_F0, REG_F31, 32) // For 32-bit MIPS, compiler only uses even numbered registers -- see cmd/compile/internal/ssa/gen/MIPSOps.go
|
||||
MIPSDWARFRegisters[REG_HI] = 64
|
||||
MIPSDWARFRegisters[REG_LO] = 65
|
||||
// The lower bits of W registers are alias to F registers
|
||||
f(REG_W0, REG_W31, 32)
|
||||
}
|
||||
|
||||
const (
|
||||
BIG = 32766
|
||||
)
|
||||
|
||||
const (
|
||||
/* mark flags */
|
||||
FOLL = 1 << 0
|
||||
LABEL = 1 << 1
|
||||
LEAF = 1 << 2
|
||||
SYNC = 1 << 3
|
||||
BRANCH = 1 << 4
|
||||
LOAD = 1 << 5
|
||||
FCMP = 1 << 6
|
||||
NOSCHED = 1 << 7
|
||||
|
||||
NSCHED = 20
|
||||
)
|
||||
|
||||
const (
|
||||
C_NONE = iota
|
||||
C_REG
|
||||
C_FREG
|
||||
C_FCREG
|
||||
C_MREG /* special processor register */
|
||||
C_WREG /* MSA registers */
|
||||
C_HI
|
||||
C_LO
|
||||
C_ZCON
|
||||
C_SCON /* 16 bit signed */
|
||||
C_UCON /* 32 bit signed, low 16 bits 0 */
|
||||
C_ADD0CON
|
||||
C_AND0CON
|
||||
C_ADDCON /* -0x8000 <= v < 0 */
|
||||
C_ANDCON /* 0 < v <= 0xFFFF */
|
||||
C_LCON /* other 32 */
|
||||
C_DCON /* other 64 (could subdivide further) */
|
||||
C_SACON /* $n(REG) where n <= int16 */
|
||||
C_SECON
|
||||
C_LACON /* $n(REG) where int16 < n <= int32 */
|
||||
C_LECON
|
||||
C_DACON /* $n(REG) where int32 < n */
|
||||
C_STCON /* $tlsvar */
|
||||
C_SBRA
|
||||
C_LBRA
|
||||
C_SAUTO
|
||||
C_LAUTO
|
||||
C_SEXT
|
||||
C_LEXT
|
||||
C_ZOREG
|
||||
C_SOREG
|
||||
C_LOREG
|
||||
C_GOK
|
||||
C_ADDR
|
||||
C_TLS
|
||||
C_TEXTSIZE
|
||||
|
||||
C_NCLASS /* must be the last */
|
||||
)
|
||||
|
||||
const (
|
||||
AABSD = obj.ABaseMIPS + obj.A_ARCHSPECIFIC + iota
|
||||
AABSF
|
||||
AABSW
|
||||
AADD
|
||||
AADDD
|
||||
AADDF
|
||||
AADDU
|
||||
AADDW
|
||||
AAND
|
||||
ABEQ
|
||||
ABFPF
|
||||
ABFPT
|
||||
ABGEZ
|
||||
ABGEZAL
|
||||
ABGTZ
|
||||
ABLEZ
|
||||
ABLTZ
|
||||
ABLTZAL
|
||||
ABNE
|
||||
ABREAK
|
||||
ACLO
|
||||
ACLZ
|
||||
ACMOVF
|
||||
ACMOVN
|
||||
ACMOVT
|
||||
ACMOVZ
|
||||
ACMPEQD
|
||||
ACMPEQF
|
||||
ACMPGED
|
||||
ACMPGEF
|
||||
ACMPGTD
|
||||
ACMPGTF
|
||||
ADIV
|
||||
ADIVD
|
||||
ADIVF
|
||||
ADIVU
|
||||
ADIVW
|
||||
AGOK
|
||||
ALL
|
||||
ALLV
|
||||
ALUI
|
||||
AMADD
|
||||
AMOVB
|
||||
AMOVBU
|
||||
AMOVD
|
||||
AMOVDF
|
||||
AMOVDW
|
||||
AMOVF
|
||||
AMOVFD
|
||||
AMOVFW
|
||||
AMOVH
|
||||
AMOVHU
|
||||
AMOVW
|
||||
AMOVWD
|
||||
AMOVWF
|
||||
AMOVWL
|
||||
AMOVWR
|
||||
AMSUB
|
||||
AMUL
|
||||
AMULD
|
||||
AMULF
|
||||
AMULU
|
||||
AMULW
|
||||
ANEGD
|
||||
ANEGF
|
||||
ANEGW
|
||||
ANEGV
|
||||
ANOOP // hardware nop
|
||||
ANOR
|
||||
AOR
|
||||
AREM
|
||||
AREMU
|
||||
ARFE
|
||||
ASC
|
||||
ASCV
|
||||
ASGT
|
||||
ASGTU
|
||||
ASLL
|
||||
ASQRTD
|
||||
ASQRTF
|
||||
ASRA
|
||||
ASRL
|
||||
ASUB
|
||||
ASUBD
|
||||
ASUBF
|
||||
ASUBU
|
||||
ASUBW
|
||||
ASYNC
|
||||
ASYSCALL
|
||||
ATEQ
|
||||
ATLBP
|
||||
ATLBR
|
||||
ATLBWI
|
||||
ATLBWR
|
||||
ATNE
|
||||
AWORD
|
||||
AXOR
|
||||
|
||||
/* 64-bit */
|
||||
AMOVV
|
||||
AMOVVL
|
||||
AMOVVR
|
||||
ASLLV
|
||||
ASRAV
|
||||
ASRLV
|
||||
ADIVV
|
||||
ADIVVU
|
||||
AREMV
|
||||
AREMVU
|
||||
AMULV
|
||||
AMULVU
|
||||
AADDV
|
||||
AADDVU
|
||||
ASUBV
|
||||
ASUBVU
|
||||
|
||||
/* 64-bit FP */
|
||||
ATRUNCFV
|
||||
ATRUNCDV
|
||||
ATRUNCFW
|
||||
ATRUNCDW
|
||||
AMOVWU
|
||||
AMOVFV
|
||||
AMOVDV
|
||||
AMOVVF
|
||||
AMOVVD
|
||||
|
||||
/* MSA */
|
||||
AVMOVB
|
||||
AVMOVH
|
||||
AVMOVW
|
||||
AVMOVD
|
||||
|
||||
ALAST
|
||||
|
||||
// aliases
|
||||
AJMP = obj.AJMP
|
||||
AJAL = obj.ACALL
|
||||
ARET = obj.ARET
|
||||
)
|
||||
|
||||
func init() {
|
||||
// The asm encoder generally assumes that the lowest 5 bits of the
|
||||
// REG_XX constants match the machine instruction encoding, i.e.
|
||||
// the lowest 5 bits is the register number.
|
||||
// Check this here.
|
||||
if REG_R0%32 != 0 {
|
||||
panic("REG_R0 is not a multiple of 32")
|
||||
}
|
||||
if REG_F0%32 != 0 {
|
||||
panic("REG_F0 is not a multiple of 32")
|
||||
}
|
||||
if REG_M0%32 != 0 {
|
||||
panic("REG_M0 is not a multiple of 32")
|
||||
}
|
||||
if REG_FCR0%32 != 0 {
|
||||
panic("REG_FCR0 is not a multiple of 32")
|
||||
}
|
||||
if REG_W0%32 != 0 {
|
||||
panic("REG_W0 is not a multiple of 32")
|
||||
}
|
||||
}
|
||||
135
vendor/github.com/twitchyliquid64/golang-asm/obj/mips/anames.go
generated
vendored
Normal file
135
vendor/github.com/twitchyliquid64/golang-asm/obj/mips/anames.go
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
// Code generated by stringer -i a.out.go -o anames.go -p mips; DO NOT EDIT.
|
||||
|
||||
package mips
|
||||
|
||||
import "github.com/twitchyliquid64/golang-asm/obj"
|
||||
|
||||
var Anames = []string{
|
||||
obj.A_ARCHSPECIFIC: "ABSD",
|
||||
"ABSF",
|
||||
"ABSW",
|
||||
"ADD",
|
||||
"ADDD",
|
||||
"ADDF",
|
||||
"ADDU",
|
||||
"ADDW",
|
||||
"AND",
|
||||
"BEQ",
|
||||
"BFPF",
|
||||
"BFPT",
|
||||
"BGEZ",
|
||||
"BGEZAL",
|
||||
"BGTZ",
|
||||
"BLEZ",
|
||||
"BLTZ",
|
||||
"BLTZAL",
|
||||
"BNE",
|
||||
"BREAK",
|
||||
"CLO",
|
||||
"CLZ",
|
||||
"CMOVF",
|
||||
"CMOVN",
|
||||
"CMOVT",
|
||||
"CMOVZ",
|
||||
"CMPEQD",
|
||||
"CMPEQF",
|
||||
"CMPGED",
|
||||
"CMPGEF",
|
||||
"CMPGTD",
|
||||
"CMPGTF",
|
||||
"DIV",
|
||||
"DIVD",
|
||||
"DIVF",
|
||||
"DIVU",
|
||||
"DIVW",
|
||||
"GOK",
|
||||
"LL",
|
||||
"LLV",
|
||||
"LUI",
|
||||
"MADD",
|
||||
"MOVB",
|
||||
"MOVBU",
|
||||
"MOVD",
|
||||
"MOVDF",
|
||||
"MOVDW",
|
||||
"MOVF",
|
||||
"MOVFD",
|
||||
"MOVFW",
|
||||
"MOVH",
|
||||
"MOVHU",
|
||||
"MOVW",
|
||||
"MOVWD",
|
||||
"MOVWF",
|
||||
"MOVWL",
|
||||
"MOVWR",
|
||||
"MSUB",
|
||||
"MUL",
|
||||
"MULD",
|
||||
"MULF",
|
||||
"MULU",
|
||||
"MULW",
|
||||
"NEGD",
|
||||
"NEGF",
|
||||
"NEGW",
|
||||
"NEGV",
|
||||
"NOOP",
|
||||
"NOR",
|
||||
"OR",
|
||||
"REM",
|
||||
"REMU",
|
||||
"RFE",
|
||||
"SC",
|
||||
"SCV",
|
||||
"SGT",
|
||||
"SGTU",
|
||||
"SLL",
|
||||
"SQRTD",
|
||||
"SQRTF",
|
||||
"SRA",
|
||||
"SRL",
|
||||
"SUB",
|
||||
"SUBD",
|
||||
"SUBF",
|
||||
"SUBU",
|
||||
"SUBW",
|
||||
"SYNC",
|
||||
"SYSCALL",
|
||||
"TEQ",
|
||||
"TLBP",
|
||||
"TLBR",
|
||||
"TLBWI",
|
||||
"TLBWR",
|
||||
"TNE",
|
||||
"WORD",
|
||||
"XOR",
|
||||
"MOVV",
|
||||
"MOVVL",
|
||||
"MOVVR",
|
||||
"SLLV",
|
||||
"SRAV",
|
||||
"SRLV",
|
||||
"DIVV",
|
||||
"DIVVU",
|
||||
"REMV",
|
||||
"REMVU",
|
||||
"MULV",
|
||||
"MULVU",
|
||||
"ADDV",
|
||||
"ADDVU",
|
||||
"SUBV",
|
||||
"SUBVU",
|
||||
"TRUNCFV",
|
||||
"TRUNCDV",
|
||||
"TRUNCFW",
|
||||
"TRUNCDW",
|
||||
"MOVWU",
|
||||
"MOVFV",
|
||||
"MOVDV",
|
||||
"MOVVF",
|
||||
"MOVVD",
|
||||
"VMOVB",
|
||||
"VMOVH",
|
||||
"VMOVW",
|
||||
"VMOVD",
|
||||
"LAST",
|
||||
}
|
||||
45
vendor/github.com/twitchyliquid64/golang-asm/obj/mips/anames0.go
generated
vendored
Normal file
45
vendor/github.com/twitchyliquid64/golang-asm/obj/mips/anames0.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mips
|
||||
|
||||
var cnames0 = []string{
|
||||
"NONE",
|
||||
"REG",
|
||||
"FREG",
|
||||
"FCREG",
|
||||
"MREG",
|
||||
"WREG",
|
||||
"HI",
|
||||
"LO",
|
||||
"ZCON",
|
||||
"SCON",
|
||||
"UCON",
|
||||
"ADD0CON",
|
||||
"AND0CON",
|
||||
"ADDCON",
|
||||
"ANDCON",
|
||||
"LCON",
|
||||
"DCON",
|
||||
"SACON",
|
||||
"SECON",
|
||||
"LACON",
|
||||
"LECON",
|
||||
"DACON",
|
||||
"STCON",
|
||||
"SBRA",
|
||||
"LBRA",
|
||||
"SAUTO",
|
||||
"LAUTO",
|
||||
"SEXT",
|
||||
"LEXT",
|
||||
"ZOREG",
|
||||
"SOREG",
|
||||
"LOREG",
|
||||
"GOK",
|
||||
"ADDR",
|
||||
"TLS",
|
||||
"TEXTSIZE",
|
||||
"NCLASS",
|
||||
}
|
||||
2108
vendor/github.com/twitchyliquid64/golang-asm/obj/mips/asm0.go
generated
vendored
Normal file
2108
vendor/github.com/twitchyliquid64/golang-asm/obj/mips/asm0.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
83
vendor/github.com/twitchyliquid64/golang-asm/obj/mips/list0.go
generated
vendored
Normal file
83
vendor/github.com/twitchyliquid64/golang-asm/obj/mips/list0.go
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
// cmd/9l/list.c from Vita Nuova.
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package mips
|
||||
|
||||
import (
|
||||
"github.com/twitchyliquid64/golang-asm/obj"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func init() {
|
||||
obj.RegisterRegister(obj.RBaseMIPS, REG_LAST+1, rconv)
|
||||
obj.RegisterOpcode(obj.ABaseMIPS, Anames)
|
||||
}
|
||||
|
||||
func rconv(r int) string {
|
||||
if r == 0 {
|
||||
return "NONE"
|
||||
}
|
||||
if r == REGG {
|
||||
// Special case.
|
||||
return "g"
|
||||
}
|
||||
if REG_R0 <= r && r <= REG_R31 {
|
||||
return fmt.Sprintf("R%d", r-REG_R0)
|
||||
}
|
||||
if REG_F0 <= r && r <= REG_F31 {
|
||||
return fmt.Sprintf("F%d", r-REG_F0)
|
||||
}
|
||||
if REG_M0 <= r && r <= REG_M31 {
|
||||
return fmt.Sprintf("M%d", r-REG_M0)
|
||||
}
|
||||
if REG_FCR0 <= r && r <= REG_FCR31 {
|
||||
return fmt.Sprintf("FCR%d", r-REG_FCR0)
|
||||
}
|
||||
if REG_W0 <= r && r <= REG_W31 {
|
||||
return fmt.Sprintf("W%d", r-REG_W0)
|
||||
}
|
||||
if r == REG_HI {
|
||||
return "HI"
|
||||
}
|
||||
if r == REG_LO {
|
||||
return "LO"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Rgok(%d)", r-obj.RBaseMIPS)
|
||||
}
|
||||
|
||||
func DRconv(a int) string {
|
||||
s := "C_??"
|
||||
if a >= C_NONE && a <= C_NCLASS {
|
||||
s = cnames0[a]
|
||||
}
|
||||
var fp string
|
||||
fp += s
|
||||
return fp
|
||||
}
|
||||
1457
vendor/github.com/twitchyliquid64/golang-asm/obj/mips/obj0.go
generated
vendored
Normal file
1457
vendor/github.com/twitchyliquid64/golang-asm/obj/mips/obj0.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
755
vendor/github.com/twitchyliquid64/golang-asm/obj/objfile.go
generated
vendored
Normal file
755
vendor/github.com/twitchyliquid64/golang-asm/obj/objfile.go
generated
vendored
Normal file
@@ -0,0 +1,755 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Writing Go object files.
|
||||
|
||||
package obj
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/twitchyliquid64/golang-asm/bio"
|
||||
"github.com/twitchyliquid64/golang-asm/goobj"
|
||||
"github.com/twitchyliquid64/golang-asm/objabi"
|
||||
"github.com/twitchyliquid64/golang-asm/sys"
|
||||
"crypto/sha1"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Entry point of writing new object file.
|
||||
func WriteObjFile(ctxt *Link, b *bio.Writer) {
|
||||
|
||||
debugAsmEmit(ctxt)
|
||||
|
||||
genFuncInfoSyms(ctxt)
|
||||
|
||||
w := writer{
|
||||
Writer: goobj.NewWriter(b),
|
||||
ctxt: ctxt,
|
||||
pkgpath: objabi.PathToPrefix(ctxt.Pkgpath),
|
||||
}
|
||||
|
||||
start := b.Offset()
|
||||
w.init()
|
||||
|
||||
// Header
|
||||
// We just reserve the space. We'll fill in the offsets later.
|
||||
flags := uint32(0)
|
||||
if ctxt.Flag_shared {
|
||||
flags |= goobj.ObjFlagShared
|
||||
}
|
||||
if w.pkgpath == "" {
|
||||
flags |= goobj.ObjFlagNeedNameExpansion
|
||||
}
|
||||
if ctxt.IsAsm {
|
||||
flags |= goobj.ObjFlagFromAssembly
|
||||
}
|
||||
h := goobj.Header{
|
||||
Magic: goobj.Magic,
|
||||
Fingerprint: ctxt.Fingerprint,
|
||||
Flags: flags,
|
||||
}
|
||||
h.Write(w.Writer)
|
||||
|
||||
// String table
|
||||
w.StringTable()
|
||||
|
||||
// Autolib
|
||||
h.Offsets[goobj.BlkAutolib] = w.Offset()
|
||||
for i := range ctxt.Imports {
|
||||
ctxt.Imports[i].Write(w.Writer)
|
||||
}
|
||||
|
||||
// Package references
|
||||
h.Offsets[goobj.BlkPkgIdx] = w.Offset()
|
||||
for _, pkg := range w.pkglist {
|
||||
w.StringRef(pkg)
|
||||
}
|
||||
|
||||
// File table (for DWARF and pcln generation).
|
||||
h.Offsets[goobj.BlkFile] = w.Offset()
|
||||
for _, f := range ctxt.PosTable.FileTable() {
|
||||
w.StringRef(filepath.ToSlash(f))
|
||||
}
|
||||
|
||||
// Symbol definitions
|
||||
h.Offsets[goobj.BlkSymdef] = w.Offset()
|
||||
for _, s := range ctxt.defs {
|
||||
w.Sym(s)
|
||||
}
|
||||
|
||||
// Short hashed symbol definitions
|
||||
h.Offsets[goobj.BlkHashed64def] = w.Offset()
|
||||
for _, s := range ctxt.hashed64defs {
|
||||
w.Sym(s)
|
||||
}
|
||||
|
||||
// Hashed symbol definitions
|
||||
h.Offsets[goobj.BlkHasheddef] = w.Offset()
|
||||
for _, s := range ctxt.hasheddefs {
|
||||
w.Sym(s)
|
||||
}
|
||||
|
||||
// Non-pkg symbol definitions
|
||||
h.Offsets[goobj.BlkNonpkgdef] = w.Offset()
|
||||
for _, s := range ctxt.nonpkgdefs {
|
||||
w.Sym(s)
|
||||
}
|
||||
|
||||
// Non-pkg symbol references
|
||||
h.Offsets[goobj.BlkNonpkgref] = w.Offset()
|
||||
for _, s := range ctxt.nonpkgrefs {
|
||||
w.Sym(s)
|
||||
}
|
||||
|
||||
// Referenced package symbol flags
|
||||
h.Offsets[goobj.BlkRefFlags] = w.Offset()
|
||||
w.refFlags()
|
||||
|
||||
// Hashes
|
||||
h.Offsets[goobj.BlkHash64] = w.Offset()
|
||||
for _, s := range ctxt.hashed64defs {
|
||||
w.Hash64(s)
|
||||
}
|
||||
h.Offsets[goobj.BlkHash] = w.Offset()
|
||||
for _, s := range ctxt.hasheddefs {
|
||||
w.Hash(s)
|
||||
}
|
||||
// TODO: hashedrefs unused/unsupported for now
|
||||
|
||||
// Reloc indexes
|
||||
h.Offsets[goobj.BlkRelocIdx] = w.Offset()
|
||||
nreloc := uint32(0)
|
||||
lists := [][]*LSym{ctxt.defs, ctxt.hashed64defs, ctxt.hasheddefs, ctxt.nonpkgdefs}
|
||||
for _, list := range lists {
|
||||
for _, s := range list {
|
||||
w.Uint32(nreloc)
|
||||
nreloc += uint32(len(s.R))
|
||||
}
|
||||
}
|
||||
w.Uint32(nreloc)
|
||||
|
||||
// Symbol Info indexes
|
||||
h.Offsets[goobj.BlkAuxIdx] = w.Offset()
|
||||
naux := uint32(0)
|
||||
for _, list := range lists {
|
||||
for _, s := range list {
|
||||
w.Uint32(naux)
|
||||
naux += uint32(nAuxSym(s))
|
||||
}
|
||||
}
|
||||
w.Uint32(naux)
|
||||
|
||||
// Data indexes
|
||||
h.Offsets[goobj.BlkDataIdx] = w.Offset()
|
||||
dataOff := uint32(0)
|
||||
for _, list := range lists {
|
||||
for _, s := range list {
|
||||
w.Uint32(dataOff)
|
||||
dataOff += uint32(len(s.P))
|
||||
}
|
||||
}
|
||||
w.Uint32(dataOff)
|
||||
|
||||
// Relocs
|
||||
h.Offsets[goobj.BlkReloc] = w.Offset()
|
||||
for _, list := range lists {
|
||||
for _, s := range list {
|
||||
for i := range s.R {
|
||||
w.Reloc(&s.R[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Aux symbol info
|
||||
h.Offsets[goobj.BlkAux] = w.Offset()
|
||||
for _, list := range lists {
|
||||
for _, s := range list {
|
||||
w.Aux(s)
|
||||
}
|
||||
}
|
||||
|
||||
// Data
|
||||
h.Offsets[goobj.BlkData] = w.Offset()
|
||||
for _, list := range lists {
|
||||
for _, s := range list {
|
||||
w.Bytes(s.P)
|
||||
}
|
||||
}
|
||||
|
||||
// Pcdata
|
||||
h.Offsets[goobj.BlkPcdata] = w.Offset()
|
||||
for _, s := range ctxt.Text { // iteration order must match genFuncInfoSyms
|
||||
if s.Func != nil {
|
||||
pc := &s.Func.Pcln
|
||||
w.Bytes(pc.Pcsp.P)
|
||||
w.Bytes(pc.Pcfile.P)
|
||||
w.Bytes(pc.Pcline.P)
|
||||
w.Bytes(pc.Pcinline.P)
|
||||
for i := range pc.Pcdata {
|
||||
w.Bytes(pc.Pcdata[i].P)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Blocks used only by tools (objdump, nm).
|
||||
|
||||
// Referenced symbol names from other packages
|
||||
h.Offsets[goobj.BlkRefName] = w.Offset()
|
||||
w.refNames()
|
||||
|
||||
h.Offsets[goobj.BlkEnd] = w.Offset()
|
||||
|
||||
// Fix up block offsets in the header
|
||||
end := start + int64(w.Offset())
|
||||
b.MustSeek(start, 0)
|
||||
h.Write(w.Writer)
|
||||
b.MustSeek(end, 0)
|
||||
}
|
||||
|
||||
type writer struct {
|
||||
*goobj.Writer
|
||||
ctxt *Link
|
||||
pkgpath string // the package import path (escaped), "" if unknown
|
||||
pkglist []string // list of packages referenced, indexed by ctxt.pkgIdx
|
||||
}
|
||||
|
||||
// prepare package index list
|
||||
func (w *writer) init() {
|
||||
w.pkglist = make([]string, len(w.ctxt.pkgIdx)+1)
|
||||
w.pkglist[0] = "" // dummy invalid package for index 0
|
||||
for pkg, i := range w.ctxt.pkgIdx {
|
||||
w.pkglist[i] = pkg
|
||||
}
|
||||
}
|
||||
|
||||
func (w *writer) StringTable() {
|
||||
w.AddString("")
|
||||
for _, p := range w.ctxt.Imports {
|
||||
w.AddString(p.Pkg)
|
||||
}
|
||||
for _, pkg := range w.pkglist {
|
||||
w.AddString(pkg)
|
||||
}
|
||||
w.ctxt.traverseSyms(traverseAll, func(s *LSym) {
|
||||
// TODO: this includes references of indexed symbols from other packages,
|
||||
// for which the linker doesn't need the name. Consider moving them to
|
||||
// a separate block (for tools only).
|
||||
if w.pkgpath != "" {
|
||||
s.Name = strings.Replace(s.Name, "\"\".", w.pkgpath+".", -1)
|
||||
}
|
||||
// Don't put names of builtins into the string table (to save
|
||||
// space).
|
||||
if s.PkgIdx == goobj.PkgIdxBuiltin {
|
||||
return
|
||||
}
|
||||
w.AddString(s.Name)
|
||||
})
|
||||
|
||||
// All filenames are in the postable.
|
||||
for _, f := range w.ctxt.PosTable.FileTable() {
|
||||
w.AddString(filepath.ToSlash(f))
|
||||
}
|
||||
}
|
||||
|
||||
func (w *writer) Sym(s *LSym) {
|
||||
abi := uint16(s.ABI())
|
||||
if s.Static() {
|
||||
abi = goobj.SymABIstatic
|
||||
}
|
||||
flag := uint8(0)
|
||||
if s.DuplicateOK() {
|
||||
flag |= goobj.SymFlagDupok
|
||||
}
|
||||
if s.Local() {
|
||||
flag |= goobj.SymFlagLocal
|
||||
}
|
||||
if s.MakeTypelink() {
|
||||
flag |= goobj.SymFlagTypelink
|
||||
}
|
||||
if s.Leaf() {
|
||||
flag |= goobj.SymFlagLeaf
|
||||
}
|
||||
if s.NoSplit() {
|
||||
flag |= goobj.SymFlagNoSplit
|
||||
}
|
||||
if s.ReflectMethod() {
|
||||
flag |= goobj.SymFlagReflectMethod
|
||||
}
|
||||
if s.TopFrame() {
|
||||
flag |= goobj.SymFlagTopFrame
|
||||
}
|
||||
if strings.HasPrefix(s.Name, "type.") && s.Name[5] != '.' && s.Type == objabi.SRODATA {
|
||||
flag |= goobj.SymFlagGoType
|
||||
}
|
||||
flag2 := uint8(0)
|
||||
if s.UsedInIface() {
|
||||
flag2 |= goobj.SymFlagUsedInIface
|
||||
}
|
||||
if strings.HasPrefix(s.Name, "go.itab.") && s.Type == objabi.SRODATA {
|
||||
flag2 |= goobj.SymFlagItab
|
||||
}
|
||||
name := s.Name
|
||||
if strings.HasPrefix(name, "gofile..") {
|
||||
name = filepath.ToSlash(name)
|
||||
}
|
||||
var align uint32
|
||||
if s.Func != nil {
|
||||
align = uint32(s.Func.Align)
|
||||
}
|
||||
if s.ContentAddressable() {
|
||||
// We generally assume data symbols are natually aligned,
|
||||
// except for strings. If we dedup a string symbol and a
|
||||
// non-string symbol with the same content, we should keep
|
||||
// the largest alignment.
|
||||
// TODO: maybe the compiler could set the alignment for all
|
||||
// data symbols more carefully.
|
||||
if s.Size != 0 && !strings.HasPrefix(s.Name, "go.string.") {
|
||||
switch {
|
||||
case w.ctxt.Arch.PtrSize == 8 && s.Size%8 == 0:
|
||||
align = 8
|
||||
case s.Size%4 == 0:
|
||||
align = 4
|
||||
case s.Size%2 == 0:
|
||||
align = 2
|
||||
}
|
||||
// don't bother setting align to 1.
|
||||
}
|
||||
}
|
||||
var o goobj.Sym
|
||||
o.SetName(name, w.Writer)
|
||||
o.SetABI(abi)
|
||||
o.SetType(uint8(s.Type))
|
||||
o.SetFlag(flag)
|
||||
o.SetFlag2(flag2)
|
||||
o.SetSiz(uint32(s.Size))
|
||||
o.SetAlign(align)
|
||||
o.Write(w.Writer)
|
||||
}
|
||||
|
||||
func (w *writer) Hash64(s *LSym) {
|
||||
if !s.ContentAddressable() || len(s.R) != 0 {
|
||||
panic("Hash of non-content-addresable symbol")
|
||||
}
|
||||
b := contentHash64(s)
|
||||
w.Bytes(b[:])
|
||||
}
|
||||
|
||||
func (w *writer) Hash(s *LSym) {
|
||||
if !s.ContentAddressable() {
|
||||
panic("Hash of non-content-addresable symbol")
|
||||
}
|
||||
b := w.contentHash(s)
|
||||
w.Bytes(b[:])
|
||||
}
|
||||
|
||||
func contentHash64(s *LSym) goobj.Hash64Type {
|
||||
var b goobj.Hash64Type
|
||||
copy(b[:], s.P)
|
||||
return b
|
||||
}
|
||||
|
||||
// Compute the content hash for a content-addressable symbol.
|
||||
// We build a content hash based on its content and relocations.
|
||||
// Depending on the category of the referenced symbol, we choose
|
||||
// different hash algorithms such that the hash is globally
|
||||
// consistent.
|
||||
// - For referenced content-addressable symbol, its content hash
|
||||
// is globally consistent.
|
||||
// - For package symbol and builtin symbol, its local index is
|
||||
// globally consistent.
|
||||
// - For non-package symbol, its fully-expanded name is globally
|
||||
// consistent. For now, we require we know the current package
|
||||
// path so we can always expand symbol names. (Otherwise,
|
||||
// symbols with relocations are not considered hashable.)
|
||||
//
|
||||
// For now, we assume there is no circular dependencies among
|
||||
// hashed symbols.
|
||||
func (w *writer) contentHash(s *LSym) goobj.HashType {
|
||||
h := sha1.New()
|
||||
// The compiler trims trailing zeros _sometimes_. We just do
|
||||
// it always.
|
||||
h.Write(bytes.TrimRight(s.P, "\x00"))
|
||||
var tmp [14]byte
|
||||
for i := range s.R {
|
||||
r := &s.R[i]
|
||||
binary.LittleEndian.PutUint32(tmp[:4], uint32(r.Off))
|
||||
tmp[4] = r.Siz
|
||||
tmp[5] = uint8(r.Type)
|
||||
binary.LittleEndian.PutUint64(tmp[6:14], uint64(r.Add))
|
||||
h.Write(tmp[:])
|
||||
rs := r.Sym
|
||||
switch rs.PkgIdx {
|
||||
case goobj.PkgIdxHashed64:
|
||||
h.Write([]byte{0})
|
||||
t := contentHash64(rs)
|
||||
h.Write(t[:])
|
||||
case goobj.PkgIdxHashed:
|
||||
h.Write([]byte{1})
|
||||
t := w.contentHash(rs)
|
||||
h.Write(t[:])
|
||||
case goobj.PkgIdxNone:
|
||||
h.Write([]byte{2})
|
||||
io.WriteString(h, rs.Name) // name is already expanded at this point
|
||||
case goobj.PkgIdxBuiltin:
|
||||
h.Write([]byte{3})
|
||||
binary.LittleEndian.PutUint32(tmp[:4], uint32(rs.SymIdx))
|
||||
h.Write(tmp[:4])
|
||||
case goobj.PkgIdxSelf:
|
||||
io.WriteString(h, w.pkgpath)
|
||||
binary.LittleEndian.PutUint32(tmp[:4], uint32(rs.SymIdx))
|
||||
h.Write(tmp[:4])
|
||||
default:
|
||||
io.WriteString(h, rs.Pkg)
|
||||
binary.LittleEndian.PutUint32(tmp[:4], uint32(rs.SymIdx))
|
||||
h.Write(tmp[:4])
|
||||
}
|
||||
}
|
||||
var b goobj.HashType
|
||||
copy(b[:], h.Sum(nil))
|
||||
return b
|
||||
}
|
||||
|
||||
func makeSymRef(s *LSym) goobj.SymRef {
|
||||
if s == nil {
|
||||
return goobj.SymRef{}
|
||||
}
|
||||
if s.PkgIdx == 0 || !s.Indexed() {
|
||||
fmt.Printf("unindexed symbol reference: %v\n", s)
|
||||
panic("unindexed symbol reference")
|
||||
}
|
||||
return goobj.SymRef{PkgIdx: uint32(s.PkgIdx), SymIdx: uint32(s.SymIdx)}
|
||||
}
|
||||
|
||||
func (w *writer) Reloc(r *Reloc) {
|
||||
var o goobj.Reloc
|
||||
o.SetOff(r.Off)
|
||||
o.SetSiz(r.Siz)
|
||||
o.SetType(uint8(r.Type))
|
||||
o.SetAdd(r.Add)
|
||||
o.SetSym(makeSymRef(r.Sym))
|
||||
o.Write(w.Writer)
|
||||
}
|
||||
|
||||
func (w *writer) aux1(typ uint8, rs *LSym) {
|
||||
var o goobj.Aux
|
||||
o.SetType(typ)
|
||||
o.SetSym(makeSymRef(rs))
|
||||
o.Write(w.Writer)
|
||||
}
|
||||
|
||||
func (w *writer) Aux(s *LSym) {
|
||||
if s.Gotype != nil {
|
||||
w.aux1(goobj.AuxGotype, s.Gotype)
|
||||
}
|
||||
if s.Func != nil {
|
||||
w.aux1(goobj.AuxFuncInfo, s.Func.FuncInfoSym)
|
||||
|
||||
for _, d := range s.Func.Pcln.Funcdata {
|
||||
w.aux1(goobj.AuxFuncdata, d)
|
||||
}
|
||||
|
||||
if s.Func.dwarfInfoSym != nil && s.Func.dwarfInfoSym.Size != 0 {
|
||||
w.aux1(goobj.AuxDwarfInfo, s.Func.dwarfInfoSym)
|
||||
}
|
||||
if s.Func.dwarfLocSym != nil && s.Func.dwarfLocSym.Size != 0 {
|
||||
w.aux1(goobj.AuxDwarfLoc, s.Func.dwarfLocSym)
|
||||
}
|
||||
if s.Func.dwarfRangesSym != nil && s.Func.dwarfRangesSym.Size != 0 {
|
||||
w.aux1(goobj.AuxDwarfRanges, s.Func.dwarfRangesSym)
|
||||
}
|
||||
if s.Func.dwarfDebugLinesSym != nil && s.Func.dwarfDebugLinesSym.Size != 0 {
|
||||
w.aux1(goobj.AuxDwarfLines, s.Func.dwarfDebugLinesSym)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Emits flags of referenced indexed symbols.
|
||||
func (w *writer) refFlags() {
|
||||
seen := make(map[*LSym]bool)
|
||||
w.ctxt.traverseSyms(traverseRefs, func(rs *LSym) { // only traverse refs, not auxs, as tools don't need auxs
|
||||
switch rs.PkgIdx {
|
||||
case goobj.PkgIdxNone, goobj.PkgIdxHashed64, goobj.PkgIdxHashed, goobj.PkgIdxBuiltin, goobj.PkgIdxSelf: // not an external indexed reference
|
||||
return
|
||||
case goobj.PkgIdxInvalid:
|
||||
panic("unindexed symbol reference")
|
||||
}
|
||||
if seen[rs] {
|
||||
return
|
||||
}
|
||||
seen[rs] = true
|
||||
symref := makeSymRef(rs)
|
||||
flag2 := uint8(0)
|
||||
if rs.UsedInIface() {
|
||||
flag2 |= goobj.SymFlagUsedInIface
|
||||
}
|
||||
if flag2 == 0 {
|
||||
return // no need to write zero flags
|
||||
}
|
||||
var o goobj.RefFlags
|
||||
o.SetSym(symref)
|
||||
o.SetFlag2(flag2)
|
||||
o.Write(w.Writer)
|
||||
})
|
||||
}
|
||||
|
||||
// Emits names of referenced indexed symbols, used by tools (objdump, nm)
|
||||
// only.
|
||||
func (w *writer) refNames() {
|
||||
seen := make(map[*LSym]bool)
|
||||
w.ctxt.traverseSyms(traverseRefs, func(rs *LSym) { // only traverse refs, not auxs, as tools don't need auxs
|
||||
switch rs.PkgIdx {
|
||||
case goobj.PkgIdxNone, goobj.PkgIdxHashed64, goobj.PkgIdxHashed, goobj.PkgIdxBuiltin, goobj.PkgIdxSelf: // not an external indexed reference
|
||||
return
|
||||
case goobj.PkgIdxInvalid:
|
||||
panic("unindexed symbol reference")
|
||||
}
|
||||
if seen[rs] {
|
||||
return
|
||||
}
|
||||
seen[rs] = true
|
||||
symref := makeSymRef(rs)
|
||||
var o goobj.RefName
|
||||
o.SetSym(symref)
|
||||
o.SetName(rs.Name, w.Writer)
|
||||
o.Write(w.Writer)
|
||||
})
|
||||
// TODO: output in sorted order?
|
||||
// Currently tools (cmd/internal/goobj package) doesn't use mmap,
|
||||
// and it just read it into a map in memory upfront. If it uses
|
||||
// mmap, if the output is sorted, it probably could avoid reading
|
||||
// into memory and just do lookups in the mmap'd object file.
|
||||
}
|
||||
|
||||
// return the number of aux symbols s have.
|
||||
func nAuxSym(s *LSym) int {
|
||||
n := 0
|
||||
if s.Gotype != nil {
|
||||
n++
|
||||
}
|
||||
if s.Func != nil {
|
||||
// FuncInfo is an aux symbol, each Funcdata is an aux symbol
|
||||
n += 1 + len(s.Func.Pcln.Funcdata)
|
||||
if s.Func.dwarfInfoSym != nil && s.Func.dwarfInfoSym.Size != 0 {
|
||||
n++
|
||||
}
|
||||
if s.Func.dwarfLocSym != nil && s.Func.dwarfLocSym.Size != 0 {
|
||||
n++
|
||||
}
|
||||
if s.Func.dwarfRangesSym != nil && s.Func.dwarfRangesSym.Size != 0 {
|
||||
n++
|
||||
}
|
||||
if s.Func.dwarfDebugLinesSym != nil && s.Func.dwarfDebugLinesSym.Size != 0 {
|
||||
n++
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// generate symbols for FuncInfo.
|
||||
func genFuncInfoSyms(ctxt *Link) {
|
||||
infosyms := make([]*LSym, 0, len(ctxt.Text))
|
||||
var pcdataoff uint32
|
||||
var b bytes.Buffer
|
||||
symidx := int32(len(ctxt.defs))
|
||||
for _, s := range ctxt.Text {
|
||||
if s.Func == nil {
|
||||
continue
|
||||
}
|
||||
o := goobj.FuncInfo{
|
||||
Args: uint32(s.Func.Args),
|
||||
Locals: uint32(s.Func.Locals),
|
||||
FuncID: objabi.FuncID(s.Func.FuncID),
|
||||
}
|
||||
pc := &s.Func.Pcln
|
||||
o.Pcsp = pcdataoff
|
||||
pcdataoff += uint32(len(pc.Pcsp.P))
|
||||
o.Pcfile = pcdataoff
|
||||
pcdataoff += uint32(len(pc.Pcfile.P))
|
||||
o.Pcline = pcdataoff
|
||||
pcdataoff += uint32(len(pc.Pcline.P))
|
||||
o.Pcinline = pcdataoff
|
||||
pcdataoff += uint32(len(pc.Pcinline.P))
|
||||
o.Pcdata = make([]uint32, len(pc.Pcdata))
|
||||
for i, pcd := range pc.Pcdata {
|
||||
o.Pcdata[i] = pcdataoff
|
||||
pcdataoff += uint32(len(pcd.P))
|
||||
}
|
||||
o.PcdataEnd = pcdataoff
|
||||
o.Funcdataoff = make([]uint32, len(pc.Funcdataoff))
|
||||
for i, x := range pc.Funcdataoff {
|
||||
o.Funcdataoff[i] = uint32(x)
|
||||
}
|
||||
i := 0
|
||||
o.File = make([]goobj.CUFileIndex, len(pc.UsedFiles))
|
||||
for f := range pc.UsedFiles {
|
||||
o.File[i] = f
|
||||
i++
|
||||
}
|
||||
sort.Slice(o.File, func(i, j int) bool { return o.File[i] < o.File[j] })
|
||||
o.InlTree = make([]goobj.InlTreeNode, len(pc.InlTree.nodes))
|
||||
for i, inl := range pc.InlTree.nodes {
|
||||
f, l := getFileIndexAndLine(ctxt, inl.Pos)
|
||||
o.InlTree[i] = goobj.InlTreeNode{
|
||||
Parent: int32(inl.Parent),
|
||||
File: goobj.CUFileIndex(f),
|
||||
Line: l,
|
||||
Func: makeSymRef(inl.Func),
|
||||
ParentPC: inl.ParentPC,
|
||||
}
|
||||
}
|
||||
|
||||
o.Write(&b)
|
||||
isym := &LSym{
|
||||
Type: objabi.SDATA, // for now, I don't think it matters
|
||||
PkgIdx: goobj.PkgIdxSelf,
|
||||
SymIdx: symidx,
|
||||
P: append([]byte(nil), b.Bytes()...),
|
||||
}
|
||||
isym.Set(AttrIndexed, true)
|
||||
symidx++
|
||||
infosyms = append(infosyms, isym)
|
||||
s.Func.FuncInfoSym = isym
|
||||
b.Reset()
|
||||
|
||||
dwsyms := []*LSym{s.Func.dwarfRangesSym, s.Func.dwarfLocSym, s.Func.dwarfDebugLinesSym, s.Func.dwarfInfoSym}
|
||||
for _, s := range dwsyms {
|
||||
if s == nil || s.Size == 0 {
|
||||
continue
|
||||
}
|
||||
s.PkgIdx = goobj.PkgIdxSelf
|
||||
s.SymIdx = symidx
|
||||
s.Set(AttrIndexed, true)
|
||||
symidx++
|
||||
infosyms = append(infosyms, s)
|
||||
}
|
||||
}
|
||||
ctxt.defs = append(ctxt.defs, infosyms...)
|
||||
}
|
||||
|
||||
// debugDumpAux is a dumper for selected aux symbols.
|
||||
func writeAuxSymDebug(ctxt *Link, par *LSym, aux *LSym) {
|
||||
// Most aux symbols (ex: funcdata) are not interesting--
|
||||
// pick out just the DWARF ones for now.
|
||||
if aux.Type != objabi.SDWARFLOC &&
|
||||
aux.Type != objabi.SDWARFFCN &&
|
||||
aux.Type != objabi.SDWARFABSFCN &&
|
||||
aux.Type != objabi.SDWARFLINES &&
|
||||
aux.Type != objabi.SDWARFRANGE {
|
||||
return
|
||||
}
|
||||
ctxt.writeSymDebugNamed(aux, "aux for "+par.Name)
|
||||
}
|
||||
|
||||
func debugAsmEmit(ctxt *Link) {
|
||||
if ctxt.Debugasm > 0 {
|
||||
ctxt.traverseSyms(traverseDefs, ctxt.writeSymDebug)
|
||||
if ctxt.Debugasm > 1 {
|
||||
fn := func(par *LSym, aux *LSym) {
|
||||
writeAuxSymDebug(ctxt, par, aux)
|
||||
}
|
||||
ctxt.traverseAuxSyms(traverseAux, fn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ctxt *Link) writeSymDebug(s *LSym) {
|
||||
ctxt.writeSymDebugNamed(s, s.Name)
|
||||
}
|
||||
|
||||
func (ctxt *Link) writeSymDebugNamed(s *LSym, name string) {
|
||||
ver := ""
|
||||
if ctxt.Debugasm > 1 {
|
||||
ver = fmt.Sprintf("<%d>", s.ABI())
|
||||
}
|
||||
fmt.Fprintf(ctxt.Bso, "%s%s ", name, ver)
|
||||
if s.Type != 0 {
|
||||
fmt.Fprintf(ctxt.Bso, "%v ", s.Type)
|
||||
}
|
||||
if s.Static() {
|
||||
fmt.Fprint(ctxt.Bso, "static ")
|
||||
}
|
||||
if s.DuplicateOK() {
|
||||
fmt.Fprintf(ctxt.Bso, "dupok ")
|
||||
}
|
||||
if s.CFunc() {
|
||||
fmt.Fprintf(ctxt.Bso, "cfunc ")
|
||||
}
|
||||
if s.NoSplit() {
|
||||
fmt.Fprintf(ctxt.Bso, "nosplit ")
|
||||
}
|
||||
if s.TopFrame() {
|
||||
fmt.Fprintf(ctxt.Bso, "topframe ")
|
||||
}
|
||||
fmt.Fprintf(ctxt.Bso, "size=%d", s.Size)
|
||||
if s.Type == objabi.STEXT {
|
||||
fmt.Fprintf(ctxt.Bso, " args=%#x locals=%#x funcid=%#x", uint64(s.Func.Args), uint64(s.Func.Locals), uint64(s.Func.FuncID))
|
||||
if s.Leaf() {
|
||||
fmt.Fprintf(ctxt.Bso, " leaf")
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(ctxt.Bso, "\n")
|
||||
if s.Type == objabi.STEXT {
|
||||
for p := s.Func.Text; p != nil; p = p.Link {
|
||||
fmt.Fprintf(ctxt.Bso, "\t%#04x ", uint(int(p.Pc)))
|
||||
if ctxt.Debugasm > 1 {
|
||||
io.WriteString(ctxt.Bso, p.String())
|
||||
} else {
|
||||
p.InnermostString(ctxt.Bso)
|
||||
}
|
||||
fmt.Fprintln(ctxt.Bso)
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(s.P); i += 16 {
|
||||
fmt.Fprintf(ctxt.Bso, "\t%#04x", uint(i))
|
||||
j := i
|
||||
for ; j < i+16 && j < len(s.P); j++ {
|
||||
fmt.Fprintf(ctxt.Bso, " %02x", s.P[j])
|
||||
}
|
||||
for ; j < i+16; j++ {
|
||||
fmt.Fprintf(ctxt.Bso, " ")
|
||||
}
|
||||
fmt.Fprintf(ctxt.Bso, " ")
|
||||
for j = i; j < i+16 && j < len(s.P); j++ {
|
||||
c := int(s.P[j])
|
||||
b := byte('.')
|
||||
if ' ' <= c && c <= 0x7e {
|
||||
b = byte(c)
|
||||
}
|
||||
ctxt.Bso.WriteByte(b)
|
||||
}
|
||||
|
||||
fmt.Fprintf(ctxt.Bso, "\n")
|
||||
}
|
||||
|
||||
sort.Sort(relocByOff(s.R)) // generate stable output
|
||||
for _, r := range s.R {
|
||||
name := ""
|
||||
ver := ""
|
||||
if r.Sym != nil {
|
||||
name = r.Sym.Name
|
||||
if ctxt.Debugasm > 1 {
|
||||
ver = fmt.Sprintf("<%d>", s.ABI())
|
||||
}
|
||||
} else if r.Type == objabi.R_TLS_LE {
|
||||
name = "TLS"
|
||||
}
|
||||
if ctxt.Arch.InFamily(sys.ARM, sys.PPC64) {
|
||||
fmt.Fprintf(ctxt.Bso, "\trel %d+%d t=%d %s%s+%x\n", int(r.Off), r.Siz, r.Type, name, ver, uint64(r.Add))
|
||||
} else {
|
||||
fmt.Fprintf(ctxt.Bso, "\trel %d+%d t=%d %s%s+%d\n", int(r.Off), r.Siz, r.Type, name, ver, r.Add)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// relocByOff sorts relocations by their offsets.
|
||||
type relocByOff []Reloc
|
||||
|
||||
func (x relocByOff) Len() int { return len(x) }
|
||||
func (x relocByOff) Less(i, j int) bool { return x[i].Off < x[j].Off }
|
||||
func (x relocByOff) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||
176
vendor/github.com/twitchyliquid64/golang-asm/obj/pass.go
generated
vendored
Normal file
176
vendor/github.com/twitchyliquid64/golang-asm/obj/pass.go
generated
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
// Inferno utils/6l/pass.c
|
||||
// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/pass.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package obj
|
||||
|
||||
// Code and data passes.
|
||||
|
||||
// brloop returns the ultimate destination of the series of unconditional jumps beginning at p.
|
||||
// In the case of an infinite loop, brloop returns nil.
|
||||
func brloop(p *Prog) *Prog {
|
||||
c := 0
|
||||
for q := p; q != nil; q = q.To.Target() {
|
||||
if q.As != AJMP || q.To.Target() == nil {
|
||||
return q
|
||||
}
|
||||
c++
|
||||
if c >= 5000 {
|
||||
// infinite loop
|
||||
return nil
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// checkaddr checks that a has an expected encoding, especially TYPE_CONST vs TYPE_ADDR.
|
||||
func checkaddr(ctxt *Link, p *Prog, a *Addr) {
|
||||
switch a.Type {
|
||||
case TYPE_NONE, TYPE_REGREG2, TYPE_REGLIST:
|
||||
return
|
||||
|
||||
case TYPE_BRANCH, TYPE_TEXTSIZE:
|
||||
if a.Reg != 0 || a.Index != 0 || a.Scale != 0 || a.Name != 0 {
|
||||
break
|
||||
}
|
||||
return
|
||||
|
||||
case TYPE_MEM:
|
||||
return
|
||||
|
||||
case TYPE_CONST:
|
||||
// TODO(rsc): After fixing SHRQ, check a.Index != 0 too.
|
||||
if a.Name != 0 || a.Sym != nil || a.Reg != 0 {
|
||||
ctxt.Diag("argument is TYPE_CONST, should be TYPE_ADDR, in %v", p)
|
||||
return
|
||||
}
|
||||
|
||||
if a.Reg != 0 || a.Scale != 0 || a.Name != 0 || a.Sym != nil || a.Val != nil {
|
||||
break
|
||||
}
|
||||
return
|
||||
|
||||
case TYPE_FCONST, TYPE_SCONST:
|
||||
if a.Reg != 0 || a.Index != 0 || a.Scale != 0 || a.Name != 0 || a.Offset != 0 || a.Sym != nil {
|
||||
break
|
||||
}
|
||||
return
|
||||
|
||||
case TYPE_REG:
|
||||
// TODO(rsc): After fixing PINSRQ, check a.Offset != 0 too.
|
||||
// TODO(rsc): After fixing SHRQ, check a.Index != 0 too.
|
||||
if a.Scale != 0 || a.Name != 0 || a.Sym != nil {
|
||||
break
|
||||
}
|
||||
return
|
||||
|
||||
case TYPE_ADDR:
|
||||
if a.Val != nil {
|
||||
break
|
||||
}
|
||||
if a.Reg == 0 && a.Index == 0 && a.Scale == 0 && a.Name == 0 && a.Sym == nil {
|
||||
ctxt.Diag("argument is TYPE_ADDR, should be TYPE_CONST, in %v", p)
|
||||
}
|
||||
return
|
||||
|
||||
case TYPE_SHIFT, TYPE_REGREG:
|
||||
if a.Index != 0 || a.Scale != 0 || a.Name != 0 || a.Sym != nil || a.Val != nil {
|
||||
break
|
||||
}
|
||||
return
|
||||
|
||||
case TYPE_INDIR:
|
||||
// Expect sym and name to be set, nothing else.
|
||||
// Technically more is allowed, but this is only used for *name(SB).
|
||||
if a.Reg != 0 || a.Index != 0 || a.Scale != 0 || a.Name == 0 || a.Offset != 0 || a.Sym == nil || a.Val != nil {
|
||||
break
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctxt.Diag("invalid encoding for argument %v", p)
|
||||
}
|
||||
|
||||
func linkpatch(ctxt *Link, sym *LSym, newprog ProgAlloc) {
|
||||
for p := sym.Func.Text; p != nil; p = p.Link {
|
||||
checkaddr(ctxt, p, &p.From)
|
||||
if p.GetFrom3() != nil {
|
||||
checkaddr(ctxt, p, p.GetFrom3())
|
||||
}
|
||||
checkaddr(ctxt, p, &p.To)
|
||||
|
||||
if ctxt.Arch.Progedit != nil {
|
||||
ctxt.Arch.Progedit(ctxt, p, newprog)
|
||||
}
|
||||
if p.To.Type != TYPE_BRANCH {
|
||||
continue
|
||||
}
|
||||
if p.To.Val != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if p.To.Sym != nil {
|
||||
continue
|
||||
}
|
||||
q := sym.Func.Text
|
||||
for q != nil && p.To.Offset != q.Pc {
|
||||
if q.Forwd != nil && p.To.Offset >= q.Forwd.Pc {
|
||||
q = q.Forwd
|
||||
} else {
|
||||
q = q.Link
|
||||
}
|
||||
}
|
||||
|
||||
if q == nil {
|
||||
name := "<nil>"
|
||||
if p.To.Sym != nil {
|
||||
name = p.To.Sym.Name
|
||||
}
|
||||
ctxt.Diag("branch out of range (%#x)\n%v [%s]", uint32(p.To.Offset), p, name)
|
||||
p.To.Type = TYPE_NONE
|
||||
}
|
||||
|
||||
p.To.SetTarget(q)
|
||||
}
|
||||
|
||||
if !ctxt.Flag_optimize {
|
||||
return
|
||||
}
|
||||
|
||||
// Collapse series of jumps to jumps.
|
||||
for p := sym.Func.Text; p != nil; p = p.Link {
|
||||
if p.To.Target() == nil {
|
||||
continue
|
||||
}
|
||||
p.To.SetTarget(brloop(p.To.Target()))
|
||||
if p.To.Target() != nil && p.To.Type == TYPE_BRANCH {
|
||||
p.To.Offset = p.To.Target().Pc
|
||||
}
|
||||
}
|
||||
}
|
||||
413
vendor/github.com/twitchyliquid64/golang-asm/obj/pcln.go
generated
vendored
Normal file
413
vendor/github.com/twitchyliquid64/golang-asm/obj/pcln.go
generated
vendored
Normal file
@@ -0,0 +1,413 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package obj
|
||||
|
||||
import (
|
||||
"github.com/twitchyliquid64/golang-asm/goobj"
|
||||
"encoding/binary"
|
||||
"log"
|
||||
)
|
||||
|
||||
// funcpctab writes to dst a pc-value table mapping the code in func to the values
|
||||
// returned by valfunc parameterized by arg. The invocation of valfunc to update the
|
||||
// current value is, for each p,
|
||||
//
|
||||
// val = valfunc(func, val, p, 0, arg);
|
||||
// record val as value at p->pc;
|
||||
// val = valfunc(func, val, p, 1, arg);
|
||||
//
|
||||
// where func is the function, val is the current value, p is the instruction being
|
||||
// considered, and arg can be used to further parameterize valfunc.
|
||||
func funcpctab(ctxt *Link, dst *Pcdata, func_ *LSym, desc string, valfunc func(*Link, *LSym, int32, *Prog, int32, interface{}) int32, arg interface{}) {
|
||||
dbg := desc == ctxt.Debugpcln
|
||||
|
||||
dst.P = dst.P[:0]
|
||||
|
||||
if dbg {
|
||||
ctxt.Logf("funcpctab %s [valfunc=%s]\n", func_.Name, desc)
|
||||
}
|
||||
|
||||
val := int32(-1)
|
||||
oldval := val
|
||||
if func_.Func.Text == nil {
|
||||
return
|
||||
}
|
||||
|
||||
pc := func_.Func.Text.Pc
|
||||
|
||||
if dbg {
|
||||
ctxt.Logf("%6x %6d %v\n", uint64(pc), val, func_.Func.Text)
|
||||
}
|
||||
|
||||
buf := make([]byte, binary.MaxVarintLen32)
|
||||
started := false
|
||||
for p := func_.Func.Text; p != nil; p = p.Link {
|
||||
// Update val. If it's not changing, keep going.
|
||||
val = valfunc(ctxt, func_, val, p, 0, arg)
|
||||
|
||||
if val == oldval && started {
|
||||
val = valfunc(ctxt, func_, val, p, 1, arg)
|
||||
if dbg {
|
||||
ctxt.Logf("%6x %6s %v\n", uint64(p.Pc), "", p)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// If the pc of the next instruction is the same as the
|
||||
// pc of this instruction, this instruction is not a real
|
||||
// instruction. Keep going, so that we only emit a delta
|
||||
// for a true instruction boundary in the program.
|
||||
if p.Link != nil && p.Link.Pc == p.Pc {
|
||||
val = valfunc(ctxt, func_, val, p, 1, arg)
|
||||
if dbg {
|
||||
ctxt.Logf("%6x %6s %v\n", uint64(p.Pc), "", p)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// The table is a sequence of (value, pc) pairs, where each
|
||||
// pair states that the given value is in effect from the current position
|
||||
// up to the given pc, which becomes the new current position.
|
||||
// To generate the table as we scan over the program instructions,
|
||||
// we emit a "(value" when pc == func->value, and then
|
||||
// each time we observe a change in value we emit ", pc) (value".
|
||||
// When the scan is over, we emit the closing ", pc)".
|
||||
//
|
||||
// The table is delta-encoded. The value deltas are signed and
|
||||
// transmitted in zig-zag form, where a complement bit is placed in bit 0,
|
||||
// and the pc deltas are unsigned. Both kinds of deltas are sent
|
||||
// as variable-length little-endian base-128 integers,
|
||||
// where the 0x80 bit indicates that the integer continues.
|
||||
|
||||
if dbg {
|
||||
ctxt.Logf("%6x %6d %v\n", uint64(p.Pc), val, p)
|
||||
}
|
||||
|
||||
if started {
|
||||
pcdelta := (p.Pc - pc) / int64(ctxt.Arch.MinLC)
|
||||
n := binary.PutUvarint(buf, uint64(pcdelta))
|
||||
dst.P = append(dst.P, buf[:n]...)
|
||||
pc = p.Pc
|
||||
}
|
||||
|
||||
delta := val - oldval
|
||||
n := binary.PutVarint(buf, int64(delta))
|
||||
dst.P = append(dst.P, buf[:n]...)
|
||||
oldval = val
|
||||
started = true
|
||||
val = valfunc(ctxt, func_, val, p, 1, arg)
|
||||
}
|
||||
|
||||
if started {
|
||||
if dbg {
|
||||
ctxt.Logf("%6x done\n", uint64(func_.Func.Text.Pc+func_.Size))
|
||||
}
|
||||
v := (func_.Size - pc) / int64(ctxt.Arch.MinLC)
|
||||
if v < 0 {
|
||||
ctxt.Diag("negative pc offset: %v", v)
|
||||
}
|
||||
n := binary.PutUvarint(buf, uint64(v))
|
||||
dst.P = append(dst.P, buf[:n]...)
|
||||
// add terminating varint-encoded 0, which is just 0
|
||||
dst.P = append(dst.P, 0)
|
||||
}
|
||||
|
||||
if dbg {
|
||||
ctxt.Logf("wrote %d bytes to %p\n", len(dst.P), dst)
|
||||
for _, p := range dst.P {
|
||||
ctxt.Logf(" %02x", p)
|
||||
}
|
||||
ctxt.Logf("\n")
|
||||
}
|
||||
}
|
||||
|
||||
// pctofileline computes either the file number (arg == 0)
|
||||
// or the line number (arg == 1) to use at p.
|
||||
// Because p.Pos applies to p, phase == 0 (before p)
|
||||
// takes care of the update.
|
||||
func pctofileline(ctxt *Link, sym *LSym, oldval int32, p *Prog, phase int32, arg interface{}) int32 {
|
||||
if p.As == ATEXT || p.As == ANOP || p.Pos.Line() == 0 || phase == 1 {
|
||||
return oldval
|
||||
}
|
||||
f, l := getFileIndexAndLine(ctxt, p.Pos)
|
||||
if arg == nil {
|
||||
return l
|
||||
}
|
||||
pcln := arg.(*Pcln)
|
||||
pcln.UsedFiles[goobj.CUFileIndex(f)] = struct{}{}
|
||||
return int32(f)
|
||||
}
|
||||
|
||||
// pcinlineState holds the state used to create a function's inlining
|
||||
// tree and the PC-value table that maps PCs to nodes in that tree.
|
||||
type pcinlineState struct {
|
||||
globalToLocal map[int]int
|
||||
localTree InlTree
|
||||
}
|
||||
|
||||
// addBranch adds a branch from the global inlining tree in ctxt to
|
||||
// the function's local inlining tree, returning the index in the local tree.
|
||||
func (s *pcinlineState) addBranch(ctxt *Link, globalIndex int) int {
|
||||
if globalIndex < 0 {
|
||||
return -1
|
||||
}
|
||||
|
||||
localIndex, ok := s.globalToLocal[globalIndex]
|
||||
if ok {
|
||||
return localIndex
|
||||
}
|
||||
|
||||
// Since tracebacks don't include column information, we could
|
||||
// use one node for multiple calls of the same function on the
|
||||
// same line (e.g., f(x) + f(y)). For now, we use one node for
|
||||
// each inlined call.
|
||||
call := ctxt.InlTree.nodes[globalIndex]
|
||||
call.Parent = s.addBranch(ctxt, call.Parent)
|
||||
localIndex = len(s.localTree.nodes)
|
||||
s.localTree.nodes = append(s.localTree.nodes, call)
|
||||
s.globalToLocal[globalIndex] = localIndex
|
||||
return localIndex
|
||||
}
|
||||
|
||||
func (s *pcinlineState) setParentPC(ctxt *Link, globalIndex int, pc int32) {
|
||||
localIndex, ok := s.globalToLocal[globalIndex]
|
||||
if !ok {
|
||||
// We know where to unwind to when we need to unwind a body identified
|
||||
// by globalIndex. But there may be no instructions generated by that
|
||||
// body (it's empty, or its instructions were CSEd with other things, etc.).
|
||||
// In that case, we don't need an unwind entry.
|
||||
// TODO: is this really right? Seems to happen a whole lot...
|
||||
return
|
||||
}
|
||||
s.localTree.setParentPC(localIndex, pc)
|
||||
}
|
||||
|
||||
// pctoinline computes the index into the local inlining tree to use at p.
|
||||
// If p is not the result of inlining, pctoinline returns -1. Because p.Pos
|
||||
// applies to p, phase == 0 (before p) takes care of the update.
|
||||
func (s *pcinlineState) pctoinline(ctxt *Link, sym *LSym, oldval int32, p *Prog, phase int32, arg interface{}) int32 {
|
||||
if phase == 1 {
|
||||
return oldval
|
||||
}
|
||||
|
||||
posBase := ctxt.PosTable.Pos(p.Pos).Base()
|
||||
if posBase == nil {
|
||||
return -1
|
||||
}
|
||||
|
||||
globalIndex := posBase.InliningIndex()
|
||||
if globalIndex < 0 {
|
||||
return -1
|
||||
}
|
||||
|
||||
if s.globalToLocal == nil {
|
||||
s.globalToLocal = make(map[int]int)
|
||||
}
|
||||
|
||||
return int32(s.addBranch(ctxt, globalIndex))
|
||||
}
|
||||
|
||||
// pctospadj computes the sp adjustment in effect.
|
||||
// It is oldval plus any adjustment made by p itself.
|
||||
// The adjustment by p takes effect only after p, so we
|
||||
// apply the change during phase == 1.
|
||||
func pctospadj(ctxt *Link, sym *LSym, oldval int32, p *Prog, phase int32, arg interface{}) int32 {
|
||||
if oldval == -1 { // starting
|
||||
oldval = 0
|
||||
}
|
||||
if phase == 0 {
|
||||
return oldval
|
||||
}
|
||||
if oldval+p.Spadj < -10000 || oldval+p.Spadj > 1100000000 {
|
||||
ctxt.Diag("overflow in spadj: %d + %d = %d", oldval, p.Spadj, oldval+p.Spadj)
|
||||
ctxt.DiagFlush()
|
||||
log.Fatalf("bad code")
|
||||
}
|
||||
|
||||
return oldval + p.Spadj
|
||||
}
|
||||
|
||||
// pctopcdata computes the pcdata value in effect at p.
|
||||
// A PCDATA instruction sets the value in effect at future
|
||||
// non-PCDATA instructions.
|
||||
// Since PCDATA instructions have no width in the final code,
|
||||
// it does not matter which phase we use for the update.
|
||||
func pctopcdata(ctxt *Link, sym *LSym, oldval int32, p *Prog, phase int32, arg interface{}) int32 {
|
||||
if phase == 0 || p.As != APCDATA || p.From.Offset != int64(arg.(uint32)) {
|
||||
return oldval
|
||||
}
|
||||
if int64(int32(p.To.Offset)) != p.To.Offset {
|
||||
ctxt.Diag("overflow in PCDATA instruction: %v", p)
|
||||
ctxt.DiagFlush()
|
||||
log.Fatalf("bad code")
|
||||
}
|
||||
|
||||
return int32(p.To.Offset)
|
||||
}
|
||||
|
||||
func linkpcln(ctxt *Link, cursym *LSym) {
|
||||
pcln := &cursym.Func.Pcln
|
||||
pcln.UsedFiles = make(map[goobj.CUFileIndex]struct{})
|
||||
|
||||
npcdata := 0
|
||||
nfuncdata := 0
|
||||
for p := cursym.Func.Text; p != nil; p = p.Link {
|
||||
// Find the highest ID of any used PCDATA table. This ignores PCDATA table
|
||||
// that consist entirely of "-1", since that's the assumed default value.
|
||||
// From.Offset is table ID
|
||||
// To.Offset is data
|
||||
if p.As == APCDATA && p.From.Offset >= int64(npcdata) && p.To.Offset != -1 { // ignore -1 as we start at -1, if we only see -1, nothing changed
|
||||
npcdata = int(p.From.Offset + 1)
|
||||
}
|
||||
// Find the highest ID of any FUNCDATA table.
|
||||
// From.Offset is table ID
|
||||
if p.As == AFUNCDATA && p.From.Offset >= int64(nfuncdata) {
|
||||
nfuncdata = int(p.From.Offset + 1)
|
||||
}
|
||||
}
|
||||
|
||||
pcln.Pcdata = make([]Pcdata, npcdata)
|
||||
pcln.Pcdata = pcln.Pcdata[:npcdata]
|
||||
pcln.Funcdata = make([]*LSym, nfuncdata)
|
||||
pcln.Funcdataoff = make([]int64, nfuncdata)
|
||||
pcln.Funcdataoff = pcln.Funcdataoff[:nfuncdata]
|
||||
|
||||
funcpctab(ctxt, &pcln.Pcsp, cursym, "pctospadj", pctospadj, nil)
|
||||
funcpctab(ctxt, &pcln.Pcfile, cursym, "pctofile", pctofileline, pcln)
|
||||
funcpctab(ctxt, &pcln.Pcline, cursym, "pctoline", pctofileline, nil)
|
||||
|
||||
// Check that all the Progs used as inline markers are still reachable.
|
||||
// See issue #40473.
|
||||
inlMarkProgs := make(map[*Prog]struct{}, len(cursym.Func.InlMarks))
|
||||
for _, inlMark := range cursym.Func.InlMarks {
|
||||
inlMarkProgs[inlMark.p] = struct{}{}
|
||||
}
|
||||
for p := cursym.Func.Text; p != nil; p = p.Link {
|
||||
if _, ok := inlMarkProgs[p]; ok {
|
||||
delete(inlMarkProgs, p)
|
||||
}
|
||||
}
|
||||
if len(inlMarkProgs) > 0 {
|
||||
ctxt.Diag("one or more instructions used as inline markers are no longer reachable")
|
||||
}
|
||||
|
||||
pcinlineState := new(pcinlineState)
|
||||
funcpctab(ctxt, &pcln.Pcinline, cursym, "pctoinline", pcinlineState.pctoinline, nil)
|
||||
for _, inlMark := range cursym.Func.InlMarks {
|
||||
pcinlineState.setParentPC(ctxt, int(inlMark.id), int32(inlMark.p.Pc))
|
||||
}
|
||||
pcln.InlTree = pcinlineState.localTree
|
||||
if ctxt.Debugpcln == "pctoinline" && len(pcln.InlTree.nodes) > 0 {
|
||||
ctxt.Logf("-- inlining tree for %s:\n", cursym)
|
||||
dumpInlTree(ctxt, pcln.InlTree)
|
||||
ctxt.Logf("--\n")
|
||||
}
|
||||
|
||||
// tabulate which pc and func data we have.
|
||||
havepc := make([]uint32, (npcdata+31)/32)
|
||||
havefunc := make([]uint32, (nfuncdata+31)/32)
|
||||
for p := cursym.Func.Text; p != nil; p = p.Link {
|
||||
if p.As == AFUNCDATA {
|
||||
if (havefunc[p.From.Offset/32]>>uint64(p.From.Offset%32))&1 != 0 {
|
||||
ctxt.Diag("multiple definitions for FUNCDATA $%d", p.From.Offset)
|
||||
}
|
||||
havefunc[p.From.Offset/32] |= 1 << uint64(p.From.Offset%32)
|
||||
}
|
||||
|
||||
if p.As == APCDATA && p.To.Offset != -1 {
|
||||
havepc[p.From.Offset/32] |= 1 << uint64(p.From.Offset%32)
|
||||
}
|
||||
}
|
||||
|
||||
// pcdata.
|
||||
for i := 0; i < npcdata; i++ {
|
||||
if (havepc[i/32]>>uint(i%32))&1 == 0 {
|
||||
continue
|
||||
}
|
||||
funcpctab(ctxt, &pcln.Pcdata[i], cursym, "pctopcdata", pctopcdata, interface{}(uint32(i)))
|
||||
}
|
||||
|
||||
// funcdata
|
||||
if nfuncdata > 0 {
|
||||
for p := cursym.Func.Text; p != nil; p = p.Link {
|
||||
if p.As != AFUNCDATA {
|
||||
continue
|
||||
}
|
||||
i := int(p.From.Offset)
|
||||
pcln.Funcdataoff[i] = p.To.Offset
|
||||
if p.To.Type != TYPE_CONST {
|
||||
// TODO: Dedup.
|
||||
//funcdata_bytes += p->to.sym->size;
|
||||
pcln.Funcdata[i] = p.To.Sym
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PCIter iterates over encoded pcdata tables.
|
||||
type PCIter struct {
|
||||
p []byte
|
||||
PC uint32
|
||||
NextPC uint32
|
||||
PCScale uint32
|
||||
Value int32
|
||||
start bool
|
||||
Done bool
|
||||
}
|
||||
|
||||
// newPCIter creates a PCIter with a scale factor for the PC step size.
|
||||
func NewPCIter(pcScale uint32) *PCIter {
|
||||
it := new(PCIter)
|
||||
it.PCScale = pcScale
|
||||
return it
|
||||
}
|
||||
|
||||
// Next advances it to the Next pc.
|
||||
func (it *PCIter) Next() {
|
||||
it.PC = it.NextPC
|
||||
if it.Done {
|
||||
return
|
||||
}
|
||||
if len(it.p) == 0 {
|
||||
it.Done = true
|
||||
return
|
||||
}
|
||||
|
||||
// Value delta
|
||||
val, n := binary.Varint(it.p)
|
||||
if n <= 0 {
|
||||
log.Fatalf("bad Value varint in pciterNext: read %v", n)
|
||||
}
|
||||
it.p = it.p[n:]
|
||||
|
||||
if val == 0 && !it.start {
|
||||
it.Done = true
|
||||
return
|
||||
}
|
||||
|
||||
it.start = false
|
||||
it.Value += int32(val)
|
||||
|
||||
// pc delta
|
||||
pc, n := binary.Uvarint(it.p)
|
||||
if n <= 0 {
|
||||
log.Fatalf("bad pc varint in pciterNext: read %v", n)
|
||||
}
|
||||
it.p = it.p[n:]
|
||||
|
||||
it.NextPC = it.PC + uint32(pc)*it.PCScale
|
||||
}
|
||||
|
||||
// init prepares it to iterate over p,
|
||||
// and advances it to the first pc.
|
||||
func (it *PCIter) Init(p []byte) {
|
||||
it.p = p
|
||||
it.PC = 0
|
||||
it.NextPC = 0
|
||||
it.Value = -1
|
||||
it.start = true
|
||||
it.Done = false
|
||||
it.Next()
|
||||
}
|
||||
314
vendor/github.com/twitchyliquid64/golang-asm/obj/plist.go
generated
vendored
Normal file
314
vendor/github.com/twitchyliquid64/golang-asm/obj/plist.go
generated
vendored
Normal file
@@ -0,0 +1,314 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package obj
|
||||
|
||||
import (
|
||||
"github.com/twitchyliquid64/golang-asm/objabi"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Plist struct {
|
||||
Firstpc *Prog
|
||||
Curfn interface{} // holds a *gc.Node, if non-nil
|
||||
}
|
||||
|
||||
// ProgAlloc is a function that allocates Progs.
|
||||
// It is used to provide access to cached/bulk-allocated Progs to the assemblers.
|
||||
type ProgAlloc func() *Prog
|
||||
|
||||
func Flushplist(ctxt *Link, plist *Plist, newprog ProgAlloc, myimportpath string) {
|
||||
// Build list of symbols, and assign instructions to lists.
|
||||
var curtext *LSym
|
||||
var etext *Prog
|
||||
var text []*LSym
|
||||
|
||||
var plink *Prog
|
||||
for p := plist.Firstpc; p != nil; p = plink {
|
||||
if ctxt.Debugasm > 0 && ctxt.Debugvlog {
|
||||
fmt.Printf("obj: %v\n", p)
|
||||
}
|
||||
plink = p.Link
|
||||
p.Link = nil
|
||||
|
||||
switch p.As {
|
||||
case AEND:
|
||||
continue
|
||||
|
||||
case ATEXT:
|
||||
s := p.From.Sym
|
||||
if s == nil {
|
||||
// func _() { }
|
||||
curtext = nil
|
||||
continue
|
||||
}
|
||||
text = append(text, s)
|
||||
etext = p
|
||||
curtext = s
|
||||
continue
|
||||
|
||||
case AFUNCDATA:
|
||||
// Rewrite reference to go_args_stackmap(SB) to the Go-provided declaration information.
|
||||
if curtext == nil { // func _() {}
|
||||
continue
|
||||
}
|
||||
if p.To.Sym.Name == "go_args_stackmap" {
|
||||
if p.From.Type != TYPE_CONST || p.From.Offset != objabi.FUNCDATA_ArgsPointerMaps {
|
||||
ctxt.Diag("FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps")
|
||||
}
|
||||
p.To.Sym = ctxt.LookupDerived(curtext, curtext.Name+".args_stackmap")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if curtext == nil {
|
||||
etext = nil
|
||||
continue
|
||||
}
|
||||
etext.Link = p
|
||||
etext = p
|
||||
}
|
||||
|
||||
if newprog == nil {
|
||||
newprog = ctxt.NewProg
|
||||
}
|
||||
|
||||
// Add reference to Go arguments for C or assembly functions without them.
|
||||
for _, s := range text {
|
||||
if !strings.HasPrefix(s.Name, "\"\".") {
|
||||
continue
|
||||
}
|
||||
found := false
|
||||
for p := s.Func.Text; p != nil; p = p.Link {
|
||||
if p.As == AFUNCDATA && p.From.Type == TYPE_CONST && p.From.Offset == objabi.FUNCDATA_ArgsPointerMaps {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
p := Appendp(s.Func.Text, newprog)
|
||||
p.As = AFUNCDATA
|
||||
p.From.Type = TYPE_CONST
|
||||
p.From.Offset = objabi.FUNCDATA_ArgsPointerMaps
|
||||
p.To.Type = TYPE_MEM
|
||||
p.To.Name = NAME_EXTERN
|
||||
p.To.Sym = ctxt.LookupDerived(s, s.Name+".args_stackmap")
|
||||
}
|
||||
}
|
||||
|
||||
// Turn functions into machine code images.
|
||||
for _, s := range text {
|
||||
mkfwd(s)
|
||||
linkpatch(ctxt, s, newprog)
|
||||
ctxt.Arch.Preprocess(ctxt, s, newprog)
|
||||
ctxt.Arch.Assemble(ctxt, s, newprog)
|
||||
if ctxt.Errors > 0 {
|
||||
continue
|
||||
}
|
||||
linkpcln(ctxt, s)
|
||||
if myimportpath != "" {
|
||||
ctxt.populateDWARF(plist.Curfn, s, myimportpath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ctxt *Link) InitTextSym(s *LSym, flag int) {
|
||||
if s == nil {
|
||||
// func _() { }
|
||||
return
|
||||
}
|
||||
if s.Func != nil {
|
||||
ctxt.Diag("InitTextSym double init for %s", s.Name)
|
||||
}
|
||||
s.Func = new(FuncInfo)
|
||||
if s.OnList() {
|
||||
ctxt.Diag("symbol %s listed multiple times", s.Name)
|
||||
}
|
||||
name := strings.Replace(s.Name, "\"\"", ctxt.Pkgpath, -1)
|
||||
s.Func.FuncID = objabi.GetFuncID(name, flag&WRAPPER != 0)
|
||||
s.Set(AttrOnList, true)
|
||||
s.Set(AttrDuplicateOK, flag&DUPOK != 0)
|
||||
s.Set(AttrNoSplit, flag&NOSPLIT != 0)
|
||||
s.Set(AttrReflectMethod, flag&REFLECTMETHOD != 0)
|
||||
s.Set(AttrWrapper, flag&WRAPPER != 0)
|
||||
s.Set(AttrNeedCtxt, flag&NEEDCTXT != 0)
|
||||
s.Set(AttrNoFrame, flag&NOFRAME != 0)
|
||||
s.Set(AttrTopFrame, flag&TOPFRAME != 0)
|
||||
s.Type = objabi.STEXT
|
||||
ctxt.Text = append(ctxt.Text, s)
|
||||
|
||||
// Set up DWARF entries for s
|
||||
ctxt.dwarfSym(s)
|
||||
}
|
||||
|
||||
func (ctxt *Link) Globl(s *LSym, size int64, flag int) {
|
||||
if s.OnList() {
|
||||
ctxt.Diag("symbol %s listed multiple times", s.Name)
|
||||
}
|
||||
s.Set(AttrOnList, true)
|
||||
ctxt.Data = append(ctxt.Data, s)
|
||||
s.Size = size
|
||||
if s.Type == 0 {
|
||||
s.Type = objabi.SBSS
|
||||
}
|
||||
if flag&DUPOK != 0 {
|
||||
s.Set(AttrDuplicateOK, true)
|
||||
}
|
||||
if flag&RODATA != 0 {
|
||||
s.Type = objabi.SRODATA
|
||||
} else if flag&NOPTR != 0 {
|
||||
if s.Type == objabi.SDATA {
|
||||
s.Type = objabi.SNOPTRDATA
|
||||
} else {
|
||||
s.Type = objabi.SNOPTRBSS
|
||||
}
|
||||
} else if flag&TLSBSS != 0 {
|
||||
s.Type = objabi.STLSBSS
|
||||
}
|
||||
if strings.HasPrefix(s.Name, "\"\"."+StaticNamePref) {
|
||||
s.Set(AttrStatic, true)
|
||||
}
|
||||
}
|
||||
|
||||
// EmitEntryLiveness generates PCDATA Progs after p to switch to the
|
||||
// liveness map active at the entry of function s. It returns the last
|
||||
// Prog generated.
|
||||
func (ctxt *Link) EmitEntryLiveness(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
|
||||
pcdata := ctxt.EmitEntryStackMap(s, p, newprog)
|
||||
pcdata = ctxt.EmitEntryRegMap(s, pcdata, newprog)
|
||||
return pcdata
|
||||
}
|
||||
|
||||
// Similar to EmitEntryLiveness, but just emit stack map.
|
||||
func (ctxt *Link) EmitEntryStackMap(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
|
||||
pcdata := Appendp(p, newprog)
|
||||
pcdata.Pos = s.Func.Text.Pos
|
||||
pcdata.As = APCDATA
|
||||
pcdata.From.Type = TYPE_CONST
|
||||
pcdata.From.Offset = objabi.PCDATA_StackMapIndex
|
||||
pcdata.To.Type = TYPE_CONST
|
||||
pcdata.To.Offset = -1 // pcdata starts at -1 at function entry
|
||||
|
||||
return pcdata
|
||||
}
|
||||
|
||||
// Similar to EmitEntryLiveness, but just emit register map.
|
||||
func (ctxt *Link) EmitEntryRegMap(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
|
||||
pcdata := Appendp(p, newprog)
|
||||
pcdata.Pos = s.Func.Text.Pos
|
||||
pcdata.As = APCDATA
|
||||
pcdata.From.Type = TYPE_CONST
|
||||
pcdata.From.Offset = objabi.PCDATA_RegMapIndex
|
||||
pcdata.To.Type = TYPE_CONST
|
||||
pcdata.To.Offset = -1
|
||||
|
||||
return pcdata
|
||||
}
|
||||
|
||||
// StartUnsafePoint generates PCDATA Progs after p to mark the
|
||||
// beginning of an unsafe point. The unsafe point starts immediately
|
||||
// after p.
|
||||
// It returns the last Prog generated.
|
||||
func (ctxt *Link) StartUnsafePoint(p *Prog, newprog ProgAlloc) *Prog {
|
||||
pcdata := Appendp(p, newprog)
|
||||
pcdata.As = APCDATA
|
||||
pcdata.From.Type = TYPE_CONST
|
||||
pcdata.From.Offset = objabi.PCDATA_RegMapIndex
|
||||
pcdata.To.Type = TYPE_CONST
|
||||
pcdata.To.Offset = objabi.PCDATA_RegMapUnsafe
|
||||
|
||||
return pcdata
|
||||
}
|
||||
|
||||
// EndUnsafePoint generates PCDATA Progs after p to mark the end of an
|
||||
// unsafe point, restoring the register map index to oldval.
|
||||
// The unsafe point ends right after p.
|
||||
// It returns the last Prog generated.
|
||||
func (ctxt *Link) EndUnsafePoint(p *Prog, newprog ProgAlloc, oldval int64) *Prog {
|
||||
pcdata := Appendp(p, newprog)
|
||||
pcdata.As = APCDATA
|
||||
pcdata.From.Type = TYPE_CONST
|
||||
pcdata.From.Offset = objabi.PCDATA_RegMapIndex
|
||||
pcdata.To.Type = TYPE_CONST
|
||||
pcdata.To.Offset = oldval
|
||||
|
||||
return pcdata
|
||||
}
|
||||
|
||||
// MarkUnsafePoints inserts PCDATAs to mark nonpreemptible and restartable
|
||||
// instruction sequences, based on isUnsafePoint and isRestartable predicate.
|
||||
// p0 is the start of the instruction stream.
|
||||
// isUnsafePoint(p) returns true if p is not safe for async preemption.
|
||||
// isRestartable(p) returns true if we can restart at the start of p (this Prog)
|
||||
// upon async preemption. (Currently multi-Prog restartable sequence is not
|
||||
// supported.)
|
||||
// isRestartable can be nil. In this case it is treated as always returning false.
|
||||
// If isUnsafePoint(p) and isRestartable(p) are both true, it is treated as
|
||||
// an unsafe point.
|
||||
func MarkUnsafePoints(ctxt *Link, p0 *Prog, newprog ProgAlloc, isUnsafePoint, isRestartable func(*Prog) bool) {
|
||||
if isRestartable == nil {
|
||||
// Default implementation: nothing is restartable.
|
||||
isRestartable = func(*Prog) bool { return false }
|
||||
}
|
||||
prev := p0
|
||||
prevPcdata := int64(-1) // entry PC data value
|
||||
prevRestart := int64(0)
|
||||
for p := prev.Link; p != nil; p, prev = p.Link, p {
|
||||
if p.As == APCDATA && p.From.Offset == objabi.PCDATA_RegMapIndex {
|
||||
prevPcdata = p.To.Offset
|
||||
continue
|
||||
}
|
||||
if prevPcdata == objabi.PCDATA_RegMapUnsafe {
|
||||
continue // already unsafe
|
||||
}
|
||||
if isUnsafePoint(p) {
|
||||
q := ctxt.StartUnsafePoint(prev, newprog)
|
||||
q.Pc = p.Pc
|
||||
q.Link = p
|
||||
// Advance to the end of unsafe point.
|
||||
for p.Link != nil && isUnsafePoint(p.Link) {
|
||||
p = p.Link
|
||||
}
|
||||
if p.Link == nil {
|
||||
break // Reached the end, don't bother marking the end
|
||||
}
|
||||
p = ctxt.EndUnsafePoint(p, newprog, prevPcdata)
|
||||
p.Pc = p.Link.Pc
|
||||
continue
|
||||
}
|
||||
if isRestartable(p) {
|
||||
val := int64(objabi.PCDATA_Restart1)
|
||||
if val == prevRestart {
|
||||
val = objabi.PCDATA_Restart2
|
||||
}
|
||||
prevRestart = val
|
||||
q := Appendp(prev, newprog)
|
||||
q.As = APCDATA
|
||||
q.From.Type = TYPE_CONST
|
||||
q.From.Offset = objabi.PCDATA_RegMapIndex
|
||||
q.To.Type = TYPE_CONST
|
||||
q.To.Offset = val
|
||||
q.Pc = p.Pc
|
||||
q.Link = p
|
||||
|
||||
if p.Link == nil {
|
||||
break // Reached the end, don't bother marking the end
|
||||
}
|
||||
if isRestartable(p.Link) {
|
||||
// Next Prog is also restartable. No need to mark the end
|
||||
// of this sequence. We'll just go ahead mark the next one.
|
||||
continue
|
||||
}
|
||||
p = Appendp(p, newprog)
|
||||
p.As = APCDATA
|
||||
p.From.Type = TYPE_CONST
|
||||
p.From.Offset = objabi.PCDATA_RegMapIndex
|
||||
p.To.Type = TYPE_CONST
|
||||
p.To.Offset = prevPcdata
|
||||
p.Pc = p.Link.Pc
|
||||
}
|
||||
}
|
||||
}
|
||||
1032
vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/a.out.go
generated
vendored
Normal file
1032
vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/a.out.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
615
vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/anames.go
generated
vendored
Normal file
615
vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/anames.go
generated
vendored
Normal file
@@ -0,0 +1,615 @@
|
||||
// Code generated by stringer -i a.out.go -o anames.go -p ppc64; DO NOT EDIT.
|
||||
|
||||
package ppc64
|
||||
|
||||
import "github.com/twitchyliquid64/golang-asm/obj"
|
||||
|
||||
var Anames = []string{
|
||||
obj.A_ARCHSPECIFIC: "ADD",
|
||||
"ADDCC",
|
||||
"ADDIS",
|
||||
"ADDV",
|
||||
"ADDVCC",
|
||||
"ADDC",
|
||||
"ADDCCC",
|
||||
"ADDCV",
|
||||
"ADDCVCC",
|
||||
"ADDME",
|
||||
"ADDMECC",
|
||||
"ADDMEVCC",
|
||||
"ADDMEV",
|
||||
"ADDE",
|
||||
"ADDECC",
|
||||
"ADDEVCC",
|
||||
"ADDEV",
|
||||
"ADDZE",
|
||||
"ADDZECC",
|
||||
"ADDZEVCC",
|
||||
"ADDZEV",
|
||||
"ADDEX",
|
||||
"AND",
|
||||
"ANDCC",
|
||||
"ANDN",
|
||||
"ANDNCC",
|
||||
"ANDISCC",
|
||||
"BC",
|
||||
"BCL",
|
||||
"BEQ",
|
||||
"BGE",
|
||||
"BGT",
|
||||
"BLE",
|
||||
"BLT",
|
||||
"BNE",
|
||||
"BVC",
|
||||
"BVS",
|
||||
"CMP",
|
||||
"CMPU",
|
||||
"CMPEQB",
|
||||
"CNTLZW",
|
||||
"CNTLZWCC",
|
||||
"CRAND",
|
||||
"CRANDN",
|
||||
"CREQV",
|
||||
"CRNAND",
|
||||
"CRNOR",
|
||||
"CROR",
|
||||
"CRORN",
|
||||
"CRXOR",
|
||||
"DIVW",
|
||||
"DIVWCC",
|
||||
"DIVWVCC",
|
||||
"DIVWV",
|
||||
"DIVWU",
|
||||
"DIVWUCC",
|
||||
"DIVWUVCC",
|
||||
"DIVWUV",
|
||||
"MODUD",
|
||||
"MODUW",
|
||||
"MODSD",
|
||||
"MODSW",
|
||||
"EQV",
|
||||
"EQVCC",
|
||||
"EXTSB",
|
||||
"EXTSBCC",
|
||||
"EXTSH",
|
||||
"EXTSHCC",
|
||||
"FABS",
|
||||
"FABSCC",
|
||||
"FADD",
|
||||
"FADDCC",
|
||||
"FADDS",
|
||||
"FADDSCC",
|
||||
"FCMPO",
|
||||
"FCMPU",
|
||||
"FCTIW",
|
||||
"FCTIWCC",
|
||||
"FCTIWZ",
|
||||
"FCTIWZCC",
|
||||
"FDIV",
|
||||
"FDIVCC",
|
||||
"FDIVS",
|
||||
"FDIVSCC",
|
||||
"FMADD",
|
||||
"FMADDCC",
|
||||
"FMADDS",
|
||||
"FMADDSCC",
|
||||
"FMOVD",
|
||||
"FMOVDCC",
|
||||
"FMOVDU",
|
||||
"FMOVS",
|
||||
"FMOVSU",
|
||||
"FMOVSX",
|
||||
"FMOVSZ",
|
||||
"FMSUB",
|
||||
"FMSUBCC",
|
||||
"FMSUBS",
|
||||
"FMSUBSCC",
|
||||
"FMUL",
|
||||
"FMULCC",
|
||||
"FMULS",
|
||||
"FMULSCC",
|
||||
"FNABS",
|
||||
"FNABSCC",
|
||||
"FNEG",
|
||||
"FNEGCC",
|
||||
"FNMADD",
|
||||
"FNMADDCC",
|
||||
"FNMADDS",
|
||||
"FNMADDSCC",
|
||||
"FNMSUB",
|
||||
"FNMSUBCC",
|
||||
"FNMSUBS",
|
||||
"FNMSUBSCC",
|
||||
"FRSP",
|
||||
"FRSPCC",
|
||||
"FSUB",
|
||||
"FSUBCC",
|
||||
"FSUBS",
|
||||
"FSUBSCC",
|
||||
"ISEL",
|
||||
"MOVMW",
|
||||
"LBAR",
|
||||
"LHAR",
|
||||
"LSW",
|
||||
"LWAR",
|
||||
"LWSYNC",
|
||||
"MOVDBR",
|
||||
"MOVWBR",
|
||||
"MOVB",
|
||||
"MOVBU",
|
||||
"MOVBZ",
|
||||
"MOVBZU",
|
||||
"MOVH",
|
||||
"MOVHBR",
|
||||
"MOVHU",
|
||||
"MOVHZ",
|
||||
"MOVHZU",
|
||||
"MOVW",
|
||||
"MOVWU",
|
||||
"MOVFL",
|
||||
"MOVCRFS",
|
||||
"MTFSB0",
|
||||
"MTFSB0CC",
|
||||
"MTFSB1",
|
||||
"MTFSB1CC",
|
||||
"MULHW",
|
||||
"MULHWCC",
|
||||
"MULHWU",
|
||||
"MULHWUCC",
|
||||
"MULLW",
|
||||
"MULLWCC",
|
||||
"MULLWVCC",
|
||||
"MULLWV",
|
||||
"NAND",
|
||||
"NANDCC",
|
||||
"NEG",
|
||||
"NEGCC",
|
||||
"NEGVCC",
|
||||
"NEGV",
|
||||
"NOR",
|
||||
"NORCC",
|
||||
"OR",
|
||||
"ORCC",
|
||||
"ORN",
|
||||
"ORNCC",
|
||||
"ORIS",
|
||||
"REM",
|
||||
"REMU",
|
||||
"RFI",
|
||||
"RLWMI",
|
||||
"RLWMICC",
|
||||
"RLWNM",
|
||||
"RLWNMCC",
|
||||
"CLRLSLWI",
|
||||
"SLW",
|
||||
"SLWCC",
|
||||
"SRW",
|
||||
"SRAW",
|
||||
"SRAWCC",
|
||||
"SRWCC",
|
||||
"STBCCC",
|
||||
"STHCCC",
|
||||
"STSW",
|
||||
"STWCCC",
|
||||
"SUB",
|
||||
"SUBCC",
|
||||
"SUBVCC",
|
||||
"SUBC",
|
||||
"SUBCCC",
|
||||
"SUBCV",
|
||||
"SUBCVCC",
|
||||
"SUBME",
|
||||
"SUBMECC",
|
||||
"SUBMEVCC",
|
||||
"SUBMEV",
|
||||
"SUBV",
|
||||
"SUBE",
|
||||
"SUBECC",
|
||||
"SUBEV",
|
||||
"SUBEVCC",
|
||||
"SUBZE",
|
||||
"SUBZECC",
|
||||
"SUBZEVCC",
|
||||
"SUBZEV",
|
||||
"SYNC",
|
||||
"XOR",
|
||||
"XORCC",
|
||||
"XORIS",
|
||||
"DCBF",
|
||||
"DCBI",
|
||||
"DCBST",
|
||||
"DCBT",
|
||||
"DCBTST",
|
||||
"DCBZ",
|
||||
"ECIWX",
|
||||
"ECOWX",
|
||||
"EIEIO",
|
||||
"ICBI",
|
||||
"ISYNC",
|
||||
"PTESYNC",
|
||||
"TLBIE",
|
||||
"TLBIEL",
|
||||
"TLBSYNC",
|
||||
"TW",
|
||||
"SYSCALL",
|
||||
"WORD",
|
||||
"RFCI",
|
||||
"FCPSGN",
|
||||
"FCPSGNCC",
|
||||
"FRES",
|
||||
"FRESCC",
|
||||
"FRIM",
|
||||
"FRIMCC",
|
||||
"FRIP",
|
||||
"FRIPCC",
|
||||
"FRIZ",
|
||||
"FRIZCC",
|
||||
"FRIN",
|
||||
"FRINCC",
|
||||
"FRSQRTE",
|
||||
"FRSQRTECC",
|
||||
"FSEL",
|
||||
"FSELCC",
|
||||
"FSQRT",
|
||||
"FSQRTCC",
|
||||
"FSQRTS",
|
||||
"FSQRTSCC",
|
||||
"CNTLZD",
|
||||
"CNTLZDCC",
|
||||
"CMPW",
|
||||
"CMPWU",
|
||||
"CMPB",
|
||||
"FTDIV",
|
||||
"FTSQRT",
|
||||
"DIVD",
|
||||
"DIVDCC",
|
||||
"DIVDE",
|
||||
"DIVDECC",
|
||||
"DIVDEU",
|
||||
"DIVDEUCC",
|
||||
"DIVDVCC",
|
||||
"DIVDV",
|
||||
"DIVDU",
|
||||
"DIVDUCC",
|
||||
"DIVDUVCC",
|
||||
"DIVDUV",
|
||||
"EXTSW",
|
||||
"EXTSWCC",
|
||||
"FCFID",
|
||||
"FCFIDCC",
|
||||
"FCFIDU",
|
||||
"FCFIDUCC",
|
||||
"FCFIDS",
|
||||
"FCFIDSCC",
|
||||
"FCTID",
|
||||
"FCTIDCC",
|
||||
"FCTIDZ",
|
||||
"FCTIDZCC",
|
||||
"LDAR",
|
||||
"MOVD",
|
||||
"MOVDU",
|
||||
"MOVWZ",
|
||||
"MOVWZU",
|
||||
"MULHD",
|
||||
"MULHDCC",
|
||||
"MULHDU",
|
||||
"MULHDUCC",
|
||||
"MULLD",
|
||||
"MULLDCC",
|
||||
"MULLDVCC",
|
||||
"MULLDV",
|
||||
"RFID",
|
||||
"RLDMI",
|
||||
"RLDMICC",
|
||||
"RLDIMI",
|
||||
"RLDIMICC",
|
||||
"RLDC",
|
||||
"RLDCCC",
|
||||
"RLDCR",
|
||||
"RLDCRCC",
|
||||
"RLDICR",
|
||||
"RLDICRCC",
|
||||
"RLDCL",
|
||||
"RLDCLCC",
|
||||
"RLDICL",
|
||||
"RLDICLCC",
|
||||
"RLDIC",
|
||||
"RLDICCC",
|
||||
"CLRLSLDI",
|
||||
"ROTL",
|
||||
"ROTLW",
|
||||
"SLBIA",
|
||||
"SLBIE",
|
||||
"SLBMFEE",
|
||||
"SLBMFEV",
|
||||
"SLBMTE",
|
||||
"SLD",
|
||||
"SLDCC",
|
||||
"SRD",
|
||||
"SRAD",
|
||||
"SRADCC",
|
||||
"SRDCC",
|
||||
"STDCCC",
|
||||
"TD",
|
||||
"DWORD",
|
||||
"REMD",
|
||||
"REMDU",
|
||||
"HRFID",
|
||||
"POPCNTD",
|
||||
"POPCNTW",
|
||||
"POPCNTB",
|
||||
"CNTTZW",
|
||||
"CNTTZWCC",
|
||||
"CNTTZD",
|
||||
"CNTTZDCC",
|
||||
"COPY",
|
||||
"PASTECC",
|
||||
"DARN",
|
||||
"LDMX",
|
||||
"MADDHD",
|
||||
"MADDHDU",
|
||||
"MADDLD",
|
||||
"LV",
|
||||
"LVEBX",
|
||||
"LVEHX",
|
||||
"LVEWX",
|
||||
"LVX",
|
||||
"LVXL",
|
||||
"LVSL",
|
||||
"LVSR",
|
||||
"STV",
|
||||
"STVEBX",
|
||||
"STVEHX",
|
||||
"STVEWX",
|
||||
"STVX",
|
||||
"STVXL",
|
||||
"VAND",
|
||||
"VANDC",
|
||||
"VNAND",
|
||||
"VOR",
|
||||
"VORC",
|
||||
"VNOR",
|
||||
"VXOR",
|
||||
"VEQV",
|
||||
"VADDUM",
|
||||
"VADDUBM",
|
||||
"VADDUHM",
|
||||
"VADDUWM",
|
||||
"VADDUDM",
|
||||
"VADDUQM",
|
||||
"VADDCU",
|
||||
"VADDCUQ",
|
||||
"VADDCUW",
|
||||
"VADDUS",
|
||||
"VADDUBS",
|
||||
"VADDUHS",
|
||||
"VADDUWS",
|
||||
"VADDSS",
|
||||
"VADDSBS",
|
||||
"VADDSHS",
|
||||
"VADDSWS",
|
||||
"VADDE",
|
||||
"VADDEUQM",
|
||||
"VADDECUQ",
|
||||
"VSUBUM",
|
||||
"VSUBUBM",
|
||||
"VSUBUHM",
|
||||
"VSUBUWM",
|
||||
"VSUBUDM",
|
||||
"VSUBUQM",
|
||||
"VSUBCU",
|
||||
"VSUBCUQ",
|
||||
"VSUBCUW",
|
||||
"VSUBUS",
|
||||
"VSUBUBS",
|
||||
"VSUBUHS",
|
||||
"VSUBUWS",
|
||||
"VSUBSS",
|
||||
"VSUBSBS",
|
||||
"VSUBSHS",
|
||||
"VSUBSWS",
|
||||
"VSUBE",
|
||||
"VSUBEUQM",
|
||||
"VSUBECUQ",
|
||||
"VMULESB",
|
||||
"VMULOSB",
|
||||
"VMULEUB",
|
||||
"VMULOUB",
|
||||
"VMULESH",
|
||||
"VMULOSH",
|
||||
"VMULEUH",
|
||||
"VMULOUH",
|
||||
"VMULESW",
|
||||
"VMULOSW",
|
||||
"VMULEUW",
|
||||
"VMULOUW",
|
||||
"VMULUWM",
|
||||
"VPMSUM",
|
||||
"VPMSUMB",
|
||||
"VPMSUMH",
|
||||
"VPMSUMW",
|
||||
"VPMSUMD",
|
||||
"VMSUMUDM",
|
||||
"VR",
|
||||
"VRLB",
|
||||
"VRLH",
|
||||
"VRLW",
|
||||
"VRLD",
|
||||
"VS",
|
||||
"VSLB",
|
||||
"VSLH",
|
||||
"VSLW",
|
||||
"VSL",
|
||||
"VSLO",
|
||||
"VSRB",
|
||||
"VSRH",
|
||||
"VSRW",
|
||||
"VSR",
|
||||
"VSRO",
|
||||
"VSLD",
|
||||
"VSRD",
|
||||
"VSA",
|
||||
"VSRAB",
|
||||
"VSRAH",
|
||||
"VSRAW",
|
||||
"VSRAD",
|
||||
"VSOI",
|
||||
"VSLDOI",
|
||||
"VCLZ",
|
||||
"VCLZB",
|
||||
"VCLZH",
|
||||
"VCLZW",
|
||||
"VCLZD",
|
||||
"VPOPCNT",
|
||||
"VPOPCNTB",
|
||||
"VPOPCNTH",
|
||||
"VPOPCNTW",
|
||||
"VPOPCNTD",
|
||||
"VCMPEQ",
|
||||
"VCMPEQUB",
|
||||
"VCMPEQUBCC",
|
||||
"VCMPEQUH",
|
||||
"VCMPEQUHCC",
|
||||
"VCMPEQUW",
|
||||
"VCMPEQUWCC",
|
||||
"VCMPEQUD",
|
||||
"VCMPEQUDCC",
|
||||
"VCMPGT",
|
||||
"VCMPGTUB",
|
||||
"VCMPGTUBCC",
|
||||
"VCMPGTUH",
|
||||
"VCMPGTUHCC",
|
||||
"VCMPGTUW",
|
||||
"VCMPGTUWCC",
|
||||
"VCMPGTUD",
|
||||
"VCMPGTUDCC",
|
||||
"VCMPGTSB",
|
||||
"VCMPGTSBCC",
|
||||
"VCMPGTSH",
|
||||
"VCMPGTSHCC",
|
||||
"VCMPGTSW",
|
||||
"VCMPGTSWCC",
|
||||
"VCMPGTSD",
|
||||
"VCMPGTSDCC",
|
||||
"VCMPNEZB",
|
||||
"VCMPNEZBCC",
|
||||
"VCMPNEB",
|
||||
"VCMPNEBCC",
|
||||
"VCMPNEH",
|
||||
"VCMPNEHCC",
|
||||
"VCMPNEW",
|
||||
"VCMPNEWCC",
|
||||
"VPERM",
|
||||
"VPERMXOR",
|
||||
"VPERMR",
|
||||
"VBPERMQ",
|
||||
"VBPERMD",
|
||||
"VSEL",
|
||||
"VSPLT",
|
||||
"VSPLTB",
|
||||
"VSPLTH",
|
||||
"VSPLTW",
|
||||
"VSPLTI",
|
||||
"VSPLTISB",
|
||||
"VSPLTISH",
|
||||
"VSPLTISW",
|
||||
"VCIPH",
|
||||
"VCIPHER",
|
||||
"VCIPHERLAST",
|
||||
"VNCIPH",
|
||||
"VNCIPHER",
|
||||
"VNCIPHERLAST",
|
||||
"VSBOX",
|
||||
"VSHASIGMA",
|
||||
"VSHASIGMAW",
|
||||
"VSHASIGMAD",
|
||||
"VMRGEW",
|
||||
"VMRGOW",
|
||||
"LXV",
|
||||
"LXVL",
|
||||
"LXVLL",
|
||||
"LXVD2X",
|
||||
"LXVW4X",
|
||||
"LXVH8X",
|
||||
"LXVB16X",
|
||||
"LXVX",
|
||||
"LXVDSX",
|
||||
"STXV",
|
||||
"STXVL",
|
||||
"STXVLL",
|
||||
"STXVD2X",
|
||||
"STXVW4X",
|
||||
"STXVH8X",
|
||||
"STXVB16X",
|
||||
"STXVX",
|
||||
"LXSDX",
|
||||
"STXSDX",
|
||||
"LXSIWAX",
|
||||
"LXSIWZX",
|
||||
"STXSIWX",
|
||||
"MFVSRD",
|
||||
"MFFPRD",
|
||||
"MFVRD",
|
||||
"MFVSRWZ",
|
||||
"MFVSRLD",
|
||||
"MTVSRD",
|
||||
"MTFPRD",
|
||||
"MTVRD",
|
||||
"MTVSRWA",
|
||||
"MTVSRWZ",
|
||||
"MTVSRDD",
|
||||
"MTVSRWS",
|
||||
"XXLAND",
|
||||
"XXLANDC",
|
||||
"XXLEQV",
|
||||
"XXLNAND",
|
||||
"XXLOR",
|
||||
"XXLORC",
|
||||
"XXLNOR",
|
||||
"XXLORQ",
|
||||
"XXLXOR",
|
||||
"XXSEL",
|
||||
"XXMRGHW",
|
||||
"XXMRGLW",
|
||||
"XXSPLT",
|
||||
"XXSPLTW",
|
||||
"XXSPLTIB",
|
||||
"XXPERM",
|
||||
"XXPERMDI",
|
||||
"XXSLDWI",
|
||||
"XXBRQ",
|
||||
"XXBRD",
|
||||
"XXBRW",
|
||||
"XXBRH",
|
||||
"XSCVDPSP",
|
||||
"XSCVSPDP",
|
||||
"XSCVDPSPN",
|
||||
"XSCVSPDPN",
|
||||
"XVCVDPSP",
|
||||
"XVCVSPDP",
|
||||
"XSCVDPSXDS",
|
||||
"XSCVDPSXWS",
|
||||
"XSCVDPUXDS",
|
||||
"XSCVDPUXWS",
|
||||
"XSCVSXDDP",
|
||||
"XSCVUXDDP",
|
||||
"XSCVSXDSP",
|
||||
"XSCVUXDSP",
|
||||
"XVCVDPSXDS",
|
||||
"XVCVDPSXWS",
|
||||
"XVCVDPUXDS",
|
||||
"XVCVDPUXWS",
|
||||
"XVCVSPSXDS",
|
||||
"XVCVSPSXWS",
|
||||
"XVCVSPUXDS",
|
||||
"XVCVSPUXWS",
|
||||
"XVCVSXDDP",
|
||||
"XVCVSXWDP",
|
||||
"XVCVUXDDP",
|
||||
"XVCVUXWDP",
|
||||
"XVCVSXDSP",
|
||||
"XVCVSXWSP",
|
||||
"XVCVUXDSP",
|
||||
"XVCVUXWSP",
|
||||
"LAST",
|
||||
}
|
||||
51
vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/anames9.go
generated
vendored
Normal file
51
vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/anames9.go
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ppc64
|
||||
|
||||
var cnames9 = []string{
|
||||
"NONE",
|
||||
"REG",
|
||||
"FREG",
|
||||
"VREG",
|
||||
"VSREG",
|
||||
"CREG",
|
||||
"SPR",
|
||||
"ZCON",
|
||||
"SCON",
|
||||
"UCON",
|
||||
"ADDCON",
|
||||
"ANDCON",
|
||||
"LCON",
|
||||
"DCON",
|
||||
"SACON",
|
||||
"SECON",
|
||||
"LACON",
|
||||
"LECON",
|
||||
"DACON",
|
||||
"SBRA",
|
||||
"LBRA",
|
||||
"LBRAPIC",
|
||||
"SAUTO",
|
||||
"LAUTO",
|
||||
"SEXT",
|
||||
"LEXT",
|
||||
"ZOREG",
|
||||
"SOREG",
|
||||
"LOREG",
|
||||
"FPSCR",
|
||||
"MSR",
|
||||
"XER",
|
||||
"LR",
|
||||
"CTR",
|
||||
"ANY",
|
||||
"GOK",
|
||||
"ADDR",
|
||||
"GOTADDR",
|
||||
"TOCADDR",
|
||||
"TLS_LE",
|
||||
"TLS_IE",
|
||||
"TEXTSIZE",
|
||||
"NCLASS",
|
||||
}
|
||||
5367
vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/asm9.go
generated
vendored
Normal file
5367
vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/asm9.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
244
vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/doc.go
generated
vendored
Normal file
244
vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/doc.go
generated
vendored
Normal file
@@ -0,0 +1,244 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package ppc64 implements a PPC64 assembler that assembles Go asm into
|
||||
the corresponding PPC64 instructions as defined by the Power ISA 3.0B.
|
||||
|
||||
This document provides information on how to write code in Go assembler
|
||||
for PPC64, focusing on the differences between Go and PPC64 assembly language.
|
||||
It assumes some knowledge of PPC64 assembler. The original implementation of
|
||||
PPC64 in Go defined many opcodes that are different from PPC64 opcodes, but
|
||||
updates to the Go assembly language used mnemonics that are mostly similar if not
|
||||
identical to the PPC64 mneumonics, such as VMX and VSX instructions. Not all detail
|
||||
is included here; refer to the Power ISA document if interested in more detail.
|
||||
|
||||
Starting with Go 1.15 the Go objdump supports the -gnu option, which provides a
|
||||
side by side view of the Go assembler and the PPC64 assembler output. This is
|
||||
extremely helpful in determining what final PPC64 assembly is generated from the
|
||||
corresponding Go assembly.
|
||||
|
||||
In the examples below, the Go assembly is on the left, PPC64 assembly on the right.
|
||||
|
||||
1. Operand ordering
|
||||
|
||||
In Go asm, the last operand (right) is the target operand, but with PPC64 asm,
|
||||
the first operand (left) is the target. The order of the remaining operands is
|
||||
not consistent: in general opcodes with 3 operands that perform math or logical
|
||||
operations have their operands in reverse order. Opcodes for vector instructions
|
||||
and those with more than 3 operands usually have operands in the same order except
|
||||
for the target operand, which is first in PPC64 asm and last in Go asm.
|
||||
|
||||
Example:
|
||||
ADD R3, R4, R5 <=> add r5, r4, r3
|
||||
|
||||
2. Constant operands
|
||||
|
||||
In Go asm, an operand that starts with '$' indicates a constant value. If the
|
||||
instruction using the constant has an immediate version of the opcode, then an
|
||||
immediate value is used with the opcode if possible.
|
||||
|
||||
Example:
|
||||
ADD $1, R3, R4 <=> addi r4, r3, 1
|
||||
|
||||
3. Opcodes setting condition codes
|
||||
|
||||
In PPC64 asm, some instructions other than compares have variations that can set
|
||||
the condition code where meaningful. This is indicated by adding '.' to the end
|
||||
of the PPC64 instruction. In Go asm, these instructions have 'CC' at the end of
|
||||
the opcode. The possible settings of the condition code depend on the instruction.
|
||||
CR0 is the default for fixed-point instructions; CR1 for floating point; CR6 for
|
||||
vector instructions.
|
||||
|
||||
Example:
|
||||
ANDCC R3, R4, R5 <=> and. r5, r3, r4 (set CR0)
|
||||
|
||||
4. Loads and stores from memory
|
||||
|
||||
In Go asm, opcodes starting with 'MOV' indicate a load or store. When the target
|
||||
is a memory reference, then it is a store; when the target is a register and the
|
||||
source is a memory reference, then it is a load.
|
||||
|
||||
MOV{B,H,W,D} variations identify the size as byte, halfword, word, doubleword.
|
||||
|
||||
Adding 'Z' to the opcode for a load indicates zero extend; if omitted it is sign extend.
|
||||
Adding 'U' to a load or store indicates an update of the base register with the offset.
|
||||
Adding 'BR' to an opcode indicates byte-reversed load or store, or the order opposite
|
||||
of the expected endian order. If 'BR' is used then zero extend is assumed.
|
||||
|
||||
Memory references n(Ra) indicate the address in Ra + n. When used with an update form
|
||||
of an opcode, the value in Ra is incremented by n.
|
||||
|
||||
Memory references (Ra+Rb) or (Ra)(Rb) indicate the address Ra + Rb, used by indexed
|
||||
loads or stores. Both forms are accepted. When used with an update then the base register
|
||||
is updated by the value in the index register.
|
||||
|
||||
Examples:
|
||||
MOVD (R3), R4 <=> ld r4,0(r3)
|
||||
MOVW (R3), R4 <=> lwa r4,0(r3)
|
||||
MOVWZU 4(R3), R4 <=> lwzu r4,4(r3)
|
||||
MOVWZ (R3+R5), R4 <=> lwzx r4,r3,r5
|
||||
MOVHZ (R3), R4 <=> lhz r4,0(r3)
|
||||
MOVHU 2(R3), R4 <=> lhau r4,2(r3)
|
||||
MOVBZ (R3), R4 <=> lbz r4,0(r3)
|
||||
|
||||
MOVD R4,(R3) <=> std r4,0(r3)
|
||||
MOVW R4,(R3) <=> stw r4,0(r3)
|
||||
MOVW R4,(R3+R5) <=> stwx r4,r3,r5
|
||||
MOVWU R4,4(R3) <=> stwu r4,4(r3)
|
||||
MOVH R4,2(R3) <=> sth r4,2(r3)
|
||||
MOVBU R4,(R3)(R5) <=> stbux r4,r3,r5
|
||||
|
||||
4. Compares
|
||||
|
||||
When an instruction does a compare or other operation that might
|
||||
result in a condition code, then the resulting condition is set
|
||||
in a field of the condition register. The condition register consists
|
||||
of 8 4-bit fields named CR0 - CR7. When a compare instruction
|
||||
identifies a CR then the resulting condition is set in that field
|
||||
to be read by a later branch or isel instruction. Within these fields,
|
||||
bits are set to indicate less than, greater than, or equal conditions.
|
||||
|
||||
Once an instruction sets a condition, then a subsequent branch, isel or
|
||||
other instruction can read the condition field and operate based on the
|
||||
bit settings.
|
||||
|
||||
Examples:
|
||||
CMP R3, R4 <=> cmp r3, r4 (CR0 assumed)
|
||||
CMP R3, R4, CR1 <=> cmp cr1, r3, r4
|
||||
|
||||
Note that the condition register is the target operand of compare opcodes, so
|
||||
the remaining operands are in the same order for Go asm and PPC64 asm.
|
||||
When CR0 is used then it is implicit and does not need to be specified.
|
||||
|
||||
5. Branches
|
||||
|
||||
Many branches are represented as a form of the BC instruction. There are
|
||||
other extended opcodes to make it easier to see what type of branch is being
|
||||
used.
|
||||
|
||||
The following is a brief description of the BC instruction and its commonly
|
||||
used operands.
|
||||
|
||||
BC op1, op2, op3
|
||||
|
||||
op1: type of branch
|
||||
16 -> bctr (branch on ctr)
|
||||
12 -> bcr (branch if cr bit is set)
|
||||
8 -> bcr+bctr (branch on ctr and cr values)
|
||||
4 -> bcr != 0 (branch if specified cr bit is not set)
|
||||
|
||||
There are more combinations but these are the most common.
|
||||
|
||||
op2: condition register field and condition bit
|
||||
|
||||
This contains an immediate value indicating which condition field
|
||||
to read and what bits to test. Each field is 4 bits long with CR0
|
||||
at bit 0, CR1 at bit 4, etc. The value is computed as 4*CR+condition
|
||||
with these condition values:
|
||||
|
||||
0 -> LT
|
||||
1 -> GT
|
||||
2 -> EQ
|
||||
3 -> OVG
|
||||
|
||||
Thus 0 means test CR0 for LT, 5 means CR1 for GT, 30 means CR7 for EQ.
|
||||
|
||||
op3: branch target
|
||||
|
||||
Examples:
|
||||
|
||||
BC 12, 0, target <=> blt cr0, target
|
||||
BC 12, 2, target <=> beq cr0, target
|
||||
BC 12, 5, target <=> bgt cr1, target
|
||||
BC 12, 30, target <=> beq cr7, target
|
||||
BC 4, 6, target <=> bne cr1, target
|
||||
BC 4, 1, target <=> ble cr1, target
|
||||
|
||||
The following extended opcodes are available for ease of use and readability:
|
||||
|
||||
BNE CR2, target <=> bne cr2, target
|
||||
BEQ CR4, target <=> beq cr4, target
|
||||
BLT target <=> blt target (cr0 default)
|
||||
BGE CR7, target <=> bge cr7, target
|
||||
|
||||
Refer to the ISA for more information on additional values for the BC instruction,
|
||||
how to handle OVG information, and much more.
|
||||
|
||||
5. Align directive
|
||||
|
||||
Starting with Go 1.12, Go asm supports the PCALIGN directive, which indicates
|
||||
that the next instruction should be aligned to the specified value. Currently
|
||||
8 and 16 are the only supported values, and a maximum of 2 NOPs will be added
|
||||
to align the code. That means in the case where the code is aligned to 4 but
|
||||
PCALIGN $16 is at that location, the code will only be aligned to 8 to avoid
|
||||
adding 3 NOPs.
|
||||
|
||||
The purpose of this directive is to improve performance for cases like loops
|
||||
where better alignment (8 or 16 instead of 4) might be helpful. This directive
|
||||
exists in PPC64 assembler and is frequently used by PPC64 assembler writers.
|
||||
|
||||
PCALIGN $16
|
||||
PCALIGN $8
|
||||
|
||||
Functions in Go are aligned to 16 bytes, as is the case in all other compilers
|
||||
for PPC64.
|
||||
|
||||
6. Shift instructions
|
||||
|
||||
The simple scalar shifts on PPC64 expect a shift count that fits in 5 bits for
|
||||
32-bit values or 6 bit for 64-bit values. If the shift count is a constant value
|
||||
greater than the max then the assembler sets it to the max for that size (31 for
|
||||
32 bit values, 63 for 64 bit values). If the shift count is in a register, then
|
||||
only the low 5 or 6 bits of the register will be used as the shift count. The
|
||||
Go compiler will add appropriate code to compare the shift value to achieve the
|
||||
the correct result, and the assembler does not add extra checking.
|
||||
|
||||
Examples:
|
||||
|
||||
SRAD $8,R3,R4 => sradi r4,r3,8
|
||||
SRD $8,R3,R4 => rldicl r4,r3,56,8
|
||||
SLD $8,R3,R4 => rldicr r4,r3,8,55
|
||||
SRAW $16,R4,R5 => srawi r5,r4,16
|
||||
SRW $40,R4,R5 => rlwinm r5,r4,0,0,31
|
||||
SLW $12,R4,R5 => rlwinm r5,r4,12,0,19
|
||||
|
||||
Some non-simple shifts have operands in the Go assembly which don't map directly
|
||||
onto operands in the PPC64 assembly. When an operand in a shift instruction in the
|
||||
Go assembly is a bit mask, that mask is represented as a start and end bit in the
|
||||
PPC64 assembly instead of a mask. See the ISA for more detail on these types of shifts.
|
||||
Here are a few examples:
|
||||
|
||||
RLWMI $7,R3,$65535,R6 => rlwimi r6,r3,7,16,31
|
||||
RLDMI $0,R4,$7,R6 => rldimi r6,r4,0,61
|
||||
|
||||
More recently, Go opcodes were added which map directly onto the PPC64 opcodes. It is
|
||||
recommended to use the newer opcodes to avoid confusion.
|
||||
|
||||
RLDICL $0,R4,$15,R6 => rldicl r6,r4,0,15
|
||||
RLDICR $0,R4,$15,R6 => rldicr r6.r4,0,15
|
||||
|
||||
Register naming
|
||||
|
||||
1. Special register usage in Go asm
|
||||
|
||||
The following registers should not be modified by user Go assembler code.
|
||||
|
||||
R0: Go code expects this register to contain the value 0.
|
||||
R1: Stack pointer
|
||||
R2: TOC pointer when compiled with -shared or -dynlink (a.k.a position independent code)
|
||||
R13: TLS pointer
|
||||
R30: g (goroutine)
|
||||
|
||||
Register names:
|
||||
|
||||
Rn is used for general purpose registers. (0-31)
|
||||
Fn is used for floating point registers. (0-31)
|
||||
Vn is used for vector registers. Slot 0 of Vn overlaps with Fn. (0-31)
|
||||
VSn is used for vector-scalar registers. V0-V31 overlap with VS32-VS63. (0-63)
|
||||
CTR represents the count register.
|
||||
LR represents the link register.
|
||||
|
||||
*/
|
||||
package ppc64
|
||||
104
vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/list9.go
generated
vendored
Normal file
104
vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/list9.go
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
// cmd/9l/list.c from Vita Nuova.
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package ppc64
|
||||
|
||||
import (
|
||||
"github.com/twitchyliquid64/golang-asm/obj"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func init() {
|
||||
obj.RegisterRegister(obj.RBasePPC64, REG_DCR0+1024, rconv)
|
||||
obj.RegisterOpcode(obj.ABasePPC64, Anames)
|
||||
}
|
||||
|
||||
func rconv(r int) string {
|
||||
if r == 0 {
|
||||
return "NONE"
|
||||
}
|
||||
if r == REGG {
|
||||
// Special case.
|
||||
return "g"
|
||||
}
|
||||
if REG_R0 <= r && r <= REG_R31 {
|
||||
return fmt.Sprintf("R%d", r-REG_R0)
|
||||
}
|
||||
if REG_F0 <= r && r <= REG_F31 {
|
||||
return fmt.Sprintf("F%d", r-REG_F0)
|
||||
}
|
||||
if REG_V0 <= r && r <= REG_V31 {
|
||||
return fmt.Sprintf("V%d", r-REG_V0)
|
||||
}
|
||||
if REG_VS0 <= r && r <= REG_VS63 {
|
||||
return fmt.Sprintf("VS%d", r-REG_VS0)
|
||||
}
|
||||
if REG_CR0 <= r && r <= REG_CR7 {
|
||||
return fmt.Sprintf("CR%d", r-REG_CR0)
|
||||
}
|
||||
if r == REG_CR {
|
||||
return "CR"
|
||||
}
|
||||
if REG_SPR0 <= r && r <= REG_SPR0+1023 {
|
||||
switch r {
|
||||
case REG_XER:
|
||||
return "XER"
|
||||
|
||||
case REG_LR:
|
||||
return "LR"
|
||||
|
||||
case REG_CTR:
|
||||
return "CTR"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("SPR(%d)", r-REG_SPR0)
|
||||
}
|
||||
|
||||
if REG_DCR0 <= r && r <= REG_DCR0+1023 {
|
||||
return fmt.Sprintf("DCR(%d)", r-REG_DCR0)
|
||||
}
|
||||
if r == REG_FPSCR {
|
||||
return "FPSCR"
|
||||
}
|
||||
if r == REG_MSR {
|
||||
return "MSR"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Rgok(%d)", r-obj.RBasePPC64)
|
||||
}
|
||||
|
||||
func DRconv(a int) string {
|
||||
s := "C_??"
|
||||
if a >= C_NONE && a <= C_NCLASS {
|
||||
s = cnames9[a]
|
||||
}
|
||||
var fp string
|
||||
fp += s
|
||||
return fp
|
||||
}
|
||||
1278
vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/obj9.go
generated
vendored
Normal file
1278
vendor/github.com/twitchyliquid64/golang-asm/obj/ppc64/obj9.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
258
vendor/github.com/twitchyliquid64/golang-asm/obj/riscv/anames.go
generated
vendored
Normal file
258
vendor/github.com/twitchyliquid64/golang-asm/obj/riscv/anames.go
generated
vendored
Normal file
@@ -0,0 +1,258 @@
|
||||
// Code generated by stringer -i cpu.go -o anames.go -p riscv; DO NOT EDIT.
|
||||
|
||||
package riscv
|
||||
|
||||
import "github.com/twitchyliquid64/golang-asm/obj"
|
||||
|
||||
var Anames = []string{
|
||||
obj.A_ARCHSPECIFIC: "ADDI",
|
||||
"SLTI",
|
||||
"SLTIU",
|
||||
"ANDI",
|
||||
"ORI",
|
||||
"XORI",
|
||||
"SLLI",
|
||||
"SRLI",
|
||||
"SRAI",
|
||||
"LUI",
|
||||
"AUIPC",
|
||||
"ADD",
|
||||
"SLT",
|
||||
"SLTU",
|
||||
"AND",
|
||||
"OR",
|
||||
"XOR",
|
||||
"SLL",
|
||||
"SRL",
|
||||
"SUB",
|
||||
"SRA",
|
||||
"SLLIRV32",
|
||||
"SRLIRV32",
|
||||
"SRAIRV32",
|
||||
"JAL",
|
||||
"JALR",
|
||||
"BEQ",
|
||||
"BNE",
|
||||
"BLT",
|
||||
"BLTU",
|
||||
"BGE",
|
||||
"BGEU",
|
||||
"LW",
|
||||
"LWU",
|
||||
"LH",
|
||||
"LHU",
|
||||
"LB",
|
||||
"LBU",
|
||||
"SW",
|
||||
"SH",
|
||||
"SB",
|
||||
"FENCE",
|
||||
"FENCEI",
|
||||
"FENCETSO",
|
||||
"ADDIW",
|
||||
"SLLIW",
|
||||
"SRLIW",
|
||||
"SRAIW",
|
||||
"ADDW",
|
||||
"SLLW",
|
||||
"SRLW",
|
||||
"SUBW",
|
||||
"SRAW",
|
||||
"LD",
|
||||
"SD",
|
||||
"MUL",
|
||||
"MULH",
|
||||
"MULHU",
|
||||
"MULHSU",
|
||||
"MULW",
|
||||
"DIV",
|
||||
"DIVU",
|
||||
"REM",
|
||||
"REMU",
|
||||
"DIVW",
|
||||
"DIVUW",
|
||||
"REMW",
|
||||
"REMUW",
|
||||
"LRD",
|
||||
"SCD",
|
||||
"LRW",
|
||||
"SCW",
|
||||
"AMOSWAPD",
|
||||
"AMOADDD",
|
||||
"AMOANDD",
|
||||
"AMOORD",
|
||||
"AMOXORD",
|
||||
"AMOMAXD",
|
||||
"AMOMAXUD",
|
||||
"AMOMIND",
|
||||
"AMOMINUD",
|
||||
"AMOSWAPW",
|
||||
"AMOADDW",
|
||||
"AMOANDW",
|
||||
"AMOORW",
|
||||
"AMOXORW",
|
||||
"AMOMAXW",
|
||||
"AMOMAXUW",
|
||||
"AMOMINW",
|
||||
"AMOMINUW",
|
||||
"RDCYCLE",
|
||||
"RDCYCLEH",
|
||||
"RDTIME",
|
||||
"RDTIMEH",
|
||||
"RDINSTRET",
|
||||
"RDINSTRETH",
|
||||
"FRCSR",
|
||||
"FSCSR",
|
||||
"FRRM",
|
||||
"FSRM",
|
||||
"FRFLAGS",
|
||||
"FSFLAGS",
|
||||
"FSRMI",
|
||||
"FSFLAGSI",
|
||||
"FLW",
|
||||
"FSW",
|
||||
"FADDS",
|
||||
"FSUBS",
|
||||
"FMULS",
|
||||
"FDIVS",
|
||||
"FMINS",
|
||||
"FMAXS",
|
||||
"FSQRTS",
|
||||
"FMADDS",
|
||||
"FMSUBS",
|
||||
"FNMADDS",
|
||||
"FNMSUBS",
|
||||
"FCVTWS",
|
||||
"FCVTLS",
|
||||
"FCVTSW",
|
||||
"FCVTSL",
|
||||
"FCVTWUS",
|
||||
"FCVTLUS",
|
||||
"FCVTSWU",
|
||||
"FCVTSLU",
|
||||
"FSGNJS",
|
||||
"FSGNJNS",
|
||||
"FSGNJXS",
|
||||
"FMVXS",
|
||||
"FMVSX",
|
||||
"FMVXW",
|
||||
"FMVWX",
|
||||
"FEQS",
|
||||
"FLTS",
|
||||
"FLES",
|
||||
"FCLASSS",
|
||||
"FLD",
|
||||
"FSD",
|
||||
"FADDD",
|
||||
"FSUBD",
|
||||
"FMULD",
|
||||
"FDIVD",
|
||||
"FMIND",
|
||||
"FMAXD",
|
||||
"FSQRTD",
|
||||
"FMADDD",
|
||||
"FMSUBD",
|
||||
"FNMADDD",
|
||||
"FNMSUBD",
|
||||
"FCVTWD",
|
||||
"FCVTLD",
|
||||
"FCVTDW",
|
||||
"FCVTDL",
|
||||
"FCVTWUD",
|
||||
"FCVTLUD",
|
||||
"FCVTDWU",
|
||||
"FCVTDLU",
|
||||
"FCVTSD",
|
||||
"FCVTDS",
|
||||
"FSGNJD",
|
||||
"FSGNJND",
|
||||
"FSGNJXD",
|
||||
"FMVXD",
|
||||
"FMVDX",
|
||||
"FEQD",
|
||||
"FLTD",
|
||||
"FLED",
|
||||
"FCLASSD",
|
||||
"FLQ",
|
||||
"FSQ",
|
||||
"FADDQ",
|
||||
"FSUBQ",
|
||||
"FMULQ",
|
||||
"FDIVQ",
|
||||
"FMINQ",
|
||||
"FMAXQ",
|
||||
"FSQRTQ",
|
||||
"FMADDQ",
|
||||
"FMSUBQ",
|
||||
"FNMADDQ",
|
||||
"FNMSUBQ",
|
||||
"FCVTWQ",
|
||||
"FCVTLQ",
|
||||
"FCVTSQ",
|
||||
"FCVTDQ",
|
||||
"FCVTQW",
|
||||
"FCVTQL",
|
||||
"FCVTQS",
|
||||
"FCVTQD",
|
||||
"FCVTWUQ",
|
||||
"FCVTLUQ",
|
||||
"FCVTQWU",
|
||||
"FCVTQLU",
|
||||
"FSGNJQ",
|
||||
"FSGNJNQ",
|
||||
"FSGNJXQ",
|
||||
"FMVXQ",
|
||||
"FMVQX",
|
||||
"FEQQ",
|
||||
"FLEQ",
|
||||
"FLTQ",
|
||||
"FCLASSQ",
|
||||
"CSRRW",
|
||||
"CSRRS",
|
||||
"CSRRC",
|
||||
"CSRRWI",
|
||||
"CSRRSI",
|
||||
"CSRRCI",
|
||||
"ECALL",
|
||||
"SCALL",
|
||||
"EBREAK",
|
||||
"SBREAK",
|
||||
"MRET",
|
||||
"SRET",
|
||||
"URET",
|
||||
"DRET",
|
||||
"WFI",
|
||||
"SFENCEVMA",
|
||||
"HFENCEGVMA",
|
||||
"HFENCEVVMA",
|
||||
"WORD",
|
||||
"BEQZ",
|
||||
"BGEZ",
|
||||
"BGT",
|
||||
"BGTU",
|
||||
"BGTZ",
|
||||
"BLE",
|
||||
"BLEU",
|
||||
"BLEZ",
|
||||
"BLTZ",
|
||||
"BNEZ",
|
||||
"FNEGD",
|
||||
"FNEGS",
|
||||
"FNED",
|
||||
"FNES",
|
||||
"MOV",
|
||||
"MOVB",
|
||||
"MOVBU",
|
||||
"MOVF",
|
||||
"MOVD",
|
||||
"MOVH",
|
||||
"MOVHU",
|
||||
"MOVW",
|
||||
"MOVWU",
|
||||
"NEG",
|
||||
"NEGW",
|
||||
"NOT",
|
||||
"SEQZ",
|
||||
"SNEZ",
|
||||
"LAST",
|
||||
}
|
||||
644
vendor/github.com/twitchyliquid64/golang-asm/obj/riscv/cpu.go
generated
vendored
Normal file
644
vendor/github.com/twitchyliquid64/golang-asm/obj/riscv/cpu.go
generated
vendored
Normal file
@@ -0,0 +1,644 @@
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
// Portions Copyright © 2019 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package riscv
|
||||
|
||||
import "github.com/twitchyliquid64/golang-asm/obj"
|
||||
|
||||
//go:generate go run ../stringer.go -i $GOFILE -o anames.go -p riscv
|
||||
|
||||
const (
|
||||
// Base register numberings.
|
||||
REG_X0 = obj.RBaseRISCV + iota
|
||||
REG_X1
|
||||
REG_X2
|
||||
REG_X3
|
||||
REG_X4
|
||||
REG_X5
|
||||
REG_X6
|
||||
REG_X7
|
||||
REG_X8
|
||||
REG_X9
|
||||
REG_X10
|
||||
REG_X11
|
||||
REG_X12
|
||||
REG_X13
|
||||
REG_X14
|
||||
REG_X15
|
||||
REG_X16
|
||||
REG_X17
|
||||
REG_X18
|
||||
REG_X19
|
||||
REG_X20
|
||||
REG_X21
|
||||
REG_X22
|
||||
REG_X23
|
||||
REG_X24
|
||||
REG_X25
|
||||
REG_X26
|
||||
REG_X27
|
||||
REG_X28
|
||||
REG_X29
|
||||
REG_X30
|
||||
REG_X31
|
||||
|
||||
// FP register numberings.
|
||||
REG_F0
|
||||
REG_F1
|
||||
REG_F2
|
||||
REG_F3
|
||||
REG_F4
|
||||
REG_F5
|
||||
REG_F6
|
||||
REG_F7
|
||||
REG_F8
|
||||
REG_F9
|
||||
REG_F10
|
||||
REG_F11
|
||||
REG_F12
|
||||
REG_F13
|
||||
REG_F14
|
||||
REG_F15
|
||||
REG_F16
|
||||
REG_F17
|
||||
REG_F18
|
||||
REG_F19
|
||||
REG_F20
|
||||
REG_F21
|
||||
REG_F22
|
||||
REG_F23
|
||||
REG_F24
|
||||
REG_F25
|
||||
REG_F26
|
||||
REG_F27
|
||||
REG_F28
|
||||
REG_F29
|
||||
REG_F30
|
||||
REG_F31
|
||||
|
||||
// This marks the end of the register numbering.
|
||||
REG_END
|
||||
|
||||
// General registers reassigned to ABI names.
|
||||
REG_ZERO = REG_X0
|
||||
REG_RA = REG_X1 // aka REG_LR
|
||||
REG_SP = REG_X2
|
||||
REG_GP = REG_X3 // aka REG_SB
|
||||
REG_TP = REG_X4 // aka REG_G
|
||||
REG_T0 = REG_X5
|
||||
REG_T1 = REG_X6
|
||||
REG_T2 = REG_X7
|
||||
REG_S0 = REG_X8
|
||||
REG_S1 = REG_X9
|
||||
REG_A0 = REG_X10
|
||||
REG_A1 = REG_X11
|
||||
REG_A2 = REG_X12
|
||||
REG_A3 = REG_X13
|
||||
REG_A4 = REG_X14
|
||||
REG_A5 = REG_X15
|
||||
REG_A6 = REG_X16
|
||||
REG_A7 = REG_X17
|
||||
REG_S2 = REG_X18
|
||||
REG_S3 = REG_X19
|
||||
REG_S4 = REG_X20 // aka REG_CTXT
|
||||
REG_S5 = REG_X21
|
||||
REG_S6 = REG_X22
|
||||
REG_S7 = REG_X23
|
||||
REG_S8 = REG_X24
|
||||
REG_S9 = REG_X25
|
||||
REG_S10 = REG_X26
|
||||
REG_S11 = REG_X27
|
||||
REG_T3 = REG_X28
|
||||
REG_T4 = REG_X29
|
||||
REG_T5 = REG_X30
|
||||
REG_T6 = REG_X31 // aka REG_TMP
|
||||
|
||||
// Go runtime register names.
|
||||
REG_G = REG_TP // G pointer.
|
||||
REG_CTXT = REG_S4 // Context for closures.
|
||||
REG_LR = REG_RA // Link register.
|
||||
REG_TMP = REG_T6 // Reserved for assembler use.
|
||||
|
||||
// ABI names for floating point registers.
|
||||
REG_FT0 = REG_F0
|
||||
REG_FT1 = REG_F1
|
||||
REG_FT2 = REG_F2
|
||||
REG_FT3 = REG_F3
|
||||
REG_FT4 = REG_F4
|
||||
REG_FT5 = REG_F5
|
||||
REG_FT6 = REG_F6
|
||||
REG_FT7 = REG_F7
|
||||
REG_FS0 = REG_F8
|
||||
REG_FS1 = REG_F9
|
||||
REG_FA0 = REG_F10
|
||||
REG_FA1 = REG_F11
|
||||
REG_FA2 = REG_F12
|
||||
REG_FA3 = REG_F13
|
||||
REG_FA4 = REG_F14
|
||||
REG_FA5 = REG_F15
|
||||
REG_FA6 = REG_F16
|
||||
REG_FA7 = REG_F17
|
||||
REG_FS2 = REG_F18
|
||||
REG_FS3 = REG_F19
|
||||
REG_FS4 = REG_F20
|
||||
REG_FS5 = REG_F21
|
||||
REG_FS6 = REG_F22
|
||||
REG_FS7 = REG_F23
|
||||
REG_FS8 = REG_F24
|
||||
REG_FS9 = REG_F25
|
||||
REG_FS10 = REG_F26
|
||||
REG_FS11 = REG_F27
|
||||
REG_FT8 = REG_F28
|
||||
REG_FT9 = REG_F29
|
||||
REG_FT10 = REG_F30
|
||||
REG_FT11 = REG_F31
|
||||
|
||||
// Names generated by the SSA compiler.
|
||||
REGSP = REG_SP
|
||||
REGG = REG_G
|
||||
)
|
||||
|
||||
// https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md#dwarf-register-numbers
|
||||
var RISCV64DWARFRegisters = map[int16]int16{
|
||||
// Integer Registers.
|
||||
REG_X0: 0,
|
||||
REG_X1: 1,
|
||||
REG_X2: 2,
|
||||
REG_X3: 3,
|
||||
REG_X4: 4,
|
||||
REG_X5: 5,
|
||||
REG_X6: 6,
|
||||
REG_X7: 7,
|
||||
REG_X8: 8,
|
||||
REG_X9: 9,
|
||||
REG_X10: 10,
|
||||
REG_X11: 11,
|
||||
REG_X12: 12,
|
||||
REG_X13: 13,
|
||||
REG_X14: 14,
|
||||
REG_X15: 15,
|
||||
REG_X16: 16,
|
||||
REG_X17: 17,
|
||||
REG_X18: 18,
|
||||
REG_X19: 19,
|
||||
REG_X20: 20,
|
||||
REG_X21: 21,
|
||||
REG_X22: 22,
|
||||
REG_X23: 23,
|
||||
REG_X24: 24,
|
||||
REG_X25: 25,
|
||||
REG_X26: 26,
|
||||
REG_X27: 27,
|
||||
REG_X28: 28,
|
||||
REG_X29: 29,
|
||||
REG_X30: 30,
|
||||
REG_X31: 31,
|
||||
|
||||
// Floating-Point Registers.
|
||||
REG_F0: 32,
|
||||
REG_F1: 33,
|
||||
REG_F2: 34,
|
||||
REG_F3: 35,
|
||||
REG_F4: 36,
|
||||
REG_F5: 37,
|
||||
REG_F6: 38,
|
||||
REG_F7: 39,
|
||||
REG_F8: 40,
|
||||
REG_F9: 41,
|
||||
REG_F10: 42,
|
||||
REG_F11: 43,
|
||||
REG_F12: 44,
|
||||
REG_F13: 45,
|
||||
REG_F14: 46,
|
||||
REG_F15: 47,
|
||||
REG_F16: 48,
|
||||
REG_F17: 49,
|
||||
REG_F18: 50,
|
||||
REG_F19: 51,
|
||||
REG_F20: 52,
|
||||
REG_F21: 53,
|
||||
REG_F22: 54,
|
||||
REG_F23: 55,
|
||||
REG_F24: 56,
|
||||
REG_F25: 57,
|
||||
REG_F26: 58,
|
||||
REG_F27: 59,
|
||||
REG_F28: 60,
|
||||
REG_F29: 61,
|
||||
REG_F30: 62,
|
||||
REG_F31: 63,
|
||||
}
|
||||
|
||||
// Prog.Mark flags.
|
||||
const (
|
||||
// NEED_PCREL_ITYPE_RELOC is set on AUIPC instructions to indicate that
|
||||
// it is the first instruction in an AUIPC + I-type pair that needs a
|
||||
// R_RISCV_PCREL_ITYPE relocation.
|
||||
NEED_PCREL_ITYPE_RELOC = 1 << 0
|
||||
|
||||
// NEED_PCREL_STYPE_RELOC is set on AUIPC instructions to indicate that
|
||||
// it is the first instruction in an AUIPC + S-type pair that needs a
|
||||
// R_RISCV_PCREL_STYPE relocation.
|
||||
NEED_PCREL_STYPE_RELOC = 1 << 1
|
||||
)
|
||||
|
||||
// RISC-V mnemonics, as defined in the "opcodes" and "opcodes-pseudo" files
|
||||
// from:
|
||||
//
|
||||
// https://github.com/riscv/riscv-opcodes
|
||||
//
|
||||
// As well as some pseudo-mnemonics (e.g. MOV) used only in the assembler.
|
||||
//
|
||||
// See also "The RISC-V Instruction Set Manual" at:
|
||||
//
|
||||
// https://riscv.org/specifications/
|
||||
//
|
||||
// If you modify this table, you MUST run 'go generate' to regenerate anames.go!
|
||||
const (
|
||||
// Unprivileged ISA (Document Version 20190608-Base-Ratified)
|
||||
|
||||
// 2.4: Integer Computational Instructions
|
||||
AADDI = obj.ABaseRISCV + obj.A_ARCHSPECIFIC + iota
|
||||
ASLTI
|
||||
ASLTIU
|
||||
AANDI
|
||||
AORI
|
||||
AXORI
|
||||
ASLLI
|
||||
ASRLI
|
||||
ASRAI
|
||||
ALUI
|
||||
AAUIPC
|
||||
AADD
|
||||
ASLT
|
||||
ASLTU
|
||||
AAND
|
||||
AOR
|
||||
AXOR
|
||||
ASLL
|
||||
ASRL
|
||||
ASUB
|
||||
ASRA
|
||||
|
||||
// The SLL/SRL/SRA instructions differ slightly between RV32 and RV64,
|
||||
// hence there are pseudo-opcodes for the RV32 specific versions.
|
||||
ASLLIRV32
|
||||
ASRLIRV32
|
||||
ASRAIRV32
|
||||
|
||||
// 2.5: Control Transfer Instructions
|
||||
AJAL
|
||||
AJALR
|
||||
ABEQ
|
||||
ABNE
|
||||
ABLT
|
||||
ABLTU
|
||||
ABGE
|
||||
ABGEU
|
||||
|
||||
// 2.6: Load and Store Instructions
|
||||
ALW
|
||||
ALWU
|
||||
ALH
|
||||
ALHU
|
||||
ALB
|
||||
ALBU
|
||||
ASW
|
||||
ASH
|
||||
ASB
|
||||
|
||||
// 2.7: Memory Ordering Instructions
|
||||
AFENCE
|
||||
AFENCEI
|
||||
AFENCETSO
|
||||
|
||||
// 5.2: Integer Computational Instructions (RV64I)
|
||||
AADDIW
|
||||
ASLLIW
|
||||
ASRLIW
|
||||
ASRAIW
|
||||
AADDW
|
||||
ASLLW
|
||||
ASRLW
|
||||
ASUBW
|
||||
ASRAW
|
||||
|
||||
// 5.3: Load and Store Instructions (RV64I)
|
||||
ALD
|
||||
ASD
|
||||
|
||||
// 7.1: Multiplication Operations
|
||||
AMUL
|
||||
AMULH
|
||||
AMULHU
|
||||
AMULHSU
|
||||
AMULW
|
||||
ADIV
|
||||
ADIVU
|
||||
AREM
|
||||
AREMU
|
||||
ADIVW
|
||||
ADIVUW
|
||||
AREMW
|
||||
AREMUW
|
||||
|
||||
// 8.2: Load-Reserved/Store-Conditional Instructions
|
||||
ALRD
|
||||
ASCD
|
||||
ALRW
|
||||
ASCW
|
||||
|
||||
// 8.3: Atomic Memory Operations
|
||||
AAMOSWAPD
|
||||
AAMOADDD
|
||||
AAMOANDD
|
||||
AAMOORD
|
||||
AAMOXORD
|
||||
AAMOMAXD
|
||||
AAMOMAXUD
|
||||
AAMOMIND
|
||||
AAMOMINUD
|
||||
AAMOSWAPW
|
||||
AAMOADDW
|
||||
AAMOANDW
|
||||
AAMOORW
|
||||
AAMOXORW
|
||||
AAMOMAXW
|
||||
AAMOMAXUW
|
||||
AAMOMINW
|
||||
AAMOMINUW
|
||||
|
||||
// 10.1: Base Counters and Timers
|
||||
ARDCYCLE
|
||||
ARDCYCLEH
|
||||
ARDTIME
|
||||
ARDTIMEH
|
||||
ARDINSTRET
|
||||
ARDINSTRETH
|
||||
|
||||
// 11.2: Floating-Point Control and Status Register
|
||||
AFRCSR
|
||||
AFSCSR
|
||||
AFRRM
|
||||
AFSRM
|
||||
AFRFLAGS
|
||||
AFSFLAGS
|
||||
AFSRMI
|
||||
AFSFLAGSI
|
||||
|
||||
// 11.5: Single-Precision Load and Store Instructions
|
||||
AFLW
|
||||
AFSW
|
||||
|
||||
// 11.6: Single-Precision Floating-Point Computational Instructions
|
||||
AFADDS
|
||||
AFSUBS
|
||||
AFMULS
|
||||
AFDIVS
|
||||
AFMINS
|
||||
AFMAXS
|
||||
AFSQRTS
|
||||
AFMADDS
|
||||
AFMSUBS
|
||||
AFNMADDS
|
||||
AFNMSUBS
|
||||
|
||||
// 11.7: Single-Precision Floating-Point Conversion and Move Instructions
|
||||
AFCVTWS
|
||||
AFCVTLS
|
||||
AFCVTSW
|
||||
AFCVTSL
|
||||
AFCVTWUS
|
||||
AFCVTLUS
|
||||
AFCVTSWU
|
||||
AFCVTSLU
|
||||
AFSGNJS
|
||||
AFSGNJNS
|
||||
AFSGNJXS
|
||||
AFMVXS
|
||||
AFMVSX
|
||||
AFMVXW
|
||||
AFMVWX
|
||||
|
||||
// 11.8: Single-Precision Floating-Point Compare Instructions
|
||||
AFEQS
|
||||
AFLTS
|
||||
AFLES
|
||||
|
||||
// 11.9: Single-Precision Floating-Point Classify Instruction
|
||||
AFCLASSS
|
||||
|
||||
// 12.3: Double-Precision Load and Store Instructions
|
||||
AFLD
|
||||
AFSD
|
||||
|
||||
// 12.4: Double-Precision Floating-Point Computational Instructions
|
||||
AFADDD
|
||||
AFSUBD
|
||||
AFMULD
|
||||
AFDIVD
|
||||
AFMIND
|
||||
AFMAXD
|
||||
AFSQRTD
|
||||
AFMADDD
|
||||
AFMSUBD
|
||||
AFNMADDD
|
||||
AFNMSUBD
|
||||
|
||||
// 12.5: Double-Precision Floating-Point Conversion and Move Instructions
|
||||
AFCVTWD
|
||||
AFCVTLD
|
||||
AFCVTDW
|
||||
AFCVTDL
|
||||
AFCVTWUD
|
||||
AFCVTLUD
|
||||
AFCVTDWU
|
||||
AFCVTDLU
|
||||
AFCVTSD
|
||||
AFCVTDS
|
||||
AFSGNJD
|
||||
AFSGNJND
|
||||
AFSGNJXD
|
||||
AFMVXD
|
||||
AFMVDX
|
||||
|
||||
// 12.6: Double-Precision Floating-Point Compare Instructions
|
||||
AFEQD
|
||||
AFLTD
|
||||
AFLED
|
||||
|
||||
// 12.7: Double-Precision Floating-Point Classify Instruction
|
||||
AFCLASSD
|
||||
|
||||
// 13.1 Quad-Precision Load and Store Instructions
|
||||
AFLQ
|
||||
AFSQ
|
||||
|
||||
// 13.2: Quad-Precision Computational Instructions
|
||||
AFADDQ
|
||||
AFSUBQ
|
||||
AFMULQ
|
||||
AFDIVQ
|
||||
AFMINQ
|
||||
AFMAXQ
|
||||
AFSQRTQ
|
||||
AFMADDQ
|
||||
AFMSUBQ
|
||||
AFNMADDQ
|
||||
AFNMSUBQ
|
||||
|
||||
// 13.3 Quad-Precision Convert and Move Instructions
|
||||
AFCVTWQ
|
||||
AFCVTLQ
|
||||
AFCVTSQ
|
||||
AFCVTDQ
|
||||
AFCVTQW
|
||||
AFCVTQL
|
||||
AFCVTQS
|
||||
AFCVTQD
|
||||
AFCVTWUQ
|
||||
AFCVTLUQ
|
||||
AFCVTQWU
|
||||
AFCVTQLU
|
||||
AFSGNJQ
|
||||
AFSGNJNQ
|
||||
AFSGNJXQ
|
||||
AFMVXQ
|
||||
AFMVQX
|
||||
|
||||
// 13.4 Quad-Precision Floating-Point Compare Instructions
|
||||
AFEQQ
|
||||
AFLEQ
|
||||
AFLTQ
|
||||
|
||||
// 13.5 Quad-Precision Floating-Point Classify Instruction
|
||||
AFCLASSQ
|
||||
|
||||
// Privileged ISA (Version 20190608-Priv-MSU-Ratified)
|
||||
|
||||
// 3.1.9: Instructions to Access CSRs
|
||||
ACSRRW
|
||||
ACSRRS
|
||||
ACSRRC
|
||||
ACSRRWI
|
||||
ACSRRSI
|
||||
ACSRRCI
|
||||
|
||||
// 3.2.1: Environment Call and Breakpoint
|
||||
AECALL
|
||||
ASCALL
|
||||
AEBREAK
|
||||
ASBREAK
|
||||
|
||||
// 3.2.2: Trap-Return Instructions
|
||||
AMRET
|
||||
ASRET
|
||||
AURET
|
||||
ADRET
|
||||
|
||||
// 3.2.3: Wait for Interrupt
|
||||
AWFI
|
||||
|
||||
// 4.2.1: Supervisor Memory-Management Fence Instruction
|
||||
ASFENCEVMA
|
||||
|
||||
// Hypervisor Memory-Management Instructions
|
||||
AHFENCEGVMA
|
||||
AHFENCEVVMA
|
||||
|
||||
// The escape hatch. Inserts a single 32-bit word.
|
||||
AWORD
|
||||
|
||||
// Pseudo-instructions. These get translated by the assembler into other
|
||||
// instructions, based on their operands.
|
||||
ABEQZ
|
||||
ABGEZ
|
||||
ABGT
|
||||
ABGTU
|
||||
ABGTZ
|
||||
ABLE
|
||||
ABLEU
|
||||
ABLEZ
|
||||
ABLTZ
|
||||
ABNEZ
|
||||
AFNEGD
|
||||
AFNEGS
|
||||
AFNED
|
||||
AFNES
|
||||
AMOV
|
||||
AMOVB
|
||||
AMOVBU
|
||||
AMOVF
|
||||
AMOVD
|
||||
AMOVH
|
||||
AMOVHU
|
||||
AMOVW
|
||||
AMOVWU
|
||||
ANEG
|
||||
ANEGW
|
||||
ANOT
|
||||
ASEQZ
|
||||
ASNEZ
|
||||
|
||||
// End marker
|
||||
ALAST
|
||||
)
|
||||
|
||||
// All unary instructions which write to their arguments (as opposed to reading
|
||||
// from them) go here. The assembly parser uses this information to populate
|
||||
// its AST in a semantically reasonable way.
|
||||
//
|
||||
// Any instructions not listed here are assumed to either be non-unary or to read
|
||||
// from its argument.
|
||||
var unaryDst = map[obj.As]bool{
|
||||
ARDCYCLE: true,
|
||||
ARDCYCLEH: true,
|
||||
ARDTIME: true,
|
||||
ARDTIMEH: true,
|
||||
ARDINSTRET: true,
|
||||
ARDINSTRETH: true,
|
||||
}
|
||||
|
||||
// Instruction encoding masks.
|
||||
const (
|
||||
// ITypeImmMask is a mask including only the immediate portion of
|
||||
// I-type instructions.
|
||||
ITypeImmMask = 0xfff00000
|
||||
|
||||
// STypeImmMask is a mask including only the immediate portion of
|
||||
// S-type instructions.
|
||||
STypeImmMask = 0xfe000f80
|
||||
|
||||
// UTypeImmMask is a mask including only the immediate portion of
|
||||
// U-type instructions.
|
||||
UTypeImmMask = 0xfffff000
|
||||
|
||||
// UJTypeImmMask is a mask including only the immediate portion of
|
||||
// UJ-type instructions.
|
||||
UJTypeImmMask = UTypeImmMask
|
||||
)
|
||||
459
vendor/github.com/twitchyliquid64/golang-asm/obj/riscv/inst.go
generated
vendored
Normal file
459
vendor/github.com/twitchyliquid64/golang-asm/obj/riscv/inst.go
generated
vendored
Normal file
@@ -0,0 +1,459 @@
|
||||
// Code generated by parse_opcodes -go; DO NOT EDIT.
|
||||
|
||||
package riscv
|
||||
|
||||
import "github.com/twitchyliquid64/golang-asm/obj"
|
||||
|
||||
type inst struct {
|
||||
opcode uint32
|
||||
funct3 uint32
|
||||
rs2 uint32
|
||||
csr int64
|
||||
funct7 uint32
|
||||
}
|
||||
|
||||
func encode(a obj.As) *inst {
|
||||
switch a {
|
||||
case ABEQ:
|
||||
return &inst{0x63, 0x0, 0x0, 0, 0x0}
|
||||
case ABNE:
|
||||
return &inst{0x63, 0x1, 0x0, 0, 0x0}
|
||||
case ABLT:
|
||||
return &inst{0x63, 0x4, 0x0, 0, 0x0}
|
||||
case ABGE:
|
||||
return &inst{0x63, 0x5, 0x0, 0, 0x0}
|
||||
case ABLTU:
|
||||
return &inst{0x63, 0x6, 0x0, 0, 0x0}
|
||||
case ABGEU:
|
||||
return &inst{0x63, 0x7, 0x0, 0, 0x0}
|
||||
case AJALR:
|
||||
return &inst{0x67, 0x0, 0x0, 0, 0x0}
|
||||
case AJAL:
|
||||
return &inst{0x6f, 0x0, 0x0, 0, 0x0}
|
||||
case ALUI:
|
||||
return &inst{0x37, 0x0, 0x0, 0, 0x0}
|
||||
case AAUIPC:
|
||||
return &inst{0x17, 0x0, 0x0, 0, 0x0}
|
||||
case AADDI:
|
||||
return &inst{0x13, 0x0, 0x0, 0, 0x0}
|
||||
case ASLLI:
|
||||
return &inst{0x13, 0x1, 0x0, 0, 0x0}
|
||||
case ASLTI:
|
||||
return &inst{0x13, 0x2, 0x0, 0, 0x0}
|
||||
case ASLTIU:
|
||||
return &inst{0x13, 0x3, 0x0, 0, 0x0}
|
||||
case AXORI:
|
||||
return &inst{0x13, 0x4, 0x0, 0, 0x0}
|
||||
case ASRLI:
|
||||
return &inst{0x13, 0x5, 0x0, 0, 0x0}
|
||||
case ASRAI:
|
||||
return &inst{0x13, 0x5, 0x0, 1024, 0x20}
|
||||
case AORI:
|
||||
return &inst{0x13, 0x6, 0x0, 0, 0x0}
|
||||
case AANDI:
|
||||
return &inst{0x13, 0x7, 0x0, 0, 0x0}
|
||||
case AADD:
|
||||
return &inst{0x33, 0x0, 0x0, 0, 0x0}
|
||||
case ASUB:
|
||||
return &inst{0x33, 0x0, 0x0, 1024, 0x20}
|
||||
case ASLL:
|
||||
return &inst{0x33, 0x1, 0x0, 0, 0x0}
|
||||
case ASLT:
|
||||
return &inst{0x33, 0x2, 0x0, 0, 0x0}
|
||||
case ASLTU:
|
||||
return &inst{0x33, 0x3, 0x0, 0, 0x0}
|
||||
case AXOR:
|
||||
return &inst{0x33, 0x4, 0x0, 0, 0x0}
|
||||
case ASRL:
|
||||
return &inst{0x33, 0x5, 0x0, 0, 0x0}
|
||||
case ASRA:
|
||||
return &inst{0x33, 0x5, 0x0, 1024, 0x20}
|
||||
case AOR:
|
||||
return &inst{0x33, 0x6, 0x0, 0, 0x0}
|
||||
case AAND:
|
||||
return &inst{0x33, 0x7, 0x0, 0, 0x0}
|
||||
case AADDIW:
|
||||
return &inst{0x1b, 0x0, 0x0, 0, 0x0}
|
||||
case ASLLIW:
|
||||
return &inst{0x1b, 0x1, 0x0, 0, 0x0}
|
||||
case ASRLIW:
|
||||
return &inst{0x1b, 0x5, 0x0, 0, 0x0}
|
||||
case ASRAIW:
|
||||
return &inst{0x1b, 0x5, 0x0, 1024, 0x20}
|
||||
case AADDW:
|
||||
return &inst{0x3b, 0x0, 0x0, 0, 0x0}
|
||||
case ASUBW:
|
||||
return &inst{0x3b, 0x0, 0x0, 1024, 0x20}
|
||||
case ASLLW:
|
||||
return &inst{0x3b, 0x1, 0x0, 0, 0x0}
|
||||
case ASRLW:
|
||||
return &inst{0x3b, 0x5, 0x0, 0, 0x0}
|
||||
case ASRAW:
|
||||
return &inst{0x3b, 0x5, 0x0, 1024, 0x20}
|
||||
case ALB:
|
||||
return &inst{0x3, 0x0, 0x0, 0, 0x0}
|
||||
case ALH:
|
||||
return &inst{0x3, 0x1, 0x0, 0, 0x0}
|
||||
case ALW:
|
||||
return &inst{0x3, 0x2, 0x0, 0, 0x0}
|
||||
case ALD:
|
||||
return &inst{0x3, 0x3, 0x0, 0, 0x0}
|
||||
case ALBU:
|
||||
return &inst{0x3, 0x4, 0x0, 0, 0x0}
|
||||
case ALHU:
|
||||
return &inst{0x3, 0x5, 0x0, 0, 0x0}
|
||||
case ALWU:
|
||||
return &inst{0x3, 0x6, 0x0, 0, 0x0}
|
||||
case ASB:
|
||||
return &inst{0x23, 0x0, 0x0, 0, 0x0}
|
||||
case ASH:
|
||||
return &inst{0x23, 0x1, 0x0, 0, 0x0}
|
||||
case ASW:
|
||||
return &inst{0x23, 0x2, 0x0, 0, 0x0}
|
||||
case ASD:
|
||||
return &inst{0x23, 0x3, 0x0, 0, 0x0}
|
||||
case AFENCE:
|
||||
return &inst{0xf, 0x0, 0x0, 0, 0x0}
|
||||
case AFENCEI:
|
||||
return &inst{0xf, 0x1, 0x0, 0, 0x0}
|
||||
case AMUL:
|
||||
return &inst{0x33, 0x0, 0x0, 32, 0x1}
|
||||
case AMULH:
|
||||
return &inst{0x33, 0x1, 0x0, 32, 0x1}
|
||||
case AMULHSU:
|
||||
return &inst{0x33, 0x2, 0x0, 32, 0x1}
|
||||
case AMULHU:
|
||||
return &inst{0x33, 0x3, 0x0, 32, 0x1}
|
||||
case ADIV:
|
||||
return &inst{0x33, 0x4, 0x0, 32, 0x1}
|
||||
case ADIVU:
|
||||
return &inst{0x33, 0x5, 0x0, 32, 0x1}
|
||||
case AREM:
|
||||
return &inst{0x33, 0x6, 0x0, 32, 0x1}
|
||||
case AREMU:
|
||||
return &inst{0x33, 0x7, 0x0, 32, 0x1}
|
||||
case AMULW:
|
||||
return &inst{0x3b, 0x0, 0x0, 32, 0x1}
|
||||
case ADIVW:
|
||||
return &inst{0x3b, 0x4, 0x0, 32, 0x1}
|
||||
case ADIVUW:
|
||||
return &inst{0x3b, 0x5, 0x0, 32, 0x1}
|
||||
case AREMW:
|
||||
return &inst{0x3b, 0x6, 0x0, 32, 0x1}
|
||||
case AREMUW:
|
||||
return &inst{0x3b, 0x7, 0x0, 32, 0x1}
|
||||
case AAMOADDW:
|
||||
return &inst{0x2f, 0x2, 0x0, 0, 0x0}
|
||||
case AAMOXORW:
|
||||
return &inst{0x2f, 0x2, 0x0, 512, 0x10}
|
||||
case AAMOORW:
|
||||
return &inst{0x2f, 0x2, 0x0, 1024, 0x20}
|
||||
case AAMOANDW:
|
||||
return &inst{0x2f, 0x2, 0x0, 1536, 0x30}
|
||||
case AAMOMINW:
|
||||
return &inst{0x2f, 0x2, 0x0, -2048, 0x40}
|
||||
case AAMOMAXW:
|
||||
return &inst{0x2f, 0x2, 0x0, -1536, 0x50}
|
||||
case AAMOMINUW:
|
||||
return &inst{0x2f, 0x2, 0x0, -1024, 0x60}
|
||||
case AAMOMAXUW:
|
||||
return &inst{0x2f, 0x2, 0x0, -512, 0x70}
|
||||
case AAMOSWAPW:
|
||||
return &inst{0x2f, 0x2, 0x0, 128, 0x4}
|
||||
case ALRW:
|
||||
return &inst{0x2f, 0x2, 0x0, 256, 0x8}
|
||||
case ASCW:
|
||||
return &inst{0x2f, 0x2, 0x0, 384, 0xc}
|
||||
case AAMOADDD:
|
||||
return &inst{0x2f, 0x3, 0x0, 0, 0x0}
|
||||
case AAMOXORD:
|
||||
return &inst{0x2f, 0x3, 0x0, 512, 0x10}
|
||||
case AAMOORD:
|
||||
return &inst{0x2f, 0x3, 0x0, 1024, 0x20}
|
||||
case AAMOANDD:
|
||||
return &inst{0x2f, 0x3, 0x0, 1536, 0x30}
|
||||
case AAMOMIND:
|
||||
return &inst{0x2f, 0x3, 0x0, -2048, 0x40}
|
||||
case AAMOMAXD:
|
||||
return &inst{0x2f, 0x3, 0x0, -1536, 0x50}
|
||||
case AAMOMINUD:
|
||||
return &inst{0x2f, 0x3, 0x0, -1024, 0x60}
|
||||
case AAMOMAXUD:
|
||||
return &inst{0x2f, 0x3, 0x0, -512, 0x70}
|
||||
case AAMOSWAPD:
|
||||
return &inst{0x2f, 0x3, 0x0, 128, 0x4}
|
||||
case ALRD:
|
||||
return &inst{0x2f, 0x3, 0x0, 256, 0x8}
|
||||
case ASCD:
|
||||
return &inst{0x2f, 0x3, 0x0, 384, 0xc}
|
||||
case AECALL:
|
||||
return &inst{0x73, 0x0, 0x0, 0, 0x0}
|
||||
case AEBREAK:
|
||||
return &inst{0x73, 0x0, 0x1, 1, 0x0}
|
||||
case AURET:
|
||||
return &inst{0x73, 0x0, 0x2, 2, 0x0}
|
||||
case ASRET:
|
||||
return &inst{0x73, 0x0, 0x2, 258, 0x8}
|
||||
case AMRET:
|
||||
return &inst{0x73, 0x0, 0x2, 770, 0x18}
|
||||
case ADRET:
|
||||
return &inst{0x73, 0x0, 0x12, 1970, 0x3d}
|
||||
case ASFENCEVMA:
|
||||
return &inst{0x73, 0x0, 0x0, 288, 0x9}
|
||||
case AWFI:
|
||||
return &inst{0x73, 0x0, 0x5, 261, 0x8}
|
||||
case ACSRRW:
|
||||
return &inst{0x73, 0x1, 0x0, 0, 0x0}
|
||||
case ACSRRS:
|
||||
return &inst{0x73, 0x2, 0x0, 0, 0x0}
|
||||
case ACSRRC:
|
||||
return &inst{0x73, 0x3, 0x0, 0, 0x0}
|
||||
case ACSRRWI:
|
||||
return &inst{0x73, 0x5, 0x0, 0, 0x0}
|
||||
case ACSRRSI:
|
||||
return &inst{0x73, 0x6, 0x0, 0, 0x0}
|
||||
case ACSRRCI:
|
||||
return &inst{0x73, 0x7, 0x0, 0, 0x0}
|
||||
case AHFENCEVVMA:
|
||||
return &inst{0x73, 0x0, 0x0, 544, 0x11}
|
||||
case AHFENCEGVMA:
|
||||
return &inst{0x73, 0x0, 0x0, 1568, 0x31}
|
||||
case AFADDS:
|
||||
return &inst{0x53, 0x0, 0x0, 0, 0x0}
|
||||
case AFSUBS:
|
||||
return &inst{0x53, 0x0, 0x0, 128, 0x4}
|
||||
case AFMULS:
|
||||
return &inst{0x53, 0x0, 0x0, 256, 0x8}
|
||||
case AFDIVS:
|
||||
return &inst{0x53, 0x0, 0x0, 384, 0xc}
|
||||
case AFSGNJS:
|
||||
return &inst{0x53, 0x0, 0x0, 512, 0x10}
|
||||
case AFSGNJNS:
|
||||
return &inst{0x53, 0x1, 0x0, 512, 0x10}
|
||||
case AFSGNJXS:
|
||||
return &inst{0x53, 0x2, 0x0, 512, 0x10}
|
||||
case AFMINS:
|
||||
return &inst{0x53, 0x0, 0x0, 640, 0x14}
|
||||
case AFMAXS:
|
||||
return &inst{0x53, 0x1, 0x0, 640, 0x14}
|
||||
case AFSQRTS:
|
||||
return &inst{0x53, 0x0, 0x0, 1408, 0x2c}
|
||||
case AFADDD:
|
||||
return &inst{0x53, 0x0, 0x0, 32, 0x1}
|
||||
case AFSUBD:
|
||||
return &inst{0x53, 0x0, 0x0, 160, 0x5}
|
||||
case AFMULD:
|
||||
return &inst{0x53, 0x0, 0x0, 288, 0x9}
|
||||
case AFDIVD:
|
||||
return &inst{0x53, 0x0, 0x0, 416, 0xd}
|
||||
case AFSGNJD:
|
||||
return &inst{0x53, 0x0, 0x0, 544, 0x11}
|
||||
case AFSGNJND:
|
||||
return &inst{0x53, 0x1, 0x0, 544, 0x11}
|
||||
case AFSGNJXD:
|
||||
return &inst{0x53, 0x2, 0x0, 544, 0x11}
|
||||
case AFMIND:
|
||||
return &inst{0x53, 0x0, 0x0, 672, 0x15}
|
||||
case AFMAXD:
|
||||
return &inst{0x53, 0x1, 0x0, 672, 0x15}
|
||||
case AFCVTSD:
|
||||
return &inst{0x53, 0x0, 0x1, 1025, 0x20}
|
||||
case AFCVTDS:
|
||||
return &inst{0x53, 0x0, 0x0, 1056, 0x21}
|
||||
case AFSQRTD:
|
||||
return &inst{0x53, 0x0, 0x0, 1440, 0x2d}
|
||||
case AFADDQ:
|
||||
return &inst{0x53, 0x0, 0x0, 96, 0x3}
|
||||
case AFSUBQ:
|
||||
return &inst{0x53, 0x0, 0x0, 224, 0x7}
|
||||
case AFMULQ:
|
||||
return &inst{0x53, 0x0, 0x0, 352, 0xb}
|
||||
case AFDIVQ:
|
||||
return &inst{0x53, 0x0, 0x0, 480, 0xf}
|
||||
case AFSGNJQ:
|
||||
return &inst{0x53, 0x0, 0x0, 608, 0x13}
|
||||
case AFSGNJNQ:
|
||||
return &inst{0x53, 0x1, 0x0, 608, 0x13}
|
||||
case AFSGNJXQ:
|
||||
return &inst{0x53, 0x2, 0x0, 608, 0x13}
|
||||
case AFMINQ:
|
||||
return &inst{0x53, 0x0, 0x0, 736, 0x17}
|
||||
case AFMAXQ:
|
||||
return &inst{0x53, 0x1, 0x0, 736, 0x17}
|
||||
case AFCVTSQ:
|
||||
return &inst{0x53, 0x0, 0x3, 1027, 0x20}
|
||||
case AFCVTQS:
|
||||
return &inst{0x53, 0x0, 0x0, 1120, 0x23}
|
||||
case AFCVTDQ:
|
||||
return &inst{0x53, 0x0, 0x3, 1059, 0x21}
|
||||
case AFCVTQD:
|
||||
return &inst{0x53, 0x0, 0x1, 1121, 0x23}
|
||||
case AFSQRTQ:
|
||||
return &inst{0x53, 0x0, 0x0, 1504, 0x2f}
|
||||
case AFLES:
|
||||
return &inst{0x53, 0x0, 0x0, -1536, 0x50}
|
||||
case AFLTS:
|
||||
return &inst{0x53, 0x1, 0x0, -1536, 0x50}
|
||||
case AFEQS:
|
||||
return &inst{0x53, 0x2, 0x0, -1536, 0x50}
|
||||
case AFLED:
|
||||
return &inst{0x53, 0x0, 0x0, -1504, 0x51}
|
||||
case AFLTD:
|
||||
return &inst{0x53, 0x1, 0x0, -1504, 0x51}
|
||||
case AFEQD:
|
||||
return &inst{0x53, 0x2, 0x0, -1504, 0x51}
|
||||
case AFLEQ:
|
||||
return &inst{0x53, 0x0, 0x0, -1440, 0x53}
|
||||
case AFLTQ:
|
||||
return &inst{0x53, 0x1, 0x0, -1440, 0x53}
|
||||
case AFEQQ:
|
||||
return &inst{0x53, 0x2, 0x0, -1440, 0x53}
|
||||
case AFCVTWS:
|
||||
return &inst{0x53, 0x0, 0x0, -1024, 0x60}
|
||||
case AFCVTWUS:
|
||||
return &inst{0x53, 0x0, 0x1, -1023, 0x60}
|
||||
case AFCVTLS:
|
||||
return &inst{0x53, 0x0, 0x2, -1022, 0x60}
|
||||
case AFCVTLUS:
|
||||
return &inst{0x53, 0x0, 0x3, -1021, 0x60}
|
||||
case AFMVXW:
|
||||
return &inst{0x53, 0x0, 0x0, -512, 0x70}
|
||||
case AFCLASSS:
|
||||
return &inst{0x53, 0x1, 0x0, -512, 0x70}
|
||||
case AFCVTWD:
|
||||
return &inst{0x53, 0x0, 0x0, -992, 0x61}
|
||||
case AFCVTWUD:
|
||||
return &inst{0x53, 0x0, 0x1, -991, 0x61}
|
||||
case AFCVTLD:
|
||||
return &inst{0x53, 0x0, 0x2, -990, 0x61}
|
||||
case AFCVTLUD:
|
||||
return &inst{0x53, 0x0, 0x3, -989, 0x61}
|
||||
case AFMVXD:
|
||||
return &inst{0x53, 0x0, 0x0, -480, 0x71}
|
||||
case AFCLASSD:
|
||||
return &inst{0x53, 0x1, 0x0, -480, 0x71}
|
||||
case AFCVTWQ:
|
||||
return &inst{0x53, 0x0, 0x0, -928, 0x63}
|
||||
case AFCVTWUQ:
|
||||
return &inst{0x53, 0x0, 0x1, -927, 0x63}
|
||||
case AFCVTLQ:
|
||||
return &inst{0x53, 0x0, 0x2, -926, 0x63}
|
||||
case AFCVTLUQ:
|
||||
return &inst{0x53, 0x0, 0x3, -925, 0x63}
|
||||
case AFMVXQ:
|
||||
return &inst{0x53, 0x0, 0x0, -416, 0x73}
|
||||
case AFCLASSQ:
|
||||
return &inst{0x53, 0x1, 0x0, -416, 0x73}
|
||||
case AFCVTSW:
|
||||
return &inst{0x53, 0x0, 0x0, -768, 0x68}
|
||||
case AFCVTSWU:
|
||||
return &inst{0x53, 0x0, 0x1, -767, 0x68}
|
||||
case AFCVTSL:
|
||||
return &inst{0x53, 0x0, 0x2, -766, 0x68}
|
||||
case AFCVTSLU:
|
||||
return &inst{0x53, 0x0, 0x3, -765, 0x68}
|
||||
case AFMVWX:
|
||||
return &inst{0x53, 0x0, 0x0, -256, 0x78}
|
||||
case AFCVTDW:
|
||||
return &inst{0x53, 0x0, 0x0, -736, 0x69}
|
||||
case AFCVTDWU:
|
||||
return &inst{0x53, 0x0, 0x1, -735, 0x69}
|
||||
case AFCVTDL:
|
||||
return &inst{0x53, 0x0, 0x2, -734, 0x69}
|
||||
case AFCVTDLU:
|
||||
return &inst{0x53, 0x0, 0x3, -733, 0x69}
|
||||
case AFMVDX:
|
||||
return &inst{0x53, 0x0, 0x0, -224, 0x79}
|
||||
case AFCVTQW:
|
||||
return &inst{0x53, 0x0, 0x0, -672, 0x6b}
|
||||
case AFCVTQWU:
|
||||
return &inst{0x53, 0x0, 0x1, -671, 0x6b}
|
||||
case AFCVTQL:
|
||||
return &inst{0x53, 0x0, 0x2, -670, 0x6b}
|
||||
case AFCVTQLU:
|
||||
return &inst{0x53, 0x0, 0x3, -669, 0x6b}
|
||||
case AFMVQX:
|
||||
return &inst{0x53, 0x0, 0x0, -160, 0x7b}
|
||||
case AFLW:
|
||||
return &inst{0x7, 0x2, 0x0, 0, 0x0}
|
||||
case AFLD:
|
||||
return &inst{0x7, 0x3, 0x0, 0, 0x0}
|
||||
case AFLQ:
|
||||
return &inst{0x7, 0x4, 0x0, 0, 0x0}
|
||||
case AFSW:
|
||||
return &inst{0x27, 0x2, 0x0, 0, 0x0}
|
||||
case AFSD:
|
||||
return &inst{0x27, 0x3, 0x0, 0, 0x0}
|
||||
case AFSQ:
|
||||
return &inst{0x27, 0x4, 0x0, 0, 0x0}
|
||||
case AFMADDS:
|
||||
return &inst{0x43, 0x0, 0x0, 0, 0x0}
|
||||
case AFMSUBS:
|
||||
return &inst{0x47, 0x0, 0x0, 0, 0x0}
|
||||
case AFNMSUBS:
|
||||
return &inst{0x4b, 0x0, 0x0, 0, 0x0}
|
||||
case AFNMADDS:
|
||||
return &inst{0x4f, 0x0, 0x0, 0, 0x0}
|
||||
case AFMADDD:
|
||||
return &inst{0x43, 0x0, 0x0, 32, 0x1}
|
||||
case AFMSUBD:
|
||||
return &inst{0x47, 0x0, 0x0, 32, 0x1}
|
||||
case AFNMSUBD:
|
||||
return &inst{0x4b, 0x0, 0x0, 32, 0x1}
|
||||
case AFNMADDD:
|
||||
return &inst{0x4f, 0x0, 0x0, 32, 0x1}
|
||||
case AFMADDQ:
|
||||
return &inst{0x43, 0x0, 0x0, 96, 0x3}
|
||||
case AFMSUBQ:
|
||||
return &inst{0x47, 0x0, 0x0, 96, 0x3}
|
||||
case AFNMSUBQ:
|
||||
return &inst{0x4b, 0x0, 0x0, 96, 0x3}
|
||||
case AFNMADDQ:
|
||||
return &inst{0x4f, 0x0, 0x0, 96, 0x3}
|
||||
case ASLLIRV32:
|
||||
return &inst{0x13, 0x1, 0x0, 0, 0x0}
|
||||
case ASRLIRV32:
|
||||
return &inst{0x13, 0x5, 0x0, 0, 0x0}
|
||||
case ASRAIRV32:
|
||||
return &inst{0x13, 0x5, 0x0, 1024, 0x20}
|
||||
case AFRFLAGS:
|
||||
return &inst{0x73, 0x2, 0x1, 1, 0x0}
|
||||
case AFSFLAGS:
|
||||
return &inst{0x73, 0x1, 0x1, 1, 0x0}
|
||||
case AFSFLAGSI:
|
||||
return &inst{0x73, 0x5, 0x1, 1, 0x0}
|
||||
case AFRRM:
|
||||
return &inst{0x73, 0x2, 0x2, 2, 0x0}
|
||||
case AFSRM:
|
||||
return &inst{0x73, 0x1, 0x2, 2, 0x0}
|
||||
case AFSRMI:
|
||||
return &inst{0x73, 0x5, 0x2, 2, 0x0}
|
||||
case AFSCSR:
|
||||
return &inst{0x73, 0x1, 0x3, 3, 0x0}
|
||||
case AFRCSR:
|
||||
return &inst{0x73, 0x2, 0x3, 3, 0x0}
|
||||
case ARDCYCLE:
|
||||
return &inst{0x73, 0x2, 0x0, -1024, 0x60}
|
||||
case ARDTIME:
|
||||
return &inst{0x73, 0x2, 0x1, -1023, 0x60}
|
||||
case ARDINSTRET:
|
||||
return &inst{0x73, 0x2, 0x2, -1022, 0x60}
|
||||
case ARDCYCLEH:
|
||||
return &inst{0x73, 0x2, 0x0, -896, 0x64}
|
||||
case ARDTIMEH:
|
||||
return &inst{0x73, 0x2, 0x1, -895, 0x64}
|
||||
case ARDINSTRETH:
|
||||
return &inst{0x73, 0x2, 0x2, -894, 0x64}
|
||||
case ASCALL:
|
||||
return &inst{0x73, 0x0, 0x0, 0, 0x0}
|
||||
case ASBREAK:
|
||||
return &inst{0x73, 0x0, 0x1, 1, 0x0}
|
||||
case AFMVXS:
|
||||
return &inst{0x53, 0x0, 0x0, -512, 0x70}
|
||||
case AFMVSX:
|
||||
return &inst{0x53, 0x0, 0x0, -256, 0x78}
|
||||
case AFENCETSO:
|
||||
return &inst{0xf, 0x0, 0x13, -1997, 0x41}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
33
vendor/github.com/twitchyliquid64/golang-asm/obj/riscv/list.go
generated
vendored
Normal file
33
vendor/github.com/twitchyliquid64/golang-asm/obj/riscv/list.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package riscv
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/twitchyliquid64/golang-asm/obj"
|
||||
)
|
||||
|
||||
func init() {
|
||||
obj.RegisterRegister(obj.RBaseRISCV, REG_END, RegName)
|
||||
obj.RegisterOpcode(obj.ABaseRISCV, Anames)
|
||||
}
|
||||
|
||||
func RegName(r int) string {
|
||||
switch {
|
||||
case r == 0:
|
||||
return "NONE"
|
||||
case r == REG_G:
|
||||
return "g"
|
||||
case r == REG_SP:
|
||||
return "SP"
|
||||
case REG_X0 <= r && r <= REG_X31:
|
||||
return fmt.Sprintf("X%d", r-REG_X0)
|
||||
case REG_F0 <= r && r <= REG_F31:
|
||||
return fmt.Sprintf("F%d", r-REG_F0)
|
||||
default:
|
||||
return fmt.Sprintf("Rgok(%d)", r-obj.RBaseRISCV)
|
||||
}
|
||||
}
|
||||
1999
vendor/github.com/twitchyliquid64/golang-asm/obj/riscv/obj.go
generated
vendored
Normal file
1999
vendor/github.com/twitchyliquid64/golang-asm/obj/riscv/obj.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1003
vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/a.out.go
generated
vendored
Normal file
1003
vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/a.out.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
720
vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/anames.go
generated
vendored
Normal file
720
vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/anames.go
generated
vendored
Normal file
@@ -0,0 +1,720 @@
|
||||
// Code generated by stringer -i a.out.go -o anames.go -p s390x; DO NOT EDIT.
|
||||
|
||||
package s390x
|
||||
|
||||
import "github.com/twitchyliquid64/golang-asm/obj"
|
||||
|
||||
var Anames = []string{
|
||||
obj.A_ARCHSPECIFIC: "ADD",
|
||||
"ADDC",
|
||||
"ADDE",
|
||||
"ADDW",
|
||||
"DIVW",
|
||||
"DIVWU",
|
||||
"DIVD",
|
||||
"DIVDU",
|
||||
"MODW",
|
||||
"MODWU",
|
||||
"MODD",
|
||||
"MODDU",
|
||||
"MULLW",
|
||||
"MULLD",
|
||||
"MULHD",
|
||||
"MULHDU",
|
||||
"MLGR",
|
||||
"SUB",
|
||||
"SUBC",
|
||||
"SUBV",
|
||||
"SUBE",
|
||||
"SUBW",
|
||||
"NEG",
|
||||
"NEGW",
|
||||
"MOVWBR",
|
||||
"MOVB",
|
||||
"MOVBZ",
|
||||
"MOVH",
|
||||
"MOVHBR",
|
||||
"MOVHZ",
|
||||
"MOVW",
|
||||
"MOVWZ",
|
||||
"MOVD",
|
||||
"MOVDBR",
|
||||
"MOVDEQ",
|
||||
"MOVDGE",
|
||||
"MOVDGT",
|
||||
"MOVDLE",
|
||||
"MOVDLT",
|
||||
"MOVDNE",
|
||||
"LOCR",
|
||||
"LOCGR",
|
||||
"FLOGR",
|
||||
"POPCNT",
|
||||
"AND",
|
||||
"ANDW",
|
||||
"OR",
|
||||
"ORW",
|
||||
"XOR",
|
||||
"XORW",
|
||||
"SLW",
|
||||
"SLD",
|
||||
"SRW",
|
||||
"SRAW",
|
||||
"SRD",
|
||||
"SRAD",
|
||||
"RLL",
|
||||
"RLLG",
|
||||
"RNSBG",
|
||||
"RXSBG",
|
||||
"ROSBG",
|
||||
"RNSBGT",
|
||||
"RXSBGT",
|
||||
"ROSBGT",
|
||||
"RISBG",
|
||||
"RISBGN",
|
||||
"RISBGZ",
|
||||
"RISBGNZ",
|
||||
"RISBHG",
|
||||
"RISBLG",
|
||||
"RISBHGZ",
|
||||
"RISBLGZ",
|
||||
"FABS",
|
||||
"FADD",
|
||||
"FADDS",
|
||||
"FCMPO",
|
||||
"FCMPU",
|
||||
"CEBR",
|
||||
"FDIV",
|
||||
"FDIVS",
|
||||
"FMADD",
|
||||
"FMADDS",
|
||||
"FMOVD",
|
||||
"FMOVS",
|
||||
"FMSUB",
|
||||
"FMSUBS",
|
||||
"FMUL",
|
||||
"FMULS",
|
||||
"FNABS",
|
||||
"FNEG",
|
||||
"FNEGS",
|
||||
"LEDBR",
|
||||
"LDEBR",
|
||||
"LPDFR",
|
||||
"LNDFR",
|
||||
"FSUB",
|
||||
"FSUBS",
|
||||
"FSQRT",
|
||||
"FSQRTS",
|
||||
"FIEBR",
|
||||
"FIDBR",
|
||||
"CPSDR",
|
||||
"LTEBR",
|
||||
"LTDBR",
|
||||
"TCEB",
|
||||
"TCDB",
|
||||
"LDGR",
|
||||
"LGDR",
|
||||
"CEFBRA",
|
||||
"CDFBRA",
|
||||
"CEGBRA",
|
||||
"CDGBRA",
|
||||
"CFEBRA",
|
||||
"CFDBRA",
|
||||
"CGEBRA",
|
||||
"CGDBRA",
|
||||
"CELFBR",
|
||||
"CDLFBR",
|
||||
"CELGBR",
|
||||
"CDLGBR",
|
||||
"CLFEBR",
|
||||
"CLFDBR",
|
||||
"CLGEBR",
|
||||
"CLGDBR",
|
||||
"CMP",
|
||||
"CMPU",
|
||||
"CMPW",
|
||||
"CMPWU",
|
||||
"TMHH",
|
||||
"TMHL",
|
||||
"TMLH",
|
||||
"TMLL",
|
||||
"IPM",
|
||||
"SPM",
|
||||
"CS",
|
||||
"CSG",
|
||||
"SYNC",
|
||||
"BC",
|
||||
"BCL",
|
||||
"BRC",
|
||||
"BEQ",
|
||||
"BGE",
|
||||
"BGT",
|
||||
"BLE",
|
||||
"BLT",
|
||||
"BLEU",
|
||||
"BLTU",
|
||||
"BNE",
|
||||
"BVC",
|
||||
"BVS",
|
||||
"SYSCALL",
|
||||
"BRCT",
|
||||
"BRCTG",
|
||||
"CRJ",
|
||||
"CGRJ",
|
||||
"CLRJ",
|
||||
"CLGRJ",
|
||||
"CIJ",
|
||||
"CGIJ",
|
||||
"CLIJ",
|
||||
"CLGIJ",
|
||||
"CMPBEQ",
|
||||
"CMPBGE",
|
||||
"CMPBGT",
|
||||
"CMPBLE",
|
||||
"CMPBLT",
|
||||
"CMPBNE",
|
||||
"CMPUBEQ",
|
||||
"CMPUBGE",
|
||||
"CMPUBGT",
|
||||
"CMPUBLE",
|
||||
"CMPUBLT",
|
||||
"CMPUBNE",
|
||||
"MVC",
|
||||
"MVCIN",
|
||||
"CLC",
|
||||
"XC",
|
||||
"OC",
|
||||
"NC",
|
||||
"EXRL",
|
||||
"LARL",
|
||||
"LA",
|
||||
"LAY",
|
||||
"LAA",
|
||||
"LAAG",
|
||||
"LAAL",
|
||||
"LAALG",
|
||||
"LAN",
|
||||
"LANG",
|
||||
"LAX",
|
||||
"LAXG",
|
||||
"LAO",
|
||||
"LAOG",
|
||||
"LMY",
|
||||
"LMG",
|
||||
"STMY",
|
||||
"STMG",
|
||||
"STCK",
|
||||
"STCKC",
|
||||
"STCKE",
|
||||
"STCKF",
|
||||
"CLEAR",
|
||||
"VA",
|
||||
"VAB",
|
||||
"VAH",
|
||||
"VAF",
|
||||
"VAG",
|
||||
"VAQ",
|
||||
"VACC",
|
||||
"VACCB",
|
||||
"VACCH",
|
||||
"VACCF",
|
||||
"VACCG",
|
||||
"VACCQ",
|
||||
"VAC",
|
||||
"VACQ",
|
||||
"VACCC",
|
||||
"VACCCQ",
|
||||
"VN",
|
||||
"VNC",
|
||||
"VAVG",
|
||||
"VAVGB",
|
||||
"VAVGH",
|
||||
"VAVGF",
|
||||
"VAVGG",
|
||||
"VAVGL",
|
||||
"VAVGLB",
|
||||
"VAVGLH",
|
||||
"VAVGLF",
|
||||
"VAVGLG",
|
||||
"VCKSM",
|
||||
"VCEQ",
|
||||
"VCEQB",
|
||||
"VCEQH",
|
||||
"VCEQF",
|
||||
"VCEQG",
|
||||
"VCEQBS",
|
||||
"VCEQHS",
|
||||
"VCEQFS",
|
||||
"VCEQGS",
|
||||
"VCH",
|
||||
"VCHB",
|
||||
"VCHH",
|
||||
"VCHF",
|
||||
"VCHG",
|
||||
"VCHBS",
|
||||
"VCHHS",
|
||||
"VCHFS",
|
||||
"VCHGS",
|
||||
"VCHL",
|
||||
"VCHLB",
|
||||
"VCHLH",
|
||||
"VCHLF",
|
||||
"VCHLG",
|
||||
"VCHLBS",
|
||||
"VCHLHS",
|
||||
"VCHLFS",
|
||||
"VCHLGS",
|
||||
"VCLZ",
|
||||
"VCLZB",
|
||||
"VCLZH",
|
||||
"VCLZF",
|
||||
"VCLZG",
|
||||
"VCTZ",
|
||||
"VCTZB",
|
||||
"VCTZH",
|
||||
"VCTZF",
|
||||
"VCTZG",
|
||||
"VEC",
|
||||
"VECB",
|
||||
"VECH",
|
||||
"VECF",
|
||||
"VECG",
|
||||
"VECL",
|
||||
"VECLB",
|
||||
"VECLH",
|
||||
"VECLF",
|
||||
"VECLG",
|
||||
"VERIM",
|
||||
"VERIMB",
|
||||
"VERIMH",
|
||||
"VERIMF",
|
||||
"VERIMG",
|
||||
"VERLL",
|
||||
"VERLLB",
|
||||
"VERLLH",
|
||||
"VERLLF",
|
||||
"VERLLG",
|
||||
"VERLLV",
|
||||
"VERLLVB",
|
||||
"VERLLVH",
|
||||
"VERLLVF",
|
||||
"VERLLVG",
|
||||
"VESLV",
|
||||
"VESLVB",
|
||||
"VESLVH",
|
||||
"VESLVF",
|
||||
"VESLVG",
|
||||
"VESL",
|
||||
"VESLB",
|
||||
"VESLH",
|
||||
"VESLF",
|
||||
"VESLG",
|
||||
"VESRA",
|
||||
"VESRAB",
|
||||
"VESRAH",
|
||||
"VESRAF",
|
||||
"VESRAG",
|
||||
"VESRAV",
|
||||
"VESRAVB",
|
||||
"VESRAVH",
|
||||
"VESRAVF",
|
||||
"VESRAVG",
|
||||
"VESRL",
|
||||
"VESRLB",
|
||||
"VESRLH",
|
||||
"VESRLF",
|
||||
"VESRLG",
|
||||
"VESRLV",
|
||||
"VESRLVB",
|
||||
"VESRLVH",
|
||||
"VESRLVF",
|
||||
"VESRLVG",
|
||||
"VX",
|
||||
"VFAE",
|
||||
"VFAEB",
|
||||
"VFAEH",
|
||||
"VFAEF",
|
||||
"VFAEBS",
|
||||
"VFAEHS",
|
||||
"VFAEFS",
|
||||
"VFAEZB",
|
||||
"VFAEZH",
|
||||
"VFAEZF",
|
||||
"VFAEZBS",
|
||||
"VFAEZHS",
|
||||
"VFAEZFS",
|
||||
"VFEE",
|
||||
"VFEEB",
|
||||
"VFEEH",
|
||||
"VFEEF",
|
||||
"VFEEBS",
|
||||
"VFEEHS",
|
||||
"VFEEFS",
|
||||
"VFEEZB",
|
||||
"VFEEZH",
|
||||
"VFEEZF",
|
||||
"VFEEZBS",
|
||||
"VFEEZHS",
|
||||
"VFEEZFS",
|
||||
"VFENE",
|
||||
"VFENEB",
|
||||
"VFENEH",
|
||||
"VFENEF",
|
||||
"VFENEBS",
|
||||
"VFENEHS",
|
||||
"VFENEFS",
|
||||
"VFENEZB",
|
||||
"VFENEZH",
|
||||
"VFENEZF",
|
||||
"VFENEZBS",
|
||||
"VFENEZHS",
|
||||
"VFENEZFS",
|
||||
"VFA",
|
||||
"VFADB",
|
||||
"WFADB",
|
||||
"WFK",
|
||||
"WFKDB",
|
||||
"VFCE",
|
||||
"VFCEDB",
|
||||
"VFCEDBS",
|
||||
"WFCEDB",
|
||||
"WFCEDBS",
|
||||
"VFCH",
|
||||
"VFCHDB",
|
||||
"VFCHDBS",
|
||||
"WFCHDB",
|
||||
"WFCHDBS",
|
||||
"VFCHE",
|
||||
"VFCHEDB",
|
||||
"VFCHEDBS",
|
||||
"WFCHEDB",
|
||||
"WFCHEDBS",
|
||||
"WFC",
|
||||
"WFCDB",
|
||||
"VCDG",
|
||||
"VCDGB",
|
||||
"WCDGB",
|
||||
"VCDLG",
|
||||
"VCDLGB",
|
||||
"WCDLGB",
|
||||
"VCGD",
|
||||
"VCGDB",
|
||||
"WCGDB",
|
||||
"VCLGD",
|
||||
"VCLGDB",
|
||||
"WCLGDB",
|
||||
"VFD",
|
||||
"VFDDB",
|
||||
"WFDDB",
|
||||
"VLDE",
|
||||
"VLDEB",
|
||||
"WLDEB",
|
||||
"VLED",
|
||||
"VLEDB",
|
||||
"WLEDB",
|
||||
"VFM",
|
||||
"VFMDB",
|
||||
"WFMDB",
|
||||
"VFMA",
|
||||
"VFMADB",
|
||||
"WFMADB",
|
||||
"VFMS",
|
||||
"VFMSDB",
|
||||
"WFMSDB",
|
||||
"VFPSO",
|
||||
"VFPSODB",
|
||||
"WFPSODB",
|
||||
"VFLCDB",
|
||||
"WFLCDB",
|
||||
"VFLNDB",
|
||||
"WFLNDB",
|
||||
"VFLPDB",
|
||||
"WFLPDB",
|
||||
"VFSQ",
|
||||
"VFSQDB",
|
||||
"WFSQDB",
|
||||
"VFS",
|
||||
"VFSDB",
|
||||
"WFSDB",
|
||||
"VFTCI",
|
||||
"VFTCIDB",
|
||||
"WFTCIDB",
|
||||
"VGFM",
|
||||
"VGFMB",
|
||||
"VGFMH",
|
||||
"VGFMF",
|
||||
"VGFMG",
|
||||
"VGFMA",
|
||||
"VGFMAB",
|
||||
"VGFMAH",
|
||||
"VGFMAF",
|
||||
"VGFMAG",
|
||||
"VGEF",
|
||||
"VGEG",
|
||||
"VGBM",
|
||||
"VZERO",
|
||||
"VONE",
|
||||
"VGM",
|
||||
"VGMB",
|
||||
"VGMH",
|
||||
"VGMF",
|
||||
"VGMG",
|
||||
"VISTR",
|
||||
"VISTRB",
|
||||
"VISTRH",
|
||||
"VISTRF",
|
||||
"VISTRBS",
|
||||
"VISTRHS",
|
||||
"VISTRFS",
|
||||
"VL",
|
||||
"VLR",
|
||||
"VLREP",
|
||||
"VLREPB",
|
||||
"VLREPH",
|
||||
"VLREPF",
|
||||
"VLREPG",
|
||||
"VLC",
|
||||
"VLCB",
|
||||
"VLCH",
|
||||
"VLCF",
|
||||
"VLCG",
|
||||
"VLEH",
|
||||
"VLEF",
|
||||
"VLEG",
|
||||
"VLEB",
|
||||
"VLEIH",
|
||||
"VLEIF",
|
||||
"VLEIG",
|
||||
"VLEIB",
|
||||
"VFI",
|
||||
"VFIDB",
|
||||
"WFIDB",
|
||||
"VLGV",
|
||||
"VLGVB",
|
||||
"VLGVH",
|
||||
"VLGVF",
|
||||
"VLGVG",
|
||||
"VLLEZ",
|
||||
"VLLEZB",
|
||||
"VLLEZH",
|
||||
"VLLEZF",
|
||||
"VLLEZG",
|
||||
"VLM",
|
||||
"VLP",
|
||||
"VLPB",
|
||||
"VLPH",
|
||||
"VLPF",
|
||||
"VLPG",
|
||||
"VLBB",
|
||||
"VLVG",
|
||||
"VLVGB",
|
||||
"VLVGH",
|
||||
"VLVGF",
|
||||
"VLVGG",
|
||||
"VLVGP",
|
||||
"VLL",
|
||||
"VMX",
|
||||
"VMXB",
|
||||
"VMXH",
|
||||
"VMXF",
|
||||
"VMXG",
|
||||
"VMXL",
|
||||
"VMXLB",
|
||||
"VMXLH",
|
||||
"VMXLF",
|
||||
"VMXLG",
|
||||
"VMRH",
|
||||
"VMRHB",
|
||||
"VMRHH",
|
||||
"VMRHF",
|
||||
"VMRHG",
|
||||
"VMRL",
|
||||
"VMRLB",
|
||||
"VMRLH",
|
||||
"VMRLF",
|
||||
"VMRLG",
|
||||
"VMN",
|
||||
"VMNB",
|
||||
"VMNH",
|
||||
"VMNF",
|
||||
"VMNG",
|
||||
"VMNL",
|
||||
"VMNLB",
|
||||
"VMNLH",
|
||||
"VMNLF",
|
||||
"VMNLG",
|
||||
"VMAE",
|
||||
"VMAEB",
|
||||
"VMAEH",
|
||||
"VMAEF",
|
||||
"VMAH",
|
||||
"VMAHB",
|
||||
"VMAHH",
|
||||
"VMAHF",
|
||||
"VMALE",
|
||||
"VMALEB",
|
||||
"VMALEH",
|
||||
"VMALEF",
|
||||
"VMALH",
|
||||
"VMALHB",
|
||||
"VMALHH",
|
||||
"VMALHF",
|
||||
"VMALO",
|
||||
"VMALOB",
|
||||
"VMALOH",
|
||||
"VMALOF",
|
||||
"VMAL",
|
||||
"VMALB",
|
||||
"VMALHW",
|
||||
"VMALF",
|
||||
"VMAO",
|
||||
"VMAOB",
|
||||
"VMAOH",
|
||||
"VMAOF",
|
||||
"VME",
|
||||
"VMEB",
|
||||
"VMEH",
|
||||
"VMEF",
|
||||
"VMH",
|
||||
"VMHB",
|
||||
"VMHH",
|
||||
"VMHF",
|
||||
"VMLE",
|
||||
"VMLEB",
|
||||
"VMLEH",
|
||||
"VMLEF",
|
||||
"VMLH",
|
||||
"VMLHB",
|
||||
"VMLHH",
|
||||
"VMLHF",
|
||||
"VMLO",
|
||||
"VMLOB",
|
||||
"VMLOH",
|
||||
"VMLOF",
|
||||
"VML",
|
||||
"VMLB",
|
||||
"VMLHW",
|
||||
"VMLF",
|
||||
"VMO",
|
||||
"VMOB",
|
||||
"VMOH",
|
||||
"VMOF",
|
||||
"VNO",
|
||||
"VNOT",
|
||||
"VO",
|
||||
"VPK",
|
||||
"VPKH",
|
||||
"VPKF",
|
||||
"VPKG",
|
||||
"VPKLS",
|
||||
"VPKLSH",
|
||||
"VPKLSF",
|
||||
"VPKLSG",
|
||||
"VPKLSHS",
|
||||
"VPKLSFS",
|
||||
"VPKLSGS",
|
||||
"VPKS",
|
||||
"VPKSH",
|
||||
"VPKSF",
|
||||
"VPKSG",
|
||||
"VPKSHS",
|
||||
"VPKSFS",
|
||||
"VPKSGS",
|
||||
"VPERM",
|
||||
"VPDI",
|
||||
"VPOPCT",
|
||||
"VREP",
|
||||
"VREPB",
|
||||
"VREPH",
|
||||
"VREPF",
|
||||
"VREPG",
|
||||
"VREPI",
|
||||
"VREPIB",
|
||||
"VREPIH",
|
||||
"VREPIF",
|
||||
"VREPIG",
|
||||
"VSCEF",
|
||||
"VSCEG",
|
||||
"VSEL",
|
||||
"VSL",
|
||||
"VSLB",
|
||||
"VSLDB",
|
||||
"VSRA",
|
||||
"VSRAB",
|
||||
"VSRL",
|
||||
"VSRLB",
|
||||
"VSEG",
|
||||
"VSEGB",
|
||||
"VSEGH",
|
||||
"VSEGF",
|
||||
"VST",
|
||||
"VSTEH",
|
||||
"VSTEF",
|
||||
"VSTEG",
|
||||
"VSTEB",
|
||||
"VSTM",
|
||||
"VSTL",
|
||||
"VSTRC",
|
||||
"VSTRCB",
|
||||
"VSTRCH",
|
||||
"VSTRCF",
|
||||
"VSTRCBS",
|
||||
"VSTRCHS",
|
||||
"VSTRCFS",
|
||||
"VSTRCZB",
|
||||
"VSTRCZH",
|
||||
"VSTRCZF",
|
||||
"VSTRCZBS",
|
||||
"VSTRCZHS",
|
||||
"VSTRCZFS",
|
||||
"VS",
|
||||
"VSB",
|
||||
"VSH",
|
||||
"VSF",
|
||||
"VSG",
|
||||
"VSQ",
|
||||
"VSCBI",
|
||||
"VSCBIB",
|
||||
"VSCBIH",
|
||||
"VSCBIF",
|
||||
"VSCBIG",
|
||||
"VSCBIQ",
|
||||
"VSBCBI",
|
||||
"VSBCBIQ",
|
||||
"VSBI",
|
||||
"VSBIQ",
|
||||
"VSUMG",
|
||||
"VSUMGH",
|
||||
"VSUMGF",
|
||||
"VSUMQ",
|
||||
"VSUMQF",
|
||||
"VSUMQG",
|
||||
"VSUM",
|
||||
"VSUMB",
|
||||
"VSUMH",
|
||||
"VTM",
|
||||
"VUPH",
|
||||
"VUPHB",
|
||||
"VUPHH",
|
||||
"VUPHF",
|
||||
"VUPLH",
|
||||
"VUPLHB",
|
||||
"VUPLHH",
|
||||
"VUPLHF",
|
||||
"VUPLL",
|
||||
"VUPLLB",
|
||||
"VUPLLH",
|
||||
"VUPLLF",
|
||||
"VUPL",
|
||||
"VUPLB",
|
||||
"VUPLHW",
|
||||
"VUPLF",
|
||||
"VMSLG",
|
||||
"VMSLEG",
|
||||
"VMSLOG",
|
||||
"VMSLEOG",
|
||||
"NOPH",
|
||||
"BYTE",
|
||||
"WORD",
|
||||
"DWORD",
|
||||
"LAST",
|
||||
}
|
||||
39
vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/anamesz.go
generated
vendored
Normal file
39
vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/anamesz.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package s390x
|
||||
|
||||
var cnamesz = []string{
|
||||
"NONE",
|
||||
"REG",
|
||||
"FREG",
|
||||
"VREG",
|
||||
"AREG",
|
||||
"ZCON",
|
||||
"SCON",
|
||||
"UCON",
|
||||
"ADDCON",
|
||||
"ANDCON",
|
||||
"LCON",
|
||||
"DCON",
|
||||
"SACON",
|
||||
"LACON",
|
||||
"DACON",
|
||||
"SBRA",
|
||||
"LBRA",
|
||||
"SAUTO",
|
||||
"LAUTO",
|
||||
"ZOREG",
|
||||
"SOREG",
|
||||
"LOREG",
|
||||
"TLS_LE",
|
||||
"TLS_IE",
|
||||
"GOK",
|
||||
"ADDR",
|
||||
"SYMADDR",
|
||||
"GOTADDR",
|
||||
"TEXTSIZE",
|
||||
"ANY",
|
||||
"NCLASS",
|
||||
}
|
||||
5043
vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/asmz.go
generated
vendored
Normal file
5043
vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/asmz.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
126
vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/condition_code.go
generated
vendored
Normal file
126
vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/condition_code.go
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package s390x
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// CCMask represents a 4-bit condition code mask. Bits that
|
||||
// are not part of the mask should be 0.
|
||||
//
|
||||
// Condition code masks represent the 4 possible values of
|
||||
// the 2-bit condition code as individual bits. Since IBM Z
|
||||
// is a big-endian platform bits are numbered from left to
|
||||
// right. The lowest value, 0, is represented by 8 (0b1000)
|
||||
// and the highest value, 3, is represented by 1 (0b0001).
|
||||
//
|
||||
// Note that condition code values have different semantics
|
||||
// depending on the instruction that set the condition code.
|
||||
// The names given here assume that the condition code was
|
||||
// set by an integer or floating point comparison. Other
|
||||
// instructions may use these same codes to indicate
|
||||
// different results such as a carry or overflow.
|
||||
type CCMask uint8
|
||||
|
||||
const (
|
||||
Never CCMask = 0 // no-op
|
||||
|
||||
// 1-bit masks
|
||||
Equal CCMask = 1 << 3
|
||||
Less CCMask = 1 << 2
|
||||
Greater CCMask = 1 << 1
|
||||
Unordered CCMask = 1 << 0
|
||||
|
||||
// 2-bit masks
|
||||
EqualOrUnordered CCMask = Equal | Unordered // not less and not greater
|
||||
LessOrEqual CCMask = Less | Equal // ordered and not greater
|
||||
LessOrGreater CCMask = Less | Greater // ordered and not equal
|
||||
LessOrUnordered CCMask = Less | Unordered // not greater and not equal
|
||||
GreaterOrEqual CCMask = Greater | Equal // ordered and not less
|
||||
GreaterOrUnordered CCMask = Greater | Unordered // not less and not equal
|
||||
|
||||
// 3-bit masks
|
||||
NotEqual CCMask = Always ^ Equal
|
||||
NotLess CCMask = Always ^ Less
|
||||
NotGreater CCMask = Always ^ Greater
|
||||
NotUnordered CCMask = Always ^ Unordered
|
||||
|
||||
// 4-bit mask
|
||||
Always CCMask = Equal | Less | Greater | Unordered
|
||||
|
||||
// useful aliases
|
||||
Carry CCMask = GreaterOrUnordered
|
||||
NoCarry CCMask = LessOrEqual
|
||||
Borrow CCMask = NoCarry
|
||||
NoBorrow CCMask = Carry
|
||||
)
|
||||
|
||||
// Inverse returns the complement of the condition code mask.
|
||||
func (c CCMask) Inverse() CCMask {
|
||||
return c ^ Always
|
||||
}
|
||||
|
||||
// ReverseComparison swaps the bits at 0b0100 and 0b0010 in the mask,
|
||||
// reversing the behavior of greater than and less than conditions.
|
||||
func (c CCMask) ReverseComparison() CCMask {
|
||||
r := c & EqualOrUnordered
|
||||
if c&Less != 0 {
|
||||
r |= Greater
|
||||
}
|
||||
if c&Greater != 0 {
|
||||
r |= Less
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (c CCMask) String() string {
|
||||
switch c {
|
||||
// 0-bit mask
|
||||
case Never:
|
||||
return "Never"
|
||||
|
||||
// 1-bit masks
|
||||
case Equal:
|
||||
return "Equal"
|
||||
case Less:
|
||||
return "Less"
|
||||
case Greater:
|
||||
return "Greater"
|
||||
case Unordered:
|
||||
return "Unordered"
|
||||
|
||||
// 2-bit masks
|
||||
case EqualOrUnordered:
|
||||
return "EqualOrUnordered"
|
||||
case LessOrEqual:
|
||||
return "LessOrEqual"
|
||||
case LessOrGreater:
|
||||
return "LessOrGreater"
|
||||
case LessOrUnordered:
|
||||
return "LessOrUnordered"
|
||||
case GreaterOrEqual:
|
||||
return "GreaterOrEqual"
|
||||
case GreaterOrUnordered:
|
||||
return "GreaterOrUnordered"
|
||||
|
||||
// 3-bit masks
|
||||
case NotEqual:
|
||||
return "NotEqual"
|
||||
case NotLess:
|
||||
return "NotLess"
|
||||
case NotGreater:
|
||||
return "NotGreater"
|
||||
case NotUnordered:
|
||||
return "NotUnordered"
|
||||
|
||||
// 4-bit mask
|
||||
case Always:
|
||||
return "Always"
|
||||
}
|
||||
|
||||
// invalid
|
||||
return fmt.Sprintf("Invalid (%#x)", c)
|
||||
}
|
||||
73
vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/listz.go
generated
vendored
Normal file
73
vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/listz.go
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
// Based on cmd/internal/obj/ppc64/list9.go.
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package s390x
|
||||
|
||||
import (
|
||||
"github.com/twitchyliquid64/golang-asm/obj"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func init() {
|
||||
obj.RegisterRegister(obj.RBaseS390X, REG_R0+1024, rconv)
|
||||
obj.RegisterOpcode(obj.ABaseS390X, Anames)
|
||||
}
|
||||
|
||||
func rconv(r int) string {
|
||||
if r == 0 {
|
||||
return "NONE"
|
||||
}
|
||||
if r == REGG {
|
||||
// Special case.
|
||||
return "g"
|
||||
}
|
||||
if REG_R0 <= r && r <= REG_R15 {
|
||||
return fmt.Sprintf("R%d", r-REG_R0)
|
||||
}
|
||||
if REG_F0 <= r && r <= REG_F15 {
|
||||
return fmt.Sprintf("F%d", r-REG_F0)
|
||||
}
|
||||
if REG_AR0 <= r && r <= REG_AR15 {
|
||||
return fmt.Sprintf("AR%d", r-REG_AR0)
|
||||
}
|
||||
if REG_V0 <= r && r <= REG_V31 {
|
||||
return fmt.Sprintf("V%d", r-REG_V0)
|
||||
}
|
||||
return fmt.Sprintf("Rgok(%d)", r-obj.RBaseS390X)
|
||||
}
|
||||
|
||||
func DRconv(a int) string {
|
||||
s := "C_??"
|
||||
if a >= C_NONE && a <= C_NCLASS {
|
||||
s = cnamesz[a]
|
||||
}
|
||||
var fp string
|
||||
fp += s
|
||||
return fp
|
||||
}
|
||||
735
vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/objz.go
generated
vendored
Normal file
735
vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/objz.go
generated
vendored
Normal file
@@ -0,0 +1,735 @@
|
||||
// Based on cmd/internal/obj/ppc64/obj9.go.
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package s390x
|
||||
|
||||
import (
|
||||
"github.com/twitchyliquid64/golang-asm/obj"
|
||||
"github.com/twitchyliquid64/golang-asm/objabi"
|
||||
"github.com/twitchyliquid64/golang-asm/sys"
|
||||
"math"
|
||||
)
|
||||
|
||||
func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
||||
p.From.Class = 0
|
||||
p.To.Class = 0
|
||||
|
||||
c := ctxtz{ctxt: ctxt, newprog: newprog}
|
||||
|
||||
// Rewrite BR/BL to symbol as TYPE_BRANCH.
|
||||
switch p.As {
|
||||
case ABR, ABL, obj.ARET, obj.ADUFFZERO, obj.ADUFFCOPY:
|
||||
if p.To.Sym != nil {
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
}
|
||||
}
|
||||
|
||||
// Rewrite float constants to values stored in memory unless they are +0.
|
||||
switch p.As {
|
||||
case AFMOVS:
|
||||
if p.From.Type == obj.TYPE_FCONST {
|
||||
f32 := float32(p.From.Val.(float64))
|
||||
if math.Float32bits(f32) == 0 { // +0
|
||||
break
|
||||
}
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Sym = ctxt.Float32Sym(f32)
|
||||
p.From.Name = obj.NAME_EXTERN
|
||||
p.From.Offset = 0
|
||||
}
|
||||
|
||||
case AFMOVD:
|
||||
if p.From.Type == obj.TYPE_FCONST {
|
||||
f64 := p.From.Val.(float64)
|
||||
if math.Float64bits(f64) == 0 { // +0
|
||||
break
|
||||
}
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Sym = ctxt.Float64Sym(f64)
|
||||
p.From.Name = obj.NAME_EXTERN
|
||||
p.From.Offset = 0
|
||||
}
|
||||
|
||||
// put constants not loadable by LOAD IMMEDIATE into memory
|
||||
case AMOVD:
|
||||
if p.From.Type == obj.TYPE_CONST {
|
||||
val := p.From.Offset
|
||||
if int64(int32(val)) != val &&
|
||||
int64(uint32(val)) != val &&
|
||||
int64(uint64(val)&(0xffffffff<<32)) != val {
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Sym = ctxt.Int64Sym(p.From.Offset)
|
||||
p.From.Name = obj.NAME_EXTERN
|
||||
p.From.Offset = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Rewrite SUB constants into ADD.
|
||||
switch p.As {
|
||||
case ASUBC:
|
||||
if p.From.Type == obj.TYPE_CONST && isint32(-p.From.Offset) {
|
||||
p.From.Offset = -p.From.Offset
|
||||
p.As = AADDC
|
||||
}
|
||||
|
||||
case ASUB:
|
||||
if p.From.Type == obj.TYPE_CONST && isint32(-p.From.Offset) {
|
||||
p.From.Offset = -p.From.Offset
|
||||
p.As = AADD
|
||||
}
|
||||
}
|
||||
|
||||
if c.ctxt.Flag_dynlink {
|
||||
c.rewriteToUseGot(p)
|
||||
}
|
||||
}
|
||||
|
||||
// Rewrite p, if necessary, to access global data via the global offset table.
|
||||
func (c *ctxtz) rewriteToUseGot(p *obj.Prog) {
|
||||
// At the moment EXRL instructions are not emitted by the compiler and only reference local symbols in
|
||||
// assembly code.
|
||||
if p.As == AEXRL {
|
||||
return
|
||||
}
|
||||
|
||||
// We only care about global data: NAME_EXTERN means a global
|
||||
// symbol in the Go sense, and p.Sym.Local is true for a few
|
||||
// internally defined symbols.
|
||||
// Rewrites must not clobber flags and therefore cannot use the
|
||||
// ADD instruction.
|
||||
if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
|
||||
// MOVD $sym, Rx becomes MOVD sym@GOT, Rx
|
||||
// MOVD $sym+<off>, Rx becomes MOVD sym@GOT, Rx or REGTMP2; MOVD $<off>(Rx or REGTMP2), Rx
|
||||
if p.To.Type != obj.TYPE_REG || p.As != AMOVD {
|
||||
c.ctxt.Diag("do not know how to handle LEA-type insn to non-register in %v with -dynlink", p)
|
||||
}
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Name = obj.NAME_GOTREF
|
||||
q := p
|
||||
if p.From.Offset != 0 {
|
||||
target := p.To.Reg
|
||||
if target == REG_R0 {
|
||||
// Cannot use R0 as input to address calculation.
|
||||
// REGTMP might be used by the assembler.
|
||||
p.To.Reg = REGTMP2
|
||||
}
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = AMOVD
|
||||
q.From.Type = obj.TYPE_ADDR
|
||||
q.From.Offset = p.From.Offset
|
||||
q.From.Reg = p.To.Reg
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = target
|
||||
p.From.Offset = 0
|
||||
}
|
||||
}
|
||||
if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN {
|
||||
c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
|
||||
}
|
||||
var source *obj.Addr
|
||||
// MOVD sym, Ry becomes MOVD sym@GOT, REGTMP2; MOVD (REGTMP2), Ry
|
||||
// MOVD Ry, sym becomes MOVD sym@GOT, REGTMP2; MOVD Ry, (REGTMP2)
|
||||
// An addition may be inserted between the two MOVs if there is an offset.
|
||||
if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
|
||||
if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
|
||||
c.ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
|
||||
}
|
||||
source = &p.From
|
||||
} else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
|
||||
source = &p.To
|
||||
} else {
|
||||
return
|
||||
}
|
||||
if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
|
||||
return
|
||||
}
|
||||
if source.Sym.Type == objabi.STLSBSS {
|
||||
return
|
||||
}
|
||||
if source.Type != obj.TYPE_MEM {
|
||||
c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
|
||||
}
|
||||
p1 := obj.Appendp(p, c.newprog)
|
||||
p2 := obj.Appendp(p1, c.newprog)
|
||||
|
||||
p1.As = AMOVD
|
||||
p1.From.Type = obj.TYPE_MEM
|
||||
p1.From.Sym = source.Sym
|
||||
p1.From.Name = obj.NAME_GOTREF
|
||||
p1.To.Type = obj.TYPE_REG
|
||||
p1.To.Reg = REGTMP2
|
||||
|
||||
p2.As = p.As
|
||||
p2.From = p.From
|
||||
p2.To = p.To
|
||||
if p.From.Name == obj.NAME_EXTERN {
|
||||
p2.From.Reg = REGTMP2
|
||||
p2.From.Name = obj.NAME_NONE
|
||||
p2.From.Sym = nil
|
||||
} else if p.To.Name == obj.NAME_EXTERN {
|
||||
p2.To.Reg = REGTMP2
|
||||
p2.To.Name = obj.NAME_NONE
|
||||
p2.To.Sym = nil
|
||||
} else {
|
||||
return
|
||||
}
|
||||
obj.Nopout(p)
|
||||
}
|
||||
|
||||
func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
||||
// TODO(minux): add morestack short-cuts with small fixed frame-size.
|
||||
if cursym.Func.Text == nil || cursym.Func.Text.Link == nil {
|
||||
return
|
||||
}
|
||||
|
||||
c := ctxtz{ctxt: ctxt, cursym: cursym, newprog: newprog}
|
||||
|
||||
p := c.cursym.Func.Text
|
||||
textstksiz := p.To.Offset
|
||||
if textstksiz == -8 {
|
||||
// Compatibility hack.
|
||||
p.From.Sym.Set(obj.AttrNoFrame, true)
|
||||
textstksiz = 0
|
||||
}
|
||||
if textstksiz%8 != 0 {
|
||||
c.ctxt.Diag("frame size %d not a multiple of 8", textstksiz)
|
||||
}
|
||||
if p.From.Sym.NoFrame() {
|
||||
if textstksiz != 0 {
|
||||
c.ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", textstksiz)
|
||||
}
|
||||
}
|
||||
|
||||
c.cursym.Func.Args = p.To.Val.(int32)
|
||||
c.cursym.Func.Locals = int32(textstksiz)
|
||||
|
||||
/*
|
||||
* find leaf subroutines
|
||||
* strip NOPs
|
||||
* expand RET
|
||||
*/
|
||||
|
||||
var q *obj.Prog
|
||||
for p := c.cursym.Func.Text; p != nil; p = p.Link {
|
||||
switch p.As {
|
||||
case obj.ATEXT:
|
||||
q = p
|
||||
p.Mark |= LEAF
|
||||
|
||||
case ABL, ABCL:
|
||||
q = p
|
||||
c.cursym.Func.Text.Mark &^= LEAF
|
||||
fallthrough
|
||||
|
||||
case ABC,
|
||||
ABRC,
|
||||
ABEQ,
|
||||
ABGE,
|
||||
ABGT,
|
||||
ABLE,
|
||||
ABLT,
|
||||
ABLEU,
|
||||
ABLTU,
|
||||
ABNE,
|
||||
ABR,
|
||||
ABVC,
|
||||
ABVS,
|
||||
ACRJ,
|
||||
ACGRJ,
|
||||
ACLRJ,
|
||||
ACLGRJ,
|
||||
ACIJ,
|
||||
ACGIJ,
|
||||
ACLIJ,
|
||||
ACLGIJ,
|
||||
ACMPBEQ,
|
||||
ACMPBGE,
|
||||
ACMPBGT,
|
||||
ACMPBLE,
|
||||
ACMPBLT,
|
||||
ACMPBNE,
|
||||
ACMPUBEQ,
|
||||
ACMPUBGE,
|
||||
ACMPUBGT,
|
||||
ACMPUBLE,
|
||||
ACMPUBLT,
|
||||
ACMPUBNE:
|
||||
q = p
|
||||
p.Mark |= BRANCH
|
||||
|
||||
default:
|
||||
q = p
|
||||
}
|
||||
}
|
||||
|
||||
autosize := int32(0)
|
||||
var pLast *obj.Prog
|
||||
var pPre *obj.Prog
|
||||
var pPreempt *obj.Prog
|
||||
wasSplit := false
|
||||
for p := c.cursym.Func.Text; p != nil; p = p.Link {
|
||||
pLast = p
|
||||
switch p.As {
|
||||
case obj.ATEXT:
|
||||
autosize = int32(textstksiz)
|
||||
|
||||
if p.Mark&LEAF != 0 && autosize == 0 {
|
||||
// A leaf function with no locals has no frame.
|
||||
p.From.Sym.Set(obj.AttrNoFrame, true)
|
||||
}
|
||||
|
||||
if !p.From.Sym.NoFrame() {
|
||||
// If there is a stack frame at all, it includes
|
||||
// space to save the LR.
|
||||
autosize += int32(c.ctxt.FixedFrameSize())
|
||||
}
|
||||
|
||||
if p.Mark&LEAF != 0 && autosize < objabi.StackSmall {
|
||||
// A leaf function with a small stack can be marked
|
||||
// NOSPLIT, avoiding a stack check.
|
||||
p.From.Sym.Set(obj.AttrNoSplit, true)
|
||||
}
|
||||
|
||||
p.To.Offset = int64(autosize)
|
||||
|
||||
q := p
|
||||
|
||||
if !p.From.Sym.NoSplit() {
|
||||
p, pPreempt = c.stacksplitPre(p, autosize) // emit pre part of split check
|
||||
pPre = p
|
||||
p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
|
||||
wasSplit = true //need post part of split
|
||||
}
|
||||
|
||||
if autosize != 0 {
|
||||
// Make sure to save link register for non-empty frame, even if
|
||||
// it is a leaf function, so that traceback works.
|
||||
// Store link register before decrementing SP, so if a signal comes
|
||||
// during the execution of the function prologue, the traceback
|
||||
// code will not see a half-updated stack frame.
|
||||
// This sequence is not async preemptible, as if we open a frame
|
||||
// at the current SP, it will clobber the saved LR.
|
||||
q = c.ctxt.StartUnsafePoint(p, c.newprog)
|
||||
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = AMOVD
|
||||
q.From.Type = obj.TYPE_REG
|
||||
q.From.Reg = REG_LR
|
||||
q.To.Type = obj.TYPE_MEM
|
||||
q.To.Reg = REGSP
|
||||
q.To.Offset = int64(-autosize)
|
||||
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = AMOVD
|
||||
q.From.Type = obj.TYPE_ADDR
|
||||
q.From.Offset = int64(-autosize)
|
||||
q.From.Reg = REGSP // not actually needed - REGSP is assumed if no reg is provided
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REGSP
|
||||
q.Spadj = autosize
|
||||
|
||||
q = c.ctxt.EndUnsafePoint(q, c.newprog, -1)
|
||||
} else if c.cursym.Func.Text.Mark&LEAF == 0 {
|
||||
// A very few functions that do not return to their caller
|
||||
// (e.g. gogo) are not identified as leaves but still have
|
||||
// no frame.
|
||||
c.cursym.Func.Text.Mark |= LEAF
|
||||
}
|
||||
|
||||
if c.cursym.Func.Text.Mark&LEAF != 0 {
|
||||
c.cursym.Set(obj.AttrLeaf, true)
|
||||
break
|
||||
}
|
||||
|
||||
if c.cursym.Func.Text.From.Sym.Wrapper() {
|
||||
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
|
||||
//
|
||||
// MOVD g_panic(g), R3
|
||||
// CMP R3, $0
|
||||
// BEQ end
|
||||
// MOVD panic_argp(R3), R4
|
||||
// ADD $(autosize+8), R1, R5
|
||||
// CMP R4, R5
|
||||
// BNE end
|
||||
// ADD $8, R1, R6
|
||||
// MOVD R6, panic_argp(R3)
|
||||
// end:
|
||||
// NOP
|
||||
//
|
||||
// The NOP is needed to give the jumps somewhere to land.
|
||||
// It is a liblink NOP, not a s390x NOP: it encodes to 0 instruction bytes.
|
||||
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
|
||||
q.As = AMOVD
|
||||
q.From.Type = obj.TYPE_MEM
|
||||
q.From.Reg = REGG
|
||||
q.From.Offset = 4 * int64(c.ctxt.Arch.PtrSize) // G.panic
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REG_R3
|
||||
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = ACMP
|
||||
q.From.Type = obj.TYPE_REG
|
||||
q.From.Reg = REG_R3
|
||||
q.To.Type = obj.TYPE_CONST
|
||||
q.To.Offset = 0
|
||||
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = ABEQ
|
||||
q.To.Type = obj.TYPE_BRANCH
|
||||
p1 := q
|
||||
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = AMOVD
|
||||
q.From.Type = obj.TYPE_MEM
|
||||
q.From.Reg = REG_R3
|
||||
q.From.Offset = 0 // Panic.argp
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REG_R4
|
||||
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = AADD
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = int64(autosize) + c.ctxt.FixedFrameSize()
|
||||
q.Reg = REGSP
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REG_R5
|
||||
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = ACMP
|
||||
q.From.Type = obj.TYPE_REG
|
||||
q.From.Reg = REG_R4
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REG_R5
|
||||
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = ABNE
|
||||
q.To.Type = obj.TYPE_BRANCH
|
||||
p2 := q
|
||||
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = AADD
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = c.ctxt.FixedFrameSize()
|
||||
q.Reg = REGSP
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REG_R6
|
||||
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = AMOVD
|
||||
q.From.Type = obj.TYPE_REG
|
||||
q.From.Reg = REG_R6
|
||||
q.To.Type = obj.TYPE_MEM
|
||||
q.To.Reg = REG_R3
|
||||
q.To.Offset = 0 // Panic.argp
|
||||
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
|
||||
q.As = obj.ANOP
|
||||
p1.To.SetTarget(q)
|
||||
p2.To.SetTarget(q)
|
||||
}
|
||||
|
||||
case obj.ARET:
|
||||
retTarget := p.To.Sym
|
||||
|
||||
if c.cursym.Func.Text.Mark&LEAF != 0 {
|
||||
if autosize == 0 {
|
||||
p.As = ABR
|
||||
p.From = obj.Addr{}
|
||||
if retTarget == nil {
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_LR
|
||||
} else {
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
p.To.Sym = retTarget
|
||||
}
|
||||
p.Mark |= BRANCH
|
||||
break
|
||||
}
|
||||
|
||||
p.As = AADD
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = int64(autosize)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGSP
|
||||
p.Spadj = -autosize
|
||||
|
||||
q = obj.Appendp(p, c.newprog)
|
||||
q.As = ABR
|
||||
q.From = obj.Addr{}
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REG_LR
|
||||
q.Mark |= BRANCH
|
||||
q.Spadj = autosize
|
||||
break
|
||||
}
|
||||
|
||||
p.As = AMOVD
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = REGSP
|
||||
p.From.Offset = 0
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_LR
|
||||
|
||||
q = p
|
||||
|
||||
if autosize != 0 {
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = AADD
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = int64(autosize)
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REGSP
|
||||
q.Spadj = -autosize
|
||||
}
|
||||
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = ABR
|
||||
q.From = obj.Addr{}
|
||||
if retTarget == nil {
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REG_LR
|
||||
} else {
|
||||
q.To.Type = obj.TYPE_BRANCH
|
||||
q.To.Sym = retTarget
|
||||
}
|
||||
q.Mark |= BRANCH
|
||||
q.Spadj = autosize
|
||||
|
||||
case AADD:
|
||||
if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
|
||||
p.Spadj = int32(-p.From.Offset)
|
||||
}
|
||||
|
||||
case obj.AGETCALLERPC:
|
||||
if cursym.Leaf() {
|
||||
/* MOVD LR, Rd */
|
||||
p.As = AMOVD
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_LR
|
||||
} else {
|
||||
/* MOVD (RSP), Rd */
|
||||
p.As = AMOVD
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = REGSP
|
||||
}
|
||||
}
|
||||
}
|
||||
if wasSplit {
|
||||
c.stacksplitPost(pLast, pPre, pPreempt, autosize) // emit post part of split check
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (*obj.Prog, *obj.Prog) {
|
||||
var q *obj.Prog
|
||||
|
||||
// MOVD g_stackguard(g), R3
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = AMOVD
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = REGG
|
||||
p.From.Offset = 2 * int64(c.ctxt.Arch.PtrSize) // G.stackguard0
|
||||
if c.cursym.CFunc() {
|
||||
p.From.Offset = 3 * int64(c.ctxt.Arch.PtrSize) // G.stackguard1
|
||||
}
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R3
|
||||
|
||||
// Mark the stack bound check and morestack call async nonpreemptible.
|
||||
// If we get preempted here, when resumed the preemption request is
|
||||
// cleared, but we'll still call morestack, which will double the stack
|
||||
// unnecessarily. See issue #35470.
|
||||
p = c.ctxt.StartUnsafePoint(p, c.newprog)
|
||||
|
||||
q = nil
|
||||
if framesize <= objabi.StackSmall {
|
||||
// small stack: SP < stackguard
|
||||
// CMPUBGE stackguard, SP, label-of-call-to-morestack
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
//q1 = p
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_R3
|
||||
p.Reg = REGSP
|
||||
p.As = ACMPUBGE
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
|
||||
} else if framesize <= objabi.StackBig {
|
||||
// large stack: SP-framesize < stackguard-StackSmall
|
||||
// ADD $-(framesize-StackSmall), SP, R4
|
||||
// CMPUBGE stackguard, R4, label-of-call-to-morestack
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = AADD
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = -(int64(framesize) - objabi.StackSmall)
|
||||
p.Reg = REGSP
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R4
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_R3
|
||||
p.Reg = REG_R4
|
||||
p.As = ACMPUBGE
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
|
||||
} else {
|
||||
// Such a large stack we need to protect against wraparound.
|
||||
// If SP is close to zero:
|
||||
// SP-stackguard+StackGuard <= framesize + (StackGuard-StackSmall)
|
||||
// The +StackGuard on both sides is required to keep the left side positive:
|
||||
// SP is allowed to be slightly below stackguard. See stack.h.
|
||||
//
|
||||
// Preemption sets stackguard to StackPreempt, a very large value.
|
||||
// That breaks the math above, so we have to check for that explicitly.
|
||||
// // stackguard is R3
|
||||
// CMP R3, $StackPreempt
|
||||
// BEQ label-of-call-to-morestack
|
||||
// ADD $StackGuard, SP, R4
|
||||
// SUB R3, R4
|
||||
// MOVD $(framesize+(StackGuard-StackSmall)), TEMP
|
||||
// CMPUBGE TEMP, R4, label-of-call-to-morestack
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = ACMP
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_R3
|
||||
p.To.Type = obj.TYPE_CONST
|
||||
p.To.Offset = objabi.StackPreempt
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
q = p
|
||||
p.As = ABEQ
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = AADD
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = int64(objabi.StackGuard)
|
||||
p.Reg = REGSP
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R4
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = ASUB
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_R3
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R4
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = AMOVD
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = int64(framesize) + int64(objabi.StackGuard) - objabi.StackSmall
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGTMP
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REGTMP
|
||||
p.Reg = REG_R4
|
||||
p.As = ACMPUBGE
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
}
|
||||
|
||||
return p, q
|
||||
}
|
||||
|
||||
func (c *ctxtz) stacksplitPost(p *obj.Prog, pPre *obj.Prog, pPreempt *obj.Prog, framesize int32) *obj.Prog {
|
||||
// Now we are at the end of the function, but logically
|
||||
// we are still in function prologue. We need to fix the
|
||||
// SP data and PCDATA.
|
||||
spfix := obj.Appendp(p, c.newprog)
|
||||
spfix.As = obj.ANOP
|
||||
spfix.Spadj = -framesize
|
||||
|
||||
pcdata := c.ctxt.EmitEntryStackMap(c.cursym, spfix, c.newprog)
|
||||
pcdata = c.ctxt.StartUnsafePoint(pcdata, c.newprog)
|
||||
|
||||
// MOVD LR, R5
|
||||
p = obj.Appendp(pcdata, c.newprog)
|
||||
pPre.To.SetTarget(p)
|
||||
p.As = AMOVD
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_LR
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R5
|
||||
if pPreempt != nil {
|
||||
pPreempt.To.SetTarget(p)
|
||||
}
|
||||
|
||||
// BL runtime.morestack(SB)
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = ABL
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
if c.cursym.CFunc() {
|
||||
p.To.Sym = c.ctxt.Lookup("runtime.morestackc")
|
||||
} else if !c.cursym.Func.Text.From.Sym.NeedCtxt() {
|
||||
p.To.Sym = c.ctxt.Lookup("runtime.morestack_noctxt")
|
||||
} else {
|
||||
p.To.Sym = c.ctxt.Lookup("runtime.morestack")
|
||||
}
|
||||
|
||||
p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
|
||||
|
||||
// BR start
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = ABR
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
p.To.SetTarget(c.cursym.Func.Text.Link)
|
||||
return p
|
||||
}
|
||||
|
||||
var unaryDst = map[obj.As]bool{
|
||||
ASTCK: true,
|
||||
ASTCKC: true,
|
||||
ASTCKE: true,
|
||||
ASTCKF: true,
|
||||
ANEG: true,
|
||||
ANEGW: true,
|
||||
AVONE: true,
|
||||
AVZERO: true,
|
||||
}
|
||||
|
||||
var Links390x = obj.LinkArch{
|
||||
Arch: sys.ArchS390X,
|
||||
Init: buildop,
|
||||
Preprocess: preprocess,
|
||||
Assemble: spanz,
|
||||
Progedit: progedit,
|
||||
UnaryDst: unaryDst,
|
||||
DWARFRegisters: S390XDWARFRegisters,
|
||||
}
|
||||
47
vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/rotate.go
generated
vendored
Normal file
47
vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/rotate.go
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package s390x
|
||||
|
||||
// RotateParams represents the immediates required for a "rotate
|
||||
// then ... selected bits instruction".
|
||||
//
|
||||
// The Start and End values are the indexes that represent
|
||||
// the masked region. They are inclusive and are in big-
|
||||
// endian order (bit 0 is the MSB, bit 63 is the LSB). They
|
||||
// may wrap around.
|
||||
//
|
||||
// Some examples:
|
||||
//
|
||||
// Masked region | Start | End
|
||||
// --------------------------+-------+----
|
||||
// 0x00_00_00_00_00_00_00_0f | 60 | 63
|
||||
// 0xf0_00_00_00_00_00_00_00 | 0 | 3
|
||||
// 0xf0_00_00_00_00_00_00_0f | 60 | 3
|
||||
//
|
||||
// The Amount value represents the amount to rotate the
|
||||
// input left by. Note that this rotation is performed
|
||||
// before the masked region is used.
|
||||
type RotateParams struct {
|
||||
Start uint8 // big-endian start bit index [0..63]
|
||||
End uint8 // big-endian end bit index [0..63]
|
||||
Amount uint8 // amount to rotate left
|
||||
}
|
||||
|
||||
func NewRotateParams(start, end, amount int64) RotateParams {
|
||||
if start&^63 != 0 {
|
||||
panic("start out of bounds")
|
||||
}
|
||||
if end&^63 != 0 {
|
||||
panic("end out of bounds")
|
||||
}
|
||||
if amount&^63 != 0 {
|
||||
panic("amount out of bounds")
|
||||
}
|
||||
return RotateParams{
|
||||
Start: uint8(start),
|
||||
End: uint8(end),
|
||||
Amount: uint8(amount),
|
||||
}
|
||||
}
|
||||
1069
vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/vector.go
generated
vendored
Normal file
1069
vendor/github.com/twitchyliquid64/golang-asm/obj/s390x/vector.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
421
vendor/github.com/twitchyliquid64/golang-asm/obj/sym.go
generated
vendored
Normal file
421
vendor/github.com/twitchyliquid64/golang-asm/obj/sym.go
generated
vendored
Normal file
@@ -0,0 +1,421 @@
|
||||
// Derived from Inferno utils/6l/obj.c and utils/6l/span.c
|
||||
// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/obj.c
|
||||
// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/span.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package obj
|
||||
|
||||
import (
|
||||
"github.com/twitchyliquid64/golang-asm/goobj"
|
||||
"github.com/twitchyliquid64/golang-asm/objabi"
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"sort"
|
||||
)
|
||||
|
||||
func Linknew(arch *LinkArch) *Link {
|
||||
ctxt := new(Link)
|
||||
ctxt.hash = make(map[string]*LSym)
|
||||
ctxt.funchash = make(map[string]*LSym)
|
||||
ctxt.statichash = make(map[string]*LSym)
|
||||
ctxt.Arch = arch
|
||||
ctxt.Pathname = objabi.WorkingDir()
|
||||
|
||||
if err := ctxt.Headtype.Set(objabi.GOOS); err != nil {
|
||||
log.Fatalf("unknown goos %s", objabi.GOOS)
|
||||
}
|
||||
|
||||
ctxt.Flag_optimize = true
|
||||
return ctxt
|
||||
}
|
||||
|
||||
// LookupDerived looks up or creates the symbol with name name derived from symbol s.
|
||||
// The resulting symbol will be static iff s is.
|
||||
func (ctxt *Link) LookupDerived(s *LSym, name string) *LSym {
|
||||
if s.Static() {
|
||||
return ctxt.LookupStatic(name)
|
||||
}
|
||||
return ctxt.Lookup(name)
|
||||
}
|
||||
|
||||
// LookupStatic looks up the static symbol with name name.
|
||||
// If it does not exist, it creates it.
|
||||
func (ctxt *Link) LookupStatic(name string) *LSym {
|
||||
s := ctxt.statichash[name]
|
||||
if s == nil {
|
||||
s = &LSym{Name: name, Attribute: AttrStatic}
|
||||
ctxt.statichash[name] = s
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// LookupABI looks up a symbol with the given ABI.
|
||||
// If it does not exist, it creates it.
|
||||
func (ctxt *Link) LookupABI(name string, abi ABI) *LSym {
|
||||
return ctxt.LookupABIInit(name, abi, nil)
|
||||
}
|
||||
|
||||
// LookupABI looks up a symbol with the given ABI.
|
||||
// If it does not exist, it creates it and
|
||||
// passes it to init for one-time initialization.
|
||||
func (ctxt *Link) LookupABIInit(name string, abi ABI, init func(s *LSym)) *LSym {
|
||||
var hash map[string]*LSym
|
||||
switch abi {
|
||||
case ABI0:
|
||||
hash = ctxt.hash
|
||||
case ABIInternal:
|
||||
hash = ctxt.funchash
|
||||
default:
|
||||
panic("unknown ABI")
|
||||
}
|
||||
|
||||
ctxt.hashmu.Lock()
|
||||
s := hash[name]
|
||||
if s == nil {
|
||||
s = &LSym{Name: name}
|
||||
s.SetABI(abi)
|
||||
hash[name] = s
|
||||
if init != nil {
|
||||
init(s)
|
||||
}
|
||||
}
|
||||
ctxt.hashmu.Unlock()
|
||||
return s
|
||||
}
|
||||
|
||||
// Lookup looks up the symbol with name name.
|
||||
// If it does not exist, it creates it.
|
||||
func (ctxt *Link) Lookup(name string) *LSym {
|
||||
return ctxt.LookupInit(name, nil)
|
||||
}
|
||||
|
||||
// LookupInit looks up the symbol with name name.
|
||||
// If it does not exist, it creates it and
|
||||
// passes it to init for one-time initialization.
|
||||
func (ctxt *Link) LookupInit(name string, init func(s *LSym)) *LSym {
|
||||
ctxt.hashmu.Lock()
|
||||
s := ctxt.hash[name]
|
||||
if s == nil {
|
||||
s = &LSym{Name: name}
|
||||
ctxt.hash[name] = s
|
||||
if init != nil {
|
||||
init(s)
|
||||
}
|
||||
}
|
||||
ctxt.hashmu.Unlock()
|
||||
return s
|
||||
}
|
||||
|
||||
func (ctxt *Link) Float32Sym(f float32) *LSym {
|
||||
i := math.Float32bits(f)
|
||||
name := fmt.Sprintf("$f32.%08x", i)
|
||||
return ctxt.LookupInit(name, func(s *LSym) {
|
||||
s.Size = 4
|
||||
s.WriteFloat32(ctxt, 0, f)
|
||||
s.Type = objabi.SRODATA
|
||||
s.Set(AttrLocal, true)
|
||||
s.Set(AttrContentAddressable, true)
|
||||
ctxt.constSyms = append(ctxt.constSyms, s)
|
||||
})
|
||||
}
|
||||
|
||||
func (ctxt *Link) Float64Sym(f float64) *LSym {
|
||||
i := math.Float64bits(f)
|
||||
name := fmt.Sprintf("$f64.%016x", i)
|
||||
return ctxt.LookupInit(name, func(s *LSym) {
|
||||
s.Size = 8
|
||||
s.WriteFloat64(ctxt, 0, f)
|
||||
s.Type = objabi.SRODATA
|
||||
s.Set(AttrLocal, true)
|
||||
s.Set(AttrContentAddressable, true)
|
||||
ctxt.constSyms = append(ctxt.constSyms, s)
|
||||
})
|
||||
}
|
||||
|
||||
func (ctxt *Link) Int64Sym(i int64) *LSym {
|
||||
name := fmt.Sprintf("$i64.%016x", uint64(i))
|
||||
return ctxt.LookupInit(name, func(s *LSym) {
|
||||
s.Size = 8
|
||||
s.WriteInt(ctxt, 0, 8, i)
|
||||
s.Type = objabi.SRODATA
|
||||
s.Set(AttrLocal, true)
|
||||
s.Set(AttrContentAddressable, true)
|
||||
ctxt.constSyms = append(ctxt.constSyms, s)
|
||||
})
|
||||
}
|
||||
|
||||
// Assign index to symbols.
|
||||
// asm is set to true if this is called by the assembler (i.e. not the compiler),
|
||||
// in which case all the symbols are non-package (for now).
|
||||
func (ctxt *Link) NumberSyms() {
|
||||
if ctxt.Headtype == objabi.Haix {
|
||||
// Data must be sorted to keep a constant order in TOC symbols.
|
||||
// As they are created during Progedit, two symbols can be switched between
|
||||
// two different compilations. Therefore, BuildID will be different.
|
||||
// TODO: find a better place and optimize to only sort TOC symbols
|
||||
sort.Slice(ctxt.Data, func(i, j int) bool {
|
||||
return ctxt.Data[i].Name < ctxt.Data[j].Name
|
||||
})
|
||||
}
|
||||
|
||||
// Constant symbols are created late in the concurrent phase. Sort them
|
||||
// to ensure a deterministic order.
|
||||
sort.Slice(ctxt.constSyms, func(i, j int) bool {
|
||||
return ctxt.constSyms[i].Name < ctxt.constSyms[j].Name
|
||||
})
|
||||
ctxt.Data = append(ctxt.Data, ctxt.constSyms...)
|
||||
ctxt.constSyms = nil
|
||||
|
||||
ctxt.pkgIdx = make(map[string]int32)
|
||||
ctxt.defs = []*LSym{}
|
||||
ctxt.hashed64defs = []*LSym{}
|
||||
ctxt.hasheddefs = []*LSym{}
|
||||
ctxt.nonpkgdefs = []*LSym{}
|
||||
|
||||
var idx, hashedidx, hashed64idx, nonpkgidx int32
|
||||
ctxt.traverseSyms(traverseDefs, func(s *LSym) {
|
||||
// if Pkgpath is unknown, cannot hash symbols with relocations, as it
|
||||
// may reference named symbols whose names are not fully expanded.
|
||||
if s.ContentAddressable() && (ctxt.Pkgpath != "" || len(s.R) == 0) {
|
||||
if len(s.P) <= 8 && len(s.R) == 0 { // we can use short hash only for symbols without relocations
|
||||
s.PkgIdx = goobj.PkgIdxHashed64
|
||||
s.SymIdx = hashed64idx
|
||||
if hashed64idx != int32(len(ctxt.hashed64defs)) {
|
||||
panic("bad index")
|
||||
}
|
||||
ctxt.hashed64defs = append(ctxt.hashed64defs, s)
|
||||
hashed64idx++
|
||||
} else {
|
||||
s.PkgIdx = goobj.PkgIdxHashed
|
||||
s.SymIdx = hashedidx
|
||||
if hashedidx != int32(len(ctxt.hasheddefs)) {
|
||||
panic("bad index")
|
||||
}
|
||||
ctxt.hasheddefs = append(ctxt.hasheddefs, s)
|
||||
hashedidx++
|
||||
}
|
||||
} else if isNonPkgSym(ctxt, s) {
|
||||
s.PkgIdx = goobj.PkgIdxNone
|
||||
s.SymIdx = nonpkgidx
|
||||
if nonpkgidx != int32(len(ctxt.nonpkgdefs)) {
|
||||
panic("bad index")
|
||||
}
|
||||
ctxt.nonpkgdefs = append(ctxt.nonpkgdefs, s)
|
||||
nonpkgidx++
|
||||
} else {
|
||||
s.PkgIdx = goobj.PkgIdxSelf
|
||||
s.SymIdx = idx
|
||||
if idx != int32(len(ctxt.defs)) {
|
||||
panic("bad index")
|
||||
}
|
||||
ctxt.defs = append(ctxt.defs, s)
|
||||
idx++
|
||||
}
|
||||
s.Set(AttrIndexed, true)
|
||||
})
|
||||
|
||||
ipkg := int32(1) // 0 is invalid index
|
||||
nonpkgdef := nonpkgidx
|
||||
ctxt.traverseSyms(traverseRefs|traverseAux, func(rs *LSym) {
|
||||
if rs.PkgIdx != goobj.PkgIdxInvalid {
|
||||
return
|
||||
}
|
||||
if !ctxt.Flag_linkshared {
|
||||
// Assign special index for builtin symbols.
|
||||
// Don't do it when linking against shared libraries, as the runtime
|
||||
// may be in a different library.
|
||||
if i := goobj.BuiltinIdx(rs.Name, int(rs.ABI())); i != -1 {
|
||||
rs.PkgIdx = goobj.PkgIdxBuiltin
|
||||
rs.SymIdx = int32(i)
|
||||
rs.Set(AttrIndexed, true)
|
||||
return
|
||||
}
|
||||
}
|
||||
pkg := rs.Pkg
|
||||
if rs.ContentAddressable() {
|
||||
// for now, only support content-addressable symbols that are always locally defined.
|
||||
panic("hashed refs unsupported for now")
|
||||
}
|
||||
if pkg == "" || pkg == "\"\"" || pkg == "_" || !rs.Indexed() {
|
||||
rs.PkgIdx = goobj.PkgIdxNone
|
||||
rs.SymIdx = nonpkgidx
|
||||
rs.Set(AttrIndexed, true)
|
||||
if nonpkgidx != nonpkgdef+int32(len(ctxt.nonpkgrefs)) {
|
||||
panic("bad index")
|
||||
}
|
||||
ctxt.nonpkgrefs = append(ctxt.nonpkgrefs, rs)
|
||||
nonpkgidx++
|
||||
return
|
||||
}
|
||||
if k, ok := ctxt.pkgIdx[pkg]; ok {
|
||||
rs.PkgIdx = k
|
||||
return
|
||||
}
|
||||
rs.PkgIdx = ipkg
|
||||
ctxt.pkgIdx[pkg] = ipkg
|
||||
ipkg++
|
||||
})
|
||||
}
|
||||
|
||||
// Returns whether s is a non-package symbol, which needs to be referenced
|
||||
// by name instead of by index.
|
||||
func isNonPkgSym(ctxt *Link, s *LSym) bool {
|
||||
if ctxt.IsAsm && !s.Static() {
|
||||
// asm symbols are referenced by name only, except static symbols
|
||||
// which are file-local and can be referenced by index.
|
||||
return true
|
||||
}
|
||||
if ctxt.Flag_linkshared {
|
||||
// The referenced symbol may be in a different shared library so
|
||||
// the linker cannot see its index.
|
||||
return true
|
||||
}
|
||||
if s.Pkg == "_" {
|
||||
// The frontend uses package "_" to mark symbols that should not
|
||||
// be referenced by index, e.g. linkname'd symbols.
|
||||
return true
|
||||
}
|
||||
if s.DuplicateOK() {
|
||||
// Dupok symbol needs to be dedup'd by name.
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// StaticNamePref is the prefix the front end applies to static temporary
|
||||
// variables. When turned into LSyms, these can be tagged as static so
|
||||
// as to avoid inserting them into the linker's name lookup tables.
|
||||
const StaticNamePref = ".stmp_"
|
||||
|
||||
type traverseFlag uint32
|
||||
|
||||
const (
|
||||
traverseDefs traverseFlag = 1 << iota
|
||||
traverseRefs
|
||||
traverseAux
|
||||
|
||||
traverseAll = traverseDefs | traverseRefs | traverseAux
|
||||
)
|
||||
|
||||
// Traverse symbols based on flag, call fn for each symbol.
|
||||
func (ctxt *Link) traverseSyms(flag traverseFlag, fn func(*LSym)) {
|
||||
lists := [][]*LSym{ctxt.Text, ctxt.Data, ctxt.ABIAliases}
|
||||
for _, list := range lists {
|
||||
for _, s := range list {
|
||||
if flag&traverseDefs != 0 {
|
||||
fn(s)
|
||||
}
|
||||
if flag&traverseRefs != 0 {
|
||||
for _, r := range s.R {
|
||||
if r.Sym != nil {
|
||||
fn(r.Sym)
|
||||
}
|
||||
}
|
||||
}
|
||||
if flag&traverseAux != 0 {
|
||||
if s.Gotype != nil {
|
||||
fn(s.Gotype)
|
||||
}
|
||||
if s.Type == objabi.STEXT {
|
||||
f := func(parent *LSym, aux *LSym) {
|
||||
fn(aux)
|
||||
}
|
||||
ctxt.traverseFuncAux(flag, s, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ctxt *Link) traverseFuncAux(flag traverseFlag, fsym *LSym, fn func(parent *LSym, aux *LSym)) {
|
||||
pc := &fsym.Func.Pcln
|
||||
if flag&traverseAux == 0 {
|
||||
// NB: should it become necessary to walk aux sym reloc references
|
||||
// without walking the aux syms themselves, this can be changed.
|
||||
panic("should not be here")
|
||||
}
|
||||
for _, d := range pc.Funcdata {
|
||||
if d != nil {
|
||||
fn(fsym, d)
|
||||
}
|
||||
}
|
||||
files := ctxt.PosTable.FileTable()
|
||||
usedFiles := make([]goobj.CUFileIndex, 0, len(pc.UsedFiles))
|
||||
for f := range pc.UsedFiles {
|
||||
usedFiles = append(usedFiles, f)
|
||||
}
|
||||
sort.Slice(usedFiles, func(i, j int) bool { return usedFiles[i] < usedFiles[j] })
|
||||
for _, f := range usedFiles {
|
||||
if filesym := ctxt.Lookup(files[f]); filesym != nil {
|
||||
fn(fsym, filesym)
|
||||
}
|
||||
}
|
||||
for _, call := range pc.InlTree.nodes {
|
||||
if call.Func != nil {
|
||||
fn(fsym, call.Func)
|
||||
}
|
||||
f, _ := linkgetlineFromPos(ctxt, call.Pos)
|
||||
if filesym := ctxt.Lookup(f); filesym != nil {
|
||||
fn(fsym, filesym)
|
||||
}
|
||||
}
|
||||
dwsyms := []*LSym{fsym.Func.dwarfRangesSym, fsym.Func.dwarfLocSym, fsym.Func.dwarfDebugLinesSym, fsym.Func.dwarfInfoSym}
|
||||
for _, dws := range dwsyms {
|
||||
if dws == nil || dws.Size == 0 {
|
||||
continue
|
||||
}
|
||||
fn(fsym, dws)
|
||||
if flag&traverseRefs != 0 {
|
||||
for _, r := range dws.R {
|
||||
if r.Sym != nil {
|
||||
fn(dws, r.Sym)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Traverse aux symbols, calling fn for each sym/aux pair.
|
||||
func (ctxt *Link) traverseAuxSyms(flag traverseFlag, fn func(parent *LSym, aux *LSym)) {
|
||||
lists := [][]*LSym{ctxt.Text, ctxt.Data, ctxt.ABIAliases}
|
||||
for _, list := range lists {
|
||||
for _, s := range list {
|
||||
if s.Gotype != nil {
|
||||
if flag&traverseDefs != 0 {
|
||||
fn(s, s.Gotype)
|
||||
}
|
||||
}
|
||||
if s.Type != objabi.STEXT {
|
||||
continue
|
||||
}
|
||||
ctxt.traverseFuncAux(flag, s, fn)
|
||||
}
|
||||
}
|
||||
}
|
||||
54
vendor/github.com/twitchyliquid64/golang-asm/obj/textflag.go
generated
vendored
Normal file
54
vendor/github.com/twitchyliquid64/golang-asm/obj/textflag.go
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file defines flags attached to various functions
|
||||
// and data objects. The compilers, assemblers, and linker must
|
||||
// all agree on these values.
|
||||
|
||||
package obj
|
||||
|
||||
const (
|
||||
// Don't profile the marked routine.
|
||||
//
|
||||
// Deprecated: Not implemented, do not use.
|
||||
NOPROF = 1
|
||||
|
||||
// It is ok for the linker to get multiple of these symbols. It will
|
||||
// pick one of the duplicates to use.
|
||||
DUPOK = 2
|
||||
|
||||
// Don't insert stack check preamble.
|
||||
NOSPLIT = 4
|
||||
|
||||
// Put this data in a read-only section.
|
||||
RODATA = 8
|
||||
|
||||
// This data contains no pointers.
|
||||
NOPTR = 16
|
||||
|
||||
// This is a wrapper function and should not count as disabling 'recover'.
|
||||
WRAPPER = 32
|
||||
|
||||
// This function uses its incoming context register.
|
||||
NEEDCTXT = 64
|
||||
|
||||
// When passed to ggloblsym, causes Local to be set to true on the LSym it creates.
|
||||
LOCAL = 128
|
||||
|
||||
// Allocate a word of thread local storage and store the offset from the
|
||||
// thread local base to the thread local storage in this variable.
|
||||
TLSBSS = 256
|
||||
|
||||
// Do not insert instructions to allocate a stack frame for this function.
|
||||
// Only valid on functions that declare a frame size of 0.
|
||||
// TODO(mwhudson): only implemented for ppc64x at present.
|
||||
NOFRAME = 512
|
||||
|
||||
// Function can call reflect.Type.Method or reflect.Type.MethodByName.
|
||||
REFLECTMETHOD = 1024
|
||||
|
||||
// Function is the top of the call stack. Call stack unwinders should stop
|
||||
// at this function.
|
||||
TOPFRAME = 2048
|
||||
)
|
||||
598
vendor/github.com/twitchyliquid64/golang-asm/obj/util.go
generated
vendored
Normal file
598
vendor/github.com/twitchyliquid64/golang-asm/obj/util.go
generated
vendored
Normal file
@@ -0,0 +1,598 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package obj
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/twitchyliquid64/golang-asm/objabi"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const REG_NONE = 0
|
||||
|
||||
// Line returns a string containing the filename and line number for p
|
||||
func (p *Prog) Line() string {
|
||||
return p.Ctxt.OutermostPos(p.Pos).Format(false, true)
|
||||
}
|
||||
func (p *Prog) InnermostLine(w io.Writer) {
|
||||
p.Ctxt.InnermostPos(p.Pos).WriteTo(w, false, true)
|
||||
}
|
||||
|
||||
// InnermostLineNumber returns a string containing the line number for the
|
||||
// innermost inlined function (if any inlining) at p's position
|
||||
func (p *Prog) InnermostLineNumber() string {
|
||||
return p.Ctxt.InnermostPos(p.Pos).LineNumber()
|
||||
}
|
||||
|
||||
// InnermostLineNumberHTML returns a string containing the line number for the
|
||||
// innermost inlined function (if any inlining) at p's position
|
||||
func (p *Prog) InnermostLineNumberHTML() string {
|
||||
return p.Ctxt.InnermostPos(p.Pos).LineNumberHTML()
|
||||
}
|
||||
|
||||
// InnermostFilename returns a string containing the innermost
|
||||
// (in inlining) filename at p's position
|
||||
func (p *Prog) InnermostFilename() string {
|
||||
// TODO For now, this is only used for debugging output, and if we need more/better information, it might change.
|
||||
// An example of what we might want to see is the full stack of positions for inlined code, so we get some visibility into what is recorded there.
|
||||
pos := p.Ctxt.InnermostPos(p.Pos)
|
||||
if !pos.IsKnown() {
|
||||
return "<unknown file name>"
|
||||
}
|
||||
return pos.Filename()
|
||||
}
|
||||
|
||||
var armCondCode = []string{
|
||||
".EQ",
|
||||
".NE",
|
||||
".CS",
|
||||
".CC",
|
||||
".MI",
|
||||
".PL",
|
||||
".VS",
|
||||
".VC",
|
||||
".HI",
|
||||
".LS",
|
||||
".GE",
|
||||
".LT",
|
||||
".GT",
|
||||
".LE",
|
||||
"",
|
||||
".NV",
|
||||
}
|
||||
|
||||
/* ARM scond byte */
|
||||
const (
|
||||
C_SCOND = (1 << 4) - 1
|
||||
C_SBIT = 1 << 4
|
||||
C_PBIT = 1 << 5
|
||||
C_WBIT = 1 << 6
|
||||
C_FBIT = 1 << 7
|
||||
C_UBIT = 1 << 7
|
||||
C_SCOND_XOR = 14
|
||||
)
|
||||
|
||||
// CConv formats opcode suffix bits (Prog.Scond).
|
||||
func CConv(s uint8) string {
|
||||
if s == 0 {
|
||||
return ""
|
||||
}
|
||||
for i := range opSuffixSpace {
|
||||
sset := &opSuffixSpace[i]
|
||||
if sset.arch == objabi.GOARCH {
|
||||
return sset.cconv(s)
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("SC???%d", s)
|
||||
}
|
||||
|
||||
// CConvARM formats ARM opcode suffix bits (mostly condition codes).
|
||||
func CConvARM(s uint8) string {
|
||||
// TODO: could be great to move suffix-related things into
|
||||
// ARM asm backends some day.
|
||||
// obj/x86 can be used as an example.
|
||||
|
||||
sc := armCondCode[(s&C_SCOND)^C_SCOND_XOR]
|
||||
if s&C_SBIT != 0 {
|
||||
sc += ".S"
|
||||
}
|
||||
if s&C_PBIT != 0 {
|
||||
sc += ".P"
|
||||
}
|
||||
if s&C_WBIT != 0 {
|
||||
sc += ".W"
|
||||
}
|
||||
if s&C_UBIT != 0 { /* ambiguous with FBIT */
|
||||
sc += ".U"
|
||||
}
|
||||
return sc
|
||||
}
|
||||
|
||||
func (p *Prog) String() string {
|
||||
if p == nil {
|
||||
return "<nil Prog>"
|
||||
}
|
||||
if p.Ctxt == nil {
|
||||
return "<Prog without ctxt>"
|
||||
}
|
||||
return fmt.Sprintf("%.5d (%v)\t%s", p.Pc, p.Line(), p.InstructionString())
|
||||
}
|
||||
|
||||
func (p *Prog) InnermostString(w io.Writer) {
|
||||
if p == nil {
|
||||
io.WriteString(w, "<nil Prog>")
|
||||
return
|
||||
}
|
||||
if p.Ctxt == nil {
|
||||
io.WriteString(w, "<Prog without ctxt>")
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(w, "%.5d (", p.Pc)
|
||||
p.InnermostLine(w)
|
||||
io.WriteString(w, ")\t")
|
||||
p.WriteInstructionString(w)
|
||||
}
|
||||
|
||||
// InstructionString returns a string representation of the instruction without preceding
|
||||
// program counter or file and line number.
|
||||
func (p *Prog) InstructionString() string {
|
||||
buf := new(bytes.Buffer)
|
||||
p.WriteInstructionString(buf)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// WriteInstructionString writes a string representation of the instruction without preceding
|
||||
// program counter or file and line number.
|
||||
func (p *Prog) WriteInstructionString(w io.Writer) {
|
||||
if p == nil {
|
||||
io.WriteString(w, "<nil Prog>")
|
||||
return
|
||||
}
|
||||
|
||||
if p.Ctxt == nil {
|
||||
io.WriteString(w, "<Prog without ctxt>")
|
||||
return
|
||||
}
|
||||
|
||||
sc := CConv(p.Scond)
|
||||
|
||||
io.WriteString(w, p.As.String())
|
||||
io.WriteString(w, sc)
|
||||
sep := "\t"
|
||||
|
||||
if p.From.Type != TYPE_NONE {
|
||||
io.WriteString(w, sep)
|
||||
WriteDconv(w, p, &p.From)
|
||||
sep = ", "
|
||||
}
|
||||
if p.Reg != REG_NONE {
|
||||
// Should not happen but might as well show it if it does.
|
||||
fmt.Fprintf(w, "%s%v", sep, Rconv(int(p.Reg)))
|
||||
sep = ", "
|
||||
}
|
||||
for i := range p.RestArgs {
|
||||
io.WriteString(w, sep)
|
||||
WriteDconv(w, p, &p.RestArgs[i])
|
||||
sep = ", "
|
||||
}
|
||||
|
||||
if p.As == ATEXT {
|
||||
// If there are attributes, print them. Otherwise, skip the comma.
|
||||
// In short, print one of these two:
|
||||
// TEXT foo(SB), DUPOK|NOSPLIT, $0
|
||||
// TEXT foo(SB), $0
|
||||
s := p.From.Sym.Attribute.TextAttrString()
|
||||
if s != "" {
|
||||
fmt.Fprintf(w, "%s%s", sep, s)
|
||||
sep = ", "
|
||||
}
|
||||
}
|
||||
if p.To.Type != TYPE_NONE {
|
||||
io.WriteString(w, sep)
|
||||
WriteDconv(w, p, &p.To)
|
||||
}
|
||||
if p.RegTo2 != REG_NONE {
|
||||
fmt.Fprintf(w, "%s%v", sep, Rconv(int(p.RegTo2)))
|
||||
}
|
||||
}
|
||||
|
||||
func (ctxt *Link) NewProg() *Prog {
|
||||
p := new(Prog)
|
||||
p.Ctxt = ctxt
|
||||
return p
|
||||
}
|
||||
|
||||
func (ctxt *Link) CanReuseProgs() bool {
|
||||
return ctxt.Debugasm == 0
|
||||
}
|
||||
|
||||
func Dconv(p *Prog, a *Addr) string {
|
||||
buf := new(bytes.Buffer)
|
||||
WriteDconv(buf, p, a)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func WriteDconv(w io.Writer, p *Prog, a *Addr) {
|
||||
switch a.Type {
|
||||
default:
|
||||
fmt.Fprintf(w, "type=%d", a.Type)
|
||||
|
||||
case TYPE_NONE:
|
||||
if a.Name != NAME_NONE || a.Reg != 0 || a.Sym != nil {
|
||||
a.WriteNameTo(w)
|
||||
fmt.Fprintf(w, "(%v)(NONE)", Rconv(int(a.Reg)))
|
||||
}
|
||||
|
||||
case TYPE_REG:
|
||||
// TODO(rsc): This special case is for x86 instructions like
|
||||
// PINSRQ CX,$1,X6
|
||||
// where the $1 is included in the p->to Addr.
|
||||
// Move into a new field.
|
||||
if a.Offset != 0 && (a.Reg < RBaseARM64 || a.Reg >= RBaseMIPS) {
|
||||
fmt.Fprintf(w, "$%d,%v", a.Offset, Rconv(int(a.Reg)))
|
||||
return
|
||||
}
|
||||
|
||||
if a.Name != NAME_NONE || a.Sym != nil {
|
||||
a.WriteNameTo(w)
|
||||
fmt.Fprintf(w, "(%v)(REG)", Rconv(int(a.Reg)))
|
||||
} else {
|
||||
io.WriteString(w, Rconv(int(a.Reg)))
|
||||
}
|
||||
if (RBaseARM64+1<<10+1<<9) /* arm64.REG_ELEM */ <= a.Reg &&
|
||||
a.Reg < (RBaseARM64+1<<11) /* arm64.REG_ELEM_END */ {
|
||||
fmt.Fprintf(w, "[%d]", a.Index)
|
||||
}
|
||||
|
||||
case TYPE_BRANCH:
|
||||
if a.Sym != nil {
|
||||
fmt.Fprintf(w, "%s(SB)", a.Sym.Name)
|
||||
} else if a.Target() != nil {
|
||||
fmt.Fprint(w, a.Target().Pc)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%d(PC)", a.Offset)
|
||||
}
|
||||
|
||||
case TYPE_INDIR:
|
||||
io.WriteString(w, "*")
|
||||
a.WriteNameTo(w)
|
||||
|
||||
case TYPE_MEM:
|
||||
a.WriteNameTo(w)
|
||||
if a.Index != REG_NONE {
|
||||
if a.Scale == 0 {
|
||||
// arm64 shifted or extended register offset, scale = 0.
|
||||
fmt.Fprintf(w, "(%v)", Rconv(int(a.Index)))
|
||||
} else {
|
||||
fmt.Fprintf(w, "(%v*%d)", Rconv(int(a.Index)), int(a.Scale))
|
||||
}
|
||||
}
|
||||
|
||||
case TYPE_CONST:
|
||||
io.WriteString(w, "$")
|
||||
a.WriteNameTo(w)
|
||||
if a.Reg != 0 {
|
||||
fmt.Fprintf(w, "(%v)", Rconv(int(a.Reg)))
|
||||
}
|
||||
|
||||
case TYPE_TEXTSIZE:
|
||||
if a.Val.(int32) == objabi.ArgsSizeUnknown {
|
||||
fmt.Fprintf(w, "$%d", a.Offset)
|
||||
} else {
|
||||
fmt.Fprintf(w, "$%d-%d", a.Offset, a.Val.(int32))
|
||||
}
|
||||
|
||||
case TYPE_FCONST:
|
||||
str := fmt.Sprintf("%.17g", a.Val.(float64))
|
||||
// Make sure 1 prints as 1.0
|
||||
if !strings.ContainsAny(str, ".e") {
|
||||
str += ".0"
|
||||
}
|
||||
fmt.Fprintf(w, "$(%s)", str)
|
||||
|
||||
case TYPE_SCONST:
|
||||
fmt.Fprintf(w, "$%q", a.Val.(string))
|
||||
|
||||
case TYPE_ADDR:
|
||||
io.WriteString(w, "$")
|
||||
a.WriteNameTo(w)
|
||||
|
||||
case TYPE_SHIFT:
|
||||
v := int(a.Offset)
|
||||
ops := "<<>>->@>"
|
||||
switch objabi.GOARCH {
|
||||
case "arm":
|
||||
op := ops[((v>>5)&3)<<1:]
|
||||
if v&(1<<4) != 0 {
|
||||
fmt.Fprintf(w, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15)
|
||||
} else {
|
||||
fmt.Fprintf(w, "R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31)
|
||||
}
|
||||
if a.Reg != 0 {
|
||||
fmt.Fprintf(w, "(%v)", Rconv(int(a.Reg)))
|
||||
}
|
||||
case "arm64":
|
||||
op := ops[((v>>22)&3)<<1:]
|
||||
r := (v >> 16) & 31
|
||||
fmt.Fprintf(w, "%s%c%c%d", Rconv(r+RBaseARM64), op[0], op[1], (v>>10)&63)
|
||||
default:
|
||||
panic("TYPE_SHIFT is not supported on " + objabi.GOARCH)
|
||||
}
|
||||
|
||||
case TYPE_REGREG:
|
||||
fmt.Fprintf(w, "(%v, %v)", Rconv(int(a.Reg)), Rconv(int(a.Offset)))
|
||||
|
||||
case TYPE_REGREG2:
|
||||
fmt.Fprintf(w, "%v, %v", Rconv(int(a.Offset)), Rconv(int(a.Reg)))
|
||||
|
||||
case TYPE_REGLIST:
|
||||
io.WriteString(w, RLconv(a.Offset))
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Addr) WriteNameTo(w io.Writer) {
|
||||
switch a.Name {
|
||||
default:
|
||||
fmt.Fprintf(w, "name=%d", a.Name)
|
||||
|
||||
case NAME_NONE:
|
||||
switch {
|
||||
case a.Reg == REG_NONE:
|
||||
fmt.Fprint(w, a.Offset)
|
||||
case a.Offset == 0:
|
||||
fmt.Fprintf(w, "(%v)", Rconv(int(a.Reg)))
|
||||
case a.Offset != 0:
|
||||
fmt.Fprintf(w, "%d(%v)", a.Offset, Rconv(int(a.Reg)))
|
||||
}
|
||||
|
||||
// Note: a.Reg == REG_NONE encodes the default base register for the NAME_ type.
|
||||
case NAME_EXTERN:
|
||||
reg := "SB"
|
||||
if a.Reg != REG_NONE {
|
||||
reg = Rconv(int(a.Reg))
|
||||
}
|
||||
if a.Sym != nil {
|
||||
fmt.Fprintf(w, "%s%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s(%s)", offConv(a.Offset), reg)
|
||||
}
|
||||
|
||||
case NAME_GOTREF:
|
||||
reg := "SB"
|
||||
if a.Reg != REG_NONE {
|
||||
reg = Rconv(int(a.Reg))
|
||||
}
|
||||
if a.Sym != nil {
|
||||
fmt.Fprintf(w, "%s%s@GOT(%s)", a.Sym.Name, offConv(a.Offset), reg)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s@GOT(%s)", offConv(a.Offset), reg)
|
||||
}
|
||||
|
||||
case NAME_STATIC:
|
||||
reg := "SB"
|
||||
if a.Reg != REG_NONE {
|
||||
reg = Rconv(int(a.Reg))
|
||||
}
|
||||
if a.Sym != nil {
|
||||
fmt.Fprintf(w, "%s<>%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
|
||||
} else {
|
||||
fmt.Fprintf(w, "<>%s(%s)", offConv(a.Offset), reg)
|
||||
}
|
||||
|
||||
case NAME_AUTO:
|
||||
reg := "SP"
|
||||
if a.Reg != REG_NONE {
|
||||
reg = Rconv(int(a.Reg))
|
||||
}
|
||||
if a.Sym != nil {
|
||||
fmt.Fprintf(w, "%s%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s(%s)", offConv(a.Offset), reg)
|
||||
}
|
||||
|
||||
case NAME_PARAM:
|
||||
reg := "FP"
|
||||
if a.Reg != REG_NONE {
|
||||
reg = Rconv(int(a.Reg))
|
||||
}
|
||||
if a.Sym != nil {
|
||||
fmt.Fprintf(w, "%s%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s(%s)", offConv(a.Offset), reg)
|
||||
}
|
||||
case NAME_TOCREF:
|
||||
reg := "SB"
|
||||
if a.Reg != REG_NONE {
|
||||
reg = Rconv(int(a.Reg))
|
||||
}
|
||||
if a.Sym != nil {
|
||||
fmt.Fprintf(w, "%s%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s(%s)", offConv(a.Offset), reg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func offConv(off int64) string {
|
||||
if off == 0 {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%+d", off)
|
||||
}
|
||||
|
||||
// opSuffixSet is like regListSet, but for opcode suffixes.
|
||||
//
|
||||
// Unlike some other similar structures, uint8 space is not
|
||||
// divided by its own values set (because there are only 256 of them).
|
||||
// Instead, every arch may interpret/format all 8 bits as they like,
|
||||
// as long as they register proper cconv function for it.
|
||||
type opSuffixSet struct {
|
||||
arch string
|
||||
cconv func(suffix uint8) string
|
||||
}
|
||||
|
||||
var opSuffixSpace []opSuffixSet
|
||||
|
||||
// RegisterOpSuffix assigns cconv function for formatting opcode suffixes
|
||||
// when compiling for GOARCH=arch.
|
||||
//
|
||||
// cconv is never called with 0 argument.
|
||||
func RegisterOpSuffix(arch string, cconv func(uint8) string) {
|
||||
opSuffixSpace = append(opSuffixSpace, opSuffixSet{
|
||||
arch: arch,
|
||||
cconv: cconv,
|
||||
})
|
||||
}
|
||||
|
||||
type regSet struct {
|
||||
lo int
|
||||
hi int
|
||||
Rconv func(int) string
|
||||
}
|
||||
|
||||
// Few enough architectures that a linear scan is fastest.
|
||||
// Not even worth sorting.
|
||||
var regSpace []regSet
|
||||
|
||||
/*
|
||||
Each architecture defines a register space as a unique
|
||||
integer range.
|
||||
Here is the list of architectures and the base of their register spaces.
|
||||
*/
|
||||
|
||||
const (
|
||||
// Because of masking operations in the encodings, each register
|
||||
// space should start at 0 modulo some power of 2.
|
||||
RBase386 = 1 * 1024
|
||||
RBaseAMD64 = 2 * 1024
|
||||
RBaseARM = 3 * 1024
|
||||
RBasePPC64 = 4 * 1024 // range [4k, 8k)
|
||||
RBaseARM64 = 8 * 1024 // range [8k, 13k)
|
||||
RBaseMIPS = 13 * 1024 // range [13k, 14k)
|
||||
RBaseS390X = 14 * 1024 // range [14k, 15k)
|
||||
RBaseRISCV = 15 * 1024 // range [15k, 16k)
|
||||
RBaseWasm = 16 * 1024
|
||||
)
|
||||
|
||||
// RegisterRegister binds a pretty-printer (Rconv) for register
|
||||
// numbers to a given register number range. Lo is inclusive,
|
||||
// hi exclusive (valid registers are lo through hi-1).
|
||||
func RegisterRegister(lo, hi int, Rconv func(int) string) {
|
||||
regSpace = append(regSpace, regSet{lo, hi, Rconv})
|
||||
}
|
||||
|
||||
func Rconv(reg int) string {
|
||||
if reg == REG_NONE {
|
||||
return "NONE"
|
||||
}
|
||||
for i := range regSpace {
|
||||
rs := ®Space[i]
|
||||
if rs.lo <= reg && reg < rs.hi {
|
||||
return rs.Rconv(reg)
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("R???%d", reg)
|
||||
}
|
||||
|
||||
type regListSet struct {
|
||||
lo int64
|
||||
hi int64
|
||||
RLconv func(int64) string
|
||||
}
|
||||
|
||||
var regListSpace []regListSet
|
||||
|
||||
// Each architecture is allotted a distinct subspace: [Lo, Hi) for declaring its
|
||||
// arch-specific register list numbers.
|
||||
const (
|
||||
RegListARMLo = 0
|
||||
RegListARMHi = 1 << 16
|
||||
|
||||
// arm64 uses the 60th bit to differentiate from other archs
|
||||
RegListARM64Lo = 1 << 60
|
||||
RegListARM64Hi = 1<<61 - 1
|
||||
|
||||
// x86 uses the 61th bit to differentiate from other archs
|
||||
RegListX86Lo = 1 << 61
|
||||
RegListX86Hi = 1<<62 - 1
|
||||
)
|
||||
|
||||
// RegisterRegisterList binds a pretty-printer (RLconv) for register list
|
||||
// numbers to a given register list number range. Lo is inclusive,
|
||||
// hi exclusive (valid register list are lo through hi-1).
|
||||
func RegisterRegisterList(lo, hi int64, rlconv func(int64) string) {
|
||||
regListSpace = append(regListSpace, regListSet{lo, hi, rlconv})
|
||||
}
|
||||
|
||||
func RLconv(list int64) string {
|
||||
for i := range regListSpace {
|
||||
rls := ®ListSpace[i]
|
||||
if rls.lo <= list && list < rls.hi {
|
||||
return rls.RLconv(list)
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("RL???%d", list)
|
||||
}
|
||||
|
||||
type opSet struct {
|
||||
lo As
|
||||
names []string
|
||||
}
|
||||
|
||||
// Not even worth sorting
|
||||
var aSpace []opSet
|
||||
|
||||
// RegisterOpcode binds a list of instruction names
|
||||
// to a given instruction number range.
|
||||
func RegisterOpcode(lo As, Anames []string) {
|
||||
if len(Anames) > AllowedOpCodes {
|
||||
panic(fmt.Sprintf("too many instructions, have %d max %d", len(Anames), AllowedOpCodes))
|
||||
}
|
||||
aSpace = append(aSpace, opSet{lo, Anames})
|
||||
}
|
||||
|
||||
func (a As) String() string {
|
||||
if 0 <= a && int(a) < len(Anames) {
|
||||
return Anames[a]
|
||||
}
|
||||
for i := range aSpace {
|
||||
as := &aSpace[i]
|
||||
if as.lo <= a && int(a-as.lo) < len(as.names) {
|
||||
return as.names[a-as.lo]
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("A???%d", a)
|
||||
}
|
||||
|
||||
var Anames = []string{
|
||||
"XXX",
|
||||
"CALL",
|
||||
"DUFFCOPY",
|
||||
"DUFFZERO",
|
||||
"END",
|
||||
"FUNCDATA",
|
||||
"JMP",
|
||||
"NOP",
|
||||
"PCALIGN",
|
||||
"PCDATA",
|
||||
"RET",
|
||||
"GETCALLERPC",
|
||||
"TEXT",
|
||||
"UNDEF",
|
||||
}
|
||||
|
||||
func Bool2int(b bool) int {
|
||||
// The compiler currently only optimizes this form.
|
||||
// See issue 6011.
|
||||
var i int
|
||||
if b {
|
||||
i = 1
|
||||
} else {
|
||||
i = 0
|
||||
}
|
||||
return i
|
||||
}
|
||||
331
vendor/github.com/twitchyliquid64/golang-asm/obj/wasm/a.out.go
generated
vendored
Normal file
331
vendor/github.com/twitchyliquid64/golang-asm/obj/wasm/a.out.go
generated
vendored
Normal file
@@ -0,0 +1,331 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package wasm
|
||||
|
||||
import "github.com/twitchyliquid64/golang-asm/obj"
|
||||
|
||||
//go:generate go run ../stringer.go -i $GOFILE -o anames.go -p wasm
|
||||
|
||||
const (
|
||||
/* mark flags */
|
||||
DONE = 1 << iota
|
||||
PRESERVEFLAGS // not allowed to clobber flags
|
||||
)
|
||||
|
||||
/*
|
||||
* wasm
|
||||
*/
|
||||
const (
|
||||
ACallImport = obj.ABaseWasm + obj.A_ARCHSPECIFIC + iota
|
||||
AGet
|
||||
ASet
|
||||
ATee
|
||||
ANot // alias for I32Eqz
|
||||
|
||||
// The following are low-level WebAssembly instructions.
|
||||
// Their order matters, since it matches the opcode encoding.
|
||||
// Gaps in the encoding are indicated by comments.
|
||||
|
||||
AUnreachable // opcode 0x00
|
||||
ANop
|
||||
ABlock
|
||||
ALoop
|
||||
AIf
|
||||
AElse
|
||||
|
||||
AEnd // opcode 0x0B
|
||||
ABr
|
||||
ABrIf
|
||||
ABrTable
|
||||
// ACall and AReturn are WebAssembly instructions. obj.ACALL and obj.ARET are higher level instructions
|
||||
// with Go semantics, e.g. they manipulate the Go stack on the linear memory.
|
||||
AReturn
|
||||
ACall
|
||||
ACallIndirect
|
||||
|
||||
ADrop // opcode 0x1A
|
||||
ASelect
|
||||
|
||||
ALocalGet // opcode 0x20
|
||||
ALocalSet
|
||||
ALocalTee
|
||||
AGlobalGet
|
||||
AGlobalSet
|
||||
|
||||
AI32Load // opcode 0x28
|
||||
AI64Load
|
||||
AF32Load
|
||||
AF64Load
|
||||
AI32Load8S
|
||||
AI32Load8U
|
||||
AI32Load16S
|
||||
AI32Load16U
|
||||
AI64Load8S
|
||||
AI64Load8U
|
||||
AI64Load16S
|
||||
AI64Load16U
|
||||
AI64Load32S
|
||||
AI64Load32U
|
||||
AI32Store
|
||||
AI64Store
|
||||
AF32Store
|
||||
AF64Store
|
||||
AI32Store8
|
||||
AI32Store16
|
||||
AI64Store8
|
||||
AI64Store16
|
||||
AI64Store32
|
||||
ACurrentMemory
|
||||
AGrowMemory
|
||||
|
||||
AI32Const
|
||||
AI64Const
|
||||
AF32Const
|
||||
AF64Const
|
||||
|
||||
AI32Eqz
|
||||
AI32Eq
|
||||
AI32Ne
|
||||
AI32LtS
|
||||
AI32LtU
|
||||
AI32GtS
|
||||
AI32GtU
|
||||
AI32LeS
|
||||
AI32LeU
|
||||
AI32GeS
|
||||
AI32GeU
|
||||
|
||||
AI64Eqz
|
||||
AI64Eq
|
||||
AI64Ne
|
||||
AI64LtS
|
||||
AI64LtU
|
||||
AI64GtS
|
||||
AI64GtU
|
||||
AI64LeS
|
||||
AI64LeU
|
||||
AI64GeS
|
||||
AI64GeU
|
||||
|
||||
AF32Eq
|
||||
AF32Ne
|
||||
AF32Lt
|
||||
AF32Gt
|
||||
AF32Le
|
||||
AF32Ge
|
||||
|
||||
AF64Eq
|
||||
AF64Ne
|
||||
AF64Lt
|
||||
AF64Gt
|
||||
AF64Le
|
||||
AF64Ge
|
||||
|
||||
AI32Clz
|
||||
AI32Ctz
|
||||
AI32Popcnt
|
||||
AI32Add
|
||||
AI32Sub
|
||||
AI32Mul
|
||||
AI32DivS
|
||||
AI32DivU
|
||||
AI32RemS
|
||||
AI32RemU
|
||||
AI32And
|
||||
AI32Or
|
||||
AI32Xor
|
||||
AI32Shl
|
||||
AI32ShrS
|
||||
AI32ShrU
|
||||
AI32Rotl
|
||||
AI32Rotr
|
||||
|
||||
AI64Clz
|
||||
AI64Ctz
|
||||
AI64Popcnt
|
||||
AI64Add
|
||||
AI64Sub
|
||||
AI64Mul
|
||||
AI64DivS
|
||||
AI64DivU
|
||||
AI64RemS
|
||||
AI64RemU
|
||||
AI64And
|
||||
AI64Or
|
||||
AI64Xor
|
||||
AI64Shl
|
||||
AI64ShrS
|
||||
AI64ShrU
|
||||
AI64Rotl
|
||||
AI64Rotr
|
||||
|
||||
AF32Abs
|
||||
AF32Neg
|
||||
AF32Ceil
|
||||
AF32Floor
|
||||
AF32Trunc
|
||||
AF32Nearest
|
||||
AF32Sqrt
|
||||
AF32Add
|
||||
AF32Sub
|
||||
AF32Mul
|
||||
AF32Div
|
||||
AF32Min
|
||||
AF32Max
|
||||
AF32Copysign
|
||||
|
||||
AF64Abs
|
||||
AF64Neg
|
||||
AF64Ceil
|
||||
AF64Floor
|
||||
AF64Trunc
|
||||
AF64Nearest
|
||||
AF64Sqrt
|
||||
AF64Add
|
||||
AF64Sub
|
||||
AF64Mul
|
||||
AF64Div
|
||||
AF64Min
|
||||
AF64Max
|
||||
AF64Copysign
|
||||
|
||||
AI32WrapI64
|
||||
AI32TruncF32S
|
||||
AI32TruncF32U
|
||||
AI32TruncF64S
|
||||
AI32TruncF64U
|
||||
AI64ExtendI32S
|
||||
AI64ExtendI32U
|
||||
AI64TruncF32S
|
||||
AI64TruncF32U
|
||||
AI64TruncF64S
|
||||
AI64TruncF64U
|
||||
AF32ConvertI32S
|
||||
AF32ConvertI32U
|
||||
AF32ConvertI64S
|
||||
AF32ConvertI64U
|
||||
AF32DemoteF64
|
||||
AF64ConvertI32S
|
||||
AF64ConvertI32U
|
||||
AF64ConvertI64S
|
||||
AF64ConvertI64U
|
||||
AF64PromoteF32
|
||||
AI32ReinterpretF32
|
||||
AI64ReinterpretF64
|
||||
AF32ReinterpretI32
|
||||
AF64ReinterpretI64
|
||||
AI32Extend8S
|
||||
AI32Extend16S
|
||||
AI64Extend8S
|
||||
AI64Extend16S
|
||||
AI64Extend32S
|
||||
|
||||
AI32TruncSatF32S // opcode 0xFC 0x00
|
||||
AI32TruncSatF32U
|
||||
AI32TruncSatF64S
|
||||
AI32TruncSatF64U
|
||||
AI64TruncSatF32S
|
||||
AI64TruncSatF32U
|
||||
AI64TruncSatF64S
|
||||
AI64TruncSatF64U
|
||||
|
||||
ALast // Sentinel: End of low-level WebAssembly instructions.
|
||||
|
||||
ARESUMEPOINT
|
||||
// ACALLNORESUME is a call which is not followed by a resume point.
|
||||
// It is allowed inside of WebAssembly blocks, whereas obj.ACALL is not.
|
||||
// However, it is not allowed to switch goroutines while inside of an ACALLNORESUME call.
|
||||
ACALLNORESUME
|
||||
|
||||
ARETUNWIND
|
||||
|
||||
AMOVB
|
||||
AMOVH
|
||||
AMOVW
|
||||
AMOVD
|
||||
|
||||
AWORD
|
||||
ALAST
|
||||
)
|
||||
|
||||
const (
|
||||
REG_NONE = 0
|
||||
)
|
||||
|
||||
const (
|
||||
// globals
|
||||
REG_SP = obj.RBaseWasm + iota // SP is currently 32-bit, until 64-bit memory operations are available
|
||||
REG_CTXT
|
||||
REG_g
|
||||
// RET* are used by runtime.return0 and runtime.reflectcall. These functions pass return values in registers.
|
||||
REG_RET0
|
||||
REG_RET1
|
||||
REG_RET2
|
||||
REG_RET3
|
||||
REG_PAUSE
|
||||
|
||||
// i32 locals
|
||||
REG_R0
|
||||
REG_R1
|
||||
REG_R2
|
||||
REG_R3
|
||||
REG_R4
|
||||
REG_R5
|
||||
REG_R6
|
||||
REG_R7
|
||||
REG_R8
|
||||
REG_R9
|
||||
REG_R10
|
||||
REG_R11
|
||||
REG_R12
|
||||
REG_R13
|
||||
REG_R14
|
||||
REG_R15
|
||||
|
||||
// f32 locals
|
||||
REG_F0
|
||||
REG_F1
|
||||
REG_F2
|
||||
REG_F3
|
||||
REG_F4
|
||||
REG_F5
|
||||
REG_F6
|
||||
REG_F7
|
||||
REG_F8
|
||||
REG_F9
|
||||
REG_F10
|
||||
REG_F11
|
||||
REG_F12
|
||||
REG_F13
|
||||
REG_F14
|
||||
REG_F15
|
||||
|
||||
// f64 locals
|
||||
REG_F16
|
||||
REG_F17
|
||||
REG_F18
|
||||
REG_F19
|
||||
REG_F20
|
||||
REG_F21
|
||||
REG_F22
|
||||
REG_F23
|
||||
REG_F24
|
||||
REG_F25
|
||||
REG_F26
|
||||
REG_F27
|
||||
REG_F28
|
||||
REG_F29
|
||||
REG_F30
|
||||
REG_F31
|
||||
|
||||
REG_PC_B // also first parameter, i32
|
||||
|
||||
MAXREG
|
||||
|
||||
MINREG = REG_SP
|
||||
REGSP = REG_SP
|
||||
REGCTXT = REG_CTXT
|
||||
REGG = REG_g
|
||||
)
|
||||
208
vendor/github.com/twitchyliquid64/golang-asm/obj/wasm/anames.go
generated
vendored
Normal file
208
vendor/github.com/twitchyliquid64/golang-asm/obj/wasm/anames.go
generated
vendored
Normal file
@@ -0,0 +1,208 @@
|
||||
// Code generated by stringer -i a.out.go -o anames.go -p wasm; DO NOT EDIT.
|
||||
|
||||
package wasm
|
||||
|
||||
import "github.com/twitchyliquid64/golang-asm/obj"
|
||||
|
||||
var Anames = []string{
|
||||
obj.A_ARCHSPECIFIC: "CallImport",
|
||||
"Get",
|
||||
"Set",
|
||||
"Tee",
|
||||
"Not",
|
||||
"Unreachable",
|
||||
"Nop",
|
||||
"Block",
|
||||
"Loop",
|
||||
"If",
|
||||
"Else",
|
||||
"End",
|
||||
"Br",
|
||||
"BrIf",
|
||||
"BrTable",
|
||||
"Return",
|
||||
"Call",
|
||||
"CallIndirect",
|
||||
"Drop",
|
||||
"Select",
|
||||
"LocalGet",
|
||||
"LocalSet",
|
||||
"LocalTee",
|
||||
"GlobalGet",
|
||||
"GlobalSet",
|
||||
"I32Load",
|
||||
"I64Load",
|
||||
"F32Load",
|
||||
"F64Load",
|
||||
"I32Load8S",
|
||||
"I32Load8U",
|
||||
"I32Load16S",
|
||||
"I32Load16U",
|
||||
"I64Load8S",
|
||||
"I64Load8U",
|
||||
"I64Load16S",
|
||||
"I64Load16U",
|
||||
"I64Load32S",
|
||||
"I64Load32U",
|
||||
"I32Store",
|
||||
"I64Store",
|
||||
"F32Store",
|
||||
"F64Store",
|
||||
"I32Store8",
|
||||
"I32Store16",
|
||||
"I64Store8",
|
||||
"I64Store16",
|
||||
"I64Store32",
|
||||
"CurrentMemory",
|
||||
"GrowMemory",
|
||||
"I32Const",
|
||||
"I64Const",
|
||||
"F32Const",
|
||||
"F64Const",
|
||||
"I32Eqz",
|
||||
"I32Eq",
|
||||
"I32Ne",
|
||||
"I32LtS",
|
||||
"I32LtU",
|
||||
"I32GtS",
|
||||
"I32GtU",
|
||||
"I32LeS",
|
||||
"I32LeU",
|
||||
"I32GeS",
|
||||
"I32GeU",
|
||||
"I64Eqz",
|
||||
"I64Eq",
|
||||
"I64Ne",
|
||||
"I64LtS",
|
||||
"I64LtU",
|
||||
"I64GtS",
|
||||
"I64GtU",
|
||||
"I64LeS",
|
||||
"I64LeU",
|
||||
"I64GeS",
|
||||
"I64GeU",
|
||||
"F32Eq",
|
||||
"F32Ne",
|
||||
"F32Lt",
|
||||
"F32Gt",
|
||||
"F32Le",
|
||||
"F32Ge",
|
||||
"F64Eq",
|
||||
"F64Ne",
|
||||
"F64Lt",
|
||||
"F64Gt",
|
||||
"F64Le",
|
||||
"F64Ge",
|
||||
"I32Clz",
|
||||
"I32Ctz",
|
||||
"I32Popcnt",
|
||||
"I32Add",
|
||||
"I32Sub",
|
||||
"I32Mul",
|
||||
"I32DivS",
|
||||
"I32DivU",
|
||||
"I32RemS",
|
||||
"I32RemU",
|
||||
"I32And",
|
||||
"I32Or",
|
||||
"I32Xor",
|
||||
"I32Shl",
|
||||
"I32ShrS",
|
||||
"I32ShrU",
|
||||
"I32Rotl",
|
||||
"I32Rotr",
|
||||
"I64Clz",
|
||||
"I64Ctz",
|
||||
"I64Popcnt",
|
||||
"I64Add",
|
||||
"I64Sub",
|
||||
"I64Mul",
|
||||
"I64DivS",
|
||||
"I64DivU",
|
||||
"I64RemS",
|
||||
"I64RemU",
|
||||
"I64And",
|
||||
"I64Or",
|
||||
"I64Xor",
|
||||
"I64Shl",
|
||||
"I64ShrS",
|
||||
"I64ShrU",
|
||||
"I64Rotl",
|
||||
"I64Rotr",
|
||||
"F32Abs",
|
||||
"F32Neg",
|
||||
"F32Ceil",
|
||||
"F32Floor",
|
||||
"F32Trunc",
|
||||
"F32Nearest",
|
||||
"F32Sqrt",
|
||||
"F32Add",
|
||||
"F32Sub",
|
||||
"F32Mul",
|
||||
"F32Div",
|
||||
"F32Min",
|
||||
"F32Max",
|
||||
"F32Copysign",
|
||||
"F64Abs",
|
||||
"F64Neg",
|
||||
"F64Ceil",
|
||||
"F64Floor",
|
||||
"F64Trunc",
|
||||
"F64Nearest",
|
||||
"F64Sqrt",
|
||||
"F64Add",
|
||||
"F64Sub",
|
||||
"F64Mul",
|
||||
"F64Div",
|
||||
"F64Min",
|
||||
"F64Max",
|
||||
"F64Copysign",
|
||||
"I32WrapI64",
|
||||
"I32TruncF32S",
|
||||
"I32TruncF32U",
|
||||
"I32TruncF64S",
|
||||
"I32TruncF64U",
|
||||
"I64ExtendI32S",
|
||||
"I64ExtendI32U",
|
||||
"I64TruncF32S",
|
||||
"I64TruncF32U",
|
||||
"I64TruncF64S",
|
||||
"I64TruncF64U",
|
||||
"F32ConvertI32S",
|
||||
"F32ConvertI32U",
|
||||
"F32ConvertI64S",
|
||||
"F32ConvertI64U",
|
||||
"F32DemoteF64",
|
||||
"F64ConvertI32S",
|
||||
"F64ConvertI32U",
|
||||
"F64ConvertI64S",
|
||||
"F64ConvertI64U",
|
||||
"F64PromoteF32",
|
||||
"I32ReinterpretF32",
|
||||
"I64ReinterpretF64",
|
||||
"F32ReinterpretI32",
|
||||
"F64ReinterpretI64",
|
||||
"I32Extend8S",
|
||||
"I32Extend16S",
|
||||
"I64Extend8S",
|
||||
"I64Extend16S",
|
||||
"I64Extend32S",
|
||||
"I32TruncSatF32S",
|
||||
"I32TruncSatF32U",
|
||||
"I32TruncSatF64S",
|
||||
"I32TruncSatF64U",
|
||||
"I64TruncSatF32S",
|
||||
"I64TruncSatF32U",
|
||||
"I64TruncSatF64S",
|
||||
"I64TruncSatF64U",
|
||||
"Last",
|
||||
"RESUMEPOINT",
|
||||
"CALLNORESUME",
|
||||
"RETUNWIND",
|
||||
"MOVB",
|
||||
"MOVH",
|
||||
"MOVW",
|
||||
"MOVD",
|
||||
"WORD",
|
||||
"LAST",
|
||||
}
|
||||
1185
vendor/github.com/twitchyliquid64/golang-asm/obj/wasm/wasmobj.go
generated
vendored
Normal file
1185
vendor/github.com/twitchyliquid64/golang-asm/obj/wasm/wasmobj.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
423
vendor/github.com/twitchyliquid64/golang-asm/obj/x86/a.out.go
generated
vendored
Normal file
423
vendor/github.com/twitchyliquid64/golang-asm/obj/x86/a.out.go
generated
vendored
Normal file
@@ -0,0 +1,423 @@
|
||||
// Inferno utils/6c/6.out.h
|
||||
// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6c/6.out.h
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package x86
|
||||
|
||||
import "github.com/twitchyliquid64/golang-asm/obj"
|
||||
|
||||
const (
|
||||
REG_NONE = 0
|
||||
)
|
||||
|
||||
const (
|
||||
REG_AL = obj.RBaseAMD64 + iota
|
||||
REG_CL
|
||||
REG_DL
|
||||
REG_BL
|
||||
REG_SPB
|
||||
REG_BPB
|
||||
REG_SIB
|
||||
REG_DIB
|
||||
REG_R8B
|
||||
REG_R9B
|
||||
REG_R10B
|
||||
REG_R11B
|
||||
REG_R12B
|
||||
REG_R13B
|
||||
REG_R14B
|
||||
REG_R15B
|
||||
|
||||
REG_AX
|
||||
REG_CX
|
||||
REG_DX
|
||||
REG_BX
|
||||
REG_SP
|
||||
REG_BP
|
||||
REG_SI
|
||||
REG_DI
|
||||
REG_R8
|
||||
REG_R9
|
||||
REG_R10
|
||||
REG_R11
|
||||
REG_R12
|
||||
REG_R13
|
||||
REG_R14
|
||||
REG_R15
|
||||
|
||||
REG_AH
|
||||
REG_CH
|
||||
REG_DH
|
||||
REG_BH
|
||||
|
||||
REG_F0
|
||||
REG_F1
|
||||
REG_F2
|
||||
REG_F3
|
||||
REG_F4
|
||||
REG_F5
|
||||
REG_F6
|
||||
REG_F7
|
||||
|
||||
REG_M0
|
||||
REG_M1
|
||||
REG_M2
|
||||
REG_M3
|
||||
REG_M4
|
||||
REG_M5
|
||||
REG_M6
|
||||
REG_M7
|
||||
|
||||
REG_K0
|
||||
REG_K1
|
||||
REG_K2
|
||||
REG_K3
|
||||
REG_K4
|
||||
REG_K5
|
||||
REG_K6
|
||||
REG_K7
|
||||
|
||||
REG_X0
|
||||
REG_X1
|
||||
REG_X2
|
||||
REG_X3
|
||||
REG_X4
|
||||
REG_X5
|
||||
REG_X6
|
||||
REG_X7
|
||||
REG_X8
|
||||
REG_X9
|
||||
REG_X10
|
||||
REG_X11
|
||||
REG_X12
|
||||
REG_X13
|
||||
REG_X14
|
||||
REG_X15
|
||||
REG_X16
|
||||
REG_X17
|
||||
REG_X18
|
||||
REG_X19
|
||||
REG_X20
|
||||
REG_X21
|
||||
REG_X22
|
||||
REG_X23
|
||||
REG_X24
|
||||
REG_X25
|
||||
REG_X26
|
||||
REG_X27
|
||||
REG_X28
|
||||
REG_X29
|
||||
REG_X30
|
||||
REG_X31
|
||||
|
||||
REG_Y0
|
||||
REG_Y1
|
||||
REG_Y2
|
||||
REG_Y3
|
||||
REG_Y4
|
||||
REG_Y5
|
||||
REG_Y6
|
||||
REG_Y7
|
||||
REG_Y8
|
||||
REG_Y9
|
||||
REG_Y10
|
||||
REG_Y11
|
||||
REG_Y12
|
||||
REG_Y13
|
||||
REG_Y14
|
||||
REG_Y15
|
||||
REG_Y16
|
||||
REG_Y17
|
||||
REG_Y18
|
||||
REG_Y19
|
||||
REG_Y20
|
||||
REG_Y21
|
||||
REG_Y22
|
||||
REG_Y23
|
||||
REG_Y24
|
||||
REG_Y25
|
||||
REG_Y26
|
||||
REG_Y27
|
||||
REG_Y28
|
||||
REG_Y29
|
||||
REG_Y30
|
||||
REG_Y31
|
||||
|
||||
REG_Z0
|
||||
REG_Z1
|
||||
REG_Z2
|
||||
REG_Z3
|
||||
REG_Z4
|
||||
REG_Z5
|
||||
REG_Z6
|
||||
REG_Z7
|
||||
REG_Z8
|
||||
REG_Z9
|
||||
REG_Z10
|
||||
REG_Z11
|
||||
REG_Z12
|
||||
REG_Z13
|
||||
REG_Z14
|
||||
REG_Z15
|
||||
REG_Z16
|
||||
REG_Z17
|
||||
REG_Z18
|
||||
REG_Z19
|
||||
REG_Z20
|
||||
REG_Z21
|
||||
REG_Z22
|
||||
REG_Z23
|
||||
REG_Z24
|
||||
REG_Z25
|
||||
REG_Z26
|
||||
REG_Z27
|
||||
REG_Z28
|
||||
REG_Z29
|
||||
REG_Z30
|
||||
REG_Z31
|
||||
|
||||
REG_CS
|
||||
REG_SS
|
||||
REG_DS
|
||||
REG_ES
|
||||
REG_FS
|
||||
REG_GS
|
||||
|
||||
REG_GDTR // global descriptor table register
|
||||
REG_IDTR // interrupt descriptor table register
|
||||
REG_LDTR // local descriptor table register
|
||||
REG_MSW // machine status word
|
||||
REG_TASK // task register
|
||||
|
||||
REG_CR0
|
||||
REG_CR1
|
||||
REG_CR2
|
||||
REG_CR3
|
||||
REG_CR4
|
||||
REG_CR5
|
||||
REG_CR6
|
||||
REG_CR7
|
||||
REG_CR8
|
||||
REG_CR9
|
||||
REG_CR10
|
||||
REG_CR11
|
||||
REG_CR12
|
||||
REG_CR13
|
||||
REG_CR14
|
||||
REG_CR15
|
||||
|
||||
REG_DR0
|
||||
REG_DR1
|
||||
REG_DR2
|
||||
REG_DR3
|
||||
REG_DR4
|
||||
REG_DR5
|
||||
REG_DR6
|
||||
REG_DR7
|
||||
|
||||
REG_TR0
|
||||
REG_TR1
|
||||
REG_TR2
|
||||
REG_TR3
|
||||
REG_TR4
|
||||
REG_TR5
|
||||
REG_TR6
|
||||
REG_TR7
|
||||
|
||||
REG_TLS
|
||||
|
||||
MAXREG
|
||||
|
||||
REG_CR = REG_CR0
|
||||
REG_DR = REG_DR0
|
||||
REG_TR = REG_TR0
|
||||
|
||||
REGARG = -1
|
||||
REGRET = REG_AX
|
||||
FREGRET = REG_X0
|
||||
REGSP = REG_SP
|
||||
REGCTXT = REG_DX
|
||||
REGEXT = REG_R15 // compiler allocates external registers R15 down
|
||||
FREGMIN = REG_X0 + 5 // first register variable
|
||||
FREGEXT = REG_X0 + 15 // first external register
|
||||
T_TYPE = 1 << 0
|
||||
T_INDEX = 1 << 1
|
||||
T_OFFSET = 1 << 2
|
||||
T_FCONST = 1 << 3
|
||||
T_SYM = 1 << 4
|
||||
T_SCONST = 1 << 5
|
||||
T_64 = 1 << 6
|
||||
T_GOTYPE = 1 << 7
|
||||
)
|
||||
|
||||
// https://www.uclibc.org/docs/psABI-x86_64.pdf, figure 3.36
|
||||
var AMD64DWARFRegisters = map[int16]int16{
|
||||
REG_AX: 0,
|
||||
REG_DX: 1,
|
||||
REG_CX: 2,
|
||||
REG_BX: 3,
|
||||
REG_SI: 4,
|
||||
REG_DI: 5,
|
||||
REG_BP: 6,
|
||||
REG_SP: 7,
|
||||
REG_R8: 8,
|
||||
REG_R9: 9,
|
||||
REG_R10: 10,
|
||||
REG_R11: 11,
|
||||
REG_R12: 12,
|
||||
REG_R13: 13,
|
||||
REG_R14: 14,
|
||||
REG_R15: 15,
|
||||
// 16 is "Return Address RA", whatever that is.
|
||||
// 17-24 vector registers (X/Y/Z).
|
||||
REG_X0: 17,
|
||||
REG_X1: 18,
|
||||
REG_X2: 19,
|
||||
REG_X3: 20,
|
||||
REG_X4: 21,
|
||||
REG_X5: 22,
|
||||
REG_X6: 23,
|
||||
REG_X7: 24,
|
||||
// 25-32 extended vector registers (X/Y/Z).
|
||||
REG_X8: 25,
|
||||
REG_X9: 26,
|
||||
REG_X10: 27,
|
||||
REG_X11: 28,
|
||||
REG_X12: 29,
|
||||
REG_X13: 30,
|
||||
REG_X14: 31,
|
||||
REG_X15: 32,
|
||||
// ST registers. %stN => FN.
|
||||
REG_F0: 33,
|
||||
REG_F1: 34,
|
||||
REG_F2: 35,
|
||||
REG_F3: 36,
|
||||
REG_F4: 37,
|
||||
REG_F5: 38,
|
||||
REG_F6: 39,
|
||||
REG_F7: 40,
|
||||
// MMX registers. %mmN => MN.
|
||||
REG_M0: 41,
|
||||
REG_M1: 42,
|
||||
REG_M2: 43,
|
||||
REG_M3: 44,
|
||||
REG_M4: 45,
|
||||
REG_M5: 46,
|
||||
REG_M6: 47,
|
||||
REG_M7: 48,
|
||||
// 48 is flags, which doesn't have a name.
|
||||
REG_ES: 50,
|
||||
REG_CS: 51,
|
||||
REG_SS: 52,
|
||||
REG_DS: 53,
|
||||
REG_FS: 54,
|
||||
REG_GS: 55,
|
||||
// 58 and 59 are {fs,gs}base, which don't have names.
|
||||
REG_TR: 62,
|
||||
REG_LDTR: 63,
|
||||
// 64-66 are mxcsr, fcw, fsw, which don't have names.
|
||||
|
||||
// 67-82 upper vector registers (X/Y/Z).
|
||||
REG_X16: 67,
|
||||
REG_X17: 68,
|
||||
REG_X18: 69,
|
||||
REG_X19: 70,
|
||||
REG_X20: 71,
|
||||
REG_X21: 72,
|
||||
REG_X22: 73,
|
||||
REG_X23: 74,
|
||||
REG_X24: 75,
|
||||
REG_X25: 76,
|
||||
REG_X26: 77,
|
||||
REG_X27: 78,
|
||||
REG_X28: 79,
|
||||
REG_X29: 80,
|
||||
REG_X30: 81,
|
||||
REG_X31: 82,
|
||||
|
||||
// 118-125 vector mask registers. %kN => KN.
|
||||
REG_K0: 118,
|
||||
REG_K1: 119,
|
||||
REG_K2: 120,
|
||||
REG_K3: 121,
|
||||
REG_K4: 122,
|
||||
REG_K5: 123,
|
||||
REG_K6: 124,
|
||||
REG_K7: 125,
|
||||
}
|
||||
|
||||
// https://www.uclibc.org/docs/psABI-i386.pdf, table 2.14
|
||||
var X86DWARFRegisters = map[int16]int16{
|
||||
REG_AX: 0,
|
||||
REG_CX: 1,
|
||||
REG_DX: 2,
|
||||
REG_BX: 3,
|
||||
REG_SP: 4,
|
||||
REG_BP: 5,
|
||||
REG_SI: 6,
|
||||
REG_DI: 7,
|
||||
// 8 is "Return Address RA", whatever that is.
|
||||
// 9 is flags, which doesn't have a name.
|
||||
// ST registers. %stN => FN.
|
||||
REG_F0: 11,
|
||||
REG_F1: 12,
|
||||
REG_F2: 13,
|
||||
REG_F3: 14,
|
||||
REG_F4: 15,
|
||||
REG_F5: 16,
|
||||
REG_F6: 17,
|
||||
REG_F7: 18,
|
||||
// XMM registers. %xmmN => XN.
|
||||
REG_X0: 21,
|
||||
REG_X1: 22,
|
||||
REG_X2: 23,
|
||||
REG_X3: 24,
|
||||
REG_X4: 25,
|
||||
REG_X5: 26,
|
||||
REG_X6: 27,
|
||||
REG_X7: 28,
|
||||
// MMX registers. %mmN => MN.
|
||||
REG_M0: 29,
|
||||
REG_M1: 30,
|
||||
REG_M2: 31,
|
||||
REG_M3: 32,
|
||||
REG_M4: 33,
|
||||
REG_M5: 34,
|
||||
REG_M6: 35,
|
||||
REG_M7: 36,
|
||||
// 39 is mxcsr, which doesn't have a name.
|
||||
REG_ES: 40,
|
||||
REG_CS: 41,
|
||||
REG_SS: 42,
|
||||
REG_DS: 43,
|
||||
REG_FS: 44,
|
||||
REG_GS: 45,
|
||||
REG_TR: 48,
|
||||
REG_LDTR: 49,
|
||||
}
|
||||
1609
vendor/github.com/twitchyliquid64/golang-asm/obj/x86/aenum.go
generated
vendored
Normal file
1609
vendor/github.com/twitchyliquid64/golang-asm/obj/x86/aenum.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1607
vendor/github.com/twitchyliquid64/golang-asm/obj/x86/anames.go
generated
vendored
Normal file
1607
vendor/github.com/twitchyliquid64/golang-asm/obj/x86/anames.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5446
vendor/github.com/twitchyliquid64/golang-asm/obj/x86/asm6.go
generated
vendored
Normal file
5446
vendor/github.com/twitchyliquid64/golang-asm/obj/x86/asm6.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4628
vendor/github.com/twitchyliquid64/golang-asm/obj/x86/avx_optabs.go
generated
vendored
Normal file
4628
vendor/github.com/twitchyliquid64/golang-asm/obj/x86/avx_optabs.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
382
vendor/github.com/twitchyliquid64/golang-asm/obj/x86/evex.go
generated
vendored
Normal file
382
vendor/github.com/twitchyliquid64/golang-asm/obj/x86/evex.go
generated
vendored
Normal file
@@ -0,0 +1,382 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x86
|
||||
|
||||
import (
|
||||
"github.com/twitchyliquid64/golang-asm/obj"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// evexBits stores EVEX prefix info that is used during instruction encoding.
|
||||
type evexBits struct {
|
||||
b1 byte // [W1mmLLpp]
|
||||
b2 byte // [NNNbbZRS]
|
||||
|
||||
// Associated instruction opcode.
|
||||
opcode byte
|
||||
}
|
||||
|
||||
// newEVEXBits creates evexBits object from enc bytes at z position.
|
||||
func newEVEXBits(z int, enc *opBytes) evexBits {
|
||||
return evexBits{
|
||||
b1: enc[z+0],
|
||||
b2: enc[z+1],
|
||||
opcode: enc[z+2],
|
||||
}
|
||||
}
|
||||
|
||||
// P returns EVEX.pp value.
|
||||
func (evex evexBits) P() byte { return (evex.b1 & evexP) >> 0 }
|
||||
|
||||
// L returns EVEX.L'L value.
|
||||
func (evex evexBits) L() byte { return (evex.b1 & evexL) >> 2 }
|
||||
|
||||
// M returns EVEX.mm value.
|
||||
func (evex evexBits) M() byte { return (evex.b1 & evexM) >> 4 }
|
||||
|
||||
// W returns EVEX.W value.
|
||||
func (evex evexBits) W() byte { return (evex.b1 & evexW) >> 7 }
|
||||
|
||||
// BroadcastEnabled reports whether BCST suffix is permitted.
|
||||
func (evex evexBits) BroadcastEnabled() bool {
|
||||
return evex.b2&evexBcst != 0
|
||||
}
|
||||
|
||||
// ZeroingEnabled reports whether Z suffix is permitted.
|
||||
func (evex evexBits) ZeroingEnabled() bool {
|
||||
return (evex.b2&evexZeroing)>>2 != 0
|
||||
}
|
||||
|
||||
// RoundingEnabled reports whether RN_SAE, RZ_SAE, RD_SAE and RU_SAE suffixes
|
||||
// are permitted.
|
||||
func (evex evexBits) RoundingEnabled() bool {
|
||||
return (evex.b2&evexRounding)>>1 != 0
|
||||
}
|
||||
|
||||
// SaeEnabled reports whether SAE suffix is permitted.
|
||||
func (evex evexBits) SaeEnabled() bool {
|
||||
return (evex.b2&evexSae)>>0 != 0
|
||||
}
|
||||
|
||||
// DispMultiplier returns displacement multiplier that is calculated
|
||||
// based on tuple type, EVEX.W and input size.
|
||||
// If embedded broadcast is used, bcst should be true.
|
||||
func (evex evexBits) DispMultiplier(bcst bool) int32 {
|
||||
if bcst {
|
||||
switch evex.b2 & evexBcst {
|
||||
case evexBcstN4:
|
||||
return 4
|
||||
case evexBcstN8:
|
||||
return 8
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
switch evex.b2 & evexN {
|
||||
case evexN1:
|
||||
return 1
|
||||
case evexN2:
|
||||
return 2
|
||||
case evexN4:
|
||||
return 4
|
||||
case evexN8:
|
||||
return 8
|
||||
case evexN16:
|
||||
return 16
|
||||
case evexN32:
|
||||
return 32
|
||||
case evexN64:
|
||||
return 64
|
||||
case evexN128:
|
||||
return 128
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
// EVEX is described by using 2-byte sequence.
|
||||
// See evexBits for more details.
|
||||
const (
|
||||
evexW = 0x80 // b1[W... ....]
|
||||
evexWIG = 0 << 7
|
||||
evexW0 = 0 << 7
|
||||
evexW1 = 1 << 7
|
||||
|
||||
evexM = 0x30 // b2[..mm ...]
|
||||
evex0F = 1 << 4
|
||||
evex0F38 = 2 << 4
|
||||
evex0F3A = 3 << 4
|
||||
|
||||
evexL = 0x0C // b1[.... LL..]
|
||||
evexLIG = 0 << 2
|
||||
evex128 = 0 << 2
|
||||
evex256 = 1 << 2
|
||||
evex512 = 2 << 2
|
||||
|
||||
evexP = 0x03 // b1[.... ..pp]
|
||||
evex66 = 1 << 0
|
||||
evexF3 = 2 << 0
|
||||
evexF2 = 3 << 0
|
||||
|
||||
// Precalculated Disp8 N value.
|
||||
// N acts like a multiplier for 8bit displacement.
|
||||
// Note that some N are not used, but their bits are reserved.
|
||||
evexN = 0xE0 // b2[NNN. ....]
|
||||
evexN1 = 0 << 5
|
||||
evexN2 = 1 << 5
|
||||
evexN4 = 2 << 5
|
||||
evexN8 = 3 << 5
|
||||
evexN16 = 4 << 5
|
||||
evexN32 = 5 << 5
|
||||
evexN64 = 6 << 5
|
||||
evexN128 = 7 << 5
|
||||
|
||||
// Disp8 for broadcasts.
|
||||
evexBcst = 0x18 // b2[...b b...]
|
||||
evexBcstN4 = 1 << 3
|
||||
evexBcstN8 = 2 << 3
|
||||
|
||||
// Flags that permit certain AVX512 features.
|
||||
// It's semantically illegal to combine evexZeroing and evexSae.
|
||||
evexZeroing = 0x4 // b2[.... .Z..]
|
||||
evexZeroingEnabled = 1 << 2
|
||||
evexRounding = 0x2 // b2[.... ..R.]
|
||||
evexRoundingEnabled = 1 << 1
|
||||
evexSae = 0x1 // b2[.... ...S]
|
||||
evexSaeEnabled = 1 << 0
|
||||
)
|
||||
|
||||
// compressedDisp8 calculates EVEX compressed displacement, if applicable.
|
||||
func compressedDisp8(disp, elemSize int32) (disp8 byte, ok bool) {
|
||||
if disp%elemSize == 0 {
|
||||
v := disp / elemSize
|
||||
if v >= -128 && v <= 127 {
|
||||
return byte(v), true
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// evexZcase reports whether given Z-case belongs to EVEX group.
|
||||
func evexZcase(zcase uint8) bool {
|
||||
return zcase > Zevex_first && zcase < Zevex_last
|
||||
}
|
||||
|
||||
// evexSuffixBits carries instruction EVEX suffix set flags.
|
||||
//
|
||||
// Examples:
|
||||
// "RU_SAE.Z" => {rounding: 3, zeroing: true}
|
||||
// "Z" => {zeroing: true}
|
||||
// "BCST" => {broadcast: true}
|
||||
// "SAE.Z" => {sae: true, zeroing: true}
|
||||
type evexSuffix struct {
|
||||
rounding byte
|
||||
sae bool
|
||||
zeroing bool
|
||||
broadcast bool
|
||||
}
|
||||
|
||||
// Rounding control values.
|
||||
// Match exact value for EVEX.L'L field (with exception of rcUnset).
|
||||
const (
|
||||
rcRNSAE = 0 // Round towards nearest
|
||||
rcRDSAE = 1 // Round towards -Inf
|
||||
rcRUSAE = 2 // Round towards +Inf
|
||||
rcRZSAE = 3 // Round towards zero
|
||||
rcUnset = 4
|
||||
)
|
||||
|
||||
// newEVEXSuffix returns proper zero value for evexSuffix.
|
||||
func newEVEXSuffix() evexSuffix {
|
||||
return evexSuffix{rounding: rcUnset}
|
||||
}
|
||||
|
||||
// evexSuffixMap maps obj.X86suffix to its decoded version.
|
||||
// Filled during init().
|
||||
var evexSuffixMap [255]evexSuffix
|
||||
|
||||
func init() {
|
||||
// Decode all valid suffixes for later use.
|
||||
for i := range opSuffixTable {
|
||||
suffix := newEVEXSuffix()
|
||||
parts := strings.Split(opSuffixTable[i], ".")
|
||||
for j := range parts {
|
||||
switch parts[j] {
|
||||
case "Z":
|
||||
suffix.zeroing = true
|
||||
case "BCST":
|
||||
suffix.broadcast = true
|
||||
case "SAE":
|
||||
suffix.sae = true
|
||||
|
||||
case "RN_SAE":
|
||||
suffix.rounding = rcRNSAE
|
||||
case "RD_SAE":
|
||||
suffix.rounding = rcRDSAE
|
||||
case "RU_SAE":
|
||||
suffix.rounding = rcRUSAE
|
||||
case "RZ_SAE":
|
||||
suffix.rounding = rcRZSAE
|
||||
}
|
||||
}
|
||||
evexSuffixMap[i] = suffix
|
||||
}
|
||||
}
|
||||
|
||||
// toDisp8 tries to convert disp to proper 8-bit displacement value.
|
||||
func toDisp8(disp int32, p *obj.Prog, asmbuf *AsmBuf) (disp8 byte, ok bool) {
|
||||
if asmbuf.evexflag {
|
||||
bcst := evexSuffixMap[p.Scond].broadcast
|
||||
elemSize := asmbuf.evex.DispMultiplier(bcst)
|
||||
return compressedDisp8(disp, elemSize)
|
||||
}
|
||||
return byte(disp), disp >= -128 && disp < 128
|
||||
}
|
||||
|
||||
// EncodeRegisterRange packs [reg0-reg1] list into 64-bit value that
|
||||
// is intended to be stored inside obj.Addr.Offset with TYPE_REGLIST.
|
||||
func EncodeRegisterRange(reg0, reg1 int16) int64 {
|
||||
return (int64(reg0) << 0) |
|
||||
(int64(reg1) << 16) |
|
||||
obj.RegListX86Lo
|
||||
}
|
||||
|
||||
// decodeRegisterRange unpacks [reg0-reg1] list from 64-bit value created by EncodeRegisterRange.
|
||||
func decodeRegisterRange(list int64) (reg0, reg1 int) {
|
||||
return int((list >> 0) & 0xFFFF),
|
||||
int((list >> 16) & 0xFFFF)
|
||||
}
|
||||
|
||||
// ParseSuffix handles the special suffix for the 386/AMD64.
|
||||
// Suffix bits are stored into p.Scond.
|
||||
//
|
||||
// Leading "." in cond is ignored.
|
||||
func ParseSuffix(p *obj.Prog, cond string) error {
|
||||
cond = strings.TrimPrefix(cond, ".")
|
||||
|
||||
suffix := newOpSuffix(cond)
|
||||
if !suffix.IsValid() {
|
||||
return inferSuffixError(cond)
|
||||
}
|
||||
|
||||
p.Scond = uint8(suffix)
|
||||
return nil
|
||||
}
|
||||
|
||||
// inferSuffixError returns non-nil error that describes what could be
|
||||
// the cause of suffix parse failure.
|
||||
//
|
||||
// At the point this function is executed there is already assembly error,
|
||||
// so we can burn some clocks to construct good error message.
|
||||
//
|
||||
// Reported issues:
|
||||
// - duplicated suffixes
|
||||
// - illegal rounding/SAE+broadcast combinations
|
||||
// - unknown suffixes
|
||||
// - misplaced suffix (e.g. wrong Z suffix position)
|
||||
func inferSuffixError(cond string) error {
|
||||
suffixSet := make(map[string]bool) // Set for duplicates detection.
|
||||
unknownSet := make(map[string]bool) // Set of unknown suffixes.
|
||||
hasBcst := false
|
||||
hasRoundSae := false
|
||||
var msg []string // Error message parts
|
||||
|
||||
suffixes := strings.Split(cond, ".")
|
||||
for i, suffix := range suffixes {
|
||||
switch suffix {
|
||||
case "Z":
|
||||
if i != len(suffixes)-1 {
|
||||
msg = append(msg, "Z suffix should be the last")
|
||||
}
|
||||
case "BCST":
|
||||
hasBcst = true
|
||||
case "SAE", "RN_SAE", "RZ_SAE", "RD_SAE", "RU_SAE":
|
||||
hasRoundSae = true
|
||||
default:
|
||||
if !unknownSet[suffix] {
|
||||
msg = append(msg, fmt.Sprintf("unknown suffix %q", suffix))
|
||||
}
|
||||
unknownSet[suffix] = true
|
||||
}
|
||||
|
||||
if suffixSet[suffix] {
|
||||
msg = append(msg, fmt.Sprintf("duplicate suffix %q", suffix))
|
||||
}
|
||||
suffixSet[suffix] = true
|
||||
}
|
||||
|
||||
if hasBcst && hasRoundSae {
|
||||
msg = append(msg, "can't combine rounding/SAE and broadcast")
|
||||
}
|
||||
|
||||
if len(msg) == 0 {
|
||||
return errors.New("bad suffix combination")
|
||||
}
|
||||
return errors.New(strings.Join(msg, "; "))
|
||||
}
|
||||
|
||||
// opSuffixTable is a complete list of possible opcode suffix combinations.
|
||||
// It "maps" uint8 suffix bits to their string representation.
|
||||
// With the exception of first and last elements, order is not important.
|
||||
var opSuffixTable = [...]string{
|
||||
"", // Map empty suffix to empty string.
|
||||
|
||||
"Z",
|
||||
|
||||
"SAE",
|
||||
"SAE.Z",
|
||||
|
||||
"RN_SAE",
|
||||
"RZ_SAE",
|
||||
"RD_SAE",
|
||||
"RU_SAE",
|
||||
"RN_SAE.Z",
|
||||
"RZ_SAE.Z",
|
||||
"RD_SAE.Z",
|
||||
"RU_SAE.Z",
|
||||
|
||||
"BCST",
|
||||
"BCST.Z",
|
||||
|
||||
"<bad suffix>",
|
||||
}
|
||||
|
||||
// opSuffix represents instruction opcode suffix.
|
||||
// Compound (multi-part) suffixes expressed with single opSuffix value.
|
||||
//
|
||||
// uint8 type is used to fit obj.Prog.Scond.
|
||||
type opSuffix uint8
|
||||
|
||||
// badOpSuffix is used to represent all invalid suffix combinations.
|
||||
const badOpSuffix = opSuffix(len(opSuffixTable) - 1)
|
||||
|
||||
// newOpSuffix returns opSuffix object that matches suffixes string.
|
||||
//
|
||||
// If no matching suffix is found, special "invalid" suffix is returned.
|
||||
// Use IsValid method to check against this case.
|
||||
func newOpSuffix(suffixes string) opSuffix {
|
||||
for i := range opSuffixTable {
|
||||
if opSuffixTable[i] == suffixes {
|
||||
return opSuffix(i)
|
||||
}
|
||||
}
|
||||
return badOpSuffix
|
||||
}
|
||||
|
||||
// IsValid reports whether suffix is valid.
|
||||
// Empty suffixes are valid.
|
||||
func (suffix opSuffix) IsValid() bool {
|
||||
return suffix != badOpSuffix
|
||||
}
|
||||
|
||||
// String returns suffix printed representation.
|
||||
//
|
||||
// It matches the string that was used to create suffix with NewX86Suffix()
|
||||
// for valid suffixes.
|
||||
// For all invalid suffixes, special marker is returned.
|
||||
func (suffix opSuffix) String() string {
|
||||
return opSuffixTable[suffix]
|
||||
}
|
||||
264
vendor/github.com/twitchyliquid64/golang-asm/obj/x86/list6.go
generated
vendored
Normal file
264
vendor/github.com/twitchyliquid64/golang-asm/obj/x86/list6.go
generated
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
// Inferno utils/6c/list.c
|
||||
// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6c/list.c
|
||||
//
|
||||
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
||||
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
||||
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
||||
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
||||
// Portions Copyright © 2004,2006 Bruce Ellis
|
||||
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
||||
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
||||
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package x86
|
||||
|
||||
import (
|
||||
"github.com/twitchyliquid64/golang-asm/obj"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var Register = []string{
|
||||
"AL", // [D_AL]
|
||||
"CL",
|
||||
"DL",
|
||||
"BL",
|
||||
"SPB",
|
||||
"BPB",
|
||||
"SIB",
|
||||
"DIB",
|
||||
"R8B",
|
||||
"R9B",
|
||||
"R10B",
|
||||
"R11B",
|
||||
"R12B",
|
||||
"R13B",
|
||||
"R14B",
|
||||
"R15B",
|
||||
"AX", // [D_AX]
|
||||
"CX",
|
||||
"DX",
|
||||
"BX",
|
||||
"SP",
|
||||
"BP",
|
||||
"SI",
|
||||
"DI",
|
||||
"R8",
|
||||
"R9",
|
||||
"R10",
|
||||
"R11",
|
||||
"R12",
|
||||
"R13",
|
||||
"R14",
|
||||
"R15",
|
||||
"AH",
|
||||
"CH",
|
||||
"DH",
|
||||
"BH",
|
||||
"F0", // [D_F0]
|
||||
"F1",
|
||||
"F2",
|
||||
"F3",
|
||||
"F4",
|
||||
"F5",
|
||||
"F6",
|
||||
"F7",
|
||||
"M0",
|
||||
"M1",
|
||||
"M2",
|
||||
"M3",
|
||||
"M4",
|
||||
"M5",
|
||||
"M6",
|
||||
"M7",
|
||||
"K0",
|
||||
"K1",
|
||||
"K2",
|
||||
"K3",
|
||||
"K4",
|
||||
"K5",
|
||||
"K6",
|
||||
"K7",
|
||||
"X0",
|
||||
"X1",
|
||||
"X2",
|
||||
"X3",
|
||||
"X4",
|
||||
"X5",
|
||||
"X6",
|
||||
"X7",
|
||||
"X8",
|
||||
"X9",
|
||||
"X10",
|
||||
"X11",
|
||||
"X12",
|
||||
"X13",
|
||||
"X14",
|
||||
"X15",
|
||||
"X16",
|
||||
"X17",
|
||||
"X18",
|
||||
"X19",
|
||||
"X20",
|
||||
"X21",
|
||||
"X22",
|
||||
"X23",
|
||||
"X24",
|
||||
"X25",
|
||||
"X26",
|
||||
"X27",
|
||||
"X28",
|
||||
"X29",
|
||||
"X30",
|
||||
"X31",
|
||||
"Y0",
|
||||
"Y1",
|
||||
"Y2",
|
||||
"Y3",
|
||||
"Y4",
|
||||
"Y5",
|
||||
"Y6",
|
||||
"Y7",
|
||||
"Y8",
|
||||
"Y9",
|
||||
"Y10",
|
||||
"Y11",
|
||||
"Y12",
|
||||
"Y13",
|
||||
"Y14",
|
||||
"Y15",
|
||||
"Y16",
|
||||
"Y17",
|
||||
"Y18",
|
||||
"Y19",
|
||||
"Y20",
|
||||
"Y21",
|
||||
"Y22",
|
||||
"Y23",
|
||||
"Y24",
|
||||
"Y25",
|
||||
"Y26",
|
||||
"Y27",
|
||||
"Y28",
|
||||
"Y29",
|
||||
"Y30",
|
||||
"Y31",
|
||||
"Z0",
|
||||
"Z1",
|
||||
"Z2",
|
||||
"Z3",
|
||||
"Z4",
|
||||
"Z5",
|
||||
"Z6",
|
||||
"Z7",
|
||||
"Z8",
|
||||
"Z9",
|
||||
"Z10",
|
||||
"Z11",
|
||||
"Z12",
|
||||
"Z13",
|
||||
"Z14",
|
||||
"Z15",
|
||||
"Z16",
|
||||
"Z17",
|
||||
"Z18",
|
||||
"Z19",
|
||||
"Z20",
|
||||
"Z21",
|
||||
"Z22",
|
||||
"Z23",
|
||||
"Z24",
|
||||
"Z25",
|
||||
"Z26",
|
||||
"Z27",
|
||||
"Z28",
|
||||
"Z29",
|
||||
"Z30",
|
||||
"Z31",
|
||||
"CS", // [D_CS]
|
||||
"SS",
|
||||
"DS",
|
||||
"ES",
|
||||
"FS",
|
||||
"GS",
|
||||
"GDTR", // [D_GDTR]
|
||||
"IDTR", // [D_IDTR]
|
||||
"LDTR", // [D_LDTR]
|
||||
"MSW", // [D_MSW]
|
||||
"TASK", // [D_TASK]
|
||||
"CR0", // [D_CR]
|
||||
"CR1",
|
||||
"CR2",
|
||||
"CR3",
|
||||
"CR4",
|
||||
"CR5",
|
||||
"CR6",
|
||||
"CR7",
|
||||
"CR8",
|
||||
"CR9",
|
||||
"CR10",
|
||||
"CR11",
|
||||
"CR12",
|
||||
"CR13",
|
||||
"CR14",
|
||||
"CR15",
|
||||
"DR0", // [D_DR]
|
||||
"DR1",
|
||||
"DR2",
|
||||
"DR3",
|
||||
"DR4",
|
||||
"DR5",
|
||||
"DR6",
|
||||
"DR7",
|
||||
"TR0", // [D_TR]
|
||||
"TR1",
|
||||
"TR2",
|
||||
"TR3",
|
||||
"TR4",
|
||||
"TR5",
|
||||
"TR6",
|
||||
"TR7",
|
||||
"TLS", // [D_TLS]
|
||||
"MAXREG", // [MAXREG]
|
||||
}
|
||||
|
||||
func init() {
|
||||
obj.RegisterRegister(REG_AL, REG_AL+len(Register), rconv)
|
||||
obj.RegisterOpcode(obj.ABaseAMD64, Anames)
|
||||
obj.RegisterRegisterList(obj.RegListX86Lo, obj.RegListX86Hi, rlconv)
|
||||
obj.RegisterOpSuffix("386", opSuffixString)
|
||||
obj.RegisterOpSuffix("amd64", opSuffixString)
|
||||
}
|
||||
|
||||
func rconv(r int) string {
|
||||
if REG_AL <= r && r-REG_AL < len(Register) {
|
||||
return Register[r-REG_AL]
|
||||
}
|
||||
return fmt.Sprintf("Rgok(%d)", r-obj.RBaseAMD64)
|
||||
}
|
||||
|
||||
func rlconv(bits int64) string {
|
||||
reg0, reg1 := decodeRegisterRange(bits)
|
||||
return fmt.Sprintf("[%s-%s]", rconv(reg0), rconv(reg1))
|
||||
}
|
||||
|
||||
func opSuffixString(s uint8) string {
|
||||
return "." + opSuffix(s).String()
|
||||
}
|
||||
1261
vendor/github.com/twitchyliquid64/golang-asm/obj/x86/obj6.go
generated
vendored
Normal file
1261
vendor/github.com/twitchyliquid64/golang-asm/obj/x86/obj6.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
44
vendor/github.com/twitchyliquid64/golang-asm/obj/x86/ytab.go
generated
vendored
Normal file
44
vendor/github.com/twitchyliquid64/golang-asm/obj/x86/ytab.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x86
|
||||
|
||||
// argListMax specifies upper arg count limit expected to be carried by obj.Prog.
|
||||
// Max len(obj.Prog.RestArgs) can be inferred from this to be 4.
|
||||
const argListMax int = 6
|
||||
|
||||
type argList [argListMax]uint8
|
||||
|
||||
type ytab struct {
|
||||
zcase uint8
|
||||
zoffset uint8
|
||||
|
||||
// Last arg is usually destination.
|
||||
// For unary instructions unaryDst is used to determine
|
||||
// if single argument is a source or destination.
|
||||
args argList
|
||||
}
|
||||
|
||||
// Returns true if yt is compatible with args.
|
||||
//
|
||||
// Elements from args and yt.args are used
|
||||
// to index ycover table like `ycover[args[i]+yt.args[i]]`.
|
||||
// This means that args should contain values that already
|
||||
// multiplied by Ymax.
|
||||
func (yt *ytab) match(args []int) bool {
|
||||
// Trailing Yxxx check is required to avoid a case
|
||||
// where shorter arg list is matched.
|
||||
// If we had exact yt.args length, it could be `yt.argc != len(args)`.
|
||||
if len(args) < len(yt.args) && yt.args[len(args)] != Yxxx {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range args {
|
||||
if ycover[args[i]+int(yt.args[i])] == 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
Reference in New Issue
Block a user