1
0

initial commit

This commit is contained in:
2026-05-31 12:33:05 +02:00
commit 5788c5d807
13 changed files with 1836 additions and 0 deletions

6
.clang-format Normal file
View File

@ -0,0 +1,6 @@
---
BasedOnStyle: LLVM
AccessModifierOffset: -4
IndentWidth: 4
QualifierAlignment: Right

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
/compile_commands.json
/out
/docs/*.pdf
/ain48

61
Makefile Normal file
View File

@ -0,0 +1,61 @@
# PROGRAMS
CC = clang
CXX = clang++
LD = clang
AR = ar
RM = rm -f
TYPST = typst
# COMPILATION FLAGS
LIBS = raylib
ifdef DEBUG
CFLAGS += -Og -g -DDEBUG
else
CFLAGS += -O2
endif
CFLAGS += -Wall -Wextra -pedantic -std=gnu23 -Iinclude -Werror=return-type $(shell pkg-config --cflags $(LIBS))
LDFLAGS += $(shell pkg-config --libs $(LIBS))
# FILES
SRCS=$(wildcard src/*.c)
DEPS=$(patsubst src/%.c, out/%.d, $(SRCS))
OBJS=$(patsubst src/%.c, out/%.o, $(SRCS))
DOCSRC=$(wildcard docs/*.typ)
DOCS=$(patsubst docs/%.typ, docs/%.pdf, $(DOCSRC))
PROGRAM=ain48
.PHONY: all build docs clean deepclean
all: build docs
build: $(PROGRAM)
docs: $(DOCS)
docs/%.pdf: docs/%.typ
$(TYPST) c $< $@
clean:
$(RM) $(PROGRAM)
$(RM) $(DOCS)
deepclean: clean
$(RM) $(OBJS)
$(RM) $(DEPS)
$(RM) compile_commands.json
$(PROGRAM): $(OBJS)
$(LD) $(LDFLAGS) $(OBJS) -o $@
out/%.d: src/%.c
@set -e ; $(RM) $@; \
$(CC) -M $(CFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,out/\1.o $@ : ,g' < $@.$$$$ > $@; \
$(RM) $@.$$$$
out/%.o: src/%.c
$(CC) $(CFLAGS) -c $< -o $@
include $(DEPS)

31
docs/.template.typ Normal file
View File

@ -0,0 +1,31 @@
#import "@preview/cetz:0.5.2"
#import "@preview/smartaref:0.1.0": cref
#import "@preview/libra:0.1.0": balance
#let conf(doc) = {
set page(paper: "a4", numbering: "1")
set text(
font: "Iosevka Etoile",
features: (cv47: 10),
number-type: "old-style",
weight: 400,
size: 12pt,
)
set par(justify: true)
set heading(numbering: "I.1")
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 strong: text.with(weight: 900)
set figure(numbering: "1", placement: auto)
show heading.where(level: 3): set heading(numbering: none)
show figure.caption: it => balance(box(width: 100%, {
it.supplement
[ ]
it.counter.display(it.numbering)
[ --- ]
it.body
}))
set raw(theme: "./gruvbox-white.tmTheme")
show raw.where(lang: "ain48"): set raw(syntaxes: "./ain48.sublime-syntax")
doc
}

28
docs/ain48.sublime-syntax Normal file
View File

@ -0,0 +1,28 @@
%YAML 1.2
---
name: Ain48
file_extensions:
- a48s
scope: source.ain48asm
contexts:
main:
- match: '(?i)\b(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)\b'
scope: keyword.operator.word.ain48
- match: '(?i)%([a-z0-7]+)\b'
scope: variable.register.ain48
- match: '#-?([0-5]+|o[0-7]+|b[01]+|x[0-9]+)\b'
scope: constant.numeric.ain48
- match: '#imm\[[0-9n]+\]'
scope: constant.numeric.ain48
- match: ';'
scope: comment
push: comments
- match: '^[a-zA-Z0-9_-]+:$'
scope: keyword.control.label.ain48
- match: '^.[a-zA-Z]+'
scope: keyword.directive.ain48
comments:
- meta_scope: comment
- match: '\n'
scope: comment
pop: true

828
docs/gruvbox-white.tmTheme Normal file
View File

@ -0,0 +1,828 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>comment</key>
<string>Based on original gruvbox color scheme.</string>
<key>author</key>
<string>Martin Radimec</string>
<key>name</key>
<string>gruvbox</string>
<key>settings</key>
<array>
<dict>
<key>settings</key>
<dict>
<key>background</key>
<string>#ffffff</string>
<key>caret</key>
<string>#3C3836</string>
<key>foreground</key>
<string>#3C3836aa</string>
<key>invisibles</key>
<string>#DA9734</string>
<key>lineHighlight</key>
<string>#FAF4D9</string>
<key>selection</key>
<string>#EDDAB5</string>
<key>bracketContentsForeground</key>
<string>#928374</string>
<key>bracketsForeground</key>
<string>#d5c4a1</string>
<key>guide</key>
<string>#EDDAB5</string>
<key>activeGuide</key>
<string>#7c6f64</string>
<key>stackGuide</key>
<string>#BEAD95</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Punctuation</string>
<key>scope</key>
<string>punctuation.definition.tag</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#418587</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Punctuation</string>
<key>scope</key>
<string>punctuation.definition.entity</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#B36586</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Constant</string>
<key>scope</key>
<string>constant</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#B36586</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Constant escape</string>
<key>scope</key>
<string>constant.character.escape</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#9A942C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Constant other</string>
<key>scope</key>
<string>constant.other</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#282828</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Entity</string>
<key>scope</key>
<string>entity</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#679B6C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Keyword</string>
<key>scope</key>
<string>keyword.operator.comparison, keyword.operator, keyword.operator.symbolic, keyword.operator.string, keyword.operator.assignment, keyword.operator.arithmetic, keyword.operator.class, keyword.operator.key, keyword.operator.logical</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#B23C15</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Keyword</string>
<key>scope</key>
<string>keyword, keyword.operator.new, keyword.other, keyword.control</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#D02B26</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Storage</string>
<key>scope</key>
<string>storage</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#D02B26</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>String</string>
<key>scope</key>
<string>string -string.unquoted.old-plist -string.unquoted.heredoc, string.unquoted.heredoc string</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#9A942C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Comment</string>
<key>scope</key>
<string>comment</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#938375</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Regexp</string>
<key>scope</key>
<string>string.regexp constant.character.escape</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#9A942C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Support</string>
<key>scope</key>
<string>support</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#DA9734</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Variable</string>
<key>scope</key>
<string>variable</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#282828</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Lang Variable</string>
<key>scope</key>
<string>variable.language</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#282828</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Function Call</string>
<key>scope</key>
<string>meta.function-call</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#282828</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Invalid</string>
<key>scope</key>
<string>invalid</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#932b1e</string>
<key>foreground</key>
<string>#282828</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Embedded Source</string>
<key>scope</key>
<string>text source, string.unquoted.heredoc, source source</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#282828</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>String embedded-source</string>
<key>scope</key>
<string>string.quoted source</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#9A942C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>String constant</string>
<key>scope</key>
<string>string</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#9A942C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Support.constant</string>
<key>scope</key>
<string>support.constant</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#DA9734</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Support.class</string>
<key>scope</key>
<string>support.class</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#679B6C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Meta.tag.A</string>
<key>scope</key>
<string>entity.name.tag</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
<key>foreground</key>
<string>#679B6C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Inner tag</string>
<key>scope</key>
<string>meta.tag, meta.tag entity</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#679B6C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>css colors</string>
<key>scope</key>
<string>constant.other.color.rgb-value</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#418587</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>css tag-name</string>
<key>scope</key>
<string>meta.selector.css entity.name.tag</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#D02B26</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>css#id</string>
<key>scope</key>
<string>meta.selector.css, entity.other.attribute-name.id</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#9A942C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>css.class</string>
<key>scope</key>
<string>meta.selector.css entity.other.attribute-name.class</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#9A942C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>css property-name:</string>
<key>scope</key>
<string>support.type.property-name.css</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#679B6C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>css @at-rule</string>
<key>scope</key>
<string>meta.preprocessor.at-rule keyword.control.at-rule</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#DA9734</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>css additional-constants</string>
<key>scope</key>
<string>meta.property-value constant</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#DA9734</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>css additional-constants</string>
<key>scope</key>
<string>meta.property-value support.constant.named-color.css</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#B23C15</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>css constructor.argument</string>
<key>scope</key>
<string>meta.constructor.argument.css</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#DA9734</string>
</dict>
</dict>
<!-- diff -->
<dict>
<key>name</key>
<string>diff.header</string>
<key>scope</key>
<string>meta.diff, meta.diff.header</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#418587</string>
<key>foreground</key>
<string>#282828</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>diff.deleted</string>
<key>scope</key>
<string>markup.deleted</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#D02B26</string>
<key>foreground</key>
<string>#282828</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>diff.changed</string>
<key>scope</key>
<string>markup.changed</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#DA9734</string>
<key>foreground</key>
<string>#282828</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>diff.inserted</string>
<key>scope</key>
<string>markup.inserted</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#679B6C</string>
<key>foreground</key>
<string>#282828</string>
</dict>
</dict>
<!-- markup -->
<dict>
<key>name</key>
<string>Bold Markup</string>
<key>scope</key>
<string>markup.bold</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Italic Markup</string>
<key>scope</key>
<string>markup.italic</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Heading Markup</string>
<key>scope</key>
<string>markup.heading</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
<key>foreground</key>
<string>#679B6C</string>
</dict>
</dict>
<!-- Language Specific -->
<!-- PHP -->
<dict>
<key>name</key>
<string>PHP: class name</string>
<key>scope</key>
<string>entity.name.type.class.php</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#679B6C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>PHP: Comment</string>
<key>scope</key>
<string>keyword.other.phpdoc</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#938375</string>
</dict>
</dict>
<!-- CSS -->
<dict>
<key>name</key>
<string>CSS: numbers</string>
<key>scope</key>
<string>constant.numeric.css, keyword.other.unit.css</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#B36586</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>CSS: entity dot, hash, comma, etc.</string>
<key>scope</key>
<string>punctuation.definition.entity.css</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#9A942C</string>
</dict>
</dict>
<!-- JS -->
<dict>
<key>name</key>
<string>JS: variable</string>
<key>scope</key>
<string>variable.language.js</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#DA9734</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>JS: unquoted labe</string>
<key>scope</key>
<string>string.unquoted.label.js</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#282828</string>
</dict>
</dict>
<!-- SQL -->
<dict>
<key>name</key>
<string>Constant other sql</string>
<key>scope</key>
<string>constant.other.table-name.sql</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#9A942C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Constant other sql</string>
<key>scope</key>
<string>constant.other.database-name.sql</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#9A942C</string>
</dict>
</dict>
<!-- Plugins -->
<!-- dired plugin -->
<dict>
<key>name</key>
<string>dired directory</string>
<key>scope</key>
<string>storage.type.dired.item.directory, dired.item.directory</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#679B6C</string>
</dict>
</dict>
<!-- orgmode plugin -->
<dict>
<key>name</key>
<string>orgmode link</string>
<key>scope</key>
<string>orgmode.link</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#DA9734</string>
<key>fontStyle</key>
<string>underline</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>orgmode page</string>
<key>scope</key>
<string>orgmode.page</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#9A942C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>orgmode break</string>
<key>scope</key>
<string>orgmode.break</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#B36586</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>orgmode headline</string>
<key>scope</key>
<string>orgmode.headline</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#679B6C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>orgmode tack</string>
<key>scope</key>
<string>orgmode.tack</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#DA9734</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>orgmode follow up</string>
<key>scope</key>
<string>orgmode.follow_up</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#DA9734</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>orgmode checkbox</string>
<key>scope</key>
<string>orgmode.checkbox</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#DA9734</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>orgmode checkbox summary</string>
<key>scope</key>
<string>orgmode.checkbox.summary</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#DA9734</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>orgmode tags</string>
<key>scope</key>
<string>orgmode.tags</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#D02B26</string>
</dict>
</dict>
<!-- AIN 48 -->
<dict>
<key>name</key>
<string>ain48 assembly label</string>
<key>scope</key>
<string>keyword.control.label.ain48</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#076678</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>ain48 assembly instruction</string>
<key>scope</key>
<string>keyword.operator.word.ain48</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#af3a03</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>ain48 assembly register</string>
<key>scope</key>
<string>variable.register.ain48</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#79740e</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>ain48 assembly constants</string>
<key>scope</key>
<string>constant.numeric.ain48</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#8f3f71</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>ain48 assembly directive</string>
<key>scope</key>
<string>keyword.directive.ain48</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#b57614</string>
</dict>
</dict>
</array>
</dict>
</plist>

677
docs/isa.typ Normal file
View File

@ -0,0 +1,677 @@
#import ".template.typ": *
#show: conf
#title[AIN-48 Instruction Set Architecture]
#align(center, grid(
columns: 4,
column-gutter: .5em,
align: left + horizon,
row-gutter: .5em,
grid.cell(rowspan: 2)[Architectúra],
[Internátionális],
[Nórmae],
grid.cell(rowspan: 2)[--- 48 bit],
[Intstrúctiónum],
[Numerátiónum],
))
#show heading: set text(weight: 900)
#show heading: it => [
#set par(justify: false)
#grid(columns: (auto, 1fr), column-gutter: .25em, if it.numbering != none {
context [#counter(heading).display(it.numbering)]
} else [], it.body)
]
= Conventions
A *byte* (singulus) is the smallest adressable part of memory, that is, a 12-bit
binary number.
A *word* (quaternus) is a binary number composed of 4 bytes, that is, a 48 bit
binary number.
In memory, multibyte numbers are laid out with the least significant byte at the
lowest memory adress
= Registers
The main registers of the architecture are all word-length:
#columns(2)[
/ %0/%nul:Constant zero
/ %01: General purpose
/ %02: General purpose
/ %03: General purpose
/ %04: General purpose
/ %05: General purpose
/ %06: General purpose
/ %07: General purpose
/ %ia: Index ad actiónem\ (Instruction pointer)
#colbreak()
/ %10: General purpose
/ %11: General purpose
/ %12: General purpose
/ %13: General purpose
/ %14: General purpose
/ %15: General purpose
/ %16: General purpose
/ %17/%it: Index ad turrim\ (Stack pointer)
]
There is also a 3-bit status register.
= Instructions as encoded
In instruction diagrams, each large rectangle represents a byte, that are
disposed in memory as implied by the reading order, starting at the lowest
memory adress.
#let instruction_diagram(..bytes, voff: 0) = {
import cetz.draw: *
for (i, b) in bytes.pos().enumerate() {
let j = 0
for (l, d) in b {
content((i * 12.5 + j + l / 2, 1 + voff), d)
j = j + l
line((i * 12.5 + j, voff), (i * 12.5 + j, 2 + voff), stroke: gray)
}
rect((i * 12.5, voff), (i * 12.5 + 12, 2 + voff))
for j in range(0, 13) {
line((i * 12.5 + j, .125 + voff), (i * 12.5 + j, -.125 + voff))
line((i * 12.5 + j, 2.125 + voff), (i * 12.5 + j, 1.875 + voff))
}
content((i * 12.5, voff + 2.25), anchor: "south-west")[11]
content((i * 12.5 + 12, voff + 2.25), anchor: "south-east")[0]
}
}
#let amal = [Actió Machinae Arithméticae Logicaeque]
== #amal
#align(
center,
cetz.canvas(
{
import cetz.draw: *
scale(.65)
instruction_diagram((
(1, [0]),
(1, [0]),
(1, [0]),
(1, [0]),
(1, [0]),
(1, [i#sub[2]\ 0]),
(1, [i#sub[1]\ 0]),
(1, [s]),
(4, [op]),
), ((4, [r#sub[d]]), (4, [r#sub[2]]), (4, [r#sub[1]])))
content((12.25, -1))[or]
instruction_diagram(voff: -5, (
(1, [0]),
(1, [0]),
(1, [0]),
(1, [0]),
(1, [0]),
(1, [i#sub[2]\ 0]),
(1, [i#sub[1]\ 1]),
(1, [s]),
(4, [op]),
), ((4, [r#sub[d]]), (4, [r#sub[2]]), (4, text(size: .9em)[imm[0:3]])))
content((12.25, -6))[or]
instruction_diagram(voff: -10, (
(1, [0]),
(1, [0]),
(1, [0]),
(1, [0]),
(1, [0]),
(1, [i#sub[2]\ 1]),
(1, [i#sub[1]\ 0]),
(1, [s]),
(4, [op]),
), ((4, [r#sub[d]]), (4, text(size: .9em)[imm[0:3]]), (4, [r#sub[1]])))
content((12.25, -11))[or]
instruction_diagram(voff: -15, (
(1, [0]),
(1, [0]),
(1, [0]),
(1, [0]),
(1, [0]),
(1, [i#sub[2]\ 1]),
(1, [i#sub[1]\ 1]),
(1, [s]),
(4, [op]),
), ((4, [r#sub[d]]), (8, [imm[0:7]])))
},
),
)
#let iml = [Immediátum Magnum Lectura]
== #iml
#align(
center,
cetz.canvas(
{
import cetz.draw: *
scale(.65)
instruction_diagram((
(1, [0]),
(1, [0]),
(1, [0]),
(1, [1]),
(1, [0]),
(1, [0]),
(1, [0]),
(1, [s]),
(4, [r]),
), ((12, [imm[0:11]]),))
instruction_diagram(((12, [imm[12:23]]),), ((12, [ımm[24:35]]),), voff: -3)
instruction_diagram(((12, [imm[36:47]]),), voff: -6)
},
),
)
#let ipl = [Immediátum Parvum Lectura]
== #ipl
#align(center, cetz.canvas({
import cetz.draw: *
scale(.65)
instruction_diagram((
(1, [0]),
(1, [0]),
(1, [0]),
(1, [1]),
(1, [1]),
(1, [0]),
(1, [0]),
(1, [s]),
(4, [r]),
), ((12, [imm[0:11]]),))
}))
#let amls = [Ad Memóriam Lectura Scripturaque]
== #amls
#align(center, cetz.canvas({
import cetz.draw: *
scale(.65)
instruction_diagram((
(1, [0]),
(1, [0]),
(1, [1]),
(1, [w]),
(4, [r#sub[d]]),
(4, [r#sub[a]]),
), ((12, [imm[0:11]]),))
}))
#let asss = [Actió Sequentiae Singulí Simplicis]
== #asss
#align(center, cetz.canvas({
import cetz.draw: *
scale(.65)
instruction_diagram((
(1, [1]),
(1, [1]),
(1, [1]),
(1, [1]),
(1, [1]),
(1, [1]),
(1, [1]),
(1, [1]),
(1, [1]),
(3, [op]),
))
}))
#let asli = [Actió Sequentiae Locí Immediátí]
== #asli
#align(
center,
cetz.canvas(
{
import cetz.draw: *
scale(.65)
instruction_diagram((
(1, [1]),
(1, [0]),
(1, [0]),
(1, [0]),
(1, [0]),
(1, [0]),
(1, [0]),
(1, [I]),
(1, [C]),
(1, [N]),
(1, [Z]),
(1, [R]),
), ((12, [imm[0:11]]),))
instruction_diagram(((12, [imm[12:23]]),), ((12, [ımm[24:35]]),), voff: -3)
instruction_diagram(((12, [imm[36:47]]),), voff: -6)
},
),
)
#let aslr = [Actió Sequentiae Loci Recordandí]
== #aslr
#align(center, cetz.canvas({
cetz.draw.scale(.65)
instruction_diagram((
(1, [1]),
(1, [0]),
(1, [1]),
(4, [r#sub[a]]),
(1, [I]),
(1, [C]),
(1, [N]),
(1, [Z]),
(1, [R]),
))
}))
#let asrd = [Actió Sequentiae Recordandó Dépositus]
== #asrd
#align(center, cetz.canvas({
cetz.draw.scale(.65)
instruction_diagram((
(1, [1]),
(1, [1]),
(1, [0]),
(4, [r#sub[a]]),
(1, [I]),
(1, [C]),
(1, [N]),
(1, [Z]),
(1, [R]),
), ((12, [imm[0:11]]),))
}))
#pagebreak(weak: true)
= Instructions by their mnemonics
Common Notations:
/ ```ain48 %a, %b, %c, ...```: any register a, b, c
/ ```ain48 #imm[n]```: An immediate (max: n bits)
/ ```ain48 %0, %nul```: Writes to ```ain48 %0 / %nul``` are discarded
/ ```ain48 (%a)```: The memory at the adress contained by %a
/ ```ain48 (#imm[n])```: The memory at the adress represented by the immediate (max n bits)
/ ```ain48 a_label```: The memory adress correspoding to the label
#let ristr(mnem) = [*#raw(mnem, lang: "ain48")* (#ref(label("ins:" + mnem), form: "page"))]
#let istr(mnem) = strong(raw(mnem, lang: "ain48"))
#let opt(a, b) = box[
*#a* = #b
]
#let optgrid(..opts) = block({
text(weight: 900)[Instruction parameters]
linebreak()
h(1em)
opts.pos().join(h(2em))
})
#let aludoc(mnemonic, opnum, opsym, commutative, s) = [
#optgrid(opt[op][#opnum], opt[s][#s])
/ Instruction format: #amal
/ #raw(mnemonic + " %a, %b, %c", lang: "ain48"): %a %b #opsym %c
#optgrid(
opt[i#sub[1]][0],
opt[i#sub[2]][0],
opt[r#sub[d]][a],
opt[r#sub[1]][b],
opt[r#sub[2]][c],
)
/ #raw(mnemonic + " %a, %b, #imm[4]", lang: "ain48"): %a %b #opsym imm
#optgrid(
opt[i#sub[1]][0],
opt[i#sub[2]][1],
opt[r#sub[d]][a],
opt[r#sub[1]][b],
opt[imm][imm],
)
#if not commutative [
/ #raw(mnemonic + " %a, #imm[4], %b", lang: "ain48"): %a imm #opsym %b
#optgrid(
opt[i#sub[1]][1],
opt[i#sub[2]][0],
opt[r#sub[d]][a],
opt[r#sub[2]][b],
opt[imm][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])
]
#let instructions = (
(mnem: "STR", name: "Subtrahere", sign: true, description: [
Subtract one signed number from another
#aludoc("STR", "01", "-", false, 1)
]),
(mnem: "ADD", name: "Addere", sign: true, description: [
Add two signed numbers together.
#aludoc("ADD", "00", "+", true, 1)
]),
(mnem: "MPL", name: "Multiplicáre", sign: true, description: [
Multiply two signed numbers together
#aludoc("MPL", "02", "×", true, 1)
/ Instruction format: #amal
]),
(mnem: "RSD", name: "Residérí", sign: true, description: [
Reminder of the euclidian division of two words
#aludoc("RSD", "05", "mod", false, 1)
]),
(mnem: "DVD", name: "Dívidere", sign: true, description: [
Divide a signed number by another
#aludoc("DVD", "04", "/", false, 1)
]),
(mnem: "DEM", name: "Ad Dextró Movére", sign: true, description: [
Shift a signed number left by a signed number.
#aludoc("DEM", "06", ">>", false, 1)
]),
(mnem: "SIM", name: "Ad Sinistró Movére", description: [
Shift a word to the left
#aludoc("SIM", "07", "<<", false, 0)
]),
(
mnem: "ILG",
name: "Immediátum Legere",
sign: true,
description: [
Load a signed immediate value into a register
/ ```ain48 ILG %a, #imm[12]```: %a imm
/ Instruction format: #ipl
#optgrid(opt[s][1], opt[r][a], opt[imm][imm])
/ ```ain48 ILG %a, #imm[48]```: %a imm
/ Instruction format: #iml
#optgrid(opt[s][1], opt[r][a], opt[imm][imm])
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
the programmer to explicitely request one format or the other: #istr("IMLG") uses #iml and
#istr("IPLG") uses #ipl.
],
also: (
("IPLG", "Immediátum Parvum Legere"),
("IMLG", "Immediátum Magnum Legere"),
),
),
(
mnem: "I",
name: "Íre",
description: [
Go to
/ ```ain48 I a_label```: %ia a_label
/ Instruction Format: #asli
#optgrid(
opt[I][1],
opt[C][0],
opt[N][0],
opt[Z][0],
opt[R][0],
opt[imm][a_label],
)
Some assemblers may opt to assemble calls to nearby labels as if they were of
the form `IRE %0, #imm[12]` with no loss of correctness.
/ ```ain48 I #imm[48]```: %ia imm\
/ Instruction Format: #asli
#optgrid(
opt[I][1],
opt[C][0],
opt[N][0],
opt[Z][0],
opt[R][0],
opt[imm][a_label],
)
/ ```ain48 I %a```: %ia %a\
/ Instruction Format: #aslr
#optgrid(
opt[I][1],
opt[C][0],
opt[N][0],
opt[Z][0],
opt[R][0],
opt[r#sub[a]][a],
)
/ ```ain48 I %nul, #imm[12]```: %ia %ia + %a
/ Instruction Format: #asrd
#optgrid(
opt[I][1],
opt[C][0],
opt[N][0],
opt[Z][0],
opt[R][0],
opt[r#sub[a]][0],
opt[imm][imm],
)
This is a special case of the format just below, where becasue offsetting from
%nul is useless, we instead understand it as an offset from %ia
/ ```ain48 I %a, #imm[12]```: %ia %a + imm
/ Instruction Format: #asrd
#optgrid(
opt[I][1],
opt[C][0],
opt[N][0],
opt[Z][0],
opt[R][0],
opt[r#sub[a]][a],
opt[imm][imm],
)
],
also: (
(
"UI",
"Si nullus est íre",
[
Used like #istr("I") but only jump if the zero bit of the staus flag is set.\
#optgrid(opt[I][0], opt[Z][1])
],
),
(
"NUI",
"Si nón nullus est íre",
[
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])
],
),
(
"NI",
"Si negatívus est íre",
[
Used like #istr("I") but only jump if the negative bit of the status flag is set.\
#optgrid(opt[I][0], opt[N][1])
],
),
(
"NNI",
"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.\
#optgrid(opt[I][1], opt[N][1])
],
),
(
"EI",
"Si excedit íre",
[
Used like #istr("I") but only jump if the carry bit of the status flag is set.\
#optgrid(opt[I][0], opt[C][1])
],
),
(
"NEI",
"Si nón excedit íre",
[
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])
],
),
(
"PI",
"Si positívus est íre",
[
Used like #istr("I") but only jump if neither the zero nor negative flags of the status
flag is set.
#optgrid(opt[I][1], opt[N][1], opt[Z][1])
],
),
(
"NPI",
"Si nón positívus est íre",
[
Used like #istr("I") but only jump if either the zero or negative flags of the status
flag are set.
#optgrid(opt[I][0], opt[N][1], opt[Z][1])
],
),
("IVC", "Invocáre", [
Used like #istr("I") but sets up a function environment prior to jumping:\
(%it) %ia; %it %it - 4
#optgrid(opt[R][1])
],),
),
),
(
mnem: "NCIVC",
name: "In Nucleó Invocáre",
description: [
Invoke a kernel space function, see your operating system's ABI for more
details.
/ Instruction format: #asss
#optgrid(opt[op][3])
/ ```ain48 NCIVC```: Perform a kernel call.
],
),
(mnem: "IRRV", name: "De Interruptó Reveníre", description: [
*Priviledged*
Instrucion used to exit from the interrupt handler.
#optgrid(opt[op][4])
]),
(mnem: "NCRV", name: "De Nucleó Reveníre", description: [
*Priviledged*
Return to user space after a system call
/ Instruction Format: #asss
#optgrid(opt[op][2])
]),
(mnem: "VEL", name: "Vel", description: [
Bitwise disjunction between two words
#aludoc("VEL", [11], sym.or, true, 0)
]),
(mnem: "NEC", name: "Nec", description: [
Bitwise negated disjunction between two words
#aludoc("NEC", [15], sym.not + sym.or, true, 0)
]),
(mnem: "AUT", name: "Aut", description: [
Bitwise difference between two numbers.
#aludoc("AUT", [12], sym.xor, true, 0)
]),
(mnem: "AEQ", name: "Aequí", description: [
Bitwise equality between two numbers.
#aludoc("AEQ", [16], [=], true, 0)
]),
(mnem: "ET", name: "Et", description: [
Bitwise logical conjunction between two numbers.
#aludoc("ET", [10], sym.and, true, 0)
]),
(mnem: "NAM", name: "Non ambó", description: [
Bitwise negated logical conjunction between two numbers.
#aludoc("NAM", [14], sym.not + sym.and, true, 0)
]),
(
mnem: "LG",
name: "Legere",
description: [
Read a word from memory
/ Instruction Format: #amls
/ ```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])
/ ```ain48 LG %a, (%b)```: This is a special case of ```ain48 LG %a, (%b), #imm[12]``` where imm = 0
],
),
(
mnem: "SC",
name: "Scríbere",
description: [
Write a word to memory
/ Instruction Format: #amls
/ ```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])
/ ```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: [
Halts Execution of the process
/ Instruction Format: #asss
#optgrid(opt[op][7])
/ ```ain48 CESS```: Pause execution.
]),
(mnem: "RV", name: "Reveníre", description: [
Returns from a subroutine.
/ Instruction Format: #asss
#optgrid(opt[op][0])
/ ```ain48 RV```: %it %it - 4; %ia (%it)
]),
(mnem: "CST", name: "Construere", description: [
Push the contents of a register onto the stack:
/ ```ain48 CST %a```: This instruction is a macro implemented as follows:\
#raw(block: true, "SC %a, (%it)\nPSTR %it, #4", lang: "ain48")
]),
(mnem: "DST", name: "Destruere", description: [
Push the contents of a register onto the stack:
/ ```ain48 DST %a```: This instruction is a macro implemented as follows:\
#raw(block: true, "PADD %it, #4\nLG %a, (%it)", lang: "ain48")
]),
(mnem: "TSC", name: "Transcríbere", description: [
Copy between registers
/ ```ain48 TSC %a, %b```: %a %b. Macro for ```ain48 VEL %a, %b, %nul```
]
),
)
#instructions.map(
it => {
let arr = ((mnem: it.mnem, desc: block(breakable: false, width: 100%)[
== #it.mnem | #it.name
#label("ins:" + it.mnem)
#it.description
#if it.keys().contains("sign") [See also #ristr("P" + it.mnem)]
]),)
if it.keys().contains("sign") {
arr.push((mnem: "P" + it.mnem, desc: [
== P#(it.mnem) | Positívós #it.name
#label("ins:P" + it.mnem)
Same form(s) as #istr(it.mnem) but with s = 0\
Unsigned version of #ristr(it.mnem)
]))
}
if it.keys().contains("also") {
for (m, n, ..r) in it.also {
arr.push((mnem: m, desc: [
== #m | #n
#label("ins:" + m)
#r.join()
See #ristr(it.mnem)
]))
if it.keys().contains("sign") {
arr.push(
(
mnem: "P" + m,
desc: [
== P#m | Positivós #n
Unsigned version of #m, see #ristr("P" + it.mnem) and #ristr(it.mnem)
],
),
)
}
}
}
arr
},
).join().sorted(key: it => it.mnem).map(it => it.desc).join()
#pagebreak(weak: true)
#outline(depth: 2)

35
docs/ucsd_abi.typ Normal file
View File

@ -0,0 +1,35 @@
#import ".template.typ": *
#show: conf
#title[Unichal Software Distribution System ABI\ Version 3.4 for AIN-48]
© University of Chalmosique, Cross. 301 -- Cross. 319
= Object Format
b
= Integer representation
= Calling convention
== Parameter passing
== Return value passing
== Call Sequence
```ain48
.at #o00000000
fib_n:
ilg %2, #0
ilg %3, #1
__loop:
padd %4, %3, %2
tsc %2, %3
tsc %3, %3
pstr %1, #1
nui __loop
tsc %1, %2
rv
```
#pagebreak(weak: true)
#outline(depth: 2)

11
include/ain48.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef AIN48__H
#define AIN48__H
#include <assert.h>
#include <common.h>
// #ifdef AIN49__IMPL
// #endif // def AIN48__IMPL
#endif // AIN48__H

47
include/common.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef __UCSD_COMMON_H__
#define __UCSD_COMMON_H__
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
// # NUMBER TYPES
typedef uint8_t u8;
typedef unsigned _BitInt(12) u12;
typedef uint16_t u16;
typedef uint32_t u32;
typedef unsigned _BitInt(48) u48;
typedef uint64_t u64;
typedef unsigned __int128 u128;
typedef size_t usz;
typedef uintptr_t uptr;
typedef _BitInt(4) i4;
typedef int8_t i8;
typedef _BitInt(12) i12;
typedef int16_t i16;
typedef int32_t i32;
typedef _BitInt(48) i48;
typedef int64_t i64;
typedef __int128 i128;
typedef ssize_t isz;
typedef intptr_t iptr;
typedef float f32;
typedef double f64;
// # LOGGING FACILITES
[[gnu::format(printf, 1, 2)]] void log_debug(char const *format, ...);
[[gnu::format(printf, 1, 2)]] void log_warn(char const *format, ...);
[[gnu::format(printf, 1, 2)]] void log_err(char const *format, ...);
[[gnu::format(printf, 1, 2)]] void log_err_errno(char const *format, ...);
void set_log_opts(FILE *f, bool colours);
extern int foo;
#endif // ndef __UCSD_COMMON_H__

28
src/asm.c Normal file
View File

@ -0,0 +1,28 @@
#include <common.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
i32 asm_main(i32 argc, char *argv[]) {
if (argc != 3) {
log_err("Usage: asm source.a48s dest.bin");
return 1;
}
int soruce_file = open(argv[1], O_RDONLY);
if (soruce_file < 0) {
log_err_errno("Failed to open file `%s`", argv[1]);
return 1;
}
struct stat statres;
if (fstat(soruce_file, &statres) < 0) {
log_err_errno("Failed to stat file `%s`", argv[1]);
return 1;
}
if (statres.st_size == 0) {
log_err("Cannot assemble an empty file");
return 1;
}
return 0;
}

52
src/logging.c Normal file
View File

@ -0,0 +1,52 @@
#include <common.h>
#include <stdio.h>
#include <errno.h>
#include <stdarg.h>
#include <string.h>
FILE *logfile;
bool logcolours = true;
[[gnu::constructor(101)]] void init_logging() {
logfile = stderr;
}
#ifndef DEBUG
void log_debug([[maybe_unused]] const char* format, ...) {}
#else
void log_debug(const char* format, ...) {
fprintf(logfile, "%s[DEBUG]%s ", logcolours ? "\033[1;44;97m" : "", logcolours ? "\033[0" : "");
va_list va;
va_start(va);
vfprintf(logfile, format, va);
va_end(va);
fprintf(logfile, "\n");
}
#endif
void log_warn(const char* format, ...) {
fprintf(logfile, "%s[WARN]%s ", logcolours ? "\033[1;43;97m": "", logcolours ? "\033[0m" : "");
va_list va;
va_start(va);
vfprintf(logfile, format, va);
va_end(va);
fprintf(logfile, "\n");
}
void log_err(const char* format, ...) {
fprintf(logfile, "%s[ERROR]%s ", logcolours ? "\033[1;41;97m": "", logcolours ? "\033[0m" : "");
va_list va;
va_start(va);
vfprintf(logfile, format, va);
va_end(va);
fprintf(logfile, "\n");
}
void log_err_errno(const char* format, ...) {
fprintf(logfile, "%s[ERROR]%s ", logcolours ? "\033[1;41;97m": "", logcolours ? "\033[0m" : "");
va_list va;
va_start(va);
vfprintf(logfile, format, va);
va_end(va);
fprintf(logfile, ": %s\n", strerror(errno));
}
void set_log_opts(FILE *f, bool colours) {
logfile = f;
logcolours = colours;
}

27
src/main.c Normal file
View File

@ -0,0 +1,27 @@
#include <common.h>
#include <stdio.h>
#include <string.h>
enum subprorgram {
ASM,
SIM,
};
const char *available = (R"m(
asm
)m");
i32 asm_main(i32 argc, char *argv[]);
i32 main(i32 argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "No subprogram called\nAvalible subprograms:%s\n", available);
return 1;
}
if (!strcmp(argv[1], "asm")) {
return asm_main(argc - 1, argv + 1);
} else {
fprintf(stderr, "Unknown subprogram `%s`\nAvailable subpograms:%s", argv[1], available);
return 1;
}
}