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_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
102 return ram_get_cdr (MIN_RAM_ENCODING
+ (i
>> 1));
104 return ram_get_car (MIN_RAM_ENCODING
+ (i
>> 1));
106 void set_global (uint8 i
, obj o
) {
108 ram_set_cdr (MIN_RAM_ENCODING
+ (i
>> 1), o
);
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 /*---------------------------------------------------------------------------*/
119 int hidden_fgetc (FILE *f
)
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);
144 if (c
>= '0' && c
<= '9')
147 if (c
>= 'A' && c
<= 'F')
148 return (c
- 'A' + 10);
150 if (c
>= 'a' && c
<= 'f')
151 return (c
- 'a' + 10);
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)
167 int read_hex_file (char *filename
)
170 FILE *f
= fopen (filename
, "r");
180 for (i
=0; i
<ROM_BYTES
; i
++)
185 while ((c
= fgetc (f
)) != EOF
)
187 if ((c
== '\r') || (c
== '\n'))
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)
200 sum
= len
+ a1
+ a2
+ t
;
208 unsigned long adr
= ((unsigned long)hi16
<< 16) + a
- CODE_START
;
210 if ((b
= read_hex_byte (f
)) < 0)
213 if (adr
>= 0 && adr
< ROM_BYTES
)
216 a
= (a
+ 1) & 0xffff;
233 if ((a1
= read_hex_byte (f
)) < 0 ||
234 (a2
= read_hex_byte (f
)) < 0)
244 if ((b
= read_hex_byte (f
)) < 0)
251 printf ("*** HEX file checksum error (expected 0x%02x)\n", sum
);
257 if ((c
!= '\r') && (c
!= '\n'))
268 printf ("*** HEX file syntax error\n");
278 /*---------------------------------------------------------------------------*/
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
287 #include "primitives.c"
288 #include "dispatch.c"
291 /*---------------------------------------------------------------------------*/
297 printf ("usage: sim file.hex\n");
301 int main (int argc
, char *argv
[])
304 rom_addr rom_start_addr
= 0;
310 if (argc
> 1 && argv
[1][0] == '-' && argv
[1][1] == 's')
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 ||
324 rom_start_addr
= (h1
<< 12) | (h2
<< 8) | (h3
<< 4) | h4
;
331 printf ("Start address = 0x%04x\n", rom_start_addr
+ CODE_START
);
337 if (!read_hex_file (argv
[1]))
338 printf ("*** Could not read hex file \"%s\"\n", argv
[1]);
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");
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
));
357 printf ("**************** memory needed = %d\n", max_live
+1);