1 /* file: "picobit-vm.c" */
4 * Copyright 2008 by Marc Feeley and Vincent St-Amour, All Rights Reserved.
8 * 15/08/2004 Release of version 1
9 * 06/07/2008 Modified for PICOBOARD2_R3
10 * 18/07/2008 Modified to use new object representation
11 * 17/12/2008 Release of version 2
16 // TODO once this is stable, put as default
17 #define INFINITE_PRECISION_BIGNUMS_not
19 /*---------------------------------------------------------------------------*/
24 typedef unsigned char uint8
;
25 typedef unsigned short uint16
;
26 typedef unsigned long uint32
;
31 typedef uint8 boolean
;
32 // TODO was signed, preventive change
34 /*---------------------------------------------------------------------------*/
54 static volatile near uint8 FW_VALUE_UP @
0x33;
55 static volatile near uint8 FW_VALUE_HI @
0x33;
56 static volatile near uint8 FW_VALUE_LO @
0x33;
58 #define ACTIVITY_LED1_LAT LATB
59 #define ACTIVITY_LED1_BIT 5
60 #define ACTIVITY_LED2_LAT LATB
61 #define ACTIVITY_LED2_BIT 4
62 static volatile near bit ACTIVITY_LED1 @
((unsigned)&ACTIVITY_LED1_LAT
*8)+ACTIVITY_LED1_BIT
;
63 static volatile near bit ACTIVITY_LED2 @
((unsigned)&ACTIVITY_LED2_LAT
*8)+ACTIVITY_LED2_BIT
;
76 #define MAX_PACKET_SIZE BUFSIZ
80 char errbuf
[PCAP_ERRBUF_SIZE
];
83 #define INTERFACE "eth0"
85 char buf
[MAX_PACKET_SIZE
]; // buffer for writing
89 #include <sys/types.h>
90 #include <sys/timeb.h>
99 /*---------------------------------------------------------------------------*/
103 #define CODE_START 0x5000
106 #define IF_TRACE(x) x
107 #define IF_GC_TRACE(x) x
110 #define IF_GC_TRACE(x)
113 /*---------------------------------------------------------------------------*/
118 #define ERROR(prim, msg) halt_with_error()
119 #define TYPE_ERROR(prim, type) halt_with_error()
126 #define ERROR(prim, msg) error (prim, msg)
127 #define TYPE_ERROR(prim, type) type_error (prim, type)
129 void error (char *prim
, char *msg
)
131 printf ("ERROR: %s: %s\n", prim
, msg
);
135 void type_error (char *prim
, char *type
)
137 printf ("ERROR: %s: An argument of type %s was expected\n", prim
, type
);
144 /*---------------------------------------------------------------------------*/
152 typedef uint16 ram_addr
;
153 typedef uint16 rom_addr
;
157 #ifdef INFINITE_PRECISION_BIGNUMS
159 #define digit_width 16
162 typedef uint16 digit
; // TODO why this ? adds to the confusion
163 typedef uint32 two_digit
;
167 /*---------------------------------------------------------------------------*/
169 #define MAX_VEC_ENCODING 8191
170 #define MIN_VEC_ENCODING 4096
171 #define VEC_BYTES ((MAX_VEC_ENCODING - MIN_VEC_ENCODING + 1)*4)
172 // TODO this is new. if the pic has less than 8k of memory, start this lower
173 // TODO the pic actually has 2k, so change these
174 // TODO we'd only actually need 1024 or so for ram and vectors, since we can't address more. this gives us a lot of rom space
176 #define MAX_RAM_ENCODING 4095
177 #define MIN_RAM_ENCODING 512
178 #define RAM_BYTES ((MAX_RAM_ENCODING - MIN_RAM_ENCODING + 1)*4)
179 // TODO watch out if we address more than what the PIC actually has
182 #define OBJ_TO_VEC_ADDR(o,f) (((ram_addr)((uint16)(o) - MIN_RAM_ENCODING) << 2) + (f))
183 #define OBJ_TO_RAM_ADDR(o,f) (((ram_addr)((uint16)(o) - MIN_RAM_ENCODING) << 2) + (f))
184 #define OBJ_TO_ROM_ADDR(o,f) (((rom_addr)((uint16)(o) - MIN_ROM_ENCODING) << 2) + (CODE_START + 4 + (f)))
189 #define ram_get(a) *(uint8*)(a+0x200)
190 #define ram_set(a,x) *(uint8*)(a+0x200) = (x)
196 uint8 ram_mem
[RAM_BYTES
+ VEC_BYTES
];
198 #define ram_get(a) ram_mem[a]
199 #define ram_set(a,x) ram_mem[a] = (x)
204 /*---------------------------------------------------------------------------*/
208 uint8
rom_get (rom_addr a
)
210 return *(rom uint8
*)a
;
218 #define ROM_BYTES 8192
219 // TODO the new pics have 32k, change this ? minus the vm size, firmware ?
221 uint8 rom_mem
[ROM_BYTES
] =
224 #define PUTCHAR_LIGHT_not
227 0xFB, 0xD7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x32
228 , 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
229 , 0x08, 0x50, 0x80, 0x16, 0xFE, 0xE8, 0x00, 0xFC
230 , 0x32, 0x80, 0x2D, 0xFE, 0xFC, 0x31, 0x80, 0x43
231 , 0xFE, 0xFC, 0x33, 0x80, 0x2D, 0xFE, 0xFC, 0x31
232 , 0x80, 0x43, 0xFE, 0x90, 0x16, 0x01, 0x20, 0xFC
233 , 0x32, 0xE3, 0xB0, 0x37, 0x09, 0xF3, 0xFF, 0x20
234 , 0xFC, 0x33, 0xE3, 0xB0, 0x40, 0x0A, 0xF3, 0xFF
235 , 0x08, 0xF3, 0xFF, 0x01, 0x40, 0x21, 0xD1, 0x00
236 , 0x02, 0xC0, 0x4C, 0x71, 0x01, 0x20, 0x50, 0x90
237 , 0x51, 0x00, 0xF1, 0x40, 0xD8, 0xB0, 0x59, 0x90
241 0xFB, 0xD7, 0x00, 0x00, 0x80, 0x08, 0xFE, 0xE8
242 , 0x00, 0xF6, 0xF5, 0x90, 0x08
246 uint8
rom_get (rom_addr a
)
248 return rom_mem
[a
-CODE_START
];
253 /*---------------------------------------------------------------------------*/
261 fixnum n MIN_FIXNUM -> 3 ... MAX_FIXNUM -> 3 + (MAX_FIXNUM-MIN_FIXNUM)
262 rom object 4 + (MAX_FIXNUM-MIN_FIXNUM) ... MIN_RAM_ENCODING-1
263 ram object MIN_RAM_ENCODING ... MAX_RAM_ENCODING
264 u8vector MIN_VEC_ENCODING ... 8191
266 layout of memory allocated objects:
268 G's represent mark bits used by the gc
270 ifdef INFINITE_PRECISION_BIGNUMS
271 bignum n 0GG***** **next** hhhhhhhh llllllll (16 bit digit)
272 TODO what to do with the gc tags for the bignums ? will this work ?
274 ifndef INFINITE_PRECISION_BIGNUMS
275 bignum n 00000000 uuuuuuuu hhhhhhhh llllllll (24 bit signed integer)
277 pair 1GGaaaaa aaaaaaaa 000ddddd dddddddd
280 gives an address space of 2^13 * 4 = 32k divided between simple objects,
283 symbol 1GG00000 00000000 00100000 00000000
285 string 1GG***** *chars** 01000000 00000000
287 u8vector 1GGxxxxx xxxxxxxx 011yyyyy yyyyyyyy
288 x is length of the vector, in bytes (stored raw, not encoded as an object)
289 y is pointer to the elements themselves (stored in vector space)
291 closure 01Gaaaaa aaaaaaaa aaaxxxxx xxxxxxxx
292 0x5ff<a<0x4000 is entry
293 x is pointer to environment
294 the reason why the environment is on the cdr (and the entry is split on 3
295 bytes) is that, when looking for a variable, a closure is considered to be a
296 pair. The compiler adds an extra offset to any variable in the closure's
297 environment, so the car of the closure (which doesn't really exist) is never
298 checked, but the cdr is followed to find the other bindings
300 continuation 1GGxxxxx xxxxxxxx 100yyyyy yyyyyyyy
301 x is parent continuation
302 y is pointer to the second half, which is a closure (contains env and entry)
304 An environment is a list of objects built out of pairs. On entry to
305 a procedure the environment is the list of parameters to which is
306 added the environment of the closure being called.
308 The first byte at the entry point of a procedure gives the arity of
311 n = 0 to 127 -> procedure has n parameters (no rest parameter)
312 n = -128 to -1 -> procedure has -n parameters, the last is
318 #define encode_bool(x) ((obj)(x))
322 #define MIN_FIXNUM_ENCODING 3
323 // TODO change these ? were -5 and 40, with the new bignums, the needs for these might change
324 #define MIN_FIXNUM -1
325 #define MAX_FIXNUM 255
326 #define MIN_ROM_ENCODING (MIN_FIXNUM_ENCODING+MAX_FIXNUM-MIN_FIXNUM+1)
328 #define ENCODE_FIXNUM(n) ((obj)(n) + (MIN_FIXNUM_ENCODING - MIN_FIXNUM))
329 #define DECODE_FIXNUM(o) ((int32)(o) - (MIN_FIXNUM_ENCODING - MIN_FIXNUM))
331 // TODO why this ifdef ?
333 #define IN_VEC(o) ((o) >= MIN_VEC_ENCODING)
334 #define IN_RAM(o) (!IN_VEC(o) && ((o) >= MIN_RAM_ENCODING))
335 #define IN_ROM(o) (!IN_VEC(o) && !IN_RAM(o) && ((o) >= MIN_ROM_ENCODING))
338 // bignum first byte : 00Gxxxxx
339 #define BIGNUM_FIELD0 0
340 #define RAM_BIGNUM(o) ((ram_get_field0 (o) & 0xc0) == BIGNUM_FIELD0)
341 #define ROM_BIGNUM(o) ((rom_get_field0 (o) & 0xc0) == BIGNUM_FIELD0)
343 // composite first byte : 1GGxxxxx
344 #define COMPOSITE_FIELD0 0x80
345 #define RAM_COMPOSITE(o) ((ram_get_field0 (o) & 0x80) == COMPOSITE_FIELD0)
346 #define ROM_COMPOSITE(o) ((rom_get_field0 (o) & 0x80) == COMPOSITE_FIELD0)
348 // pair third byte : 000xxxxx
349 #define PAIR_FIELD2 0
350 #define RAM_PAIR(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == PAIR_FIELD2))
351 #define ROM_PAIR(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == PAIR_FIELD2))
353 // symbol third byte : 001xxxxx
354 #define SYMBOL_FIELD2 0x20
355 #define RAM_SYMBOL(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == SYMBOL_FIELD2))
356 #define ROM_SYMBOL(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == SYMBOL_FIELD2))
358 // string third byte : 010xxxxx
359 #define STRING_FIELD2 0x40
360 #define RAM_STRING(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == STRING_FIELD2))
361 #define ROM_STRING(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == STRING_FIELD2))
363 // vector third byte : 011xxxxx
364 #define VECTOR_FIELD2 0x60
365 #define RAM_VECTOR(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == VECTOR_FIELD2))
366 #define ROM_VECTOR(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == VECTOR_FIELD2))
368 // continuation third byte : 100xxxxx
369 #define CONTINUATION_FIELD2 0x80
370 #define RAM_CONTINUATION(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == CONTINUATION_FIELD2))
371 #define ROM_CONTINUATION(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == CONTINUATION_FIELD2))
373 // closure first byte : 01Gxxxxx
374 #define CLOSURE_FIELD0 0x40
375 #define RAM_CLOSURE(o) ((ram_get_field0 (o) & 0xc0) == CLOSURE_FIELD0)
376 #define ROM_CLOSURE(o) ((rom_get_field0 (o) & 0xc0) == CLOSURE_FIELD0)
379 /*---------------------------------------------------------------------------*/
381 #define RAM_GET_FIELD0_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,0))
382 #define RAM_SET_FIELD0_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,0), val)
383 #define ROM_GET_FIELD0_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,0))
385 #define RAM_GET_GC_TAGS_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x60)
386 #define RAM_GET_GC_TAG0_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x20)
387 #define RAM_GET_GC_TAG1_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x40)
388 #define RAM_SET_GC_TAGS_MACRO(o,tags) \
389 (RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0x9f) | (tags)))
390 #define RAM_SET_GC_TAG0_MACRO(o,tag) \
391 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xdf) | (tag))
392 #define RAM_SET_GC_TAG1_MACRO(o,tag) \
393 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xbf) | (tag))
396 #define RAM_GET_FIELD1_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,1))
397 #define RAM_GET_FIELD2_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,2))
398 #define RAM_GET_FIELD3_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,3))
399 #define RAM_SET_FIELD1_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,1), val)
400 #define RAM_SET_FIELD2_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,2), val)
401 #define RAM_SET_FIELD3_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,3), val)
402 #define ROM_GET_FIELD1_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,1))
403 #define ROM_GET_FIELD2_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,2))
404 #define ROM_GET_FIELD3_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,3))
405 #define VEC_GET_BYTE0_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,0))
406 #define VEC_GET_BYTE1_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,1))
407 #define VEC_GET_BYTE2_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,2))
408 #define VEC_GET_BYTE3_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,3))
409 #define VEC_SET_BYTE0_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,0), val)
410 #define VEC_SET_BYTE1_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,1), val)
411 #define VEC_SET_BYTE2_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,2), val)
412 #define VEC_SET_BYTE3_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,3), val)
415 uint8
ram_get_gc_tags (obj o
) { return RAM_GET_GC_TAGS_MACRO(o
); }
416 uint8
ram_get_gc_tag0 (obj o
) { return RAM_GET_GC_TAG0_MACRO(o
); }
417 uint8
ram_get_gc_tag1 (obj o
) { return RAM_GET_GC_TAG1_MACRO(o
); }
418 void ram_set_gc_tags (obj o
, uint8 tags
) { RAM_SET_GC_TAGS_MACRO(o
, tags
); }
419 void ram_set_gc_tag0 (obj o
, uint8 tag
) { RAM_SET_GC_TAG0_MACRO(o
,tag
); }
420 void ram_set_gc_tag1 (obj o
, uint8 tag
) { RAM_SET_GC_TAG1_MACRO(o
,tag
); }
421 uint8
ram_get_field0 (obj o
) { return RAM_GET_FIELD0_MACRO(o
); }
422 word
ram_get_field1 (obj o
) { return RAM_GET_FIELD1_MACRO(o
); }
423 word
ram_get_field2 (obj o
) { return RAM_GET_FIELD2_MACRO(o
); }
424 word
ram_get_field3 (obj o
) { return RAM_GET_FIELD3_MACRO(o
); }
425 word
ram_get_fieldn (obj o
, uint8 n
)
429 case 0: return ram_get_field0 (o
);
430 case 1: return ram_get_field1 (o
);
431 case 2: return ram_get_field2 (o
);
432 case 3: return ram_get_field3 (o
);
435 void ram_set_field0 (obj o
, uint8 val
) { RAM_SET_FIELD0_MACRO(o
,val
); }
436 void ram_set_field1 (obj o
, word val
) { RAM_SET_FIELD1_MACRO(o
,val
); }
437 void ram_set_field2 (obj o
, word val
) { RAM_SET_FIELD2_MACRO(o
,val
); }
438 void ram_set_field3 (obj o
, word val
) { RAM_SET_FIELD3_MACRO(o
,val
); }
439 void ram_set_fieldn (obj o
, uint8 n
, word val
)
443 case 0: ram_set_field0 (o
, val
); break;
444 case 1: ram_set_field1 (o
, val
); break;
445 case 2: ram_set_field2 (o
, val
); break;
446 case 3: ram_set_field3 (o
, val
); break;
449 uint8
rom_get_field0 (obj o
) { return ROM_GET_FIELD0_MACRO(o
); }
450 word
rom_get_field1 (obj o
) { return ROM_GET_FIELD1_MACRO(o
); }
451 word
rom_get_field2 (obj o
) { return ROM_GET_FIELD2_MACRO(o
); }
452 word
rom_get_field3 (obj o
) { return ROM_GET_FIELD3_MACRO(o
); }
453 /* word vec_get_byte0 (obj o) { return VEC_GET_BYTE0_MACRO(o); } */
454 /* word vec_get_byte1 (obj o) { return VEC_GET_BYTE1_MACRO(o); } */
455 /* word vec_get_byte2 (obj o) { return VEC_GET_BYTE2_MACRO(o); } */
456 /* word vec_get_byte3 (obj o) { return VEC_GET_BYTE3_MACRO(o); } */
457 /* word vec_set_byte0 (obj o, word val) { VEC_SET_BYTE0_MACRO(o,val); } */
458 /* word vec_set_byte1 (obj o, word val) { VEC_SET_BYTE1_MACRO(o,val); } */
459 /* word vec_set_byte2 (obj o, word val) { VEC_SET_BYTE2_MACRO(o,val); } */
460 /* word vec_set_byte3 (obj o, word val) { VEC_SET_BYTE3_MACRO(o,val); } */
462 obj
get_field0 (obj o
) // TODO these are not used yet, will they be useful at all ?
465 return ram_get_field0 (o
);
467 return rom_get_field0 (o
);
469 obj
get_field1 (obj o
)
472 return ram_get_field1 (o
);
474 return rom_get_field1 (o
);
476 obj
get_field2 (obj o
)
479 return ram_get_field2 (o
);
481 return rom_get_field2 (o
);
483 obj
get_field3 (obj o
)
486 return ram_get_field3 (o
);
488 return rom_get_field3 (o
);
492 obj
ram_get_car (obj o
)
493 { return ((ram_get_field0 (o
) & 0x1f) << 8) | ram_get_field1 (o
); }
494 obj
rom_get_car (obj o
)
495 { return ((rom_get_field0 (o
) & 0x1f) << 8) | rom_get_field1 (o
); }
496 obj
ram_get_cdr (obj o
)
497 { return ((ram_get_field2 (o
) & 0x1f) << 8) | ram_get_field3 (o
); }
498 obj
rom_get_cdr (obj o
)
499 { return ((rom_get_field2 (o
) & 0x1f) << 8) | rom_get_field3 (o
); }
503 return ram_get_car (o
);
505 return rom_get_car (o
);
510 return ram_get_cdr (o
);
512 return rom_get_cdr (o
);
515 void ram_set_car (obj o
, obj val
)
517 ram_set_field0 (o
, (val
>> 8) | (ram_get_field0 (o
) & 0xe0));
518 ram_set_field1 (o
, val
& 0xff);
520 void ram_set_cdr (obj o
, obj val
)
522 ram_set_field2 (o
, (val
>> 8) | (ram_get_field2 (o
) & 0xe0));
523 ram_set_field3 (o
, val
& 0xff);
526 obj
ram_get_entry (obj o
)
528 return (((ram_get_field0 (o
) & 0x1f) << 11)
529 | (ram_get_field1 (o
) << 3)
530 | (ram_get_field2 (o
) >> 5));
532 obj
rom_get_entry (obj o
)
534 return (((rom_get_field0 (o
) & 0x1f) << 11)
535 | (rom_get_field1 (o
) << 3)
536 | (rom_get_field2 (o
) >> 5));
538 obj
get_entry (obj o
)
541 return ram_get_entry (o
);
543 return rom_get_entry (o
);
547 obj
get_global (uint8 i
)
548 // globals occupy the beginning of ram, with 2 globals per word
551 return ram_get_cdr (MIN_RAM_ENCODING
+ (i
/ 2));
553 return ram_get_car (MIN_RAM_ENCODING
+ (i
/ 2));
556 void set_global (uint8 i
, obj o
)
559 ram_set_cdr (MIN_RAM_ENCODING
+ (i
/ 2), o
);
561 ram_set_car (MIN_RAM_ENCODING
+ (i
/ 2), o
);
565 void show_type (obj o
) // for debugging purposes
568 if (o
== OBJ_FALSE
) printf("#f");
569 else if (o
== OBJ_TRUE
) printf("#t");
570 else if (o
== OBJ_NULL
) printf("()");
571 else if (o
< MIN_ROM_ENCODING
) printf("fixnum");
574 if (RAM_BIGNUM(o
)) printf("ram bignum");
575 else if (RAM_PAIR(o
)) printf("ram pair");
576 else if (RAM_SYMBOL(o
)) printf("ram symbol");
577 else if (RAM_STRING(o
)) printf("ram string");
578 else if (RAM_VECTOR(o
)) printf("ram vector");
579 else if (RAM_CONTINUATION(o
)) printf("ram continuation");
580 else if (RAM_CLOSURE(o
)) printf("ram closure");
584 if (ROM_BIGNUM(o
)) printf("rom bignum");
585 else if (ROM_PAIR(o
)) printf("rom pair");
586 else if (ROM_SYMBOL(o
)) printf("rom symbol");
587 else if (ROM_STRING(o
)) printf("rom string");
588 else if (ROM_VECTOR(o
)) printf("rom vector");
589 else if (ROM_CONTINUATION(o
)) printf("rom continuation");
590 else if (RAM_CLOSURE(o
)) printf("rom closure");
597 /*---------------------------------------------------------------------------*/
599 /* Interface to GC */
601 // TODO explain what each tag means, with 1-2 mark bits
602 #define GC_TAG_0_LEFT (1<<5)
603 #define GC_TAG_1_LEFT (2<<5)
604 #define GC_TAG_UNMARKED (0<<5)
606 /* Number of object fields of objects in ram */
607 #define HAS_2_OBJECT_FIELDS(visit) (RAM_PAIR(visit) || RAM_CONTINUATION(visit))
608 #ifdef INFINITE_PRECISION_BIGNUMS
609 #define HAS_1_OBJECT_FIELD(visit) (RAM_COMPOSITE(visit) \
610 || RAM_CLOSURE(visit) || RAM_BIGNUM(visit))
612 #define HAS_1_OBJECT_FIELD(visit) (RAM_COMPOSITE(visit) || RAM_CLOSURE(visit))
614 // all composites except pairs and continuations have 1 object field
616 #define NIL OBJ_FALSE
618 /*---------------------------------------------------------------------------*/
620 /* Garbage collector */
622 obj free_list
; /* list of unused cells */
623 obj free_list_vec
; /* list of unused cells in vector space */
625 obj arg1
; /* root set */
633 uint8 na
; /* interpreter variables */
644 void init_ram_heap (void)
647 obj o
= MAX_RAM_ENCODING
;
651 while (o
> (MIN_RAM_ENCODING
+ (glovars
+ 1) / 2))
652 // we don't want to add globals to the free list, and globals occupy the
653 // beginning of memory at the rate of 2 globals per word (car and cdr)
655 ram_set_gc_tags (o
, GC_TAG_UNMARKED
);
656 ram_set_car (o
, free_list
);
661 free_list_vec
= MIN_VEC_ENCODING
;
662 ram_set_car (free_list_vec
, 0);
663 // each node of the free list must know the free length that follows it
664 // this free length is stored in words, not in bytes
665 // if we did count in bytes, the number might need more than 13 bits
666 ram_set_cdr (free_list_vec
, VEC_BYTES
/ 4);
668 for (i
=0; i
<glovars
; i
++)
669 set_global (i
, OBJ_FALSE
);
696 IF_GC_TRACE(printf ("push stack=%d visit=%d (tag=%d)\n", stack
, visit
, ram_get_gc_tags (visit
)>>5));
698 if ((HAS_1_OBJECT_FIELD (visit
) && ram_get_gc_tag0 (visit
))
699 || (HAS_2_OBJECT_FIELDS (visit
)
700 && (ram_get_gc_tags (visit
) != GC_TAG_UNMARKED
)))
701 IF_GC_TRACE(printf ("case 1\n"));
704 if (HAS_2_OBJECT_FIELDS(visit
)) // pairs and continuations
706 IF_GC_TRACE(printf ("case 2\n"));
710 temp
= ram_get_cdr (visit
);
714 IF_GC_TRACE(printf ("case 3\n"));
715 ram_set_gc_tags (visit
, GC_TAG_1_LEFT
);
716 ram_set_cdr (visit
, stack
);
720 IF_GC_TRACE(printf ("case 4\n"));
725 if (HAS_1_OBJECT_FIELD(visit
))
727 IF_GC_TRACE(printf ("case 5\n"));
731 if (RAM_CLOSURE(visit
)) // closures have the pointer in the cdr
732 temp
= ram_get_cdr (visit
);
734 temp
= ram_get_car (visit
);
738 IF_GC_TRACE(printf ("case 6\n"));
739 ram_set_gc_tag0 (visit
, GC_TAG_0_LEFT
);
740 if (RAM_CLOSURE(visit
))
741 ram_set_cdr (visit
, stack
);
743 ram_set_car (visit
, stack
);
748 IF_GC_TRACE(printf ("case 7\n"));
751 IF_GC_TRACE(printf ("case 8\n"));
753 ram_set_gc_tag0 (visit
, GC_TAG_0_LEFT
);
758 IF_GC_TRACE(printf ("pop stack=%d visit=%d (tag=%d)\n", stack
, visit
, ram_get_gc_tags (visit
)>>6));
762 if (HAS_2_OBJECT_FIELDS(stack
) && ram_get_gc_tag1 (stack
))
764 IF_GC_TRACE(printf ("case 9\n"));
766 temp
= ram_get_cdr (stack
); /* pop through cdr */
767 ram_set_cdr (stack
, visit
);
771 ram_set_gc_tag1(visit
, GC_TAG_UNMARKED
);
772 // we unset the "1-left" bit
777 if (RAM_CLOSURE(stack
))
778 // closures have one object field, but it's in the cdr
780 IF_GC_TRACE(printf ("case 10\n"));
782 temp
= ram_get_cdr (stack
); /* pop through cdr */
783 ram_set_cdr (stack
, visit
);
790 IF_GC_TRACE(printf ("case 11\n"));
792 temp
= ram_get_car (stack
); /* pop through car */
793 ram_set_car (stack
, visit
);
814 obj visit
= MAX_RAM_ENCODING
;
818 while (visit
>= (MIN_RAM_ENCODING
+ ((glovars
+ 1) / 2)))
819 // we don't want to sweep the global variables area
821 if ((RAM_COMPOSITE(visit
)
822 && (ram_get_gc_tags (visit
) == GC_TAG_UNMARKED
)) // 2 mark bit
823 || !(ram_get_gc_tags (visit
) & GC_TAG_0_LEFT
)) // 1 mark bit
826 if (RAM_VECTOR(visit
))
827 // when we sweep a vector, we also have to sweep its contents
829 obj o
= ram_get_cdr (visit
);
830 uint16 i
= ram_get_car (visit
); // number of elements
831 ram_set_car (o
, free_list_vec
);
832 ram_set_cdr (o
, (i
+ 3) / 4); // free length, in words
834 // TODO merge free spaces
836 ram_set_car (visit
, free_list
);
841 if (RAM_COMPOSITE(visit
))
842 ram_set_gc_tags (visit
, GC_TAG_UNMARKED
);
843 else // only 1 mark bit to unset
844 ram_set_gc_tag0 (visit
, GC_TAG_UNMARKED
);
856 printf ("**************** memory needed = %d\n", max_live
+1);
866 IF_TRACE(printf("\nGC BEGINS\n"));
868 IF_GC_TRACE(printf("arg1\n"));
870 IF_GC_TRACE(printf("arg2\n"));
872 IF_GC_TRACE(printf("arg3\n"));
874 IF_GC_TRACE(printf("arg4\n"));
876 IF_GC_TRACE(printf("arg5\n"));
878 IF_GC_TRACE(printf("cont\n"));
880 IF_GC_TRACE(printf("env\n"));
883 IF_GC_TRACE(printf("globals\n"));
884 for (i
=0; i
<glovars
; i
++)
885 mark (get_global (i
));
890 obj
alloc_ram_cell (void)
904 ERROR("alloc_ram_cell", "memory is full");
909 free_list
= ram_get_car (o
);
914 obj
alloc_ram_cell_init (uint8 f0
, uint8 f1
, uint8 f2
, uint8 f3
)
916 obj o
= alloc_ram_cell ();
918 ram_set_field0 (o
, f0
);
919 ram_set_field1 (o
, f1
);
920 ram_set_field2 (o
, f2
);
921 ram_set_field3 (o
, f3
);
926 obj
alloc_vec_cell (uint16 n
)
928 obj o
= free_list_vec
;
937 while ((ram_get_cdr (o
) * 4) < n
) // free space too small
939 if (o
== 0) // no free space, or none big enough
941 if (gc_done
) // we gc'd, but no space is big enough for the vector
942 ERROR("alloc_vec_cell", "no room for vector");
950 } // TODO merge adjacent free spaces, maybe compact ?
955 // case 1 : the new vector fills every free word advertized, we remove the
956 // node from the free list
957 if (((ram_get_cdr(o
) * 4) - n
) < 4)
960 ram_set_car (prec
, ram_get_car (o
));
962 free_list_vec
= ram_get_car (o
);
964 // case 2 : there is still some space left in the free section, create a new
965 // node to represent this space
968 obj new_free
= o
+ (n
+ 3)/4;
970 ram_set_car (prec
, new_free
);
972 free_list_vec
= new_free
;
973 ram_set_car (new_free
, ram_get_car (o
));
974 ram_set_cdr (new_free
, ram_get_cdr (o
) - (n
+ 3)/4);
980 /*---------------------------------------------------------------------------*/
982 #ifdef INFINITE_PRECISION_BIGNUMS
984 int8
decode_int8 (obj o
) // TODO never used except in decode_int, clean useless functions
985 { // TODO really fishy, to use only 8 bits this way...
987 if (o
< MIN_FIXNUM_ENCODING
)
988 TYPE_ERROR("decode_int8.0", "integer");
990 if (o
<= (MIN_FIXNUM_ENCODING
+ (MAX_FIXNUM
- MIN_FIXNUM
)))
991 return DECODE_FIXNUM(o
);
996 TYPE_ERROR("decode_int8.1", "integer");
997 return ram_get_field3 (o
);
1002 TYPE_ERROR("decode_int8.2", "integer");
1003 return rom_get_field3 (o
);
1006 TYPE_ERROR("decode_int8.3", "integer");
1008 // TODO how could this possibly work ? it does not consider other fields, same for encoding, get to the bottom of this
1010 int32
decode_int (obj o
)
1012 return decode_int8 (o
); // TODO FOOBAR clearly wrong, is it used ?
1016 obj
encode_int (int32 n
) // TODO never used in the bignum code
1018 if (n
>= MIN_FIXNUM
&& n
<= MAX_FIXNUM
){
1019 return ENCODE_FIXNUM(n
);
1022 return alloc_ram_cell_init (BIGNUM_FIELD0
, ENCODE_FIXNUM(0), n
>> 8, n
);
1027 int32
decode_int (obj o
)
1033 if (o
< MIN_FIXNUM_ENCODING
)
1034 TYPE_ERROR("decode_int.0", "integer");
1036 if (o
<= (MIN_FIXNUM_ENCODING
+ (MAX_FIXNUM
- MIN_FIXNUM
)))
1037 return DECODE_FIXNUM(o
);
1042 TYPE_ERROR("decode_int.1", "integer");
1044 u
= ram_get_field1 (o
);
1045 h
= ram_get_field2 (o
);
1046 l
= ram_get_field3 (o
);
1051 TYPE_ERROR("decode_int.2", "integer");
1053 u
= rom_get_field1 (o
);
1054 h
= rom_get_field2 (o
);
1055 l
= rom_get_field3 (o
);
1058 TYPE_ERROR("decode_int.3", "integer");
1060 if (u
>= 128) // negative
1061 return ((int32
)((((int16
)u
- 256) << 8) + h
) << 8) + l
;
1063 return ((int32
)(((int16
)u
<< 8) + h
) << 8) + l
;
1066 obj
encode_int (int32 n
)
1068 if (n
>= MIN_FIXNUM
&& n
<= MAX_FIXNUM
)
1069 return ENCODE_FIXNUM(n
);
1071 return alloc_ram_cell_init (BIGNUM_FIELD0
, n
>> 16, n
>> 8, n
);
1076 /*---------------------------------------------------------------------------*/
1088 else if (o
== OBJ_TRUE
)
1090 else if (o
== OBJ_NULL
)
1092 else if (o
<= (MIN_FIXNUM_ENCODING
+ (MAX_FIXNUM
- MIN_FIXNUM
)))
1093 printf ("%d", DECODE_FIXNUM(o
));
1103 if ((in_ram
&& RAM_BIGNUM(o
)) || (!in_ram
&& ROM_BIGNUM(o
))) // TODO FIX for new bignums
1104 printf ("%d", decode_int (o
));
1105 else if ((in_ram
&& RAM_COMPOSITE(o
)) || (!in_ram
&& ROM_COMPOSITE(o
)))
1110 if ((in_ram
&& RAM_PAIR(o
)) || (!in_ram
&& ROM_PAIR(o
)))
1114 car
= ram_get_car (o
);
1115 cdr
= ram_get_cdr (o
);
1119 car
= rom_get_car (o
);
1120 cdr
= rom_get_cdr (o
);
1129 if (cdr
== OBJ_NULL
)
1131 else if ((IN_RAM(cdr
) && RAM_PAIR(cdr
))
1132 || (IN_ROM(cdr
) && ROM_PAIR(cdr
)))
1136 car
= ram_get_car (cdr
);
1137 cdr
= ram_get_cdr (cdr
);
1141 car
= rom_get_car (cdr
);
1142 cdr
= rom_get_cdr (cdr
);
1155 else if ((in_ram
&& RAM_SYMBOL(o
)) || (!in_ram
&& ROM_SYMBOL(o
)))
1156 printf ("#<symbol>");
1157 else if ((in_ram
&& RAM_STRING(o
)) || (!in_ram
&& ROM_STRING(o
)))
1158 printf ("#<string>");
1159 else if ((in_ram
&& RAM_VECTOR(o
)) || (!in_ram
&& ROM_VECTOR(o
)))
1160 printf ("#<vector %d>", o
);
1164 car
= ram_get_car (o
);
1165 cdr
= ram_get_cdr (o
);
1166 // ugly hack, takes advantage of the fact that pairs and
1167 // continuations have the same layout
1177 env
= ram_get_cdr (o
);
1179 env
= rom_get_cdr (o
);
1182 pc
= ram_get_entry (o
);
1184 pc
= rom_get_entry (o
);
1186 printf ("{0x%04x ", pc
);
1195 void show_state (rom_addr pc
)
1198 printf ("pc=0x%04x bytecode=0x%02x env=", pc
, rom_get (pc
));
1215 /*---------------------------------------------------------------------------*/
1217 /* Integer operations */
1219 #ifdef INFINITE_PRECISION_BIGNUMS
1221 #define obj_eq(x,y) ((x) == (y))
1223 #define integer_hi_set(x,y) ram_set_car (x, y)
1224 // TODO FOOBIGNUMS won't work, I think, will erase next pointer (or set it only in part) ACTUALLY, this is probably supposed to change the pointer. changed field1, npw changes the whole car
1226 #define ZERO ENCODE_FIXNUM(0)
1227 #define NEG1 (ZERO-1)
1228 #define POS1 (ZERO+1)
1230 // TODO this integer type is a mess, it should be obj, for clarity
1231 integer
make_integer (digit lo
, integer hi
) // TODO BAD, should use encode_int instead
1233 // TODO could this be fixed by a call to encode_int ?
1234 /* if(!hi && lo <= MAX_FIXNUM) // TODO dependent on the current fixnum range, which starts at 0, fix this */ // TODO would this even be useful ? don't the math routines already revert to fixnums if needed ? or norm does it ?
1235 /* return ENCODE_FIXNUM(lo); */
1236 // TODO won't work, and the bignum functions are unaware of fixnums
1237 return alloc_ram_cell_init (BIGNUM_FIELD0
| (hi
>> 8), hi
, lo
>> 8, lo
); // TODO hi should always be a 13-bit pointer, to avoid clobbering the bignum field
1240 integer
integer_hi (integer x
) // TODO should be used for decoding
1243 return ram_get_car (x
);
1245 return rom_get_car (x
);
1246 else if (x
< (MIN_FIXNUM_ENCODING
- MIN_FIXNUM
))
1247 return NEG1
; /* negative fixnum */
1249 return ZERO
; /* nonnegative fixnum */
1252 digit
integer_lo (integer x
)
1255 return (((digit
)ram_get_field2 (x
)) << 8) + ram_get_field3 (x
);
1257 return (((digit
)rom_get_field2 (x
)) << 8) + rom_get_field3 (x
);
1259 return DECODE_FIXNUM(x
);
1262 integer
norm (obj prefix
, integer n
)
1264 /* norm(prefix,n) returns a normalized integer whose value is the
1265 integer n prefixed with the digits in prefix (a list of digits) */
1267 while (prefix
!= NIL
)
1269 digit d
= integer_lo (prefix
);
1272 prefix
= integer_hi (temp
);
1274 if (obj_eq (n
, ZERO
))
1276 if (d
<= MAX_FIXNUM
)
1278 n
= ENCODE_FIXNUM ((uint8
)d
);
1279 continue; // TODO with cast to unsigned, will it work for negative numbers ? or is it only handled in the next branch ?
1282 else if (obj_eq (n
, NEG1
))
1284 if (d
>= (1<<digit_width
) + MIN_FIXNUM
)
1286 n
= ENCODE_FIXNUM (d
- (1<<digit_width
)); // TODO had a cast, origianlly to int8, changed to uint8 which didn't work (obviously, we use -1 here), is a cast necessary at all ?
1291 integer_hi_set (temp
, n
);
1298 boolean
negp (integer x
)
1300 /* negp(x) returns true iff x is negative */
1305 if (obj_eq (x
, ZERO
)) return false;
1306 } while (!obj_eq (x
, NEG1
));
1311 int8
cmp (integer x
, integer y
)
1313 /* cmp(x,y) return -1 when x<y, 1 when x>y, and 0 when x=y */
1321 if (obj_eq (x
, ZERO
) || obj_eq (x
, NEG1
))
1324 { if (negp (y
)) result
= 1; else result
= -1; }
1328 if (obj_eq (y
, ZERO
) || obj_eq (y
, NEG1
))
1330 if (negp (x
)) result
= -1; else result
= 1;
1334 xlo
= integer_lo (x
);
1335 ylo
= integer_lo (y
);
1339 { if (xlo
< ylo
) result
= -1; else result
= 1; }
1344 uint16
integer_length (integer x
)
1346 /* integer_length(x) returns the number of bits in the binary
1347 representation of the nonnegative integer x */
1353 while (!obj_eq ((next
= integer_hi (x
)), ZERO
)) // TODO what happens if it ends with -1 ?
1355 result
+= digit_width
;
1370 integer
shr (integer x
)
1372 /* shr(x) returns the integer x shifted one bit to the right */
1379 if (obj_eq (x
, ZERO
) || obj_eq (x
, NEG1
))
1381 result
= norm (result
, x
);
1387 result
= make_integer ((d
>> 1) |
1388 ((integer_lo (x
) & 1) ? (1<<(digit_width
-1)) : 0),
1395 integer
negative_carry (integer carry
)
1403 integer
shl (integer x
)
1405 /* shl(x) returns the integer x shifted one bit to the left */
1407 integer negc
= ZERO
; /* negative carry */
1414 if (obj_eq (x
, negc
))
1416 result
= norm (result
, x
);
1423 negc
= negative_carry (d
& (1<<(digit_width
-1))); // TODO right side is constant, and sixpic has no constant folding
1424 result
= make_integer ((d
<< 1) | obj_eq (temp
, NEG1
), result
);
1430 integer
shift_left (integer x
, uint16 n
) // TODO have the primitves been changed for this and right ?
1432 /* shift_left(x,n) returns the integer x shifted n bits to the left */
1434 if (obj_eq (x
, ZERO
))
1437 while (n
& (digit_width
-1))
1445 x
= make_integer (0, x
);
1452 integer
add (integer x
, integer y
)
1454 /* add(x,y) returns the sum of the integers x and y */
1456 integer negc
= ZERO
; /* negative carry */
1457 obj result
= NIL
; /* nil terminated for the norm function */
1463 if (obj_eq (x
, negc
))
1465 result
= norm (result
, y
);
1469 if (obj_eq (y
, negc
))
1471 result
= norm (result
, x
);
1475 dx
= integer_lo (x
);
1476 dy
= integer_lo (y
);
1477 dx
= dx
+ dy
; /* may wrap around */
1479 if (obj_eq (negc
, ZERO
))
1480 negc
= negative_carry (dx
< dy
);
1483 dx
++; /* may wrap around */
1484 negc
= negative_carry (dx
<= dy
);
1490 result
= make_integer (dx
, result
);
1496 integer
invert (integer x
)
1498 if (obj_eq (x
, ZERO
))
1504 integer
sub (integer x
, integer y
)
1506 /* sub(x,y) returns the difference of the integers x and y */
1507 integer negc
= NEG1
; /* negative carry */
1514 if (obj_eq (x
, negc
) && (obj_eq (y
, ZERO
) || obj_eq (y
, NEG1
)))
1516 result
= norm (result
, invert (y
));
1520 if (obj_eq (y
, invert (negc
)))
1522 result
= norm (result
, x
);
1526 dx
= integer_lo (x
);
1527 dy
= ~integer_lo (y
);
1528 dx
= dx
+ dy
; /* may wrap around */
1530 if (obj_eq (negc
, ZERO
))
1531 negc
= negative_carry (dx
< dy
);
1534 dx
++; /* may wrap around */
1535 negc
= negative_carry (dx
<= dy
);
1541 result
= make_integer (dx
, result
);
1547 integer
neg (integer x
)
1549 /* neg(x) returns the integer -x */
1551 return sub (ZERO
, x
);
1554 integer
scale (digit n
, integer x
)
1556 /* scale(n,x) returns the integer n*x */
1562 if ((n
== 0) || obj_eq (x
, ZERO
))
1573 if (obj_eq (x
, ZERO
))
1575 if (carry
<= MAX_FIXNUM
)
1576 result
= norm (result
, ENCODE_FIXNUM ((uint8
)carry
)); // TODO was fixnum, and int8 (signed)
1578 result
= norm (result
, make_integer (carry
, ZERO
));
1582 if (obj_eq (x
, NEG1
))
1585 if (carry
>= ((1<<digit_width
) + MIN_FIXNUM
))
1586 result
= norm (result
, ENCODE_FIXNUM ((uint8
)carry
)); // TODO was fixnum, and int8 (signed)
1588 result
= norm (result
, make_integer (carry
, NEG1
));
1592 m
= (two_digit
)integer_lo (x
) * n
+ carry
;
1595 carry
= m
>> digit_width
;
1596 result
= make_integer ((digit
)m
, result
);
1602 integer
mulnonneg (integer x
, integer y
)
1604 /* mulnonneg(x,y) returns the product of the integers x and y
1605 where x is nonnegative */
1608 integer s
= scale (integer_lo (x
), y
);
1612 result
= make_integer (integer_lo (s
), result
);
1616 if (obj_eq (x
, ZERO
))
1619 s
= add (s
, scale (integer_lo (x
), y
));
1622 return norm (result
, s
);
1625 // TODO have functions mul and div that handle negative arguments ? currently, the logic is in prim_mul and prim_div
1626 integer
divnonneg (integer x
, integer y
)
1628 /* divnonneg(x,y) returns the quotient and remainder of
1629 the integers x and y where x and y are nonnegative */
1631 integer result
= ZERO
;
1632 uint16 lx
= integer_length (x
);
1633 uint16 ly
= integer_length (y
);
1639 y
= shift_left (y
, lx
);
1643 result
= shl (result
);
1644 if (cmp (x
, y
) >= 0)
1647 result
= add (POS1
, result
);
1650 } while (lx
-- != 0);
1659 long long x
; // TODO long long is 32 bits here, what about on a 64 bit machine ?
1660 x
= ((long long)integer_lo (integer_hi (integer_hi (integer_hi (n
))))<<48)+
1661 ((long long)integer_lo (integer_hi (integer_hi (n
)))<<32)+
1662 ((long long)integer_lo (integer_hi (n
))<<16)+
1663 (long long)integer_lo (n
);
1664 printf ("%lld ", x
);
1665 // TODO test for hex output, to avoid signedness problems
1666 /* printf("%x %x %x %x\n", // TODO prob, if a lower part is 0, will show 0, not 0000 */
1667 /* integer_lo (integer_hi (integer_hi (integer_hi (n)))), */
1668 /* integer_lo (integer_hi (integer_hi (n))), */
1669 /* integer_lo (integer_hi (n)), */
1670 /* integer_lo (n)); */
1673 integer
enc (long long n
) // TODO used only for debugging
1675 integer result
= NIL
;
1677 while (n
!= 0 && n
!= -1)
1679 result
= make_integer ((digit
)n
, result
);
1684 return norm (result
, NEG1
);
1686 return norm (result
, ZERO
);
1689 void test (void) // TODO still in use ? no, but useful for tests
1699 zero
= make_integer (0x0000, 0);
1700 min1
= make_integer (0xffff, 0);
1701 integer_hi_set (zero
, ZERO
);
1702 integer_hi_set (min1
, NEG1
);
1704 min2
= make_integer (0xfffe, NEG1
);
1705 one
= make_integer (0x0001, ZERO
);
1706 two
= make_integer (0x0002, ZERO
);
1707 three
= make_integer (0x0003, ZERO
);
1708 four
= make_integer (0x0004, ZERO
);
1710 if (negp (ZERO
)) printf ("zero is negp\n"); // should not show
1711 if (negp (NEG1
)) printf ("min1 is negp\n");
1713 printf ("cmp(5,5) = %d\n",cmp (make_integer (5, ZERO
), make_integer (5, ZERO
)));
1714 printf ("cmp(2,5) = %d\n",cmp (make_integer (2, ZERO
), make_integer (5, ZERO
)));
1715 printf ("cmp(5,2) = %d\n",cmp (make_integer (5, ZERO
), make_integer (2, ZERO
)));
1717 printf ("cmp(-5,-5) = %d\n",cmp (make_integer (-5, NEG1
), make_integer (-5, NEG1
)));
1718 printf ("cmp(-2,-5) = %d\n",cmp (make_integer (-2, NEG1
), make_integer (-5, NEG1
)));
1719 printf ("cmp(-5,-2) = %d\n",cmp (make_integer (-5, NEG1
), make_integer (-2, NEG1
)));
1721 printf ("cmp(-5,65533) = %d\n",cmp (make_integer (-5, NEG1
), make_integer (65533, ZERO
)));
1722 printf ("cmp(-5,2) = %d\n",cmp (make_integer (-5, NEG1
), make_integer (2, ZERO
)));
1723 printf ("cmp(5,-65533) = %d\n",cmp (make_integer (5, ZERO
), make_integer (-65533, NEG1
)));
1724 printf ("cmp(5,-2) = %d\n",cmp (make_integer (5, ZERO
), make_integer (-2, NEG1
)));
1726 printf ("integer_length(0) = %d\n", integer_length (ZERO
)); // these return the number of bits necessary to encode
1727 printf ("integer_length(1) = %d\n", integer_length (make_integer (1, ZERO
)));
1728 printf ("integer_length(2) = %d\n", integer_length (make_integer (2, ZERO
)));
1729 printf ("integer_length(3) = %d\n", integer_length (make_integer (3, ZERO
)));
1730 printf ("integer_length(4) = %d\n", integer_length (make_integer (4, ZERO
)));
1731 printf ("integer_length(65536 + 4) = %d\n", integer_length (make_integer (4, make_integer (1, ZERO
))));
1734 printf ("1 = %d\n", one
); // TODO these show the address, useful ?
1735 printf ("2 = %d\n", two
);
1736 printf ("4 = %d\n", four
);
1737 printf ("norm(2) = %d\n", norm (make_integer (0, make_integer (2, NIL
)), ZERO
)); // TODO these show the fixnum address (6 and 7), so it seems to be working
1738 printf ("norm(2) = %d\n", norm (make_integer (0, make_integer (2, NIL
)), ZERO
));
1739 printf ("norm(3) = %d\n", norm (make_integer (0, make_integer (3, NIL
)), ZERO
));
1740 printf ("norm(3) = %d\n", norm (make_integer (0, make_integer (3, NIL
)), ZERO
));
1742 printf ("shl(1) = %d\n", shl (one
)); // TODO fixnums, again
1743 printf ("shl(2) = %d\n", shl (two
));
1748 // should show powers of 2 incerasing, then decreasing
1749 for (i
=1; i
<=34; i
++)
1751 printf("\nloop-1 : i=%d len=%d ", i
, integer_length(n
));
1755 for (i
=1; i
<=35; i
++)
1757 printf("\nloop-2 : i=%d len=%d ", i
, integer_length(n
));
1764 integer n
= shift_left (four
, 5);
1767 for (i
=0; i
<=14; i
++)
1769 printf("\nloop-3 : i=%d len=%d ", i
);
1770 p (shift_left (n
, i
*4));
1775 p (add (enc (32768), enc (32768))); printf("\n"); // 65536
1776 p (add (enc (32768+(65536*65535LL)), enc (32768))); printf("\n"); // 4294967296
1778 p (sub (enc (32768), enc (-32768))); printf("\n"); // 65536
1779 p (sub (enc (32768+(65536*65535LL)), enc (-32768))); printf("\n"); // 4294967296
1781 p (sub (enc (32768), enc (32769))); printf("\n"); // -1
1782 p (sub (enc (32768), enc (132768))); printf("\n"); // -100000
1783 p (add(sub (enc (32768), enc (32769)), enc(1000))); printf("\n"); // 999
1785 // TODO mul was scrapped, logic is now in prim_mul
1786 /* p (mul (enc (123456789), enc (1000000000))); printf("\n"); // 123456789000000000 */
1787 /* p (mul (enc (123456789), enc (-1000000000))); printf("\n"); // -123456789000000000 */
1788 /* p (mul (enc (-123456789), enc (1000000000))); printf("\n"); // -123456789000000000 */
1789 /* p (mul (enc (-123456789), enc (-1000000000))); printf("\n"); // 123456789000000000 */
1790 /* p (mul (enc (-123456789), neg (enc (1000000000)))); printf("\n"); // 123456789000000000 */
1792 p (divnonneg (enc (10000000-1), enc (500000))); printf("\n"); // 19
1803 void prim_numberp (void)
1805 if (arg1
>= MIN_FIXNUM_ENCODING
1806 && arg1
<= (MIN_FIXNUM_ENCODING
+ (MAX_FIXNUM
- MIN_FIXNUM
)))
1811 arg1
= encode_bool (RAM_BIGNUM(arg1
));
1812 else if (IN_ROM(arg1
))
1813 arg1
= encode_bool (ROM_BIGNUM(arg1
));
1819 void decode_2_int_args (void) // TODO fix for bignums ?
1821 a1
= decode_int (arg1
); // TODO all math primitives call it, even for bignums, this is probably what causes problems, maybe not, since the primitives don't use a1 or a2, but rather arg1 and arg2
1822 a2
= decode_int (arg2
);
1825 void prim_add (void)
1827 #ifdef INFINITE_PRECISION_BIGNUMS
1828 arg1
= add (arg1
, arg2
);
1830 decode_2_int_args ();
1831 arg1
= encode_int (a1
+ a2
);
1836 void prim_sub (void)
1838 #ifdef INFINITE_PRECISION_BIGNUMS
1839 arg1
= sub (arg1
, arg2
);
1841 decode_2_int_args ();
1842 arg1
= encode_int (a1
- a2
);
1847 void prim_mul (void)
1849 #ifdef INFINITE_PRECISION_BIGNUMS
1851 a2
= negp (arg2
); // -1 if negative
1852 arg1
= mulnonneg (a1
? neg(arg1
) : arg1
,
1853 a2
? neg(arg2
) : arg2
);
1854 if (a1
+ a2
== 1) // only one of the 2 was negative
1857 decode_2_int_args ();
1858 arg1
= encode_int (a1
* a2
);
1863 void prim_div (void)
1865 #ifdef INFINITE_PRECISION_BIGNUMS
1866 if (obj_eq(arg2
, ZERO
))
1867 ERROR("quotient", "divide by 0");
1869 a2
= negp (arg2
); // -1 if negative
1870 arg1
= divnonneg (a1
? neg(arg1
) : arg1
,
1871 a2
? neg(arg2
) : arg2
);
1872 if (a1
+ a2
== 1) // only one of the 2 was negative
1875 decode_2_int_args ();
1877 ERROR("quotient", "divide by 0");
1878 arg1
= encode_int (a1
/ a2
);
1883 void prim_rem (void)
1885 #ifdef INFINITE_PRECISION_BIGNUMS
1886 if (obj_eq(arg2
, ZERO
))
1887 ERROR("remainder", "divide by 0");
1888 if (negp(arg1
) || negp(arg2
))
1889 ERROR("remainder", "only positive numbers are supported");
1890 // TODO fix this to handle negatives
1891 // TODO logic quite similar to mul and div (likely, once we fix), abstract ?
1892 arg3
= divnonneg (arg1
, arg2
);
1893 arg4
= mulnonneg (arg2
, arg3
);
1894 arg1
= sub(arg1
, arg4
);
1898 decode_2_int_args ();
1900 ERROR("remainder", "divide by 0");
1901 arg1
= encode_int (a1
% a2
);
1906 void prim_neg (void)
1908 #ifdef INFINITE_PRECISION_BIGNUMS
1911 a1
= decode_int (arg1
);
1912 arg1
= encode_int (- a1
);
1918 #ifdef INFINITE_PRECISION_BIGNUMS
1919 arg1
= encode_bool(cmp (arg1
, arg2
) == 0);
1921 decode_2_int_args ();
1922 arg1
= encode_bool(a1
== a2
);
1929 #ifdef INFINITE_PRECISION_BIGNUMS
1930 arg1
= encode_bool(cmp (arg1
, arg2
) < 0);
1932 decode_2_int_args ();
1933 arg1
= encode_bool(a1
< a2
);
1940 #ifdef INFINITE_PRECISION_BIGNUMS
1941 arg1
= encode_bool(cmp (arg1
, arg2
) > 0);
1943 decode_2_int_args ();
1944 arg1
= encode_bool(a1
> a2
);
1949 void prim_ior (void) // TODO FOOBIGNUMS these have not been implemented with bignums, do it
1951 decode_2_int_args (); // TODO is the function call overhead worth it ?
1952 arg1
= encode_int (a1
| a2
);
1956 void prim_xor (void)
1958 decode_2_int_args (); // TODO is the function call overhead worth it ?
1959 arg1
= encode_int (a1
^ a2
);
1964 /*---------------------------------------------------------------------------*/
1966 /* List operations */
1968 void prim_pairp (void)
1971 arg1
= encode_bool (RAM_PAIR(arg1
));
1972 else if (IN_ROM(arg1
))
1973 arg1
= encode_bool (ROM_PAIR(arg1
));
1978 obj
cons (obj car
, obj cdr
)
1980 return alloc_ram_cell_init (COMPOSITE_FIELD0
| (car
>> 8),
1982 PAIR_FIELD2
| (cdr
>> 8),
1986 void prim_cons (void)
1988 arg1
= cons (arg1
, arg2
);
1992 void prim_car (void)
1996 if (!RAM_PAIR(arg1
))
1997 TYPE_ERROR("car.0", "pair");
1998 arg1
= ram_get_car (arg1
);
2000 else if (IN_ROM(arg1
))
2002 if (!ROM_PAIR(arg1
))
2003 TYPE_ERROR("car.1", "pair");
2004 arg1
= rom_get_car (arg1
);
2008 TYPE_ERROR("car.2", "pair");
2012 void prim_cdr (void)
2016 if (!RAM_PAIR(arg1
))
2017 TYPE_ERROR("cdr.0", "pair");
2018 arg1
= ram_get_cdr (arg1
);
2020 else if (IN_ROM(arg1
))
2022 if (!ROM_PAIR(arg1
))
2023 TYPE_ERROR("cdr.1", "pair");
2024 arg1
= rom_get_cdr (arg1
);
2028 TYPE_ERROR("cdr.2", "pair");
2032 void prim_set_car (void)
2036 if (!RAM_PAIR(arg1
))
2037 TYPE_ERROR("set-car!.0", "pair");
2039 ram_set_car (arg1
, arg2
);
2045 TYPE_ERROR("set-car!.1", "pair");
2049 void prim_set_cdr (void)
2053 if (!RAM_PAIR(arg1
))
2054 TYPE_ERROR("set-cdr!.0", "pair");
2056 ram_set_cdr (arg1
, arg2
);
2062 TYPE_ERROR("set-cdr!.1", "pair");
2066 void prim_nullp (void)
2068 arg1
= encode_bool (arg1
== OBJ_NULL
);
2071 /*---------------------------------------------------------------------------*/
2073 /* Vector operations */
2075 void prim_u8vectorp (void)
2078 arg1
= encode_bool (RAM_VECTOR(arg1
));
2079 else if (IN_ROM(arg1
))
2080 arg1
= encode_bool (ROM_VECTOR(arg1
));
2085 void prim_make_u8vector (void)
2087 decode_2_int_args (); // arg1 is length, arg2 is contents
2088 // TODO adapt for the new bignums
2090 ERROR("make-u8vector", "byte vectors can only contain bytes");
2092 arg3
= alloc_vec_cell (a1
);
2093 arg1
= alloc_ram_cell_init (COMPOSITE_FIELD0
| (a1
>> 8),
2095 VECTOR_FIELD2
| (arg3
>> 8),
2098 a1
= (a1
+ 3) / 4; // actual length, in words
2101 ram_set_field0 (arg3
, a2
);
2102 ram_set_field1 (arg3
, a2
);
2103 ram_set_field2 (arg3
, a2
);
2104 ram_set_field3 (arg3
, a2
);
2109 void prim_u8vector_ref (void)
2111 a2
= decode_int (arg2
);
2112 // TODO adapt for the new bignums
2115 if (!RAM_VECTOR(arg1
))
2116 TYPE_ERROR("u8vector-ref.0", "vector");
2117 if ((ram_get_car (arg1
) <= a2
) || (a2
< 0))
2118 ERROR("u8vector-ref.0", "vector index invalid");
2119 arg1
= ram_get_cdr (arg1
);
2121 else if (IN_ROM(arg1
))
2123 if (!ROM_VECTOR(arg1
))
2124 TYPE_ERROR("u8vector-ref.1", "vector");
2125 if ((rom_get_car (arg1
) <= a2
) || (a2
< 0))
2126 ERROR("u8vector-ref.1", "vector index invalid");
2127 arg1
= rom_get_cdr (arg1
);
2130 TYPE_ERROR("u8vector-ref.2", "vector");
2137 arg1
= encode_int (ram_get_fieldn (arg1
, a2
));
2139 else // rom vector, stored as a list
2142 arg1
= rom_get_cdr (arg1
);
2144 // the contents are already encoded as fixnums
2145 arg1
= rom_get_car (arg1
);
2153 void prim_u8vector_set (void)
2154 { // TODO a lot in common with ref, abstract that
2155 a2
= decode_int (arg2
); // TODO adapt for bignums
2156 a3
= decode_int (arg3
);
2159 ERROR("u8vector-set!", "byte vectors can only contain bytes");
2163 if (!RAM_VECTOR(arg1
))
2164 TYPE_ERROR("u8vector-set!.0", "vector");
2165 if ((ram_get_car (arg1
) <= a2
) || (a2
< 0))
2166 ERROR("u8vector-set!", "vector index invalid");
2167 arg1
= ram_get_cdr (arg1
);
2170 TYPE_ERROR("u8vector-set!.1", "vector");
2175 ram_set_fieldn (arg1
, a2
, a3
);
2182 void prim_u8vector_length (void)
2186 if (!RAM_VECTOR(arg1
))
2187 TYPE_ERROR("u8vector-length.0", "vector");
2188 arg1
= encode_int (ram_get_car (arg1
));
2190 else if (IN_ROM(arg1
))
2192 if (!ROM_VECTOR(arg1
))
2193 TYPE_ERROR("u8vector-length.1", "vector");
2194 arg1
= encode_int (rom_get_car (arg1
));
2197 TYPE_ERROR("u8vector-length.2", "vector");
2200 void prim_u8vector_copy (void)
2202 // arg1 is source, arg2 is source-start, arg3 is target, arg4 is target-start
2203 // arg5 is number of bytes to copy
2205 a1
= decode_int (arg2
); // TODO adapt for bignums
2206 a2
= decode_int (arg4
);
2207 a3
= decode_int (arg5
);
2209 // case 1 : ram to ram
2210 if (IN_RAM(arg1
) && IN_RAM(arg3
))
2212 if (!RAM_VECTOR(arg1
) || !RAM_VECTOR(arg3
))
2213 TYPE_ERROR("u8vector-copy!.0", "vector");
2214 if ((ram_get_car (arg1
) < (a1
+ a3
)) || (a1
< 0) ||
2215 (ram_get_car (arg3
) < (a2
+ a3
)) || (a2
< 0))
2216 ERROR("u8vector-copy!.0", "vector index invalid");
2218 // position to the start
2219 arg1
= ram_get_cdr (arg1
);
2222 arg3
= ram_get_cdr (arg3
);
2229 ram_set_fieldn (arg3
, a2
, ram_get_fieldn (arg1
, a1
));
2233 a1
%= 4; // TODO merge with the previous similar block ?
2239 // case 2 : rom to ram
2240 else if (IN_ROM(arg1
) && IN_RAM(arg3
))
2242 if (!ROM_VECTOR(arg1
) || !RAM_VECTOR(arg3
))
2243 TYPE_ERROR("u8vector-copy!.1", "vector");
2244 if ((rom_get_car (arg1
) < (a1
+ a3
)) || (a1
< 0) ||
2245 (ram_get_car (arg3
) < (a2
+ a3
)) || (a2
< 0))
2246 ERROR("u8vector-copy!.1", "vector index invalid");
2248 arg1
= rom_get_cdr (arg1
);
2250 arg1
= rom_get_cdr (arg1
);
2252 arg3
= ram_get_cdr (arg3
);
2258 ram_set_fieldn (arg3
, a2
, decode_int (rom_get_car (arg1
)));
2260 arg1
= rom_get_cdr (arg1
);
2263 a2
%= 4; // TODO very similar to the other case
2267 TYPE_ERROR("u8vector-copy!.2", "vector");
2276 /*---------------------------------------------------------------------------*/
2278 /* Miscellaneous operations */
2280 void prim_eqp (void)
2282 arg1
= encode_bool (arg1
== arg2
);
2286 void prim_not (void)
2288 arg1
= encode_bool (arg1
== OBJ_FALSE
);
2291 void prim_symbolp (void)
2294 arg1
= encode_bool (RAM_SYMBOL(arg1
));
2295 else if (IN_ROM(arg1
))
2296 arg1
= encode_bool (ROM_SYMBOL(arg1
));
2301 void prim_stringp (void)
2304 arg1
= encode_bool (RAM_STRING(arg1
));
2305 else if (IN_ROM(arg1
))
2306 arg1
= encode_bool (ROM_STRING(arg1
));
2311 void prim_string2list (void)
2315 if (!RAM_STRING(arg1
))
2316 TYPE_ERROR("string->list.0", "string");
2318 arg1
= ram_get_car (arg1
);
2320 else if (IN_ROM(arg1
))
2322 if (!ROM_STRING(arg1
))
2323 TYPE_ERROR("string->list.1", "string");
2325 arg1
= rom_get_car (arg1
);
2328 TYPE_ERROR("string->list.2", "string");
2331 void prim_list2string (void)
2333 arg1
= alloc_ram_cell_init (COMPOSITE_FIELD0
| ((arg1
& 0x1f00) >> 8),
2339 void prim_booleanp (void)
2341 arg1
= encode_bool (arg1
< 2);
2345 /*---------------------------------------------------------------------------*/
2347 /* Robot specific operations */
2350 void prim_print (void)
2365 int32
read_clock (void)
2371 now
= from_now( 0 );
2379 static int32 start
= 0;
2384 now
= tb
.time
* 1000 + tb
.millitm
;
2391 static int32 start
= 0;
2394 if (gettimeofday (&tv
, NULL
) == 0)
2396 now
= tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
2410 void prim_clock (void)
2412 arg1
= encode_int (read_clock ());
2416 void prim_motor (void)
2418 decode_2_int_args (); // TODO fix for bignums
2420 if (a1
< 1 || a1
> 2 || a2
< -100 || a2
> 100)
2421 ERROR("motor", "argument out of range");
2425 MOTOR_set( a1
, a2
);
2431 printf ("motor %d -> power=%d\n", a1
, a2
);
2441 void prim_led (void)
2443 decode_2_int_args (); // TODO fix for bignums
2444 a3
= decode_int (arg3
);
2446 if (a1
< 1 || a1
> 3 || a2
< 0 || a3
< 0)
2447 ERROR("led", "argument out of range");
2451 LED_set( a1
, a2
, a3
);
2457 printf ("led %d -> duty=%d period=%d\n", a1
, a2
, a3
);
2468 void prim_led2_color (void)
2470 a1
= decode_int (arg1
); // TODO fix for bignums
2472 if (a1
< 0 || a1
> 1)
2473 ERROR("led2-colors", "argument out of range");
2477 LED2_color_set( a1
);
2483 printf ("led2-color -> %s\n", (a1
==0)?"green":"red");
2492 void prim_getchar_wait (void)
2494 decode_2_int_args(); // TODO fix for bignums
2495 a1
= read_clock () + a1
;
2497 if (a1
< 0 || a2
< 1 || a2
> 3)
2498 ERROR("getchar-wait", "argument out of range");
2505 serial_port_set ports
;
2506 ports
= serial_rx_wait_with_timeout( a2
, a1
);
2508 arg1
= encode_int (serial_rx_read( ports
));
2523 arg1
= encode_int (_getch ());
2526 } while (read_clock () < a1
);
2531 arg1
= encode_int (getchar ());
2539 void prim_putchar (void)
2541 decode_2_int_args ();
2543 if (a1
< 0 || a1
> 255 || a2
< 1 || a2
> 3)
2544 ERROR("putchar", "argument out of range");
2548 serial_tx_write( a2
, a1
);
2564 void prim_beep (void)
2566 decode_2_int_args (); // TODO fix for bignums
2568 if (a1
< 1 || a1
> 255 || a2
< 0)
2569 ERROR("beep", "argument out of range");
2573 beep( a1
, from_now( a2
) );
2579 printf ("beep -> freq-div=%d duration=%d\n", a1
, a2
);
2589 void prim_adc (void)
2593 a1
= decode_int (arg1
); // TODO fix for bignums
2595 if (a1
< 1 || a1
> 3)
2596 ERROR("adc", "argument out of range");
2606 x
= read_clock () & 255;
2608 if (x
> 127) x
= 256 - x
;
2614 arg1
= encode_int (x
);
2618 void prim_dac (void) // TODO not used
2620 a1
= decode_int (arg1
); // TODO fix for bignums
2622 if (a1
< 0 || a1
> 255)
2623 ERROR("dac", "argument out of range");
2633 printf ("dac -> %d\n", a1
);
2642 void prim_sernum (void)
2658 arg1
= encode_int (x
);
2662 /*---------------------------------------------------------------------------*/
2663 // networking, currently works only on workstations
2667 void prim_network_init (void)
2668 { // TODO maybe put in the initialization of the vm
2669 handle
= pcap_open_live(INTERFACE
, MAX_PACKET_SIZE
, PROMISC
, TO_MSEC
, errbuf
);
2671 ERROR("network-init", "interface not responding");
2674 void prim_network_cleanup (void)
2675 { // TODO maybe put in halt ?
2679 void prim_receive_packet_to_u8vector (void)
2681 // arg1 is the vector in which to put the received packet
2682 if (!RAM_VECTOR(arg1
))
2683 TYPE_ERROR("receive-packet-to-u8vector", "vector");
2685 // receive the packet in the buffer
2686 struct pcap_pkthdr header
;
2687 const u_char
*packet
;
2689 packet
= pcap_next(handle
, &header
);
2694 if (ram_get_car (arg1
) < header
.len
)
2695 ERROR("receive-packet-to-u8vector", "packet longer than vector");
2697 if (header
.len
> 0) // we have received a packet, write it in the vector
2699 arg2
= rom_get_cdr (arg1
);
2700 arg1
= header
.len
; // we return the length of the received packet
2705 ram_set_fieldn (arg2
, a1
% 4, (char)packet
[a1
]);
2707 arg2
+= (a1
% 4) ? 0 : 1;
2712 else // no packet to be read
2716 void prim_send_packet_from_u8vector (void)
2718 // arg1 is the vector which contains the packet to be sent
2719 // arg2 is the length of the packet
2720 // TODO only works with ram vectors for now
2721 if (!RAM_VECTOR(arg1
))
2722 TYPE_ERROR("send-packet-from-vector!", "vector");
2723 a2
= decode_int (arg2
); // TODO fix for bignums
2726 // TODO test if the length of the packet is longer than the length of the vector
2727 if (ram_get_car (arg1
) < a2
)
2728 ERROR("send-packet-from-u8vector", "packet cannot be longer than vector");
2730 arg1
= ram_get_cdr (arg1
);
2732 // copy the packet to the output buffer
2734 buf
[a1
] = ram_get_fieldn (arg1
, a1
% 4);
2735 // TODO maybe I could just give pcap the pointer to the memory BREGG
2737 if (pcap_sendpacket(handle
, buf
, a2
) < 0) // TODO an error has occurred, can we reuse the interface ?
2747 /*---------------------------------------------------------------------------*/
2751 int hidden_fgetc (FILE *f
)
2761 #define fgetc(f) hidden_fgetc(f)
2763 void write_hex_nibble (int n
)
2765 putchar ("0123456789ABCDEF"[n
]);
2768 void write_hex (uint8 n
)
2770 write_hex_nibble (n
>> 4);
2771 write_hex_nibble (n
& 0x0f);
2776 if (c
>= '0' && c
<= '9')
2779 if (c
>= 'A' && c
<= 'F')
2780 return (c
- 'A' + 10);
2782 if (c
>= 'a' && c
<= 'f')
2783 return (c
- 'a' + 10);
2788 int read_hex_byte (FILE *f
)
2790 int h1
= hex (fgetc (f
));
2791 int h2
= hex (fgetc (f
));
2793 if (h1
>= 0 && h2
>= 0)
2794 return (h1
<<4) + h2
;
2799 int read_hex_file (char *filename
)
2802 FILE *f
= fopen (filename
, "r");
2812 for (i
=0; i
<ROM_BYTES
; i
++)
2817 while ((c
= fgetc (f
)) != EOF
)
2819 if ((c
== '\r') || (c
== '\n'))
2823 (len
= read_hex_byte (f
)) < 0 ||
2824 (a1
= read_hex_byte (f
)) < 0 ||
2825 (a2
= read_hex_byte (f
)) < 0 ||
2826 (t
= read_hex_byte (f
)) < 0)
2832 sum
= len
+ a1
+ a2
+ t
;
2840 unsigned long adr
= ((unsigned long)hi16
<< 16) + a
- CODE_START
;
2842 if ((b
= read_hex_byte (f
)) < 0)
2845 if (adr
>= 0 && adr
< ROM_BYTES
)
2848 a
= (a
+ 1) & 0xffff;
2865 if ((a1
= read_hex_byte (f
)) < 0 ||
2866 (a2
= read_hex_byte (f
)) < 0)
2871 hi16
= (a1
<<8) + a2
;
2876 if ((b
= read_hex_byte (f
)) < 0)
2883 printf ("*** HEX file checksum error (expected 0x%02x)\n", sum
);
2889 if ((c
!= '\r') && (c
!= '\n'))
2900 printf ("*** HEX file syntax error\n");
2910 /*---------------------------------------------------------------------------*/
2912 #define FETCH_NEXT_BYTECODE() bytecode = rom_get (pc++)
2914 #define BEGIN_DISPATCH() \
2916 IF_TRACE(show_state (pc)); \
2917 FETCH_NEXT_BYTECODE(); \
2918 bytecode_hi4 = bytecode & 0xf0; \
2919 bytecode_lo4 = bytecode & 0x0f; \
2920 switch (bytecode_hi4 >> 4) {
2922 #define END_DISPATCH() }
2924 #define CASE(opcode) case (opcode>>4):;
2926 #define DISPATCH(); goto dispatch;
2931 #define bytecode TABLAT
2932 #define bytecode_hi4 WREG
2935 #define PUSH_CONSTANT1 0x00
2936 #define PUSH_CONSTANT2 0x10
2937 #define PUSH_STACK1 0x20
2938 #define PUSH_STACK2 0x30
2939 #define PUSH_GLOBAL 0x40
2940 #define SET_GLOBAL 0x50
2943 #define LABEL_INSTR 0x80
2944 #define PUSH_CONSTANT_LONG 0x90
2956 char *prim_name
[64] =
2980 "prim #%graft-to-cont",
2981 "prim #%return-to-cont",
2985 "prim #%string->list",
2986 "prim #%list->string",
2987 "prim #%make-u8vector",
2988 "prim #%u8vector-ref",
2989 "prim #%u8vector-set!",
2994 "prim #%led2-color",
2995 "prim #%getchar-wait",
3001 "prim #%u8vector-length",
3002 "prim #%u8vector-copy!",
3007 "prim #%network-init",
3008 "prim #%network-cleanup",
3009 "prim #%receive-packet-to-u8vector",
3010 "prim #%send-packet-from-u8vector",
3026 #define PUSH_ARG1() push_arg1 ()
3029 void push_arg1 (void)
3031 env
= cons (arg1
, env
);
3037 obj o
= ram_get_car (env
);
3038 env
= ram_get_cdr (env
);
3042 void pop_procedure (void)
3048 if (!RAM_CLOSURE(arg1
))
3049 TYPE_ERROR("pop_procedure.0", "procedure");
3051 entry
= ram_get_entry (arg1
) + CODE_START
;
3053 else if (IN_ROM(arg1
))
3055 if (!ROM_CLOSURE(arg1
))
3056 TYPE_ERROR("pop_procedure.1", "procedure");
3058 entry
= rom_get_entry (arg1
) + CODE_START
;
3061 TYPE_ERROR("pop_procedure.2", "procedure");
3064 void handle_arity_and_rest_param (void)
3068 np
= rom_get (entry
++);
3070 if ((np
& 0x80) == 0)
3073 ERROR("handle_arity_and_rest_param.0", "wrong number of arguments");
3080 ERROR("handle_arity_and_rest_param.1", "wrong number of arguments");
3088 arg3
= cons (arg4
, arg3
);
3094 arg1
= cons (arg3
, arg1
);
3099 void build_env (void)
3105 arg1
= cons (arg3
, arg1
);
3113 void save_cont (void)
3115 // the second half is a closure
3116 arg3
= alloc_ram_cell_init (CLOSURE_FIELD0
| (pc
>> 11),
3118 ((pc
& 0x0007) << 5) | (env
>> 8),
3120 cont
= alloc_ram_cell_init (COMPOSITE_FIELD0
| (cont
>> 8),
3122 CONTINUATION_FIELD2
| (arg3
>> 8),
3127 void interpreter (void)
3129 pc
= (CODE_START
+ 4) + ((rom_addr
)rom_get (CODE_START
+2) << 2);
3131 glovars
= rom_get (CODE_START
+3); // number of global variables
3137 /***************************************************************************/
3138 CASE(PUSH_CONSTANT1
);
3140 IF_TRACE(printf(" (push-constant "); show (bytecode_lo4
); printf (")\n"));
3142 arg1
= bytecode_lo4
;
3148 /***************************************************************************/
3149 CASE(PUSH_CONSTANT2
);
3151 IF_TRACE(printf(" (push-constant "); show (bytecode_lo4
+16); printf (")\n"));
3152 arg1
= bytecode_lo4
+16;
3158 /***************************************************************************/
3161 IF_TRACE(printf(" (push-stack %d)\n", bytecode_lo4
));
3165 while (bytecode_lo4
!= 0)
3167 arg1
= ram_get_cdr (arg1
);
3171 arg1
= ram_get_car (arg1
);
3177 /***************************************************************************/
3180 IF_TRACE(printf(" (push-stack %d)\n", bytecode_lo4
+16));
3186 while (bytecode_lo4
!= 0)
3188 arg1
= ram_get_cdr (arg1
);
3192 arg1
= ram_get_car (arg1
);
3198 /***************************************************************************/
3201 IF_TRACE(printf(" (push-global %d)\n", bytecode_lo4
));
3203 arg1
= get_global (bytecode_lo4
);
3209 /***************************************************************************/
3212 IF_TRACE(printf(" (set-global %d)\n", bytecode_lo4
));
3214 set_global (bytecode_lo4
, POP());
3218 /***************************************************************************/
3221 IF_TRACE(printf(" (call %d)\n", bytecode_lo4
));
3226 handle_arity_and_rest_param ();
3237 /***************************************************************************/
3240 IF_TRACE(printf(" (jump %d)\n", bytecode_lo4
));
3245 handle_arity_and_rest_param ();
3255 /***************************************************************************/
3258 switch (bytecode_lo4
)
3260 case 0: // call-toplevel
3261 FETCH_NEXT_BYTECODE();
3264 FETCH_NEXT_BYTECODE();
3266 IF_TRACE(printf(" (call-toplevel 0x%04x)\n",
3267 ((arg2
<< 8) | bytecode
) + CODE_START
));
3269 entry
= (arg2
<< 8) + bytecode
+ CODE_START
;
3272 na
= rom_get (entry
++);
3285 case 1: // jump-toplevel
3286 FETCH_NEXT_BYTECODE();
3289 FETCH_NEXT_BYTECODE();
3291 IF_TRACE(printf(" (jump-toplevel 0x%04x)\n",
3292 ((arg2
<< 8) | bytecode
) + CODE_START
));
3294 entry
= (arg2
<< 8) + bytecode
+ CODE_START
;
3297 na
= rom_get (entry
++);
3310 FETCH_NEXT_BYTECODE();
3313 FETCH_NEXT_BYTECODE();
3315 IF_TRACE(printf(" (goto 0x%04x)\n",
3316 (arg2
<< 8) + bytecode
+ CODE_START
));
3318 pc
= (arg2
<< 8) + bytecode
+ CODE_START
;
3322 case 3: // goto-if-false
3323 FETCH_NEXT_BYTECODE();
3326 FETCH_NEXT_BYTECODE();
3328 IF_TRACE(printf(" (goto-if-false 0x%04x)\n",
3329 (arg2
<< 8) + bytecode
+ CODE_START
));
3331 if (POP() == OBJ_FALSE
)
3332 pc
= (arg2
<< 8) + bytecode
+ CODE_START
;
3337 FETCH_NEXT_BYTECODE();
3340 FETCH_NEXT_BYTECODE();
3342 IF_TRACE(printf(" (closure 0x%04x)\n", (arg2
<< 8) | bytecode
));
3344 arg3
= POP(); // env
3346 entry
= (arg2
<< 8) | bytecode
;
3348 arg1
= alloc_ram_cell_init (CLOSURE_FIELD0
| (arg2
>> 3),
3349 ((arg2
& 0x07) << 5) | (bytecode
>> 3),
3350 ((bytecode
&0x07) <<5) |((arg3
&0x1f00) >>8),
3360 case 5: // call-toplevel-short
3361 FETCH_NEXT_BYTECODE(); // TODO the short version have a lot in common with the long ones, abstract ?
3362 // TODO short instructions don't work at the moment
3363 IF_TRACE(printf(" (call-toplevel-short 0x%04x)\n",
3364 pc
+ bytecode
+ CODE_START
));
3366 entry
= pc
+ bytecode
+ CODE_START
;
3369 na
= rom_get (entry
++);
3381 case 6: // jump-toplevel-short
3382 FETCH_NEXT_BYTECODE();
3384 IF_TRACE(printf(" (jump-toplevel-short 0x%04x)\n",
3385 pc
+ bytecode
+ CODE_START
));
3387 entry
= pc
+ bytecode
+ CODE_START
;
3390 na
= rom_get (entry
++);
3401 case 7: // goto-short
3402 FETCH_NEXT_BYTECODE();
3404 IF_TRACE(printf(" (goto-short 0x%04x)\n", pc
+ bytecode
+ CODE_START
));
3406 pc
= pc
+ bytecode
+ CODE_START
;
3410 case 8: // goto-if-false-short
3411 FETCH_NEXT_BYTECODE();
3413 IF_TRACE(printf(" (goto-if-false-short 0x%04x)\n",
3414 pc
+ bytecode
+ CODE_START
));
3416 if (POP() == OBJ_FALSE
)
3417 pc
= pc
+ bytecode
+ CODE_START
;
3421 case 9: // closure-short
3422 FETCH_NEXT_BYTECODE();
3424 IF_TRACE(printf(" (closure-short 0x%04x)\n", pc
+ bytecode
));
3426 arg3
= POP(); // env
3428 entry
= pc
+ bytecode
;
3430 arg1
= alloc_ram_cell_init (CLOSURE_FIELD0
| (arg2
>> 3),
3431 ((arg2
& 0x07) << 5) | (bytecode
>> 3),
3432 ((bytecode
&0x07) <<5) |((arg3
&0x1f00) >>8),
3451 case 14: // push_global [long]
3452 FETCH_NEXT_BYTECODE();
3454 IF_TRACE(printf(" (push-global [long] %d)\n", bytecode
));
3456 arg1
= get_global (bytecode
);
3462 case 15: // set_global [long]
3463 FETCH_NEXT_BYTECODE();
3465 IF_TRACE(printf(" (set-global [long] %d)\n", bytecode
));
3467 set_global (bytecode
, POP());
3474 /***************************************************************************/
3475 CASE(PUSH_CONSTANT_LONG
);
3477 /* push-constant [long] */
3479 FETCH_NEXT_BYTECODE();
3481 IF_TRACE(printf(" (push [long] 0x%04x)\n", (bytecode_lo4
<< 8) + bytecode
));
3483 arg1
= (bytecode_lo4
<< 8) | bytecode
;
3488 /***************************************************************************/
3489 CASE(FREE1
); // FREE
3493 /***************************************************************************/
3494 CASE(FREE2
); // FREE
3498 /***************************************************************************/
3501 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
]));
3503 switch (bytecode_lo4
)
3506 arg1
= POP(); prim_numberp (); PUSH_ARG1(); break;
3508 arg2
= POP(); arg1
= POP(); prim_add (); PUSH_ARG1(); break;
3510 arg2
= POP(); arg1
= POP(); prim_sub (); PUSH_ARG1(); break;
3512 arg2
= POP(); arg1
= POP(); prim_mul (); PUSH_ARG1(); break;
3514 arg2
= POP(); arg1
= POP(); prim_div (); PUSH_ARG1(); break;
3516 arg2
= POP(); arg1
= POP(); prim_rem (); PUSH_ARG1(); break;
3518 arg1
= POP(); prim_neg (); PUSH_ARG1(); break;
3520 arg2
= POP(); arg1
= POP(); prim_eq (); PUSH_ARG1(); break;
3522 arg2
= POP(); arg1
= POP(); prim_lt (); PUSH_ARG1(); break;
3524 arg2
= POP(); arg1
= POP(); prim_ior (); PUSH_ARG1(); break;
3526 arg2
= POP(); arg1
= POP(); prim_gt (); PUSH_ARG1(); break;
3528 arg2
= POP(); arg1
= POP(); prim_xor (); PUSH_ARG1(); break;
3530 arg1
= POP(); prim_pairp (); PUSH_ARG1(); break;
3532 arg2
= POP(); arg1
= POP(); prim_cons (); PUSH_ARG1(); break;
3534 arg1
= POP(); prim_car (); PUSH_ARG1(); break;
3536 arg1
= POP(); prim_cdr (); PUSH_ARG1(); break;
3541 /***************************************************************************/
3544 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
+16]));
3546 switch (bytecode_lo4
)
3549 arg2
= POP(); arg1
= POP(); prim_set_car (); break;
3551 arg2
= POP(); arg1
= POP(); prim_set_cdr (); break;
3553 arg1
= POP(); prim_nullp (); PUSH_ARG1(); break;
3555 arg2
= POP(); arg1
= POP(); prim_eqp (); PUSH_ARG1(); break;
3557 arg1
= POP(); prim_not (); PUSH_ARG1(); break;
3559 /* prim #%get-cont */
3564 /* prim #%graft-to-cont */
3566 arg1
= POP(); /* thunk to call */
3567 cont
= POP(); /* continuation */
3574 handle_arity_and_rest_param ();
3584 /* prim #%return-to-cont */
3586 arg1
= POP(); /* value to return */
3587 cont
= POP(); /* continuation */
3589 arg2
= ram_get_cdr (cont
);
3591 pc
= ram_get_entry (arg2
);
3593 env
= ram_get_cdr (arg2
);
3594 cont
= ram_get_car (cont
);
3604 /* prim #%symbol? */
3605 arg1
= POP(); prim_symbolp (); PUSH_ARG1(); break;
3607 /* prim #%string? */
3608 arg1
= POP(); prim_stringp (); PUSH_ARG1(); break;
3610 /* prim #%string->list */
3611 arg1
= POP(); prim_string2list (); PUSH_ARG1(); break;
3613 /* prim #%list->string */
3614 arg1
= POP(); prim_list2string (); PUSH_ARG1(); break;
3616 /* prim #%make-u8vector */
3617 arg2
= POP(); arg1
= POP(); prim_make_u8vector (); PUSH_ARG1(); break;
3619 /* prim #%u8vector-ref */
3620 arg2
= POP(); arg1
= POP(); prim_u8vector_ref (); PUSH_ARG1(); break;
3622 /* prim #%u8vector-set! */
3623 arg3
= POP(); arg2
= POP(); arg1
= POP(); prim_u8vector_set (); break;
3628 /***************************************************************************/
3631 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
+32]));
3633 switch (bytecode_lo4
)
3642 prim_clock (); PUSH_ARG1(); break;
3645 arg2
= POP(); arg1
= POP(); prim_motor (); break;
3648 arg3
= POP(); arg2
= POP(); arg1
= POP(); prim_led (); ;break;
3650 /* prim #%led2-color */
3651 arg1
= POP(); prim_led2_color (); break;
3653 /* prim #%getchar-wait */
3654 arg2
= POP(); arg1
= POP(); prim_getchar_wait (); PUSH_ARG1(); break;
3656 /* prim #%putchar */
3657 arg2
= POP(); arg1
= POP(); prim_putchar (); break;
3660 arg2
= POP(); arg1
= POP(); prim_beep (); break;
3663 arg1
= POP(); prim_adc (); PUSH_ARG1(); break;
3665 /* prim #%u8vector? */
3666 arg1
= POP(); prim_u8vectorp (); PUSH_ARG1(); break;
3669 prim_sernum (); PUSH_ARG1(); break;
3671 /* prim #%u8vector-length */
3672 arg1
= POP(); prim_u8vector_length (); PUSH_ARG1(); break;
3674 /* prim #%u8vector-copy! */
3675 arg5
= POP(); arg4
= POP(); arg3
= POP(); arg2
= POP(); arg1
= POP();
3676 prim_u8vector_copy (); break;
3691 arg2
= ram_get_cdr (cont
);
3692 pc
= ram_get_entry (arg2
);
3693 env
= ram_get_cdr (arg2
);
3694 cont
= ram_get_car (cont
);
3702 /***************************************************************************/
3706 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
]));
3708 switch (bytecode_lo4
)
3711 /* prim #%boolean? */
3712 arg1
= POP(); prim_booleanp (); PUSH_ARG1(); break;
3714 /* prim #%network-init */
3715 prim_network_init (); break;
3717 /* prim #%network-cleanup */
3718 prim_network_cleanup (); break;
3720 /* prim #%receive-packet-to-u8vector */
3721 arg1
= POP(); prim_receive_packet_to_u8vector (); PUSH_ARG1(); break;
3723 /* prim #%send-packet-from-u8vector */
3724 arg2
= POP(); arg1
= POP(); prim_send_packet_from_u8vector ();
3752 /***************************************************************************/
3757 /*---------------------------------------------------------------------------*/
3763 printf ("usage: sim file.hex\n");
3767 int main (int argc
, char *argv
[])
3770 rom_addr rom_start_addr
= 0;
3776 if (argc
> 1 && argv
[1][0] == '-' && argv
[1][1] == 's')
3783 if ((h1
= hex (argv
[1][2])) < 0 ||
3784 (h2
= hex (argv
[1][3])) < 0 ||
3785 (h3
= hex (argv
[1][4])) != 0 ||
3786 (h4
= hex (argv
[1][5])) != 0 ||
3790 rom_start_addr
= (h1
<< 12) | (h2
<< 8) | (h3
<< 4) | h4
;
3797 printf ("Start address = 0x%04x\n", rom_start_addr
+ CODE_START
);
3803 if (!read_hex_file (argv
[1]))
3804 printf ("*** Could not read hex file \"%s\"\n", argv
[1]);
3809 if (rom_get (CODE_START
+0) != 0xfb ||
3810 rom_get (CODE_START
+1) != 0xd7)
3811 printf ("*** The hex file was not compiled with PICOBIT\n");
3815 for (i
=0; i
<8192; i
++)
3816 if (rom_get (i
) != 0xff)
3817 printf ("rom_mem[0x%04x] = 0x%02x\n", i
, rom_get (i
));
3823 printf ("**************** memory needed = %d\n", max_live
+1);
3833 /*---------------------------------------------------------------------------*/