fix(asm): reject the arm64 REGTMP spellings the toolchain refuses
Assisted-by: GLM 5.3
This commit is contained in:
1 parent
2385bb7069
commit
7a69be8b59
3 files changed
+88
-14
No files matched your search
+42
-7
@@ -980,9 +980,13 @@ func encodeARM64DPSR(mnem string, baseOp uint32, ops []*ast.Operand) ([]byte, er
|
||||
}
|
||||
// Beyond the bitmask immediates, and for the ZR destinations, the
|
||||
// toolchain materialises the constant into REGTMP and uses the
|
||||
// register form (asm7.go cases 62 and 13). BIC/ORN/EON read the
|
||||
// written value, so the materialisation uses v before any
|
||||
// inversion.
|
||||
// register form (asm7.go cases 62 and 13). A REGTMP source
|
||||
// register is refused, the materialisation clobbering it before
|
||||
// the register form reads it. BIC/ORN/EON read the written
|
||||
// value, so the materialisation uses v before any inversion.
|
||||
if rn == 27 {
|
||||
return nil, fmt.Errorf("%s: cannot use REGTMP as source", mnem)
|
||||
}
|
||||
written := v
|
||||
if inverted {
|
||||
written = ^v
|
||||
@@ -1515,7 +1519,12 @@ func arm64AddSubImmWords(mnem string, v int64, rn, rd int, ext bool) ([]uint32,
|
||||
// Constant into REGTMP (R27), then the register form. The first word
|
||||
// mirrors omovconst (asm7.go case 62): MOVZ for a movcon value, MOVN for
|
||||
// the complement form, the bitmask ORR otherwise, and the full
|
||||
// omovlconst sequence when no single word carries the value.
|
||||
// omovlconst sequence when no single word carries the value. A REGTMP
|
||||
// source register is refused: the materialisation would clobber it
|
||||
// before the register form reads it (asm7.go cases 13 and 62).
|
||||
if rn == 27 {
|
||||
return nil, fmt.Errorf("%s: cannot use REGTMP as source", mnem)
|
||||
}
|
||||
var seq []uint32
|
||||
switch s := arm64Movcon(d); {
|
||||
case s >= 0:
|
||||
@@ -2284,7 +2293,7 @@ func encodeARM64MemOp(mnem string, mem *ast.Operand, reg int, load bool, fi arm6
|
||||
// ADD offsets from the operand's own base register, [SP] and [Rn]
|
||||
// alike; beyond the split band the offset reaches the literal pool.
|
||||
if !arm64OffsetSplitReach(off, lt) {
|
||||
return arm64PoolAccess(mnem, lt, opc, off, rn, reg, pc, pool, poolBase)
|
||||
return arm64PoolAccess(mnem, lt, opc, off, rn, reg, pc, pool, poolBase, load)
|
||||
}
|
||||
hi, lo, ok := arm64SplitImm24(off, bits.TrailingZeros64(uint64(scale)))
|
||||
if !ok {
|
||||
@@ -2301,7 +2310,16 @@ func encodeARM64MemOp(mnem string, mem *ast.Operand, reg int, load bool, fi arm6
|
||||
// into REGTMP, then the access against the register pair (asm7.go cases
|
||||
// 30/31 and omovlit). The pooled words sit at poolBase plus the entry's
|
||||
// offset, both function-relative, so the imm19 distance resolves here.
|
||||
func arm64PoolAccess(mnem string, lt a64LSType, opc int, off int64, rn, reg, pc int, pool *arm64Pool, poolBase int) ([]byte, error) {
|
||||
func arm64PoolAccess(mnem string, lt a64LSType, opc int, off int64, rn, reg, pc int, pool *arm64Pool, poolBase int, load bool) ([]byte, error) {
|
||||
// The toolchain refuses a REGTMP data register or base on the pool path
|
||||
// (asm7.go cases 30/31): the literal load itself rides REGTMP.
|
||||
if reg == 27 || rn == 27 {
|
||||
kind := "load"
|
||||
if !load {
|
||||
kind = "store"
|
||||
}
|
||||
return nil, fmt.Errorf("%s: REGTMP used in large offset %s", mnem, kind)
|
||||
}
|
||||
if pool == nil {
|
||||
return nil, fmt.Errorf("%s: offset %d out of range (literal pool not supported)", mnem, off)
|
||||
}
|
||||
@@ -3904,7 +3922,12 @@ func encodeARM64Pair(mnem string, baseOp uint32, ops []*ast.Operand, pc int, fi
|
||||
}
|
||||
// Offsets within ±4095 the imm7 field cannot carry move the whole
|
||||
// distance into REGTMP first (asm7.go cases 74/76: add/sub + ldp/stp).
|
||||
// A store refuses a REGTMP pair member here (case 76: the add would
|
||||
// clobber it before the store reads it); a load allows one.
|
||||
if off >= -4095 && off <= 4095 {
|
||||
if !load && (rt1 == 27 || rt2 == 27) {
|
||||
return nil, fmt.Errorf("%s: cannot use REGTMP as source", mnem)
|
||||
}
|
||||
op, v := uint32(0), off // ADD
|
||||
if v < 0 {
|
||||
op, v = 1, -v // SUB
|
||||
@@ -3916,8 +3939,20 @@ func encodeARM64Pair(mnem string, baseOp uint32, ops []*ast.Operand, pc int, fi
|
||||
}
|
||||
// Positive offsets up to 16 MiB split into two ADDs: the low imm12 bits
|
||||
// from the base register into REGTMP, the high multiple of 0x1000 on top
|
||||
// (asm7.go cases 75/77). Beyond the band the offset reaches the pool.
|
||||
// (asm7.go cases 75/77). Beyond the band the offset reaches the pool,
|
||||
// which refuses a REGTMP base outright and, for the stores, a REGTMP
|
||||
// pair member as well.
|
||||
if off < 0 || off > 0xffffff {
|
||||
if rn == 27 {
|
||||
kind := "load"
|
||||
if !load {
|
||||
kind = "store"
|
||||
}
|
||||
return nil, fmt.Errorf("%s: REGTMP used in large offset %s", mnem, kind)
|
||||
}
|
||||
if !load && (rt1 == 27 || rt2 == 27) {
|
||||
return nil, fmt.Errorf("%s: REGTMP used in large offset store", mnem)
|
||||
}
|
||||
if pool == nil {
|
||||
return nil, fmt.Errorf("%s: offset %d out of range (literal pool not supported)", mnem, off)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user