From 4c077727be8edf7a6d107b5e7bb8a6e47833c69d Mon Sep 17 00:00:00 2001 From: Vincent St-Amour Date: Sat, 7 Feb 2009 19:12:29 -0500 Subject: [PATCH] Cleanup. Split the code into various files. --- debug.c | 43 +++ gc.c | 317 ++++++++++++++++++++ picobit-vm.c | 940 +++++------------------------------------------------------ picobit-vm.h | 429 +++++++++++++++++++++++++++ picobit.scm | 5 +- 5 files changed, 865 insertions(+), 869 deletions(-) create mode 100644 debug.c create mode 100644 gc.c create mode 100644 picobit-vm.h diff --git a/debug.c b/debug.c new file mode 100644 index 0000000..286bddf --- /dev/null +++ b/debug.c @@ -0,0 +1,43 @@ +/* file: "debug.c" */ + +/* + * Copyright 2004-2009 by Marc Feeley and Vincent St-Amour, All Rights Reserved. + */ + +// debugging functions + +#include "picobit-vm.h" +// needs some memory access functions defined above +#include "objects.h" + +#ifdef WORKSTATION +void show_type (obj o) // for debugging purposes + { + printf("%d : ", o); + if (o == OBJ_FALSE) printf("#f"); + else if (o == OBJ_TRUE) printf("#t"); + else if (o == OBJ_NULL) printf("()"); + else if (o < MIN_ROM_ENCODING) printf("fixnum"); + else if (IN_RAM (o)) + { + if (RAM_BIGNUM(o)) printf("ram bignum"); + else if (RAM_PAIR(o)) printf("ram pair"); + else if (RAM_SYMBOL(o)) printf("ram symbol"); + else if (RAM_STRING(o)) printf("ram string"); + else if (RAM_VECTOR(o)) printf("ram vector"); + else if (RAM_CONTINUATION(o)) printf("ram continuation"); + else if (RAM_CLOSURE(o)) printf("ram closure"); + } + else // ROM + { + if (ROM_BIGNUM(o)) printf("rom bignum"); + else if (ROM_PAIR(o)) printf("rom pair"); + else if (ROM_SYMBOL(o)) printf("rom symbol"); + else if (ROM_STRING(o)) printf("rom string"); + else if (ROM_VECTOR(o)) printf("rom vector"); + else if (ROM_CONTINUATION(o)) printf("rom continuation"); + else if (RAM_CLOSURE(o)) printf("rom closure"); + } + printf("\n"); + } +#endif diff --git a/gc.c b/gc.c new file mode 100644 index 0000000..5c1a95d --- /dev/null +++ b/gc.c @@ -0,0 +1,317 @@ +/* file: "gc.c" */ + +/* + * Copyright 2004-2009 by Marc Feeley and Vincent St-Amour, All Rights Reserved. + */ + +#include "picobit-vm.h" + +void init_ram_heap (void) { + uint8 i; + obj o = MAX_RAM_ENCODING; + + free_list = 0; + + while (o > (MIN_RAM_ENCODING + (glovars + 1) / 2)) { + // we don't want to add globals to the free list, and globals occupy the + // beginning of memory at the rate of 2 globals per word (car and cdr) + ram_set_gc_tags (o, GC_TAG_UNMARKED); + ram_set_car (o, free_list); + free_list = o; + o--; + } + + free_list_vec = MIN_VEC_ENCODING; + ram_set_car (free_list_vec, 0); + // each node of the free list must know the free length that follows it + // this free length is stored in words, not in bytes + // if we did count in bytes, the number might need more than 13 bits + ram_set_cdr (free_list_vec, VEC_BYTES / 4); + + for (i=0; i>5)); + + if ((HAS_1_OBJECT_FIELD (visit) && ram_get_gc_tag0 (visit)) + || (HAS_2_OBJECT_FIELDS (visit) + && (ram_get_gc_tags (visit) != GC_TAG_UNMARKED))) + IF_GC_TRACE(printf ("case 1\n")); + else { + if (HAS_2_OBJECT_FIELDS(visit)) { // pairs and continuations + IF_GC_TRACE(printf ("case 2\n")); + + visit_field2: + + temp = ram_get_cdr (visit); + + if (IN_RAM(temp)) { + IF_GC_TRACE(printf ("case 3\n")); + ram_set_gc_tags (visit, GC_TAG_1_LEFT); + ram_set_cdr (visit, stack); + goto push; + } + + IF_GC_TRACE(printf ("case 4\n")); + + goto visit_field1; + } + + if (HAS_1_OBJECT_FIELD(visit)) { + IF_GC_TRACE(printf ("case 5\n")); + + visit_field1: + + // closures have the pointer in the cdr, not in the car as others + if (RAM_CLOSURE(visit)) + temp = ram_get_cdr (visit); + else + temp = ram_get_car (visit); + + if (IN_RAM(temp)) { + IF_GC_TRACE(printf ("case 6\n")); + ram_set_gc_tag0 (visit, GC_TAG_0_LEFT); + if (RAM_CLOSURE(visit)) + ram_set_cdr (visit, stack); + else + ram_set_car (visit, stack); + + goto push; + } + + IF_GC_TRACE(printf ("case 7\n")); + } + else + IF_GC_TRACE(printf ("case 8\n")); + + ram_set_gc_tag0 (visit, GC_TAG_0_LEFT); + } + + pop: + + IF_GC_TRACE(printf ("pop stack=%d visit=%d (tag=%d)\n", stack, visit, ram_get_gc_tags (visit)>>6)); + + if (stack != NIL) { + if (HAS_2_OBJECT_FIELDS(stack) && ram_get_gc_tag1 (stack)) { + IF_GC_TRACE(printf ("case 9\n")); + + temp = ram_get_cdr (stack); /* pop through cdr */ + ram_set_cdr (stack, visit); + visit = stack; + stack = temp; + + ram_set_gc_tag1(visit, GC_TAG_UNMARKED); + // we unset the "1-left" bit + + goto visit_field1; + } + + if (RAM_CLOSURE(stack)) { + // closures have one object field, but it's in the cdr + IF_GC_TRACE(printf ("case 10\n")); + + temp = ram_get_cdr (stack); /* pop through cdr */ + ram_set_cdr (stack, visit); + visit = stack; + stack = temp; + + goto pop; + } + + IF_GC_TRACE(printf ("case 11\n")); + + temp = ram_get_car (stack); /* pop through car */ + ram_set_car (stack, visit); + visit = stack; + stack = temp; + + goto pop; + } + } +} + +#ifdef DEBUG_GC +int max_live = 0; +#endif + +void sweep (void) { + /* sweep phase */ + +#ifdef DEBUG_GC + int n = 0; +#endif + + obj visit = MAX_RAM_ENCODING; + + free_list = 0; + + while (visit >= (MIN_RAM_ENCODING + ((glovars + 1) / 2))) { + // we don't want to sweep the global variables area + if ((RAM_COMPOSITE(visit) + && (ram_get_gc_tags (visit) == GC_TAG_UNMARKED)) // 2 mark bit + || !(ram_get_gc_tags (visit) & GC_TAG_0_LEFT)) { // 1 mark bit + /* unmarked? */ + if (RAM_VECTOR(visit)) { + // when we sweep a vector, we also have to sweep its contents + obj o = ram_get_cdr (visit); + uint16 i = ram_get_car (visit); // number of elements + ram_set_car (o, free_list_vec); + ram_set_cdr (o, (i + 3) / 4); // free length, in words + free_list_vec = o; + // TODO merge free spaces + } + ram_set_car (visit, free_list); + free_list = visit; + } + else { + if (RAM_COMPOSITE(visit)) + ram_set_gc_tags (visit, GC_TAG_UNMARKED); + else // only 1 mark bit to unset + ram_set_gc_tag0 (visit, GC_TAG_UNMARKED); +#ifdef DEBUG_GC + n++; +#endif + } + visit--; + } + +#ifdef DEBUG_GC + if (n > max_live) { + max_live = n; + printf ("**************** memory needed = %d\n", max_live+1); + fflush (stdout); + } +#endif +} + +void gc (void) { + uint8 i; + + IF_TRACE(printf("\nGC BEGINS\n")); + + IF_GC_TRACE(printf("arg1\n")); + mark (arg1); + IF_GC_TRACE(printf("arg2\n")); + mark (arg2); + IF_GC_TRACE(printf("arg3\n")); + mark (arg3); + IF_GC_TRACE(printf("arg4\n")); + mark (arg4); + IF_GC_TRACE(printf("arg5\n")); + mark (arg5); + IF_GC_TRACE(printf("cont\n")); + mark (cont); + IF_GC_TRACE(printf("env\n")); + mark (env); + + IF_GC_TRACE(printf("globals\n")); + for (i=0; i - -static volatile near uint8 FW_VALUE_UP @ 0x33; -static volatile near uint8 FW_VALUE_HI @ 0x33; -static volatile near uint8 FW_VALUE_LO @ 0x33; - -#define ACTIVITY_LED1_LAT LATB -#define ACTIVITY_LED1_BIT 5 -#define ACTIVITY_LED2_LAT LATB -#define ACTIVITY_LED2_BIT 4 -static volatile near bit ACTIVITY_LED1 @ ((unsigned)&ACTIVITY_LED1_LAT*8)+ACTIVITY_LED1_BIT; -static volatile near bit ACTIVITY_LED2 @ ((unsigned)&ACTIVITY_LED2_LAT*8)+ACTIVITY_LED2_BIT; - -#endif - - -#ifdef WORKSTATION - -#include -#include -#include - -// for libpcap - -#define MAX_PACKET_SIZE BUFSIZ -#define PROMISC 1 -#define TO_MSEC 1 - -char errbuf[PCAP_ERRBUF_SIZE]; -pcap_t *handle; - -#define INTERFACE "eth0" - -char buf [MAX_PACKET_SIZE]; // buffer for writing - - -#ifdef _WIN32 -#include -#include -#include -#else -#include -#endif - -#endif - - -/*---------------------------------------------------------------------------*/ - -#define WORD_BITS 8 - -#define CODE_START 0x5000 - -#ifdef DEBUG -#define IF_TRACE(x) x -#define IF_GC_TRACE(x) x -#else -#define IF_TRACE(x) -#define IF_GC_TRACE(x) -#endif - -/*---------------------------------------------------------------------------*/ - - -#ifdef PICOBOARD2 - -#define ERROR(prim, msg) halt_with_error() -#define TYPE_ERROR(prim, type) halt_with_error() - -#endif - - -#ifdef WORKSTATION - -#define ERROR(prim, msg) error (prim, msg) -#define TYPE_ERROR(prim, type) type_error (prim, type) - -void error (char *prim, char *msg) -{ +void error (char *prim, char *msg) { printf ("ERROR: %s: %s\n", prim, msg); exit (1); } -void type_error (char *prim, char *type) -{ +void type_error (char *prim, char *type) { printf ("ERROR: %s: An argument of type %s was expected\n", prim, type); exit (1); } -#endif - - -/*---------------------------------------------------------------------------*/ - -#if WORD_BITS <= 8 -typedef uint8 word; -#else -typedef uint16 word; -#endif - -typedef uint16 ram_addr; -typedef uint16 rom_addr; - -typedef uint16 obj; - -#ifdef INFINITE_PRECISION_BIGNUMS - -#define digit_width 16 - -typedef obj integer; -typedef uint16 digit; // TODO why this ? adds to the confusion -typedef uint32 two_digit; - -#endif - /*---------------------------------------------------------------------------*/ -#define MAX_VEC_ENCODING 8191 -#define MIN_VEC_ENCODING 4096 -#define VEC_BYTES ((MAX_VEC_ENCODING - MIN_VEC_ENCODING + 1)*4) -// TODO this is new. if the pic has less than 8k of memory, start this lower -// TODO the pic actually has 2k, so change these -// 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 - -#define MAX_RAM_ENCODING 4095 -#define MIN_RAM_ENCODING 512 -#define RAM_BYTES ((MAX_RAM_ENCODING - MIN_RAM_ENCODING + 1)*4) -// TODO watch out if we address more than what the PIC actually has - -#if WORD_BITS == 8 -#define OBJ_TO_VEC_ADDR(o,f) (((ram_addr)((uint16)(o) - MIN_RAM_ENCODING) << 2) + (f)) -#define OBJ_TO_RAM_ADDR(o,f) (((ram_addr)((uint16)(o) - MIN_RAM_ENCODING) << 2) + (f)) -#define OBJ_TO_ROM_ADDR(o,f) (((rom_addr)((uint16)(o) - MIN_ROM_ENCODING) << 2) + (CODE_START + 4 + (f))) -#endif - -#ifdef PICOBOARD2 - -#define ram_get(a) *(uint8*)(a+0x200) -#define ram_set(a,x) *(uint8*)(a+0x200) = (x) -#endif - - -#ifdef WORKSTATION - -uint8 ram_mem[RAM_BYTES + VEC_BYTES]; - -#define ram_get(a) ram_mem[a] -#define ram_set(a,x) ram_mem[a] = (x) - -#endif - - -/*---------------------------------------------------------------------------*/ - -#ifdef PICOBOARD2 - -uint8 rom_get (rom_addr a) -{ - return *(rom uint8*)a; -} - -#endif - - -#ifdef WORKSTATION - -#define ROM_BYTES 8192 -// TODO the new pics have 32k, change this ? minus the vm size, firmware ? +// memory access uint8 rom_mem[ROM_BYTES] = { #define RED_GREEN #define PUTCHAR_LIGHT_not - #ifdef RED_GREEN 0xFB, 0xD7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x32 , 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00 @@ -242,252 +54,44 @@ uint8 rom_mem[ROM_BYTES] = , 0x00, 0xF6, 0xF5, 0x90, 0x08 #endif }; - -uint8 rom_get (rom_addr a) -{ +uint8 rom_get (rom_addr a) { return rom_mem[a-CODE_START]; } -#endif - -/*---------------------------------------------------------------------------*/ - -/* - OBJECT ENCODING: - - #f 0 - #t 1 - () 2 - fixnum n MIN_FIXNUM -> 3 ... MAX_FIXNUM -> 3 + (MAX_FIXNUM-MIN_FIXNUM) - rom object 4 + (MAX_FIXNUM-MIN_FIXNUM) ... MIN_RAM_ENCODING-1 - ram object MIN_RAM_ENCODING ... MAX_RAM_ENCODING - u8vector MIN_VEC_ENCODING ... 8191 - - layout of memory allocated objects: - - G's represent mark bits used by the gc - - ifdef INFINITE_PRECISION_BIGNUMS - bignum n 0GG***** **next** hhhhhhhh llllllll (16 bit digit) - TODO what to do with the gc tags for the bignums ? will this work ? - - ifndef INFINITE_PRECISION_BIGNUMS - bignum n 00000000 uuuuuuuu hhhhhhhh llllllll (24 bit signed integer) - - pair 1GGaaaaa aaaaaaaa 000ddddd dddddddd - a is car - d is cdr - gives an address space of 2^13 * 4 = 32k divided between simple objects, - rom, ram and vectors - - symbol 1GG00000 00000000 00100000 00000000 - - string 1GG***** *chars** 01000000 00000000 - - u8vector 1GGxxxxx xxxxxxxx 011yyyyy yyyyyyyy - x is length of the vector, in bytes (stored raw, not encoded as an object) - y is pointer to the elements themselves (stored in vector space) - - closure 01Gaaaaa aaaaaaaa aaaxxxxx xxxxxxxx - 0x5ff procedure has n parameters (no rest parameter) - n = -128 to -1 -> procedure has -n parameters, the last is - a rest parameter -*/ - -#define OBJ_FALSE 0 -#define OBJ_TRUE 1 -#define encode_bool(x) ((obj)(x)) - -#define OBJ_NULL 2 - -#define MIN_FIXNUM_ENCODING 3 -// TODO change these ? were -5 and 40, with the new bignums, the needs for these might change -#define MIN_FIXNUM -1 -#define MAX_FIXNUM 255 -#define MIN_ROM_ENCODING (MIN_FIXNUM_ENCODING+MAX_FIXNUM-MIN_FIXNUM+1) - -#define ENCODE_FIXNUM(n) ((obj)(n) + (MIN_FIXNUM_ENCODING - MIN_FIXNUM)) -#define DECODE_FIXNUM(o) ((int32)(o) - (MIN_FIXNUM_ENCODING - MIN_FIXNUM)) - -// TODO why this ifdef ? -#if WORD_BITS == 8 -#define IN_VEC(o) ((o) >= MIN_VEC_ENCODING) -#define IN_RAM(o) (!IN_VEC(o) && ((o) >= MIN_RAM_ENCODING)) -#define IN_ROM(o) (!IN_VEC(o) && !IN_RAM(o) && ((o) >= MIN_ROM_ENCODING)) -#endif - -// bignum first byte : 00Gxxxxx -#define BIGNUM_FIELD0 0 -#define RAM_BIGNUM(o) ((ram_get_field0 (o) & 0xc0) == BIGNUM_FIELD0) -#define ROM_BIGNUM(o) ((rom_get_field0 (o) & 0xc0) == BIGNUM_FIELD0) - -// composite first byte : 1GGxxxxx -#define COMPOSITE_FIELD0 0x80 -#define RAM_COMPOSITE(o) ((ram_get_field0 (o) & 0x80) == COMPOSITE_FIELD0) -#define ROM_COMPOSITE(o) ((rom_get_field0 (o) & 0x80) == COMPOSITE_FIELD0) - -// pair third byte : 000xxxxx -#define PAIR_FIELD2 0 -#define RAM_PAIR(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == PAIR_FIELD2)) -#define ROM_PAIR(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == PAIR_FIELD2)) - -// symbol third byte : 001xxxxx -#define SYMBOL_FIELD2 0x20 -#define RAM_SYMBOL(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == SYMBOL_FIELD2)) -#define ROM_SYMBOL(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == SYMBOL_FIELD2)) - -// string third byte : 010xxxxx -#define STRING_FIELD2 0x40 -#define RAM_STRING(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == STRING_FIELD2)) -#define ROM_STRING(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == STRING_FIELD2)) - -// vector third byte : 011xxxxx -#define VECTOR_FIELD2 0x60 -#define RAM_VECTOR(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == VECTOR_FIELD2)) -#define ROM_VECTOR(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == VECTOR_FIELD2)) - -// continuation third byte : 100xxxxx -#define CONTINUATION_FIELD2 0x80 -#define RAM_CONTINUATION(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == CONTINUATION_FIELD2)) -#define ROM_CONTINUATION(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == CONTINUATION_FIELD2)) - -// closure first byte : 01Gxxxxx -#define CLOSURE_FIELD0 0x40 -#define RAM_CLOSURE(o) ((ram_get_field0 (o) & 0xc0) == CLOSURE_FIELD0) -#define ROM_CLOSURE(o) ((rom_get_field0 (o) & 0xc0) == CLOSURE_FIELD0) - - -/*---------------------------------------------------------------------------*/ - -#define RAM_GET_FIELD0_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,0)) -#define RAM_SET_FIELD0_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,0), val) -#define ROM_GET_FIELD0_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,0)) - -#define RAM_GET_GC_TAGS_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x60) -#define RAM_GET_GC_TAG0_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x20) -#define RAM_GET_GC_TAG1_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x40) -#define RAM_SET_GC_TAGS_MACRO(o,tags) \ - (RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0x9f) | (tags))) -#define RAM_SET_GC_TAG0_MACRO(o,tag) \ - RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xdf) | (tag)) -#define RAM_SET_GC_TAG1_MACRO(o,tag) \ - RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xbf) | (tag)) - -#if WORD_BITS == 8 -#define RAM_GET_FIELD1_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,1)) -#define RAM_GET_FIELD2_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,2)) -#define RAM_GET_FIELD3_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,3)) -#define RAM_SET_FIELD1_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,1), val) -#define RAM_SET_FIELD2_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,2), val) -#define RAM_SET_FIELD3_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,3), val) -#define ROM_GET_FIELD1_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,1)) -#define ROM_GET_FIELD2_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,2)) -#define ROM_GET_FIELD3_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,3)) -#define VEC_GET_BYTE0_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,0)) -#define VEC_GET_BYTE1_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,1)) -#define VEC_GET_BYTE2_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,2)) -#define VEC_GET_BYTE3_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,3)) -#define VEC_SET_BYTE0_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,0), val) -#define VEC_SET_BYTE1_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,1), val) -#define VEC_SET_BYTE2_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,2), val) -#define VEC_SET_BYTE3_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,3), val) -#endif - -uint8 ram_get_gc_tags (obj o) { return RAM_GET_GC_TAGS_MACRO(o); } -uint8 ram_get_gc_tag0 (obj o) { return RAM_GET_GC_TAG0_MACRO(o); } -uint8 ram_get_gc_tag1 (obj o) { return RAM_GET_GC_TAG1_MACRO(o); } -void ram_set_gc_tags (obj o, uint8 tags) { RAM_SET_GC_TAGS_MACRO(o, tags); } -void ram_set_gc_tag0 (obj o, uint8 tag) { RAM_SET_GC_TAG0_MACRO(o,tag); } -void ram_set_gc_tag1 (obj o, uint8 tag) { RAM_SET_GC_TAG1_MACRO(o,tag); } -uint8 ram_get_field0 (obj o) { return RAM_GET_FIELD0_MACRO(o); } +word ram_get_gc_tags (obj o) { return RAM_GET_GC_TAGS_MACRO(o); } +word ram_get_gc_tag0 (obj o) { return RAM_GET_GC_TAG0_MACRO(o); } +word ram_get_gc_tag1 (obj o) { return RAM_GET_GC_TAG1_MACRO(o); } +void ram_set_gc_tags (obj o, word tags) { RAM_SET_GC_TAGS_MACRO(o, tags); } +void ram_set_gc_tag0 (obj o, word tag) { RAM_SET_GC_TAG0_MACRO(o,tag); } +void ram_set_gc_tag1 (obj o, word tag) { RAM_SET_GC_TAG1_MACRO(o,tag); } +word ram_get_field0 (obj o) { return RAM_GET_FIELD0_MACRO(o); } word ram_get_field1 (obj o) { return RAM_GET_FIELD1_MACRO(o); } word ram_get_field2 (obj o) { return RAM_GET_FIELD2_MACRO(o); } word ram_get_field3 (obj o) { return RAM_GET_FIELD3_MACRO(o); } -word ram_get_fieldn (obj o, uint8 n) -{ - switch (n) - { - case 0: return ram_get_field0 (o); - case 1: return ram_get_field1 (o); - case 2: return ram_get_field2 (o); - case 3: return ram_get_field3 (o); - } +word ram_get_fieldn (obj o, word n) { // TODO have as a macro ? + switch (n) { + case 0: return ram_get_field0 (o); + case 1: return ram_get_field1 (o); + case 2: return ram_get_field2 (o); + case 3: return ram_get_field3 (o); + } } -void ram_set_field0 (obj o, uint8 val) { RAM_SET_FIELD0_MACRO(o,val); } +void ram_set_field0 (obj o, word val) { RAM_SET_FIELD0_MACRO(o,val); } void ram_set_field1 (obj o, word val) { RAM_SET_FIELD1_MACRO(o,val); } void ram_set_field2 (obj o, word val) { RAM_SET_FIELD2_MACRO(o,val); } void ram_set_field3 (obj o, word val) { RAM_SET_FIELD3_MACRO(o,val); } -void ram_set_fieldn (obj o, uint8 n, word val) -{ - switch (n) - { - case 0: ram_set_field0 (o, val); break; - case 1: ram_set_field1 (o, val); break; - case 2: ram_set_field2 (o, val); break; - case 3: ram_set_field3 (o, val); break; - } -} -uint8 rom_get_field0 (obj o) { return ROM_GET_FIELD0_MACRO(o); } +void ram_set_fieldn (obj o, uint8 n, word val) { // TODO have as a macro ? + switch (n) { + case 0: ram_set_field0 (o, val); break; + case 1: ram_set_field1 (o, val); break; + case 2: ram_set_field2 (o, val); break; + case 3: ram_set_field3 (o, val); break; + } +} +word rom_get_field0 (obj o) { return ROM_GET_FIELD0_MACRO(o); } word rom_get_field1 (obj o) { return ROM_GET_FIELD1_MACRO(o); } word rom_get_field2 (obj o) { return ROM_GET_FIELD2_MACRO(o); } word rom_get_field3 (obj o) { return ROM_GET_FIELD3_MACRO(o); } -/* word vec_get_byte0 (obj o) { return VEC_GET_BYTE0_MACRO(o); } */ -/* word vec_get_byte1 (obj o) { return VEC_GET_BYTE1_MACRO(o); } */ -/* word vec_get_byte2 (obj o) { return VEC_GET_BYTE2_MACRO(o); } */ -/* word vec_get_byte3 (obj o) { return VEC_GET_BYTE3_MACRO(o); } */ -/* word vec_set_byte0 (obj o, word val) { VEC_SET_BYTE0_MACRO(o,val); } */ -/* word vec_set_byte1 (obj o, word val) { VEC_SET_BYTE1_MACRO(o,val); } */ -/* word vec_set_byte2 (obj o, word val) { VEC_SET_BYTE2_MACRO(o,val); } */ -/* word vec_set_byte3 (obj o, word val) { VEC_SET_BYTE3_MACRO(o,val); } */ - -obj get_field0 (obj o) // TODO these are not used yet, will they be useful at all ? -{ - if (IN_RAM(o)) - return ram_get_field0 (o); - else - return rom_get_field0 (o); -} -obj get_field1 (obj o) -{ - if (IN_RAM(o)) - return ram_get_field1 (o); - else - return rom_get_field1 (o); -} -obj get_field2 (obj o) -{ - if (IN_RAM(o)) - return ram_get_field2 (o); - else - return rom_get_field2 (o); -} -obj get_field3 (obj o) -{ - if (IN_RAM(o)) - return ram_get_field3 (o); - else - return rom_get_field3 (o); -} - obj ram_get_car (obj o) { return ((ram_get_field0 (o) & 0x1f) << 8) | ram_get_field1 (o); } @@ -497,484 +101,86 @@ obj ram_get_cdr (obj o) { return ((ram_get_field2 (o) & 0x1f) << 8) | ram_get_field3 (o); } obj rom_get_cdr (obj o) { return ((rom_get_field2 (o) & 0x1f) << 8) | rom_get_field3 (o); } -obj get_car (obj o) -{ - if (IN_RAM(o)) - return ram_get_car (o); - else - return rom_get_car (o); -} -obj get_cdr (obj o) -{ - if (IN_RAM(o)) - return ram_get_cdr (o); - else - return rom_get_cdr (o); -} -void ram_set_car (obj o, obj val) -{ +void ram_set_car (obj o, obj val) { ram_set_field0 (o, (val >> 8) | (ram_get_field0 (o) & 0xe0)); ram_set_field1 (o, val & 0xff); } -void ram_set_cdr (obj o, obj val) -{ +void ram_set_cdr (obj o, obj val) { ram_set_field2 (o, (val >> 8) | (ram_get_field2 (o) & 0xe0)); ram_set_field3 (o, val & 0xff); } -obj ram_get_entry (obj o) -{ +// function entry point +obj ram_get_entry (obj o) { return (((ram_get_field0 (o) & 0x1f) << 11) | (ram_get_field1 (o) << 3) | (ram_get_field2 (o) >> 5)); } -obj rom_get_entry (obj o) -{ +obj rom_get_entry (obj o){ return (((rom_get_field0 (o) & 0x1f) << 11) | (rom_get_field1 (o) << 3) | (rom_get_field2 (o) >> 5)); } -obj get_entry (obj o) -{ - if (IN_RAM(o)) - return ram_get_entry (o); - else - return rom_get_entry (o); -} - -obj get_global (uint8 i) +obj get_global (uint8 i) { // globals occupy the beginning of ram, with 2 globals per word -{ if (i & 1) return ram_get_cdr (MIN_RAM_ENCODING + (i / 2)); else return ram_get_car (MIN_RAM_ENCODING + (i / 2)); } - -void set_global (uint8 i, obj o) -{ +void set_global (uint8 i, obj o) { if (i & 1) ram_set_cdr (MIN_RAM_ENCODING + (i / 2), o); else ram_set_car (MIN_RAM_ENCODING + (i / 2), o); } -#ifdef WORKSTATION -void show_type (obj o) // for debugging purposes - { - printf("%d : ", o); - if (o == OBJ_FALSE) printf("#f"); - else if (o == OBJ_TRUE) printf("#t"); - else if (o == OBJ_NULL) printf("()"); - else if (o < MIN_ROM_ENCODING) printf("fixnum"); - else if (IN_RAM (o)) - { - if (RAM_BIGNUM(o)) printf("ram bignum"); - else if (RAM_PAIR(o)) printf("ram pair"); - else if (RAM_SYMBOL(o)) printf("ram symbol"); - else if (RAM_STRING(o)) printf("ram string"); - else if (RAM_VECTOR(o)) printf("ram vector"); - else if (RAM_CONTINUATION(o)) printf("ram continuation"); - else if (RAM_CLOSURE(o)) printf("ram closure"); - } - else // ROM - { - if (ROM_BIGNUM(o)) printf("rom bignum"); - else if (ROM_PAIR(o)) printf("rom pair"); - else if (ROM_SYMBOL(o)) printf("rom symbol"); - else if (ROM_STRING(o)) printf("rom string"); - else if (ROM_VECTOR(o)) printf("rom vector"); - else if (ROM_CONTINUATION(o)) printf("rom continuation"); - else if (RAM_CLOSURE(o)) printf("rom closure"); - } - printf("\n"); - } -#endif - - -/*---------------------------------------------------------------------------*/ - -/* Interface to GC */ - -// TODO explain what each tag means, with 1-2 mark bits -#define GC_TAG_0_LEFT (1<<5) -#define GC_TAG_1_LEFT (2<<5) -#define GC_TAG_UNMARKED (0<<5) - -/* Number of object fields of objects in ram */ -#define HAS_2_OBJECT_FIELDS(visit) (RAM_PAIR(visit) || RAM_CONTINUATION(visit)) -#ifdef INFINITE_PRECISION_BIGNUMS -#define HAS_1_OBJECT_FIELD(visit) (RAM_COMPOSITE(visit) \ - || RAM_CLOSURE(visit) || RAM_BIGNUM(visit)) -#else -#define HAS_1_OBJECT_FIELD(visit) (RAM_COMPOSITE(visit) || RAM_CLOSURE(visit)) -#endif -// all composites except pairs and continuations have 1 object field - -#define NIL OBJ_FALSE - -/*---------------------------------------------------------------------------*/ - -/* Garbage collector */ -obj free_list; /* list of unused cells */ -obj free_list_vec; /* list of unused cells in vector space */ - -obj arg1; /* root set */ -obj arg2; -obj arg3; -obj arg4; -obj arg5; -obj cont; -obj env; - -uint8 na; /* interpreter variables */ -rom_addr pc; -uint8 glovars; -rom_addr entry; -uint8 bytecode; -uint8 bytecode_hi4; -uint8 bytecode_lo4; -int32 a1; -int32 a2; -int32 a3; - -void init_ram_heap (void) -{ - uint8 i; - obj o = MAX_RAM_ENCODING; - - free_list = 0; - - while (o > (MIN_RAM_ENCODING + (glovars + 1) / 2)) - // we don't want to add globals to the free list, and globals occupy the - // beginning of memory at the rate of 2 globals per word (car and cdr) - { - ram_set_gc_tags (o, GC_TAG_UNMARKED); - ram_set_car (o, free_list); - free_list = o; - o--; - } - - free_list_vec = MIN_VEC_ENCODING; - ram_set_car (free_list_vec, 0); - // each node of the free list must know the free length that follows it - // this free length is stored in words, not in bytes - // if we did count in bytes, the number might need more than 13 bits - ram_set_cdr (free_list_vec, VEC_BYTES / 4); - - for (i=0; i>5)); - - if ((HAS_1_OBJECT_FIELD (visit) && ram_get_gc_tag0 (visit)) - || (HAS_2_OBJECT_FIELDS (visit) - && (ram_get_gc_tags (visit) != GC_TAG_UNMARKED))) - IF_GC_TRACE(printf ("case 1\n")); - else - { - if (HAS_2_OBJECT_FIELDS(visit)) // pairs and continuations - { - IF_GC_TRACE(printf ("case 2\n")); - - visit_field2: - - temp = ram_get_cdr (visit); - - if (IN_RAM(temp)) - { - IF_GC_TRACE(printf ("case 3\n")); - ram_set_gc_tags (visit, GC_TAG_1_LEFT); - ram_set_cdr (visit, stack); - goto push; - } - - IF_GC_TRACE(printf ("case 4\n")); - - goto visit_field1; - } - - if (HAS_1_OBJECT_FIELD(visit)) - { - IF_GC_TRACE(printf ("case 5\n")); - - visit_field1: - - if (RAM_CLOSURE(visit)) // closures have the pointer in the cdr - temp = ram_get_cdr (visit); - else - temp = ram_get_car (visit); - - if (IN_RAM(temp)) - { - IF_GC_TRACE(printf ("case 6\n")); - ram_set_gc_tag0 (visit, GC_TAG_0_LEFT); - if (RAM_CLOSURE(visit)) - ram_set_cdr (visit, stack); - else - ram_set_car (visit, stack); - - goto push; - } - - IF_GC_TRACE(printf ("case 7\n")); - } - else - IF_GC_TRACE(printf ("case 8\n")); - - ram_set_gc_tag0 (visit, GC_TAG_0_LEFT); - } - - pop: - - IF_GC_TRACE(printf ("pop stack=%d visit=%d (tag=%d)\n", stack, visit, ram_get_gc_tags (visit)>>6)); - - if (stack != NIL) - { - if (HAS_2_OBJECT_FIELDS(stack) && ram_get_gc_tag1 (stack)) - { - IF_GC_TRACE(printf ("case 9\n")); - - temp = ram_get_cdr (stack); /* pop through cdr */ - ram_set_cdr (stack, visit); - visit = stack; - stack = temp; - - ram_set_gc_tag1(visit, GC_TAG_UNMARKED); - // we unset the "1-left" bit - - goto visit_field1; - } - - if (RAM_CLOSURE(stack)) - // closures have one object field, but it's in the cdr - { - IF_GC_TRACE(printf ("case 10\n")); - - temp = ram_get_cdr (stack); /* pop through cdr */ - ram_set_cdr (stack, visit); - visit = stack; - stack = temp; - - goto pop; - } - - IF_GC_TRACE(printf ("case 11\n")); - - temp = ram_get_car (stack); /* pop through car */ - ram_set_car (stack, visit); - visit = stack; - stack = temp; - - goto pop; - } - } +obj get_field1 (obj o) { + if (IN_RAM(o)) + return ram_get_field1 (o); + else + return rom_get_field1 (o); } - -#ifdef DEBUG_GC -int max_live = 0; -#endif - -void sweep (void) -{ - /* sweep phase */ - -#ifdef DEBUG_GC - int n = 0; -#endif - - obj visit = MAX_RAM_ENCODING; - - free_list = 0; - - while (visit >= (MIN_RAM_ENCODING + ((glovars + 1) / 2))) - // we don't want to sweep the global variables area - { - if ((RAM_COMPOSITE(visit) - && (ram_get_gc_tags (visit) == GC_TAG_UNMARKED)) // 2 mark bit - || !(ram_get_gc_tags (visit) & GC_TAG_0_LEFT)) // 1 mark bit - /* unmarked? */ - { - if (RAM_VECTOR(visit)) - // when we sweep a vector, we also have to sweep its contents - { - obj o = ram_get_cdr (visit); - uint16 i = ram_get_car (visit); // number of elements - ram_set_car (o, free_list_vec); - ram_set_cdr (o, (i + 3) / 4); // free length, in words - free_list_vec = o; - // TODO merge free spaces - } - ram_set_car (visit, free_list); - free_list = visit; - } - else - { - if (RAM_COMPOSITE(visit)) - ram_set_gc_tags (visit, GC_TAG_UNMARKED); - else // only 1 mark bit to unset - ram_set_gc_tag0 (visit, GC_TAG_UNMARKED); -#ifdef DEBUG_GC - n++; -#endif - } - visit--; - } - -#ifdef DEBUG_GC - if (n > max_live) - { - max_live = n; - printf ("**************** memory needed = %d\n", max_live+1); - fflush (stdout); - } -#endif +obj get_field2 (obj o) { + if (IN_RAM(o)) + return ram_get_field2 (o); + else + return rom_get_field2 (o); } - -void gc (void) -{ - uint8 i; - - IF_TRACE(printf("\nGC BEGINS\n")); - - IF_GC_TRACE(printf("arg1\n")); - mark (arg1); - IF_GC_TRACE(printf("arg2\n")); - mark (arg2); - IF_GC_TRACE(printf("arg3\n")); - mark (arg3); - IF_GC_TRACE(printf("arg4\n")); - mark (arg4); - IF_GC_TRACE(printf("arg5\n")); - mark (arg5); - IF_GC_TRACE(printf("cont\n")); - mark (cont); - IF_GC_TRACE(printf("env\n")); - mark (env); - - IF_GC_TRACE(printf("globals\n")); - for (i=0; i + +static volatile near uint8 FW_VALUE_UP @ 0x33; +static volatile near uint8 FW_VALUE_HI @ 0x33; +static volatile near uint8 FW_VALUE_LO @ 0x33; + +#define ACTIVITY_LED1_LAT LATB +#define ACTIVITY_LED1_BIT 5 +#define ACTIVITY_LED2_LAT LATB +#define ACTIVITY_LED2_BIT 4 +static volatile near bit ACTIVITY_LED1 @ ((unsigned)&ACTIVITY_LED1_LAT*8)+ACTIVITY_LED1_BIT; +static volatile near bit ACTIVITY_LED2 @ ((unsigned)&ACTIVITY_LED2_LAT*8)+ACTIVITY_LED2_BIT; + +#endif + + +#ifdef WORKSTATION + +#include +#include +#include + +// for libpcap +#define MAX_PACKET_SIZE BUFSIZ +#define PROMISC 1 +#define TO_MSEC 1 +char errbuf[PCAP_ERRBUF_SIZE]; +pcap_t *handle; +#define INTERFACE "eth0" +char buf [MAX_PACKET_SIZE]; // buffer for writing + + +#ifdef _WIN32 + +#include +#include +#include + +#else + +#include + +#endif + +#endif + +/*---------------------------------------------------------------------------*/ + +// miscellaneous definitions +// TODO put at the end ? + +// TODO these 2 are only used in negp, use them elsewhere ? +#define true 1 +#define false 0 + +#define CODE_START 0x5000 + +/*---------------------------------------------------------------------------*/ + +// debugging + +#ifdef DEBUG +#define IF_TRACE(x) x +#define IF_GC_TRACE(x) x +#else +#define IF_TRACE(x) +#define IF_GC_TRACE(x) +#endif + +/*---------------------------------------------------------------------------*/ + +// error handling + +#ifdef PICOBOARD2 +#define ERROR(prim, msg) halt_with_error() +#define TYPE_ERROR(prim, type) halt_with_error() +#endif + +#ifdef WORKSTATION +#define ERROR(prim, msg) error (prim, msg) +#define TYPE_ERROR(prim, type) type_error (prim, type) +void error (char *prim, char *msg); +void type_error (char *prim, char *type); +#endif + +/*---------------------------------------------------------------------------*/ + +// address space layout +// TODO document each zone, also explain that since vector space is in ram, it uses the ram primitives + +#define MAX_VEC_ENCODING 8191 +#define MIN_VEC_ENCODING 4096 +#define VEC_BYTES ((MAX_VEC_ENCODING - MIN_VEC_ENCODING + 1)*4) +// if the pic has less than 8k of memory, start vector space lower +// TODO the pic actually has 2k, so change these +// 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 + +#define MAX_RAM_ENCODING 4095 +#define MIN_RAM_ENCODING 512 +#define RAM_BYTES ((MAX_RAM_ENCODING - MIN_RAM_ENCODING + 1)*4) +// TODO watch out if we address more than what the PIC actually has + +#define MIN_FIXNUM_ENCODING 3 +#define MIN_FIXNUM -1 +#define MAX_FIXNUM 255 +#define MIN_ROM_ENCODING (MIN_FIXNUM_ENCODING+MAX_FIXNUM-MIN_FIXNUM+1) + +#define OBJ_TO_RAM_ADDR(o,f) (((ram_addr)((uint16)(o) - MIN_RAM_ENCODING) << 2) + (f)) +#define OBJ_TO_ROM_ADDR(o,f) (((rom_addr)((uint16)(o) - MIN_ROM_ENCODING) << 2) + (CODE_START + 4 + (f))) + + +#ifdef PICOBOARD2 +#define ram_get(a) *(uint8*)(a+0x200) +#define ram_set(a,x) *(uint8*)(a+0x200) = (x) +#endif + + +#ifdef WORKSTATION +uint8 ram_mem[RAM_BYTES + VEC_BYTES]; +#define ram_get(a) ram_mem[a] +#define ram_set(a,x) ram_mem[a] = (x) +#endif + +#ifdef PICOBOARD2 +uint8 rom_get (rom_addr a){ + return *(rom uint8*)a; +} +#endif + + +#ifdef WORKSTATION +#define ROM_BYTES 8192 +// TODO the new pics have 32k, change this ? minus the vm size, firmware ? +uint8 rom_mem[ROM_BYTES]; +uint8 rom_get (rom_addr a); +#endif + +/*---------------------------------------------------------------------------*/ + +// memory access + +#define RAM_GET_FIELD0_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,0)) +#define RAM_SET_FIELD0_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,0), val) +#define ROM_GET_FIELD0_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,0)) + +#define RAM_GET_GC_TAGS_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x60) +#define RAM_GET_GC_TAG0_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x20) +#define RAM_GET_GC_TAG1_MACRO(o) (RAM_GET_FIELD0_MACRO(o) & 0x40) +#define RAM_SET_GC_TAGS_MACRO(o,tags) \ + (RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0x9f) | (tags))) +#define RAM_SET_GC_TAG0_MACRO(o,tag) \ + RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xdf) | (tag)) +#define RAM_SET_GC_TAG1_MACRO(o,tag) \ + RAM_SET_FIELD0_MACRO(o,(RAM_GET_FIELD0_MACRO(o) & 0xbf) | (tag)) + +#define RAM_GET_FIELD1_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,1)) +#define RAM_GET_FIELD2_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,2)) +#define RAM_GET_FIELD3_MACRO(o) ram_get (OBJ_TO_RAM_ADDR(o,3)) +#define RAM_SET_FIELD1_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,1), val) +#define RAM_SET_FIELD2_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,2), val) +#define RAM_SET_FIELD3_MACRO(o,val) ram_set (OBJ_TO_RAM_ADDR(o,3), val) +#define ROM_GET_FIELD1_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,1)) +#define ROM_GET_FIELD2_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,2)) +#define ROM_GET_FIELD3_MACRO(o) rom_get (OBJ_TO_ROM_ADDR(o,3)) + +word ram_get_gc_tags (obj o); +word ram_get_gc_tag0 (obj o); +word ram_get_gc_tag1 (obj o); +void ram_set_gc_tags (obj o, word tags); +void ram_set_gc_tag0 (obj o, word tag); +void ram_set_gc_tag1 (obj o, word tag); +word ram_get_field0 (obj o); +word ram_get_field1 (obj o); +word ram_get_field2 (obj o); +word ram_get_field3 (obj o); +word ram_get_fieldn (obj o, word n); +void ram_set_field0 (obj o, word val); +void ram_set_field1 (obj o, word val); +void ram_set_field2 (obj o, word val); +void ram_set_field3 (obj o, word val); +void ram_set_fieldn (obj o, uint8 n, word val); +word rom_get_field0 (obj o); +word rom_get_field1 (obj o); +word rom_get_field2 (obj o); +word rom_get_field3 (obj o); + +obj ram_get_car (obj o); +obj rom_get_car (obj o); +obj ram_get_cdr (obj o); +obj rom_get_cdr (obj o); +void ram_set_car (obj o, obj val); +void ram_set_cdr (obj o, obj val); + +obj ram_get_entry (obj o); +obj rom_get_entry (obj o); + +obj get_global (uint8 i); +void set_global (uint8 i, obj o); + +/*---------------------------------------------------------------------------*/ + +/* + OBJECT ENCODING: + + #f 0 + #t 1 + () 2 + fixnum n MIN_FIXNUM -> 3 ... MAX_FIXNUM -> 3 + (MAX_FIXNUM-MIN_FIXNUM) + rom object 4 + (MAX_FIXNUM-MIN_FIXNUM) ... MIN_RAM_ENCODING-1 + ram object MIN_RAM_ENCODING ... MAX_RAM_ENCODING + u8vector MIN_VEC_ENCODING ... 8191 + + layout of memory allocated objects: + + Gs represent mark bits used by the gc + + ifdef INFINITE_PRECISION_BIGNUMS + bignum n 0GG***** **next** hhhhhhhh llllllll (16 bit digit) + TODO what to do with the gc tags for the bignums ? will this work ? + + ifndef INFINITE_PRECISION_BIGNUMS + bignum n 00000000 uuuuuuuu hhhhhhhh llllllll (24 bit signed integer) + + pair 1GGaaaaa aaaaaaaa 000ddddd dddddddd + a is car + d is cdr + gives an address space of 2^13 * 4 = 32k divided between simple objects, + rom, ram and vectors + + symbol 1GG00000 00000000 00100000 00000000 + + string 1GG***** *chars** 01000000 00000000 + + u8vector 1GGxxxxx xxxxxxxx 011yyyyy yyyyyyyy + x is length of the vector, in bytes (stored raw, not encoded as an object) + y is pointer to the elements themselves (stored in vector space) + + closure 01Gaaaaa aaaaaaaa aaaxxxxx xxxxxxxx + 0x5ff procedure has n parameters (no rest parameter) + n = -128 to -1 -> procedure has -n parameters, the last is + a rest parameter +*/ + +#define OBJ_FALSE 0 +#define OBJ_TRUE 1 +#define encode_bool(x) ((obj)(x)) + +#define OBJ_NULL 2 + +// fixnum definitions in picobit-vm.h , address space layout section + +#define ENCODE_FIXNUM(n) ((obj)(n) + (MIN_FIXNUM_ENCODING - MIN_FIXNUM)) +#define DECODE_FIXNUM(o) ((int32)(o) - (MIN_FIXNUM_ENCODING - MIN_FIXNUM)) + +#define IN_VEC(o) ((o) >= MIN_VEC_ENCODING) +#define IN_RAM(o) (!IN_VEC(o) && ((o) >= MIN_RAM_ENCODING)) +#define IN_ROM(o) (!IN_VEC(o) && !IN_RAM(o) && ((o) >= MIN_ROM_ENCODING)) + +// bignum first byte : 00Gxxxxx +#define BIGNUM_FIELD0 0 +#define RAM_BIGNUM(o) ((ram_get_field0 (o) & 0xc0) == BIGNUM_FIELD0) +#define ROM_BIGNUM(o) ((rom_get_field0 (o) & 0xc0) == BIGNUM_FIELD0) + +// composite first byte : 1GGxxxxx +#define COMPOSITE_FIELD0 0x80 +#define RAM_COMPOSITE(o) ((ram_get_field0 (o) & 0x80) == COMPOSITE_FIELD0) +#define ROM_COMPOSITE(o) ((rom_get_field0 (o) & 0x80) == COMPOSITE_FIELD0) + +// pair third byte : 000xxxxx +#define PAIR_FIELD2 0 +#define RAM_PAIR(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == PAIR_FIELD2)) +#define ROM_PAIR(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == PAIR_FIELD2)) + +// symbol third byte : 001xxxxx +#define SYMBOL_FIELD2 0x20 +#define RAM_SYMBOL(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == SYMBOL_FIELD2)) +#define ROM_SYMBOL(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == SYMBOL_FIELD2)) + +// string third byte : 010xxxxx +#define STRING_FIELD2 0x40 +#define RAM_STRING(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == STRING_FIELD2)) +#define ROM_STRING(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == STRING_FIELD2)) + +// vector third byte : 011xxxxx +#define VECTOR_FIELD2 0x60 +#define RAM_VECTOR(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == VECTOR_FIELD2)) +#define ROM_VECTOR(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == VECTOR_FIELD2)) + +// continuation third byte : 100xxxxx +#define CONTINUATION_FIELD2 0x80 +#define RAM_CONTINUATION(o) (RAM_COMPOSITE (o) && ((ram_get_field2 (o) & 0xe0) == CONTINUATION_FIELD2)) +#define ROM_CONTINUATION(o) (ROM_COMPOSITE (o) && ((rom_get_field2 (o) & 0xe0) == CONTINUATION_FIELD2)) + +// closure first byte : 01Gxxxxx +#define CLOSURE_FIELD0 0x40 +#define RAM_CLOSURE(o) ((ram_get_field0 (o) & 0xc0) == CLOSURE_FIELD0) +#define ROM_CLOSURE(o) ((rom_get_field0 (o) & 0xc0) == CLOSURE_FIELD0) + +/*---------------------------------------------------------------------------*/ + +// garbage collector + +// TODO explain what each tag means, with 1-2 mark bits +#define GC_TAG_0_LEFT (1<<5) +#define GC_TAG_1_LEFT (2<<5) +#define GC_TAG_UNMARKED (0<<5) + +/* Number of object fields of objects in ram */ +#define HAS_2_OBJECT_FIELDS(visit) (RAM_PAIR(visit) || RAM_CONTINUATION(visit)) +#ifdef INFINITE_PRECISION_BIGNUMS +#define HAS_1_OBJECT_FIELD(visit) (RAM_COMPOSITE(visit) \ + || RAM_CLOSURE(visit) || RAM_BIGNUM(visit)) +#else +#define HAS_1_OBJECT_FIELD(visit) (RAM_COMPOSITE(visit) || RAM_CLOSURE(visit)) +#endif +// all composites except pairs and continuations have 1 object field + +#define NIL OBJ_FALSE + +obj free_list; /* list of unused cells */ +obj free_list_vec; /* list of unused cells in vector space */ + +obj arg1; /* root set */ +obj arg2; +obj arg3; +obj arg4; +obj arg5; +obj cont; +obj env; + +uint8 na; /* interpreter variables */ +rom_addr pc; +uint8 glovars; +rom_addr entry; +uint8 bytecode; +uint8 bytecode_hi4; +uint8 bytecode_lo4; +int32 a1; +int32 a2; +int32 a3; + +/*---------------------------------------------------------------------------*/ + +#endif + diff --git a/picobit.scm b/picobit.scm index b0618f4..1ba59ca 100644 --- a/picobit.scm +++ b/picobit.scm @@ -1,6 +1,7 @@ -; File: "picobit.scm", Time-stamp: <2006-05-08 16:04:37 feeley> +;;;; File: "picobit.scm", Time-stamp: <2006-05-08 16:04:37 feeley> -; Copyright (C) 2008 by Marc Feeley and Vincent St-Amour, All Rights Reserved. +;;;; Copyright (C) 2004-2009 by Marc Feeley and Vincent St-Amour +;;;; All Rights Reserved. (define-macro (dummy) (proper-tail-calls-set! #f) -- 2.11.4.GIT