27#include "pico/stdlib.h"
36extern uint16_t run9900(uint8_t* memory, uint16_t pc, uint16_t wp, uint8_t* regx38);
43#define MEM_SIZE (0x10000u + 36)
46#define SCRATCH 0x0200u
47#define REG(r) ((uint32_t)(WP + (r) * 2u))
49static _Alignas(4) uint8_t mem[MEM_SIZE];
58static
int indepTotal = 0;
59static
int indepPassed = 0;
60static
int indepFailed = 0;
61static
int indepPass = 1;
66static inline
void w16(uint32_t addr, uint16_t v)
68 mem[addr] = (uint8_t)(v >> 8);
69 mem[addr + 1] = (uint8_t)(v & 0xFF);
72static inline uint16_t r16(uint32_t addr)
74 return (uint16_t)((mem[addr] << 8) | mem[addr + 1]);
84static void setup(
const uint16_t* regs)
86 memset(mem, 0,
sizeof(mem));
88 for (
int i = 0; i < 16; i++)
94static void load_prog(
const uint8_t* prog, uint16_t len)
96 memcpy(mem + PROG, prog, len);
100static void run_c(
void);
102static void run_asm(
void)
106 run9900(mem, PROG, WP, &r38);
118static bool f18aMemory =
false;
120static void run_c(
void)
124 tms9900_init(&cpu, mem, &r38, PROG, WP);
125 cpu.f18aMemory = f18aMemory;
131static void check(
const char* label,
int ok,
const char* detail)
134 if (indepPass) indepTotal++;
137 if (indepPass) indepPassed++;
138 printf(
" PASS: %s\n", label);
141 if (indepPass) indepFailed++;
142 printf(
" FAIL: %s - %s\n", label, detail);
144 for (
int i = 0; i < 8; i++) printf(
" R%d=%04X", i, r16(REG(i)));
150static char _det[128];
152#define CHECK_REG(lbl, reg, expected) do { \
153 uint16_t _v = r16(REG(reg)); \
154 if (_v == (expected)) { check(lbl, 1, ""); } \
155 else { snprintf(_det,sizeof(_det),"R%d=%04X expected %04X",reg,_v,(uint16_t)(expected)); check(lbl,0,_det); } \
158#define CHECK_MEM16(lbl, addr, expected) do { \
159 uint16_t _v = r16(addr); \
160 if (_v == (expected)) { check(lbl, 1, ""); } \
161 else { snprintf(_det,sizeof(_det),"[%04X]=%04X expected %04X",(uint16_t)(addr),_v,(uint16_t)(expected)); check(lbl,0,_det); } \
164#define CHECK_MEM8(lbl, addr, expected) do { \
165 uint8_t _v = mem[addr]; \
166 if (_v == (expected)) { check(lbl, 1, ""); } \
167 else { snprintf(_det,sizeof(_det),"[%04X]=%02X expected %02X",(uint16_t)(addr),_v,(uint8_t)(expected)); check(lbl,0,_det); } \
175static inline void emit(uint8_t* b, uint16_t* o, uint16_t w)
177 b[(*o)++] = (uint8_t)(w >> 8);
178 b[(*o)++] = (uint8_t)(w & 0xFF);
183static inline void li (uint8_t* b, uint16_t* o, uint8_t rd, uint16_t imm) { emit(b,o,(uint16_t)(0x0200u|rd)); emit(b,o,imm); }
184static inline void ai (uint8_t* b, uint16_t* o, uint8_t rd, uint16_t imm) { emit(b,o,(uint16_t)(0x0220u|rd)); emit(b,o,imm); }
185static inline void andi_op(uint8_t* b, uint16_t* o, uint8_t rd, uint16_t imm) { emit(b,o,(uint16_t)(0x0240u|rd)); emit(b,o,imm); }
186static inline void ori_op (uint8_t* b, uint16_t* o, uint8_t rd, uint16_t imm) { emit(b,o,(uint16_t)(0x0260u|rd)); emit(b,o,imm); }
187static inline void ci (uint8_t* b, uint16_t* o, uint8_t rd, uint16_t imm) { emit(b,o,(uint16_t)(0x0280u|rd)); emit(b,o,imm); }
188static inline void stwp (uint8_t* b, uint16_t* o, uint8_t rd) { emit(b,o,(uint16_t)(0x02A0u|rd)); }
189static inline void stst (uint8_t* b, uint16_t* o, uint8_t rd) { emit(b,o,(uint16_t)(0x02C0u|rd)); }
190static inline void lwpi (uint8_t* b, uint16_t* o, uint16_t wp) { emit(b,o,0x02E0u); emit(b,o,wp); }
191static inline void limi (uint8_t* b, uint16_t* o, uint16_t mask) { emit(b,o,0x0300u); emit(b,o,mask); }
192static inline void rtwp (uint8_t* b, uint16_t* o) { emit(b,o,0x0380u); }
194static inline void blwp (uint8_t* b, uint16_t* o, uint16_t addr) { emit(b,o,(uint16_t)(0x0400u|(2u<<4)|0)); emit(b,o,addr); }
195static inline void b_ind (uint8_t* b, uint16_t* o, uint8_t rd) { emit(b,o,(uint16_t)(0x0440u|(1u<<4)|rd)); }
196static inline void b_abs (uint8_t* b, uint16_t* o, uint16_t addr) { emit(b,o,(uint16_t)(0x0440u|(2u<<4)|0)); emit(b,o,addr); }
198static inline void x_reg (uint8_t* b, uint16_t* o, uint8_t rd) { emit(b,o,(uint16_t)(0x0480u|rd)); }
199static inline void clr (uint8_t* b, uint16_t* o, uint8_t rd) { emit(b,o,(uint16_t)(0x04C0u|rd)); }
200static inline void neg (uint8_t* b, uint16_t* o, uint8_t rd) { emit(b,o,(uint16_t)(0x0500u|rd)); }
201static inline void inv (uint8_t* b, uint16_t* o, uint8_t rd) { emit(b,o,(uint16_t)(0x0540u|rd)); }
202static inline void inc (uint8_t* b, uint16_t* o, uint8_t rd) { emit(b,o,(uint16_t)(0x0580u|rd)); }
203static inline void inct (uint8_t* b, uint16_t* o, uint8_t rd) { emit(b,o,(uint16_t)(0x05C0u|rd)); }
204static inline void dec (uint8_t* b, uint16_t* o, uint8_t rd) { emit(b,o,(uint16_t)(0x0600u|rd)); }
205static inline void dect (uint8_t* b, uint16_t* o, uint8_t rd) { emit(b,o,(uint16_t)(0x0640u|rd)); }
206static inline void bl_abs (uint8_t* b, uint16_t* o, uint16_t addr) { emit(b,o,(uint16_t)(0x0680u|(2u<<4)|0)); emit(b,o,addr); }
207static inline void swpb (uint8_t* b, uint16_t* o, uint8_t rd) { emit(b,o,(uint16_t)(0x06C0u|rd)); }
208static inline void seto (uint8_t* b, uint16_t* o, uint8_t rd) { emit(b,o,(uint16_t)(0x0700u|rd)); }
209static inline void abs_r (uint8_t* b, uint16_t* o, uint8_t rd) { emit(b,o,(uint16_t)(0x0740u|rd)); }
210static inline void rt (uint8_t* b, uint16_t* o) { emit(b,o,(uint16_t)(0x0440u|(1u<<4)|11u)); }
213static inline void sra (uint8_t* b, uint16_t* o, uint8_t rd, uint8_t c) { emit(b,o,(uint16_t)(0x0800u|((uint16_t)(c&0xF)<<4)|(rd&0xF))); }
214static inline void srl (uint8_t* b, uint16_t* o, uint8_t rd, uint8_t c) { emit(b,o,(uint16_t)(0x0900u|((uint16_t)(c&0xF)<<4)|(rd&0xF))); }
215static inline void sla (uint8_t* b, uint16_t* o, uint8_t rd, uint8_t c) { emit(b,o,(uint16_t)(0x0A00u|((uint16_t)(c&0xF)<<4)|(rd&0xF))); }
216static inline void src_op (uint8_t* b, uint16_t* o, uint8_t rd, uint8_t c) { emit(b,o,(uint16_t)(0x0B00u|((uint16_t)(c&0xF)<<4)|(rd&0xF))); }
224static inline void jcc(uint8_t* b, uint16_t* o, uint8_t cond, int8_t off)
226 emit(b, o, (uint16_t)(0x1000u | ((uint16_t)(cond & 0xF) << 8) | (uint8_t)off));
229static inline void jmp (uint8_t* b, uint16_t* o, int8_t off) { jcc(b,o,0x0,off); }
230static inline void jlt (uint8_t* b, uint16_t* o, int8_t off) { jcc(b,o,0x1,off); }
231static inline void jle (uint8_t* b, uint16_t* o, int8_t off) { jcc(b,o,0x2,off); }
232static inline void jeq (uint8_t* b, uint16_t* o, int8_t off) { jcc(b,o,0x3,off); }
233static inline void jhe (uint8_t* b, uint16_t* o, int8_t off) { jcc(b,o,0x4,off); }
234static inline void jgt (uint8_t* b, uint16_t* o, int8_t off) { jcc(b,o,0x5,off); }
235static inline void jne (uint8_t* b, uint16_t* o, int8_t off) { jcc(b,o,0x6,off); }
236static inline void jnc (uint8_t* b, uint16_t* o, int8_t off) { jcc(b,o,0x7,off); }
237static inline void joc (uint8_t* b, uint16_t* o, int8_t off) { jcc(b,o,0x8,off); }
238static inline void jno (uint8_t* b, uint16_t* o, int8_t off) { jcc(b,o,0x9,off); }
239static inline void jl (uint8_t* b, uint16_t* o, int8_t off) { jcc(b,o,0xA,off); }
240static inline void jh (uint8_t* b, uint16_t* o, int8_t off) { jcc(b,o,0xB,off); }
241static inline void jop (uint8_t* b, uint16_t* o, int8_t off) { jcc(b,o,0xC,off); }
243static inline void coc (uint8_t* b, uint16_t* o, uint8_t rs, uint8_t rd) { emit(b,o,(uint16_t)(0x2000u|((uint16_t)rd<<6)|rs)); }
244static inline void czc (uint8_t* b, uint16_t* o, uint8_t rs, uint8_t rd) { emit(b,o,(uint16_t)(0x2400u|((uint16_t)rd<<6)|rs)); }
245static inline void xor_rr (uint8_t* b, uint16_t* o, uint8_t rs, uint8_t rd) { emit(b,o,(uint16_t)(0x2800u|((uint16_t)rd<<6)|rs)); }
246static inline void pix (uint8_t* b, uint16_t* o, uint8_t rs, uint8_t rd) { emit(b,o,(uint16_t)(0x2C00u|((uint16_t)rd<<6)|rs)); }
247static inline void mpy (uint8_t* b, uint16_t* o, uint8_t rs, uint8_t rd) { emit(b,o,(uint16_t)(0x3800u|((uint16_t)rd<<6)|rs)); }
248static inline void div_op (uint8_t* b, uint16_t* o, uint8_t rs, uint8_t rd) { emit(b,o,(uint16_t)(0x3C00u|((uint16_t)rd<<6)|rs)); }
252static inline void szc_rr (uint8_t* b, uint16_t* o, uint8_t rs, uint8_t rd) { emit(b,o,(uint16_t)(0x4000u|((uint16_t)rd<<6)|rs)); }
253static inline void szcb_rr(uint8_t* b, uint16_t* o, uint8_t rs, uint8_t rd) { emit(b,o,(uint16_t)(0x5000u|((uint16_t)rd<<6)|rs)); }
254static inline void sub_rr (uint8_t* b, uint16_t* o, uint8_t rs, uint8_t rd) { emit(b,o,(uint16_t)(0x6000u|((uint16_t)rd<<6)|rs)); }
255static inline void sb_rr (uint8_t* b, uint16_t* o, uint8_t rs, uint8_t rd) { emit(b,o,(uint16_t)(0x7000u|((uint16_t)rd<<6)|rs)); }
256static inline void cb_rr (uint8_t* b, uint16_t* o, uint8_t rs, uint8_t rd) { emit(b,o,(uint16_t)(0x9000u|((uint16_t)rd<<6)|rs)); }
257static inline void add_rr (uint8_t* b, uint16_t* o, uint8_t rs, uint8_t rd) { emit(b,o,(uint16_t)(0xA000u|((uint16_t)rd<<6)|rs)); }
258static inline void ab_rr (uint8_t* b, uint16_t* o, uint8_t rs, uint8_t rd) { emit(b,o,(uint16_t)(0xB000u|((uint16_t)rd<<6)|rs)); }
259static inline void mov_rr (uint8_t* b, uint16_t* o, uint8_t rs, uint8_t rd) { emit(b,o,(uint16_t)(0xC000u|((uint16_t)rd<<6)|rs)); }
260static inline void mov_ir (uint8_t* b, uint16_t* o, uint8_t rs, uint8_t rd) { emit(b,o,(uint16_t)(0xC000u|((uint16_t)rd<<6)|(1u<<4)|rs)); }
261static inline void mov_ri (uint8_t* b, uint16_t* o, uint8_t rs, uint8_t rd) { emit(b,o,(uint16_t)(0xC000u|((uint16_t)(0x10u|rd)<<6)|rs)); }
262static inline void mov_ar (uint8_t* b, uint16_t* o, uint16_t addr, uint8_t rd) { emit(b,o,(uint16_t)(0xC000u|((uint16_t)rd<<6)|(2u<<4)|0)); emit(b,o,addr); }
263static inline void movb_rr(uint8_t* b, uint16_t* o, uint8_t rs, uint8_t rd) { emit(b,o,(uint16_t)(0xD000u|((uint16_t)rd<<6)|rs)); }
264static inline void soc_rr (uint8_t* b, uint16_t* o, uint8_t rs, uint8_t rd) { emit(b,o,(uint16_t)(0xE000u|((uint16_t)rd<<6)|rs)); }
265static inline void socb_rr(uint8_t* b, uint16_t* o, uint8_t rs, uint8_t rd) { emit(b,o,(uint16_t)(0xF000u|((uint16_t)rd<<6)|rs)); }
271static void test_data_transfer(
void)
273 printf(
"\n=== Data Transfer ===\n");
274 uint8_t p[MAX_PROG]; uint16_t n;
277 printf(
" LI R0,0x1234\n");
278 n=0; li(p,&n,0,0x1234); emit(p,&n,IDLE);
279 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"LI R0,0x1234 [ASM]", 0, 0x1234);
280 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"LI R0,0x1234 [C]", 0, 0x1234);
283 printf(
" MOV R0,R1\n");
284 n=0; li(p,&n,0,0xABCD); mov_rr(p,&n,0,1); emit(p,&n,IDLE);
285 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"MOV R0->R1", 1, 0xABCD);
286 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"MOV R0->R1", 1, 0xABCD);
289 printf(
" MOV *R0,R1\n");
290 n=0; mov_ir(p,&n,0,1); emit(p,&n,IDLE);
291 { uint16_t regs[16]={0}; regs[0]=SCRATCH;
292 setup(regs); w16(SCRATCH,0xBEEF); load_prog(p,n);
293 run_asm(); CHECK_REG(
"MOV *R0->R1", 1, 0xBEEF);
294 setup(regs); w16(SCRATCH,0xBEEF); load_prog(p,n);
295 run_c(); CHECK_REG(
"MOV *R0->R1", 1, 0xBEEF); }
298 printf(
" MOV R0,*R1\n");
299 n=0; mov_ri(p,&n,0,1); emit(p,&n,IDLE);
300 { uint16_t regs[16]={0}; regs[0]=0x1234; regs[1]=SCRATCH;
301 setup(regs); load_prog(p,n); run_asm(); CHECK_MEM16(
"MOV R0->*R1", SCRATCH, 0x1234);
302 setup(regs); load_prog(p,n); run_c(); CHECK_MEM16(
"MOV R0->*R1", SCRATCH, 0x1234); }
305 printf(
" MOV @addr,R1\n");
306 n=0; mov_ar(p,&n,SCRATCH,1); emit(p,&n,IDLE);
307 setup(NULL); w16(SCRATCH,0xCAFE); load_prog(p,n);
308 run_asm(); CHECK_REG(
"MOV @abs->R1", 1, 0xCAFE);
309 setup(NULL); w16(SCRATCH,0xCAFE); load_prog(p,n);
310 run_c(); CHECK_REG(
"MOV @abs->R1", 1, 0xCAFE);
313 printf(
" MOV *R0+,R2\n");
314 n=0; emit(p,&n,(uint16_t)(0xC000u|((uint16_t)2<<6)|(3u<<4)|0)); emit(p,&n,IDLE);
315 { uint16_t regs[16]={0}; regs[0]=SCRATCH;
316 setup(regs); w16(SCRATCH,0x5A5A); load_prog(p,n);
317 run_asm(); CHECK_REG(
"autoinc R0", 0, SCRATCH+2); CHECK_REG(
"autoinc R2", 2, 0x5A5A);
318 setup(regs); w16(SCRATCH,0x5A5A); load_prog(p,n);
319 run_c(); CHECK_REG(
"autoinc R0", 0, SCRATCH+2); CHECK_REG(
"autoinc R2", 2, 0x5A5A); }
322 printf(
" MOVB R0,R1\n");
323 n=0; li(p,&n,0,0x5500); movb_rr(p,&n,0,1); emit(p,&n,IDLE);
324 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"MOVB R0->R1", 1, 0x5500);
325 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"MOVB R0->R1", 1, 0x5500);
328static void test_arithmetic(
void)
330 printf(
"\n=== Arithmetic ===\n");
331 uint8_t p[MAX_PROG]; uint16_t n;
334 printf(
" A R0,R1 (3+4=7)\n");
335 n=0; li(p,&n,0,3); li(p,&n,1,4); add_rr(p,&n,0,1); emit(p,&n,IDLE);
336 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"A 3+4=7", 1, 7);
337 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"A 3+4=7", 1, 7);
340 printf(
" A carry (0xFFFF+1)\n");
341 n=0; li(p,&n,0,0xFFFF); li(p,&n,1,1); add_rr(p,&n,0,1); stst(p,&n,2); emit(p,&n,IDLE);
342 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"ADD carry result", 1, 0);
343 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"ADD carry result", 1, 0);
345 setup(NULL); load_prog(p,n); run_asm(); { uint16_t st=r16(REG(2));
346 snprintf(_det,
sizeof(_det),
"ST=%04X C-bit missing",st);
347 check(
"ADD carry flag [ASM]", (st&0x1000)!=0, _det); }
348 setup(NULL); load_prog(p,n); run_c(); { uint16_t st=r16(REG(2));
349 snprintf(_det,
sizeof(_det),
"ST=%04X C-bit missing",st);
350 check(
"ADD carry flag [C]", (st&0x1000)!=0, _det); }
353 printf(
" S R0,R1 (5-3=2)\n");
354 n=0; li(p,&n,0,3); li(p,&n,1,5); sub_rr(p,&n,0,1); emit(p,&n,IDLE);
355 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"S 5-3=2", 1, 2);
356 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"S 5-3=2", 1, 2);
359 printf(
" NEG R0 (1->0xFFFF)\n");
360 n=0; li(p,&n,0,1); neg(p,&n,0); emit(p,&n,IDLE);
361 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"NEG 1", 0, 0xFFFF);
362 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"NEG 1", 0, 0xFFFF);
365 printf(
" ABS R0 (0x0005)\n");
366 n=0; li(p,&n,0,5); abs_r(p,&n,0); emit(p,&n,IDLE);
367 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"ABS pos", 0, 5);
368 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"ABS pos", 0, 5);
371 printf(
" ABS R0 (0xFFFB->5)\n");
372 n=0; li(p,&n,0,0xFFFB); abs_r(p,&n,0); emit(p,&n,IDLE);
373 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"ABS neg", 0, 5);
374 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"ABS neg", 0, 5);
377 printf(
" INC R0 (4->5)\n");
378 n=0; li(p,&n,0,4); inc(p,&n,0); emit(p,&n,IDLE);
379 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"INC", 0, 5);
380 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"INC", 0, 5);
383 printf(
" INCT R0 (4->6)\n");
384 n=0; li(p,&n,0,4); inct(p,&n,0); emit(p,&n,IDLE);
385 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"INCT", 0, 6);
386 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"INCT", 0, 6);
389 printf(
" DEC R0 (5->4)\n");
390 n=0; li(p,&n,0,5); dec(p,&n,0); emit(p,&n,IDLE);
391 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"DEC", 0, 4);
392 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"DEC", 0, 4);
395 printf(
" DECT R0 (6->4)\n");
396 n=0; li(p,&n,0,6); dect(p,&n,0); emit(p,&n,IDLE);
397 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"DECT", 0, 4);
398 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"DECT", 0, 4);
401 printf(
" AI R0,0x10 (5+16=21)\n");
402 n=0; li(p,&n,0,5); ai(p,&n,0,0x10); emit(p,&n,IDLE);
403 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"AI", 0, 21);
404 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"AI", 0, 21);
407 printf(
" MPY R1,R0 (3*4=12)\n");
408 n=0; li(p,&n,0,3); li(p,&n,1,4); mpy(p,&n,1,0); emit(p,&n,IDLE);
409 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"MPY hi", 0, 0); CHECK_REG(
"MPY lo", 1, 12);
410 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"MPY hi", 0, 0); CHECK_REG(
"MPY lo", 1, 12);
413 printf(
" DIV R2,R0 (12/4=3)\n");
414 n=0; li(p,&n,0,0); li(p,&n,1,12); li(p,&n,2,4); div_op(p,&n,2,0); emit(p,&n,IDLE);
415 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"DIV quot", 0, 3); CHECK_REG(
"DIV rem", 1, 0);
416 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"DIV quot", 0, 3); CHECK_REG(
"DIV rem", 1, 0);
421 printf(
" AB R0,R1 (0x01+0x02 in the high byte)\n");
422 n=0; li(p,&n,0,0x0100); li(p,&n,1,0x0234); ab_rr(p,&n,0,1); emit(p,&n,IDLE);
423 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"AB", 1, 0x0334);
424 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"AB", 1, 0x0334);
426 printf(
" SB R0,R1 (0x05-0x02 in the high byte)\n");
427 n=0; li(p,&n,0,0x0200); li(p,&n,1,0x0534); sb_rr(p,&n,0,1); emit(p,&n,IDLE);
428 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"SB", 1, 0x0334);
429 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"SB", 1, 0x0334);
435 printf(
" DIV by zero (overflow, operands unchanged)\n");
436 n=0; li(p,&n,0,1); li(p,&n,1,2); li(p,&n,2,0); div_op(p,&n,2,0); stst(p,&n,3); emit(p,&n,IDLE);
437 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"DIV/0 hi", 0, 1); CHECK_REG(
"DIV/0 lo", 1, 2);
438 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"DIV/0 hi", 0, 1); CHECK_REG(
"DIV/0 lo", 1, 2);
439 setup(NULL); load_prog(p,n); run_asm(); { uint16_t st=r16(REG(3));
440 snprintf(_det,
sizeof(_det),
"ST=%04X OV-bit missing",st);
441 check(
"DIV/0 OV [ASM]", (st&0x0800)!=0, _det); }
442 setup(NULL); load_prog(p,n); run_c(); { uint16_t st=r16(REG(3));
443 snprintf(_det,
sizeof(_det),
"ST=%04X OV-bit missing",st);
444 check(
"DIV/0 OV [C]", (st&0x0800)!=0, _det); }
446 printf(
" DIV quotient too wide (overflow)\n");
447 n=0; li(p,&n,0,5); li(p,&n,1,0); li(p,&n,2,4); div_op(p,&n,2,0); stst(p,&n,3); emit(p,&n,IDLE);
448 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"DIV OV hi", 0, 5); CHECK_REG(
"DIV OV lo", 1, 0);
449 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"DIV OV hi", 0, 5); CHECK_REG(
"DIV OV lo", 1, 0);
450 setup(NULL); load_prog(p,n); run_asm(); { uint16_t st=r16(REG(3));
451 snprintf(_det,
sizeof(_det),
"ST=%04X OV-bit missing",st);
452 check(
"DIV wide OV [ASM]", (st&0x0800)!=0, _det); }
453 setup(NULL); load_prog(p,n); run_c(); { uint16_t st=r16(REG(3));
454 snprintf(_det,
sizeof(_det),
"ST=%04X OV-bit missing",st);
455 check(
"DIV wide OV [C]", (st&0x0800)!=0, _det); }
458 printf(
" NEG 0x8000 (overflow)\n");
459 n=0; li(p,&n,0,0x8000); neg(p,&n,0); stst(p,&n,1); emit(p,&n,IDLE);
460 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"NEG 0x8000 result", 0, 0x8000);
461 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"NEG 0x8000 result", 0, 0x8000);
462 setup(NULL); load_prog(p,n); run_asm(); { uint16_t st=r16(REG(1));
463 snprintf(_det,
sizeof(_det),
"ST=%04X OV-bit missing",st);
464 check(
"NEG 0x8000 OV [ASM]", (st&0x0800)!=0, _det); }
465 setup(NULL); load_prog(p,n); run_c(); { uint16_t st=r16(REG(1));
466 snprintf(_det,
sizeof(_det),
"ST=%04X OV-bit missing",st);
467 check(
"NEG 0x8000 OV [C]", (st&0x0800)!=0, _det); }
470static void test_logical(
void)
472 printf(
"\n=== Logical ===\n");
473 uint8_t p[MAX_PROG]; uint16_t n;
476 printf(
" SZC R0,R1\n");
477 n=0; li(p,&n,0,0x00FF); li(p,&n,1,0xFFFF); szc_rr(p,&n,0,1); emit(p,&n,IDLE);
478 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"SZC", 1, 0xFF00);
479 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"SZC", 1, 0xFF00);
482 printf(
" SOC R0,R1\n");
483 n=0; li(p,&n,0,0x0F0F); li(p,&n,1,0xF0F0); soc_rr(p,&n,0,1); emit(p,&n,IDLE);
484 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"SOC", 1, 0xFFFF);
485 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"SOC", 1, 0xFFFF);
488 printf(
" XOR R0,R1\n");
489 n=0; li(p,&n,0,0xAAAA); li(p,&n,1,0xFFFF); xor_rr(p,&n,0,1); emit(p,&n,IDLE);
490 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"XOR", 1, 0x5555);
491 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"XOR", 1, 0x5555);
495 n=0; li(p,&n,0,0xAAAA); inv(p,&n,0); emit(p,&n,IDLE);
496 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"INV", 0, 0x5555);
497 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"INV", 0, 0x5555);
501 n=0; li(p,&n,0,0x1234); clr(p,&n,0); emit(p,&n,IDLE);
502 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"CLR", 0, 0);
503 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"CLR", 0, 0);
506 printf(
" SETO R0\n");
507 n=0; seto(p,&n,0); emit(p,&n,IDLE);
508 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"SETO", 0, 0xFFFF);
509 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"SETO", 0, 0xFFFF);
512 printf(
" ANDI R0,0x0F0F\n");
513 n=0; li(p,&n,0,0xFFFF); andi_op(p,&n,0,0x0F0F); emit(p,&n,IDLE);
514 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"ANDI", 0, 0x0F0F);
515 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"ANDI", 0, 0x0F0F);
518 printf(
" ORI R0,0xFF00\n");
519 n=0; li(p,&n,0,0x00FF); ori_op(p,&n,0,0xFF00); emit(p,&n,IDLE);
520 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"ORI", 0, 0xFFFF);
521 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"ORI", 0, 0xFFFF);
524 printf(
" COC R0,R1 (match)\n");
525 n=0; li(p,&n,0,0x0F0F); li(p,&n,1,0xFFFF); coc(p,&n,0,1); stst(p,&n,2); emit(p,&n,IDLE);
526 setup(NULL); load_prog(p,n); run_asm(); { uint16_t st=r16(REG(2));
527 snprintf(_det,
sizeof(_det),
"ST=%04X EQ-bit missing",st);
528 check(
"COC EQ [ASM]", (st&0x2000)!=0, _det); }
529 setup(NULL); load_prog(p,n); run_c(); { uint16_t st=r16(REG(2));
530 snprintf(_det,
sizeof(_det),
"ST=%04X EQ-bit missing",st);
531 check(
"COC EQ [C]", (st&0x2000)!=0, _det); }
535 printf(
" CZC R0,R1 (all clear)\n");
536 n=0; li(p,&n,0,0x00FF); li(p,&n,1,0xFF00); czc(p,&n,0,1); stst(p,&n,2); emit(p,&n,IDLE);
537 setup(NULL); load_prog(p,n); run_asm(); { uint16_t st=r16(REG(2));
538 snprintf(_det,
sizeof(_det),
"ST=%04X EQ-bit missing",st);
539 check(
"CZC EQ [ASM]", (st&0x2000)!=0, _det); }
540 setup(NULL); load_prog(p,n); run_c(); { uint16_t st=r16(REG(2));
541 snprintf(_det,
sizeof(_det),
"ST=%04X EQ-bit missing",st);
542 check(
"CZC EQ [C]", (st&0x2000)!=0, _det); }
544 printf(
" CZC R0,R1 (one bit set)\n");
545 n=0; li(p,&n,0,0x00FF); li(p,&n,1,0xFF01); czc(p,&n,0,1); stst(p,&n,2); emit(p,&n,IDLE);
546 setup(NULL); load_prog(p,n); run_asm(); { uint16_t st=r16(REG(2));
547 snprintf(_det,
sizeof(_det),
"ST=%04X EQ-bit should be clear",st);
548 check(
"CZC not EQ [ASM]", (st&0x2000)==0, _det); }
549 setup(NULL); load_prog(p,n); run_c(); { uint16_t st=r16(REG(2));
550 snprintf(_det,
sizeof(_det),
"ST=%04X EQ-bit should be clear",st);
551 check(
"CZC not EQ [C]", (st&0x2000)==0, _det); }
556 printf(
" SZCB R0,R1\n");
557 n=0; li(p,&n,0,0x0F00); li(p,&n,1,0xFF55); szcb_rr(p,&n,0,1); emit(p,&n,IDLE);
558 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"SZCB", 1, 0xF055);
559 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"SZCB", 1, 0xF055);
561 printf(
" SOCB R0,R1\n");
562 n=0; li(p,&n,0,0x0F00); li(p,&n,1,0xF055); socb_rr(p,&n,0,1); emit(p,&n,IDLE);
563 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"SOCB", 1, 0xFF55);
564 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"SOCB", 1, 0xFF55);
567 printf(
" CB R0,R1 (equal)\n");
568 n=0; li(p,&n,0,0xAA00); li(p,&n,1,0xAAFF); cb_rr(p,&n,0,1); stst(p,&n,2); emit(p,&n,IDLE);
569 setup(NULL); load_prog(p,n); run_asm(); { uint16_t st=r16(REG(2));
570 snprintf(_det,
sizeof(_det),
"ST=%04X EQ-bit missing",st);
571 check(
"CB EQ [ASM]", (st&0x2000)!=0, _det); }
572 setup(NULL); load_prog(p,n); run_c(); { uint16_t st=r16(REG(2));
573 snprintf(_det,
sizeof(_det),
"ST=%04X EQ-bit missing",st);
574 check(
"CB EQ [C]", (st&0x2000)!=0, _det); }
577static void test_shifts(
void)
579 printf(
"\n=== Shifts ===\n");
580 uint8_t p[MAX_PROG]; uint16_t n;
583 printf(
" SRA R0,4\n");
584 n=0; li(p,&n,0,0x8000); sra(p,&n,0,4); emit(p,&n,IDLE);
585 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"SRA 4", 0, 0xF800);
586 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"SRA 4", 0, 0xF800);
589 printf(
" SRL R0,4\n");
590 n=0; li(p,&n,0,0x8000); srl(p,&n,0,4); emit(p,&n,IDLE);
591 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"SRL 4", 0, 0x0800);
592 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"SRL 4", 0, 0x0800);
595 printf(
" SLA R0,4\n");
596 n=0; li(p,&n,0,0x0001); sla(p,&n,0,4); emit(p,&n,IDLE);
597 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"SLA 4", 0, 0x0010);
598 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"SLA 4", 0, 0x0010);
601 printf(
" SRC R0,4\n");
602 n=0; li(p,&n,0,0x1234); src_op(p,&n,0,4); emit(p,&n,IDLE);
603 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"SRC 4", 0, 0x4123);
604 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"SRC 4", 0, 0x4123);
607 printf(
" SRA R1,R0 (count from R0)\n");
608 n=0; li(p,&n,0,4); li(p,&n,1,0x8000); sra(p,&n,1,0); emit(p,&n,IDLE);
609 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"SRA R0-count", 1, 0xF800);
610 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"SRA R0-count", 1, 0xF800);
613 printf(
" SLA overflow (0x4000<<1)\n");
614 n=0; li(p,&n,0,0x4000); sla(p,&n,0,1); stst(p,&n,1); emit(p,&n,IDLE);
615 setup(NULL); load_prog(p,n); run_asm(); { uint16_t st=r16(REG(1));
616 snprintf(_det,
sizeof(_det),
"ST=%04X OV-bit missing",st);
617 check(
"SLA OV [ASM]", (st&0x0800)!=0, _det); }
618 setup(NULL); load_prog(p,n); run_c(); { uint16_t st=r16(REG(1));
619 snprintf(_det,
sizeof(_det),
"ST=%04X OV-bit missing",st);
620 check(
"SLA OV [C]", (st&0x0800)!=0, _det); }
623static void test_branches(
void)
625 printf(
"\n=== Branches ===\n");
626 uint8_t p[MAX_PROG]; uint16_t n;
629 printf(
" CI/JEQ taken\n");
631 li(p,&n,0,5); ci(p,&n,0,5);
635 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"JEQ taken", 0, 5);
636 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"JEQ taken", 0, 5);
639 printf(
" CI/JEQ not taken\n");
641 li(p,&n,0,5); ci(p,&n,0,6);
645 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"JEQ not taken", 0, 0x1111);
646 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"JEQ not taken", 0, 0x1111);
649 printf(
" JNE loop (3 iters)\n");
655 jne(p,&n,(int8_t)(-4));
657 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"JNE loop R0", 0, 0);
658 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"JNE loop R0", 0, 0);
664 uint16_t sub_off = 0;
667 uint16_t bl_off = n; bl_abs(p,&n,0);
673 uint16_t sub_addr = PROG + sub_off;
674 p[bl_off+2] = (uint8_t)(sub_addr>>8);
675 p[bl_off+3] = (uint8_t)(sub_addr&0xFF);
676 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"BL/RT R0", 0, 0xBEEF);
677 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"BL/RT R0", 0, 0xBEEF);
683 uint16_t li5_off = n;
688 uint16_t bind_target = (uint16_t)(PROG + n);
691 p[li5_off+2] = (uint8_t)(bind_target >> 8);
692 p[li5_off+3] = (uint8_t)(bind_target & 0xFF);
693 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"B *R5", 0, 0xB00B);
694 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"B *R5", 0, 0xB00B);
697 printf(
" B @addr\n");
699 uint16_t babs_off = n;
703 uint16_t babs_target = (uint16_t)(PROG + n);
706 p[babs_off+2] = (uint8_t)(babs_target >> 8);
707 p[babs_off+3] = (uint8_t)(babs_target & 0xFF);
708 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"B @addr", 0, 0xCAFE);
709 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"B @addr", 0, 0xCAFE);
716static void test_jumps(
void)
718 printf(
"\n=== Jump conditions ===\n");
719 uint8_t p[MAX_PROG]; uint16_t n;
724#define CHECK_JUMP(lbl, taken) do { \
725 li(p,&n,1,0xDEAD); emit(p,&n,IDLE); \
726 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(lbl, 1, (taken) ? 0 : 0xDEAD); \
727 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(lbl, 1, (taken) ? 0 : 0xDEAD); \
731 n=0; jmp(p,&n,2); CHECK_JUMP(
"JMP", 1);
735 printf(
" JLT / JGT (signed)\n");
736 n=0; li(p,&n,0,0xFFFF); ci(p,&n,0,1); jlt(p,&n,2); CHECK_JUMP(
"JLT taken", 1);
737 n=0; li(p,&n,0,5); ci(p,&n,0,3); jlt(p,&n,2); CHECK_JUMP(
"JLT not taken", 0);
738 n=0; li(p,&n,0,5); ci(p,&n,0,3); jgt(p,&n,2); CHECK_JUMP(
"JGT taken", 1);
739 n=0; li(p,&n,0,0xFFFF); ci(p,&n,0,1); jgt(p,&n,2); CHECK_JUMP(
"JGT not taken", 0);
741 printf(
" JL / JH (unsigned)\n");
742 n=0; li(p,&n,0,1); ci(p,&n,0,5); jl(p,&n,2); CHECK_JUMP(
"JL taken", 1);
743 n=0; li(p,&n,0,5); ci(p,&n,0,1); jl(p,&n,2); CHECK_JUMP(
"JL not taken", 0);
744 n=0; li(p,&n,0,5); ci(p,&n,0,1); jh(p,&n,2); CHECK_JUMP(
"JH taken", 1);
745 n=0; li(p,&n,0,5); ci(p,&n,0,5); jh(p,&n,2); CHECK_JUMP(
"JH not taken", 0);
748 printf(
" JLE / JHE\n");
749 n=0; li(p,&n,0,1); ci(p,&n,0,5); jle(p,&n,2); CHECK_JUMP(
"JLE on less", 1);
750 n=0; li(p,&n,0,5); ci(p,&n,0,5); jle(p,&n,2); CHECK_JUMP(
"JLE on equal", 1);
751 n=0; li(p,&n,0,5); ci(p,&n,0,1); jle(p,&n,2); CHECK_JUMP(
"JLE not taken", 0);
752 n=0; li(p,&n,0,5); ci(p,&n,0,1); jhe(p,&n,2); CHECK_JUMP(
"JHE on greater", 1);
753 n=0; li(p,&n,0,5); ci(p,&n,0,5); jhe(p,&n,2); CHECK_JUMP(
"JHE on equal", 1);
754 n=0; li(p,&n,0,1); ci(p,&n,0,5); jhe(p,&n,2); CHECK_JUMP(
"JHE not taken", 0);
756 printf(
" JOC / JNC\n");
757 n=0; li(p,&n,0,0xFFFF); ai(p,&n,0,1); joc(p,&n,2); CHECK_JUMP(
"JOC taken", 1);
758 n=0; li(p,&n,0,0); ai(p,&n,0,1); joc(p,&n,2); CHECK_JUMP(
"JOC not taken", 0);
759 n=0; li(p,&n,0,0); ai(p,&n,0,1); jnc(p,&n,2); CHECK_JUMP(
"JNC taken", 1);
760 n=0; li(p,&n,0,0xFFFF); ai(p,&n,0,1); jnc(p,&n,2); CHECK_JUMP(
"JNC not taken", 0);
764 n=0; li(p,&n,0,1); ai(p,&n,0,1); jno(p,&n,2); CHECK_JUMP(
"JNO taken", 1);
765 n=0; li(p,&n,0,0x7FFF); ai(p,&n,0,1); jno(p,&n,2); CHECK_JUMP(
"JNO not taken", 0);
769 n=0; li(p,&n,2,0x0100); li(p,&n,3,0); cb_rr(p,&n,2,3); jop(p,&n,2);
770 CHECK_JUMP(
"JOP taken", 1);
771 n=0; li(p,&n,2,0x0300); li(p,&n,3,0); cb_rr(p,&n,2,3); jop(p,&n,2);
772 CHECK_JUMP(
"JOP not taken", 0);
777static void test_misc(
void)
779 printf(
"\n=== Misc ===\n");
780 uint8_t p[MAX_PROG]; uint16_t n;
783 printf(
" SWPB R0\n");
784 n=0; li(p,&n,0,0x1234); swpb(p,&n,0); emit(p,&n,IDLE);
785 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"SWPB", 0, 0x3412);
786 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"SWPB", 0, 0x3412);
789 printf(
" STST R0 (after EQ)\n");
790 n=0; li(p,&n,0,5); ci(p,&n,0,5); stst(p,&n,1); emit(p,&n,IDLE);
791 setup(NULL); load_prog(p,n); run_asm(); { uint16_t st=r16(REG(1));
792 snprintf(_det,
sizeof(_det),
"ST=%04X EQ-bit missing",st);
793 check(
"STST EQ [ASM]", (st&0x2000)!=0, _det); }
794 setup(NULL); load_prog(p,n); run_c(); { uint16_t st=r16(REG(1));
795 snprintf(_det,
sizeof(_det),
"ST=%04X EQ-bit missing",st);
796 check(
"STST EQ [C]", (st&0x2000)!=0, _det); }
799 printf(
" STWP R0\n");
800 n=0; stwp(p,&n,0); emit(p,&n,IDLE);
801 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"STWP", 0, WP);
802 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"STWP", 0, WP);
807 printf(
" X R5 (executing INC R0)\n");
808 n=0; li(p,&n,5,0x0580); li(p,&n,0,5); x_reg(p,&n,5); emit(p,&n,IDLE);
809 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"X INC R0", 0, 6);
810 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"X INC R0", 0, 6);
814 printf(
" LWPI (register file moves)\n");
815 n=0; lwpi(p,&n,SCRATCH); li(p,&n,0,0x1234); stwp(p,&n,1); emit(p,&n,IDLE);
816 setup(NULL); load_prog(p,n); run_asm();
817 CHECK_MEM16(
"LWPI new R0", SCRATCH, 0x1234); CHECK_MEM16(
"LWPI WP", SCRATCH+2, SCRATCH);
818 setup(NULL); load_prog(p,n); run_c();
819 CHECK_MEM16(
"LWPI new R0", SCRATCH, 0x1234); CHECK_MEM16(
"LWPI WP", SCRATCH+2, SCRATCH);
824 printf(
" LIMI (immediate consumed)\n");
825 n=0; limi(p,&n,2); li(p,&n,0,7); emit(p,&n,IDLE);
826 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"LIMI then LI", 0, 7);
827 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"LIMI then LI", 0, 7);
834static void test_pix(
void)
836 printf(
"\n=== F18A PIX (BL) ===\n");
837 uint8_t p[MAX_PROG]; uint16_t n;
840 printf(
" PIX address, VR35=10\n");
841 n=0; li(p,&n,1,0x0503); li(p,&n,2,0x4000); pix(p,&n,1,2); emit(p,&n,IDLE);
842 setup(NULL); load_prog(p,n); mem[0x6020]=0; mem[0x6023]=10;
843 run_asm(); CHECK_REG(
"PIX addr", 2, 0x000A);
844 setup(NULL); load_prog(p,n); mem[0x6020]=0; mem[0x6023]=10;
845 run_c(); CHECK_REG(
"PIX addr", 2, 0x000A);
848 printf(
" PIX address wraps at 16KB\n");
849 n=0; li(p,&n,1,0x0064); li(p,&n,2,0x4000); pix(p,&n,1,2); emit(p,&n,IDLE);
850 setup(NULL); load_prog(p,n); mem[0x6020]=0xFF; mem[0x6023]=4;
851 run_asm(); CHECK_REG(
"PIX wrap", 2, 0x0024);
852 setup(NULL); load_prog(p,n); mem[0x6020]=0xFF; mem[0x6023]=4;
853 run_c(); CHECK_REG(
"PIX wrap", 2, 0x0024);
856 printf(
" PIX write, colour 3 at x=5\n");
857 n=0; li(p,&n,1,0x0503); li(p,&n,2,0x0003); pix(p,&n,1,2); emit(p,&n,IDLE);
858 setup(NULL); load_prog(p,n); mem[0x6020]=0; mem[0x6023]=10;
859 run_asm(); CHECK_MEM8(
"PIX write", 0x000A, 0x30);
860 setup(NULL); load_prog(p,n); mem[0x6020]=0; mem[0x6023]=10;
861 run_c(); CHECK_MEM8(
"PIX write", 0x000A, 0x30);
864static void test_blwp(
void)
866 printf(
"\n=== BLWP/RTWP ===\n");
867 uint8_t p[MAX_PROG*4]; uint16_t n;
879 uint16_t vec_off = 0x10;
880 uint16_t new_wp_off = 0x20;
881 uint16_t sub_off = 0x40;
883 uint16_t vec_addr = PROG + vec_off;
884 uint16_t new_wp_addr = PROG + new_wp_off;
885 uint16_t sub_addr = PROG + sub_off;
887 memset(p, 0,
sizeof(p));
889 blwp(p, &n, vec_addr);
890 li(p, &n, 0, 0x1111);
894 p[vec_off] = (uint8_t)(new_wp_addr >> 8);
895 p[vec_off+1] = (uint8_t)(new_wp_addr & 0xFF);
896 p[vec_off+2] = (uint8_t)(sub_addr >> 8);
897 p[vec_off+3] = (uint8_t)(sub_addr & 0xFF);
901 li(p, &n, 3, 0xD0AE);
904 uint16_t prog_len = n;
905 printf(
" BLWP/RTWP\n");
907 setup(NULL); load_prog(p, prog_len);
909 CHECK_REG(
"BLWP/RTWP R0 after return [ASM]", 0, 0x1111);
911 setup(NULL); load_prog(p, prog_len);
913 CHECK_REG(
"BLWP/RTWP R0 after return [C]", 0, 0x1111);
923static void test_decode_flat(
void)
925 printf(
"\n=== PICO9918 flat memory ===\n");
926 uint8_t p[MAX_PROG]; uint16_t n;
928 printf(
" above the F18A's GRAM window is memory\n");
929 n=0; li(p,&n,1,0x4800); li(p,&n,2,0xBEEF); mov_ri(p,&n,2,1); emit(p,&n,IDLE);
930 setup(NULL); load_prog(p,n); run_asm(); CHECK_MEM16(
">4800 [ASM]", 0x4800, 0xBEEF);
931 setup(NULL); load_prog(p,n); run_c(); CHECK_MEM16(
">4800 [C]", 0x4800, 0xBEEF);
933 printf(
" the palette window does not mirror\n");
934 n=0; li(p,&n,1,0x5F82); li(p,&n,2,0x1234); mov_ri(p,&n,2,1); emit(p,&n,IDLE);
935 setup(NULL); load_prog(p,n); run_asm(); CHECK_MEM16(
">5F82 [ASM]", 0x5F82, 0x1234);
936 setup(NULL); load_prog(p,n); run_c(); CHECK_MEM16(
">5F82 [C]", 0x5F82, 0x1234);
938 printf(
" the scanline byte is writable, and >C000 up is there at all\n");
939 n=0; li(p,&n,1,0x7000); li(p,&n,2,0x0102); mov_ri(p,&n,2,1);
940 li(p,&n,3,0xD000); li(p,&n,4,0x0304); mov_ri(p,&n,4,3); mov_ar(p,&n,0xC010,5);
942 setup(NULL); load_prog(p,n); mem[0xC010]=0x77; mem[0xC011]=0x88;
943 run_asm(); CHECK_MEM16(
">7000 [ASM]", 0x7000, 0x0102);
944 CHECK_MEM16(
">D000 [ASM]", 0xD000, 0x0304); CHECK_REG(
">C010 [ASM]", 5, 0x7788);
945 setup(NULL); load_prog(p,n); mem[0xC010]=0x77; mem[0xC011]=0x88;
946 run_c(); CHECK_MEM16(
">7000 [C]", 0x7000, 0x0102);
947 CHECK_MEM16(
">D000 [C]", 0xD000, 0x0304); CHECK_REG(
">C010 [C]", 5, 0x7788);
950static void test_decode(
void)
952 printf(
"\n=== F18A address decode (C core) ===\n");
953 uint8_t p[MAX_PROG]; uint16_t n;
956 printf(
" GRAM is 2KB, mirrored\n");
957 n=0; li(p,&n,1,0x4800); li(p,&n,2,0xBEEF); mov_ri(p,&n,2,1); emit(p,&n,IDLE);
958 setup(NULL); load_prog(p,n); run_c(); CHECK_MEM16(
"GRAM >4800", 0x4000, 0xBEEF);
960 printf(
" palette is 128 bytes, mirrored\n");
961 n=0; li(p,&n,1,0x5F82); li(p,&n,2,0x1234); mov_ri(p,&n,2,1); emit(p,&n,IDLE);
962 setup(NULL); load_prog(p,n); run_c(); CHECK_MEM16(
"palette >5F82", 0x5002, 0x1234);
964 printf(
" registers are 64, mirrored\n");
965 n=0; li(p,&n,1,0x6F44); li(p,&n,2,0xAA55); mov_ri(p,&n,2,1); emit(p,&n,IDLE);
966 setup(NULL); load_prog(p,n); run_c(); CHECK_MEM16(
"register >6F44", 0x6004, 0xAA55);
968 printf(
" DMA ports are 16, mirrored\n");
969 n=0; li(p,&n,1,0x8F14); li(p,&n,2,0x0102); mov_ri(p,&n,2,1); emit(p,&n,IDLE);
970 setup(NULL); load_prog(p,n); run_c(); CHECK_MEM16(
"DMA >8F14", 0x8004, 0x0102);
972 printf(
" scanline and blanking are read-only\n");
973 n=0; li(p,&n,1,0x7000); clr(p,&n,2); mov_ri(p,&n,2,1); mov_ir(p,&n,1,3); emit(p,&n,IDLE);
974 setup(NULL); load_prog(p,n); mem[0x7000]=0x5A; mem[0x7001]=0xA5;
975 run_c(); CHECK_MEM16(
"scanline write dropped", 0x7000, 0x5AA5);
976 CHECK_REG(
"scanline read", 3, 0x5AA5);
978 printf(
" version reads the byte the host reads from SR14\n");
979 n=0; mov_ar(p,&n,0xA246,2); emit(p,&n,IDLE);
980 setup(NULL); load_prog(p,n); mem[0xB00E]=0x1A; run_c(); CHECK_REG(
"version >A246", 2, 0x1A1A);
982 printf(
" GPU status is the low seven bits of SR2\n");
983 n=0; li(p,&n,1,0xB000); li(p,&n,2,0x2A3F); mov_ri(p,&n,2,1); emit(p,&n,IDLE);
984 setup(NULL); load_prog(p,n); mem[0xB002]=0x80; run_c();
985 CHECK_MEM8(
"status >B000 -> SR2", 0xB002, 0xBF);
986 CHECK_MEM8(
"status left SR0 alone", 0xB000, 0x00);
988 printf(
" nothing is there above >BFFF\n");
989 n=0; mov_ar(p,&n,0xC010,2); li(p,&n,1,0xD000); li(p,&n,3,0xFFFF); mov_ri(p,&n,3,1);
991 setup(NULL); load_prog(p,n); mem[0xC010]=0x77; mem[0xC011]=0x88;
992 run_c(); CHECK_REG(
"read >C010", 2, 0x0000);
993 CHECK_MEM16(
"write >D000 dropped", 0xD000, 0x0000);
998static void test_stress(
void)
1000 printf(
"\n=== Stress: Fibonacci(10)=55 ===\n");
1001 uint8_t p[MAX_PROG]; uint16_t n;
1009 printf(
" Fibonacci(10)\n");
1011 li(p,&n,0,10); li(p,&n,1,0); li(p,&n,2,1);
1019 jne(p,&n,(int8_t)(-8));
1022 setup(NULL); load_prog(p,n); run_asm(); CHECK_REG(
"Fib(10) [ASM]", 1, 55);
1023 setup(NULL); load_prog(p,n); run_c(); CHECK_REG(
"Fib(10) [C]", 1, 55);
1034#if defined(LIB_PICO_STDIO_USB)
1035 for (
int i = 0; i < 100 && !stdio_usb_connected(); i++)
1043 printf(
"=========================================\n");
1044 printf(
" TMS9900 Unit Tests \n");
1046 printf(
" ASM core (%-4s) vs C core \n", TMS9900_ASM_CORE);
1048 printf(
" portable C core, both passes \n");
1050 printf(
"=========================================\n");
1052 test_data_transfer();
1065 printf(
"\n=========================================\n");
1067 printf(
" Results: %d/%d passed (%d failed)\n", passed, total, failed);
1069 printf(
" Results: %d/%d passed (%d failed)\n", indepPassed, indepTotal, indepFailed);
1070 printf(
" One core, so the %d checks run repeat every case that has an assembly half\n", total);
1072 printf(
"=========================================\n");
1074 printf(
" ALL TESTS PASSED\n");
1076 printf(
" FAILURES DETECTED\n");
1077 printf(
"=========================================\n");
1081 const uint LED = 25;
1083 gpio_set_dir(LED, GPIO_OUT);
1085 gpio_put(LED, failed == 0 ? 1 : 0);
1091 return failed == 0 ? 0 : 1;
pico9918-core - TMS9900 CPU interpreter (portable C)