1 /* file: "picobit-vm.c" */
4 * Copyright 2004-2009 by Marc Feeley and Vincent St-Amour, All Rights Reserved.
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 /*---------------------------------------------------------------------------*/
21 void error (char *prim
, char *msg
) {
22 printf ("ERROR: %s: %s\n", prim
, msg
);
26 void type_error (char *prim
, char *type
) {
27 printf ("ERROR: %s: An argument of type %s was expected\n", prim
, type
);
33 void halt_with_error () {
43 /*---------------------------------------------------------------------------*/
47 word
ram_get_fieldn (obj o
, word 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 ?
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
108 return ram_get_cdr (MIN_RAM_ENCODING
+ (i
>> 1));
110 return ram_get_car (MIN_RAM_ENCODING
+ (i
>> 1));
112 void set_global (uint8 i
, obj o
) {
114 ram_set_cdr (MIN_RAM_ENCODING
+ (i
>> 1), o
);
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 /*---------------------------------------------------------------------------*/
125 int hidden_fgetc (FILE *f
)
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);
150 if (c
>= '0' && c
<= '9')
153 if (c
>= 'A' && c
<= 'F')
154 return (c
- 'A' + 10);
156 if (c
>= 'a' && c
<= 'f')
157 return (c
- 'a' + 10);
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)
173 int read_hex_file (char *filename
)
176 FILE *f
= fopen (filename
, "r");
186 for (i
=0; i
<ROM_BYTES
; i
++)
191 while ((c
= fgetc (f
)) != EOF
)
193 if ((c
== '\r') || (c
== '\n'))
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)
206 sum
= len
+ a1
+ a2
+ t
;
214 unsigned long adr
= ((unsigned long)hi16
<< 16) + a
- CODE_START
;
216 if ((b
= read_hex_byte (f
)) < 0)
219 if (adr
>= 0 && adr
< ROM_BYTES
)
222 a
= (a
+ 1) & 0xffff;
239 if ((a1
= read_hex_byte (f
)) < 0 ||
240 (a2
= read_hex_byte (f
)) < 0)
250 if ((b
= read_hex_byte (f
)) < 0)
257 printf ("*** HEX file checksum error (expected 0x%02x)\n", sum
);
263 if ((c
!= '\r') && (c
!= '\n'))
274 printf ("*** HEX file syntax error\n");
284 /*---------------------------------------------------------------------------*/
287 // TODO since picobit-vm.h can now contain code (with LESS_MACROS), including
288 // the header in each results in multiple definitions of these functions.
289 // no separate compilation
293 #include "primitives.c"
294 #include "dispatch.c"
297 /*---------------------------------------------------------------------------*/
303 printf ("usage: sim file.hex\n");
307 int main (int argc
, char *argv
[])
310 rom_addr rom_start_addr
= 0;
316 if (argc
> 1 && argv
[1][0] == '-' && argv
[1][1] == 's')
323 if ((h1
= hex (argv
[1][2])) < 0 ||
324 (h2
= hex (argv
[1][3])) < 0 ||
325 (h3
= hex (argv
[1][4])) != 0 ||
326 (h4
= hex (argv
[1][5])) != 0 ||
330 rom_start_addr
= (h1
<< 12) | (h2
<< 8) | (h3
<< 4) | h4
;
337 printf ("Start address = 0x%04x\n", rom_start_addr
+ CODE_START
);
343 if (!read_hex_file (argv
[1]))
344 printf ("*** Could not read hex file \"%s\"\n", argv
[1]);
349 if (rom_get (CODE_START
+0) != 0xfb ||
350 rom_get (CODE_START
+1) != 0xd7)
351 printf ("*** The hex file was not compiled with PICOBIT\n");
355 for (i
=0; i
<8192; i
++)
356 if (rom_get (i
) != 0xff)
357 printf ("rom_mem[0x%04x] = 0x%02x\n", i
, rom_get (i
));
363 printf ("**************** memory needed = %d\n", max_live
+1);