// Copyright (c) 2026 Petr Balvín (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 }