1
0

Compare commits

...

2 Commits

Author SHA1 Message Date
cinthyr
905d05624f docs: Fix a whole lot of typos in the ISA docs 2026-05-31 20:53:09 +02:00
dd699cc933 tooling: add vim syntax for ain-48 assembly 2026-05-31 20:46:55 +02:00
5 changed files with 151 additions and 113 deletions

1
.gitignore vendored
View File

@ -2,4 +2,5 @@
/build /build
/docs/*.pdf /docs/*.pdf
/ain48 /ain48
/scratch

View File

@ -13,7 +13,6 @@
set par(justify: true) set par(justify: true)
set heading(numbering: "I.1") set heading(numbering: "I.1")
show raw: set text(font: "Iosevka Slab", size: 1em / .8) show raw: set text(font: "Iosevka Slab", size: 1em / .8)
show math.equation: set text(font: "Fira Math", weight: 400)
show title: align.with(center) show title: align.with(center)
show strong: text.with(weight: 900) show strong: text.with(weight: 900)
set figure(numbering: "1", placement: auto) set figure(numbering: "1", placement: auto)

View File

@ -11,7 +11,7 @@
[Internátionális], [Internátionális],
[Nórmae], [Nórmae],
grid.cell(rowspan: 2)[--- 48 bit], grid.cell(rowspan: 2)[--- 48 bit],
[Intstrúctiónum], [Instrúctiónum],
[Numerátiónum], [Numerátiónum],
)) ))
@ -24,14 +24,14 @@
] ]
= Conventions = Conventions
A *byte* (singulus) is the smallest adressable part of memory, that is, a 12-bit A *byte* (singulus) is the smallest addressable part of memory, that is, a 12-bit
binary number. binary number.
A *word* (quaternus) is a binary number composed of 4 bytes, that is, a 48 bit A *word* (quaternus) is a binary number composed of 4 bytes, that is, a 48 bit
binary number. binary number.
In memory, multibyte numbers are laid out with the least significant byte at the In memory, multibyte numbers are laid out with the least significant byte at the
lowest memory adress lowest memory address.
= Registers = Registers
The main registers of the architecture are all word-length: The main registers of the architecture are all word-length:
@ -62,7 +62,7 @@ There is also a 3-bit status register.
In instruction diagrams, each large rectangle represents a byte, that are In instruction diagrams, each large rectangle represents a byte, that are
disposed in memory as implied by the reading order, starting at the lowest disposed in memory as implied by the reading order, starting at the lowest
memory adress. memory address.
#let instruction_diagram(..bytes, voff: 0) = { #let instruction_diagram(..bytes, voff: 0) = {
import cetz.draw: * import cetz.draw: *
@ -101,8 +101,8 @@ memory adress.
(1, [i#sub[2]\ 0]), (1, [i#sub[2]\ 0]),
(1, [i#sub[1]\ 0]), (1, [i#sub[1]\ 0]),
(1, [s]), (1, [s]),
(4, [op]), (4, [ac]),
), ((4, [r#sub[d]]), (4, [r#sub[2]]), (4, [r#sub[1]]))) ), ((4, [r#sub[f]]), (4, [r#sub[2]]), (4, [r#sub[1]])))
content((12.25, -1))[or] content((12.25, -1))[or]
instruction_diagram(voff: -5, ( instruction_diagram(voff: -5, (
(1, [0]), (1, [0]),
@ -113,8 +113,8 @@ memory adress.
(1, [i#sub[2]\ 0]), (1, [i#sub[2]\ 0]),
(1, [i#sub[1]\ 1]), (1, [i#sub[1]\ 1]),
(1, [s]), (1, [s]),
(4, [op]), (4, [ac]),
), ((4, [r#sub[d]]), (4, [r#sub[2]]), (4, text(size: .9em)[imm[0:3]]))) ), ((4, [r#sub[f]]), (4, [r#sub[2]]), (4, text(size: .9em)[imm[0:3]])))
content((12.25, -6))[or] content((12.25, -6))[or]
instruction_diagram(voff: -10, ( instruction_diagram(voff: -10, (
(1, [0]), (1, [0]),
@ -126,7 +126,7 @@ memory adress.
(1, [i#sub[1]\ 0]), (1, [i#sub[1]\ 0]),
(1, [s]), (1, [s]),
(4, [op]), (4, [op]),
), ((4, [r#sub[d]]), (4, text(size: .9em)[imm[0:3]]), (4, [r#sub[1]]))) ), ((4, [r#sub[f]]), (4, text(size: .9em)[imm[0:3]]), (4, [r#sub[1]])))
content((12.25, -11))[or] content((12.25, -11))[or]
instruction_diagram(voff: -15, ( instruction_diagram(voff: -15, (
(1, [0]), (1, [0]),
@ -137,8 +137,8 @@ memory adress.
(1, [i#sub[2]\ 1]), (1, [i#sub[2]\ 1]),
(1, [i#sub[1]\ 1]), (1, [i#sub[1]\ 1]),
(1, [s]), (1, [s]),
(4, [op]), (4, [ac]),
), ((4, [r#sub[d]]), (8, [imm[0:7]]))) ), ((4, [r#sub[f]]), (8, [imm[0:7]])))
}, },
), ),
) )
@ -197,9 +197,9 @@ memory adress.
(1, [0]), (1, [0]),
(1, [0]), (1, [0]),
(1, [1]), (1, [1]),
(1, [w]), (1, [s]),
(4, [r#sub[d]]), (4, [r#sub[d]]),
(4, [r#sub[a]]), (4, [r#sub[l]]),
), ((12, [imm[0:11]]),)) ), ((12, [imm[0:11]]),))
})) }))
@ -218,7 +218,7 @@ memory adress.
(1, [1]), (1, [1]),
(1, [1]), (1, [1]),
(1, [1]), (1, [1]),
(3, [op]), (3, [ac]),
)) ))
})) }))
@ -239,10 +239,10 @@ memory adress.
(1, [0]), (1, [0]),
(1, [0]), (1, [0]),
(1, [0]), (1, [0]),
(1, [I]),
(1, [C]), (1, [C]),
(1, [E]),
(1, [N]), (1, [N]),
(1, [Z]), (1, [U]),
(1, [R]), (1, [R]),
), ((12, [imm[0:11]]),)) ), ((12, [imm[0:11]]),))
instruction_diagram(((12, [imm[12:23]]),), ((12, [imm[24:35]]),), voff: -3) instruction_diagram(((12, [imm[12:23]]),), ((12, [imm[24:35]]),), voff: -3)
@ -260,11 +260,11 @@ memory adress.
(1, [1]), (1, [1]),
(1, [0]), (1, [0]),
(1, [1]), (1, [1]),
(4, [r#sub[a]]), (4, [r#sub[l]]),
(1, [I]), (1, [I]),
(1, [C]), (1, [E]),
(1, [N]), (1, [N]),
(1, [Z]), (1, [U]),
(1, [R]), (1, [R]),
)) ))
})) }))
@ -278,11 +278,11 @@ memory adress.
(1, [1]), (1, [1]),
(1, [1]), (1, [1]),
(1, [0]), (1, [0]),
(4, [r#sub[a]]), (4, [r#sub[l]]),
(1, [I]), (1, [I]),
(1, [C]), (1, [E]),
(1, [N]), (1, [N]),
(1, [Z]), (1, [U]),
(1, [R]), (1, [R]),
), ((12, [imm[0:11]]),)) ), ((12, [imm[0:11]]),))
})) }))
@ -294,9 +294,9 @@ Common Notations:
/ ```ain48 %a, %b, %c, ...```: any register a, b, c / ```ain48 %a, %b, %c, ...```: any register a, b, c
/ ```ain48 #imm[n]```: An immediate (max: n bits) / ```ain48 #imm[n]```: An immediate (max: n bits)
/ ```ain48 %0, %nul```: Writes to ```ain48 %0 / %nul``` are discarded / ```ain48 %0, %nul```: Writes to ```ain48 %0 / %nul``` are discarded
/ ```ain48 (%a)```: The memory at the adress contained by %a / ```ain48 (%a)```: The memory at the address contained by %a
/ ```ain48 (#imm[n])```: The memory at the adress represented by the immediate (max n bits) / ```ain48 (#imm[n])```: The memory at the address represented by the immediate (max n bits)
/ ```ain48 a_label```: The memory adress correspoding to the label / ```ain48 a_label```: The memory address corresponding to the label
#let ristr(mnem) = [*#raw(mnem, lang: "ain48")* (#ref(label("ins:" + mnem), form: "page"))] #let ristr(mnem) = [*#raw(mnem, lang: "ain48")* (#ref(label("ins:" + mnem), form: "page"))]
#let istr(mnem) = strong(raw(mnem, lang: "ain48")) #let istr(mnem) = strong(raw(mnem, lang: "ain48"))
@ -316,7 +316,7 @@ Common Notations:
#optgrid( #optgrid(
opt[i#sub[1]][0], opt[i#sub[1]][0],
opt[i#sub[2]][0], opt[i#sub[2]][0],
opt[r#sub[d]][a], opt[r#sub[f]][a],
opt[r#sub[1]][b], opt[r#sub[1]][b],
opt[r#sub[2]][c], opt[r#sub[2]][c],
) )
@ -324,7 +324,7 @@ Common Notations:
#optgrid( #optgrid(
opt[i#sub[1]][0], opt[i#sub[1]][0],
opt[i#sub[2]][1], opt[i#sub[2]][1],
opt[r#sub[d]][a], opt[r#sub[f]][a],
opt[r#sub[1]][b], opt[r#sub[1]][b],
opt[imm][imm], opt[imm][imm],
) )
@ -333,51 +333,61 @@ Common Notations:
#optgrid( #optgrid(
opt[i#sub[1]][1], opt[i#sub[1]][1],
opt[i#sub[2]][0], opt[i#sub[2]][0],
opt[r#sub[d]][a], opt[r#sub[f]][a],
opt[r#sub[2]][b], opt[r#sub[2]][b],
opt[imm][imm], opt[imm][imm],
) )
] ]
/ #raw(mnemonic + " %a, #imm[8]", lang: "ain48"): %a %a #opsym imm / #raw(mnemonic + " %a, #imm[8]", lang: "ain48"): %a %a #opsym imm
#optgrid(opt[i#sub[1]][1], opt[i#sub[2]][1], opt[r#sub[d]][a], opt[imm][imm]) #optgrid(opt[i#sub[1]][1], opt[i#sub[2]][1], opt[r#sub[f]][a], opt[imm][imm])
] ]
#let instructions = ( #let instructions = (
(mnem: "STR", name: "Subtrahere", sign: true, description: [ (mnem: "STR", name: "Subtrahere", sign: true, description: [
Subtract one signed number from another Subtract one signed number from another.
#aludoc("STR", "01", "-", false, 1) #aludoc("STR", "01", "-", false, 1)
/ Instruction format: #amal
]), ]),
(mnem: "ADD", name: "Addere", sign: true, description: [ (mnem: "ADD", name: "Addere", sign: true, description: [
Add two signed numbers together. Add two signed numbers together.
#aludoc("ADD", "00", "+", true, 1) #aludoc("ADD", "00", "+", true, 1)
/ Instruction format: #amal
]), ]),
(mnem: "MPL", name: "Multiplicáre", sign: true, description: [ (mnem: "MPL", name: "Multiplicáre", sign: true, description: [
Multiply two signed numbers together Multiply two signed numbers together.
#aludoc("MPL", "02", "×", true, 1) #aludoc("MPL", "02", "×", true, 1)
/ Instruction format: #amal / Instruction format: #amal
]), ]),
(mnem: "RSD", name: "Residérí", sign: true, description: [ (mnem: "RSD", name: "Residérí", sign: true, description: [
Reminder of the euclidian division of two words Remainder of the Euclidean division of two signed integers.
Will raise an arithmetic exception if the right operand is zero.
#aludoc("RSD", "05", "mod", false, 1) #aludoc("RSD", "05", "mod", false, 1)
/ Instruction format: #amal
]), ]),
(mnem: "DVD", name: "Dívidere", sign: true, description: [ (mnem: "DVD", name: "Dívidere", sign: true, description: [
Divide a signed number by another Integer part of the Euclidean division of two signed integers.
Will raise an arithmetic exception if the right operand is zero.
#aludoc("DVD", "04", "/", false, 1) #aludoc("DVD", "04", "/", false, 1)
/ Instruction format: #amal
]), ]),
(mnem: "DEM", name: "Ad Dextró Movére", sign: true, description: [ (mnem: "DEM", name: "Ad Dextró Movére", sign: true, description: [
Shift a signed number left by a signed number. Shift a signed number right by a signed number.
Will raise an arithmetic exception if the right operand is negative.
#aludoc("DEM", "06", ">>", false, 1) #aludoc("DEM", "06", ">>", false, 1)
/ Instruction format: #amal
]), ]),
(mnem: "SIM", name: "Ad Sinistró Movére", description: [ (mnem: "SIM", name: "Ad Sinistró Movére", description: [
Shift a word to the left Shift a word to the left.
Will raise an arithmetic exception if the right operand is negative.
#aludoc("SIM", "07", "<<", false, 0) #aludoc("SIM", "07", "<<", false, 0)
/ Instruction format: #amal
]), ]),
( (
mnem: "ILG", mnem: "ILG",
name: "Immediátum Legere", name: "Immediátum Legere",
sign: true, sign: true,
description: [ description: [
Load a signed immediate value into a register Load a signed immediate value into a register.
/ ```ain48 ILG %a, #imm[12]```: %a imm / ```ain48 ILG %a, #imm[12]```: %a imm
/ Instruction format: #ipl / Instruction format: #ipl
#optgrid(opt[s][1], opt[r][a], opt[imm][imm]) #optgrid(opt[s][1], opt[r][a], opt[imm][imm])
@ -386,7 +396,7 @@ Common Notations:
#optgrid(opt[s][1], opt[r][a], opt[imm][imm]) #optgrid(opt[s][1], opt[r][a], opt[imm][imm])
The assembler has freedom to choose the appropriate format given the size of the The assembler has freedom to choose the appropriate format given the size of the
immediate. The mnemonics #ristr("IMLG") and #ristr("IPLG") also exist to allow immediate. The mnemonics #ristr("IMLG") and #ristr("IPLG") also exist to allow
the programmer to explicitely request one format or the other: #istr("IMLG") uses #iml and the programmer to explicitly request one format or the other: #istr("IMLG") uses #iml and
#istr("IPLG") uses #ipl. #istr("IPLG") uses #ipl.
], ],
also: ( also: (
@ -398,15 +408,10 @@ Common Notations:
mnem: "I", mnem: "I",
name: "Íre", name: "Íre",
description: [ description: [
Go to Go to (jump to) an instruction other than the one immediately following this instruction.
/ ```ain48 I a_label```: %ia a_label / ```ain48 I a_label```: %ia a_label
/ Instruction Format: #asli / Instruction format: #asli
#optgrid( #optgrid(
opt[I][1],
opt[C][0],
opt[N][0],
opt[Z][0],
opt[R][0],
opt[imm][a_label], opt[imm][a_label],
) )
Some assemblers may opt to assemble calls to nearby labels as if they were of Some assemblers may opt to assemble calls to nearby labels as if they were of
@ -414,44 +419,24 @@ Common Notations:
/ ```ain48 I #imm[48]```: %ia imm\ / ```ain48 I #imm[48]```: %ia imm\
/ Instruction Format: #asli / Instruction Format: #asli
#optgrid( #optgrid(
opt[I][1],
opt[C][0],
opt[N][0],
opt[Z][0],
opt[R][0],
opt[imm][a_label], opt[imm][a_label],
) )
/ ```ain48 I %a```: %ia %a\ / ```ain48 I %a```: %ia %a\
/ Instruction Format: #aslr / Instruction Format: #aslr
#optgrid( #optgrid(
opt[I][1],
opt[C][0],
opt[N][0],
opt[Z][0],
opt[R][0],
opt[r#sub[a]][a], opt[r#sub[a]][a],
) )
/ ```ain48 I %nul, #imm[12]```: %ia %ia + %a / ```ain48 I %nul, #imm[12]```: %ia %ia + %a
/ Instruction Format: #asrd / Instruction Format: #asrd
#optgrid( #optgrid(
opt[I][1],
opt[C][0],
opt[N][0],
opt[Z][0],
opt[R][0],
opt[r#sub[a]][0], opt[r#sub[a]][0],
opt[imm][imm], opt[imm][imm],
) )
This is a special case of the format just below, where becasue offsetting from This is a special case of the format just below, where because offsetting from
%nul is useless, we instead understand it as an offset from %ia %nul is useless, we instead interpret it as an offset from %ia.
/ ```ain48 I %a, #imm[12]```: %ia %a + imm / ```ain48 I %a, #imm[12]```: %ia %a + imm
/ Instruction Format: #asrd / Instruction Format: #asrd
#optgrid( #optgrid(
opt[I][1],
opt[C][0],
opt[N][0],
opt[Z][0],
opt[R][0],
opt[r#sub[a]][a], opt[r#sub[a]][a],
opt[imm][imm], opt[imm][imm],
) )
@ -462,23 +447,23 @@ Common Notations:
"UI", "UI",
"Si nullus est íre", "Si nullus est íre",
[ [
Used like #istr("I") but only jump if the zero bit of the staus flag is set.\ Used like #istr("I"), but only jump if the zero bit of the status flag is set.\
#optgrid(opt[I][0], opt[Z][1]) #optgrid(opt[I][0], opt[U][1])
], ],
), ),
( (
"NUI", "NUI",
"Si nón nullus est íre", "Si nón nullus est íre",
[ [
Used like #istr("I") but only jump if the zero bit of the status flag is not set.\ Used like #istr("I"), but only jump if the zero bit of the status flag is not set.\
#optgrid(opt[I][1], opt[Z][1]) #optgrid(opt[I][1], opt[U][1])
], ],
), ),
( (
"NI", "NI",
"Si negatívus est íre", "Si negatívus est íre",
[ [
Used like #istr("I") but only jump if the negative bit of the status flag is set.\ Used like #istr("I"), but only jump if the negative bit of the status flag is set.\
#optgrid(opt[I][0], opt[N][1]) #optgrid(opt[I][0], opt[N][1])
], ],
), ),
@ -486,7 +471,7 @@ Common Notations:
"NNI", "NNI",
"Si nón negatívus est íre", "Si nón negatívus est íre",
[ [
Used like #istr("I") but only jump if the negative bit of the status flag is not set.\ Used like #istr("I"), but only jump if the negative bit of the status flag is not set.\
#optgrid(opt[I][1], opt[N][1]) #optgrid(opt[I][1], opt[N][1])
], ],
), ),
@ -494,15 +479,15 @@ Common Notations:
"EI", "EI",
"Si excedit íre", "Si excedit íre",
[ [
Used like #istr("I") but only jump if the carry bit of the status flag is set.\ Used like #istr("I"), but only jump if the carry bit of the status flag is set.\
#optgrid(opt[I][0], opt[C][1]) #optgrid(opt[I][0], opt[E][1])
], ],
), ),
( (
"NEI", "NEI",
"Si nón excedit íre", "Si nón excedit íre",
[ [
Used like #istr("I") but only jump if the carry bit of the status flag is not set.\ Used like #istr("I"), but only jump if the carry bit of the status flag is not set.\
#optgrid(opt[I][1], opt[C][1]) #optgrid(opt[I][1], opt[C][1])
], ],
), ),
@ -510,22 +495,22 @@ Common Notations:
"PI", "PI",
"Si positívus est íre", "Si positívus est íre",
[ [
Used like #istr("I") but only jump if neither the zero nor negative flags of the status Used like #istr("I"), but only jump if neither the zero nor negative flag of the status
flag is set. flag is set.
#optgrid(opt[I][1], opt[N][1], opt[Z][1]) #optgrid(opt[I][1], opt[N][1], opt[U][1])
], ],
), ),
( (
"NPI", "NPI",
"Si nón positívus est íre", "Si nón positívus est íre",
[ [
Used like #istr("I") but only jump if either the zero or negative flags of the status Used like #istr("I"), but only jump if either the zero or negative flag of the status
flag are set. flag is set.
#optgrid(opt[I][0], opt[N][1], opt[Z][1]) #optgrid(opt[I][0], opt[N][1], opt[U][1])
], ],
), ),
("IVC", "Invocáre", [ ("IVC", "Invocáre", [
Used like #istr("I") but sets up a function environment prior to jumping:\ Used like #istr("I"), but sets up a function environment prior to jumping:\
(%it) %ia; %it %it - 4 (%it) %ia; %it %it - 4
#optgrid(opt[R][1]) #optgrid(opt[R][1])
@ -539,23 +524,26 @@ Common Notations:
Invoke a kernel space function, see your operating system's ABI for more Invoke a kernel space function, see your operating system's ABI for more
details. details.
/ Instruction format: #asss / Instruction format: #asss
#optgrid(opt[op][3]) #optgrid(opt[ac][3])
/ ```ain48 NCIVC```: Perform a kernel call. / ```ain48 NCIVC```: Perform a kernel call.
], ],
), ),
(mnem: "IRRV", name: "De Interruptó Reveníre", description: [ (mnem: "IRRV", name: "De Interruptó Reveníre", description: [
*Priviledged* *Privileged*
Instrucion used to exit from the interrupt handler. Instruction used to exit from the interrupt handler.
#optgrid(opt[op][4]) / Instruction format: #asss
#optgrid(opt[ac][4])
/ ```ain48 IRRV```: Return from an interrupt.
]), ]),
(mnem: "NCRV", name: "De Nucleó Reveníre", description: [ (mnem: "NCRV", name: "De Nucleó Reveníre", description: [
*Priviledged* *Privileged*
Return to user space after a system call Return to user space after a system call.
/ Instruction Format: #asss / Instruction Format: #asss
#optgrid(opt[op][2]) #optgrid(opt[ac][2])
/ ```ain48 IRRV```: Return from kernelspace.
]), ]),
(mnem: "VEL", name: "Vel", description: [ (mnem: "VEL", name: "Vel", description: [
Bitwise disjunction between two words Bitwise disjunction between two words.
#aludoc("VEL", [11], sym.or, true, 0) #aludoc("VEL", [11], sym.or, true, 0)
]), ]),
(mnem: "NEC", name: "Nec", description: [ (mnem: "NEC", name: "Nec", description: [
@ -582,51 +570,56 @@ Common Notations:
mnem: "LG", mnem: "LG",
name: "Legere", name: "Legere",
description: [ description: [
Read a word from memory Read a word from memory.
/ Instruction Format: #amls / Instruction Format: #amls
/ ```ain48 LG %a, (%b), #imm[12]```: %a (%b + imm) / ```ain48 LG %a, (%b), #imm[12]```: %a (%b + imm)
#optgrid(opt[w][0], opt[r#sub[d]][a], opt[r#sub[a]][b], opt[imm][imm]) #optgrid(opt[s][0], opt[r#sub[d]][a], opt[r#sub[a]][b], opt[imm][imm])
/ ```ain48 LG %a, (%b)```: This is a special case of ```ain48 LG %a, (%b), #imm[12]``` where imm = 0 / ```ain48 LG %a, (%b)```: This is a special case of ```ain48 LG %a, (%b), #imm[12]``` where imm = 0.
], ],
), ),
( (
mnem: "SC", mnem: "SC",
name: "Scríbere", name: "Scríbere",
description: [ description: [
Write a word to memory Write a word to memory.
/ Instruction Format: #amls / Instruction Format: #amls
/ ```ain48 SC %a, (%b), #imm[12]```: (%b + imm) %a / ```ain48 SC %a, (%b), #imm[12]```: (%b + imm) %a
#optgrid(opt[w][1], opt[r#sub[d]][a], opt[r#sub[a]][b], opt[imm][imm]) #optgrid(opt[s][1], opt[r#sub[d]][a], opt[r#sub[a]][b], opt[imm][imm])
/ ```ain48 SC %a, (%b)```: This is a special case of ```ain48 SC %a, (%b), #imm[12]``` where imm = 0 / ```ain48 SC %a, (%b)```: This is a special case of ```ain48 SC %a, (%b), #imm[12]``` where imm = 0
], ],
), ),
(mnem: "CESS", name: "Cessáre", description: [ (mnem: "CESS", name: "Cessáre", description: [
Halts Execution of the process *Privileged* Halts the CPU.
/ Instruction Format: #asss / Instruction Format: #asss
#optgrid(opt[op][7]) #optgrid(opt[ac][7])
/ ```ain48 CESS```: Pause execution. / ```ain48 CESS```: Pause execution.
]), ]),
(mnem: "RV", name: "Reveníre", description: [ (mnem: "RV", name: "Reveníre", description: [
Returns from a subroutine. Returns from a subroutine.
/ Instruction Format: #asss / Instruction Format: #asss
#optgrid(opt[op][0]) #optgrid(opt[ac][0])
/ ```ain48 RV```: %it %it - 4; %ia (%it) / ```ain48 RV```: %it %it - 4; %ia (%it)
]), ]),
(mnem: "CST", name: "Construere", description: [ (mnem: "CST", name: "Construere", description: [
Push the contents of a register onto the stack: Push the contents of a register onto the stack.
/ ```ain48 CST %a```: This instruction is a macro implemented as follows:\ / ```ain48 CST %a```: This instruction is a macro implemented as follows:\
#raw(block: true, "SC %a, (%it)\nPSTR %it, #4", lang: "ain48") #raw(block: true, "SC %a, (%it)\nPSTR %it, #4", lang: "ain48")
]), ]),
(mnem: "DST", name: "Destruere", description: [ (mnem: "DST", name: "Destruere", description: [
Push the contents of a register onto the stack: Pop the contents of the top of the stack into a register.
/ ```ain48 DST %a```: This instruction is a macro implemented as follows:\ / ```ain48 DST %a```: This instruction is a macro implemented as follows:\
#raw(block: true, "PADD %it, #4\nLG %a, (%it)", lang: "ain48") #raw(block: true, "PADD %it, #4\nLG %a, (%it)", lang: "ain48")
]), ]),
(mnem: "TSC", name: "Transcríbere", description: [ (mnem: "TSC", name: "Transcríbere", description: [
Copy between registers Copy between registers.
/ ```ain48 TSC %a, %b```: %a %b. Macro for ```ain48 VEL %a, %b, %nul``` / ```ain48 TSC %a, %b```: %a %b.
] This instruction is a macro implemented as ```ain48 VEL %a, %b, %nul```.
), ]),
(mnem: "AN", name: "Actió Nulla", description: [
Do nothing except increment the instruction counter.
/ ```ain48 AN```: Do nothing.
This instruction is a macro implemented as ```ain48 IPLG %0, #0```.
]),
) )
#instructions.map( #instructions.map(
@ -643,7 +636,7 @@ Common Notations:
== P#(it.mnem) | Positívós #it.name == P#(it.mnem) | Positívós #it.name
#label("ins:P" + it.mnem) #label("ins:P" + it.mnem)
Same form(s) as #istr(it.mnem) but with s = 0\ Same form(s) as #istr(it.mnem) but with s = 0\
Unsigned version of #ristr(it.mnem) Unsigned version of #ristr(it.mnem).
])) ]))
} }
if it.keys().contains("also") { if it.keys().contains("also") {
@ -662,7 +655,7 @@ Common Notations:
mnem: "P" + m, mnem: "P" + m,
desc: [ desc: [
== P#m | Positivós #n == P#m | Positivós #n
Unsigned version of #m, see #ristr("P" + it.mnem) and #ristr(it.mnem) Unsigned version of #m; see #ristr("P" + it.mnem) and #ristr(it.mnem).
], ],
), ),
) )

View File

@ -0,0 +1,6 @@
" ftdetect file for AIN-48 assembly
au BufRead,BufNewFile *.ain48s set filetype=ain48asm
au BufRead,BufNewFile *.ain48asm set filetype=ain48asm
au BufRead,BufNewFile *.a48s set filetype=ain48asm
au BufRead,BufNewFile *.a48asm set filetype=ain48asm

View File

@ -0,0 +1,39 @@
" Vim syntax file
" Language: AIN-48 Assembly
" Maintainer: Annwan
" Latest Revision: 31 May 2026
if exists("b:current_syntax")
finish
endif
syn case ignore
syn keyword ain48Mnemonic add aeq aut cess cst dem dst dvd ei et i ilg imlg iplg irrv ivc lg mpl nam ncivc ncrv nec nei ni nni npi nui padd pdem pdvd pi pilg pimlg piplg pmpl prsd pstr rsd rv sc sim str tsc ui vel
" Senary constants
syn match ain48Immediate "#[Ss][0-5]\+"
syn match ain48Immediate "#-[Ss][0-5]\+"
" Octal constants
syn match ain48Immediate "#[Oo][0-7]\+"
syn match ain48Immediate "#-[Oo][0-7]\+"
" Decimal constants
syn match ain48Immediate "#[Xx][0-9]\+"
syn match ain48Immediate "#-[Xx][0-9]\+"
" Binary constants
syn match ain48Immediate "#[Bb][01]\+"
syn match ain48Immediate "#-[Bb][01]\+"
syn match ain48Register "%[0-7a-z]\+"
syn match ain48Directive "\.[a-z0-9_-]\+"
syn match ain48Comment ";.*$" contains=ain48Todo
syn keyword ain48Todo contained TODO FIXME NOTE
syn match ain48Label "^[a-zA-Z0-9_-]\+:"
hi link ain48Mnemonic Statement
hi link ain48Comment Comment
hi link ain48Immediate Constant
hi link ain48Directive PreProc
hi link ain48Label Label
hi link ain48Register Identifier