Commit 9c67516e authored by fanzha02's avatar fanzha02 Committed by Ben Shi

cmd/internal/obj/arm64: add support for most system registers

This patch supports the EL0 and EL1 system registers used in MRS/MSR
instructions. This patch refactors the assembler code, allowing the
assembler to read system register information from the automatically
generated sysRegEnc.go file and move existing declared system registers
to the sysRegEnc.go file.

This patch adds 431 system registers, it is worth noting that the number
of special registers is initialized to less than 1024 in the list7.go file.

This CL also adds some test cases to test the newly added system registers.

The test cases are contributed by Dianhong Xu <Dianhong.Xu@arm.com>

Change-Id: Ic09a937eaaeefe82bd08b5dd726808f8ff6cebf6
Reviewed-on: https://go-review.googlesource.com/c/go/+/189577Reviewed-by: default avatarBen Shi <powerman1st@163.com>
Run-TryBot: Ben Shi <powerman1st@163.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent b91b3d9c
......@@ -267,21 +267,15 @@ func archArm64() *Arch {
for i := arm64.REG_V0; i <= arm64.REG_V31; i++ {
register[obj.Rconv(i)] = int16(i)
}
// System registers.
for i := 0; i < len(arm64.SystemReg); i++ {
register[arm64.SystemReg[i].Name] = arm64.SystemReg[i].Reg
}
register["LR"] = arm64.REGLINK
register["DAIF"] = arm64.REG_DAIF
register["NZCV"] = arm64.REG_NZCV
register["FPSR"] = arm64.REG_FPSR
register["FPCR"] = arm64.REG_FPCR
register["SPSR_EL1"] = arm64.REG_SPSR_EL1
register["ELR_EL1"] = arm64.REG_ELR_EL1
register["SPSR_EL2"] = arm64.REG_SPSR_EL2
register["ELR_EL2"] = arm64.REG_ELR_EL2
register["CurrentEL"] = arm64.REG_CurrentEL
register["SP_EL0"] = arm64.REG_SP_EL0
register["SPSel"] = arm64.REG_SPSel
register["DAIFSet"] = arm64.REG_DAIFSet
register["DAIFClr"] = arm64.REG_DAIFClr
register["DCZID_EL0"] = arm64.REG_DCZID_EL0
register["PLDL1KEEP"] = arm64.REG_PLDL1KEEP
register["PLDL1STRM"] = arm64.REG_PLDL1STRM
register["PLDL2KEEP"] = arm64.REG_PLDL2KEEP
......
This diff is collapsed.
......@@ -195,22 +195,12 @@ const (
// Special registers, after subtracting obj.RBaseARM64, bit 12 indicates
// a special register and the low bits select the register.
// AUTO_SYSREG_END is the last item in the automatically generated system register
// declaration, and it is defined in the sysRegEnc.go file.
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_SPECIAL = obj.RBaseARM64 + 1<<12
REG_DAIFSet = AUTO_SYSREG_END + iota
REG_DAIFClr
REG_DCZID_EL0
REG_PLDL1KEEP
REG_PLDL1STRM
REG_PLDL2KEEP
......
......@@ -842,15 +842,6 @@ var pstatefield = []struct {
{REG_DAIFClr, 3<<16 | 4<<12 | 7<<5},
}
// the System register values, and value to use in instruction
var systemreg = []struct {
reg int16
enc uint32
}{
{REG_ELR_EL1, 8<<16 | 4<<12 | 1<<5},
{REG_DCZID_EL0, 3<<19 | 3<<16 | 7<<5},
}
var prfopfield = []struct {
reg int16
enc uint32
......@@ -3513,12 +3504,8 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 = c.oprrr(p, AMRS)
v := uint32(0)
for i := 0; i < len(systemreg); i++ {
if systemreg[i].reg == p.From.Reg {
v = systemreg[i].enc
break
}
}
// SysRegEnc function returns the system register encoding.
_, v = SysRegEnc(p.From.Reg)
if v == 0 {
c.ctxt.Diag("illegal system register:\n%v", p)
}
......@@ -3533,12 +3520,8 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 = c.oprrr(p, AMSR)
v := uint32(0)
for i := 0; i < len(systemreg); i++ {
if systemreg[i].reg == p.To.Reg {
v = systemreg[i].enc
break
}
}
// SysRegEnc function returns the system register encoding.
_, v = SysRegEnc(p.To.Reg)
if v == 0 {
c.ctxt.Diag("illegal system register:\n%v", p)
}
......
......@@ -112,34 +112,10 @@ func rconv(r int) string {
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"
case r == REG_DCZID_EL0:
return "DCZID_EL0"
case r == REG_PLDL1KEEP:
return "PLDL1KEEP"
case r == REG_PLDL1STRM:
......@@ -232,6 +208,11 @@ func rconv(r int) string {
case REG_ELEM <= r && r < REG_ELEM_END:
return fmt.Sprintf("V%d.%s", r&31, arrange((r>>5)&15))
}
// Return system register name.
name, _ := SysRegEnc(int16(r))
if name != "" {
return name
}
return fmt.Sprintf("badreg(%d)", r)
}
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment