| ... | ... |
@@ -10,17 +10,15 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn |
| 10 | 10 |
|
| 11 | 11 |
## Assembly Syntax |
| 12 | 12 |
|
| 13 |
+- `;variable`, a named address(zero-page) |
|
| 13 | 14 |
- `:label`, a named address |
| 14 |
-- `+literal`, a numeric value |
|
| 15 |
-- `.pointer`, pointer to a label |
|
| 15 |
+- `.pointer`, a pointer to a label |
|
| 16 |
+- `@0010`, a position in the program |
|
| 16 | 17 |
|
| 17 | 18 |
``` |
| 18 | 19 |
< conditionals > |
| 19 | 20 |
|
| 20 |
-0302 ADD |
|
| 21 |
-05 EQU |
|
| 22 |
- |
|
| 23 |
-.there JMZ |
|
| 21 |
+.there ( 0a 05 GTH ) JMC |
|
| 24 | 22 |
|
| 25 | 23 |
:here |
| 26 | 24 |
< when not equal > |
| ... | ... |
@@ -35,10 +33,15 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn |
| 35 | 33 |
|
| 36 | 34 |
## Mission |
| 37 | 35 |
|
| 36 |
+### Assembler |
|
| 37 |
+ |
|
| 38 |
+- Crash on missing label |
|
| 38 | 39 |
- Catch overflow/underflow |
| 40 |
+- Constants |
|
| 39 | 41 |
- Jumps should be relative |
| 40 |
-- constants |
|
| 41 |
-- variables |
|
| 42 |
+ |
|
| 43 |
+### CPU |
|
| 44 |
+ |
|
| 42 | 45 |
- Pointers/Literals |
| 43 | 46 |
- A Three-Way Decision Routine(http://www.6502.org/tutorials/compare_instructions.html) |
| 44 | 47 |
- Carry flag? |
| ... | ... |
@@ -47,7 +50,7 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn |
| 47 | 50 |
- Detect mouse click |
| 48 | 51 |
- SDL Layer Emulator |
| 49 | 52 |
- Build PPU |
| 50 |
-- Interrupts |
|
| 53 |
+- Interrupts, vectors |
|
| 51 | 54 |
|
| 52 | 55 |
### 16 Bit Missions |
| 53 | 56 |
|
| ... | ... |
@@ -56,10 +59,6 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn |
| 56 | 59 |
- Implement addressing |
| 57 | 60 |
- Implement 16 bits operations |
| 58 | 61 |
|
| 59 |
-## Notes |
|
| 60 |
- |
|
| 61 |
-- Forth logic operators pop 2 items and add a bool to the stack, is that viable in uxn? |
|
| 62 |
- |
|
| 63 | 62 |
## Refs |
| 64 | 63 |
|
| 65 | 64 |
https://code.9front.org/hg/plan9front/file/a7f9946e238f/sys/src/games/nes/cpu.c |
| ... | ... |
@@ -86,14 +86,14 @@ void op_dup() { wspush(wspeek()); }
|
| 86 | 86 |
void op_swp() { Uint8 b = wspop(), a = wspop(); wspush(b); wspush(a); }
|
| 87 | 87 |
void op_ovr() { wspush(cpu.wst.dat[cpu.wst.ptr - 2]); }
|
| 88 | 88 |
void op_rot() { Uint8 c = wspop(),b = wspop(),a = wspop(); wspush(b); wspush(c); wspush(a); }
|
| 89 |
-void op_jmi() { cpu.rom.ptr = wspop(); }
|
|
| 90 |
-void op_jsi() { rspush(cpu.rom.ptr); cpu.rom.ptr = wspop(); }
|
|
| 91 |
-void op_jmz() { Uint8 a = wspop(); if(getflag(FLAG_ZERO)){ cpu.rom.ptr = a; } setflag(FLAG_ZERO,0); }
|
|
| 92 |
-void op_jsz() { Uint8 a = wspop(); if(getflag(FLAG_ZERO)){ rspush(cpu.rom.ptr); cpu.rom.ptr = a; } setflag(FLAG_ZERO,0); }
|
|
| 93 |
-void op_equ() { setflag(FLAG_ZERO, wspop() == wspeek()); }
|
|
| 94 |
-void op_neq() { setflag(FLAG_ZERO, wspop() != wspeek()); }
|
|
| 95 |
-void op_gth() { setflag(FLAG_ZERO, wspop() < wspeek()); }
|
|
| 96 |
-void op_lth() { setflag(FLAG_ZERO, wspop() > wspeek()); }
|
|
| 89 |
+void op_jmu() { cpu.rom.ptr = wspop(); }
|
|
| 90 |
+void op_jsu() { rspush(cpu.rom.ptr); cpu.rom.ptr = wspop(); }
|
|
| 91 |
+void op_jmc() { if(wspop()) op_jmu(); }
|
|
| 92 |
+void op_jsc() { if(wspop()) op_jsu(); }
|
|
| 93 |
+void op_equ() { wspush(wspop() == wspop()); }
|
|
| 94 |
+void op_neq() { wspush(wspop() != wspop()); }
|
|
| 95 |
+void op_gth() { wspush(wspop() < wspop()); }
|
|
| 96 |
+void op_lth() { wspush(wspop() > wspop()); }
|
|
| 97 | 97 |
void op_and() { wspush(wspop() & wspop()); }
|
| 98 | 98 |
void op_ora() { wspush(wspop() | wspop()); }
|
| 99 | 99 |
void op_rol() { wspush(wspop() << 1); }
|
| ... | ... |
@@ -105,12 +105,12 @@ void op_div() { wspush(wspop() / wspop()); }
|
| 105 | 105 |
|
| 106 | 106 |
void (*ops[])(void) = {
|
| 107 | 107 |
op_brk, op_rts, op_lit, op_drp, op_dup, op_swp, op_ovr, op_rot, |
| 108 |
- op_jmi, op_jsi, op_jmz, op_jsz, op_equ, op_neq, op_gth, op_lth, |
|
| 108 |
+ op_jmu, op_jsu, op_jmc, op_jsc, op_equ, op_neq, op_gth, op_lth, |
|
| 109 | 109 |
op_and, op_ora, op_rol, op_ror, op_add, op_sub, op_mul, op_div}; |
| 110 | 110 |
|
| 111 | 111 |
Uint8 opr[][2] = {
|
| 112 | 112 |
{0,0}, {0,0}, {0,0}, {1,0}, {0,1}, {1,1}, {0,1}, {3,3},
|
| 113 |
- {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0},
|
|
| 113 |
+ {2,0}, {2,0}, {2,0}, {2,0}, {2,1}, {2,1}, {2,1}, {2,1},
|
|
| 114 | 114 |
{1,0}, {1,0}, {1,0}, {1,0}, {2,1}, {0,0}, {0,0}, {0,0},
|
| 115 | 115 |
{2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}
|
| 116 | 116 |
}; |
| ... | ... |
@@ -17,7 +17,7 @@ WITH REGARD TO THIS SOFTWARE. |
| 17 | 17 |
typedef unsigned char Uint8; |
| 18 | 18 |
|
| 19 | 19 |
typedef struct {
|
| 20 |
- int len; |
|
| 20 |
+ int ptr; |
|
| 21 | 21 |
Uint8 data[PRGLEN]; |
| 22 | 22 |
} Program; |
| 23 | 23 |
|
| ... | ... |
@@ -33,7 +33,7 @@ Label labels[256]; |
| 33 | 33 |
|
| 34 | 34 |
char opcodes[][4] = {
|
| 35 | 35 |
"BRK", "RTS", "LIT", "POP", "DUP", "SWP", "OVR", "ROT", |
| 36 |
- "JMI", "JSI", "JMZ", "JSZ", "EQU", "NEQ", "GTH", "LTH", |
|
| 36 |
+ "JMU", "JSU", "JMC", "JSC", "EQU", "NEQ", "GTH", "LTH", |
|
| 37 | 37 |
"AND", "ORA", "ROL", "ROR", "ADD", "SUB", "MUL", "DIV"}; |
| 38 | 38 |
|
| 39 | 39 |
/* clang-format on */ |
| ... | ... |
@@ -112,7 +112,7 @@ shex(char *s) /* string to num */ |
| 112 | 112 |
void |
| 113 | 113 |
pushprg(Uint8 hex) |
| 114 | 114 |
{
|
| 115 |
- p.data[p.len++] = hex; |
|
| 115 |
+ p.data[p.ptr++] = hex; |
|
| 116 | 116 |
} |
| 117 | 117 |
|
| 118 | 118 |
void |
| ... | ... |
@@ -151,13 +151,13 @@ addlabel(char *id, Uint8 addr) |
| 151 | 151 |
Label *l = &labels[labelslen++]; |
| 152 | 152 |
scpy(suca(id), l->name, LABELIDLEN); |
| 153 | 153 |
l->addr = addr; |
| 154 |
- printf("new label: %s=%02x\n", l->name, l->addr);
|
|
| 154 |
+ printf("New label: %s[0x%02x]\n", l->name, l->addr);
|
|
| 155 | 155 |
} |
| 156 | 156 |
|
| 157 | 157 |
void |
| 158 | 158 |
addconst(char *id, Uint8 value) |
| 159 | 159 |
{
|
| 160 |
- printf("new const: %s=%02x\n", id, value);
|
|
| 160 |
+ printf("New const: %s[%02x]\n", id, value);
|
|
| 161 | 161 |
} |
| 162 | 162 |
|
| 163 | 163 |
Label * |
| ... | ... |
@@ -181,18 +181,13 @@ findop(char *s) |
| 181 | 181 |
} |
| 182 | 182 |
|
| 183 | 183 |
int |
| 184 |
-getlength(char *w) |
|
| 184 |
+ismarker(char *w) |
|
| 185 | 185 |
{
|
| 186 |
- if(findop(w) || scmp(w, "BRK")) return 1; |
|
| 187 |
- if(w[0] == '.') return 3; |
|
| 188 |
- if(w[0] == ':') return 0; |
|
| 189 |
- if(sihx(w)) { return slen(w) / 2 + 2; }
|
|
| 190 |
- printf("Unknown length %s\n", w);
|
|
| 191 |
- return 0; |
|
| 186 |
+ return w[0] == '(' || w[0] == ')' || w[0] == '{' || w[0] == '}';
|
|
| 192 | 187 |
} |
| 193 | 188 |
|
| 194 | 189 |
int |
| 195 |
-comment(char *w, int *skip) |
|
| 190 |
+iscomment(char *w, int *skip) |
|
| 196 | 191 |
{
|
| 197 | 192 |
if(w[0] == '>') {
|
| 198 | 193 |
*skip = 0; |
| ... | ... |
@@ -203,15 +198,31 @@ comment(char *w, int *skip) |
| 203 | 198 |
return 0; |
| 204 | 199 |
} |
| 205 | 200 |
|
| 201 |
+int |
|
| 202 |
+getlength(char *w) |
|
| 203 |
+{
|
|
| 204 |
+ if(findop(w) || scmp(w, "BRK")) return 1; |
|
| 205 |
+ if(w[0] == '.') return 3; |
|
| 206 |
+ if(w[0] == ':') return 0; |
|
| 207 |
+ if(w[0] == ';') return 0; |
|
| 208 |
+ if(w[0] == '@') return 0; |
|
| 209 |
+ if(sihx(w)) { return slen(w) / 2 + 2; }
|
|
| 210 |
+ if(ismarker(w)) return 0; |
|
| 211 |
+ printf("Unknown length %s\n", w);
|
|
| 212 |
+ return 0; |
|
| 213 |
+} |
|
| 214 |
+ |
|
| 206 | 215 |
void |
| 207 | 216 |
pass1(FILE *f) |
| 208 | 217 |
{
|
| 209 | 218 |
int skip = 0; |
| 210 | 219 |
int addr = 0; |
| 220 |
+ int vars = 0; |
|
| 211 | 221 |
char word[64]; |
| 212 | 222 |
while(fscanf(f, "%s", word) == 1) {
|
| 213 |
- if(comment(word, &skip)) continue; |
|
| 223 |
+ if(iscomment(word, &skip)) continue; |
|
| 214 | 224 |
if(word[0] == ':') addlabel(word + 1, addr); |
| 225 |
+ if(word[0] == ';') addlabel(word + 1, vars++); |
|
| 215 | 226 |
addr += getlength(word); |
| 216 | 227 |
} |
| 217 | 228 |
rewind(f); |
| ... | ... |
@@ -226,9 +237,12 @@ pass2(FILE *f) |
| 226 | 237 |
Uint8 op = 0; |
| 227 | 238 |
Label *l; |
| 228 | 239 |
if(word[0] == ':') continue; |
| 240 |
+ if(word[0] == ';') continue; |
|
| 229 | 241 |
suca(word); |
| 230 |
- if(comment(word, &skip)) continue; |
|
| 231 |
- if((op = findop(word)) || scmp(word, "BRK")) |
|
| 242 |
+ if(iscomment(word, &skip) || ismarker(word)) continue; |
|
| 243 |
+ if(word[0] == '@') |
|
| 244 |
+ p.ptr = shex(word + 1); |
|
| 245 |
+ else if((op = findop(word)) || scmp(word, "BRK")) |
|
| 232 | 246 |
pushprg(op); |
| 233 | 247 |
else if((l = findlabel(word + 1))) |
| 234 | 248 |
pushlabel(l); |