1 /* file: "picobit-vm.c" */
4 * Copyright 2004 by Marc Feeley, All Rights Reserved.
8 * 15/08/2004 Release of version 1
9 * 6/07/2008 Modified for PICOBOARD2_R3
15 /*---------------------------------------------------------------------------*/
20 typedef unsigned char uint8
;
21 typedef unsigned short uint16
;
22 typedef unsigned long uint32
;
24 /*---------------------------------------------------------------------------*/
44 static volatile near uint8 FW_VALUE_UP @
0x33;
45 static volatile near uint8 FW_VALUE_HI @
0x33;
46 static volatile near uint8 FW_VALUE_LO @
0x33;
48 #define ACTIVITY_LED1_LAT LATB
49 #define ACTIVITY_LED1_BIT 5
50 #define ACTIVITY_LED2_LAT LATB
51 #define ACTIVITY_LED2_BIT 4
52 static volatile near bit ACTIVITY_LED1 @
((unsigned)&ACTIVITY_LED1_LAT
*8)+ACTIVITY_LED1_BIT
;
53 static volatile near bit ACTIVITY_LED2 @
((unsigned)&ACTIVITY_LED2_LAT
*8)+ACTIVITY_LED2_BIT
;
64 #include <sys/types.h>
65 #include <sys/timeb.h>
74 /*---------------------------------------------------------------------------*/
78 #define CODE_START 0x5000
84 #define IF_GC_TRACE(x)
87 #define IF_GC_TRACE(x)
90 /*---------------------------------------------------------------------------*/
95 #define ERROR(msg) halt_with_error()
96 #define TYPE_ERROR(type) halt_with_error()
103 #define ERROR(msg) error (msg)
104 #define TYPE_ERROR(type) type_error (type)
106 void error (char *msg
)
108 printf ("ERROR: %s\n", msg
);
112 void type_error (char *type
)
114 printf ("ERROR: An argument of type %s was expected\n", type
);
121 /*---------------------------------------------------------------------------*/
129 typedef uint16 ram_addr
;
130 typedef uint16 rom_addr
;
134 /*---------------------------------------------------------------------------*/
136 #define MIN_RAM_ENCODING 128
137 #define MAX_RAM_ENCODING 8192
138 // TODO some space in rom is not used, use for fixnums ?
139 #define RAM_BYTES ((MAX_RAM_ENCODING - MIN_RAM_ENCODING + 1)*4)
141 // TODO change if we change the proportion of rom and ram addresses
143 #define OBJ_TO_RAM_ADDR(o,f) (((ram_addr)((uint16)(o) - MIN_RAM_ENCODING) << 2) + (f))
144 #define OBJ_TO_ROM_ADDR(o,f) (((rom_addr)((uint8)(o) - MIN_ROM_ENCODING) << 2) + (CODE_START + 4 + (f)))
151 #pragma udata picobit_heap=0x200
152 uint8 ram_mem
[RAM_BYTES
];
156 #define ram_get(a) *(uint8*)(a+0x200)
157 #define ram_set(a,x) *(uint8*)(a+0x200) = (x)
164 uint8 ram_mem
[RAM_BYTES
];
166 #define ram_get(a) ram_mem[a]
167 #define ram_set(a,x) ram_mem[a] = (x)
172 /*---------------------------------------------------------------------------*/
179 uint8
rom_get (rom_addr a
)
181 return *(rom uint8
*)a
;
189 #define ROM_BYTES 8192
191 uint8 rom_mem
[ROM_BYTES
] =
194 #define PUTCHAR_LIGHT_not
197 0xFB, 0xD7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x32
198 , 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
199 , 0x08, 0x50, 0x80, 0x16, 0xFE, 0xE8, 0x00, 0xFC
200 , 0x32, 0x80, 0x2D, 0xFE, 0xFC, 0x31, 0x80, 0x43
201 , 0xFE, 0xFC, 0x33, 0x80, 0x2D, 0xFE, 0xFC, 0x31
202 , 0x80, 0x43, 0xFE, 0x90, 0x16, 0x01, 0x20, 0xFC
203 , 0x32, 0xE3, 0xB0, 0x37, 0x09, 0xF3, 0xFF, 0x20
204 , 0xFC, 0x33, 0xE3, 0xB0, 0x40, 0x0A, 0xF3, 0xFF
205 , 0x08, 0xF3, 0xFF, 0x01, 0x40, 0x21, 0xD1, 0x00
206 , 0x02, 0xC0, 0x4C, 0x71, 0x01, 0x20, 0x50, 0x90
207 , 0x51, 0x00, 0xF1, 0x40, 0xD8, 0xB0, 0x59, 0x90
211 0xFB, 0xD7, 0x00, 0x00, 0x80, 0x08, 0xFE, 0xE8
212 , 0x00, 0xF6, 0xF5, 0x90, 0x08
216 uint8
rom_get (rom_addr a
)
218 return rom_mem
[a
-CODE_START
];
223 obj globals
[GLOVARS
];
225 /*---------------------------------------------------------------------------*/
233 fixnum n MIN_FIXNUM -> 3 ... MAX_FIXNUM -> 3 + (MAX_FIXNUM-MIN_FIXNUM)
234 TODO do we want 0..127 as fixnums ? would reduce number of ra/om objects
235 rom object 4 + (MAX_FIXNUM-MIN_FIXNUM) ... MIN_RAM_ENCODING-1
236 ram object MIN_RAM_ENCODING ... 4095 TODO was 255, now we have 12 bits
238 layout of memory allocated objects:
240 G's represent mark bits used by the gc TODO change GC, and does not use the same bits
242 bignum n 00G00000 uuuuuuuu hhhhhhhh llllllll (24 bit signed integer)
243 TODO we could have 29-bit integers
245 pair 1GGaaaaa aaaaaaaa 000ddddd dddddddd
246 TODO was 00000010 aaaaaaaa aaaadddd dddddddd
249 gives an address space of 2^13 * 4 = 32k (not all of it is for RAM, though)
251 symbol 1GG00000 00000000 00100000 00000000
253 string 1GG***** *chars** 01000000 00000000
255 vector 1GG***** *elems** 01100000 00000000 TODO not used yet
257 closure 01Gxxxxx xxxxxxxx aaaaaaaa aaaaaaaa TODO OLD
258 closure 01Gaaaaa aaaaaaaa aaaxxxxx xxxxxxxx
259 0x5ff<a<0x4000 is entry
260 x is pointer to environment
261 the reason why the environment is on the cdr (and the entry is split on 3
262 bytes) is that, when looking for a variable, a closure is considered to be a
263 pair. The compiler adds an extra offset to any variable in the closure's
264 environment, so the car of the closure (which doesn't really exist) is never
265 checked, but the cdr is followed to find the other bindings
267 continuation 01Gxxxxx xxxxxxxx aaaaaaaa aaaaaaaa 0x5ff<a<0x4000 is pc TODO old
268 continuation 01Gxxxxx xxxxxxxx 100yyyyy yyyyyyyy
269 x is parent continuation
270 y is pointer to the second half, which is a closure (contains env and entry)
272 An environment is a list of objects built out of pairs. On entry to
273 a procedure the environment is the list of parameters to which is
274 added the environment of the closure being called.
276 The first byte at the entry point of a procedure gives the arity of
279 n = 0 to 127 -> procedure has n parameters (no rest parameter)
280 n = -128 to -1 -> procedure has -n parameters, the last is
288 #define MIN_FIXNUM_ENCODING 3
289 #define MIN_FIXNUM (-5)
290 #define MAX_FIXNUM 40
291 #define MIN_ROM_ENCODING (MIN_FIXNUM_ENCODING+MAX_FIXNUM-MIN_FIXNUM+1)
293 #define ENCODE_FIXNUM(n) ((obj)(n) + (MIN_FIXNUM_ENCODING - MIN_FIXNUM))
294 #define DECODE_FIXNUM(o) ((int32)(o) - (MIN_FIXNUM_ENCODING - MIN_FIXNUM))
297 #define IN_RAM(o) ((o) >= MIN_RAM_ENCODING)
298 #define IN_ROM(o) ((int8)(o) >= MIN_ROM_ENCODING)
301 // bignum first byte : 00G00000
302 #define BIGNUM_FIELD0 0
303 #define RAM_BIGNUM(o) ((ram_get_field0 (o) & 0xc0) == BIGNUM_FIELD0)
304 #define ROM_BIGNUM(o) ((rom_get_field0 (o) & 0xc0) == BIGNUM_FIELD0)
306 // composite first byte : 1GGxxxxx
307 #define COMPOSITE_FIELD0 0x80
308 #define RAM_COMPOSITE(o) ((ram_get_field0 (o) & 0x80) == COMPOSITE_FIELD0)
309 #define ROM_COMPOSITE(o) ((rom_get_field0 (o) & 0x80) == COMPOSITE_FIELD0)
311 // pair third byte : 000xxxxx
312 #define PAIR_FIELD2 0
313 #define RAM_PAIR(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == PAIR_FIELD2))
314 #define ROM_PAIR(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == PAIR_FIELD2))
316 // symbol third byte : 001xxxxx
317 #define SYMBOL_FIELD2 0x20
318 #define RAM_SYMBOL(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == SYMBOL_FIELD2))
319 #define ROM_SYMBOL(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == SYMBOL_FIELD2))
321 // string third byte : 010xxxxx
322 #define STRING_FIELD2 0x40
323 #define RAM_STRING(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == STRING_FIELD2))
324 #define ROM_STRING(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == STRING_FIELD2))
326 // vector third byte : 011xxxxx
327 #define VECTOR_FIELD2 0x60
328 #define RAM_VECTOR(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == VECTOR_FIELD2))
329 #define ROM_VECTOR(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == VECTOR_FIELD2))
331 // continuation third byte : 100xxxxx
332 #define CONTINUATION_FIELD2 0x80
333 #define RAM_CONTINUATION(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == CONTINUATION_FIELD2))
334 #define ROM_CONTINUATION(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == CONTINUATION_FIELD2))
336 // closure first byte : 01Gxxxxx
337 #define CLOSURE_FIELD0 0x40
338 #define RAM_CLOSURE(o) ((ram_get_field0 (o) & 0xc0) == CLOSURE_FIELD0)
339 #define ROM_CLOSURE(o) ((rom_get_field0 (o) & 0xc0) == CLOSURE_FIELD0)
341 /*---------------------------------------------------------------------------*/
343 #define RAM_GET_FIELD0_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,0))
344 #define RAM_SET_FIELD0_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,0), val)
345 #define ROM_GET_FIELD0_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,0))
347 #define RAM_GET_GC_TAGS_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x60)
348 #define RAM_SET_GC_TAGS_MACRO(o,tags) \
349 (RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0x9f) | (tags)))
350 #define RAM_SET_GC_TAG0_MACRO(o,tag) \
351 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xdf) | (tag))
352 #define RAM_SET_GC_TAG1_MACRO(o,tag) \
353 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xbf) | (tag))
356 #define RAM_GET_FIELD1_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,1))
357 #define RAM_GET_FIELD2_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,2))
358 #define RAM_GET_FIELD3_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,3))
359 #define RAM_SET_FIELD1_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,1), val)
360 #define RAM_SET_FIELD2_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,2), val)
361 #define RAM_SET_FIELD3_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,3), val)
362 #define ROM_GET_FIELD1_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,1))
363 #define ROM_GET_FIELD2_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,2))
364 #define ROM_GET_FIELD3_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,3))
368 #define RAM_GET_FIELD1_MACRO(o) \
369 (ram_get (OBJ_TO_RAM_ADDR(o,1)) + ((RAM_GET_FIELD0_MACRO(o) & 0x03)<<8))
370 #define RAM_GET_FIELD2_MACRO(o) \
371 (ram_get (OBJ_TO_RAM_ADDR(o,2)) + ((RAM_GET_FIELD0_MACRO(o) & 0x0c)<<6))
372 #define RAM_GET_FIELD3_MACRO(o) \
373 (ram_get (OBJ_TO_RAM_ADDR(o,3)) + ((RAM_GET_FIELD0_MACRO(o) & 0x30)<<4))
374 #define RAM_SET_FIELD1_MACRO(o,val) \
376 ram_set (OBJ_TO_RAM_ADDR(o,1), (val) & 0xff); \
377 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xfc) + (((val) >> 8) & 0x03)); \
379 #define RAM_SET_FIELD2_MACRO(o,val) \
381 ram_set (OBJ_TO_RAM_ADDR(o,2), (val) & 0xff); \
382 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xf3) + (((val) >> 6) & 0x0c)); \
384 #define RAM_SET_FIELD3_MACRO(o,val) \
386 ram_set (OBJ_TO_RAM_ADDR(o,3), (val) & 0xff); \
387 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xcf) + (((val) >> 4) & 0x30)); \
389 #define ROM_GET_FIELD1_MACRO(o) \
390 (rom_get (OBJ_TO_ROM_ADDR(o,1)) + ((ROM_GET_FIELD0_MACRO(o) & 0x03)<<8))
391 #define ROM_GET_FIELD2_MACRO(o) \
392 (rom_get (OBJ_TO_ROM_ADDR(o,2)) + ((ROM_GET_FIELD0_MACRO(o) & 0x0c)<<6))
393 #define ROM_GET_FIELD3_MACRO(o) \
394 (rom_get (OBJ_TO_ROM_ADDR(o,3)) + ((ROM_GET_FIELD0_MACRO(o) & 0x30)<<4))
397 uint8
ram_get_gc_tags (obj o
) { return RAM_GET_GC_TAGS_MACRO(o
); }
398 void ram_set_gc_tags (obj o
, uint8 tags
) { RAM_SET_GC_TAGS_MACRO(o
, tags
); }
399 void ram_set_gc_tag0 (obj o
, uint8 tag
) { RAM_SET_GC_TAG0_MACRO(o
,tag
); }
400 void ram_set_gc_tag1 (obj o
, uint8 tag
) { RAM_SET_GC_TAG1_MACRO(o
,tag
); }
401 uint8
ram_get_field0 (obj o
) { return RAM_GET_FIELD0_MACRO(o
); }
402 word
ram_get_field1 (obj o
) { return RAM_GET_FIELD1_MACRO(o
); } // TODO used to return obj, which used to be the same as words
403 word
ram_get_field2 (obj o
) { return RAM_GET_FIELD2_MACRO(o
); }
404 word
ram_get_field3 (obj o
) { return RAM_GET_FIELD3_MACRO(o
); }
405 void ram_set_field0 (obj o
, uint8 val
) { RAM_SET_FIELD0_MACRO(o
,val
); }
406 void ram_set_field1 (obj o
, word val
) { RAM_SET_FIELD1_MACRO(o
,val
); }
407 void ram_set_field2 (obj o
, word val
) { RAM_SET_FIELD2_MACRO(o
,val
); }
408 void ram_set_field3 (obj o
, word val
) { RAM_SET_FIELD3_MACRO(o
,val
); }
409 uint8
rom_get_field0 (obj o
) { return ROM_GET_FIELD0_MACRO(o
); }
410 word
rom_get_field1 (obj o
) { return ROM_GET_FIELD1_MACRO(o
); }
411 word
rom_get_field2 (obj o
) { return ROM_GET_FIELD2_MACRO(o
); }
412 word
rom_get_field3 (obj o
) { return ROM_GET_FIELD3_MACRO(o
); }
414 obj
ram_get_car (obj o
)
415 { return ((ram_get_field0 (o
) & 0x1f) << 8) | ram_get_field1 (o
); }
416 obj
rom_get_car (obj o
)
417 { return ((rom_get_field0 (o
) & 0x1f) << 8) | rom_get_field1 (o
); }
418 obj
ram_get_cdr (obj o
)
419 { return ((ram_get_field2 (o
) & 0x1f) << 8) | ram_get_field3 (o
); }
420 obj
rom_get_cdr (obj o
)
421 { return ((rom_get_field2 (o
) & 0x1f) << 8) | rom_get_field3 (o
); }
422 void ram_set_car (obj o
, obj val
)
424 ram_set_field0 (o
, ((val
& 0x1f00) >> 8) | (ram_get_field0 (o
) & 0xc0));
425 ram_set_field1 (o
, val
& 0xff);
427 void ram_set_cdr (obj o
, obj val
)
429 ram_set_field2 (o
, ((val
& 0x1f00) >> 8) | (ram_get_field2 (o
) & 0xc0));
430 ram_set_field3 (o
, val
& 0xff);
433 obj
get_global (uint8 i
)
438 void set_global (uint8 i
, obj o
)
443 /*---------------------------------------------------------------------------*/
445 /* Interface to GC */
447 /* GC tags are in the top 2 bits of field 0 */
448 #define GC_TAG_0_LEFT (1<<5)
449 // TODO was 3<<5, changed to play nice with procedures and bignums, but should actually set only this bit, not clear the other
450 #define GC_TAG_1_LEFT (2<<5)
451 #define GC_TAG_UNMARKED (0<<5) /* must be 0 */ // TODO FOOBAR is it ok ? eevn for bignums ?
453 /* Number of object fields of objects in ram */
454 #define HAS_2_OBJECT_FIELDS(visit) (RAM_PAIR(visit) || RAM_CONTINUATION(visit))
455 #define HAS_1_OBJECT_FIELD(visit) (RAM_COMPOSITE(visit) || RAM_CLOSURE(visit))
456 // TODO now we consider that all composites have at least 1 field, even symbols, as do procedures. no problem for symbols, since the car is always #f (make sure)
457 // TODO if we ever have true bignums, bignums will have 1 object field
459 #define NIL OBJ_FALSE
461 /*---------------------------------------------------------------------------*/
463 /* Garbage collector */
465 obj free_list
; /* list of unused cells */
467 obj arg1
; /* root set */
474 uint8 na
; /* interpreter variables */ // TODO what's na ?
480 obj second_half
; /* the second half of continuations */
485 void init_ram_heap (void)
488 obj o
= MAX_RAM_ENCODING
;
492 while (o
>= MIN_RAM_ENCODING
)
494 ram_set_gc_tags (o
, GC_TAG_UNMARKED
);
495 ram_set_car (o
, free_list
);
500 for (i
=0; i
<GLOVARS
; i
++)
501 set_global (i
, OBJ_FALSE
);
509 second_half
= OBJ_FALSE
;
516 obj stack
; // TODO do we need a stack ? since we have 0-1-2 children, we could do deutsche schorr waite
528 IF_GC_TRACE(printf ("push stack=%d (tag=%d) visit=%d (tag=%d)\n", stack
, ram_get_gc_tags (stack
)>>6, visit
, ram_get_gc_tags (visit
)>>6));
531 * Four cases are possible:
534 * stack visit tag F1 F2 F3
535 * NIL | +---+---+---+---+
540 * tag F1 F2 F3 stack visit tag F1 F2 F3
541 * +---+---+---+---+ | | +---+---+---+---+
542 * | 1 | | | | <-+ +-> | ? | | | |
543 * +---+---+---+-|-+ +---+---+---+---+
544 * <-----------------+
547 * tag F1 F2 F3 stack visit tag F1 F2 F3
548 * +---+---+---+---+ | | +---+---+---+---+
549 * | 2 | | | | <-+ +-> | ? | | | |
550 * +---+---+-|-+---+ +---+---+---+---+
554 * tag F1 F2 F3 stack visit tag F1 F2 F3
555 * +---+---+---+---+ | | +---+---+---+---+
556 * | 3 | | | | <-+ +-> | ? | | | |
557 * +---+-|-+---+---+ +---+---+---+---+
560 // TODO since no-one has 3 fields anymore, not really 4 cases ?
562 // if (ram_get_gc_tags (visit) != GC_TAG_UNMARKED) // TODO always matches procedures, WRONG, maybe check only the right gc bit ?/
563 if (ram_get_gc_tags (visit
) & 0x2f) // TODO we check only the last gc bit
564 IF_GC_TRACE(printf ("case 1\n")); // TODO are there cases where checking only the last gc bit is wrong ?
565 // TODO FOOBAR ok, with our new way, what do we check here ?
568 if (HAS_2_OBJECT_FIELDS(visit
))
570 IF_GC_TRACE(printf ("case 5\n"));
571 // TODO we don't have cases 2-4 anymore
575 temp
= ram_get_cdr (visit
);
579 IF_GC_TRACE(printf ("case 6\n"));
580 ram_set_gc_tags (visit
, GC_TAG_1_LEFT
);
581 ram_set_cdr (visit
, stack
);
585 IF_GC_TRACE(printf ("case 7\n"));
590 if (HAS_1_OBJECT_FIELD(visit
))
592 IF_GC_TRACE(printf ("case 8\n"));
596 temp
= ram_get_car (visit
);
600 IF_GC_TRACE(printf ("case 9\n"));
601 ram_set_gc_tag0 (visit
, GC_TAG_0_LEFT
); // TODO changed, now we only set bit 0, we don't change bit 1, since some objets have only 1 mark bit
602 ram_set_car (visit
, stack
);
606 IF_GC_TRACE(printf ("case 10\n"));
609 IF_GC_TRACE(printf ("case 11\n"));
611 ram_set_gc_tag0 (visit
, GC_TAG_0_LEFT
); // TODO changed, same as above
616 IF_GC_TRACE(printf ("pop stack=%d (tag=%d) visit=%d (tag=%d)\n", stack
, ram_get_gc_tags (stack
)>>6, visit
, ram_get_gc_tags (visit
)>>6));
620 if (ram_get_gc_tags (stack
) == GC_TAG_1_LEFT
) // TODO FOOBAR, this is always true for closures that have not been marked, can such an object get here ? probably not, since when a procedure is popped, it has already been visited, so will be at 0 left
622 IF_GC_TRACE(printf ("case 13\n"));
624 temp
= ram_get_cdr (stack
); /* pop through field 2 */
625 ram_set_cdr (stack
, visit
);
632 IF_GC_TRACE(printf ("case 14\n"));
634 temp
= ram_get_car (stack
); /* pop through field 1 */
635 ram_set_car (stack
, visit
);
656 obj visit
= MAX_RAM_ENCODING
;
660 while (visit
>= MIN_RAM_ENCODING
)
662 if ((RAM_COMPOSITE(visit
) && (ram_get_gc_tags (visit
) == GC_TAG_UNMARKED
)) || (ram_get_gc_tags (visit
) & GC_TAG_0_LEFT
)) /* unmarked? */
663 // TODO now we check only 1 bit if the object has only 1 mark bit
665 ram_set_car (visit
, free_list
);
670 if (RAM_COMPOSITE(visit
))
671 ram_set_gc_tags (visit
, GC_TAG_UNMARKED
);
672 else // only 1 mark bit to unset
673 ram_set_gc_tag0 (visit
, GC_TAG_UNMARKED
);
685 printf ("**************** memory needed = %d\n", max_live
+1);
702 for (i
=0; i
<GLOVARS
; i
++)
703 mark (get_global (i
));
708 obj
alloc_ram_cell (void)
722 ERROR("memory is full");
727 free_list
= ram_get_field1 (o
);
732 obj
alloc_ram_cell_init (uint8 f0
, uint8 f1
, uint8 f2
, uint8 f3
)
734 obj o
= alloc_ram_cell ();
736 ram_set_field0 (o
, f0
);
737 ram_set_field1 (o
, f1
);
738 ram_set_field2 (o
, f2
);
739 ram_set_field3 (o
, f3
);
744 /*---------------------------------------------------------------------------*/
746 int32
decode_int (obj o
)
752 if (o
< MIN_FIXNUM_ENCODING
)
753 TYPE_ERROR("integer");
755 if (o
<= (MIN_FIXNUM_ENCODING
+ (MAX_FIXNUM
- MIN_FIXNUM
)))
756 return DECODE_FIXNUM(o
);
761 TYPE_ERROR("integer");
763 u
= ram_get_field1 (o
);
764 h
= ram_get_field2 (o
);
765 l
= ram_get_field3 (o
);
770 TYPE_ERROR("integer");
772 u
= rom_get_field1 (o
);
773 h
= rom_get_field2 (o
);
774 l
= rom_get_field3 (o
);
777 TYPE_ERROR("integer");
780 return ((int32
)((((int16
)u
- 256) << 8) + h
) << 8) + l
;
782 return ((int32
)(((int16
)u
<< 8) + h
) << 8) + l
;
785 obj
encode_int (int32 n
)
787 if (n
>= MIN_FIXNUM
&& n
<= MAX_FIXNUM
)
788 return ENCODE_FIXNUM(n
);
790 return alloc_ram_cell_init (BIGNUM_FIELD0
, n
>> 16, n
>> 8, n
);
793 /*---------------------------------------------------------------------------*/
805 else if (o
== OBJ_TRUE
)
807 else if (o
== OBJ_NULL
)
809 else if (o
<= (MIN_FIXNUM_ENCODING
+ (MAX_FIXNUM
- MIN_FIXNUM
)))
810 printf ("%d", DECODE_FIXNUM(o
));
820 if ((in_ram
&& RAM_BIGNUM(o
)) || (!in_ram
&& ROM_BIGNUM(o
)))
822 printf ("\n%d\n", ROM_BIGNUM(o
)); // TODO debug
823 printf ("%d", decode_int (o
)); // TODO gets here, but shouldn't, with test-globals
825 else if ((in_ram
&& RAM_COMPOSITE(o
)) || ROM_COMPOSITE(o
))
830 if (in_ram
&& RAM_PAIR(o
))
832 car
= ram_get_car (o
);
833 cdr
= ram_get_cdr (o
);
841 else if (RAM_PAIR(cdr
))
843 car
= ram_get_car (cdr
);
844 cdr
= ram_get_cdr (cdr
);
856 else if (!in_ram
&& ROM_PAIR(o
))
858 car
= rom_get_car (o
);
859 cdr
= rom_get_cdr (o
);
866 else if (ROM_PAIR(cdr
))
868 car
= rom_get_car (cdr
);
869 cdr
= rom_get_cdr (cdr
);
874 else // TODO lots of repetition
881 else if ((in_ram
&& RAM_SYMBOL(o
)) || (!in_ram
&& ROM_SYMBOL(o
)))
882 printf ("#<symbol>");
883 else if ((in_ram
&& RAM_STRING(o
)) || (!in_ram
&& ROM_STRING(o
)))
884 printf ("#<string>");
885 else if ((in_ram
&& RAM_VECTOR(o
)) || (!in_ram
&& ROM_VECTOR(o
)))
886 printf ("#<vector>");
891 /* obj parent_cont; */
895 /* env = ram_get_car (o); */
897 /* env = rom_get_cdr (o); */
900 /* parent_cont = ram_get_field2 (o); */
902 /* parent_cont = rom_get_field2 (o); */
905 /* pc = ((rom_addr)(field0 + ((CODE_START>>8) - CLOSURE_FIELD0)) << 8) + ram_get_field3 (o); */
907 /* pc = ((rom_addr)(field0 + ((CODE_START>>8) - CLOSURE_FIELD0)) << 8) + rom_get_field3 (o); */
909 /* printf ("{0x%04x ", pc); */
912 /* show (parent_cont); */
913 /* printf ("}"); */ // TODO the representation of procedures changed
914 printf ("#<procedure>");
921 void show_state (rom_addr pc
)
923 printf ("pc=0x%04x bytecode=0x%02x env=", pc
, rom_get (pc
));
940 /*---------------------------------------------------------------------------*/
942 /* Integer operations */
944 #define encode_bool(x) ((obj)(x))
946 void prim_numberp (void)
948 if (arg1
>= MIN_FIXNUM_ENCODING
949 && arg1
<= (MIN_FIXNUM_ENCODING
+ (MAX_FIXNUM
- MIN_FIXNUM
)))
954 arg1
= encode_bool (RAM_BIGNUM(arg1
));
955 else if (IN_ROM(arg1
))
956 arg1
= encode_bool (ROM_BIGNUM(arg1
));
962 void decode_2_int_args (void)
964 a1
= decode_int (arg1
);
965 a2
= decode_int (arg2
);
970 decode_2_int_args ();
971 arg1
= encode_int (a1
+ a2
);
977 decode_2_int_args ();
978 arg1
= encode_int (a1
- a2
);
984 decode_2_int_args ();
985 arg1
= encode_int (a1
* a2
);
991 decode_2_int_args ();
993 ERROR("divide by 0");
994 arg1
= encode_int (a1
/ a2
);
1000 decode_2_int_args ();
1002 ERROR("divide by 0");
1003 arg1
= encode_int (a1
% a2
);
1007 void prim_neg (void)
1009 a1
= decode_int (arg1
);
1010 arg1
= encode_int (- a1
);
1015 decode_2_int_args ();
1016 arg1
= encode_bool (a1
== a2
);
1022 decode_2_int_args ();
1023 arg1
= encode_bool (a1
< a2
);
1029 decode_2_int_args ();
1030 arg1
= encode_bool (a1
> a2
);
1034 void prim_ior (void)
1036 a1
= decode_int (arg1
);
1037 a2
= decode_int (arg2
);
1038 arg1
= encode_int (a1
| a2
);
1042 void prim_xor (void)
1044 a1
= decode_int (arg1
);
1045 a2
= decode_int (arg2
);
1046 arg1
= encode_int (a1
^ a2
);
1051 /*---------------------------------------------------------------------------*/
1053 /* List operations */
1055 void prim_pairp (void)
1058 arg1
= encode_bool (RAM_PAIR(arg1
));
1059 else if (IN_ROM(arg1
))
1060 arg1
= encode_bool (ROM_PAIR(arg1
));
1065 obj
cons (obj car
, obj cdr
)
1067 return alloc_ram_cell_init (COMPOSITE_FIELD0
| ((car
& 0x1f00) >> 8),
1069 PAIR_FIELD2
| ((cdr
& 0x1f00) >> 8),
1073 void prim_cons (void)
1075 arg1
= cons (arg1
, arg2
);
1079 void prim_car (void)
1083 if (!RAM_PAIR(arg1
))
1085 arg1
= ram_get_car (arg1
);
1087 else if (IN_ROM(arg1
))
1089 if (!ROM_PAIR(arg1
))
1091 arg1
= rom_get_car (arg1
);
1099 void prim_cdr (void)
1103 if (!RAM_PAIR(arg1
))
1105 arg1
= ram_get_cdr (arg1
);
1107 else if (IN_ROM(arg1
))
1109 if (!ROM_PAIR(arg1
))
1111 arg1
= rom_get_cdr (arg1
);
1119 void prim_set_car (void)
1123 if (!RAM_PAIR(arg1
))
1126 ram_set_car (arg1
, arg2
);
1136 void prim_set_cdr (void)
1140 if (!RAM_PAIR(arg1
))
1143 ram_set_cdr (arg1
, arg2
);
1153 void prim_nullp (void)
1155 arg1
= encode_bool (arg1
== OBJ_NULL
);
1158 /*---------------------------------------------------------------------------*/
1160 /* Miscellaneous operations */
1162 void prim_eqp (void)
1164 arg1
= encode_bool (arg1
== arg2
);
1168 void prim_not (void)
1170 arg1
= encode_bool (arg1
== OBJ_FALSE
);
1173 void prim_symbolp (void)
1176 arg1
= encode_bool (RAM_SYMBOL(arg1
));
1177 else if (IN_ROM(arg1
))
1178 arg1
= encode_bool (ROM_SYMBOL(arg1
));
1183 void prim_stringp (void)
1186 arg1
= encode_bool (RAM_STRING(arg1
));
1187 else if (IN_ROM(arg1
))
1188 arg1
= encode_bool (ROM_STRING(arg1
));
1193 void prim_string2list (void)
1197 if (!RAM_STRING(arg1
))
1198 TYPE_ERROR("string");
1200 arg1
= ram_get_car (arg1
);
1202 else if (IN_ROM(arg1
))
1204 if (!ROM_STRING(arg1
))
1205 TYPE_ERROR("string");
1207 arg1
= rom_get_car (arg1
);
1210 TYPE_ERROR("string");
1213 void prim_list2string (void)
1215 arg1
= alloc_ram_cell_init (COMPOSITE_FIELD0
| ((arg1
& 0x1f00) >> 8),
1222 /*---------------------------------------------------------------------------*/
1224 /* Robot specific operations */
1227 void prim_print (void)
1242 int32
read_clock (void)
1248 now
= from_now( 0 );
1256 static int32 start
= 0;
1261 now
= tb
.time
* 1000 + tb
.millitm
;
1268 static int32 start
= 0;
1271 if (gettimeofday (&tv
, NULL
) == 0)
1273 now
= tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
1287 void prim_clock (void)
1289 arg1
= encode_int (read_clock ());
1293 void prim_motor (void)
1295 decode_2_int_args ();
1297 if (a1
< 1 || a1
> 2 || a2
< -100 || a2
> 100)
1298 ERROR("argument out of range to procedure \"motor\"");
1308 printf ("motor %d -> power=%d\n", a1
, a2
);
1318 void prim_led (void)
1320 decode_2_int_args ();
1321 a3
= decode_int (arg3
);
1323 if (a1
< 1 || a1
> 3 || a2
< 0 || a3
< 0)
1324 ERROR("argument out of range to procedure \"led\"");
1328 LED_set( a1
, a2
, a3
);
1334 printf ("led %d -> duty=%d period=%d\n", a1
, a2
, a3
);
1345 void prim_led2_color (void)
1347 a1
= decode_int (arg1
);
1349 if (a1
< 0 || a1
> 1)
1350 ERROR("argument out of range to procedure \"led2-color\"");
1354 LED2_color_set( a1
);
1360 printf ("led2-color -> %s\n", (a1
==0)?"green":"red");
1369 void prim_getchar_wait (void)
1371 decode_2_int_args();
1372 a1
= read_clock () + a1
;
1374 if (a1
< 0 || a2
< 1 || a2
> 3)
1375 ERROR("argument out of range to procedure \"getchar-wait\"");
1382 serial_port_set ports
;
1383 ports
= serial_rx_wait_with_timeout( a2
, a1
);
1385 arg1
= encode_int (serial_rx_read( ports
));
1400 arg1
= encode_int (_getch ());
1403 } while (read_clock () < a1
);
1408 arg1
= encode_int (getchar ());
1416 void prim_putchar (void)
1418 decode_2_int_args ();
1420 if (a1
< 0 || a1
> 255 || a2
< 1 || a2
> 3)
1421 ERROR("argument out of range to procedure \"putchar\"");
1425 serial_tx_write( a2
, a1
);
1441 void prim_beep (void)
1443 decode_2_int_args ();
1445 if (a1
< 1 || a1
> 255 || a2
< 0)
1446 ERROR("argument out of range to procedure \"beep\"");
1450 beep( a1
, from_now( a2
) );
1456 printf ("beep -> freq-div=%d duration=%d\n", a1
, a2
);
1466 void prim_adc (void)
1470 a1
= decode_int (arg1
);
1472 if (a1
< 1 || a1
> 3)
1473 ERROR("argument out of range to procedure \"adc\"");
1483 x
= read_clock () & 255;
1485 if (x
> 127) x
= 256 - x
;
1491 arg1
= encode_int (x
);
1495 void prim_dac (void)
1497 a1
= decode_int (arg1
);
1499 if (a1
< 0 || a1
> 255)
1500 ERROR("argument out of range to procedure \"dac\"");
1510 printf ("dac -> %d\n", a1
);
1519 void prim_sernum (void)
1535 arg1
= encode_int (x
);
1539 /*---------------------------------------------------------------------------*/
1543 int hidden_fgetc (FILE *f
)
1553 #define fgetc(f) hidden_fgetc(f)
1555 void write_hex_nibble (int n
)
1557 putchar ("0123456789ABCDEF"[n
]);
1560 void write_hex (uint8 n
)
1562 write_hex_nibble (n
>> 4);
1563 write_hex_nibble (n
& 0x0f);
1568 if (c
>= '0' && c
<= '9')
1571 if (c
>= 'A' && c
<= 'F')
1572 return (c
- 'A' + 10);
1574 if (c
>= 'a' && c
<= 'f')
1575 return (c
- 'a' + 10);
1580 int read_hex_byte (FILE *f
)
1582 int h1
= hex (fgetc (f
));
1583 int h2
= hex (fgetc (f
));
1585 if (h1
>= 0 && h2
>= 0)
1586 return (h1
<<4) + h2
;
1591 int read_hex_file (char *filename
)
1594 FILE *f
= fopen (filename
, "r");
1604 for (i
=0; i
<ROM_BYTES
; i
++)
1609 while ((c
= fgetc (f
)) != EOF
)
1611 if ((c
== '\r') || (c
== '\n'))
1615 (len
= read_hex_byte (f
)) < 0 ||
1616 (a1
= read_hex_byte (f
)) < 0 ||
1617 (a2
= read_hex_byte (f
)) < 0 ||
1618 (t
= read_hex_byte (f
)) < 0)
1624 sum
= len
+ a1
+ a2
+ t
;
1632 unsigned long adr
= ((unsigned long)hi16
<< 16) + a
- CODE_START
;
1634 if ((b
= read_hex_byte (f
)) < 0)
1637 if (adr
>= 0 && adr
< ROM_BYTES
)
1640 a
= (a
+ 1) & 0xffff;
1657 if ((a1
= read_hex_byte (f
)) < 0 ||
1658 (a2
= read_hex_byte (f
)) < 0)
1663 hi16
= (a1
<<8) + a2
;
1668 if ((b
= read_hex_byte (f
)) < 0)
1675 printf ("*** HEX file checksum error (expected 0x%02x)\n", sum
);
1681 if ((c
!= '\r') && (c
!= '\n'))
1692 printf ("*** HEX file syntax error\n");
1702 /*---------------------------------------------------------------------------*/
1704 #define FETCH_NEXT_BYTECODE() bytecode = rom_get (pc++)
1706 #define BEGIN_DISPATCH() \
1708 IF_TRACE(show_state (pc)); \
1709 FETCH_NEXT_BYTECODE(); \
1710 bytecode_hi4 = bytecode & 0xf0; \
1711 bytecode_lo4 = bytecode & 0x0f; \
1712 switch (bytecode_hi4 >> 4) {
1714 #define END_DISPATCH() }
1716 #define CASE(opcode) case (opcode>>4):;
1718 #define DISPATCH(); goto dispatch;
1723 #define bytecode TABLAT
1724 #define bytecode_hi4 WREG
1727 #define PUSH_CONSTANT1 0x00
1728 #define PUSH_CONSTANT2 0x10
1729 #define PUSH_STACK1 0x20
1730 #define PUSH_STACK2 0x30
1731 #define PUSH_GLOBAL 0x40
1732 #define SET_GLOBAL 0x50
1735 #define CALL_TOPLEVEL 0x80
1736 #define JUMP_TOPLEVEL 0x90
1738 #define GOTO_IF_FALSE 0xb0
1739 #define CLOSURE 0xc0
1746 char *prim_name
[48] =
1770 "prim #%graft-to-cont",
1771 "prim #%return-to-cont",
1775 "prim #%string->list",
1776 "prim #%list->string",
1784 "prim #%led2-color",
1785 "prim #%getchar-wait",
1792 "push-constant [long]",
1800 #define PUSH_ARG1() push_arg1 ()
1803 void push_arg1 (void)
1805 env
= cons (arg1
, env
);
1811 obj o
= ram_get_car (env
);
1812 env
= ram_get_cdr (env
);
1816 void pop_procedure (void)
1817 { // TODO BARF what to do when continuations end up here ?
1822 if (RAM_CONTINUATION(arg1
))
1823 ERROR("continuation in pop_procedure"); // TODO this might be legitimate, but for now, we can't do this. if this error comes up, fix this function so it can handle continuations
1825 if (!RAM_CLOSURE(arg1
))
1826 TYPE_ERROR("procedure");
1828 entry
= (((ram_get_field0 (arg1
) & 0x1f) << 11)
1829 | (ram_get_field1 (arg1
) << 3)
1830 | (ram_get_field2 (arg1
) >> 5)) + CODE_START
;
1832 else if (IN_ROM(arg1
))
1834 if (ROM_CONTINUATION(arg1
))
1835 ERROR("continuation in pop_procedure"); // TODO same as above
1837 if (!ROM_CLOSURE(arg1
))
1838 TYPE_ERROR("procedure");
1840 entry
= (((rom_get_field0 (arg1
) & 0x1f) << 11)
1841 | (rom_get_field1 (arg1
) << 3)
1842 | (rom_get_field2 (arg1
) >> 5)) + CODE_START
;
1845 TYPE_ERROR("procedure");
1848 void handle_arity_and_rest_param (void)
1852 np
= rom_get (entry
++);
1854 if ((np
& 0x80) == 0)
1857 ERROR("wrong number of arguments");
1864 ERROR("wrong number of arguments");
1872 arg3
= cons (arg4
, arg3
);
1878 arg1
= cons (arg3
, arg1
);
1879 arg3
= OBJ_FALSE
; // TODO changed nothing with the new new closures, everything looks ok
1883 void build_env (void)
1889 arg1
= cons (arg3
, arg1
);
1894 arg3
= OBJ_FALSE
; // TODO changed nothing here either
1897 void save_cont (void)
1899 // the second half is a closure
1900 second_half
= alloc_ram_cell_init (CLOSURE_FIELD0
| ((pc
& 0xf800) >> 11),
1902 ((pc
& 0x0007) << 5) | (env
>> 8),
1904 cont
= alloc_ram_cell_init (COMPOSITE_FIELD0
| (cont
>> 8),
1906 CONTINUATION_FIELD2
| (second_half
>> 8),
1907 second_half
& 0xff);
1909 /* cont = alloc_ram_cell_init (CLOSURE_FIELD0 | ((second_half &0x1f00) >> 8), */
1910 /* second_half & 0xff, */
1911 /* (pc & 0xff00) >> 8, */
1915 void interpreter (void)
1919 pc
= (CODE_START
+ 4) + ((rom_addr
)rom_get (CODE_START
+2) << 2);
1923 /***************************************************************************/
1924 CASE(PUSH_CONSTANT1
);
1926 IF_TRACE(printf(" (push-constant "); show (bytecode_lo4
); printf (")\n"));
1928 arg1
= bytecode_lo4
;
1934 /***************************************************************************/
1935 CASE(PUSH_CONSTANT2
);
1937 IF_TRACE(printf(" (push-constant "); show (bytecode_lo4
+16); printf (")\n"));
1938 arg1
= bytecode_lo4
+16;
1944 /***************************************************************************/
1947 IF_TRACE(printf(" (push-stack %d)\n", bytecode_lo4
));
1951 while (bytecode_lo4
!= 0)
1953 arg1
= ram_get_cdr (arg1
);
1957 arg1
= ram_get_car (arg1
); // TODO BARF what to do if we want to get something in the env of a continuation ? will it happen, or only when called, when it becomes a simple closure ? if only when a closure, we're fine, I guess, since 1 is added to the offset by the compiler to skip the closure
1963 /***************************************************************************/
1966 IF_TRACE(printf(" (push-stack %d)\n", bytecode_lo4
+16));
1972 while (bytecode_lo4
!= 0)
1974 arg1
= ram_get_cdr (arg1
);
1978 arg1
= ram_get_car (arg1
);
1984 /***************************************************************************/
1987 IF_TRACE(printf(" (push-global %d)\n", bytecode_lo4
));
1989 arg1
= get_global (bytecode_lo4
);
1995 /***************************************************************************/
1998 IF_TRACE(printf(" (set-global %d)\n", bytecode_lo4
));
2000 set_global (bytecode_lo4
, POP());
2004 /***************************************************************************/
2007 IF_TRACE(printf(" (call %d)\n", bytecode_lo4
));
2011 pop_procedure (); // TODO FOOBAR can we call a continuation ? if so, fix pop_procedure
2012 handle_arity_and_rest_param ();
2023 /***************************************************************************/
2026 IF_TRACE(printf(" (jump %d)\n", bytecode_lo4
));
2031 handle_arity_and_rest_param ();
2041 /***************************************************************************/
2042 CASE(CALL_TOPLEVEL
);
2044 FETCH_NEXT_BYTECODE();
2045 second_half
= bytecode
; // TODO make sure second_half is not already in use
2047 FETCH_NEXT_BYTECODE();
2049 IF_TRACE(printf(" (call-toplevel 0x%04x)\n", ((second_half
<< 8) | bytecode
) + CODE_START
));
2051 entry
= ((second_half
<< 8) | bytecode
) + CODE_START
; // TODO FOOBAR we have the last 4 bits of the opcode free, to do pretty much anything
2054 na
= rom_get (entry
++);
2066 /***************************************************************************/
2067 CASE(JUMP_TOPLEVEL
);
2069 FETCH_NEXT_BYTECODE();
2070 second_half
= bytecode
; // TODO make sure second_half is not already in use
2072 FETCH_NEXT_BYTECODE();
2074 IF_TRACE(printf(" (jump-toplevel 0x%04x)\n", ((second_half
<< 8) | bytecode
) + CODE_START
));
2076 entry
= ((second_half
<< 8) | bytecode
) + CODE_START
;
2079 na
= rom_get (entry
++);
2090 /***************************************************************************/
2093 FETCH_NEXT_BYTECODE();
2094 // TODO goto's use 12-bit addresses, unlike calls and jumps, which use 16, is it ok ?
2095 IF_TRACE(printf(" (goto 0x%04x)\n", ((rom_addr
)(bytecode_lo4
+ (CODE_START
>> 8)) << 8) + bytecode
));
2097 pc
= ((rom_addr
)(bytecode_lo4
+ (CODE_START
>> 8)) << 8) + bytecode
;
2101 /***************************************************************************/
2102 CASE(GOTO_IF_FALSE
);
2104 FETCH_NEXT_BYTECODE();
2106 IF_TRACE(printf(" (goto-if-false 0x%04x)\n", ((rom_addr
)(bytecode_lo4
+ (CODE_START
>> 8)) << 8) + bytecode
));
2108 if (POP() == OBJ_FALSE
)
2109 pc
= ((rom_addr
)(bytecode_lo4
+ (CODE_START
>> 8)) << 8) + bytecode
;
2113 /***************************************************************************/
2116 FETCH_NEXT_BYTECODE();
2117 second_half
= bytecode
;
2119 FETCH_NEXT_BYTECODE();
2121 IF_TRACE(printf(" (closure 0x%04x)\n", (second_half
<< 8) | bytecode
));
2122 // TODO original had CODE_START, while the real code below didn't
2124 arg2
= POP(); // #f TODO should be, at least, and not used anymore, would it break anything not to use it in the compiler anymore ? maybe try, it's not urgent, but would be nice
2125 arg3
= POP(); // env
2127 entry
= (second_half
<< 8) | bytecode
; // TODO original had no CODE_START, why ?
2129 arg1
= alloc_ram_cell_init (CLOSURE_FIELD0
| (second_half
>> 3),
2130 ((second_half
& 0x07) << 5) | (bytecode
>> 3),
2131 ((bytecode
& 0x07) << 5) |((arg3
& 0x1f00) >> 8),
2141 /***************************************************************************/
2144 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
]));
2146 switch (bytecode_lo4
)
2149 arg1
= POP(); prim_numberp (); PUSH_ARG1(); break;
2151 arg2
= POP(); arg1
= POP(); prim_add (); PUSH_ARG1(); break;
2153 arg2
= POP(); arg1
= POP(); prim_sub (); PUSH_ARG1(); break;
2155 arg2
= POP(); arg1
= POP(); prim_mul (); PUSH_ARG1(); break;
2157 arg2
= POP(); arg1
= POP(); prim_div (); PUSH_ARG1(); break;
2159 arg2
= POP(); arg1
= POP(); prim_rem (); PUSH_ARG1(); break;
2161 arg1
= POP(); prim_neg (); PUSH_ARG1(); break;
2163 arg2
= POP(); arg1
= POP(); prim_eq (); PUSH_ARG1(); break;
2165 arg2
= POP(); arg1
= POP(); prim_lt (); PUSH_ARG1(); break;
2167 arg2
= POP(); arg1
= POP(); prim_ior (); PUSH_ARG1(); break;
2169 arg2
= POP(); arg1
= POP(); prim_gt (); PUSH_ARG1(); break;
2171 arg2
= POP(); arg1
= POP(); prim_xor (); PUSH_ARG1(); break;
2173 arg1
= POP(); prim_pairp (); PUSH_ARG1(); break;
2175 arg2
= POP(); arg1
= POP(); prim_cons (); PUSH_ARG1(); break;
2177 arg1
= POP(); prim_car (); PUSH_ARG1(); break;
2179 arg1
= POP(); prim_cdr (); PUSH_ARG1(); break;
2184 /***************************************************************************/
2187 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
+16]));
2189 switch (bytecode_lo4
)
2192 arg2
= POP(); arg1
= POP(); prim_set_car (); break;
2194 arg2
= POP(); arg1
= POP(); prim_set_cdr (); break;
2196 arg1
= POP(); prim_nullp (); PUSH_ARG1(); break;
2198 arg2
= POP(); arg1
= POP(); prim_eqp (); PUSH_ARG1(); break;
2200 arg1
= POP(); prim_not (); PUSH_ARG1(); break;
2202 /* prim #%get-cont */
2207 /* prim #%graft-to-cont */
2209 arg1
= POP(); /* thunk to call */
2210 cont
= POP(); /* continuation */
2212 PUSH_ARG1(); // TODO we don't call the continuation, no change was needed
2217 handle_arity_and_rest_param ();
2227 /* prim #%return-to-cont */
2229 arg1
= POP(); /* value to return */
2230 cont
= POP(); /* continuation */
2232 second_half
= ram_get_cdr (cont
);
2234 pc
= ((ram_get_field0 (second_half
) >> 11) // TODO have a function for that
2235 | ((ram_get_field1 (second_half
) >> 3) & 0xff)
2236 | (ram_get_field2 (second_half
) & 0x07)) + CODE_START
;
2238 env
= ram_get_cdr (second_half
);
2239 cont
= ram_get_car (cont
);
2248 /* prim #%symbol? */
2249 arg1
= POP(); prim_symbolp (); PUSH_ARG1(); break;
2251 /* prim #%string? */
2252 arg1
= POP(); prim_stringp (); PUSH_ARG1(); break;
2254 /* prim #%string->list */
2255 arg1
= POP(); prim_string2list (); PUSH_ARG1(); break;
2257 /* prim #%list->string */
2258 arg1
= POP(); prim_list2string (); PUSH_ARG1(); break;
2271 /***************************************************************************/
2274 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
+32]));
2276 switch (bytecode_lo4
)
2285 prim_clock (); PUSH_ARG1(); break;
2288 arg2
= POP(); arg1
= POP(); prim_motor (); break;
2291 arg3
= POP(); arg2
= POP(); arg1
= POP(); prim_led (); ;break;
2293 /* prim #%led2-color */
2294 arg1
= POP(); prim_led2_color (); break;
2296 /* prim #%getchar-wait */
2297 arg2
= POP(); arg1
= POP(); prim_getchar_wait (); PUSH_ARG1(); break;
2299 /* prim #%putchar */
2300 arg2
= POP(); arg1
= POP(); prim_putchar (); break;
2303 arg2
= POP(); arg1
= POP(); prim_beep (); break;
2306 arg1
= POP(); prim_adc (); PUSH_ARG1(); break;
2309 arg1
= POP(); prim_dac (); break;
2312 prim_sernum (); PUSH_ARG1(); break;
2318 /* push-constant [long] */
2319 FETCH_NEXT_BYTECODE();
2320 second_half
= bytecode
;
2321 FETCH_NEXT_BYTECODE();
2322 arg1
= (second_half
<< 8) | bytecode
;
2338 second_half
= ram_get_cdr (cont
);
2339 pc
= ((ram_get_field0 (second_half
) >> 11)
2340 | ((ram_get_field1 (second_half
) >> 3) & 0xff)
2341 | (ram_get_field2 (second_half
) & 0x07)) + CODE_START
;
2342 env
= ram_get_cdr (second_half
);
2343 cont
= ram_get_car (cont
);
2350 /***************************************************************************/
2355 /*---------------------------------------------------------------------------*/
2361 printf ("usage: sim file.hex\n");
2365 int main (int argc
, char *argv
[])
2368 rom_addr rom_start_addr
= 0;
2370 if (argc
> 1 && argv
[1][0] == '-' && argv
[1][1] == 's')
2377 if ((h1
= hex (argv
[1][2])) < 0 ||
2378 (h2
= hex (argv
[1][3])) < 0 ||
2379 (h3
= hex (argv
[1][4])) != 0 ||
2380 (h4
= hex (argv
[1][5])) != 0 ||
2384 rom_start_addr
= (h1
<< 12) | (h2
<< 8) | (h3
<< 4) | h4
;
2391 printf ("Start address = 0x%04x\n", rom_start_addr
);
2397 if (!read_hex_file (argv
[1]))
2398 printf ("*** Could not read hex file \"%s\"\n", argv
[1]);
2403 if (rom_get (CODE_START
+0) != 0xfb ||
2404 rom_get (CODE_START
+1) != 0xd7)
2405 printf ("*** The hex file was not compiled with PICOBIT\n");
2409 for (i
=0; i
<8192; i
++)
2410 if (rom_get (i
) != 0xff)
2411 printf ("rom_mem[0x%04x] = 0x%02x\n", i
, rom_get (i
));
2417 printf ("**************** memory needed = %d\n", max_live
+1);
2427 /*---------------------------------------------------------------------------*/