From: eric fang Date: Tue, 18 Jul 2023 06:50:49 +0000 (+0000) Subject: cmd/asm: Fix encoding error of register offset shifted by 0 on arm64 X-Git-Tag: go1.22rc1~1544 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=02482a546fd7d626427ce336a4622b90d82c14d1;p=gostls13.git cmd/asm: Fix encoding error of register offset shifted by 0 on arm64 The following instruction is wrongly encoded on arm64: MOVD (R2)(R3<<0), R1 It's incorrectly encoded as MOVD (R2)(R3<<3), R1 The reason for the error is that we hard-coded the shift encoding to 6, which is correct for the MOVB and MOVBU instructions because it only allows a shift amount of 0, but it is wrong for the MOVD instruction because it also allows other shift values. For instructions MOVB, MOVBU and FMOVB, the extension amount must be 0, encoded in "S" as 0 if omitted, or as 1 if present. But in Go, we don't distinguish between Rn. and Rn.<<0, so we encode it as that does not present. This makes no difference to the function of the instruction. Change-Id: I2afe3498392cc9b2ecd524c7744f28b9d6d107b8 Reviewed-on: https://go-review.googlesource.com/c/go/+/510995 Reviewed-by: Heschi Kreinick Reviewed-by: Cherry Mui Run-TryBot: Eric Fang TryBot-Result: Gopher Robot --- diff --git a/src/cmd/asm/internal/asm/testdata/arm64.s b/src/cmd/asm/internal/asm/testdata/arm64.s index 11bd678552..2c7d638319 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64.s +++ b/src/cmd/asm/internal/asm/testdata/arm64.s @@ -595,6 +595,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8 MOVD (R3)(R6*1), R5 // 656866f8 MOVD (R2)(R6), R4 // 446866f8 MOVWU (R19)(R20<<2), R20 // 747a74b8 + MOVD (R2)(R3<<0), R1 // 416863f8 MOVD (R2)(R6<<3), R4 // 447866f8 MOVD (R3)(R7.SXTX<<3), R8 // 68f867f8 MOVWU (R5)(R4.UXTW), R10 // aa4864b8 @@ -604,7 +605,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8 MOVHU (R1)(R2<<1), R5 // 25786278 MOVB (R9)(R3.UXTW), R6 // 2649a338 MOVB (R10)(R6), R15 // 4f69a638 - MOVB (R29)(R30<<0), R14 // ae7bbe38 + MOVB (R29)(R30<<0), R14 // ae6bbe38 MOVB (R29)(R30), R14 // ae6bbe38 MOVH (R5)(R7.SXTX<<1), R19 // b3f8a778 MOVH (R8)(R4<<1), R10 // 0a79a478 diff --git a/src/cmd/asm/internal/asm/testdata/arm64enc.s b/src/cmd/asm/internal/asm/testdata/arm64enc.s index 7ef3a7f5f0..cc002a1584 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64enc.s +++ b/src/cmd/asm/internal/asm/testdata/arm64enc.s @@ -186,7 +186,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8 MOVBU.P 42(R2), R12 // 4ca44238 MOVBU.W -27(R2), R14 // 4e5c5e38 MOVBU 2916(R24), R3 // 03936d39 - MOVBU (R19)(R14<<0), R23 // 777a6e38 + MOVBU (R19)(R14<<0), R23 // 776a6e38 MOVBU (R2)(R8.SXTX), R19 // 53e86838 MOVBU (R27)(R23), R14 // 6e6b7738 MOVHU.P 107(R14), R13 // cdb54678 diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index ff8daad857..2ee7b0f6c6 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -7601,6 +7601,11 @@ func (c *ctxt7) encRegShiftOrExt(p *obj.Prog, a *obj.Addr, r int16) uint32 { case REG_UXTW <= r && r < REG_UXTX: if a.Type == obj.TYPE_MEM { if num == 0 { + // According to the arm64 specification, for instructions MOVB, MOVBU and FMOVB, + // the extension amount must be 0, encoded in "S" as 0 if omitted, or as 1 if present. + // But in Go, we don't distinguish between Rn.UXTW and Rn.UXTW<<0, so we encode it as + // that does not present. This makes no difference to the function of the instruction. + // This is also true for extensions LSL, SXTW and SXTX. return roff(rm, 2, 2) } else { return roff(rm, 2, 6) @@ -7636,7 +7641,11 @@ func (c *ctxt7) encRegShiftOrExt(p *obj.Prog, a *obj.Addr, r int16) uint32 { } case REG_LSL <= r && r < REG_ARNG: if a.Type == obj.TYPE_MEM { // (R1)(R2<<1) - return roff(rm, 3, 6) + if num == 0 { + return roff(rm, 3, 2) + } else { + return roff(rm, 3, 6) + } } else if isADDWop(p.As) { return roff(rm, 2, num) }