1
0

Compare commits

...

4 Commits

Author SHA1 Message Date
2317f1e2b7 programs: start rewrite to haskell 2026-06-08 14:03:05 +02:00
30ff19d7ff docs: isa: add sized instructions 2026-06-08 13:59:47 +02:00
cinthyr
52b743de9a tooling: add syntax highlighting for Kakoune
Signed-off-by: Annwan <annwan@annwan.me>
2026-06-05 15:34:49 +02:00
cinthyr
f1ef3d99f1 typo: [0-5]+ > s[0-5]+
Signed-off-by: Annwan <annwan@annwan.me>
2026-06-03 11:25:38 +02:00
16 changed files with 553 additions and 655 deletions

2
.gitignore vendored
View File

@ -4,4 +4,6 @@
/docs/*.pdf /docs/*.pdf
/ain48 /ain48
/scratch /scratch
/programs/dist-newstyle/

View File

@ -1,67 +0,0 @@
# 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, build/%.d, $(SRCS))
OBJS=$(patsubst src/%.c, build/%.o, $(SRCS))
DOCSRC=$(wildcard docs/*.typ)
DOCS=$(patsubst docs/%.typ, docs/%.pdf, $(DOCSRC))
PROGRAM=ain48
.PHONY: all build docs clean deepclean setup
all: setup build docs
setup: compile_flags.txt
build: $(PROGRAM)
docs: $(DOCS)
docs/%.pdf: docs/%.typ
$(TYPST) c $< $@
clean:
$(RM) $(OBJS)
$(RM) $(DEPS)
$(RM) compile_flags.txt
deepclean: clean
$(RM) $(PROGRAM)
$(RM) $(DOCS)
compile_flags.txt: Makefile
printf "%s\n" $(CFLAGS) > $@
$(PROGRAM): $(OBJS)
$(LD) $(LDFLAGS) $(OBJS) -o $@
build/%.d: src/%.c
@mkdir -p $(@D)
@set -e ; $(RM) $@; \
$(CC) -M $(CFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,build/\1.o $@ : ,g' < $@.$$$$ > $@; \
$(RM) $@.$$$$
build/%.o: src/%.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) -c $< -o $@
include $(DEPS)

17
docs/Makefile Normal file
View File

@ -0,0 +1,17 @@
# PROGRAMS
RM = rm -f
TYPST = typst
# FILES
DOCSRC=$(wildcard *.typ)
DOCS=$(DOCSRC:.typ=.pdf)
.PHONY: all docs clean
all: docs
docs: $(DOCS)
%.pdf: %.typ
$(TYPST) c $< $@
clean:
$(RM) $(DOCS)

View File

@ -6,11 +6,11 @@ file_extensions:
scope: source.ain48asm scope: source.ain48asm
contexts: contexts:
main: 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' - match: '(?i)\b(P?[SBQ]?(ADD|DEM|DVD|MPL|RSD|SIM|STR)|AEQ|AN|AUT|[SBQ]?(LG|SC)|CESS|CST|DST|(N?[ENUP])?I|ET|P?I[MP]?LG|IRRV|(NC)?(IVC|RV)|NAM|NEC|TSC|VEL)\b'
scope: keyword.operator.word.ain48 scope: keyword.operator.word.ain48
- match: '(?i)%([a-z0-7]+)\b' - match: '(?i)%([a-z0-7]+)\b'
scope: variable.register.ain48 scope: variable.register.ain48
- match: '#-?([0-5]+|o[0-7]+|b[01]+|x[0-9]+)\b' - match: '#-?(s[0-5]+|o[0-7]+|b[01]+|x[0-9]+)\b'
scope: constant.numeric.ain48 scope: constant.numeric.ain48
- match: '#imm\[[0-9n]+\]' - match: '#imm\[[0-9n]+\]'
scope: constant.numeric.ain48 scope: constant.numeric.ain48

View File

@ -27,6 +27,9 @@
A *byte* (singulus) is the smallest addressable 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 *half-word* (binus) is a binary number composed of 2 bytes, that is, a 24 bit
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.
@ -79,9 +82,8 @@ memory address.
(1, [0]), (1, [0]),
(1, [0]), (1, [0]),
(1, [0]), (1, [0]),
(1, [0]), (2, [m]),
(1, [i#sub[2]\ 0]), (1, [i\ 0]),
(1, [i#sub[1]\ 0]),
(1, [s]), (1, [s]),
(4, [ac]), (4, [ac]),
), ((4, [r#sub[f]]), (4, [r#sub[2]]), (4, [r#sub[1]]))) ), ((4, [r#sub[f]]), (4, [r#sub[2]]), (4, [r#sub[1]])))
@ -91,33 +93,8 @@ memory address.
(1, [0]), (1, [0]),
(1, [0]), (1, [0]),
(1, [0]), (1, [0]),
(1, [0]), (2, [m]),
(1, [i#sub[2]\ 0]), (1, [i\ 1]),
(1, [i#sub[1]\ 1]),
(1, [s]),
(4, [ac]),
), ((4, [r#sub[f]]), (4, [r#sub[2]]), (4, text(size: .9em)[imm[0:3]])))
content((12.25, -6))[or]
byte_diag(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[f]]), (4, text(size: .9em)[imm[0:3]]), (4, [r#sub[1]])))
content((12.25, -11))[or]
byte_diag(voff: -15, (
(1, [0]),
(1, [0]),
(1, [0]),
(1, [0]),
(1, [0]),
(1, [i#sub[2]\ 1]),
(1, [i#sub[1]\ 1]),
(1, [s]), (1, [s]),
(4, [ac]), (4, [ac]),
), ((4, [r#sub[f]]), (8, [imm[0:7]]))) ), ((4, [r#sub[f]]), (8, [imm[0:7]])))
@ -135,13 +112,13 @@ memory address.
import cetz.draw: * import cetz.draw: *
scale(.65) scale(.65)
byte_diag(( byte_diag((
(1, [0]),
(1, [0]), (1, [0]),
(1, [0]), (1, [0]),
(1, [1]), (1, [1]),
(1, [0]), (1, [0]),
(1, [0]), (1, [0]),
(1, [0]), (1, [0]),
(1, [0]),
(1, [s]), (1, [s]),
(4, [r]), (4, [r]),
), ((12, [imm[0:11]]),)) ), ((12, [imm[0:11]]),))
@ -160,9 +137,9 @@ memory address.
byte_diag(( byte_diag((
(1, [0]), (1, [0]),
(1, [0]), (1, [0]),
(1, [1]),
(1, [1]),
(1, [0]), (1, [0]),
(1, [1]),
(1, [1]),
(1, [0]), (1, [0]),
(1, [0]), (1, [0]),
(1, [s]), (1, [s]),
@ -176,9 +153,9 @@ memory address.
import cetz.draw: * import cetz.draw: *
scale(.65) scale(.65)
byte_diag(( byte_diag((
(1, [0]),
(1, [0]), (1, [0]),
(1, [1]), (1, [1]),
(1, [0]),
(1, [s]), (1, [s]),
(4, [r#sub[d]]), (4, [r#sub[d]]),
(4, [r#sub[l]]), (4, [r#sub[l]]),
@ -291,79 +268,65 @@ Common Notations:
h(1em) h(1em)
opts.pos().join(h(2em)) opts.pos().join(h(2em))
}) })
#let aludoc(mnemonic, opnum, opsym, commutative, s) = [ #let aludoc(mnemonic, opnum, opsym, s) = [
#optgrid(opt[op][#opnum], opt[s][#s]) #optgrid(opt[op][#opnum], opt[s][#s], opt[w][2])
/ Instruction format: #amal / Instruction format: #amal
/ #raw(mnemonic + " %a, %b, %c", lang: "ain48"): %a %b #opsym %c / #raw(mnemonic + " %a, %b, %c", lang: "ain48"): %a %b #opsym %c
#optgrid( #optgrid(
opt[i#sub[1]][0], opt[i][0],
opt[i#sub[2]][0],
opt[r#sub[f]][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],
) )
/ #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[f]][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[f]][a],
opt[r#sub[2]][b],
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[f]][a], opt[imm][imm]) #optgrid(opt[i][1], opt[r#sub[f]][a], opt[imm][imm])
] ]
#let sized_also(mnem, name) = (also: (
( "S" + mnem, "Singulum " + name, [Same as #istr(mnem), but operates on bytes #optgrid(opt[w][0])]),
( "B" + mnem, "Binum " + name, [Same as #istr(mnem), but operates on half-words #optgrid(opt[w][1])]),
( "Q" + mnem, "Quaternum " + name, [Alias for the unsized version, operates on words]),
))
#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", "-", 1)
/ Instruction format: #amal / Instruction format: #amal
]), ], ..sized_also("STR", "Subtrahere")),
(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", "+", 1)
/ Instruction format: #amal / Instruction format: #amal
]), ], ..sized_also("ADD", "Addere")),
(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", "×", 1)
/ Instruction format: #amal / Instruction format: #amal
]), ], ..sized_also("MPL", "Multiplicáre")),
(mnem: "RSD", name: "Residérí", sign: true, description: [ (mnem: "RSD", name: "Residérí", sign: true, description: [
Remainder of the Euclidean division of two signed integers. Remainder of the Euclidean division of two signed integers.
Will raise an arithmetic exception if the right operand is zero. Will raise an arithmetic exception if the right operand is zero.
#aludoc("RSD", "05", "mod", false, 1) #aludoc("RSD", "05", "mod", 1)
/ Instruction format: #amal / Instruction format: #amal
]), ], ..sized_also("RSD", "Residérí")),
(mnem: "DVD", name: "Dívidere", sign: true, description: [ (mnem: "DVD", name: "Dívidere", sign: true, description: [
Integer part of the Euclidean division of two signed integers. Integer part of the Euclidean division of two signed integers.
Will raise an arithmetic exception if the right operand is zero. Will raise an arithmetic exception if the right operand is zero.
#aludoc("DVD", "04", "/", false, 1) #aludoc("DVD", "04", "/", 1)
/ Instruction format: #amal / Instruction format: #amal
]), ], ..sized_also("DVD", "Dívidere")),
(mnem: "DEM", name: "Ad Dextró Movére", sign: true, description: [ (mnem: "DEM", name: "Ad Dextró Movére", sign: true, description: [
Shift a signed number right by a signed number. Shift a signed number right by a signed number.
Will raise an arithmetic exception if the right operand is negative. Will raise an arithmetic exception if the right operand is negative.
#aludoc("DEM", "06", ">>", false, 1) #aludoc("DEM", "06", ">>", 1)
/ Instruction format: #amal / Instruction format: #amal
]), ], ..sized_also("DEM", "Ad Dextró Movére")),
(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. Will raise an arithmetic exception if the right operand is negative.
#aludoc("SIM", "07", "<<", false, 0) #aludoc("SIM", "07", "<<", 0)
/ Instruction format: #amal / Instruction format: #amal
]), ], ..sized_also("SIM", "Ad Sinistró Movére")),
( (
mnem: "ILG", mnem: "ILG",
name: "Immediátum Legere", name: "Immediátum Legere",
@ -526,27 +489,27 @@ Common Notations:
]), ]),
(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, 0)
]), ]),
(mnem: "NEC", name: "Nec", description: [ (mnem: "NEC", name: "Nec", description: [
Bitwise negated disjunction between two words Bitwise negated disjunction between two words
#aludoc("NEC", [15], sym.not + sym.or, true, 0) #aludoc("NEC", [15], sym.not + sym.or, 0)
]), ]),
(mnem: "AUT", name: "Aut", description: [ (mnem: "AUT", name: "Aut", description: [
Bitwise difference between two numbers. Bitwise difference between two numbers.
#aludoc("AUT", [12], sym.xor, true, 0) #aludoc("AUT", [12], sym.xor, 0)
]), ]),
(mnem: "AEQ", name: "Aequí", description: [ (mnem: "AEQ", name: "Aequí", description: [
Bitwise equality between two numbers. Bitwise equality between two numbers.
#aludoc("AEQ", [16], [=], true, 0) #aludoc("AEQ", [16], [=], 0)
]), ]),
(mnem: "ET", name: "Et", description: [ (mnem: "ET", name: "Et", description: [
Bitwise logical conjunction between two numbers. Bitwise logical conjunction between two numbers.
#aludoc("ET", [10], sym.and, true, 0) #aludoc("ET", [10], sym.and, 0)
]), ]),
(mnem: "NAM", name: "Non ambó", description: [ (mnem: "NAM", name: "Non ambó", description: [
Bitwise negated logical conjunction between two numbers. Bitwise negated logical conjunction between two numbers.
#aludoc("NAM", [14], sym.not + sym.and, true, 0) #aludoc("NAM", [14], sym.not + sym.and, 0)
]), ]),
( (
mnem: "LG", mnem: "LG",
@ -558,6 +521,7 @@ Common Notations:
#optgrid(opt[s][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.
], ],
..sized_also("LG", "Legere"),
), ),
( (
mnem: "SC", mnem: "SC",
@ -569,6 +533,7 @@ Common Notations:
#optgrid(opt[s][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
], ],
..sized_also("SC", "Scríbere")
), ),
(mnem: "CESS", name: "Cessáre", description: [ (mnem: "CESS", name: "Cessáre", description: [
*Privileged* Halts the CPU. *Privileged* Halts the CPU.
@ -637,7 +602,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 #istr(m); see #ristr("P" + it.mnem) and #ristr(it.mnem).
], ],
), ),
) )

55
editors/kak/a48s.kak Normal file
View File

@ -0,0 +1,55 @@
# ain48 assembly syntax highlighting
# put this in your autoload folder in ~/.config/kak/autoload and it should work
# note: if you are *creating* an autoload folder in that location,
# the *default* autoload scripts in /usr/share/kak/autoload will not trigger,
# so it might be a good idea to copy the contents of that directory.
hook global BufCreate .*\.(a|ain)48(s|asm) %{
set-option buffer filetype a48s
}
hook global WinSetOption filetype=a48s %{
require-module a48s
hook -once -always window WinSetOption filetype=.* %{
remove-hooks window a48s-.+
}
}
hook -group a48s-highlight global WinSetOption filetype=a48s %{
add-highlighter window/a48s ref a48s
hook -once -always window WinSetOption filetype=.* %{
remove-highlighter window/a48s
}
}
provide-module a48s %{
add-highlighter shared/a48s regions
add-highlighter shared/a48s/ region ';' '\n' fill comment
add-highlighter shared/a48s/dqstring region '"' '"' group
add-highlighter shared/a48s/dqstring/ fill string
add-highlighter shared/a48s/dqstring/ \
regex (\\[\\abefhnrtv\n])|(\\.) 1:keyword 2:Error
add-highlighter shared/a48s/code default-region group
# immediates
add-highlighter shared/a48s/code/ regex \
(?i)#-?(s[0-5]+|o[0-7]+|b[01]+|x[0-9]+)\b \
0:value
# registers
add-highlighter shared/a48s/code/ regex (?i)%([a-z0-7]+)\b 0:builtin
# directives
add-highlighter shared/a48s/code/ regex \.[a-zA-Z]+ 0:type
# labels
add-highlighter shared/a48s/code/ regex ^\h*[A-Za-z0-9_.-]+: 0:operator
# instructions
add-highlighter shared/a48s/code/ regex \
(?i)\b((p?(add|dem|dvd|i[mp]?lg|mpl|rsd|str))|(n?[enpu]?i)|(ir|nc)?rv|(nc)?ivc|aeq|an|aut|cess|cst|dem|dst|et|(p?[sbq])?(lg|sc)|nam|nec|sim|tsc|vel)\b \
0:keyword
# the regex is painfully long but i can't do anything about that so...
}

View File

@ -1,67 +0,0 @@
#ifndef AIN48__H
#define AIN48__H
#include <assert.h>
#include <common.h>
enum instruction_format {
AMAL,
IML,
IPL,
AMLS,
ASSS,
ASLI,
ASLR,
ASRD,
};
enum amal_ac : u8 {
ADD = 000,
STR = 001,
MPL = 002,
DVD = 004,
RSD = 005,
DEM = 006,
ET = 010,
VEL = 011,
AUT = 012,
NAM = 014,
NEC = 015,
};
enum asss_ac : u8 {
RV = 00,
IRRV = 04,
NCIVC = 03,
NCRV = 02,
};
// clang-format off
struct instruction {
enum instruction_format format;
union {
struct {
bool s, i1, i2; enum amal_ac ac; u4 rf;
union {
u8 imm; i8 simm;
struct {
union { u4 r2; u4 imm2; i4 simm2; };
union { u4 r1; u4 imm1; u4 simm1; };
};
} data;
} AMAL;
struct { u4 r; u48 imm; } IML;
struct { bool s; u4 r; union { u12 imm; i12 simm; }; } IPL;
struct { bool s; u4 rd; u4 rl; i12 imm; } AMLS;
enum asss_ac ASSS_ac;
struct { bool I, E, N, U, R; u48 imm; } ASLI;
struct { bool I, E, N, U, R; u4 rl; } ASLR;
struct { bool I, E, N, U, R; u4 rl; i12 imm; } ASRD;
};
};
// clang-format on
u12 *ain48_read_instr(u12 *code, struct instruction *i);
u12 *ain48_write_instr(u12 *code, struct instruction *i);
#endif // AIN48__H

View File

@ -1,49 +0,0 @@
#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 unsigned _BitInt(4) u4;
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_info(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__

34
programs/ain48.cabal Normal file
View File

@ -0,0 +1,34 @@
cabal-version: 3.0
-- The cabal-version field refers to the version of the .cabal specification,
-- and can be different from the cabal-install (the tool) version and the
-- Cabal (the library) version you are using. As such, the Cabal (the library)
-- version used must be equal or greater than the version stated in this field.
-- Starting from the specification version 2.2, the cabal-version field must be
-- the first thing in the cabal file.
-- Initial package description 'ain48' generated by
name: ain48
version: 0.1.0.0
homepage: https://git.annwan.me/worldbuilding/ain48
license: MIT
author: Annwan
maintainer: annwan@annwan.me
build-type: Simple
common warnings
ghc-options: -Wall
library
default-language: GHC2024
hs-source-dirs: common
build-depends: base ^>= 4.21.2.0
exposed-modules: Ain48.Types
executable dump12
import: warnings
main-is: Main.hs
-- other-modules:
build-depends: base ^>=4.21.2.0
, ain48
, optparse-applicative
hs-source-dirs: dump12
default-language: GHC2024

View File

@ -0,0 +1,383 @@
module Ain48.Types
( module Data.Word
, module Data.Int
, Word4(..), Word6(..), Word12(..), Word24(..), Word48(..)
, Int4(..), Int6(..), Int12(..), Int24(..), Int48(..),
) where
import Data.Word (Word8, Word16, Word32, Word64)
import Data.Int (Int8, Int16, Int32, Int64)
import Data.Bits ((.&.))
import Data.Bifunctor (bimap)
newtype Word4 = Word4 { unWord4 :: Word8 } deriving (Eq)
instance Show Word4 where
show :: Word4 -> String
show = show . unWord4
instance Num Word4 where
(+) :: Word4 -> Word4 -> Word4
(+) a b = Word4 $ unWord4 a + unWord4 b
(*) :: Word4 -> Word4 -> Word4
(*) a b = Word4 $ unWord4 a * unWord4 b
(-) :: Word4 -> Word4 -> Word4
(-) a b = Word4 $ unWord4 a - unWord4 b
abs :: Word4 -> Word4
abs = Word4 . abs . unWord4
signum :: Word4 -> Word4
signum = Word4 . signum . unWord4
fromInteger :: Integer -> Word4
fromInteger = Word4 . (.&. 0xF) . fromInteger
instance Ord Word4 where
compare :: Word4 -> Word4 -> Ordering
compare a b = compare (unWord4 a) (unWord4 b)
instance Real Word4 where
toRational :: Word4 -> Rational
toRational = toRational . unWord4
instance Bounded Word4 where
minBound :: Word4
minBound = Word4 0
maxBound :: Word4
maxBound = Word4 0xF
instance Enum Word4 where
fromEnum :: Word4 -> Int
fromEnum = fromEnum . unWord4
toEnum :: Int -> Word4
toEnum = Word4 . (.&. 0xF) . toEnum
instance Integral Word4 where
quotRem :: Word4 -> Word4 -> (Word4, Word4)
quotRem a b = bimap Word4 Word4 $ quotRem (unWord4 a) (unWord4 b)
toInteger :: Word4 -> Integer
toInteger = toInteger . unWord4
newtype Word6 = Word6 { unWord6 :: Word8 } deriving (Eq)
instance Show Word6 where
show :: Word6 -> String
show = show . unWord6
instance Num Word6 where
(+) :: Word6 -> Word6 -> Word6
(+) a b = Word6 $ unWord6 a + unWord6 b
(*) :: Word6 -> Word6 -> Word6
(*) a b = Word6 $ unWord6 a * unWord6 b
(-) :: Word6 -> Word6 -> Word6
(-) a b = Word6 $ unWord6 a - unWord6 b
abs :: Word6 -> Word6
abs = Word6 . abs . unWord6
signum :: Word6 -> Word6
signum = Word6 . signum . unWord6
fromInteger :: Integer -> Word6
fromInteger = Word6 . (.&. 0x3F) . fromInteger
instance Ord Word6 where
compare :: Word6 -> Word6 -> Ordering
compare a b = compare (unWord6 a) (unWord6 b)
instance Real Word6 where
toRational :: Word6 -> Rational
toRational = toRational . unWord6
instance Bounded Word6 where
minBound :: Word6
minBound = Word6 0
maxBound :: Word6
maxBound = Word6 0x3F
instance Enum Word6 where
fromEnum :: Word6 -> Int
fromEnum = fromEnum . unWord6
toEnum :: Int -> Word6
toEnum = Word6 . (.&. 0x3F) . toEnum
instance Integral Word6 where
quotRem :: Word6 -> Word6 -> (Word6, Word6)
quotRem a b = bimap Word6 Word6 $ quotRem (unWord6 a) (unWord6 b)
toInteger :: Word6 -> Integer
toInteger = toInteger . unWord6
newtype Word12 = Word12 { unWord12 :: Word16 } deriving (Eq)
instance Show Word12 where
show :: Word12 -> String
show = show . unWord12
instance Num Word12 where
(+) :: Word12 -> Word12 -> Word12
(+) a b = Word12 $ unWord12 a + unWord12 b
(*) :: Word12 -> Word12 -> Word12
(*) a b = Word12 $ unWord12 a * unWord12 b
(-) :: Word12 -> Word12 -> Word12
(-) a b = Word12 $ unWord12 a - unWord12 b
abs :: Word12 -> Word12
abs = Word12 . abs . unWord12
signum :: Word12 -> Word12
signum = Word12 . signum . unWord12
fromInteger :: Integer -> Word12
fromInteger = Word12 . (.&. 0xFFF) . fromInteger
instance Ord Word12 where
compare :: Word12 -> Word12 -> Ordering
compare a b = compare (unWord12 a) (unWord12 b)
instance Real Word12 where
toRational :: Word12 -> Rational
toRational = toRational . unWord12
instance Bounded Word12 where
minBound :: Word12
minBound = Word12 0
maxBound :: Word12
maxBound = Word12 0xFFF
instance Enum Word12 where
fromEnum :: Word12 -> Int
fromEnum = fromEnum . unWord12
toEnum :: Int -> Word12
toEnum = Word12 . (.&. 0xFFF) . toEnum
instance Integral Word12 where
quotRem :: Word12 -> Word12 -> (Word12, Word12)
quotRem a b = bimap Word12 Word12 $ quotRem (unWord12 a) (unWord12 b)
toInteger :: Word12 -> Integer
toInteger = toInteger . unWord12
newtype Word24 = Word24 { unWord24 :: Word32 } deriving (Eq)
instance Show Word24 where
show :: Word24 -> String
show = show . unWord24
instance Num Word24 where
(+) :: Word24 -> Word24 -> Word24
(+) a b = Word24 $ unWord24 a + unWord24 b
(*) :: Word24 -> Word24 -> Word24
(*) a b = Word24 $ unWord24 a * unWord24 b
(-) :: Word24 -> Word24 -> Word24
(-) a b = Word24 $ unWord24 a - unWord24 b
abs :: Word24 -> Word24
abs = Word24 . abs . unWord24
signum :: Word24 -> Word24
signum = Word24 . signum . unWord24
fromInteger :: Integer -> Word24
fromInteger = Word24 . (.&. 0xFFFFFF) . fromInteger
instance Ord Word24 where
compare :: Word24 -> Word24 -> Ordering
compare a b = compare (unWord24 a) (unWord24 b)
instance Real Word24 where
toRational :: Word24 -> Rational
toRational = toRational . unWord24
instance Bounded Word24 where
minBound :: Word24
minBound = Word24 0
maxBound :: Word24
maxBound = Word24 0xFFFFFF
instance Enum Word24 where
fromEnum :: Word24 -> Int
fromEnum = fromEnum . unWord24
toEnum :: Int -> Word24
toEnum = Word24 . (.&. 0xFFFFFF) . toEnum
instance Integral Word24 where
quotRem :: Word24 -> Word24 -> (Word24, Word24)
quotRem a b = bimap Word24 Word24 $ quotRem (unWord24 a) (unWord24 b)
toInteger :: Word24 -> Integer
toInteger = toInteger . unWord24
newtype Word48 = Word48 { unWord48 :: Word64 } deriving (Eq)
instance Show Word48 where
show :: Word48 -> String
show = show . unWord48
instance Num Word48 where
(+) :: Word48 -> Word48 -> Word48
(+) a b = Word48 $ unWord48 a + unWord48 b
(*) :: Word48 -> Word48 -> Word48
(*) a b = Word48 $ unWord48 a * unWord48 b
(-) :: Word48 -> Word48 -> Word48
(-) a b = Word48 $ unWord48 a - unWord48 b
abs :: Word48 -> Word48
abs = Word48 . abs . unWord48
signum :: Word48 -> Word48
signum = Word48 . signum . unWord48
fromInteger :: Integer -> Word48
fromInteger = Word48 . (.&. 0xFFFFFFFFFFFF) . fromInteger
instance Ord Word48 where
compare :: Word48 -> Word48 -> Ordering
compare a b = compare (unWord48 a) (unWord48 b)
instance Real Word48 where
toRational :: Word48 -> Rational
toRational = toRational . unWord48
instance Bounded Word48 where
minBound :: Word48
minBound = Word48 0
maxBound :: Word48
maxBound = Word48 0xFFFFFFFFFFFF
instance Enum Word48 where
fromEnum :: Word48 -> Int
fromEnum = fromEnum . unWord48
toEnum :: Int -> Word48
toEnum = Word48 . (.&. 0xFFFFFFFFFFFF) . toEnum
instance Integral Word48 where
quotRem :: Word48 -> Word48 -> (Word48, Word48)
quotRem a b = bimap Word48 Word48 $ quotRem (unWord48 a) (unWord48 b)
toInteger :: Word48 -> Integer
toInteger = toInteger . unWord48
newtype Int4 = Int4 { unInt4 :: Int8 } deriving (Eq)
instance Show Int4 where
show :: Int4 -> String
show = show . unInt4
instance Num Int4 where
(+) :: Int4 -> Int4 -> Int4
(+) a b = Int4 $ unInt4 a + unInt4 b
(*) :: Int4 -> Int4 -> Int4
(*) a b = Int4 $ unInt4 a * unInt4 b
(-) :: Int4 -> Int4 -> Int4
(-) a b = Int4 $ unInt4 a - unInt4 b
abs :: Int4 -> Int4
abs = Int4 . abs . unInt4
signum :: Int4 -> Int4
signum = Int4 . signum . unInt4
fromInteger :: Integer -> Int4
fromInteger = Int4 . (.&. 0xF) . fromInteger
instance Ord Int4 where
compare :: Int4 -> Int4 -> Ordering
compare a b = compare (unInt4 a) (unInt4 b)
instance Real Int4 where
toRational :: Int4 -> Rational
toRational = toRational . unInt4
instance Bounded Int4 where
minBound :: Int4
minBound = Int4 (-8)
maxBound :: Int4
maxBound = Int4 7
instance Enum Int4 where
fromEnum :: Int4 -> Int
fromEnum = fromEnum . unInt4
toEnum :: Int -> Int4
toEnum = Int4 . (.&. 0xF) . toEnum
instance Integral Int4 where
quotRem :: Int4 -> Int4 -> (Int4, Int4)
quotRem a b = bimap Int4 Int4 $ quotRem (unInt4 a) (unInt4 b)
toInteger :: Int4 -> Integer
toInteger = toInteger . unInt4
newtype Int6 = Int6 { unInt6 :: Int8 } deriving (Eq)
instance Show Int6 where
show :: Int6 -> String
show = show . unInt6
instance Num Int6 where
(+) :: Int6 -> Int6 -> Int6
(+) a b = Int6 $ unInt6 a + unInt6 b
(*) :: Int6 -> Int6 -> Int6
(*) a b = Int6 $ unInt6 a * unInt6 b
(-) :: Int6 -> Int6 -> Int6
(-) a b = Int6 $ unInt6 a - unInt6 b
abs :: Int6 -> Int6
abs = Int6 . abs . unInt6
signum :: Int6 -> Int6
signum = Int6 . signum . unInt6
fromInteger :: Integer -> Int6
fromInteger = Int6 . (.&. 0x3F) . fromInteger
instance Ord Int6 where
compare :: Int6 -> Int6 -> Ordering
compare a b = compare (unInt6 a) (unInt6 b)
instance Real Int6 where
toRational :: Int6 -> Rational
toRational = toRational . unInt6
instance Bounded Int6 where
minBound :: Int6
minBound = Int6 (-32)
maxBound :: Int6
maxBound = Int6 31
instance Enum Int6 where
fromEnum :: Int6 -> Int
fromEnum = fromEnum . unInt6
toEnum :: Int -> Int6
toEnum = Int6 . (.&. 0x3F) . toEnum
instance Integral Int6 where
quotRem :: Int6 -> Int6 -> (Int6, Int6)
quotRem a b = (bimap Int6 Int6) $ quotRem (unInt6 a) (unInt6 b)
toInteger :: Int6 -> Integer
toInteger = toInteger . unInt6
newtype Int12 = Int12 { unInt12 :: Int16 } deriving (Eq)
instance Show Int12 where
show :: Int12 -> String
show = show . unInt12
instance Num Int12 where
(+) :: Int12 -> Int12 -> Int12
(+) a b = Int12 $ unInt12 a + unInt12 b
(*) :: Int12 -> Int12 -> Int12
(*) a b = Int12 $ unInt12 a * unInt12 b
(-) :: Int12 -> Int12 -> Int12
(-) a b = Int12 $ unInt12 a - unInt12 b
abs :: Int12 -> Int12
abs = Int12 . abs . unInt12
signum :: Int12 -> Int12
signum = Int12 . signum . unInt12
fromInteger :: Integer -> Int12
fromInteger = Int12 . (.&. 0xFFF) . fromInteger
instance Ord Int12 where
compare :: Int12 -> Int12 -> Ordering
compare a b = compare (unInt12 a) (unInt12 b)
instance Real Int12 where
toRational :: Int12 -> Rational
toRational = toRational . unInt12
instance Bounded Int12 where
minBound :: Int12
minBound = Int12 (-2048)
maxBound :: Int12
maxBound = Int12 2047
instance Enum Int12 where
fromEnum :: Int12 -> Int
fromEnum = fromEnum . unInt12
toEnum :: Int -> Int12
toEnum = Int12 . (.&. 0xFFF) . toEnum
instance Integral Int12 where
quotRem :: Int12 -> Int12 -> (Int12, Int12)
quotRem a b = bimap Int12 Int12 $ quotRem (unInt12 a) (unInt12 b)
toInteger :: Int12 -> Integer
toInteger = toInteger . unInt12
newtype Int24 = Int24 { unInt24 :: Int32 } deriving (Eq)
instance Show Int24 where
show :: Int24 -> String
show = show . unInt24
instance Num Int24 where
(+) :: Int24 -> Int24 -> Int24
(+) a b = Int24 $ unInt24 a + unInt24 b
(*) :: Int24 -> Int24 -> Int24
(*) a b = Int24 $ unInt24 a * unInt24 b
(-) :: Int24 -> Int24 -> Int24
(-) a b = Int24 $ unInt24 a - unInt24 b
abs :: Int24 -> Int24
abs = Int24 . abs . unInt24
signum :: Int24 -> Int24
signum = Int24 . signum . unInt24
fromInteger :: Integer -> Int24
fromInteger = Int24 . (.&. 0xFFFFFF) . fromInteger
instance Ord Int24 where
compare :: Int24 -> Int24 -> Ordering
compare a b = compare (unInt24 a) (unInt24 b)
instance Real Int24 where
toRational :: Int24 -> Rational
toRational = toRational . unInt24
instance Bounded Int24 where
minBound :: Int24
minBound = Int24 (-8388608)
maxBound :: Int24
maxBound = Int24 8388607
instance Enum Int24 where
fromEnum :: Int24 -> Int
fromEnum = fromEnum . unInt24
toEnum :: Int -> Int24
toEnum = Int24 . (.&. 0xFFFFFF) . toEnum
instance Integral Int24 where
quotRem :: Int24 -> Int24 -> (Int24, Int24)
quotRem a b = bimap Int24 Int24 $ quotRem (unInt24 a) (unInt24 b)
toInteger :: Int24 -> Integer
toInteger = toInteger . unInt24
newtype Int48 = Int48 { unInt48 :: Int64 } deriving (Eq)
instance Show Int48 where
show :: Int48 -> String
show = show . unInt48
instance Num Int48 where
(+) :: Int48 -> Int48 -> Int48
(+) a b = Int48 $ unInt48 a + unInt48 b
(*) :: Int48 -> Int48 -> Int48
(*) a b = Int48 $ unInt48 a * unInt48 b
(-) :: Int48 -> Int48 -> Int48
(-) a b = Int48 $ unInt48 a - unInt48 b
abs :: Int48 -> Int48
abs = Int48 . abs . unInt48
signum :: Int48 -> Int48
signum = Int48 . signum . unInt48
fromInteger = Int48 . (.&. 0xFFFFFFFFFFFF) . fromInteger
instance Ord Int48 where
compare a b = compare (unInt48 a) (unInt48 b)
instance Real Int48 where
toRational = toRational . unInt48
instance Bounded Int48 where
minBound = Int48 (-140737488355328)
maxBound = Int48 140737488355327
instance Enum Int48 where
fromEnum = fromEnum . unInt48
toEnum = Int48 . (.&. 0xFFFFFFFFFFFF) . toEnum
instance Integral Int48 where
quotRem a b = (\(a, b) -> (Int48 a, Int48 b)) $ quotRem (unInt48 a) (unInt48 b)
toInteger = toInteger . unInt48

16
programs/dump12/Main.hs Normal file
View File

@ -0,0 +1,16 @@
module Main (main) where
import Ain48.Types
import Options.Applicative
parser_opts :: Parser Bool
parser_opts = switch ( long "decode"
<> short 'd'
<> help "Decode a binary file instead of encoding a dump file")
main :: IO ()
main = do
opts <- execParser $ info (parser_opts <**> helper)
( fullDesc <> progDesc "Convert to and from 12 bit byte binaries"
<> header "dump12 --- conversion utility" )
print opts

View File

@ -1,191 +0,0 @@
#include <ain48.h>
#include <string.h>
u12 *ain48_write_instruction(u12 *code, struct instruction *i) {
u4 u4tmp;
u8 u8tmp;
switch (i->format) {
case AMAL:
*code++ = i->AMAL.ac | (i->AMAL.s ? 1 << 4 : 0) |
(i->AMAL.i1 ? 1 << 5 : 0) | (i->AMAL.i2 ? 1 << 6 : 0);
*code = ((u12)i->AMAL.rf) << 8;
if (!i->AMAL.i1)
*code |= ((u12)i->AMAL.data.r1) << 4;
if (!i->AMAL.i2)
*code |= ((u12)i->AMAL.data.r2);
if (i->AMAL.i1 && i->AMAL.i2) {
if (i->AMAL.s)
memcpy(&u8tmp, &i->AMAL.data.simm, sizeof(u8));
else
u8tmp = i->AMAL.data.imm;
*code |= u8tmp;
} else if (i->AMAL.i1) {
if (i->AMAL.s)
memcpy(&u4tmp, &i->AMAL.data.simm1, sizeof(u4));
else
u4tmp = i->AMAL.data.imm1;
*code |= u4tmp;
} else if (i->AMAL.i2) {
if (i->AMAL.s)
memcpy(&u4tmp, &i->AMAL.data.simm2, sizeof(u4));
else
u4tmp = i->AMAL.data.imm2;
*code |= ((u12)u4tmp) << 4;
}
return ++code;
case IML:
*code++ = 00400 | i->IML.r;
*code++ = i->IML.imm & 07777;
*code++ = (i->IML.imm >> 12) & 07777;
*code++ = (i->IML.imm >> 24) & 07777;
*code++ = (i->IML.imm >> 36) & 07777;
return code;
case IPL:
*code++ = 00500 | (i->IPL.s ? (1 << 4) : 0) | i->IPL.r;
if (i->IPL.s) {
memcpy(code++, &i->IPL.simm, sizeof(u12));
} else {
*code++ = i->IPL.imm;
}
return code;
case AMLS:
*code++ = 01000 | (i->AMLS.s ? 1 << 8 : 0) | (((u12)i->AMLS.rd) << 4) |
i->AMLS.rl;
memcpy(code++, &i->AMLS.imm, sizeof(u12));
return code;
case ASSS:
*code++ = 07770 | i->ASSS_ac;
return code;
case ASLI:
*code++ = 04000 | (i->ASLI.R ? 1 << 0 : 0) | (i->ASLI.U ? 1 << 1 : 0) |
(i->ASLI.N ? 1 << 2 : 0) | (i->ASLI.E ? 1 << 3 : 0) |
(i->ASLI.I ? 1 << 4 : 0);
*code++ = i->ASLI.imm & 07777;
*code++ = (i->ASLI.imm >> 12) & 07777;
*code++ = (i->ASLI.imm >> 24) & 07777;
*code++ = (i->ASLI.imm >> 36) & 07777;
return code;
case ASLR:
*code++ = 05000 | (i->ASLR.R ? 1 << 0 : 0) | (i->ASLR.U ? 1 << 1 : 0) |
(i->ASLR.N ? 1 << 2 : 0) | (i->ASLR.E ? 1 << 3 : 0) |
(i->ASLR.I ? 1 << 4 : 0) | (((u12)i->ASLR.rl) << 5);
return code;
case ASRD:
*code++ = 05000 | (i->ASRD.R ? 1 << 0 : 0) | (i->ASRD.U ? 1 << 1 : 0) |
(i->ASRD.N ? 1 << 2 : 0) | (i->ASRD.E ? 1 << 3 : 0) |
(i->ASLR.I ? 1 << 4 : 0) | (((u12)i->ASRD.rl) << 5);
memcpy(code++, &i->ASRD.imm, sizeof(u12));
return code;
default:
return nullptr;
}
}
u12 *ain48_read_instr(u12 *code, struct instruction *i) {
u12 byte = *code++;
if ((byte & 07600) == 0) { // AMAL
i->format = AMAL;
i->AMAL.i1 = (byte & 00040) > 0;
i->AMAL.i2 = (byte & 00100) > 0;
i->AMAL.s = (byte & 00020) > 0;
i->AMAL.ac = (enum amal_ac) (byte & 00017);
byte = *code++;
i->AMAL.rf = (byte >> 8) & 017;
if (!i->AMAL.i1)
i->AMAL.data.r1 = (byte >> 4) & 017;
if (!i->AMAL.i2)
i->AMAL.data.r2 = byte & 017;
if (i->AMAL.i1 && i->AMAL.i2) {
if (i->AMAL.s) {
u8 tmp = byte & 0377;
memcpy(&i->AMAL.data.simm, &tmp, sizeof(i8));
} else
i->AMAL.data.imm = byte & 0337;
} else if (i->AMAL.i1) {
if (i->AMAL.s) {
u4 tmp = byte & 017;
memcpy(&i->AMAL.data.simm1, &tmp, sizeof(i4));
}
else
i->AMAL.data.imm1 = byte & 017;
} else if (i->AMAL.i2) {
if (i->AMAL.s) {
u4 tmp = (byte >> 4) & 017;
memcpy(&i->AMAL.data.simm2, &tmp, sizeof(i4));
}
else
i->AMAL.data.imm2 = (byte >> 4) & 017;
}
return code;
} else if ((byte & 07600) == 00400) { // IML
i->format = IML;
i->IML.r = byte & 017;
byte = *code++;
i->IML.imm = (u48)byte;
byte = *code++;
i->IML.imm |= ((u48)byte << 12);
byte = *code++;
i->IML.imm |= ((u48)byte << 24);
byte = *code++;
i->IML.imm |= ((u48)byte << 36);
return code;
} else if ((byte & 07600) == 00600) { // IPL
i->format = IPL;
i->IPL.r = byte & 017;
i->IPL.s = (byte & 00020) > 0;
byte = *code++;
if (i->IPL.s) {
memcpy(&i->IPL.simm, &byte, sizeof(i12));
} else {
i->IPL.imm = byte;
}
return code;
} else if ((byte & 07000) == 01000) { // AMLS
i->format = AMLS;
i->AMLS.s = (byte & 00400) > 0;
i->AMLS.rd = (byte >> 4) & 017;
i->AMLS.rl = byte & 017;
memcpy(&i->AMLS.imm, code++, sizeof(i12));
return code;
} else if ((byte & 07770) == 07770) { // ASSS
i->format = ASSS;
i->ASSS_ac = byte & 00007;
return code;
} else if ((byte & 07000) == 04000) { // ASLI
i->format = ASLI;
i->ASLI.R = (byte & 0b1) > 0;
i->ASLI.U = (byte & 0b10) > 0;
i->ASLI.N = (byte & 0b100) > 0;
i->ASLI.E = (byte & 0b1000) > 0;
i->ASLI.I = (byte & 0b10000) > 0;
byte = *code++;
i->ASLI.imm = (u48)byte;
byte = *code++;
i->ASLI.imm |= ((u48)byte << 12);
byte = *code++;
i->ASLI.imm |= ((u48)byte << 24);
byte = *code++;
i->ASLI.imm |= ((u48)byte << 36);
return code;
} else if ((byte & 07000) == 05000) { // ASLR
i->format = ASLR;
i->ASLR.R = (byte & 0b1) > 0;
i->ASLR.U = (byte & 0b10) > 0;
i->ASLR.N = (byte & 0b100) > 0;
i->ASLR.E = (byte & 0b1000) > 0;
i->ASLR.I = (byte & 0b10000) > 0;
i->ASLR.rl = (byte >> 5) & 017;
return code;
} else if ((byte & 07000) == 06000) { // ASRD
i->format = ASRD;
i->ASRD.R = (byte & 0b1) > 0;
i->ASRD.U = (byte & 0b10) > 0;
i->ASRD.N = (byte & 0b100) > 0;
i->ASRD.E = (byte & 0b1000) > 0;
i->ASRD.I = (byte & 0b10000) > 0;
i->ASRD.rl = (byte >> 5) & 017;
memcpy(&i->ASRD.imm, code++, sizeof(i12));
return code;
} else return nullptr; // ILLEGAL INSTRUCTION
}

View File

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

View File

@ -1,85 +0,0 @@
#include <common.h>
#include <fcntl.h>
#include <unistd.h>
void dump12_usage() { log_info("Usage: dump12 [-b|-t] [source] [dest]"); }
i32 dump12_main(i32 argc, char *argv[]) {
bool to_bin = true;
char *inpath = nullptr;
char *outpath = nullptr;
for (i32 i = 1; i < argc; ++i) {
char *arg = argv[i];
if (arg[0] == '-' && arg[1] == 'b' && arg[2] == '\0') {
to_bin = true;
} else if (arg[0] == '-' && arg[1] == 't' && arg[2] == '\0') {
to_bin = false;
} else if (arg[0] == '-' && arg[1] == 'h' && arg[2] == '\0') {
dump12_usage();
return 0;
} else if (inpath == nullptr) {
inpath = arg;
} else if (outpath == nullptr) {
outpath = arg;
} else {
log_err("Too many arguments");
return 1;
}
}
int infd = (inpath == nullptr) ? 0 : open(inpath, O_RDONLY);
if (infd < 0) {
log_err_errno("Couldn't open `%s`", inpath);
return 1;
}
int outfd =
(inpath == nullptr) ? 1 : open(outpath, O_CREAT | O_TRUNC | O_WRONLY);
if (outfd < 0) {
log_err_errno("Couldn't open `%s`", outpath);
return 1;
}
if (to_bin) {
u12 byte12 = 0;
u8 count = 0;
u8 c;
while (read(infd, &c, 1) > 0) {
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
byte12 = (byte12 << 3) | (c - '0');
count++;
break;
default:
}
if (count == 4) {
u8 bs[2] = {byte12 & 0xFF, (byte12 >> 8) & 0xFF};
write(outfd, bs, 2);
count = 0;
byte12 = 0;
}
}
} else {
usz bytecount = 0;
u8 readbuf[2];
while (read(infd, readbuf, 2) > 0) {
u12 byte12 = readbuf[0] | (readbuf[1] << 8);
bytecount ++;
u8 outbuf[5] = {
((byte12 >> 9) & 7) + '0',
((byte12 >> 6) & 7) + '0',
((byte12 >> 3) & 7) + '0',
(byte12 & 7) + '0',
(bytecount % 8) ? ' ': '\n',
};
write(outfd, outbuf, 5);
}
}
close(infd);
close(outfd);
return 0;
}

View File

@ -1,60 +0,0 @@
#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[0m" : "");
va_list va;
va_start(va);
vfprintf(logfile, format, va);
va_end(va);
fprintf(logfile, "\n");
}
#endif
void log_info(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_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;
}

View File

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