mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/internal/obj/loong64: add atomic memory access instructions support
The AM* atomic access instruction performs a sequence of “read-modify-write”
operations on a memory cell atomically. Specifically, it retrieves the old
value at the specified address in memory and writes it to the general register
rd, performs some simple operations on the old value in memory and the value
in the general register rk, and then write the result of the operation back
to the memory address pointed to by general register rj.
Go asm syntax:
AM{SWAP/ADD/AND/OR/XOR/MAX/MIN}[DB]{W/V} RK, (RJ), RD
AM{MAX/MIN}[DB]{WU/VU} RK, (RJ), RD
Equivalent platform assembler syntax:
am{swap/add/and/or/xor/max/min}[_db].{w/d} rd, rk, rj
am{max/min}[_db].{wu/du} rd, rk, rj
Ref: https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html
Change-Id: I99ea4553ae731675180d63691c19ef334e7e7817
Reviewed-on: https://go-review.googlesource.com/c/go/+/481577
Reviewed-by: Meidan Li <limeidan@loongson.cn>
Reviewed-by: sophie zhao <zhaoxiaolin@loongson.cn>
Reviewed-by: Mauri de Souza Meneguzzo <mauri870@gmail.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Qiqi Huang <huangqiqi@loongson.cn>
Reviewed-by: WANG Xuerui <git@xen0n.name>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
parent
ca17bda856
commit
504212bbd7
6 changed files with 241 additions and 4 deletions
|
|
@ -356,7 +356,7 @@ var optab = []Optab{
|
|||
{ATEQ, C_SCON, C_NONE, C_NONE, C_REG, C_NONE, 15, 8, 0, 0},
|
||||
|
||||
{ARDTIMELW, C_NONE, C_NONE, C_NONE, C_REG, C_REG, 62, 4, 0, 0},
|
||||
|
||||
{AAMSWAPW, C_REG, C_NONE, C_NONE, C_ZOREG, C_REG, 66, 4, 0, 0},
|
||||
{ANOOP, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 49, 4, 0, 0},
|
||||
|
||||
{obj.APCALIGN, C_SCON, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
|
||||
|
|
@ -374,6 +374,63 @@ var optab = []Optab{
|
|||
{obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0},
|
||||
}
|
||||
|
||||
var atomicInst = map[obj.As]uint32{
|
||||
AAMSWAPB: 0x070B8 << 15, // amswap.b
|
||||
AAMSWAPH: 0x070B9 << 15, // amswap.h
|
||||
AAMSWAPW: 0x070C0 << 15, // amswap.w
|
||||
AAMSWAPV: 0x070C1 << 15, // amswap.d
|
||||
AAMCASB: 0x070B0 << 15, // amcas.b
|
||||
AAMCASH: 0x070B1 << 15, // amcas.h
|
||||
AAMCASW: 0x070B2 << 15, // amcas.w
|
||||
AAMCASV: 0x070B3 << 15, // amcas.d
|
||||
AAMADDW: 0x070C2 << 15, // amadd.w
|
||||
AAMADDV: 0x070C3 << 15, // amadd.d
|
||||
AAMANDW: 0x070C4 << 15, // amand.w
|
||||
AAMANDV: 0x070C5 << 15, // amand.d
|
||||
AAMORW: 0x070C6 << 15, // amor.w
|
||||
AAMORV: 0x070C7 << 15, // amor.d
|
||||
AAMXORW: 0x070C8 << 15, // amxor.w
|
||||
AAMXORV: 0x070C9 << 15, // amxor.d
|
||||
AAMMAXW: 0x070CA << 15, // ammax.w
|
||||
AAMMAXV: 0x070CB << 15, // ammax.d
|
||||
AAMMINW: 0x070CC << 15, // ammin.w
|
||||
AAMMINV: 0x070CD << 15, // ammin.d
|
||||
AAMMAXWU: 0x070CE << 15, // ammax.wu
|
||||
AAMMAXVU: 0x070CF << 15, // ammax.du
|
||||
AAMMINWU: 0x070D0 << 15, // ammin.wu
|
||||
AAMMINVU: 0x070D1 << 15, // ammin.du
|
||||
AAMSWAPDBB: 0x070BC << 15, // amswap_db.b
|
||||
AAMSWAPDBH: 0x070BD << 15, // amswap_db.h
|
||||
AAMSWAPDBW: 0x070D2 << 15, // amswap_db.w
|
||||
AAMSWAPDBV: 0x070D3 << 15, // amswap_db.d
|
||||
AAMCASDBB: 0x070B4 << 15, // amcas_db.b
|
||||
AAMCASDBH: 0x070B5 << 15, // amcas_db.h
|
||||
AAMCASDBW: 0x070B6 << 15, // amcas_db.w
|
||||
AAMCASDBV: 0x070B7 << 15, // amcas_db.d
|
||||
AAMADDDBW: 0x070D4 << 15, // amadd_db.w
|
||||
AAMADDDBV: 0x070D5 << 15, // amadd_db.d
|
||||
AAMANDDBW: 0x070D6 << 15, // amand_db.w
|
||||
AAMANDDBV: 0x070D7 << 15, // amand_db.d
|
||||
AAMORDBW: 0x070D8 << 15, // amor_db.w
|
||||
AAMORDBV: 0x070D9 << 15, // amor_db.d
|
||||
AAMXORDBW: 0x070DA << 15, // amxor_db.w
|
||||
AAMXORDBV: 0x070DB << 15, // amxor_db.d
|
||||
AAMMAXDBW: 0x070DC << 15, // ammax_db.w
|
||||
AAMMAXDBV: 0x070DD << 15, // ammax_db.d
|
||||
AAMMINDBW: 0x070DE << 15, // ammin_db.w
|
||||
AAMMINDBV: 0x070DF << 15, // ammin_db.d
|
||||
AAMMAXDBWU: 0x070E0 << 15, // ammax_db.wu
|
||||
AAMMAXDBVU: 0x070E1 << 15, // ammax_db.du
|
||||
AAMMINDBWU: 0x070E2 << 15, // ammin_db.wu
|
||||
AAMMINDBVU: 0x070E3 << 15, // ammin_db.du
|
||||
}
|
||||
|
||||
func IsAtomicInst(as obj.As) bool {
|
||||
_, ok := atomicInst[as]
|
||||
|
||||
return ok
|
||||
}
|
||||
|
||||
// pcAlignPadLength returns the number of bytes required to align pc to alignedValue,
|
||||
// reporting an error if alignedValue is not a power of two or is out of range.
|
||||
func pcAlignPadLength(ctxt *obj.Link, pc int64, alignedValue int64) int {
|
||||
|
|
@ -1182,6 +1239,14 @@ func buildop(ctxt *obj.Link) {
|
|||
|
||||
case ANOOP:
|
||||
opset(obj.AUNDEF, r0)
|
||||
|
||||
case AAMSWAPW:
|
||||
for i := range atomicInst {
|
||||
if i == AAMSWAPW {
|
||||
continue
|
||||
}
|
||||
opset(i, r0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1817,6 +1882,18 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
|||
rel2.Sym = p.From.Sym
|
||||
rel2.Type = objabi.R_LOONG64_GOT_LO
|
||||
rel2.Add = 0x0
|
||||
|
||||
case 66: // am* From, To, RegTo2 ==> am* RegTo2, From, To
|
||||
rk := p.From.Reg
|
||||
rj := p.To.Reg
|
||||
rd := p.RegTo2
|
||||
|
||||
// See section 2.2.7.1 of https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html
|
||||
// for the register usage constraints.
|
||||
if rd == rj || rd == rk {
|
||||
c.ctxt.Diag("illegal register combination: %v\n", p)
|
||||
}
|
||||
o1 = OP_RRR(atomicInst[p.As], uint32(rk), uint32(rj), uint32(rd))
|
||||
}
|
||||
|
||||
out[0] = o1
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue