cmd/internal/obj/riscv: correctly split immediates for FLW/FLD/FSW/FSD
The FLW/FLD/FSW/FSD instructions can have immediates that exceed 12-bits and
therefore cannot be encoded in the RISCV instruction. Handle these as we do
for other load/store instructions. Also add test coverage for all load/store
instructions with large immediates.
Fixes compilation issue reported by Carlos Eduardo de Paula.
Updates #27532
Change-Id: Ifa62f19493b3acaba5a90ac31d2df209a3afea81
Reviewed-on: https://go-review.googlesource.com/c/go/+/215037
Reviewed-by: Carlos Eduardo de Paula <me@carlosedp.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/cmd/internal/obj/riscv/asm_test.go b/src/cmd/internal/obj/riscv/asm_test.go
index 0fe0caf..849a87b 100644
--- a/src/cmd/internal/obj/riscv/asm_test.go
+++ b/src/cmd/internal/obj/riscv/asm_test.go
@@ -77,3 +77,57 @@
t.Errorf("%v\n%s", err, out)
}
}
+
+func TestImmediateSplitting(t *testing.T) {
+ dir, err := ioutil.TempDir("", "testimmsplit")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(dir)
+ tmpfile := filepath.Join(dir, "x.s")
+ asm := `
+TEXT _stub(SB),$0-0
+ LB 4096(X5), X6
+ LH 4096(X5), X6
+ LW 4096(X5), X6
+ LD 4096(X5), X6
+ LBU 4096(X5), X6
+ LHU 4096(X5), X6
+ LWU 4096(X5), X6
+ SB X6, 4096(X5)
+ SH X6, 4096(X5)
+ SW X6, 4096(X5)
+ SD X6, 4096(X5)
+
+ FLW 4096(X5), F6
+ FLD 4096(X5), F6
+ FSW F6, 4096(X5)
+ FSD F6, 4096(X5)
+
+ MOVB 4096(X5), X6
+ MOVH 4096(X5), X6
+ MOVW 4096(X5), X6
+ MOV 4096(X5), X6
+ MOVBU 4096(X5), X6
+ MOVHU 4096(X5), X6
+ MOVWU 4096(X5), X6
+
+ MOVB X6, 4096(X5)
+ MOVH X6, 4096(X5)
+ MOVW X6, 4096(X5)
+ MOV X6, 4096(X5)
+
+ MOVF 4096(X5), F6
+ MOVD 4096(X5), F6
+ MOVF F6, 4096(X5)
+ MOVD F6, 4096(X5)
+`
+ if err := ioutil.WriteFile(tmpfile, []byte(asm), 0644); err != nil {
+ t.Fatal(err)
+ }
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
+ cmd.Env = append(os.Environ(), "GOARCH=riscv64", "GOOS=linux")
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Errorf("%v\n%s", err, out)
+ }
+}
diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go
index 721908f..2da9512 100644
--- a/src/cmd/internal/obj/riscv/obj.go
+++ b/src/cmd/internal/obj/riscv/obj.go
@@ -716,11 +716,7 @@
// <load> $imm, REG, TO (load $imm+(REG), TO)
// <store> $imm, REG, TO (store $imm+(TO), REG)
- case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU,
- ASD, ASB, ASH, ASW:
- // LUI $high, TMP
- // ADDI $low, TMP, TMP
- q := *p
+ case ALB, ALH, ALW, ALD, ALBU, ALHU, ALWU, AFLW, AFLD, ASB, ASH, ASW, ASD, AFSW, AFSD:
low, high, err := Split32BitImmediate(p.From.Offset)
if err != nil {
ctxt.Diag("%v: constant %d too large", p, p.From.Offset)
@@ -729,8 +725,9 @@
break // no need to split
}
+ q := *p
switch q.As {
- case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU:
+ case ALB, ALH, ALW, ALD, ALBU, ALHU, ALWU, AFLW, AFLD:
// LUI $high, TMP
// ADD TMP, REG, TMP
// <load> $low, TMP, TO
@@ -752,7 +749,7 @@
p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: low}
p.Reg = REG_TMP
- case ASD, ASB, ASH, ASW:
+ case ASB, ASH, ASW, ASD, AFSW, AFSD:
// LUI $high, TMP
// ADD TMP, TO, TMP
// <store> $low, REG, TMP