fix(asm): read the arm64 move-wide immediate as an unsigned pattern
Assisted-by: GLM 5.3 Flash
This commit is contained in:
+14
-14
@@ -3069,29 +3069,29 @@ func encodeARM64MoveWide(mnem string, baseOp uint32, ops []*ast.Operand) ([]byte
|
||||
// base, so MOVZ and MOVN come along for free.
|
||||
opc := baseOp >> 29 & 3
|
||||
sf := baseOp >> 31 & 1
|
||||
v := arm64Imm64(ops[0])
|
||||
if v < 0 {
|
||||
return nil, fmt.Errorf("%s: negative immediate %d", mnem, v)
|
||||
// The toolchain's optab case 33, shared by the whole family in both
|
||||
// widths: the immediate is one unsigned 64-bit pattern (a high-lane
|
||||
// constant such as $(40000<<48) arrives negative through int64
|
||||
// folding), it must occupy exactly one 16-bit lane, zero is rejected,
|
||||
// and the W forms cannot reach the top half.
|
||||
u := uint64(arm64Imm64(ops[0]))
|
||||
if u == 0 {
|
||||
return nil, fmt.Errorf("%s: zero immediate cannot be handled", mnem)
|
||||
}
|
||||
hw := -1
|
||||
for i := range 4 {
|
||||
if v>>(uint(i)*16)&0xFFFF != 0 {
|
||||
hw = i
|
||||
for lane := range 4 {
|
||||
if u&^(uint64(0xFFFF)<<(lane*16)) == 0 {
|
||||
hw = lane
|
||||
break
|
||||
}
|
||||
}
|
||||
if hw < 0 {
|
||||
hw = 0 // zero: every chunk is zero, hw = 0 carries it
|
||||
}
|
||||
for i := hw + 1; i < 4; i++ {
|
||||
if v>>(uint(i)*16)&0xFFFF != 0 {
|
||||
return nil, fmt.Errorf("%s: immediate %d does not fit one 16-bit chunk", mnem, v)
|
||||
}
|
||||
return nil, fmt.Errorf("%s: immediate %#x does not fit one 16-bit chunk", mnem, u)
|
||||
}
|
||||
if sf == 0 && hw > 1 {
|
||||
return nil, fmt.Errorf("%s: immediate %d out of range for the 32-bit form", mnem, v)
|
||||
return nil, fmt.Errorf("%s: immediate %#x out of range for the 32-bit form", mnem, u)
|
||||
}
|
||||
return a64wordLE(a64MoveWide(sf, opc, uint32(hw), uint32(v>>uint(hw*16)&0xFFFF), uint32(rd))), nil
|
||||
return a64wordLE(a64MoveWide(sf, opc, uint32(hw), uint32(u>>uint(hw*16)&0xFFFF), uint32(rd))), nil
|
||||
}
|
||||
|
||||
// ---- Bitfield/EXTR encoding ----
|
||||
|
||||
Reference in New Issue
Block a user