BASIC compiler/interpreter for PIC32MX/MZ-80K
修訂 | e677a14f0b3a2cf6e37bdc7db4baeedee1abbb4d (tree) |
---|---|
時間 | 2019-05-13 09:13:02 |
作者 | Katsumi <kmorimatsu@sour...> |
Commiter | Katsumi |
USECLIB and CLIB statements & functions.
@@ -0,0 +1,329 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by K.Tanaka & Katsumi | |
4 | + http://www.ze.em-net.ne.jp/~kenken/index.html | |
5 | + http://hp.vector.co.jp/authors/VA016157/ | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include "compiler.h" | |
13 | +#include "api.h" | |
14 | +#include "main.h" | |
15 | + | |
16 | +/* | |
17 | + CMPDATA_USECLIB structure | |
18 | + type: CMPDATA_USECLIB (8) | |
19 | + len: 2 | |
20 | + data16: n/a (0) | |
21 | + record[1]: clib name as integer | |
22 | + | |
23 | + CMPDATA_CLIBFUNC structure | |
24 | + type: CMPDATA_CLIBFUNC (9) | |
25 | + len: 4 | |
26 | + data16: n/a (0) | |
27 | + record[1]: clib name as integer | |
28 | + record[2]: func name as integer | |
29 | + record[3]: pointer to function | |
30 | +*/ | |
31 | + | |
32 | +// CLIB name used (name as 31 bit integer) | |
33 | +static unsigned int g_clib; | |
34 | + | |
35 | +char* useclib_statement(){ | |
36 | + int i; | |
37 | + int* cmpdata; | |
38 | + do { | |
39 | + next_position(); | |
40 | + i=check_var_name(); | |
41 | + if (i<65536) return ERR_SYNTAX; | |
42 | + // Check if the clib already exists | |
43 | + cmpdata_reset(); | |
44 | + while(cmpdata=cmpdata_find(CMPDATA_USECLIB)){ | |
45 | + if (cmpdata[1]==i) { | |
46 | + // The clib was already defined. | |
47 | + i=0; | |
48 | + break; | |
49 | + } | |
50 | + } | |
51 | + if (i) { | |
52 | + // Load new file to define clib. | |
53 | + g_clib=i; | |
54 | + return ERR_COMPILE_CLIB; | |
55 | + } | |
56 | + if (g_source[g_srcpos]==',') { | |
57 | + g_srcpos++; | |
58 | + } else { | |
59 | + break; | |
60 | + } | |
61 | + } while(1); | |
62 | + return 0; | |
63 | +} | |
64 | + | |
65 | +/* | |
66 | + * g_data[] contains the data from MachiKania compiler for this library | |
67 | + * g_data[0] : lib_calloc_memory | |
68 | + * g_data[1] : lib_delete | |
69 | + * g_data[2] : g_gp | |
70 | + * g_data[3-]: Reserved for higher version of CLIB | |
71 | + */ | |
72 | +void* g_data_for_clib[]={ | |
73 | + lib_calloc_memory, | |
74 | + lib_delete, | |
75 | + 0, // = g_gp | |
76 | +}; | |
77 | + | |
78 | +void* call_clib_init(void** data, void* address){ | |
79 | + // Store gp and ra | |
80 | + asm volatile("#":::"s0"); | |
81 | + asm volatile("#":::"ra"); | |
82 | + asm volatile("addu $t9,$a1,$zero"); | |
83 | + asm volatile("addu $s0,$gp,$zero"); | |
84 | + asm volatile("jalr $ra,$t9"); | |
85 | + asm volatile("addu $gp,$s0,$zero"); | |
86 | +} | |
87 | + | |
88 | +char* clib_main(){ | |
89 | + char* err; | |
90 | + unsigned int begin,end,addr; | |
91 | + void* clibdata; | |
92 | + int* functions; | |
93 | + int* got; | |
94 | + int i,opos,adjust; | |
95 | + char* clib; | |
96 | + int record[3]; | |
97 | + // Insert CMPDATA_USELIB | |
98 | + record[0]=g_clib; | |
99 | + err=cmpdata_insert(CMPDATA_USECLIB,0,&record[0],1); | |
100 | + if (err) return err; | |
101 | + // Determine begin and end addresses | |
102 | + begin=0x000fffff; | |
103 | + end=0; | |
104 | + while(1){ | |
105 | + err=hex_read_line(); | |
106 | + if (err) return err; | |
107 | + if (g_hexline.type==1) { | |
108 | + // EOF | |
109 | + break; | |
110 | + } else if (g_hexline.type==4) { | |
111 | + // extended linear address | |
112 | + addr=g_hexline.data[0]; | |
113 | + addr=addr<<8; | |
114 | + addr|=g_hexline.data[0]; | |
115 | + addr=addr<<16; | |
116 | + } else if (g_hexline.type==0) { | |
117 | + // data | |
118 | + addr&=0xffff0000; | |
119 | + addr|=g_hexline.address; | |
120 | + if (addr<begin) begin=addr; | |
121 | + if (end<addr && addr<0x000fffff) { | |
122 | + end=addr+g_hexline.size; | |
123 | + } | |
124 | + } else { | |
125 | + // Unknown type | |
126 | + return ERR_HEX_ERROR; | |
127 | + } | |
128 | + } | |
129 | + hex_reinit_file(); | |
130 | + // Assign and clear region | |
131 | + check_obj_space((end-begin+3)>>2); | |
132 | + clib=(char*)&g_object[g_objpos]; | |
133 | + got=(int*)&g_object[g_objpos]; | |
134 | + for(i=0;i<((end-begin+3)>>2);i++) g_object[g_objpos++]=0; | |
135 | + // Load binary from HEX file | |
136 | + while(1){ | |
137 | + err=hex_read_line(); | |
138 | + if (err) return err; | |
139 | + if (g_hexline.type==1) { | |
140 | + // EOF | |
141 | + break; | |
142 | + } else if (g_hexline.type==4) { | |
143 | + // extended linear address | |
144 | + addr=g_hexline.data[0]; | |
145 | + addr=addr<<8; | |
146 | + addr|=g_hexline.data[0]; | |
147 | + addr=addr<<16; | |
148 | + } else if (g_hexline.type==0) { | |
149 | + // data | |
150 | + addr&=0xffff0000; | |
151 | + addr|=g_hexline.address; | |
152 | + for(i=0;i<g_hexline.size;i++){ | |
153 | + clib[addr-begin+i]=g_hexline.data[i]; | |
154 | + } | |
155 | + } else { | |
156 | + // Unknown type | |
157 | + return ERR_HEX_ERROR; | |
158 | + } | |
159 | + } | |
160 | + // Calculate the adjustment value. | |
161 | + // Note that the address of clib_init() is 0x8000. | |
162 | + adjust=(int)clib+0x8000-begin-0xA0008000; | |
163 | + // Modify Global Offset Table (GOT) | |
164 | + for(i=0;i<(0x8000-begin)>>2;i++){ | |
165 | + if ((got[i]&0xFFF00000)==0xA0000000) { | |
166 | + got[i]+=adjust; | |
167 | + } | |
168 | + } | |
169 | + // Prepare g_data_for_clib[] | |
170 | + g_data_for_clib[2]=(void*)g_gp; | |
171 | + // Call the clib_init() to get the address of clibdata array. | |
172 | + clibdata=call_clib_init(&g_data_for_clib[0],(void*)0xA0008000+adjust); | |
173 | + // Check version | |
174 | + if (((int*)clibdata)[0]>SYSVERI) { | |
175 | + return "Newer version of C library than MachiKania cannot be used."; | |
176 | + } | |
177 | + // Get functions array | |
178 | + clibdata=(void*)(((int*)clibdata)[2])+adjust; | |
179 | + functions=clibdata; | |
180 | + // Construct CMPDATA_CLIBFUNC records. | |
181 | + while(clib=(char*)functions[0]){ | |
182 | + clibdata=(void*)functions[1]; | |
183 | + functions+=2; | |
184 | + // clib is function name as string | |
185 | + // clibdata is address of C function | |
186 | + clib+=adjust; | |
187 | + clibdata+=adjust; | |
188 | + i=str_to_name_int(clib); | |
189 | + if (i<65536) return "Wrong C library function name"; | |
190 | + record[0]=g_clib; | |
191 | + record[1]=i; | |
192 | + record[2]=(int)clibdata; | |
193 | + err=cmpdata_insert(CMPDATA_CLIBFUNC,0,&record[0],3); | |
194 | + if (err) return err; | |
195 | + } | |
196 | + // Initial assembly is a jump statement to jump to the the following routine. | |
197 | + g_object[0]=0x08000000 | ((((int)(&g_object[g_objpos]))&0x0FFFFFFF)>>2); // j xxxxxxxx | |
198 | + // All done | |
199 | + return 0; | |
200 | +} | |
201 | + | |
202 | +char* useclib_begin(char* buff){ | |
203 | + int i,j,cwd_id; | |
204 | + char* err; | |
205 | + char* clibname; | |
206 | + char filename[11]; | |
207 | + int* record; | |
208 | + // Remove a objects before USECLIB statement | |
209 | + g_objpos=0; | |
210 | + // Insert twp NOP assemblies. This will be replaced by branch statement. | |
211 | + check_obj_space(2); | |
212 | + g_object[g_objpos++]=0x00000000; // nop | |
213 | + g_object[g_objpos++]=0x00000000; // nop | |
214 | + // Construct HEX file name to open | |
215 | + clibname=resolve_label(g_clib); | |
216 | + for(i=0;filename[i]=clibname[i];i++); | |
217 | + filename[i++]='.'; | |
218 | + filename[i++]='H'; | |
219 | + filename[i++]='E'; | |
220 | + filename[i++]='X'; | |
221 | + filename[i++]=0; | |
222 | + // Open file in current directory | |
223 | + err=hex_init_file(buff,filename); | |
224 | + if (!err) { | |
225 | + // HEX file found in current directory. | |
226 | + err=clib_main(); | |
227 | + hex_close_file(); | |
228 | + } else { | |
229 | + // Hex file not found in current directory. | |
230 | + // Find it in LIB directory. | |
231 | + if (!FSgetcwd(buff,256)) return ERR_UNKNOWN; | |
232 | + for(i=0;buff[i];i++); | |
233 | + cwd_id=cmpdata_get_id(); | |
234 | + if (!cwd_id) return ERR_UNKNOWN; | |
235 | + err=cmpdata_insert(CMPDATA_TEMP,cwd_id,(int*)(&buff[0]),(i+1+3)>>2); | |
236 | + if (err) return err; | |
237 | + // Change current directory to class library directory | |
238 | + for(i=0;buff[i]="\\LIB\\"[i];i++); | |
239 | + for(j=0;buff[i++]=clibname[j];j++); | |
240 | + buff[i]=0; | |
241 | + FSchdir(buff); | |
242 | + err=hex_init_file(buff,filename); | |
243 | + if (!err) { | |
244 | + // HEX file found in LIB directory | |
245 | + err=clib_main(); | |
246 | + hex_close_file(); | |
247 | + } else { | |
248 | + err=ERR_NO_CLIB; | |
249 | + } | |
250 | + // Restore current dirctory | |
251 | + cmpdata_reset(); | |
252 | + while(record=cmpdata_find(CMPDATA_TEMP)){ | |
253 | + if ((record[0]&0xffff)==cwd_id) break; | |
254 | + } | |
255 | + if (!record) return ERR_UNKNOWN; | |
256 | + FSchdir((char*)(&record[1])); | |
257 | + cmpdata_delete(record); | |
258 | + } | |
259 | + return err; | |
260 | +} | |
261 | + | |
262 | +void lib_clib(int* params, void* address){ | |
263 | + // Store gp and ra | |
264 | + asm volatile("#":::"s0"); | |
265 | + asm volatile("#":::"ra"); | |
266 | + asm volatile("addu $t9,$a1,$zero"); | |
267 | + asm volatile("addu $s0,$gp,$zero"); | |
268 | + asm volatile("lw $a3,16($a0)"); | |
269 | + asm volatile("lw $a2,12($a0)"); | |
270 | + asm volatile("lw $a1,8($a0)"); | |
271 | + asm volatile("lw $a0,4($a0)"); | |
272 | + asm volatile("jalr $ra,$t9"); | |
273 | + asm volatile("addu $gp,$s0,$zero"); | |
274 | +} | |
275 | + | |
276 | +char* clib_statement(){ | |
277 | + char* err; | |
278 | + int* record; | |
279 | + int clib,func; | |
280 | + int numparams,stack; | |
281 | + // CLIB name | |
282 | + next_position(); | |
283 | + clib=check_var_name(); | |
284 | + if (clib<65536) return ERR_SYNTAX; | |
285 | + // Check if the clib exists | |
286 | + cmpdata_reset(); | |
287 | + while (record=cmpdata_find(CMPDATA_USECLIB)){ | |
288 | + if (record[1]==clib) break; | |
289 | + } | |
290 | + if (!record) return ERR_NO_CLIB; | |
291 | + next_position(); | |
292 | + if (g_source[g_srcpos++]!=',') return ERR_SYNTAX; | |
293 | + // Function name | |
294 | + next_position(); | |
295 | + func=check_var_name(); | |
296 | + if (func<65536) return ERR_SYNTAX; | |
297 | + cmpdata_reset(); | |
298 | + while (record=cmpdata_find(CMPDATA_CLIBFUNC)){ | |
299 | + if (record[1]==clib && record[2]==func) break; | |
300 | + } | |
301 | + if (!record) return "Function not found in the C library"; | |
302 | + // Construct parameter(s) | |
303 | + next_position(); | |
304 | + numparams=0; | |
305 | + while (g_source[g_srcpos]==',') { | |
306 | + numparams++; | |
307 | + if (4<numparams) return ERR_SYNTAX; | |
308 | + else if (1==numparams) { | |
309 | + check_obj_space(1); | |
310 | + stack=g_objpos++; | |
311 | + } | |
312 | + g_srcpos++; | |
313 | + g_object[stack]=0x27BD0000|(65536-numparams*4); // addiu sp,sp,-xx | |
314 | + err=get_stringFloatOrValue(); | |
315 | + if (err) return err; | |
316 | + check_obj_space(1); | |
317 | + g_object[g_objpos++]=0xAFA20000|(numparams*4); // sw v0,xx(sp) | |
318 | + next_position(); | |
319 | + } | |
320 | + // Call CLIB | |
321 | + check_obj_space(2); | |
322 | + g_object[g_objpos++]=0x3C050000|(((unsigned int)record[3])>>16); // lui a1,xxxx | |
323 | + g_object[g_objpos++]=0x34A50000|(((unsigned int)record[3])&0x0000FFFF); // ori a1,a1,xxxx | |
324 | + call_quicklib_code(lib_clib,ASM_ADDU_A0_SP_ZERO); // All done | |
325 | + check_obj_space(1); | |
326 | + if (numparams) g_object[g_objpos++]=0x27BD0000|(numparams*4); // addiu sp,sp,xx | |
327 | + return 0; | |
328 | +} | |
329 | + |
@@ -40,6 +40,14 @@ | ||
40 | 40 | // RAM size used for object and heap |
41 | 41 | #define RAMSIZE (PERSISTENT_RAM_SIZE-EXCEPTION_DATA_SIZE) |
42 | 42 | |
43 | +/* Structures */ | |
44 | +typedef struct{ | |
45 | + unsigned char size; | |
46 | + unsigned short address; | |
47 | + unsigned char type; | |
48 | + unsigned char data[16]; | |
49 | +} HEXLINE; | |
50 | + | |
43 | 51 | /* Enums */ |
44 | 52 | enum variable{ |
45 | 53 | VAR_INTEGER, |
@@ -228,6 +236,7 @@ extern int g_class; | ||
228 | 236 | extern int g_compiling_class; |
229 | 237 | extern unsigned char g_num_classes; |
230 | 238 | extern char g_option_fastfield; |
239 | +extern HEXLINE g_hexline; | |
231 | 240 | extern int g_temp; |
232 | 241 | |
233 | 242 | /* Prototypes */ |
@@ -340,6 +349,7 @@ int* cmpdata_findfirst(unsigned char type); | ||
340 | 349 | void cmpdata_delete(int* record); |
341 | 350 | |
342 | 351 | int check_var_name(); |
352 | +int str_to_name_int(char* str); | |
343 | 353 | int get_var_number(); |
344 | 354 | int search_var_name(int nameint); |
345 | 355 | char* register_var_name(int nameint); |
@@ -384,6 +394,16 @@ char* coretimer_statement(); | ||
384 | 394 | char* coretimer_function(); |
385 | 395 | char* interrupt_statement(); |
386 | 396 | |
397 | +char* useclib_statement(); | |
398 | +char* useclib_begin(char* buff); | |
399 | +char* clib_statement(); | |
400 | + | |
401 | +char* hex_init_file(char* buff,char* filename); | |
402 | +void hex_reinit_file(); | |
403 | +void hex_close_file(); | |
404 | +char* hex_read_line(); | |
405 | +char* hex_construct_line(); | |
406 | + | |
387 | 407 | /* Error messages */ |
388 | 408 | #define ERR_SYNTAX (char*)(g_err_str[0]) |
389 | 409 | #define ERR_NE_BINARY (char*)(g_err_str[1]) |
@@ -415,6 +435,9 @@ char* interrupt_statement(); | ||
415 | 435 | #define ERR_INVALID_CLASS (char*)(g_err_str[27]) |
416 | 436 | #define ERR_NO_INIT (char*)(g_err_str[28]) |
417 | 437 | #define ERR_OPTION_CLASSCODE (char*)(g_err_str[29]) |
438 | +#define ERR_COMPILE_CLIB (char*)(g_err_str[30]) | |
439 | +#define ERR_NO_CLIB (char*)(g_err_str[31]) | |
440 | +#define ERR_HEX_ERROR (char*)(g_err_str[32]) | |
418 | 441 | |
419 | 442 | /* compile data type numbers */ |
420 | 443 | #define CMPDATA_RESERVED 0 |
@@ -425,6 +448,8 @@ char* interrupt_statement(); | ||
425 | 448 | #define CMPDATA_UNSOLVED 5 |
426 | 449 | #define CMPDATA_TEMP 6 |
427 | 450 | #define CMPDATA_FASTFIELD 7 |
451 | +#define CMPDATA_USECLIB 8 | |
452 | +#define CMPDATA_CLIBFUNC 9 | |
428 | 453 | // Sub types follow |
429 | 454 | #define CMPTYPE_PUBLIC_FIELD 0 |
430 | 455 | #define CMPTYPE_PRIVATE_FIELD 1 |
@@ -485,6 +510,7 @@ char* interrupt_statement(); | ||
485 | 510 | } while (0) |
486 | 511 | |
487 | 512 | #define ASM_NOP 0x00000000 |
513 | +#define ASM_ADDU_A0_SP_ZERO 0x03A02021 | |
488 | 514 | #define ASM_ADDU_A0_V0_ZERO 0x00402021 |
489 | 515 | #define ASM_ADDU_A1_V0_ZERO 0x00402821 |
490 | 516 | #define ASM_ADDU_A2_V0_ZERO 0x00403021 |
@@ -34,6 +34,7 @@ static const char initext[]; | ||
34 | 34 | static const char bastext[]; |
35 | 35 | static const char class1text[]; |
36 | 36 | static const char class2text[]; |
37 | +static const char hextext[]; | |
37 | 38 | |
38 | 39 | static char* readtext; |
39 | 40 | static int filepos; |
@@ -130,6 +131,9 @@ FSFILE* FSfopen(const char * fileName, const char *mode){ | ||
130 | 131 | } else if (fileName[i+1]=='I' && fileName[i+2]=='N' && fileName[i+3]=='I') { |
131 | 132 | // INI file |
132 | 133 | readtext=(char*)&initext[0]; |
134 | + } else if (fileName[i+1]=='H' && fileName[i+2]=='E' && fileName[i+3]=='X') { | |
135 | + // HEX file | |
136 | + readtext=(char*)&hextext[0]; | |
133 | 137 | } else if (fileName[i+1]=='B' && fileName[i+2]=='A' && fileName[i+3]=='S') { |
134 | 138 | // Select BAS file |
135 | 139 | if (fileName[i-6]=='C' && fileName[i-5]=='L' && fileName[i-4]=='A' && |
@@ -184,6 +188,7 @@ long FSftell (FSFILE * fo){ | ||
184 | 188 | return 0; |
185 | 189 | } |
186 | 190 | int FSfseek(FSFILE *stream, long offset, int whence){ |
191 | + filepos=offset; | |
187 | 192 | return 0; |
188 | 193 | } |
189 | 194 | /* |
@@ -228,12 +233,11 @@ static const char initext[]= | ||
228 | 233 | "#PRINT\n"; |
229 | 234 | |
230 | 235 | static const char bastext[]= |
231 | -"USECLASS CLASS1,CLASS2\n" | |
232 | -"OPTION FASTFIELD\n" | |
236 | +"useclib TCLIB\n" | |
233 | 237 | "CLS\n" |
234 | -"o=new(CLASS1)\n" | |
235 | -"o.T1=123\n" | |
236 | -"print o.T2()\n" | |
238 | +"print clib$(TCLIB,TEST,0);\n" | |
239 | +"print clib$(TCLIB,TEST,1)\n" | |
240 | +"\n" | |
237 | 241 | "\n" |
238 | 242 | "\n" |
239 | 243 | "\n" |
@@ -255,6 +259,36 @@ static const char class2text[]= | ||
255 | 259 | "\n" |
256 | 260 | "\n"; |
257 | 261 | |
262 | +static const char hextext[]= | |
263 | +":020000040000fa\n" | |
264 | +":1080000000001c3c707f9c2721e09903e0ffbd2706\n" | |
265 | +":108010001c00bfaf1000bcaf1880828f000044acc2\n" | |
266 | +":108020001c80998f09f82003000000001000bc8f0d\n" | |
267 | +":108030002080828f1c00bf8f0800e0032000bd2736\n" | |
268 | +":020000040000fa\n" | |
269 | +":107f80000000000000000080a07f00a0708000a022\n" | |
270 | +":107f9000fc8000a0000001a0788000a0000000008c\n" | |
271 | +":020000040000fa\n" | |
272 | +":108070000800e0030000000000001c3cf87e9c2784\n" | |
273 | +":1080800021e09903040080542480828f2480828f11\n" | |
274 | +":108090000800e003d48042240800e003e480422486\n" | |
275 | +":1080a00000001c3cd07e9c2721e09903e0ffbd2707\n" | |
276 | +":1080b0001c00bfaf1000bcaf2880998f09f82003c7\n" | |
277 | +":1080c000000000001000bc8f1c00bf8f0800e00300\n" | |
278 | +":0480d0002000bd27a8\n" | |
279 | +":020000040000fa\n" | |
280 | +":1080d40048656c6c6f20576f726c6421000000005f\n" | |
281 | +":1080e4005468697320697320612074657374000097\n" | |
282 | +":0880f400544553540000000044\n" | |
283 | +":020000040000fa\n" | |
284 | +":1080fc0040010000800000001c8100a00000000076\n" | |
285 | +":020000040000fa\n" | |
286 | +":10810c0000000000222222222222222222222222cb\n" | |
287 | +":020000040000fa\n" | |
288 | +":0c811c00f48000a0a08000a00000000083\n" | |
289 | +":00000001FF\n" | |
290 | +; | |
291 | + | |
258 | 292 | /* |
259 | 293 | Test function for constructing assemblies from C codes. |
260 | 294 | */ |
@@ -285,6 +319,15 @@ int _debug_test(int a0, int a1, int a2, int a3, int param4, int param5){ | ||
285 | 319 | return a2+a3; |
286 | 320 | } |
287 | 321 | |
322 | +int _debug_test2(int a0, int a1, int a2, int a3, int a4){ | |
323 | + int v0; | |
324 | + v0=v0+a0; | |
325 | + v0=v0*a1; | |
326 | + v0=v0 & a3; | |
327 | + v0=v0 | a4; | |
328 | + return v0; | |
329 | +} | |
330 | + | |
288 | 331 | /* |
289 | 332 | Break point used for debugging object code. |
290 | 333 |
@@ -42,6 +42,9 @@ const char* g_err_str[]={ | ||
42 | 42 | "Invalid in class file", |
43 | 43 | "INIT method does not exist", |
44 | 44 | "ERR_OPTION_CLASSCODE", |
45 | + "ERR_COMPILE_CLIB", | |
46 | + "C library not found", | |
47 | + "HEX file syntax error", | |
45 | 48 | }; |
46 | 49 | |
47 | 50 | char* resolve_label(int s6){ |
@@ -13,10 +13,12 @@ | ||
13 | 13 | #include "api.h" |
14 | 14 | #include "compiler.h" |
15 | 15 | |
16 | -static FSFILE* g_fhandle; | |
17 | -static char* g_fbuff; | |
18 | -static int g_size; | |
19 | -static int g_filepoint; | |
16 | +// Variables used for file handling, shared with the other components | |
17 | +// Note that only one file can be open | |
18 | +FSFILE* g_fhandle; | |
19 | +char* g_fbuff; | |
20 | +int g_size; | |
21 | +int g_filepoint; | |
20 | 22 | |
21 | 23 | char* init_file(char* buff,char* appname){ |
22 | 24 | // Open file |
@@ -147,7 +149,7 @@ int compile_and_link_file(char* buff,char* appname){ | ||
147 | 149 | err=compile_file(); |
148 | 150 | close_file(); |
149 | 151 | |
150 | - // If compiling a class file is required, do it. | |
152 | + // If compiling a class file or a clib is required, do it. | |
151 | 153 | if (err==ERR_COMPILE_CLASS) { |
152 | 154 | j=g_compiling_class; |
153 | 155 | i=compile_and_link_class(buff, g_class); |
@@ -155,6 +157,11 @@ int compile_and_link_file(char* buff,char* appname){ | ||
155 | 157 | if (i) return i; |
156 | 158 | // Continue compiling current file from the beginning. |
157 | 159 | continue; |
160 | + } else if (err==ERR_COMPILE_CLIB) { | |
161 | + err=useclib_begin(buff); | |
162 | + // Continue compiling current file from the beginning. | |
163 | + if (err) break; | |
164 | + continue; | |
158 | 165 | } |
159 | 166 | break; |
160 | 167 | } |
@@ -239,7 +246,7 @@ int compile_and_link_class(char* buff,int class){ | ||
239 | 246 | // Restore current dirctory |
240 | 247 | cmpdata_reset(); |
241 | 248 | while(record=cmpdata_find(CMPDATA_TEMP)){ |
242 | - if (cwd_id=(record[0]&0xffff)) break; | |
249 | + if ((record[0]&0xffff)==cwd_id) break; | |
243 | 250 | } |
244 | 251 | if (!record) break; |
245 | 252 | FSchdir((char*)(&record[1])); |
@@ -494,6 +494,8 @@ char* float_function(void){ | ||
494 | 494 | err=gosub_function(); |
495 | 495 | } else if (nextCodeIs("ARGS#(")) { |
496 | 496 | err=args_function(); |
497 | + } else if (nextCodeIs("CLIB#(")) { | |
498 | + err=clib_statement(); | |
497 | 499 | } else if (nextCodeIs("PI#")) { |
498 | 500 | return float_constant(3.141593); |
499 | 501 | } else { |
@@ -520,6 +522,7 @@ static const void* str_func_list[]={ | ||
520 | 522 | "SYSTEM$(",system_function, |
521 | 523 | "FINPUT$(",finput_function, |
522 | 524 | "GETDIR$(",getdir_function, |
525 | + "CLIB$(",clib_statement, | |
523 | 526 | // Additional functions follow |
524 | 527 | ADDITIONAL_STR_FUNCTIONS |
525 | 528 | }; |
@@ -609,6 +612,7 @@ static const void* int_func_list[]={ | ||
609 | 612 | "EXEC(",exec_function, |
610 | 613 | "CORETIMER(",coretimer_function, |
611 | 614 | "READKEY(",readkey_function, |
615 | + "CLIB(",clib_statement, | |
612 | 616 | // Additional functions follow |
613 | 617 | ADDITIONAL_INT_FUNCTIONS |
614 | 618 | }; |
@@ -95,5 +95,8 @@ unsigned char g_num_classes; | ||
95 | 95 | // OPTION FASTFIELD |
96 | 96 | char g_option_fastfield; |
97 | 97 | |
98 | +// Result of reading a HEX file line | |
99 | +HEXLINE g_hexline; | |
100 | + | |
98 | 101 | // General purpose integer used for asigning value with pointer |
99 | 102 | int g_temp; |
@@ -863,7 +863,7 @@ ON GOTO分やON GOSUB文はサポートしていません。ただし、例え | ||
863 | 863 | を扱いたい場合は、同名の変数をVAR指定しないようにして下さい。 |
864 | 864 | |
865 | 865 | <バージョン履歴> |
866 | -・KM-1303 2019年5月公開。 | |
866 | +・KM-1303 2019年?月公開。 | |
867 | 867 | ・タイマー機能(USETIMER,TIMER, CORETIMERステートメントとTIMER(), CORETIMER()関 |
868 | 868 | 数)を追加。 |
869 | 869 | ・割り込み機能(INTERRUPTステートメント)を追加。 |
@@ -0,0 +1,222 @@ | ||
1 | +/* | |
2 | + This file is provided under the LGPL license ver 2.1. | |
3 | + Written by K.Tanaka & Katsumi | |
4 | + http://www.ze.em-net.ne.jp/~kenken/index.html | |
5 | + http://hp.vector.co.jp/authors/VA016157/ | |
6 | +*/ | |
7 | + | |
8 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include "compiler.h" | |
13 | +#include "api.h" | |
14 | + | |
15 | +/* | |
16 | + Intel HEX format example | |
17 | + :040bf000ffffffcf35 | |
18 | + +--------------------- Byte count | |
19 | + | +---------------- Address | |
20 | + | | +------------- Record type (00:Data, 01:EOF, 04: Extended linear addres | |
21 | + | | | +---- Data | |
22 | + | | | | +- Checksum | |
23 | + | | | | | | |
24 | + : 04 0bf0 00 ffffffcf 35 | |
25 | + | |
26 | + Record types: | |
27 | + case 0: // data | |
28 | + case 4: // extended linear address | |
29 | + case 1: // EOF | |
30 | + | |
31 | +*/ | |
32 | + | |
33 | +/* | |
34 | + Example of HEX file | |
35 | + | |
36 | +:020000040000fa | |
37 | +:1080000000001c3c707f9c2721e09903e0ffbd2706 | |
38 | +:108010001c00bfaf1000bcaf0e0080101880828f14 | |
39 | +:10802000000044ac1c80828f80ff42241c80848f1f | |
40 | +:10803000000040a0010042242b184400fdff6054c2 | |
41 | +:10804000000040a02080998f09f820030000000064 | |
42 | +:108050001000bc8f2480828f1c00bf8f0800e003bb | |
43 | +:048060002000bd2718 | |
44 | +:020000040000fa | |
45 | +:107f80000000000000000080a47f00a0008000a08e | |
46 | +:107f9000708000a0fc8000a0000001a0788000a0fc | |
47 | +:047fa00000000000dd | |
48 | +:020000040000fa | |
49 | +:108070000800e0030000000000001c3cf87e9c2784 | |
50 | +:1080800021e09903040080542880828f2880828f09 | |
51 | +:108090000800e003d48042240800e003e480422486 | |
52 | +:1080a00000001c3cd07e9c2721e09903e0ffbd2707 | |
53 | +:1080b0001c00bfaf1000bcaf2c80998f09f82003c3 | |
54 | +:1080c000000000001000bc8f1c00bf8f0800e00300 | |
55 | +:0480d0002000bd27a8 | |
56 | +:020000040000fa | |
57 | +:1080d40048656c6c6f20576f726c6421000000005f | |
58 | +:1080e4005468697320697320612074657374000097 | |
59 | +:0880f400544553540000000044 | |
60 | +:020000040000fa | |
61 | +:1080fc0040010000800000001c8100a00000000076 | |
62 | +:020000040000fa | |
63 | +:10810c0000000000222222222222222222222222cb | |
64 | +:020000040000fa | |
65 | +:0c811c00f48000a0a08000a00000000083 | |
66 | +:00000001FF | |
67 | +*/ | |
68 | + | |
69 | +// Use the same global vars in file.c | |
70 | +extern FSFILE* g_fhandle; | |
71 | +extern char* g_fbuff; | |
72 | +extern int g_size; | |
73 | +extern int g_filepoint; | |
74 | +// Vars used only in this file | |
75 | +static unsigned char g_checksum; | |
76 | + | |
77 | +void hex_read_file(int blocklen){ | |
78 | + int i; | |
79 | + if (blocklen==512) { | |
80 | + // This is first read. Initialize parameter(s). | |
81 | + g_srcpos=0; | |
82 | + g_filepoint=0; | |
83 | + } else if (g_size<512) { | |
84 | + // Already reached the end of file. | |
85 | + return; | |
86 | + } else { | |
87 | + // Shift buffer and source position 256 bytes. | |
88 | + for(i=0;i<256;i++) g_fbuff[i]=g_fbuff[i+256]; | |
89 | + g_srcpos-=256; | |
90 | + g_filepoint+=256; | |
91 | + } | |
92 | + // Read 512 or 256 bytes from SD card. | |
93 | + g_size=512-blocklen+FSfread((void*)&g_fbuff[512-blocklen],1,blocklen,g_fhandle); | |
94 | + // All lower cases | |
95 | + for(i=512-blocklen;i<512;i++){ | |
96 | + if ('A'<=g_fbuff[i] && g_fbuff[i]<='F') g_fbuff[i]+=0x20; | |
97 | + } | |
98 | +} | |
99 | + | |
100 | +int hex_read_byte(){ | |
101 | + unsigned char b1,b2; | |
102 | + b1=g_fbuff[g_srcpos++]; | |
103 | + b2=g_fbuff[g_srcpos++]; | |
104 | + if ('0'<=b1 && b1<='9') { | |
105 | + b1-='0'; | |
106 | + } else if ('a'<=b1 && b1<='f') { | |
107 | + b1-='a'; | |
108 | + b1+=0x0a; | |
109 | + } else { | |
110 | + return -1; | |
111 | + } | |
112 | + if ('0'<=b2 && b2<='9') { | |
113 | + b2-='0'; | |
114 | + } else if ('a'<=b2 && b2<='f') { | |
115 | + b2-='a'; | |
116 | + b2+=0x0a; | |
117 | + } else { | |
118 | + return -1; | |
119 | + } | |
120 | + b1=(b1<<4)|b2; | |
121 | + g_checksum+=b1; | |
122 | + return b1; | |
123 | +} | |
124 | + | |
125 | +char* hex_read_line(){ | |
126 | + int i,j; | |
127 | + // Initialize checksum | |
128 | + g_checksum=0; | |
129 | + // Maintain at least 256 characters in cache. | |
130 | + if (256<=g_srcpos) hex_read_file(256); | |
131 | + // Read a hex file line | |
132 | + if (g_fbuff[g_srcpos++]!=':') return ERR_HEX_ERROR; | |
133 | + // Read size | |
134 | + i=hex_read_byte(); | |
135 | + if (i<0) return ERR_HEX_ERROR; | |
136 | + g_hexline.size=(unsigned char)i; | |
137 | + // Read address | |
138 | + i=hex_read_byte(); | |
139 | + if (i<0) return ERR_HEX_ERROR; | |
140 | + g_hexline.address=(unsigned short)(i<<8); | |
141 | + i=hex_read_byte(); | |
142 | + if (i<0) return ERR_HEX_ERROR; | |
143 | + g_hexline.address|=(unsigned short)(i); | |
144 | + // Ready type | |
145 | + i=hex_read_byte(); | |
146 | + if (i<0) return ERR_HEX_ERROR; | |
147 | + g_hexline.type=(unsigned char)i; | |
148 | + // Read data | |
149 | + for(j=0;j<g_hexline.size;j++){ | |
150 | + i=hex_read_byte(); | |
151 | + if (i<0) return ERR_HEX_ERROR; | |
152 | + g_hexline.data[j]=(unsigned char)i; | |
153 | + } | |
154 | + // Read checksum | |
155 | + i=hex_read_byte(); | |
156 | + if (i<0) return ERR_HEX_ERROR; | |
157 | + if (g_checksum) return ERR_HEX_ERROR; | |
158 | + // All done. Remove enter. | |
159 | + if (g_fbuff[g_srcpos]=='\r') g_srcpos++; | |
160 | + if (g_fbuff[g_srcpos]=='\n') g_srcpos++; | |
161 | + return 0; | |
162 | +} | |
163 | + | |
164 | +static char g_hex_line[46]; | |
165 | +void hex_construct_byte(unsigned char data,int pos){ | |
166 | + g_hex_line[pos] ="0123456789abcdef"[data>>8]; | |
167 | + g_hex_line[pos+1]="0123456789abcdef"[data&15]; | |
168 | + g_checksum+=data; | |
169 | +} | |
170 | +char* hex_construct_line(){ | |
171 | + int i; | |
172 | + g_checksum=0; | |
173 | + // Write size | |
174 | + hex_construct_byte(g_hexline.size,0); | |
175 | + // Write address | |
176 | + hex_construct_byte(g_hexline.address>>8,2); | |
177 | + hex_construct_byte(g_hexline.address&15,4); | |
178 | + // Write type | |
179 | + hex_construct_byte(g_hexline.type,6); | |
180 | + // Write data | |
181 | + for(i=0;i<g_hexline.size;i++){ | |
182 | + hex_construct_byte(g_hexline.data[i],8+i); | |
183 | + } | |
184 | + // Write checksum | |
185 | + hex_construct_byte(0-g_checksum,8+i); | |
186 | + // All done. Add CRLF and 0x00 | |
187 | + g_hex_line[10+i]=0x0d; | |
188 | + g_hex_line[11+i]=0x0a; | |
189 | + g_hex_line[12+i]=0; | |
190 | + return (char*)&g_hex_line[0]; | |
191 | +} | |
192 | + | |
193 | +void hex_reinit_file(){ | |
194 | + // Go to point 0 | |
195 | + FSfseek(g_fhandle,0,SEEK_SET); | |
196 | + // Initialize parameters | |
197 | + g_srcpos=0; | |
198 | + g_filepoint=0; | |
199 | + // Read first 512 bytes | |
200 | + hex_read_file(512); | |
201 | +} | |
202 | + | |
203 | +char* hex_init_file(char* buff,char* filename){ | |
204 | + // Open file | |
205 | + g_fhandle=FSfopen(filename,"r"); | |
206 | + if (!g_fhandle) { | |
207 | + return ERR_UNKNOWN; | |
208 | + } | |
209 | + // Initialize parameters | |
210 | + g_fbuff=buff; | |
211 | + g_source=buff; | |
212 | + g_srcpos=0; | |
213 | + g_filepoint=0; | |
214 | + // Read first 512 bytes | |
215 | + hex_read_file(512); | |
216 | + return 0; | |
217 | +} | |
218 | + | |
219 | +void hex_close_file(){ | |
220 | + FSfclose(g_fhandle); | |
221 | +} | |
222 | + |
@@ -7,8 +7,9 @@ | ||
7 | 7 | |
8 | 8 | #define MEGALOPA |
9 | 9 | #define SYSVER1 "Megalopa" |
10 | -#define SYSVER2 "1.3" | |
11 | -#define BASVER "KM-1303" | |
10 | +#define SYSVER2 "1.4" | |
11 | +#define SYSVERI 0x0140 | |
12 | +#define BASVER "KM-1304" | |
12 | 13 | |
13 | 14 | #define INIFILE "MACHIKAM.INI" // 初期設定ファイル |
14 | 15 | #define HEXFILE "MACHIKAM.HEX" // 実行中HEXファイル名がこれと一致した場合はエディタ起動 |
@@ -72,6 +72,8 @@ file_044=. | ||
72 | 72 | file_045=. |
73 | 73 | file_046=. |
74 | 74 | file_047=. |
75 | +file_048=. | |
76 | +file_049=. | |
75 | 77 | [GENERATED_FILES] |
76 | 78 | file_000=no |
77 | 79 | file_001=no |
@@ -121,6 +123,8 @@ file_044=no | ||
121 | 123 | file_045=no |
122 | 124 | file_046=no |
123 | 125 | file_047=no |
126 | +file_048=no | |
127 | +file_049=no | |
124 | 128 | [OTHER_FILES] |
125 | 129 | file_000=no |
126 | 130 | file_001=no |
@@ -166,10 +170,12 @@ file_040=no | ||
166 | 170 | file_041=no |
167 | 171 | file_042=no |
168 | 172 | file_043=no |
169 | -file_044=yes | |
170 | -file_045=yes | |
173 | +file_044=no | |
174 | +file_045=no | |
171 | 175 | file_046=yes |
172 | 176 | file_047=yes |
177 | +file_048=yes | |
178 | +file_049=yes | |
173 | 179 | [FILE_INFO] |
174 | 180 | file_000=compiler.c |
175 | 181 | file_001=debug.c |
@@ -200,25 +206,27 @@ file_025=class.c | ||
200 | 206 | file_026=args.c |
201 | 207 | file_027=interface\keyinput.c |
202 | 208 | file_028=timer.c |
203 | -file_029=api.h | |
204 | -file_030=compiler.h | |
205 | -file_031=debug.h | |
206 | -file_032=editor.h | |
207 | -file_033=main.h | |
208 | -file_034=envspecific.h | |
209 | -file_035=io.h | |
210 | -file_036=interface\keyinput.h | |
211 | -file_037=interface\lib_video_megalopa.h | |
212 | -file_038=interface\ps2keyboard.h | |
213 | -file_039=interface\sdfsio370f.h | |
214 | -file_040=interface\lib_videoout_megalopa.X.a | |
215 | -file_041=interface\ps2keyboard370f.X.a | |
216 | -file_042=interface\sdfsio370fLib.X.a | |
217 | -file_043=app_p32MX370F512H.ld | |
218 | -file_044=help.txt | |
219 | -file_045=reservednames.js | |
220 | -file_046=class.txt | |
221 | -file_047=sharedfiles.js | |
209 | +file_029=clib.c | |
210 | +file_030=hexfile.c | |
211 | +file_031=api.h | |
212 | +file_032=compiler.h | |
213 | +file_033=debug.h | |
214 | +file_034=editor.h | |
215 | +file_035=main.h | |
216 | +file_036=envspecific.h | |
217 | +file_037=io.h | |
218 | +file_038=interface\keyinput.h | |
219 | +file_039=interface\lib_video_megalopa.h | |
220 | +file_040=interface\ps2keyboard.h | |
221 | +file_041=interface\sdfsio370f.h | |
222 | +file_042=interface\lib_videoout_megalopa.X.a | |
223 | +file_043=interface\ps2keyboard370f.X.a | |
224 | +file_044=interface\sdfsio370fLib.X.a | |
225 | +file_045=app_p32MX370F512H.ld | |
226 | +file_046=help.txt | |
227 | +file_047=reservednames.js | |
228 | +file_048=class.txt | |
229 | +file_049=sharedfiles.js | |
222 | 230 | [SUITE_INFO] |
223 | 231 | suite_guid={62D235D8-2DB2-49CD-AF24-5489A6015337} |
224 | 232 | suite_state= |
@@ -100,6 +100,7 @@ var namearray=[ | ||
100 | 100 | 'CHR', |
101 | 101 | 'CIRCLE', |
102 | 102 | 'CLEAR', |
103 | + 'CLIB', | |
103 | 104 | 'CLS', |
104 | 105 | 'COLOR', |
105 | 106 | 'COS', |
@@ -12,6 +12,7 @@ | ||
12 | 12 | var filearray=[ |
13 | 13 | 'args.c', |
14 | 14 | 'class.c', |
15 | + 'clib.c', | |
15 | 16 | 'cmpdata.c', |
16 | 17 | 'compiler.c', |
17 | 18 | 'debug.c', |
@@ -21,6 +22,7 @@ var filearray=[ | ||
21 | 22 | 'float.c', |
22 | 23 | 'function.c', |
23 | 24 | 'globalvars.c', |
25 | + 'hexfile.c', | |
24 | 26 | 'library.c', |
25 | 27 | 'linker.c', |
26 | 28 | 'memory.c', |
@@ -1754,6 +1754,8 @@ static const void* statement_list[]={ | ||
1754 | 1754 | "INTERRUPT ",interrupt_statement, |
1755 | 1755 | "IDLE",idle_statement, |
1756 | 1756 | "CORETIMER",coretimer_statement, |
1757 | + "USECLIB",useclib_statement, | |
1758 | + "CLIB",clib_statement, | |
1757 | 1759 | // List of additional statements follows |
1758 | 1760 | ADDITIONAL_STATEMENTS |
1759 | 1761 | }; |
@@ -32,6 +32,7 @@ static const int reserved_var_names[]={ | ||
32 | 32 | 0x0001129b, /*CHR*/ |
33 | 33 | 0x0e7f3303, /*CIRCLE*/ |
34 | 34 | 0x0067525f, /*CLEAR*/ |
35 | + 0x0003c489, /*CLIB*/ | |
35 | 36 | 0x00011330, /*CLS*/ |
36 | 37 | 0x0069cb6b, /*COLOR*/ |
37 | 38 | 0x0001139f, /*COS*/ |
@@ -194,6 +195,18 @@ int check_var_name(){ | ||
194 | 195 | return i; |
195 | 196 | } |
196 | 197 | |
198 | +int str_to_name_int(char* str){ | |
199 | + int i; | |
200 | + char* src=g_source; | |
201 | + int pos=g_srcpos; | |
202 | + g_source=str; | |
203 | + g_srcpos=0; | |
204 | + i=check_var_name(); | |
205 | + g_source=src; | |
206 | + g_srcpos=pos; | |
207 | + return i; | |
208 | +} | |
209 | + | |
197 | 210 | /* |
198 | 211 | int get_var_number(); |
199 | 212 | This function returns variable number that can be used as the index of $s8 |