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
);
32 /*---------------------------------------------------------------------------*/
37 uint8 rom_mem
[ROM_BYTES
] =
40 #define PUTCHAR_LIGHT_not
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
56 0xFB, 0xD7, 0x00, 0x00, 0x80, 0x08, 0xFE, 0xE8
57 , 0x00, 0xF6, 0xF5, 0x90, 0x08
60 uint8
rom_get (rom_addr a
) {
61 return rom_mem
[a
-CODE_START
];
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 ?
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 ?
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
133 return ram_get_cdr (MIN_RAM_ENCODING
+ (i
/ 2));
135 return ram_get_car (MIN_RAM_ENCODING
+ (i
/ 2));
137 void set_global (uint8 i
, obj o
) {
139 ram_set_cdr (MIN_RAM_ENCODING
+ (i
/ 2), o
);
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 /*---------------------------------------------------------------------------*/
150 #ifndef INFINITE_PRECISION_BIGNUMS
152 // regular (finite, 24 bits) bignums
154 int32
decode_int (obj o
) {
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
);
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
)) {
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
);
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
);
199 void decode_2_int_args (void) {
200 a1
= decode_int (arg1
);
201 a2
= decode_int (arg2
);
204 /*---------------------------------------------------------------------------*/
208 int hidden_fgetc (FILE *f
)
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);
233 if (c
>= '0' && c
<= '9')
236 if (c
>= 'A' && c
<= 'F')
237 return (c
- 'A' + 10);
239 if (c
>= 'a' && c
<= 'f')
240 return (c
- 'a' + 10);
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)
256 int read_hex_file (char *filename
)
259 FILE *f
= fopen (filename
, "r");
269 for (i
=0; i
<ROM_BYTES
; i
++)
274 while ((c
= fgetc (f
)) != EOF
)
276 if ((c
== '\r') || (c
== '\n'))
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)
289 sum
= len
+ a1
+ a2
+ t
;
297 unsigned long adr
= ((unsigned long)hi16
<< 16) + a
- CODE_START
;
299 if ((b
= read_hex_byte (f
)) < 0)
302 if (adr
>= 0 && adr
< ROM_BYTES
)
305 a
= (a
+ 1) & 0xffff;
322 if ((a1
= read_hex_byte (f
)) < 0 ||
323 (a2
= read_hex_byte (f
)) < 0)
333 if ((b
= read_hex_byte (f
)) < 0)
340 printf ("*** HEX file checksum error (expected 0x%02x)\n", sum
);
346 if ((c
!= '\r') && (c
!= '\n'))
357 printf ("*** HEX file syntax error\n");
367 /*---------------------------------------------------------------------------*/
373 printf ("usage: sim file.hex\n");
377 int main (int argc
, char *argv
[])
380 rom_addr rom_start_addr
= 0;
386 if (argc
> 1 && argv
[1][0] == '-' && argv
[1][1] == 's')
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 ||
400 rom_start_addr
= (h1
<< 12) | (h2
<< 8) | (h3
<< 4) | h4
;
407 printf ("Start address = 0x%04x\n", rom_start_addr
+ CODE_START
);
413 if (!read_hex_file (argv
[1]))
414 printf ("*** Could not read hex file \"%s\"\n", argv
[1]);
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");
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
));
433 printf ("**************** memory needed = %d\n", max_live
+1);