Browse code

Hello world with strlen

neauoire authored on 06/02/2021 18:39:13
Showing 5 changed files
... ...
@@ -27,6 +27,10 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn
27 27
 - `|0010`, move to position in the program
28 28
 - `"hello`, push literal bytes for word "hello"
29 29
 
30
+### Operator modes
31
+
32
+- `,1234 ,0001 ADD^`, 16-bits operators have the short flag `^`.
33
+
30 34
 ```
31 35
 ( hello world )
32 36
 
... ...
@@ -6,14 +6,19 @@
6 6
 
7 7
 |0100 @RESET
8 8
 
9
-"hello
9
+@word1 "hello_word ( len: 0x0b )
10 10
 
11 11
 @loop
12
-	,dev1w STR
13
-	,incr JSU ( call incr )
14
-	,05 NEQ ,loop ROT JSC
12
+	,dev1w STR ( write to stdout )
13
+	,incr JSU ( increment itr )
14
+	,word1 ,strlen JSU ( get strlen )
15
+	NEQ ,loop ROT JSC ( loop != strlen )
15 16
 
16
-BRK ( RESET )
17
+BRK
18
+
19
+@strlen
20
+	,0001 ADD^ PEK
21
+	RTS
17 22
 
18 23
 @incr
19 24
 	,iterator LDR
... ...
@@ -21,7 +26,7 @@ BRK ( RESET )
21 26
 	,iterator STR 
22 27
 	,iterator LDR
23 28
 	RTS
24
-	
29
+
25 30
 |c000 @FRAME BRK 
26 31
 |d000 @ERROR BRK 
27 32
 |FFFA .RESET .FRAME .ERROR
28 33
new file mode 100644
... ...
@@ -0,0 +1,32 @@
1
+( hello world )
2
+
3
+;iterator
4
+:dev1r FFF0
5
+:dev1w FFF1
6
+
7
+|0100 @RESET
8
+
9
+@word1 "hello_word ( len: 0x0b )
10
+
11
+@loop
12
+	,dev1w STR ( write to stdout )
13
+	,incr JSU ( increment itr )
14
+	,word1 ,strlen JSU ( get strlen )
15
+	NEQ ,loop ROT JSC ( loop != strlen )
16
+
17
+BRK
18
+
19
+@strlen
20
+	,0001 ADD^ PEK
21
+	RTS
22
+
23
+@incr
24
+	,iterator LDR
25
+	,01 ADD
26
+	,iterator STR 
27
+	,iterator LDR
28
+	RTS
29
+
30
+|c000 @FRAME BRK 
31
+|d000 @ERROR BRK 
32
+|FFFA .RESET .FRAME .ERROR
... ...
@@ -12,7 +12,7 @@ WITH REGARD TO THIS SOFTWARE.
12 12
 */
13 13
 
14 14
 #define FLAG_HALT 0x01
15
-#define FLAG_ZERO 0x02
15
+#define FLAG_SHORT 0x02
16 16
 #define FLAG_CARRY 0x04
17 17
 #define FLAG_TRAPS 0x08
18 18
 
... ...
@@ -96,6 +96,7 @@ Uint8 rampeek8(Uint16 s) { return cpu.ram.dat[s] & 0xff; }
96 96
 Uint8 mempeek8(Uint16 s) { return cpu.rom.dat[s]; }
97 97
 Uint16 mempeek16(Uint16 s) { return (cpu.rom.dat[s] << 8) + (cpu.rom.dat[s+1] & 0xff); }
98 98
 void wspush8(Uint8 b) { cpu.wst.dat[cpu.wst.ptr++] = b; }
99
+void wspush16(Uint16 s) { wspush8(s >> 8); wspush8(s & 0xff); }
99 100
 Uint8 wspop8(void) { return cpu.wst.dat[--cpu.wst.ptr]; }
100 101
 Uint16 wspop16(void) { return wspop8() + (wspop8() << 8); }
101 102
 Uint8 wspeek8(void) { return cpu.wst.dat[cpu.wst.ptr - 1]; }
... ...
@@ -116,24 +117,31 @@ void op_jmc() { if(wspop8()) op_jmu(); }
116 117
 void op_jsc() { if(wspop8()) op_jsu(); }
117 118
 void op_equ() { wspush8(wspop8() == wspop8()); }
118 119
 void op_neq() { wspush8(wspop8() != wspop8()); }
119
-void op_gth() {	wspush8(wspop8() < wspop8()); }
120
-void op_lth() {	wspush8(wspop8() > wspop8()); }
121
-void op_and() {	wspush8(wspop8() & wspop8()); }
122
-void op_ora() {	wspush8(wspop8() | wspop8()); }
120
+void op_gth() { wspush8(wspop8() < wspop8()); }
121
+void op_lth() { wspush8(wspop8() > wspop8()); }
122
+void op_and() { wspush8(wspop8() & wspop8()); }
123
+void op_ora() { wspush8(wspop8() | wspop8()); }
123 124
 void op_rol() { wspush8(wspop8() << 1); }
124 125
 void op_ror() { wspush8(wspop8() >> 1); }
125
-void op_add() { wspush8(wspop8() + wspop8()); }
126
+void op_add() { 
127
+	if(getflag(FLAG_SHORT))
128
+		wspush16(wspop16() + wspop16()); 
129
+	else
130
+		wspush8(wspop8() + wspop8()); 
131
+}
126 132
 void op_sub() { wspush8(wspop8() - wspop8()); }
127 133
 void op_mul() { wspush8(wspop8() * wspop8()); }
128 134
 void op_div() { wspush8(wspop8() / wspop8()); }
129 135
 void op_ldr() { wspush8(cpu.ram.dat[wspop16()]); }
130 136
 void op_str() { cpu.ram.dat[wspop16()] = wspop8(); }
137
+void op_pek() { wspush8(cpu.rom.dat[wspop16()]); }
138
+void op_pok() { printf("TODO:\n");}
131 139
 
132
-void (*ops[])(void) = {
140
+void (*ops[])() = {
133 141
 	op_brk, op_rts, op_lit, op_drp, op_dup, op_swp, op_ovr, op_rot, 
134 142
 	op_jmu, op_jsu, op_jmc, op_jsc, op_equ, op_neq, op_gth, op_lth, 
135 143
 	op_and, op_ora, op_rol, op_ror, op_add, op_sub, op_mul, op_div,
136
-	op_ldr, op_str, op_brk, op_brk, op_brk, op_brk, op_brk, op_brk
144
+	op_ldr, op_str, op_pek, op_pok, op_brk, op_brk, op_brk, op_brk
137 145
 };
138 146
 
139 147
 Uint8 opr[][2] = {
... ...
@@ -162,9 +170,9 @@ reset(void)
162 170
 }
163 171
 
164 172
 int
165
-error(char *name)
173
+error(char *name, int id)
166 174
 {
167
-	printf("Error: %s, at 0x%04x\n", name, cpu.counter);
175
+	printf("Error: %s[%04x], at 0x%04x\n", name, id, cpu.counter);
168 176
 	return 0;
169 177
 }
170 178
 
... ...
@@ -177,31 +185,48 @@ device1(Uint8 *read, Uint8 *write)
177 185
 	return 0;
178 186
 }
179 187
 
188
+void
189
+opc(Uint8 src, Uint8 *op, Uint8 *mode)
190
+{
191
+	*op = src;
192
+	*op &= ~(1 << 5);
193
+	*op &= ~(1 << 6);
194
+	*op &= ~(1 << 7);
195
+	*mode = src;
196
+	*mode &= ~(1 << 0);
197
+	*mode &= ~(1 << 1);
198
+	*mode &= ~(1 << 2);
199
+	*mode &= ~(1 << 3);
200
+}
201
+
180 202
 int
181 203
 eval(void)
182 204
 {
183 205
 	Uint8 instr = cpu.rom.dat[cpu.rom.ptr++];
206
+	Uint8 op, opmode;
207
+	/* when literal */
184 208
 	if(cpu.literal > 0) {
185 209
 		wspush8(instr);
186 210
 		cpu.literal--;
187 211
 		return 1;
188 212
 	}
189
-	if(instr < 32) {
190
-		if(cpu.wst.ptr < opr[instr][0])
191
-			return error("Stack underflow");
192
-		/* TODO stack overflow */
193
-		(*ops[instr])();
194
-	}
195
-	if(instr > 0x10)
196
-		setflag(FLAG_ZERO, 0);
197
-	if(cpu.counter == 128) {
198
-		return error("Reached bounds");
199
-	}
213
+	/* when opcode */
214
+	opc(instr, &op, &opmode);
215
+	setflag(FLAG_SHORT, (instr >> 5) & 1);
216
+	if((instr >> 6) & 1)
217
+		printf("Unused flag: %02x\n", instr);
218
+	if((instr >> 7) & 1)
219
+		printf("Unused flag: %02x\n", instr);
220
+	/* TODO: setflag(FLAG_B, (instr >> 6) & 1); */
221
+	/* TODO: setflag(FLAG_C, (instr >> 7) & 1); */
222
+	if(cpu.wst.ptr < opr[op][0])
223
+		return error("Stack underflow", op);
224
+	(*ops[op])();
200 225
 	cpu.counter++;
201 226
 	return 1;
202 227
 }
203 228
 
204
-void
229
+int
205 230
 start(FILE *f)
206 231
 {
207 232
 	reset();
... ...
@@ -216,6 +241,8 @@ start(FILE *f)
216 241
 		/* experimental */
217 242
 		if(cpu.ram.dat[0xfff1])
218 243
 			device1(&cpu.ram.dat[0xfff0], &cpu.ram.dat[0xfff1]);
244
+		if(cpu.counter > 256)
245
+			return error("Reached bounds", cpu.counter);
219 246
 	}
220 247
 	/*eval frame */
221 248
 	printf("\nPhase: frame\n");
... ...
@@ -227,10 +254,11 @@ start(FILE *f)
227 254
 	printf("ended @ %d steps | ", cpu.counter);
228 255
 	printf("hf: %x zf: %x cf: %x tf: %x\n",
229 256
 		getflag(FLAG_HALT) != 0,
230
-		getflag(FLAG_ZERO) != 0,
257
+		getflag(FLAG_SHORT) != 0,
231 258
 		getflag(FLAG_CARRY) != 0,
232 259
 		getflag(FLAG_TRAPS) != 0);
233 260
 	printf("\n");
261
+	return 1;
234 262
 }
235 263
 
236 264
 int
... ...
@@ -238,10 +266,11 @@ main(int argc, char *argv[])
238 266
 {
239 267
 	FILE *f;
240 268
 	if(argc < 2)
241
-		return error("No input.");
269
+		return error("No input.", 0);
242 270
 	if(!(f = fopen(argv[1], "rb")))
243
-		return error("Missing input.");
244
-	start(f);
271
+		return error("Missing input.", 0);
272
+	if(!start(f))
273
+		return error("Program error", 0);
245 274
 	/* print result */
246 275
 	echos(&cpu.wst, 0x40, "stack");
247 276
 	echom(&cpu.ram, 0x40, "ram");
... ...
@@ -29,11 +29,11 @@ Label labels[256];
29 29
 
30 30
 /* clang-format off */
31 31
 
32
-char opcodes[][4] = {
32
+char ops[][4] = {
33 33
 	"BRK", "RTS", "LIT", "POP", "DUP", "SWP", "OVR", "ROT",
34 34
 	"JMU", "JSU", "JMC", "JSC", "EQU", "NEQ", "GTH", "LTH",
35 35
 	"AND", "ORA", "ROL", "ROR", "ADD", "SUB", "MUL", "DIV",
36
-	"LDR", "STR", "---", "---", "---", "---", "---", "---"
36
+	"LDR", "STR", "PEK", "POK", "---", "---", "---", "---"
37 37
 };
38 38
 
39 39
 /* clang-format on */
... ...
@@ -162,6 +162,27 @@ findlabel(char *s)
162 162
 	return NULL;
163 163
 }
164 164
 
165
+Uint8
166
+findop(char *s)
167
+{
168
+	int i;
169
+	for(i = 0; i < 32; ++i) {
170
+		int m = 0;
171
+		if(ops[i][0] != s[0]) continue;
172
+		if(ops[i][1] != s[1]) continue;
173
+		if(ops[i][2] != s[2]) continue;
174
+		while(s[3 + m]) {
175
+			char c = s[3 + m];
176
+			if(c == '^') i |= (1 << 5); /* mode: 16 bits */
177
+			if(c == '&') i |= (1 << 6); /* mode: unused */
178
+			if(c == '~') i |= (1 << 7); /* mode: unused */
179
+			m++;
180
+		}
181
+		return i;
182
+	}
183
+	return 0;
184
+}
185
+
165 186
 #pragma mark - Parser
166 187
 
167 188
 int
... ...
@@ -171,16 +192,6 @@ error(char *name, char *id)
171 192
 	return 0;
172 193
 }
173 194
 
174
-Uint8
175
-findop(char *s)
176
-{
177
-	int i;
178
-	for(i = 0; i < 32; ++i)
179
-		if(scmp(opcodes[i], s))
180
-			return i;
181
-	return 0;
182
-}
183
-
184 195
 int
185 196
 makelabel(char *id, Uint16 addr)
186 197
 {
... ...
@@ -210,7 +221,6 @@ pass1(FILE *f)
210 221
 	char w[64];
211 222
 	while(fscanf(f, "%s", w) == 1) {
212 223
 		if(iscomment(w, &skip)) continue;
213
-		suca(w);
214 224
 		if(w[0] == '@' && !makelabel(w + 1, addr))
215 225
 			return error("Pass1 failed", w);
216 226
 		if(w[0] == ';' && !makelabel(w + 1, vars++))
... ...
@@ -253,7 +263,6 @@ pass2(FILE *f)
253 263
 		Label *l;
254 264
 		if(w[0] == '@') continue;
255 265
 		if(w[0] == ';') continue;
256
-		suca(w);
257 266
 		if(iscomment(w, &skip)) continue;
258 267
 		if(w[0] == '|')
259 268
 			p.ptr = shex(w + 1);
... ...
@@ -261,10 +270,10 @@ pass2(FILE *f)
261 270
 			fscanf(f, "%s", w);
262 271
 		else if(w[0] == '"')
263 272
 			pushword(w + 1);
264
-		else if((op = findop(w)) || scmp(w, "BRK"))
265
-			pushbyte(op, 0);
266 273
 		else if((l = findlabel(w + 1)))
267 274
 			pushshort(l->addr, w[0] == ',');
275
+		else if((op = findop(w)) || scmp(w, "BRK"))
276
+			pushbyte(op, 0);
268 277
 		else if(sihx(w + 1) && slen(w + 1) == 2)
269 278
 			pushbyte(shex(w + 1), w[0] == ',');
270 279
 		else if(sihx(w + 1) && slen(w + 1) == 4)