Since we don't use closures as pairs in the stack anymore, the
[picobit.git] / picobit-vm.c
blob81bd3232417486374e02f9f0d0543beb73537dfc
1 /* file: "picobit-vm.c" */
3 /*
4 * Copyright 2004-2009 by Marc Feeley and Vincent St-Amour, All Rights Reserved.
6 * History:
8 * 15/08/2004 Release of version 1
9 * 06/07/2008 Modified for PICOBOARD2_R3
10 * 18/07/2008 Modified to use new object representation
11 * 17/12/2008 Release of version 2
14 #include "picobit-vm.h"
16 /*---------------------------------------------------------------------------*/
18 // error handling
20 #ifdef WORKSTATION
21 void error (char *prim, char *msg) {
22 printf ("ERROR: %s: %s\n", prim, msg);
23 exit (1);
26 void type_error (char *prim, char *type) {
27 printf ("ERROR: %s: An argument of type %s was expected\n", prim, type);
28 exit (1);
30 #endif
32 #ifdef SIXPIC
33 void halt_with_error () {
34 uart_write(101); // e
35 uart_write(114); // r
36 uart_write(114); // r
37 uart_write(13);
38 uart_write(10);
39 exit();
41 #endif
43 /*---------------------------------------------------------------------------*/
45 // memory access
47 word ram_get_fieldn (obj o, word n) {
48 switch (n) {
49 case 0: return ram_get_field0 (o);
50 case 1: return ram_get_field1 (o);
51 case 2: return ram_get_field2 (o);
52 case 3: return ram_get_field3 (o);
55 void ram_set_fieldn (obj o, uint8 n, word val) { // TODO have as a macro ?
56 switch (n) {
57 case 0: ram_set_field0 (o, val); break;
58 case 1: ram_set_field1 (o, val); break;
59 case 2: ram_set_field2 (o, val); break;
60 case 3: ram_set_field3 (o, val); break;
64 // these temporary variables are necessary with SIXPIC, or else the shift
65 // results will be 8 bits values, which is wrong
66 obj ram_get_car (obj o) {
67 uint16 tmp = ram_get_field0 (o) & 0x1f;
68 return (tmp << 8) | ram_get_field1 (o);
70 obj rom_get_car (obj o) {
71 uint16 tmp = rom_get_field0 (o) & 0x1f;
72 return (tmp << 8) | rom_get_field1 (o);
74 obj ram_get_cdr (obj o) {
75 uint16 tmp = ram_get_field2 (o) & 0x1f;
76 return (tmp << 8) | ram_get_field3 (o);
78 obj rom_get_cdr (obj o) {
79 uint16 tmp = rom_get_field2 (o) & 0x1f;
80 return (tmp << 8) | rom_get_field3 (o);
83 void ram_set_car (obj o, obj val) {
84 ram_set_field0 (o, (val >> 8) | (ram_get_field0 (o) & 0xe0));
85 ram_set_field1 (o, val & 0xff);
87 void ram_set_cdr (obj o, obj val) {
88 ram_set_field2 (o, (val >> 8) | (ram_get_field2 (o) & 0xe0));
89 ram_set_field3 (o, val & 0xff);
92 // function entry point
93 // the temporary variables are necessary with SIXPIC, see above
94 obj ram_get_entry (obj o) {
95 uint16 tmp = ram_get_field2 (o);
96 return ((tmp << 8) | ram_get_field3 (o));
98 obj rom_get_entry (obj o){
99 uint16 tmp = rom_get_field2 (o);
100 return ((tmp << 8) | rom_get_field3 (o));
103 obj get_global (uint8 i) {
104 // globals occupy the beginning of ram, with 2 globals per word
105 if (i & 1)
106 return ram_get_cdr (MIN_RAM_ENCODING + (i >> 1));
107 else
108 return ram_get_car (MIN_RAM_ENCODING + (i >> 1));
110 void set_global (uint8 i, obj o) {
111 if (i & 1)
112 ram_set_cdr (MIN_RAM_ENCODING + (i >> 1), o);
113 else
114 ram_set_car (MIN_RAM_ENCODING + (i >> 1), o);
117 // TODO generic functions (get_field0, get_car, etc) that work for both rom and ram were not used, are in garbage
119 /*---------------------------------------------------------------------------*/
121 #ifdef WORKSTATION
123 int hidden_fgetc (FILE *f)
125 int c = fgetc (f);
126 #if 0
127 printf ("{%d}",c);
128 fflush (stdout);
129 #endif
130 return c;
133 #define fgetc(f) hidden_fgetc(f)
135 void write_hex_nibble (int n)
137 putchar ("0123456789ABCDEF"[n]);
140 void write_hex (uint8 n)
142 write_hex_nibble (n >> 4);
143 write_hex_nibble (n & 0x0f);
146 int hex (int c)
148 if (c >= '0' && c <= '9')
149 return (c - '0');
151 if (c >= 'A' && c <= 'F')
152 return (c - 'A' + 10);
154 if (c >= 'a' && c <= 'f')
155 return (c - 'a' + 10);
157 return -1;
160 int read_hex_byte (FILE *f)
162 int h1 = hex (fgetc (f));
163 int h2 = hex (fgetc (f));
165 if (h1 >= 0 && h2 >= 0)
166 return (h1<<4) + h2;
168 return -1;
171 int read_hex_file (char *filename)
173 int c;
174 FILE *f = fopen (filename, "r");
175 int result = 0;
176 int len;
177 int a, a1, a2;
178 int t;
179 int b;
180 int i;
181 uint8 sum;
182 int hi16 = 0;
184 for (i=0; i<ROM_BYTES; i++)
185 rom_mem[i] = 0xff;
187 if (f != NULL)
189 while ((c = fgetc (f)) != EOF)
191 if ((c == '\r') || (c == '\n'))
192 continue;
194 if (c != ':' ||
195 (len = read_hex_byte (f)) < 0 ||
196 (a1 = read_hex_byte (f)) < 0 ||
197 (a2 = read_hex_byte (f)) < 0 ||
198 (t = read_hex_byte (f)) < 0)
199 break;
201 a = (a1 << 8) + a2;
203 i = 0;
204 sum = len + a1 + a2 + t;
206 if (t == 0)
208 next0:
210 if (i < len)
212 unsigned long adr = ((unsigned long)hi16 << 16) + a - CODE_START;
214 if ((b = read_hex_byte (f)) < 0)
215 break;
217 if (adr >= 0 && adr < ROM_BYTES)
218 rom_mem[adr] = b;
220 a = (a + 1) & 0xffff;
221 i++;
222 sum += b;
224 goto next0;
227 else if (t == 1)
229 if (len != 0)
230 break;
232 else if (t == 4)
234 if (len != 2)
235 break;
237 if ((a1 = read_hex_byte (f)) < 0 ||
238 (a2 = read_hex_byte (f)) < 0)
239 break;
241 sum += a1 + a2;
243 hi16 = (a1<<8) + a2;
245 else
246 break;
248 if ((b = read_hex_byte (f)) < 0)
249 break;
251 sum = -sum;
253 if (sum != b)
255 printf ("*** HEX file checksum error (expected 0x%02x)\n", sum);
256 break;
259 c = fgetc (f);
261 if ((c != '\r') && (c != '\n'))
262 break;
264 if (t == 1)
266 result = 1;
267 break;
271 if (result == 0)
272 printf ("*** HEX file syntax error\n");
274 fclose (f);
277 return result;
280 #endif
282 /*---------------------------------------------------------------------------*/
284 /* #ifdef ROBOT */
285 // TODO since picobit-vm.h can now contain code (with LESS_MACROS), including
286 // the header in each results in multiple definitions of these functions.
287 // no separate compilation
288 #include "debug.c"
289 #include "gc.c"
290 #include "bignums.c"
291 #include "primitives.c"
292 #include "dispatch.c"
293 /* #endif */
295 /*---------------------------------------------------------------------------*/
297 #ifdef WORKSTATION
299 void usage ()
301 printf ("usage: sim file.hex\n");
302 exit (1);
305 int main (int argc, char *argv[])
307 int errcode = 0;
308 rom_addr rom_start_addr = 0;
310 #ifdef TEST_BIGNUM
311 test();
312 #endif
314 if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 's')
316 int h1;
317 int h2;
318 int h3;
319 int h4;
321 if ((h1 = hex (argv[1][2])) < 0 ||
322 (h2 = hex (argv[1][3])) < 0 ||
323 (h3 = hex (argv[1][4])) != 0 ||
324 (h4 = hex (argv[1][5])) != 0 ||
325 argv[1][6] != '\0')
326 usage ();
328 rom_start_addr = (h1 << 12) | (h2 << 8) | (h3 << 4) | h4;
330 argv++;
331 argc--;
334 #ifdef DEBUG
335 printf ("Start address = 0x%04x\n", rom_start_addr + CODE_START);
336 #endif
338 if (argc != 2)
339 usage ();
341 if (!read_hex_file (argv[1]))
342 printf ("*** Could not read hex file \"%s\"\n", argv[1]);
343 else
345 int i;
347 if (rom_get (CODE_START+0) != 0xfb ||
348 rom_get (CODE_START+1) != 0xd7)
349 printf ("*** The hex file was not compiled with PICOBIT\n");
350 else
352 #if 0
353 for (i=0; i<8192; i++)
354 if (rom_get (i) != 0xff)
355 printf ("rom_mem[0x%04x] = 0x%02x\n", i, rom_get (i));
356 #endif
358 interpreter ();
360 #ifdef DEBUG_GC
361 printf ("**************** memory needed = %d\n", max_live+1);
362 #endif
366 return errcode;
369 #endif
371 #ifdef SIXPIC
372 interpreter();
373 #endif
375 #ifdef HI_TECH_C
376 void main () {
377 interpreter();
379 #endif