merge
[dcpu16] / dcpu16.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include <unistd.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <assert.h>
8 #include <sysexits.h>
9
10 #include "dcpu16.h"
11
12 /*
13 * emulates the DCPU16 system from http://0x10c.com/doc/dcpu-16.txt
14 * currently emulates '1.7' spec from http://pastebin.com/Q4JvQvnM
15 *
16 * I couldn't remember ever implementing an emulator before, so this
17 * happened. As such, consider this a toy in progress.
18 * There are likely many improvable aspects.
19 *
20 * Justin Wind <justin.wind@gmail.com>
21 * 2012 04 05 - implementation started
22 * 2012 05 05 - start of v1.7 revisions
23 * 2012 05 08 - v1.7 revisions mostly complete
24 *
25 * TODO
26 * !! v1.7 bit-shift and signed opcodes need to be reviewed/finished
27 * !! v1.7 hardware interface needs to be finished
28 * !! v1.7 interrupts need to be finished
29 * change api to print into buffers rather than stdio
30 * let callbacks determine whether to override events, or just observe
31 * sort init callbacks by base addr, to call in-order
32 * make all callbacks register addr range of interest
33 */
34
35 static const char * const src_id_ = "$Id$";
36
37 #define OPCODE_BASIC_BITS 5
38 #define OPCODE_OPERAND_B_BITS 5
39 #define OPCODE_OPERAND_A_BITS 6
40
41 const char * const dcpu16_reg_names[] = {
42 "A",
43 "B",
44 "C",
45 "X",
46 "Y",
47 "Z",
48 "I",
49 "J",
50 "PC",
51 "SP",
52 "EX",
53 "IA",
54 NULL
55 };
56
57 #define MSG_(__level__, __vm__, ...) do { ((__vm__) ? ((struct dcpu16 *)(__vm__))->msg_cb_ : dcpu16_msg_)((__level__), __VA_ARGS__); } while (0)
58 #define MSG_INFO(__vm__,...) MSG_(DCPU16_MSG_INFO, __vm__, __VA_ARGS__)
59 #define MSG_ERROR(__vm__,...) MSG_(DCPU16_MSG_ERROR, __vm__, __VA_ARGS__)
60 #ifdef DEBUG
61 #define MSG_DEBUG(__vm__,...) MSG_(DCPU16_MSG_DEBUG, __vm__, __VA_ARGS__)
62 #else /* DEBUG */
63 #define MSG_DEBUG(__vm__,...) do {} while (0)
64 #endif /* DEBUG */
65 #ifdef DEBUG_DECODE
66 #define MSG_DEBUG_DECODE (DCPU16_MSG_DEBUG + 2)
67 #endif /* DEBUG_DECODE
68
69 /* messages could be sent nowhere */
70 static void msg_null_(unsigned int l, char *fmt, ...) { (void)l, (void)fmt; }
71
72 /* messages default to standard streams */
73 static void msg_default_(unsigned int, char *, ...) __attribute__((format(printf, 2, 3)));
74 static inline
75 void msg_default_(unsigned int l, char *fmt, ...) {
76 static const char * const msg_tag_[] = { "info", "error", "debug" };
77 FILE *f = (l <= DCPU16_MSG_INFO) ? stderr : stdout;
78 va_list ap;
79
80 if (l < sizeof msg_tag_ / sizeof *msg_tag_)
81 fprintf(f, "[%s] ", msg_tag_[l]);
82 else
83 fprintf(f, "[%u] ", l);
84
85 va_start(ap, fmt);
86 vfprintf(f, fmt, ap);
87 va_end(ap);
88
89 fprintf(f, "\n");
90
91 fflush(f);
92 }
93
94 /* dcpu16 message callback
95 * This function pointer is copied into newly instantiated dcpu16 structures,
96 * and is invoked directly for messages independant of a dcpu16 context.
97 */
98 dcpu16_msg_cb_t *dcpu16_msg_ = msg_default_;
99
100 /* set a new default message callback */
101 /* returns the previous setting */
102 dcpu16_msg_cb_t *dcpu16_msg_set_default(dcpu16_msg_cb_t *msg_cb) {
103 dcpu16_msg_cb_t *r = dcpu16_msg_;
104 dcpu16_msg_ = msg_cb ? msg_cb : msg_null_;
105 return r;
106 }
107 /* set a new callback */
108 dcpu16_msg_cb_t *dcpu16_msg_set(struct dcpu16 *vm, dcpu16_msg_cb_t *msg_cb) {
109 dcpu16_msg_cb_t *r = vm->msg_cb_;
110 vm->msg_cb_ = msg_cb ? msg_cb : msg_null_;
111 return r;
112 }
113
114 /* acct_event_
115 * invokes callbacks for specified event
116 */
117 static inline
118 void acct_event_(struct dcpu16 *vm, dcpu16_acct_event ev, DCPU16_WORD addr) {
119 struct dcpu16_acct_cb *cb = vm->cb_table_;
120 size_t i;
121
122 for (i = 0; i < vm->cb_table_entries_; i++) {
123 if ( (cb[i].mask & ev) )
124 if (addr >= cb[i].addr_l && addr <= cb[i].addr_h)
125 cb[i].fn(vm, ev, addr, cb[i].data);
126 }
127 }
128
129
130 /* add an entry to the interrupt queue */
131 static
132 int interrupt_enqueue_(struct dcpu16 *vm, DCPU16_WORD message) {
133 vm->interrupts_[vm->interrupts_tail_] = message;
134 vm->interrupts_tail_ += 1;
135 vm->interrupts_tail_ %= DCPU16_INTERRUPT_QUEUE_SIZE;
136
137 if (vm->interrupts_tail_ == vm->interrupts_head_) {
138 vm->on_fire_ = 1;
139 MSG_INFO(vm, "interrupt queue overflow (system is now on fire)");
140 return -1;
141 }
142
143 return 0;
144 }
145
146 static
147 DCPU16_WORD interrupt_dequeue_(struct dcpu16 *vm) {
148 DCPU16_WORD message;
149
150 if (vm->interrupts_tail_ == vm->interrupts_head_) {
151 MSG_INFO(vm, "interrupt underflow");
152 return 0;
153 }
154
155 message = vm->interrupts_[vm->interrupts_head_];
156 vm->interrupts_head_ += 1;
157 vm->interrupts_head_ %= DCPU16_INTERRUPT_QUEUE_SIZE;
158
159 return message;
160 }
161
162 inline
163 void dcpu16_cycle_inc(struct dcpu16 *vm, unsigned int n) {
164 size_t i;
165
166 while (n--) {
167 /* new cycle */
168 vm->cycle_ += 1;
169 MSG_DEBUG(vm, "%s>> starting cycle %llu", __func__, vm->cycle_);
170
171 /* signal interested cycle hooks */
172 acct_event_(vm, DCPU16_ACCT_EV_CYCLE, vm->reg[DCPU16_REG_PC]);
173
174 /* signal attached hardware */
175 for (i = 0; i < vm->hw_table_entries_; i++) {
176 MSG_DEBUG(vm, "%s>> notifying %s", __func__, vm->hw_table_[i].mod->name_);
177 if (vm->hw_table_[i].mod->cycle)
178 vm->hw_table_[i].mod->cycle(vm, &vm->hw_table_[i]);
179 }
180 }
181 }
182
183 /* value_decode_
184 * sets *v to be the address of the represented value
185 * value_is_a is 0 for b, 1 for a, alters behavior of some operands
186 * value_data is 'nextword' for this operand, ignored if unused
187 * workv is buffer to use to accumulate literal value into, before use. one exists for either potential instruction operand
188 * e_addr is set to a referenced address, for accounting callback
189 * pc_adjust is set to how to change the program counter
190 * stack_adjust is set to how to change the stack pointer
191 * cycle_adjust is set to number of cycles spent looking up operand
192 *
193 * zero all adjustables before decoding first operand, and pass in these values when
194 * decoding next operand..
195 *
196 */
197 #define EWHAT_NONE (0)
198 #define EWHAT_REG (1<<1)
199 #define EWHAT_RAM (1<<2)
200 static inline
201 void value_decode_(struct dcpu16 *vm, DCPU16_WORD value, unsigned int value_is_a, DCPU16_WORD value_data,
202 DCPU16_WORD *work_v, DCPU16_WORD **v, DCPU16_WORD *e_addr, enum dcpu16_register_indexes *e_reg, unsigned int *e_what,
203 short *pc_adjust, short *sp_adjust, unsigned int *cycle_adjust) {
204 assert(value <= 0x3f);
205
206 DCPU16_WORD pc = (DCPU16_WORD)(vm->reg[DCPU16_REG_PC] + *pc_adjust),
207 sp = (DCPU16_WORD)(vm->reg[DCPU16_REG_SP] + *sp_adjust);
208
209 (void)pc;
210
211 #ifdef DEBUG_DECODE
212 MSG_(MSG_DEBUG_DECODE, vm ,"%s>> is_a:%u pc:0x%04x sp:0x%04x value_data:0x%04x\n",
213 __func__,
214 value_is_a,
215 pc,
216 sp,
217 value_data);
218 #endif /* DEBUG_DECODE */
219
220 if (value <= 0x07) { /* register */
221 *e_what = EWHAT_REG;
222 *e_reg = value & 0x07;
223 *v = vm->reg + *e_reg;
224
225 #ifdef DEBUG_DECODE
226 MSG_(MSG_DEBUG_DECODE, vm, "%s>> %s (0x%04x)",
227 __func__,
228 dcpu16_reg_names[value],
229 **v);
230 #endif /* DEBUG_DECODE */
231
232 return;
233 }
234
235 if (value <= 0x0f) { /* [register] */
236 *e_what = EWHAT_RAM;
237 *e_addr = vm->reg[value & 0x07];
238 *v = &(vm->ram[ *e_addr ]);
239 acct_event_(vm, DCPU16_ACCT_EV_REG_READ, value & 0x07);
240
241 #ifdef DEBUG_DECODE
242 MSG_(MSG_DEBUG_DECODE, vm, "%s>> [%s] [0x%04x] (0x%04x)",
243 __func__,
244 dcpu16_reg_names[value & 0x07],
245 vm->reg[value & 0x07],
246 **v);
247 #endif /* DEBUG_DECODE */
248
249 return;
250 }
251
252 if (value <= 0x17) { /* [next word + register] */
253 acct_event_(vm, DCPU16_ACCT_EV_REG_WRITE, DCPU16_REG_PC);
254 *pc_adjust += 1; /* consume next word */
255 *cycle_adjust += 1;
256 *e_what = EWHAT_RAM;
257 *e_addr = value_data + vm->reg[value & 0x07];
258 acct_event_(vm, DCPU16_ACCT_EV_REG_READ, value & 0x07);
259 *v = vm->ram + *e_addr;
260
261 #ifdef DEBUG_DECODE
262 MSG_(MSG_DEBUG_DECODE, vm, "%s>> [nextword + %s] [0x%04x + 0x%04x] (0x%04x)",
263 __func__,
264 dcpu16_reg_names[value & 0x07],
265 value_data,
266 vm->reg[value & 0x07],
267 **v);
268 #endif /* DEBUG_DECODE */
269
270 return;
271 }
272
273 switch (value) {
274 case 0x18: /* PUSH/[--SP] or POP/[SP++] */
275 *e_what = EWHAT_RAM;
276 acct_event_(vm, DCPU16_ACCT_EV_REG_READ, DCPU16_REG_SP);
277 acct_event_(vm, DCPU16_ACCT_EV_REG_WRITE, DCPU16_REG_SP);
278 if (value_is_a == 0) { /* b */
279 *v = &(vm->ram[sp - 1]);
280 *sp_adjust -= 1;
281 *e_addr = sp - 1;
282
283 #ifdef DEBUG_DECODE
284 MSG_(MSG_DEBUG_DECODE, vm, "%s>> PUSH [0x%04x] (0x%04x)", __func__, sp - 1, **v);
285 #endif /* DEBUG_DECODE */
286
287 } else { /* a */
288 *v = &(vm->ram[sp]);
289 *sp_adjust += 1;
290 *e_addr = sp;
291
292 #ifdef DEBUG_DECODE
293 MSG_(MSG_DEBUG_DECODE, vm, "%s>> POP [0x%04x] (0x%04x)", __func__, sp, **v);
294 #endif /* DEBUG_DECODE */
295
296 }
297 break;
298
299 case 0x19: /* PEEK/[SP] */
300 acct_event_(vm, DCPU16_ACCT_EV_REG_READ, DCPU16_REG_SP);
301 *e_what = EWHAT_RAM;
302 *v = &(vm->ram[sp]);
303 *e_addr = sp;
304
305 #ifdef DEBUG_DECODE
306 MSG_(MSG_DEBUG_DECODE, vm, "%s>> PEEK [0x%04x] (0x%04x)",
307 __func__,
308 sp,
309 **v);
310 #endif /* DEBUG_DECODE */
311 break;
312
313 case 0x1a: /* PICK n */
314 acct_event_(vm, DCPU16_ACCT_EV_REG_READ, DCPU16_REG_SP);
315 *e_what = EWHAT_RAM;
316 *pc_adjust += 1;
317 *cycle_adjust += 1;
318 *e_addr = sp + value_data;
319 *v = vm->ram + *e_addr;
320
321 #ifdef DEBUG_DECODE
322 MSG_(MSG_DEBUG_DECODE, vm, "%s>> PICK 0x%04x [0x%04x] (0x%04x)",
323 __func__,
324 value_data,
325 sp + value_data,
326 **v);
327 #endif /* DEBUG_DECODE */
328 break;
329
330 case 0x1b: /* SP */
331 *e_reg = DCPU16_REG_SP;
332 *e_what = EWHAT_REG;
333 *v = &(vm->reg[DCPU16_REG_SP]);
334
335 #ifdef DEBUG_DECODE
336 MSG_(MSG_DEBUG_DECODE, vm, "%s>> %s (0x%04x)",
337 __func__,
338 dcpu16_reg_names[DCPU16_REG_SP],
339 **v);
340 #endif /* DEBUG_DECODE */
341 break;
342
343 case 0x1c: /* PC */
344 *e_reg = DCPU16_REG_PC;
345 *e_what = EWHAT_REG;
346 *v = &(vm->reg[DCPU16_REG_PC]);
347
348 #ifdef DEBUG_DECODE
349 MSG_(MSG_DEBUG_DECODE, vm, "%s>> %s (0x%04x)",
350 __func__,
351 dcpu16_reg_names[DCPU16_REG_PC],
352 **v);
353 #endif /* DEBUG_DECODE */
354 break;
355
356 case 0x1d: /* EX */
357 *e_reg = DCPU16_REG_EX;
358 *e_what = EWHAT_REG;
359 *v = &(vm->reg[DCPU16_REG_EX]);
360
361 #ifdef DEBUG_DECODE
362 MSG_(MSG_DEBUG_DECODE, vm, "%s>> %s (0x%04x)",
363 __func__,
364 dcpu16_reg_names[DCPU16_REG_EX],
365 **v);
366 #endif /* DEBUG_DECODE */
367 break;
368
369 case 0x1e: /* [next word] / [[pc++]] */
370 *e_what = EWHAT_RAM;
371 acct_event_(vm, DCPU16_ACCT_EV_REG_WRITE, DCPU16_REG_PC);
372 *pc_adjust += 1;
373 *cycle_adjust += 1;
374 *e_addr = value_data;
375 *v = vm->ram + *e_addr;
376
377 #ifdef DEBUG_DECODE
378 MSG_(MSG_DEBUG_DECODE, vm, "%s>> [nextword] [0x%04x] (0x%04x)",
379 __func__,
380 value_data,
381 **v);
382 #endif /* DEBUG_DECODE */
383 break;
384
385 case 0x1f: /* next word (literal) / [pc++] */
386 *e_what = EWHAT_NONE;
387 acct_event_(vm, DCPU16_ACCT_EV_REG_WRITE, DCPU16_REG_PC);
388 *pc_adjust += 1;
389 *cycle_adjust += 1;
390 *work_v = value_data;
391 *v = work_v;
392
393 #ifdef DEBUG_DECODE
394 MSG_(MSG_DEBUG_DECODE, vm, "%s>> nextword (0x%04x)",
395 __func__,
396 **v);
397 #endif /* DEBUG_DECODE */
398 break;
399
400 default: /* 0x20-0x3f: literal values 0xffff-0x1e */
401 *e_what = EWHAT_NONE;
402 *work_v = (value & 0x1f) - 1;
403 *v = work_v;
404
405 #ifdef DEBUG_DECODE
406 MSG_(MSG_DEBUG_DECODE, vm, "%s>> literal (0x%04x)",
407 __func__,
408 **v);
409 #endif /* DEBUG_DECODE */
410 }
411 }
412
413
414 #define OPCODE_NAME_LEN 16
415 struct opcode_entry {
416 unsigned short value;
417 char name[OPCODE_NAME_LEN];
418 void (*impl)(struct dcpu16 *, DCPU16_WORD, DCPU16_WORD, DCPU16_WORD, DCPU16_WORD);
419 };
420
421 /* messy boilerplate for opcode handlers */
422
423 /* opcode doesn't adjust its own PC, the step function which invoked it handles that */
424 /* opcode does adjust stack and cycle count */
425
426 #define OP_IMPL(x) static void op_##x(struct dcpu16 *vm, DCPU16_WORD val_b, DCPU16_WORD val_b_data, DCPU16_WORD val_a, DCPU16_WORD val_a_data)
427
428 #define OP_TYPE(op_type) DCPU16_WORD *a, *b;\
429 DCPU16_WORD ev_a_addr = 0, ev_b_addr = 0;\
430 enum dcpu16_register_indexes ev_a_reg = DCPU16_REG__NUM, ev_b_reg = DCPU16_REG__NUM;\
431 unsigned int ev_a_what = 0, ev_b_what = 0;\
432 short pc_adjust = 0, sp_adjust = 0;\
433 unsigned int cycle_adjust = 0;\
434 do {\
435 op_type;\
436 value_decode_(vm, val_a, 1, val_a_data,\
437 &vm->reg_work_[1], &a, &ev_a_addr, &ev_a_reg, &ev_a_what,\
438 &pc_adjust, &sp_adjust, &cycle_adjust);\
439 vm->reg[DCPU16_REG_SP] += sp_adjust;\
440 if (cycle_adjust) dcpu16_cycle_inc(vm, cycle_adjust);\
441 } while (0)
442 #define OP_NBI_ (void)val_b, (void)b, (void)ev_b_addr, (void)val_b_data, (void)ev_b_reg, (void)ev_b_what
443 #define OP_BASIC_ value_decode_(vm, val_b, 0, val_b_data,\
444 &vm->reg_work_[0], &b, &ev_b_addr, &ev_b_reg, &ev_b_what,\
445 &pc_adjust, &sp_adjust, &cycle_adjust)
446 #define OP_BASIC(x) OP_TYPE(OP_BASIC_)
447 #define OP_NBI(x) OP_TYPE(OP_NBI_)
448
449 /* after invoking one of these header macros, the instruction and operands will have been decoded, and the control registers have been adjusted to the next instruction et cetera */
450
451 /*
452 accounting helpers, these fire off the related callbacks for memory reads,
453 memory writes, and execution of reserved instructions
454 */
455 #define ACCT_ILL(addr) do { acct_event_(vm, DCPU16_ACCT_EV_NOP, addr); } while (0)
456 #define ACCT_RAM_R(addr) do { acct_event_(vm, DCPU16_ACCT_EV_READ, addr); } while (0)
457 #define ACCT_RAM_W(addr) do { acct_event_(vm, DCPU16_ACCT_EV_WRITE, addr); } while (0)
458 #define ACCT_REG_R(reg) do { acct_event_(vm, DCPU16_ACCT_EV_REG_READ, reg); } while (0)
459 #define ACCT_REG_W(reg) do { acct_event_(vm, DCPU16_ACCT_EV_REG_WRITE, reg); } while (0)
460
461 #define ACCT_R(__x__) do {\
462 if (ev_##__x__##_what & EWHAT_REG) ACCT_REG_R(ev_##__x__##_reg);\
463 if (ev_##__x__##_what & EWHAT_RAM) ACCT_RAM_R(ev_##__x__##_addr);\
464 } while (0)
465 #define ACCT_W(__x__) do {\
466 if (ev_##__x__##_what & EWHAT_REG) ACCT_REG_W(ev_##__x__##_reg);\
467 if (ev_##__x__##_what & EWHAT_RAM) ACCT_RAM_W(ev_##__x__##_addr);\
468 } while (0)
469
470 /* extended opcodes */
471
472 /*
473 N.B. this next function currently decodes values -- id est, it is
474 an opcode processing terminus; however, if 'future instruction set
475 expansion' happens, this will probably need to behave more like
476 the OP_IMPL(_nbi_) function which invoked it, if those instructions
477 have zero or differently styled operands.
478 */
479 OP_IMPL(nbi__reserved_) {
480 OP_NBI(nbi__reserved_);
481 /* reserved for future expansion */
482
483 /* fire an illegal instruction event for current instruction */
484 DCPU16_WORD future_opcode = (vm->ram[vm->reg[DCPU16_REG_PC] - pc_adjust] >> (OPCODE_BASIC_BITS + OPCODE_OPERAND_B_BITS));
485
486 MSG_INFO(vm, "reserved future opcode 0x%04x invoked", future_opcode);
487
488 ACCT_ILL(vm->reg[DCPU16_REG_PC] - pc_adjust);
489
490 dcpu16_cycle_inc(vm, 1);
491 }
492
493 OP_IMPL(nbi_jsr) {
494 OP_NBI(nbi_jsr);
495 /* pushes the address of the next instruction to the stack, then sets PC to a */
496
497 ACCT_R(a);
498
499 ACCT_REG_R(DCPU16_REG_PC);
500 ACCT_REG_R(DCPU16_REG_SP);
501 vm->ram[ --vm->reg[DCPU16_REG_SP] ] = vm->reg[DCPU16_REG_PC];
502 ACCT_REG_W(DCPU16_REG_SP);
503 ACCT_RAM_W(vm->reg[DCPU16_REG_SP] + 1);
504
505 vm->reg[DCPU16_REG_PC] = *a;
506 ACCT_REG_W(DCPU16_REG_PC);
507
508
509 dcpu16_cycle_inc(vm, 2);
510 }
511
512 OP_IMPL(nbi__reserved2_) {
513 OP_NBI(nbi__reserved2_);
514 /* reserved */
515
516 MSG_INFO(vm, "reserved nbi opcode invoked");
517
518 ACCT_ILL(vm->reg[DCPU16_REG_PC] - pc_adjust);
519
520 dcpu16_cycle_inc(vm, 1);
521 }
522
523 OP_IMPL(nbi_int) {
524 OP_NBI(nbi_int);
525
526 ACCT_R(a);
527
528 ACCT_REG_R(DCPU16_REG_IA);
529 if (vm->reg[DCPU16_REG_IA]) {
530 if ( interrupt_enqueue_(vm, *a) ) {
531 MSG_INFO(vm, "failed to queue interrupt");
532 return;
533 }
534
535 if (vm->interrupts_deferred_)
536 return;
537
538 vm->interrupts_deferred_ = 1;
539
540 ACCT_REG_R(DCPU16_REG_PC);
541 ACCT_REG_R(DCPU16_REG_SP);
542 vm->ram[--vm->reg[DCPU16_REG_SP]] = vm->reg[DCPU16_REG_PC];
543 ACCT_RAM_W(vm->reg[DCPU16_REG_SP] + 1);
544 ACCT_REG_W(DCPU16_REG_SP);
545
546 ACCT_REG_R(DCPU16_REG_A);
547 ACCT_REG_R(DCPU16_REG_SP);
548 vm->ram[--vm->reg[DCPU16_REG_SP]] = vm->reg[DCPU16_REG_A];
549 ACCT_RAM_W(vm->reg[DCPU16_REG_SP] + 1);
550 ACCT_REG_W(DCPU16_REG_SP);
551
552 ACCT_REG_R(DCPU16_REG_IA);
553 vm->reg[DCPU16_REG_PC] = vm->reg[DCPU16_REG_IA];
554 ACCT_REG_W(DCPU16_REG_PC);
555
556 vm->reg[DCPU16_REG_A] = *a;
557 ACCT_REG_W(DCPU16_REG_A);
558 }
559
560 dcpu16_cycle_inc(vm, 4);
561 }
562
563 OP_IMPL(nbi_iag) {
564 OP_NBI(nbi_iag);
565
566 ACCT_REG_R(DCPU16_REG_IA);
567 *a = vm->reg[DCPU16_REG_IA];
568
569 ACCT_W(a);
570
571 dcpu16_cycle_inc(vm, 1);
572 }
573
574 OP_IMPL(nbi_ias) {
575 OP_NBI(nbi_ias);
576
577 ACCT_R(a);
578
579 vm->reg[DCPU16_REG_IA] = *a;
580 ACCT_REG_W(DCPU16_REG_IA);
581
582 dcpu16_cycle_inc(vm, 1);
583 }
584
585 /* does this just ignore its operand? */
586 OP_IMPL(nbi_rfi) {
587 OP_NBI(nbi_rfi);
588
589 /* well, it consumes the argument, currently, so I guess pretend like we care */
590 ACCT_R(a);
591
592 vm->interrupts_deferred_ = 0;
593
594 ACCT_REG_R(DCPU16_REG_SP);
595 ACCT_RAM_R(vm->reg[DCPU16_REG_SP]);
596 vm->reg[DCPU16_REG_A] = vm->ram[vm->reg[DCPU16_REG_SP]++];
597 ACCT_REG_W(DCPU16_REG_A);
598 ACCT_REG_W(DCPU16_REG_SP);
599
600 ACCT_REG_R(DCPU16_REG_SP);
601 ACCT_RAM_R(vm->reg[DCPU16_REG_SP]);
602 vm->reg[DCPU16_REG_PC] = vm->ram[vm->reg[DCPU16_REG_SP]++];
603 ACCT_REG_W(DCPU16_REG_PC);
604 ACCT_REG_W(DCPU16_REG_SP);
605
606 dcpu16_cycle_inc(vm, 3);
607 }
608
609 OP_IMPL(nbi_iaq) {
610 OP_NBI(nbi_iaq);
611
612 ACCT_R(a);
613
614 if (*a) {
615 vm->interrupts_deferred_ = 1;
616 } else {
617 vm->interrupts_deferred_ = 0;
618 }
619
620 dcpu16_cycle_inc(vm, 2);
621 }
622
623 OP_IMPL(nbi_hwn) {
624 OP_NBI(nbi_hwn);
625
626 *a = vm->hw_table_entries_;
627 ACCT_W(a);
628
629 dcpu16_cycle_inc(vm, 2);
630 }
631
632 OP_IMPL(nbi_hwq) {
633 OP_NBI(nbi_hwq);
634
635 ACCT_R(a);
636
637 if (*a >= vm->hw_table_entries_) {
638 MSG_INFO(vm, "hardware query for non-extant device 0x%04x", *a);
639 vm->reg[DCPU16_REG_A] = 0;
640 vm->reg[DCPU16_REG_B] = 0;
641 vm->reg[DCPU16_REG_C] = 0;
642 vm->reg[DCPU16_REG_X] = 0;
643 vm->reg[DCPU16_REG_Y] = 0;
644 } else {
645 vm->reg[DCPU16_REG_A] = vm->hw_table_[*a].mod->id_l;
646 vm->reg[DCPU16_REG_B] = vm->hw_table_[*a].mod->id_h;
647 vm->reg[DCPU16_REG_C] = vm->hw_table_[*a].mod->ver;
648 vm->reg[DCPU16_REG_X] = vm->hw_table_[*a].mod->mfg_l;
649 vm->reg[DCPU16_REG_Y] = vm->hw_table_[*a].mod->mfg_h;
650 }
651
652 ACCT_REG_W(DCPU16_REG_A);
653 ACCT_REG_W(DCPU16_REG_B);
654 ACCT_REG_W(DCPU16_REG_C);
655 ACCT_REG_W(DCPU16_REG_X);
656 ACCT_REG_W(DCPU16_REG_Y);
657
658 dcpu16_cycle_inc(vm, 4);
659 }
660
661 OP_IMPL(nbi_hwi) {
662 OP_NBI(nbi_hwi);
663
664 ACCT_R(a);
665
666 if (*a > vm->hw_table_entries_) {
667 MSG_INFO(vm, "interrupt for non-extant device 0x%04x", *a);
668 return;
669 }
670
671 if (vm->hw_table_[*a].mod->hwi)
672 vm->hw_table_[*a].mod->hwi(vm, &vm->hw_table_[*a]);
673 else
674 MSG_INFO(vm, "hardware 0x%04x has no interrupt handler", *a);
675
676 dcpu16_cycle_inc(vm, 4);
677 }
678
679 OP_IMPL(nbi_hcf) {
680 OP_NBI(nbi_hcf);
681
682 ACCT_R(a);
683
684 vm->on_fire_ = 1;
685 MSG_INFO(vm, "system on fire");
686
687 dcpu16_cycle_inc(vm, 9);
688 }
689
690 static const struct opcode_entry opcode_nbi_entries[] = {
691 {0x00, "(reserved)", op_nbi__reserved_},
692 {0x01, "JSR", op_nbi_jsr},
693 {0x02, "(reserved)", op_nbi__reserved2_},
694 {0x03, "(reserved)", op_nbi__reserved2_},
695 {0x04, "(reserved)", op_nbi__reserved2_},
696 {0x05, "(reserved)", op_nbi__reserved2_},
697 {0x06, "(reserved)", op_nbi__reserved2_},
698 {0x07, "HCF", op_nbi_hcf}, /* undocumented */
699 {0x08, "INT", op_nbi_int},
700 {0x09, "IAG", op_nbi_iag},
701 {0x0a, "IAS", op_nbi_ias},
702 {0x0b, "RFI", op_nbi_rfi},
703 {0x0c, "IAQ", op_nbi_iaq},
704 {0x0d, "(reserved)", op_nbi__reserved2_},
705 {0x0e, "(reserved)", op_nbi__reserved2_},
706 {0x0f, "(reserved)", op_nbi__reserved2_},
707 {0x10, "HWN", op_nbi_hwn},
708 {0x11, "HWQ", op_nbi_hwq},
709 {0x12, "HWI", op_nbi_hwi},
710 {0x13, "(reserved)", op_nbi__reserved2_},
711 {0x00, "", NULL}
712 };
713 #define OPCODE_NBI_MAX (((sizeof(opcode_nbi_entries)) / (sizeof(struct opcode_entry))) - 1)
714
715
716 /* basic opcodes */
717
718 /*
719 N.B. the following function does not decode values.
720 Decoding is handled by the secondary opcode functions it calls.
721 */
722 OP_IMPL(_nbi_) {
723 /* non-basic instruction */
724
725 /* don't do normal value decoding here */
726
727 DCPU16_WORD nbi_opcode = val_b;
728 const struct opcode_entry *e = opcode_nbi_entries;
729
730 (void)val_b_data;
731
732 e = opcode_nbi_entries + ( (nbi_opcode < OPCODE_NBI_MAX) ? nbi_opcode : (OPCODE_NBI_MAX - 1) );
733
734 assert(e->impl != NULL);
735
736 MSG_DEBUG(vm, "%s>> %s 0x%04x", __func__, e->name, val_b);
737 e->impl(vm, 0, 0, val_a, val_a_data);
738 }
739
740 OP_IMPL(set) {
741 OP_BASIC(set);
742 /* sets b to a */
743
744 ACCT_R(a);
745
746 /*
747 if b is a literal, it's aimed at a scratch register,
748 so it's fine to update, as it won't have any effect.
749 */
750 *b = *a;
751
752 ACCT_W(b);
753
754 dcpu16_cycle_inc(vm, 1);
755 }
756
757 OP_IMPL(add) {
758 OP_BASIC(add);
759 /* sets b to b+a, sets EX to 0x0001 if there's an overflow, 0x0 otherwise */
760 unsigned int acc = *b + *a;
761
762 ACCT_R(b);
763 ACCT_R(a);
764
765 *b = acc;
766 vm->reg[DCPU16_REG_EX] = (acc > 0xffff);
767
768 ACCT_REG_W(DCPU16_REG_EX);
769
770 ACCT_W(b);
771
772 dcpu16_cycle_inc(vm, 2);
773 }
774
775 OP_IMPL(sub) {
776 OP_BASIC(sub);
777 /* sets b to b-a, sets EX to 0xffff if there's an underflow, 0x0 otherwise */
778 unsigned int acc = *b - *a;
779
780 ACCT_R(b);
781 ACCT_R(a);
782
783 *b = acc;
784 vm->reg[DCPU16_REG_EX] = (acc > 0xffff);
785
786 ACCT_REG_W(DCPU16_REG_EX);
787
788 ACCT_W(b);
789
790 dcpu16_cycle_inc(vm, 2);
791 }
792
793 OP_IMPL(mul) {
794 OP_BASIC(mul);
795 /* sets b to b*a, unsigned, sets EX to ((b*a)>>16)&0xffff */
796 unsigned int acc = *b * *a;
797
798 ACCT_R(b);
799 ACCT_R(a);
800
801 *b = acc;
802 vm->reg[DCPU16_REG_EX] = acc >> 16;
803
804 ACCT_REG_W(DCPU16_REG_EX);
805
806 ACCT_W(b);
807
808 dcpu16_cycle_inc(vm, 2);
809 }
810
811 OP_IMPL(mli) {
812 OP_BASIC(mli);
813 /* sets b to b*a, signed */
814 int acc = (short)*b * (short)*a;
815
816 ACCT_R(b);
817 ACCT_R(a);
818
819 *b = acc;
820 vm->reg[DCPU16_REG_EX] = acc >> 16;
821
822 ACCT_REG_W(DCPU16_REG_EX);
823
824 ACCT_W(b);
825
826 dcpu16_cycle_inc(vm, 2);
827 }
828
829 OP_IMPL(div) {
830 OP_BASIC(div);
831 /* sets b to b/a, sets EX to ((b<<16)/a)&0xffff. if a==0, sets a and EX to 0 instead. */
832
833 ACCT_R(b);
834 ACCT_R(a);
835
836 if (*a == 0) {
837 *b = 0;
838 vm->reg[DCPU16_REG_EX] = 0;
839 } else {
840 *b = *b / *a;
841 vm->reg[DCPU16_REG_EX] = (*b << 16) / *a;
842 }
843
844 ACCT_REG_W(DCPU16_REG_EX);
845
846 ACCT_W(b);
847
848 dcpu16_cycle_inc(vm, 3);
849 }
850
851 OP_IMPL(dvi) {
852 OP_BASIC(dvi);
853 /* sets b to b/a, signed, round towards 0 */
854
855 ACCT_R(b);
856 ACCT_R(a);
857
858 if (*a == 0) {
859 *b = 0;
860 vm->reg[DCPU16_REG_EX] = 0;
861 } else {
862 *b = (short)*b / (short)*a;
863 vm->reg[DCPU16_REG_EX] = (short)(*b << 16) / (short)*a;
864 }
865
866 ACCT_REG_W(DCPU16_REG_EX);
867 ACCT_W(b);
868
869 dcpu16_cycle_inc(vm, 3);
870 }
871
872 OP_IMPL(mod) {
873 OP_BASIC(mod);
874 /* sets b to b%a. if a==0, sets b to 0 instead. */
875
876 ACCT_R(b);
877 ACCT_R(a);
878
879 if (*a == 0) {
880 *b = 0;
881 } else {
882 *b = *b % *a;
883 }
884
885 ACCT_W(a);
886
887 dcpu16_cycle_inc(vm, 3);
888 }
889
890 OP_IMPL(mdi) {
891 OP_BASIC(mdi);
892 /* sets b to b%a, signed */
893
894 ACCT_R(b);
895 ACCT_R(a);
896
897 if (*a == 0) {
898 *b = 0;
899 } else {
900 *b = (short)*b % (short)*a;
901 }
902
903 ACCT_W(b);
904
905 dcpu16_cycle_inc(vm, 3);
906 }
907
908 OP_IMPL(and) {
909 OP_BASIC(and);
910 /* sets b to b&a */
911
912 ACCT_R(b);
913 ACCT_R(a);
914
915 *b = *b & *a;
916
917 ACCT_W(b);
918
919 dcpu16_cycle_inc(vm, 1);
920 }
921
922 OP_IMPL(bor) {
923 OP_BASIC(bor);
924 /* sets b to b|a */
925
926 ACCT_R(b);
927 ACCT_R(a);
928
929 *b = *b | *a;
930
931 ACCT_W(b);
932
933 dcpu16_cycle_inc(vm, 1);
934 }
935
936 OP_IMPL(xor) {
937 OP_BASIC(xor);
938 /* sets b to b^a */
939
940 ACCT_R(b);
941 ACCT_R(a);
942
943 *b = *b ^ *a;
944
945 dcpu16_cycle_inc(vm, 1);
946
947 ACCT_W(b);
948 }
949
950 OP_IMPL(shr) {
951 OP_BASIC(shr);
952 /* sets b to b>>>a, sets EX to ((b<<16)>>a)&0xffff */
953 unsigned int acc = *b >> *a;
954
955 ACCT_R(b);
956 ACCT_R(a);
957
958 *b = acc & 0xffff;
959 vm->reg[DCPU16_REG_EX] = (*b << 16) >> *a;
960
961 MSG_ERROR(vm, "IMPLEMENT");
962
963 ACCT_REG_W(DCPU16_REG_EX);
964 ACCT_W(b);
965
966 dcpu16_cycle_inc(vm, 2);
967 }
968
969 OP_IMPL(asr) {
970 OP_BASIC(asr);
971 /* sets b to b>>a, sets EX to ((b<<16)>>>a)&0xffff (arithmetic shift) (treats b as signed) */
972 unsigned int acc = *b << *a;
973
974 ACCT_R(b);
975 ACCT_R(a);
976
977 *b = acc & 0xffff;
978 vm->reg[DCPU16_REG_EX] = (*b << 16) >> *a;
979
980 MSG_ERROR(vm, "IMPLEMENT");
981
982 ACCT_REG_W(DCPU16_REG_EX);
983 ACCT_W(b);
984
985 dcpu16_cycle_inc(vm, 2);
986 }
987
988 OP_IMPL(shl) {
989 OP_BASIC(shl);
990 /* sets b to b<<a, sets EX to ((b<<a)>>16)&0xffff */
991 unsigned int acc = *b << *a;
992
993 ACCT_R(b);
994 ACCT_R(a);
995
996 *b = acc;
997
998 vm->reg[DCPU16_REG_EX] = acc >> 16;
999
1000 ACCT_REG_W(DCPU16_REG_EX);
1001 ACCT_W(b);
1002
1003 dcpu16_cycle_inc(vm, 2);
1004 }
1005
1006 OP_IMPL(ifb) {
1007 OP_BASIC(ifb);
1008 /* performs next instruction only if (b&a)!=0 */
1009
1010 ACCT_R(b);
1011 ACCT_R(a);
1012
1013 if ((*b & *a) != 0) {
1014 /* */
1015 } else {
1016 vm->skip_ = 1;
1017 dcpu16_cycle_inc(vm, 1);
1018 }
1019
1020 dcpu16_cycle_inc(vm, 2);
1021 }
1022
1023 OP_IMPL(ifc) {
1024 OP_BASIC(ifc);
1025 /* performs next instruction only if (b&a)==0 */
1026
1027 ACCT_R(b);
1028 ACCT_R(a);
1029
1030 if ((*b & *a) == 0) {
1031 /* */
1032 } else {
1033 vm->skip_ = 1;
1034 dcpu16_cycle_inc(vm, 1);
1035 }
1036
1037 dcpu16_cycle_inc(vm, 2);
1038 }
1039
1040 OP_IMPL(ife) {
1041 OP_BASIC(ife);
1042 /* performs next instruction only if b==a */
1043
1044 ACCT_R(b);
1045 ACCT_R(a);
1046
1047 if (*b == *a) {
1048 /* */
1049 } else {
1050 vm->skip_ = 1;
1051 dcpu16_cycle_inc(vm, 1);
1052 }
1053
1054 dcpu16_cycle_inc(vm, 2);
1055 }
1056
1057 OP_IMPL(ifn) {
1058 OP_BASIC(ifn);
1059 /* performs next instruction only if b!=a */
1060
1061 ACCT_R(b);
1062 ACCT_R(a);
1063
1064 if (*b != *a) {
1065 /* */
1066 } else {
1067 vm->skip_ = 1;
1068 dcpu16_cycle_inc(vm, 1);
1069 }
1070
1071 dcpu16_cycle_inc(vm, 2);
1072 }
1073
1074 OP_IMPL(ifg) {
1075 OP_BASIC(ifg);
1076 /* performs next instruction only if b>a */
1077
1078 ACCT_R(b);
1079 ACCT_R(a);
1080
1081 if (*b > *a) {
1082 /* */
1083 } else {
1084 vm->skip_ = 1;
1085 dcpu16_cycle_inc(vm, 1);
1086 }
1087
1088 dcpu16_cycle_inc(vm, 2);
1089 }
1090
1091 OP_IMPL(ifa) {
1092 OP_BASIC(ifa);
1093 /* performs next instruction only if b>a (signed) */
1094
1095 ACCT_R(b);
1096 ACCT_R(a);
1097
1098 if (*b > *a) {
1099 /* */
1100 } else {
1101 vm->skip_ = 1;
1102 dcpu16_cycle_inc(vm, 1);
1103 }
1104
1105 dcpu16_cycle_inc(vm, 2);
1106 }
1107
1108 OP_IMPL(ifl) {
1109 OP_BASIC(ifl);
1110 /* performs next instruction only if b<a */
1111
1112 ACCT_R(b);
1113 ACCT_R(a);
1114
1115 if (*b < *a) {
1116 /* */
1117 } else {
1118 vm->skip_ = 1;
1119 dcpu16_cycle_inc(vm, 1);
1120 }
1121
1122 dcpu16_cycle_inc(vm, 2);
1123 }
1124
1125 OP_IMPL(ifu) {
1126 OP_BASIC(ifu);
1127 /* performs next instruction only if b<a (signed) */
1128
1129 ACCT_R(b);
1130 ACCT_R(a);
1131
1132 if (*b < *a) {
1133 /* */
1134 } else {
1135 vm->skip_ = 1;
1136 dcpu16_cycle_inc(vm, 1);
1137 }
1138
1139 dcpu16_cycle_inc(vm, 2);
1140 }
1141
1142 OP_IMPL(adx) {
1143 OP_BASIC(adx);
1144 /* sets b to b+a+EX, sets EX to 0x0001 if overflow, 0x0 otherwise */
1145 unsigned int acc;
1146
1147 ACCT_R(b);
1148 ACCT_R(a);
1149
1150 ACCT_REG_R(DCPU16_REG_EX);
1151
1152 acc = *b + *a + vm->reg[DCPU16_REG_EX];
1153 *b = acc & 0xffff;
1154 if (acc > 0xffff)
1155 vm->reg[DCPU16_REG_EX] = 0x0001;
1156 else
1157 vm->reg[DCPU16_REG_EX] = 0x0000;
1158
1159 ACCT_REG_W(DCPU16_REG_EX);
1160 ACCT_W(b);
1161
1162 dcpu16_cycle_inc(vm, 3);
1163 }
1164
1165 OP_IMPL(sbx) {
1166 OP_BASIC(sbx);
1167 /* sets b to b-a+EX, sets EX to 0xffff if underflow, 0x0 otherwise */
1168 unsigned int acc;
1169
1170 ACCT_R(b);
1171 ACCT_R(a);
1172
1173 ACCT_REG_R(DCPU16_REG_EX);
1174
1175 acc = *b - *a + vm->reg[DCPU16_REG_EX];
1176 *b = acc & 0xffff;
1177 if (acc > 0xffff)
1178 vm->reg[DCPU16_REG_EX] = 0xffff;
1179 else
1180 vm->reg[DCPU16_REG_EX] = 0;
1181
1182 ACCT_REG_W(DCPU16_REG_EX);
1183
1184 ACCT_W(b);
1185
1186 dcpu16_cycle_inc(vm, 3);
1187 }
1188
1189 OP_IMPL(sti) {
1190 OP_BASIC(sti);
1191 /* sets b to a, then increases I and J by 1 */
1192
1193 ACCT_R(b);
1194 ACCT_R(a);
1195
1196 *b = *a;
1197 vm->reg[DCPU16_REG_I] += 1;
1198 vm->reg[DCPU16_REG_J] += 1;
1199
1200 ACCT_REG_W(DCPU16_REG_I);
1201 ACCT_REG_W(DCPU16_REG_J);
1202
1203 ACCT_W(b);
1204
1205 dcpu16_cycle_inc(vm, 2);
1206 }
1207
1208 OP_IMPL(std) {
1209 OP_BASIC(std);
1210 /* sets b to a, then decreases I and J by 1 */
1211
1212 ACCT_R(b);
1213 ACCT_R(a);
1214
1215 *b = *a;
1216 vm->reg[DCPU16_REG_I] -= 1;
1217 vm->reg[DCPU16_REG_J] -= 1;
1218
1219 ACCT_REG_W(DCPU16_REG_I);
1220 ACCT_REG_W(DCPU16_REG_J);
1221
1222 ACCT_W(b);
1223
1224 dcpu16_cycle_inc(vm, 2);
1225 }
1226
1227 OP_IMPL(_reserved_) {
1228 OP_BASIC(_reserved_);
1229
1230 MSG_INFO(vm, "reserved opcode invoked");
1231
1232 ACCT_ILL(vm->reg[DCPU16_REG_PC] - pc_adjust);
1233 }
1234
1235 static const struct opcode_entry opcode_basic_entries[] = {
1236 {0x00, "(nbi)", op__nbi_},
1237 {0x01, "SET", op_set },
1238 {0x02, "ADD", op_add },
1239 {0x03, "SUB", op_sub },
1240 {0x04, "MUL", op_mul },
1241 {0x05, "MLI", op_mli },
1242 {0x06, "DIV", op_div },
1243 {0x07, "DVI", op_dvi },
1244 {0x08, "MOD", op_mod },
1245 {0x09, "MDI", op_mdi },
1246 {0x0a, "AND", op_and },
1247 {0x0b, "BOR", op_bor },
1248 {0x0c, "XOR", op_xor },
1249 {0x0d, "SHR", op_shr },
1250 {0x0e, "ASR", op_asr },
1251 {0x0f, "SHL", op_shl },
1252 {0x10, "IFB", op_ifb },
1253 {0x11, "IFC", op_ifc },
1254 {0x12, "IFE", op_ife },
1255 {0x13, "IFN", op_ifn },
1256 {0x14, "IFG", op_ifg },
1257 {0x15, "IFA", op_ifa },
1258 {0x16, "IFL", op_ifl },
1259 {0x17, "IFU", op_ifu },
1260 {0x18, "(reserved)", op__reserved_ },
1261 {0x19, "(reserved)", op__reserved_ },
1262 {0x1a, "ADX", op_adx },
1263 {0x1b, "SBX", op_sbx },
1264 {0x1c, "(reserved)", op__reserved_ },
1265 {0x1d, "(reserved)", op__reserved_ },
1266 {0x1e, "STI", op_sti },
1267 {0x1f, "STD", op_std },
1268 {0x00, "", NULL }
1269 };
1270 #define OPCODE_BASIC_MAX (((sizeof(opcode_basic_entries)) / (sizeof(struct opcode_entry))) - 1)
1271
1272 static inline
1273 void dump_operand_value_(DCPU16_WORD value, DCPU16_WORD nextword, unsigned int value_position) {
1274 printf(" ");
1275 if (value <= 0x07) {
1276 printf("%s", dcpu16_reg_names[value]);
1277 } else if (value <= 0x0f) {
1278 printf("[%s]", dcpu16_reg_names[value & 0x07]);
1279 } else if (value <= 0x17) {
1280 printf("[0x%04x + %s]", nextword, dcpu16_reg_names[value & 0x07]);
1281 } else switch (value) {
1282 case 0x18:
1283 if (value_position == 0) { /* b */
1284 printf("PUSH");
1285 } else {
1286 printf("POP");
1287 }
1288 break;
1289 case 0x19: printf("PEEK"); break;
1290 case 0x1a: printf("PICK 0x%04x", nextword); break;
1291 case 0x1b: printf("SP"); break;
1292 case 0x1c: printf("PC"); break;
1293 case 0x1d: printf("EX"); break;
1294 case 0x1e: printf("[0x%04x]", nextword); break;
1295 case 0x1f: printf("0x%04x", nextword); break;
1296 default: printf("0x%02x", value - 0x21);
1297 }
1298 }
1299
1300 static inline
1301 int operand_snprint_(char *buf, size_t buf_sz, DCPU16_WORD value, DCPU16_WORD nextword, unsigned int operand_is_a) {
1302 int len;
1303
1304 len = snprintf(buf, buf_sz, " ");
1305 if ((size_t)len >= buf_sz)
1306 return -1;
1307
1308 buf += len, buf_sz -= len;
1309
1310 if (value <= 0x07) {
1311 len = snprintf(buf, buf_sz, "%s", dcpu16_reg_names[value]);
1312 } else if (value <= 0x0f) {
1313 len = snprintf(buf, buf_sz, "[%s]", dcpu16_reg_names[value & 0x07]);
1314 } else if (value <= 0x17) {
1315 len = snprintf(buf, buf_sz, "[0x%04x + %s]", nextword, dcpu16_reg_names[value & 0x07]);
1316 } else switch (value) {
1317 case 0x18:
1318 if (operand_is_a == 0) { /* b */
1319 len = snprintf(buf, buf_sz, "PUSH");
1320 } else {
1321 len = snprintf(buf, buf_sz, "POP");
1322 }
1323 break;
1324 case 0x19: len = snprintf(buf, buf_sz, "PEEK"); break;
1325 case 0x1a: len = snprintf(buf, buf_sz, "PICK 0x%04x", nextword); break;
1326 case 0x1b: len = snprintf(buf, buf_sz, "SP"); break;
1327 case 0x1c: len = snprintf(buf, buf_sz, "PC"); break;
1328 case 0x1d: len = snprintf(buf, buf_sz, "EX"); break;
1329 case 0x1e: len = snprintf(buf, buf_sz, "[0x%04x]", nextword); break;
1330 case 0x1f: len = snprintf(buf, buf_sz, "0x%04x", nextword); break;
1331 default: len = snprintf(buf, buf_sz, "0x%02x", (short)(value - 0x21));
1332 }
1333
1334 if ((size_t)len >= buf_sz)
1335 return -1;
1336
1337 return len;
1338 }
1339
1340
1341 /* split a sequence of (one to three) words into the components of an instruction */
1342 static inline
1343 void instruction_decode_(DCPU16_WORD *mem, DCPU16_WORD addr,
1344 DCPU16_WORD *opcode, DCPU16_WORD *b, DCPU16_WORD **b_data, DCPU16_WORD *a, DCPU16_WORD **a_data,
1345 DCPU16_WORD *instr_len) {
1346 *opcode = *a = *b = mem[addr];
1347 *opcode = mem[addr] & ((1 << OPCODE_BASIC_BITS) - 1);
1348 *b = (mem[addr] >> OPCODE_BASIC_BITS) & ((1 << OPCODE_OPERAND_B_BITS) - 1);
1349 *a = (mem[addr] >> (OPCODE_BASIC_BITS + OPCODE_OPERAND_B_BITS)) & ((1 << OPCODE_OPERAND_A_BITS) - 1);
1350 *instr_len = 1;
1351
1352 if ((*opcode != 0x0000) &&
1353 ( (*b >= 0x10 && *b <= 0x17) || *b == 0x1e || *b == 0x1f ) ) {
1354 *b_data = mem + (DCPU16_WORD)(addr + *instr_len);
1355 *instr_len += 1;
1356 } else {
1357 *b_data = NULL;
1358 }
1359
1360 if ( (*opcode != 0x0000 || (*opcode == 0 && *b != 0x0000) )
1361 && ( (*a >= 0x10 && *a <= 0x17) || *a == 0x1e || *a == 0x1f) ) {
1362 *a_data = mem + (DCPU16_WORD)(addr + *instr_len);
1363 *instr_len += 1;
1364 } else {
1365 *a_data = NULL;
1366 }
1367
1368 #ifdef DEBUG_DECODE
1369 MSG_(MSG_DEBUG_DECODE, NULL, "\n%s: [0x%04x]:0x%04x op:0x%02x b:0x%02x (b_data:0x%04x) a:0x%02x (a_data:0x%04x) len:0x%02x\n",
1370 __func__,
1371 addr,
1372 mem[addr],
1373 *opcode,
1374 *b,
1375 *b_data ? **b_data : 0,
1376 *a,
1377 *a_data ? **a_data : 0,
1378 *instr_len);
1379 #endif /* DEBUG_DECODE */
1380 }
1381
1382 /* dcpu16_mnemonify_buf
1383 print words as words
1384 */
1385 DCPU16_WORD dcpu16_mnemonify_buf(DCPU16_WORD *buf) {
1386 DCPU16_WORD opcode, b, a, instr_len, *b_data, *a_data;
1387 const struct opcode_entry *e;
1388 char operand[16];
1389
1390 instruction_decode_(buf, 0, &opcode, &b, &b_data, &a, &a_data, &instr_len);
1391
1392 if (opcode == 0x0000)
1393 e = opcode_nbi_entries +
1394 ( (b < OPCODE_NBI_MAX) ? b : (OPCODE_NBI_MAX - 1) );
1395 else
1396 e = opcode_basic_entries + opcode;
1397 printf("%s", e->name);
1398
1399 if (opcode) {
1400 operand_snprint_(operand, sizeof operand, b, b_data ? *b_data : 0, 0);
1401 printf("%s,", operand);
1402 }
1403
1404 if (opcode || b) {
1405 operand_snprint_(operand, sizeof operand, a, a_data ? *a_data : 0, 1);
1406 printf("%s", operand);
1407 }
1408
1409 return instr_len;
1410 }
1411
1412 /* dcpu16_disassemble_print
1413 print the words of the instruction at addr, followed by its assembly representation
1414 returns the length of the instruction in words
1415 */
1416 DCPU16_WORD dcpu16_disassemble_print(struct dcpu16 *vm, DCPU16_WORD addr) {
1417 DCPU16_WORD opcode, b, a, instr_len, i, *b_data, *a_data;
1418 DCPU16_WORD buf[3] = { vm->ram[addr], vm->ram[(DCPU16_WORD)(addr + 1)], vm->ram[(DCPU16_WORD)(addr + 2)] };
1419 unsigned int indent = 0;
1420 unsigned int partial = 0;
1421
1422 if (!vm) return 0;
1423
1424 #if 0
1425 /*
1426 Check the previous instruction, to see if this one should be
1427 indented. This check isn't foolproof, as preceeding addresses
1428 could be data which happen to match instructions..
1429 */
1430 for (i = 3; i; i--) {
1431 instruction_decode_(vm->ram, (DCPU16_WORD)(addr - i), &opcode, &b, &b_data, &a, &a_data, &instr_len);
1432 if (instr_len > i)
1433 partial++;
1434 if (instr_len == i
1435 && (opcode >= 0x10 && opcode <= 0x17) ) {
1436 indent++;
1437 break;
1438 }
1439 }
1440 #endif
1441
1442 /* just need instr_len */
1443 instruction_decode_(vm->ram, addr, &opcode, &b, &b_data, &a, &a_data, &instr_len);
1444
1445 /* show the raw words */
1446 printf("%04x", vm->ram[addr]);
1447 for (i = 1; i < instr_len; i++) {
1448 printf(" %04x", vm->ram[addr + i]);
1449 }
1450
1451 /* align things neatly, show the instruction */
1452 printf("%s%s ;%s%s",
1453 instr_len < 3 ? " " : "",
1454 instr_len < 2 ? " " : "",
1455 partial ? "*" : " ",
1456 indent ? " " : "");
1457
1458 dcpu16_mnemonify_buf(buf);
1459
1460 return instr_len;
1461 }
1462
1463 int dcpu16_interrupt(struct dcpu16 *vm, DCPU16_WORD message) {
1464 MSG_DEBUG(vm, "%s>> message:0x%04x", __func__, message);
1465 return interrupt_enqueue_(vm, message);
1466 }
1467
1468 /* execute the next instruction */
1469 void dcpu16_step(struct dcpu16 *vm) {
1470 DCPU16_WORD opcode, b, a, instr_len, *b_data, *a_data;
1471 const struct opcode_entry *e;
1472
1473 if (!vm)
1474 return;
1475
1476 instruction_decode_(vm->ram, vm->reg[DCPU16_REG_PC], &opcode, &b, &b_data, &a, &a_data, &instr_len);
1477
1478 /* consume what we decoded */
1479 /* this happens immediately as PC might be re-set as an operation */
1480 vm->reg[DCPU16_REG_PC] += instr_len;
1481
1482 /* run the operation */
1483 e = opcode_basic_entries + opcode;
1484 MSG_DEBUG(vm, "%s", e->name ? e->name : "???");
1485 e->impl(vm, b, b_data ? *b_data : 0, a, a_data ? *a_data : 0);
1486
1487
1488 /* and jump over next instr(s) if needed */
1489 while (vm->skip_) {
1490 instruction_decode_(vm->ram, vm->reg[DCPU16_REG_PC], &opcode, &b, &b_data, &a, &a_data, &instr_len);
1491 vm->reg[DCPU16_REG_PC] += instr_len;
1492 MSG_DEBUG(vm, "%s>> ++ SKIPPED %x words", __func__, instr_len);
1493 if (opcode >= 0x10 && opcode <= 0x17) {
1494 /* skipping a branch instruction? skip branch's skippable instruction as well */
1495 dcpu16_cycle_inc(vm, 1);
1496 } else {
1497 vm->skip_ = 0;
1498 }
1499 }
1500
1501 /* if we're currently servicing interrupts */
1502 if (vm->interrupts_deferred_ == 0) {
1503 /* and there are interrupts to be serviced */
1504 if (vm->interrupts_head_ != vm->interrupts_tail_) {
1505 DCPU16_WORD message;
1506 message = interrupt_dequeue_(vm);
1507
1508 MSG_DEBUG(vm, "%s>> %s interrupt IA:0x%04x message:0x%04x",
1509 __func__,
1510 vm->reg[DCPU16_REG_IA] ? "servicing" : "ignoring",
1511 vm->reg[DCPU16_REG_IA],
1512 message);
1513
1514 if (vm->reg[DCPU16_REG_IA]) {
1515 /* then service the next interrupt */
1516 vm->interrupts_deferred_ = 1;
1517 vm->ram[--vm->reg[DCPU16_REG_SP]] = vm->reg[DCPU16_REG_PC];
1518 vm->ram[--vm->reg[DCPU16_REG_SP]] = vm->reg[DCPU16_REG_A];
1519 vm->reg[DCPU16_REG_PC] = vm->reg[DCPU16_REG_IA];
1520 vm->reg[DCPU16_REG_A] = message;
1521 }
1522 }
1523 }
1524 }
1525
1526
1527 /* instantiate a new 'hardware' device */
1528 struct dcpu16_hw *dcpu16_hw_new(struct dcpu16 *vm, struct dcpu16_hw_module *mod, void *data) {
1529 struct dcpu16_hw *hw;
1530
1531 MSG_DEBUG(vm, "%s>> mod:%p data:%p", __func__, mod, data);
1532
1533 hw = malloc(sizeof *hw);
1534 if (hw == NULL) {
1535 MSG_ERROR(vm, "%s():%s", "malloc", strerror(errno));
1536 return NULL;
1537 }
1538 hw->vm = vm;
1539 hw->mod = mod;
1540
1541 if (mod->data_init) {
1542 if (mod->data_init(hw, data)) {
1543 MSG_ERROR(vm, "failed to init hw module data");
1544 free(hw);
1545 return NULL;
1546 }
1547 } else {
1548 hw->data = NULL;
1549 }
1550
1551 return hw;
1552 }
1553
1554 /* destroy a 'hardware' device */
1555 void dcpu16_hw_del(struct dcpu16_hw **hw) {
1556 if (hw) {
1557 if (*hw) {
1558 MSG_DEBUG((*hw)->vm, "%s>> hw:%p",
1559 __func__,
1560 *hw);
1561
1562 if ((*hw)->mod->data_free) {
1563 (*hw)->mod->data_free(*hw);
1564 }
1565 free(*hw);
1566 *hw = NULL;
1567 }
1568 }
1569 }
1570
1571 /* dcpu16_hw_ctl
1572 * invokes per-module controls for hw device
1573 */
1574 int dcpu16_hw_ctl(struct dcpu16_hw *hw, const char *cmd, void *data_in, void *data_out) {
1575 if (!hw)
1576 return -1;
1577
1578 MSG_DEBUG(hw->vm, "%s>> name:%s cmd:%s in:%p out:%p",
1579 __func__,
1580 hw->mod->name_,
1581 cmd,
1582 data_in,
1583 data_out);
1584
1585 if (hw->mod) {
1586 if (hw->mod->ctl) {
1587 if (cmd) {
1588 return hw->mod->ctl(hw, cmd, data_in, data_out);
1589 }
1590 }
1591 }
1592
1593 return 0;
1594 }
1595
1596
1597 /* dcpu16_hw_attach
1598 * registers new 'hardware' device with system
1599 */
1600 int dcpu16_hw_attach(struct dcpu16 *vm, struct dcpu16_hw *hw) {
1601 if (!vm || !hw)
1602 return -1;
1603
1604 MSG_DEBUG(vm, "%s>> name:%s ID:0x%04x%04x MFG:0x%04x%04x VER:0x%04x",
1605 __func__,
1606 hw->mod->name_,
1607 hw->mod->id_h, hw->mod->id_l,
1608 hw->mod->mfg_l, hw->mod->mfg_h,
1609 hw->mod->ver);
1610
1611 if (vm->hw_table_entries_ == 0xffff) {
1612 MSG_ERROR(vm, "maximum hardware entries reached");
1613 return -1;
1614 }
1615
1616 if (vm->hw_table_entries_ == vm->hw_table_allocated_) {
1617 size_t new_entries = vm->hw_table_allocated_ + 32;
1618 void *tmp_ptr = realloc(vm->hw_table_, new_entries * sizeof * (vm->hw_table_));
1619 if (tmp_ptr == NULL) {
1620 MSG_ERROR(vm, "%s():%s", "realloc", strerror(errno));
1621 return -1;
1622 }
1623 vm->hw_table_ = tmp_ptr;
1624 vm->hw_table_allocated_ += 32;
1625 }
1626
1627 memcpy(vm->hw_table_ + vm->hw_table_entries_, hw, sizeof *hw);
1628 vm->hw_table_entries_++;
1629
1630 MSG_DEBUG(vm, "%s>> added hw entry %zu", __func__, vm->hw_table_entries_);
1631
1632 return 0;
1633 }
1634
1635 /* dcpu16_acct_add
1636 * Register callback fn to be triggered whenever event matching any events
1637 * in bitwise mask occur.
1638 */
1639 int dcpu16_acct_add(struct dcpu16 *vm, dcpu16_acct_event mask, dcpu16_ev_cb_t *fn, DCPU16_WORD addr_l, DCPU16_WORD addr_h, void *data) {
1640 struct dcpu16_acct_cb cb = {
1641 .mask = mask,
1642 .addr_l = addr_l,
1643 .addr_h = addr_h,
1644 .fn = fn,
1645 .data = data,
1646 };
1647
1648 if (!vm)
1649 return -1;
1650
1651 cb.mask = mask;
1652 cb.addr_l = addr_l;
1653 cb.addr_h = addr_h;
1654 cb.fn = fn;
1655 cb.data = data;
1656
1657 if (vm->cb_table_entries_ == vm->cb_table_allocated_) {
1658 size_t new_entries = vm->cb_table_allocated_ + 32;
1659 void *tmp_ptr = realloc(vm->cb_table_, new_entries * sizeof *(vm->cb_table_));
1660 if (tmp_ptr == NULL) {
1661 MSG_ERROR(vm, "%s():%s", "realloc", strerror(errno));
1662 return -1;
1663 }
1664 vm->cb_table_ = tmp_ptr;
1665 vm->cb_table_allocated_ += 32;
1666 }
1667
1668 memcpy(vm->cb_table_ + vm->cb_table_entries_, &cb, sizeof cb);
1669 vm->cb_table_entries_++;
1670
1671 MSG_DEBUG(vm, "%s>> attached event callback %zu", __func__, vm->cb_table_entries_);
1672
1673 return 0;
1674 }
1675
1676 /* dcpu16_reset
1677 * signals cpu to reset, clearing runstate and ram, then reload any init callbacks
1678 */
1679 void dcpu16_reset(struct dcpu16 *vm) {
1680 size_t i;
1681
1682 if (!vm)
1683 return;
1684
1685 MSG_DEBUG(vm, "%s>> reset", __func__);
1686
1687 vm->skip_ = 0;
1688 vm->interrupts_deferred_ = 0;
1689 vm->on_fire_ = 0;
1690 memset(vm->interrupts_, 0, sizeof vm->interrupts_);
1691 vm->interrupts_head_ = 0;
1692 vm->interrupts_tail_ = 0;
1693
1694 /* signal attached hardware */
1695 for (i = 0; i < vm->hw_table_entries_; i++) {
1696 if (vm->hw_table_[i].mod->reset)
1697 vm->hw_table_[i].mod->reset(vm, &vm->hw_table_[i]);
1698 }
1699
1700 memset(vm->reg, 0, sizeof vm->reg);
1701 memset(vm->ram, 0, sizeof vm->ram);
1702 vm->cycle_ = 0;
1703
1704 acct_event_(vm, DCPU16_ACCT_EV_RESET, 0);
1705 }
1706
1707 /* dcpu16_new
1708 * allocate a new dcpu16 instance
1709 */
1710 struct dcpu16 *dcpu16_new(void) {
1711 struct dcpu16 *vm;
1712
1713 vm = calloc(1, sizeof *vm);
1714 if (vm == NULL)
1715 MSG_ERROR(NULL, "%s: %s(%zu): %s", __func__, "calloc", strerror(errno));
1716
1717 vm->msg_cb_ = dcpu16_msg_;
1718
1719 return vm;
1720 }
1721
1722 /* dcpu16_delete
1723 * release a dcpu16 instance
1724 */
1725 void dcpu16_delete(struct dcpu16 **vm) {
1726 if (!vm || !*vm)
1727 return;
1728
1729 free(*vm);
1730 *vm = NULL;
1731 }