... | ... |
@@ -17,20 +17,20 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn |
17 | 17 |
``` |
18 | 18 |
< conditionals > |
19 | 19 |
|
20 |
-+03 +02 ADD |
|
21 |
-+05 EQU |
|
20 |
+0302 ADD |
|
21 |
+05 EQU |
|
22 | 22 |
|
23 |
-.there JMQ |
|
23 |
+.there JMQ |
|
24 | 24 |
|
25 | 25 |
:here |
26 |
- < when not equal > |
|
27 |
- +ee |
|
28 |
- BRK |
|
26 |
+ < when not equal > |
|
27 |
+ ee |
|
28 |
+ BRK |
|
29 | 29 |
|
30 | 30 |
:there |
31 |
- < when is equal > |
|
32 |
- +ff |
|
33 |
- BRK |
|
31 |
+ < when is equal > |
|
32 |
+ ff |
|
33 |
+ BRK |
|
34 | 34 |
``` |
35 | 35 |
|
36 | 36 |
## Mission |
... | ... |
@@ -44,10 +44,6 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn |
44 | 44 |
- Print word to stdout |
45 | 45 |
- Draw pixel to screen |
46 | 46 |
- Detect mouse click |
47 |
-- 16 bits addressing |
|
48 |
-- jumping to subroutine should be relative |
|
49 |
-- Implement addressing |
|
50 |
-- Implement 16 bits operations |
|
51 | 47 |
- Jumps should be relative |
52 | 48 |
- Catch overflow/underflow |
53 | 49 |
- Audo-detect literals length. |
... | ... |
@@ -55,6 +51,13 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn |
55 | 51 |
- Build PPU |
56 | 52 |
- Interrupts |
57 | 53 |
|
54 |
+### 16 Bit Missions |
|
55 |
+ |
|
56 |
+- 16 bits addressing |
|
57 |
+- jumping to subroutine should be relative |
|
58 |
+- Implement addressing |
|
59 |
+- Implement 16 bits operations |
|
60 |
+ |
|
58 | 61 |
## Refs |
59 | 62 |
|
60 | 63 |
https://code.9front.org/hg/plan9front/file/a7f9946e238f/sys/src/games/nes/cpu.c |
... | ... |
@@ -1,16 +1,16 @@ |
1 | 1 |
< conditionals > |
2 | 2 |
|
3 |
-+03 +02 ADD |
|
4 |
-+05 EQU |
|
3 |
+0302 ADD |
|
4 |
+05 EQU |
|
5 | 5 |
|
6 |
-.there JMQ |
|
6 |
+.there JMQ |
|
7 | 7 |
|
8 | 8 |
:here |
9 |
- < when not equal > |
|
10 |
- +ee |
|
11 |
- BRK |
|
9 |
+ < when not equal > |
|
10 |
+ ee |
|
11 |
+ BRK |
|
12 | 12 |
|
13 | 13 |
:there |
14 |
- < when is equal > |
|
15 |
- +ff |
|
16 |
- BRK |
|
14 |
+ < when is equal > |
|
15 |
+ ff |
|
16 |
+ BRK |
... | ... |
@@ -2,17 +2,17 @@ |
2 | 2 |
|
3 | 3 |
:begin |
4 | 4 |
.addall JSR ADD ADD |
5 |
- +06 EQU .isequal JSR |
|
5 |
+ 06 EQU .isequal JSR |
|
6 | 6 |
BRK |
7 | 7 |
|
8 | 8 |
:add1 |
9 |
- +01 RTS |
|
9 |
+ 01 RTS |
|
10 | 10 |
|
11 | 11 |
:add2 |
12 |
- +02 RTS |
|
12 |
+ 02 RTS |
|
13 | 13 |
|
14 | 14 |
:add3 |
15 |
- +03 RTS |
|
15 |
+ 03 RTS |
|
16 | 16 |
|
17 | 17 |
:addall |
18 | 18 |
.add1 JSR |
... | ... |
@@ -21,5 +21,5 @@ |
21 | 21 |
RTS |
22 | 22 |
|
23 | 23 |
:isequal |
24 |
- .addall JSR +ff |
|
24 |
+ .addall JSR ff |
|
25 | 25 |
RTS |
... | ... |
@@ -19,15 +19,15 @@ WITH REGARD TO THIS SOFTWARE. |
19 | 19 |
#define STACK_DEPTH 256 |
20 | 20 |
|
21 | 21 |
typedef unsigned char Uint8; |
22 |
+typedef unsigned short Uint16; |
|
22 | 23 |
|
23 | 24 |
typedef struct { |
24 |
- Uint8 literal; |
|
25 |
- Uint8 status, counter; |
|
26 |
- Uint8 memory[STACK_DEPTH]; |
|
25 |
+ Uint8 literal, status; |
|
27 | 26 |
Uint8 mptr, sptr, rsptr; |
27 |
+ Uint8 memory[STACK_DEPTH]; |
|
28 | 28 |
Uint8 stack[STACK_DEPTH]; |
29 | 29 |
Uint8 rstack[STACK_DEPTH]; |
30 |
- Uint8 address[STACK_DEPTH]; |
|
30 |
+ Uint16 counter; |
|
31 | 31 |
} Computer; |
32 | 32 |
|
33 | 33 |
Computer cpu; |
... | ... |
@@ -92,7 +92,7 @@ rspop(void) |
92 | 92 |
|
93 | 93 |
void op_brk() { setflag(FLAG_HALT, 1); } |
94 | 94 |
void op_rts() { cpu.mptr = rspop(); } |
95 |
-void op_lit() { cpu.literal += 1; } |
|
95 |
+void op_lit() { cpu.literal += cpu.memory[cpu.mptr++]; } |
|
96 | 96 |
void op_drp() { spop(); } |
97 | 97 |
void op_dup() { spush(cpu.stack[cpu.sptr - 1]); } |
98 | 98 |
void op_swp() { Uint8 b = spop(), a = spop(); spush(b); spush(a); } |
... | ... |
@@ -100,8 +100,8 @@ void op_ovr() { spush(cpu.stack[cpu.sptr - 2]); } |
100 | 100 |
void op_rot() { Uint8 c = spop(),b = spop(),a = spop(); spush(b); spush(c); spush(a); } |
101 | 101 |
void op_jmp() { cpu.mptr = spop(); } |
102 | 102 |
void op_jsr() { rspush(cpu.mptr); cpu.mptr = spop(); } |
103 |
-void op_jmq() { if(getflag(FLAG_ZERO)){ op_jmp(); } setflag(FLAG_ZERO,0); } |
|
104 |
-void op_jsq() { if(getflag(FLAG_ZERO)){ op_jsr(); } setflag(FLAG_ZERO,0); } |
|
103 |
+void op_jmq() { Uint8 a = spop(); if(getflag(FLAG_ZERO)){ cpu.mptr = a; } setflag(FLAG_ZERO,0); } |
|
104 |
+void op_jsq() { Uint8 a = spop(); if(getflag(FLAG_ZERO)){ rspush(cpu.mptr); cpu.mptr = a; } setflag(FLAG_ZERO,0); } |
|
105 | 105 |
void op_equ() { setflag(FLAG_ZERO, spop() == spop()); } |
106 | 106 |
void op_neq() { setflag(FLAG_ZERO, spop() != spop()); } |
107 | 107 |
void op_lth() { setflag(FLAG_ZERO, spop() < spop()); } |
... | ... |
@@ -120,6 +120,13 @@ void (*ops[])(void) = { |
120 | 120 |
op_jmp, op_jsr, op_jmq, op_jsq, op_equ, op_neq, op_gth, op_lth, |
121 | 121 |
op_and, op_ora, op_rol, op_ror, op_add, op_sub, op_mul, op_div}; |
122 | 122 |
|
123 |
+Uint8 opr[][2] = { |
|
124 |
+ {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, |
|
125 |
+ {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, |
|
126 |
+ {0,0}, {0,0}, {0,0}, {0,0}, {2,1}, {0,0}, {0,0}, {0,0}, |
|
127 |
+ {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, |
|
128 |
+}; |
|
129 |
+ |
|
123 | 130 |
/* clang-format on */ |
124 | 131 |
|
125 | 132 |
void |
... | ... |
@@ -148,38 +155,40 @@ load(FILE *f) |
148 | 155 |
fread(cpu.memory, sizeof(cpu.memory), 1, f); |
149 | 156 |
} |
150 | 157 |
|
151 |
-void |
|
158 |
+int |
|
152 | 159 |
eval() |
153 | 160 |
{ |
154 | 161 |
Uint8 instr = cpu.memory[cpu.mptr++]; |
155 | 162 |
if(cpu.literal > 0) { |
156 | 163 |
spush(instr); |
157 | 164 |
cpu.literal--; |
158 |
- return; |
|
165 |
+ return 1; |
|
159 | 166 |
} |
160 |
- if(instr < 24) |
|
167 |
+ if(instr < 24) { |
|
168 |
+ if(cpu.sptr < opr[instr][0]) |
|
169 |
+ return error("Stack underflow"); |
|
170 |
+ /* TODO stack overflow */ |
|
161 | 171 |
(*ops[instr])(); |
172 |
+ } |
|
162 | 173 |
if(instr > 0x10) |
163 | 174 |
setflag(FLAG_ZERO, 0); |
175 |
+ cpu.counter++; |
|
176 |
+ return 1; |
|
164 | 177 |
} |
165 | 178 |
|
166 | 179 |
void |
167 | 180 |
run(void) |
168 | 181 |
{ |
169 |
- int i; |
|
170 |
- while((cpu.status & FLAG_HALT) == 0) |
|
171 |
- eval(cpu); |
|
182 |
+ while(!(cpu.status & FLAG_HALT) && eval(cpu)) |
|
183 |
+ ; |
|
172 | 184 |
/* debug */ |
173 |
- printf("ended @ %d | ", cpu.counter); |
|
185 |
+ printf("ended @ %d steps | ", cpu.counter); |
|
174 | 186 |
printf("hf: %x zf: %x cf: %x tf: %x\n", |
175 |
- getflag(FLAG_HALT), |
|
176 |
- getflag(FLAG_ZERO), |
|
177 |
- getflag(FLAG_CARRY), |
|
178 |
- getflag(FLAG_TRAPS)); |
|
179 |
- printf("\n\n"); |
|
180 |
- for(i = 0; i < 4; i++) |
|
181 |
- printf("%d-", (cpu.status & (1 << i)) != 0); |
|
182 |
- printf("\n\n"); |
|
187 |
+ getflag(FLAG_HALT) != 0, |
|
188 |
+ getflag(FLAG_ZERO) != 0, |
|
189 |
+ getflag(FLAG_CARRY) != 0, |
|
190 |
+ getflag(FLAG_TRAPS) != 0); |
|
191 |
+ printf("\n"); |
|
183 | 192 |
} |
184 | 193 |
|
185 | 194 |
int |
... | ... |
@@ -29,33 +29,14 @@ typedef struct { |
29 | 29 |
int labelslen; |
30 | 30 |
Label labels[256]; |
31 | 31 |
|
32 |
+/* clang-format off */ |
|
33 |
+ |
|
32 | 34 |
char opcodes[][4] = { |
33 |
- "BRK", |
|
34 |
- "RTS", |
|
35 |
- "LIT", |
|
36 |
- "POP", |
|
37 |
- "DUP", |
|
38 |
- "SWP", |
|
39 |
- "OVR", |
|
40 |
- "ROT", |
|
41 |
- /* */ |
|
42 |
- "JMP", |
|
43 |
- "JSR", |
|
44 |
- "JMQ", |
|
45 |
- "JSQ", |
|
46 |
- "EQU", |
|
47 |
- "NEQ", |
|
48 |
- "LTH", |
|
49 |
- "GTH", |
|
50 |
- "---", |
|
51 |
- "---", |
|
52 |
- "---", |
|
53 |
- "---", |
|
54 |
- "ADD", |
|
55 |
- "SUB", |
|
56 |
- "MUL", |
|
57 |
- "DIV" |
|
58 |
- /* */}; |
|
35 |
+ "BRK", "RTS", "LIT", "POP", "DUP", "SWP", "OVR", "ROT", |
|
36 |
+ "JMP", "JSR", "JMQ", "JSQ", "EQU", "NEQ", "LTH", "GTH", |
|
37 |
+ "AND", "ORA", "ROL", "ROR", "ADD", "SUB", "MUL", "DIV"}; |
|
38 |
+ |
|
39 |
+/* clang-format on */ |
|
59 | 40 |
|
60 | 41 |
Program p; |
61 | 42 |
|
... | ... |
@@ -81,6 +62,15 @@ scpy(char *src, char *dst, int len) /* string copy */ |
81 | 62 |
return dst; |
82 | 63 |
} |
83 | 64 |
|
65 |
+int |
|
66 |
+slen(char *s) /* string length */ |
|
67 |
+{ |
|
68 |
+ int i = 0; |
|
69 |
+ while(s[i] && s[++i]) |
|
70 |
+ ; |
|
71 |
+ return i; |
|
72 |
+} |
|
73 |
+ |
|
84 | 74 |
char * |
85 | 75 |
suca(char *s) /* string to uppercase */ |
86 | 76 |
{ |
... | ... |
@@ -120,11 +110,41 @@ shex(char *s) /* string to num */ |
120 | 110 |
#pragma mark - Parser |
121 | 111 |
|
122 | 112 |
void |
123 |
-addprg(Uint8 hex) |
|
113 |
+pushprg(Uint8 hex) |
|
124 | 114 |
{ |
125 | 115 |
p.data[p.len++] = hex; |
126 | 116 |
} |
127 | 117 |
|
118 |
+void |
|
119 |
+pushlabel(Label *l) |
|
120 |
+{ |
|
121 |
+ pushprg(0x02); |
|
122 |
+ pushprg(0x01); |
|
123 |
+ pushprg(l->addr); |
|
124 |
+} |
|
125 |
+ |
|
126 |
+void |
|
127 |
+pushliteral(char *w) |
|
128 |
+{ |
|
129 |
+ int len = slen(w) / 2, value = shex(w); |
|
130 |
+ pushprg(0x02); |
|
131 |
+ pushprg(len); |
|
132 |
+ switch(len) { |
|
133 |
+ case 1: |
|
134 |
+ pushprg(value); |
|
135 |
+ break; |
|
136 |
+ case 2: |
|
137 |
+ pushprg(value >> 8); |
|
138 |
+ pushprg(value); |
|
139 |
+ break; |
|
140 |
+ case 3: |
|
141 |
+ pushprg(value >> 16); |
|
142 |
+ pushprg(value >> 8); |
|
143 |
+ pushprg(value); |
|
144 |
+ break; |
|
145 |
+ } |
|
146 |
+} |
|
147 |
+ |
|
128 | 148 |
void |
129 | 149 |
addlabel(char *id, Uint8 addr) |
130 | 150 |
{ |
... | ... |
@@ -164,10 +184,9 @@ int |
164 | 184 |
getlength(char *w) |
165 | 185 |
{ |
166 | 186 |
if(findop(w) || scmp(w, "BRK")) return 1; |
167 |
- if(w[0] == '.') return 2; |
|
187 |
+ if(w[0] == '.') return 3; |
|
168 | 188 |
if(w[0] == ':') return 0; |
169 |
- if(w[0] == '+') return 2; |
|
170 |
- if(w[0] == '-') return 2; |
|
189 |
+ if(sihx(w)) { return slen(w) / 2 + 2; } |
|
171 | 190 |
printf("Unknown length %s\n", w); |
172 | 191 |
return 0; |
173 | 192 |
} |
... | ... |
@@ -209,21 +228,14 @@ pass2(FILE *f) |
209 | 228 |
if(word[0] == ':') continue; |
210 | 229 |
suca(word); |
211 | 230 |
if(comment(word, &skip)) continue; |
212 |
- /* literals */ |
|
213 |
- if(word[0] == '+' || word[0] == '-') |
|
214 |
- addprg(0x02); |
|
215 |
- if(word[0] == '+') |
|
216 |
- addprg(shex(word + 1)); |
|
217 |
- else if(word[0] == '-') |
|
218 |
- addprg((Uint8)(-1 * shex(word + 1))); |
|
219 |
- /* opcodes */ |
|
220 |
- else if((op = findop(word)) || scmp(word, "BRK")) |
|
221 |
- addprg(op); |
|
222 |
- else if((l = findlabel(word + 1))) { |
|
223 |
- addprg(0x02); |
|
224 |
- addprg(l->addr); |
|
225 |
- } else |
|
226 |
- printf("unknown: %s\n", word); |
|
231 |
+ if((op = findop(word)) || scmp(word, "BRK")) |
|
232 |
+ pushprg(op); |
|
233 |
+ else if((l = findlabel(word + 1))) |
|
234 |
+ pushlabel(l); |
|
235 |
+ else if(sihx(word)) |
|
236 |
+ pushliteral(word); |
|
237 |
+ else |
|
238 |
+ printf("Unknown label: %s\n", word); |
|
227 | 239 |
} |
228 | 240 |
} |
229 | 241 |
|