mirror of
https://git.sr.ht/~rabbits/uxn
synced 2024-11-22 13:55:11 +00:00
*
This commit is contained in:
parent
588a0f8b92
commit
72d9c98f35
4 changed files with 67 additions and 50 deletions
56
README.md
56
README.md
|
@ -8,34 +8,29 @@ A stack-based VM, written in ANSI C.
|
|||
cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn
|
||||
```
|
||||
|
||||
## OP Codes
|
||||
## Assembly Syntax
|
||||
|
||||
```
|
||||
VALUE OPCODE EXPLANATION
|
||||
0x00000000 NOP do nothing
|
||||
0x00000001 ADD pop a, pop b, push a + b
|
||||
0x00000002 SUB pop a, pop b, push a - b
|
||||
0x00000003 AND pop a, pop b, push a & b
|
||||
0x00000004 OR pop a, pop b, push a | b
|
||||
0x00000005 XOR pop a, pop b, push a ^ b
|
||||
0x00000006 NOT pop a, push !a
|
||||
0x00000007 IN read one byte from stdin, push as word on stack
|
||||
0x00000008 OUT pop one word and write to stream as one byte
|
||||
0x00000009 LOAD pop a, push word read from address a
|
||||
0x0000000A STOR pop a, pop b, write b to address a
|
||||
0x0000000B JMP pop a, goto a
|
||||
0x0000000C JZ pop a, pop b, if a == 0 goto b
|
||||
0x0000000D PUSH push next word
|
||||
0x0000000E DUP duplicate word on stack
|
||||
0x0000000F SWAP swap top two words on stack
|
||||
0x00000010 ROL3 rotate top three words on stack once left, (a b c) -> (b c a)
|
||||
0x00000011 OUTNUM pop one word and write to stream as number
|
||||
0x00000012 JNZ pop a, pop b, if a != 0 goto b
|
||||
0x00000013 DROP remove top of stack
|
||||
0x00000014 PUSHIP push a in IP stack
|
||||
0x00000015 POPIP pop IP stack to current IP, effectively performing a jump
|
||||
0x00000016 DROPIP pop IP, but do not jump
|
||||
0x00000017 COMPL pop a, push the complement of a
|
||||
: starting a definition
|
||||
& obtaining pointers
|
||||
( stack comments
|
||||
` inlining bytecodes
|
||||
' strings
|
||||
# numbers
|
||||
$ characters
|
||||
~ vector
|
||||
[ 12 34 ] real values
|
||||
< 12 34 > relative values
|
||||
( 12 34 ) deadzone
|
||||
```
|
||||
|
||||
```
|
||||
;add-two JSR
|
||||
|
||||
BRK
|
||||
|
||||
:add-two
|
||||
[ 2 ] ADD RTS
|
||||
```
|
||||
|
||||
## Design
|
||||
|
@ -50,12 +45,11 @@ VALUE OPCODE EXPLANATION
|
|||
|
||||
### Assembly
|
||||
|
||||
- `%25`, decimal
|
||||
- `#25`, hex
|
||||
#### Addressing
|
||||
|
||||
```
|
||||
2 2 + $ef
|
||||
```
|
||||
- `label`, a named offset[TODO]
|
||||
- `literal`, a numeric value
|
||||
- `pointer`, pointer to an address[TODO]
|
||||
|
||||
### Assembler
|
||||
|
||||
|
|
6
build.sh
6
build.sh
|
@ -10,14 +10,14 @@ rm -f ./uxn
|
|||
|
||||
# debug(slow)
|
||||
cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined uxnasm.c -o uxnasm
|
||||
cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined uxn.c -o uxn
|
||||
# cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined uxn.c -o uxn
|
||||
|
||||
# build(fast)
|
||||
# cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn
|
||||
|
||||
# Size
|
||||
echo "Size: $(du -sk ./uxn)"
|
||||
# echo "Size: $(du -sk ./uxn)"
|
||||
|
||||
# run
|
||||
./uxnasm program.usm program.rom
|
||||
./uxn program.rom
|
||||
# ./uxn program.rom
|
||||
|
|
|
@ -1 +1 @@
|
|||
#12 #34 add
|
||||
LIT 25 26 LIT DUP ADD BRK
|
53
uxnasm.c
53
uxnasm.c
|
@ -14,13 +14,14 @@ WITH REGARD TO THIS SOFTWARE.
|
|||
#define PRGLEN 256
|
||||
|
||||
typedef unsigned char Uint8;
|
||||
typedef unsigned short Uint16;
|
||||
|
||||
typedef struct {
|
||||
int ptr;
|
||||
Uint16 data[PRGLEN];
|
||||
Uint8 data[PRGLEN];
|
||||
} Program;
|
||||
|
||||
char opcodes[][4] = {"BRK", "LIT", "DUP", "DRP", "SWP", "SLP", "PSH", "POP", "JMP", "JSR", "RST", "BEQ", "EQU", "NEQ", "LTH", "GTH"};
|
||||
|
||||
Program p;
|
||||
|
||||
#pragma mark - Helpers
|
||||
|
@ -35,6 +36,16 @@ scmp(char *a, char *b) /* string compare */
|
|||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
suca(char *s) /* string to uppercase */
|
||||
{
|
||||
int i = 0;
|
||||
char c;
|
||||
while((c = s[i]))
|
||||
s[i++] = c >= 'a' && c <= 'z' ? c - ('a' - 'A') : c;
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
shex(char *s) /* string to num */
|
||||
{
|
||||
|
@ -53,10 +64,27 @@ shex(char *s) /* string to num */
|
|||
Uint8
|
||||
getopcode(char *s)
|
||||
{
|
||||
if(scmp(s, "add")) {
|
||||
return 0x01;
|
||||
int i;
|
||||
for(i = 0; i < 16; ++i)
|
||||
if(scmp(opcodes[i], suca(s)))
|
||||
return i;
|
||||
return 0xff;
|
||||
}
|
||||
return 0;
|
||||
|
||||
void
|
||||
echo(Uint8 *s, Uint8 len, Uint8 ptr, char *name)
|
||||
{
|
||||
int i;
|
||||
printf("%s\n", name);
|
||||
for(i = 0; i < len; ++i) {
|
||||
if(i % 16 == 0)
|
||||
printf("\n");
|
||||
if(ptr == i)
|
||||
printf("[%02x]", s[i]);
|
||||
else
|
||||
printf(" %02x ", s[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -64,16 +92,10 @@ pass1(FILE *f)
|
|||
{
|
||||
char word[64];
|
||||
while(fscanf(f, "%s", word) == 1) {
|
||||
int lit = 0, val = 0;
|
||||
if(word[0] == '#') {
|
||||
lit = 0;
|
||||
val = shex(word + 1);
|
||||
} else {
|
||||
lit = 1;
|
||||
val = getopcode(word);
|
||||
}
|
||||
printf("#%d -> %s[%02x %02x]\n", p.ptr, word, lit, val);
|
||||
p.data[p.ptr++] = (val << 8) + (lit & 0xff);
|
||||
int op = getopcode(word);
|
||||
if(op == 0xff)
|
||||
op = shex(word);
|
||||
p.data[p.ptr++] = op;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,5 +117,6 @@ main(int argc, char *argv[])
|
|||
pass1(f);
|
||||
fwrite(p.data, sizeof(p.data), 1, fopen(argv[2], "wb"));
|
||||
fclose(f);
|
||||
echo(p.data, 0x40, 0, "program");
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue