From 8a7ecbf992367b1f4a309e585a638dee7c44a17c Mon Sep 17 00:00:00 2001 From: hikarupsp Date: Wed, 12 Mar 2014 20:56:56 +0900 Subject: [PATCH] =?utf8?q?=E6=94=B9=E8=A1=8C=E3=82=B3=E3=83=BC=E3=83=89?= =?utf8?q?=E3=81=AE=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- comlib.c | 150 +-- dpndenv.c | 854 +++++++-------- fontdata.c | 198 ++-- function.c | 1434 ++++++++++++------------- jitc.c | 138 +-- jitc.h | 236 ++--- jitcx86.c | 3420 ++++++++++++++++++++++++++++++------------------------------ main.c | 676 ++++++------ osecpu.h | 448 ++++---- randmt.c | 92 +- readme.txt | 38 +- screen.c | 208 ++-- 12 files changed, 3946 insertions(+), 3946 deletions(-) diff --git a/comlib.c b/comlib.c index f1d434a..84c3cb9 100644 --- a/comlib.c +++ b/comlib.c @@ -1,76 +1,76 @@ -#include "osecpu.h" - -struct ComLib_Str { - const unsigned char *p; - int bitBuf, bitBufLen; - int tmp; -}; - -int ComLib_getBit(struct ComLib_Str *s) -{ - //ビットを一つずつ取り出す - if (s->bitBufLen == 0) { - s->bitBuf = s->p[0] | s->p[1] << 8; - s->p += 2; - s->bitBufLen = 16; - } - s->bitBufLen--; - return (s->bitBuf >> s->bitBufLen) & 1; -} - -int ComLib_getTmpBit(struct ComLib_Str *s) -{ - //次のビットをtmpの一番下のビットに押し込んで、その次のビットを返す - s->tmp = (s->tmp << 1 | ComLib_getBit(s)) & 0xffff; - return ComLib_getBit(s); -} - -unsigned char *ComLib_main(const unsigned char *p, unsigned char *q) -{ - //hh4デコーダー? - struct ComLib_Str s; - int i, dis = 0; - dis |= -1; - s.p = p; - s.bitBufLen = 0; - goto l1; -l0: - *q++ = *s.p++; -l1: - i = ComLib_getBit(&s); - if (i != 0){ - //4bit? - goto l0; - } - s.tmp = 1; - do { - i = ComLib_getTmpBit(&s); - if (s.tmp == 0){ - goto fin; - } - } while (i == 0); - if (s.tmp >= 3){ - dis = ~((s.tmp - 3) << 8 | *s.p++); - } - s.tmp &= 0; - i = ComLib_getTmpBit(&s); - s.tmp = s.tmp << 1 | i; - if (s.tmp == 0) { - s.tmp |= 1; - do { - i = ComLib_getTmpBit(&s); - } while (i == 0); - s.tmp += 2; - } - s.tmp++; - if (dis < -0xd00){ - s.tmp++; - } - for (i = 0; i < s.tmp; i++){ - q[i] = q[i + dis]; - } - q += s.tmp; - goto l1; -fin: - return q; +#include "osecpu.h" + +struct ComLib_Str { + const unsigned char *p; + int bitBuf, bitBufLen; + int tmp; +}; + +int ComLib_getBit(struct ComLib_Str *s) +{ + //ビットを一つずつ取り出す + if (s->bitBufLen == 0) { + s->bitBuf = s->p[0] | s->p[1] << 8; + s->p += 2; + s->bitBufLen = 16; + } + s->bitBufLen--; + return (s->bitBuf >> s->bitBufLen) & 1; +} + +int ComLib_getTmpBit(struct ComLib_Str *s) +{ + //次のビットをtmpの一番下のビットに押し込んで、その次のビットを返す + s->tmp = (s->tmp << 1 | ComLib_getBit(s)) & 0xffff; + return ComLib_getBit(s); +} + +unsigned char *ComLib_main(const unsigned char *p, unsigned char *q) +{ + //hh4デコーダー? + struct ComLib_Str s; + int i, dis = 0; + dis |= -1; + s.p = p; + s.bitBufLen = 0; + goto l1; +l0: + *q++ = *s.p++; +l1: + i = ComLib_getBit(&s); + if (i != 0){ + //4bit? + goto l0; + } + s.tmp = 1; + do { + i = ComLib_getTmpBit(&s); + if (s.tmp == 0){ + goto fin; + } + } while (i == 0); + if (s.tmp >= 3){ + dis = ~((s.tmp - 3) << 8 | *s.p++); + } + s.tmp &= 0; + i = ComLib_getTmpBit(&s); + s.tmp = s.tmp << 1 | i; + if (s.tmp == 0) { + s.tmp |= 1; + do { + i = ComLib_getTmpBit(&s); + } while (i == 0); + s.tmp += 2; + } + s.tmp++; + if (dis < -0xd00){ + s.tmp++; + } + for (i = 0; i < s.tmp; i++){ + q[i] = q[i + dis]; + } + q += s.tmp; + goto l1; +fin: + return q; } \ No newline at end of file diff --git a/dpndenv.c b/dpndenv.c index 3c8a81e..54a520b 100644 --- a/dpndenv.c +++ b/dpndenv.c @@ -1,428 +1,428 @@ -#include "osecpu.h" - - -#if (DRV_OSNUM == 0x0002) -// -// for Mac OSX 32-bit -// -#include -#include - -void *mallocRWE(int bytes) -{ - void *p = malloc(bytes); - vm_protect(mach_task_self(), (vm_address_t) p, bytes, FALSE, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE); - return p; -} - -NSApplication* app; - -@interface OSECPUView : NSView -{ - unsigned char *_buf; - int _sx; - int _sy; - CGContextRef _context; -} - -- (id)initWithFrame:(NSRect)frameRect buf:(unsigned char *)buf sx:(int)sx sy:(int)sy; -- (void)drawRect:(NSRect)rect; -@end - -@implementation OSECPUView -- (id)initWithFrame:(NSRect)frameRect buf:(unsigned char *)buf sx:(int)sx sy:(int)sy -{ - self = [super initWithFrame:frameRect]; - if (self) { - _buf = buf; - _sx = sx; - _sy = sy; - } - return self; -} - -- (void)drawRect:(NSRect)rect { - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - _context = CGBitmapContextCreate (_buf, _sx, _sy, 8, 4 * _sx, colorSpace, (kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst)); - CGImageRef image = CGBitmapContextCreateImage(_context); - CGContextRef currentContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - CGContextDrawImage(currentContext, NSRectToCGRect(rect), image); - - CFRelease(colorSpace); - CFRelease(image); -} - -@end - -@interface Main : NSObject -{ - int argc; - const unsigned char **argv; - char *winClosed; - OSECPUView *_view; -} - -- (void)runApp; -- (void)createThread:(int)_argc args:(const unsigned char **)_argv; -- (BOOL)windowShouldClose:(id)sender; -- (void)openWin:(unsigned char *)buf sx:(int)sx sy:(int)sy winClosed:(char *)_winClosed; -- (void)flushWin:(NSRect)rect; -@end - -@implementation Main -- (void)runApp -{ - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - HeavyOSECPUMain(argc, (char **)argv); - [NSApp terminate:self]; - [pool release]; -} - -- (void)createThread : (int)_argc args:(const unsigned char **)_argv -{ - argc = _argc; - argv = _argv; - NSThread *thread = [[[NSThread alloc] initWithTarget:self selector:@selector(runApp) object:nil] autorelease]; - [thread start]; -} - -- (BOOL)windowShouldClose:(id)sender -{ - *winClosed = 1; - return YES; -} - -- (void)openWin:(unsigned char *)buf sx:(int)sx sy:(int) sy winClosed:(char *)_winClosed -{ - - NSWindow* window = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, sx, sy) styleMask: NSTitledWindowMask | NSMiniaturizableWindowMask | NSClosableWindowMask backing: NSBackingStoreBuffered defer: NO]; - [window setTitle: @"osecpu"]; - [window center]; - [window makeKeyAndOrderFront:nil]; - [window setReleasedWhenClosed:YES]; - window.delegate = self; - winClosed = _winClosed; - - _view = [[OSECPUView alloc] initWithFrame:NSMakeRect(0,0,sx,sy) buf:buf sx:sx sy:sy]; - [window.contentView addSubview:_view]; -} - -- (void)flushWin : (NSRect)rect -{ - [_view drawRect:rect]; -} - -@end - -id objc_main; - -int main(int argc, char **argv) -{ - objc_main = [[Main alloc] init]; - - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - app = [[NSApplication alloc] init]; - [objc_main createThread:argc args:(const unsigned char **)argv]; - [app run]; - [pool release]; - return 0; -} - -void drv_openWin(int sx, int sy, unsigned char *buf, char *winClosed) -{ - [objc_main openWin:buf sx:sx sy:sy winClosed:winClosed]; -} - -void drv_flshWin(int sx, int sy, int x0, int y0) -{ - [objc_main flushWin:NSMakeRect(x0,y0,sx,sy)]; -} - -void drv_sleep(int msec) -{ - [NSThread sleepForTimeInterval:0.001*msec]; - return; -} - - -#elif (DRV_OSNUM == 0x0003) - -#error "Your OS is not supported." - -#elif (DRV_OSNUM == 0x0001) -// -// for Windows 32-bit -// -#include - -#define TIMER_ID 1 -#define TIMER_INTERVAL 10 - -struct BLD_WORK { - HINSTANCE hi; - HWND hw; - BITMAPINFO bmi; - int tmcount1, tmcount2, flags, smp; /* bit0: 終了 */ - HANDLE mtx; - char *winClosed; -}; - -struct BLD_WORK bld_work; - -struct BL_WIN { - int xsiz, ysiz, *buf; -}; - -struct BL_WORK { - struct BL_WIN win; - jmp_buf jb; - int csiz_x, csiz_y, cx, cy, col0, col1, tabsiz, slctwin; - int tmcount, tmcount0, mod, rand_seed; - int *cbuf; - unsigned char *ftyp; - unsigned char **fptn; - int *ccol, *cbak; - int *kbuf, kbuf_rp, kbuf_wp, kbuf_c; -}; - -struct BL_WORK bl_work; - -#define BL_SIZ_KBUF 8192 - -#define BL_WAITKEYF 0x00000001 -#define BL_WAITKEYNF 0x00000002 -#define BL_WAITKEY 0x00000003 -#define BL_GETKEY 0x00000004 -#define BL_CLEARREP 0x00000008 -#define BL_DELFFF 0x00000010 - -#define BL_KEYMODE 0x00000000 // 作りかけ, make/remake/breakが見えるかどうか - -#define w bl_work -#define dw bld_work - -void bld_openWin(int x, int y, char *winClosed); -void bld_flshWin(int sx, int sy, int x0, int y0); -LRESULT CALLBACK WndProc(HWND hw, unsigned int msg, WPARAM wp, LPARAM lp); -void bl_cls(); -int bl_iCol(int i); -void bl_readyWin(int n); - -static HANDLE threadhandle; - -int main(int argc, char **argv) -{ - // Program entry point - return HeavyOSECPUMain(argc, argv); -} - -void *mallocRWE(int bytes) -{ - void *p = malloc(bytes); - DWORD dmy; - VirtualProtect(p, bytes, PAGE_EXECUTE_READWRITE, &dmy); - return p; -} - -static int winthread(void *dmy) -{ - WNDCLASSEX wc; - RECT r; - int i, x, y; - MSG msg; - - x = dw.bmi.bmiHeader.biWidth; - y = -dw.bmi.bmiHeader.biHeight; - - wc.cbSize = sizeof (WNDCLASSEX); - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = WndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = dw.hi; - wc.hIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), - IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); - wc.hIconSm = wc.hIcon; - wc.hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), - IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); - wc.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE; - wc.lpszMenuName = NULL; - wc.lpszClassName = L"WinClass"; - if (RegisterClassEx(&wc) == 0) - return 1; - r.left = 0; - r.top = 0; - r.right = x; - r.bottom = y; - AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, FALSE); - x = r.right - r.left; - y = r.bottom - r.top; - - char *t = "osecpu"; - - dw.hw = CreateWindowA("WinClass", t, WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, CW_USEDEFAULT, x, y, NULL, NULL, dw.hi, NULL); - if (dw.hw == NULL) - return 1; - ShowWindow(dw.hw, SW_SHOW); - UpdateWindow(dw.hw); - SetTimer(dw.hw, TIMER_ID, TIMER_INTERVAL, NULL); - SetTimer(dw.hw, TIMER_ID + 1, TIMER_INTERVAL * 10, NULL); - SetTimer(dw.hw, TIMER_ID + 2, TIMER_INTERVAL * 100, NULL); - dw.flags |= 2 | 4; - - for (;;) { - i = GetMessage(&msg, NULL, 0, 0); - if (i == 0 || i == -1) /* エラーもしくは終了メッセージ */ - break; - /* そのほかはとりあえずデフォルト処理で */ - TranslateMessage(&msg); - DispatchMessage(&msg); - } - // PostQuitMessage(0); - dw.flags |= 1; /* 終了, bld_waitNF()が見つける */ - if (dw.winClosed != NULL) - *dw.winClosed = 1; - return 0; -} - -void bld_openWin(int sx, int sy, char *winClosed) -{ - static int i; - - dw.bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER); - dw.bmi.bmiHeader.biWidth = sx; - dw.bmi.bmiHeader.biHeight = -sy; - dw.bmi.bmiHeader.biPlanes = 1; - dw.bmi.bmiHeader.biBitCount = 32; - dw.bmi.bmiHeader.biCompression = BI_RGB; - dw.winClosed = winClosed; - - threadhandle = CreateThread(NULL, 0, (void *)&winthread, NULL, 0, (void *)&i); - - return; -} - -void drv_flshWin(int sx, int sy, int x0, int y0) -{ - InvalidateRect(dw.hw, NULL, FALSE); - UpdateWindow(dw.hw); - return; -} - -LRESULT CALLBACK WndProc(HWND hw, unsigned int msg, WPARAM wp, LPARAM lp) -{ - int i, j; - if (msg == WM_PAINT) { - PAINTSTRUCT ps; - HDC hdc = BeginPaint(dw.hw, &ps); - SetDIBitsToDevice(hdc, 0, 0, w.win.xsiz, w.win.ysiz, - 0, 0, 0, w.win.ysiz, w.win.buf, &dw.bmi, DIB_RGB_COLORS); - EndPaint(dw.hw, &ps); - } - if (msg == WM_DESTROY) { - PostQuitMessage(0); - return 0; - } - if (msg == WM_TIMER && wp == TIMER_ID) { - w.tmcount += TIMER_INTERVAL; - return 0; - } - if (msg == WM_TIMER && wp == TIMER_ID + 1) { - dw.tmcount1 += TIMER_INTERVAL * 10; - w.tmcount = dw.tmcount1; - return 0; - } - if (msg == WM_TIMER && wp == TIMER_ID + 2) { - dw.tmcount2 += TIMER_INTERVAL * 100; - w.tmcount = dw.tmcount1 = dw.tmcount2; - return 0; - } - if (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) { - i = -1; - - if (wp == VK_RETURN) i = KEY_ENTER; - if (wp == VK_ESCAPE) i = KEY_ESC; - if (wp == VK_BACK) i = KEY_BACKSPACE; - if (wp == VK_TAB) i = KEY_TAB; - if (wp == VK_PRIOR) i = KEY_PAGEUP; - if (wp == VK_NEXT) i = KEY_PAGEDWN; - if (wp == VK_END) i = KEY_END; - if (wp == VK_HOME) i = KEY_HOME; - if (wp == VK_LEFT) i = KEY_LEFT; - if (wp == VK_RIGHT) i = KEY_RIGHT; - if (wp == VK_UP) i = KEY_UP; - if (wp == VK_DOWN) i = KEY_DOWN; - if (wp == VK_INSERT) i = KEY_INS; - if (wp == VK_DELETE) i = KEY_DEL; - j &= 0; - if ((GetKeyState(VK_LCONTROL) & (1 << 15)) != 0) j |= 1 << 17; - if ((GetKeyState(VK_LMENU) & (1 << 15)) != 0) j |= 1 << 18; - if ((GetKeyState(VK_RCONTROL) & (1 << 15)) != 0) j |= 1 << 25; - if ((GetKeyState(VK_RMENU) & (1 << 15)) != 0) j |= 1 << 26; - if ((GetKeyState(VK_RSHIFT) & (1 << 15)) != 0) i |= 1 << 24; - if ((GetKeyState(VK_LSHIFT) & (1 << 15)) != 0) i |= 1 << 16; - if ((GetKeyState(VK_NUMLOCK) & (1 << 0)) != 0) i |= 1 << 22; - if ((GetKeyState(VK_CAPITAL) & (1 << 0)) != 0) i |= 1 << 23; - if (j != 0) { - if ('A' <= wp && wp <= 'Z') i = wp; - } - if (i != -1) { - putKeybuf(i | j); - // bl_putKeyB(1, &i); - return 0; - } - } - if (msg == WM_KEYUP) { - i = 0xfff; - // bl_putKeyB(1, &i); - } - if (msg == WM_CHAR) { - i = 0; - if (' ' <= wp && wp <= 0x7e) { - i = wp; - j &= 0; - if ((GetKeyState(VK_LCONTROL) & (1 << 15)) != 0) j |= 1 << 17; - if ((GetKeyState(VK_LMENU) & (1 << 15)) != 0) j |= 1 << 18; - if ((GetKeyState(VK_RCONTROL) & (1 << 15)) != 0) j |= 1 << 25; - if ((GetKeyState(VK_RMENU) & (1 << 15)) != 0) j |= 1 << 26; - if ((GetKeyState(VK_RSHIFT) & (1 << 15)) != 0) i |= 1 << 24; - if ((GetKeyState(VK_LSHIFT) & (1 << 15)) != 0) i |= 1 << 16; - if ((GetKeyState(VK_NUMLOCK) & (1 << 0)) != 0) i |= 1 << 22; - if ((GetKeyState(VK_CAPITAL) & (1 << 0)) != 0) i |= 1 << 23; - if (('A' <= wp && wp <= 'Z') || ('a' <= wp && wp <= 'z')) { - if (j != 0) { - i |= j; - i &= ~0x20; - } - } - putKeybuf(i); - // bl_putKeyB(1, &i); - return 0; - } - } - return DefWindowProc(hw, msg, wp, lp); -} - -void drv_openWin(int sx, int sy, UCHAR *buf, char *winClosed) -{ - w.win.buf = (int *)buf; - w.win.xsiz = sx; - w.win.ysiz = sy; - bld_openWin(sx, sy, winClosed); - return; -} - -void drv_sleep(int msec) -{ - Sleep(msec); - // MsgWaitForMultipleObjects(1, &threadhandle, FALSE, msec, QS_ALLINPUT); - /* 勉強不足でまだ書き方が分かりません! */ - return; -} - -#else - -#error "Illegal OS type. Edit osecpu.h and look at DRV_OSNUM" - +#include "osecpu.h" + + +#if (DRV_OSNUM == 0x0002) +// +// for Mac OSX 32-bit +// +#include +#include + +void *mallocRWE(int bytes) +{ + void *p = malloc(bytes); + vm_protect(mach_task_self(), (vm_address_t) p, bytes, FALSE, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE); + return p; +} + +NSApplication* app; + +@interface OSECPUView : NSView +{ + unsigned char *_buf; + int _sx; + int _sy; + CGContextRef _context; +} + +- (id)initWithFrame:(NSRect)frameRect buf:(unsigned char *)buf sx:(int)sx sy:(int)sy; +- (void)drawRect:(NSRect)rect; +@end + +@implementation OSECPUView +- (id)initWithFrame:(NSRect)frameRect buf:(unsigned char *)buf sx:(int)sx sy:(int)sy +{ + self = [super initWithFrame:frameRect]; + if (self) { + _buf = buf; + _sx = sx; + _sy = sy; + } + return self; +} + +- (void)drawRect:(NSRect)rect { + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + _context = CGBitmapContextCreate (_buf, _sx, _sy, 8, 4 * _sx, colorSpace, (kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst)); + CGImageRef image = CGBitmapContextCreateImage(_context); + CGContextRef currentContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + CGContextDrawImage(currentContext, NSRectToCGRect(rect), image); + + CFRelease(colorSpace); + CFRelease(image); +} + +@end + +@interface Main : NSObject +{ + int argc; + const unsigned char **argv; + char *winClosed; + OSECPUView *_view; +} + +- (void)runApp; +- (void)createThread:(int)_argc args:(const unsigned char **)_argv; +- (BOOL)windowShouldClose:(id)sender; +- (void)openWin:(unsigned char *)buf sx:(int)sx sy:(int)sy winClosed:(char *)_winClosed; +- (void)flushWin:(NSRect)rect; +@end + +@implementation Main +- (void)runApp +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + HeavyOSECPUMain(argc, (char **)argv); + [NSApp terminate:self]; + [pool release]; +} + +- (void)createThread : (int)_argc args:(const unsigned char **)_argv +{ + argc = _argc; + argv = _argv; + NSThread *thread = [[[NSThread alloc] initWithTarget:self selector:@selector(runApp) object:nil] autorelease]; + [thread start]; +} + +- (BOOL)windowShouldClose:(id)sender +{ + *winClosed = 1; + return YES; +} + +- (void)openWin:(unsigned char *)buf sx:(int)sx sy:(int) sy winClosed:(char *)_winClosed +{ + + NSWindow* window = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, sx, sy) styleMask: NSTitledWindowMask | NSMiniaturizableWindowMask | NSClosableWindowMask backing: NSBackingStoreBuffered defer: NO]; + [window setTitle: @"osecpu"]; + [window center]; + [window makeKeyAndOrderFront:nil]; + [window setReleasedWhenClosed:YES]; + window.delegate = self; + winClosed = _winClosed; + + _view = [[OSECPUView alloc] initWithFrame:NSMakeRect(0,0,sx,sy) buf:buf sx:sx sy:sy]; + [window.contentView addSubview:_view]; +} + +- (void)flushWin : (NSRect)rect +{ + [_view drawRect:rect]; +} + +@end + +id objc_main; + +int main(int argc, char **argv) +{ + objc_main = [[Main alloc] init]; + + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + app = [[NSApplication alloc] init]; + [objc_main createThread:argc args:(const unsigned char **)argv]; + [app run]; + [pool release]; + return 0; +} + +void drv_openWin(int sx, int sy, unsigned char *buf, char *winClosed) +{ + [objc_main openWin:buf sx:sx sy:sy winClosed:winClosed]; +} + +void drv_flshWin(int sx, int sy, int x0, int y0) +{ + [objc_main flushWin:NSMakeRect(x0,y0,sx,sy)]; +} + +void drv_sleep(int msec) +{ + [NSThread sleepForTimeInterval:0.001*msec]; + return; +} + + +#elif (DRV_OSNUM == 0x0003) + +#error "Your OS is not supported." + +#elif (DRV_OSNUM == 0x0001) +// +// for Windows 32-bit +// +#include + +#define TIMER_ID 1 +#define TIMER_INTERVAL 10 + +struct BLD_WORK { + HINSTANCE hi; + HWND hw; + BITMAPINFO bmi; + int tmcount1, tmcount2, flags, smp; /* bit0: 終了 */ + HANDLE mtx; + char *winClosed; +}; + +struct BLD_WORK bld_work; + +struct BL_WIN { + int xsiz, ysiz, *buf; +}; + +struct BL_WORK { + struct BL_WIN win; + jmp_buf jb; + int csiz_x, csiz_y, cx, cy, col0, col1, tabsiz, slctwin; + int tmcount, tmcount0, mod, rand_seed; + int *cbuf; + unsigned char *ftyp; + unsigned char **fptn; + int *ccol, *cbak; + int *kbuf, kbuf_rp, kbuf_wp, kbuf_c; +}; + +struct BL_WORK bl_work; + +#define BL_SIZ_KBUF 8192 + +#define BL_WAITKEYF 0x00000001 +#define BL_WAITKEYNF 0x00000002 +#define BL_WAITKEY 0x00000003 +#define BL_GETKEY 0x00000004 +#define BL_CLEARREP 0x00000008 +#define BL_DELFFF 0x00000010 + +#define BL_KEYMODE 0x00000000 // 作りかけ, make/remake/breakが見えるかどうか + +#define w bl_work +#define dw bld_work + +void bld_openWin(int x, int y, char *winClosed); +void bld_flshWin(int sx, int sy, int x0, int y0); +LRESULT CALLBACK WndProc(HWND hw, unsigned int msg, WPARAM wp, LPARAM lp); +void bl_cls(); +int bl_iCol(int i); +void bl_readyWin(int n); + +static HANDLE threadhandle; + +int main(int argc, char **argv) +{ + // Program entry point + return HeavyOSECPUMain(argc, argv); +} + +void *mallocRWE(int bytes) +{ + void *p = malloc(bytes); + DWORD dmy; + VirtualProtect(p, bytes, PAGE_EXECUTE_READWRITE, &dmy); + return p; +} + +static int winthread(void *dmy) +{ + WNDCLASSEX wc; + RECT r; + int i, x, y; + MSG msg; + + x = dw.bmi.bmiHeader.biWidth; + y = -dw.bmi.bmiHeader.biHeight; + + wc.cbSize = sizeof (WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = dw.hi; + wc.hIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), + IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + wc.hIconSm = wc.hIcon; + wc.hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), + IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + wc.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE; + wc.lpszMenuName = NULL; + wc.lpszClassName = L"WinClass"; + if (RegisterClassEx(&wc) == 0) + return 1; + r.left = 0; + r.top = 0; + r.right = x; + r.bottom = y; + AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, FALSE); + x = r.right - r.left; + y = r.bottom - r.top; + + char *t = "osecpu"; + + dw.hw = CreateWindowA("WinClass", t, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, x, y, NULL, NULL, dw.hi, NULL); + if (dw.hw == NULL) + return 1; + ShowWindow(dw.hw, SW_SHOW); + UpdateWindow(dw.hw); + SetTimer(dw.hw, TIMER_ID, TIMER_INTERVAL, NULL); + SetTimer(dw.hw, TIMER_ID + 1, TIMER_INTERVAL * 10, NULL); + SetTimer(dw.hw, TIMER_ID + 2, TIMER_INTERVAL * 100, NULL); + dw.flags |= 2 | 4; + + for (;;) { + i = GetMessage(&msg, NULL, 0, 0); + if (i == 0 || i == -1) /* エラーもしくは終了メッセージ */ + break; + /* そのほかはとりあえずデフォルト処理で */ + TranslateMessage(&msg); + DispatchMessage(&msg); + } + // PostQuitMessage(0); + dw.flags |= 1; /* 終了, bld_waitNF()が見つける */ + if (dw.winClosed != NULL) + *dw.winClosed = 1; + return 0; +} + +void bld_openWin(int sx, int sy, char *winClosed) +{ + static int i; + + dw.bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER); + dw.bmi.bmiHeader.biWidth = sx; + dw.bmi.bmiHeader.biHeight = -sy; + dw.bmi.bmiHeader.biPlanes = 1; + dw.bmi.bmiHeader.biBitCount = 32; + dw.bmi.bmiHeader.biCompression = BI_RGB; + dw.winClosed = winClosed; + + threadhandle = CreateThread(NULL, 0, (void *)&winthread, NULL, 0, (void *)&i); + + return; +} + +void drv_flshWin(int sx, int sy, int x0, int y0) +{ + InvalidateRect(dw.hw, NULL, FALSE); + UpdateWindow(dw.hw); + return; +} + +LRESULT CALLBACK WndProc(HWND hw, unsigned int msg, WPARAM wp, LPARAM lp) +{ + int i, j; + if (msg == WM_PAINT) { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(dw.hw, &ps); + SetDIBitsToDevice(hdc, 0, 0, w.win.xsiz, w.win.ysiz, + 0, 0, 0, w.win.ysiz, w.win.buf, &dw.bmi, DIB_RGB_COLORS); + EndPaint(dw.hw, &ps); + } + if (msg == WM_DESTROY) { + PostQuitMessage(0); + return 0; + } + if (msg == WM_TIMER && wp == TIMER_ID) { + w.tmcount += TIMER_INTERVAL; + return 0; + } + if (msg == WM_TIMER && wp == TIMER_ID + 1) { + dw.tmcount1 += TIMER_INTERVAL * 10; + w.tmcount = dw.tmcount1; + return 0; + } + if (msg == WM_TIMER && wp == TIMER_ID + 2) { + dw.tmcount2 += TIMER_INTERVAL * 100; + w.tmcount = dw.tmcount1 = dw.tmcount2; + return 0; + } + if (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) { + i = -1; + + if (wp == VK_RETURN) i = KEY_ENTER; + if (wp == VK_ESCAPE) i = KEY_ESC; + if (wp == VK_BACK) i = KEY_BACKSPACE; + if (wp == VK_TAB) i = KEY_TAB; + if (wp == VK_PRIOR) i = KEY_PAGEUP; + if (wp == VK_NEXT) i = KEY_PAGEDWN; + if (wp == VK_END) i = KEY_END; + if (wp == VK_HOME) i = KEY_HOME; + if (wp == VK_LEFT) i = KEY_LEFT; + if (wp == VK_RIGHT) i = KEY_RIGHT; + if (wp == VK_UP) i = KEY_UP; + if (wp == VK_DOWN) i = KEY_DOWN; + if (wp == VK_INSERT) i = KEY_INS; + if (wp == VK_DELETE) i = KEY_DEL; + j &= 0; + if ((GetKeyState(VK_LCONTROL) & (1 << 15)) != 0) j |= 1 << 17; + if ((GetKeyState(VK_LMENU) & (1 << 15)) != 0) j |= 1 << 18; + if ((GetKeyState(VK_RCONTROL) & (1 << 15)) != 0) j |= 1 << 25; + if ((GetKeyState(VK_RMENU) & (1 << 15)) != 0) j |= 1 << 26; + if ((GetKeyState(VK_RSHIFT) & (1 << 15)) != 0) i |= 1 << 24; + if ((GetKeyState(VK_LSHIFT) & (1 << 15)) != 0) i |= 1 << 16; + if ((GetKeyState(VK_NUMLOCK) & (1 << 0)) != 0) i |= 1 << 22; + if ((GetKeyState(VK_CAPITAL) & (1 << 0)) != 0) i |= 1 << 23; + if (j != 0) { + if ('A' <= wp && wp <= 'Z') i = wp; + } + if (i != -1) { + putKeybuf(i | j); + // bl_putKeyB(1, &i); + return 0; + } + } + if (msg == WM_KEYUP) { + i = 0xfff; + // bl_putKeyB(1, &i); + } + if (msg == WM_CHAR) { + i = 0; + if (' ' <= wp && wp <= 0x7e) { + i = wp; + j &= 0; + if ((GetKeyState(VK_LCONTROL) & (1 << 15)) != 0) j |= 1 << 17; + if ((GetKeyState(VK_LMENU) & (1 << 15)) != 0) j |= 1 << 18; + if ((GetKeyState(VK_RCONTROL) & (1 << 15)) != 0) j |= 1 << 25; + if ((GetKeyState(VK_RMENU) & (1 << 15)) != 0) j |= 1 << 26; + if ((GetKeyState(VK_RSHIFT) & (1 << 15)) != 0) i |= 1 << 24; + if ((GetKeyState(VK_LSHIFT) & (1 << 15)) != 0) i |= 1 << 16; + if ((GetKeyState(VK_NUMLOCK) & (1 << 0)) != 0) i |= 1 << 22; + if ((GetKeyState(VK_CAPITAL) & (1 << 0)) != 0) i |= 1 << 23; + if (('A' <= wp && wp <= 'Z') || ('a' <= wp && wp <= 'z')) { + if (j != 0) { + i |= j; + i &= ~0x20; + } + } + putKeybuf(i); + // bl_putKeyB(1, &i); + return 0; + } + } + return DefWindowProc(hw, msg, wp, lp); +} + +void drv_openWin(int sx, int sy, UCHAR *buf, char *winClosed) +{ + w.win.buf = (int *)buf; + w.win.xsiz = sx; + w.win.ysiz = sy; + bld_openWin(sx, sy, winClosed); + return; +} + +void drv_sleep(int msec) +{ + Sleep(msec); + // MsgWaitForMultipleObjects(1, &threadhandle, FALSE, msec, QS_ALLINPUT); + /* 勉強不足でまだ書き方が分かりません! */ + return; +} + +#else + +#error "Illegal OS type. Edit osecpu.h and look at DRV_OSNUM" + #endif \ No newline at end of file diff --git a/fontdata.c b/fontdata.c index 8d2c2e4..f204532 100644 --- a/fontdata.c +++ b/fontdata.c @@ -1,99 +1,99 @@ - -unsigned char fontdata[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, - 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x44, 0x44, 0x44, 0xfe, 0x44, 0x44, 0x44, 0x44, 0x44, 0xfe, 0x44, 0x44, 0x44, 0x00, 0x00, - 0x10, 0x3a, 0x56, 0x92, 0x92, 0x90, 0x50, 0x38, 0x14, 0x12, 0x92, 0x92, 0xd4, 0xb8, 0x10, 0x10, - 0x62, 0x92, 0x94, 0x94, 0x68, 0x08, 0x10, 0x10, 0x20, 0x2c, 0x52, 0x52, 0x92, 0x8c, 0x00, 0x00, - 0x00, 0x70, 0x88, 0x88, 0x88, 0x90, 0x60, 0x47, 0xa2, 0x92, 0x8a, 0x84, 0x46, 0x39, 0x00, 0x00, - 0x04, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x02, 0x00, - 0x80, 0x40, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x40, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x92, 0x54, 0x38, 0x54, 0x92, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0xfe, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, - 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x40, 0x80, 0x80, - 0x00, 0x18, 0x24, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x24, 0x18, 0x00, 0x00, - 0x00, 0x08, 0x18, 0x28, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, - 0x00, 0x18, 0x24, 0x42, 0x42, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x40, 0x40, 0x7e, 0x00, 0x00, - 0x00, 0x18, 0x24, 0x42, 0x02, 0x02, 0x04, 0x18, 0x04, 0x02, 0x02, 0x42, 0x24, 0x18, 0x00, 0x00, - 0x00, 0x0c, 0x0c, 0x0c, 0x14, 0x14, 0x14, 0x24, 0x24, 0x44, 0x7e, 0x04, 0x04, 0x1e, 0x00, 0x00, - 0x00, 0x7c, 0x40, 0x40, 0x40, 0x58, 0x64, 0x02, 0x02, 0x02, 0x02, 0x42, 0x24, 0x18, 0x00, 0x00, - 0x00, 0x18, 0x24, 0x42, 0x40, 0x58, 0x64, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, - 0x00, 0x7e, 0x42, 0x42, 0x04, 0x04, 0x08, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, - 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x24, 0x18, 0x24, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, - 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x26, 0x1a, 0x02, 0x42, 0x24, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, - 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, - 0x00, 0x38, 0x44, 0x82, 0x82, 0x82, 0x04, 0x08, 0x10, 0x10, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x38, 0x44, 0x82, 0x9a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x9c, 0x80, 0x46, 0x38, 0x00, 0x00, - 0x00, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00, - 0x00, 0xf0, 0x48, 0x44, 0x44, 0x44, 0x48, 0x78, 0x44, 0x42, 0x42, 0x42, 0x44, 0xf8, 0x00, 0x00, - 0x00, 0x3a, 0x46, 0x42, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x82, 0x42, 0x44, 0x38, 0x00, 0x00, - 0x00, 0xf8, 0x44, 0x44, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x44, 0x44, 0xf8, 0x00, 0x00, - 0x00, 0xfe, 0x42, 0x42, 0x40, 0x40, 0x44, 0x7c, 0x44, 0x40, 0x40, 0x42, 0x42, 0xfe, 0x00, 0x00, - 0x00, 0xfe, 0x42, 0x42, 0x40, 0x40, 0x44, 0x7c, 0x44, 0x44, 0x40, 0x40, 0x40, 0xf0, 0x00, 0x00, - 0x00, 0x3a, 0x46, 0x42, 0x82, 0x80, 0x80, 0x9e, 0x82, 0x82, 0x82, 0x42, 0x46, 0x38, 0x00, 0x00, - 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00, - 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, - 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x84, 0x48, 0x30, 0x00, - 0x00, 0xe7, 0x42, 0x44, 0x48, 0x50, 0x50, 0x60, 0x50, 0x50, 0x48, 0x44, 0x42, 0xe7, 0x00, 0x00, - 0x00, 0xf0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x42, 0xfe, 0x00, 0x00, - 0x00, 0xc3, 0x42, 0x66, 0x66, 0x66, 0x5a, 0x5a, 0x5a, 0x42, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00, - 0x00, 0xc7, 0x42, 0x62, 0x62, 0x52, 0x52, 0x52, 0x4a, 0x4a, 0x4a, 0x46, 0x46, 0xe2, 0x00, 0x00, - 0x00, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38, 0x00, 0x00, - 0x00, 0xf8, 0x44, 0x42, 0x42, 0x42, 0x44, 0x78, 0x40, 0x40, 0x40, 0x40, 0x40, 0xf0, 0x00, 0x00, - 0x00, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x92, 0x8a, 0x44, 0x3a, 0x00, 0x00, - 0x00, 0xfc, 0x42, 0x42, 0x42, 0x42, 0x7c, 0x44, 0x42, 0x42, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00, - 0x00, 0x3a, 0x46, 0x82, 0x82, 0x80, 0x40, 0x38, 0x04, 0x02, 0x82, 0x82, 0xc4, 0xb8, 0x00, 0x00, - 0x00, 0xfe, 0x92, 0x92, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, - 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x3c, 0x00, 0x00, - 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x24, 0x24, 0x24, 0x24, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, - 0x00, 0xe7, 0x42, 0x42, 0x42, 0x5a, 0x5a, 0x5a, 0x5a, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, - 0x00, 0xe7, 0x42, 0x42, 0x24, 0x24, 0x24, 0x18, 0x24, 0x24, 0x24, 0x42, 0x42, 0xe7, 0x00, 0x00, - 0x00, 0xee, 0x44, 0x44, 0x44, 0x28, 0x28, 0x28, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, - 0x00, 0xfe, 0x84, 0x84, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x42, 0x82, 0xfe, 0x00, 0x00, - 0x00, 0x3e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3e, 0x00, - 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x04, 0x02, 0x02, - 0x00, 0x7c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x7c, 0x00, - 0x00, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, - 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x04, 0x3c, 0x44, 0x84, 0x84, 0x8c, 0x76, 0x00, 0x00, - 0xc0, 0x40, 0x40, 0x40, 0x40, 0x58, 0x64, 0x42, 0x42, 0x42, 0x42, 0x42, 0x64, 0x58, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x4c, 0x84, 0x84, 0x80, 0x80, 0x82, 0x44, 0x38, 0x00, 0x00, - 0x0c, 0x04, 0x04, 0x04, 0x04, 0x34, 0x4c, 0x84, 0x84, 0x84, 0x84, 0x84, 0x4c, 0x36, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0x82, 0xfc, 0x80, 0x82, 0x42, 0x3c, 0x00, 0x00, - 0x0e, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x4c, 0x84, 0x84, 0x84, 0x84, 0x4c, 0x34, 0x04, 0x04, 0x78, - 0xc0, 0x40, 0x40, 0x40, 0x40, 0x58, 0x64, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0xe3, 0x00, 0x00, - 0x00, 0x10, 0x10, 0x00, 0x00, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, - 0x00, 0x04, 0x04, 0x00, 0x00, 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08, 0x30, - 0xc0, 0x40, 0x40, 0x40, 0x40, 0x4e, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0xe6, 0x00, 0x00, - 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0xdb, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x64, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0xe3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x64, 0x42, 0x42, 0x42, 0x42, 0x42, 0x64, 0x58, 0x40, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x4c, 0x84, 0x84, 0x84, 0x84, 0x84, 0x4c, 0x34, 0x04, 0x0e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x62, 0x42, 0x40, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x86, 0x82, 0xc0, 0x38, 0x06, 0x82, 0xc2, 0xbc, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3b, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x24, 0x24, 0x24, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x42, 0x42, 0x5a, 0x5a, 0x5a, 0x24, 0x24, 0x24, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x44, 0x28, 0x28, 0x10, 0x28, 0x28, 0x44, 0xc6, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x42, 0x42, 0x24, 0x24, 0x24, 0x18, 0x18, 0x10, 0x10, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x84, 0x08, 0x10, 0x20, 0x42, 0x82, 0xfe, 0x00, 0x00, - 0x00, 0x06, 0x08, 0x10, 0x10, 0x10, 0x10, 0x60, 0x10, 0x10, 0x10, 0x10, 0x08, 0x06, 0x00, 0x00, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x00, 0x60, 0x10, 0x08, 0x08, 0x08, 0x08, 0x06, 0x08, 0x08, 0x08, 0x08, 0x10, 0x60, 0x00, 0x00, - 0x00, 0x72, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x44, 0x82, 0xfe, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00 -}; + +unsigned char fontdata[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, + 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x44, 0x44, 0x44, 0xfe, 0x44, 0x44, 0x44, 0x44, 0x44, 0xfe, 0x44, 0x44, 0x44, 0x00, 0x00, + 0x10, 0x3a, 0x56, 0x92, 0x92, 0x90, 0x50, 0x38, 0x14, 0x12, 0x92, 0x92, 0xd4, 0xb8, 0x10, 0x10, + 0x62, 0x92, 0x94, 0x94, 0x68, 0x08, 0x10, 0x10, 0x20, 0x2c, 0x52, 0x52, 0x92, 0x8c, 0x00, 0x00, + 0x00, 0x70, 0x88, 0x88, 0x88, 0x90, 0x60, 0x47, 0xa2, 0x92, 0x8a, 0x84, 0x46, 0x39, 0x00, 0x00, + 0x04, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x02, 0x00, + 0x80, 0x40, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x40, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x92, 0x54, 0x38, 0x54, 0x92, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0xfe, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x40, 0x80, 0x80, + 0x00, 0x18, 0x24, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x24, 0x18, 0x00, 0x00, + 0x00, 0x08, 0x18, 0x28, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, + 0x00, 0x18, 0x24, 0x42, 0x42, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x40, 0x40, 0x7e, 0x00, 0x00, + 0x00, 0x18, 0x24, 0x42, 0x02, 0x02, 0x04, 0x18, 0x04, 0x02, 0x02, 0x42, 0x24, 0x18, 0x00, 0x00, + 0x00, 0x0c, 0x0c, 0x0c, 0x14, 0x14, 0x14, 0x24, 0x24, 0x44, 0x7e, 0x04, 0x04, 0x1e, 0x00, 0x00, + 0x00, 0x7c, 0x40, 0x40, 0x40, 0x58, 0x64, 0x02, 0x02, 0x02, 0x02, 0x42, 0x24, 0x18, 0x00, 0x00, + 0x00, 0x18, 0x24, 0x42, 0x40, 0x58, 0x64, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, + 0x00, 0x7e, 0x42, 0x42, 0x04, 0x04, 0x08, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, + 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x24, 0x18, 0x24, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, + 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x26, 0x1a, 0x02, 0x42, 0x24, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x08, 0x10, + 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, + 0x00, 0x38, 0x44, 0x82, 0x82, 0x82, 0x04, 0x08, 0x10, 0x10, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x38, 0x44, 0x82, 0x9a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x9c, 0x80, 0x46, 0x38, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00, + 0x00, 0xf0, 0x48, 0x44, 0x44, 0x44, 0x48, 0x78, 0x44, 0x42, 0x42, 0x42, 0x44, 0xf8, 0x00, 0x00, + 0x00, 0x3a, 0x46, 0x42, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x82, 0x42, 0x44, 0x38, 0x00, 0x00, + 0x00, 0xf8, 0x44, 0x44, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x44, 0x44, 0xf8, 0x00, 0x00, + 0x00, 0xfe, 0x42, 0x42, 0x40, 0x40, 0x44, 0x7c, 0x44, 0x40, 0x40, 0x42, 0x42, 0xfe, 0x00, 0x00, + 0x00, 0xfe, 0x42, 0x42, 0x40, 0x40, 0x44, 0x7c, 0x44, 0x44, 0x40, 0x40, 0x40, 0xf0, 0x00, 0x00, + 0x00, 0x3a, 0x46, 0x42, 0x82, 0x80, 0x80, 0x9e, 0x82, 0x82, 0x82, 0x42, 0x46, 0x38, 0x00, 0x00, + 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00, + 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, + 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x84, 0x48, 0x30, 0x00, + 0x00, 0xe7, 0x42, 0x44, 0x48, 0x50, 0x50, 0x60, 0x50, 0x50, 0x48, 0x44, 0x42, 0xe7, 0x00, 0x00, + 0x00, 0xf0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x42, 0xfe, 0x00, 0x00, + 0x00, 0xc3, 0x42, 0x66, 0x66, 0x66, 0x5a, 0x5a, 0x5a, 0x42, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00, + 0x00, 0xc7, 0x42, 0x62, 0x62, 0x52, 0x52, 0x52, 0x4a, 0x4a, 0x4a, 0x46, 0x46, 0xe2, 0x00, 0x00, + 0x00, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38, 0x00, 0x00, + 0x00, 0xf8, 0x44, 0x42, 0x42, 0x42, 0x44, 0x78, 0x40, 0x40, 0x40, 0x40, 0x40, 0xf0, 0x00, 0x00, + 0x00, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x92, 0x8a, 0x44, 0x3a, 0x00, 0x00, + 0x00, 0xfc, 0x42, 0x42, 0x42, 0x42, 0x7c, 0x44, 0x42, 0x42, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00, + 0x00, 0x3a, 0x46, 0x82, 0x82, 0x80, 0x40, 0x38, 0x04, 0x02, 0x82, 0x82, 0xc4, 0xb8, 0x00, 0x00, + 0x00, 0xfe, 0x92, 0x92, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, + 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x3c, 0x00, 0x00, + 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x24, 0x24, 0x24, 0x24, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, + 0x00, 0xe7, 0x42, 0x42, 0x42, 0x5a, 0x5a, 0x5a, 0x5a, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, + 0x00, 0xe7, 0x42, 0x42, 0x24, 0x24, 0x24, 0x18, 0x24, 0x24, 0x24, 0x42, 0x42, 0xe7, 0x00, 0x00, + 0x00, 0xee, 0x44, 0x44, 0x44, 0x28, 0x28, 0x28, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, + 0x00, 0xfe, 0x84, 0x84, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x42, 0x82, 0xfe, 0x00, 0x00, + 0x00, 0x3e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3e, 0x00, + 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x04, 0x02, 0x02, + 0x00, 0x7c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x7c, 0x00, + 0x00, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, + 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x04, 0x3c, 0x44, 0x84, 0x84, 0x8c, 0x76, 0x00, 0x00, + 0xc0, 0x40, 0x40, 0x40, 0x40, 0x58, 0x64, 0x42, 0x42, 0x42, 0x42, 0x42, 0x64, 0x58, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x4c, 0x84, 0x84, 0x80, 0x80, 0x82, 0x44, 0x38, 0x00, 0x00, + 0x0c, 0x04, 0x04, 0x04, 0x04, 0x34, 0x4c, 0x84, 0x84, 0x84, 0x84, 0x84, 0x4c, 0x36, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0x82, 0xfc, 0x80, 0x82, 0x42, 0x3c, 0x00, 0x00, + 0x0e, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x4c, 0x84, 0x84, 0x84, 0x84, 0x4c, 0x34, 0x04, 0x04, 0x78, + 0xc0, 0x40, 0x40, 0x40, 0x40, 0x58, 0x64, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0xe3, 0x00, 0x00, + 0x00, 0x10, 0x10, 0x00, 0x00, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, + 0x00, 0x04, 0x04, 0x00, 0x00, 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08, 0x30, + 0xc0, 0x40, 0x40, 0x40, 0x40, 0x4e, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0xe6, 0x00, 0x00, + 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0xdb, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x64, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0xe3, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x64, 0x42, 0x42, 0x42, 0x42, 0x42, 0x64, 0x58, 0x40, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x4c, 0x84, 0x84, 0x84, 0x84, 0x84, 0x4c, 0x34, 0x04, 0x0e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x62, 0x42, 0x40, 0x40, 0x40, 0x40, 0x40, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x86, 0x82, 0xc0, 0x38, 0x06, 0x82, 0xc2, 0xbc, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3b, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x24, 0x24, 0x24, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x42, 0x42, 0x5a, 0x5a, 0x5a, 0x24, 0x24, 0x24, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x44, 0x28, 0x28, 0x10, 0x28, 0x28, 0x44, 0xc6, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x42, 0x42, 0x24, 0x24, 0x24, 0x18, 0x18, 0x10, 0x10, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x84, 0x08, 0x10, 0x20, 0x42, 0x82, 0xfe, 0x00, 0x00, + 0x00, 0x06, 0x08, 0x10, 0x10, 0x10, 0x10, 0x60, 0x10, 0x10, 0x10, 0x10, 0x08, 0x06, 0x00, 0x00, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x00, 0x60, 0x10, 0x08, 0x08, 0x08, 0x08, 0x06, 0x08, 0x08, 0x08, 0x08, 0x10, 0x60, 0x00, 0x00, + 0x00, 0x72, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x44, 0x82, 0xfe, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00 +}; diff --git a/function.c b/function.c index 43750fd..f0e1f62 100644 --- a/function.c +++ b/function.c @@ -1,717 +1,717 @@ -#include "osecpu.h" - -extern unsigned char fontdata[]; // @fontdata.c - -const char *searchArg(int argc, const char **argv, const char *tag, int i) -{ - int j, l; - const char *r = NULL; - if (tag != NULL) { - l = (int)strlen(tag); - for (j = 1; j < argc; j++) { - if (strncmp(argv[j], tag, l) == 0) { - r = argv[j] + l; - if (i == 0){ - break; - } - i--; - } - } - } - else { - for (j = 1; j < argc; j++) { - if (strchr(argv[j], ':') == NULL) { - r = argv[j]; - if (i == 0){ - break; - } - i--; - } - } - } - if (i != 0){ - r = NULL; - } - return r; -} - -void devFunc0001(int len, unsigned char *puc, HOSECPU_RuntimeEnvironment *r) -{ - while (len > 0) { - putOsaskChar(*puc++, r); - len--; - } - return; -} - -void devFunc0006(int mod, int sx, int sy, int x, int y, int c, int len, unsigned char *puc, HOSECPU_RuntimeEnvironment *r) -{ - int xx; - int yy; - int i, ddx, ddy, j, ch, dx, dy; - - if (sy == 0){ - sy = sx; - } - xx = x + sx * 8; - yy = y + sy * 16; - if (xx <= 0 || xx > mainWindow.xsize || yy <= 0 || yy > mainWindow.ysize){ - (*(r->errHndl))(r); - } - if (x < 0 || x >= mainWindow.xsize || y < 0 || y >= mainWindow.ysize){ - (*(r->errHndl))(r); - } - - - if ((mod & 3) == 0 && sx == 1 && sy == 1) { - // メジャーケースを高速化. - for (i = 0; i < len; i++) { - ch = puc[i]; - if (0x10 <= ch && ch <= 0x1f) - ch = "0123456789ABCDEF"[ch & 0x0f]; - for (dy = 0; dy < 16; dy++) { - j = fontdata[(ch - ' ') * 16 + dy]; - for (dx = 0; dx < 8; dx++) { - if ((j & (0x80 >> dx)) != 0){ - mainWindow.vram[(x + dx) + (y + dy) * mainWindow.xsize] = c; - } - } - } - x += 8; - } - return; - } - for (i = 0; i < len; i++) { - ch = puc[i]; - if (0x10 <= ch && ch <= 0x1f) - ch = "0123456789ABCDEF"[ch & 0x0f]; - for (dy = 0; dy < 16; dy++) { - j = fontdata[(ch - ' ') * 16 + dy]; - for (ddy = 0; ddy < sy; ddy++) { - for (dx = 0; dx < 8; dx++) { - if ((j & (0x80 >> dx)) != 0) { - for (ddx = 0; ddx < sx; ddx++) { - switch (mod & 3) { - case 0: - mainWindow.vram[x + y * mainWindow.xsize] = c; - break; - case 1: - mainWindow.vram[x + y * mainWindow.xsize] |= c; - break; - case 2: - mainWindow.vram[x + y * mainWindow.xsize] ^= c; - break; - case 3: - mainWindow.vram[x + y * mainWindow.xsize] &= c; - break; - } - x++; - } - } else{ - x += sx; - } - } - x -= sx * 8; - y++; - } - } - x += sx * 8; - y -= sy * 16; - } - return; -} - -void devFunc0004(int mod, int x0, int y0, int x1, int y1, int c) -{ - int x, y; - if (mod == 0) { - for (y = y0; y <= y1; y++) { - for (x = x0; x <= x1; x++) { - mainWindow.vram[x + y * mainWindow.xsize] = c; - } - } - } - else { - for (y = y0; y <= y1; y++) { - for (x = x0; x <= x1; x++) { - switch (mod) { - case 1: - mainWindow.vram[x + y * mainWindow.xsize] |= c; - break; - case 2: - mainWindow.vram[x + y * mainWindow.xsize] ^= c; - break; - case 3: - mainWindow.vram[x + y * mainWindow.xsize] &= c; - break; - } - } - } - } - return; -} - -int devFunc0016(int buflen, unsigned char *buf, int plen, unsigned char *p, int qlen, int *q, HOSECPU_RuntimeEnvironment *r) -{ - int i = 0, base, j, k; - char sign; - - while (plen > 0) { - if (i >= buflen){ - (*(r->errHndl))(r); - } - if (*p != 0x01) { - buf[i++] = *p++; - plen--; - continue; - } - p++; - plen--; - if (qlen < 4){ - (*(r->errHndl))(r); - } - base = q[0]; - sign = 0; - if (base == 0){ - base = 16; - } -#if (REVISION == 1) - if (base == -3){ - base = 10; - } -#endif - if (base == -1){ - base = 10; - } - if (base < 0 || base > 16){ - (*(r->errHndl))(r); - } - if (q[1] + i > buflen){ - (*(r->errHndl))(r); - } - j = q[3]; - if ((q[2] & 4) == 0) { - // jは符号付き整数. - if ((q[2] & 8) != 0 && j > 0){ - sign = '+'; - } - if (j < 0) { - sign = '-'; j *= -1; - } - } else{ - // jは符号無し整数. - if ((q[2] & 8) != 0 && j != 0){ - sign = '+'; - } - } - for (k = q[1] - 1; k >= 0; k--) { - buf[i + k] = (j % base) + 0x10; - j = ((unsigned)j) / base; - } - k = 0; - if ((q[2] & 2) == 0 && j == 0) { - for (k = 0; k < q[1] - 1; k++) { - if (buf[i + k] != 0x10){ - break; - } - buf[i + k] = ' '; - } - } - if (sign != 0) { - if (k > 0){ - k--; - } - buf[i + k] = sign; - } - if ((q[2] & 1) != 0 && buf[i] == ' ') { - for (j = 0; k < q[1]; k++, j++){ - buf[i + j] = buf[i + k]; - } - i += j; - } else{ - i += q[1]; - } - qlen -= 4; - q += 4; - } - return i; -} - -void devFunc(HOSECPU_RuntimeEnvironment *r) -{ - FILE *fp; - int i, c; - int x, y, len, dx, dy; - unsigned char *puc; - unsigned char pucbuf[256]; - - //サイズを節約するためにEBPを128バイトずらしているのを元に戻す - r = (HOSECPU_RuntimeEnvironment *) (((char *)r) - 128); - - if (r->winClosed != 0){ - longjmp(*(r->setjmpEnv), 1); - } - if (0xff44 <= r->ireg[0x30] && r->ireg[0x30] <= 0xff48) { - if (mainWindow.vram == NULL) { - mainWindow.xsize = 640; - mainWindow.ysize = 480; - mainWindow.vram = malloc(640 * 480 * 4); - drv_openWin(640, 480, (void *)mainWindow.vram, &r->winClosed); - r->autoSleep = 1; - for (i = 640 * 480 - 1; i >= 0; i--){ - mainWindow.vram[i] = 0; - } - } - } - - switch (r->ireg[0x30]){ - case 0xff00: - printf("R31=%d(dec)\n", r->ireg[0x31]); - break; - - case 0xff01: - /* return: R30, P31 */ - if (r->buf0 == NULL){ - r->buf0 = malloc(1024 * 1024); - } - if (r->mainArgc <= r->ireg[0x31]) { - fprintf(stderr, "devFunc: error: R30=ff01: argc error: R31=%08X\n", r->ireg[0x31]); - exit(1); - } - fp = fopen(r->mainArgv[r->ireg[0x31]], "rb"); - if (fp == NULL) { - fprintf(stderr, "devFunc: error: R30=ff01: fopen error: '%s'\n", r->mainArgv[r->ireg[0x31]]); - exit(1); - } - i = (int)fread(r->buf0, 1, 1024 * 1024 - 4, fp); - if (i >= 1024 * 1024 - 4 || i < 0) { - fprintf(stderr, "devFunc: error: R30=ff01: fread error: '%s'\n", r->mainArgv[r->ireg[0x31]]); - exit(1); - } - fclose(fp); - r->preg[0x31].p = r->buf0; - r->preg[0x31].p0 = r->buf0; - r->preg[0x31].p1 = r->buf0 + i; - r->preg[0x31].typ = 3; // T_UINT8 - r->ireg[0x30] = i; - break; - - case 0xff02: - /* return: none */ - if (r->mainArgc <= r->ireg[0x31]) { - fprintf(stderr, "devFunc: error: R30=ff02: argc error: R31=%08X\n", r->ireg[0x31]); - exit(1); - } - fp = fopen(r->mainArgv[r->ireg[0x31]], "wb"); - if (fp == NULL) { - fprintf(stderr, "devFunc: error: R30=ff02: fopen error: '%s'\n", r->mainArgv[r->ireg[0x31]]); - exit(1); - } - if (r->ireg[0x32] >= 1024 * 1024 || r->ireg[0x32] < 0){ - fprintf(stderr, "devFunc: error: R30=ff02: fwrite error: R02=%08X\n", r->ireg[0x32]); - exit(1); - } - fwrite(r->preg[0x31].p, 1, r->ireg[0x32], fp); - fclose(fp); - break; - - case 0xff03: - /* return: P31 */ - if (r->buf1 == NULL){ - r->buf1 = malloc(1024 * 1024); - } - r->preg[0x31].p = r->buf1; - r->preg[0x31].p0 = r->buf1; - r->preg[0x31].p1 = r->buf1 + 1024 * 1024; - break; - - case 0xff04: - printf("P31.(p-p0)=%d(dec)\n", (int)(r->preg[0x31].p - r->preg[0x31].p0)); - break; - - case 0xff05: - fwrite(r->preg[0x31].p, 1, r->ireg[0x31], stdout); - break; - - case 0xff06: - // R31はリターンコード. - // これを反映すべきだが、現状は手抜きでいつも正常終了. - longjmp(*(r->setjmpEnv), 1); - break; - - case 0xff07: - // マシになった文字列表示.OSASK文字列に対応.offにすれば通常の文字列処理もできる.現状はonのみサポート. - checkString(r, 0x31, 0x31); - devFunc0001(r->ireg[0x31], r->preg[0x31].p, r); - break; - - case 0xff08: - // JITC on JITC - // R31: 言語(back-end, front-end, ... - // R32: level - // R33: debugInfo1 - checkString(r, 0x34, 0x31); - if (r->ireg[0x33] < 0 || r->ireg[0x33] > 15 || r->debugInfo1 > 15){ - (*(r->errHndl))(r); - } - for (i = 0; i < r->maxLabels; i++){ - r->label[i].opt = 0; - } - puc = r->preg[0x31].p; - i = jitCompiler(r->jitbuf, r->jitbuf1, puc, puc + r->ireg[0x34], puc, r->label, r->maxLabels, r->ireg[0x32], di1_serial, JITC_NOSTARTUP + 0); - if (i == 0) { - i = jitCompiler(r->jitbuf, r->jitbuf1, puc, puc + r->ireg[0x34], puc, r->label, r->maxLabels, r->ireg[0x32], di1_serial, JITC_NOSTARTUP + JITC_PHASE1 + 0); - if (i >= 0) { - r->mapDi1s[r->debugInfo1][r->ireg[0x33]] = di1_serial; - di1_serial++; - r->ireg[0x30] = 0; - r->preg[0x31].p = r->jitbuf; - r->preg[0x31].typ = 0; // TYP_CODE - r->preg[0x31].p0 = r->jitbuf; - r->preg[0x31].p1 = r->jitbuf + 1; - //int j; for (j = 0; j < i; j++) printf("%02X ", r->jitbuf[j]); putchar('\n'); - r->jitbuf += i; - static unsigned char ff08_ret[3] = { 0x1e, 0x3f, 0x30 }; - i = jitCompiler(r->jitbuf, r->jitbuf1, ff08_ret, ff08_ret + 3, puc, r->label, r->maxLabels, r->ireg[0x32], -1, JITC_NOSTARTUP + JITC_PHASE1 + 0); - r->jitbuf += i; - break; - } - } - r->ireg[0x30] = -1; - break; - - case 0xff09: - // たぶんbit7を使ったテキストはうまく処理できない(これはもはや仕様にしても問題ないかも). - checkString(r, 0x31, 0x31); - len = devFunc0016(sizeof pucbuf, pucbuf, r->ireg[0x31], r->preg[0x31].p, r->ireg[0x32], (int *)r->preg[0x32].p, r); - devFunc0001(len, pucbuf, r); - break; - - case 0xff40: - /* R31とR32でサイズを指定 */ - mainWindow.xsize = r->ireg[0x31]; - mainWindow.ysize = r->ireg[0x32]; - if (mainWindow.xsize <= 0 || mainWindow.ysize <= 0){ - (*(r->errHndl))(r); - } - r->preg[0x31].p = (void *)(mainWindow.vram = malloc(mainWindow.xsize * mainWindow.ysize * 4)); - r->preg[0x31].p0 = r->preg[0x31].p; - r->preg[0x31].p1 = r->preg[0x31].p + mainWindow.xsize * mainWindow.ysize * 4; - drv_openWin(r->ireg[0x31], r->ireg[0x32], r->preg[0x31].p, &r->winClosed); - // drv_flshWin(r->ireg[1], r->ireg[2], 0, 0); - r->autoSleep = 1; - for (i = mainWindow.xsize * mainWindow.ysize - 1; i >= 0; i--){ - mainWindow.vram[i] = 0; - } - break; - - case 0xff41: - /* R31とR32でサイズを指定、R33とR34でx0,y0指定 */ - if (r->ireg[0x31] == -1) { - r->ireg[0x31] = mainWindow.xsize; r->ireg[0x33] &= 0; - } - if (r->ireg[0x32] == -1) { - r->ireg[0x32] = mainWindow.ysize; r->ireg[0x34] &= 0; - } - checkRect(r, 0x31); - drv_flshWin(r->ireg[0x31], r->ireg[0x32], r->ireg[0x33], r->ireg[0x34]); - break; - - case 0xff42: - if (r->ireg[0x32] == -1) { - r->autoSleep = 1; - longjmp(*(r->setjmpEnv), 1); - } - if (r->ireg[0x32] < 0){ - (*(r->errHndl))(r); - } - r->autoSleep = 0; - if ((r->ireg[0x31] & 1) == 0 && mainWindow.vram != NULL){ - drv_flshWin(mainWindow.xsize, mainWindow.ysize, 0, 0); - } - for (;;) { - if (r->winClosed != 0){ - longjmp(*(r->setjmpEnv), 1); - } - drv_sleep(r->ireg[0x32]); - if ((r->ireg[0x31] & 2) != 0 && keybuf_c <= 0){ - continue; - } - break; - } - break; - - case 0xff43: - // 1:peek - // 2:stdin - // 4,8: ソース指定. - // 16: shift, lock系を有効化. - // 32: 左右のshift系を区別する. - if (r->ireg[0x31] == 2) { // なぜ3にしなかったのか... - r->ireg[0x30] = fgetc(stdin); - if (r->ireg[0x30] == EOF){ - r->ireg[0x30] = -1; - } - break; - } - r->ireg[0x30] |= -1; - if (keybuf_c > 0) { - r->ireg[0x30] = keybuf[keybuf_r]; - if ((r->ireg[0x31] & 16) == 0){ - r->ireg[0x30] &= 0x3e3effff; - } - if ((r->ireg[0x31] & 32) == 0){ - r->ireg[0x30] |= (r->ireg[0x30] >> 8) & 0xff0000; - } - if ((r->ireg[0x31] & 1) != 0) { - keybuf_c--; - keybuf_r = (keybuf_r + 1) & (KEYBUFSIZ - 1); - } - } - r->ireg[0x32] = r->ireg[0x33] = 0; - if (r->ireg[0x30] == 4132) r->ireg[0x32]--; - if (r->ireg[0x30] == 4133) r->ireg[0x33]--; - if (r->ireg[0x30] == 4134) r->ireg[0x32]++; - if (r->ireg[0x30] == 4135) r->ireg[0x33]++; - break; - - case 0xff44: - c = loadColor(r, 0x34); - if (r->ireg[0x32] < 0 || r->ireg[0x32] >= mainWindow.xsize || - r->ireg[0x33] < 0 || r->ireg[0x33] >= mainWindow.ysize){ - (*(r->errHndl))(r); - } - - switch ((r->ireg[0x31] & 3)) { - case 0: - mainWindow.vram[r->ireg[0x32] + r->ireg[0x33] * mainWindow.xsize] = c; - break; - case 1: - mainWindow.vram[r->ireg[0x32] + r->ireg[0x33] * mainWindow.xsize] |= c; - break; - case 2: - mainWindow.vram[r->ireg[0x32] + r->ireg[0x33] * mainWindow.xsize] ^= c; - break; - case 3: - mainWindow.vram[r->ireg[0x32] + r->ireg[0x33] * mainWindow.xsize] &= c; - break; - } - break; - - case 0xff45: - //drawLine - c = loadColor(r, 0x36); - if (r->ireg[0x32] < 0 || r->ireg[0x32] >= mainWindow.xsize || - r->ireg[0x33] < 0 || r->ireg[0x33] >= mainWindow.ysize){ - (*(r->errHndl))(r); - } - if (r->ireg[0x34] < 0 || r->ireg[0x34] >= mainWindow.xsize || - r->ireg[0x35] < 0 || r->ireg[0x35] >= mainWindow.ysize){ - (*(r->errHndl))(r); - } - dx = r->ireg[0x34] - r->ireg[0x32]; - dy = r->ireg[0x35] - r->ireg[0x33]; - x = r->ireg[0x32] << 10; - y = r->ireg[0x33] << 10; - if (dx < 0){ - dx = -dx; - } - if (dy < 0){ - dy = -dy; - } - if (dx >= dy) { - len = dx + 1; dx = 1024; - if (r->ireg[0x32] > r->ireg[0x34]){ - dx *= -1; - } - if (r->ireg[0x33] > r->ireg[0x35]){ - dy *= -1; - } - dy = (dy << 10) / len; - } else { - len = dy + 1; dy = 1024; - if (r->ireg[0x33] > r->ireg[0x35]){ - dy *= -1; - } - if (r->ireg[0x32] > r->ireg[0x34]){ - dx *= -1; - } - dx = (dx << 10) / len; - } - if ((r->ireg[0x31] & 3) == 0) { - for (i = 0; i < len; i++) { - mainWindow.vram[(x >> 10) + (y >> 10) * mainWindow.xsize] = c; - x += dx; - y += dy; - } - break; - } - for (i = 0; i < len; i++) { - // if ((r->ireg[0x31] & 3) == 0) vram[(x >> 10) + (y >> 10) * v_xsiz] = c; - switch ((r->ireg[0x31] & 3)) { - case 1: - mainWindow.vram[(x >> 10) + (y >> 10) * mainWindow.xsize] |= c; - break; - case 2: - mainWindow.vram[(x >> 10) + (y >> 10) * mainWindow.xsize] ^= c; - break; - case 3: - mainWindow.vram[(x >> 10) + (y >> 10) * mainWindow.xsize] &= c; - break; - default: - break; - } - x += dx; - y += dy; - } - break; - - case 0xff46: // fillRect(opt:R31, xsiz:R32, ysiz:R33, x0:R34, y0:R35, c:R36) - c = loadColor(r, 0x36); - if (r->ireg[0x32] == -1) { r->ireg[0x32] = mainWindow.xsize; r->ireg[0x34] &= 0; } - if (r->ireg[0x33] == -1) { r->ireg[0x33] = mainWindow.ysize; r->ireg[0x35] &= 0; } - checkRect(r, 0x32); - int mod3 = r->ireg[0x31] & 3, x0 = r->ireg[0x34], y0 = r->ireg[0x35], x1 = r->ireg[0x34] + r->ireg[0x32] - 1, y1 = r->ireg[0x35] + r->ireg[0x33] - 1; - if ((r->ireg[0x31] & 0x20) == 0) { - devFunc0004(mod3, x0, y0, x1, y1, c); - } else { // drawRect - devFunc0004(mod3, x0, y0, x1, y0, c); - devFunc0004(mod3, x0, y1, x1, y1, c); - devFunc0004(mod3, x0, y0, x0, y1, c); - devFunc0004(mod3, x1, y0, x1, y1, c); - } - break; - - case 0xff47: // fillOval(opt:R31, xsiz:R32, ysiz:R33, x0:R34, y0:R35, c:R36) - // これの計算精度はアーキテクチャに依存する. - c = loadColor(r, 0x36); - if (r->ireg[0x32] == -1) { - r->ireg[0x32] = mainWindow.xsize; r->ireg[0x34] &= 0; - } - if (r->ireg[0x33] == -1) { - r->ireg[0x33] = mainWindow.ysize; r->ireg[0x35] &= 0; - } - checkRect(r, 0x32); - double dcx = 0.5 * (r->ireg[0x32] - 1); - double dcy = 0.5 * (r->ireg[0x33] - 1); - double dcxy = (dcx + 0.5) * (dcy + 0.5) - 0.1; - dcxy *= dcxy; - mod3 = r->ireg[0x31] & 3; - x1 = r->ireg[0x32]; - y1 = r->ireg[0x33]; - if (mod3 == 0 && (r->ireg[0x31] & 0x20) == 0) { - for (y = 0; y < y1; y++) { - double dty = (y - dcy) * dcx; - for (x = 0; x < x1; x++) { - double dtx = (x - dcx) * dcy; - if (dtx * dtx + dty * dty > dcxy){ - continue; - } - mainWindow.vram[(x + r->ireg[0x34]) + (y + r->ireg[0x35]) * mainWindow.xsize] = c; - } - } - } else { -#define DRAWOVALPARAM 1 - double dcx1 = 0.5 * (r->ireg[0x32] - (1 + DRAWOVALPARAM * 2)); - double dcy1 = 0.5 * (r->ireg[0x33] - (1 + DRAWOVALPARAM * 2)); - double dcxy1 = (dcx1 + 0.5) * (dcy1 + 0.5) - 0.1; - dcxy1 *= dcxy1; - for (y = 0; y < y1; y++) { - double dty = (y - dcy) * dcx; - double dty1 = (y - dcy) * dcx1; - for (x = 0; x < x1; x++) { - double dtx = (x - dcx) * dcy; - double dtx1 = (x - dcx) * dcy1; - if (dtx * dtx + dty * dty > dcxy){ - continue; - } - if (DRAWOVALPARAM <= x && x < x1 - DRAWOVALPARAM && DRAWOVALPARAM <= y && y < y1 - DRAWOVALPARAM) { - if (dtx1 * dtx1 + dty1 * dty1 < dcxy1){ - continue; - } - } - switch (mod3) { - case 0: - mainWindow.vram[(x + r->ireg[0x34]) + (y + r->ireg[0x35]) * mainWindow.xsize] = c; - break; - case 1: - mainWindow.vram[(x + r->ireg[0x34]) + (y + r->ireg[0x35]) * mainWindow.xsize] |= c; - break; - case 2: - mainWindow.vram[(x + r->ireg[0x34]) + (y + r->ireg[0x35]) * mainWindow.xsize] ^= c; - break; - case 3: - mainWindow.vram[(x + r->ireg[0x34]) + (y + r->ireg[0x35]) * mainWindow.xsize] &= c; - break; - } - } - } - } - break; - - case 0xff48: // drawString(opt:R31, xsiz:R32, ysiz:R33, x0:R34, y0:R35, c:R36, s.len:R37, s.p:P31) - checkString(r, 0x37, 0x31); - devFunc0006(r->ireg[0x31], r->ireg[0x32], r->ireg[0x33], r->ireg[0x34], r->ireg[0x35], loadColor(r, 0x36), r->ireg[0x37], r->preg[0x31].p, r); - break; - - case 0xff49: - // **** junkApi_rand(i, max) **** - // 0 <= i <= maxとなるiを返す。 - // max==0のとき、iはSINT32全体を範囲とする乱数となる。 - r->ireg[0x30] = randGetNextUInt32(); - if (r->ireg[0x31] > 0){ - r->ireg[0x30] = (r->ireg[0x30] & 0x7fffffff) % (r->ireg[0x31] + 1); - } - break; - - case 0xff4a: /* seedの指定 */ - randStatInit(r->ireg[0x31]); - break; - - case 0xff4b: /* 適当なseedを提供 */ - r->ireg[0x30] = (int)(time(NULL) ^ (long)0x55555555); - break; - - case 0xff4c: - checkString(r, 0x37, 0x31); - len = devFunc0016(sizeof pucbuf, pucbuf, r->ireg[0x37], r->preg[0x31].p, r->ireg[0x38], (int *)r->preg[0x32].p, r); - devFunc0006(r->ireg[0x31], r->ireg[0x32], r->ireg[0x33], r->ireg[0x34], r->ireg[0x35], loadColor(r, 0x36), len, pucbuf, r); - break; - - case 0xff4d: - // bitblt(mod, xsiz, ysiz, xscale, yscale, x0, y0, lineskip, inv, p_buf, typ0, p_table, typ1); - // mod: 0x20:use_table, 0x40:inv_is_visible & typ1_is_color - puc = r->preg[0x31].p; - mod3 = r->ireg[0x31] & 3; - dx = r->ireg[0x34]; - dy = r->ireg[0x35]; - if (dy == 0){ - dy = dx; - } - if (r->ireg[0x32] == -1) { - r->ireg[0x32] = mainWindow.xsize / dx; r->ireg[0x36] &= 0; - } - if (r->ireg[0x33] == -1) { - r->ireg[0x33] = mainWindow.ysize / dy; r->ireg[0x37] &= 0; - } - for (y = 0; y < r->ireg[0x33]; y++) { - y0 = y * dy + r->ireg[0x37]; - for (x = 0; x < r->ireg[0x32]; x++) { - x0 = x * dx + r->ireg[0x36]; - c = iColor1[*puc++]; - devFunc0004(mod3, x0, y0, x0 + dx, y0 + dy, c); - } - puc += r->ireg[0x38]; - } - break; - - default: - printf("devFunc: error: R30=%08X\n", r->ireg[0x30]); - exit(EXIT_FAILURE); - - } - return; -} - - - +#include "osecpu.h" + +extern unsigned char fontdata[]; // @fontdata.c + +const char *searchArg(int argc, const char **argv, const char *tag, int i) +{ + int j, l; + const char *r = NULL; + if (tag != NULL) { + l = (int)strlen(tag); + for (j = 1; j < argc; j++) { + if (strncmp(argv[j], tag, l) == 0) { + r = argv[j] + l; + if (i == 0){ + break; + } + i--; + } + } + } + else { + for (j = 1; j < argc; j++) { + if (strchr(argv[j], ':') == NULL) { + r = argv[j]; + if (i == 0){ + break; + } + i--; + } + } + } + if (i != 0){ + r = NULL; + } + return r; +} + +void devFunc0001(int len, unsigned char *puc, HOSECPU_RuntimeEnvironment *r) +{ + while (len > 0) { + putOsaskChar(*puc++, r); + len--; + } + return; +} + +void devFunc0006(int mod, int sx, int sy, int x, int y, int c, int len, unsigned char *puc, HOSECPU_RuntimeEnvironment *r) +{ + int xx; + int yy; + int i, ddx, ddy, j, ch, dx, dy; + + if (sy == 0){ + sy = sx; + } + xx = x + sx * 8; + yy = y + sy * 16; + if (xx <= 0 || xx > mainWindow.xsize || yy <= 0 || yy > mainWindow.ysize){ + (*(r->errHndl))(r); + } + if (x < 0 || x >= mainWindow.xsize || y < 0 || y >= mainWindow.ysize){ + (*(r->errHndl))(r); + } + + + if ((mod & 3) == 0 && sx == 1 && sy == 1) { + // メジャーケースを高速化. + for (i = 0; i < len; i++) { + ch = puc[i]; + if (0x10 <= ch && ch <= 0x1f) + ch = "0123456789ABCDEF"[ch & 0x0f]; + for (dy = 0; dy < 16; dy++) { + j = fontdata[(ch - ' ') * 16 + dy]; + for (dx = 0; dx < 8; dx++) { + if ((j & (0x80 >> dx)) != 0){ + mainWindow.vram[(x + dx) + (y + dy) * mainWindow.xsize] = c; + } + } + } + x += 8; + } + return; + } + for (i = 0; i < len; i++) { + ch = puc[i]; + if (0x10 <= ch && ch <= 0x1f) + ch = "0123456789ABCDEF"[ch & 0x0f]; + for (dy = 0; dy < 16; dy++) { + j = fontdata[(ch - ' ') * 16 + dy]; + for (ddy = 0; ddy < sy; ddy++) { + for (dx = 0; dx < 8; dx++) { + if ((j & (0x80 >> dx)) != 0) { + for (ddx = 0; ddx < sx; ddx++) { + switch (mod & 3) { + case 0: + mainWindow.vram[x + y * mainWindow.xsize] = c; + break; + case 1: + mainWindow.vram[x + y * mainWindow.xsize] |= c; + break; + case 2: + mainWindow.vram[x + y * mainWindow.xsize] ^= c; + break; + case 3: + mainWindow.vram[x + y * mainWindow.xsize] &= c; + break; + } + x++; + } + } else{ + x += sx; + } + } + x -= sx * 8; + y++; + } + } + x += sx * 8; + y -= sy * 16; + } + return; +} + +void devFunc0004(int mod, int x0, int y0, int x1, int y1, int c) +{ + int x, y; + if (mod == 0) { + for (y = y0; y <= y1; y++) { + for (x = x0; x <= x1; x++) { + mainWindow.vram[x + y * mainWindow.xsize] = c; + } + } + } + else { + for (y = y0; y <= y1; y++) { + for (x = x0; x <= x1; x++) { + switch (mod) { + case 1: + mainWindow.vram[x + y * mainWindow.xsize] |= c; + break; + case 2: + mainWindow.vram[x + y * mainWindow.xsize] ^= c; + break; + case 3: + mainWindow.vram[x + y * mainWindow.xsize] &= c; + break; + } + } + } + } + return; +} + +int devFunc0016(int buflen, unsigned char *buf, int plen, unsigned char *p, int qlen, int *q, HOSECPU_RuntimeEnvironment *r) +{ + int i = 0, base, j, k; + char sign; + + while (plen > 0) { + if (i >= buflen){ + (*(r->errHndl))(r); + } + if (*p != 0x01) { + buf[i++] = *p++; + plen--; + continue; + } + p++; + plen--; + if (qlen < 4){ + (*(r->errHndl))(r); + } + base = q[0]; + sign = 0; + if (base == 0){ + base = 16; + } +#if (REVISION == 1) + if (base == -3){ + base = 10; + } +#endif + if (base == -1){ + base = 10; + } + if (base < 0 || base > 16){ + (*(r->errHndl))(r); + } + if (q[1] + i > buflen){ + (*(r->errHndl))(r); + } + j = q[3]; + if ((q[2] & 4) == 0) { + // jは符号付き整数. + if ((q[2] & 8) != 0 && j > 0){ + sign = '+'; + } + if (j < 0) { + sign = '-'; j *= -1; + } + } else{ + // jは符号無し整数. + if ((q[2] & 8) != 0 && j != 0){ + sign = '+'; + } + } + for (k = q[1] - 1; k >= 0; k--) { + buf[i + k] = (j % base) + 0x10; + j = ((unsigned)j) / base; + } + k = 0; + if ((q[2] & 2) == 0 && j == 0) { + for (k = 0; k < q[1] - 1; k++) { + if (buf[i + k] != 0x10){ + break; + } + buf[i + k] = ' '; + } + } + if (sign != 0) { + if (k > 0){ + k--; + } + buf[i + k] = sign; + } + if ((q[2] & 1) != 0 && buf[i] == ' ') { + for (j = 0; k < q[1]; k++, j++){ + buf[i + j] = buf[i + k]; + } + i += j; + } else{ + i += q[1]; + } + qlen -= 4; + q += 4; + } + return i; +} + +void devFunc(HOSECPU_RuntimeEnvironment *r) +{ + FILE *fp; + int i, c; + int x, y, len, dx, dy; + unsigned char *puc; + unsigned char pucbuf[256]; + + //サイズを節約するためにEBPを128バイトずらしているのを元に戻す + r = (HOSECPU_RuntimeEnvironment *) (((char *)r) - 128); + + if (r->winClosed != 0){ + longjmp(*(r->setjmpEnv), 1); + } + if (0xff44 <= r->ireg[0x30] && r->ireg[0x30] <= 0xff48) { + if (mainWindow.vram == NULL) { + mainWindow.xsize = 640; + mainWindow.ysize = 480; + mainWindow.vram = malloc(640 * 480 * 4); + drv_openWin(640, 480, (void *)mainWindow.vram, &r->winClosed); + r->autoSleep = 1; + for (i = 640 * 480 - 1; i >= 0; i--){ + mainWindow.vram[i] = 0; + } + } + } + + switch (r->ireg[0x30]){ + case 0xff00: + printf("R31=%d(dec)\n", r->ireg[0x31]); + break; + + case 0xff01: + /* return: R30, P31 */ + if (r->buf0 == NULL){ + r->buf0 = malloc(1024 * 1024); + } + if (r->mainArgc <= r->ireg[0x31]) { + fprintf(stderr, "devFunc: error: R30=ff01: argc error: R31=%08X\n", r->ireg[0x31]); + exit(1); + } + fp = fopen(r->mainArgv[r->ireg[0x31]], "rb"); + if (fp == NULL) { + fprintf(stderr, "devFunc: error: R30=ff01: fopen error: '%s'\n", r->mainArgv[r->ireg[0x31]]); + exit(1); + } + i = (int)fread(r->buf0, 1, 1024 * 1024 - 4, fp); + if (i >= 1024 * 1024 - 4 || i < 0) { + fprintf(stderr, "devFunc: error: R30=ff01: fread error: '%s'\n", r->mainArgv[r->ireg[0x31]]); + exit(1); + } + fclose(fp); + r->preg[0x31].p = r->buf0; + r->preg[0x31].p0 = r->buf0; + r->preg[0x31].p1 = r->buf0 + i; + r->preg[0x31].typ = 3; // T_UINT8 + r->ireg[0x30] = i; + break; + + case 0xff02: + /* return: none */ + if (r->mainArgc <= r->ireg[0x31]) { + fprintf(stderr, "devFunc: error: R30=ff02: argc error: R31=%08X\n", r->ireg[0x31]); + exit(1); + } + fp = fopen(r->mainArgv[r->ireg[0x31]], "wb"); + if (fp == NULL) { + fprintf(stderr, "devFunc: error: R30=ff02: fopen error: '%s'\n", r->mainArgv[r->ireg[0x31]]); + exit(1); + } + if (r->ireg[0x32] >= 1024 * 1024 || r->ireg[0x32] < 0){ + fprintf(stderr, "devFunc: error: R30=ff02: fwrite error: R02=%08X\n", r->ireg[0x32]); + exit(1); + } + fwrite(r->preg[0x31].p, 1, r->ireg[0x32], fp); + fclose(fp); + break; + + case 0xff03: + /* return: P31 */ + if (r->buf1 == NULL){ + r->buf1 = malloc(1024 * 1024); + } + r->preg[0x31].p = r->buf1; + r->preg[0x31].p0 = r->buf1; + r->preg[0x31].p1 = r->buf1 + 1024 * 1024; + break; + + case 0xff04: + printf("P31.(p-p0)=%d(dec)\n", (int)(r->preg[0x31].p - r->preg[0x31].p0)); + break; + + case 0xff05: + fwrite(r->preg[0x31].p, 1, r->ireg[0x31], stdout); + break; + + case 0xff06: + // R31はリターンコード. + // これを反映すべきだが、現状は手抜きでいつも正常終了. + longjmp(*(r->setjmpEnv), 1); + break; + + case 0xff07: + // マシになった文字列表示.OSASK文字列に対応.offにすれば通常の文字列処理もできる.現状はonのみサポート. + checkString(r, 0x31, 0x31); + devFunc0001(r->ireg[0x31], r->preg[0x31].p, r); + break; + + case 0xff08: + // JITC on JITC + // R31: 言語(back-end, front-end, ... + // R32: level + // R33: debugInfo1 + checkString(r, 0x34, 0x31); + if (r->ireg[0x33] < 0 || r->ireg[0x33] > 15 || r->debugInfo1 > 15){ + (*(r->errHndl))(r); + } + for (i = 0; i < r->maxLabels; i++){ + r->label[i].opt = 0; + } + puc = r->preg[0x31].p; + i = jitCompiler(r->jitbuf, r->jitbuf1, puc, puc + r->ireg[0x34], puc, r->label, r->maxLabels, r->ireg[0x32], di1_serial, JITC_NOSTARTUP + 0); + if (i == 0) { + i = jitCompiler(r->jitbuf, r->jitbuf1, puc, puc + r->ireg[0x34], puc, r->label, r->maxLabels, r->ireg[0x32], di1_serial, JITC_NOSTARTUP + JITC_PHASE1 + 0); + if (i >= 0) { + r->mapDi1s[r->debugInfo1][r->ireg[0x33]] = di1_serial; + di1_serial++; + r->ireg[0x30] = 0; + r->preg[0x31].p = r->jitbuf; + r->preg[0x31].typ = 0; // TYP_CODE + r->preg[0x31].p0 = r->jitbuf; + r->preg[0x31].p1 = r->jitbuf + 1; + //int j; for (j = 0; j < i; j++) printf("%02X ", r->jitbuf[j]); putchar('\n'); + r->jitbuf += i; + static unsigned char ff08_ret[3] = { 0x1e, 0x3f, 0x30 }; + i = jitCompiler(r->jitbuf, r->jitbuf1, ff08_ret, ff08_ret + 3, puc, r->label, r->maxLabels, r->ireg[0x32], -1, JITC_NOSTARTUP + JITC_PHASE1 + 0); + r->jitbuf += i; + break; + } + } + r->ireg[0x30] = -1; + break; + + case 0xff09: + // たぶんbit7を使ったテキストはうまく処理できない(これはもはや仕様にしても問題ないかも). + checkString(r, 0x31, 0x31); + len = devFunc0016(sizeof pucbuf, pucbuf, r->ireg[0x31], r->preg[0x31].p, r->ireg[0x32], (int *)r->preg[0x32].p, r); + devFunc0001(len, pucbuf, r); + break; + + case 0xff40: + /* R31とR32でサイズを指定 */ + mainWindow.xsize = r->ireg[0x31]; + mainWindow.ysize = r->ireg[0x32]; + if (mainWindow.xsize <= 0 || mainWindow.ysize <= 0){ + (*(r->errHndl))(r); + } + r->preg[0x31].p = (void *)(mainWindow.vram = malloc(mainWindow.xsize * mainWindow.ysize * 4)); + r->preg[0x31].p0 = r->preg[0x31].p; + r->preg[0x31].p1 = r->preg[0x31].p + mainWindow.xsize * mainWindow.ysize * 4; + drv_openWin(r->ireg[0x31], r->ireg[0x32], r->preg[0x31].p, &r->winClosed); + // drv_flshWin(r->ireg[1], r->ireg[2], 0, 0); + r->autoSleep = 1; + for (i = mainWindow.xsize * mainWindow.ysize - 1; i >= 0; i--){ + mainWindow.vram[i] = 0; + } + break; + + case 0xff41: + /* R31とR32でサイズを指定、R33とR34でx0,y0指定 */ + if (r->ireg[0x31] == -1) { + r->ireg[0x31] = mainWindow.xsize; r->ireg[0x33] &= 0; + } + if (r->ireg[0x32] == -1) { + r->ireg[0x32] = mainWindow.ysize; r->ireg[0x34] &= 0; + } + checkRect(r, 0x31); + drv_flshWin(r->ireg[0x31], r->ireg[0x32], r->ireg[0x33], r->ireg[0x34]); + break; + + case 0xff42: + if (r->ireg[0x32] == -1) { + r->autoSleep = 1; + longjmp(*(r->setjmpEnv), 1); + } + if (r->ireg[0x32] < 0){ + (*(r->errHndl))(r); + } + r->autoSleep = 0; + if ((r->ireg[0x31] & 1) == 0 && mainWindow.vram != NULL){ + drv_flshWin(mainWindow.xsize, mainWindow.ysize, 0, 0); + } + for (;;) { + if (r->winClosed != 0){ + longjmp(*(r->setjmpEnv), 1); + } + drv_sleep(r->ireg[0x32]); + if ((r->ireg[0x31] & 2) != 0 && keybuf_c <= 0){ + continue; + } + break; + } + break; + + case 0xff43: + // 1:peek + // 2:stdin + // 4,8: ソース指定. + // 16: shift, lock系を有効化. + // 32: 左右のshift系を区別する. + if (r->ireg[0x31] == 2) { // なぜ3にしなかったのか... + r->ireg[0x30] = fgetc(stdin); + if (r->ireg[0x30] == EOF){ + r->ireg[0x30] = -1; + } + break; + } + r->ireg[0x30] |= -1; + if (keybuf_c > 0) { + r->ireg[0x30] = keybuf[keybuf_r]; + if ((r->ireg[0x31] & 16) == 0){ + r->ireg[0x30] &= 0x3e3effff; + } + if ((r->ireg[0x31] & 32) == 0){ + r->ireg[0x30] |= (r->ireg[0x30] >> 8) & 0xff0000; + } + if ((r->ireg[0x31] & 1) != 0) { + keybuf_c--; + keybuf_r = (keybuf_r + 1) & (KEYBUFSIZ - 1); + } + } + r->ireg[0x32] = r->ireg[0x33] = 0; + if (r->ireg[0x30] == 4132) r->ireg[0x32]--; + if (r->ireg[0x30] == 4133) r->ireg[0x33]--; + if (r->ireg[0x30] == 4134) r->ireg[0x32]++; + if (r->ireg[0x30] == 4135) r->ireg[0x33]++; + break; + + case 0xff44: + c = loadColor(r, 0x34); + if (r->ireg[0x32] < 0 || r->ireg[0x32] >= mainWindow.xsize || + r->ireg[0x33] < 0 || r->ireg[0x33] >= mainWindow.ysize){ + (*(r->errHndl))(r); + } + + switch ((r->ireg[0x31] & 3)) { + case 0: + mainWindow.vram[r->ireg[0x32] + r->ireg[0x33] * mainWindow.xsize] = c; + break; + case 1: + mainWindow.vram[r->ireg[0x32] + r->ireg[0x33] * mainWindow.xsize] |= c; + break; + case 2: + mainWindow.vram[r->ireg[0x32] + r->ireg[0x33] * mainWindow.xsize] ^= c; + break; + case 3: + mainWindow.vram[r->ireg[0x32] + r->ireg[0x33] * mainWindow.xsize] &= c; + break; + } + break; + + case 0xff45: + //drawLine + c = loadColor(r, 0x36); + if (r->ireg[0x32] < 0 || r->ireg[0x32] >= mainWindow.xsize || + r->ireg[0x33] < 0 || r->ireg[0x33] >= mainWindow.ysize){ + (*(r->errHndl))(r); + } + if (r->ireg[0x34] < 0 || r->ireg[0x34] >= mainWindow.xsize || + r->ireg[0x35] < 0 || r->ireg[0x35] >= mainWindow.ysize){ + (*(r->errHndl))(r); + } + dx = r->ireg[0x34] - r->ireg[0x32]; + dy = r->ireg[0x35] - r->ireg[0x33]; + x = r->ireg[0x32] << 10; + y = r->ireg[0x33] << 10; + if (dx < 0){ + dx = -dx; + } + if (dy < 0){ + dy = -dy; + } + if (dx >= dy) { + len = dx + 1; dx = 1024; + if (r->ireg[0x32] > r->ireg[0x34]){ + dx *= -1; + } + if (r->ireg[0x33] > r->ireg[0x35]){ + dy *= -1; + } + dy = (dy << 10) / len; + } else { + len = dy + 1; dy = 1024; + if (r->ireg[0x33] > r->ireg[0x35]){ + dy *= -1; + } + if (r->ireg[0x32] > r->ireg[0x34]){ + dx *= -1; + } + dx = (dx << 10) / len; + } + if ((r->ireg[0x31] & 3) == 0) { + for (i = 0; i < len; i++) { + mainWindow.vram[(x >> 10) + (y >> 10) * mainWindow.xsize] = c; + x += dx; + y += dy; + } + break; + } + for (i = 0; i < len; i++) { + // if ((r->ireg[0x31] & 3) == 0) vram[(x >> 10) + (y >> 10) * v_xsiz] = c; + switch ((r->ireg[0x31] & 3)) { + case 1: + mainWindow.vram[(x >> 10) + (y >> 10) * mainWindow.xsize] |= c; + break; + case 2: + mainWindow.vram[(x >> 10) + (y >> 10) * mainWindow.xsize] ^= c; + break; + case 3: + mainWindow.vram[(x >> 10) + (y >> 10) * mainWindow.xsize] &= c; + break; + default: + break; + } + x += dx; + y += dy; + } + break; + + case 0xff46: // fillRect(opt:R31, xsiz:R32, ysiz:R33, x0:R34, y0:R35, c:R36) + c = loadColor(r, 0x36); + if (r->ireg[0x32] == -1) { r->ireg[0x32] = mainWindow.xsize; r->ireg[0x34] &= 0; } + if (r->ireg[0x33] == -1) { r->ireg[0x33] = mainWindow.ysize; r->ireg[0x35] &= 0; } + checkRect(r, 0x32); + int mod3 = r->ireg[0x31] & 3, x0 = r->ireg[0x34], y0 = r->ireg[0x35], x1 = r->ireg[0x34] + r->ireg[0x32] - 1, y1 = r->ireg[0x35] + r->ireg[0x33] - 1; + if ((r->ireg[0x31] & 0x20) == 0) { + devFunc0004(mod3, x0, y0, x1, y1, c); + } else { // drawRect + devFunc0004(mod3, x0, y0, x1, y0, c); + devFunc0004(mod3, x0, y1, x1, y1, c); + devFunc0004(mod3, x0, y0, x0, y1, c); + devFunc0004(mod3, x1, y0, x1, y1, c); + } + break; + + case 0xff47: // fillOval(opt:R31, xsiz:R32, ysiz:R33, x0:R34, y0:R35, c:R36) + // これの計算精度はアーキテクチャに依存する. + c = loadColor(r, 0x36); + if (r->ireg[0x32] == -1) { + r->ireg[0x32] = mainWindow.xsize; r->ireg[0x34] &= 0; + } + if (r->ireg[0x33] == -1) { + r->ireg[0x33] = mainWindow.ysize; r->ireg[0x35] &= 0; + } + checkRect(r, 0x32); + double dcx = 0.5 * (r->ireg[0x32] - 1); + double dcy = 0.5 * (r->ireg[0x33] - 1); + double dcxy = (dcx + 0.5) * (dcy + 0.5) - 0.1; + dcxy *= dcxy; + mod3 = r->ireg[0x31] & 3; + x1 = r->ireg[0x32]; + y1 = r->ireg[0x33]; + if (mod3 == 0 && (r->ireg[0x31] & 0x20) == 0) { + for (y = 0; y < y1; y++) { + double dty = (y - dcy) * dcx; + for (x = 0; x < x1; x++) { + double dtx = (x - dcx) * dcy; + if (dtx * dtx + dty * dty > dcxy){ + continue; + } + mainWindow.vram[(x + r->ireg[0x34]) + (y + r->ireg[0x35]) * mainWindow.xsize] = c; + } + } + } else { +#define DRAWOVALPARAM 1 + double dcx1 = 0.5 * (r->ireg[0x32] - (1 + DRAWOVALPARAM * 2)); + double dcy1 = 0.5 * (r->ireg[0x33] - (1 + DRAWOVALPARAM * 2)); + double dcxy1 = (dcx1 + 0.5) * (dcy1 + 0.5) - 0.1; + dcxy1 *= dcxy1; + for (y = 0; y < y1; y++) { + double dty = (y - dcy) * dcx; + double dty1 = (y - dcy) * dcx1; + for (x = 0; x < x1; x++) { + double dtx = (x - dcx) * dcy; + double dtx1 = (x - dcx) * dcy1; + if (dtx * dtx + dty * dty > dcxy){ + continue; + } + if (DRAWOVALPARAM <= x && x < x1 - DRAWOVALPARAM && DRAWOVALPARAM <= y && y < y1 - DRAWOVALPARAM) { + if (dtx1 * dtx1 + dty1 * dty1 < dcxy1){ + continue; + } + } + switch (mod3) { + case 0: + mainWindow.vram[(x + r->ireg[0x34]) + (y + r->ireg[0x35]) * mainWindow.xsize] = c; + break; + case 1: + mainWindow.vram[(x + r->ireg[0x34]) + (y + r->ireg[0x35]) * mainWindow.xsize] |= c; + break; + case 2: + mainWindow.vram[(x + r->ireg[0x34]) + (y + r->ireg[0x35]) * mainWindow.xsize] ^= c; + break; + case 3: + mainWindow.vram[(x + r->ireg[0x34]) + (y + r->ireg[0x35]) * mainWindow.xsize] &= c; + break; + } + } + } + } + break; + + case 0xff48: // drawString(opt:R31, xsiz:R32, ysiz:R33, x0:R34, y0:R35, c:R36, s.len:R37, s.p:P31) + checkString(r, 0x37, 0x31); + devFunc0006(r->ireg[0x31], r->ireg[0x32], r->ireg[0x33], r->ireg[0x34], r->ireg[0x35], loadColor(r, 0x36), r->ireg[0x37], r->preg[0x31].p, r); + break; + + case 0xff49: + // **** junkApi_rand(i, max) **** + // 0 <= i <= maxとなるiを返す。 + // max==0のとき、iはSINT32全体を範囲とする乱数となる。 + r->ireg[0x30] = randGetNextUInt32(); + if (r->ireg[0x31] > 0){ + r->ireg[0x30] = (r->ireg[0x30] & 0x7fffffff) % (r->ireg[0x31] + 1); + } + break; + + case 0xff4a: /* seedの指定 */ + randStatInit(r->ireg[0x31]); + break; + + case 0xff4b: /* 適当なseedを提供 */ + r->ireg[0x30] = (int)(time(NULL) ^ (long)0x55555555); + break; + + case 0xff4c: + checkString(r, 0x37, 0x31); + len = devFunc0016(sizeof pucbuf, pucbuf, r->ireg[0x37], r->preg[0x31].p, r->ireg[0x38], (int *)r->preg[0x32].p, r); + devFunc0006(r->ireg[0x31], r->ireg[0x32], r->ireg[0x33], r->ireg[0x34], r->ireg[0x35], loadColor(r, 0x36), len, pucbuf, r); + break; + + case 0xff4d: + // bitblt(mod, xsiz, ysiz, xscale, yscale, x0, y0, lineskip, inv, p_buf, typ0, p_table, typ1); + // mod: 0x20:use_table, 0x40:inv_is_visible & typ1_is_color + puc = r->preg[0x31].p; + mod3 = r->ireg[0x31] & 3; + dx = r->ireg[0x34]; + dy = r->ireg[0x35]; + if (dy == 0){ + dy = dx; + } + if (r->ireg[0x32] == -1) { + r->ireg[0x32] = mainWindow.xsize / dx; r->ireg[0x36] &= 0; + } + if (r->ireg[0x33] == -1) { + r->ireg[0x33] = mainWindow.ysize / dy; r->ireg[0x37] &= 0; + } + for (y = 0; y < r->ireg[0x33]; y++) { + y0 = y * dy + r->ireg[0x37]; + for (x = 0; x < r->ireg[0x32]; x++) { + x0 = x * dx + r->ireg[0x36]; + c = iColor1[*puc++]; + devFunc0004(mod3, x0, y0, x0 + dx, y0 + dy, c); + } + puc += r->ireg[0x38]; + } + break; + + default: + printf("devFunc: error: R30=%08X\n", r->ireg[0x30]); + exit(EXIT_FAILURE); + + } + return; +} + + + diff --git a/jitc.c b/jitc.c index 8c7f2b7..ca621d5 100644 --- a/jitc.c +++ b/jitc.c @@ -1,69 +1,69 @@ -#include "osecpu.h" -#include "jitc.h" - -// -// JITC common functions (architecture not dependent) -// - -void errorHandler(HOSECPU_RuntimeEnvironment *r) -{ - puts("security error! abort..."); - printf("debugInfo0=%d, debugInfo1=%d\n", r->debugInfo0, r->debugInfo1); -#if (USE_DEBUGGER != 0) - dbgrMain(r); -#endif - exit(1); -} - -int jitCompCmdLen(const unsigned char *src) -{ - //BCode命令長を取得する - int i = 1; - - if (0x01 <= *src && *src < 0x04){ - // LB, LIMM, PLIMM - i = 6; - } else if (*src == 0x04){ - // CND - i = 2; - } else if (0x08 <= *src && *src < 0x0d){ - // LMEM, SMEM, ??, ??, ?? - i = 8 + src[7] * 4; - } else if (0x0e <= *src && *src < 0x10){ - // PADD, PDIF - i = 8; - } else if (0x10 <= *src && *src < 0x1c){ - // CP/OR, XOR, AND, ADD, SUB, MUL, SHL, SAR, DIV, MOD, - i = 4; - } else if (0x1c <= *src && *src < 0x1f){ - // ??, ??, PCP - i = 3; - } else if (*src == 0x1f){ - // ?? - i = 11; - } else if(0x20 <= *src && *src < 0x2e){ - // CMPE, CMPNE, CMPL, CMPGE, CMPLE, CMPG, TSTZ, TSTNZ, - // PCMPE, PCMPNE, PCMPL, PCMPGE, PCMPLE, PCMPG, - i = 4; - } else if (*src == 0x2f){ - // ?? - i = 4 + src[1]; - } else if (0x30 <= *src && *src < 0x34){ - // ??, ??, MALLOC, ?? - i = 4; - } else if (0x3c <= *src && *src < 0x3e){ - // ??, ?? - i = 7; - } else if (*src == 0xfe){ - // REMARK - i = 2 + src[1]; - } - - return i; -} - - - - - - +#include "osecpu.h" +#include "jitc.h" + +// +// JITC common functions (architecture not dependent) +// + +void errorHandler(HOSECPU_RuntimeEnvironment *r) +{ + puts("security error! abort..."); + printf("debugInfo0=%d, debugInfo1=%d\n", r->debugInfo0, r->debugInfo1); +#if (USE_DEBUGGER != 0) + dbgrMain(r); +#endif + exit(1); +} + +int jitCompCmdLen(const unsigned char *src) +{ + //BCode命令長を取得する + int i = 1; + + if (0x01 <= *src && *src < 0x04){ + // LB, LIMM, PLIMM + i = 6; + } else if (*src == 0x04){ + // CND + i = 2; + } else if (0x08 <= *src && *src < 0x0d){ + // LMEM, SMEM, ??, ??, ?? + i = 8 + src[7] * 4; + } else if (0x0e <= *src && *src < 0x10){ + // PADD, PDIF + i = 8; + } else if (0x10 <= *src && *src < 0x1c){ + // CP/OR, XOR, AND, ADD, SUB, MUL, SHL, SAR, DIV, MOD, + i = 4; + } else if (0x1c <= *src && *src < 0x1f){ + // ??, ??, PCP + i = 3; + } else if (*src == 0x1f){ + // ?? + i = 11; + } else if(0x20 <= *src && *src < 0x2e){ + // CMPE, CMPNE, CMPL, CMPGE, CMPLE, CMPG, TSTZ, TSTNZ, + // PCMPE, PCMPNE, PCMPL, PCMPGE, PCMPLE, PCMPG, + i = 4; + } else if (*src == 0x2f){ + // ?? + i = 4 + src[1]; + } else if (0x30 <= *src && *src < 0x34){ + // ??, ??, MALLOC, ?? + i = 4; + } else if (0x3c <= *src && *src < 0x3e){ + // ??, ?? + i = 7; + } else if (*src == 0xfe){ + // REMARK + i = 2 + src[1]; + } + + return i; +} + + + + + + diff --git a/jitc.h b/jitc.h index 8da198b..102950c 100644 --- a/jitc.h +++ b/jitc.h @@ -1,118 +1,118 @@ - -#ifndef HeavyOSECPU_jitc_h -#define HeavyOSECPU_jitc_h - -// Error flags -#define JITC_ERR_MASK 255 -#define JITC_ERR_PHASE0ONLY 256 -#define JITC_ERR_REGNUM (1 | JITC_ERR_PHASE0ONLY) -#define JITC_ERR_DST1 (2 | JITC_ERR_PHASE0ONLY) -#define JITC_ERR_OPECODE (3 | JITC_ERR_PHASE0ONLY) -#define JITC_ERR_LABELNUM (4 | JITC_ERR_PHASE0ONLY) -#define JITC_ERR_LABELREDEF (5 | JITC_ERR_PHASE0ONLY) -#define JITC_ERR_PREFIX (6 | JITC_ERR_PHASE0ONLY) -#define JITC_ERR_LABELNODEF 7 -#define JITC_ERR_LABELTYP 8 -#define JITC_ERR_IDIOM 9 -#define JITC_ERR_PREGNUM (10 | JITC_ERR_PHASE0ONLY) -#define JITC_ERR_SRC1 (11 | JITC_ERR_PHASE0ONLY) -#define JITC_ERR_BADTYPE (12 | JITC_ERR_PHASE0ONLY) -#define JITC_ERR_PREFIXFAR (13 | JITC_ERR_PHASE0ONLY) -#define JITC_ERR_INTERNAL 99 - -// Byte operations -#define jitCompPutByte1(p, c0) *p++ = c0 -#define jitCompPutByte2(p, c0, c1) *p++ = c0; *p++ = c1 -#define jitCompPutByte3(p, c0, c1, c2) *p++ = c0; *p++ = c1; *p++ = c2 -#define jitCompPutByte4(p, c0, c1, c2, c3) *p++ = c0; *p++ = c1; *p++ = c2; *p++ = c3 - -// -// functions (jitc internal) -// - -// @jitc.c -void errorHandler(HOSECPU_RuntimeEnvironment *r); -int jitCompCmdLen(const unsigned char *src); - -// @jitcx86.c -#if (JITC_ARCNUM == 0x0001) -// -// for x86-32bit -// - -// 他のCPUへ移植する人へ: -// 以下の定数は最適化のためのものなので、すべて0として簡単に移植しても問題ありません -#define jitCompA0001_USE_R3F_CMPJMP 1*1 -#define jitCompA0001_USE_R3F_IMM32 1*1 -#define jitCompA0001_USE_R3F_IMM8 1*1 -#define jitCompA0001_USE_R3F_INCDEC 1*1 -#define jitCompA0001_OPTIMIZE_JMP 1*1 -#define jitCompA0001_OPTIMIZE_MOV 1*1 /* 1にすると速度低下する? */ -#define jitCompA0001_OPTIMIZE_CMP 1*1 -#define jitCompA0001_OPTIMIZE_ALIGN 4*1 /* 0-8を想定 */ -#define jitCompA0001_EBP128 128*1 - -struct JitCompWork { - unsigned char *dst, *dst0; - int err, maxLabels; -#if (jitCompA0001_USE_R3F_IMM32 != 0) - int r3f; -#endif - char prefix; //CND命令の値を記録(初期値=0) -}; - -void jitCompPutImm32(struct JitCompWork *w, int i); -int jitCompGetImm32(const unsigned char *src); -int jitCompGetLabelNum(struct JitCompWork *w, const unsigned char *src); -void jitCompA0001_85DispN(struct JitCompWork *w, int disp, int n); -void jitCompA0001_movEbpDispReg32(struct JitCompWork *w, int disp, int reg32); -void jitCompA0001_movReg32EbpDisp(struct JitCompWork *w, int reg32, int disp); -void jitCompA0001_movEaxRxx(struct JitCompWork *w, int rxx); -void jitCompA0001_movRxxEax(struct JitCompWork *w, int rxx); -void jitCompA0001_fixPrefix(struct JitCompWork *w); -void jitCompA0001_checkCompPtr(struct JitCompWork *w, int p0, int p1); -void jitCompA000_loadRegCacheAll(struct JitCompWork *w); -void jitCompA000_storeRegCacheAll(struct JitCompWork *w); -void jitCompA000_loadRegCacheEcx(struct JitCompWork *w); -void jitCompA000_storeRegCacheEcx(struct JitCompWork *w); -void jitCompA000_loadRegCacheEdx(struct JitCompWork *w); -void jitCompA000_storeRegCacheEdx(struct JitCompWork *w); -int jitCompA000_selectRegCache(int rxx, int reg); -void jitCompA000_loadPRegCacheAll(struct JitCompWork *w); -void jitCompA000_storePRegCacheAll(struct JitCompWork *w); -int jitCompA000_selectPRegCache(int pxx, int reg); -int jitCompA000_convTyp(int t); -int jitCompA000_dataWidth(int t); -void jitCompA0001_checkType0(struct JitCompWork *w, int pxx, int typ, int ac); -void jitCompA0001_checkType(struct JitCompWork *w, int pxx, int typ, int ac); -void jitCompA0001_checkLimit(struct JitCompWork *w, int reg, int pxx); -int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *src, const unsigned char *src1, const unsigned char *src0, HOSECPU_LabelListTag *label, int maxLabels, int level, int debugInfo1, int flags); -unsigned char *jitCompCallFunc(unsigned char *dst, void *func); -unsigned char *jitCompInit(unsigned char *dst); -void func3c(char *ebp, int opt, int r1, int p1, int lenR, int lenP, int r0, int p0); -void func3d(char *ebp, int opt, int r1, int p1, int lenR, int lenP, int r0, int p0); -void funcf4(char *ebp, int pxx, int typ, int len); -void funcf5(char *ebp, int pxx, int typ, int len); -void funcf6(char *ebp, int pxx, int typ, int len); -void funcf7(char *ebp, int pxx, int typ, int len); -void errHndl(HOSECPU_RuntimeEnvironment *r); -int jitc0(unsigned char **qq, unsigned char *q1, const unsigned char *p0, const unsigned char *p1, int level, HOSECPU_LabelListTag *label); -#if (USE_DEBUGGER != 0) -int dbgrGetRegNum(const char *p); -void dbgrMain(HOSECPU_RuntimeEnvironment *r); -#endif - - - - - - - - - - - - -#endif - -#endif + +#ifndef HeavyOSECPU_jitc_h +#define HeavyOSECPU_jitc_h + +// Error flags +#define JITC_ERR_MASK 255 +#define JITC_ERR_PHASE0ONLY 256 +#define JITC_ERR_REGNUM (1 | JITC_ERR_PHASE0ONLY) +#define JITC_ERR_DST1 (2 | JITC_ERR_PHASE0ONLY) +#define JITC_ERR_OPECODE (3 | JITC_ERR_PHASE0ONLY) +#define JITC_ERR_LABELNUM (4 | JITC_ERR_PHASE0ONLY) +#define JITC_ERR_LABELREDEF (5 | JITC_ERR_PHASE0ONLY) +#define JITC_ERR_PREFIX (6 | JITC_ERR_PHASE0ONLY) +#define JITC_ERR_LABELNODEF 7 +#define JITC_ERR_LABELTYP 8 +#define JITC_ERR_IDIOM 9 +#define JITC_ERR_PREGNUM (10 | JITC_ERR_PHASE0ONLY) +#define JITC_ERR_SRC1 (11 | JITC_ERR_PHASE0ONLY) +#define JITC_ERR_BADTYPE (12 | JITC_ERR_PHASE0ONLY) +#define JITC_ERR_PREFIXFAR (13 | JITC_ERR_PHASE0ONLY) +#define JITC_ERR_INTERNAL 99 + +// Byte operations +#define jitCompPutByte1(p, c0) *p++ = c0 +#define jitCompPutByte2(p, c0, c1) *p++ = c0; *p++ = c1 +#define jitCompPutByte3(p, c0, c1, c2) *p++ = c0; *p++ = c1; *p++ = c2 +#define jitCompPutByte4(p, c0, c1, c2, c3) *p++ = c0; *p++ = c1; *p++ = c2; *p++ = c3 + +// +// functions (jitc internal) +// + +// @jitc.c +void errorHandler(HOSECPU_RuntimeEnvironment *r); +int jitCompCmdLen(const unsigned char *src); + +// @jitcx86.c +#if (JITC_ARCNUM == 0x0001) +// +// for x86-32bit +// + +// 他のCPUへ移植する人へ: +// 以下の定数は最適化のためのものなので、すべて0として簡単に移植しても問題ありません +#define jitCompA0001_USE_R3F_CMPJMP 1*1 +#define jitCompA0001_USE_R3F_IMM32 1*1 +#define jitCompA0001_USE_R3F_IMM8 1*1 +#define jitCompA0001_USE_R3F_INCDEC 1*1 +#define jitCompA0001_OPTIMIZE_JMP 1*1 +#define jitCompA0001_OPTIMIZE_MOV 1*1 /* 1にすると速度低下する? */ +#define jitCompA0001_OPTIMIZE_CMP 1*1 +#define jitCompA0001_OPTIMIZE_ALIGN 4*1 /* 0-8を想定 */ +#define jitCompA0001_EBP128 128*1 + +struct JitCompWork { + unsigned char *dst, *dst0; + int err, maxLabels; +#if (jitCompA0001_USE_R3F_IMM32 != 0) + int r3f; +#endif + char prefix; //CND命令の値を記録(初期値=0) +}; + +void jitCompPutImm32(struct JitCompWork *w, int i); +int jitCompGetImm32(const unsigned char *src); +int jitCompGetLabelNum(struct JitCompWork *w, const unsigned char *src); +void jitCompA0001_85DispN(struct JitCompWork *w, int disp, int n); +void jitCompA0001_movEbpDispReg32(struct JitCompWork *w, int disp, int reg32); +void jitCompA0001_movReg32EbpDisp(struct JitCompWork *w, int reg32, int disp); +void jitCompA0001_movEaxRxx(struct JitCompWork *w, int rxx); +void jitCompA0001_movRxxEax(struct JitCompWork *w, int rxx); +void jitCompA0001_fixPrefix(struct JitCompWork *w); +void jitCompA0001_checkCompPtr(struct JitCompWork *w, int p0, int p1); +void jitCompA000_loadRegCacheAll(struct JitCompWork *w); +void jitCompA000_storeRegCacheAll(struct JitCompWork *w); +void jitCompA000_loadRegCacheEcx(struct JitCompWork *w); +void jitCompA000_storeRegCacheEcx(struct JitCompWork *w); +void jitCompA000_loadRegCacheEdx(struct JitCompWork *w); +void jitCompA000_storeRegCacheEdx(struct JitCompWork *w); +int jitCompA000_selectRegCache(int rxx, int reg); +void jitCompA000_loadPRegCacheAll(struct JitCompWork *w); +void jitCompA000_storePRegCacheAll(struct JitCompWork *w); +int jitCompA000_selectPRegCache(int pxx, int reg); +int jitCompA000_convTyp(int t); +int jitCompA000_dataWidth(int t); +void jitCompA0001_checkType0(struct JitCompWork *w, int pxx, int typ, int ac); +void jitCompA0001_checkType(struct JitCompWork *w, int pxx, int typ, int ac); +void jitCompA0001_checkLimit(struct JitCompWork *w, int reg, int pxx); +int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *src, const unsigned char *src1, const unsigned char *src0, HOSECPU_LabelListTag *label, int maxLabels, int level, int debugInfo1, int flags); +unsigned char *jitCompCallFunc(unsigned char *dst, void *func); +unsigned char *jitCompInit(unsigned char *dst); +void func3c(char *ebp, int opt, int r1, int p1, int lenR, int lenP, int r0, int p0); +void func3d(char *ebp, int opt, int r1, int p1, int lenR, int lenP, int r0, int p0); +void funcf4(char *ebp, int pxx, int typ, int len); +void funcf5(char *ebp, int pxx, int typ, int len); +void funcf6(char *ebp, int pxx, int typ, int len); +void funcf7(char *ebp, int pxx, int typ, int len); +void errHndl(HOSECPU_RuntimeEnvironment *r); +int jitc0(unsigned char **qq, unsigned char *q1, const unsigned char *p0, const unsigned char *p1, int level, HOSECPU_LabelListTag *label); +#if (USE_DEBUGGER != 0) +int dbgrGetRegNum(const char *p); +void dbgrMain(HOSECPU_RuntimeEnvironment *r); +#endif + + + + + + + + + + + + +#endif + +#endif diff --git a/jitcx86.c b/jitcx86.c index 6d73552..aa29a5c 100644 --- a/jitcx86.c +++ b/jitcx86.c @@ -1,1711 +1,1711 @@ -#include "osecpu.h" -#include "jitc.h" - -#if (JITC_ARCNUM == 0x0001) -// -// for x86-32bit -// - -void jitCompPutImm32(struct JitCompWork *w, int i) -{ - jitCompPutByte1(w->dst, i & 0xff); - jitCompPutByte1(w->dst, (i >> 8) & 0xff); - jitCompPutByte1(w->dst, (i >> 16) & 0xff); - jitCompPutByte1(w->dst, (i >> 24) & 0xff); - return; -} - -int jitCompGetImm32(const unsigned char *src) -{ - return (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; -} - -int jitCompGetLabelNum(struct JitCompWork *w, const unsigned char *src) -{ - int i = jitCompGetImm32(src); - if (i < 0 || i >= w->maxLabels) { - w->err = JITC_ERR_LABELNUM; - i = 0; - } - return i; -} - -void jitCompA0001_85DispN(struct JitCompWork *w, int disp, int n) -{ - disp -= jitCompA0001_EBP128; - if (-128 <= disp && disp <= 127) { - jitCompPutByte2(w->dst, 0x45 | (n << 3), disp & 0xff); - } else { - jitCompPutByte1(w->dst, 0x85 | (n << 3)); - jitCompPutImm32(w, disp); - } - return; -} - -void jitCompA0001_movEbpDispReg32(struct JitCompWork *w, int disp, int reg32) -{ - jitCompPutByte1(w->dst, 0x89); /* MOV(mem, reg32); */ - jitCompA0001_85DispN(w, disp, reg32); - return; -} - -void jitCompA0001_movReg32EbpDisp(struct JitCompWork *w, int reg32, int disp) -{ - jitCompPutByte1(w->dst, 0x8b); /* MOV(reg32, mem); */ - jitCompA0001_85DispN(w, disp, reg32); - return; -} - -void jitCompA0001_movEaxRxx(struct JitCompWork *w, int rxx) -{ -#if (jitCompA0001_USE_R3F_IMM32 != 0) - if (rxx == 0x3f) { - jitCompPutByte1(w->dst, 0xb8); /* MOV(EAX, ?); */ - jitCompPutImm32(w, w->r3f); - return; - } -#endif - if (rxx >= 0x40 || rxx < 0){ - w->err = JITC_ERR_REGNUM; - } - jitCompA0001_movReg32EbpDisp(w, 0 /* EAX */, rxx * 4); /* MOV(EAX, [EBP+?]); */ - return; -} - -void jitCompA0001_movRxxEax(struct JitCompWork *w, int rxx) -{ - if (rxx >= 0x40 || rxx < 0){ - w->err = JITC_ERR_REGNUM; - } - jitCompA0001_movEbpDispReg32(w, rxx * 4, 0 /* EAX */); /* MOV([EBP+?], EAX); */ - return; -} - -void jitCompA0001_fixPrefix(struct JitCompWork *w) -{ - if (w->prefix != 0) { - if (w->dst - w->dst0 > 127){ - w->err = JITC_ERR_REGNUM; - } - w->dst0[-1] = (unsigned char)((w->dst - w->dst0) & 0xff); - } - return; -} - -void jitCompA0001_checkCompPtr(struct JitCompWork *w, int p0, int p1) -{ - if (p0 >= 0x3f || p0 < 0){ - w->err = JITC_ERR_PREGNUM; - } - if (p1 >= 0x3f || p1 < 0){ - w->err = JITC_ERR_PREGNUM; - } - /* 比較可能可能なのかのチェックのコードを出力 */ /* 未完成 */ - return; -} - -void jitCompA000_loadRegCacheAll(struct JitCompWork *w) -{ - jitCompA0001_movReg32EbpDisp(w, 3 /* EBX */, 0 * 4); /* EBX = R00; */ - jitCompA0001_movReg32EbpDisp(w, 1 /* ECX */, 1 * 4); /* ECX = R01; */ - jitCompA0001_movReg32EbpDisp(w, 2 /* EDX */, 2 * 4); /* EDX = R02; */ - return; -} - -void jitCompA000_storeRegCacheAll(struct JitCompWork *w) -{ - jitCompA0001_movEbpDispReg32(w, 0 * 4, 3 /* EBX */); /* R00 = EBX; */ - jitCompA0001_movEbpDispReg32(w, 1 * 4, 1 /* ECX */); /* R01 = ECX; */ - jitCompA0001_movEbpDispReg32(w, 2 * 4, 2 /* EDX */); /* R02 = EDX; */ - return; -} - -void jitCompA000_loadRegCacheEcx(struct JitCompWork *w) -{ - jitCompA0001_movReg32EbpDisp(w, 1 /* ECX */, 1 * 4); /* ECX = R01; */ - return; -} - -void jitCompA000_storeRegCacheEcx(struct JitCompWork *w) -{ - jitCompA0001_movEbpDispReg32(w, 1 * 4, 1 /* ECX */); /* R01 = ECX; */ - return; -} - -void jitCompA000_loadRegCacheEdx(struct JitCompWork *w) -{ - jitCompA0001_movReg32EbpDisp(w, 2 /* EDX */, 2 * 4); /* EDX = R02; */ - return; -} - -void jitCompA000_storeRegCacheEdx(struct JitCompWork *w) -{ - jitCompA0001_movEbpDispReg32(w, 2 * 4, 2 /* EDX */); /* R02 = EDX; */ - return; -} - -int jitCompA000_selectRegCache(int rxx, int reg) -{ - switch (rxx) { - case 0: - //EBX - reg = 3; - break; - case 1: - //ECX - reg = 1; - break; - case 2: - //EDX - reg = 2; - break; - } - return reg; -} - -void jitCompA000_loadPRegCacheAll(struct JitCompWork *w) -{ - // jitCompA0001_movReg32EbpDisp(w, 5 /* EBP */, 256 + 0 * 32 + 0); /* EBP = P00; */ - jitCompA0001_movReg32EbpDisp(w, 6 /* ESI */, 256 + 1 * 32 + 0); /* ESI = P01; */ - jitCompA0001_movReg32EbpDisp(w, 7 /* EDI */, 256 + 2 * 32 + 0); /* EDI = P02; */ - return; -} - -void jitCompA000_storePRegCacheAll(struct JitCompWork *w) -{ - // jitCompA0001_movEbpDispReg32(w, 256 + 0 * 32 + 0, 5 /* EBP */); /* P00 = EBP; */ - jitCompA0001_movEbpDispReg32(w, 256 + 1 * 32 + 0, 6 /* ESI */); /* P01 = ESI; */ - jitCompA0001_movEbpDispReg32(w, 256 + 2 * 32 + 0, 7 /* EDI */); /* P02 = EDI; */ - return; -} - -int jitCompA000_selectPRegCache(int pxx, int reg) -{ - // if (pxx == 0) reg = 5; /* EBP */ - switch (pxx) { - case 1: - //ESI - reg = 6; - break; - - case 2: - //EDI - reg = 7; - break; - } - return reg; -} - -int jitCompA000_convTyp(int t) -{ - int r = -1; - - if (1 <= t && t <= 7){ - r = t; - } else if (8 <= t && t <= 13){ - r = 2 | (t & 1); - } else if (14 <= t && t <= 15){ - r = 4 | (t & 1); - } else if (16 <= t && t <= 21){ - r = 6 | (t & 1); - } - return r; -} - -int jitCompA000_dataWidth(int t) -{ - int r = -1; - if (t == 0x0001) r = 256; - t >>= 1; - if (t == 0x0002 / 2) r = 8; - if (t == 0x0004 / 2) r = 16; - if (t == 0x0006 / 2) r = 32; - if (t == 0x0008 / 2) r = 4; - if (t == 0x000a / 2) r = 2; - if (t == 0x000c / 2) r = 1; - if (t == 0x000e / 2) r = 12; - if (t == 0x0010 / 2) r = 20; - if (t == 0x0012 / 2) r = 24; - if (t == 0x0014 / 2) r = 28; - return r; -} - -static unsigned char *errfnc; - -void jitCompA0001_checkType0(struct JitCompWork *w, int pxx, int typ, int ac) -{ - if (typ <= 0) { w->err = JITC_ERR_BADTYPE; } - if (typ > 0x7f) { w->err = JITC_ERR_INTERNAL; } - jitCompA0001_movReg32EbpDisp(w, 0 /* EAX */, 256 + pxx * 32 + 4); /* MOV(EAX, [EBP+?]); */ /* typ */ - jitCompPutByte3(w->dst, 0x83, 0xf8, typ & 0x7f); /* CMP(EAX, ?); */ - jitCompPutByte2(w->dst, 0x0f, 0x85); /* JNE */ - jitCompPutImm32(w, errfnc - (w->dst + 4)); - return; -} - -void jitCompA0001_checkType(struct JitCompWork *w, int pxx, int typ, int ac) -// data用. -// 将来的にはaliveやアクセス権チェックも入れる -{ - jitCompA0001_checkType0(w, pxx, typ, ac); - return; -} - -void jitCompA0001_checkLimit(struct JitCompWork *w, int reg, int pxx) -{ - jitCompPutByte1(w->dst, 0x3b); /* CMP(reg, [EBP+?]); */ - jitCompA0001_85DispN(w, 256 + pxx * 32 + 8, reg); /* p0 */ - jitCompPutByte2(w->dst, 0x0f, 0x82); /* JB */ - jitCompPutImm32(w, errfnc - (w->dst + 4)); - jitCompPutByte1(w->dst, 0x3b); /* CMP(reg, [EBP+?]); */ - jitCompA0001_85DispN(w, 256 + pxx * 32 + 12, reg); /* p1 */ - jitCompPutByte2(w->dst, 0x0f, 0x83); /* JAE */ - jitCompPutImm32(w, errfnc - (w->dst + 4)); - return; -} - -// F5の場合、decoderが対応するalloc-freeを結びつけるのが簡単で、typやlenを指定必須にしてもフロントエンドコードに影響はない. -int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *src, const unsigned char *src1, const unsigned char *src0, HOSECPU_LabelListTag *label, int maxLabels, int level, int debugInfo1, int flags) -{ - // For IA-32 (x86, 32-bit) - // 本来ならこのレイヤでは文法チェックしない - // - // dst : 現在の書き込みアドレス。 - // dst1 : 書き込みアドレスの最大値 - // src : 現在の読み込みアドレス(ヘッダ部は飛ばしてある - // src1 : 読み込みアドレスの最大値 - // src0 : 読み込みバイナリのアドレス - struct JitCompWork w; - unsigned char *dst00 = dst, *enter0 = NULL, *tmp_ucp; - char *errmsg = ""; - const unsigned char *oldsrc; - int timecount = 0, i, j = 0, lastlabel = -1, debugInfo0 = -1; - int reg0, reg1, reg2, cmp0reg = -1, cmp0lev = 0; - w.dst = w.dst0 = dst; - w.err = 0; - w.maxLabels = maxLabels; - - if ((flags & JITC_NOSTARTUP) == 0) { - jitCompPutByte1(w.dst, 0x60); /* PUSHAD(); */ - jitCompA000_loadRegCacheAll(&w); /* start-up */ - jitCompA000_loadPRegCacheAll(&w); - } - if (level <= JITC_LV_SLOWER) { - jitCompPutByte2(w.dst, 0x31, 0xc0); /* XOR(EAX, EAX); */ - jitCompA0001_movEbpDispReg32(&w, 2304 + 0, 0 /* EAX */); /* MOV(debugInfo0, EAX); */ - jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, ?); */ - jitCompPutImm32(&w, debugInfo1); - jitCompA0001_movEbpDispReg32(&w, 2304 + 4, 0 /* EAX */); /* MOV(debugInfo1, EAX); */ - } - while (src < src1) { - w.prefix = 0; //0x04 CND 命令で変更される - if (w.dst + 256 > dst1) { w.err = JITC_ERR_DST1; goto err_w; } // 書き込み領域が残り256バイト未満ならエラー - timecount++; - if (timecount >= 64) { - timecount -= 64; - /* 未完成(timeoutチェックコードを入れる) */ - } - prefix_continue: // CND命令実行後ここに戻る - switch (*src) { - - case 0x00: /* NOP */ - if (w.prefix != 0) { w.err = JITC_ERR_PREFIX; goto err_w; } // 「条件付きでNOPを実行」するなんて、矛盾している! - break; - - case 0x01: /* LB */ - - /* - * LB : ラベル設置命令。(6byte) - * ・prefex = 1にする - * ・timecount++し、timecountのチェックをする。 - * ・ラベル位置を登録する。 - * ・割り込みがある場合、このタイミングで割り込みを発生させる。 - * - * 1 2 3 456 - * LB 01 opt imm32 - * - */ - - if (enter0 == NULL && (src[6] == 0x3c /* 多数のレジスタをスタックに退避 */ || (src[6] == 0xfe/* REMARK */ && src[7] == 0x01 && src[9] == 0x3c))) { //beginFunc()中のLB - // LB命令の後に0x3C命令・・・beginFunc() - jitCompPutByte1(w.dst, 0xe9); // (x86) JMP rel32 : 次の命令との相対オフセットだけ相対ニアジャンプする - enter0 = w.dst; - jitCompPutImm32(&w, 0); // 飛び相対座標が0 ・・・パイプラインのフラッシュ?? - } - if (src[6] == 0x34) { // LBの次の命令がDATA ・・・DAT_SA0(label, typ32, length) ・・・メモリ確保命令 - tmp_ucp = w.dst; - jitCompPutByte1(w.dst, 0xe9); // (x86) JMP rel32 : 次の命令との相対オフセットだけ相対ニアジャンプする - i = jitCompGetImm32(&src[7]); // type32 を取得 - j = 32; - if (i != 1) { - i = jitCompA000_convTyp(i); - j = 0; - if (i == 2 || i == 3) { j = 1; } - if (i == 4 || i == 5) { j = 2; } - if (i == 6 || i == 7) { j = 4; } - } - j *= jitCompGetImm32(&src[11]); - if (j <= 0) w.err = JITC_ERR_BADTYPE; - jitCompPutImm32(&w, j); -#if (jitCompA0001_OPTIMIZE_JMP != 0) - if (j <= 127 - jitCompA0001_OPTIMIZE_ALIGN) { - w.dst -= 5; - jitCompPutByte2(w.dst, 0xeb, j); - } -#endif - } -#if (jitCompA0001_OPTIMIZE_ALIGN != 0) - for (;;) { - i = ((int)w.dst) & (jitCompA0001_OPTIMIZE_ALIGN - 1); /* ALIGNで割ったあまりを計算 */ - if (i == 0) break; - i = jitCompA0001_OPTIMIZE_ALIGN - i; - if (i == 1) { jitCompPutByte1(w.dst, 0x90); j += i; } /* NOP(); */ - if (i == 2) { jitCompPutByte2(w.dst, 0x89, 0xc0); j += i; } /* MOV(EAX, EAX); */ - if (i == 3) { jitCompPutByte3(w.dst, 0x8d, 0x76, 0x00); j += i; } /* LEA(ESI, [ESI+0]); */ - if (i == 4) { jitCompPutByte4(w.dst, 0x8d, 0x74, 0x26, 0x00); j += i; } /* LEA(ESI, [ESI*1+0]); */ - if (i == 5) { jitCompPutByte1(w.dst, 0x0d); jitCompPutImm32(&w, 0); j += i; } /* OR(EAX, 0); */ - if (i == 6) { jitCompPutByte2(w.dst, 0x8d, 0xb6); jitCompPutImm32(&w, 0); j += i; } /* LEA(ESI, [ESI+0]); */ - if (i >= 7) { jitCompPutByte3(w.dst, 0x8d, 0xb4, 0x26); jitCompPutImm32(&w, 0); j += 7; } /* LEA(ESI, [ESI*1+0]); */ - } -#endif - if (src[6] == 0x34) { - tmp_ucp[1] = j & 0xff; - if (*tmp_ucp == 0xe9) { - tmp_ucp[2] = (j >> 8) & 0xff; - tmp_ucp[3] = (j >> 16) & 0xff; - tmp_ucp[4] = (j >> 24) & 0xff; - } - } - if ((flags & JITC_PHASE1) == 0) { - i = jitCompGetLabelNum(&w, src + 2); - //printf("i=%06X %06X\n", i, src-src0); - if (label[i].opt != 0 && w.err == 0) { w.err = JITC_ERR_LABELREDEF; goto err_w; } - if (w.prefix != 0) { w.err = JITC_ERR_PREFIX; goto err_w; } - label[i].opt = src[1] + 1; - label[i].typ = 0; /* TYP_CODE */ - label[i].p = w.dst; - label[i].p1 = w.dst + 1; - lastlabel = i; - } - cmp0reg = -1; - timecount = 0; - /* 未完成(timeoutチェックコードを入れる) */ - break; - - case 0x02: /* LIMM */ - - /* - * LIMM : 定数即値代入命令(6byte) - * - * 1 2 3456 - * 02 reg0R imm32 - * - * ・reg3F は条件比較慣用句指定用&演算命令即値慣用句指定用。よってCND命令の直後では使用できない。 - */ - - if (src[1] == 0x3f && w.prefix != 0) w.err = JITC_ERR_PREFIX; // CND命令の直後でR3Fを書き換えるなんて変だよね - -#if (jitCompA0001_USE_R3F_IMM32 != 0) - if (src[1] == 0x3f) { // R3Fへの代入は例外敵に、 w.r3f を使用 - w.r3f = jitCompGetImm32(src + 2); - break; - } -#endif - i = jitCompGetImm32(src + 2); // 与えられた即値(第二引数)を取得 - - /* R00-R02 なら EBX, ECX, EDX 、それ以外なら EAX のレジスタIDを reg0 に代入 */ - reg0 = jitCompA000_selectRegCache(src[1], 0 /* EAX */); - -#if (jitCompA0001_OPTIMIZE_MOV != 0) - if (i == 0) { - jitCompPutByte2(w.dst, 0x31, 0xc0 | reg0 << 3 | reg0); /* XOR(reg0, reg0); */ - jitCompA0001_movRxxEax(&w, src[1]); - break; - } -#endif - - /* reg0 のレジスタに対応したMOV命令を発行 */ - jitCompPutByte1(w.dst, 0xb8 | reg0); /* MOV(reg0, ?); == 10111000b+wr imm32 */ - jitCompPutImm32(&w, i); - - if (reg0 == 0) // R03以降の、レジスタの内容をメモリ上に格納してエミュレートする場合 - - jitCompA0001_movRxxEax(&w, src[1]); - break; - - case 0x03: /* PLIMM */ /* 未完成(plsまで対応) */ - - /* - * PLIMM : ラベル番号代入命令(6byte) - * - * 1 2 3456 - * 03 PXX imm32 - * - * ・P28 はAPI用 - * ・P30 はリターンアドレス - * ・P3F はプログラムカウンタ - */ - - i = jitCompGetLabelNum(&w, src + 2); // Pxxに代入するラベルの番号(第二引数) - if ((flags & JITC_PHASE1) != 0 && w.err == 0) { // Phase 1であるならば - if (label[i].opt == 0) { w.err = JITC_ERR_LABELNODEF; goto err_w; } // 指定されたラベル番号は存在しない - if (src[1] != 0x3f && label[i].opt != 2) { w.err = JITC_ERR_LABELTYP; goto err_w; } // - if (src[1] == 0x3f && label[i].typ != 0) { w.err = JITC_ERR_LABELTYP; goto err_w; } // プログラムカウンタに TYP_CODEでない値は代入できない - } - if (src[1] == 0x3f) { // プログラムカウンタへの代入なら - if (w.prefix == 0) { // CND命令による条件付きでなければ、即座に移動 - jitCompPutByte1(w.dst, 0xe9); /* JMP(?); */ - } - else { // 直前はCND命令。 - - /* - * CND命令 - * 1 2 - * 04 reg0R - * - * いま、dstの末端はJZ命令になっている。 0x0F 0x84 cd - */ - - // JZのとび先アドレスの書き換え? - w.dst[-1] = w.dst[-2] ^ 0xf1; /* 74->85, 75->84 */ - w.dst[-2] = 0x0f; - - w.prefix = 0; - } - j = 0; - if ((flags & JITC_PHASE1) != 0 || (((flags & JITC_PHASE1) == 0) && label[i].opt != 0)) // label番号iが確保されていれば (このif文は意味をなさない) - j = label[i].p - (w.dst + 4); // j はとび先の相対番地 - jitCompPutImm32(&w, j); // JMP もしくは JZ 命令のアドレス部を記述 -#if (jitCompA0001_OPTIMIZE_JMP != 0) - if (-128 - 3 <= j && j < 0) { - if (w.dst[-5] == 0xe9) { - j += 3; - w.dst -= 5; - jitCompPutByte1(w.dst, 0xeb); /* JMP(?); */ - } - else { - j += 4; - w.dst -= 6; - jitCompPutByte1(w.dst, w.dst[1] ^ 0xf0); - } - jitCompPutByte1(w.dst, j & 0xff); - } -#endif - } - else { // プログラムカウンタ以外への代入 - - // 代入先が P01, P02なら ESI, EDI,それ以外ならEAXを指定 - reg0 = jitCompA000_selectPRegCache(src[1], 0 /* EAX */); - jitCompPutByte1(w.dst, 0xb8 | reg0); /* MOV(reg0, ?); */ - jitCompPutImm32(&w, (int)label[i].p); // ラベルのパスを各レジスタに代入 - - // レジスタへの代入をメモリでエミュレーションする場合は、スタックに積む。 - if (reg0 == 0) - jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32, 0); /* MOV([EBP+?], EAX); */ - - if (level < JITC_LV_FASTEST) { - jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + 8, reg0); /* MOV([EBP+?], reg0); */ /* p0 */ - jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, ?); */ - jitCompPutImm32(&w, label[i].typ); - jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + 4, 0); /* MOV([EBP+?], EAX); */ /* typ */ - jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, ?); */ - jitCompPutImm32(&w, (int)label[i].p1); - jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + 12, 0); /* MOV([EBP+?], EAX); */ /* p1 */ - jitCompPutByte2(w.dst, 0x31, 0xc0); /* XOR(EAX, EAX); */ - jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + 16, 0); /* MOV([EBP+?], EAX); */ /* liveSign */ - jitCompA0001_movReg32EbpDisp(&w, 0, 2320); /* MOV(EAX, ptrCtrl); */ - jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + 20, 0); /* MOV([EBP+?], EAX); */ /* pls */ - } - } - break; - - case 0x04: /* CND (prefix) */ - - /* - * CND命令 - * 与えられたRxxの最下位ビットが1であれば後続の命令を実行、そうでなければ飛ばす。 - */ - - if (src[1] >= 0x40) w.err = JITC_ERR_REGNUM; // R00-R3F 以外のレジスタは比較対象にできない - - // 比較対象のレジスタがメモリ上にあれば-1, それ以外なら適切なレジスタ番号を返す - reg0 = jitCompA000_selectRegCache(src[1], -1 /* mem */); - - /* TEST命令を発行 */ - if (reg0 < 0) { //比較対象のレジスタはメモリ上にある - jitCompPutByte1(w.dst, 0xf7); /* TEST([EBP+?],1); */ - jitCompA0001_85DispN(&w, src[1] * 4, 0); - } - else { - jitCompPutByte2(w.dst, 0xf7, 0xc0 | reg0); /* TEST(reg0,1); */ - } - jitCompPutImm32(&w, 1); - - /* JZ命令を発行 */ - jitCompPutByte2(w.dst, 0x74, 0x00); /* JZ($+2) */ - cmp0reg = -1; - if (w.err != 0) goto err_w; - src += 2; - w.prefix = 1; // プリフィックスをセット - w.dst0 = w.dst; - goto prefix_continue; - - case 0x08: /* LMEM */ /* 完成 */ - i = jitCompGetImm32(src + 2); - if (i == 0x0001) w.err = JITC_ERR_BADTYPE; - if (level < JITC_LV_FASTER) { - jitCompA0001_checkType(&w, src[6], i, 0); // read - cmp0reg = -1; - } - reg0 = jitCompA000_selectRegCache(src[1], 0 /* EAX */); - reg1 = jitCompA000_selectPRegCache(src[6], 2 /* EDX */); - if (reg0 != 0 /* EAX */ && reg1 == 2 /* EDX */) - reg1 = 0; /* EAX */ - if (reg1 == 2 /* EDX */) - jitCompA000_storeRegCacheEdx(&w); - if (reg1 <= 3 /* EAX, EDX */) - jitCompA0001_movReg32EbpDisp(&w, reg1, 256 + src[6] * 32 + 0); /* MOV(reg1, [EBP+?]); */ - if (level < JITC_LV_FASTER) - jitCompA0001_checkLimit(&w, reg1, src[6]); - i = jitCompA000_convTyp(jitCompGetImm32(src + 2)); - switch (i) { - case 0x0002: - jitCompPutByte3(w.dst, 0x0f, 0xbe, reg0 << 3 | reg1); /* MOVSX(reg0,BYTE [reg1]); */ - break; - case 0x0003: - jitCompPutByte3(w.dst, 0x0f, 0xb6, reg0 << 3 | reg1); /* MOVZX(reg0,BYTE [reg1]); */ - break; - case 0x0004: - jitCompPutByte3(w.dst, 0x0f, 0xbf, reg0 << 3 | reg1); /* MOVSX(reg0,WORD [reg1]); */ - break; - case 0x0005: - jitCompPutByte3(w.dst, 0x0f, 0xb7, reg0 << 3 | reg1); /* MOVZX(reg0,WORD [reg1]); */ - break; - case 0x0006: - case 0x0007: - jitCompPutByte2(w.dst, 0x8b, reg0 << 3 | reg1); /* MOV(reg0, [reg1]); */ - break; - default: - w.err = JITC_ERR_BADTYPE; - } - if (reg0 == 0 /* EAX */) - jitCompA0001_movRxxEax(&w, src[1]); - if (reg1 == 2 /* EDX */) - jitCompA000_loadRegCacheEdx(&w); - break; - - case 0x09: /* SMEM */ /* 完成 */ - i = jitCompGetImm32(src + 2); - if (i == 0x0001) w.err = JITC_ERR_BADTYPE; - if (level < JITC_LV_FASTER) { - jitCompA0001_checkType(&w, src[6], i, 1); // write - cmp0reg = -1; - } - reg0 = jitCompA000_selectRegCache(src[1], 0 /* EAX */); - reg1 = jitCompA000_selectPRegCache(src[6], 2 /* EDX */); - if (reg0 != 0 /* EAX */ && reg1 == 2 /* EDX */) - reg1 = 0; /* EAX */ - if (reg1 == 2 /* EDX */) - jitCompA000_storeRegCacheEdx(&w); - if (reg1 <= 3 /* EAX, EDX */) - jitCompA0001_movReg32EbpDisp(&w, reg1, 256 + src[6] * 32 + 0); /* MOV(reg1, [EBP+?]); */ - if (level < JITC_LV_FASTER) - jitCompA0001_checkLimit(&w, reg1, src[6]); - if (reg0 == 0 /* EAX */) - jitCompA0001_movEaxRxx(&w, src[1]); - /* 値の範囲チェック */ - i = jitCompA000_convTyp(jitCompGetImm32(src + 2)); - switch (i) { - case 0x0002: - case 0x0003: - jitCompPutByte2(w.dst, 0x88, reg0 << 3 | reg1); /* MOV([reg1], BYTE(reg0)); */ - break; - case 0x0004: - case 0x0005: - jitCompPutByte3(w.dst, 0x66, 0x89, reg0 << 3 | reg1); /* MOV([reg1], WORD(reg0)); */ - break; - case 0x0006: - case 0x0007: - jitCompPutByte2(w.dst, 0x89, reg0 << 3 | reg1); /* MOV([reg1], reg0); */ - break; - default: - w.err = JITC_ERR_BADTYPE; - } - if (reg1 == 2 /* EDX */) - jitCompA000_loadRegCacheEdx(&w); - break; - - case 0x0a: /* PLMEM */ /* 完成 */ - i = jitCompGetImm32(src + 2); - if (i != 0x0001) w.err = JITC_ERR_BADTYPE; - if (level < JITC_LV_FASTER) { - jitCompA0001_checkType(&w, src[6], i, 0); // read - cmp0reg = -1; - } - reg0 = jitCompA000_selectPRegCache(src[1], 0 /* EAX */); - reg1 = jitCompA000_selectPRegCache(src[6], 2 /* EDX */); - // if (reg0 != 0 /* EAX */ && reg1 == 2 /* EDX */) /* これをやってはいけない!(by K, 2013.08.02) */ - // reg1 = 0; /* EAX */ - if (reg0 == reg1 && reg0 != 0) { // bugfix: hinted by yao, 2013.09.14. thanks! - jitCompA000_storePRegCacheAll(&w); - reg1 = 2; /* EDX */ - } - if (reg1 == 2 /* EDX */) - jitCompA000_storeRegCacheEdx(&w); - if (reg1 <= 3 /* EAX, EDX */) - jitCompA0001_movReg32EbpDisp(&w, reg1, 256 + src[6] * 32 + 0); /* MOV(reg1, [EBP+?]); */ - if (level < JITC_LV_FASTER) - jitCompA0001_checkLimit(&w, reg1, src[6]); - jitCompPutByte2(w.dst, 0x8b, reg0 << 3 | reg1); /* MOV(reg0, [reg1]); */ - if (reg0 == 0 /* EAX */) - jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + 0, 0); /* MOV([EBP+?], EAX); */ - for (i = 4; i < 32; i += 4) { - jitCompPutByte3(w.dst, 0x8b, 0x40 | reg1, i); /* MOV(EAX, [reg1+?]); */ - jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + i, 0 /* EAX */); /* MOV([EBP+?], EAX); */ - } - if (reg1 == 2 /* EDX */) - jitCompA000_loadRegCacheEdx(&w); - break; - - case 0x0b: /* PSMEM */ /* 完成 */ - i = jitCompGetImm32(src + 2); - if (i != 0x0001) w.err = JITC_ERR_BADTYPE; - if (level < JITC_LV_FASTER) { - jitCompA0001_checkType(&w, src[6], i, 1); // write - cmp0reg = -1; - } - reg0 = jitCompA000_selectPRegCache(src[1], 0 /* EAX */); - reg1 = jitCompA000_selectPRegCache(src[6], 2 /* EDX */); - // if (reg0 != 0 /* EAX */ && reg1 == 2 /* EDX */) /* これをやってはいけない!(by K, 2013.08.02) */ - // reg1 = 0; /* EAX */ - if (reg1 == 2 /* EDX */) - jitCompA000_storeRegCacheEdx(&w); - if (reg1 <= 3 /* EAX, EDX */) - jitCompA0001_movReg32EbpDisp(&w, reg1, 256 + src[6] * 32 + 0); /* MOV(reg1, [EBP+?]); */ - if (level < JITC_LV_FASTER) - jitCompA0001_checkLimit(&w, reg1, src[6]); - if (reg0 == 0 /* EAX */) - jitCompA0001_movReg32EbpDisp(&w, reg0, 256 + src[1] * 32 + 0); /* MOV(reg0, [EBP+?]); */ - jitCompPutByte2(w.dst, 0x89, reg0 << 3 | reg1); /* MOV([reg1], reg0); */ - for (i = 4; i < 32; i += 4) { - jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, 256 + src[1] * 32 + i); /* MOV(EAX, [EBP+?]); */ - jitCompPutByte3(w.dst, 0x89, 0x40 | reg1, i); /* MOV([reg1+?], EAX); */ - } - if (reg1 == 2 /* EDX */) - jitCompA000_loadRegCacheEdx(&w); - break; - - case 0x0e: /* PADD */ /* 完成 */ - if (level < JITC_LV_FASTER) { - jitCompA0001_checkType0(&w, src[6], jitCompGetImm32(src + 2), 2); // other, aliveテストはとりあえずしない. - cmp0reg = -1; - } - reg0 = jitCompA000_selectPRegCache(src[1], 0 /* EAX */); - reg1 = jitCompA000_selectPRegCache(src[6], -1 /* mem */); - if (reg1 < 0 /* mem */) - jitCompA0001_movReg32EbpDisp(&w, reg0, 256 + src[6] * 32 + 0); /* MOV(reg0, [EBP+?]); */ - if (reg1 >= 0 && reg0 != reg1) { - jitCompPutByte2(w.dst, 0x89, 0xc0 | reg1 << 3 | reg0); /* MOV(reg0, reg1); */ - } - i = jitCompGetImm32(src + 2); - j = -1; - if (i == 1) - j = 5; /* 32 */ - else { - i = jitCompA000_convTyp(i); - if (0x0002 <= i && i <= 0x0007) - j = (i - 0x0002) >> 1; - } - if (j < 0) { w.err = JITC_ERR_BADTYPE; goto err_w; } -#if (jitCompA0001_USE_R3F_IMM32 != 0) - if (src[7] == 0x3f) { - j = w.r3f << j; -#if (jitCompA0001_USE_R3F_IMM8 != 0) - if (-0x80 <= j && j <= 0x7f) { -#if (jitCompA0001_USE_R3F_INCDEC != 0) - if (j == 1) { jitCompPutByte1(w.dst, 0x40 | reg0); goto padd1; } /* INC */ - if (j == -1) { jitCompPutByte1(w.dst, 0x48 | reg0); goto padd1; } /* DEC */ -#endif - jitCompPutByte3(w.dst, 0x83, 0xc0 | reg0, j & 0xff); /* ADD(reg0, im8); */ - goto padd1; - } -#endif - if (reg0 == 0) { - jitCompPutByte1(w.dst, 0x05); /* ADD(reg0, ?); */ - } - else { - jitCompPutByte2(w.dst, 0x81, 0xc0 | reg0); /* ADD(reg0, ?); */ - } - jitCompPutImm32(&w, j); - goto padd1; - } -#endif - if (src[7] >= 0x40) w.err = JITC_ERR_REGNUM; - if (j == 0) { - reg1 = jitCompA000_selectRegCache(src[7], -1 /* mem */); - if (reg1 >= 0) { - jitCompPutByte2(w.dst, 0x01, 0xc0 | reg1 << 3 | reg0); /* ADD(reg0, reg1); */ - } - else { - jitCompPutByte1(w.dst, 0x03); /* ADD(reg0, [EBP+?]); */ - jitCompA0001_85DispN(&w, src[7] * 4, reg0); - } - } - else { - reg1 = jitCompA000_selectRegCache(src[7], -1 /* mem */); - reg2 = 2; /* EDX */ - jitCompA000_storeRegCacheEdx(&w); - if (reg1 < 0) - jitCompA0001_movReg32EbpDisp(&w, reg2, src[7] * 4); /* MOV(reg2, [EBP+?]); */ - if (reg1 >= 0 && reg1 != reg2) { - jitCompPutByte2(w.dst, 0x89, 0xc0 | reg1 << 3 | reg2); /* MOV(reg2, reg1); */ - } - jitCompPutByte3(w.dst, 0xc1, 0xe0 | reg2, j); /* SHL(reg2, ?); */ - jitCompPutByte2(w.dst, 0x01, 0xc0 | reg2 << 3 | reg0); /* ADD(reg0, reg2); */ - jitCompA000_loadRegCacheEdx(&w); - } -#if (jitCompA0001_USE_R3F_IMM32 != 0) - padd1: -#endif - if (reg0 == 0 /* EAX */) - jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + 0, reg0); /* MOV([EBP+?], reg0); */ - if (src[1] != src[6]) { - for (i = 4; i < 32; i += 4) { - jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, 256 + src[6] * 32 + i); /* MOV(EAX, [EBP+?]); */ - jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + i, 0 /* EAX */); /* MOV([EBP+?], EAX); */ - } - } - cmp0reg = -1; - break; - - case 0x0f: /* PDIF */ /* 未完成 */ - reg0 = jitCompA000_selectRegCache(src[1], 0 /* EAX */); - jitCompA000_storePRegCacheAll(&w); // 手抜き. - jitCompA0001_checkCompPtr(&w, src[6], src[7]); - jitCompA0001_movReg32EbpDisp(&w, reg0, 256 + src[6] * 32 + 0); /* MOV(reg0, [EBP+?]); */ - jitCompPutByte1(w.dst, 0x2b); /* SUB(EAX, [EBP+?]); */ - jitCompA0001_85DispN(&w, 256 + src[7] * 32 + 0, reg0); - i = jitCompA000_convTyp(jitCompGetImm32(src + 2)); - j = -1; - if (0x0002 <= i && i <= 0x0007) - j = (i - 0x0002) >> 1; - if (j < 0) { w.err = JITC_ERR_BADTYPE; goto err_w; } - if (j > 0) { - jitCompPutByte3(w.dst, 0xc1, 0xf8 | reg0, j); /* SAR(reg0,?); */ - } - if (reg0 == 0 /* EAX */) - jitCompA0001_movRxxEax(&w, src[1]); - cmp0reg = src[1]; cmp0lev = 1; - break; - - case 0x10: /* OR */ - case 0x11: /* XOR */ - case 0x12: /* AND */ - case 0x14: /* ADD */ - case 0x15: /* SUB */ - case 0x16: /* MUL */ - if (src[1] >= 0x3f) w.err = JITC_ERR_REGNUM; - reg0 = jitCompA000_selectRegCache(src[1], 0 /* EAX */); - reg1 = jitCompA000_selectRegCache(src[2], -1 /* mem */); -#if (jitCompA0001_USE_R3F_IMM32 != 0) - if (src[2] == 0x3f) { // SUBのみ該当. - if (*src != 0x15) w.err = JITC_ERR_REGNUM; - reg2 = jitCompA000_selectRegCache(src[3], -1 /* mem */); - if (reg2 >= 0) - jitCompA000_storeRegCacheAll(&w); - jitCompPutByte1(w.dst, 0xb8 | reg0); /* MOV(reg0, ?); */ - jitCompPutImm32(&w, w.r3f); - jitCompPutByte1(w.dst, 0x2b); - jitCompA0001_85DispN(&w, src[3] * 4, reg0); - if (reg0 == 0) - jitCompA0001_movRxxEax(&w, src[1]); - break; - } -#endif - if (reg1 < 0) { - jitCompA0001_movReg32EbpDisp(&w, reg0, src[2] * 4); /* MOV(reg0, [EBP+?]); */ - } - if (reg1 >= 0 && reg0 != reg1) { - jitCompPutByte2(w.dst, 0x89, 0xc0 | reg1 << 3 | reg0); /* MOV(reg0, reg1); */ - } - if (!(src[0] == 0x10 && src[3] == 0xff)) { // bugfix: hinted by Iris, 2013.06.26. thanks! - cmp0reg = src[1]; - cmp0lev = 1; - if (src[0] < 0x14) - cmp0lev = 2; - if (src[0] == 0x16) - cmp0reg = -1; - } - if (!(src[0] == 0x10 && src[3] == 0xff)) { -#if (jitCompA0001_USE_R3F_IMM32 != 0) - if (src[3] == 0x3f) { - if (*src == 0x16 && w.r3f == -1) { - jitCompPutByte2(w.dst, 0xf7, 0xd8 | reg0); /* NEG(reg0); */ - if (reg0 == 0) - jitCompA0001_movRxxEax(&w, src[1]); - break; - } -#if (jitCompA0001_USE_R3F_INCDEC != 0) - if ((*src == 0x14 && w.r3f == 1) || (*src == 0x15 && w.r3f == -1)) { - jitCompPutByte1(w.dst, 0x40 | reg0); /* INC(reg0); */ - if (reg0 == 0) - jitCompA0001_movRxxEax(&w, src[1]); - break; - } - if ((*src == 0x15 && w.r3f == 1) || (*src == 0x14 && w.r3f == -1)) { - jitCompPutByte1(w.dst, 0x48 | reg0); /* DEC(reg0); */ - if (reg0 == 0) - jitCompA0001_movRxxEax(&w, src[1]); - break; - } -#endif -#if (jitCompA0001_USE_R3F_IMM8 != 0) - if (-0x80 <= w.r3f && w.r3f <= 0x7f) { - if (*src != 0x16) { - static unsigned char basic_op_table_im8[] = { 0xc8, 0xf0, 0xe0, 0, 0xc0, 0xe8 }; - jitCompPutByte3(w.dst, 0x83, basic_op_table_im8[*src - 0x10] | reg0, w.r3f & 0xff); - } - else { - jitCompPutByte3(w.dst, 0x6b, 0xc0 | reg0 << 3 | reg0, w.r3f & 0xff); - } - if (reg0 == 0) - jitCompA0001_movRxxEax(&w, src[1]); - break; - } -#endif - if (reg0 == 0 /* EAX */) { - static unsigned char basic_op_table_im32_eax[] = { 0x0d, 0x35, 0x25, 0, 0x05, 0x2d, 0xc0 }; - if (*src == 0x16) { jitCompPutByte1(w.dst, 0x69); } - jitCompPutByte1(w.dst, basic_op_table_im32_eax[*src - 0x10]); - } - else { - if (*src != 0x16) { - static unsigned char basic_op_table_im32_reg[] = { 0xc8, 0xf0, 0xe0, 0, 0xc0, 0xe8 }; - jitCompPutByte2(w.dst, 0x81, basic_op_table_im32_reg[*src - 0x10] | reg0); - } - else { - jitCompPutByte2(w.dst, 0x69, 0xc0 | reg0 << 3 | reg0); - } - } - jitCompPutImm32(&w, w.r3f); - if (reg0 == 0) - jitCompA0001_movRxxEax(&w, src[1]); - break; - } -#endif - reg1 = jitCompA000_selectRegCache(src[3], -1 /* mem */); - if (src[3] >= 0x40) w.err = JITC_ERR_REGNUM; - if (*src != 0x16) { - if (reg1 >= 0) { - static unsigned char basic_op_table_rr[] = { 0x09, 0x31, 0x21, 0, 0x01, 0x29 }; /* op(reg,reg); */ - jitCompPutByte2(w.dst, basic_op_table_rr[*src - 0x10], 0xc0 | reg1 << 3 | reg0); - } - else { - static unsigned char basic_op_table_rm[] = { 0x0b, 0x33, 0x23, 0, 0x03, 0x2b, 0xaf }; /* op(reg,mem); */ - jitCompPutByte1(w.dst, basic_op_table_rm[*src - 0x10]); - jitCompA0001_85DispN(&w, src[3] * 4, reg0); - } - } - else { - if (reg1 >= 0) { - jitCompPutByte3(w.dst, 0x0f, 0xaf, 0xc0 | reg0 << 3 | reg1); - } - else { - jitCompPutByte2(w.dst, 0x0f, 0xaf); - jitCompA0001_85DispN(&w, src[3] * 4, reg0); - } - } - } - if (reg0 == 0) - jitCompA0001_movRxxEax(&w, src[1]); - break; - - case 0x18: /* SHL */ - case 0x19: /* SAR */ - if (src[1] >= 0x3f) w.err = JITC_ERR_REGNUM; - if (src[3] >= 0x40) w.err = JITC_ERR_REGNUM; -#if (jitCompA0001_USE_R3F_IMM32 != 0) - if (src[3] == 0x3f) { - reg0 = jitCompA000_selectRegCache(src[1], 0 /* EAX */); - reg1 = jitCompA000_selectRegCache(src[2], -1 /* mem */); - if (src[1] >= 0x3f) w.err = JITC_ERR_REGNUM; - if (reg1 == -1) - jitCompA0001_movReg32EbpDisp(&w, reg0, src[2] * 4); /* MOV(reg1, [EBP+?]); */ - else { - if (reg0 != reg1) { - jitCompPutByte2(w.dst, 0x89, 0xc0 | reg1 << 3 | reg0); /* MOV(reg0, reg1); */ - } - } - if (*src == 0x18) { jitCompPutByte3(w.dst, 0xc1, 0xe0 | reg0, w.r3f); } /* SHL(reg0, im8); */ - if (*src == 0x19) { jitCompPutByte3(w.dst, 0xc1, 0xf8 | reg0, w.r3f); } /* SAR(reg0, im8); */ - if (reg0 == 0 /* EAX */) - jitCompA0001_movRxxEax(&w, src[1]); - cmp0reg = src[1]; - cmp0lev = 1; - break; - } -#endif - jitCompA000_storeRegCacheAll(&w); // 手抜き. - jitCompA0001_movReg32EbpDisp(&w, 1 /* ECX */, src[3] * 4); /* MOV(ECX, [EBP+?]); */ -#if (jitCompA0001_USE_R3F_IMM32 != 0) - if (src[2] == 0x3f) { - jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, ?); */ - jitCompPutImm32(&w, w.r3f); - } - else { - jitCompA0001_movEaxRxx(&w, src[2]); - } -#else - jitCompA0001_movEaxRxx(&w, src[2]); -#endif - if (*src == 0x18) { jitCompPutByte2(w.dst, 0xd3, 0xe0); } /* SHL(EAX, CL); */ - if (*src == 0x19) { jitCompPutByte2(w.dst, 0xd3, 0xf8); } /* SAR(EAX, CL); */ - jitCompA0001_movRxxEax(&w, src[1]); - jitCompA000_loadRegCacheAll(&w); // 手抜き. - cmp0reg = src[1]; - cmp0lev = 1; - break; - - case 0x1a: /* DIV */ - case 0x1b: /* MOD */ - if (src[1] >= 0x3f) w.err = JITC_ERR_REGNUM; - if (src[2] >= 0x40) w.err = JITC_ERR_REGNUM; - if (src[3] >= 0x40) w.err = JITC_ERR_REGNUM; - jitCompA000_storeRegCacheAll(&w); // 手抜き. -#if (jitCompA0001_USE_R3F_IMM32 != 0) - if (src[3] == 0x3f) { - jitCompPutByte1(w.dst, 0xb8 | 1); /* MOV(ECX, ?); */ - jitCompPutImm32(&w, w.r3f); - } - else { - jitCompA0001_movReg32EbpDisp(&w, 1 /* ECX */, src[3] * 4); /* MOV(ECX, [EBP+?]); */ - } - if (src[2] == 0x3f) { - jitCompPutByte1(w.dst, 0xb8 | 0); /* MOV(EAX, ?); */ - jitCompPutImm32(&w, w.r3f); - } - else { - jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, src[2] * 4); /* MOV(EAX, [EBP+?]); */ - } -#else - jitCompA0001_movReg32EbpDisp(&w, 1 /* ECX */, src[3] * 4); /* MOV(ECX, [EBP+?]); */ - jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, src[2] * 4); /* MOV(EAX, [EBP+?]); */ -#endif - jitCompPutByte1(w.dst, 0x99); /* CDQ(); */ - /* ECXがゼロではないことを確認すべき */ - jitCompPutByte2(w.dst, 0xf7, 0xf9); /* IDIV(ECX); */ - if (*src == 0x1a) { jitCompA0001_movEbpDispReg32(&w, src[1] * 4, 0 /* EAX */); } - if (*src == 0x1b) { jitCompA0001_movEbpDispReg32(&w, src[1] * 4, 2 /* EDX */); } - jitCompA000_loadRegCacheAll(&w); // 手抜き. - cmp0reg = -1; - break; - - case 0x1c: /* PLMT0 */ - case 0x1d: /* PLMT1 */ - if (src[1] >= 0x40 || src[2] >= 0x40) w.err = JITC_ERR_PREGNUM; - if (level < JITC_LV_FASTEST) { - cmp0reg = -1; - if (level < JITC_LV_FASTER) { - // typ が一致していることを確認. - // plsとliveSignが一致していることを確認. - - // preg1はp0 <= p <= p1 を満たしているか?. - // 新しいp0/p1は古いp0〜p1に適合しているか?. - - } - } - - case 0x1e: /* PCP */ /* 未完成(p1まで完成) */ - if (src[1] >= 0x40 || src[2] >= 0x40) w.err = JITC_ERR_PREGNUM; - if (src[2] == 0x3f) w.err = JITC_ERR_PREGNUM; - if (src[1] != 0x3f) { - /* src[2] == 0xff の場合に対応できてない */ - jitCompA000_storePRegCacheAll(&w); // 手抜き. - for (i = 0; i < 32; i += 4) { - jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, 256 + src[2] * 32 + i); /* MOV(EAX, [EBP+?]); */ - jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + i, 0 /* EAX */); /* MOV([EBP+?], EAX); */ - } - jitCompA000_loadPRegCacheAll(&w); // 手抜き. - } - else { - if (level < JITC_LV_FASTER) { - jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, 256 + src[2] * 32 + 4); /* MOV(EAX, [EBP+?]); */ /* typ */ - jitCompPutByte3(w.dst, 0x83, 0xf8, 0); /* CMP(EAX, 0); */ - jitCompPutByte2(w.dst, 0x0f, 0x85); /* JNE */ - jitCompPutImm32(&w, errfnc - (w.dst + 4)); - /* セキュリティチェックが足りてない!(aliveとか) */ - } - reg0 = 0; /* EAX */ - jitCompA000_storePRegCacheAll(&w); // 手抜き. - jitCompA0001_movReg32EbpDisp(&w, reg0, 256 + src[2] * 32 + 0); /* MOV(EAX, [EBP+?]); */ - if (level < JITC_LV_FASTER) { - jitCompPutByte1(w.dst, 0x3b); /* CMP(reg0, [EBP+?]); */ - jitCompA0001_85DispN(&w, 256 + src[2] * 32 + 8, reg0); /* p0 */ - jitCompPutByte2(w.dst, 0x0f, 0x85); /* JNE */ - jitCompPutImm32(&w, errfnc - (w.dst + 4)); - } - jitCompPutByte2(w.dst, 0xff, 0xe0); /* JMP(EAX); */ - } - break; - - case 0x1f: /* PCST */ - if (jitCompGetImm32(src + 2) == 0) { - if (level < JITC_LV_FASTER) - jitCompA0001_checkType0(&w, src[6], jitCompGetImm32(src + 7), 2); - jitCompA000_storePRegCacheAll(&w); // 手抜き. - for (i = 0; i < 32 - 4; i += 4) { - jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, 256 + src[6] * 32 + i); /* MOV(EAX, [EBP+?]); */ - if (i == 4) { - jitCompPutByte1(w.dst, 0x0d); /* OR(EAX, ?); */ - jitCompPutImm32(&w, 0x80000000); - } - jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + i, 0 /* EAX */); /* MOV([EBP+?], EAX); */ - } - jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, ?); */ - jitCompPutImm32(&w, debugInfo1); - jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + 28, 0 /* EAX */); /* MOV([EBP+?], EAX); */ - jitCompA000_loadPRegCacheAll(&w); // 手抜き. - cmp0reg = -1; - break; - } - if (jitCompGetImm32(src + 7) == 0) { - jitCompA000_storePRegCacheAll(&w); // 手抜き. - for (i = 0; i < 32 - 4; i += 4) { - jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, 256 + src[6] * 32 + i); /* MOV(EAX, [EBP+?]); */ - if (i == 4) { - jitCompPutByte1(w.dst, 0x25); /* AND(EAX, ?); */ - jitCompPutImm32(&w, 0x7fffffff); - } - jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + i, 0 /* EAX */); /* MOV([EBP+?], EAX); */ - } - if (level < JITC_LV_FASTER) { - jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, 256 + src[6] * 32 + 28); /* MOV(EAX, [EBP+?]); */ - jitCompPutByte1(w.dst, 0x3d); /* CMP(EAX, ?); */ - jitCompPutImm32(&w, debugInfo1); - jitCompPutByte2(w.dst, 0x74, 8); /* JE */ - jitCompPutByte2(w.dst, 0x31, 0xc0); /* XOR(EAX, EAX); (2) */ - jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + 0, 0 /* EAX */); /* MOV([EBP+?], EAX); (1+1+4) */ - } - jitCompA000_loadPRegCacheAll(&w); // 手抜き. - cmp0reg = -1; - break; - } - w.err = JITC_ERR_OPECODE; - goto err_w; - - case 0x20: /* CMPE */ - case 0x21: /* CMPNE */ - case 0x22: /* CMPL */ - case 0x23: /* CMPGE */ - case 0x24: /* CMPLE */ - case 0x25: /* CMPG */ - case 0x26: /* TSTZ */ - case 0x27: /* TSTNZ */ - reg0 = jitCompA000_selectRegCache(src[2], 0 /* EAX */); - reg1 = jitCompA000_selectRegCache(src[3], -1 /* mem */); - if (src[1] == 0x3f) { - /* 特殊構文チェック */ - if (w.prefix != 0) { w.err = JITC_ERR_PREFIX; goto err_w; } - if (src[4] != 0x04 || src[5] != 0x3f || src[6] != 0x03 || src[7] != 0x3f) { - w.err = JITC_ERR_IDIOM; goto err_w; - } - } - if (reg0 == 0) - jitCompA0001_movEaxRxx(&w, src[2]); -#if (jitCompA0001_USE_R3F_IMM32 != 0) - if (src[3] == 0x3f) { -#if (jitCompA0001_OPTIMIZE_CMP != 0) - if ((*src <= 0x25 && w.r3f == 0) || (*src >= 0x26 && w.r3f == -1)) { - i = 0; - if (cmp0reg == src[2]) { - if (cmp0lev >= 1 && (src[0] == 0x20 || src[0] == 0x21 || src[0] == 0x26 || src[0] == 0x27)) - i = 1; - if (cmp0lev >= 2 && (src[0] == 0x22 || src[0] == 0x23 || src[0] == 0x24 || src[0] == 0x25)) - i = 1; - } - if (i == 0) { - jitCompPutByte2(w.dst, 0x85, 0xc0 | reg0 << 3 | reg0); /* TEST(reg0, reg0); */ - } - cmp0reg = src[2]; - cmp0lev = 2; - goto cmpcc1; - } -#endif -#if (jitCompA0001_USE_R3F_IMM8 != 0) - if (-0x80 <= w.r3f && w.r3f <= 0x7f && *src <= 0x25) { - jitCompPutByte3(w.dst, 0x83, 0xf8 | reg0, w.r3f); - goto cmpcc1; - } -#endif - if (reg0 == 0) { - if (*src <= 0x25) { jitCompPutByte1(w.dst, 0x3d); } - if (*src >= 0x26) { jitCompPutByte1(w.dst, 0xa9); } - } - else { - if (*src <= 0x25) { jitCompPutByte2(w.dst, 0x81, 0xf8 | reg0); } - if (*src >= 0x26) { jitCompPutByte2(w.dst, 0xf7, 0xc0 | reg0); } - } - jitCompPutImm32(&w, w.r3f); - goto cmpcc1; - } -#endif - if (src[3] >= 0x40) w.err = JITC_ERR_PREGNUM; - if (reg1 >= 0) { - if (*src <= 0x25) { jitCompPutByte2(w.dst, 0x39, 0xc0 | reg1 << 3 | reg0); } - if (*src >= 0x26) { jitCompPutByte2(w.dst, 0x85, 0xc0 | reg1 << 3 | reg0); } - } - else { - if (*src <= 0x25) { jitCompPutByte1(w.dst, 0x3b); } - if (*src >= 0x26) { jitCompPutByte1(w.dst, 0x85); } - jitCompA0001_85DispN(&w, src[3] * 4, reg0); - } - cmpcc1: - if (w.err != 0) goto err_w; - static unsigned char cmpcc_table0[] = { - 0x04, 0x05, 0x0c, 0x0d, 0x0e, 0x0f, 0x04, 0x05, /* CMPcc, TSTcc */ - 0x04, 0x05, 0x02, 0x03, 0x06, 0x07 /* PCMPcc */ - }; -#if (jitCompA0001_USE_R3F_CMPJMP != 0) - if (src[1] == 0x3f) { - /* 特殊構文を利用した最適化 */ - jitCompPutByte2(w.dst, 0x0f, 0x80 | cmpcc_table0[*src - 0x20]); - src += 6; - i = jitCompGetLabelNum(&w, src + 2); - if ((flags & JITC_PHASE1) != 0 && w.err != 0) { - if (label[i].opt == 0) { w.err = JITC_ERR_LABELNODEF; goto err_w; } - // if (label[i].typ != 1) { w.err = JITC_ERR_LABELTYP; goto err_w; } - } - j = 0; - if ((flags & JITC_PHASE1) != 0 || (((flags & JITC_PHASE1) == 0) && label[i].opt != 0)) - j = label[i].p - (w.dst + 4); - jitCompPutImm32(&w, j); -#if (jitCompA0001_OPTIMIZE_JMP != 0) - if (-128 - 4 <= j && j < 0) { - j += 4; - w.dst -= 6; - jitCompPutByte2(w.dst, w.dst[1] ^ 0xf0, j & 0xff); - } -#endif - src += 6; - if (w.err != 0) goto err_w; - continue; - } -#endif - /* 一般的なJITC */ - reg0 = jitCompA000_selectRegCache(src[1], 0 /* EAX */); - jitCompPutByte3(w.dst, 0x0f, 0x90 | cmpcc_table0[*src - 0x20], 0xc0 | reg0); /* SETcc(BYTE(reg0)); */ - jitCompPutByte3(w.dst, 0x0f, 0xb6, 0xc0 | reg0 << 3 | reg0); /* MOVZX(reg0, BYTE(reg0)); */ - jitCompPutByte2(w.dst, 0xf7, 0xd8 | reg0); /* NEG(reg0); */ - if (reg0 == 0) - jitCompA0001_movRxxEax(&w, src[1]); - cmp0reg = src[2]; - cmp0lev = 1; - break; - - case 0x28: /* PCMPE */ - case 0x29: /* PCMPNE */ - case 0x2a: /* PCMPL */ - case 0x2b: /* PCMPGE */ - case 0x2c: /* PCMPLE */ - case 0x2d: /* PCMPG */ - if (src[1] == 0x3f) { - /* 特殊構文チェック */ - if (w.prefix != 0) { w.err = JITC_ERR_PREFIX; goto err_w; } - if (src[4] != 0x04 || src[5] != 0x3f || src[6] != 0x03 || src[7] != 0x3f) { - w.err = JITC_ERR_IDIOM; goto err_w; - } - } - if (src[2] >= 0x40) w.err = JITC_ERR_PREGNUM; - jitCompA000_storePRegCacheAll(&w); // 手抜き. - if (src[3] != 0xff) - jitCompA0001_checkCompPtr(&w, src[2], src[3]); - jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, 256 + src[2] * 32 + 0); /* MOV(EAX, [EBP+?]); */ - if (src[3] != 0xff) { - jitCompPutByte1(w.dst, 0x3b); /* CMP(EAX, [EBP+?]); */ - jitCompA0001_85DispN(&w, 256 + src[3] * 32 + 0, 0); - } - else { - /* ヌルポインタとの比較はこれでいいのか?たぶんよくない */ - jitCompPutByte3(w.dst, 0x83, 0xf8, 0x00); /* CMP(EAX, 0); */ - } - cmp0reg = -1; - goto cmpcc1; - - case 0x30: /* talloc(old:F4) */ - case 0x31: /* tfree(old:F5) */ - case 0x32: /* malloc(old:F6) */ - case 0x33: /* mfree(old:F7) */ - jitCompA000_storeRegCacheAll(&w); // 手抜き. - jitCompA000_storePRegCacheAll(&w); // 手抜き. - jitCompPutByte2(w.dst, 0x6a, src[3]); /* PUSH(?); */ - jitCompPutByte2(w.dst, 0x6a, src[2]); /* PUSH(?); */ - jitCompPutByte2(w.dst, 0x6a, src[1]); /* PUSH(?); */ - jitCompPutByte1(w.dst, 0x55); /* PUSH(EBP); */ - jitCompPutByte1(w.dst, 0xe8); - if (*src == 0x30) j = ((unsigned char *)&funcf4) - (w.dst + 4); - if (*src == 0x31) j = ((unsigned char *)&funcf5) - (w.dst + 4); - if (*src == 0x32) j = ((unsigned char *)&funcf6) - (w.dst + 4); - if (*src == 0x33) j = ((unsigned char *)&funcf7) - (w.dst + 4); - jitCompPutImm32(&w, j); - jitCompPutByte3(w.dst, 0x83, 0xc4, 0x10); /* ADD(ESP,16); */ - jitCompA000_loadRegCacheAll(&w); // 手抜き. - jitCompA000_loadPRegCacheAll(&w); // 手抜き. - cmp0reg = -1; - break; - - case 0x34: /* data (暫定) */ - cmp0reg = -1; - if (w.prefix != 0) { w.err = JITC_ERR_PREFIX; goto err_w; } - int k = jitCompGetImm32(&src[1]), tmpData, bitCount, dataWidth = jitCompA000_dataWidth(k); - if (lastlabel >= 0 && label[lastlabel].typ == 0) - label[lastlabel].typ = k; - if (k != 1) { - i = jitCompA000_convTyp(k); - if (i < 2 || i > 7) { w.err = JITC_ERR_BADTYPE; goto err_w; } - } - j = jitCompGetImm32(&src[5]); - oldsrc = src; - src += 9; - if (k != 1) { - bitCount = 7; - while (j > 0) { - if (src >= src1) { w.err = JITC_ERR_SRC1; src = oldsrc; goto err_w; } - if (w.dst + 256 > dst1) { w.err = JITC_ERR_DST1; src = oldsrc; goto err_w; } - tmpData = 0; - for (k = 0; k < dataWidth; k++) { - tmpData = tmpData << 1 | ((*src >> bitCount) & 1); - bitCount--; - if (bitCount < 0) { - bitCount = 7; - src++; - } - } - if ((i & 1) == 0 && dataWidth <= 31 && (tmpData >> (dataWidth - 1)) != 0) { - tmpData -= 1 << dataWidth; - } - if (i == 2 || i == 3) { jitCompPutByte1(w.dst, tmpData & 0xff); } - if (i == 4 || i == 5) { jitCompPutByte2(w.dst, tmpData & 0xff, (tmpData >> 8) & 0xff); } - if (i == 6 || i == 7) { jitCompPutByte4(w.dst, tmpData & 0xff, (tmpData >> 8) & 0xff, (tmpData >> 16) & 0xff, (tmpData >> 24) & 0xff); } - j--; - } - } - else { - while (j > 0) { - if (src >= src1) { w.err = JITC_ERR_SRC1; src = oldsrc; goto err_w; } - if (w.dst + 256 > dst1) { w.err = JITC_ERR_DST1; src = oldsrc; goto err_w; } - i = jitCompGetImm32(src); - src += 4; - if ((flags & JITC_PHASE1) != 0 && w.err == 0) { - if (label[i].opt == 0) { w.err = JITC_ERR_LABELNODEF; goto err_w; } - } - jitCompPutImm32(&w, (int)label[i].p); - jitCompPutImm32(&w, label[i].typ); - jitCompPutImm32(&w, (int)label[i].p); - jitCompPutImm32(&w, (int)label[i].p1); - jitCompPutImm32(&w, 0); /* liveSign */ - jitCompPutImm32(&w, 2320); /* pls */ - jitCompPutImm32(&w, 0); - jitCompPutImm32(&w, 0); - j--; - } - } - if (lastlabel >= 0 && label[lastlabel].p1 < w.dst) - label[lastlabel].p1 = w.dst; - continue; - - case 0x3c: /* ENTER */ - jitCompA000_storeRegCacheAll(&w); // 手抜き. - jitCompA000_storePRegCacheAll(&w); // 手抜き. - jitCompPutByte2(w.dst, 0x6a, src[6]); /* PUSH(?); */ - jitCompPutByte2(w.dst, 0x6a, src[5]); /* PUSH(?); */ - jitCompPutByte2(w.dst, 0x6a, src[4] & 0x0f); /* PUSH(?); */ - jitCompPutByte2(w.dst, 0x6a, (src[4] >> 4) & 0x0f); /* PUSH(?); */ - jitCompPutByte2(w.dst, 0x6a, src[3]); /* PUSH(?); */ - jitCompPutByte2(w.dst, 0x6a, src[2]); /* PUSH(?); */ - jitCompPutByte2(w.dst, 0x6a, src[1]); /* PUSH(?); */ - jitCompPutByte1(w.dst, 0x55); /* PUSH(EBP); */ - jitCompPutByte1(w.dst, 0xe8); - j = ((unsigned char *)&func3c) - (w.dst + 4); - jitCompPutImm32(&w, j); - jitCompPutByte3(w.dst, 0x83, 0xc4, 0x20); /* ADD(ESP,32); */ - jitCompA000_loadRegCacheAll(&w); // 手抜き. - jitCompA000_loadPRegCacheAll(&w); // 手抜き. - cmp0reg = -1; - break; - - case 0x3d: /* LEAVE */ - jitCompA000_storeRegCacheAll(&w); // 手抜き. - jitCompA000_storePRegCacheAll(&w); // 手抜き. - jitCompPutByte2(w.dst, 0x6a, src[6]); /* PUSH(?); */ - jitCompPutByte2(w.dst, 0x6a, src[5]); /* PUSH(?); */ - jitCompPutByte2(w.dst, 0x6a, src[4] & 0x0f); /* PUSH(?); */ - jitCompPutByte2(w.dst, 0x6a, (src[4] >> 4) & 0x0f); /* PUSH(?); */ - jitCompPutByte2(w.dst, 0x6a, src[3]); /* PUSH(?); */ - jitCompPutByte2(w.dst, 0x6a, src[2]); /* PUSH(?); */ - jitCompPutByte2(w.dst, 0x6a, src[1]); /* PUSH(?); */ - jitCompPutByte1(w.dst, 0x55); /* PUSH(EBP); */ - jitCompPutByte1(w.dst, 0xe8); - j = ((unsigned char *)&func3d) - (w.dst + 4); - jitCompPutImm32(&w, j); - jitCompPutByte3(w.dst, 0x83, 0xc4, 0x20); /* ADD(ESP,32); */ - jitCompA000_loadRegCacheAll(&w); // 手抜き. - jitCompA000_loadPRegCacheAll(&w); // 手抜き. - cmp0reg = -1; - break; - - case 0xfe: /* remark */ - if (src[1] == 0x01 && src[2] == 0x00) { // DBGINFO1 - if (level <= JITC_LV_SLOWER) { - jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, ?); */ - jitCompPutImm32(&w, debugInfo1); - jitCompA0001_movEbpDispReg32(&w, 2304 + 4, 0 /* EAX */); /* MOV(debugInfo1, EAX); */ - } - } - if (src[1] == 0x01 && src[2] == 0x03) { // DBGINFO1CLR - if (level <= JITC_LV_SLOWER) { - jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, ?); */ - jitCompPutImm32(&w, -1); - jitCompA0001_movEbpDispReg32(&w, 2304 + 4, 0 /* EAX */); /* MOV(debugInfo1, EAX); */ - } - } - if (src[1] == 0x05 && src[2] == 0x00) { // DBGINFO0 - if (level <= JITC_LV_SLOWEST) { - debugInfo0 = jitCompGetImm32(src + 3); - // jitCompPutByte1(w.dst, 0xbf); /* MOV(EDI, ?); */ - // jitCompPutImm32(&w, debugInfo0); - jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, ?); */ - jitCompPutImm32(&w, debugInfo0); - jitCompA0001_movEbpDispReg32(&w, 2304 + 0, 0 /* EAX */); /* MOV(debugInfo0, EAX); */ - } - } - break; - - default: - w.err = JITC_ERR_OPECODE; - goto err_w; - } - if (w.err != 0) goto err_w; - jitCompA0001_fixPrefix(&w); - if (w.err != 0) goto err_w; - src += jitCompCmdLen(src); - } - if (enter0 != NULL) { - j = w.dst - (enter0 + 4); - enter0[0] = j & 0xff; - enter0[1] = (j >> 8) & 0xff; - enter0[2] = (j >> 16) & 0xff; - enter0[3] = (j >> 24) & 0xff; - } - if ((flags & JITC_NOSTARTUP) == 0) { - jitCompA000_storeRegCacheAll(&w); - jitCompA000_storePRegCacheAll(&w); - jitCompPutByte1(w.dst, 0x61); /* POPAD(); */ - } - if ((flags & JITC_PHASE1) != 0) - return w.dst - dst00; - return 0; - -err_w: - if ((w.err & JITC_ERR_PHASE0ONLY) != 0) { - if ((flags & JITC_PHASE1) == 0) - w.err &= ~JITC_ERR_PHASE0ONLY; - } - if (w.err == (JITC_ERR_MASK & JITC_ERR_REGNUM)) errmsg = "reg-number error"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_DST1)) errmsg = "dst1 error"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_OPECODE)) errmsg = "opecode error"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_LABELNUM)) errmsg = "label number too large"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_LABELREDEF)) errmsg = "label redefine"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_PREFIX)) { errmsg = "prefix redefine"; w.dst -= 2; } - if (w.err == (JITC_ERR_MASK & JITC_ERR_LABELNODEF)) errmsg = "label not defined"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_LABELTYP)) errmsg = "label type error"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_IDIOM)) errmsg = "idiom error"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_PREGNUM)) errmsg = "preg-number error"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_SRC1)) errmsg = "src1 error"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_BADTYPE)) errmsg = "bad type code"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_PREFIXFAR)) errmsg = "prefix internal error"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_INTERNAL)) errmsg = "general internal error"; - if (*errmsg != '\0') { - fprintf(stderr, "JITC: %s at %06X (debugInfo0=%d)\n ", errmsg, src - src0, debugInfo0); - for (i = 0; i < 16; i++) - fprintf(stderr, "%02X ", src[i]); - static char *table[0x30] = { - "NOP", "LB", "LIMM", "PLIMM", "CND", "??", "??", "??", - "LMEM", "SMEM", "PLMEM", "PSMEM", "LEA", "??", "PADD", "PDIF", - "CP/OR", "XOR", "AND", "??", "ADD", "SUB", "MUL", "??", - "SHL", "SAR", "DIV", "MOD", "PLMT0", "PLMT1", "PCP", "PCST", - "CMPE", "CMPNE", "CMPL", "CMPGE", "CMPLE", "CMPG", "TSTZ", "TSTNZ", - "PCMPE", "PCMPNE", "PCMPL", "PCMPGE", "PCMPLE", "PCMPG", "??", "EXT" }; - errmsg = "??"; - if (*src < 0x30) errmsg = table[*src]; - fprintf(stderr, "(%s)\n", errmsg); - } - return -1; -} - -unsigned char *jitCompCallFunc(unsigned char *dst, void *func) -{ - struct JitCompWork w; - w.dst = dst; - jitCompA000_storeRegCacheAll(&w); - jitCompA000_storePRegCacheAll(&w); - jitCompPutByte1(w.dst, 0x60); /* PUSHAD(); */ - jitCompPutByte1(w.dst, 0x50); /* PUSH(EAX); */ /* for 16byte-align(win32では不要なのだけど、MacOSには必要らしい) */ - jitCompPutByte1(w.dst, 0x55); /* PUSH(EBP); */ - jitCompPutByte1(w.dst, 0xe8); /* CALL(func); */ - int j = ((unsigned char *)func) - (w.dst + 4); - - //この関数の中では結局w->dstしか参照していない - jitCompPutImm32(&w, j); - - jitCompPutByte1(w.dst, 0x58); /* POP(EAX); */ /* (win32では不要なのだけど、MacOSには必要らしい) */ - jitCompPutByte1(w.dst, 0x58); /* POP(EAX); */ - jitCompPutByte1(w.dst, 0x61); /* POPAD(); */ - jitCompA000_loadRegCacheAll(&w); - jitCompA000_loadPRegCacheAll(&w); - jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, 256 + 0x30 * 32 + 0); /* MOV(EAX, [EBP+?]); */ - jitCompPutByte2(w.dst, 0xff, 0xe0); /* JMP(EAX); */ - return w.dst; -} - -unsigned char *jitCompInit(unsigned char *dst) -{ - errfnc = dst; - return jitCompCallFunc(dst, &errHndl); -} - -void func3c(char *ebp, int opt, int r1, int p1, int lenR, int lenP, int r0, int p0) -{ - HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); - int i, *pi; - HOSECPU_PointerRegisterEntry *pp; - if (r->junkStack + 2048 > r->junkStack1) (*(r->errHndl))(r); - pi = (void *)r->junkStack; r->junkStack += r1 * 4; - for (i = 0; i < r1; i++) - pi[i] = r->ireg[i]; - pp = (void *)r->junkStack; r->junkStack += p1 * 32; - for (i = 0; i < p1; i++) - pp[i] = r->preg[i]; - pp = (void *)r->junkStack; r->junkStack += 32; - *pp = r->preg[0x30]; - pi = (void *)r->junkStack; r->junkStack += 4; - *pi = opt << 16 | r1 << 8 | p1; - for (i = 0; i < lenR; i++) - r->ireg[r0 + i] = r->ireg[0x30 + i]; - for (i = 0; i < lenP; i++) - r->preg[p0 + i] = r->preg[0x31 + i]; - return; -} - -void func3d(char *ebp, int opt, int r1, int p1, int lenR, int lenP, int r0, int p0) -{ - HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); - int i; - r->junkStack -= 4; - r->junkStack -= 32; - HOSECPU_PointerRegisterEntry *pp = (void *)r->junkStack; - r->preg[0x30] = *pp; - r->junkStack -= p1 * 32; pp = (void *)r->junkStack; - for (i = 0; i < p1; i++) - r->preg[i] = pp[i]; - r->junkStack -= r1 * 4; int *pi = (void *)r->junkStack; - for (i = 0; i < r1; i++) - r->ireg[i] = pi[i]; - return; -} - -void funcf4(char *ebp, int pxx, int typ, int len) -{ - HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); - int width = jitCompA000_dataWidth(jitCompA000_convTyp(r->ireg[typ])) >> 3; - if (width < 0 || r->ireg[len] < 0) - (*(r->errHndl))(r); - void *p = r->junkStack; - if (r->junkStack + width * r->ireg[len] + 256 > r->junkStack1) (*(r->errHndl))(r); - r->junkStack += width * r->ireg[len]; - r->preg[pxx].p = p; - r->preg[pxx].typ = r->ireg[typ]; - r->preg[pxx].p0 = p; - r->preg[pxx].p1 = (void *)r->junkStack; - int *pi = (int *)r->junkStack; - *pi = width * r->ireg[len]; - r->junkStack += sizeof (int); - if (r->ireg[typ] == 1) { - int i, i1 = (width * r->ireg[len]) >> 2; - pi = p; - for (i = 0; i < i1; i++) - pi[i] = 0; - } - return; -} - -void funcf5(char *ebp, int pxx, int typ, int len) -{ - // pxxはダミーで参照されない - HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); - r->junkStack -= sizeof (int); - int *pi = (int *)r->junkStack; - r->junkStack -= *pi; -#if 0 - int width = jitCompA000_dataWidth(r->ireg[typ]); - void *p = r->junkStack; - r->junkStack -= width * r->ireg[len]; -#endif - return; -} - -void funcf6(char *ebp, int pxx, int typ, int len) -{ - HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); - int width = jitCompA000_dataWidth(jitCompA000_convTyp(r->ireg[typ])) >> 3; - if (width < 0 || r->ireg[len] < 0) - (*(r->errHndl))(r); - void *p = malloc(width * r->ireg[len]); - r->preg[pxx].p = p; - r->preg[pxx].typ = r->ireg[typ]; - r->preg[pxx].p0 = p; - r->preg[pxx].p1 = (unsigned char *)p + width * r->ireg[len]; - if (r->ireg[typ] == 1) { - int i, i1 = (width * r->ireg[len]) >> 2, *pi; - pi = p; - for (i = 0; i < i1; i++) - pi[i] = 0; - for (i = 1; i < i1; i += 8) - pi[i] |= -1; - } - return; -} - -void funcf7(char *ebp, int pxx, int typ, int len) -{ - // typとlenはダミーで参照されない - HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); - free(r->preg[pxx].p); - return; -} - -void errHndl(HOSECPU_RuntimeEnvironment *r) -{ - r = (HOSECPU_RuntimeEnvironment *) (((char *)r) - jitCompA0001_EBP128); - (*(r->errHndl))(r); - // ここに帰ってきてはいけない. -} - -/* - * jitcの出力コードをひとまとめにする関数を作成しその中身をjitCompile()で生成 - * - * qq : 出力バイナリの書き込み位置のアドレスへの参照(書き込み位置を呼び出しに反映させるため参照渡しにする) - * q1 : 出力バイナリの書き込み位置のアドレスの最大値 - * p0 : (*.ose)バイナリの読み込み位置のアドレス(ヘッダ部除去済) - * p1 : (*.ose)バイナリの読み込み位置の取りうる最大値 - * (ただし、「確保したメモリ」の最大値なのでこれより手前にゴミデータが入っているかもしれない) - * ret=1 : ヘッダのエラー - * ret=2 : jitコンパイルエラー - */ -int jitc0(unsigned char **qq, unsigned char *q1, const unsigned char *p0, const unsigned char *p1, int level, HOSECPU_LabelListTag *label) -{ - unsigned char *q = *qq; - if (p0[0] != 0x05 || p0[1] != SIGN1) // OSECPUのヘッダ (05E1) を確認 - return 1; - - *q++ = 0x55; /* PUSH(EBP); */ - *q++ = 0x8b; *q++ = 0x6c; *q++ = 0x24; *q++ = 0x08; /* MOV(EBP,[ESP+8]); */ - - int i; - for (i = 0; i < JITC_MAXLABELS; i++) - label[i].opt = 0; - - // 以下のjitCompile()呼び出しでは第二引数をq1-2にした方がよいのではないか? - i = jitCompiler(q, q1, p0 + 2, p1, p0, label, JITC_MAXLABELS, level, di1_serial, 0); - if (i != 0) return 2; - i = jitCompiler(q, q1, p0 + 2, p1, p0, label, JITC_MAXLABELS, level, di1_serial, JITC_PHASE1 + 0); - if (i < 0) return 2; - q += i; - - *q++ = 0x5d; /* POP(EBP); */ - *q++ = 0xc3; /* RET(); */ - - *qq = q; - return 0; -} - -#if (USE_DEBUGGER != 0) - -int dbgrGetRegNum(const char *p) -{ - int i, j, r = -1; - if (p[2] <= ' ') { - i = p[0] - '0'; - j = p[1] - '0'; - if (i > 9) i -= 'A' - '0' - 10; - if (j > 9) j -= 'A' - '0' - 10; - if (0 <= i && i <= 15 && 0 <= j && j <= 15) - r = i << 4 | j; - } - return r; -} - -void dbgrMain(HOSECPU_RuntimeEnvironment *r) -{ - if (r->dbgr == 0) return; - for (;;) { - char cmd[64], *p; - int i, j, k; - printf("\ndbgr>"); - p = fgets(cmd, 64, stdin); - if (p == NULL) break; - if (cmd[0] == '\0') continue; - if (cmd[0] == 'q' && cmd[1] <= ' ') break; - if (cmd[0] == 'p' && cmd[1] <= ' ' && cmd[1] != '\0') { - p = &cmd[2]; - while (*p <= ' ' && *p != '\0') p++; - if (*p == 'R') { - i = dbgrGetRegNum(p + 1); - if (0 <= i && i <= 0x3f) { - printf("R%02X = 0x%08X = %d\n", i, r->ireg[i], r->ireg[i]); - } - else - puts("register name error"); - continue; - } - if (*p == 'P') { - i = dbgrGetRegNum(p + 1); - if (0 <= i && i <= 0x3f) { - p = "invalid"; - if (0 <= r->preg[i].typ && r->preg[i].typ <= 0x15) { - static char *typName[] = { - "T_CODE", "T_VPTR", "T_SINT8", "T_UINT8", - "T_SINT16", "T_UINT16", "T_SINT32", "T_UINT32", - "T_SINT4", "T_UINT4", "T_SINT2", "T_UINT2", - "T_SINT1", "T_UINT1", "T_SINT12", "T_UINT12", - "T_SINT20", "T_UINT20", "T_SINT24", "T_UINT24", - "T_SINT28", "T_UINT28" - }; - p = typName[r->preg[i].typ]; - } - printf("P%02X:\n type = %s(%04X), (origin-ptr) = 0x%08X\n", i, p, r->preg[i].typ, (unsigned int)(r->preg[i].p0)); - if (r->preg[i].p != NULL && r->preg[i].p0 != NULL) { - j = jitCompA000_dataWidth(jitCompA000_convTyp(r->preg[i].typ)) >> 3; - if (j <= 0) j = 1; - k = (r->preg[i].p1 - r->preg[i].p0) / j; - printf(" size = 0x%08X = %d\n", k, k); - k = (r->preg[i].p - r->preg[i].p0) / j; - printf(" pos = 0x%08X = %d\n", k, k); - } - else { - puts(" null pointer"); - } - } - else - puts("register name error"); - continue; - } - } - puts("command error"); - } - return; -} - -#endif - - +#include "osecpu.h" +#include "jitc.h" + +#if (JITC_ARCNUM == 0x0001) +// +// for x86-32bit +// + +void jitCompPutImm32(struct JitCompWork *w, int i) +{ + jitCompPutByte1(w->dst, i & 0xff); + jitCompPutByte1(w->dst, (i >> 8) & 0xff); + jitCompPutByte1(w->dst, (i >> 16) & 0xff); + jitCompPutByte1(w->dst, (i >> 24) & 0xff); + return; +} + +int jitCompGetImm32(const unsigned char *src) +{ + return (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; +} + +int jitCompGetLabelNum(struct JitCompWork *w, const unsigned char *src) +{ + int i = jitCompGetImm32(src); + if (i < 0 || i >= w->maxLabels) { + w->err = JITC_ERR_LABELNUM; + i = 0; + } + return i; +} + +void jitCompA0001_85DispN(struct JitCompWork *w, int disp, int n) +{ + disp -= jitCompA0001_EBP128; + if (-128 <= disp && disp <= 127) { + jitCompPutByte2(w->dst, 0x45 | (n << 3), disp & 0xff); + } else { + jitCompPutByte1(w->dst, 0x85 | (n << 3)); + jitCompPutImm32(w, disp); + } + return; +} + +void jitCompA0001_movEbpDispReg32(struct JitCompWork *w, int disp, int reg32) +{ + jitCompPutByte1(w->dst, 0x89); /* MOV(mem, reg32); */ + jitCompA0001_85DispN(w, disp, reg32); + return; +} + +void jitCompA0001_movReg32EbpDisp(struct JitCompWork *w, int reg32, int disp) +{ + jitCompPutByte1(w->dst, 0x8b); /* MOV(reg32, mem); */ + jitCompA0001_85DispN(w, disp, reg32); + return; +} + +void jitCompA0001_movEaxRxx(struct JitCompWork *w, int rxx) +{ +#if (jitCompA0001_USE_R3F_IMM32 != 0) + if (rxx == 0x3f) { + jitCompPutByte1(w->dst, 0xb8); /* MOV(EAX, ?); */ + jitCompPutImm32(w, w->r3f); + return; + } +#endif + if (rxx >= 0x40 || rxx < 0){ + w->err = JITC_ERR_REGNUM; + } + jitCompA0001_movReg32EbpDisp(w, 0 /* EAX */, rxx * 4); /* MOV(EAX, [EBP+?]); */ + return; +} + +void jitCompA0001_movRxxEax(struct JitCompWork *w, int rxx) +{ + if (rxx >= 0x40 || rxx < 0){ + w->err = JITC_ERR_REGNUM; + } + jitCompA0001_movEbpDispReg32(w, rxx * 4, 0 /* EAX */); /* MOV([EBP+?], EAX); */ + return; +} + +void jitCompA0001_fixPrefix(struct JitCompWork *w) +{ + if (w->prefix != 0) { + if (w->dst - w->dst0 > 127){ + w->err = JITC_ERR_REGNUM; + } + w->dst0[-1] = (unsigned char)((w->dst - w->dst0) & 0xff); + } + return; +} + +void jitCompA0001_checkCompPtr(struct JitCompWork *w, int p0, int p1) +{ + if (p0 >= 0x3f || p0 < 0){ + w->err = JITC_ERR_PREGNUM; + } + if (p1 >= 0x3f || p1 < 0){ + w->err = JITC_ERR_PREGNUM; + } + /* 比較可能可能なのかのチェックのコードを出力 */ /* 未完成 */ + return; +} + +void jitCompA000_loadRegCacheAll(struct JitCompWork *w) +{ + jitCompA0001_movReg32EbpDisp(w, 3 /* EBX */, 0 * 4); /* EBX = R00; */ + jitCompA0001_movReg32EbpDisp(w, 1 /* ECX */, 1 * 4); /* ECX = R01; */ + jitCompA0001_movReg32EbpDisp(w, 2 /* EDX */, 2 * 4); /* EDX = R02; */ + return; +} + +void jitCompA000_storeRegCacheAll(struct JitCompWork *w) +{ + jitCompA0001_movEbpDispReg32(w, 0 * 4, 3 /* EBX */); /* R00 = EBX; */ + jitCompA0001_movEbpDispReg32(w, 1 * 4, 1 /* ECX */); /* R01 = ECX; */ + jitCompA0001_movEbpDispReg32(w, 2 * 4, 2 /* EDX */); /* R02 = EDX; */ + return; +} + +void jitCompA000_loadRegCacheEcx(struct JitCompWork *w) +{ + jitCompA0001_movReg32EbpDisp(w, 1 /* ECX */, 1 * 4); /* ECX = R01; */ + return; +} + +void jitCompA000_storeRegCacheEcx(struct JitCompWork *w) +{ + jitCompA0001_movEbpDispReg32(w, 1 * 4, 1 /* ECX */); /* R01 = ECX; */ + return; +} + +void jitCompA000_loadRegCacheEdx(struct JitCompWork *w) +{ + jitCompA0001_movReg32EbpDisp(w, 2 /* EDX */, 2 * 4); /* EDX = R02; */ + return; +} + +void jitCompA000_storeRegCacheEdx(struct JitCompWork *w) +{ + jitCompA0001_movEbpDispReg32(w, 2 * 4, 2 /* EDX */); /* R02 = EDX; */ + return; +} + +int jitCompA000_selectRegCache(int rxx, int reg) +{ + switch (rxx) { + case 0: + //EBX + reg = 3; + break; + case 1: + //ECX + reg = 1; + break; + case 2: + //EDX + reg = 2; + break; + } + return reg; +} + +void jitCompA000_loadPRegCacheAll(struct JitCompWork *w) +{ + // jitCompA0001_movReg32EbpDisp(w, 5 /* EBP */, 256 + 0 * 32 + 0); /* EBP = P00; */ + jitCompA0001_movReg32EbpDisp(w, 6 /* ESI */, 256 + 1 * 32 + 0); /* ESI = P01; */ + jitCompA0001_movReg32EbpDisp(w, 7 /* EDI */, 256 + 2 * 32 + 0); /* EDI = P02; */ + return; +} + +void jitCompA000_storePRegCacheAll(struct JitCompWork *w) +{ + // jitCompA0001_movEbpDispReg32(w, 256 + 0 * 32 + 0, 5 /* EBP */); /* P00 = EBP; */ + jitCompA0001_movEbpDispReg32(w, 256 + 1 * 32 + 0, 6 /* ESI */); /* P01 = ESI; */ + jitCompA0001_movEbpDispReg32(w, 256 + 2 * 32 + 0, 7 /* EDI */); /* P02 = EDI; */ + return; +} + +int jitCompA000_selectPRegCache(int pxx, int reg) +{ + // if (pxx == 0) reg = 5; /* EBP */ + switch (pxx) { + case 1: + //ESI + reg = 6; + break; + + case 2: + //EDI + reg = 7; + break; + } + return reg; +} + +int jitCompA000_convTyp(int t) +{ + int r = -1; + + if (1 <= t && t <= 7){ + r = t; + } else if (8 <= t && t <= 13){ + r = 2 | (t & 1); + } else if (14 <= t && t <= 15){ + r = 4 | (t & 1); + } else if (16 <= t && t <= 21){ + r = 6 | (t & 1); + } + return r; +} + +int jitCompA000_dataWidth(int t) +{ + int r = -1; + if (t == 0x0001) r = 256; + t >>= 1; + if (t == 0x0002 / 2) r = 8; + if (t == 0x0004 / 2) r = 16; + if (t == 0x0006 / 2) r = 32; + if (t == 0x0008 / 2) r = 4; + if (t == 0x000a / 2) r = 2; + if (t == 0x000c / 2) r = 1; + if (t == 0x000e / 2) r = 12; + if (t == 0x0010 / 2) r = 20; + if (t == 0x0012 / 2) r = 24; + if (t == 0x0014 / 2) r = 28; + return r; +} + +static unsigned char *errfnc; + +void jitCompA0001_checkType0(struct JitCompWork *w, int pxx, int typ, int ac) +{ + if (typ <= 0) { w->err = JITC_ERR_BADTYPE; } + if (typ > 0x7f) { w->err = JITC_ERR_INTERNAL; } + jitCompA0001_movReg32EbpDisp(w, 0 /* EAX */, 256 + pxx * 32 + 4); /* MOV(EAX, [EBP+?]); */ /* typ */ + jitCompPutByte3(w->dst, 0x83, 0xf8, typ & 0x7f); /* CMP(EAX, ?); */ + jitCompPutByte2(w->dst, 0x0f, 0x85); /* JNE */ + jitCompPutImm32(w, errfnc - (w->dst + 4)); + return; +} + +void jitCompA0001_checkType(struct JitCompWork *w, int pxx, int typ, int ac) +// data用. +// 将来的にはaliveやアクセス権チェックも入れる +{ + jitCompA0001_checkType0(w, pxx, typ, ac); + return; +} + +void jitCompA0001_checkLimit(struct JitCompWork *w, int reg, int pxx) +{ + jitCompPutByte1(w->dst, 0x3b); /* CMP(reg, [EBP+?]); */ + jitCompA0001_85DispN(w, 256 + pxx * 32 + 8, reg); /* p0 */ + jitCompPutByte2(w->dst, 0x0f, 0x82); /* JB */ + jitCompPutImm32(w, errfnc - (w->dst + 4)); + jitCompPutByte1(w->dst, 0x3b); /* CMP(reg, [EBP+?]); */ + jitCompA0001_85DispN(w, 256 + pxx * 32 + 12, reg); /* p1 */ + jitCompPutByte2(w->dst, 0x0f, 0x83); /* JAE */ + jitCompPutImm32(w, errfnc - (w->dst + 4)); + return; +} + +// F5の場合、decoderが対応するalloc-freeを結びつけるのが簡単で、typやlenを指定必須にしてもフロントエンドコードに影響はない. +int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *src, const unsigned char *src1, const unsigned char *src0, HOSECPU_LabelListTag *label, int maxLabels, int level, int debugInfo1, int flags) +{ + // For IA-32 (x86, 32-bit) + // 本来ならこのレイヤでは文法チェックしない + // + // dst : 現在の書き込みアドレス。 + // dst1 : 書き込みアドレスの最大値 + // src : 現在の読み込みアドレス(ヘッダ部は飛ばしてある + // src1 : 読み込みアドレスの最大値 + // src0 : 読み込みバイナリのアドレス + struct JitCompWork w; + unsigned char *dst00 = dst, *enter0 = NULL, *tmp_ucp; + char *errmsg = ""; + const unsigned char *oldsrc; + int timecount = 0, i, j = 0, lastlabel = -1, debugInfo0 = -1; + int reg0, reg1, reg2, cmp0reg = -1, cmp0lev = 0; + w.dst = w.dst0 = dst; + w.err = 0; + w.maxLabels = maxLabels; + + if ((flags & JITC_NOSTARTUP) == 0) { + jitCompPutByte1(w.dst, 0x60); /* PUSHAD(); */ + jitCompA000_loadRegCacheAll(&w); /* start-up */ + jitCompA000_loadPRegCacheAll(&w); + } + if (level <= JITC_LV_SLOWER) { + jitCompPutByte2(w.dst, 0x31, 0xc0); /* XOR(EAX, EAX); */ + jitCompA0001_movEbpDispReg32(&w, 2304 + 0, 0 /* EAX */); /* MOV(debugInfo0, EAX); */ + jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, ?); */ + jitCompPutImm32(&w, debugInfo1); + jitCompA0001_movEbpDispReg32(&w, 2304 + 4, 0 /* EAX */); /* MOV(debugInfo1, EAX); */ + } + while (src < src1) { + w.prefix = 0; //0x04 CND 命令で変更される + if (w.dst + 256 > dst1) { w.err = JITC_ERR_DST1; goto err_w; } // 書き込み領域が残り256バイト未満ならエラー + timecount++; + if (timecount >= 64) { + timecount -= 64; + /* 未完成(timeoutチェックコードを入れる) */ + } + prefix_continue: // CND命令実行後ここに戻る + switch (*src) { + + case 0x00: /* NOP */ + if (w.prefix != 0) { w.err = JITC_ERR_PREFIX; goto err_w; } // 「条件付きでNOPを実行」するなんて、矛盾している! + break; + + case 0x01: /* LB */ + + /* + * LB : ラベル設置命令。(6byte) + * ・prefex = 1にする + * ・timecount++し、timecountのチェックをする。 + * ・ラベル位置を登録する。 + * ・割り込みがある場合、このタイミングで割り込みを発生させる。 + * + * 1 2 3 456 + * LB 01 opt imm32 + * + */ + + if (enter0 == NULL && (src[6] == 0x3c /* 多数のレジスタをスタックに退避 */ || (src[6] == 0xfe/* REMARK */ && src[7] == 0x01 && src[9] == 0x3c))) { //beginFunc()中のLB + // LB命令の後に0x3C命令・・・beginFunc() + jitCompPutByte1(w.dst, 0xe9); // (x86) JMP rel32 : 次の命令との相対オフセットだけ相対ニアジャンプする + enter0 = w.dst; + jitCompPutImm32(&w, 0); // 飛び相対座標が0 ・・・パイプラインのフラッシュ?? + } + if (src[6] == 0x34) { // LBの次の命令がDATA ・・・DAT_SA0(label, typ32, length) ・・・メモリ確保命令 + tmp_ucp = w.dst; + jitCompPutByte1(w.dst, 0xe9); // (x86) JMP rel32 : 次の命令との相対オフセットだけ相対ニアジャンプする + i = jitCompGetImm32(&src[7]); // type32 を取得 + j = 32; + if (i != 1) { + i = jitCompA000_convTyp(i); + j = 0; + if (i == 2 || i == 3) { j = 1; } + if (i == 4 || i == 5) { j = 2; } + if (i == 6 || i == 7) { j = 4; } + } + j *= jitCompGetImm32(&src[11]); + if (j <= 0) w.err = JITC_ERR_BADTYPE; + jitCompPutImm32(&w, j); +#if (jitCompA0001_OPTIMIZE_JMP != 0) + if (j <= 127 - jitCompA0001_OPTIMIZE_ALIGN) { + w.dst -= 5; + jitCompPutByte2(w.dst, 0xeb, j); + } +#endif + } +#if (jitCompA0001_OPTIMIZE_ALIGN != 0) + for (;;) { + i = ((int)w.dst) & (jitCompA0001_OPTIMIZE_ALIGN - 1); /* ALIGNで割ったあまりを計算 */ + if (i == 0) break; + i = jitCompA0001_OPTIMIZE_ALIGN - i; + if (i == 1) { jitCompPutByte1(w.dst, 0x90); j += i; } /* NOP(); */ + if (i == 2) { jitCompPutByte2(w.dst, 0x89, 0xc0); j += i; } /* MOV(EAX, EAX); */ + if (i == 3) { jitCompPutByte3(w.dst, 0x8d, 0x76, 0x00); j += i; } /* LEA(ESI, [ESI+0]); */ + if (i == 4) { jitCompPutByte4(w.dst, 0x8d, 0x74, 0x26, 0x00); j += i; } /* LEA(ESI, [ESI*1+0]); */ + if (i == 5) { jitCompPutByte1(w.dst, 0x0d); jitCompPutImm32(&w, 0); j += i; } /* OR(EAX, 0); */ + if (i == 6) { jitCompPutByte2(w.dst, 0x8d, 0xb6); jitCompPutImm32(&w, 0); j += i; } /* LEA(ESI, [ESI+0]); */ + if (i >= 7) { jitCompPutByte3(w.dst, 0x8d, 0xb4, 0x26); jitCompPutImm32(&w, 0); j += 7; } /* LEA(ESI, [ESI*1+0]); */ + } +#endif + if (src[6] == 0x34) { + tmp_ucp[1] = j & 0xff; + if (*tmp_ucp == 0xe9) { + tmp_ucp[2] = (j >> 8) & 0xff; + tmp_ucp[3] = (j >> 16) & 0xff; + tmp_ucp[4] = (j >> 24) & 0xff; + } + } + if ((flags & JITC_PHASE1) == 0) { + i = jitCompGetLabelNum(&w, src + 2); + //printf("i=%06X %06X\n", i, src-src0); + if (label[i].opt != 0 && w.err == 0) { w.err = JITC_ERR_LABELREDEF; goto err_w; } + if (w.prefix != 0) { w.err = JITC_ERR_PREFIX; goto err_w; } + label[i].opt = src[1] + 1; + label[i].typ = 0; /* TYP_CODE */ + label[i].p = w.dst; + label[i].p1 = w.dst + 1; + lastlabel = i; + } + cmp0reg = -1; + timecount = 0; + /* 未完成(timeoutチェックコードを入れる) */ + break; + + case 0x02: /* LIMM */ + + /* + * LIMM : 定数即値代入命令(6byte) + * + * 1 2 3456 + * 02 reg0R imm32 + * + * ・reg3F は条件比較慣用句指定用&演算命令即値慣用句指定用。よってCND命令の直後では使用できない。 + */ + + if (src[1] == 0x3f && w.prefix != 0) w.err = JITC_ERR_PREFIX; // CND命令の直後でR3Fを書き換えるなんて変だよね + +#if (jitCompA0001_USE_R3F_IMM32 != 0) + if (src[1] == 0x3f) { // R3Fへの代入は例外敵に、 w.r3f を使用 + w.r3f = jitCompGetImm32(src + 2); + break; + } +#endif + i = jitCompGetImm32(src + 2); // 与えられた即値(第二引数)を取得 + + /* R00-R02 なら EBX, ECX, EDX 、それ以外なら EAX のレジスタIDを reg0 に代入 */ + reg0 = jitCompA000_selectRegCache(src[1], 0 /* EAX */); + +#if (jitCompA0001_OPTIMIZE_MOV != 0) + if (i == 0) { + jitCompPutByte2(w.dst, 0x31, 0xc0 | reg0 << 3 | reg0); /* XOR(reg0, reg0); */ + jitCompA0001_movRxxEax(&w, src[1]); + break; + } +#endif + + /* reg0 のレジスタに対応したMOV命令を発行 */ + jitCompPutByte1(w.dst, 0xb8 | reg0); /* MOV(reg0, ?); == 10111000b+wr imm32 */ + jitCompPutImm32(&w, i); + + if (reg0 == 0) // R03以降の、レジスタの内容をメモリ上に格納してエミュレートする場合 + + jitCompA0001_movRxxEax(&w, src[1]); + break; + + case 0x03: /* PLIMM */ /* 未完成(plsまで対応) */ + + /* + * PLIMM : ラベル番号代入命令(6byte) + * + * 1 2 3456 + * 03 PXX imm32 + * + * ・P28 はAPI用 + * ・P30 はリターンアドレス + * ・P3F はプログラムカウンタ + */ + + i = jitCompGetLabelNum(&w, src + 2); // Pxxに代入するラベルの番号(第二引数) + if ((flags & JITC_PHASE1) != 0 && w.err == 0) { // Phase 1であるならば + if (label[i].opt == 0) { w.err = JITC_ERR_LABELNODEF; goto err_w; } // 指定されたラベル番号は存在しない + if (src[1] != 0x3f && label[i].opt != 2) { w.err = JITC_ERR_LABELTYP; goto err_w; } // + if (src[1] == 0x3f && label[i].typ != 0) { w.err = JITC_ERR_LABELTYP; goto err_w; } // プログラムカウンタに TYP_CODEでない値は代入できない + } + if (src[1] == 0x3f) { // プログラムカウンタへの代入なら + if (w.prefix == 0) { // CND命令による条件付きでなければ、即座に移動 + jitCompPutByte1(w.dst, 0xe9); /* JMP(?); */ + } + else { // 直前はCND命令。 + + /* + * CND命令 + * 1 2 + * 04 reg0R + * + * いま、dstの末端はJZ命令になっている。 0x0F 0x84 cd + */ + + // JZのとび先アドレスの書き換え? + w.dst[-1] = w.dst[-2] ^ 0xf1; /* 74->85, 75->84 */ + w.dst[-2] = 0x0f; + + w.prefix = 0; + } + j = 0; + if ((flags & JITC_PHASE1) != 0 || (((flags & JITC_PHASE1) == 0) && label[i].opt != 0)) // label番号iが確保されていれば (このif文は意味をなさない) + j = label[i].p - (w.dst + 4); // j はとび先の相対番地 + jitCompPutImm32(&w, j); // JMP もしくは JZ 命令のアドレス部を記述 +#if (jitCompA0001_OPTIMIZE_JMP != 0) + if (-128 - 3 <= j && j < 0) { + if (w.dst[-5] == 0xe9) { + j += 3; + w.dst -= 5; + jitCompPutByte1(w.dst, 0xeb); /* JMP(?); */ + } + else { + j += 4; + w.dst -= 6; + jitCompPutByte1(w.dst, w.dst[1] ^ 0xf0); + } + jitCompPutByte1(w.dst, j & 0xff); + } +#endif + } + else { // プログラムカウンタ以外への代入 + + // 代入先が P01, P02なら ESI, EDI,それ以外ならEAXを指定 + reg0 = jitCompA000_selectPRegCache(src[1], 0 /* EAX */); + jitCompPutByte1(w.dst, 0xb8 | reg0); /* MOV(reg0, ?); */ + jitCompPutImm32(&w, (int)label[i].p); // ラベルのパスを各レジスタに代入 + + // レジスタへの代入をメモリでエミュレーションする場合は、スタックに積む。 + if (reg0 == 0) + jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32, 0); /* MOV([EBP+?], EAX); */ + + if (level < JITC_LV_FASTEST) { + jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + 8, reg0); /* MOV([EBP+?], reg0); */ /* p0 */ + jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, ?); */ + jitCompPutImm32(&w, label[i].typ); + jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + 4, 0); /* MOV([EBP+?], EAX); */ /* typ */ + jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, ?); */ + jitCompPutImm32(&w, (int)label[i].p1); + jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + 12, 0); /* MOV([EBP+?], EAX); */ /* p1 */ + jitCompPutByte2(w.dst, 0x31, 0xc0); /* XOR(EAX, EAX); */ + jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + 16, 0); /* MOV([EBP+?], EAX); */ /* liveSign */ + jitCompA0001_movReg32EbpDisp(&w, 0, 2320); /* MOV(EAX, ptrCtrl); */ + jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + 20, 0); /* MOV([EBP+?], EAX); */ /* pls */ + } + } + break; + + case 0x04: /* CND (prefix) */ + + /* + * CND命令 + * 与えられたRxxの最下位ビットが1であれば後続の命令を実行、そうでなければ飛ばす。 + */ + + if (src[1] >= 0x40) w.err = JITC_ERR_REGNUM; // R00-R3F 以外のレジスタは比較対象にできない + + // 比較対象のレジスタがメモリ上にあれば-1, それ以外なら適切なレジスタ番号を返す + reg0 = jitCompA000_selectRegCache(src[1], -1 /* mem */); + + /* TEST命令を発行 */ + if (reg0 < 0) { //比較対象のレジスタはメモリ上にある + jitCompPutByte1(w.dst, 0xf7); /* TEST([EBP+?],1); */ + jitCompA0001_85DispN(&w, src[1] * 4, 0); + } + else { + jitCompPutByte2(w.dst, 0xf7, 0xc0 | reg0); /* TEST(reg0,1); */ + } + jitCompPutImm32(&w, 1); + + /* JZ命令を発行 */ + jitCompPutByte2(w.dst, 0x74, 0x00); /* JZ($+2) */ + cmp0reg = -1; + if (w.err != 0) goto err_w; + src += 2; + w.prefix = 1; // プリフィックスをセット + w.dst0 = w.dst; + goto prefix_continue; + + case 0x08: /* LMEM */ /* 完成 */ + i = jitCompGetImm32(src + 2); + if (i == 0x0001) w.err = JITC_ERR_BADTYPE; + if (level < JITC_LV_FASTER) { + jitCompA0001_checkType(&w, src[6], i, 0); // read + cmp0reg = -1; + } + reg0 = jitCompA000_selectRegCache(src[1], 0 /* EAX */); + reg1 = jitCompA000_selectPRegCache(src[6], 2 /* EDX */); + if (reg0 != 0 /* EAX */ && reg1 == 2 /* EDX */) + reg1 = 0; /* EAX */ + if (reg1 == 2 /* EDX */) + jitCompA000_storeRegCacheEdx(&w); + if (reg1 <= 3 /* EAX, EDX */) + jitCompA0001_movReg32EbpDisp(&w, reg1, 256 + src[6] * 32 + 0); /* MOV(reg1, [EBP+?]); */ + if (level < JITC_LV_FASTER) + jitCompA0001_checkLimit(&w, reg1, src[6]); + i = jitCompA000_convTyp(jitCompGetImm32(src + 2)); + switch (i) { + case 0x0002: + jitCompPutByte3(w.dst, 0x0f, 0xbe, reg0 << 3 | reg1); /* MOVSX(reg0,BYTE [reg1]); */ + break; + case 0x0003: + jitCompPutByte3(w.dst, 0x0f, 0xb6, reg0 << 3 | reg1); /* MOVZX(reg0,BYTE [reg1]); */ + break; + case 0x0004: + jitCompPutByte3(w.dst, 0x0f, 0xbf, reg0 << 3 | reg1); /* MOVSX(reg0,WORD [reg1]); */ + break; + case 0x0005: + jitCompPutByte3(w.dst, 0x0f, 0xb7, reg0 << 3 | reg1); /* MOVZX(reg0,WORD [reg1]); */ + break; + case 0x0006: + case 0x0007: + jitCompPutByte2(w.dst, 0x8b, reg0 << 3 | reg1); /* MOV(reg0, [reg1]); */ + break; + default: + w.err = JITC_ERR_BADTYPE; + } + if (reg0 == 0 /* EAX */) + jitCompA0001_movRxxEax(&w, src[1]); + if (reg1 == 2 /* EDX */) + jitCompA000_loadRegCacheEdx(&w); + break; + + case 0x09: /* SMEM */ /* 完成 */ + i = jitCompGetImm32(src + 2); + if (i == 0x0001) w.err = JITC_ERR_BADTYPE; + if (level < JITC_LV_FASTER) { + jitCompA0001_checkType(&w, src[6], i, 1); // write + cmp0reg = -1; + } + reg0 = jitCompA000_selectRegCache(src[1], 0 /* EAX */); + reg1 = jitCompA000_selectPRegCache(src[6], 2 /* EDX */); + if (reg0 != 0 /* EAX */ && reg1 == 2 /* EDX */) + reg1 = 0; /* EAX */ + if (reg1 == 2 /* EDX */) + jitCompA000_storeRegCacheEdx(&w); + if (reg1 <= 3 /* EAX, EDX */) + jitCompA0001_movReg32EbpDisp(&w, reg1, 256 + src[6] * 32 + 0); /* MOV(reg1, [EBP+?]); */ + if (level < JITC_LV_FASTER) + jitCompA0001_checkLimit(&w, reg1, src[6]); + if (reg0 == 0 /* EAX */) + jitCompA0001_movEaxRxx(&w, src[1]); + /* 値の範囲チェック */ + i = jitCompA000_convTyp(jitCompGetImm32(src + 2)); + switch (i) { + case 0x0002: + case 0x0003: + jitCompPutByte2(w.dst, 0x88, reg0 << 3 | reg1); /* MOV([reg1], BYTE(reg0)); */ + break; + case 0x0004: + case 0x0005: + jitCompPutByte3(w.dst, 0x66, 0x89, reg0 << 3 | reg1); /* MOV([reg1], WORD(reg0)); */ + break; + case 0x0006: + case 0x0007: + jitCompPutByte2(w.dst, 0x89, reg0 << 3 | reg1); /* MOV([reg1], reg0); */ + break; + default: + w.err = JITC_ERR_BADTYPE; + } + if (reg1 == 2 /* EDX */) + jitCompA000_loadRegCacheEdx(&w); + break; + + case 0x0a: /* PLMEM */ /* 完成 */ + i = jitCompGetImm32(src + 2); + if (i != 0x0001) w.err = JITC_ERR_BADTYPE; + if (level < JITC_LV_FASTER) { + jitCompA0001_checkType(&w, src[6], i, 0); // read + cmp0reg = -1; + } + reg0 = jitCompA000_selectPRegCache(src[1], 0 /* EAX */); + reg1 = jitCompA000_selectPRegCache(src[6], 2 /* EDX */); + // if (reg0 != 0 /* EAX */ && reg1 == 2 /* EDX */) /* これをやってはいけない!(by K, 2013.08.02) */ + // reg1 = 0; /* EAX */ + if (reg0 == reg1 && reg0 != 0) { // bugfix: hinted by yao, 2013.09.14. thanks! + jitCompA000_storePRegCacheAll(&w); + reg1 = 2; /* EDX */ + } + if (reg1 == 2 /* EDX */) + jitCompA000_storeRegCacheEdx(&w); + if (reg1 <= 3 /* EAX, EDX */) + jitCompA0001_movReg32EbpDisp(&w, reg1, 256 + src[6] * 32 + 0); /* MOV(reg1, [EBP+?]); */ + if (level < JITC_LV_FASTER) + jitCompA0001_checkLimit(&w, reg1, src[6]); + jitCompPutByte2(w.dst, 0x8b, reg0 << 3 | reg1); /* MOV(reg0, [reg1]); */ + if (reg0 == 0 /* EAX */) + jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + 0, 0); /* MOV([EBP+?], EAX); */ + for (i = 4; i < 32; i += 4) { + jitCompPutByte3(w.dst, 0x8b, 0x40 | reg1, i); /* MOV(EAX, [reg1+?]); */ + jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + i, 0 /* EAX */); /* MOV([EBP+?], EAX); */ + } + if (reg1 == 2 /* EDX */) + jitCompA000_loadRegCacheEdx(&w); + break; + + case 0x0b: /* PSMEM */ /* 完成 */ + i = jitCompGetImm32(src + 2); + if (i != 0x0001) w.err = JITC_ERR_BADTYPE; + if (level < JITC_LV_FASTER) { + jitCompA0001_checkType(&w, src[6], i, 1); // write + cmp0reg = -1; + } + reg0 = jitCompA000_selectPRegCache(src[1], 0 /* EAX */); + reg1 = jitCompA000_selectPRegCache(src[6], 2 /* EDX */); + // if (reg0 != 0 /* EAX */ && reg1 == 2 /* EDX */) /* これをやってはいけない!(by K, 2013.08.02) */ + // reg1 = 0; /* EAX */ + if (reg1 == 2 /* EDX */) + jitCompA000_storeRegCacheEdx(&w); + if (reg1 <= 3 /* EAX, EDX */) + jitCompA0001_movReg32EbpDisp(&w, reg1, 256 + src[6] * 32 + 0); /* MOV(reg1, [EBP+?]); */ + if (level < JITC_LV_FASTER) + jitCompA0001_checkLimit(&w, reg1, src[6]); + if (reg0 == 0 /* EAX */) + jitCompA0001_movReg32EbpDisp(&w, reg0, 256 + src[1] * 32 + 0); /* MOV(reg0, [EBP+?]); */ + jitCompPutByte2(w.dst, 0x89, reg0 << 3 | reg1); /* MOV([reg1], reg0); */ + for (i = 4; i < 32; i += 4) { + jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, 256 + src[1] * 32 + i); /* MOV(EAX, [EBP+?]); */ + jitCompPutByte3(w.dst, 0x89, 0x40 | reg1, i); /* MOV([reg1+?], EAX); */ + } + if (reg1 == 2 /* EDX */) + jitCompA000_loadRegCacheEdx(&w); + break; + + case 0x0e: /* PADD */ /* 完成 */ + if (level < JITC_LV_FASTER) { + jitCompA0001_checkType0(&w, src[6], jitCompGetImm32(src + 2), 2); // other, aliveテストはとりあえずしない. + cmp0reg = -1; + } + reg0 = jitCompA000_selectPRegCache(src[1], 0 /* EAX */); + reg1 = jitCompA000_selectPRegCache(src[6], -1 /* mem */); + if (reg1 < 0 /* mem */) + jitCompA0001_movReg32EbpDisp(&w, reg0, 256 + src[6] * 32 + 0); /* MOV(reg0, [EBP+?]); */ + if (reg1 >= 0 && reg0 != reg1) { + jitCompPutByte2(w.dst, 0x89, 0xc0 | reg1 << 3 | reg0); /* MOV(reg0, reg1); */ + } + i = jitCompGetImm32(src + 2); + j = -1; + if (i == 1) + j = 5; /* 32 */ + else { + i = jitCompA000_convTyp(i); + if (0x0002 <= i && i <= 0x0007) + j = (i - 0x0002) >> 1; + } + if (j < 0) { w.err = JITC_ERR_BADTYPE; goto err_w; } +#if (jitCompA0001_USE_R3F_IMM32 != 0) + if (src[7] == 0x3f) { + j = w.r3f << j; +#if (jitCompA0001_USE_R3F_IMM8 != 0) + if (-0x80 <= j && j <= 0x7f) { +#if (jitCompA0001_USE_R3F_INCDEC != 0) + if (j == 1) { jitCompPutByte1(w.dst, 0x40 | reg0); goto padd1; } /* INC */ + if (j == -1) { jitCompPutByte1(w.dst, 0x48 | reg0); goto padd1; } /* DEC */ +#endif + jitCompPutByte3(w.dst, 0x83, 0xc0 | reg0, j & 0xff); /* ADD(reg0, im8); */ + goto padd1; + } +#endif + if (reg0 == 0) { + jitCompPutByte1(w.dst, 0x05); /* ADD(reg0, ?); */ + } + else { + jitCompPutByte2(w.dst, 0x81, 0xc0 | reg0); /* ADD(reg0, ?); */ + } + jitCompPutImm32(&w, j); + goto padd1; + } +#endif + if (src[7] >= 0x40) w.err = JITC_ERR_REGNUM; + if (j == 0) { + reg1 = jitCompA000_selectRegCache(src[7], -1 /* mem */); + if (reg1 >= 0) { + jitCompPutByte2(w.dst, 0x01, 0xc0 | reg1 << 3 | reg0); /* ADD(reg0, reg1); */ + } + else { + jitCompPutByte1(w.dst, 0x03); /* ADD(reg0, [EBP+?]); */ + jitCompA0001_85DispN(&w, src[7] * 4, reg0); + } + } + else { + reg1 = jitCompA000_selectRegCache(src[7], -1 /* mem */); + reg2 = 2; /* EDX */ + jitCompA000_storeRegCacheEdx(&w); + if (reg1 < 0) + jitCompA0001_movReg32EbpDisp(&w, reg2, src[7] * 4); /* MOV(reg2, [EBP+?]); */ + if (reg1 >= 0 && reg1 != reg2) { + jitCompPutByte2(w.dst, 0x89, 0xc0 | reg1 << 3 | reg2); /* MOV(reg2, reg1); */ + } + jitCompPutByte3(w.dst, 0xc1, 0xe0 | reg2, j); /* SHL(reg2, ?); */ + jitCompPutByte2(w.dst, 0x01, 0xc0 | reg2 << 3 | reg0); /* ADD(reg0, reg2); */ + jitCompA000_loadRegCacheEdx(&w); + } +#if (jitCompA0001_USE_R3F_IMM32 != 0) + padd1: +#endif + if (reg0 == 0 /* EAX */) + jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + 0, reg0); /* MOV([EBP+?], reg0); */ + if (src[1] != src[6]) { + for (i = 4; i < 32; i += 4) { + jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, 256 + src[6] * 32 + i); /* MOV(EAX, [EBP+?]); */ + jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + i, 0 /* EAX */); /* MOV([EBP+?], EAX); */ + } + } + cmp0reg = -1; + break; + + case 0x0f: /* PDIF */ /* 未完成 */ + reg0 = jitCompA000_selectRegCache(src[1], 0 /* EAX */); + jitCompA000_storePRegCacheAll(&w); // 手抜き. + jitCompA0001_checkCompPtr(&w, src[6], src[7]); + jitCompA0001_movReg32EbpDisp(&w, reg0, 256 + src[6] * 32 + 0); /* MOV(reg0, [EBP+?]); */ + jitCompPutByte1(w.dst, 0x2b); /* SUB(EAX, [EBP+?]); */ + jitCompA0001_85DispN(&w, 256 + src[7] * 32 + 0, reg0); + i = jitCompA000_convTyp(jitCompGetImm32(src + 2)); + j = -1; + if (0x0002 <= i && i <= 0x0007) + j = (i - 0x0002) >> 1; + if (j < 0) { w.err = JITC_ERR_BADTYPE; goto err_w; } + if (j > 0) { + jitCompPutByte3(w.dst, 0xc1, 0xf8 | reg0, j); /* SAR(reg0,?); */ + } + if (reg0 == 0 /* EAX */) + jitCompA0001_movRxxEax(&w, src[1]); + cmp0reg = src[1]; cmp0lev = 1; + break; + + case 0x10: /* OR */ + case 0x11: /* XOR */ + case 0x12: /* AND */ + case 0x14: /* ADD */ + case 0x15: /* SUB */ + case 0x16: /* MUL */ + if (src[1] >= 0x3f) w.err = JITC_ERR_REGNUM; + reg0 = jitCompA000_selectRegCache(src[1], 0 /* EAX */); + reg1 = jitCompA000_selectRegCache(src[2], -1 /* mem */); +#if (jitCompA0001_USE_R3F_IMM32 != 0) + if (src[2] == 0x3f) { // SUBのみ該当. + if (*src != 0x15) w.err = JITC_ERR_REGNUM; + reg2 = jitCompA000_selectRegCache(src[3], -1 /* mem */); + if (reg2 >= 0) + jitCompA000_storeRegCacheAll(&w); + jitCompPutByte1(w.dst, 0xb8 | reg0); /* MOV(reg0, ?); */ + jitCompPutImm32(&w, w.r3f); + jitCompPutByte1(w.dst, 0x2b); + jitCompA0001_85DispN(&w, src[3] * 4, reg0); + if (reg0 == 0) + jitCompA0001_movRxxEax(&w, src[1]); + break; + } +#endif + if (reg1 < 0) { + jitCompA0001_movReg32EbpDisp(&w, reg0, src[2] * 4); /* MOV(reg0, [EBP+?]); */ + } + if (reg1 >= 0 && reg0 != reg1) { + jitCompPutByte2(w.dst, 0x89, 0xc0 | reg1 << 3 | reg0); /* MOV(reg0, reg1); */ + } + if (!(src[0] == 0x10 && src[3] == 0xff)) { // bugfix: hinted by Iris, 2013.06.26. thanks! + cmp0reg = src[1]; + cmp0lev = 1; + if (src[0] < 0x14) + cmp0lev = 2; + if (src[0] == 0x16) + cmp0reg = -1; + } + if (!(src[0] == 0x10 && src[3] == 0xff)) { +#if (jitCompA0001_USE_R3F_IMM32 != 0) + if (src[3] == 0x3f) { + if (*src == 0x16 && w.r3f == -1) { + jitCompPutByte2(w.dst, 0xf7, 0xd8 | reg0); /* NEG(reg0); */ + if (reg0 == 0) + jitCompA0001_movRxxEax(&w, src[1]); + break; + } +#if (jitCompA0001_USE_R3F_INCDEC != 0) + if ((*src == 0x14 && w.r3f == 1) || (*src == 0x15 && w.r3f == -1)) { + jitCompPutByte1(w.dst, 0x40 | reg0); /* INC(reg0); */ + if (reg0 == 0) + jitCompA0001_movRxxEax(&w, src[1]); + break; + } + if ((*src == 0x15 && w.r3f == 1) || (*src == 0x14 && w.r3f == -1)) { + jitCompPutByte1(w.dst, 0x48 | reg0); /* DEC(reg0); */ + if (reg0 == 0) + jitCompA0001_movRxxEax(&w, src[1]); + break; + } +#endif +#if (jitCompA0001_USE_R3F_IMM8 != 0) + if (-0x80 <= w.r3f && w.r3f <= 0x7f) { + if (*src != 0x16) { + static unsigned char basic_op_table_im8[] = { 0xc8, 0xf0, 0xe0, 0, 0xc0, 0xe8 }; + jitCompPutByte3(w.dst, 0x83, basic_op_table_im8[*src - 0x10] | reg0, w.r3f & 0xff); + } + else { + jitCompPutByte3(w.dst, 0x6b, 0xc0 | reg0 << 3 | reg0, w.r3f & 0xff); + } + if (reg0 == 0) + jitCompA0001_movRxxEax(&w, src[1]); + break; + } +#endif + if (reg0 == 0 /* EAX */) { + static unsigned char basic_op_table_im32_eax[] = { 0x0d, 0x35, 0x25, 0, 0x05, 0x2d, 0xc0 }; + if (*src == 0x16) { jitCompPutByte1(w.dst, 0x69); } + jitCompPutByte1(w.dst, basic_op_table_im32_eax[*src - 0x10]); + } + else { + if (*src != 0x16) { + static unsigned char basic_op_table_im32_reg[] = { 0xc8, 0xf0, 0xe0, 0, 0xc0, 0xe8 }; + jitCompPutByte2(w.dst, 0x81, basic_op_table_im32_reg[*src - 0x10] | reg0); + } + else { + jitCompPutByte2(w.dst, 0x69, 0xc0 | reg0 << 3 | reg0); + } + } + jitCompPutImm32(&w, w.r3f); + if (reg0 == 0) + jitCompA0001_movRxxEax(&w, src[1]); + break; + } +#endif + reg1 = jitCompA000_selectRegCache(src[3], -1 /* mem */); + if (src[3] >= 0x40) w.err = JITC_ERR_REGNUM; + if (*src != 0x16) { + if (reg1 >= 0) { + static unsigned char basic_op_table_rr[] = { 0x09, 0x31, 0x21, 0, 0x01, 0x29 }; /* op(reg,reg); */ + jitCompPutByte2(w.dst, basic_op_table_rr[*src - 0x10], 0xc0 | reg1 << 3 | reg0); + } + else { + static unsigned char basic_op_table_rm[] = { 0x0b, 0x33, 0x23, 0, 0x03, 0x2b, 0xaf }; /* op(reg,mem); */ + jitCompPutByte1(w.dst, basic_op_table_rm[*src - 0x10]); + jitCompA0001_85DispN(&w, src[3] * 4, reg0); + } + } + else { + if (reg1 >= 0) { + jitCompPutByte3(w.dst, 0x0f, 0xaf, 0xc0 | reg0 << 3 | reg1); + } + else { + jitCompPutByte2(w.dst, 0x0f, 0xaf); + jitCompA0001_85DispN(&w, src[3] * 4, reg0); + } + } + } + if (reg0 == 0) + jitCompA0001_movRxxEax(&w, src[1]); + break; + + case 0x18: /* SHL */ + case 0x19: /* SAR */ + if (src[1] >= 0x3f) w.err = JITC_ERR_REGNUM; + if (src[3] >= 0x40) w.err = JITC_ERR_REGNUM; +#if (jitCompA0001_USE_R3F_IMM32 != 0) + if (src[3] == 0x3f) { + reg0 = jitCompA000_selectRegCache(src[1], 0 /* EAX */); + reg1 = jitCompA000_selectRegCache(src[2], -1 /* mem */); + if (src[1] >= 0x3f) w.err = JITC_ERR_REGNUM; + if (reg1 == -1) + jitCompA0001_movReg32EbpDisp(&w, reg0, src[2] * 4); /* MOV(reg1, [EBP+?]); */ + else { + if (reg0 != reg1) { + jitCompPutByte2(w.dst, 0x89, 0xc0 | reg1 << 3 | reg0); /* MOV(reg0, reg1); */ + } + } + if (*src == 0x18) { jitCompPutByte3(w.dst, 0xc1, 0xe0 | reg0, w.r3f); } /* SHL(reg0, im8); */ + if (*src == 0x19) { jitCompPutByte3(w.dst, 0xc1, 0xf8 | reg0, w.r3f); } /* SAR(reg0, im8); */ + if (reg0 == 0 /* EAX */) + jitCompA0001_movRxxEax(&w, src[1]); + cmp0reg = src[1]; + cmp0lev = 1; + break; + } +#endif + jitCompA000_storeRegCacheAll(&w); // 手抜き. + jitCompA0001_movReg32EbpDisp(&w, 1 /* ECX */, src[3] * 4); /* MOV(ECX, [EBP+?]); */ +#if (jitCompA0001_USE_R3F_IMM32 != 0) + if (src[2] == 0x3f) { + jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, ?); */ + jitCompPutImm32(&w, w.r3f); + } + else { + jitCompA0001_movEaxRxx(&w, src[2]); + } +#else + jitCompA0001_movEaxRxx(&w, src[2]); +#endif + if (*src == 0x18) { jitCompPutByte2(w.dst, 0xd3, 0xe0); } /* SHL(EAX, CL); */ + if (*src == 0x19) { jitCompPutByte2(w.dst, 0xd3, 0xf8); } /* SAR(EAX, CL); */ + jitCompA0001_movRxxEax(&w, src[1]); + jitCompA000_loadRegCacheAll(&w); // 手抜き. + cmp0reg = src[1]; + cmp0lev = 1; + break; + + case 0x1a: /* DIV */ + case 0x1b: /* MOD */ + if (src[1] >= 0x3f) w.err = JITC_ERR_REGNUM; + if (src[2] >= 0x40) w.err = JITC_ERR_REGNUM; + if (src[3] >= 0x40) w.err = JITC_ERR_REGNUM; + jitCompA000_storeRegCacheAll(&w); // 手抜き. +#if (jitCompA0001_USE_R3F_IMM32 != 0) + if (src[3] == 0x3f) { + jitCompPutByte1(w.dst, 0xb8 | 1); /* MOV(ECX, ?); */ + jitCompPutImm32(&w, w.r3f); + } + else { + jitCompA0001_movReg32EbpDisp(&w, 1 /* ECX */, src[3] * 4); /* MOV(ECX, [EBP+?]); */ + } + if (src[2] == 0x3f) { + jitCompPutByte1(w.dst, 0xb8 | 0); /* MOV(EAX, ?); */ + jitCompPutImm32(&w, w.r3f); + } + else { + jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, src[2] * 4); /* MOV(EAX, [EBP+?]); */ + } +#else + jitCompA0001_movReg32EbpDisp(&w, 1 /* ECX */, src[3] * 4); /* MOV(ECX, [EBP+?]); */ + jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, src[2] * 4); /* MOV(EAX, [EBP+?]); */ +#endif + jitCompPutByte1(w.dst, 0x99); /* CDQ(); */ + /* ECXがゼロではないことを確認すべき */ + jitCompPutByte2(w.dst, 0xf7, 0xf9); /* IDIV(ECX); */ + if (*src == 0x1a) { jitCompA0001_movEbpDispReg32(&w, src[1] * 4, 0 /* EAX */); } + if (*src == 0x1b) { jitCompA0001_movEbpDispReg32(&w, src[1] * 4, 2 /* EDX */); } + jitCompA000_loadRegCacheAll(&w); // 手抜き. + cmp0reg = -1; + break; + + case 0x1c: /* PLMT0 */ + case 0x1d: /* PLMT1 */ + if (src[1] >= 0x40 || src[2] >= 0x40) w.err = JITC_ERR_PREGNUM; + if (level < JITC_LV_FASTEST) { + cmp0reg = -1; + if (level < JITC_LV_FASTER) { + // typ が一致していることを確認. + // plsとliveSignが一致していることを確認. + + // preg1はp0 <= p <= p1 を満たしているか?. + // 新しいp0/p1は古いp0〜p1に適合しているか?. + + } + } + + case 0x1e: /* PCP */ /* 未完成(p1まで完成) */ + if (src[1] >= 0x40 || src[2] >= 0x40) w.err = JITC_ERR_PREGNUM; + if (src[2] == 0x3f) w.err = JITC_ERR_PREGNUM; + if (src[1] != 0x3f) { + /* src[2] == 0xff の場合に対応できてない */ + jitCompA000_storePRegCacheAll(&w); // 手抜き. + for (i = 0; i < 32; i += 4) { + jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, 256 + src[2] * 32 + i); /* MOV(EAX, [EBP+?]); */ + jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + i, 0 /* EAX */); /* MOV([EBP+?], EAX); */ + } + jitCompA000_loadPRegCacheAll(&w); // 手抜き. + } + else { + if (level < JITC_LV_FASTER) { + jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, 256 + src[2] * 32 + 4); /* MOV(EAX, [EBP+?]); */ /* typ */ + jitCompPutByte3(w.dst, 0x83, 0xf8, 0); /* CMP(EAX, 0); */ + jitCompPutByte2(w.dst, 0x0f, 0x85); /* JNE */ + jitCompPutImm32(&w, errfnc - (w.dst + 4)); + /* セキュリティチェックが足りてない!(aliveとか) */ + } + reg0 = 0; /* EAX */ + jitCompA000_storePRegCacheAll(&w); // 手抜き. + jitCompA0001_movReg32EbpDisp(&w, reg0, 256 + src[2] * 32 + 0); /* MOV(EAX, [EBP+?]); */ + if (level < JITC_LV_FASTER) { + jitCompPutByte1(w.dst, 0x3b); /* CMP(reg0, [EBP+?]); */ + jitCompA0001_85DispN(&w, 256 + src[2] * 32 + 8, reg0); /* p0 */ + jitCompPutByte2(w.dst, 0x0f, 0x85); /* JNE */ + jitCompPutImm32(&w, errfnc - (w.dst + 4)); + } + jitCompPutByte2(w.dst, 0xff, 0xe0); /* JMP(EAX); */ + } + break; + + case 0x1f: /* PCST */ + if (jitCompGetImm32(src + 2) == 0) { + if (level < JITC_LV_FASTER) + jitCompA0001_checkType0(&w, src[6], jitCompGetImm32(src + 7), 2); + jitCompA000_storePRegCacheAll(&w); // 手抜き. + for (i = 0; i < 32 - 4; i += 4) { + jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, 256 + src[6] * 32 + i); /* MOV(EAX, [EBP+?]); */ + if (i == 4) { + jitCompPutByte1(w.dst, 0x0d); /* OR(EAX, ?); */ + jitCompPutImm32(&w, 0x80000000); + } + jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + i, 0 /* EAX */); /* MOV([EBP+?], EAX); */ + } + jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, ?); */ + jitCompPutImm32(&w, debugInfo1); + jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + 28, 0 /* EAX */); /* MOV([EBP+?], EAX); */ + jitCompA000_loadPRegCacheAll(&w); // 手抜き. + cmp0reg = -1; + break; + } + if (jitCompGetImm32(src + 7) == 0) { + jitCompA000_storePRegCacheAll(&w); // 手抜き. + for (i = 0; i < 32 - 4; i += 4) { + jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, 256 + src[6] * 32 + i); /* MOV(EAX, [EBP+?]); */ + if (i == 4) { + jitCompPutByte1(w.dst, 0x25); /* AND(EAX, ?); */ + jitCompPutImm32(&w, 0x7fffffff); + } + jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + i, 0 /* EAX */); /* MOV([EBP+?], EAX); */ + } + if (level < JITC_LV_FASTER) { + jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, 256 + src[6] * 32 + 28); /* MOV(EAX, [EBP+?]); */ + jitCompPutByte1(w.dst, 0x3d); /* CMP(EAX, ?); */ + jitCompPutImm32(&w, debugInfo1); + jitCompPutByte2(w.dst, 0x74, 8); /* JE */ + jitCompPutByte2(w.dst, 0x31, 0xc0); /* XOR(EAX, EAX); (2) */ + jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + 0, 0 /* EAX */); /* MOV([EBP+?], EAX); (1+1+4) */ + } + jitCompA000_loadPRegCacheAll(&w); // 手抜き. + cmp0reg = -1; + break; + } + w.err = JITC_ERR_OPECODE; + goto err_w; + + case 0x20: /* CMPE */ + case 0x21: /* CMPNE */ + case 0x22: /* CMPL */ + case 0x23: /* CMPGE */ + case 0x24: /* CMPLE */ + case 0x25: /* CMPG */ + case 0x26: /* TSTZ */ + case 0x27: /* TSTNZ */ + reg0 = jitCompA000_selectRegCache(src[2], 0 /* EAX */); + reg1 = jitCompA000_selectRegCache(src[3], -1 /* mem */); + if (src[1] == 0x3f) { + /* 特殊構文チェック */ + if (w.prefix != 0) { w.err = JITC_ERR_PREFIX; goto err_w; } + if (src[4] != 0x04 || src[5] != 0x3f || src[6] != 0x03 || src[7] != 0x3f) { + w.err = JITC_ERR_IDIOM; goto err_w; + } + } + if (reg0 == 0) + jitCompA0001_movEaxRxx(&w, src[2]); +#if (jitCompA0001_USE_R3F_IMM32 != 0) + if (src[3] == 0x3f) { +#if (jitCompA0001_OPTIMIZE_CMP != 0) + if ((*src <= 0x25 && w.r3f == 0) || (*src >= 0x26 && w.r3f == -1)) { + i = 0; + if (cmp0reg == src[2]) { + if (cmp0lev >= 1 && (src[0] == 0x20 || src[0] == 0x21 || src[0] == 0x26 || src[0] == 0x27)) + i = 1; + if (cmp0lev >= 2 && (src[0] == 0x22 || src[0] == 0x23 || src[0] == 0x24 || src[0] == 0x25)) + i = 1; + } + if (i == 0) { + jitCompPutByte2(w.dst, 0x85, 0xc0 | reg0 << 3 | reg0); /* TEST(reg0, reg0); */ + } + cmp0reg = src[2]; + cmp0lev = 2; + goto cmpcc1; + } +#endif +#if (jitCompA0001_USE_R3F_IMM8 != 0) + if (-0x80 <= w.r3f && w.r3f <= 0x7f && *src <= 0x25) { + jitCompPutByte3(w.dst, 0x83, 0xf8 | reg0, w.r3f); + goto cmpcc1; + } +#endif + if (reg0 == 0) { + if (*src <= 0x25) { jitCompPutByte1(w.dst, 0x3d); } + if (*src >= 0x26) { jitCompPutByte1(w.dst, 0xa9); } + } + else { + if (*src <= 0x25) { jitCompPutByte2(w.dst, 0x81, 0xf8 | reg0); } + if (*src >= 0x26) { jitCompPutByte2(w.dst, 0xf7, 0xc0 | reg0); } + } + jitCompPutImm32(&w, w.r3f); + goto cmpcc1; + } +#endif + if (src[3] >= 0x40) w.err = JITC_ERR_PREGNUM; + if (reg1 >= 0) { + if (*src <= 0x25) { jitCompPutByte2(w.dst, 0x39, 0xc0 | reg1 << 3 | reg0); } + if (*src >= 0x26) { jitCompPutByte2(w.dst, 0x85, 0xc0 | reg1 << 3 | reg0); } + } + else { + if (*src <= 0x25) { jitCompPutByte1(w.dst, 0x3b); } + if (*src >= 0x26) { jitCompPutByte1(w.dst, 0x85); } + jitCompA0001_85DispN(&w, src[3] * 4, reg0); + } + cmpcc1: + if (w.err != 0) goto err_w; + static unsigned char cmpcc_table0[] = { + 0x04, 0x05, 0x0c, 0x0d, 0x0e, 0x0f, 0x04, 0x05, /* CMPcc, TSTcc */ + 0x04, 0x05, 0x02, 0x03, 0x06, 0x07 /* PCMPcc */ + }; +#if (jitCompA0001_USE_R3F_CMPJMP != 0) + if (src[1] == 0x3f) { + /* 特殊構文を利用した最適化 */ + jitCompPutByte2(w.dst, 0x0f, 0x80 | cmpcc_table0[*src - 0x20]); + src += 6; + i = jitCompGetLabelNum(&w, src + 2); + if ((flags & JITC_PHASE1) != 0 && w.err != 0) { + if (label[i].opt == 0) { w.err = JITC_ERR_LABELNODEF; goto err_w; } + // if (label[i].typ != 1) { w.err = JITC_ERR_LABELTYP; goto err_w; } + } + j = 0; + if ((flags & JITC_PHASE1) != 0 || (((flags & JITC_PHASE1) == 0) && label[i].opt != 0)) + j = label[i].p - (w.dst + 4); + jitCompPutImm32(&w, j); +#if (jitCompA0001_OPTIMIZE_JMP != 0) + if (-128 - 4 <= j && j < 0) { + j += 4; + w.dst -= 6; + jitCompPutByte2(w.dst, w.dst[1] ^ 0xf0, j & 0xff); + } +#endif + src += 6; + if (w.err != 0) goto err_w; + continue; + } +#endif + /* 一般的なJITC */ + reg0 = jitCompA000_selectRegCache(src[1], 0 /* EAX */); + jitCompPutByte3(w.dst, 0x0f, 0x90 | cmpcc_table0[*src - 0x20], 0xc0 | reg0); /* SETcc(BYTE(reg0)); */ + jitCompPutByte3(w.dst, 0x0f, 0xb6, 0xc0 | reg0 << 3 | reg0); /* MOVZX(reg0, BYTE(reg0)); */ + jitCompPutByte2(w.dst, 0xf7, 0xd8 | reg0); /* NEG(reg0); */ + if (reg0 == 0) + jitCompA0001_movRxxEax(&w, src[1]); + cmp0reg = src[2]; + cmp0lev = 1; + break; + + case 0x28: /* PCMPE */ + case 0x29: /* PCMPNE */ + case 0x2a: /* PCMPL */ + case 0x2b: /* PCMPGE */ + case 0x2c: /* PCMPLE */ + case 0x2d: /* PCMPG */ + if (src[1] == 0x3f) { + /* 特殊構文チェック */ + if (w.prefix != 0) { w.err = JITC_ERR_PREFIX; goto err_w; } + if (src[4] != 0x04 || src[5] != 0x3f || src[6] != 0x03 || src[7] != 0x3f) { + w.err = JITC_ERR_IDIOM; goto err_w; + } + } + if (src[2] >= 0x40) w.err = JITC_ERR_PREGNUM; + jitCompA000_storePRegCacheAll(&w); // 手抜き. + if (src[3] != 0xff) + jitCompA0001_checkCompPtr(&w, src[2], src[3]); + jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, 256 + src[2] * 32 + 0); /* MOV(EAX, [EBP+?]); */ + if (src[3] != 0xff) { + jitCompPutByte1(w.dst, 0x3b); /* CMP(EAX, [EBP+?]); */ + jitCompA0001_85DispN(&w, 256 + src[3] * 32 + 0, 0); + } + else { + /* ヌルポインタとの比較はこれでいいのか?たぶんよくない */ + jitCompPutByte3(w.dst, 0x83, 0xf8, 0x00); /* CMP(EAX, 0); */ + } + cmp0reg = -1; + goto cmpcc1; + + case 0x30: /* talloc(old:F4) */ + case 0x31: /* tfree(old:F5) */ + case 0x32: /* malloc(old:F6) */ + case 0x33: /* mfree(old:F7) */ + jitCompA000_storeRegCacheAll(&w); // 手抜き. + jitCompA000_storePRegCacheAll(&w); // 手抜き. + jitCompPutByte2(w.dst, 0x6a, src[3]); /* PUSH(?); */ + jitCompPutByte2(w.dst, 0x6a, src[2]); /* PUSH(?); */ + jitCompPutByte2(w.dst, 0x6a, src[1]); /* PUSH(?); */ + jitCompPutByte1(w.dst, 0x55); /* PUSH(EBP); */ + jitCompPutByte1(w.dst, 0xe8); + if (*src == 0x30) j = ((unsigned char *)&funcf4) - (w.dst + 4); + if (*src == 0x31) j = ((unsigned char *)&funcf5) - (w.dst + 4); + if (*src == 0x32) j = ((unsigned char *)&funcf6) - (w.dst + 4); + if (*src == 0x33) j = ((unsigned char *)&funcf7) - (w.dst + 4); + jitCompPutImm32(&w, j); + jitCompPutByte3(w.dst, 0x83, 0xc4, 0x10); /* ADD(ESP,16); */ + jitCompA000_loadRegCacheAll(&w); // 手抜き. + jitCompA000_loadPRegCacheAll(&w); // 手抜き. + cmp0reg = -1; + break; + + case 0x34: /* data (暫定) */ + cmp0reg = -1; + if (w.prefix != 0) { w.err = JITC_ERR_PREFIX; goto err_w; } + int k = jitCompGetImm32(&src[1]), tmpData, bitCount, dataWidth = jitCompA000_dataWidth(k); + if (lastlabel >= 0 && label[lastlabel].typ == 0) + label[lastlabel].typ = k; + if (k != 1) { + i = jitCompA000_convTyp(k); + if (i < 2 || i > 7) { w.err = JITC_ERR_BADTYPE; goto err_w; } + } + j = jitCompGetImm32(&src[5]); + oldsrc = src; + src += 9; + if (k != 1) { + bitCount = 7; + while (j > 0) { + if (src >= src1) { w.err = JITC_ERR_SRC1; src = oldsrc; goto err_w; } + if (w.dst + 256 > dst1) { w.err = JITC_ERR_DST1; src = oldsrc; goto err_w; } + tmpData = 0; + for (k = 0; k < dataWidth; k++) { + tmpData = tmpData << 1 | ((*src >> bitCount) & 1); + bitCount--; + if (bitCount < 0) { + bitCount = 7; + src++; + } + } + if ((i & 1) == 0 && dataWidth <= 31 && (tmpData >> (dataWidth - 1)) != 0) { + tmpData -= 1 << dataWidth; + } + if (i == 2 || i == 3) { jitCompPutByte1(w.dst, tmpData & 0xff); } + if (i == 4 || i == 5) { jitCompPutByte2(w.dst, tmpData & 0xff, (tmpData >> 8) & 0xff); } + if (i == 6 || i == 7) { jitCompPutByte4(w.dst, tmpData & 0xff, (tmpData >> 8) & 0xff, (tmpData >> 16) & 0xff, (tmpData >> 24) & 0xff); } + j--; + } + } + else { + while (j > 0) { + if (src >= src1) { w.err = JITC_ERR_SRC1; src = oldsrc; goto err_w; } + if (w.dst + 256 > dst1) { w.err = JITC_ERR_DST1; src = oldsrc; goto err_w; } + i = jitCompGetImm32(src); + src += 4; + if ((flags & JITC_PHASE1) != 0 && w.err == 0) { + if (label[i].opt == 0) { w.err = JITC_ERR_LABELNODEF; goto err_w; } + } + jitCompPutImm32(&w, (int)label[i].p); + jitCompPutImm32(&w, label[i].typ); + jitCompPutImm32(&w, (int)label[i].p); + jitCompPutImm32(&w, (int)label[i].p1); + jitCompPutImm32(&w, 0); /* liveSign */ + jitCompPutImm32(&w, 2320); /* pls */ + jitCompPutImm32(&w, 0); + jitCompPutImm32(&w, 0); + j--; + } + } + if (lastlabel >= 0 && label[lastlabel].p1 < w.dst) + label[lastlabel].p1 = w.dst; + continue; + + case 0x3c: /* ENTER */ + jitCompA000_storeRegCacheAll(&w); // 手抜き. + jitCompA000_storePRegCacheAll(&w); // 手抜き. + jitCompPutByte2(w.dst, 0x6a, src[6]); /* PUSH(?); */ + jitCompPutByte2(w.dst, 0x6a, src[5]); /* PUSH(?); */ + jitCompPutByte2(w.dst, 0x6a, src[4] & 0x0f); /* PUSH(?); */ + jitCompPutByte2(w.dst, 0x6a, (src[4] >> 4) & 0x0f); /* PUSH(?); */ + jitCompPutByte2(w.dst, 0x6a, src[3]); /* PUSH(?); */ + jitCompPutByte2(w.dst, 0x6a, src[2]); /* PUSH(?); */ + jitCompPutByte2(w.dst, 0x6a, src[1]); /* PUSH(?); */ + jitCompPutByte1(w.dst, 0x55); /* PUSH(EBP); */ + jitCompPutByte1(w.dst, 0xe8); + j = ((unsigned char *)&func3c) - (w.dst + 4); + jitCompPutImm32(&w, j); + jitCompPutByte3(w.dst, 0x83, 0xc4, 0x20); /* ADD(ESP,32); */ + jitCompA000_loadRegCacheAll(&w); // 手抜き. + jitCompA000_loadPRegCacheAll(&w); // 手抜き. + cmp0reg = -1; + break; + + case 0x3d: /* LEAVE */ + jitCompA000_storeRegCacheAll(&w); // 手抜き. + jitCompA000_storePRegCacheAll(&w); // 手抜き. + jitCompPutByte2(w.dst, 0x6a, src[6]); /* PUSH(?); */ + jitCompPutByte2(w.dst, 0x6a, src[5]); /* PUSH(?); */ + jitCompPutByte2(w.dst, 0x6a, src[4] & 0x0f); /* PUSH(?); */ + jitCompPutByte2(w.dst, 0x6a, (src[4] >> 4) & 0x0f); /* PUSH(?); */ + jitCompPutByte2(w.dst, 0x6a, src[3]); /* PUSH(?); */ + jitCompPutByte2(w.dst, 0x6a, src[2]); /* PUSH(?); */ + jitCompPutByte2(w.dst, 0x6a, src[1]); /* PUSH(?); */ + jitCompPutByte1(w.dst, 0x55); /* PUSH(EBP); */ + jitCompPutByte1(w.dst, 0xe8); + j = ((unsigned char *)&func3d) - (w.dst + 4); + jitCompPutImm32(&w, j); + jitCompPutByte3(w.dst, 0x83, 0xc4, 0x20); /* ADD(ESP,32); */ + jitCompA000_loadRegCacheAll(&w); // 手抜き. + jitCompA000_loadPRegCacheAll(&w); // 手抜き. + cmp0reg = -1; + break; + + case 0xfe: /* remark */ + if (src[1] == 0x01 && src[2] == 0x00) { // DBGINFO1 + if (level <= JITC_LV_SLOWER) { + jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, ?); */ + jitCompPutImm32(&w, debugInfo1); + jitCompA0001_movEbpDispReg32(&w, 2304 + 4, 0 /* EAX */); /* MOV(debugInfo1, EAX); */ + } + } + if (src[1] == 0x01 && src[2] == 0x03) { // DBGINFO1CLR + if (level <= JITC_LV_SLOWER) { + jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, ?); */ + jitCompPutImm32(&w, -1); + jitCompA0001_movEbpDispReg32(&w, 2304 + 4, 0 /* EAX */); /* MOV(debugInfo1, EAX); */ + } + } + if (src[1] == 0x05 && src[2] == 0x00) { // DBGINFO0 + if (level <= JITC_LV_SLOWEST) { + debugInfo0 = jitCompGetImm32(src + 3); + // jitCompPutByte1(w.dst, 0xbf); /* MOV(EDI, ?); */ + // jitCompPutImm32(&w, debugInfo0); + jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, ?); */ + jitCompPutImm32(&w, debugInfo0); + jitCompA0001_movEbpDispReg32(&w, 2304 + 0, 0 /* EAX */); /* MOV(debugInfo0, EAX); */ + } + } + break; + + default: + w.err = JITC_ERR_OPECODE; + goto err_w; + } + if (w.err != 0) goto err_w; + jitCompA0001_fixPrefix(&w); + if (w.err != 0) goto err_w; + src += jitCompCmdLen(src); + } + if (enter0 != NULL) { + j = w.dst - (enter0 + 4); + enter0[0] = j & 0xff; + enter0[1] = (j >> 8) & 0xff; + enter0[2] = (j >> 16) & 0xff; + enter0[3] = (j >> 24) & 0xff; + } + if ((flags & JITC_NOSTARTUP) == 0) { + jitCompA000_storeRegCacheAll(&w); + jitCompA000_storePRegCacheAll(&w); + jitCompPutByte1(w.dst, 0x61); /* POPAD(); */ + } + if ((flags & JITC_PHASE1) != 0) + return w.dst - dst00; + return 0; + +err_w: + if ((w.err & JITC_ERR_PHASE0ONLY) != 0) { + if ((flags & JITC_PHASE1) == 0) + w.err &= ~JITC_ERR_PHASE0ONLY; + } + if (w.err == (JITC_ERR_MASK & JITC_ERR_REGNUM)) errmsg = "reg-number error"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_DST1)) errmsg = "dst1 error"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_OPECODE)) errmsg = "opecode error"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_LABELNUM)) errmsg = "label number too large"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_LABELREDEF)) errmsg = "label redefine"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_PREFIX)) { errmsg = "prefix redefine"; w.dst -= 2; } + if (w.err == (JITC_ERR_MASK & JITC_ERR_LABELNODEF)) errmsg = "label not defined"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_LABELTYP)) errmsg = "label type error"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_IDIOM)) errmsg = "idiom error"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_PREGNUM)) errmsg = "preg-number error"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_SRC1)) errmsg = "src1 error"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_BADTYPE)) errmsg = "bad type code"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_PREFIXFAR)) errmsg = "prefix internal error"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_INTERNAL)) errmsg = "general internal error"; + if (*errmsg != '\0') { + fprintf(stderr, "JITC: %s at %06X (debugInfo0=%d)\n ", errmsg, src - src0, debugInfo0); + for (i = 0; i < 16; i++) + fprintf(stderr, "%02X ", src[i]); + static char *table[0x30] = { + "NOP", "LB", "LIMM", "PLIMM", "CND", "??", "??", "??", + "LMEM", "SMEM", "PLMEM", "PSMEM", "LEA", "??", "PADD", "PDIF", + "CP/OR", "XOR", "AND", "??", "ADD", "SUB", "MUL", "??", + "SHL", "SAR", "DIV", "MOD", "PLMT0", "PLMT1", "PCP", "PCST", + "CMPE", "CMPNE", "CMPL", "CMPGE", "CMPLE", "CMPG", "TSTZ", "TSTNZ", + "PCMPE", "PCMPNE", "PCMPL", "PCMPGE", "PCMPLE", "PCMPG", "??", "EXT" }; + errmsg = "??"; + if (*src < 0x30) errmsg = table[*src]; + fprintf(stderr, "(%s)\n", errmsg); + } + return -1; +} + +unsigned char *jitCompCallFunc(unsigned char *dst, void *func) +{ + struct JitCompWork w; + w.dst = dst; + jitCompA000_storeRegCacheAll(&w); + jitCompA000_storePRegCacheAll(&w); + jitCompPutByte1(w.dst, 0x60); /* PUSHAD(); */ + jitCompPutByte1(w.dst, 0x50); /* PUSH(EAX); */ /* for 16byte-align(win32では不要なのだけど、MacOSには必要らしい) */ + jitCompPutByte1(w.dst, 0x55); /* PUSH(EBP); */ + jitCompPutByte1(w.dst, 0xe8); /* CALL(func); */ + int j = ((unsigned char *)func) - (w.dst + 4); + + //この関数の中では結局w->dstしか参照していない + jitCompPutImm32(&w, j); + + jitCompPutByte1(w.dst, 0x58); /* POP(EAX); */ /* (win32では不要なのだけど、MacOSには必要らしい) */ + jitCompPutByte1(w.dst, 0x58); /* POP(EAX); */ + jitCompPutByte1(w.dst, 0x61); /* POPAD(); */ + jitCompA000_loadRegCacheAll(&w); + jitCompA000_loadPRegCacheAll(&w); + jitCompA0001_movReg32EbpDisp(&w, 0 /* EAX */, 256 + 0x30 * 32 + 0); /* MOV(EAX, [EBP+?]); */ + jitCompPutByte2(w.dst, 0xff, 0xe0); /* JMP(EAX); */ + return w.dst; +} + +unsigned char *jitCompInit(unsigned char *dst) +{ + errfnc = dst; + return jitCompCallFunc(dst, &errHndl); +} + +void func3c(char *ebp, int opt, int r1, int p1, int lenR, int lenP, int r0, int p0) +{ + HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); + int i, *pi; + HOSECPU_PointerRegisterEntry *pp; + if (r->junkStack + 2048 > r->junkStack1) (*(r->errHndl))(r); + pi = (void *)r->junkStack; r->junkStack += r1 * 4; + for (i = 0; i < r1; i++) + pi[i] = r->ireg[i]; + pp = (void *)r->junkStack; r->junkStack += p1 * 32; + for (i = 0; i < p1; i++) + pp[i] = r->preg[i]; + pp = (void *)r->junkStack; r->junkStack += 32; + *pp = r->preg[0x30]; + pi = (void *)r->junkStack; r->junkStack += 4; + *pi = opt << 16 | r1 << 8 | p1; + for (i = 0; i < lenR; i++) + r->ireg[r0 + i] = r->ireg[0x30 + i]; + for (i = 0; i < lenP; i++) + r->preg[p0 + i] = r->preg[0x31 + i]; + return; +} + +void func3d(char *ebp, int opt, int r1, int p1, int lenR, int lenP, int r0, int p0) +{ + HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); + int i; + r->junkStack -= 4; + r->junkStack -= 32; + HOSECPU_PointerRegisterEntry *pp = (void *)r->junkStack; + r->preg[0x30] = *pp; + r->junkStack -= p1 * 32; pp = (void *)r->junkStack; + for (i = 0; i < p1; i++) + r->preg[i] = pp[i]; + r->junkStack -= r1 * 4; int *pi = (void *)r->junkStack; + for (i = 0; i < r1; i++) + r->ireg[i] = pi[i]; + return; +} + +void funcf4(char *ebp, int pxx, int typ, int len) +{ + HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); + int width = jitCompA000_dataWidth(jitCompA000_convTyp(r->ireg[typ])) >> 3; + if (width < 0 || r->ireg[len] < 0) + (*(r->errHndl))(r); + void *p = r->junkStack; + if (r->junkStack + width * r->ireg[len] + 256 > r->junkStack1) (*(r->errHndl))(r); + r->junkStack += width * r->ireg[len]; + r->preg[pxx].p = p; + r->preg[pxx].typ = r->ireg[typ]; + r->preg[pxx].p0 = p; + r->preg[pxx].p1 = (void *)r->junkStack; + int *pi = (int *)r->junkStack; + *pi = width * r->ireg[len]; + r->junkStack += sizeof (int); + if (r->ireg[typ] == 1) { + int i, i1 = (width * r->ireg[len]) >> 2; + pi = p; + for (i = 0; i < i1; i++) + pi[i] = 0; + } + return; +} + +void funcf5(char *ebp, int pxx, int typ, int len) +{ + // pxxはダミーで参照されない + HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); + r->junkStack -= sizeof (int); + int *pi = (int *)r->junkStack; + r->junkStack -= *pi; +#if 0 + int width = jitCompA000_dataWidth(r->ireg[typ]); + void *p = r->junkStack; + r->junkStack -= width * r->ireg[len]; +#endif + return; +} + +void funcf6(char *ebp, int pxx, int typ, int len) +{ + HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); + int width = jitCompA000_dataWidth(jitCompA000_convTyp(r->ireg[typ])) >> 3; + if (width < 0 || r->ireg[len] < 0) + (*(r->errHndl))(r); + void *p = malloc(width * r->ireg[len]); + r->preg[pxx].p = p; + r->preg[pxx].typ = r->ireg[typ]; + r->preg[pxx].p0 = p; + r->preg[pxx].p1 = (unsigned char *)p + width * r->ireg[len]; + if (r->ireg[typ] == 1) { + int i, i1 = (width * r->ireg[len]) >> 2, *pi; + pi = p; + for (i = 0; i < i1; i++) + pi[i] = 0; + for (i = 1; i < i1; i += 8) + pi[i] |= -1; + } + return; +} + +void funcf7(char *ebp, int pxx, int typ, int len) +{ + // typとlenはダミーで参照されない + HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); + free(r->preg[pxx].p); + return; +} + +void errHndl(HOSECPU_RuntimeEnvironment *r) +{ + r = (HOSECPU_RuntimeEnvironment *) (((char *)r) - jitCompA0001_EBP128); + (*(r->errHndl))(r); + // ここに帰ってきてはいけない. +} + +/* + * jitcの出力コードをひとまとめにする関数を作成しその中身をjitCompile()で生成 + * + * qq : 出力バイナリの書き込み位置のアドレスへの参照(書き込み位置を呼び出しに反映させるため参照渡しにする) + * q1 : 出力バイナリの書き込み位置のアドレスの最大値 + * p0 : (*.ose)バイナリの読み込み位置のアドレス(ヘッダ部除去済) + * p1 : (*.ose)バイナリの読み込み位置の取りうる最大値 + * (ただし、「確保したメモリ」の最大値なのでこれより手前にゴミデータが入っているかもしれない) + * ret=1 : ヘッダのエラー + * ret=2 : jitコンパイルエラー + */ +int jitc0(unsigned char **qq, unsigned char *q1, const unsigned char *p0, const unsigned char *p1, int level, HOSECPU_LabelListTag *label) +{ + unsigned char *q = *qq; + if (p0[0] != 0x05 || p0[1] != SIGN1) // OSECPUのヘッダ (05E1) を確認 + return 1; + + *q++ = 0x55; /* PUSH(EBP); */ + *q++ = 0x8b; *q++ = 0x6c; *q++ = 0x24; *q++ = 0x08; /* MOV(EBP,[ESP+8]); */ + + int i; + for (i = 0; i < JITC_MAXLABELS; i++) + label[i].opt = 0; + + // 以下のjitCompile()呼び出しでは第二引数をq1-2にした方がよいのではないか? + i = jitCompiler(q, q1, p0 + 2, p1, p0, label, JITC_MAXLABELS, level, di1_serial, 0); + if (i != 0) return 2; + i = jitCompiler(q, q1, p0 + 2, p1, p0, label, JITC_MAXLABELS, level, di1_serial, JITC_PHASE1 + 0); + if (i < 0) return 2; + q += i; + + *q++ = 0x5d; /* POP(EBP); */ + *q++ = 0xc3; /* RET(); */ + + *qq = q; + return 0; +} + +#if (USE_DEBUGGER != 0) + +int dbgrGetRegNum(const char *p) +{ + int i, j, r = -1; + if (p[2] <= ' ') { + i = p[0] - '0'; + j = p[1] - '0'; + if (i > 9) i -= 'A' - '0' - 10; + if (j > 9) j -= 'A' - '0' - 10; + if (0 <= i && i <= 15 && 0 <= j && j <= 15) + r = i << 4 | j; + } + return r; +} + +void dbgrMain(HOSECPU_RuntimeEnvironment *r) +{ + if (r->dbgr == 0) return; + for (;;) { + char cmd[64], *p; + int i, j, k; + printf("\ndbgr>"); + p = fgets(cmd, 64, stdin); + if (p == NULL) break; + if (cmd[0] == '\0') continue; + if (cmd[0] == 'q' && cmd[1] <= ' ') break; + if (cmd[0] == 'p' && cmd[1] <= ' ' && cmd[1] != '\0') { + p = &cmd[2]; + while (*p <= ' ' && *p != '\0') p++; + if (*p == 'R') { + i = dbgrGetRegNum(p + 1); + if (0 <= i && i <= 0x3f) { + printf("R%02X = 0x%08X = %d\n", i, r->ireg[i], r->ireg[i]); + } + else + puts("register name error"); + continue; + } + if (*p == 'P') { + i = dbgrGetRegNum(p + 1); + if (0 <= i && i <= 0x3f) { + p = "invalid"; + if (0 <= r->preg[i].typ && r->preg[i].typ <= 0x15) { + static char *typName[] = { + "T_CODE", "T_VPTR", "T_SINT8", "T_UINT8", + "T_SINT16", "T_UINT16", "T_SINT32", "T_UINT32", + "T_SINT4", "T_UINT4", "T_SINT2", "T_UINT2", + "T_SINT1", "T_UINT1", "T_SINT12", "T_UINT12", + "T_SINT20", "T_UINT20", "T_SINT24", "T_UINT24", + "T_SINT28", "T_UINT28" + }; + p = typName[r->preg[i].typ]; + } + printf("P%02X:\n type = %s(%04X), (origin-ptr) = 0x%08X\n", i, p, r->preg[i].typ, (unsigned int)(r->preg[i].p0)); + if (r->preg[i].p != NULL && r->preg[i].p0 != NULL) { + j = jitCompA000_dataWidth(jitCompA000_convTyp(r->preg[i].typ)) >> 3; + if (j <= 0) j = 1; + k = (r->preg[i].p1 - r->preg[i].p0) / j; + printf(" size = 0x%08X = %d\n", k, k); + k = (r->preg[i].p - r->preg[i].p0) / j; + printf(" pos = 0x%08X = %d\n", k, k); + } + else { + puts(" null pointer"); + } + } + else + puts("register name error"); + continue; + } + } + puts("command error"); + } + return; +} + +#endif + + #endif \ No newline at end of file diff --git a/main.c b/main.c index 293622e..a5dcbf8 100644 --- a/main.c +++ b/main.c @@ -1,338 +1,338 @@ -#include "osecpu.h" - -int *keybuf, keybuf_r, keybuf_w, keybuf_c; -HOSECPU_Device_Window mainWindow; -//デバッグ用。プログラム中の随所で加算される変数 -int di1_serial; - - - -unsigned char *Init_LoadSysLib(char argv0[], unsigned char *tmpWorkMemory); -void LoadAppBin(HOSECPU_RuntimeEnvironment *env); - -void putKeybuf(int i) -{ - if (keybuf_c < KEYBUFSIZ) { - keybuf[keybuf_w] = i; - keybuf_c++; - keybuf_w = (keybuf_w + 1) & (KEYBUFSIZ - 1); - } - return; -} - -int HeavyOSECPUMain(int argc, char **argv) -{ - FILE *fp; - unsigned char *jitbuf, *sysjit00, *sysjit; - unsigned char *systmp0, *systmp1, *systmp2; - unsigned char *opTbl; - HOSECPU_LabelListTag *label; - int tmpsiz, i; - jmp_buf setjmpEnv; - double tm0, tm1, tm2; - HOSECPU_PointerControlTag *ptrCtrl; - unsigned char *syslib; - int argDebug = 0, stacksiz = 1; - const char *cp; - HOSECPU_RuntimeEnvironment env; - void(*jitfunc)(char *); - unsigned char *jp; - - //Initialize mainWindow - mainWindow.vram = NULL; - mainWindow.xsize = 0; - mainWindow.ysize = 0; - di1_serial = 0; - - //実行環境初期化 - env.mainArgc = argc; - env.mainArgv = (const char **)argv; - env.appBin = malloc(APPSIZ1); - env.executionLevel = JITC_LV_SLOWEST; - jitbuf = mallocRWE(1024 * 1024); /* とりあえず1MBで */ - //unsigned char *sysjit0 = mallocRWE(SJITSIZ1), *sysjit1 = sysjit0, *sysjit00 = sysjit0; - // syslib.oseのjitc結果を格納する領域を確保。 - sysjit00 = mallocRWE(SJITSIZ1); - sysjit = sysjit00; - // 現在の、jitc結果を格納するメモリへの書き込み位置のアドレス - // sysjit: 現在のjitc書き込み位置 - // sysjit00: jitc結果の先頭 - //ワークメモリを三つくらいもらう - systmp0 = malloc(SYSTMP0SIZ); /* syslibのjitc用 */ - systmp1 = malloc(SYSTMP1SIZ); - systmp2 = malloc(1024 * 1024); - - opTbl = malloc(256); - label = malloc(JITC_MAXLABELS * sizeof (HOSECPU_LabelListTag)); - keybuf = malloc(KEYBUFSIZ * sizeof (int)); - keybuf_r = keybuf_w = keybuf_c = 0; - ptrCtrl = malloc(PTRCTRLSIZ * sizeof (HOSECPU_PointerControlTag)); - - randStatInit((unsigned int)time(NULL)); - for (i = 0; i < PTRCTRLSIZ; i++) { - ptrCtrl[i].liveSign = 0; - ptrCtrl[i].size = -1; - } - ptrCtrl[0].size = -2; - - /* syslibの読み込み */ - syslib = Init_LoadSysLib(argv[0], systmp0); - - sysjit = jitCompInit(sysjit); - sysjit00 = sysjit; - // labelはjitc0()内で初期化される。 - i = jitc0(&sysjit, sysjit00 + SJITSIZ1, syslib + 32, syslib + SYSLIBSIZ1, JITC_LV_SLOWEST+9, label); - if (i != 0){ - fputs("syslib-file JITC error.\n", stderr); - return 1; - } - - // エラー時にデバッグ用に表示する変数を加算 - di1_serial++; - - /* アプリバイナリの読み込み */ - LoadAppBin(&env); - - /* クロック初期化 */ - tm0 = clock() / (double)CLOCKS_PER_SEC; - - if (env.appBin[2] == 0xf0) { - // tek5圧縮がかかっている -#if (USE_TEK5 != 0) - env.appSize1 = tek5Decomp(env.appBin + 2, env.appBin + env.appSize0, systmp0) + 2; -#else - env.appSize1 = -9; -#endif - if (env.appSize1 < 0) { - fputs("unsupported-format(tek5)\n", stderr); - return 1; - } - } - //デバッグモード指定 - cp = searchArg(argc, (const char **)argv, "debug:", 0); - if (cp != NULL){ - argDebug = *cp - '0'; - } - //スタックサイズ指定(MiB単位) - cp = searchArg(argc, (const char **)argv, "stack:", 0); - if (cp != NULL){ - stacksiz = strtol(cp, NULL, 0); - } - jp = jitbuf; /* JIT-pointer */ - - /* フロントエンドコードをバックエンドコードに変換する */ - if ((env.appBin[2] & 0xf0) != 0) { - systmp0[0] = env.appBin[0]; - systmp0[1] = env.appBin[1]; - env.preg[2].p = systmp0 + 2; - env.preg[3].p = systmp0 + SYSTMP0SIZ; - env.preg[4].p = env.appBin + 2; - env.preg[5].p = env.appBin + env.appSize1; - env.preg[6].p = systmp1; - env.preg[7].p = systmp1 + SYSTMP1SIZ; - env.preg[10].p = systmp2; - int pxxFlag[64], typLabel[4096]; - env.preg[0x0b].p = (void *)pxxFlag; - env.preg[0x0c].p = (void *)typLabel; - env.preg[0x0d].p = opTbl; - jitfunc = (void *)sysjit00; - (*jitfunc)(((char *)&env) + 128); /* サイズを節約するためにEBPを128バイトずらす */ - if (env.ireg[0] != 0) { - jp = env.preg[2].p - 1; - fprintf(stderr, "unpack error: %02X (at %06X) (R00=%d)\n", *jp, jp - systmp0, env.ireg[0]); - if ((argDebug & 2) != 0) { - fp = fopen("debug2.bin", "wb"); - fwrite(systmp0, 1, jp - systmp0 + 16, fp); - fclose(fp); - } - exit(1); - } - tmpsiz = env.preg[2].p - systmp0; - } else{ - memcpy(systmp0, env.appBin, env.appSize1); - tmpsiz = env.appSize1; - } - - if ((argDebug & 2) != 0) { - /*変換後のバックエンドコードをファイルへ保存*/ - fp = fopen("debug2.bin", "wb"); - fwrite(systmp0, 1, tmpsiz, fp); - fclose(fp); - } - - //JITコンパイル - i = jitc0(&jp, jitbuf + 1024 * 1024, systmp0, systmp0 + tmpsiz, env.executionLevel, label); - if (i == 1){ - fputs("app-file header error.\n", stderr); - return 1; - } - if (i != 0){ - return 1; - } - di1_serial++; - - int appsiz2 = jp - jitbuf; - - unsigned char *p28 = jp; - jp = jitCompCallFunc(jp, &devFunc); - - tm1 = clock() / (double)CLOCKS_PER_SEC; - - /* レジスタ初期化 */ - for (i = 0; i < 64; i++){ - env.ireg[i] = 0; - } - for (i = 0; i < 64; i++) { - env.preg[i].p = NULL; - env.preg[i].typ = -1; - env.preg[i].p0 = NULL; - env.preg[i].p1 = NULL; - } - - env.buf0 = env.buf1 = NULL; - env.preg[0x28].p = p28; - env.preg[0x28].typ = 0; // TYP_CODE - env.preg[0x28].p0 = p28; - env.preg[0x28].p1 = p28 + 1; - //env.preg[0x00].p = malloc(1024 * 1024) + (1024 * 1024 - 32); - env.junkStack = malloc(stacksiz << 20); - env.junkStack1 = env.junkStack + (stacksiz << 20); - env.winClosed = 0; - env.autoSleep = 0; - env.setjmpEnv = &setjmpEnv; - env.lastConsoleChar = '\n'; - - env.label = label; - env.maxLabels = JITC_MAXLABELS; - env.jitbuf = jp; - env.jitbuf1 = jitbuf + 1024 * 1024; - env.errHndl = &errorHandler; - - env.dbgr = 0; - if (searchArg(argc, (const char **)argv, "dbgr:1", 0) != NULL){ - env.dbgr = 1; - } - - if ((argDebug & 1) != 0) { - fp = fopen("debug1.bin", "wb"); - fwrite(jitbuf, 1, jp - jitbuf, fp); - fclose(fp); - } - - /* JITコード実行 */ - jitfunc = (void *)jitbuf; - if (setjmp(setjmpEnv) == 0){ - (*jitfunc)(((char *)&env) + 128); /* サイズを節約するためにEBPを128バイトずらす */ - } - if (env.autoSleep != 0) { - if (mainWindow.vram != NULL){ - drv_flshWin(mainWindow.xsize, mainWindow.ysize, 0, 0); - } - while (env.winClosed == 0){ - drv_sleep(100); - } - } - if (env.lastConsoleChar != '\n'){ - putchar('\n'); - } - - tm2 = clock() / (double)CLOCKS_PER_SEC; - - /* 実行結果確認のためのレジスタダンプ */ - if (searchArg(argc, (const char **)argv, "verbose:1", 0) != NULL) { - printf("time: JITC=%.3f[sec], exec=%.3f[sec]\n", tm1 - tm0, tm2 - tm1); - printf("size: OSECPU=%d, decomp=%d, tmp=%d, native=%d\n", env.appSize0, env.appSize1, tmpsiz, appsiz2); - printf("result:\n"); - 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]); - } -#if (USE_DEBUGGER != 0) - dbgrMain(&env); -#endif - return 0; -} - -unsigned char *Init_LoadSysLib(char argv0[], unsigned char *tmpWorkMemory) -{ - unsigned char *syslib; - FILE *fp; - unsigned char *up; - int appsize; - - /* syslibの読み込み */ - syslib = malloc(SYSLIBSIZ1); - fp = fopen(SYSLIB_OSE, "rb"); - if (fp == NULL) { - syslib[0] = '/'; - strcpy((char *)syslib + 1, argv0); - up = syslib + 1; - while (*up != '\0'){ - up++; - } - while (*up != '/' && *up != 0x5c){ - up--; - } - up++; - strcpy((char *)up, SYSLIB_OSE); - fp = fopen((char *)syslib + 1, "rb"); - } - if (fp == NULL) { - fputs("syslib-file fopen error.\n", stderr); - exit(EXIT_FAILURE); - } - appsize = fread(syslib, 1, SYSLIBSIZ1 - 4, fp); - fclose(fp); - if (appsize >= SYSLIBSIZ1 - 4) { - fputs("syslib-file too large.\n", stderr); - exit(EXIT_FAILURE); - } - if (syslib[0] == 0x05 && syslib[1] == 0xc1) { - // maklib のライブラリ形式である。 - memcpy(tmpWorkMemory, syslib, appsize); - ComLib_main(tmpWorkMemory + 2, syslib + 2); - syslib[0] = 0x05; - syslib[1] = 0x1b; - } - - fp = fopen("syslib_dbg.ose", "wb"); - fwrite(syslib, 1, SYSLIBSIZ1, fp); - fclose(fp); - return syslib; -} - -void LoadAppBin(HOSECPU_RuntimeEnvironment *env) -{ - FILE *fp; - const char *fileName; - /* アプリバイナリの読み込み */ - if (env->mainArgc <= 1) { - //アプリ名未指定なので何事もなく終了 - exit(EXIT_SUCCESS); - } - fileName = env->mainArgv[1]; - //アプリ名先頭に:n:をつけることでレベルnでの実行が可能? - if (fileName[0] == ':' && fileName[2] == ':') { - env->executionLevel = fileName[1] - '0'; - if (env->executionLevel < 0 || env->executionLevel > 9){ - env->executionLevel = JITC_LV_SLOWEST; - } - fileName += 3; - } - - fp = fopen(fileName, "rb"); - if (fp == NULL) { - fputs("app-file load error.\n", stderr); - exit(EXIT_FAILURE); - } - env->appSize0 = fread(env->appBin, 1, APPSIZ1 - 4, fp); - env->appSize1 = env->appSize0; - fclose(fp); - - if (env->appSize0 >= APPSIZ1 - 4) { - fputs("app-file too large.\n", stderr); - exit(EXIT_FAILURE); - } - if (env->appSize0 < 3) { - fputs("app-file header error.\n", stderr); - exit(EXIT_FAILURE); - } -} +#include "osecpu.h" + +int *keybuf, keybuf_r, keybuf_w, keybuf_c; +HOSECPU_Device_Window mainWindow; +//デバッグ用。プログラム中の随所で加算される変数 +int di1_serial; + + + +unsigned char *Init_LoadSysLib(char argv0[], unsigned char *tmpWorkMemory); +void LoadAppBin(HOSECPU_RuntimeEnvironment *env); + +void putKeybuf(int i) +{ + if (keybuf_c < KEYBUFSIZ) { + keybuf[keybuf_w] = i; + keybuf_c++; + keybuf_w = (keybuf_w + 1) & (KEYBUFSIZ - 1); + } + return; +} + +int HeavyOSECPUMain(int argc, char **argv) +{ + FILE *fp; + unsigned char *jitbuf, *sysjit00, *sysjit; + unsigned char *systmp0, *systmp1, *systmp2; + unsigned char *opTbl; + HOSECPU_LabelListTag *label; + int tmpsiz, i; + jmp_buf setjmpEnv; + double tm0, tm1, tm2; + HOSECPU_PointerControlTag *ptrCtrl; + unsigned char *syslib; + int argDebug = 0, stacksiz = 1; + const char *cp; + HOSECPU_RuntimeEnvironment env; + void(*jitfunc)(char *); + unsigned char *jp; + + //Initialize mainWindow + mainWindow.vram = NULL; + mainWindow.xsize = 0; + mainWindow.ysize = 0; + di1_serial = 0; + + //実行環境初期化 + env.mainArgc = argc; + env.mainArgv = (const char **)argv; + env.appBin = malloc(APPSIZ1); + env.executionLevel = JITC_LV_SLOWEST; + jitbuf = mallocRWE(1024 * 1024); /* とりあえず1MBで */ + //unsigned char *sysjit0 = mallocRWE(SJITSIZ1), *sysjit1 = sysjit0, *sysjit00 = sysjit0; + // syslib.oseのjitc結果を格納する領域を確保。 + sysjit00 = mallocRWE(SJITSIZ1); + sysjit = sysjit00; + // 現在の、jitc結果を格納するメモリへの書き込み位置のアドレス + // sysjit: 現在のjitc書き込み位置 + // sysjit00: jitc結果の先頭 + //ワークメモリを三つくらいもらう + systmp0 = malloc(SYSTMP0SIZ); /* syslibのjitc用 */ + systmp1 = malloc(SYSTMP1SIZ); + systmp2 = malloc(1024 * 1024); + + opTbl = malloc(256); + label = malloc(JITC_MAXLABELS * sizeof (HOSECPU_LabelListTag)); + keybuf = malloc(KEYBUFSIZ * sizeof (int)); + keybuf_r = keybuf_w = keybuf_c = 0; + ptrCtrl = malloc(PTRCTRLSIZ * sizeof (HOSECPU_PointerControlTag)); + + randStatInit((unsigned int)time(NULL)); + for (i = 0; i < PTRCTRLSIZ; i++) { + ptrCtrl[i].liveSign = 0; + ptrCtrl[i].size = -1; + } + ptrCtrl[0].size = -2; + + /* syslibの読み込み */ + syslib = Init_LoadSysLib(argv[0], systmp0); + + sysjit = jitCompInit(sysjit); + sysjit00 = sysjit; + // labelはjitc0()内で初期化される。 + i = jitc0(&sysjit, sysjit00 + SJITSIZ1, syslib + 32, syslib + SYSLIBSIZ1, JITC_LV_SLOWEST+9, label); + if (i != 0){ + fputs("syslib-file JITC error.\n", stderr); + return 1; + } + + // エラー時にデバッグ用に表示する変数を加算 + di1_serial++; + + /* アプリバイナリの読み込み */ + LoadAppBin(&env); + + /* クロック初期化 */ + tm0 = clock() / (double)CLOCKS_PER_SEC; + + if (env.appBin[2] == 0xf0) { + // tek5圧縮がかかっている +#if (USE_TEK5 != 0) + env.appSize1 = tek5Decomp(env.appBin + 2, env.appBin + env.appSize0, systmp0) + 2; +#else + env.appSize1 = -9; +#endif + if (env.appSize1 < 0) { + fputs("unsupported-format(tek5)\n", stderr); + return 1; + } + } + //デバッグモード指定 + cp = searchArg(argc, (const char **)argv, "debug:", 0); + if (cp != NULL){ + argDebug = *cp - '0'; + } + //スタックサイズ指定(MiB単位) + cp = searchArg(argc, (const char **)argv, "stack:", 0); + if (cp != NULL){ + stacksiz = strtol(cp, NULL, 0); + } + jp = jitbuf; /* JIT-pointer */ + + /* フロントエンドコードをバックエンドコードに変換する */ + if ((env.appBin[2] & 0xf0) != 0) { + systmp0[0] = env.appBin[0]; + systmp0[1] = env.appBin[1]; + env.preg[2].p = systmp0 + 2; + env.preg[3].p = systmp0 + SYSTMP0SIZ; + env.preg[4].p = env.appBin + 2; + env.preg[5].p = env.appBin + env.appSize1; + env.preg[6].p = systmp1; + env.preg[7].p = systmp1 + SYSTMP1SIZ; + env.preg[10].p = systmp2; + int pxxFlag[64], typLabel[4096]; + env.preg[0x0b].p = (void *)pxxFlag; + env.preg[0x0c].p = (void *)typLabel; + env.preg[0x0d].p = opTbl; + jitfunc = (void *)sysjit00; + (*jitfunc)(((char *)&env) + 128); /* サイズを節約するためにEBPを128バイトずらす */ + if (env.ireg[0] != 0) { + jp = env.preg[2].p - 1; + fprintf(stderr, "unpack error: %02X (at %06X) (R00=%d)\n", *jp, jp - systmp0, env.ireg[0]); + if ((argDebug & 2) != 0) { + fp = fopen("debug2.bin", "wb"); + fwrite(systmp0, 1, jp - systmp0 + 16, fp); + fclose(fp); + } + exit(1); + } + tmpsiz = env.preg[2].p - systmp0; + } else{ + memcpy(systmp0, env.appBin, env.appSize1); + tmpsiz = env.appSize1; + } + + if ((argDebug & 2) != 0) { + /*変換後のバックエンドコードをファイルへ保存*/ + fp = fopen("debug2.bin", "wb"); + fwrite(systmp0, 1, tmpsiz, fp); + fclose(fp); + } + + //JITコンパイル + i = jitc0(&jp, jitbuf + 1024 * 1024, systmp0, systmp0 + tmpsiz, env.executionLevel, label); + if (i == 1){ + fputs("app-file header error.\n", stderr); + return 1; + } + if (i != 0){ + return 1; + } + di1_serial++; + + int appsiz2 = jp - jitbuf; + + unsigned char *p28 = jp; + jp = jitCompCallFunc(jp, &devFunc); + + tm1 = clock() / (double)CLOCKS_PER_SEC; + + /* レジスタ初期化 */ + for (i = 0; i < 64; i++){ + env.ireg[i] = 0; + } + for (i = 0; i < 64; i++) { + env.preg[i].p = NULL; + env.preg[i].typ = -1; + env.preg[i].p0 = NULL; + env.preg[i].p1 = NULL; + } + + env.buf0 = env.buf1 = NULL; + env.preg[0x28].p = p28; + env.preg[0x28].typ = 0; // TYP_CODE + env.preg[0x28].p0 = p28; + env.preg[0x28].p1 = p28 + 1; + //env.preg[0x00].p = malloc(1024 * 1024) + (1024 * 1024 - 32); + env.junkStack = malloc(stacksiz << 20); + env.junkStack1 = env.junkStack + (stacksiz << 20); + env.winClosed = 0; + env.autoSleep = 0; + env.setjmpEnv = &setjmpEnv; + env.lastConsoleChar = '\n'; + + env.label = label; + env.maxLabels = JITC_MAXLABELS; + env.jitbuf = jp; + env.jitbuf1 = jitbuf + 1024 * 1024; + env.errHndl = &errorHandler; + + env.dbgr = 0; + if (searchArg(argc, (const char **)argv, "dbgr:1", 0) != NULL){ + env.dbgr = 1; + } + + if ((argDebug & 1) != 0) { + fp = fopen("debug1.bin", "wb"); + fwrite(jitbuf, 1, jp - jitbuf, fp); + fclose(fp); + } + + /* JITコード実行 */ + jitfunc = (void *)jitbuf; + if (setjmp(setjmpEnv) == 0){ + (*jitfunc)(((char *)&env) + 128); /* サイズを節約するためにEBPを128バイトずらす */ + } + if (env.autoSleep != 0) { + if (mainWindow.vram != NULL){ + drv_flshWin(mainWindow.xsize, mainWindow.ysize, 0, 0); + } + while (env.winClosed == 0){ + drv_sleep(100); + } + } + if (env.lastConsoleChar != '\n'){ + putchar('\n'); + } + + tm2 = clock() / (double)CLOCKS_PER_SEC; + + /* 実行結果確認のためのレジスタダンプ */ + if (searchArg(argc, (const char **)argv, "verbose:1", 0) != NULL) { + printf("time: JITC=%.3f[sec], exec=%.3f[sec]\n", tm1 - tm0, tm2 - tm1); + printf("size: OSECPU=%d, decomp=%d, tmp=%d, native=%d\n", env.appSize0, env.appSize1, tmpsiz, appsiz2); + printf("result:\n"); + 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]); + } +#if (USE_DEBUGGER != 0) + dbgrMain(&env); +#endif + return 0; +} + +unsigned char *Init_LoadSysLib(char argv0[], unsigned char *tmpWorkMemory) +{ + unsigned char *syslib; + FILE *fp; + unsigned char *up; + int appsize; + + /* syslibの読み込み */ + syslib = malloc(SYSLIBSIZ1); + fp = fopen(SYSLIB_OSE, "rb"); + if (fp == NULL) { + syslib[0] = '/'; + strcpy((char *)syslib + 1, argv0); + up = syslib + 1; + while (*up != '\0'){ + up++; + } + while (*up != '/' && *up != 0x5c){ + up--; + } + up++; + strcpy((char *)up, SYSLIB_OSE); + fp = fopen((char *)syslib + 1, "rb"); + } + if (fp == NULL) { + fputs("syslib-file fopen error.\n", stderr); + exit(EXIT_FAILURE); + } + appsize = fread(syslib, 1, SYSLIBSIZ1 - 4, fp); + fclose(fp); + if (appsize >= SYSLIBSIZ1 - 4) { + fputs("syslib-file too large.\n", stderr); + exit(EXIT_FAILURE); + } + if (syslib[0] == 0x05 && syslib[1] == 0xc1) { + // maklib のライブラリ形式である。 + memcpy(tmpWorkMemory, syslib, appsize); + ComLib_main(tmpWorkMemory + 2, syslib + 2); + syslib[0] = 0x05; + syslib[1] = 0x1b; + } + + fp = fopen("syslib_dbg.ose", "wb"); + fwrite(syslib, 1, SYSLIBSIZ1, fp); + fclose(fp); + return syslib; +} + +void LoadAppBin(HOSECPU_RuntimeEnvironment *env) +{ + FILE *fp; + const char *fileName; + /* アプリバイナリの読み込み */ + if (env->mainArgc <= 1) { + //アプリ名未指定なので何事もなく終了 + exit(EXIT_SUCCESS); + } + fileName = env->mainArgv[1]; + //アプリ名先頭に:n:をつけることでレベルnでの実行が可能? + if (fileName[0] == ':' && fileName[2] == ':') { + env->executionLevel = fileName[1] - '0'; + if (env->executionLevel < 0 || env->executionLevel > 9){ + env->executionLevel = JITC_LV_SLOWEST; + } + fileName += 3; + } + + fp = fopen(fileName, "rb"); + if (fp == NULL) { + fputs("app-file load error.\n", stderr); + exit(EXIT_FAILURE); + } + env->appSize0 = fread(env->appBin, 1, APPSIZ1 - 4, fp); + env->appSize1 = env->appSize0; + fclose(fp); + + if (env->appSize0 >= APPSIZ1 - 4) { + fputs("app-file too large.\n", stderr); + exit(EXIT_FAILURE); + } + if (env->appSize0 < 3) { + fputs("app-file header error.\n", stderr); + exit(EXIT_FAILURE); + } +} diff --git a/osecpu.h b/osecpu.h index db19e83..ae38f99 100644 --- a/osecpu.h +++ b/osecpu.h @@ -1,224 +1,224 @@ -#ifndef _HDLOAD_OSECPU -#define _HDLOAD_OSECPU 1 - -/* Visual Studio で fopen()やsprintf() などの古い関数を使用する時に出る警告を抑止する*/ -#define _CRT_SECURE_NO_WARNINGS 1 - -// -// Including stdc headers -// - -#include -#include -#include -#include -#include -#include - - -// -// Compile options -// - -// Target architecture -// 1 : i386 -#define JITC_ARCNUM 0x0001 - -// Target operating system -// 1 : Windows 32bit -// 2 : Mac OSX 32bit -// 3 : blike for Linux -#ifdef _WIN32 -#define DRV_OSNUM 0x0001 -#endif -#ifdef __APPLE__ -#define DRV_OSNUM 0x0002 -#endif -#ifdef __linux__ -#define DRV_OSNUM 0x0003 -#endif -//#define DRV_OSNUM 0x0002 - -// Decoder (syslib.ose) setting -// syslib.ose is necessary to work OSECPU -#define SYSLIB_OSE "syslib.ose" - -// -// Define constant values -// - -// SIGN1: The 2nd signature of OSECPU Format(05 e1) -// It will be changed in OSECPU Rev.2 to "e2" (no adaptation in their binary layers) -#define SIGN1 0xe1 - -#define USE_DEBUGGER 1 -#define USE_TEK5 0 //元々は1 - -/* JITC mode flags */ -#define JITC_LV_SLOWEST 0 /* デバッグ支援は何でもやる */ -#define JITC_LV_SLOWER 1 /* エラーモジュールはレポートできるが、行番号は分からない、テストは過剰 */ -#define JITC_LV_SAFE 2 /* とにかく止まる、場所は不明、テストは必要最小限 */ -#define JITC_LV_FASTER 4 /* 情報は生成するがチェックをしない */ -#define JITC_LV_FASTEST 5 /* 情報すら生成しない */ -#define JITC_PHASE1 0x0001 -#define JITC_SKIPCHECK 0x0002 /* セキュリティチェックを省略する(高速危険モード) */ -#define JITC_NOSTARTUP 0x0004 -#define JITC_MAXLABELS 4096 -#define PTRCTRLSIZ 4096 - -#define APPSIZ1 1 * 1024 * 1024 /* 1MB for now */ -#define JITSIZ1 1 * 1024 * 1024 /* 1MB for now */ -#define SJITSIZ1 1 * 1024 * 1024 /* 1MB for now */ -#define SYSLIBSIZ1 1 * 1024 * 1024 /* 1MB for now */ -#define SYSTMP0SIZ 1 * 1024 * 1024 /* 1MB for now */ -#define SYSTMP1SIZ 2 * 1024 * 1024 /* 1MB for now */ - -#define KEYBUFSIZ 4096 - -#define KEY_ENTER '\n' -#define KEY_ESC 27 -#define KEY_BACKSPACE 8 -#define KEY_TAB 9 -#define KEY_PAGEUP 0x1020 -#define KEY_PAGEDWN 0x1021 -#define KEY_END 0x1022 -#define KEY_HOME 0x1023 -#define KEY_LEFT 0x1024 -#define KEY_UP 0x1025 -#define KEY_RIGHT 0x1026 -#define KEY_DOWN 0x1027 -#define KEY_INS 0x1028 -#define KEY_DEL 0x1029 - -// -// HOSECPU structures -// -typedef struct PtrCtrl HOSECPU_PointerControlTag; -struct PtrCtrl { - int liveSign; - int size, typ; - unsigned char *p0; -}; - -typedef struct Ptr HOSECPU_PointerRegisterEntry; -struct Ptr { /* 32バイト(=256bit!) */ - unsigned char *p; - int typ; - unsigned char *p0, *p1; - int liveSign; - HOSECPU_PointerControlTag *pls; - int flags, dummy; /* read/writeなど */ -}; - -typedef struct LabelTable HOSECPU_LabelListTag; -struct LabelTable { - unsigned char *p, *p1; - int opt; - /* - * default = -1 - * TYP_CODE = 0 - * T_UINT8 = 3 - * - * 将来的には UInt8, SInt32, Flt64, UInt8, VPtr が使えるようになる http://osecpu.osask.jp/wiki/?page0053 - */ - int typ; -}; - -typedef struct Device_Window HOSECPU_Device_Window; -struct Device_Window { - int *vram; - int xsize, ysize; -}; - -typedef struct Regs HOSECPU_RuntimeEnvironment; -struct Regs { - int ireg[64]; /* 32bit整数レジスタ */ - HOSECPU_PointerRegisterEntry preg[64]; /* ポインタレジスタ */ - // - int debugInfo0, debugInfo1, dmy[2]; /* 2304 */ - HOSECPU_PointerControlTag *ptrCtrl; /* 2320 */ - char winClosed, autoSleep; - jmp_buf *setjmpEnv; - - /* Main environment */ - int mainArgc; // HOSECPU起動引数の個数 - const char **mainArgv; // HOSECPU起動引数リスト - unsigned char *appBin; // 実行するアプリのバイナリ - int appSize0; - int appSize1; - int executionLevel; - - /* for-junkApi */ - unsigned char *buf0, *buf1, *junkStack, lastConsoleChar, *junkStack1; - - HOSECPU_LabelListTag *label; - int maxLabels; - unsigned char *jitbuf, *jitbuf1; - void(*errHndl)(HOSECPU_RuntimeEnvironment *); - char dbgr; - int mapDi1s[16][16]; -}; - -// -// Grobal values -// - -extern int *keybuf, keybuf_r, keybuf_w, keybuf_c; -extern HOSECPU_Device_Window mainWindow; -// di1_serial: デバッグ用。プログラム中の随所で加算される変数 -extern int di1_serial; - -// -// Functions -// - -// @main.c -void putKeybuf(int i); -int HeavyOSECPUMain(int argc, char **argv); - -// @comlib.c -unsigned char *ComLib_main(const unsigned char *p, unsigned char *q); -// @dpndenv.c -// OSに依存する関数群を定義する。 -void *mallocRWE(int bytes); // 実行権付きメモリのmalloc. -void drv_openWin(int x, int y, unsigned char *buf, char *winClosed); -void drv_flshWin(int sx, int sy, int x0, int y0); -void drv_sleep(int msec); - -// @function.c -void dbgrMain(HOSECPU_RuntimeEnvironment *r); -const char *searchArg(int argc, const char **argv, const char *tag, int i); // コマンドライン引数処理. -void devFunc(HOSECPU_RuntimeEnvironment *r); // junkApiを処理する関数 - -// @jitc.c -int jitc0(unsigned char **qq, unsigned char *q1, const unsigned char *p0, const unsigned char *p1, int level, HOSECPU_LabelListTag *label); -int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *src, const unsigned char *src1, const unsigned char *src0, HOSECPU_LabelListTag *label, int maxLabels, int level, int debugInfo1, int flags); -unsigned char *jitCompCallFunc(unsigned char *dst, void *func); -unsigned char *jitCompInit(unsigned char *dst); -void errorHandler(HOSECPU_RuntimeEnvironment *r); - -// @randmt.c -void randStatInit(unsigned int seed); -void randStatNext(); -unsigned int randGetNextUInt32(void); - -// @screen.c -static int iColor1[] = { - 0x000000, 0xff0000, 0x00ff00, 0xffff00, - 0x0000ff, 0xff00ff, 0x00ffff, 0xffffff -}; -void putOsaskChar(int c, HOSECPU_RuntimeEnvironment *r); -void checkString(HOSECPU_RuntimeEnvironment *r, int rxx, int pxx); -void checkRect(HOSECPU_RuntimeEnvironment *r, int rxx); -int loadColor(HOSECPU_RuntimeEnvironment *r, int rxx); - -#if (USE_TEK5 != 0) -/* tek.cを移植するのは大変だと思ったので、断念 */ -#error "tek is not supported. edit switch.h and set USE_TEK5=0" -// #include "tek.c" -// int tek5Decomp(unsigned char *buf, unsigned char *buf1, unsigned char *tmp); -#endif - - -#endif - +#ifndef _HDLOAD_OSECPU +#define _HDLOAD_OSECPU 1 + +/* Visual Studio で fopen()やsprintf() などの古い関数を使用する時に出る警告を抑止する*/ +#define _CRT_SECURE_NO_WARNINGS 1 + +// +// Including stdc headers +// + +#include +#include +#include +#include +#include +#include + + +// +// Compile options +// + +// Target architecture +// 1 : i386 +#define JITC_ARCNUM 0x0001 + +// Target operating system +// 1 : Windows 32bit +// 2 : Mac OSX 32bit +// 3 : blike for Linux +#ifdef _WIN32 +#define DRV_OSNUM 0x0001 +#endif +#ifdef __APPLE__ +#define DRV_OSNUM 0x0002 +#endif +#ifdef __linux__ +#define DRV_OSNUM 0x0003 +#endif +//#define DRV_OSNUM 0x0002 + +// Decoder (syslib.ose) setting +// syslib.ose is necessary to work OSECPU +#define SYSLIB_OSE "syslib.ose" + +// +// Define constant values +// + +// SIGN1: The 2nd signature of OSECPU Format(05 e1) +// It will be changed in OSECPU Rev.2 to "e2" (no adaptation in their binary layers) +#define SIGN1 0xe1 + +#define USE_DEBUGGER 1 +#define USE_TEK5 0 //元々は1 + +/* JITC mode flags */ +#define JITC_LV_SLOWEST 0 /* デバッグ支援は何でもやる */ +#define JITC_LV_SLOWER 1 /* エラーモジュールはレポートできるが、行番号は分からない、テストは過剰 */ +#define JITC_LV_SAFE 2 /* とにかく止まる、場所は不明、テストは必要最小限 */ +#define JITC_LV_FASTER 4 /* 情報は生成するがチェックをしない */ +#define JITC_LV_FASTEST 5 /* 情報すら生成しない */ +#define JITC_PHASE1 0x0001 +#define JITC_SKIPCHECK 0x0002 /* セキュリティチェックを省略する(高速危険モード) */ +#define JITC_NOSTARTUP 0x0004 +#define JITC_MAXLABELS 4096 +#define PTRCTRLSIZ 4096 + +#define APPSIZ1 1 * 1024 * 1024 /* 1MB for now */ +#define JITSIZ1 1 * 1024 * 1024 /* 1MB for now */ +#define SJITSIZ1 1 * 1024 * 1024 /* 1MB for now */ +#define SYSLIBSIZ1 1 * 1024 * 1024 /* 1MB for now */ +#define SYSTMP0SIZ 1 * 1024 * 1024 /* 1MB for now */ +#define SYSTMP1SIZ 2 * 1024 * 1024 /* 1MB for now */ + +#define KEYBUFSIZ 4096 + +#define KEY_ENTER '\n' +#define KEY_ESC 27 +#define KEY_BACKSPACE 8 +#define KEY_TAB 9 +#define KEY_PAGEUP 0x1020 +#define KEY_PAGEDWN 0x1021 +#define KEY_END 0x1022 +#define KEY_HOME 0x1023 +#define KEY_LEFT 0x1024 +#define KEY_UP 0x1025 +#define KEY_RIGHT 0x1026 +#define KEY_DOWN 0x1027 +#define KEY_INS 0x1028 +#define KEY_DEL 0x1029 + +// +// HOSECPU structures +// +typedef struct PtrCtrl HOSECPU_PointerControlTag; +struct PtrCtrl { + int liveSign; + int size, typ; + unsigned char *p0; +}; + +typedef struct Ptr HOSECPU_PointerRegisterEntry; +struct Ptr { /* 32バイト(=256bit!) */ + unsigned char *p; + int typ; + unsigned char *p0, *p1; + int liveSign; + HOSECPU_PointerControlTag *pls; + int flags, dummy; /* read/writeなど */ +}; + +typedef struct LabelTable HOSECPU_LabelListTag; +struct LabelTable { + unsigned char *p, *p1; + int opt; + /* + * default = -1 + * TYP_CODE = 0 + * T_UINT8 = 3 + * + * 将来的には UInt8, SInt32, Flt64, UInt8, VPtr が使えるようになる http://osecpu.osask.jp/wiki/?page0053 + */ + int typ; +}; + +typedef struct Device_Window HOSECPU_Device_Window; +struct Device_Window { + int *vram; + int xsize, ysize; +}; + +typedef struct Regs HOSECPU_RuntimeEnvironment; +struct Regs { + int ireg[64]; /* 32bit整数レジスタ */ + HOSECPU_PointerRegisterEntry preg[64]; /* ポインタレジスタ */ + // + int debugInfo0, debugInfo1, dmy[2]; /* 2304 */ + HOSECPU_PointerControlTag *ptrCtrl; /* 2320 */ + char winClosed, autoSleep; + jmp_buf *setjmpEnv; + + /* Main environment */ + int mainArgc; // HOSECPU起動引数の個数 + const char **mainArgv; // HOSECPU起動引数リスト + unsigned char *appBin; // 実行するアプリのバイナリ + int appSize0; + int appSize1; + int executionLevel; + + /* for-junkApi */ + unsigned char *buf0, *buf1, *junkStack, lastConsoleChar, *junkStack1; + + HOSECPU_LabelListTag *label; + int maxLabels; + unsigned char *jitbuf, *jitbuf1; + void(*errHndl)(HOSECPU_RuntimeEnvironment *); + char dbgr; + int mapDi1s[16][16]; +}; + +// +// Grobal values +// + +extern int *keybuf, keybuf_r, keybuf_w, keybuf_c; +extern HOSECPU_Device_Window mainWindow; +// di1_serial: デバッグ用。プログラム中の随所で加算される変数 +extern int di1_serial; + +// +// Functions +// + +// @main.c +void putKeybuf(int i); +int HeavyOSECPUMain(int argc, char **argv); + +// @comlib.c +unsigned char *ComLib_main(const unsigned char *p, unsigned char *q); +// @dpndenv.c +// OSに依存する関数群を定義する。 +void *mallocRWE(int bytes); // 実行権付きメモリのmalloc. +void drv_openWin(int x, int y, unsigned char *buf, char *winClosed); +void drv_flshWin(int sx, int sy, int x0, int y0); +void drv_sleep(int msec); + +// @function.c +void dbgrMain(HOSECPU_RuntimeEnvironment *r); +const char *searchArg(int argc, const char **argv, const char *tag, int i); // コマンドライン引数処理. +void devFunc(HOSECPU_RuntimeEnvironment *r); // junkApiを処理する関数 + +// @jitc.c +int jitc0(unsigned char **qq, unsigned char *q1, const unsigned char *p0, const unsigned char *p1, int level, HOSECPU_LabelListTag *label); +int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *src, const unsigned char *src1, const unsigned char *src0, HOSECPU_LabelListTag *label, int maxLabels, int level, int debugInfo1, int flags); +unsigned char *jitCompCallFunc(unsigned char *dst, void *func); +unsigned char *jitCompInit(unsigned char *dst); +void errorHandler(HOSECPU_RuntimeEnvironment *r); + +// @randmt.c +void randStatInit(unsigned int seed); +void randStatNext(); +unsigned int randGetNextUInt32(void); + +// @screen.c +static int iColor1[] = { + 0x000000, 0xff0000, 0x00ff00, 0xffff00, + 0x0000ff, 0xff00ff, 0x00ffff, 0xffffff +}; +void putOsaskChar(int c, HOSECPU_RuntimeEnvironment *r); +void checkString(HOSECPU_RuntimeEnvironment *r, int rxx, int pxx); +void checkRect(HOSECPU_RuntimeEnvironment *r, int rxx); +int loadColor(HOSECPU_RuntimeEnvironment *r, int rxx); + +#if (USE_TEK5 != 0) +/* tek.cを移植するのは大変だと思ったので、断念 */ +#error "tek is not supported. edit switch.h and set USE_TEK5=0" +// #include "tek.c" +// int tek5Decomp(unsigned char *buf, unsigned char *buf1, unsigned char *tmp); +#endif + + +#endif + diff --git a/randmt.c b/randmt.c index 4770690..3b003c7 100644 --- a/randmt.c +++ b/randmt.c @@ -1,46 +1,46 @@ - -#include "osecpu.h" - -static struct { - unsigned stat[4], mat1, mat2, tmat; -} randStat; - -// tinyMTの32bit版のアルゴリズムを使っています : http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/TINYMT/index-jp.html -void randStatNext() -{ - unsigned x, y; - x = (randStat.stat[0] & 0x7fffffff) ^ randStat.stat[1] ^ randStat.stat[2]; - y = randStat.stat[3]; - x ^= x << 1; - y ^= (y >> 1) ^ x; - randStat.stat[1] = randStat.stat[2] ^ (-((int)(y & 1)) & randStat.mat1); - randStat.stat[2] = x ^ (y << 10) ^ (-((int)(y & 1)) & randStat.mat2); - randStat.stat[3] = y; - return; -} - -void randStatInit(unsigned seed) -{ - int i; - randStat.stat[0] = seed; - randStat.stat[1] = randStat.mat1 = 0x8f7011ee; - randStat.stat[2] = randStat.mat2 = 0xfc78ff1f; - randStat.stat[3] = randStat.tmat = 0x3793fdff; - for (i = 1; i < 8; i++){ - randStat.stat[i & 3] ^= i + ((unsigned)1812433253) * (randStat.stat[(i - 1) & 3] ^ (randStat.stat[(i - 1) & 3] >> 30)); - } - for (i = 0; i < 8; i++){ - randStatNext(); - } - return; -} - -unsigned int randGetNextUInt32(void) -{ - //次の乱数を取得する。 - unsigned int u32t; - - randStatNext(); - u32t = randStat.stat[0] + (randStat.stat[2] >> 8); - return (randStat.stat[3] ^ u32t ^ (-((int)(u32t & 1)) & randStat.tmat)); -} + +#include "osecpu.h" + +static struct { + unsigned stat[4], mat1, mat2, tmat; +} randStat; + +// tinyMTの32bit版のアルゴリズムを使っています : http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/TINYMT/index-jp.html +void randStatNext() +{ + unsigned x, y; + x = (randStat.stat[0] & 0x7fffffff) ^ randStat.stat[1] ^ randStat.stat[2]; + y = randStat.stat[3]; + x ^= x << 1; + y ^= (y >> 1) ^ x; + randStat.stat[1] = randStat.stat[2] ^ (-((int)(y & 1)) & randStat.mat1); + randStat.stat[2] = x ^ (y << 10) ^ (-((int)(y & 1)) & randStat.mat2); + randStat.stat[3] = y; + return; +} + +void randStatInit(unsigned seed) +{ + int i; + randStat.stat[0] = seed; + randStat.stat[1] = randStat.mat1 = 0x8f7011ee; + randStat.stat[2] = randStat.mat2 = 0xfc78ff1f; + randStat.stat[3] = randStat.tmat = 0x3793fdff; + for (i = 1; i < 8; i++){ + randStat.stat[i & 3] ^= i + ((unsigned)1812433253) * (randStat.stat[(i - 1) & 3] ^ (randStat.stat[(i - 1) & 3] >> 30)); + } + for (i = 0; i < 8; i++){ + randStatNext(); + } + return; +} + +unsigned int randGetNextUInt32(void) +{ + //次の乱数を取得する。 + unsigned int u32t; + + randStatNext(); + u32t = randStat.stat[0] + (randStat.stat[2] >> 8); + return (randStat.stat[3] ^ u32t ^ (-((int)(u32t & 1)) & randStat.tmat)); +} diff --git a/readme.txt b/readme.txt index ae141a7..41c770f 100644 --- a/readme.txt +++ b/readme.txt @@ -1,19 +1,19 @@ -HeavyOSECPU - -OSECPUを学習する人向けにソースコードを幾つかのファイルに分割し、多少は読みやすくなったかもしれない非公式OSECPUソースコードのパッケージ。ソースコードの内容はほとんど本家のOSECPUと同じです。 -今のところまともに動作しないので実用目的で使用することはできません。 -名前の由来: 本家よりもファイルサイズが「重く」なることから。 - -プロジェクトページ -https://sourceforge.jp/projects/heavyosecpu/ - -OSECPUの概要 -http://osecpu.osask.jp/wiki/ - - -■ Visual Studioでの開き方 - -Visual Studio を起動し、ファイル->新規作成->既存のコードからプロジェクトを作成 -を選択して、このディレクトリを指定しプロジェクトを生成してください。 - -ビルドした後、実行するためには、実行ファイルの存在するディレクトリにsyslib.oseをコピーする必要があります。Visual Studioによって作成されたDebugディレクトリに同梱のsyslib.oseをコピーしてください。 +HeavyOSECPU + +OSECPUを学習する人向けにソースコードを幾つかのファイルに分割し、多少は読みやすくなったかもしれない非公式OSECPUソースコードのパッケージ。ソースコードの内容はほとんど本家のOSECPUと同じです。 +今のところまともに動作しないので実用目的で使用することはできません。 +名前の由来: 本家よりもファイルサイズが「重く」なることから。 + +プロジェクトページ +https://sourceforge.jp/projects/heavyosecpu/ + +OSECPUの概要 +http://osecpu.osask.jp/wiki/ + + +■ Visual Studioでの開き方 + +Visual Studio を起動し、ファイル->新規作成->既存のコードからプロジェクトを作成 +を選択して、このディレクトリを指定しプロジェクトを生成してください。 + +ビルドした後、実行するためには、実行ファイルの存在するディレクトリにsyslib.oseをコピーする必要があります。Visual Studioによって作成されたDebugディレクトリに同梱のsyslib.oseをコピーしてください。 diff --git a/screen.c b/screen.c index 447a2c3..878a1c1 100644 --- a/screen.c +++ b/screen.c @@ -1,105 +1,105 @@ -#include "osecpu.h" - -void putOsaskChar(int c, HOSECPU_RuntimeEnvironment *r) -{ - if (0x10 <= c && c <= 0x1f){ - c = "0123456789ABCDEF"[c & 0x0f]; - } - putchar(c); - r->lastConsoleChar = c; - return; -} - -void checkString(HOSECPU_RuntimeEnvironment *r, int rxx, int pxx) -{ - char c = 0; - if (r->preg[pxx].typ != 0x03){ - c = 1; - } - if (r->preg[pxx].p < r->preg[pxx].p0){ - c = 1; - } - if (r->ireg[rxx] < 0){ - c = 1; - } - if (r->preg[pxx].p + r->ireg[rxx] > r->preg[pxx].p1){ - c = 1; - } - if (c != 0){ - (*(r->errHndl))(r); - } - return; -} - -int loadColor(HOSECPU_RuntimeEnvironment *r, int rxx) -{ - int c, m, rr, gg, bb; - c = r->ireg[rxx]; - m = r->ireg[0x31] & 0x0c; - if (m == 0x04) { - if (c < -1 || c > 7){ - (*(r->errHndl))(r); - } - c = iColor1[c & 0x07]; - } - if (m == 0x08) { - // 00, 24, 48, 6d, 91, b6, da, ff - if (c < 0 || c >= (1 << 9)){ - (*(r->errHndl))(r); - } - rr = (c >> 6) & 0x07; - gg = (c >> 3) & 0x07; - bb = c & 0x07; - rr = (rr * 255) / 7; - gg = (gg * 255) / 7; - bb = (bb * 255) / 7; - c = rr << 16 | gg << 8 | bb; - } - if (m == 0x0c) { - // 00, 08, 10, 18, 20, 29, 31, 39, - // 41, 4a, 52, 5a, 62, 6a, 73, 7b, - // 83, 8b, 94, 9c, a4, ac, b4, bd, - // c5, cd, d5, de, e6, ee, f6, ff - if (c < 0 || c >= (1 << 15)){ - (*(r->errHndl))(r); - } - rr = (c >> 10) & 0x1f; - gg = (c >> 5) & 0x1f; - bb = c & 0x1f; - rr = (rr * 255) / 31; - gg = (gg * 255) / 31; - bb = (bb * 255) / 31; - c = rr << 16 | gg << 8 | bb; - } - return c; -} - -void checkRect(HOSECPU_RuntimeEnvironment *r, int rxx) -{ - char c = 0; - int i; - if (r->ireg[rxx + 0] <= 0 || r->ireg[rxx + 0] > mainWindow.xsize){ - c = 1; - } - if (r->ireg[rxx + 1] <= 0 || r->ireg[rxx + 1] > mainWindow.ysize){ - c = 1; - } - if (r->ireg[rxx + 2] < 0 || r->ireg[rxx + 2] >= mainWindow.xsize){ - c = 1; - } - if (r->ireg[rxx + 3] < 0 || r->ireg[rxx + 3] >= mainWindow.ysize){ - c = 1; - } - i = r->ireg[rxx + 2] + r->ireg[rxx + 0]; - if (i <= 0 || i > mainWindow.xsize){ - c = 1; - } - i = r->ireg[rxx + 1] + r->ireg[rxx + 3]; - if (i <= 0 || i > mainWindow.ysize){ - c = 1; - } - if (c != 0){ - (*(r->errHndl))(r); - } - return; +#include "osecpu.h" + +void putOsaskChar(int c, HOSECPU_RuntimeEnvironment *r) +{ + if (0x10 <= c && c <= 0x1f){ + c = "0123456789ABCDEF"[c & 0x0f]; + } + putchar(c); + r->lastConsoleChar = c; + return; +} + +void checkString(HOSECPU_RuntimeEnvironment *r, int rxx, int pxx) +{ + char c = 0; + if (r->preg[pxx].typ != 0x03){ + c = 1; + } + if (r->preg[pxx].p < r->preg[pxx].p0){ + c = 1; + } + if (r->ireg[rxx] < 0){ + c = 1; + } + if (r->preg[pxx].p + r->ireg[rxx] > r->preg[pxx].p1){ + c = 1; + } + if (c != 0){ + (*(r->errHndl))(r); + } + return; +} + +int loadColor(HOSECPU_RuntimeEnvironment *r, int rxx) +{ + int c, m, rr, gg, bb; + c = r->ireg[rxx]; + m = r->ireg[0x31] & 0x0c; + if (m == 0x04) { + if (c < -1 || c > 7){ + (*(r->errHndl))(r); + } + c = iColor1[c & 0x07]; + } + if (m == 0x08) { + // 00, 24, 48, 6d, 91, b6, da, ff + if (c < 0 || c >= (1 << 9)){ + (*(r->errHndl))(r); + } + rr = (c >> 6) & 0x07; + gg = (c >> 3) & 0x07; + bb = c & 0x07; + rr = (rr * 255) / 7; + gg = (gg * 255) / 7; + bb = (bb * 255) / 7; + c = rr << 16 | gg << 8 | bb; + } + if (m == 0x0c) { + // 00, 08, 10, 18, 20, 29, 31, 39, + // 41, 4a, 52, 5a, 62, 6a, 73, 7b, + // 83, 8b, 94, 9c, a4, ac, b4, bd, + // c5, cd, d5, de, e6, ee, f6, ff + if (c < 0 || c >= (1 << 15)){ + (*(r->errHndl))(r); + } + rr = (c >> 10) & 0x1f; + gg = (c >> 5) & 0x1f; + bb = c & 0x1f; + rr = (rr * 255) / 31; + gg = (gg * 255) / 31; + bb = (bb * 255) / 31; + c = rr << 16 | gg << 8 | bb; + } + return c; +} + +void checkRect(HOSECPU_RuntimeEnvironment *r, int rxx) +{ + char c = 0; + int i; + if (r->ireg[rxx + 0] <= 0 || r->ireg[rxx + 0] > mainWindow.xsize){ + c = 1; + } + if (r->ireg[rxx + 1] <= 0 || r->ireg[rxx + 1] > mainWindow.ysize){ + c = 1; + } + if (r->ireg[rxx + 2] < 0 || r->ireg[rxx + 2] >= mainWindow.xsize){ + c = 1; + } + if (r->ireg[rxx + 3] < 0 || r->ireg[rxx + 3] >= mainWindow.ysize){ + c = 1; + } + i = r->ireg[rxx + 2] + r->ireg[rxx + 0]; + if (i <= 0 || i > mainWindow.xsize){ + c = 1; + } + i = r->ireg[rxx + 1] + r->ireg[rxx + 3]; + if (i <= 0 || i > mainWindow.ysize){ + c = 1; + } + if (c != 0){ + (*(r->errHndl))(r); + } + return; } \ No newline at end of file -- 2.11.0