Moved some code around.
[picobit/chj.git] / picobit-vm.c
blobb9d17674e0e6ccf1b439cbbd12fedfb306f89c47
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 /*---------------------------------------------------------------------------*/
34 // memory access
36 #ifdef WORKSTATION
37 uint8 rom_mem[ROM_BYTES] =
39 #define RED_GREEN
40 #define PUTCHAR_LIGHT_not
41 #ifdef RED_GREEN
42 0xFB, 0xD7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x32
43 , 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
44 , 0x08, 0x50, 0x80, 0x16, 0xFE, 0xE8, 0x00, 0xFC
45 , 0x32, 0x80, 0x2D, 0xFE, 0xFC, 0x31, 0x80, 0x43
46 , 0xFE, 0xFC, 0x33, 0x80, 0x2D, 0xFE, 0xFC, 0x31
47 , 0x80, 0x43, 0xFE, 0x90, 0x16, 0x01, 0x20, 0xFC
48 , 0x32, 0xE3, 0xB0, 0x37, 0x09, 0xF3, 0xFF, 0x20
49 , 0xFC, 0x33, 0xE3, 0xB0, 0x40, 0x0A, 0xF3, 0xFF
50 , 0x08, 0xF3, 0xFF, 0x01, 0x40, 0x21, 0xD1, 0x00
51 , 0x02, 0xC0, 0x4C, 0x71, 0x01, 0x20, 0x50, 0x90
52 , 0x51, 0x00, 0xF1, 0x40, 0xD8, 0xB0, 0x59, 0x90
53 , 0x51, 0x00, 0xFF
54 #endif
55 #ifdef PUTCHAR_LIGHT
56 0xFB, 0xD7, 0x00, 0x00, 0x80, 0x08, 0xFE, 0xE8
57 , 0x00, 0xF6, 0xF5, 0x90, 0x08
58 #endif
60 uint8 rom_get (rom_addr a) {
61 return rom_mem[a-CODE_START];
63 #endif
65 word ram_get_gc_tags (obj o) { return RAM_GET_GC_TAGS_MACRO(o); }
66 word ram_get_gc_tag0 (obj o) { return RAM_GET_GC_TAG0_MACRO(o); }
67 word ram_get_gc_tag1 (obj o) { return RAM_GET_GC_TAG1_MACRO(o); }
68 void ram_set_gc_tags (obj o, word tags) { RAM_SET_GC_TAGS_MACRO(o, tags); }
69 void ram_set_gc_tag0 (obj o, word tag) { RAM_SET_GC_TAG0_MACRO(o,tag); }
70 void ram_set_gc_tag1 (obj o, word tag) { RAM_SET_GC_TAG1_MACRO(o,tag); }
71 word ram_get_field0 (obj o) { return RAM_GET_FIELD0_MACRO(o); }
72 word ram_get_field1 (obj o) { return RAM_GET_FIELD1_MACRO(o); }
73 word ram_get_field2 (obj o) { return RAM_GET_FIELD2_MACRO(o); }
74 word ram_get_field3 (obj o) { return RAM_GET_FIELD3_MACRO(o); }
75 word ram_get_fieldn (obj o, word n) { // TODO have as a macro ?
76 switch (n) {
77 case 0: return ram_get_field0 (o);
78 case 1: return ram_get_field1 (o);
79 case 2: return ram_get_field2 (o);
80 case 3: return ram_get_field3 (o);
83 void ram_set_field0 (obj o, word val) { RAM_SET_FIELD0_MACRO(o,val); }
84 void ram_set_field1 (obj o, word val) { RAM_SET_FIELD1_MACRO(o,val); }
85 void ram_set_field2 (obj o, word val) { RAM_SET_FIELD2_MACRO(o,val); }
86 void ram_set_field3 (obj o, word val) { RAM_SET_FIELD3_MACRO(o,val); }
87 void ram_set_fieldn (obj o, uint8 n, word val) { // TODO have as a macro ?
88 switch (n) {
89 case 0: ram_set_field0 (o, val); break;
90 case 1: ram_set_field1 (o, val); break;
91 case 2: ram_set_field2 (o, val); break;
92 case 3: ram_set_field3 (o, val); break;
95 word rom_get_field0 (obj o) { return ROM_GET_FIELD0_MACRO(o); }
96 word rom_get_field1 (obj o) { return ROM_GET_FIELD1_MACRO(o); }
97 word rom_get_field2 (obj o) { return ROM_GET_FIELD2_MACRO(o); }
98 word rom_get_field3 (obj o) { return ROM_GET_FIELD3_MACRO(o); }
100 obj ram_get_car (obj o)
101 { return ((ram_get_field0 (o) & 0x1f) << 8) | ram_get_field1 (o); }
102 obj rom_get_car (obj o)
103 { return ((rom_get_field0 (o) & 0x1f) << 8) | rom_get_field1 (o); }
104 obj ram_get_cdr (obj o)
105 { return ((ram_get_field2 (o) & 0x1f) << 8) | ram_get_field3 (o); }
106 obj rom_get_cdr (obj o)
107 { return ((rom_get_field2 (o) & 0x1f) << 8) | rom_get_field3 (o); }
109 void ram_set_car (obj o, obj val) {
110 ram_set_field0 (o, (val >> 8) | (ram_get_field0 (o) & 0xe0));
111 ram_set_field1 (o, val & 0xff);
113 void ram_set_cdr (obj o, obj val) {
114 ram_set_field2 (o, (val >> 8) | (ram_get_field2 (o) & 0xe0));
115 ram_set_field3 (o, val & 0xff);
118 // function entry point
119 obj ram_get_entry (obj o) {
120 return (((ram_get_field0 (o) & 0x1f) << 11)
121 | (ram_get_field1 (o) << 3)
122 | (ram_get_field2 (o) >> 5));
124 obj rom_get_entry (obj o){
125 return (((rom_get_field0 (o) & 0x1f) << 11)
126 | (rom_get_field1 (o) << 3)
127 | (rom_get_field2 (o) >> 5));
130 obj get_global (uint8 i) {
131 // globals occupy the beginning of ram, with 2 globals per word
132 if (i & 1)
133 return ram_get_cdr (MIN_RAM_ENCODING + (i / 2));
134 else
135 return ram_get_car (MIN_RAM_ENCODING + (i / 2));
137 void set_global (uint8 i, obj o) {
138 if (i & 1)
139 ram_set_cdr (MIN_RAM_ENCODING + (i / 2), o);
140 else
141 ram_set_car (MIN_RAM_ENCODING + (i / 2), o);
144 // TODO generic functions (get_field0, get_car, etc) that work for both rom and ram were not used, are in garbage
146 /*---------------------------------------------------------------------------*/
148 #ifdef WORKSTATION
150 int hidden_fgetc (FILE *f)
152 int c = fgetc (f);
153 #if 0
154 printf ("{%d}",c);
155 fflush (stdout);
156 #endif
157 return c;
160 #define fgetc(f) hidden_fgetc(f)
162 void write_hex_nibble (int n)
164 putchar ("0123456789ABCDEF"[n]);
167 void write_hex (uint8 n)
169 write_hex_nibble (n >> 4);
170 write_hex_nibble (n & 0x0f);
173 int hex (int c)
175 if (c >= '0' && c <= '9')
176 return (c - '0');
178 if (c >= 'A' && c <= 'F')
179 return (c - 'A' + 10);
181 if (c >= 'a' && c <= 'f')
182 return (c - 'a' + 10);
184 return -1;
187 int read_hex_byte (FILE *f)
189 int h1 = hex (fgetc (f));
190 int h2 = hex (fgetc (f));
192 if (h1 >= 0 && h2 >= 0)
193 return (h1<<4) + h2;
195 return -1;
198 int read_hex_file (char *filename)
200 int c;
201 FILE *f = fopen (filename, "r");
202 int result = 0;
203 int len;
204 int a, a1, a2;
205 int t;
206 int b;
207 int i;
208 uint8 sum;
209 int hi16 = 0;
211 for (i=0; i<ROM_BYTES; i++)
212 rom_mem[i] = 0xff;
214 if (f != NULL)
216 while ((c = fgetc (f)) != EOF)
218 if ((c == '\r') || (c == '\n'))
219 continue;
221 if (c != ':' ||
222 (len = read_hex_byte (f)) < 0 ||
223 (a1 = read_hex_byte (f)) < 0 ||
224 (a2 = read_hex_byte (f)) < 0 ||
225 (t = read_hex_byte (f)) < 0)
226 break;
228 a = (a1 << 8) + a2;
230 i = 0;
231 sum = len + a1 + a2 + t;
233 if (t == 0)
235 next0:
237 if (i < len)
239 unsigned long adr = ((unsigned long)hi16 << 16) + a - CODE_START;
241 if ((b = read_hex_byte (f)) < 0)
242 break;
244 if (adr >= 0 && adr < ROM_BYTES)
245 rom_mem[adr] = b;
247 a = (a + 1) & 0xffff;
248 i++;
249 sum += b;
251 goto next0;
254 else if (t == 1)
256 if (len != 0)
257 break;
259 else if (t == 4)
261 if (len != 2)
262 break;
264 if ((a1 = read_hex_byte (f)) < 0 ||
265 (a2 = read_hex_byte (f)) < 0)
266 break;
268 sum += a1 + a2;
270 hi16 = (a1<<8) + a2;
272 else
273 break;
275 if ((b = read_hex_byte (f)) < 0)
276 break;
278 sum = -sum;
280 if (sum != b)
282 printf ("*** HEX file checksum error (expected 0x%02x)\n", sum);
283 break;
286 c = fgetc (f);
288 if ((c != '\r') && (c != '\n'))
289 break;
291 if (t == 1)
293 result = 1;
294 break;
298 if (result == 0)
299 printf ("*** HEX file syntax error\n");
301 fclose (f);
304 return result;
307 #endif
309 /*---------------------------------------------------------------------------*/
311 #ifdef PICOBOARD2
312 // no separate compilation
313 #include "debug.c"
314 #include "gc.c"
315 #include "bignums.c"
316 #include "primitives.c"
317 #include "dispatch.c"
318 #endif
320 /*---------------------------------------------------------------------------*/
322 #ifdef WORKSTATION
324 void usage (void)
326 printf ("usage: sim file.hex\n");
327 exit (1);
330 int main (int argc, char *argv[])
332 int errcode = 1;
333 rom_addr rom_start_addr = 0;
335 #ifdef TEST_BIGNUM
336 test();
337 #endif
339 if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 's')
341 int h1;
342 int h2;
343 int h3;
344 int h4;
346 if ((h1 = hex (argv[1][2])) < 0 ||
347 (h2 = hex (argv[1][3])) < 0 ||
348 (h3 = hex (argv[1][4])) != 0 ||
349 (h4 = hex (argv[1][5])) != 0 ||
350 argv[1][6] != '\0')
351 usage ();
353 rom_start_addr = (h1 << 12) | (h2 << 8) | (h3 << 4) | h4;
355 argv++;
356 argc--;
359 #ifdef DEBUG
360 printf ("Start address = 0x%04x\n", rom_start_addr + CODE_START);
361 #endif
363 if (argc != 2)
364 usage ();
366 if (!read_hex_file (argv[1]))
367 printf ("*** Could not read hex file \"%s\"\n", argv[1]);
368 else
370 int i;
372 if (rom_get (CODE_START+0) != 0xfb ||
373 rom_get (CODE_START+1) != 0xd7)
374 printf ("*** The hex file was not compiled with PICOBIT\n");
375 else
377 #if 0
378 for (i=0; i<8192; i++)
379 if (rom_get (i) != 0xff)
380 printf ("rom_mem[0x%04x] = 0x%02x\n", i, rom_get (i));
381 #endif
383 interpreter ();
385 #ifdef DEBUG_GC
386 printf ("**************** memory needed = %d\n", max_live+1);
387 #endif
391 return errcode;
394 #endif