Added ior and xor tests to the repository.
[picobit/chj.git] / picobit-vm.h
blob4d5a0e749295a6dfaedfec81308faf9240084d22
1 /* file: "picobit-vm.h" */
3 /*
4 * Copyright 2004-2009 by Marc Feeley and Vincent St-Amour, All Rights Reserved.
5 */
7 #ifndef PICOBIT_VM_H
8 #define PICOBIT_VM_H
10 #define DEBUG_not
11 #define DEBUG_GC_not
12 #define INFINITE_PRECISION_BIGNUMS
14 /*---------------------------------------------------------------------------*/
16 // types
18 typedef char int8;
19 typedef short int16;
20 typedef long int32;
21 typedef unsigned char uint8;
22 typedef unsigned short uint16;
23 typedef unsigned long uint32;
25 typedef uint8 word;
27 typedef uint16 ram_addr;
28 typedef uint16 rom_addr;
30 // pointers are 13 bits
31 typedef uint16 obj;
33 /*---------------------------------------------------------------------------*/
35 // environment
37 #ifdef PICOBOARD2
38 #define ROBOT
39 #endif
41 #ifdef HI_TECH_C
42 #define ROBOT
43 #endif
45 #ifndef ROBOT
46 #define WORKSTATION
47 #endif
50 #ifdef HI_TECH_C
52 #include <pic18.h>
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;
65 #endif
68 #ifdef WORKSTATION
70 #include <stdio.h>
71 #include <stdlib.h>
72 #include <pcap.h>
74 // for libpcap
75 #define MAX_PACKET_SIZE BUFSIZ
76 #define PROMISC 1
77 #define TO_MSEC 1
78 char errbuf[PCAP_ERRBUF_SIZE];
79 pcap_t *handle;
80 #define INTERFACE "eth0"
81 char buf [MAX_PACKET_SIZE]; // buffer for writing
84 #ifdef _WIN32
86 #include <sys/types.h>
87 #include <sys/timeb.h>
88 #include <conio.h>
90 #else
92 #include <sys/time.h>
94 #endif
96 #endif
98 /*---------------------------------------------------------------------------*/
100 // miscellaneous definitions
101 // TODO put at the end ?
103 // TODO these 2 are only used in negp, use them elsewhere ?
104 #define true 1
105 #define false 0
107 #define CODE_START 0x5000
109 /*---------------------------------------------------------------------------*/
111 // debugging
113 #ifdef DEBUG
114 #define IF_TRACE(x) x
115 #define IF_GC_TRACE(x) x
116 #else
117 #define IF_TRACE(x)
118 #define IF_GC_TRACE(x)
119 #endif
121 /*---------------------------------------------------------------------------*/
123 // error handling
125 #ifdef PICOBOARD2
126 #define ERROR(prim, msg) halt_with_error()
127 #define TYPE_ERROR(prim, type) halt_with_error()
128 #endif
130 #ifdef WORKSTATION
131 #define ERROR(prim, msg) error (prim, msg)
132 #define TYPE_ERROR(prim, type) type_error (prim, type)
133 void error (char *prim, char *msg);
134 void type_error (char *prim, char *type);
135 #endif
137 /*---------------------------------------------------------------------------*/
139 // address space layout
140 // TODO document each zone, also explain that since vector space is in ram, it uses the ram primitives
142 #define MAX_VEC_ENCODING 8191
143 #define MIN_VEC_ENCODING 4096
144 #define VEC_BYTES ((MAX_VEC_ENCODING - MIN_VEC_ENCODING + 1)*4)
145 // if the pic has less than 8k of memory, start vector space lower
146 // TODO the pic actually has 2k, so change these
147 // 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
149 #define MAX_RAM_ENCODING 4095
150 #define MIN_RAM_ENCODING 512
151 #define RAM_BYTES ((MAX_RAM_ENCODING - MIN_RAM_ENCODING + 1)*4)
152 // TODO watch out if we address more than what the PIC actually has
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) (((ram_addr)((uint16)(o) - MIN_RAM_ENCODING) << 2) + (f))
160 #define OBJ_TO_ROM_ADDR(o,f) (((rom_addr)((uint16)(o) - MIN_ROM_ENCODING) << 2) + (CODE_START + 4 + (f)))
163 #ifdef PICOBOARD2
164 #define ram_get(a) *(uint8*)(a+0x200)
165 #define ram_set(a,x) *(uint8*)(a+0x200) = (x)
166 #endif
169 #ifdef WORKSTATION
170 uint8 ram_mem[RAM_BYTES + VEC_BYTES];
171 #define ram_get(a) ram_mem[a]
172 #define ram_set(a,x) ram_mem[a] = (x)
173 #endif
175 #ifdef PICOBOARD2
176 uint8 rom_get (rom_addr a){
177 return *(rom uint8*)a;
179 #endif
182 #ifdef WORKSTATION
183 #define ROM_BYTES 8192
184 // TODO the new pics have 32k, change this ? minus the vm size, firmware ?
185 uint8 rom_mem[ROM_BYTES];
186 uint8 rom_get (rom_addr a);
187 #endif
189 /*---------------------------------------------------------------------------*/
191 // memory access
193 #define RAM_GET_FIELD0_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,0))
194 #define RAM_SET_FIELD0_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,0), val)
195 #define ROM_GET_FIELD0_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,0))
197 #define RAM_GET_GC_TAGS_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x60)
198 #define RAM_GET_GC_TAG0_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x20)
199 #define RAM_GET_GC_TAG1_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x40)
200 #define RAM_SET_GC_TAGS_MACRO(o,tags) \
201 (RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0x9f) | (tags)))
202 #define RAM_SET_GC_TAG0_MACRO(o,tag) \
203 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xdf) | (tag))
204 #define RAM_SET_GC_TAG1_MACRO(o,tag) \
205 RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xbf) | (tag))
207 #define RAM_GET_FIELD1_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,1))
208 #define RAM_GET_FIELD2_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,2))
209 #define RAM_GET_FIELD3_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,3))
210 #define RAM_SET_FIELD1_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,1), val)
211 #define RAM_SET_FIELD2_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,2), val)
212 #define RAM_SET_FIELD3_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,3), val)
213 #define ROM_GET_FIELD1_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,1))
214 #define ROM_GET_FIELD2_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,2))
215 #define ROM_GET_FIELD3_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,3))
217 word ram_get_gc_tags (obj o);
218 word ram_get_gc_tag0 (obj o);
219 word ram_get_gc_tag1 (obj o);
220 void ram_set_gc_tags (obj o, word tags);
221 void ram_set_gc_tag0 (obj o, word tag);
222 void ram_set_gc_tag1 (obj o, word tag);
223 word ram_get_field0 (obj o);
224 word ram_get_field1 (obj o);
225 word ram_get_field2 (obj o);
226 word ram_get_field3 (obj o);
227 word ram_get_fieldn (obj o, word n);
228 void ram_set_field0 (obj o, word val);
229 void ram_set_field1 (obj o, word val);
230 void ram_set_field2 (obj o, word val);
231 void ram_set_field3 (obj o, word val);
232 void ram_set_fieldn (obj o, uint8 n, word val);
233 word rom_get_field0 (obj o);
234 word rom_get_field1 (obj o);
235 word rom_get_field2 (obj o);
236 word rom_get_field3 (obj o);
238 obj ram_get_car (obj o);
239 obj rom_get_car (obj o);
240 obj ram_get_cdr (obj o);
241 obj rom_get_cdr (obj o);
242 void ram_set_car (obj o, obj val);
243 void ram_set_cdr (obj o, obj val);
245 obj ram_get_entry (obj o);
246 obj rom_get_entry (obj o);
248 obj get_global (uint8 i);
249 void set_global (uint8 i, obj o);
251 /*---------------------------------------------------------------------------*/
254 OBJECT ENCODING:
256 #f 0
257 #t 1
258 () 2
259 fixnum n MIN_FIXNUM -> 3 ... MAX_FIXNUM -> 3 + (MAX_FIXNUM-MIN_FIXNUM)
260 rom object 4 + (MAX_FIXNUM-MIN_FIXNUM) ... MIN_RAM_ENCODING-1
261 ram object MIN_RAM_ENCODING ... MAX_RAM_ENCODING
262 u8vector MIN_VEC_ENCODING ... 8191
264 layout of memory allocated objects:
266 Gs represent mark bits used by the gc
268 ifdef INFINITE_PRECISION_BIGNUMS
269 bignum n 0GG***** **next** hhhhhhhh llllllll (16 bit digit)
270 TODO what to do with the gc tags for the bignums ? will this work ?
272 ifndef INFINITE_PRECISION_BIGNUMS
273 bignum n 00000000 uuuuuuuu hhhhhhhh llllllll (24 bit signed integer)
275 pair 1GGaaaaa aaaaaaaa 000ddddd dddddddd
276 a is car
277 d is cdr
278 gives an address space of 2^13 * 4 = 32k divided between simple objects,
279 rom, ram and vectors
281 symbol 1GG00000 00000000 00100000 00000000
283 string 1GG***** *chars** 01000000 00000000
285 u8vector 1GGxxxxx xxxxxxxx 011yyyyy yyyyyyyy
286 x is length of the vector, in bytes (stored raw, not encoded as an object)
287 y is pointer to the elements themselves (stored in vector space)
289 closure 01Gaaaaa aaaaaaaa aaaxxxxx xxxxxxxx
290 0x5ff<a<0x4000 is entry
291 x is pointer to environment
292 the reason why the environment is on the cdr (and the entry is split on 3
293 bytes) is that, when looking for a variable, a closure is considered to be a
294 pair. The compiler adds an extra offset to any variable in the closure's
295 environment, so the car of the closure (which doesn't really exist) is never
296 checked, but the cdr is followed to find the other bindings
298 continuation 1GGxxxxx xxxxxxxx 100yyyyy yyyyyyyy
299 x is parent continuation
300 y is pointer to the second half, which is a closure (contains env and entry)
302 An environment is a list of objects built out of pairs. On entry to
303 a procedure the environment is the list of parameters to which is
304 added the environment of the closure being called.
306 The first byte at the entry point of a procedure gives the arity of
307 the procedure:
309 n = 0 to 127 -> procedure has n parameters (no rest parameter)
310 n = -128 to -1 -> procedure has -n parameters, the last is
311 a rest parameter
314 #define OBJ_FALSE 0
315 #define OBJ_TRUE 1
316 #define encode_bool(x) ((obj)(x))
318 #define OBJ_NULL 2
320 // fixnum definitions in picobit-vm.h , address space layout section
322 #define ENCODE_FIXNUM(n) ((obj)(n) + (MIN_FIXNUM_ENCODING - MIN_FIXNUM))
323 #define DECODE_FIXNUM(o) ((int32)(o) - (MIN_FIXNUM_ENCODING - MIN_FIXNUM))
325 #define IN_VEC(o) ((o) >= MIN_VEC_ENCODING)
326 #define IN_RAM(o) (!IN_VEC(o) && ((o) >= MIN_RAM_ENCODING))
327 #define IN_ROM(o) (!IN_VEC(o) && !IN_RAM(o) && ((o) >= MIN_ROM_ENCODING))
329 // bignum first byte : 00Gxxxxx
330 #define BIGNUM_FIELD0 0
331 #define RAM_BIGNUM(o) ((ram_get_field0 (o) & 0xc0) == BIGNUM_FIELD0)
332 #define ROM_BIGNUM(o) ((rom_get_field0 (o) & 0xc0) == BIGNUM_FIELD0)
334 // composite first byte : 1GGxxxxx
335 #define COMPOSITE_FIELD0 0x80
336 #define RAM_COMPOSITE(o) ((ram_get_field0 (o) & 0x80) == COMPOSITE_FIELD0)
337 #define ROM_COMPOSITE(o) ((rom_get_field0 (o) & 0x80) == COMPOSITE_FIELD0)
339 // pair third byte : 000xxxxx
340 #define PAIR_FIELD2 0
341 #define RAM_PAIR(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == PAIR_FIELD2))
342 #define ROM_PAIR(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == PAIR_FIELD2))
344 // symbol third byte : 001xxxxx
345 #define SYMBOL_FIELD2 0x20
346 #define RAM_SYMBOL(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == SYMBOL_FIELD2))
347 #define ROM_SYMBOL(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == SYMBOL_FIELD2))
349 // string third byte : 010xxxxx
350 #define STRING_FIELD2 0x40
351 #define RAM_STRING(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == STRING_FIELD2))
352 #define ROM_STRING(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == STRING_FIELD2))
354 // vector third byte : 011xxxxx
355 #define VECTOR_FIELD2 0x60
356 #define RAM_VECTOR(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == VECTOR_FIELD2))
357 #define ROM_VECTOR(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == VECTOR_FIELD2))
359 // continuation third byte : 100xxxxx
360 #define CONTINUATION_FIELD2 0x80
361 #define RAM_CONTINUATION(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == CONTINUATION_FIELD2))
362 #define ROM_CONTINUATION(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == CONTINUATION_FIELD2))
364 // closure first byte : 01Gxxxxx
365 #define CLOSURE_FIELD0 0x40
366 #define RAM_CLOSURE(o) ((ram_get_field0 (o) & 0xc0) == CLOSURE_FIELD0)
367 #define ROM_CLOSURE(o) ((rom_get_field0 (o) & 0xc0) == CLOSURE_FIELD0)
369 /*---------------------------------------------------------------------------*/
371 // bignum definitions
373 #ifdef INFINITE_PRECISION_BIGNUMS
375 #define digit_width 16
377 typedef obj integer;
378 typedef uint16 digit; // TODO why these ? adds to the confusion
379 typedef uint32 two_digit;
381 #define obj_eq(x,y) ((x) == (y))
382 #define integer_hi_set(x,y) ram_set_car (x, y)
384 #define ZERO ENCODE_FIXNUM(0)
385 #define NEG1 (ZERO-1)
386 #define POS1 (ZERO+1)
388 integer make_integer (digit lo, integer hi);
389 integer integer_hi (integer x);
390 digit integer_lo (integer x);
392 integer norm (obj prefix, integer n);
393 uint8 negp (integer x);
394 int8 cmp (integer x, integer y);
395 uint16 integer_length (integer x);
396 integer shr (integer x);
397 integer negative_carry (integer carry);
398 integer shl (integer x);
399 integer shift_left (integer x, uint16 n);
400 integer add (integer x, integer y);
401 integer invert (integer x);
402 integer sub (integer x, integer y);
403 integer neg (integer x);
404 integer scale (digit n, integer x);
405 integer mulnonneg (integer x, integer y);
406 integer divnonneg (integer x, integer y);
408 int32 decode_int (obj o);
409 obj encode_int (int32 n);
411 #endif
413 /*---------------------------------------------------------------------------*/
415 // garbage collector
417 // TODO explain what each tag means, with 1-2 mark bits
418 #define GC_TAG_0_LEFT (1<<5)
419 #define GC_TAG_1_LEFT (2<<5)
420 #define GC_TAG_UNMARKED (0<<5)
422 /* Number of object fields of objects in ram */
423 #define HAS_2_OBJECT_FIELDS(visit) (RAM_PAIR(visit) || RAM_CONTINUATION(visit))
424 #ifdef INFINITE_PRECISION_BIGNUMS
425 #define HAS_1_OBJECT_FIELD(visit) (RAM_COMPOSITE(visit) \
426 || RAM_CLOSURE(visit) || RAM_BIGNUM(visit))
427 #else
428 #define HAS_1_OBJECT_FIELD(visit) (RAM_COMPOSITE(visit) || RAM_CLOSURE(visit))
429 #endif
430 // all composites except pairs and continuations have 1 object field
432 #define NIL OBJ_FALSE
434 obj free_list; /* list of unused cells */
435 obj free_list_vec; /* list of unused cells in vector space */
437 obj arg1; /* root set */
438 obj arg2;
439 obj arg3;
440 obj arg4;
441 obj arg5;
442 obj cont;
443 obj env;
445 uint8 na; /* interpreter variables */
446 rom_addr pc;
447 uint8 glovars;
448 rom_addr entry;
449 uint8 bytecode;
450 uint8 bytecode_hi4;
451 uint8 bytecode_lo4;
452 int32 a1;
453 int32 a2;
454 int32 a3;
456 /*---------------------------------------------------------------------------*/
458 // primitives
460 #ifdef WORKSTATION
461 char *prim_name[64];
462 #endif
464 void prim_numberp (void);
465 void prim_add (void);
466 void prim_mul (void);
467 void prim_div (void);
468 void prim_rem (void);
469 void prim_neg (void);
470 void prim_eq (void);
471 void prim_lt (void);
472 void prim_gt (void);
473 // TODO we have extra primitives, pring back geq, leq, and put them in a sensible place in the primitives
474 void prim_ior (void);
475 void prim_xor (void);
477 void prim_pairp (void);
478 obj cons (obj car, obj cdr);
479 void prim_cons (void);
480 void prim_car (void);
481 void prim_cdr (void);
482 void prim_set_car (void);
483 void prim_set_cdr (void);
484 void prim_nullp (void);
486 void prim_u8vectorp (void);
487 void prim_make_u8vector (void);
488 void prim_u8vector_ref (void);
489 void prim_u8vector_set (void);
490 void prim_u8vector_length (void);
491 void prim_u8vector_copy (void);
493 void prim_eqp (void);
494 void prim_not (void);
495 void prim_symbolp (void);
496 void prim_stringp (void);
497 void prim_string2list (void);
498 void prim_list2string (void);
499 void prim_booleanp (void);
501 #ifdef WORKSTATION
502 void show (obj o);
503 void print (obj o);
504 #endif
505 void prim_print (void);
506 int32 read_clock (void);
507 void prim_clock (void);
508 void prim_motor (void);
509 void prim_led (void);
510 void prim_led2_color (void);
511 void prim_getchar_wait (void);
512 void prim_putchar (void);
513 void prim_beep (void);
514 void prim_adc (void);
515 void prim_sernum (void);
517 void prim_network_init (void);
518 void prim_network_cleanup (void);
519 void prim_receive_packet_to_u8vector (void);
520 void prim_send_packet_from_u8vector (void);
522 /*---------------------------------------------------------------------------*/
524 // dispatch
526 #define FETCH_NEXT_BYTECODE() bytecode = rom_get (pc++)
528 #define BEGIN_DISPATCH() \
529 dispatch: \
530 IF_TRACE(show_state (pc)); \
531 FETCH_NEXT_BYTECODE(); \
532 bytecode_hi4 = bytecode & 0xf0; \
533 bytecode_lo4 = bytecode & 0x0f; \
534 switch (bytecode_hi4 >> 4) {
536 #define END_DISPATCH() }
538 #define CASE(opcode) case (opcode>>4):;
540 #define DISPATCH(); goto dispatch;
542 #define PUSH_CONSTANT1 0x00
543 #define PUSH_CONSTANT2 0x10
544 #define PUSH_STACK1 0x20
545 #define PUSH_STACK2 0x30
546 #define PUSH_GLOBAL 0x40
547 #define SET_GLOBAL 0x50
548 #define CALL 0x60
549 #define JUMP 0x70
550 #define LABEL_INSTR 0x80
551 #define PUSH_CONSTANT_LONG 0x90
553 #define FREE1 0xa0
554 #define FREE2 0xb0
556 #define PRIM1 0xc0
557 #define PRIM2 0xd0
558 #define PRIM3 0xe0
559 #define PRIM4 0xf0
561 #define PUSH_ARG1() push_arg1 ()
562 #define POP() pop()
564 void push_arg1 (void);
565 obj pop (void);
566 void pop_procedure (void);
567 void handle_arity_and_rest_param (void);
568 void build_env (void);
569 void save_cont (void);
570 void interpreter (void);
572 /*---------------------------------------------------------------------------*/
574 // debugging functions
576 void show_type (obj o);
577 void show_state (rom_addr pc);
579 /*---------------------------------------------------------------------------*/
581 #endif