1 /* file: "picobit-vm.c" */
4 * Copyright 2004 by Marc Feeley, All Rights Reserved.
8 * 15/08/2004 Release of version 1
14 /*---------------------------------------------------------------------------*/
19 typedef unsigned char uint8
;
20 typedef unsigned short uint16
;
21 typedef unsigned long uint32
;
23 /*---------------------------------------------------------------------------*/
43 extern volatile near uint8 IR_TX_BUF
[2+(8+2)+2];
44 extern volatile near uint8 FW_EVENTS
;
45 extern volatile near uint8 FW_OPS
;
46 extern volatile near uint8 IR_TX_LENGTH
;
47 extern volatile near uint8 IR_TX_LEDS
;
48 extern volatile near uint8 IR_TX_CURRENT_LEDS
;
49 extern volatile near uint8 IR_TX_POWER
;
50 extern volatile near uint8 IR_TX_CURRENT_POWER
;
51 extern volatile near uint8 IR_TX_SHIFT_REG
;
52 extern volatile near uint8 IR_TX_PTR
;
53 extern volatile near uint8 IR_TX_TIMEOUT
;
54 extern volatile near uint8 IR_TX_WAIT_RANGE
;
55 extern volatile near uint8 IR_TX_RETRY_COUNT
;
56 extern volatile near uint8 IR_TX_CRC_HI
;
57 extern volatile near uint8 IR_TX_CRC_LO
;
58 extern volatile near uint8 IR_TX_HI4
;
59 extern volatile near uint8 IR_TX_LO4
;
60 extern volatile near uint8 INT_IR_STATE_HI
;
61 extern volatile near uint8 INT_IR_STATE_LO
;
62 extern volatile near uint8 INT_PCLATH
;
63 extern volatile near uint8 INT_CODE
;
64 extern volatile near uint8 IR_BIT_CLOCK
;
65 extern volatile near uint8 CLOCK_UP
;
66 extern volatile near uint8 CLOCK_HI
;
67 extern volatile near uint8 CLOCK_LO
;
68 extern volatile near uint8 RANDOM
;
69 extern volatile near uint8 NODE_NUM
;
70 extern volatile near uint8 IR_RX_SOURCE
;
71 extern volatile near uint8 IR_RX_LENGTH
;
72 extern volatile near uint8 IR_RX_BUF
[2+(2+8)+2];
73 extern volatile near uint8 IR_RX_CRC_HI
;
74 extern volatile near uint8 IR_RX_CRC_LO
;
75 extern volatile near uint8 IR_RX_HI4
;
76 extern volatile near uint8 IR_RX_LO4
;
77 extern volatile near uint8 DRIVE_A_MODE
;
78 extern volatile near uint8 DRIVE_A_PWM
;
79 extern volatile near uint8 DRIVE_B_MODE
;
80 extern volatile near uint8 DRIVE_B_PWM
;
81 extern volatile near uint8 DRIVE_C_MODE
;
82 extern volatile near uint8 DRIVE_C_PWM
;
83 extern volatile near uint8 MOTOR_ID
;
84 extern volatile near uint8 FW_VALUE_UP
;
85 extern volatile near uint8 MOTOR_ROT
;
86 extern volatile near uint8 FW_VALUE_HI
;
87 extern volatile near uint8 MOTOR_POW
;
88 extern volatile near uint8 FW_VALUE_LO
;
89 extern volatile near uint8 FW_VALUE_TMP
;
90 extern volatile near uint8 FW_LAST_TX_TIME_LO
;
91 extern volatile near uint8 IR_RX_SAMPLE_TIMER
;
92 extern volatile near uint8 IR_RX_SHIFT_REG
;
93 extern volatile near uint8 IR_RX_PREVIOUS
;
94 extern volatile near uint8 IR_RX_PTR
;
95 extern volatile near uint8 IR_RX_BYTE
;
96 extern volatile near uint8 STDIO_TX_SEQ_NUM
;
97 extern volatile near uint8 STDIO_RX_SEQ_NUM
;
98 extern volatile near uint8 FW_TEMP1
;
100 extern void fw_clock_read (void);
101 extern void fw_motor (void);
102 extern void fw_light_read (void);
103 extern void fw_ir_tx (void);
104 extern void fw_ir_rx_stdio_char (void);
105 extern void fw_ir_tx_wait_ready (void);
106 extern void fw_ir_tx_stdio (void);
107 extern void program_mode (void);
116 static volatile near uint8 FW_VALUE_UP @
0x33;
117 static volatile near uint8 FW_VALUE_HI @
0x33;
118 static volatile near uint8 FW_VALUE_LO @
0x33;
120 #define ACTIVITY_LED1_LAT LATB
121 #define ACTIVITY_LED1_BIT 5
122 #define ACTIVITY_LED2_LAT LATB
123 #define ACTIVITY_LED2_BIT 4
124 static volatile near bit ACTIVITY_LED1 @
((unsigned)&ACTIVITY_LED1_LAT
*8)+ACTIVITY_LED1_BIT
;
125 static volatile near bit ACTIVITY_LED2 @
((unsigned)&ACTIVITY_LED2_LAT
*8)+ACTIVITY_LED2_BIT
;
136 #include <sys/types.h>
137 #include <sys/timeb.h>
140 #include <sys/time.h>
146 /*---------------------------------------------------------------------------*/
150 #define CODE_START 0x2000
155 #define IF_TRACE(x) x
156 #define IF_GC_TRACE(x)
159 #define IF_GC_TRACE(x)
162 /*---------------------------------------------------------------------------*/
167 #define ERROR(msg) program_mode ()
168 #define TYPE_ERROR(type) program_mode ()
175 #define ERROR(msg) error (msg)
176 #define TYPE_ERROR(type) type_error (type)
178 void error (char *msg
)
180 printf ("ERROR: %s\n", msg
);
184 void type_error (char *type
)
186 printf ("ERROR: An argument of type %s was expected\n", type
);
193 /*---------------------------------------------------------------------------*/
201 typedef uint16 ram_addr
;
202 typedef uint16 rom_addr
;
206 /*---------------------------------------------------------------------------*/
208 #define MIN_RAM_ENCODING 128
209 #define MAX_RAM_ENCODING 8192
210 // TODO some space in rom is not used, use for fixnums ?
211 #define RAM_BYTES ((MAX_RAM_ENCODING - MIN_RAM_ENCODING + 1)*4)
213 // TODO change if we change the proportion of rom and ram addresses
215 #define OBJ_TO_RAM_ADDR(o,f) (((ram_addr)((uint16)(o) - MIN_RAM_ENCODING) << 2) + (f))
216 #define OBJ_TO_ROM_ADDR(o,f) (((rom_addr)((uint8)(o) - MIN_ROM_ENCODING) << 2) + (CODE_START + 4 + (f)))
222 #define ram_get(a) *(uint8*)(a+0x200)
223 #define ram_set(a,x) *(uint8*)(a+0x200) = (x)
230 uint8 ram_mem
[RAM_BYTES
];
232 #define ram_get(a) ram_mem[a]
233 #define ram_set(a,x) ram_mem[a] = (x)
238 /*---------------------------------------------------------------------------*/
245 uint8
rom_get (rom_addr a
)
247 return *(rom uint8
*)a
;
255 #define ROM_BYTES 8192
257 uint8 rom_mem
[ROM_BYTES
] =
260 #define PUTCHAR_LIGHT_not
263 0xFB, 0xD7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x32
264 , 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
265 , 0x08, 0x50, 0x80, 0x16, 0xFE, 0xE8, 0x00, 0xFC
266 , 0x32, 0x80, 0x2D, 0xFE, 0xFC, 0x31, 0x80, 0x43
267 , 0xFE, 0xFC, 0x33, 0x80, 0x2D, 0xFE, 0xFC, 0x31
268 , 0x80, 0x43, 0xFE, 0x90, 0x16, 0x01, 0x20, 0xFC
269 , 0x32, 0xE3, 0xB0, 0x37, 0x09, 0xF3, 0xFF, 0x20
270 , 0xFC, 0x33, 0xE3, 0xB0, 0x40, 0x0A, 0xF3, 0xFF
271 , 0x08, 0xF3, 0xFF, 0x01, 0x40, 0x21, 0xD1, 0x00
272 , 0x02, 0xC0, 0x4C, 0x71, 0x01, 0x20, 0x50, 0x90
273 , 0x51, 0x00, 0xF1, 0x40, 0xD8, 0xB0, 0x59, 0x90
277 0xFB, 0xD7, 0x00, 0x00, 0x80, 0x08, 0xFE, 0xE8
278 , 0x00, 0xF6, 0xF5, 0x90, 0x08
282 uint8
rom_get (rom_addr a
)
284 return rom_mem
[a
-CODE_START
];
289 obj globals
[GLOVARS
];
291 /*---------------------------------------------------------------------------*/
299 fixnum n MIN_FIXNUM -> 3 ... MAX_FIXNUM -> 3 + (MAX_FIXNUM-MIN_FIXNUM)
300 TODO do we want 0..127 as fixnums ? would reduce number of ra/om objects
301 rom object 4 + (MAX_FIXNUM-MIN_FIXNUM) ... MIN_RAM_ENCODING-1
302 ram object MIN_RAM_ENCODING ... 4095 TODO was 255, now we have 12 bits
304 layout of memory allocated objects:
306 G's represent mark bits used by the gc TODO change GC, and does not use the same bits
308 bignum n 00G00000 uuuuuuuu hhhhhhhh llllllll (24 bit signed integer)
309 TODO we could have 29-bit integers
311 pair 1GGaaaaa aaaaaaaa 000ddddd dddddddd
312 TODO was 00000010 aaaaaaaa aaaadddd dddddddd
315 gives an address space of 2^13 * 4 = 32k (not all of it is for RAM, though)
317 symbol 1GG00000 00000000 00100000 00000000 TODO not used ? seems symbols are not even really supported, but the led user functions do use them, strange
319 string 1GG***** *chars** 01000000 00000000
321 vector 1GG***** *elems** 01100000 00000000 TODO not used yet
323 closure 01Gxxxxx xxxxxxxx aaaaaaaa aaaaaaaa
324 0x5ff<a<0x4000 is entry TODO we now have more 16 bits for the entry, 16 whole, how to use it ?
325 x is pointer to environment
327 continuation 01Gxxxxx xxxxxxxx aaaaaaaa aaaaaaaa 0x5ff<a<0x4000 is pc
328 TODO actually, 16 bits for the code
329 x is pointer to the second half
330 TODO ok, ugly hack, closures are in only one object, but continuations (since they seem to only be created by the runtime) are stored in 2, the compiler doesn't need to be changed much, not for closures at least, we'll just have to see if the similar representation is used somewhere in the vm
332 second half 1GGxxxxx xxxxxxxx 000yyyyy yyyyyyyy
333 of continuations, actually a simple pair
335 y is parent continuation
337 An environment is a list of objects built out of pairs. On entry to
338 a procedure the environment is the list of parameters to which is
339 added the environment of the closure being called.
341 The first byte at the entry point of a procedure gives the arity of
344 n = 0 to 127 -> procedure has n parameters (no rest parameter)
345 n = -128 to -1 -> procedure has -n parameters, the last is
353 #define MIN_FIXNUM_ENCODING 3
354 #define MIN_FIXNUM (-5)
355 #define MAX_FIXNUM 40
356 #define MIN_ROM_ENCODING (MIN_FIXNUM_ENCODING+MAX_FIXNUM-MIN_FIXNUM+1)
358 #define ENCODE_FIXNUM(n) ((obj)(n) + (MIN_FIXNUM_ENCODING - MIN_FIXNUM))
359 #define DECODE_FIXNUM(o) ((int32)(o) - (MIN_FIXNUM_ENCODING - MIN_FIXNUM))
362 #define IN_RAM(o) ((o) >= MIN_RAM_ENCODING)
363 #define IN_ROM(o) ((int8)(o) >= MIN_ROM_ENCODING)
366 // bignum first byte : 00G00000
367 #define BIGNUM_FIELD0 0
368 #define RAM_BIGNUM(o) ((ram_get_field0 (o) & 0xc0) == BIGNUM_FIELD0)
369 #define ROM_BIGNUM(o) ((rom_get_field0 (o) & 0xc0) == BIGNUM_FIELD0)
371 // composite first byte : 1GGxxxxx
372 #define COMPOSITE_FIELD0 0x80
373 #define RAM_COMPOSITE(o) ((ram_get_field0 (o) & 0x80) == COMPOSITE_FIELD0)
374 #define ROM_COMPOSITE(o) ((rom_get_field0 (o) & 0x80) == COMPOSITE_FIELD0)
376 // pair third byte : 000xxxxx
377 #define PAIR_FIELD2 0
378 #define RAM_PAIR(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == PAIR_FIELD2))
379 #define ROM_PAIR(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == PAIR_FIELD2))
381 // symbol third byte : 001xxxxx
382 #define SYMBOL_FIELD2 0x20
383 #define RAM_SYMBOL(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == SYMBOL_FIELD2))
384 #define ROM_SYMBOL(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == SYMBOL_FIELD2))
386 // string third byte : 010xxxxx
387 #define STRING_FIELD2 0x40
388 #define RAM_STRING(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == STRING_FIELD2))
389 #define ROM_STRING(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == STRING_FIELD2))
391 // vector third byte : 011xxxxx
392 #define VECTOR_FIELD2 0x60
393 #define RAM_VECTOR(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == VECTOR_FIELD2))
394 #define ROM_VECTOR(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == VECTOR_FIELD2))
396 // procedure / continuation first byte : 01Gxxxxx
397 #define PROCEDURE_FIELD0 0x40
398 #define RAM_PROCEDURE(o) ((ram_get_field0 (o) & 0xc0) == PROCEDURE_FIELD0)
399 #define ROM_PROCEDURE(o) ((rom_get_field0 (o) & 0xc0) == PROCEDURE_FIELD0)
401 /*---------------------------------------------------------------------------*/
403 #define RAM_GET_FIELD0_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,0))
404 #define RAM_SET_FIELD0_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,0), val)
405 #define ROM_GET_FIELD0_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,0))
407 // TODO changed, now gc bits are 0x60, were 0xc0, but the 1st is not always used
408 #define RAM_GET_GC_TAGS_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x60)
409 #define RAM_SET_GC_TAGS_MACRO(o,tags) \
410 (RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0x9f) | (tags)))
411 #define RAM_SET_GC_TAG0_MACRO(o,tag) \
412 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xdf) | (tag))
413 #define RAM_SET_GC_TAG1_MACRO(o,tag) \
414 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xbf) | (tag))
415 // TODO we can't set them both at once now, since some objects only have 1
416 // FOOBAR, maybe we can
419 #define RAM_GET_FIELD1_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,1))
420 #define RAM_GET_FIELD2_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,2))
421 #define RAM_GET_FIELD3_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,3))
422 #define RAM_SET_FIELD1_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,1), val)
423 #define RAM_SET_FIELD2_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,2), val)
424 #define RAM_SET_FIELD3_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,3), val)
425 #define ROM_GET_FIELD1_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,1))
426 #define ROM_GET_FIELD2_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,2))
427 #define ROM_GET_FIELD3_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,3))
430 // TODO this might be of use, but doesn't look like it is for now
432 #define RAM_GET_FIELD1_MACRO(o) \
433 (ram_get (OBJ_TO_RAM_ADDR(o,1)) + ((RAM_GET_FIELD0_MACRO(o) & 0x03)<<8))
434 #define RAM_GET_FIELD2_MACRO(o) \
435 (ram_get (OBJ_TO_RAM_ADDR(o,2)) + ((RAM_GET_FIELD0_MACRO(o) & 0x0c)<<6))
436 #define RAM_GET_FIELD3_MACRO(o) \
437 (ram_get (OBJ_TO_RAM_ADDR(o,3)) + ((RAM_GET_FIELD0_MACRO(o) & 0x30)<<4))
438 #define RAM_SET_FIELD1_MACRO(o,val) \
440 ram_set (OBJ_TO_RAM_ADDR(o,1), (val) & 0xff); \
441 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xfc) + (((val) >> 8) & 0x03)); \
443 #define RAM_SET_FIELD2_MACRO(o,val) \
445 ram_set (OBJ_TO_RAM_ADDR(o,2), (val) & 0xff); \
446 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xf3) + (((val) >> 6) & 0x0c)); \
448 #define RAM_SET_FIELD3_MACRO(o,val) \
450 ram_set (OBJ_TO_RAM_ADDR(o,3), (val) & 0xff); \
451 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xcf) + (((val) >> 4) & 0x30)); \
453 #define ROM_GET_FIELD1_MACRO(o) \
454 (rom_get (OBJ_TO_ROM_ADDR(o,1)) + ((ROM_GET_FIELD0_MACRO(o) & 0x03)<<8))
455 #define ROM_GET_FIELD2_MACRO(o) \
456 (rom_get (OBJ_TO_ROM_ADDR(o,2)) + ((ROM_GET_FIELD0_MACRO(o) & 0x0c)<<6))
457 #define ROM_GET_FIELD3_MACRO(o) \
458 (rom_get (OBJ_TO_ROM_ADDR(o,3)) + ((ROM_GET_FIELD0_MACRO(o) & 0x30)<<4))
461 uint8
ram_get_gc_tags (obj o
) { return RAM_GET_GC_TAGS_MACRO(o
); }
462 void ram_set_gc_tags (obj o
, uint8 tags
) { RAM_SET_GC_TAGS_MACRO(o
, tags
); }
463 void ram_set_gc_tag0 (obj o
, uint8 tag
) { RAM_SET_GC_TAG0_MACRO(o
,tag
); }
464 void ram_set_gc_tag1 (obj o
, uint8 tag
) { RAM_SET_GC_TAG1_MACRO(o
,tag
); }
465 // TODO we can't set them both at once anymore, some object only use 1
466 // FOOBAR actually, we might be able to, if we don't ever set or unset something used for the type
467 uint8
ram_get_field0 (obj o
) { return RAM_GET_FIELD0_MACRO(o
); }
468 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
469 word
ram_get_field2 (obj o
) { return RAM_GET_FIELD2_MACRO(o
); }
470 word
ram_get_field3 (obj o
) { return RAM_GET_FIELD3_MACRO(o
); }
471 void ram_set_field0 (obj o
, uint8 val
) { RAM_SET_FIELD0_MACRO(o
,val
); }
472 void ram_set_field1 (obj o
, word val
) { RAM_SET_FIELD1_MACRO(o
,val
); }
473 void ram_set_field2 (obj o
, word val
) { RAM_SET_FIELD2_MACRO(o
,val
); }
474 void ram_set_field3 (obj o
, word val
) { RAM_SET_FIELD3_MACRO(o
,val
); }
475 uint8
rom_get_field0 (obj o
) { return ROM_GET_FIELD0_MACRO(o
); }
476 word
rom_get_field1 (obj o
) { return ROM_GET_FIELD1_MACRO(o
); }
477 word
rom_get_field2 (obj o
) { return ROM_GET_FIELD2_MACRO(o
); }
478 word
rom_get_field3 (obj o
) { return ROM_GET_FIELD3_MACRO(o
); }
480 obj
ram_get_car (obj o
)
481 { return ((ram_get_field0 (o
) & 0x1f) << 8) | ram_get_field1 (o
); }
482 obj
rom_get_car (obj o
)
483 { return ((rom_get_field0 (o
) & 0x1f) << 8) | rom_get_field1 (o
); }
484 obj
ram_get_cdr (obj o
)
485 { return ((ram_get_field2 (o
) & 0x1f) << 8) | ram_get_field3 (o
); }
486 obj
rom_get_cdr (obj o
)
487 { return ((rom_get_field2 (o
) & 0x1f) << 8) | rom_get_field3 (o
); }
488 void ram_set_car (obj o
, obj val
)
490 ram_set_field0 (o
, ((val
& 0x1f00) >> 8) | (ram_get_field0 (o
) & 0xc0));
491 ram_set_field1 (o
, val
& 0xff);
493 void ram_set_cdr (obj o
, obj val
)
495 ram_set_field2 (o
, ((val
& 0x1f00) >> 8) | (ram_get_field2 (o
) & 0xc0));
496 ram_set_field3 (o
, val
& 0xff);
499 obj
get_global (uint8 i
) // TODO 8 ? do we want more than 256 globals ?
504 void set_global (uint8 i
, obj o
)
509 /*---------------------------------------------------------------------------*/
511 /* Interface to GC */
513 /* GC tags are in the top 2 bits of field 0 */
514 // TODO change GC with new representation FOOBAR
515 #define GC_TAG_0_LEFT (1<<5)
516 // TODO was 3<<5, changed to play nice with procedures and bignums, but should actually set only this bit, not clear the other
517 #define GC_TAG_1_LEFT (2<<5)
518 #define GC_TAG_UNMARKED (0<<5) /* must be 0 */ // TODO FOOBAR is it ok ? eevn for bignums ?
520 /* Number of object fields of objects in ram */
521 #define HAS_2_OBJECT_FIELDS(visit) (RAM_PAIR(visit))
522 #define HAS_1_OBJECT_FIELD(visit) (RAM_COMPOSITE(visit) || RAM_PROCEDURE(visit))
523 // TODO now we consider that all composites have at least 1 field, even symbols, as do procedures. no problem for symbols, since the car is always #f
524 // TODO was : (RAM_STRING(visit) || RAM_VECTOR(visit) || RAM_PROCEDURE(visit))
525 // TODO no real way to tell using simple inequality
526 // TODO if we ever have true bignums, bignums will have 1 object field
528 #define NIL OBJ_FALSE
530 /*---------------------------------------------------------------------------*/
532 /* Garbage collector */
534 obj free_list
; /* list of unused cells */
536 obj arg1
; /* root set */
543 uint8 na
; /* interpreter variables */ // TODO what's na ?
549 obj second_half
; /* the second half of continuations */
554 void init_ram_heap (void)
557 obj o
= MAX_RAM_ENCODING
;
561 while (o
>= MIN_RAM_ENCODING
)
563 ram_set_gc_tags (o
, GC_TAG_UNMARKED
);
564 ram_set_car (o
, free_list
); // TODO was field1
569 for (i
=0; i
<GLOVARS
; i
++)
570 set_global (i
, OBJ_FALSE
);
578 second_half
= OBJ_FALSE
;
585 obj stack
; // TODO do we need a stack ? since we have 0-1-2 children, we could do deutsche schorr waite
597 IF_GC_TRACE(printf ("push stack=%d (tag=%d) visit=%d (tag=%d)\n", stack
, ram_get_gc_tags (stack
)>>6, visit
, ram_get_gc_tags (visit
)>>6));
600 * Four cases are possible:
603 * stack visit tag F1 F2 F3
604 * NIL | +---+---+---+---+
609 * tag F1 F2 F3 stack visit tag F1 F2 F3
610 * +---+---+---+---+ | | +---+---+---+---+
611 * | 1 | | | | <-+ +-> | ? | | | |
612 * +---+---+---+-|-+ +---+---+---+---+
613 * <-----------------+
616 * tag F1 F2 F3 stack visit tag F1 F2 F3
617 * +---+---+---+---+ | | +---+---+---+---+
618 * | 2 | | | | <-+ +-> | ? | | | |
619 * +---+---+-|-+---+ +---+---+---+---+
623 * tag F1 F2 F3 stack visit tag F1 F2 F3
624 * +---+---+---+---+ | | +---+---+---+---+
625 * | 3 | | | | <-+ +-> | ? | | | |
626 * +---+-|-+---+---+ +---+---+---+---+
629 // TODO since no-one has 3 fields anymore, not really 4 cases ?
631 // if (ram_get_gc_tags (visit) != GC_TAG_UNMARKED) // TODO always matches procedures, WRONG, maybe check only the right gc bit ?/
632 if (ram_get_gc_tags (visit
) & 0x2f) // TODO we check only the last gc bit
633 IF_GC_TRACE(printf ("case 1\n")); // TODO are there cases where checking only the last gc bit is wrong ?
634 // TODO FOOBAR ok, with our new way, what do we check here ?
637 if (HAS_2_OBJECT_FIELDS(visit
))
639 IF_GC_TRACE(printf ("case 5\n"));
640 // TODO we don't have cases 2-4 anymore
644 temp
= ram_get_cdr (visit
);
648 IF_GC_TRACE(printf ("case 6\n"));
649 ram_set_gc_tags (visit
, GC_TAG_1_LEFT
);
650 ram_set_cdr (visit
, stack
);
654 IF_GC_TRACE(printf ("case 7\n"));
659 if (HAS_1_OBJECT_FIELD(visit
))
661 IF_GC_TRACE(printf ("case 8\n"));
665 temp
= ram_get_car (visit
);
669 IF_GC_TRACE(printf ("case 9\n"));
670 ram_set_gc_tag0 (visit
, GC_TAG_0_LEFT
); // TODO changed, now we only set the bit 0, we don't change the bit 1, since some objets have only 1 mark bit
671 ram_set_car (visit
, stack
);
675 IF_GC_TRACE(printf ("case 10\n"));
678 IF_GC_TRACE(printf ("case 11\n"));
680 ram_set_gc_tag0 (visit
, GC_TAG_0_LEFT
); // TODO changed, same as above
685 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));
689 if (ram_get_gc_tags (stack
) == GC_TAG_1_LEFT
) // TODO FOOBAR, this is always true for procedures that have not been marked, can such an object get here ? probably not, since when a procedure is popped, it has already been visited, so will be at 0 left
691 IF_GC_TRACE(printf ("case 13\n"));
693 temp
= ram_get_cdr (stack
); /* pop through field 2 */
694 ram_set_cdr (stack
, visit
);
701 IF_GC_TRACE(printf ("case 14\n"));
703 temp
= ram_get_car (stack
); /* pop through field 1 */
704 ram_set_car (stack
, visit
);
725 obj visit
= MAX_RAM_ENCODING
;
729 while (visit
>= MIN_RAM_ENCODING
)
731 if ((RAM_COMPOSITE(visit
) && (ram_get_gc_tags (visit
) == GC_TAG_UNMARKED
)) || (ram_get_gc_tags (visit
) & GC_TAG_0_LEFT
)) /* unmarked? */
732 // TODO now we check only 1 bit if the object has only 1 mark bit
734 ram_set_car (visit
, free_list
); // TODO was field1
739 if (RAM_COMPOSITE(visit
))
740 ram_set_gc_tags (visit
, GC_TAG_UNMARKED
);
741 else // only 1 mark bit to unset
742 ram_set_gc_tag0 (visit
, GC_TAG_UNMARKED
);
754 printf ("**************** memory needed = %d\n", max_live
+1);
771 for (i
=0; i
<GLOVARS
; i
++)
772 mark (get_global (i
));
777 obj
alloc_ram_cell (void)
791 ERROR("memory is full");
796 free_list
= ram_get_field1 (o
);
801 obj
alloc_ram_cell_init (uint8 f0
, uint8 f1
, uint8 f2
, uint8 f3
)
803 obj o
= alloc_ram_cell ();
805 ram_set_field0 (o
, f0
);
806 ram_set_field1 (o
, f1
);
807 ram_set_field2 (o
, f2
);
808 ram_set_field3 (o
, f3
);
813 /*---------------------------------------------------------------------------*/
815 int32
decode_int (obj o
)
821 if (o
< MIN_FIXNUM_ENCODING
)
822 TYPE_ERROR("integer");
824 if (o
<= (MIN_FIXNUM_ENCODING
+ (MAX_FIXNUM
- MIN_FIXNUM
)))
825 return DECODE_FIXNUM(o
);
830 TYPE_ERROR("integer");
832 u
= ram_get_field1 (o
);
833 h
= ram_get_field2 (o
);
834 l
= ram_get_field3 (o
);
839 TYPE_ERROR("integer");
841 u
= rom_get_field1 (o
);
842 h
= rom_get_field2 (o
);
843 l
= rom_get_field3 (o
);
846 TYPE_ERROR("integer");
849 return ((int32
)((((int16
)u
- 256) << 8) + h
) << 8) + l
;
851 return ((int32
)(((int16
)u
<< 8) + h
) << 8) + l
;
854 obj
encode_int (int32 n
)
856 if (n
>= MIN_FIXNUM
&& n
<= MAX_FIXNUM
)
857 return ENCODE_FIXNUM(n
);
859 return alloc_ram_cell_init (BIGNUM_FIELD0
, n
>> 16, n
>> 8, n
);
862 /*---------------------------------------------------------------------------*/
874 else if (o
== OBJ_TRUE
)
876 else if (o
== OBJ_NULL
)
878 else if (o
<= (MIN_FIXNUM_ENCODING
+ (MAX_FIXNUM
- MIN_FIXNUM
)))
879 printf ("%d", DECODE_FIXNUM(o
));
889 if ((in_ram
&& RAM_BIGNUM(o
)) || ROM_BIGNUM(o
))
890 printf ("%d", decode_int (o
));
891 else if ((in_ram
&& RAM_COMPOSITE(o
)) || ROM_COMPOSITE(o
))
896 if (in_ram
&& RAM_PAIR(o
))
898 car
= ram_get_car (o
);
899 cdr
= ram_get_cdr (o
);
907 else if (RAM_PAIR(ram_get_field0 (cdr
)))
909 car
= ram_get_car (cdr
);
910 cdr
= ram_get_cdr (cdr
);
922 else if (ROM_PAIR(o
))
924 car
= rom_get_car (o
);
925 cdr
= rom_get_cdr (o
);
932 else if (ROM_PAIR(rom_get_field0 (cdr
)))
934 car
= rom_get_car (cdr
);
935 cdr
= rom_get_cdr (cdr
);
940 else // TODO lots of repetition
947 else if ((in_ram
&& RAM_SYMBOL(o
)) || ROM_SYMBOL(o
))
948 printf ("#<symbol>");
949 else if ((in_ram
&& RAM_STRING(o
)) || ROM_STRING(o
))
950 printf ("#<string>");
951 else if ((in_ram
&& RAM_VECTOR(o
)) || ROM_VECTOR(o
))
952 printf ("#<vector>");
957 /* obj parent_cont; */
961 /* env = ram_get_field1 (o); */
963 /* env = rom_get_field1 (o); */
966 /* parent_cont = ram_get_field2 (o); */
968 /* parent_cont = rom_get_field2 (o); */
971 /* pc = ((rom_addr)(field0 + ((CODE_START>>8) - PROCEDURE_FIELD0)) << 8) + ram_get_field3 (o); */
973 /* pc = ((rom_addr)(field0 + ((CODE_START>>8) - PROCEDURE_FIELD0)) << 8) + rom_get_field3 (o); */
975 /* printf ("{0x%04x ", pc); */
978 /* show (parent_cont); */
979 /* printf ("}"); */ // TODO the representation of procedures changed
980 printf ("#<procedure>");
987 void show_state (rom_addr pc
)
989 printf ("pc=0x%04x bytecode=0x%02x env=", pc
, rom_get (pc
));
1006 /*---------------------------------------------------------------------------*/
1008 /* Integer operations */
1010 #define encode_bool(x) ((obj)(x))
1012 void prim_numberp (void)
1014 if (arg1
>= MIN_FIXNUM_ENCODING
1015 && arg1
<= (MIN_FIXNUM_ENCODING
+ (MAX_FIXNUM
- MIN_FIXNUM
)))
1020 arg1
= encode_bool (RAM_BIGNUM(arg1
));
1021 else if (IN_ROM(arg1
))
1022 arg1
= encode_bool (ROM_BIGNUM(arg1
));
1028 void decode_2_int_args (void)
1030 a1
= decode_int (arg1
);
1031 a2
= decode_int (arg2
);
1034 void prim_add (void)
1036 decode_2_int_args ();
1037 arg1
= encode_int (a1
+ a2
);
1041 void prim_sub (void)
1043 decode_2_int_args ();
1044 arg1
= encode_int (a1
- a2
);
1048 void prim_mul (void)
1050 decode_2_int_args ();
1051 arg1
= encode_int (a1
* a2
);
1055 void prim_div (void)
1057 decode_2_int_args ();
1059 ERROR("divide by 0");
1060 arg1
= encode_int (a1
/ a2
);
1064 void prim_rem (void)
1066 decode_2_int_args ();
1068 ERROR("divide by 0");
1069 arg1
= encode_int (a1
% a2
);
1073 void prim_neg (void)
1075 a1
= decode_int (arg1
);
1076 arg1
= encode_int (- a1
);
1081 decode_2_int_args ();
1082 arg1
= encode_bool (a1
== a2
);
1088 decode_2_int_args ();
1089 arg1
= encode_bool (a1
< a2
);
1095 decode_2_int_args ();
1096 arg1
= encode_bool (a1
> a2
);
1100 /*---------------------------------------------------------------------------*/
1102 /* List operations */
1104 void prim_pairp (void)
1107 arg1
= encode_bool (RAM_PAIR(arg1
));
1108 else if (IN_ROM(arg1
))
1109 arg1
= encode_bool (ROM_PAIR(arg1
));
1114 obj
cons (obj car
, obj cdr
)
1116 return alloc_ram_cell_init (COMPOSITE_FIELD0
| ((car
& 0x1f00) >> 8),
1118 PAIR_FIELD2
| ((cdr
& 0x1f00) >> 8),
1122 void prim_cons (void)
1124 arg1
= cons (arg1
, arg2
);
1128 void prim_car (void)
1132 if (!RAM_PAIR(arg1
))
1134 arg1
= ram_get_car (arg1
);
1136 else if (IN_ROM(arg1
))
1138 if (!ROM_PAIR(arg1
))
1140 arg1
= rom_get_car (arg1
);
1146 void prim_cdr (void)
1150 if (!RAM_PAIR(arg1
))
1152 arg1
= ram_get_cdr (arg1
);
1154 else if (IN_ROM(arg1
))
1156 if (!ROM_PAIR(arg1
))
1158 arg1
= rom_get_cdr (arg1
);
1164 void prim_set_car (void)
1168 if (!RAM_PAIR(arg1
))
1171 ram_set_car (arg1
, arg2
);
1179 void prim_set_cdr (void)
1183 if (!RAM_PAIR(arg1
))
1186 ram_set_cdr (arg1
, arg2
);
1194 void prim_nullp (void)
1196 arg1
= encode_bool (arg1
== OBJ_NULL
);
1199 /*---------------------------------------------------------------------------*/
1201 /* Miscellaneous operations */
1203 void prim_eqp (void)
1205 arg1
= encode_bool (arg1
== arg2
);
1209 void prim_not (void)
1211 arg1
= encode_bool (arg1
== OBJ_FALSE
);
1214 void prim_symbolp (void)
1217 arg1
= encode_bool (RAM_SYMBOL(arg1
));
1218 else if (IN_ROM(arg1
))
1219 arg1
= encode_bool (ROM_SYMBOL(arg1
));
1224 void prim_stringp (void)
1227 arg1
= encode_bool (RAM_STRING(arg1
));
1228 else if (IN_ROM(arg1
))
1229 arg1
= encode_bool (ROM_STRING(arg1
));
1234 void prim_string2list (void)
1238 if (!RAM_STRING(arg1
))
1239 TYPE_ERROR("string");
1241 arg1
= ram_get_car (arg1
);
1243 else if (IN_ROM(arg1
))
1245 if (!ROM_STRING(arg1
))
1246 TYPE_ERROR("string");
1248 arg1
= rom_get_car (arg1
);
1251 TYPE_ERROR("string");
1254 void prim_list2string (void)
1256 arg1
= alloc_ram_cell_init (COMPOSITE_FIELD0
| ((arg1
& 0x1f00) >> 8),
1262 void prim_ior (void)
1264 a1
= decode_int (arg1
);
1265 a2
= decode_int (arg2
);
1266 arg1
= encode_int (a1
| a2
);
1270 void prim_xor (void)
1272 a1
= decode_int (arg1
);
1273 a2
= decode_int (arg2
);
1274 arg1
= encode_int (a1
^ a2
);
1279 /*---------------------------------------------------------------------------*/
1281 /* Robot specific operations */
1284 void prim_print (void)
1299 int32
read_clock (void)
1307 now
= ((int32
)(((int16
)FW_VALUE_UP
<< 8) + FW_VALUE_HI
) << 8) + FW_VALUE_LO
;
1315 static int32 start
= 0;
1320 now
= tb
.time
* 100 + tb
.millitm
/ 10;
1327 static int32 start
= 0;
1330 if (gettimeofday (&tv
, NULL
) == 0)
1332 now
= tv
.tv_sec
* 100 + tv
.tv_usec
/ 10000;
1346 void prim_clock (void)
1348 arg1
= encode_int (read_clock ());
1352 void prim_motor (void)
1354 decode_2_int_args ();
1355 a3
= decode_int (arg3
);
1357 if (a1
< 0 || a1
> 2 || a2
< -1 || a2
> 1 || a3
< -4 || a3
> 4)
1358 ERROR("argument out of range to procedure \"motor\"");
1372 printf ("motor %d -> rotation=%d power=%d\n", a1
, a2
, a3
);
1383 void prim_led (void)
1385 a1
= decode_int (arg1
);
1387 if (a1
< 0 || a1
> 2){
1388 printf("%d", a1
); // TODO debug
1389 ERROR("argument out of range to procedure \"led\"");
1394 LATBbits
.LATB5
= (a1
== 1);
1395 LATBbits
.LATB4
= (a1
== 2);
1401 ACTIVITY_LED1
= (a1
== 1);
1402 ACTIVITY_LED2
= (a1
== 2);
1408 printf ("led -> %s\n", (a1
==1)?"red":(a1
==2)?"green":"off");
1417 void prim_getchar_wait (void)
1419 a1
= decode_int (arg1
);
1420 a1
= read_clock () + a1
;
1428 uint8 seq_num
= STDIO_RX_SEQ_NUM
;
1430 fw_ir_rx_stdio_char ();
1432 if (seq_num
!= STDIO_RX_SEQ_NUM
)
1434 arg1
= encode_int (FW_VALUE_LO
);
1437 } while (read_clock () < a1
);
1451 arg1
= encode_int (_getch ());
1454 } while (read_clock () < a1
);
1459 arg1
= encode_int (getchar ());
1467 void prim_putchar (void)
1469 a1
= decode_int (arg1
);
1471 if (a1
< 0 || a1
> 255)
1472 ERROR("argument out of range to procedure \"putchar\"");
1476 fw_ir_tx_wait_ready ();
1496 void prim_light (void)
1504 light
= FW_VALUE_LO
;
1510 light
= read_clock () & 31;
1512 if (light
> 15) light
= 32 - light
;
1518 arg1
= encode_int (light
);
1522 /*---------------------------------------------------------------------------*/
1526 int hidden_fgetc (FILE *f
)
1536 #define fgetc(f) hidden_fgetc(f)
1538 void write_hex_nibble (int n
)
1540 putchar ("0123456789ABCDEF"[n
]);
1543 void write_hex (uint8 n
)
1545 write_hex_nibble (n
>> 4);
1546 write_hex_nibble (n
& 0x0f);
1551 if (c
>= '0' && c
<= '9')
1554 if (c
>= 'A' && c
<= 'F')
1555 return (c
- 'A' + 10);
1557 if (c
>= 'a' && c
<= 'f')
1558 return (c
- 'a' + 10);
1563 int read_hex_byte (FILE *f
)
1565 int h1
= hex (fgetc (f
));
1566 int h2
= hex (fgetc (f
));
1568 if (h1
>= 0 && h2
>= 0)
1569 return (h1
<<4) + h2
;
1574 int read_hex_file (char *filename
)
1577 FILE *f
= fopen (filename
, "r");
1587 for (i
=0; i
<ROM_BYTES
; i
++)
1592 while ((c
= fgetc (f
)) != EOF
)
1594 if ((c
== '\r') || (c
== '\n'))
1598 (len
= read_hex_byte (f
)) < 0 ||
1599 (a1
= read_hex_byte (f
)) < 0 ||
1600 (a2
= read_hex_byte (f
)) < 0 ||
1601 (t
= read_hex_byte (f
)) < 0)
1607 sum
= len
+ a1
+ a2
+ t
;
1615 unsigned long adr
= ((unsigned long)hi16
<< 16) + a
- CODE_START
;
1617 if ((b
= read_hex_byte (f
)) < 0)
1620 if (adr
>= 0 && adr
< ROM_BYTES
)
1623 a
= (a
+ 1) & 0xffff;
1640 if ((a1
= read_hex_byte (f
)) < 0 ||
1641 (a2
= read_hex_byte (f
)) < 0)
1646 hi16
= (a1
<<8) + a2
;
1651 if ((b
= read_hex_byte (f
)) < 0)
1658 printf ("*** HEX file checksum error (expected 0x%02x)\n", sum
);
1664 if ((c
!= '\r') && (c
!= '\n'))
1675 printf ("*** HEX file syntax error\n");
1685 /*---------------------------------------------------------------------------*/
1687 #define FETCH_NEXT_BYTECODE() bytecode = rom_get (pc++)
1689 #define BEGIN_DISPATCH() \
1691 IF_TRACE(show_state (pc)); \
1692 FETCH_NEXT_BYTECODE(); \
1693 bytecode_hi4 = bytecode & 0xf0; \
1694 bytecode_lo4 = bytecode & 0x0f; \
1695 switch (bytecode_hi4 >> 4) {
1697 #define END_DISPATCH() }
1699 #define CASE(opcode) case (opcode>>4):;
1701 #define DISPATCH(); goto dispatch;
1706 #define bytecode TABLAT
1707 #define bytecode_hi4 WREG
1710 #define PUSH_CONSTANT1 0x00
1711 #define PUSH_CONSTANT2 0x10
1712 #define PUSH_STACK1 0x20
1713 #define PUSH_STACK2 0x30
1714 #define PUSH_GLOBAL 0x40
1715 #define SET_GLOBAL 0x50
1718 #define CALL_TOPLEVEL 0x80
1719 #define JUMP_TOPLEVEL 0x90
1721 #define GOTO_IF_FALSE 0xb0
1722 #define CLOSURE 0xc0
1729 char *prim_name
[48] =
1753 "prim #%graft-to-cont",
1754 "prim #%return-to-cont",
1758 "prim #%string->list",
1759 "prim #%list->string",
1760 "prim #%set-fst!", // ADDED TODO obsolete, but kept to have the right size
1761 "prim #%set-snd!", // ADDED
1762 "prim #%set-trd!", // ADDED
1767 "prim #%getchar-wait",
1770 "prim #%triplet?", // ADDED
1771 "prim #%triplet", // ADDED
1772 "prim #%fst", // ADDED
1773 "prim #%snd", // ADDED
1774 "prim #%trd", // ADDED
1775 "push-constant [long]",
1783 #define PUSH_ARG1() push_arg1 ()
1786 void push_arg1 (void)
1788 env
= cons (arg1
, env
);
1794 obj o
= ram_get_car (env
);
1795 env
= ram_get_cdr (env
);
1799 void pop_procedure (void) // TODO where do we get the env of the procedure ?
1800 { // TODO can continuations end up ond the stack ? if so, they act differently than procedures
1804 if (RAM_PROCEDURE(arg1
))
1805 TYPE_ERROR("procedure");
1807 entry
= ((ram_get_field2 (arg1
) << 8) | ram_get_field3 (arg1
))
1810 else if (IN_ROM(arg1
))
1812 if (ROM_PROCEDURE(arg1
))
1813 TYPE_ERROR("procedure");
1815 entry
= ((rom_get_field2 (arg1
) << 8) | rom_get_field3 (arg1
))
1819 TYPE_ERROR("procedure");
1822 void handle_arity_and_rest_param (void)
1826 np
= rom_get (entry
++); // TODO does that mean we can't have procedures in ram ?
1828 if ((np
& 0x80) == 0)
1831 ERROR("wrong number of arguments");
1838 ERROR("wrong number of arguments");
1846 arg3
= cons (arg4
, arg3
);
1852 arg1
= cons (arg3
, arg1
); // TODO what shpuld be the value of arg1 at this point ? the popped procedure ? the old env ? looks like the popped procedure
1857 void build_env (void)
1863 arg1
= cons (arg3
, arg1
);
1871 void save_cont (void)
1873 second_half
= cons (env
, cont
);
1874 cont
= alloc_ram_cell_init (PROCEDURE_FIELD0
| ((second_half
&0x1f00) >> 8),
1880 void interpreter (void)
1884 pc
= (CODE_START
+ 4) + ((rom_addr
)rom_get (CODE_START
+2) << 2);
1888 /***************************************************************************/
1889 CASE(PUSH_CONSTANT1
);
1891 IF_TRACE(printf(" (push-constant "); show (bytecode_lo4
); printf (")\n"));
1893 arg1
= bytecode_lo4
;
1899 /***************************************************************************/
1900 CASE(PUSH_CONSTANT2
);
1902 IF_TRACE(printf(" (push-constant "); show (bytecode_lo4
+16); printf (")\n"));
1903 // TODO for bigger fixnums and co, we have to use push long ? fix push long
1904 arg1
= bytecode_lo4
+16;
1910 /***************************************************************************/
1913 IF_TRACE(printf(" (push-stack %d)\n", bytecode_lo4
));
1917 while (bytecode_lo4
!= 0)
1919 arg1
= ram_get_cdr (arg1
);
1923 arg1
= ram_get_car (arg1
);
1929 /***************************************************************************/
1932 IF_TRACE(printf(" (push-stack %d)\n", bytecode_lo4
+16)); // TODO do we ever need to go this far in the stack ? since the stack is the env, maybe, if not, we have one free instruction
1938 while (bytecode_lo4
!= 0)
1940 arg1
= ram_get_cdr (arg1
);
1944 arg1
= ram_get_car (arg1
);
1950 /***************************************************************************/
1953 IF_TRACE(printf(" (push-global %d)\n", bytecode_lo4
));
1955 arg1
= get_global (bytecode_lo4
);
1961 /***************************************************************************/
1964 IF_TRACE(printf(" (set-global %d)\n", bytecode_lo4
));
1966 set_global (bytecode_lo4
, POP());
1970 /***************************************************************************/
1973 IF_TRACE(printf(" (call %d)\n", bytecode_lo4
));
1978 handle_arity_and_rest_param ();
1989 /***************************************************************************/
1992 IF_TRACE(printf(" (jump %d)\n", bytecode_lo4
));
1997 handle_arity_and_rest_param ();
2007 /***************************************************************************/
2008 CASE(CALL_TOPLEVEL
);
2010 FETCH_NEXT_BYTECODE();
2011 second_half
= bytecode
; // TODO make sure second_half is not already in use
2013 FETCH_NEXT_BYTECODE();
2015 IF_TRACE(printf(" (call-toplevel 0x%04x)\n", ((second_half
<< 8) | bytecode
) + CODE_START
));
2017 entry
= ((second_half
<< 8) | bytecode
) + CODE_START
; // TODO FOOBAR we'd have to change the compiler to use 2 bytes after the opcode instead of one, and now we have the last 4 bits of the opcode free, to do pretty much anything
2020 na
= rom_get (entry
++);
2032 /***************************************************************************/
2033 CASE(JUMP_TOPLEVEL
);
2035 FETCH_NEXT_BYTECODE();
2036 second_half
= bytecode
; // TODO make sure second_half is not already in use
2038 FETCH_NEXT_BYTECODE();
2040 IF_TRACE(printf(" (jump-toplevel 0x%04x)\n", ((second_half
<< 8) | bytecode
) + CODE_START
));
2042 entry
= ((second_half
<< 8) | bytecode
) + CODE_START
;
2045 na
= rom_get (entry
++);
2056 /***************************************************************************/
2059 FETCH_NEXT_BYTECODE();
2060 // TODO goto's use 12-bit addresses, unlike calls and jumps, which use 16, is it ok ?
2061 IF_TRACE(printf(" (goto 0x%04x)\n", ((rom_addr
)(bytecode_lo4
+ (CODE_START
>> 8)) << 8) + bytecode
));
2063 pc
= ((rom_addr
)(bytecode_lo4
+ (CODE_START
>> 8)) << 8) + bytecode
;
2067 /***************************************************************************/
2068 CASE(GOTO_IF_FALSE
);
2070 FETCH_NEXT_BYTECODE();
2072 IF_TRACE(printf(" (goto-if-false 0x%04x)\n", ((rom_addr
)(bytecode_lo4
+ (CODE_START
>> 8)) << 8) + bytecode
));
2074 if (POP() == OBJ_FALSE
)
2075 pc
= ((rom_addr
)(bytecode_lo4
+ (CODE_START
>> 8)) << 8) + bytecode
;
2079 /***************************************************************************/
2082 FETCH_NEXT_BYTECODE();
2083 second_half
= bytecode
;
2085 FETCH_NEXT_BYTECODE();
2087 IF_TRACE(printf(" (closure 0x%04x)\n", (second_half
<< 8) | bytecode
));
2088 // TODO original had CODE_START, while the real code below didn't
2090 arg2
= POP(); // #f TODO should be, at least, and not used anymore
2091 arg3
= POP(); // env
2093 entry
= (second_half
<< 8) | bytecode
; // TODO original had no CODE_START, why ?
2095 arg1
= alloc_ram_cell_init (PROCEDURE_FIELD0
| ((arg3
& 0x1f00) >> 8),
2107 /***************************************************************************/
2110 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
]));
2112 switch (bytecode_lo4
)
2115 arg1
= POP(); prim_numberp (); PUSH_ARG1(); break;
2117 arg2
= POP(); arg1
= POP(); prim_add (); PUSH_ARG1(); break;
2119 arg2
= POP(); arg1
= POP(); prim_sub (); PUSH_ARG1(); break;
2121 arg2
= POP(); arg1
= POP(); prim_mul (); PUSH_ARG1(); break;
2123 arg2
= POP(); arg1
= POP(); prim_div (); PUSH_ARG1(); break;
2125 arg2
= POP(); arg1
= POP(); prim_rem (); PUSH_ARG1(); break;
2127 arg1
= POP(); prim_neg (); PUSH_ARG1(); break;
2129 arg2
= POP(); arg1
= POP(); prim_eq (); PUSH_ARG1(); break;
2131 arg2
= POP(); arg1
= POP(); prim_lt (); PUSH_ARG1(); break;
2133 arg2
= POP(); arg1
= POP(); prim_ior (); PUSH_ARG1(); break;
2135 arg2
= POP(); arg1
= POP(); prim_gt (); PUSH_ARG1(); break;
2137 arg2
= POP(); arg1
= POP(); prim_xor (); PUSH_ARG1(); break;
2139 arg1
= POP(); prim_pairp (); PUSH_ARG1(); break;
2141 arg2
= POP(); arg1
= POP(); prim_cons (); PUSH_ARG1(); break;
2143 arg1
= POP(); prim_car (); PUSH_ARG1(); break;
2145 arg1
= POP(); prim_cdr (); PUSH_ARG1(); break;
2150 /***************************************************************************/
2153 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
+16]));
2155 switch (bytecode_lo4
)
2158 arg2
= POP(); arg1
= POP(); prim_set_car (); break;
2160 arg2
= POP(); arg1
= POP(); prim_set_cdr (); break;
2162 arg1
= POP(); prim_nullp (); PUSH_ARG1(); break;
2164 arg2
= POP(); arg1
= POP(); prim_eqp (); PUSH_ARG1(); break;
2166 arg1
= POP(); prim_not (); PUSH_ARG1(); break;
2168 /* prim #%get-cont */
2173 /* prim #%graft-to-cont */
2175 arg1
= POP(); /* thunk to call */
2176 cont
= POP(); /* continuation */
2183 handle_arity_and_rest_param ();
2193 /* prim #%return-to-cont */
2195 arg1
= POP(); /* value to return */
2196 cont
= POP(); /* continuation */
2198 pc
= ((ram_get_field2 (cont
) << 8) | ram_get_field3 (cont
)) + CODE_START
;
2199 second_half
= ram_get_car (cont
);
2200 env
= ram_get_car (second_half
);
2201 cont
= ram_get_cdr (second_half
);
2210 /* prim #%symbol? */
2211 arg1
= POP(); prim_symbolp (); PUSH_ARG1(); break;
2213 /* prim #%string? */
2214 arg1
= POP(); prim_stringp (); PUSH_ARG1(); break;
2216 /* prim #%string->list */
2217 arg1
= POP(); prim_string2list (); PUSH_ARG1(); break;
2219 /* prim #%list->string */
2220 arg1
= POP(); prim_list2string (); PUSH_ARG1(); break;
2233 /***************************************************************************/
2236 IF_TRACE(printf(" (%s)\n", prim_name
[bytecode_lo4
+32]));
2238 switch (bytecode_lo4
)
2247 prim_clock (); PUSH_ARG1(); break;
2250 arg3
= POP(); arg2
= POP(); arg1
= POP(); prim_motor (); break;
2253 arg1
= POP(); prim_led (); ;break;
2255 /* prim #%getchar-wait */
2256 arg1
= POP(); prim_getchar_wait (); PUSH_ARG1(); break;
2258 /* prim #%putchar */
2259 arg1
= POP(); prim_putchar (); break;
2262 prim_light (); PUSH_ARG1(); break;
2264 case 7: // TODO since not all of them will be used for vectors, maybe some could be used to have more globals ? or something else ?
2276 /* push-constant [long] */
2277 FETCH_NEXT_BYTECODE();
2278 second_half
= bytecode
;
2279 FETCH_NEXT_BYTECODE();
2280 arg1
= (second_half
<< 8) | bytecode
;
2296 pc
= ((ram_get_field2 (cont
) << 8) | ram_get_field3 (cont
)) + CODE_START
;
2297 second_half
= ram_get_car (cont
);
2298 env
= ram_get_car (second_half
);
2299 cont
= ram_get_cdr (second_half
);
2306 /***************************************************************************/
2311 /*---------------------------------------------------------------------------*/
2317 printf ("usage: sim file.hex\n");
2321 int main (int argc
, char *argv
[])
2324 rom_addr rom_start_addr
= 0;
2326 if (argc
> 1 && argv
[1][0] == '-' && argv
[1][1] == 's')
2333 if ((h1
= hex (argv
[1][2])) < 0 ||
2334 (h2
= hex (argv
[1][3])) < 0 ||
2335 (h3
= hex (argv
[1][4])) != 0 ||
2336 (h4
= hex (argv
[1][5])) != 0 ||
2340 rom_start_addr
= (h1
<< 12) | (h2
<< 8) | (h3
<< 4) | h4
;
2347 printf ("Start address = 0x%04x\n", rom_start_addr
);
2353 if (!read_hex_file (argv
[1]))
2354 printf ("*** Could not read hex file \"%s\"\n", argv
[1]);
2359 if (rom_get (CODE_START
+0) != 0xfb ||
2360 rom_get (CODE_START
+1) != 0xd7)
2361 printf ("*** The hex file was not compiled with PICOBIT\n");
2365 for (i
=0; i
<8192; i
++)
2366 if (rom_get (i
) != 0xff)
2367 printf ("rom_mem[0x%04x] = 0x%02x\n", i
, rom_get (i
));
2373 printf ("**************** memory needed = %d\n", max_live
+1);
2383 /*---------------------------------------------------------------------------*/
2387 /* $Id: c018i.c,v 1.1.2.1 2004/03/09 16:47:01 sealep Exp $ */
2389 /* Copyright (c)1999 Microchip Technology */
2391 /* MPLAB-C18 startup code, including initialized data */
2394 /* external reference to the user's main routine */
2395 extern void main (void);
2396 /* prototype for the startup function */
2399 void _startup (void);
2400 /* prototype for the initialized data setup */
2401 void _do_cinit (void);
2403 extern volatile near
unsigned long short TBLPTR
;
2404 extern near
unsigned FSR0
;
2405 extern near
char FPFLAGS
;
2409 #pragma code _entry_scn=0x000000
2413 _asm
goto _startup _endasm
2416 #pragma code _startup_scn
2423 // Initialize the stack pointer
2424 lfsr
1, _stack lfsr
2, _stack clrf TBLPTRU
, 0 // 1st silicon doesn't do this on POR
2425 bcf FPFLAGS
,RND
,0 // Initialize rounding flag for floating point libs
2430 // Call the user's main routine
2434 } /* end _startup() */
2436 /* MPLAB-C18 initialized data memory support */
2437 /* The linker will populate the _cinit table */
2438 extern far rom
struct
2440 unsigned short num_init
;
2451 #pragma code _cinit_scn
2455 /* we'll make the assumption in the following code that these statics
2456 * will be allocated into the same bank.
2458 static short long prom
;
2459 static unsigned short curr_byte
;
2460 static unsigned short curr_entry
;
2461 static short long data_ptr
;
2463 // Initialized data...
2464 TBLPTR
= (short long)&_cinit
;
2472 movwf curr_entry
+1, 1
2474 //while (curr_entry)
2479 tstfsz curr_entry
, 1
2483 /* Count down so we only have to look up the data in _cinit
2486 * At this point we know that TBLPTR points to the top of the current
2487 * entry in _cinit, so we can just start reading the from, to, and
2491 /* read the source address */
2501 /* skip a byte since it's stored as a 32bit int */
2503 /* read the destination address directly into FSR0 */
2510 /* skip two bytes since it's stored as a 32bit int */
2513 /* read the destination address directly into FSR0 */
2519 movwf curr_byte
+1, 1
2520 /* skip two bytes since it's stored as a 32bit int */
2524 //prom = data_ptr->from;
2525 //FSR0 = data_ptr->to;
2526 //curr_byte = (unsigned short) data_ptr->size;
2527 /* the table pointer now points to the next entry. Save it
2528 * off since we'll be using the table pointer to do the copying
2533 /* now assign the source address to the table pointer */
2536 /* do the copy loop */
2538 // determine if we have any more bytes to copy
2540 movf curr_byte
, 1, 1
2542 bnz
2 // copy_one_byte
2543 movf curr_byte
+ 1, 1, 1
2544 bz
7 // done_copying
2551 // decrement byte counter
2552 decf curr_byte
, 1, 1
2554 decf curr_byte
+ 1, 1, 1
2555 bra
-7 // copy_one_byte
2560 /* restore the table pointer for the next entry */
2569 #pragma code picobit_boot=0x001ffa
2570 void _picobit_boot (void)
2572 _asm
goto _startup _endasm
2577 /*---------------------------------------------------------------------------*/