mirror of
https://github.com/golang/go.git
synced 2025-05-28 19:02:22 +00:00
cmd/internal/obj{,/loong64}: instructions and registers for loong64
Implemented an assembler for LoongArch64(loong64 is short name) - this provides register definitions and instruction encoding as defined in the LoongArch Instruction Set Manual. LoongArch Instruction Set Manual: https://github.com/loongson/LoongArch-Documentation/releases Contributors to the linux/loong64 port are: Weining Lu <luweining@loongson.cn> Lei Wang <wanglei@loongson.cn> Lingqin Gong <gonglingqin@loongson.cn> Xiaolin Zhao <zhaoxiaolin@loongson.cn> Meidan Li <limeidan@loongson.cn> Xiaojuan Zhai <zhaixiaojuan@loongson.cn> Qiyuan Pu <puqiyuan@loongson.cn> Guoqi Chen <chenguoqi@loongson.cn> This port has been updated to Go 1.15.6: https://github.com/loongson/go Updates #46229 Change-Id: I930d2a19246496e3ca36d55539183c0f9f650ad9 Reviewed-on: https://go-review.googlesource.com/c/go/+/342309 Reviewed-by: David Chase <drchase@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@google.com> Run-TryBot: Ian Lance Taylor <iant@google.com>
This commit is contained in:
parent
857cda4625
commit
c1105cfd43
@ -442,6 +442,7 @@ const (
|
||||
ABasePPC64
|
||||
ABaseARM64
|
||||
ABaseMIPS
|
||||
ABaseLoong64
|
||||
ABaseRISCV
|
||||
ABaseS390X
|
||||
ABaseWasm
|
||||
|
414
src/cmd/internal/obj/loong64/a.out.go
Normal file
414
src/cmd/internal/obj/loong64/a.out.go
Normal file
@ -0,0 +1,414 @@
|
||||
// Copyright 2022 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 loong64
|
||||
|
||||
import (
|
||||
"cmd/internal/obj"
|
||||
)
|
||||
|
||||
//go:generate go run ../stringer.go -i $GOFILE -o anames.go -p loong64
|
||||
|
||||
const (
|
||||
NSNAME = 8
|
||||
NSYM = 50
|
||||
NREG = 32 // number of general registers
|
||||
NFREG = 32 // number of floating point registers
|
||||
)
|
||||
|
||||
const (
|
||||
REG_R0 = obj.RBaseLOONG64 + iota // must be a multiple of 32
|
||||
REG_R1
|
||||
REG_R2
|
||||
REG_R3
|
||||
REG_R4
|
||||
REG_R5
|
||||
REG_R6
|
||||
REG_R7
|
||||
REG_R8
|
||||
REG_R9
|
||||
REG_R10
|
||||
REG_R11
|
||||
REG_R12
|
||||
REG_R13
|
||||
REG_R14
|
||||
REG_R15
|
||||
REG_R16
|
||||
REG_R17
|
||||
REG_R18
|
||||
REG_R19
|
||||
REG_R20
|
||||
REG_R21
|
||||
REG_R22
|
||||
REG_R23
|
||||
REG_R24
|
||||
REG_R25
|
||||
REG_R26
|
||||
REG_R27
|
||||
REG_R28
|
||||
REG_R29
|
||||
REG_R30
|
||||
REG_R31
|
||||
|
||||
REG_F0 // must be a multiple of 32
|
||||
REG_F1
|
||||
REG_F2
|
||||
REG_F3
|
||||
REG_F4
|
||||
REG_F5
|
||||
REG_F6
|
||||
REG_F7
|
||||
REG_F8
|
||||
REG_F9
|
||||
REG_F10
|
||||
REG_F11
|
||||
REG_F12
|
||||
REG_F13
|
||||
REG_F14
|
||||
REG_F15
|
||||
REG_F16
|
||||
REG_F17
|
||||
REG_F18
|
||||
REG_F19
|
||||
REG_F20
|
||||
REG_F21
|
||||
REG_F22
|
||||
REG_F23
|
||||
REG_F24
|
||||
REG_F25
|
||||
REG_F26
|
||||
REG_F27
|
||||
REG_F28
|
||||
REG_F29
|
||||
REG_F30
|
||||
REG_F31
|
||||
|
||||
REG_FCSR0 // must be a multiple of 32
|
||||
REG_FCSR1
|
||||
REG_FCSR2
|
||||
REG_FCSR3 // only four registers are needed
|
||||
REG_FCSR4
|
||||
REG_FCSR5
|
||||
REG_FCSR6
|
||||
REG_FCSR7
|
||||
REG_FCSR8
|
||||
REG_FCSR9
|
||||
REG_FCSR10
|
||||
REG_FCSR11
|
||||
REG_FCSR12
|
||||
REG_FCSR13
|
||||
REG_FCSR14
|
||||
REG_FCSR15
|
||||
REG_FCSR16
|
||||
REG_FCSR17
|
||||
REG_FCSR18
|
||||
REG_FCSR19
|
||||
REG_FCSR20
|
||||
REG_FCSR21
|
||||
REG_FCSR22
|
||||
REG_FCSR23
|
||||
REG_FCSR24
|
||||
REG_FCSR25
|
||||
REG_FCSR26
|
||||
REG_FCSR27
|
||||
REG_FCSR28
|
||||
REG_FCSR29
|
||||
REG_FCSR30
|
||||
REG_FCSR31
|
||||
|
||||
REG_FCC0 // must be a multiple of 32
|
||||
REG_FCC1
|
||||
REG_FCC2
|
||||
REG_FCC3
|
||||
REG_FCC4
|
||||
REG_FCC5
|
||||
REG_FCC6
|
||||
REG_FCC7 // only eight registers are needed
|
||||
REG_FCC8
|
||||
REG_FCC9
|
||||
REG_FCC10
|
||||
REG_FCC11
|
||||
REG_FCC12
|
||||
REG_FCC13
|
||||
REG_FCC14
|
||||
REG_FCC15
|
||||
REG_FCC16
|
||||
REG_FCC17
|
||||
REG_FCC18
|
||||
REG_FCC19
|
||||
REG_FCC20
|
||||
REG_FCC21
|
||||
REG_FCC22
|
||||
REG_FCC23
|
||||
REG_FCC24
|
||||
REG_FCC25
|
||||
REG_FCC26
|
||||
REG_FCC27
|
||||
REG_FCC28
|
||||
REG_FCC29
|
||||
REG_FCC30
|
||||
REG_FCC31
|
||||
|
||||
REG_LAST = REG_FCC31 // the last defined register
|
||||
|
||||
REG_SPECIAL = REG_FCSR0
|
||||
|
||||
REGZERO = REG_R0 // set to zero
|
||||
REGLINK = REG_R1
|
||||
REGSP = REG_R3
|
||||
REGRET = REG_R19
|
||||
REGARG = -1 // -1 disables passing the first argument in register
|
||||
REGRT1 = REG_R19 // reserved for runtime, duffzero and duffcopy
|
||||
REGRT2 = REG_R20 // reserved for runtime, duffcopy
|
||||
REGCTXT = REG_R29 // context for closures
|
||||
REGG = REG_R22 // G in loong64
|
||||
REGTMP = REG_R30 // used by the assembler
|
||||
FREGRET = REG_F0
|
||||
)
|
||||
|
||||
var LOONG64DWARFRegisters = map[int16]int16{}
|
||||
|
||||
func init() {
|
||||
// f assigns dwarfregisters[from:to] = (base):(to-from+base)
|
||||
f := func(from, to, base int16) {
|
||||
for r := int16(from); r <= to; r++ {
|
||||
LOONG64DWARFRegisters[r] = (r - from) + base
|
||||
}
|
||||
}
|
||||
f(REG_R0, REG_R31, 0)
|
||||
f(REG_F0, REG_F31, 32)
|
||||
|
||||
}
|
||||
|
||||
const (
|
||||
BIG = 2046
|
||||
)
|
||||
|
||||
const (
|
||||
// mark flags
|
||||
LABEL = 1 << 0
|
||||
LEAF = 1 << 1
|
||||
SYNC = 1 << 2
|
||||
BRANCH = 1 << 3
|
||||
)
|
||||
|
||||
const (
|
||||
C_NONE = iota
|
||||
C_REG
|
||||
C_FREG
|
||||
C_FCSRREG
|
||||
C_FCCREG
|
||||
C_ZCON
|
||||
C_SCON // 12 bit signed
|
||||
C_UCON // 32 bit signed, low 12 bits 0
|
||||
C_ADD0CON
|
||||
C_AND0CON
|
||||
C_ADDCON // -0x800 <= v < 0
|
||||
C_ANDCON // 0 < v <= 0xFFF
|
||||
C_LCON // other 32
|
||||
C_DCON // other 64 (could subdivide further)
|
||||
C_SACON // $n(REG) where n <= int12
|
||||
C_SECON
|
||||
C_LACON // $n(REG) where int12 < n <= int32
|
||||
C_LECON
|
||||
C_DACON // $n(REG) where int32 < n
|
||||
C_STCON // $tlsvar
|
||||
C_SBRA
|
||||
C_LBRA
|
||||
C_SAUTO
|
||||
C_LAUTO
|
||||
C_SEXT
|
||||
C_LEXT
|
||||
C_ZOREG
|
||||
C_SOREG
|
||||
C_LOREG
|
||||
C_GOK
|
||||
C_ADDR
|
||||
C_TLS
|
||||
C_TEXTSIZE
|
||||
|
||||
C_NCLASS // must be the last
|
||||
)
|
||||
|
||||
const (
|
||||
AABSD = obj.ABaseLoong64 + obj.A_ARCHSPECIFIC + iota
|
||||
AABSF
|
||||
AADD
|
||||
AADDD
|
||||
AADDF
|
||||
AADDU
|
||||
|
||||
AADDW
|
||||
AAND
|
||||
ABEQ
|
||||
ABGEZ
|
||||
ABLEZ
|
||||
ABGTZ
|
||||
ABLTZ
|
||||
ABFPF
|
||||
ABFPT
|
||||
|
||||
ABNE
|
||||
ABREAK
|
||||
ACLO
|
||||
ACLZ
|
||||
|
||||
ACMPEQD
|
||||
ACMPEQF
|
||||
|
||||
ACMPGED // ACMPGED -> fcmp.sle.d
|
||||
ACMPGEF // ACMPGEF -> fcmp.sle.s
|
||||
ACMPGTD // ACMPGTD -> fcmp.slt.d
|
||||
ACMPGTF // ACMPGTF -> fcmp.slt.s
|
||||
|
||||
ALU12IW
|
||||
ALU32ID
|
||||
ALU52ID
|
||||
APCADDU12I
|
||||
AJIRL
|
||||
ABGE
|
||||
ABLT
|
||||
ABLTU
|
||||
ABGEU
|
||||
|
||||
ADIV
|
||||
ADIVD
|
||||
ADIVF
|
||||
ADIVU
|
||||
ADIVW
|
||||
|
||||
ALL
|
||||
ALLV
|
||||
|
||||
ALUI
|
||||
|
||||
AMOVB
|
||||
AMOVBU
|
||||
|
||||
AMOVD
|
||||
AMOVDF
|
||||
AMOVDW
|
||||
AMOVF
|
||||
AMOVFD
|
||||
AMOVFW
|
||||
|
||||
AMOVH
|
||||
AMOVHU
|
||||
AMOVW
|
||||
|
||||
AMOVWD
|
||||
AMOVWF
|
||||
|
||||
AMOVWL
|
||||
AMOVWR
|
||||
|
||||
AMUL
|
||||
AMULD
|
||||
AMULF
|
||||
AMULU
|
||||
AMULH
|
||||
AMULHU
|
||||
AMULW
|
||||
ANEGD
|
||||
ANEGF
|
||||
|
||||
ANEGW
|
||||
ANEGV
|
||||
|
||||
ANOOP // hardware nop
|
||||
ANOR
|
||||
AOR
|
||||
AREM
|
||||
AREMU
|
||||
|
||||
ARFE
|
||||
|
||||
ASC
|
||||
ASCV
|
||||
|
||||
ASGT
|
||||
ASGTU
|
||||
|
||||
ASLL
|
||||
ASQRTD
|
||||
ASQRTF
|
||||
ASRA
|
||||
ASRL
|
||||
ASUB
|
||||
ASUBD
|
||||
ASUBF
|
||||
|
||||
ASUBU
|
||||
ASUBW
|
||||
ADBAR
|
||||
ASYSCALL
|
||||
|
||||
ATEQ
|
||||
ATNE
|
||||
|
||||
AWORD
|
||||
|
||||
AXOR
|
||||
|
||||
// 64-bit
|
||||
AMOVV
|
||||
AMOVVL
|
||||
AMOVVR
|
||||
|
||||
ASLLV
|
||||
ASRAV
|
||||
ASRLV
|
||||
ADIVV
|
||||
ADIVVU
|
||||
|
||||
AREMV
|
||||
AREMVU
|
||||
|
||||
AMULV
|
||||
AMULVU
|
||||
AMULHV
|
||||
AMULHVU
|
||||
AADDV
|
||||
AADDVU
|
||||
ASUBV
|
||||
ASUBVU
|
||||
|
||||
// 64-bit FP
|
||||
ATRUNCFV
|
||||
ATRUNCDV
|
||||
ATRUNCFW
|
||||
ATRUNCDW
|
||||
|
||||
AMOVWU
|
||||
AMOVFV
|
||||
AMOVDV
|
||||
AMOVVF
|
||||
AMOVVD
|
||||
|
||||
ALAST
|
||||
|
||||
// aliases
|
||||
AJMP = obj.AJMP
|
||||
AJAL = obj.ACALL
|
||||
ARET = obj.ARET
|
||||
)
|
||||
|
||||
func init() {
|
||||
// The asm encoder generally assumes that the lowest 5 bits of the
|
||||
// REG_XX constants match the machine instruction encoding, i.e.
|
||||
// the lowest 5 bits is the register number.
|
||||
// Check this here.
|
||||
if REG_R0%32 != 0 {
|
||||
panic("REG_R0 is not a multiple of 32")
|
||||
}
|
||||
if REG_F0%32 != 0 {
|
||||
panic("REG_F0 is not a multiple of 32")
|
||||
}
|
||||
if REG_FCSR0%32 != 0 {
|
||||
panic("REG_FCSR0 is not a multiple of 32")
|
||||
}
|
||||
if REG_FCC0%32 != 0 {
|
||||
panic("REG_FCC0 is not a multiple of 32")
|
||||
}
|
||||
}
|
130
src/cmd/internal/obj/loong64/anames.go
Normal file
130
src/cmd/internal/obj/loong64/anames.go
Normal file
@ -0,0 +1,130 @@
|
||||
// Code generated by stringer -i a.out.go -o anames.go -p loong64; DO NOT EDIT.
|
||||
|
||||
package loong64
|
||||
|
||||
import "cmd/internal/obj"
|
||||
|
||||
var Anames = []string{
|
||||
obj.A_ARCHSPECIFIC: "ABSD",
|
||||
"ABSF",
|
||||
"ADD",
|
||||
"ADDD",
|
||||
"ADDF",
|
||||
"ADDU",
|
||||
"ADDW",
|
||||
"AND",
|
||||
"BEQ",
|
||||
"BGEZ",
|
||||
"BLEZ",
|
||||
"BGTZ",
|
||||
"BLTZ",
|
||||
"BFPF",
|
||||
"BFPT",
|
||||
"BNE",
|
||||
"BREAK",
|
||||
"CLO",
|
||||
"CLZ",
|
||||
"CMPEQD",
|
||||
"CMPEQF",
|
||||
"CMPGED",
|
||||
"CMPGEF",
|
||||
"CMPGTD",
|
||||
"CMPGTF",
|
||||
"LU12IW",
|
||||
"LU32ID",
|
||||
"LU52ID",
|
||||
"PCADDU12I",
|
||||
"JIRL",
|
||||
"BGE",
|
||||
"BLT",
|
||||
"BLTU",
|
||||
"BGEU",
|
||||
"DIV",
|
||||
"DIVD",
|
||||
"DIVF",
|
||||
"DIVU",
|
||||
"DIVW",
|
||||
"LL",
|
||||
"LLV",
|
||||
"LUI",
|
||||
"MOVB",
|
||||
"MOVBU",
|
||||
"MOVD",
|
||||
"MOVDF",
|
||||
"MOVDW",
|
||||
"MOVF",
|
||||
"MOVFD",
|
||||
"MOVFW",
|
||||
"MOVH",
|
||||
"MOVHU",
|
||||
"MOVW",
|
||||
"MOVWD",
|
||||
"MOVWF",
|
||||
"MOVWL",
|
||||
"MOVWR",
|
||||
"MUL",
|
||||
"MULD",
|
||||
"MULF",
|
||||
"MULU",
|
||||
"MULH",
|
||||
"MULHU",
|
||||
"MULW",
|
||||
"NEGD",
|
||||
"NEGF",
|
||||
"NEGW",
|
||||
"NEGV",
|
||||
"NOOP",
|
||||
"NOR",
|
||||
"OR",
|
||||
"REM",
|
||||
"REMU",
|
||||
"RFE",
|
||||
"SC",
|
||||
"SCV",
|
||||
"SGT",
|
||||
"SGTU",
|
||||
"SLL",
|
||||
"SQRTD",
|
||||
"SQRTF",
|
||||
"SRA",
|
||||
"SRL",
|
||||
"SUB",
|
||||
"SUBD",
|
||||
"SUBF",
|
||||
"SUBU",
|
||||
"SUBW",
|
||||
"DBAR",
|
||||
"SYSCALL",
|
||||
"TEQ",
|
||||
"TNE",
|
||||
"WORD",
|
||||
"XOR",
|
||||
"MOVV",
|
||||
"MOVVL",
|
||||
"MOVVR",
|
||||
"SLLV",
|
||||
"SRAV",
|
||||
"SRLV",
|
||||
"DIVV",
|
||||
"DIVVU",
|
||||
"REMV",
|
||||
"REMVU",
|
||||
"MULV",
|
||||
"MULVU",
|
||||
"MULHV",
|
||||
"MULHVU",
|
||||
"ADDV",
|
||||
"ADDVU",
|
||||
"SUBV",
|
||||
"SUBVU",
|
||||
"TRUNCFV",
|
||||
"TRUNCDV",
|
||||
"TRUNCFW",
|
||||
"TRUNCDW",
|
||||
"MOVWU",
|
||||
"MOVFV",
|
||||
"MOVDV",
|
||||
"MOVVF",
|
||||
"MOVVD",
|
||||
"LAST",
|
||||
}
|
1960
src/cmd/internal/obj/loong64/asm.go
Normal file
1960
src/cmd/internal/obj/loong64/asm.go
Normal file
File diff suppressed because it is too large
Load Diff
43
src/cmd/internal/obj/loong64/cnames.go
Normal file
43
src/cmd/internal/obj/loong64/cnames.go
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2022 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 loong64
|
||||
|
||||
var cnames0 = []string{
|
||||
"NONE",
|
||||
"REG",
|
||||
"FREG",
|
||||
"FCREG",
|
||||
"FCSRREG",
|
||||
"FCCREG",
|
||||
"ZCON",
|
||||
"SCON",
|
||||
"UCON",
|
||||
"ADD0CON",
|
||||
"AND0CON",
|
||||
"ADDCON",
|
||||
"ANDCON",
|
||||
"LCON",
|
||||
"DCON",
|
||||
"SACON",
|
||||
"SECON",
|
||||
"LACON",
|
||||
"LECON",
|
||||
"DACON",
|
||||
"STCON",
|
||||
"SBRA",
|
||||
"LBRA",
|
||||
"SAUTO",
|
||||
"LAUTO",
|
||||
"SEXT",
|
||||
"LEXT",
|
||||
"ZOREG",
|
||||
"SOREG",
|
||||
"LOREG",
|
||||
"GOK",
|
||||
"ADDR",
|
||||
"TLS",
|
||||
"TEXTSIZE",
|
||||
"NCLASS",
|
||||
}
|
46
src/cmd/internal/obj/loong64/list.go
Normal file
46
src/cmd/internal/obj/loong64/list.go
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright 2022 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 loong64
|
||||
|
||||
import (
|
||||
"cmd/internal/obj"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func init() {
|
||||
obj.RegisterRegister(obj.RBaseLOONG64, REG_LAST+1, rconv)
|
||||
obj.RegisterOpcode(obj.ABaseLoong64, Anames)
|
||||
}
|
||||
|
||||
func rconv(r int) string {
|
||||
if r == 0 {
|
||||
return "NONE"
|
||||
}
|
||||
if r == REGG {
|
||||
// Special case.
|
||||
return "g"
|
||||
}
|
||||
if REG_R0 <= r && r <= REG_R31 {
|
||||
return fmt.Sprintf("R%d", r-REG_R0)
|
||||
}
|
||||
if REG_F0 <= r && r <= REG_F31 {
|
||||
return fmt.Sprintf("F%d", r-REG_F0)
|
||||
}
|
||||
if REG_FCSR0 <= r && r <= REG_FCSR31 {
|
||||
return fmt.Sprintf("FCSR%d", r-REG_FCSR0)
|
||||
}
|
||||
if REG_FCC0 <= r && r <= REG_FCC31 {
|
||||
return fmt.Sprintf("FCC%d", r-REG_FCC0)
|
||||
}
|
||||
return fmt.Sprintf("Rgok(%d)", r-obj.RBaseLOONG64)
|
||||
}
|
||||
|
||||
func DRconv(a int) string {
|
||||
s := "C_??"
|
||||
if a >= C_NONE && a <= C_NCLASS {
|
||||
s = cnames0[a]
|
||||
}
|
||||
return s
|
||||
}
|
701
src/cmd/internal/obj/loong64/obj.go
Normal file
701
src/cmd/internal/obj/loong64/obj.go
Normal file
@ -0,0 +1,701 @@
|
||||
// Copyright 2022 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 loong64
|
||||
|
||||
import (
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/objabi"
|
||||
"cmd/internal/sys"
|
||||
|
||||
"math"
|
||||
)
|
||||
|
||||
func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
||||
// Rewrite JMP/JAL to symbol as TYPE_BRANCH.
|
||||
switch p.As {
|
||||
case AJMP,
|
||||
AJAL,
|
||||
ARET,
|
||||
obj.ADUFFZERO,
|
||||
obj.ADUFFCOPY:
|
||||
if p.To.Sym != nil {
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
}
|
||||
}
|
||||
|
||||
// Rewrite float constants to values stored in memory.
|
||||
switch p.As {
|
||||
case AMOVF:
|
||||
if p.From.Type == obj.TYPE_FCONST {
|
||||
f32 := float32(p.From.Val.(float64))
|
||||
if math.Float32bits(f32) == 0 {
|
||||
p.As = AMOVW
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REGZERO
|
||||
break
|
||||
}
|
||||
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 {
|
||||
f64 := p.From.Val.(float64)
|
||||
if math.Float64bits(f64) == 0 {
|
||||
p.As = AMOVV
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REGZERO
|
||||
break
|
||||
}
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Sym = ctxt.Float64Sym(f64)
|
||||
p.From.Name = obj.NAME_EXTERN
|
||||
p.From.Offset = 0
|
||||
}
|
||||
}
|
||||
|
||||
// Rewrite SUB constants into ADD.
|
||||
switch p.As {
|
||||
case ASUB:
|
||||
if p.From.Type == obj.TYPE_CONST {
|
||||
p.From.Offset = -p.From.Offset
|
||||
p.As = AADD
|
||||
}
|
||||
|
||||
case ASUBU:
|
||||
if p.From.Type == obj.TYPE_CONST {
|
||||
p.From.Offset = -p.From.Offset
|
||||
p.As = AADDU
|
||||
}
|
||||
|
||||
case ASUBV:
|
||||
if p.From.Type == obj.TYPE_CONST {
|
||||
p.From.Offset = -p.From.Offset
|
||||
p.As = AADDV
|
||||
}
|
||||
|
||||
case ASUBVU:
|
||||
if p.From.Type == obj.TYPE_CONST {
|
||||
p.From.Offset = -p.From.Offset
|
||||
p.As = AADDVU
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
||||
c := ctxt0{ctxt: ctxt, newprog: newprog, cursym: cursym}
|
||||
|
||||
p := c.cursym.Func().Text
|
||||
textstksiz := p.To.Offset
|
||||
|
||||
if textstksiz < 0 {
|
||||
c.ctxt.Diag("negative frame size %d - did you mean NOFRAME?", textstksiz)
|
||||
}
|
||||
if p.From.Sym.NoFrame() {
|
||||
if textstksiz != 0 {
|
||||
c.ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", textstksiz)
|
||||
}
|
||||
}
|
||||
|
||||
c.cursym.Func().Args = p.To.Val.(int32)
|
||||
c.cursym.Func().Locals = int32(textstksiz)
|
||||
|
||||
/*
|
||||
* find leaf subroutines
|
||||
* expand RET
|
||||
*/
|
||||
|
||||
for p := c.cursym.Func().Text; p != nil; p = p.Link {
|
||||
switch p.As {
|
||||
case obj.ATEXT:
|
||||
p.Mark |= LABEL | LEAF | SYNC
|
||||
if p.Link != nil {
|
||||
p.Link.Mark |= LABEL
|
||||
}
|
||||
|
||||
case AMOVW,
|
||||
AMOVV:
|
||||
if p.To.Type == obj.TYPE_REG && p.To.Reg >= REG_SPECIAL {
|
||||
p.Mark |= LABEL | SYNC
|
||||
break
|
||||
}
|
||||
if p.From.Type == obj.TYPE_REG && p.From.Reg >= REG_SPECIAL {
|
||||
p.Mark |= LABEL | SYNC
|
||||
}
|
||||
|
||||
case ASYSCALL,
|
||||
AWORD:
|
||||
p.Mark |= LABEL | SYNC
|
||||
|
||||
case ANOR:
|
||||
if p.To.Type == obj.TYPE_REG {
|
||||
if p.To.Reg == REGZERO {
|
||||
p.Mark |= LABEL | SYNC
|
||||
}
|
||||
}
|
||||
|
||||
case AJAL,
|
||||
obj.ADUFFZERO,
|
||||
obj.ADUFFCOPY:
|
||||
c.cursym.Func().Text.Mark &^= LEAF
|
||||
fallthrough
|
||||
|
||||
case AJMP,
|
||||
ABEQ,
|
||||
ABGEU,
|
||||
ABLTU,
|
||||
ABLTZ,
|
||||
ABNE,
|
||||
ABFPT, ABFPF:
|
||||
p.Mark |= BRANCH
|
||||
q1 := p.To.Target()
|
||||
if q1 != nil {
|
||||
for q1.As == obj.ANOP {
|
||||
q1 = q1.Link
|
||||
p.To.SetTarget(q1)
|
||||
}
|
||||
|
||||
if q1.Mark&LEAF == 0 {
|
||||
q1.Mark |= LABEL
|
||||
}
|
||||
}
|
||||
q1 = p.Link
|
||||
if q1 != nil {
|
||||
q1.Mark |= LABEL
|
||||
}
|
||||
|
||||
case ARET:
|
||||
if p.Link != nil {
|
||||
p.Link.Mark |= LABEL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var mov, add obj.As
|
||||
|
||||
add = AADDV
|
||||
mov = AMOVV
|
||||
|
||||
var q *obj.Prog
|
||||
var q1 *obj.Prog
|
||||
autosize := int32(0)
|
||||
var p1 *obj.Prog
|
||||
var p2 *obj.Prog
|
||||
for p := c.cursym.Func().Text; p != nil; p = p.Link {
|
||||
o := p.As
|
||||
switch o {
|
||||
case obj.ATEXT:
|
||||
autosize = int32(textstksiz)
|
||||
|
||||
if p.Mark&LEAF != 0 && autosize == 0 {
|
||||
// A leaf function with no locals has no frame.
|
||||
p.From.Sym.Set(obj.AttrNoFrame, true)
|
||||
}
|
||||
|
||||
if !p.From.Sym.NoFrame() {
|
||||
// If there is a stack frame at all, it includes
|
||||
// space to save the LR.
|
||||
autosize += int32(c.ctxt.Arch.FixedFrameSize)
|
||||
}
|
||||
|
||||
if autosize&4 != 0 {
|
||||
autosize += 4
|
||||
}
|
||||
|
||||
if autosize == 0 && c.cursym.Func().Text.Mark&LEAF == 0 {
|
||||
if c.cursym.Func().Text.From.Sym.NoSplit() {
|
||||
if ctxt.Debugvlog {
|
||||
ctxt.Logf("save suppressed in: %s\n", c.cursym.Name)
|
||||
}
|
||||
|
||||
c.cursym.Func().Text.Mark |= LEAF
|
||||
}
|
||||
}
|
||||
|
||||
p.To.Offset = int64(autosize) - ctxt.Arch.FixedFrameSize
|
||||
|
||||
if c.cursym.Func().Text.Mark&LEAF != 0 {
|
||||
c.cursym.Set(obj.AttrLeaf, true)
|
||||
if p.From.Sym.NoFrame() {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !p.From.Sym.NoSplit() {
|
||||
p = c.stacksplit(p, autosize) // emit split check
|
||||
}
|
||||
|
||||
q = p
|
||||
|
||||
if autosize != 0 {
|
||||
// Make sure to save link register for non-empty frame, even if
|
||||
// it is a leaf function, so that traceback works.
|
||||
// Store link register before decrement SP, so if a signal comes
|
||||
// during the execution of the function prologue, the traceback
|
||||
// code will not see a half-updated stack frame.
|
||||
// This sequence is not async preemptible, as if we open a frame
|
||||
// at the current SP, it will clobber the saved LR.
|
||||
q = c.ctxt.StartUnsafePoint(q, c.newprog)
|
||||
|
||||
q = obj.Appendp(q, newprog)
|
||||
q.As = mov
|
||||
q.Pos = p.Pos
|
||||
q.From.Type = obj.TYPE_REG
|
||||
q.From.Reg = REGLINK
|
||||
q.To.Type = obj.TYPE_MEM
|
||||
q.To.Offset = int64(-autosize)
|
||||
q.To.Reg = REGSP
|
||||
|
||||
q = obj.Appendp(q, newprog)
|
||||
q.As = add
|
||||
q.Pos = p.Pos
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = int64(-autosize)
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REGSP
|
||||
q.Spadj = +autosize
|
||||
|
||||
q = c.ctxt.EndUnsafePoint(q, c.newprog, -1)
|
||||
}
|
||||
|
||||
if c.cursym.Func().Text.From.Sym.Wrapper() && c.cursym.Func().Text.Mark&LEAF == 0 {
|
||||
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
|
||||
//
|
||||
// MOV g_panic(g), R1
|
||||
// BEQ R1, end
|
||||
// MOV panic_argp(R1), R2
|
||||
// ADD $(autosize+FIXED_FRAME), R29, R3
|
||||
// BNE R2, R3, end
|
||||
// ADD $FIXED_FRAME, R29, R2
|
||||
// MOV R2, panic_argp(R1)
|
||||
// end:
|
||||
// NOP
|
||||
//
|
||||
// The NOP is needed to give the jumps somewhere to land.
|
||||
// It is a liblink NOP, not an hardware NOP: it encodes to 0 instruction bytes.
|
||||
//
|
||||
// We don't generate this for leafs because that means the wrapped
|
||||
// function was inlined into the wrapper.
|
||||
|
||||
q = obj.Appendp(q, newprog)
|
||||
|
||||
q.As = mov
|
||||
q.From.Type = obj.TYPE_MEM
|
||||
q.From.Reg = REGG
|
||||
q.From.Offset = 4 * int64(c.ctxt.Arch.PtrSize) // G.panic
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REG_R19
|
||||
|
||||
q = obj.Appendp(q, newprog)
|
||||
q.As = ABEQ
|
||||
q.From.Type = obj.TYPE_REG
|
||||
q.From.Reg = REG_R19
|
||||
q.To.Type = obj.TYPE_BRANCH
|
||||
q.Mark |= BRANCH
|
||||
p1 = q
|
||||
|
||||
q = obj.Appendp(q, newprog)
|
||||
q.As = mov
|
||||
q.From.Type = obj.TYPE_MEM
|
||||
q.From.Reg = REG_R19
|
||||
q.From.Offset = 0 // Panic.argp
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REG_R4
|
||||
|
||||
q = obj.Appendp(q, newprog)
|
||||
q.As = add
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = int64(autosize) + ctxt.Arch.FixedFrameSize
|
||||
q.Reg = REGSP
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REG_R5
|
||||
|
||||
q = obj.Appendp(q, newprog)
|
||||
q.As = ABNE
|
||||
q.From.Type = obj.TYPE_REG
|
||||
q.From.Reg = REG_R4
|
||||
q.Reg = REG_R5
|
||||
q.To.Type = obj.TYPE_BRANCH
|
||||
q.Mark |= BRANCH
|
||||
p2 = q
|
||||
|
||||
q = obj.Appendp(q, newprog)
|
||||
q.As = add
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = ctxt.Arch.FixedFrameSize
|
||||
q.Reg = REGSP
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REG_R4
|
||||
|
||||
q = obj.Appendp(q, newprog)
|
||||
q.As = mov
|
||||
q.From.Type = obj.TYPE_REG
|
||||
q.From.Reg = REG_R4
|
||||
q.To.Type = obj.TYPE_MEM
|
||||
q.To.Reg = REG_R19
|
||||
q.To.Offset = 0 // Panic.argp
|
||||
|
||||
q = obj.Appendp(q, newprog)
|
||||
|
||||
q.As = obj.ANOP
|
||||
p1.To.SetTarget(q)
|
||||
p2.To.SetTarget(q)
|
||||
}
|
||||
|
||||
case ARET:
|
||||
if p.From.Type == obj.TYPE_CONST {
|
||||
ctxt.Diag("using BECOME (%v) is not supported!", p)
|
||||
break
|
||||
}
|
||||
|
||||
retSym := p.To.Sym
|
||||
p.To.Name = obj.NAME_NONE // clear fields as we may modify p to other instruction
|
||||
p.To.Sym = nil
|
||||
|
||||
if c.cursym.Func().Text.Mark&LEAF != 0 {
|
||||
if autosize == 0 {
|
||||
p.As = AJMP
|
||||
p.From = obj.Addr{}
|
||||
if retSym != nil { // retjmp
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
p.To.Name = obj.NAME_EXTERN
|
||||
p.To.Sym = retSym
|
||||
} else {
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Reg = REGLINK
|
||||
p.To.Offset = 0
|
||||
}
|
||||
p.Mark |= BRANCH
|
||||
break
|
||||
}
|
||||
|
||||
p.As = add
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = int64(autosize)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGSP
|
||||
p.Spadj = -autosize
|
||||
|
||||
q = c.newprog()
|
||||
q.As = AJMP
|
||||
q.Pos = p.Pos
|
||||
if retSym != nil { // retjmp
|
||||
q.To.Type = obj.TYPE_BRANCH
|
||||
q.To.Name = obj.NAME_EXTERN
|
||||
q.To.Sym = retSym
|
||||
} else {
|
||||
q.To.Type = obj.TYPE_MEM
|
||||
q.To.Offset = 0
|
||||
q.To.Reg = REGLINK
|
||||
}
|
||||
q.Mark |= BRANCH
|
||||
q.Spadj = +autosize
|
||||
|
||||
q.Link = p.Link
|
||||
p.Link = q
|
||||
break
|
||||
}
|
||||
|
||||
p.As = mov
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Offset = 0
|
||||
p.From.Reg = REGSP
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGLINK
|
||||
|
||||
if autosize != 0 {
|
||||
q = c.newprog()
|
||||
q.As = add
|
||||
q.Pos = p.Pos
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = int64(autosize)
|
||||
q.To.Type = obj.TYPE_REG
|
||||
q.To.Reg = REGSP
|
||||
q.Spadj = -autosize
|
||||
|
||||
q.Link = p.Link
|
||||
p.Link = q
|
||||
}
|
||||
|
||||
q1 = c.newprog()
|
||||
q1.As = AJMP
|
||||
q1.Pos = p.Pos
|
||||
if retSym != nil { // retjmp
|
||||
q1.To.Type = obj.TYPE_BRANCH
|
||||
q1.To.Name = obj.NAME_EXTERN
|
||||
q1.To.Sym = retSym
|
||||
} else {
|
||||
q1.To.Type = obj.TYPE_MEM
|
||||
q1.To.Offset = 0
|
||||
q1.To.Reg = REGLINK
|
||||
}
|
||||
q1.Mark |= BRANCH
|
||||
q1.Spadj = +autosize
|
||||
|
||||
q1.Link = q.Link
|
||||
q.Link = q1
|
||||
|
||||
case AADD,
|
||||
AADDU,
|
||||
AADDV,
|
||||
AADDVU:
|
||||
if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
|
||||
p.Spadj = int32(-p.From.Offset)
|
||||
}
|
||||
|
||||
case obj.AGETCALLERPC:
|
||||
if cursym.Leaf() {
|
||||
// MOV LR, Rd
|
||||
p.As = mov
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REGLINK
|
||||
} else {
|
||||
// MOV (RSP), Rd
|
||||
p.As = mov
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = REGSP
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ctxt0) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
|
||||
var mov, add obj.As
|
||||
|
||||
add = AADDV
|
||||
mov = AMOVV
|
||||
if c.ctxt.Flag_maymorestack != "" {
|
||||
// Save LR and REGCTXT.
|
||||
frameSize := 2 * c.ctxt.Arch.PtrSize
|
||||
|
||||
p = c.ctxt.StartUnsafePoint(p, c.newprog)
|
||||
|
||||
// MOV REGLINK, -8/-16(SP)
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = mov
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REGLINK
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Offset = int64(-frameSize)
|
||||
p.To.Reg = REGSP
|
||||
|
||||
// MOV REGCTXT, -4/-8(SP)
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = mov
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REGCTXT
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Offset = -int64(c.ctxt.Arch.PtrSize)
|
||||
p.To.Reg = REGSP
|
||||
|
||||
// ADD $-8/$-16, SP
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = add
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = int64(-frameSize)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGSP
|
||||
p.Spadj = int32(frameSize)
|
||||
|
||||
// JAL maymorestack
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = AJAL
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
// See ../x86/obj6.go
|
||||
p.To.Sym = c.ctxt.LookupABI(c.ctxt.Flag_maymorestack, c.cursym.ABI())
|
||||
p.Mark |= BRANCH
|
||||
|
||||
// Restore LR and REGCTXT.
|
||||
|
||||
// MOV 0(SP), REGLINK
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = mov
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Offset = 0
|
||||
p.From.Reg = REGSP
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGLINK
|
||||
|
||||
// MOV 4/8(SP), REGCTXT
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = mov
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Offset = int64(c.ctxt.Arch.PtrSize)
|
||||
p.From.Reg = REGSP
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGCTXT
|
||||
|
||||
// ADD $8/$16, SP
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = add
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = int64(frameSize)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REGSP
|
||||
p.Spadj = int32(-frameSize)
|
||||
|
||||
p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
|
||||
}
|
||||
|
||||
// Jump back to here after morestack returns.
|
||||
startPred := p
|
||||
|
||||
// MOV g_stackguard(g), R19
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = mov
|
||||
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_R19
|
||||
|
||||
// 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)
|
||||
|
||||
var q *obj.Prog
|
||||
if framesize <= objabi.StackSmall {
|
||||
// small stack: SP < stackguard
|
||||
// AGTU SP, stackguard, R19
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = ASGTU
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REGSP
|
||||
p.Reg = REG_R19
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R19
|
||||
} else {
|
||||
// large stack: SP-framesize < stackguard-StackSmall
|
||||
offset := int64(framesize) - objabi.StackSmall
|
||||
if framesize > objabi.StackBig {
|
||||
// Such a large stack we need to protect against underflow.
|
||||
// The runtime guarantees SP > objabi.StackBig, but
|
||||
// framesize is large enough that SP-framesize may
|
||||
// underflow, causing a direct comparison with the
|
||||
// stack guard to incorrectly succeed. We explicitly
|
||||
// guard against underflow.
|
||||
//
|
||||
// SGTU $(framesize-StackSmall), SP, R4
|
||||
// BNE R4, label-of-call-to-morestack
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = ASGTU
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = offset
|
||||
p.Reg = REGSP
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R4
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
q = p
|
||||
p.As = ABNE
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_R4
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
p.Mark |= BRANCH
|
||||
}
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = add
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = -offset
|
||||
p.Reg = REGSP
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R4
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = ASGTU
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_R4
|
||||
p.Reg = REG_R19
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R19
|
||||
}
|
||||
|
||||
// q1: BNE R19, done
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
q1 := p
|
||||
|
||||
p.As = ABNE
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REG_R19
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
p.Mark |= BRANCH
|
||||
|
||||
// MOV LINK, R5
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = mov
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = REGLINK
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R5
|
||||
if q != nil {
|
||||
q.To.SetTarget(p)
|
||||
p.Mark |= LABEL
|
||||
}
|
||||
|
||||
p = c.ctxt.EmitEntryStackMap(c.cursym, p, c.newprog)
|
||||
|
||||
// JAL runtime.morestack(SB)
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = AJAL
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
if c.cursym.CFunc() {
|
||||
p.To.Sym = c.ctxt.Lookup("runtime.morestackc")
|
||||
} else if !c.cursym.Func().Text.From.Sym.NeedCtxt() {
|
||||
p.To.Sym = c.ctxt.Lookup("runtime.morestack_noctxt")
|
||||
} else {
|
||||
p.To.Sym = c.ctxt.Lookup("runtime.morestack")
|
||||
}
|
||||
p.Mark |= BRANCH
|
||||
|
||||
p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
|
||||
|
||||
// JMP start
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = AJMP
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
p.To.SetTarget(startPred.Link)
|
||||
startPred.Link.Mark |= LABEL
|
||||
p.Mark |= BRANCH
|
||||
|
||||
// placeholder for q1's jump target
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = obj.ANOP // zero-width place holder
|
||||
q1.To.SetTarget(p)
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func (c *ctxt0) addnop(p *obj.Prog) {
|
||||
q := c.newprog()
|
||||
q.As = ANOOP
|
||||
q.Pos = p.Pos
|
||||
q.Link = p.Link
|
||||
p.Link = q
|
||||
}
|
||||
|
||||
var Linkloong64 = obj.LinkArch{
|
||||
Arch: sys.ArchLoong64,
|
||||
Init: buildop,
|
||||
Preprocess: preprocess,
|
||||
Assemble: span0,
|
||||
Progedit: progedit,
|
||||
DWARFRegisters: LOONG64DWARFRegisters,
|
||||
}
|
@ -507,15 +507,16 @@ var regSpace []regSet
|
||||
const (
|
||||
// Because of masking operations in the encodings, each register
|
||||
// space should start at 0 modulo some power of 2.
|
||||
RBase386 = 1 * 1024
|
||||
RBaseAMD64 = 2 * 1024
|
||||
RBaseARM = 3 * 1024
|
||||
RBasePPC64 = 4 * 1024 // range [4k, 8k)
|
||||
RBaseARM64 = 8 * 1024 // range [8k, 13k)
|
||||
RBaseMIPS = 13 * 1024 // range [13k, 14k)
|
||||
RBaseS390X = 14 * 1024 // range [14k, 15k)
|
||||
RBaseRISCV = 15 * 1024 // range [15k, 16k)
|
||||
RBaseWasm = 16 * 1024
|
||||
RBase386 = 1 * 1024
|
||||
RBaseAMD64 = 2 * 1024
|
||||
RBaseARM = 3 * 1024
|
||||
RBasePPC64 = 4 * 1024 // range [4k, 8k)
|
||||
RBaseARM64 = 8 * 1024 // range [8k, 13k)
|
||||
RBaseMIPS = 13 * 1024 // range [13k, 14k)
|
||||
RBaseS390X = 14 * 1024 // range [14k, 15k)
|
||||
RBaseRISCV = 15 * 1024 // range [15k, 16k)
|
||||
RBaseWasm = 16 * 1024
|
||||
RBaseLOONG64 = 17 * 1024
|
||||
)
|
||||
|
||||
// RegisterRegister binds a pretty-printer (Rconv) for register
|
||||
|
Loading…
x
Reference in New Issue
Block a user