38 lines
1.4 KiB
Go
38 lines
1.4 KiB
Go
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
|||
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
||
|
|
|
||
|
|
package disasm
|
||
|
|
|
||
|
|
import "fmt"
|
||
|
|
|
||
|
|
// golang.org/x/arch refuses a corner of the arm64 exception-generation
|
||
|
|
// space outright: the hypervisor call HVC, the secure monitor call SMC and
|
||
|
|
// the speculation barrier SB. The toolchain's assembler corpus carries all
|
||
|
|
// three with machine-checked encodings (arm64enc.s's "HVC $61428 //
|
||
|
|
// 82fe1dd4" and its kin), so the disassembler names them from the raw word
|
||
|
|
// in the error branch, the way the amd64 table does.
|
||
|
|
//
|
||
|
|
// The encodings are the exception space 1101 0100 0 opc imm16 op2: HVC is
|
||
|
|
// opc 000 with the op2 marker 00010, SMC the same opc with 00011, and SB
|
||
|
|
// the fixed barrier word 0xD50330FF. Every other shape in the space keeps
|
||
|
|
// the placeholder.
|
||
|
|
|
||
|
|
// nameARM64Rejected names an arm64 word the decoder refuses. It reports
|
||
|
|
// the rendered text, the instruction's length in bytes and whether the word
|
||
|
|
// matched a family; a non-match keeps the placeholder.
|
||
|
|
func nameARM64Rejected(code []byte) (string, int, bool) {
|
||
|
|
w := uint32(code[0]) | uint32(code[1])<<8 | uint32(code[2])<<16 | uint32(code[3])<<24
|
||
|
|
switch {
|
||
|
|
case w == 0xd50330ff:
|
||
|
|
return "SB", 4, true
|
||
|
|
case w>>21 == 0x6a0:
|
||
|
|
imm := (w >> 5) & 0xffff
|
||
|
|
switch w & 0x1f {
|
||
|
|
case 0x02:
|
||
|
|
return fmt.Sprintf("HVC $%d", imm), 4, true
|
||
|
|
case 0x03:
|
||
|
|
return fmt.Sprintf("SMC $%d", imm), 4, true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return "", 0, false
|
||
|
|
}
|