1 /* file: "picobit-vm.h" */
4 * Copyright 2004-2009 by Marc Feeley and Vincent St-Amour, All Rights Reserved.
12 #define INFINITE_PRECISION_BIGNUMS
14 /*---------------------------------------------------------------------------*/
19 // these types are already defined in SIXPIC
23 typedef unsigned char uint8
;
24 typedef unsigned short uint16
;
25 typedef unsigned long uint32
;
30 typedef uint16 ram_addr
;
31 typedef uint16 rom_addr
;
33 // pointers are 13 bits
36 /*---------------------------------------------------------------------------*/
57 static volatile near uint8 FW_VALUE_UP @
0x33;
58 static volatile near uint8 FW_VALUE_HI @
0x33;
59 static volatile near uint8 FW_VALUE_LO @
0x33;
61 #define ACTIVITY_LED1_LAT LATB
62 #define ACTIVITY_LED1_BIT 5
63 #define ACTIVITY_LED2_LAT LATB
64 #define ACTIVITY_LED2_BIT 4
65 static volatile near bit ACTIVITY_LED1 @
((unsigned)&ACTIVITY_LED1_LAT
*8)+ACTIVITY_LED1_BIT
;
66 static volatile near bit ACTIVITY_LED2 @
((unsigned)&ACTIVITY_LED2_LAT
*8)+ACTIVITY_LED2_BIT
;
78 #define MAX_PACKET_SIZE BUFSIZ
81 char errbuf
[PCAP_ERRBUF_SIZE
];
83 #define INTERFACE "eth0"
84 char buf
[MAX_PACKET_SIZE
]; // buffer for writing
89 #include <sys/types.h>
90 #include <sys/timeb.h>
101 /*---------------------------------------------------------------------------*/
103 // miscellaneous definitions
104 // TODO put at the end ?
106 // TODO these 2 are only used in negp, use them elsewhere ?
110 #define CODE_START 0x8000
112 /*---------------------------------------------------------------------------*/
117 #define IF_TRACE(x) x
118 #define IF_GC_TRACE(x) x
121 #define IF_GC_TRACE(x)
124 /*---------------------------------------------------------------------------*/
129 #define ERROR(prim, msg) halt_with_error()
130 #define TYPE_ERROR(prim, type) halt_with_error()
134 #define ERROR(prim, msg) error (prim, msg)
135 #define TYPE_ERROR(prim, type) type_error (prim, type)
136 void error (char *prim
, char *msg
);
137 void type_error (char *prim
, char *type
);
140 /*---------------------------------------------------------------------------*/
142 // address space layout
143 // TODO document each zone, also explain that since vector space is in ram, it uses the ram primitives
145 #define MAX_VEC_ENCODING 2047
146 #define MIN_VEC_ENCODING 1280
147 #define VEC_BYTES ((MAX_VEC_ENCODING - MIN_VEC_ENCODING + 1)*4)
148 // if the pic has less than 8k of memory, start vector space lower
150 #define MAX_RAM_ENCODING 1279
151 #define MIN_RAM_ENCODING 512
152 #define RAM_BYTES ((MAX_RAM_ENCODING - MIN_RAM_ENCODING + 1)*4)
154 #define MIN_FIXNUM_ENCODING 3
155 #define MIN_FIXNUM -1
156 #define MAX_FIXNUM 255
157 #define MIN_ROM_ENCODING (MIN_FIXNUM_ENCODING + MAX_FIXNUM - MIN_FIXNUM + 1)
159 #define OBJ_TO_RAM_ADDR(o,f) ((((o) - MIN_RAM_ENCODING) << 2) + (f))
160 #define OBJ_TO_ROM_ADDR(o,f) ((((o) - MIN_ROM_ENCODING) << 2) + (CODE_START + 4 + (f)))
164 #define ram_get(a) *(a+0x200)
165 #define ram_set(a,x) *(a+0x200) = (x)
167 #define ram_get(a) *(uint8*)(a+0x200)
168 #define ram_set(a,x) *(uint8*)(a+0x200) = (x)
172 uint8 ram_mem
[RAM_BYTES
+ VEC_BYTES
];
173 #define ram_get(a) ram_mem[a]
174 #define ram_set(a,x) ram_mem[a] = (x)
179 // provided by SIXPIC
180 uint8
rom_get (rom_addr a
){
181 return *(rom uint8
*)a
;
187 #define ROM_BYTES 8192
188 uint8 rom_mem
[ROM_BYTES
] =
191 #define PUTCHAR_LIGHT_not
193 0xFB, 0xD7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x32
194 , 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
195 , 0x08, 0x50, 0x80, 0x16, 0xFE, 0xE8, 0x00, 0xFC
196 , 0x32, 0x80, 0x2D, 0xFE, 0xFC, 0x31, 0x80, 0x43
197 , 0xFE, 0xFC, 0x33, 0x80, 0x2D, 0xFE, 0xFC, 0x31
198 , 0x80, 0x43, 0xFE, 0x90, 0x16, 0x01, 0x20, 0xFC
199 , 0x32, 0xE3, 0xB0, 0x37, 0x09, 0xF3, 0xFF, 0x20
200 , 0xFC, 0x33, 0xE3, 0xB0, 0x40, 0x0A, 0xF3, 0xFF
201 , 0x08, 0xF3, 0xFF, 0x01, 0x40, 0x21, 0xD1, 0x00
202 , 0x02, 0xC0, 0x4C, 0x71, 0x01, 0x20, 0x50, 0x90
203 , 0x51, 0x00, 0xF1, 0x40, 0xD8, 0xB0, 0x59, 0x90
207 0xFB, 0xD7, 0x00, 0x00, 0x80, 0x08, 0xFE, 0xE8
208 , 0x00, 0xF6, 0xF5, 0x90, 0x08
211 uint8
rom_get (rom_addr a
) {
212 return rom_mem
[a
-CODE_START
];
216 #define RAM_GET_FIELD0_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,0))
217 #define RAM_SET_FIELD0_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,0), val)
218 #define ROM_GET_FIELD0_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,0))
220 #define RAM_GET_GC_TAGS_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x60)
221 #define RAM_GET_GC_TAG0_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x20)
222 #define RAM_GET_GC_TAG1_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x40)
223 #define RAM_SET_GC_TAGS_MACRO(o,tags) \
224 (RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0x9f) | (tags)))
225 #define RAM_SET_GC_TAG0_MACRO(o,tag) \
226 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xdf) | (tag))
227 #define RAM_SET_GC_TAG1_MACRO(o,tag) \
228 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xbf) | (tag))
230 #define RAM_GET_FIELD1_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,1))
231 #define RAM_GET_FIELD2_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,2))
232 #define RAM_GET_FIELD3_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,3))
233 #define RAM_SET_FIELD1_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,1), val)
234 #define RAM_SET_FIELD2_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,2), val)
235 #define RAM_SET_FIELD3_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,3), val)
236 #define ROM_GET_FIELD1_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,1))
237 #define ROM_GET_FIELD2_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,2))
238 #define ROM_GET_FIELD3_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,3))
240 word
ram_get_gc_tags (obj o
) { return RAM_GET_GC_TAGS_MACRO(o
); }
241 word
ram_get_gc_tag0 (obj o
) { return RAM_GET_GC_TAG0_MACRO(o
); }
242 word
ram_get_gc_tag1 (obj o
) { return RAM_GET_GC_TAG1_MACRO(o
); }
243 void ram_set_gc_tags (obj o
, word tags
) { RAM_SET_GC_TAGS_MACRO(o
, tags
); }
244 void ram_set_gc_tag0 (obj o
, word tag
) { RAM_SET_GC_TAG0_MACRO(o
,tag
); }
245 void ram_set_gc_tag1 (obj o
, word tag
) { RAM_SET_GC_TAG1_MACRO(o
,tag
); }
246 word
ram_get_field0 (obj o
) { return RAM_GET_FIELD0_MACRO(o
); }
247 word
ram_get_field1 (obj o
) { return RAM_GET_FIELD1_MACRO(o
); }
248 word
ram_get_field2 (obj o
) { return RAM_GET_FIELD2_MACRO(o
); }
249 word
ram_get_field3 (obj o
) { return RAM_GET_FIELD3_MACRO(o
); }
250 void ram_set_field0 (obj o
, word val
) { RAM_SET_FIELD0_MACRO(o
,val
); }
251 void ram_set_field1 (obj o
, word val
) { RAM_SET_FIELD1_MACRO(o
,val
); }
252 void ram_set_field2 (obj o
, word val
) { RAM_SET_FIELD2_MACRO(o
,val
); }
253 void ram_set_field3 (obj o
, word val
) { RAM_SET_FIELD3_MACRO(o
,val
); }
254 word
rom_get_field0 (obj o
) { return ROM_GET_FIELD0_MACRO(o
); }
255 word
rom_get_field1 (obj o
) { return ROM_GET_FIELD1_MACRO(o
); }
256 word
rom_get_field2 (obj o
) { return ROM_GET_FIELD2_MACRO(o
); }
257 word
rom_get_field3 (obj o
) { return ROM_GET_FIELD3_MACRO(o
); }
259 obj
ram_get_car (obj o
);
260 obj
rom_get_car (obj o
);
261 obj
ram_get_cdr (obj o
);
262 obj
rom_get_cdr (obj o
);
263 void ram_set_car (obj o
, obj val
);
264 void ram_set_cdr (obj o
, obj val
);
266 obj
ram_get_entry (obj o
);
267 obj
rom_get_entry (obj o
);
269 obj
get_global (uint8 i
);
270 void set_global (uint8 i
, obj o
);
273 /*---------------------------------------------------------------------------*/
281 fixnum n MIN_FIXNUM -> 3 ... MAX_FIXNUM -> 3 + (MAX_FIXNUM-MIN_FIXNUM)
282 rom object 4 + (MAX_FIXNUM-MIN_FIXNUM) ... MIN_RAM_ENCODING-1
283 ram object MIN_RAM_ENCODING ... MAX_RAM_ENCODING
284 u8vector MIN_VEC_ENCODING ... 8191
286 layout of memory allocated objects:
288 Gs represent mark bits used by the gc
290 ifdef INFINITE_PRECISION_BIGNUMS
291 bignum n 0GG***** **next** hhhhhhhh llllllll (16 bit digit)
292 TODO what to do with the gc tags for the bignums ? will this work ?
294 ifndef INFINITE_PRECISION_BIGNUMS
295 bignum n 00000000 uuuuuuuu hhhhhhhh llllllll (24 bit signed integer)
296 TODO doesn't work properly for the moment. only 16 bits are usable now
298 pair 1GGaaaaa aaaaaaaa 000ddddd dddddddd
301 gives an address space of 2^13 * 4 = 32k divided between simple objects,
304 symbol 1GG00000 00000000 00100000 00000000
306 string 1GG***** *chars** 01000000 00000000
308 u8vector 1GGxxxxx xxxxxxxx 011yyyyy yyyyyyyy
309 x is length of the vector, in bytes (stored raw, not encoded as an object)
310 y is pointer to the elements themselves (stored in vector space)
312 closure 01Gaaaaa aaaaaaaa aaaxxxxx xxxxxxxx
313 0x5ff<a<0x4000 is entry
314 x is pointer to environment
315 the reason why the environment is on the cdr (and the entry is split on 3
316 bytes) is that, when looking for a variable, a closure is considered to be a
317 pair. The compiler adds an extra offset to any variable in the closure's
318 environment, so the car of the closure (which doesn't really exist) is never
319 checked, but the cdr is followed to find the other bindings
321 continuation 1GGxxxxx xxxxxxxx 100yyyyy yyyyyyyy
322 x is parent continuation
323 y is pointer to the second half, which is a closure (contains env and entry)
325 An environment is a list of objects built out of pairs. On entry to
326 a procedure the environment is the list of parameters to which is
327 added the environment of the closure being called.
329 The first byte at the entry point of a procedure gives the arity of
332 n = 0 to 127 -> procedure has n parameters (no rest parameter)
333 n = -128 to -1 -> procedure has -n parameters, the last is
339 #define encode_bool(x) (x)
343 // fixnum definitions in picobit-vm.h , address space layout section
345 #define ENCODE_FIXNUM(n) ((n) + (MIN_FIXNUM_ENCODING - MIN_FIXNUM))
346 #define DECODE_FIXNUM(o) ((o) - (MIN_FIXNUM_ENCODING - MIN_FIXNUM))
348 #define IN_VEC(o) ((o) >= MIN_VEC_ENCODING)
349 #define IN_RAM(o) (!IN_VEC(o) && ((o) >= MIN_RAM_ENCODING))
350 #define IN_ROM(o) (!IN_VEC(o) && !IN_RAM(o) && ((o) >= MIN_ROM_ENCODING))
352 // bignum first byte : 00Gxxxxx
353 #define BIGNUM_FIELD0 0
354 #define RAM_BIGNUM(o) ((ram_get_field0 (o) & 0xc0) == BIGNUM_FIELD0)
355 #define ROM_BIGNUM(o) ((rom_get_field0 (o) & 0xc0) == BIGNUM_FIELD0)
357 // composite first byte : 1GGxxxxx
358 #define COMPOSITE_FIELD0 0x80
359 #define RAM_COMPOSITE(o) ((ram_get_field0 (o) & 0x80) == COMPOSITE_FIELD0)
360 #define ROM_COMPOSITE(o) ((rom_get_field0 (o) & 0x80) == COMPOSITE_FIELD0)
362 // pair third byte : 000xxxxx
363 #define PAIR_FIELD2 0
364 #define RAM_PAIR(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == PAIR_FIELD2))
365 #define ROM_PAIR(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == PAIR_FIELD2))
367 // symbol third byte : 001xxxxx
368 #define SYMBOL_FIELD2 0x20
369 #define RAM_SYMBOL(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == SYMBOL_FIELD2))
370 #define ROM_SYMBOL(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == SYMBOL_FIELD2))
372 // string third byte : 010xxxxx
373 #define STRING_FIELD2 0x40
374 #define RAM_STRING(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == STRING_FIELD2))
375 #define ROM_STRING(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == STRING_FIELD2))
377 // vector third byte : 011xxxxx
378 #define VECTOR_FIELD2 0x60
379 #define RAM_VECTOR(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == VECTOR_FIELD2))
380 #define ROM_VECTOR(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == VECTOR_FIELD2))
382 // continuation third byte : 100xxxxx
383 #define CONTINUATION_FIELD2 0x80
384 #define RAM_CONTINUATION(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == CONTINUATION_FIELD2))
385 #define ROM_CONTINUATION(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == CONTINUATION_FIELD2))
387 // closure first byte : 01Gxxxxx
388 #define CLOSURE_FIELD0 0x40
389 #define RAM_CLOSURE(o) ((ram_get_field0 (o) & 0xc0) == CLOSURE_FIELD0)
390 #define ROM_CLOSURE(o) ((rom_get_field0 (o) & 0xc0) == CLOSURE_FIELD0)
392 /*---------------------------------------------------------------------------*/
394 // bignum definitions
396 #ifdef INFINITE_PRECISION_BIGNUMS
398 #define digit_width 16
401 typedef uint16 digit
; // TODO why these ? adds to the confusion
402 typedef uint32 two_digit
;
404 #define obj_eq(x,y) ((x) == (y))
405 #define integer_hi_set(x,y) ram_set_car (x, y)
407 #define ZERO ENCODE_FIXNUM(0)
408 #define NEG1 (ZERO-1)
409 #define POS1 (ZERO+1)
411 integer
make_integer (digit lo
, integer hi
);
412 integer
integer_hi (integer x
);
413 digit
integer_lo (integer x
);
415 integer
norm (obj prefix
, integer n
);
416 uint8
negp (integer x
);
417 uint8
cmp (integer x
, integer y
);
418 uint16
integer_length (integer x
);
419 integer
shr (integer x
);
420 integer
negative_carry (integer carry
);
421 integer
shl (integer x
);
422 integer
shift_left (integer x
, uint16 n
);
423 integer
add (integer x
, integer y
);
424 integer
invert (integer x
);
425 integer
sub (integer x
, integer y
);
426 integer
neg (integer x
);
427 integer
scale (digit n
, integer x
);
428 integer
mulnonneg (integer x
, integer y
);
429 integer
divnonneg (integer x
, integer y
);
431 uint16
decode_int (obj o
);
432 obj
encode_int (uint16 n
);
436 /*---------------------------------------------------------------------------*/
440 // TODO explain what each tag means, with 1-2 mark bits
441 #define GC_TAG_0_LEFT (1<<5)
442 #define GC_TAG_1_LEFT (2<<5)
443 #define GC_TAG_UNMARKED (0<<5)
445 /* Number of object fields of objects in ram */
446 #define HAS_2_OBJECT_FIELDS(visit) (RAM_PAIR(visit) || RAM_CONTINUATION(visit))
447 #ifdef INFINITE_PRECISION_BIGNUMS
448 #define HAS_1_OBJECT_FIELD(visit) (RAM_COMPOSITE(visit) \
449 || RAM_CLOSURE(visit) || RAM_BIGNUM(visit))
451 #define HAS_1_OBJECT_FIELD(visit) (RAM_COMPOSITE(visit) || RAM_CLOSURE(visit))
453 // all composites except pairs and continuations have 1 object field
455 #define NIL OBJ_FALSE
457 obj free_list
; /* list of unused cells */
458 obj free_list_vec
; /* list of unused cells in vector space */
460 obj arg1
; /* root set */
468 uint8 na
; /* interpreter variables */
479 /*---------------------------------------------------------------------------*/
487 void prim_numberp ();
496 // TODO we have extra primitives, pring back geq, leq, and put them in a sensible place in the primitives
501 obj
cons (obj car
, obj cdr
);
505 void prim_set_car ();
506 void prim_set_cdr ();
509 void prim_u8vectorp ();
510 void prim_make_u8vector ();
511 void prim_u8vector_ref ();
512 void prim_u8vector_set ();
513 void prim_u8vector_length ();
514 void prim_u8vector_copy ();
518 void prim_symbolp ();
519 void prim_stringp ();
520 void prim_string2list ();
521 void prim_list2string ();
522 void prim_booleanp ();
529 uint32
read_clock ();
533 void prim_led2_color ();
534 void prim_getchar_wait ();
535 void prim_putchar ();
540 void prim_network_init ();
541 void prim_network_cleanup ();
542 void prim_receive_packet_to_u8vector ();
543 void prim_send_packet_from_u8vector ();
545 /*---------------------------------------------------------------------------*/
549 #define FETCH_NEXT_BYTECODE() bytecode = rom_get (pc++)
551 #define BEGIN_DISPATCH() \
553 IF_TRACE(show_state (pc)); \
554 FETCH_NEXT_BYTECODE(); \
555 bytecode_hi4 = bytecode & 0xf0; \
556 bytecode_lo4 = bytecode & 0x0f; \
557 switch (bytecode_hi4 >> 4) {
559 #define END_DISPATCH() }
561 #define CASE(opcode) case (opcode):;
563 #define DISPATCH(); goto dispatch;
565 #define PUSH_CONSTANT1 0x0
566 #define PUSH_CONSTANT2 0x1
567 #define PUSH_STACK1 0x2
568 #define PUSH_STACK2 0x3
569 #define PUSH_GLOBAL 0x4
570 #define SET_GLOBAL 0x5
573 #define LABEL_INSTR 0x8
574 #define PUSH_CONSTANT_LONG 0x9
584 #define PUSH_ARG1() push_arg1 ()
589 void pop_procedure ();
590 void handle_arity_and_rest_param ();
595 /*---------------------------------------------------------------------------*/
597 // debugging functions
600 void show_type (obj o
);
601 void show_state (rom_addr pc
);
604 /*---------------------------------------------------------------------------*/