mirror of
https://github.com/golang/go
synced 2024-10-16 12:53:34 +00:00
cmd/internal/obj, cmd/internal/obj/arm64: add support for GOARCH=arm64
ARM64 (ARMv8) has 32 general purpose, 64-bit integer registers (R0-R31), 32 64-bit scalar floating point registers (F0-F31), and 32 128-bit vector registers (unused, V0-V31). R31 is either the stack pointer (RSP), or the zero register (ZR), depending on the instruction. Note the distinction between the hardware stack pointer, RSP, and the virtual stack pointer SP. The (hardware) stack pointer must be 16-byte aligned at all times; the RSP register itself must be aligned, offset(RSP) only has to have natural alignment. Instructions are fixed-width, and are 32-bit wide. ARM64 supports ARMv7 too (32-bit ARM), but not in the same process. In general, there is not much in common between 32-bit ARM and ARM64, it's a new architecture. All implementations have floating point instructions. This change adds a Prog.To3 field analogous to Prog.To. It is used by exclusive load/store instructions such as STLXR which read from one register, and write to both a register and a memory address. STLXRW R1, (R0), R3 This will store the word contained in R1 to the memory address pointed by R0. R3 will be updated with the status result of the store. It is used to implement atomic operations. No other changes are made to the portable Prog and Addr structures. Change-Id: Ie839029aa5265bbad35769d9689eca11e1c48c47 Reviewed-on: https://go-review.googlesource.com/7046 Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
25e213752b
commit
26bbe7ac9b
711
src/cmd/internal/obj/arm64/7.out.go
Normal file
711
src/cmd/internal/obj/arm64/7.out.go
Normal file
|
@ -0,0 +1,711 @@
|
|||
// cmd/7c/7.out.h from Vita Nuova.
|
||||
// https://code.google.com/p/ken-cc/source/browse/src/cmd/7c/7.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 arm64
|
||||
|
||||
import "cmd/internal/obj"
|
||||
|
||||
const (
|
||||
NSNAME = 8
|
||||
NSYM = 50
|
||||
NREG = 32 /* number of general registers */
|
||||
NFREG = 32 /* number of floating point registers */
|
||||
)
|
||||
|
||||
// General purpose registers, kept in the low bits of Prog.Reg.
|
||||
const (
|
||||
// integer
|
||||
REG_R0 = obj.RBaseARM64 + iota
|
||||
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
|
||||
|
||||
// scalar floating point
|
||||
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
|
||||
|
||||
// SIMD
|
||||
REG_V0
|
||||
REG_V1
|
||||
REG_V2
|
||||
REG_V3
|
||||
REG_V4
|
||||
REG_V5
|
||||
REG_V6
|
||||
REG_V7
|
||||
REG_V8
|
||||
REG_V9
|
||||
REG_V10
|
||||
REG_V11
|
||||
REG_V12
|
||||
REG_V13
|
||||
REG_V14
|
||||
REG_V15
|
||||
REG_V16
|
||||
REG_V17
|
||||
REG_V18
|
||||
REG_V19
|
||||
REG_V20
|
||||
REG_V21
|
||||
REG_V22
|
||||
REG_V23
|
||||
REG_V24
|
||||
REG_V25
|
||||
REG_V26
|
||||
REG_V27
|
||||
REG_V28
|
||||
REG_V29
|
||||
REG_V30
|
||||
REG_V31
|
||||
|
||||
// The EQ in
|
||||
// CSET EQ, R0
|
||||
// is encoded as TYPE_REG, even though it's not really a register.
|
||||
COND_EQ
|
||||
COND_NE
|
||||
COND_HS
|
||||
COND_LO
|
||||
COND_MI
|
||||
COND_PL
|
||||
COND_VS
|
||||
COND_VC
|
||||
COND_HI
|
||||
COND_LS
|
||||
COND_GE
|
||||
COND_LT
|
||||
COND_GT
|
||||
COND_LE
|
||||
COND_AL
|
||||
COND_NV
|
||||
|
||||
REG_RSP = REG_V31 + 32 // to differentiate ZR/SP, REG_RSP&0x1f = 31
|
||||
)
|
||||
|
||||
// Not registers, but flags that can be combined with regular register
|
||||
// constants to indicate extended register conversion. When checking,
|
||||
// you should subtract obj.RBaseARM64 first. From this difference, bit 11
|
||||
// indicates extended register, bits 8-10 select the conversion mode.
|
||||
const REG_EXT = obj.RBaseARM64 + 1<<11
|
||||
|
||||
const (
|
||||
REG_UXTB = REG_EXT + iota<<8
|
||||
REG_UXTH
|
||||
REG_UXTW
|
||||
REG_UXTX
|
||||
REG_SXTB
|
||||
REG_SXTH
|
||||
REG_SXTW
|
||||
REG_SXTX
|
||||
)
|
||||
|
||||
// Special registers, after subtracting obj.RBaseARM64, bit 12 indicates
|
||||
// a special register and the low bits select the register.
|
||||
const (
|
||||
REG_SPECIAL = obj.RBaseARM64 + 1<<12 + iota
|
||||
REG_DAIF
|
||||
REG_NZCV
|
||||
REG_FPSR
|
||||
REG_FPCR
|
||||
REG_SPSR_EL1
|
||||
REG_ELR_EL1
|
||||
REG_SPSR_EL2
|
||||
REG_ELR_EL2
|
||||
REG_CurrentEL
|
||||
REG_SP_EL0
|
||||
REG_SPSel
|
||||
REG_DAIFSet
|
||||
REG_DAIFClr
|
||||
)
|
||||
|
||||
// Register assignments:
|
||||
//
|
||||
// compiler allocates R0 up as temps
|
||||
// compiler allocates register variables R7-R25
|
||||
// compiler allocates external registers R26 down
|
||||
//
|
||||
// compiler allocates register variables F7-F26
|
||||
// compiler allocates external registers F26 down
|
||||
const (
|
||||
REGMIN = REG_R7 // register variables allocated from here to REGMAX
|
||||
REGRT1 = REG_R16 // ARM64 IP0, for external linker, runtime, duffzero and duffcopy
|
||||
REGRT2 = REG_R17 // ARM64 IP1, for external linker, runtime, duffcopy
|
||||
REGPR = REG_R18 // ARM64 platform register, unused in the Go toolchain
|
||||
REGMAX = REG_R25
|
||||
|
||||
REGCTXT = REG_R26 // environment for closures
|
||||
REGTMP = REG_R27 // reserved for liblink
|
||||
REGG = REG_R28 // G
|
||||
REGFP = REG_R29 // frame pointer, unused in the Go toolchain
|
||||
REGLINK = REG_R30
|
||||
|
||||
// ARM64 uses R31 as both stack pointer and zero register,
|
||||
// depending on the instruction. To differentiate RSP from ZR,
|
||||
// we use a different numeric value for REGZERO and REGSP.
|
||||
REGZERO = REG_R31
|
||||
REGSP = REG_RSP
|
||||
|
||||
FREGRET = REG_F0
|
||||
FREGMIN = REG_F7 // first register variable
|
||||
FREGMAX = REG_F26 // last register variable for 7g only
|
||||
FREGEXT = REG_F26 // first external register
|
||||
FREGZERO = REG_F28 // both float and double
|
||||
FREGHALF = REG_F29 // double
|
||||
FREGONE = REG_F30 // double
|
||||
FREGTWO = REG_F31 // double
|
||||
)
|
||||
|
||||
const (
|
||||
BIG = 2048 - 8
|
||||
)
|
||||
|
||||
const (
|
||||
/* mark flags */
|
||||
LABEL = 1 << iota
|
||||
LEAF
|
||||
FLOAT
|
||||
BRANCH
|
||||
LOAD
|
||||
FCMP
|
||||
SYNC
|
||||
LIST
|
||||
FOLL
|
||||
NOSCHED
|
||||
)
|
||||
|
||||
const (
|
||||
C_NONE = iota
|
||||
C_REG // R0..R30
|
||||
C_RSP // R0..R30, RSP
|
||||
C_FREG // F0..F31
|
||||
C_VREG // V0..V31
|
||||
C_PAIR // (Rn, Rm)
|
||||
C_SHIFT // Rn<<2
|
||||
C_EXTREG // Rn.UXTB<<3
|
||||
C_SPR // REG_NZCV
|
||||
C_COND // EQ, NE, etc
|
||||
|
||||
C_ZCON // $0 or ZR
|
||||
C_ADDCON0 // 12-bit unsigned, unshifted
|
||||
C_ADDCON // 12-bit unsigned, shifted left by 0 or 12
|
||||
C_MOVCON // generated by a 16-bit constant, optionally inverted and/or shifted by multiple of 16
|
||||
C_BITCON // bitfield and logical immediate masks
|
||||
C_ABCON // could be C_ADDCON or C_BITCON
|
||||
C_MBCON // could be C_MOVCON or C_BITCON
|
||||
C_LCON // 32-bit constant
|
||||
C_VCON // 64-bit constant
|
||||
C_FCON // floating-point constant
|
||||
C_VCONADDR // 64-bit memory address
|
||||
|
||||
C_AACON // ADDCON offset in auto constant $a(FP)
|
||||
C_LACON // 32-bit offset in auto constant $a(FP)
|
||||
C_AECON // ADDCON offset in extern constant $e(SB)
|
||||
|
||||
// TODO(aram): only one branch class should be enough
|
||||
C_SBRA // for TYPE_BRANCH
|
||||
C_LBRA
|
||||
|
||||
C_NPAUTO // -512 <= x < 0, 0 mod 8
|
||||
C_NSAUTO // -256 <= x < 0
|
||||
C_PSAUTO // 0 to 255
|
||||
C_PPAUTO // 0 to 504, 0 mod 8
|
||||
C_UAUTO4K // 0 to 4095
|
||||
C_UAUTO8K // 0 to 8190, 0 mod 2
|
||||
C_UAUTO16K // 0 to 16380, 0 mod 4
|
||||
C_UAUTO32K // 0 to 32760, 0 mod 8
|
||||
C_UAUTO64K // 0 to 65520, 0 mod 16
|
||||
C_LAUTO // any other 32-bit constant
|
||||
|
||||
C_SEXT1 // 0 to 4095, direct
|
||||
C_SEXT2 // 0 to 8190
|
||||
C_SEXT4 // 0 to 16380
|
||||
C_SEXT8 // 0 to 32760
|
||||
C_SEXT16 // 0 to 65520
|
||||
C_LEXT
|
||||
|
||||
// TODO(aram): s/AUTO/INDIR/
|
||||
C_ZOREG // 0(R)
|
||||
C_NPOREG // mirror NPAUTO, etc
|
||||
C_NSOREG
|
||||
C_PSOREG
|
||||
C_PPOREG
|
||||
C_UOREG4K
|
||||
C_UOREG8K
|
||||
C_UOREG16K
|
||||
C_UOREG32K
|
||||
C_UOREG64K
|
||||
C_LOREG
|
||||
|
||||
C_ADDR // TODO(aram): explain difference from C_VCONADDR
|
||||
C_ROFF // register offset (including register extended)
|
||||
|
||||
C_GOK
|
||||
C_TEXTSIZE
|
||||
C_NCLASS // must be last
|
||||
)
|
||||
|
||||
const (
|
||||
C_XPRE = 1 << 6 // match arm.C_WBIT, so Prog.String know how to print it
|
||||
C_XPOST = 1 << 5 // match arm.C_PBIT, so Prog.String know how to print it
|
||||
)
|
||||
|
||||
//go:generate go run ../stringer.go -i $GOFILE -o anames.go -p arm64
|
||||
|
||||
const (
|
||||
AADC = obj.ABaseARM64 + obj.A_ARCHSPECIFIC + iota
|
||||
AADCS
|
||||
AADCSW
|
||||
AADCW
|
||||
AADD
|
||||
AADDS
|
||||
AADDSW
|
||||
AADDW
|
||||
AADR
|
||||
AADRP
|
||||
AAND
|
||||
AANDS
|
||||
AANDSW
|
||||
AANDW
|
||||
AASR
|
||||
AASRW
|
||||
AAT
|
||||
ABFI
|
||||
ABFIW
|
||||
ABFM
|
||||
ABFMW
|
||||
ABFXIL
|
||||
ABFXILW
|
||||
ABIC
|
||||
ABICS
|
||||
ABICSW
|
||||
ABICW
|
||||
ABRK
|
||||
ACBNZ
|
||||
ACBNZW
|
||||
ACBZ
|
||||
ACBZW
|
||||
ACCMN
|
||||
ACCMNW
|
||||
ACCMP
|
||||
ACCMPW
|
||||
ACINC
|
||||
ACINCW
|
||||
ACINV
|
||||
ACINVW
|
||||
ACLREX
|
||||
ACLS
|
||||
ACLSW
|
||||
ACLZ
|
||||
ACLZW
|
||||
ACMN
|
||||
ACMNW
|
||||
ACMP
|
||||
ACMPW
|
||||
ACNEG
|
||||
ACNEGW
|
||||
ACRC32B
|
||||
ACRC32CB
|
||||
ACRC32CH
|
||||
ACRC32CW
|
||||
ACRC32CX
|
||||
ACRC32H
|
||||
ACRC32W
|
||||
ACRC32X
|
||||
ACSEL
|
||||
ACSELW
|
||||
ACSET
|
||||
ACSETM
|
||||
ACSETMW
|
||||
ACSETW
|
||||
ACSINC
|
||||
ACSINCW
|
||||
ACSINV
|
||||
ACSINVW
|
||||
ACSNEG
|
||||
ACSNEGW
|
||||
ADC
|
||||
ADCPS1
|
||||
ADCPS2
|
||||
ADCPS3
|
||||
ADMB
|
||||
ADRPS
|
||||
ADSB
|
||||
AEON
|
||||
AEONW
|
||||
AEOR
|
||||
AEORW
|
||||
AERET
|
||||
AEXTR
|
||||
AEXTRW
|
||||
AHINT
|
||||
AHLT
|
||||
AHVC
|
||||
AIC
|
||||
AISB
|
||||
ALDAR
|
||||
ALDARB
|
||||
ALDARH
|
||||
ALDARW
|
||||
ALDAXP
|
||||
ALDAXPW
|
||||
ALDAXR
|
||||
ALDAXRB
|
||||
ALDAXRH
|
||||
ALDAXRW
|
||||
ALDP
|
||||
ALDXR
|
||||
ALDXRB
|
||||
ALDXRH
|
||||
ALDXRW
|
||||
ALDXP
|
||||
ALDXPW
|
||||
ALSL
|
||||
ALSLW
|
||||
ALSR
|
||||
ALSRW
|
||||
AMADD
|
||||
AMADDW
|
||||
AMNEG
|
||||
AMNEGW
|
||||
AMOVK
|
||||
AMOVKW
|
||||
AMOVN
|
||||
AMOVNW
|
||||
AMOVZ
|
||||
AMOVZW
|
||||
AMRS
|
||||
AMSR
|
||||
AMSUB
|
||||
AMSUBW
|
||||
AMUL
|
||||
AMULW
|
||||
AMVN
|
||||
AMVNW
|
||||
ANEG
|
||||
ANEGS
|
||||
ANEGSW
|
||||
ANEGW
|
||||
ANGC
|
||||
ANGCS
|
||||
ANGCSW
|
||||
ANGCW
|
||||
AORN
|
||||
AORNW
|
||||
AORR
|
||||
AORRW
|
||||
APRFM
|
||||
APRFUM
|
||||
ARBIT
|
||||
ARBITW
|
||||
AREM
|
||||
AREMW
|
||||
AREV
|
||||
AREV16
|
||||
AREV16W
|
||||
AREV32
|
||||
AREVW
|
||||
AROR
|
||||
ARORW
|
||||
ASBC
|
||||
ASBCS
|
||||
ASBCSW
|
||||
ASBCW
|
||||
ASBFIZ
|
||||
ASBFIZW
|
||||
ASBFM
|
||||
ASBFMW
|
||||
ASBFX
|
||||
ASBFXW
|
||||
ASDIV
|
||||
ASDIVW
|
||||
ASEV
|
||||
ASEVL
|
||||
ASMADDL
|
||||
ASMC
|
||||
ASMNEGL
|
||||
ASMSUBL
|
||||
ASMULH
|
||||
ASMULL
|
||||
ASTXR
|
||||
ASTXRB
|
||||
ASTXRH
|
||||
ASTXP
|
||||
ASTXPW
|
||||
ASTXRW
|
||||
ASTLP
|
||||
ASTLPW
|
||||
ASTLR
|
||||
ASTLRB
|
||||
ASTLRH
|
||||
ASTLRW
|
||||
ASTLXP
|
||||
ASTLXPW
|
||||
ASTLXR
|
||||
ASTLXRB
|
||||
ASTLXRH
|
||||
ASTLXRW
|
||||
ASTP
|
||||
ASUB
|
||||
ASUBS
|
||||
ASUBSW
|
||||
ASUBW
|
||||
ASVC
|
||||
ASXTB
|
||||
ASXTBW
|
||||
ASXTH
|
||||
ASXTHW
|
||||
ASXTW
|
||||
ASYS
|
||||
ASYSL
|
||||
ATBNZ
|
||||
ATBZ
|
||||
ATLBI
|
||||
ATST
|
||||
ATSTW
|
||||
AUBFIZ
|
||||
AUBFIZW
|
||||
AUBFM
|
||||
AUBFMW
|
||||
AUBFX
|
||||
AUBFXW
|
||||
AUDIV
|
||||
AUDIVW
|
||||
AUMADDL
|
||||
AUMNEGL
|
||||
AUMSUBL
|
||||
AUMULH
|
||||
AUMULL
|
||||
AUREM
|
||||
AUREMW
|
||||
AUXTB
|
||||
AUXTH
|
||||
AUXTW
|
||||
AUXTBW
|
||||
AUXTHW
|
||||
AWFE
|
||||
AWFI
|
||||
AYIELD
|
||||
AMOVB
|
||||
AMOVBU
|
||||
AMOVH
|
||||
AMOVHU
|
||||
AMOVW
|
||||
AMOVWU
|
||||
AMOVD
|
||||
AMOVNP
|
||||
AMOVNPW
|
||||
AMOVP
|
||||
AMOVPD
|
||||
AMOVPQ
|
||||
AMOVPS
|
||||
AMOVPSW
|
||||
AMOVPW
|
||||
ABEQ
|
||||
ABNE
|
||||
ABCS
|
||||
ABHS
|
||||
ABCC
|
||||
ABLO
|
||||
ABMI
|
||||
ABPL
|
||||
ABVS
|
||||
ABVC
|
||||
ABHI
|
||||
ABLS
|
||||
ABGE
|
||||
ABLT
|
||||
ABGT
|
||||
ABLE
|
||||
AFABSD
|
||||
AFABSS
|
||||
AFADDD
|
||||
AFADDS
|
||||
AFCCMPD
|
||||
AFCCMPED
|
||||
AFCCMPS
|
||||
AFCCMPES
|
||||
AFCMPD
|
||||
AFCMPED
|
||||
AFCMPES
|
||||
AFCMPS
|
||||
AFCVTSD
|
||||
AFCVTDS
|
||||
AFCVTZSD
|
||||
AFCVTZSDW
|
||||
AFCVTZSS
|
||||
AFCVTZSSW
|
||||
AFCVTZUD
|
||||
AFCVTZUDW
|
||||
AFCVTZUS
|
||||
AFCVTZUSW
|
||||
AFDIVD
|
||||
AFDIVS
|
||||
AFMOVD
|
||||
AFMOVS
|
||||
AFMULD
|
||||
AFMULS
|
||||
AFNEGD
|
||||
AFNEGS
|
||||
AFSQRTD
|
||||
AFSQRTS
|
||||
AFSUBD
|
||||
AFSUBS
|
||||
ASCVTFD
|
||||
ASCVTFS
|
||||
ASCVTFWD
|
||||
ASCVTFWS
|
||||
AUCVTFD
|
||||
AUCVTFS
|
||||
AUCVTFWD
|
||||
AUCVTFWS
|
||||
AHISTORY
|
||||
ANAME
|
||||
AWORD
|
||||
ADYNT
|
||||
AINIT
|
||||
ABCASE
|
||||
ACASE
|
||||
ADWORD
|
||||
ASIGNAME
|
||||
AGOK
|
||||
AEND
|
||||
AFCSELS
|
||||
AFCSELD
|
||||
AFMAXS
|
||||
AFMINS
|
||||
AFMAXD
|
||||
AFMIND
|
||||
AFMAXNMS
|
||||
AFMAXNMD
|
||||
AFNMULS
|
||||
AFNMULD
|
||||
AFRINTNS
|
||||
AFRINTND
|
||||
AFRINTPS
|
||||
AFRINTPD
|
||||
AFRINTMS
|
||||
AFRINTMD
|
||||
AFRINTZS
|
||||
AFRINTZD
|
||||
AFRINTAS
|
||||
AFRINTAD
|
||||
AFRINTXS
|
||||
AFRINTXD
|
||||
AFRINTIS
|
||||
AFRINTID
|
||||
AFMADDS
|
||||
AFMADDD
|
||||
AFMSUBS
|
||||
AFMSUBD
|
||||
AFNMADDS
|
||||
AFNMADDD
|
||||
AFNMSUBS
|
||||
AFNMSUBD
|
||||
AFMINNMS
|
||||
AFMINNMD
|
||||
AFCVTDH
|
||||
AFCVTHS
|
||||
AFCVTHD
|
||||
AFCVTSH
|
||||
AAESD
|
||||
AAESE
|
||||
AAESIMC
|
||||
AAESMC
|
||||
ASHA1C
|
||||
ASHA1H
|
||||
ASHA1M
|
||||
ASHA1P
|
||||
ASHA1SU0
|
||||
ASHA1SU1
|
||||
ASHA256H
|
||||
ASHA256H2
|
||||
ASHA256SU0
|
||||
ASHA256SU1
|
||||
ALAST
|
||||
AB = obj.AJMP
|
||||
ABL = obj.ACALL
|
||||
)
|
379
src/cmd/internal/obj/arm64/anames.go
Normal file
379
src/cmd/internal/obj/arm64/anames.go
Normal file
|
@ -0,0 +1,379 @@
|
|||
// Generated by stringer -i 7.out.go -o anames.go -p arm64
|
||||
// Do not edit.
|
||||
|
||||
package arm64
|
||||
|
||||
import "cmd/internal/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",
|
||||
"LDAR",
|
||||
"LDARB",
|
||||
"LDARH",
|
||||
"LDARW",
|
||||
"LDAXP",
|
||||
"LDAXPW",
|
||||
"LDAXR",
|
||||
"LDAXRB",
|
||||
"LDAXRH",
|
||||
"LDAXRW",
|
||||
"LDP",
|
||||
"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",
|
||||
"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",
|
||||
"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",
|
||||
"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",
|
||||
"FMOVD",
|
||||
"FMOVS",
|
||||
"FMULD",
|
||||
"FMULS",
|
||||
"FNEGD",
|
||||
"FNEGS",
|
||||
"FSQRTD",
|
||||
"FSQRTS",
|
||||
"FSUBD",
|
||||
"FSUBS",
|
||||
"SCVTFD",
|
||||
"SCVTFS",
|
||||
"SCVTFWD",
|
||||
"SCVTFWS",
|
||||
"UCVTFD",
|
||||
"UCVTFS",
|
||||
"UCVTFWD",
|
||||
"UCVTFWS",
|
||||
"HISTORY",
|
||||
"NAME",
|
||||
"WORD",
|
||||
"DYNT",
|
||||
"INIT",
|
||||
"BCASE",
|
||||
"CASE",
|
||||
"DWORD",
|
||||
"SIGNAME",
|
||||
"GOK",
|
||||
"END",
|
||||
"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",
|
||||
"LAST",
|
||||
}
|
62
src/cmd/internal/obj/arm64/anames7.go
Normal file
62
src/cmd/internal/obj/arm64/anames7.go
Normal file
|
@ -0,0 +1,62 @@
|
|||
package arm64
|
||||
|
||||
var cnames7 = []string{
|
||||
"NONE",
|
||||
"REG",
|
||||
"RSP",
|
||||
"FREG",
|
||||
"VREG",
|
||||
"PAIR",
|
||||
"SHIFT",
|
||||
"EXTREG",
|
||||
"SPR",
|
||||
"COND",
|
||||
"ZCON",
|
||||
"ADDCON0",
|
||||
"ADDCON",
|
||||
"MOVCON",
|
||||
"BITCON",
|
||||
"ABCON",
|
||||
"MBCON",
|
||||
"LCON",
|
||||
"VCON",
|
||||
"FCON",
|
||||
"VCONADDR",
|
||||
"AACON",
|
||||
"LACON",
|
||||
"AECON",
|
||||
"SBRA",
|
||||
"LBRA",
|
||||
"NPAUTO",
|
||||
"NSAUTO",
|
||||
"PSAUTO",
|
||||
"PPAUTO",
|
||||
"UAUTO4K",
|
||||
"UAUTO8K",
|
||||
"UAUTO16K",
|
||||
"UAUTO32K",
|
||||
"UAUTO64K",
|
||||
"LAUTO",
|
||||
"SEXT1",
|
||||
"SEXT2",
|
||||
"SEXT4",
|
||||
"SEXT8",
|
||||
"SEXT16",
|
||||
"LEXT",
|
||||
"ZOREG",
|
||||
"NPOREG",
|
||||
"NSOREG",
|
||||
"PSOREG",
|
||||
"PPOREG",
|
||||
"UOREG4K",
|
||||
"UOREG8K",
|
||||
"UOREG16K",
|
||||
"UOREG32K",
|
||||
"UOREG64K",
|
||||
"LOREG",
|
||||
"ADDR",
|
||||
"ROFF",
|
||||
"GOK",
|
||||
"TEXTSIZE",
|
||||
"NCLASS",
|
||||
}
|
4194
src/cmd/internal/obj/arm64/asm7.go
Normal file
4194
src/cmd/internal/obj/arm64/asm7.go
Normal file
File diff suppressed because it is too large
Load diff
114
src/cmd/internal/obj/arm64/list7.go
Normal file
114
src/cmd/internal/obj/arm64/list7.go
Normal file
|
@ -0,0 +1,114 @@
|
|||
// 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 (
|
||||
"cmd/internal/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)
|
||||
}
|
||||
|
||||
func Rconv(r int) string {
|
||||
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_F0)
|
||||
case COND_EQ <= r && r <= COND_NV:
|
||||
return strcond[r-COND_EQ]
|
||||
case r == REGSP:
|
||||
return "RSP"
|
||||
case r == REG_DAIF:
|
||||
return "DAIF"
|
||||
case r == REG_NZCV:
|
||||
return "NZCV"
|
||||
case r == REG_FPSR:
|
||||
return "FPSR"
|
||||
case r == REG_FPCR:
|
||||
return "FPCR"
|
||||
case r == REG_SPSR_EL1:
|
||||
return "SPSR_EL1"
|
||||
case r == REG_ELR_EL1:
|
||||
return "ELR_EL1"
|
||||
case r == REG_SPSR_EL2:
|
||||
return "SPSR_EL2"
|
||||
case r == REG_ELR_EL2:
|
||||
return "ELR_EL2"
|
||||
case r == REG_CurrentEL:
|
||||
return "CurrentEL"
|
||||
case r == REG_SP_EL0:
|
||||
return "SP_EL0"
|
||||
case r == REG_SPSel:
|
||||
return "SPSel"
|
||||
case r == REG_DAIFSet:
|
||||
return "DAIFSet"
|
||||
case r == REG_DAIFClr:
|
||||
return "DAIFClr"
|
||||
}
|
||||
return fmt.Sprintf("badreg(%d)", r)
|
||||
}
|
||||
|
||||
func DRconv(a int) string {
|
||||
if a >= C_NONE && a <= C_NCLASS {
|
||||
return cnames7[a]
|
||||
}
|
||||
return "C_??"
|
||||
}
|
829
src/cmd/internal/obj/arm64/obj7.go
Normal file
829
src/cmd/internal/obj/arm64/obj7.go
Normal file
|
@ -0,0 +1,829 @@
|
|||
// 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 (
|
||||
"cmd/internal/obj"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
)
|
||||
|
||||
var complements = []int16{
|
||||
AADD: ASUB,
|
||||
AADDW: ASUBW,
|
||||
ASUB: AADD,
|
||||
ASUBW: AADDW,
|
||||
ACMP: ACMN,
|
||||
ACMPW: ACMNW,
|
||||
ACMN: ACMP,
|
||||
ACMNW: ACMPW,
|
||||
}
|
||||
|
||||
func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32, noctxt int) *obj.Prog {
|
||||
// MOV g_stackguard(g), R1
|
||||
p = obj.Appendp(ctxt, p)
|
||||
|
||||
p.As = AMOVD
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = REGG
|
||||
p.From.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
|
||||
if ctxt.Cursym.Cfunc != 0 {
|
||||
p.From.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
|
||||
}
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R1
|
||||
|
||||
q := (*obj.Prog)(nil)
|
||||
if framesize <= obj.StackSmall {
|
||||
// small stack: SP < stackguard
|
||||
// MOV SP, R2
|
||||
// CMP stackguard, R2
|
||||
p = obj.Appendp(ctxt, p)
|
||||
|
||||
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(ctxt, p)
|
||||
p.As = ACMP
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_R1
|
||||
p.Reg = REG_R2
|
||||
} else if framesize <= obj.StackBig {
|
||||
// large stack: SP-framesize < stackguard-StackSmall
|
||||
// SUB $framesize, SP, R2
|
||||
// CMP stackguard, R2
|
||||
p = obj.Appendp(ctxt, p)
|
||||
|
||||
p.As = ASUB
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = int64(framesize)
|
||||
p.Reg = REGSP
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R2
|
||||
|
||||
p = obj.Appendp(ctxt, p)
|
||||
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(ctxt, p)
|
||||
|
||||
p.As = ACMP
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = obj.StackPreempt
|
||||
p.Reg = REG_R1
|
||||
|
||||
p = obj.Appendp(ctxt, p)
|
||||
q = p
|
||||
p.As = ABEQ
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
|
||||
p = obj.Appendp(ctxt, p)
|
||||
p.As = AADD
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = obj.StackGuard
|
||||
p.Reg = REGSP
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R2
|
||||
|
||||
p = obj.Appendp(ctxt, p)
|
||||
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(ctxt, p)
|
||||
p.As = AMOVD
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = int64(framesize) + (obj.StackGuard - obj.StackSmall)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R3
|
||||
|
||||
p = obj.Appendp(ctxt, p)
|
||||
p.As = ACMP
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_R3
|
||||
p.Reg = REG_R2
|
||||
}
|
||||
|
||||
// BHI done
|
||||
p = obj.Appendp(ctxt, p)
|
||||
q1 := p
|
||||
|
||||
p.As = ABHI
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
|
||||
// MOV LR, R3
|
||||
p = obj.Appendp(ctxt, p)
|
||||
|
||||
p.As = AMOVD
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REGLINK
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R3
|
||||
if q != nil {
|
||||
q.Pcond = p
|
||||
}
|
||||
|
||||
// TODO(minux): only for debug
|
||||
p = obj.Appendp(ctxt, p)
|
||||
p.As = AMOVD
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = int64(framesize)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGTMP
|
||||
|
||||
// BL runtime.morestack(SB)
|
||||
p = obj.Appendp(ctxt, p)
|
||||
|
||||
p.As = ABL
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
if ctxt.Cursym.Cfunc != 0 {
|
||||
p.To.Sym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
|
||||
} else {
|
||||
p.To.Sym = ctxt.Symmorestack[noctxt]
|
||||
}
|
||||
|
||||
// B start
|
||||
p = obj.Appendp(ctxt, p)
|
||||
|
||||
p.As = AB
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
p.Pcond = ctxt.Cursym.Text.Link
|
||||
|
||||
// placeholder for q1's jump target
|
||||
p = obj.Appendp(ctxt, p)
|
||||
|
||||
p.As = obj.ANOP
|
||||
q1.Pcond = p
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func progedit(ctxt *obj.Link, p *obj.Prog) {
|
||||
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 {
|
||||
f32 := float32(p.From.U.Dval)
|
||||
i32 := math.Float32bits(f32)
|
||||
literal := fmt.Sprintf("$f32.%08x", uint32(i32))
|
||||
s := obj.Linklookup(ctxt, literal, 0)
|
||||
s.Size = 4
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Sym = s
|
||||
p.From.Name = obj.NAME_EXTERN
|
||||
p.From.Offset = 0
|
||||
}
|
||||
|
||||
case AFMOVD:
|
||||
if p.From.Type == obj.TYPE_FCONST {
|
||||
i64 := math.Float64bits(p.From.U.Dval)
|
||||
literal := fmt.Sprintf("$f64.%016x", uint64(i64))
|
||||
s := obj.Linklookup(ctxt, literal, 0)
|
||||
s.Size = 8
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Sym = s
|
||||
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,
|
||||
AADDW,
|
||||
ASUB,
|
||||
ASUBW,
|
||||
ACMP,
|
||||
ACMPW,
|
||||
ACMN,
|
||||
ACMNW:
|
||||
if p.From.Type == obj.NAME_EXTERN && p.From.Offset < 0 {
|
||||
p.From.Offset = -p.From.Offset
|
||||
p.As = complements[p.As]
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func follow(ctxt *obj.Link, s *obj.LSym) {
|
||||
ctxt.Cursym = s
|
||||
|
||||
firstp := ctxt.NewProg()
|
||||
lastp := firstp
|
||||
xfol(ctxt, s.Text, &lastp)
|
||||
lastp.Link = nil
|
||||
s.Text = firstp.Link
|
||||
}
|
||||
|
||||
func relinv(a int) int {
|
||||
switch a {
|
||||
case ABEQ:
|
||||
return ABNE
|
||||
case ABNE:
|
||||
return ABEQ
|
||||
case ABCS:
|
||||
return ABCC
|
||||
case ABHS:
|
||||
return ABLO
|
||||
case ABCC:
|
||||
return ABCS
|
||||
case ABLO:
|
||||
return ABHS
|
||||
case ABMI:
|
||||
return ABPL
|
||||
case ABPL:
|
||||
return ABMI
|
||||
case ABVS:
|
||||
return ABVC
|
||||
case ABVC:
|
||||
return ABVS
|
||||
case ABHI:
|
||||
return ABLS
|
||||
case ABLS:
|
||||
return ABHI
|
||||
case ABGE:
|
||||
return ABLT
|
||||
case ABLT:
|
||||
return ABGE
|
||||
case ABGT:
|
||||
return ABLE
|
||||
case ABLE:
|
||||
return ABGT
|
||||
}
|
||||
|
||||
log.Fatalf("unknown relation: %s", Anames[a])
|
||||
return 0
|
||||
}
|
||||
|
||||
func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
|
||||
var q *obj.Prog
|
||||
var r *obj.Prog
|
||||
var a int
|
||||
var i int
|
||||
|
||||
loop:
|
||||
if p == nil {
|
||||
return
|
||||
}
|
||||
a = int(p.As)
|
||||
if a == AB {
|
||||
q = p.Pcond
|
||||
if q != nil {
|
||||
p.Mark |= FOLL
|
||||
p = q
|
||||
if !(p.Mark&FOLL != 0) {
|
||||
goto loop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if p.Mark&FOLL != 0 {
|
||||
i = 0
|
||||
q = p
|
||||
for ; i < 4; (func() { i++; q = q.Link })() {
|
||||
if q == *last || q == nil {
|
||||
break
|
||||
}
|
||||
a = int(q.As)
|
||||
if a == obj.ANOP {
|
||||
i--
|
||||
continue
|
||||
}
|
||||
|
||||
if a == AB || a == obj.ARET || a == AERET {
|
||||
goto copy
|
||||
}
|
||||
if q.Pcond == nil || (q.Pcond.Mark&FOLL != 0) {
|
||||
continue
|
||||
}
|
||||
if a != ABEQ && a != ABNE {
|
||||
continue
|
||||
}
|
||||
|
||||
copy:
|
||||
for {
|
||||
r = ctxt.NewProg()
|
||||
*r = *p
|
||||
if !(r.Mark&FOLL != 0) {
|
||||
fmt.Printf("cant happen 1\n")
|
||||
}
|
||||
r.Mark |= FOLL
|
||||
if p != q {
|
||||
p = p.Link
|
||||
(*last).Link = r
|
||||
*last = r
|
||||
continue
|
||||
}
|
||||
|
||||
(*last).Link = r
|
||||
*last = r
|
||||
if a == AB || a == obj.ARET || a == AERET {
|
||||
return
|
||||
}
|
||||
if a == ABNE {
|
||||
r.As = ABEQ
|
||||
} else {
|
||||
r.As = ABNE
|
||||
}
|
||||
r.Pcond = p.Link
|
||||
r.Link = p.Pcond
|
||||
if !(r.Link.Mark&FOLL != 0) {
|
||||
xfol(ctxt, r.Link, last)
|
||||
}
|
||||
if !(r.Pcond.Mark&FOLL != 0) {
|
||||
fmt.Printf("cant happen 2\n")
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
a = AB
|
||||
q = ctxt.NewProg()
|
||||
q.As = int16(a)
|
||||
q.Lineno = p.Lineno
|
||||
q.To.Type = obj.TYPE_BRANCH
|
||||
q.To.Offset = p.Pc
|
||||
q.Pcond = p
|
||||
p = q
|
||||
}
|
||||
|
||||
p.Mark |= FOLL
|
||||
(*last).Link = p
|
||||
*last = p
|
||||
if a == AB || a == obj.ARET || a == AERET {
|
||||
return
|
||||
}
|
||||
if p.Pcond != nil {
|
||||
if a != ABL && p.Link != nil {
|
||||
q = obj.Brchain(ctxt, p.Link)
|
||||
if a != obj.ATEXT && a != ABCASE {
|
||||
if q != nil && (q.Mark&FOLL != 0) {
|
||||
p.As = int16(relinv(a))
|
||||
p.Link = p.Pcond
|
||||
p.Pcond = q
|
||||
}
|
||||
}
|
||||
|
||||
xfol(ctxt, p.Link, last)
|
||||
q = obj.Brchain(ctxt, p.Pcond)
|
||||
if q == nil {
|
||||
q = p.Pcond
|
||||
}
|
||||
if q.Mark&FOLL != 0 {
|
||||
p.Pcond = q
|
||||
return
|
||||
}
|
||||
|
||||
p = q
|
||||
goto loop
|
||||
}
|
||||
}
|
||||
|
||||
p = p.Link
|
||||
goto loop
|
||||
}
|
||||
|
||||
func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
|
||||
if ctxt.Symmorestack[0] == nil {
|
||||
ctxt.Symmorestack[0] = obj.Linklookup(ctxt, "runtime.morestack", 0)
|
||||
ctxt.Symmorestack[1] = obj.Linklookup(ctxt, "runtime.morestack_noctxt", 0)
|
||||
}
|
||||
|
||||
ctxt.Cursym = cursym
|
||||
|
||||
if cursym.Text == nil || cursym.Text.Link == nil {
|
||||
return
|
||||
}
|
||||
|
||||
p := cursym.Text
|
||||
textstksiz := p.To.Offset
|
||||
aoffset := int32(textstksiz)
|
||||
|
||||
cursym.Args = p.To.U.Argsize
|
||||
cursym.Locals = int32(textstksiz)
|
||||
|
||||
/*
|
||||
* find leaf subroutines
|
||||
* strip NOPs
|
||||
* expand RET
|
||||
*/
|
||||
obj.Bflush(ctxt.Bso)
|
||||
q := (*obj.Prog)(nil)
|
||||
var q1 *obj.Prog
|
||||
for p := cursym.Text; p != nil; p = p.Link {
|
||||
switch p.As {
|
||||
case obj.ATEXT:
|
||||
p.Mark |= LEAF
|
||||
|
||||
case obj.ARET:
|
||||
break
|
||||
|
||||
case obj.ANOP:
|
||||
q1 = p.Link
|
||||
q.Link = q1 /* q is non-nop */
|
||||
q1.Mark |= p.Mark
|
||||
continue
|
||||
|
||||
case ABL,
|
||||
obj.ADUFFZERO,
|
||||
obj.ADUFFCOPY:
|
||||
cursym.Text.Mark &^= LEAF
|
||||
fallthrough
|
||||
|
||||
case ACBNZ,
|
||||
ACBZ,
|
||||
ACBNZW,
|
||||
ACBZW,
|
||||
ATBZ,
|
||||
ATBNZ,
|
||||
ABCASE,
|
||||
AB,
|
||||
ABEQ,
|
||||
ABNE,
|
||||
ABCS,
|
||||
ABHS,
|
||||
ABCC,
|
||||
ABLO,
|
||||
ABMI,
|
||||
ABPL,
|
||||
ABVS,
|
||||
ABVC,
|
||||
ABHI,
|
||||
ABLS,
|
||||
ABGE,
|
||||
ABLT,
|
||||
ABGT,
|
||||
ABLE,
|
||||
AADR, /* strange */
|
||||
AADRP:
|
||||
q1 = p.Pcond
|
||||
|
||||
if q1 != nil {
|
||||
for q1.As == obj.ANOP {
|
||||
q1 = q1.Link
|
||||
p.Pcond = q1
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
q = p
|
||||
}
|
||||
|
||||
var o int
|
||||
var q2 *obj.Prog
|
||||
var retjmp *obj.LSym
|
||||
var stkadj int64
|
||||
for p := cursym.Text; p != nil; p = p.Link {
|
||||
o = int(p.As)
|
||||
switch o {
|
||||
case obj.ATEXT:
|
||||
cursym.Text = p
|
||||
if textstksiz < 0 {
|
||||
ctxt.Autosize = 0
|
||||
} else {
|
||||
ctxt.Autosize = int32(textstksiz + 8)
|
||||
}
|
||||
if (cursym.Text.Mark&LEAF != 0) && ctxt.Autosize <= 8 {
|
||||
ctxt.Autosize = 0
|
||||
} else if ctxt.Autosize&(16-1) != 0 {
|
||||
stkadj = 16 - (int64(ctxt.Autosize) & (16 - 1))
|
||||
ctxt.Autosize += int32(stkadj)
|
||||
cursym.Locals += int32(stkadj)
|
||||
}
|
||||
p.To.Offset = int64(ctxt.Autosize) - 8
|
||||
if ctxt.Autosize == 0 && !(cursym.Text.Mark&LEAF != 0) {
|
||||
if ctxt.Debugvlog != 0 {
|
||||
fmt.Fprintf(ctxt.Bso, "save suppressed in: %s\n", cursym.Text.From.Sym.Name)
|
||||
}
|
||||
obj.Bflush(ctxt.Bso)
|
||||
cursym.Text.Mark |= LEAF
|
||||
}
|
||||
|
||||
if !(p.From3.Offset&obj.NOSPLIT != 0) {
|
||||
p = stacksplit(ctxt, p, ctxt.Autosize, bool2int(cursym.Text.From3.Offset&obj.NEEDCTXT == 0)) // emit split check
|
||||
}
|
||||
|
||||
aoffset = ctxt.Autosize
|
||||
if aoffset > 0xF0 {
|
||||
aoffset = 0xF0
|
||||
}
|
||||
if cursym.Text.Mark&LEAF != 0 {
|
||||
cursym.Leaf = 1
|
||||
if ctxt.Autosize == 0 {
|
||||
break
|
||||
}
|
||||
aoffset = 0
|
||||
}
|
||||
|
||||
q = p
|
||||
if ctxt.Autosize > aoffset {
|
||||
q = ctxt.NewProg()
|
||||
q.As = ASUB
|
||||
q.Lineno = p.Lineno
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = int64(ctxt.Autosize) - int64(aoffset)
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REGSP
|
||||
q.Spadj = int32(q.From.Offset)
|
||||
q.Link = p.Link
|
||||
p.Link = q
|
||||
if cursym.Text.Mark&LEAF != 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
q1 = ctxt.NewProg()
|
||||
q1.As = AMOVD
|
||||
q1.Lineno = p.Lineno
|
||||
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.Link = q.Link
|
||||
q1.Spadj = aoffset
|
||||
q.Link = q1
|
||||
|
||||
if cursym.Text.From3.Offset&obj.WRAPPER != 0 {
|
||||
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
|
||||
//
|
||||
// MOV g_panic(g), R1
|
||||
// CMP ZR, R1
|
||||
// BEQ end
|
||||
// MOV panic_argp(R1), R2
|
||||
// ADD $(autosize+8), RSP, R3
|
||||
// CMP R2, R3
|
||||
// BNE end
|
||||
// ADD $8, RSP, R4
|
||||
// MOVD R4, panic_argp(R1)
|
||||
// end:
|
||||
// NOP
|
||||
//
|
||||
// The NOP is needed to give the jumps somewhere to land.
|
||||
// It is a liblink NOP, not a ARM64 NOP: it encodes to 0 instruction bytes.
|
||||
q = q1
|
||||
|
||||
q = obj.Appendp(ctxt, q)
|
||||
q.As = AMOVD
|
||||
q.From.Type = obj.TYPE_MEM
|
||||
q.From.Reg = REGG
|
||||
q.From.Offset = 4 * int64(ctxt.Arch.Ptrsize) // G.panic
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REG_R1
|
||||
|
||||
q = obj.Appendp(ctxt, q)
|
||||
q.As = ACMP
|
||||
q.From.Type = obj.TYPE_REG
|
||||
q.From.Reg = REGZERO
|
||||
q.Reg = REG_R1
|
||||
|
||||
q = obj.Appendp(ctxt, q)
|
||||
q.As = ABEQ
|
||||
q.To.Type = obj.TYPE_BRANCH
|
||||
q1 = q
|
||||
|
||||
q = obj.Appendp(ctxt, q)
|
||||
q.As = AMOVD
|
||||
q.From.Type = obj.TYPE_MEM
|
||||
q.From.Reg = REG_R1
|
||||
q.From.Offset = 0 // Panic.argp
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REG_R2
|
||||
|
||||
q = obj.Appendp(ctxt, q)
|
||||
q.As = AADD
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = int64(ctxt.Autosize) + 8
|
||||
q.Reg = REGSP
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REG_R3
|
||||
|
||||
q = obj.Appendp(ctxt, q)
|
||||
q.As = ACMP
|
||||
q.From.Type = obj.TYPE_REG
|
||||
q.From.Reg = REG_R2
|
||||
q.Reg = REG_R3
|
||||
|
||||
q = obj.Appendp(ctxt, q)
|
||||
q.As = ABNE
|
||||
q.To.Type = obj.TYPE_BRANCH
|
||||
q2 = q
|
||||
|
||||
q = obj.Appendp(ctxt, q)
|
||||
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
|
||||
|
||||
q = obj.Appendp(ctxt, q)
|
||||
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
|
||||
|
||||
q = obj.Appendp(ctxt, q)
|
||||
|
||||
q.As = obj.ANOP
|
||||
q1.Pcond = q
|
||||
q2.Pcond = q
|
||||
}
|
||||
|
||||
case obj.ARET:
|
||||
nocache(p)
|
||||
if p.From.Type == obj.TYPE_CONST {
|
||||
ctxt.Diag("using BECOME (%v) is not supported!", p)
|
||||
break
|
||||
}
|
||||
|
||||
retjmp = p.To.Sym
|
||||
p.To = obj.Addr{}
|
||||
if cursym.Text.Mark&LEAF != 0 {
|
||||
if ctxt.Autosize != 0 {
|
||||
p.As = AADD
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = int64(ctxt.Autosize)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGSP
|
||||
p.Spadj = -ctxt.Autosize
|
||||
}
|
||||
} else {
|
||||
/* want write-back pre-indexed SP+autosize -> SP, loading REGLINK*/
|
||||
aoffset = ctxt.Autosize
|
||||
|
||||
if aoffset > 0xF0 {
|
||||
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
|
||||
if ctxt.Autosize > aoffset {
|
||||
q = ctxt.NewProg()
|
||||
q.As = AADD
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = int64(ctxt.Autosize) - int64(aoffset)
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REGSP
|
||||
q.Link = p.Link
|
||||
q.Spadj = int32(-q.From.Offset)
|
||||
q.Lineno = p.Lineno
|
||||
p.Link = q
|
||||
p = q
|
||||
}
|
||||
}
|
||||
|
||||
if p.As != obj.ARET {
|
||||
q = ctxt.NewProg()
|
||||
q.Lineno = p.Lineno
|
||||
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 = +ctxt.Autosize
|
||||
break
|
||||
}
|
||||
|
||||
p.As = obj.ARET
|
||||
p.Lineno = p.Lineno
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Offset = 0
|
||||
p.To.Reg = REGLINK
|
||||
p.Spadj = +ctxt.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)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func nocache(p *obj.Prog) {
|
||||
p.Optab = 0
|
||||
p.From.Class = 0
|
||||
p.To.Class = 0
|
||||
}
|
||||
|
||||
var unaryDst = map[int]bool{
|
||||
AWORD: true,
|
||||
ADWORD: true,
|
||||
ABL: true,
|
||||
AB: true,
|
||||
}
|
||||
|
||||
var Linkarm64 = obj.LinkArch{
|
||||
ByteOrder: binary.LittleEndian,
|
||||
Name: "arm64",
|
||||
Thechar: '7',
|
||||
Preprocess: preprocess,
|
||||
Assemble: span7,
|
||||
Follow: follow,
|
||||
Progedit: progedit,
|
||||
UnaryDst: unaryDst,
|
||||
Minlc: 4,
|
||||
Ptrsize: 8,
|
||||
Regsize: 8,
|
||||
}
|
12
src/cmd/internal/obj/arm64/util.go
Normal file
12
src/cmd/internal/obj/arm64/util.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
// 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
|
||||
|
||||
func bool2int(b bool) int {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
|
@ -66,6 +66,7 @@ type Prog struct {
|
|||
Reg int16
|
||||
From3 Addr
|
||||
To Addr
|
||||
To2 Addr
|
||||
Opt interface{}
|
||||
Forwd *Prog
|
||||
Pcond *Prog
|
||||
|
@ -505,6 +506,7 @@ const (
|
|||
R_SIZE
|
||||
R_CALL
|
||||
R_CALLARM
|
||||
R_CALLARM64
|
||||
R_CALLIND
|
||||
R_CALLPOWER
|
||||
R_CONST
|
||||
|
|
|
@ -332,6 +332,9 @@ func (p *Prog) String() string {
|
|||
if p.To.Type != TYPE_NONE {
|
||||
fmt.Fprintf(&buf, "%s%v", sep, Dconv(p, &p.To))
|
||||
}
|
||||
if p.To2.Type != TYPE_NONE {
|
||||
fmt.Fprintf(&buf, "%s%v", sep, Dconv(p, &p.To2))
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
|
@ -523,10 +526,8 @@ const (
|
|||
RBase386 = 1 * 1024
|
||||
RBaseAMD64 = 2 * 1024
|
||||
RBaseARM = 3 * 1024
|
||||
RBasePPC64 = 4 * 1024
|
||||
// The next free base is 8*1024 (PPC64 has many registers).
|
||||
// Alternatively, the next architecture, with an ordinary
|
||||
// number of registers, could go under PPC64.
|
||||
RBasePPC64 = 4 * 1024 // range [4k, 8k)
|
||||
RBaseARM64 = 8 * 1024 // range [8k, 12k)
|
||||
)
|
||||
|
||||
// RegisterRegister binds a pretty-printer (Rconv) for register
|
||||
|
@ -585,6 +586,7 @@ const (
|
|||
ABaseARM
|
||||
ABaseAMD64
|
||||
ABasePPC64
|
||||
ABaseARM64
|
||||
AMask = 1<<12 - 1 // AND with this to use the opcode as an array index.
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in a new issue