7 static u16 hw_stack
[STACK_LEN
];
8 static struct opcode_word mem_prog
[MEM_PROG_LEN
];
11 #define IXS_NAME_MAX 4
12 static const char ixs_to_name
[4][IXS_NAME_MAX
] = {
13 "i0", "i1", "i2", "i3",
16 #define REG_NAME_MAX 6
17 static const char regs_to_name
[16][REG_NAME_MAX
] = {
18 "i0l", "i0h", "i1l", "i1h",
19 "i2l", "i2h", "i3l", "i3h",
20 "ipl", "iph", "stat", "r3",
21 "r2", "r1", "r0", "a",
24 const char * get_ixs_name(enum alu_ixs ixs
)
26 return ixs_to_name
[ixs
];
29 const char * get_regs_name(enum alu_regs regs
)
31 return regs_to_name
[regs
];
36 for (unsigned idx
=STACK_LEN
-1;idx
>0;idx
--) {
37 hw_stack
[idx
] = hw_stack
[idx
-1];
47 for (unsigned idx
=0;idx
<STACK_LEN
-1;idx
++) {
48 hw_stack
[idx
] = hw_stack
[idx
+1];
55 static u16
do_alu_testb(u8 op
, u8 val
)
58 struct cpuflags flags
= read_flags(0);
60 #ifdef QUIRK_TESTB_IS_AND
65 acc
= op
& (1 << (val
& 7));
68 flags
.z
= (acc
== 0)?1:0;
70 write_flags(flags
, 1);
71 write_reg8(MAIN_REG_A
, acc
, 1);
77 static u16
do_move_mem(u16 dest
, u8 src
)
79 log_instr_name("move");
81 write_mem(dest
, src
, 1);
86 #define OP5_NAME_MAX 12
87 static const char op5_to_name
[32][OP5_NAME_MAX
] = {
89 "cmpa", "cmp", "and", "subs", "subd", "subdc", "mula", "subsc",
91 "xor", "unknown_09", "move", "or", "add", "addc", "mul", "unknown_0f",
93 "shra", "inc", "cmvd", "cmvs", "shrc", "incc", "shr", "unknown_17",
95 "cpl1", "cpl2", "shl", "dec", "cpl2c", "unknown_1d","shlc", "decc"
99 //indexed alu with immediate
101 static u16
do_alu_op5(
102 enum alu_op5 alu
, enum alu_regs dest
, u8 op1
, enum alu_regs op2_enum
)
108 struct cpuflags flags
= read_flags(0);
109 //TODO log only where required (move into cases)
111 log_instr_name("%s", op5_to_name
[alu
]);
116 op2
= read_reg8(op2_enum
, 1);
117 acc
= (u8
)((s8
)(op1
) - (s8
)(op2
));
119 flags
.c
= (((s8
)(op2
)) > ((s8
)(op1
)))?0:1;
120 flags
.z
= (acc
== 0)?1:0;
121 flags
.v
= flags
.c
&& (!flags
.z
);
123 write_flags(flags
, 1);
124 write_reg8(MAIN_REG_A
, acc
, 1);
127 op2
= read_reg8(op2_enum
, 1);
131 flags
.c
= (op2
> op1
)?0:1;
132 flags
.z
= (acc
== 0)?1:0;
133 flags
.v
= flags
.c
&& (!flags
.z
);
135 write_flags(flags
, 1);
136 write_reg8(MAIN_REG_A
, acc
, 1);
139 op2
= read_reg8(op2_enum
, 1);
143 flags
.z
= (acc
== 0)?1:0;
145 write_flags(flags
, 1);
146 write_reg8(MAIN_REG_A
, acc
, 1);
147 //TODO global function?
148 if (dest
!= MAIN_REG_A
)
149 write_reg8(dest
, acc
, 1);
152 op2
= read_reg8(op2_enum
, 1);
154 acc
= (u8
)((s16
)op2
- (s16
)op1
);
156 //TODO maybe better eval?
157 if ((((s16
)((s8
)(op2
)) - (s16
)((s8
)(op1
))) < -0x80) ||
158 (((s16
)((s8
)(op2
)) - (s16
)((s8
)(op1
))) > 0x7f)) {
163 flags
.c
= (op1
> op2
)?0:1;
164 flags
.z
= (acc
== 0)?1:0;
166 write_flags(flags
, 1);
167 write_reg8(MAIN_REG_A
, acc
, 1);
168 if (dest
!= MAIN_REG_A
)
169 write_reg8(dest
, acc
, 1);
172 op2
= read_reg8(op2_enum
, 1);
174 acc
= (u8
)((s16
)op1
- (s16
)op2
);
176 //TODO maybe better eval?
177 if ((((s16
)((s8
)(op1
)) - (s16
)((s8
)(op2
))) < -0x80) ||
178 (((s16
)((s8
)(op1
)) - (s16
)((s8
)(op2
))) > 0x7f)) {
183 flags
.c
= (op2
> op1
)?0:1;
184 flags
.z
= (acc
== 0)?1:0;
186 write_flags(flags
, 1);
187 write_reg8(MAIN_REG_A
, acc
, 1);
188 if (dest
!= MAIN_REG_A
)
189 write_reg8(dest
, acc
, 1);
192 op2
= read_reg8(op2_enum
, 1);
194 //TODO maybe better flag evaluation?
195 acc
= (s16
)op1
- (s16
)op2
- (flags
.c
?0:1);
197 if ((((s16
)((s8
)(op1
)) - (s16
)((s8
)(op2
))) < -0x80) ||
198 (((s16
)((s8
)(op1
)) - (s16
)((s8
)(op2
))) > 0x7f)) {
204 flags
.c
= (op2
> op1
)?0:1;
205 flags
.z
= (acc
== 0)?1:0;
207 write_flags(flags
, 1);
208 write_reg8(MAIN_REG_A
, acc
, 1);
209 if (dest
!= MAIN_REG_A
)
210 write_reg8(dest
, acc
, 1);
213 op2
= read_reg8(op2_enum
, 1);
215 s16temp
= ((s16
)op1
) * ((s16
)op2
);
216 acc
= s16temp
& 0xff;
218 write_reg8(MAIN_REG_A
, acc
, 1);
219 write_reg8(dest
, s16temp
>> 8, 1);
222 op2
= read_reg8(op2_enum
, 1);
224 acc
= (s16
)op2
- (s16
)op1
- (flags
.c
?0:1);
226 //TODO maybe better eval?
227 if ((((s16
)((s8
)(op2
)) - (s16
)((s8
)(op1
))) < -0x80) ||
228 (((s16
)((s8
)(op2
)) - (s16
)((s8
)(op1
))) > 0x7f)) {
233 flags
.c
= (op1
> op2
)?0:1;
234 flags
.z
= (acc
== 0)?1:0;
236 write_flags(flags
, 1);
237 write_reg8(MAIN_REG_A
, acc
, 1);
238 if (dest
!= MAIN_REG_A
)
239 write_reg8(dest
, acc
, 1);
242 op2
= read_reg8(op2_enum
, 1);
246 flags
.z
= (acc
== 0)?1:0;
248 write_flags(flags
, 1);
249 write_reg8(MAIN_REG_A
, acc
, 1);
250 if (dest
!= MAIN_REG_A
)
251 write_reg8(dest
, acc
, 1);
256 flags
.z
= (acc
== 0)?1:0;
258 write_flags(flags
, 1);
259 write_reg8(MAIN_REG_A
, acc
, 1);
260 if (dest
!= MAIN_REG_A
)
261 write_reg8(dest
, acc
, 1);
264 op2
= read_reg8(op2_enum
, 1);
268 flags
.z
= (acc
== 0)?1:0;
270 write_flags(flags
, 1);
271 write_reg8(MAIN_REG_A
, acc
, 1);
272 if (dest
!= MAIN_REG_A
)
273 write_reg8(dest
, acc
, 1);
276 op2
= read_reg8(op2_enum
, 1);
278 //TODO double reg read, read only once!!
280 acc
= u16temp
& 0xff;
282 // fprintf(stderr, " \n||%02x %02x|| ", op1, op2);
284 if (((s8
)op1
> 0) && ((s8
)op2
> 0)) {
285 flags
.v
= ((s8
)u16temp
< 0)?1:0;
286 // fprintf(stderr, " >>>A %02x %02x<<<\n", u16temp, s16temp);
287 } else if (((s8
)op1
< 0) && ((s8
)op2
< 0)) {
288 flags
.v
= ((s8
)u16temp
> 0)?1:0;
289 // fprintf(stderr, " >>>B %02x %02x<<<\n", u16temp, s16temp);
292 // fprintf(stderr, " >>>C %02x %02x<<<\n", u16temp, s16temp);
294 flags
.c
= (u16temp
> 0xff)?1:0;
295 flags
.z
= (acc
== 0)?1:0;
297 write_flags(flags
, 1);
298 write_reg8(MAIN_REG_A
, acc
, 1);
299 if (dest
!= MAIN_REG_A
)
300 write_reg8(dest
, acc
, 1);
303 op2
= read_reg8(op2_enum
, 1);
306 u16temp
= op1
+ op2
+ (flags
.c
?1:0);
307 acc
= u16temp
& 0xff;
310 if (((s8
)op1
> 0) && ((s8
)op2
> 0)) {
311 flags
.v
= ((s8
)u16temp
< 0)?1:0;
312 // fprintf(stderr, " >>>A %02x %02x<<<\n", u16temp, s16temp);
313 } else if (((s8
)op1
< 0) && ((s8
)op2
< 0)) {
314 flags
.v
= ((s8
)u16temp
> 0)?1:0;
315 // fprintf(stderr, " >>>B %02x %02x<<<\n", u16temp, s16temp);
318 // fprintf(stderr, " >>>C %02x %02x<<<\n", u16temp, s16temp);
320 // flags.v = (u16temp > 0x7f)?1:0;
321 flags
.c
= (u16temp
> 0xff)?1:0;
322 flags
.z
= (acc
== 0)?1:0;
324 write_flags(flags
, 1);
325 write_reg8(MAIN_REG_A
, acc
, 1);
326 if (dest
!= MAIN_REG_A
)
327 write_reg8(dest
, acc
, 1);
330 op2
= read_reg8(op2_enum
, 1);
332 u16temp
= ((s16
)op1
) * ((s16
)op2
);
333 acc
= u16temp
& 0xff;
335 write_reg8(MAIN_REG_A
, acc
, 1);
336 write_reg8(dest
, u16temp
>> 8, 1);
339 acc
= ((op1
>> 1) & 0x7f) | (op1
& 0x80);
341 flags
.c
= (op1
& 1)?1:0;
343 flags
.z
= (acc
== 0)?1:0;
345 write_flags(flags
, 1);
346 write_reg8(MAIN_REG_A
, acc
, 1);
347 if (dest
!= MAIN_REG_A
)
348 write_reg8(dest
, acc
, 1);
353 flags
.v
= (op1
== 0x7f)?1:0;
354 flags
.c
= (acc
== 0)?1:0;
355 flags
.z
= (acc
== 0)?1:0;
357 write_flags(flags
, 1);
358 write_reg8(MAIN_REG_A
, acc
, 1);
359 if (dest
!= MAIN_REG_A
)
360 write_reg8(dest
, acc
, 1);
363 //TODO log if depends on flag state
364 flags
.z
= (op1
== 0)?1:0; //always modified
369 write_reg8(MAIN_REG_A
, acc
, 1);
370 if (dest
!= MAIN_REG_A
)
371 write_reg8(dest
, acc
, 1);
374 write_flags(flags
, 1);
377 flags
.z
= (op1
== 0)?1:0; //always modified
382 write_reg8(MAIN_REG_A
, acc
, 1);
383 if (dest
!= MAIN_REG_A
)
384 write_reg8(dest
, acc
, 1);
387 write_flags(flags
, 1);
390 acc
= ((op1
>> 1) & 0x7f) | (flags
.c
?0x80:0);
392 flags
.c
= (op1
& 1)?1:0;
394 flags
.z
= (acc
== 0)?1:0;
396 write_flags(flags
, 1);
397 write_reg8(MAIN_REG_A
, acc
, 1);
398 if (dest
!= MAIN_REG_A
)
399 write_reg8(dest
, acc
, 1);
403 acc
= (op1
) + (flags
.c
?1:0);
405 flags
.v
= ((op1
== 0x7f)&&(flags
.c
))?1:0;
406 flags
.c
= (acc
== 0)?1:0;
407 flags
.z
= (acc
== 0)?1:0;
409 write_flags(flags
, 1);
410 write_reg8(MAIN_REG_A
, acc
, 1);
411 if (dest
!= MAIN_REG_A
)
412 write_reg8(dest
, acc
, 1);
415 acc
= ((op1
>> 1) & 0x7f);
418 flags
.c
= (op1
& 1)?1:0;
419 flags
.z
= (acc
== 0)?1:0;
421 write_flags(flags
, 1);
422 write_reg8(MAIN_REG_A
, acc
, 1);
423 if (dest
!= MAIN_REG_A
)
424 write_reg8(dest
, acc
, 1);
429 flags
.z
= (acc
== 0)?1:0;
431 write_flags(flags
, 1);
432 write_reg8(MAIN_REG_A
, acc
, 1);
433 if (dest
!= MAIN_REG_A
)
434 write_reg8(dest
, acc
, 1);
439 flags
.v
= (op1
== 0x80)?1:0;
440 flags
.c
= (op1
== 0)?1:0;
441 flags
.z
= (acc
== 0)?1:0;
443 write_flags(flags
, 1);
444 write_reg8(MAIN_REG_A
, acc
, 1);
445 if (dest
!= MAIN_REG_A
)
446 write_reg8(dest
, acc
, 1);
449 acc
= ((op1
<< 1) & 0xfe);
451 flags
.v
= (((op1
>> 7)&1)!=((op1
>> 6)&1))?1:0;
452 flags
.c
= (op1
& 0x80)?1:0;
453 flags
.z
= (acc
== 0)?1:0;
455 write_flags(flags
, 1);
456 write_reg8(MAIN_REG_A
, acc
, 1);
457 if (dest
!= MAIN_REG_A
)
458 write_reg8(dest
, acc
, 1);
463 flags
.v
= (op1
== 0x80)?1:0;
464 flags
.c
= (acc
== 0xff)?0:1;
465 flags
.z
= (acc
== 0)?1:0;
467 write_flags(flags
, 1);
468 write_reg8(MAIN_REG_A
, acc
, 1);
469 if (dest
!= MAIN_REG_A
)
470 write_reg8(dest
, acc
, 1);
473 acc
= (~ op1
) + (flags
.c
?1:0);
475 flags
.v
= ((op1
== 0x80)&&(flags
.c
))?1:0;
476 flags
.c
= ((op1
== 0)&&(flags
.c
))?1:0; //NOTICE causal
477 flags
.z
= (acc
== 0)?1:0;
479 write_flags(flags
, 1);
480 write_reg8(MAIN_REG_A
, acc
, 1);
481 if (dest
!= MAIN_REG_A
)
482 write_reg8(dest
, acc
, 1);
485 acc
= ((op1
<< 1) & 0xfe) | (flags
.c
?1:0);
487 flags
.v
= (((op1
>> 7)&1)!=((op1
>> 6)&1))?1:0;
488 flags
.c
= (op1
& 0x80)?1:0;
489 flags
.z
= (acc
== 0)?1:0;
491 write_flags(flags
, 1);
492 write_reg8(MAIN_REG_A
, acc
, 1);
493 if (dest
!= MAIN_REG_A
)
494 write_reg8(dest
, acc
, 1);
498 acc
= op1
+ (flags
.c
?1:0) - 1;
500 flags
.v
= (acc
== 0x7f)?1:0;
501 flags
.c
= (acc
== 0xff)?0:1;
502 flags
.z
= (acc
== 0)?1:0;
504 write_flags(flags
, 1);
505 write_reg8(MAIN_REG_A
, acc
, 1);
506 if (dest
!= MAIN_REG_A
)
507 write_reg8(dest
, acc
, 1);
510 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
518 #define JMP_NAME_MAX 6
519 static const char jmp_type_name
[8][JMP_NAME_MAX
] = {
520 "jcc", "jvc", "jzc", "jmp",
521 "jcs", "jvs", "jzs", "jevt",
525 static unsigned do_jump(enum jmp_type cc
) {
527 struct reg_stat stat
;
532 log_access_read_add("(> !c) ");
536 log_access_read_add("(>= !o) ");
540 log_access_read_add("(!= !z) ");
546 log_access_read_add("(<= C) ");
550 log_access_read_add("(< O) ");
554 log_access_read_add("(== Z) ");
557 stat
.raw
= read_reg8(MAIN_REG_STAT
, 1);
558 log_access_read_add("(event) ");
559 return (stat
.ev0
|| stat
.ev1
)?1:0;
561 return 0; //default error?
564 /** ******** opcodes *******/
566 static u16
opcode_jump_imm(struct opcode_word opcode
)
568 u16 addr
= (~opcode
.jmp_imm
.n_addr
) & 0xffff;
569 enum jmp_type cc
= opcode
.jmp_imm
.cc
;
571 log_instr_name("%s", jmp_type_name
[cc
]);
572 log_instr_args("0x%04hx", addr
);
576 // fprintf(stderr, "GO");
579 // fprintf(stderr, "SKIP");
584 static u16
opcode_jump_ip(struct opcode_word opcode
)
586 u16 addr
= read_ip(1);
587 enum jmp_type cc
= opcode
.jmp_imm
.cc
; //borrowed?
589 log_instr_name("%s", jmp_type_name
[cc
]);
590 log_instr_args("ip");
594 // log_comment_add("GO");
597 // log_comment_add("SKIP");
602 static u16
opcode_nop(struct opcode_word opcode
)
604 log_instr_name("nop");
608 static u16
opcode_ret(struct opcode_word opcode
)
610 log_instr_name("ret");
614 static u16
opcode_reti(struct opcode_word opcode
)
616 log_instr_name("reti");
618 struct reg_stat stat
;
619 stat
.raw
= read_reg8(MAIN_REG_STAT
, 1);
621 write_reg8(MAIN_REG_STAT
, stat
.raw
, 1);
626 static u16
opcode_pop(struct opcode_word opcode
)
628 log_instr_name("pop");
630 write_ip(do_pop(), 1);
635 static u16
opcode_push(struct opcode_word opcode
)
637 log_instr_name("push");
644 static u16
opcode_call_imm(struct opcode_word opcode
)
646 u16 addr
= ~(opcode
.call_imm
.n_addr
& 0xffff);
648 log_instr_name("call");
649 log_instr_args("0x%04hx", addr
);
651 do_push(read_pc() + 1);
656 static u16
opcode_call_ip(struct opcode_word opcode
)
658 u16 addr
= read_ip(1);
660 log_instr_name("call");
661 log_instr_args("ip");
663 do_push(read_pc() + 1);
668 static u16
opcode_calls_imm(struct opcode_word opcode
)
670 u16 addr
= ~(opcode
.calls_imm
.n_addr
& 0xffff);
672 log_instr_name("calls");
673 log_instr_args("0x%04hx", addr
);
675 write_ip(read_pc() + 1, 1);
679 static u16
opcode_calls_ip(struct opcode_word opcode
)
681 u16 addr
= read_ip(1);
683 log_instr_name("calls");
684 log_instr_args("ip");
686 write_ip(read_pc() + 1, 1);
690 static u16
opcode_pmd(struct opcode_word opcode
)
693 log_instr_name("pmd");
696 log_instr_args("on");
698 log_instr_args("off");
704 static u16
opcode_halt(struct opcode_word opcode
)
706 struct reg_stat stat
;
707 stat
.raw
= read_reg8(MAIN_REG_STAT
, 1);
709 log_instr_name("halt");
711 sim_breakpoint_set(SIM_BREAKPOINT_HALT
);
713 if (stat
.ev0
|| stat
.ev1
) {
718 // write_reg8(MAIN_REG_STAT, stat.raw, 1);
728 static u16
opcode_freq(struct opcode_word opcode
)
730 log_instr_name("freq");
732 switch(opcode
.freq
.div
) {
734 log_instr_args("clk");
737 log_instr_args("clk/2");
740 log_instr_args("clk/4");
743 log_instr_args("clk/8");
746 log_instr_args("clk/16");
749 log_instr_args("invalid div table = %01hhx",
757 static u16
opcode_sflag(struct opcode_word opcode
)
759 struct cpuflags f
= read_flags(1);
761 log_instr_name("sflag");
767 (((f
.c
^ f
.v
)&1) << 6) |
770 //bit 3 = was halt (only 816l?)
774 //rest bit, undefined -> can be "1" -> never
778 write_reg8(MAIN_REG_A
, acc
, 1);
784 //alu1 rx, (ix, 0x12)
785 static u16
opcode_alu1(struct opcode_word opcode
)
787 enum alu_op5 alu
= opcode
.alu1
.alu_op
;
788 enum alu_ixs ixs
= opcode
.alu1
.ix
;
789 enum alu_regs dst
= opcode
.alu1
.dst
;
790 u8 offset
= opcode
.alu1
.offset
;
792 log_instr_args("%s, (%s, 0x%02hhx)",
798 u16 addr
= read_ix(ixs
, 1) + offset
;
808 //alu2 rx, -(ix, 0x12)+
809 static u16
opcode_alu2(struct opcode_word opcode
)
811 enum alu_op5 alu
= opcode
.alu2
.alu_op
;
812 enum alu_ixs ixs
= opcode
.alu2
.ix
;
813 enum alu_regs dst
= opcode
.alu2
.dst
;
814 unsigned sign
= opcode
.alu2
.sign
;
815 u8 cpl2_offset
= opcode
.alu2
.cpl2_offset
;
822 log_instr_args("%s, -(%s, 0x%02hhx)",
823 get_regs_name(dst
), get_ixs_name(ixs
), cpl2_offset
);
825 addr
= read_ix(ixs
, 1) + ((s16
)(cpl2_offset
) | 0xff80);
829 log_instr_args("%s, (%s, 0x%02hhx)+",
830 get_regs_name(dst
), get_ixs_name(ixs
), cpl2_offset
);
832 addr
= read_ix(ixs
, 1);
833 newix
= addr
+ cpl2_offset
;
843 //NOTICE problem with modification causality (opcode i0l, -(i0, 42)) ... everything is: stores new index value after the memory access is done
844 write_ix(ixs
, newix
, 1);
849 #define OP4_NAME_MAX 12
850 static const char op4_to_name
[16][OP4_NAME_MAX
] = {
852 "cmpa", "cmp", "and", "subs", "subd", "subdc", "mula", "subsc",
854 "xor", "unknown_09", "move", "or", "add", "addc", "mul", "tstb",
858 static u16
opcode_alu3(struct opcode_word opcode
)
860 enum alu_op4 alu
= opcode
.alu3
.alu_op
;
861 enum alu_regs dst
= opcode
.alu3
.dst
;
862 u8 val
= (~opcode
.alu3
.n_data
) & 0xff;
864 log_instr_name("%s", op4_to_name
[alu
]);
866 log_instr_args("%s, #0x%02hhx", get_regs_name(dst
), val
);
868 if (alu
== OP4_TESTB
) {
869 return do_alu_testb(read_reg8(dst
, 1), val
);
880 //only register operands
881 static u16
opcode_alu4(struct opcode_word opcode
)
883 enum alu_op5 alu
= opcode
.alu4
.alu_op
;
884 enum alu_regs reg_op2_k
= opcode
.alu4
.op2
;
885 enum alu_regs reg_op1_j
= opcode
.alu4
.op1
;
886 enum alu_regs reg_res_i
= opcode
.alu4
.dst
;
892 log_instr_args("%s, %s",
893 get_regs_name(reg_op1_j
),
894 get_regs_name(reg_op2_k
));
896 if (reg_res_i
!= 0xf) {
897 log_comment_add("bad reg field I/res %s",
898 get_regs_name(reg_res_i
));
911 //alu4 regi, regj, regk
912 log_instr_args("%s, %s, %s",
913 get_regs_name(reg_res_i
),
914 get_regs_name(reg_op1_j
),
915 get_regs_name(reg_op2_k
));
917 case OP5_MOVE
: //probably
933 log_instr_args("%s, %s",
934 get_regs_name(reg_res_i
),
935 get_regs_name(reg_op1_j
));
937 if (reg_op2_k
!= 0xf) {
938 log_comment_add("bad regk array %s",
939 get_regs_name(reg_op2_k
));
943 //alu4 regi, regj, regk
944 log_instr_args("%s, %s, %s",
945 get_regs_name(reg_res_i
),
946 get_regs_name(reg_op1_j
),
947 get_regs_name(reg_op2_k
));
948 log_comment_add("unknown reg use");
955 read_reg8(reg_op1_j
, 1),
960 //alu5 regi, (ix, r3)
961 static u16
opcode_alu5(struct opcode_word opcode
)
963 enum alu_op5 alu
= opcode
.alu5
.alu_op
;
964 enum alu_ixs ixs
= opcode
.alu5
.ix
;
965 enum alu_regs dst
= opcode
.alu5
.dst
;
966 u16 addr
= read_ix(ixs
, 1) + read_reg8(MAIN_REG_R3
, 1);
968 log_instr_args("%s, (%s, r3)",
969 get_regs_name(dst
), get_ixs_name(ixs
));
979 //alu6 regi, direct addr
980 static u16
opcode_alu6(struct opcode_word opcode
)
982 enum alu_op5 alu
= opcode
.alu6
.alu_op
;
983 enum alu_regs dst
= opcode
.alu6
.dst
;
984 u16 addr
= (~opcode
.alu6
.n_addr
) & 0xff;
986 log_instr_args("%s, 0x%02hhx",
987 get_regs_name(dst
), addr
);
997 //move7 (ix, r3), reg
998 static u16
opcode_move7(struct opcode_word opcode
)
1000 enum alu_ixs ixs
= opcode
.move7
.ix
;
1001 enum alu_regs src
= opcode
.move7
.src
;
1002 u16 addr
= read_ix(ixs
, 1) + read_reg8(MAIN_REG_R3
, 1);
1004 log_instr_args("(%s, r3), %s",
1005 get_ixs_name(ixs
), get_regs_name(src
));
1013 static u16
opcode_move8(struct opcode_word opcode
)
1015 enum alu_ixs ixs
= opcode
.move8
.ix
;
1016 enum alu_regs src
= opcode
.move8
.src
;
1017 u8 cpl2_offset
= opcode
.move8
.cpl2_offset
;
1021 if (opcode
.move8
.sign
) {
1022 //pre/signed: move8 -(ix, 0x12), reg
1023 log_instr_args("-(%s, 0x%02hhx), %s",
1024 get_ixs_name(ixs
), cpl2_offset
, get_regs_name(src
));
1026 addr
= read_ix(ixs
, 1) + ((s16
)(cpl2_offset
) | 0xff80);
1030 //post/unsigned: move8 (ix, 0x12)+, reg
1031 log_instr_args("(%s, 0x%02hhx)+, %s",
1032 get_ixs_name(ixs
), cpl2_offset
, get_regs_name(src
));
1034 addr
= read_ix(ixs
, 1);
1036 newix
= addr
+ cpl2_offset
;
1044 //NOTICE problem with modification causality (opcode i0l, -(i0, 42)) ... everything is: stores new index value after the memory access is done
1045 write_ix(ixs
, newix
, 1);
1050 //move9 (ix, 0xff), reg
1051 static u16
opcode_move9(struct opcode_word opcode
)
1053 enum alu_ixs ixs
= opcode
.move9
.ix
;
1054 enum alu_regs src
= opcode
.move9
.src
;
1055 u16 addr
= read_ix(ixs
, 1) + opcode
.move9
.offset
;
1057 log_instr_args("(%s, 0x%02hhx), %s",
1058 get_ixs_name(ixs
), opcode
.move9
.offset
, get_regs_name(src
));
1066 //move10 0xff, reg (direct address)
1067 static u16
opcode_move10(struct opcode_word opcode
)
1069 enum alu_regs src
= opcode
.move10
.src
;
1070 u8 addr
= (~opcode
.move10
.n_addr
) & 0xff;
1072 log_instr_args("0x%02hhx, %s",
1073 addr
, get_regs_name(src
));
1081 //move11 0xff, #0x42
1082 static u16
opcode_move11(struct opcode_word opcode
)
1084 u8 addr
= (~opcode
.move11
.n_addr
) & 0xff;
1085 u8 val
= (~opcode
.move11
.n_data
) & 0xff;
1087 log_instr_args("0x%02hhx, #0x%02hhx",
1097 static u16
opcode_inval(struct opcode_word opcode
)
1099 log_instr_name("!inval %06x", opcode
.raw
);
1100 return read_pc()+1; //??
1105 #define DECODER_ALL_BITS 0x3fffff
1106 static const struct opcode_decoder cr816
[] = {
1107 {DECODER_ALL_BITS
, DECODER_ALL_BITS
, opcode_nop
},
1108 {DECODER_ALL_BITS
, 0x3f3fff, opcode_ret
},
1109 {DECODER_ALL_BITS
, 0x3f1fff, opcode_reti
},
1110 {DECODER_ALL_BITS
, 0x3ebfff, opcode_pop
},
1111 {0x3f0000, 0x3a0000, opcode_calls_imm
},
1112 {0x3f0000, 0x390000, opcode_call_imm
},
1113 {0x380000, 0x300000, opcode_jump_imm
},
1114 {DECODER_ALL_BITS
, 0x2dffff, opcode_push
},
1115 {DECODER_ALL_BITS
, 0x2affff, opcode_calls_ip
},
1116 {DECODER_ALL_BITS
, 0x29ffff, opcode_call_ip
},
1117 {0x38ffff, 0x20ffff, opcode_jump_ip
},
1118 {0x380000, 0x180000, opcode_alu1
},
1119 {0x380000, 0x100000, opcode_alu2
},
1120 {0x3f0000, 0x0e0000, opcode_alu3
},
1121 {0x3e0000, 0x0c0000, opcode_alu4
},
1122 {0x3ffeff, 0x0beeff, opcode_pmd
},
1123 {DECODER_ALL_BITS
, 0x0bdfff, opcode_halt
},
1124 {0x3ffff0, 0x0bbff0, opcode_freq
},
1125 {DECODER_ALL_BITS
, 0x0b7fff, opcode_sflag
},
1126 {0x3e00fc, 0x0600fc, opcode_alu5
},
1127 {0x3e0000, 0x040000, opcode_alu6
},
1128 {0x3fc0ff, 0x0380ff, opcode_move7
},
1129 {0x3fc000, 0x034000, opcode_move8
},
1130 {0x3fc000, 0x02c000, opcode_move9
},
1131 {0x3ff000, 0x01b000, opcode_move10
},
1132 {0x3f0000, 0x000000, opcode_move11
},
1133 {0, 0, opcode_inval
}, //stopper last
1136 u16
opcode_decode(struct opcode_word opcode
)
1139 u16 curr_pc
= 0; //reset if bug?
1142 if ((opcode
.raw
& cr816
[i
].and_mask
) == cr816
[i
].equal
) {
1143 curr_pc
= cr816
[i
].opcode_fcn(opcode
);
1145 // if (cr816[i].and_mask == 0)
1155 struct opcode_word
read_code(u16 addr
)
1157 struct opcode_word ret
;
1159 ret
= mem_prog
[addr
];
1164 void init_isa(char * filename
)
1166 memset(hw_stack
, 0, STACK_LEN
*2);
1168 for (unsigned addr
= 0; addr
< MEM_PROG_LEN
; addr
++) {
1169 mem_prog
[addr
].raw
= 0x3fffff; //NOP
1170 // mem_prog[addr].raw = 0x0bdfff; //halt
1175 struct opcode_word word
;
1177 fp
= fopen(filename
, "r");
1179 perror("code dump opening");
1183 while (fread(&word
.raw
, 3, 1, fp
) == 1) {
1184 mem_prog
[addr
] = word
;
1191 //just validations vvv
1193 //opcodes validation (ADD)
1195 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x0f)&0xff);
1196 mem_prog
[addr
++].raw
= 0x0ecd00 | ((~0xf6)&0xff);
1198 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x43)&0xff);
1199 mem_prog
[addr
++].raw
= 0x0ecd00 | ((~0x42)&0xff);
1201 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0xff)&0xff);
1202 mem_prog
[addr
++].raw
= 0x0ecd00 | ((~0x01)&0xff);
1203 mem_prog
[addr
++].raw
= 0x0bdfff;
1207 //opcodes validation (CMP)
1209 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x50)&0xff);
1210 mem_prog
[addr
++].raw
= 0x0e1d00 | ((~0x62)&0xff);
1212 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x50)&0xff);
1213 mem_prog
[addr
++].raw
= 0x0e1d00 | ((~0x99)&0xff);
1215 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x50)&0xff);
1216 mem_prog
[addr
++].raw
= 0x0e1d00 | ((~0x50)&0xff);
1218 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x50)&0xff);
1219 mem_prog
[addr
++].raw
= 0x0e1d00 | ((~0x47)&0xff);
1221 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0xb6)&0xff);
1222 mem_prog
[addr
++].raw
= 0x0e1d00 | ((~0xb4)&0xff);
1224 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x7e)&0xff);
1225 mem_prog
[addr
++].raw
= 0x0e1d00 | ((~0x80)&0xff);
1227 mem_prog
[addr
++].raw
= 0x0bdfff;
1231 //opcodes validation (CMPA)
1233 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x50)&0xff);
1234 mem_prog
[addr
++].raw
= 0x0e0d00 | ((~0x62)&0xff);
1236 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x50)&0xff);
1237 mem_prog
[addr
++].raw
= 0x0e0d00 | ((~0x50)&0xff);
1239 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x50)&0xff);
1240 mem_prog
[addr
++].raw
= 0x0e0d00 | ((~0x47)&0xff);
1242 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x50)&0xff);
1243 mem_prog
[addr
++].raw
= 0x0e0d00 | ((~0x99)&0xff);
1245 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x90)&0xff);
1246 mem_prog
[addr
++].raw
= 0x0e0d00 | ((~0x82)&0xff);
1248 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x90)&0xff);
1249 mem_prog
[addr
++].raw
= 0x0e0d00 | ((~0x90)&0xff);
1251 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x90)&0xff);
1252 mem_prog
[addr
++].raw
= 0x0e0d00 | ((~0xa7)&0xff);
1254 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x90)&0xff);
1255 mem_prog
[addr
++].raw
= 0x0e0d00 | ((~0x05)&0xff);
1258 mem_prog
[addr
++].raw
= 0x0bdfff;
1262 //opcodes validation
1266 // ============== subsc
1267 mem_prog
[addr
++].raw
= 0x0eae00; //move r0,ff
1268 mem_prog
[addr
++].raw
= 0x0d9fee; //cpl2 r0
1269 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x77)&0xff);
1270 mem_prog
[addr
++].raw
= 0x0e7d00 | ((~0x07)&0xff);
1271 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1273 mem_prog
[addr
++].raw
= 0x0eaeff; //move r0,0
1274 mem_prog
[addr
++].raw
= 0x0d9fee; //cpl2 r0
1275 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x77)&0xff);
1276 mem_prog
[addr
++].raw
= 0x0e7d00 | ((~0x07)&0xff);
1277 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1279 mem_prog
[addr
++].raw
= 0x0eae00; //move r0,ff
1280 mem_prog
[addr
++].raw
= 0x0d9fee; //cpl2 r0
1281 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x07)&0xff);
1282 mem_prog
[addr
++].raw
= 0x0e7d00 | ((~0x77)&0xff);
1283 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1285 mem_prog
[addr
++].raw
= 0x0eaeff; //move r0,0
1286 mem_prog
[addr
++].raw
= 0x0d9fee; //cpl2 r0
1287 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x07)&0xff);
1288 mem_prog
[addr
++].raw
= 0x0e7d00 | ((~0x77)&0xff);
1289 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1291 mem_prog
[addr
++].raw
= 0x0eaeff; //move r0,0
1292 mem_prog
[addr
++].raw
= 0x0d9fee; //cpl2 r0
1293 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0xc6)&0xff);
1294 mem_prog
[addr
++].raw
= 0x0e7d00 | ((~0x5a)&0xff);
1295 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1297 mem_prog
[addr
++].raw
= 0x0eae00; //move r0,ff
1298 mem_prog
[addr
++].raw
= 0x0d9fee; //cpl2 r0
1299 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x6c)&0xff);
1300 mem_prog
[addr
++].raw
= 0x0e7d00 | ((~0xa5)&0xff);
1301 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1303 mem_prog
[addr
++].raw
= 0x0bdfff; //halt
1305 // ============== subdc
1306 mem_prog
[addr
++].raw
= 0x0eae00; //move r0,ff
1307 mem_prog
[addr
++].raw
= 0x0d9fee; //cpl2 r0
1308 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x77)&0xff);
1309 mem_prog
[addr
++].raw
= 0x0e5d00 | ((~0x07)&0xff);
1310 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1312 mem_prog
[addr
++].raw
= 0x0eaeff; //move r0,0
1313 mem_prog
[addr
++].raw
= 0x0d9fee; //cpl2 r0
1314 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x77)&0xff);
1315 mem_prog
[addr
++].raw
= 0x0e5d00 | ((~0x07)&0xff);
1316 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1318 mem_prog
[addr
++].raw
= 0x0eae00; //move r0,ff
1319 mem_prog
[addr
++].raw
= 0x0d9fee; //cpl2 r0
1320 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x07)&0xff);
1321 mem_prog
[addr
++].raw
= 0x0e5d00 | ((~0x77)&0xff);
1322 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1324 mem_prog
[addr
++].raw
= 0x0eaeff; //move r0,0
1325 mem_prog
[addr
++].raw
= 0x0d9fee; //cpl2 r0
1326 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x07)&0xff);
1327 mem_prog
[addr
++].raw
= 0x0e5d00 | ((~0x77)&0xff);
1328 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1330 mem_prog
[addr
++].raw
= 0x0eae00; //move r0,ff
1331 mem_prog
[addr
++].raw
= 0x0d9fee; //cpl2 r0
1332 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0xa5)&0xff);
1333 mem_prog
[addr
++].raw
= 0x0e5d00 | ((~0x6c)&0xff);
1334 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1336 mem_prog
[addr
++].raw
= 0x0eae00; //move r0,ff
1337 mem_prog
[addr
++].raw
= 0x0d9fee; //cpl2 r0
1338 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x5a)&0xff);
1339 mem_prog
[addr
++].raw
= 0x0e5d00 | ((~0xc6)&0xff);
1340 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1342 mem_prog
[addr
++].raw
= 0x0bdfff; //halt
1344 // ============== subs
1345 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x56)&0xff);
1346 mem_prog
[addr
++].raw
= 0x0e3d00 | ((~0x12)&0xff);
1347 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1349 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x56)&0xff);
1350 mem_prog
[addr
++].raw
= 0x0e3d00 | ((~0x90)&0xff);
1351 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1353 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x12)&0xff);
1354 mem_prog
[addr
++].raw
= 0x0e3d00 | ((~0x56)&0xff);
1355 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1357 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x90)&0xff);
1358 mem_prog
[addr
++].raw
= 0x0e3d00 | ((~0x56)&0xff);
1359 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1361 mem_prog
[addr
++].raw
= 0x0bdfff; //halt
1363 // ============== subd
1364 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x56)&0xff);
1365 mem_prog
[addr
++].raw
= 0x0e4d00 | ((~0x12)&0xff);
1366 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1368 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x56)&0xff);
1369 mem_prog
[addr
++].raw
= 0x0e4d00 | ((~0x90)&0xff);
1370 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1372 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x12)&0xff);
1373 mem_prog
[addr
++].raw
= 0x0e4d00 | ((~0x56)&0xff);
1374 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1376 mem_prog
[addr
++].raw
= 0x0ead00 | ((~0x90)&0xff);
1377 mem_prog
[addr
++].raw
= 0x0e4d00 | ((~0x56)&0xff);
1378 mem_prog
[addr
++].raw
= 0x3fffff; //nop
1380 mem_prog
[addr
++].raw
= 0x0bdfff;