Removed code that dealt with ROM closure, since these don't exist.
[picobit.git] / picobit-vm.c
blobbd163709e1618345ef718fe4f4ac85c0dcf05663
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));
99 obj get_global (uint8 i) {
100 // globals occupy the beginning of ram, with 2 globals per word
101 if (i & 1)
102 return ram_get_cdr (MIN_RAM_ENCODING + (i >> 1));
103 else
104 return ram_get_car (MIN_RAM_ENCODING + (i >> 1));
106 void set_global (uint8 i, obj o) {
107 if (i & 1)
108 ram_set_cdr (MIN_RAM_ENCODING + (i >> 1), o);
109 else
110 ram_set_car (MIN_RAM_ENCODING + (i >> 1), o);
113 // TODO generic functions (get_field0, get_car, etc) that work for both rom and ram were not used, are in garbage
115 /*---------------------------------------------------------------------------*/
117 #ifdef WORKSTATION
119 int hidden_fgetc (FILE *f)
121 int c = fgetc (f);
122 #if 0
123 printf ("{%d}",c);
124 fflush (stdout);
125 #endif
126 return c;
129 #define fgetc(f) hidden_fgetc(f)
131 void write_hex_nibble (int n)
133 putchar ("0123456789ABCDEF"[n]);
136 void write_hex (uint8 n)
138 write_hex_nibble (n >> 4);
139 write_hex_nibble (n & 0x0f);
142 int hex (int c)
144 if (c >= '0' && c <= '9')
145 return (c - '0');
147 if (c >= 'A' && c <= 'F')
148 return (c - 'A' + 10);
150 if (c >= 'a' && c <= 'f')
151 return (c - 'a' + 10);
153 return -1;
156 int read_hex_byte (FILE *f)
158 int h1 = hex (fgetc (f));
159 int h2 = hex (fgetc (f));
161 if (h1 >= 0 && h2 >= 0)
162 return (h1<<4) + h2;
164 return -1;
167 int read_hex_file (char *filename)
169 int c;
170 FILE *f = fopen (filename, "r");
171 int result = 0;
172 int len;
173 int a, a1, a2;
174 int t;
175 int b;
176 int i;
177 uint8 sum;
178 int hi16 = 0;
180 for (i=0; i<ROM_BYTES; i++)
181 rom_mem[i] = 0xff;
183 if (f != NULL)
185 while ((c = fgetc (f)) != EOF)
187 if ((c == '\r') || (c == '\n'))
188 continue;
190 if (c != ':' ||
191 (len = read_hex_byte (f)) < 0 ||
192 (a1 = read_hex_byte (f)) < 0 ||
193 (a2 = read_hex_byte (f)) < 0 ||
194 (t = read_hex_byte (f)) < 0)
195 break;
197 a = (a1 << 8) + a2;
199 i = 0;
200 sum = len + a1 + a2 + t;
202 if (t == 0)
204 next0:
206 if (i < len)
208 unsigned long adr = ((unsigned long)hi16 << 16) + a - CODE_START;
210 if ((b = read_hex_byte (f)) < 0)
211 break;
213 if (adr >= 0 && adr < ROM_BYTES)
214 rom_mem[adr] = b;
216 a = (a + 1) & 0xffff;
217 i++;
218 sum += b;
220 goto next0;
223 else if (t == 1)
225 if (len != 0)
226 break;
228 else if (t == 4)
230 if (len != 2)
231 break;
233 if ((a1 = read_hex_byte (f)) < 0 ||
234 (a2 = read_hex_byte (f)) < 0)
235 break;
237 sum += a1 + a2;
239 hi16 = (a1<<8) + a2;
241 else
242 break;
244 if ((b = read_hex_byte (f)) < 0)
245 break;
247 sum = -sum;
249 if (sum != b)
251 printf ("*** HEX file checksum error (expected 0x%02x)\n", sum);
252 break;
255 c = fgetc (f);
257 if ((c != '\r') && (c != '\n'))
258 break;
260 if (t == 1)
262 result = 1;
263 break;
267 if (result == 0)
268 printf ("*** HEX file syntax error\n");
270 fclose (f);
273 return result;
276 #endif
278 /*---------------------------------------------------------------------------*/
280 /* #ifdef ROBOT */
281 // TODO since picobit-vm.h can now contain code (with LESS_MACROS), including
282 // the header in each results in multiple definitions of these functions.
283 // no separate compilation
284 #include "debug.c"
285 #include "gc.c"
286 #include "bignums.c"
287 #include "primitives.c"
288 #include "dispatch.c"
289 /* #endif */
291 /*---------------------------------------------------------------------------*/
293 #ifdef WORKSTATION
295 void usage ()
297 printf ("usage: sim file.hex\n");
298 exit (1);
301 int main (int argc, char *argv[])
303 int errcode = 0;
304 rom_addr rom_start_addr = 0;
306 #ifdef TEST_BIGNUM
307 test();
308 #endif
310 if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 's')
312 int h1;
313 int h2;
314 int h3;
315 int h4;
317 if ((h1 = hex (argv[1][2])) < 0 ||
318 (h2 = hex (argv[1][3])) < 0 ||
319 (h3 = hex (argv[1][4])) != 0 ||
320 (h4 = hex (argv[1][5])) != 0 ||
321 argv[1][6] != '\0')
322 usage ();
324 rom_start_addr = (h1 << 12) | (h2 << 8) | (h3 << 4) | h4;
326 argv++;
327 argc--;
330 #ifdef DEBUG
331 printf ("Start address = 0x%04x\n", rom_start_addr + CODE_START);
332 #endif
334 if (argc != 2)
335 usage ();
337 if (!read_hex_file (argv[1]))
338 printf ("*** Could not read hex file \"%s\"\n", argv[1]);
339 else
341 int i;
343 if (rom_get (CODE_START+0) != 0xfb ||
344 rom_get (CODE_START+1) != 0xd7)
345 printf ("*** The hex file was not compiled with PICOBIT\n");
346 else
348 #if 0
349 for (i=0; i<8192; i++)
350 if (rom_get (i) != 0xff)
351 printf ("rom_mem[0x%04x] = 0x%02x\n", i, rom_get (i));
352 #endif
354 interpreter ();
356 #ifdef DEBUG_GC
357 printf ("**************** memory needed = %d\n", max_live+1);
358 #endif
362 return errcode;
365 #endif
367 #ifdef SIXPIC
368 interpreter();
369 #endif
371 #ifdef HI_TECH_C
372 void main () {
373 interpreter();
375 #endif