diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/cmd/asm/internal/asm/testdata/riscv64.s | 6 | ||||
| -rw-r--r-- | src/cmd/internal/obj/riscv/obj.go | 22 | ||||
| -rw-r--r-- | src/cmd/internal/obj/riscv/obj_test.go | 7 |
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 } |
