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