cmd/internal/obj/riscv: use signed immediates for U-instructions
On RISCV64, the U-instructions (AUIPC and LUI) take 20 bits, append 12 bits
of zeros and sign extend to 64-bits. As such, the 20 bit immediate value is
signed not unsigned.
Updates #27532
Change-Id: I725215a1dc500106dbfdc0a4425f3c0b2a6f411e
Reviewed-on: https://go-review.googlesource.com/c/go/+/216257
Reviewed-by: Cherry Zhang <cherryyz@google.com>
diff --git a/src/cmd/asm/internal/asm/testdata/riscvenc.s b/src/cmd/asm/internal/asm/testdata/riscvenc.s
index 3e93199..8a90551 100644
--- a/src/cmd/asm/internal/asm/testdata/riscvenc.s
+++ b/src/cmd/asm/internal/asm/testdata/riscvenc.s
@@ -60,11 +60,13 @@
AUIPC $0, X10 // 17050000
AUIPC $0, X11 // 97050000
AUIPC $1, X10 // 17150000
- AUIPC $1048575, X10 // 17f5ffff
+ AUIPC $-524288, X15 // 97070080
+ AUIPC $524287, X10 // 17f5ff7f
LUI $0, X15 // b7070000
LUI $167, X15 // b7770a00
- LUI $1048575, X15 // b7f7ffff
+ LUI $-524288, X15 // b7070080
+ LUI $524287, X15 // b7f7ff7f
SLL X6, X5, X7 // b3936200
SLL X5, X6 // 33135300
@@ -89,15 +91,15 @@
// to 2 because they transfer control to the second instruction
// in the function (the first instruction being an invisible
// stack pointer adjustment).
- JAL X5, start // JAL X5, 2 // eff2dff0
+ JAL X5, start // JAL X5, 2 // eff25ff0
JALR X6, (X5) // 67830200
JALR X6, 4(X5) // 67834200
- BEQ X5, X6, start // BEQ X5, X6, 2 // e38062f0
- BNE X5, X6, start // BNE X5, X6, 2 // e39e62ee
- BLT X5, X6, start // BLT X5, X6, 2 // e3cc62ee
- BLTU X5, X6, start // BLTU X5, X6, 2 // e3ea62ee
- BGE X5, X6, start // BGE X5, X6, 2 // e3d862ee
- BGEU X5, X6, start // BGEU X5, X6, 2 // e3f662ee
+ BEQ X5, X6, start // BEQ X5, X6, 2 // e38c62ee
+ BNE X5, X6, start // BNE X5, X6, 2 // e39a62ee
+ BLT X5, X6, start // BLT X5, X6, 2 // e3c862ee
+ BLTU X5, X6, start // BLTU X5, X6, 2 // e3e662ee
+ BGE X5, X6, start // BGE X5, X6, 2 // e3d462ee
+ BGEU X5, X6, start // BGEU X5, X6, 2 // e3f262ee
// 2.6: Load and Store Instructions
LW (X5), X6 // 03a30200
@@ -271,7 +273,7 @@
// 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 // 6ff05fcd
+ JMP start // JMP 2 // 6ff0dfcc
JMP (X5) // 67800200
JMP 4(X5) // 67804200
diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go
index 6b36a94..e90769e 100644
--- a/src/cmd/internal/obj/riscv/obj.go
+++ b/src/cmd/internal/obj/riscv/obj.go
@@ -1287,13 +1287,6 @@
return min <= x && x <= max
}
-// immUFits reports whether immediate value x fits in nbits bits
-// as an unsigned integer.
-func immUFits(x int64, nbits uint) bool {
- var max int64 = 1<<nbits - 1
- return 0 <= x && x <= max
-}
-
// immI extracts the signed integer literal of the specified size from an Addr.
func immI(a obj.Addr, nbits uint) uint32 {
if a.Type != obj.TYPE_CONST {
@@ -1305,17 +1298,6 @@
return uint32(a.Offset)
}
-// immU extracts the unsigned integer literal of the specified size from an Addr.
-func immU(a obj.Addr, nbits uint) uint32 {
- if a.Type != obj.TYPE_CONST {
- panic(fmt.Sprintf("ill typed: %+v", a))
- }
- if !immUFits(a.Offset, nbits) {
- panic(fmt.Sprintf("unsigned immediate %d in %v cannot fit in %d bits", a.Offset, a, nbits))
- }
- return uint32(a.Offset)
-}
-
func wantImmI(p *obj.Prog, pos string, a obj.Addr, nbits uint) {
if a.Type != obj.TYPE_CONST {
p.Ctxt.Diag("%v\texpected immediate in %s position but got %s", p, pos, obj.Dconv(p, &a))
@@ -1326,16 +1308,6 @@
}
}
-func wantImmU(p *obj.Prog, pos string, a obj.Addr, nbits uint) {
- if a.Type != obj.TYPE_CONST {
- p.Ctxt.Diag("%v\texpected immediate in %s position but got %s", p, pos, obj.Dconv(p, &a))
- return
- }
- if !immUFits(a.Offset, nbits) {
- p.Ctxt.Diag("%v\tunsigned immediate in %s position cannot be larger than %d bits but got %d", p, pos, nbits, a.Offset)
- }
-}
-
func wantReg(p *obj.Prog, pos string, descr string, r, min, max int16) {
if r < min || r > max {
p.Ctxt.Diag("%v\texpected %s register in %s position but got non-%s register %s", p, descr, pos, descr, RegName(int(r)))
@@ -1457,7 +1429,7 @@
// to represent this state?
return
}
- wantImmU(p, "from", p.From, 20)
+ wantImmI(p, "from", p.From, 20)
wantIntRegAddr(p, "to", &p.To)
}
@@ -1578,7 +1550,7 @@
// Rather than have the user/compiler generate a 32 bit constant, the
// bottommost bits of which must all be zero, instead accept just the
// top bits.
- imm := immU(p.From, 20)
+ imm := immI(p.From, 20)
rd := regIAddr(p.To)
ins := encode(p.As)
if ins == nil {
@@ -1627,7 +1599,7 @@
}
func EncodeUImmediate(imm int64) (int64, error) {
- if !immUFits(imm, 20) {
+ if !immIFits(imm, 20) {
return 0, fmt.Errorf("immediate %#x does not fit in 20 bits", imm)
}
return imm << 12, nil