aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmd/asm/internal/asm/testdata/riscv64.s6
-rw-r--r--src/cmd/internal/obj/riscv/obj.go22
-rw-r--r--src/cmd/internal/obj/riscv/obj_test.go7
3 files changed, 26 insertions, 9 deletions
diff --git a/src/cmd/asm/internal/asm/testdata/riscv64.s b/src/cmd/asm/internal/asm/testdata/riscv64.s
index 4615119af0..1b23680e26 100644
--- a/src/cmd/asm/internal/asm/testdata/riscv64.s
+++ b/src/cmd/asm/internal/asm/testdata/riscv64.s
@@ -1993,9 +1993,12 @@ start:
// Converted to load and shift(s)
MOV $0xffffffff, X5 // MOV $4294967295, X5 // 9302f0ff93d20202
+ MOV $0x80000001, X5 // MOV $2147483649, X5 // b70200809b8212009392020293d20202 or b70200809b821200bb820208
MOV $0x100000000, X5 // MOV $4294967296, X5 // 9302100093920202
MOV $0xfffffffffffda, X5 // MOV $4503599627370458, X5 // 9302d0fe9392d20093d2c200
MOV $0xffffffffffffe, X5 // MOV $4503599627370494, X5 // 9302f0ff9392d20093d2c200
+ MOV $0x0800000010000000, X5 // MOV $576460752571858944, X5 // b70200809b8212009392020293d24200
+ MOV $0x0abcdabcd0000000, X5 // MOV $773733740479250432, X5 // b7b2cdab9b82d2bc9392020293d24200
MOV $0x7fffffff00000000, X5 // MOV $9223372032559808512, X5 // b70200809b82f2ff93920202
MOV $0x8000000100000000, X5 // MOV $-9223372032559808512, X5 // b70200809b82120093920202
MOV $0xffffffff00000000, X5 // MOV $-4294967296, X5 // 9302f0ff93920202
@@ -2003,11 +2006,8 @@ start:
MOV $0x7fffffffffffffff, X5 // MOV $9223372036854775807, X5 // 9302f0ff93d21200
// Converted to load of symbol (AUIPC + LD)
- MOV $0x80000001, X5 // MOV $2147483649, X5 // 9702000083b20200
MOV $0x100000001, X5 // MOV $4294967297, X5 // 9702000083b20200
- MOV $0x0800000010000000, X5 // MOV $576460752571858944, X5 // 9702000083b20200
MOV $0x8000000010000000, X5 // MOV $-9223372036586340352, X5 // 9702000083b20200
- MOV $0x0abcdabcd0000000, X5 // MOV $773733740479250432, X5 // 9702000083b20200
MOV $0x8abcdabcd0000000, X5 // MOV $-8449638296375525376, X5 // 9702000083b20200
MOV $0xfff0000000ffffff, X5 // MOV $-4503599610593281, X5 // 9702000083b20200
diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go
index 28bba008f7..5bab0ff419 100644
--- a/src/cmd/internal/obj/riscv/obj.go
+++ b/src/cmd/internal/obj/riscv/obj.go
@@ -3461,19 +3461,28 @@ func splitShiftConst(v int64) (imm int64, lsh int, rsh int, ok bool) {
// See if we can reconstruct this value from a small negative constant.
rsh = bits.LeadingZeros64(uint64(v))
ones := bits.OnesCount64((uint64(v) >> lsh) >> 11)
- c = signExtend(1<<11|((v>>lsh)&0x7ff), 12)
if rsh+ones+lsh+11 == 64 {
+ c = signExtend(1<<11|((v>>lsh)&0x7ff), 12)
if lsh > 0 || c != -1 {
lsh += rsh
}
return c, lsh, rsh, true
}
+ // See if we can reconstruct this value from a zero extended signed
+ // 32 bit integer. This will require four instructions on rva20u64
+ // and three instructions on rva22u64 or higher.
+ if int64(uint32(c)) == c {
+ c = int64(int32(c))
+ lsh, rsh = 32, 32-lsh
+ return c, lsh, rsh, true
+ }
+
return 0, 0, 0, false
}
// isShiftConst indicates whether a constant can be represented as a signed
-// 32 bit integer that is left shifted.
+// 32 bit integer that is left and/or right shifted.
func isShiftConst(v int64) bool {
_, lsh, rsh, ok := splitShiftConst(v)
return ok && (lsh > 0 || rsh > 0)
@@ -3908,10 +3917,14 @@ func instructionsForMOVConst(p *obj.Prog) []*instruction {
// SLLI $13, X10
// SRLI $12, X10
//
- var insSLLI, insSRLI *instruction
+ var insSLLI, insSRLI, insMOVWU *instruction
if err := immIFits(ins.imm, 32); err != nil {
if c, lsh, rsh, ok := splitShiftConst(ins.imm); ok {
ins.imm = c
+ if buildcfg.GORISCV64 >= 22 && lsh == 32 && rsh == 32 {
+ insMOVWU = &instruction{as: AADDUW, rd: ins.rd, rs1: ins.rd, rs2: REG_ZERO}
+ lsh, rsh = 0, 0
+ }
if lsh > 0 {
insSLLI = &instruction{as: ASLLI, rd: ins.rd, rs1: ins.rd, imm: int64(lsh)}
}
@@ -3941,6 +3954,9 @@ func instructionsForMOVConst(p *obj.Prog) []*instruction {
inss = append(inss, ins)
}
}
+ if insMOVWU != nil {
+ inss = append(inss, insMOVWU)
+ }
if insSLLI != nil {
inss = append(inss, insSLLI)
}
diff --git a/src/cmd/internal/obj/riscv/obj_test.go b/src/cmd/internal/obj/riscv/obj_test.go
index 87b31e5a89..d4e7e14db6 100644
--- a/src/cmd/internal/obj/riscv/obj_test.go
+++ b/src/cmd/internal/obj/riscv/obj_test.go
@@ -17,12 +17,13 @@ func TestSplitShiftConst(t *testing.T) {
wantRsh int
wantOk bool
}{
- {0x100000000, 1, 32, 0, true},
- {0xfffff001, 0, 0, 0, false},
+ {0xfffff001, -4095, 32, 32, true},
{0xfffff801, -2047, 32, 32, true},
{0xfffffff1, -15, 32, 32, true},
{0xffffffff, -1, 0, 32, true},
{0xfffffffe, 0x7fffffff, 1, 0, true},
+ {0x80a9b553, -2136361645, 32, 32, true},
+ {0x100000000, 1, 32, 0, true},
{0xfffffffffffda, -19, 13, 12, true},
{0xfffffffffffde, -17, 13, 12, true},
{0x000003ffffffffff, -1, 0, 22, true},
@@ -31,7 +32,7 @@ func TestSplitShiftConst(t *testing.T) {
{0x7fffffffffffffff, -1, 0, 1, true},
{0x7f7f7f7f7f7f7f7f, 0, 0, 0, false},
{0x0080000010000000, 0x8000001, 28, 0, true},
- {0x0abcdabcd0000000, 0, 0, 0, false},
+ {0x0abcdabcd0000000, -1412584499, 32, 4, true},
{-4503599610593281, 0, 0, 0, false}, // 0x8abcdabcd0000000
{-7543254330000000, 0, 0, 0, false}, // 0xfff0000000ffffff
}