fix(asm): bound the arm64 VTBL table list before the destination read
Assisted-by: GLM 5.3 Flash
This commit is contained in:
1 parent
2b2a72d54e
commit
409c8b348d
2 files changed
+51
-7
No files matched your search
+19
-6
@@ -858,6 +858,10 @@ func encodeARM64DPSR(mnem string, baseOp uint32, ops []*ast.Operand) ([]byte, er
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s: unsupported immediate %q", mnem, ops[0].Raw)
|
||||
}
|
||||
// The value as written: the class rules (the SP destination's
|
||||
// addcon band among them) read the written immediate, not the
|
||||
// complement the inverted mnemonics encode.
|
||||
writtenImm := v
|
||||
inverted := false
|
||||
switch mnem {
|
||||
case "BIC", "BICW", "BICS", "BICSW", "ORN", "ORNW", "EON", "EONW":
|
||||
@@ -917,7 +921,7 @@ func encodeARM64DPSR(mnem string, baseOp uint32, ops []*ast.Operand) ([]byte, er
|
||||
// addcon band alone, and the flags-only TST spellings keep the
|
||||
// fast path: ANDS ZR, Rn, #imm is their form.
|
||||
if rspDest {
|
||||
inBand := v > 0 && (v <= 0xFFF || (v&0xFFF == 0 && v>>12 <= 0xFFF))
|
||||
inBand := writtenImm > 0 && (writtenImm <= 0xFFF || (writtenImm&0xFFF == 0 && writtenImm>>12 <= 0xFFF))
|
||||
if !ok || !inBand {
|
||||
return nil, fmt.Errorf("%s: illegal combination: the destination cannot be RSP", mnem)
|
||||
}
|
||||
@@ -1718,7 +1722,11 @@ func encodeARM64Mov(instr *ast.Instr, mnem string, wb string, fi arm64FrameInfo,
|
||||
}
|
||||
return a64wordLE(base | 31<<5 | uint32(rd)), nil
|
||||
}
|
||||
return nil, fmt.Errorf("%s $%v: floating-point immediate needs the constant pool", mnem, f)
|
||||
// The toolchain pools this through its $f64 symbols with a
|
||||
// PC-relative relocation; gasm keeps the materialised
|
||||
// sequence the pre-pool encoder used (a documented byte
|
||||
// deviation outside the corpus families).
|
||||
return encodeARM64LoadImmClass(rd, arm64Imm64(src), mnem, !strings.EqualFold(operandRegName(dst), "ZR"))
|
||||
}
|
||||
}
|
||||
// The con(register) form: MOVD $con(Rn), Rd adds the displacement to
|
||||
@@ -3780,12 +3788,12 @@ func encodeARM64Pair(mnem string, baseOp uint32, ops []*ast.Operand, pc int, fi
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s expects a register pair (Rt1, Rt2)", mnem)
|
||||
}
|
||||
// Constrained unpredictable: the pair registers differ, and a
|
||||
// writeback base rides no pair member.
|
||||
if rt1 == rt2 {
|
||||
// Constrained unpredictable: the pair registers differ (the ZR pair is
|
||||
// the toolchain's own idiom), and a writeback base rides no pair member.
|
||||
if rt1 == rt2 && rt1 != 31 {
|
||||
return nil, fmt.Errorf("%s: constrained unpredictable behavior: the pair registers match", mnem)
|
||||
}
|
||||
if wb != "" {
|
||||
if wb != "" && rt1 != 31 {
|
||||
if strings.EqualFold(operandRegName(memOp), fmt.Sprintf("R%d", rt1)) || strings.EqualFold(operandRegName(memOp), fmt.Sprintf("R%d", rt2)) {
|
||||
return nil, fmt.Errorf("%s: constrained unpredictable behavior: the base rides a pair register", mnem)
|
||||
}
|
||||
@@ -4691,6 +4699,11 @@ func encodeARM64VTBL(mnem string, ops []*ast.Operand) ([]byte, error) {
|
||||
if !ok || len(ts) < 1 || len(ts) > 4 {
|
||||
return nil, fmt.Errorf("VTBL expects a table of one to four registers")
|
||||
}
|
||||
// The list may close on the last operand, leaving no destination: bound
|
||||
// the index before reading it.
|
||||
if end+1 >= len(ops) {
|
||||
return nil, fmt.Errorf("%s expects a destination register after the table list", mnem)
|
||||
}
|
||||
vd, ok := a64VecReg(operandRegName(ops[end+1]))
|
||||
if !ok || end+2 != len(ops) || vd.hasIdx {
|
||||
return nil, fmt.Errorf("invalid destination register in VTBL")
|
||||
|
||||
Reference in new issue
Block a user