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);
432 obj
ram_get_entry (obj o
)
434 return (((ram_get_field0 (o
) & 0x1f) << 11)
435 | (ram_get_field1 (o
) << 3)
436 | (ram_get_field2 (o
) >> 5));
438 obj
rom_get_entry (obj o
)
440 return (((rom_get_field0 (o
) & 0x1f) << 11)
441 | (rom_get_field1 (o
) << 3)
442 | (rom_get_field2 (o
) >> 5));
445 obj
get_global (uint8 i
)
450 void set_global (uint8 i
, obj o
)
455 /*---------------------------------------------------------------------------*/
457 /* Interface to GC */
459 /* GC tags are in the top 2 bits of field 0 */
460 #define GC_TAG_0_LEFT (1<<5)
461 // TODO was 3<<5, changed to play nice with procedures and bignums, but should actually set only this bit, not clear the other
462 #define GC_TAG_1_LEFT (2<<5)
463 #define GC_TAG_UNMARKED (0<<5) /* must be 0 */ // TODO FOOBAR is it ok ? eevn for bignums ?
465 /* Number of object fields of objects in ram */
466 #define HAS_2_OBJECT_FIELDS(visit) (RAM_PAIR(visit) || RAM_CONTINUATION(visit))
467 #define HAS_1_OBJECT_FIELD(visit) (RAM_COMPOSITE(visit) || RAM_CLOSURE(visit))
468 // 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)
469 // TODO if we ever have true bignums, bignums will have 1 object field
471 #define NIL OBJ_FALSE
473 /*---------------------------------------------------------------------------*/
475 /* Garbage collector */
477 obj free_list
; /* list of unused cells */
479 obj arg1
; /* root set */
486 uint8 na
; /* interpreter variables */ // TODO what's na ?
492 obj second_half
; /* the second half of continuations */
497 void init_ram_heap (void)
500 obj o
= MAX_RAM_ENCODING
;
504 while (o
>= MIN_RAM_ENCODING
)
506 ram_set_gc_tags (o
, GC_TAG_UNMARKED
);
507 ram_set_car (o
, free_list
);
512 for (i
=0; i
<GLOVARS
; i
++)
513 set_global (i
, OBJ_FALSE
);
521 second_half
= OBJ_FALSE
;
528 obj stack
; // TODO do we need a stack ? since we have 0-1-2 children, we could do deutsche schorr waite
540 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));
543 * Four cases are possible:
546 * stack visit tag F1 F2 F3
547 * NIL | +---+---+---+---+
552 * tag F1 F2 F3 stack visit tag F1 F2 F3
553 * +---+---+---+---+ | | +---+---+---+---+
554 * | 1 | | | | <-+ +-> | ? | | | |
555 * +---+---+---+-|-+ +---+---+---+---+
556 * <-----------------+
559 * tag F1 F2 F3 stack visit tag F1 F2 F3
560 * +---+---+---+---+ | | +---+---+---+---+
561 * | 2 | | | | <-+ +-> | ? | | | |
562 * +---+---+-|-+---+ +---+---+---+---+
566 * tag F1 F2 F3 stack visit tag F1 F2 F3
567 * +---+---+---+---+ | | +---+---+---+---+
568 * | 3 | | | | <-+ +-> | ? | | | |
569 * +---+-|-+---+---+ +---+---+---+---+
572 // TODO since no-one has 3 fields anymore, not really 4 cases ?
574 // if (ram_get_gc_tags (visit) != GC_TAG_UNMARKED) // TODO always matches procedures, WRONG, maybe check only the right gc bit ?/
575 if (ram_get_gc_tags (visit
) & 0x2f) // TODO we check only the last gc bit
576 IF_GC_TRACE(printf ("case 1\n")); // TODO are there cases where checking only the last gc bit is wrong ?
577 // TODO FOOBAR ok, with our new way, what do we check here ?
580 if (HAS_2_OBJECT_FIELDS(visit
))
582 IF_GC_TRACE(printf ("case 5\n"));
583 // TODO we don't have cases 2-4 anymore
587 temp
= ram_get_cdr (visit
);
591 IF_GC_TRACE(printf ("case 6\n"));
592 ram_set_gc_tags (visit
, GC_TAG_1_LEFT
);
593 ram_set_cdr (visit
, stack
);
597 IF_GC_TRACE(printf ("case 7\n"));
602 if (HAS_1_OBJECT_FIELD(visit
))
604 IF_GC_TRACE(printf ("case 8\n"));
608 temp
= ram_get_car (visit
);
612 IF_GC_TRACE(printf ("case 9\n"));
613 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
614 ram_set_car (visit
, stack
);
618 IF_GC_TRACE(printf ("case 10\n"));
621 IF_GC_TRACE(printf ("case 11\n"));
623 ram_set_gc_tag0 (visit
, GC_TAG_0_LEFT
); // TODO changed, same as above
628 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));
632 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
634 IF_GC_TRACE(printf ("case 13\n"));
636 temp
= ram_get_cdr (stack
); /* pop through field 2 */
637 ram_set_cdr (stack
, visit
);
644 IF_GC_TRACE(printf ("case 14\n"));
646 temp
= ram_get_car (stack
); /* pop through field 1 */
647 ram_set_car (stack
, visit
);
668 obj visit
= MAX_RAM_ENCODING
;
672 while (visit
>= MIN_RAM_ENCODING
)
674 if ((RAM_COMPOSITE(visit
) && (ram_get_gc_tags (visit
) == GC_TAG_UNMARKED
)) || (ram_get_gc_tags (visit
) & GC_TAG_0_LEFT
)) /* unmarked? */
675 // TODO now we check only 1 bit if the object has only 1 mark bit
677 ram_set_car (visit
, free_list
);
682 if (RAM_COMPOSITE(visit
))
683 ram_set_gc_tags (visit
, GC_TAG_UNMARKED
);
684 else // only 1 mark bit to unset
685 ram_set_gc_tag0 (visit
, GC_TAG_UNMARKED
);
697 printf ("**************** memory needed = %d\n", max_live
+1);
714 for (i
=0; i
<GLOVARS
; i
++)
715 mark (get_global (i
));
720 obj
alloc_ram_cell (void)
734 ERROR("memory is full");
739 free_list
= ram_get_field1 (o
);
744 obj
alloc_ram_cell_init (uint8 f0
, uint8 f1
, uint8 f2
, uint8 f3
)
746 obj o
= alloc_ram_cell ();
748 ram_set_field0 (o
, f0
);
749 ram_set_field1 (o
, f1
);
750 ram_set_field2 (o
, f2
);
751 ram_set_field3 (o
, f3
);
756 /*---------------------------------------------------------------------------*/
758 int32
decode_int (obj o
)
764 if (o
< MIN_FIXNUM_ENCODING
)
765 TYPE_ERROR("integer");
767 if (o
<= (MIN_FIXNUM_ENCODING
+ (MAX_FIXNUM
- MIN_FIXNUM
)))
768 return DECODE_FIXNUM(o
);
773 TYPE_ERROR("integer");
775 u
= ram_get_field1 (o
);
776 h
= ram_get_field2 (o
);
777 l
= ram_get_field3 (o
);
782 TYPE_ERROR("integer");
784 u
= rom_get_field1 (o
);
785 h
= rom_get_field2 (o
);
786 l
= rom_get_field3 (o
);
789 TYPE_ERROR("integer");
792 return ((int32
)((((int16
)u
- 256) << 8) + h
) << 8) + l
;
794 return ((int32
)(((int16
)u
<< 8) + h
) << 8) + l
;
797 obj
encode_int (int32 n
)
799 if (n
>= MIN_FIXNUM
&& n
<= MAX_FIXNUM
)
800 return ENCODE_FIXNUM(n
);
802 return alloc_ram_cell_init (BIGNUM_FIELD0
, n
>> 16, n
>> 8, n
);
805 /*---------------------------------------------------------------------------*/
817 else if (o
== OBJ_TRUE
)
819 else if (o
== OBJ_NULL
)
821 else if (o
<= (MIN_FIXNUM_ENCODING
+ (MAX_FIXNUM
- MIN_FIXNUM
)))
822 printf ("%d", DECODE_FIXNUM(o
));
832 if ((in_ram
&& RAM_BIGNUM(o
)) || (!in_ram
&& ROM_BIGNUM(o
)))
833 printf ("%d", decode_int (o
));
834 else if ((in_ram
&& RAM_COMPOSITE(o
)) || (!in_ram
&& ROM_COMPOSITE(o
)))
839 if (in_ram
&& RAM_PAIR(o
))
841 car
= ram_get_car (o
);
842 cdr
= ram_get_cdr (o
);
850 else if (RAM_PAIR(cdr
))
852 car
= ram_get_car (cdr
);
853 cdr
= ram_get_cdr (cdr
);
865 else if (!in_ram
&& ROM_PAIR(o
))
867 car
= rom_get_car (o
);
868 cdr
= rom_get_cdr (o
);
875 else if (ROM_PAIR(cdr
))
877 car
= rom_get_car (cdr
);
878 cdr
= rom_get_cdr (cdr
);
883 else // TODO lots of repetition
890 else if ((in_ram
&& RAM_SYMBOL(o
)) || (!in_ram
&& ROM_SYMBOL(o
)))
891 printf ("#<symbol>");
892 else if ((in_ram
&& RAM_STRING(o
)) || (!in_ram
&& ROM_STRING(o
)))
893 printf ("#<string>");
894 else if ((in_ram
&& RAM_VECTOR(o
)) || (!in_ram
&& ROM_VECTOR(o
)))
895 printf ("#<vector>");
899 car
= ram_get_car (o
);
900 cdr
= ram_get_cdr (o
);
901 goto loop_ram
; // TODO ugly hack, takes advantage of the fact that pairs and continuations have the same layout
907 /* obj parent_cont; */
910 if (IN_RAM(o
)) // TODO can closures be in rom ? I don't think so
911 env
= ram_get_cdr (o
); // TODO was car, but representation changed
913 env
= rom_get_cdr (o
);
916 /* parent_cont = ram_get_field2 (o); */
918 /* parent_cont = rom_get_field2 (o); */
921 pc
= ram_get_entry (o
);
923 pc
= rom_get_entry (o
);
925 printf ("{0x%04x ", pc
);
928 /* show (parent_cont); */
930 /* printf ("#<procedure>"); */
937 void show_state (rom_addr pc
)
939 printf ("pc=0x%04x bytecode=0x%02x env=", pc
, rom_get (pc
));
956 /*---------------------------------------------------------------------------*/
958 /* Integer operations */
960 #define encode_bool(x) ((obj)(x))
962 void prim_numberp (void)
964 if (arg1
>= MIN_FIXNUM_ENCODING
965 && arg1
<= (MIN_FIXNUM_ENCODING
+ (MAX_FIXNUM
- MIN_FIXNUM
)))
970 arg1
= encode_bool (RAM_BIGNUM(arg1
));
971 else if (IN_ROM(arg1
))
972 arg1
= encode_bool (ROM_BIGNUM(arg1
));
978 void decode_2_int_args (void)
980 a1
= decode_int (arg1
);
981 a2
= decode_int (arg2
);
986 decode_2_int_args ();
987 arg1
= encode_int (a1
+ a2
);
993 decode_2_int_args ();
994 arg1
= encode_int (a1
- a2
);
1000 decode_2_int_args ();
1001 arg1
= encode_int (a1
* a2
);
1005 void prim_div (void)
1007 decode_2_int_args ();
1009 ERROR("divide by 0");
1010 arg1
= encode_int (a1
/ a2
);
1014 void prim_rem (void)
1016 decode_2_int_args ();
1018 ERROR("divide by 0");
1019 arg1
= encode_int (a1
% a2
);
1023 void prim_neg (void)
1025 a1
= decode_int (arg1
);
1026 arg1
= encode_int (- a1
);
1031 decode_2_int_args ();
1032 arg1
= encode_bool (a1
== a2
);
1038 decode_2_int_args ();
1039 arg1
= encode_bool (a1
< a2
);
1045 decode_2_int_args ();
1046 arg1
= encode_bool (a1
> a2
);
1050 void prim_ior (void)
1052 a1
= decode_int (arg1
);
1053 a2
= decode_int (arg2
);
1054 arg1
= encode_int (a1
| a2
);
1058 void prim_xor (void)
1060 a1
= decode_int (arg1
);
1061 a2
= decode_int (arg2
);
1062 arg1
= encode_int (a1
^ a2
);
1067 /*---------------------------------------------------------------------------*/
1069 /* List operations */
1071 void prim_pairp (void)
1074 arg1
= encode_bool (RAM_PAIR(arg1
));
1075 else if (IN_ROM(arg1
))
1076 arg1
= encode_bool (ROM_PAIR(arg1
));
1081 obj
cons (obj car
, obj cdr
)
1083 return alloc_ram_cell_init (COMPOSITE_FIELD0
| ((car
& 0x1f00) >> 8),
1085 PAIR_FIELD2
| ((cdr
& 0x1f00) >> 8),
1089 void prim_cons (void)
1091 arg1
= cons (arg1
, arg2
);
1095 void prim_car (void)
1099 if (!RAM_PAIR(arg1
))
1101 arg1
= ram_get_car (arg1
);
1103 else if (IN_ROM(arg1
))
1105 if (!ROM_PAIR(arg1
))
1107 arg1
= rom_get_car (arg1
);
1115 void prim_cdr (void)
1119 if (!RAM_PAIR(arg1
))
1121 arg1
= ram_get_cdr (arg1
);
1123 else if (IN_ROM(arg1
))
1125 if (!ROM_PAIR(arg1
))
1127 arg1
= rom_get_cdr (arg1
);
1135 void prim_set_car (void)
1139 if (!RAM_PAIR(arg1
))
1142 ram_set_car (arg1
, arg2
);
1152 void prim_set_cdr (void)
1156 if (!RAM_PAIR(arg1
))
1159 ram_set_cdr (arg1
, arg2
);
1169 void prim_nullp (void)
1171 arg1
= encode_bool (arg1
== OBJ_NULL
);
1174 /*---------------------------------------------------------------------------*/
1176 /* Miscellaneous operations */
1178 void prim_eqp (void)
1180 arg1
= encode_bool (arg1
== arg2
);
1184 void prim_not (void)
1186 arg1
= encode_bool (arg1
== OBJ_FALSE
);
1189 void prim_symbolp (void)
1192 arg1
= encode_bool (RAM_SYMBOL(arg1
));
1193 else if (IN_ROM(arg1
))
1194 arg1
= encode_bool (ROM_SYMBOL(arg1
));
1199 void prim_stringp (void)
1202 arg1
= encode_bool (RAM_STRING(arg1
));
1203 else if (IN_ROM(arg1
))
1204 arg1
= encode_bool (ROM_STRING(arg1
));
1209 void prim_string2list (void)
1213 if (!RAM_STRING(arg1
))
1214 TYPE_ERROR("string");
1216 arg1
= ram_get_car (arg1
);
1218 else if (IN_ROM(arg1
))
1220 if (!ROM_STRING(arg1
))
1221 TYPE_ERROR("string");
1223 arg1
= rom_get_car (arg1
);
1226 TYPE_ERROR("string");
1229 void prim_list2string (void)
1231 arg1
= alloc_ram_cell_init (COMPOSITE_FIELD0
| ((arg1
& 0x1f00) >> 8),
1238 /*---------------------------------------------------------------------------*/
1240 /* Robot specific operations */
1243 void prim_print (void)
1258 int32
read_clock (void)
1264 now
= from_now( 0 );
1272 static int32 start
= 0;
1277 now
= tb
.time
* 1000 + tb
.millitm
;
1284 static int32 start
= 0;
1287 if (gettimeofday (&tv
, NULL
) == 0)
1289 now
= tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
1303 void prim_clock (void)
1305 arg1
= encode_int (read_clock ());
1309 void prim_motor (void)
1311 decode_2_int_args ();
1313 if (a1
< 1 || a1
> 2 || a2
< -100 || a2
> 100)
1314 ERROR("argument out of range to procedure \"motor\"");
1324 printf ("motor %d -> power=%d\n", a1
, a2
);
1334 void prim_led (void)
1336 decode_2_int_args ();
1337 a3
= decode_int (arg3
);
1339 if (a1
< 1 || a1
> 3 || a2
< 0 || a3
< 0)
1340 ERROR("argument out of range to procedure \"led\"");
1344 LED_set( a1
, a2
, a3
);
1350 printf ("led %d -> duty=%d period=%d\n", a1
, a2
, a3
);
1361 void prim_led2_color (void)
1363 a1
= decode_int (arg1
);
1365 if (a1
< 0 || a1
> 1)
1366 ERROR("argument out of range to procedure \"led2-color\"");
1370 LED2_color_set( a1
);
1376 printf ("led2-color -> %s\n", (a1
==0)?"green":"red");
1385 void prim_getchar_wait (void)
1387 decode_2_int_args();
1388 a1
= read_clock () + a1
;
1390 if (a1
< 0 || a2
< 1 || a2
> 3)
1391 ERROR("argument out of range to procedure \"getchar-wait\"");
1398 serial_port_set ports
;
1399 ports
= serial_rx_wait_with_timeout( a2
, a1
);
1401 arg1
= encode_int (serial_rx_read( ports
));
1416 arg1
= encode_int (_getch ());
1419 } while (read_clock () < a1
);
1424 arg1
= encode_int (getchar ());
1432 void prim_putchar (void)
1434 decode_2_int_args ();
1436 if (a1
< 0 || a1
> 255 || a2
< 1 || a2
> 3)
1437 ERROR("argument out of range to procedure \"putchar\"");
1441 serial_tx_write( a2
, a1
);
1457 void prim_beep (void)
1459 decode_2_int_args ();
1461 if (a1
< 1 || a1
> 255 || a2
< 0)
1462 ERROR("argument out of range to procedure \"beep\"");
1466 beep( a1
, from_now( a2
) );
1472 printf ("beep -> freq-div=%d duration=%d\n", a1
, a2
);
1482 void prim_adc (void)
1486 a1
= decode_int (arg1
);
1488 if (a1
< 1 || a1
> 3)
1489 ERROR("argument out of range to procedure \"adc\"");
1499 x
= read_clock () & 255;
1501 if (x
> 127) x
= 256 - x
;
1507 arg1
= encode_int (x
);
1511 void prim_dac (void)
1513 a1
= decode_int (arg1
);
1515 if (a1
< 0 || a1
> 255)
1516 ERROR("argument out of range to procedure \"dac\"");
1526 printf ("dac -> %d\n", a1
);
1535 void prim_sernum (void)
1551 arg1
= encode_int (x
);
1555 /*---------------------------------------------------------------------------*/
1559 int hidden_fgetc (FILE *f
)
1569 #define fgetc(f) hidden_fgetc(f)
1571 void write_hex_nibble (int n
)
1573 putchar ("0123456789ABCDEF"[n
]);
1576 void write_hex (uint8 n
)
1578 write_hex_nibble (n
>> 4);
1579 write_hex_nibble (n
& 0x0f);
1584 if (c
>= '0' && c
<= '9')
1587 if (c
>= 'A' && c
<= 'F')
1588 return (c
- 'A' + 10);
1590 if (c
>= 'a' && c
<= 'f')
1591 return (c
- 'a' + 10);
1596 int read_hex_byte (FILE *f
)
1598 int h1
= hex (fgetc (f
));
1599 int h2
= hex (fgetc (f
));
1601 if (h1
>= 0 && h2
>= 0)
1602 return (h1
<<4) + h2
;
1607 int read_hex_file (char *filename
)
1610 FILE *f
= fopen (filename
, "r");
1620 for (i
=0; i
<ROM_BYTES
; i
++)
1625 while ((c
= fgetc (f
)) != EOF
)
1627 if ((c
== '\r') || (c
== '\n'))
1631 (len
= read_hex_byte (f
)) < 0 ||
1632 (a1
= read_hex_byte (f
)) < 0 ||
1633 (a2
= read_hex_byte (f
)) < 0 ||
1634 (t
= read_hex_byte (f
)) < 0)
1640 sum
= len
+ a1
+ a2
+ t
;
1648 unsigned long adr
= ((unsigned long)hi16
<< 16) + a
- CODE_START
;
1650 if ((b
= read_hex_byte (f
)) < 0)
1653 if (adr
>= 0 && adr
< ROM_BYTES
)
1656 a
= (a
+ 1) & 0xffff;
1673 if ((a1
= read_hex_byte (f
)) < 0 ||
1674 (a2
= read_hex_byte (f
)) < 0)
1679 hi16
= (a1
<<8) + a2
;
1684 if ((b
= read_hex_byte (f
)) < 0)
1691 printf ("*** HEX file checksum error (expected 0x%02x)\n", sum
);
1697 if ((c
!= '\r') && (c
!= '\n'))
1708 printf ("*** HEX file syntax error\n");
1718 /*---------------------------------------------------------------------------*/
1720 #define FETCH_NEXT_BYTECODE() bytecode = rom_get (pc++)
1722 #define BEGIN_DISPATCH() \
1724 IF_TRACE(show_state (pc)); \
1725 FETCH_NEXT_BYTECODE(); \
1726 bytecode_hi4 = bytecode & 0xf0; \
1727 bytecode_lo4 = bytecode & 0x0f; \
1728 switch (bytecode_hi4 >> 4) {
1730 #define END_DISPATCH() }
1732 #define CASE(opcode) case (opcode>>4):;
1734 #define DISPATCH(); goto dispatch;
1739 #define bytecode TABLAT
1740 #define bytecode_hi4 WREG
1743 #define PUSH_CONSTANT1 0x00
1744 #define PUSH_CONSTANT2 0x10
1745 #define PUSH_STACK1 0x20
1746 #define PUSH_STACK2 0x30
1747 #define PUSH_GLOBAL 0x40
1748 #define SET_GLOBAL 0x50
1751 #define CALL_TOPLEVEL 0x80
1752 #define JUMP_TOPLEVEL 0x90
1754 #define GOTO_IF_FALSE 0xb0
1755 #define CLOSURE 0xc0
1762 char *prim_name
[48] =
1786 "prim #%graft-to-cont",
1787 "prim #%return-to-cont",
1791 "prim #%string->list",
1792 "prim #%list->string",
1800 "prim #%led2-color",
1801 "prim #%getchar-wait",
1808 "push-constant [long]",
1816 #define PUSH_ARG1() push_arg1 ()
1819 void push_arg1 (void)
1821 env
= cons (arg1
, env
);
1827 obj o
= ram_get_car (env
);
1828 env
= ram_get_cdr (env
);
1832 void pop_procedure (void)
1838 if (RAM_CONTINUATION(arg1
))
1839 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
1841 if (!RAM_CLOSURE(arg1
))
1842 TYPE_ERROR("procedure");
1844 entry
= ram_get_entry (arg1
) + CODE_START
; // FOO all addresses in the bytecode should be from 0, not from CODE_START, should be fixed everywhere, but might not be
1846 else if (IN_ROM(arg1
))
1848 if (ROM_CONTINUATION(arg1
))
1849 ERROR("continuation in pop_procedure"); // TODO same as above
1851 if (!ROM_CLOSURE(arg1
))
1852 TYPE_ERROR("procedure");
1854 entry
= rom_get_entry (arg1
) + CODE_START
;
1857 TYPE_ERROR("procedure");
1860 void handle_arity_and_rest_param (void)
1864 np
= rom_get (entry
++);
1866 if ((np
& 0x80) == 0)
1869 ERROR("wrong number of arguments");
1876 ERROR("wrong number of arguments");
1884 arg3
= cons (arg4
, arg3
);
1890 arg1
= cons (arg3
, arg1
);
1891 arg3
= OBJ_FALSE
; // TODO changed nothing with the new new closures, everything looks ok
1895 void build_env (void)
1901 arg1
= cons (arg3
, arg1
);
1906 arg3
= OBJ_FALSE
; // TODO changed nothing here either
1909 void save_cont (void)
1910 { // BARF probably a problem here
1911 // the second half is a closure
1912 /* second_half = alloc_ram_cell_init (CLOSURE_FIELD0 | ((pc & 0xf800) >> 11), */
1913 /* (pc & 0x07f8) >> 3, */
1914 /* ((pc & 0x0007) << 5) | (env >> 8), */
1916 second_half
= alloc_ram_cell_init (CLOSURE_FIELD0
| (pc
>> 11),
1917 (pc
>> 3) & 0xff, // BREGG
1918 ((pc
& 0x0007) << 5) | (env
>> 8),
1920 // BREGG problem is, we add the start twice, in get entry, and somewhere else, but pc doesn't have it initially
1921 cont
= alloc_ram_cell_init (COMPOSITE_FIELD0
| (cont
>> 8),
1923 CONTINUATION_FIELD2
| (second_half
>> 8),
1924 second_half
& 0xff);
1927 void interpreter (void)
1931 pc
= (CODE_START
+ 4) + ((rom_addr
)rom_get (CODE_START
+2) << 2);
1935 /***************************************************************************/
1936 CASE(PUSH_CONSTANT1
);
1938 IF_TRACE(printf(" (push-constant "); show (bytecode_lo4
); printf (")\n"));
1940 arg1
= bytecode_lo4
;
1946 /***************************************************************************/
1947 CASE(PUSH_CONSTANT2
);
1949 IF_TRACE(printf(" (push-constant "); show (bytecode_lo4
+16); printf (")\n"));
1950 arg1
= bytecode_lo4
+16;
1956 /***************************************************************************/
1959 IF_TRACE(printf(" (push-stack %d)\n", bytecode_lo4
));
1963 while (bytecode_lo4
!= 0)
1965 arg1
= ram_get_cdr (arg1
);
1969 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
1975 /***************************************************************************/
1978 IF_TRACE(printf(" (push-stack %d)\n", bytecode_lo4
+16));
1984 while (bytecode_lo4
!= 0)
1986 arg1
= ram_get_cdr (arg1
);
1990 arg1
= ram_get_car (arg1
);
1996 /***************************************************************************/
1999 IF_TRACE(printf(" (push-global %d)\n", bytecode_lo4
));
2001 arg1
= get_global (bytecode_lo4
);
2007 /***************************************************************************/
2010 IF_TRACE(printf(" (set-global %d)\n", bytecode_lo4
));
2012 set_global (bytecode_lo4
, POP());
2016 /***************************************************************************/
2019 IF_TRACE(printf(" (call %d)\n", bytecode_lo4
));
2023 pop_procedure (); // TODO FOOBAR can we call a continuation ? if so, fix pop_procedure
2024 handle_arity_and_rest_param ();
2035 /***************************************************************************/
2038 IF_TRACE(printf(" (jump %d)\n", bytecode_lo4
));
2043 handle_arity_and_rest_param ();
2053 /***************************************************************************/
2054 CASE(CALL_TOPLEVEL
);
2056 FETCH_NEXT_BYTECODE();
2057 second_half
= bytecode
; // TODO make sure second_half is not already in use
2059 FETCH_NEXT_BYTECODE();
2061 IF_TRACE(printf(" (call-toplevel 0x%04x)\n", ((second_half
<< 8) | bytecode
) + CODE_START
));
2063 entry
= (second_half
<< 8) + bytecode
+ CODE_START
; // TODO FOOBAR we have the last 4 bits of the opcode free, to do pretty much anything
2066 na
= rom_get (entry
++);
2078 /***************************************************************************/
2079 CASE(JUMP_TOPLEVEL
);
2081 FETCH_NEXT_BYTECODE();
2082 second_half
= bytecode
; // TODO make sure second_half is not already in use
2084 FETCH_NEXT_BYTECODE();
2086 IF_TRACE(printf(" (jump-toplevel 0x%04x)\n", ((second_half
<< 8) | bytecode
) + CODE_START
));
2088 entry
= (second_half
<< 8) + bytecode
+ CODE_START
; // TODO this is a common pattern
2091 na
= rom_get (entry
++);
2102 /***************************************************************************/
2105 FETCH_NEXT_BYTECODE();
2106 second_half
= bytecode
;
2108 FETCH_NEXT_BYTECODE();
2110 // TODO goto's use 12-bit addresses, unlike calls and jumps, which use 16, is it ok ?
2111 // actually, the compiler gives them 16 bit addresses now, it seems
2112 // that means we have even more free instructions, but that now even gotos are on 3 bytes
2113 IF_TRACE(printf(" (goto 0x%04x)\n", ((rom_addr
)(bytecode_lo4
+ (CODE_START
>> 8)) << 8) + bytecode
));
2115 pc
= (second_half
<< 8) + bytecode
+ CODE_START
;
2116 /* pc = ((rom_addr)(bytecode_lo4 + (CODE_START >> 8)) << 8) + bytecode; */ // TODO not anymore
2120 /***************************************************************************/
2121 CASE(GOTO_IF_FALSE
);
2123 FETCH_NEXT_BYTECODE();
2124 second_half
= bytecode
;
2126 FETCH_NEXT_BYTECODE();
2128 IF_TRACE(printf(" (goto-if-false 0x%04x)\n", ((rom_addr
)(bytecode_lo4
+ (CODE_START
>> 8)) << 8) + bytecode
));
2130 if (POP() == OBJ_FALSE
)
2131 pc
= (second_half
<< 8) + bytecode
+ CODE_START
;
2132 /* pc = ((rom_addr)(bytecode_lo4 + (CODE_START >> 8)) << 8) + bytecode; */
2136 /***************************************************************************/
2139 FETCH_NEXT_BYTECODE();
2140 second_half
= bytecode
;
2142 FETCH_NEXT_BYTECODE();
2144 IF_TRACE(printf(" (closure 0x%04x)\n", (second_half
<< 8) | bytecode
));
2145 // TODO original had CODE_START, while the real code below didn't
2147 /* 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 */ // TODO we got rid of this in the compiler
2148 arg3
= POP(); // env
2150 entry
= (second_half
<< 8) | bytecode
; // TODO original had no CODE_START, why ?
2152 arg1
= alloc_ram_cell_init (CLOSURE_FIELD0
| (second_half
>> 3),
2153 ((second_half
& 0x07) << 5) | (bytecode
>> 3),
2154 ((bytecode
& 0x07) << 5) |((arg3
& 0x1f00) >> 8),
2164 /***************************************************************************/
2167 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
]));
2169 switch (bytecode_lo4
)
2172 arg1
= POP(); prim_numberp (); PUSH_ARG1(); break;
2174 arg2
= POP(); arg1
= POP(); prim_add (); PUSH_ARG1(); break;
2176 arg2
= POP(); arg1
= POP(); prim_sub (); PUSH_ARG1(); break;
2178 arg2
= POP(); arg1
= POP(); prim_mul (); PUSH_ARG1(); break;
2180 arg2
= POP(); arg1
= POP(); prim_div (); PUSH_ARG1(); break;
2182 arg2
= POP(); arg1
= POP(); prim_rem (); PUSH_ARG1(); break;
2184 arg1
= POP(); prim_neg (); PUSH_ARG1(); break;
2186 arg2
= POP(); arg1
= POP(); prim_eq (); PUSH_ARG1(); break;
2188 arg2
= POP(); arg1
= POP(); prim_lt (); PUSH_ARG1(); break;
2190 arg2
= POP(); arg1
= POP(); prim_ior (); PUSH_ARG1(); break;
2192 arg2
= POP(); arg1
= POP(); prim_gt (); PUSH_ARG1(); break;
2194 arg2
= POP(); arg1
= POP(); prim_xor (); PUSH_ARG1(); break;
2196 arg1
= POP(); prim_pairp (); PUSH_ARG1(); break;
2198 arg2
= POP(); arg1
= POP(); prim_cons (); PUSH_ARG1(); break;
2200 arg1
= POP(); prim_car (); PUSH_ARG1(); break;
2202 arg1
= POP(); prim_cdr (); PUSH_ARG1(); break;
2207 /***************************************************************************/
2210 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
+16]));
2212 switch (bytecode_lo4
)
2215 arg2
= POP(); arg1
= POP(); prim_set_car (); break;
2217 arg2
= POP(); arg1
= POP(); prim_set_cdr (); break;
2219 arg1
= POP(); prim_nullp (); PUSH_ARG1(); break;
2221 arg2
= POP(); arg1
= POP(); prim_eqp (); PUSH_ARG1(); break;
2223 arg1
= POP(); prim_not (); PUSH_ARG1(); break;
2225 /* prim #%get-cont */
2230 /* prim #%graft-to-cont */
2232 arg1
= POP(); /* thunk to call */
2233 cont
= POP(); /* continuation */
2235 PUSH_ARG1(); // TODO we don't call the continuation, no change was needed
2240 handle_arity_and_rest_param ();
2250 /* prim #%return-to-cont */
2252 arg1
= POP(); /* value to return */
2253 cont
= POP(); /* continuation */
2255 second_half
= ram_get_cdr (cont
);
2257 pc
= ram_get_entry (second_half
);
2259 env
= ram_get_cdr (second_half
);
2260 cont
= ram_get_car (cont
);
2269 /* prim #%symbol? */
2270 arg1
= POP(); prim_symbolp (); PUSH_ARG1(); break;
2272 /* prim #%string? */
2273 arg1
= POP(); prim_stringp (); PUSH_ARG1(); break;
2275 /* prim #%string->list */
2276 arg1
= POP(); prim_string2list (); PUSH_ARG1(); break;
2278 /* prim #%list->string */
2279 arg1
= POP(); prim_list2string (); PUSH_ARG1(); break;
2292 /***************************************************************************/
2295 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
+32]));
2297 switch (bytecode_lo4
)
2306 prim_clock (); PUSH_ARG1(); break;
2309 arg2
= POP(); arg1
= POP(); prim_motor (); break;
2312 arg3
= POP(); arg2
= POP(); arg1
= POP(); prim_led (); ;break;
2314 /* prim #%led2-color */
2315 arg1
= POP(); prim_led2_color (); break;
2317 /* prim #%getchar-wait */
2318 arg2
= POP(); arg1
= POP(); prim_getchar_wait (); PUSH_ARG1(); break;
2320 /* prim #%putchar */
2321 arg2
= POP(); arg1
= POP(); prim_putchar (); break;
2324 arg2
= POP(); arg1
= POP(); prim_beep (); break;
2327 arg1
= POP(); prim_adc (); PUSH_ARG1(); break;
2330 arg1
= POP(); prim_dac (); break;
2333 prim_sernum (); PUSH_ARG1(); break;
2339 /* push-constant [long] */
2340 FETCH_NEXT_BYTECODE();
2341 second_half
= bytecode
;
2342 FETCH_NEXT_BYTECODE();
2343 arg1
= (second_half
<< 8) | bytecode
;
2359 second_half
= ram_get_cdr (cont
);
2360 pc
= ram_get_entry (second_half
);
2361 env
= ram_get_cdr (second_half
);
2362 cont
= ram_get_car (cont
);
2369 /***************************************************************************/
2374 /*---------------------------------------------------------------------------*/
2380 printf ("usage: sim file.hex\n");
2384 int main (int argc
, char *argv
[])
2387 rom_addr rom_start_addr
= 0;
2389 if (argc
> 1 && argv
[1][0] == '-' && argv
[1][1] == 's')
2396 if ((h1
= hex (argv
[1][2])) < 0 ||
2397 (h2
= hex (argv
[1][3])) < 0 ||
2398 (h3
= hex (argv
[1][4])) != 0 ||
2399 (h4
= hex (argv
[1][5])) != 0 ||
2403 rom_start_addr
= (h1
<< 12) | (h2
<< 8) | (h3
<< 4) | h4
;
2410 printf ("Start address = 0x%04x\n", rom_start_addr
);
2416 if (!read_hex_file (argv
[1]))
2417 printf ("*** Could not read hex file \"%s\"\n", argv
[1]);
2422 if (rom_get (CODE_START
+0) != 0xfb ||
2423 rom_get (CODE_START
+1) != 0xd7)
2424 printf ("*** The hex file was not compiled with PICOBIT\n");
2428 for (i
=0; i
<8192; i
++)
2429 if (rom_get (i
) != 0xff)
2430 printf ("rom_mem[0x%04x] = 0x%02x\n", i
, rom_get (i
));
2436 printf ("**************** memory needed = %d\n", max_live
+1);
2446 /*---------------------------------------------------------------------------*/