commit e52878c5e2165687e2c9abe23d2b27055600faa5 Author: Louis Burke Date: Sat Sep 2 10:01:24 2023 -0400 w: Initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..867733f --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# ASCII Rendered, Compiled Target Invocation Code + +Like the JVM, but the "binaries" consist of printable ASCII characters and the +result can be more easily precompiled for native execution. + diff --git a/doc/documentation.md b/doc/documentation.md new file mode 100644 index 0000000..5315c60 --- /dev/null +++ b/doc/documentation.md @@ -0,0 +1,133 @@ +# ASCII Rendered, Compiled Target Invocation Code + +Like the JVM, but the "binaries" consist of printable ASCII characters and the +result can be more easily precompiled for native execution. + +## Opcodes + +```{=todo} +Notate that immediates can be: …###, …###.###, …$name, or …v (for abcinxyz) +for most operations that take immediates. +``` + +### Summary + + | -0 | -1 | -2 | -3 | -4 | -5 | -6 | -7 +---:|:------:|:------:|:------:|:------:|:------:|:------:|:------:|:------: +000-|`0 BNEZ`|`1 LDAB`|`2 LDAS`|`3 LDAI`|`4 LDAW`|`5 STAB`|`6 STAS`|`7 STAI` +001-|`8 STAW`|`9 CASS`|`A PUTA`|`B PUTB`|`C PUTC`|`D MCLR`|`E FTOI`|`F FREE` +010-|`G LDOI`|`H LDOS`|`I PUTI`|`J MOFF`|`K MCPY`|`L ROLL`|`M MNEW`|`N PUTN` +011-|`O ITOC`|`P PICK`|`Q LDOW`|`R MALL`|`S ITOS`|`T ????`|`U CMPU`|`V B_OR` +100-|`W ITOW`|`X PUTX`|`Y PUTY`|`Z PUTZ`|`a GETA`|`b GETB`|`c GETC`|`d MSET` +101-|`e SROT`|`f FMOD`|`g FINV`|`h OVER`|`i GETI`|`j FNEG`|`k SPOP`|`l BITC` +110-|`m FSUB`|`n GETN`|`o LDOB`|`p FMUL`|`q FDIV`|`r FREM`|`s FADD`|`t SWAP` +111-|`u USHR`|`v FABS`|`w SDUP`|`x GETX`|`y GETY`|`z GETZ`|`_ INEG`|`. ITOF` +200-|`+ IADD`|`- ISUB`|`* IMUL`|`/ IDIV`|`% IMOD`|`\ IREM`|`| IABS`|`$ VALU` +201-|`@ CALL`|`< BLTZ`|`{ BLEZ`|`= BEQZ`|`} BGEZ`|`> BGTZ`|`, JUMP`|`; RTRN` +210-|`& BAND`|`^ BXOR`|`! BNOT`|`[ BSHL`|`] BSHR`|`? CMPI`|`~ CMPF`|`: LABL` +211-|`( DPTH`|`) PACK`|`' IMP1`|`" IMP2`|`\` BKPT`|`␣ NOP`|`# COMM`|`¶ BEAT` +[Operations by code][ops-by-code] + +In this table x, y, and z are integers; a, b, and c are floating point numbers; +p and q are memory pointers; and f is a function pointer. Additionally +→ indicates a basic operation, while ⇒ indicates an operation using an immediate +value, and ↔ indicates a meta operation. + + Code | Stack | Description +-----:|:-------------------:|:-------------------------------------------------- +0 BNEZ| … x ⇒ … | branch to immediate if x not zero +1 LDAB| … p → … x | load byte x from p +2 LDAS| … p → … x | load short x from p +3 LDAI| … p → … x | load int x from p +4 LDAW| … p → … x | load word x from p +5 STAB| … p x → … | store byte x to p +6 STAS| … p x → … | store short x to p +7 STAI| … p x → … | store int x to p +8 STAW| … p x → … | store word x to p +9 CASS| … p x y → … z | compare and swap x and y at p, return success +A PUTA| … x → … | store x in rA +B PUTB| … x → … | store x in rB +C PUTC| … x → … | store x in rC +D MCLR| … p x → … | memclear x bytes from p +E FTOI| … a → … x | round a to integer and store in x +F FREE| … p → … | free memory at p +G LDOI| … p ⇒ … x | load int at p plus immediate offset in x +H LDOS| … p ⇒ … x | load short at p plus immediate offset in x +I PUTI| … x → … | store x in rI +J MOFF| … p x → … q | set q to memory pointer p shifted by x bytes +K MCPY| … p q x → … | copy x bytes of memory from p to q +L ROLL| … x y ‥ z ⇒ … y ‥ z x | roll stack by immediate places +M MNEW| … ⇒ … p | allocate memory for immediate bytes at p +N PUTN| … x → … | store x in rN +O ITOC| … x → … x | truncate x to 8 bits, then sign extend +P PICK| … x ‥ z ⇒ … x ‥ z x | pick stack element at immediate place +Q LDOW| … p ⇒ … x | load word at p plus immediate offset in x +R MALL| … x → … p | allocate memory for x bytes at p +S ITOS| … x → … x | truncate x to 16 bits, then sign extend +T ????| | reserved for future instruction +U CMPU| … x y → … z | compare x to y unsigned and set z such that x o y is z o 0 +V B_OR| … x y → … z | bitwise OR x and y and store in z +W ITOW| … x → … x | truncate x to 32 bits, then sign extend +X PUTX| … x → … | store x in rX +Y PUTY| … x → … | store x in rY +Z PUTZ| … x → … | store x in rZ +a GETA| … → … x | load x from rA +b GETB| … → … x | load x from rB +c GETC| … → … x | load x from rC +d MSET| … p x ⇒ … | set x bytes of memory to immediate value at p +e SROT| … x y z → … y z x | rotate stack +f FMOD| … a b → … c | set c to the modulo of a by b +g FINV| … f → f … | invoke f, saving return address on stack +h OVER| … x y → … x y x | stack over +i GETI| … → … x | load x from rI +j FNEG| … a → … a | negate a +k SPOP| … x → … | stack pop +l BITC| … x y → … z | bit clear y from x to z (z = x and not y) +m FSUB| … a b → … c | set c to the difference between a and b (a - b) +n GETN| … → … x | load x from rN +o LDOB| … p ⇒ … x | load byte at p plus immediate offset in x +p FMUL| … a b → … c | set c to the product of a and b +q FDIV| … a b → … c | set c to the quotient of a by b +r FREM| … a b → … c | set c to the remainder of a by b +s FADD| … a b → … c | set c to the sum of a and b +t SWAP| … x y → … y x | stack swap +u USHR| … x ⇒ … x | logical shift x by immediate bits right +v FABS| … a → … a | take the absolute value of a +w SDUP| … x → … x x | stack duplicate +x GETX| … → … x | load x from rX +y GETY| … → … x | load x from rY +z GETZ| … → … x | load x from rZ +_ INEG| … x → … x | negate x +. ITOF| … x → … a | convert x to a floating point number +\+ IADD|… x y → … z | set z to the sum of x and y +\- ISUB|… x y → … z | set z to the difference between x and y (x - y) +\* IMUL|… x y → … z | set z to the product of x and y +/ IDIV| … x y → … z | set z to the quotient of x by y +% IMOD| … x y → … z | set z to the modulo of x by y +\ IREM| … x y → … z | set z to the remainder of x by y +\| IABS|… x → … x | take the absolute value of x +$ VALU| … ↔ … * | load constant value +@ CALL| … ↔ … | call immediate name +< BLTZ| … x ⇒ … | branch to immediate if x less than zero +{ BLEZ| … x ⇒ … | branch to immediate if x is less than or equal to zero +\= BEQZ|… x ⇒ … | branch to immediate if x is zero +} BGEZ| … x ⇒ … | branch to immediate if x is greater or equal to zero +\> BGTZ|… x ⇒ … | branch to immediate if x is greater than zero +, JUMP| … ⇒ … | jump to immediate without pushing return address +; RETN| … f ⇒ … | return from subroutine (jump but for stack) +& BAND| … x y → … z | set z to the bitwise and of x and y +^ BXOR| … x y → … z | set z to the bitwise xor of x and y +! BNOT| … x → y | set y to the bitwise not of x +[ BSHL| … x ⇒ … x | left shift x by immediate bits +] BSHR| … x ⇒ … x | arithmetic right shift x by immediate bits +? CMPI| … x y → … z | compare x to y and set z such that x o y is z o 0 +~ CMPF| … a b ⇒ … c | compare a to b and set c such that a o b is z o c within an immediate error +\: LABL|… f ↔ … | label code location +( DPTH| … → … x | set x to depth of stack (before x) +) PACK| … p x → … | pack x elements of stack (before p) into array p +' IMP1| | implementation defined reserved operation 1 (no immediate) +" IMP2| | implementation defined reserved operation 2 (immediate) +\` BKPT| … ↔ … | trigger breakpoint, or exit if not debugging +␣ NOOP| … ↔ … | do nothing, maybe end identifier definition +¶ BEAT| … ↔ … | mark a beat for relative branching +[Operations in order][ops-in-order] diff --git a/src/arctic.c b/src/arctic.c new file mode 100644 index 0000000..ca75424 --- /dev/null +++ b/src/arctic.c @@ -0,0 +1,67 @@ +#include "arctic.h" + +#include + +int arctic_max_expanded_size(int compressed_size) { + /* at most every 6th byte is free */ + return (6 * compressed_size) / 5 + 1; +} + +int arctic_max_compressed_size(int expanded_size) { + return (5 * expanded_size) / 6 + 1; +} + +void arctic_expand(char *expanded, const char *compressed) { + // TODO +} + +void arctic_compress(char *compressed, const char *expanded) { + // TODO +} + +static const char *parse_immediate(const char *expanded, struct ArcticOperation *op) { + return expanded; // TODO +} + +void arctic_normalize(struct ArcticOperation *ops, const char *expanded) { + const char *o = expanded; + struct ArcticOperation *op = ops; + + *op = (struct ArcticOperation){ 0 }; + + while (*o) { + int opcode = *o++; + + switch (*o) { + /* ops with an immediate */ + case '0': case 'G': case 'H': case 'L': case 'M': case 'P': + case 'Q': case 'd': case 'o': case 'u': case '<': case '{': + case '=': case '}': case '>': case ',': case ';': case '[': + case ']': case '"': + o = parse_immediate(o, op); + + /* ops without an immediate */ + case '1': case '2': case '3': case '4': case '5': case '6': + case '7': case '8': case '9': case 'A': case 'B': case 'C': + case 'D': case 'E': case 'F': case 'I': case 'J': case 'K': + case 'N': case 'O': case 'R': case 'S': case 'U': case 'V': + case 'W': case 'X': case 'Y': case 'Z': case 'a': case 'b': + case 'c': case 'e': case 'f': case 'g': case 'h': case 'i': + case 'j': case 'k': case 'l': case 'm': case 'n': case 'p': + case 'q': case 'r': case 's': case 't': case 'v': case 'w': + case 'x': case 'y': case 'z': case '_': case '.': case '+': + case '-': case '*': case '/': case '%': case '\\': case '|': + case '&': case '^': case '!': case '?': case '(': case ')': + op->opcode = opcode; + *++op = (struct ArcticOperation){ 0 }; + break; + + /* unusual ops */ + case '$': case '@': case ':': case '`': case ' ': case '\n': + case '\'': + + default: /* non-active characters */ + break; + } + } +} diff --git a/src/arctic.h b/src/arctic.h new file mode 100644 index 0000000..36e9ba5 --- /dev/null +++ b/src/arctic.h @@ -0,0 +1,41 @@ +/* ARCTIC library header. To be used as a utility by interpreters and compilers. + * Author: Louis A. Burke + */ +#ifndef ARCTIC_H +#define ARCTIC_H + +#include + +/* encoding/decoding */ +int arctic_max_expanded_size(int compressed_size); +int arctic_max_compressed_size(int expanded_size); +void arctic_expand(char *expanded, const char *compressed); +void arctic_compress(char *compressed, const char *expanded); + +/* normalization */ +struct ArcticIdentifier { + const char *start; /* a pointer into the input, or null */ + int length; +}; + +enum ArcticImmediateKind { ARCTIC_NAME, ARCTIC_INTEGER, ARCTIC_NUMBER }; + +struct ArcticImmediate { + enum ArcticImmediateKind kind; + + union { + struct ArcticIdentifier name; + int64_t integer; + double number; + }; +}; + +struct ArcticOperation { + struct ArcticIdentifier label; + struct ArcticImmediate immediate; + int opcode; /* won't be beat or nop or comm */ +}; + +void arctic_normalize(struct ArcticOperation *ops, const char *expanded); + +#endif /* ARCTIC_H */