mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[chore] Update gin to v1.9.0 (#1553)
This commit is contained in:
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,
|
||||
}
|
Reference in New Issue
Block a user