Files

210 lines
7.9 KiB
Go
Raw Permalink Normal View History

// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: BSD-3-Clause
package arch
import "fmt"
func buildARM64() *Table {
return newTable(ARM64, arm64Registers(), relaxCounts(mergedInstrs(arm64Summaries(), commonGeneratedInstrs, arm64GeneratedInstrs, arm64Aliases())))
}
// arm64Aliases are the branch/jump spellings the assembler front-end accepts in
// addition to the generated opcode table (notably the unconditional B and BL).
func arm64Aliases() []string {
return []string{
"B", "BL", "BCS", "BHS", "BCC", "BLO", "BMI", "BPL", "BVS", "BVC",
"BHI", "BLS", "CBZW", "CBNZW", "ADR", "ADRP",
}
}
// arm64Summaries returns the curated documentation/operand-count table keyed by
// upper-case mnemonic; it enriches the complete generated name list.
func arm64Summaries() map[string]Instr { return toMap(arm64Curated()) }
// arm64Registers builds the arm64 (AArch64) register file.
func arm64Registers() []Register {
var regs []Register
add := func(name string, class RegClass, desc string) {
regs = append(regs, Register{Name: name, Class: class, Desc: desc})
}
// General-purpose integer registers R0-R30.
for i := 0; i <= 30; i++ {
add(fmt.Sprintf("R%d", i), GPR, "64-bit general-purpose register")
}
add("R18_PLATFORM", GPR, "R18 under its toolchain-reserved Windows name (an alias of R18)")
add("ZR", Special, "zero register (reads as 0)")
add("SP", Special, "stack pointer")
add("LR", Special, "link register (alias of R30)")
add("PC", Special, "program counter")
add("RSP", Special, "stack pointer (alias)")
// Floating-point / SIMD registers: F (scalar FP) and V (vector).
for i := 0; i <= 31; i++ {
add(fmt.Sprintf("F%d", i), Float, "floating-point register")
add(fmt.Sprintf("V%d", i), VecARM, "128-bit SIMD/vector register")
}
return regs
}
// arm64Curated returns the hand-written subset of arm64 (AArch64) instructions
// that carry a summary and/or an operand-count range. 32-bit operations carry
// a W suffix. The authoritative, complete set is arm64GeneratedInstrs.
func arm64Curated() []Instr {
var t []Instr
// Data movement (loads and stores are MOVx with a memory operand).
for _, m := range []string{
"MOVB", "MOVBU", "MOVH", "MOVHU", "MOVW", "MOVWU", "MOVD",
"FMOVS", "FMOVD",
} {
t = append(t, ic(m, "Move / load / store", 2, 2))
}
for _, m := range []string{"MOVK", "MOVN", "MOVZ", "MOVKW", "MOVNW", "MOVZW"} {
t = append(t, i(m, "Move wide constant"))
}
for _, m := range []string{"ADR", "ADRP"} {
t = append(t, ic(m, "Address of label/page", 2, 2))
}
// Integer arithmetic and logic (64-bit and W 32-bit forms).
for _, op := range []string{"ADD", "ADDS", "SUB", "SUBS", "AND", "ANDS", "ORR", "ORN", "EOR", "EON", "BIC", "BICS", "ADC", "ADCS", "SBC", "SBCS"} {
t = append(t, i(op, op+" (64-bit)"))
t = append(t, i(op+"W", op+" (32-bit)"))
}
for _, op := range []string{"NEG", "NGC", "MVN"} {
t = append(t, i(op, op+" (64-bit)"))
t = append(t, i(op+"W", op+" (32-bit)"))
}
for _, op := range []string{"MUL", "MNEG", "SMULL", "UMULL", "SMULH", "UMULH", "MADD", "MSUB", "SMADDL", "UMADDL", "SMSUBL", "UMSUBL"} {
t = append(t, i(op, "Multiply / multiply-accumulate"))
}
for _, op := range []string{"UDIV", "SDIV", "UDIVW", "SDIVW"} {
t = append(t, ic(op, "Divide", 3, 3))
}
// Shifts, rotates and bit manipulation.
for _, op := range []string{"LSL", "LSR", "ASR", "ROR"} {
t = append(t, i(op, op+" shift"))
t = append(t, i(op+"W", op+" shift (32-bit)"))
}
for _, op := range []string{"LSLV", "LSRV", "ASRV", "RORV", "LSLVW", "LSRVW", "ASRVW", "RORVW"} {
t = append(t, i(op, "Variable shift"))
}
for _, op := range []string{"RBIT", "REV", "REV16", "REV32", "REV64", "CLZ", "CLS", "RBITW", "REVW", "CLZW", "CLSW"} {
t = append(t, ic(op, "Bit manipulation", 2, 2))
}
for _, op := range []string{"UBFX", "SBFX", "UBFM", "SBFM", "BFXIL", "EXTR"} {
t = append(t, i(op, "Bitfield extract"))
}
// Compare and test.
for _, op := range []string{"CMP", "CMN", "TST"} {
t = append(t, i(op, op+" (64-bit)"))
t = append(t, i(op+"W", op+" (32-bit)"))
}
// Conditional select.
for _, op := range []string{"CSEL", "CSINC", "CSINV", "CSNEG", "CSET", "CSETM", "CINC", "CINV", "CNEG"} {
t = append(t, i(op, "Conditional select"))
t = append(t, i(op+"W", "Conditional select (32-bit)"))
}
for _, op := range []string{"CCMP", "CCMN", "CCMPW", "CCMNW"} {
t = append(t, i(op, "Conditional compare"))
}
// Control flow.
t = append(t, ic("B", "Unconditional branch", 1, 1))
t = append(t, ic("BL", "Branch with link", 1, 1))
for _, cc := range []string{
"EQ", "NE", "CS", "HS", "CC", "LO", "MI", "PL", "VS", "VC",
"HI", "LS", "GE", "LT", "GT", "LE", "AL", "NV",
} {
t = append(t, ic("B"+cc, "Conditional branch", 1, 1))
}
for _, op := range []string{"CBZ", "CBNZ", "TBZ", "TBNZ"} {
t = append(t, i(op, "Compare/test and branch"))
t = append(t, i(op+"W", "Compare/test and branch (32-bit)"))
}
t = append(t, ic("RET", "Return", 0, 1))
t = append(t, ic("BR", "Branch to register", 1, 1))
t = append(t, ic("BLR", "Branch with link to register", 1, 1))
t = append(t, ic("NOP", "No operation", 0, 1))
t = append(t, ic("BRK", "Breakpoint", 0, 1))
for _, op := range []string{"SVC", "HVC", "SMC"} {
t = append(t, i(op, "Exception generation"))
}
for _, op := range []string{"DMB", "DSB", "ISB"} {
t = append(t, i(op, "Barrier"))
}
for _, op := range []string{"MRS", "MSR"} {
t = append(t, ic(op, "System register access", 2, 2))
}
// Atomics (LSE and load-exclusive/store-exclusive).
for _, op := range []string{
"LDAXR", "LDAXRB", "LDAXRH", "LDAXRW", "STXR", "STXRB", "STXRH", "STXRW",
"LDAR", "LDARB", "LDARH", "LDARW", "STLR", "STLRB", "STLRH", "STLRW",
"LDADD", "LDCLR", "LDEOR", "LDSET", "SWP", "CAS", "CASAL", "CASL",
} {
t = append(t, i(op, "Atomic memory operation"))
}
// Register-pair loads and stores.
for _, op := range []string{"LDP", "STP", "LDPW", "STPW", "FLDPD", "FSTPD"} {
t = append(t, ic(op, "Register-pair load or store", 2, 2))
}
// Cache maintenance and prefetch.
t = append(t, i("DC", "Data cache maintenance"))
t = append(t, i("PRFM", "Memory prefetch"))
for _, op := range []string{"LDADDAL", "LDCLRAL", "LDORAL", "SWPAL"} {
t = append(t, i(op, "Atomic memory operation with acquire and release semantics"))
}
// Cryptographic extensions.
for _, op := range []string{"AESE", "AESD", "AESMC", "AESIMC"} {
t = append(t, i(op, "AES round"))
}
for _, op := range []string{
"SHA1C", "SHA1P", "SHA1M", "SHA1H", "SHA1SU0", "SHA1SU1",
"SHA256H", "SHA256H2", "SHA256SU0", "SHA256SU1",
"SHA512H", "SHA512H2", "SHA512SU0", "SHA512SU1",
} {
t = append(t, i(op, "SHA round"))
}
for _, op := range []string{"VEOR3", "VBCAX", "VXAR", "VRAX1"} {
t = append(t, i(op, "Three-way XOR / rotate crypto vector operation"))
}
// Floating-point scalar.
for _, op := range []string{
"FADD", "FSUB", "FMUL", "FDIV", "FNEG", "FABS", "FSQRT", "FMIN", "FMAX",
"FMADD", "FMSUB", "FNMADD", "FNMSUB", "FCMP", "FCMPE",
"FCVT", "FCVTZS", "FCVTZU", "FCVTNS", "FCVTNU", "FCVTAS", "FCVTAU",
"SCVTF", "UCVTF", "FRINTM", "FRINTN", "FRINTP", "FRINTZ",
} {
t = append(t, i(op, "Floating-point operation"))
}
t = append(t, i("FMOV", "Floating-point move"))
// NEON / SIMD vector (arrangement carried by the operand suffix).
for _, op := range []string{
"VADD", "VSUB", "VMUL", "VMLA", "VMLS", "VNEG", "VABS", "VMIN", "VMAX",
"VAND", "VORR", "VEOR", "VBIC", "VBIF", "VBSL", "VNOT",
"VDUP", "VMOV", "VMOVI", "VMOVQ",
"VLD1", "VLD2", "VLD3", "VLD4", "VST1", "VST2", "VST3", "VST4",
"VCNT", "VREV16", "VREV32", "VREV64", "VUZP1", "VUZP2", "VZIP1", "VZIP2", "VTRN1", "VTRN2",
"VSHL", "VSHR", "VSSHLL", "VUSHR", "VEXT", "VTBL", "VTBX",
"VADDV", "VUMAXV", "VUMINV", "VSMAXV", "VSMINV",
"VFADD", "VFSUB", "VFMUL", "VFDIV", "VFNEG", "VFABS", "VFMIN", "VFMAX",
"VFMLA", "VFMLS", "VFCVT", "VSCVTF", "VUCVTF", "VFCMEQ", "VFCMGT", "VFCMLT",
"VCMPEQ", "VCMPGT", "VCMPGE", "VSHLL",
} {
t = append(t, i(op, "NEON SIMD vector operation"))
}
return t
}