mirror of
https://github.com/golang/go.git
synced 2026-06-28 03:40:37 +00:00
cmd/asm, cmd/internal/obj: add riscv64 pseudo CSR ops
Add support for the riscv64 pseudo CSR ops; CSRR, CSRW, CSRS, CSRC, CSRWI, CSRSI, CSRCI. We also add tests to check that we can correctly encode CSRR instructions that read all the RVV CSR registers. Change-Id: I50b2d6da4f5847e65ab8017cd36f068b2ce525b3 Reviewed-on: https://go-review.googlesource.com/c/go/+/650577 Reviewed-by: Meng Zhuo <mengzhuo1203@gmail.com> Reviewed-by: Carlos Amedee <carlos@golang.org> LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Mark Freeman <markfreeman@google.com>
This commit is contained in:
parent
02b3e0d4dd
commit
ca10097f29
7 changed files with 112 additions and 9 deletions
|
|
@ -47,6 +47,22 @@ func IsRISCV64CSRO(op obj.As) (imm bool, ok bool) {
|
|||
return
|
||||
}
|
||||
|
||||
// IsRISCV64PseudoCSRO reports whether the op is a pseudo instruction
|
||||
// that uses CSR symbolic names, whether that instruction expects a register
|
||||
// or an immediate source operand and what the expected index of the operand
|
||||
// containing the CSR name should be.
|
||||
func IsRISCV64PseudoCSRO(op obj.As) (imm bool, index int, ok bool) {
|
||||
switch op {
|
||||
case riscv.ACSRCI, riscv.ACSRSI, riscv.ACSRWI:
|
||||
imm, index, ok = true, 1, true
|
||||
case riscv.ACSRC, riscv.ACSRS, riscv.ACSRW:
|
||||
imm, index, ok = false, 1, true
|
||||
case riscv.ACSRR:
|
||||
imm, index, ok = false, 0, true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var riscv64SpecialOperand map[string]riscv.SpecialOperand
|
||||
|
||||
// RISCV64SpecialOperand returns the internal representation of a special operand.
|
||||
|
|
|
|||
|
|
@ -665,6 +665,25 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
|
|||
prog.AddRestSource(a[1])
|
||||
break
|
||||
}
|
||||
} else if p.arch.Family == sys.RISCV64 {
|
||||
// RISCV64 pseudo instructions that reference CSRs with symbolic names.
|
||||
if isImm, specialIndex, ok := arch.IsRISCV64PseudoCSRO(op); ok {
|
||||
if a[0].Type != obj.TYPE_CONST && isImm {
|
||||
p.errorf("invalid value for first operand to %s instruction, must be a 5 bit unsigned immediate", op)
|
||||
return
|
||||
}
|
||||
if a[specialIndex].Type != obj.TYPE_SPECIAL {
|
||||
p.errorf("invalid value for first or second operand to %s instruction, must be a CSR name", op)
|
||||
return
|
||||
}
|
||||
prog.AddRestSourceArgs([]obj.Addr{a[specialIndex]})
|
||||
if specialIndex == 0 {
|
||||
prog.To = a[1]
|
||||
} else {
|
||||
prog.From = a[0]
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
prog.From = a[0]
|
||||
prog.To = a[1]
|
||||
|
|
|
|||
16
src/cmd/asm/internal/asm/testdata/riscv64.s
vendored
16
src/cmd/asm/internal/asm/testdata/riscv64.s
vendored
|
|
@ -177,6 +177,16 @@ start:
|
|||
SD X5, 4(X6) // 23325300
|
||||
|
||||
// 7.1: CSR Instructions
|
||||
CSRC X5, VSTART // 73b08200
|
||||
CSRC $2, VSTART // 73708100
|
||||
CSRCI $2, VSTART // 73708100
|
||||
CSRR CYCLE, X5 // f32200c0
|
||||
CSRR VCSR, X5 // f322f000
|
||||
CSRR VL, X5 // f32200c2
|
||||
CSRR VLENB, X5 // f32220c2
|
||||
CSRR VSTART, X5 // f3228000
|
||||
CSRR VXSAT, X5 // f3229000
|
||||
CSRR VXRM, X5 // f322a000
|
||||
CSRRC X0, CYCLE, X5 // f33200c0
|
||||
CSRRC X0, CYCLE, X0 // 733000c0
|
||||
CSRRC X10, CYCLE, X5 // f33205c0
|
||||
|
|
@ -193,6 +203,12 @@ start:
|
|||
CSRRW X10, CYCLE, X5 // f31205c0
|
||||
CSRRW $2, TIME, X5 // f35211c0
|
||||
CSRRWI $2, TIME, X5 // f35211c0
|
||||
CSRS X10, VSTART // 73208500
|
||||
CSRS $2, VSTART // 73608100
|
||||
CSRSI $2, VSTART // 73608100
|
||||
CSRW X10, VSTART // 73108500
|
||||
CSRW $2, VSTART // 73508100
|
||||
CSRWI $2, VSTART // 73508100
|
||||
|
||||
// 8.1: Base Counters and Timers (Zicntr)
|
||||
RDCYCLE X5 // f32200c0
|
||||
|
|
|
|||
19
src/cmd/asm/internal/asm/testdata/riscv64error.s
vendored
19
src/cmd/asm/internal/asm/testdata/riscv64error.s
vendored
|
|
@ -3,9 +3,14 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
TEXT errors(SB),$0
|
||||
CSRC X5, TU // ERROR "unknown CSR"
|
||||
CSRC (X5), CYCLE // ERROR "integer register or immediate expected for 1st operand"
|
||||
CSRC $-1, TIME // ERROR "immediate out of range 0 to 31"
|
||||
CSRR TU, X5 // ERROR "unknown CSR"
|
||||
CSRR CYCLE, (X5) // ERROR "needs an integer register output"
|
||||
CSRRC (X10), CYCLE, X5 // ERROR "integer register or immediate expected for 1st operand"
|
||||
CSRRC X0, TU, X5 // ERROR "unknown CSR"
|
||||
CSRRC X0, CYCLE // ERROR "missing CSR name"
|
||||
CSRRC X0, X5 // ERROR "missing CSR name"
|
||||
CSRRC X0, CYCLE, (X10) // ERROR "needs an integer register output"
|
||||
CSRRC $-1, TIME, X15 // ERROR "immediate out of range 0 to 31"
|
||||
CSRRCI $32, TIME, X15 // ERROR "immediate out of range 0 to 31"
|
||||
|
|
@ -13,17 +18,25 @@ TEXT errors(SB),$0
|
|||
CSRRS (X10), CYCLE, X5 // ERROR "integer register or immediate expected for 1st operand"
|
||||
CSRRS X0, CYCLE, (X10) // ERROR "needs an integer register output"
|
||||
CSRRS X0, TU, X5 // ERROR "unknown CSR"
|
||||
CSRRS X0, CYCLE // ERROR "missing CSR name"
|
||||
CSRRS X0, X5 // ERROR "missing CSR name"
|
||||
CSRRS $-1, TIME, X15 // ERROR "immediate out of range 0 to 31"
|
||||
CSRRSI $32, TIME, X15 // ERROR "immediate out of range 0 to 31"
|
||||
CSRRSI $1, TIME, (X15) // ERROR "needs an integer register output"
|
||||
CSRRW (X10), CYCLE, X5 // ERROR "integer register or immediate expected for 1st operand"
|
||||
CSRRW X0, TU, X5 // ERROR "unknown CSR"
|
||||
CSRRW X0, CYCLE // ERROR "missing CSR name"
|
||||
CSRRW X0, X5 // ERROR "missing CSR name"
|
||||
CSRRW X0, CYCLE, (X5) // ERROR "needs an integer register output"
|
||||
CSRRW $-1, TIME, X15 // ERROR "immediate out of range 0 to 31"
|
||||
CSRRWI $32, TIME, X15 // ERROR "immediate out of range 0 to 31"
|
||||
CSRRWI $1, TIME, (X15) // ERROR "needs an integer register output"
|
||||
CSRW X5, TU // ERROR "unknown CSR"
|
||||
CSRW $-1, TIME // ERROR "immediate out of range 0 to 31"
|
||||
CSRWI $32, TIME // ERROR "immediate out of range 0 to 31"
|
||||
CSRS (X5), CYCLE // ERROR "integer register or immediate expected for 1st operand"
|
||||
CSRS X5, TU // ERROR "unknown CSR"
|
||||
CSRS $-1, TIME // ERROR "immediate out of range 0 to 31"
|
||||
CSRSI $32, TIME // ERROR "immediate out of range 0 to 31"
|
||||
CSRW (X5), CYCLE // ERROR "integer register or immediate expected for 1st operand"
|
||||
MOV $errors(SB), (X5) // ERROR "address load must target register"
|
||||
MOV $8(SP), (X5) // ERROR "address load must target register"
|
||||
MOVB $8(SP), X5 // ERROR "unsupported address load"
|
||||
|
|
|
|||
|
|
@ -921,6 +921,13 @@ var Anames = []string{
|
|||
"BLEZ",
|
||||
"BLTZ",
|
||||
"BNEZ",
|
||||
"CSRC",
|
||||
"CSRCI",
|
||||
"CSRR",
|
||||
"CSRS",
|
||||
"CSRSI",
|
||||
"CSRW",
|
||||
"CSRWI",
|
||||
"FABSD",
|
||||
"FABSS",
|
||||
"FNED",
|
||||
|
|
|
|||
|
|
@ -1490,6 +1490,13 @@ const (
|
|||
ABLEZ
|
||||
ABLTZ
|
||||
ABNEZ
|
||||
ACSRC
|
||||
ACSRCI
|
||||
ACSRR
|
||||
ACSRS
|
||||
ACSRSI
|
||||
ACSRW
|
||||
ACSRWI
|
||||
AFABSD
|
||||
AFABSS
|
||||
AFNED
|
||||
|
|
|
|||
|
|
@ -4362,12 +4362,41 @@ func instructionsForProg(p *obj.Prog, compress bool) []*instruction {
|
|||
ins.imm = -1022
|
||||
}
|
||||
|
||||
case ACSRRC, ACSRRCI, ACSRRS, ACSRRSI, ACSRRW, ACSRRWI:
|
||||
case ACSRC, ACSRRC, ACSRCI, ACSRRCI, ACSRR, ACSRS, ACSRSI, ACSRRS, ACSRRSI, ACSRRW, ACSRRWI, ACSRW, ACSRWI:
|
||||
switch {
|
||||
case ins.as == ACSRCI || (ins.as == ACSRC && p.From.Type == obj.TYPE_CONST):
|
||||
ins.as = ACSRRCI
|
||||
ins.rd = REG_ZERO
|
||||
case ins.as == ACSRC:
|
||||
ins.as = ACSRRC
|
||||
ins.rd = REG_ZERO
|
||||
case ins.as == ACSRSI || (ins.as == ACSRS && p.From.Type == obj.TYPE_CONST):
|
||||
ins.as = ACSRRSI
|
||||
ins.rd = REG_ZERO
|
||||
case ins.as == ACSRS:
|
||||
ins.as = ACSRRS
|
||||
ins.rd = REG_ZERO
|
||||
case ins.as == ACSRWI || (ins.as == ACSRW && p.From.Type == obj.TYPE_CONST):
|
||||
ins.as = ACSRRWI
|
||||
ins.rd = REG_ZERO
|
||||
case ins.as == ACSRW:
|
||||
ins.as = ACSRRW
|
||||
ins.rd = REG_ZERO
|
||||
default:
|
||||
if p.To.Type != obj.TYPE_REG {
|
||||
p.Ctxt.Diag("%v: needs an integer register output", p)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if len(p.RestArgs) == 0 || p.RestArgs[0].Type != obj.TYPE_SPECIAL {
|
||||
p.Ctxt.Diag("%v: missing CSR name", p)
|
||||
return nil
|
||||
}
|
||||
if p.From.Type == obj.TYPE_CONST {
|
||||
if ins.as == ACSRR {
|
||||
ins.as = ACSRRS
|
||||
ins.rs1 = REG_ZERO
|
||||
} else if p.From.Type == obj.TYPE_CONST {
|
||||
imm := p.From.Offset
|
||||
if imm < 0 || imm >= 32 {
|
||||
p.Ctxt.Diag("%v: immediate out of range 0 to 31", p)
|
||||
|
|
@ -4380,10 +4409,6 @@ func instructionsForProg(p *obj.Prog, compress bool) []*instruction {
|
|||
p.Ctxt.Diag("%v: integer register or immediate expected for 1st operand", p)
|
||||
return nil
|
||||
}
|
||||
if p.To.Type != obj.TYPE_REG {
|
||||
p.Ctxt.Diag("%v: needs an integer register output", p)
|
||||
return nil
|
||||
}
|
||||
csrNum := SpecialOperand(p.RestArgs[0].Offset).encode()
|
||||
if csrNum >= 1<<12 {
|
||||
p.Ctxt.Diag("%v: unknown CSR", p)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue