| ... | ... |
@@ -24,18 +24,26 @@ evaluxn(u, u->vframe); /* Each frame |
| 24 | 24 |
|
| 25 | 25 |
## Assembly Syntax |
| 26 | 26 |
|
| 27 |
-### Write |
|
| 27 |
+### Assign |
|
| 28 | 28 |
|
| 29 |
-- `;variable`, automatically assign an address to a label. |
|
| 30 |
-- `:const FFCF`, manually assign an address to a label. |
|
| 31 | 29 |
- `@label`, assign the current address to a label. |
| 30 |
+- `;variable 2`, assign an address to a label automatically. |
|
| 31 |
+- `:const 1a2b`, assign an address to a label manually. |
|
| 32 | 32 |
|
| 33 | 33 |
### Read |
| 34 | 34 |
|
| 35 | 35 |
- `,literal`, push label value to stack, prefixed with `LIT LEN`. |
| 36 | 36 |
- `.pointer`, push label value to stack. |
| 37 |
-- `+1234`, push positive lit signed value to stack. |
|
| 38 |
-- `-abcd`, push negative lit signed value to stack. |
|
| 37 |
+ |
|
| 38 |
+### Write |
|
| 39 |
+ |
|
| 40 |
+- `ADD`, an opcode. |
|
| 41 |
+- `#1a`, a literal byte. |
|
| 42 |
+- `#12ef`, a literal short. |
|
| 43 |
+- `+1a`, a literal signed byte. |
|
| 44 |
+- `+12ef`, a literal signed short. |
|
| 45 |
+- `-1a`, a literal signed byte(negative). |
|
| 46 |
+- `-12ef`, a literal signed short(negative). |
|
| 39 | 47 |
|
| 40 | 48 |
### Special |
| 41 | 49 |
|
| ... | ... |
@@ -45,37 +53,30 @@ evaluxn(u, u->vframe); /* Each frame |
| 45 | 53 |
|
| 46 | 54 |
### Operator modes |
| 47 | 55 |
|
| 48 |
-- `,1234 ,0001 ADD2`, 16-bits operators have the short flag `2`. |
|
| 49 |
-- `,12 ,11 GTH JMP?`, conditional operators have the cond flag `?`. |
|
| 56 |
+- `#1234 #0001 ADD2`, 16-bits operators have the short flag `2`. |
|
| 57 |
+- `#12 #11 GTH JMP?`, conditional operators have the cond flag `?`. |
|
| 50 | 58 |
- `+21 -03 MULS`, signed operators have the cond flag `S`. |
| 51 | 59 |
|
| 52 | 60 |
``` |
| 53 |
-( hello world ) |
|
| 54 |
- |
|
| 55 |
-;iterator |
|
| 61 |
+:dev/w fff9 ( const write port ) |
|
| 62 |
+;i 1 ( var iterator ) |
|
| 56 | 63 |
|
| 57 | 64 |
|0100 @RESET |
| 58 | 65 |
|
| 59 |
-@word1 "hello_world ( len: 0x0b ) |
|
| 66 |
+ #00 ,dev/w STR ( set dev/write to console ) |
|
| 60 | 67 |
|
| 61 |
-@loop |
|
| 62 |
- ,00 IOW ( write to device#0 ) |
|
| 63 |
- ,incr JSR ( increment itr ) |
|
| 64 |
- ,word1 ,strlen JSR ( get strlen ) |
|
| 65 |
- NEQ ,loop ROT JSR? ( loop != strlen ) |
|
| 68 |
+ @word1 "hello_world ( len: 0x0b ) |
|
| 66 | 69 |
|
| 67 |
-BRK |
|
| 70 |
+ @loop |
|
| 71 |
+ IOW ( write to device#0 ) |
|
| 72 |
+ ,i LDR #01 ADD ,i STR ( increment itr ) |
|
| 73 |
+ ,i LDR ( a = i ) |
|
| 74 |
+ ,word1 ,strlen JSR ( b = string length ) |
|
| 75 |
+ NEQ ,loop ROT JSR? POP^ ( a != b ? loop ) |
|
| 68 | 76 |
|
| 69 |
-@strlen |
|
| 70 |
- ,0001 ADD^ LDR |
|
| 71 |
- RTS |
|
| 77 |
+BRK |
|
| 72 | 78 |
|
| 73 |
-@incr |
|
| 74 |
- ,iterator LDR |
|
| 75 |
- ,01 ADD |
|
| 76 |
- ,iterator STR |
|
| 77 |
- ,iterator LDR |
|
| 78 |
- RTS |
|
| 79 |
+@strlen #0001 ADD2 LDR RTS |
|
| 79 | 80 |
|
| 80 | 81 |
|c000 @FRAME BRK |
| 81 | 82 |
|d000 @ERROR BRK |
| ... | ... |
@@ -92,7 +92,7 @@ findlabel(char *s) |
| 92 | 92 |
} |
| 93 | 93 |
|
| 94 | 94 |
Uint8 |
| 95 |
-findoperator(char *s) |
|
| 95 |
+findopcode(char *s) |
|
| 96 | 96 |
{
|
| 97 | 97 |
int i; |
| 98 | 98 |
for(i = 0; i < 0x20; ++i) {
|
| ... | ... |
@@ -128,7 +128,7 @@ makelabel(char *name, Uint16 addr) |
| 128 | 128 |
return error("Label duplicate", name);
|
| 129 | 129 |
if(sihx(name)) |
| 130 | 130 |
return error("Label name is hex number", name);
|
| 131 |
- if(findoperator(name)) |
|
| 131 |
+ if(findopcode(name)) |
|
| 132 | 132 |
return error("Label name is invalid", name);
|
| 133 | 133 |
l = &labels[labelslen++]; |
| 134 | 134 |
l->addr = addr; |
| ... | ... |
@@ -174,20 +174,18 @@ pass1(FILE *f) |
| 174 | 174 |
} else if(w[0] == ':') {
|
| 175 | 175 |
if(!makeconst(w + 1, f)) |
| 176 | 176 |
return error("Pass1 failed", w);
|
| 177 |
- } else if(findoperator(w) || scmp(w, "BRK")) |
|
| 177 |
+ } else if(findopcode(w) || scmp(w, "BRK")) |
|
| 178 | 178 |
addr += 1; |
| 179 | 179 |
else {
|
| 180 | 180 |
switch(w[0]) {
|
| 181 | 181 |
case '|': addr = shex(w + 1); break; |
| 182 | 182 |
case '"': addr += slen(w + 1) + 2; break; |
| 183 | 183 |
case '.': addr += 2; break; |
| 184 |
+ case ',': addr += 4; break; |
|
| 184 | 185 |
case '+': /* signed positive */ |
| 185 | 186 |
case '-': /* signed negative */ |
| 186 |
- case ',': |
|
| 187 |
- addr += (sihx(w + 1) && slen(w + 1) == 2 ? 1 : 2); |
|
| 188 |
- addr += (sihx(w + 1) ? slen(w + 1) / 2 : 2); |
|
| 189 |
- break; |
|
| 190 |
- default: return error("Unknown label", w);
|
|
| 187 |
+ case '#': addr += (slen(w + 1) == 2 ? 2 : 4); break; |
|
| 188 |
+ default: return error("Unknown label in first pass", w);
|
|
| 191 | 189 |
} |
| 192 | 190 |
} |
| 193 | 191 |
} |
| ... | ... |
@@ -207,18 +205,18 @@ pass2(FILE *f) |
| 207 | 205 |
if(cmnt(w, &skip)) continue; |
| 208 | 206 |
/* clang-format off */ |
| 209 | 207 |
if(w[0] == '|') p.ptr = shex(w + 1); |
| 208 |
+ else if((op = findopcode(w)) || scmp(w, "BRK")) pushbyte(op, 0); |
|
| 210 | 209 |
else if(w[0] == ':') fscanf(f, "%s", w); |
| 211 | 210 |
else if(w[0] == ';') fscanf(f, "%s", w); |
| 211 |
+ else if(w[0] == '#' && sihx(w + 1) && slen(w + 1) == 2) pushbyte(shex(w), 1); |
|
| 212 |
+ else if(w[0] == '#' && sihx(w + 1) && slen(w + 1) == 4) pushshort(shex(w), 1); |
|
| 212 | 213 |
else if(w[0] == '+' && sihx(w + 1) && slen(w + 1) == 2) pushbyte((Sint8)shex(w + 1), 1); |
| 213 | 214 |
else if(w[0] == '+' && sihx(w + 1) && slen(w + 1) == 4) pushshort((Sint16)shex(w + 1), 1); |
| 214 | 215 |
else if(w[0] == '-' && sihx(w + 1) && slen(w + 1) == 2) pushbyte((Sint8)(shex(w + 1) * -1), 1); |
| 215 | 216 |
else if(w[0] == '-' && sihx(w + 1) && slen(w + 1) == 4) pushshort((Sint16)(shex(w + 1) * -1), 1); |
| 216 | 217 |
else if(w[0] == '"') pushtext(w + 1); |
| 217 | 218 |
else if((l = findlabel(w + 1))) pushshort(l->addr, w[0] == ','); |
| 218 |
- else if((op = findoperator(w)) || scmp(w, "BRK")) pushbyte(op, 0); |
|
| 219 |
- else if(sihx(w + 1) && slen(w + 1) == 2) pushbyte(shex(w + 1), w[0] == ','); |
|
| 220 |
- else if(sihx(w + 1) && slen(w + 1) == 4) pushshort(shex(w + 1), w[0] == ','); |
|
| 221 |
- else return error("Unknown label", w);
|
|
| 219 |
+ else return error("Unknown label in second pass", w);
|
|
| 222 | 220 |
/* clang-format on */ |
| 223 | 221 |
} |
| 224 | 222 |
return 1; |
| ... | ... |
@@ -24,5 +24,5 @@ rm -f ./bin/emulator |
| 24 | 24 |
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 emulator.c -L/usr/local/lib -lSDL2 -o bin/emulator |
| 25 | 25 |
|
| 26 | 26 |
# run |
| 27 |
-./bin/assembler examples/draw.usm bin/boot.rom |
|
| 27 |
+./bin/assembler examples/pixels.usm bin/boot.rom |
|
| 28 | 28 |
./bin/emulator bin/boot.rom |
| 29 | 29 |
deleted file mode 100644 |
| ... | ... |
@@ -1,39 +0,0 @@ |
| 1 |
-( benchmark ) |
|
| 2 |
- |
|
| 3 |
-|0100 @RESET |
|
| 4 |
- |
|
| 5 |
-( arithmetic ) |
|
| 6 |
-,12 ,34 ADD ,46 EQU #00 STR |
|
| 7 |
-,12 ,06 SUB ,0c EQU #01 STR |
|
| 8 |
-,12 ,06 MUL ,6c EQU #02 STR |
|
| 9 |
-,12 ,06 DIV ,03 EQU #03 STR |
|
| 10 |
-,12 ,12 EQU #04 STR |
|
| 11 |
-,12 ,13 NEQ #05 STR |
|
| 12 |
-,12 ,11 GTH #06 STR |
|
| 13 |
-,12 ,13 LTH #07 STR |
|
| 14 |
- |
|
| 15 |
-( arithmetic 16-bit ) |
|
| 16 |
-,1234 ,2345 ADD2 ,3579 EQU2 #08 STR |
|
| 17 |
-,1234 ,0123 SUB2 ,1111 EQU2 #09 STR |
|
| 18 |
-,1234 ,0102 MUL2 ,5868 EQU2 #0a STR |
|
| 19 |
-,5678 ,0100 DIV2 ,0056 EQU2 #0b STR |
|
| 20 |
-,1234 ,1234 EQU2 #0c STR |
|
| 21 |
-,1234 ,0123 NEQ2 #0d STR |
|
| 22 |
-,1234 ,1233 GTH2 #0e STR |
|
| 23 |
-,1234 ,1235 LTH2 #0f STR |
|
| 24 |
- |
|
| 25 |
-BRK |
|
| 26 |
- |
|
| 27 |
-@diff8 ( result of abs sub ) |
|
| 28 |
- OVR OVR GTH ,diff8sub ROT JMP? POP2 |
|
| 29 |
- SWP @diff8sub SUB |
|
| 30 |
-RTS |
|
| 31 |
- |
|
| 32 |
-@diff16 ( result of abs sub16 ) |
|
| 33 |
- OVR2 OVR2 GTH2 ,diff16sub ROT JMP? POP2 |
|
| 34 |
- SWP2 @diff16sub SUB2 |
|
| 35 |
-RTS |
|
| 36 |
- |
|
| 37 |
-|c000 @FRAME BRK |
|
| 38 |
-|d000 @ERROR BRK |
|
| 39 |
-|FFFA .RESET .FRAME .ERROR |
| ... | ... |
@@ -5,21 +5,20 @@ |
| 5 | 5 |
|
| 6 | 6 |
|0100 @RESET |
| 7 | 7 |
|
| 8 |
- ,00 ,dev/w STR ( set dev/write to console ) |
|
| 8 |
+ #00 ,dev/w STR ( set dev/write to console ) |
|
| 9 | 9 |
|
| 10 |
- @word1 "hello_world ( len: 0x0b ) |
|
| 10 |
+ @word1 "hello_world ( len: 0x0b ) |
|
| 11 | 11 |
|
| 12 | 12 |
@loop |
| 13 |
- IOW ( write to device#0 ) |
|
| 14 |
- ,incr JSR ( increment itr ) |
|
| 15 |
- ,i LDR ( a = i ) |
|
| 16 |
- ,word1 ,strlen JSR ( b = string length ) |
|
| 17 |
- NEQ ,loop ROT JSR? ( a != b ? loop ) |
|
| 13 |
+ IOW ( write to device#0 ) |
|
| 14 |
+ ,i LDR #01 ADD ,i STR ( increment itr ) |
|
| 15 |
+ ,i LDR ( a = i ) |
|
| 16 |
+ ,word1 ,strlen JSR ( b = string length ) |
|
| 17 |
+ NEQ ,loop ROT JSR? POP^ ( a != b ? loop ) |
|
| 18 | 18 |
|
| 19 | 19 |
BRK |
| 20 | 20 |
|
| 21 |
-@strlen ,0001 ADD2 LDR RTS |
|
| 22 |
-@incr ,i LDR ,01 ADD ,i STR RTS |
|
| 21 |
+@strlen #0001 ADD2 LDR RTS |
|
| 23 | 22 |
|
| 24 | 23 |
|c000 @FRAME BRK |
| 25 | 24 |
|d000 @ERROR BRK |
| ... | ... |
@@ -7,31 +7,29 @@ |
| 7 | 7 |
|
| 8 | 8 |
|0100 @RESET |
| 9 | 9 |
|
| 10 |
- ,01 ,dev/w STR ( set dev/write to screen ) |
|
| 11 |
- ,01 ,color STR ( set color ) |
|
| 12 |
- ,0020 ,x STR2 ( set x-pos ) |
|
| 13 |
- ,0030 ,y STR2 ( set y-pos ) |
|
| 14 |
- ,01 ,alive STR ( set alive = true ) |
|
| 10 |
+ #01 ,dev/w STR ( set dev/write to screen ) |
|
| 11 |
+ #01 ,color STR ( set color ) |
|
| 12 |
+ #0020 ,x STR2 ( set x-pos ) |
|
| 13 |
+ #0030 ,y STR2 ( set y-pos ) |
|
| 14 |
+ #01 ,alive STR ( set alive = true ) |
|
| 15 | 15 |
|
| 16 | 16 |
BRK |
| 17 | 17 |
|
| 18 | 18 |
|c000 @FRAME |
| 19 | 19 |
|
| 20 |
- ,alive LDR ,00 EQU BRK? |
|
| 21 |
- ,01 ,color LDR ,x LDR2 ,y LDR2 ,putpixel JSR |
|
| 20 |
+ ,alive LDR #00 EQU BRK? |
|
| 21 |
+ #01 ,color LDR ,x LDR2 ,y LDR2 ,putpixel JSR |
|
| 22 | 22 |
,move JSR |
| 23 | 23 |
|
| 24 | 24 |
BRK |
| 25 | 25 |
|
| 26 | 26 |
@move |
| 27 |
- ,x LDR2 ,0001 ADD2 ,x STR2 ( incr x ) |
|
| 28 |
- ,x LDR2 ,0040 LTH2 RTS? ( if x > 60 ) |
|
| 29 |
- ,0020 ,x STR2 ( x = 0x0020 ) |
|
| 30 |
- ,y LDR2 ,0001 ADD2 ,y STR2 ( incr y ) |
|
| 31 |
- |
|
| 32 |
- ,y LDR2 ,0050 LTH2 RTS? ( y > 50 ) |
|
| 33 |
- ,00 ,alive STR ( alive = 0 ) |
|
| 34 |
- |
|
| 27 |
+ ,x LDR2 #0001 ADD2 ,x STR2 ( incr x ) |
|
| 28 |
+ ,x LDR2 #0040 LTH2 RTS? ( if x > 60 ) |
|
| 29 |
+ #0020 ,x STR2 ( x = 0x0020 ) |
|
| 30 |
+ ,y LDR2 #0001 ADD2 ,y STR2 ( incr y ) |
|
| 31 |
+ ,y LDR2 #0050 LTH2 RTS? ( y > 50 ) |
|
| 32 |
+ #00 ,alive STR ( alive = 0 ) |
|
| 35 | 33 |
RTS |
| 36 | 34 |
|
| 37 | 35 |
@putpixel |
| ... | ... |
@@ -8,17 +8,16 @@ |
| 8 | 8 |
|0100 @RESET |
| 9 | 9 |
|
| 10 | 10 |
( set read/write to dev/screen ) |
| 11 |
- ,01 DUP ,dev/r STR ,dev/w STR |
|
| 11 |
+ #01 DUP ,dev/r STR ,dev/w STR |
|
| 12 | 12 |
|
| 13 | 13 |
( load screen size ) |
| 14 |
- ,00 IOR2 ,width STR2 |
|
| 15 |
- ,02 IOR2 ,height STR2 |
|
| 14 |
+ #00 IOR2 ,width STR2 |
|
| 15 |
+ #02 IOR2 ,height STR2 |
|
| 16 | 16 |
|
| 17 | 17 |
( draw pixel at screen center ) |
| 18 |
- |
|
| 19 |
- ,0101 |
|
| 20 |
- ,width LDR2 ,0002 DIV2 |
|
| 21 |
- ,height LDR2 ,0002 DIV2 |
|
| 18 |
+ #0101 |
|
| 19 |
+ ,width LDR2 #0002 DIV2 |
|
| 20 |
+ ,height LDR2 #0002 DIV2 |
|
| 22 | 21 |
,putpixel JSR |
| 23 | 22 |
|
| 24 | 23 |
BRK |
| ... | ... |
@@ -1,19 +1,16 @@ |
| 1 |
-( my test file, junk ) |
|
| 1 |
+( comment ) |
|
| 2 | 2 |
|
| 3 |
-:dev/r fff8 ( std read port ) |
|
| 4 |
-:dev/w fff9 ( std write port ) |
|
| 5 |
- |
|
| 6 |
-;x 2 |
|
| 3 |
+:const abcd |
|
| 4 |
+;byte 1 |
|
| 5 |
+;short 2 |
|
| 7 | 6 |
|
| 8 | 7 |
|0100 @RESET |
| 9 | 8 |
|
| 10 |
- ,00 ,dev/w STR ( set dev/write to console ) |
|
| 11 |
- |
|
| 12 |
- +1234 -0012 ADDS2 |
|
| 9 |
+ 12 34 ADD |
|
| 10 |
+ 1234 0001 ADD2 |
|
| 13 | 11 |
|
| 14 | 12 |
BRK |
| 15 | 13 |
|
| 16 |
- |
|
| 17 | 14 |
|c000 @FRAME BRK |
| 18 | 15 |
|d000 @ERROR BRK |
| 19 | 16 |
|FFFA .RESET .FRAME .ERROR |