1 /* file: "dispatch.c" */
4 * Copyright 2004-2009 by Marc Feeley and Vincent St-Amour, All Rights Reserved.
7 #include "picobit-vm.h"
10 env
= cons (arg1
, env
);
15 obj o
= ram_get_car (env
);
16 env
= ram_get_cdr (env
);
20 void pop_procedure () {
24 if (!RAM_CLOSURE(arg1
))
25 TYPE_ERROR("pop_procedure.0", "procedure");
27 entry
= ram_get_entry (arg1
) + CODE_START
;
30 TYPE_ERROR("pop_procedure.1", "procedure");
33 uint8
handle_arity_and_rest_param (uint8 na
) {
36 np
= rom_get (entry
++);
39 arg1
= ram_get_car(arg1
); // closed environment
41 if ((np
& 0x80) == 0) {
43 ERROR("handle_arity_and_rest_param.0", "wrong number of arguments");
49 ERROR("handle_arity_and_rest_param.1", "wrong number of arguments");
56 arg3
= cons (arg4
, arg3
);
62 arg1
= cons (arg3
, arg1
);
69 uint8
build_env (uint8 na
) {
73 arg1
= cons (arg3
, arg1
);
82 // the second half is a closure
83 arg3
= alloc_ram_cell_init (CLOSURE_FIELD0
| (env
>> 8),
87 cont
= alloc_ram_cell_init (COMPOSITE_FIELD0
| (cont
>> 8),
89 CONTINUATION_FIELD2
| (arg3
>> 8),
95 pc
= rom_get (CODE_START
+2);
96 pc
= (CODE_START
+ 4) + (pc
<< 2);
98 glovars
= rom_get (CODE_START
+3); // number of global variables
103 IF_TRACE(show_state (pc
));
104 FETCH_NEXT_BYTECODE();
105 bytecode_hi4
= bytecode
& 0xf0;
106 bytecode_lo4
= bytecode
& 0x0f;
108 switch (bytecode_hi4
>> 4) {
110 /*************************************************************************/
111 case PUSH_CONSTANT1
:
113 IF_TRACE(printf(" (push-constant "); show (bytecode_lo4
); printf (")\n"));
121 /*************************************************************************/
122 case PUSH_CONSTANT2
:
124 IF_TRACE(printf(" (push-constant "); show (bytecode_lo4
+16); printf (")\n"));
125 arg1
= bytecode_lo4
+16;
131 /*************************************************************************/
134 IF_TRACE(printf(" (push-stack %d)\n", bytecode_lo4
));
138 while (bytecode_lo4
!= 0) {
139 arg1
= ram_get_cdr (arg1
);
143 arg1
= ram_get_car (arg1
);
149 /*************************************************************************/
152 IF_TRACE(printf(" (push-stack %d)\n", bytecode_lo4
+16));
158 while (bytecode_lo4
!= 0) {
159 arg1
= ram_get_cdr (arg1
);
163 arg1
= ram_get_car (arg1
);
169 /*************************************************************************/
172 IF_TRACE(printf(" (push-global %d)\n", bytecode_lo4
));
174 arg1
= get_global (bytecode_lo4
);
180 /*************************************************************************/
183 IF_TRACE(printf(" (set-global %d)\n", bytecode_lo4
));
185 set_global (bytecode_lo4
, pop());
189 /*************************************************************************/
192 IF_TRACE(printf(" (call %d)\n", bytecode_lo4
));
195 build_env (handle_arity_and_rest_param (bytecode_lo4
));
205 /*************************************************************************/
208 IF_TRACE(printf(" (jump %d)\n", bytecode_lo4
));
211 build_env (handle_arity_and_rest_param (bytecode_lo4
));
220 /*************************************************************************/
223 switch (bytecode_lo4
) {
224 case 0: // call-toplevel
225 FETCH_NEXT_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
;
236 build_env (rom_get (entry
++));
247 case 1: // jump-toplevel
248 FETCH_NEXT_BYTECODE();
251 FETCH_NEXT_BYTECODE();
253 IF_TRACE(printf(" (jump-toplevel 0x%04x)\n",
254 ((arg2
<< 8) | bytecode
) + CODE_START
));
256 entry
= (arg2
<< 8) + bytecode
+ CODE_START
;
259 build_env (rom_get (entry
++));
270 FETCH_NEXT_BYTECODE();
273 FETCH_NEXT_BYTECODE();
275 IF_TRACE(printf(" (goto 0x%04x)\n",
276 (arg2
<< 8) + bytecode
+ CODE_START
));
278 pc
= (arg2
<< 8) + bytecode
+ CODE_START
;
282 case 3: // goto-if-false
283 FETCH_NEXT_BYTECODE();
286 FETCH_NEXT_BYTECODE();
288 IF_TRACE(printf(" (goto-if-false 0x%04x)\n",
289 (arg2
<< 8) + bytecode
+ CODE_START
));
291 if (pop() == OBJ_FALSE
)
292 pc
= (arg2
<< 8) + bytecode
+ CODE_START
;
297 FETCH_NEXT_BYTECODE();
300 FETCH_NEXT_BYTECODE();
302 entry
= (arg2
<< 8) | bytecode
;
304 IF_TRACE(printf(" (closure 0x%04x)\n", entry
));
308 arg1
= alloc_ram_cell_init (CLOSURE_FIELD0
| (arg3
>> 8),
321 case 5: // call-toplevel-rel8
322 FETCH_NEXT_BYTECODE(); // TODO the short version have a lot in common with the long ones, abstract ?
324 IF_TRACE(printf(" (call-toplevel-rel8 0x%04x)\n", pc
+ bytecode
- 128));
326 entry
= pc
+ bytecode
- 128;
329 build_env (rom_get (entry
++));
339 case 6: // jump-toplevel-rel8
340 FETCH_NEXT_BYTECODE();
342 IF_TRACE(printf(" (jump-toplevel-rel8 0x%04x)\n", pc
+ bytecode
- 128));
344 entry
= pc
+ bytecode
- 128;
347 build_env (rom_get (entry
++));
357 FETCH_NEXT_BYTECODE();
359 IF_TRACE(printf(" (goto-rel8 0x%04x)\n", pc
+ bytecode
- 128));
361 pc
= pc
+ bytecode
- 128;
365 case 8: // goto-if-false-rel8
366 FETCH_NEXT_BYTECODE();
368 IF_TRACE(printf(" (goto-if-false-rel8 0x%04x)\n", pc
+ bytecode
- 128));
370 if (pop() == OBJ_FALSE
)
371 pc
= pc
+ bytecode
- 128;
375 // TODO why does this not work? don't worry about it now, as it is disabled in the compiler
377 case 9: // closure-rel8
378 FETCH_NEXT_BYTECODE();
380 entry
= pc
+ bytecode
- 128;
382 IF_TRACE(printf(" (closure-rel8 0x%04x)\n", entry
));
386 arg1
= alloc_ram_cell_init (CLOSURE_FIELD0
| (entry
>> 11),
388 ((entry
& 0x07) << 5) | ((arg3
>> 8) & 0x1f),
408 case 14: // push_global [long]
409 FETCH_NEXT_BYTECODE();
411 IF_TRACE(printf(" (push-global [long] %d)\n", bytecode
));
413 arg1
= get_global (bytecode
);
419 case 15: // set_global [long]
420 FETCH_NEXT_BYTECODE();
422 IF_TRACE(printf(" (set-global [long] %d)\n", bytecode
));
424 set_global (bytecode
, pop());
431 /*************************************************************************/
432 case PUSH_CONSTANT_LONG
:
434 /* push-constant [long] */
436 FETCH_NEXT_BYTECODE();
438 IF_TRACE(printf(" (push [long] 0x%04x)\n", (bytecode_lo4
<< 8) + bytecode
));
440 // necessary since SIXPIC would have kept the result of the shift at 8 bits
442 arg1
= (arg1
<< 8) | bytecode
;
447 /*************************************************************************/
449 case JUMP_TOPLEVEL_REL4
:
451 IF_TRACE(printf(" (jump-toplevel-rel4 0x%04x)\n", pc
+ (bytecode
& 0x0f)));
453 entry
= pc
+ (bytecode
& 0x0f);
456 build_env (rom_get (entry
++));
465 /*************************************************************************/
467 case GOTO_IF_FALSE_REL4
:
469 IF_TRACE(printf(" (goto-if-false-rel4 0x%04x)\n", pc
+ (bytecode
& 0x0f)));
471 if (pop() == OBJ_FALSE
)
472 pc
= pc
+ (bytecode
& 0x0f);
476 /*************************************************************************/
479 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
]));
481 switch (bytecode_lo4
) {
483 arg1
= pop(); prim_numberp (); push_arg1(); break;
485 arg2
= pop(); arg1
= pop(); prim_add (); push_arg1(); break;
487 arg2
= pop(); arg1
= pop(); prim_sub (); push_arg1(); break;
489 arg2
= pop(); arg1
= pop(); prim_mul_non_neg (); push_arg1(); break;
491 arg2
= pop(); arg1
= pop(); prim_div_non_neg (); push_arg1(); break;
493 arg2
= pop(); arg1
= pop(); prim_rem (); push_arg1(); break;
499 arg2
= pop(); arg1
= pop(); prim_eq (); push_arg1(); break;
501 arg2
= pop(); arg1
= pop(); prim_lt (); push_arg1(); break;
507 arg2
= pop(); arg1
= pop(); prim_gt (); push_arg1(); break;
513 arg1
= pop(); prim_pairp (); push_arg1(); break;
515 arg2
= pop(); arg1
= pop(); prim_cons (); push_arg1(); break;
517 arg1
= pop(); prim_car (); push_arg1(); break;
519 arg1
= pop(); prim_cdr (); push_arg1(); break;
524 /*************************************************************************/
527 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
+16]));
529 switch (bytecode_lo4
) {
531 arg2
= pop(); arg1
= pop(); prim_set_car (); break;
533 arg2
= pop(); arg1
= pop(); prim_set_cdr (); break;
535 arg1
= pop(); prim_nullp (); push_arg1(); break;
537 arg2
= pop(); arg1
= pop(); prim_eqp (); push_arg1(); break;
539 arg1
= pop(); prim_not (); push_arg1(); break;
541 /* prim #%get-cont */
546 /* prim #%graft-to-cont */
548 arg1
= pop(); /* thunk to call */
549 cont
= pop(); /* continuation */
554 build_env (handle_arity_and_rest_param (0));
563 /* prim #%return-to-cont */
565 arg1
= pop(); /* value to return */
566 cont
= pop(); /* continuation */
568 arg2
= ram_get_cdr (cont
);
570 pc
= ram_get_entry (arg2
);
572 env
= ram_get_car (arg2
);
573 cont
= ram_get_car (cont
);
584 arg1
= pop(); prim_symbolp (); push_arg1(); break;
587 arg1
= pop(); prim_stringp (); push_arg1(); break;
589 /* prim #%string->list */
590 arg1
= pop(); prim_string2list (); push_arg1(); break;
592 /* prim #%list->string */
593 arg1
= pop(); prim_list2string (); push_arg1(); break;
595 /* prim #%make-u8vector */
596 // not exactly like the standard Scheme function.
597 // only takes one argument, and does not fill the vector
598 arg1
= pop(); prim_make_u8vector (); push_arg1(); break;
600 /* prim #%u8vector-ref */
601 arg2
= pop(); arg1
= pop(); prim_u8vector_ref (); push_arg1(); break;
603 /* prim #%u8vector-set! */
604 arg3
= pop(); arg2
= pop(); arg1
= pop(); prim_u8vector_set (); break;
609 /*************************************************************************/
612 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
+32]));
614 switch (bytecode_lo4
) {
622 prim_clock (); push_arg1(); break;
625 arg2
= pop(); arg1
= pop(); prim_motor (); break;
628 arg3
= pop(); arg2
= pop(); arg1
= pop(); prim_led (); ;break;
630 /* prim #%led2-color */
631 arg1
= pop(); prim_led2_color (); break;
633 /* prim #%getchar-wait */
634 arg2
= pop(); arg1
= pop(); prim_getchar_wait (); push_arg1(); break;
637 arg2
= pop(); arg1
= pop(); prim_putchar (); break;
640 arg2
= pop(); arg1
= pop(); prim_beep (); break;
643 arg1
= pop(); prim_adc (); push_arg1(); break;
645 /* prim #%u8vector? */
646 arg1
= pop(); prim_u8vectorp (); push_arg1(); break;
649 prim_sernum (); push_arg1(); break;
651 /* prim #%u8vector-length */
652 arg1
= pop(); prim_u8vector_length (); push_arg1(); break;
669 arg2
= ram_get_cdr (cont
);
670 pc
= ram_get_entry (arg2
);
671 env
= ram_get_car (arg2
);
672 cont
= ram_get_car (cont
);
680 /*************************************************************************/
684 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
]));
686 switch (bytecode_lo4
) {
688 /* prim #%boolean? */
689 arg1
= pop(); prim_booleanp (); push_arg1(); break;
692 /* prim #%network-init */
693 prim_network_init (); break;
695 /* prim #%network-cleanup */
696 prim_network_cleanup (); break;
698 /* prim #%receive-packet-to-u8vector */
699 arg1
= pop(); prim_receive_packet_to_u8vector (); push_arg1(); break;
701 /* prim #%send-packet-from-u8vector */
702 arg2
= pop(); arg1
= pop(); prim_send_packet_from_u8vector ();
706 arg2
= pop(); arg1
= pop(); prim_ior (); push_arg1(); break;
709 arg2
= pop(); arg1
= pop(); prim_xor (); push_arg1(); break;
735 /*************************************************************************/