• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

タグ
未設定

よく使われているワード(クリックで追加)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

BASIC compiler/interpreter for PIC32MX/MZ-80K


コミットメタ情報

リビジョン3beac033cf70cabacfb722bcde919574506edb13 (tree)
日時2019-05-26 11:28:20
作者Katsumi <kmorimatsu@sour...>
コミッターKatsumi

ログメッセージ

Debug: Exception when using CLIB in MSRA

変更サマリ

差分

--- a/mips/megalopa/clib.c
+++ b/mips/megalopa/clib.c
@@ -112,11 +112,14 @@ const void* const g_data_clib[]={
112112 // CLIB name used (name as 31 bit integer)
113113 static unsigned int g_clib;
114114
115+void init_clib(){
116+ // Initialize g_data_clib_var[]
117+ g_data_clib_var[0]=(void*)g_gp;
118+}
119+
115120 char* useclib_statement(){
116121 int i;
117122 int* cmpdata;
118- // Initialize g_data_clib_var[]
119- g_data_clib_var[0]=(void*)g_gp;
120123 do {
121124 next_position();
122125 i=check_var_name();
@@ -266,7 +269,9 @@ char* clib_main(){
266269 g_object[g_objpos++]=0x3C050000|((((unsigned int)(0xA0008000+adjust))>>16)&0x0000FFFF); // lui a1,xxxx
267270 g_object[g_objpos++]=0x34A50000|(((unsigned int)(0xA0008000+adjust))&0x0000FFFF); // ori a1,a1,xxxx
268271 call_quicklib_code(call_clib_init,ASM_ADDIU_A0_ZERO_ | 0);
269- // All done
272+ // All done. Shift g_object as the beginning of main BASIC code.
273+ g_object+=g_objpos;
274+ g_objpos=0;
270275 return 0;
271276 }
272277
--- a/mips/megalopa/compiler.h
+++ b/mips/megalopa/compiler.h
@@ -398,6 +398,7 @@ char* coretimer_statement();
398398 char* coretimer_function();
399399 char* interrupt_statement();
400400
401+void init_clib();
401402 char* useclib_statement();
402403 char* useclib_begin(char* buff);
403404 char* clib_method(char type);
--- a/mips/megalopa/file.c
+++ b/mips/megalopa/file.c
@@ -89,6 +89,8 @@ char* compile_file(){
8989 char* err;
9090 // Read first 512 bytes
9191 read_file(512);
92+ // Skip BOM (UTF-8) if exists
93+ if (0xEF==g_source[0] && 0xBB==g_source[1] && 0xBF==g_source[2]) g_srcpos=3;
9294 // Compile line by line
9395 while (g_size==512) {
9496 err=compile_line();
--- a/mips/megalopa/run.c
+++ b/mips/megalopa/run.c
@@ -46,7 +46,7 @@ int runbasic(char *appname,int mode){
4646 //  -1:ファイルエラー
4747 //  -2:リンクエラー
4848 //  1以上:コンパイルエラーの発生行(行番号ではなくファイル上の何行目か)
49- int i;
49+ int i,j;
5050 char* buff;
5151 char* err;
5252
@@ -85,19 +85,23 @@ int runbasic(char *appname,int mode){
8585 // Initialize music system
8686 init_music();
8787
88+ // Initialize clib
89+ init_clib();
90+
8891 printstr("BASIC "BASVER"\n");
8992 wait60thsec(15);
9093
9194 printstr("Compiling...");
9295
9396 if (mode==RUNMODE_COPY_AND_RUN) {
94- // Copy the object from MOS
95- appname=(char*)MACHIKANIA_OBJ_ADDRESS;
96- for(i=0;i<RAMSIZE;i++) RAM[i]=appname[i];
9797 // Set g_object/g_objpos for library functions like lib_read().
9898 // The g_object/g_objpos values are stoared just before MOS.
9999 g_object=(int*)g_object_mos;
100100 g_objpos=g_objpos_mos;
101+ // Copy the object from MOS
102+ j=(int)(&g_object[g_objpos])-(int)(&RAM[0]);
103+ appname=(char*)MACHIKANIA_OBJ_ADDRESS;
104+ for(i=0;i<j;i++) RAM[i]=appname[i];
101105 } else {
102106 // Initialize compiler
103107 cmpdata_init();
--- /dev/null
+++ b/mips/protozoea/clib.c
@@ -0,0 +1,431 @@
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+/*
33+ * g_data_clib[] contains the data from MachiKania compiler for this library
34+ */
35+void* g_data_clib_var[]={
36+ 0, // will be g_gp, g_data[0][0],"0"
37+};
38+
39+const void* const g_data_clib_core[]={
40+ lib_calloc_memory,// g_data[1][0],"0"
41+ lib_delete, // g_data[1][1],"4"
42+};
43+
44+const void* const g_data_clib_file[]={
45+#ifdef __DEBUG
46+ 0 // Disabled in debug mode
47+#else
48+ FSInit, // g_data[2][0],"0"
49+ FSfopen, // g_data[2][1],"4"
50+ FSfclose, // g_data[2][2],"8"
51+ FSfread, // g_data[2][3],"12"
52+ FSfwrite, // g_data[2][4],"16"
53+ FSfeof, // g_data[2][5],"20"
54+ FSftell, // g_data[2][6],"24"
55+ FSfseek, // g_data[2][7],"28"
56+ FSrewind, // g_data[2][8],"32"
57+ FindFirst,// g_data[2][9],"36"
58+ FindNext, // g_data[2][10],"40"
59+ FSmkdir, // g_data[2][11],"44"
60+ FSgetcwd, // g_data[2][12],"48"
61+ FSchdir, // g_data[2][13],"52"
62+ FSremove, // g_data[2][14],"56"
63+ FSrename, // g_data[2][15],"60"
64+#endif
65+};
66+
67+const void* const g_data_clib_video[]={
68+ start_composite,// g_data[3][0],"0"
69+ stop_composite, // g_data[3][1],"4"
70+ printchar, // g_data[3][2],"8"
71+ printstr, // g_data[3][3],"12"
72+ printnum, // g_data[3][4],"16"
73+ printnum2, // g_data[3][5],"20"
74+ cls, // g_data[3][6],"24"
75+ vramscroll, // g_data[3][7],"28"
76+ setcursorcolor, // g_data[3][8],"32"
77+ setcursor, // g_data[3][9],"36"
78+ set_palette, // g_data[3][10],"40"
79+ set_bgcolor, // g_data[3][11],"44"
80+};
81+
82+const void* const g_data_clib_graphic[]={
83+ g_pset, // g_data[4][0],"0"
84+ g_putbmpmn, // g_data[4][1],"4"
85+ g_clrbmpmn, // g_data[4][2],"8"
86+ g_gline, // g_data[4][3],"12"
87+ g_hline, // g_data[4][4],"16"
88+ g_circle, // g_data[4][5],"20"
89+ g_circlefill, // g_data[4][6],"24"
90+ g_boxfill, // g_data[4][7],"28"
91+ g_putfont, // g_data[4][8],"32"
92+ g_printstr, // g_data[4][9],"36"
93+ g_printnum, // g_data[4][10],"40"
94+ g_printnum2, // g_data[4][11],"44"
95+ g_color, // g_data[4][12],"48"
96+};
97+
98+const void* const g_data_clib_keyboard[]={
99+ shiftkeys, // g_data[5][0],"0"
100+ ps2readkey,// g_data[5][1],"4"
101+};
102+
103+const void* const g_data_clib[]={
104+ &g_data_clib_var[0], // g_data[0],"0"
105+ &g_data_clib_core[0], // g_data[1],"4"
106+ &g_data_clib_file[0], // g_data[2],"8"
107+ &g_data_clib_video[0], // g_data[3],"12"
108+ &g_data_clib_graphic[0], // g_data[4],"16"
109+ &g_data_clib_keyboard[0],// g_data[5],"20"
110+};
111+
112+// CLIB name used (name as 31 bit integer)
113+static unsigned int g_clib;
114+
115+void init_clib(){
116+ // Initialize g_data_clib_var[]
117+ g_data_clib_var[0]=(void*)g_gp;
118+}
119+
120+char* useclib_statement(){
121+ int i;
122+ int* cmpdata;
123+ do {
124+ next_position();
125+ i=check_var_name();
126+ if (i<65536) return ERR_SYNTAX;
127+ // Check if the clib already exists
128+ cmpdata_reset();
129+ while(cmpdata=cmpdata_find(CMPDATA_USECLIB)){
130+ if (cmpdata[1]==i) {
131+ // The clib was already defined.
132+ i=0;
133+ break;
134+ }
135+ }
136+ if (i) {
137+ // Load new file to define clib.
138+ g_clib=i;
139+ return ERR_COMPILE_CLIB;
140+ }
141+ if (g_source[g_srcpos]==',') {
142+ g_srcpos++;
143+ } else {
144+ break;
145+ }
146+ } while(1);
147+ return 0;
148+}
149+
150+void* call_clib_init(void** data, void* address){
151+ // Store gp and ra
152+ asm volatile("#":::"s0");
153+ asm volatile("#":::"ra");
154+ asm volatile("addu $t9,$a1,$zero");
155+ asm volatile("addu $s0,$gp,$zero");
156+ asm volatile("jalr $ra,$t9");
157+ asm volatile("addu $gp,$s0,$zero");
158+}
159+
160+char* clib_main(){
161+ char* err;
162+ unsigned int begin,end,addr;
163+ void* clibdata;
164+ int* functions;
165+ int* got;
166+ int i,opos,adjust;
167+ char* clib;
168+ int record[3];
169+ // Insert CMPDATA_USELIB
170+ record[0]=g_clib;
171+ err=cmpdata_insert(CMPDATA_USECLIB,0,&record[0],1);
172+ if (err) return err;
173+ // Determine begin and end addresses
174+ begin=0x000fffff;
175+ end=0;
176+ while(1){
177+ err=hex_read_line();
178+ if (err) return err;
179+ if (g_hexline.type==1) {
180+ // EOF
181+ break;
182+ } else if (g_hexline.type==4) {
183+ // extended linear address
184+ addr=g_hexline.data[0];
185+ addr=addr<<8;
186+ addr|=g_hexline.data[0];
187+ addr=addr<<16;
188+ } else if (g_hexline.type==0) {
189+ // data
190+ addr&=0xffff0000;
191+ addr|=g_hexline.address;
192+ if (addr<begin) begin=addr;
193+ if (end<addr && addr<0x000fffff) {
194+ end=addr+g_hexline.size;
195+ }
196+ } else {
197+ // Unknown type
198+ return ERR_HEX_ERROR;
199+ }
200+ }
201+ hex_reinit_file();
202+ // Assign and clear region
203+ check_obj_space((end-begin+3)>>2);
204+ clib=(char*)&g_object[g_objpos];
205+ got=(int*)&g_object[g_objpos];
206+ for(i=0;i<((end-begin+3)>>2);i++) g_object[g_objpos++]=0;
207+ // Load binary from HEX file
208+ while(1){
209+ err=hex_read_line();
210+ if (err) return err;
211+ if (g_hexline.type==1) {
212+ // EOF
213+ break;
214+ } else if (g_hexline.type==4) {
215+ // extended linear address
216+ addr=g_hexline.data[0];
217+ addr=addr<<8;
218+ addr|=g_hexline.data[0];
219+ addr=addr<<16;
220+ } else if (g_hexline.type==0) {
221+ // data
222+ addr&=0xffff0000;
223+ addr|=g_hexline.address;
224+ for(i=0;i<g_hexline.size;i++){
225+ clib[addr-begin+i]=g_hexline.data[i];
226+ }
227+ } else {
228+ // Unknown type
229+ return ERR_HEX_ERROR;
230+ }
231+ }
232+ // Calculate the adjustment value.
233+ // Note that the address of clib_init() is 0x8000.
234+ adjust=(int)clib+0x8000-begin-0xA0008000;
235+ // Modify Global Offset Table (GOT)
236+ for(i=0;i<(0x8000-begin)>>2;i++){
237+ if ((got[i]&0xFFF00000)==0xA0000000) {
238+ got[i]+=adjust;
239+ }
240+ }
241+ // Call the clib_init() to get the address of clibdata array.
242+ clibdata=call_clib_init((void**)&g_data_clib[0],(void*)(0xA0008000+adjust));
243+ // Check version
244+ if (((int*)clibdata)[0]>SYSVERI) {
245+ return "Newer version of C library than MachiKania cannot be used.";
246+ }
247+ // Get functions array
248+ clibdata=(void*)(((int*)clibdata)[2])+adjust;
249+ functions=clibdata;
250+ // Construct CMPDATA_CLIBFUNC records.
251+ while(clib=(char*)functions[0]){
252+ clibdata=(void*)functions[1];
253+ functions+=2;
254+ // clib is function name as string
255+ // clibdata is address of C function
256+ clib+=adjust;
257+ clibdata+=adjust;
258+ i=str_to_name_int(clib);
259+ if (i<65536) return "Wrong C library function name";
260+ record[0]=g_clib;
261+ record[1]=i;
262+ record[2]=(int)clibdata;
263+ err=cmpdata_insert(CMPDATA_CLIBFUNC,0,&record[0],3);
264+ if (err) return err;
265+ }
266+ // Initial assembly is a jump statement to jump to the the following routine.
267+ g_object[0]=0x08000000 | ((((int)(&g_object[g_objpos]))&0x0FFFFFFF)>>2); // j xxxxxxxx
268+ // Insert initialization code
269+ g_object[g_objpos++]=0x3C050000|((((unsigned int)(0xA0008000+adjust))>>16)&0x0000FFFF); // lui a1,xxxx
270+ g_object[g_objpos++]=0x34A50000|(((unsigned int)(0xA0008000+adjust))&0x0000FFFF); // ori a1,a1,xxxx
271+ call_quicklib_code(call_clib_init,ASM_ADDIU_A0_ZERO_ | 0);
272+ // All done. Shift g_object as the beginning of main BASIC code.
273+ g_object+=g_objpos;
274+ g_objpos=0;
275+ return 0;
276+}
277+
278+char* useclib_begin(char* buff){
279+ int i,j,cwd_id;
280+ char* err;
281+ char* clibname;
282+ char filename[11];
283+ int* record;
284+ // Remove a objects before USECLIB statement
285+ g_objpos=0;
286+ // Insert twp NOP assemblies. This will be replaced by branch statement.
287+ check_obj_space(2);
288+ g_object[g_objpos++]=0x00000000; // nop
289+ g_object[g_objpos++]=0x00000000; // nop
290+ // Construct HEX file name to open
291+ clibname=resolve_label(g_clib);
292+ for(i=0;filename[i]=clibname[i];i++);
293+ filename[i++]='.';
294+ filename[i++]='H';
295+ filename[i++]='E';
296+ filename[i++]='X';
297+ filename[i++]=0;
298+ // Open file in current directory
299+ err=hex_init_file(buff,filename);
300+ if (!err) {
301+ // HEX file found in current directory.
302+ err=clib_main();
303+ hex_close_file();
304+ } else {
305+ // Hex file not found in current directory.
306+ // Find it in LIB directory.
307+ if (!FSgetcwd(buff,256)) return ERR_UNKNOWN;
308+ for(i=0;buff[i];i++);
309+ cwd_id=cmpdata_get_id();
310+ if (!cwd_id) return ERR_UNKNOWN;
311+ err=cmpdata_insert(CMPDATA_TEMP,cwd_id,(int*)(&buff[0]),(i+1+3)>>2);
312+ if (err) return err;
313+ // Change current directory to class library directory
314+ for(i=0;buff[i]="\\LIB\\"[i];i++);
315+ for(j=0;buff[i++]=clibname[j];j++);
316+ buff[i]=0;
317+ FSchdir(buff);
318+ err=hex_init_file(buff,filename);
319+ if (!err) {
320+ // HEX file found in LIB directory
321+ err=clib_main();
322+ hex_close_file();
323+ } else {
324+ err=ERR_NO_CLIB;
325+ }
326+ // Restore current dirctory
327+ cmpdata_reset();
328+ while(record=cmpdata_find(CMPDATA_TEMP)){
329+ if ((record[0]&0xffff)==cwd_id) break;
330+ }
331+ if (!record) return ERR_UNKNOWN;
332+ FSchdir((char*)(&record[1]));
333+ cmpdata_delete(record);
334+ }
335+ return err;
336+}
337+
338+void lib_clib(int* params, void* address){
339+ // Store gp and ra
340+ asm volatile("#":::"s0");
341+ asm volatile("#":::"ra");
342+ asm volatile("addu $t9,$a1,$zero");
343+ asm volatile("addu $s0,$gp,$zero");
344+ asm volatile("lw $a3,16($a0)");
345+ asm volatile("lw $a2,12($a0)");
346+ asm volatile("lw $a1,8($a0)");
347+ asm volatile("lw $a0,4($a0)");
348+ asm volatile("jalr $ra,$t9");
349+ asm volatile("addu $gp,$s0,$zero");
350+}
351+
352+char* clib_method(char type){
353+ char* err;
354+ int* record;
355+ int clib,func;
356+ int numparams,stack,spos;
357+ // CLIB name
358+ next_position();
359+ spos=g_srcpos;
360+ clib=check_var_name();
361+ if (clib<65536) return ERR_SYNTAX;
362+ // Check if the clib exists
363+ cmpdata_reset();
364+ while (record=cmpdata_find(CMPDATA_USECLIB)){
365+ if (record[1]==clib) break;
366+ }
367+ if (!record) {
368+ g_srcpos=spos;
369+ return ERR_NO_CLIB;
370+ }
371+ if (g_source[g_srcpos++]!=':') return ERR_SYNTAX;
372+ if (g_source[g_srcpos++]!=':') return ERR_SYNTAX;
373+ // Function name
374+ func=check_var_name();
375+ if (func<65536) return ERR_SYNTAX;
376+ cmpdata_reset();
377+ while (record=cmpdata_find(CMPDATA_CLIBFUNC)){
378+ if (record[1]==clib && record[2]==func) break;
379+ }
380+ if (!record) return "Function not found in the C library";
381+ // Check type and following syntax
382+ if (type==',') {
383+ // This is CLIB(CLASS:METHOD) style
384+ } else {
385+ // Type is either 0 (integer), $ (string), or # (float)
386+ // This is CLASS::METHOD() style
387+ if (type) {
388+ if (g_source[g_srcpos++]!=type) return ERR_SYNTAX;
389+ }
390+ if (g_source[g_srcpos++]!='(') return ERR_SYNTAX;
391+ }
392+ // Construct parameter(s)
393+ next_position();
394+ numparams=0;
395+ if (','==type && g_source[g_srcpos]!=',') {
396+ // This is CLIB(CLASS:METHOD) style
397+ // no parameter
398+ } else if (','!=type && g_source[g_srcpos]==')') {
399+ // This is CLASS::METHOD() style
400+ // no parameter
401+ } else {
402+ // There is parameter(s)
403+ do {
404+ numparams++;
405+ if (4<numparams) return ERR_SYNTAX;
406+ else if (1==numparams) {
407+ check_obj_space(1);
408+ stack=g_objpos++;
409+ }
410+ if (g_source[g_srcpos]==',') g_srcpos++;
411+ g_object[stack]=0x27BD0000|(65536-numparams*4); // addiu sp,sp,-xx
412+ err=get_stringFloatOrValue();
413+ if (err) return err;
414+ check_obj_space(1);
415+ g_object[g_objpos++]=0xAFA20000|(numparams*4); // sw v0,xx(sp)
416+ next_position();
417+ } while (g_source[g_srcpos]==',');
418+ }
419+ // Call CLIB
420+ check_obj_space(2);
421+ g_object[g_objpos++]=0x3C050000|(((unsigned int)record[3])>>16); // lui a1,xxxx
422+ g_object[g_objpos++]=0x34A50000|(((unsigned int)record[3])&0x0000FFFF); // ori a1,a1,xxxx
423+ call_quicklib_code(lib_clib,ASM_ADDU_A0_SP_ZERO); // All done
424+ check_obj_space(1);
425+ if (numparams) g_object[g_objpos++]=0x27BD0000|(numparams*4); // addiu sp,sp,xx
426+ return 0;
427+}
428+
429+char* clib_statement(){
430+ return clib_method(',');
431+}
\ No newline at end of file
--- /dev/null
+++ b/mips/protozoea/clib.txt
@@ -0,0 +1,108 @@
1+<Cライブラリーの利用方法>
2+
3+まず、Cライブラリーの使い方について述べます。作成方法については、下の方を参照して
4+下さい。
5+
6+Cライブラリーの本体は、「*.HEX」ファイルです。拡張子が「HEX」のファイルが、BASIC
7+プログラムが置かれているのと同じディレクトリーか、LIBディレクトリーの所定の場所に
8+ある事を確認して下さい。
9+
10+BASICプログラム中では、まず冒頭でUSECLIBステートメントを記述して下さい。
11+
12+USECLIB x[,y[,z[, ... ]]]
13+ Cライブラリーの利用を宣言する。x,y,z等は、ライブラリー名を6文字以内の英数字
14+ で指定。
15+
16+ここでは、「*.HEX」ファイルのファイル名を、指定します。「TCLIB.HEX」なら
17+「USECLIB TCLIB」と記述します。
18+
19+Cライブラリー内の関数を呼び出すには、以下のいずれかの方法を取ります。それぞれの
20+関数の詳しい使用方法については、Cライブラリーに付属のドキュメントを参照して下さ
21+い。
22+
23+CLIB xxx::yyy[,z1[,z2 ...]]
24+ Cライブラリー内の関数を呼び出す。xxxはライブラリー名、yyyは関数名。z1, z2等
25+ は引数(オプション)。
26+CLIB(xxx::yyy[,z1[,z2 ... ]])
27+ Cライブラリー内の関数を呼び出し、整数を返す。xxxはライブラリー名、yyyは関数
28+ 名。z1, z2等は引数(オプション)。xxx::yyy([z1[,z2 ... ]])と書いても同じ。
29+CLIB$(xxx::yyy[,z1[,z2 ... ]])
30+ Cライブラリー内の関数を呼び出し、文字列を返す。xxxはライブラリー名、yyyは関
31+ 数名。z1, z2等は引数(オプション)。xxx::yyy$([z1[,z2 ... ]])と書いても同じ。
32+CLIB#(xxx::yyy[,z1[,z2 ... ]])
33+ Cライブラリー内の関数を呼び出し、実数を返す。xxxはライブラリー名、yyyは関
34+ 数名。z1, z2等は引数(オプション)。xxx::yyy#([z1[,z2 ... ]])と書いても同じ。
35+
36+<使用例>
37+
38+USECLIB TCLIB
39+PRINT TCLIB::TEST$(0)
40+PRINT TCLIB::TEST$(1)
41+
42+<Cライブラリーの作成方法>
43+
44+Cライブラリーを作製する場合には、MPLAB X IDEとXC32コンパイラーのver 1.42以降が
45+必要です。
46+
47+まず、ライブラリー作成用のテンプレートをダウンロードして下さい。少なくとも、次の
48+ファイルが含まれているはずです。
49+
50+clib.c
51+clib.h
52+clib_p32MX370F512H.ld
53+example.c
54+
55+「File->Project Properties」を選択します。次の設定を確認し、異なっていれば値を
56+変更してください。
57+ Categories: Conf
58+ Compiler Toochains: XC32 (v1.42以降)
59+ Categories: xc32-gcc
60+ Additinal options: -mgen-pie-static
61+ Option categories: Optimization
62+ optimization-level: 1
63+ Generated Command Line: -g -O1
64+ Categories: xc32-ld
65+ Additional options: --no-data-init
66+ Option categories: General
67+ Remove unused sections: チェックを入れる
68+ Option categories: Libraries
69+ Exclude Standard Libraries: チェックを入れる
70+ Generated Command Line: --gc-sections --no-code-in-dinit --no-dinit-in-serial-mem -nostdlib -Map="${DISTDIR}/${PROJECTNAME}.${IMAGE_TYPE}.map"
71+
72+clib.c, clib.h, clib_p32MX370F512H.ldの3つは、通常は編集せずにそのまま使います。
73+example.cを編集(必要ならばファイル名を変更)する事で、Cライブラリーを作製して下さ
74+い。コンパイルして出来たHEXファイルが、完成した本体です。
75+
76+<Cライブラリーの仕様>
77+
78+Cライブラリーを作成するにあたり、以下の規約に従って下さい。
79+
80+1.グローバル変数・スタティック変数領域の容量は、128バイト。
81+ ・20個ほどのグローバル変数・スタティック変数が使用可能。
82+ ・大きなメモリー領域が必要な場合は、malloc(), calloc(), free()を使用する。
83+ ・グローバル変数の初期化は、init()関数で行なわなければならない。
84+ ・スタティック変数は実行前の初期化はできない(常に0で初期化される)。
85+
86+2.パブリック関数を、その呼び出し名と共にリストアップする事。
87+ ・functions[]グローバル変数に指定する。
88+ ・フォーマットについては、example.cを参照。
89+
90+3.パブリック関数の引数は、4つまで。
91+
92+4.割り込みは使用出来ない。
93+
94+<グローバル変数領域のサイズ変更>
95+
96+より大きな変数領域が必要な場合は、calloc()で領域を割り当てる事が推奨されます。
97+それでも、グローバル変数領域が足りない場合は、以下の方法でサイズ変更出来ます。
98+
99+1.clib_p[32MC370F512H.ldを編集する。
100+ ・「kseg1_data_mem」の設定の所、「-0x080」と「LENGTH = 0x080」となっている所
101+  を適当なサイズに変更する。
102+
103+2.clib.hを編集する。
104+ ・「#define CLIB_DATA_MEM_SIZE 0x0080」の所、上記で変更した値と同じになるよう
105+  に、編集する。
106+
107+<バージョン履歴>
108+・KM-1209/KM1304 2019年?月公開。
--- a/mips/protozoea/compiler.h
+++ b/mips/protozoea/compiler.h
@@ -398,6 +398,7 @@ char* coretimer_statement();
398398 char* coretimer_function();
399399 char* interrupt_statement();
400400
401+void init_clib();
401402 char* useclib_statement();
402403 char* useclib_begin(char* buff);
403404 char* clib_method(char type);
--- /dev/null
+++ b/mips/protozoea/hexfile.c
@@ -0,0 +1,271 @@
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+ : 02 0000 04 1fc0 1b
26+ : 00 0000 01 FF
27+
28+ Record types:
29+ case 0: // data
30+ case 4: // extended linear address
31+ case 1: // EOF
32+
33+*/
34+
35+/*
36+ Example of HEX file
37+
38+:020000040000fa
39+:1080000000001c3c707f9c2721e09903e0ffbd2706
40+:108010001c00bfaf1000bcaf0e0080101880828f14
41+:10802000000044ac1c80828f80ff42241c80848f1f
42+:10803000000040a0010042242b184400fdff6054c2
43+:10804000000040a02080998f09f820030000000064
44+:108050001000bc8f2480828f1c00bf8f0800e003bb
45+:048060002000bd2718
46+:020000040000fa
47+:107f80000000000000000080a47f00a0008000a08e
48+:107f9000708000a0fc8000a0000001a0788000a0fc
49+:047fa00000000000dd
50+:020000040000fa
51+:108070000800e0030000000000001c3cf87e9c2784
52+:1080800021e09903040080542880828f2880828f09
53+:108090000800e003d48042240800e003e480422486
54+:1080a00000001c3cd07e9c2721e09903e0ffbd2707
55+:1080b0001c00bfaf1000bcaf2c80998f09f82003c3
56+:1080c000000000001000bc8f1c00bf8f0800e00300
57+:0480d0002000bd27a8
58+:020000040000fa
59+:1080d40048656c6c6f20576f726c6421000000005f
60+:1080e4005468697320697320612074657374000097
61+:0880f400544553540000000044
62+:020000040000fa
63+:1080fc0040010000800000001c8100a00000000076
64+:020000040000fa
65+:10810c0000000000222222222222222222222222cb
66+:020000040000fa
67+:0c811c00f48000a0a08000a00000000083
68+:00000001FF
69+*/
70+
71+// Use the same global vars in file.c
72+extern FSFILE* g_fhandle;
73+extern char* g_fbuff;
74+extern int g_size;
75+extern int g_filepoint;
76+// Vars used only in this file
77+static unsigned char g_checksum;
78+
79+void hex_read_file(int blocklen){
80+ int i;
81+ if (blocklen==512) {
82+ // This is first read. Initialize parameter(s).
83+ g_srcpos=0;
84+ g_filepoint=0;
85+ } else if (g_size<512) {
86+ // Already reached the end of file.
87+ return;
88+ } else {
89+ // Shift buffer and source position 256 bytes.
90+ for(i=0;i<256;i++) g_fbuff[i]=g_fbuff[i+256];
91+ g_srcpos-=256;
92+ g_filepoint+=256;
93+ }
94+ // Read 512 or 256 bytes from SD card.
95+ g_size=512-blocklen+FSfread((void*)&g_fbuff[512-blocklen],1,blocklen,g_fhandle);
96+ // All lower cases
97+ for(i=512-blocklen;i<512;i++){
98+ if ('A'<=g_fbuff[i] && g_fbuff[i]<='F') g_fbuff[i]+=0x20;
99+ }
100+}
101+
102+int hex_read_byte(){
103+ unsigned char b1,b2;
104+ b1=g_fbuff[g_srcpos++];
105+ b2=g_fbuff[g_srcpos++];
106+ if ('0'<=b1 && b1<='9') {
107+ b1-='0';
108+ } else if ('a'<=b1 && b1<='f') {
109+ b1-='a';
110+ b1+=0x0a;
111+ } else {
112+ return -1;
113+ }
114+ if ('0'<=b2 && b2<='9') {
115+ b2-='0';
116+ } else if ('a'<=b2 && b2<='f') {
117+ b2-='a';
118+ b2+=0x0a;
119+ } else {
120+ return -1;
121+ }
122+ b1=(b1<<4)|b2;
123+ g_checksum+=b1;
124+ return b1;
125+}
126+
127+char* hex_read_line(){
128+ int i,j;
129+ // Initialize checksum
130+ g_checksum=0;
131+ // Maintain at least 256 characters in cache.
132+ if (256<=g_srcpos) hex_read_file(256);
133+ // Read a hex file line
134+ if (g_fbuff[g_srcpos++]!=':') return ERR_HEX_ERROR;
135+ // Read size
136+ i=hex_read_byte();
137+ if (i<0) return ERR_HEX_ERROR;
138+ g_hexline.size=(unsigned char)i;
139+ // Read address
140+ i=hex_read_byte();
141+ if (i<0) return ERR_HEX_ERROR;
142+ g_hexline.address=(unsigned short)(i<<8);
143+ i=hex_read_byte();
144+ if (i<0) return ERR_HEX_ERROR;
145+ g_hexline.address|=(unsigned short)(i);
146+ // Ready type
147+ i=hex_read_byte();
148+ if (i<0) return ERR_HEX_ERROR;
149+ g_hexline.type=(unsigned char)i;
150+ // Read data
151+ for(j=0;j<g_hexline.size;j++){
152+ i=hex_read_byte();
153+ if (i<0) return ERR_HEX_ERROR;
154+ g_hexline.data[j]=(unsigned char)i;
155+ }
156+ // Read checksum
157+ i=hex_read_byte();
158+ if (i<0) return ERR_HEX_ERROR;
159+ if (g_checksum) return ERR_HEX_ERROR;
160+ // All done. Remove enter.
161+ if (g_fbuff[g_srcpos]=='\r') g_srcpos++;
162+ if (g_fbuff[g_srcpos]=='\n') g_srcpos++;
163+ return 0;
164+}
165+
166+static char g_hex_line[47]=":";
167+void hex_construct_byte(unsigned char data,int pos){
168+ g_hex_line[pos+0]="0123456789abcdef"[data>>4];
169+ g_hex_line[pos+1]="0123456789abcdef"[data&15];
170+ g_checksum+=data;
171+}
172+char* hex_construct_line(){
173+ int i;
174+ g_checksum=0;
175+ // Write size
176+ hex_construct_byte(g_hexline.size,1);
177+ // Write address
178+ hex_construct_byte(g_hexline.address>>8,3);
179+ hex_construct_byte(g_hexline.address&0xff,5);
180+ // Write type
181+ hex_construct_byte(g_hexline.type,7);
182+ // Write data
183+ for(i=0;i<g_hexline.size;i++){
184+ hex_construct_byte(g_hexline.data[i],9+i*2);
185+ }
186+ // Write checksum
187+ hex_construct_byte(0-g_checksum,9+i*2);
188+ // All done. Add CRLF and 0x00
189+ g_hex_line[11+i*2]=0x0d;
190+ g_hex_line[12+i*2]=0x0a;
191+ g_hex_line[13+i*2]=0;
192+ return (char*)&g_hex_line[0];
193+}
194+
195+void hex_reinit_file(){
196+ // Go to point 0
197+ FSfseek(g_fhandle,0,SEEK_SET);
198+ // Initialize parameters
199+ g_srcpos=0;
200+ g_filepoint=0;
201+ // Read first 512 bytes
202+ hex_read_file(512);
203+}
204+
205+char* hex_init_file(char* buff,char* filename){
206+ // Open file
207+ g_fhandle=FSfopen(filename,"r");
208+ if (!g_fhandle) {
209+ return ERR_UNKNOWN;
210+ }
211+ // Initialize parameters
212+ g_fbuff=buff;
213+ g_source=buff;
214+ g_srcpos=0;
215+ g_filepoint=0;
216+ // Read first 512 bytes
217+ hex_read_file(512);
218+ return 0;
219+}
220+
221+void hex_close_file(){
222+ FSfclose(g_fhandle);
223+}
224+
225+char* hex_write(FSFILE* fhandle){
226+ int i,j;
227+ char* str;
228+ // Construct the line string.
229+ str=hex_construct_line();
230+ // Determine string length
231+ for(i=0;str[i];i++);
232+ j=FSfwrite(str,1,i,fhandle);
233+ if (j<i) return ERR_FILE;
234+ return 0;
235+}
236+
237+
238+char* hex_write_address(FSFILE* fhandle,unsigned short addr){
239+ int i,j;
240+ char* str;
241+ addr&=0x7fff; // Write 0x1d00 instead of 0x9d00.
242+ g_hexline.size=2;
243+ g_hexline.type=4;
244+ g_hexline.address=0;
245+ g_hexline.data[0]=addr>>8;
246+ g_hexline.data[1]=addr&0xff;
247+ return hex_write(fhandle);
248+}
249+
250+char* hex_write_data_16(FSFILE* fhandle,unsigned short addr,unsigned int* object){
251+ int i,j;
252+ char* str;
253+ g_hexline.size=16;
254+ g_hexline.type=0;
255+ g_hexline.address=addr;
256+ for(i=0;i<4;i++){
257+ g_hexline.data[i*4+0]=object[i];
258+ g_hexline.data[i*4+1]=object[i]>>8;
259+ g_hexline.data[i*4+2]=object[i]>>16;
260+ g_hexline.data[i*4+3]=object[i]>>24;
261+ }
262+ return hex_write(fhandle);
263+}
264+
265+char* hex_write_eof(FSFILE* fhandle){
266+ int i;
267+ i=FSfwrite(":00000001FF\x0d\x0a",1,13,fhandle);
268+ if (i<13) return ERR_FILE;
269+ return 0;
270+}
271+
--- a/mips/protozoea/run.c
+++ b/mips/protozoea/run.c
@@ -46,7 +46,7 @@ int runbasic(char *appname,int mode){
4646 //  -1:ファイルエラー
4747 //  -2:リンクエラー
4848 //  1以上:コンパイルエラーの発生行(行番号ではなくファイル上の何行目か)
49- int i;
49+ int i,j;
5050 char* buff;
5151 char* err;
5252
@@ -85,19 +85,23 @@ int runbasic(char *appname,int mode){
8585 // Initialize music system
8686 init_music();
8787
88+ // Initialize clib
89+ init_clib();
90+
8891 printstr("BASIC "BASVER"\n");
8992 wait60thsec(15);
9093
9194 printstr("Compiling...");
9295
9396 if (mode==RUNMODE_COPY_AND_RUN) {
94- // Copy the object from MOS
95- appname=(char*)MACHIKANIA_OBJ_ADDRESS;
96- for(i=0;i<RAMSIZE;i++) RAM[i]=appname[i];
9797 // Set g_object/g_objpos for library functions like lib_read().
9898 // The g_object/g_objpos values are stoared just before MOS.
9999 g_object=(int*)g_object_mos;
100100 g_objpos=g_objpos_mos;
101+ // Copy the object from MOS
102+ j=(int)(&g_object[g_objpos])-(int)(&RAM[0]);
103+ appname=(char*)MACHIKANIA_OBJ_ADDRESS;
104+ for(i=0;i<j;i++) RAM[i]=appname[i];
101105 } else {
102106 // Initialize compiler
103107 cmpdata_init();
--- /dev/null
+++ b/mips/zoea/clib.c
@@ -0,0 +1,431 @@
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+/*
33+ * g_data_clib[] contains the data from MachiKania compiler for this library
34+ */
35+void* g_data_clib_var[]={
36+ 0, // will be g_gp, g_data[0][0],"0"
37+};
38+
39+const void* const g_data_clib_core[]={
40+ lib_calloc_memory,// g_data[1][0],"0"
41+ lib_delete, // g_data[1][1],"4"
42+};
43+
44+const void* const g_data_clib_file[]={
45+#ifdef __DEBUG
46+ 0 // Disabled in debug mode
47+#else
48+ FSInit, // g_data[2][0],"0"
49+ FSfopen, // g_data[2][1],"4"
50+ FSfclose, // g_data[2][2],"8"
51+ FSfread, // g_data[2][3],"12"
52+ FSfwrite, // g_data[2][4],"16"
53+ FSfeof, // g_data[2][5],"20"
54+ FSftell, // g_data[2][6],"24"
55+ FSfseek, // g_data[2][7],"28"
56+ FSrewind, // g_data[2][8],"32"
57+ FindFirst,// g_data[2][9],"36"
58+ FindNext, // g_data[2][10],"40"
59+ FSmkdir, // g_data[2][11],"44"
60+ FSgetcwd, // g_data[2][12],"48"
61+ FSchdir, // g_data[2][13],"52"
62+ FSremove, // g_data[2][14],"56"
63+ FSrename, // g_data[2][15],"60"
64+#endif
65+};
66+
67+const void* const g_data_clib_video[]={
68+ start_composite,// g_data[3][0],"0"
69+ stop_composite, // g_data[3][1],"4"
70+ printchar, // g_data[3][2],"8"
71+ printstr, // g_data[3][3],"12"
72+ printnum, // g_data[3][4],"16"
73+ printnum2, // g_data[3][5],"20"
74+ cls, // g_data[3][6],"24"
75+ vramscroll, // g_data[3][7],"28"
76+ setcursorcolor, // g_data[3][8],"32"
77+ setcursor, // g_data[3][9],"36"
78+ set_palette, // g_data[3][10],"40"
79+ set_bgcolor, // g_data[3][11],"44"
80+};
81+
82+const void* const g_data_clib_graphic[]={
83+ g_pset, // g_data[4][0],"0"
84+ g_putbmpmn, // g_data[4][1],"4"
85+ g_clrbmpmn, // g_data[4][2],"8"
86+ g_gline, // g_data[4][3],"12"
87+ g_hline, // g_data[4][4],"16"
88+ g_circle, // g_data[4][5],"20"
89+ g_circlefill, // g_data[4][6],"24"
90+ g_boxfill, // g_data[4][7],"28"
91+ g_putfont, // g_data[4][8],"32"
92+ g_printstr, // g_data[4][9],"36"
93+ g_printnum, // g_data[4][10],"40"
94+ g_printnum2, // g_data[4][11],"44"
95+ g_color, // g_data[4][12],"48"
96+};
97+
98+const void* const g_data_clib_keyboard[]={
99+ shiftkeys, // g_data[5][0],"0"
100+ ps2readkey,// g_data[5][1],"4"
101+};
102+
103+const void* const g_data_clib[]={
104+ &g_data_clib_var[0], // g_data[0],"0"
105+ &g_data_clib_core[0], // g_data[1],"4"
106+ &g_data_clib_file[0], // g_data[2],"8"
107+ &g_data_clib_video[0], // g_data[3],"12"
108+ &g_data_clib_graphic[0], // g_data[4],"16"
109+ &g_data_clib_keyboard[0],// g_data[5],"20"
110+};
111+
112+// CLIB name used (name as 31 bit integer)
113+static unsigned int g_clib;
114+
115+void init_clib(){
116+ // Initialize g_data_clib_var[]
117+ g_data_clib_var[0]=(void*)g_gp;
118+}
119+
120+char* useclib_statement(){
121+ int i;
122+ int* cmpdata;
123+ do {
124+ next_position();
125+ i=check_var_name();
126+ if (i<65536) return ERR_SYNTAX;
127+ // Check if the clib already exists
128+ cmpdata_reset();
129+ while(cmpdata=cmpdata_find(CMPDATA_USECLIB)){
130+ if (cmpdata[1]==i) {
131+ // The clib was already defined.
132+ i=0;
133+ break;
134+ }
135+ }
136+ if (i) {
137+ // Load new file to define clib.
138+ g_clib=i;
139+ return ERR_COMPILE_CLIB;
140+ }
141+ if (g_source[g_srcpos]==',') {
142+ g_srcpos++;
143+ } else {
144+ break;
145+ }
146+ } while(1);
147+ return 0;
148+}
149+
150+void* call_clib_init(void** data, void* address){
151+ // Store gp and ra
152+ asm volatile("#":::"s0");
153+ asm volatile("#":::"ra");
154+ asm volatile("addu $t9,$a1,$zero");
155+ asm volatile("addu $s0,$gp,$zero");
156+ asm volatile("jalr $ra,$t9");
157+ asm volatile("addu $gp,$s0,$zero");
158+}
159+
160+char* clib_main(){
161+ char* err;
162+ unsigned int begin,end,addr;
163+ void* clibdata;
164+ int* functions;
165+ int* got;
166+ int i,opos,adjust;
167+ char* clib;
168+ int record[3];
169+ // Insert CMPDATA_USELIB
170+ record[0]=g_clib;
171+ err=cmpdata_insert(CMPDATA_USECLIB,0,&record[0],1);
172+ if (err) return err;
173+ // Determine begin and end addresses
174+ begin=0x000fffff;
175+ end=0;
176+ while(1){
177+ err=hex_read_line();
178+ if (err) return err;
179+ if (g_hexline.type==1) {
180+ // EOF
181+ break;
182+ } else if (g_hexline.type==4) {
183+ // extended linear address
184+ addr=g_hexline.data[0];
185+ addr=addr<<8;
186+ addr|=g_hexline.data[0];
187+ addr=addr<<16;
188+ } else if (g_hexline.type==0) {
189+ // data
190+ addr&=0xffff0000;
191+ addr|=g_hexline.address;
192+ if (addr<begin) begin=addr;
193+ if (end<addr && addr<0x000fffff) {
194+ end=addr+g_hexline.size;
195+ }
196+ } else {
197+ // Unknown type
198+ return ERR_HEX_ERROR;
199+ }
200+ }
201+ hex_reinit_file();
202+ // Assign and clear region
203+ check_obj_space((end-begin+3)>>2);
204+ clib=(char*)&g_object[g_objpos];
205+ got=(int*)&g_object[g_objpos];
206+ for(i=0;i<((end-begin+3)>>2);i++) g_object[g_objpos++]=0;
207+ // Load binary from HEX file
208+ while(1){
209+ err=hex_read_line();
210+ if (err) return err;
211+ if (g_hexline.type==1) {
212+ // EOF
213+ break;
214+ } else if (g_hexline.type==4) {
215+ // extended linear address
216+ addr=g_hexline.data[0];
217+ addr=addr<<8;
218+ addr|=g_hexline.data[0];
219+ addr=addr<<16;
220+ } else if (g_hexline.type==0) {
221+ // data
222+ addr&=0xffff0000;
223+ addr|=g_hexline.address;
224+ for(i=0;i<g_hexline.size;i++){
225+ clib[addr-begin+i]=g_hexline.data[i];
226+ }
227+ } else {
228+ // Unknown type
229+ return ERR_HEX_ERROR;
230+ }
231+ }
232+ // Calculate the adjustment value.
233+ // Note that the address of clib_init() is 0x8000.
234+ adjust=(int)clib+0x8000-begin-0xA0008000;
235+ // Modify Global Offset Table (GOT)
236+ for(i=0;i<(0x8000-begin)>>2;i++){
237+ if ((got[i]&0xFFF00000)==0xA0000000) {
238+ got[i]+=adjust;
239+ }
240+ }
241+ // Call the clib_init() to get the address of clibdata array.
242+ clibdata=call_clib_init((void**)&g_data_clib[0],(void*)(0xA0008000+adjust));
243+ // Check version
244+ if (((int*)clibdata)[0]>SYSVERI) {
245+ return "Newer version of C library than MachiKania cannot be used.";
246+ }
247+ // Get functions array
248+ clibdata=(void*)(((int*)clibdata)[2])+adjust;
249+ functions=clibdata;
250+ // Construct CMPDATA_CLIBFUNC records.
251+ while(clib=(char*)functions[0]){
252+ clibdata=(void*)functions[1];
253+ functions+=2;
254+ // clib is function name as string
255+ // clibdata is address of C function
256+ clib+=adjust;
257+ clibdata+=adjust;
258+ i=str_to_name_int(clib);
259+ if (i<65536) return "Wrong C library function name";
260+ record[0]=g_clib;
261+ record[1]=i;
262+ record[2]=(int)clibdata;
263+ err=cmpdata_insert(CMPDATA_CLIBFUNC,0,&record[0],3);
264+ if (err) return err;
265+ }
266+ // Initial assembly is a jump statement to jump to the the following routine.
267+ g_object[0]=0x08000000 | ((((int)(&g_object[g_objpos]))&0x0FFFFFFF)>>2); // j xxxxxxxx
268+ // Insert initialization code
269+ g_object[g_objpos++]=0x3C050000|((((unsigned int)(0xA0008000+adjust))>>16)&0x0000FFFF); // lui a1,xxxx
270+ g_object[g_objpos++]=0x34A50000|(((unsigned int)(0xA0008000+adjust))&0x0000FFFF); // ori a1,a1,xxxx
271+ call_quicklib_code(call_clib_init,ASM_ADDIU_A0_ZERO_ | 0);
272+ // All done. Shift g_object as the beginning of main BASIC code.
273+ g_object+=g_objpos;
274+ g_objpos=0;
275+ return 0;
276+}
277+
278+char* useclib_begin(char* buff){
279+ int i,j,cwd_id;
280+ char* err;
281+ char* clibname;
282+ char filename[11];
283+ int* record;
284+ // Remove a objects before USECLIB statement
285+ g_objpos=0;
286+ // Insert twp NOP assemblies. This will be replaced by branch statement.
287+ check_obj_space(2);
288+ g_object[g_objpos++]=0x00000000; // nop
289+ g_object[g_objpos++]=0x00000000; // nop
290+ // Construct HEX file name to open
291+ clibname=resolve_label(g_clib);
292+ for(i=0;filename[i]=clibname[i];i++);
293+ filename[i++]='.';
294+ filename[i++]='H';
295+ filename[i++]='E';
296+ filename[i++]='X';
297+ filename[i++]=0;
298+ // Open file in current directory
299+ err=hex_init_file(buff,filename);
300+ if (!err) {
301+ // HEX file found in current directory.
302+ err=clib_main();
303+ hex_close_file();
304+ } else {
305+ // Hex file not found in current directory.
306+ // Find it in LIB directory.
307+ if (!FSgetcwd(buff,256)) return ERR_UNKNOWN;
308+ for(i=0;buff[i];i++);
309+ cwd_id=cmpdata_get_id();
310+ if (!cwd_id) return ERR_UNKNOWN;
311+ err=cmpdata_insert(CMPDATA_TEMP,cwd_id,(int*)(&buff[0]),(i+1+3)>>2);
312+ if (err) return err;
313+ // Change current directory to class library directory
314+ for(i=0;buff[i]="\\LIB\\"[i];i++);
315+ for(j=0;buff[i++]=clibname[j];j++);
316+ buff[i]=0;
317+ FSchdir(buff);
318+ err=hex_init_file(buff,filename);
319+ if (!err) {
320+ // HEX file found in LIB directory
321+ err=clib_main();
322+ hex_close_file();
323+ } else {
324+ err=ERR_NO_CLIB;
325+ }
326+ // Restore current dirctory
327+ cmpdata_reset();
328+ while(record=cmpdata_find(CMPDATA_TEMP)){
329+ if ((record[0]&0xffff)==cwd_id) break;
330+ }
331+ if (!record) return ERR_UNKNOWN;
332+ FSchdir((char*)(&record[1]));
333+ cmpdata_delete(record);
334+ }
335+ return err;
336+}
337+
338+void lib_clib(int* params, void* address){
339+ // Store gp and ra
340+ asm volatile("#":::"s0");
341+ asm volatile("#":::"ra");
342+ asm volatile("addu $t9,$a1,$zero");
343+ asm volatile("addu $s0,$gp,$zero");
344+ asm volatile("lw $a3,16($a0)");
345+ asm volatile("lw $a2,12($a0)");
346+ asm volatile("lw $a1,8($a0)");
347+ asm volatile("lw $a0,4($a0)");
348+ asm volatile("jalr $ra,$t9");
349+ asm volatile("addu $gp,$s0,$zero");
350+}
351+
352+char* clib_method(char type){
353+ char* err;
354+ int* record;
355+ int clib,func;
356+ int numparams,stack,spos;
357+ // CLIB name
358+ next_position();
359+ spos=g_srcpos;
360+ clib=check_var_name();
361+ if (clib<65536) return ERR_SYNTAX;
362+ // Check if the clib exists
363+ cmpdata_reset();
364+ while (record=cmpdata_find(CMPDATA_USECLIB)){
365+ if (record[1]==clib) break;
366+ }
367+ if (!record) {
368+ g_srcpos=spos;
369+ return ERR_NO_CLIB;
370+ }
371+ if (g_source[g_srcpos++]!=':') return ERR_SYNTAX;
372+ if (g_source[g_srcpos++]!=':') return ERR_SYNTAX;
373+ // Function name
374+ func=check_var_name();
375+ if (func<65536) return ERR_SYNTAX;
376+ cmpdata_reset();
377+ while (record=cmpdata_find(CMPDATA_CLIBFUNC)){
378+ if (record[1]==clib && record[2]==func) break;
379+ }
380+ if (!record) return "Function not found in the C library";
381+ // Check type and following syntax
382+ if (type==',') {
383+ // This is CLIB(CLASS:METHOD) style
384+ } else {
385+ // Type is either 0 (integer), $ (string), or # (float)
386+ // This is CLASS::METHOD() style
387+ if (type) {
388+ if (g_source[g_srcpos++]!=type) return ERR_SYNTAX;
389+ }
390+ if (g_source[g_srcpos++]!='(') return ERR_SYNTAX;
391+ }
392+ // Construct parameter(s)
393+ next_position();
394+ numparams=0;
395+ if (','==type && g_source[g_srcpos]!=',') {
396+ // This is CLIB(CLASS:METHOD) style
397+ // no parameter
398+ } else if (','!=type && g_source[g_srcpos]==')') {
399+ // This is CLASS::METHOD() style
400+ // no parameter
401+ } else {
402+ // There is parameter(s)
403+ do {
404+ numparams++;
405+ if (4<numparams) return ERR_SYNTAX;
406+ else if (1==numparams) {
407+ check_obj_space(1);
408+ stack=g_objpos++;
409+ }
410+ if (g_source[g_srcpos]==',') g_srcpos++;
411+ g_object[stack]=0x27BD0000|(65536-numparams*4); // addiu sp,sp,-xx
412+ err=get_stringFloatOrValue();
413+ if (err) return err;
414+ check_obj_space(1);
415+ g_object[g_objpos++]=0xAFA20000|(numparams*4); // sw v0,xx(sp)
416+ next_position();
417+ } while (g_source[g_srcpos]==',');
418+ }
419+ // Call CLIB
420+ check_obj_space(2);
421+ g_object[g_objpos++]=0x3C050000|(((unsigned int)record[3])>>16); // lui a1,xxxx
422+ g_object[g_objpos++]=0x34A50000|(((unsigned int)record[3])&0x0000FFFF); // ori a1,a1,xxxx
423+ call_quicklib_code(lib_clib,ASM_ADDU_A0_SP_ZERO); // All done
424+ check_obj_space(1);
425+ if (numparams) g_object[g_objpos++]=0x27BD0000|(numparams*4); // addiu sp,sp,xx
426+ return 0;
427+}
428+
429+char* clib_statement(){
430+ return clib_method(',');
431+}
\ No newline at end of file
--- /dev/null
+++ b/mips/zoea/clib.txt
@@ -0,0 +1,108 @@
1+<Cライブラリーの利用方法>
2+
3+まず、Cライブラリーの使い方について述べます。作成方法については、下の方を参照して
4+下さい。
5+
6+Cライブラリーの本体は、「*.HEX」ファイルです。拡張子が「HEX」のファイルが、BASIC
7+プログラムが置かれているのと同じディレクトリーか、LIBディレクトリーの所定の場所に
8+ある事を確認して下さい。
9+
10+BASICプログラム中では、まず冒頭でUSECLIBステートメントを記述して下さい。
11+
12+USECLIB x[,y[,z[, ... ]]]
13+ Cライブラリーの利用を宣言する。x,y,z等は、ライブラリー名を6文字以内の英数字
14+ で指定。
15+
16+ここでは、「*.HEX」ファイルのファイル名を、指定します。「TCLIB.HEX」なら
17+「USECLIB TCLIB」と記述します。
18+
19+Cライブラリー内の関数を呼び出すには、以下のいずれかの方法を取ります。それぞれの
20+関数の詳しい使用方法については、Cライブラリーに付属のドキュメントを参照して下さ
21+い。
22+
23+CLIB xxx::yyy[,z1[,z2 ...]]
24+ Cライブラリー内の関数を呼び出す。xxxはライブラリー名、yyyは関数名。z1, z2等
25+ は引数(オプション)。
26+CLIB(xxx::yyy[,z1[,z2 ... ]])
27+ Cライブラリー内の関数を呼び出し、整数を返す。xxxはライブラリー名、yyyは関数
28+ 名。z1, z2等は引数(オプション)。xxx::yyy([z1[,z2 ... ]])と書いても同じ。
29+CLIB$(xxx::yyy[,z1[,z2 ... ]])
30+ Cライブラリー内の関数を呼び出し、文字列を返す。xxxはライブラリー名、yyyは関
31+ 数名。z1, z2等は引数(オプション)。xxx::yyy$([z1[,z2 ... ]])と書いても同じ。
32+CLIB#(xxx::yyy[,z1[,z2 ... ]])
33+ Cライブラリー内の関数を呼び出し、実数を返す。xxxはライブラリー名、yyyは関
34+ 数名。z1, z2等は引数(オプション)。xxx::yyy#([z1[,z2 ... ]])と書いても同じ。
35+
36+<使用例>
37+
38+USECLIB TCLIB
39+PRINT TCLIB::TEST$(0)
40+PRINT TCLIB::TEST$(1)
41+
42+<Cライブラリーの作成方法>
43+
44+Cライブラリーを作製する場合には、MPLAB X IDEとXC32コンパイラーのver 1.42以降が
45+必要です。
46+
47+まず、ライブラリー作成用のテンプレートをダウンロードして下さい。少なくとも、次の
48+ファイルが含まれているはずです。
49+
50+clib.c
51+clib.h
52+clib_p32MX370F512H.ld
53+example.c
54+
55+「File->Project Properties」を選択します。次の設定を確認し、異なっていれば値を
56+変更してください。
57+ Categories: Conf
58+ Compiler Toochains: XC32 (v1.42以降)
59+ Categories: xc32-gcc
60+ Additinal options: -mgen-pie-static
61+ Option categories: Optimization
62+ optimization-level: 1
63+ Generated Command Line: -g -O1
64+ Categories: xc32-ld
65+ Additional options: --no-data-init
66+ Option categories: General
67+ Remove unused sections: チェックを入れる
68+ Option categories: Libraries
69+ Exclude Standard Libraries: チェックを入れる
70+ Generated Command Line: --gc-sections --no-code-in-dinit --no-dinit-in-serial-mem -nostdlib -Map="${DISTDIR}/${PROJECTNAME}.${IMAGE_TYPE}.map"
71+
72+clib.c, clib.h, clib_p32MX370F512H.ldの3つは、通常は編集せずにそのまま使います。
73+example.cを編集(必要ならばファイル名を変更)する事で、Cライブラリーを作製して下さ
74+い。コンパイルして出来たHEXファイルが、完成した本体です。
75+
76+<Cライブラリーの仕様>
77+
78+Cライブラリーを作成するにあたり、以下の規約に従って下さい。
79+
80+1.グローバル変数・スタティック変数領域の容量は、128バイト。
81+ ・20個ほどのグローバル変数・スタティック変数が使用可能。
82+ ・大きなメモリー領域が必要な場合は、malloc(), calloc(), free()を使用する。
83+ ・グローバル変数の初期化は、init()関数で行なわなければならない。
84+ ・スタティック変数は実行前の初期化はできない(常に0で初期化される)。
85+
86+2.パブリック関数を、その呼び出し名と共にリストアップする事。
87+ ・functions[]グローバル変数に指定する。
88+ ・フォーマットについては、example.cを参照。
89+
90+3.パブリック関数の引数は、4つまで。
91+
92+4.割り込みは使用出来ない。
93+
94+<グローバル変数領域のサイズ変更>
95+
96+より大きな変数領域が必要な場合は、calloc()で領域を割り当てる事が推奨されます。
97+それでも、グローバル変数領域が足りない場合は、以下の方法でサイズ変更出来ます。
98+
99+1.clib_p[32MC370F512H.ldを編集する。
100+ ・「kseg1_data_mem」の設定の所、「-0x080」と「LENGTH = 0x080」となっている所
101+  を適当なサイズに変更する。
102+
103+2.clib.hを編集する。
104+ ・「#define CLIB_DATA_MEM_SIZE 0x0080」の所、上記で変更した値と同じになるよう
105+  に、編集する。
106+
107+<バージョン履歴>
108+・KM-1209/KM1304 2019年?月公開。
--- a/mips/zoea/compiler.h
+++ b/mips/zoea/compiler.h
@@ -398,6 +398,7 @@ char* coretimer_statement();
398398 char* coretimer_function();
399399 char* interrupt_statement();
400400
401+void init_clib();
401402 char* useclib_statement();
402403 char* useclib_begin(char* buff);
403404 char* clib_method(char type);
--- /dev/null
+++ b/mips/zoea/hexfile.c
@@ -0,0 +1,271 @@
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+ : 02 0000 04 1fc0 1b
26+ : 00 0000 01 FF
27+
28+ Record types:
29+ case 0: // data
30+ case 4: // extended linear address
31+ case 1: // EOF
32+
33+*/
34+
35+/*
36+ Example of HEX file
37+
38+:020000040000fa
39+:1080000000001c3c707f9c2721e09903e0ffbd2706
40+:108010001c00bfaf1000bcaf0e0080101880828f14
41+:10802000000044ac1c80828f80ff42241c80848f1f
42+:10803000000040a0010042242b184400fdff6054c2
43+:10804000000040a02080998f09f820030000000064
44+:108050001000bc8f2480828f1c00bf8f0800e003bb
45+:048060002000bd2718
46+:020000040000fa
47+:107f80000000000000000080a47f00a0008000a08e
48+:107f9000708000a0fc8000a0000001a0788000a0fc
49+:047fa00000000000dd
50+:020000040000fa
51+:108070000800e0030000000000001c3cf87e9c2784
52+:1080800021e09903040080542880828f2880828f09
53+:108090000800e003d48042240800e003e480422486
54+:1080a00000001c3cd07e9c2721e09903e0ffbd2707
55+:1080b0001c00bfaf1000bcaf2c80998f09f82003c3
56+:1080c000000000001000bc8f1c00bf8f0800e00300
57+:0480d0002000bd27a8
58+:020000040000fa
59+:1080d40048656c6c6f20576f726c6421000000005f
60+:1080e4005468697320697320612074657374000097
61+:0880f400544553540000000044
62+:020000040000fa
63+:1080fc0040010000800000001c8100a00000000076
64+:020000040000fa
65+:10810c0000000000222222222222222222222222cb
66+:020000040000fa
67+:0c811c00f48000a0a08000a00000000083
68+:00000001FF
69+*/
70+
71+// Use the same global vars in file.c
72+extern FSFILE* g_fhandle;
73+extern char* g_fbuff;
74+extern int g_size;
75+extern int g_filepoint;
76+// Vars used only in this file
77+static unsigned char g_checksum;
78+
79+void hex_read_file(int blocklen){
80+ int i;
81+ if (blocklen==512) {
82+ // This is first read. Initialize parameter(s).
83+ g_srcpos=0;
84+ g_filepoint=0;
85+ } else if (g_size<512) {
86+ // Already reached the end of file.
87+ return;
88+ } else {
89+ // Shift buffer and source position 256 bytes.
90+ for(i=0;i<256;i++) g_fbuff[i]=g_fbuff[i+256];
91+ g_srcpos-=256;
92+ g_filepoint+=256;
93+ }
94+ // Read 512 or 256 bytes from SD card.
95+ g_size=512-blocklen+FSfread((void*)&g_fbuff[512-blocklen],1,blocklen,g_fhandle);
96+ // All lower cases
97+ for(i=512-blocklen;i<512;i++){
98+ if ('A'<=g_fbuff[i] && g_fbuff[i]<='F') g_fbuff[i]+=0x20;
99+ }
100+}
101+
102+int hex_read_byte(){
103+ unsigned char b1,b2;
104+ b1=g_fbuff[g_srcpos++];
105+ b2=g_fbuff[g_srcpos++];
106+ if ('0'<=b1 && b1<='9') {
107+ b1-='0';
108+ } else if ('a'<=b1 && b1<='f') {
109+ b1-='a';
110+ b1+=0x0a;
111+ } else {
112+ return -1;
113+ }
114+ if ('0'<=b2 && b2<='9') {
115+ b2-='0';
116+ } else if ('a'<=b2 && b2<='f') {
117+ b2-='a';
118+ b2+=0x0a;
119+ } else {
120+ return -1;
121+ }
122+ b1=(b1<<4)|b2;
123+ g_checksum+=b1;
124+ return b1;
125+}
126+
127+char* hex_read_line(){
128+ int i,j;
129+ // Initialize checksum
130+ g_checksum=0;
131+ // Maintain at least 256 characters in cache.
132+ if (256<=g_srcpos) hex_read_file(256);
133+ // Read a hex file line
134+ if (g_fbuff[g_srcpos++]!=':') return ERR_HEX_ERROR;
135+ // Read size
136+ i=hex_read_byte();
137+ if (i<0) return ERR_HEX_ERROR;
138+ g_hexline.size=(unsigned char)i;
139+ // Read address
140+ i=hex_read_byte();
141+ if (i<0) return ERR_HEX_ERROR;
142+ g_hexline.address=(unsigned short)(i<<8);
143+ i=hex_read_byte();
144+ if (i<0) return ERR_HEX_ERROR;
145+ g_hexline.address|=(unsigned short)(i);
146+ // Ready type
147+ i=hex_read_byte();
148+ if (i<0) return ERR_HEX_ERROR;
149+ g_hexline.type=(unsigned char)i;
150+ // Read data
151+ for(j=0;j<g_hexline.size;j++){
152+ i=hex_read_byte();
153+ if (i<0) return ERR_HEX_ERROR;
154+ g_hexline.data[j]=(unsigned char)i;
155+ }
156+ // Read checksum
157+ i=hex_read_byte();
158+ if (i<0) return ERR_HEX_ERROR;
159+ if (g_checksum) return ERR_HEX_ERROR;
160+ // All done. Remove enter.
161+ if (g_fbuff[g_srcpos]=='\r') g_srcpos++;
162+ if (g_fbuff[g_srcpos]=='\n') g_srcpos++;
163+ return 0;
164+}
165+
166+static char g_hex_line[47]=":";
167+void hex_construct_byte(unsigned char data,int pos){
168+ g_hex_line[pos+0]="0123456789abcdef"[data>>4];
169+ g_hex_line[pos+1]="0123456789abcdef"[data&15];
170+ g_checksum+=data;
171+}
172+char* hex_construct_line(){
173+ int i;
174+ g_checksum=0;
175+ // Write size
176+ hex_construct_byte(g_hexline.size,1);
177+ // Write address
178+ hex_construct_byte(g_hexline.address>>8,3);
179+ hex_construct_byte(g_hexline.address&0xff,5);
180+ // Write type
181+ hex_construct_byte(g_hexline.type,7);
182+ // Write data
183+ for(i=0;i<g_hexline.size;i++){
184+ hex_construct_byte(g_hexline.data[i],9+i*2);
185+ }
186+ // Write checksum
187+ hex_construct_byte(0-g_checksum,9+i*2);
188+ // All done. Add CRLF and 0x00
189+ g_hex_line[11+i*2]=0x0d;
190+ g_hex_line[12+i*2]=0x0a;
191+ g_hex_line[13+i*2]=0;
192+ return (char*)&g_hex_line[0];
193+}
194+
195+void hex_reinit_file(){
196+ // Go to point 0
197+ FSfseek(g_fhandle,0,SEEK_SET);
198+ // Initialize parameters
199+ g_srcpos=0;
200+ g_filepoint=0;
201+ // Read first 512 bytes
202+ hex_read_file(512);
203+}
204+
205+char* hex_init_file(char* buff,char* filename){
206+ // Open file
207+ g_fhandle=FSfopen(filename,"r");
208+ if (!g_fhandle) {
209+ return ERR_UNKNOWN;
210+ }
211+ // Initialize parameters
212+ g_fbuff=buff;
213+ g_source=buff;
214+ g_srcpos=0;
215+ g_filepoint=0;
216+ // Read first 512 bytes
217+ hex_read_file(512);
218+ return 0;
219+}
220+
221+void hex_close_file(){
222+ FSfclose(g_fhandle);
223+}
224+
225+char* hex_write(FSFILE* fhandle){
226+ int i,j;
227+ char* str;
228+ // Construct the line string.
229+ str=hex_construct_line();
230+ // Determine string length
231+ for(i=0;str[i];i++);
232+ j=FSfwrite(str,1,i,fhandle);
233+ if (j<i) return ERR_FILE;
234+ return 0;
235+}
236+
237+
238+char* hex_write_address(FSFILE* fhandle,unsigned short addr){
239+ int i,j;
240+ char* str;
241+ addr&=0x7fff; // Write 0x1d00 instead of 0x9d00.
242+ g_hexline.size=2;
243+ g_hexline.type=4;
244+ g_hexline.address=0;
245+ g_hexline.data[0]=addr>>8;
246+ g_hexline.data[1]=addr&0xff;
247+ return hex_write(fhandle);
248+}
249+
250+char* hex_write_data_16(FSFILE* fhandle,unsigned short addr,unsigned int* object){
251+ int i,j;
252+ char* str;
253+ g_hexline.size=16;
254+ g_hexline.type=0;
255+ g_hexline.address=addr;
256+ for(i=0;i<4;i++){
257+ g_hexline.data[i*4+0]=object[i];
258+ g_hexline.data[i*4+1]=object[i]>>8;
259+ g_hexline.data[i*4+2]=object[i]>>16;
260+ g_hexline.data[i*4+3]=object[i]>>24;
261+ }
262+ return hex_write(fhandle);
263+}
264+
265+char* hex_write_eof(FSFILE* fhandle){
266+ int i;
267+ i=FSfwrite(":00000001FF\x0d\x0a",1,13,fhandle);
268+ if (i<13) return ERR_FILE;
269+ return 0;
270+}
271+
--- a/mips/zoea/run.c
+++ b/mips/zoea/run.c
@@ -46,7 +46,7 @@ int runbasic(char *appname,int mode){
4646 //  -1:ファイルエラー
4747 //  -2:リンクエラー
4848 //  1以上:コンパイルエラーの発生行(行番号ではなくファイル上の何行目か)
49- int i;
49+ int i,j;
5050 char* buff;
5151 char* err;
5252
@@ -85,19 +85,23 @@ int runbasic(char *appname,int mode){
8585 // Initialize music system
8686 init_music();
8787
88+ // Initialize clib
89+ init_clib();
90+
8891 printstr("BASIC "BASVER"\n");
8992 wait60thsec(15);
9093
9194 printstr("Compiling...");
9295
9396 if (mode==RUNMODE_COPY_AND_RUN) {
94- // Copy the object from MOS
95- appname=(char*)MACHIKANIA_OBJ_ADDRESS;
96- for(i=0;i<RAMSIZE;i++) RAM[i]=appname[i];
9797 // Set g_object/g_objpos for library functions like lib_read().
9898 // The g_object/g_objpos values are stoared just before MOS.
9999 g_object=(int*)g_object_mos;
100100 g_objpos=g_objpos_mos;
101+ // Copy the object from MOS
102+ j=(int)(&g_object[g_objpos])-(int)(&RAM[0]);
103+ appname=(char*)MACHIKANIA_OBJ_ADDRESS;
104+ for(i=0;i<j;i++) RAM[i]=appname[i];
101105 } else {
102106 // Initialize compiler
103107 cmpdata_init();