ca7a8c0894e2c221e3804113390d8beb565061e3
[picobit.git] / picobit-vm.c
blobca7a8c0894e2c221e3804113390d8beb565061e3
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_field0 (o) & 0x1f;
96 uint16 tmp2 = ram_get_field1 (o);
97 return ((tmp << 11) | (tmp2 << 3) | (ram_get_field2 (o) >> 5));
99 obj rom_get_entry (obj o){
100 uint16 tmp = rom_get_field0 (o) & 0x1f;
101 uint16 tmp2 = rom_get_field1 (o);
102 return ((tmp << 11) | (tmp2 << 3) | (rom_get_field2 (o) >> 5));
105 obj get_global (uint8 i) {
106 // globals occupy the beginning of ram, with 2 globals per word
107 if (i & 1)
108 return ram_get_cdr (MIN_RAM_ENCODING + (i >> 1));
109 else
110 return ram_get_car (MIN_RAM_ENCODING + (i >> 1));
112 void set_global (uint8 i, obj o) {
113 if (i & 1)
114 ram_set_cdr (MIN_RAM_ENCODING + (i >> 1), o);
115 else
116 ram_set_car (MIN_RAM_ENCODING + (i >> 1), o);
119 // TODO generic functions (get_field0, get_car, etc) that work for both rom and ram were not used, are in garbage
121 /*---------------------------------------------------------------------------*/
123 #ifdef WORKSTATION
125 int hidden_fgetc (FILE *f)
127 int c = fgetc (f);
128 #if 0
129 printf ("{%d}",c);
130 fflush (stdout);
131 #endif
132 return c;
135 #define fgetc(f) hidden_fgetc(f)
137 void write_hex_nibble (int n)
139 putchar ("0123456789ABCDEF"[n]);
142 void write_hex (uint8 n)
144 write_hex_nibble (n >> 4);
145 write_hex_nibble (n & 0x0f);
148 int hex (int c)
150 if (c >= '0' && c <= '9')
151 return (c - '0');
153 if (c >= 'A' && c <= 'F')
154 return (c - 'A' + 10);
156 if (c >= 'a' && c <= 'f')
157 return (c - 'a' + 10);
159 return -1;
162 int read_hex_byte (FILE *f)
164 int h1 = hex (fgetc (f));
165 int h2 = hex (fgetc (f));
167 if (h1 >= 0 && h2 >= 0)
168 return (h1<<4) + h2;
170 return -1;
173 int read_hex_file (char *filename)
175 int c;
176 FILE *f = fopen (filename, "r");
177 int result = 0;
178 int len;
179 int a, a1, a2;
180 int t;
181 int b;
182 int i;
183 uint8 sum;
184 int hi16 = 0;
186 for (i=0; i<ROM_BYTES; i++)
187 rom_mem[i] = 0xff;
189 if (f != NULL)
191 while ((c = fgetc (f)) != EOF)
193 if ((c == '\r') || (c == '\n'))
194 continue;
196 if (c != ':' ||
197 (len = read_hex_byte (f)) < 0 ||
198 (a1 = read_hex_byte (f)) < 0 ||
199 (a2 = read_hex_byte (f)) < 0 ||
200 (t = read_hex_byte (f)) < 0)
201 break;
203 a = (a1 << 8) + a2;
205 i = 0;
206 sum = len + a1 + a2 + t;
208 if (t == 0)
210 next0:
212 if (i < len)
214 unsigned long adr = ((unsigned long)hi16 << 16) + a - CODE_START;
216 if ((b = read_hex_byte (f)) < 0)
217 break;
219 if (adr >= 0 && adr < ROM_BYTES)
220 rom_mem[adr] = b;
222 a = (a + 1) & 0xffff;
223 i++;
224 sum += b;
226 goto next0;
229 else if (t == 1)
231 if (len != 0)
232 break;
234 else if (t == 4)
236 if (len != 2)
237 break;
239 if ((a1 = read_hex_byte (f)) < 0 ||
240 (a2 = read_hex_byte (f)) < 0)
241 break;
243 sum += a1 + a2;
245 hi16 = (a1<<8) + a2;
247 else
248 break;
250 if ((b = read_hex_byte (f)) < 0)
251 break;
253 sum = -sum;
255 if (sum != b)
257 printf ("*** HEX file checksum error (expected 0x%02x)\n", sum);
258 break;
261 c = fgetc (f);
263 if ((c != '\r') && (c != '\n'))
264 break;
266 if (t == 1)
268 result = 1;
269 break;
273 if (result == 0)
274 printf ("*** HEX file syntax error\n");
276 fclose (f);
279 return result;
282 #endif
284 /*---------------------------------------------------------------------------*/
286 #ifdef ROBOT
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