Compare commits
2 Commits
52b743de9a
...
2317f1e2b7
| Author | SHA1 | Date | |
|---|---|---|---|
|
2317f1e2b7
|
|||
|
30ff19d7ff
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -4,4 +4,6 @@
|
||||
/docs/*.pdf
|
||||
/ain48
|
||||
/scratch
|
||||
/programs/dist-newstyle/
|
||||
|
||||
|
||||
|
||||
67
Makefile
67
Makefile
@ -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
17
docs/Makefile
Normal 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)
|
||||
@ -6,7 +6,7 @@ file_extensions:
|
||||
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'
|
||||
- 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
|
||||
- match: '(?i)%([a-z0-7]+)\b'
|
||||
scope: variable.register.ain48
|
||||
|
||||
121
docs/isa.typ
121
docs/isa.typ
@ -27,6 +27,9 @@
|
||||
A *byte* (singulus) is the smallest addressable part of memory, that is, a 12-bit
|
||||
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
|
||||
binary number.
|
||||
|
||||
@ -79,9 +82,8 @@ memory address.
|
||||
(1, [0]),
|
||||
(1, [0]),
|
||||
(1, [0]),
|
||||
(1, [0]),
|
||||
(1, [i#sub[2]\ 0]),
|
||||
(1, [i#sub[1]\ 0]),
|
||||
(2, [m]),
|
||||
(1, [i\ 0]),
|
||||
(1, [s]),
|
||||
(4, [ac]),
|
||||
), ((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, [i#sub[2]\ 0]),
|
||||
(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]),
|
||||
(2, [m]),
|
||||
(1, [i\ 1]),
|
||||
(1, [s]),
|
||||
(4, [ac]),
|
||||
), ((4, [r#sub[f]]), (8, [imm[0:7]])))
|
||||
@ -135,13 +112,13 @@ memory address.
|
||||
import cetz.draw: *
|
||||
scale(.65)
|
||||
byte_diag((
|
||||
(1, [0]),
|
||||
(1, [0]),
|
||||
(1, [0]),
|
||||
(1, [1]),
|
||||
(1, [0]),
|
||||
(1, [0]),
|
||||
(1, [0]),
|
||||
(1, [0]),
|
||||
(1, [s]),
|
||||
(4, [r]),
|
||||
), ((12, [imm[0:11]]),))
|
||||
@ -160,9 +137,9 @@ memory address.
|
||||
byte_diag((
|
||||
(1, [0]),
|
||||
(1, [0]),
|
||||
(1, [1]),
|
||||
(1, [1]),
|
||||
(1, [0]),
|
||||
(1, [1]),
|
||||
(1, [1]),
|
||||
(1, [0]),
|
||||
(1, [0]),
|
||||
(1, [s]),
|
||||
@ -176,9 +153,9 @@ memory address.
|
||||
import cetz.draw: *
|
||||
scale(.65)
|
||||
byte_diag((
|
||||
(1, [0]),
|
||||
(1, [0]),
|
||||
(1, [1]),
|
||||
(1, [0]),
|
||||
(1, [s]),
|
||||
(4, [r#sub[d]]),
|
||||
(4, [r#sub[l]]),
|
||||
@ -291,79 +268,65 @@ Common Notations:
|
||||
h(1em)
|
||||
opts.pos().join(h(2em))
|
||||
})
|
||||
#let aludoc(mnemonic, opnum, opsym, commutative, s) = [
|
||||
#optgrid(opt[op][#opnum], opt[s][#s])
|
||||
#let aludoc(mnemonic, opnum, opsym, s) = [
|
||||
#optgrid(opt[op][#opnum], opt[s][#s], opt[w][2])
|
||||
/ 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[i][0],
|
||||
opt[r#sub[f]][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[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
|
||||
#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 = (
|
||||
(mnem: "STR", name: "Subtrahere", sign: true, description: [
|
||||
Subtract one signed number from another.
|
||||
#aludoc("STR", "01", "-", false, 1)
|
||||
#aludoc("STR", "01", "-", 1)
|
||||
/ Instruction format: #amal
|
||||
]),
|
||||
], ..sized_also("STR", "Subtrahere")),
|
||||
(mnem: "ADD", name: "Addere", sign: true, description: [
|
||||
Add two signed numbers together.
|
||||
#aludoc("ADD", "00", "+", true, 1)
|
||||
#aludoc("ADD", "00", "+", 1)
|
||||
/ Instruction format: #amal
|
||||
]),
|
||||
], ..sized_also("ADD", "Addere")),
|
||||
(mnem: "MPL", name: "Multiplicáre", sign: true, description: [
|
||||
Multiply two signed numbers together.
|
||||
#aludoc("MPL", "02", "×", true, 1)
|
||||
#aludoc("MPL", "02", "×", 1)
|
||||
/ Instruction format: #amal
|
||||
]),
|
||||
], ..sized_also("MPL", "Multiplicáre")),
|
||||
(mnem: "RSD", name: "Residérí", sign: true, description: [
|
||||
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", 1)
|
||||
/ Instruction format: #amal
|
||||
]),
|
||||
], ..sized_also("RSD", "Residérí")),
|
||||
(mnem: "DVD", name: "Dívidere", sign: true, description: [
|
||||
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", "/", 1)
|
||||
/ Instruction format: #amal
|
||||
]),
|
||||
], ..sized_also("DVD", "Dívidere")),
|
||||
(mnem: "DEM", name: "Ad Dextró Movére", sign: true, description: [
|
||||
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", ">>", 1)
|
||||
/ Instruction format: #amal
|
||||
]),
|
||||
], ..sized_also("DEM", "Ad Dextró Movére")),
|
||||
(mnem: "SIM", name: "Ad Sinistró Movére", description: [
|
||||
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", "<<", 0)
|
||||
/ Instruction format: #amal
|
||||
]),
|
||||
], ..sized_also("SIM", "Ad Sinistró Movére")),
|
||||
(
|
||||
mnem: "ILG",
|
||||
name: "Immediátum Legere",
|
||||
@ -526,27 +489,27 @@ Common Notations:
|
||||
]),
|
||||
(mnem: "VEL", name: "Vel", description: [
|
||||
Bitwise disjunction between two words.
|
||||
#aludoc("VEL", [11], sym.or, true, 0)
|
||||
#aludoc("VEL", [11], sym.or, 0)
|
||||
]),
|
||||
(mnem: "NEC", name: "Nec", description: [
|
||||
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: [
|
||||
Bitwise difference between two numbers.
|
||||
#aludoc("AUT", [12], sym.xor, true, 0)
|
||||
#aludoc("AUT", [12], sym.xor, 0)
|
||||
]),
|
||||
(mnem: "AEQ", name: "Aequí", description: [
|
||||
Bitwise equality between two numbers.
|
||||
#aludoc("AEQ", [16], [=], true, 0)
|
||||
#aludoc("AEQ", [16], [=], 0)
|
||||
]),
|
||||
(mnem: "ET", name: "Et", description: [
|
||||
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: [
|
||||
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",
|
||||
@ -558,6 +521,7 @@ Common Notations:
|
||||
#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.
|
||||
],
|
||||
..sized_also("LG", "Legere"),
|
||||
),
|
||||
(
|
||||
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])
|
||||
/ ```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: [
|
||||
*Privileged* Halts the CPU.
|
||||
@ -637,7 +602,7 @@ Common Notations:
|
||||
mnem: "P" + m,
|
||||
desc: [
|
||||
== 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).
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
@ -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
|
||||
@ -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
34
programs/ain48.cabal
Normal 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
|
||||
383
programs/common/Ain48/Types.hs
Normal file
383
programs/common/Ain48/Types.hs
Normal 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
16
programs/dump12/Main.hs
Normal 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
|
||||
191
src/ain48.c
191
src/ain48.c
@ -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
|
||||
|
||||
}
|
||||
28
src/asm.c
28
src/asm.c
@ -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;
|
||||
}
|
||||
85
src/dump12.c
85
src/dump12.c
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
27
src/main.c
27
src/main.c
@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user