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
|
ABasePPC64
|
||||||
ABaseARM64
|
ABaseARM64
|
||||||
ABaseMIPS
|
ABaseMIPS
|
||||||
|
ABaseLoong64
|
||||||
ABaseRISCV
|
ABaseRISCV
|
||||||
ABaseS390X
|
ABaseS390X
|
||||||
ABaseWasm
|
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 (
|
const (
|
||||||
// Because of masking operations in the encodings, each register
|
// Because of masking operations in the encodings, each register
|
||||||
// space should start at 0 modulo some power of 2.
|
// space should start at 0 modulo some power of 2.
|
||||||
RBase386 = 1 * 1024
|
RBase386 = 1 * 1024
|
||||||
RBaseAMD64 = 2 * 1024
|
RBaseAMD64 = 2 * 1024
|
||||||
RBaseARM = 3 * 1024
|
RBaseARM = 3 * 1024
|
||||||
RBasePPC64 = 4 * 1024 // range [4k, 8k)
|
RBasePPC64 = 4 * 1024 // range [4k, 8k)
|
||||||
RBaseARM64 = 8 * 1024 // range [8k, 13k)
|
RBaseARM64 = 8 * 1024 // range [8k, 13k)
|
||||||
RBaseMIPS = 13 * 1024 // range [13k, 14k)
|
RBaseMIPS = 13 * 1024 // range [13k, 14k)
|
||||||
RBaseS390X = 14 * 1024 // range [14k, 15k)
|
RBaseS390X = 14 * 1024 // range [14k, 15k)
|
||||||
RBaseRISCV = 15 * 1024 // range [15k, 16k)
|
RBaseRISCV = 15 * 1024 // range [15k, 16k)
|
||||||
RBaseWasm = 16 * 1024
|
RBaseWasm = 16 * 1024
|
||||||
|
RBaseLOONG64 = 17 * 1024
|
||||||
)
|
)
|
||||||
|
|
||||||
// RegisterRegister binds a pretty-printer (Rconv) for register
|
// RegisterRegister binds a pretty-printer (Rconv) for register
|
||||||
|
Loading…
x
Reference in New Issue
Block a user