aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj
diff options
context:
space:
mode:
authorWang Yaduo <wangyaduo@linux.alibaba.com>2024-01-31 10:37:35 +0800
committerM Zhuo <mengzhuo1203@gmail.com>2024-03-20 14:19:33 +0000
commitdb423dde85ad4923c2c4addb1cd96f119c7b6dc6 (patch)
treea930d2d11f3d94cbb9e201b74a9abfa6fe9a8b2e /src/cmd/internal/obj
parente39af550f8ea57504510dc5d5fa70ba934f16fa0 (diff)
downloadgo-db423dde85ad4923c2c4addb1cd96f119c7b6dc6.tar.xz
cmd/internal/obj: support Zba, Zbb, Zbs extensions in riscv64 assembler
Add assembler support for Zba, Zbb, Zbs extensions, which are mandatory in the rva22u64 profile. These can be used to accelerate address computation and bit manipulation. Change-Id: Ie90fe6b76b1382cf69984a0e71a72d3cba0e750a Reviewed-on: https://go-review.googlesource.com/c/go/+/559655 Reviewed-by: M Zhuo <mengzhuo1203@gmail.com> Run-TryBot: Joel Sing <joel@sing.id.au> Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Joel Sing <joel@sing.id.au> Reviewed-by: Keith Randall <khr@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/cmd/internal/obj')
-rw-r--r--src/cmd/internal/obj/riscv/anames.go46
-rw-r--r--src/cmd/internal/obj/riscv/cpu.go58
-rw-r--r--src/cmd/internal/obj/riscv/inst.go84
-rw-r--r--src/cmd/internal/obj/riscv/obj.go90
4 files changed, 258 insertions, 20 deletions
diff --git a/src/cmd/internal/obj/riscv/anames.go b/src/cmd/internal/obj/riscv/anames.go
index e547c6d5e9..60c7b48620 100644
--- a/src/cmd/internal/obj/riscv/anames.go
+++ b/src/cmd/internal/obj/riscv/anames.go
@@ -217,6 +217,46 @@ var Anames = []string{
"DRET",
"WFI",
"SFENCEVMA",
+ "ADDUW",
+ "SH1ADD",
+ "SH1ADDUW",
+ "SH2ADD",
+ "SH2ADDUW",
+ "SH3ADD",
+ "SH3ADDUW",
+ "SLLIUW",
+ "ANDN",
+ "ORN",
+ "XNOR",
+ "CLZ",
+ "CLZW",
+ "CTZ",
+ "CTZW",
+ "CPOP",
+ "CPOPW",
+ "MAX",
+ "MAXU",
+ "MIN",
+ "MINU",
+ "SEXTB",
+ "SEXTH",
+ "ZEXTH",
+ "ROL",
+ "ROLW",
+ "ROR",
+ "RORI",
+ "RORIW",
+ "RORW",
+ "ORCB",
+ "REV8",
+ "BCLR",
+ "BCLRI",
+ "BEXT",
+ "BEXTI",
+ "BINV",
+ "BINVI",
+ "BSET",
+ "BSETI",
"WORD",
"BEQZ",
"BGEZ",
@@ -246,12 +286,6 @@ var Anames = []string{
"NEG",
"NEGW",
"NOT",
- "ROL",
- "ROLW",
- "ROR",
- "RORI",
- "RORIW",
- "RORW",
"SEQZ",
"SNEZ",
"LAST",
diff --git a/src/cmd/internal/obj/riscv/cpu.go b/src/cmd/internal/obj/riscv/cpu.go
index 00513a4a79..43ed3bc1f0 100644
--- a/src/cmd/internal/obj/riscv/cpu.go
+++ b/src/cmd/internal/obj/riscv/cpu.go
@@ -572,6 +572,58 @@ const (
// 4.2.1: Supervisor Memory-Management Fence Instruction
ASFENCEVMA
+ //
+ // RISC-V Bit-Manipulation ISA-extensions (1.0)
+ //
+
+ // 1.1: Address Generation Instructions (Zba)
+ AADDUW
+ ASH1ADD
+ ASH1ADDUW
+ ASH2ADD
+ ASH2ADDUW
+ ASH3ADD
+ ASH3ADDUW
+ ASLLIUW
+
+ // 1.2: Basic Bit Manipulation (Zbb)
+ AANDN
+ AORN
+ AXNOR
+ ACLZ
+ ACLZW
+ ACTZ
+ ACTZW
+ ACPOP
+ ACPOPW
+ AMAX
+ AMAXU
+ AMIN
+ AMINU
+ ASEXTB
+ ASEXTH
+ AZEXTH
+
+ // 1.3: Bitwise Rotation (Zbb)
+ AROL
+ AROLW
+ AROR
+ ARORI
+ ARORIW
+ ARORW
+ AORCB
+ AREV8
+
+ // 1.5: Single-bit Instructions (Zbs)
+ ABCLR
+ ABCLRI
+ ABEXT
+ ABEXTI
+ ABINV
+ ABINVI
+ ABSET
+ ABSETI
+
// The escape hatch. Inserts a single 32-bit word.
AWORD
@@ -605,12 +657,6 @@ const (
ANEG
ANEGW
ANOT
- AROL
- AROLW
- AROR
- ARORI
- ARORIW
- ARORW
ASEQZ
ASNEZ
diff --git a/src/cmd/internal/obj/riscv/inst.go b/src/cmd/internal/obj/riscv/inst.go
index 6cb11cdfb5..223ddd15b2 100644
--- a/src/cmd/internal/obj/riscv/inst.go
+++ b/src/cmd/internal/obj/riscv/inst.go
@@ -1,4 +1,4 @@
-// Code generated by parse.py -go rv64_a rv64_d rv64_f rv64_i rv64_m rv64_q rv_a rv_d rv_f rv_i rv_m rv_q rv_s rv_system rv_zicsr; DO NOT EDIT.
+// Code generated by ./parse.py -go rv64_a rv64_d rv64_f rv64_i rv64_m rv64_q rv64_zba rv64_zbb rv64_zbs rv_a rv_d rv_f rv_i rv_m rv_q rv_zba rv_zbb rv_zbs rv_s rv_system rv_zicsr; DO NOT EDIT.
package riscv
import "cmd/internal/obj"
@@ -15,6 +15,8 @@ func encode(a obj.As) *inst {
switch a {
case AADD:
return &inst{0x33, 0x0, 0x0, 0, 0x0}
+ case AADDUW:
+ return &inst{0x3b, 0x0, 0x0, 128, 0x4}
case AADDI:
return &inst{0x13, 0x0, 0x0, 0, 0x0}
case AADDIW:
@@ -61,20 +63,46 @@ func encode(a obj.As) *inst {
return &inst{0x33, 0x7, 0x0, 0, 0x0}
case AANDI:
return &inst{0x13, 0x7, 0x0, 0, 0x0}
+ case AANDN:
+ return &inst{0x33, 0x7, 0x0, 1024, 0x20}
case AAUIPC:
return &inst{0x17, 0x0, 0x0, 0, 0x0}
+ case ABCLR:
+ return &inst{0x33, 0x1, 0x0, 1152, 0x24}
+ case ABCLRI:
+ return &inst{0x13, 0x1, 0x0, 1152, 0x24}
case ABEQ:
return &inst{0x63, 0x0, 0x0, 0, 0x0}
+ case ABEXT:
+ return &inst{0x33, 0x5, 0x0, 1152, 0x24}
+ case ABEXTI:
+ return &inst{0x13, 0x5, 0x0, 1152, 0x24}
case ABGE:
return &inst{0x63, 0x5, 0x0, 0, 0x0}
case ABGEU:
return &inst{0x63, 0x7, 0x0, 0, 0x0}
+ case ABINV:
+ return &inst{0x33, 0x1, 0x0, 1664, 0x34}
+ case ABINVI:
+ return &inst{0x13, 0x1, 0x0, 1664, 0x34}
case ABLT:
return &inst{0x63, 0x4, 0x0, 0, 0x0}
case ABLTU:
return &inst{0x63, 0x6, 0x0, 0, 0x0}
case ABNE:
return &inst{0x63, 0x1, 0x0, 0, 0x0}
+ case ABSET:
+ return &inst{0x33, 0x1, 0x0, 640, 0x14}
+ case ABSETI:
+ return &inst{0x13, 0x1, 0x0, 640, 0x14}
+ case ACLZ:
+ return &inst{0x13, 0x1, 0x0, 1536, 0x30}
+ case ACLZW:
+ return &inst{0x1b, 0x1, 0x0, 1536, 0x30}
+ case ACPOP:
+ return &inst{0x13, 0x1, 0x2, 1538, 0x30}
+ case ACPOPW:
+ return &inst{0x1b, 0x1, 0x2, 1538, 0x30}
case ACSRRC:
return &inst{0x73, 0x3, 0x0, 0, 0x0}
case ACSRRCI:
@@ -87,6 +115,10 @@ func encode(a obj.As) *inst {
return &inst{0x73, 0x1, 0x0, 0, 0x0}
case ACSRRWI:
return &inst{0x73, 0x5, 0x0, 0, 0x0}
+ case ACTZ:
+ return &inst{0x13, 0x1, 0x1, 1537, 0x30}
+ case ACTZW:
+ return &inst{0x1b, 0x1, 0x1, 1537, 0x30}
case ADIV:
return &inst{0x33, 0x4, 0x0, 32, 0x1}
case ADIVU:
@@ -95,8 +127,6 @@ func encode(a obj.As) *inst {
return &inst{0x3b, 0x5, 0x0, 32, 0x1}
case ADIVW:
return &inst{0x3b, 0x4, 0x0, 32, 0x1}
- case ADRET:
- return &inst{0x73, 0x0, 0x12, 1970, 0x3d}
case AEBREAK:
return &inst{0x73, 0x0, 0x1, 1, 0x0}
case AECALL:
@@ -337,6 +367,14 @@ func encode(a obj.As) *inst {
return &inst{0x3, 0x2, 0x0, 0, 0x0}
case ALWU:
return &inst{0x3, 0x6, 0x0, 0, 0x0}
+ case AMAX:
+ return &inst{0x33, 0x6, 0x0, 160, 0x5}
+ case AMAXU:
+ return &inst{0x33, 0x7, 0x0, 160, 0x5}
+ case AMIN:
+ return &inst{0x33, 0x4, 0x0, 160, 0x5}
+ case AMINU:
+ return &inst{0x33, 0x5, 0x0, 160, 0x5}
case AMRET:
return &inst{0x73, 0x0, 0x2, 770, 0x18}
case AMUL:
@@ -351,8 +389,12 @@ func encode(a obj.As) *inst {
return &inst{0x3b, 0x0, 0x0, 32, 0x1}
case AOR:
return &inst{0x33, 0x6, 0x0, 0, 0x0}
+ case AORCB:
+ return &inst{0x13, 0x5, 0x7, 647, 0x14}
case AORI:
return &inst{0x13, 0x6, 0x0, 0, 0x0}
+ case AORN:
+ return &inst{0x33, 0x6, 0x0, 1024, 0x20}
case APAUSE:
return &inst{0xf, 0x0, 0x10, 16, 0x0}
case ARDCYCLE:
@@ -375,6 +417,20 @@ func encode(a obj.As) *inst {
return &inst{0x3b, 0x7, 0x0, 32, 0x1}
case AREMW:
return &inst{0x3b, 0x6, 0x0, 32, 0x1}
+ case AREV8:
+ return &inst{0x13, 0x5, 0x18, 1720, 0x35}
+ case AROL:
+ return &inst{0x33, 0x1, 0x0, 1536, 0x30}
+ case AROLW:
+ return &inst{0x3b, 0x1, 0x0, 1536, 0x30}
+ case AROR:
+ return &inst{0x33, 0x5, 0x0, 1536, 0x30}
+ case ARORI:
+ return &inst{0x13, 0x5, 0x0, 1536, 0x30}
+ case ARORIW:
+ return &inst{0x1b, 0x5, 0x0, 1536, 0x30}
+ case ARORW:
+ return &inst{0x3b, 0x5, 0x0, 1536, 0x30}
case ASB:
return &inst{0x23, 0x0, 0x0, 0, 0x0}
case ASBREAK:
@@ -387,14 +443,32 @@ func encode(a obj.As) *inst {
return &inst{0x73, 0x0, 0x0, 0, 0x0}
case ASD:
return &inst{0x23, 0x3, 0x0, 0, 0x0}
+ case ASEXTB:
+ return &inst{0x13, 0x1, 0x4, 1540, 0x30}
+ case ASEXTH:
+ return &inst{0x13, 0x1, 0x5, 1541, 0x30}
case ASFENCEVMA:
return &inst{0x73, 0x0, 0x0, 288, 0x9}
case ASH:
return &inst{0x23, 0x1, 0x0, 0, 0x0}
+ case ASH1ADD:
+ return &inst{0x33, 0x2, 0x0, 512, 0x10}
+ case ASH1ADDUW:
+ return &inst{0x3b, 0x2, 0x0, 512, 0x10}
+ case ASH2ADD:
+ return &inst{0x33, 0x4, 0x0, 512, 0x10}
+ case ASH2ADDUW:
+ return &inst{0x3b, 0x4, 0x0, 512, 0x10}
+ case ASH3ADD:
+ return &inst{0x33, 0x6, 0x0, 512, 0x10}
+ case ASH3ADDUW:
+ return &inst{0x3b, 0x6, 0x0, 512, 0x10}
case ASLL:
return &inst{0x33, 0x1, 0x0, 0, 0x0}
case ASLLI:
return &inst{0x13, 0x1, 0x0, 0, 0x0}
+ case ASLLIUW:
+ return &inst{0x1b, 0x1, 0x0, 128, 0x4}
case ASLLIW:
return &inst{0x1b, 0x1, 0x0, 0, 0x0}
case ASLLW:
@@ -433,10 +507,14 @@ func encode(a obj.As) *inst {
return &inst{0x23, 0x2, 0x0, 0, 0x0}
case AWFI:
return &inst{0x73, 0x0, 0x5, 261, 0x8}
+ case AXNOR:
+ return &inst{0x33, 0x4, 0x0, 1024, 0x20}
case AXOR:
return &inst{0x33, 0x4, 0x0, 0, 0x0}
case AXORI:
return &inst{0x13, 0x4, 0x0, 0, 0x0}
+ case AZEXTH:
+ return &inst{0x3b, 0x4, 0x0, 128, 0x4}
}
return nil
}
diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go
index f508adafed..4c5417f754 100644
--- a/src/cmd/internal/obj/riscv/obj.go
+++ b/src/cmd/internal/obj/riscv/obj.go
@@ -60,7 +60,9 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
AADD, AAND, AOR, AXOR, ASLL, ASRL, ASUB, ASRA,
AMUL, AMULH, AMULHU, AMULHSU, AMULW, ADIV, ADIVU, ADIVW, ADIVUW,
AREM, AREMU, AREMW, AREMUW,
- AROL, AROLW, AROR, ARORW, ARORI, ARORIW:
+ AADDUW, ASH1ADD, ASH1ADDUW, ASH2ADD, ASH2ADDUW, ASH3ADD, ASH3ADDUW, ASLLIUW,
+ AANDN, AORN, AXNOR, AMAX, AMAXU, AMIN, AMINU, AROL, AROLW, AROR, ARORW, ARORI, ARORIW,
+ ABCLR, ABCLRI, ABEXT, ABEXTI, ABINV, ABINVI, ABSET, ABSETI:
p.Reg = p.To.Reg
}
}
@@ -91,10 +93,6 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
p.As = ASRAI
case AADDW:
p.As = AADDIW
- case AROR:
- p.As = ARORI
- case ARORW:
- p.As = ARORIW
case ASUBW:
p.As, p.From.Offset = AADDIW, -p.From.Offset
case ASLLW:
@@ -103,6 +101,18 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
p.As = ASRLIW
case ASRAW:
p.As = ASRAIW
+ case AROR:
+ p.As = ARORI
+ case ARORW:
+ p.As = ARORIW
+ case ABCLR:
+ p.As = ABCLRI
+ case ABEXT:
+ p.As = ABEXTI
+ case ABINV:
+ p.As = ABINVI
+ case ABSET:
+ p.As = ABSETI
}
}
@@ -1108,6 +1118,13 @@ func wantEvenOffset(ctxt *obj.Link, ins *instruction, offset int64) {
}
}
+func validateRII(ctxt *obj.Link, ins *instruction) {
+ wantIntReg(ctxt, ins, "rd", ins.rd)
+ wantIntReg(ctxt, ins, "rs1", ins.rs1)
+ wantNoneReg(ctxt, ins, "rs2", ins.rs2)
+ wantNoneReg(ctxt, ins, "rs3", ins.rs3)
+}
+
func validateRIII(ctxt *obj.Link, ins *instruction) {
wantIntReg(ctxt, ins, "rd", ins.rd)
wantIntReg(ctxt, ins, "rs1", ins.rs1)
@@ -1261,6 +1278,10 @@ func encodeR4(as obj.As, rs1, rs2, rs3, rd, funct3, funct2 uint32) uint32 {
return rs3<<27 | funct2<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | funct3<<12 | rd<<7 | enc.opcode
}
+func encodeRII(ins *instruction) uint32 {
+ return encodeR(ins.as, regI(ins.rs1), 0, regI(ins.rd), ins.funct3, ins.funct7)
+}
+
func encodeRIII(ins *instruction) uint32 {
return encodeR(ins.as, regI(ins.rs1), regI(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
}
@@ -1492,6 +1513,7 @@ var (
// indicates an S-type instruction with rs2 being a float register.
rIIIEncoding = encoding{encode: encodeRIII, validate: validateRIII, length: 4}
+ rIIEncoding = encoding{encode: encodeRII, validate: validateRII, length: 4}
rFFFEncoding = encoding{encode: encodeRFFF, validate: validateRFFF, length: 4}
rFFFFEncoding = encoding{encode: encodeRFFFF, validate: validateRFFFF, length: 4}
rFFIEncoding = encoding{encode: encodeRFFI, validate: validateRFFI, length: 4}
@@ -1724,6 +1746,58 @@ var encodings = [ALAST & obj.AMask]encoding{
AECALL & obj.AMask: iIEncoding,
AEBREAK & obj.AMask: iIEncoding,
+ //
+ // RISC-V Bit-Manipulation ISA-extensions (1.0)
+ //
+
+ // 1.1: Address Generation Instructions (Zba)
+ AADDUW & obj.AMask: rIIIEncoding,
+ ASH1ADD & obj.AMask: rIIIEncoding,
+ ASH1ADDUW & obj.AMask: rIIIEncoding,
+ ASH2ADD & obj.AMask: rIIIEncoding,
+ ASH2ADDUW & obj.AMask: rIIIEncoding,
+ ASH3ADD & obj.AMask: rIIIEncoding,
+ ASH3ADDUW & obj.AMask: rIIIEncoding,
+ ASLLIUW & obj.AMask: iIEncoding,
+
+ // 1.2: Basic Bit Manipulation (Zbb)
+ AANDN & obj.AMask: rIIIEncoding,
+ ACLZ & obj.AMask: rIIEncoding,
+ ACLZW & obj.AMask: rIIEncoding,
+ ACPOP & obj.AMask: rIIEncoding,
+ ACPOPW & obj.AMask: rIIEncoding,
+ ACTZ & obj.AMask: rIIEncoding,
+ ACTZW & obj.AMask: rIIEncoding,
+ AMAX & obj.AMask: rIIIEncoding,
+ AMAXU & obj.AMask: rIIIEncoding,
+ AMIN & obj.AMask: rIIIEncoding,
+ AMINU & obj.AMask: rIIIEncoding,
+ AORN & obj.AMask: rIIIEncoding,
+ ASEXTB & obj.AMask: rIIEncoding,
+ ASEXTH & obj.AMask: rIIEncoding,
+ AXNOR & obj.AMask: rIIIEncoding,
+ AZEXTH & obj.AMask: rIIEncoding,
+
+ // 1.3: Bitwise Rotation (Zbb)
+ AROL & obj.AMask: rIIIEncoding,
+ AROLW & obj.AMask: rIIIEncoding,
+ AROR & obj.AMask: rIIIEncoding,
+ ARORI & obj.AMask: iIEncoding,
+ ARORIW & obj.AMask: iIEncoding,
+ ARORW & obj.AMask: rIIIEncoding,
+ AORCB & obj.AMask: iIEncoding,
+ AREV8 & obj.AMask: iIEncoding,
+
+ // 1.5: Single-bit Instructions (Zbs)
+ ABCLR & obj.AMask: rIIIEncoding,
+ ABCLRI & obj.AMask: iIEncoding,
+ ABEXT & obj.AMask: rIIIEncoding,
+ ABEXTI & obj.AMask: iIEncoding,
+ ABINV & obj.AMask: rIIIEncoding,
+ ABINVI & obj.AMask: iIEncoding,
+ ABSET & obj.AMask: rIIIEncoding,
+ ABSETI & obj.AMask: iIEncoding,
+
// Escape hatch
AWORD & obj.AMask: rawEncoding,
@@ -2421,6 +2495,12 @@ func instructionsForProg(p *obj.Prog) []*instruction {
if ins.imm < 0 || ins.imm > 31 {
p.Ctxt.Diag("%v: shift amount out of range 0 to 31", p)
}
+
+ case ACLZ, ACLZW, ACTZ, ACTZW, ACPOP, ACPOPW, ASEXTB, ASEXTH, AZEXTH:
+ ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
+
+ case AORCB, AREV8:
+ ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
}
for _, ins := range inss {