Revisión | eefe55010f308d5c8a0604f069e2c96864339927 (tree) |
---|---|
Tiempo | 2014-05-29 02:29:20 |
Autor | hikarupsp <hikarupsp@user...> |
Commiter | hikarupsp |
osecpu106a
@@ -2,3 +2,4 @@ | ||
2 | 2 | a.out |
3 | 3 | make_vm.bat |
4 | 4 | osecpu-test.exe |
5 | +osecpu-test.bin |
@@ -1,5 +1,7 @@ | ||
1 | 1 | CC = cc |
2 | -SRCS = extend.c float.c integer.c osecpu-vm.c pointer.c test.c | |
2 | +SRCS = api.c driver.c extend.c float.c \ | |
3 | + integer.c osecpu-vm.c other.c pointer.c \ | |
4 | + test.c | |
3 | 5 | BINNAME = osecpu-test.bin |
4 | 6 | |
5 | 7 | $(BINNAME): $(SRCS) |
@@ -0,0 +1,76 @@ | ||
1 | +#include "osecpu-vm.h" | |
2 | +#include <setjmp.h> | |
3 | + | |
4 | +const Int32 *apiEntry(OsecpuVm *vm); | |
5 | + | |
6 | +/* driver.c */ | |
7 | +void *mallocRWE(int bytes); // 実行権付きメモリのmalloc. | |
8 | +void drv_openWin(int x, int y, unsigned char *buf, char *winClosed); | |
9 | +void drv_flshWin(int sx, int sy, int x0, int y0); | |
10 | +void drv_sleep(int msec); | |
11 | + | |
12 | +void apiInit(OsecpuVm *vm) | |
13 | +{ | |
14 | + vm->p[0x28].typ = PTR_TYP_NATIVECODE; | |
15 | + vm->p[0x28].p = (void *) &apiEntry; | |
16 | + return; | |
17 | +} | |
18 | + | |
19 | +Int32 apiGetRxx(OsecpuVm *vm, int r, int bit); | |
20 | + | |
21 | +void api0001_putString(OsecpuVm *vm); | |
22 | +void api0002_drawPoint(OsecpuVm *vm); | |
23 | +void api0003_drawLine(OsecpuVm *vm); | |
24 | +void api0004_rect(OsecpuVm *vm); | |
25 | +void api0005_oval(OsecpuVm *vm); | |
26 | +void api0006_drawString(OsecpuVm *vm); | |
27 | +void api0008_exit(OsecpuVm *vm); | |
28 | +void api0009_sleep(OsecpuVm *vm); | |
29 | + | |
30 | +const Int32 *apiEntry(OsecpuVm *vm) | |
31 | +// VMの再開地点を返す. | |
32 | +{ | |
33 | + int func = apiGetRxx(vm, 0x30, 16); | |
34 | + if (vm->errorCode != 0) goto fin; | |
35 | + if (func == 0x0001) { api0001_putString(vm); goto fin; } | |
36 | + if (func == 0x0002) { api0002_drawPoint(vm); goto fin; } | |
37 | + if (func == 0x0003) { api0003_drawLine(vm); goto fin; } | |
38 | + if (func == 0x0004) { api0004_rect(vm); goto fin; } | |
39 | + if (func == 0x0005) { api0005_oval(vm); goto fin; } | |
40 | + if (func == 0x0006) { api0006_drawString(vm); goto fin; } | |
41 | + if (func == 0x0008) { api0008_exit(vm); goto fin; } | |
42 | + if (func == 0x0009) { api0009_sleep(vm); goto fin; } | |
43 | + jitcSetRetCode(&vm->errorCode, EXEC_API_ERROR); | |
44 | +fin: ; | |
45 | + const Int32 *retcode = NULL; | |
46 | + execStep_checkMemAccess(vm, 0x30, PTR_TYP_CODE, EXEC_CMA_FLAG_EXEC); // 主にliveSignのチェック. | |
47 | + if (vm->errorCode == 0) | |
48 | + retcode = (const Int32 *) vm->p[0x30].p; | |
49 | + return retcode; | |
50 | +} | |
51 | + | |
52 | +Int32 apiGetRxx(OsecpuVm *vm, int r, int bit) | |
53 | +{ | |
54 | + Int32 i, value = vm->r[r]; | |
55 | + if (vm->bit[r] != BIT_DISABLE_REG && vm->bit[r] < bit) | |
56 | + jitcSetRetCode(&vm->errorCode, EXEC_BAD_BITS); | |
57 | + i = (-1) << bit; | |
58 | + if ((value & (1 << (bit - 1))) == 0) { | |
59 | + // 符号ビットが0だった. | |
60 | + value &= ~i; | |
61 | + } else { | |
62 | + // 符号ビットが1だった. | |
63 | + value |= i; | |
64 | + } | |
65 | + return value; | |
66 | +} | |
67 | + | |
68 | +void api0001_putString(OsecpuVm *vm) { } | |
69 | +void api0002_drawPoint(OsecpuVm *vm) { } | |
70 | +void api0003_drawLine(OsecpuVm *vm) { } | |
71 | +void api0004_rect(OsecpuVm *vm) { puts("api0004_rect"); } | |
72 | +void api0005_oval(OsecpuVm *vm) { } | |
73 | +void api0006_drawString(OsecpuVm *vm) { } | |
74 | +void api0008_exit(OsecpuVm *vm) { } | |
75 | +void api0009_sleep(OsecpuVm *vm) { } | |
76 | + |
@@ -0,0 +1,56 @@ | ||
1 | +bit[]に関するメモ | |
2 | + | |
3 | +#1. 目的 | |
4 | +整数演算に関するbitは、多倍長演算において、どの精度まで行えば結果が変わらないのかをVMに教えるための手段である。 | |
5 | +したがって、bit=32であってもVMは64ビット演算をするかもしれないし、256ビット演算をするかもしれない。 | |
6 | +しかしそれによって、最終的な結果が少しでも変わることは許さない。 | |
7 | +この情報があればVM(特にJITコンパイラ)は、処理を高速化できる。 | |
8 | + | |
9 | +#2. 注意すべき点 | |
10 | +レジスタやメモリのbitの情報は、高速モードでは一切生成されない。参照もされない。 | |
11 | +あるタスクがあって、それは最初安全モードで動作していたとする。それが一度高速モードに切り替わって、また安全モードに | |
12 | +戻ったとしても、結果は正しく得られなければならない。高速モード中に情報が失われているので、チェック能力が下がるのは | |
13 | +かまわない。 | |
14 | +つまりbitに依存した動作をすることは許されない。 | |
15 | + | |
16 | +#3. タスクセーブに関すること | |
17 | +タスクセーブでは、不定ビットは全て0か1に初期化される。と思ったが、これは必要ないかもしれない。 | |
18 | +なぜなら高速モードではbitがないので、この不定ビットつぶしができない。つまり他のタスクからの情報が流出しうる。 | |
19 | +となれば、やはり消すのは別のところでやるべきだ。malloc時に重要であると明示させるのがよさそう。 | |
20 | +そうすればVMもしくはOSは、free時にゼロクリアできる。 | |
21 | +同じ問題はレジスタでも起こり得る。だから重要な値を持つレジスタは明示的にデータを消さなければいけない。 | |
22 | +その際には必要なビット幅でLIMMをするべき。その後にbit=0のLIMMをしてもしなくてもいい。 | |
23 | +これは2度手間だけど、使用頻度を考えれば妥当。 | |
24 | + | |
25 | +#4. VMは安全モードの場合は、不定ビットをレジスタ内に残さず、常に符号拡張した状態で処理する。 | |
26 | +これは値の範囲チェックをするため。高速モードでは、不定ビットを残していてもよい。 | |
27 | +タスクセーブ時には、不定ビットは殺してしまう。 | |
28 | +しかしこの方法では、高速モードから安全モードに移行した際に問題にならないか? | |
29 | +高速モードではどこまでビットをつぶすべきか分かっていないのだから。 | |
30 | +さてこまった。となると、高速モードから安全モードに戻せないとしたほうがいいのかもしれない。 | |
31 | +もしくはbitに不明という状態を許すか?不明の間は、しょうがないのでチェックができない。 | |
32 | +分かったらすぐにチェックをする。まあこれもありかもしれない。・・・よしこれにしよう。 | |
33 | + | |
34 | +#5. LMEM | |
35 | + | |
36 | + | |
37 | + | |
38 | +#6. SMEM | |
39 | +(1)SINT32のメモリに対して、bit=16のデータを書き込むことは許される。 | |
40 | + その場合、メモリのbitは16になる。書いた値が読み出せるかどうかのチェックはない。 | |
41 | +(2)UINT32のメモリに対して、bit=16のデータを書き込むことは許される。 | |
42 | + その場合、メモリのbitは16になる。書いた値が読み出せるかどうかのチェックは少しある。 | |
43 | + それはデータが負ではないこと。負はどうやっても読み出せないから。 | |
44 | +dat.bit=min(reg.bit, SMEM.bit) | |
45 | +(3)typ.bit >= dat.bit は原則OK。ただし、符号のチェックはある。 | |
46 | + unsignedなtypで、reg<0ならダメ。 | |
47 | +(4)typ.bit < dat.bit の場合は、値の範囲が妥当なら問題ない。範囲がまずければやはりエラーになる。 | |
48 | +(5)2F-0がある場合は、ダメな場合でもメモリのbitが0になるだけで、アプリは例外を起こさずに続行できる。 | |
49 | + しかしそれでも符号のチェックはある。 | |
50 | +(6)2F-0でUINT系を全部エラーにしてしまえばいいかとも思ったけど、レジスタの用法はわからないので、 | |
51 | + 将来のアプリに配慮した。 | |
52 | + | |
53 | +#7. LMEM, SMEMのプリフィクス | |
54 | +2F-0: マスクリード、マスクライト。 | |
55 | +2F-1: レジスタ退避用のリードライト。 | |
56 | +2F-2: メモリのbitを0にする。 |
@@ -0,0 +1,526 @@ | ||
1 | +/* OS依存関数 */ | |
2 | +void *mallocRWE(int bytes); // 実行権付きメモリのmalloc. | |
3 | +void drv_openWin(int x, int y, unsigned char *buf, char *winClosed); | |
4 | +void drv_flshWin(int sx, int sy, int x0, int y0); | |
5 | +void drv_sleep(int msec); | |
6 | + | |
7 | +#if (!defined(JITC_OSNUM)) | |
8 | + #if (defined(_WIN32)) | |
9 | + #define JITC_OSNUM 0x0001 | |
10 | + #endif | |
11 | + #if (defined(__APPLE__)) | |
12 | + #define JITC_OSNUM 0x0002 | |
13 | + #endif | |
14 | + #if (defined(__linux__)) | |
15 | + #define JITC_OSNUM 0x0003 | |
16 | + #endif | |
17 | + /* 0001: win32-x86-32bit */ | |
18 | + /* 0002: MacOS-x86-32bit */ | |
19 | + /* 0003: linux-x86-32bit */ | |
20 | +#endif | |
21 | + | |
22 | +/* OS依存部 */ | |
23 | + | |
24 | +#if (DRV_OSNUM == 0x0001) | |
25 | + | |
26 | +#include <windows.h> | |
27 | +#include <setjmp.h> | |
28 | + | |
29 | +#define TIMER_ID 1 | |
30 | +#define TIMER_INTERVAL 10 | |
31 | + | |
32 | +struct BLD_WORK { | |
33 | + HINSTANCE hi; | |
34 | + HWND hw; | |
35 | + BITMAPINFO bmi; | |
36 | + int tmcount1, tmcount2, flags, smp; /* bit0: 終了 */ | |
37 | + HANDLE mtx; | |
38 | + char *winClosed; | |
39 | +}; | |
40 | + | |
41 | +struct BLD_WORK bld_work; | |
42 | + | |
43 | +struct BL_WIN { | |
44 | + int xsiz, ysiz, *buf; | |
45 | +}; | |
46 | + | |
47 | +struct BL_WORK { | |
48 | + struct BL_WIN win; | |
49 | + jmp_buf jb; | |
50 | + int csiz_x, csiz_y, cx, cy, col0, col1, tabsiz, slctwin; | |
51 | + int tmcount, tmcount0, mod, rand_seed; | |
52 | + int *cbuf; | |
53 | + unsigned char *ftyp; | |
54 | + unsigned char **fptn; | |
55 | + int *ccol, *cbak; | |
56 | + int *kbuf, kbuf_rp, kbuf_wp, kbuf_c; | |
57 | +}; | |
58 | + | |
59 | +struct BL_WORK bl_work; | |
60 | + | |
61 | +#define BL_SIZ_KBUF 8192 | |
62 | + | |
63 | +#define BL_WAITKEYF 0x00000001 | |
64 | +#define BL_WAITKEYNF 0x00000002 | |
65 | +#define BL_WAITKEY 0x00000003 | |
66 | +#define BL_GETKEY 0x00000004 | |
67 | +#define BL_CLEARREP 0x00000008 | |
68 | +#define BL_DELFFF 0x00000010 | |
69 | + | |
70 | +#define BL_KEYMODE 0x00000000 // 作りかけ, make/remake/breakが見えるかどうか | |
71 | + | |
72 | +#define w bl_work | |
73 | +#define dw bld_work | |
74 | + | |
75 | +void bld_openWin(int x, int y, char *winClosed); | |
76 | +void bld_flshWin(int sx, int sy, int x0, int y0); | |
77 | +LRESULT CALLBACK WndProc(HWND hw, unsigned int msg, WPARAM wp, LPARAM lp); | |
78 | +void bl_cls(); | |
79 | +int bl_iCol(int i); | |
80 | +void bl_readyWin(int n); | |
81 | + | |
82 | +static HANDLE threadhandle; | |
83 | + | |
84 | +int main(int argc, const UCHAR **argv) | |
85 | +{ | |
86 | + return OsecpuMain(argc, argv); | |
87 | +} | |
88 | + | |
89 | +void *mallocRWE(int bytes) | |
90 | +{ | |
91 | + void *p = malloc(bytes); | |
92 | + DWORD dmy; | |
93 | + VirtualProtect(p, bytes, PAGE_EXECUTE_READWRITE, &dmy); | |
94 | + return p; | |
95 | +} | |
96 | + | |
97 | +static int winthread(void *dmy) | |
98 | +{ | |
99 | + WNDCLASSEX wc; | |
100 | + RECT r; | |
101 | + unsigned char *p, *p0, *p00; | |
102 | + int i, x, y; | |
103 | + MSG msg; | |
104 | + | |
105 | + x = dw.bmi.bmiHeader.biWidth; | |
106 | + y = - dw.bmi.bmiHeader.biHeight; | |
107 | + | |
108 | + wc.cbSize = sizeof (WNDCLASSEX); | |
109 | + wc.style = CS_HREDRAW | CS_VREDRAW; | |
110 | + wc.lpfnWndProc = WndProc; | |
111 | + wc.cbClsExtra = 0; | |
112 | + wc.cbWndExtra = 0; | |
113 | + wc.hInstance = dw.hi; | |
114 | + wc.hIcon = (HICON) LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), | |
115 | + IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); | |
116 | + wc.hIconSm = wc.hIcon; | |
117 | + wc.hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), | |
118 | + IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); | |
119 | + wc.hbrBackground = (HBRUSH) COLOR_APPWORKSPACE; | |
120 | + wc.lpszMenuName = NULL; | |
121 | + wc.lpszClassName = "WinClass"; | |
122 | + if (RegisterClassEx(&wc) == 0) | |
123 | + return 1; | |
124 | + r.left = 0; | |
125 | + r.top = 0; | |
126 | + r.right = x; | |
127 | + r.bottom = y; | |
128 | + AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, FALSE); | |
129 | + x = r.right - r.left; | |
130 | + y = r.bottom - r.top; | |
131 | + | |
132 | +#if 0 | |
133 | + static unsigned char t[32]; | |
134 | + p00 = p0 = p = GetCommandLineA(); | |
135 | + if (*p == 0x22) { | |
136 | + p00 = p0 = ++p; | |
137 | + while (*p != '\0' && *p != 0x22) { | |
138 | + if (*p == '\\') | |
139 | + p0 = p + 1; | |
140 | + p++; | |
141 | + } | |
142 | + } else { | |
143 | + while (*p > ' ') { | |
144 | + if (*p == '\\') | |
145 | + p0 = p + 1; | |
146 | + p++; | |
147 | + } | |
148 | + } | |
149 | + if (p - p0 > 4 && p[-4] == '.' && p[-3] == 'e' && p[-2] == 'x' && p[-1] == 'e') | |
150 | + p -= 4; | |
151 | + for (i = 0; i < 32 - 1; i++) { | |
152 | + if (p <= &p0[i]) | |
153 | + break; | |
154 | + t[i] = p0[i]; | |
155 | + } | |
156 | + t[i] = '\0'; | |
157 | +#endif | |
158 | + char *t = "osecpu"; | |
159 | + | |
160 | + dw.hw = CreateWindowA(wc.lpszClassName, t, WS_OVERLAPPEDWINDOW, | |
161 | + CW_USEDEFAULT, CW_USEDEFAULT, x, y, NULL, NULL, dw.hi, NULL); | |
162 | + if (dw.hw == NULL) | |
163 | + return 1; | |
164 | + ShowWindow(dw.hw, SW_SHOW); | |
165 | + UpdateWindow(dw.hw); | |
166 | + SetTimer(dw.hw, TIMER_ID, TIMER_INTERVAL, NULL); | |
167 | + SetTimer(dw.hw, TIMER_ID + 1, TIMER_INTERVAL * 10, NULL); | |
168 | + SetTimer(dw.hw, TIMER_ID + 2, TIMER_INTERVAL * 100, NULL); | |
169 | + dw.flags |= 2 | 4; | |
170 | + | |
171 | + for (;;) { | |
172 | + i = GetMessage(&msg, NULL, 0, 0); | |
173 | + if (i == 0 || i == -1) /* エラーもしくは終了メッセージ */ | |
174 | + break; | |
175 | + /* そのほかはとりあえずデフォルト処理で */ | |
176 | + TranslateMessage(&msg); | |
177 | + DispatchMessage(&msg); | |
178 | + } | |
179 | +// PostQuitMessage(0); | |
180 | + dw.flags |= 1; /* 終了, bld_waitNF()が見つける */ | |
181 | + if (dw.winClosed != NULL) | |
182 | + *dw.winClosed = 1; | |
183 | + return 0; | |
184 | +} | |
185 | + | |
186 | +void bld_openWin(int sx, int sy, char *winClosed) | |
187 | +{ | |
188 | + static int i; | |
189 | + | |
190 | + dw.bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER); | |
191 | + dw.bmi.bmiHeader.biWidth = sx; | |
192 | + dw.bmi.bmiHeader.biHeight = - sy; | |
193 | + dw.bmi.bmiHeader.biPlanes = 1; | |
194 | + dw.bmi.bmiHeader.biBitCount = 32; | |
195 | + dw.bmi.bmiHeader.biCompression = BI_RGB; | |
196 | + dw.winClosed = winClosed; | |
197 | + | |
198 | + threadhandle = CreateThread(NULL, 0, (void *) &winthread, NULL, 0, (void *) &i); | |
199 | + | |
200 | + return; | |
201 | +} | |
202 | + | |
203 | +void drv_flshWin(int sx, int sy, int x0, int y0) | |
204 | +{ | |
205 | + InvalidateRect(dw.hw, NULL, FALSE); | |
206 | + UpdateWindow(dw.hw); | |
207 | + return; | |
208 | +} | |
209 | + | |
210 | +LRESULT CALLBACK WndProc(HWND hw, unsigned int msg, WPARAM wp, LPARAM lp) | |
211 | +{ | |
212 | + int i, j; | |
213 | + if (msg == WM_PAINT) { | |
214 | + PAINTSTRUCT ps; | |
215 | + HDC hdc = BeginPaint(dw.hw, &ps); | |
216 | + SetDIBitsToDevice(hdc, 0, 0, w.win.xsiz, w.win.ysiz, | |
217 | + 0, 0, 0, w.win.ysiz, w.win.buf, &dw.bmi, DIB_RGB_COLORS); | |
218 | + EndPaint(dw.hw, &ps); | |
219 | + } | |
220 | + if (msg == WM_DESTROY) { | |
221 | + PostQuitMessage(0); | |
222 | + return 0; | |
223 | + } | |
224 | + if (msg == WM_TIMER && wp == TIMER_ID) { | |
225 | + w.tmcount += TIMER_INTERVAL; | |
226 | + return 0; | |
227 | + } | |
228 | + if (msg == WM_TIMER && wp == TIMER_ID + 1) { | |
229 | + dw.tmcount1 += TIMER_INTERVAL * 10; | |
230 | + w.tmcount = dw.tmcount1; | |
231 | + return 0; | |
232 | + } | |
233 | + if (msg == WM_TIMER && wp == TIMER_ID + 2) { | |
234 | + dw.tmcount2 += TIMER_INTERVAL * 100; | |
235 | + w.tmcount = dw.tmcount1 = dw.tmcount2; | |
236 | + return 0; | |
237 | + } | |
238 | + if (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) { | |
239 | + i = -1; | |
240 | +#if 0 | |
241 | + int s_sht = GetKeyState(VK_SHIFT); | |
242 | + int s_ctl = GetKeyState(VK_CONTROL); | |
243 | + int s_cap = GetKeyState(VK_CAPITAL); | |
244 | + int s_num = GetKeyState(VK_NUMLOCK); | |
245 | + if ('A' <= wp && wp <= 'Z') { | |
246 | + i = wp; | |
247 | + if (((s_sht < 0) ^ (s_cap & 1)) == 0) | |
248 | + i += 'a' - 'A'; | |
249 | + } | |
250 | + if (wp == VK_SPACE) i = ' '; | |
251 | +#endif | |
252 | + if (wp == VK_RETURN) i = KEY_ENTER; | |
253 | + if (wp == VK_ESCAPE) i = KEY_ESC; | |
254 | + if (wp == VK_BACK) i = KEY_BACKSPACE; | |
255 | + if (wp == VK_TAB) i = KEY_TAB; | |
256 | + if (wp == VK_PRIOR) i = KEY_PAGEUP; | |
257 | + if (wp == VK_NEXT) i = KEY_PAGEDWN; | |
258 | + if (wp == VK_END) i = KEY_END; | |
259 | + if (wp == VK_HOME) i = KEY_HOME; | |
260 | + if (wp == VK_LEFT) i = KEY_LEFT; | |
261 | + if (wp == VK_RIGHT) i = KEY_RIGHT; | |
262 | + if (wp == VK_UP) i = KEY_UP; | |
263 | + if (wp == VK_DOWN) i = KEY_DOWN; | |
264 | + if (wp == VK_INSERT) i = KEY_INS; | |
265 | + if (wp == VK_DELETE) i = KEY_DEL; | |
266 | + j &= 0; | |
267 | + if ((GetKeyState(VK_LCONTROL) & (1 << 15)) != 0) j |= 1 << 17; | |
268 | + if ((GetKeyState(VK_LMENU) & (1 << 15)) != 0) j |= 1 << 18; | |
269 | + if ((GetKeyState(VK_RCONTROL) & (1 << 15)) != 0) j |= 1 << 25; | |
270 | + if ((GetKeyState(VK_RMENU) & (1 << 15)) != 0) j |= 1 << 26; | |
271 | + if ((GetKeyState(VK_RSHIFT) & (1 << 15)) != 0) i |= 1 << 24; | |
272 | + if ((GetKeyState(VK_LSHIFT) & (1 << 15)) != 0) i |= 1 << 16; | |
273 | + if ((GetKeyState(VK_NUMLOCK) & (1 << 0)) != 0) i |= 1 << 22; | |
274 | + if ((GetKeyState(VK_CAPITAL) & (1 << 0)) != 0) i |= 1 << 23; | |
275 | + if (j != 0) { | |
276 | + if ('A' <= wp && wp <= 'Z') i = wp; | |
277 | + } | |
278 | + if (i != -1) { | |
279 | + putKeybuf(i | j); | |
280 | +// bl_putKeyB(1, &i); | |
281 | + return 0; | |
282 | + } | |
283 | + } | |
284 | + if (msg == WM_KEYUP) { | |
285 | + i = 0xfff; | |
286 | +// bl_putKeyB(1, &i); | |
287 | + } | |
288 | + if (msg == WM_CHAR) { | |
289 | + i = 0; | |
290 | + if (' ' <= wp && wp <= 0x7e) { | |
291 | + i = wp; | |
292 | + j &= 0; | |
293 | + if ((GetKeyState(VK_LCONTROL) & (1 << 15)) != 0) j |= 1 << 17; | |
294 | + if ((GetKeyState(VK_LMENU) & (1 << 15)) != 0) j |= 1 << 18; | |
295 | + if ((GetKeyState(VK_RCONTROL) & (1 << 15)) != 0) j |= 1 << 25; | |
296 | + if ((GetKeyState(VK_RMENU) & (1 << 15)) != 0) j |= 1 << 26; | |
297 | + if ((GetKeyState(VK_RSHIFT) & (1 << 15)) != 0) i |= 1 << 24; | |
298 | + if ((GetKeyState(VK_LSHIFT) & (1 << 15)) != 0) i |= 1 << 16; | |
299 | + if ((GetKeyState(VK_NUMLOCK) & (1 << 0)) != 0) i |= 1 << 22; | |
300 | + if ((GetKeyState(VK_CAPITAL) & (1 << 0)) != 0) i |= 1 << 23; | |
301 | + if (('A' <= wp && wp <= 'Z') || ('a' <= wp && wp <= 'z')) { | |
302 | + if (j != 0) { | |
303 | + i |= j; | |
304 | + i &= ~0x20; | |
305 | + } | |
306 | + } | |
307 | + putKeybuf(i); | |
308 | +// bl_putKeyB(1, &i); | |
309 | + return 0; | |
310 | + } | |
311 | + } | |
312 | + return DefWindowProc(hw, msg, wp, lp); | |
313 | +} | |
314 | + | |
315 | +void drv_openWin(int sx, int sy, UCHAR *buf, char *winClosed) | |
316 | +{ | |
317 | + int i, x, y; | |
318 | +// if (sx <= 0 || sy <= 0) return; | |
319 | +// if (sx < 160) return; | |
320 | + w.win.buf = (int *) buf; | |
321 | + w.win.xsiz = sx; | |
322 | + w.win.ysiz = sy; | |
323 | + bld_openWin(sx, sy, winClosed); | |
324 | + return; | |
325 | +} | |
326 | + | |
327 | +void drv_sleep(int msec) | |
328 | +{ | |
329 | + Sleep(msec); | |
330 | +// MsgWaitForMultipleObjects(1, &threadhandle, FALSE, msec, QS_ALLINPUT); | |
331 | + /* 勉強不足でまだ書き方が分かりません! */ | |
332 | + return; | |
333 | +} | |
334 | + | |
335 | +#endif | |
336 | + | |
337 | +#if (DRV_OSNUM == 0x0002) | |
338 | + | |
339 | +// by Liva, 2013.05.29- | |
340 | + | |
341 | +#include <mach/mach.h> | |
342 | +#include <Cocoa/Cocoa.h> | |
343 | + | |
344 | +void *mallocRWE(int bytes) | |
345 | +{ | |
346 | + void *p = malloc(bytes); | |
347 | + vm_protect(mach_task_self(), (vm_address_t) p, bytes, FALSE, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE); | |
348 | + return p; | |
349 | +} | |
350 | + | |
351 | +NSApplication* app; | |
352 | + | |
353 | +@interface OSECPUView : NSView { | |
354 | + UCHAR *_buf; | |
355 | + int _sx; | |
356 | + int _sy; | |
357 | + CGContextRef _context; | |
358 | +} | |
359 | + | |
360 | +- (id)initWithFrame:(NSRect)frameRect | |
361 | + buf : (UCHAR *) buf | |
362 | + sx : (int) sx | |
363 | + sy : (int) sy; | |
364 | + | |
365 | +- (void)drawRect:(NSRect)rect; | |
366 | +@end | |
367 | + | |
368 | +@implementation OSECPUView | |
369 | +- (id)initWithFrame:(NSRect)frameRect | |
370 | + buf : (UCHAR *) buf | |
371 | + sx : (int) sx | |
372 | + sy : (int) sy | |
373 | +{ | |
374 | + self = [super initWithFrame:frameRect]; | |
375 | + if (self) { | |
376 | + _buf = buf; | |
377 | + _sx = sx; | |
378 | + _sy = sy; | |
379 | + } | |
380 | + return self; | |
381 | +} | |
382 | + | |
383 | +- (void)drawRect:(NSRect)rect { | |
384 | + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); | |
385 | + _context = CGBitmapContextCreate (_buf, _sx, _sy, 8, 4 * _sx, colorSpace, (kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst)); | |
386 | + CGImageRef image = CGBitmapContextCreateImage(_context); | |
387 | + CGContextRef currentContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; | |
388 | + CGContextDrawImage(currentContext, NSRectToCGRect(rect), image); | |
389 | +} | |
390 | + | |
391 | +@end | |
392 | + | |
393 | +@interface Main : NSObject<NSWindowDelegate> { | |
394 | + int argc; | |
395 | + const UCHAR **argv; | |
396 | + char *winClosed; | |
397 | + OSECPUView *_view; | |
398 | +} | |
399 | + | |
400 | +- (void)runApp; | |
401 | +- (void)createThread : (int)_argc | |
402 | +args : (const UCHAR **)_argv; | |
403 | +- (BOOL)windowShouldClose:(id)sender; | |
404 | +- (void)openWin : (UCHAR *)buf | |
405 | +sx : (int) sx | |
406 | +sy : (int) sy | |
407 | +winClosed : (char *)_winClosed; | |
408 | +- (void)flushWin : (NSRect) rect; | |
409 | +@end | |
410 | + | |
411 | +@implementation Main | |
412 | +- (void)runApp | |
413 | +{ | |
414 | + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; | |
415 | + OsecpuMain(argc,argv); | |
416 | + [NSApp terminate:self]; | |
417 | + [pool release]; | |
418 | +} | |
419 | + | |
420 | +- (void)createThread : (int)_argc | |
421 | + args : (const UCHAR **)_argv | |
422 | +{ | |
423 | + argc = _argc; | |
424 | + argv = _argv; | |
425 | + NSThread *thread = [[[NSThread alloc] initWithTarget:self selector:@selector(runApp) object:nil] autorelease]; | |
426 | + [thread start]; | |
427 | +} | |
428 | + | |
429 | +- (BOOL)windowShouldClose:(id)sender | |
430 | +{ | |
431 | + *winClosed = 1; | |
432 | + return YES; | |
433 | +} | |
434 | + | |
435 | +- (void)openWin : (UCHAR *)buf | |
436 | + sx : (int) sx | |
437 | + sy : (int) sy | |
438 | + winClosed : (char *)_winClosed | |
439 | +{ | |
440 | + | |
441 | + NSWindow* window = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, sx, sy) styleMask: NSTitledWindowMask | NSMiniaturizableWindowMask | NSClosableWindowMask backing: NSBackingStoreBuffered defer: NO]; | |
442 | + [window setTitle: @"osecpu"]; | |
443 | + [window center]; | |
444 | + [window makeKeyAndOrderFront:nil]; | |
445 | + [window setReleasedWhenClosed:YES]; | |
446 | + window.delegate = self; | |
447 | + winClosed = _winClosed; | |
448 | + | |
449 | + _view = [[OSECPUView alloc] initWithFrame:NSMakeRect(0,0,sx,sy) buf:buf sx:sx sy:sy]; | |
450 | + [window.contentView addSubview:_view]; | |
451 | +} | |
452 | + | |
453 | +- (void)flushWin : (NSRect) rect | |
454 | + { | |
455 | + [_view drawRect:rect]; | |
456 | + } | |
457 | + | |
458 | +@end | |
459 | + | |
460 | +id objc_main; | |
461 | + | |
462 | +int main(int argc, const UCHAR **argv) | |
463 | +{ | |
464 | + objc_main = [[Main alloc] init]; | |
465 | + | |
466 | + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; | |
467 | + app = [[NSApplication alloc] init]; | |
468 | + [objc_main createThread:argc args:argv]; | |
469 | + [app run]; | |
470 | + [pool release]; | |
471 | + return 0; | |
472 | +} | |
473 | + | |
474 | +void drv_openWin(int sx, int sy, UCHAR *buf, char *winClosed) | |
475 | +{ | |
476 | + [objc_main openWin:buf sx:sx sy:sy winClosed:winClosed]; | |
477 | +} | |
478 | + | |
479 | +void drv_flshWin(int sx, int sy, int x0, int y0) | |
480 | +{ | |
481 | + [objc_main flushWin:NSMakeRect(x0,y0,sx,sy)]; | |
482 | +} | |
483 | + | |
484 | +void drv_sleep(int msec) | |
485 | +{ | |
486 | + [NSThread sleepForTimeInterval:0.001*msec]; | |
487 | + return; | |
488 | +} | |
489 | + | |
490 | +#endif | |
491 | + | |
492 | +#if (DRV_OSNUM == 0x0003) | |
493 | + | |
494 | +// by takeutch-kemeco, 2013.07.25- | |
495 | + | |
496 | +// gcc -D__linux__ osecpu.c `pkg-config blike --cflags --libs` -o osecpu | |
497 | + | |
498 | + | |
499 | +void __bl_openWin_attach_vram(int, int, int*); | |
500 | +void *__bld_mallocRWE(unsigned int); | |
501 | +void bld_flshWin(int, int, int, int); | |
502 | +void bl_wait(int); | |
503 | +void __bld_set_callback_key_press(void (*f)(void*, const int)); | |
504 | +void __bld_set_callback_key_release(void (*f)(void*, const int)); | |
505 | + | |
506 | +extern int bl_argc; | |
507 | +extern const UCHAR** bl_argv; | |
508 | + | |
509 | +static void __drv_bld_callback_key_press(void* a, const int keyval) { if (keyval != -1) putKeybuf(keyval); } | |
510 | +static void __drv_bld_callback_key_release(void* a, const int keyval) { /* putKeybuf(0x0fff); */ } | |
511 | + | |
512 | +void *mallocRWE(int bytes) { return __bld_mallocRWE(bytes); } | |
513 | +void drv_openWin(int sx, int sy, UCHAR *buf, char *winClosed) { __bl_openWin_attach_vram(sx, sy, (int*) buf); } | |
514 | +void drv_flshWin(int sx, int sy, int x0, int y0) { bld_flshWin(sx, sy, x0, y0); } | |
515 | +void drv_sleep(int msec) { bl_wait(msec); } | |
516 | + | |
517 | +blMain() | |
518 | +{ | |
519 | + __bld_set_callback_key_press(__drv_bld_callback_key_press); | |
520 | + __bld_set_callback_key_release(__drv_bld_callback_key_release); | |
521 | + OsecpuMain(bl_argc, bl_argv); | |
522 | +} | |
523 | + | |
524 | +#endif /* (DRV_OSNUM == 0x0003) */ | |
525 | + | |
526 | + |
@@ -12,9 +12,9 @@ int jitcStepExtend(OsecpuJitc *jitc) | ||
12 | 12 | return -1; |
13 | 13 | } |
14 | 14 | |
15 | -void jitcAfterStepExtend(OsecpuJitc *jitc) | |
15 | +int jitcAfterStepExtend(OsecpuJitc *jitc) | |
16 | 16 | { |
17 | - return; | |
17 | + return 0; | |
18 | 18 | } |
19 | 19 | |
20 | 20 | void execStepExtend(OsecpuVm *vm) |
@@ -95,6 +95,7 @@ int jitcStepFloat(OsecpuJitc *jitc) | ||
95 | 95 | jitcStep_checkFxx(pRC, f); |
96 | 96 | jitcStep_checkBits32(pRC, bit0); |
97 | 97 | jitcStep_checkRxxNotR3F(pRC, r); |
98 | + jitc->prefix2f[0] = 0; // 2F-0. | |
98 | 99 | goto fin; |
99 | 100 | } |
100 | 101 | if (0x48 <= opecode && opecode <= 0x4d) { |
@@ -125,9 +126,9 @@ fin1: | ||
125 | 126 | return retcode; |
126 | 127 | } |
127 | 128 | |
128 | -void jitcAfterStepFloat(OsecpuJitc *jitc) | |
129 | +int jitcAfterStepFloat(OsecpuJitc *jitc) | |
129 | 130 | { |
130 | - return; | |
131 | + return 0; | |
131 | 132 | } |
132 | 133 | |
133 | 134 | void execStepFloat(OsecpuVm *vm) |
@@ -200,7 +201,7 @@ void execStepFloat(OsecpuVm *vm) | ||
200 | 201 | } |
201 | 202 | vm->r[r] = (Int32) vm->f[f]; |
202 | 203 | vm->bit[r] = bit0; |
203 | - execStep_checkBitsRange(vm->r[r], bit0, vm); | |
204 | + vm->r[r] = execStep_checkBitsRange(vm->r[r], bit0, vm, 0, 0); | |
204 | 205 | ip += 5; |
205 | 206 | goto fin; |
206 | 207 | } |
@@ -1,6 +1,37 @@ | ||
1 | 1 | #include "osecpu-vm.h" |
2 | 2 | |
3 | -// 整数命令: 02, 10-16, 18-1B, 20-27, FD | |
3 | +// 整数命令: 02, 08-09, 10-16, 18-1B, 20-27, 2F, FD | |
4 | + | |
5 | +int getTypBitInteger(int typ) | |
6 | +{ | |
7 | + int retcode = 0; | |
8 | + if (2 <= typ && typ <= 21) { | |
9 | + static unsigned char table[10] = { 8, 16, 32, 4, 2, 1, 12, 20, 24, 28 }; | |
10 | + retcode = table[(typ - 2) / 2]; | |
11 | + } | |
12 | + return retcode; | |
13 | +} | |
14 | + | |
15 | +void getTypInfoInteger(int typ, int *typSize0, int *typSize1, int *typSign) | |
16 | +// typSize0: 公式サイズ(ビット単位). | |
17 | +// typSize1: 内部サイズ(バイト単位). | |
18 | +// typSign: 符号の有無(0は符号なし). | |
19 | +{ | |
20 | + *typSize0 = *typSize1 = -1; | |
21 | + if (2 <= typ && typ <= 21) { | |
22 | + int bytes; | |
23 | + if ((typ & 1) == 0) | |
24 | + *typSign = -1; // typが偶数なら符号あり. | |
25 | + else | |
26 | + *typSign = 0; // typが奇数なら符号なし. | |
27 | + *typSize0 = getTypBitInteger(typ); | |
28 | + bytes = (*typSize0 + 7) / 8; | |
29 | + if (bytes == 3) bytes = 4; | |
30 | + *typSize1 = bytes; | |
31 | + } | |
32 | + return; | |
33 | +} | |
34 | + | |
4 | 35 | |
5 | 36 | void jitcInitInteger(OsecpuJitc *jitc) |
6 | 37 | { |
@@ -12,13 +43,9 @@ int jitcStepInteger(OsecpuJitc *jitc) | ||
12 | 43 | { |
13 | 44 | Int32 *ip = jitc->hh4Buffer; |
14 | 45 | Int32 opecode = ip[0], imm; |
15 | - int bit, bit0, bit1, r, r0, r1, r2; | |
46 | + int bit, bit0, bit1, r, r0, r1, r2, p, typ; | |
16 | 47 | int retcode = -1, *pRC = &retcode; |
17 | - int i; | |
18 | - if (opecode == 0x00) { /* NOP */ | |
19 | - jitcSetHh4BufferSimple(jitc, 1); | |
20 | - goto fin; | |
21 | - } | |
48 | + int i, j; | |
22 | 49 | if (opecode == 0x02) { /* LIMM(imm, Rxx, bits); */ |
23 | 50 | ip[1] = hh4ReaderGetSigned(&jitc->hh4r); |
24 | 51 | ip[2] = hh4ReaderGetUnsigned(&jitc->hh4r); |
@@ -42,6 +69,43 @@ int jitcStepInteger(OsecpuJitc *jitc) | ||
42 | 69 | jitc->ope04 = jitc->dst; |
43 | 70 | goto fin; |
44 | 71 | } |
72 | + if (opecode == 0x08) { /* LMEM(p, typ, 0, r, bit); */ | |
73 | + jitcSetHh4BufferSimple(jitc, 6); | |
74 | + p = ip[1]; typ = ip[2]; i = ip[3]; r = ip[4]; bit = ip[5]; | |
75 | + if (i != 0) { | |
76 | + jitcSetRetCode(pRC, JITC_UNSUPPORTED); | |
77 | + goto fin; | |
78 | + } | |
79 | + jitcStep_checkPxx(pRC, p); | |
80 | + jitcStep_checkRxxNotR3F(pRC, r); | |
81 | + jitcStep_checkBits32(pRC, bit); | |
82 | + if (jitc->prefix2f[0] != 0 && jitc->prefix2f[1] != 0) | |
83 | + jitcSetRetCode(pRC, JITC_BAD_PREFIX); // 2F-n系プリフィクスは1個まで. | |
84 | + jitc->prefix2f[0] = 0; // 2F-0. | |
85 | + jitc->prefix2f[1] = 0; // 2F-1. | |
86 | + goto fin; | |
87 | + } | |
88 | + if (opecode == 0x09) { /* SMEM(r, bit, p, typ, 0); */ | |
89 | + jitcSetHh4BufferSimple(jitc, 6); | |
90 | + r = ip[1]; bit = ip[2]; p = ip[3]; typ = ip[4]; i = ip[5]; | |
91 | + if (i != 0) { | |
92 | + jitcSetRetCode(pRC, JITC_UNSUPPORTED); | |
93 | + goto fin; | |
94 | + } | |
95 | + jitcStep_checkPxx(pRC, p); | |
96 | + jitcStep_checkRxxNotR3F(pRC, r); | |
97 | + j = 0; | |
98 | + for (i = 0; i < 3; i++) { | |
99 | + if (jitc->prefix2f[i] != 0) | |
100 | + j++; | |
101 | + } | |
102 | + if (j > 1) | |
103 | + jitcSetRetCode(pRC, JITC_BAD_PREFIX); // 2F-n系プリフィクスは1個まで. | |
104 | + jitc->prefix2f[0] = 0; // 2F-0. | |
105 | + jitc->prefix2f[1] = 0; // 2F-1. | |
106 | + jitc->prefix2f[2] = 0; // 2F-2. | |
107 | + goto fin; | |
108 | + } | |
45 | 109 | if (0x10 <= opecode && opecode <= 0x1b && opecode != 0x13 && opecode != 0x17) { |
46 | 110 | jitcSetHh4BufferSimple(jitc, 5); |
47 | 111 | r1 = ip[1]; r2 = ip[2]; r0 = ip[3]; bit = ip[4]; |
@@ -49,6 +113,7 @@ int jitcStepInteger(OsecpuJitc *jitc) | ||
49 | 113 | jitcStep_checkRxx(pRC, r2); |
50 | 114 | jitcStep_checkRxxNotR3F(pRC, r0); |
51 | 115 | jitcStep_checkBits32(pRC, bit); |
116 | + jitc->prefix2f[0] = 0; // 2F-0. | |
52 | 117 | goto fin; |
53 | 118 | } |
54 | 119 | if (opecode == 0x13) { // SBX. |
@@ -59,6 +124,7 @@ int jitcStepInteger(OsecpuJitc *jitc) | ||
59 | 124 | if (r2 != 0x3f) |
60 | 125 | jitcSetRetCode(pRC, JITC_BAD_RXX); |
61 | 126 | jitcStep_checkBits32(pRC, bit); |
127 | + jitc->prefix2f[0] = 0; // 2F-0. | |
62 | 128 | goto fin; |
63 | 129 | } |
64 | 130 | if (0x20 <= opecode && opecode <= 0x27) { |
@@ -71,13 +137,6 @@ int jitcStepInteger(OsecpuJitc *jitc) | ||
71 | 137 | jitcStep_checkBits32(pRC, bit1); |
72 | 138 | goto fin; |
73 | 139 | } |
74 | - if (opecode == 0xfd) { | |
75 | - jitcSetHh4BufferSimple(jitc, 3); | |
76 | - imm = ip[1]; r = ip[2]; | |
77 | - if (0 <= r && r <= 3) | |
78 | - jitc->dr[r] = imm; | |
79 | - goto fin; | |
80 | - } | |
81 | 140 | goto fin1; |
82 | 141 | fin: |
83 | 142 | if (retcode == -1) |
@@ -86,46 +145,120 @@ fin1: | ||
86 | 145 | return retcode; |
87 | 146 | } |
88 | 147 | |
89 | -void jitcAfterStepInteger(OsecpuJitc *jitc) | |
148 | +int jitcAfterStepInteger(OsecpuJitc *jitc) | |
90 | 149 | { |
150 | + int i, retcode = 0; | |
91 | 151 | if (jitc->ope04 != NULL && jitc->dst != jitc->ope04) { |
92 | 152 | // CND命令の直後の命令を検出. |
93 | 153 | Int32 *dst04 = jitc->ope04; |
94 | 154 | dst04[2] = jitc->instrLength; // 直後の命令の命令長. |
95 | 155 | jitc->ope04 = NULL; |
96 | 156 | } |
97 | - return; | |
157 | + return 0; | |
158 | +} | |
159 | + | |
160 | +Int32 execStep_checkBitsRange(Int32 value, int bit, OsecpuVm *vm, int bit1, int bit2) | |
161 | +{ | |
162 | + int max, min, i; | |
163 | + if (bit1 != BIT_DISABLE_REG && bit2 != BIT_DISABLE_REG && vm->prefix2f[0] == 0) { | |
164 | + max = 1 << (bit - 1); // 例: bits=8だとmax=128になる. | |
165 | + max--; // 例: bits=8だとmax=127になる. | |
166 | + min = - max - 1; // 例: bits=8だとmin=-128になる。 | |
167 | + if (!(min <= value && value <= max)) | |
168 | + jitcSetRetCode(&vm->errorCode, EXEC_BITS_RANGE_OVER); | |
169 | + } else { | |
170 | + vm->prefix2f[0] = 0; | |
171 | + if (bit > 0) { | |
172 | + i = (-1) << bit; | |
173 | + if ((value & (1 << (bit - 1))) == 0) { | |
174 | + // 符号ビットが0だった. | |
175 | + value &= ~i; | |
176 | + } else { | |
177 | + // 符号ビットが1だった. | |
178 | + value |= i; | |
179 | + } | |
180 | + } else | |
181 | + value = 0; | |
182 | + } | |
183 | + return value; | |
98 | 184 | } |
99 | 185 | |
100 | 186 | void execStepInteger(OsecpuVm *vm) |
101 | 187 | { |
102 | 188 | const Int32 *ip = vm->ip; |
103 | 189 | Int32 opecode = ip[0], imm; |
104 | - int bit, bit0, bit1, r, r0, r1, r2; | |
105 | - int i; | |
106 | - if (opecode == 0x00) { // NOP(); | |
107 | - ip++; | |
108 | - goto fin; | |
109 | - } | |
190 | + int bit, bit0, bit1, r, r0, r1, r2, p, typ, typSign, typSize0, typSize1; | |
191 | + int i, mbit, tbit; | |
110 | 192 | if (opecode == 0x02) { // LIMM(imm, Rxx, bits); |
111 | 193 | imm = ip[1]; r = ip[2]; bit = ip[3]; |
112 | 194 | vm->r[r] = imm; |
113 | 195 | vm->bit[r] = bit; |
114 | - execStep_checkBitsRange(vm->r[r], bit, vm); | |
196 | + execStep_checkBitsRange(vm->r[r], bit, vm, 0, 0); | |
115 | 197 | ip += 4; |
116 | 198 | goto fin; |
117 | 199 | } |
118 | 200 | if (opecode == 0x04) { /* CND(Rxx); */ |
119 | - r = ip[1]; | |
120 | - i = ip[2]; | |
201 | + r = ip[1]; i = ip[2]; | |
121 | 202 | ip += 3; |
122 | 203 | if ((vm->r[r] & 1) == 0) |
123 | 204 | ip += i; |
124 | 205 | goto fin; |
125 | 206 | } |
207 | + if (opecode == 0x08) { /* LMEM(p, typ, 0, r, bit); */ | |
208 | + p = ip[1]; typ = ip[2]; r = ip[4]; bit = ip[5]; | |
209 | + execStep_checkMemAccess(vm, p, typ, EXEC_CMA_FLAG_READ); | |
210 | + if (vm->errorCode != 0) goto fin; | |
211 | + mbit = *(vm->p[p].bit); | |
212 | + tbit = getTypBitInteger(typ); | |
213 | + if (mbit == BIT_DISABLE_MEM) | |
214 | + tbit = mbit; | |
215 | + getTypInfoInteger(typ, &typSize0, &typSize1, &typSign); | |
216 | + if (typSize1 == 1 && typSign == 0) { | |
217 | + unsigned char *puc = (unsigned char *) vm->p[p].p; | |
218 | + vm->r[r] = *puc; | |
219 | + } | |
220 | + if (typSize1 == 1 && typSign != 0) { | |
221 | + signed char *psc = (signed char *) vm->p[p].p; | |
222 | + vm->r[r] = *psc; | |
223 | + } | |
224 | + if (typSize1 == 2 && typSign == 0) { | |
225 | + unsigned short *pus = (unsigned short *) vm->p[p].p; | |
226 | + vm->r[r] = *pus; | |
227 | + } | |
228 | + if (typSize1 == 2 && typSign != 0) { | |
229 | + signed short *pss = (signed short *) vm->p[p].p; | |
230 | + vm->r[r] = *pss; | |
231 | + } | |
232 | + if (typSize1 == 4 && typSign == 0) { | |
233 | + unsigned int *pui = (unsigned int *) vm->p[p].p; | |
234 | + vm->r[r] = *pui; | |
235 | + } | |
236 | + if (typSize1 == 4 && typSign != 0) { | |
237 | + signed int *psi = (signed int *) vm->p[p].p; | |
238 | + vm->r[r] = *psi; | |
239 | + } | |
240 | + if (vm->prefix2f[1] == 0) { | |
241 | + if (mbit < tbit && mbit < bit) | |
242 | + jitcSetRetCode(&vm->errorCode, EXEC_BAD_BITS); // 不確定ビットの参照がある場合. | |
243 | + } else { | |
244 | + if (bit > mbit) | |
245 | + bit = mbit; | |
246 | + vm->prefix2f[1] = 0; | |
247 | + } | |
248 | + vm->bit[r] = bit; | |
249 | + if (tbit > bit) | |
250 | + vm->r[r] = execStep_checkBitsRange(vm->r[r], bit, vm, 0, 0); // 部分リードの場合は、ゴミビットを消す. | |
251 | + ip += 6; | |
252 | + goto fin; | |
253 | + } | |
254 | + | |
126 | 255 | if (0x10 <= opecode && opecode <= 0x16 && opecode != 0x13) { |
127 | 256 | r1 = ip[1]; r2 = ip[2]; r0 = ip[3]; bit = ip[4]; |
128 | - if (bit > vm->bit[r1] || bit > vm->bit[r2]) { | |
257 | + if (vm->bit[r1] != BIT_DISABLE_REG && bit > vm->bit[r1]) { | |
258 | + jitcSetRetCode(&vm->errorCode, EXEC_BAD_BITS); | |
259 | + goto fin; | |
260 | + } | |
261 | + if (vm->bit[r2] != BIT_DISABLE_REG && bit > vm->bit[r2]) { | |
129 | 262 | jitcSetRetCode(&vm->errorCode, EXEC_BAD_BITS); |
130 | 263 | goto fin; |
131 | 264 | } |
@@ -136,13 +269,13 @@ void execStepInteger(OsecpuVm *vm) | ||
136 | 269 | if (opecode == 0x15) vm->r[r0] = vm->r[r1] - vm->r[r2]; // SUB(r0, r1, r2, bits); |
137 | 270 | if (opecode == 0x16) vm->r[r0] = vm->r[r1] * vm->r[r2]; // MUL(r0, r1, r2, bits); |
138 | 271 | vm->bit[r0] = bit; |
139 | - execStep_checkBitsRange(vm->r[r0], bit, vm); | |
272 | + vm->r[r0] = execStep_checkBitsRange(vm->r[r0], bit, vm, vm->bit[r1], vm->bit[r2]); | |
140 | 273 | ip += 5; |
141 | 274 | goto fin; |
142 | 275 | } |
143 | 276 | if (opecode == 0x13) { // SBX. |
144 | 277 | r1 = ip[1]; r0 = ip[3]; bit = ip[4]; |
145 | - if (bit > vm->bit[r1]) { | |
278 | + if (vm->bit[r1] != BIT_DISABLE_REG && bit > vm->bit[r1]) { | |
146 | 279 | jitcSetRetCode(&vm->errorCode, EXEC_BAD_BITS); |
147 | 280 | goto fin; |
148 | 281 | } |
@@ -159,17 +292,17 @@ void execStepInteger(OsecpuVm *vm) | ||
159 | 292 | vm->r[r0] = vm->r[r1] | i; |
160 | 293 | } |
161 | 294 | vm->bit[r0] = bit; |
162 | - execStep_checkBitsRange(vm->r[r0], bit, vm); | |
295 | + vm->r[r0] = execStep_checkBitsRange(vm->r[r0], bit, vm, vm->bit[r1], 0); | |
163 | 296 | ip += 5; |
164 | 297 | goto fin; |
165 | 298 | } |
166 | 299 | if (0x18 <= opecode && opecode <= 0x19) { |
167 | 300 | r1 = ip[1]; r2 = ip[2]; r0 = ip[3]; bit = ip[4]; |
168 | - if (bit > vm->bit[r1]) { | |
301 | + if (vm->bit[r1] != BIT_DISABLE_REG && bit > vm->bit[r1]) { | |
169 | 302 | jitcSetRetCode(&vm->errorCode, EXEC_BAD_BITS); |
170 | 303 | goto fin; |
171 | 304 | } |
172 | - if (bit <= vm->r[r2] || vm->r[r2] < 0) { | |
305 | + if (vm->r[r2] < 0) { | |
173 | 306 | jitcSetRetCode(&vm->errorCode, EXEC_BAD_R2); |
174 | 307 | goto fin; |
175 | 308 | } |
@@ -178,13 +311,17 @@ void execStepInteger(OsecpuVm *vm) | ||
178 | 311 | else |
179 | 312 | vm->r[r0] = vm->r[r1] >> vm->r[r2]; // SAR |
180 | 313 | vm->bit[r0] = bit; |
181 | - execStep_checkBitsRange(vm->r[r0], bit, vm); | |
314 | + vm->r[r0] = execStep_checkBitsRange(vm->r[r0], bit, vm, vm->bit[r1], 0); | |
182 | 315 | ip += 5; |
183 | 316 | goto fin; |
184 | 317 | } |
185 | 318 | if (0x1a <= opecode && opecode <= 0x1b) { |
186 | 319 | r1 = ip[1]; r2 = ip[2]; r0 = ip[3]; bit = ip[4]; |
187 | - if (bit > vm->bit[r1] || bit > vm->bit[r2]) { | |
320 | + if (vm->bit[r1] != BIT_DISABLE_REG && bit > vm->bit[r1]) { | |
321 | + jitcSetRetCode(&vm->errorCode, EXEC_BAD_BITS); | |
322 | + goto fin; | |
323 | + } | |
324 | + if (vm->bit[r2] != BIT_DISABLE_REG && bit > vm->bit[r2]) { | |
188 | 325 | jitcSetRetCode(&vm->errorCode, EXEC_BAD_BITS); |
189 | 326 | goto fin; |
190 | 327 | } |
@@ -197,13 +334,17 @@ void execStepInteger(OsecpuVm *vm) | ||
197 | 334 | else |
198 | 335 | vm->r[r0] = vm->r[r1] % vm->r[r2]; |
199 | 336 | vm->bit[r0] = bit; |
200 | - execStep_checkBitsRange(vm->r[r0], bit, vm); | |
337 | + vm->r[r0] = execStep_checkBitsRange(vm->r[r0], bit, vm, vm->bit[r1], vm->bit[r2]); | |
201 | 338 | ip += 5; |
202 | 339 | goto fin; |
203 | 340 | } |
204 | 341 | if (0x20 <= opecode && opecode <= 0x27) { |
205 | 342 | r1 = ip[1]; r2 = ip[2]; bit1 = ip[3]; r0 = ip[4]; bit0 = ip[5]; |
206 | - if (bit1 > vm->bit[r1] || bit1 > vm->bit[r2]) { | |
343 | + if (vm->bit[r1] != BIT_DISABLE_REG && bit > vm->bit[r1]) { | |
344 | + jitcSetRetCode(&vm->errorCode, EXEC_BAD_BITS); | |
345 | + goto fin; | |
346 | + } | |
347 | + if (vm->bit[r2] != BIT_DISABLE_REG && bit > vm->bit[r2]) { | |
207 | 348 | jitcSetRetCode(&vm->errorCode, EXEC_BAD_BITS); |
208 | 349 | goto fin; |
209 | 350 | } |
@@ -230,8 +371,32 @@ void execStepInteger(OsecpuVm *vm) | ||
230 | 371 | ip += 6; |
231 | 372 | goto fin; |
232 | 373 | } |
374 | + | |
233 | 375 | fin: |
234 | - vm->ip = ip; | |
376 | + if (vm->errorCode <= 0) | |
377 | + vm->ip = ip; | |
378 | + return; | |
379 | +} | |
380 | + | |
381 | +void jitcStep_checkBits32(int *pRC, int bits) | |
382 | +{ | |
383 | + if (!(0 <= bits && bits <= 32)) | |
384 | + jitcSetRetCode(pRC, JITC_BAD_BITS); | |
235 | 385 | return; |
236 | 386 | } |
237 | 387 | |
388 | +void jitcStep_checkRxx(int *pRC, int rxx) | |
389 | +{ | |
390 | + if (!(0x00 <= rxx && rxx <= 0x3f)) | |
391 | + jitcSetRetCode(pRC, JITC_BAD_RXX); | |
392 | + return; | |
393 | +} | |
394 | + | |
395 | +void jitcStep_checkRxxNotR3F(int *pRC, int rxx) | |
396 | +{ | |
397 | + if (!(0x00 <= rxx && rxx <= 0x3e)) | |
398 | + jitcSetRetCode(pRC, JITC_BAD_RXX); | |
399 | + return; | |
400 | +} | |
401 | + | |
402 | + |
@@ -33,3 +33,59 @@ | ||
33 | 33 | data命令でも浮動小数点を使えるようになりたいからそれは後日がんばる。 |
34 | 34 | 次はLMEMだなー。その次がPADD。 |
35 | 35 | |
36 | +2014.05.23金: | |
37 | + プリフィクスについて: | |
38 | + 解釈できるプリフィクスは、認識した後に0クリアすること。そうしなければエラーになる。 | |
39 | + 2Fプリフィクスは、フラグ的な指定なので、命令ごとに意味が異なる。 | |
40 | + LMEMに対する、2F-0プリフィクスについて: | |
41 | + 2F-0プリフィクスがない場合: | |
42 | + (1) mem.bit < typ.bit なら、セキュリティ例外になる。 | |
43 | + mem.bit: メモリのbit[]値 | |
44 | + typ.bit: そのメモリの型での最大のbit値 | |
45 | + reg.bit: LMEM命令内のbit値で、これは命令実行後にRxxのbit[]値になる | |
46 | + 2F-0プリフィクスがある場合: | |
47 | + (1) reg.bit = min(reg.bit, mem.bit) とする。結果が何であろうとセキュリティ例外にはならない。 | |
48 | + この場合、不定値をロードしてもレジスタが不定値なるだけで処理を続行できる。 | |
49 | + しかしこの値を使って演算しようとすると、エラーになる。 | |
50 | + SMEMに対する、2F-0プリフィクスについて: | |
51 | + 2F-0プリフィクスがない場合: | |
52 | + (1) typ.bit > reg.bit なら、セキュリティ例外になる。 | |
53 | + (2) typで指定されている型で表現可能な範囲にregがないのであれば、セキュリティ例外になる。 | |
54 | + (3) mem.bit = typ.bit になる。 | |
55 | + 2F-0プリフィクスがある場合: | |
56 | + (1) typで指定されている型で表現可能な範囲にregがないのであれば、mem.bit = 0 になる。 | |
57 | + (2) そうでなければ mem.bit = reg.bit になる。 | |
58 | + つまり例外を起こさずに何とかする。 | |
59 | + この場合、unsignedな型は指定できない。 | |
60 | + SMEMに対する、2F-1プリフィクスについて: | |
61 | + 2F-1プリフィクスがあると、Rxxフィールドは無視されて、メモリは無条件にbit[]値を0にされる。 | |
62 | + 明示的にメモリを不定値したい場合は、これが望ましい。適当なレジスタに不定値を代入して格納する方法だと | |
63 | + 高速モード時に不要なSMEM命令が残ってしまうかもしれない。 | |
64 | + SMEMに対する、2F-2プリフィクスについて: | |
65 | + 2F-2プリフィクスがある場合: | |
66 | + (1) typ.bit > reg.bit なら、セキュリティ例外になる。 | |
67 | + (2) 実際に書き込まれるのは、typ.bitでマスクされた下位の値のみ。 | |
68 | + (3) mem.bit = typ.bit になる。 | |
69 | + (上記のメモは、もはや古い内容。メモだから残しているだけ。) | |
70 | + data命令がpointer.cの中にあるのはうまくない! | |
71 | + | |
72 | +2014.05.27火: | |
73 | + レンジチェックに関する諸問題: | |
74 | + (1) 高速モードから安全モードへ切り替えることを想定すると、bit[]に「不明」を認めなければいけない。 | |
75 | + しかしそうなると、レンジチェックの手順はかなり複雑になる。 | |
76 | + ソースデータに「不明」がある場合、結果が出た後に結果を正規化する必要がある。 | |
77 | + (2) 安全モードだけでも、C=(A+B)&3;のような計算をするときに、A+Bの結果を2ビットの精度で演算できるべきでは | |
78 | + ないか?・・・となると、A+Bの計算をするときに結果が2ビットで収まらなくても構わないということを認めなければ | |
79 | + いけない。そのために2F-0プリフィクスを付ける。 | |
80 | + (3) まず論点としては、レンジチェックをやめてしまえばいいのではないかということがある。ごみデータが現れることは | |
81 | + 高速モードじゃなくても十分に起こり得ることなのであって、そうなるとそれに気を使うのは面倒なだけではないか? | |
82 | + しかしとりあえず、まだあきらめずにレンジチェックをやる方向で検討する。この(3)は思考過程を記録として残すために | |
83 | + 書いた。 | |
84 | + (4) 2F-0プリフィクスがある場合、レンジチェックはしないで、むしろ結果がそのレンジに収まるように符号拡張をする。 | |
85 | + そうしないと以後のレンジチェックに障るかもしれないので。 | |
86 | + 例外検出に関する諸問題: | |
87 | + 例外を検出した時に、正常系だった最後の値を保持する(おかしくなった原因命令を実行する直前の状態にする)のは | |
88 | + 負担が大きいので、それはやらない。これについては、将来の逆再生機能に期待するべきだ。 | |
89 | + driver.cについて: | |
90 | + 確かMacOS版にバグの修正があった気がするけど、まだそこまで手が回らない。落ち着いたら確認する。 | |
91 | + |
@@ -155,8 +155,11 @@ void jitcInitDstLogSetPhase(OsecpuJitc *jitc, int phase) | ||
155 | 155 | for (i = 0; i < JITC_DSTLOG_SIZE; i++) |
156 | 156 | jitc->dstLog[i] = NULL; |
157 | 157 | jitc->dstLogIndex = 0; |
158 | + for (i = 0; i < PREFIX2F_SIZE; i++) | |
159 | + jitc->prefix2f[i] = 0; | |
158 | 160 | jitc->phase = phase; |
159 | 161 | jitcInitInteger(jitc); |
162 | + jitcInitOther(jitc); | |
160 | 163 | jitcInitPointer(jitc); |
161 | 164 | jitcInitFloat(jitc); |
162 | 165 | jitcInitExtend(jitc); |
@@ -184,6 +187,7 @@ int jitcStep(OsecpuJitc *jitc) | ||
184 | 187 | int retcode = -1, *pRC = &retcode, i; |
185 | 188 | jitc->hh4Buffer[0] = hh4ReaderGetUnsigned(&jitc->hh4r); |
186 | 189 | retcode = jitcStepInteger(jitc); if (retcode >= 0) goto fin; |
190 | + retcode = jitcStepOther(jitc); if (retcode >= 0) goto fin; | |
187 | 191 | retcode = jitcStepPointer(jitc); if (retcode >= 0) goto fin; |
188 | 192 | retcode = jitcStepFloat(jitc); if (retcode >= 0) goto fin; |
189 | 193 | retcode = jitcStepExtend(jitc); if (retcode >= 0) goto fin; |
@@ -197,10 +201,11 @@ fin: | ||
197 | 201 | goto fin1; |
198 | 202 | for (i = 0; i < jitc->instrLength; i++) |
199 | 203 | jitc->dst[i] = jitc->hh4Buffer[i]; |
200 | - jitcAfterStepInteger(jitc); | |
201 | - jitcAfterStepPointer(jitc); | |
202 | - jitcAfterStepFloat(jitc); | |
203 | - jitcAfterStepExtend(jitc); | |
204 | + retcode = jitcAfterStepInteger(jitc); if (retcode > 0) goto fin1; | |
205 | + retcode = jitcAfterStepOther(jitc); if (retcode > 0) goto fin1; | |
206 | + retcode = jitcAfterStepPointer(jitc); if (retcode > 0) goto fin1; | |
207 | + retcode = jitcAfterStepFloat(jitc); if (retcode > 0) goto fin1; | |
208 | + retcode = jitcAfterStepExtend(jitc); if (retcode > 0) goto fin1; | |
204 | 209 | i = jitc->dstLogIndex; |
205 | 210 | jitc->dstLog[i] = jitc->dst; // エラーのなかった命令は記録する. |
206 | 211 | jitc->dstLogIndex = (i + 1) % JITC_DSTLOG_SIZE; |
@@ -236,27 +241,6 @@ fin: | ||
236 | 241 | return jitc->errorCode; |
237 | 242 | } |
238 | 243 | |
239 | -void jitcStep_checkBits32(int *pRC, int bits) | |
240 | -{ | |
241 | - if (!(0 <= bits && bits <= 32)) | |
242 | - jitcSetRetCode(pRC, JITC_BAD_BITS); | |
243 | - return; | |
244 | -} | |
245 | - | |
246 | -void jitcStep_checkRxx(int *pRC, int rxx) | |
247 | -{ | |
248 | - if (!(0x00 <= rxx && rxx <= 0x3f)) | |
249 | - jitcSetRetCode(pRC, JITC_BAD_RXX); | |
250 | - return; | |
251 | -} | |
252 | - | |
253 | -void jitcStep_checkRxxNotR3F(int *pRC, int rxx) | |
254 | -{ | |
255 | - if (!(0x00 <= rxx && rxx <= 0x3e)) | |
256 | - jitcSetRetCode(pRC, JITC_BAD_RXX); | |
257 | - return; | |
258 | -} | |
259 | - | |
260 | 244 | // exec関係. |
261 | 245 | |
262 | 246 | int execStep(OsecpuVm *vm) |
@@ -264,6 +248,7 @@ int execStep(OsecpuVm *vm) | ||
264 | 248 | const Int32 *ip = vm->ip; |
265 | 249 | vm->errorCode = 0; |
266 | 250 | execStepInteger(vm); if (ip != vm->ip || vm->errorCode != 0) goto fin; |
251 | + execStepOther(vm); if (ip != vm->ip || vm->errorCode != 0) goto fin; | |
267 | 252 | execStepPointer(vm); if (ip != vm->ip || vm->errorCode != 0) goto fin; |
268 | 253 | execStepFloat(vm); if (ip != vm->ip || vm->errorCode != 0) goto fin; |
269 | 254 | execStepExtend(vm); if (ip != vm->ip || vm->errorCode != 0) goto fin; |
@@ -280,6 +265,9 @@ fin: | ||
280 | 265 | |
281 | 266 | int execAll(OsecpuVm *vm) |
282 | 267 | { |
268 | + int i; | |
269 | + for (i = 0; i < PREFIX2F_SIZE; i++) | |
270 | + vm->prefix2f[i] = 0; | |
283 | 271 | for (;;) { |
284 | 272 | // 理想は適当な上限を決めて、休み休みでやるべきかもしれない. |
285 | 273 | execStep(vm); |
@@ -288,16 +276,6 @@ int execAll(OsecpuVm *vm) | ||
288 | 276 | return vm->errorCode; |
289 | 277 | } |
290 | 278 | |
291 | -void execStep_checkBitsRange(Int32 value, int bits, OsecpuVm *vm) | |
292 | -{ | |
293 | - int max, min; | |
294 | - max = 1 << (bits - 1); // 例: bits=8だとmax=128になる. | |
295 | - max--; // 例: bits=8だとmax=127になる. | |
296 | - min = - max - 1; // 例: bits=8だとmin=-128になる。 | |
297 | - if (!(min <= value && value <= max)) | |
298 | - jitcSetRetCode(&vm->errorCode, EXEC_BITS_RANGE_OVER); | |
299 | - return; | |
300 | -} | |
301 | 279 | |
302 | 280 | // 関連ツール関数. |
303 | 281 |
@@ -48,6 +48,7 @@ typedef struct _BitReader { | ||
48 | 48 | } BitReader; |
49 | 49 | |
50 | 50 | #define JITC_DSTLOG_SIZE 16 |
51 | +#define PREFIX2F_SIZE 16 | |
51 | 52 | |
52 | 53 | typedef struct _OsecpuJitc { |
53 | 54 | int phase, dstLogIndex; |
@@ -60,6 +61,7 @@ typedef struct _OsecpuJitc { | ||
60 | 61 | int errorCode, instrLength; |
61 | 62 | Int32 dr[4]; // Integer |
62 | 63 | Int32 *ope04; // Integer |
64 | + unsigned char prefix2f[PREFIX2F_SIZE]; // Integer | |
63 | 65 | } OsecpuJitc; |
64 | 66 | |
65 | 67 | typedef struct _OsecpuVm { |
@@ -72,6 +74,7 @@ typedef struct _OsecpuVm { | ||
72 | 74 | const Int32 *ip, *ip1; /* instruction-pointer, program-counter */ |
73 | 75 | const Defines *defines; |
74 | 76 | int errorCode; |
77 | + unsigned char prefix2f[PREFIX2F_SIZE]; | |
75 | 78 | } OsecpuVm; |
76 | 79 | |
77 | 80 | // osecpu-vm.c |
@@ -112,10 +115,8 @@ int jitcAll(OsecpuJitc *jitc); | ||
112 | 115 | #define JITC_BAD_LABEL_TYPE 14 |
113 | 116 | #define JITC_LABEL_UNDEFINED 15 |
114 | 117 | #define JITC_BAD_TYPE 16 |
115 | - | |
116 | -void jitcStep_checkBits32(int *pRC, int bits); | |
117 | -void jitcStep_checkRxx(int *pRC, int rxx); | |
118 | -void jitcStep_checkRxxNotR3F(int *pRC, int rxx); | |
118 | +#define JITC_BAD_PREFIX 17 | |
119 | +#define JITC_UNSUPPORTED 18 | |
119 | 120 | |
120 | 121 | int execStep(OsecpuVm *r); // 検証済みのOSECPU命令を一つだけ実行する. |
121 | 122 | int execAll(OsecpuVm *vm); |
@@ -125,32 +126,62 @@ int execAll(OsecpuVm *vm); | ||
125 | 126 | #define EXEC_BAD_R2 3 // SBX, SHL, SARのr2が不適切. |
126 | 127 | #define EXEC_DIVISION_BY_ZERO 4 |
127 | 128 | #define EXEC_SRC_OVERRUN 5 |
129 | +#define EXEC_TYP_MISMATCH 6 | |
130 | +#define EXEC_PTR_RANGE_OVER 7 | |
131 | +#define EXEC_BAD_ACCESS 8 | |
132 | +#define EXEC_API_ERROR 9 | |
128 | 133 | #define EXEC_ABORT_OPECODE_M1 0xffff |
129 | 134 | |
130 | -void execStep_checkBitsRange(Int32 value, int bits, OsecpuVm *vm); | |
135 | +#define EXEC_CMA_FLAG_SEEK 1 | |
136 | +#define EXEC_CMA_FLAG_READ 2 | |
137 | +#define EXEC_CMA_FLAG_WRITE 4 | |
138 | +#define EXEC_CMA_FLAG_EXEC 8 | |
139 | + | |
140 | +#define BIT_DISABLE_REG -1 | |
141 | +#define BIT_DISABLE_MEM 255 | |
142 | + | |
143 | +#define PTR_TYP_CODE -1 | |
144 | +#define PTR_TYP_NATIVECODE -2 | |
131 | 145 | |
132 | 146 | unsigned char *hh4StrToBin(unsigned char *src, unsigned char *src1, unsigned char *dst, unsigned char *dst1); |
133 | 147 | |
134 | -// integer.c : 整数命令 | |
148 | +// integer.c : 整数命令. | |
135 | 149 | void jitcInitInteger(OsecpuJitc *jitc); |
136 | 150 | int jitcStepInteger(OsecpuJitc *jitc); |
137 | -void jitcAfterStepInteger(OsecpuJitc *jitc); | |
151 | +int jitcAfterStepInteger(OsecpuJitc *jitc); | |
138 | 152 | void execStepInteger(OsecpuVm *vm); |
139 | 153 | |
140 | -// pointer.c : ポインタ命令 | |
154 | +int getTypBitInteger(int typ); | |
155 | +void getTypInfoInteger(int typ, int *typSize0, int *typSize1, int *typSign); | |
156 | +Int32 execStep_checkBitsRange(Int32 value, int bit, OsecpuVm *vm, int bit1, int bit2); | |
157 | +void jitcStep_checkBits32(int *pRC, int bits); | |
158 | +void jitcStep_checkRxx(int *pRC, int rxx); | |
159 | +void jitcStep_checkRxxNotR3F(int *pRC, int rxx); | |
160 | + | |
161 | +// pointer.c : ポインタ命令. | |
141 | 162 | void jitcInitPointer(OsecpuJitc *jitc); |
142 | 163 | int jitcStepPointer(OsecpuJitc *jitc); |
143 | -void jitcAfterStepPointer(OsecpuJitc *jitc); | |
164 | +int jitcAfterStepPointer(OsecpuJitc *jitc); | |
144 | 165 | void execStepPointer(OsecpuVm *vm); |
145 | 166 | |
167 | +void getTypSize(int typ, int *typSize0, int *typSize1, int *typSign); // これは直すべき. | |
168 | +void jitcStep_checkPxx(int *pRC, int pxx); | |
169 | +void execStep_checkMemAccess(OsecpuVm *vm, int p, int typ, int flag); | |
170 | + | |
146 | 171 | // float.c : 浮動小数点命令 |
147 | 172 | void jitcInitFloat(OsecpuJitc *jitc); |
148 | 173 | int jitcStepFloat(OsecpuJitc *jitc); |
149 | -void jitcAfterStepFloat(OsecpuJitc *jitc); | |
174 | +int jitcAfterStepFloat(OsecpuJitc *jitc); | |
150 | 175 | void execStepFloat(OsecpuVm *vm); |
151 | 176 | |
177 | +// other.c : 雑命令. | |
178 | +void jitcInitOther(OsecpuJitc *jitc); | |
179 | +int jitcStepOther(OsecpuJitc *jitc); | |
180 | +int jitcAfterStepOther(OsecpuJitc *jitc); | |
181 | +void execStepOther(OsecpuVm *vm); | |
182 | + | |
152 | 183 | // extend.c : 拡張命令関係. |
153 | 184 | void jitcInitExtend(OsecpuJitc *jitc); |
154 | 185 | int jitcStepExtend(OsecpuJitc *jitc); |
155 | -void jitcAfterStepExtend(OsecpuJitc *jitc); | |
186 | +int jitcAfterStepExtend(OsecpuJitc *jitc); | |
156 | 187 | void execStepExtend(OsecpuVm *vm); |
@@ -0,0 +1,87 @@ | ||
1 | +#include "osecpu-vm.h" | |
2 | + | |
3 | +// その他の命令: 00, 2F, FD | |
4 | + | |
5 | +void jitcInitOther(OsecpuJitc *jitc) | |
6 | +{ | |
7 | + jitc->ope04 = NULL; | |
8 | + return; | |
9 | +} | |
10 | + | |
11 | +int jitcStepOther(OsecpuJitc *jitc) | |
12 | +{ | |
13 | + Int32 *ip = jitc->hh4Buffer; | |
14 | + Int32 opecode = ip[0], imm; | |
15 | + int bit, bit0, bit1, r, r0, r1, r2, p, typ; | |
16 | + int retcode = -1, *pRC = &retcode; | |
17 | + int i, j; | |
18 | + if (opecode == 0x00) { /* NOP */ | |
19 | + jitcSetHh4BufferSimple(jitc, 1); | |
20 | + goto fin; | |
21 | + } | |
22 | + if (opecode == 0x2f) { | |
23 | + jitcSetHh4BufferSimple(jitc, 2); | |
24 | + i = ip[1]; | |
25 | + if (i < PREFIX2F_SIZE && jitc->prefix2f[i] == 0) | |
26 | + jitc->prefix2f[i] = 1; | |
27 | + else | |
28 | + jitcSetRetCode(pRC, JITC_BAD_PREFIX); | |
29 | + goto fin; | |
30 | + } | |
31 | + if (opecode == 0xfd) { | |
32 | + jitcSetHh4BufferSimple(jitc, 3); | |
33 | + imm = ip[1]; r = ip[2]; | |
34 | + if (0 <= r && r <= 3) | |
35 | + jitc->dr[r] = imm; | |
36 | + goto fin; | |
37 | + } | |
38 | + goto fin1; | |
39 | +fin: | |
40 | + if (retcode == -1) | |
41 | + retcode = 0; | |
42 | +fin1: | |
43 | + return retcode; | |
44 | +} | |
45 | + | |
46 | +int jitcAfterStepOther(OsecpuJitc *jitc) | |
47 | +{ | |
48 | + int i, retcode = 0; | |
49 | + if (jitc->hh4Buffer[0] != 0x2f) { | |
50 | + // 未解釈の2Fプリフィクスが残っていないか調査. | |
51 | + // 解釈したら0クリアするのが作法. | |
52 | + for (i = 0; i < PREFIX2F_SIZE; i++) { | |
53 | + if (jitc->prefix2f[i] != 0) | |
54 | + retcode = JITC_BAD_PREFIX; | |
55 | + } | |
56 | + } | |
57 | + return 0; | |
58 | +} | |
59 | + | |
60 | +void execStepOther(OsecpuVm *vm) | |
61 | +{ | |
62 | + const Int32 *ip = vm->ip; | |
63 | + Int32 opecode = ip[0], imm; | |
64 | + int bit, bit0, bit1, r, r0, r1, r2, p, typ, typSign, typSize0, typSize1; | |
65 | + int i, mbit, tbit; | |
66 | + if (opecode == 0x00) { // NOP(); | |
67 | + ip++; | |
68 | + goto fin; | |
69 | + } | |
70 | + if (opecode == 0x2f) { | |
71 | + i = ip[1]; | |
72 | + vm->prefix2f[i] = 1; | |
73 | + ip += 2; | |
74 | + goto fin; | |
75 | + } | |
76 | + if (opecode == 0xfd) { | |
77 | + imm = ip[1]; r = ip[2]; | |
78 | + if (0 <= r && r <= 3) | |
79 | + vm->dr[r] = imm; | |
80 | + goto fin; | |
81 | + } | |
82 | +fin: | |
83 | + if (vm->errorCode <= 0) | |
84 | + vm->ip = ip; | |
85 | + return; | |
86 | +} | |
87 | + |
@@ -1,19 +1,12 @@ | ||
1 | 1 | #include "osecpu-vm.h" |
2 | 2 | |
3 | -// ポインタ関連命令: 01, 03, 2E | |
3 | +// ポインタ関連命令: 01, 03, 0E, 1E, 2E | |
4 | 4 | |
5 | 5 | void jitcInitPointer(OsecpuJitc *jitc) |
6 | 6 | { |
7 | 7 | return; |
8 | 8 | } |
9 | 9 | |
10 | -void jitcStep_checkPxx(int *pRC, int pxx) | |
11 | -{ | |
12 | - if (!(0x00 <= pxx && pxx <= 0x3f)) | |
13 | - jitcSetRetCode(pRC, JITC_BAD_PXX); | |
14 | - return; | |
15 | -} | |
16 | - | |
17 | 10 | void getTypSize(int typ, int *typSize0, int *typSize1, int *typSign) |
18 | 11 | // typSize0: 入力バイナリ内でのビット数. |
19 | 12 | // typSize1: 出力バイナリ内でのバイト数. |
@@ -39,7 +32,7 @@ int jitcStepPointer(OsecpuJitc *jitc) | ||
39 | 32 | Int32 *ip = jitc->hh4Buffer; |
40 | 33 | Int32 opecode = ip[0], imm; |
41 | 34 | int retcode = -1, *pRC = &retcode; |
42 | - int i, j, opt, p, typ, len, typSign, typSize0, typSize1; | |
35 | + int i, j, opt, p, p0, p1, r, bit, typ, len, typSign, typSize0, typSize1; | |
43 | 36 | if (opecode == 0x01) { /* LB(opt, uimm); */ |
44 | 37 | jitcSetHh4BufferSimple(jitc, 3); |
45 | 38 | i = ip[1]; opt = ip[2]; |
@@ -56,7 +49,7 @@ int jitcStepPointer(OsecpuJitc *jitc) | ||
56 | 49 | jitcSetRetCode(pRC, JITC_BAD_LABEL_TYPE); |
57 | 50 | goto fin; |
58 | 51 | } |
59 | - jitc->defines->label[i].typ = -1; // とりあえずコードラベルにする. | |
52 | + jitc->defines->label[i].typ = PTR_TYP_CODE; // とりあえずコードラベルにする. | |
60 | 53 | jitc->defines->label[i].opt = opt; |
61 | 54 | jitc->defines->label[i].dst = jitc->dst; |
62 | 55 | goto fin; |
@@ -74,11 +67,29 @@ int jitcStepPointer(OsecpuJitc *jitc) | ||
74 | 67 | jitcSetRetCode(pRC, JITC_LABEL_UNDEFINED); |
75 | 68 | if (p != 0x3f && jitc->defines->label[i].opt == 0) |
76 | 69 | jitcSetRetCode(pRC, JITC_BAD_LABEL_TYPE); |
77 | - if (p == 0x3f && jitc->defines->label[i].typ != -1) | |
70 | + if (p == 0x3f && jitc->defines->label[i].typ != PTR_TYP_CODE) | |
78 | 71 | jitcSetRetCode(pRC, JITC_BAD_LABEL_TYPE); // P3Fにデータラベルを代入できない. |
79 | 72 | goto fin; |
80 | 73 | } |
81 | - if (opecode == 0x2e) { // data | |
74 | + if (opecode == 0x0e) { // PADD(r, bit, p1, typ, p0); | |
75 | + jitcSetHh4BufferSimple(jitc, 6); | |
76 | + r = ip[1]; bit = ip[2]; p1 = ip[3]; typ = ip[4]; p0 = ip[5]; | |
77 | + jitcStep_checkPxx(pRC, p0); | |
78 | + jitcStep_checkPxx(pRC, p1); | |
79 | + jitcStep_checkRxx(pRC, r); | |
80 | + jitcStep_checkBits32(pRC, bit); | |
81 | + goto fin; | |
82 | + } | |
83 | + if (opecode == 0x1e) { // PCP(p1, p0); | |
84 | + jitcSetHh4BufferSimple(jitc, 3); | |
85 | + p1 = ip[1]; p0 = ip[2]; | |
86 | + jitcStep_checkPxx(pRC, p0); | |
87 | + jitcStep_checkPxx(pRC, p1); | |
88 | + if (p1 == 0x3f) | |
89 | + jitcSetRetCode(pRC, JITC_BAD_PXX); | |
90 | + goto fin; | |
91 | + } | |
92 | + if (opecode == 0x2e) { // data...これはother.cへ移動させるべき | |
82 | 93 | BitReader br; |
83 | 94 | typ = hh4ReaderGetUnsigned(&jitc->hh4r); |
84 | 95 | len = hh4ReaderGetUnsigned(&jitc->hh4r); |
@@ -88,7 +99,7 @@ int jitcStepPointer(OsecpuJitc *jitc) | ||
88 | 99 | goto fin; |
89 | 100 | } |
90 | 101 | jitc->instrLength = 0; // 自前で処理するので、この値は0にする. |
91 | - if (jitc->dst + 3 + (typSize1 * len + 3) / 4 > jitc->dst1) { | |
102 | + if (jitc->dst + 3 + (typSize1 * len + 3) / 4 + (len + 3) / 4 > jitc->dst1) { | |
92 | 103 | jitcSetRetCode(pRC, JITC_DST_OVERRUN); |
93 | 104 | goto fin; |
94 | 105 | } |
@@ -132,12 +143,14 @@ int jitcStepPointer(OsecpuJitc *jitc) | ||
132 | 143 | } |
133 | 144 | jitc->dst += (typSize1 * len + 3) / 4; |
134 | 145 | unsigned char *puc = (unsigned char *) jitc->dst; |
146 | + int tbit = getTypBitInteger(typ); | |
135 | 147 | for (i = 0; i < len; i++) |
136 | - puc[i] = 0xff; // bits=255. | |
148 | + puc[i] = tbit; | |
137 | 149 | jitc->dst += (len + 3) / 4; |
138 | 150 | } |
139 | 151 | for (j = 0; j < JITC_DSTLOG_SIZE; j++) { |
140 | - Int32 *dstLog = jitc->dstLog[jitc->dstLogIndex + JITC_DSTLOG_SIZE - 1 - j]; | |
152 | + Int32 *dstLog = jitc->dstLog[(jitc->dstLogIndex + JITC_DSTLOG_SIZE - 1 - j) % JITC_DSTLOG_SIZE]; | |
153 | + // 1つ前、2つ前、3つ前...の命令をチェックしている. | |
141 | 154 | if (dstLog == NULL) break; |
142 | 155 | if (dstLog[0] != 0x01) break; |
143 | 156 | i = dstLog[1]; |
@@ -155,16 +168,16 @@ fin1: | ||
155 | 168 | return retcode; |
156 | 169 | } |
157 | 170 | |
158 | -void jitcAfterStepPointer(OsecpuJitc *jitc) | |
171 | +int jitcAfterStepPointer(OsecpuJitc *jitc) | |
159 | 172 | { |
160 | - return; | |
173 | + return 0; | |
161 | 174 | } |
162 | 175 | |
163 | 176 | void execStepPointer(OsecpuVm *vm) |
164 | 177 | { |
165 | 178 | const Int32 *ip = vm->ip; |
166 | 179 | Int32 opecode = ip[0]; |
167 | - int i, p, typ, len, typSign, typSize0, typSize1; | |
180 | + int i, p, r, p0, p1, bit, typ, len, typSign, typSize0, typSize1; | |
168 | 181 | if (opecode == 0x01) { /* LB(opt, uimm); */ |
169 | 182 | ip += 3; |
170 | 183 | goto fin; |
@@ -175,17 +188,21 @@ void execStepPointer(OsecpuVm *vm) | ||
175 | 188 | ip = (const Int32 *) vm->defines->label[i].dst; |
176 | 189 | else { |
177 | 190 | typ = vm->defines->label[i].typ; |
178 | - vm->p[p].p = (unsigned char *) vm->defines->label[i].dst; | |
179 | 191 | vm->p[p].typ = typ; |
180 | - vm->p[p].p0 = vm->p[p].p; | |
181 | 192 | if (typ >= 2) { |
193 | + vm->p[p].p = (unsigned char *) (vm->defines->label[i].dst + 3); | |
194 | + vm->p[p].p0 = vm->p[p].p; | |
182 | 195 | len = vm->defines->label[i].dst[2]; // 2e(data)のlenフィールド値. |
183 | - getTypSize(typ, NULL, &typSize1, NULL); | |
196 | + getTypSize(typ, &typSize0, &typSize1, &typSign); | |
184 | 197 | vm->p[p].p1 = vm->p[p].p + typSize1 * len; |
185 | 198 | vm->p[p].bit = vm->p[p].p + ((typSize1 * len + 3) / 4) * 4; |
199 | + vm->p[p].flags = 6; // over-seek:ok, read:ok, write:ok | |
186 | 200 | } |
187 | - if (typ == -1) { // コードラベル. | |
201 | + if (typ == PTR_TYP_CODE) { // コードラベル. | |
202 | + vm->p[p].p = (unsigned char *) vm->defines->label[i].dst; | |
203 | + vm->p[p].p0 = vm->p[p].p; | |
188 | 204 | vm->p[p].p1 = vm->p[p].p + 1; |
205 | + vm->p[p].flags = 0; // over-seek:ok, read:err, write:err | |
189 | 206 | } |
190 | 207 | if (typ == 1) { // VPtr. |
191 | 208 | } |
@@ -193,6 +210,40 @@ void execStepPointer(OsecpuVm *vm) | ||
193 | 210 | } |
194 | 211 | goto fin; |
195 | 212 | } |
213 | + if (opecode == 0x0e) { // PADD(r, bit, p1, typ, p0); | |
214 | + r = ip[1]; bit = ip[2]; p1 = ip[3]; typ = ip[4]; p0 = ip[5]; | |
215 | + getTypSize(typ, &typSize0, &typSize1, &typSign); | |
216 | + i = execStep_checkBitsRange(vm->r[r], bit, vm, 0, 0); | |
217 | + vm->p[p0] = vm->p[p1]; | |
218 | + vm->p[p0].p += i * typSize1; | |
219 | + vm->p[p0].bit += i; | |
220 | + execStep_checkMemAccess(vm, p0, typ, EXEC_CMA_FLAG_SEEK); | |
221 | + ip += 6; | |
222 | + } | |
223 | + if (opecode == 0x1e) { // PCP(p1, p0); | |
224 | + p1 = ip[1]; p0 = ip[2]; | |
225 | + if (p0 == 0x3f) { | |
226 | + if (vm->p[p1].typ == PTR_TYP_CODE) { // code | |
227 | + execStep_checkMemAccess(vm, p1, PTR_TYP_CODE, EXEC_CMA_FLAG_EXEC); // 主にliveSignのチェック. | |
228 | + if (vm->errorCode != 0) goto fin; | |
229 | + ip = (const Int32 *) vm->p[p1].p; | |
230 | + } | |
231 | + if (vm->p[p1].typ == PTR_TYP_NATIVECODE) { // native-code (API) | |
232 | + const Int32 *(*func)(OsecpuVm *); | |
233 | + const Int32 *nextIp; | |
234 | + func = (void *) vm->p[p1].p; | |
235 | + nextIp = (*func)(vm); | |
236 | + if (nextIp != NULL) | |
237 | + ip = nextIp; | |
238 | + else | |
239 | + jitcSetRetCode(&vm->errorCode, EXEC_API_ERROR); | |
240 | + } | |
241 | + } else { | |
242 | + vm->p[p0] = vm->p[p1]; | |
243 | + ip += 3; | |
244 | + } | |
245 | + goto fin; | |
246 | + } | |
196 | 247 | if (opecode == 0x2e) { // data |
197 | 248 | typ = ip[1]; len = ip[2]; |
198 | 249 | getTypSize(typ, &typSize0, &typSize1, &typSign); |
@@ -204,3 +255,31 @@ fin: | ||
204 | 255 | return; |
205 | 256 | } |
206 | 257 | |
258 | +void jitcStep_checkPxx(int *pRC, int pxx) | |
259 | +{ | |
260 | + if (!(0x00 <= pxx && pxx <= 0x3f)) | |
261 | + jitcSetRetCode(pRC, JITC_BAD_PXX); | |
262 | + return; | |
263 | +} | |
264 | + | |
265 | +void execStep_checkMemAccess(OsecpuVm *vm, int p, int typ, int flag) | |
266 | +{ | |
267 | + if (vm->p[p].typ != typ) | |
268 | + jitcSetRetCode(&vm->errorCode, EXEC_TYP_MISMATCH); | |
269 | + if (vm->p[p].p < vm->p[p].p0 || vm->p[p].p1 <= vm->p[p].p) { | |
270 | + if (flag != EXEC_CMA_FLAG_SEEK) | |
271 | + jitcSetRetCode(&vm->errorCode, EXEC_PTR_RANGE_OVER); | |
272 | + else { | |
273 | + if ((vm->p[p].flags & 1) != 0) | |
274 | + jitcSetRetCode(&vm->errorCode, EXEC_PTR_RANGE_OVER); // over-seek検出. | |
275 | + } | |
276 | + } | |
277 | + if (flag == EXEC_CMA_FLAG_READ && (vm->p[p].flags & EXEC_CMA_FLAG_READ) == 0) | |
278 | + jitcSetRetCode(&vm->errorCode, EXEC_BAD_ACCESS); | |
279 | + if (flag == EXEC_CMA_FLAG_WRITE && (vm->p[p].flags & EXEC_CMA_FLAG_WRITE) == 0) | |
280 | + jitcSetRetCode(&vm->errorCode, EXEC_BAD_ACCESS); | |
281 | + | |
282 | + // ToDo: liveSignに対応する. | |
283 | + return; | |
284 | +} | |
285 | + |
@@ -1,5 +1,7 @@ | ||
1 | 1 | #include "osecpu-vm.h" |
2 | 2 | |
3 | +void apiInit(OsecpuVm *vm); | |
4 | + | |
3 | 5 | #define BUFFER_SIZE 256 |
4 | 6 | |
5 | 7 | int main(int argc, const char **argv) |
@@ -60,8 +62,15 @@ int main(int argc, const char **argv) | ||
60 | 62 | "1 2 1" // LB1(2); |
61 | 63 | "ae 2 84 01 23 45 67" // data(UINT8, 4, 0x01, 0x23, 0x45, 0x67); |
62 | 64 | "3 2 1" // PLIMM(P01, 2); |
63 | - "2 1 3 a0" // LIMM32(R03, 1); | |
65 | + "2 84 3 a0" // LIMM32(R03, 4); | |
66 | + "2 2 bf a0" // LIMM32(R3F, 2); | |
67 | + "8e bf a0 1 2 1" // PADD32(P01, UINT8, P01, R3F); | |
68 | + "88 1 2 0 3 a0" // LMEM32(P01, UINT8, 0, R03); | |
64 | 69 | #endif |
70 | + "2 84 b0 a0" // LIMM32(R30, 4); | |
71 | + "3 3 b0" // PLIMM(P30, 3); | |
72 | + "9e a8 bf" // PCP(P3F, P28); | |
73 | + "1 3 1" // LB1(3); | |
65 | 74 | |
66 | 75 | , NULL, hh4src, &hh4src[BUFFER_SIZE] |
67 | 76 | ); |
@@ -84,6 +93,7 @@ int main(int argc, const char **argv) | ||
84 | 93 | vm.ip1 = jitc.dst; |
85 | 94 | // この時点で、i32buf[]は破棄しても良い. |
86 | 95 | |
96 | + apiInit(&vm); | |
87 | 97 | // execAll()を使って、j32buf[]内の中間コードを実行する. |
88 | 98 | printf("execAll()=%d\n", execAll(&vm)); // 65535なら成功(EXEC_ABORT_OPECODE_M1). |
89 | 99 | printf("R00=%d\n", vm.r[0x00]); |