]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/riscv: use signed immediates for U-instructions
authorJoel Sing <joel@sing.id.au>
Wed, 22 Jan 2020 16:38:31 +0000 (03:38 +1100)
committerJoel Sing <joel@sing.id.au>
Tue, 28 Jan 2020 02:39:28 +0000 (02:39 +0000)
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>
src/cmd/asm/internal/asm/testdata/riscvenc.s
src/cmd/internal/obj/riscv/obj.go

index 3e9319954bead9b7c5c9e411bcdff5878a6f65f5..8a905514db87d954d6e1e23841d331ed6475260c 100644 (file)
@@ -60,11 +60,13 @@ start:
        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 @@ start:
        // 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 @@ start:
        // 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
 
index 6b36a94daaa613c956c8b12da1b90cdd399e2831..e90769eb20e099284015672dfb614b1caf2e06a5 100644 (file)
@@ -1287,13 +1287,6 @@ func immIFits(x int64, nbits uint) bool {
        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 @@ func immI(a obj.Addr, nbits uint) uint32 {
        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 wantImmI(p *obj.Prog, pos string, a obj.Addr, nbits uint) {
        }
 }
 
-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 @@ func validateU(p *obj.Prog) {
                // 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 @@ func encodeU(p *obj.Prog) uint32 {
        // 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 EncodeSImmediate(imm int64) (int64, error) {
 }
 
 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