Added ior and xor tests to the repository.
[picobit/chj.git] / dispatch.c
blob3a394bea698315b275872f6c284e81bf2bb550f1
1 /* file: "dispatch.c" */
3 /*
4 * Copyright 2004-2009 by Marc Feeley and Vincent St-Amour, All Rights Reserved.
5 */
7 #include "picobit-vm.h"
9 void push_arg1 (void) {
10 env = cons (arg1, env);
11 arg1 = OBJ_FALSE;
14 obj pop (void) {
15 obj o = ram_get_car (env);
16 env = ram_get_cdr (env);
17 return o;
20 void pop_procedure (void) {
21 arg1 = POP();
23 if (IN_RAM(arg1)) {
24 if (!RAM_CLOSURE(arg1))
25 TYPE_ERROR("pop_procedure.0", "procedure");
27 entry = ram_get_entry (arg1) + CODE_START;
29 else if (IN_ROM(arg1)) {
30 if (!ROM_CLOSURE(arg1))
31 TYPE_ERROR("pop_procedure.1", "procedure");
33 entry = rom_get_entry (arg1) + CODE_START;
35 else
36 TYPE_ERROR("pop_procedure.2", "procedure");
39 void handle_arity_and_rest_param (void) {
40 uint8 np;
42 np = rom_get (entry++);
44 if ((np & 0x80) == 0) {
45 if (na != np)
46 ERROR("handle_arity_and_rest_param.0", "wrong number of arguments");
48 else {
49 np = ~np;
51 if (na < np)
52 ERROR("handle_arity_and_rest_param.1", "wrong number of arguments");
54 arg3 = OBJ_NULL;
56 while (na > np) {
57 arg4 = POP();
59 arg3 = cons (arg4, arg3);
60 arg4 = OBJ_FALSE;
62 na--;
65 arg1 = cons (arg3, arg1);
66 arg3 = OBJ_FALSE;
70 void build_env (void) {
71 while (na != 0) {
72 arg3 = POP();
74 arg1 = cons (arg3, arg1);
76 na--;
79 arg3 = OBJ_FALSE;
82 void save_cont (void) {
83 // the second half is a closure
84 arg3 = alloc_ram_cell_init (CLOSURE_FIELD0 | (pc >> 11),
85 (pc >> 3) & 0xff,
86 ((pc & 0x0007) << 5) | (env >> 8),
87 env & 0xff);
88 cont = alloc_ram_cell_init (COMPOSITE_FIELD0 | (cont >> 8),
89 cont & 0xff,
90 CONTINUATION_FIELD2 | (arg3 >> 8),
91 arg3 & 0xff);
92 arg3 = OBJ_FALSE;
95 void interpreter (void) {
96 pc = (CODE_START + 4) + ((rom_addr)rom_get (CODE_START+2) << 2);
98 glovars = rom_get (CODE_START+3); // number of global variables
100 init_ram_heap ();
102 BEGIN_DISPATCH();
104 /***************************************************************************/
105 CASE(PUSH_CONSTANT1);
107 IF_TRACE(printf(" (push-constant "); show (bytecode_lo4); printf (")\n"));
109 arg1 = bytecode_lo4;
111 PUSH_ARG1();
113 DISPATCH();
115 /***************************************************************************/
116 CASE(PUSH_CONSTANT2);
118 IF_TRACE(printf(" (push-constant "); show (bytecode_lo4+16); printf (")\n"));
119 arg1 = bytecode_lo4+16;
121 PUSH_ARG1();
123 DISPATCH();
125 /***************************************************************************/
126 CASE(PUSH_STACK1);
128 IF_TRACE(printf(" (push-stack %d)\n", bytecode_lo4));
130 arg1 = env;
132 while (bytecode_lo4 != 0) {
133 arg1 = ram_get_cdr (arg1);
134 bytecode_lo4--;
137 arg1 = ram_get_car (arg1);
139 PUSH_ARG1();
141 DISPATCH();
143 /***************************************************************************/
144 CASE(PUSH_STACK2);
146 IF_TRACE(printf(" (push-stack %d)\n", bytecode_lo4+16));
148 bytecode_lo4 += 16;
150 arg1 = env;
152 while (bytecode_lo4 != 0) {
153 arg1 = ram_get_cdr (arg1);
154 bytecode_lo4--;
157 arg1 = ram_get_car (arg1);
159 PUSH_ARG1();
161 DISPATCH();
163 /***************************************************************************/
164 CASE(PUSH_GLOBAL);
166 IF_TRACE(printf(" (push-global %d)\n", bytecode_lo4));
168 arg1 = get_global (bytecode_lo4);
170 PUSH_ARG1();
172 DISPATCH();
174 /***************************************************************************/
175 CASE(SET_GLOBAL);
177 IF_TRACE(printf(" (set-global %d)\n", bytecode_lo4));
179 set_global (bytecode_lo4, POP());
181 DISPATCH();
183 /***************************************************************************/
184 CASE(CALL);
186 IF_TRACE(printf(" (call %d)\n", bytecode_lo4));
188 na = bytecode_lo4;
190 pop_procedure ();
191 handle_arity_and_rest_param ();
192 build_env ();
193 save_cont ();
195 env = arg1;
196 pc = entry;
198 arg1 = OBJ_FALSE;
200 DISPATCH();
202 /***************************************************************************/
203 CASE(JUMP);
205 IF_TRACE(printf(" (jump %d)\n", bytecode_lo4));
207 na = bytecode_lo4;
209 pop_procedure ();
210 handle_arity_and_rest_param ();
211 build_env ();
213 env = arg1;
214 pc = entry;
216 arg1 = OBJ_FALSE;
218 DISPATCH();
220 /***************************************************************************/
221 CASE(LABEL_INSTR);
223 switch (bytecode_lo4) {
224 case 0: // call-toplevel
225 FETCH_NEXT_BYTECODE();
226 arg2 = bytecode;
228 FETCH_NEXT_BYTECODE();
230 IF_TRACE(printf(" (call-toplevel 0x%04x)\n",
231 ((arg2 << 8) | bytecode) + CODE_START));
233 entry = (arg2 << 8) + bytecode + CODE_START;
234 arg1 = OBJ_NULL;
236 na = rom_get (entry++);
238 build_env ();
239 save_cont ();
241 env = arg1;
242 pc = entry;
244 arg1 = OBJ_FALSE;
245 arg2 = OBJ_FALSE;
247 break;
249 case 1: // jump-toplevel
250 FETCH_NEXT_BYTECODE();
251 arg2 = bytecode;
253 FETCH_NEXT_BYTECODE();
255 IF_TRACE(printf(" (jump-toplevel 0x%04x)\n",
256 ((arg2 << 8) | bytecode) + CODE_START));
258 entry = (arg2 << 8) + bytecode + CODE_START;
259 arg1 = OBJ_NULL;
261 na = rom_get (entry++);
263 build_env ();
265 env = arg1;
266 pc = entry;
268 arg1 = OBJ_FALSE;
269 arg2 = OBJ_FALSE;
271 break;
273 case 2: // goto
274 FETCH_NEXT_BYTECODE();
275 arg2 = bytecode;
277 FETCH_NEXT_BYTECODE();
279 IF_TRACE(printf(" (goto 0x%04x)\n",
280 (arg2 << 8) + bytecode + CODE_START));
282 pc = (arg2 << 8) + bytecode + CODE_START;
284 break;
286 case 3: // goto-if-false
287 FETCH_NEXT_BYTECODE();
288 arg2 = bytecode;
290 FETCH_NEXT_BYTECODE();
292 IF_TRACE(printf(" (goto-if-false 0x%04x)\n",
293 (arg2 << 8) + bytecode + CODE_START));
295 if (POP() == OBJ_FALSE)
296 pc = (arg2 << 8) + bytecode + CODE_START;
298 break;
300 case 4: // closure
301 FETCH_NEXT_BYTECODE();
302 arg2 = bytecode;
304 FETCH_NEXT_BYTECODE();
306 IF_TRACE(printf(" (closure 0x%04x)\n", (arg2 << 8) | bytecode));
308 arg3 = POP(); // env
310 entry = (arg2 << 8) | bytecode;
312 arg1 = alloc_ram_cell_init (CLOSURE_FIELD0 | (arg2 >> 3),
313 ((arg2 & 0x07) << 5) | (bytecode >> 3),
314 ((bytecode &0x07) <<5) |((arg3 &0x1f00) >>8),
315 arg3 & 0xff);
317 PUSH_ARG1();
319 arg2 = OBJ_FALSE;
320 arg3 = OBJ_FALSE;
322 break;
324 case 5: // call-toplevel-short
325 FETCH_NEXT_BYTECODE(); // TODO the short version have a lot in common with the long ones, abstract ?
326 // TODO short instructions don't work at the moment
327 IF_TRACE(printf(" (call-toplevel-short 0x%04x)\n",
328 pc + bytecode + CODE_START));
330 entry = pc + bytecode + CODE_START;
331 arg1 = OBJ_NULL;
333 na = rom_get (entry++);
335 build_env ();
336 save_cont ();
338 env = arg1;
339 pc = entry;
341 arg1 = OBJ_FALSE;
343 break;
345 case 6: // jump-toplevel-short
346 FETCH_NEXT_BYTECODE();
348 IF_TRACE(printf(" (jump-toplevel-short 0x%04x)\n",
349 pc + bytecode + CODE_START));
351 entry = pc + bytecode + CODE_START;
352 arg1 = OBJ_NULL;
354 na = rom_get (entry++);
356 build_env ();
358 env = arg1;
359 pc = entry;
361 arg1 = OBJ_FALSE;
363 break;
365 case 7: // goto-short
366 FETCH_NEXT_BYTECODE();
368 IF_TRACE(printf(" (goto-short 0x%04x)\n", pc + bytecode + CODE_START));
370 pc = pc + bytecode + CODE_START;
372 break;
374 case 8: // goto-if-false-short
375 FETCH_NEXT_BYTECODE();
377 IF_TRACE(printf(" (goto-if-false-short 0x%04x)\n",
378 pc + bytecode + CODE_START));
380 if (POP() == OBJ_FALSE)
381 pc = pc + bytecode + CODE_START;
383 break;
385 case 9: // closure-short
386 FETCH_NEXT_BYTECODE();
388 IF_TRACE(printf(" (closure-short 0x%04x)\n", pc + bytecode));
390 arg3 = POP(); // env
392 entry = pc + bytecode;
394 arg1 = alloc_ram_cell_init (CLOSURE_FIELD0 | (arg2 >> 3),
395 ((arg2 & 0x07) << 5) | (bytecode >> 3),
396 ((bytecode &0x07) <<5) |((arg3 &0x1f00) >>8),
397 arg3 & 0xff);
399 PUSH_ARG1();
401 arg3 = OBJ_FALSE;
403 break;
405 #if 0
406 case 10:
407 break;
408 case 11:
409 break;
410 case 12:
411 break;
412 case 13:
413 break;
414 #endif
415 case 14: // push_global [long]
416 FETCH_NEXT_BYTECODE();
418 IF_TRACE(printf(" (push-global [long] %d)\n", bytecode));
420 arg1 = get_global (bytecode);
422 PUSH_ARG1();
424 break;
426 case 15: // set_global [long]
427 FETCH_NEXT_BYTECODE();
429 IF_TRACE(printf(" (set-global [long] %d)\n", bytecode));
431 set_global (bytecode, POP());
433 break;
436 DISPATCH();
438 /***************************************************************************/
439 CASE(PUSH_CONSTANT_LONG);
441 /* push-constant [long] */
443 FETCH_NEXT_BYTECODE();
445 IF_TRACE(printf(" (push [long] 0x%04x)\n", (bytecode_lo4 << 8) + bytecode));
447 arg1 = (bytecode_lo4 << 8) | bytecode;
448 PUSH_ARG1();
450 DISPATCH();
452 /***************************************************************************/
453 CASE(FREE1); // FREE
455 DISPATCH();
457 /***************************************************************************/
458 CASE(FREE2); // FREE
460 DISPATCH();
462 /***************************************************************************/
463 CASE(PRIM1);
465 IF_TRACE(printf(" (%s)\n", prim_name[bytecode_lo4]));
467 switch (bytecode_lo4) {
468 case 0:
469 arg1 = POP(); prim_numberp (); PUSH_ARG1(); break;
470 case 1:
471 arg2 = POP(); arg1 = POP(); prim_add (); PUSH_ARG1(); break;
472 case 2:
473 arg2 = POP(); arg1 = POP(); prim_sub (); PUSH_ARG1(); break;
474 case 3:
475 arg2 = POP(); arg1 = POP(); prim_mul (); PUSH_ARG1(); break;
476 case 4:
477 arg2 = POP(); arg1 = POP(); prim_div (); PUSH_ARG1(); break;
478 case 5:
479 arg2 = POP(); arg1 = POP(); prim_rem (); PUSH_ARG1(); break;
480 case 6:
481 arg1 = POP(); prim_neg (); PUSH_ARG1(); break;
482 case 7:
483 arg2 = POP(); arg1 = POP(); prim_eq (); PUSH_ARG1(); break;
484 case 8:
485 arg2 = POP(); arg1 = POP(); prim_lt (); PUSH_ARG1(); break;
486 case 9:
487 arg2 = POP(); arg1 = POP(); prim_ior (); PUSH_ARG1(); break; // TODO swap these 2 and geq, leq ?
488 case 10:
489 arg2 = POP(); arg1 = POP(); prim_gt (); PUSH_ARG1(); break;
490 case 11:
491 arg2 = POP(); arg1 = POP(); prim_xor (); PUSH_ARG1(); break;
492 case 12:
493 arg1 = POP(); prim_pairp (); PUSH_ARG1(); break;
494 case 13:
495 arg2 = POP(); arg1 = POP(); prim_cons (); PUSH_ARG1(); break;
496 case 14:
497 arg1 = POP(); prim_car (); PUSH_ARG1(); break;
498 case 15:
499 arg1 = POP(); prim_cdr (); PUSH_ARG1(); break;
502 DISPATCH();
504 /***************************************************************************/
505 CASE(PRIM2);
507 IF_TRACE(printf(" (%s)\n", prim_name[bytecode_lo4+16]));
509 switch (bytecode_lo4) {
510 case 0:
511 arg2 = POP(); arg1 = POP(); prim_set_car (); break;
512 case 1:
513 arg2 = POP(); arg1 = POP(); prim_set_cdr (); break;
514 case 2:
515 arg1 = POP(); prim_nullp (); PUSH_ARG1(); break;
516 case 3:
517 arg2 = POP(); arg1 = POP(); prim_eqp (); PUSH_ARG1(); break;
518 case 4:
519 arg1 = POP(); prim_not (); PUSH_ARG1(); break;
520 case 5:
521 /* prim #%get-cont */
522 arg1 = cont;
523 PUSH_ARG1();
524 break;
525 case 6:
526 /* prim #%graft-to-cont */
528 arg1 = POP(); /* thunk to call */
529 cont = POP(); /* continuation */
531 PUSH_ARG1();
533 na = 0;
535 pop_procedure ();
536 handle_arity_and_rest_param ();
537 build_env ();
539 env = arg1;
540 pc = entry;
542 arg1 = OBJ_FALSE;
544 break;
545 case 7:
546 /* prim #%return-to-cont */
548 arg1 = POP(); /* value to return */
549 cont = POP(); /* continuation */
551 arg2 = ram_get_cdr (cont);
553 pc = ram_get_entry (arg2);
555 env = ram_get_cdr (arg2);
556 cont = ram_get_car (cont);
558 PUSH_ARG1();
559 arg2 = OBJ_FALSE;
561 break;
562 case 8:
563 /* prim #%halt */
564 return;
565 case 9:
566 /* prim #%symbol? */
567 arg1 = POP(); prim_symbolp (); PUSH_ARG1(); break;
568 case 10:
569 /* prim #%string? */
570 arg1 = POP(); prim_stringp (); PUSH_ARG1(); break;
571 case 11:
572 /* prim #%string->list */
573 arg1 = POP(); prim_string2list (); PUSH_ARG1(); break;
574 case 12:
575 /* prim #%list->string */
576 arg1 = POP(); prim_list2string (); PUSH_ARG1(); break;
577 case 13:
578 /* prim #%make-u8vector */
579 arg2 = POP(); arg1 = POP(); prim_make_u8vector (); PUSH_ARG1(); break;
580 case 14:
581 /* prim #%u8vector-ref */
582 arg2 = POP(); arg1 = POP(); prim_u8vector_ref (); PUSH_ARG1(); break;
583 case 15:
584 /* prim #%u8vector-set! */
585 arg3 = POP(); arg2 = POP(); arg1 = POP(); prim_u8vector_set (); break;
588 DISPATCH();
590 /***************************************************************************/
591 CASE(PRIM3);
593 IF_TRACE(printf(" (%s)\n", prim_name[bytecode_lo4+32]));
595 switch (bytecode_lo4) {
596 case 0:
597 /* prim #%print */
598 arg1 = POP();
599 prim_print ();
600 break;
601 case 1:
602 /* prim #%clock */
603 prim_clock (); PUSH_ARG1(); break;
604 case 2:
605 /* prim #%motor */
606 arg2 = POP(); arg1 = POP(); prim_motor (); break;
607 case 3:
608 /* prim #%led */
609 arg3 = POP(); arg2 = POP(); arg1 = POP(); prim_led (); ;break;
610 case 4:
611 /* prim #%led2-color */
612 arg1 = POP(); prim_led2_color (); break;
613 case 5:
614 /* prim #%getchar-wait */
615 arg2 = POP(); arg1 = POP(); prim_getchar_wait (); PUSH_ARG1(); break;
616 case 6:
617 /* prim #%putchar */
618 arg2 = POP(); arg1 = POP(); prim_putchar (); break;
619 case 7:
620 /* prim #%beep */
621 arg2 = POP(); arg1 = POP(); prim_beep (); break;
622 case 8:
623 /* prim #%adc */
624 arg1 = POP(); prim_adc (); PUSH_ARG1(); break;
625 case 9:
626 /* prim #%u8vector? */
627 arg1 = POP(); prim_u8vectorp (); PUSH_ARG1(); break;
628 case 10:
629 /* prim #%sernum */
630 prim_sernum (); PUSH_ARG1(); break;
631 case 11:
632 /* prim #%u8vector-length */
633 arg1 = POP(); prim_u8vector_length (); PUSH_ARG1(); break;
634 case 12:
635 /* prim #%u8vector-copy! */
636 arg5 = POP(); arg4 = POP(); arg3 = POP(); arg2 = POP(); arg1 = POP();
637 prim_u8vector_copy (); break;
638 break;
639 case 13:
640 /* shift */
641 arg1 = POP();
642 POP();
643 PUSH_ARG1();
644 break;
645 case 14:
646 /* pop */
647 POP();
648 break;
649 case 15:
650 /* return */
651 arg1 = POP();
652 arg2 = ram_get_cdr (cont);
653 pc = ram_get_entry (arg2);
654 env = ram_get_cdr (arg2);
655 cont = ram_get_car (cont);
656 PUSH_ARG1();
657 arg2 = OBJ_FALSE;
658 break;
661 DISPATCH();
663 /***************************************************************************/
665 CASE(PRIM4);
667 IF_TRACE(printf(" (%s)\n", prim_name[bytecode_lo4]));
669 switch (bytecode_lo4) {
670 case 0:
671 /* prim #%boolean? */
672 arg1 = POP(); prim_booleanp (); PUSH_ARG1(); break;
673 case 1:
674 /* prim #%network-init */
675 prim_network_init (); break;
676 case 2:
677 /* prim #%network-cleanup */
678 prim_network_cleanup (); break;
679 case 3:
680 /* prim #%receive-packet-to-u8vector */
681 arg1 = POP(); prim_receive_packet_to_u8vector (); PUSH_ARG1(); break;
682 case 4:
683 /* prim #%send-packet-from-u8vector */
684 arg2 = POP(); arg1 = POP(); prim_send_packet_from_u8vector ();
685 PUSH_ARG1(); break;
686 case 5:
687 /* prim #% <= */
688 arg2 = POP(); arg1 = POP(); prim_leq (); PUSH_ARG1(); break;
689 break;
690 case 6:
691 /* prim #% >= */
692 arg2 = POP(); arg1 = POP(); prim_geq (); PUSH_ARG1(); break;
693 break;
694 #if 0
695 case 7:
696 break;
697 case 8:
698 break;
699 case 9:
700 break;
701 case 10:
702 break;
703 case 11:
704 break;
705 case 12:
706 break;
707 case 13:
708 break;
709 case 14:
710 break;
711 case 15:
712 break;
713 #endif
716 DISPATCH();
718 /***************************************************************************/
720 END_DISPATCH();