OSDN Git Service

785bf0393fb6c1e0ba1a8bd98f47ab78d727ebf9
[heavyosecpu/HeavyOSECPU.git] / main.c
1 #include "osecpu.h"\r
2 \r
3 int *keybuf, keybuf_r, keybuf_w, keybuf_c;\r
4 HOSECPU_Device_Window mainWindow;\r
5 //デバッグ用。プログラム中の随所で加算される変数\r
6 int di1_serial;\r
7 \r
8 \r
9 \r
10 unsigned char *Init_LoadSysLib(char argv0[], unsigned char *tmpWorkMemory);\r
11 void LoadAppBin(HOSECPU_RuntimeEnvironment *env);\r
12 \r
13 void putKeybuf(int i)\r
14 {\r
15         if (keybuf_c < KEYBUFSIZ) {\r
16                 keybuf[keybuf_w] = i;\r
17                 keybuf_c++;\r
18                 keybuf_w = (keybuf_w + 1) & (KEYBUFSIZ - 1);\r
19         }\r
20         return;\r
21 }\r
22 \r
23 int HeavyOSECPUMain(int argc, char **argv)\r
24 {\r
25         FILE *fp;\r
26         unsigned char *jitbuf, *sysjit00, *sysjit;\r
27         unsigned char *systmp0, *systmp1, *systmp2;\r
28         unsigned char *opTbl;\r
29         HOSECPU_LabelListTag *label;\r
30         int tmpsiz, i;\r
31         double tm0, tm1, tm2;\r
32         HOSECPU_PointerControlTag *ptrCtrl;\r
33         unsigned char *syslib;\r
34         int argDebug = 0, stacksiz = 1;\r
35         const  char *cp;\r
36         HOSECPU_RuntimeEnvironment env;\r
37         void(*jitfunc)(char *);\r
38         unsigned char *jp;\r
39         \r
40         //Initialize mainWindow\r
41         mainWindow.vram = NULL;\r
42         mainWindow.xsize = 0;\r
43         mainWindow.ysize = 0;\r
44         di1_serial = 0;\r
45         \r
46         //実行環境初期化\r
47         env.mainArgc = argc;\r
48         env.mainArgv = (const char **)argv;\r
49         env.appBin = malloc(APPSIZ1);\r
50         env.executionLevel = JITC_LV_SLOWEST;\r
51         jitbuf = mallocRWE(1024 * 1024); /* とりあえず1MBで */\r
52         //unsigned char *sysjit0 = mallocRWE(SJITSIZ1), *sysjit1 = sysjit0, *sysjit00 = sysjit0;\r
53         // syslib.oseのjitc結果を格納する領域を確保。\r
54         sysjit00 = mallocRWE(SJITSIZ1);\r
55         sysjit = sysjit00;\r
56         // 現在の、jitc結果を格納するメモリへの書き込み位置のアドレス\r
57         // sysjit: 現在のjitc書き込み位置\r
58         // sysjit00: jitc結果の先頭\r
59         //ワークメモリを三つくらいもらう\r
60         systmp0 = malloc(SYSTMP0SIZ);   /* syslibのjitc用 */\r
61         systmp1 = malloc(SYSTMP1SIZ);\r
62         systmp2 = malloc(1024 * 1024);\r
63         \r
64         opTbl = malloc(256);\r
65         label = malloc(JITC_MAXLABELS * sizeof (HOSECPU_LabelListTag));\r
66         keybuf = malloc(KEYBUFSIZ * sizeof (int));\r
67         keybuf_r = keybuf_w = keybuf_c = 0;\r
68         ptrCtrl = malloc(PTRCTRLSIZ * sizeof (HOSECPU_PointerControlTag));\r
69         \r
70         randStatInit((unsigned int)time(NULL));\r
71         for (i = 0; i < PTRCTRLSIZ; i++) {\r
72                 ptrCtrl[i].liveSign = 0;\r
73                 ptrCtrl[i].size = -1;\r
74         }\r
75         ptrCtrl[0].size = -2;\r
76         \r
77         /* syslibの読み込み */\r
78         syslib = Init_LoadSysLib(argv[0], systmp0);\r
79         \r
80         sysjit = jitCompInit(sysjit);\r
81         sysjit00 = sysjit;\r
82         // labelはjitc0()内で初期化される。\r
83         i = jitc0(&sysjit, sysjit00 + SJITSIZ1, syslib + 32, syslib + SYSLIBSIZ1, JITC_LV_SLOWEST+9, label);\r
84         if (i != 0){\r
85                 fputs("syslib-file JITC error.\n", stderr);\r
86                 return 1;\r
87         }\r
88         \r
89         // エラー時にデバッグ用に表示する変数を加算\r
90         di1_serial++;\r
91         \r
92         /* アプリバイナリの読み込み */\r
93         LoadAppBin(&env);\r
94         \r
95         /* クロック初期化 */\r
96         tm0 = clock() / (double)CLOCKS_PER_SEC;\r
97         \r
98         if (env.appBin[2] == 0xf0) {\r
99                 // tek5圧縮がかかっている\r
100 #if (USE_TEK5 != 0)\r
101                 env.appSize1 = tek5Decomp(env.appBin + 2, env.appBin + env.appSize0, systmp0);\r
102                 env.appSize1 += 2;\r
103 #else\r
104                 env.appSize1 = -9;\r
105 #endif\r
106                 if (env.appSize1 < 0) {\r
107                         fputs("unsupported-format(tek5)\n", stderr);\r
108                         return 1;\r
109                 }\r
110         }\r
111         //デバッグモード指定\r
112         cp = searchArg(argc, (const char **)argv, "debug:", 0);\r
113         if (cp != NULL){\r
114                 argDebug = *cp - '0';\r
115         }\r
116         //スタックサイズ指定(MiB単位)\r
117         cp = searchArg(argc, (const char **)argv, "stack:", 0);\r
118         if (cp != NULL){\r
119                 stacksiz = strtol(cp, NULL, 0);\r
120         }\r
121 \r
122         // jitbufは先頭。 jpは現在位置\r
123         jp = jitbuf; /* JIT-pointer */\r
124         \r
125         /* フロントエンドコードをバックエンドコードに変換する */\r
126         if ((env.appBin[2] & 0xf0) != 0) {                              // 3バイト目が00なら処理しない\r
127                 systmp0[0] = env.appBin[0];\r
128                 systmp0[1] = env.appBin[1];\r
129                 env.preg[2].p = systmp0 + 2;\r
130                 env.preg[3].p = systmp0 + SYSTMP0SIZ;\r
131                 env.preg[4].p = env.appBin + 2;\r
132                 env.preg[5].p = env.appBin + env.appSize1;\r
133                 env.preg[6].p = systmp1;\r
134                 env.preg[7].p = systmp1 + SYSTMP1SIZ;\r
135                 env.preg[10].p = systmp2;\r
136                 int pxxFlag[64], typLabel[4096];\r
137                 env.preg[0x0b].p = (void *)pxxFlag;\r
138                 env.preg[0x0c].p = (void *)typLabel;\r
139                 env.preg[0x0d].p = opTbl;\r
140                 jitfunc = (void *)sysjit00;\r
141                 (*jitfunc)(((char *)&env) + 128); /* サイズを節約するためにEBPを128バイトずらす */\r
142                 if (env.ireg[0] != 0) {\r
143                         jp = env.preg[2].p - 1;\r
144                         fprintf(stderr, "unpack error: %02X (at %06X) (R00=%d)\n", *jp, jp - systmp0, env.ireg[0]);\r
145                         if ((argDebug & 2) != 0) {\r
146                                 fp = fopen("debug2.bin", "wb");\r
147                                 fwrite(systmp0, 1, jp - systmp0 + 16, fp);\r
148                                 fclose(fp);\r
149                         }\r
150                         exit(1);\r
151                 }\r
152                 tmpsiz = env.preg[2].p - systmp0;\r
153         } else{\r
154                 memcpy(systmp0, env.appBin, env.appSize1);\r
155                 tmpsiz = env.appSize1;\r
156         }\r
157         \r
158         if ((argDebug & 2) != 0) {\r
159                 /*変換後のバックエンドコードをファイルへ保存*/\r
160                 fp = fopen("debug2.bin", "wb");\r
161                 fwrite(systmp0, 1, tmpsiz, fp);\r
162                 fclose(fp);\r
163         }\r
164         \r
165         //JITコンパイル\r
166         i = jitc0(&jp, jitbuf + 1024 * 1024, systmp0, systmp0 + tmpsiz, env.executionLevel, label);\r
167         if (i == 1){\r
168                 fputs("app-file header error.\n", stderr);\r
169                 return 1;\r
170         }\r
171         if (i != 0){\r
172                 return 1;\r
173         }\r
174         di1_serial++;\r
175         \r
176         int appsiz2 = jp - jitbuf;\r
177         \r
178         unsigned char *p28 = jp;\r
179         jp = jitCompCallFunc(jp, &devFunc);\r
180         \r
181         tm1 = clock() / (double)CLOCKS_PER_SEC;\r
182         \r
183         /* レジスタ初期化 */\r
184         for (i = 0; i < 64; i++){\r
185                 env.ireg[i] = 0;\r
186         }\r
187         for (i = 0; i < 64; i++) {\r
188                 env.preg[i].p = NULL;\r
189                 env.preg[i].typ = -1;\r
190                 env.preg[i].p0 = NULL;\r
191                 env.preg[i].p1 = NULL;\r
192         }\r
193         \r
194         env.buf0 = env.buf1 = NULL;\r
195 \r
196         // p28にapiをコールするアドレスを設定\r
197         env.preg[0x28].p = p28; // p28には、devFuncをコールするコードが書かれている\r
198         env.preg[0x28].typ = 0; // TYP_CODE\r
199         env.preg[0x28].p0 = p28;                // アドレス演算できる範囲を制限\r
200         env.preg[0x28].p1 = p28 + 1;    // アドレス演算できる範囲を制限\r
201 \r
202         //env.preg[0x00].p = malloc(1024 * 1024) + (1024 * 1024 - 32);\r
203         env.junkStack = malloc(stacksiz << 20);\r
204         env.junkStack1 = env.junkStack + (stacksiz << 20);\r
205         env.winClosed = 0;\r
206         env.autoSleep = 0;\r
207         env.lastConsoleChar = '\n';\r
208         \r
209         env.label = label;\r
210         env.maxLabels = JITC_MAXLABELS;\r
211         env.jitbuf = jp;\r
212         env.jitbuf1 = jitbuf + 1024 * 1024;\r
213         env.errHndl = &errorHandler;\r
214         env.appReturnCode = 0;\r
215         \r
216         env.dbgr = 0;\r
217         if (searchArg(argc, (const char **)argv, "dbgr:1", 0) != NULL){\r
218                 env.dbgr = 1;\r
219         }\r
220         \r
221         if ((argDebug & 1) != 0) {\r
222                 fp = fopen("debug1.bin", "wb");\r
223                 fwrite(jitbuf, 1, jp - jitbuf, fp);\r
224                 fclose(fp);\r
225         }\r
226         \r
227         /* JITコード実行 */\r
228         jitfunc = (void *)jitbuf;\r
229         if (setjmp(env.setjmpEnv) == 0){\r
230                 (*jitfunc)(((char *)&env) + 128); /* サイズを節約するためにEBPを128バイトずらす */\r
231         }\r
232         if (env.autoSleep != 0) {\r
233                 if (mainWindow.vram != NULL){\r
234                         drv_flshWin(mainWindow.xsize, mainWindow.ysize, 0, 0);\r
235                 }\r
236                 while (env.winClosed == 0){\r
237                         drv_sleep(100);\r
238                 }\r
239         }\r
240         if (env.lastConsoleChar != '\n'){\r
241                 putchar('\n');\r
242         }\r
243         \r
244         tm2 = clock() / (double)CLOCKS_PER_SEC;\r
245         \r
246         /* 実行結果確認のためのレジスタダンプ */\r
247         if (searchArg(argc, (const char **)argv, "verbose:1", 0) != NULL) {\r
248                 printf("time: JITC=%.3f[sec], exec=%.3f[sec]\n", tm1 - tm0, tm2 - tm1);\r
249                 printf("size: OSECPU=%d, decomp=%d, tmp=%d, native=%d\n", env.appSize0, env.appSize1, tmpsiz, appsiz2);\r
250                 printf("result:\n");\r
251                 printf("R00:0x%08X  R01:0x%08X  R02:0x%08X  R03:0x%08X\n", env.ireg[0], env.ireg[1], env.ireg[2], env.ireg[3]);\r
252         }\r
253 #if (USE_DEBUGGER != 0)\r
254         dbgrMain(&env);\r
255 #endif\r
256         return env.appReturnCode;\r
257 }\r
258 \r
259 unsigned char *Init_LoadSysLib(char argv0[], unsigned char *tmpWorkMemory)\r
260 {\r
261         unsigned char *syslib;\r
262         FILE *fp;\r
263         unsigned char *up;\r
264         int appsize;\r
265         \r
266         /* syslibの読み込み */\r
267         syslib = malloc(SYSLIBSIZ1);\r
268         fp = fopen(SYSLIB_OSE, "rb");\r
269         if (fp == NULL) {\r
270                 syslib[0] = '/';\r
271                 strcpy((char *)syslib + 1, argv0);\r
272                 up = syslib + 1;\r
273                 while (*up != '\0'){\r
274                         up++;\r
275                 }\r
276                 while (*up != '/' && *up != 0x5c){\r
277                         up--;\r
278                 }\r
279                 up++;\r
280                 strcpy((char *)up, SYSLIB_OSE);\r
281                 fp = fopen((char *)syslib + 1, "rb");\r
282         }\r
283         if (fp == NULL) {\r
284                 fputs("syslib-file fopen error.\n", stderr);\r
285                 exit(EXIT_FAILURE);\r
286         }\r
287         appsize = fread(syslib, 1, SYSLIBSIZ1 - 4, fp);\r
288         fclose(fp);\r
289         if (appsize >= SYSLIBSIZ1 - 4) {\r
290                 fputs("syslib-file too large.\n", stderr);\r
291                 exit(EXIT_FAILURE);\r
292         }\r
293         if (syslib[0] == 0x05 && syslib[1] == 0xc1) {\r
294                 // maklib のライブラリ形式である。\r
295                 memcpy(tmpWorkMemory, syslib, appsize);\r
296                 ComLib_main(tmpWorkMemory + 2, syslib + 2);\r
297                 syslib[0] = 0x05;\r
298                 syslib[1] = 0x1b;\r
299         }\r
300         \r
301         fp = fopen("syslib_dbg.ose", "wb");\r
302         fwrite(syslib, 1, SYSLIBSIZ1, fp);\r
303         fclose(fp);\r
304         return syslib;\r
305 }\r
306 \r
307 void LoadAppBin(HOSECPU_RuntimeEnvironment *env)\r
308 {\r
309         FILE *fp;\r
310         const char *fileName;\r
311         /* アプリバイナリの読み込み */\r
312         if (env->mainArgc <= 1) {\r
313                 //アプリ名未指定なので何事もなく終了\r
314                 exit(EXIT_SUCCESS);\r
315         }\r
316         fileName = env->mainArgv[1];\r
317         //アプリ名先頭に:n:をつけることでレベルnでの実行が可能?\r
318         if (fileName[0] == ':' && fileName[2] == ':') {\r
319                 env->executionLevel = fileName[1] - '0';\r
320                 if (env->executionLevel < 0 || env->executionLevel > 9){\r
321                         env->executionLevel = JITC_LV_SLOWEST;\r
322                 }\r
323                 fileName += 3;\r
324         }\r
325         \r
326         fp = fopen(fileName, "rb");\r
327         if (fp == NULL) {\r
328                 fputs("app-file load error.\n", stderr);\r
329                 exit(EXIT_FAILURE);\r
330         }\r
331         env->appSize0 = fread(env->appBin, 1, APPSIZ1 - 4, fp);\r
332         env->appSize1 = env->appSize0;\r
333         fclose(fp);\r
334         \r
335         if (env->appSize0 >= APPSIZ1 - 4) {\r
336                 fputs("app-file too large.\n", stderr);\r
337                 exit(EXIT_FAILURE);\r
338         }\r
339         if (env->appSize0 < 3) {\r
340                 fputs("app-file header error.\n", stderr);\r
341                 exit(EXIT_FAILURE);\r
342         }\r
343 }\r