OSDN Git Service

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