mirror of
https://github.com/golang/go
synced 2024-11-17 15:54:39 -07:00
cmd/asm,cmd/internal/obj/riscv: add LR/SC instructions
Add support for Load-Reserved (LR) and Store-Conditional (SC) instructions. Use instructions in place of currently used defines. Updates #36765 Change-Id: I77e660639802293ece40cfde4865ac237e3308d6 Reviewed-on: https://go-review.googlesource.com/c/go/+/220540 Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
2a08f3c181
commit
85a8526a7e
25
src/cmd/asm/internal/arch/riscv64.go
Normal file
25
src/cmd/asm/internal/arch/riscv64.go
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
// This file encapsulates some of the odd characteristics of the RISCV64
|
||||
// instruction set, to minimize its interaction with the core of the
|
||||
// assembler.
|
||||
|
||||
package arch
|
||||
|
||||
import (
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/obj/riscv"
|
||||
)
|
||||
|
||||
// IsRISCV64AMO reports whether the op (as defined by a riscv.A*
|
||||
// constant) is one of the AMO instructions that requires special
|
||||
// handling.
|
||||
func IsRISCV64AMO(op obj.As) bool {
|
||||
switch op {
|
||||
case riscv.ASCW, riscv.ASCD:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
@ -590,7 +590,7 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
|
||||
prog.To = a[1]
|
||||
case 3:
|
||||
switch p.arch.Family {
|
||||
case sys.MIPS, sys.MIPS64, sys.RISCV64:
|
||||
case sys.MIPS, sys.MIPS64:
|
||||
prog.From = a[0]
|
||||
prog.Reg = p.getRegister(prog, op, &a[1])
|
||||
prog.To = a[2]
|
||||
@ -675,6 +675,21 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
|
||||
p.errorf("invalid addressing modes for %s instruction", op)
|
||||
return
|
||||
}
|
||||
case sys.RISCV64:
|
||||
// RISCV64 instructions with one input and two outputs.
|
||||
if arch.IsRISCV64AMO(op) {
|
||||
prog.From = a[0]
|
||||
prog.To = a[1]
|
||||
if a[2].Type != obj.TYPE_REG {
|
||||
p.errorf("invalid addressing modes for third operand to %s instruction, must be register", op)
|
||||
return
|
||||
}
|
||||
prog.RegTo2 = a[2].Reg
|
||||
break
|
||||
}
|
||||
prog.From = a[0]
|
||||
prog.Reg = p.getRegister(prog, op, &a[1])
|
||||
prog.To = a[2]
|
||||
case sys.S390X:
|
||||
prog.From = a[0]
|
||||
if a[1].Type == obj.TYPE_REG {
|
||||
|
8
src/cmd/asm/internal/asm/testdata/riscvenc.s
vendored
8
src/cmd/asm/internal/asm/testdata/riscvenc.s
vendored
@ -157,6 +157,12 @@ start:
|
||||
REMW X5, X6, X7 // bb635302
|
||||
REMUW X5, X6, X7 // bb735302
|
||||
|
||||
// 8.2: Load-Reserved/Store-Conditional
|
||||
LRW (X5), X6 // 2fa30214
|
||||
LRD (X5), X6 // 2fb30214
|
||||
SCW X5, (X6), X7 // af23531c
|
||||
SCD X5, (X6), X7 // af33531c
|
||||
|
||||
// 10.1: Base Counters and Timers
|
||||
RDCYCLE X5 // f32200c0
|
||||
RDTIME X5 // f32210c0
|
||||
@ -276,7 +282,7 @@ start:
|
||||
// These jumps can get printed as jumps to 2 because they go to the
|
||||
// second instruction in the function (the first instruction is an
|
||||
// invisible stack pointer adjustment).
|
||||
JMP start // JMP 2 // 6ff09fcc
|
||||
JMP start // JMP 2 // 6ff09fcb
|
||||
JMP (X5) // 67800200
|
||||
JMP 4(X5) // 67804200
|
||||
|
||||
|
@ -1318,7 +1318,7 @@ func validateRaw(ctxt *obj.Link, ins *instruction) {
|
||||
}
|
||||
|
||||
// encodeR encodes an R-type RISC-V instruction.
|
||||
func encodeR(as obj.As, rs1, rs2, rd, funct3 uint32) uint32 {
|
||||
func encodeR(as obj.As, rs1, rs2, rd, funct3, funct7 uint32) uint32 {
|
||||
enc := encode(as)
|
||||
if enc == nil {
|
||||
panic("encodeR: could not encode instruction")
|
||||
@ -1326,31 +1326,31 @@ func encodeR(as obj.As, rs1, rs2, rd, funct3 uint32) uint32 {
|
||||
if enc.rs2 != 0 && rs2 != 0 {
|
||||
panic("encodeR: instruction uses rs2, but rs2 was nonzero")
|
||||
}
|
||||
return enc.funct7<<25 | enc.rs2<<20 | rs2<<20 | rs1<<15 | enc.funct3<<12 | funct3<<12 | rd<<7 | enc.opcode
|
||||
return funct7<<25 | enc.funct7<<25 | enc.rs2<<20 | rs2<<20 | rs1<<15 | enc.funct3<<12 | funct3<<12 | rd<<7 | enc.opcode
|
||||
}
|
||||
|
||||
func encodeRIII(ins *instruction) uint32 {
|
||||
return encodeR(ins.as, regI(ins.rs1), regI(ins.rs2), regI(ins.rd), ins.funct3)
|
||||
return encodeR(ins.as, regI(ins.rs1), regI(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
|
||||
}
|
||||
|
||||
func encodeRFFF(ins *instruction) uint32 {
|
||||
return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rd), ins.funct3)
|
||||
return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rd), ins.funct3, ins.funct7)
|
||||
}
|
||||
|
||||
func encodeRFFI(ins *instruction) uint32 {
|
||||
return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regI(ins.rd), ins.funct3)
|
||||
return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
|
||||
}
|
||||
|
||||
func encodeRFI(ins *instruction) uint32 {
|
||||
return encodeR(ins.as, regF(ins.rs2), 0, regI(ins.rd), ins.funct3)
|
||||
return encodeR(ins.as, regF(ins.rs2), 0, regI(ins.rd), ins.funct3, ins.funct7)
|
||||
}
|
||||
|
||||
func encodeRIF(ins *instruction) uint32 {
|
||||
return encodeR(ins.as, regI(ins.rs2), 0, regF(ins.rd), ins.funct3)
|
||||
return encodeR(ins.as, regI(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7)
|
||||
}
|
||||
|
||||
func encodeRFF(ins *instruction) uint32 {
|
||||
return encodeR(ins.as, regF(ins.rs2), 0, regF(ins.rd), ins.funct3)
|
||||
return encodeR(ins.as, regF(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7)
|
||||
}
|
||||
|
||||
// encodeI encodes an I-type RISC-V instruction.
|
||||
@ -1585,6 +1585,12 @@ var encodings = [ALAST & obj.AMask]encoding{
|
||||
AREMW & obj.AMask: rIIIEncoding,
|
||||
AREMUW & obj.AMask: rIIIEncoding,
|
||||
|
||||
// 8.2: Load-Reserved/Store-Conditional
|
||||
ALRW & obj.AMask: rIIIEncoding,
|
||||
ALRD & obj.AMask: rIIIEncoding,
|
||||
ASCW & obj.AMask: rIIIEncoding,
|
||||
ASCD & obj.AMask: rIIIEncoding,
|
||||
|
||||
// 10.1: Base Counters and Timers
|
||||
ARDCYCLE & obj.AMask: iIEncoding,
|
||||
ARDTIME & obj.AMask: iIEncoding,
|
||||
@ -1699,6 +1705,7 @@ type instruction struct {
|
||||
rs2 uint32 // Source register 2
|
||||
imm int64 // Immediate
|
||||
funct3 uint32 // Function 3
|
||||
funct7 uint32 // Function 7
|
||||
}
|
||||
|
||||
func (ins *instruction) encode() (uint32, error) {
|
||||
@ -1764,6 +1771,16 @@ func instructionsForProg(p *obj.Prog) []*instruction {
|
||||
ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
|
||||
ins.imm = p.To.Offset
|
||||
|
||||
case ALRW, ALRD:
|
||||
// Set aq to use acquire access ordering, which matches Go's memory requirements.
|
||||
ins.funct7 = 2
|
||||
ins.rs1, ins.rs2 = uint32(p.From.Reg), REG_ZERO
|
||||
|
||||
case ASCW, ASCD:
|
||||
// Set aq to use acquire access ordering, which matches Go's memory requirements.
|
||||
ins.funct7 = 2
|
||||
ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg)
|
||||
|
||||
case AECALL, AEBREAK, ARDCYCLE, ARDTIME, ARDINSTRET:
|
||||
insEnc := encode(p.As)
|
||||
if p.To.Type == obj.TYPE_NONE {
|
||||
|
@ -52,9 +52,9 @@ TEXT ·Cas(SB), NOSPLIT, $0-17
|
||||
MOVW old+8(FP), A1
|
||||
MOVW new+12(FP), A2
|
||||
cas_again:
|
||||
AMOWSC(LR_,13,10,0) // lr.w.aq a3,(a0)
|
||||
LRW (A0), A3
|
||||
BNE A3, A1, cas_fail
|
||||
AMOWSC(SC_,14,10,12) // sc.w.aq a4,a2,(a0)
|
||||
SCW A2, (A0), A4
|
||||
BNE A4, ZERO, cas_again
|
||||
MOV $1, A0
|
||||
MOVB A0, ret+16(FP)
|
||||
@ -70,9 +70,9 @@ TEXT ·Cas64(SB), NOSPLIT, $0-25
|
||||
MOV old+8(FP), A1
|
||||
MOV new+16(FP), A2
|
||||
cas_again:
|
||||
AMODSC(LR_,13,10,0) // lr.d.aq a3,(a0)
|
||||
LRD (A0), A3
|
||||
BNE A3, A1, cas_fail
|
||||
AMODSC(SC_,14,10,12) // sc.d.aq a4,a2,(a0)
|
||||
SCD A2, (A0), A4
|
||||
BNE A4, ZERO, cas_again
|
||||
MOV $1, A0
|
||||
MOVB A0, ret+24(FP)
|
||||
@ -84,7 +84,7 @@ cas_fail:
|
||||
// func Load(ptr *uint32) uint32
|
||||
TEXT ·Load(SB),NOSPLIT|NOFRAME,$0-12
|
||||
MOV ptr+0(FP), A0
|
||||
AMOWSC(LR_,10,10,0)
|
||||
LRW (A0), A0
|
||||
MOVW A0, ret+8(FP)
|
||||
RET
|
||||
|
||||
@ -100,7 +100,7 @@ TEXT ·Load8(SB),NOSPLIT|NOFRAME,$0-9
|
||||
// func Load64(ptr *uint64) uint64
|
||||
TEXT ·Load64(SB),NOSPLIT|NOFRAME,$0-16
|
||||
MOV ptr+0(FP), A0
|
||||
AMODSC(LR_,10,10,0)
|
||||
LRD (A0), A0
|
||||
MOV A0, ret+8(FP)
|
||||
RET
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user