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) x
85 // TODO the last x was added to have gc debug info
88 #define IF_GC_TRACE(x)
91 /*---------------------------------------------------------------------------*/
96 #define ERROR(msg) halt_with_error()
97 #define TYPE_ERROR(type) halt_with_error()
104 #define ERROR(msg) error (msg)
105 #define TYPE_ERROR(type) type_error (type)
107 void error (char *msg
)
109 printf ("ERROR: %s\n", msg
);
113 void type_error (char *type
)
115 printf ("ERROR: An argument of type %s was expected\n", type
);
122 /*---------------------------------------------------------------------------*/
130 typedef uint16 ram_addr
;
131 typedef uint16 rom_addr
;
135 /*---------------------------------------------------------------------------*/
137 #define MIN_RAM_ENCODING 128
138 #define MAX_RAM_ENCODING 8192
139 #define RAM_BYTES ((MAX_RAM_ENCODING - MIN_RAM_ENCODING + 1)*4)
140 // TODO watch out if we address more than what the PIC actually has
142 // TODO change if we change the proportion of rom and ram addresses
144 #define OBJ_TO_RAM_ADDR(o,f) (((ram_addr)((uint16)(o) - MIN_RAM_ENCODING) << 2) + (f))
145 #define OBJ_TO_ROM_ADDR(o,f) (((rom_addr)((uint8)(o) - MIN_ROM_ENCODING) << 2) + (CODE_START + 4 + (f)))
152 #pragma udata picobit_heap=0x200
153 uint8 ram_mem
[RAM_BYTES
];
157 #define ram_get(a) *(uint8*)(a+0x200)
158 #define ram_set(a,x) *(uint8*)(a+0x200) = (x)
165 uint8 ram_mem
[RAM_BYTES
];
167 #define ram_get(a) ram_mem[a]
168 #define ram_set(a,x) ram_mem[a] = (x)
173 /*---------------------------------------------------------------------------*/
180 uint8
rom_get (rom_addr a
)
182 return *(rom uint8
*)a
;
190 #define ROM_BYTES 8192
192 uint8 rom_mem
[ROM_BYTES
] =
195 #define PUTCHAR_LIGHT_not
198 0xFB, 0xD7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x32
199 , 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
200 , 0x08, 0x50, 0x80, 0x16, 0xFE, 0xE8, 0x00, 0xFC
201 , 0x32, 0x80, 0x2D, 0xFE, 0xFC, 0x31, 0x80, 0x43
202 , 0xFE, 0xFC, 0x33, 0x80, 0x2D, 0xFE, 0xFC, 0x31
203 , 0x80, 0x43, 0xFE, 0x90, 0x16, 0x01, 0x20, 0xFC
204 , 0x32, 0xE3, 0xB0, 0x37, 0x09, 0xF3, 0xFF, 0x20
205 , 0xFC, 0x33, 0xE3, 0xB0, 0x40, 0x0A, 0xF3, 0xFF
206 , 0x08, 0xF3, 0xFF, 0x01, 0x40, 0x21, 0xD1, 0x00
207 , 0x02, 0xC0, 0x4C, 0x71, 0x01, 0x20, 0x50, 0x90
208 , 0x51, 0x00, 0xF1, 0x40, 0xD8, 0xB0, 0x59, 0x90
212 0xFB, 0xD7, 0x00, 0x00, 0x80, 0x08, 0xFE, 0xE8
213 , 0x00, 0xF6, 0xF5, 0x90, 0x08
217 uint8
rom_get (rom_addr a
)
219 return rom_mem
[a
-CODE_START
];
224 obj globals
[GLOVARS
];
226 /*---------------------------------------------------------------------------*/
234 fixnum n MIN_FIXNUM -> 3 ... MAX_FIXNUM -> 3 + (MAX_FIXNUM-MIN_FIXNUM)
235 TODO do we want 0..127 as fixnums ? would reduce number of ra/om objects
236 rom object 4 + (MAX_FIXNUM-MIN_FIXNUM) ... MIN_RAM_ENCODING-1
237 ram object MIN_RAM_ENCODING ... 4095 TODO was 255, now we have 12 bits
239 layout of memory allocated objects:
241 G's represent mark bits used by the gc TODO change GC, and does not use the same bits
243 bignum n 00G00000 uuuuuuuu hhhhhhhh llllllll (24 bit signed integer)
244 TODO we could have 29-bit integers
246 pair 1GGaaaaa aaaaaaaa 000ddddd 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 1GGxxxxx xxxxxxxx 100yyyyy yyyyyyyy
268 x is parent continuation
269 y is pointer to the second half, which is a closure (contains env and entry)
271 An environment is a list of objects built out of pairs. On entry to
272 a procedure the environment is the list of parameters to which is
273 added the environment of the closure being called.
275 The first byte at the entry point of a procedure gives the arity of
278 n = 0 to 127 -> procedure has n parameters (no rest parameter)
279 n = -128 to -1 -> procedure has -n parameters, the last is
287 #define MIN_FIXNUM_ENCODING 3
288 #define MIN_FIXNUM (-5)
289 #define MAX_FIXNUM 40
290 #define MIN_ROM_ENCODING (MIN_FIXNUM_ENCODING+MAX_FIXNUM-MIN_FIXNUM+1)
292 #define ENCODE_FIXNUM(n) ((obj)(n) + (MIN_FIXNUM_ENCODING - MIN_FIXNUM))
293 #define DECODE_FIXNUM(o) ((int32)(o) - (MIN_FIXNUM_ENCODING - MIN_FIXNUM))
296 #define IN_RAM(o) ((o) >= MIN_RAM_ENCODING)
297 #define IN_ROM(o) ((o) >= MIN_ROM_ENCODING)
299 // TODO BARF rom only checks the lower bound, might cause problem if not used in an else
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)
342 /*---------------------------------------------------------------------------*/
344 #define RAM_GET_FIELD0_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,0))
345 #define RAM_SET_FIELD0_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,0), val)
346 #define ROM_GET_FIELD0_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,0))
348 #define RAM_GET_GC_TAGS_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x60)
349 #define RAM_GET_GC_TAG0_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x20)
350 #define RAM_GET_GC_TAG1_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x40)
351 #define RAM_SET_GC_TAGS_MACRO(o,tags) \
352 (RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0x9f) | (tags)))
353 #define RAM_SET_GC_TAG0_MACRO(o,tag) \
354 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xdf) | (tag))
355 #define RAM_SET_GC_TAG1_MACRO(o,tag) \
356 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xbf) | (tag))
359 #define RAM_GET_FIELD1_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,1))
360 #define RAM_GET_FIELD2_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,2))
361 #define RAM_GET_FIELD3_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,3))
362 #define RAM_SET_FIELD1_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,1), val)
363 #define RAM_SET_FIELD2_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,2), val)
364 #define RAM_SET_FIELD3_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,3), val)
365 #define ROM_GET_FIELD1_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,1))
366 #define ROM_GET_FIELD2_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,2))
367 #define ROM_GET_FIELD3_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,3))
371 #define RAM_GET_FIELD1_MACRO(o) \
372 (ram_get (OBJ_TO_RAM_ADDR(o,1)) + ((RAM_GET_FIELD0_MACRO(o) & 0x03)<<8))
373 #define RAM_GET_FIELD2_MACRO(o) \
374 (ram_get (OBJ_TO_RAM_ADDR(o,2)) + ((RAM_GET_FIELD0_MACRO(o) & 0x0c)<<6))
375 #define RAM_GET_FIELD3_MACRO(o) \
376 (ram_get (OBJ_TO_RAM_ADDR(o,3)) + ((RAM_GET_FIELD0_MACRO(o) & 0x30)<<4))
377 #define RAM_SET_FIELD1_MACRO(o,val) \
379 ram_set (OBJ_TO_RAM_ADDR(o,1), (val) & 0xff); \
380 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xfc) + (((val) >> 8) & 0x03)); \
382 #define RAM_SET_FIELD2_MACRO(o,val) \
384 ram_set (OBJ_TO_RAM_ADDR(o,2), (val) & 0xff); \
385 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xf3) + (((val) >> 6) & 0x0c)); \
387 #define RAM_SET_FIELD3_MACRO(o,val) \
389 ram_set (OBJ_TO_RAM_ADDR(o,3), (val) & 0xff); \
390 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xcf) + (((val) >> 4) & 0x30)); \
392 #define ROM_GET_FIELD1_MACRO(o) \
393 (rom_get (OBJ_TO_ROM_ADDR(o,1)) + ((ROM_GET_FIELD0_MACRO(o) & 0x03)<<8))
394 #define ROM_GET_FIELD2_MACRO(o) \
395 (rom_get (OBJ_TO_ROM_ADDR(o,2)) + ((ROM_GET_FIELD0_MACRO(o) & 0x0c)<<6))
396 #define ROM_GET_FIELD3_MACRO(o) \
397 (rom_get (OBJ_TO_ROM_ADDR(o,3)) + ((ROM_GET_FIELD0_MACRO(o) & 0x30)<<4))
400 uint8
ram_get_gc_tags (obj o
) { return RAM_GET_GC_TAGS_MACRO(o
); }
401 uint8
ram_get_gc_tag0 (obj o
) { return RAM_GET_GC_TAG0_MACRO(o
); }
402 uint8
ram_get_gc_tag1 (obj o
) { return RAM_GET_GC_TAG1_MACRO(o
); }
403 void ram_set_gc_tags (obj o
, uint8 tags
) { RAM_SET_GC_TAGS_MACRO(o
, tags
); }
404 void ram_set_gc_tag0 (obj o
, uint8 tag
) { RAM_SET_GC_TAG0_MACRO(o
,tag
); }
405 void ram_set_gc_tag1 (obj o
, uint8 tag
) { RAM_SET_GC_TAG1_MACRO(o
,tag
); }
406 uint8
ram_get_field0 (obj o
) { return RAM_GET_FIELD0_MACRO(o
); }
407 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
408 word
ram_get_field2 (obj o
) { return RAM_GET_FIELD2_MACRO(o
); }
409 word
ram_get_field3 (obj o
) { return RAM_GET_FIELD3_MACRO(o
); }
410 void ram_set_field0 (obj o
, uint8 val
) { RAM_SET_FIELD0_MACRO(o
,val
); }
411 void ram_set_field1 (obj o
, word val
) { RAM_SET_FIELD1_MACRO(o
,val
); }
412 void ram_set_field2 (obj o
, word val
) { RAM_SET_FIELD2_MACRO(o
,val
); }
413 void ram_set_field3 (obj o
, word val
) { RAM_SET_FIELD3_MACRO(o
,val
); }
414 uint8
rom_get_field0 (obj o
) { return ROM_GET_FIELD0_MACRO(o
); }
415 word
rom_get_field1 (obj o
) { return ROM_GET_FIELD1_MACRO(o
); }
416 word
rom_get_field2 (obj o
) { return ROM_GET_FIELD2_MACRO(o
); }
417 word
rom_get_field3 (obj o
) { return ROM_GET_FIELD3_MACRO(o
); }
419 obj
ram_get_car (obj o
)
420 { return ((ram_get_field0 (o
) & 0x1f) << 8) | ram_get_field1 (o
); }
421 obj
rom_get_car (obj o
)
422 { return ((rom_get_field0 (o
) & 0x1f) << 8) | rom_get_field1 (o
); }
423 obj
ram_get_cdr (obj o
)
424 { return ((ram_get_field2 (o
) & 0x1f) << 8) | ram_get_field3 (o
); }
425 obj
rom_get_cdr (obj o
)
426 { return ((rom_get_field2 (o
) & 0x1f) << 8) | rom_get_field3 (o
); }
427 void ram_set_car (obj o
, obj val
)
429 ram_set_field0 (o
, ((val
& 0x1f00) >> 8) | (ram_get_field0 (o
) & 0xc0));
430 ram_set_field1 (o
, val
& 0xff);
432 void ram_set_cdr (obj o
, obj val
)
434 ram_set_field2 (o
, ((val
& 0x1f00) >> 8) | (ram_get_field2 (o
) & 0xc0));
435 ram_set_field3 (o
, val
& 0xff);
437 obj
ram_get_entry (obj o
)
439 return (((ram_get_field0 (o
) & 0x1f) << 11)
440 | (ram_get_field1 (o
) << 3)
441 | (ram_get_field2 (o
) >> 5));
443 obj
rom_get_entry (obj o
)
445 return (((rom_get_field0 (o
) & 0x1f) << 11)
446 | (rom_get_field1 (o
) << 3)
447 | (rom_get_field2 (o
) >> 5));
450 obj
get_global (uint8 i
)
455 void set_global (uint8 i
, obj o
)
461 void show_type (obj o
) // for debugging purposes
465 if (RAM_BIGNUM(o
)) printf("%x : ram bignum\n", o
);
466 else if (RAM_PAIR(o
)) printf("%x : ram pair\n", o
);
467 else if (RAM_SYMBOL(o
)) printf("%x : ram symbol\n", o
);
468 else if (RAM_STRING(o
)) printf("%x : ram string\n", o
);
469 else if (RAM_VECTOR(o
)) printf("%x : ram vector\n", o
);
470 else if (RAM_CONTINUATION(o
)) printf("%x : ram continuation\n", o
);
471 else if (RAM_CLOSURE(o
)) printf("%x : ram closure\n", o
);
475 if (ROM_BIGNUM(o
)) printf("%x : rom bignum\n", o
);
476 else if (ROM_PAIR(o
)) printf("%x : rom pair\n", o
);
477 else if (ROM_SYMBOL(o
)) printf("%x : rom symbol\n", o
);
478 else if (ROM_STRING(o
)) printf("%x : rom string\n", o
);
479 else if (ROM_VECTOR(o
)) printf("%x : rom vector\n", o
);
480 else if (ROM_CONTINUATION(o
)) printf("%x : rom continuation\n", o
);
481 else if (RAM_CLOSURE(o
)) printf("%x : rom closure\n", o
);
487 /*---------------------------------------------------------------------------*/
489 /* Interface to GC */
491 /* GC tags are in the top 2 bits of field 0 */
492 #define GC_TAG_0_LEFT (1<<5)
493 // TODO was 3<<5, changed to play nice with procedures and bignums, but should actually set only this bit, not clear the other
494 #define GC_TAG_1_LEFT (2<<5)
495 #define GC_TAG_UNMARKED (0<<5)
497 /* Number of object fields of objects in ram */
498 #define HAS_2_OBJECT_FIELDS(visit) (RAM_PAIR(visit) || RAM_CONTINUATION(visit))
499 #define HAS_1_OBJECT_FIELD(visit) (RAM_COMPOSITE(visit) || RAM_CLOSURE(visit))
500 // all composites except pairs and continuations have 1 object field
501 // TODO if we ever have true bignums, bignums will have 1 object field
503 #define NIL OBJ_FALSE
505 /*---------------------------------------------------------------------------*/
507 /* Garbage collector */
509 obj free_list
; /* list of unused cells */
511 obj arg1
; /* root set */
518 uint8 na
; /* interpreter variables */ // TODO number of args, never more than a byte
524 obj second_half
; /* the second half of continuations */
529 void init_ram_heap (void)
532 obj o
= MAX_RAM_ENCODING
;
536 while (o
>= MIN_RAM_ENCODING
)
538 ram_set_gc_tags (o
, GC_TAG_UNMARKED
);
539 ram_set_car (o
, free_list
);
544 for (i
=0; i
<GLOVARS
; i
++)
545 set_global (i
, OBJ_FALSE
);
553 second_half
= OBJ_FALSE
;
573 // TODO seems gc is called much too early, after 256 is reached
575 // IF_GC_TRACE(printf ("push stack=%d (tag=%d) visit=%d (tag=%d)\n", stack, ram_get_gc_tags (stack)>>5, visit, ram_get_gc_tags (visit)>>5)); // TODO error here, tried to get the tag of nil
576 IF_GC_TRACE(printf ("push stack=%d visit=%d (tag=%d)\n", stack
, visit
, ram_get_gc_tags (visit
)>>5));
578 if ((HAS_1_OBJECT_FIELD (visit
) && ram_get_gc_tag0 (visit
))
579 || (HAS_2_OBJECT_FIELDS (visit
)
580 && (ram_get_gc_tags (visit
) != GC_TAG_UNMARKED
)))
581 // TODO ugly condition
582 IF_GC_TRACE(printf ("case 1\n"));
585 if (HAS_2_OBJECT_FIELDS(visit
)) // pairs and continuations
587 IF_GC_TRACE(printf ("case 5\n"));
591 temp
= ram_get_cdr (visit
);
595 IF_GC_TRACE(printf ("case 6\n"));
596 ram_set_gc_tags (visit
, GC_TAG_1_LEFT
);
597 ram_set_cdr (visit
, stack
);
601 IF_GC_TRACE(printf ("case 7\n"));
606 if (HAS_1_OBJECT_FIELD(visit
))
608 IF_GC_TRACE(printf ("case 8\n"));
612 if (RAM_CLOSURE(visit
)) // closures have the pointer in the cdr
613 temp
= ram_get_cdr (visit
);
615 temp
= ram_get_car (visit
);
619 IF_GC_TRACE(printf ("case 9\n"));
620 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
621 if (RAM_CLOSURE(visit
)) // closures still have the pointer in the cdr TODO inverted
622 ram_set_cdr (visit
, stack
); // TODO BREGG is it ok ? closures seem to get messed up
624 ram_set_car (visit
, stack
);
626 goto push
; // TODO the loop goes through here, is the stack correctly set ?
629 IF_GC_TRACE(printf ("case 10\n"));
632 IF_GC_TRACE(printf ("case 11\n"));
634 ram_set_gc_tag0 (visit
, GC_TAG_0_LEFT
); // TODO changed, same as above
639 /* 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)); */
640 // TODO, like for push, getting the gc tags of nil is not great
641 IF_GC_TRACE(printf ("pop stack=%d visit=%d (tag=%d)\n", stack
, visit
, ram_get_gc_tags (visit
)>>6));
645 /* if ((ram_get_gc_tags (stack) == GC_TAG_1_LEFT)) */
646 /* // this condition will always be true for unmarked closures, but */
647 /* // such an object will never be on the stack (procedures will */
648 /* // always be marked at this point), so no false positives */
649 if (HAS_2_OBJECT_FIELDS(stack
) && ram_get_gc_tag1 (stack
))
650 // TODO more specific, might help, but if the bit stays set we'll loop
652 IF_GC_TRACE(printf ("case 13\n"));
654 temp
= ram_get_cdr (stack
); /* pop through cdr */
655 ram_set_cdr (stack
, visit
);
658 /* printf("FOO: %d\n", RAM_CONTINUATION(243)); // TODO ok, it's a continuation that causes us problems */
660 ram_set_gc_tag1(visit
, GC_TAG_UNMARKED
);
661 // we unset the "1-left" bit
666 if (RAM_CLOSURE(stack
)) // TODO doesn't seem to solve the problem
667 // closures have one object field, but it's in the cdr
668 // TODO will the stack ever be a closure ?
670 IF_GC_TRACE(printf ("case 13.5\n")); // TODO renumber cases
672 temp
= ram_get_cdr (stack
); /* pop through cdr */
673 ram_set_cdr (stack
, visit
);
674 visit
= stack
; // TODO BREGG do we set it back as we should ?
680 IF_GC_TRACE(printf ("case 14\n"));
682 temp
= ram_get_car (stack
); /* pop through car */
683 ram_set_car (stack
, visit
);
704 obj visit
= MAX_RAM_ENCODING
;
708 while (visit
>= MIN_RAM_ENCODING
)
710 if ((RAM_COMPOSITE(visit
)
711 && (ram_get_gc_tags (visit
) == GC_TAG_UNMARKED
)) // 2 mark bit
712 || !(ram_get_gc_tags (visit
) & GC_TAG_0_LEFT
)) // 1 mark bit
715 ram_set_car (visit
, free_list
);
718 else // TODO do closures get swept even if they are live ?
720 if (RAM_COMPOSITE(visit
))
721 ram_set_gc_tags (visit
, GC_TAG_UNMARKED
);
722 else // only 1 mark bit to unset
723 ram_set_gc_tag0 (visit
, GC_TAG_UNMARKED
);
735 printf ("**************** memory needed = %d\n", max_live
+1);
745 IF_GC_TRACE(printf("\nGC BEGINS\n"));
754 for (i
=0; i
<GLOVARS
; i
++)
755 mark (get_global (i
));
760 obj
alloc_ram_cell (void)
774 ERROR("memory is full");
779 free_list
= ram_get_car (o
); // TODO was field1
784 obj
alloc_ram_cell_init (uint8 f0
, uint8 f1
, uint8 f2
, uint8 f3
)
786 obj o
= alloc_ram_cell ();
788 ram_set_field0 (o
, f0
);
789 ram_set_field1 (o
, f1
);
790 ram_set_field2 (o
, f2
);
791 ram_set_field3 (o
, f3
);
796 /*---------------------------------------------------------------------------*/
798 int32
decode_int (obj o
)
804 if (o
< MIN_FIXNUM_ENCODING
)
805 TYPE_ERROR("integer");
807 if (o
<= (MIN_FIXNUM_ENCODING
+ (MAX_FIXNUM
- MIN_FIXNUM
)))
808 return DECODE_FIXNUM(o
);
813 TYPE_ERROR("integer");
815 u
= ram_get_field1 (o
);
816 h
= ram_get_field2 (o
);
817 l
= ram_get_field3 (o
);
822 TYPE_ERROR("integer");
824 u
= rom_get_field1 (o
);
825 h
= rom_get_field2 (o
);
826 l
= rom_get_field3 (o
);
829 TYPE_ERROR("integer");
832 return ((int32
)((((int16
)u
- 256) << 8) + h
) << 8) + l
;
834 return ((int32
)(((int16
)u
<< 8) + h
) << 8) + l
;
837 obj
encode_int (int32 n
)
839 if (n
>= MIN_FIXNUM
&& n
<= MAX_FIXNUM
)
840 return ENCODE_FIXNUM(n
);
842 return alloc_ram_cell_init (BIGNUM_FIELD0
, n
>> 16, n
>> 8, n
);
845 /*---------------------------------------------------------------------------*/
857 else if (o
== OBJ_TRUE
)
859 else if (o
== OBJ_NULL
)
861 else if (o
<= (MIN_FIXNUM_ENCODING
+ (MAX_FIXNUM
- MIN_FIXNUM
)))
862 printf ("%d", DECODE_FIXNUM(o
));
863 else // TODO past here, everything is either in ram or in rom, until we add a 3rd space for vectors, that is
872 if ((in_ram
&& RAM_BIGNUM(o
)) || (!in_ram
&& ROM_BIGNUM(o
)))
873 printf ("%d", decode_int (o
));
874 else if ((in_ram
&& RAM_COMPOSITE(o
)) || (!in_ram
&& ROM_COMPOSITE(o
)))
879 if ((in_ram
&& RAM_PAIR(o
)) || (!in_ram
&& ROM_PAIR(o
))) // TODO not exactly efficient, fix it
883 car
= ram_get_car (o
);
884 cdr
= ram_get_cdr (o
);
888 car
= rom_get_car (o
);
889 cdr
= rom_get_cdr (o
);
900 else if ((IN_RAM(cdr
) && RAM_PAIR(cdr
))
901 || (IN_ROM(cdr
) && ROM_PAIR(cdr
)))
905 car
= ram_get_car (cdr
);
906 cdr
= ram_get_cdr (cdr
);
910 car
= rom_get_car (cdr
);
911 cdr
= rom_get_cdr (cdr
);
924 else if ((in_ram
&& RAM_SYMBOL(o
)) || (!in_ram
&& ROM_SYMBOL(o
)))
925 printf ("#<symbol>");
926 else if ((in_ram
&& RAM_STRING(o
)) || (!in_ram
&& ROM_STRING(o
)))
927 printf ("#<string>");
928 else if ((in_ram
&& RAM_VECTOR(o
)) || (!in_ram
&& ROM_VECTOR(o
)))
929 printf ("#<vector>");
933 car
= ram_get_car (o
);
934 cdr
= ram_get_cdr (o
);
935 goto loop
; // TODO ugly hack, takes advantage of the fact that pairs and continuations have the same layout
943 if (IN_RAM(o
)) // TODO can closures be in rom ? I don't think so
944 env
= ram_get_cdr (o
);
946 env
= rom_get_cdr (o
);
949 pc
= ram_get_entry (o
);
951 pc
= rom_get_entry (o
);
953 printf ("{0x%04x ", pc
);
962 void show_state (rom_addr pc
)
965 printf ("pc=0x%04x bytecode=0x%02x env=", pc
, rom_get (pc
));
982 /*---------------------------------------------------------------------------*/
984 /* Integer operations */
986 #define encode_bool(x) ((obj)(x))
988 void prim_numberp (void)
990 if (arg1
>= MIN_FIXNUM_ENCODING
991 && arg1
<= (MIN_FIXNUM_ENCODING
+ (MAX_FIXNUM
- MIN_FIXNUM
)))
996 arg1
= encode_bool (RAM_BIGNUM(arg1
));
997 else if (IN_ROM(arg1
))
998 arg1
= encode_bool (ROM_BIGNUM(arg1
));
1004 void decode_2_int_args (void)
1006 a1
= decode_int (arg1
);
1007 a2
= decode_int (arg2
);
1010 void prim_add (void)
1012 decode_2_int_args ();
1013 arg1
= encode_int (a1
+ a2
);
1017 void prim_sub (void)
1019 decode_2_int_args ();
1020 arg1
= encode_int (a1
- a2
);
1024 void prim_mul (void)
1026 decode_2_int_args ();
1027 arg1
= encode_int (a1
* a2
);
1031 void prim_div (void)
1033 decode_2_int_args ();
1035 ERROR("divide by 0");
1036 arg1
= encode_int (a1
/ a2
);
1040 void prim_rem (void)
1042 decode_2_int_args ();
1044 ERROR("divide by 0");
1045 arg1
= encode_int (a1
% a2
);
1049 void prim_neg (void)
1051 a1
= decode_int (arg1
);
1052 arg1
= encode_int (- a1
);
1057 decode_2_int_args ();
1058 arg1
= encode_bool (a1
== a2
);
1064 decode_2_int_args ();
1065 arg1
= encode_bool (a1
< a2
);
1071 decode_2_int_args ();
1072 arg1
= encode_bool (a1
> a2
);
1076 void prim_ior (void)
1078 a1
= decode_int (arg1
);
1079 a2
= decode_int (arg2
);
1080 arg1
= encode_int (a1
| a2
);
1084 void prim_xor (void)
1086 a1
= decode_int (arg1
);
1087 a2
= decode_int (arg2
);
1088 arg1
= encode_int (a1
^ a2
);
1093 /*---------------------------------------------------------------------------*/
1095 /* List operations */
1097 void prim_pairp (void)
1100 arg1
= encode_bool (RAM_PAIR(arg1
));
1101 else if (IN_ROM(arg1
))
1102 arg1
= encode_bool (ROM_PAIR(arg1
));
1107 obj
cons (obj car
, obj cdr
)
1109 return alloc_ram_cell_init (COMPOSITE_FIELD0
| ((car
& 0x1f00) >> 8),
1111 PAIR_FIELD2
| ((cdr
& 0x1f00) >> 8),
1115 void prim_cons (void)
1117 arg1
= cons (arg1
, arg2
);
1121 void prim_car (void)
1125 if (!RAM_PAIR(arg1
))
1127 arg1
= ram_get_car (arg1
);
1129 else if (IN_ROM(arg1
))
1131 if (!ROM_PAIR(arg1
))
1133 arg1
= rom_get_car (arg1
);
1141 void prim_cdr (void)
1145 if (!RAM_PAIR(arg1
))
1147 arg1
= ram_get_cdr (arg1
);
1149 else if (IN_ROM(arg1
))
1151 if (!ROM_PAIR(arg1
))
1153 arg1
= rom_get_cdr (arg1
);
1161 void prim_set_car (void)
1165 if (!RAM_PAIR(arg1
))
1168 ram_set_car (arg1
, arg2
);
1178 void prim_set_cdr (void)
1182 if (!RAM_PAIR(arg1
))
1185 ram_set_cdr (arg1
, arg2
);
1195 void prim_nullp (void)
1197 arg1
= encode_bool (arg1
== OBJ_NULL
);
1200 /*---------------------------------------------------------------------------*/
1202 /* Miscellaneous operations */
1204 void prim_eqp (void)
1206 arg1
= encode_bool (arg1
== arg2
);
1210 void prim_not (void)
1212 arg1
= encode_bool (arg1
== OBJ_FALSE
);
1215 void prim_symbolp (void)
1218 arg1
= encode_bool (RAM_SYMBOL(arg1
));
1219 else if (IN_ROM(arg1
))
1220 arg1
= encode_bool (ROM_SYMBOL(arg1
));
1225 void prim_stringp (void)
1228 arg1
= encode_bool (RAM_STRING(arg1
));
1229 else if (IN_ROM(arg1
))
1230 arg1
= encode_bool (ROM_STRING(arg1
));
1235 void prim_string2list (void)
1239 if (!RAM_STRING(arg1
))
1240 TYPE_ERROR("string");
1242 arg1
= ram_get_car (arg1
);
1244 else if (IN_ROM(arg1
))
1246 if (!ROM_STRING(arg1
))
1247 TYPE_ERROR("string");
1249 arg1
= rom_get_car (arg1
);
1252 TYPE_ERROR("string");
1255 void prim_list2string (void)
1257 arg1
= alloc_ram_cell_init (COMPOSITE_FIELD0
| ((arg1
& 0x1f00) >> 8),
1264 /*---------------------------------------------------------------------------*/
1266 /* Robot specific operations */
1269 void prim_print (void)
1284 int32
read_clock (void)
1290 now
= from_now( 0 );
1298 static int32 start
= 0;
1303 now
= tb
.time
* 1000 + tb
.millitm
;
1310 static int32 start
= 0;
1313 if (gettimeofday (&tv
, NULL
) == 0)
1315 now
= tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
1329 void prim_clock (void)
1331 arg1
= encode_int (read_clock ());
1335 void prim_motor (void)
1337 decode_2_int_args ();
1339 if (a1
< 1 || a1
> 2 || a2
< -100 || a2
> 100)
1340 ERROR("argument out of range to procedure \"motor\"");
1350 printf ("motor %d -> power=%d\n", a1
, a2
);
1360 void prim_led (void)
1362 decode_2_int_args ();
1363 a3
= decode_int (arg3
);
1365 if (a1
< 1 || a1
> 3 || a2
< 0 || a3
< 0)
1366 ERROR("argument out of range to procedure \"led\"");
1370 LED_set( a1
, a2
, a3
);
1376 printf ("led %d -> duty=%d period=%d\n", a1
, a2
, a3
);
1387 void prim_led2_color (void)
1389 a1
= decode_int (arg1
);
1391 if (a1
< 0 || a1
> 1)
1392 ERROR("argument out of range to procedure \"led2-color\"");
1396 LED2_color_set( a1
);
1402 printf ("led2-color -> %s\n", (a1
==0)?"green":"red");
1411 void prim_getchar_wait (void)
1413 decode_2_int_args();
1414 a1
= read_clock () + a1
;
1416 if (a1
< 0 || a2
< 1 || a2
> 3)
1417 ERROR("argument out of range to procedure \"getchar-wait\"");
1424 serial_port_set ports
;
1425 ports
= serial_rx_wait_with_timeout( a2
, a1
);
1427 arg1
= encode_int (serial_rx_read( ports
));
1442 arg1
= encode_int (_getch ());
1445 } while (read_clock () < a1
);
1450 arg1
= encode_int (getchar ());
1458 void prim_putchar (void)
1460 decode_2_int_args ();
1462 if (a1
< 0 || a1
> 255 || a2
< 1 || a2
> 3)
1463 ERROR("argument out of range to procedure \"putchar\"");
1467 serial_tx_write( a2
, a1
);
1483 void prim_beep (void)
1485 decode_2_int_args ();
1487 if (a1
< 1 || a1
> 255 || a2
< 0)
1488 ERROR("argument out of range to procedure \"beep\"");
1492 beep( a1
, from_now( a2
) );
1498 printf ("beep -> freq-div=%d duration=%d\n", a1
, a2
);
1508 void prim_adc (void)
1512 a1
= decode_int (arg1
);
1514 if (a1
< 1 || a1
> 3)
1515 ERROR("argument out of range to procedure \"adc\"");
1525 x
= read_clock () & 255;
1527 if (x
> 127) x
= 256 - x
;
1533 arg1
= encode_int (x
);
1537 void prim_dac (void)
1539 a1
= decode_int (arg1
);
1541 if (a1
< 0 || a1
> 255)
1542 ERROR("argument out of range to procedure \"dac\"");
1552 printf ("dac -> %d\n", a1
);
1561 void prim_sernum (void)
1577 arg1
= encode_int (x
);
1581 /*---------------------------------------------------------------------------*/
1585 int hidden_fgetc (FILE *f
)
1595 #define fgetc(f) hidden_fgetc(f)
1597 void write_hex_nibble (int n
)
1599 putchar ("0123456789ABCDEF"[n
]);
1602 void write_hex (uint8 n
)
1604 write_hex_nibble (n
>> 4);
1605 write_hex_nibble (n
& 0x0f);
1610 if (c
>= '0' && c
<= '9')
1613 if (c
>= 'A' && c
<= 'F')
1614 return (c
- 'A' + 10);
1616 if (c
>= 'a' && c
<= 'f')
1617 return (c
- 'a' + 10);
1622 int read_hex_byte (FILE *f
)
1624 int h1
= hex (fgetc (f
));
1625 int h2
= hex (fgetc (f
));
1627 if (h1
>= 0 && h2
>= 0)
1628 return (h1
<<4) + h2
;
1633 int read_hex_file (char *filename
)
1636 FILE *f
= fopen (filename
, "r");
1646 for (i
=0; i
<ROM_BYTES
; i
++)
1651 while ((c
= fgetc (f
)) != EOF
)
1653 if ((c
== '\r') || (c
== '\n'))
1657 (len
= read_hex_byte (f
)) < 0 ||
1658 (a1
= read_hex_byte (f
)) < 0 ||
1659 (a2
= read_hex_byte (f
)) < 0 ||
1660 (t
= read_hex_byte (f
)) < 0)
1666 sum
= len
+ a1
+ a2
+ t
;
1674 unsigned long adr
= ((unsigned long)hi16
<< 16) + a
- CODE_START
;
1676 if ((b
= read_hex_byte (f
)) < 0)
1679 if (adr
>= 0 && adr
< ROM_BYTES
)
1682 a
= (a
+ 1) & 0xffff;
1699 if ((a1
= read_hex_byte (f
)) < 0 ||
1700 (a2
= read_hex_byte (f
)) < 0)
1705 hi16
= (a1
<<8) + a2
;
1710 if ((b
= read_hex_byte (f
)) < 0)
1717 printf ("*** HEX file checksum error (expected 0x%02x)\n", sum
);
1723 if ((c
!= '\r') && (c
!= '\n'))
1734 printf ("*** HEX file syntax error\n");
1744 /*---------------------------------------------------------------------------*/
1746 #define FETCH_NEXT_BYTECODE() bytecode = rom_get (pc++)
1748 #define BEGIN_DISPATCH() \
1750 IF_TRACE(show_state (pc)); \
1751 FETCH_NEXT_BYTECODE(); \
1752 bytecode_hi4 = bytecode & 0xf0; \
1753 bytecode_lo4 = bytecode & 0x0f; \
1754 switch (bytecode_hi4 >> 4) {
1756 #define END_DISPATCH() }
1758 #define CASE(opcode) case (opcode>>4):;
1760 #define DISPATCH(); goto dispatch;
1765 #define bytecode TABLAT
1766 #define bytecode_hi4 WREG
1769 #define PUSH_CONSTANT1 0x00
1770 #define PUSH_CONSTANT2 0x10
1771 #define PUSH_STACK1 0x20
1772 #define PUSH_STACK2 0x30
1773 #define PUSH_GLOBAL 0x40
1774 #define SET_GLOBAL 0x50
1777 #define CALL_TOPLEVEL 0x80
1778 #define JUMP_TOPLEVEL 0x90
1780 #define GOTO_IF_FALSE 0xb0
1781 #define CLOSURE 0xc0
1788 char *prim_name
[48] =
1812 "prim #%graft-to-cont",
1813 "prim #%return-to-cont",
1817 "prim #%string->list",
1818 "prim #%list->string",
1826 "prim #%led2-color",
1827 "prim #%getchar-wait",
1834 "push-constant [long]",
1842 #define PUSH_ARG1() push_arg1 ()
1845 void push_arg1 (void)
1847 env
= cons (arg1
, env
);
1853 obj o
= ram_get_car (env
);
1854 env
= ram_get_cdr (env
);
1858 void pop_procedure (void)
1864 if (!RAM_CLOSURE(arg1
))
1865 TYPE_ERROR("procedure");
1867 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
1869 else if (IN_ROM(arg1
))
1871 if (!ROM_CLOSURE(arg1
))
1872 TYPE_ERROR("procedure");
1874 entry
= rom_get_entry (arg1
) + CODE_START
;
1877 TYPE_ERROR("procedure");
1880 void handle_arity_and_rest_param (void)
1884 np
= rom_get (entry
++);
1886 if ((np
& 0x80) == 0)
1889 ERROR("wrong number of arguments");
1896 ERROR("wrong number of arguments");
1904 arg3
= cons (arg4
, arg3
);
1910 arg1
= cons (arg3
, arg1
);
1911 arg3
= OBJ_FALSE
; // TODO changed nothing with the new new closures, everything looks ok
1915 void build_env (void)
1921 arg1
= cons (arg3
, arg1
);
1926 arg3
= OBJ_FALSE
; // TODO changed nothing here either
1929 void save_cont (void)
1931 // the second half is a closure
1932 second_half
= alloc_ram_cell_init (CLOSURE_FIELD0
| (pc
>> 11),
1934 ((pc
& 0x0007) << 5) | (env
>> 8),
1936 cont
= alloc_ram_cell_init (COMPOSITE_FIELD0
| (cont
>> 8),
1938 CONTINUATION_FIELD2
| (second_half
>> 8),
1939 second_half
& 0xff);
1942 void interpreter (void)
1946 pc
= (CODE_START
+ 4) + ((rom_addr
)rom_get (CODE_START
+2) << 2);
1950 /***************************************************************************/
1951 CASE(PUSH_CONSTANT1
);
1953 IF_TRACE(printf(" (push-constant "); show (bytecode_lo4
); printf (")\n"));
1955 arg1
= bytecode_lo4
;
1961 /***************************************************************************/
1962 CASE(PUSH_CONSTANT2
);
1964 IF_TRACE(printf(" (push-constant "); show (bytecode_lo4
+16); printf (")\n"));
1965 arg1
= bytecode_lo4
+16;
1971 /***************************************************************************/
1974 IF_TRACE(printf(" (push-stack %d)\n", bytecode_lo4
));
1978 while (bytecode_lo4
!= 0)
1980 arg1
= ram_get_cdr (arg1
);
1984 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
1990 /***************************************************************************/
1993 IF_TRACE(printf(" (push-stack %d)\n", bytecode_lo4
+16));
1999 while (bytecode_lo4
!= 0)
2001 arg1
= ram_get_cdr (arg1
);
2005 arg1
= ram_get_car (arg1
);
2011 /***************************************************************************/
2014 IF_TRACE(printf(" (push-global %d)\n", bytecode_lo4
));
2016 arg1
= get_global (bytecode_lo4
);
2022 /***************************************************************************/
2025 IF_TRACE(printf(" (set-global %d)\n", bytecode_lo4
));
2027 set_global (bytecode_lo4
, POP());
2031 /***************************************************************************/
2034 IF_TRACE(printf(" (call %d)\n", bytecode_lo4
));
2039 handle_arity_and_rest_param ();
2050 /***************************************************************************/
2053 IF_TRACE(printf(" (jump %d)\n", bytecode_lo4
));
2058 handle_arity_and_rest_param ();
2068 /***************************************************************************/
2069 CASE(CALL_TOPLEVEL
);
2071 FETCH_NEXT_BYTECODE();
2072 second_half
= bytecode
; // TODO make sure second_half is not already in use
2074 FETCH_NEXT_BYTECODE();
2076 IF_TRACE(printf(" (call-toplevel 0x%04x)\n", ((second_half
<< 8) | bytecode
) + CODE_START
));
2078 entry
= (second_half
<< 8) + bytecode
+ CODE_START
; // TODO FOOBAR we have the last 4 bits of the opcode free, to do pretty much anything
2081 na
= rom_get (entry
++);
2093 /***************************************************************************/
2094 CASE(JUMP_TOPLEVEL
);
2096 FETCH_NEXT_BYTECODE();
2097 second_half
= bytecode
; // TODO make sure second_half is not already in use
2099 FETCH_NEXT_BYTECODE();
2101 IF_TRACE(printf(" (jump-toplevel 0x%04x)\n", ((second_half
<< 8) | bytecode
) + CODE_START
));
2103 entry
= (second_half
<< 8) + bytecode
+ CODE_START
; // TODO this is a common pattern
2106 na
= rom_get (entry
++);
2117 /***************************************************************************/
2120 FETCH_NEXT_BYTECODE();
2121 second_half
= bytecode
;
2123 FETCH_NEXT_BYTECODE();
2125 // TODO goto's use 12-bit addresses, unlike calls and jumps, which use 16, is it ok ?
2126 // actually, the compiler gives them 16 bit addresses now, it seems
2127 // that means we have even more free instructions, but that now even gotos are on 3 bytes
2128 IF_TRACE(printf(" (goto 0x%04x)\n", ((rom_addr
)(bytecode_lo4
+ (CODE_START
>> 8)) << 8) + bytecode
));
2130 pc
= (second_half
<< 8) + bytecode
+ CODE_START
;
2131 /* pc = ((rom_addr)(bytecode_lo4 + (CODE_START >> 8)) << 8) + bytecode; */ // TODO not anymore
2135 /***************************************************************************/
2136 CASE(GOTO_IF_FALSE
);
2138 FETCH_NEXT_BYTECODE();
2139 second_half
= bytecode
;
2141 FETCH_NEXT_BYTECODE();
2143 IF_TRACE(printf(" (goto-if-false 0x%04x)\n", ((rom_addr
)(bytecode_lo4
+ (CODE_START
>> 8)) << 8) + bytecode
));
2145 if (POP() == OBJ_FALSE
)
2146 pc
= (second_half
<< 8) + bytecode
+ CODE_START
;
2147 /* pc = ((rom_addr)(bytecode_lo4 + (CODE_START >> 8)) << 8) + bytecode; */
2151 /***************************************************************************/
2154 FETCH_NEXT_BYTECODE();
2155 second_half
= bytecode
;
2157 FETCH_NEXT_BYTECODE();
2159 IF_TRACE(printf(" (closure 0x%04x)\n", (second_half
<< 8) | bytecode
));
2160 // TODO original had CODE_START, while the real code below didn't
2162 /* 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
2163 arg3
= POP(); // env
2165 entry
= (second_half
<< 8) | bytecode
; // TODO original had no CODE_START, why ?
2167 arg1
= alloc_ram_cell_init (CLOSURE_FIELD0
| (second_half
>> 3),
2168 ((second_half
& 0x07) << 5) | (bytecode
>> 3),
2169 ((bytecode
& 0x07) << 5) |((arg3
& 0x1f00) >> 8),
2179 /***************************************************************************/
2182 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
]));
2184 switch (bytecode_lo4
)
2187 arg1
= POP(); prim_numberp (); PUSH_ARG1(); break;
2189 arg2
= POP(); arg1
= POP(); prim_add (); PUSH_ARG1(); break;
2191 arg2
= POP(); arg1
= POP(); prim_sub (); PUSH_ARG1(); break;
2193 arg2
= POP(); arg1
= POP(); prim_mul (); PUSH_ARG1(); break;
2195 arg2
= POP(); arg1
= POP(); prim_div (); PUSH_ARG1(); break;
2197 arg2
= POP(); arg1
= POP(); prim_rem (); PUSH_ARG1(); break;
2199 arg1
= POP(); prim_neg (); PUSH_ARG1(); break;
2201 arg2
= POP(); arg1
= POP(); prim_eq (); PUSH_ARG1(); break;
2203 arg2
= POP(); arg1
= POP(); prim_lt (); PUSH_ARG1(); break;
2205 arg2
= POP(); arg1
= POP(); prim_ior (); PUSH_ARG1(); break;
2207 arg2
= POP(); arg1
= POP(); prim_gt (); PUSH_ARG1(); break;
2209 arg2
= POP(); arg1
= POP(); prim_xor (); PUSH_ARG1(); break;
2211 arg1
= POP(); prim_pairp (); PUSH_ARG1(); break;
2213 arg2
= POP(); arg1
= POP(); prim_cons (); PUSH_ARG1(); break;
2215 arg1
= POP(); prim_car (); PUSH_ARG1(); break;
2217 arg1
= POP(); prim_cdr (); PUSH_ARG1(); break;
2222 /***************************************************************************/
2225 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
+16]));
2227 switch (bytecode_lo4
)
2230 arg2
= POP(); arg1
= POP(); prim_set_car (); break;
2232 arg2
= POP(); arg1
= POP(); prim_set_cdr (); break;
2234 arg1
= POP(); prim_nullp (); PUSH_ARG1(); break;
2236 arg2
= POP(); arg1
= POP(); prim_eqp (); PUSH_ARG1(); break;
2238 arg1
= POP(); prim_not (); PUSH_ARG1(); break;
2240 /* prim #%get-cont */
2245 /* prim #%graft-to-cont */
2247 arg1
= POP(); /* thunk to call */
2248 cont
= POP(); /* continuation */
2255 handle_arity_and_rest_param ();
2265 /* prim #%return-to-cont */
2267 arg1
= POP(); /* value to return */
2268 cont
= POP(); /* continuation */
2270 second_half
= ram_get_cdr (cont
);
2272 pc
= ram_get_entry (second_half
);
2274 env
= ram_get_cdr (second_half
);
2275 cont
= ram_get_car (cont
);
2284 /* prim #%symbol? */
2285 arg1
= POP(); prim_symbolp (); PUSH_ARG1(); break;
2287 /* prim #%string? */
2288 arg1
= POP(); prim_stringp (); PUSH_ARG1(); break;
2290 /* prim #%string->list */
2291 arg1
= POP(); prim_string2list (); PUSH_ARG1(); break;
2293 /* prim #%list->string */
2294 arg1
= POP(); prim_list2string (); PUSH_ARG1(); break;
2307 /***************************************************************************/
2310 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
+32]));
2312 switch (bytecode_lo4
)
2321 prim_clock (); PUSH_ARG1(); break;
2324 arg2
= POP(); arg1
= POP(); prim_motor (); break;
2327 arg3
= POP(); arg2
= POP(); arg1
= POP(); prim_led (); ;break;
2329 /* prim #%led2-color */
2330 arg1
= POP(); prim_led2_color (); break;
2332 /* prim #%getchar-wait */
2333 arg2
= POP(); arg1
= POP(); prim_getchar_wait (); PUSH_ARG1(); break;
2335 /* prim #%putchar */
2336 arg2
= POP(); arg1
= POP(); prim_putchar (); break;
2339 arg2
= POP(); arg1
= POP(); prim_beep (); break;
2342 arg1
= POP(); prim_adc (); PUSH_ARG1(); break;
2345 arg1
= POP(); prim_dac (); break;
2348 prim_sernum (); PUSH_ARG1(); break;
2354 /* push-constant [long] */ // BARF seems to be wrong
2355 FETCH_NEXT_BYTECODE();
2356 second_half
= bytecode
;
2357 FETCH_NEXT_BYTECODE();
2358 arg1
= (second_half
<< 8) | bytecode
;
2374 second_half
= ram_get_cdr (cont
);
2375 pc
= ram_get_entry (second_half
);
2376 env
= ram_get_cdr (second_half
);
2377 cont
= ram_get_car (cont
);
2384 /***************************************************************************/
2389 /*---------------------------------------------------------------------------*/
2395 printf ("usage: sim file.hex\n");
2399 int main (int argc
, char *argv
[])
2402 rom_addr rom_start_addr
= 0;
2404 if (argc
> 1 && argv
[1][0] == '-' && argv
[1][1] == 's')
2411 if ((h1
= hex (argv
[1][2])) < 0 ||
2412 (h2
= hex (argv
[1][3])) < 0 ||
2413 (h3
= hex (argv
[1][4])) != 0 ||
2414 (h4
= hex (argv
[1][5])) != 0 ||
2418 rom_start_addr
= (h1
<< 12) | (h2
<< 8) | (h3
<< 4) | h4
;
2425 printf ("Start address = 0x%04x\n", rom_start_addr
); // TODO says 0, but should be CODE_START ?
2431 if (!read_hex_file (argv
[1]))
2432 printf ("*** Could not read hex file \"%s\"\n", argv
[1]);
2437 if (rom_get (CODE_START
+0) != 0xfb ||
2438 rom_get (CODE_START
+1) != 0xd7)
2439 printf ("*** The hex file was not compiled with PICOBIT\n");
2443 for (i
=0; i
<8192; i
++)
2444 if (rom_get (i
) != 0xff)
2445 printf ("rom_mem[0x%04x] = 0x%02x\n", i
, rom_get (i
));
2451 printf ("**************** memory needed = %d\n", max_live
+1);
2461 /*---------------------------------------------------------------------------*/