cmd/internal/obj/loong64: change the immediate range of ALSL{W/WU/V}

When executing the alsl.w/wu/d family of instructions, the actual shift amount is the immediate value
in the instruction encoding plus one. Therefore, this change is made to align the immediate value
in the assembly code with the programmer's intended shift amount, and to include the result of
the immediate value minus one in the final encoding.

Change-Id: Ic82249251878eabde8372e183d841a03f963f9f9
Reviewed-on: https://go-review.googlesource.com/c/go/+/693475
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Mark Freeman <markfreeman@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: abner chenc <chenguoqi@loongson.cn>
Reviewed-by: sophie zhao <zhaoxiaolin@loongson.cn>
This commit is contained in:
limeidan 2025-08-06 14:57:39 +08:00 committed by abner chenc
parent f3606b0825
commit 73ff6d1480
3 changed files with 30 additions and 5 deletions

View file

@ -1101,6 +1101,6 @@ lable2:
XVBITREVV $63, X2, X1 // 41fc1977
// ALSL{W/WU/D}
ALSLW $3, R4, R5, R6 // 86940500
ALSLWU $3, R4, R5, R6 // 86940700
ALSLV $3, R4, R5, R6 // 86942d00
ALSLW $4, R4, R5, R6 // 86940500
ALSLWU $4, R4, R5, R6 // 86940700
ALSLV $4, R4, R5, R6 // 86942d00

View file

@ -425,7 +425,7 @@ var optab = []Optab{
{APRELD, C_SOREG, C_U5CON, C_NONE, C_NONE, C_NONE, 47, 4, 0, 0},
{APRELDX, C_SOREG, C_DCON, C_U5CON, C_NONE, C_NONE, 48, 20, 0, 0},
{AALSLV, C_U2CON, C_REG, C_REG, C_REG, C_NONE, 64, 4, 0, 0},
{AALSLV, C_U3CON, C_REG, C_REG, C_REG, C_NONE, 64, 4, 0, 0},
{obj.APCALIGN, C_U12CON, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
{obj.APCDATA, C_32CON, C_NONE, C_NONE, C_32CON, C_NONE, 0, 0, 0, 0},
@ -2742,8 +2742,12 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 = OP_RR(c.oprr(p.As), uint32(p.To.Reg), uint32(p.RegTo2))
case 64: // alsl rd, rj, rk, sa2
sa := p.From.Offset - 1
if sa > 3 {
c.ctxt.Diag("The shift amount is too large.")
}
r := p.GetFrom3().Reg
o1 = OP_2IRRR(c.opirrr(p.As), uint32(p.From.Offset), uint32(r), uint32(p.Reg), uint32(p.To.Reg))
o1 = OP_2IRRR(c.opirrr(p.As), uint32(sa), uint32(r), uint32(p.Reg), uint32(p.To.Reg))
case 65: // mov sym@GOT, r ==> pcalau12i + ld.d
o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(p.To.Reg))

View file

@ -268,6 +268,27 @@ Note: In the following sections 3.1 to 3.6, "ui4" (4-bit unsigned int immediate)
bits[11:1]: block size, the value range is [16, 1024], and it must be an integer multiple of 16
bits[20:12]: block num, the value range is [1, 256]
bits[36:21]: stride, the value range is [0, 0xffff]
4. ShiftAdd instructions
Mapping between Go and platform assembly:
Go assembly | platform assembly
ALSL.W/WU/V $Imm, Rj, Rk, Rd | alsl.w/wu/d rd, rj, rk, $imm
Instruction encoding format is as follows:
| 31 ~ 17 | 16 ~ 15 | 14 ~ 10 | 9 ~ 5 | 4 ~ 0 |
| opcode | sa2 | rk | rj | rd |
The alsl.w/wu/v series of instructions shift the data in rj left by sa+1, add the value
in rk, and write the result to rd.
To allow programmers to directly write the desired shift amount in assembly code, we actually write
the value of sa2+1 in the assembly code and then include the value of sa2 in the instruction encoding.
For example:
Go assembly | instruction Encoding
ALSLV $4, r4, r5, R6 | 002d9486
*/
package loong64