Files
gasm-sdk/arch/arm64.go
T

182 lines
6.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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("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", "CASAL",
} {
t = append(t, i(op, "Atomic memory 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
}