diff options
| author | Joel Sing <joel@sing.id.au> | 2024-02-08 13:54:10 +1100 |
|---|---|---|
| committer | Joel Sing <joel@sing.id.au> | 2024-03-07 14:57:07 +0000 |
| commit | 997636760e2d981bb2f5ba486e0702e60a07ba16 (patch) | |
| tree | f4272eb6f8f4bd67d8b8c73e857f09233419a412 /src/cmd/internal/obj | |
| parent | 58052fe8e707cc0285cffb239bc7a5343243e316 (diff) | |
| download | go-997636760e2d981bb2f5ba486e0702e60a07ba16.tar.xz | |
cmd/compile,cmd/internal/obj: provide rotation pseudo-instructions for riscv64
Provide and use rotation pseudo-instructions for riscv64. The RISC-V bitmanip
extension adds support for hardware rotation instructions in the form of ROL,
ROLW, ROR, RORI, RORIW and RORW. These are easily implemented in the assembler
as pseudo-instructions for CPUs that do not support the bitmanip extension.
This approach provides a number of advantages, including reducing the rewrite
rules needed in the compiler, simplifying codegen tests and most importantly,
allowing these instructions to be used in assembly (for example, riscv64
optimised versions of SHA-256 and SHA-512). When bitmanip support is added,
these instruction sequences can simply be replaced with a single instruction
if permitted by the GORISCV64 profile.
Change-Id: Ia23402e1a82f211ac760690deb063386056ae1fa
Reviewed-on: https://go-review.googlesource.com/c/go/+/565015
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: M Zhuo <mengzhuo1203@gmail.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Run-TryBot: Joel Sing <joel@sing.id.au>
Diffstat (limited to 'src/cmd/internal/obj')
| -rw-r--r-- | src/cmd/internal/obj/riscv/anames.go | 6 | ||||
| -rw-r--r-- | src/cmd/internal/obj/riscv/cpu.go | 6 | ||||
| -rw-r--r-- | src/cmd/internal/obj/riscv/obj.go | 51 |
3 files changed, 62 insertions, 1 deletions
diff --git a/src/cmd/internal/obj/riscv/anames.go b/src/cmd/internal/obj/riscv/anames.go index d2c41971b8..e547c6d5e9 100644 --- a/src/cmd/internal/obj/riscv/anames.go +++ b/src/cmd/internal/obj/riscv/anames.go @@ -246,6 +246,12 @@ 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 919f07b1a9..00513a4a79 100644 --- a/src/cmd/internal/obj/riscv/cpu.go +++ b/src/cmd/internal/obj/riscv/cpu.go @@ -605,6 +605,12 @@ const ( ANEG ANEGW ANOT + AROL + AROLW + AROR + ARORI + ARORIW + ARORW ASEQZ ASNEZ diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 3ec740f85a..f508adafed 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -59,7 +59,8 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { AADDIW, ASLLIW, ASRLIW, ASRAIW, AADDW, ASUBW, ASLLW, ASRLW, ASRAW, AADD, AAND, AOR, AXOR, ASLL, ASRL, ASUB, ASRA, AMUL, AMULH, AMULHU, AMULHSU, AMULW, ADIV, ADIVU, ADIVW, ADIVUW, - AREM, AREMU, AREMW, AREMUW: + AREM, AREMU, AREMW, AREMUW, + AROL, AROLW, AROR, ARORW, ARORI, ARORIW: p.Reg = p.To.Reg } } @@ -90,6 +91,10 @@ 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: @@ -2193,6 +2198,47 @@ func instructionsForMOV(p *obj.Prog) []*instruction { return inss } +// instructionsForRotate returns the machine instructions for a bitwise rotation. +func instructionsForRotate(p *obj.Prog, ins *instruction) []*instruction { + switch ins.as { + case AROL, AROLW, AROR, ARORW: + // ROL -> OR (SLL x y) (SRL x (NEG y)) + // ROR -> OR (SRL x y) (SLL x (NEG y)) + sllOp, srlOp := ASLL, ASRL + if ins.as == AROLW || ins.as == ARORW { + sllOp, srlOp = ASLLW, ASRLW + } + shift1, shift2 := sllOp, srlOp + if ins.as == AROR || ins.as == ARORW { + shift1, shift2 = shift2, shift1 + } + return []*instruction{ + &instruction{as: ASUB, rs1: REG_ZERO, rs2: ins.rs2, rd: REG_TMP}, + &instruction{as: shift2, rs1: ins.rs1, rs2: REG_TMP, rd: REG_TMP}, + &instruction{as: shift1, rs1: ins.rs1, rs2: ins.rs2, rd: ins.rd}, + &instruction{as: AOR, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd}, + } + + case ARORI, ARORIW: + // ROR -> OR (SLLI -x y) (SRLI x y) + sllOp, srlOp := ASLLI, ASRLI + sllImm := int64(int8(-ins.imm) & 63) + if ins.as == ARORIW { + sllOp, srlOp = ASLLIW, ASRLIW + sllImm = int64(int8(-ins.imm) & 31) + } + return []*instruction{ + &instruction{as: srlOp, rs1: ins.rs1, rd: REG_TMP, imm: ins.imm}, + &instruction{as: sllOp, rs1: ins.rs1, rd: ins.rd, imm: sllImm}, + &instruction{as: AOR, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd}, + } + + default: + p.Ctxt.Diag("%v: unknown rotation", p) + return nil + } +} + // instructionsForProg returns the machine instructions for an *obj.Prog. func instructionsForProg(p *obj.Prog) []*instruction { ins := instructionForProg(p) @@ -2363,6 +2409,9 @@ func instructionsForProg(p *obj.Prog) []*instruction { ins.as = AFSGNJND ins.rs1 = uint32(p.From.Reg) + case AROL, AROLW, AROR, ARORW, ARORI, ARORIW: + inss = instructionsForRotate(p, ins) + case ASLLI, ASRLI, ASRAI: if ins.imm < 0 || ins.imm > 63 { p.Ctxt.Diag("%v: shift amount out of range 0 to 63", p) |
