Added ior and xor tests to the repository.
[picobit/chj.git] / picobit-vm.c
blob9273b83ed86f7d431fa5afdde076464bfc81a0f7
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 // primitives
150 #ifndef INFINITE_PRECISION_BIGNUMS
152 // regular (finite, 24 bits) bignums
154 int32 decode_int (obj o) {
155 uint8 u;
156 uint8 h;
157 uint8 l;
159 if (o < MIN_FIXNUM_ENCODING)
160 TYPE_ERROR("decode_int.0", "integer");
162 if (o <= (MIN_FIXNUM_ENCODING + (MAX_FIXNUM - MIN_FIXNUM)))
163 return DECODE_FIXNUM(o);
165 if (IN_RAM(o)) {
166 if (!RAM_BIGNUM(o))
167 TYPE_ERROR("decode_int.1", "integer");
169 u = ram_get_field1 (o);
170 h = ram_get_field2 (o);
171 l = ram_get_field3 (o);
173 else if (IN_ROM(o)) {
174 if (!ROM_BIGNUM(o))
175 TYPE_ERROR("decode_int.2", "integer");
177 u = rom_get_field1 (o);
178 h = rom_get_field2 (o);
179 l = rom_get_field3 (o);
181 else
182 TYPE_ERROR("decode_int.3", "integer");
184 if (u >= 128) // negative
185 return ((int32)((((int16)u - 256) << 8) + h) << 8) + l;
187 return ((int32)(((int16)u << 8) + h) << 8) + l;
190 obj encode_int (int32 n) {
191 if (n >= MIN_FIXNUM && n <= MAX_FIXNUM)
192 return ENCODE_FIXNUM(n);
194 return alloc_ram_cell_init (BIGNUM_FIELD0, n >> 16, n >> 8, n);
197 #endif
199 void decode_2_int_args (void) {
200 a1 = decode_int (arg1);
201 a2 = decode_int (arg2);
204 /*---------------------------------------------------------------------------*/
206 #ifdef WORKSTATION
208 int hidden_fgetc (FILE *f)
210 int c = fgetc (f);
211 #if 0
212 printf ("{%d}",c);
213 fflush (stdout);
214 #endif
215 return c;
218 #define fgetc(f) hidden_fgetc(f)
220 void write_hex_nibble (int n)
222 putchar ("0123456789ABCDEF"[n]);
225 void write_hex (uint8 n)
227 write_hex_nibble (n >> 4);
228 write_hex_nibble (n & 0x0f);
231 int hex (int c)
233 if (c >= '0' && c <= '9')
234 return (c - '0');
236 if (c >= 'A' && c <= 'F')
237 return (c - 'A' + 10);
239 if (c >= 'a' && c <= 'f')
240 return (c - 'a' + 10);
242 return -1;
245 int read_hex_byte (FILE *f)
247 int h1 = hex (fgetc (f));
248 int h2 = hex (fgetc (f));
250 if (h1 >= 0 && h2 >= 0)
251 return (h1<<4) + h2;
253 return -1;
256 int read_hex_file (char *filename)
258 int c;
259 FILE *f = fopen (filename, "r");
260 int result = 0;
261 int len;
262 int a, a1, a2;
263 int t;
264 int b;
265 int i;
266 uint8 sum;
267 int hi16 = 0;
269 for (i=0; i<ROM_BYTES; i++)
270 rom_mem[i] = 0xff;
272 if (f != NULL)
274 while ((c = fgetc (f)) != EOF)
276 if ((c == '\r') || (c == '\n'))
277 continue;
279 if (c != ':' ||
280 (len = read_hex_byte (f)) < 0 ||
281 (a1 = read_hex_byte (f)) < 0 ||
282 (a2 = read_hex_byte (f)) < 0 ||
283 (t = read_hex_byte (f)) < 0)
284 break;
286 a = (a1 << 8) + a2;
288 i = 0;
289 sum = len + a1 + a2 + t;
291 if (t == 0)
293 next0:
295 if (i < len)
297 unsigned long adr = ((unsigned long)hi16 << 16) + a - CODE_START;
299 if ((b = read_hex_byte (f)) < 0)
300 break;
302 if (adr >= 0 && adr < ROM_BYTES)
303 rom_mem[adr] = b;
305 a = (a + 1) & 0xffff;
306 i++;
307 sum += b;
309 goto next0;
312 else if (t == 1)
314 if (len != 0)
315 break;
317 else if (t == 4)
319 if (len != 2)
320 break;
322 if ((a1 = read_hex_byte (f)) < 0 ||
323 (a2 = read_hex_byte (f)) < 0)
324 break;
326 sum += a1 + a2;
328 hi16 = (a1<<8) + a2;
330 else
331 break;
333 if ((b = read_hex_byte (f)) < 0)
334 break;
336 sum = -sum;
338 if (sum != b)
340 printf ("*** HEX file checksum error (expected 0x%02x)\n", sum);
341 break;
344 c = fgetc (f);
346 if ((c != '\r') && (c != '\n'))
347 break;
349 if (t == 1)
351 result = 1;
352 break;
356 if (result == 0)
357 printf ("*** HEX file syntax error\n");
359 fclose (f);
362 return result;
365 #endif
367 /*---------------------------------------------------------------------------*/
369 #ifdef WORKSTATION
371 void usage (void)
373 printf ("usage: sim file.hex\n");
374 exit (1);
377 int main (int argc, char *argv[])
379 int errcode = 1;
380 rom_addr rom_start_addr = 0;
382 #ifdef TEST_BIGNUM
383 test();
384 #endif
386 if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 's')
388 int h1;
389 int h2;
390 int h3;
391 int h4;
393 if ((h1 = hex (argv[1][2])) < 0 ||
394 (h2 = hex (argv[1][3])) < 0 ||
395 (h3 = hex (argv[1][4])) != 0 ||
396 (h4 = hex (argv[1][5])) != 0 ||
397 argv[1][6] != '\0')
398 usage ();
400 rom_start_addr = (h1 << 12) | (h2 << 8) | (h3 << 4) | h4;
402 argv++;
403 argc--;
406 #ifdef DEBUG
407 printf ("Start address = 0x%04x\n", rom_start_addr + CODE_START);
408 #endif
410 if (argc != 2)
411 usage ();
413 if (!read_hex_file (argv[1]))
414 printf ("*** Could not read hex file \"%s\"\n", argv[1]);
415 else
417 int i;
419 if (rom_get (CODE_START+0) != 0xfb ||
420 rom_get (CODE_START+1) != 0xd7)
421 printf ("*** The hex file was not compiled with PICOBIT\n");
422 else
424 #if 0
425 for (i=0; i<8192; i++)
426 if (rom_get (i) != 0xff)
427 printf ("rom_mem[0x%04x] = 0x%02x\n", i, rom_get (i));
428 #endif
430 interpreter ();
432 #ifdef DEBUG_GC
433 printf ("**************** memory needed = %d\n", max_live+1);
434 #endif
438 return errcode;
441 #endif