diff --git a/Mini vMac.xcodeproj/project.pbxproj b/Mini vMac.xcodeproj/project.pbxproj index 2347a5d..76e88af 100644 --- a/Mini vMac.xcodeproj/project.pbxproj +++ b/Mini vMac.xcodeproj/project.pbxproj @@ -218,10 +218,8 @@ 2834232D1CF9C0F10088B634 /* DISAM68K.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = DISAM68K.c; sourceTree = ""; }; 2834232E1CF9C0F10088B634 /* DISAM68K.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = DISAM68K.h; sourceTree = ""; }; 2834232F1CF9C0F10088B634 /* ENDIANAC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ENDIANAC.h; sourceTree = ""; }; - 283423301CF9C0F10088B634 /* FB1BPP2I.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = FB1BPP2I.h; sourceTree = ""; }; 283423311CF9C0F10088B634 /* FPCPEMDV.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = FPCPEMDV.h; sourceTree = ""; }; 283423321CF9C0F10088B634 /* FPMATHEM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = FPMATHEM.h; sourceTree = ""; }; - 283423331CF9C0F10088B634 /* FPMATHNT.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = FPMATHNT.h; sourceTree = ""; }; 283423341CF9C0F10088B634 /* GLOBGLUE.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = GLOBGLUE.c; sourceTree = ""; }; 283423351CF9C0F10088B634 /* GLOBGLUE.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = GLOBGLUE.h; sourceTree = ""; }; 283423361CF9C0F10088B634 /* INTLCHAR.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = INTLCHAR.h; sourceTree = ""; }; @@ -257,7 +255,6 @@ 283423541CF9C0F10088B634 /* SNDEMDEV.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = SNDEMDEV.h; sourceTree = ""; }; 283423551CF9C0F10088B634 /* SONYEMDV.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = SONYEMDV.c; sourceTree = ""; }; 283423561CF9C0F10088B634 /* SONYEMDV.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = SONYEMDV.h; sourceTree = ""; }; - 283423571CF9C0F10088B634 /* STRCONST.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = STRCONST.h; sourceTree = ""; }; 283423581CF9C0F10088B634 /* SYSDEPNS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = SYSDEPNS.h; sourceTree = ""; }; 283423591CF9C0F10088B634 /* VIA2EMDV.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = VIA2EMDV.c; sourceTree = ""; }; 2834235A1CF9C0F10088B634 /* VIA2EMDV.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = VIA2EMDV.h; sourceTree = ""; }; @@ -301,6 +298,8 @@ 28BDBEB71D230EEB0072ED5B /* MacII-640x480.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = "MacII-640x480.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; 28BDBEBA1D230F280072ED5B /* CNFGGLOB.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CNFGGLOB.h; sourceTree = ""; }; 28BDBEBB1D230F280072ED5B /* EMCONFIG.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EMCONFIG.h; sourceTree = ""; }; + 28C63A5D1F76970000BB02B3 /* HPMCHACK.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HPMCHACK.h; sourceTree = ""; }; + 28C63A5E1F76979500BB02B3 /* STRCNENG.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = STRCNENG.h; sourceTree = ""; }; 28CE8ECB1CD4CDC500FE25A8 /* MYOSGLUE.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYOSGLUE.m; sourceTree = ""; }; 28CE8ED41CD4F56C00FE25A8 /* ScreenView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScreenView.h; sourceTree = ""; }; 28CE8ED51CD4F56C00FE25A8 /* ScreenView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScreenView.m; sourceTree = ""; }; @@ -479,12 +478,11 @@ 2834232D1CF9C0F10088B634 /* DISAM68K.c */, 2834232E1CF9C0F10088B634 /* DISAM68K.h */, 2834232F1CF9C0F10088B634 /* ENDIANAC.h */, - 283423301CF9C0F10088B634 /* FB1BPP2I.h */, 283423311CF9C0F10088B634 /* FPCPEMDV.h */, 283423321CF9C0F10088B634 /* FPMATHEM.h */, - 283423331CF9C0F10088B634 /* FPMATHNT.h */, 283423341CF9C0F10088B634 /* GLOBGLUE.c */, 283423351CF9C0F10088B634 /* GLOBGLUE.h */, + 28C63A5D1F76970000BB02B3 /* HPMCHACK.h */, 283423361CF9C0F10088B634 /* INTLCHAR.h */, 283423371CF9C0F10088B634 /* IWMEMDEV.c */, 283423381CF9C0F10088B634 /* IWMEMDEV.h */, @@ -518,7 +516,7 @@ 283423541CF9C0F10088B634 /* SNDEMDEV.h */, 283423551CF9C0F10088B634 /* SONYEMDV.c */, 283423561CF9C0F10088B634 /* SONYEMDV.h */, - 283423571CF9C0F10088B634 /* STRCONST.h */, + 28C63A5E1F76979500BB02B3 /* STRCNENG.h */, 283423581CF9C0F10088B634 /* SYSDEPNS.h */, 283423591CF9C0F10088B634 /* VIA2EMDV.c */, 2834235A1CF9C0F10088B634 /* VIA2EMDV.h */, diff --git a/Mini vMac/Assets.xcassets/AppIcon.appiconset/Contents.json b/Mini vMac/Assets.xcassets/AppIcon.appiconset/Contents.json index 5100f1b..4aba9b4 100644 --- a/Mini vMac/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Mini vMac/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,5 +1,15 @@ { "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, { "size" : "29x29", "idiom" : "iphone", @@ -36,6 +46,16 @@ "filename" : "Icon-60@3x.png", "scale" : "3x" }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, { "size" : "29x29", "idiom" : "ipad", diff --git a/Mini vMac/Base.lproj/Main.storyboard b/Mini vMac/Base.lproj/Main.storyboard index ccd7e87..3249eca 100644 --- a/Mini vMac/Base.lproj/Main.storyboard +++ b/Mini vMac/Base.lproj/Main.storyboard @@ -1,9 +1,13 @@ - - + + + + + - + + @@ -15,15 +19,15 @@ - + - + - + - + @@ -46,18 +50,18 @@ - + - + - + - + - + @@ -81,13 +85,13 @@ - + - + - + @@ -108,41 +112,41 @@ - + - + - + - + @@ -150,41 +154,41 @@ - + - + - + - + @@ -235,29 +239,29 @@ - + - + - + - + @@ -317,7 +321,7 @@ - + diff --git a/Mini vMac/CNFGGLOB.h b/Mini vMac/CNFGGLOB.h index 99ec54d..e7cb2de 100644 --- a/Mini vMac/CNFGGLOB.h +++ b/Mini vMac/CNFGGLOB.h @@ -29,8 +29,8 @@ typedef uint32_t ui5b; typedef int32_t si5b; #define HaveRealsi5b 1 -#define HaveRealui6b 0 -#define HaveRealsi6b 0 +#define HaveRealui6b 1 +#define HaveRealsi6b 1 /* --- integer representation types ---- */ @@ -62,8 +62,8 @@ typedef uint64_t ui6b; #define NeedIntlChars 1 #define kStrAppName "Mini vMac" -#define kAppVariationStr "minivmac-3.4.0-ios" -#define kStrCopyrightYear "2016" +#define kAppVariationStr "minivmac-3.5.8-ios" +#define kStrCopyrightYear "2017" #define kMaintainerName "Jesús A. Álvarez" #define kStrHomePage "https://namedfork.net/minivmac" #define VarFullScreen 0 diff --git a/Mini vMac/Info.plist b/Mini vMac/Info.plist index f16e691..5c7c337 100644 --- a/Mini vMac/Info.plist +++ b/Mini vMac/Info.plist @@ -71,6 +71,8 @@ APPL CFBundleShortVersionString 2.2.3 + MNVMVersion + 3.5.8 CFBundleSignature ???? CFBundleVersion diff --git a/Mini vMac/MYOSGLUE.m b/Mini vMac/MYOSGLUE.m index e5e2bb1..8e885a4 100644 --- a/Mini vMac/MYOSGLUE.m +++ b/Mini vMac/MYOSGLUE.m @@ -30,7 +30,7 @@ #include "SYSDEPNS.h" #include "ENDIANAC.h" #include "MYOSGLUE.h" -#include "STRCONST.h" +#include "STRCNENG.h" #include "EMCONFIG.h" #import "EmulatorProtocol.h" diff --git a/Mini vMac/mnvm_core/ACTVCODE.h b/Mini vMac/mnvm_core/ACTVCODE.h index 410a24b..fa46353 100755 --- a/Mini vMac/mnvm_core/ACTVCODE.h +++ b/Mini vMac/mnvm_core/ACTVCODE.h @@ -1,394 +1 @@ -/* - ACTVCODE.h - - Copyright (C) 2009 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - ACTiVation CODE -*/ - -LOCALFUNC uimr KeyFun0(uimr x, uimr y, uimr m) -{ - uimr r = x + y; - - if ((r >= m) || (r < x)) { - r -= m; - } - - return r; -} - -LOCALFUNC uimr KeyFun1(uimr x, uimr y, uimr m) -{ - uimr r = 0; - uimr t = x; - uimr s = y; - - while (s > 0) { - if (0 != (s & 1)) { - r = KeyFun0(r, t, m); - } - t = KeyFun0(t, t, m); - s >>= 1; - } - - return r; -} - -LOCALFUNC uimr KeyFun2(uimr x, uimr y, uimr m) -{ - uimr r = 1; - uimr t = x; - uimr s = y; - - while (s > 0) { - if (0 != (s & 1)) { - r = KeyFun1(r, t, m); - } - t = KeyFun1(t, t, m); - s >>= 1; - } - - return r; -} - -LOCALFUNC blnr CheckActvCode(ui3p p, blnr *Trial) -{ - blnr IsOk = falseblnr; - uimr v0 = do_get_mem_long(p); - uimr v1 = do_get_mem_long(p + 4); - - if (v0 > KeyCon2) { - /* v0 too big */ - } else if (v1 > KeyCon4) { - /* v1 too big */ - } else { - uimr t0 = KeyFun0(v0, KeyCon0, KeyCon2); - uimr t1 = KeyFun2(KeyCon1, t0, KeyCon2); - uimr t2 = KeyFun2(v1, KeyCon3, KeyCon4); - uimr t3 = KeyFun0(t2, KeyCon4 - t1, KeyCon4); - uimr t4 = KeyFun0(t3, KeyCon4 - KeyCon5, KeyCon4); - if ((0 == (t4 >> 8)) && (t4 >= KeyCon6)) { - *Trial = falseblnr; - IsOk = trueblnr; - } else if (0 == t4) { - *Trial = trueblnr; - IsOk = trueblnr; - } - } - - return IsOk; -} - -/* user interface */ - -LOCALFUNC blnr Key2Digit(int key, ui3r *r) -{ - ui3r v; - - switch (key) { - case MKC_0: - case MKC_KP0: - v = 0; - break; - case MKC_1: - case MKC_KP1: - v = 1; - break; - case MKC_2: - case MKC_KP2: - v = 2; - break; - case MKC_3: - case MKC_KP3: - v = 3; - break; - case MKC_4: - case MKC_KP4: - v = 4; - break; - case MKC_5: - case MKC_KP5: - v = 5; - break; - case MKC_6: - case MKC_KP6: - v = 6; - break; - case MKC_7: - case MKC_KP7: - v = 7; - break; - case MKC_8: - case MKC_KP8: - v = 8; - break; - case MKC_9: - case MKC_KP9: - v = 9; - break; - default: - return falseblnr; - break; - } - - *r = v; - return trueblnr; -} - -#define ActvCodeMaxLen 20 -LOCALVAR ui4r ActvCodeLen = 0; -LOCALVAR ui3b ActvCodeDigits[ActvCodeMaxLen]; - -#define ActvCodeFileLen 8 - -#if UseActvFile -FORWARDFUNC tMacErr ActvCodeFileSave(ui3p p); -FORWARDFUNC tMacErr ActvCodeFileLoad(ui3p p); -#endif - -LOCALVAR ui3b CurActvCode[ActvCodeFileLen]; - -LOCALPROC DoActvCodeModeKey(int key) -{ - ui3r digit; - ui3r L; - int i; - blnr Trial; - - if (MKC_BackSpace == key) { - if (ActvCodeLen > 0) { - --ActvCodeLen; - NeedWholeScreenDraw = trueblnr; - } - } else if (Key2Digit(key, &digit)) { - if (ActvCodeLen < (ActvCodeMaxLen - 1)) { - ActvCodeDigits[ActvCodeLen] = digit; - ++ActvCodeLen; - NeedWholeScreenDraw = trueblnr; - L = ActvCodeDigits[0] + (1 + 9); - if (ActvCodeLen == L) { - uimr v0 = 0; - uimr v1 = 0; - - for (i = 1; i < (ActvCodeDigits[0] + 1); ++i) { - v0 = v0 * 10 + ActvCodeDigits[i]; - } - for (; i < ActvCodeLen; ++i) { - v1 = v1 * 10 + ActvCodeDigits[i]; - } - - do_put_mem_long(&CurActvCode[0], v0); - do_put_mem_long(&CurActvCode[4], v1); - - if (CheckActvCode(CurActvCode, &Trial)) { - SpecialModeClr(SpclModeActvCode); - NeedWholeScreenDraw = trueblnr; -#if UseActvFile - if (Trial) { - MacMsg( - "Using temporary code.", - "Thank you for trying Mini vMac!", - falseblnr); - } else { - if (mnvm_noErr != ActvCodeFileSave(CurActvCode)) - { - MacMsg("Oops", - "I could not save the activation code" - " to disk.", - falseblnr); - } else { - MacMsg("Activation succeeded.", - "Thank you!", falseblnr); - } - } -#else - MacMsg( - "Thank you for trying Mini vMac!", - "sample variation : ^v", - falseblnr); -#endif - } - } else if (ActvCodeLen > L) { - --ActvCodeLen; - } - } - } -} - -LOCALPROC DrawCellsActvCodeModeBody(void) -{ -#if UseActvFile - DrawCellsOneLineStr("Please enter your activation code:"); - DrawCellsBlankLine(); -#else - DrawCellsOneLineStr( - "To try this variation of ^p, please type these numbers:"); - DrawCellsBlankLine(); - DrawCellsOneLineStr("281 953 822 340"); - DrawCellsBlankLine(); -#endif - - if (0 == ActvCodeLen) { - DrawCellsOneLineStr("?"); - } else { - int i; - ui3r L = ActvCodeDigits[0] + (1 + 9); - - DrawCellsBeginLine(); - for (i = 0; i < L; ++i) { - if (0 == ((L - i) % 3)) { - if (0 != i) { - DrawCellAdvance(kCellSpace); - } - } - if (i < ActvCodeLen) { - DrawCellAdvance(kCellDigit0 + ActvCodeDigits[i]); - } else if (i == ActvCodeLen) { - DrawCellAdvance(kCellQuestion); - } else { - DrawCellAdvance(kCellHyphen); - } - } - DrawCellsEndLine(); - if (L == ActvCodeLen) { - DrawCellsBlankLine(); - DrawCellsOneLineStr( - "Sorry, this is not a valid activation code."); - } - } - -#if UseActvFile - DrawCellsBlankLine(); - DrawCellsOneLineStr( - "If you haven;}t obtained an activation code yet," - " here is a temporary one:"); - DrawCellsBlankLine(); - DrawCellsOneLineStr("281 953 822 340"); -#else - DrawCellsBlankLine(); - DrawCellsOneLineStr(kStrForMoreInfo); - DrawCellsOneLineStr("http://www.gryphel.com/c/var/"); -#endif -} - -LOCALPROC DrawActvCodeMode(void) -{ - DrawSpclMode0( -#if UseActvFile - "Activation Code", -#else - "sample variation : ^v", -#endif - DrawCellsActvCodeModeBody); -} - -#if UseActvFile -LOCALPROC ClStrAppendHexNib(int *L0, ui3b *r, ui3r v) -{ - if (v < 10) { - ClStrAppendChar(L0, r, kCellDigit0 + v); - } else { - ClStrAppendChar(L0, r, kCellUpA + (v - 10)); - } -} - -LOCALPROC ClStrAppendHexByte(int *L0, ui3b *r, ui3r v) -{ - ClStrAppendHexNib(L0, r, (v >> 4) & 0x0F); - ClStrAppendHexNib(L0, r, v & 0x0F); -} - -LOCALPROC ClStrAppendHexWord(int *L0, ui3b *r, ui4r v) -{ - ClStrAppendHexByte(L0, r, (v >> 8) & 0xFF); - ClStrAppendHexByte(L0, r, v & 0xFF); -} - -LOCALPROC ClStrAppendHexLong(int *L0, ui3b *r, ui5r v) -{ - ClStrAppendHexWord(L0, r, (v >> 16) & 0xFFFF); - ClStrAppendHexWord(L0, r, v & 0xFFFF); -} -#endif - -LOCALPROC CopyRegistrationStr(void) -{ - ui3b ps[ClStrMaxLength]; - int i; - int L; - tPbuf j; -#if UseActvFile - int L0; - ui5r sum; - - ClStrFromSubstCStr(&L0, ps, "^v "); - - for (i = 0; i < L0; ++i) { - ps[i] = Cell2MacAsciiMap[ps[i]]; - } - L = L0; - - sum = 0; - for (i = 0; i < L; ++i) { - sum += ps[i]; - sum = (sum << 5) | ((sum >> (32 - 5)) & 0x1F); - sum += (sum << 8); - } - - sum &= 0x1FFFFFFF; - - sum = KeyFun0(sum, do_get_mem_long(&CurActvCode[0]), KeyCon4); - - ClStrAppendHexLong(&L, ps, sum); - - sum = KeyFun0(sum, do_get_mem_long(&CurActvCode[4]), KeyCon4); - sum = KeyFun2(sum, KeyCon3, KeyCon4); - - ClStrAppendHexLong(&L, ps, sum); - - for (i = L0; i < L; ++i) { - ps[i] = Cell2MacAsciiMap[ps[i]]; - } -#else - ClStrFromSubstCStr(&L, ps, "^v"); - - for (i = 0; i < L; ++i) { - ps[i] = Cell2MacAsciiMap[ps[i]]; - } -#endif - - if (mnvm_noErr == PbufNew(L, &j)) { - PbufTransfer(ps, j, 0, L, trueblnr); - HTCEexport(j); - } -} - -LOCALFUNC blnr ActvCodeInit(void) -{ -#if UseActvFile - blnr Trial; - - if ((mnvm_noErr != ActvCodeFileLoad(CurActvCode)) - || (! CheckActvCode(CurActvCode, &Trial)) - || Trial - ) -#endif - { - SpecialModeSet(SpclModeActvCode); - NeedWholeScreenDraw = trueblnr; - } - - return trueblnr; -} +/* ACTVCODE.h Copyright (C) 2009 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* ACTiVation CODE */ LOCALFUNC uimr KeyFun0(uimr x, uimr y, uimr m) { uimr r = x + y; if ((r >= m) || (r < x)) { r -= m; } return r; } LOCALFUNC uimr KeyFun1(uimr x, uimr y, uimr m) { uimr r = 0; uimr t = x; uimr s = y; while (s > 0) { if (0 != (s & 1)) { r = KeyFun0(r, t, m); } t = KeyFun0(t, t, m); s >>= 1; } return r; } LOCALFUNC uimr KeyFun2(uimr x, uimr y, uimr m) { uimr r = 1; uimr t = x; uimr s = y; while (s > 0) { if (0 != (s & 1)) { r = KeyFun1(r, t, m); } t = KeyFun1(t, t, m); s >>= 1; } return r; } LOCALFUNC blnr CheckActvCode(ui3p p, blnr *Trial) { blnr IsOk = falseblnr; uimr v0 = do_get_mem_long(p); uimr v1 = do_get_mem_long(p + 4); if (v0 > KeyCon2) { /* v0 too big */ } else if (v1 > KeyCon4) { /* v1 too big */ } else { uimr t0 = KeyFun0(v0, KeyCon0, KeyCon2); uimr t1 = KeyFun2(KeyCon1, t0, KeyCon2); uimr t2 = KeyFun2(v1, KeyCon3, KeyCon4); uimr t3 = KeyFun0(t2, KeyCon4 - t1, KeyCon4); uimr t4 = KeyFun0(t3, KeyCon4 - KeyCon5, KeyCon4); if ((0 == (t4 >> 8)) && (t4 >= KeyCon6)) { *Trial = falseblnr; IsOk = trueblnr; } else if (0 == t4) { *Trial = trueblnr; IsOk = trueblnr; } } return IsOk; } /* user interface */ LOCALFUNC blnr Key2Digit(int key, ui3r *r) { ui3r v; switch (key) { case MKC_0: case MKC_KP0: v = 0; break; case MKC_1: case MKC_KP1: v = 1; break; case MKC_2: case MKC_KP2: v = 2; break; case MKC_3: case MKC_KP3: v = 3; break; case MKC_4: case MKC_KP4: v = 4; break; case MKC_5: case MKC_KP5: v = 5; break; case MKC_6: case MKC_KP6: v = 6; break; case MKC_7: case MKC_KP7: v = 7; break; case MKC_8: case MKC_KP8: v = 8; break; case MKC_9: case MKC_KP9: v = 9; break; default: return falseblnr; break; } *r = v; return trueblnr; } #define ActvCodeMaxLen 20 LOCALVAR ui4r ActvCodeLen = 0; LOCALVAR ui3b ActvCodeDigits[ActvCodeMaxLen]; #define ActvCodeFileLen 8 #if UseActvFile FORWARDFUNC tMacErr ActvCodeFileSave(ui3p p); FORWARDFUNC tMacErr ActvCodeFileLoad(ui3p p); #endif LOCALVAR ui3b CurActvCode[ActvCodeFileLen]; LOCALPROC DoActvCodeModeKey(int key) { ui3r digit; ui3r L; int i; blnr Trial; if (MKC_BackSpace == key) { if (ActvCodeLen > 0) { --ActvCodeLen; NeedWholeScreenDraw = trueblnr; } } else if (Key2Digit(key, &digit)) { if (ActvCodeLen < (ActvCodeMaxLen - 1)) { ActvCodeDigits[ActvCodeLen] = digit; ++ActvCodeLen; NeedWholeScreenDraw = trueblnr; L = ActvCodeDigits[0] + (1 + 9); if (ActvCodeLen == L) { uimr v0 = 0; uimr v1 = 0; for (i = 1; i < (ActvCodeDigits[0] + 1); ++i) { v0 = v0 * 10 + ActvCodeDigits[i]; } for (; i < ActvCodeLen; ++i) { v1 = v1 * 10 + ActvCodeDigits[i]; } do_put_mem_long(&CurActvCode[0], v0); do_put_mem_long(&CurActvCode[4], v1); if (CheckActvCode(CurActvCode, &Trial)) { SpecialModeClr(SpclModeActvCode); NeedWholeScreenDraw = trueblnr; #if UseActvFile if (Trial) { MacMsg( "Using temporary code.", "Thank you for trying Mini vMac!", falseblnr); } else { if (mnvm_noErr != ActvCodeFileSave(CurActvCode)) { MacMsg("Oops", "I could not save the activation code" " to disk.", falseblnr); } else { MacMsg("Activation succeeded.", "Thank you!", falseblnr); } } #else MacMsg( "Thank you for trying Mini vMac!", "sample variation : ^v", falseblnr); #endif } } else if (ActvCodeLen > L) { --ActvCodeLen; } } } } LOCALPROC DrawCellsActvCodeModeBody(void) { #if UseActvFile DrawCellsOneLineStr("Please enter your activation code:"); DrawCellsBlankLine(); #else DrawCellsOneLineStr( "To try this variation of ^p, please type these numbers:"); DrawCellsBlankLine(); DrawCellsOneLineStr("281 953 822 340"); DrawCellsBlankLine(); #endif if (0 == ActvCodeLen) { DrawCellsOneLineStr("?"); } else { int i; ui3r L = ActvCodeDigits[0] + (1 + 9); DrawCellsBeginLine(); for (i = 0; i < L; ++i) { if (0 == ((L - i) % 3)) { if (0 != i) { DrawCellAdvance(kCellSpace); } } if (i < ActvCodeLen) { DrawCellAdvance(kCellDigit0 + ActvCodeDigits[i]); } else if (i == ActvCodeLen) { DrawCellAdvance(kCellQuestion); } else { DrawCellAdvance(kCellHyphen); } } DrawCellsEndLine(); if (L == ActvCodeLen) { DrawCellsBlankLine(); DrawCellsOneLineStr( "Sorry, this is not a valid activation code."); } } #if UseActvFile DrawCellsBlankLine(); DrawCellsOneLineStr( "If you haven;}t obtained an activation code yet," " here is a temporary one:"); DrawCellsBlankLine(); DrawCellsOneLineStr("281 953 822 340"); #else DrawCellsBlankLine(); DrawCellsOneLineStr(kStrForMoreInfo); DrawCellsOneLineStr("http://www.gryphel.com/c/var/"); #endif } LOCALPROC DrawActvCodeMode(void) { DrawSpclMode0( #if UseActvFile "Activation Code", #else "sample variation : ^v", #endif DrawCellsActvCodeModeBody); } #if UseActvFile LOCALPROC ClStrAppendHexLong(int *L0, ui3b *r, ui5r v) { ClStrAppendHexWord(L0, r, (v >> 16) & 0xFFFF); ClStrAppendHexWord(L0, r, v & 0xFFFF); } #endif LOCALPROC CopyRegistrationStr(void) { ui3b ps[ClStrMaxLength]; int i; int L; tPbuf j; #if UseActvFile int L0; ui5r sum; ClStrFromSubstCStr(&L0, ps, "^v "); for (i = 0; i < L0; ++i) { ps[i] = Cell2MacAsciiMap[ps[i]]; } L = L0; sum = 0; for (i = 0; i < L; ++i) { sum += ps[i]; sum = (sum << 5) | ((sum >> (32 - 5)) & 0x1F); sum += (sum << 8); } sum &= 0x1FFFFFFF; sum = KeyFun0(sum, do_get_mem_long(&CurActvCode[0]), KeyCon4); ClStrAppendHexLong(&L, ps, sum); sum = KeyFun0(sum, do_get_mem_long(&CurActvCode[4]), KeyCon4); sum = KeyFun2(sum, KeyCon3, KeyCon4); ClStrAppendHexLong(&L, ps, sum); for (i = L0; i < L; ++i) { ps[i] = Cell2MacAsciiMap[ps[i]]; } #else ClStrFromSubstCStr(&L, ps, "^v"); for (i = 0; i < L; ++i) { ps[i] = Cell2MacAsciiMap[ps[i]]; } #endif if (mnvm_noErr == PbufNew(L, &j)) { PbufTransfer(ps, j, 0, L, trueblnr); HTCEexport(j); } } LOCALFUNC blnr ActvCodeInit(void) { #if UseActvFile blnr Trial; if ((mnvm_noErr != ActvCodeFileLoad(CurActvCode)) || (! CheckActvCode(CurActvCode, &Trial)) || Trial ) #endif { SpecialModeSet(SpclModeActvCode); NeedWholeScreenDraw = trueblnr; } return trueblnr; } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/ADBEMDEV.c b/Mini vMac/mnvm_core/ADBEMDEV.c index c841c29..7b237e9 100755 --- a/Mini vMac/mnvm_core/ADBEMDEV.c +++ b/Mini vMac/mnvm_core/ADBEMDEV.c @@ -1,207 +1 @@ -/* - ADBEMDEV.c - - Copyright (C) 2008 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - Apple Desktop Bus EMulated DEVice -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" -#include "MYOSGLUE.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" -#endif - -#include "ADBEMDEV.h" - -#ifdef _VIA_Debug -#include -#endif - -IMPORTPROC ADB_ShiftOutData(ui3b v); -IMPORTFUNC ui3b ADB_ShiftInData(void); - -#include "ADBSHARE.h" - -LOCALVAR blnr ADB_ListenDatBuf; -LOCALVAR ui3b ADB_IndexDatBuf; - -GLOBALPROC ADB_DoNewState(void) -{ - ui3b state = ADB_st1 * 2 + ADB_st0; -#ifdef _VIA_Debug - fprintf(stderr, "ADB_DoNewState: %d\n", state); -#endif - { - ADB_Int = 1; - switch (state) { - case 0: /* Start a new command */ - if (ADB_ListenDatBuf) { - ADB_ListenDatBuf = falseblnr; - ADB_SzDatBuf = ADB_IndexDatBuf; - ADB_EndListen(); - } - ADB_TalkDatBuf = falseblnr; - ADB_IndexDatBuf = 0; - ADB_CurCmd = ADB_ShiftInData(); - /* which sets interrupt, acknowleding command */ -#ifdef _VIA_Debug - fprintf(stderr, "in: %d\n", ADB_CurCmd); -#endif - switch ((ADB_CurCmd >> 2) & 3) { - case 0: /* reserved */ - switch (ADB_CurCmd & 3) { - case 0: /* Send Reset */ - ADB_DoReset(); - break; - case 1: /* Flush */ - ADB_Flush(); - break; - case 2: /* reserved */ - case 3: /* reserved */ - ReportAbnormal("Reserved ADB command"); - break; - } - break; - case 1: /* reserved */ - ReportAbnormal("Reserved ADB command"); - break; - case 2: /* listen */ - ADB_ListenDatBuf = trueblnr; -#ifdef _VIA_Debug - fprintf(stderr, "*** listening\n"); -#endif - break; - case 3: /* talk */ - ADB_DoTalk(); - break; - } - break; - case 1: /* Transfer date byte (even) */ - case 2: /* Transfer date byte (odd) */ - if (! ADB_ListenDatBuf) { - /* - will get here even if no pending talk data, - when there is pending event from device - other than the one polled by the last talk - command. this probably indicates a bug. - */ - if ((! ADB_TalkDatBuf) - || (ADB_IndexDatBuf >= ADB_SzDatBuf)) - { - ADB_ShiftOutData(0xFF); - ADB_Data = 1; - ADB_Int = 0; - } else { -#ifdef _VIA_Debug - fprintf(stderr, "*** talk one\n"); -#endif - ADB_ShiftOutData(ADB_DatBuf[ADB_IndexDatBuf]); - ADB_Data = 1; - ADB_IndexDatBuf += 1; - } - } else { - if (ADB_IndexDatBuf >= ADB_MaxSzDatBuf) { - ReportAbnormal("ADB listen too much"); - /* ADB_MaxSzDatBuf isn't big enough */ - (void) ADB_ShiftInData(); - } else { -#ifdef _VIA_Debug - fprintf(stderr, "*** listen one\n"); -#endif - ADB_DatBuf[ADB_IndexDatBuf] = ADB_ShiftInData(); - ADB_IndexDatBuf += 1; - } - } - break; - case 3: /* idle */ - if (ADB_ListenDatBuf) { - ReportAbnormal("ADB idle follows listen"); - /* apparently doesn't happen */ - } - if (ADB_TalkDatBuf) { - if (ADB_IndexDatBuf != 0) { - ReportAbnormal("idle when not done talking"); - } - ADB_ShiftOutData(0xFF); - /* ADB_Int = 0; */ - } else if (CheckForADBanyEvt()) { - if (((ADB_CurCmd >> 2) & 3) == 3) { - ADB_DoTalk(); - } - ADB_ShiftOutData(0xFF); - /* ADB_Int = 0; */ - } - break; - } - } -} - -GLOBALPROC ADBstate_ChangeNtfy(void) -{ -#ifdef _VIA_Debug - fprintf(stderr, "ADBstate_ChangeNtfy: %d, %d, %d\n", - ADB_st1, ADB_st0, GetCuriCount()); -#endif - ICT_add(kICT_ADB_NewState, - 348160UL * kCycleScale / 64 * kMyClockMult); - /* - Macintosh Family Hardware Reference say device "must respond - to talk command within 260 microseconds", which translates - to about 190 instructions. But haven't seen much problems - even for very large values (tens of thousands), and do see - problems for small values. 50 is definitely too small, - mouse doesn't move smoothly. There may still be some - signs of this problem with 150. - - On the other hand, how fast the device must respond may - not be related to how fast the ADB transceiver responds. - */ -} - -GLOBALPROC ADB_DataLineChngNtfy(void) -{ -#ifdef _VIA_Debug - fprintf(stderr, "ADB_DataLineChngNtfy: %d\n", ADB_Data); -#endif -} - -GLOBALPROC ADB_Update(void) -{ - ui3b state = ADB_st1 * 2 + ADB_st0; - - if (state == 3) { /* idle */ - if (ADB_TalkDatBuf) { - /* ignore, presumably being taken care of */ - } else if (CheckForADBanyEvt()) - { - if (((ADB_CurCmd >> 2) & 3) == 3) { - ADB_DoTalk(); - } - ADB_ShiftOutData(0xFF); - /* - Wouldn't expect this would be needed unless - there is actually talk data. But without it, - ADB never polls the other devices. Clearing - ADB_Int has no effect. - */ - /* - ADB_Int = 0; - seems to have no effect, which probably indicates a bug - */ - } - } -} +/* ADBEMDEV.c Copyright (C) 2008 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* Apple Desktop Bus EMulated DEVice */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif #include "ADBEMDEV.h" #ifdef _VIA_Debug #include #endif /* ReportAbnormalID unused 0x0C06 - 0x0CFF */ IMPORTPROC ADB_ShiftOutData(ui3b v); IMPORTFUNC ui3b ADB_ShiftInData(void); #include "ADBSHARE.h" LOCALVAR blnr ADB_ListenDatBuf; LOCALVAR ui3b ADB_IndexDatBuf; GLOBALPROC ADB_DoNewState(void) { ui3b state = ADB_st1 * 2 + ADB_st0; #ifdef _VIA_Debug fprintf(stderr, "ADB_DoNewState: %d\n", state); #endif { ADB_Int = 1; switch (state) { case 0: /* Start a new command */ if (ADB_ListenDatBuf) { ADB_ListenDatBuf = falseblnr; ADB_SzDatBuf = ADB_IndexDatBuf; ADB_EndListen(); } ADB_TalkDatBuf = falseblnr; ADB_IndexDatBuf = 0; ADB_CurCmd = ADB_ShiftInData(); /* which sets interrupt, acknowleding command */ #ifdef _VIA_Debug fprintf(stderr, "in: %d\n", ADB_CurCmd); #endif switch ((ADB_CurCmd >> 2) & 3) { case 0: /* reserved */ switch (ADB_CurCmd & 3) { case 0: /* Send Reset */ ADB_DoReset(); break; case 1: /* Flush */ ADB_Flush(); break; case 2: /* reserved */ case 3: /* reserved */ ReportAbnormalID(0x0C01, "Reserved ADB command"); break; } break; case 1: /* reserved */ ReportAbnormalID(0x0C02, "Reserved ADB command"); break; case 2: /* listen */ ADB_ListenDatBuf = trueblnr; #ifdef _VIA_Debug fprintf(stderr, "*** listening\n"); #endif break; case 3: /* talk */ ADB_DoTalk(); break; } break; case 1: /* Transfer date byte (even) */ case 2: /* Transfer date byte (odd) */ if (! ADB_ListenDatBuf) { /* will get here even if no pending talk data, when there is pending event from device other than the one polled by the last talk command. this probably indicates a bug. */ if ((! ADB_TalkDatBuf) || (ADB_IndexDatBuf >= ADB_SzDatBuf)) { ADB_ShiftOutData(0xFF); ADB_Data = 1; ADB_Int = 0; } else { #ifdef _VIA_Debug fprintf(stderr, "*** talk one\n"); #endif ADB_ShiftOutData(ADB_DatBuf[ADB_IndexDatBuf]); ADB_Data = 1; ADB_IndexDatBuf += 1; } } else { if (ADB_IndexDatBuf >= ADB_MaxSzDatBuf) { ReportAbnormalID(0x0C03, "ADB listen too much"); /* ADB_MaxSzDatBuf isn't big enough */ (void) ADB_ShiftInData(); } else { #ifdef _VIA_Debug fprintf(stderr, "*** listen one\n"); #endif ADB_DatBuf[ADB_IndexDatBuf] = ADB_ShiftInData(); ADB_IndexDatBuf += 1; } } break; case 3: /* idle */ if (ADB_ListenDatBuf) { ReportAbnormalID(0x0C04, "ADB idle follows listen"); /* apparently doesn't happen */ } if (ADB_TalkDatBuf) { if (ADB_IndexDatBuf != 0) { ReportAbnormalID(0x0C05, "idle when not done talking"); } ADB_ShiftOutData(0xFF); /* ADB_Int = 0; */ } else if (CheckForADBanyEvt()) { if (((ADB_CurCmd >> 2) & 3) == 3) { ADB_DoTalk(); } ADB_ShiftOutData(0xFF); /* ADB_Int = 0; */ } break; } } } GLOBALPROC ADBstate_ChangeNtfy(void) { #ifdef _VIA_Debug fprintf(stderr, "ADBstate_ChangeNtfy: %d, %d, %d\n", ADB_st1, ADB_st0, GetCuriCount()); #endif ICT_add(kICT_ADB_NewState, 348160UL * kCycleScale / 64 * kMyClockMult); /* Macintosh Family Hardware Reference say device "must respond to talk command within 260 microseconds", which translates to about 190 instructions. But haven't seen much problems even for very large values (tens of thousands), and do see problems for small values. 50 is definitely too small, mouse doesn't move smoothly. There may still be some signs of this problem with 150. On the other hand, how fast the device must respond may not be related to how fast the ADB transceiver responds. */ } GLOBALPROC ADB_DataLineChngNtfy(void) { #ifdef _VIA_Debug fprintf(stderr, "ADB_DataLineChngNtfy: %d\n", ADB_Data); #endif } GLOBALPROC ADB_Update(void) { ui3b state = ADB_st1 * 2 + ADB_st0; if (state == 3) { /* idle */ if (ADB_TalkDatBuf) { /* ignore, presumably being taken care of */ } else if (CheckForADBanyEvt()) { if (((ADB_CurCmd >> 2) & 3) == 3) { ADB_DoTalk(); } ADB_ShiftOutData(0xFF); /* Wouldn't expect this would be needed unless there is actually talk data. But without it, ADB never polls the other devices. Clearing ADB_Int has no effect. */ /* ADB_Int = 0; seems to have no effect, which probably indicates a bug */ } } } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/ADBEMDEV.h b/Mini vMac/mnvm_core/ADBEMDEV.h index 8216334..9f9f59e 100755 --- a/Mini vMac/mnvm_core/ADBEMDEV.h +++ b/Mini vMac/mnvm_core/ADBEMDEV.h @@ -1,27 +1 @@ -/* - ADBEMDEV.h - - Copyright (C) 2008 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef ADBEMDEV_H -#error "header already included" -#else -#define ADBEMDEV_H -#endif - - -EXPORTPROC ADBstate_ChangeNtfy(void); -EXPORTPROC ADB_DoNewState(void); -EXPORTPROC ADB_DataLineChngNtfy(void); -EXPORTPROC ADB_Update(void); +/* ADBEMDEV.h Copyright (C) 2008 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef ADBEMDEV_H #error "header already included" #else #define ADBEMDEV_H #endif EXPORTPROC ADBstate_ChangeNtfy(void); EXPORTPROC ADB_DoNewState(void); EXPORTPROC ADB_DataLineChngNtfy(void); EXPORTPROC ADB_Update(void); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/ADBSHARE.h b/Mini vMac/mnvm_core/ADBSHARE.h index 01ed40d..49cc545 100755 --- a/Mini vMac/mnvm_core/ADBSHARE.h +++ b/Mini vMac/mnvm_core/ADBSHARE.h @@ -1,282 +1 @@ -/* - ADBSHARE.h - - Copyright (C) 2008 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - Apple Desktop Bus SHAREd code - shared by emulation of different implementations of ADB -*/ - -#ifdef ADBSHARE_H -#error "header already included" -#else -#define ADBSHARE_H -#endif - - -#define ADB_MaxSzDatBuf 8 - -LOCALVAR ui3b ADB_SzDatBuf; -LOCALVAR blnr ADB_TalkDatBuf = falseblnr; -LOCALVAR ui3b ADB_DatBuf[ADB_MaxSzDatBuf]; -LOCALVAR ui3b ADB_CurCmd = 0; -LOCALVAR ui3b NotSoRandAddr = 1; - -LOCALVAR ui3b MouseADBAddress; -LOCALVAR blnr SavedCurMouseButton = falseblnr; -LOCALVAR ui4r MouseADBDeltaH = 0; -LOCALVAR ui4r MouseADBDeltaV = 0; - -LOCALPROC ADB_DoMouseTalk(void) -{ - switch (ADB_CurCmd & 3) { - case 0: - { - blnr overflow = falseblnr; - ui4b partH; - ui4b partV; - blnr MouseButtonChange = falseblnr; - MyEvtQEl *p = MyEvtQOutP(); - if (nullpr != p) { - if (MyEvtQElKindMouseDelta == p->kind) { - MouseADBDeltaH += p->u.pos.h; - MouseADBDeltaV += p->u.pos.v; - MyEvtQOutDone(); - } - } - partH = MouseADBDeltaH; - partV = MouseADBDeltaV; - - if ((si4b)MouseADBDeltaH < 0) { - partH = - partH; - } - if ((si4b)MouseADBDeltaV < 0) { - partV = - partV; - } - if ((partH >> 6) > 0) { - overflow = trueblnr; - partH = (1 << 6) - 1; - } - if ((partV >> 6) > 0) { - overflow = trueblnr; - partV = (1 << 6) - 1; - } - if ((si4b)MouseADBDeltaH < 0) { - partH = - partH; - } - if ((si4b)MouseADBDeltaV < 0) { - partV = - partV; - } - MouseADBDeltaH -= partH; - MouseADBDeltaV -= partV; - if (! overflow) { - MyEvtQEl *p = MyEvtQOutP(); - if (nullpr != p) { - if (MyEvtQElKindMouseButton == p->kind) { - SavedCurMouseButton = p->u.press.down; - MouseButtonChange = trueblnr; - MyEvtQOutDone(); - } - } - } - if ((0 != partH) || (0 != partV) || MouseButtonChange) { - ADB_SzDatBuf = 2; - ADB_TalkDatBuf = trueblnr; - ADB_DatBuf[0] = (SavedCurMouseButton ? 0x00 : 0x80) - | (partV & 127); - ADB_DatBuf[1] = /* 0x00 */ 0x80 | (partH & 127); - } - } - ADBMouseDisabled = 0; - break; - case 3: - ADB_SzDatBuf = 2; - ADB_TalkDatBuf = trueblnr; - ADB_DatBuf[0] = 0x60 | (NotSoRandAddr & 0x0f); - ADB_DatBuf[1] = 0x01; - NotSoRandAddr += 1; - break; - default: - ReportAbnormal("Talk to unknown mouse register"); - break; - } -} - -LOCALPROC ADB_DoMouseListen(void) -{ - switch (ADB_CurCmd & 3) { - case 3: - if (ADB_DatBuf[1] == 0xFE) { - /* change address */ - MouseADBAddress = (ADB_DatBuf[0] & 0x0F); - } else { - ReportAbnormal("unknown listen op to mouse register 3"); - } - break; - default: - ReportAbnormal("listen to unknown mouse register"); - break; - } -} - -LOCALVAR ui3b KeyboardADBAddress; - -LOCALFUNC blnr CheckForADBkeyEvt(ui3b *NextADBkeyevt) -{ - int i; - blnr KeyDown; - - if (! FindKeyEvent(&i, &KeyDown)) { - return falseblnr; - } else { -#if dbglog_HAVE && 0 - if (KeyDown) { - dbglog_WriteNote("Got a KeyDown"); - } -#endif - switch (i) { - case MKC_Control: - i = 0x36; - break; - case MKC_Left: - i = 0x3B; - break; - case MKC_Right: - i = 0x3C; - break; - case MKC_Down: - i = 0x3D; - break; - case MKC_Up: - i = 0x3E; - break; - default: - /* unchanged */ - break; - } - *NextADBkeyevt = (KeyDown ? 0x00 : 0x80) | i; - return trueblnr; - } -} - -LOCALPROC ADB_DoKeyboardTalk(void) -{ - switch (ADB_CurCmd & 3) { - case 0: - { - ui3b NextADBkeyevt; - - if (CheckForADBkeyEvt(&NextADBkeyevt)) { - ADB_SzDatBuf = 2; - ADB_TalkDatBuf = trueblnr; - ADB_DatBuf[0] = NextADBkeyevt; - if (! CheckForADBkeyEvt(&NextADBkeyevt)) { - ADB_DatBuf[1] = 0xFF; - } else { - ADB_DatBuf[1] = NextADBkeyevt; - } - } - } - break; - case 3: - ADB_SzDatBuf = 2; - ADB_TalkDatBuf = trueblnr; - ADB_DatBuf[0] = 0x60 | (NotSoRandAddr & 0x0f); - ADB_DatBuf[1] = 0x01; - NotSoRandAddr += 1; - break; - default: - ReportAbnormal("Talk to unknown keyboard register"); - break; - } -} - -LOCALPROC ADB_DoKeyboardListen(void) -{ - switch (ADB_CurCmd & 3) { - case 3: - if (ADB_DatBuf[1] == 0xFE) { - /* change address */ - KeyboardADBAddress = (ADB_DatBuf[0] & 0x0F); - } else { - ReportAbnormal( - "unknown listen op to keyboard register 3"); - } - break; - default: - ReportAbnormal("listen to unknown keyboard register"); - break; - } -} - -LOCALFUNC blnr CheckForADBanyEvt(void) -{ - MyEvtQEl *p = MyEvtQOutP(); - if (nullpr != p) { - switch (p->kind) { - case MyEvtQElKindMouseButton: - case MyEvtQElKindMouseDelta: - case MyEvtQElKindKey: - return trueblnr; - break; - default: - break; - } - } - - return (0 != MouseADBDeltaH) && (0 != MouseADBDeltaV); -} - -LOCALPROC ADB_DoTalk(void) -{ - ui3b Address = ADB_CurCmd >> 4; - if (Address == MouseADBAddress) { - ADB_DoMouseTalk(); - } else if (Address == KeyboardADBAddress) { - ADB_DoKeyboardTalk(); - } -} - -LOCALPROC ADB_EndListen(void) -{ - ui3b Address = ADB_CurCmd >> 4; - if (Address == MouseADBAddress) { - ADB_DoMouseListen(); - } else if (Address == KeyboardADBAddress) { - ADB_DoKeyboardListen(); - } -} - -LOCALPROC ADB_DoReset(void) -{ - MouseADBAddress = 3; - KeyboardADBAddress = 2; -} - -LOCALPROC ADB_Flush(void) -{ - ui3b Address = ADB_CurCmd >> 4; - - if ((Address == KeyboardADBAddress) - || (Address == MouseADBAddress)) - { - ADB_SzDatBuf = 2; - ADB_TalkDatBuf = trueblnr; - ADB_DatBuf[0] = 0x00; - ADB_DatBuf[1] = 0x00; - } else { - ReportAbnormal("Unhandled ADB Flush"); - } -} +/* ADBSHARE.h Copyright (C) 2008 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* Apple Desktop Bus SHAREd code shared by emulation of different implementations of ADB */ #ifdef ADBSHARE_H #error "header already included" #else #define ADBSHARE_H #endif /* ReportAbnormalID unused 0x0D08 - 0x0DFF */ #define ADB_MaxSzDatBuf 8 LOCALVAR ui3b ADB_SzDatBuf; LOCALVAR blnr ADB_TalkDatBuf = falseblnr; LOCALVAR ui3b ADB_DatBuf[ADB_MaxSzDatBuf]; LOCALVAR ui3b ADB_CurCmd = 0; LOCALVAR ui3b NotSoRandAddr = 1; LOCALVAR ui3b MouseADBAddress; LOCALVAR blnr SavedCurMouseButton = falseblnr; LOCALVAR ui4r MouseADBDeltaH = 0; LOCALVAR ui4r MouseADBDeltaV = 0; LOCALPROC ADB_DoMouseTalk(void) { switch (ADB_CurCmd & 3) { case 0: { blnr overflow = falseblnr; ui4b partH; ui4b partV; blnr MouseButtonChange = falseblnr; MyEvtQEl *p = MyEvtQOutP(); if (nullpr != p) { if (MyEvtQElKindMouseDelta == p->kind) { MouseADBDeltaH += p->u.pos.h; MouseADBDeltaV += p->u.pos.v; MyEvtQOutDone(); } } partH = MouseADBDeltaH; partV = MouseADBDeltaV; if ((si4b)MouseADBDeltaH < 0) { partH = - partH; } if ((si4b)MouseADBDeltaV < 0) { partV = - partV; } if ((partH >> 6) > 0) { overflow = trueblnr; partH = (1 << 6) - 1; } if ((partV >> 6) > 0) { overflow = trueblnr; partV = (1 << 6) - 1; } if ((si4b)MouseADBDeltaH < 0) { partH = - partH; } if ((si4b)MouseADBDeltaV < 0) { partV = - partV; } MouseADBDeltaH -= partH; MouseADBDeltaV -= partV; if (! overflow) { MyEvtQEl *p = MyEvtQOutP(); if (nullpr != p) { if (MyEvtQElKindMouseButton == p->kind) { SavedCurMouseButton = p->u.press.down; MouseButtonChange = trueblnr; MyEvtQOutDone(); } } } if ((0 != partH) || (0 != partV) || MouseButtonChange) { ADB_SzDatBuf = 2; ADB_TalkDatBuf = trueblnr; ADB_DatBuf[0] = (SavedCurMouseButton ? 0x00 : 0x80) | (partV & 127); ADB_DatBuf[1] = /* 0x00 */ 0x80 | (partH & 127); } } ADBMouseDisabled = 0; break; case 3: ADB_SzDatBuf = 2; ADB_TalkDatBuf = trueblnr; ADB_DatBuf[0] = 0x60 | (NotSoRandAddr & 0x0f); ADB_DatBuf[1] = 0x01; NotSoRandAddr += 1; break; default: ReportAbnormalID(0x0D01, "Talk to unknown mouse register"); break; } } LOCALPROC ADB_DoMouseListen(void) { switch (ADB_CurCmd & 3) { case 3: if (ADB_DatBuf[1] == 0xFE) { /* change address */ MouseADBAddress = (ADB_DatBuf[0] & 0x0F); } else { ReportAbnormalID(0x0D02, "unknown listen op to mouse register 3"); } break; default: ReportAbnormalID(0x0D03, "listen to unknown mouse register"); break; } } LOCALVAR ui3b KeyboardADBAddress; LOCALFUNC blnr CheckForADBkeyEvt(ui3b *NextADBkeyevt) { int i; blnr KeyDown; if (! FindKeyEvent(&i, &KeyDown)) { return falseblnr; } else { #if dbglog_HAVE && 0 if (KeyDown) { dbglog_WriteNote("Got a KeyDown"); } #endif switch (i) { case MKC_Control: i = 0x36; break; case MKC_Left: i = 0x3B; break; case MKC_Right: i = 0x3C; break; case MKC_Down: i = 0x3D; break; case MKC_Up: i = 0x3E; break; default: /* unchanged */ break; } *NextADBkeyevt = (KeyDown ? 0x00 : 0x80) | i; return trueblnr; } } LOCALPROC ADB_DoKeyboardTalk(void) { switch (ADB_CurCmd & 3) { case 0: { ui3b NextADBkeyevt; if (CheckForADBkeyEvt(&NextADBkeyevt)) { ADB_SzDatBuf = 2; ADB_TalkDatBuf = trueblnr; ADB_DatBuf[0] = NextADBkeyevt; if (! CheckForADBkeyEvt(&NextADBkeyevt)) { ADB_DatBuf[1] = 0xFF; } else { ADB_DatBuf[1] = NextADBkeyevt; } } } break; case 3: ADB_SzDatBuf = 2; ADB_TalkDatBuf = trueblnr; ADB_DatBuf[0] = 0x60 | (NotSoRandAddr & 0x0f); ADB_DatBuf[1] = 0x01; NotSoRandAddr += 1; break; default: ReportAbnormalID(0x0D04, "Talk to unknown keyboard register"); break; } } LOCALPROC ADB_DoKeyboardListen(void) { switch (ADB_CurCmd & 3) { case 3: if (ADB_DatBuf[1] == 0xFE) { /* change address */ KeyboardADBAddress = (ADB_DatBuf[0] & 0x0F); } else { ReportAbnormalID(0x0D05, "unknown listen op to keyboard register 3"); } break; default: ReportAbnormalID(0x0D06, "listen to unknown keyboard register"); break; } } LOCALFUNC blnr CheckForADBanyEvt(void) { MyEvtQEl *p = MyEvtQOutP(); if (nullpr != p) { switch (p->kind) { case MyEvtQElKindMouseButton: case MyEvtQElKindMouseDelta: case MyEvtQElKindKey: return trueblnr; break; default: break; } } return (0 != MouseADBDeltaH) && (0 != MouseADBDeltaV); } LOCALPROC ADB_DoTalk(void) { ui3b Address = ADB_CurCmd >> 4; if (Address == MouseADBAddress) { ADB_DoMouseTalk(); } else if (Address == KeyboardADBAddress) { ADB_DoKeyboardTalk(); } } LOCALPROC ADB_EndListen(void) { ui3b Address = ADB_CurCmd >> 4; if (Address == MouseADBAddress) { ADB_DoMouseListen(); } else if (Address == KeyboardADBAddress) { ADB_DoKeyboardListen(); } } LOCALPROC ADB_DoReset(void) { MouseADBAddress = 3; KeyboardADBAddress = 2; } LOCALPROC ADB_Flush(void) { ui3b Address = ADB_CurCmd >> 4; if ((Address == KeyboardADBAddress) || (Address == MouseADBAddress)) { ADB_SzDatBuf = 2; ADB_TalkDatBuf = trueblnr; ADB_DatBuf[0] = 0x00; ADB_DatBuf[1] = 0x00; } else { ReportAbnormalID(0x0D07, "Unhandled ADB Flush"); } } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/ALTKEYSM.h b/Mini vMac/mnvm_core/ALTKEYSM.h index 89588d6..80f3a61 100755 --- a/Mini vMac/mnvm_core/ALTKEYSM.h +++ b/Mini vMac/mnvm_core/ALTKEYSM.h @@ -1,209 +1 @@ -/* - ALTKEYSM.h - - Copyright (C) 2007 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - ALTernate KEYs Mode -*/ - -#ifdef ALTKEYSM_H -#error "header already included" -#else -#define ALTKEYSM_H -#endif - -LOCALVAR blnr AltKeysLockText = falseblnr; -LOCALVAR blnr AltKeysTrueCmnd = falseblnr; -LOCALVAR blnr AltKeysTrueOption = falseblnr; -LOCALVAR blnr AltKeysTrueShift = falseblnr; -LOCALVAR blnr AltKeysModOn = falseblnr; -LOCALVAR blnr AltKeysTextOn = falseblnr; - -LOCALPROC CheckAltKeyUseMode(void) -{ - blnr NewAltKeysTextOn; - - AltKeysModOn = AltKeysTrueCmnd - || AltKeysTrueOption || AltKeysTrueShift; - NewAltKeysTextOn = AltKeysLockText || AltKeysModOn; - if (NewAltKeysTextOn != AltKeysTextOn) { - DisconnectKeyCodes(kKeepMaskControl | kKeepMaskCapsLock - | (AltKeysTrueCmnd ? kKeepMaskCommand : 0) - | (AltKeysTrueOption ? kKeepMaskOption : 0) - | (AltKeysTrueShift ? kKeepMaskShift : 0)); - AltKeysTextOn = NewAltKeysTextOn; - } -} - -LOCALPROC Keyboard_UpdateKeyMap1(int key, blnr down) -{ - if (MKC_Command == key) { - AltKeysTrueCmnd = down; - CheckAltKeyUseMode(); - Keyboard_UpdateKeyMap(key, down); - } else if (MKC_Option == key) { - AltKeysTrueOption = down; - CheckAltKeyUseMode(); - Keyboard_UpdateKeyMap(key, down); - } else if (MKC_Shift == key) { - AltKeysTrueShift = down; - CheckAltKeyUseMode(); - Keyboard_UpdateKeyMap(key, down); - } else if (MKC_SemiColon == key) { - if (down && ! AltKeysModOn) { - if (AltKeysLockText) { - AltKeysLockText = falseblnr; - NeedWholeScreenDraw = trueblnr; - SpecialModeClr(SpclModeAltKeyText); - - CheckAltKeyUseMode(); - } - } else { - Keyboard_UpdateKeyMap(key, down); - } - } else if (AltKeysTextOn) { - Keyboard_UpdateKeyMap(key, down); - } else if (MKC_M == key) { - if (down) { - if (! AltKeysLockText) { - AltKeysLockText = trueblnr; - SpecialModeSet(SpclModeAltKeyText); - NeedWholeScreenDraw = trueblnr; - CheckAltKeyUseMode(); - } - } - } else { - switch (key) { - case MKC_A: - key = MKC_SemiColon; - break; - case MKC_B: - key = MKC_BackSlash; - break; - case MKC_C: - key = MKC_F3; - break; - case MKC_D: - key = MKC_Option; - break; - case MKC_E: - key = MKC_BackSpace; - break; - case MKC_F: - key = MKC_Command; - break; - case MKC_G: - key = MKC_Enter; - break; - case MKC_H: - key = MKC_Equal; - break; - case MKC_I: - key = MKC_Up; - break; - case MKC_J: - key = MKC_Left; - break; - case MKC_K: - key = MKC_Down; - break; - case MKC_L: - key = MKC_Right; - break; - case MKC_M: - /* handled above */ - break; - case MKC_N: - key = MKC_Minus; - break; - case MKC_O: - key = MKC_RightBracket; - break; - case MKC_P: - return; /* none */ - break; - case MKC_Q: - key = MKC_Grave; - break; - case MKC_R: - key = MKC_Return; - break; - case MKC_S: - key = MKC_Shift; - break; - case MKC_T: - key = MKC_Tab; - break; - case MKC_U: - key = MKC_LeftBracket; - break; - case MKC_V: - key = MKC_F4; - break; - case MKC_W: - return; /* none */ - break; - case MKC_X: - key = MKC_F2; - break; - case MKC_Y: - key = MKC_Escape; - break; - case MKC_Z: - key = MKC_F1; - break; - default: - break; - } - Keyboard_UpdateKeyMap(key, down); - } -} - -LOCALPROC DisconnectKeyCodes1(ui5b KeepMask) -{ - DisconnectKeyCodes(KeepMask); - - if (! (0 != (KeepMask & kKeepMaskCommand))) { - AltKeysTrueCmnd = falseblnr; - } - if (! (0 != (KeepMask & kKeepMaskOption))) { - AltKeysTrueOption = falseblnr; - } - if (! (0 != (KeepMask & kKeepMaskShift))) { - AltKeysTrueShift = falseblnr; - } - AltKeysModOn = AltKeysTrueCmnd - || AltKeysTrueOption || AltKeysTrueShift; - AltKeysTextOn = AltKeysLockText || AltKeysModOn; -} - -LOCALPROC DrawAltKeyMode(void) -{ - int i; - - CurCellv0 = ControlBoxv0; - CurCellh0 = ControlBoxh0; - - DrawCellAdvance(kInsertText00); - for (i = (ControlBoxw - 4) / 2; --i >= 0; ) { - DrawCellAdvance(kInsertText04); - } - DrawCellAdvance(kInsertText01); - DrawCellAdvance(kInsertText02); - for (i = (ControlBoxw - 4) / 2; --i >= 0; ) { - DrawCellAdvance(kInsertText04); - } - DrawCellAdvance(kInsertText03); -} +/* ALTKEYSM.h Copyright (C) 2007 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* ALTernate KEYs Mode */ #ifdef ALTKEYSM_H #error "header already included" #else #define ALTKEYSM_H #endif LOCALVAR blnr AltKeysLockText = falseblnr; LOCALVAR blnr AltKeysTrueCmnd = falseblnr; LOCALVAR blnr AltKeysTrueOption = falseblnr; LOCALVAR blnr AltKeysTrueShift = falseblnr; LOCALVAR blnr AltKeysModOn = falseblnr; LOCALVAR blnr AltKeysTextOn = falseblnr; LOCALPROC CheckAltKeyUseMode(void) { blnr NewAltKeysTextOn; AltKeysModOn = AltKeysTrueCmnd || AltKeysTrueOption || AltKeysTrueShift; NewAltKeysTextOn = AltKeysLockText || AltKeysModOn; if (NewAltKeysTextOn != AltKeysTextOn) { DisconnectKeyCodes(kKeepMaskControl | kKeepMaskCapsLock | (AltKeysTrueCmnd ? kKeepMaskCommand : 0) | (AltKeysTrueOption ? kKeepMaskOption : 0) | (AltKeysTrueShift ? kKeepMaskShift : 0)); AltKeysTextOn = NewAltKeysTextOn; } } LOCALPROC Keyboard_UpdateKeyMap1(int key, blnr down) { if (MKC_Command == key) { AltKeysTrueCmnd = down; CheckAltKeyUseMode(); Keyboard_UpdateKeyMap(key, down); } else if (MKC_Option == key) { AltKeysTrueOption = down; CheckAltKeyUseMode(); Keyboard_UpdateKeyMap(key, down); } else if (MKC_Shift == key) { AltKeysTrueShift = down; CheckAltKeyUseMode(); Keyboard_UpdateKeyMap(key, down); } else if (MKC_SemiColon == key) { if (down && ! AltKeysModOn) { if (AltKeysLockText) { AltKeysLockText = falseblnr; NeedWholeScreenDraw = trueblnr; SpecialModeClr(SpclModeAltKeyText); CheckAltKeyUseMode(); } } else { Keyboard_UpdateKeyMap(key, down); } } else if (AltKeysTextOn) { Keyboard_UpdateKeyMap(key, down); } else if (MKC_M == key) { if (down) { if (! AltKeysLockText) { AltKeysLockText = trueblnr; SpecialModeSet(SpclModeAltKeyText); NeedWholeScreenDraw = trueblnr; CheckAltKeyUseMode(); } } } else { switch (key) { case MKC_A: key = MKC_SemiColon; break; case MKC_B: key = MKC_BackSlash; break; case MKC_C: key = MKC_F3; break; case MKC_D: key = MKC_Option; break; case MKC_E: key = MKC_BackSpace; break; case MKC_F: key = MKC_Command; break; case MKC_G: key = MKC_Enter; break; case MKC_H: key = MKC_Equal; break; case MKC_I: key = MKC_Up; break; case MKC_J: key = MKC_Left; break; case MKC_K: key = MKC_Down; break; case MKC_L: key = MKC_Right; break; case MKC_M: /* handled above */ break; case MKC_N: key = MKC_Minus; break; case MKC_O: key = MKC_RightBracket; break; case MKC_P: return; /* none */ break; case MKC_Q: key = MKC_Grave; break; case MKC_R: key = MKC_Return; break; case MKC_S: key = MKC_Shift; break; case MKC_T: key = MKC_Tab; break; case MKC_U: key = MKC_LeftBracket; break; case MKC_V: key = MKC_F4; break; case MKC_W: return; /* none */ break; case MKC_X: key = MKC_F2; break; case MKC_Y: key = MKC_Escape; break; case MKC_Z: key = MKC_F1; break; default: break; } Keyboard_UpdateKeyMap(key, down); } } LOCALPROC DisconnectKeyCodes1(ui5b KeepMask) { DisconnectKeyCodes(KeepMask); if (! (0 != (KeepMask & kKeepMaskCommand))) { AltKeysTrueCmnd = falseblnr; } if (! (0 != (KeepMask & kKeepMaskOption))) { AltKeysTrueOption = falseblnr; } if (! (0 != (KeepMask & kKeepMaskShift))) { AltKeysTrueShift = falseblnr; } AltKeysModOn = AltKeysTrueCmnd || AltKeysTrueOption || AltKeysTrueShift; AltKeysTextOn = AltKeysLockText || AltKeysModOn; } LOCALPROC DrawAltKeyMode(void) { int i; CurCellv0 = ControlBoxv0; CurCellh0 = ControlBoxh0; DrawCellAdvance(kInsertText00); for (i = (ControlBoxw - 4) / 2; --i >= 0; ) { DrawCellAdvance(kInsertText04); } DrawCellAdvance(kInsertText01); DrawCellAdvance(kInsertText02); for (i = (ControlBoxw - 4) / 2; --i >= 0; ) { DrawCellAdvance(kInsertText04); } DrawCellAdvance(kInsertText03); } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/ASCEMDEV.c b/Mini vMac/mnvm_core/ASCEMDEV.c index 5a04f5f..3c956be 100755 --- a/Mini vMac/mnvm_core/ASCEMDEV.c +++ b/Mini vMac/mnvm_core/ASCEMDEV.c @@ -1,849 +1 @@ -/* - ASCEMDEV.c - - Copyright (C) 2008 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - Apple Sound Chip EMulated DEVice -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" -#include "ENDIANAC.h" -#include "MYOSGLUE.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" -#include "VIAEMDEV.h" -#endif - -#include "ASCEMDEV.h" - -LOCALVAR ui3r SoundReg801 = 0; -LOCALVAR ui3r SoundReg802 = 0; -LOCALVAR ui3r SoundReg803 = 0; -LOCALVAR ui3r SoundReg804 = 0; -LOCALVAR ui3r SoundReg805 = 0; -LOCALVAR ui3r SoundReg_Volume = 0; /* 0x806 */ -/* LOCALVAR ui3r SoundReg807 = 0; */ - -LOCALVAR ui3b ASC_SampBuff[0x800]; - -struct ASC_ChanR { - ui3b freq[4]; - ui3b phase[4]; -}; -typedef struct ASC_ChanR ASC_ChanR; - -LOCALVAR ASC_ChanR ASC_ChanA[4]; - -LOCALVAR ui4b ASC_FIFO_Out = 0; -LOCALVAR ui4b ASC_FIFO_InA = 0; -LOCALVAR ui4b ASC_FIFO_InB = 0; -LOCALVAR blnr ASC_Playing = falseblnr; - -#define ASC_dolog (dbglog_HAVE && 0) - -#ifdef ASC_interrupt_PulseNtfy -IMPORTPROC ASC_interrupt_PulseNtfy(void); -#endif - -LOCALPROC ASC_RecalcStatus(void) -{ - if ((1 == SoundReg801) && ASC_Playing) { - if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200) { - SoundReg804 &= ~ 0x01; - } else { - SoundReg804 |= 0x01; - } - if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x400) { - SoundReg804 |= 0x02; - } else { - SoundReg804 &= ~ 0x02; - } - if (0 != (SoundReg802 & 2)) { - if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x200) { - SoundReg804 &= ~ 0x04; - } else { - SoundReg804 |= 0x04; - } - if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x400) { - SoundReg804 |= 0x08; - } else { - SoundReg804 &= ~ 0x08; - } - } - } -} - -LOCALPROC ASC_ClearFIFO(void) -{ - ASC_FIFO_Out = 0; - ASC_FIFO_InA = 0; - ASC_FIFO_InB = 0; - ASC_Playing = falseblnr; - ASC_RecalcStatus(); -} - -GLOBALFUNC ui5b ASC_Access(ui5b Data, blnr WriteMem, CPTR addr) -{ - if (addr < 0x800) { - if (WriteMem) { - if (1 == SoundReg801) { - if (0 == (addr & 0x400)) { - if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x400) - { -#if 0 /* seems to happen in tetris */ - ReportAbnormal("ASC - Channel A Overflow"); -#endif - SoundReg804 |= 0x02; - } else { - - ASC_SampBuff[ASC_FIFO_InA & 0x3FF] = Data; - - ++ASC_FIFO_InA; - if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200) - { - if (0 != (SoundReg804 & 0x01)) { - /* happens normally */ - SoundReg804 &= ~ 0x01; - } - } else { -#if 0 /* doesn't seem to be necessary, but doesn't hurt either */ - SoundReg804 |= 0x01; -#endif - } - if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x400) - { - SoundReg804 |= 0x02; -#if ASC_dolog - dbglog_WriteNote("ASC : setting full flag A"); -#endif - } else { - if (0 != (SoundReg804 & 0x02)) { - ReportAbnormal("ASC_Access : " - "full flag A not already clear"); - SoundReg804 &= ~ 0x02; - } - } - - } - } else { - if (0 == (SoundReg802 & 2)) { - ReportAbnormal("ASC - Channel B for Mono"); - } - if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x400) - { - ReportAbnormal("ASC - Channel B Overflow"); - SoundReg804 |= 0x08; - } else { - - ASC_SampBuff[0x400 + (ASC_FIFO_InB & 0x3FF)] = Data; - - ++ASC_FIFO_InB; - if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x200) - { - if (0 != (SoundReg804 & 0x04)) { - /* happens normally */ - SoundReg804 &= ~ 0x04; - } - } else { -#if 0 /* doesn't seem to be necessary, but doesn't hurt either */ - SoundReg804 |= 0x04; -#endif - } - if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x400) - { - SoundReg804 |= 0x08; -#if ASC_dolog - dbglog_WriteNote("ASC : setting full flag B"); -#endif - } else { - if (0 != (SoundReg804 & 0x08)) { - ReportAbnormal("ASC_Access : " - "full flag B not already clear"); - SoundReg804 &= ~ 0x08; - } - } - - } - } -#if ASC_dolog && 0 - dbglog_writeCStr("ASC_InputIndex ="); - dbglog_writeNum(ASC_InputIndex); - dbglog_writeReturn(); -#endif - } else { - ASC_SampBuff[addr] = Data; - } - } else { - Data = ASC_SampBuff[addr]; - } - -#if ASC_dolog && 1 -#if 0 - if (((addr & 0x1FF) >= 0x04) - && ((addr & 0x1FF) < (0x200 - 0x04))) - { - /* don't report them all */ - } else -#endif - { - dbglog_AddrAccess("ASC_Access SampBuff", - Data, WriteMem, addr); - } -#endif - } else if (addr < 0x810) { - switch (addr) { - case 0x800: /* VERSION */ - if (WriteMem) { - ReportAbnormal("ASC - writing VERSION"); - } else { - Data = 0; - } -#if ASC_dolog && 1 - dbglog_AddrAccess("ASC_Access Control (VERSION)", - Data, WriteMem, addr); -#endif - break; - case 0x801: /* ENABLE */ - if (WriteMem) { - if (1 == Data) { - if (1 != SoundReg801) { - ASC_ClearFIFO(); - } - } else { - if (Data > 2) { - ReportAbnormal("ASC - unexpected ENABLE"); - } - } - SoundReg801 = Data; - } else { - Data = SoundReg801; - /* happens in LodeRunner */ - } -#if ASC_dolog && 1 - dbglog_AddrAccess("ASC_Access Control (ENABLE)", - Data, WriteMem, addr); -#endif - break; - case 0x802: /* CONTROL */ - if (WriteMem) { -#if 1 - if (0 != SoundReg801) { - if (SoundReg802 == Data) { - /* - this happens normally, - such as in Lunar Phantom - */ - } else { - if (1 == SoundReg801) { -/* - happens in dark castle, if play other sound first, - such as by changing beep sound in sound control panel. -*/ - ASC_ClearFIFO(); - } - -#if 0 - ReportAbnormal( - "ASC - changing CONTROL while ENABLEd"); -#endif - } - } -#endif - if (0 != (Data & ~ 2)) { - ReportAbnormal( - "ASC - unexpected CONTROL value"); - } - SoundReg802 = Data; - } else { - Data = SoundReg802; - ReportAbnormal( - "ASC - reading CONTROL value"); - } -#if ASC_dolog && 1 - dbglog_AddrAccess("ASC_Access Control (CONTROL)", - Data, WriteMem, addr); -#endif - break; - case 0x803: - if (WriteMem) { - if (0 != (Data & ~ 0x80)) { - ReportAbnormal( - "ASC - unexpected FIFO MODE"); - } - if (0 != (Data & 0x80)) { - if (0 != (SoundReg803 & 0x80)) { - ReportAbnormal( - "ASC - set clear FIFO again"); - } else - if (1 != SoundReg801) { -#if 0 /* happens in system 6, such as with Lunar Phantom */ - ReportAbnormal( - "ASC - clear FIFO when not FIFO mode"); -#endif - } else - { - ASC_ClearFIFO(); - /* - ASC_interrupt_PulseNtfy(); - Doesn't seem to be needed, - but doesn't hurt either. - */ - } - } - SoundReg803 = Data; - } else { - Data = SoundReg803; - } -#if ASC_dolog && 1 - dbglog_AddrAccess("ASC_Access Control (FIFO MODE)", - Data, WriteMem, addr); -#endif - break; - case 0x804: - if (WriteMem) { -#if 0 - if ((0 != SoundReg804) && (0 != Data)) { - ReportAbnormal( - "ASC - set FIFO IRQ STATUS when not 0"); - } -#endif - SoundReg804 = Data; - if (0 != SoundReg804) { - ASC_interrupt_PulseNtfy(); - /* - Generating this interrupt seems - to be the point of writing to - this register. - */ - } -#if ASC_dolog && 1 - dbglog_AddrAccess( - "ASC_Access Control (FIFO IRQ STATUS)", - Data, WriteMem, addr); -#endif - } else { - Data = SoundReg804; -#if 0 - if (1 != SoundReg801) { - /* no, ok, part of normal interrupt handling */ - ReportAbnormal( - "ASC - read STATUS when not FIFO"); - } -#endif - /* SoundReg804 = 0; */ - SoundReg804 &= ~ 0x01; - SoundReg804 &= ~ 0x04; - /* - In lunar phantom, observe checking - full flag before first write, but - status was read previous. - */ -#if ASC_dolog && 1 -#if 0 - if (0 != Data) -#endif - { - dbglog_AddrAccess( - "ASC_Access Control (FIFO IRQ STATUS)", - Data, WriteMem, addr); - } -#endif - } - break; - case 0x805: - if (WriteMem) { - SoundReg805 = Data; - /* cleared in LodeRunner */ - } else { - Data = SoundReg805; - ReportAbnormal( - "ASC - readingWAVE CONTROL register"); - } -#if ASC_dolog && 1 - dbglog_AddrAccess("ASC_Access Control (WAVE CONTROL)", - Data, WriteMem, addr); -#endif - break; - case 0x806: /* VOLUME */ - if (WriteMem) { - SoundReg_Volume = Data >> 5; - if (0 != (Data & 0x1F)) { - ReportAbnormal("ASC - unexpected volume value"); - } - } else { - Data = SoundReg_Volume << 5; - ReportAbnormal("ASC - reading volume register"); - } -#if ASC_dolog && 1 - dbglog_AddrAccess("ASC_Access Control (VOLUME)", - Data, WriteMem, addr); -#endif - break; - case 0x807: /* CLOCK RATE */ - if (WriteMem) { - /* SoundReg807 = Data; */ - if (0 != Data) { - ReportAbnormal("ASC - nonstandard CLOCK RATE"); - } - } else { - /* Data = SoundReg807; */ - ReportAbnormal("ASC - reading CLOCK RATE"); - } -#if ASC_dolog && 1 - dbglog_AddrAccess("ASC_Access Control (CLOCK RATE)", - Data, WriteMem, addr); -#endif - break; - case 0x808: /* CONTROL */ - if (WriteMem) { - ReportAbnormal("ASC - write to 808"); - } else { - /* happens on boot System 7.5.5 */ - Data = 0; - } -#if ASC_dolog && 1 - dbglog_AddrAccess("ASC_Access Control (CONTROL)", - Data, WriteMem, addr); -#endif - break; - case 0x80A: /* ? */ - if (WriteMem) { - ReportAbnormal("ASC - write to 80A"); - } else { - /* - happens in system 6, Lunar Phantom, - soon after new game. - */ - Data = 0; - } -#if ASC_dolog && 1 - dbglog_AddrAccess("ASC_Access Control (80A)", - Data, WriteMem, addr); -#endif - break; - default: - if (WriteMem) { - } else { - Data = 0; - } - ReportAbnormal("ASC - unknown ASC reg"); -#if ASC_dolog && 1 - dbglog_AddrAccess("ASC_Access Control (?)", - Data, WriteMem, addr); -#endif - break; - } - } else if (addr < 0x830) { - ui3r b = addr & 3; - ui3r chan = ((addr - 0x810) >> 3) & 3; - - if (0 != (addr & 4)) { - - if (WriteMem) { - ASC_ChanA[chan].freq[b] = Data; - } else { - Data = ASC_ChanA[chan].freq[b]; - } -#if ASC_dolog && 1 - dbglog_AddrAccess("ASC_Access Control (frequency)", - Data, WriteMem, addr); -#endif -#if ASC_dolog && 0 - dbglog_writeCStr("freq b="); - dbglog_writeNum(WriteMem); - dbglog_writeCStr(", chan="); - dbglog_writeNum(chan); - dbglog_writeReturn(); -#endif - } else { - - if (WriteMem) { - ASC_ChanA[chan].phase[b] = Data; - } else { - Data = ASC_ChanA[chan].phase[b]; - } -#if ASC_dolog && 1 - dbglog_AddrAccess("ASC_Access Control (phase)", - Data, WriteMem, addr); -#endif - } - } else if (addr < 0x838) { -#if ASC_dolog && 1 - dbglog_AddrAccess("ASC_Access Control *** unknown reg", - Data, WriteMem, addr); -#endif - } else { -#if ASC_dolog && 1 - dbglog_AddrAccess("ASC_Access Control ? *** unknown reg", - Data, WriteMem, addr); -#endif - - ReportAbnormal("unknown ASC reg"); - } - - return Data; -} - -/* - approximate volume levels of vMac, so: - - x * vol_mult[SoundVolume] >> 16 - + vol_offset[SoundVolume] - = {approx} (x - kCenterSound) / (8 - SoundVolume) + kCenterSound; -*/ - -LOCALVAR const ui4b vol_mult[] = { - 8192, 9362, 10922, 13107, 16384, 21845, 32768 -}; - -LOCALVAR const trSoundSamp vol_offset[] = { -#if 3 == kLn2SoundSampSz - 112, 110, 107, 103, 96, 86, 64, 0 -#elif 4 == kLn2SoundSampSz - 28672, 28087, 27307, 26215, 24576, 21846, 16384, 0 -#else -#error "unsupported kLn2SoundSampSz" -#endif -}; - -LOCALVAR const ui4b SubTick_offset[kNumSubTicks] = { - 0, 23, 46, 69, 92, 115, 138, 161, - 185, 208, 231, 254, 277, 300, 323, 346 -}; - -LOCALVAR const ui3r SubTick_n[kNumSubTicks] = { - 23, 23, 23, 23, 23, 23, 23, 24, - 23, 23, 23, 23, 23, 23, 23, 24 -}; - -GLOBALPROC ASC_SubTick(int SubTick) -{ - ui4r actL; -#if MySoundEnabled - tpSoundSamp p; -#endif - ui4r i; - ui4r n = SubTick_n[SubTick]; - ui3b SoundVolume = SoundReg_Volume; - -#if MySoundEnabled -label_retry: - p = MySound_BeginWrite(n, &actL); -#else - actL = n; -#endif - if (actL > 0) { - - if (1 == SoundReg801) { - ui3p addr; - - if (0 != (SoundReg802 & 2)) { - - if (! ASC_Playing) { - if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200) { - if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x200) - { - SoundReg804 &= ~ 0x01; - SoundReg804 &= ~ 0x04; - ASC_Playing = trueblnr; -#if ASC_dolog - dbglog_WriteNote("ASC : start stereo playing"); -#endif - } else { - if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) == 0) - if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) - >= 370) - { -#if ASC_dolog - dbglog_WriteNote("ASC : switch to mono"); -#endif - SoundReg802 &= ~ 2; - /* - cludge to get Tetris to work, - may not actually work on real machine. - */ - } - } - } - } - - for (i = 0; i < actL; i++) { - if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) == 0) { - ASC_Playing = falseblnr; - } - if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) == 0) { - ASC_Playing = falseblnr; - } - if (! ASC_Playing) { -#if MySoundEnabled - *p++ = 0x80; -#endif - } else - { - - addr = ASC_SampBuff + (ASC_FIFO_Out & 0x3FF); - -#if ASC_dolog && 1 - dbglog_StartLine(); - dbglog_writeCStr("out sound "); - dbglog_writeCStr("["); - dbglog_writeHex(ASC_FIFO_Out); - dbglog_writeCStr("]"); - dbglog_writeCStr(" = "); - dbglog_writeHex(*addr); - dbglog_writeCStr(" , "); - dbglog_writeHex(addr[0x400]); - dbglog_writeReturn(); -#endif -#if MySoundEnabled - *p++ = ((addr[0] + addr[0x400]) -#if 4 == kLn2SoundSampSz - << 8 -#endif - ) >> 1; -#endif - - ASC_FIFO_Out += 1; - - } - } - - } else { - - /* mono */ - - if (! ASC_Playing) { - if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200) - { - SoundReg804 &= ~ 0x01; - ASC_Playing = trueblnr; -#if ASC_dolog - dbglog_WriteNote("ASC : start mono playing"); -#endif - } - } - - for (i = 0; i < actL; i++) { - if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) == 0) { - ASC_Playing = falseblnr; - } - if (! ASC_Playing) { -#if MySoundEnabled - *p++ = 0x80; -#endif - } else - { - - addr = ASC_SampBuff + (ASC_FIFO_Out & 0x3FF); - -#if ASC_dolog && 1 - dbglog_StartLine(); - dbglog_writeCStr("out sound "); - dbglog_writeCStr("["); - dbglog_writeHex(ASC_FIFO_Out); - dbglog_writeCStr("]"); - dbglog_writeCStr(" = "); - dbglog_writeHex(*addr); - dbglog_writeCStr(", in buff: "); - dbglog_writeHex((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)); - dbglog_writeReturn(); -#endif - -#if MySoundEnabled - *p++ = (addr[0]) -#if 4 == kLn2SoundSampSz - << 8 -#endif - ; -#endif - - /* Move the address on */ - /* *addr = 0x80; */ - /* addr += 2; */ - ASC_FIFO_Out += 1; - - } - } - - } - } else if (2 == SoundReg801) { - ui4r v; - ui4r i0; - ui4r i1; - ui4r i2; - ui4r i3; - ui5r freq0 = do_get_mem_long(ASC_ChanA[0].freq); - ui5r freq1 = do_get_mem_long(ASC_ChanA[1].freq); - ui5r freq2 = do_get_mem_long(ASC_ChanA[2].freq); - ui5r freq3 = do_get_mem_long(ASC_ChanA[3].freq); - ui5r phase0 = do_get_mem_long(ASC_ChanA[0].phase); - ui5r phase1 = do_get_mem_long(ASC_ChanA[1].phase); - ui5r phase2 = do_get_mem_long(ASC_ChanA[2].phase); - ui5r phase3 = do_get_mem_long(ASC_ChanA[3].phase); -#if ASC_dolog && 1 - dbglog_writeCStr("freq0="); - dbglog_writeNum(freq0); - dbglog_writeCStr(", freq1="); - dbglog_writeNum(freq1); - dbglog_writeCStr(", freq2="); - dbglog_writeNum(freq2); - dbglog_writeCStr(", freq3="); - dbglog_writeNum(freq3); - dbglog_writeReturn(); -#endif - for (i = 0; i < actL; i++) { - - phase0 += freq0; - phase1 += freq1; - phase2 += freq2; - phase3 += freq3; - -#if 1 - i0 = ((phase0 + 0x4000) >> 15) & 0x1FF; - i1 = ((phase1 + 0x4000) >> 15) & 0x1FF; - i2 = ((phase2 + 0x4000) >> 15) & 0x1FF; - i3 = ((phase3 + 0x4000) >> 15) & 0x1FF; -#else - i0 = ((phase0 + 0x8000) >> 16) & 0x1FF; - i1 = ((phase1 + 0x8000) >> 16) & 0x1FF; - i2 = ((phase2 + 0x8000) >> 16) & 0x1FF; - i3 = ((phase3 + 0x8000) >> 16) & 0x1FF; -#endif - - v = ASC_SampBuff[i0] - + ASC_SampBuff[0x0200 + i1] - + ASC_SampBuff[0x0400 + i2] - + ASC_SampBuff[0x0600 + i3]; -#if ASC_dolog && 1 - dbglog_StartLine(); - dbglog_writeCStr("i0="); - dbglog_writeNum(i0); - dbglog_writeCStr(", i1="); - dbglog_writeNum(i1); - dbglog_writeCStr(", i2="); - dbglog_writeNum(i2); - dbglog_writeCStr(", i3="); - dbglog_writeNum(i3); - dbglog_writeCStr(", output sound v="); - dbglog_writeNum(v); - dbglog_writeReturn(); -#endif - -#if MySoundEnabled - *p++ = (v >> 2); -#endif - } - - do_put_mem_long(ASC_ChanA[0].phase, phase0); - do_put_mem_long(ASC_ChanA[1].phase, phase1); - do_put_mem_long(ASC_ChanA[2].phase, phase2); - do_put_mem_long(ASC_ChanA[3].phase, phase3); - } else { -#if MySoundEnabled - for (i = 0; i < actL; i++) { - *p++ = kCenterSound; - } -#endif - } - - -#if MySoundEnabled - if (SoundVolume < 7) { - /* - Usually have volume at 7, so this - is just for completeness. - */ - ui5b mult = (ui5b)vol_mult[SoundVolume]; - trSoundSamp offset = vol_offset[SoundVolume]; - - p -= actL; - for (i = 0; i < actL; i++) { - *p = (trSoundSamp)((ui5b)(*p) * mult >> 16) + offset; - ++p; - } - } - - MySound_EndWrite(actL); - n -= actL; - if (n > 0) { - goto label_retry; - } -#endif - } - -#if 1 - if ((1 == SoundReg801) && ASC_Playing) { - if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200) { - if (0 != (SoundReg804 & 0x01)) { - ReportAbnormal("half flag A not already clear"); - SoundReg804 &= ~ 0x01; - } - } else { - if (0 != (SoundReg804 & 0x01)) { - /* happens in lode runner */ - } else { -#if ASC_dolog - dbglog_WriteNote("setting half flag A"); -#endif - ASC_interrupt_PulseNtfy(); - SoundReg804 |= 0x01; - } - } - if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x400) { - if (0 == (SoundReg804 & 0x02)) { - ReportAbnormal("full flag A not already set"); - SoundReg804 |= 0x02; - } - } else { - if (0 != (SoundReg804 & 0x02)) { - /* ReportAbnormal("full flag A not already clear"); */ - SoundReg804 &= ~ 0x02; - } - } - if (0 != (SoundReg802 & 2)) { - if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x200) { - if (0 != (SoundReg804 & 0x04)) { - ReportAbnormal("half flag B not already clear"); - SoundReg804 &= ~ 0x04; - } - } else { - if (0 != (SoundReg804 & 0x04)) { - /* happens in Lunar Phantom */ - } else { -#if ASC_dolog - dbglog_WriteNote("setting half flag B"); -#endif - ASC_interrupt_PulseNtfy(); - SoundReg804 |= 0x04; - } - } - if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x400) { - if (0 == (SoundReg804 & 0x08)) { - ReportAbnormal("full flag B not already set"); - SoundReg804 |= 0x08; - } - } else { - if (0 != (SoundReg804 & 0x08)) { - /* - ReportAbnormal("full flag B not already clear"); - */ - SoundReg804 &= ~ 0x08; - } - } - } - } -#endif -} +/* ASCEMDEV.c Copyright (C) 2008 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* Apple Sound Chip EMulated DEVice */ #ifndef AllFiles #include "SYSDEPNS.h" #include "ENDIANAC.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "VIAEMDEV.h" #endif #include "ASCEMDEV.h" /* ReportAbnormalID unused 0x0F0E, 0x0F1E - 0x0FFF */ LOCALVAR ui3r SoundReg801 = 0; LOCALVAR ui3r SoundReg802 = 0; LOCALVAR ui3r SoundReg803 = 0; LOCALVAR ui3r SoundReg804 = 0; LOCALVAR ui3r SoundReg805 = 0; LOCALVAR ui3r SoundReg_Volume = 0; /* 0x806 */ /* LOCALVAR ui3r SoundReg807 = 0; */ LOCALVAR ui3b ASC_SampBuff[0x800]; struct ASC_ChanR { ui3b freq[4]; ui3b phase[4]; }; typedef struct ASC_ChanR ASC_ChanR; LOCALVAR ASC_ChanR ASC_ChanA[4]; LOCALVAR ui4b ASC_FIFO_Out = 0; LOCALVAR ui4b ASC_FIFO_InA = 0; LOCALVAR ui4b ASC_FIFO_InB = 0; LOCALVAR blnr ASC_Playing = falseblnr; #define ASC_dolog (dbglog_HAVE && 0) #ifdef ASC_interrupt_PulseNtfy IMPORTPROC ASC_interrupt_PulseNtfy(void); #endif LOCALPROC ASC_RecalcStatus(void) { if ((1 == SoundReg801) && ASC_Playing) { if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200) { SoundReg804 &= ~ 0x01; } else { SoundReg804 |= 0x01; } if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x400) { SoundReg804 |= 0x02; } else { SoundReg804 &= ~ 0x02; } if (0 != (SoundReg802 & 2)) { if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x200) { SoundReg804 &= ~ 0x04; } else { SoundReg804 |= 0x04; } if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x400) { SoundReg804 |= 0x08; } else { SoundReg804 &= ~ 0x08; } } } } LOCALPROC ASC_ClearFIFO(void) { ASC_FIFO_Out = 0; ASC_FIFO_InA = 0; ASC_FIFO_InB = 0; ASC_Playing = falseblnr; ASC_RecalcStatus(); } GLOBALFUNC ui5b ASC_Access(ui5b Data, blnr WriteMem, CPTR addr) { if (addr < 0x800) { if (WriteMem) { if (1 == SoundReg801) { if (0 == (addr & 0x400)) { if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x400) { #if 0 /* seems to happen in tetris */ ReportAbnormalID(0x0F01, "ASC - Channel A Overflow"); #endif SoundReg804 |= 0x02; } else { ASC_SampBuff[ASC_FIFO_InA & 0x3FF] = Data; ++ASC_FIFO_InA; if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200) { if (0 != (SoundReg804 & 0x01)) { /* happens normally */ SoundReg804 &= ~ 0x01; } } else { #if 0 /* doesn't seem to be necessary, but doesn't hurt either */ SoundReg804 |= 0x01; #endif } if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x400) { SoundReg804 |= 0x02; #if ASC_dolog dbglog_WriteNote("ASC : setting full flag A"); #endif } else { if (0 != (SoundReg804 & 0x02)) { ReportAbnormalID(0x0F02, "ASC_Access : " "full flag A not already clear"); SoundReg804 &= ~ 0x02; } } } } else { if (0 == (SoundReg802 & 2)) { ReportAbnormalID(0x0F03, "ASC - Channel B for Mono"); } if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x400) { ReportAbnormalID(0x0F04, "ASC - Channel B Overflow"); SoundReg804 |= 0x08; } else { ASC_SampBuff[0x400 + (ASC_FIFO_InB & 0x3FF)] = Data; ++ASC_FIFO_InB; if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x200) { if (0 != (SoundReg804 & 0x04)) { /* happens normally */ SoundReg804 &= ~ 0x04; } } else { #if 0 /* doesn't seem to be necessary, but doesn't hurt either */ SoundReg804 |= 0x04; #endif } if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x400) { SoundReg804 |= 0x08; #if ASC_dolog dbglog_WriteNote("ASC : setting full flag B"); #endif } else { if (0 != (SoundReg804 & 0x08)) { ReportAbnormalID(0x0F05, "ASC_Access : " "full flag B not already clear"); SoundReg804 &= ~ 0x08; } } } } #if ASC_dolog && 0 dbglog_writeCStr("ASC_InputIndex ="); dbglog_writeNum(ASC_InputIndex); dbglog_writeReturn(); #endif } else { ASC_SampBuff[addr] = Data; } } else { Data = ASC_SampBuff[addr]; } #if ASC_dolog && 1 #if 0 if (((addr & 0x1FF) >= 0x04) && ((addr & 0x1FF) < (0x200 - 0x04))) { /* don't report them all */ } else #endif { dbglog_AddrAccess("ASC_Access SampBuff", Data, WriteMem, addr); } #endif } else if (addr < 0x810) { switch (addr) { case 0x800: /* VERSION */ if (WriteMem) { ReportAbnormalID(0x0F06, "ASC - writing VERSION"); } else { Data = 0; } #if ASC_dolog && 1 dbglog_AddrAccess("ASC_Access Control (VERSION)", Data, WriteMem, addr); #endif break; case 0x801: /* ENABLE */ if (WriteMem) { if (1 == Data) { if (1 != SoundReg801) { ASC_ClearFIFO(); } } else { if (Data > 2) { ReportAbnormalID(0x0F07, "ASC - unexpected ENABLE"); } } SoundReg801 = Data; } else { Data = SoundReg801; /* happens in LodeRunner */ } #if ASC_dolog && 1 dbglog_AddrAccess("ASC_Access Control (ENABLE)", Data, WriteMem, addr); #endif break; case 0x802: /* CONTROL */ if (WriteMem) { #if 1 if (0 != SoundReg801) { if (SoundReg802 == Data) { /* this happens normally, such as in Lunar Phantom */ } else { if (1 == SoundReg801) { /* happens in dark castle, if play other sound first, such as by changing beep sound in sound control panel. */ ASC_ClearFIFO(); } #if 0 ReportAbnormalID(0x0F08, "ASC - changing CONTROL while ENABLEd"); #endif } } #endif if (0 != (Data & ~ 2)) { ReportAbnormalID(0x0F09, "ASC - unexpected CONTROL value"); } SoundReg802 = Data; } else { Data = SoundReg802; ReportAbnormalID(0x0F0A, "ASC - reading CONTROL value"); } #if ASC_dolog && 1 dbglog_AddrAccess("ASC_Access Control (CONTROL)", Data, WriteMem, addr); #endif break; case 0x803: if (WriteMem) { if (0 != (Data & ~ 0x80)) { ReportAbnormalID(0x0F0B, "ASC - unexpected FIFO MODE"); } if (0 != (Data & 0x80)) { if (0 != (SoundReg803 & 0x80)) { ReportAbnormalID(0x0F0C, "ASC - set clear FIFO again"); } else if (1 != SoundReg801) { #if 0 /* happens in system 6, such as with Lunar Phantom */ ReportAbnormalID(0x0F0D, "ASC - clear FIFO when not FIFO mode"); #endif } else { ASC_ClearFIFO(); /* ASC_interrupt_PulseNtfy(); Doesn't seem to be needed, but doesn't hurt either. */ } } SoundReg803 = Data; } else { Data = SoundReg803; } #if ASC_dolog && 1 dbglog_AddrAccess("ASC_Access Control (FIFO MODE)", Data, WriteMem, addr); #endif break; case 0x804: if (WriteMem) { #if 0 if ((0 != SoundReg804) && (0 != Data)) { ReportAbnormalID(0x0F0F, "ASC - set FIFO IRQ STATUS when not 0"); } #endif SoundReg804 = Data; if (0 != SoundReg804) { ASC_interrupt_PulseNtfy(); /* Generating this interrupt seems to be the point of writing to this register. */ } #if ASC_dolog && 1 dbglog_AddrAccess( "ASC_Access Control (FIFO IRQ STATUS)", Data, WriteMem, addr); #endif } else { Data = SoundReg804; #if 0 if (1 != SoundReg801) { /* no, ok, part of normal interrupt handling */ ReportAbnormalID(0x0F10, "ASC - read STATUS when not FIFO"); } #endif /* SoundReg804 = 0; */ SoundReg804 &= ~ 0x01; SoundReg804 &= ~ 0x04; /* In lunar phantom, observe checking full flag before first write, but status was read previous. */ #if ASC_dolog && 1 #if 0 if (0 != Data) #endif { dbglog_AddrAccess( "ASC_Access Control (FIFO IRQ STATUS)", Data, WriteMem, addr); } #endif } break; case 0x805: if (WriteMem) { SoundReg805 = Data; /* cleared in LodeRunner */ } else { Data = SoundReg805; ReportAbnormalID(0x0F11, "ASC - reading WAVE CONTROL register"); } #if ASC_dolog && 1 dbglog_AddrAccess("ASC_Access Control (WAVE CONTROL)", Data, WriteMem, addr); #endif break; case 0x806: /* VOLUME */ if (WriteMem) { SoundReg_Volume = Data >> 5; if (0 != (Data & 0x1F)) { ReportAbnormalID(0x0F12, "ASC - unexpected volume value"); } } else { Data = SoundReg_Volume << 5; ReportAbnormalID(0x0F13, "ASC - reading volume register"); } #if ASC_dolog && 1 dbglog_AddrAccess("ASC_Access Control (VOLUME)", Data, WriteMem, addr); #endif break; case 0x807: /* CLOCK RATE */ if (WriteMem) { /* SoundReg807 = Data; */ if (0 != Data) { ReportAbnormalID(0x0F14, "ASC - nonstandard CLOCK RATE"); } } else { /* Data = SoundReg807; */ ReportAbnormalID(0x0F15, "ASC - reading CLOCK RATE"); } #if ASC_dolog && 1 dbglog_AddrAccess("ASC_Access Control (CLOCK RATE)", Data, WriteMem, addr); #endif break; case 0x808: /* CONTROL */ if (WriteMem) { ReportAbnormalID(0x0F16, "ASC - write to 808"); } else { /* happens on boot System 7.5.5 */ Data = 0; } #if ASC_dolog && 1 dbglog_AddrAccess("ASC_Access Control (CONTROL)", Data, WriteMem, addr); #endif break; case 0x80A: /* ? */ if (WriteMem) { ReportAbnormalID(0x0F17, "ASC - write to 80A"); } else { /* happens in system 6, Lunar Phantom, soon after new game. */ Data = 0; } #if ASC_dolog && 1 dbglog_AddrAccess("ASC_Access Control (80A)", Data, WriteMem, addr); #endif break; default: if (WriteMem) { } else { Data = 0; } ReportAbnormalID(0x0F18, "ASC - unknown ASC reg"); #if ASC_dolog && 1 dbglog_AddrAccess("ASC_Access Control (?)", Data, WriteMem, addr); #endif break; } } else if (addr < 0x830) { ui3r b = addr & 3; ui3r chan = ((addr - 0x810) >> 3) & 3; if (0 != (addr & 4)) { if (WriteMem) { ASC_ChanA[chan].freq[b] = Data; } else { Data = ASC_ChanA[chan].freq[b]; } #if ASC_dolog && 1 dbglog_AddrAccess("ASC_Access Control (frequency)", Data, WriteMem, addr); #endif #if ASC_dolog && 0 dbglog_writeCStr("freq b="); dbglog_writeNum(WriteMem); dbglog_writeCStr(", chan="); dbglog_writeNum(chan); dbglog_writeReturn(); #endif } else { if (WriteMem) { ASC_ChanA[chan].phase[b] = Data; } else { Data = ASC_ChanA[chan].phase[b]; } #if ASC_dolog && 1 dbglog_AddrAccess("ASC_Access Control (phase)", Data, WriteMem, addr); #endif } } else if (addr < 0x838) { #if ASC_dolog && 1 dbglog_AddrAccess("ASC_Access Control *** unknown reg", Data, WriteMem, addr); #endif } else { #if ASC_dolog && 1 dbglog_AddrAccess("ASC_Access Control ? *** unknown reg", Data, WriteMem, addr); #endif ReportAbnormalID(0x0F19, "unknown ASC reg"); } return Data; } /* approximate volume levels of vMac, so: x * vol_mult[SoundVolume] >> 16 + vol_offset[SoundVolume] = {approx} (x - kCenterSound) / (8 - SoundVolume) + kCenterSound; */ LOCALVAR const ui4b vol_mult[] = { 8192, 9362, 10922, 13107, 16384, 21845, 32768 }; LOCALVAR const trSoundSamp vol_offset[] = { #if 3 == kLn2SoundSampSz 112, 110, 107, 103, 96, 86, 64, 0 #elif 4 == kLn2SoundSampSz 28672, 28087, 27307, 26215, 24576, 21846, 16384, 0 #else #error "unsupported kLn2SoundSampSz" #endif }; LOCALVAR const ui3r SubTick_n[kNumSubTicks] = { 23, 23, 23, 23, 23, 23, 23, 24, 23, 23, 23, 23, 23, 23, 23, 24 }; GLOBALPROC ASC_SubTick(int SubTick) { ui4r actL; #if MySoundEnabled tpSoundSamp p; #endif ui4r i; ui4r n = SubTick_n[SubTick]; #if MySoundEnabled ui3b SoundVolume = SoundReg_Volume; #endif #if MySoundEnabled label_retry: p = MySound_BeginWrite(n, &actL); #else actL = n; #endif if (actL > 0) { if (1 == SoundReg801) { #if MySoundEnabled ui3p addr; #endif if (0 != (SoundReg802 & 2)) { if (! ASC_Playing) { if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200) { if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x200) { SoundReg804 &= ~ 0x01; SoundReg804 &= ~ 0x04; ASC_Playing = trueblnr; #if ASC_dolog dbglog_WriteNote("ASC : start stereo playing"); #endif } else { if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) == 0) if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 370) { #if ASC_dolog dbglog_WriteNote("ASC : switch to mono"); #endif SoundReg802 &= ~ 2; /* cludge to get Tetris to work, may not actually work on real machine. */ } } } } for (i = 0; i < actL; i++) { if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) == 0) { ASC_Playing = falseblnr; } if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) == 0) { ASC_Playing = falseblnr; } if (! ASC_Playing) { #if MySoundEnabled *p++ = 0x80; #endif } else { #if MySoundEnabled addr = ASC_SampBuff + (ASC_FIFO_Out & 0x3FF); #if ASC_dolog && 1 dbglog_StartLine(); dbglog_writeCStr("out sound "); dbglog_writeCStr("["); dbglog_writeHex(ASC_FIFO_Out); dbglog_writeCStr("]"); dbglog_writeCStr(" = "); dbglog_writeHex(*addr); dbglog_writeCStr(" , "); dbglog_writeHex(addr[0x400]); dbglog_writeReturn(); #endif *p++ = ((addr[0] + addr[0x400]) #if 4 == kLn2SoundSampSz << 8 #endif ) >> 1; #endif /* MySoundEnabled */ ASC_FIFO_Out += 1; } } } else { /* mono */ if (! ASC_Playing) { if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200) { SoundReg804 &= ~ 0x01; ASC_Playing = trueblnr; #if ASC_dolog dbglog_WriteNote("ASC : start mono playing"); #endif } } for (i = 0; i < actL; i++) { if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) == 0) { ASC_Playing = falseblnr; } if (! ASC_Playing) { #if MySoundEnabled *p++ = 0x80; #endif } else { #if MySoundEnabled addr = ASC_SampBuff + (ASC_FIFO_Out & 0x3FF); #if ASC_dolog && 1 dbglog_StartLine(); dbglog_writeCStr("out sound "); dbglog_writeCStr("["); dbglog_writeHex(ASC_FIFO_Out); dbglog_writeCStr("]"); dbglog_writeCStr(" = "); dbglog_writeHex(*addr); dbglog_writeCStr(", in buff: "); dbglog_writeHex((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)); dbglog_writeReturn(); #endif *p++ = (addr[0]) #if 4 == kLn2SoundSampSz << 8 #endif ; #endif /* MySoundEnabled */ /* Move the address on */ /* *addr = 0x80; */ /* addr += 2; */ ASC_FIFO_Out += 1; } } } } else if (2 == SoundReg801) { #if MySoundEnabled ui4r v; ui4r i0; ui4r i1; ui4r i2; ui4r i3; #endif ui5r freq0 = do_get_mem_long(ASC_ChanA[0].freq); ui5r freq1 = do_get_mem_long(ASC_ChanA[1].freq); ui5r freq2 = do_get_mem_long(ASC_ChanA[2].freq); ui5r freq3 = do_get_mem_long(ASC_ChanA[3].freq); ui5r phase0 = do_get_mem_long(ASC_ChanA[0].phase); ui5r phase1 = do_get_mem_long(ASC_ChanA[1].phase); ui5r phase2 = do_get_mem_long(ASC_ChanA[2].phase); ui5r phase3 = do_get_mem_long(ASC_ChanA[3].phase); #if ASC_dolog && 1 dbglog_writeCStr("freq0="); dbglog_writeNum(freq0); dbglog_writeCStr(", freq1="); dbglog_writeNum(freq1); dbglog_writeCStr(", freq2="); dbglog_writeNum(freq2); dbglog_writeCStr(", freq3="); dbglog_writeNum(freq3); dbglog_writeReturn(); #endif for (i = 0; i < actL; i++) { phase0 += freq0; phase1 += freq1; phase2 += freq2; phase3 += freq3; #if MySoundEnabled #if 1 i0 = ((phase0 + 0x4000) >> 15) & 0x1FF; i1 = ((phase1 + 0x4000) >> 15) & 0x1FF; i2 = ((phase2 + 0x4000) >> 15) & 0x1FF; i3 = ((phase3 + 0x4000) >> 15) & 0x1FF; #else i0 = ((phase0 + 0x8000) >> 16) & 0x1FF; i1 = ((phase1 + 0x8000) >> 16) & 0x1FF; i2 = ((phase2 + 0x8000) >> 16) & 0x1FF; i3 = ((phase3 + 0x8000) >> 16) & 0x1FF; #endif v = ASC_SampBuff[i0] + ASC_SampBuff[0x0200 + i1] + ASC_SampBuff[0x0400 + i2] + ASC_SampBuff[0x0600 + i3]; #if ASC_dolog && 1 dbglog_StartLine(); dbglog_writeCStr("i0="); dbglog_writeNum(i0); dbglog_writeCStr(", i1="); dbglog_writeNum(i1); dbglog_writeCStr(", i2="); dbglog_writeNum(i2); dbglog_writeCStr(", i3="); dbglog_writeNum(i3); dbglog_writeCStr(", output sound v="); dbglog_writeNum(v); dbglog_writeReturn(); #endif *p++ = (v >> 2); #endif /* MySoundEnabled */ } do_put_mem_long(ASC_ChanA[0].phase, phase0); do_put_mem_long(ASC_ChanA[1].phase, phase1); do_put_mem_long(ASC_ChanA[2].phase, phase2); do_put_mem_long(ASC_ChanA[3].phase, phase3); } else { #if MySoundEnabled for (i = 0; i < actL; i++) { *p++ = kCenterSound; } #endif } #if MySoundEnabled if (SoundVolume < 7) { /* Usually have volume at 7, so this is just for completeness. */ ui5b mult = (ui5b)vol_mult[SoundVolume]; trSoundSamp offset = vol_offset[SoundVolume]; p -= actL; for (i = 0; i < actL; i++) { *p = (trSoundSamp)((ui5b)(*p) * mult >> 16) + offset; ++p; } } MySound_EndWrite(actL); n -= actL; if (n > 0) { goto label_retry; } #endif } #if 1 if ((1 == SoundReg801) && ASC_Playing) { if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200) { if (0 != (SoundReg804 & 0x01)) { ReportAbnormalID(0x0F1A, "half flag A not already clear"); SoundReg804 &= ~ 0x01; } } else { if (0 != (SoundReg804 & 0x01)) { /* happens in lode runner */ } else { #if ASC_dolog dbglog_WriteNote("setting half flag A"); #endif ASC_interrupt_PulseNtfy(); SoundReg804 |= 0x01; } } if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x400) { if (0 == (SoundReg804 & 0x02)) { ReportAbnormalID(0x0F1B, "full flag A not already set"); SoundReg804 |= 0x02; } } else { if (0 != (SoundReg804 & 0x02)) { /* ReportAbnormal("full flag A not already clear"); */ SoundReg804 &= ~ 0x02; } } if (0 != (SoundReg802 & 2)) { if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x200) { if (0 != (SoundReg804 & 0x04)) { ReportAbnormalID(0x0F1C, "half flag B not already clear"); SoundReg804 &= ~ 0x04; } } else { if (0 != (SoundReg804 & 0x04)) { /* happens in Lunar Phantom */ } else { #if ASC_dolog dbglog_WriteNote("setting half flag B"); #endif ASC_interrupt_PulseNtfy(); SoundReg804 |= 0x04; } } if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x400) { if (0 == (SoundReg804 & 0x08)) { ReportAbnormalID(0x0F1D, "full flag B not already set"); SoundReg804 |= 0x08; } } else { if (0 != (SoundReg804 & 0x08)) { /* ReportAbnormal("full flag B not already clear"); */ SoundReg804 &= ~ 0x08; } } } } #endif } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/ASCEMDEV.h b/Mini vMac/mnvm_core/ASCEMDEV.h index e0c586e..44e95d0 100755 --- a/Mini vMac/mnvm_core/ASCEMDEV.h +++ b/Mini vMac/mnvm_core/ASCEMDEV.h @@ -1,24 +1 @@ -/* - ASCEMDEV.h - - Copyright (C) 2008 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef ASCEMDEV_H -#error "header already included" -#else -#define ASCEMDEV_H -#endif - -EXPORTFUNC ui5b ASC_Access(ui5b Data, blnr WriteMem, CPTR addr); -EXPORTPROC ASC_SubTick(int SubTick); +/* ASCEMDEV.h Copyright (C) 2008 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef ASCEMDEV_H #error "header already included" #else #define ASCEMDEV_H #endif EXPORTFUNC ui5b ASC_Access(ui5b Data, blnr WriteMem, CPTR addr); EXPORTPROC ASC_SubTick(int SubTick); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/BPFILTER.h b/Mini vMac/mnvm_core/BPFILTER.h index 2414f95..efc5538 100755 --- a/Mini vMac/mnvm_core/BPFILTER.h +++ b/Mini vMac/mnvm_core/BPFILTER.h @@ -1,362 +1 @@ -/* - BPFILTER.h - - Copyright (C) 2012 Michael Fort, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - Berkeley Packet Filter for localtalk emulation -*/ - -/* BPF and devices */ -static unsigned char device_address[6] = { - 0 -}; -static unsigned int device_buffer_size = 0; -static int fd = -1; /* BPF file descriptor */ -static struct bpf_version bpf_version; -static struct bpf_program bpf_program; -static struct bpf_insn insns[] = -{ - /* Program for BPF to filter out non-LTOE packets */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x809B, 0, 1), - BPF_STMT(BPF_RET + BPF_K, 65535), - BPF_STMT(BPF_RET + BPF_K, 0), -}; - -GLOBALVAR ui3p LT_TxBuffer = NULL; - -/* Transmit state */ -GLOBALVAR ui4r LT_TxBuffSz = 0; - -/* - Transmit buffer that is reused from tx packet to tx packet. - The 's' byte represents the source mac address (ours) and we don't - have to initialize it because the MAC device will automatically - fill it in for us. The four 'p' bytes represent the process number - of this Mini vMac application. It helps differentiate packets - between two applications running on the same machine. It is not - used at this time. There is a small chance two applications could - get the same LLAP/SDLC address to start with and would not work - correctly (1 in 254). The 'S' bytes are the size of the LLAP packet - since it can be smaller than the minimum sized Ethernet frame. - The process number is replaced at initialization. The size is - updated just before sending to BPF. All LLAP data is inserted - starting at byte 20. -*/ -static unsigned char tx_buffer[20 + LT_TxBfMxSz] = - "\xFF\xFF\xFF\xFF\xFF\xFFssssss\x80\x9BppppSS"; - -/* Receive state */ -GLOBALVAR ui3p LT_RxBuffer = NULL; - /* When data pending, this is used */ -GLOBALVAR ui5r LT_RxBuffSz = 0; - /* When data pending, this is used */ - -/* Macro used by only the get_sockaddrs function for readability. */ -#define ROUNDUP(a, size) \ - (((a) & ((size) - 1)) ? (1 + ((a) | ((size) - 1))) : (a)) - -/* - Utility function needed for walking the addresses of the - kernel route lookup -*/ -LOCALPROC get_sockaddrs(int addrs, struct sockaddr* sa, - struct sockaddr** rti_info) -{ - int loop; - int incr; - - for (loop = 0; loop < RTAX_MAX; loop++) { - if (addrs & (1 << loop)) { - rti_info[loop] = sa; - incr = sa->sa_len ? ROUNDUP(sa->sa_len, sizeof(uint32_t)) - : sizeof(uint32_t); - sa = (struct sockaddr*)((unsigned long int)sa + incr); - } else { - rti_info[loop] = NULL; - } - } -} - -/* - This ugly function does a lot of steps to prepare the BPF - for our use. - 1. Find the ethernet interface that the default route uses. - 2. Determine the maximum number of BPF devices can exist. - 3. Search for a usable BPF device and open it. - 4. Set the BPF device to use our ethernet interface. - 5. Get the proper buffer size to use with the BPF device. - 6. Set some useful modes of operation on the BPF device. - 7. Install a program on the device that filters out non-LTOE - packets. -*/ - -LOCALFUNC int get_ethernet(void) -{ - int result; - int size; - struct rt_msghdr* message; - struct sockaddr_in* addrs; - struct sockaddr* sa_list[RTAX_MAX]; - int loop; - char filename[64]; - struct ifreq ifreq; - int enable = 1; - struct kinfo_proc kp; - size_t len = sizeof(kp); - int max = 4; - - char device[32]; - - /* Get a socket to routed for IPv4 */ - fd = socket(PF_ROUTE, SOCK_RAW, AF_INET); - if (fd == -1) { - return falseblnr; - } - - /* Allocate a message */ - size = sizeof(struct rt_msghdr) + 16 * sizeof(struct sockaddr_in); - message = (struct rt_msghdr*)malloc(size); - if (! message) { - close(fd); - return falseblnr; - } - memset(message, 0, size); - addrs = (struct sockaddr_in*)(message + 1); - - /* Fill in the request */ - message->rtm_msglen = size; - message->rtm_version = RTM_VERSION; - message->rtm_type = RTM_GET; - message->rtm_addrs - = RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_IFP | RTA_IFA; - addrs->sin_len = sizeof(struct sockaddr_in); - addrs->sin_family = AF_INET; - addrs->sin_addr.s_addr = 0; /* 0.0.0.0 is default route */ - - /* Send the message to the kernel */ - result = write(fd, message, size); - if (result < 0) { - close(fd); - free(message); - return falseblnr; - } - - /* Read the result from the kernel */ - result = read(fd, message, size); - if (result < 0) { - close(fd); - free(message); - return falseblnr; - } - - /* Close the route socket */ - close(fd); - - /* Get pointer to the result then parse it */ - struct sockaddr* sa = (struct sockaddr*) - ((unsigned long int)message + sizeof(struct rt_msghdr)); - get_sockaddrs(message->rtm_addrs, sa, sa_list); - - /* Must have a LINK (Ethernet) */ - if ((! sa_list[RTAX_IFP]) - || (sa_list[RTAX_IFP]->sa_family != AF_LINK)) - { - return falseblnr; - } - - int namelen; - int addrlen; - namelen = ((struct sockaddr_dl*)sa_list[RTAX_IFP])->sdl_nlen; - addrlen = ((struct sockaddr_dl*)sa_list[RTAX_IFP])->sdl_alen; - strncpy(device, - &((struct sockaddr_dl*)sa_list[RTAX_IFP])->sdl_data[0], - namelen); - device[namelen] = 0; - memcpy(device_address, - &((struct sockaddr_dl*)sa_list[RTAX_IFP])->sdl_data[namelen], - 6); - memcpy(&(tx_buffer[6]), - &((struct sockaddr_dl*)sa_list[RTAX_IFP])->sdl_data[namelen], - 6); - - result = sysctlbyname("debug.bpf_maxdevices", &kp, &len, NULL, 0); - if (result == -1) { - return falseblnr; - } - max = *((int *)&kp); - - for (loop = 0; loop < max; loop++) { - sprintf(filename, "/dev/bpf%d", loop); - fd = open(filename, O_RDWR | O_NONBLOCK | O_EXLOCK); - if (fd >= 0) { - /* sprintf(buffer, "using %s\n", filename); */ - break; - } - } - - if (fd <= 0) { - return falseblnr; - } - - memset(&ifreq, 0, sizeof(struct ifreq)); - strncpy(ifreq.ifr_name, device, IFNAMSIZ); - result = ioctl(fd, BIOCSETIF, &ifreq); - if (result) { - return falseblnr; - } - - result = ioctl(fd, BIOCGBLEN, &device_buffer_size); - if (result) { - return falseblnr; - } - - result = ioctl(fd, BIOCPROMISC, &enable); - if (result) { - return falseblnr; - } - - result = ioctl(fd, BIOCSSEESENT, &enable); - if (result) { - return falseblnr; - } - - result = ioctl(fd, BIOCSHDRCMPLT, &enable); - if (result) { - return falseblnr; - } - - result = ioctl(fd, BIOCIMMEDIATE, &enable); - if (result) { - return falseblnr; - } - - result = ioctl(fd, BIOCVERSION, &bpf_version); - if (result) { - return falseblnr; - } - - bpf_program.bf_len = 4; - bpf_program.bf_insns = insns; - - result = ioctl(fd, BIOCSETF, &bpf_program); - if (result) { - return falseblnr; - } - - return trueblnr; -} - -LOCALVAR unsigned char *MyRxBuffer = NULL; - -/* - External function needed at startup to initialize the LocalTalk - functionality. -*/ -LOCALFUNC int InitLocalTalk(void) -{ - /* Perform a lot of stuff to get access to the Ethernet */ - get_ethernet(); - - /* - Save the process id in the transmit buffer as it may be used - later to uniquely identify the sender to identify collisions - in dynamic llap node address assignment. - */ - *((uint32_t*)(&tx_buffer[14])) = htonl(getpid()); - - LT_TxBuffer = (ui3p)&tx_buffer[20]; - - MyRxBuffer = malloc(device_buffer_size); - if (NULL == MyRxBuffer) { - return falseblnr; - } - - /* Initialized properly */ - return trueblnr; -} - -GLOBALPROC LT_TransmitPacket(void) -{ - int count; - - /* - Write the length in the packet. This is needed because - Ethernet has a minimum 60 bytes length, which the MAC chip - will enforce on TX. Without the size, a simple 3 byte LLAP - packet would look like a (60 - 14 =) 46 byte LLAP packet. - */ - *((uint16_t*)(&tx_buffer[18])) = htons(LT_TxBuffSz); - - /* Send the packet to Ethernet */ - count = write(fd, tx_buffer, 20 + LT_TxBuffSz); -} - -LOCALVAR unsigned char* NextPacket = NULL; -LOCALVAR unsigned char* EndPackets = NULL; - -LOCALPROC LocalTalkTick0(void) -{ - /* Get a single buffer worth of packets from BPF */ - unsigned char* device_buffer = MyRxBuffer; - int bytes = read(fd, device_buffer, device_buffer_size); - if (bytes > 0) { - /* Maybe multiple packets in this buffer */ -#if 0 - dbglog_WriteNote("SCC founds packets from BPF"); -#endif - NextPacket = device_buffer; - EndPackets = device_buffer + bytes; - } -} - -GLOBALPROC LT_ReceivePacket(void) -{ -label_retry: - if (NextPacket == NULL) { - LocalTalkTick0(); - if (NextPacket != NULL) { - goto label_retry; - } - } else if (NextPacket >= EndPackets) { -#if 0 - dbglog_WriteNote("SCC finished set of packets from BPF"); -#endif - NextPacket = NULL; - goto label_retry; - } else { - unsigned char* packet = NextPacket; - /* Get pointer to BPF header */ - struct bpf_hdr* header = (struct bpf_hdr *)packet; - - /* Advance to next packet in buffer */ - NextPacket += BPF_WORDALIGN(header->bh_hdrlen - + header->bh_caplen); - - /* Get clean references to data */ - int ethernet_length = header->bh_caplen - 14; - int llap_length = htons(*((uint16_t*)(packet - + header->bh_hdrlen + 18))); - unsigned char* start = packet + header->bh_hdrlen + 20; - - if (llap_length <= ethernet_length) { - /* Start the receiver */ - LT_RxBuffer = (ui3p)start; - LT_RxBuffSz = llap_length; - } else { - goto label_retry; - } - } -} +/* BPFILTER.h Copyright (C) 2012 Michael Fort, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* Berkeley Packet Filter for localtalk emulation */ /* BPF and devices */ static unsigned char device_address[6] = { 0 }; static unsigned int device_buffer_size = 0; static int fd = -1; /* BPF file descriptor */ static struct bpf_version bpf_version; static struct bpf_program bpf_program; static struct bpf_insn insns[] = { /* Program for BPF to filter out non-LTOE packets */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12), BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x809B, 0, 1), BPF_STMT(BPF_RET + BPF_K, 65535), BPF_STMT(BPF_RET + BPF_K, 0), }; GLOBALVAR ui3p LT_TxBuffer = NULL; /* Transmit state */ GLOBALVAR ui4r LT_TxBuffSz = 0; /* Transmit buffer that is reused from tx packet to tx packet. The 's' byte represents the source mac address (ours) and we don't have to initialize it because the MAC device will automatically fill it in for us. The four 'p' bytes represent the process number of this Mini vMac application. It helps differentiate packets between two applications running on the same machine. It is not used at this time. There is a small chance two applications could get the same LLAP/SDLC address to start with and would not work correctly (1 in 254). The 'S' bytes are the size of the LLAP packet since it can be smaller than the minimum sized Ethernet frame. The process number is replaced at initialization. The size is updated just before sending to BPF. All LLAP data is inserted starting at byte 20. */ static unsigned char tx_buffer[20 + LT_TxBfMxSz] = "\xFF\xFF\xFF\xFF\xFF\xFFssssss\x80\x9BppppSS"; /* Receive state */ GLOBALVAR ui3p LT_RxBuffer = NULL; /* When data pending, this is used */ GLOBALVAR ui5r LT_RxBuffSz = 0; /* When data pending, this is used */ /* Macro used by only the get_sockaddrs function for readability. */ #define ROUNDUP(a, size) \ (((a) & ((size) - 1)) ? (1 + ((a) | ((size) - 1))) : (a)) /* Utility function needed for walking the addresses of the kernel route lookup */ LOCALPROC get_sockaddrs(int addrs, struct sockaddr* sa, struct sockaddr** rti_info) { int loop; int incr; for (loop = 0; loop < RTAX_MAX; loop++) { if (addrs & (1 << loop)) { rti_info[loop] = sa; incr = sa->sa_len ? ROUNDUP(sa->sa_len, sizeof(uint32_t)) : sizeof(uint32_t); sa = (struct sockaddr*)((unsigned long int)sa + incr); } else { rti_info[loop] = NULL; } } } /* This ugly function does a lot of steps to prepare the BPF for our use. 1. Find the ethernet interface that the default route uses. 2. Determine the maximum number of BPF devices can exist. 3. Search for a usable BPF device and open it. 4. Set the BPF device to use our ethernet interface. 5. Get the proper buffer size to use with the BPF device. 6. Set some useful modes of operation on the BPF device. 7. Install a program on the device that filters out non-LTOE packets. */ LOCALFUNC int get_ethernet(void) { int result; int size; struct rt_msghdr* message; struct sockaddr_in* addrs; struct sockaddr* sa_list[RTAX_MAX]; int loop; char filename[64]; struct ifreq ifreq; int enable = 1; struct kinfo_proc kp; size_t len = sizeof(kp); int max = 4; char device[32]; /* Get a socket to routed for IPv4 */ fd = socket(PF_ROUTE, SOCK_RAW, AF_INET); if (fd == -1) { return falseblnr; } /* Allocate a message */ size = sizeof(struct rt_msghdr) + 16 * sizeof(struct sockaddr_in); message = (struct rt_msghdr*)malloc(size); if (! message) { close(fd); return falseblnr; } memset(message, 0, size); addrs = (struct sockaddr_in*)(message + 1); /* Fill in the request */ message->rtm_msglen = size; message->rtm_version = RTM_VERSION; message->rtm_type = RTM_GET; message->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_IFP | RTA_IFA; addrs->sin_len = sizeof(struct sockaddr_in); addrs->sin_family = AF_INET; addrs->sin_addr.s_addr = 0; /* 0.0.0.0 is default route */ /* Send the message to the kernel */ result = write(fd, message, size); if (result < 0) { close(fd); free(message); return falseblnr; } /* Read the result from the kernel */ result = read(fd, message, size); if (result < 0) { close(fd); free(message); return falseblnr; } /* Close the route socket */ close(fd); /* Get pointer to the result then parse it */ struct sockaddr* sa = (struct sockaddr*) ((unsigned long int)message + sizeof(struct rt_msghdr)); get_sockaddrs(message->rtm_addrs, sa, sa_list); /* Must have a LINK (Ethernet) */ if ((! sa_list[RTAX_IFP]) || (sa_list[RTAX_IFP]->sa_family != AF_LINK)) { return falseblnr; } int namelen = ((struct sockaddr_dl*)sa_list[RTAX_IFP])->sdl_nlen; #if 0 int addrlen = ((struct sockaddr_dl*)sa_list[RTAX_IFP])->sdl_alen; #endif strncpy(device, &((struct sockaddr_dl*)sa_list[RTAX_IFP])->sdl_data[0], namelen); device[namelen] = 0; memcpy(device_address, &((struct sockaddr_dl*)sa_list[RTAX_IFP])->sdl_data[namelen], 6); memcpy(&(tx_buffer[6]), &((struct sockaddr_dl*)sa_list[RTAX_IFP])->sdl_data[namelen], 6); result = sysctlbyname("debug.bpf_maxdevices", &kp, &len, NULL, 0); if (result == -1) { return falseblnr; } max = *((int *)&kp); for (loop = 0; loop < max; loop++) { sprintf(filename, "/dev/bpf%d", loop); fd = open(filename, O_RDWR | O_NONBLOCK | O_EXLOCK); if (fd >= 0) { /* sprintf(buffer, "using %s\n", filename); */ break; } } if (fd <= 0) { return falseblnr; } memset(&ifreq, 0, sizeof(struct ifreq)); strncpy(ifreq.ifr_name, device, IFNAMSIZ); result = ioctl(fd, BIOCSETIF, &ifreq); if (result) { return falseblnr; } result = ioctl(fd, BIOCGBLEN, &device_buffer_size); if (result) { return falseblnr; } result = ioctl(fd, BIOCPROMISC, &enable); if (result) { return falseblnr; } result = ioctl(fd, BIOCSSEESENT, &enable); if (result) { return falseblnr; } result = ioctl(fd, BIOCSHDRCMPLT, &enable); if (result) { return falseblnr; } result = ioctl(fd, BIOCIMMEDIATE, &enable); if (result) { return falseblnr; } result = ioctl(fd, BIOCVERSION, &bpf_version); if (result) { return falseblnr; } bpf_program.bf_len = 4; bpf_program.bf_insns = insns; result = ioctl(fd, BIOCSETF, &bpf_program); if (result) { return falseblnr; } return trueblnr; } LOCALVAR unsigned char *MyRxBuffer = NULL; /* External function needed at startup to initialize the LocalTalk functionality. */ LOCALFUNC int InitLocalTalk(void) { /* Perform a lot of stuff to get access to the Ethernet */ get_ethernet(); /* Save the process id in the transmit buffer as it may be used later to uniquely identify the sender to identify collisions in dynamic llap node address assignment. */ *((uint32_t*)(&tx_buffer[14])) = htonl(getpid()); LT_TxBuffer = (ui3p)&tx_buffer[20]; MyRxBuffer = malloc(device_buffer_size); if (NULL == MyRxBuffer) { return falseblnr; } /* Initialized properly */ return trueblnr; } GLOBALOSGLUPROC LT_TransmitPacket(void) { int count; /* Write the length in the packet. This is needed because Ethernet has a minimum 60 bytes length, which the MAC chip will enforce on TX. Without the size, a simple 3 byte LLAP packet would look like a (60 - 14 =) 46 byte LLAP packet. */ *((uint16_t*)(&tx_buffer[18])) = htons(LT_TxBuffSz); /* Send the packet to Ethernet */ count = write(fd, tx_buffer, 20 + LT_TxBuffSz); (void)count; /* unused */ } LOCALVAR unsigned char* NextPacket = NULL; LOCALVAR unsigned char* EndPackets = NULL; LOCALPROC LocalTalkTick0(void) { /* Get a single buffer worth of packets from BPF */ unsigned char* device_buffer = MyRxBuffer; int bytes = read(fd, device_buffer, device_buffer_size); if (bytes > 0) { /* Maybe multiple packets in this buffer */ #if 0 dbglog_WriteNote("SCC founds packets from BPF"); #endif NextPacket = device_buffer; EndPackets = device_buffer + bytes; } } GLOBALOSGLUPROC LT_ReceivePacket(void) { label_retry: if (NextPacket == NULL) { LocalTalkTick0(); if (NextPacket != NULL) { goto label_retry; } } else if (NextPacket >= EndPackets) { #if 0 dbglog_WriteNote("SCC finished set of packets from BPF"); #endif NextPacket = NULL; goto label_retry; } else { unsigned char* packet = NextPacket; /* Get pointer to BPF header */ struct bpf_hdr* header = (struct bpf_hdr *)packet; /* Advance to next packet in buffer */ NextPacket += BPF_WORDALIGN(header->bh_hdrlen + header->bh_caplen); /* Get clean references to data */ int ethernet_length = header->bh_caplen - 14; int llap_length = htons(*((uint16_t*)(packet + header->bh_hdrlen + 18))); unsigned char* start = packet + header->bh_hdrlen + 20; if (llap_length <= ethernet_length) { /* Start the receiver */ LT_RxBuffer = (ui3p)start; LT_RxBuffSz = llap_length; } else { goto label_retry; } } } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/COMOSGLU.h b/Mini vMac/mnvm_core/COMOSGLU.h index 3725ba6..fbb467e 100755 --- a/Mini vMac/mnvm_core/COMOSGLU.h +++ b/Mini vMac/mnvm_core/COMOSGLU.h @@ -1,1184 +1 @@ -/* - COMOSGLU.h - - Copyright (C) 2009 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - COMmon code for Operating System GLUe -*/ - - -GLOBALVAR ui3p ROM = nullpr; - -GLOBALVAR ui5b vSonyWritableMask = 0; -GLOBALVAR ui5b vSonyInsertedMask = 0; - -#if IncludeSonyRawMode -GLOBALVAR blnr vSonyRawMode = falseblnr; -#endif - -#if IncludeSonyNew -GLOBALVAR blnr vSonyNewDiskWanted = falseblnr; -GLOBALVAR ui5b vSonyNewDiskSize; -#endif - -#if IncludeSonyNameNew -GLOBALVAR tPbuf vSonyNewDiskName = NotAPbuf; -#endif - -GLOBALVAR ui5b CurMacDateInSeconds = 0; -GLOBALVAR ui5b CurMacLatitude = 0; -GLOBALVAR ui5b CurMacLongitude = 0; -GLOBALVAR ui5b CurMacDelta = 0; - -#if 0 != vMacScreenDepth -GLOBALVAR blnr UseColorMode = falseblnr; -GLOBALVAR blnr ColorModeWorks = falseblnr; -#endif - -#if 0 != vMacScreenDepth -GLOBALVAR blnr ColorMappingChanged = falseblnr; -#endif - -#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4) -GLOBALVAR ui4r CLUT_reds[CLUT_size]; -GLOBALVAR ui4r CLUT_greens[CLUT_size]; -GLOBALVAR ui4r CLUT_blues[CLUT_size]; -#endif - -LOCALVAR blnr RequestMacOff = falseblnr; - -GLOBALVAR blnr ForceMacOff = falseblnr; - -GLOBALVAR blnr WantMacInterrupt = falseblnr; - -GLOBALVAR blnr WantMacReset = falseblnr; - -GLOBALVAR ui3b SpeedValue = WantInitSpeedValue; - -#if EnableAutoSlow -GLOBALVAR blnr WantNotAutoSlow = (WantInitNotAutoSlow != 0); -#endif - -GLOBALVAR ui4b CurMouseV = 0; -GLOBALVAR ui4b CurMouseH = 0; - -#if EnableMouseMotion && MayFullScreen -LOCALVAR blnr HaveMouseMotion = falseblnr; -#endif - -#if EnableAutoSlow -GLOBALVAR ui5r QuietTime = 0; -GLOBALVAR ui5r QuietSubTicks = 0; -#endif - -#if IncludePbufs -LOCALVAR ui5b PbufAllocatedMask; -LOCALVAR ui5b PbufSize[NumPbufs]; -#endif - -#if IncludePbufs -#define PbufIsAllocated(i) ((PbufAllocatedMask & ((ui5b)1 << (i))) != 0) -#endif - -#if IncludePbufs -LOCALFUNC blnr FirstFreePbuf(tPbuf *r) -{ - tPbuf i; - - for (i = 0; i < NumPbufs; ++i) { - if (! PbufIsAllocated(i)) { - *r = i; - return trueblnr; - } - } - return falseblnr; -} -#endif - -#if IncludePbufs -LOCALPROC PbufNewNotify(tPbuf Pbuf_No, ui5b count) -{ - PbufSize[Pbuf_No] = count; - PbufAllocatedMask |= ((ui5b)1 << Pbuf_No); -} -#endif - -#if IncludePbufs -LOCALPROC PbufDisposeNotify(tPbuf Pbuf_No) -{ - PbufAllocatedMask &= ~ ((ui5b)1 << Pbuf_No); -} -#endif - -#if IncludePbufs -GLOBALFUNC tMacErr CheckPbuf(tPbuf Pbuf_No) -{ - tMacErr result; - - if (Pbuf_No >= NumPbufs) { - result = mnvm_nsDrvErr; - } else if (! PbufIsAllocated(Pbuf_No)) { - result = mnvm_offLinErr; - } else { - result = mnvm_noErr; - } - - return result; -} -#endif - -#if IncludePbufs -GLOBALFUNC tMacErr PbufGetSize(tPbuf Pbuf_No, ui5r *Count) -{ - tMacErr result = CheckPbuf(Pbuf_No); - - if (mnvm_noErr == result) { - *Count = PbufSize[Pbuf_No]; - } - - return result; -} -#endif - -LOCALFUNC blnr FirstFreeDisk(tDrive *Drive_No) -{ - tDrive i; - - for (i = 0; i < NumDrives; ++i) { - if (! vSonyIsInserted(i)) { - *Drive_No = i; - return trueblnr; - } - } - return falseblnr; -} - -GLOBALFUNC blnr AnyDiskInserted(void) -{ -#if 0 - tDrive i; - - for (i = 0; i < NumDrives; ++i) { - if (vSonyIsInserted(i)) { - return trueblnr; - } - } - return falseblnr; -#endif - return 0 != vSonyInsertedMask; -} - -GLOBALPROC DiskRevokeWritable(tDrive Drive_No) -{ - vSonyWritableMask &= ~ ((ui5b)1 << Drive_No); -} - -LOCALPROC DiskInsertNotify(tDrive Drive_No, blnr locked) -{ - vSonyInsertedMask |= ((ui5b)1 << Drive_No); - if (! locked) { - vSonyWritableMask |= ((ui5b)1 << Drive_No); - } - - QuietEnds(); -} - -LOCALPROC DiskEjectedNotify(tDrive Drive_No) -{ - vSonyWritableMask &= ~ ((ui5b)1 << Drive_No); - vSonyInsertedMask &= ~ ((ui5b)1 << Drive_No); -} - -/* - block type - for operating on multiple ui3b elements - at a time. -*/ - -#if LittleEndianUnaligned || BigEndianUnaligned - -#define uibb ui5b -#define uibr ui5r -#define ln2uiblockn 2 - -#if 0 -#define uibb long long -#define uibr long long -#define ln2uiblockn 3 -#endif - -#else - -#define uibb ui3b -#define uibr ui3r -#define ln2uiblockn 0 - -#endif - -#define uiblockn (1 << ln2uiblockn) -#define ln2uiblockbitsn (3 + ln2uiblockn) -#define uiblockbitsn (8 * uiblockn) - -LOCALFUNC blnr FindFirstChangeInLVecs(uibb *ptr1, uibb *ptr2, - uimr L, uimr *j) -{ -/* - find index of first difference -*/ - uibb *p1 = ptr1; - uibb *p2 = ptr2; - uimr i; - - for (i = L; i != 0; --i) { - if (*p1++ != *p2++) { - --p1; - *j = p1 - ptr1; - return trueblnr; - } - } - return falseblnr; -} - -LOCALPROC FindLastChangeInLVecs(uibb *ptr1, uibb *ptr2, - uimr L, uimr *j) -{ -/* - find index of last difference, assuming there is one -*/ - uibb *p1 = ptr1 + L; - uibb *p2 = ptr2 + L; - - while (*--p1 == *--p2) { - } - *j = p1 - ptr1; -} - -LOCALPROC FindLeftRightChangeInLMat(uibb *ptr1, uibb *ptr2, - uimr width, uimr top, uimr bottom, - uimr *LeftMin0, uibr *LeftMask0, - uimr *RightMax0, uibr *RightMask0) -{ - uimr i; - uimr j; - uibb *p1; - uibb *p2; - uibr x; - ui5r offset = top * width; - uibb *p10 = (uibb *)ptr1 + offset; - uibb *p20 = (uibb *)ptr2 + offset; - uimr LeftMin = *LeftMin0; - uimr RightMax = *RightMax0; - uibr LeftMask = 0; - uibr RightMask = 0; - for (i = top; i < bottom; ++i) { - p1 = p10; - p2 = p20; - for (j = 0; j < LeftMin; ++j) { - x = *p1++ ^ *p2++; - if (0 != x) { - LeftMin = j; - LeftMask = x; - goto Label_3; - } - } - LeftMask |= (*p1 ^ *p2); -Label_3: - p1 = p10 + RightMax; - p2 = p20 + RightMax; - RightMask |= (*p1++ ^ *p2++); - for (j = RightMax + 1; j < width; ++j) { - x = *p1++ ^ *p2++; - if (0 != x) { - RightMax = j; - RightMask = x; - } - } - - p10 += width; - p20 += width; - } - *LeftMin0 = LeftMin; - *RightMax0 = RightMax; - *LeftMask0 = LeftMask; - *RightMask0 = RightMask; -} - -LOCALVAR ui3p screencomparebuff = nullpr; - -LOCALVAR uimr NextDrawRow = 0; - - -#if BigEndianUnaligned - -#define FlipCheckMonoBits (uiblockbitsn - 1) - -#else - -#define FlipCheckMonoBits 7 - -#endif - -#define FlipCheckBits (FlipCheckMonoBits >> vMacScreenDepth) - -#ifndef WantColorTransValid -#define WantColorTransValid 0 -#endif - -#if WantColorTransValid -LOCALVAR blnr ColorTransValid = falseblnr; -#endif - -LOCALFUNC blnr ScreenFindChanges(ui3p screencurrentbuff, - si3b TimeAdjust, si4b *top, si4b *left, si4b *bottom, si4b *right) -{ - uimr j0; - uimr j1; - uimr j0h; - uimr j1h; - uimr j0v; - uimr j1v; - uimr copysize; - uimr copyoffset; - uimr copyrows; - uimr LimitDrawRow; - uimr MaxRowsDrawnPerTick; - uimr LeftMin; - uimr RightMax; - uibr LeftMask; - uibr RightMask; - int j; - - if (TimeAdjust < 4) { - MaxRowsDrawnPerTick = vMacScreenHeight; - } else if (TimeAdjust < 6) { - MaxRowsDrawnPerTick = vMacScreenHeight / 2; - } else { - MaxRowsDrawnPerTick = vMacScreenHeight / 4; - } - -#if 0 != vMacScreenDepth - if (UseColorMode) { - if (ColorMappingChanged) { - ColorMappingChanged = falseblnr; - j0h = 0; - j1h = vMacScreenWidth; - j0v = 0; - j1v = vMacScreenHeight; -#if WantColorTransValid - ColorTransValid = falseblnr; -#endif - } else { - if (! FindFirstChangeInLVecs( - (uibb *)screencurrentbuff - + NextDrawRow * (vMacScreenBitWidth / uiblockbitsn), - (uibb *)screencomparebuff - + NextDrawRow * (vMacScreenBitWidth / uiblockbitsn), - ((uimr)(vMacScreenHeight - NextDrawRow) - * (uimr)vMacScreenBitWidth) / uiblockbitsn, - &j0)) - { - NextDrawRow = 0; - return falseblnr; - } - j0v = j0 / (vMacScreenBitWidth / uiblockbitsn); - j0h = j0 - j0v * (vMacScreenBitWidth / uiblockbitsn); - j0v += NextDrawRow; - LimitDrawRow = j0v + MaxRowsDrawnPerTick; - if (LimitDrawRow >= vMacScreenHeight) { - LimitDrawRow = vMacScreenHeight; - NextDrawRow = 0; - } else { - NextDrawRow = LimitDrawRow; - } - FindLastChangeInLVecs((uibb *)screencurrentbuff, - (uibb *)screencomparebuff, - ((uimr)LimitDrawRow - * (uimr)vMacScreenBitWidth) / uiblockbitsn, - &j1); - j1v = j1 / (vMacScreenBitWidth / uiblockbitsn); - j1h = j1 - j1v * (vMacScreenBitWidth / uiblockbitsn); - j1v++; - - if (j0h < j1h) { - LeftMin = j0h; - RightMax = j1h; - } else { - LeftMin = j1h; - RightMax = j0h; - } - - FindLeftRightChangeInLMat((uibb *)screencurrentbuff, - (uibb *)screencomparebuff, - (vMacScreenBitWidth / uiblockbitsn), - j0v, j1v, &LeftMin, &LeftMask, &RightMax, &RightMask); - -#if vMacScreenDepth > ln2uiblockbitsn - j0h = (LeftMin >> (vMacScreenDepth - ln2uiblockbitsn)); -#elif ln2uiblockbitsn > vMacScreenDepth - for (j = 0; j < (1 << (ln2uiblockbitsn - vMacScreenDepth)); - ++j) - { - if (0 != (LeftMask - & (((((uibr)1) << (1 << vMacScreenDepth)) - 1) - << ((j ^ FlipCheckBits) << vMacScreenDepth)))) - { - goto Label_1c; - } - } -Label_1c: - j0h = (LeftMin << (ln2uiblockbitsn - vMacScreenDepth)) + j; -#else - j0h = LeftMin; -#endif - -#if vMacScreenDepth > ln2uiblockbitsn - j1h = (RightMax >> (vMacScreenDepth - ln2uiblockbitsn)) + 1; -#elif ln2uiblockbitsn > vMacScreenDepth - for (j = (uiblockbitsn >> vMacScreenDepth); --j >= 0; ) { - if (0 != (RightMask - & (((((uibr)1) << (1 << vMacScreenDepth)) - 1) - << ((j ^ FlipCheckBits) << vMacScreenDepth)))) - { - goto Label_2c; - } - } -Label_2c: - j1h = (RightMax << (ln2uiblockbitsn - vMacScreenDepth)) - + j + 1; -#else - j1h = RightMax + 1; -#endif - } - - copyrows = j1v - j0v; - copyoffset = j0v * vMacScreenByteWidth; - copysize = copyrows * vMacScreenByteWidth; - } else -#endif - { -#if 0 != vMacScreenDepth - if (ColorMappingChanged) { - ColorMappingChanged = falseblnr; - j0h = 0; - j1h = vMacScreenWidth; - j0v = 0; - j1v = vMacScreenHeight; -#if WantColorTransValid - ColorTransValid = falseblnr; -#endif - } else -#endif - { - if (! FindFirstChangeInLVecs( - (uibb *)screencurrentbuff - + NextDrawRow * (vMacScreenWidth / uiblockbitsn), - (uibb *)screencomparebuff - + NextDrawRow * (vMacScreenWidth / uiblockbitsn), - ((uimr)(vMacScreenHeight - NextDrawRow) - * (uimr)vMacScreenWidth) / uiblockbitsn, - &j0)) - { - NextDrawRow = 0; - return falseblnr; - } - j0v = j0 / (vMacScreenWidth / uiblockbitsn); - j0h = j0 - j0v * (vMacScreenWidth / uiblockbitsn); - j0v += NextDrawRow; - LimitDrawRow = j0v + MaxRowsDrawnPerTick; - if (LimitDrawRow >= vMacScreenHeight) { - LimitDrawRow = vMacScreenHeight; - NextDrawRow = 0; - } else { - NextDrawRow = LimitDrawRow; - } - FindLastChangeInLVecs((uibb *)screencurrentbuff, - (uibb *)screencomparebuff, - ((uimr)LimitDrawRow - * (uimr)vMacScreenWidth) / uiblockbitsn, - &j1); - j1v = j1 / (vMacScreenWidth / uiblockbitsn); - j1h = j1 - j1v * (vMacScreenWidth / uiblockbitsn); - j1v++; - - if (j0h < j1h) { - LeftMin = j0h; - RightMax = j1h; - } else { - LeftMin = j1h; - RightMax = j0h; - } - - FindLeftRightChangeInLMat((uibb *)screencurrentbuff, - (uibb *)screencomparebuff, - (vMacScreenWidth / uiblockbitsn), - j0v, j1v, &LeftMin, &LeftMask, &RightMax, &RightMask); - - for (j = 0; j < uiblockbitsn; ++j) { - if (0 != (LeftMask - & (((uibr)1) << (j ^ FlipCheckMonoBits)))) - { - goto Label_1; - } - } -Label_1: - j0h = LeftMin * uiblockbitsn + j; - - for (j = uiblockbitsn; --j >= 0; ) { - if (0 != (RightMask - & (((uibr)1) << (j ^ FlipCheckMonoBits)))) - { - goto Label_2; - } - } -Label_2: - j1h = RightMax * uiblockbitsn + j + 1; - } - - copyrows = j1v - j0v; - copyoffset = j0v * vMacScreenMonoByteWidth; - copysize = copyrows * vMacScreenMonoByteWidth; - } - - MyMoveBytes((anyp)screencurrentbuff + copyoffset, - (anyp)screencomparebuff + copyoffset, - copysize); - - *top = j0v; - *left = j0h; - *bottom = j1v; - *right = j1h; - - return trueblnr; -} - -GLOBALVAR blnr EmVideoDisable = falseblnr; -GLOBALVAR si3b EmLagTime = 0; - -GLOBALVAR ui5b OnTrueTime = 0; - /* - The time slice we are currently dealing - with, in the same units as TrueEmulatedTime. - */ - -LOCALVAR si4b ScreenChangedTop; -LOCALVAR si4b ScreenChangedLeft; -LOCALVAR si4b ScreenChangedBottom; -LOCALVAR si4b ScreenChangedRight; - -LOCALPROC ScreenClearChanges(void) -{ - ScreenChangedTop = vMacScreenHeight; - ScreenChangedBottom = 0; - ScreenChangedLeft = vMacScreenWidth; - ScreenChangedRight = 0; -} - -LOCALPROC ScreenChangedAll(void) -{ - ScreenChangedTop = 0; - ScreenChangedBottom = vMacScreenHeight; - ScreenChangedLeft = 0; - ScreenChangedRight = vMacScreenWidth; -} - -#if EnableAutoSlow -LOCALVAR si4b ScreenChangedQuietTop = vMacScreenHeight; -LOCALVAR si4b ScreenChangedQuietLeft = vMacScreenWidth; -LOCALVAR si4b ScreenChangedQuietBottom = 0; -LOCALVAR si4b ScreenChangedQuietRight = 0; -#endif - -GLOBALPROC Screen_OutputFrame(ui3p screencurrentbuff) -{ - si4b top; - si4b left; - si4b bottom; - si4b right; - - if (! EmVideoDisable) { - if (ScreenFindChanges(screencurrentbuff, EmLagTime, - &top, &left, &bottom, &right)) - { - if (top < ScreenChangedTop) { - ScreenChangedTop = top; - } - if (bottom > ScreenChangedBottom) { - ScreenChangedBottom = bottom; - } - if (left < ScreenChangedLeft) { - ScreenChangedLeft = left; - } - if (right > ScreenChangedRight) { - ScreenChangedRight = right; - } - -#if EnableAutoSlow - if (top < ScreenChangedQuietTop) { - ScreenChangedQuietTop = top; - } - if (bottom > ScreenChangedQuietBottom) { - ScreenChangedQuietBottom = bottom; - } - if (left < ScreenChangedQuietLeft) { - ScreenChangedQuietLeft = left; - } - if (right > ScreenChangedQuietRight) { - ScreenChangedQuietRight = right; - } - - if (((ScreenChangedQuietRight - ScreenChangedQuietLeft) > 1) - || ((ScreenChangedQuietBottom - - ScreenChangedQuietTop) > 32)) - { - ScreenChangedQuietTop = vMacScreenHeight; - ScreenChangedQuietLeft = vMacScreenWidth; - ScreenChangedQuietBottom = 0; - ScreenChangedQuietRight = 0; - - QuietEnds(); - } -#endif - } - } -} - -#if MayFullScreen -LOCALVAR ui4r ViewHSize; -LOCALVAR ui4r ViewVSize; -LOCALVAR ui4r ViewHStart = 0; -LOCALVAR ui4r ViewVStart = 0; -#if EnableMouseMotion -LOCALVAR si4b SavedMouseH; -LOCALVAR si4b SavedMouseV; -#endif -#endif - -#ifndef WantAutoScrollBorder -#define WantAutoScrollBorder 0 -#endif - -#if EnableMouseMotion && MayFullScreen -LOCALPROC AutoScrollScreen(void) -{ - si4b Shift; - si4b Limit; - - /* - Scroll in multiples of two pixels, so as to - work better with the common gray pattern. - ViewHSize and ViewVSize are constrained - to a multiple of two. - - Mac OS (some versions at least) constrains - the mouse position to be less than the screen - height and width, not allowing equal to it. - Can still scroll to see last pixel because - scroll in multiples of two pixels. - */ - - if (vMacScreenWidth != ViewHSize) { - Shift = 0; - Limit = ViewHStart -#if WantAutoScrollBorder - + (ViewHSize / 16) -#endif - ; - if (CurMouseH < Limit) { - Shift = (Limit - CurMouseH + 1) & (~ 1); - Limit = ViewHStart; - if (Shift >= Limit) { - Shift = Limit; - } - Shift = - Shift; - } else { - Limit = ViewHStart + ViewHSize -#if WantAutoScrollBorder - - (ViewHSize / 16) -#endif - ; - if (CurMouseH > Limit) { - Shift = (CurMouseH - Limit + 1) & (~ 1); - Limit = vMacScreenWidth - ViewHSize - ViewHStart; - if (Shift >= Limit) { - Shift = Limit; - } - } - } - - if (Shift != 0) { - ViewHStart += Shift; - SavedMouseH += Shift; - ScreenChangedAll(); - } - } - - if (vMacScreenHeight != ViewVSize) { - Shift = 0; - Limit = ViewVStart -#if WantAutoScrollBorder - + (ViewVSize / 16) -#endif - ; - if (CurMouseV < Limit) { - Shift = (Limit - CurMouseV + 1) & (~ 1); - Limit = ViewVStart; - if (Shift >= Limit) { - Shift = Limit; - } - Shift = - Shift; - } else { - Limit = ViewVStart + ViewVSize -#if WantAutoScrollBorder - - (ViewVSize / 16) -#endif - ; - if (CurMouseV > Limit) { - Shift = (CurMouseV - Limit + 1) & (~ 1); - Limit = vMacScreenHeight - ViewVSize - ViewVStart; - if (Shift >= Limit) { - Shift = Limit; - } - } - } - - if (Shift != 0) { - ViewVStart += Shift; - SavedMouseV += Shift; - ScreenChangedAll(); - } - } -} -#endif - -LOCALPROC SetLongs(ui5b *p, long n) -{ - long i; - - for (i = n; --i >= 0; ) { - *p++ = (ui5b) -1; - } -} - -LOCALVAR uimr ReserveAllocOffset; -LOCALVAR ui3p ReserveAllocBigBlock = nullpr; - -#define PowOf2(p) ((uimr)1 << (p)) -#define Pow2Mask(p) (PowOf2(p) - 1) -#define ModPow2(i, p) ((i) & Pow2Mask(p)) -#define FloorDivPow2(i, p) ((i) >> (p)) -#define FloorPow2Mult(i, p) ((i) & (~ Pow2Mask(p))) -#define CeilPow2Mult(i, p) FloorPow2Mult((i) + Pow2Mask(p), (p)) - /* warning - CeilPow2Mult evaluates p twice */ - -GLOBALPROC ReserveAllocOneBlock(ui3p *p, uimr n, - ui3r align, blnr FillOnes) -{ - ReserveAllocOffset = CeilPow2Mult(ReserveAllocOffset, align); - if (nullpr == ReserveAllocBigBlock) { - *p = nullpr; - } else { - *p = ReserveAllocBigBlock + ReserveAllocOffset; - if (FillOnes) { - SetLongs((ui5b *)*p, n / 4); - } - } - ReserveAllocOffset += n; -} - -/* --- sending debugging info to file --- */ - -#if dbglog_HAVE - -#define dbglog_bufsz PowOf2(dbglog_buflnsz) -LOCALVAR uimr dbglog_bufpos = 0; - -LOCALVAR char *dbglog_bufp = nullpr; - -LOCALPROC dbglog_ReserveAlloc(void) -{ - ReserveAllocOneBlock((ui3p *)&dbglog_bufp, dbglog_bufsz, - 5, falseblnr); -} - -#define dbglog_open dbglog_open0 - -LOCALPROC dbglog_close(void) -{ - uimr n = ModPow2(dbglog_bufpos, dbglog_buflnsz); - if (n != 0) { - dbglog_write0(dbglog_bufp, n); - } - - dbglog_close0(); -} - -LOCALPROC dbglog_write(char *p, uimr L) -{ - uimr r; - uimr bufposmod; - uimr curbufdiv; - uimr newbufpos = dbglog_bufpos + L; - uimr newbufdiv = FloorDivPow2(newbufpos, dbglog_buflnsz); - -label_retry: - curbufdiv = FloorDivPow2(dbglog_bufpos, dbglog_buflnsz); - bufposmod = ModPow2(dbglog_bufpos, dbglog_buflnsz); - if (newbufdiv != curbufdiv) { - r = dbglog_bufsz - bufposmod; - MyMoveBytes((anyp)p, (anyp)(dbglog_bufp + bufposmod), r); - dbglog_write0(dbglog_bufp, dbglog_bufsz); - L -= r; - p += r; - dbglog_bufpos += r; - goto label_retry; - } - MyMoveBytes((anyp)p, (anyp)dbglog_bufp + bufposmod, L); - dbglog_bufpos = newbufpos; -} - -LOCALFUNC uimr CStrLength(char *s) -{ - char *p = s; - - while (*p++ != 0) { - } - return p - s - 1; -} - -GLOBALPROC dbglog_writeCStr(char *s) -{ - /* fprintf(DumpFile, "%s", s); */ - dbglog_write(s, CStrLength(s)); -} - -GLOBALPROC dbglog_writeReturn(void) -{ - dbglog_writeCStr("\n"); - /* fprintf(DumpFile, "\n"); */ -} - -GLOBALPROC dbglog_writeHex(uimr x) -{ - ui3r v; - char s[16]; - char *p = s + 16; - uimr n = 0; - - do { - v = x & 0x0F; - if (v < 10) { - *--p = '0' + v; - } else { - *--p = 'A' + v - 10; - } - x >>= 4; - ++n; - } while (x != 0); - - dbglog_write(p, n); - /* fprintf(DumpFile, "%d", (int)x); */ -} - -GLOBALPROC dbglog_writeNum(uimr x) -{ - uimr newx; - char s[16]; - char *p = s + 16; - uimr n = 0; - - do { - newx = x / (uimr)10; - *--p = '0' + (x - newx * 10); - x = newx; - ++n; - } while (x != 0); - - dbglog_write(p, n); - /* fprintf(DumpFile, "%d", (int)x); */ -} - -GLOBALPROC dbglog_writeMacChar(ui3r x) -{ - char s; - - if ((x > 32) && (x < 127)) { - s = x; - } else { - s = '?'; - } - - dbglog_write(&s, 1); -} - -LOCALPROC dbglog_writeSpace(void) -{ - dbglog_writeCStr(" "); -} - -GLOBALPROC dbglog_writeln(char *s) -{ - dbglog_writeCStr(s); - dbglog_writeReturn(); -} - -GLOBALPROC dbglog_writelnNum(char *s, simr v) -{ - dbglog_writeCStr(s); - dbglog_writeSpace(); - dbglog_writeNum(v); - dbglog_writeReturn(); -} - -#endif - -/* my event queue */ - -#define MyEvtQLg2Sz 4 -#define MyEvtQSz (1 << MyEvtQLg2Sz) -#define MyEvtQIMask (MyEvtQSz - 1) - -LOCALVAR MyEvtQEl MyEvtQA[MyEvtQSz]; -LOCALVAR ui4r MyEvtQIn = 0; -LOCALVAR ui4r MyEvtQOut = 0; - -GLOBALFUNC MyEvtQEl * MyEvtQOutP(void) -{ - MyEvtQEl *p = nullpr; - if (MyEvtQIn != MyEvtQOut) { - p = &MyEvtQA[MyEvtQOut & MyEvtQIMask]; - } - return p; -} - -GLOBALPROC MyEvtQOutDone(void) -{ - ++MyEvtQOut; -} - -LOCALVAR blnr MyEvtQNeedRecover = falseblnr; - /* events lost because of full queue */ - -LOCALFUNC MyEvtQEl * MyEvtQElPreviousIn(void) -{ - MyEvtQEl *p = NULL; - if (MyEvtQIn - MyEvtQOut != 0) { - p = &MyEvtQA[(MyEvtQIn - 1) & MyEvtQIMask]; - } - - return p; -} - -LOCALFUNC MyEvtQEl * MyEvtQElAlloc(void) -{ - MyEvtQEl *p = NULL; - if (MyEvtQIn - MyEvtQOut >= MyEvtQSz) { - MyEvtQNeedRecover = trueblnr; - } else { - p = &MyEvtQA[MyEvtQIn & MyEvtQIMask]; - - ++MyEvtQIn; - } - - return p; -} - -LOCALVAR ui5b theKeys[4]; - -LOCALPROC Keyboard_UpdateKeyMap(int key, blnr down) -{ - int k = key & 127; /* just for safety */ - int bit = 1 << (k & 7); - ui3b *kp = (ui3b *)theKeys; - ui3b *kpi = &kp[k / 8]; - blnr CurDown = ((*kpi & bit) != 0); - if (CurDown != down) { - MyEvtQEl *p = MyEvtQElAlloc(); - if (NULL != p) { - p->kind = MyEvtQElKindKey; - p->u.press.key = k; - p->u.press.down = down; - - if (down) { - *kpi |= bit; - } else { - *kpi &= ~ bit; - } - } - - QuietEnds(); - } -} - -LOCALVAR blnr MyMouseButtonState = falseblnr; - -LOCALPROC MyMouseButtonSet(blnr down) -{ - if (MyMouseButtonState != down) { - MyEvtQEl *p = MyEvtQElAlloc(); - if (NULL != p) { - p->kind = MyEvtQElKindMouseButton; - p->u.press.down = down; - - MyMouseButtonState = down; - } - - QuietEnds(); - } -} - -#if EnableMouseMotion && MayFullScreen -LOCALPROC MyMousePositionSetDelta(ui4r dh, ui4r dv) -{ - if ((dh != 0) || (dv != 0)) { - MyEvtQEl *p = MyEvtQElPreviousIn(); - if ((NULL != p) && (MyEvtQElKindMouseDelta == p->kind)) { - p->u.pos.h += dh; - p->u.pos.v += dv; - } else { - p = MyEvtQElAlloc(); - if (NULL != p) { - p->kind = MyEvtQElKindMouseDelta; - p->u.pos.h = dh; - p->u.pos.v = dv; - } - } - - QuietEnds(); - } -} -#endif - -LOCALVAR ui4b MyMousePosCurV = 0; -LOCALVAR ui4b MyMousePosCurH = 0; - -LOCALPROC MyMousePositionSet(ui4r h, ui4r v) -{ - if ((h != MyMousePosCurH) || (v != MyMousePosCurV)) { - MyEvtQEl *p = MyEvtQElPreviousIn(); - if ((NULL == p) || (MyEvtQElKindMousePos != p->kind)) { - p = MyEvtQElAlloc(); - } - if (NULL != p) { - p->kind = MyEvtQElKindMousePos; - p->u.pos.h = h; - p->u.pos.v = v; - - MyMousePosCurH = h; - MyMousePosCurV = v; - } - - QuietEnds(); - } -} - -#if 0 -#define Keyboard_TestKeyMap(key) \ - ((((ui3b *)theKeys)[(key) / 8] & (1 << ((key) & 7))) != 0) -#endif - -LOCALPROC InitKeyCodes(void) -{ - theKeys[0] = 0; - theKeys[1] = 0; - theKeys[2] = 0; - theKeys[3] = 0; -} - -#define kKeepMaskControl (1 << 0) -#define kKeepMaskCapsLock (1 << 1) -#define kKeepMaskCommand (1 << 2) -#define kKeepMaskOption (1 << 3) -#define kKeepMaskShift (1 << 4) - -LOCALPROC DisconnectKeyCodes(ui5b KeepMask) -{ - /* - Called when may miss key ups, - so act is if all pressed keys have been released, - except maybe for control, caps lock, command, - option and shift. - */ - - int j; - int b; - int key; - ui5b m; - - for (j = 0; j < 16; ++j) { - ui3b k1 = ((ui3b *)theKeys)[j]; - if (0 != k1) { - ui3b bit = 1; - for (b = 0; b < 8; ++b) { - if (0 != (k1 & bit)) { - key = j * 8 + b; - switch (key) { - case MKC_Control: m = kKeepMaskControl; break; - case MKC_CapsLock: m = kKeepMaskCapsLock; break; - case MKC_Command: m = kKeepMaskCommand; break; - case MKC_Option: m = kKeepMaskOption; break; - case MKC_Shift: m = kKeepMaskShift; break; - default: m = 0; break; - } - if (0 == (KeepMask & m)) { - Keyboard_UpdateKeyMap(key, falseblnr); - } - } - bit <<= 1; - } - } - } -} - -LOCALPROC MyEvtQTryRecoverFromFull(void) -{ - MyMouseButtonSet(falseblnr); - DisconnectKeyCodes(0); -} - -/* MacMsg */ - -LOCALVAR char *SavedBriefMsg = nullpr; -LOCALVAR char *SavedLongMsg; -LOCALVAR blnr SavedFatalMsg; - -LOCALPROC MacMsg(char *briefMsg, char *longMsg, blnr fatal) -{ - if (nullpr != SavedBriefMsg) { - /* - ignore the new message, only display the - first error. - */ - } else { - SavedBriefMsg = briefMsg; - SavedLongMsg = longMsg; - SavedFatalMsg = fatal; - } -} - -GLOBALPROC WarnMsgCorruptedROM(void) -{ - MacMsg(kStrCorruptedROMTitle, kStrCorruptedROMMessage, falseblnr); -} - -GLOBALPROC WarnMsgUnsupportedROM(void) -{ - MacMsg(kStrUnsupportedROMTitle, - kStrUnsupportedROMMessage, falseblnr); -} - -GLOBALPROC WarnMsgAbnormal(void) -{ - MacMsg(kStrReportAbnormalTitle, - kStrReportAbnormalMessage, falseblnr); -} +/* COMOSGLU.h Copyright (C) 2009 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* COMmon code for Operating System GLUe */ #if EnableMouseMotion && MayFullScreen #define EnableFSMouseMotion 1 #else #define EnableFSMouseMotion 0 #endif #if EnableMagnify || VarFullScreen #define EnableRecreateW 1 #else #define EnableRecreateW 0 #endif #if EnableRecreateW || EnableFSMouseMotion #define EnableMoveMouse 1 #else #define EnableMoveMouse 0 #endif GLOBALVAR ui3p ROM = nullpr; GLOBALVAR ui5b vSonyWritableMask = 0; GLOBALVAR ui5b vSonyInsertedMask = 0; #if IncludeSonyRawMode GLOBALVAR blnr vSonyRawMode = falseblnr; #endif #if IncludeSonyNew GLOBALVAR blnr vSonyNewDiskWanted = falseblnr; GLOBALVAR ui5b vSonyNewDiskSize; #endif #if IncludeSonyNameNew GLOBALVAR tPbuf vSonyNewDiskName = NotAPbuf; #endif GLOBALVAR ui5b CurMacDateInSeconds = 0; GLOBALVAR ui5b CurMacLatitude = 0; GLOBALVAR ui5b CurMacLongitude = 0; GLOBALVAR ui5b CurMacDelta = 0; #if 0 != vMacScreenDepth GLOBALVAR blnr UseColorMode = falseblnr; GLOBALVAR blnr ColorModeWorks = falseblnr; #endif #if 0 != vMacScreenDepth GLOBALVAR blnr ColorMappingChanged = falseblnr; #endif #if (0 != vMacScreenDepth) && (vMacScreenDepth < 4) GLOBALVAR ui4r CLUT_reds[CLUT_size]; GLOBALVAR ui4r CLUT_greens[CLUT_size]; GLOBALVAR ui4r CLUT_blues[CLUT_size]; #endif LOCALVAR blnr RequestMacOff = falseblnr; GLOBALVAR blnr ForceMacOff = falseblnr; GLOBALVAR blnr WantMacInterrupt = falseblnr; GLOBALVAR blnr WantMacReset = falseblnr; GLOBALVAR ui3b SpeedValue = WantInitSpeedValue; #if EnableAutoSlow GLOBALVAR blnr WantNotAutoSlow = (WantInitNotAutoSlow != 0); #endif GLOBALVAR ui4b CurMouseV = 0; GLOBALVAR ui4b CurMouseH = 0; #if EnableFSMouseMotion LOCALVAR blnr HaveMouseMotion = falseblnr; #endif #if EnableAutoSlow GLOBALVAR ui5r QuietTime = 0; GLOBALVAR ui5r QuietSubTicks = 0; #endif #ifndef GrabKeysFullScreen #define GrabKeysFullScreen 1 #endif #ifndef GrabKeysMaxFullScreen #define GrabKeysMaxFullScreen 0 #endif #if IncludePbufs LOCALVAR ui5b PbufAllocatedMask; LOCALVAR ui5b PbufSize[NumPbufs]; #endif #if IncludePbufs #define PbufIsAllocated(i) ((PbufAllocatedMask & ((ui5b)1 << (i))) != 0) #endif #if IncludePbufs LOCALFUNC blnr FirstFreePbuf(tPbuf *r) { tPbuf i; for (i = 0; i < NumPbufs; ++i) { if (! PbufIsAllocated(i)) { *r = i; return trueblnr; } } return falseblnr; } #endif #if IncludePbufs LOCALPROC PbufNewNotify(tPbuf Pbuf_No, ui5b count) { PbufSize[Pbuf_No] = count; PbufAllocatedMask |= ((ui5b)1 << Pbuf_No); } #endif #if IncludePbufs LOCALPROC PbufDisposeNotify(tPbuf Pbuf_No) { PbufAllocatedMask &= ~ ((ui5b)1 << Pbuf_No); } #endif #if IncludePbufs GLOBALOSGLUFUNC tMacErr CheckPbuf(tPbuf Pbuf_No) { tMacErr result; if (Pbuf_No >= NumPbufs) { result = mnvm_nsDrvErr; } else if (! PbufIsAllocated(Pbuf_No)) { result = mnvm_offLinErr; } else { result = mnvm_noErr; } return result; } #endif #if IncludePbufs GLOBALOSGLUFUNC tMacErr PbufGetSize(tPbuf Pbuf_No, ui5r *Count) { tMacErr result = CheckPbuf(Pbuf_No); if (mnvm_noErr == result) { *Count = PbufSize[Pbuf_No]; } return result; } #endif LOCALFUNC blnr FirstFreeDisk(tDrive *Drive_No) { tDrive i; for (i = 0; i < NumDrives; ++i) { if (! vSonyIsInserted(i)) { *Drive_No = i; return trueblnr; } } return falseblnr; } GLOBALOSGLUFUNC blnr AnyDiskInserted(void) { #if 0 tDrive i; for (i = 0; i < NumDrives; ++i) { if (vSonyIsInserted(i)) { return trueblnr; } } return falseblnr; #endif return 0 != vSonyInsertedMask; } GLOBALOSGLUPROC DiskRevokeWritable(tDrive Drive_No) { vSonyWritableMask &= ~ ((ui5b)1 << Drive_No); } LOCALPROC DiskInsertNotify(tDrive Drive_No, blnr locked) { vSonyInsertedMask |= ((ui5b)1 << Drive_No); if (! locked) { vSonyWritableMask |= ((ui5b)1 << Drive_No); } QuietEnds(); } LOCALPROC DiskEjectedNotify(tDrive Drive_No) { vSonyWritableMask &= ~ ((ui5b)1 << Drive_No); vSonyInsertedMask &= ~ ((ui5b)1 << Drive_No); } /* block type - for operating on multiple ui3b elements at a time. */ #if LittleEndianUnaligned || BigEndianUnaligned #define uibb ui5b #define uibr ui5r #define ln2uiblockn 2 #if 0 #define uibb long long #define uibr long long #define ln2uiblockn 3 #endif #else #define uibb ui3b #define uibr ui3r #define ln2uiblockn 0 #endif #define uiblockn (1 << ln2uiblockn) #define ln2uiblockbitsn (3 + ln2uiblockn) #define uiblockbitsn (8 * uiblockn) LOCALFUNC blnr FindFirstChangeInLVecs(uibb *ptr1, uibb *ptr2, uimr L, uimr *j) { /* find index of first difference */ uibb *p1 = ptr1; uibb *p2 = ptr2; uimr i; for (i = L; i != 0; --i) { if (*p1++ != *p2++) { --p1; *j = p1 - ptr1; return trueblnr; } } return falseblnr; } LOCALPROC FindLastChangeInLVecs(uibb *ptr1, uibb *ptr2, uimr L, uimr *j) { /* find index of last difference, assuming there is one */ uibb *p1 = ptr1 + L; uibb *p2 = ptr2 + L; while (*--p1 == *--p2) { } *j = p1 - ptr1; } LOCALPROC FindLeftRightChangeInLMat(uibb *ptr1, uibb *ptr2, uimr width, uimr top, uimr bottom, uimr *LeftMin0, uibr *LeftMask0, uimr *RightMax0, uibr *RightMask0) { uimr i; uimr j; uibb *p1; uibb *p2; uibr x; ui5r offset = top * width; uibb *p10 = (uibb *)ptr1 + offset; uibb *p20 = (uibb *)ptr2 + offset; uimr LeftMin = *LeftMin0; uimr RightMax = *RightMax0; uibr LeftMask = 0; uibr RightMask = 0; for (i = top; i < bottom; ++i) { p1 = p10; p2 = p20; for (j = 0; j < LeftMin; ++j) { x = *p1++ ^ *p2++; if (0 != x) { LeftMin = j; LeftMask = x; goto Label_3; } } LeftMask |= (*p1 ^ *p2); Label_3: p1 = p10 + RightMax; p2 = p20 + RightMax; RightMask |= (*p1++ ^ *p2++); for (j = RightMax + 1; j < width; ++j) { x = *p1++ ^ *p2++; if (0 != x) { RightMax = j; RightMask = x; } } p10 += width; p20 += width; } *LeftMin0 = LeftMin; *RightMax0 = RightMax; *LeftMask0 = LeftMask; *RightMask0 = RightMask; } LOCALVAR ui3p screencomparebuff = nullpr; LOCALVAR uimr NextDrawRow = 0; #if BigEndianUnaligned #define FlipCheckMonoBits (uiblockbitsn - 1) #else #define FlipCheckMonoBits 7 #endif #define FlipCheckBits (FlipCheckMonoBits >> vMacScreenDepth) #ifndef WantColorTransValid #define WantColorTransValid 0 #endif #if WantColorTransValid LOCALVAR blnr ColorTransValid = falseblnr; #endif LOCALFUNC blnr ScreenFindChanges(ui3p screencurrentbuff, si3b TimeAdjust, si4b *top, si4b *left, si4b *bottom, si4b *right) { uimr j0; uimr j1; uimr j0h; uimr j1h; uimr j0v; uimr j1v; uimr copysize; uimr copyoffset; uimr copyrows; uimr LimitDrawRow; uimr MaxRowsDrawnPerTick; uimr LeftMin; uimr RightMax; uibr LeftMask; uibr RightMask; int j; if (TimeAdjust < 4) { MaxRowsDrawnPerTick = vMacScreenHeight; } else if (TimeAdjust < 6) { MaxRowsDrawnPerTick = vMacScreenHeight / 2; } else { MaxRowsDrawnPerTick = vMacScreenHeight / 4; } #if 0 != vMacScreenDepth if (UseColorMode) { if (ColorMappingChanged) { ColorMappingChanged = falseblnr; j0h = 0; j1h = vMacScreenWidth; j0v = 0; j1v = vMacScreenHeight; #if WantColorTransValid ColorTransValid = falseblnr; #endif } else { if (! FindFirstChangeInLVecs( (uibb *)screencurrentbuff + NextDrawRow * (vMacScreenBitWidth / uiblockbitsn), (uibb *)screencomparebuff + NextDrawRow * (vMacScreenBitWidth / uiblockbitsn), ((uimr)(vMacScreenHeight - NextDrawRow) * (uimr)vMacScreenBitWidth) / uiblockbitsn, &j0)) { NextDrawRow = 0; return falseblnr; } j0v = j0 / (vMacScreenBitWidth / uiblockbitsn); j0h = j0 - j0v * (vMacScreenBitWidth / uiblockbitsn); j0v += NextDrawRow; LimitDrawRow = j0v + MaxRowsDrawnPerTick; if (LimitDrawRow >= vMacScreenHeight) { LimitDrawRow = vMacScreenHeight; NextDrawRow = 0; } else { NextDrawRow = LimitDrawRow; } FindLastChangeInLVecs((uibb *)screencurrentbuff, (uibb *)screencomparebuff, ((uimr)LimitDrawRow * (uimr)vMacScreenBitWidth) / uiblockbitsn, &j1); j1v = j1 / (vMacScreenBitWidth / uiblockbitsn); j1h = j1 - j1v * (vMacScreenBitWidth / uiblockbitsn); j1v++; if (j0h < j1h) { LeftMin = j0h; RightMax = j1h; } else { LeftMin = j1h; RightMax = j0h; } FindLeftRightChangeInLMat((uibb *)screencurrentbuff, (uibb *)screencomparebuff, (vMacScreenBitWidth / uiblockbitsn), j0v, j1v, &LeftMin, &LeftMask, &RightMax, &RightMask); #if vMacScreenDepth > ln2uiblockbitsn j0h = (LeftMin >> (vMacScreenDepth - ln2uiblockbitsn)); #elif ln2uiblockbitsn > vMacScreenDepth for (j = 0; j < (1 << (ln2uiblockbitsn - vMacScreenDepth)); ++j) { if (0 != (LeftMask & (((((uibr)1) << (1 << vMacScreenDepth)) - 1) << ((j ^ FlipCheckBits) << vMacScreenDepth)))) { goto Label_1c; } } Label_1c: j0h = (LeftMin << (ln2uiblockbitsn - vMacScreenDepth)) + j; #else j0h = LeftMin; #endif #if vMacScreenDepth > ln2uiblockbitsn j1h = (RightMax >> (vMacScreenDepth - ln2uiblockbitsn)) + 1; #elif ln2uiblockbitsn > vMacScreenDepth for (j = (uiblockbitsn >> vMacScreenDepth); --j >= 0; ) { if (0 != (RightMask & (((((uibr)1) << (1 << vMacScreenDepth)) - 1) << ((j ^ FlipCheckBits) << vMacScreenDepth)))) { goto Label_2c; } } Label_2c: j1h = (RightMax << (ln2uiblockbitsn - vMacScreenDepth)) + j + 1; #else j1h = RightMax + 1; #endif } copyrows = j1v - j0v; copyoffset = j0v * vMacScreenByteWidth; copysize = copyrows * vMacScreenByteWidth; } else #endif { #if 0 != vMacScreenDepth if (ColorMappingChanged) { ColorMappingChanged = falseblnr; j0h = 0; j1h = vMacScreenWidth; j0v = 0; j1v = vMacScreenHeight; #if WantColorTransValid ColorTransValid = falseblnr; #endif } else #endif { if (! FindFirstChangeInLVecs( (uibb *)screencurrentbuff + NextDrawRow * (vMacScreenWidth / uiblockbitsn), (uibb *)screencomparebuff + NextDrawRow * (vMacScreenWidth / uiblockbitsn), ((uimr)(vMacScreenHeight - NextDrawRow) * (uimr)vMacScreenWidth) / uiblockbitsn, &j0)) { NextDrawRow = 0; return falseblnr; } j0v = j0 / (vMacScreenWidth / uiblockbitsn); j0h = j0 - j0v * (vMacScreenWidth / uiblockbitsn); j0v += NextDrawRow; LimitDrawRow = j0v + MaxRowsDrawnPerTick; if (LimitDrawRow >= vMacScreenHeight) { LimitDrawRow = vMacScreenHeight; NextDrawRow = 0; } else { NextDrawRow = LimitDrawRow; } FindLastChangeInLVecs((uibb *)screencurrentbuff, (uibb *)screencomparebuff, ((uimr)LimitDrawRow * (uimr)vMacScreenWidth) / uiblockbitsn, &j1); j1v = j1 / (vMacScreenWidth / uiblockbitsn); j1h = j1 - j1v * (vMacScreenWidth / uiblockbitsn); j1v++; if (j0h < j1h) { LeftMin = j0h; RightMax = j1h; } else { LeftMin = j1h; RightMax = j0h; } FindLeftRightChangeInLMat((uibb *)screencurrentbuff, (uibb *)screencomparebuff, (vMacScreenWidth / uiblockbitsn), j0v, j1v, &LeftMin, &LeftMask, &RightMax, &RightMask); for (j = 0; j < uiblockbitsn; ++j) { if (0 != (LeftMask & (((uibr)1) << (j ^ FlipCheckMonoBits)))) { goto Label_1; } } Label_1: j0h = LeftMin * uiblockbitsn + j; for (j = uiblockbitsn; --j >= 0; ) { if (0 != (RightMask & (((uibr)1) << (j ^ FlipCheckMonoBits)))) { goto Label_2; } } Label_2: j1h = RightMax * uiblockbitsn + j + 1; } copyrows = j1v - j0v; copyoffset = j0v * vMacScreenMonoByteWidth; copysize = copyrows * vMacScreenMonoByteWidth; } MyMoveBytes((anyp)screencurrentbuff + copyoffset, (anyp)screencomparebuff + copyoffset, copysize); *top = j0v; *left = j0h; *bottom = j1v; *right = j1h; return trueblnr; } GLOBALVAR blnr EmVideoDisable = falseblnr; GLOBALVAR si3b EmLagTime = 0; GLOBALVAR ui5b OnTrueTime = 0; /* The time slice we are currently dealing with, in the same units as TrueEmulatedTime. */ LOCALVAR si4b ScreenChangedTop; LOCALVAR si4b ScreenChangedLeft; LOCALVAR si4b ScreenChangedBottom; LOCALVAR si4b ScreenChangedRight; LOCALPROC ScreenClearChanges(void) { ScreenChangedTop = vMacScreenHeight; ScreenChangedBottom = 0; ScreenChangedLeft = vMacScreenWidth; ScreenChangedRight = 0; } LOCALPROC ScreenChangedAll(void) { ScreenChangedTop = 0; ScreenChangedBottom = vMacScreenHeight; ScreenChangedLeft = 0; ScreenChangedRight = vMacScreenWidth; } #if EnableAutoSlow LOCALVAR si4b ScreenChangedQuietTop = vMacScreenHeight; LOCALVAR si4b ScreenChangedQuietLeft = vMacScreenWidth; LOCALVAR si4b ScreenChangedQuietBottom = 0; LOCALVAR si4b ScreenChangedQuietRight = 0; #endif GLOBALOSGLUPROC Screen_OutputFrame(ui3p screencurrentbuff) { si4b top; si4b left; si4b bottom; si4b right; if (! EmVideoDisable) { if (ScreenFindChanges(screencurrentbuff, EmLagTime, &top, &left, &bottom, &right)) { if (top < ScreenChangedTop) { ScreenChangedTop = top; } if (bottom > ScreenChangedBottom) { ScreenChangedBottom = bottom; } if (left < ScreenChangedLeft) { ScreenChangedLeft = left; } if (right > ScreenChangedRight) { ScreenChangedRight = right; } #if EnableAutoSlow if (top < ScreenChangedQuietTop) { ScreenChangedQuietTop = top; } if (bottom > ScreenChangedQuietBottom) { ScreenChangedQuietBottom = bottom; } if (left < ScreenChangedQuietLeft) { ScreenChangedQuietLeft = left; } if (right > ScreenChangedQuietRight) { ScreenChangedQuietRight = right; } if (((ScreenChangedQuietRight - ScreenChangedQuietLeft) > 1) || ((ScreenChangedQuietBottom - ScreenChangedQuietTop) > 32)) { ScreenChangedQuietTop = vMacScreenHeight; ScreenChangedQuietLeft = vMacScreenWidth; ScreenChangedQuietBottom = 0; ScreenChangedQuietRight = 0; QuietEnds(); } #endif } } } #if MayFullScreen LOCALVAR ui4r ViewHSize; LOCALVAR ui4r ViewVSize; LOCALVAR ui4r ViewHStart = 0; LOCALVAR ui4r ViewVStart = 0; #if EnableFSMouseMotion LOCALVAR si4b SavedMouseH; LOCALVAR si4b SavedMouseV; #endif #endif #ifndef WantAutoScrollBorder #define WantAutoScrollBorder 0 #endif #if EnableFSMouseMotion LOCALPROC AutoScrollScreen(void) { si4b Shift; si4b Limit; /* Scroll in multiples of two pixels, so as to work better with the common gray pattern. ViewHSize and ViewVSize are constrained to a multiple of two. Mac OS (some versions at least) constrains the mouse position to be less than the screen height and width, not allowing equal to it. Can still scroll to see last pixel because scroll in multiples of two pixels. */ if (vMacScreenWidth != ViewHSize) { Shift = 0; Limit = ViewHStart #if WantAutoScrollBorder + (ViewHSize / 16) #endif ; if (CurMouseH < Limit) { Shift = (Limit - CurMouseH + 1) & (~ 1); Limit = ViewHStart; if (Shift >= Limit) { Shift = Limit; } Shift = - Shift; } else { Limit = ViewHStart + ViewHSize #if WantAutoScrollBorder - (ViewHSize / 16) #endif ; if (CurMouseH > Limit) { Shift = (CurMouseH - Limit + 1) & (~ 1); Limit = vMacScreenWidth - ViewHSize - ViewHStart; if (Shift >= Limit) { Shift = Limit; } } } if (Shift != 0) { ViewHStart += Shift; SavedMouseH += Shift; ScreenChangedAll(); } } if (vMacScreenHeight != ViewVSize) { Shift = 0; Limit = ViewVStart #if WantAutoScrollBorder + (ViewVSize / 16) #endif ; if (CurMouseV < Limit) { Shift = (Limit - CurMouseV + 1) & (~ 1); Limit = ViewVStart; if (Shift >= Limit) { Shift = Limit; } Shift = - Shift; } else { Limit = ViewVStart + ViewVSize #if WantAutoScrollBorder - (ViewVSize / 16) #endif ; if (CurMouseV > Limit) { Shift = (CurMouseV - Limit + 1) & (~ 1); Limit = vMacScreenHeight - ViewVSize - ViewVStart; if (Shift >= Limit) { Shift = Limit; } } } if (Shift != 0) { ViewVStart += Shift; SavedMouseV += Shift; ScreenChangedAll(); } } } #endif LOCALPROC SetLongs(ui5b *p, long n) { long i; for (i = n; --i >= 0; ) { *p++ = (ui5b) -1; } } LOCALVAR uimr ReserveAllocOffset; LOCALVAR ui3p ReserveAllocBigBlock = nullpr; #define PowOf2(p) ((uimr)1 << (p)) #define Pow2Mask(p) (PowOf2(p) - 1) #define ModPow2(i, p) ((i) & Pow2Mask(p)) #define FloorDivPow2(i, p) ((i) >> (p)) #define FloorPow2Mult(i, p) ((i) & (~ Pow2Mask(p))) #define CeilPow2Mult(i, p) FloorPow2Mult((i) + Pow2Mask(p), (p)) /* warning - CeilPow2Mult evaluates p twice */ GLOBALOSGLUPROC ReserveAllocOneBlock(ui3p *p, uimr n, ui3r align, blnr FillOnes) { ReserveAllocOffset = CeilPow2Mult(ReserveAllocOffset, align); if (nullpr == ReserveAllocBigBlock) { *p = nullpr; } else { *p = ReserveAllocBigBlock + ReserveAllocOffset; if (FillOnes) { SetLongs((ui5b *)*p, n / 4); } } ReserveAllocOffset += n; } /* --- sending debugging info to file --- */ #if dbglog_HAVE #define dbglog_bufsz PowOf2(dbglog_buflnsz) LOCALVAR uimr dbglog_bufpos = 0; LOCALVAR char *dbglog_bufp = nullpr; LOCALPROC dbglog_ReserveAlloc(void) { ReserveAllocOneBlock((ui3p *)&dbglog_bufp, dbglog_bufsz, 5, falseblnr); } #define dbglog_open dbglog_open0 LOCALPROC dbglog_close(void) { uimr n = ModPow2(dbglog_bufpos, dbglog_buflnsz); if (n != 0) { dbglog_write0(dbglog_bufp, n); } dbglog_close0(); } LOCALPROC dbglog_write(char *p, uimr L) { uimr r; uimr bufposmod; uimr curbufdiv; uimr newbufpos = dbglog_bufpos + L; uimr newbufdiv = FloorDivPow2(newbufpos, dbglog_buflnsz); label_retry: curbufdiv = FloorDivPow2(dbglog_bufpos, dbglog_buflnsz); bufposmod = ModPow2(dbglog_bufpos, dbglog_buflnsz); if (newbufdiv != curbufdiv) { r = dbglog_bufsz - bufposmod; MyMoveBytes((anyp)p, (anyp)(dbglog_bufp + bufposmod), r); dbglog_write0(dbglog_bufp, dbglog_bufsz); L -= r; p += r; dbglog_bufpos += r; goto label_retry; } MyMoveBytes((anyp)p, (anyp)dbglog_bufp + bufposmod, L); dbglog_bufpos = newbufpos; } LOCALFUNC uimr CStrLength(char *s) { char *p = s; while (*p++ != 0) { } return p - s - 1; } GLOBALOSGLUPROC dbglog_writeCStr(char *s) { /* fprintf(DumpFile, "%s", s); */ dbglog_write(s, CStrLength(s)); } GLOBALOSGLUPROC dbglog_writeReturn(void) { dbglog_writeCStr("\n"); /* fprintf(DumpFile, "\n"); */ } GLOBALOSGLUPROC dbglog_writeHex(uimr x) { ui3r v; char s[16]; char *p = s + 16; uimr n = 0; do { v = x & 0x0F; if (v < 10) { *--p = '0' + v; } else { *--p = 'A' + v - 10; } x >>= 4; ++n; } while (x != 0); dbglog_write(p, n); /* fprintf(DumpFile, "%d", (int)x); */ } GLOBALOSGLUPROC dbglog_writeNum(uimr x) { uimr newx; char s[16]; char *p = s + 16; uimr n = 0; do { newx = x / (uimr)10; *--p = '0' + (x - newx * 10); x = newx; ++n; } while (x != 0); dbglog_write(p, n); /* fprintf(DumpFile, "%d", (int)x); */ } GLOBALOSGLUPROC dbglog_writeMacChar(ui3r x) { char s; if ((x > 32) && (x < 127)) { s = x; } else { s = '?'; } dbglog_write(&s, 1); } LOCALPROC dbglog_writeSpace(void) { dbglog_writeCStr(" "); } GLOBALOSGLUPROC dbglog_writeln(char *s) { dbglog_writeCStr(s); dbglog_writeReturn(); } GLOBALOSGLUPROC dbglog_writelnNum(char *s, simr v) { dbglog_writeCStr(s); dbglog_writeSpace(); dbglog_writeNum(v); dbglog_writeReturn(); } #endif /* my event queue */ #define MyEvtQLg2Sz 4 #define MyEvtQSz (1 << MyEvtQLg2Sz) #define MyEvtQIMask (MyEvtQSz - 1) LOCALVAR MyEvtQEl MyEvtQA[MyEvtQSz]; LOCALVAR ui4r MyEvtQIn = 0; LOCALVAR ui4r MyEvtQOut = 0; GLOBALOSGLUFUNC MyEvtQEl * MyEvtQOutP(void) { MyEvtQEl *p = nullpr; if (MyEvtQIn != MyEvtQOut) { p = &MyEvtQA[MyEvtQOut & MyEvtQIMask]; } return p; } GLOBALOSGLUPROC MyEvtQOutDone(void) { ++MyEvtQOut; } LOCALVAR blnr MyEvtQNeedRecover = falseblnr; /* events lost because of full queue */ LOCALFUNC MyEvtQEl * MyEvtQElPreviousIn(void) { MyEvtQEl *p = NULL; if (MyEvtQIn - MyEvtQOut != 0) { p = &MyEvtQA[(MyEvtQIn - 1) & MyEvtQIMask]; } return p; } LOCALFUNC MyEvtQEl * MyEvtQElAlloc(void) { MyEvtQEl *p = NULL; if (MyEvtQIn - MyEvtQOut >= MyEvtQSz) { MyEvtQNeedRecover = trueblnr; } else { p = &MyEvtQA[MyEvtQIn & MyEvtQIMask]; ++MyEvtQIn; } return p; } LOCALVAR ui5b theKeys[4]; LOCALPROC Keyboard_UpdateKeyMap(int key, blnr down) { int k = key & 127; /* just for safety */ int bit = 1 << (k & 7); ui3b *kp = (ui3b *)theKeys; ui3b *kpi = &kp[k / 8]; blnr CurDown = ((*kpi & bit) != 0); if (CurDown != down) { MyEvtQEl *p = MyEvtQElAlloc(); if (NULL != p) { p->kind = MyEvtQElKindKey; p->u.press.key = k; p->u.press.down = down; if (down) { *kpi |= bit; } else { *kpi &= ~ bit; } } QuietEnds(); } } LOCALVAR blnr MyMouseButtonState = falseblnr; LOCALPROC MyMouseButtonSet(blnr down) { if (MyMouseButtonState != down) { MyEvtQEl *p = MyEvtQElAlloc(); if (NULL != p) { p->kind = MyEvtQElKindMouseButton; p->u.press.down = down; MyMouseButtonState = down; } QuietEnds(); } } #if EnableFSMouseMotion LOCALPROC MyMousePositionSetDelta(ui4r dh, ui4r dv) { if ((dh != 0) || (dv != 0)) { MyEvtQEl *p = MyEvtQElPreviousIn(); if ((NULL != p) && (MyEvtQElKindMouseDelta == p->kind)) { p->u.pos.h += dh; p->u.pos.v += dv; } else { p = MyEvtQElAlloc(); if (NULL != p) { p->kind = MyEvtQElKindMouseDelta; p->u.pos.h = dh; p->u.pos.v = dv; } } QuietEnds(); } } #endif LOCALVAR ui4b MyMousePosCurV = 0; LOCALVAR ui4b MyMousePosCurH = 0; LOCALPROC MyMousePositionSet(ui4r h, ui4r v) { if ((h != MyMousePosCurH) || (v != MyMousePosCurV)) { MyEvtQEl *p = MyEvtQElPreviousIn(); if ((NULL == p) || (MyEvtQElKindMousePos != p->kind)) { p = MyEvtQElAlloc(); } if (NULL != p) { p->kind = MyEvtQElKindMousePos; p->u.pos.h = h; p->u.pos.v = v; MyMousePosCurH = h; MyMousePosCurV = v; } QuietEnds(); } } #if 0 #define Keyboard_TestKeyMap(key) \ ((((ui3b *)theKeys)[(key) / 8] & (1 << ((key) & 7))) != 0) #endif LOCALPROC InitKeyCodes(void) { theKeys[0] = 0; theKeys[1] = 0; theKeys[2] = 0; theKeys[3] = 0; } #define kKeepMaskControl (1 << 0) #define kKeepMaskCapsLock (1 << 1) #define kKeepMaskCommand (1 << 2) #define kKeepMaskOption (1 << 3) #define kKeepMaskShift (1 << 4) LOCALPROC DisconnectKeyCodes(ui5b KeepMask) { /* Called when may miss key ups, so act is if all pressed keys have been released, except maybe for control, caps lock, command, option and shift. */ int j; int b; int key; ui5b m; for (j = 0; j < 16; ++j) { ui3b k1 = ((ui3b *)theKeys)[j]; if (0 != k1) { ui3b bit = 1; for (b = 0; b < 8; ++b) { if (0 != (k1 & bit)) { key = j * 8 + b; switch (key) { case MKC_Control: m = kKeepMaskControl; break; case MKC_CapsLock: m = kKeepMaskCapsLock; break; case MKC_Command: m = kKeepMaskCommand; break; case MKC_Option: m = kKeepMaskOption; break; case MKC_Shift: m = kKeepMaskShift; break; default: m = 0; break; } if (0 == (KeepMask & m)) { Keyboard_UpdateKeyMap(key, falseblnr); } } bit <<= 1; } } } } LOCALPROC MyEvtQTryRecoverFromFull(void) { MyMouseButtonSet(falseblnr); DisconnectKeyCodes(0); } /* MacMsg */ LOCALVAR char *SavedBriefMsg = nullpr; LOCALVAR char *SavedLongMsg; LOCALVAR ui4r SavedIDMsg = 0; LOCALVAR blnr SavedFatalMsg; LOCALPROC MacMsg(char *briefMsg, char *longMsg, blnr fatal) { if (nullpr != SavedBriefMsg) { /* ignore the new message, only display the first error. */ } else { SavedBriefMsg = briefMsg; SavedLongMsg = longMsg; SavedFatalMsg = fatal; } } GLOBALOSGLUPROC WarnMsgCorruptedROM(void) { MacMsg(kStrCorruptedROMTitle, kStrCorruptedROMMessage, falseblnr); } GLOBALOSGLUPROC WarnMsgUnsupportedROM(void) { MacMsg(kStrUnsupportedROMTitle, kStrUnsupportedROMMessage, falseblnr); } GLOBALOSGLUPROC WarnMsgAbnormalID(ui4r id) { MacMsg(kStrReportAbnormalTitle, kStrReportAbnormalMessage, falseblnr); if (0 != SavedIDMsg) { /* ignore the new message, only display the first error. */ } else { SavedIDMsg = id; } } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/CONTROLM.h b/Mini vMac/mnvm_core/CONTROLM.h index 118b296..b3677ba 100755 --- a/Mini vMac/mnvm_core/CONTROLM.h +++ b/Mini vMac/mnvm_core/CONTROLM.h @@ -1,1034 +1 @@ -/* - CONTROLM.h - - Copyright (C) 2007 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - CONTROL Mode -*/ - -#ifdef CONTROLM_H -#error "header already included" -#else -#define CONTROLM_H -#endif - -enum { -#if EnableDemoMsg - SpclModeDemo, -#endif -#if EnableAltKeysMode - SpclModeAltKeyText, -#endif -#if UseActvCode - SpclModeActvCode, -#endif - SpclModeMessage, -#if UseControlKeys - SpclModeControl, -#endif - - kNumSpclModes -}; - -LOCALVAR uimr SpecialModes = 0; - -LOCALVAR blnr NeedWholeScreenDraw = falseblnr; - -#define SpecialModeSet(i) SpecialModes |= (1 << (i)) -#define SpecialModeClr(i) SpecialModes &= ~ (1 << (i)) -#define SpecialModeTst(i) (0 != (SpecialModes & (1 << (i)))) - -#define MacMsgDisplayed SpecialModeTst(SpclModeMessage) - -LOCALVAR ui3p CntrlDisplayBuff = nullpr; - -LOCALPROC DrawCell(unsigned int h, unsigned int v, int x) -{ -#if 1 - /* safety check */ - if ((h < ((long)vMacScreenWidth / 8 - 2)) - && (v < (vMacScreenHeight / 16 - 1))) -#endif - { - int i; - ui3p p0 = ((ui3p)CellData) + 16 * x; - -#if 0 != vMacScreenDepth - if (UseColorMode) { - ui3p p = CntrlDisplayBuff - + ((h + 1) << vMacScreenDepth) - + (v * 16 + 11) * vMacScreenByteWidth; - - for (i = 16; --i >= 0; ) { -#if 1 == vMacScreenDepth - int k; - ui3b t0 = *p0; - ui3p p2 = p; - for (k = 2; --k >= 0; ) { - *p2++ = (((t0) & 0x80) ? 0xC0 : 0x00) - | (((t0) & 0x40) ? 0x30 : 0x00) - | (((t0) & 0x20) ? 0x0C : 0x00) - | (((t0) & 0x10) ? 0x03 : 0x00); - /* black RRGGBBAA, white RRGGBBAA */ - t0 <<= 4; - } -#elif 2 == vMacScreenDepth - int k; - ui3b t0 = *p0; - ui3p p2 = p; - for (k = 4; --k >= 0; ) { - *p2++ = (((t0) & 0x40) ? 0x0F : 0x00) - | (((t0) & 0x80) ? 0xF0 : 0x00); - /* black RRGGBBAA, white RRGGBBAA */ - t0 <<= 2; - } -#elif 3 == vMacScreenDepth - int k; - ui3b t0 = *p0; - ui3p p2 = p; - for (k = 8; --k >= 0; ) { - *p2++ = ((t0 >> k) & 0x01) ? 0xFF : 0x00; - /* black RRGGBBAA, white RRGGBBAA */ - } -#elif 4 == vMacScreenDepth - int k; - ui4r v; - ui3b t0 = *p0; - ui3p p2 = p; - for (k = 8; --k >= 0; ) { - v = ((t0 >> k) & 0x01) ? 0x0000 : 0x7FFF; - /* black RRGGBBAA, white RRGGBBAA */ - /* *((ui4b *)p2)++ = v; need big endian, so : */ - *p2++ = v >> 8; - *p2++ = v; - } -#elif 5 == vMacScreenDepth - int k; - ui5r v; - ui3b t0 = *p0; - ui3p p2 = p; - for (k = 8; --k >= 0; ) { - v = ((t0 >> k) & 0x01) ? 0x00000000 : 0x00FFFFFF; - /* black RRGGBBAA, white RRGGBBAA */ - /* *((ui5b *)p2)++ = v; need big endian, so : */ - *p2++ = v >> 24; - *p2++ = v >> 16; - *p2++ = v >> 8; - *p2++ = v; - } -#endif - p += vMacScreenByteWidth; - p0 ++; - } - } else -#endif - { - ui3p p = CntrlDisplayBuff + (h + 1) - + (v * 16 + 11) * vMacScreenMonoByteWidth; - - for (i = 16; --i >= 0; ) { - *p = *p0; - p += vMacScreenMonoByteWidth; - p0 ++; - } - } - } -} - -#define ControlBoxh0 0 -#define ControlBoxw 62 -#define ControlBoxv0 0 - -#define hLimit (ControlBoxh0 + ControlBoxw - 1) -#define hStart (ControlBoxh0 + 1) - - -LOCALVAR int CurCellh0; -LOCALVAR int CurCellv0; - -LOCALPROC DrawCellsBeginLine(void) -{ - DrawCell(ControlBoxh0, CurCellv0, kCellMiddleLeft); - CurCellh0 = hStart; -} - -LOCALPROC DrawCellsEndLine(void) -{ - int i; - - for (i = CurCellh0; i < hLimit; ++i) { - DrawCell(i, CurCellv0, kCellSpace); - } - DrawCell(hLimit, CurCellv0, kCellMiddleRight); - CurCellv0++; -} - -LOCALPROC DrawCellsBottomLine(void) -{ - int i; - - DrawCell(ControlBoxh0 + 0, CurCellv0, kCellLowerLeft); - for (i = hStart; i < hLimit; ++i) { - DrawCell(i, CurCellv0, kCellLowerMiddle); - } - DrawCell(hLimit, CurCellv0, kCellLowerRight); -} - -LOCALPROC DrawCellAdvance(int x) -{ - DrawCell(CurCellh0, CurCellv0, x); - CurCellh0++; -} - -LOCALPROC DrawCellsBlankLine(void) -{ - DrawCellsBeginLine(); - DrawCellsEndLine(); -} - -LOCALPROC DrawCellsFromStr(char *s) -{ - ui3b ps[ClStrMaxLength]; - ui3b cs; - int L; - int i; - int j; - int w; - - ClStrFromSubstCStr(&L, ps, s); - - i = 0; - - while (i < L) { - cs = ps[i]; - i++; - if (CurCellh0 < hLimit) { - DrawCellAdvance(cs); - } else { - /* line is too wide, wrap */ - if (kCellSpace != cs) { - --i; /* back up one char, at least */ - - /* now try backing up to beginning of word */ - j = i; - w = CurCellh0 - hStart; - - while ((w > 0) && (j > 0) - && (ps[j - 1] != kCellSpace)) - { - --j; - --w; - } - if (w != 0) { - i = j; - CurCellh0 = hStart + w; - } - /* - else if w == 0, then have backed up to - beginning of line, so just let the word - be split. - */ - } - /* - else if cs == kCellSpace, just lose the space. - */ - DrawCellsEndLine(); - /* - draw white space over the part of - the word that have already drawn - */ - DrawCellsBeginLine(); - } - } -} - -LOCALPROC DrawCellsOneLineStr(char *s) -{ - DrawCellsBeginLine(); - DrawCellsFromStr(s); - DrawCellsEndLine(); -} - -LOCALPROC DrawCellsKeyCommand(char *k, char *s) -{ - DrawCellsBeginLine(); - DrawCellsFromStr("'"); - DrawCellsFromStr(k); - DrawCellsFromStr("' - "); - DrawCellsFromStr(s); - DrawCellsEndLine(); -} - -typedef void (*SpclModeBody) (void); - -LOCALPROC DrawSpclMode0(char *Title, SpclModeBody Body) -{ - int i; - int k; - - CurCellv0 = ControlBoxv0 + 0; - DrawCell(ControlBoxh0 + 0, CurCellv0, kCellUpperLeft); - k = kCellIcon00; - for (i = hStart; i < hStart + 4; ++i) { - DrawCell(i, CurCellv0, k); - k++; - } - for (i = hStart + 4; i < hLimit; ++i) { - DrawCell(i, CurCellv0, kCellUpperMiddle); - } - DrawCell(hLimit, CurCellv0, kCellUpperRight); - ++CurCellv0; - - DrawCellsBeginLine(); - for (i = hStart; i < hStart + 4; ++i) { - DrawCellAdvance(k); - k++; - } - DrawCellAdvance(kCellSpace); - DrawCellsFromStr(Title); - DrawCellsEndLine(); - - DrawCellsBeginLine(); - for (i = hStart; i < hStart + 4; ++i) { - DrawCellAdvance(k); - k++; - } - for (i = hStart + 4; i < hLimit; ++i) { - DrawCellAdvance(kCellGraySep); - } - DrawCellsEndLine(); - - if (nullpr != Body) { - Body(); - } - - DrawCellsBottomLine(); -} - -#if EnableAltKeysMode -#include "ALTKEYSM.h" -#else -#define Keyboard_UpdateKeyMap1 Keyboard_UpdateKeyMap -#define DisconnectKeyCodes1 DisconnectKeyCodes -#endif - -LOCALPROC DrawCellsMessageModeBody(void) -{ - DrawCellsOneLineStr(SavedBriefMsg); - DrawCellsBlankLine(); - DrawCellsOneLineStr(SavedLongMsg); -} - -LOCALPROC DrawMessageMode(void) -{ - DrawSpclMode0(kStrModeMessage, DrawCellsMessageModeBody); -} - -LOCALPROC MacMsgDisplayOff(void) -{ - SpecialModeClr(SpclModeMessage); - SavedBriefMsg = nullpr; - NeedWholeScreenDraw = trueblnr; -} - -LOCALPROC MacMsgDisplayOn(void) -{ - NeedWholeScreenDraw = trueblnr; - DisconnectKeyCodes1(kKeepMaskControl | kKeepMaskCapsLock); - /* command */ - SpecialModeSet(SpclModeMessage); -} - -LOCALPROC DoMessageModeKey(int key) -{ - if (MKC_C == key) { - MacMsgDisplayOff(); - } -} - -LOCALPROC MacMsgOverride(char *briefMsg, char *longMsg) -{ - if (MacMsgDisplayed) { - MacMsgDisplayOff(); - } - MacMsg(briefMsg, longMsg, falseblnr); -} - -#if NeedDoMoreCommandsMsg -LOCALPROC DoMoreCommandsMsg(void) -{ - MacMsgOverride(kStrMoreCommandsTitle, - kStrMoreCommandsMessage); -} -#endif - -#if NeedDoAboutMsg -LOCALPROC DoAboutMsg(void) -{ - MacMsgOverride(kStrAboutTitle, - kStrAboutMessage); -} -#endif - -#if UseControlKeys - -LOCALVAR blnr LastControlKey = falseblnr; -LOCALVAR int CurControlMode = 0; -LOCALVAR int ControlMessage = 0; - -enum { - kCntrlModeOff, - kCntrlModeBase, - kCntrlModeConfirmReset, - kCntrlModeConfirmInterrupt, - kCntrlModeConfirmQuit, - kCntrlModeSpeedControl, - - kNumCntrlModes -}; - -enum { - kCntrlMsgBaseStart, -#if EnableMagnify - kCntrlMsgMagnify, -#endif -#if VarFullScreen - kCntrlMsgFullScreen, -#endif - kCntrlMsgConfirmResetStart, - kCntrlMsgHaveReset, - kCntrlMsgResetCancelled, - kCntrlMsgConfirmInterruptStart, - kCntrlMsgHaveInterrupted, - kCntrlMsgInterruptCancelled, - kCntrlMsgConfirmQuitStart, - kCntrlMsgQuitCancelled, - kCntrlMsgEmCntrl, - kCntrlMsgSpeedControlStart, - kCntrlMsgNewSpeed, - kCntrlMsgNewStopped, - kCntrlMsgNewRunInBack, -#if EnableAutoSlow - kCntrlMsgNewAutoSlow, -#endif - kCntrlMsgAbout, - kCntrlMsgHelp, -#if UseActvCode || EnableDemoMsg - kCntrlMsgRegStrCopied, -#endif - - kNumCntrlMsgs -}; - -LOCALPROC DoEnterControlMode(void) -{ - CurControlMode = kCntrlModeBase; - ControlMessage = kCntrlMsgBaseStart; - NeedWholeScreenDraw = trueblnr; - DisconnectKeyCodes1(kKeepMaskControl | kKeepMaskCapsLock); - SpecialModeSet(SpclModeControl); -} - -LOCALPROC DoLeaveControlMode(void) -{ - SpecialModeClr(SpclModeControl); - CurControlMode = kCntrlModeOff; - NeedWholeScreenDraw = trueblnr; -} - -LOCALPROC Keyboard_UpdateControlKey(blnr down) -{ - if (down != LastControlKey) { - LastControlKey = down; - if (down) { - DoEnterControlMode(); - } else { - DoLeaveControlMode(); - } - } -} - -LOCALPROC SetSpeedValue(ui3b i) -{ - SpeedValue = i; - CurControlMode = kCntrlModeBase; - ControlMessage = kCntrlMsgNewSpeed; -} - -#if VarFullScreen -FORWARDPROC ToggleWantFullScreen(void); -#endif -#if UseActvCode -FORWARDPROC CopyRegistrationStr(void); -#elif EnableDemoMsg -LOCALPROC CopyRegistrationStr(void) -{ - ui3b ps[ClStrMaxLength]; - int i; - int L; - tPbuf j; - - ClStrFromSubstCStr(&L, ps, "^v"); - - for (i = 0; i < L; ++i) { - ps[i] = Cell2MacAsciiMap[ps[i]]; - } - - if (mnvm_noErr == PbufNew(L, &j)) { - PbufTransfer(ps, j, 0, L, trueblnr); - HTCEexport(j); - } -} -#endif - -LOCALPROC DoControlModeKey(int key) -{ - switch (CurControlMode) { - case kCntrlModeBase: - switch (key) { - case MKC_K: - ControlKeyPressed = ! ControlKeyPressed; - ControlMessage = kCntrlMsgEmCntrl; - Keyboard_UpdateKeyMap1(MKC_Control, - ControlKeyPressed); - break; - case MKC_S: - CurControlMode = kCntrlModeSpeedControl; - ControlMessage = kCntrlMsgSpeedControlStart; - break; - case MKC_I: - CurControlMode = kCntrlModeConfirmInterrupt; - ControlMessage = kCntrlMsgConfirmInterruptStart; - break; - case MKC_R: - if (! AnyDiskInserted()) { - WantMacReset = trueblnr; - ControlMessage = kCntrlMsgHaveReset; - } else { - CurControlMode = kCntrlModeConfirmReset; - ControlMessage = kCntrlMsgConfirmResetStart; - } - break; - case MKC_Q: - if (! AnyDiskInserted()) { - ForceMacOff = trueblnr; - } else { - CurControlMode = kCntrlModeConfirmQuit; - ControlMessage = kCntrlMsgConfirmQuitStart; - } - break; - case MKC_A: - ControlMessage = kCntrlMsgAbout; - break; - case MKC_H: - ControlMessage = kCntrlMsgHelp; - break; -#if NeedRequestInsertDisk - case MKC_O: - RequestInsertDisk = trueblnr; - break; -#endif -#if EnableMagnify - case MKC_M: - WantMagnify = ! WantMagnify; - ControlMessage = kCntrlMsgMagnify; - break; -#endif -#if VarFullScreen - case MKC_F: - ToggleWantFullScreen(); - ControlMessage = kCntrlMsgFullScreen; - break; -#endif -#if UseActvCode || EnableDemoMsg - case MKC_P: - CopyRegistrationStr(); - ControlMessage = kCntrlMsgRegStrCopied; - break; -#endif - } - break; - case kCntrlModeConfirmReset: - switch (key) { - case MKC_Y: - WantMacReset = trueblnr; - CurControlMode = kCntrlModeBase; - ControlMessage = kCntrlMsgHaveReset; - break; - case MKC_R: - /* ignore, in case of repeat */ - break; - case MKC_N: - default: - CurControlMode = kCntrlModeBase; - ControlMessage = kCntrlMsgResetCancelled; - break; - } - break; - case kCntrlModeConfirmInterrupt: - switch (key) { - case MKC_Y: - WantMacInterrupt = trueblnr; - CurControlMode = kCntrlModeBase; - ControlMessage = kCntrlMsgHaveInterrupted; - break; - case MKC_I: - /* ignore, in case of repeat */ - break; - case MKC_N: - default: - CurControlMode = kCntrlModeBase; - ControlMessage = kCntrlMsgInterruptCancelled; - break; - } - break; - case kCntrlModeConfirmQuit: - switch (key) { - case MKC_Y: - ForceMacOff = trueblnr; - CurControlMode = kCntrlModeBase; - ControlMessage = kCntrlMsgBaseStart; - /* shouldn't see this message since quitting */ - break; - case MKC_Q: - /* ignore, in case of repeat */ - break; - case MKC_N: - default: - CurControlMode = kCntrlModeBase; - ControlMessage = kCntrlMsgQuitCancelled; - break; - } - break; - case kCntrlModeSpeedControl: - switch (key) { - case MKC_E: - CurControlMode = kCntrlModeBase; - ControlMessage = kCntrlMsgBaseStart; - break; - case MKC_B: - RunInBackground = ! RunInBackground; - CurControlMode = kCntrlModeBase; - ControlMessage = kCntrlMsgNewRunInBack; - break; - case MKC_D: - SpeedStopped = ! SpeedStopped; - CurControlMode = kCntrlModeBase; - ControlMessage = kCntrlMsgNewStopped; - break; -#if EnableAutoSlow - case MKC_W: - WantNotAutoSlow = ! WantNotAutoSlow; - CurControlMode = kCntrlModeBase; - ControlMessage = kCntrlMsgNewAutoSlow; - break; -#endif - case MKC_Z: - SetSpeedValue(0); - break; - case MKC_1: - SetSpeedValue(1); - break; - case MKC_2: - SetSpeedValue(2); - break; - case MKC_3: - SetSpeedValue(3); - break; - case MKC_4: - SetSpeedValue(4); - break; - case MKC_5: - SetSpeedValue(5); - break; - case MKC_A: - SetSpeedValue((ui3b) -1); - break; - } - break; - } - NeedWholeScreenDraw = trueblnr; -} - -LOCALFUNC char * ControlMode2TitleStr(void) -{ - char *s; - - switch (CurControlMode) { - case kCntrlModeConfirmReset: - s = kStrModeConfirmReset; - break; - case kCntrlModeConfirmInterrupt: - s = kStrModeConfirmInterrupt; - break; - case kCntrlModeConfirmQuit: - s = kStrModeConfirmQuit; - break; - case kCntrlModeSpeedControl: - s = kStrModeSpeedControl; - break; - case kCntrlModeBase: - default: - if (kCntrlMsgHelp == ControlMessage) { - s = kStrModeControlHelp; - } else { - s = kStrModeControlBase; - } - break; - } - - return s; -} - -LOCALPROC DrawCellsControlModeBody(void) -{ - switch (ControlMessage) { - case kCntrlMsgAbout: -#ifndef kStrSponsorName - DrawCellsOneLineStr(kStrProgramInfo); -#else - DrawCellsOneLineStr(kStrSponsorIs); - DrawCellsOneLineStr(kStrSponsorName); -#endif - - DrawCellsBlankLine(); - - DrawCellsOneLineStr(kStrWorkOfMany); - DrawCellsOneLineStr(kMaintainerName); - DrawCellsOneLineStr(kStrForMoreInfo); - DrawCellsOneLineStr("^w"); - - DrawCellsBlankLine(); - - DrawCellsBeginLine(); - DrawCellsFromStr(kStrLicense); - DrawCellsFromStr(kStrDisclaimer); - DrawCellsEndLine(); - - break; - - case kCntrlMsgHelp: - DrawCellsOneLineStr(kStrHowToLeaveControl); - DrawCellsOneLineStr(kStrHowToPickACommand); - DrawCellsBlankLine(); - DrawCellsKeyCommand("A", kStrCmdAbout); -#if NeedRequestInsertDisk - DrawCellsKeyCommand("O", kStrCmdOpenDiskImage); -#endif - DrawCellsKeyCommand("Q", kStrCmdQuit); - DrawCellsKeyCommand("S", kStrCmdSpeedControl); -#if EnableMagnify - DrawCellsKeyCommand("M", kStrCmdMagnifyToggle); -#endif -#if VarFullScreen - DrawCellsKeyCommand("F", kStrCmdFullScrnToggle); -#endif - DrawCellsKeyCommand("K", kStrCmdCtrlKeyToggle); - DrawCellsKeyCommand("R", kStrCmdReset); - DrawCellsKeyCommand("I", kStrCmdInterrupt); - DrawCellsKeyCommand("H", kStrCmdHelp); - break; - case kCntrlMsgSpeedControlStart: - DrawCellsOneLineStr(kStrCurrentSpeed); - DrawCellsKeyCommand("Z", "1x"); - DrawCellsKeyCommand("1", "2x"); - DrawCellsKeyCommand("2", "4x"); - DrawCellsKeyCommand("3", "8x"); - DrawCellsKeyCommand("4", "16x"); - DrawCellsKeyCommand("5", "32x"); - DrawCellsKeyCommand("A", kStrSpeedAllOut); - DrawCellsBlankLine(); - DrawCellsKeyCommand("D", kStrSpeedStopped); - DrawCellsKeyCommand("B", kStrSpeedBackToggle); -#if EnableAutoSlow - DrawCellsKeyCommand("W", kStrSpeedAutoSlowToggle); -#endif - DrawCellsBlankLine(); - DrawCellsKeyCommand("E", kStrSpeedExit); - break; - case kCntrlMsgNewSpeed: - DrawCellsOneLineStr(kStrNewSpeed); - break; - case kCntrlMsgNewRunInBack: - DrawCellsOneLineStr(kStrNewRunInBack); - break; - case kCntrlMsgNewStopped: - DrawCellsOneLineStr(kStrNewStopped); - break; -#if EnableAutoSlow - case kCntrlMsgNewAutoSlow: - DrawCellsOneLineStr(kStrNewAutoSlow); - break; -#endif -#if EnableMagnify - case kCntrlMsgMagnify: - DrawCellsOneLineStr(kStrNewMagnify); - break; -#endif -#if VarFullScreen - case kCntrlMsgFullScreen: - DrawCellsOneLineStr(kStrNewFullScreen); - break; -#endif -#if UseActvCode - case kCntrlMsgRegStrCopied: - DrawCellsOneLineStr("Registration String copied."); - break; -#elif EnableDemoMsg - case kCntrlMsgRegStrCopied: - DrawCellsOneLineStr("Variation name copied."); - break; -#endif - case kCntrlMsgConfirmResetStart: - DrawCellsOneLineStr(kStrConfirmReset); - DrawCellsBlankLine(); - DrawCellsKeyCommand("Y", kStrResetDo); - DrawCellsKeyCommand("N", kStrResetNo); - break; - case kCntrlMsgHaveReset: - DrawCellsOneLineStr(kStrHaveReset); - break; - case kCntrlMsgResetCancelled: - DrawCellsOneLineStr(kStrCancelledReset); - break; - case kCntrlMsgConfirmInterruptStart: - DrawCellsOneLineStr(kStrConfirmInterrupt); - DrawCellsBlankLine(); - DrawCellsKeyCommand("Y", kStrInterruptDo); - DrawCellsKeyCommand("N", kStrInterruptNo); - break; - case kCntrlMsgHaveInterrupted: - DrawCellsOneLineStr(kStrHaveInterrupted); - break; - case kCntrlMsgInterruptCancelled: - DrawCellsOneLineStr(kStrCancelledInterrupt); - break; - case kCntrlMsgConfirmQuitStart: - DrawCellsOneLineStr(kStrConfirmQuit); - DrawCellsBlankLine(); - DrawCellsKeyCommand("Y", kStrQuitDo); - DrawCellsKeyCommand("N", kStrQuitNo); - break; - case kCntrlMsgQuitCancelled: - DrawCellsOneLineStr(kStrCancelledQuit); - break; - case kCntrlMsgEmCntrl: - DrawCellsOneLineStr(kStrNewCntrlKey); - break; - case kCntrlMsgBaseStart: - default: - DrawCellsOneLineStr(kStrHowToLeaveControl); - break; - } -} - -LOCALPROC DrawControlMode(void) -{ - DrawSpclMode0(ControlMode2TitleStr(), DrawCellsControlModeBody); -} - -#endif /* UseControlKeys */ - -#if EnableDemoMsg - -LOCALPROC DrawDemoMode(void) -{ - CurCellv0 = ControlBoxv0 + ((9 * CurMacDateInSeconds) & 0x0F); - CurCellh0 = ControlBoxh0 + ((15 * CurMacDateInSeconds) & 0x1F); - - DrawCellAdvance(kCellDemo0); - DrawCellAdvance(kCellDemo6); - DrawCellAdvance(kCellDemo6); - DrawCellAdvance(kCellDemo7); - DrawCellAdvance(kCellDemo1); - DrawCellAdvance(kCellDemo2); - DrawCellAdvance(kCellDemo3); - DrawCellAdvance(kCellDemo4); - DrawCellAdvance(kCellDemo7); - DrawCellAdvance(kCellDemo6); - DrawCellAdvance(kCellDemo6); - DrawCellAdvance(kCellDemo5); -} - -LOCALPROC DemoModeSecondNotify(void) -{ - NeedWholeScreenDraw = trueblnr; - SpecialModeSet(SpclModeDemo); -} - -#endif /* EnableDemoMsg */ - -#if UseActvCode -#include "ACTVCODE.h" -#endif - -LOCALPROC DrawSpclMode(void) -{ -#if UseControlKeys - if (SpecialModeTst(SpclModeControl)) { - DrawControlMode(); - } else -#endif - if (SpecialModeTst(SpclModeMessage)) { - DrawMessageMode(); - } else -#if UseActvCode - if (SpecialModeTst(SpclModeActvCode)) { - DrawActvCodeMode(); - } else -#endif -#if EnableAltKeysMode - if (SpecialModeTst(SpclModeAltKeyText)) { - DrawAltKeyMode(); - } else -#endif -#if EnableDemoMsg - if (SpecialModeTst(SpclModeDemo)) { - DrawDemoMode(); - } else -#endif - { - /* should not get here */ - } -} - -LOCALFUNC ui3p GetCurDrawBuff(void) -{ - ui3p p = screencomparebuff; - - if (0 != SpecialModes) { - MyMoveBytes((anyp)p, (anyp)CntrlDisplayBuff, -#if 0 != vMacScreenDepth - UseColorMode ? vMacScreenNumBytes : -#endif - vMacScreenMonoNumBytes - ); - p = CntrlDisplayBuff; - - DrawSpclMode(); - } - - return p; -} - -LOCALPROC Keyboard_UpdateKeyMap2(int key, blnr down) -{ -#ifndef MKC_formac_Control -#if SwapCommandControl -#define MKC_formac_Control MKC_Command -#else -#define MKC_formac_Control MKC_Control -#endif -#endif -#if MKC_formac_Control != MKC_Control - if (MKC_Control == key) { - key = MKC_formac_Control; - } else -#endif - -#ifndef MKC_formac_Command -#if SwapCommandControl -#define MKC_formac_Command MKC_Control -#else -#define MKC_formac_Command MKC_Command -#endif -#endif -#if MKC_formac_Command != MKC_Command - if (MKC_Command == key) { - key = MKC_formac_Command; - } else -#endif - -#ifndef MKC_formac_Option -#define MKC_formac_Option MKC_Option -#endif -#if MKC_formac_Option != MKC_Option - if (MKC_Option == key) { - key = MKC_formac_Option; - } else -#endif - -#ifndef MKC_formac_F1 -#define MKC_formac_F1 MKC_Option -#endif -#if MKC_formac_F1 != MKC_F1 - if (MKC_F1 == key) { - key = MKC_formac_F1; - } else -#endif - -#ifndef MKC_formac_F2 -#define MKC_formac_F2 MKC_Command -#endif -#if MKC_formac_F2 != MKC_F2 - if (MKC_F2 == key) { - key = MKC_formac_F2; - } else -#endif - - { - } - - -#if UseControlKeys - if (MKC_Control == key) { - Keyboard_UpdateControlKey(down); - } else -#endif - if ((0 == SpecialModes) -#if EnableAltKeysMode || EnableDemoMsg - || (0 == (SpecialModes & ~ ( - 0 -#if EnableAltKeysMode - | (1 << SpclModeAltKeyText) -#endif -#if EnableDemoMsg - | (1 << SpclModeDemo) -#endif - ))) -#endif - || (MKC_CapsLock == key) - ) - { - /* pass through */ - Keyboard_UpdateKeyMap1(key, down); - } else { - if (down) { -#if UseControlKeys - if (SpecialModeTst(SpclModeControl)) { - DoControlModeKey(key); - } else -#endif - if (SpecialModeTst(SpclModeMessage)) { - DoMessageModeKey(key); - } else -#if UseActvCode - if (SpecialModeTst(SpclModeActvCode)) { - DoActvCodeModeKey(key); - } else -#endif - { - } - } /* else if not down ignore */ - } -} - -LOCALPROC DisconnectKeyCodes2(void) -{ - DisconnectKeyCodes1(kKeepMaskControl | kKeepMaskCapsLock); -#if UseControlKeys - Keyboard_UpdateControlKey(falseblnr); -#endif -} +/* CONTROLM.h Copyright (C) 2007 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* CONTROL Mode */ #ifdef CONTROLM_H #error "header already included" #else #define CONTROLM_H #endif enum { #if EnableDemoMsg SpclModeDemo, #endif #if EnableAltKeysMode SpclModeAltKeyText, #endif #if UseActvCode SpclModeActvCode, #endif SpclModeMessage, #if UseControlKeys SpclModeControl, #endif kNumSpclModes }; LOCALVAR uimr SpecialModes = 0; LOCALVAR blnr NeedWholeScreenDraw = falseblnr; #define SpecialModeSet(i) SpecialModes |= (1 << (i)) #define SpecialModeClr(i) SpecialModes &= ~ (1 << (i)) #define SpecialModeTst(i) (0 != (SpecialModes & (1 << (i)))) #define MacMsgDisplayed SpecialModeTst(SpclModeMessage) LOCALVAR ui3p CntrlDisplayBuff = nullpr; LOCALPROC DrawCell(unsigned int h, unsigned int v, int x) { #if 1 /* safety check */ if ((h < ((long)vMacScreenWidth / 8 - 2)) && (v < (vMacScreenHeight / 16 - 1))) #endif { int i; ui3p p0 = ((ui3p)CellData) + 16 * x; #if 0 != vMacScreenDepth if (UseColorMode) { ui3p p = CntrlDisplayBuff + ((h + 1) << vMacScreenDepth) + (v * 16 + 11) * vMacScreenByteWidth; for (i = 16; --i >= 0; ) { #if 1 == vMacScreenDepth int k; ui3b t0 = *p0; ui3p p2 = p; for (k = 2; --k >= 0; ) { *p2++ = (((t0) & 0x80) ? 0xC0 : 0x00) | (((t0) & 0x40) ? 0x30 : 0x00) | (((t0) & 0x20) ? 0x0C : 0x00) | (((t0) & 0x10) ? 0x03 : 0x00); /* black RRGGBBAA, white RRGGBBAA */ t0 <<= 4; } #elif 2 == vMacScreenDepth int k; ui3b t0 = *p0; ui3p p2 = p; for (k = 4; --k >= 0; ) { *p2++ = (((t0) & 0x40) ? 0x0F : 0x00) | (((t0) & 0x80) ? 0xF0 : 0x00); /* black RRGGBBAA, white RRGGBBAA */ t0 <<= 2; } #elif 3 == vMacScreenDepth int k; ui3b t0 = *p0; ui3p p2 = p; for (k = 8; --k >= 0; ) { *p2++ = ((t0 >> k) & 0x01) ? 0xFF : 0x00; /* black RRGGBBAA, white RRGGBBAA */ } #elif 4 == vMacScreenDepth int k; ui4r v; ui3b t0 = *p0; ui3p p2 = p; for (k = 8; --k >= 0; ) { v = ((t0 >> k) & 0x01) ? 0x0000 : 0x7FFF; /* black RRGGBBAA, white RRGGBBAA */ /* *((ui4b *)p2)++ = v; need big endian, so : */ *p2++ = v >> 8; *p2++ = v; } #elif 5 == vMacScreenDepth int k; ui5r v; ui3b t0 = *p0; ui3p p2 = p; for (k = 8; --k >= 0; ) { v = ((t0 >> k) & 0x01) ? 0x00000000 : 0x00FFFFFF; /* black RRGGBBAA, white RRGGBBAA */ /* *((ui5b *)p2)++ = v; need big endian, so : */ *p2++ = v >> 24; *p2++ = v >> 16; *p2++ = v >> 8; *p2++ = v; } #endif p += vMacScreenByteWidth; p0 ++; } } else #endif { ui3p p = CntrlDisplayBuff + (h + 1) + (v * 16 + 11) * vMacScreenMonoByteWidth; for (i = 16; --i >= 0; ) { *p = *p0; p += vMacScreenMonoByteWidth; p0 ++; } } } } #define ControlBoxh0 0 #define ControlBoxw 62 #define ControlBoxv0 0 #define hLimit (ControlBoxh0 + ControlBoxw - 1) #define hStart (ControlBoxh0 + 1) LOCALVAR int CurCellh0; LOCALVAR int CurCellv0; LOCALPROC DrawCellsBeginLine(void) { DrawCell(ControlBoxh0, CurCellv0, kCellMiddleLeft); CurCellh0 = hStart; } LOCALPROC DrawCellsEndLine(void) { int i; for (i = CurCellh0; i < hLimit; ++i) { DrawCell(i, CurCellv0, kCellSpace); } DrawCell(hLimit, CurCellv0, kCellMiddleRight); CurCellv0++; } LOCALPROC DrawCellsBottomLine(void) { int i; DrawCell(ControlBoxh0 + 0, CurCellv0, kCellLowerLeft); for (i = hStart; i < hLimit; ++i) { DrawCell(i, CurCellv0, kCellLowerMiddle); } DrawCell(hLimit, CurCellv0, kCellLowerRight); } LOCALPROC DrawCellAdvance(int x) { DrawCell(CurCellh0, CurCellv0, x); CurCellh0++; } LOCALPROC DrawCellsBlankLine(void) { DrawCellsBeginLine(); DrawCellsEndLine(); } LOCALPROC DrawCellsFromStr(char *s) { ui3b ps[ClStrMaxLength]; ui3b cs; int L; int i; int j; int w; ClStrFromSubstCStr(&L, ps, s); i = 0; while (i < L) { cs = ps[i]; i++; if (CurCellh0 < hLimit) { DrawCellAdvance(cs); } else { /* line is too wide, wrap */ if (kCellSpace != cs) { --i; /* back up one char, at least */ /* now try backing up to beginning of word */ j = i; w = CurCellh0 - hStart; while ((w > 0) && (j > 0) && (ps[j - 1] != kCellSpace)) { --j; --w; } if (w != 0) { i = j; CurCellh0 = hStart + w; } /* else if w == 0, then have backed up to beginning of line, so just let the word be split. */ } /* else if cs == kCellSpace, just lose the space. */ DrawCellsEndLine(); /* draw white space over the part of the word that have already drawn */ DrawCellsBeginLine(); } } } LOCALPROC DrawCellsOneLineStr(char *s) { DrawCellsBeginLine(); DrawCellsFromStr(s); DrawCellsEndLine(); } LOCALPROC DrawCellsKeyCommand(char *k, char *s) { DrawCellsBeginLine(); DrawCellsFromStr("'"); DrawCellsFromStr(k); DrawCellsFromStr("' - "); DrawCellsFromStr(s); DrawCellsEndLine(); } typedef void (*SpclModeBody) (void); LOCALPROC DrawSpclMode0(char *Title, SpclModeBody Body) { int i; int k; CurCellv0 = ControlBoxv0 + 0; DrawCell(ControlBoxh0 + 0, CurCellv0, kCellUpperLeft); k = kCellIcon00; for (i = hStart; i < hStart + 4; ++i) { DrawCell(i, CurCellv0, k); k++; } for (i = hStart + 4; i < hLimit; ++i) { DrawCell(i, CurCellv0, kCellUpperMiddle); } DrawCell(hLimit, CurCellv0, kCellUpperRight); ++CurCellv0; DrawCellsBeginLine(); for (i = hStart; i < hStart + 4; ++i) { DrawCellAdvance(k); k++; } DrawCellAdvance(kCellSpace); DrawCellsFromStr(Title); DrawCellsEndLine(); DrawCellsBeginLine(); for (i = hStart; i < hStart + 4; ++i) { DrawCellAdvance(k); k++; } for (i = hStart + 4; i < hLimit; ++i) { DrawCellAdvance(kCellGraySep); } DrawCellsEndLine(); if (nullpr != Body) { Body(); } DrawCellsBottomLine(); } #if EnableAltKeysMode #include "ALTKEYSM.h" #else #define Keyboard_UpdateKeyMap1 Keyboard_UpdateKeyMap #define DisconnectKeyCodes1 DisconnectKeyCodes #endif LOCALPROC ClStrAppendHexNib(int *L0, ui3b *r, ui3r v) { if (v < 10) { ClStrAppendChar(L0, r, kCellDigit0 + v); } else { ClStrAppendChar(L0, r, kCellUpA + (v - 10)); } } LOCALPROC ClStrAppendHexByte(int *L0, ui3b *r, ui3r v) { ClStrAppendHexNib(L0, r, (v >> 4) & 0x0F); ClStrAppendHexNib(L0, r, v & 0x0F); } LOCALPROC ClStrAppendHexWord(int *L0, ui3b *r, ui4r v) { ClStrAppendHexByte(L0, r, (v >> 8) & 0xFF); ClStrAppendHexByte(L0, r, v & 0xFF); } LOCALPROC DrawCellsOneLineHexWord(ui4r v) { ui3b ps[ClStrMaxLength]; int L = 0; int i; ClStrAppendHexWord(&L, ps, v); DrawCellsBeginLine(); for (i = 0; i < L; ++i) { DrawCellAdvance(ps[i]); } DrawCellsEndLine(); } LOCALPROC DrawCellsMessageModeBody(void) { DrawCellsOneLineStr(SavedBriefMsg); DrawCellsBlankLine(); DrawCellsOneLineStr(SavedLongMsg); if (0 != SavedIDMsg) { DrawCellsBlankLine(); DrawCellsOneLineHexWord(SavedIDMsg); } } LOCALPROC DrawMessageMode(void) { DrawSpclMode0(kStrModeMessage, DrawCellsMessageModeBody); } LOCALPROC MacMsgDisplayOff(void) { SpecialModeClr(SpclModeMessage); SavedBriefMsg = nullpr; SavedIDMsg = 0; NeedWholeScreenDraw = trueblnr; } LOCALPROC MacMsgDisplayOn(void) { NeedWholeScreenDraw = trueblnr; DisconnectKeyCodes1(kKeepMaskControl | kKeepMaskCapsLock); /* command */ SpecialModeSet(SpclModeMessage); } LOCALPROC DoMessageModeKey(int key) { if (MKC_C == key) { MacMsgDisplayOff(); } } LOCALPROC MacMsgOverride(char *briefMsg, char *longMsg) { if (MacMsgDisplayed) { MacMsgDisplayOff(); } MacMsg(briefMsg, longMsg, falseblnr); } #if NeedDoMoreCommandsMsg LOCALPROC DoMoreCommandsMsg(void) { MacMsgOverride(kStrMoreCommandsTitle, kStrMoreCommandsMessage); } #endif #if NeedDoAboutMsg LOCALPROC DoAboutMsg(void) { MacMsgOverride(kStrAboutTitle, kStrAboutMessage); } #endif #if UseControlKeys LOCALVAR blnr LastControlKey = falseblnr; LOCALVAR int CurControlMode = 0; LOCALVAR int ControlMessage = 0; enum { kCntrlModeOff, kCntrlModeBase, kCntrlModeConfirmReset, kCntrlModeConfirmInterrupt, kCntrlModeConfirmQuit, kCntrlModeSpeedControl, kNumCntrlModes }; enum { kCntrlMsgBaseStart, #if EnableMagnify kCntrlMsgMagnify, #endif #if VarFullScreen kCntrlMsgFullScreen, #endif kCntrlMsgConfirmResetStart, kCntrlMsgHaveReset, kCntrlMsgResetCancelled, kCntrlMsgConfirmInterruptStart, kCntrlMsgHaveInterrupted, kCntrlMsgInterruptCancelled, kCntrlMsgConfirmQuitStart, kCntrlMsgQuitCancelled, kCntrlMsgEmCntrl, kCntrlMsgSpeedControlStart, kCntrlMsgNewSpeed, kCntrlMsgNewStopped, kCntrlMsgNewRunInBack, #if EnableAutoSlow kCntrlMsgNewAutoSlow, #endif kCntrlMsgAbout, kCntrlMsgHelp, #if UseActvCode || EnableDemoMsg kCntrlMsgRegStrCopied, #endif kNumCntrlMsgs }; LOCALPROC DoEnterControlMode(void) { CurControlMode = kCntrlModeBase; ControlMessage = kCntrlMsgBaseStart; NeedWholeScreenDraw = trueblnr; DisconnectKeyCodes1(kKeepMaskControl | kKeepMaskCapsLock); SpecialModeSet(SpclModeControl); } LOCALPROC DoLeaveControlMode(void) { SpecialModeClr(SpclModeControl); CurControlMode = kCntrlModeOff; NeedWholeScreenDraw = trueblnr; } LOCALPROC Keyboard_UpdateControlKey(blnr down) { if (down != LastControlKey) { LastControlKey = down; if (down) { DoEnterControlMode(); } else { DoLeaveControlMode(); } } } LOCALPROC SetSpeedValue(ui3b i) { SpeedValue = i; CurControlMode = kCntrlModeBase; ControlMessage = kCntrlMsgNewSpeed; } #if VarFullScreen FORWARDPROC ToggleWantFullScreen(void); #endif #if UseActvCode FORWARDPROC CopyRegistrationStr(void); #elif EnableDemoMsg LOCALPROC CopyRegistrationStr(void) { ui3b ps[ClStrMaxLength]; int i; int L; tPbuf j; ClStrFromSubstCStr(&L, ps, "^v"); for (i = 0; i < L; ++i) { ps[i] = Cell2MacAsciiMap[ps[i]]; } if (mnvm_noErr == PbufNew(L, &j)) { PbufTransfer(ps, j, 0, L, trueblnr); HTCEexport(j); } } #endif LOCALPROC DoControlModeKey(int key) { switch (CurControlMode) { case kCntrlModeBase: switch (key) { case MKC_K: ControlKeyPressed = ! ControlKeyPressed; ControlMessage = kCntrlMsgEmCntrl; Keyboard_UpdateKeyMap1(MKC_Control, ControlKeyPressed); break; case MKC_S: CurControlMode = kCntrlModeSpeedControl; ControlMessage = kCntrlMsgSpeedControlStart; break; case MKC_I: CurControlMode = kCntrlModeConfirmInterrupt; ControlMessage = kCntrlMsgConfirmInterruptStart; break; case MKC_R: if (! AnyDiskInserted()) { WantMacReset = trueblnr; ControlMessage = kCntrlMsgHaveReset; } else { CurControlMode = kCntrlModeConfirmReset; ControlMessage = kCntrlMsgConfirmResetStart; } break; case MKC_Q: if (! AnyDiskInserted()) { ForceMacOff = trueblnr; } else { CurControlMode = kCntrlModeConfirmQuit; ControlMessage = kCntrlMsgConfirmQuitStart; } break; case MKC_A: ControlMessage = kCntrlMsgAbout; break; case MKC_H: ControlMessage = kCntrlMsgHelp; break; #if NeedRequestInsertDisk case MKC_O: RequestInsertDisk = trueblnr; break; #endif #if EnableMagnify case MKC_M: WantMagnify = ! WantMagnify; ControlMessage = kCntrlMsgMagnify; break; #endif #if VarFullScreen case MKC_F: ToggleWantFullScreen(); ControlMessage = kCntrlMsgFullScreen; break; #endif #if UseActvCode || EnableDemoMsg case MKC_P: CopyRegistrationStr(); ControlMessage = kCntrlMsgRegStrCopied; break; #endif } break; case kCntrlModeConfirmReset: switch (key) { case MKC_Y: WantMacReset = trueblnr; CurControlMode = kCntrlModeBase; ControlMessage = kCntrlMsgHaveReset; break; case MKC_R: /* ignore, in case of repeat */ break; case MKC_N: default: CurControlMode = kCntrlModeBase; ControlMessage = kCntrlMsgResetCancelled; break; } break; case kCntrlModeConfirmInterrupt: switch (key) { case MKC_Y: WantMacInterrupt = trueblnr; CurControlMode = kCntrlModeBase; ControlMessage = kCntrlMsgHaveInterrupted; break; case MKC_I: /* ignore, in case of repeat */ break; case MKC_N: default: CurControlMode = kCntrlModeBase; ControlMessage = kCntrlMsgInterruptCancelled; break; } break; case kCntrlModeConfirmQuit: switch (key) { case MKC_Y: ForceMacOff = trueblnr; CurControlMode = kCntrlModeBase; ControlMessage = kCntrlMsgBaseStart; /* shouldn't see this message since quitting */ break; case MKC_Q: /* ignore, in case of repeat */ break; case MKC_N: default: CurControlMode = kCntrlModeBase; ControlMessage = kCntrlMsgQuitCancelled; break; } break; case kCntrlModeSpeedControl: switch (key) { case MKC_E: CurControlMode = kCntrlModeBase; ControlMessage = kCntrlMsgBaseStart; break; case MKC_B: RunInBackground = ! RunInBackground; CurControlMode = kCntrlModeBase; ControlMessage = kCntrlMsgNewRunInBack; break; case MKC_D: SpeedStopped = ! SpeedStopped; CurControlMode = kCntrlModeBase; ControlMessage = kCntrlMsgNewStopped; break; #if EnableAutoSlow case MKC_W: WantNotAutoSlow = ! WantNotAutoSlow; CurControlMode = kCntrlModeBase; ControlMessage = kCntrlMsgNewAutoSlow; break; #endif case MKC_Z: SetSpeedValue(0); break; case MKC_1: SetSpeedValue(1); break; case MKC_2: SetSpeedValue(2); break; case MKC_3: SetSpeedValue(3); break; case MKC_4: SetSpeedValue(4); break; case MKC_5: SetSpeedValue(5); break; case MKC_A: SetSpeedValue((ui3b) -1); break; } break; } NeedWholeScreenDraw = trueblnr; } LOCALFUNC char * ControlMode2TitleStr(void) { char *s; switch (CurControlMode) { case kCntrlModeConfirmReset: s = kStrModeConfirmReset; break; case kCntrlModeConfirmInterrupt: s = kStrModeConfirmInterrupt; break; case kCntrlModeConfirmQuit: s = kStrModeConfirmQuit; break; case kCntrlModeSpeedControl: s = kStrModeSpeedControl; break; case kCntrlModeBase: default: if (kCntrlMsgHelp == ControlMessage) { s = kStrModeControlHelp; } else { s = kStrModeControlBase; } break; } return s; } LOCALPROC DrawCellsControlModeBody(void) { switch (ControlMessage) { case kCntrlMsgAbout: #ifndef kStrSponsorName DrawCellsOneLineStr(kStrProgramInfo); #else DrawCellsOneLineStr(kStrSponsorIs); DrawCellsOneLineStr(kStrSponsorName); #endif DrawCellsBlankLine(); DrawCellsOneLineStr(kStrWorkOfMany); DrawCellsOneLineStr(kMaintainerName); DrawCellsOneLineStr(kStrForMoreInfo); DrawCellsOneLineStr("^w"); DrawCellsBlankLine(); DrawCellsBeginLine(); DrawCellsFromStr(kStrLicense); DrawCellsFromStr(kStrDisclaimer); DrawCellsEndLine(); break; case kCntrlMsgHelp: DrawCellsOneLineStr(kStrHowToLeaveControl); DrawCellsOneLineStr(kStrHowToPickACommand); DrawCellsBlankLine(); DrawCellsKeyCommand("A", kStrCmdAbout); #if NeedRequestInsertDisk DrawCellsKeyCommand("O", kStrCmdOpenDiskImage); #endif DrawCellsKeyCommand("Q", kStrCmdQuit); DrawCellsKeyCommand("S", kStrCmdSpeedControl); #if EnableMagnify DrawCellsKeyCommand("M", kStrCmdMagnifyToggle); #endif #if VarFullScreen DrawCellsKeyCommand("F", kStrCmdFullScrnToggle); #endif DrawCellsKeyCommand("K", kStrCmdCtrlKeyToggle); DrawCellsKeyCommand("R", kStrCmdReset); DrawCellsKeyCommand("I", kStrCmdInterrupt); DrawCellsKeyCommand("H", kStrCmdHelp); break; case kCntrlMsgSpeedControlStart: DrawCellsOneLineStr(kStrCurrentSpeed); DrawCellsKeyCommand("Z", "1x"); DrawCellsKeyCommand("1", "2x"); DrawCellsKeyCommand("2", "4x"); DrawCellsKeyCommand("3", "8x"); DrawCellsKeyCommand("4", "16x"); DrawCellsKeyCommand("5", "32x"); DrawCellsKeyCommand("A", kStrSpeedAllOut); DrawCellsBlankLine(); DrawCellsKeyCommand("D", kStrSpeedStopped); DrawCellsKeyCommand("B", kStrSpeedBackToggle); #if EnableAutoSlow DrawCellsKeyCommand("W", kStrSpeedAutoSlowToggle); #endif DrawCellsBlankLine(); DrawCellsKeyCommand("E", kStrSpeedExit); break; case kCntrlMsgNewSpeed: DrawCellsOneLineStr(kStrNewSpeed); break; case kCntrlMsgNewRunInBack: DrawCellsOneLineStr(kStrNewRunInBack); break; case kCntrlMsgNewStopped: DrawCellsOneLineStr(kStrNewStopped); break; #if EnableAutoSlow case kCntrlMsgNewAutoSlow: DrawCellsOneLineStr(kStrNewAutoSlow); break; #endif #if EnableMagnify case kCntrlMsgMagnify: DrawCellsOneLineStr(kStrNewMagnify); break; #endif #if VarFullScreen case kCntrlMsgFullScreen: DrawCellsOneLineStr(kStrNewFullScreen); break; #endif #if UseActvCode case kCntrlMsgRegStrCopied: DrawCellsOneLineStr("Registration String copied."); break; #elif EnableDemoMsg case kCntrlMsgRegStrCopied: DrawCellsOneLineStr("Variation name copied."); break; #endif case kCntrlMsgConfirmResetStart: DrawCellsOneLineStr(kStrConfirmReset); DrawCellsBlankLine(); DrawCellsKeyCommand("Y", kStrResetDo); DrawCellsKeyCommand("N", kStrResetNo); break; case kCntrlMsgHaveReset: DrawCellsOneLineStr(kStrHaveReset); break; case kCntrlMsgResetCancelled: DrawCellsOneLineStr(kStrCancelledReset); break; case kCntrlMsgConfirmInterruptStart: DrawCellsOneLineStr(kStrConfirmInterrupt); DrawCellsBlankLine(); DrawCellsKeyCommand("Y", kStrInterruptDo); DrawCellsKeyCommand("N", kStrInterruptNo); break; case kCntrlMsgHaveInterrupted: DrawCellsOneLineStr(kStrHaveInterrupted); break; case kCntrlMsgInterruptCancelled: DrawCellsOneLineStr(kStrCancelledInterrupt); break; case kCntrlMsgConfirmQuitStart: DrawCellsOneLineStr(kStrConfirmQuit); DrawCellsBlankLine(); DrawCellsKeyCommand("Y", kStrQuitDo); DrawCellsKeyCommand("N", kStrQuitNo); break; case kCntrlMsgQuitCancelled: DrawCellsOneLineStr(kStrCancelledQuit); break; case kCntrlMsgEmCntrl: DrawCellsOneLineStr(kStrNewCntrlKey); break; case kCntrlMsgBaseStart: default: DrawCellsOneLineStr(kStrHowToLeaveControl); break; } } LOCALPROC DrawControlMode(void) { DrawSpclMode0(ControlMode2TitleStr(), DrawCellsControlModeBody); } #endif /* UseControlKeys */ #if EnableDemoMsg LOCALPROC DrawDemoMode(void) { CurCellv0 = ControlBoxv0 + ((9 * CurMacDateInSeconds) & 0x0F); CurCellh0 = ControlBoxh0 + ((15 * CurMacDateInSeconds) & 0x1F); DrawCellAdvance(kCellDemo0); DrawCellAdvance(kCellDemo6); DrawCellAdvance(kCellDemo6); DrawCellAdvance(kCellDemo7); DrawCellAdvance(kCellDemo1); DrawCellAdvance(kCellDemo2); DrawCellAdvance(kCellDemo3); DrawCellAdvance(kCellDemo4); DrawCellAdvance(kCellDemo7); DrawCellAdvance(kCellDemo6); DrawCellAdvance(kCellDemo6); DrawCellAdvance(kCellDemo5); } LOCALPROC DemoModeSecondNotify(void) { NeedWholeScreenDraw = trueblnr; SpecialModeSet(SpclModeDemo); } #endif /* EnableDemoMsg */ #if UseActvCode #include "ACTVCODE.h" #endif LOCALPROC DrawSpclMode(void) { #if UseControlKeys if (SpecialModeTst(SpclModeControl)) { DrawControlMode(); } else #endif if (SpecialModeTst(SpclModeMessage)) { DrawMessageMode(); } else #if UseActvCode if (SpecialModeTst(SpclModeActvCode)) { DrawActvCodeMode(); } else #endif #if EnableAltKeysMode if (SpecialModeTst(SpclModeAltKeyText)) { DrawAltKeyMode(); } else #endif #if EnableDemoMsg if (SpecialModeTst(SpclModeDemo)) { DrawDemoMode(); } else #endif { /* should not get here */ } } LOCALFUNC ui3p GetCurDrawBuff(void) { ui3p p = screencomparebuff; if (0 != SpecialModes) { MyMoveBytes((anyp)p, (anyp)CntrlDisplayBuff, #if 0 != vMacScreenDepth UseColorMode ? vMacScreenNumBytes : #endif vMacScreenMonoNumBytes ); p = CntrlDisplayBuff; DrawSpclMode(); } return p; } LOCALPROC Keyboard_UpdateKeyMap2(int key, blnr down) { #ifndef MKC_formac_Control #if SwapCommandControl #define MKC_formac_Control MKC_Command #else #define MKC_formac_Control MKC_Control #endif #endif #if MKC_formac_Control != MKC_Control if (MKC_Control == key) { key = MKC_formac_Control; } else #endif #ifndef MKC_formac_Command #if SwapCommandControl #define MKC_formac_Command MKC_Control #else #define MKC_formac_Command MKC_Command #endif #endif #if MKC_formac_Command != MKC_Command if (MKC_Command == key) { key = MKC_formac_Command; } else #endif #ifndef MKC_formac_Option #define MKC_formac_Option MKC_Option #endif #if MKC_formac_Option != MKC_Option if (MKC_Option == key) { key = MKC_formac_Option; } else #endif #ifndef MKC_formac_F1 #define MKC_formac_F1 MKC_Option #endif #if MKC_formac_F1 != MKC_F1 if (MKC_F1 == key) { key = MKC_formac_F1; } else #endif #ifndef MKC_formac_F2 #define MKC_formac_F2 MKC_Command #endif #if MKC_formac_F2 != MKC_F2 if (MKC_F2 == key) { key = MKC_formac_F2; } else #endif { } #if UseControlKeys if (MKC_Control == key) { Keyboard_UpdateControlKey(down); } else #endif if ((0 == SpecialModes) #if EnableAltKeysMode || EnableDemoMsg || (0 == (SpecialModes & ~ ( 0 #if EnableAltKeysMode | (1 << SpclModeAltKeyText) #endif #if EnableDemoMsg | (1 << SpclModeDemo) #endif ))) #endif || (MKC_CapsLock == key) ) { /* pass through */ Keyboard_UpdateKeyMap1(key, down); } else { if (down) { #if UseControlKeys if (SpecialModeTst(SpclModeControl)) { DoControlModeKey(key); } else #endif if (SpecialModeTst(SpclModeMessage)) { DoMessageModeKey(key); } else #if UseActvCode if (SpecialModeTst(SpclModeActvCode)) { DoActvCodeModeKey(key); } else #endif { } } /* else if not down ignore */ } } LOCALPROC DisconnectKeyCodes2(void) { DisconnectKeyCodes1(kKeepMaskControl | kKeepMaskCapsLock); #if UseControlKeys Keyboard_UpdateControlKey(falseblnr); #endif } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/DATE2SEC.h b/Mini vMac/mnvm_core/DATE2SEC.h index 504b620..0058861 100755 --- a/Mini vMac/mnvm_core/DATE2SEC.h +++ b/Mini vMac/mnvm_core/DATE2SEC.h @@ -1,117 +1 @@ -/* - DATE2SEC.h - Copyright (C) 2003 Bradford L. Barrett, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - DATE 2(to) SEConds - - convert year/month/day/hour/minute/second - to number of seconds since the beginning - of 1904, the format for storing dates - on the Macintosh. - - The function jdate is from the program Webalizer - by Bradford L. Barrett. -*/ - -#ifdef DATE2SEC_H -#error "header already included" -#else -#define DATE2SEC_H -#endif - -/* - The function jdate was found at the end of the file - webalizer.c in the program webalizer at - "www.mrunix.net/webalizer/". - Here is copyright info from the top of that file: - - webalizer - a web server log analysis program - - Copyright (C) 1997-2000 Bradford L. Barrett (brad@mrunix.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version, and provided that the above - copyright and permission notice is included with all distributed - copies of this or derived software. -*/ - -/* ************************************************************* */ -/* */ -/* JDATE - Julian date calculator */ -/* */ -/* Calculates the number of days since Jan 1, 0000. */ -/* */ -/* Originally written by Bradford L. Barrett (03/17/1988) */ -/* Returns an unsigned long value representing the number of */ -/* days since January 1, 0000. */ -/* */ -/* Note: Due to the changes made by Pope Gregory XIII in the */ -/* 16th Centyry (Feb 24, 1582), dates before 1583 will */ -/* not return a truely accurate number (will be at least */ -/* 10 days off). Somehow, I don't think this will */ -/* present much of a problem for most situations :) */ -/* */ -/* Usage: days = jdate(day, month, year) */ -/* */ -/* The number returned is adjusted by 5 to facilitate day of */ -/* week calculations. The mod of the returned value gives the */ -/* day of the week the date is. (ie: dow = days % 7) where */ -/* dow will return 0=Sunday, 1=Monday, 2=Tuesday, etc... */ -/* */ -/* ************************************************************* */ - -LOCALFUNC ui5b jdate(int day, int month, int year) -{ - ui5b days; /* value returned */ - int mtable[] = { - 0, 31, 59, 90, 120, 151, - 181, 212, 243, 273, 304, 334 - }; - - /* - First, calculate base number including leap - and Centenial year stuff - */ - - days = (((ui5b)year * 365) + day + mtable[month - 1] - + ((year + 4) / 4) - ((year / 100) - (year / 400))); - - /* now adjust for leap year before March 1st */ - - if ((year % 4 == 0) - && (! ((year % 100 == 0) && (year % 400 != 0))) - && (month < 3)) - { - --days; - } - - /* done, return with calculated value */ - - return (days + 5); -} - -LOCALFUNC ui5b Date2MacSeconds(int second, int minute, int hour, - int day, int month, int year) -{ - ui5b curjdate; - ui5b basejdate; - - curjdate = jdate(day, month, year); - basejdate = jdate(1, 1, 1904); - return (((curjdate - basejdate) * 24 + hour) * 60 - + minute) * 60 + second; -} +/* DATE2SEC.h Copyright (C) 2003 Bradford L. Barrett, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* DATE 2(to) SEConds convert year/month/day/hour/minute/second to number of seconds since the beginning of 1904, the format for storing dates on the Macintosh. The function jdate is from the program Webalizer by Bradford L. Barrett. */ #ifdef DATE2SEC_H #error "header already included" #else #define DATE2SEC_H #endif /* The function jdate was found at the end of the file webalizer.c in the program webalizer at "www.mrunix.net/webalizer/". Here is copyright info from the top of that file: webalizer - a web server log analysis program Copyright (C) 1997-2000 Bradford L. Barrett (brad@mrunix.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version, and provided that the above copyright and permission notice is included with all distributed copies of this or derived software. */ /* ************************************************************* */ /* */ /* JDATE - Julian date calculator */ /* */ /* Calculates the number of days since Jan 1, 0000. */ /* */ /* Originally written by Bradford L. Barrett (03/17/1988) */ /* Returns an unsigned long value representing the number of */ /* days since January 1, 0000. */ /* */ /* Note: Due to the changes made by Pope Gregory XIII in the */ /* 16th Centyry (Feb 24, 1582), dates before 1583 will */ /* not return a truely accurate number (will be at least */ /* 10 days off). Somehow, I don't think this will */ /* present much of a problem for most situations :) */ /* */ /* Usage: days = jdate(day, month, year) */ /* */ /* The number returned is adjusted by 5 to facilitate day of */ /* week calculations. The mod of the returned value gives the */ /* day of the week the date is. (ie: dow = days % 7) where */ /* dow will return 0=Sunday, 1=Monday, 2=Tuesday, etc... */ /* */ /* ************************************************************* */ LOCALFUNC ui5b jdate(int day, int month, int year) { ui5b days; /* value returned */ int mtable[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; /* First, calculate base number including leap and Centenial year stuff */ days = (((ui5b)year * 365) + day + mtable[month - 1] + ((year + 4) / 4) - ((year / 100) - (year / 400))); /* now adjust for leap year before March 1st */ if ((year % 4 == 0) && (! ((year % 100 == 0) && (year % 400 != 0))) && (month < 3)) { --days; } /* done, return with calculated value */ return (days + 5); } LOCALFUNC ui5b Date2MacSeconds(int second, int minute, int hour, int day, int month, int year) { ui5b curjdate; ui5b basejdate; curjdate = jdate(day, month, year); basejdate = jdate(1, 1, 1904); return (((curjdate - basejdate) * 24 + hour) * 60 + minute) * 60 + second; } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/DISAM68K.c b/Mini vMac/mnvm_core/DISAM68K.c index 60c988e..9a41037 100755 --- a/Mini vMac/mnvm_core/DISAM68K.c +++ b/Mini vMac/mnvm_core/DISAM68K.c @@ -1,2936 +1 @@ -/* - DISAM68K.c - - Copyright (C) 2010 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - DISAssemble Motorola 68K instructions. -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" - -#include "ENDIANAC.h" -#include "MYOSGLUE.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" - -#include "M68KITAB.h" -#endif - -#include "DISAM68K.h" - -LOCALVAR ui5r Disasm_pc; - -/* - don't use get_vm_byte/get_vm_word/get_vm_long - so as to be sure of no side effects - (if pc points to memory mapped device) -*/ - -LOCALVAR ui3p Disasm_pcp; -LOCALVAR ui5r Disasm_pc_blockmask; -LOCALVAR ui3b Disasm_pcp_dummy[2] = { - 0, 0 -}; - -IMPORTFUNC ATTep FindATTel(CPTR addr); - -LOCALPROC Disasm_Find_pcp(void) -{ - ATTep p; - - p = FindATTel(Disasm_pc); - if (0 == (p->Access & kATTA_readreadymask)) { - Disasm_pcp = Disasm_pcp_dummy; - Disasm_pc_blockmask = 0; - } else { - Disasm_pc_blockmask = p->usemask & ~ p->cmpmask; - Disasm_pc_blockmask = Disasm_pc_blockmask - & ~ (Disasm_pc_blockmask + 1); - Disasm_pcp = p->usebase + (Disasm_pc & p->usemask); - } -} - -LOCALFUNC MayNotInline ui4r Disasm_nextiword(void) -/* NOT sign extended */ -{ - ui4r r = do_get_mem_word(Disasm_pcp); - Disasm_pcp += 2; - Disasm_pc += 2; - if (0 == (Disasm_pc_blockmask & Disasm_pc)) { - Disasm_Find_pcp(); - } - return r; -} - -LOCALFUNC ui3r Disasm_nextibyte(void) -{ - return (ui3b) Disasm_nextiword(); -} - -LOCALFUNC MayNotInline ui5r Disasm_nextilong(void) -{ - ui5r hi = Disasm_nextiword(); - ui5r lo = Disasm_nextiword(); - ui5r r = ((hi << 16) & 0xFFFF0000) - | (lo & 0x0000FFFF); - - return r; -} - -LOCALPROC Disasm_setpc(CPTR newpc) -{ - if (newpc != Disasm_pc) { - Disasm_pc = newpc; - - Disasm_Find_pcp(); - } -} - -LOCALVAR ui5b Disasm_opcode; - -LOCALVAR ui5b Disasm_opsize; - -#define Disasm_b76 ((Disasm_opcode >> 6) & 3) -#define Disasm_b8 ((Disasm_opcode >> 8) & 1) -#define Disasm_mode ((Disasm_opcode >> 3) & 7) -#define Disasm_reg (Disasm_opcode & 7) -#define Disasm_md6 ((Disasm_opcode >> 6) & 7) -#define Disasm_rg9 ((Disasm_opcode >> 9) & 7) - -LOCALPROC DisasmOpSizeFromb76(void) -{ - Disasm_opsize = 1 << Disasm_b76; - switch (Disasm_opsize) { - case 1 : - dbglog_writeCStr(".B"); - break; - case 2 : - dbglog_writeCStr(".W"); - break; - case 4 : - dbglog_writeCStr(".L"); - break; - } -} - -LOCALPROC MayNotInline DisasmModeRegister(ui5b themode, ui5b thereg) -{ - switch (themode) { - case 0 : - dbglog_writeCStr("D"); - dbglog_writeHex(thereg); - break; - case 1 : - dbglog_writeCStr("A"); - dbglog_writeHex(thereg); - break; - case 2 : - dbglog_writeCStr("(A"); - dbglog_writeHex(thereg); - dbglog_writeCStr(")"); - break; - case 3 : - dbglog_writeCStr("(A"); - dbglog_writeHex(thereg); - dbglog_writeCStr(")+"); - break; - case 4 : - dbglog_writeCStr("-(A"); - dbglog_writeHex(thereg); - dbglog_writeCStr(")"); - break; - case 5 : - dbglog_writeHex(Disasm_nextiword()); - dbglog_writeCStr("(A"); - dbglog_writeHex(thereg); - dbglog_writeCStr(")"); - break; - case 6 : - dbglog_writeCStr("???"); -#if 0 - ArgKind = AKMemory; - ArgAddr.mem = get_disp_ea(m68k_areg(thereg)); -#endif - break; - case 7 : - switch (thereg) { - case 0 : - dbglog_writeCStr("("); - dbglog_writeHex(Disasm_nextiword()); - dbglog_writeCStr(")"); - break; - case 1 : - dbglog_writeCStr("("); - dbglog_writeHex(Disasm_nextilong()); - dbglog_writeCStr(")"); - break; - case 2 : - { - ui5r s = Disasm_pc; - s += ui5r_FromSWord(Disasm_nextiword()); - dbglog_writeCStr("("); - dbglog_writeHex(s); - dbglog_writeCStr(")"); - } - break; - case 3 : - dbglog_writeCStr("???"); -#if 0 - ArgKind = AKMemory; - s = get_disp_ea(Disasm_pc); -#endif - break; - case 4 : - dbglog_writeCStr("#"); - if (Disasm_opsize == 2) { - dbglog_writeHex(Disasm_nextiword()); - } else if (Disasm_opsize < 2) { - dbglog_writeHex(Disasm_nextibyte()); - } else { - dbglog_writeHex(Disasm_nextilong()); - } - break; - } - break; - case 8 : - dbglog_writeCStr("#"); - dbglog_writeHex(thereg); - break; - } -} - -LOCALPROC DisasmStartOne(char *s) -{ - dbglog_writeCStr(s); -} - -LOCALPROC Disasm_xxxxxxxxssmmmrrr(char *s) -{ - DisasmStartOne(s); - DisasmOpSizeFromb76(); - dbglog_writeCStr(" "); - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROC DisasmEaD_xxxxdddxssmmmrrr(char *s) -{ - DisasmStartOne(s); - DisasmOpSizeFromb76(); - dbglog_writeCStr(" "); - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeCStr(", "); - dbglog_writeCStr("D"); - dbglog_writeHex(Disasm_rg9); - dbglog_writeReturn(); -} - -LOCALPROC DisasmI_xxxxxxxxssmmmrrr(char *s) -{ - DisasmStartOne(s); - DisasmOpSizeFromb76(); - dbglog_writeCStr(" #"); - if (Disasm_opsize == 2) { - dbglog_writeHex(ui5r_FromSWord(Disasm_nextiword())); - } else if (Disasm_opsize < 2) { - dbglog_writeHex(ui5r_FromSByte(Disasm_nextibyte())); - } else { - dbglog_writeHex(ui5r_FromSLong(Disasm_nextilong())); - } - dbglog_writeCStr(", "); - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROC DisasmsAA_xxxxdddxssxxxrrr(char *s) -{ - DisasmStartOne(s); - DisasmOpSizeFromb76(); - DisasmModeRegister(3, Disasm_reg); - dbglog_writeCStr(", "); - DisasmModeRegister(3, Disasm_rg9); - dbglog_writeReturn(); -} - -LOCALFUNC ui5r Disasm_octdat(ui5r x) -{ - if (x == 0) { - return 8; - } else { - return x; - } -} - -LOCALPROC Disasm_xxxxnnnxssmmmrrr(char *s) -{ - DisasmStartOne(s); - DisasmOpSizeFromb76(); - dbglog_writeCStr(" #"); - - dbglog_writeHex(Disasm_octdat(Disasm_rg9)); - dbglog_writeCStr(", "); - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROC DisasmDEa_xxxxdddxssmmmrrr(char *s) -{ - DisasmStartOne(s); - DisasmOpSizeFromb76(); - dbglog_writeCStr(" D"); - dbglog_writeHex(Disasm_rg9); - dbglog_writeCStr(", "); - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROC DisasmEaA_xxxxdddsxxmmmrrr(char *s) -{ - DisasmStartOne(s); - - Disasm_opsize = Disasm_b8 * 2 + 2; - if (Disasm_opsize == 2) { - dbglog_writeCStr(".W"); - } else { - dbglog_writeCStr(".L"); - } - dbglog_writeCStr(" "); - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeCStr(", A"); - dbglog_writeHex(Disasm_rg9); - dbglog_writeReturn(); -} - -LOCALPROC DisasmDD_xxxxdddxssxxxrrr(char *s) -{ - DisasmStartOne(s); - DisasmOpSizeFromb76(); - dbglog_writeCStr(" "); - DisasmModeRegister(0, Disasm_reg); - dbglog_writeCStr(", "); - DisasmModeRegister(0, Disasm_rg9); - dbglog_writeReturn(); -} - -LOCALPROC DisasmAAs_xxxxdddxssxxxrrr(char *s) -{ - DisasmStartOne(s); - DisasmOpSizeFromb76(); - dbglog_writeCStr(" "); - DisasmModeRegister(4, Disasm_reg); - dbglog_writeCStr(", "); - DisasmModeRegister(4, Disasm_rg9); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmTst(void) -{ - /* Tst 01001010ssmmmrrr */ - Disasm_xxxxxxxxssmmmrrr("TST"); -} - -LOCALPROCUSEDONCE DisasmCompare(void) -{ - /* Cmp 1011ddd0ssmmmrrr */ - DisasmEaD_xxxxdddxssmmmrrr("CMP"); -} - -LOCALPROCUSEDONCE DisasmCmpI(void) -{ - /* CMPI 00001100ssmmmrrr */ - DisasmI_xxxxxxxxssmmmrrr("CMP"); -} - -LOCALPROCUSEDONCE DisasmCmpM(void) -{ - /* CmpM 1011ddd1ss001rrr */ - DisasmsAA_xxxxdddxssxxxrrr("CMP"); -} - -LOCALPROC DisasmCC(void) -{ - switch ((Disasm_opcode >> 8) & 15) { - case 0: dbglog_writeCStr("T"); break; - case 1: dbglog_writeCStr("F"); break; - case 2: dbglog_writeCStr("HI"); break; - case 3: dbglog_writeCStr("LS"); break; - case 4: dbglog_writeCStr("CC"); break; - case 5: dbglog_writeCStr("CS"); break; - case 6: dbglog_writeCStr("NE"); break; - case 7: dbglog_writeCStr("EQ"); break; - case 8: dbglog_writeCStr("VC"); break; - case 9: dbglog_writeCStr("VS"); break; - case 10: dbglog_writeCStr("P"); break; - case 11: dbglog_writeCStr("MI"); break; - case 12: dbglog_writeCStr("GE"); break; - case 13: dbglog_writeCStr("LT"); break; - case 14: dbglog_writeCStr("GT"); break; - case 15: dbglog_writeCStr("LE"); break; - default: break; /* shouldn't get here */ - } -} - -LOCALPROCUSEDONCE DisasmBcc(void) -{ - /* Bcc 0110ccccnnnnnnnn */ - ui5b src = ((ui5b)Disasm_opcode) & 255; - ui5r s = Disasm_pc; - - if (0 == ((Disasm_opcode >> 8) & 15)) { - DisasmStartOne("BRA"); - } else { - DisasmStartOne("B"); - DisasmCC(); - } - dbglog_writeCStr(" "); - - if (src == 0) { - s += ui5r_FromSWord(Disasm_nextiword()); - } else -#if Use68020 - if (src == 255) { - s += ui5r_FromSLong(Disasm_nextilong()); - /* ReportAbnormal("long branch in DoCode6"); */ - /* Used by various Apps */ - } else -#endif - { - s += ui5r_FromSByte(src); - } - dbglog_writeHex(s); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmDBcc(void) -{ - /* DBcc 0101cccc11001ddd */ - - ui5r s = Disasm_pc; - - DisasmStartOne("DB"); - DisasmCC(); - - dbglog_writeCStr(" D"); - dbglog_writeHex(Disasm_reg); - dbglog_writeCStr(", "); - - s += (si5b)(si4b)Disasm_nextiword(); - dbglog_writeHex(s); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmSwap(void) -{ - /* Swap 0100100001000rrr */ - - DisasmStartOne("SWAP D"); - dbglog_writeHex(Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROC DisasmMove(void) /* MOVE */ -{ - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeCStr(", "); - DisasmModeRegister(Disasm_md6, Disasm_rg9); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmMoveL(void) -{ - DisasmStartOne("MOVE.L "); - Disasm_opsize = 4; - DisasmMove(); -} - -LOCALPROCUSEDONCE DisasmMoveW(void) -{ - DisasmStartOne("MOVE.W "); - Disasm_opsize = 2; - DisasmMove(); -} - -LOCALPROCUSEDONCE DisasmMoveB(void) -{ - DisasmStartOne("MOVE.B "); - Disasm_opsize = 1; - DisasmMove(); -} - -LOCALPROCUSEDONCE DisasmMoveAL(void) -{ - DisasmStartOne("MOVEA.L "); - Disasm_opsize = 4; - DisasmMove(); -} - -LOCALPROCUSEDONCE DisasmMoveAW(void) -{ - DisasmStartOne("MOVEA.W "); - Disasm_opsize = 2; - DisasmMove(); -} - -LOCALPROCUSEDONCE DisasmMoveQ(void) -{ - /* MoveQ 0111ddd0nnnnnnnn */ - DisasmStartOne("MOVEQ #"); - dbglog_writeHex(ui5r_FromSByte(Disasm_opcode)); - dbglog_writeCStr(", D"); - dbglog_writeHex(Disasm_rg9); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmAddEaR(void) -{ - DisasmEaD_xxxxdddxssmmmrrr("ADD"); -} - -LOCALPROCUSEDONCE DisasmAddQ(void) -{ - /* AddQ 0101nnn0ssmmmrrr */ - Disasm_xxxxnnnxssmmmrrr("ADDQ"); -} - -LOCALPROCUSEDONCE DisasmAddI(void) -{ - DisasmI_xxxxxxxxssmmmrrr("ADDI"); -} - -LOCALPROCUSEDONCE DisasmAddREa(void) -{ - DisasmDEa_xxxxdddxssmmmrrr("ADD"); -} - -LOCALPROCUSEDONCE DisasmSubEaR(void) -{ - DisasmEaD_xxxxdddxssmmmrrr("SUB"); -} - -LOCALPROCUSEDONCE DisasmSubQ(void) -{ - /* SubQ 0101nnn1ssmmmrrr */ - Disasm_xxxxnnnxssmmmrrr("SUBQ"); -} - -LOCALPROCUSEDONCE DisasmSubI(void) -{ - DisasmI_xxxxxxxxssmmmrrr("SUBI"); -} - -LOCALPROCUSEDONCE DisasmSubREa(void) -{ - DisasmDEa_xxxxdddxssmmmrrr("SUB"); -} - -LOCALPROCUSEDONCE DisasmLea(void) -{ - /* Lea 0100aaa111mmmrrr */ - DisasmStartOne("LEA "); - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeCStr(", A"); - dbglog_writeHex(Disasm_rg9); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmPEA(void) -{ - /* PEA 0100100001mmmrrr */ - DisasmStartOne("PEA "); - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmALine(void) -{ - DisasmStartOne("$"); - dbglog_writeHex(Disasm_opcode); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmBsr(void) -{ - ui5b src = ((ui5b)Disasm_opcode) & 255; - ui5r s = Disasm_pc; - - DisasmStartOne("BSR "); - if (src == 0) { - s += (si5b)(si4b)Disasm_nextiword(); - } else -#if Use68020 - if (src == 255) { - s += (si5b)Disasm_nextilong(); - /* ReportAbnormal("long branch in DoCode6"); */ - /* Used by various Apps */ - } else -#endif - { - s += (si5b)(si3b)src; - } - dbglog_writeHex(s); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmJsr(void) -{ - /* Jsr 0100111010mmmrrr */ - DisasmStartOne("JSR "); - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmLinkA6(void) -{ - DisasmStartOne("LINK A6, "); - dbglog_writeHex(Disasm_nextiword()); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmMOVEMRmM(void) -{ - /* MOVEM reg to mem 0100100011s100rrr */ - si4b z; - ui5r regmask; - - DisasmStartOne("MOVEM"); - if (Disasm_b76 == 2) { - dbglog_writeCStr(".W"); - } else { - dbglog_writeCStr(".L"); - } - dbglog_writeCStr(" "); - regmask = Disasm_nextiword(); - - for (z = 16; --z >= 0; ) { - if ((regmask & (1 << (15 - z))) != 0) { - if (z >= 8) { - dbglog_writeCStr("A"); - dbglog_writeHex(z - 8); - } else { - dbglog_writeCStr("D"); - dbglog_writeHex(z); - } - } - } - dbglog_writeCStr(", -(A"); - dbglog_writeHex(Disasm_reg); - dbglog_writeCStr(")"); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmMOVEMApR(void) -{ - /* MOVEM mem to reg 0100110011s011rrr */ - si4b z; - ui5r regmask; - - regmask = Disasm_nextiword(); - - DisasmStartOne("MOVEM"); - if (Disasm_b76 == 2) { - dbglog_writeCStr(".W"); - } else { - dbglog_writeCStr(".L"); - } - dbglog_writeCStr(" (A"); - dbglog_writeHex(Disasm_reg); - dbglog_writeCStr(")+, "); - - for (z = 0; z < 16; ++z) { - if ((regmask & (1 << z)) != 0) { - if (z >= 8) { - dbglog_writeCStr("A"); - dbglog_writeHex(z - 8); - } else { - dbglog_writeCStr("D"); - dbglog_writeHex(z); - } - } - } - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmUnlkA6(void) -{ - DisasmStartOne("UNLINK A6"); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmRts(void) -{ - /* Rts 0100111001110101 */ - DisasmStartOne("RTS"); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmJmp(void) -{ - /* JMP 0100111011mmmrrr */ - DisasmStartOne("JMP "); - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmClr(void) -{ - /* Clr 01000010ssmmmrrr */ - Disasm_xxxxxxxxssmmmrrr("CLR"); -} - -LOCALPROCUSEDONCE DisasmAddA(void) -{ - /* ADDA 1101dddm11mmmrrr */ - DisasmEaA_xxxxdddsxxmmmrrr("ADDA"); -} - -LOCALPROCUSEDONCE DisasmAddQA(void) -{ - /* 0101nnn0ss001rrr */ - DisasmStartOne("ADDQA #"); - dbglog_writeHex(Disasm_octdat(Disasm_rg9)); - dbglog_writeCStr(", A"); - dbglog_writeHex(Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmSubQA(void) -{ - /* 0101nnn1ss001rrr */ - DisasmStartOne("SUBQA #"); - dbglog_writeHex(Disasm_octdat(Disasm_rg9)); - dbglog_writeCStr(", A"); - dbglog_writeHex(Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmSubA(void) -{ - /* SUBA 1001dddm11mmmrrr */ - DisasmEaA_xxxxdddsxxmmmrrr("SUBA"); -} - -LOCALPROCUSEDONCE DisasmCmpA(void) -{ - DisasmStartOne("CMPA "); - Disasm_opsize = Disasm_b8 * 2 + 2; - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeCStr(", A"); - dbglog_writeHex(Disasm_rg9); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmAddXd(void) -{ - DisasmDD_xxxxdddxssxxxrrr("ADDX"); -} - -LOCALPROCUSEDONCE DisasmAddXm(void) -{ - DisasmAAs_xxxxdddxssxxxrrr("ADDX"); -} - -LOCALPROCUSEDONCE DisasmSubXd(void) -{ - DisasmDD_xxxxdddxssxxxrrr("SUBX"); -} - -LOCALPROCUSEDONCE DisasmSubXm(void) -{ - DisasmAAs_xxxxdddxssxxxrrr("SUBX"); -} - -LOCALPROC DisasmBinOp1(ui5r x) -{ - if (Disasm_b8) { - switch (x) { - case 0: - DisasmStartOne("ASR"); - break; - case 1: - DisasmStartOne("LSR"); - break; - case 2: - DisasmStartOne("RXR"); - break; - case 3: - DisasmStartOne("ROR"); - break; - default: - /* should not get here */ - break; - } - } else { - switch (x) { - case 0: - DisasmStartOne("ASL"); - break; - case 1: - DisasmStartOne("LSL"); - break; - case 2: - DisasmStartOne("RXL"); - break; - case 3: - DisasmStartOne("ROL"); - break; - default: - /* should not get here */ - break; - } - } -} - -LOCALPROCUSEDONCE DisasmRolopNM(void) -{ - DisasmBinOp1(Disasm_rg9); - dbglog_writeCStr(" "); - Disasm_opsize = 2; - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmRolopND(void) -{ - /* 1110cccdss0ttddd */ - DisasmBinOp1(Disasm_mode & 3); - DisasmOpSizeFromb76(); - dbglog_writeCStr(" #"); - dbglog_writeHex(Disasm_octdat(Disasm_rg9)); - dbglog_writeCStr(", "); - DisasmModeRegister(0, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmRolopDD(void) -{ - /* 1110rrrdss1ttddd */ - DisasmBinOp1(Disasm_mode & 3); - DisasmOpSizeFromb76(); - dbglog_writeCStr(" "); - DisasmModeRegister(0, Disasm_rg9); - dbglog_writeCStr(", "); - DisasmModeRegister(0, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROC DisasmBinBitOp1(void) -{ - switch (Disasm_b76) { - case 0: - DisasmStartOne("BTST"); - break; - case 1: - DisasmStartOne("BCHG"); - break; - case 2: - DisasmStartOne("BCLR"); - break; - case 3: - DisasmStartOne("BSET"); - break; - default: - /* should not get here */ - break; - } -} - -LOCALPROCUSEDONCE DisasmBitOpDD(void) -{ - /* dynamic bit, Opcode = 0000ddd1tt000rrr */ - DisasmBinBitOp1(); - Disasm_opsize = 4; - dbglog_writeCStr(" "); - DisasmModeRegister(0, Disasm_rg9); - dbglog_writeCStr(", "); - DisasmModeRegister(0, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmBitOpDM(void) -{ - /* dynamic bit, Opcode = 0000ddd1ttmmmrrr */ - DisasmBinBitOp1(); - Disasm_opsize = 1; - dbglog_writeCStr(" "); - DisasmModeRegister(0, Disasm_rg9); - dbglog_writeCStr(", "); - DisasmModeRegister(Disasm_mode, Disasm_rg9); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmBitOpND(void) -{ - /* static bit 00001010tt000rrr */ - DisasmBinBitOp1(); - Disasm_opsize = 4; - dbglog_writeCStr(" #"); - dbglog_writeHex(ui5r_FromSByte(Disasm_nextibyte())); - dbglog_writeCStr(", "); - DisasmModeRegister(0, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmBitOpNM(void) -{ - /* static bit 00001010ttmmmrrr */ - DisasmBinBitOp1(); - Disasm_opsize = 1; - dbglog_writeCStr(" #"); - dbglog_writeHex(ui5r_FromSByte(Disasm_nextibyte())); - dbglog_writeCStr(", "); - DisasmModeRegister(Disasm_mode, Disasm_rg9); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmAndI(void) -{ - DisasmI_xxxxxxxxssmmmrrr("ANDI"); -} - -LOCALPROCUSEDONCE DisasmAndDEa(void) -{ - /* And 1100ddd1ssmmmrrr */ - DisasmDEa_xxxxdddxssmmmrrr("AND"); -} - -LOCALPROCUSEDONCE DisasmAndEaD(void) -{ - /* And 1100ddd0ssmmmrrr */ - DisasmEaD_xxxxdddxssmmmrrr("AND"); -} - -LOCALPROCUSEDONCE DisasmOrI(void) -{ - DisasmI_xxxxxxxxssmmmrrr("ORI"); -} - -LOCALPROCUSEDONCE DisasmOrDEa(void) -{ - /* OR 1000ddd1ssmmmrrr */ - DisasmDEa_xxxxdddxssmmmrrr("OR"); -} - -LOCALPROCUSEDONCE DisasmOrEaD(void) -{ - /* OR 1000ddd0ssmmmrrr */ - DisasmEaD_xxxxdddxssmmmrrr("OR"); -} - -LOCALPROCUSEDONCE DisasmEorI(void) -{ - DisasmI_xxxxxxxxssmmmrrr("EORI"); -} - -LOCALPROCUSEDONCE DisasmEor(void) -{ - /* Eor 1011ddd1ssmmmrrr */ - DisasmDEa_xxxxdddxssmmmrrr("EOR"); -} - -LOCALPROCUSEDONCE DisasmNot(void) -{ - /* Not 01000110ssmmmrrr */ - Disasm_xxxxxxxxssmmmrrr("NOT"); -} - -LOCALPROCUSEDONCE DisasmScc(void) -{ - /* Scc 0101cccc11mmmrrr */ - Disasm_opsize = 1; - DisasmStartOne("S"); - DisasmCC(); - dbglog_writeCStr(" "); - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmEXTL(void) -{ - DisasmStartOne("EXT.L D"); - dbglog_writeHex(Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmEXTW(void) -{ - DisasmStartOne("EXT.W D"); - dbglog_writeHex(Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmNeg(void) -{ - /* Neg 01000100ssmmmrrr */ - Disasm_xxxxxxxxssmmmrrr("NEG"); -} - -LOCALPROCUSEDONCE DisasmNegX(void) -{ - /* NegX 01000000ssmmmrrr */ - Disasm_xxxxxxxxssmmmrrr("NEGX"); -} - -LOCALPROCUSEDONCE DisasmMulU(void) -{ - /* MulU 1100ddd011mmmrrr */ - Disasm_opsize = 2; - DisasmStartOne("MULU "); - - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeCStr(", "); - DisasmModeRegister(0, Disasm_rg9); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmMulS(void) -{ - /* MulS 1100ddd111mmmrrr */ - Disasm_opsize = 2; - DisasmStartOne("MULS "); - - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeCStr(", "); - DisasmModeRegister(0, Disasm_rg9); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmDivU(void) -{ - /* DivU 1000ddd011mmmrrr */ - - Disasm_opsize = 2; - DisasmStartOne("DIVU "); - - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeCStr(", "); - DisasmModeRegister(0, Disasm_rg9); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmDivS(void) -{ - /* DivS 1000ddd111mmmrrr */ - - Disasm_opsize = 2; - DisasmStartOne("DIVS "); - - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeCStr(", "); - DisasmModeRegister(0, Disasm_rg9); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmExgdd(void) -{ - /* Exg 1100ddd101000rrr */ - - Disasm_opsize = 4; - DisasmStartOne("EXG "); - DisasmModeRegister(0, Disasm_rg9); - dbglog_writeCStr(", "); - DisasmModeRegister(0, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmExgaa(void) -{ - /* Exg 1100ddd101001rrr */ - - Disasm_opsize = 4; - DisasmStartOne("EXG "); - DisasmModeRegister(1, Disasm_rg9); - dbglog_writeCStr(", "); - DisasmModeRegister(1, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmExgda(void) -{ - /* Exg 1100ddd110001rrr */ - - Disasm_opsize = 4; - DisasmStartOne("EXG "); - DisasmModeRegister(0, Disasm_rg9); - dbglog_writeCStr(", "); - DisasmModeRegister(1, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmMoveCCREa(void) -{ - /* Move from CCR 0100001011mmmrrr */ - Disasm_opsize = 2; - DisasmStartOne("MOVE CCR, "); - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmMoveEaCR(void) -{ - /* 0100010011mmmrrr */ - Disasm_opsize = 2; - DisasmStartOne("MOVE "); - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeCStr(", CCR"); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmMoveSREa(void) -{ - /* Move from SR 0100000011mmmrrr */ - Disasm_opsize = 2; - DisasmStartOne("MOVE SR, "); - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmMoveEaSR(void) -{ - /* 0100011011mmmrrr */ - Disasm_opsize = 2; - DisasmStartOne("MOVE "); - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeCStr(", SR"); - dbglog_writeReturn(); -} - -LOCALPROC DisasmBinOpStatusCCR(void) -{ - switch (Disasm_rg9) { - case 0 : - DisasmStartOne("OR"); - break; - case 1 : - DisasmStartOne("AND"); - break; - case 5 : - DisasmStartOne("EOR"); - break; - default: /* should not happen */ - break; - } - DisasmOpSizeFromb76(); - dbglog_writeCStr(" #"); - dbglog_writeHex(ui5r_FromSWord(Disasm_nextiword())); - if (Disasm_b76 != 0) { - dbglog_writeCStr(", SR"); - } else { - dbglog_writeCStr(", CCR"); - } - dbglog_writeReturn(); -} - -LOCALPROC disasmreglist(si4b direction, ui5b m1, ui5b r1) -{ - si4b z; - ui5r regmask; - - DisasmStartOne("MOVEM"); - - regmask = Disasm_nextiword(); - Disasm_opsize = 2 * Disasm_b76 - 2; - - if (Disasm_opsize == 2) { - dbglog_writeCStr(".W"); - } else { - dbglog_writeCStr(".L"); - } - - dbglog_writeCStr(" "); - - if (direction != 0) { - DisasmModeRegister(m1, r1); - dbglog_writeCStr(", "); - } - - for (z = 0; z < 16; ++z) { - if ((regmask & (1 << z)) != 0) { - if (z >= 8) { - dbglog_writeCStr("A"); - dbglog_writeHex(z - 8); - } else { - dbglog_writeCStr("D"); - dbglog_writeHex(z); - } - } - } - - if (direction == 0) { - dbglog_writeCStr(", "); - DisasmModeRegister(m1, r1); - } - - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmMOVEMrm(void) -{ - /* MOVEM reg to mem 010010001ssmmmrrr */ - disasmreglist(0, Disasm_mode, Disasm_reg); -} - -LOCALPROCUSEDONCE DisasmMOVEMmr(void) -{ - /* MOVEM mem to reg 0100110011smmmrrr */ - disasmreglist(1, Disasm_mode, Disasm_reg); -} - -LOCALPROC DisasmByteBinOp(char *s, ui5b m1, ui5b r1, ui5b m2, ui5b r2) -{ - DisasmStartOne(s); - dbglog_writeCStr(" "); - DisasmOpSizeFromb76(); - DisasmModeRegister(m1, r1); - dbglog_writeCStr(", "); - DisasmModeRegister(m2, r2); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmAbcdr(void) -{ - /* ABCD 1100ddd100000rrr */ - DisasmByteBinOp("ABCD", 0, Disasm_reg, 0, Disasm_rg9); -} - -LOCALPROCUSEDONCE DisasmAbcdm(void) -{ - /* ABCD 1100ddd100001rrr */ - DisasmByteBinOp("ABCD", 4, Disasm_reg, 4, Disasm_rg9); -} - -LOCALPROCUSEDONCE DisasmSbcdr(void) -{ - /* SBCD 1000xxx100000xxx */ - DisasmByteBinOp("ABCD", 0, Disasm_reg, 0, Disasm_rg9); -} - -LOCALPROCUSEDONCE DisasmSbcdm(void) -{ - /* SBCD 1000xxx100001xxx */ - DisasmByteBinOp("ABCD", 4, Disasm_reg, 4, Disasm_rg9); -} - -LOCALPROCUSEDONCE DisasmNbcd(void) -{ - /* Nbcd 0100100000mmmrrr */ - Disasm_xxxxxxxxssmmmrrr("NBCD"); -} - -LOCALPROCUSEDONCE DisasmRte(void) -{ - /* Rte 0100111001110011 */ - DisasmStartOne("RTE"); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmNop(void) -{ - /* Nop 0100111001110001 */ - DisasmStartOne("NOP"); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmMoveP(void) -{ - /* MoveP 0000ddd1mm001aaa */ - - DisasmStartOne("MOVEP"); - if (0 == (Disasm_b76 & 1)) { - Disasm_opsize = 2; - dbglog_writeCStr(".W"); - } else { - Disasm_opsize = 4; - dbglog_writeCStr(".L"); - } - dbglog_writeCStr(" "); - if (Disasm_b76 < 2) { - DisasmModeRegister(5, Disasm_reg); - dbglog_writeCStr(", "); - DisasmModeRegister(0, Disasm_rg9); - } else { - DisasmModeRegister(0, Disasm_rg9); - dbglog_writeCStr(", "); - DisasmModeRegister(5, Disasm_reg); - } - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmIllegal(void) -{ - DisasmStartOne("ILLEGAL"); - dbglog_writeReturn(); -} - -LOCALPROC DisasmCheck(void) -{ - DisasmStartOne("CHK"); - if (2 == Disasm_opsize) { - dbglog_writeCStr(".W"); - } else { - dbglog_writeCStr(".L"); - } - dbglog_writeCStr(" "); - - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeCStr(", "); - DisasmModeRegister(0, Disasm_rg9); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmChkW(void) -{ - /* Chk.W 0100ddd110mmmrrr */ - Disasm_opsize = 2; - DisasmCheck(); -} - -LOCALPROCUSEDONCE DisasmTrap(void) -{ - /* Trap 010011100100vvvv */ - DisasmStartOne("TRAP "); - dbglog_writeHex(Disasm_opcode & 15); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmTrapV(void) -{ - /* TrapV 0100111001110110 */ - DisasmStartOne("TRAPV"); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmRtr(void) -{ - /* Rtr 0100111001110111 */ - DisasmStartOne("RTR"); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmLink(void) -{ - DisasmStartOne("LINK A"); - dbglog_writeHex(Disasm_reg); - dbglog_writeCStr(", "); - dbglog_writeHex(Disasm_nextiword()); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmUnlk(void) -{ - DisasmStartOne("UNLINK A"); - dbglog_writeHex(Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmMoveRUSP(void) -{ - /* MOVE USP 0100111001100aaa */ - DisasmStartOne("MOVE A"); - dbglog_writeHex(Disasm_reg); - dbglog_writeCStr(", USP"); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmMoveUSPR(void) -{ - /* MOVE USP 0100111001101aaa */ - DisasmStartOne("MOVE USP, A"); - dbglog_writeHex(Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmTas(void) -{ - /* Tas 0100101011mmmrrr */ - Disasm_opsize = 1; - DisasmStartOne("TAS"); - dbglog_writeCStr(" "); - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmFLine(void) -{ - DisasmStartOne("$"); - dbglog_writeHex(Disasm_opcode); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmCallMorRtm(void) -{ - DisasmStartOne("CALLM #"); - dbglog_writeHex(Disasm_nextibyte()); - dbglog_writeCStr(", "); - DisasmModeRegister(Disasm_mode, Disasm_reg); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmStop(void) -{ - /* Stop 0100111001110010 */ - DisasmStartOne("STOP #"); - dbglog_writeHex(Disasm_nextiword()); - dbglog_writeReturn(); -} - -LOCALPROCUSEDONCE DisasmReset(void) -{ - /* Reset 0100111001100000 */ - DisasmStartOne("RESET"); - dbglog_writeReturn(); -} - -#if Use68020 -LOCALPROCUSEDONCE DisasmEXTBL(void) -{ - /* EXTB.L */ - DisasmStartOne("EXTB.L D"); - dbglog_writeHex(Disasm_reg); - dbglog_writeReturn(); -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DisasmTRAPcc(void) -{ - /* TRAPcc 0101cccc11111sss */ - - DisasmStartOne("TRAP"); - DisasmCC(); - - switch (Disasm_reg) { - case 2: - dbglog_writeCStr(" "); - dbglog_writeHex(Disasm_nextiword()); - break; - case 3: - dbglog_writeCStr(" "); - dbglog_writeHex(Disasm_nextilong()); - break; - case 4: - /* no optional data */ - break; - default: - /* illegal format */ - break; - } - - dbglog_writeReturn(); -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DisasmChkL(void) -{ - /* Chk.L 0100ddd100mmmrrr */ - Disasm_opsize = 4; - DisasmCheck(); -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DisasmBkpt(void) -{ - /* BKPT 0100100001001rrr */ - DisasmStartOne("BKPT #"); - dbglog_writeHex(Disasm_reg); - dbglog_writeReturn(); -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DisasmDivL(void) -{ - /* DIVU 0100110001mmmrrr 0rrr0s0000000rrr */ - /* DIVS 0100110001mmmrrr 0rrr1s0000000rrr */ - Disasm_opsize = 4; - DisasmStartOne("DIV"); - - { - ui4b extra = Disasm_nextiword(); - ui5b rDr = extra & 7; - ui5b rDq = (extra >> 12) & 7; - - if (extra & 0x0800) { - dbglog_writeCStr("S"); - } else { - dbglog_writeCStr("U"); - } - if (extra & 0x0400) { - dbglog_writeCStr("L"); - } - dbglog_writeCStr(".L "); - - DisasmModeRegister(Disasm_mode, Disasm_reg); - - dbglog_writeCStr(", "); - - if (rDr != rDq) { - dbglog_writeCStr("D"); - dbglog_writeHex(rDr); - dbglog_writeCStr(":"); - } - dbglog_writeCStr("D"); - dbglog_writeHex(rDq); - } - - dbglog_writeReturn(); -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DisasmMulL(void) -{ - /* MULU 0100110000mmmrrr 0rrr0s0000000rrr */ - /* MULS 0100110000mmmrrr 0rrr1s0000000rrr */ - - Disasm_opsize = 4; - DisasmStartOne("MUL"); - - { - ui4b extra = Disasm_nextiword(); - ui5b rhi = extra & 7; - ui5b rlo = (extra >> 12) & 7; - - if (extra & 0x0800) { - dbglog_writeCStr("S"); - } else { - dbglog_writeCStr("U"); - } - - dbglog_writeCStr(".L "); - - DisasmModeRegister(Disasm_mode, Disasm_reg); - - dbglog_writeCStr(", "); - - if (extra & 0x400) { - dbglog_writeCStr("D"); - dbglog_writeHex(rhi); - dbglog_writeCStr(":"); - } - dbglog_writeCStr("D"); - dbglog_writeHex(rlo); - } - - dbglog_writeReturn(); -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DisasmRtd(void) -{ - /* Rtd 0100111001110100 */ - DisasmStartOne("RTD #"); - dbglog_writeHex((si5b)(si4b)Disasm_nextiword()); - dbglog_writeReturn(); -} -#endif - -#if Use68020 -LOCALPROC DisasmControlReg(ui4r i) -{ - switch (i) { - case 0x0000: - dbglog_writeCStr("SFC"); - break; - case 0x0001: - dbglog_writeCStr("DFC"); - break; - case 0x0002: - dbglog_writeCStr("CACR"); - break; - case 0x0800: - dbglog_writeCStr("USP"); - break; - case 0x0801: - dbglog_writeCStr("VBR"); - break; - case 0x0802: - dbglog_writeCStr("CAAR"); - break; - case 0x0803: - dbglog_writeCStr("MSP"); - break; - case 0x0804: - dbglog_writeCStr("ISP"); - break; - default: - dbglog_writeCStr("???"); - break; - } -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DisasmMoveC(void) -{ - /* MOVEC 010011100111101m */ - DisasmStartOne("MOVEC "); - - { - ui4b src = Disasm_nextiword(); - int regno = (src >> 12) & 0x0F; - switch (Disasm_reg) { - case 2: - DisasmControlReg(src & 0x0FFF); - dbglog_writeCStr(", "); - if (regno < 8) { - dbglog_writeCStr("D"); - } else { - dbglog_writeCStr("A"); - } - dbglog_writeHex(regno & 7); - break; - case 3: - if (regno < 8) { - dbglog_writeCStr("D"); - } else { - dbglog_writeCStr("A"); - } - dbglog_writeHex(regno & 7); - - dbglog_writeCStr(", "); - - DisasmControlReg(src & 0x0FFF); - break; - default: - /* illegal */ - break; - } - } - - dbglog_writeReturn(); -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DisasmLinkL(void) -{ - /* Link.L 0100100000001rrr */ - DisasmStartOne("LINK.L A"); - dbglog_writeHex(Disasm_reg); - dbglog_writeCStr(", "); - dbglog_writeHex(Disasm_nextilong()); - dbglog_writeReturn(); -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DisasmPack(void) -{ - DisasmStartOne("PACK ???"); - dbglog_writeReturn(); - /* DoCodePack */ -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DisasmUnpk(void) -{ - DisasmStartOne("UNPK ???"); - dbglog_writeReturn(); - /* DoCodeUnpk */ -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DisasmCHK2orCMP2(void) -{ - DisasmStartOne("CHK2/CMP2 ???"); - dbglog_writeReturn(); - /* DoCHK2orCMP2 */ -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DisasmCAS2(void) -{ - DisasmStartOne("CAS2 ???"); - dbglog_writeReturn(); - /* DoCAS2 */ -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DisasmCAS(void) -{ - DisasmStartOne("CAS ???"); - dbglog_writeReturn(); - /* DoDoCAS */ -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DisasmMOVES(void) -{ - DisasmStartOne("MOVES ???"); - dbglog_writeReturn(); - /* DoMOVES */ -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DisasmBitField(void) -{ - DisasmStartOne("BitField ???"); - dbglog_writeReturn(); - /* DoBitField */ -} -#endif - -LOCALFUNC blnr IsValidAddrMode(void) -{ - return (Disasm_mode != 7) || (Disasm_reg < 5); -} - -LOCALFUNC blnr IsValidDstAddrMode(void) -{ - return (Disasm_md6 != 7) || (Disasm_rg9 < 2); -} - -LOCALFUNC MayNotInline blnr IsValidDataAltAddrMode(void) -{ - blnr IsOk; - - switch (Disasm_mode) { - case 1: - default: /* keep compiler happy */ - IsOk = falseblnr; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - IsOk = trueblnr; - break; - case 7: - IsOk = Disasm_reg < 2; - break; - } - - return IsOk; -} - -LOCALFUNC MayNotInline blnr IsValidDataAddrMode(void) -{ - blnr IsOk; - - switch (Disasm_mode) { - case 1: - default: /* keep compiler happy */ - IsOk = falseblnr; - break; - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - IsOk = trueblnr; - break; - case 7: - IsOk = Disasm_reg < 5; - break; - } - - return IsOk; -} - -LOCALFUNC MayNotInline blnr IsValidControlAddrMode(void) -{ - blnr IsOk; - - switch (Disasm_mode) { - case 0: - case 1: - case 3: - case 4: - default: /* keep compiler happy */ - IsOk = falseblnr; - break; - case 2: - case 5: - case 6: - IsOk = trueblnr; - break; - case 7: - IsOk = Disasm_reg < 4; - break; - } - - return IsOk; -} - -LOCALFUNC MayNotInline blnr IsValidControlAltAddrMode(void) -{ - blnr IsOk; - - switch (Disasm_mode) { - case 0: - case 1: - case 3: - case 4: - default: /* keep compiler happy */ - IsOk = falseblnr; - break; - case 2: - case 5: - case 6: - IsOk = trueblnr; - break; - case 7: - IsOk = Disasm_reg < 2; - break; - } - - return IsOk; -} - -LOCALFUNC MayNotInline blnr IsValidAltMemAddrMode(void) -{ - blnr IsOk; - - switch (Disasm_mode) { - case 0: - case 1: - default: /* keep compiler happy */ - IsOk = falseblnr; - break; - case 2: - case 3: - case 4: - case 5: - case 6: - IsOk = trueblnr; - break; - case 7: - IsOk = Disasm_reg < 2; - break; - } - - return IsOk; -} - -LOCALPROC DisasmCode0(void) -{ - if (Disasm_b8 == 1) { - if (Disasm_mode == 1) { - /* MoveP 0000ddd1mm001aaa */ - DisasmMoveP(); - } else { - /* dynamic bit, Opcode = 0000ddd1ttmmmrrr */ - if (Disasm_mode == 0) { - DisasmBitOpDD(); - } else { - if (Disasm_b76 == 0) { - if (IsValidDataAddrMode()) { - DisasmBitOpDM(); - } else { - DisasmIllegal(); - } - } else { - if (IsValidDataAltAddrMode()) { - DisasmBitOpDM(); - } else { - DisasmIllegal(); - } - } - } - } - } else { - if (Disasm_rg9 == 4) { - /* static bit 00001010ssmmmrrr */ - if (Disasm_mode == 0) { - DisasmBitOpND(); - } else { - if (Disasm_b76 == 0) { - if ((Disasm_mode == 7) && (Disasm_reg == 4)) { - DisasmIllegal(); - } else { - if (IsValidDataAddrMode()) { - DisasmBitOpNM(); - } else { - DisasmIllegal(); - } - } - } else { - if (IsValidDataAltAddrMode()) { - DisasmBitOpNM(); - } else { - DisasmIllegal(); - } - } - } - } else - if (Disasm_b76 == 3) { -#if Use68020 - if (Disasm_rg9 < 3) { - /* CHK2 or CMP2 00000ss011mmmrrr */ - if (IsValidControlAddrMode()) { - DisasmCHK2orCMP2(); - } else { - DisasmIllegal(); - } - } else - if (Disasm_rg9 >= 5) { - if ((Disasm_mode == 7) && (Disasm_reg == 4)) { - /* CAS2 00001ss011111100 */ - DisasmCAS2(); - } else { - /* CAS 00001ss011mmmrrr */ - DisasmCAS2(); - } - } else - if (Disasm_rg9 == 3) { - /* CALLM or RTM 0000011011mmmrrr */ - DisasmCallMorRtm(); - } else -#endif - { - DisasmIllegal(); - } - } else - if (Disasm_rg9 == 6) { - /* CMPI 00001100ssmmmrrr */ - if (IsValidDataAltAddrMode()) { - DisasmCmpI(); - } else { - DisasmIllegal(); - } - } else if (Disasm_rg9 == 7) { -#if Use68020 - /* MoveS 00001110ssmmmrrr */ - if (IsValidAltMemAddrMode()) { - DisasmMoveSREa(); - } else { - DisasmIllegal(); - } -#else - DisasmIllegal(); -#endif - } else { - if ((Disasm_mode == 7) && (Disasm_reg == 4)) { - switch (Disasm_rg9) { - case 0: - case 1: - case 5: - DisasmBinOpStatusCCR(); - break; - default: - DisasmIllegal(); - break; - } - } else { - if (! IsValidDataAltAddrMode()) { - DisasmIllegal(); - } else { - switch (Disasm_rg9) { - case 0: - DisasmOrI(); - break; - case 1: - DisasmAndI(); - break; - case 2: - DisasmSubI(); - break; - case 3: - DisasmAddI(); - break; - case 5: - DisasmEorI(); - break; - default: - /* - for compiler. - should be 0, 1, 2, 3, or 5 - */ - DisasmIllegal(); - break; - } - } - } - } - } -} - -LOCALPROC DisasmCode1(void) -{ - if ((Disasm_mode == 1) || ! IsValidAddrMode()) { - DisasmIllegal(); - } else if (Disasm_md6 == 1) { /* MOVEA */ - DisasmIllegal(); - } else if (! IsValidDstAddrMode()) { - DisasmIllegal(); - } else { - DisasmMoveB(); - } -} - -LOCALPROC DisasmCode2(void) -{ - if (Disasm_md6 == 1) { /* MOVEA */ - if (IsValidAddrMode()) { - DisasmMoveAL(); - } else { - DisasmIllegal(); - } - } else if (! IsValidAddrMode()) { - DisasmIllegal(); - } else if (! IsValidDstAddrMode()) { - DisasmIllegal(); - } else { - DisasmMoveL(); - } -} - -LOCALPROC DisasmCode3(void) -{ - if (Disasm_md6 == 1) { /* MOVEA */ - if (IsValidAddrMode()) { - DisasmMoveAW(); - } else { - DisasmIllegal(); - } - } else if (! IsValidAddrMode()) { - DisasmIllegal(); - } else if (! IsValidDstAddrMode()) { - DisasmIllegal(); - } else { - DisasmMoveW(); - } -} - -LOCALPROC DisasmCode4(void) -{ - if (Disasm_b8 != 0) { - switch (Disasm_b76) { - case 0: -#if Use68020 - /* Chk.L 0100ddd100mmmrrr */ - if (IsValidDataAddrMode()) { - DisasmChkL(); - } else { - DisasmIllegal(); - } -#else - DisasmIllegal(); -#endif - break; - case 1: - DisasmIllegal(); - break; - case 2: - /* Chk.W 0100ddd110mmmrrr */ - if (IsValidDataAddrMode()) { - DisasmChkW(); - } else { - DisasmIllegal(); - } - break; - case 3: - default: /* keep compiler happy */ -#if Use68020 - if ((0 == Disasm_mode) && (4 == Disasm_rg9)) { - DisasmEXTBL(); - } else -#endif - { - /* Lea 0100aaa111mmmrrr */ - if (IsValidControlAddrMode()) { - DisasmLea(); - } else { - DisasmIllegal(); - } - } - break; - } - } else { - switch (Disasm_rg9) { - case 0: - if (Disasm_b76 != 3) { - /* NegX 01000000ssmmmrrr */ - if (IsValidDataAltAddrMode()) { - DisasmNegX(); - } else { - DisasmIllegal(); - } - } else { -#if Use68020 -/* reference seems incorrect to say not for 68000 */ -#endif - /* Move from SR 0100000011mmmrrr */ - if (IsValidDataAltAddrMode()) { - DisasmMoveSREa(); - } else { - DisasmIllegal(); - } - } - break; - case 1: - if (Disasm_b76 != 3) { - /* Clr 01000010ssmmmrrr */ - if (IsValidDataAltAddrMode()) { - DisasmClr(); - } else { - DisasmIllegal(); - } - } else { -#if Use68020 - /* Move from CCR 0100001011mmmrrr */ - if (IsValidDataAltAddrMode()) { - DisasmMoveCCREa(); - } else { - DisasmIllegal(); - } -#else - DisasmIllegal(); -#endif - } - break; - case 2: - if (Disasm_b76 != 3) { - /* Neg 01000100ssmmmrrr */ - if (IsValidDataAltAddrMode()) { - DisasmNeg(); - } else { - DisasmIllegal(); - } - } else { - /* Move to CCR 0100010011mmmrrr */ - if (IsValidDataAddrMode()) { - DisasmMoveEaCR(); - } else { - DisasmIllegal(); - } - } - break; - case 3: - if (Disasm_b76 != 3) { - /* Not 01000110ssmmmrrr */ - if (IsValidDataAltAddrMode()) { - DisasmNot(); - } else { - DisasmIllegal(); - } - } else { - /* Move from SR 0100011011mmmrrr */ - if (IsValidDataAddrMode()) { - DisasmMoveEaSR(); - } else { - DisasmIllegal(); - } - } - break; - case 4: - switch (Disasm_b76) { - case 0: -#if Use68020 - if (Disasm_mode == 1) { - /* Link.L 0100100000001rrr */ - DisasmLinkL(); - } else -#endif - { - /* Nbcd 0100100000mmmrrr */ - if (IsValidDataAltAddrMode()) { - DisasmNbcd(); - } else { - DisasmIllegal(); - } - } - break; - case 1: - if (Disasm_mode == 0) { - /* Swap 0100100001000rrr */ - DisasmSwap(); - } else -#if Use68020 - if (Disasm_mode == 1) { - DisasmBkpt(); - } else -#endif - { - /* PEA 0100100001mmmrrr */ - if (IsValidControlAddrMode()) { - DisasmPEA(); - } else { - DisasmIllegal(); - } - } - break; - case 2: - if (Disasm_mode == 0) { - /* EXT.W */ - DisasmEXTW(); - } else { - /* - MOVEM Disasm_reg - to mem 01001d001ssmmmrrr - */ - if (Disasm_mode == 4) { - DisasmMOVEMRmM(); - } else { - if (IsValidControlAltAddrMode()) { - DisasmMOVEMrm(); - } else { - DisasmIllegal(); - } - } - } - break; - case 3: - default: /* keep compiler happy */ - if (Disasm_mode == 0) { - /* EXT.L */ - DisasmEXTL(); - } else { - /* - MOVEM Disasm_reg - to mem 01001d001ssmmmrrr - */ - if (Disasm_mode == 4) { - DisasmMOVEMRmM(); - } else { - if (IsValidControlAltAddrMode()) { - DisasmMOVEMrm(); - } else { - DisasmIllegal(); - } - } - } - break; - } - break; - case 5: - if (Disasm_b76 == 3) { - if ((Disasm_mode == 7) && (Disasm_reg == 4)) { - /* the ILLEGAL instruction */ - DisasmIllegal(); - } else { - /* Tas 0100101011mmmrrr */ - if (IsValidDataAltAddrMode()) { - DisasmTas(); - } else { - DisasmIllegal(); - } - } - } else { - /* Tst 01001010ssmmmrrr */ - if (Disasm_b76 == 0) { - if (IsValidDataAltAddrMode()) { - DisasmTst(); - } else { - DisasmIllegal(); - } - } else { - if (IsValidAddrMode()) { - DisasmTst(); - } else { - DisasmIllegal(); - } - } - } - break; - case 6: - if (((Disasm_opcode >> 7) & 1) == 1) { - /* MOVEM mem to Disasm_reg 0100110011smmmrrr */ - if (Disasm_mode == 3) { - DisasmMOVEMApR(); - } else { - if (IsValidControlAddrMode()) { - DisasmMOVEMmr(); - } else { - DisasmIllegal(); - } - } - } else { -#if Use68020 - if (((Disasm_opcode >> 6) & 1) == 1) { - /* DIVU 0100110001mmmrrr 0rrr0s0000000rrr */ - /* DIVS 0100110001mmmrrr 0rrr1s0000000rrr */ - DisasmDivL(); - } else { - /* MULU 0100110000mmmrrr 0rrr0s0000000rrr */ - /* MULS 0100110000mmmrrr 0rrr1s0000000rrr */ - DisasmMulL(); - } -#else - DisasmIllegal(); -#endif - } - break; - case 7: - default: /* keep compiler happy */ - switch (Disasm_b76) { - case 0: - DisasmIllegal(); - break; - case 1: - switch (Disasm_mode) { - case 0: - case 1: - /* Trap 010011100100vvvv */ - DisasmTrap(); - break; - case 2: - /* Link */ - if (Disasm_reg == 6) { - DisasmLinkA6(); - } else { - DisasmLink(); - } - break; - case 3: - /* Unlk */ - if (Disasm_reg == 6) { - DisasmUnlkA6(); - } else { - DisasmUnlk(); - } - break; - case 4: - /* MOVE USP 0100111001100aaa */ - DisasmMoveRUSP(); - break; - case 5: - /* MOVE USP 0100111001101aaa */ - DisasmMoveUSPR(); - break; - case 6: - switch (Disasm_reg) { - case 0: - /* Reset 0100111001100000 */ - DisasmReset(); - break; - case 1: - /* - Nop Opcode - = 0100111001110001 - */ - DisasmNop(); - break; - case 2: - /* Stop 0100111001110010 */ - DisasmStop(); - break; - case 3: - /* Rte 0100111001110011 */ - DisasmRte(); - break; - case 4: - /* Rtd 0100111001110100 */ -#if Use68020 - DisasmRtd(); -#else - DisasmIllegal(); -#endif - break; - case 5: - /* Rts 0100111001110101 */ - DisasmRts(); - break; - case 6: - /* TrapV 0100111001110110 */ - DisasmTrapV(); - break; - case 7: - default: /* keep compiler happy */ - /* Rtr 0100111001110111 */ - DisasmRtr(); - break; - } - break; - case 7: - default: /* keep compiler happy */ -#if Use68020 - /* MOVEC 010011100111101m */ - DisasmMoveC(); -#else - DisasmIllegal(); -#endif - break; - } - break; - case 2: - /* Jsr 0100111010mmmrrr */ - if (IsValidControlAddrMode()) { - DisasmJsr(); - } else { - DisasmIllegal(); - } - break; - case 3: - default: /* keep compiler happy */ - /* JMP 0100111011mmmrrr */ - if (IsValidControlAddrMode()) { - DisasmJmp(); - } else { - DisasmIllegal(); - } - break; - } - break; - } - } -} - -LOCALPROC DisasmCode5(void) -{ - if (Disasm_b76 == 3) { - if (Disasm_mode == 1) { - /* DBcc 0101cccc11001ddd */ - DisasmDBcc(); - } else { -#if Use68020 - if ((Disasm_mode == 7) && (Disasm_reg >= 2)) { - /* TRAPcc 0101cccc11111sss */ - DisasmTRAPcc(); - } else -#endif - { - /* Scc 0101cccc11mmmrrr */ - if (IsValidDataAltAddrMode()) { - DisasmScc(); - } else { - DisasmIllegal(); - } - } - } - } else { - if (Disasm_mode == 1) { - if (Disasm_b8 == 0) { - DisasmAddQA(); /* AddQA 0101nnn0ss001rrr */ - } else { - DisasmSubQA(); /* SubQA 0101nnn1ss001rrr */ - } - } else { - if (Disasm_b8 == 0) { - /* AddQ 0101nnn0ssmmmrrr */ - if (IsValidDataAltAddrMode()) { - DisasmAddQ(); - } else { - DisasmIllegal(); - } - } else { - /* SubQ 0101nnn1ssmmmrrr */ - if (IsValidDataAltAddrMode()) { - DisasmSubQ(); - } else { - DisasmIllegal(); - } - } - } - } -} - -LOCALPROC DisasmCode6(void) -{ - ui5b cond = (Disasm_opcode >> 8) & 15; - - if (cond == 1) { - /* Bsr 01100001nnnnnnnn */ - DisasmBsr(); - } else if (cond == 0) { - /* Bra 01100000nnnnnnnn */ - DisasmBcc(); - } else { - /* Bcc 0110ccccnnnnnnnn */ - DisasmBcc(); - } -} - -LOCALPROC DisasmCode7(void) -{ - if (Disasm_b8 == 0) { - DisasmMoveQ(); - } else { - DisasmIllegal(); - } -} - -LOCALPROC DisasmCode8(void) -{ - if (Disasm_b76 == 3) { - if (Disasm_b8 == 0) { - /* DivU 1000ddd011mmmrrr */ - if (IsValidDataAddrMode()) { - DisasmDivU(); - } else { - DisasmIllegal(); - } - } else { - /* DivS 1000ddd111mmmrrr */ - if (IsValidDataAddrMode()) { - DisasmDivS(); - } else { - DisasmIllegal(); - } - } - } else { - if (Disasm_b8 == 0) { - /* OR 1000ddd0ssmmmrrr */ - if (IsValidDataAddrMode()) { - DisasmOrEaD(); - } else { - DisasmIllegal(); - } - } else { - if (Disasm_mode < 2) { - switch (Disasm_b76) { - case 0: - /* SBCD 1000xxx10000mxxx */ - if (Disasm_mode == 0) { - DisasmSbcdr(); - } else { - DisasmSbcdm(); - } - break; -#if Use68020 - case 1: - /* PACK 1000rrr10100mrrr */ - DisasmPack(); - break; - case 2: - /* UNPK 1000rrr11000mrrr */ - DisasmUnpk(); - break; -#endif - default: - DisasmIllegal(); - break; - } - } else { - /* OR 1000ddd1ssmmmrrr */ - if (IsValidDataAltAddrMode()) { - DisasmOrDEa(); - } else { - DisasmIllegal(); - } - } - } - } -} - -LOCALPROC DisasmCode9(void) -{ - if (Disasm_b76 == 3) { - /* SUBA 1001dddm11mmmrrr */ - if (IsValidAddrMode()) { - DisasmSubA(); - } else { - DisasmIllegal(); - } - } else { - if (Disasm_b8 == 0) { - /* SUB 1001ddd0ssmmmrrr */ - if (IsValidAddrMode()) { - DisasmSubEaR(); - } else { - DisasmIllegal(); - } - } else { - if (Disasm_mode == 0) { - /* SUBX 1001ddd1ss000rrr */ - DisasmSubXd(); - } else if (Disasm_mode == 1) { - /* SUBX 1001ddd1ss001rrr */ - DisasmSubXm(); - } else { - /* SUB 1001ddd1ssmmmrrr */ - if (IsValidAltMemAddrMode()) { - DisasmSubREa(); - } else { - DisasmIllegal(); - } - } - } - } -} - -LOCALPROC DisasmCodeA(void) -{ - DisasmALine(); -} - -LOCALPROC DisasmCodeB(void) -{ - if (Disasm_b76 == 3) { - /* CMPA 1011ddds11mmmrrr */ - if (IsValidAddrMode()) { - DisasmCmpA(); - } else { - DisasmIllegal(); - } - } else if (Disasm_b8 == 1) { - if (Disasm_mode == 1) { - /* CmpM 1011ddd1ss001rrr */ - DisasmCmpM(); - } else { - /* Eor 1011ddd1ssmmmrrr */ - if (IsValidDataAltAddrMode()) { - DisasmEor(); - } else { - DisasmIllegal(); - } - } - } else { - /* Cmp 1011ddd0ssmmmrrr */ - if (IsValidAddrMode()) { - DisasmCompare(); - } else { - DisasmIllegal(); - } - } -} - -LOCALPROC DisasmCodeC(void) -{ - if (Disasm_b76 == 3) { - if (Disasm_b8 == 0) { - /* MulU 1100ddd011mmmrrr */ - if (IsValidDataAddrMode()) { - DisasmMulU(); - } else { - DisasmIllegal(); - } - } else { - /* MulS 1100ddd111mmmrrr */ - if (IsValidDataAddrMode()) { - DisasmMulS(); - } else { - DisasmIllegal(); - } - } - } else { - if (Disasm_b8 == 0) { - /* And 1100ddd0ssmmmrrr */ - if (IsValidDataAddrMode()) { - DisasmAndEaD(); - } else { - DisasmIllegal(); - } - } else { - if (Disasm_mode < 2) { - switch (Disasm_b76) { - case 0: - /* ABCD 1100ddd10000mrrr */ - if (Disasm_mode == 0) { - DisasmAbcdr(); - } else { - DisasmAbcdm(); - } - break; - case 1: - /* Exg 1100ddd10100trrr */ - if (Disasm_mode == 0) { - DisasmExgdd(); - } else { - DisasmExgaa(); - } - break; - case 2: - default: /* keep compiler happy */ - if (Disasm_mode == 0) { - DisasmIllegal(); - } else { - /* Exg 1100ddd110001rrr */ - DisasmExgda(); - } - break; - } - } else { - /* And 1100ddd1ssmmmrrr */ - if (IsValidAltMemAddrMode()) { - DisasmAndDEa(); - } else { - DisasmIllegal(); - } - } - } - } -} - -LOCALPROC DisasmCodeD(void) -{ - if (Disasm_b76 == 3) { - /* ADDA 1101dddm11mmmrrr */ - if (IsValidAddrMode()) { - DisasmAddA(); - } else { - DisasmIllegal(); - } - } else { - if (Disasm_b8 == 0) { - /* ADD 1101ddd0ssmmmrrr */ - if (IsValidAddrMode()) { - DisasmAddEaR(); - } else { - DisasmIllegal(); - } - } else { - if (Disasm_mode == 0) { - DisasmAddXd(); - } else if (Disasm_mode == 1) { - DisasmAddXm(); - } else { - /* ADD 1101ddd1ssmmmrrr */ - if (IsValidAltMemAddrMode()) { - DisasmAddREa(); - } else { - DisasmIllegal(); - } - } - } - } -} - -LOCALPROC DisasmCodeE(void) -{ - if (Disasm_b76 == 3) { - if ((Disasm_opcode & 0x0800) != 0) { -#if Use68020 - /* 11101???11mmmrrr */ - switch (Disasm_mode) { - case 1: - case 3: - case 4: - default: /* keep compiler happy */ - DisasmIllegal(); - break; - case 0: - case 2: - case 5: - case 6: - DisasmBitField(); - break; - case 7: - switch (Disasm_reg) { - case 0: - case 1: - DisasmBitField(); - break; - case 2: - case 3: - switch ((Disasm_opcode >> 8) & 7) { - case 0: /* BFTST */ - case 1: /* BFEXTU */ - case 3: /* BFEXTS */ - case 5: /* BFFFO */ - DisasmBitField(); - break; - default: - DisasmIllegal(); - break; - } - break; - default: - DisasmIllegal(); - break; - } - break; - } -#else - DisasmIllegal(); -#endif - } else { - /* 11100ttd11mmmddd */ - if (IsValidAltMemAddrMode()) { - DisasmRolopNM(); - } else { - DisasmIllegal(); - } - } - } else { - if (Disasm_mode < 4) { - /* 1110cccdss0ttddd */ - DisasmRolopND(); - } else { - /* 1110rrrdss1ttddd */ - DisasmRolopDD(); - } - } -} - -LOCALPROC DisasmCodeF(void) -{ - DisasmFLine(); -} - -LOCALPROC m68k_Disasm_one(void) -{ - Disasm_opcode = Disasm_nextiword(); - - switch (Disasm_opcode >> 12) { - case 0x0: - DisasmCode0(); - break; - case 0x1: - DisasmCode1(); - break; - case 0x2: - DisasmCode2(); - break; - case 0x3: - DisasmCode3(); - break; - case 0x4: - DisasmCode4(); - break; - case 0x5: - DisasmCode5(); - break; - case 0x6: - DisasmCode6(); - break; - case 0x7: - DisasmCode7(); - break; - case 0x8: - DisasmCode8(); - break; - case 0x9: - DisasmCode9(); - break; - case 0xA: - DisasmCodeA(); - break; - case 0xB: - DisasmCodeB(); - break; - case 0xC: - DisasmCodeC(); - break; - case 0xD: - DisasmCodeD(); - break; - case 0xE: - DisasmCodeE(); - break; - case 0xF: - default: /* keep compiler happy */ - DisasmCodeF(); - break; - } -} - -#define Ln2SavedPCs 4 -#define NumSavedPCs (1 << Ln2SavedPCs) -#define SavedPCsMask (NumSavedPCs - 1) -LOCALVAR ui5r SavedPCs[NumSavedPCs]; -LOCALVAR ui5r SavedPCsIn = 0; -LOCALVAR ui5r SavedPCsOut = 0; - -#define DisasmIncludeCycles 0 - -LOCALPROCUSEDONCE DisasmOneAndBack(ui5r pc) -{ -#if DisasmIncludeCycles - dbglog_writeHex(GetCuriCount()); - dbglog_writeCStr(" "); -#endif - dbglog_writeHex(pc); - dbglog_writeCStr(" "); - Disasm_setpc(pc); - m68k_Disasm_one(); -} - -LOCALPROCUSEDONCE DisasmSavedPCs(void) -{ - ui5r n = SavedPCsIn - SavedPCsOut; - - if (n != 0) { - ui5r pc; -#if DisasmIncludeCycles - ui5r i; -#endif - blnr Skipped = falseblnr; - ui5r j = SavedPCsOut; - - SavedPCsOut = SavedPCsIn; - /* - do first, prevent recursion - in case of error while disassembling. - (i.e. failure to read emulated memory.) - */ - -#if DisasmIncludeCycles - i = GetCuriCount(); -#endif - - if (n > NumSavedPCs) { - n = NumSavedPCs; - j = SavedPCsIn - NumSavedPCs; - dbglog_writeReturn(); - Skipped = trueblnr; - } - - do { - --n; - pc = SavedPCs[j & SavedPCsMask]; -#if DisasmIncludeCycles - dbglog_writeHex(i /* - n */); - dbglog_writeCStr("-? "); -#endif - dbglog_writeHex(pc); - dbglog_writeCStr(" "); - Disasm_setpc(pc); - m68k_Disasm_one(); - ++j; - } while (n != 0); - -#if 0 - if (Skipped) { - si4b z; - - for (z = 0; z < 16; ++z) { - if (z >= 8) { - dbglog_writeCStr(" A"); - dbglog_writeHex(z - 8); - } else { - dbglog_writeCStr(" D"); - dbglog_writeHex(z); - } - dbglog_writeCStr(" = "); - dbglog_writeHex(regs.regs[z]); - dbglog_writeReturn(); - } - } -#endif - } -} - -LOCALVAR ui5r DisasmCounter = 0; - -GLOBALPROC DisasmOneOrSave(ui5r pc) -{ - if (0 != DisasmCounter) { - DisasmOneAndBack(pc); - --DisasmCounter; - } else { - SavedPCs[SavedPCsIn & SavedPCsMask] = pc; - ++SavedPCsIn; - } -} - -GLOBALPROC m68k_WantDisasmContext(void) -{ - DisasmSavedPCs(); - DisasmCounter = /* 256 */ 128; -} +/* DISAM68K.c Copyright (C) 2010 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* DISAssemble Motorola 68K instructions. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "ENDIANAC.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "M68KITAB.h" #endif #include "DISAM68K.h" LOCALVAR ui5r Disasm_pc; /* don't use get_vm_byte/get_vm_word/get_vm_long so as to be sure of no side effects (if pc points to memory mapped device) */ LOCALVAR ui3p Disasm_pcp; LOCALVAR ui5r Disasm_pc_blockmask; LOCALVAR ui3b Disasm_pcp_dummy[2] = { 0, 0 }; IMPORTFUNC ATTep FindATTel(CPTR addr); LOCALPROC Disasm_Find_pcp(void) { ATTep p; p = FindATTel(Disasm_pc); if (0 == (p->Access & kATTA_readreadymask)) { Disasm_pcp = Disasm_pcp_dummy; Disasm_pc_blockmask = 0; } else { Disasm_pc_blockmask = p->usemask & ~ p->cmpmask; Disasm_pc_blockmask = Disasm_pc_blockmask & ~ (Disasm_pc_blockmask + 1); Disasm_pcp = p->usebase + (Disasm_pc & p->usemask); } } LOCALFUNC ui4r Disasm_nextiword(void) /* NOT sign extended */ { ui4r r = do_get_mem_word(Disasm_pcp); Disasm_pcp += 2; Disasm_pc += 2; if (0 == (Disasm_pc_blockmask & Disasm_pc)) { Disasm_Find_pcp(); } return r; } LOCALINLINEFUNC ui3r Disasm_nextibyte(void) { return (ui3b) Disasm_nextiword(); } LOCALFUNC ui5r Disasm_nextilong(void) { ui5r hi = Disasm_nextiword(); ui5r lo = Disasm_nextiword(); ui5r r = ((hi << 16) & 0xFFFF0000) | (lo & 0x0000FFFF); return r; } LOCALPROC Disasm_setpc(CPTR newpc) { if (newpc != Disasm_pc) { Disasm_pc = newpc; Disasm_Find_pcp(); } } LOCALVAR ui5b Disasm_opcode; LOCALVAR ui5b Disasm_opsize; #define Disasm_b76 ((Disasm_opcode >> 6) & 3) #define Disasm_b8 ((Disasm_opcode >> 8) & 1) #define Disasm_mode ((Disasm_opcode >> 3) & 7) #define Disasm_reg (Disasm_opcode & 7) #define Disasm_md6 ((Disasm_opcode >> 6) & 7) #define Disasm_rg9 ((Disasm_opcode >> 9) & 7) LOCALPROC DisasmOpSizeFromb76(void) { Disasm_opsize = 1 << Disasm_b76; switch (Disasm_opsize) { case 1 : dbglog_writeCStr(".B"); break; case 2 : dbglog_writeCStr(".W"); break; case 4 : dbglog_writeCStr(".L"); break; } } LOCALPROC DisasmModeRegister(ui5b themode, ui5b thereg) { switch (themode) { case 0 : dbglog_writeCStr("D"); dbglog_writeHex(thereg); break; case 1 : dbglog_writeCStr("A"); dbglog_writeHex(thereg); break; case 2 : dbglog_writeCStr("(A"); dbglog_writeHex(thereg); dbglog_writeCStr(")"); break; case 3 : dbglog_writeCStr("(A"); dbglog_writeHex(thereg); dbglog_writeCStr(")+"); break; case 4 : dbglog_writeCStr("-(A"); dbglog_writeHex(thereg); dbglog_writeCStr(")"); break; case 5 : dbglog_writeHex(Disasm_nextiword()); dbglog_writeCStr("(A"); dbglog_writeHex(thereg); dbglog_writeCStr(")"); break; case 6 : dbglog_writeCStr("???"); #if 0 ArgKind = AKMemory; ArgAddr.mem = get_disp_ea(m68k_areg(thereg)); #endif break; case 7 : switch (thereg) { case 0 : dbglog_writeCStr("("); dbglog_writeHex(Disasm_nextiword()); dbglog_writeCStr(")"); break; case 1 : dbglog_writeCStr("("); dbglog_writeHex(Disasm_nextilong()); dbglog_writeCStr(")"); break; case 2 : { ui5r s = Disasm_pc; s += ui5r_FromSWord(Disasm_nextiword()); dbglog_writeCStr("("); dbglog_writeHex(s); dbglog_writeCStr(")"); } break; case 3 : dbglog_writeCStr("???"); #if 0 ArgKind = AKMemory; s = get_disp_ea(Disasm_pc); #endif break; case 4 : dbglog_writeCStr("#"); if (Disasm_opsize == 2) { dbglog_writeHex(Disasm_nextiword()); } else if (Disasm_opsize < 2) { dbglog_writeHex(Disasm_nextibyte()); } else { dbglog_writeHex(Disasm_nextilong()); } break; } break; case 8 : dbglog_writeCStr("#"); dbglog_writeHex(thereg); break; } } LOCALPROC DisasmStartOne(char *s) { dbglog_writeCStr(s); } LOCALPROC Disasm_xxxxxxxxssmmmrrr(char *s) { DisasmStartOne(s); DisasmOpSizeFromb76(); dbglog_writeCStr(" "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROC DisasmEaD_xxxxdddxssmmmrrr(char *s) { DisasmStartOne(s); DisasmOpSizeFromb76(); dbglog_writeCStr(" "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", "); dbglog_writeCStr("D"); dbglog_writeHex(Disasm_rg9); dbglog_writeReturn(); } LOCALPROC DisasmI_xxxxxxxxssmmmrrr(char *s) { DisasmStartOne(s); DisasmOpSizeFromb76(); dbglog_writeCStr(" #"); if (Disasm_opsize == 2) { dbglog_writeHex(ui5r_FromSWord(Disasm_nextiword())); } else if (Disasm_opsize < 2) { dbglog_writeHex(ui5r_FromSByte(Disasm_nextibyte())); } else { dbglog_writeHex(ui5r_FromSLong(Disasm_nextilong())); } dbglog_writeCStr(", "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROC DisasmsAA_xxxxdddxssxxxrrr(char *s) { DisasmStartOne(s); DisasmOpSizeFromb76(); DisasmModeRegister(3, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(3, Disasm_rg9); dbglog_writeReturn(); } LOCALFUNC ui5r Disasm_octdat(ui5r x) { if (x == 0) { return 8; } else { return x; } } LOCALPROC Disasm_xxxxnnnxssmmmrrr(char *s) { DisasmStartOne(s); DisasmOpSizeFromb76(); dbglog_writeCStr(" #"); dbglog_writeHex(Disasm_octdat(Disasm_rg9)); dbglog_writeCStr(", "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROC DisasmDEa_xxxxdddxssmmmrrr(char *s) { DisasmStartOne(s); DisasmOpSizeFromb76(); dbglog_writeCStr(" D"); dbglog_writeHex(Disasm_rg9); dbglog_writeCStr(", "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROC DisasmEaA_xxxxdddsxxmmmrrr(char *s) { DisasmStartOne(s); Disasm_opsize = Disasm_b8 * 2 + 2; if (Disasm_opsize == 2) { dbglog_writeCStr(".W"); } else { dbglog_writeCStr(".L"); } dbglog_writeCStr(" "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", A"); dbglog_writeHex(Disasm_rg9); dbglog_writeReturn(); } LOCALPROC DisasmDD_xxxxdddxssxxxrrr(char *s) { DisasmStartOne(s); DisasmOpSizeFromb76(); dbglog_writeCStr(" "); DisasmModeRegister(0, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeReturn(); } LOCALPROC DisasmAAs_xxxxdddxssxxxrrr(char *s) { DisasmStartOne(s); DisasmOpSizeFromb76(); dbglog_writeCStr(" "); DisasmModeRegister(4, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(4, Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmTst(void) { /* Tst 01001010ssmmmrrr */ Disasm_xxxxxxxxssmmmrrr("TST"); } LOCALPROCUSEDONCE DisasmCompare(void) { /* Cmp 1011ddd0ssmmmrrr */ DisasmEaD_xxxxdddxssmmmrrr("CMP"); } LOCALPROCUSEDONCE DisasmCmpI(void) { /* CMPI 00001100ssmmmrrr */ DisasmI_xxxxxxxxssmmmrrr("CMP"); } LOCALPROCUSEDONCE DisasmCmpM(void) { /* CmpM 1011ddd1ss001rrr */ DisasmsAA_xxxxdddxssxxxrrr("CMP"); } LOCALPROC DisasmCC(void) { switch ((Disasm_opcode >> 8) & 15) { case 0: dbglog_writeCStr("T"); break; case 1: dbglog_writeCStr("F"); break; case 2: dbglog_writeCStr("HI"); break; case 3: dbglog_writeCStr("LS"); break; case 4: dbglog_writeCStr("CC"); break; case 5: dbglog_writeCStr("CS"); break; case 6: dbglog_writeCStr("NE"); break; case 7: dbglog_writeCStr("EQ"); break; case 8: dbglog_writeCStr("VC"); break; case 9: dbglog_writeCStr("VS"); break; case 10: dbglog_writeCStr("P"); break; case 11: dbglog_writeCStr("MI"); break; case 12: dbglog_writeCStr("GE"); break; case 13: dbglog_writeCStr("LT"); break; case 14: dbglog_writeCStr("GT"); break; case 15: dbglog_writeCStr("LE"); break; default: break; /* shouldn't get here */ } } LOCALPROCUSEDONCE DisasmBcc(void) { /* Bcc 0110ccccnnnnnnnn */ ui5b src = ((ui5b)Disasm_opcode) & 255; ui5r s = Disasm_pc; if (0 == ((Disasm_opcode >> 8) & 15)) { DisasmStartOne("BRA"); } else { DisasmStartOne("B"); DisasmCC(); } dbglog_writeCStr(" "); if (src == 0) { s += ui5r_FromSWord(Disasm_nextiword()); } else #if Use68020 if (src == 255) { s += ui5r_FromSLong(Disasm_nextilong()); /* ReportAbnormal("long branch in DoCode6"); */ /* Used by various Apps */ } else #endif { s += ui5r_FromSByte(src); } dbglog_writeHex(s); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmDBcc(void) { /* DBcc 0101cccc11001ddd */ ui5r s = Disasm_pc; DisasmStartOne("DB"); DisasmCC(); dbglog_writeCStr(" D"); dbglog_writeHex(Disasm_reg); dbglog_writeCStr(", "); s += (si5b)(si4b)Disasm_nextiword(); dbglog_writeHex(s); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmSwap(void) { /* Swap 0100100001000rrr */ DisasmStartOne("SWAP D"); dbglog_writeHex(Disasm_reg); dbglog_writeReturn(); } LOCALPROC DisasmMove(void) /* MOVE */ { DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(Disasm_md6, Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMoveL(void) { DisasmStartOne("MOVE.L "); Disasm_opsize = 4; DisasmMove(); } LOCALPROCUSEDONCE DisasmMoveW(void) { DisasmStartOne("MOVE.W "); Disasm_opsize = 2; DisasmMove(); } LOCALPROCUSEDONCE DisasmMoveB(void) { DisasmStartOne("MOVE.B "); Disasm_opsize = 1; DisasmMove(); } LOCALPROCUSEDONCE DisasmMoveAL(void) { DisasmStartOne("MOVEA.L "); Disasm_opsize = 4; DisasmMove(); } LOCALPROCUSEDONCE DisasmMoveAW(void) { DisasmStartOne("MOVEA.W "); Disasm_opsize = 2; DisasmMove(); } LOCALPROCUSEDONCE DisasmMoveQ(void) { /* MoveQ 0111ddd0nnnnnnnn */ DisasmStartOne("MOVEQ #"); dbglog_writeHex(ui5r_FromSByte(Disasm_opcode)); dbglog_writeCStr(", D"); dbglog_writeHex(Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmAddEaR(void) { DisasmEaD_xxxxdddxssmmmrrr("ADD"); } LOCALPROCUSEDONCE DisasmAddQ(void) { /* AddQ 0101nnn0ssmmmrrr */ Disasm_xxxxnnnxssmmmrrr("ADDQ"); } LOCALPROCUSEDONCE DisasmAddI(void) { DisasmI_xxxxxxxxssmmmrrr("ADDI"); } LOCALPROCUSEDONCE DisasmAddREa(void) { DisasmDEa_xxxxdddxssmmmrrr("ADD"); } LOCALPROCUSEDONCE DisasmSubEaR(void) { DisasmEaD_xxxxdddxssmmmrrr("SUB"); } LOCALPROCUSEDONCE DisasmSubQ(void) { /* SubQ 0101nnn1ssmmmrrr */ Disasm_xxxxnnnxssmmmrrr("SUBQ"); } LOCALPROCUSEDONCE DisasmSubI(void) { DisasmI_xxxxxxxxssmmmrrr("SUBI"); } LOCALPROCUSEDONCE DisasmSubREa(void) { DisasmDEa_xxxxdddxssmmmrrr("SUB"); } LOCALPROCUSEDONCE DisasmLea(void) { /* Lea 0100aaa111mmmrrr */ DisasmStartOne("LEA "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", A"); dbglog_writeHex(Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmPEA(void) { /* PEA 0100100001mmmrrr */ DisasmStartOne("PEA "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmALine(void) { DisasmStartOne("$"); dbglog_writeHex(Disasm_opcode); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmBsr(void) { ui5b src = ((ui5b)Disasm_opcode) & 255; ui5r s = Disasm_pc; DisasmStartOne("BSR "); if (src == 0) { s += (si5b)(si4b)Disasm_nextiword(); } else #if Use68020 if (src == 255) { s += (si5b)Disasm_nextilong(); /* ReportAbnormal("long branch in DoCode6"); */ /* Used by various Apps */ } else #endif { s += (si5b)(si3b)src; } dbglog_writeHex(s); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmJsr(void) { /* Jsr 0100111010mmmrrr */ DisasmStartOne("JSR "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmLinkA6(void) { DisasmStartOne("LINK A6, "); dbglog_writeHex(Disasm_nextiword()); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMOVEMRmM(void) { /* MOVEM reg to mem 0100100011s100rrr */ si4b z; ui5r regmask; DisasmStartOne("MOVEM"); if (Disasm_b76 == 2) { dbglog_writeCStr(".W"); } else { dbglog_writeCStr(".L"); } dbglog_writeCStr(" "); regmask = Disasm_nextiword(); for (z = 16; --z >= 0; ) { if ((regmask & (1 << (15 - z))) != 0) { if (z >= 8) { dbglog_writeCStr("A"); dbglog_writeHex(z - 8); } else { dbglog_writeCStr("D"); dbglog_writeHex(z); } } } dbglog_writeCStr(", -(A"); dbglog_writeHex(Disasm_reg); dbglog_writeCStr(")"); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMOVEMApR(void) { /* MOVEM mem to reg 0100110011s011rrr */ si4b z; ui5r regmask; regmask = Disasm_nextiword(); DisasmStartOne("MOVEM"); if (Disasm_b76 == 2) { dbglog_writeCStr(".W"); } else { dbglog_writeCStr(".L"); } dbglog_writeCStr(" (A"); dbglog_writeHex(Disasm_reg); dbglog_writeCStr(")+, "); for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { if (z >= 8) { dbglog_writeCStr("A"); dbglog_writeHex(z - 8); } else { dbglog_writeCStr("D"); dbglog_writeHex(z); } } } dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmUnlkA6(void) { DisasmStartOne("UNLINK A6"); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmRts(void) { /* Rts 0100111001110101 */ DisasmStartOne("RTS"); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmJmp(void) { /* JMP 0100111011mmmrrr */ DisasmStartOne("JMP "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmClr(void) { /* Clr 01000010ssmmmrrr */ Disasm_xxxxxxxxssmmmrrr("CLR"); } LOCALPROCUSEDONCE DisasmAddA(void) { /* ADDA 1101dddm11mmmrrr */ DisasmEaA_xxxxdddsxxmmmrrr("ADDA"); } LOCALPROCUSEDONCE DisasmAddQA(void) { /* 0101nnn0ss001rrr */ DisasmStartOne("ADDQA #"); dbglog_writeHex(Disasm_octdat(Disasm_rg9)); dbglog_writeCStr(", A"); dbglog_writeHex(Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmSubQA(void) { /* 0101nnn1ss001rrr */ DisasmStartOne("SUBQA #"); dbglog_writeHex(Disasm_octdat(Disasm_rg9)); dbglog_writeCStr(", A"); dbglog_writeHex(Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmSubA(void) { /* SUBA 1001dddm11mmmrrr */ DisasmEaA_xxxxdddsxxmmmrrr("SUBA"); } LOCALPROCUSEDONCE DisasmCmpA(void) { DisasmStartOne("CMPA "); Disasm_opsize = Disasm_b8 * 2 + 2; DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", A"); dbglog_writeHex(Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmAddXd(void) { DisasmDD_xxxxdddxssxxxrrr("ADDX"); } LOCALPROCUSEDONCE DisasmAddXm(void) { DisasmAAs_xxxxdddxssxxxrrr("ADDX"); } LOCALPROCUSEDONCE DisasmSubXd(void) { DisasmDD_xxxxdddxssxxxrrr("SUBX"); } LOCALPROCUSEDONCE DisasmSubXm(void) { DisasmAAs_xxxxdddxssxxxrrr("SUBX"); } LOCALPROC DisasmBinOp1(ui5r x) { if (! Disasm_b8) { switch (x) { case 0: DisasmStartOne("ASR"); break; case 1: DisasmStartOne("LSR"); break; case 2: DisasmStartOne("RXR"); break; case 3: DisasmStartOne("ROR"); break; default: /* should not get here */ break; } } else { switch (x) { case 0: DisasmStartOne("ASL"); break; case 1: DisasmStartOne("LSL"); break; case 2: DisasmStartOne("RXL"); break; case 3: DisasmStartOne("ROL"); break; default: /* should not get here */ break; } } } LOCALPROCUSEDONCE DisasmRolopNM(void) { DisasmBinOp1(Disasm_rg9); dbglog_writeCStr(" "); Disasm_opsize = 2; DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmRolopND(void) { /* 1110cccdss0ttddd */ DisasmBinOp1(Disasm_mode & 3); DisasmOpSizeFromb76(); dbglog_writeCStr(" #"); dbglog_writeHex(Disasm_octdat(Disasm_rg9)); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmRolopDD(void) { /* 1110rrrdss1ttddd */ DisasmBinOp1(Disasm_mode & 3); DisasmOpSizeFromb76(); dbglog_writeCStr(" "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_reg); dbglog_writeReturn(); } LOCALPROC DisasmBinBitOp1(void) { switch (Disasm_b76) { case 0: DisasmStartOne("BTST"); break; case 1: DisasmStartOne("BCHG"); break; case 2: DisasmStartOne("BCLR"); break; case 3: DisasmStartOne("BSET"); break; default: /* should not get here */ break; } } LOCALPROCUSEDONCE DisasmBitOpDD(void) { /* dynamic bit, Opcode = 0000ddd1tt000rrr */ DisasmBinBitOp1(); Disasm_opsize = 4; dbglog_writeCStr(" "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmBitOpDM(void) { /* dynamic bit, Opcode = 0000ddd1ttmmmrrr */ DisasmBinBitOp1(); Disasm_opsize = 1; dbglog_writeCStr(" "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeCStr(", "); DisasmModeRegister(Disasm_mode, Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmBitOpND(void) { /* static bit 00001010tt000rrr */ DisasmBinBitOp1(); Disasm_opsize = 4; dbglog_writeCStr(" #"); dbglog_writeHex(ui5r_FromSByte(Disasm_nextibyte())); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmBitOpNM(void) { /* static bit 00001010ttmmmrrr */ DisasmBinBitOp1(); Disasm_opsize = 1; dbglog_writeCStr(" #"); dbglog_writeHex(ui5r_FromSByte(Disasm_nextibyte())); dbglog_writeCStr(", "); DisasmModeRegister(Disasm_mode, Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmAndI(void) { DisasmI_xxxxxxxxssmmmrrr("ANDI"); } LOCALPROCUSEDONCE DisasmAndDEa(void) { /* And 1100ddd1ssmmmrrr */ DisasmDEa_xxxxdddxssmmmrrr("AND"); } LOCALPROCUSEDONCE DisasmAndEaD(void) { /* And 1100ddd0ssmmmrrr */ DisasmEaD_xxxxdddxssmmmrrr("AND"); } LOCALPROCUSEDONCE DisasmOrI(void) { DisasmI_xxxxxxxxssmmmrrr("ORI"); } LOCALPROCUSEDONCE DisasmOrDEa(void) { /* OR 1000ddd1ssmmmrrr */ DisasmDEa_xxxxdddxssmmmrrr("OR"); } LOCALPROCUSEDONCE DisasmOrEaD(void) { /* OR 1000ddd0ssmmmrrr */ DisasmEaD_xxxxdddxssmmmrrr("OR"); } LOCALPROCUSEDONCE DisasmEorI(void) { DisasmI_xxxxxxxxssmmmrrr("EORI"); } LOCALPROCUSEDONCE DisasmEor(void) { /* Eor 1011ddd1ssmmmrrr */ DisasmDEa_xxxxdddxssmmmrrr("EOR"); } LOCALPROCUSEDONCE DisasmNot(void) { /* Not 01000110ssmmmrrr */ Disasm_xxxxxxxxssmmmrrr("NOT"); } LOCALPROCUSEDONCE DisasmScc(void) { /* Scc 0101cccc11mmmrrr */ Disasm_opsize = 1; DisasmStartOne("S"); DisasmCC(); dbglog_writeCStr(" "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmEXTL(void) { DisasmStartOne("EXT.L D"); dbglog_writeHex(Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmEXTW(void) { DisasmStartOne("EXT.W D"); dbglog_writeHex(Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmNeg(void) { /* Neg 01000100ssmmmrrr */ Disasm_xxxxxxxxssmmmrrr("NEG"); } LOCALPROCUSEDONCE DisasmNegX(void) { /* NegX 01000000ssmmmrrr */ Disasm_xxxxxxxxssmmmrrr("NEGX"); } LOCALPROCUSEDONCE DisasmMulU(void) { /* MulU 1100ddd011mmmrrr */ Disasm_opsize = 2; DisasmStartOne("MULU "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMulS(void) { /* MulS 1100ddd111mmmrrr */ Disasm_opsize = 2; DisasmStartOne("MULS "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmDivU(void) { /* DivU 1000ddd011mmmrrr */ Disasm_opsize = 2; DisasmStartOne("DIVU "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmDivS(void) { /* DivS 1000ddd111mmmrrr */ Disasm_opsize = 2; DisasmStartOne("DIVS "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmExgdd(void) { /* Exg 1100ddd101000rrr */ Disasm_opsize = 4; DisasmStartOne("EXG "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmExgaa(void) { /* Exg 1100ddd101001rrr */ Disasm_opsize = 4; DisasmStartOne("EXG "); DisasmModeRegister(1, Disasm_rg9); dbglog_writeCStr(", "); DisasmModeRegister(1, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmExgda(void) { /* Exg 1100ddd110001rrr */ Disasm_opsize = 4; DisasmStartOne("EXG "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeCStr(", "); DisasmModeRegister(1, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMoveCCREa(void) { /* Move from CCR 0100001011mmmrrr */ Disasm_opsize = 2; DisasmStartOne("MOVE CCR, "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMoveEaCR(void) { /* 0100010011mmmrrr */ Disasm_opsize = 2; DisasmStartOne("MOVE "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", CCR"); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMoveSREa(void) { /* Move from SR 0100000011mmmrrr */ Disasm_opsize = 2; DisasmStartOne("MOVE SR, "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMoveEaSR(void) { /* 0100011011mmmrrr */ Disasm_opsize = 2; DisasmStartOne("MOVE "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", SR"); dbglog_writeReturn(); } LOCALPROC DisasmBinOpStatusCCR(void) { switch (Disasm_rg9) { case 0 : DisasmStartOne("OR"); break; case 1 : DisasmStartOne("AND"); break; case 5 : DisasmStartOne("EOR"); break; default: /* should not happen */ break; } DisasmOpSizeFromb76(); dbglog_writeCStr(" #"); dbglog_writeHex(ui5r_FromSWord(Disasm_nextiword())); if (Disasm_b76 != 0) { dbglog_writeCStr(", SR"); } else { dbglog_writeCStr(", CCR"); } dbglog_writeReturn(); } LOCALPROC disasmreglist(si4b direction, ui5b m1, ui5b r1) { si4b z; ui5r regmask; DisasmStartOne("MOVEM"); regmask = Disasm_nextiword(); Disasm_opsize = 2 * Disasm_b76 - 2; if (Disasm_opsize == 2) { dbglog_writeCStr(".W"); } else { dbglog_writeCStr(".L"); } dbglog_writeCStr(" "); if (direction != 0) { DisasmModeRegister(m1, r1); dbglog_writeCStr(", "); } for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { if (z >= 8) { dbglog_writeCStr("A"); dbglog_writeHex(z - 8); } else { dbglog_writeCStr("D"); dbglog_writeHex(z); } } } if (direction == 0) { dbglog_writeCStr(", "); DisasmModeRegister(m1, r1); } dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMOVEMrm(void) { /* MOVEM reg to mem 010010001ssmmmrrr */ disasmreglist(0, Disasm_mode, Disasm_reg); } LOCALPROCUSEDONCE DisasmMOVEMmr(void) { /* MOVEM mem to reg 0100110011smmmrrr */ disasmreglist(1, Disasm_mode, Disasm_reg); } LOCALPROC DisasmByteBinOp(char *s, ui5b m1, ui5b r1, ui5b m2, ui5b r2) { DisasmStartOne(s); dbglog_writeCStr(" "); DisasmOpSizeFromb76(); DisasmModeRegister(m1, r1); dbglog_writeCStr(", "); DisasmModeRegister(m2, r2); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmAbcdr(void) { /* ABCD 1100ddd100000rrr */ DisasmByteBinOp("ABCD", 0, Disasm_reg, 0, Disasm_rg9); } LOCALPROCUSEDONCE DisasmAbcdm(void) { /* ABCD 1100ddd100001rrr */ DisasmByteBinOp("ABCD", 4, Disasm_reg, 4, Disasm_rg9); } LOCALPROCUSEDONCE DisasmSbcdr(void) { /* SBCD 1000xxx100000xxx */ DisasmByteBinOp("ABCD", 0, Disasm_reg, 0, Disasm_rg9); } LOCALPROCUSEDONCE DisasmSbcdm(void) { /* SBCD 1000xxx100001xxx */ DisasmByteBinOp("ABCD", 4, Disasm_reg, 4, Disasm_rg9); } LOCALPROCUSEDONCE DisasmNbcd(void) { /* Nbcd 0100100000mmmrrr */ Disasm_xxxxxxxxssmmmrrr("NBCD"); } LOCALPROCUSEDONCE DisasmRte(void) { /* Rte 0100111001110011 */ DisasmStartOne("RTE"); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmNop(void) { /* Nop 0100111001110001 */ DisasmStartOne("NOP"); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMoveP(void) { /* MoveP 0000ddd1mm001aaa */ DisasmStartOne("MOVEP"); if (0 == (Disasm_b76 & 1)) { Disasm_opsize = 2; dbglog_writeCStr(".W"); } else { Disasm_opsize = 4; dbglog_writeCStr(".L"); } dbglog_writeCStr(" "); if (Disasm_b76 < 2) { DisasmModeRegister(5, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_rg9); } else { DisasmModeRegister(0, Disasm_rg9); dbglog_writeCStr(", "); DisasmModeRegister(5, Disasm_reg); } dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmIllegal(void) { DisasmStartOne("ILLEGAL"); dbglog_writeReturn(); } LOCALPROC DisasmCheck(void) { DisasmStartOne("CHK"); if (2 == Disasm_opsize) { dbglog_writeCStr(".W"); } else { dbglog_writeCStr(".L"); } dbglog_writeCStr(" "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmChkW(void) { /* Chk.W 0100ddd110mmmrrr */ Disasm_opsize = 2; DisasmCheck(); } LOCALPROCUSEDONCE DisasmTrap(void) { /* Trap 010011100100vvvv */ DisasmStartOne("TRAP "); dbglog_writeHex(Disasm_opcode & 15); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmTrapV(void) { /* TrapV 0100111001110110 */ DisasmStartOne("TRAPV"); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmRtr(void) { /* Rtr 0100111001110111 */ DisasmStartOne("RTR"); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmLink(void) { DisasmStartOne("LINK A"); dbglog_writeHex(Disasm_reg); dbglog_writeCStr(", "); dbglog_writeHex(Disasm_nextiword()); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmUnlk(void) { DisasmStartOne("UNLINK A"); dbglog_writeHex(Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMoveRUSP(void) { /* MOVE USP 0100111001100aaa */ DisasmStartOne("MOVE A"); dbglog_writeHex(Disasm_reg); dbglog_writeCStr(", USP"); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMoveUSPR(void) { /* MOVE USP 0100111001101aaa */ DisasmStartOne("MOVE USP, A"); dbglog_writeHex(Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmTas(void) { /* Tas 0100101011mmmrrr */ Disasm_opsize = 1; DisasmStartOne("TAS"); dbglog_writeCStr(" "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmFLine(void) { DisasmStartOne("$"); dbglog_writeHex(Disasm_opcode); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmCallMorRtm(void) { DisasmStartOne("CALLM #"); dbglog_writeHex(Disasm_nextibyte()); dbglog_writeCStr(", "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmStop(void) { /* Stop 0100111001110010 */ DisasmStartOne("STOP #"); dbglog_writeHex(Disasm_nextiword()); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmReset(void) { /* Reset 0100111001100000 */ DisasmStartOne("RESET"); dbglog_writeReturn(); } #if Use68020 LOCALPROCUSEDONCE DisasmEXTBL(void) { /* EXTB.L */ DisasmStartOne("EXTB.L D"); dbglog_writeHex(Disasm_reg); dbglog_writeReturn(); } #endif #if Use68020 LOCALPROCUSEDONCE DisasmTRAPcc(void) { /* TRAPcc 0101cccc11111sss */ DisasmStartOne("TRAP"); DisasmCC(); switch (Disasm_reg) { case 2: dbglog_writeCStr(" "); dbglog_writeHex(Disasm_nextiword()); break; case 3: dbglog_writeCStr(" "); dbglog_writeHex(Disasm_nextilong()); break; case 4: /* no optional data */ break; default: /* illegal format */ break; } dbglog_writeReturn(); } #endif #if Use68020 LOCALPROCUSEDONCE DisasmChkL(void) { /* Chk.L 0100ddd100mmmrrr */ Disasm_opsize = 4; DisasmCheck(); } #endif #if Use68020 LOCALPROCUSEDONCE DisasmBkpt(void) { /* BKPT 0100100001001rrr */ DisasmStartOne("BKPT #"); dbglog_writeHex(Disasm_reg); dbglog_writeReturn(); } #endif #if Use68020 LOCALPROCUSEDONCE DisasmDivL(void) { /* DIVU 0100110001mmmrrr 0rrr0s0000000rrr */ /* DIVS 0100110001mmmrrr 0rrr1s0000000rrr */ Disasm_opsize = 4; DisasmStartOne("DIV"); { ui4b extra = Disasm_nextiword(); ui5b rDr = extra & 7; ui5b rDq = (extra >> 12) & 7; if (extra & 0x0800) { dbglog_writeCStr("S"); } else { dbglog_writeCStr("U"); } if (extra & 0x0400) { dbglog_writeCStr("L"); } dbglog_writeCStr(".L "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", "); if (rDr != rDq) { dbglog_writeCStr("D"); dbglog_writeHex(rDr); dbglog_writeCStr(":"); } dbglog_writeCStr("D"); dbglog_writeHex(rDq); } dbglog_writeReturn(); } #endif #if Use68020 LOCALPROCUSEDONCE DisasmMulL(void) { /* MULU 0100110000mmmrrr 0rrr0s0000000rrr */ /* MULS 0100110000mmmrrr 0rrr1s0000000rrr */ Disasm_opsize = 4; DisasmStartOne("MUL"); { ui4b extra = Disasm_nextiword(); ui5b rhi = extra & 7; ui5b rlo = (extra >> 12) & 7; if (extra & 0x0800) { dbglog_writeCStr("S"); } else { dbglog_writeCStr("U"); } dbglog_writeCStr(".L "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", "); if (extra & 0x400) { dbglog_writeCStr("D"); dbglog_writeHex(rhi); dbglog_writeCStr(":"); } dbglog_writeCStr("D"); dbglog_writeHex(rlo); } dbglog_writeReturn(); } #endif #if Use68020 LOCALPROCUSEDONCE DisasmRtd(void) { /* Rtd 0100111001110100 */ DisasmStartOne("RTD #"); dbglog_writeHex((si5b)(si4b)Disasm_nextiword()); dbglog_writeReturn(); } #endif #if Use68020 LOCALPROC DisasmControlReg(ui4r i) { switch (i) { case 0x0000: dbglog_writeCStr("SFC"); break; case 0x0001: dbglog_writeCStr("DFC"); break; case 0x0002: dbglog_writeCStr("CACR"); break; case 0x0800: dbglog_writeCStr("USP"); break; case 0x0801: dbglog_writeCStr("VBR"); break; case 0x0802: dbglog_writeCStr("CAAR"); break; case 0x0803: dbglog_writeCStr("MSP"); break; case 0x0804: dbglog_writeCStr("ISP"); break; default: dbglog_writeCStr("???"); break; } } #endif #if Use68020 LOCALPROCUSEDONCE DisasmMoveC(void) { /* MOVEC 010011100111101m */ DisasmStartOne("MOVEC "); { ui4b src = Disasm_nextiword(); int regno = (src >> 12) & 0x0F; switch (Disasm_reg) { case 2: DisasmControlReg(src & 0x0FFF); dbglog_writeCStr(", "); if (regno < 8) { dbglog_writeCStr("D"); } else { dbglog_writeCStr("A"); } dbglog_writeHex(regno & 7); break; case 3: if (regno < 8) { dbglog_writeCStr("D"); } else { dbglog_writeCStr("A"); } dbglog_writeHex(regno & 7); dbglog_writeCStr(", "); DisasmControlReg(src & 0x0FFF); break; default: /* illegal */ break; } } dbglog_writeReturn(); } #endif #if Use68020 LOCALPROCUSEDONCE DisasmLinkL(void) { /* Link.L 0100100000001rrr */ DisasmStartOne("LINK.L A"); dbglog_writeHex(Disasm_reg); dbglog_writeCStr(", "); dbglog_writeHex(Disasm_nextilong()); dbglog_writeReturn(); } #endif #if Use68020 LOCALPROCUSEDONCE DisasmPack(void) { DisasmStartOne("PACK ???"); dbglog_writeReturn(); /* DoCodePack */ } #endif #if Use68020 LOCALPROCUSEDONCE DisasmUnpk(void) { DisasmStartOne("UNPK ???"); dbglog_writeReturn(); /* DoCodeUnpk */ } #endif #if Use68020 LOCALPROCUSEDONCE DisasmCHK2orCMP2(void) { DisasmStartOne("CHK2/CMP2 ???"); dbglog_writeReturn(); /* DoCHK2orCMP2 */ } #endif #if Use68020 LOCALPROCUSEDONCE DisasmCAS2(void) { DisasmStartOne("CAS2 ???"); dbglog_writeReturn(); /* DoCAS2 */ } #endif #if Use68020 LOCALPROCUSEDONCE DisasmCAS(void) { DisasmStartOne("CAS ???"); dbglog_writeReturn(); /* DoDoCAS */ } #endif #if Use68020 LOCALPROCUSEDONCE DisasmMOVES(void) { DisasmStartOne("MOVES ???"); dbglog_writeReturn(); /* DoMOVES */ } #endif #if Use68020 LOCALPROCUSEDONCE DisasmBitField(void) { DisasmStartOne("BitField ???"); dbglog_writeReturn(); /* DoBitField */ } #endif LOCALFUNC blnr IsValidAddrMode(void) { return (Disasm_mode != 7) || (Disasm_reg < 5); } LOCALFUNC blnr IsValidDstAddrMode(void) { return (Disasm_md6 != 7) || (Disasm_rg9 < 2); } LOCALFUNC blnr IsValidDataAltAddrMode(void) { blnr IsOk; switch (Disasm_mode) { case 1: default: /* keep compiler happy */ IsOk = falseblnr; break; case 0: case 2: case 3: case 4: case 5: case 6: IsOk = trueblnr; break; case 7: IsOk = Disasm_reg < 2; break; } return IsOk; } LOCALFUNC blnr IsValidDataAddrMode(void) { blnr IsOk; switch (Disasm_mode) { case 1: default: /* keep compiler happy */ IsOk = falseblnr; break; case 0: case 2: case 3: case 4: case 5: case 6: IsOk = trueblnr; break; case 7: IsOk = Disasm_reg < 5; break; } return IsOk; } LOCALFUNC blnr IsValidControlAddrMode(void) { blnr IsOk; switch (Disasm_mode) { case 0: case 1: case 3: case 4: default: /* keep compiler happy */ IsOk = falseblnr; break; case 2: case 5: case 6: IsOk = trueblnr; break; case 7: IsOk = Disasm_reg < 4; break; } return IsOk; } LOCALFUNC blnr IsValidControlAltAddrMode(void) { blnr IsOk; switch (Disasm_mode) { case 0: case 1: case 3: case 4: default: /* keep compiler happy */ IsOk = falseblnr; break; case 2: case 5: case 6: IsOk = trueblnr; break; case 7: IsOk = Disasm_reg < 2; break; } return IsOk; } LOCALFUNC blnr IsValidAltMemAddrMode(void) { blnr IsOk; switch (Disasm_mode) { case 0: case 1: default: /* keep compiler happy */ IsOk = falseblnr; break; case 2: case 3: case 4: case 5: case 6: IsOk = trueblnr; break; case 7: IsOk = Disasm_reg < 2; break; } return IsOk; } LOCALPROCUSEDONCE DisasmCode0(void) { if (Disasm_b8 == 1) { if (Disasm_mode == 1) { /* MoveP 0000ddd1mm001aaa */ DisasmMoveP(); } else { /* dynamic bit, Opcode = 0000ddd1ttmmmrrr */ if (Disasm_mode == 0) { DisasmBitOpDD(); } else { if (Disasm_b76 == 0) { if (IsValidDataAddrMode()) { DisasmBitOpDM(); } else { DisasmIllegal(); } } else { if (IsValidDataAltAddrMode()) { DisasmBitOpDM(); } else { DisasmIllegal(); } } } } } else { if (Disasm_rg9 == 4) { /* static bit 00001010ssmmmrrr */ if (Disasm_mode == 0) { DisasmBitOpND(); } else { if (Disasm_b76 == 0) { if ((Disasm_mode == 7) && (Disasm_reg == 4)) { DisasmIllegal(); } else { if (IsValidDataAddrMode()) { DisasmBitOpNM(); } else { DisasmIllegal(); } } } else { if (IsValidDataAltAddrMode()) { DisasmBitOpNM(); } else { DisasmIllegal(); } } } } else if (Disasm_b76 == 3) { #if Use68020 if (Disasm_rg9 < 3) { /* CHK2 or CMP2 00000ss011mmmrrr */ if (IsValidControlAddrMode()) { DisasmCHK2orCMP2(); } else { DisasmIllegal(); } } else if (Disasm_rg9 >= 5) { if ((Disasm_mode == 7) && (Disasm_reg == 4)) { /* CAS2 00001ss011111100 */ DisasmCAS2(); } else { /* CAS 00001ss011mmmrrr */ DisasmCAS2(); } } else if (Disasm_rg9 == 3) { /* CALLM or RTM 0000011011mmmrrr */ DisasmCallMorRtm(); } else #endif { DisasmIllegal(); } } else if (Disasm_rg9 == 6) { /* CMPI 00001100ssmmmrrr */ if (IsValidDataAltAddrMode()) { DisasmCmpI(); } else { DisasmIllegal(); } } else if (Disasm_rg9 == 7) { #if Use68020 /* MoveS 00001110ssmmmrrr */ if (IsValidAltMemAddrMode()) { DisasmMoveSREa(); } else { DisasmIllegal(); } #else DisasmIllegal(); #endif } else { if ((Disasm_mode == 7) && (Disasm_reg == 4)) { switch (Disasm_rg9) { case 0: case 1: case 5: DisasmBinOpStatusCCR(); break; default: DisasmIllegal(); break; } } else { if (! IsValidDataAltAddrMode()) { DisasmIllegal(); } else { switch (Disasm_rg9) { case 0: DisasmOrI(); break; case 1: DisasmAndI(); break; case 2: DisasmSubI(); break; case 3: DisasmAddI(); break; case 5: DisasmEorI(); break; default: /* for compiler. should be 0, 1, 2, 3, or 5 */ DisasmIllegal(); break; } } } } } } LOCALPROCUSEDONCE DisasmCode1(void) { if ((Disasm_mode == 1) || ! IsValidAddrMode()) { DisasmIllegal(); } else if (Disasm_md6 == 1) { /* MOVEA */ DisasmIllegal(); } else if (! IsValidDstAddrMode()) { DisasmIllegal(); } else { DisasmMoveB(); } } LOCALPROCUSEDONCE DisasmCode2(void) { if (Disasm_md6 == 1) { /* MOVEA */ if (IsValidAddrMode()) { DisasmMoveAL(); } else { DisasmIllegal(); } } else if (! IsValidAddrMode()) { DisasmIllegal(); } else if (! IsValidDstAddrMode()) { DisasmIllegal(); } else { DisasmMoveL(); } } LOCALPROCUSEDONCE DisasmCode3(void) { if (Disasm_md6 == 1) { /* MOVEA */ if (IsValidAddrMode()) { DisasmMoveAW(); } else { DisasmIllegal(); } } else if (! IsValidAddrMode()) { DisasmIllegal(); } else if (! IsValidDstAddrMode()) { DisasmIllegal(); } else { DisasmMoveW(); } } LOCALPROCUSEDONCE DisasmCode4(void) { if (Disasm_b8 != 0) { switch (Disasm_b76) { case 0: #if Use68020 /* Chk.L 0100ddd100mmmrrr */ if (IsValidDataAddrMode()) { DisasmChkL(); } else { DisasmIllegal(); } #else DisasmIllegal(); #endif break; case 1: DisasmIllegal(); break; case 2: /* Chk.W 0100ddd110mmmrrr */ if (IsValidDataAddrMode()) { DisasmChkW(); } else { DisasmIllegal(); } break; case 3: default: /* keep compiler happy */ #if Use68020 if ((0 == Disasm_mode) && (4 == Disasm_rg9)) { DisasmEXTBL(); } else #endif { /* Lea 0100aaa111mmmrrr */ if (IsValidControlAddrMode()) { DisasmLea(); } else { DisasmIllegal(); } } break; } } else { switch (Disasm_rg9) { case 0: if (Disasm_b76 != 3) { /* NegX 01000000ssmmmrrr */ if (IsValidDataAltAddrMode()) { DisasmNegX(); } else { DisasmIllegal(); } } else { #if Use68020 /* reference seems incorrect to say not for 68000 */ #endif /* Move from SR 0100000011mmmrrr */ if (IsValidDataAltAddrMode()) { DisasmMoveSREa(); } else { DisasmIllegal(); } } break; case 1: if (Disasm_b76 != 3) { /* Clr 01000010ssmmmrrr */ if (IsValidDataAltAddrMode()) { DisasmClr(); } else { DisasmIllegal(); } } else { #if Use68020 /* Move from CCR 0100001011mmmrrr */ if (IsValidDataAltAddrMode()) { DisasmMoveCCREa(); } else { DisasmIllegal(); } #else DisasmIllegal(); #endif } break; case 2: if (Disasm_b76 != 3) { /* Neg 01000100ssmmmrrr */ if (IsValidDataAltAddrMode()) { DisasmNeg(); } else { DisasmIllegal(); } } else { /* Move to CCR 0100010011mmmrrr */ if (IsValidDataAddrMode()) { DisasmMoveEaCR(); } else { DisasmIllegal(); } } break; case 3: if (Disasm_b76 != 3) { /* Not 01000110ssmmmrrr */ if (IsValidDataAltAddrMode()) { DisasmNot(); } else { DisasmIllegal(); } } else { /* Move from SR 0100011011mmmrrr */ if (IsValidDataAddrMode()) { DisasmMoveEaSR(); } else { DisasmIllegal(); } } break; case 4: switch (Disasm_b76) { case 0: #if Use68020 if (Disasm_mode == 1) { /* Link.L 0100100000001rrr */ DisasmLinkL(); } else #endif { /* Nbcd 0100100000mmmrrr */ if (IsValidDataAltAddrMode()) { DisasmNbcd(); } else { DisasmIllegal(); } } break; case 1: if (Disasm_mode == 0) { /* Swap 0100100001000rrr */ DisasmSwap(); } else #if Use68020 if (Disasm_mode == 1) { DisasmBkpt(); } else #endif { /* PEA 0100100001mmmrrr */ if (IsValidControlAddrMode()) { DisasmPEA(); } else { DisasmIllegal(); } } break; case 2: if (Disasm_mode == 0) { /* EXT.W */ DisasmEXTW(); } else { /* MOVEM Disasm_reg to mem 01001d001ssmmmrrr */ if (Disasm_mode == 4) { DisasmMOVEMRmM(); } else { if (IsValidControlAltAddrMode()) { DisasmMOVEMrm(); } else { DisasmIllegal(); } } } break; case 3: default: /* keep compiler happy */ if (Disasm_mode == 0) { /* EXT.L */ DisasmEXTL(); } else { /* MOVEM Disasm_reg to mem 01001d001ssmmmrrr */ if (Disasm_mode == 4) { DisasmMOVEMRmM(); } else { if (IsValidControlAltAddrMode()) { DisasmMOVEMrm(); } else { DisasmIllegal(); } } } break; } break; case 5: if (Disasm_b76 == 3) { if ((Disasm_mode == 7) && (Disasm_reg == 4)) { /* the ILLEGAL instruction */ DisasmIllegal(); } else { /* Tas 0100101011mmmrrr */ if (IsValidDataAltAddrMode()) { DisasmTas(); } else { DisasmIllegal(); } } } else { /* Tst 01001010ssmmmrrr */ if (Disasm_b76 == 0) { if (IsValidDataAltAddrMode()) { DisasmTst(); } else { DisasmIllegal(); } } else { if (IsValidAddrMode()) { DisasmTst(); } else { DisasmIllegal(); } } } break; case 6: if (((Disasm_opcode >> 7) & 1) == 1) { /* MOVEM mem to Disasm_reg 0100110011smmmrrr */ if (Disasm_mode == 3) { DisasmMOVEMApR(); } else { if (IsValidControlAddrMode()) { DisasmMOVEMmr(); } else { DisasmIllegal(); } } } else { #if Use68020 if (((Disasm_opcode >> 6) & 1) == 1) { /* DIVU 0100110001mmmrrr 0rrr0s0000000rrr */ /* DIVS 0100110001mmmrrr 0rrr1s0000000rrr */ DisasmDivL(); } else { /* MULU 0100110000mmmrrr 0rrr0s0000000rrr */ /* MULS 0100110000mmmrrr 0rrr1s0000000rrr */ DisasmMulL(); } #else DisasmIllegal(); #endif } break; case 7: default: /* keep compiler happy */ switch (Disasm_b76) { case 0: DisasmIllegal(); break; case 1: switch (Disasm_mode) { case 0: case 1: /* Trap 010011100100vvvv */ DisasmTrap(); break; case 2: /* Link */ if (Disasm_reg == 6) { DisasmLinkA6(); } else { DisasmLink(); } break; case 3: /* Unlk */ if (Disasm_reg == 6) { DisasmUnlkA6(); } else { DisasmUnlk(); } break; case 4: /* MOVE USP 0100111001100aaa */ DisasmMoveRUSP(); break; case 5: /* MOVE USP 0100111001101aaa */ DisasmMoveUSPR(); break; case 6: switch (Disasm_reg) { case 0: /* Reset 0100111001100000 */ DisasmReset(); break; case 1: /* Nop Opcode = 0100111001110001 */ DisasmNop(); break; case 2: /* Stop 0100111001110010 */ DisasmStop(); break; case 3: /* Rte 0100111001110011 */ DisasmRte(); break; case 4: /* Rtd 0100111001110100 */ #if Use68020 DisasmRtd(); #else DisasmIllegal(); #endif break; case 5: /* Rts 0100111001110101 */ DisasmRts(); break; case 6: /* TrapV 0100111001110110 */ DisasmTrapV(); break; case 7: default: /* keep compiler happy */ /* Rtr 0100111001110111 */ DisasmRtr(); break; } break; case 7: default: /* keep compiler happy */ #if Use68020 /* MOVEC 010011100111101m */ DisasmMoveC(); #else DisasmIllegal(); #endif break; } break; case 2: /* Jsr 0100111010mmmrrr */ if (IsValidControlAddrMode()) { DisasmJsr(); } else { DisasmIllegal(); } break; case 3: default: /* keep compiler happy */ /* JMP 0100111011mmmrrr */ if (IsValidControlAddrMode()) { DisasmJmp(); } else { DisasmIllegal(); } break; } break; } } } LOCALPROCUSEDONCE DisasmCode5(void) { if (Disasm_b76 == 3) { if (Disasm_mode == 1) { /* DBcc 0101cccc11001ddd */ DisasmDBcc(); } else { #if Use68020 if ((Disasm_mode == 7) && (Disasm_reg >= 2)) { /* TRAPcc 0101cccc11111sss */ DisasmTRAPcc(); } else #endif { /* Scc 0101cccc11mmmrrr */ if (IsValidDataAltAddrMode()) { DisasmScc(); } else { DisasmIllegal(); } } } } else { if (Disasm_mode == 1) { if (Disasm_b8 == 0) { DisasmAddQA(); /* AddQA 0101nnn0ss001rrr */ } else { DisasmSubQA(); /* SubQA 0101nnn1ss001rrr */ } } else { if (Disasm_b8 == 0) { /* AddQ 0101nnn0ssmmmrrr */ if (IsValidDataAltAddrMode()) { DisasmAddQ(); } else { DisasmIllegal(); } } else { /* SubQ 0101nnn1ssmmmrrr */ if (IsValidDataAltAddrMode()) { DisasmSubQ(); } else { DisasmIllegal(); } } } } } LOCALPROCUSEDONCE DisasmCode6(void) { ui5b cond = (Disasm_opcode >> 8) & 15; if (cond == 1) { /* Bsr 01100001nnnnnnnn */ DisasmBsr(); } else if (cond == 0) { /* Bra 01100000nnnnnnnn */ DisasmBcc(); } else { /* Bcc 0110ccccnnnnnnnn */ DisasmBcc(); } } LOCALPROCUSEDONCE DisasmCode7(void) { if (Disasm_b8 == 0) { DisasmMoveQ(); } else { DisasmIllegal(); } } LOCALPROCUSEDONCE DisasmCode8(void) { if (Disasm_b76 == 3) { if (Disasm_b8 == 0) { /* DivU 1000ddd011mmmrrr */ if (IsValidDataAddrMode()) { DisasmDivU(); } else { DisasmIllegal(); } } else { /* DivS 1000ddd111mmmrrr */ if (IsValidDataAddrMode()) { DisasmDivS(); } else { DisasmIllegal(); } } } else { if (Disasm_b8 == 0) { /* OR 1000ddd0ssmmmrrr */ if (IsValidDataAddrMode()) { DisasmOrEaD(); } else { DisasmIllegal(); } } else { if (Disasm_mode < 2) { switch (Disasm_b76) { case 0: /* SBCD 1000xxx10000mxxx */ if (Disasm_mode == 0) { DisasmSbcdr(); } else { DisasmSbcdm(); } break; #if Use68020 case 1: /* PACK 1000rrr10100mrrr */ DisasmPack(); break; case 2: /* UNPK 1000rrr11000mrrr */ DisasmUnpk(); break; #endif default: DisasmIllegal(); break; } } else { /* OR 1000ddd1ssmmmrrr */ if (IsValidDataAltAddrMode()) { DisasmOrDEa(); } else { DisasmIllegal(); } } } } } LOCALPROCUSEDONCE DisasmCode9(void) { if (Disasm_b76 == 3) { /* SUBA 1001dddm11mmmrrr */ if (IsValidAddrMode()) { DisasmSubA(); } else { DisasmIllegal(); } } else { if (Disasm_b8 == 0) { /* SUB 1001ddd0ssmmmrrr */ if (IsValidAddrMode()) { DisasmSubEaR(); } else { DisasmIllegal(); } } else { if (Disasm_mode == 0) { /* SUBX 1001ddd1ss000rrr */ DisasmSubXd(); } else if (Disasm_mode == 1) { /* SUBX 1001ddd1ss001rrr */ DisasmSubXm(); } else { /* SUB 1001ddd1ssmmmrrr */ if (IsValidAltMemAddrMode()) { DisasmSubREa(); } else { DisasmIllegal(); } } } } } LOCALPROCUSEDONCE DisasmCodeA(void) { DisasmALine(); } LOCALPROCUSEDONCE DisasmCodeB(void) { if (Disasm_b76 == 3) { /* CMPA 1011ddds11mmmrrr */ if (IsValidAddrMode()) { DisasmCmpA(); } else { DisasmIllegal(); } } else if (Disasm_b8 == 1) { if (Disasm_mode == 1) { /* CmpM 1011ddd1ss001rrr */ DisasmCmpM(); } else { /* Eor 1011ddd1ssmmmrrr */ if (IsValidDataAltAddrMode()) { DisasmEor(); } else { DisasmIllegal(); } } } else { /* Cmp 1011ddd0ssmmmrrr */ if (IsValidAddrMode()) { DisasmCompare(); } else { DisasmIllegal(); } } } LOCALPROCUSEDONCE DisasmCodeC(void) { if (Disasm_b76 == 3) { if (Disasm_b8 == 0) { /* MulU 1100ddd011mmmrrr */ if (IsValidDataAddrMode()) { DisasmMulU(); } else { DisasmIllegal(); } } else { /* MulS 1100ddd111mmmrrr */ if (IsValidDataAddrMode()) { DisasmMulS(); } else { DisasmIllegal(); } } } else { if (Disasm_b8 == 0) { /* And 1100ddd0ssmmmrrr */ if (IsValidDataAddrMode()) { DisasmAndEaD(); } else { DisasmIllegal(); } } else { if (Disasm_mode < 2) { switch (Disasm_b76) { case 0: /* ABCD 1100ddd10000mrrr */ if (Disasm_mode == 0) { DisasmAbcdr(); } else { DisasmAbcdm(); } break; case 1: /* Exg 1100ddd10100trrr */ if (Disasm_mode == 0) { DisasmExgdd(); } else { DisasmExgaa(); } break; case 2: default: /* keep compiler happy */ if (Disasm_mode == 0) { DisasmIllegal(); } else { /* Exg 1100ddd110001rrr */ DisasmExgda(); } break; } } else { /* And 1100ddd1ssmmmrrr */ if (IsValidAltMemAddrMode()) { DisasmAndDEa(); } else { DisasmIllegal(); } } } } } LOCALPROCUSEDONCE DisasmCodeD(void) { if (Disasm_b76 == 3) { /* ADDA 1101dddm11mmmrrr */ if (IsValidAddrMode()) { DisasmAddA(); } else { DisasmIllegal(); } } else { if (Disasm_b8 == 0) { /* ADD 1101ddd0ssmmmrrr */ if (IsValidAddrMode()) { DisasmAddEaR(); } else { DisasmIllegal(); } } else { if (Disasm_mode == 0) { DisasmAddXd(); } else if (Disasm_mode == 1) { DisasmAddXm(); } else { /* ADD 1101ddd1ssmmmrrr */ if (IsValidAltMemAddrMode()) { DisasmAddREa(); } else { DisasmIllegal(); } } } } } LOCALPROCUSEDONCE DisasmCodeE(void) { if (Disasm_b76 == 3) { if ((Disasm_opcode & 0x0800) != 0) { #if Use68020 /* 11101???11mmmrrr */ switch (Disasm_mode) { case 1: case 3: case 4: default: /* keep compiler happy */ DisasmIllegal(); break; case 0: case 2: case 5: case 6: DisasmBitField(); break; case 7: switch (Disasm_reg) { case 0: case 1: DisasmBitField(); break; case 2: case 3: switch ((Disasm_opcode >> 8) & 7) { case 0: /* BFTST */ case 1: /* BFEXTU */ case 3: /* BFEXTS */ case 5: /* BFFFO */ DisasmBitField(); break; default: DisasmIllegal(); break; } break; default: DisasmIllegal(); break; } break; } #else DisasmIllegal(); #endif } else { /* 11100ttd11mmmddd */ if (IsValidAltMemAddrMode()) { DisasmRolopNM(); } else { DisasmIllegal(); } } } else { if (Disasm_mode < 4) { /* 1110cccdss0ttddd */ DisasmRolopND(); } else { /* 1110rrrdss1ttddd */ DisasmRolopDD(); } } } LOCALPROCUSEDONCE DisasmCodeF(void) { DisasmFLine(); } LOCALPROC m68k_Disasm_one(void) { Disasm_opcode = Disasm_nextiword(); switch (Disasm_opcode >> 12) { case 0x0: DisasmCode0(); break; case 0x1: DisasmCode1(); break; case 0x2: DisasmCode2(); break; case 0x3: DisasmCode3(); break; case 0x4: DisasmCode4(); break; case 0x5: DisasmCode5(); break; case 0x6: DisasmCode6(); break; case 0x7: DisasmCode7(); break; case 0x8: DisasmCode8(); break; case 0x9: DisasmCode9(); break; case 0xA: DisasmCodeA(); break; case 0xB: DisasmCodeB(); break; case 0xC: DisasmCodeC(); break; case 0xD: DisasmCodeD(); break; case 0xE: DisasmCodeE(); break; case 0xF: default: /* keep compiler happy */ DisasmCodeF(); break; } } #define Ln2SavedPCs 4 #define NumSavedPCs (1 << Ln2SavedPCs) #define SavedPCsMask (NumSavedPCs - 1) LOCALVAR ui5r SavedPCs[NumSavedPCs]; LOCALVAR ui5r SavedPCsIn = 0; LOCALVAR ui5r SavedPCsOut = 0; #define DisasmIncludeCycles 0 LOCALPROCUSEDONCE DisasmOneAndBack(ui5r pc) { #if DisasmIncludeCycles dbglog_writeHex(GetCuriCount()); dbglog_writeCStr(" "); #endif dbglog_writeHex(pc); dbglog_writeCStr(" "); Disasm_setpc(pc); m68k_Disasm_one(); } LOCALPROCUSEDONCE DisasmSavedPCs(void) { ui5r n = SavedPCsIn - SavedPCsOut; if (n != 0) { ui5r pc; #if DisasmIncludeCycles ui5r i; #endif #if 0 blnr Skipped = falseblnr; #endif ui5r j = SavedPCsOut; SavedPCsOut = SavedPCsIn; /* do first, prevent recursion in case of error while disassembling. (i.e. failure to read emulated memory.) */ #if DisasmIncludeCycles i = GetCuriCount(); #endif if (n > NumSavedPCs) { n = NumSavedPCs; j = SavedPCsIn - NumSavedPCs; dbglog_writeReturn(); #if 0 Skipped = trueblnr; #endif } do { --n; pc = SavedPCs[j & SavedPCsMask]; #if DisasmIncludeCycles dbglog_writeHex(i /* - n */); dbglog_writeCStr("-? "); #endif dbglog_writeHex(pc); dbglog_writeCStr(" "); Disasm_setpc(pc); m68k_Disasm_one(); ++j; } while (n != 0); #if 0 if (Skipped) { si4b z; for (z = 0; z < 16; ++z) { if (z >= 8) { dbglog_writeCStr(" A"); dbglog_writeHex(z - 8); } else { dbglog_writeCStr(" D"); dbglog_writeHex(z); } dbglog_writeCStr(" = "); dbglog_writeHex(regs.regs[z]); dbglog_writeReturn(); } } #endif } } LOCALVAR ui5r DisasmCounter = 0; GLOBALPROC DisasmOneOrSave(ui5r pc) { if (0 != DisasmCounter) { DisasmOneAndBack(pc); --DisasmCounter; } else { SavedPCs[SavedPCsIn & SavedPCsMask] = pc; ++SavedPCsIn; } } GLOBALPROC m68k_WantDisasmContext(void) { DisasmSavedPCs(); DisasmCounter = /* 256 */ 128; } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/DISAM68K.h b/Mini vMac/mnvm_core/DISAM68K.h index 7569349..f834eb8 100755 --- a/Mini vMac/mnvm_core/DISAM68K.h +++ b/Mini vMac/mnvm_core/DISAM68K.h @@ -1,29 +1 @@ -/* - DISAM68K.h - - Copyright (C) 2010 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - DISAssemble Motorola 68K instructions. -*/ - -#ifdef DIS1M68K_H -#error "header already included" -#else -#define DIS1M68K_H -#endif - -EXPORTPROC DisasmOneOrSave(ui5r pc); - -EXPORTPROC m68k_WantDisasmContext(void); +/* DISAM68K.h Copyright (C) 2010 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* DISAssemble Motorola 68K instructions. */ #ifdef DIS1M68K_H #error "header already included" #else #define DIS1M68K_H #endif EXPORTPROC DisasmOneOrSave(ui5r pc); EXPORTPROC m68k_WantDisasmContext(void); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/ENDIANAC.h b/Mini vMac/mnvm_core/ENDIANAC.h index 88f7bb1..7086528 100755 --- a/Mini vMac/mnvm_core/ENDIANAC.h +++ b/Mini vMac/mnvm_core/ENDIANAC.h @@ -1,140 +1 @@ -/* - ENDIANAC.h - - Copyright (C) 2006 Bernd Schmidt, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - ENDIAN ACcess - - Deals with endian issues in memory access. - - This code is adapted from code in the Un*x Amiga Emulator by - Bernd Schmidt, as found in vMac by Philip Cummins. -*/ - -#ifdef ENDIANAC_H -#ifndef AllFiles -#error "header already included" -#endif -#else -#define ENDIANAC_H -#endif - -#if 0 -/* works in GCC from Apple. others? */ -static inline ui5r MySwapUi5r(ui5r _data) -{ - __asm__ ("bswap %0" : "+r" (_data)); - return _data; -} -#define HaveMySwapUi5r 1 -#endif - -#ifndef HaveMySwapUi5r -#define HaveMySwapUi5r 0 -#endif - -#define do_get_mem_byte(a) ((ui3r)*((ui3b *)(a))) - -#if BigEndianUnaligned -#define do_get_mem_word(a) ((ui4r)*((ui4b *)(a))) -#else -static MayInline ui4r do_get_mem_word(ui3p a) -{ -#if LittleEndianUnaligned - ui4b b = (*((ui4b *)(a))); - - return ((b & 0x00FF) << 8) | ((b >> 8) & 0x00FF); -#else - return (((ui4r)*a) << 8) | ((ui4r)*(a + 1)); -#endif -} -#endif - -#if BigEndianUnaligned -#define do_get_mem_long(a) ((ui5r)*((ui5b *)(a))) -#elif HaveMySwapUi5r && LittleEndianUnaligned -#define do_get_mem_long(a) (MySwapUi5r((ui5r)*((ui5b *)(a)))) -#else -static MayInline ui5r do_get_mem_long(ui3p a) -{ -#if LittleEndianUnaligned -#if 0 - return ((b << 24) & 0xFF000000) - | ((b << 8) & 0x00FF0000) - | ((b >> 8) & 0x0000FF00) - | ((b >> 24) & 0x000000FF); - /* - no, this doesn't do well with apple tools, - instead try combining two 16 bit swaps. - */ -#endif - ui5b b = (*((ui5b *)(a))); - ui4b b1 = b; - ui4b b2 = b >> 16; - ui4b c1 = ((b1 & 0x00FF) << 8) | ((b1 >> 8) & 0x00FF); - ui4b c2 = ((b2 & 0x00FF) << 8) | ((b2 >> 8) & 0x00FF); - - return (((ui5r)c1) << 16) | ((ui5r)c2); - /* - better, though still doesn't use BSWAP - instruction with apple tools for intel. - */ -#else - return (((ui5r)*a) << 24) | (((ui5r)*(a + 1)) << 16) - | (((ui5r)*(a + 2)) << 8) | ((ui5r)*(a + 3)); -#endif -} -#endif - -#define do_put_mem_byte(a, v) ((*((ui3b *)(a))) = (v)) - -#if BigEndianUnaligned -#define do_put_mem_word(a, v) ((*((ui4b *)(a))) = (v)) -#else -static MayInline void do_put_mem_word(ui3p a, ui4r v) -{ -#if LittleEndianUnaligned - ui4b b = ((v & 0x00FF) << 8) | ((v >> 8) & 0x00FF); - - *(ui4b *)a = b; -#else - *a = v >> 8; - *(a + 1) = v; -#endif -} -#endif - -#if BigEndianUnaligned -#define do_put_mem_long(a, v) ((*((ui5b *)(a))) = (v)) -#elif HaveMySwapUi5r && LittleEndianUnaligned -#define do_put_mem_long(a, v) ((*((ui5b *)(a))) = MySwapUi5r(v)) -#else -static MayInline void do_put_mem_long(ui3p a, ui5r v) -{ -#if LittleEndianUnaligned - ui4b b1 = v; - ui4b b2 = v >> 16; - ui4b c1 = ((b1 & 0x00FF) << 8) | ((b1 >> 8) & 0x00FF); - ui4b c2 = ((b2 & 0x00FF) << 8) | ((b2 >> 8) & 0x00FF); - - *(ui5b *)a = (c1 << 16) | c2; -#else - *a = v >> 24; - *(a + 1) = v >> 16; - *(a + 2) = v >> 8; - *(a + 3) = v; -#endif -} -#endif +/* ENDIANAC.h Copyright (C) 2006 Bernd Schmidt, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* ENDIAN ACcess Deals with endian issues in memory access. This code is adapted from code in the Un*x Amiga Emulator by Bernd Schmidt, as found in vMac by Philip Cummins. */ #ifdef ENDIANAC_H #ifndef AllFiles #error "header already included" #endif #else #define ENDIANAC_H #endif #define do_get_mem_byte(a) ((ui3r)*((ui3b *)(a))) #if BigEndianUnaligned #define do_get_mem_word(a) ((ui4r)*((ui4b *)(a))) #else LOCALINLINEFUNC ui4r do_get_mem_word(ui3p a) { #if LittleEndianUnaligned ui4b b = (*((ui4b *)(a))); return ((b & 0x00FF) << 8) | ((b >> 8) & 0x00FF); #else return (((ui4r)*a) << 8) | ((ui4r)*(a + 1)); #endif } #endif #if BigEndianUnaligned #define do_get_mem_long(a) ((ui5r)*((ui5b *)(a))) #elif HaveMySwapUi5r && LittleEndianUnaligned #define do_get_mem_long(a) (MySwapUi5r((ui5r)*((ui5b *)(a)))) #else LOCALINLINEFUNC ui5r do_get_mem_long(ui3p a) { #if LittleEndianUnaligned #if 0 ui5b b = (*((ui5b *)(a))); return ((b & 0x000000FF) << 24) | ((b & 0x0000FF00) << 8) | ((b & 0x00FF0000) >> 8) | ((b & 0xFF000000) >> 24); #endif #if 0 ui5b b = (*((ui5b *)(a))); return ((b << 24) & 0xFF000000) | ((b << 8) & 0x00FF0000) | ((b >> 8) & 0x0000FF00) | ((b >> 24) & 0x000000FF); /* no, this doesn't do well with apple tools, instead try combining two 16 bit swaps. */ #endif ui5b b = (*((ui5b *)(a))); ui4b b1 = b; ui4b b2 = b >> 16; ui4b c1 = ((b1 & 0x00FF) << 8) | ((b1 >> 8) & 0x00FF); ui4b c2 = ((b2 & 0x00FF) << 8) | ((b2 >> 8) & 0x00FF); return (((ui5r)c1) << 16) | ((ui5r)c2); /* better, though still doesn't use BSWAP instruction with apple tools for intel. */ #else return (((ui5r)*a) << 24) | (((ui5r)*(a + 1)) << 16) | (((ui5r)*(a + 2)) << 8) | ((ui5r)*(a + 3)); #endif } #endif #define do_put_mem_byte(a, v) ((*((ui3b *)(a))) = (v)) #if BigEndianUnaligned #define do_put_mem_word(a, v) ((*((ui4b *)(a))) = (v)) #else LOCALINLINEFUNC void do_put_mem_word(ui3p a, ui4r v) { #if LittleEndianUnaligned ui4b b = ((v & 0x00FF) << 8) | ((v >> 8) & 0x00FF); *(ui4b *)a = b; #else *a = v >> 8; *(a + 1) = v; #endif } #endif #if BigEndianUnaligned #define do_put_mem_long(a, v) ((*((ui5b *)(a))) = (v)) #elif HaveMySwapUi5r && LittleEndianUnaligned #define do_put_mem_long(a, v) ((*((ui5b *)(a))) = MySwapUi5r(v)) #else LOCALINLINEFUNC void do_put_mem_long(ui3p a, ui5r v) { #if LittleEndianUnaligned ui4b b1 = v; ui4b b2 = v >> 16; ui4b c1 = ((b1 & 0x00FF) << 8) | ((b1 >> 8) & 0x00FF); ui4b c2 = ((b2 & 0x00FF) << 8) | ((b2 >> 8) & 0x00FF); *(ui5b *)a = (c1 << 16) | c2; #else *a = v >> 24; *(a + 1) = v >> 16; *(a + 2) = v >> 8; *(a + 3) = v; #endif } #endif \ No newline at end of file diff --git a/Mini vMac/mnvm_core/FB1BPP2I.h b/Mini vMac/mnvm_core/FB1BPP2I.h deleted file mode 100755 index e1e5406..0000000 --- a/Mini vMac/mnvm_core/FB1BPP2I.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - FB1BPP2I.h - - Copyright (C) 2012 Kevin Keeling - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -EXPORTPROC FB1BPPtoIndexed(u32*, u8*, int); diff --git a/Mini vMac/mnvm_core/FPCPEMDV.h b/Mini vMac/mnvm_core/FPCPEMDV.h index 380c254..c005966 100755 --- a/Mini vMac/mnvm_core/FPCPEMDV.h +++ b/Mini vMac/mnvm_core/FPCPEMDV.h @@ -1,1142 +1 @@ -/* - FPCPEMDV.h - - Copyright (C) 2007 Ross Martin, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - Floating Point CoProcessor Emulated Device - (included by MINEM68K.c) -*/ - - -LOCALVAR struct fpustruct -{ - myfpr fp[8]; - CPTR FPIAR; /* Floating point instruction address register */ -} fpu_dat; - -LOCALPROC myfp_SetFPIAR(ui5r v) -{ - fpu_dat.FPIAR = v; -} - -LOCALFUNC ui5r myfp_GetFPIAR(void) -{ - return fpu_dat.FPIAR; -} - -LOCALFUNC blnr MayNotInline DecodeAddrModeRegister( - ui5b themode, ui5b thereg) -{ - switch (themode) { - case 2 : - case 3 : - case 4 : - case 5 : - case 6 : - DecodeModeRegister(themode, thereg); - return trueblnr; - break; - case 7 : - switch (thereg) { - case 0 : - case 1 : - case 2 : - case 3 : - DecodeModeRegister(themode, thereg); - return trueblnr; - break; - case 4 : - regs.ArgKind = AKMemory; - regs.ArgAddr.mem = m68k_getpc(); - if (regs.opsize == 1) { - ++regs.ArgAddr.mem; - } - m68k_setpc(regs.ArgAddr.mem + regs.opsize); - return trueblnr; - break; - default : - return falseblnr; - break; - } - break; - default : - return falseblnr; - break; - } -} - -LOCALPROC read_long_double(ui5r addr, myfpr *r) -{ - ui4r v2; - ui5r v1; - ui5r v0; - - v2 = get_word(addr + 0); - /* ignore word at offset 2 */ - v1 = get_long(addr + 4); - v0 = get_long(addr + 8); - - myfp_FromExtendedFormat(r, v2, v1, v0); -} - -LOCALPROC write_long_double(ui5r addr, myfpr *xx) -{ - ui4r v2; - ui5r v1; - ui5r v0; - - myfp_ToExtendedFormat(xx, &v2, &v1, &v0); - - put_word(addr + 0, v2); - put_word(addr + 2, 0); - put_long(addr + 4, v1); - put_long(addr + 8, v0); -} - -LOCALPROC read_double(ui5r addr, myfpr *r) -{ - ui5r v1; - ui5r v0; - - v1 = get_long(addr + 0); - v0 = get_long(addr + 4); - - myfp_FromDoubleFormat(r, v1, v0); -} - -LOCALPROC write_double(ui5r addr, myfpr *dd) -{ - ui5r v1; - ui5r v0; - - myfp_ToDoubleFormat(dd, &v1, &v0); - - put_long(addr + 0, v1); - put_long(addr + 4, v0); -} - -#if 0 -LOCALPROC read_single(ui5r addr, myfpr *r) -{ - myfp_FromSingleFormat(r, get_long(addr)); -} - -LOCALPROC write_single(ui5r addr, myfpr *ff) -{ - put_long(addr, myfp_ToSingleFormat(ff)); -} -#endif - - -LOCALFUNC int CheckFPCondition(ui4b predicate) -{ - int condition_true = 0; - - ui3r cc = myfp_GetConditionCodeByte(); - - int c_nan = (cc) & 1; - /* int c_inf = (cc >> 1) & 1; */ - int c_zero = (cc >> 2) & 1; - int c_neg = (cc >> 3) & 1; - - /* - printf( - "FPSR Checked: c_nan=%d, c_zero=%d, c_neg=%d," - " predicate=0x%04x\n", - c_nan, c_zero, c_neg, predicate); - */ - - switch (predicate) { - case 0x11: /* SEQ */ - case 0x01: /* EQ */ - condition_true = c_zero; - break; - case 0x1E: /* SNE */ - case 0x0E: /* NE */ - condition_true = ! c_zero; - break; - case 0x02: /* OGT */ - case 0x12: /* GT */ - condition_true = (! c_neg) && (! c_zero) && (! c_nan); - break; - case 0x0D: /* ULE */ - case 0x1D: /* NGT */ - condition_true = c_neg || c_zero || c_nan; - break; - case 0x03: /* OGE */ - case 0x13: /* GE */ - condition_true = c_zero || ((! c_neg) && (! c_nan)); - break; - case 0x0C: /* ULT */ - case 0x1C: /* NGE */ - condition_true = c_nan || ((! c_zero) && c_neg) ; - break; - case 0x04: /* OLT */ - case 0x14: /* LT */ - condition_true = c_neg && (! c_nan) && (! c_zero); - break; - case 0x0B: /* UGE */ - case 0x1B: /* NLT */ - condition_true = c_nan || c_zero || (! c_neg); - break; - case 0x05: /* OLE */ - case 0x15: /* LE */ - condition_true = ((! c_nan) && c_neg) || c_zero; - break; - case 0x0A: /* UGT */ - case 0x1A: /* NLE */ - condition_true = c_nan || ((! c_neg) && (! c_zero)); - break; - case 0x06: /* OGL */ - case 0x16: /* GL */ - condition_true = (! c_nan) && (! c_zero); - break; - case 0x09: /* UEQ */ - case 0x19: /* NGL */ - condition_true = c_nan || c_zero; - break; - case 0x07: /* OR */ - case 0x17: /* GLE */ - condition_true = ! c_nan; - break; - case 0x08: /* NGLE */ - case 0x18: /* NGLE */ - condition_true = c_nan; - break; - case 0x00: /* SFALSE */ - case 0x10: /* FALSE */ - condition_true = 0; - break; - case 0x0F: /* STRUE */ - case 0x1F: /* TRUE */ - condition_true = 1; - break; - } - - /* printf("condition_true=%d\n", condition_true); */ - - return condition_true; -} - -LOCALPROCUSEDONCE DoCodeFPU_Save(void) -{ - if ((regs.opcode == 0xF327) || (regs.opcode == 0xF32D)) { -#if 0 - regs.opsize = 4; /* actually unsized */ - DecodeModeRegister(mode, reg); - SetArgValue(0); /* for now, try null state frame */ -#endif - /* 28 byte 68881 IDLE frame */ - - regs.opsize = 28; /* actually unsized */ - if (! DecodeAddrModeRegister(mode, reg)) { - ReportAbnormal( - "DecodeAddrModeRegister fails in DoCodeFPU_Save"); - } else { - put_long(regs.ArgAddr.mem, 0x1f180000); - put_long(regs.ArgAddr.mem + 4, 0); - put_long(regs.ArgAddr.mem + 8, 0); - put_long(regs.ArgAddr.mem + 12, 0); - put_long(regs.ArgAddr.mem + 16, 0); - put_long(regs.ArgAddr.mem + 20, 0); - put_long(regs.ArgAddr.mem + 24, 0x70000000); - } - - } else { - ReportAbnormal("unimplemented FPU Save"); - DoCodeFdefault(); - } -} - -LOCALPROCUSEDONCE DoCodeFPU_Restore(void) -{ - if ((regs.opcode == 0xF35F) || (regs.opcode == 0xF36D)) { - ui5r dstvalue; - regs.opsize = 4; /* actually unsized */ - - if (! DecodeAddrModeRegister(mode, reg)) { - ReportAbnormal( - "DecodeAddrModeRegister fails in DoCodeFPU_Restore"); - DoCodeFdefault(); - } else { - dstvalue = get_long(regs.ArgAddr.mem); - if (dstvalue != 0) { - if (0x1f180000 == dstvalue) { - if (3 == mode) { - m68k_areg(reg) = regs.ArgAddr.mem + 28; - } - } else { - ReportAbnormal("unknown restore"); - /* not a null state we saved */ - DoCodeFdefault(); - } - } - } - } else { - ReportAbnormal("unimplemented FPU Restore"); - DoCodeFdefault(); - } -} - -LOCALPROC DoCodeFPU_FBcc(blnr IsLong) -{ - /* - Also get here for a NOP instruction (opcode 0xF280), - which is simply a FBF.w with offset 0 - */ - - ui4b predicate = regs.opcode & 0x3F; - - int condition_true = CheckFPCondition(predicate); - -#if FastRelativeJump - ui3p s = regs.pc_p; -#else - ui5r s = m68k_getpc(); -#endif - - - if (IsLong) { - s += ui5r_FromSLong(nextilong()); - } else { - s += ui5r_FromSWord(nextiword()); - } - - if (condition_true) { -#if FastRelativeJump - regs.pc_p = s; -#else - m68k_setpc(s); -#endif - } - - /* printf("pc_p set to 0x%p in FBcc (32bit)\n", regs.pc_p); */ -} - -LOCALPROCUSEDONCE DoCodeFPU_DBcc(void) -{ - ui4b word2 = (int)nextiword(); - - ui4b predicate = word2 & 0x3F; - - int condition_true = CheckFPCondition(predicate); - -#if FastRelativeJump - ui3p srcvalue = regs.pc_p; -#else - ui5r srcvalue = m68k_getpc(); -#endif - - srcvalue += (si5b)(si4b)nextiword(); - - if (! condition_true) { - ui5b fdb_count = ui5r_FromSWord(m68k_dreg(reg)) - 1; - m68k_dreg(reg) = - (m68k_dreg(reg) & ~ 0xFFFF) | (fdb_count & 0xFFFF); - if ((si5b)fdb_count != -1) { -#if FastRelativeJump - regs.pc_p = srcvalue; -#else - m68k_setpc(srcvalue); -#endif - - /* printf("pc_p set to 0x%p in DoCodeDBcc\n", regs.pc_p); */ - } - } -} - -LOCALPROCUSEDONCE DoCodeFPU_Trapcc(void) -{ - ui4b word2 = (int)nextiword(); - - ui4b predicate = word2 & 0x3F; - - int condition_true = CheckFPCondition(predicate); - - if (reg == 2) { - (void) nextiword(); - } else if (reg == 3) { - (void) nextilong(); - } else if (reg == 4) { - } else { - ReportAbnormal("Invalid FTRAPcc (?"); - } - - if (condition_true) { - ReportAbnormal("FTRAPcc trapping"); - Exception(7); - } -} - -LOCALPROCUSEDONCE DoCodeFPU_Scc(void) -{ - ui4b word2 = (int)nextiword(); - - ui4b predicate = word2 & 0x3F; - - int condition_true = CheckFPCondition(predicate); - - regs.opsize = 1; - DecodeModeRegister(mode, reg); - if (condition_true) { - SetArgValue(0xFFFF); - } else { - SetArgValue(0x0000); - } -} - -LOCALPROC DoCodeF_InvalidPlusWord(void) -{ - BackupPC(); - DoCodeFdefault(); -} - -LOCALFUNC int CountCSIAlist(ui4b word2) -{ - ui4b regselect = (word2 >> 10) & 0x7; - int num = 0; - - if (regselect & 1) { - num++; - } - if (regselect & 2) { - num++; - } - if (regselect & 4) { - num++; - } - - return num; -} - -LOCALPROCUSEDONCE DoCodeFPU_Move_EA_CSIA(ui4b word2) -{ - int n; - ui5b ea_value[3]; - ui4b regselect = (word2 >> 10) & 0x7; - int num = CountCSIAlist(word2); - - if (regselect == 0) { - ReportAbnormal("Invalid FMOVE instruction"); - DoCodeF_InvalidPlusWord(); - return; - } - - /* FMOVEM.L , */ - - regs.opsize = 4 * num; - DecodeModeRegister(mode, reg); - - regs.opsize = 4; - ea_value[0] = GetArgValue(); - if (num > 1) { - ea_value[1] = get_long(regs.ArgAddr.mem + 4); - } - if (num > 2) { - ea_value[2] = get_long(regs.ArgAddr.mem + 8); - } - - n = 0; - if (regselect & (1 << 2)) { - myfp_SetFPCR(ea_value[n++]); - } - if (regselect & (1 << 1)) { - myfp_SetFPSR(ea_value[n++]); - } - if (regselect & (1 << 0)) { - myfp_SetFPIAR(ea_value[n++]); - } -} - -LOCALPROCUSEDONCE DoCodeFPU_MoveM_CSIA_EA(ui4b word2) -{ - int n; - ui5b ea_value[3]; - int num = CountCSIAlist(word2); - - ui4b regselect = (word2 >> 10) & 0x7; - - if (regselect == 0) { - ReportAbnormal("Invalid FMOVE instruction"); - DoCodeF_InvalidPlusWord(); - return; - } - - /* FMOVEM.L , */ - - n = 0; - if (regselect & (1 << 2)) { - ea_value[n++] = myfp_GetFPCR(); - } - if (regselect & (1 << 1)) { - ea_value[n++] = myfp_GetFPSR(); - } - if (regselect & (1 << 0)) { - ea_value[n++] = myfp_GetFPIAR(); - } - - regs.opsize = 4 * num; - DecodeModeRegister(mode, reg); - - SetArgValue(ea_value[0]); - if (num > 1) { - put_long(regs.ArgAddr.mem + 4, ea_value[1]); - } - if (num > 2) { - put_long(regs.ArgAddr.mem + 8, ea_value[2]); - } -} - -LOCALPROCUSEDONCE DoCodeFPU_MoveM_EA_list(ui4b word2) -{ - int i; - ui5r myaddr; - ui4b register_list = word2; - - ui4b fmove_mode = (word2 >> 11) & 0x3; - - /* FMOVEM.X , */ - - if ((fmove_mode == 0) || (fmove_mode == 1)) { - ReportAbnormal("Invalid FMOVEM.X instruction"); - DoCodeF_InvalidPlusWord(); - return; - } - - if (fmove_mode == 3) { - /* Dynamic mode */ - register_list = regs.regs[(word2 >> 4) & 7]; - } - - if (mode == 3) { - /* Postincrement mode */ - - for (i = 0; i <= 7; i++) { - int j = 1 << (7 - i); - if (j & register_list) { - regs.opsize = 12; - DecodeModeRegister(mode, reg); - read_long_double(regs.ArgAddr.mem, &fpu_dat.fp[i]); - } - } - } else { - /* Control mode */ - - regs.opsize = 12; - DecodeModeRegister(mode, reg); - - myaddr = regs.ArgAddr.mem; - - for (i = 0; i <= 7; i++) { - int j = 1 << (7 - i); - if (j & register_list) { - read_long_double(myaddr, &fpu_dat.fp[i]); - myaddr += 12; - } - } - } -} - -LOCALPROCUSEDONCE DoCodeFPU_MoveM_list_EA(ui4b word2) -{ - /* FMOVEM.X , */ - - int i; - ui5r myaddr; - ui4b register_list = word2; - - ui4b fmove_mode = (word2 >> 11) & 0x3; - - if ((fmove_mode == 1) || (fmove_mode == 3)) { - /* Dynamic mode */ - register_list = regs.regs[(word2 >> 4) & 7]; - } - - if (mode == 4) { - /* Predecrement mode */ - - for (i = 7; i >= 0; i--) { - int j = 1 << i; - if (j & register_list) { - regs.opsize = 12; - DecodeModeRegister(mode, reg); - write_long_double(regs.ArgAddr.mem, &fpu_dat.fp[i]); - } - } - } else { - /* Control mode */ - - regs.opsize = 12; - DecodeModeRegister(mode, reg); - - myaddr = regs.ArgAddr.mem; - - for (i = 0; i <= 7; i++) { - int j = 1 << (7 - i); - if (j & register_list) { - write_long_double(myaddr, &fpu_dat.fp[i]); - myaddr += 12; - } - } - } -} - -LOCALPROCUSEDONCE DoCodeFPU_MoveCR(ui4b word2) -{ - /* FMOVECR */ - - if (regs.opcode != 0xF200) { - ReportAbnormal("bad opcode in FMOVECR"); - DoCodeF_InvalidPlusWord(); - } else { - ui4b RomOffset = word2 & 0x7F; - ui4b DestReg = (word2 >> 7) & 0x7; - - if (! myfp_getCR(&fpu_dat.fp[DestReg], RomOffset)) { - ReportAbnormal("Invalid constant number in FMOVECR"); - DoCodeF_InvalidPlusWord(); - } - } -} - -LOCALPROC SaveResultAndFPSR(myfpr *DestReg, myfpr *result) -{ - *DestReg = *result; - myfp_SetConditionCodeByteFromResult(result); -} - -LOCALPROC DoCodeFPU_GenOp(ui4b word2, myfpr *source) -{ - myfpr result; - myfpr t0; - myfpr *DestReg = &fpu_dat.fp[(word2 >> 7) & 0x7]; - - switch (word2 & 0x7F) { - - case 0x00: /* FMOVE */ - SaveResultAndFPSR(DestReg, source); - break; - - case 0x01: /* FINT */ - myfp_Int(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x02: /* FSINH */ - myfp_Sinh(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x03: /* FINTRZ */ - myfp_IntRZ(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x04: /* FSQRT */ - myfp_Sqrt(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x06: /* FLOGNP1 */ - myfp_LogNP1(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x08: /* FETOXM1 */ - myfp_EToXM1(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x09: /* FTANH */ - myfp_Tanh(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x0A: /* FATAN */ - myfp_ATan(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x0C: /* FASIN */ - myfp_ASin(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x0D: /* FATANH */ - myfp_ATanh(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x0E: /* FSIN */ - myfp_Sin(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x0F: /* FTAN */ - myfp_Tan(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x10: /* FETOX */ - myfp_EToX(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x11: /* FTWOTOX */ - myfp_TwoToX(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x12: /* FTENTOX */ - myfp_TenToX(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x14: /* FLOGN */ - myfp_LogN(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x15: /* FLOG10 */ - myfp_Log10(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x16: /* FLOG2 */ - myfp_Log2(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x18: /* FABS */ - myfp_Abs(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x19: /* FCOSH */ - myfp_Cosh(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x1A: /* FNEG */ - myfp_Neg(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x1C: /* FACOS */ - myfp_ACos(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x1D: /* FCOS */ - myfp_Cos(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x1E: /* FGETEXP */ - myfp_GetExp(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x1F: /* FGETMAN */ - myfp_GetMan(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x20: /* FDIV */ - myfp_Div(&result, DestReg, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x21: /* FMOD */ /* 0x2D in some docs, 0x21 in others ? */ - myfp_Mod(&result, DestReg, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x22: /* FADD */ - myfp_Add(&result, DestReg, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x23: /* FMUL */ - myfp_Mul(&result, DestReg, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x24: /* FSGLDIV */ - myfp_Div(&t0, DestReg, source); - myfp_RoundToSingle(&result, &t0); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x25: /* FREM */ - myfp_Rem(&result, DestReg, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x26: /* FSCALE */ - myfp_Scale(&result, DestReg, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x27: /* FSGLMUL */ - myfp_Mul(&t0, DestReg, source); - myfp_RoundToSingle(&result, &t0); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x28: /* FSUB */ - myfp_Sub(&result, DestReg, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - /* FSINCOS */ - myfp_SinCos(&result, &fpu_dat.fp[word2 & 0x7], source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x38: /* FCMP */ - myfp_Sub(&result, DestReg, source); - /* don't save result */ - myfp_SetConditionCodeByteFromResult(&result); - break; - - case 0x3A: /* FTST */ - myfp_SetConditionCodeByteFromResult(source); - break; - - /* - everything after here is not in 68881/68882, - appears first in 68040 - */ - - case 0x40: /* FSMOVE */ - myfp_RoundToSingle(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x41: /* FSSQRT */ - myfp_Sqrt(&t0, source); - myfp_RoundToSingle(&result, &t0); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x44: /* FDMOVE */ - myfp_RoundToDouble(&result, source); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x45: /* FDSQRT */ - myfp_Sqrt(&t0, source); - myfp_RoundToDouble(&result, &t0); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x58: /* FSABS */ - myfp_Abs(&t0, source); - myfp_RoundToSingle(&result, &t0); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x5A: /* FSNEG */ - myfp_Neg(&t0, source); - myfp_RoundToSingle(&result, &t0); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x5C: /* FDABS */ - myfp_Abs(&t0, source); - myfp_RoundToDouble(&result, &t0); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x5E: /* FDNEG */ - myfp_Neg(&t0, source); - myfp_RoundToDouble(&result, &t0); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x60: /* FSDIV */ - myfp_Div(&t0, DestReg, source); - myfp_RoundToSingle(&result, &t0); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x62: /* FSADD */ - myfp_Add(&t0, DestReg, source); - myfp_RoundToSingle(&result, &t0); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x63: /* FSMUL */ - myfp_Mul(&t0, DestReg, source); - myfp_RoundToSingle(&result, &t0); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x64: /* FDDIV */ - myfp_Div(&t0, DestReg, source); - myfp_RoundToDouble(&result, &t0); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x66: /* FDADD */ - myfp_Add(&t0, DestReg, source); - myfp_RoundToDouble(&result, &t0); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x67: /* FDMUL */ - myfp_Mul(&t0, DestReg, source); - myfp_RoundToDouble(&result, &t0); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x68: /* FSSUB */ - myfp_Sub(&t0, DestReg, source); - myfp_RoundToSingle(&result, &t0); - SaveResultAndFPSR(DestReg, &result); - break; - - case 0x6C: /* FDSUB */ - myfp_Sub(&t0, DestReg, source); - myfp_RoundToDouble(&result, &t0); - SaveResultAndFPSR(DestReg, &result); - break; - - default: - ReportAbnormal("Invalid Floating Point Instruction"); - DoCodeF_InvalidPlusWord(); - break; - } -} - -LOCALPROCUSEDONCE DoCodeFPU_GenOpReg(ui4b word2) -{ - ui4r regselect = (word2 >> 10) & 0x7; - - DoCodeFPU_GenOp(word2, &fpu_dat.fp[regselect]); -} - -LOCALPROCUSEDONCE DoCodeFPU_GenOpEA(ui4b word2) -{ - myfpr source; - - switch ((word2 >> 10) & 0x7) { - case 0: /* long-word integer */ - regs.opsize = 4; - DecodeModeRegister(mode, reg); - myfp_FromLong(&source, GetArgValue()); - DoCodeFPU_GenOp(word2, &source); - break; - case 1: /* Single-Precision real */ - regs.opsize = 4; - DecodeModeRegister(mode, reg); - myfp_FromSingleFormat(&source, GetArgValue()); - DoCodeFPU_GenOp(word2, &source); - break; - case 2: /* extended precision real */ - regs.opsize = 12; - if (! DecodeAddrModeRegister(mode, reg)) { - ReportAbnormal( - "DecodeAddrModeRegister fails GetFPSource X"); - DoCodeF_InvalidPlusWord(); - } else { - read_long_double(regs.ArgAddr.mem, &source); - DoCodeFPU_GenOp(word2, &source); - } - break; - case 3: /* packed-decimal real */ - ReportAbnormal("Packed Decimal in GetFPSource"); - regs.opsize = 16; - /* correct? just set to a constant for now */ - if (! DecodeAddrModeRegister(mode, reg)) { - ReportAbnormal( - "DecodeAddrModeRegister fails GetFPSource P"); - DoCodeF_InvalidPlusWord(); - } else { - /* *r = 9123456789.0; */ - DoCodeFPU_GenOp(word2, &source); - } - break; - case 4: /* Word integer */ - regs.opsize = 2; - DecodeModeRegister(mode, reg); - myfp_FromLong(&source, GetArgValue()); - DoCodeFPU_GenOp(word2, &source); - break; - case 5: /* Double-precision real */ - regs.opsize = 8; - if (! DecodeAddrModeRegister(mode, reg)) { - ReportAbnormal( - "DecodeAddrModeRegister fails GetFPSource D"); - DoCodeF_InvalidPlusWord(); - } else { - read_double(regs.ArgAddr.mem, &source); - DoCodeFPU_GenOp(word2, &source); - } - break; - case 6: /* Byte Integer */ - regs.opsize = 1; - DecodeModeRegister(mode, reg); - myfp_FromLong(&source, GetArgValue()); - DoCodeFPU_GenOp(word2, &source); - break; - case 7: /* Not a valid source specifier */ - DoCodeFPU_MoveCR(word2); - break; - default: - /* should not be able to get here */ - break; - } -} - -LOCALPROCUSEDONCE DoCodeFPU_Move_FP_EA(ui4b word2) -{ - /* FMOVE FP?, */ - - ui4r SourceReg = (word2 >> 7) & 0x7; - myfpr *source = &fpu_dat.fp[SourceReg]; - - switch ((word2 >> 10) & 0x7) { - case 0: /* long-word integer */ - regs.opsize = 4; - DecodeModeRegister(mode, reg); - SetArgValue(myfp_ToLong(source)); - break; - case 1: /* Single-Precision real */ - regs.opsize = 4; - DecodeModeRegister(mode, reg); - SetArgValue(myfp_ToSingleFormat(source)); - break; - case 2: /* extended precision real */ - regs.opsize = 12; - if (! DecodeAddrModeRegister(mode, reg)) { - ReportAbnormal("DecodeAddrModeRegister fails FMOVE X"); - DoCodeF_InvalidPlusWord(); - } else { - write_long_double(regs.ArgAddr.mem, source); - } - break; - case 3: /* packed-decimal real */ - ReportAbnormal("Packed Decimal in FMOVE"); - regs.opsize = 16; /* correct? don't even write anything */ - if (! DecodeAddrModeRegister(mode, reg)) { - ReportAbnormal("DecodeAddrModeRegister fails FMOVE P"); - DoCodeF_InvalidPlusWord(); - } else { - /* ? */ - } - break; - case 4: /* Word integer */ - regs.opsize = 2; - DecodeModeRegister(mode, reg); - SetArgValue(myfp_ToLong(source)); - break; - case 5: /* Double-precision real */ - regs.opsize = 8; - if (! DecodeAddrModeRegister(mode, reg)) { - ReportAbnormal("DecodeAddrModeRegister fails FMOVE D"); - DoCodeF_InvalidPlusWord(); - } else { - write_double(regs.ArgAddr.mem, source); - } - break; - case 6: /* Byte Integer */ - regs.opsize = 1; - DecodeModeRegister(mode, reg); - SetArgValue(myfp_ToLong(source)); - break; - default: - ReportAbnormal("Bad Source Specifier in FMOVE"); - DoCodeF_InvalidPlusWord(); - break; - } -} - -LOCALPROCUSEDONCE DoCodeFPU_md60(void) -{ - ui4b word2 = (int)nextiword(); - - switch ((word2 >> 13) & 0x7) { - case 0: - DoCodeFPU_GenOpReg(word2); - break; - case 2: - DoCodeFPU_GenOpEA(word2); - break; - case 3: - DoCodeFPU_Move_FP_EA(word2); - break; - case 4: - DoCodeFPU_Move_EA_CSIA(word2); - break; - case 5: - DoCodeFPU_MoveM_CSIA_EA(word2); - break; - case 6: - DoCodeFPU_MoveM_EA_list(word2); - break; - case 7: - DoCodeFPU_MoveM_list_EA(word2); - break; - default: - ReportAbnormal("Invalid Floating Point Instruction"); - DoCodeF_InvalidPlusWord(); - break; - } -} - -LOCALPROCUSEDONCE DoCodeFPU(void) -{ - switch (md6) { - case 0: - DoCodeFPU_md60(); - break; - case 1: - if (mode == 1) { - DoCodeFPU_DBcc(); - } else if (mode == 7) { - DoCodeFPU_Trapcc(); - } else { - DoCodeFPU_Scc(); - } - break; - case 2: - DoCodeFPU_FBcc(falseblnr); - break; - case 3: - DoCodeFPU_FBcc(trueblnr); - break; - case 4: - DoCodeFPU_Save(); - break; - case 5: - DoCodeFPU_Restore(); - break; - default: - /* fall through */ - ReportAbnormal("Invalid Floating Point Instruction"); - DoCodeFdefault(); - break; - } -} +/* FPCPEMDV.h Copyright (C) 2007 Ross Martin, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* Floating Point CoProcessor Emulated Device (included by MINEM68K.c) */ /* ReportAbnormalID unused 0x0306 - 0x03FF */ LOCALVAR struct fpustruct { myfpr fp[8]; CPTR FPIAR; /* Floating point instruction address register */ } fpu_dat; LOCALPROC myfp_SetFPIAR(ui5r v) { fpu_dat.FPIAR = v; } LOCALFUNC ui5r myfp_GetFPIAR(void) { return fpu_dat.FPIAR; } LOCALFUNC blnr DecodeAddrModeRegister(ui5b sz) { ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat; ui4r themode = (Dat >> 3) & 7; ui4r thereg = Dat & 7; switch (themode) { case 2 : case 3 : case 4 : case 5 : case 6 : return DecodeModeRegister(sz); break; case 7 : switch (thereg) { case 0 : case 1 : case 2 : case 3 : case 4 : return DecodeModeRegister(sz); break; default : return falseblnr; break; } break; default : return falseblnr; break; } } LOCALPROC read_long_double(ui5r addr, myfpr *r) { ui4r v2; ui5r v1; ui5r v0; v2 = get_word(addr + 0); /* ignore word at offset 2 */ v1 = get_long(addr + 4); v0 = get_long(addr + 8); myfp_FromExtendedFormat(r, v2, v1, v0); } LOCALPROC write_long_double(ui5r addr, myfpr *xx) { ui4r v2; ui5r v1; ui5r v0; myfp_ToExtendedFormat(xx, &v2, &v1, &v0); put_word(addr + 0, v2); put_word(addr + 2, 0); put_long(addr + 4, v1); put_long(addr + 8, v0); } LOCALPROC read_double(ui5r addr, myfpr *r) { ui5r v1; ui5r v0; v1 = get_long(addr + 0); v0 = get_long(addr + 4); myfp_FromDoubleFormat(r, v1, v0); } LOCALPROC write_double(ui5r addr, myfpr *dd) { ui5r v1; ui5r v0; myfp_ToDoubleFormat(dd, &v1, &v0); put_long(addr + 0, v1); put_long(addr + 4, v0); } #if 0 LOCALPROC read_single(ui5r addr, myfpr *r) { myfp_FromSingleFormat(r, get_long(addr)); } LOCALPROC write_single(ui5r addr, myfpr *ff) { put_long(addr, myfp_ToSingleFormat(ff)); } #endif LOCALFUNC int CheckFPCondition(ui4b predicate) { int condition_true = 0; ui3r cc = myfp_GetConditionCodeByte(); int c_nan = (cc) & 1; /* int c_inf = (cc >> 1) & 1; */ int c_zero = (cc >> 2) & 1; int c_neg = (cc >> 3) & 1; /* printf( "FPSR Checked: c_nan=%d, c_zero=%d, c_neg=%d," " predicate=0x%04x\n", c_nan, c_zero, c_neg, predicate); */ switch (predicate) { case 0x11: /* SEQ */ case 0x01: /* EQ */ condition_true = c_zero; break; case 0x1E: /* SNE */ case 0x0E: /* NE */ condition_true = ! c_zero; break; case 0x02: /* OGT */ case 0x12: /* GT */ condition_true = (! c_neg) && (! c_zero) && (! c_nan); break; case 0x0D: /* ULE */ case 0x1D: /* NGT */ condition_true = c_neg || c_zero || c_nan; break; case 0x03: /* OGE */ case 0x13: /* GE */ condition_true = c_zero || ((! c_neg) && (! c_nan)); break; case 0x0C: /* ULT */ case 0x1C: /* NGE */ condition_true = c_nan || ((! c_zero) && c_neg) ; break; case 0x04: /* OLT */ case 0x14: /* LT */ condition_true = c_neg && (! c_nan) && (! c_zero); break; case 0x0B: /* UGE */ case 0x1B: /* NLT */ condition_true = c_nan || c_zero || (! c_neg); break; case 0x05: /* OLE */ case 0x15: /* LE */ condition_true = ((! c_nan) && c_neg) || c_zero; break; case 0x0A: /* UGT */ case 0x1A: /* NLE */ condition_true = c_nan || ((! c_neg) && (! c_zero)); break; case 0x06: /* OGL */ case 0x16: /* GL */ condition_true = (! c_nan) && (! c_zero); break; case 0x09: /* UEQ */ case 0x19: /* NGL */ condition_true = c_nan || c_zero; break; case 0x07: /* OR */ case 0x17: /* GLE */ condition_true = ! c_nan; break; case 0x08: /* NGLE */ case 0x18: /* NGLE */ condition_true = c_nan; break; case 0x00: /* SFALSE */ case 0x10: /* FALSE */ condition_true = 0; break; case 0x0F: /* STRUE */ case 0x1F: /* TRUE */ condition_true = 1; break; } /* printf("condition_true=%d\n", condition_true); */ return condition_true; } LOCALIPROC DoCodeFPU_dflt(void) { ReportAbnormalID(0x0301, "unimplemented Floating Point Instruction"); #if dbglog_HAVE { ui4r opcode = ((ui4r)(V_regs.CurDecOpY.v[0].AMd) << 8) | V_regs.CurDecOpY.v[0].ArgDat; dbglog_writelnNum("opcode", opcode); } #endif DoCodeFdefault(); } LOCALIPROC DoCodeFPU_Save(void) { ui4r opcode = ((ui4r)(V_regs.CurDecOpY.v[0].AMd) << 8) | V_regs.CurDecOpY.v[0].ArgDat; if ((opcode == 0xF327) || (opcode == 0xF32D)) { #if 0 DecodeModeRegister(4); SetArgValueL(0); /* for now, try null state frame */ #endif /* 28 byte 68881 IDLE frame */ if (! DecodeAddrModeRegister(28)) { DoCodeFPU_dflt(); #if dbglog_HAVE dbglog_writeln( "DecodeAddrModeRegister fails in DoCodeFPU_Save"); #endif } else { put_long(V_regs.ArgAddr.mem, 0x1f180000); put_long(V_regs.ArgAddr.mem + 4, 0); put_long(V_regs.ArgAddr.mem + 8, 0); put_long(V_regs.ArgAddr.mem + 12, 0); put_long(V_regs.ArgAddr.mem + 16, 0); put_long(V_regs.ArgAddr.mem + 20, 0); put_long(V_regs.ArgAddr.mem + 24, 0x70000000); } } else { DoCodeFPU_dflt(); #if dbglog_HAVE dbglog_writeln("unimplemented FPU Save"); #endif } } LOCALIPROC DoCodeFPU_Restore(void) { ui4r opcode = ((ui4r)(V_regs.CurDecOpY.v[0].AMd) << 8) | V_regs.CurDecOpY.v[0].ArgDat; ui4r themode = (opcode >> 3) & 7; ui4r thereg = opcode & 7; if ((opcode == 0xF35F) || (opcode == 0xF36D)) { ui5r dstvalue; if (! DecodeAddrModeRegister(4)) { DoCodeFPU_dflt(); #if dbglog_HAVE dbglog_writeln( "DecodeAddrModeRegister fails in DoCodeFPU_Restore"); #endif } else { dstvalue = get_long(V_regs.ArgAddr.mem); if (dstvalue != 0) { if (0x1f180000 == dstvalue) { if (3 == themode) { m68k_areg(thereg) = V_regs.ArgAddr.mem + 28; } } else { DoCodeFPU_dflt(); #if dbglog_HAVE dbglog_writeln("unknown restore"); /* not a null state we saved */ #endif } } } } else { DoCodeFPU_dflt(); #if dbglog_HAVE dbglog_writeln("unimplemented FPU Restore"); #endif } } LOCALIPROC DoCodeFPU_FBccW(void) { /* Also get here for a NOP instruction (opcode 0xF280), which is simply a FBF.w with offset 0 */ ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat; if (CheckFPCondition(Dat & 0x3F)) { DoCodeBraW(); } else { SkipiWord(); } /* printf("pc_p set to 0x%p in FBcc (32bit)\n", V_pc_p); */ } LOCALIPROC DoCodeFPU_FBccL(void) { ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat; if (CheckFPCondition(Dat & 0x3F)) { DoCodeBraL(); } else { SkipiLong(); } } LOCALIPROC DoCodeFPU_DBcc(void) { ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat; ui4r thereg = Dat & 7; ui4b word2 = (int)nextiword(); ui4b predicate = word2 & 0x3F; int condition_true = CheckFPCondition(predicate); if (! condition_true) { ui5b fdb_count = ui5r_FromSWord(m68k_dreg(thereg)) - 1; m68k_dreg(thereg) = (m68k_dreg(thereg) & ~ 0xFFFF) | (fdb_count & 0xFFFF); if ((si5b)fdb_count == -1) { SkipiWord(); } else { DoCodeBraW(); } } else { SkipiWord(); } } LOCALIPROC DoCodeFPU_Trapcc(void) { ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat; ui4r thereg = Dat & 7; ui4b word2 = (int)nextiword(); ui4b predicate = word2 & 0x3F; int condition_true = CheckFPCondition(predicate); if (thereg == 2) { (void) nextiword(); } else if (thereg == 3) { (void) nextilong(); } else if (thereg == 4) { } else { ReportAbnormalID(0x0302, "Invalid FTRAPcc (?"); } if (condition_true) { ReportAbnormalID(0x0303, "FTRAPcc trapping"); Exception(7); } } LOCALIPROC DoCodeFPU_Scc(void) { ui4b word2 = (int)nextiword(); if (! DecodeModeRegister(1)) { DoCodeFPU_dflt(); #if dbglog_HAVE dbglog_writeln("bad mode/reg in DoCodeFPU_Scc"); #endif } else { if (CheckFPCondition(word2 & 0x3F)) { SetArgValueB(0xFFFF); } else { SetArgValueB(0x0000); } } } LOCALPROC DoCodeF_InvalidPlusWord(void) { BackupPC(); DoCodeFPU_dflt(); } LOCALFUNC int CountCSIAlist(ui4b word2) { ui4b regselect = (word2 >> 10) & 0x7; int num = 0; if (regselect & 1) { num++; } if (regselect & 2) { num++; } if (regselect & 4) { num++; } return num; } LOCALPROC DoCodeFPU_Move_EA_CSIA(ui4b word2) { int n; ui5b ea_value[3]; ui4b regselect = (word2 >> 10) & 0x7; int num = CountCSIAlist(word2); if (regselect == 0) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln("Invalid FMOVE instruction"); #endif return; } /* FMOVEM.L , */ if (! DecodeModeRegister(4 * num)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln("bad mode/reg in DoCodeFPU_Move_EA_CSIA"); #endif } else { ea_value[0] = GetArgValueL(); if (num > 1) { ea_value[1] = get_long(V_regs.ArgAddr.mem + 4); } if (num > 2) { ea_value[2] = get_long(V_regs.ArgAddr.mem + 8); } n = 0; if (regselect & (1 << 2)) { myfp_SetFPCR(ea_value[n++]); } if (regselect & (1 << 1)) { myfp_SetFPSR(ea_value[n++]); } if (regselect & (1 << 0)) { myfp_SetFPIAR(ea_value[n++]); } } } LOCALPROC DoCodeFPU_MoveM_CSIA_EA(ui4b word2) { int n; ui5b ea_value[3]; int num = CountCSIAlist(word2); ui4b regselect = (word2 >> 10) & 0x7; /* FMOVEM.L , */ if (0 == regselect) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln("Invalid FMOVE instruction"); #endif } else if (! DecodeModeRegister(4 * num)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln("bad mode/reg in DoCodeFPU_MoveM_CSIA_EA"); #endif } else { n = 0; if (regselect & (1 << 2)) { ea_value[n++] = myfp_GetFPCR(); } if (regselect & (1 << 1)) { ea_value[n++] = myfp_GetFPSR(); } if (regselect & (1 << 0)) { ea_value[n++] = myfp_GetFPIAR(); } SetArgValueL(ea_value[0]); if (num > 1) { put_long(V_regs.ArgAddr.mem + 4, ea_value[1]); } if (num > 2) { put_long(V_regs.ArgAddr.mem + 8, ea_value[2]); } } } LOCALPROC DoCodeFPU_MoveM_EA_list(ui4b word2) { int i; ui5r myaddr; ui5r count; ui4b register_list = word2; ui4b fmove_mode = (word2 >> 11) & 0x3; /* FMOVEM.X , */ if ((fmove_mode == 0) || (fmove_mode == 1)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln("Invalid FMOVEM.X instruction"); #endif return; } if (fmove_mode == 3) { /* Dynamic mode */ register_list = V_regs.regs[(word2 >> 4) & 7]; } count = 0; for (i = 0; i <= 7; i++) { int j = 1 << (7 - i); if (j & register_list) { ++count; } } if (! DecodeModeRegister(12 * count)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln( "DecodeModeRegister fails DoCodeFPU_MoveM_EA_list"); #endif } else { /* Postincrement mode or Control mode */ myaddr = V_regs.ArgAddr.mem; for (i = 0; i <= 7; i++) { int j = 1 << (7 - i); if (j & register_list) { read_long_double(myaddr, &fpu_dat.fp[i]); myaddr += 12; } } } } LOCALPROC DoCodeFPU_MoveM_list_EA(ui4b word2) { /* FMOVEM.X , */ int i; ui5r myaddr; ui5r count; ui4b register_list = word2; ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat; ui4r themode = (Dat >> 3) & 7; ui4b fmove_mode = (word2 >> 11) & 0x3; if ((fmove_mode == 1) || (fmove_mode == 3)) { /* Dynamic mode */ register_list = V_regs.regs[(word2 >> 4) & 7]; } count = 0; for (i = 7; i >= 0; i--) { int j = 1 << i; if (j & register_list) { ++count; } } if (! DecodeModeRegister(12 * count)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln( "DecodeModeRegister fails DoCodeFPU_MoveM_list_EA"); #endif } else { if (themode == 4) { /* Predecrement mode */ myaddr = V_regs.ArgAddr.mem + 12 * count; for (i = 7; i >= 0; i--) { int j = 1 << i; if (j & register_list) { myaddr -= 12; write_long_double(myaddr, &fpu_dat.fp[i]); } } } else { /* Control mode */ myaddr = V_regs.ArgAddr.mem; for (i = 0; i <= 7; i++) { int j = 1 << (7 - i); if (j & register_list) { write_long_double(myaddr, &fpu_dat.fp[i]); myaddr += 12; } } } } } LOCALPROC DoCodeFPU_MoveCR(ui4b word2) { /* FMOVECR */ ui4r opcode = ((ui4r)(V_regs.CurDecOpY.v[0].AMd) << 8) | V_regs.CurDecOpY.v[0].ArgDat; if (opcode != 0xF200) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln("bad opcode in FMOVECR"); #endif } else { ui4b RomOffset = word2 & 0x7F; ui4b DestReg = (word2 >> 7) & 0x7; if (! myfp_getCR(&fpu_dat.fp[DestReg], RomOffset)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln("Invalid constant number in FMOVECR"); #endif } } } LOCALPROC SaveResultAndFPSR(myfpr *DestReg, myfpr *result) { *DestReg = *result; myfp_SetConditionCodeByteFromResult(result); } LOCALPROC DoCodeFPU_GenOp(ui4b word2, myfpr *source) { myfpr result; myfpr t0; myfpr *DestReg = &fpu_dat.fp[(word2 >> 7) & 0x7]; switch (word2 & 0x7F) { case 0x00: /* FMOVE */ SaveResultAndFPSR(DestReg, source); break; case 0x01: /* FINT */ myfp_Int(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x02: /* FSINH */ myfp_Sinh(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x03: /* FINTRZ */ myfp_IntRZ(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x04: /* FSQRT */ myfp_Sqrt(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x06: /* FLOGNP1 */ myfp_LogNP1(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x08: /* FETOXM1 */ myfp_EToXM1(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x09: /* FTANH */ myfp_Tanh(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x0A: /* FATAN */ myfp_ATan(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x0C: /* FASIN */ myfp_ASin(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x0D: /* FATANH */ myfp_ATanh(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x0E: /* FSIN */ myfp_Sin(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x0F: /* FTAN */ myfp_Tan(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x10: /* FETOX */ myfp_EToX(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x11: /* FTWOTOX */ myfp_TwoToX(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x12: /* FTENTOX */ myfp_TenToX(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x14: /* FLOGN */ myfp_LogN(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x15: /* FLOG10 */ myfp_Log10(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x16: /* FLOG2 */ myfp_Log2(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x18: /* FABS */ myfp_Abs(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x19: /* FCOSH */ myfp_Cosh(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x1A: /* FNEG */ myfp_Neg(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x1C: /* FACOS */ myfp_ACos(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x1D: /* FCOS */ myfp_Cos(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x1E: /* FGETEXP */ myfp_GetExp(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x1F: /* FGETMAN */ myfp_GetMan(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x20: /* FDIV */ myfp_Div(&result, DestReg, source); SaveResultAndFPSR(DestReg, &result); break; case 0x21: /* FMOD */ /* 0x2D in some docs, 0x21 in others ? */ myfp_Mod(&result, DestReg, source); SaveResultAndFPSR(DestReg, &result); break; case 0x22: /* FADD */ myfp_Add(&result, DestReg, source); SaveResultAndFPSR(DestReg, &result); break; case 0x23: /* FMUL */ myfp_Mul(&result, DestReg, source); SaveResultAndFPSR(DestReg, &result); break; case 0x24: /* FSGLDIV */ myfp_Div(&t0, DestReg, source); myfp_RoundToSingle(&result, &t0); SaveResultAndFPSR(DestReg, &result); break; case 0x25: /* FREM */ myfp_Rem(&result, DestReg, source); SaveResultAndFPSR(DestReg, &result); break; case 0x26: /* FSCALE */ myfp_Scale(&result, DestReg, source); SaveResultAndFPSR(DestReg, &result); break; case 0x27: /* FSGLMUL */ myfp_Mul(&t0, DestReg, source); myfp_RoundToSingle(&result, &t0); SaveResultAndFPSR(DestReg, &result); break; case 0x28: /* FSUB */ myfp_Sub(&result, DestReg, source); SaveResultAndFPSR(DestReg, &result); break; case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: /* FSINCOS */ myfp_SinCos(&result, &fpu_dat.fp[word2 & 0x7], source); SaveResultAndFPSR(DestReg, &result); break; case 0x38: /* FCMP */ myfp_Sub(&result, DestReg, source); /* don't save result */ myfp_SetConditionCodeByteFromResult(&result); break; case 0x3A: /* FTST */ myfp_SetConditionCodeByteFromResult(source); break; /* everything after here is not in 68881/68882, appears first in 68040 */ case 0x40: /* FSMOVE */ myfp_RoundToSingle(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x41: /* FSSQRT */ myfp_Sqrt(&t0, source); myfp_RoundToSingle(&result, &t0); SaveResultAndFPSR(DestReg, &result); break; case 0x44: /* FDMOVE */ myfp_RoundToDouble(&result, source); SaveResultAndFPSR(DestReg, &result); break; case 0x45: /* FDSQRT */ myfp_Sqrt(&t0, source); myfp_RoundToDouble(&result, &t0); SaveResultAndFPSR(DestReg, &result); break; case 0x58: /* FSABS */ myfp_Abs(&t0, source); myfp_RoundToSingle(&result, &t0); SaveResultAndFPSR(DestReg, &result); break; case 0x5A: /* FSNEG */ myfp_Neg(&t0, source); myfp_RoundToSingle(&result, &t0); SaveResultAndFPSR(DestReg, &result); break; case 0x5C: /* FDABS */ myfp_Abs(&t0, source); myfp_RoundToDouble(&result, &t0); SaveResultAndFPSR(DestReg, &result); break; case 0x5E: /* FDNEG */ myfp_Neg(&t0, source); myfp_RoundToDouble(&result, &t0); SaveResultAndFPSR(DestReg, &result); break; case 0x60: /* FSDIV */ myfp_Div(&t0, DestReg, source); myfp_RoundToSingle(&result, &t0); SaveResultAndFPSR(DestReg, &result); break; case 0x62: /* FSADD */ myfp_Add(&t0, DestReg, source); myfp_RoundToSingle(&result, &t0); SaveResultAndFPSR(DestReg, &result); break; case 0x63: /* FSMUL */ myfp_Mul(&t0, DestReg, source); myfp_RoundToSingle(&result, &t0); SaveResultAndFPSR(DestReg, &result); break; case 0x64: /* FDDIV */ myfp_Div(&t0, DestReg, source); myfp_RoundToDouble(&result, &t0); SaveResultAndFPSR(DestReg, &result); break; case 0x66: /* FDADD */ myfp_Add(&t0, DestReg, source); myfp_RoundToDouble(&result, &t0); SaveResultAndFPSR(DestReg, &result); break; case 0x67: /* FDMUL */ myfp_Mul(&t0, DestReg, source); myfp_RoundToDouble(&result, &t0); SaveResultAndFPSR(DestReg, &result); break; case 0x68: /* FSSUB */ myfp_Sub(&t0, DestReg, source); myfp_RoundToSingle(&result, &t0); SaveResultAndFPSR(DestReg, &result); break; case 0x6C: /* FDSUB */ myfp_Sub(&t0, DestReg, source); myfp_RoundToDouble(&result, &t0); SaveResultAndFPSR(DestReg, &result); break; default: DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln("Invalid DoCodeFPU_GenOp"); #endif break; } } LOCALPROC DoCodeFPU_GenOpReg(ui4b word2) { ui4r regselect = (word2 >> 10) & 0x7; DoCodeFPU_GenOp(word2, &fpu_dat.fp[regselect]); } LOCALPROC DoCodeFPU_GenOpEA(ui4b word2) { myfpr source; switch ((word2 >> 10) & 0x7) { case 0: /* long-word integer */ if (! DecodeModeRegister(4)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln( "DecodeModeRegister fails GetFPSource L"); #endif } else { myfp_FromLong(&source, GetArgValueL()); DoCodeFPU_GenOp(word2, &source); } break; case 1: /* Single-Precision real */ if (! DecodeModeRegister(4)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln( "DecodeModeRegister fails GetFPSource S"); #endif } else { myfp_FromSingleFormat(&source, GetArgValueL()); DoCodeFPU_GenOp(word2, &source); } break; case 2: /* extended precision real */ if (! DecodeAddrModeRegister(12)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln( "DecodeAddrModeRegister fails GetFPSource X"); #endif } else { read_long_double(V_regs.ArgAddr.mem, &source); DoCodeFPU_GenOp(word2, &source); } break; case 3: /* packed-decimal real */ if (! DecodeAddrModeRegister(16)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln( "DecodeAddrModeRegister fails GetFPSource P"); #endif } else { ReportAbnormalID(0x0304, "Packed Decimal in GetFPSource"); /* correct? just set to a constant for now */ /* *r = 9123456789.0; */ DoCodeFPU_GenOp(word2, &source); } break; case 4: /* Word integer */ if (! DecodeModeRegister(2)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln( "DecodeModeRegister fails GetFPSource W"); #endif } else { myfp_FromLong(&source, GetArgValueW()); DoCodeFPU_GenOp(word2, &source); } break; case 5: /* Double-precision real */ if (! DecodeAddrModeRegister(8)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln( "DecodeAddrModeRegister fails GetFPSource D"); #endif } else { read_double(V_regs.ArgAddr.mem, &source); DoCodeFPU_GenOp(word2, &source); } break; case 6: /* Byte Integer */ if (! DecodeModeRegister(1)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln( "DecodeModeRegister fails GetFPSource B"); #endif } else { myfp_FromLong(&source, GetArgValueB()); DoCodeFPU_GenOp(word2, &source); } break; case 7: /* Not a valid source specifier */ DoCodeFPU_MoveCR(word2); break; default: /* should not be able to get here */ break; } } LOCALPROC DoCodeFPU_Move_FP_EA(ui4b word2) { /* FMOVE FP?, */ ui4r SourceReg = (word2 >> 7) & 0x7; myfpr *source = &fpu_dat.fp[SourceReg]; switch ((word2 >> 10) & 0x7) { case 0: /* long-word integer */ if (! DecodeModeRegister(4)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln("DecodeModeRegister fails FMOVE L"); #endif } else { SetArgValueL(myfp_ToLong(source)); } break; case 1: /* Single-Precision real */ if (! DecodeModeRegister(4)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln("DecodeModeRegister fails FMOVE S"); #endif } else { SetArgValueL(myfp_ToSingleFormat(source)); } break; case 2: /* extended precision real */ if (! DecodeAddrModeRegister(12)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln("DecodeAddrModeRegister fails FMOVE X"); #endif } else { write_long_double(V_regs.ArgAddr.mem, source); } break; case 3: /* packed-decimal real */ if (! DecodeAddrModeRegister(16)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln("DecodeAddrModeRegister fails FMOVE P"); #endif } else { ReportAbnormalID(0x0305, "Packed Decimal in FMOVE"); /* ? */ } break; case 4: /* Word integer */ if (! DecodeModeRegister(2)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln("DecodeModeRegister fails FMOVE W"); #endif } else { SetArgValueW(myfp_ToLong(source)); } break; case 5: /* Double-precision real */ if (! DecodeAddrModeRegister(8)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln("DecodeAddrModeRegister fails FMOVE D"); #endif } else { write_double(V_regs.ArgAddr.mem, source); } break; case 6: /* Byte Integer */ if (! DecodeModeRegister(1)) { DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writeln("DecodeModeRegister fails FMOVE B"); #endif } else { SetArgValueB(myfp_ToLong(source)); } break; default: DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writelnNum("Bad Source Specifier in FMOVE", (word2 >> 10) & 0x7); #endif break; } } LOCALIPROC DoCodeFPU_md60(void) { ui4b word2 = (int)nextiword(); switch ((word2 >> 13) & 0x7) { case 0: DoCodeFPU_GenOpReg(word2); break; case 2: DoCodeFPU_GenOpEA(word2); break; case 3: DoCodeFPU_Move_FP_EA(word2); break; case 4: DoCodeFPU_Move_EA_CSIA(word2); break; case 5: DoCodeFPU_MoveM_CSIA_EA(word2); break; case 6: DoCodeFPU_MoveM_EA_list(word2); break; case 7: DoCodeFPU_MoveM_list_EA(word2); break; default: DoCodeF_InvalidPlusWord(); #if dbglog_HAVE dbglog_writelnNum("Invalid DoCodeFPU_md60", (word2 >> 13) & 0x7); #endif break; } } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/FPMATHEM.h b/Mini vMac/mnvm_core/FPMATHEM.h index 3045ca7..8e738f7 100755 --- a/Mini vMac/mnvm_core/FPMATHEM.h +++ b/Mini vMac/mnvm_core/FPMATHEM.h @@ -1,6165 +1 @@ -/* - FPMATHEM.h - - Copyright (C) 2007 John R. Hauser, Stanislav Shwartsman, - Ross Martin, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - Floating Point MATH implemented with software EMulation - - Based on the SoftFloat IEC/IEEE Floating-point Arithmetic - Package, Release 2b, written by John R. Hauser. - - Also uses extensions to SoftFloat, written for - Bochs (x86 achitecture simulator), by Stanislav Shwartsman. -*/ - -/* - original SoftFloat Copyright notice: - - Written by John R. Hauser. This work was made possible in part by the - International Computer Science Institute, located at Suite 600, 1947 Center - Street, Berkeley, California 94704. Funding was partially provided by the - National Science Foundation under grant MIP-9311980. The original version - of this code was written as part of a project to build a fixed-point vector - processor in collaboration with the University of California at Berkeley, - overseen by Profs. Nelson Morgan and John Wawrzynek. More information - is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ - arithmetic/SoftFloat.html'. - - THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has - been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES - RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS - AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, - COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE - EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE - INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR - OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - - Derivative works are acceptable, even for commercial purposes, so long as - (1) the source code for the derivative work includes prominent notice that - the work is derivative, and (2) the source code includes prominent notice with - these four paragraphs for those parts of this code that are retained. -*/ - -/* - original Stanislav Shwartsman Copyright notice: - - This source file is an extension to the SoftFloat IEC/IEEE Floating-point - Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) - floating point emulation. - - THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has - been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES - RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS - AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, - COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE - EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE - INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR - OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - - Derivative works are acceptable, even for commercial purposes, so long as - (1) the source code for the derivative work includes prominent notice that - the work is derivative, and (2) the source code includes prominent notice with - these four paragraphs for those parts of this code that are retained. - - .*============================================================================ - * Written for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*. -*/ - - - -/* soft float stuff */ - -/* - should avoid 64 bit literals. -*/ - -typedef ui3r flag; /* 0/1 */ - -/* - To fix: softfloat representation of - denormalized extended precision numbers - is different than on 68881. -*/ - -#define cIncludeFPUUnused cIncludeUnused - -/* ----- from original file "softfloat.h" ----- */ - -/*====================================================================== - -This C header file is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -["original SoftFloat Copyright notice" went here, included near top of -this file.] - -======================================================================*/ - -/*---------------------------------------------------------------------------- -| The macro `FLOATX80' must be defined to enable the extended double-precision -| floating-point format `floatx80'. If this macro is not defined, the -| `floatx80' type will not be defined, and none of the functions that either -| input or output the `floatx80' type will be defined. The same applies to -| the `FLOAT128' macro and the quadruple-precision format `float128'. -*----------------------------------------------------------------------------*/ -#define FLOATX80 -#define FLOAT128 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point types. -*----------------------------------------------------------------------------*/ - -typedef struct { - ui6b low; - unsigned short high; -} floatx80; - -#ifdef FLOAT128 -typedef struct { - ui6b low, high; -} float128; -#endif - - -/* ----- end from original file "softfloat.h" ----- */ - - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point rounding mode. -*----------------------------------------------------------------------------*/ -enum { - float_round_nearest_even = 0, - float_round_down = 1, - float_round_up = 2, - float_round_to_zero = 3 -}; - -/*---------------------------------------------------------------------------- -| Floating-point rounding mode, extended double-precision rounding precision, -| and exception flags. -*----------------------------------------------------------------------------*/ - -LOCALVAR si3r float_rounding_mode = float_round_nearest_even; - - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point exception flags. -*----------------------------------------------------------------------------*/ - -enum { - float_flag_invalid = 1, - float_flag_divbyzero = 4, - float_flag_overflow = 8, - float_flag_underflow = 16, - float_flag_inexact = 32 -}; -LOCALVAR si3r float_exception_flags = 0; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision rounding precision. Valid -| values are 32, 64, and 80. -*----------------------------------------------------------------------------*/ - -LOCALVAR si3r floatx80_rounding_precision = 80; - -/*---------------------------------------------------------------------------- -| Primitive arithmetic functions, including multi-word arithmetic, and -| division and square root approximations. (Can be specialized to target if -| desired.) -*----------------------------------------------------------------------------*/ - -/* ----- from original file "softfloat-macros" ----- */ - -/*============================================================================ - -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -["original SoftFloat Copyright notice" went here, included near top of this file.] - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 32, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -| The result is stored in the location pointed to by `zPtr'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALPROC shift32RightJamming( ui5b a, si4r count, ui5b *zPtr ) -{ - ui5b z; - - if ( count == 0 ) { - z = a; - } - else if ( count < 32 ) { - z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 ); - } - else { - z = ( a != 0 ); - } - *zPtr = z; - -} - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 64, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -| The result is stored in the location pointed to by `zPtr'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALPROC shift64RightJamming( ui6b a, si4r count, ui6b *zPtr ) -{ - ui6b z; - - if ( count == 0 ) { - z = a; - } - else if ( count < 64 ) { - z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 ); - } - else { - z = ( a != 0 ); - } - *zPtr = z; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64 -| _plus_ the number of bits given in `count'. The shifted result is at most -| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The -| bits shifted off form a second 64-bit result as follows: The _last_ bit -| shifted off is the most-significant bit of the extra result, and the other -| 63 bits of the extra result are all zero if and only if _all_but_the_last_ -| bits shifted off were all zero. This extra result is stored in the location -| pointed to by `z1Ptr'. The value of `count' can be arbitrarily large. -| (This routine makes more sense if `a0' and `a1' are considered to form -| a fixed-point value with binary point between `a0' and `a1'. This fixed- -| point value is shifted right by the number of bits given in `count', and -| the integer part of the result is returned at the location pointed to by -| `z0Ptr'. The fractional part of the result may be slightly corrupted as -| described above, and is returned at the location pointed to by `z1Ptr'.) -*----------------------------------------------------------------------------*/ - -MayInline LOCALPROC shift64ExtraRightJamming( - ui6b a0, ui6b a1, si4r count, ui6b *z0Ptr, ui6b *z1Ptr ) -{ - ui6b z0, z1; - si3r negCount = ( - count ) & 63; - - if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count; - } - else { - if ( count == 64 ) { - z1 = a0 | ( a1 != 0 ); - } - else { - z1 = ( ( a0 | a1 ) != 0 ); - } - z0 = 0; - } - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. Any bits shifted off are lost. The value -| of `count' can be arbitrarily large; in particular, if `count' is greater -| than 128, the result will be 0. The result is broken into two 64-bit pieces -| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALPROC shift128Right( - ui6b a0, ui6b a1, si4r count, ui6b *z0Ptr, ui6b *z1Ptr ) -{ - ui6b z0, z1; - si3r negCount = ( - count ) & 63; - - if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count ); - z0 = a0>>count; - } - else { - z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0; - z0 = 0; - } - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. If any nonzero bits are shifted off, they -| are ``jammed'' into the least significant bit of the result by setting the -| least significant bit to 1. The value of `count' can be arbitrarily large; -| in particular, if `count' is greater than 128, the result will be either -| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or -| nonzero. The result is broken into two 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALPROC shift128RightJamming( - ui6b a0, ui6b a1, si4r count, ui6b *z0Ptr, ui6b *z1Ptr ) -{ - ui6b z0, z1; - si3r negCount = ( - count ) & 63; - - if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count ) | ( ( a1<>count; - } - else { - if ( count == 64 ) { - z1 = a0 | ( a1 != 0 ); - } - else if ( count < 128 ) { - z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<>count ); - z0 = a0>>count; - } - else { - if ( count == 64 ) { - z2 = a1; - z1 = a0; - } - else { - a2 |= a1; - if ( count < 128 ) { - z2 = a0<>( count & 63 ); - } - else { - z2 = ( count == 128 ) ? a0 : ( a0 != 0 ); - z1 = 0; - } - } - z0 = 0; - } - z2 |= ( a2 != 0 ); - } - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the -| number of bits given in `count'. Any bits shifted off are lost. The value -| of `count' must be less than 64. The result is broken into two 64-bit -| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALPROC shortShift128Left( - ui6b a0, ui6b a1, si4r count, ui6b *z0Ptr, ui6b *z1Ptr ) -{ - - *z1Ptr = a1<>( ( - count ) & 63 ) ); - -} - -/*---------------------------------------------------------------------------- -| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit -| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so -| any carry out is lost. The result is broken into two 64-bit pieces which -| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALPROC add128( - ui6b a0, ui6b a1, ui6b b0, ui6b b1, ui6b *z0Ptr, ui6b *z1Ptr ) -{ - ui6b z1; - - z1 = a1 + b1; - *z1Ptr = z1; - *z0Ptr = a0 + b0 + ( z1 < a1 ); -} - -/*---------------------------------------------------------------------------- -| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the -| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is -| modulo 2^192, so any carry out is lost. The result is broken into three -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', -| `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALPROC add192( - ui6b a0, - ui6b a1, - ui6b a2, - ui6b b0, - ui6b b1, - ui6b b2, - ui6b *z0Ptr, - ui6b *z1Ptr, - ui6b *z2Ptr) -{ - ui6b z0, z1, z2; - si3r carry0, carry1; - - z2 = a2 + b2; - carry1 = ( z2 < a2 ); - z1 = a1 + b1; - carry0 = ( z1 < a1 ); - z0 = a0 + b0; - z1 += carry1; - z0 += ( z1 < carry1 ); - z0 += carry0; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the -| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo -| 2^128, so any borrow out (carry out) is lost. The result is broken into two -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and -| `z1Ptr'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALPROC - sub128( - ui6b a0, ui6b a1, ui6b b0, ui6b b1, ui6b *z0Ptr, ui6b *z1Ptr ) -{ - - *z1Ptr = a1 - b1; - *z0Ptr = a0 - b0 - ( a1 < b1 ); - -} - -/*---------------------------------------------------------------------------- -| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2' -| from the 192-bit value formed by concatenating `a0', `a1', and `a2'. -| Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The -| result is broken into three 64-bit pieces which are stored at the locations -| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALPROC - sub192( - ui6b a0, - ui6b a1, - ui6b a2, - ui6b b0, - ui6b b1, - ui6b b2, - ui6b *z0Ptr, - ui6b *z1Ptr, - ui6b *z2Ptr - ) -{ - ui6b z0, z1, z2; - si3r borrow0, borrow1; - - z2 = a2 - b2; - borrow1 = ( a2 < b2 ); - z1 = a1 - b1; - borrow0 = ( a1 < b1 ); - z0 = a0 - b0; - z0 -= ( z1 < borrow1 ); - z1 -= borrow1; - z0 -= borrow0; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken -| into two 64-bit pieces which are stored at the locations pointed to by -| `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALPROC mul64To128( ui6b a, ui6b b, ui6b *z0Ptr, ui6b *z1Ptr ) -{ - ui5b aHigh, aLow, bHigh, bLow; - ui6b z0, zMiddleA, zMiddleB, z1; - - aLow = a; - aHigh = a>>32; - bLow = b; - bHigh = b>>32; - z1 = ( (ui6b) aLow ) * bLow; - zMiddleA = ( (ui6b) aLow ) * bHigh; - zMiddleB = ( (ui6b) aHigh ) * bLow; - z0 = ( (ui6b) aHigh ) * bHigh; - zMiddleA += zMiddleB; - z0 += ( ( (ui6b) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 ); - zMiddleA <<= 32; - z1 += zMiddleA; - z0 += ( z1 < zMiddleA ); - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by -| `b' to obtain a 192-bit product. The product is broken into three 64-bit -| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and -| `z2Ptr'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALPROC - mul128By64To192( - ui6b a0, - ui6b a1, - ui6b b, - ui6b *z0Ptr, - ui6b *z1Ptr, - ui6b *z2Ptr - ) -{ - ui6b z0, z1, z2, more1; - - mul64To128( a1, b, &z1, &z2 ); - mul64To128( a0, b, &z0, &more1 ); - add128( z0, more1, 0, z1, &z0, &z1 ); - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the -| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit -| product. The product is broken into four 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALPROC - mul128To256( - ui6b a0, - ui6b a1, - ui6b b0, - ui6b b1, - ui6b *z0Ptr, - ui6b *z1Ptr, - ui6b *z2Ptr, - ui6b *z3Ptr - ) -{ - ui6b z0, z1, z2, z3; - ui6b more1, more2; - - mul64To128( a1, b1, &z2, &z3 ); - mul64To128( a1, b0, &z1, &more2 ); - add128( z1, more2, 0, z2, &z1, &z2 ); - mul64To128( a0, b0, &z0, &more1 ); - add128( z0, more1, 0, z1, &z0, &z1 ); - mul64To128( a0, b1, &more1, &more2 ); - add128( more1, more2, 0, z2, &more1, &z2 ); - add128( z0, z1, 0, more1, &z0, &z1 ); - *z3Ptr = z3; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Returns an approximation to the 64-bit integer quotient obtained by dividing -| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The -| divisor `b' must be at least 2^63. If q is the exact quotient truncated -| toward zero, the approximation returned lies between q and q + 2 inclusive. -| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit -| unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -LOCALFUNC ui6b estimateDiv128To64( ui6b a0, ui6b a1, ui6b b ) -{ - ui6b b0, b1; - ui6b rem0, rem1, term0, term1; - ui6b z; - - if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF ); - b0 = b>>32; - z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32; - mul64To128( b, z, &term0, &term1 ); - sub128( a0, a1, term0, term1, &rem0, &rem1 ); - while ( ( (si6b) rem0 ) < 0 ) { - z -= LIT64( 0x100000000 ); - b1 = b<<32; - add128( rem0, rem1, b0, b1, &rem0, &rem1 ); - } - rem0 = ( rem0<<32 ) | ( rem1>>32 ); - z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : rem0 / b0; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns an approximation to the square root of the 32-bit significand given -| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of -| `aExp' (the least significant bit) is 1, the integer returned approximates -| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp' -| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either -| case, the approximation returned lies strictly within +/-2 of the exact -| value. -*----------------------------------------------------------------------------*/ - -LOCALFUNC ui5b estimateSqrt32( si4r aExp, ui5b a ) -{ - static const ui4b sqrtOddAdjustments[] = { - 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0, - 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67 - }; - static const ui4b sqrtEvenAdjustments[] = { - 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E, - 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002 - }; - si3r index; - ui5b z; - - index = ( a>>27 ) & 15; - if ( aExp & 1 ) { - z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ]; - z = ( ( a / z )<<14 ) + ( z<<15 ); - a >>= 1; - } - else { - z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ]; - z = a / z + z; - z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 ); - if ( z <= a ) return (ui5b) ( ( (si5b) a )>>1 ); - } - return ( (ui5b) ( ( ( (ui6b) a )<<31 ) / z ) ) + ( z>>1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 32 is returned. -*----------------------------------------------------------------------------*/ - -LOCALFUNC si3r countLeadingZeros32( ui5b a ) -{ - static const si3r countLeadingZerosHigh[] = { - 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - si3r shiftCount; - - shiftCount = 0; - if ( a < 0x10000 ) { - shiftCount += 16; - a <<= 16; - } - if ( a < 0x1000000 ) { - shiftCount += 8; - a <<= 8; - } - shiftCount += countLeadingZerosHigh[ a>>24 ]; - return shiftCount; - -} - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 64 is returned. -*----------------------------------------------------------------------------*/ - -LOCALFUNC si3r countLeadingZeros64( ui6b a ) -{ - si3r shiftCount; - - shiftCount = 0; - if ( a < ( (ui6b) 1 )<<32 ) { - shiftCount += 32; - } - else { - a >>= 32; - } - shiftCount += countLeadingZeros32( a ); - return shiftCount; - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' -| is equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -MayInline LOCALFUNC flag eq128( ui6b a0, ui6b a1, ui6b b0, ui6b b1 ) -{ - - return ( a0 == b0 ) && ( a1 == b1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than or equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -MayInline LOCALFUNC flag le128( ui6b a0, ui6b a1, ui6b b0, ui6b b1 ) -{ - - return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise, -| returns 0. -*----------------------------------------------------------------------------*/ - -MayInline LOCALFUNC flag lt128( ui6b a0, ui6b a1, ui6b b0, ui6b b1 ) -{ - - return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is -| not equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -#if cIncludeFPUUnused -MayInline LOCALFUNC flag ne128( ui6b a0, ui6b a1, ui6b b0, ui6b b1 ) -{ - - return ( a0 != b0 ) || ( a1 != b1 ); - -} -#endif - -/* ----- end from original file "softfloat-macros" ----- */ - -/*---------------------------------------------------------------------------- -| Functions and definitions to determine: (1) whether tininess for underflow -| is detected before or after rounding by default, (2) what (if anything) -| happens when exceptions are raised, (3) how signaling NaNs are distinguished -| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs -| are propagated from function inputs to output. These details are target- -| specific. -*----------------------------------------------------------------------------*/ - -/* ----- from original file "softfloat-specialize" ----- */ - -/*============================================================================ - -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -["original SoftFloat Copyright notice" went here, included near top of this file.] - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point underflow tininess-detection mode. -*----------------------------------------------------------------------------*/ -enum { - float_tininess_after_rounding = 0, - float_tininess_before_rounding = 1 -}; - -/*---------------------------------------------------------------------------- -| Underflow tininess-detection mode, statically initialized to default value. -| (The declaration in `softfloat.h' must match the `si3r' type here.) -*----------------------------------------------------------------------------*/ -LOCALVAR si3r float_detect_tininess = float_tininess_after_rounding; - -/*---------------------------------------------------------------------------- -| Routine to raise any or all of the software IEC/IEEE floating-point -| exception flags. -*----------------------------------------------------------------------------*/ -/*---------------------------------------------------------------------------- -| Raises the exceptions specified by `flags'. Floating-point traps can be -| defined here if desired. It is currently not possible for such a trap -| to substitute a result value. If traps are not implemented, this routine -| should be simply `float_exception_flags |= flags;'. -*----------------------------------------------------------------------------*/ - -LOCALFUNC void float_raise( si3r flags ) -{ - - float_exception_flags |= flags; - -} - -/*---------------------------------------------------------------------------- -| Internal canonical NaN format. -*----------------------------------------------------------------------------*/ -typedef struct { - flag sign; - ui6b high, low; -} commonNaNT; - -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. The -| `high' and `low' values hold the most- and least-significant bits, -| respectively. -*----------------------------------------------------------------------------*/ -#define floatx80_default_nan_high 0xFFFF -#define floatx80_default_nan_low LIT64( 0xC000000000000000 ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -LOCALFUNC flag floatx80_is_nan( floatx80 a ) -{ - - return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (ui6b) ( a.low<<1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -LOCALFUNC flag floatx80_is_signaling_nan( floatx80 a ) -{ - ui6b aLow; - - aLow = a.low & ~ LIT64( 0x4000000000000000 ); - return - ( ( a.high & 0x7FFF ) == 0x7FFF ) - && (ui6b) ( aLow<<1 ) - && ( a.low == aLow ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the -| invalid exception is raised. -*----------------------------------------------------------------------------*/ - -LOCALFUNC commonNaNT floatx80ToCommonNaN( floatx80 a ) -{ - commonNaNT z; - - if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a.high>>15; - z.low = 0; - z.high = a.low<<1; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the extended -| double-precision floating-point format. -*----------------------------------------------------------------------------*/ - -LOCALFUNC floatx80 commonNaNToFloatx80( commonNaNT a ) -{ - floatx80 z; - - z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); - z.high = ( ( (ui4b) a.sign )<<15 ) | 0x7FFF; - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes two extended double-precision floating-point values `a' and `b', one -| of which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -LOCALFUNC floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = floatx80_is_nan( a ); - aIsSignalingNaN = floatx80_is_signaling_nan( a ); - bIsNaN = floatx80_is_nan( b ); - bIsSignalingNaN = floatx80_is_signaling_nan( b ); - a.low |= LIT64( 0xC000000000000000 ); - b.low |= LIT64( 0xC000000000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsSignalingNaN ) { - if ( bIsSignalingNaN ) goto returnLargerSignificand; - return bIsNaN ? b : a; - } - else if ( aIsNaN ) { - if ( bIsSignalingNaN | ! bIsNaN ) return a; - returnLargerSignificand: - if ( a.low < b.low ) return b; - if ( b.low < a.low ) return a; - return ( a.high < b.high ) ? a : b; - } - else { - return b; - } - -} - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| The pattern for a default generated quadruple-precision NaN. The `high' and -| `low' values hold the most- and least-significant bits, respectively. -*----------------------------------------------------------------------------*/ -#define float128_default_nan_high LIT64( 0xFFFF800000000000 ) -#define float128_default_nan_low LIT64( 0x0000000000000000 ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -LOCALFUNC flag float128_is_nan( float128 a ) -{ - - return - ( LIT64( 0xFFFE000000000000 ) <= (ui6b) ( a.high<<1 ) ) - && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -LOCALFUNC flag float128_is_signaling_nan( float128 a ) -{ - - return - ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) - && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -LOCALFUNC commonNaNT float128ToCommonNaN( float128 a ) -{ - commonNaNT z; - - if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a.high>>63; - shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the quadruple- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -LOCALFUNC float128 commonNaNToFloat128( commonNaNT a ) -{ - float128 z; - - shift128Right( a.high, a.low, 16, &z.high, &z.low ); - z.high |= ( ( (ui6b) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes two quadruple-precision floating-point values `a' and `b', one of -| which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -LOCALFUNC float128 propagateFloat128NaN( float128 a, float128 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float128_is_nan( a ); - aIsSignalingNaN = float128_is_signaling_nan( a ); - bIsNaN = float128_is_nan( b ); - bIsSignalingNaN = float128_is_signaling_nan( b ); - a.high |= LIT64( 0x0000800000000000 ); - b.high |= LIT64( 0x0000800000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsSignalingNaN ) { - if ( bIsSignalingNaN ) goto returnLargerSignificand; - return bIsNaN ? b : a; - } - else if ( aIsNaN ) { - if ( bIsSignalingNaN | ! bIsNaN ) return a; - returnLargerSignificand: - if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b; - if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a; - return ( a.high < b.high ) ? a : b; - } - else { - return b; - } - -} - -#endif - -/* ----- end from original file "softfloat-specialize" ----- */ - -/* ----- from original file "softfloat.c" ----- */ - - -/*============================================================================ - -This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -["original SoftFloat Copyright notice" went here, included near top of this file.] - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 -| and 7, and returns the properly rounded 32-bit integer corresponding to the -| input. If `zSign' is 1, the input is negated before being converted to an -| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input -| is simply rounded to an integer, with the inexact exception raised if the -| input cannot be represented exactly as an integer. However, if the fixed- -| point input is too large, the invalid exception is raised and the largest -| positive or negative integer is returned. -*----------------------------------------------------------------------------*/ - -LOCALFUNC si5r roundAndPackInt32( flag zSign, ui6b absZ ) -{ - si3r roundingMode; - flag roundNearestEven; - si3r roundIncrement, roundBits; - si5r z; - - roundingMode = float_rounding_mode; - roundNearestEven = ( roundingMode == float_round_nearest_even ); - roundIncrement = 0x40; - if ( ! roundNearestEven ) { - if ( roundingMode == float_round_to_zero ) { - roundIncrement = 0; - } - else { - roundIncrement = 0x7F; - if ( zSign ) { - if ( roundingMode == float_round_up ) roundIncrement = 0; - } - else { - if ( roundingMode == float_round_down ) roundIncrement = 0; - } - } - } - roundBits = absZ & 0x7F; - absZ = ( absZ + roundIncrement )>>7; - absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); - z = absZ; - if ( zSign ) z = - z; - if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { - float_raise( float_flag_invalid ); - return zSign ? (si5b) 0x80000000 : 0x7FFFFFFF; - } - if ( roundBits ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALFUNC ui6b extractFloatx80Frac( floatx80 a ) -{ - - return a.low; - -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALFUNC si5r extractFloatx80Exp( floatx80 a ) -{ - - return a.high & 0x7FFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the extended double-precision floating-point value -| `a'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALFUNC flag extractFloatx80Sign( floatx80 a ) -{ - - return a.high>>15; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal extended double-precision floating-point value -| represented by the denormalized significand `aSig'. The normalized exponent -| and significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -LOCALPROC - normalizeFloatx80Subnormal( ui6b aSig, si5r *zExpPtr, ui6b *zSigPtr ) -{ - si3r shiftCount; - - shiftCount = countLeadingZeros64( aSig ); - *zSigPtr = aSig<>48 ) & 0x7FFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the quadruple-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALFUNC flag extractFloat128Sign( float128 a ) -{ - - return a.high>>63; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal quadruple-precision floating-point value -| represented by the denormalized significand formed by the concatenation of -| `aSig0' and `aSig1'. The normalized exponent is stored at the location -| pointed to by `zExpPtr'. The most significant 49 bits of the normalized -| significand are stored at the location pointed to by `zSig0Ptr', and the -| least significant 64 bits of the normalized significand are stored at the -| location pointed to by `zSig1Ptr'. -*----------------------------------------------------------------------------*/ - -LOCALPROC - normalizeFloat128Subnormal( - ui6b aSig0, - ui6b aSig1, - si5r *zExpPtr, - ui6b *zSig0Ptr, - ui6b *zSig1Ptr - ) -{ - si3r shiftCount; - - if ( aSig0 == 0 ) { - shiftCount = countLeadingZeros64( aSig1 ) - 15; - if ( shiftCount < 0 ) { - *zSig0Ptr = aSig1>>( - shiftCount ); - *zSig1Ptr = aSig1<<( shiftCount & 63 ); - } - else { - *zSig0Ptr = aSig1<>= shiftCount; - z = aSig; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (si5b) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig<>1; - if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z.low += roundBitsMask; - } - } - z.low &= ~ roundBitsMask; - if ( z.low == 0 ) { - ++z.high; - z.low = LIT64( 0x8000000000000000 ); - } - if ( z.low != a.low ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the extended double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the sum is -| negated before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) -{ - si5r aExp, bExp, zExp; - ui6b aSig, bSig, zSig0, zSig1; - si5r expDiff; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) { - if ( aExp == 0x7FFF ) { - if ( (ui6b) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) --expDiff; - shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FFF ) { - if ( (ui6b) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) ++expDiff; - shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); - zExp = bExp; - } - else { - if ( aExp == 0x7FFF ) { - if ( (ui6b) ( ( aSig | bSig )<<1 ) ) { - return propagateFloatx80NaN( a, b ); - } - return a; - } - zSig1 = 0; - zSig0 = aSig + bSig; - if ( aExp == 0 ) { - normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 ); - goto roundAndPack; - } - zExp = aExp; - goto shiftRight1; - } - zSig0 = aSig + bSig; - if ( (si6b) zSig0 < 0 ) goto roundAndPack; - shiftRight1: - shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 ); - zSig0 |= LIT64( 0x8000000000000000 ); - ++zExp; - roundAndPack: - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the extended -| double-precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) -{ - si5r aExp, bExp, zExp; - ui6b aSig, bSig, zSig0, zSig1; - si5r expDiff; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FFF ) { - if ( (ui6b) ( ( aSig | bSig )<<1 ) ) { - return propagateFloatx80NaN( a, b ); - } - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - zSig1 = 0; - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloatx80( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FFF ) { - if ( (ui6b) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) ++expDiff; - shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); - bBigger: - sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 ); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FFF ) { - if ( (ui6b) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) --expDiff; - shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); - aBigger: - sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 ); - zExp = aExp; - normalizeRoundAndPack: - return - normalizeRoundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the extended double-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC floatx80 floatx80_add( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign == bSign ) { - return addFloatx80Sigs( a, b, aSign ); - } - else { - return subFloatx80Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC floatx80 floatx80_sub( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign == bSign ) { - return subFloatx80Sigs( a, b, aSign ); - } - else { - return addFloatx80Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC floatx80 floatx80_mul( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - si5r aExp, bExp, zExp; - ui6b aSig, bSig, zSig0, zSig1; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( (ui6b) ( aSig<<1 ) - || ( ( bExp == 0x7FFF ) && (ui6b) ( bSig<<1 ) ) ) { - return propagateFloatx80NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) goto invalid; - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( bExp == 0x7FFF ) { - if ( (ui6b) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x3FFE; - mul64To128( aSig, bSig, &zSig0, &zSig1 ); - if ( 0 < (si6b) zSig0 ) { - shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 ); - --zExp; - } - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the extended double-precision floating-point -| value `a' by the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC floatx80 floatx80_div( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - si5r aExp, bExp, zExp; - ui6b aSig, bSig, zSig0, zSig1; - ui6b rem0, rem1, rem2, term0, term1, term2; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( (ui6b) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - if ( bExp == 0x7FFF ) { - if ( (ui6b) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - goto invalid; - } - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( bExp == 0x7FFF ) { - if ( (ui6b) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - float_raise( float_flag_divbyzero ); - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); - } - if ( aSig == 0 ) { - /* - added by pcp. this invalid input seems to - cause hang in estimateDiv128To64. should - validate inputs generally. - */ - return packFloatx80( zSign, 0, 0 ); - } - zExp = aExp - bExp + 0x3FFE; - rem1 = 0; - if ( bSig <= aSig ) { - shift128Right( aSig, 0, 1, &aSig, &rem1 ); - ++zExp; - } - zSig0 = estimateDiv128To64( aSig, rem1, bSig ); - mul64To128( bSig, zSig0, &term0, &term1 ); - sub128( aSig, rem1, term0, term1, &rem0, &rem1 ); - while ( (si6b) rem0 < 0 ) { - --zSig0; - add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, bSig ); - if ( (ui6b) ( zSig1<<1 ) <= 8 ) { - mul64To128( bSig, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - while ( (si6b) rem1 < 0 ) { - --zSig1; - add128( rem1, rem2, 0, bSig, &rem1, &rem2 ); - } - zSig1 |= ( ( rem1 | rem2 ) != 0 ); - } - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the extended double-precision floating-point value -| `a' with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC floatx80 floatx80_rem( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - si5r aExp, bExp, expDiff; - ui6b aSig0, aSig1, bSig; - ui6b q, term0, term1, alternateASig0, alternateASig1; - floatx80 z; - - aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - if ( aExp == 0x7FFF ) { - if ( (ui6b) ( aSig0<<1 ) - || ( ( bExp == 0x7FFF ) && (ui6b) ( bSig<<1 ) ) ) { - return propagateFloatx80NaN( a, b ); - } - goto invalid; - } - if ( bExp == 0x7FFF ) { - if ( (ui6b) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( (ui6b) ( aSig0<<1 ) == 0 ) return a; - normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); - } - bSig |= LIT64( 0x8000000000000000 ); - zSign = aSign; - expDiff = aExp - bExp; - aSig1 = 0; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - shift128Right( aSig0, 0, 1, &aSig0, &aSig1 ); - expDiff = 0; - } - q = ( bSig <= aSig0 ); - if ( q ) aSig0 -= bSig; - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - mul64To128( bSig, q, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 ); - expDiff -= 62; - } - expDiff += 64; - if ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - q >>= 64 - expDiff; - mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 ); - while ( le128( term0, term1, aSig0, aSig1 ) ) { - ++q; - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - } - } - else { - term1 = 0; - term0 = bSig; - } - sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 ); - if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) - || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) - && ( q & 1 ) ) - ) { - aSig0 = alternateASig0; - aSig1 = alternateASig1; - zSign = ! zSign; - } - return - normalizeRoundAndPackFloatx80( - 80, zSign, bExp + expDiff, aSig0, aSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the extended double-precision floating-point -| value `a'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC floatx80 floatx80_sqrt( floatx80 a ) -{ - flag aSign; - si5r aExp, zExp; - ui6b aSig0, aSig1, zSig0, zSig1, doubleZSig0; - ui6b rem0, rem1, rem2, rem3, term0, term1, term2, term3; - floatx80 z; - - aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (ui6b) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a ); - if ( ! aSign ) return a; - goto invalid; - } - if ( aSign ) { - if ( ( aExp | aSig0 ) == 0 ) return a; - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - if ( aExp == 0 ) { - if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 ); - normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); - } - zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF; - zSig0 = estimateSqrt32( aExp, aSig0>>32 ); - shift128Right( aSig0, 0, 2 + ( aExp & 1 ), &aSig0, &aSig1 ); - zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); - doubleZSig0 = zSig0<<1; - mul64To128( zSig0, zSig0, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); - while ( (si6b) rem0 < 0 ) { - --zSig0; - doubleZSig0 -= 2; - add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); - if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) { - if ( zSig1 == 0 ) zSig1 = 1; - mul64To128( doubleZSig0, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - mul64To128( zSig1, zSig1, &term2, &term3 ); - sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); - while ( (si6b) rem1 < 0 ) { - --zSig1; - shortShift128Left( 0, zSig1, 1, &term2, &term3 ); - term3 |= 1; - term2 |= doubleZSig0; - add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 ); - zSig0 |= doubleZSig0; - return - roundAndPackFloatx80( - floatx80_rounding_precision, 0, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| equal to the corresponding value `b', and 0 otherwise. The comparison is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -#if cIncludeFPUUnused -LOCALFUNC flag floatx80_eq( floatx80 a, floatx80 b ) -{ - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (ui6b) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (ui6b) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (ui4b) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} -#endif - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| less than or equal to the corresponding value `b', and 0 otherwise. The -| comparison is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -#if cIncludeFPUUnused -LOCALFUNC flag floatx80_le( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (ui6b) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (ui6b) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (ui4b) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} -#endif - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| less than the corresponding value `b', and 0 otherwise. The comparison -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -#if cIncludeFPUUnused -LOCALFUNC flag floatx80_lt( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (ui6b) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (ui6b) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (ui4b) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} -#endif - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is equal -| to the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -#if cIncludeFPUUnused -LOCALFUNC flag floatx80_eq_signaling( floatx80 a, floatx80 b ) -{ - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (ui6b) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (ui6b) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (ui4b) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} -#endif - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is less -| than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs -| do not cause an exception. Otherwise, the comparison is performed according -| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -#if cIncludeFPUUnused -LOCALFUNC flag floatx80_le_quiet( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (ui6b) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (ui6b) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (ui4b) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} -#endif - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is less -| than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause -| an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -#if cIncludeFPUUnused -LOCALFUNC flag floatx80_lt_quiet( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (ui6b) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (ui6b) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (ui4b) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the extended double-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC floatx80 float128_to_floatx80( float128 a ) -{ - flag aSign; - si5r aExp; - ui6b aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloatx80( float128ToCommonNaN( a ) ); - } - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - else { - aSig0 |= LIT64( 0x0001000000000000 ); - } - shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 ); - return roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the quadruple-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC float128 addFloat128Sigs( float128 a, float128 b, flag zSign ) -{ - si5r aExp, bExp, zExp; - ui6b aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - si5r expDiff; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) { - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig0 |= LIT64( 0x0001000000000000 ); - } - shift128ExtraRightJamming( - bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig0 |= LIT64( 0x0001000000000000 ); - } - shift128ExtraRightJamming( - aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 ); - zExp = bExp; - } - else { - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 | bSig0 | bSig1 ) { - return propagateFloat128NaN( a, b ); - } - return a; - } - add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 ); - zSig2 = 0; - zSig0 |= LIT64( 0x0002000000000000 ); - zExp = aExp; - goto shiftRight1; - } - aSig0 |= LIT64( 0x0001000000000000 ); - add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - --zExp; - if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack; - ++zExp; - shiftRight1: - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); - roundAndPack: - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the quadruple- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC float128 subFloat128Sigs( float128 a, float128 b, flag zSign ) -{ - si5r aExp, bExp, zExp; - ui6b aSig0, aSig1, bSig0, bSig1, zSig0, zSig1; - si5r expDiff; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - expDiff = aExp - bExp; - shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); - shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 ); - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 | bSig0 | bSig1 ) { - return propagateFloat128NaN( a, b ); - } - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig0 < aSig0 ) goto aBigger; - if ( aSig0 < bSig0 ) goto bBigger; - if ( bSig1 < aSig1 ) goto aBigger; - if ( aSig1 < bSig1 ) goto bBigger; - return packFloat128( float_rounding_mode == float_round_down, 0, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig0 |= LIT64( 0x4000000000000000 ); - } - shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); - bSig0 |= LIT64( 0x4000000000000000 ); - bBigger: - sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 ); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig0 |= LIT64( 0x4000000000000000 ); - } - shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 ); - aSig0 |= LIT64( 0x4000000000000000 ); - aBigger: - sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the quadruple-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC float128 float128_add( float128 a, float128 b ) -{ - flag aSign, bSign; - - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign == bSign ) { - return addFloat128Sigs( a, b, aSign ); - } - else { - return subFloat128Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC float128 float128_sub( float128 a, float128 b ) -{ - flag aSign, bSign; - - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign == bSign ) { - return subFloat128Sigs( a, b, aSign ); - } - else { - return addFloat128Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC float128 float128_mul( float128 a, float128 b ) -{ - flag aSign, bSign, zSign; - si5r aExp, bExp, zExp; - ui6b aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( ( aSig0 | aSig1 ) - || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { - return propagateFloat128NaN( a, b ); - } - if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid; - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - if ( ( aExp | aSig0 | aSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - zExp = aExp + bExp - 0x4000; - aSig0 |= LIT64( 0x0001000000000000 ); - shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 ); - mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 ); - add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 ); - zSig2 |= ( zSig3 != 0 ); - if ( LIT64( 0x0002000000000000 ) <= zSig0 ) { - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); - ++zExp; - } - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the quadruple-precision floating-point value -| `a' by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC float128 float128_div( float128 a, float128 b ) -{ - flag aSign, bSign, zSign; - si5r aExp, bExp, zExp; - ui6b aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - ui6b rem0, rem1, rem2, rem3, term0, term1, term2, term3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - goto invalid; - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign, 0, 0, 0 ); - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) { - if ( ( aExp | aSig0 | aSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - float_raise( float_flag_divbyzero ); - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - zExp = aExp - bExp + 0x3FFD; - shortShift128Left( - aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 ); - shortShift128Left( - bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); - if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) { - shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 ); - ++zExp; - } - zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 ); - mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 ); - sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 ); - while ( (si6b) rem0 < 0 ) { - --zSig0; - add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 ); - } - zSig1 = estimateDiv128To64( rem1, rem2, bSig0 ); - if ( ( zSig1 & 0x3FFF ) <= 4 ) { - mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 ); - sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 ); - while ( (si6b) rem1 < 0 ) { - --zSig1; - add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 ); - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -#endif - -typedef unsigned int float32; - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal single-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -LOCALPROC - normalizeFloat32Subnormal( ui5b aSig, si4r *zExpPtr, ui5b *zSigPtr ) -{ - si3r shiftCount; - - shiftCount = countLeadingZeros32( aSig ) - 8; - *zSigPtr = aSig<>23 ) & 0xFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALFUNC flag extractFloat32Sign( float32 a ) -{ - - return a>>31; - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -LOCALFUNC flag float32_is_signaling_nan( float32 a ) -{ - - return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -LOCALFUNC commonNaNT float32ToCommonNaN( float32 a ) -{ - commonNaNT z; - - if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a>>31; - z.low = 0; - z.high = ( (ui6b) a )<<41; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the extended double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC floatx80 float32_to_floatx80( float32 a ) -{ - flag aSign; - si4r aExp; - ui5b aSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a ) ); - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - aSig |= 0x00800000; - return packFloatx80( aSign, aExp + 0x3F80, ( (ui6b) aSig )<<40 ); - -} - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a -| single-precision floating-point value, returning the result. After being -| shifted into the proper positions, the three fields are simply added -| together to form the result. This means that any integer portion of `zSig' -| will be added into the exponent. Since a properly normalized significand -| will have an integer portion equal to 1, the `zExp' input should be 1 less -| than the desired result exponent whenever `zSig' is a complete, normalized -| significand. -*----------------------------------------------------------------------------*/ - -MayInline LOCALFUNC float32 packFloat32( flag zSign, si4r zExp, ui5b zSig ) -{ - - return ( ( (ui5b) zSign )<<31 ) + ( ( (ui5b) zExp )<<23 ) + zSig; - -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper single-precision floating- -| point value corresponding to the abstract input. Ordinarily, the abstract -| value is simply rounded and packed into the single-precision format, with -| the inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded to -| a subnormal number, and the underflow and inexact exceptions are raised if -| the abstract input cannot be represented exactly as a subnormal single- -| precision floating-point number. -| The input significand `zSig' has its binary point between bits 30 -| and 29, which is 7 bits to the left of the usual location. This shifted -| significand must be normalized or smaller. If `zSig' is not normalized, -| `zExp' must be 0; in that case, the result returned is a subnormal number, -| and it must not require rounding. In the usual case that `zSig' is -| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent. -| The handling of underflow and overflow follows the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC float32 roundAndPackFloat32( flag zSign, si4r zExp, ui5b zSig ) -{ - si3r roundingMode; - flag roundNearestEven; - si3r roundIncrement, roundBits; - flag isTiny; - - roundingMode = float_rounding_mode; - roundNearestEven = ( roundingMode == float_round_nearest_even ); - roundIncrement = 0x40; - if ( ! roundNearestEven ) { - if ( roundingMode == float_round_to_zero ) { - roundIncrement = 0; - } - else { - roundIncrement = 0x7F; - if ( zSign ) { - if ( roundingMode == float_round_up ) roundIncrement = 0; - } - else { - if ( roundingMode == float_round_down ) roundIncrement = 0; - } - } - } - roundBits = zSig & 0x7F; - if ( 0xFD <= (ui4b) zExp ) { - if ( ( 0xFD < zExp ) - || ( ( zExp == 0xFD ) - && ( (si5b) ( zSig + roundIncrement ) < 0 ) ) - ) { - float_raise( float_flag_overflow | float_flag_inexact ); - return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 ); - } - if ( zExp < 0 ) { - isTiny = - ( float_detect_tininess == float_tininess_before_rounding ) - || ( zExp < -1 ) - || ( zSig + roundIncrement < 0x80000000 ); - shift32RightJamming( zSig, - zExp, &zSig ); - zExp = 0; - roundBits = zSig & 0x7F; - if ( isTiny && roundBits ) float_raise( float_flag_underflow ); - } - } - if ( roundBits ) float_exception_flags |= float_flag_inexact; - zSig = ( zSig + roundIncrement )>>7; - zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); - if ( zSig == 0 ) zExp = 0; - return packFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the single- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -LOCALFUNC float32 commonNaNToFloat32( commonNaNT a ) -{ - - return ( ( (ui5b) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the single-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC float32 floatx80_to_float32( floatx80 a ) -{ - flag aSign; - si5r aExp; - ui6b aSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (ui6b) ( aSig<<1 ) ) { - return commonNaNToFloat32( floatx80ToCommonNaN( a ) ); - } - return packFloat32( aSign, 0xFF, 0 ); - } - shift64RightJamming( aSig, 33, &aSig ); - if ( aExp || aSig ) aExp -= 0x3F81; - return roundAndPackFloat32( aSign, aExp, aSig ); - -} - - -typedef ui6b float64; - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALFUNC ui6b extractFloat64Frac( float64 a ) -{ - - return a & LIT64( 0x000FFFFFFFFFFFFF ); - -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALFUNC si4r extractFloat64Exp( float64 a ) -{ - - return ( a>>52 ) & 0x7FF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -MayInline LOCALFUNC flag extractFloat64Sign( float64 a ) -{ - - return a>>63; - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -LOCALFUNC flag float64_is_signaling_nan( float64 a ) -{ - - return - ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) - && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -LOCALFUNC commonNaNT float64ToCommonNaN( float64 a ) -{ - commonNaNT z; - - if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a>>63; - z.low = 0; - z.high = a<<12; - return z; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal double-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -LOCALPROC - normalizeFloat64Subnormal( ui6b aSig, si4r *zExpPtr, ui6b *zSigPtr ) -{ - si3r shiftCount; - - shiftCount = countLeadingZeros64( aSig ) - 11; - *zSigPtr = aSig<>10; - zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven ); - if ( zSig == 0 ) zExp = 0; - return packFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the double- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -LOCALFUNC float64 commonNaNToFloat64( commonNaNT a ) -{ - - return - ( ( (ui6b) a.sign )<<63 ) - | LIT64( 0x7FF8000000000000 ) - | ( a.high>>12 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the double-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC float64 floatx80_to_float64( floatx80 a ) -{ - flag aSign; - si5r aExp; - ui6b aSig, zSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (ui6b) ( aSig<<1 ) ) { - return commonNaNToFloat64( floatx80ToCommonNaN( a ) ); - } - return packFloat64( aSign, 0x7FF, 0 ); - } - shift64RightJamming( aSig, 1, &zSig ); - if ( aExp || aSig ) aExp -= 0x3C01; - return roundAndPackFloat64( aSign, aExp, zSig ); - -} - -/* ----- end from original file "softfloat.c" ----- */ - -typedef si4r Bit16s; -typedef si5r Bit32s; -typedef si6r Bit64s; - -typedef ui5r Bit32u; -typedef ui6r Bit64u; - -#define int16_indefinite 0x8000 - -/*---------------------------------------------------------------------------- -| Takes extended double-precision floating-point NaN `a' and returns the -| appropriate NaN result. If `a' is a signaling NaN, the invalid exception -| is raised. -*----------------------------------------------------------------------------*/ - -LOCALFUNC floatx80 propagateOneFloatx80NaN(floatx80 *a) -{ - if (floatx80_is_signaling_nan(*a)) - float_raise(float_flag_invalid); - - a->low |= LIT64(0xC000000000000000); - - return *a; -} - -#define float_flag_denormal 0x02 - -#define floatx80_default_nan_exp 0xFFFF -#define floatx80_default_nan_fraction LIT64(0xC000000000000000) - -#define packFloatx80m(zSign, zExp, zSig) {(zSig), ((zSign) << 15) + (zExp) } - -/*---------------------------------------------------------------------------- -| Packs two 64-bit precision integers into into the quadruple-precision -| floating-point value, returning the result. -*----------------------------------------------------------------------------*/ - -#define packFloat2x128m(zHi, zLo) {(zLo), (zHi)} -#define PACK_FLOAT_128(hi,lo) packFloat2x128m(LIT64(hi),LIT64(lo)) - -static const floatx80 floatx80_default_nan = - packFloatx80m(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point ordering relations -*----------------------------------------------------------------------------*/ -enum { - float_relation_less = -1, - float_relation_equal = 0, - float_relation_greater = 1, - float_relation_unordered = 2 -}; - -#define EXP_BIAS 0x3FFF - - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the extended double-precision floating- -| point value `a' and quadruple-precision floating point value `b'. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC floatx80 floatx80_mul128(floatx80 a, float128 b) -{ - Bit32s aExp, bExp, zExp; - Bit64u aSig, bSig0, bSig1, zSig0, zSig1, zSig2; - int aSign, bSign, zSign; - - // handle unsupported extended double-precision floating encodings - if (0 /* floatx80_is_unsupported(a) */) - { - invalid: - float_raise(float_flag_invalid); - return floatx80_default_nan; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig0 = extractFloat128Frac0(b); - bSig1 = extractFloat128Frac1(b); - bExp = extractFloat128Exp(b); - bSign = extractFloat128Sign(b); - - zSign = aSign ^ bSign; - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1) - || ((bExp == 0x7FFF) && (bSig0 | bSig1))) - { - floatx80 r = commonNaNToFloatx80(float128ToCommonNaN(b)); - return propagateFloatx80NaN(a, r); - } - if (bExp == 0) { - if ((bSig0 | bSig1) == 0) goto invalid; - float_raise(float_flag_denormal); - } - return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000)); - } - if (bExp == 0x7FFF) { - if (bSig0 | bSig1) { - floatx80 r = commonNaNToFloatx80(float128ToCommonNaN(b)); - return propagateFloatx80NaN(a, r); - } - if (aExp == 0) { - if (aSig == 0) goto invalid; - float_raise(float_flag_denormal); - } - return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000)); - } - if (aExp == 0) { - if (aSig == 0) { - if ((bExp == 0) && (bSig0 | bSig1)) float_raise(float_flag_denormal); - return packFloatx80(zSign, 0, 0); - } - float_raise(float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - if ((bSig0 | bSig1) == 0) return packFloatx80(zSign, 0, 0); - float_raise(float_flag_denormal); - normalizeFloat128Subnormal(bSig0, bSig1, &bExp, &bSig0, &bSig1); - } - else bSig0 |= LIT64(0x0001000000000000); - - zExp = aExp + bExp - 0x3FFE; - shortShift128Left(bSig0, bSig1, 15, &bSig0, &bSig1); - mul128By64To192(bSig0, bSig1, aSig, &zSig0, &zSig1, &zSig2); - if (0 < (Bit64s) zSig0) { - shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); - --zExp; - } - return - roundAndPackFloatx80(floatx80_rounding_precision, - zSign, zExp, zSig0, zSig1); -} - -/* ----- from original file "softfloatx80.h" ----- */ - -/* - ["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.] -*/ - - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point class. -*----------------------------------------------------------------------------*/ -typedef enum { - float_zero, - float_NaN, - float_negative_inf, - float_positive_inf, - float_denormal, - float_normalized -} float_class_t; - - -/*----------------------------------------------------------------------------- -| Calculates the absolute value of the extended double-precision floating-point -| value `a'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -#if 0 -inline floatx80 floatx80_abs(floatx80 *reg) -{ - reg->high &= 0x7FFF; - return *reg; -} -#endif - -/*----------------------------------------------------------------------------- -| Changes the sign of the extended double-precision floating-point value 'a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC floatx80 floatx80_chs(floatx80 *x) -{ - x->high ^= 0x8000; - return *x; -} - -/* ----- end from original file "softfloatx80.h" ----- */ - -/* ----- from original file "softfloatx80.cc" ----- */ - -/* - ["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.] -*/ - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 16-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic - which means in particular that the conversion -| is rounded according to the current rounding mode. If `a' is a NaN or the -| conversion overflows, the integer indefinite value is returned. -*----------------------------------------------------------------------------*/ - -#if cIncludeFPUUnused -LOCALFUNC Bit16s floatx80_to_int16(floatx80 a) -{ -#if 0 - if (floatx80_is_unsupported(a)) - { - float_raise(float_flag_invalid); - return int16_indefinite; - } -#endif - - Bit32s v32 = floatx80_to_int32(a); - - if ((v32 > 32767) || (v32 < -32768)) { - float_exception_flags = float_flag_invalid; // throw way other flags - return int16_indefinite; - } - - return (Bit16s) v32; -} -#endif - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 16-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic, except that the conversion is always rounded -| toward zero. If `a' is a NaN or the conversion overflows, the integer -| indefinite value is returned. -*----------------------------------------------------------------------------*/ - -#if cIncludeFPUUnused -LOCALFUNC Bit16s floatx80_to_int16_round_to_zero(floatx80 a) -{ -#if 0 - if (floatx80_is_unsupported(a)) - { - float_raise(float_flag_invalid); - return int16_indefinite; - } -#endif - - Bit32s v32 = floatx80_to_int32_round_to_zero(a); - - if ((v32 > 32767) || (v32 < -32768)) { - float_exception_flags = float_flag_invalid; // throw way other flags - return int16_indefinite; - } - - return (Bit16s) v32; -} -#endif - -/*---------------------------------------------------------------------------- -| Separate the source extended double-precision floating point value `a' -| into its exponent and significand, store the significant back to the -| 'a' and return the exponent. The operation performed is a superset of -| the IEC/IEEE recommended logb(x) function. -*----------------------------------------------------------------------------*/ - -LOCALFUNC floatx80 floatx80_extract(floatx80 *a) -{ - Bit64u aSig = extractFloatx80Frac(*a); - Bit32s aExp = extractFloatx80Exp(*a); - int aSign = extractFloatx80Sign(*a); - -#if 0 - if (floatx80_is_unsupported(*a)) - { - float_raise(float_flag_invalid); - *a = floatx80_default_nan; - return *a; - } -#endif - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) - { - *a = propagateOneFloatx80NaN(a); - return *a; - } - return packFloatx80(0, 0x7FFF, LIT64(0x8000000000000000)); - } - if (aExp == 0) - { - if (aSig == 0) { - float_raise(float_flag_divbyzero); - *a = packFloatx80(aSign, 0, 0); - return packFloatx80(1, 0x7FFF, LIT64(0x8000000000000000)); - } - float_raise(float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - - a->high = (aSign << 15) + 0x3FFF; - a->low = aSig; - return int32_to_floatx80(aExp - 0x3FFF); -} - -/*---------------------------------------------------------------------------- -| Scales extended double-precision floating-point value in operand `a' by -| value `b'. The function truncates the value in the second operand 'b' to -| an integral value and adds that value to the exponent of the operand 'a'. -| The operation performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -LOCALFUNC floatx80 floatx80_scale(floatx80 a, floatx80 b) -{ - int shiftCount; - Bit32s scale; - - // handle unsupported extended double-precision floating encodings -#if 0 - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) - { - float_raise(float_flag_invalid); - return floatx80_default_nan; - } -#endif - - Bit64u aSig = extractFloatx80Frac(a); - Bit32s aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - Bit64u bSig = extractFloatx80Frac(b); - Bit32s bExp = extractFloatx80Exp(b); - int bSign = extractFloatx80Sign(b); - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) - { - return propagateFloatx80NaN(a, b); - } - if ((bExp == 0x7FFF) && bSign) { - float_raise(float_flag_invalid); - return floatx80_default_nan; - } - if (bSig && (bExp == 0)) float_raise(float_flag_denormal); - return a; - } - if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b); - if ((aExp | aSig) == 0) { - if (! bSign) { - float_raise(float_flag_invalid); - return floatx80_default_nan; - } - return a; - } - if (aSig && (aExp == 0)) float_raise(float_flag_denormal); - if (bSign) return packFloatx80(aSign, 0, 0); - return packFloatx80(aSign, 0x7FFF, LIT64(0x8000000000000000)); - } - if (aExp == 0) { - if (bSig && (bExp == 0)) float_raise(float_flag_denormal); - if (aSig == 0) return a; - float_raise(float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - if (bExp < 0x3FFF) - return normalizeRoundAndPackFloatx80(80, aSign, aExp, aSig, 0); - } - if (bExp == 0) { - if (bSig == 0) return a; - float_raise(float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - - if (bExp > 0x400E) { - /* generate appropriate overflow/underflow */ - return roundAndPackFloatx80(80, aSign, - bSign ? -0x3FFF : 0x7FFF, aSig, 0); - } - - if (bExp < 0x3FFF) return a; - - shiftCount = 0x403E - bExp; - bSig >>= shiftCount; - scale = (Bit32s) bSig; - if (bSign) scale = -scale; /* -32768..32767 */ - return - roundAndPackFloatx80(80, aSign, aExp+scale, aSig, 0); -} - -/*---------------------------------------------------------------------------- -| Determine extended-precision floating-point number class. -*----------------------------------------------------------------------------*/ - -#if cIncludeFPUUnused -LOCALFUNC float_class_t floatx80_class(floatx80 a) -{ - Bit32s aExp = extractFloatx80Exp(a); - Bit64u aSig = extractFloatx80Frac(a); - - if(aExp == 0) { - if (aSig == 0) - return float_zero; - - /* denormal or pseudo-denormal */ - return float_denormal; - } - - /* valid numbers have the MS bit set */ - if (!(aSig & LIT64(0x8000000000000000))) - return float_NaN; /* report unsupported as NaNs */ - - if(aExp == 0x7fff) { - int aSign = extractFloatx80Sign(a); - - if (((Bit64u) (aSig<< 1)) == 0) - return (aSign) ? float_negative_inf : float_positive_inf; - - return float_NaN; - } - - return float_normalized; -} -#endif - -/*---------------------------------------------------------------------------- -| Compare between two extended precision floating point numbers. Returns -| 'float_relation_equal' if the operands are equal, 'float_relation_less' if -| the value 'a' is less than the corresponding value `b', -| 'float_relation_greater' if the value 'a' is greater than the corresponding -| value `b', or 'float_relation_unordered' otherwise. -*----------------------------------------------------------------------------*/ - -#if cIncludeFPUUnused -LOCALFUNC int floatx80_compare(floatx80 a, floatx80 b) -{ - int aSign; - int bSign; - Bit64u aSig; - Bit32s aExp; - Bit64u bSig; - Bit32s bExp; - int less_than; - float_class_t aClass = floatx80_class(a); - float_class_t bClass = floatx80_class(b); - - if (aClass == float_NaN || bClass == float_NaN) - { - float_raise(float_flag_invalid); - return float_relation_unordered; - } - - if (aClass == float_denormal || bClass == float_denormal) - { - float_raise(float_flag_denormal); - } - - aSign = extractFloatx80Sign(a); - bSign = extractFloatx80Sign(b); - - if (aClass == float_zero) { - if (bClass == float_zero) return float_relation_equal; - return bSign ? float_relation_greater : float_relation_less; - } - - if (bClass == float_zero || aSign != bSign) { - return aSign ? float_relation_less : float_relation_greater; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - - if (aClass == float_denormal) - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - - if (bClass == float_denormal) - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - - if (aExp == bExp && aSig == bSig) - return float_relation_equal; - - less_than = - aSign ? ((bExp < aExp) || ((bExp == aExp) && (bSig < aSig))) - : ((aExp < bExp) || ((aExp == bExp) && (aSig < bSig))); - - if (less_than) return float_relation_less; - - return float_relation_greater; -} -#endif - -/*---------------------------------------------------------------------------- -| Compare between two extended precision floating point numbers. Returns -| 'float_relation_equal' if the operands are equal, 'float_relation_less' if -| the value 'a' is less than the corresponding value `b', -| 'float_relation_greater' if the value 'a' is greater than the corresponding -| value `b', or 'float_relation_unordered' otherwise. Quiet NaNs do not cause -| an exception. -*----------------------------------------------------------------------------*/ - -#if cIncludeFPUUnused -LOCALFUNC int floatx80_compare_quiet(floatx80 a, floatx80 b) -{ - int aSign; - int bSign; - Bit64u aSig; - Bit32s aExp; - Bit64u bSig; - Bit32s bExp; - int less_than; - float_class_t aClass = floatx80_class(a); - float_class_t bClass = floatx80_class(b); - - if (aClass == float_NaN || bClass == float_NaN) - { -#if 0 - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) - float_raise(float_flag_invalid); -#endif - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - float_raise(float_flag_invalid); - - return float_relation_unordered; - } - - if (aClass == float_denormal || bClass == float_denormal) - { - float_raise(float_flag_denormal); - } - - aSign = extractFloatx80Sign(a); - bSign = extractFloatx80Sign(b); - - if (aClass == float_zero) { - if (bClass == float_zero) return float_relation_equal; - return bSign ? float_relation_greater : float_relation_less; - } - - if (bClass == float_zero || aSign != bSign) { - return aSign ? float_relation_less : float_relation_greater; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - - if (aClass == float_denormal) - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - - if (bClass == float_denormal) - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - - if (aExp == bExp && aSig == bSig) - return float_relation_equal; - - less_than = - aSign ? ((bExp < aExp) || ((bExp == aExp) && (bSig < aSig))) - : ((aExp < bExp) || ((aExp == bExp) && (aSig < bSig))); - - if (less_than) return float_relation_less; - return float_relation_greater; -} -#endif - -/* ----- end from original file "softfloatx80.cc" ----- */ - -/* ----- from original file "fprem.cc" ----- */ - -/* - ["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.] -*/ - -#define USE_estimateDiv128To64 - -/* executes single exponent reduction cycle */ -LOCALFUNC Bit64u remainder_kernel(Bit64u aSig0, Bit64u bSig, int expDiff, Bit64u *zSig0, Bit64u *zSig1) -{ - Bit64u term0, term1; - Bit64u aSig1 = 0; - Bit64u q; - - shortShift128Left(aSig1, aSig0, expDiff, &aSig1, &aSig0); - q = estimateDiv128To64(aSig1, aSig0, bSig); - mul64To128(bSig, q, &term0, &term1); - sub128(aSig1, aSig0, term0, term1, zSig1, zSig0); - while ((Bit64s)(*zSig1) < 0) { - --q; - add128(*zSig1, *zSig0, 0, bSig, zSig1, zSig0); - } - return q; -} - -LOCALFUNC floatx80 do_fprem(floatx80 a, floatx80 b, Bit64u *q, int rounding_mode) -{ - Bit32s aExp, bExp, zExp, expDiff; - Bit64u aSig0, aSig1, bSig; - int aSign; - *q = 0; - -#if 0 - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) - { - float_raise(float_flag_invalid); - return floatx80_default_nan; - } -#endif - - aSig0 = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig0<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) { - return propagateFloatx80NaN(a, b); - } - float_raise(float_flag_invalid); - return floatx80_default_nan; - } - if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b); - if (aExp == 0 && aSig0) { - float_raise(float_flag_denormal); - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); - return (a.low & LIT64(0x8000000000000000)) ? - packFloatx80(aSign, aExp, aSig0) : a; - } - return a; - } - if (bExp == 0) { - if (bSig == 0) { - float_raise(float_flag_invalid); - return floatx80_default_nan; - } - float_raise(float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - if (aExp == 0) { - if (aSig0 == 0) return a; - float_raise(float_flag_denormal); - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); - } - expDiff = aExp - bExp; - aSig1 = 0; - - if (expDiff >= 64) { - int n = (expDiff & 0x1f) | 0x20; - remainder_kernel(aSig0, bSig, n, &aSig0, &aSig1); - zExp = aExp - n; - *q = (Bit64u) -1; - } - else { - zExp = bExp; - - if (expDiff < 0) { - if (expDiff < -1) - return (a.low & LIT64(0x8000000000000000)) ? - packFloatx80(aSign, aExp, aSig0) : a; - shift128Right(aSig0, 0, 1, &aSig0, &aSig1); - expDiff = 0; - } - - if (expDiff > 0) { - *q = remainder_kernel(aSig0, bSig, expDiff, &aSig0, &aSig1); - } - else { - if (bSig <= aSig0) { - aSig0 -= bSig; - *q = 1; - } - } - - if (rounding_mode == float_round_nearest_even) - { - Bit64u term0, term1; - shift128Right(bSig, 0, 1, &term0, &term1); - - if (! lt128(aSig0, aSig1, term0, term1)) - { - int lt = lt128(term0, term1, aSig0, aSig1); - int eq = eq128(aSig0, aSig1, term0, term1); - - if ((eq && (*q & 1)) || lt) { - aSign = !aSign; - ++*q; - } - if (lt) sub128(bSig, 0, aSig0, aSig1, &aSig0, &aSig1); - } - } - } - - return normalizeRoundAndPackFloatx80(80, aSign, zExp, aSig0, aSig1); -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the extended double-precision floating-point value -| `a' with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -#if cIncludeFPUUnused -LOCALFUNC floatx80 floatx80_ieee754_remainder(floatx80 a, floatx80 b, Bit64u *q) -{ - return do_fprem(a, b, q, float_round_nearest_even); -} -#endif - -/*---------------------------------------------------------------------------- -| Returns the remainder of the extended double-precision floating-point value -| `a' with respect to the corresponding value `b'. Unlike previous function -| the function does not compute the remainder specified in the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. This function operates -| differently from the previous function in the way that it rounds the -| quotient of 'a' divided by 'b' to an integer. -*----------------------------------------------------------------------------*/ - -LOCALFUNC floatx80 floatx80_remainder(floatx80 a, floatx80 b, Bit64u *q) -{ - return do_fprem(a, b, q, float_round_to_zero); -} - -/* ----- end from original file "fprem.cc" ----- */ - -/* ----- from original file "fpu_constant.h" ----- */ - -/* - ["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.] -*/ - -// Pentium CPU uses only 68-bit precision M_PI approximation -// #define BETTER_THAN_PENTIUM - -////////////////////////////// -// PI, PI/2, PI/4 constants -////////////////////////////// - -#define FLOATX80_PI_EXP (0x4000) - -// 128-bit PI fraction -#ifdef BETTER_THAN_PENTIUM -#define FLOAT_PI_HI (LIT64(0xc90fdaa22168c234)) -#define FLOAT_PI_LO (LIT64(0xc4c6628b80dc1cd1)) -#else -#define FLOAT_PI_HI (LIT64(0xc90fdaa22168c234)) -#define FLOAT_PI_LO (LIT64(0xC000000000000000)) -#endif - -#define FLOATX80_PI2_EXP (0x3FFF) -#define FLOATX80_PI4_EXP (0x3FFE) - -////////////////////////////// -// 3PI/4 constant -////////////////////////////// - -#define FLOATX80_3PI4_EXP (0x4000) - -// 128-bit 3PI/4 fraction -#ifdef BETTER_THAN_PENTIUM -#define FLOAT_3PI4_HI (LIT64(0x96cbe3f9990e91a7)) -#define FLOAT_3PI4_LO (LIT64(0x9394c9e8a0a5159c)) -#else -#define FLOAT_3PI4_HI (LIT64(0x96cbe3f9990e91a7)) -#define FLOAT_3PI4_LO (LIT64(0x9000000000000000)) -#endif - -////////////////////////////// -// 1/LN2 constant -////////////////////////////// - -#define FLOAT_LN2INV_EXP (0x3FFF) - -// 128-bit 1/LN2 fraction -#ifdef BETTER_THAN_PENTIUM -#define FLOAT_LN2INV_HI (LIT64(0xb8aa3b295c17f0bb)) -#define FLOAT_LN2INV_LO (LIT64(0xbe87fed0691d3e89)) -#else -#define FLOAT_LN2INV_HI (LIT64(0xb8aa3b295c17f0bb)) -#define FLOAT_LN2INV_LO (LIT64(0xC000000000000000)) -#endif - -/* ----- end from original file "fpu_constant.h" ----- */ - -/* ----- from original file "poly.cc" ----- */ - -/* - ["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.] -*/ - -// 2 3 4 n -// f(x) ~ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) -// 0 1 2 3 4 n -// -// -- 2k -- 2k+1 -// p(x) = > C * x q(x) = > C * x -// -- 2k -- 2k+1 -// -// f(x) ~ [ p(x) + x * q(x) ] -// - -LOCALFUNC float128 EvalPoly(float128 x, float128 *arr, unsigned n) -{ - float128 r2; - float128 x2 = float128_mul(x, x); - unsigned i; - -#if 0 - assert(n > 1); -#endif - - float128 r1 = arr[--n]; - i = n; - while(i >= 2) { - r1 = float128_mul(r1, x2); - i -= 2; - r1 = float128_add(r1, arr[i]); - } - if (i) r1 = float128_mul(r1, x); - - r2 = arr[--n]; - i = n; - while(i >= 2) { - r2 = float128_mul(r2, x2); - i -= 2; - r2 = float128_add(r2, arr[i]); - } - if (i) r2 = float128_mul(r2, x); - - return float128_add(r1, r2); -} - -// 2 4 6 8 2n -// f(x) ~ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) -// 0 1 2 3 4 n -// -// -- 4k -- 4k+2 -// p(x) = > C * x q(x) = > C * x -// -- 2k -- 2k+1 -// -// 2 -// f(x) ~ [ p(x) + x * q(x) ] -// - -LOCALFUNC float128 EvenPoly(float128 x, float128 *arr, unsigned n) -{ - return EvalPoly(float128_mul(x, x), arr, n); -} - -// 3 5 7 9 2n+1 -// f(x) ~ (C * x) + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) -// 0 1 2 3 4 n -// 2 4 6 8 2n -// = x * [ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) -// 0 1 2 3 4 n -// -// -- 4k -- 4k+2 -// p(x) = > C * x q(x) = > C * x -// -- 2k -- 2k+1 -// -// 2 -// f(x) ~ x * [ p(x) + x * q(x) ] -// - -LOCALFUNC float128 OddPoly(float128 x, float128 *arr, unsigned n) -{ - return float128_mul(x, EvenPoly(x, arr, n)); -} - -/* ----- end from original file "poly.cc" ----- */ - -/* ----- from original file "fyl2x.cc" ----- */ - -/* - ["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.] -*/ - -static const floatx80 floatx80_one = - packFloatx80m(0, 0x3fff, LIT64(0x8000000000000000)); - -static const float128 float128_one = - packFloat2x128m(LIT64(0x3fff000000000000), LIT64(0x0000000000000000)); -static const float128 float128_two = - packFloat2x128m(LIT64(0x4000000000000000), LIT64(0x0000000000000000)); - -static const float128 float128_ln2inv2 = - packFloat2x128m(LIT64(0x400071547652b82f), LIT64(0xe1777d0ffda0d23a)); - -#define SQRT2_HALF_SIG LIT64(0xb504f333f9de6484) - -#define L2_ARR_SIZE 9 - -static float128 ln_arr[L2_ARR_SIZE] = -{ - PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ - PACK_FLOAT_128(0x3ffd555555555555, 0x5555555555555555), /* 3 */ - PACK_FLOAT_128(0x3ffc999999999999, 0x999999999999999a), /* 5 */ - PACK_FLOAT_128(0x3ffc249249249249, 0x2492492492492492), /* 7 */ - PACK_FLOAT_128(0x3ffbc71c71c71c71, 0xc71c71c71c71c71c), /* 9 */ - PACK_FLOAT_128(0x3ffb745d1745d174, 0x5d1745d1745d1746), /* 11 */ - PACK_FLOAT_128(0x3ffb3b13b13b13b1, 0x3b13b13b13b13b14), /* 13 */ - PACK_FLOAT_128(0x3ffb111111111111, 0x1111111111111111), /* 15 */ - PACK_FLOAT_128(0x3ffae1e1e1e1e1e1, 0xe1e1e1e1e1e1e1e2) /* 17 */ -}; - -LOCALFUNC float128 poly_ln(float128 x1) -{ -/* - // - // 3 5 7 9 11 13 15 - // 1+u u u u u u u u - // 1/2 ln --- ~ u + --- + --- + --- + --- + ---- + ---- + ---- = - // 1-u 3 5 7 9 11 13 15 - // - // 2 4 6 8 10 12 14 - // u u u u u u u - // = u * [ 1 + --- + --- + --- + --- + ---- + ---- + ---- ] = - // 3 5 7 9 11 13 15 - // - // 3 3 - // -- 4k -- 4k+2 - // p(u) = > C * u q(u) = > C * u - // -- 2k -- 2k+1 - // k=0 k=0 - // - // 1+u 2 - // 1/2 ln --- ~ u * [ p(u) + u * q(u) ] - // 1-u - // -*/ - return OddPoly(x1, ln_arr, L2_ARR_SIZE); -} - -/* required sqrt(2)/2 < x < sqrt(2) */ -LOCALFUNC float128 poly_l2(float128 x) -{ - /* using float128 for approximation */ - float128 x_p1 = float128_add(x, float128_one); - float128 x_m1 = float128_sub(x, float128_one); - x = float128_div(x_m1, x_p1); - x = poly_ln(x); - x = float128_mul(x, float128_ln2inv2); - return x; -} - -LOCALFUNC float128 poly_l2p1(float128 x) -{ - /* using float128 for approximation */ - float128 x_p2 = float128_add(x, float128_two); - x = float128_div(x, x_p2); - x = poly_ln(x); - x = float128_mul(x, float128_ln2inv2); - return x; -} - -// ================================================= -// FYL2X Compute y * log (x) -// 2 -// ================================================= - -// -// Uses the following identities: -// -// 1. ---------------------------------------------------------- -// ln(x) -// log (x) = -------, ln (x*y) = ln(x) + ln(y) -// 2 ln(2) -// -// 2. ---------------------------------------------------------- -// 1+u x-1 -// ln (x) = ln -----, when u = ----- -// 1-u x+1 -// -// 3. ---------------------------------------------------------- -// 3 5 7 2n+1 -// 1+u u u u u -// ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ] -// 1-u 3 5 7 2n+1 -// - -LOCALFUNC floatx80 fyl2x(floatx80 a, floatx80 b) -{ - int aSign; - int bSign; - Bit64u aSig; - Bit32s aExp; - Bit64u bSig; - Bit32s bExp; - int zSign; - int ExpDiff; - Bit64u zSig0, zSig1; - float128 x; - - // handle unsupported extended double-precision floating encodings - if (0 /* floatx80_is_unsupported(a) */) { -invalid: - float_raise(float_flag_invalid); - return floatx80_default_nan; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - bSign = extractFloatx80Sign(b); - - zSign = bSign ^ 1; - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1) - || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) - { - return propagateFloatx80NaN(a, b); - } - if (aSign) goto invalid; - else { - if (bExp == 0) { - if (bSig == 0) goto invalid; - float_raise(float_flag_denormal); - } - return packFloatx80(bSign, 0x7FFF, LIT64(0x8000000000000000)); - } - } - if (bExp == 0x7FFF) - { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b); - if (aSign && (Bit64u)(aExp | aSig)) goto invalid; - if (aSig && (aExp == 0)) - float_raise(float_flag_denormal); - if (aExp < 0x3FFF) { - return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000)); - } - if (aExp == 0x3FFF && ((Bit64u) (aSig<<1) == 0)) goto invalid; - return packFloatx80(bSign, 0x7FFF, LIT64(0x8000000000000000)); - } - if (aExp == 0) { - if (aSig == 0) { - if ((bExp | bSig) == 0) goto invalid; - float_raise(float_flag_divbyzero); - return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000)); - } - if (aSign) goto invalid; - float_raise(float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - if (aSign) goto invalid; - if (bExp == 0) { - if (bSig == 0) { - if (aExp < 0x3FFF) return packFloatx80(zSign, 0, 0); - return packFloatx80(bSign, 0, 0); - } - float_raise(float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - if (aExp == 0x3FFF && ((Bit64u) (aSig<<1) == 0)) - return packFloatx80(bSign, 0, 0); - - float_raise(float_flag_inexact); - - ExpDiff = aExp - 0x3FFF; - aExp = 0; - if (aSig >= SQRT2_HALF_SIG) { - ExpDiff++; - aExp--; - } - - /* ******************************** */ - /* using float128 for approximation */ - /* ******************************** */ - - shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); - x = packFloat128(0, aExp+0x3FFF, zSig0, zSig1); - x = poly_l2(x); - x = float128_add(x, floatx80_to_float128(int32_to_floatx80(ExpDiff))); - return floatx80_mul128(b, x); -} - -// ================================================= -// FYL2XP1 Compute y * log (x + 1) -// 2 -// ================================================= - -// -// Uses the following identities: -// -// 1. ---------------------------------------------------------- -// ln(x) -// log (x) = ------- -// 2 ln(2) -// -// 2. ---------------------------------------------------------- -// 1+u x -// ln (x+1) = ln -----, when u = ----- -// 1-u x+2 -// -// 3. ---------------------------------------------------------- -// 3 5 7 2n+1 -// 1+u u u u u -// ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ] -// 1-u 3 5 7 2n+1 -// - -LOCALFUNC floatx80 fyl2xp1(floatx80 a, floatx80 b) -{ - Bit32s aExp, bExp; - Bit64u aSig, bSig, zSig0, zSig1, zSig2; - int aSign, bSign; - int zSign; - float128 x; - - // handle unsupported extended double-precision floating encodings - if (0 /* floatx80_is_unsupported(a) */) { -invalid: - float_raise(float_flag_invalid); - return floatx80_default_nan; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - bSign = extractFloatx80Sign(b); - zSign = aSign ^ bSign; - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1) - || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) - { - return propagateFloatx80NaN(a, b); - } - if (aSign) goto invalid; - else { - if (bExp == 0) { - if (bSig == 0) goto invalid; - float_raise(float_flag_denormal); - } - return packFloatx80(bSign, 0x7FFF, LIT64(0x8000000000000000)); - } - } - if (bExp == 0x7FFF) - { - if ((Bit64u) (bSig<<1)) - return propagateFloatx80NaN(a, b); - - if (aExp == 0) { - if (aSig == 0) goto invalid; - float_raise(float_flag_denormal); - } - - return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000)); - } - if (aExp == 0) { - if (aSig == 0) { - if (bSig && (bExp == 0)) float_raise(float_flag_denormal); - return packFloatx80(zSign, 0, 0); - } - float_raise(float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - if (bSig == 0) return packFloatx80(zSign, 0, 0); - float_raise(float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - - float_raise(float_flag_inexact); - - if (aSign && aExp >= 0x3FFF) - return a; - - if (aExp >= 0x3FFC) // big argument - { - return fyl2x(floatx80_add(a, floatx80_one), b); - } - - // handle tiny argument - if (aExp < EXP_BIAS-70) - { - // first order approximation, return (a*b)/ln(2) - Bit32s zExp = aExp + FLOAT_LN2INV_EXP - 0x3FFE; - - mul128By64To192(FLOAT_LN2INV_HI, FLOAT_LN2INV_LO, aSig, &zSig0, &zSig1, &zSig2); - if (0 < (Bit64s) zSig0) { - shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); - --zExp; - } - - zExp = zExp + bExp - 0x3FFE; - mul128By64To192(zSig0, zSig1, bSig, &zSig0, &zSig1, &zSig2); - if (0 < (Bit64s) zSig0) { - shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); - --zExp; - } - - return - roundAndPackFloatx80(80, aSign ^ bSign, zExp, zSig0, zSig1); - } - - /* ******************************** */ - /* using float128 for approximation */ - /* ******************************** */ - - shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); - x = packFloat128(aSign, aExp, zSig0, zSig1); - x = poly_l2p1(x); - return floatx80_mul128(b, x); -} - -/* ----- end from original file "fyl2x.cc" ----- */ - -/* ----- from original file "f2xm1.cc" ----- */ - -/* - ["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.] -*/ - -static const floatx80 floatx80_negone = packFloatx80m(1, 0x3fff, LIT64(0x8000000000000000)); -static const floatx80 floatx80_neghalf = packFloatx80m(1, 0x3ffe, LIT64(0x8000000000000000)); -static const float128 float128_ln2 = - packFloat2x128m(LIT64(0x3ffe62e42fefa39e), LIT64(0xf35793c7673007e6)); - -#define LN2_SIG LIT64(0xb17217f7d1cf79ac) - -#define EXP_ARR_SIZE 15 - -static float128 exp_arr[EXP_ARR_SIZE] = -{ - PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ - PACK_FLOAT_128(0x3ffe000000000000, 0x0000000000000000), /* 2 */ - PACK_FLOAT_128(0x3ffc555555555555, 0x5555555555555555), /* 3 */ - PACK_FLOAT_128(0x3ffa555555555555, 0x5555555555555555), /* 4 */ - PACK_FLOAT_128(0x3ff8111111111111, 0x1111111111111111), /* 5 */ - PACK_FLOAT_128(0x3ff56c16c16c16c1, 0x6c16c16c16c16c17), /* 6 */ - PACK_FLOAT_128(0x3ff2a01a01a01a01, 0xa01a01a01a01a01a), /* 7 */ - PACK_FLOAT_128(0x3fefa01a01a01a01, 0xa01a01a01a01a01a), /* 8 */ - PACK_FLOAT_128(0x3fec71de3a556c73, 0x38faac1c88e50017), /* 9 */ - PACK_FLOAT_128(0x3fe927e4fb7789f5, 0xc72ef016d3ea6679), /* 10 */ - PACK_FLOAT_128(0x3fe5ae64567f544e, 0x38fe747e4b837dc7), /* 11 */ - PACK_FLOAT_128(0x3fe21eed8eff8d89, 0x7b544da987acfe85), /* 12 */ - PACK_FLOAT_128(0x3fde6124613a86d0, 0x97ca38331d23af68), /* 13 */ - PACK_FLOAT_128(0x3fda93974a8c07c9, 0xd20badf145dfa3e5), /* 14 */ - PACK_FLOAT_128(0x3fd6ae7f3e733b81, 0xf11d8656b0ee8cb0) /* 15 */ -}; - -/* required -1 < x < 1 */ -LOCALFUNC float128 poly_exp(float128 x) -{ -/* - // 2 3 4 5 6 7 8 9 - // x x x x x x x x x - // e - 1 ~ x + --- + --- + --- + --- + --- + --- + --- + --- + ... - // 2! 3! 4! 5! 6! 7! 8! 9! - // - // 2 3 4 5 6 7 8 - // x x x x x x x x - // = x [ 1 + --- + --- + --- + --- + --- + --- + --- + --- + ... ] - // 2! 3! 4! 5! 6! 7! 8! 9! - // - // 8 8 - // -- 2k -- 2k+1 - // p(x) = > C * x q(x) = > C * x - // -- 2k -- 2k+1 - // k=0 k=0 - // - // x - // e - 1 ~ x * [ p(x) + x * q(x) ] - // -*/ - float128 t = EvalPoly(x, exp_arr, EXP_ARR_SIZE); - return float128_mul(t, x); -} - -// ================================================= -// x -// FX2P1 Compute 2 - 1 -// ================================================= - -// -// Uses the following identities: -// -// 1. ---------------------------------------------------------- -// x x*ln(2) -// 2 = e -// -// 2. ---------------------------------------------------------- -// 2 3 4 5 n -// x x x x x x x -// e = 1 + --- + --- + --- + --- + --- + ... + --- + ... -// 1! 2! 3! 4! 5! n! -// - -LOCALFUNC floatx80 f2xm1(floatx80 a) -{ - Bit64u zSig0, zSig1; - float128 x; - -#if 0 - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a)) - { - float_raise(float_flag_invalid); - return floatx80_default_nan; - } -#endif - - Bit64u aSig = extractFloatx80Frac(a); - Bit32s aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) - return propagateOneFloatx80NaN(&a); - - return (aSign) ? floatx80_negone : a; - } - - if (aExp == 0) { - if (aSig == 0) return a; - float_raise(float_flag_denormal | float_flag_inexact); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - - tiny_argument: - mul64To128(aSig, LN2_SIG, &zSig0, &zSig1); - if (0 < (Bit64s) zSig0) { - shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); - --aExp; - } - return - roundAndPackFloatx80(80, aSign, aExp, zSig0, zSig1); - } - - float_raise(float_flag_inexact); - - if (aExp < 0x3FFF) - { - if (aExp < EXP_BIAS-68) - goto tiny_argument; - - /* ******************************** */ - /* using float128 for approximation */ - /* ******************************** */ - - x = floatx80_to_float128(a); - x = float128_mul(x, float128_ln2); - x = poly_exp(x); - return float128_to_floatx80(x); - } - else - { - if ((a.high == 0xBFFF) && (! (aSig<<1))) - return floatx80_neghalf; - - return a; - } -} - -/* ----- end from original file "f2xm1.cc" ----- */ - -/* ----- from original file "fsincos.cc" ----- */ - -/* - ["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.] -*/ - -#define USE_estimateDiv128To64 - -#if 0 -static const floatx80 floatx80_one = packFloatx80m(0, 0x3fff, LIT64(0x8000000000000000)); -#endif - -/* reduce trigonometric function argument using 128-bit precision - M_PI approximation */ -LOCALFUNC Bit64u argument_reduction_kernel(Bit64u aSig0, int Exp, Bit64u *zSig0, Bit64u *zSig1) -{ - Bit64u term0, term1, term2; - Bit64u aSig1 = 0; - Bit64u q; - - shortShift128Left(aSig1, aSig0, Exp, &aSig1, &aSig0); - q = estimateDiv128To64(aSig1, aSig0, FLOAT_PI_HI); - mul128By64To192(FLOAT_PI_HI, FLOAT_PI_LO, q, &term0, &term1, &term2); - sub128(aSig1, aSig0, term0, term1, zSig1, zSig0); - while ((Bit64s)(*zSig1) < 0) { - --q; - add192(*zSig1, *zSig0, term2, 0, FLOAT_PI_HI, FLOAT_PI_LO, zSig1, zSig0, &term2); - } - *zSig1 = term2; - return q; -} - -LOCALFUNC int reduce_trig_arg(int expDiff, int *zSign, Bit64u *aSig0, Bit64u *aSig1) -{ - Bit64u term0, term1, q = 0; - - if (expDiff < 0) { - shift128Right(*aSig0, 0, 1, aSig0, aSig1); - expDiff = 0; - } - if (expDiff > 0) { - q = argument_reduction_kernel(*aSig0, expDiff, aSig0, aSig1); - } - else { - if (FLOAT_PI_HI <= *aSig0) { - *aSig0 -= FLOAT_PI_HI; - q = 1; - } - } - - shift128Right(FLOAT_PI_HI, FLOAT_PI_LO, 1, &term0, &term1); - if (! lt128(*aSig0, *aSig1, term0, term1)) - { - int lt = lt128(term0, term1, *aSig0, *aSig1); - int eq = eq128(*aSig0, *aSig1, term0, term1); - - if ((eq && (q & 1)) || lt) { - *zSign = !*zSign; - ++q; - } - if (lt) sub128(FLOAT_PI_HI, FLOAT_PI_LO, *aSig0, *aSig1, aSig0, aSig1); - } - - return (int)(q & 3); -} - -#define SIN_ARR_SIZE 9 -#define COS_ARR_SIZE 9 - -static float128 sin_arr[SIN_ARR_SIZE] = -{ - PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ - PACK_FLOAT_128(0xbffc555555555555, 0x5555555555555555), /* 3 */ - PACK_FLOAT_128(0x3ff8111111111111, 0x1111111111111111), /* 5 */ - PACK_FLOAT_128(0xbff2a01a01a01a01, 0xa01a01a01a01a01a), /* 7 */ - PACK_FLOAT_128(0x3fec71de3a556c73, 0x38faac1c88e50017), /* 9 */ - PACK_FLOAT_128(0xbfe5ae64567f544e, 0x38fe747e4b837dc7), /* 11 */ - PACK_FLOAT_128(0x3fde6124613a86d0, 0x97ca38331d23af68), /* 13 */ - PACK_FLOAT_128(0xbfd6ae7f3e733b81, 0xf11d8656b0ee8cb0), /* 15 */ - PACK_FLOAT_128(0x3fce952c77030ad4, 0xa6b2605197771b00) /* 17 */ -}; - -static float128 cos_arr[COS_ARR_SIZE] = -{ - PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 0 */ - PACK_FLOAT_128(0xbffe000000000000, 0x0000000000000000), /* 2 */ - PACK_FLOAT_128(0x3ffa555555555555, 0x5555555555555555), /* 4 */ - PACK_FLOAT_128(0xbff56c16c16c16c1, 0x6c16c16c16c16c17), /* 6 */ - PACK_FLOAT_128(0x3fefa01a01a01a01, 0xa01a01a01a01a01a), /* 8 */ - PACK_FLOAT_128(0xbfe927e4fb7789f5, 0xc72ef016d3ea6679), /* 10 */ - PACK_FLOAT_128(0x3fe21eed8eff8d89, 0x7b544da987acfe85), /* 12 */ - PACK_FLOAT_128(0xbfda93974a8c07c9, 0xd20badf145dfa3e5), /* 14 */ - PACK_FLOAT_128(0x3fd2ae7f3e733b81, 0xf11d8656b0ee8cb0) /* 16 */ -}; - -/* 0 <= x <= pi/4 */ -MayInline LOCALFUNC float128 poly_sin(float128 x) -{ - // 3 5 7 9 11 13 15 - // x x x x x x x - // sin (x) ~ x - --- + --- - --- + --- - ---- + ---- - ---- = - // 3! 5! 7! 9! 11! 13! 15! - // - // 2 4 6 8 10 12 14 - // x x x x x x x - // = x * [ 1 - --- + --- - --- + --- - ---- + ---- - ---- ] = - // 3! 5! 7! 9! 11! 13! 15! - // - // 3 3 - // -- 4k -- 4k+2 - // p(x) = > C * x > 0 q(x) = > C * x < 0 - // -- 2k -- 2k+1 - // k=0 k=0 - // - // 2 - // sin(x) ~ x * [ p(x) + x * q(x) ] - // - - return OddPoly(x, sin_arr, SIN_ARR_SIZE); -} - -/* 0 <= x <= pi/4 */ -MayInline LOCALFUNC float128 poly_cos(float128 x) -{ - // 2 4 6 8 10 12 14 - // x x x x x x x - // cos (x) ~ 1 - --- + --- - --- + --- - ---- + ---- - ---- - // 2! 4! 6! 8! 10! 12! 14! - // - // 3 3 - // -- 4k -- 4k+2 - // p(x) = > C * x > 0 q(x) = > C * x < 0 - // -- 2k -- 2k+1 - // k=0 k=0 - // - // 2 - // cos(x) ~ [ p(x) + x * q(x) ] - // - - return EvenPoly(x, cos_arr, COS_ARR_SIZE); -} - -MayInline LOCALPROC sincos_invalid(floatx80 *sin_a, floatx80 *cos_a, floatx80 a) -{ - if (sin_a) *sin_a = a; - if (cos_a) *cos_a = a; -} - -MayInline LOCALPROC sincos_tiny_argument(floatx80 *sin_a, floatx80 *cos_a, floatx80 a) -{ - if (sin_a) *sin_a = a; - if (cos_a) *cos_a = floatx80_one; -} - -LOCALFUNC floatx80 sincos_approximation(int neg, float128 r, Bit64u quotient) -{ - floatx80 result; - - if (quotient & 0x1) { - r = poly_cos(r); - neg = 0; - } else { - r = poly_sin(r); - } - - result = float128_to_floatx80(r); - if (quotient & 0x2) - neg = ! neg; - - if (neg) - floatx80_chs(&result); - - return result; -} - -// ================================================= -// FSINCOS Compute sin(x) and cos(x) -// ================================================= - -// -// Uses the following identities: -// ---------------------------------------------------------- -// -// sin(-x) = -sin(x) -// cos(-x) = cos(x) -// -// sin(x+y) = sin(x)*cos(y)+cos(x)*sin(y) -// cos(x+y) = sin(x)*sin(y)+cos(x)*cos(y) -// -// sin(x+ pi/2) = cos(x) -// sin(x+ pi) = -sin(x) -// sin(x+3pi/2) = -cos(x) -// sin(x+2pi) = sin(x) -// - -LOCALFUNC int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a) -{ - float128 r; - Bit64u aSig0, aSig1 = 0; - Bit32s aExp, zExp, expDiff; - int aSign, zSign; - int q = 0; - -#if 0 - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a)) - { - goto invalid; - } -#endif - - aSig0 = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - /* invalid argument */ - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig0<<1)) { - sincos_invalid(sin_a, cos_a, propagateOneFloatx80NaN(&a)); - return 0; - } - -#if 0 - invalid: -#endif - float_raise(float_flag_invalid); - sincos_invalid(sin_a, cos_a, floatx80_default_nan); - return 0; - } - - if (aExp == 0) { - if (aSig0 == 0) { - sincos_tiny_argument(sin_a, cos_a, a); - return 0; - } - - float_raise(float_flag_denormal); - - /* handle pseudo denormals */ - if (! (aSig0 & LIT64(0x8000000000000000))) - { - float_raise(float_flag_inexact); - if (sin_a) - float_raise(float_flag_underflow); - sincos_tiny_argument(sin_a, cos_a, a); - return 0; - } - - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); - } - - zSign = aSign; - zExp = EXP_BIAS; - expDiff = aExp - zExp; - - /* argument is out-of-range */ - if (expDiff >= 63) - return -1; - - float_raise(float_flag_inexact); - - if (expDiff < -1) { // doesn't require reduction - if (expDiff <= -68) { - a = packFloatx80(aSign, aExp, aSig0); - sincos_tiny_argument(sin_a, cos_a, a); - return 0; - } - zExp = aExp; - } - else { - q = reduce_trig_arg(expDiff, &zSign, &aSig0, &aSig1); - } - - /* **************************** */ - /* argument reduction completed */ - /* **************************** */ - - /* using float128 for approximation */ - r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1); - - if (aSign) q = -q; - if (sin_a) *sin_a = sincos_approximation(zSign, r, q); - if (cos_a) *cos_a = sincos_approximation(zSign, r, q+1); - - return 0; -} - -// ================================================= -// FPTAN Compute tan(x) -// ================================================= - -// -// Uses the following identities: -// -// 1. ---------------------------------------------------------- -// -// sin(-x) = -sin(x) -// cos(-x) = cos(x) -// -// sin(x+y) = sin(x)*cos(y)+cos(x)*sin(y) -// cos(x+y) = sin(x)*sin(y)+cos(x)*cos(y) -// -// sin(x+ pi/2) = cos(x) -// sin(x+ pi) = -sin(x) -// sin(x+3pi/2) = -cos(x) -// sin(x+2pi) = sin(x) -// -// 2. ---------------------------------------------------------- -// -// sin(x) -// tan(x) = ------ -// cos(x) -// - -LOCALFUNC int ftan(floatx80 *a) -{ - float128 r; - float128 sin_r; - float128 cos_r; - Bit64u aSig0, aSig1 = 0; - Bit32s aExp, zExp, expDiff; - int aSign, zSign; - int q = 0; - -#if 0 - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(*a)) - { - goto invalid; - } -#endif - - aSig0 = extractFloatx80Frac(*a); - aExp = extractFloatx80Exp(*a); - aSign = extractFloatx80Sign(*a); - - /* invalid argument */ - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig0<<1)) - { - *a = propagateOneFloatx80NaN(a); - return 0; - } - -#if 0 - invalid: -#endif - float_raise(float_flag_invalid); - *a = floatx80_default_nan; - return 0; - } - - if (aExp == 0) { - if (aSig0 == 0) return 0; - float_raise(float_flag_denormal); - /* handle pseudo denormals */ - if (! (aSig0 & LIT64(0x8000000000000000))) - { - float_raise(float_flag_inexact | float_flag_underflow); - return 0; - } - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); - } - - zSign = aSign; - zExp = EXP_BIAS; - expDiff = aExp - zExp; - - /* argument is out-of-range */ - if (expDiff >= 63) - return -1; - - float_raise(float_flag_inexact); - - if (expDiff < -1) { // doesn't require reduction - if (expDiff <= -68) { - *a = packFloatx80(aSign, aExp, aSig0); - return 0; - } - zExp = aExp; - } - else { - q = reduce_trig_arg(expDiff, &zSign, &aSig0, &aSig1); - } - - /* **************************** */ - /* argument reduction completed */ - /* **************************** */ - - /* using float128 for approximation */ - r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1); - - sin_r = poly_sin(r); - cos_r = poly_cos(r); - - if (q & 0x1) { - r = float128_div(cos_r, sin_r); - zSign = ! zSign; - } else { - r = float128_div(sin_r, cos_r); - } - - *a = float128_to_floatx80(r); - if (zSign) - floatx80_chs(a); - - return 0; -} - -/* ----- end from original file "fsincos.cc" ----- */ - -/* ----- from original file "fpatan.cc" ----- */ - -/* - ["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.] -*/ - -#define FPATAN_ARR_SIZE 11 - -#if 0 -static const float128 float128_one = - packFloat2x128m(LIT64(0x3fff000000000000), LIT64(0x0000000000000000)); -#endif -static const float128 float128_sqrt3 = - packFloat2x128m(LIT64(0x3fffbb67ae8584ca), LIT64(0xa73b25742d7078b8)); -static const floatx80 floatx80_pi = - packFloatx80m(0, 0x4000, LIT64(0xc90fdaa22168c235)); - -static const float128 float128_pi2 = - packFloat2x128m(LIT64(0x3fff921fb54442d1), LIT64(0x8469898CC5170416)); -static const float128 float128_pi4 = - packFloat2x128m(LIT64(0x3ffe921fb54442d1), LIT64(0x8469898CC5170416)); -static const float128 float128_pi6 = - packFloat2x128m(LIT64(0x3ffe0c152382d736), LIT64(0x58465BB32E0F580F)); - -static float128 atan_arr[FPATAN_ARR_SIZE] = -{ - PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ - PACK_FLOAT_128(0xbffd555555555555, 0x5555555555555555), /* 3 */ - PACK_FLOAT_128(0x3ffc999999999999, 0x999999999999999a), /* 5 */ - PACK_FLOAT_128(0xbffc249249249249, 0x2492492492492492), /* 7 */ - PACK_FLOAT_128(0x3ffbc71c71c71c71, 0xc71c71c71c71c71c), /* 9 */ - PACK_FLOAT_128(0xbffb745d1745d174, 0x5d1745d1745d1746), /* 11 */ - PACK_FLOAT_128(0x3ffb3b13b13b13b1, 0x3b13b13b13b13b14), /* 13 */ - PACK_FLOAT_128(0xbffb111111111111, 0x1111111111111111), /* 15 */ - PACK_FLOAT_128(0x3ffae1e1e1e1e1e1, 0xe1e1e1e1e1e1e1e2), /* 17 */ - PACK_FLOAT_128(0xbffaaf286bca1af2, 0x86bca1af286bca1b), /* 19 */ - PACK_FLOAT_128(0x3ffa861861861861, 0x8618618618618618) /* 21 */ -}; - -/* |x| < 1/4 */ -LOCALFUNC float128 poly_atan(float128 x1) -{ -/* - // 3 5 7 9 11 13 15 17 - // x x x x x x x x - // atan(x) ~ x - --- + --- - --- + --- - ---- + ---- - ---- + ---- - // 3 5 7 9 11 13 15 17 - // - // 2 4 6 8 10 12 14 16 - // x x x x x x x x - // = x * [ 1 - --- + --- - --- + --- - ---- + ---- - ---- + ---- ] - // 3 5 7 9 11 13 15 17 - // - // 5 5 - // -- 4k -- 4k+2 - // p(x) = > C * x q(x) = > C * x - // -- 2k -- 2k+1 - // k=0 k=0 - // - // 2 - // atan(x) ~ x * [ p(x) + x * q(x) ] - // -*/ - return OddPoly(x1, atan_arr, FPATAN_ARR_SIZE); -} - -// ================================================= -// FPATAN Compute y * log (x) -// 2 -// ================================================= - -// -// Uses the following identities: -// -// 1. ---------------------------------------------------------- -// -// atan(-x) = -atan(x) -// -// 2. ---------------------------------------------------------- -// -// x + y -// atan(x) + atan(y) = atan -------, xy < 1 -// 1-xy -// -// x + y -// atan(x) + atan(y) = atan ------- + PI, x > 0, xy > 1 -// 1-xy -// -// x + y -// atan(x) + atan(y) = atan ------- - PI, x < 0, xy > 1 -// 1-xy -// -// 3. ---------------------------------------------------------- -// -// atan(x) = atan(INF) + atan(- 1/x) -// -// x-1 -// atan(x) = PI/4 + atan( ----- ) -// x+1 -// -// x * sqrt(3) - 1 -// atan(x) = PI/6 + atan( ----------------- ) -// x + sqrt(3) -// -// 4. ---------------------------------------------------------- -// 3 5 7 9 2n+1 -// x x x x n x -// atan(x) = x - --- + --- - --- + --- - ... + (-1) ------ + ... -// 3 5 7 9 2n+1 -// - -LOCALFUNC floatx80 fpatan(floatx80 a, floatx80 b) -{ - float128 a128; - float128 b128; - float128 x; - int swap, add_pi6, add_pi4; - Bit32s xExp; - floatx80 result; - int rSign; - - // handle unsupported extended double-precision floating encodings -#if 0 - if (floatx80_is_unsupported(a)) { - float_raise(float_flag_invalid); - return floatx80_default_nan; - } -#endif - - Bit64u aSig = extractFloatx80Frac(a); - Bit32s aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - Bit64u bSig = extractFloatx80Frac(b); - Bit32s bExp = extractFloatx80Exp(b); - int bSign = extractFloatx80Sign(b); - - int zSign = aSign ^ bSign; - - if (bExp == 0x7FFF) - { - if ((Bit64u) (bSig<<1)) - return propagateFloatx80NaN(a, b); - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) - return propagateFloatx80NaN(a, b); - - if (aSign) { /* return 3PI/4 */ - return roundAndPackFloatx80(80, bSign, - FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO); - } - else { /* return PI/4 */ - return roundAndPackFloatx80(80, bSign, - FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO); - } - } - - if (aSig && (aExp == 0)) - float_raise(float_flag_denormal); - - /* return PI/2 */ - return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO); - } - if (aExp == 0x7FFF) - { - if ((Bit64u) (aSig<<1)) - return propagateFloatx80NaN(a, b); - - if (bSig && (bExp == 0)) - float_raise(float_flag_denormal); - -return_PI_or_ZERO: - - if (aSign) { /* return PI */ - return roundAndPackFloatx80(80, bSign, FLOATX80_PI_EXP, FLOAT_PI_HI, FLOAT_PI_LO); - } else { /* return 0 */ - return packFloatx80(bSign, 0, 0); - } - } - if (bExp == 0) - { - if (bSig == 0) { - if (aSig && (aExp == 0)) float_raise(float_flag_denormal); - goto return_PI_or_ZERO; - } - - float_raise(float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - if (aExp == 0) - { - if (aSig == 0) /* return PI/2 */ - return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO); - - float_raise(float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - - float_raise(float_flag_inexact); - - /* |a| = |b| ==> return PI/4 */ - if (aSig == bSig && aExp == bExp) - return roundAndPackFloatx80(80, bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO); - - /* ******************************** */ - /* using float128 for approximation */ - /* ******************************** */ - - a128 = normalizeRoundAndPackFloat128(0, aExp-0x10, aSig, 0); - b128 = normalizeRoundAndPackFloat128(0, bExp-0x10, bSig, 0); - swap = 0; - add_pi6 = 0; - add_pi4 = 0; - - if (aExp > bExp || (aExp == bExp && aSig > bSig)) - { - x = float128_div(b128, a128); - } - else { - x = float128_div(a128, b128); - swap = 1; - } - - xExp = extractFloat128Exp(x); - - if (xExp <= EXP_BIAS-40) - goto approximation_completed; - - if (x.high >= LIT64(0x3ffe800000000000)) // 3/4 < x < 1 - { - /* - arctan(x) = arctan((x-1)/(x+1)) + pi/4 - */ - float128 t1 = float128_sub(x, float128_one); - float128 t2 = float128_add(x, float128_one); - x = float128_div(t1, t2); - add_pi4 = 1; - } - else - { - /* argument correction */ - if (xExp >= 0x3FFD) // 1/4 < x < 3/4 - { - /* - arctan(x) = arctan((x*sqrt(3)-1)/(x+sqrt(3))) + pi/6 - */ - float128 t1 = float128_mul(x, float128_sqrt3); - float128 t2 = float128_add(x, float128_sqrt3); - x = float128_sub(t1, float128_one); - x = float128_div(x, t2); - add_pi6 = 1; - } - } - - x = poly_atan(x); - if (add_pi6) x = float128_add(x, float128_pi6); - if (add_pi4) x = float128_add(x, float128_pi4); - -approximation_completed: - if (swap) x = float128_sub(float128_pi2, x); - result = float128_to_floatx80(x); - if (zSign) floatx80_chs(&result); - rSign = extractFloatx80Sign(result); - if (!bSign && rSign) - return floatx80_add(result, floatx80_pi); - if (bSign && !rSign) - return floatx80_sub(result, floatx80_pi); - return result; -} - -/* ----- end from original file "fpatan.cc" ----- */ - -/* end soft float stuff */ - -typedef floatx80 myfpr; - -LOCALPROC myfp_FromExtendedFormat(myfpr *r, ui4r v2, ui5r v1, ui5r v0) -{ - r->high = v2; - r->low = (((ui6b)v1) << 32) | (v0 & 0xFFFFFFFF); -} - -LOCALPROC myfp_ToExtendedFormat(myfpr *dd, ui4r *v2, ui5r *v1, ui5r *v0) -{ - *v0 = ((ui6b) dd->low) & 0xFFFFFFFF; - *v1 = (((ui6b) dd->low) >> 32) & 0xFFFFFFFF; - *v2 = dd->high; -} - -LOCALPROC myfp_FromDoubleFormat(myfpr *r, ui5r v1, ui5r v0) -{ - float64 t = (float64)((((ui6b)v1) << 32) | (v0 & 0xFFFFFFFF)); - - *r = float64_to_floatx80(t); -} - -LOCALPROC myfp_ToDoubleFormat(myfpr *dd, ui5r *v1, ui5r *v0) -{ - float64 t = floatx80_to_float64(*dd); - - *v0 = ((ui6b) t) & 0xFFFFFFFF; - *v1 = (((ui6b) t) >> 32) & 0xFFFFFFFF; -} - -LOCALPROC myfp_FromSingleFormat(myfpr *r, ui5r x) -{ - *r = float32_to_floatx80(x); -} - -LOCALFUNC ui5r myfp_ToSingleFormat(myfpr *ff) -{ - return floatx80_to_float32(*ff); -} - -LOCALPROC myfp_FromLong(myfpr *r, ui5r x) -{ - *r = int32_to_floatx80( x ); -} - -LOCALFUNC ui5r myfp_ToLong(myfpr *x) -{ - return floatx80_to_int32( *x ); -} - -LOCALFUNC blnr myfp_IsNan(myfpr *x) -{ - return floatx80_is_nan(*x); -} - -LOCALFUNC blnr myfp_IsInf(myfpr *x) -{ - return ( ( x->high & 0x7FFF ) == 0x7FFF ) && (0 == ((ui6b) ( x->low<<1 ))); -} - -LOCALFUNC blnr myfp_IsZero(myfpr *x) -{ - return ( ( x->high & 0x7FFF ) == 0x0000 ) && (0 == ((ui6b) ( x->low<<1 ))); -} - -LOCALFUNC blnr myfp_IsNeg(myfpr *x) -{ - return ( ( x->high & 0x8000 ) != 0x0000 ); -} - -LOCALPROC myfp_Add(myfpr *r, const myfpr *a, const myfpr *b) -{ - *r = floatx80_add(*a, *b); -} - -LOCALPROC myfp_Sub(myfpr *r, const myfpr *a, const myfpr *b) -{ - *r = floatx80_sub(*a, *b); -} - -LOCALPROC myfp_Mul(myfpr *r, const myfpr *a, const myfpr *b) -{ - *r = floatx80_mul(*a, *b); -} - -LOCALPROC myfp_Div(myfpr *r, const myfpr *a, const myfpr *b) -{ - *r = floatx80_div(*a, *b); -} - -LOCALPROC myfp_Rem(myfpr *r, const myfpr *a, const myfpr *b) -{ - *r = floatx80_rem(*a, *b); -} - -LOCALPROC myfp_Sqrt(myfpr *r, myfpr *x) -{ - *r = floatx80_sqrt(*x); -} - -LOCALPROC myfp_Mod(myfpr *r, myfpr *a, myfpr *b) -{ - Bit64u q; - *r = floatx80_remainder(*a, *b, &q); - /* should save low byte of q */ -} - -LOCALPROC myfp_Scale(myfpr *r, myfpr *a, myfpr *b) -{ - *r = floatx80_scale(*a, *b); -} - -LOCALPROC myfp_GetMan(myfpr *r, myfpr *x) -{ - *r = *x; - (void) floatx80_extract(r); -} - -LOCALPROC myfp_GetExp(myfpr *r, myfpr *x) -{ - floatx80 t0 = *x; - *r = floatx80_extract(&t0); -} - -LOCALPROC myfp_floor(myfpr *r, myfpr *x) -{ - si3r SaveRoundingMode = float_rounding_mode; - - float_rounding_mode = float_round_down; - *r = floatx80_round_to_int(*x); - float_rounding_mode = SaveRoundingMode; -} - -LOCALPROC myfp_IntRZ(myfpr *r, myfpr *x) -{ - si3r SaveRoundingMode = float_rounding_mode; - - float_rounding_mode = float_round_to_zero; - *r = floatx80_round_to_int(*x); - float_rounding_mode = SaveRoundingMode; -} - -LOCALPROC myfp_Int(myfpr *r, myfpr *x) -{ - *r = floatx80_round_to_int(*x); -} - -LOCALPROC myfp_RoundToSingle(myfpr *r, myfpr *x) -{ - float32 t0 = floatx80_to_float32(*x); - - *r = float32_to_floatx80(t0); -} - -LOCALPROC myfp_RoundToDouble(myfpr *r, myfpr *x) -{ - float64 t0 = floatx80_to_float64(*x); - - *r = float64_to_floatx80(t0); -} - -LOCALPROC myfp_Abs(myfpr *r, myfpr *x) -{ - *r = *x; - r->high &= 0x7FFF; -} - -LOCALPROC myfp_Neg(myfpr *r, myfpr *x) -{ - *r = *x; - r->high ^= 0x8000; -} - -LOCALPROC myfp_TwoToX(myfpr *r, myfpr *x) -{ - floatx80 t2; - floatx80 t3; - floatx80 t4; - floatx80 t5; - myfp_floor(&t2, x); - t3 = floatx80_sub(*x, t2); - t4 = f2xm1(t3); - t5 = floatx80_add(t4, floatx80_one); - *r = floatx80_scale(t5, t2); -} - -LOCALPROC myfp_TenToX(myfpr *r, myfpr *x) -{ - floatx80 t1; - const floatx80 t = /* 1.0 / log(2.0) */ - packFloatx80m(0, 0x3fff, LIT64(0xb8aa3b295c17f0bc)); - const floatx80 t2 = /* log(10.0) */ - packFloatx80m(0, 0x4000, LIT64(0x935d8dddaaa8ac17)); - t1 = floatx80_mul(floatx80_mul(*x, t), t2); - myfp_TwoToX(r, &t1); -} - -LOCALPROC myfp_EToX(myfpr *r, myfpr *x) -{ - floatx80 t1; - const floatx80 t = /* 1.0 / log(2.0) */ - packFloatx80m(0, 0x3fff, LIT64(0xb8aa3b295c17f0bc)); - t1 = floatx80_mul(*x, t); - myfp_TwoToX(r, &t1); -} - -LOCALPROC myfp_EToXM1(myfpr *r, myfpr *x) -{ - floatx80 t1; - floatx80 t2; - floatx80 t3; - floatx80 t4; - floatx80 t5; - floatx80 t6; - const floatx80 t = /* 1.0 / log(2.0) */ - packFloatx80m(0, 0x3fff, LIT64(0xb8aa3b295c17f0bc)); - t1 = floatx80_mul(*x, t); - myfp_floor(&t2, &t1); - t3 = floatx80_sub(t1, t2); - t4 = f2xm1(t3); - if (myfp_IsZero(&t2)) { - *r = t4; - } else { - t5 = floatx80_add(t4, floatx80_one); - t6 = floatx80_scale(t5, t2); - *r = floatx80_sub(t6, floatx80_one); - } -} - -LOCALPROC myfp_Log2(myfpr *r, myfpr *x) -{ - *r = fyl2x(*x, floatx80_one); -} - -LOCALPROC myfp_LogN(myfpr *r, myfpr *x) -{ - const floatx80 t = /* log(2.0) */ - packFloatx80m(0, 0x3ffe, LIT64(0xb17217f7d1cf79ac)); - *r = fyl2x(*x, t); -} - -LOCALPROC myfp_Log10(myfpr *r, myfpr *x) -{ - const floatx80 t = /* log10(2.0) = ln(2) / ln(10), unknown accuracy */ - packFloatx80m(0, 0x3ffd, LIT64(0x9a209a84fbcff798)); - *r = fyl2x(*x, t); -} - -LOCALPROC myfp_LogNP1(myfpr *r, myfpr *x) -{ - const floatx80 t = /* log(2.0) */ - packFloatx80m(0, 0x3ffe, LIT64(0xb17217f7d1cf79ac)); - *r = fyl2xp1(*x, t); -} - -LOCALPROC myfp_Sin(myfpr *r, myfpr *x) -{ - (void) fsincos(*x, r, 0); -} - -LOCALPROC myfp_Cos(myfpr *r, myfpr *x) -{ - (void) fsincos(*x, 0, r); -} - -LOCALPROC myfp_Tan(myfpr *r, myfpr *x) -{ - *r = *x; - (void) ftan(r); -} - -LOCALPROC myfp_ATan(myfpr *r, myfpr *x) -{ - *r = fpatan(floatx80_one, *x); -} - -LOCALPROC myfp_ASin(myfpr *r, myfpr *x) -{ - floatx80 x2 = floatx80_mul(*x, *x); - floatx80 mx2 = floatx80_sub(floatx80_one, x2); - floatx80 cx = floatx80_sqrt(mx2); - - *r = fpatan(cx, *x); -} - -LOCALPROC myfp_ACos(myfpr *r, myfpr *x) -{ - floatx80 x2 = floatx80_mul(*x, *x); - floatx80 mx2 = floatx80_sub(floatx80_one, x2); - floatx80 cx = floatx80_sqrt(mx2); - - *r = fpatan(*x, cx); -} - -static const floatx80 floatx80_zero = - packFloatx80m(0, 0x0000, LIT64(0x0000000000000000)); - -static const floatx80 floatx80_Two = - packFloatx80m(0, 0x4000, LIT64(0x8000000000000000)); - -static const floatx80 floatx80_Ten = - packFloatx80m(0, 0x4002, LIT64(0xa000000000000000)); - -LOCALPROC myfp_Sinh(myfpr *r, myfpr *x) -{ - myfpr ex; - myfpr nx; - myfpr enx; - myfpr t1; - - myfp_EToX(&ex, x); - myfp_Neg(&nx, x); - myfp_EToX(&enx, &nx); - myfp_Sub(&t1, &ex, &enx); - myfp_Div(r, &t1, &floatx80_Two); -} - -LOCALPROC myfp_Cosh(myfpr *r, myfpr *x) -{ - myfpr ex; - myfpr nx; - myfpr enx; - myfpr t1; - - myfp_EToX(&ex, x); - myfp_Neg(&nx, x); - myfp_EToX(&enx, &nx); - myfp_Add(&t1, &ex, &enx); - myfp_Div(r, &t1, &floatx80_Two); -} - -LOCALPROC myfp_Tanh(myfpr *r, myfpr *x) -{ - myfpr x2; - myfpr ex2; - myfpr ex2m1; - myfpr ex2p1; - - myfp_Mul(&x2, x, &floatx80_Two); - myfp_EToX(&ex2, &x2); - myfp_Sub(&ex2m1, &ex2, &floatx80_one); - myfp_Add(&ex2p1, &ex2, &floatx80_one); - myfp_Div(r, &ex2m1, &ex2p1); -} - -LOCALPROC myfp_ATanh(myfpr *r, myfpr *x) -{ - myfpr onepx; - myfpr onemx; - myfpr dv; - myfpr ldv; - - myfp_Add(&onepx, x, &floatx80_one); - myfp_Sub(&onemx, x, &floatx80_one); - myfp_Div(&dv, &onepx, &onemx); - myfp_LogN(&ldv, &dv); - myfp_Div(r, &ldv, &floatx80_Two); -} - -LOCALPROC myfp_SinCos(myfpr *r_sin, myfpr *r_cos, myfpr *source) -{ - (void) fsincos(*source, r_sin, r_cos); -} - -LOCALFUNC blnr myfp_getCR(myfpr *r, ui4b opmode) -{ - switch (opmode) { - case 0x00: - *r = floatx80_pi; /* M_PI */ - break; - case 0x0B: - { - const floatx80 t = - packFloatx80m(0, 0x3ffd, LIT64(0x9a209a84fbcff798)); - *r = t; /* log10(2.0) = ln(2) / ln(10), unknown accuracy */ - } - break; - case 0x0C: - { - const floatx80 t = - packFloatx80m(0, 0x4000, LIT64(0xadf85458a2bb4a9b)); - *r = t; /* exp(1.0), unknown accuracy */ - } - break; - case 0x0D: - { - const floatx80 t = - packFloatx80m(0, 0x3fff, LIT64(0xb8aa3b295c17f0bc)); - *r = t; /* 1.0 / log(2.0) */ - } - break; - case 0x0E: - { - const floatx80 t = - packFloatx80m(0, 0x3ffd, LIT64(0xde5bd8a937287195)); - *r = t; /* 1.0 / log(10.0), unknown accuracy */ - } - break; - case 0x0F: - *r = floatx80_zero; /* 0.0 */ - break; - case 0x30: - { - const floatx80 t = - packFloatx80m(0, 0x3ffe, LIT64(0xb17217f7d1cf79ac)); - *r = t; /* log(2.0) */ - } - break; - case 0x31: - { - const floatx80 t = - packFloatx80m(0, 0x4000, LIT64(0x935d8dddaaa8ac17)); - *r = t; /* log(10.0) */ - } - break; - case 0x32: - *r = floatx80_one; /* 1.0 */ - break; - case 0x33: - *r = floatx80_Ten; /* 10.0 */ - break; - case 0x34: - { - const floatx80 t = - packFloatx80m(0, 0x4005, LIT64(0xc800000000000000)); - *r = t; /* 100.0 */ - } - break; - case 0x35: - { - const floatx80 t = - packFloatx80m(0, 0x400c, LIT64(0x9c40000000000000)); - *r = t; /* 10000.0 */ - } - break; - case 0x36: - { - const floatx80 t = - packFloatx80m(0, 0x4019, LIT64(0xbebc200000000000)); - *r = t; /* 1.0e8 */ - } - break; - case 0x37: - { - const floatx80 t = - packFloatx80m(0, 0x4034, LIT64(0x8e1bc9bf04000000)); - *r = t; /* 1.0e16 */ - } - break; - case 0x38: - { - const floatx80 t = - packFloatx80m(0, 0x4069, LIT64(0x9dc5ada82b70b59e)); - *r = t; /* 1.0e32 */ - } - break; - case 0x39: - { - const floatx80 t = - packFloatx80m(0, 0x40d3, LIT64(0xc2781f49ffcfa6d5)); - *r = t; /* 1.0e64 */ - } - break; - case 0x3A: - { - const floatx80 t = - packFloatx80m(0, 0x41a8, LIT64(0x93ba47c980e98ce0)); - *r = t; /* 1.0e128 */ - } - break; - case 0x3B: - { - const floatx80 t = - packFloatx80m(0, 0x4351, LIT64(0xaa7eebfb9df9de8e)); - *r = t; /* 1.0e256 */ - } - break; - case 0x3C: - { - const floatx80 t = - packFloatx80m(0, 0x46a3, LIT64(0xe319a0aea60e91c7)); - *r = t; /* 1.0e512 */ - } - break; - case 0x3D: - { - const floatx80 t = - packFloatx80m(0, 0x4d48, LIT64(0xc976758681750c17)); - *r = t; /* 1.0e1024 */ - } - break; - case 0x3E: - { - const floatx80 t = - packFloatx80m(0, 0x5a92, LIT64(0x9e8b3b5dc53d5de5)); - *r = t; /* 1.0e2048 */ - } - break; - case 0x3F: - { - const floatx80 t = - packFloatx80m(0, 0x7525, LIT64(0xc46052028a20979b)); - *r = t; /* 1.0e4096 */ - } - break; - default: - return falseblnr; - } - return trueblnr; -} - -/* Floating point control register */ - -LOCALPROC myfp_SetFPCR(ui5r v) -{ - switch ((v >> 4) & 0x03) { - case 0: - float_rounding_mode = float_round_nearest_even; - break; - case 1: - float_rounding_mode = float_round_to_zero; - break; - case 2: - float_rounding_mode = float_round_down; - break; - case 3: - float_rounding_mode = float_round_up; - break; - } - switch ((v >> 6) & 0x03) { - case 0: - floatx80_rounding_precision = 80; - break; - case 1: - floatx80_rounding_precision = 32; - break; - case 2: - floatx80_rounding_precision = 64; - break; - case 3: - ReportAbnormal("Bad rounding precision in myfp_SetFPCR"); - floatx80_rounding_precision = 80; - break; - } - if (0 != (v & 0xF)) { - ReportAbnormal("Reserved bits not zero in myfp_SetFPCR"); - } -} - -LOCALFUNC ui5r myfp_GetFPCR(void) -{ - ui5r v = 0; - - switch (float_rounding_mode) { - case float_round_nearest_even: - /* v |= (0 << 4); */ - break; - case float_round_to_zero: - v |= (1 << 4); - break; - case float_round_down: - v |= (2 << 4); - break; - case float_round_up: - v |= (3 << 4); - break; - } - - if (80 == floatx80_rounding_precision) { - /* v |= (0 << 6); */ - } else if (32 == floatx80_rounding_precision) { - v |= (1 << 6); - } else if (64 == floatx80_rounding_precision) { - v |= (2 << 6); - } else { - ReportAbnormal("Bad rounding precision in myfp_GetFPCR"); - } - - return v; -} - -LOCALVAR struct myfp_envStruct -{ - ui5r FPSR; /* Floating point status register */ -} myfp_env; - -LOCALPROC myfp_SetFPSR(ui5r v) -{ - myfp_env.FPSR = v; -} - -LOCALFUNC ui5r myfp_GetFPSR(void) -{ - return myfp_env.FPSR; -} - -LOCALFUNC ui3r myfp_GetConditionCodeByte(void) -{ - return (myfp_env.FPSR >> 24) & 0x0F; -} - -LOCALPROC myfp_SetConditionCodeByte(ui3r v) -{ - myfp_env.FPSR = ((myfp_env.FPSR & 0x00FFFFFF) - | (v << 24)); -} - -LOCALPROC myfp_SetConditionCodeByteFromResult(myfpr *result) -{ - /* Set condition codes here based on result */ - - int c_nan = myfp_IsNan(result) ? 1 : 0; - int c_inf = myfp_IsInf(result) ? 1 : 0; - int c_zero = myfp_IsZero(result) ? 1 : 0; - int c_neg = myfp_IsNeg(result) ? 1 : 0; - - myfp_SetConditionCodeByte(c_nan - | (c_inf << 1) - | (c_zero << 2) - | (c_neg << 3)); -} +/* FPMATHEM.h Copyright (C) 2007 John R. Hauser, Stanislav Shwartsman, Ross Martin, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* Floating Point MATH implemented with software EMulation Based on the SoftFloat IEC/IEEE Floating-point Arithmetic Package, Release 2b, written by John R. Hauser. Also uses extensions to SoftFloat, written for Bochs (x86 achitecture simulator), by Stanislav Shwartsman. */ /* original SoftFloat Copyright notice: Written by John R. Hauser. This work was made possible in part by the International Computer Science Institute, located at Suite 600, 1947 Center Street, Berkeley, California 94704. Funding was partially provided by the National Science Foundation under grant MIP-9311980. The original version of this code was written as part of a project to build a fixed-point vector processor in collaboration with the University of California at Berkeley, overseen by Profs. Nelson Morgan and John Wawrzynek. More information is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ arithmetic/SoftFloat.html'. THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. Derivative works are acceptable, even for commercial purposes, so long as (1) the source code for the derivative work includes prominent notice that the work is derivative, and (2) the source code includes prominent notice with these four paragraphs for those parts of this code that are retained. */ /* original Stanislav Shwartsman Copyright notice: This source file is an extension to the SoftFloat IEC/IEEE Floating-point Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) floating point emulation. THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. Derivative works are acceptable, even for commercial purposes, so long as (1) the source code for the derivative work includes prominent notice that the work is derivative, and (2) the source code includes prominent notice with these four paragraphs for those parts of this code that are retained. .*============================================================================ * Written for Bochs (x86 achitecture simulator) by * Stanislav Shwartsman [sshwarts at sourceforge net] * ==========================================================================*. */ /* ReportAbnormalID unused 0x0204 - 0x02FF */ /* soft float stuff */ /* should avoid 64 bit literals. */ typedef ui3r flag; /* 0/1 */ /* To fix: softfloat representation of denormalized extended precision numbers is different than on 68881. */ #define cIncludeFPUUnused cIncludeUnused /* ----- from original file "softfloat.h" ----- */ /*====================================================================== This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic Package, Release 2b. ["original SoftFloat Copyright notice" went here, included near top of this file.] ======================================================================*/ /*---------------------------------------------------------------------------- | The macro `FLOATX80' must be defined to enable the extended double-precision | floating-point format `floatx80'. If this macro is not defined, the | `floatx80' type will not be defined, and none of the functions that either | input or output the `floatx80' type will be defined. The same applies to | the `FLOAT128' macro and the quadruple-precision format `float128'. *----------------------------------------------------------------------------*/ #define FLOATX80 #define FLOAT128 /*---------------------------------------------------------------------------- | Software IEC/IEEE floating-point types. *----------------------------------------------------------------------------*/ typedef struct { ui6b low; unsigned short high; } floatx80; #ifdef FLOAT128 typedef struct { ui6b low, high; } float128; #endif /* ----- end from original file "softfloat.h" ----- */ /*---------------------------------------------------------------------------- | Software IEC/IEEE floating-point rounding mode. *----------------------------------------------------------------------------*/ enum { float_round_nearest_even = 0, float_round_down = 1, float_round_up = 2, float_round_to_zero = 3 }; /*---------------------------------------------------------------------------- | Floating-point rounding mode, extended double-precision rounding precision, | and exception flags. *----------------------------------------------------------------------------*/ LOCALVAR si3r float_rounding_mode = float_round_nearest_even; /*---------------------------------------------------------------------------- | Software IEC/IEEE floating-point exception flags. *----------------------------------------------------------------------------*/ enum { float_flag_invalid = 1, float_flag_divbyzero = 4, float_flag_overflow = 8, float_flag_underflow = 16, float_flag_inexact = 32 }; LOCALVAR si3r float_exception_flags = 0; /*---------------------------------------------------------------------------- | Software IEC/IEEE extended double-precision rounding precision. Valid | values are 32, 64, and 80. *----------------------------------------------------------------------------*/ LOCALVAR si3r floatx80_rounding_precision = 80; /*---------------------------------------------------------------------------- | Primitive arithmetic functions, including multi-word arithmetic, and | division and square root approximations. (Can be specialized to target if | desired.) *----------------------------------------------------------------------------*/ /* ----- from original file "softfloat-macros" ----- */ /*============================================================================ This C source fragment is part of the SoftFloat IEC/IEEE Floating-point Arithmetic Package, Release 2b. ["original SoftFloat Copyright notice" went here, included near top of this file.] =============================================================================*/ /*---------------------------------------------------------------------------- | Shifts `a' right by the number of bits given in `count'. If any nonzero | bits are shifted off, they are ``jammed'' into the least significant bit of | the result by setting the least significant bit to 1. The value of `count' | can be arbitrarily large; in particular, if `count' is greater than 32, the | result will be either 0 or 1, depending on whether `a' is zero or nonzero. | The result is stored in the location pointed to by `zPtr'. *----------------------------------------------------------------------------*/ LOCALINLINEPROC shift32RightJamming( ui5b a, si4r count, ui5b *zPtr ) { ui5b z; if ( count == 0 ) { z = a; } else if ( count < 32 ) { z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 ); } else { z = ( a != 0 ); } *zPtr = z; } /*---------------------------------------------------------------------------- | Shifts `a' right by the number of bits given in `count'. If any nonzero | bits are shifted off, they are ``jammed'' into the least significant bit of | the result by setting the least significant bit to 1. The value of `count' | can be arbitrarily large; in particular, if `count' is greater than 64, the | result will be either 0 or 1, depending on whether `a' is zero or nonzero. | The result is stored in the location pointed to by `zPtr'. *----------------------------------------------------------------------------*/ LOCALINLINEPROC shift64RightJamming( ui6b a, si4r count, ui6b *zPtr ) { ui6b z; if ( count == 0 ) { z = a; } else if ( count < 64 ) { z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 ); } else { z = ( a != 0 ); } *zPtr = z; } /*---------------------------------------------------------------------------- | Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64 | _plus_ the number of bits given in `count'. The shifted result is at most | 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The | bits shifted off form a second 64-bit result as follows: The _last_ bit | shifted off is the most-significant bit of the extra result, and the other | 63 bits of the extra result are all zero if and only if _all_but_the_last_ | bits shifted off were all zero. This extra result is stored in the location | pointed to by `z1Ptr'. The value of `count' can be arbitrarily large. | (This routine makes more sense if `a0' and `a1' are considered to form | a fixed-point value with binary point between `a0' and `a1'. This fixed- | point value is shifted right by the number of bits given in `count', and | the integer part of the result is returned at the location pointed to by | `z0Ptr'. The fractional part of the result may be slightly corrupted as | described above, and is returned at the location pointed to by `z1Ptr'.) *----------------------------------------------------------------------------*/ LOCALINLINEPROC shift64ExtraRightJamming( ui6b a0, ui6b a1, si4r count, ui6b *z0Ptr, ui6b *z1Ptr ) { ui6b z0, z1; si3r negCount = ( - count ) & 63; if ( count == 0 ) { z1 = a1; z0 = a0; } else if ( count < 64 ) { z1 = ( a0<>count; } else { if ( count == 64 ) { z1 = a0 | ( a1 != 0 ); } else { z1 = ( ( a0 | a1 ) != 0 ); } z0 = 0; } *z1Ptr = z1; *z0Ptr = z0; } /*---------------------------------------------------------------------------- | Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the | number of bits given in `count'. Any bits shifted off are lost. The value | of `count' can be arbitrarily large; in particular, if `count' is greater | than 128, the result will be 0. The result is broken into two 64-bit pieces | which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. *----------------------------------------------------------------------------*/ LOCALINLINEPROC shift128Right( ui6b a0, ui6b a1, si4r count, ui6b *z0Ptr, ui6b *z1Ptr ) { ui6b z0, z1; si3r negCount = ( - count ) & 63; if ( count == 0 ) { z1 = a1; z0 = a0; } else if ( count < 64 ) { z1 = ( a0<>count ); z0 = a0>>count; } else { z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0; z0 = 0; } *z1Ptr = z1; *z0Ptr = z0; } /*---------------------------------------------------------------------------- | Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the | number of bits given in `count'. If any nonzero bits are shifted off, they | are ``jammed'' into the least significant bit of the result by setting the | least significant bit to 1. The value of `count' can be arbitrarily large; | in particular, if `count' is greater than 128, the result will be either | 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or | nonzero. The result is broken into two 64-bit pieces which are stored at | the locations pointed to by `z0Ptr' and `z1Ptr'. *----------------------------------------------------------------------------*/ LOCALINLINEPROC shift128RightJamming( ui6b a0, ui6b a1, si4r count, ui6b *z0Ptr, ui6b *z1Ptr ) { ui6b z0, z1; si3r negCount = ( - count ) & 63; if ( count == 0 ) { z1 = a1; z0 = a0; } else if ( count < 64 ) { z1 = ( a0<>count ) | ( ( a1<>count; } else { if ( count == 64 ) { z1 = a0 | ( a1 != 0 ); } else if ( count < 128 ) { z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<>count ); z0 = a0>>count; } else { if ( count == 64 ) { z2 = a1; z1 = a0; } else { a2 |= a1; if ( count < 128 ) { z2 = a0<>( count & 63 ); } else { z2 = ( count == 128 ) ? a0 : ( a0 != 0 ); z1 = 0; } } z0 = 0; } z2 |= ( a2 != 0 ); } *z2Ptr = z2; *z1Ptr = z1; *z0Ptr = z0; } /*---------------------------------------------------------------------------- | Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the | number of bits given in `count'. Any bits shifted off are lost. The value | of `count' must be less than 64. The result is broken into two 64-bit | pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. *----------------------------------------------------------------------------*/ LOCALINLINEPROC shortShift128Left( ui6b a0, ui6b a1, si4r count, ui6b *z0Ptr, ui6b *z1Ptr ) { *z1Ptr = a1<>( ( - count ) & 63 ) ); } /*---------------------------------------------------------------------------- | Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit | value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so | any carry out is lost. The result is broken into two 64-bit pieces which | are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. *----------------------------------------------------------------------------*/ LOCALINLINEPROC add128( ui6b a0, ui6b a1, ui6b b0, ui6b b1, ui6b *z0Ptr, ui6b *z1Ptr ) { ui6b z1; z1 = a1 + b1; *z1Ptr = z1; *z0Ptr = a0 + b0 + ( z1 < a1 ); } /*---------------------------------------------------------------------------- | Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the | 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is | modulo 2^192, so any carry out is lost. The result is broken into three | 64-bit pieces which are stored at the locations pointed to by `z0Ptr', | `z1Ptr', and `z2Ptr'. *----------------------------------------------------------------------------*/ LOCALINLINEPROC add192( ui6b a0, ui6b a1, ui6b a2, ui6b b0, ui6b b1, ui6b b2, ui6b *z0Ptr, ui6b *z1Ptr, ui6b *z2Ptr) { ui6b z0, z1, z2; si3r carry0, carry1; z2 = a2 + b2; carry1 = ( z2 < a2 ); z1 = a1 + b1; carry0 = ( z1 < a1 ); z0 = a0 + b0; z1 += carry1; z0 += ( z1 < carry1 ); z0 += carry0; *z2Ptr = z2; *z1Ptr = z1; *z0Ptr = z0; } /*---------------------------------------------------------------------------- | Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the | 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo | 2^128, so any borrow out (carry out) is lost. The result is broken into two | 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and | `z1Ptr'. *----------------------------------------------------------------------------*/ LOCALINLINEPROC sub128( ui6b a0, ui6b a1, ui6b b0, ui6b b1, ui6b *z0Ptr, ui6b *z1Ptr ) { *z1Ptr = a1 - b1; *z0Ptr = a0 - b0 - ( a1 < b1 ); } /*---------------------------------------------------------------------------- | Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2' | from the 192-bit value formed by concatenating `a0', `a1', and `a2'. | Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The | result is broken into three 64-bit pieces which are stored at the locations | pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'. *----------------------------------------------------------------------------*/ LOCALINLINEPROC sub192( ui6b a0, ui6b a1, ui6b a2, ui6b b0, ui6b b1, ui6b b2, ui6b *z0Ptr, ui6b *z1Ptr, ui6b *z2Ptr ) { ui6b z0, z1, z2; si3r borrow0, borrow1; z2 = a2 - b2; borrow1 = ( a2 < b2 ); z1 = a1 - b1; borrow0 = ( a1 < b1 ); z0 = a0 - b0; z0 -= ( z1 < borrow1 ); z1 -= borrow1; z0 -= borrow0; *z2Ptr = z2; *z1Ptr = z1; *z0Ptr = z0; } /*---------------------------------------------------------------------------- | Multiplies `a' by `b' to obtain a 128-bit product. The product is broken | into two 64-bit pieces which are stored at the locations pointed to by | `z0Ptr' and `z1Ptr'. *----------------------------------------------------------------------------*/ #ifndef HaveUi5to6Mul #define HaveUi5to6Mul 1 #endif #if HaveUi5to6Mul LOCALINLINEPROC Ui5to6Mul( ui5b src1, ui5b src2, ui6b *z) { *z = ((ui6b) src1) * src2; } #else LOCALINLINEPROC Ui6fromHiLo(ui5b hi, ui5b lo, ui6b *z) { *z = (((ui6b)(hi)) << 32) + lo; #if 0 z->lo = hi; z->hi = lo; #endif } LOCALPROC Ui5to6Mul( ui5b src1, ui5b src2, ui6b *z) { ui4b src1_lo = ui5b_lo(src1); ui4b src2_lo = ui5b_lo(src2); ui4b src1_hi = ui5b_hi(src1); ui4b src2_hi = ui5b_hi(src2); ui5b r0 = ( (ui6b) src1_lo ) * src2_lo; ui5b r1 = ( (ui6b) src1_hi ) * src2_lo; ui5b r2 = ( (ui6b) src1_lo ) * src2_hi; ui5b r3 = ( (ui6b) src1_hi ) * src2_hi; ui5b ra1 = ui5b_hi(r0) + ui5b_lo(r1) + ui5b_lo(r2); ui5b lo = (ui5b_lo(ra1) << 16) | ui5b_lo(r0); ui5b hi = ui5b_hi(ra1) + ui5b_hi(r1) + ui5b_hi(r2) + r3; Ui6fromHiLo(hi, lo, z); } #endif LOCALINLINEPROC mul64To128( ui6b a, ui6b b, ui6b *z0Ptr, ui6b *z1Ptr ) { ui5b aHigh, aLow, bHigh, bLow; ui6b z0, zMiddleA, zMiddleB, z1; aLow = a; aHigh = a>>32; bLow = b; bHigh = b>>32; Ui5to6Mul(aLow, bLow, &z1); Ui5to6Mul(aLow, bHigh, &zMiddleA); Ui5to6Mul(aHigh, bLow, &zMiddleB); Ui5to6Mul(aHigh, bHigh, &z0); zMiddleA += zMiddleB; z0 += ( ( (ui6b) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 ); zMiddleA <<= 32; z1 += zMiddleA; z0 += ( z1 < zMiddleA ); *z1Ptr = z1; *z0Ptr = z0; } /*---------------------------------------------------------------------------- | Multiplies the 128-bit value formed by concatenating `a0' and `a1' by | `b' to obtain a 192-bit product. The product is broken into three 64-bit | pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and | `z2Ptr'. *----------------------------------------------------------------------------*/ LOCALINLINEPROC mul128By64To192( ui6b a0, ui6b a1, ui6b b, ui6b *z0Ptr, ui6b *z1Ptr, ui6b *z2Ptr ) { ui6b z0, z1, z2, more1; mul64To128( a1, b, &z1, &z2 ); mul64To128( a0, b, &z0, &more1 ); add128( z0, more1, 0, z1, &z0, &z1 ); *z2Ptr = z2; *z1Ptr = z1; *z0Ptr = z0; } /*---------------------------------------------------------------------------- | Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the | 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit | product. The product is broken into four 64-bit pieces which are stored at | the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'. *----------------------------------------------------------------------------*/ LOCALINLINEPROC mul128To256( ui6b a0, ui6b a1, ui6b b0, ui6b b1, ui6b *z0Ptr, ui6b *z1Ptr, ui6b *z2Ptr, ui6b *z3Ptr ) { ui6b z0, z1, z2, z3; ui6b more1, more2; mul64To128( a1, b1, &z2, &z3 ); mul64To128( a1, b0, &z1, &more2 ); add128( z1, more2, 0, z2, &z1, &z2 ); mul64To128( a0, b0, &z0, &more1 ); add128( z0, more1, 0, z1, &z0, &z1 ); mul64To128( a0, b1, &more1, &more2 ); add128( more1, more2, 0, z2, &more1, &z2 ); add128( z0, z1, 0, more1, &z0, &z1 ); *z3Ptr = z3; *z2Ptr = z2; *z1Ptr = z1; *z0Ptr = z0; } /*---------------------------------------------------------------------------- | Returns an approximation to the 64-bit integer quotient obtained by dividing | `b' into the 128-bit value formed by concatenating `a0' and `a1'. The | divisor `b' must be at least 2^63. If q is the exact quotient truncated | toward zero, the approximation returned lies between q and q + 2 inclusive. | If the exact quotient q is larger than 64 bits, the maximum positive 64-bit | unsigned integer is returned. *----------------------------------------------------------------------------*/ #ifndef HaveUi6Div #define HaveUi6Div 0 #endif #if HaveUi6Div #define Ui6Div(x, y) ((x) / (y)) #else /* Assuming other 64 bit operations available, like compare, subtract, shift. */ LOCALFUNC ui6b Ui6Div(ui6b num, ui6b den) { ui6b bit = 1; ui6b res = 0; while ((den < num) && bit && ! (den & (LIT64(1) << 63))) { den <<= 1; bit <<= 1; } while (bit) { if (num >= den) { num -= den; res |= bit; } bit >>= 1; den >>= 1; } return res; } #endif LOCALFUNC ui6b estimateDiv128To64( ui6b a0, ui6b a1, ui6b b ) { ui6b b0, b1; ui6b rem0, rem1, term0, term1; ui6b z; if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF ); b0 = b>>32; z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : Ui6Div(a0, b0) << 32; mul64To128( b, z, &term0, &term1 ); sub128( a0, a1, term0, term1, &rem0, &rem1 ); while ( ( (si6b) rem0 ) < 0 ) { z -= LIT64( 0x100000000 ); b1 = b<<32; add128( rem0, rem1, b0, b1, &rem0, &rem1 ); } rem0 = ( rem0<<32 ) | ( rem1>>32 ); z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : Ui6Div(rem0, b0); return z; } /*---------------------------------------------------------------------------- | Returns an approximation to the square root of the 32-bit significand given | by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of | `aExp' (the least significant bit) is 1, the integer returned approximates | 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp' | is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either | case, the approximation returned lies strictly within +/-2 of the exact | value. *----------------------------------------------------------------------------*/ LOCALFUNC ui5b estimateSqrt32( si4r aExp, ui5b a ) { static const ui4b sqrtOddAdjustments[] = { 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0, 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67 }; static const ui4b sqrtEvenAdjustments[] = { 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E, 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002 }; si3r index; ui5b z; index = ( a>>27 ) & 15; if ( aExp & 1 ) { z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ]; z = ( ( a / z )<<14 ) + ( z<<15 ); a >>= 1; } else { z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ]; z = a / z + z; z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 ); if ( z <= a ) return (ui5b) ( ( (si5b) a )>>1 ); } return ( (ui5b) Ui6Div( ( ( (ui6b) a )<<31 ), z ) ) + ( z>>1 ); } /*---------------------------------------------------------------------------- | Returns the number of leading 0 bits before the most-significant 1 bit of | `a'. If `a' is zero, 32 is returned. *----------------------------------------------------------------------------*/ LOCALFUNC si3r countLeadingZeros32( ui5b a ) { static const si3r countLeadingZerosHigh[] = { 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; si3r shiftCount; shiftCount = 0; if ( a < 0x10000 ) { shiftCount += 16; a <<= 16; } if ( a < 0x1000000 ) { shiftCount += 8; a <<= 8; } shiftCount += countLeadingZerosHigh[ a>>24 ]; return shiftCount; } /*---------------------------------------------------------------------------- | Returns the number of leading 0 bits before the most-significant 1 bit of | `a'. If `a' is zero, 64 is returned. *----------------------------------------------------------------------------*/ LOCALFUNC si3r countLeadingZeros64( ui6b a ) { si3r shiftCount; shiftCount = 0; if ( a < ( (ui6b) 1 )<<32 ) { shiftCount += 32; } else { a >>= 32; } shiftCount += countLeadingZeros32( a ); return shiftCount; } /*---------------------------------------------------------------------------- | Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' | is equal to the 128-bit value formed by concatenating `b0' and `b1'. | Otherwise, returns 0. *----------------------------------------------------------------------------*/ LOCALINLINEFUNC flag eq128( ui6b a0, ui6b a1, ui6b b0, ui6b b1 ) { return ( a0 == b0 ) && ( a1 == b1 ); } /*---------------------------------------------------------------------------- | Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less | than or equal to the 128-bit value formed by concatenating `b0' and `b1'. | Otherwise, returns 0. *----------------------------------------------------------------------------*/ LOCALINLINEFUNC flag le128( ui6b a0, ui6b a1, ui6b b0, ui6b b1 ) { return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) ); } /*---------------------------------------------------------------------------- | Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less | than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise, | returns 0. *----------------------------------------------------------------------------*/ LOCALINLINEFUNC flag lt128( ui6b a0, ui6b a1, ui6b b0, ui6b b1 ) { return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) ); } /*---------------------------------------------------------------------------- | Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is | not equal to the 128-bit value formed by concatenating `b0' and `b1'. | Otherwise, returns 0. *----------------------------------------------------------------------------*/ #if cIncludeFPUUnused LOCALINLINEFUNC flag ne128( ui6b a0, ui6b a1, ui6b b0, ui6b b1 ) { return ( a0 != b0 ) || ( a1 != b1 ); } #endif /* ----- end from original file "softfloat-macros" ----- */ /*---------------------------------------------------------------------------- | Functions and definitions to determine: (1) whether tininess for underflow | is detected before or after rounding by default, (2) what (if anything) | happens when exceptions are raised, (3) how signaling NaNs are distinguished | from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs | are propagated from function inputs to output. These details are target- | specific. *----------------------------------------------------------------------------*/ /* ----- from original file "softfloat-specialize" ----- */ /*============================================================================ This C source fragment is part of the SoftFloat IEC/IEEE Floating-point Arithmetic Package, Release 2b. ["original SoftFloat Copyright notice" went here, included near top of this file.] =============================================================================*/ /*---------------------------------------------------------------------------- | Software IEC/IEEE floating-point underflow tininess-detection mode. *----------------------------------------------------------------------------*/ enum { float_tininess_after_rounding = 0, float_tininess_before_rounding = 1 }; /*---------------------------------------------------------------------------- | Underflow tininess-detection mode, statically initialized to default value. | (The declaration in `softfloat.h' must match the `si3r' type here.) *----------------------------------------------------------------------------*/ LOCALVAR si3r float_detect_tininess = float_tininess_after_rounding; /*---------------------------------------------------------------------------- | Routine to raise any or all of the software IEC/IEEE floating-point | exception flags. *----------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- | Raises the exceptions specified by `flags'. Floating-point traps can be | defined here if desired. It is currently not possible for such a trap | to substitute a result value. If traps are not implemented, this routine | should be simply `float_exception_flags |= flags;'. *----------------------------------------------------------------------------*/ LOCALFUNC void float_raise( si3r flags ) { float_exception_flags |= flags; } /*---------------------------------------------------------------------------- | Internal canonical NaN format. *----------------------------------------------------------------------------*/ typedef struct { flag sign; ui6b high, low; } commonNaNT; /*---------------------------------------------------------------------------- | The pattern for a default generated extended double-precision NaN. The | `high' and `low' values hold the most- and least-significant bits, | respectively. *----------------------------------------------------------------------------*/ #define floatx80_default_nan_high 0xFFFF #define floatx80_default_nan_low LIT64( 0xC000000000000000 ) /*---------------------------------------------------------------------------- | Returns 1 if the extended double-precision floating-point value `a' is a | NaN; otherwise returns 0. *----------------------------------------------------------------------------*/ LOCALFUNC flag floatx80_is_nan( floatx80 a ) { return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (ui6b) ( a.low<<1 ); } /*---------------------------------------------------------------------------- | Returns 1 if the extended double-precision floating-point value `a' is a | signaling NaN; otherwise returns 0. *----------------------------------------------------------------------------*/ LOCALFUNC flag floatx80_is_signaling_nan( floatx80 a ) { ui6b aLow; aLow = a.low & ~ LIT64( 0x4000000000000000 ); return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (ui6b) ( aLow<<1 ) && ( a.low == aLow ); } /*---------------------------------------------------------------------------- | Returns the result of converting the extended double-precision floating- | point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the | invalid exception is raised. *----------------------------------------------------------------------------*/ LOCALFUNC commonNaNT floatx80ToCommonNaN( floatx80 a ) { commonNaNT z; if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); z.sign = a.high>>15; z.low = 0; z.high = a.low<<1; return z; } /*---------------------------------------------------------------------------- | Returns the result of converting the canonical NaN `a' to the extended | double-precision floating-point format. *----------------------------------------------------------------------------*/ LOCALFUNC floatx80 commonNaNToFloatx80( commonNaNT a ) { floatx80 z; z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); z.high = ( ( (ui4b) a.sign )<<15 ) | 0x7FFF; return z; } /*---------------------------------------------------------------------------- | Takes two extended double-precision floating-point values `a' and `b', one | of which is a NaN, and returns the appropriate NaN result. If either `a' or | `b' is a signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ LOCALFUNC floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) { flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; aIsNaN = floatx80_is_nan( a ); aIsSignalingNaN = floatx80_is_signaling_nan( a ); bIsNaN = floatx80_is_nan( b ); bIsSignalingNaN = floatx80_is_signaling_nan( b ); a.low |= LIT64( 0xC000000000000000 ); b.low |= LIT64( 0xC000000000000000 ); if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); if ( aIsSignalingNaN ) { if ( bIsSignalingNaN ) goto returnLargerSignificand; return bIsNaN ? b : a; } else if ( aIsNaN ) { if ( bIsSignalingNaN | ! bIsNaN ) return a; returnLargerSignificand: if ( a.low < b.low ) return b; if ( b.low < a.low ) return a; return ( a.high < b.high ) ? a : b; } else { return b; } } #ifdef FLOAT128 /*---------------------------------------------------------------------------- | The pattern for a default generated quadruple-precision NaN. The `high' and | `low' values hold the most- and least-significant bits, respectively. *----------------------------------------------------------------------------*/ #define float128_default_nan_high LIT64( 0xFFFF800000000000 ) #define float128_default_nan_low LIT64( 0x0000000000000000 ) /*---------------------------------------------------------------------------- | Returns 1 if the quadruple-precision floating-point value `a' is a NaN; | otherwise returns 0. *----------------------------------------------------------------------------*/ LOCALFUNC flag float128_is_nan( float128 a ) { return ( LIT64( 0xFFFE000000000000 ) <= (ui6b) ( a.high<<1 ) ) && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); } /*---------------------------------------------------------------------------- | Returns 1 if the quadruple-precision floating-point value `a' is a | signaling NaN; otherwise returns 0. *----------------------------------------------------------------------------*/ LOCALFUNC flag float128_is_signaling_nan( float128 a ) { return ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); } /*---------------------------------------------------------------------------- | Returns the result of converting the quadruple-precision floating-point NaN | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ LOCALFUNC commonNaNT float128ToCommonNaN( float128 a ) { commonNaNT z; if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); z.sign = a.high>>63; shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); return z; } /*---------------------------------------------------------------------------- | Returns the result of converting the canonical NaN `a' to the quadruple- | precision floating-point format. *----------------------------------------------------------------------------*/ LOCALFUNC float128 commonNaNToFloat128( commonNaNT a ) { float128 z; shift128Right( a.high, a.low, 16, &z.high, &z.low ); z.high |= ( ( (ui6b) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); return z; } /*---------------------------------------------------------------------------- | Takes two quadruple-precision floating-point values `a' and `b', one of | which is a NaN, and returns the appropriate NaN result. If either `a' or | `b' is a signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ LOCALFUNC float128 propagateFloat128NaN( float128 a, float128 b ) { flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; aIsNaN = float128_is_nan( a ); aIsSignalingNaN = float128_is_signaling_nan( a ); bIsNaN = float128_is_nan( b ); bIsSignalingNaN = float128_is_signaling_nan( b ); a.high |= LIT64( 0x0000800000000000 ); b.high |= LIT64( 0x0000800000000000 ); if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); if ( aIsSignalingNaN ) { if ( bIsSignalingNaN ) goto returnLargerSignificand; return bIsNaN ? b : a; } else if ( aIsNaN ) { if ( bIsSignalingNaN | ! bIsNaN ) return a; returnLargerSignificand: if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b; if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a; return ( a.high < b.high ) ? a : b; } else { return b; } } #endif /* ----- end from original file "softfloat-specialize" ----- */ /* ----- from original file "softfloat.c" ----- */ /*============================================================================ This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic Package, Release 2b. ["original SoftFloat Copyright notice" went here, included near top of this file.] =============================================================================*/ /*---------------------------------------------------------------------------- | Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 | and 7, and returns the properly rounded 32-bit integer corresponding to the | input. If `zSign' is 1, the input is negated before being converted to an | integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input | is simply rounded to an integer, with the inexact exception raised if the | input cannot be represented exactly as an integer. However, if the fixed- | point input is too large, the invalid exception is raised and the largest | positive or negative integer is returned. *----------------------------------------------------------------------------*/ LOCALFUNC si5r roundAndPackInt32( flag zSign, ui6b absZ ) { si3r roundingMode; flag roundNearestEven; si3r roundIncrement, roundBits; si5r z; roundingMode = float_rounding_mode; roundNearestEven = ( roundingMode == float_round_nearest_even ); roundIncrement = 0x40; if ( ! roundNearestEven ) { if ( roundingMode == float_round_to_zero ) { roundIncrement = 0; } else { roundIncrement = 0x7F; if ( zSign ) { if ( roundingMode == float_round_up ) roundIncrement = 0; } else { if ( roundingMode == float_round_down ) roundIncrement = 0; } } } roundBits = absZ & 0x7F; absZ = ( absZ + roundIncrement )>>7; absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); z = absZ; if ( zSign ) z = - z; if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { float_raise( float_flag_invalid ); return zSign ? (si5b) 0x80000000 : 0x7FFFFFFF; } if ( roundBits ) float_exception_flags |= float_flag_inexact; return z; } /*---------------------------------------------------------------------------- | Returns the fraction bits of the extended double-precision floating-point | value `a'. *----------------------------------------------------------------------------*/ LOCALINLINEFUNC ui6b extractFloatx80Frac( floatx80 a ) { return a.low; } /*---------------------------------------------------------------------------- | Returns the exponent bits of the extended double-precision floating-point | value `a'. *----------------------------------------------------------------------------*/ LOCALINLINEFUNC si5r extractFloatx80Exp( floatx80 a ) { return a.high & 0x7FFF; } /*---------------------------------------------------------------------------- | Returns the sign bit of the extended double-precision floating-point value | `a'. *----------------------------------------------------------------------------*/ LOCALINLINEFUNC flag extractFloatx80Sign( floatx80 a ) { return a.high>>15; } /*---------------------------------------------------------------------------- | Normalizes the subnormal extended double-precision floating-point value | represented by the denormalized significand `aSig'. The normalized exponent | and significand are stored at the locations pointed to by `zExpPtr' and | `zSigPtr', respectively. *----------------------------------------------------------------------------*/ LOCALPROC normalizeFloatx80Subnormal( ui6b aSig, si5r *zExpPtr, ui6b *zSigPtr ) { si3r shiftCount; shiftCount = countLeadingZeros64( aSig ); *zSigPtr = aSig<>48 ) & 0x7FFF; } /*---------------------------------------------------------------------------- | Returns the sign bit of the quadruple-precision floating-point value `a'. *----------------------------------------------------------------------------*/ LOCALINLINEFUNC flag extractFloat128Sign( float128 a ) { return a.high>>63; } /*---------------------------------------------------------------------------- | Normalizes the subnormal quadruple-precision floating-point value | represented by the denormalized significand formed by the concatenation of | `aSig0' and `aSig1'. The normalized exponent is stored at the location | pointed to by `zExpPtr'. The most significant 49 bits of the normalized | significand are stored at the location pointed to by `zSig0Ptr', and the | least significant 64 bits of the normalized significand are stored at the | location pointed to by `zSig1Ptr'. *----------------------------------------------------------------------------*/ LOCALPROC normalizeFloat128Subnormal( ui6b aSig0, ui6b aSig1, si5r *zExpPtr, ui6b *zSig0Ptr, ui6b *zSig1Ptr ) { si3r shiftCount; if ( aSig0 == 0 ) { shiftCount = countLeadingZeros64( aSig1 ) - 15; if ( shiftCount < 0 ) { *zSig0Ptr = aSig1>>( - shiftCount ); *zSig1Ptr = aSig1<<( shiftCount & 63 ); } else { *zSig0Ptr = aSig1<>= shiftCount; z = aSig; if ( aSign ) z = - z; if ( ( z < 0 ) ^ aSign ) { invalid: float_raise( float_flag_invalid ); return aSign ? (si5b) 0x80000000 : 0x7FFFFFFF; } if ( ( aSig<>1; if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; } else if ( roundingMode != float_round_to_zero ) { if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) { z.low += roundBitsMask; } } z.low &= ~ roundBitsMask; if ( z.low == 0 ) { ++z.high; z.low = LIT64( 0x8000000000000000 ); } if ( z.low != a.low ) float_exception_flags |= float_flag_inexact; return z; } /*---------------------------------------------------------------------------- | Returns the result of adding the absolute values of the extended double- | precision floating-point values `a' and `b'. If `zSign' is 1, the sum is | negated before being returned. `zSign' is ignored if the result is a NaN. | The addition is performed according to the IEC/IEEE Standard for Binary | Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) { si5r aExp, bExp, zExp; ui6b aSig, bSig, zSig0, zSig1; si5r expDiff; aSig = extractFloatx80Frac( a ); aExp = extractFloatx80Exp( a ); bSig = extractFloatx80Frac( b ); bExp = extractFloatx80Exp( b ); expDiff = aExp - bExp; if ( 0 < expDiff ) { if ( aExp == 0x7FFF ) { if ( (ui6b) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); return a; } if ( bExp == 0 ) --expDiff; shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); zExp = aExp; } else if ( expDiff < 0 ) { if ( bExp == 0x7FFF ) { if ( (ui6b) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); } if ( aExp == 0 ) ++expDiff; shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); zExp = bExp; } else { if ( aExp == 0x7FFF ) { if ( (ui6b) ( ( aSig | bSig )<<1 ) ) { return propagateFloatx80NaN( a, b ); } return a; } zSig1 = 0; zSig0 = aSig + bSig; if ( aExp == 0 ) { normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 ); goto roundAndPack; } zExp = aExp; goto shiftRight1; } zSig0 = aSig + bSig; if ( (si6b) zSig0 < 0 ) goto roundAndPack; shiftRight1: shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 ); zSig0 |= LIT64( 0x8000000000000000 ); ++zExp; roundAndPack: return roundAndPackFloatx80( floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); } /*---------------------------------------------------------------------------- | Returns the result of subtracting the absolute values of the extended | double-precision floating-point values `a' and `b'. If `zSign' is 1, the | difference is negated before being returned. `zSign' is ignored if the | result is a NaN. The subtraction is performed according to the IEC/IEEE | Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) { si5r aExp, bExp, zExp; ui6b aSig, bSig, zSig0, zSig1; si5r expDiff; floatx80 z; aSig = extractFloatx80Frac( a ); aExp = extractFloatx80Exp( a ); bSig = extractFloatx80Frac( b ); bExp = extractFloatx80Exp( b ); expDiff = aExp - bExp; if ( 0 < expDiff ) goto aExpBigger; if ( expDiff < 0 ) goto bExpBigger; if ( aExp == 0x7FFF ) { if ( (ui6b) ( ( aSig | bSig )<<1 ) ) { return propagateFloatx80NaN( a, b ); } float_raise( float_flag_invalid ); z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; } if ( aExp == 0 ) { aExp = 1; bExp = 1; } zSig1 = 0; if ( bSig < aSig ) goto aBigger; if ( aSig < bSig ) goto bBigger; return packFloatx80( float_rounding_mode == float_round_down, 0, 0 ); bExpBigger: if ( bExp == 0x7FFF ) { if ( (ui6b) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) ); } if ( aExp == 0 ) ++expDiff; shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); bBigger: sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 ); zExp = bExp; zSign ^= 1; goto normalizeRoundAndPack; aExpBigger: if ( aExp == 0x7FFF ) { if ( (ui6b) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); return a; } if ( bExp == 0 ) --expDiff; shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); aBigger: sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 ); zExp = aExp; normalizeRoundAndPack: return normalizeRoundAndPackFloatx80( floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); } /*---------------------------------------------------------------------------- | Returns the result of adding the extended double-precision floating-point | values `a' and `b'. The operation is performed according to the IEC/IEEE | Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC floatx80 floatx80_add( floatx80 a, floatx80 b ) { flag aSign, bSign; aSign = extractFloatx80Sign( a ); bSign = extractFloatx80Sign( b ); if ( aSign == bSign ) { return addFloatx80Sigs( a, b, aSign ); } else { return subFloatx80Sigs( a, b, aSign ); } } /*---------------------------------------------------------------------------- | Returns the result of subtracting the extended double-precision floating- | point values `a' and `b'. The operation is performed according to the | IEC/IEEE Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC floatx80 floatx80_sub( floatx80 a, floatx80 b ) { flag aSign, bSign; aSign = extractFloatx80Sign( a ); bSign = extractFloatx80Sign( b ); if ( aSign == bSign ) { return subFloatx80Sigs( a, b, aSign ); } else { return addFloatx80Sigs( a, b, aSign ); } } /*---------------------------------------------------------------------------- | Returns the result of multiplying the extended double-precision floating- | point values `a' and `b'. The operation is performed according to the | IEC/IEEE Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC floatx80 floatx80_mul( floatx80 a, floatx80 b ) { flag aSign, bSign, zSign; si5r aExp, bExp, zExp; ui6b aSig, bSig, zSig0, zSig1; floatx80 z; aSig = extractFloatx80Frac( a ); aExp = extractFloatx80Exp( a ); aSign = extractFloatx80Sign( a ); bSig = extractFloatx80Frac( b ); bExp = extractFloatx80Exp( b ); bSign = extractFloatx80Sign( b ); zSign = aSign ^ bSign; if ( aExp == 0x7FFF ) { if ( (ui6b) ( aSig<<1 ) || ( ( bExp == 0x7FFF ) && (ui6b) ( bSig<<1 ) ) ) { return propagateFloatx80NaN( a, b ); } if ( ( bExp | bSig ) == 0 ) goto invalid; return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); } if ( bExp == 0x7FFF ) { if ( (ui6b) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); if ( ( aExp | aSig ) == 0 ) { invalid: float_raise( float_flag_invalid ); z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; } return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); } if ( aExp == 0 ) { if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); } if ( bExp == 0 ) { if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 ); normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); } zExp = aExp + bExp - 0x3FFE; mul64To128( aSig, bSig, &zSig0, &zSig1 ); if ( 0 < (si6b) zSig0 ) { shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 ); --zExp; } return roundAndPackFloatx80( floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); } /*---------------------------------------------------------------------------- | Returns the result of dividing the extended double-precision floating-point | value `a' by the corresponding value `b'. The operation is performed | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC floatx80 floatx80_div( floatx80 a, floatx80 b ) { flag aSign, bSign, zSign; si5r aExp, bExp, zExp; ui6b aSig, bSig, zSig0, zSig1; ui6b rem0, rem1, rem2, term0, term1, term2; floatx80 z; aSig = extractFloatx80Frac( a ); aExp = extractFloatx80Exp( a ); aSign = extractFloatx80Sign( a ); bSig = extractFloatx80Frac( b ); bExp = extractFloatx80Exp( b ); bSign = extractFloatx80Sign( b ); zSign = aSign ^ bSign; if ( aExp == 0x7FFF ) { if ( (ui6b) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); if ( bExp == 0x7FFF ) { if ( (ui6b) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); goto invalid; } return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); } if ( bExp == 0x7FFF ) { if ( (ui6b) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); return packFloatx80( zSign, 0, 0 ); } if ( bExp == 0 ) { if ( bSig == 0 ) { if ( ( aExp | aSig ) == 0 ) { invalid: float_raise( float_flag_invalid ); z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; } float_raise( float_flag_divbyzero ); return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); } normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); } if ( aExp == 0 ) { if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); } if ( aSig == 0 ) { /* added by pcp. this invalid input seems to cause hang in estimateDiv128To64. should validate inputs generally. */ return packFloatx80( zSign, 0, 0 ); } if ( (si6b) bSig >= 0 ) { /* added by pcp. another check. invalid input, most significant bit should be set? */ return packFloatx80( zSign, 0, 0 ); } zExp = aExp - bExp + 0x3FFE; rem1 = 0; if ( bSig <= aSig ) { shift128Right( aSig, 0, 1, &aSig, &rem1 ); ++zExp; } zSig0 = estimateDiv128To64( aSig, rem1, bSig ); mul64To128( bSig, zSig0, &term0, &term1 ); sub128( aSig, rem1, term0, term1, &rem0, &rem1 ); while ( (si6b) rem0 < 0 ) { --zSig0; add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); } zSig1 = estimateDiv128To64( rem1, 0, bSig ); if ( (ui6b) ( zSig1<<1 ) <= 8 ) { mul64To128( bSig, zSig1, &term1, &term2 ); sub128( rem1, 0, term1, term2, &rem1, &rem2 ); while ( (si6b) rem1 < 0 ) { --zSig1; add128( rem1, rem2, 0, bSig, &rem1, &rem2 ); } zSig1 |= ( ( rem1 | rem2 ) != 0 ); } return roundAndPackFloatx80( floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); } /*---------------------------------------------------------------------------- | Returns the remainder of the extended double-precision floating-point value | `a' with respect to the corresponding value `b'. The operation is performed | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC floatx80 floatx80_rem( floatx80 a, floatx80 b ) { flag aSign, /* bSign, */ zSign; si5r aExp, bExp, expDiff; ui6b aSig0, aSig1, bSig; ui6b q, term0, term1, alternateASig0, alternateASig1; floatx80 z; aSig0 = extractFloatx80Frac( a ); aExp = extractFloatx80Exp( a ); aSign = extractFloatx80Sign( a ); bSig = extractFloatx80Frac( b ); bExp = extractFloatx80Exp( b ); /* not used. should it be? bSign = extractFloatx80Sign( b ); */ if ( aExp == 0x7FFF ) { if ( (ui6b) ( aSig0<<1 ) || ( ( bExp == 0x7FFF ) && (ui6b) ( bSig<<1 ) ) ) { return propagateFloatx80NaN( a, b ); } goto invalid; } if ( bExp == 0x7FFF ) { if ( (ui6b) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); return a; } if ( bExp == 0 ) { if ( bSig == 0 ) { invalid: float_raise( float_flag_invalid ); z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; } normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); } if ( aExp == 0 ) { if ( (ui6b) ( aSig0<<1 ) == 0 ) return a; normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); } bSig |= LIT64( 0x8000000000000000 ); zSign = aSign; expDiff = aExp - bExp; aSig1 = 0; if ( expDiff < 0 ) { if ( expDiff < -1 ) return a; shift128Right( aSig0, 0, 1, &aSig0, &aSig1 ); expDiff = 0; } q = ( bSig <= aSig0 ); if ( q ) aSig0 -= bSig; expDiff -= 64; while ( 0 < expDiff ) { q = estimateDiv128To64( aSig0, aSig1, bSig ); q = ( 2 < q ) ? q - 2 : 0; mul64To128( bSig, q, &term0, &term1 ); sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 ); expDiff -= 62; } expDiff += 64; if ( 0 < expDiff ) { q = estimateDiv128To64( aSig0, aSig1, bSig ); q = ( 2 < q ) ? q - 2 : 0; q >>= 64 - expDiff; mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 ); sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 ); while ( le128( term0, term1, aSig0, aSig1 ) ) { ++q; sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); } } else { term1 = 0; term0 = bSig; } sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 ); if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) && ( q & 1 ) ) ) { aSig0 = alternateASig0; aSig1 = alternateASig1; zSign = ! zSign; } return normalizeRoundAndPackFloatx80( 80, zSign, bExp + expDiff, aSig0, aSig1 ); } /*---------------------------------------------------------------------------- | Returns the square root of the extended double-precision floating-point | value `a'. The operation is performed according to the IEC/IEEE Standard | for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC floatx80 floatx80_sqrt( floatx80 a ) { flag aSign; si5r aExp, zExp; ui6b aSig0, aSig1, zSig0, zSig1, doubleZSig0; ui6b rem0, rem1, rem2, rem3, term0, term1, term2, term3; floatx80 z; aSig0 = extractFloatx80Frac( a ); aExp = extractFloatx80Exp( a ); aSign = extractFloatx80Sign( a ); if ( aExp == 0x7FFF ) { if ( (ui6b) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a ); if ( ! aSign ) return a; goto invalid; } if ( aSign ) { if ( ( aExp | aSig0 ) == 0 ) return a; invalid: float_raise( float_flag_invalid ); z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; } if ( aExp == 0 ) { if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 ); normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); } zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF; zSig0 = estimateSqrt32( aExp, aSig0>>32 ); shift128Right( aSig0, 0, 2 + ( aExp & 1 ), &aSig0, &aSig1 ); zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); doubleZSig0 = zSig0<<1; mul64To128( zSig0, zSig0, &term0, &term1 ); sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); while ( (si6b) rem0 < 0 ) { --zSig0; doubleZSig0 -= 2; add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); } zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) { if ( zSig1 == 0 ) zSig1 = 1; mul64To128( doubleZSig0, zSig1, &term1, &term2 ); sub128( rem1, 0, term1, term2, &rem1, &rem2 ); mul64To128( zSig1, zSig1, &term2, &term3 ); sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); while ( (si6b) rem1 < 0 ) { --zSig1; shortShift128Left( 0, zSig1, 1, &term2, &term3 ); term3 |= 1; term2 |= doubleZSig0; add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); } zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); } shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 ); zSig0 |= doubleZSig0; return roundAndPackFloatx80( floatx80_rounding_precision, 0, zExp, zSig0, zSig1 ); } /*---------------------------------------------------------------------------- | Returns 1 if the extended double-precision floating-point value `a' is | equal to the corresponding value `b', and 0 otherwise. The comparison is | performed according to the IEC/IEEE Standard for Binary Floating-Point | Arithmetic. *----------------------------------------------------------------------------*/ #if cIncludeFPUUnused LOCALFUNC flag floatx80_eq( floatx80 a, floatx80 b ) { if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) && (ui6b) ( extractFloatx80Frac( a )<<1 ) ) || ( ( extractFloatx80Exp( b ) == 0x7FFF ) && (ui6b) ( extractFloatx80Frac( b )<<1 ) ) ) { if ( floatx80_is_signaling_nan( a ) || floatx80_is_signaling_nan( b ) ) { float_raise( float_flag_invalid ); } return 0; } return ( a.low == b.low ) && ( ( a.high == b.high ) || ( ( a.low == 0 ) && ( (ui4b) ( ( a.high | b.high )<<1 ) == 0 ) ) ); } #endif /*---------------------------------------------------------------------------- | Returns 1 if the extended double-precision floating-point value `a' is | less than or equal to the corresponding value `b', and 0 otherwise. The | comparison is performed according to the IEC/IEEE Standard for Binary | Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ #if cIncludeFPUUnused LOCALFUNC flag floatx80_le( floatx80 a, floatx80 b ) { flag aSign, bSign; if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) && (ui6b) ( extractFloatx80Frac( a )<<1 ) ) || ( ( extractFloatx80Exp( b ) == 0x7FFF ) && (ui6b) ( extractFloatx80Frac( b )<<1 ) ) ) { float_raise( float_flag_invalid ); return 0; } aSign = extractFloatx80Sign( a ); bSign = extractFloatx80Sign( b ); if ( aSign != bSign ) { return aSign || ( ( ( (ui4b) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) == 0 ); } return aSign ? le128( b.high, b.low, a.high, a.low ) : le128( a.high, a.low, b.high, b.low ); } #endif /*---------------------------------------------------------------------------- | Returns 1 if the extended double-precision floating-point value `a' is | less than the corresponding value `b', and 0 otherwise. The comparison | is performed according to the IEC/IEEE Standard for Binary Floating-Point | Arithmetic. *----------------------------------------------------------------------------*/ #if cIncludeFPUUnused LOCALFUNC flag floatx80_lt( floatx80 a, floatx80 b ) { flag aSign, bSign; if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) && (ui6b) ( extractFloatx80Frac( a )<<1 ) ) || ( ( extractFloatx80Exp( b ) == 0x7FFF ) && (ui6b) ( extractFloatx80Frac( b )<<1 ) ) ) { float_raise( float_flag_invalid ); return 0; } aSign = extractFloatx80Sign( a ); bSign = extractFloatx80Sign( b ); if ( aSign != bSign ) { return aSign && ( ( ( (ui4b) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) != 0 ); } return aSign ? lt128( b.high, b.low, a.high, a.low ) : lt128( a.high, a.low, b.high, b.low ); } #endif /*---------------------------------------------------------------------------- | Returns 1 if the extended double-precision floating-point value `a' is equal | to the corresponding value `b', and 0 otherwise. The invalid exception is | raised if either operand is a NaN. Otherwise, the comparison is performed | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ #if cIncludeFPUUnused LOCALFUNC flag floatx80_eq_signaling( floatx80 a, floatx80 b ) { if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) && (ui6b) ( extractFloatx80Frac( a )<<1 ) ) || ( ( extractFloatx80Exp( b ) == 0x7FFF ) && (ui6b) ( extractFloatx80Frac( b )<<1 ) ) ) { float_raise( float_flag_invalid ); return 0; } return ( a.low == b.low ) && ( ( a.high == b.high ) || ( ( a.low == 0 ) && ( (ui4b) ( ( a.high | b.high )<<1 ) == 0 ) ) ); } #endif /*---------------------------------------------------------------------------- | Returns 1 if the extended double-precision floating-point value `a' is less | than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs | do not cause an exception. Otherwise, the comparison is performed according | to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ #if cIncludeFPUUnused LOCALFUNC flag floatx80_le_quiet( floatx80 a, floatx80 b ) { flag aSign, bSign; if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) && (ui6b) ( extractFloatx80Frac( a )<<1 ) ) || ( ( extractFloatx80Exp( b ) == 0x7FFF ) && (ui6b) ( extractFloatx80Frac( b )<<1 ) ) ) { if ( floatx80_is_signaling_nan( a ) || floatx80_is_signaling_nan( b ) ) { float_raise( float_flag_invalid ); } return 0; } aSign = extractFloatx80Sign( a ); bSign = extractFloatx80Sign( b ); if ( aSign != bSign ) { return aSign || ( ( ( (ui4b) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) == 0 ); } return aSign ? le128( b.high, b.low, a.high, a.low ) : le128( a.high, a.low, b.high, b.low ); } #endif /*---------------------------------------------------------------------------- | Returns 1 if the extended double-precision floating-point value `a' is less | than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause | an exception. Otherwise, the comparison is performed according to the | IEC/IEEE Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ #if cIncludeFPUUnused LOCALFUNC flag floatx80_lt_quiet( floatx80 a, floatx80 b ) { flag aSign, bSign; if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) && (ui6b) ( extractFloatx80Frac( a )<<1 ) ) || ( ( extractFloatx80Exp( b ) == 0x7FFF ) && (ui6b) ( extractFloatx80Frac( b )<<1 ) ) ) { if ( floatx80_is_signaling_nan( a ) || floatx80_is_signaling_nan( b ) ) { float_raise( float_flag_invalid ); } return 0; } aSign = extractFloatx80Sign( a ); bSign = extractFloatx80Sign( b ); if ( aSign != bSign ) { return aSign && ( ( ( (ui4b) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) != 0 ); } return aSign ? lt128( b.high, b.low, a.high, a.low ) : lt128( a.high, a.low, b.high, b.low ); } #endif #ifdef FLOAT128 /*---------------------------------------------------------------------------- | Returns the result of converting the quadruple-precision floating-point | value `a' to the extended double-precision floating-point format. The | conversion is performed according to the IEC/IEEE Standard for Binary | Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC floatx80 float128_to_floatx80( float128 a ) { flag aSign; si5r aExp; ui6b aSig0, aSig1; aSig1 = extractFloat128Frac1( a ); aSig0 = extractFloat128Frac0( a ); aExp = extractFloat128Exp( a ); aSign = extractFloat128Sign( a ); if ( aExp == 0x7FFF ) { if ( aSig0 | aSig1 ) { return commonNaNToFloatx80( float128ToCommonNaN( a ) ); } return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); } if ( aExp == 0 ) { if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 ); normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); } else { aSig0 |= LIT64( 0x0001000000000000 ); } shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 ); return roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 ); } /*---------------------------------------------------------------------------- | Returns the result of adding the absolute values of the quadruple-precision | floating-point values `a' and `b'. If `zSign' is 1, the sum is negated | before being returned. `zSign' is ignored if the result is a NaN. | The addition is performed according to the IEC/IEEE Standard for Binary | Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC float128 addFloat128Sigs( float128 a, float128 b, flag zSign ) { si5r aExp, bExp, zExp; ui6b aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; si5r expDiff; aSig1 = extractFloat128Frac1( a ); aSig0 = extractFloat128Frac0( a ); aExp = extractFloat128Exp( a ); bSig1 = extractFloat128Frac1( b ); bSig0 = extractFloat128Frac0( b ); bExp = extractFloat128Exp( b ); expDiff = aExp - bExp; if ( 0 < expDiff ) { if ( aExp == 0x7FFF ) { if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); return a; } if ( bExp == 0 ) { --expDiff; } else { bSig0 |= LIT64( 0x0001000000000000 ); } shift128ExtraRightJamming( bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 ); zExp = aExp; } else if ( expDiff < 0 ) { if ( bExp == 0x7FFF ) { if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); return packFloat128( zSign, 0x7FFF, 0, 0 ); } if ( aExp == 0 ) { ++expDiff; } else { aSig0 |= LIT64( 0x0001000000000000 ); } shift128ExtraRightJamming( aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 ); zExp = bExp; } else { if ( aExp == 0x7FFF ) { if ( aSig0 | aSig1 | bSig0 | bSig1 ) { return propagateFloat128NaN( a, b ); } return a; } add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 ); zSig2 = 0; zSig0 |= LIT64( 0x0002000000000000 ); zExp = aExp; goto shiftRight1; } aSig0 |= LIT64( 0x0001000000000000 ); add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); --zExp; if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack; ++zExp; shiftRight1: shift128ExtraRightJamming( zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); roundAndPack: return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); } /*---------------------------------------------------------------------------- | Returns the result of subtracting the absolute values of the quadruple- | precision floating-point values `a' and `b'. If `zSign' is 1, the | difference is negated before being returned. `zSign' is ignored if the | result is a NaN. The subtraction is performed according to the IEC/IEEE | Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC float128 subFloat128Sigs( float128 a, float128 b, flag zSign ) { si5r aExp, bExp, zExp; ui6b aSig0, aSig1, bSig0, bSig1, zSig0, zSig1; si5r expDiff; float128 z; aSig1 = extractFloat128Frac1( a ); aSig0 = extractFloat128Frac0( a ); aExp = extractFloat128Exp( a ); bSig1 = extractFloat128Frac1( b ); bSig0 = extractFloat128Frac0( b ); bExp = extractFloat128Exp( b ); expDiff = aExp - bExp; shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 ); if ( 0 < expDiff ) goto aExpBigger; if ( expDiff < 0 ) goto bExpBigger; if ( aExp == 0x7FFF ) { if ( aSig0 | aSig1 | bSig0 | bSig1 ) { return propagateFloat128NaN( a, b ); } float_raise( float_flag_invalid ); z.low = float128_default_nan_low; z.high = float128_default_nan_high; return z; } if ( aExp == 0 ) { aExp = 1; bExp = 1; } if ( bSig0 < aSig0 ) goto aBigger; if ( aSig0 < bSig0 ) goto bBigger; if ( bSig1 < aSig1 ) goto aBigger; if ( aSig1 < bSig1 ) goto bBigger; return packFloat128( float_rounding_mode == float_round_down, 0, 0, 0 ); bExpBigger: if ( bExp == 0x7FFF ) { if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 ); } if ( aExp == 0 ) { ++expDiff; } else { aSig0 |= LIT64( 0x4000000000000000 ); } shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); bSig0 |= LIT64( 0x4000000000000000 ); bBigger: sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 ); zExp = bExp; zSign ^= 1; goto normalizeRoundAndPack; aExpBigger: if ( aExp == 0x7FFF ) { if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); return a; } if ( bExp == 0 ) { --expDiff; } else { bSig0 |= LIT64( 0x4000000000000000 ); } shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 ); aSig0 |= LIT64( 0x4000000000000000 ); aBigger: sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); zExp = aExp; normalizeRoundAndPack: --zExp; return normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 ); } /*---------------------------------------------------------------------------- | Returns the result of adding the quadruple-precision floating-point values | `a' and `b'. The operation is performed according to the IEC/IEEE Standard | for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC float128 float128_add( float128 a, float128 b ) { flag aSign, bSign; aSign = extractFloat128Sign( a ); bSign = extractFloat128Sign( b ); if ( aSign == bSign ) { return addFloat128Sigs( a, b, aSign ); } else { return subFloat128Sigs( a, b, aSign ); } } /*---------------------------------------------------------------------------- | Returns the result of subtracting the quadruple-precision floating-point | values `a' and `b'. The operation is performed according to the IEC/IEEE | Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC float128 float128_sub( float128 a, float128 b ) { flag aSign, bSign; aSign = extractFloat128Sign( a ); bSign = extractFloat128Sign( b ); if ( aSign == bSign ) { return subFloat128Sigs( a, b, aSign ); } else { return addFloat128Sigs( a, b, aSign ); } } /*---------------------------------------------------------------------------- | Returns the result of multiplying the quadruple-precision floating-point | values `a' and `b'. The operation is performed according to the IEC/IEEE | Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC float128 float128_mul( float128 a, float128 b ) { flag aSign, bSign, zSign; si5r aExp, bExp, zExp; ui6b aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; float128 z; aSig1 = extractFloat128Frac1( a ); aSig0 = extractFloat128Frac0( a ); aExp = extractFloat128Exp( a ); aSign = extractFloat128Sign( a ); bSig1 = extractFloat128Frac1( b ); bSig0 = extractFloat128Frac0( b ); bExp = extractFloat128Exp( b ); bSign = extractFloat128Sign( b ); zSign = aSign ^ bSign; if ( aExp == 0x7FFF ) { if ( ( aSig0 | aSig1 ) || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { return propagateFloat128NaN( a, b ); } if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid; return packFloat128( zSign, 0x7FFF, 0, 0 ); } if ( bExp == 0x7FFF ) { if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); if ( ( aExp | aSig0 | aSig1 ) == 0 ) { invalid: float_raise( float_flag_invalid ); z.low = float128_default_nan_low; z.high = float128_default_nan_high; return z; } return packFloat128( zSign, 0x7FFF, 0, 0 ); } if ( aExp == 0 ) { if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); } if ( bExp == 0 ) { if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); } zExp = aExp + bExp - 0x4000; aSig0 |= LIT64( 0x0001000000000000 ); shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 ); mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 ); add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 ); zSig2 |= ( zSig3 != 0 ); if ( LIT64( 0x0002000000000000 ) <= zSig0 ) { shift128ExtraRightJamming( zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); ++zExp; } return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); } /*---------------------------------------------------------------------------- | Returns the result of dividing the quadruple-precision floating-point value | `a' by the corresponding value `b'. The operation is performed according to | the IEC/IEEE Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC float128 float128_div( float128 a, float128 b ) { flag aSign, bSign, zSign; si5r aExp, bExp, zExp; ui6b aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; ui6b rem0, rem1, rem2, rem3, term0, term1, term2, term3; float128 z; aSig1 = extractFloat128Frac1( a ); aSig0 = extractFloat128Frac0( a ); aExp = extractFloat128Exp( a ); aSign = extractFloat128Sign( a ); bSig1 = extractFloat128Frac1( b ); bSig0 = extractFloat128Frac0( b ); bExp = extractFloat128Exp( b ); bSign = extractFloat128Sign( b ); zSign = aSign ^ bSign; if ( aExp == 0x7FFF ) { if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); if ( bExp == 0x7FFF ) { if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); goto invalid; } return packFloat128( zSign, 0x7FFF, 0, 0 ); } if ( bExp == 0x7FFF ) { if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); return packFloat128( zSign, 0, 0, 0 ); } if ( bExp == 0 ) { if ( ( bSig0 | bSig1 ) == 0 ) { if ( ( aExp | aSig0 | aSig1 ) == 0 ) { invalid: float_raise( float_flag_invalid ); z.low = float128_default_nan_low; z.high = float128_default_nan_high; return z; } float_raise( float_flag_divbyzero ); return packFloat128( zSign, 0x7FFF, 0, 0 ); } normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); } if ( aExp == 0 ) { if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); } zExp = aExp - bExp + 0x3FFD; shortShift128Left( aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 ); shortShift128Left( bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) { shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 ); ++zExp; } zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 ); mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 ); sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 ); while ( (si6b) rem0 < 0 ) { --zSig0; add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 ); } zSig1 = estimateDiv128To64( rem1, rem2, bSig0 ); if ( ( zSig1 & 0x3FFF ) <= 4 ) { mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 ); sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 ); while ( (si6b) rem1 < 0 ) { --zSig1; add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 ); } zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); } shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 ); return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); } #endif typedef unsigned int float32; /*---------------------------------------------------------------------------- | Normalizes the subnormal single-precision floating-point value represented | by the denormalized significand `aSig'. The normalized exponent and | significand are stored at the locations pointed to by `zExpPtr' and | `zSigPtr', respectively. *----------------------------------------------------------------------------*/ LOCALPROC normalizeFloat32Subnormal( ui5b aSig, si4r *zExpPtr, ui5b *zSigPtr ) { si3r shiftCount; shiftCount = countLeadingZeros32( aSig ) - 8; *zSigPtr = aSig<>23 ) & 0xFF; } /*---------------------------------------------------------------------------- | Returns the sign bit of the single-precision floating-point value `a'. *----------------------------------------------------------------------------*/ LOCALINLINEFUNC flag extractFloat32Sign( float32 a ) { return a>>31; } /*---------------------------------------------------------------------------- | Returns 1 if the single-precision floating-point value `a' is a signaling | NaN; otherwise returns 0. *----------------------------------------------------------------------------*/ LOCALFUNC flag float32_is_signaling_nan( float32 a ) { return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); } /*---------------------------------------------------------------------------- | Returns the result of converting the single-precision floating-point NaN | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ LOCALFUNC commonNaNT float32ToCommonNaN( float32 a ) { commonNaNT z; if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); z.sign = a>>31; z.low = 0; z.high = ( (ui6b) a )<<41; return z; } /*---------------------------------------------------------------------------- | Returns the result of converting the single-precision floating-point value | `a' to the extended double-precision floating-point format. The conversion | is performed according to the IEC/IEEE Standard for Binary Floating-Point | Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC floatx80 float32_to_floatx80( float32 a ) { flag aSign; si4r aExp; ui5b aSig; aSig = extractFloat32Frac( a ); aExp = extractFloat32Exp( a ); aSign = extractFloat32Sign( a ); if ( aExp == 0xFF ) { if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a ) ); return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); } if ( aExp == 0 ) { if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); normalizeFloat32Subnormal( aSig, &aExp, &aSig ); } aSig |= 0x00800000; return packFloatx80( aSign, aExp + 0x3F80, ( (ui6b) aSig )<<40 ); } /*---------------------------------------------------------------------------- | Packs the sign `zSign', exponent `zExp', and significand `zSig' into a | single-precision floating-point value, returning the result. After being | shifted into the proper positions, the three fields are simply added | together to form the result. This means that any integer portion of `zSig' | will be added into the exponent. Since a properly normalized significand | will have an integer portion equal to 1, the `zExp' input should be 1 less | than the desired result exponent whenever `zSig' is a complete, normalized | significand. *----------------------------------------------------------------------------*/ LOCALINLINEFUNC float32 packFloat32( flag zSign, si4r zExp, ui5b zSig ) { return ( ( (ui5b) zSign )<<31 ) + ( ( (ui5b) zExp )<<23 ) + zSig; } /*---------------------------------------------------------------------------- | Takes an abstract floating-point value having sign `zSign', exponent `zExp', | and significand `zSig', and returns the proper single-precision floating- | point value corresponding to the abstract input. Ordinarily, the abstract | value is simply rounded and packed into the single-precision format, with | the inexact exception raised if the abstract input cannot be represented | exactly. However, if the abstract value is too large, the overflow and | inexact exceptions are raised and an infinity or maximal finite value is | returned. If the abstract value is too small, the input value is rounded to | a subnormal number, and the underflow and inexact exceptions are raised if | the abstract input cannot be represented exactly as a subnormal single- | precision floating-point number. | The input significand `zSig' has its binary point between bits 30 | and 29, which is 7 bits to the left of the usual location. This shifted | significand must be normalized or smaller. If `zSig' is not normalized, | `zExp' must be 0; in that case, the result returned is a subnormal number, | and it must not require rounding. In the usual case that `zSig' is | normalized, `zExp' must be 1 less than the ``true'' floating-point exponent. | The handling of underflow and overflow follows the IEC/IEEE Standard for | Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC float32 roundAndPackFloat32( flag zSign, si4r zExp, ui5b zSig ) { si3r roundingMode; flag roundNearestEven; si3r roundIncrement, roundBits; flag isTiny; roundingMode = float_rounding_mode; roundNearestEven = ( roundingMode == float_round_nearest_even ); roundIncrement = 0x40; if ( ! roundNearestEven ) { if ( roundingMode == float_round_to_zero ) { roundIncrement = 0; } else { roundIncrement = 0x7F; if ( zSign ) { if ( roundingMode == float_round_up ) roundIncrement = 0; } else { if ( roundingMode == float_round_down ) roundIncrement = 0; } } } roundBits = zSig & 0x7F; if ( 0xFD <= (ui4b) zExp ) { if ( ( 0xFD < zExp ) || ( ( zExp == 0xFD ) && ( (si5b) ( zSig + roundIncrement ) < 0 ) ) ) { float_raise( float_flag_overflow | float_flag_inexact ); return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 ); } if ( zExp < 0 ) { isTiny = ( float_detect_tininess == float_tininess_before_rounding ) || ( zExp < -1 ) || ( zSig + roundIncrement < 0x80000000 ); shift32RightJamming( zSig, - zExp, &zSig ); zExp = 0; roundBits = zSig & 0x7F; if ( isTiny && roundBits ) float_raise( float_flag_underflow ); } } if ( roundBits ) float_exception_flags |= float_flag_inexact; zSig = ( zSig + roundIncrement )>>7; zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); if ( zSig == 0 ) zExp = 0; return packFloat32( zSign, zExp, zSig ); } /*---------------------------------------------------------------------------- | Returns the result of converting the canonical NaN `a' to the single- | precision floating-point format. *----------------------------------------------------------------------------*/ LOCALFUNC float32 commonNaNToFloat32( commonNaNT a ) { return ( ( (ui5b) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); } /*---------------------------------------------------------------------------- | Returns the result of converting the extended double-precision floating- | point value `a' to the single-precision floating-point format. The | conversion is performed according to the IEC/IEEE Standard for Binary | Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC float32 floatx80_to_float32( floatx80 a ) { flag aSign; si5r aExp; ui6b aSig; aSig = extractFloatx80Frac( a ); aExp = extractFloatx80Exp( a ); aSign = extractFloatx80Sign( a ); if ( aExp == 0x7FFF ) { if ( (ui6b) ( aSig<<1 ) ) { return commonNaNToFloat32( floatx80ToCommonNaN( a ) ); } return packFloat32( aSign, 0xFF, 0 ); } shift64RightJamming( aSig, 33, &aSig ); if ( aExp || aSig ) aExp -= 0x3F81; return roundAndPackFloat32( aSign, aExp, aSig ); } typedef ui6b float64; /*---------------------------------------------------------------------------- | Returns the fraction bits of the double-precision floating-point value `a'. *----------------------------------------------------------------------------*/ LOCALINLINEFUNC ui6b extractFloat64Frac( float64 a ) { return a & LIT64( 0x000FFFFFFFFFFFFF ); } /*---------------------------------------------------------------------------- | Returns the exponent bits of the double-precision floating-point value `a'. *----------------------------------------------------------------------------*/ LOCALINLINEFUNC si4r extractFloat64Exp( float64 a ) { return ( a>>52 ) & 0x7FF; } /*---------------------------------------------------------------------------- | Returns the sign bit of the double-precision floating-point value `a'. *----------------------------------------------------------------------------*/ LOCALINLINEFUNC flag extractFloat64Sign( float64 a ) { return a>>63; } /*---------------------------------------------------------------------------- | Returns 1 if the double-precision floating-point value `a' is a signaling | NaN; otherwise returns 0. *----------------------------------------------------------------------------*/ LOCALFUNC flag float64_is_signaling_nan( float64 a ) { return ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); } /*---------------------------------------------------------------------------- | Returns the result of converting the double-precision floating-point NaN | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ LOCALFUNC commonNaNT float64ToCommonNaN( float64 a ) { commonNaNT z; if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); z.sign = a>>63; z.low = 0; z.high = a<<12; return z; } /*---------------------------------------------------------------------------- | Normalizes the subnormal double-precision floating-point value represented | by the denormalized significand `aSig'. The normalized exponent and | significand are stored at the locations pointed to by `zExpPtr' and | `zSigPtr', respectively. *----------------------------------------------------------------------------*/ LOCALPROC normalizeFloat64Subnormal( ui6b aSig, si4r *zExpPtr, ui6b *zSigPtr ) { si3r shiftCount; shiftCount = countLeadingZeros64( aSig ) - 11; *zSigPtr = aSig<>10; zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven ); if ( zSig == 0 ) zExp = 0; return packFloat64( zSign, zExp, zSig ); } /*---------------------------------------------------------------------------- | Returns the result of converting the canonical NaN `a' to the double- | precision floating-point format. *----------------------------------------------------------------------------*/ LOCALFUNC float64 commonNaNToFloat64( commonNaNT a ) { return ( ( (ui6b) a.sign )<<63 ) | LIT64( 0x7FF8000000000000 ) | ( a.high>>12 ); } /*---------------------------------------------------------------------------- | Returns the result of converting the extended double-precision floating- | point value `a' to the double-precision floating-point format. The | conversion is performed according to the IEC/IEEE Standard for Binary | Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC float64 floatx80_to_float64( floatx80 a ) { flag aSign; si5r aExp; ui6b aSig, zSig; aSig = extractFloatx80Frac( a ); aExp = extractFloatx80Exp( a ); aSign = extractFloatx80Sign( a ); if ( aExp == 0x7FFF ) { if ( (ui6b) ( aSig<<1 ) ) { return commonNaNToFloat64( floatx80ToCommonNaN( a ) ); } return packFloat64( aSign, 0x7FF, 0 ); } shift64RightJamming( aSig, 1, &zSig ); if ( aExp || aSig ) aExp -= 0x3C01; return roundAndPackFloat64( aSign, aExp, zSig ); } /* ----- end from original file "softfloat.c" ----- */ typedef si4r Bit16s; typedef si5r Bit32s; typedef si6r Bit64s; typedef ui5r Bit32u; typedef ui6r Bit64u; #define int16_indefinite 0x8000 /*---------------------------------------------------------------------------- | Takes extended double-precision floating-point NaN `a' and returns the | appropriate NaN result. If `a' is a signaling NaN, the invalid exception | is raised. *----------------------------------------------------------------------------*/ LOCALFUNC floatx80 propagateOneFloatx80NaN(floatx80 *a) { if (floatx80_is_signaling_nan(*a)) float_raise(float_flag_invalid); a->low |= LIT64(0xC000000000000000); return *a; } #define float_flag_denormal 0x02 #define floatx80_default_nan_exp 0xFFFF #define floatx80_default_nan_fraction LIT64(0xC000000000000000) #define packFloatx80m(zSign, zExp, zSig) {(zSig), ((zSign) << 15) + (zExp) } /*---------------------------------------------------------------------------- | Packs two 64-bit precision integers into into the quadruple-precision | floating-point value, returning the result. *----------------------------------------------------------------------------*/ #define packFloat2x128m(zHi, zLo) {(zLo), (zHi)} #define PACK_FLOAT_128(hi,lo) packFloat2x128m(LIT64(hi),LIT64(lo)) static const floatx80 floatx80_default_nan = packFloatx80m(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); /*---------------------------------------------------------------------------- | Software IEC/IEEE floating-point ordering relations *----------------------------------------------------------------------------*/ enum { float_relation_less = -1, float_relation_equal = 0, float_relation_greater = 1, float_relation_unordered = 2 }; #define EXP_BIAS 0x3FFF /*---------------------------------------------------------------------------- | Returns the result of multiplying the extended double-precision floating- | point value `a' and quadruple-precision floating point value `b'. The | operation is performed according to the IEC/IEEE Standard for Binary | Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC floatx80 floatx80_mul128(floatx80 a, float128 b) { Bit32s aExp, bExp, zExp; Bit64u aSig, bSig0, bSig1, zSig0, zSig1, zSig2; int aSign, bSign, zSign; // handle unsupported extended double-precision floating encodings if (0 /* floatx80_is_unsupported(a) */) { invalid: float_raise(float_flag_invalid); return floatx80_default_nan; } aSig = extractFloatx80Frac(a); aExp = extractFloatx80Exp(a); aSign = extractFloatx80Sign(a); bSig0 = extractFloat128Frac0(b); bSig1 = extractFloat128Frac1(b); bExp = extractFloat128Exp(b); bSign = extractFloat128Sign(b); zSign = aSign ^ bSign; if (aExp == 0x7FFF) { if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (bSig0 | bSig1))) { floatx80 r = commonNaNToFloatx80(float128ToCommonNaN(b)); return propagateFloatx80NaN(a, r); } if (bExp == 0) { if ((bSig0 | bSig1) == 0) goto invalid; float_raise(float_flag_denormal); } return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000)); } if (bExp == 0x7FFF) { if (bSig0 | bSig1) { floatx80 r = commonNaNToFloatx80(float128ToCommonNaN(b)); return propagateFloatx80NaN(a, r); } if (aExp == 0) { if (aSig == 0) goto invalid; float_raise(float_flag_denormal); } return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000)); } if (aExp == 0) { if (aSig == 0) { if ((bExp == 0) && (bSig0 | bSig1)) float_raise(float_flag_denormal); return packFloatx80(zSign, 0, 0); } float_raise(float_flag_denormal); normalizeFloatx80Subnormal(aSig, &aExp, &aSig); } if (bExp == 0) { if ((bSig0 | bSig1) == 0) return packFloatx80(zSign, 0, 0); float_raise(float_flag_denormal); normalizeFloat128Subnormal(bSig0, bSig1, &bExp, &bSig0, &bSig1); } else bSig0 |= LIT64(0x0001000000000000); zExp = aExp + bExp - 0x3FFE; shortShift128Left(bSig0, bSig1, 15, &bSig0, &bSig1); mul128By64To192(bSig0, bSig1, aSig, &zSig0, &zSig1, &zSig2); if (0 < (Bit64s) zSig0) { shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); --zExp; } return roundAndPackFloatx80(floatx80_rounding_precision, zSign, zExp, zSig0, zSig1); } /* ----- from original file "softfloatx80.h" ----- */ /* ["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.] */ /*---------------------------------------------------------------------------- | Software IEC/IEEE floating-point class. *----------------------------------------------------------------------------*/ typedef enum { float_zero, float_NaN, float_negative_inf, float_positive_inf, float_denormal, float_normalized } float_class_t; /*----------------------------------------------------------------------------- | Calculates the absolute value of the extended double-precision floating-point | value `a'. The operation is performed according to the IEC/IEEE Standard | for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ #if 0 inline floatx80 floatx80_abs(floatx80 *reg) { reg->high &= 0x7FFF; return *reg; } #endif /*----------------------------------------------------------------------------- | Changes the sign of the extended double-precision floating-point value 'a'. | The operation is performed according to the IEC/IEEE Standard for Binary | Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC floatx80 floatx80_chs(floatx80 *x) { x->high ^= 0x8000; return *x; } /* ----- end from original file "softfloatx80.h" ----- */ /* ----- from original file "softfloatx80.cc" ----- */ /* ["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.] */ /*---------------------------------------------------------------------------- | Returns the result of converting the extended double-precision floating- | point value `a' to the 16-bit two's complement integer format. The | conversion is performed according to the IEC/IEEE Standard for Binary | Floating-Point Arithmetic - which means in particular that the conversion | is rounded according to the current rounding mode. If `a' is a NaN or the | conversion overflows, the integer indefinite value is returned. *----------------------------------------------------------------------------*/ #if cIncludeFPUUnused LOCALFUNC Bit16s floatx80_to_int16(floatx80 a) { #if 0 if (floatx80_is_unsupported(a)) { float_raise(float_flag_invalid); return int16_indefinite; } #endif Bit32s v32 = floatx80_to_int32(a); if ((v32 > 32767) || (v32 < -32768)) { float_exception_flags = float_flag_invalid; // throw way other flags return int16_indefinite; } return (Bit16s) v32; } #endif /*---------------------------------------------------------------------------- | Returns the result of converting the extended double-precision floating- | point value `a' to the 16-bit two's complement integer format. The | conversion is performed according to the IEC/IEEE Standard for Binary | Floating-Point Arithmetic, except that the conversion is always rounded | toward zero. If `a' is a NaN or the conversion overflows, the integer | indefinite value is returned. *----------------------------------------------------------------------------*/ #if cIncludeFPUUnused LOCALFUNC Bit16s floatx80_to_int16_round_to_zero(floatx80 a) { #if 0 if (floatx80_is_unsupported(a)) { float_raise(float_flag_invalid); return int16_indefinite; } #endif Bit32s v32 = floatx80_to_int32_round_to_zero(a); if ((v32 > 32767) || (v32 < -32768)) { float_exception_flags = float_flag_invalid; // throw way other flags return int16_indefinite; } return (Bit16s) v32; } #endif /*---------------------------------------------------------------------------- | Separate the source extended double-precision floating point value `a' | into its exponent and significand, store the significant back to the | 'a' and return the exponent. The operation performed is a superset of | the IEC/IEEE recommended logb(x) function. *----------------------------------------------------------------------------*/ LOCALFUNC floatx80 floatx80_extract(floatx80 *a) { Bit64u aSig = extractFloatx80Frac(*a); Bit32s aExp = extractFloatx80Exp(*a); int aSign = extractFloatx80Sign(*a); #if 0 if (floatx80_is_unsupported(*a)) { float_raise(float_flag_invalid); *a = floatx80_default_nan; return *a; } #endif if (aExp == 0x7FFF) { if ((Bit64u) (aSig<<1)) { *a = propagateOneFloatx80NaN(a); return *a; } return packFloatx80(0, 0x7FFF, LIT64(0x8000000000000000)); } if (aExp == 0) { if (aSig == 0) { float_raise(float_flag_divbyzero); *a = packFloatx80(aSign, 0, 0); return packFloatx80(1, 0x7FFF, LIT64(0x8000000000000000)); } float_raise(float_flag_denormal); normalizeFloatx80Subnormal(aSig, &aExp, &aSig); } a->high = (aSign << 15) + 0x3FFF; a->low = aSig; return int32_to_floatx80(aExp - 0x3FFF); } /*---------------------------------------------------------------------------- | Scales extended double-precision floating-point value in operand `a' by | value `b'. The function truncates the value in the second operand 'b' to | an integral value and adds that value to the exponent of the operand 'a'. | The operation performed according to the IEC/IEEE Standard for Binary | Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ LOCALFUNC floatx80 floatx80_scale(floatx80 a, floatx80 b) { int shiftCount; Bit32s scale; // handle unsupported extended double-precision floating encodings #if 0 if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) { float_raise(float_flag_invalid); return floatx80_default_nan; } #endif Bit64u aSig = extractFloatx80Frac(a); Bit32s aExp = extractFloatx80Exp(a); int aSign = extractFloatx80Sign(a); Bit64u bSig = extractFloatx80Frac(b); Bit32s bExp = extractFloatx80Exp(b); int bSign = extractFloatx80Sign(b); if (aExp == 0x7FFF) { if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) { return propagateFloatx80NaN(a, b); } if ((bExp == 0x7FFF) && bSign) { float_raise(float_flag_invalid); return floatx80_default_nan; } if (bSig && (bExp == 0)) float_raise(float_flag_denormal); return a; } if (bExp == 0x7FFF) { if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b); if ((aExp | aSig) == 0) { if (! bSign) { float_raise(float_flag_invalid); return floatx80_default_nan; } return a; } if (aSig && (aExp == 0)) float_raise(float_flag_denormal); if (bSign) return packFloatx80(aSign, 0, 0); return packFloatx80(aSign, 0x7FFF, LIT64(0x8000000000000000)); } if (aExp == 0) { if (bSig && (bExp == 0)) float_raise(float_flag_denormal); if (aSig == 0) return a; float_raise(float_flag_denormal); normalizeFloatx80Subnormal(aSig, &aExp, &aSig); if (bExp < 0x3FFF) return normalizeRoundAndPackFloatx80(80, aSign, aExp, aSig, 0); } if (bExp == 0) { if (bSig == 0) return a; float_raise(float_flag_denormal); normalizeFloatx80Subnormal(bSig, &bExp, &bSig); } if (bExp > 0x400E) { /* generate appropriate overflow/underflow */ return roundAndPackFloatx80(80, aSign, bSign ? -0x3FFF : 0x7FFF, aSig, 0); } if (bExp < 0x3FFF) return a; shiftCount = 0x403E - bExp; bSig >>= shiftCount; scale = (Bit32s) bSig; if (bSign) scale = -scale; /* -32768..32767 */ return roundAndPackFloatx80(80, aSign, aExp+scale, aSig, 0); } /*---------------------------------------------------------------------------- | Determine extended-precision floating-point number class. *----------------------------------------------------------------------------*/ #if cIncludeFPUUnused LOCALFUNC float_class_t floatx80_class(floatx80 a) { Bit32s aExp = extractFloatx80Exp(a); Bit64u aSig = extractFloatx80Frac(a); if(aExp == 0) { if (aSig == 0) return float_zero; /* denormal or pseudo-denormal */ return float_denormal; } /* valid numbers have the MS bit set */ if (!(aSig & LIT64(0x8000000000000000))) return float_NaN; /* report unsupported as NaNs */ if(aExp == 0x7fff) { int aSign = extractFloatx80Sign(a); if (((Bit64u) (aSig<< 1)) == 0) return (aSign) ? float_negative_inf : float_positive_inf; return float_NaN; } return float_normalized; } #endif /*---------------------------------------------------------------------------- | Compare between two extended precision floating point numbers. Returns | 'float_relation_equal' if the operands are equal, 'float_relation_less' if | the value 'a' is less than the corresponding value `b', | 'float_relation_greater' if the value 'a' is greater than the corresponding | value `b', or 'float_relation_unordered' otherwise. *----------------------------------------------------------------------------*/ #if cIncludeFPUUnused LOCALFUNC int floatx80_compare(floatx80 a, floatx80 b) { int aSign; int bSign; Bit64u aSig; Bit32s aExp; Bit64u bSig; Bit32s bExp; int less_than; float_class_t aClass = floatx80_class(a); float_class_t bClass = floatx80_class(b); if (aClass == float_NaN || bClass == float_NaN) { float_raise(float_flag_invalid); return float_relation_unordered; } if (aClass == float_denormal || bClass == float_denormal) { float_raise(float_flag_denormal); } aSign = extractFloatx80Sign(a); bSign = extractFloatx80Sign(b); if (aClass == float_zero) { if (bClass == float_zero) return float_relation_equal; return bSign ? float_relation_greater : float_relation_less; } if (bClass == float_zero || aSign != bSign) { return aSign ? float_relation_less : float_relation_greater; } aSig = extractFloatx80Frac(a); aExp = extractFloatx80Exp(a); bSig = extractFloatx80Frac(b); bExp = extractFloatx80Exp(b); if (aClass == float_denormal) normalizeFloatx80Subnormal(aSig, &aExp, &aSig); if (bClass == float_denormal) normalizeFloatx80Subnormal(bSig, &bExp, &bSig); if (aExp == bExp && aSig == bSig) return float_relation_equal; less_than = aSign ? ((bExp < aExp) || ((bExp == aExp) && (bSig < aSig))) : ((aExp < bExp) || ((aExp == bExp) && (aSig < bSig))); if (less_than) return float_relation_less; return float_relation_greater; } #endif /*---------------------------------------------------------------------------- | Compare between two extended precision floating point numbers. Returns | 'float_relation_equal' if the operands are equal, 'float_relation_less' if | the value 'a' is less than the corresponding value `b', | 'float_relation_greater' if the value 'a' is greater than the corresponding | value `b', or 'float_relation_unordered' otherwise. Quiet NaNs do not cause | an exception. *----------------------------------------------------------------------------*/ #if cIncludeFPUUnused LOCALFUNC int floatx80_compare_quiet(floatx80 a, floatx80 b) { int aSign; int bSign; Bit64u aSig; Bit32s aExp; Bit64u bSig; Bit32s bExp; int less_than; float_class_t aClass = floatx80_class(a); float_class_t bClass = floatx80_class(b); if (aClass == float_NaN || bClass == float_NaN) { #if 0 if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) float_raise(float_flag_invalid); #endif if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) float_raise(float_flag_invalid); return float_relation_unordered; } if (aClass == float_denormal || bClass == float_denormal) { float_raise(float_flag_denormal); } aSign = extractFloatx80Sign(a); bSign = extractFloatx80Sign(b); if (aClass == float_zero) { if (bClass == float_zero) return float_relation_equal; return bSign ? float_relation_greater : float_relation_less; } if (bClass == float_zero || aSign != bSign) { return aSign ? float_relation_less : float_relation_greater; } aSig = extractFloatx80Frac(a); aExp = extractFloatx80Exp(a); bSig = extractFloatx80Frac(b); bExp = extractFloatx80Exp(b); if (aClass == float_denormal) normalizeFloatx80Subnormal(aSig, &aExp, &aSig); if (bClass == float_denormal) normalizeFloatx80Subnormal(bSig, &bExp, &bSig); if (aExp == bExp && aSig == bSig) return float_relation_equal; less_than = aSign ? ((bExp < aExp) || ((bExp == aExp) && (bSig < aSig))) : ((aExp < bExp) || ((aExp == bExp) && (aSig < bSig))); if (less_than) return float_relation_less; return float_relation_greater; } #endif /* ----- end from original file "softfloatx80.cc" ----- */ /* ----- from original file "fprem.cc" ----- */ /* ["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.] */ #define USE_estimateDiv128To64 /* executes single exponent reduction cycle */ LOCALFUNC Bit64u remainder_kernel(Bit64u aSig0, Bit64u bSig, int expDiff, Bit64u *zSig0, Bit64u *zSig1) { Bit64u term0, term1; Bit64u aSig1 = 0; Bit64u q; shortShift128Left(aSig1, aSig0, expDiff, &aSig1, &aSig0); q = estimateDiv128To64(aSig1, aSig0, bSig); mul64To128(bSig, q, &term0, &term1); sub128(aSig1, aSig0, term0, term1, zSig1, zSig0); while ((Bit64s)(*zSig1) < 0) { --q; add128(*zSig1, *zSig0, 0, bSig, zSig1, zSig0); } return q; } LOCALFUNC floatx80 do_fprem(floatx80 a, floatx80 b, Bit64u *q, int rounding_mode) { Bit32s aExp, bExp, zExp, expDiff; Bit64u aSig0, aSig1, bSig; int aSign; *q = 0; #if 0 // handle unsupported extended double-precision floating encodings if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) { float_raise(float_flag_invalid); return floatx80_default_nan; } #endif aSig0 = extractFloatx80Frac(a); aExp = extractFloatx80Exp(a); aSign = extractFloatx80Sign(a); bSig = extractFloatx80Frac(b); bExp = extractFloatx80Exp(b); if (aExp == 0x7FFF) { if ((Bit64u) (aSig0<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) { return propagateFloatx80NaN(a, b); } float_raise(float_flag_invalid); return floatx80_default_nan; } if (bExp == 0x7FFF) { if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b); if (aExp == 0 && aSig0) { float_raise(float_flag_denormal); normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); return (a.low & LIT64(0x8000000000000000)) ? packFloatx80(aSign, aExp, aSig0) : a; } return a; } if (bExp == 0) { if (bSig == 0) { float_raise(float_flag_invalid); return floatx80_default_nan; } float_raise(float_flag_denormal); normalizeFloatx80Subnormal(bSig, &bExp, &bSig); } if (aExp == 0) { if (aSig0 == 0) return a; float_raise(float_flag_denormal); normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); } expDiff = aExp - bExp; aSig1 = 0; if (expDiff >= 64) { int n = (expDiff & 0x1f) | 0x20; remainder_kernel(aSig0, bSig, n, &aSig0, &aSig1); zExp = aExp - n; *q = (Bit64u) -1; } else { zExp = bExp; if (expDiff < 0) { if (expDiff < -1) return (a.low & LIT64(0x8000000000000000)) ? packFloatx80(aSign, aExp, aSig0) : a; shift128Right(aSig0, 0, 1, &aSig0, &aSig1); expDiff = 0; } if (expDiff > 0) { *q = remainder_kernel(aSig0, bSig, expDiff, &aSig0, &aSig1); } else { if (bSig <= aSig0) { aSig0 -= bSig; *q = 1; } } if (rounding_mode == float_round_nearest_even) { Bit64u term0, term1; shift128Right(bSig, 0, 1, &term0, &term1); if (! lt128(aSig0, aSig1, term0, term1)) { int lt = lt128(term0, term1, aSig0, aSig1); int eq = eq128(aSig0, aSig1, term0, term1); if ((eq && (*q & 1)) || lt) { aSign = !aSign; ++*q; } if (lt) sub128(bSig, 0, aSig0, aSig1, &aSig0, &aSig1); } } } return normalizeRoundAndPackFloatx80(80, aSign, zExp, aSig0, aSig1); } /*---------------------------------------------------------------------------- | Returns the remainder of the extended double-precision floating-point value | `a' with respect to the corresponding value `b'. The operation is performed | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ #if cIncludeFPUUnused LOCALFUNC floatx80 floatx80_ieee754_remainder(floatx80 a, floatx80 b, Bit64u *q) { return do_fprem(a, b, q, float_round_nearest_even); } #endif /*---------------------------------------------------------------------------- | Returns the remainder of the extended double-precision floating-point value | `a' with respect to the corresponding value `b'. Unlike previous function | the function does not compute the remainder specified in the IEC/IEEE | Standard for Binary Floating-Point Arithmetic. This function operates | differently from the previous function in the way that it rounds the | quotient of 'a' divided by 'b' to an integer. *----------------------------------------------------------------------------*/ LOCALFUNC floatx80 floatx80_remainder(floatx80 a, floatx80 b, Bit64u *q) { return do_fprem(a, b, q, float_round_to_zero); } /* ----- end from original file "fprem.cc" ----- */ /* ----- from original file "fpu_constant.h" ----- */ /* ["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.] */ // Pentium CPU uses only 68-bit precision M_PI approximation // #define BETTER_THAN_PENTIUM ////////////////////////////// // PI, PI/2, PI/4 constants ////////////////////////////// #define FLOATX80_PI_EXP (0x4000) // 128-bit PI fraction #ifdef BETTER_THAN_PENTIUM #define FLOAT_PI_HI (LIT64(0xc90fdaa22168c234)) #define FLOAT_PI_LO (LIT64(0xc4c6628b80dc1cd1)) #else #define FLOAT_PI_HI (LIT64(0xc90fdaa22168c234)) #define FLOAT_PI_LO (LIT64(0xC000000000000000)) #endif #define FLOATX80_PI2_EXP (0x3FFF) #define FLOATX80_PI4_EXP (0x3FFE) ////////////////////////////// // 3PI/4 constant ////////////////////////////// #define FLOATX80_3PI4_EXP (0x4000) // 128-bit 3PI/4 fraction #ifdef BETTER_THAN_PENTIUM #define FLOAT_3PI4_HI (LIT64(0x96cbe3f9990e91a7)) #define FLOAT_3PI4_LO (LIT64(0x9394c9e8a0a5159c)) #else #define FLOAT_3PI4_HI (LIT64(0x96cbe3f9990e91a7)) #define FLOAT_3PI4_LO (LIT64(0x9000000000000000)) #endif ////////////////////////////// // 1/LN2 constant ////////////////////////////// #define FLOAT_LN2INV_EXP (0x3FFF) // 128-bit 1/LN2 fraction #ifdef BETTER_THAN_PENTIUM #define FLOAT_LN2INV_HI (LIT64(0xb8aa3b295c17f0bb)) #define FLOAT_LN2INV_LO (LIT64(0xbe87fed0691d3e89)) #else #define FLOAT_LN2INV_HI (LIT64(0xb8aa3b295c17f0bb)) #define FLOAT_LN2INV_LO (LIT64(0xC000000000000000)) #endif /* ----- end from original file "fpu_constant.h" ----- */ /* ----- from original file "poly.cc" ----- */ /* ["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.] */ // 2 3 4 n // f(x) ~ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) // 0 1 2 3 4 n // // -- 2k -- 2k+1 // p(x) = > C * x q(x) = > C * x // -- 2k -- 2k+1 // // f(x) ~ [ p(x) + x * q(x) ] // LOCALFUNC float128 EvalPoly(float128 x, float128 *arr, unsigned n) { float128 r2; float128 x2 = float128_mul(x, x); unsigned i; #if 0 assert(n > 1); #endif float128 r1 = arr[--n]; i = n; while(i >= 2) { r1 = float128_mul(r1, x2); i -= 2; r1 = float128_add(r1, arr[i]); } if (i) r1 = float128_mul(r1, x); r2 = arr[--n]; i = n; while(i >= 2) { r2 = float128_mul(r2, x2); i -= 2; r2 = float128_add(r2, arr[i]); } if (i) r2 = float128_mul(r2, x); return float128_add(r1, r2); } // 2 4 6 8 2n // f(x) ~ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) // 0 1 2 3 4 n // // -- 4k -- 4k+2 // p(x) = > C * x q(x) = > C * x // -- 2k -- 2k+1 // // 2 // f(x) ~ [ p(x) + x * q(x) ] // LOCALFUNC float128 EvenPoly(float128 x, float128 *arr, unsigned n) { return EvalPoly(float128_mul(x, x), arr, n); } // 3 5 7 9 2n+1 // f(x) ~ (C * x) + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) // 0 1 2 3 4 n // 2 4 6 8 2n // = x * [ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) // 0 1 2 3 4 n // // -- 4k -- 4k+2 // p(x) = > C * x q(x) = > C * x // -- 2k -- 2k+1 // // 2 // f(x) ~ x * [ p(x) + x * q(x) ] // LOCALFUNC float128 OddPoly(float128 x, float128 *arr, unsigned n) { return float128_mul(x, EvenPoly(x, arr, n)); } /* ----- end from original file "poly.cc" ----- */ /* ----- from original file "fyl2x.cc" ----- */ /* ["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.] */ static const floatx80 floatx80_one = packFloatx80m(0, 0x3fff, LIT64(0x8000000000000000)); static const float128 float128_one = packFloat2x128m(LIT64(0x3fff000000000000), LIT64(0x0000000000000000)); static const float128 float128_two = packFloat2x128m(LIT64(0x4000000000000000), LIT64(0x0000000000000000)); static const float128 float128_ln2inv2 = packFloat2x128m(LIT64(0x400071547652b82f), LIT64(0xe1777d0ffda0d23a)); #define SQRT2_HALF_SIG LIT64(0xb504f333f9de6484) #define L2_ARR_SIZE 9 static float128 ln_arr[L2_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ PACK_FLOAT_128(0x3ffd555555555555, 0x5555555555555555), /* 3 */ PACK_FLOAT_128(0x3ffc999999999999, 0x999999999999999a), /* 5 */ PACK_FLOAT_128(0x3ffc249249249249, 0x2492492492492492), /* 7 */ PACK_FLOAT_128(0x3ffbc71c71c71c71, 0xc71c71c71c71c71c), /* 9 */ PACK_FLOAT_128(0x3ffb745d1745d174, 0x5d1745d1745d1746), /* 11 */ PACK_FLOAT_128(0x3ffb3b13b13b13b1, 0x3b13b13b13b13b14), /* 13 */ PACK_FLOAT_128(0x3ffb111111111111, 0x1111111111111111), /* 15 */ PACK_FLOAT_128(0x3ffae1e1e1e1e1e1, 0xe1e1e1e1e1e1e1e2) /* 17 */ }; LOCALFUNC float128 poly_ln(float128 x1) { /* // // 3 5 7 9 11 13 15 // 1+u u u u u u u u // 1/2 ln --- ~ u + --- + --- + --- + --- + ---- + ---- + ---- = // 1-u 3 5 7 9 11 13 15 // // 2 4 6 8 10 12 14 // u u u u u u u // = u * [ 1 + --- + --- + --- + --- + ---- + ---- + ---- ] = // 3 5 7 9 11 13 15 // // 3 3 // -- 4k -- 4k+2 // p(u) = > C * u q(u) = > C * u // -- 2k -- 2k+1 // k=0 k=0 // // 1+u 2 // 1/2 ln --- ~ u * [ p(u) + u * q(u) ] // 1-u // */ return OddPoly(x1, ln_arr, L2_ARR_SIZE); } /* required sqrt(2)/2 < x < sqrt(2) */ LOCALFUNC float128 poly_l2(float128 x) { /* using float128 for approximation */ float128 x_p1 = float128_add(x, float128_one); float128 x_m1 = float128_sub(x, float128_one); x = float128_div(x_m1, x_p1); x = poly_ln(x); x = float128_mul(x, float128_ln2inv2); return x; } LOCALFUNC float128 poly_l2p1(float128 x) { /* using float128 for approximation */ float128 x_p2 = float128_add(x, float128_two); x = float128_div(x, x_p2); x = poly_ln(x); x = float128_mul(x, float128_ln2inv2); return x; } // ================================================= // FYL2X Compute y * log (x) // 2 // ================================================= // // Uses the following identities: // // 1. ---------------------------------------------------------- // ln(x) // log (x) = -------, ln (x*y) = ln(x) + ln(y) // 2 ln(2) // // 2. ---------------------------------------------------------- // 1+u x-1 // ln (x) = ln -----, when u = ----- // 1-u x+1 // // 3. ---------------------------------------------------------- // 3 5 7 2n+1 // 1+u u u u u // ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ] // 1-u 3 5 7 2n+1 // LOCALFUNC floatx80 fyl2x(floatx80 a, floatx80 b) { int aSign; int bSign; Bit64u aSig; Bit32s aExp; Bit64u bSig; Bit32s bExp; int zSign; int ExpDiff; Bit64u zSig0, zSig1; float128 x; // handle unsupported extended double-precision floating encodings if (0 /* floatx80_is_unsupported(a) */) { invalid: float_raise(float_flag_invalid); return floatx80_default_nan; } aSig = extractFloatx80Frac(a); aExp = extractFloatx80Exp(a); aSign = extractFloatx80Sign(a); bSig = extractFloatx80Frac(b); bExp = extractFloatx80Exp(b); bSign = extractFloatx80Sign(b); zSign = bSign ^ 1; if (aExp == 0x7FFF) { if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) { return propagateFloatx80NaN(a, b); } if (aSign) goto invalid; else { if (bExp == 0) { if (bSig == 0) goto invalid; float_raise(float_flag_denormal); } return packFloatx80(bSign, 0x7FFF, LIT64(0x8000000000000000)); } } if (bExp == 0x7FFF) { if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b); if (aSign && (Bit64u)(aExp | aSig)) goto invalid; if (aSig && (aExp == 0)) float_raise(float_flag_denormal); if (aExp < 0x3FFF) { return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000)); } if (aExp == 0x3FFF && ((Bit64u) (aSig<<1) == 0)) goto invalid; return packFloatx80(bSign, 0x7FFF, LIT64(0x8000000000000000)); } if (aExp == 0) { if (aSig == 0) { if ((bExp | bSig) == 0) goto invalid; float_raise(float_flag_divbyzero); return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000)); } if (aSign) goto invalid; float_raise(float_flag_denormal); normalizeFloatx80Subnormal(aSig, &aExp, &aSig); } if (aSign) goto invalid; if (bExp == 0) { if (bSig == 0) { if (aExp < 0x3FFF) return packFloatx80(zSign, 0, 0); return packFloatx80(bSign, 0, 0); } float_raise(float_flag_denormal); normalizeFloatx80Subnormal(bSig, &bExp, &bSig); } if (aExp == 0x3FFF && ((Bit64u) (aSig<<1) == 0)) return packFloatx80(bSign, 0, 0); float_raise(float_flag_inexact); ExpDiff = aExp - 0x3FFF; aExp = 0; if (aSig >= SQRT2_HALF_SIG) { ExpDiff++; aExp--; } /* ******************************** */ /* using float128 for approximation */ /* ******************************** */ shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); x = packFloat128(0, aExp+0x3FFF, zSig0, zSig1); x = poly_l2(x); x = float128_add(x, floatx80_to_float128(int32_to_floatx80(ExpDiff))); return floatx80_mul128(b, x); } // ================================================= // FYL2XP1 Compute y * log (x + 1) // 2 // ================================================= // // Uses the following identities: // // 1. ---------------------------------------------------------- // ln(x) // log (x) = ------- // 2 ln(2) // // 2. ---------------------------------------------------------- // 1+u x // ln (x+1) = ln -----, when u = ----- // 1-u x+2 // // 3. ---------------------------------------------------------- // 3 5 7 2n+1 // 1+u u u u u // ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ] // 1-u 3 5 7 2n+1 // LOCALFUNC floatx80 fyl2xp1(floatx80 a, floatx80 b) { Bit32s aExp, bExp; Bit64u aSig, bSig, zSig0, zSig1, zSig2; int aSign, bSign; int zSign; float128 x; // handle unsupported extended double-precision floating encodings if (0 /* floatx80_is_unsupported(a) */) { invalid: float_raise(float_flag_invalid); return floatx80_default_nan; } aSig = extractFloatx80Frac(a); aExp = extractFloatx80Exp(a); aSign = extractFloatx80Sign(a); bSig = extractFloatx80Frac(b); bExp = extractFloatx80Exp(b); bSign = extractFloatx80Sign(b); zSign = aSign ^ bSign; if (aExp == 0x7FFF) { if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) { return propagateFloatx80NaN(a, b); } if (aSign) goto invalid; else { if (bExp == 0) { if (bSig == 0) goto invalid; float_raise(float_flag_denormal); } return packFloatx80(bSign, 0x7FFF, LIT64(0x8000000000000000)); } } if (bExp == 0x7FFF) { if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b); if (aExp == 0) { if (aSig == 0) goto invalid; float_raise(float_flag_denormal); } return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000)); } if (aExp == 0) { if (aSig == 0) { if (bSig && (bExp == 0)) float_raise(float_flag_denormal); return packFloatx80(zSign, 0, 0); } float_raise(float_flag_denormal); normalizeFloatx80Subnormal(aSig, &aExp, &aSig); } if (bExp == 0) { if (bSig == 0) return packFloatx80(zSign, 0, 0); float_raise(float_flag_denormal); normalizeFloatx80Subnormal(bSig, &bExp, &bSig); } float_raise(float_flag_inexact); if (aSign && aExp >= 0x3FFF) return a; if (aExp >= 0x3FFC) // big argument { return fyl2x(floatx80_add(a, floatx80_one), b); } // handle tiny argument if (aExp < EXP_BIAS-70) { // first order approximation, return (a*b)/ln(2) Bit32s zExp = aExp + FLOAT_LN2INV_EXP - 0x3FFE; mul128By64To192(FLOAT_LN2INV_HI, FLOAT_LN2INV_LO, aSig, &zSig0, &zSig1, &zSig2); if (0 < (Bit64s) zSig0) { shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); --zExp; } zExp = zExp + bExp - 0x3FFE; mul128By64To192(zSig0, zSig1, bSig, &zSig0, &zSig1, &zSig2); if (0 < (Bit64s) zSig0) { shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); --zExp; } return roundAndPackFloatx80(80, aSign ^ bSign, zExp, zSig0, zSig1); } /* ******************************** */ /* using float128 for approximation */ /* ******************************** */ shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); x = packFloat128(aSign, aExp, zSig0, zSig1); x = poly_l2p1(x); return floatx80_mul128(b, x); } /* ----- end from original file "fyl2x.cc" ----- */ /* ----- from original file "f2xm1.cc" ----- */ /* ["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.] */ static const floatx80 floatx80_negone = packFloatx80m(1, 0x3fff, LIT64(0x8000000000000000)); static const floatx80 floatx80_neghalf = packFloatx80m(1, 0x3ffe, LIT64(0x8000000000000000)); static const float128 float128_ln2 = packFloat2x128m(LIT64(0x3ffe62e42fefa39e), LIT64(0xf35793c7673007e6)); #define LN2_SIG LIT64(0xb17217f7d1cf79ac) #define EXP_ARR_SIZE 15 static float128 exp_arr[EXP_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ PACK_FLOAT_128(0x3ffe000000000000, 0x0000000000000000), /* 2 */ PACK_FLOAT_128(0x3ffc555555555555, 0x5555555555555555), /* 3 */ PACK_FLOAT_128(0x3ffa555555555555, 0x5555555555555555), /* 4 */ PACK_FLOAT_128(0x3ff8111111111111, 0x1111111111111111), /* 5 */ PACK_FLOAT_128(0x3ff56c16c16c16c1, 0x6c16c16c16c16c17), /* 6 */ PACK_FLOAT_128(0x3ff2a01a01a01a01, 0xa01a01a01a01a01a), /* 7 */ PACK_FLOAT_128(0x3fefa01a01a01a01, 0xa01a01a01a01a01a), /* 8 */ PACK_FLOAT_128(0x3fec71de3a556c73, 0x38faac1c88e50017), /* 9 */ PACK_FLOAT_128(0x3fe927e4fb7789f5, 0xc72ef016d3ea6679), /* 10 */ PACK_FLOAT_128(0x3fe5ae64567f544e, 0x38fe747e4b837dc7), /* 11 */ PACK_FLOAT_128(0x3fe21eed8eff8d89, 0x7b544da987acfe85), /* 12 */ PACK_FLOAT_128(0x3fde6124613a86d0, 0x97ca38331d23af68), /* 13 */ PACK_FLOAT_128(0x3fda93974a8c07c9, 0xd20badf145dfa3e5), /* 14 */ PACK_FLOAT_128(0x3fd6ae7f3e733b81, 0xf11d8656b0ee8cb0) /* 15 */ }; /* required -1 < x < 1 */ LOCALFUNC float128 poly_exp(float128 x) { /* // 2 3 4 5 6 7 8 9 // x x x x x x x x x // e - 1 ~ x + --- + --- + --- + --- + --- + --- + --- + --- + ... // 2! 3! 4! 5! 6! 7! 8! 9! // // 2 3 4 5 6 7 8 // x x x x x x x x // = x [ 1 + --- + --- + --- + --- + --- + --- + --- + --- + ... ] // 2! 3! 4! 5! 6! 7! 8! 9! // // 8 8 // -- 2k -- 2k+1 // p(x) = > C * x q(x) = > C * x // -- 2k -- 2k+1 // k=0 k=0 // // x // e - 1 ~ x * [ p(x) + x * q(x) ] // */ float128 t = EvalPoly(x, exp_arr, EXP_ARR_SIZE); return float128_mul(t, x); } // ================================================= // x // FX2P1 Compute 2 - 1 // ================================================= // // Uses the following identities: // // 1. ---------------------------------------------------------- // x x*ln(2) // 2 = e // // 2. ---------------------------------------------------------- // 2 3 4 5 n // x x x x x x x // e = 1 + --- + --- + --- + --- + --- + ... + --- + ... // 1! 2! 3! 4! 5! n! // LOCALFUNC floatx80 f2xm1(floatx80 a) { Bit64u zSig0, zSig1; float128 x; #if 0 // handle unsupported extended double-precision floating encodings if (floatx80_is_unsupported(a)) { float_raise(float_flag_invalid); return floatx80_default_nan; } #endif Bit64u aSig = extractFloatx80Frac(a); Bit32s aExp = extractFloatx80Exp(a); int aSign = extractFloatx80Sign(a); if (aExp == 0x7FFF) { if ((Bit64u) (aSig<<1)) return propagateOneFloatx80NaN(&a); return (aSign) ? floatx80_negone : a; } if (aExp == 0) { if (aSig == 0) return a; float_raise(float_flag_denormal | float_flag_inexact); normalizeFloatx80Subnormal(aSig, &aExp, &aSig); tiny_argument: mul64To128(aSig, LN2_SIG, &zSig0, &zSig1); if (0 < (Bit64s) zSig0) { shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); --aExp; } return roundAndPackFloatx80(80, aSign, aExp, zSig0, zSig1); } float_raise(float_flag_inexact); if (aExp < 0x3FFF) { if (aExp < EXP_BIAS-68) goto tiny_argument; /* ******************************** */ /* using float128 for approximation */ /* ******************************** */ x = floatx80_to_float128(a); x = float128_mul(x, float128_ln2); x = poly_exp(x); return float128_to_floatx80(x); } else { if ((a.high == 0xBFFF) && (! (aSig<<1))) return floatx80_neghalf; return a; } } /* ----- end from original file "f2xm1.cc" ----- */ /* ----- from original file "fsincos.cc" ----- */ /* ["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.] */ #define USE_estimateDiv128To64 #if 0 static const floatx80 floatx80_one = packFloatx80m(0, 0x3fff, LIT64(0x8000000000000000)); #endif /* reduce trigonometric function argument using 128-bit precision M_PI approximation */ LOCALFUNC Bit64u argument_reduction_kernel(Bit64u aSig0, int Exp, Bit64u *zSig0, Bit64u *zSig1) { Bit64u term0, term1, term2; Bit64u aSig1 = 0; Bit64u q; shortShift128Left(aSig1, aSig0, Exp, &aSig1, &aSig0); q = estimateDiv128To64(aSig1, aSig0, FLOAT_PI_HI); mul128By64To192(FLOAT_PI_HI, FLOAT_PI_LO, q, &term0, &term1, &term2); sub128(aSig1, aSig0, term0, term1, zSig1, zSig0); while ((Bit64s)(*zSig1) < 0) { --q; add192(*zSig1, *zSig0, term2, 0, FLOAT_PI_HI, FLOAT_PI_LO, zSig1, zSig0, &term2); } *zSig1 = term2; return q; } LOCALFUNC int reduce_trig_arg(int expDiff, int *zSign, Bit64u *aSig0, Bit64u *aSig1) { Bit64u term0, term1, q = 0; if (expDiff < 0) { shift128Right(*aSig0, 0, 1, aSig0, aSig1); expDiff = 0; } if (expDiff > 0) { q = argument_reduction_kernel(*aSig0, expDiff, aSig0, aSig1); } else { if (FLOAT_PI_HI <= *aSig0) { *aSig0 -= FLOAT_PI_HI; q = 1; } } shift128Right(FLOAT_PI_HI, FLOAT_PI_LO, 1, &term0, &term1); if (! lt128(*aSig0, *aSig1, term0, term1)) { int lt = lt128(term0, term1, *aSig0, *aSig1); int eq = eq128(*aSig0, *aSig1, term0, term1); if ((eq && (q & 1)) || lt) { *zSign = !*zSign; ++q; } if (lt) sub128(FLOAT_PI_HI, FLOAT_PI_LO, *aSig0, *aSig1, aSig0, aSig1); } return (int)(q & 3); } #define SIN_ARR_SIZE 9 #define COS_ARR_SIZE 9 static float128 sin_arr[SIN_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ PACK_FLOAT_128(0xbffc555555555555, 0x5555555555555555), /* 3 */ PACK_FLOAT_128(0x3ff8111111111111, 0x1111111111111111), /* 5 */ PACK_FLOAT_128(0xbff2a01a01a01a01, 0xa01a01a01a01a01a), /* 7 */ PACK_FLOAT_128(0x3fec71de3a556c73, 0x38faac1c88e50017), /* 9 */ PACK_FLOAT_128(0xbfe5ae64567f544e, 0x38fe747e4b837dc7), /* 11 */ PACK_FLOAT_128(0x3fde6124613a86d0, 0x97ca38331d23af68), /* 13 */ PACK_FLOAT_128(0xbfd6ae7f3e733b81, 0xf11d8656b0ee8cb0), /* 15 */ PACK_FLOAT_128(0x3fce952c77030ad4, 0xa6b2605197771b00) /* 17 */ }; static float128 cos_arr[COS_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 0 */ PACK_FLOAT_128(0xbffe000000000000, 0x0000000000000000), /* 2 */ PACK_FLOAT_128(0x3ffa555555555555, 0x5555555555555555), /* 4 */ PACK_FLOAT_128(0xbff56c16c16c16c1, 0x6c16c16c16c16c17), /* 6 */ PACK_FLOAT_128(0x3fefa01a01a01a01, 0xa01a01a01a01a01a), /* 8 */ PACK_FLOAT_128(0xbfe927e4fb7789f5, 0xc72ef016d3ea6679), /* 10 */ PACK_FLOAT_128(0x3fe21eed8eff8d89, 0x7b544da987acfe85), /* 12 */ PACK_FLOAT_128(0xbfda93974a8c07c9, 0xd20badf145dfa3e5), /* 14 */ PACK_FLOAT_128(0x3fd2ae7f3e733b81, 0xf11d8656b0ee8cb0) /* 16 */ }; /* 0 <= x <= pi/4 */ LOCALINLINEFUNC float128 poly_sin(float128 x) { // 3 5 7 9 11 13 15 // x x x x x x x // sin (x) ~ x - --- + --- - --- + --- - ---- + ---- - ---- = // 3! 5! 7! 9! 11! 13! 15! // // 2 4 6 8 10 12 14 // x x x x x x x // = x * [ 1 - --- + --- - --- + --- - ---- + ---- - ---- ] = // 3! 5! 7! 9! 11! 13! 15! // // 3 3 // -- 4k -- 4k+2 // p(x) = > C * x > 0 q(x) = > C * x < 0 // -- 2k -- 2k+1 // k=0 k=0 // // 2 // sin(x) ~ x * [ p(x) + x * q(x) ] // return OddPoly(x, sin_arr, SIN_ARR_SIZE); } /* 0 <= x <= pi/4 */ LOCALINLINEFUNC float128 poly_cos(float128 x) { // 2 4 6 8 10 12 14 // x x x x x x x // cos (x) ~ 1 - --- + --- - --- + --- - ---- + ---- - ---- // 2! 4! 6! 8! 10! 12! 14! // // 3 3 // -- 4k -- 4k+2 // p(x) = > C * x > 0 q(x) = > C * x < 0 // -- 2k -- 2k+1 // k=0 k=0 // // 2 // cos(x) ~ [ p(x) + x * q(x) ] // return EvenPoly(x, cos_arr, COS_ARR_SIZE); } LOCALINLINEPROC sincos_invalid(floatx80 *sin_a, floatx80 *cos_a, floatx80 a) { if (sin_a) *sin_a = a; if (cos_a) *cos_a = a; } LOCALINLINEPROC sincos_tiny_argument(floatx80 *sin_a, floatx80 *cos_a, floatx80 a) { if (sin_a) *sin_a = a; if (cos_a) *cos_a = floatx80_one; } LOCALFUNC floatx80 sincos_approximation(int neg, float128 r, Bit64u quotient) { floatx80 result; if (quotient & 0x1) { r = poly_cos(r); neg = 0; } else { r = poly_sin(r); } result = float128_to_floatx80(r); if (quotient & 0x2) neg = ! neg; if (neg) floatx80_chs(&result); return result; } // ================================================= // FSINCOS Compute sin(x) and cos(x) // ================================================= // // Uses the following identities: // ---------------------------------------------------------- // // sin(-x) = -sin(x) // cos(-x) = cos(x) // // sin(x+y) = sin(x)*cos(y)+cos(x)*sin(y) // cos(x+y) = sin(x)*sin(y)+cos(x)*cos(y) // // sin(x+ pi/2) = cos(x) // sin(x+ pi) = -sin(x) // sin(x+3pi/2) = -cos(x) // sin(x+2pi) = sin(x) // LOCALFUNC int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a) { float128 r; Bit64u aSig0, aSig1 = 0; Bit32s aExp, zExp, expDiff; int aSign, zSign; int q = 0; #if 0 // handle unsupported extended double-precision floating encodings if (floatx80_is_unsupported(a)) { goto invalid; } #endif aSig0 = extractFloatx80Frac(a); aExp = extractFloatx80Exp(a); aSign = extractFloatx80Sign(a); /* invalid argument */ if (aExp == 0x7FFF) { if ((Bit64u) (aSig0<<1)) { sincos_invalid(sin_a, cos_a, propagateOneFloatx80NaN(&a)); return 0; } #if 0 invalid: #endif float_raise(float_flag_invalid); sincos_invalid(sin_a, cos_a, floatx80_default_nan); return 0; } if (aExp == 0) { if (aSig0 == 0) { sincos_tiny_argument(sin_a, cos_a, a); return 0; } float_raise(float_flag_denormal); /* handle pseudo denormals */ if (! (aSig0 & LIT64(0x8000000000000000))) { float_raise(float_flag_inexact); if (sin_a) float_raise(float_flag_underflow); sincos_tiny_argument(sin_a, cos_a, a); return 0; } normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); } zSign = aSign; zExp = EXP_BIAS; expDiff = aExp - zExp; /* argument is out-of-range */ if (expDiff >= 63) return -1; float_raise(float_flag_inexact); if (expDiff < -1) { // doesn't require reduction if (expDiff <= -68) { a = packFloatx80(aSign, aExp, aSig0); sincos_tiny_argument(sin_a, cos_a, a); return 0; } zExp = aExp; } else { q = reduce_trig_arg(expDiff, &zSign, &aSig0, &aSig1); } /* **************************** */ /* argument reduction completed */ /* **************************** */ /* using float128 for approximation */ r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1); if (aSign) q = -q; if (sin_a) *sin_a = sincos_approximation(zSign, r, q); if (cos_a) *cos_a = sincos_approximation(zSign, r, q+1); return 0; } // ================================================= // FPTAN Compute tan(x) // ================================================= // // Uses the following identities: // // 1. ---------------------------------------------------------- // // sin(-x) = -sin(x) // cos(-x) = cos(x) // // sin(x+y) = sin(x)*cos(y)+cos(x)*sin(y) // cos(x+y) = sin(x)*sin(y)+cos(x)*cos(y) // // sin(x+ pi/2) = cos(x) // sin(x+ pi) = -sin(x) // sin(x+3pi/2) = -cos(x) // sin(x+2pi) = sin(x) // // 2. ---------------------------------------------------------- // // sin(x) // tan(x) = ------ // cos(x) // LOCALFUNC int ftan(floatx80 *a) { float128 r; float128 sin_r; float128 cos_r; Bit64u aSig0, aSig1 = 0; Bit32s aExp, zExp, expDiff; int aSign, zSign; int q = 0; #if 0 // handle unsupported extended double-precision floating encodings if (floatx80_is_unsupported(*a)) { goto invalid; } #endif aSig0 = extractFloatx80Frac(*a); aExp = extractFloatx80Exp(*a); aSign = extractFloatx80Sign(*a); /* invalid argument */ if (aExp == 0x7FFF) { if ((Bit64u) (aSig0<<1)) { *a = propagateOneFloatx80NaN(a); return 0; } #if 0 invalid: #endif float_raise(float_flag_invalid); *a = floatx80_default_nan; return 0; } if (aExp == 0) { if (aSig0 == 0) return 0; float_raise(float_flag_denormal); /* handle pseudo denormals */ if (! (aSig0 & LIT64(0x8000000000000000))) { float_raise(float_flag_inexact | float_flag_underflow); return 0; } normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); } zSign = aSign; zExp = EXP_BIAS; expDiff = aExp - zExp; /* argument is out-of-range */ if (expDiff >= 63) return -1; float_raise(float_flag_inexact); if (expDiff < -1) { // doesn't require reduction if (expDiff <= -68) { *a = packFloatx80(aSign, aExp, aSig0); return 0; } zExp = aExp; } else { q = reduce_trig_arg(expDiff, &zSign, &aSig0, &aSig1); } /* **************************** */ /* argument reduction completed */ /* **************************** */ /* using float128 for approximation */ r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1); sin_r = poly_sin(r); cos_r = poly_cos(r); if (q & 0x1) { r = float128_div(cos_r, sin_r); zSign = ! zSign; } else { r = float128_div(sin_r, cos_r); } *a = float128_to_floatx80(r); if (zSign) floatx80_chs(a); return 0; } /* ----- end from original file "fsincos.cc" ----- */ /* ----- from original file "fpatan.cc" ----- */ /* ["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.] */ #define FPATAN_ARR_SIZE 11 #if 0 static const float128 float128_one = packFloat2x128m(LIT64(0x3fff000000000000), LIT64(0x0000000000000000)); #endif static const float128 float128_sqrt3 = packFloat2x128m(LIT64(0x3fffbb67ae8584ca), LIT64(0xa73b25742d7078b8)); static const floatx80 floatx80_pi = packFloatx80m(0, 0x4000, LIT64(0xc90fdaa22168c235)); static const float128 float128_pi2 = packFloat2x128m(LIT64(0x3fff921fb54442d1), LIT64(0x8469898CC5170416)); static const float128 float128_pi4 = packFloat2x128m(LIT64(0x3ffe921fb54442d1), LIT64(0x8469898CC5170416)); static const float128 float128_pi6 = packFloat2x128m(LIT64(0x3ffe0c152382d736), LIT64(0x58465BB32E0F580F)); static float128 atan_arr[FPATAN_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ PACK_FLOAT_128(0xbffd555555555555, 0x5555555555555555), /* 3 */ PACK_FLOAT_128(0x3ffc999999999999, 0x999999999999999a), /* 5 */ PACK_FLOAT_128(0xbffc249249249249, 0x2492492492492492), /* 7 */ PACK_FLOAT_128(0x3ffbc71c71c71c71, 0xc71c71c71c71c71c), /* 9 */ PACK_FLOAT_128(0xbffb745d1745d174, 0x5d1745d1745d1746), /* 11 */ PACK_FLOAT_128(0x3ffb3b13b13b13b1, 0x3b13b13b13b13b14), /* 13 */ PACK_FLOAT_128(0xbffb111111111111, 0x1111111111111111), /* 15 */ PACK_FLOAT_128(0x3ffae1e1e1e1e1e1, 0xe1e1e1e1e1e1e1e2), /* 17 */ PACK_FLOAT_128(0xbffaaf286bca1af2, 0x86bca1af286bca1b), /* 19 */ PACK_FLOAT_128(0x3ffa861861861861, 0x8618618618618618) /* 21 */ }; /* |x| < 1/4 */ LOCALFUNC float128 poly_atan(float128 x1) { /* // 3 5 7 9 11 13 15 17 // x x x x x x x x // atan(x) ~ x - --- + --- - --- + --- - ---- + ---- - ---- + ---- // 3 5 7 9 11 13 15 17 // // 2 4 6 8 10 12 14 16 // x x x x x x x x // = x * [ 1 - --- + --- - --- + --- - ---- + ---- - ---- + ---- ] // 3 5 7 9 11 13 15 17 // // 5 5 // -- 4k -- 4k+2 // p(x) = > C * x q(x) = > C * x // -- 2k -- 2k+1 // k=0 k=0 // // 2 // atan(x) ~ x * [ p(x) + x * q(x) ] // */ return OddPoly(x1, atan_arr, FPATAN_ARR_SIZE); } // ================================================= // FPATAN Compute y * log (x) // 2 // ================================================= // // Uses the following identities: // // 1. ---------------------------------------------------------- // // atan(-x) = -atan(x) // // 2. ---------------------------------------------------------- // // x + y // atan(x) + atan(y) = atan -------, xy < 1 // 1-xy // // x + y // atan(x) + atan(y) = atan ------- + PI, x > 0, xy > 1 // 1-xy // // x + y // atan(x) + atan(y) = atan ------- - PI, x < 0, xy > 1 // 1-xy // // 3. ---------------------------------------------------------- // // atan(x) = atan(INF) + atan(- 1/x) // // x-1 // atan(x) = PI/4 + atan( ----- ) // x+1 // // x * sqrt(3) - 1 // atan(x) = PI/6 + atan( ----------------- ) // x + sqrt(3) // // 4. ---------------------------------------------------------- // 3 5 7 9 2n+1 // x x x x n x // atan(x) = x - --- + --- - --- + --- - ... + (-1) ------ + ... // 3 5 7 9 2n+1 // LOCALFUNC floatx80 fpatan(floatx80 a, floatx80 b) { float128 a128; float128 b128; float128 x; int swap, add_pi6, add_pi4; Bit32s xExp; floatx80 result; int rSign; // handle unsupported extended double-precision floating encodings #if 0 if (floatx80_is_unsupported(a)) { float_raise(float_flag_invalid); return floatx80_default_nan; } #endif Bit64u aSig = extractFloatx80Frac(a); Bit32s aExp = extractFloatx80Exp(a); int aSign = extractFloatx80Sign(a); Bit64u bSig = extractFloatx80Frac(b); Bit32s bExp = extractFloatx80Exp(b); int bSign = extractFloatx80Sign(b); int zSign = aSign ^ bSign; if (bExp == 0x7FFF) { if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b); if (aExp == 0x7FFF) { if ((Bit64u) (aSig<<1)) return propagateFloatx80NaN(a, b); if (aSign) { /* return 3PI/4 */ return roundAndPackFloatx80(80, bSign, FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO); } else { /* return PI/4 */ return roundAndPackFloatx80(80, bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO); } } if (aSig && (aExp == 0)) float_raise(float_flag_denormal); /* return PI/2 */ return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO); } if (aExp == 0x7FFF) { if ((Bit64u) (aSig<<1)) return propagateFloatx80NaN(a, b); if (bSig && (bExp == 0)) float_raise(float_flag_denormal); return_PI_or_ZERO: if (aSign) { /* return PI */ return roundAndPackFloatx80(80, bSign, FLOATX80_PI_EXP, FLOAT_PI_HI, FLOAT_PI_LO); } else { /* return 0 */ return packFloatx80(bSign, 0, 0); } } if (bExp == 0) { if (bSig == 0) { if (aSig && (aExp == 0)) float_raise(float_flag_denormal); goto return_PI_or_ZERO; } float_raise(float_flag_denormal); normalizeFloatx80Subnormal(bSig, &bExp, &bSig); } if (aExp == 0) { if (aSig == 0) /* return PI/2 */ return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO); float_raise(float_flag_denormal); normalizeFloatx80Subnormal(aSig, &aExp, &aSig); } float_raise(float_flag_inexact); /* |a| = |b| ==> return PI/4 */ if (aSig == bSig && aExp == bExp) return roundAndPackFloatx80(80, bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO); /* ******************************** */ /* using float128 for approximation */ /* ******************************** */ a128 = normalizeRoundAndPackFloat128(0, aExp-0x10, aSig, 0); b128 = normalizeRoundAndPackFloat128(0, bExp-0x10, bSig, 0); swap = 0; add_pi6 = 0; add_pi4 = 0; if (aExp > bExp || (aExp == bExp && aSig > bSig)) { x = float128_div(b128, a128); } else { x = float128_div(a128, b128); swap = 1; } xExp = extractFloat128Exp(x); if (xExp <= EXP_BIAS-40) goto approximation_completed; if (x.high >= LIT64(0x3ffe800000000000)) // 3/4 < x < 1 { /* arctan(x) = arctan((x-1)/(x+1)) + pi/4 */ float128 t1 = float128_sub(x, float128_one); float128 t2 = float128_add(x, float128_one); x = float128_div(t1, t2); add_pi4 = 1; } else { /* argument correction */ if (xExp >= 0x3FFD) // 1/4 < x < 3/4 { /* arctan(x) = arctan((x*sqrt(3)-1)/(x+sqrt(3))) + pi/6 */ float128 t1 = float128_mul(x, float128_sqrt3); float128 t2 = float128_add(x, float128_sqrt3); x = float128_sub(t1, float128_one); x = float128_div(x, t2); add_pi6 = 1; } } x = poly_atan(x); if (add_pi6) x = float128_add(x, float128_pi6); if (add_pi4) x = float128_add(x, float128_pi4); approximation_completed: if (swap) x = float128_sub(float128_pi2, x); result = float128_to_floatx80(x); if (zSign) floatx80_chs(&result); rSign = extractFloatx80Sign(result); if (!bSign && rSign) return floatx80_add(result, floatx80_pi); if (bSign && !rSign) return floatx80_sub(result, floatx80_pi); return result; } /* ----- end from original file "fpatan.cc" ----- */ /* end soft float stuff */ typedef floatx80 myfpr; LOCALPROC myfp_FromExtendedFormat(myfpr *r, ui4r v2, ui5r v1, ui5r v0) { r->high = v2; r->low = (((ui6b)v1) << 32) | (v0 & 0xFFFFFFFF); } LOCALPROC myfp_ToExtendedFormat(myfpr *dd, ui4r *v2, ui5r *v1, ui5r *v0) { *v0 = ((ui6b) dd->low) & 0xFFFFFFFF; *v1 = (((ui6b) dd->low) >> 32) & 0xFFFFFFFF; *v2 = dd->high; } LOCALPROC myfp_FromDoubleFormat(myfpr *r, ui5r v1, ui5r v0) { float64 t = (float64)((((ui6b)v1) << 32) | (v0 & 0xFFFFFFFF)); *r = float64_to_floatx80(t); } LOCALPROC myfp_ToDoubleFormat(myfpr *dd, ui5r *v1, ui5r *v0) { float64 t = floatx80_to_float64(*dd); *v0 = ((ui6b) t) & 0xFFFFFFFF; *v1 = (((ui6b) t) >> 32) & 0xFFFFFFFF; } LOCALPROC myfp_FromSingleFormat(myfpr *r, ui5r x) { *r = float32_to_floatx80(x); } LOCALFUNC ui5r myfp_ToSingleFormat(myfpr *ff) { return floatx80_to_float32(*ff); } LOCALPROC myfp_FromLong(myfpr *r, ui5r x) { *r = int32_to_floatx80( x ); } LOCALFUNC ui5r myfp_ToLong(myfpr *x) { return floatx80_to_int32( *x ); } LOCALFUNC blnr myfp_IsNan(myfpr *x) { return floatx80_is_nan(*x); } LOCALFUNC blnr myfp_IsInf(myfpr *x) { return ( ( x->high & 0x7FFF ) == 0x7FFF ) && (0 == ((ui6b) ( x->low<<1 ))); } LOCALFUNC blnr myfp_IsZero(myfpr *x) { return ( ( x->high & 0x7FFF ) == 0x0000 ) && (0 == ((ui6b) ( x->low<<1 ))); } LOCALFUNC blnr myfp_IsNeg(myfpr *x) { return ( ( x->high & 0x8000 ) != 0x0000 ); } LOCALPROC myfp_Add(myfpr *r, const myfpr *a, const myfpr *b) { *r = floatx80_add(*a, *b); } LOCALPROC myfp_Sub(myfpr *r, const myfpr *a, const myfpr *b) { *r = floatx80_sub(*a, *b); } LOCALPROC myfp_Mul(myfpr *r, const myfpr *a, const myfpr *b) { *r = floatx80_mul(*a, *b); } LOCALPROC myfp_Div(myfpr *r, const myfpr *a, const myfpr *b) { *r = floatx80_div(*a, *b); } LOCALPROC myfp_Rem(myfpr *r, const myfpr *a, const myfpr *b) { *r = floatx80_rem(*a, *b); } LOCALPROC myfp_Sqrt(myfpr *r, myfpr *x) { *r = floatx80_sqrt(*x); } LOCALPROC myfp_Mod(myfpr *r, myfpr *a, myfpr *b) { Bit64u q; *r = floatx80_remainder(*a, *b, &q); /* should save low byte of q */ } LOCALPROC myfp_Scale(myfpr *r, myfpr *a, myfpr *b) { *r = floatx80_scale(*a, *b); } LOCALPROC myfp_GetMan(myfpr *r, myfpr *x) { *r = *x; (void) floatx80_extract(r); } LOCALPROC myfp_GetExp(myfpr *r, myfpr *x) { floatx80 t0 = *x; *r = floatx80_extract(&t0); } LOCALPROC myfp_floor(myfpr *r, myfpr *x) { si3r SaveRoundingMode = float_rounding_mode; float_rounding_mode = float_round_down; *r = floatx80_round_to_int(*x); float_rounding_mode = SaveRoundingMode; } LOCALPROC myfp_IntRZ(myfpr *r, myfpr *x) { si3r SaveRoundingMode = float_rounding_mode; float_rounding_mode = float_round_to_zero; *r = floatx80_round_to_int(*x); float_rounding_mode = SaveRoundingMode; } LOCALPROC myfp_Int(myfpr *r, myfpr *x) { *r = floatx80_round_to_int(*x); } LOCALPROC myfp_RoundToSingle(myfpr *r, myfpr *x) { float32 t0 = floatx80_to_float32(*x); *r = float32_to_floatx80(t0); } LOCALPROC myfp_RoundToDouble(myfpr *r, myfpr *x) { float64 t0 = floatx80_to_float64(*x); *r = float64_to_floatx80(t0); } LOCALPROC myfp_Abs(myfpr *r, myfpr *x) { *r = *x; r->high &= 0x7FFF; } LOCALPROC myfp_Neg(myfpr *r, myfpr *x) { *r = *x; r->high ^= 0x8000; } LOCALPROC myfp_TwoToX(myfpr *r, myfpr *x) { floatx80 t2; floatx80 t3; floatx80 t4; floatx80 t5; myfp_floor(&t2, x); t3 = floatx80_sub(*x, t2); t4 = f2xm1(t3); t5 = floatx80_add(t4, floatx80_one); *r = floatx80_scale(t5, t2); } LOCALPROC myfp_TenToX(myfpr *r, myfpr *x) { floatx80 t1; const floatx80 t = /* 1.0 / log(2.0) */ packFloatx80m(0, 0x3fff, LIT64(0xb8aa3b295c17f0bc)); const floatx80 t2 = /* log(10.0) */ packFloatx80m(0, 0x4000, LIT64(0x935d8dddaaa8ac17)); t1 = floatx80_mul(floatx80_mul(*x, t), t2); myfp_TwoToX(r, &t1); } LOCALPROC myfp_EToX(myfpr *r, myfpr *x) { floatx80 t1; const floatx80 t = /* 1.0 / log(2.0) */ packFloatx80m(0, 0x3fff, LIT64(0xb8aa3b295c17f0bc)); t1 = floatx80_mul(*x, t); myfp_TwoToX(r, &t1); } LOCALPROC myfp_EToXM1(myfpr *r, myfpr *x) { floatx80 t1; floatx80 t2; floatx80 t3; floatx80 t4; floatx80 t5; floatx80 t6; const floatx80 t = /* 1.0 / log(2.0) */ packFloatx80m(0, 0x3fff, LIT64(0xb8aa3b295c17f0bc)); t1 = floatx80_mul(*x, t); myfp_floor(&t2, &t1); t3 = floatx80_sub(t1, t2); t4 = f2xm1(t3); if (myfp_IsZero(&t2)) { *r = t4; } else { t5 = floatx80_add(t4, floatx80_one); t6 = floatx80_scale(t5, t2); *r = floatx80_sub(t6, floatx80_one); } } LOCALPROC myfp_Log2(myfpr *r, myfpr *x) { *r = fyl2x(*x, floatx80_one); } LOCALPROC myfp_LogN(myfpr *r, myfpr *x) { const floatx80 t = /* log(2.0) */ packFloatx80m(0, 0x3ffe, LIT64(0xb17217f7d1cf79ac)); *r = fyl2x(*x, t); } LOCALPROC myfp_Log10(myfpr *r, myfpr *x) { const floatx80 t = /* log10(2.0) = ln(2) / ln(10), unknown accuracy */ packFloatx80m(0, 0x3ffd, LIT64(0x9a209a84fbcff798)); *r = fyl2x(*x, t); } LOCALPROC myfp_LogNP1(myfpr *r, myfpr *x) { const floatx80 t = /* log(2.0) */ packFloatx80m(0, 0x3ffe, LIT64(0xb17217f7d1cf79ac)); *r = fyl2xp1(*x, t); } LOCALPROC myfp_Sin(myfpr *r, myfpr *x) { (void) fsincos(*x, r, 0); } LOCALPROC myfp_Cos(myfpr *r, myfpr *x) { (void) fsincos(*x, 0, r); } LOCALPROC myfp_Tan(myfpr *r, myfpr *x) { *r = *x; (void) ftan(r); } LOCALPROC myfp_ATan(myfpr *r, myfpr *x) { *r = fpatan(floatx80_one, *x); } LOCALPROC myfp_ASin(myfpr *r, myfpr *x) { floatx80 x2 = floatx80_mul(*x, *x); floatx80 mx2 = floatx80_sub(floatx80_one, x2); floatx80 cx = floatx80_sqrt(mx2); *r = fpatan(cx, *x); } LOCALPROC myfp_ACos(myfpr *r, myfpr *x) { floatx80 x2 = floatx80_mul(*x, *x); floatx80 mx2 = floatx80_sub(floatx80_one, x2); floatx80 cx = floatx80_sqrt(mx2); *r = fpatan(*x, cx); } static const floatx80 floatx80_zero = packFloatx80m(0, 0x0000, LIT64(0x0000000000000000)); static const floatx80 floatx80_Two = packFloatx80m(0, 0x4000, LIT64(0x8000000000000000)); static const floatx80 floatx80_Ten = packFloatx80m(0, 0x4002, LIT64(0xa000000000000000)); LOCALPROC myfp_Sinh(myfpr *r, myfpr *x) { myfpr ex; myfpr nx; myfpr enx; myfpr t1; myfp_EToX(&ex, x); myfp_Neg(&nx, x); myfp_EToX(&enx, &nx); myfp_Sub(&t1, &ex, &enx); myfp_Div(r, &t1, &floatx80_Two); } LOCALPROC myfp_Cosh(myfpr *r, myfpr *x) { myfpr ex; myfpr nx; myfpr enx; myfpr t1; myfp_EToX(&ex, x); myfp_Neg(&nx, x); myfp_EToX(&enx, &nx); myfp_Add(&t1, &ex, &enx); myfp_Div(r, &t1, &floatx80_Two); } LOCALPROC myfp_Tanh(myfpr *r, myfpr *x) { myfpr x2; myfpr ex2; myfpr ex2m1; myfpr ex2p1; myfp_Mul(&x2, x, &floatx80_Two); myfp_EToX(&ex2, &x2); myfp_Sub(&ex2m1, &ex2, &floatx80_one); myfp_Add(&ex2p1, &ex2, &floatx80_one); myfp_Div(r, &ex2m1, &ex2p1); } LOCALPROC myfp_ATanh(myfpr *r, myfpr *x) { myfpr onepx; myfpr onemx; myfpr dv; myfpr ldv; myfp_Add(&onepx, x, &floatx80_one); myfp_Sub(&onemx, x, &floatx80_one); myfp_Div(&dv, &onepx, &onemx); myfp_LogN(&ldv, &dv); myfp_Div(r, &ldv, &floatx80_Two); } LOCALPROC myfp_SinCos(myfpr *r_sin, myfpr *r_cos, myfpr *source) { (void) fsincos(*source, r_sin, r_cos); } LOCALFUNC blnr myfp_getCR(myfpr *r, ui4b opmode) { switch (opmode) { case 0x00: *r = floatx80_pi; /* M_PI */ break; case 0x0B: { const floatx80 t = packFloatx80m(0, 0x3ffd, LIT64(0x9a209a84fbcff798)); *r = t; /* log10(2.0) = ln(2) / ln(10), unknown accuracy */ } break; case 0x0C: { const floatx80 t = packFloatx80m(0, 0x4000, LIT64(0xadf85458a2bb4a9b)); *r = t; /* exp(1.0), unknown accuracy */ } break; case 0x0D: { const floatx80 t = packFloatx80m(0, 0x3fff, LIT64(0xb8aa3b295c17f0bc)); *r = t; /* 1.0 / log(2.0) */ } break; case 0x0E: { const floatx80 t = packFloatx80m(0, 0x3ffd, LIT64(0xde5bd8a937287195)); *r = t; /* 1.0 / log(10.0), unknown accuracy */ } break; case 0x0F: *r = floatx80_zero; /* 0.0 */ break; case 0x30: { const floatx80 t = packFloatx80m(0, 0x3ffe, LIT64(0xb17217f7d1cf79ac)); *r = t; /* log(2.0) */ } break; case 0x31: { const floatx80 t = packFloatx80m(0, 0x4000, LIT64(0x935d8dddaaa8ac17)); *r = t; /* log(10.0) */ } break; case 0x32: *r = floatx80_one; /* 1.0 */ break; case 0x33: *r = floatx80_Ten; /* 10.0 */ break; case 0x34: { const floatx80 t = packFloatx80m(0, 0x4005, LIT64(0xc800000000000000)); *r = t; /* 100.0 */ } break; case 0x35: { const floatx80 t = packFloatx80m(0, 0x400c, LIT64(0x9c40000000000000)); *r = t; /* 10000.0 */ } break; case 0x36: { const floatx80 t = packFloatx80m(0, 0x4019, LIT64(0xbebc200000000000)); *r = t; /* 1.0e8 */ } break; case 0x37: { const floatx80 t = packFloatx80m(0, 0x4034, LIT64(0x8e1bc9bf04000000)); *r = t; /* 1.0e16 */ } break; case 0x38: { const floatx80 t = packFloatx80m(0, 0x4069, LIT64(0x9dc5ada82b70b59e)); *r = t; /* 1.0e32 */ } break; case 0x39: { const floatx80 t = packFloatx80m(0, 0x40d3, LIT64(0xc2781f49ffcfa6d5)); *r = t; /* 1.0e64 */ } break; case 0x3A: { const floatx80 t = packFloatx80m(0, 0x41a8, LIT64(0x93ba47c980e98ce0)); *r = t; /* 1.0e128 */ } break; case 0x3B: { const floatx80 t = packFloatx80m(0, 0x4351, LIT64(0xaa7eebfb9df9de8e)); *r = t; /* 1.0e256 */ } break; case 0x3C: { const floatx80 t = packFloatx80m(0, 0x46a3, LIT64(0xe319a0aea60e91c7)); *r = t; /* 1.0e512 */ } break; case 0x3D: { const floatx80 t = packFloatx80m(0, 0x4d48, LIT64(0xc976758681750c17)); *r = t; /* 1.0e1024 */ } break; case 0x3E: { const floatx80 t = packFloatx80m(0, 0x5a92, LIT64(0x9e8b3b5dc53d5de5)); *r = t; /* 1.0e2048 */ } break; case 0x3F: { const floatx80 t = packFloatx80m(0, 0x7525, LIT64(0xc46052028a20979b)); *r = t; /* 1.0e4096 */ } break; default: return falseblnr; } return trueblnr; } /* Floating point control register */ LOCALPROC myfp_SetFPCR(ui5r v) { switch ((v >> 4) & 0x03) { case 0: float_rounding_mode = float_round_nearest_even; break; case 1: float_rounding_mode = float_round_to_zero; break; case 2: float_rounding_mode = float_round_down; break; case 3: float_rounding_mode = float_round_up; break; } switch ((v >> 6) & 0x03) { case 0: floatx80_rounding_precision = 80; break; case 1: floatx80_rounding_precision = 32; break; case 2: floatx80_rounding_precision = 64; break; case 3: ReportAbnormalID(0x0201, "Bad rounding precision in myfp_SetFPCR"); floatx80_rounding_precision = 80; break; } if (0 != (v & 0xF)) { ReportAbnormalID(0x0202, "Reserved bits not zero in myfp_SetFPCR"); } } LOCALFUNC ui5r myfp_GetFPCR(void) { ui5r v = 0; switch (float_rounding_mode) { case float_round_nearest_even: /* v |= (0 << 4); */ break; case float_round_to_zero: v |= (1 << 4); break; case float_round_down: v |= (2 << 4); break; case float_round_up: v |= (3 << 4); break; } if (80 == floatx80_rounding_precision) { /* v |= (0 << 6); */ } else if (32 == floatx80_rounding_precision) { v |= (1 << 6); } else if (64 == floatx80_rounding_precision) { v |= (2 << 6); } else { ReportAbnormalID(0x0203, "Bad rounding precision in myfp_GetFPCR"); } return v; } LOCALVAR struct myfp_envStruct { ui5r FPSR; /* Floating point status register */ } myfp_env; LOCALPROC myfp_SetFPSR(ui5r v) { myfp_env.FPSR = v; } LOCALFUNC ui5r myfp_GetFPSR(void) { return myfp_env.FPSR; } LOCALFUNC ui3r myfp_GetConditionCodeByte(void) { return (myfp_env.FPSR >> 24) & 0x0F; } LOCALPROC myfp_SetConditionCodeByte(ui3r v) { myfp_env.FPSR = ((myfp_env.FPSR & 0x00FFFFFF) | (v << 24)); } LOCALPROC myfp_SetConditionCodeByteFromResult(myfpr *result) { /* Set condition codes here based on result */ int c_nan = myfp_IsNan(result) ? 1 : 0; int c_inf = myfp_IsInf(result) ? 1 : 0; int c_zero = myfp_IsZero(result) ? 1 : 0; int c_neg = myfp_IsNeg(result) ? 1 : 0; myfp_SetConditionCodeByte(c_nan | (c_inf << 1) | (c_zero << 2) | (c_neg << 3)); } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/FPMATHNT.h b/Mini vMac/mnvm_core/FPMATHNT.h deleted file mode 100755 index 4b3c16c..0000000 --- a/Mini vMac/mnvm_core/FPMATHNT.h +++ /dev/null @@ -1,503 +0,0 @@ -/* - FPMATHNT.h - - Copyright (C) 2009 Ross Martin, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - Floating Point MATH implemented with NaTive operations -*/ - -#include -#include - -#define FPDEBUG if (0) -/* #define FPDEBUG */ - -typedef long double myfpr; - -/* - Only valid for a host that's an X386 processor - - 68881 extended is 96 bits. This is 1 bit sign, 15 bits exponent - 16 bits unused, 1 bit explicit integer bit of mantissa, and - 63 bits of normal mantissa - - Intel extended is packed into 128 bits. It is 80 bits, with - 1 bit sign, 15 bits exponent, 1 bit explicit integer bit of - mantissa, and 63 bits of mantissa. - - So for the most part these match. Just have to match the correct - bytes. -*/ - -#if BigEndianUnaligned -#define fldbitsi(i) (9 - (i)) -#else -#define fldbitsi(i) (i) -#endif - -LOCALPROC myfp_FromExtendedFormat(myfpr *r, ui4r v2, ui5r v1, ui5r v0) -{ - int ii; - union { - ui3b fbits[16]; - myfpr x; - } extended_p, fixer; - myfpr result; - - /* filler. Don't really need, helped me debug */ - for (ii = 10; ii < 16; ii++) { - extended_p.fbits[ii] = 0x77; - } - - /* sign and exponent */ - *(ui4b *)&extended_p.fbits[fldbitsi(8)] = v2; - - /* mantissa */ - *(ui5b *)&extended_p.fbits[fldbitsi(4)] = v1; - *(ui5b *)&extended_p.fbits[fldbitsi(0)] = v0; - - result = extended_p.x; - - - FPDEBUG printf("read_long_double reads %lf (0x", - (double)extended_p.x); - FPDEBUG { - int ii; - - for (ii = 12; ii >= 0; ii--) { - printf("%02x", extended_p.fbits[ii]); - } - } - - - - /* - Check for unusual condition where 68881 mantissa high bit - isnt' set. - This is an error for the x86 FPU, so I need to patch it. - */ - - if ((extended_p.fbits[fldbitsi(7)] & 0x80) == 0x00) { - /* High bit of mantissa isn't set */ - - if (((extended_p.fbits[fldbitsi(9)] & 0x7F) == 0x7F) - && (extended_p.fbits[fldbitsi(8)] == 0xFF)) - { - /* infinity, OK for mantissa high bit to not be set */ - } else if (((extended_p.fbits[fldbitsi(9)] & 0x7F) == 0x00) - && (extended_p.fbits[fldbitsi(8)] == 0x00)) - { - /* zero, OK for mantissa high bit to not be set */ - } else { - /* - Not OK for mantissa high bit to not be set. - Fix using the FPU itself - */ - - extended_p.fbits[fldbitsi(7)] = - extended_p.fbits[fldbitsi(7)] | 0x80; - /* Force top bit to 1 */ - - /* - Create a second extended long with *only* the high bit - of the mantissa set, identical sign and exponent. Then - subtract it off to remove the 1 bit we just forced in - the top of the mantissa. - */ - - /* sign and exponent */ - fixer.fbits[fldbitsi(9)] = extended_p.fbits[fldbitsi(9)]; - fixer.fbits[fldbitsi(8)] = extended_p.fbits[fldbitsi(8)]; - - /* mantissa */ - fixer.fbits[fldbitsi(7)] = 0x80; - fixer.fbits[fldbitsi(6)] = 0x00; - fixer.fbits[fldbitsi(5)] = 0x00; - fixer.fbits[fldbitsi(4)] = 0x00; - fixer.fbits[fldbitsi(3)] = 0x00; - fixer.fbits[fldbitsi(2)] = 0x00; - fixer.fbits[fldbitsi(1)] = 0x00; - fixer.fbits[fldbitsi(0)] = 0x00; - - result = extended_p.x - fixer.x; - - FPDEBUG - { - printf( - "Fixing denormalized extended precision float\n"); - - printf("XP: 0x"); - for (ii = 0; ii < 16; ii++) { - printf("%02x", extended_p.fbits[ii]); - } - printf(" %lf\n", (double)extended_p.x); - - printf("FX: 0x"); - for (ii = 0; ii < 16; ii++) { - printf("%02x", fixer.fbits[ii]); - } - printf(" %lf\n", (double)fixer.x); - - fixer.x = result; - - printf("Out: 0x"); - for (ii = 0; ii < 16; ii++) { - printf("%02x", fixer.fbits[ii]); - } - printf(" %lf\n", (double)fixer.x); - } - } - } - - /* - printf("XP: 0x"); - for (ii = 0; ii < 16; ii++) { - printf("%02x", extended_p.fbits[ii]); - } - printf(" %lf\n", (double)extended_p.x); - - extended_p.x = 1.5 + 7.0 / 1024 / 1024 / 1024 / 1024; - - printf("ZP: 0x"); - for(ii = 0; ii < 16; ii++) { - printf("%02x", extended_p.fbits[ii]); - } - printf(" %lf\n", (double)extended_p.x); - */ - - /* - printf("read_long_double returns %lf\n", (double)extended_p.x); - */ - - *r = result; -} - - -LOCALPROC myfp_ToExtendedFormat(myfpr *dd, ui4r *v2, ui5r *v1, ui5r *v0) -{ - union { - ui3b fbits[16]; - myfpr x; - } extended_p; - - extended_p.x = *dd; - - /* sign and exponent */ - *v2 = *(ui4b *)&extended_p.fbits[fldbitsi(8)]; - - /* mantissa */ - *v1 = *(ui5b *)&extended_p.fbits[fldbitsi(4)]; - *v0 = *(ui5b *)&extended_p.fbits[fldbitsi(0)]; -} - - -/* - Only valid for a host that's an X386 processor -*/ - -#if BigEndianUnaligned -#define fdbitsi(i) (7 - (i)) -#else -#define fdbitsi(i) (i) -#endif - -LOCALPROC myfp_FromDoubleFormat(myfpr *r, ui5r v1, ui5r v0) -{ - union { - ui3b fbits[8]; - double d; - } double_p; - - *(ui5b *)&double_p.fbits[fdbitsi(4)] = v1; - *(ui5b *)&double_p.fbits[fdbitsi(0)] = v0; - - *r = (myfpr)double_p.d; -} - -LOCALPROC myfp_ToDoubleFormat(myfpr *dd, ui5r *v1, ui5r *v0) -{ - union { - ui3b fbits[8]; - double d; - } double_p; - - double_p.d = (double)*dd; - - *v1 = *(ui5b *)&double_p.fbits[fdbitsi(4)]; - *v0 = *(ui5b *)&double_p.fbits[fdbitsi(0)]; -} - - -LOCALPROC myfp_FromSingleFormat(myfpr *r, ui5r x) -{ - union { - ui5b fbits; - float f; - } single_p; - - single_p.fbits = x; - - *r = (myfpr)single_p.f; -} - - -LOCALFUNC ui5r myfp_ToSingleFormat(myfpr *ff) -{ - union { - ui5b fbits; - float f; - } single_p; - - single_p.f = (float)*ff; - - return single_p.fbits; -} - -LOCALPROC myfp_FromLong(myfpr *r, ui5r x) -{ - *r = (myfpr)(si5b)x; -} - -LOCALFUNC ui5r myfp_ToLong(myfpr *x) -{ - return (ui5r)(si5r)(si5b)*x; -} - -LOCALFUNC blnr myfp_IsNan(myfpr *x) -{ - return isnan(*x); -} - -LOCALFUNC blnr myfp_IsInf(myfpr *x) -{ - return isinf(*x); -} - -LOCALFUNC blnr myfp_IsZero(myfpr *x) -{ - return (*x == 0.0); -} - -LOCALFUNC blnr myfp_IsNeg(myfpr *x) -{ - return (*x < 0.0); -} - -#define myfp_Add(r, a, b) (*r) = ((*a) + (*b)) -#define myfp_Sub(r, a, b) (*r) = ((*a) - (*b)) -#define myfp_Mul(r, a, b) (*r) = ((*a) * (*b)) -#define myfp_Div(r, a, b) (*r) = ((*a) / (*b)) -#define myfp_Mod(r, a, b) (*r) = (fmod((*a), (*b))) -#define myfp_Rem(r, a, b) (*r) = (remainder((*a), (*b))) - -LOCALPROC myfp_Scale(myfpr *r, myfpr *a, myfpr *b) -{ - myfpr fscaleval; - fscaleval = (*b < 0.0) ? ceil(*b) : floor(*b); - *r = *a * pow(2.0, fscaleval); -} - -LOCALPROC myfp_GetMan(myfpr *r, myfpr *x) -{ - int expval; - - *r = frexp(*x, &expval) * 2.0; -} - -LOCALPROC myfp_GetExp(myfpr *r, myfpr *x) -{ - int expval; - - (void) frexp(*x, &expval); - *r = (myfpr) (expval - 1); -} - -LOCALPROC myfp_IntRZ(myfpr *r, myfpr *x) -{ - *r = (*x < 0.0) ? ceil(*x) : floor(*x); -} - -LOCALPROC myfp_Int(myfpr *r, myfpr *x) -{ - /* Should take the current rounding mode into account, don't */ - *r = floor(*x + 0.5); -} - -#define myfp_RoundToSingle(r, x) (*r) = ((myfpr)(float)(*x)) -#define myfp_RoundToDouble(r, x) (*r) = ((myfpr)(double)(*x)) - -#define myfp_Abs(r, x) (*r) = (((*x) < 0) ? - (*x) : (*x)) -#define myfp_Neg(r, x) (*r) = (- (*x)) -#define myfp_Sqrt(r, x) (*r) = (sqrt(*x)) - -#define myfp_TenToX(r, x) (*r) = (pow(10.0, *x)) -#define myfp_TwoToX(r, x) (*r) = (pow(2.0, *x)) -#define myfp_EToX(r, x) (*r) = (exp(*x)) -#define myfp_EToXM1(r, x) (*r) = (exp(*x) - 1.0) -#define myfp_Log10(r, x) (*r) = (log10(*x)) -#define myfp_Log2(r, x) (*r) = (log(*x) / log(2.0)) -#define myfp_LogN(r, x) (*r) = (log(*x)) -#define myfp_LogNP1(r, x) (*x) = (log(*x + 1.0)) - -#define myfp_Sin(r, x) (*r) = (sin(*x)) -#define myfp_Cos(r, x) (*r) = (cos(*x)) -#define myfp_Tan(r, x) (*r) = (tan(*x)) - -#define myfp_ASin(r, x) (*r) = (asin(*x)) -#define myfp_ACos(r, x) (*r) = (acos(*x)) -#define myfp_ATan(r, x) (*r) = (atan(*x)) - -#define myfp_Sinh(r, x) (*r) = (sinh(*x)) -#define myfp_Cosh(r, x) (*r) = (cosh(*x)) -#define myfp_Tanh(r, x) (*r) = (tanh(*x)) - -#define myfp_ATanh(r, x) (*r) = (atanh(*x)) - -LOCALPROC myfp_SinCos(myfpr *r_sin, myfpr *r_cos, myfpr *source) -{ - *r_sin = sin(*source); - *r_cos = cos(*source); -} - -LOCALFUNC blnr myfp_getCR(myfpr *r, ui4b opmode) -{ - myfpr v; - - switch (opmode) { - case 0x00: - v = M_PI; - break; - case 0x0B: - v = log10(2.0); - break; - case 0x0C: - v = exp(1.0); - break; - case 0x0D: - v = 1.0 / log(2.0); - break; - case 0x0E: - v = 1.0 / log(10.0); - break; - case 0x0F: - v = 0.0; - break; - case 0x30: - v = log(2.0); - break; - case 0x31: - v = log(10.0); - break; - case 0x32: - v = 1.0; - break; - case 0x33: - v = 10.0; - break; - case 0x34: - v = 100.0; - break; - case 0x35: - v = 10000.0; - break; - case 0x36: - v = 1.0e8; - break; - case 0x37: - v = 1.0e16; - break; - case 0x38: - v = 1.0e32; - break; - case 0x39: - v = 1.0e64; - break; - case 0x3A: - v = 1.0e128; - break; - case 0x3B: - v = 1.0e256; - break; - case 0x3C: - v = 1.0e512; - break; - case 0x3D: - v = 1.0e1024; - break; - case 0x3E: - v = 1.0e2048; - break; - case 0x3F: - v = 1.0e4096; - break; - default: - return falseblnr; - } - - *r = v; - return trueblnr; -} - -LOCALVAR struct myfp_envStruct -{ - ui5r FPCR; /* Floating point control register */ - ui5r FPSR; /* Floating point status register */ -} myfp_env; - -LOCALPROC myfp_SetFPCR(ui5r v) -{ - myfp_env.FPCR = v; -} - -LOCALPROC myfp_SetFPSR(ui5r v) -{ - myfp_env.FPSR = v; -} - -LOCALFUNC ui5r myfp_GetFPCR(void) -{ - return myfp_env.FPCR; -} - -LOCALFUNC ui5r myfp_GetFPSR(void) -{ - return myfp_env.FPSR; -} - -LOCALFUNC ui3r myfp_GetConditionCodeByte(void) -{ - return (myfp_env.FPSR >> 24) & 0x0F; -} - -LOCALPROC myfp_SetConditionCodeByte(ui3r v) -{ - myfp_env.FPSR = ((myfp_env.FPSR & 0x00FFFFFF) - | (v << 24)); -} - -LOCALPROC myfp_SetConditionCodeByteFromResult(myfpr *result) -{ - /* Set condition codes here based on result */ - - int c_nan = myfp_IsNan(result) ? 1 : 0; - int c_inf = myfp_IsInf(result) ? 1 : 0; - int c_zero = myfp_IsZero(result) ? 1 : 0; - int c_neg = myfp_IsNeg(result) ? 1 : 0; - - myfp_SetConditionCodeByte(c_nan - | (c_inf << 1) - | (c_zero << 2) - | (c_neg << 3)); -} diff --git a/Mini vMac/mnvm_core/GLOBGLUE.c b/Mini vMac/mnvm_core/GLOBGLUE.c index 8145bd1..5f61e70 100755 --- a/Mini vMac/mnvm_core/GLOBGLUE.c +++ b/Mini vMac/mnvm_core/GLOBGLUE.c @@ -1,1743 +1 @@ -/* - GLOBGLUE.c - - Copyright (C) 2003 Bernd Schmidt, Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - GLOBal GLUE (or GLOB of GLUE) - - Holds the program together. - - Some code here adapted from "custom.c" in vMac by Philip Cummins, - in turn descended from code in the Un*x Amiga Emulator by - Bernd Schmidt. -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" - -#include "MYOSGLUE.h" -#include "ENDIANAC.h" -#include "EMCONFIG.h" -#endif - -#include "GLOBGLUE.h" - -IMPORTPROC m68k_reset(void); -IMPORTPROC IWM_Reset(void); -IMPORTPROC SCC_Reset(void); -IMPORTPROC SCSI_Reset(void); -IMPORTPROC VIA1_Reset(void); -#if EmVIA2 -IMPORTPROC VIA2_Reset(void); -#endif -IMPORTPROC Sony_Reset(void); - -IMPORTPROC ExtnDisk_Access(CPTR p); -IMPORTPROC ExtnSony_Access(CPTR p); -#if EmVidCard -IMPORTPROC ExtnVideo_Access(CPTR p); -#endif - -IMPORTPROC Sony_SetQuitOnEject(void); - -IMPORTPROC m68k_IPLchangeNtfy(void); -IMPORTPROC MINEM68K_Init( - ui3b *fIPL); - -IMPORTFUNC ui5b GetCyclesRemaining(void); -IMPORTPROC SetCyclesRemaining(ui5b n); - -IMPORTPROC SetHeadATTel(ATTep p); -IMPORTFUNC ATTep FindATTel(CPTR addr); - -IMPORTFUNC ui5b SCSI_Access(ui5b Data, blnr WriteMem, CPTR addr); -IMPORTFUNC ui5b SCC_Access(ui5b Data, blnr WriteMem, CPTR addr); -IMPORTFUNC ui5b IWM_Access(ui5b Data, blnr WriteMem, CPTR addr); -IMPORTFUNC ui5b VIA1_Access(ui5b Data, blnr WriteMem, CPTR addr); -#if EmVIA2 -IMPORTFUNC ui5b VIA2_Access(ui5b Data, blnr WriteMem, CPTR addr); -#endif -#if EmASC -IMPORTFUNC ui5b ASC_Access(ui5b Data, blnr WriteMem, CPTR addr); -#endif - -IMPORTFUNC ui3r get_vm_byte(CPTR addr); -IMPORTFUNC ui4r get_vm_word(CPTR addr); -IMPORTFUNC ui5r get_vm_long(CPTR addr); - -IMPORTPROC put_vm_byte(CPTR addr, ui3r b); -IMPORTPROC put_vm_word(CPTR addr, ui4r w); -IMPORTPROC put_vm_long(CPTR addr, ui5r l); - -GLOBALVAR ui5r my_disk_icon_addr; - -GLOBALPROC customreset(void) -{ - IWM_Reset(); - SCC_Reset(); - SCSI_Reset(); - VIA1_Reset(); -#if EmVIA2 - VIA2_Reset(); -#endif - Sony_Reset(); - Extn_Reset(); -#if CurEmMd <= kEmMd_Plus - WantMacReset = trueblnr; - /* - kludge, code in Finder appears - to do RESET and not expect - to come back. Maybe asserting - the RESET somehow causes - other hardware compenents to - later reset the 68000. - */ -#endif -} - -GLOBALVAR ui3p RAM = nullpr; - -#if EmVidCard -GLOBALVAR ui3p VidROM = nullpr; -#endif - -#if IncludeVidMem -GLOBALVAR ui3p VidMem = nullpr; -#endif - -GLOBALVAR ui3b Wires[kNumWires]; - - -#if WantDisasm -IMPORTPROC m68k_WantDisasmContext(void); -#endif - -#if WantDisasm -GLOBALPROC dbglog_StartLine(void) -{ - m68k_WantDisasmContext(); - dbglog_writeCStr(" "); -} -#endif - -#if dbglog_HAVE -GLOBALPROC dbglog_WriteMemArrow(blnr WriteMem) -{ - if (WriteMem) { - dbglog_writeCStr(" <- "); - } else { - dbglog_writeCStr(" -> "); - } -} -#endif - -#if dbglog_HAVE -GLOBALPROC dbglog_AddrAccess(char *s, ui5r Data, - blnr WriteMem, ui5r addr) -{ - dbglog_StartLine(); - dbglog_writeCStr(s); - dbglog_writeCStr("["); - dbglog_writeHex(addr); - dbglog_writeCStr("]"); - dbglog_WriteMemArrow(WriteMem); - dbglog_writeHex(Data); - dbglog_writeReturn(); -} -#endif - -#if dbglog_HAVE -GLOBALPROC dbglog_Access(char *s, ui5r Data, blnr WriteMem) -{ - dbglog_StartLine(); - dbglog_writeCStr(s); - dbglog_WriteMemArrow(WriteMem); - dbglog_writeHex(Data); - dbglog_writeReturn(); -} -#endif - -#if dbglog_HAVE -GLOBALPROC dbglog_WriteNote(char *s) -{ - dbglog_StartLine(); - dbglog_writeCStr(s); - dbglog_writeReturn(); -} -#endif - -#if dbglog_HAVE -GLOBALPROC dbglog_WriteSetBool(char *s, blnr v) -{ - dbglog_StartLine(); - dbglog_writeCStr(s); - dbglog_writeCStr(" <- "); - if (v) { - dbglog_writeCStr("1"); - } else { - dbglog_writeCStr("0"); - } - dbglog_writeReturn(); -} -#endif - -LOCALVAR blnr GotOneAbnormal = falseblnr; - -#ifndef ReportAbnormalInterrupt -#define ReportAbnormalInterrupt 0 -#endif - -#if dbglog_HAVE -GLOBALPROC DoReportAbnormal(char *s) -#else -GLOBALPROC DoReportAbnormal(void) -#endif -{ -#if dbglog_HAVE - dbglog_StartLine(); - dbglog_writeCStr("*** abnormal : "); - dbglog_writeCStr(s); - dbglog_writeReturn(); -#endif - if (! GotOneAbnormal) { - WarnMsgAbnormal(); -#if ReportAbnormalInterrupt - SetInterruptButton(trueblnr); -#endif - GotOneAbnormal = trueblnr; - } -} - -/* map of address space */ - -#define kRAM_Base 0x00000000 /* when overlay off */ -#if (CurEmMd == kEmMd_PB100) -#define kRAM_ln2Spc 23 -#elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) -#define kRAM_ln2Spc 23 -#else -#define kRAM_ln2Spc 22 -#endif - -#if IncludeVidMem -#if CurEmMd == kEmMd_PB100 -#define kVidMem_Base 0x00FA0000 -#define kVidMem_ln2Spc 16 -#else -#define kVidMem_Base 0x00540000 -#define kVidMem_ln2Spc 18 -#endif -#endif - -#if CurEmMd == kEmMd_PB100 -#define kSCSI_Block_Base 0x00F90000 -#define kSCSI_ln2Spc 16 -#else -#define kSCSI_Block_Base 0x00580000 -#define kSCSI_ln2Spc 19 -#endif - -#define kRAM_Overlay_Base 0x00600000 /* when overlay on */ -#define kRAM_Overlay_Top 0x00800000 - -#if CurEmMd == kEmMd_PB100 -#define kSCCRd_Block_Base 0x00FD0000 -#define kSCC_ln2Spc 16 -#else -#define kSCCRd_Block_Base 0x00800000 -#define kSCC_ln2Spc 22 -#endif - -#if CurEmMd != kEmMd_PB100 -#define kSCCWr_Block_Base 0x00A00000 -#define kSCCWr_Block_Top 0x00C00000 -#endif - -#if CurEmMd == kEmMd_PB100 -#define kIWM_Block_Base 0x00F60000 -#define kIWM_ln2Spc 16 -#else -#define kIWM_Block_Base 0x00C00000 -#define kIWM_ln2Spc 21 -#endif - -#if CurEmMd == kEmMd_PB100 -#define kVIA1_Block_Base 0x00F70000 -#define kVIA1_ln2Spc 16 -#else -#define kVIA1_Block_Base 0x00E80000 -#define kVIA1_ln2Spc 19 -#endif - -#if CurEmMd == kEmMd_PB100 -#define kASC_Block_Base 0x00FB0000 -#define kASC_ln2Spc 16 -#endif -#define kASC_Mask 0x00000FFF - - -#if IncludeExtnPbufs -LOCALFUNC tMacErr PbufTransferVM(CPTR Buffera, - tPbuf i, ui5r offset, ui5r count, blnr IsWrite) -{ - tMacErr result; - ui5b contig; - ui3p Buffer; - -label_1: - if (0 == count) { - result = mnvm_noErr; - } else { - Buffer = get_real_address0(count, ! IsWrite, Buffera, &contig); - if (0 == contig) { - result = mnvm_miscErr; - } else { - PbufTransfer(Buffer, i, offset, contig, IsWrite); - offset += contig; - Buffera += contig; - count -= contig; - goto label_1; - } - } - - return result; -} -#endif - -/* extension mechanism */ - -#if IncludeExtnPbufs -#define kCmndPbufFeatures 1 -#define kCmndPbufNew 2 -#define kCmndPbufDispose 3 -#define kCmndPbufGetSize 4 -#define kCmndPbufTransfer 5 -#endif - -#if IncludeExtnPbufs -LOCALPROC ExtnParamBuffers_Access(CPTR p) -{ - tMacErr result = mnvm_controlErr; - - switch (get_vm_word(p + ExtnDat_commnd)) { - case kCmndVersion: - put_vm_word(p + ExtnDat_version, 1); - result = mnvm_noErr; - break; - case kCmndPbufFeatures: - put_vm_long(p + ExtnDat_params + 0, 0); - result = mnvm_noErr; - break; - case kCmndPbufNew: - { - tPbuf Pbuf_No; - ui5b count = get_vm_long(p + ExtnDat_params + 4); - /* reserved word at offset 2, should be zero */ - result = PbufNew(count, &Pbuf_No); - put_vm_word(p + ExtnDat_params + 0, Pbuf_No); - } - break; - case kCmndPbufDispose: - { - tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 0); - /* reserved word at offset 2, should be zero */ - result = CheckPbuf(Pbuf_No); - if (mnvm_noErr == result) { - PbufDispose(Pbuf_No); - } - } - break; - case kCmndPbufGetSize: - { - ui5r Count; - tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 0); - /* reserved word at offset 2, should be zero */ - - result = PbufGetSize(Pbuf_No, &Count); - if (mnvm_noErr == result) { - put_vm_long(p + ExtnDat_params + 4, Count); - } - } - break; - case kCmndPbufTransfer: - { - ui5r PbufCount; - tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 0); - /* reserved word at offset 2, should be zero */ - ui5r offset = get_vm_long(p + ExtnDat_params + 4); - ui5r count = get_vm_long(p + ExtnDat_params + 8); - CPTR Buffera = get_vm_long(p + ExtnDat_params + 12); - blnr IsWrite = - (get_vm_word(p + ExtnDat_params + 16) != 0); - result = PbufGetSize(Pbuf_No, &PbufCount); - if (mnvm_noErr == result) { - ui5r endoff = offset + count; - if ((endoff < offset) /* overflow */ - || (endoff > PbufCount)) - { - result = mnvm_eofErr; - } else { - result = PbufTransferVM(Buffera, - Pbuf_No, offset, count, IsWrite); - } - } - } - break; - } - - put_vm_word(p + ExtnDat_result, result); -} -#endif - -#if IncludeExtnHostTextClipExchange -#define kCmndHTCEFeatures 1 -#define kCmndHTCEExport 2 -#define kCmndHTCEImport 3 -#endif - -#if IncludeExtnHostTextClipExchange -LOCALPROC ExtnHostTextClipExchange_Access(CPTR p) -{ - tMacErr result = mnvm_controlErr; - - switch (get_vm_word(p + ExtnDat_commnd)) { - case kCmndVersion: - put_vm_word(p + ExtnDat_version, 1); - result = mnvm_noErr; - break; - case kCmndHTCEFeatures: - put_vm_long(p + ExtnDat_params + 0, 0); - result = mnvm_noErr; - break; - case kCmndHTCEExport: - { - tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 0); - - result = CheckPbuf(Pbuf_No); - if (mnvm_noErr == result) { - result = HTCEexport(Pbuf_No); - } - } - break; - case kCmndHTCEImport: - { - tPbuf Pbuf_No; - result = HTCEimport(&Pbuf_No); - put_vm_word(p + ExtnDat_params + 0, Pbuf_No); - } - break; - } - - put_vm_word(p + ExtnDat_result, result); -} -#endif - -#define kFindExtnExtension 0x64E1F58A -#define kDiskDriverExtension 0x4C9219E6 -#if IncludeExtnPbufs -#define kHostParamBuffersExtension 0x314C87BF -#endif -#if IncludeExtnHostTextClipExchange -#define kHostClipExchangeExtension 0x27B130CA -#endif - -#define kCmndFindExtnFind 1 -#define kCmndFindExtnId2Code 2 -#define kCmndFindExtnCount 3 - -#define kParamFindExtnTheExtn 8 -#define kParamFindExtnTheId 12 - -LOCALPROC ExtnFind_Access(CPTR p) -{ - tMacErr result = mnvm_controlErr; - - switch (get_vm_word(p + ExtnDat_commnd)) { - case kCmndVersion: - put_vm_word(p + ExtnDat_version, 1); - result = mnvm_noErr; - break; - case kCmndFindExtnFind: - { - ui5b extn = get_vm_long(p + kParamFindExtnTheExtn); - - if (extn == kDiskDriverExtension) { - put_vm_word(p + kParamFindExtnTheId, kExtnDisk); - result = mnvm_noErr; - } else -#if IncludeExtnPbufs - if (extn == kHostParamBuffersExtension) { - put_vm_word(p + kParamFindExtnTheId, - kExtnParamBuffers); - result = mnvm_noErr; - } else -#endif -#if IncludeExtnHostTextClipExchange - if (extn == kHostClipExchangeExtension) { - put_vm_word(p + kParamFindExtnTheId, - kExtnHostTextClipExchange); - result = mnvm_noErr; - } else -#endif - if (extn == kFindExtnExtension) { - put_vm_word(p + kParamFindExtnTheId, - kExtnFindExtn); - result = mnvm_noErr; - } else - { - /* not found */ - } - } - break; - case kCmndFindExtnId2Code: - { - ui4r extn = get_vm_word(p + kParamFindExtnTheId); - - if (extn == kExtnDisk) { - put_vm_long(p + kParamFindExtnTheExtn, - kDiskDriverExtension); - result = mnvm_noErr; - } else -#if IncludeExtnPbufs - if (extn == kExtnParamBuffers) { - put_vm_long(p + kParamFindExtnTheExtn, - kHostParamBuffersExtension); - result = mnvm_noErr; - } else -#endif -#if IncludeExtnHostTextClipExchange - if (extn == kExtnHostTextClipExchange) { - put_vm_long(p + kParamFindExtnTheExtn, - kHostClipExchangeExtension); - result = mnvm_noErr; - } else -#endif - if (extn == kExtnFindExtn) { - put_vm_long(p + kParamFindExtnTheExtn, - kFindExtnExtension); - result = mnvm_noErr; - } else - { - /* not found */ - } - } - break; - case kCmndFindExtnCount: - put_vm_word(p + kParamFindExtnTheId, kNumExtns); - result = mnvm_noErr; - break; - } - - put_vm_word(p + ExtnDat_result, result); -} - -#define kDSK_Params_Hi 0 -#define kDSK_Params_Lo 1 -#define kDSK_QuitOnEject 3 /* obsolete */ - -LOCALVAR ui4b ParamAddrHi; - -LOCALPROC Extn_Access(ui5b Data, CPTR addr) -{ - switch (addr) { - case kDSK_Params_Hi: - ParamAddrHi = Data; - break; - case kDSK_Params_Lo: - { - CPTR p = ParamAddrHi << 16 | Data; - - ParamAddrHi = (ui4b) - 1; - if (kcom_callcheck == get_vm_word(p + ExtnDat_checkval)) - { - put_vm_word(p + ExtnDat_checkval, 0); - - switch (get_vm_word(p + ExtnDat_extension)) { - case kExtnFindExtn: - ExtnFind_Access(p); - break; -#if EmVidCard - case kExtnVideo: - ExtnVideo_Access(p); - break; -#endif -#if IncludeExtnPbufs - case kExtnParamBuffers: - ExtnParamBuffers_Access(p); - break; -#endif -#if IncludeExtnHostTextClipExchange - case kExtnHostTextClipExchange: - ExtnHostTextClipExchange_Access(p); - break; -#endif - case kExtnDisk: - ExtnDisk_Access(p); - break; - case kExtnSony: - ExtnSony_Access(p); - break; - default: - put_vm_word(p + ExtnDat_result, - mnvm_controlErr); - break; - } - } - } - break; - case kDSK_QuitOnEject: - /* obsolete, kept for compatibility */ - Sony_SetQuitOnEject(); - break; - } -} - -GLOBALPROC Extn_Reset(void) -{ - ParamAddrHi = (ui4b) - 1; -} - -/* implementation of read/write for everything but RAM and ROM */ - -#define kSCC_Mask 0x03 - -#define kVIA1_Mask 0x00000F -#if EmVIA2 -#define kVIA2_Mask 0x00000F -#endif - -#define kIWM_Mask 0x00000F /* Allocated Memory Bandwidth for IWM */ - -#if CurEmMd <= kEmMd_512Ke -#define ROM_CmpZeroMask 0 -#elif CurEmMd <= kEmMd_Plus -#define ROM_CmpZeroMask 0x00020000 -#elif CurEmMd <= kEmMd_PB100 -#define ROM_CmpZeroMask 0 -#elif CurEmMd <= kEmMd_IIx -#define ROM_CmpZeroMask 0 -#else -#error "ROM_CmpZeroMask not defined" -#endif - -#define kROM_cmpmask (0x00F00000 | ROM_CmpZeroMask) - -#if CurEmMd <= kEmMd_512Ke -#define Overlay_ROM_CmpZeroMask 0x00100000 -#elif CurEmMd <= kEmMd_Plus -#define Overlay_ROM_CmpZeroMask 0x00020000 -#elif CurEmMd <= kEmMd_Classic -#define Overlay_ROM_CmpZeroMask 0x00300000 -#elif CurEmMd <= kEmMd_PB100 -#define Overlay_ROM_CmpZeroMask 0 -#elif CurEmMd <= kEmMd_IIx -#define Overlay_ROM_CmpZeroMask 0 -#else -#error "Overlay_ROM_CmpZeroMask not defined" -#endif - -enum { - kMMDV_VIA1, -#if EmVIA2 - kMMDV_VIA2, -#endif - kMMDV_SCC, - kMMDV_Extn, -#if EmASC - kMMDV_ASC, -#endif - kMMDV_SCSI, - kMMDV_IWM, - - kNumMMDVs -}; - -enum { -#if CurEmMd >= kEmMd_SE - kMAN_OverlayOff, -#endif - - kNumMANs -}; - - -LOCALVAR ATTer ATTListA[MaxATTListN]; -LOCALVAR ui4r LastATTel; - - -LOCALPROC AddToATTList(ATTep p) -{ - ui4r NewLast = LastATTel + 1; - if (NewLast >= MaxATTListN) { - ReportAbnormal("MaxATTListN not big enough"); - } else { - ATTListA[LastATTel] = *p; - LastATTel = NewLast; - } -} - -LOCALPROC InitATTList(void) -{ - LastATTel = 0; -} - -LOCALPROC FinishATTList(void) -{ - { - /* add guard */ - ATTer r; - - r.cmpmask = 0; - r.cmpvalu = 0; - r.usemask = 0; - r.usebase = nullpr; - r.Access = 0; - AddToATTList(&r); - } - - { - ui4r i = LastATTel; - ATTep p = &ATTListA[LastATTel]; - ATTep h = nullpr; - - while (0 != i) { - --i; - --p; - p->Next = h; - h = p; - } - -#if 0 /* verify list. not for final version */ - { - ATTep q1; - ATTep q2; - for (q1 = h; nullpr != q1->Next; q1 = q1->Next) { - if ((q1->cmpvalu & ~ q1->cmpmask) != 0) { - ReportAbnormal("ATTListA bad entry"); - } - for (q2 = q1->Next; nullpr != q2->Next; q2 = q2->Next) { - ui5r common_mask = (q1->cmpmask) & (q2->cmpmask); - if ((q1->cmpvalu & common_mask) == - (q2->cmpvalu & common_mask)) - { - ReportAbnormal("ATTListA Conflict"); - } - } - } - } -#endif - - SetHeadATTel(h); - } -} - -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) -LOCALPROC SetUp_RAM24(void) -{ - ATTer r; - ui5r bankbit = 0x00100000 << (((VIA2_iA7 << 1) | VIA2_iA6) << 1); - -#if kRAMa_Size == kRAMb_Size - if (kRAMa_Size == bankbit) { - /* properly set up balanced RAM */ - r.cmpmask = 0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1); - r.cmpvalu = 0; - r.usemask = ((1 << kRAM_ln2Spc) - 1) & (kRAM_Size - 1); - r.usebase = RAM; - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); - } else -#endif - { - bankbit &= 0x00FFFFFF; /* if too large, always use RAMa */ - - if (0 != bankbit) { -#if kRAMb_Size != 0 - r.cmpmask = bankbit - | (0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1)); - r.cmpvalu = bankbit; - r.usemask = ((1 << kRAM_ln2Spc) - 1) & (kRAMb_Size - 1); - r.usebase = kRAMa_Size + RAM; - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); -#endif - } - - { - r.cmpmask = bankbit - | (0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1)); - r.cmpvalu = 0; - r.usemask = ((1 << kRAM_ln2Spc) - 1) & (kRAMa_Size - 1); - r.usebase = RAM; - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); - } - } -} -#endif - -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) -LOCALPROC SetUp_io(void) -{ - ATTer r; - - if (Addr32) { - r.cmpmask = 0xFF01E000; - r.cmpvalu = 0x50000000; - } else { - r.cmpmask = 0x00F1E000; - r.cmpvalu = 0x00F00000; - } - r.usebase = nullpr; - r.Access = kATTA_mmdvmask; - r.MMDV = kMMDV_VIA1; - AddToATTList(&r); - - if (Addr32) { - r.cmpmask = 0xFF01E000; - r.cmpvalu = 0x50000000 | 0x2000; - } else { - r.cmpmask = 0x00F1E000; - r.cmpvalu = 0x00F00000 | 0x2000; - } - r.usebase = nullpr; - r.Access = kATTA_mmdvmask; - r.MMDV = kMMDV_VIA2; - AddToATTList(&r); - - if (Addr32) { - r.cmpmask = 0xFF01E000; - r.cmpvalu = 0x50000000 | 0x4000; - } else { - r.cmpmask = 0x00F1E000; - r.cmpvalu = 0x00F00000 | 0x4000; - } - r.usebase = nullpr; - r.Access = kATTA_mmdvmask; - r.MMDV = kMMDV_SCC; - AddToATTList(&r); - - if (Addr32) { - r.cmpmask = 0xFF01E000; - r.cmpvalu = 0x50000000 | 0x0C000; - } else { - r.cmpmask = 0x00F1E000; - r.cmpvalu = 0x00F00000 | 0x0C000; - } - r.usebase = nullpr; - r.Access = kATTA_mmdvmask; - r.MMDV = kMMDV_Extn; - AddToATTList(&r); - - if (Addr32) { - r.cmpmask = 0xFF01E000; - r.cmpvalu = 0x50000000 | 0x10000; - } else { - r.cmpmask = 0x00F1E000; - r.cmpvalu = 0x00F00000 | 0x10000; - } - r.usebase = nullpr; - r.Access = kATTA_mmdvmask; - r.MMDV = kMMDV_SCSI; - AddToATTList(&r); - - if (Addr32) { - r.cmpmask = 0xFF01E000; - r.cmpvalu = 0x50000000 | 0x14000; - } else { - r.cmpmask = 0x00F1E000; - r.cmpvalu = 0x00F00000 | 0x14000; - } - r.usebase = nullpr; - r.Access = kATTA_mmdvmask; - r.MMDV = kMMDV_ASC; - AddToATTList(&r); - - if (Addr32) { - r.cmpmask = 0xFF01E000; - r.cmpvalu = 0x50000000 | 0x16000; - } else { - r.cmpmask = 0x00F1E000; - r.cmpvalu = 0x00F00000 | 0x16000; - } - r.usebase = nullpr; - r.Access = kATTA_mmdvmask; - r.MMDV = kMMDV_IWM; - AddToATTList(&r); - -#if 0 - case 14: - /* - fail, nothing supposed to be here, - but rom accesses it anyway - */ - { - ui5r addr2 = addr & 0x1FFFF; - - if ((addr2 != 0x1DA00) && (addr2 != 0x1DC00)) { - ReportAbnormal("another unknown access"); - } - } - get_fail_realblock(p); - break; -#endif -} -#endif - -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) -LOCALPROC SetUp_address24(void) -{ - ATTer r; - - if (MemOverlay) { - ReportAbnormal("Overlay with 24 bit addressing"); - } - - if (MemOverlay) { - r.cmpmask = Overlay_ROM_CmpZeroMask | - (0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1)); - r.cmpvalu = kRAM_Base; - r.usemask = kROM_Size - 1; - r.usebase = ROM; - r.Access = kATTA_readreadymask; - AddToATTList(&r); - } else { - SetUp_RAM24(); - } - - r.cmpmask = kROM_cmpmask; - r.cmpvalu = kROM_Base; - r.usemask = kROM_Size - 1; - r.usebase = ROM; - r.Access = kATTA_readreadymask; - AddToATTList(&r); - - r.cmpmask = 0x00FFFFFF & ~ (0x100000 - 1); - r.cmpvalu = 0x900000; - r.usemask = (kVidMemRAM_Size - 1) & (0x100000 - 1); - r.usebase = VidMem; - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); -#if kVidMemRAM_Size >= 0x00200000 - r.cmpmask = 0x00FFFFFF & ~ (0x100000 - 1); - r.cmpvalu = 0xA00000; - r.usemask = (0x100000 - 1); - r.usebase = VidMem + (1 << 20); - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); -#endif -#if kVidMemRAM_Size >= 0x00400000 - r.cmpmask = 0x00FFFFFF & ~ (0x100000 - 1); - r.cmpvalu = 0xB00000; - r.usemask = (0x100000 - 1); - r.usebase = VidMem + (2 << 20); - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); - r.cmpmask = 0x00FFFFFF & ~ (0x100000 - 1); - r.cmpvalu = 0xC00000; - r.usemask = (0x100000 - 1); - r.usebase = VidMem + (3 << 20); - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); -#endif - - SetUp_io(); -} -#endif - -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) -LOCALPROC SetUp_address32(void) -{ - ATTer r; - - if (MemOverlay) { - r.cmpmask = ~ ((1 << 30) - 1); - r.cmpvalu = 0; - r.usemask = kROM_Size - 1; - r.usebase = ROM; - r.Access = kATTA_readreadymask; - AddToATTList(&r); - } else { - ui5r bankbit = - 0x00100000 << (((VIA2_iA7 << 1) | VIA2_iA6) << 1); -#if kRAMa_Size == kRAMb_Size - if (kRAMa_Size == bankbit) { - /* properly set up balanced RAM */ - r.cmpmask = ~ ((1 << 30) - 1); - r.cmpvalu = 0; - r.usemask = kRAM_Size - 1; - r.usebase = RAM; - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); - } else -#endif - { -#if kRAMb_Size != 0 - r.cmpmask = bankbit | ~ ((1 << 30) - 1); - r.cmpvalu = bankbit; - r.usemask = kRAMb_Size - 1; - r.usebase = kRAMa_Size + RAM; - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); -#endif - - r.cmpmask = bankbit | ~ ((1 << 30) - 1); - r.cmpvalu = 0; - r.usemask = kRAMa_Size - 1; - r.usebase = RAM; - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); - } - } - - r.cmpmask = ~ ((1 << 28) - 1); - r.cmpvalu = 0x40000000; - r.usemask = kROM_Size - 1; - r.usebase = ROM; - r.Access = kATTA_readreadymask; - AddToATTList(&r); - -#if 0 - /* haven't persuaded emulated computer to look here yet. */ - /* NuBus super space */ - r.cmpmask = ~ ((1 << 28) - 1); - r.cmpvalu = 0x90000000; - r.usemask = kVidMemRAM_Size - 1; - r.usebase = VidMem; - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); -#endif - - /* Standard NuBus space */ - r.cmpmask = ~ ((1 << 20) - 1); - r.cmpvalu = 0xF9F00000; - r.usemask = kVidROM_Size - 1; - r.usebase = VidROM; - r.Access = kATTA_readreadymask; - AddToATTList(&r); -#if 0 - r.cmpmask = ~ 0x007FFFFF; - r.cmpvalu = 0xF9000000; - r.usemask = 0x007FFFFF & (kVidMemRAM_Size - 1); - r.usebase = VidMem; - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); -#endif - - r.cmpmask = ~ 0x000FFFFF; - r.cmpvalu = 0xF9900000; - r.usemask = 0x000FFFFF & (kVidMemRAM_Size - 1); - r.usebase = VidMem; - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); -/* kludge to allow more than 1M of Video Memory */ -#if kVidMemRAM_Size >= 0x00200000 - r.cmpmask = ~ 0x000FFFFF; - r.cmpvalu = 0xF9A00000; - r.usemask = 0x000FFFFF & (kVidMemRAM_Size - 1); - r.usebase = VidMem + (1 << 20); - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); -#endif -#if kVidMemRAM_Size >= 0x00400000 - r.cmpmask = ~ 0x000FFFFF; - r.cmpvalu = 0xF9B00000; - r.usemask = 0x000FFFFF & (kVidMemRAM_Size - 1); - r.usebase = VidMem + (2 << 20); - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); - r.cmpmask = ~ 0x000FFFFF; - r.cmpvalu = 0xF9C00000; - r.usemask = 0x000FFFFF & (kVidMemRAM_Size - 1); - r.usebase = VidMem + (3 << 20); - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); -#endif - - SetUp_io(); - -#if 0 - if ((addr >= 0x58000000) && (addr < 0x58000004)) { - /* test hardware. fail */ - } -#endif -} -#endif - -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) -LOCALPROC SetUp_address(void) -{ - if (Addr32) { - SetUp_address32(); - } else { - SetUp_address24(); - } -} -#endif - -/* - unlike in the real Mac Plus, Mini vMac - will allow misaligned memory access, - since it is easier to allow it than - it is to correctly simulate a bus error - and back out of the current instruction. -*/ - -#if (CurEmMd != kEmMd_II) && (CurEmMd != kEmMd_IIx) -LOCALPROC SetUp_RAM24(void) -{ - ATTer r; - -#if (0 == kRAMb_Size) || (kRAMa_Size == kRAMb_Size) - r.cmpmask = 0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1); - r.cmpvalu = kRAM_Base; - r.usemask = kRAM_Size - 1; - r.usebase = RAM; - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); -#else - /* unbalanced memory */ - -#if 0 != (0x00FFFFFF & kRAMa_Size) - /* condition should always be true if configuration file right */ - r.cmpmask = 0x00FFFFFF & (kRAMa_Size | ~ ((1 << kRAM_ln2Spc) - 1)); - r.cmpvalu = kRAM_Base + kRAMa_Size; - r.usemask = kRAMb_Size - 1; - r.usebase = kRAMa_Size + RAM; - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); -#endif - - r.cmpmask = 0x00FFFFFF & (kRAMa_Size | ~ ((1 << kRAM_ln2Spc) - 1)); - r.cmpvalu = kRAM_Base; - r.usemask = kRAMa_Size - 1; - r.usebase = RAM; - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); -#endif -} -#endif - -#if (CurEmMd != kEmMd_II) && (CurEmMd != kEmMd_IIx) -LOCALPROC SetUp_address(void) -{ - ATTer r; - - if (MemOverlay) { - r.cmpmask = Overlay_ROM_CmpZeroMask | - (0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1)); - r.cmpvalu = kRAM_Base; - r.usemask = kROM_Size - 1; - r.usebase = ROM; - r.Access = kATTA_readreadymask; - AddToATTList(&r); - } else { - SetUp_RAM24(); - } - - r.cmpmask = kROM_cmpmask; - r.cmpvalu = kROM_Base; -#if (CurEmMd >= kEmMd_SE) - if (MemOverlay) { - r.usebase = nullpr; - r.Access = kATTA_ntfymask; - r.Ntfy = kMAN_OverlayOff; - } else -#endif - { - r.usemask = kROM_Size - 1; - r.usebase = ROM; - r.Access = kATTA_readreadymask; - } - AddToATTList(&r); - - if (MemOverlay) { - r.cmpmask = 0x00E00000; - r.cmpvalu = kRAM_Overlay_Base; -#if (0 == kRAMb_Size) || (kRAMa_Size == kRAMb_Size) - r.usemask = kRAM_Size - 1; - /* note that cmpmask and usemask overlap for 4M */ - r.usebase = RAM; - r.Access = kATTA_readwritereadymask; -#else - /* unbalanced memory */ - r.usemask = kRAMb_Size - 1; - r.usebase = kRAMa_Size + RAM; - r.Access = kATTA_readwritereadymask; -#endif - AddToATTList(&r); - } - -#if IncludeVidMem - r.cmpmask = 0x00FFFFFF & ~ ((1 << kVidMem_ln2Spc) - 1); - r.cmpvalu = kVidMem_Base; - r.usemask = kVidMemRAM_Size - 1; - r.usebase = VidMem; - r.Access = kATTA_readwritereadymask; - AddToATTList(&r); -#endif - - r.cmpmask = 0x00FFFFFF & ~ ((1 << kVIA1_ln2Spc) - 1); - r.cmpvalu = kVIA1_Block_Base; - r.usebase = nullpr; - r.Access = kATTA_mmdvmask; - r.MMDV = kMMDV_VIA1; - AddToATTList(&r); - - r.cmpmask = 0x00FFFFFF & ~ ((1 << kSCC_ln2Spc) - 1); - r.cmpvalu = kSCCRd_Block_Base; - r.usebase = nullpr; - r.Access = kATTA_mmdvmask; - r.MMDV = kMMDV_SCC; - AddToATTList(&r); - - r.cmpmask = 0x00FFFFFF & ~ ((1 << kExtn_ln2Spc) - 1); - r.cmpvalu = kExtn_Block_Base; - r.usebase = nullpr; - r.Access = kATTA_mmdvmask; - r.MMDV = kMMDV_Extn; - AddToATTList(&r); - -#if CurEmMd == kEmMd_PB100 - r.cmpmask = 0x00FFFFFF & ~ ((1 << kASC_ln2Spc) - 1); - r.cmpvalu = kASC_Block_Base; - r.usebase = nullpr; - r.Access = kATTA_mmdvmask; - r.MMDV = kMMDV_ASC; - AddToATTList(&r); -#endif - - r.cmpmask = 0x00FFFFFF & ~ ((1 << kSCSI_ln2Spc) - 1); - r.cmpvalu = kSCSI_Block_Base; - r.usebase = nullpr; - r.Access = kATTA_mmdvmask; - r.MMDV = kMMDV_SCSI; - AddToATTList(&r); - - r.cmpmask = 0x00FFFFFF & ~ ((1 << kIWM_ln2Spc) - 1); - r.cmpvalu = kIWM_Block_Base; - r.usebase = nullpr; - r.Access = kATTA_mmdvmask; - r.MMDV = kMMDV_IWM; - AddToATTList(&r); -} -#endif - -LOCALPROC SetUpMemBanks(void) -{ - InitATTList(); - - SetUp_address(); - - FinishATTList(); -} - -#if 0 -LOCALPROC get_fail_realblock(ATTep p) -{ - p->cmpmask = 0; - p->cmpvalu = 0xFFFFFFFF; - p->usemask = 0; - p->usebase = nullpr; - p->Access = 0; -} -#endif - -GLOBALFUNC ui5b MMDV_Access(ATTep p, ui5b Data, - blnr WriteMem, blnr ByteSize, CPTR addr) -{ - switch (p->MMDV) { - case kMMDV_VIA1: - if (! ByteSize) { -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) - if (WriteMem && (addr == 0xF40006)) { - /* for weirdness on shutdown in System 6 */ -#if 0 - VIA1_Access((Data >> 8) & 0x00FF, WriteMem, - (addr >> 9) & kVIA1_Mask); - VIA1_Access((Data) & 0x00FF, WriteMem, - (addr >> 9) & kVIA1_Mask); -#endif - } else -#endif - { - ReportAbnormal("access VIA1 word"); - } - } else if ((addr & 1) != 0) { - ReportAbnormal("access VIA1 odd"); - } else { -#if CurEmMd != kEmMd_PB100 -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) - if ((addr & 0x000001FE) != 0x00000000) -#else - if ((addr & 0x000FE1FE) != 0x000FE1FE) -#endif - { - ReportAbnormal("access VIA1 nonstandard address"); - } -#endif - Data = VIA1_Access(Data, WriteMem, - (addr >> 9) & kVIA1_Mask); - } - - break; -#if EmVIA2 - case kMMDV_VIA2: - if (! ByteSize) { - if ((! WriteMem) - && ((0x3e00 == (addr & 0x1FFFF)) - || (0x3e02 == (addr & 0x1FFFF)))) - { - /* for weirdness at offset 0x71E in ROM */ - Data = - (VIA2_Access(Data, WriteMem, - (addr >> 9) & kVIA2_Mask) << 8) - | VIA2_Access(Data, WriteMem, - (addr >> 9) & kVIA2_Mask); - - } else { - ReportAbnormal("access VIA2 word"); - } - } else if ((addr & 1) != 0) { - if (0x3FFF == (addr & 0x1FFFF)) { - /* - for weirdness at offset 0x7C4 in ROM. - looks like bug. - */ - Data = VIA2_Access(Data, WriteMem, - (addr >> 9) & kVIA2_Mask); - } else { - ReportAbnormal("access VIA2 odd"); - } - } else { - if ((addr & 0x000001FE) != 0x00000000) { - ReportAbnormal("access VIA2 nonstandard address"); - } - Data = VIA2_Access(Data, WriteMem, - (addr >> 9) & kVIA2_Mask); - } - break; -#endif - case kMMDV_SCC: - -#if (CurEmMd >= kEmMd_SE) \ - && ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)) - - if ((addr & 0x00100000) == 0) { - ReportAbnormal("access SCC unassigned address"); - } else -#endif - if (! ByteSize) { - ReportAbnormal("Attemped Phase Adjust"); - } else -#if ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)) - if (WriteMem != ((addr & 1) != 0)) { - if (WriteMem) { -#if CurEmMd >= kEmMd_512Ke -#if CurEmMd != kEmMd_PB100 - ReportAbnormal("access SCC even/odd"); - /* - This happens on boot with 64k ROM. - */ -#endif -#endif - } else { - SCC_Reset(); - } - } else -#endif -#if (CurEmMd != kEmMd_PB100) \ - && ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)) - - if (WriteMem != (addr >= kSCCWr_Block_Base)) { - ReportAbnormal("access SCC wr/rd base wrong"); - } else -#endif - { -#if CurEmMd != kEmMd_PB100 -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) - if ((addr & 0x1FF9) != 0x00000000) -#else - if ((addr & 0x001FFFF8) != 0x001FFFF8) -#endif - { - ReportAbnormal("access SCC nonstandard address"); - } -#endif - Data = SCC_Access(Data, WriteMem, - (addr >> 1) & kSCC_Mask); - } - break; - case kMMDV_Extn: - if (ByteSize) { - ReportAbnormal("access Sony byte"); - } else if ((addr & 1) != 0) { - ReportAbnormal("access Sony odd"); - } else if (! WriteMem) { - ReportAbnormal("access Sony read"); - } else { - Extn_Access(Data, (addr >> 1) & 0x0F); - } - break; -#if EmASC - case kMMDV_ASC: - if (! ByteSize) { -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) - if (WriteMem) { - (void) ASC_Access((Data >> 8) & 0x00FF, - WriteMem, addr & kASC_Mask); - Data = ASC_Access((Data) & 0x00FF, - WriteMem, (addr + 1) & kASC_Mask); - } else { - Data = - (ASC_Access((Data >> 8) & 0x00FF, - WriteMem, addr & kASC_Mask) << 8) - | ASC_Access((Data) & 0x00FF, - WriteMem, (addr + 1) & kASC_Mask); - } -#else - ReportAbnormal("access ASC word"); -#endif - } else { - Data = ASC_Access(Data, WriteMem, addr & kASC_Mask); - } - break; -#endif - case kMMDV_SCSI: - if (! ByteSize) { - ReportAbnormal("access SCSI word"); - } else -#if ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)) - if (WriteMem != ((addr & 1) != 0)) { - ReportAbnormal("access SCSI even/odd"); - } else -#endif - { -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) - if ((addr & 0x1F8F) != 0x00000000) { - ReportAbnormal("access SCSI nonstandard address"); - } -#endif - Data = SCSI_Access(Data, WriteMem, (addr >> 4) & 0x07); - } - - break; - case kMMDV_IWM: -#if (CurEmMd >= kEmMd_SE) \ - && ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)) - - if ((addr & 0x00100000) == 0) { - ReportAbnormal("access IWM unassigned address"); - } else -#endif - if (! ByteSize) { -#if ExtraAbnormalReports - ReportAbnormal("access IWM word"); - /* - This happens when quitting 'Glider 3.1.2'. - perhaps a bad handle is being disposed of. - */ -#endif - } else -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) - if ((addr & 1) != 0) { - ReportAbnormal("access IWM odd"); - } else -#else - if ((addr & 1) == 0) { - ReportAbnormal("access IWM even"); - } else -#endif - { -#if (CurEmMd != kEmMd_PB100) \ - && ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)) - - if ((addr & 0x001FE1FF) != 0x001FE1FF) { - ReportAbnormal("access IWM nonstandard address"); - } -#endif - Data = IWM_Access(Data, WriteMem, - (addr >> 9) & kIWM_Mask); - } - - break; - } - - return Data; -} - -GLOBALFUNC blnr MemAccessNtfy(ATTep pT) -{ - blnr v = falseblnr; - - switch (pT->Ntfy) { -#if CurEmMd >= kEmMd_SE - case kMAN_OverlayOff: - pT->Access = kATTA_readreadymask; - - MemOverlay = 0; - SetUpMemBanks(); - - v = trueblnr; - - break; -#endif - } - - return v; -} - -GLOBALPROC MemOverlay_ChangeNtfy(void) -{ -#if CurEmMd <= kEmMd_Plus - SetUpMemBanks(); -#elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) - SetUpMemBanks(); -#endif -} - -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) -GLOBALPROC Addr32_ChangeNtfy(void) -{ - SetUpMemBanks(); -} -#endif - -LOCALFUNC ATTep get_address_realblock1(blnr WriteMem, CPTR addr) -{ - ATTep p; - -Label_Retry: - p = FindATTel(addr); - if (0 != (p->Access & - (WriteMem ? kATTA_writereadymask : kATTA_readreadymask))) - { - /* ok */ - } else { - if (0 != (p->Access & kATTA_ntfymask)) { - if (MemAccessNtfy(p)) { - goto Label_Retry; - } - } - p = nullpr; /* fail */ - } - - return p; -} - -GLOBALFUNC ui3p get_real_address0(ui5b L, blnr WritableMem, CPTR addr, - ui5b *actL) -{ - ui5b RealSize; - ui5b bankleft; - ui3p p; - ATTep q; - - q = get_address_realblock1(WritableMem, addr); - if (nullpr == q) { - *actL = 0; - p = nullpr; - } else { - ui5b bankoffset = addr & q->usemask; - RealSize = q->usemask + 1; - bankleft = RealSize - bankoffset; - p = bankoffset + q->usebase; - if (bankleft >= L) { - /* this block is big enough (by far the most common case) */ - *actL = L; - } else { - /* - not big enough, look if following block - is contiguous in real memory. - */ - ui3p bankend; - ui5b n = L; -label_1: - addr += bankleft; - n -= bankleft; - bankend = RealSize + q->usebase; - - q = get_address_realblock1(WritableMem, addr); - if ((nullpr == q) - || (q->usebase != bankend)) - { - /* following block not contiguous */ - *actL = L - n; - } else { - RealSize = q->usemask + 1; - if (RealSize >= n) { - /* following block is contiguous and big enough */ - *actL = L; /* ok */ - } else { - bankoffset = addr & q->usemask; - if (bankoffset != 0) { - ReportAbnormal( - "problem with get_address_realblock1"); - } - bankleft = RealSize; - goto label_1; - } - } - } - } - - return p; -} - -GLOBALVAR blnr InterruptButton = falseblnr; - -GLOBALPROC SetInterruptButton(blnr v) -{ - if (InterruptButton != v) { - InterruptButton = v; - VIAorSCCinterruptChngNtfy(); - } -} - -LOCALVAR ui3b CurIPL = 0; - -GLOBALPROC VIAorSCCinterruptChngNtfy(void) -{ -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) - ui3b NewIPL; - - if (InterruptButton) { - NewIPL = 7; - } else if (SCCInterruptRequest) { - NewIPL = 4; - } else if (VIA2_InterruptRequest) { - NewIPL = 2; - } else if (VIA1_InterruptRequest) { - NewIPL = 1; - } else { - NewIPL = 0; - } -#else - ui3b VIAandNotSCC = VIA1_InterruptRequest - & ~ SCCInterruptRequest; - ui3b NewIPL = VIAandNotSCC - | (SCCInterruptRequest << 1) - | (InterruptButton << 2); -#endif - if (NewIPL != CurIPL) { - CurIPL = NewIPL; - m68k_IPLchangeNtfy(); - } -} - -GLOBALFUNC blnr AddrSpac_Init(void) -{ - int i; - - for (i = 0; i < kNumWires; i++) { - Wires[i] = 1; - } - - MINEM68K_Init( - &CurIPL); - return trueblnr; -} - -GLOBALPROC Memory_Reset(void) -{ - MemOverlay = 1; - SetUpMemBanks(); -} - -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) -EXPORTPROC PowerOff_ChangeNtfy(void); -GLOBALPROC PowerOff_ChangeNtfy(void) -{ - if (! VIA2_iB2) { - ForceMacOff = trueblnr; - } -} -#endif - -/* user event queue utilities */ - -#if HaveMasterMyEvtQLock -GLOBALVAR ui4r MasterMyEvtQLock = 0; - /* - Takes a few ticks to process button event because - of debounce code of Mac. So have this mechanism - to prevent processing further events meanwhile. - */ -#endif - -GLOBALFUNC blnr FindKeyEvent(int *VirtualKey, blnr *KeyDown) -{ - MyEvtQEl *p; - - if ( -#if HaveMasterMyEvtQLock - (0 == MasterMyEvtQLock) && -#endif - (nullpr != (p = MyEvtQOutP()))) - { - if (MyEvtQElKindKey == p->kind) { - *VirtualKey = p->u.press.key; - *KeyDown = p->u.press.down; - MyEvtQOutDone(); - return trueblnr; - } - } - - return falseblnr; -} - -/* task management */ - -#ifdef _VIA_Debug -#include -#endif - -GLOBALVAR uimr ICTactive; -GLOBALVAR iCountt ICTwhen[kNumICTs]; - -GLOBALPROC ICT_Zap(void) -{ - ICTactive = 0; -} - -LOCALPROC InsertICT(int taskid, iCountt when) -{ - ICTwhen[taskid] = when; - ICTactive |= (1 << taskid); -} - -GLOBALVAR iCountt NextiCount = 0; - -GLOBALFUNC iCountt GetCuriCount(void) -{ - return NextiCount - GetCyclesRemaining(); -} - -GLOBALPROC ICT_add(int taskid, ui5b n) -{ - /* n must be > 0 */ - si5r x = GetCyclesRemaining(); - ui5b when = NextiCount - x + n; - -#ifdef _VIA_Debug - fprintf(stderr, "ICT_add: %d, %d, %d\n", when, taskid, n); -#endif - InsertICT(taskid, when); - - if (x > (si5r)n) { - SetCyclesRemaining(n); - NextiCount = when; - } -} +/* GLOBGLUE.c Copyright (C) 2003 Bernd Schmidt, Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* GLOBal GLUE (or GLOB of GLUE) Holds the program together. Some code here adapted from "custom.c" in vMac by Philip Cummins, in turn descended from code in the Un*x Amiga Emulator by Bernd Schmidt. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "ENDIANAC.h" #include "EMCONFIG.h" #endif #include "GLOBGLUE.h" /* ReportAbnormalID unused 0x111D - 0x11FF */ /* ReportAbnormalID ranges unused 0x12xx - 0xFFxx */ IMPORTPROC m68k_reset(void); IMPORTPROC IWM_Reset(void); IMPORTPROC SCC_Reset(void); IMPORTPROC SCSI_Reset(void); IMPORTPROC VIA1_Reset(void); #if EmVIA2 IMPORTPROC VIA2_Reset(void); #endif IMPORTPROC Sony_Reset(void); IMPORTPROC ExtnDisk_Access(CPTR p); IMPORTPROC ExtnSony_Access(CPTR p); #if EmVidCard IMPORTPROC ExtnVideo_Access(CPTR p); #endif IMPORTPROC Sony_SetQuitOnEject(void); IMPORTPROC m68k_IPLchangeNtfy(void); IMPORTPROC MINEM68K_Init( ui3b *fIPL); IMPORTFUNC ui5b GetCyclesRemaining(void); IMPORTPROC SetCyclesRemaining(ui5b n); IMPORTPROC SetHeadATTel(ATTep p); IMPORTFUNC ATTep FindATTel(CPTR addr); IMPORTFUNC ui5b SCSI_Access(ui5b Data, blnr WriteMem, CPTR addr); IMPORTFUNC ui5b SCC_Access(ui5b Data, blnr WriteMem, CPTR addr); IMPORTFUNC ui5b IWM_Access(ui5b Data, blnr WriteMem, CPTR addr); IMPORTFUNC ui5b VIA1_Access(ui5b Data, blnr WriteMem, CPTR addr); #if EmVIA2 IMPORTFUNC ui5b VIA2_Access(ui5b Data, blnr WriteMem, CPTR addr); #endif #if EmASC IMPORTFUNC ui5b ASC_Access(ui5b Data, blnr WriteMem, CPTR addr); #endif IMPORTFUNC ui3r get_vm_byte(CPTR addr); IMPORTFUNC ui4r get_vm_word(CPTR addr); IMPORTFUNC ui5r get_vm_long(CPTR addr); IMPORTPROC put_vm_byte(CPTR addr, ui3r b); IMPORTPROC put_vm_word(CPTR addr, ui4r w); IMPORTPROC put_vm_long(CPTR addr, ui5r l); GLOBALVAR ui5r my_disk_icon_addr; GLOBALPROC customreset(void) { IWM_Reset(); SCC_Reset(); SCSI_Reset(); VIA1_Reset(); #if EmVIA2 VIA2_Reset(); #endif Sony_Reset(); Extn_Reset(); #if CurEmMd <= kEmMd_Plus WantMacReset = trueblnr; /* kludge, code in Finder appears to do RESET and not expect to come back. Maybe asserting the RESET somehow causes other hardware compenents to later reset the 68000. */ #endif } GLOBALVAR ui3p RAM = nullpr; #if EmVidCard GLOBALVAR ui3p VidROM = nullpr; #endif #if IncludeVidMem GLOBALVAR ui3p VidMem = nullpr; #endif GLOBALVAR ui3b Wires[kNumWires]; #if WantDisasm IMPORTPROC m68k_WantDisasmContext(void); #endif #if WantDisasm GLOBALPROC dbglog_StartLine(void) { m68k_WantDisasmContext(); dbglog_writeCStr(" "); } #endif #if dbglog_HAVE GLOBALPROC dbglog_WriteMemArrow(blnr WriteMem) { if (WriteMem) { dbglog_writeCStr(" <- "); } else { dbglog_writeCStr(" -> "); } } #endif #if dbglog_HAVE GLOBALPROC dbglog_AddrAccess(char *s, ui5r Data, blnr WriteMem, ui5r addr) { dbglog_StartLine(); dbglog_writeCStr(s); dbglog_writeCStr("["); dbglog_writeHex(addr); dbglog_writeCStr("]"); dbglog_WriteMemArrow(WriteMem); dbglog_writeHex(Data); dbglog_writeReturn(); } #endif #if dbglog_HAVE GLOBALPROC dbglog_Access(char *s, ui5r Data, blnr WriteMem) { dbglog_StartLine(); dbglog_writeCStr(s); dbglog_WriteMemArrow(WriteMem); dbglog_writeHex(Data); dbglog_writeReturn(); } #endif #if dbglog_HAVE GLOBALPROC dbglog_WriteNote(char *s) { dbglog_StartLine(); dbglog_writeCStr(s); dbglog_writeReturn(); } #endif #if dbglog_HAVE GLOBALPROC dbglog_WriteSetBool(char *s, blnr v) { dbglog_StartLine(); dbglog_writeCStr(s); dbglog_writeCStr(" <- "); if (v) { dbglog_writeCStr("1"); } else { dbglog_writeCStr("0"); } dbglog_writeReturn(); } #endif LOCALVAR blnr GotOneAbnormal = falseblnr; #ifndef ReportAbnormalInterrupt #define ReportAbnormalInterrupt 0 #endif GLOBALPROC DoReportAbnormalID(ui4r id #if dbglog_HAVE , char *s #endif ) { #if dbglog_HAVE dbglog_StartLine(); dbglog_writeCStr("*** abnormal : "); dbglog_writeCStr(s); dbglog_writeReturn(); #endif if (! GotOneAbnormal) { WarnMsgAbnormalID(id); #if ReportAbnormalInterrupt SetInterruptButton(trueblnr); #endif GotOneAbnormal = trueblnr; } } /* map of address space */ #define kRAM_Base 0x00000000 /* when overlay off */ #if (CurEmMd == kEmMd_PB100) #define kRAM_ln2Spc 23 #elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) #define kRAM_ln2Spc 23 #else #define kRAM_ln2Spc 22 #endif #if IncludeVidMem #if CurEmMd == kEmMd_PB100 #define kVidMem_Base 0x00FA0000 #define kVidMem_ln2Spc 16 #else #define kVidMem_Base 0x00540000 #define kVidMem_ln2Spc 18 #endif #endif #if CurEmMd == kEmMd_PB100 #define kSCSI_Block_Base 0x00F90000 #define kSCSI_ln2Spc 16 #else #define kSCSI_Block_Base 0x00580000 #define kSCSI_ln2Spc 19 #endif #define kRAM_Overlay_Base 0x00600000 /* when overlay on */ #define kRAM_Overlay_Top 0x00800000 #if CurEmMd == kEmMd_PB100 #define kSCCRd_Block_Base 0x00FD0000 #define kSCC_ln2Spc 16 #else #define kSCCRd_Block_Base 0x00800000 #define kSCC_ln2Spc 22 #endif #if CurEmMd != kEmMd_PB100 #define kSCCWr_Block_Base 0x00A00000 #define kSCCWr_Block_Top 0x00C00000 #endif #if CurEmMd == kEmMd_PB100 #define kIWM_Block_Base 0x00F60000 #define kIWM_ln2Spc 16 #else #define kIWM_Block_Base 0x00C00000 #define kIWM_ln2Spc 21 #endif #if CurEmMd == kEmMd_PB100 #define kVIA1_Block_Base 0x00F70000 #define kVIA1_ln2Spc 16 #else #define kVIA1_Block_Base 0x00E80000 #define kVIA1_ln2Spc 19 #endif #if CurEmMd == kEmMd_PB100 #define kASC_Block_Base 0x00FB0000 #define kASC_ln2Spc 16 #endif #define kASC_Mask 0x00000FFF #if IncludeExtnPbufs LOCALFUNC tMacErr PbufTransferVM(CPTR Buffera, tPbuf i, ui5r offset, ui5r count, blnr IsWrite) { tMacErr result; ui5b contig; ui3p Buffer; label_1: if (0 == count) { result = mnvm_noErr; } else { Buffer = get_real_address0(count, ! IsWrite, Buffera, &contig); if (0 == contig) { result = mnvm_miscErr; } else { PbufTransfer(Buffer, i, offset, contig, IsWrite); offset += contig; Buffera += contig; count -= contig; goto label_1; } } return result; } #endif /* extension mechanism */ #if IncludeExtnPbufs #define kCmndPbufFeatures 1 #define kCmndPbufNew 2 #define kCmndPbufDispose 3 #define kCmndPbufGetSize 4 #define kCmndPbufTransfer 5 #endif #if IncludeExtnPbufs LOCALPROC ExtnParamBuffers_Access(CPTR p) { tMacErr result = mnvm_controlErr; switch (get_vm_word(p + ExtnDat_commnd)) { case kCmndVersion: put_vm_word(p + ExtnDat_version, 1); result = mnvm_noErr; break; case kCmndPbufFeatures: put_vm_long(p + ExtnDat_params + 0, 0); result = mnvm_noErr; break; case kCmndPbufNew: { tPbuf Pbuf_No; ui5b count = get_vm_long(p + ExtnDat_params + 4); /* reserved word at offset 2, should be zero */ result = PbufNew(count, &Pbuf_No); put_vm_word(p + ExtnDat_params + 0, Pbuf_No); } break; case kCmndPbufDispose: { tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 0); /* reserved word at offset 2, should be zero */ result = CheckPbuf(Pbuf_No); if (mnvm_noErr == result) { PbufDispose(Pbuf_No); } } break; case kCmndPbufGetSize: { ui5r Count; tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 0); /* reserved word at offset 2, should be zero */ result = PbufGetSize(Pbuf_No, &Count); if (mnvm_noErr == result) { put_vm_long(p + ExtnDat_params + 4, Count); } } break; case kCmndPbufTransfer: { ui5r PbufCount; tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 0); /* reserved word at offset 2, should be zero */ ui5r offset = get_vm_long(p + ExtnDat_params + 4); ui5r count = get_vm_long(p + ExtnDat_params + 8); CPTR Buffera = get_vm_long(p + ExtnDat_params + 12); blnr IsWrite = (get_vm_word(p + ExtnDat_params + 16) != 0); result = PbufGetSize(Pbuf_No, &PbufCount); if (mnvm_noErr == result) { ui5r endoff = offset + count; if ((endoff < offset) /* overflow */ || (endoff > PbufCount)) { result = mnvm_eofErr; } else { result = PbufTransferVM(Buffera, Pbuf_No, offset, count, IsWrite); } } } break; } put_vm_word(p + ExtnDat_result, result); } #endif #if IncludeExtnHostTextClipExchange #define kCmndHTCEFeatures 1 #define kCmndHTCEExport 2 #define kCmndHTCEImport 3 #endif #if IncludeExtnHostTextClipExchange LOCALPROC ExtnHostTextClipExchange_Access(CPTR p) { tMacErr result = mnvm_controlErr; switch (get_vm_word(p + ExtnDat_commnd)) { case kCmndVersion: put_vm_word(p + ExtnDat_version, 1); result = mnvm_noErr; break; case kCmndHTCEFeatures: put_vm_long(p + ExtnDat_params + 0, 0); result = mnvm_noErr; break; case kCmndHTCEExport: { tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 0); result = CheckPbuf(Pbuf_No); if (mnvm_noErr == result) { result = HTCEexport(Pbuf_No); } } break; case kCmndHTCEImport: { tPbuf Pbuf_No; result = HTCEimport(&Pbuf_No); put_vm_word(p + ExtnDat_params + 0, Pbuf_No); } break; } put_vm_word(p + ExtnDat_result, result); } #endif #define kFindExtnExtension 0x64E1F58A #define kDiskDriverExtension 0x4C9219E6 #if IncludeExtnPbufs #define kHostParamBuffersExtension 0x314C87BF #endif #if IncludeExtnHostTextClipExchange #define kHostClipExchangeExtension 0x27B130CA #endif #define kCmndFindExtnFind 1 #define kCmndFindExtnId2Code 2 #define kCmndFindExtnCount 3 #define kParamFindExtnTheExtn 8 #define kParamFindExtnTheId 12 LOCALPROC ExtnFind_Access(CPTR p) { tMacErr result = mnvm_controlErr; switch (get_vm_word(p + ExtnDat_commnd)) { case kCmndVersion: put_vm_word(p + ExtnDat_version, 1); result = mnvm_noErr; break; case kCmndFindExtnFind: { ui5b extn = get_vm_long(p + kParamFindExtnTheExtn); if (extn == kDiskDriverExtension) { put_vm_word(p + kParamFindExtnTheId, kExtnDisk); result = mnvm_noErr; } else #if IncludeExtnPbufs if (extn == kHostParamBuffersExtension) { put_vm_word(p + kParamFindExtnTheId, kExtnParamBuffers); result = mnvm_noErr; } else #endif #if IncludeExtnHostTextClipExchange if (extn == kHostClipExchangeExtension) { put_vm_word(p + kParamFindExtnTheId, kExtnHostTextClipExchange); result = mnvm_noErr; } else #endif if (extn == kFindExtnExtension) { put_vm_word(p + kParamFindExtnTheId, kExtnFindExtn); result = mnvm_noErr; } else { /* not found */ } } break; case kCmndFindExtnId2Code: { ui4r extn = get_vm_word(p + kParamFindExtnTheId); if (extn == kExtnDisk) { put_vm_long(p + kParamFindExtnTheExtn, kDiskDriverExtension); result = mnvm_noErr; } else #if IncludeExtnPbufs if (extn == kExtnParamBuffers) { put_vm_long(p + kParamFindExtnTheExtn, kHostParamBuffersExtension); result = mnvm_noErr; } else #endif #if IncludeExtnHostTextClipExchange if (extn == kExtnHostTextClipExchange) { put_vm_long(p + kParamFindExtnTheExtn, kHostClipExchangeExtension); result = mnvm_noErr; } else #endif if (extn == kExtnFindExtn) { put_vm_long(p + kParamFindExtnTheExtn, kFindExtnExtension); result = mnvm_noErr; } else { /* not found */ } } break; case kCmndFindExtnCount: put_vm_word(p + kParamFindExtnTheId, kNumExtns); result = mnvm_noErr; break; } put_vm_word(p + ExtnDat_result, result); } #define kDSK_Params_Hi 0 #define kDSK_Params_Lo 1 #define kDSK_QuitOnEject 3 /* obsolete */ LOCALVAR ui4b ParamAddrHi; LOCALPROC Extn_Access(ui5b Data, CPTR addr) { switch (addr) { case kDSK_Params_Hi: ParamAddrHi = Data; break; case kDSK_Params_Lo: { CPTR p = ParamAddrHi << 16 | Data; ParamAddrHi = (ui4b) - 1; if (kcom_callcheck == get_vm_word(p + ExtnDat_checkval)) { put_vm_word(p + ExtnDat_checkval, 0); switch (get_vm_word(p + ExtnDat_extension)) { case kExtnFindExtn: ExtnFind_Access(p); break; #if EmVidCard case kExtnVideo: ExtnVideo_Access(p); break; #endif #if IncludeExtnPbufs case kExtnParamBuffers: ExtnParamBuffers_Access(p); break; #endif #if IncludeExtnHostTextClipExchange case kExtnHostTextClipExchange: ExtnHostTextClipExchange_Access(p); break; #endif case kExtnDisk: ExtnDisk_Access(p); break; case kExtnSony: ExtnSony_Access(p); break; default: put_vm_word(p + ExtnDat_result, mnvm_controlErr); break; } } } break; case kDSK_QuitOnEject: /* obsolete, kept for compatibility */ Sony_SetQuitOnEject(); break; } } GLOBALPROC Extn_Reset(void) { ParamAddrHi = (ui4b) - 1; } /* implementation of read/write for everything but RAM and ROM */ #define kSCC_Mask 0x03 #define kVIA1_Mask 0x00000F #if EmVIA2 #define kVIA2_Mask 0x00000F #endif #define kIWM_Mask 0x00000F /* Allocated Memory Bandwidth for IWM */ #if CurEmMd <= kEmMd_512Ke #define ROM_CmpZeroMask 0 #elif CurEmMd <= kEmMd_Plus #if kROM_Size > 0x00020000 #define ROM_CmpZeroMask 0 /* For hacks like Mac ROM-inator */ #else #define ROM_CmpZeroMask 0x00020000 #endif #elif CurEmMd <= kEmMd_PB100 #define ROM_CmpZeroMask 0 #elif CurEmMd <= kEmMd_IIx #define ROM_CmpZeroMask 0 #else #error "ROM_CmpZeroMask not defined" #endif #define kROM_cmpmask (0x00F00000 | ROM_CmpZeroMask) #if CurEmMd <= kEmMd_512Ke #define Overlay_ROM_CmpZeroMask 0x00100000 #elif CurEmMd <= kEmMd_Plus #define Overlay_ROM_CmpZeroMask 0x00020000 #elif CurEmMd <= kEmMd_Classic #define Overlay_ROM_CmpZeroMask 0x00300000 #elif CurEmMd <= kEmMd_PB100 #define Overlay_ROM_CmpZeroMask 0 #elif CurEmMd <= kEmMd_IIx #define Overlay_ROM_CmpZeroMask 0 #else #error "Overlay_ROM_CmpZeroMask not defined" #endif enum { kMMDV_VIA1, #if EmVIA2 kMMDV_VIA2, #endif kMMDV_SCC, kMMDV_Extn, #if EmASC kMMDV_ASC, #endif kMMDV_SCSI, kMMDV_IWM, kNumMMDVs }; enum { #if CurEmMd >= kEmMd_SE kMAN_OverlayOff, #endif kNumMANs }; LOCALVAR ATTer ATTListA[MaxATTListN]; LOCALVAR ui4r LastATTel; LOCALPROC AddToATTList(ATTep p) { ui4r NewLast = LastATTel + 1; if (NewLast >= MaxATTListN) { ReportAbnormalID(0x1101, "MaxATTListN not big enough"); } else { ATTListA[LastATTel] = *p; LastATTel = NewLast; } } LOCALPROC InitATTList(void) { LastATTel = 0; } LOCALPROC FinishATTList(void) { { /* add guard */ ATTer r; r.cmpmask = 0; r.cmpvalu = 0; r.usemask = 0; r.usebase = nullpr; r.Access = 0; AddToATTList(&r); } { ui4r i = LastATTel; ATTep p = &ATTListA[LastATTel]; ATTep h = nullpr; while (0 != i) { --i; --p; p->Next = h; h = p; } #if 0 /* verify list. not for final version */ { ATTep q1; ATTep q2; for (q1 = h; nullpr != q1->Next; q1 = q1->Next) { if ((q1->cmpvalu & ~ q1->cmpmask) != 0) { ReportAbnormalID(0x1102, "ATTListA bad entry"); } for (q2 = q1->Next; nullpr != q2->Next; q2 = q2->Next) { ui5r common_mask = (q1->cmpmask) & (q2->cmpmask); if ((q1->cmpvalu & common_mask) == (q2->cmpvalu & common_mask)) { ReportAbnormalID(0x1103, "ATTListA Conflict"); } } } } #endif SetHeadATTel(h); } } #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) LOCALPROC SetUp_RAM24(void) { ATTer r; ui5r bankbit = 0x00100000 << (((VIA2_iA7 << 1) | VIA2_iA6) << 1); #if kRAMa_Size == kRAMb_Size if (kRAMa_Size == bankbit) { /* properly set up balanced RAM */ r.cmpmask = 0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1); r.cmpvalu = 0; r.usemask = ((1 << kRAM_ln2Spc) - 1) & (kRAM_Size - 1); r.usebase = RAM; r.Access = kATTA_readwritereadymask; AddToATTList(&r); } else #endif { bankbit &= 0x00FFFFFF; /* if too large, always use RAMa */ if (0 != bankbit) { #if kRAMb_Size != 0 r.cmpmask = bankbit | (0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1)); r.cmpvalu = bankbit; r.usemask = ((1 << kRAM_ln2Spc) - 1) & (kRAMb_Size - 1); r.usebase = kRAMa_Size + RAM; r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif } { r.cmpmask = bankbit | (0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1)); r.cmpvalu = 0; r.usemask = ((1 << kRAM_ln2Spc) - 1) & (kRAMa_Size - 1); r.usebase = RAM; r.Access = kATTA_readwritereadymask; AddToATTList(&r); } } } #endif #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) LOCALPROC SetUp_io(void) { ATTer r; if (Addr32) { r.cmpmask = 0xFF01E000; r.cmpvalu = 0x50000000; } else { r.cmpmask = 0x00F1E000; r.cmpvalu = 0x00F00000; } r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_VIA1; AddToATTList(&r); if (Addr32) { r.cmpmask = 0xFF01E000; r.cmpvalu = 0x50000000 | 0x2000; } else { r.cmpmask = 0x00F1E000; r.cmpvalu = 0x00F00000 | 0x2000; } r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_VIA2; AddToATTList(&r); if (Addr32) { r.cmpmask = 0xFF01E000; r.cmpvalu = 0x50000000 | 0x4000; } else { r.cmpmask = 0x00F1E000; r.cmpvalu = 0x00F00000 | 0x4000; } r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_SCC; AddToATTList(&r); if (Addr32) { r.cmpmask = 0xFF01E000; r.cmpvalu = 0x50000000 | 0x0C000; } else { r.cmpmask = 0x00F1E000; r.cmpvalu = 0x00F00000 | 0x0C000; } r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_Extn; AddToATTList(&r); if (Addr32) { r.cmpmask = 0xFF01E000; r.cmpvalu = 0x50000000 | 0x10000; } else { r.cmpmask = 0x00F1E000; r.cmpvalu = 0x00F00000 | 0x10000; } r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_SCSI; AddToATTList(&r); if (Addr32) { r.cmpmask = 0xFF01E000; r.cmpvalu = 0x50000000 | 0x14000; } else { r.cmpmask = 0x00F1E000; r.cmpvalu = 0x00F00000 | 0x14000; } r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_ASC; AddToATTList(&r); if (Addr32) { r.cmpmask = 0xFF01E000; r.cmpvalu = 0x50000000 | 0x16000; } else { r.cmpmask = 0x00F1E000; r.cmpvalu = 0x00F00000 | 0x16000; } r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_IWM; AddToATTList(&r); #if 0 case 14: /* fail, nothing supposed to be here, but rom accesses it anyway */ { ui5r addr2 = addr & 0x1FFFF; if ((addr2 != 0x1DA00) && (addr2 != 0x1DC00)) { ReportAbnormalID(0x1104, "another unknown access"); } } get_fail_realblock(p); break; #endif } #endif #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) LOCALPROC SetUp_address24(void) { ATTer r; #if 0 if (MemOverlay) { ReportAbnormalID(0x1105, "Overlay with 24 bit addressing"); } #endif if (MemOverlay) { r.cmpmask = Overlay_ROM_CmpZeroMask | (0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1)); r.cmpvalu = kRAM_Base; r.usemask = kROM_Size - 1; r.usebase = ROM; r.Access = kATTA_readreadymask; AddToATTList(&r); } else { SetUp_RAM24(); } r.cmpmask = kROM_cmpmask; r.cmpvalu = kROM_Base; r.usemask = kROM_Size - 1; r.usebase = ROM; r.Access = kATTA_readreadymask; AddToATTList(&r); r.cmpmask = 0x00FFFFFF & ~ (0x100000 - 1); r.cmpvalu = 0x900000; r.usemask = (kVidMemRAM_Size - 1) & (0x100000 - 1); r.usebase = VidMem; r.Access = kATTA_readwritereadymask; AddToATTList(&r); #if kVidMemRAM_Size >= 0x00200000 r.cmpmask = 0x00FFFFFF & ~ (0x100000 - 1); r.cmpvalu = 0xA00000; r.usemask = (0x100000 - 1); r.usebase = VidMem + (1 << 20); r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif #if kVidMemRAM_Size >= 0x00400000 r.cmpmask = 0x00FFFFFF & ~ (0x100000 - 1); r.cmpvalu = 0xB00000; r.usemask = (0x100000 - 1); r.usebase = VidMem + (2 << 20); r.Access = kATTA_readwritereadymask; AddToATTList(&r); r.cmpmask = 0x00FFFFFF & ~ (0x100000 - 1); r.cmpvalu = 0xC00000; r.usemask = (0x100000 - 1); r.usebase = VidMem + (3 << 20); r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif SetUp_io(); } #endif #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) LOCALPROC SetUp_address32(void) { ATTer r; if (MemOverlay) { r.cmpmask = ~ ((1 << 30) - 1); r.cmpvalu = 0; r.usemask = kROM_Size - 1; r.usebase = ROM; r.Access = kATTA_readreadymask; AddToATTList(&r); } else { ui5r bankbit = 0x00100000 << (((VIA2_iA7 << 1) | VIA2_iA6) << 1); #if kRAMa_Size == kRAMb_Size if (kRAMa_Size == bankbit) { /* properly set up balanced RAM */ r.cmpmask = ~ ((1 << 30) - 1); r.cmpvalu = 0; r.usemask = kRAM_Size - 1; r.usebase = RAM; r.Access = kATTA_readwritereadymask; AddToATTList(&r); } else #endif { #if kRAMb_Size != 0 r.cmpmask = bankbit | ~ ((1 << 30) - 1); r.cmpvalu = bankbit; r.usemask = kRAMb_Size - 1; r.usebase = kRAMa_Size + RAM; r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif r.cmpmask = bankbit | ~ ((1 << 30) - 1); r.cmpvalu = 0; r.usemask = kRAMa_Size - 1; r.usebase = RAM; r.Access = kATTA_readwritereadymask; AddToATTList(&r); } } r.cmpmask = ~ ((1 << 28) - 1); r.cmpvalu = 0x40000000; r.usemask = kROM_Size - 1; r.usebase = ROM; r.Access = kATTA_readreadymask; AddToATTList(&r); #if 0 /* haven't persuaded emulated computer to look here yet. */ /* NuBus super space */ r.cmpmask = ~ ((1 << 28) - 1); r.cmpvalu = 0x90000000; r.usemask = kVidMemRAM_Size - 1; r.usebase = VidMem; r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif /* Standard NuBus space */ r.cmpmask = ~ ((1 << 20) - 1); r.cmpvalu = 0xF9F00000; r.usemask = kVidROM_Size - 1; r.usebase = VidROM; r.Access = kATTA_readreadymask; AddToATTList(&r); #if 0 r.cmpmask = ~ 0x007FFFFF; r.cmpvalu = 0xF9000000; r.usemask = 0x007FFFFF & (kVidMemRAM_Size - 1); r.usebase = VidMem; r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif r.cmpmask = ~ 0x000FFFFF; r.cmpvalu = 0xF9900000; r.usemask = 0x000FFFFF & (kVidMemRAM_Size - 1); r.usebase = VidMem; r.Access = kATTA_readwritereadymask; AddToATTList(&r); /* kludge to allow more than 1M of Video Memory */ #if kVidMemRAM_Size >= 0x00200000 r.cmpmask = ~ 0x000FFFFF; r.cmpvalu = 0xF9A00000; r.usemask = 0x000FFFFF & (kVidMemRAM_Size - 1); r.usebase = VidMem + (1 << 20); r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif #if kVidMemRAM_Size >= 0x00400000 r.cmpmask = ~ 0x000FFFFF; r.cmpvalu = 0xF9B00000; r.usemask = 0x000FFFFF & (kVidMemRAM_Size - 1); r.usebase = VidMem + (2 << 20); r.Access = kATTA_readwritereadymask; AddToATTList(&r); r.cmpmask = ~ 0x000FFFFF; r.cmpvalu = 0xF9C00000; r.usemask = 0x000FFFFF & (kVidMemRAM_Size - 1); r.usebase = VidMem + (3 << 20); r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif SetUp_io(); #if 0 if ((addr >= 0x58000000) && (addr < 0x58000004)) { /* test hardware. fail */ } #endif } #endif #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) LOCALPROC SetUp_address(void) { if (Addr32) { SetUp_address32(); } else { SetUp_address24(); } } #endif /* unlike in the real Mac Plus, Mini vMac will allow misaligned memory access, since it is easier to allow it than it is to correctly simulate a bus error and back out of the current instruction. */ #ifndef ln2mtb #define AddToATTListWithMTB AddToATTList #else LOCALPROC AddToATTListWithMTB(ATTep p) { /* Test of memory mapping system. */ ATTer r; r.Access = p->Access; r.cmpmask = p->cmpmask | (1 << ln2mtb); r.usemask = p->usemask & ~ (1 << ln2mtb); r.cmpvalu = p->cmpvalu + (1 << ln2mtb); r.usebase = p->usebase; AddToATTList(&r); r.cmpvalu = p->cmpvalu; r.usebase = p->usebase + (1 << ln2mtb); AddToATTList(&r); } #endif #if (CurEmMd != kEmMd_II) && (CurEmMd != kEmMd_IIx) LOCALPROC SetUp_RAM24(void) { ATTer r; #if (0 == kRAMb_Size) || (kRAMa_Size == kRAMb_Size) r.cmpmask = 0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1); r.cmpvalu = kRAM_Base; r.usemask = kRAM_Size - 1; r.usebase = RAM; r.Access = kATTA_readwritereadymask; AddToATTListWithMTB(&r); #else /* unbalanced memory */ #if 0 != (0x00FFFFFF & kRAMa_Size) /* condition should always be true if configuration file right */ r.cmpmask = 0x00FFFFFF & (kRAMa_Size | ~ ((1 << kRAM_ln2Spc) - 1)); r.cmpvalu = kRAM_Base + kRAMa_Size; r.usemask = kRAMb_Size - 1; r.usebase = kRAMa_Size + RAM; r.Access = kATTA_readwritereadymask; AddToATTListWithMTB(&r); #endif r.cmpmask = 0x00FFFFFF & (kRAMa_Size | ~ ((1 << kRAM_ln2Spc) - 1)); r.cmpvalu = kRAM_Base; r.usemask = kRAMa_Size - 1; r.usebase = RAM; r.Access = kATTA_readwritereadymask; AddToATTListWithMTB(&r); #endif } #endif #if (CurEmMd != kEmMd_II) && (CurEmMd != kEmMd_IIx) LOCALPROC SetUp_address(void) { ATTer r; if (MemOverlay) { r.cmpmask = Overlay_ROM_CmpZeroMask | (0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1)); r.cmpvalu = kRAM_Base; r.usemask = kROM_Size - 1; r.usebase = ROM; r.Access = kATTA_readreadymask; AddToATTListWithMTB(&r); } else { SetUp_RAM24(); } r.cmpmask = kROM_cmpmask; r.cmpvalu = kROM_Base; #if (CurEmMd >= kEmMd_SE) if (MemOverlay) { r.usebase = nullpr; r.Access = kATTA_ntfymask; r.Ntfy = kMAN_OverlayOff; AddToATTList(&r); } else #endif { r.usemask = kROM_Size - 1; r.usebase = ROM; r.Access = kATTA_readreadymask; AddToATTListWithMTB(&r); } if (MemOverlay) { r.cmpmask = 0x00E00000; r.cmpvalu = kRAM_Overlay_Base; #if (0 == kRAMb_Size) || (kRAMa_Size == kRAMb_Size) r.usemask = kRAM_Size - 1; /* note that cmpmask and usemask overlap for 4M */ r.usebase = RAM; r.Access = kATTA_readwritereadymask; #else /* unbalanced memory */ r.usemask = kRAMb_Size - 1; r.usebase = kRAMa_Size + RAM; r.Access = kATTA_readwritereadymask; #endif AddToATTListWithMTB(&r); } #if IncludeVidMem r.cmpmask = 0x00FFFFFF & ~ ((1 << kVidMem_ln2Spc) - 1); r.cmpvalu = kVidMem_Base; r.usemask = kVidMemRAM_Size - 1; r.usebase = VidMem; r.Access = kATTA_readwritereadymask; AddToATTList(&r); #endif r.cmpmask = 0x00FFFFFF & ~ ((1 << kVIA1_ln2Spc) - 1); r.cmpvalu = kVIA1_Block_Base; r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_VIA1; AddToATTList(&r); r.cmpmask = 0x00FFFFFF & ~ ((1 << kSCC_ln2Spc) - 1); r.cmpvalu = kSCCRd_Block_Base; r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_SCC; AddToATTList(&r); r.cmpmask = 0x00FFFFFF & ~ ((1 << kExtn_ln2Spc) - 1); r.cmpvalu = kExtn_Block_Base; r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_Extn; AddToATTList(&r); #if CurEmMd == kEmMd_PB100 r.cmpmask = 0x00FFFFFF & ~ ((1 << kASC_ln2Spc) - 1); r.cmpvalu = kASC_Block_Base; r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_ASC; AddToATTList(&r); #endif r.cmpmask = 0x00FFFFFF & ~ ((1 << kSCSI_ln2Spc) - 1); r.cmpvalu = kSCSI_Block_Base; r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_SCSI; AddToATTList(&r); r.cmpmask = 0x00FFFFFF & ~ ((1 << kIWM_ln2Spc) - 1); r.cmpvalu = kIWM_Block_Base; r.usebase = nullpr; r.Access = kATTA_mmdvmask; r.MMDV = kMMDV_IWM; AddToATTList(&r); } #endif LOCALPROC SetUpMemBanks(void) { InitATTList(); SetUp_address(); FinishATTList(); } #if 0 LOCALPROC get_fail_realblock(ATTep p) { p->cmpmask = 0; p->cmpvalu = 0xFFFFFFFF; p->usemask = 0; p->usebase = nullpr; p->Access = 0; } #endif GLOBALFUNC ui5b MMDV_Access(ATTep p, ui5b Data, blnr WriteMem, blnr ByteSize, CPTR addr) { switch (p->MMDV) { case kMMDV_VIA1: if (! ByteSize) { #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) if (WriteMem && (addr == 0xF40006)) { /* for weirdness on shutdown in System 6 */ #if 0 VIA1_Access((Data >> 8) & 0x00FF, WriteMem, (addr >> 9) & kVIA1_Mask); VIA1_Access((Data) & 0x00FF, WriteMem, (addr >> 9) & kVIA1_Mask); #endif } else #endif { ReportAbnormalID(0x1106, "access VIA1 word"); } } else if ((addr & 1) != 0) { ReportAbnormalID(0x1107, "access VIA1 odd"); } else { #if CurEmMd != kEmMd_PB100 #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) if ((addr & 0x000001FE) != 0x00000000) #else if ((addr & 0x000FE1FE) != 0x000FE1FE) #endif { ReportAbnormalID(0x1108, "access VIA1 nonstandard address"); } #endif Data = VIA1_Access(Data, WriteMem, (addr >> 9) & kVIA1_Mask); } break; #if EmVIA2 case kMMDV_VIA2: if (! ByteSize) { if ((! WriteMem) && ((0x3e00 == (addr & 0x1FFFF)) || (0x3e02 == (addr & 0x1FFFF)))) { /* for weirdness at offset 0x71E in ROM */ Data = (VIA2_Access(Data, WriteMem, (addr >> 9) & kVIA2_Mask) << 8) | VIA2_Access(Data, WriteMem, (addr >> 9) & kVIA2_Mask); } else { ReportAbnormalID(0x1109, "access VIA2 word"); } } else if ((addr & 1) != 0) { if (0x3FFF == (addr & 0x1FFFF)) { /* for weirdness at offset 0x7C4 in ROM. looks like bug. */ Data = VIA2_Access(Data, WriteMem, (addr >> 9) & kVIA2_Mask); } else { ReportAbnormalID(0x110A, "access VIA2 odd"); } } else { if ((addr & 0x000001FE) != 0x00000000) { ReportAbnormalID(0x110B, "access VIA2 nonstandard address"); } Data = VIA2_Access(Data, WriteMem, (addr >> 9) & kVIA2_Mask); } break; #endif case kMMDV_SCC: #if (CurEmMd >= kEmMd_SE) \ && ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)) if ((addr & 0x00100000) == 0) { ReportAbnormalID(0x110C, "access SCC unassigned address"); } else #endif if (! ByteSize) { ReportAbnormalID(0x110D, "Attemped Phase Adjust"); } else #if ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)) if (WriteMem != ((addr & 1) != 0)) { if (WriteMem) { #if CurEmMd >= kEmMd_512Ke #if CurEmMd != kEmMd_PB100 ReportAbnormalID(0x110E, "access SCC even/odd"); /* This happens on boot with 64k ROM. */ #endif #endif } else { SCC_Reset(); } } else #endif #if (CurEmMd != kEmMd_PB100) \ && ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)) if (WriteMem != (addr >= kSCCWr_Block_Base)) { ReportAbnormalID(0x110F, "access SCC wr/rd base wrong"); } else #endif { #if CurEmMd != kEmMd_PB100 #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) if ((addr & 0x1FF9) != 0x00000000) #else if ((addr & 0x001FFFF8) != 0x001FFFF8) #endif { ReportAbnormalID(0x1110, "access SCC nonstandard address"); } #endif Data = SCC_Access(Data, WriteMem, (addr >> 1) & kSCC_Mask); } break; case kMMDV_Extn: if (ByteSize) { ReportAbnormalID(0x1111, "access Sony byte"); } else if ((addr & 1) != 0) { ReportAbnormalID(0x1112, "access Sony odd"); } else if (! WriteMem) { ReportAbnormalID(0x1113, "access Sony read"); } else { Extn_Access(Data, (addr >> 1) & 0x0F); } break; #if EmASC case kMMDV_ASC: if (! ByteSize) { #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) if (WriteMem) { (void) ASC_Access((Data >> 8) & 0x00FF, WriteMem, addr & kASC_Mask); Data = ASC_Access((Data) & 0x00FF, WriteMem, (addr + 1) & kASC_Mask); } else { Data = (ASC_Access((Data >> 8) & 0x00FF, WriteMem, addr & kASC_Mask) << 8) | ASC_Access((Data) & 0x00FF, WriteMem, (addr + 1) & kASC_Mask); } #else ReportAbnormalID(0x1114, "access ASC word"); #endif } else { Data = ASC_Access(Data, WriteMem, addr & kASC_Mask); } break; #endif case kMMDV_SCSI: if (! ByteSize) { ReportAbnormalID(0x1115, "access SCSI word"); } else #if ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)) if (WriteMem != ((addr & 1) != 0)) { ReportAbnormalID(0x1116, "access SCSI even/odd"); } else #endif { #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) if ((addr & 0x1F8F) != 0x00000000) { ReportAbnormalID(0x1117, "access SCSI nonstandard address"); } #endif Data = SCSI_Access(Data, WriteMem, (addr >> 4) & 0x07); } break; case kMMDV_IWM: #if (CurEmMd >= kEmMd_SE) \ && ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)) if ((addr & 0x00100000) == 0) { ReportAbnormalID(0x1118, "access IWM unassigned address"); } else #endif if (! ByteSize) { #if ExtraAbnormalReports ReportAbnormalID(0x1119, "access IWM word"); /* This happens when quitting 'Glider 3.1.2'. perhaps a bad handle is being disposed of. */ #endif } else #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) if ((addr & 1) != 0) { ReportAbnormalID(0x111A, "access IWM odd"); } else #else if ((addr & 1) == 0) { ReportAbnormalID(0x111B, "access IWM even"); } else #endif { #if (CurEmMd != kEmMd_PB100) \ && ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)) if ((addr & 0x001FE1FF) != 0x001FE1FF) { ReportAbnormalID(0x111C, "access IWM nonstandard address"); } #endif Data = IWM_Access(Data, WriteMem, (addr >> 9) & kIWM_Mask); } break; } return Data; } GLOBALFUNC blnr MemAccessNtfy(ATTep pT) { blnr v = falseblnr; switch (pT->Ntfy) { #if CurEmMd >= kEmMd_SE case kMAN_OverlayOff: pT->Access = kATTA_readreadymask; MemOverlay = 0; SetUpMemBanks(); v = trueblnr; break; #endif } return v; } GLOBALPROC MemOverlay_ChangeNtfy(void) { #if CurEmMd <= kEmMd_Plus SetUpMemBanks(); #elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) SetUpMemBanks(); #endif } #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) GLOBALPROC Addr32_ChangeNtfy(void) { SetUpMemBanks(); } #endif LOCALFUNC ATTep get_address_realblock1(blnr WriteMem, CPTR addr) { ATTep p; Label_Retry: p = FindATTel(addr); if (0 != (p->Access & (WriteMem ? kATTA_writereadymask : kATTA_readreadymask))) { /* ok */ } else { if (0 != (p->Access & kATTA_ntfymask)) { if (MemAccessNtfy(p)) { goto Label_Retry; } } p = nullpr; /* fail */ } return p; } GLOBALFUNC ui3p get_real_address0(ui5b L, blnr WritableMem, CPTR addr, ui5b *actL) { ui5b bankleft; ui3p p; ATTep q; q = get_address_realblock1(WritableMem, addr); if (nullpr == q) { *actL = 0; p = nullpr; } else { ui5r m2 = q->usemask & ~ q->cmpmask; ui5r m3 = m2 & ~ (m2 + 1); p = q->usebase + (addr & q->usemask); bankleft = (m3 + 1) - (addr & m3); if (bankleft >= L) { /* this block is big enough (by far the most common case) */ *actL = L; } else { *actL = bankleft; } } return p; } GLOBALVAR blnr InterruptButton = falseblnr; GLOBALPROC SetInterruptButton(blnr v) { if (InterruptButton != v) { InterruptButton = v; VIAorSCCinterruptChngNtfy(); } } LOCALVAR ui3b CurIPL = 0; GLOBALPROC VIAorSCCinterruptChngNtfy(void) { #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) ui3b NewIPL; if (InterruptButton) { NewIPL = 7; } else if (SCCInterruptRequest) { NewIPL = 4; } else if (VIA2_InterruptRequest) { NewIPL = 2; } else if (VIA1_InterruptRequest) { NewIPL = 1; } else { NewIPL = 0; } #else ui3b VIAandNotSCC = VIA1_InterruptRequest & ~ SCCInterruptRequest; ui3b NewIPL = VIAandNotSCC | (SCCInterruptRequest << 1) | (InterruptButton << 2); #endif if (NewIPL != CurIPL) { CurIPL = NewIPL; m68k_IPLchangeNtfy(); } } GLOBALFUNC blnr AddrSpac_Init(void) { int i; for (i = 0; i < kNumWires; i++) { Wires[i] = 1; } MINEM68K_Init( &CurIPL); return trueblnr; } GLOBALPROC Memory_Reset(void) { MemOverlay = 1; SetUpMemBanks(); } #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) EXPORTPROC PowerOff_ChangeNtfy(void); GLOBALPROC PowerOff_ChangeNtfy(void) { if (! VIA2_iB2) { ForceMacOff = trueblnr; } } #endif /* user event queue utilities */ #if HaveMasterMyEvtQLock GLOBALVAR ui4r MasterMyEvtQLock = 0; /* Takes a few ticks to process button event because of debounce code of Mac. So have this mechanism to prevent processing further events meanwhile. */ #endif GLOBALFUNC blnr FindKeyEvent(int *VirtualKey, blnr *KeyDown) { MyEvtQEl *p; if ( #if HaveMasterMyEvtQLock (0 == MasterMyEvtQLock) && #endif (nullpr != (p = MyEvtQOutP()))) { if (MyEvtQElKindKey == p->kind) { *VirtualKey = p->u.press.key; *KeyDown = p->u.press.down; MyEvtQOutDone(); return trueblnr; } } return falseblnr; } /* task management */ #ifdef _VIA_Debug #include #endif GLOBALVAR uimr ICTactive; GLOBALVAR iCountt ICTwhen[kNumICTs]; GLOBALPROC ICT_Zap(void) { ICTactive = 0; } LOCALPROC InsertICT(int taskid, iCountt when) { ICTwhen[taskid] = when; ICTactive |= (1 << taskid); } GLOBALVAR iCountt NextiCount = 0; GLOBALFUNC iCountt GetCuriCount(void) { return NextiCount - GetCyclesRemaining(); } GLOBALPROC ICT_add(int taskid, ui5b n) { /* n must be > 0 */ si5r x = GetCyclesRemaining(); ui5b when = NextiCount - x + n; #ifdef _VIA_Debug fprintf(stderr, "ICT_add: %d, %d, %d\n", when, taskid, n); #endif InsertICT(taskid, when); if (x > (si5r)n) { SetCyclesRemaining(n); NextiCount = when; } } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/GLOBGLUE.h b/Mini vMac/mnvm_core/GLOBGLUE.h index aeb4a6e..9cb4587 100755 --- a/Mini vMac/mnvm_core/GLOBGLUE.h +++ b/Mini vMac/mnvm_core/GLOBGLUE.h @@ -1,255 +1 @@ -/* - GLOBGLUE.h - - Copyright (C) 2003 Bernd Schmidt, Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef GLOBGLUE_H -#error "header already included" -#else -#define GLOBGLUE_H -#endif - - -#define kEmMd_128K 0 -#define kEmMd_512Ke 1 -#define kEmMd_Plus 2 -#define kEmMd_SE 3 -#define kEmMd_SEFDHD 4 -#define kEmMd_Classic 5 -#define kEmMd_PB100 6 -#define kEmMd_II 7 -#define kEmMd_IIx 8 - -#define RAMSafetyMarginFudge 4 - -#define kRAM_Size (kRAMa_Size + kRAMb_Size) -EXPORTVAR(ui3p, RAM) - /* - allocated by MYOSGLUE to be at least - kRAM_Size + RAMSafetyMarginFudge - bytes. Because of shortcuts taken in GLOBGLUE.c, it is in theory - possible for the emulator to write up to 3 bytes past kRAM_Size. - */ - -#if EmVidCard -EXPORTVAR(ui3p, VidROM) -#endif - -#if IncludeVidMem -EXPORTVAR(ui3p, VidMem) -#endif - -EXPORTPROC MemOverlay_ChangeNtfy(void); - -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) -EXPORTPROC Addr32_ChangeNtfy(void); -#endif - -/* - representation of pointer into memory of emulated computer. -*/ -typedef ui5b CPTR; - -/* - mapping of address space to real memory -*/ - -EXPORTFUNC ui3p get_real_address0(ui5b L, blnr WritableMem, CPTR addr, - ui5b *actL); - -/* - memory access routines that can use when have address - that is known to be in RAM (and that is in the first - copy of the ram, not the duplicates, i.e. < kRAM_Size). -*/ - -#define get_ram_byte(addr) do_get_mem_byte((addr) + RAM) -#define get_ram_word(addr) do_get_mem_word((addr) + RAM) -#define get_ram_long(addr) do_get_mem_long((addr) + RAM) - -#define put_ram_byte(addr, b) do_put_mem_byte((addr) + RAM, (b)) -#define put_ram_word(addr, w) do_put_mem_word((addr) + RAM, (w)) -#define put_ram_long(addr, l) do_put_mem_long((addr) + RAM, (l)) - -#define get_ram_address(addr) ((addr) + RAM) - -/* - accessing addresses that don't map to - real memory, i.e. memory mapped devices -*/ - -EXPORTFUNC blnr AddrSpac_Init(void); - - -#define ui5r_FromSByte(x) ((ui5r)(si5r)(si3b)(ui3b)(x)) -#define ui5r_FromSWord(x) ((ui5r)(si5r)(si4b)(ui4b)(x)) -#define ui5r_FromSLong(x) ((ui5r)(si5r)(si5b)(ui5b)(x)) - -#define ui5r_FromUByte(x) ((ui5r)(ui3b)(x)) -#define ui5r_FromUWord(x) ((ui5r)(ui4b)(x)) -#define ui5r_FromULong(x) ((ui5r)(ui5b)(x)) - - -#define LOCALPROCUSEDONCE LOCALFUNC MayInline void - -#if WantDisasm -EXPORTPROC dbglog_StartLine(void); -#else -#define dbglog_StartLine() -#endif - -#if dbglog_HAVE -EXPORTPROC dbglog_WriteMemArrow(blnr WriteMem); - -EXPORTPROC dbglog_WriteNote(char *s); -EXPORTPROC dbglog_WriteSetBool(char *s, blnr v); -EXPORTPROC dbglog_AddrAccess(char *s, - ui5r Data, blnr WriteMem, ui5r addr); -EXPORTPROC dbglog_Access(char *s, ui5r Data, blnr WriteMem); -#endif - -#if dbglog_HAVE -#define ReportAbnormal DoReportAbnormal -EXPORTPROC DoReportAbnormal(char *s); -#else -#define ReportAbnormal(s) DoReportAbnormal() -EXPORTPROC DoReportAbnormal(void); -#endif - -EXPORTPROC VIAorSCCinterruptChngNtfy(void); - -EXPORTVAR(blnr, InterruptButton) -EXPORTPROC SetInterruptButton(blnr v); - -enum { - kICT_SubTick, -#if EmClassicKbrd - kICT_Kybd_ReceiveCommand, - kICT_Kybd_ReceiveEndCommand, -#endif -#if EmADB - kICT_ADB_NewState, -#endif -#if EmPMU - kICT_PMU_Task, -#endif - kICT_VIA1_Timer1Check, - kICT_VIA1_Timer2Check, -#if EmVIA2 - kICT_VIA2_Timer1Check, - kICT_VIA2_Timer2Check, -#endif - - kNumICTs -}; - -EXPORTPROC ICT_add(int taskid, ui5b n); - -#define iCountt ui5b -EXPORTFUNC iCountt GetCuriCount(void); -EXPORTPROC ICT_Zap(void); - -EXPORTVAR(uimr, ICTactive) -EXPORTVAR(iCountt, ICTwhen[kNumICTs]) -EXPORTVAR(iCountt, NextiCount) - -EXPORTVAR(ui3b, Wires[kNumWires]) - -#define kLn2CycleScale 6 -#define kCycleScale (1 << kLn2CycleScale) - -#if WantCycByPriOp -#define RdAvgXtraCyc /* 0 */ (kCycleScale + kCycleScale / 4) -#define WrAvgXtraCyc /* 0 */ (kCycleScale + kCycleScale / 4) -#endif - -#define kNumSubTicks 16 - - -#define HaveMasterMyEvtQLock EmClassicKbrd -#if HaveMasterMyEvtQLock -EXPORTVAR(ui4r, MasterMyEvtQLock) -#endif -EXPORTFUNC blnr FindKeyEvent(int *VirtualKey, blnr *KeyDown); - - -/* minivmac extensions */ - -#define ExtnDat_checkval 0 -#define ExtnDat_extension 2 -#define ExtnDat_commnd 4 -#define ExtnDat_result 6 -#define ExtnDat_params 8 - -#define kCmndVersion 0 -#define ExtnDat_version 8 - -enum { - kExtnFindExtn, /* must be first */ - - kExtnDisk, - kExtnSony, -#if EmVidCard - kExtnVideo, -#endif -#if IncludeExtnPbufs - kExtnParamBuffers, -#endif -#if IncludeExtnHostTextClipExchange - kExtnHostTextClipExchange, -#endif - - kNumExtns -}; - -#define kcom_callcheck 0x5B17 - -EXPORTVAR(ui5r, my_disk_icon_addr) - -EXPORTPROC Memory_Reset(void); - -EXPORTPROC Extn_Reset(void); - -EXPORTPROC customreset(void); - -struct ATTer { - struct ATTer *Next; - ui5r cmpmask; - ui5r cmpvalu; - ui5r Access; - ui5r usemask; - ui3p usebase; - ui3r MMDV; - ui3r Ntfy; - ui4r Pad0; - ui5r Pad1; /* make 32 byte structure, on 32 bit systems */ -}; -typedef struct ATTer ATTer; -typedef ATTer *ATTep; - -#define kATTA_readreadybit 0 -#define kATTA_writereadybit 1 -#define kATTA_mmdvbit 2 -#define kATTA_ntfybit 3 - -#define kATTA_readwritereadymask \ - ((1 << kATTA_readreadybit) | (1 << kATTA_writereadybit)) -#define kATTA_readreadymask (1 << kATTA_readreadybit) -#define kATTA_writereadymask (1 << kATTA_writereadybit) -#define kATTA_mmdvmask (1 << kATTA_mmdvbit) -#define kATTA_ntfymask (1 << kATTA_ntfybit) - -EXPORTFUNC ui5b MMDV_Access(ATTep p, ui5b Data, - blnr WriteMem, blnr ByteSize, CPTR addr); -EXPORTFUNC blnr MemAccessNtfy(ATTep pT); +/* GLOBGLUE.h Copyright (C) 2003 Bernd Schmidt, Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef GLOBGLUE_H #error "header already included" #else #define GLOBGLUE_H #endif #define kEmMd_Twig43 0 #define kEmMd_Twiggy 1 #define kEmMd_128K 2 #define kEmMd_512Ke 3 #define kEmMd_Plus 4 #define kEmMd_SE 5 #define kEmMd_SEFDHD 6 #define kEmMd_Classic 7 #define kEmMd_PB100 8 #define kEmMd_II 9 #define kEmMd_IIx 10 #define RAMSafetyMarginFudge 4 #define kRAM_Size (kRAMa_Size + kRAMb_Size) EXPORTVAR(ui3p, RAM) /* allocated by MYOSGLUE to be at least kRAM_Size + RAMSafetyMarginFudge bytes. Because of shortcuts taken in GLOBGLUE.c, it is in theory possible for the emulator to write up to 3 bytes past kRAM_Size. */ #if EmVidCard EXPORTVAR(ui3p, VidROM) #endif #if IncludeVidMem EXPORTVAR(ui3p, VidMem) #endif EXPORTPROC MemOverlay_ChangeNtfy(void); #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) EXPORTPROC Addr32_ChangeNtfy(void); #endif /* representation of pointer into memory of emulated computer. */ typedef ui5b CPTR; /* mapping of address space to real memory */ EXPORTFUNC ui3p get_real_address0(ui5b L, blnr WritableMem, CPTR addr, ui5b *actL); /* memory access routines that can use when have address that is known to be in RAM (and that is in the first copy of the ram, not the duplicates, i.e. < kRAM_Size). */ #ifndef ln2mtb #define get_ram_byte(addr) do_get_mem_byte((addr) + RAM) #define get_ram_word(addr) do_get_mem_word((addr) + RAM) #define get_ram_long(addr) do_get_mem_long((addr) + RAM) #define put_ram_byte(addr, b) do_put_mem_byte((addr) + RAM, (b)) #define put_ram_word(addr, w) do_put_mem_word((addr) + RAM, (w)) #define put_ram_long(addr, l) do_put_mem_long((addr) + RAM, (l)) #else #define get_ram_byte get_vm_byte #define get_ram_word get_vm_word #define get_ram_long get_vm_long #define put_ram_byte put_vm_byte #define put_ram_word put_vm_word #define put_ram_long put_vm_long #endif #define get_ram_address(addr) ((addr) + RAM) /* accessing addresses that don't map to real memory, i.e. memory mapped devices */ EXPORTFUNC blnr AddrSpac_Init(void); #define ui5r_FromSByte(x) ((ui5r)(si5r)(si3b)(ui3b)(x)) #define ui5r_FromSWord(x) ((ui5r)(si5r)(si4b)(ui4b)(x)) #define ui5r_FromSLong(x) ((ui5r)(si5r)(si5b)(ui5b)(x)) #define ui5r_FromUByte(x) ((ui5r)(ui3b)(x)) #define ui5r_FromUWord(x) ((ui5r)(ui4b)(x)) #define ui5r_FromULong(x) ((ui5r)(ui5b)(x)) #if WantDisasm EXPORTPROC dbglog_StartLine(void); #else #define dbglog_StartLine() #endif #if dbglog_HAVE EXPORTPROC dbglog_WriteMemArrow(blnr WriteMem); EXPORTPROC dbglog_WriteNote(char *s); EXPORTPROC dbglog_WriteSetBool(char *s, blnr v); EXPORTPROC dbglog_AddrAccess(char *s, ui5r Data, blnr WriteMem, ui5r addr); EXPORTPROC dbglog_Access(char *s, ui5r Data, blnr WriteMem); #endif #if dbglog_HAVE #define ReportAbnormalID DoReportAbnormalID #else #define ReportAbnormalID(id, s) DoReportAbnormalID(id) #endif EXPORTPROC DoReportAbnormalID(ui4r id #if dbglog_HAVE , char *s #endif ); EXPORTPROC VIAorSCCinterruptChngNtfy(void); EXPORTVAR(blnr, InterruptButton) EXPORTPROC SetInterruptButton(blnr v); enum { kICT_SubTick, #if EmClassicKbrd kICT_Kybd_ReceiveCommand, kICT_Kybd_ReceiveEndCommand, #endif #if EmADB kICT_ADB_NewState, #endif #if EmPMU kICT_PMU_Task, #endif kICT_VIA1_Timer1Check, kICT_VIA1_Timer2Check, #if EmVIA2 kICT_VIA2_Timer1Check, kICT_VIA2_Timer2Check, #endif kNumICTs }; EXPORTPROC ICT_add(int taskid, ui5b n); #define iCountt ui5b EXPORTFUNC iCountt GetCuriCount(void); EXPORTPROC ICT_Zap(void); EXPORTVAR(uimr, ICTactive) EXPORTVAR(iCountt, ICTwhen[kNumICTs]) EXPORTVAR(iCountt, NextiCount) EXPORTVAR(ui3b, Wires[kNumWires]) #define kLn2CycleScale 6 #define kCycleScale (1 << kLn2CycleScale) #if WantCycByPriOp #define RdAvgXtraCyc /* 0 */ (kCycleScale + kCycleScale / 4) #define WrAvgXtraCyc /* 0 */ (kCycleScale + kCycleScale / 4) #endif #define kNumSubTicks 16 #define HaveMasterMyEvtQLock EmClassicKbrd #if HaveMasterMyEvtQLock EXPORTVAR(ui4r, MasterMyEvtQLock) #endif EXPORTFUNC blnr FindKeyEvent(int *VirtualKey, blnr *KeyDown); /* minivmac extensions */ #define ExtnDat_checkval 0 #define ExtnDat_extension 2 #define ExtnDat_commnd 4 #define ExtnDat_result 6 #define ExtnDat_params 8 #define kCmndVersion 0 #define ExtnDat_version 8 enum { kExtnFindExtn, /* must be first */ kExtnDisk, kExtnSony, #if EmVidCard kExtnVideo, #endif #if IncludeExtnPbufs kExtnParamBuffers, #endif #if IncludeExtnHostTextClipExchange kExtnHostTextClipExchange, #endif kNumExtns }; #define kcom_callcheck 0x5B17 EXPORTVAR(ui5r, my_disk_icon_addr) EXPORTPROC Memory_Reset(void); EXPORTPROC Extn_Reset(void); EXPORTPROC customreset(void); struct ATTer { struct ATTer *Next; ui5r cmpmask; ui5r cmpvalu; ui5r Access; ui5r usemask; /* Should be one less than a power of two. */ ui3p usebase; ui3r MMDV; ui3r Ntfy; ui4r Pad0; ui5r Pad1; /* make 32 byte structure, on 32 bit systems */ }; typedef struct ATTer ATTer; typedef ATTer *ATTep; #define kATTA_readreadybit 0 #define kATTA_writereadybit 1 #define kATTA_mmdvbit 2 #define kATTA_ntfybit 3 #define kATTA_readwritereadymask \ ((1 << kATTA_readreadybit) | (1 << kATTA_writereadybit)) #define kATTA_readreadymask (1 << kATTA_readreadybit) #define kATTA_writereadymask (1 << kATTA_writereadybit) #define kATTA_mmdvmask (1 << kATTA_mmdvbit) #define kATTA_ntfymask (1 << kATTA_ntfybit) EXPORTFUNC ui5b MMDV_Access(ATTep p, ui5b Data, blnr WriteMem, blnr ByteSize, CPTR addr); EXPORTFUNC blnr MemAccessNtfy(ATTep pT); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/HPMCHACK.h b/Mini vMac/mnvm_core/HPMCHACK.h new file mode 100755 index 0000000..9a7e8f8 --- /dev/null +++ b/Mini vMac/mnvm_core/HPMCHACK.h @@ -0,0 +1 @@ +/* HPMCHACK.c Copyright (C) 2016 Steve Chamberlin, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* HaPpy MaCintosh Hack Patch the ROM for alternatives to the Happy Macintosh icon displayed on boot when a disk is inserted. */ #define kAHM_aside 0 #define kAHM_cheese 1 #define kAHM_evil 2 #define kAHM_horror 3 #define kAHM_lady_mac 4 #define kAHM_moustache 5 #define kAHM_nerdy 6 #define kAHM_pirate 7 #define kAHM_sleepy 8 #define kAHM_sly 9 #define kAHM_sunglasses 10 #define kAHM_surprise 11 #define kAHM_tongue 12 #define kAHM_yuck 13 #define kAHM_zombie 14 LOCALVAR const ui3b my_HappyMac_icon[] = { #if CurAltHappyMac == kAHM_aside 0x00, 0x00, 0x39, 0x38, 0x21, 0x20, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00 #endif #if CurAltHappyMac == kAHM_cheese 0x10, 0x10, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF8, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0x10, 0x10, 0x0F, 0xE0, #endif #if CurAltHappyMac == kAHM_evil 0x00, 0x00, 0x10, 0x10, 0x08, 0x20, 0x0C, 0x60, 0x00, 0x00, 0x20, 0x08, 0x20, 0x08, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00 #endif #if CurAltHappyMac == kAHM_horror 0x38, 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x38, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80 #endif #if CurAltHappyMac == kAHM_lady_mac 0x38, 0x38, 0x45, 0x44, 0x55, 0x54, 0x45, 0x44, 0x39, 0x38, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x03, 0x00 #endif #if CurAltHappyMac == kAHM_moustache 0x00, 0x00, 0x11, 0x10, 0x11, 0x10, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x08, 0x40, 0x07, 0x80 #endif #if CurAltHappyMac == kAHM_nerdy 0x38, 0x38, 0x45, 0x45, 0xD7, 0xD6, 0x45, 0x44, 0x39, 0x38, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00 #endif #if CurAltHappyMac == kAHM_pirate 0x00, 0x81, 0x00, 0x7E, 0x11, 0x7E, 0x11, 0x3C, 0x01, 0x3C, 0x01, 0x18, 0x03, 0x00, 0x00, 0x00, 0x08, 0x40, 0x07, 0x80 #endif #if CurAltHappyMac == kAHM_sleepy 0x00, 0x00, 0x1C, 0x70, 0x22, 0x88, 0x00, 0x00, 0x1C, 0x70, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00 #endif #if CurAltHappyMac == kAHM_sly 0x00, 0x00, 0x08, 0x20, 0x14, 0x50, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x3F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 #endif #if CurAltHappyMac == kAHM_sunglasses 0x00, 0x00, 0xFF, 0xFE, 0x7D, 0x7C, 0x7D, 0x7C, 0x39, 0x38, 0x03, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00 #endif #if CurAltHappyMac == kAHM_surprise 0x1C, 0x70, 0x22, 0x88, 0x41, 0x04, 0x49, 0x24, 0x41, 0x04, 0x22, 0x88, 0x1C, 0x70, 0x01, 0x00, 0x03, 0x80, 0x03, 0x80 #endif #if CurAltHappyMac == kAHM_tongue 0x00, 0x00, 0x1E, 0x78, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04, 0x3F, 0xFC, 0x05, 0x40, 0x05, 0x40, 0x04, 0x40, 0x03, 0x80 #endif #if CurAltHappyMac == kAHM_yuck 0x00, 0x00, 0x18, 0x30, 0x04, 0x40, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x15, 0x50, 0x04, 0x40, 0x03, 0x80 #endif #if CurAltHappyMac == kAHM_zombie 0x70, 0x7C, 0x88, 0x82, 0x88, 0x8A, 0xA8, 0x8A, 0x70, 0x82, 0x00, 0x42, 0x00, 0x3C, 0x1E, 0x00, 0x3F, 0x00, 0x3F, 0x00 #endif }; #if CurEmMd <= kEmMd_Twig43 #define HappyMacBase 0xA34 #elif CurEmMd <= kEmMd_Twiggy #define HappyMacBase 0x8F4 #elif CurEmMd <= kEmMd_128K #define HappyMacBase 0x8A0 #elif CurEmMd <= kEmMd_Plus #define HappyMacBase 0xFD2 #elif CurEmMd <= kEmMd_Classic #define HappyMacBase 0x125C #elif CurEmMd <= kEmMd_PB100 #define HappyMacBase 0x2BB0 #elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) #define HappyMacBase 0x1948 #endif LOCALPROC PatchHappyMac(void) { #if (CurEmMd == kEmMd_PB100) \ || (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) int i; ui3b *dst = HappyMacBase + ROM + 0x18; ui3b *src = (ui3b *)my_HappyMac_icon; for (i = 10; --i >= 0; ) { ++dst; *dst++ = *src++; *dst++ = *src++; ++dst; } #else MyMoveBytes((anyp)my_HappyMac_icon, (anyp)(HappyMacBase + ROM), sizeof(my_HappyMac_icon)); #endif } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/INTLCHAR.h b/Mini vMac/mnvm_core/INTLCHAR.h index e943c8a..d7a0dd9 100755 --- a/Mini vMac/mnvm_core/INTLCHAR.h +++ b/Mini vMac/mnvm_core/INTLCHAR.h @@ -1,1951 +1 @@ -/* - INTLCHAR.h - - Copyright (C) 2010 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - InterNaTionAL CHARacters -*/ - -/* master copy of private font data */ -/* - Data in commments: - Mini vMac Cell name - Mac Roman - windows-1252 code page - Unicode - plain ascii - ClStrAppendSubstCStr encoding - HTML character entity -*/ -LOCALVAR const ui3b CellData[] = { - /* kCellUpA 101 0x41 0x0041 'A' 'A' A */ - 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x7E, - 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellUpB 102 0x42 0x0042 'B' 'B' B */ - 0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x7C, 0x42, - 0x42, 0x42, 0x42, 0x7C, 0x00, 0x00, 0x00, 0x00, - /* kCellUpC 103 0x43 0x0043 'C' 'C' C */ - 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x40, 0x40, - 0x40, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellUpD 104 0x44 0x0044 'D' 'D' D */ - 0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x7C, 0x00, 0x00, 0x00, 0x00, - /* kCellUpE 105 0x45 0x0045 'E' 'E' E */ - 0x00, 0x00, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, - 0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, - /* kCellUpF 106 0x46 0x0046 'F' 'F' F */ - 0x00, 0x00, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, - 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, - /* kCellUpG 107 0x47 0x0047 'G' 'G' G */ - 0x00, 0x00, 0x00, 0x3C, 0x42, 0x40, 0x40, 0x4E, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellUpH 110 0x48 0x0048 'H' 'H' H */ - 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7E, - 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellUpI 111 0x49 0x0049 'I' 'I' I */ - 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, - /* kCellUpJ 112 0x4A 0x004A 'J' 'J' J */ - 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellUpK 113 0x4B 0x004B 'K' 'K' K */ - 0x00, 0x00, 0x00, 0x42, 0x44, 0x48, 0x50, 0x60, - 0x50, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellUpL 114 0x4C 0x004C 'L' 'L' L */ - 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, - /* kCellUpM 115 0x4D 0x004D 'M' 'M' M */ - 0x00, 0x00, 0x00, 0x82, 0xC6, 0xAA, 0x92, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00, - /* kCellUpN 116 0x4E 0x004E 'N' 'N' N */ - 0x00, 0x00, 0x00, 0x42, 0x42, 0x62, 0x52, 0x4A, - 0x46, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellUpO 117 0x4F 0x004F 'O' 'O' O */ - 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellUpP 120 0x50 0x0050 'P' 'P' P */ - 0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x7C, - 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, - /* kCellUpQ 121 0x51 0x0051 'Q' 'Q' Q */ - 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x10, 0x0C, 0x00, 0x00, - /* kCellUpR 122 0x52 0x0052 'R' 'R' R */ - 0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x7C, - 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellUpS 123 0x53 0x0053 'S' 'S' S */ - 0x00, 0x00, 0x00, 0x3C, 0x42, 0x40, 0x40, 0x3C, - 0x02, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellUpT 124 0x54 0x0054 'T' 'T' T */ - 0x00, 0x00, 0x00, 0x7F, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, - /* kCellUpU 125 0x55 0x0055 'U' 'U' U */ - 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellUpV 126 0x56 0x0056 'V' 'V' V */ - 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x44, - 0x48, 0x50, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, - /* kCellUpW 127 0x57 0x0057 'W' 'W' W */ - 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x5A, 0x66, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellUpX 130 0x58 0x0058 'X' 'X' X */ - 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x24, 0x18, - 0x24, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellUpY 131 0x59 0x0059 'Y' 'Y' Y */ - 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x14, - 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, - /* kCellUpZ 132 0x5A 0x005A 'Z' 'Z' Z */ - 0x00, 0x00, 0x00, 0x7E, 0x02, 0x04, 0x08, 0x10, - 0x20, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, - /* kCellLoA 141 0x61 0x0061 'a' 'a' a */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x42, - 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, - /* kCellLoB 142 0x62 0x0062 'b' 'b' b */ - 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7C, 0x42, - 0x42, 0x42, 0x42, 0x7C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoC 143 0x63 0x0063 'c' 'c' c */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, - 0x40, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoD 144 0x64 0x0064 'd' 'd' d */ - 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x3E, 0x42, - 0x42, 0x42, 0x42, 0x3E, 0x00, 0x00, 0x00, 0x00, - /* kCellLoE 145 0x65 0x0065 'e' 'e' e */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, - 0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoF 146 0x66 0x0066 'f' 'f' f */ - 0x00, 0x00, 0x00, 0x0E, 0x10, 0x10, 0x3C, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, - /* kCellLoG 147 0x67 0x0067 'g' 'g' g */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x42, - 0x42, 0x42, 0x42, 0x3E, 0x02, 0x42, 0x3C, 0x00, - /* kCellLoH 150 0x68 0x0068 'h' 'h' h */ - 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7C, 0x42, - 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellLoI 151 0x69 0x0069 'i' 'i' i */ - 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, - /* kCellLoJ 152 0x6A 0x006A 'j' 'j' j */ - 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x70, 0x00, - /* kCellLoK 153 0x6B 0x006B 'k' 'k' k */ - 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x44, 0x48, - 0x70, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellLoL 154 0x6C 0x006C 'l' 'l' l */ - 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, - /* kCellLoM 155 0x6D 0x006D 'm' 'm' m */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x00, 0x00, 0x00, 0x00, - /* kCellLoN 156 0x6E 0x006E 'n' 'n' n */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x42, - 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellLoO 157 0x6F 0x006F 'o' 'o' o */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoP 160 0x70 0x0070 'p' 'p' p */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x42, - 0x42, 0x42, 0x42, 0x7C, 0x40, 0x40, 0x00, 0x00, - /* kCellLoQ 161 0x71 0x0071 'q' 'q' q */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x42, - 0x42, 0x42, 0x42, 0x3E, 0x02, 0x02, 0x00, 0x00, - /* kCellLoR 162 0x72 0x0072 'r' 'r' r */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5C, 0x62, - 0x42, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, - /* kCellLoS 163 0x73 0x0073 's' 's' s */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, - 0x3C, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoT 164 0x74 0x0074 't' 't' t */ - 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x78, 0x20, - 0x20, 0x20, 0x20, 0x1C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoU 165 0x75 0x0075 'u' 'u' u */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, - 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, - /* kCellLoV 166 0x76 0x0076 'v' 'v' v */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x44, - 0x48, 0x50, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, - /* kCellLoW 167 0x77 0x0077 'w' 'w' w */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x6C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoX 170 0x78 0x0078 'x' 'x' x */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x24, - 0x18, 0x18, 0x24, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellLoY 171 0x79 0x0079 'y' 'y' y */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3E, 0x02, 0x42, 0x3C, 0x00, - /* kCellLoZ 172 0x7A 0x007A 'z' 'z' z */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x04, - 0x08, 0x10, 0x20, 0x7E, 0x00, 0x00, 0x00, 0x00, - /* kCellDigit0 060 0x30 0x0030 '0' '0' 0 */ - 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellDigit1 061 0x31 0x0031 '1' '1' 1 */ - 0x00, 0x00, 0x00, 0x08, 0x18, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, - /* kCellDigit2 062 0x32 0x0032 '2' '2' 2 */ - 0x00, 0x00, 0x00, 0x3C, 0x42, 0x02, 0x02, 0x04, - 0x08, 0x10, 0x20, 0x7E, 0x00, 0x00, 0x00, 0x00, - /* kCellDigit3 063 0x33 0x0033 '3' '3' 3 */ - 0x00, 0x00, 0x00, 0x3C, 0x42, 0x02, 0x0C, 0x02, - 0x02, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellDigit4 064 0x34 0x0034 '4' '4' 4 */ - 0x00, 0x00, 0x00, 0x04, 0x0C, 0x14, 0x24, 0x7E, - 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, - /* kCellDigit5 065 0x35 0x0035 '5' '5' 5 */ - 0x00, 0x00, 0x00, 0x7E, 0x40, 0x40, 0x7C, 0x02, - 0x02, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellDigit6 066 0x36 0x0036 '6' '6' 6 */ - 0x00, 0x00, 0x00, 0x1C, 0x20, 0x40, 0x7C, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellDigit7 067 0x37 0x0037 '7' '7' 7 */ - 0x00, 0x00, 0x00, 0x7E, 0x02, 0x02, 0x04, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, - /* kCellDigit8 070 0x38 0x0038 '8' '8' 8 */ - 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x3C, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellDigit9 071 0x39 0x0039 '9' '9' 9 */ - 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, - 0x3E, 0x02, 0x04, 0x38, 0x00, 0x00, 0x00, 0x00, - /* kCellExclamation 041 0x21 0x0021 '!' '!' ! */ - 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, - /* kCellAmpersand 046 0x26 0x0026 '&' '&' amp */ - 0x00, 0x00, 0x00, 0x30, 0x48, 0x48, 0x50, 0x20, - 0x50, 0x4A, 0x44, 0x3A, 0x00, 0x00, 0x00, 0x00, - /* kCellApostrophe 047 0x27 0x0027 '\047' ';la' apos */ - 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* kCellLeftParen 050 0x28 0x0028 '(' '(' ( */ - 0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, - /* kCellRightParen 051 0x29 0x0029 ')' ')' ) */ - 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, - /* kCellComma 054 0x2C 0x002C ',' ',' , */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x08, 0x08, 0x08, 0x10, 0x00, 0x00, - /* kCellHyphen 055 0x2D 0x002D '-' '-' - */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* kCellPeriod 056 0x2E 0x002E '.' '.' . */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, - /* kCellSlash 057 0x2F 0x002F '/' '/' / */ - 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x08, 0x08, - 0x10, 0x10, 0x20, 0x20, 0x40, 0x00, 0x00, 0x00, - /* kCellColon 072 0x3A 0x003A ':' ':' : */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, - 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, - /* kCellSemicolon 073 0x3B 0x003B ';' ';ls' #59 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, - 0x00, 0x00, 0x08, 0x08, 0x08, 0x10, 0x00, 0x00, - /* kCellQuestion 077 0x3F 0x003F '?' '?' ? */ - 0x00, 0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x10, - 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, - /* kCellEllipsis 311 0x85 0x2026 '_' ';ll' #8230 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, - /* kCellUnderscore 137 0x5F 0x005F '_' '_' _ */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, - /* kCellLeftDQuote 322 0x93 0x201C '"' ';[' ldquo */ - 0x00, 0x00, 0x00, 0x24, 0x48, 0x6C, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* kCellRightDQuote 323 0x94 0x201D '"' ';{' rdquo */ - 0x00, 0x00, 0x00, 0x36, 0x12, 0x24, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* kCellLeftSQuote 324 0x91 0x2018 '\047' ';]' lsquo */ - 0x00, 0x00, 0x00, 0x08, 0x10, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* kCellRightSQuote 325 0x92 0x2019 '\047' ';}' rsquo */ - 0x00, 0x00, 0x00, 0x18, 0x08, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* kCellCopyright 251 0xA9 0x00A9 'c' ';g' copy */ - 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x9A, 0xA2, - 0xA2, 0x9A, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, - /* kCellSpace 040 0x20 0x0020 '\040' '' #32 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - -#if NeedIntlChars - /* kCellUpADiaeresis 200 0xC4 0x00C4 'A' ';uA' Auml */ - 0x00, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x7E, - 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellUpARing 201 0xC5 0x00C5 'A' ';A' Aring */ - 0x3C, 0x42, 0x42, 0x3C, 0x42, 0x42, 0x42, 0x7E, - 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellUpCCedilla 202 0xC7 0x00C7 'C' ';C' Ccedil */ - 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x40, 0x40, - 0x40, 0x40, 0x42, 0x3C, 0x08, 0x08, 0x10, 0x00, - /* kCellUpEAcute 203 0xC9 0x00C9 'E' ';eE' Eacute */ - 0x08, 0x10, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, - 0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, - /* kCellUpNTilde 204 0xD1 0x00D1 'N' ';nN' Ntilde */ - 0x32, 0x4C, 0x00, 0x42, 0x42, 0x62, 0x52, 0x4A, - 0x46, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellUpODiaeresis 205 0xD6 0x00D6 'O' ';uO' Ouml */ - 0x00, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellUpUDiaeresis 206 0xDC 0x00DC 'U' ';uU' Uuml */ - 0x00, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoAAcute 207 0xE1 0x00E1 'a' ';ea' aacute */ - 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3E, 0x42, - 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, - /* kCellLoAGrave 210 0xE0 0x00E0 'a' ';`a' agrave */ - 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3E, 0x42, - 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, - /* kCellLoACircumflex 211 0xE2 0x00E2 'a' ';ia' acirc */ - 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3E, 0x42, - 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, - /* kCellLoADiaeresis 212 0xE4 0x00E4 'a' ';ua' auml */ - 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x3E, 0x42, - 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, - /* kCellLoATilde 213 0xE3 0x00E3 'a' ';na' atilde */ - 0x00, 0x00, 0x00, 0x32, 0x4C, 0x00, 0x3E, 0x42, - 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, - /* kCellLoARing 214 0xE5 0x00E5 'a' ';a' aring */ - 0x00, 0x00, 0x18, 0x24, 0x24, 0x18, 0x3E, 0x42, - 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, - /* kCellLoCCedilla 215 0xE7 0x00E7 'c' ';c' ccedil */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, - 0x40, 0x40, 0x42, 0x3C, 0x08, 0x08, 0x10, 0x00, - /* kCellLoEAcute 216 0xE9 0x00E9 'e' ';ee' eacute */ - 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3C, 0x42, - 0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoEGrave 217 0xE8 0x00E8 'e' ';`e' egrave */ - 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3C, 0x42, - 0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoECircumflex 220 0xEA 0x00EA 'e' ';ie' ecirc */ - 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3C, 0x42, - 0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoEDiaeresis 221 0xEB 0x00EB 'e' ';ue' euml */ - 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x3C, 0x42, - 0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoIAcute 222 0xED 0x00ED 'i' ';ei' iacute */ - 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, - /* kCellLoIGrave 223 0xEC 0x00EC 'i' ';`i' igrave */ - 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, - /* kCellLoICircumflex 224 0xEE 0x00EE 'i' ';ii' icirc */ - 0x00, 0x00, 0x00, 0x10, 0x28, 0x00, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, - /* kCellLoIDiaeresis 225 0xEF 0x00EF 'i' ';ui' iuml */ - 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, - /* kCellLoNTilde 226 0xF1 0x00F1 'n' ';nn' ntilde */ - 0x00, 0x00, 0x00, 0x32, 0x4C, 0x00, 0x7C, 0x42, - 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellLoOAcute 227 0xF3 0x00F3 'o' ';eo' oacute */ - 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3C, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoOGrave 230 0xF2 0x00F2 'o' ';`o' ograve */ - 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3C, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoOCircumflex 231 0xF4 0x00F4 'o' ';io' ocirc */ - 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3C, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoODiaeresis 232 0xF6 0x00F6 'o' ';uo' ouml */ - 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x3C, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoOTilde 233 0xF5 0x00F5 'o' ';no' otilde */ - 0x00, 0x00, 0x00, 0x32, 0x4C, 0x00, 0x3C, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoUAcute 234 0xFA 0x00FA 'u' ';eu' uacute */ - 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x42, 0x42, - 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, - /* kCellLoUGrave 235 0xF9 0x00F9 'u' ';`u' ugrave */ - 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x42, 0x42, - 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, - /* kCellLoUCircumflex 236 0xFB 0x00FB 'u' ';iu' ucirc */ - 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x42, 0x42, - 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, - /* kCellLoUDiaeresis 237 0xFC 0x00FC 'u' ';uu' uuml */ - 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x42, 0x42, - 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, - - /* kCellUpAE 256 0xC6 0x00C6 '?' ';lE' AElig */ - 0x00, 0x00, 0x00, 0x3E, 0x48, 0x48, 0x48, 0x7C, - 0x48, 0x48, 0x48, 0x4E, 0x00, 0x00, 0x00, 0x00, - /* kCellUpOStroke 257 0xD8 0x00D8 'O' ';O' Oslash */ - 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x46, 0x5A, - 0x62, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - - /* kCellLoAE 276 0xE6 0x00E6 '?' ';le' aelig */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x52, - 0x5E, 0x50, 0x52, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoOStroke 277 0xF8 0x00F8 'o' ';o' oslash */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x46, - 0x5A, 0x62, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellInvQuestion 300 0xBF 0x00BF '?' ';?' iquest */ - 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, - 0x20, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, - /* kCellInvExclam 301 0xA1 0x00A1 '!' ';1' iexcl */ - 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, - - /* kCellUpAGrave 313 0xC0 0x00C0 'A' ';`A' Agrave */ - 0x10, 0x08, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, - 0x7E, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellUpATilde 314 0xC3 0x00C3 'A' ';nA' Atilde */ - 0x32, 0x4C, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, - 0x7E, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellUpOTilde 315 0xD5 0x00D5 'O' ';nO' Otilde */ - 0x32, 0x4C, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellUpLigatureOE 316 0x8C 0x0152 '?' ';Q' OElig */ - 0x00, 0x00, 0x00, 0x3E, 0x48, 0x48, 0x48, 0x4E, - 0x48, 0x48, 0x48, 0x3E, 0x00, 0x00, 0x00, 0x00, - /* kCellLoLigatureOE 317 0x9C 0x0153 '?' ';q' oelig */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x52, - 0x5E, 0x50, 0x52, 0x2C, 0x00, 0x00, 0x00, 0x00, - - /* kCellLoYDiaeresis 330 0xFF 0x00FF 'y' ';uy' yuml */ - 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3E, 0x02, 0x42, 0x3C, 0x00, - /* kCellUpYDiaeresis 331 0x9F 0x0178 'Y' ';uY' Yuml */ - 0x00, 0x14, 0x00, 0x22, 0x22, 0x22, 0x22, 0x14, - 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, - - /* kCellUpACircumflex 345 0xC2 0x00C2 'A' ';iA' Acirc */ - 0x18, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x7E, - 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellUpECircumflex 346 0xCA 0x00CA 'E' ';iE' Ecirc */ - 0x18, 0x24, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, - 0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, - /* kCellUpAAcute 347 0xC1 0x00C1 'A' ';eA' Aacute */ - 0x08, 0x10, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, - 0x7E, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellUpEDiaeresis 350 0xCB 0x00CB 'E' ';uE' Euml */ - 0x00, 0x24, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, - 0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, - /* kCellUpEGrave 351 0xC8 0x00C8 'E' ';`E' Egrave */ - 0x10, 0x08, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, - 0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, - /* kCellUpIAcute 352 0xCD 0x00CD 'A' ';eI' Iacute */ - 0x04, 0x08, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x00, - /* kCellUpICircumflex 353 0xCE 0x00CE 'I' ';iI' Icirc */ - 0x08, 0x14, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x00, - /* kCellUpIDiaeresis 354 0xCF 0x00CF 'I' ';uI' Iuml */ - 0x00, 0x14, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x00, - /* kCellUpIGrave 355 0xCC 0x00CC 'I' ';`I' Igrave */ - 0x10, 0x08, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x00, - /* kCellUpOAcute 356 0xD3 0x00D3 'O' ';eO' Oacute */ - 0x08, 0x10, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellUpOCircumflex 357 0xD4 0x00D4 'O' ';iO' Ocirc */ - 0x18, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - - /* kCellUpOGrave 361 0xD2 0x00D2 'O' ';`O' Ograve */ - 0x10, 0x08, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellUpUAcute 362 0xDA 0x00DA 'U' ';eU' Uacute */ - 0x08, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellUpUCircumflex 363 0xDB 0x00DB 'U' ';iU' Ucirc */ - 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellUpUGrave 364 0xD9 0x00D9 'U' ';`U' Ugrave */ - 0x10, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellSharpS 247 0xDF 0x00DF 'B' ';s' szlig */ - 0x00, 0x00, 0x00, 0x1C, 0x22, 0x42, 0x44, 0x44, - 0x42, 0x42, 0x42, 0x5C, 0x40, 0x00, 0x00, 0x00, - - /* kCellUpACedille 260 ? 0x0104 'A' ';dA' #260 */ - 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x7E, - 0x42, 0x42, 0x42, 0x42, 0x04, 0x04, 0x02, 0x00, - /* kCellLoACedille 261 ? 0x0105 'a' ';da' #261 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x42, - 0x42, 0x42, 0x46, 0x3A, 0x04, 0x04, 0x02, 0x00, - /* kCellUpCAcute 262 ? 0x0106 'C' ';eC' #262 */ - 0x08, 0x10, 0x00, 0x3C, 0x42, 0x42, 0x40, 0x40, - 0x40, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoCAcute 263 ? 0x0107 'c' ';ec' #263 */ - 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3C, 0x42, - 0x40, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellUpECedille 264 ? 0x0118 'E' ';dE' #280 */ - 0x00, 0x00, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, - 0x40, 0x40, 0x40, 0x7E, 0x04, 0x04, 0x02, 0x00, - /* kCellLoECedille 265 ? 0x0119 'e' ';de' #281 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, - 0x7E, 0x40, 0x42, 0x3C, 0x08, 0x08, 0x04, 0x00, - /* kCellUpLBar 266 ? 0x0141 'L' ';dL' #321 */ - 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x60, 0x40, - 0xC0, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, - /* kCellLoLBar 267 ? 0x0142 'l' ';dl' #322 */ - 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x0C, 0x08, - 0x18, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, - /* kCellUpNAcute 270 ? 0x0143 'N' ';eN' #323 */ - 0x08, 0x10, 0x00, 0x42, 0x42, 0x62, 0x52, 0x4A, - 0x46, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellLoNAcute 271 ? 0x0144 'n' ';en' #324 */ - 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x7C, 0x42, - 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, - /* kCellUpSAcute 272 ? 0x015A 'S' ';eS' #346 */ - 0x08, 0x10, 0x00, 0x3C, 0x42, 0x40, 0x40, 0x3C, - 0x02, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellLoSAcute 273 ? 0x015B 's' ';es' #347 */ - 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3C, 0x42, - 0x3C, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, - /* kCellUpZAcute 274 ? 0x0179 'Z' ';eZ' #377 */ - 0x08, 0x10, 0x00, 0x7E, 0x02, 0x04, 0x08, 0x10, - 0x20, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, - /* kCellLoZAcute 275 ? 0x017A 'z' ';ez' #378 */ - 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x7E, 0x04, - 0x08, 0x10, 0x20, 0x7E, 0x00, 0x00, 0x00, 0x00, - /* kCellUpZDot 276 ? 0x017B 'Z' ';dZ' #379 */ - 0x10, 0x00, 0x00, 0x7E, 0x02, 0x04, 0x08, 0x10, - 0x20, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, - /* kCellLoZDot 277 ? 0x017C 'z' ';dz' #380 */ - 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x7E, 0x04, - 0x08, 0x10, 0x20, 0x7E, 0x00, 0x00, 0x00, 0x00, -#endif - - /* kCellUpperLeft */ - 0xFF, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - /* kCellUpperMiddle */ - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* kCellMiddleLeft */ - 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - /* kCellMiddleLeft */ - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - /* kCellMiddleRight */ - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - /* kCellLowerLeft */ - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFF, - /* kCellLowerMiddle */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - /* kCellLowerRight */ - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, - /* kCellGraySep */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* kCellIcon00 */ - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, - /* kCellIcon01 */ - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x18, 0x18, - /* kCellIcon02 */ - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x18, 0x30, - /* kCellIcon03 */ - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xE0, 0x10, 0x10, 0x10, 0x90, 0x90, 0x90, - /* kCellIcon10 */ - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - /* kCellIcon11 */ - 0x18, 0x18, 0x19, 0x1B, 0x1E, 0x1C, 0x18, 0x10, - 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* kCellIcon12 */ - 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, - /* kCellIcon13 */ - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - /* kCellIcon20 */ - 0x08, 0x08, 0x08, 0x07, 0x04, 0x04, 0x04, 0x07, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* kCellIcon21 */ - 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* kCellIcon22 */ - 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* kCellIcon23 */ - 0x10, 0x10, 0x10, 0xE0, 0x20, 0x20, 0x20, 0xE0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -#if EnableAltKeysMode - /* kInsertText00 */ - 0xFF, 0x80, 0x80, 0x80, 0x80, 0x83, 0x80, 0x80, - 0x80, 0x80, 0x83, 0x80, 0x80, 0x80, 0x80, 0xFF, - /* kInsertText01 */ - 0xFF, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x19, - 0x1B, 0x1E, 0x1C, 0x18, 0x10, 0x00, 0x00, 0xFF, - /* kInsertText02 */ - 0xFF, 0x00, 0x00, 0x18, 0x30, 0x60, 0xC0, 0x80, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, - /* kInsertText03 */ - 0xFF, 0x01, 0x01, 0x01, 0x01, 0xC1, 0x01, 0x01, - 0x01, 0x01, 0xC1, 0x01, 0x01, 0x01, 0x01, 0xFF, - /* kInsertText04 */ - 0xFF, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, - 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0x00, 0xFF, -#endif -#if EnableDemoMsg - /* kCellDemo0 */ - 0xFF, 0x80, 0x80, 0x80, 0x80, 0x83, 0x80, 0x80, - 0x80, 0x80, 0x83, 0x80, 0x80, 0x80, 0x80, 0xFF, - /* kCellDemo1 */ - 0xFF, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x7C, 0x00, 0x00, 0x00, 0xFF, - /* kCellDemo2 */ - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, - 0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0xFF, - /* kCellDemo3 */ - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x00, 0x00, 0x00, 0xFF, - /* kCellDemo4 */ - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, - 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0xFF, - /* kCellDemo5 */ - 0xFF, 0x01, 0x01, 0x01, 0x01, 0xC1, 0x01, 0x01, - 0x01, 0x01, 0xC1, 0x01, 0x01, 0x01, 0x01, 0xFF, - /* kCellDemo6 */ - 0xFF, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, - 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0x00, 0xFF, - /* kCellDemo7 */ - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, -#endif - - 0x00 /* just so last above line can end in ',' */ -}; - -enum { - kCellUpA, - kCellUpB, - kCellUpC, - kCellUpD, - kCellUpE, - kCellUpF, - kCellUpG, - kCellUpH, - kCellUpI, - kCellUpJ, - kCellUpK, - kCellUpL, - kCellUpM, - kCellUpN, - kCellUpO, - kCellUpP, - kCellUpQ, - kCellUpR, - kCellUpS, - kCellUpT, - kCellUpU, - kCellUpV, - kCellUpW, - kCellUpX, - kCellUpY, - kCellUpZ, - kCellLoA, - kCellLoB, - kCellLoC, - kCellLoD, - kCellLoE, - kCellLoF, - kCellLoG, - kCellLoH, - kCellLoI, - kCellLoJ, - kCellLoK, - kCellLoL, - kCellLoM, - kCellLoN, - kCellLoO, - kCellLoP, - kCellLoQ, - kCellLoR, - kCellLoS, - kCellLoT, - kCellLoU, - kCellLoV, - kCellLoW, - kCellLoX, - kCellLoY, - kCellLoZ, - kCellDigit0, - kCellDigit1, - kCellDigit2, - kCellDigit3, - kCellDigit4, - kCellDigit5, - kCellDigit6, - kCellDigit7, - kCellDigit8, - kCellDigit9, - kCellExclamation, - kCellAmpersand, - kCellApostrophe, - kCellLeftParen, - kCellRightParen, - kCellComma, - kCellHyphen, - kCellPeriod, - kCellSlash, - kCellColon, - kCellSemicolon, - kCellQuestion, - kCellEllipsis, - kCellUnderscore, - kCellLeftDQuote, - kCellRightDQuote, - kCellLeftSQuote, - kCellRightSQuote, - kCellCopyright, - kCellSpace, - -#if NeedIntlChars - kCellUpADiaeresis, - kCellUpARing, - kCellUpCCedilla, - kCellUpEAcute, - kCellUpNTilde, - kCellUpODiaeresis, - kCellUpUDiaeresis, - kCellLoAAcute, - kCellLoAGrave, - kCellLoACircumflex, - kCellLoADiaeresis, - kCellLoATilde, - kCellLoARing, - kCellLoCCedilla, - kCellLoEAcute, - kCellLoEGrave, - kCellLoECircumflex, - kCellLoEDiaeresis, - kCellLoIAcute, - kCellLoIGrave, - kCellLoICircumflex, - kCellLoIDiaeresis, - kCellLoNTilde, - kCellLoOAcute, - kCellLoOGrave, - kCellLoOCircumflex, - kCellLoODiaeresis, - kCellLoOTilde, - kCellLoUAcute, - kCellLoUGrave, - kCellLoUCircumflex, - kCellLoUDiaeresis, - - kCellUpAE, - kCellUpOStroke, - - kCellLoAE, - kCellLoOStroke, - kCellInvQuestion, - kCellInvExclam, - - kCellUpAGrave, - kCellUpATilde, - kCellUpOTilde, - kCellUpLigatureOE, - kCellLoLigatureOE, - - kCellLoYDiaeresis, - kCellUpYDiaeresis, - - kCellUpACircumflex, - kCellUpECircumflex, - kCellUpAAcute, - kCellUpEDiaeresis, - kCellUpEGrave, - kCellUpIAcute, - kCellUpICircumflex, - kCellUpIDiaeresis, - kCellUpIGrave, - kCellUpOAcute, - kCellUpOCircumflex, - - kCellUpOGrave, - kCellUpUAcute, - kCellUpUCircumflex, - kCellUpUGrave, - kCellSharpS, - - kCellUpACedille, - kCellLoACedille, - kCellUpCAcute, - kCellLoCAcute, - kCellUpECedille, - kCellLoECedille, - kCellUpLBar, - kCellLoLBar, - kCellUpNAcute, - kCellLoNAcute, - kCellUpSAcute, - kCellLoSAcute, - kCellUpZAcute, - kCellLoZAcute, - kCellUpZDot, - kCellLoZDot, -#endif - - kCellUpperLeft, - kCellUpperMiddle, - kCellUpperRight, - kCellMiddleLeft, - kCellMiddleRight, - kCellLowerLeft, - kCellLowerMiddle, - kCellLowerRight, - kCellGraySep, - kCellIcon00, - kCellIcon01, - kCellIcon02, - kCellIcon03, - kCellIcon10, - kCellIcon11, - kCellIcon12, - kCellIcon13, - kCellIcon20, - kCellIcon21, - kCellIcon22, - kCellIcon23, -#if EnableAltKeysMode - kInsertText00, - kInsertText01, - kInsertText02, - kInsertText03, - kInsertText04, -#endif -#if EnableDemoMsg - kCellDemo0, - kCellDemo1, - kCellDemo2, - kCellDemo3, - kCellDemo4, - kCellDemo5, - kCellDemo6, - kCellDemo7, -#endif - - kNumCells -}; - -#if UseActvCode && 0 -#define UseActvFile 1 -#else -#define UseActvFile 0 -#endif - -#ifndef NeedCell2MacAsciiMap -#if UseActvCode || EnableDemoMsg -#define NeedCell2MacAsciiMap 1 -#else -#define NeedCell2MacAsciiMap 0 -#endif -#endif - -#if NeedCell2MacAsciiMap -/* Mac Roman character set */ -LOCALVAR const char Cell2MacAsciiMap[] = { - '\101', /* kCellUpA */ - '\102', /* kCellUpB */ - '\103', /* kCellUpC */ - '\104', /* kCellUpD */ - '\105', /* kCellUpE */ - '\106', /* kCellUpF */ - '\107', /* kCellUpG */ - '\110', /* kCellUpH */ - '\111', /* kCellUpI */ - '\112', /* kCellUpJ */ - '\113', /* kCellUpK */ - '\114', /* kCellUpL */ - '\115', /* kCellUpM */ - '\116', /* kCellUpN */ - '\117', /* kCellUpO */ - '\120', /* kCellUpP */ - '\121', /* kCellUpQ */ - '\122', /* kCellUpR */ - '\123', /* kCellUpS */ - '\124', /* kCellUpT */ - '\125', /* kCellUpU */ - '\126', /* kCellUpV */ - '\127', /* kCellUpW */ - '\130', /* kCellUpX */ - '\131', /* kCellUpY */ - '\132', /* kCellUpZ */ - '\141', /* kCellLoA */ - '\142', /* kCellLoB */ - '\143', /* kCellLoC */ - '\144', /* kCellLoD */ - '\145', /* kCellLoE */ - '\146', /* kCellLoF */ - '\147', /* kCellLoG */ - '\150', /* kCellLoH */ - '\151', /* kCellLoI */ - '\152', /* kCellLoJ */ - '\153', /* kCellLoK */ - '\154', /* kCellLoL */ - '\155', /* kCellLoM */ - '\156', /* kCellLoN */ - '\157', /* kCellLoO */ - '\160', /* kCellLoP */ - '\161', /* kCellLoQ */ - '\162', /* kCellLoR */ - '\163', /* kCellLoS */ - '\164', /* kCellLoT */ - '\165', /* kCellLoU */ - '\166', /* kCellLoV */ - '\167', /* kCellLoW */ - '\170', /* kCellLoX */ - '\171', /* kCellLoY */ - '\172', /* kCellLoZ */ - '\060', /* kCellDigit0 */ - '\061', /* kCellDigit1 */ - '\062', /* kCellDigit2 */ - '\063', /* kCellDigit3 */ - '\064', /* kCellDigit4 */ - '\065', /* kCellDigit5 */ - '\066', /* kCellDigit6 */ - '\067', /* kCellDigit7 */ - '\070', /* kCellDigit8 */ - '\071', /* kCellDigit9 */ - '\041', /* kCellExclamation */ - '\046', /* kCellAmpersand */ - '\047', /* kCellApostrophe */ - '\050', /* kCellLeftParen */ - '\051', /* kCellRightParen */ - '\054', /* kCellComma */ - '\055', /* kCellHyphen */ - '\056', /* kCellPeriod */ - '\057', /* kCellSlash */ - '\072', /* kCellColon */ - '\073', /* kCellSemicolon */ - '\077', /* kCellQuestion */ - '\311', /* kCellEllipsis */ - '\137', /* kCellUnderscore */ - '\322', /* kCellLeftDQuote */ - '\323', /* kCellRightDQuote */ - '\324', /* kCellLeftSQuote */ - '\325', /* kCellRightSQuote */ - '\251', /* kCellCopyright */ - '\040', /* kCellSpace */ - -#if NeedIntlChars - '\200', /* kCellUpADiaeresis */ - '\201', /* kCellUpARing */ - '\202', /* kCellUpCCedilla */ - '\203', /* kCellUpEAcute */ - '\204', /* kCellUpNTilde */ - '\205', /* kCellUpODiaeresis */ - '\206', /* kCellUpUDiaeresis */ - '\207', /* kCellLoAAcute */ - '\210', /* kCellLoAGrave */ - '\211', /* kCellLoACircumflex */ - '\212', /* kCellLoADiaeresis */ - '\213', /* kCellLoATilde */ - '\214', /* kCellLoARing */ - '\215', /* kCellLoCCedilla */ - '\216', /* kCellLoEAcute */ - '\217', /* kCellLoEGrave */ - '\220', /* kCellLoECircumflex */ - '\221', /* kCellLoEDiaeresis */ - '\222', /* kCellLoIAcute */ - '\223', /* kCellLoIGrave */ - '\224', /* kCellLoICircumflex */ - '\225', /* kCellLoIDiaeresis */ - '\226', /* kCellLoNTilde */ - '\227', /* kCellLoOAcute */ - '\230', /* kCellLoOGrave */ - '\231', /* kCellLoOCircumflex */ - '\232', /* kCellLoODiaeresis */ - '\233', /* kCellLoOTilde */ - '\234', /* kCellLoUAcute */ - '\235', /* kCellLoUGrave */ - '\236', /* kCellLoUCircumflex */ - '\237', /* kCellLoUDiaeresis */ - - '\256', /* kCellUpAE */ - '\257', /* kCellUpOStroke */ - - '\276', /* kCellLoAE */ - '\277', /* kCellLoOStroke */ - '\300', /* kCellInvQuestion */ - '\301', /* kCellInvExclam */ - - '\313', /* kCellUpAGrave */ - '\314', /* kCellUpATilde */ - '\315', /* kCellUpOTilde */ - '\316', /* kCellUpLigatureOE */ - '\317', /* kCellLoLigatureOE */ - - '\330', /* kCellLoYDiaeresis */ - '\331', /* kCellUpYDiaeresis */ - - '\345', /* kCellUpACircumflex */ - '\346', /* kCellUpECircumflex */ - '\347', /* kCellUpAAcute */ - '\350', /* kCellUpEDiaeresis */ - '\351', /* kCellUpEGrave */ - '\352', /* kCellUpIAcute */ - '\353', /* kCellUpICircumflex */ - '\354', /* kCellUpIDiaeresis */ - '\355', /* kCellUpIGrave */ - '\356', /* kCellUpOAcute */ - '\357', /* kCellUpOCircumflex */ - - '\361', /* kCellUpOGrave */ - '\362', /* kCellUpUAcute */ - '\363', /* kCellUpUCircumflex */ - '\364', /* kCellUpUGrave */ - '\247', /* kCellSharpS */ - - '\260', /* kCellUpACedille */ - '\261', /* kCellLoACedille */ - '\262', /* kCellUpCAcute */ - '\263', /* kCellLoCAcute */ - '\264', /* kCellUpECedille */ - '\265', /* kCellLoECedille */ - '\266', /* kCellUpLBar */ - '\267', /* kCellLoLBar */ - '\270', /* kCellUpNAcute */ - '\271', /* kCellLoNAcute */ - '\272', /* kCellUpSAcute */ - '\273', /* kCellLoSAcute */ - '\274', /* kCellUpZAcute */ - '\275', /* kCellLoZAcute */ - '\276', /* kCellUpZDot */ - '\277', /* kCellLoZDot */ -#endif - - '\0' /* just so last above line can end in ',' */ -}; -#endif - -#ifndef NeedCell2WinAsciiMap -#define NeedCell2WinAsciiMap 0 -#endif - -#if NeedCell2WinAsciiMap -/* Windows character set (windows-1252 code page) */ -LOCALVAR const ui3b Cell2WinAsciiMap[] = { - 0x41, /* kCellUpA */ - 0x42, /* kCellUpB */ - 0x43, /* kCellUpC */ - 0x44, /* kCellUpD */ - 0x45, /* kCellUpE */ - 0x46, /* kCellUpF */ - 0x47, /* kCellUpG */ - 0x48, /* kCellUpH */ - 0x49, /* kCellUpI */ - 0x4A, /* kCellUpJ */ - 0x4B, /* kCellUpK */ - 0x4C, /* kCellUpL */ - 0x4D, /* kCellUpM */ - 0x4E, /* kCellUpN */ - 0x4F, /* kCellUpO */ - 0x50, /* kCellUpP */ - 0x51, /* kCellUpQ */ - 0x52, /* kCellUpR */ - 0x53, /* kCellUpS */ - 0x54, /* kCellUpT */ - 0x55, /* kCellUpU */ - 0x56, /* kCellUpV */ - 0x57, /* kCellUpW */ - 0x58, /* kCellUpX */ - 0x59, /* kCellUpY */ - 0x5A, /* kCellUpZ */ - 0x61, /* kCellLoA */ - 0x62, /* kCellLoB */ - 0x63, /* kCellLoC */ - 0x64, /* kCellLoD */ - 0x65, /* kCellLoE */ - 0x66, /* kCellLoF */ - 0x67, /* kCellLoG */ - 0x68, /* kCellLoH */ - 0x69, /* kCellLoI */ - 0x6A, /* kCellLoJ */ - 0x6B, /* kCellLoK */ - 0x6C, /* kCellLoL */ - 0x6D, /* kCellLoM */ - 0x6E, /* kCellLoN */ - 0x6F, /* kCellLoO */ - 0x70, /* kCellLoP */ - 0x71, /* kCellLoQ */ - 0x72, /* kCellLoR */ - 0x73, /* kCellLoS */ - 0x74, /* kCellLoT */ - 0x75, /* kCellLoU */ - 0x76, /* kCellLoV */ - 0x77, /* kCellLoW */ - 0x78, /* kCellLoX */ - 0x79, /* kCellLoY */ - 0x7A, /* kCellLoZ */ - 0x30, /* kCellDigit0 */ - 0x31, /* kCellDigit1 */ - 0x32, /* kCellDigit2 */ - 0x33, /* kCellDigit3 */ - 0x34, /* kCellDigit4 */ - 0x35, /* kCellDigit5 */ - 0x36, /* kCellDigit6 */ - 0x37, /* kCellDigit7 */ - 0x38, /* kCellDigit8 */ - 0x39, /* kCellDigit9 */ - 0x21, /* kCellExclamation */ - 0x26, /* kCellAmpersand */ - 0x27, /* kCellApostrophe */ - 0x28, /* kCellLeftParen */ - 0x29, /* kCellRightParen */ - 0x2C, /* kCellComma */ - 0x2D, /* kCellHyphen */ - 0x2E, /* kCellPeriod */ - 0x2F, /* kCellSlash */ - 0x3A, /* kCellColon */ - 0x3B, /* kCellSemicolon */ - 0x3F, /* kCellQuestion */ - 0x85, /* kCellEllipsis */ - 0x5F, /* kCellUnderscore */ - 0x93, /* kCellLeftDQuote */ - 0x94, /* kCellRightDQuote */ - 0x91, /* kCellLeftSQuote */ - 0x92, /* kCellRightSQuote */ - 0xA9, /* kCellCopyright */ - 0x20, /* kCellSpace */ - -#if NeedIntlChars - 0xC4, /* kCellUpADiaeresis */ - 0xC5, /* kCellUpARing */ - 0xC7, /* kCellUpCCedilla */ - 0xC9, /* kCellUpEAcute */ - 0xD1, /* kCellUpNTilde */ - 0xD6, /* kCellUpODiaeresis */ - 0xDC, /* kCellUpUDiaeresis */ - 0xE1, /* kCellLoAAcute */ - 0xE0, /* kCellLoAGrave */ - 0xE2, /* kCellLoACircumflex */ - 0xE4, /* kCellLoADiaeresis */ - 0xE3, /* kCellLoATilde */ - 0xE5, /* kCellLoARing */ - 0xE7, /* kCellLoCCedilla */ - 0xE9, /* kCellLoEAcute */ - 0xE8, /* kCellLoEGrave */ - 0xEA, /* kCellLoECircumflex */ - 0xEB, /* kCellLoEDiaeresis */ - 0xED, /* kCellLoIAcute */ - 0xEC, /* kCellLoIGrave */ - 0xEE, /* kCellLoICircumflex */ - 0xEF, /* kCellLoIDiaeresis */ - 0xF1, /* kCellLoNTilde */ - 0xF3, /* kCellLoOAcute */ - 0xF2, /* kCellLoOGrave */ - 0xF4, /* kCellLoOCircumflex */ - 0xF6, /* kCellLoODiaeresis */ - 0xF5, /* kCellLoOTilde */ - 0xFA, /* kCellLoUAcute */ - 0xF9, /* kCellLoUGrave */ - 0xFB, /* kCellLoUCircumflex */ - 0xFC, /* kCellLoUDiaeresis */ - - 0xC6, /* kCellUpAE */ - 0xD8, /* kCellUpOStroke */ - - 0xE6, /* kCellLoAE */ - 0xF8, /* kCellLoOStroke */ - 0xBF, /* kCellInvQuestion */ - 0xA1, /* kCellInvExclam */ - - 0xC0, /* kCellUpAGrave */ - 0xC3, /* kCellUpATilde */ - 0xD5, /* kCellUpOTilde */ - 0x8C, /* kCellUpLigatureOE */ - 0x9C, /* kCellLoLigatureOE */ - - 0xFF, /* kCellLoYDiaeresis */ - 0x9F, /* kCellUpYDiaeresis */ - - 0xC2, /* kCellUpACircumflex */ - 0xCA, /* kCellUpECircumflex */ - 0xC1, /* kCellUpAAcute */ - 0xCB, /* kCellUpEDiaeresis */ - 0xC8, /* kCellUpEGrave */ - 0xCD, /* kCellUpIAcute */ - 0xCE, /* kCellUpICircumflex */ - 0xCF, /* kCellUpIDiaeresis */ - 0xCC, /* kCellUpIGrave */ - 0xD3, /* kCellUpOAcute */ - 0xD4, /* kCellUpOCircumflex */ - - 0xD2, /* kCellUpOGrave */ - 0xDA, /* kCellUpUAcute */ - 0xDB, /* kCellUpUCircumflex */ - 0xD9, /* kCellUpUGrave */ - 0xDF, /* kCellSharpS */ - - 0x41, /* kCellUpACedille */ - 0x61, /* kCellLoACedille */ - 0x43, /* kCellUpCAcute */ - 0x63, /* kCellLoCAcute */ - 0x45, /* kCellUpECedille */ - 0x65, /* kCellLoECedille */ - 0x4C, /* kCellUpLBar */ - 0x6C, /* kCellLoLBar */ - 0x4E, /* kCellUpNAcute */ - 0x6E, /* kCellLoNAcute */ - 0x53, /* kCellUpSAcute */ - 0x73, /* kCellLoSAcute */ - 0x5A, /* kCellUpZAcute */ - 0x7A, /* kCellLoZAcute */ - 0x5A, /* kCellUpZDot */ - 0x7A, /* kCellLoZDot */ -#endif - - '\0' /* just so last above line can end in ',' */ -}; -#endif - -#ifndef NeedCell2PlainAsciiMap -#define NeedCell2PlainAsciiMap 0 -#endif - -#if NeedCell2PlainAsciiMap -/* Plain ascii - remove accents when possible */ -LOCALVAR const char Cell2PlainAsciiMap[] = { - 'A', /* kCellUpA */ - 'B', /* kCellUpB */ - 'C', /* kCellUpC */ - 'D', /* kCellUpD */ - 'E', /* kCellUpE */ - 'F', /* kCellUpF */ - 'G', /* kCellUpG */ - 'H', /* kCellUpH */ - 'I', /* kCellUpI */ - 'J', /* kCellUpJ */ - 'K', /* kCellUpK */ - 'L', /* kCellUpL */ - 'M', /* kCellUpM */ - 'N', /* kCellUpN */ - 'O', /* kCellUpO */ - 'P', /* kCellUpP */ - 'Q', /* kCellUpQ */ - 'R', /* kCellUpR */ - 'S', /* kCellUpS */ - 'T', /* kCellUpT */ - 'U', /* kCellUpU */ - 'V', /* kCellUpV */ - 'W', /* kCellUpW */ - 'X', /* kCellUpX */ - 'Y', /* kCellUpY */ - 'Z', /* kCellUpZ */ - 'a', /* kCellLoA */ - 'b', /* kCellLoB */ - 'c', /* kCellLoC */ - 'd', /* kCellLoD */ - 'e', /* kCellLoE */ - 'f', /* kCellLoF */ - 'g', /* kCellLoG */ - 'h', /* kCellLoH */ - 'i', /* kCellLoI */ - 'j', /* kCellLoJ */ - 'k', /* kCellLoK */ - 'l', /* kCellLoL */ - 'm', /* kCellLoM */ - 'n', /* kCellLoN */ - 'o', /* kCellLoO */ - 'p', /* kCellLoP */ - 'q', /* kCellLoQ */ - 'r', /* kCellLoR */ - 's', /* kCellLoS */ - 't', /* kCellLoT */ - 'u', /* kCellLoU */ - 'v', /* kCellLoV */ - 'w', /* kCellLoW */ - 'x', /* kCellLoX */ - 'y', /* kCellLoY */ - 'z', /* kCellLoZ */ - '0', /* kCellDigit0 */ - '1', /* kCellDigit1 */ - '2', /* kCellDigit2 */ - '3', /* kCellDigit3 */ - '4', /* kCellDigit4 */ - '5', /* kCellDigit5 */ - '6', /* kCellDigit6 */ - '7', /* kCellDigit7 */ - '8', /* kCellDigit8 */ - '9', /* kCellDigit9 */ - '!', /* kCellExclamation */ - '&', /* kCellAmpersand */ - '\047', /* kCellApostrophe */ - '(', /* kCellLeftParen */ - ')', /* kCellRightParen */ - ',', /* kCellComma */ - '-', /* kCellHyphen */ - '.', /* kCellPeriod */ - '/', /* kCellSlash */ - ':', /* kCellColon */ - ';', /* kCellSemicolon */ - '?', /* kCellQuestion */ - '_', /* kCellEllipsis */ - '_', /* kCellUnderscore */ - '"', /* kCellLeftDQuote */ - '"', /* kCellRightDQuote */ - '\047', /* kCellLeftSQuote */ - '\047', /* kCellRightSQuote */ - 'c', /* kCellCopyright */ - ' ', /* kCellSpace */ - -#if NeedIntlChars - 'A', /* kCellUpADiaeresis */ - 'A', /* kCellUpARing */ - 'C', /* kCellUpCCedilla */ - 'E', /* kCellUpEAcute */ - 'N', /* kCellUpNTilde */ - 'O', /* kCellUpODiaeresis */ - 'U', /* kCellUpUDiaeresis */ - 'a', /* kCellLoAAcute */ - 'a', /* kCellLoAGrave */ - 'a', /* kCellLoACircumflex */ - 'a', /* kCellLoADiaeresis */ - 'a', /* kCellLoATilde */ - 'a', /* kCellLoARing */ - 'c', /* kCellLoCCedilla */ - 'e', /* kCellLoEAcute */ - 'e', /* kCellLoEGrave */ - 'e', /* kCellLoECircumflex */ - 'e', /* kCellLoEDiaeresis */ - 'i', /* kCellLoIAcute */ - 'i', /* kCellLoIGrave */ - 'i', /* kCellLoICircumflex */ - 'i', /* kCellLoIDiaeresis */ - 'n', /* kCellLoNTilde */ - 'o', /* kCellLoOAcute */ - 'o', /* kCellLoOGrave */ - 'o', /* kCellLoOCircumflex */ - 'o', /* kCellLoODiaeresis */ - 'o', /* kCellLoOTilde */ - 'u', /* kCellLoUAcute */ - 'u', /* kCellLoUGrave */ - 'u', /* kCellLoUCircumflex */ - 'u', /* kCellLoUDiaeresis */ - - '?', /* kCellUpAE */ - 'O', /* kCellUpOStroke */ - - '?', /* kCellLoAE */ - 'o', /* kCellLoOStroke */ - '?', /* kCellInvQuestion */ - '!', /* kCellInvExclam */ - - 'A', /* kCellUpAGrave */ - 'A', /* kCellUpATilde */ - 'O', /* kCellUpOTilde */ - '?', /* kCellUpLigatureOE */ - '?', /* kCellLoLigatureOE */ - - 'y', /* kCellLoYDiaeresis */ - 'Y', /* kCellUpYDiaeresis */ - - 'A', /* kCellUpACircumflex */ - 'E', /* kCellUpECircumflex */ - 'A', /* kCellUpAAcute */ - 'E', /* kCellUpEDiaeresis */ - 'E', /* kCellUpEGrave */ - 'A', /* kCellUpIAcute */ - 'I', /* kCellUpICircumflex */ - 'I', /* kCellUpIDiaeresis */ - 'I', /* kCellUpIGrave */ - 'O', /* kCellUpOAcute */ - 'O', /* kCellUpOCircumflex */ - - 'O', /* kCellUpOGrave */ - 'U', /* kCellUpUAcute */ - 'U', /* kCellUpUCircumflex */ - 'U', /* kCellUpUGrave */ - 'B', /* kCellSharpS */ - - 'A', /* kCellUpACedille */ - 'a', /* kCellLoACedille */ - 'C', /* kCellUpCAcute */ - 'c', /* kCellLoCAcute */ - 'E', /* kCellUpECedille */ - 'e', /* kCellLoECedille */ - 'L', /* kCellUpLBar */ - 'l', /* kCellLoLBar */ - 'N', /* kCellUpNAcute */ - 'n', /* kCellLoNAcute */ - 'S', /* kCellUpSAcute */ - 's', /* kCellLoSAcute */ - 'Z', /* kCellUpZAcute */ - 'z', /* kCellLoZAcute */ - 'Z', /* kCellUpZDot */ - 'z', /* kCellLoZDot */ -#endif - - '\0' /* just so last above line can end in ',' */ -}; -#endif - -#ifndef NeedCell2UnicodeMap -#define NeedCell2UnicodeMap 0 -#endif - -#if NeedCell2UnicodeMap -/* Unicode character set */ -LOCALVAR const ui4b Cell2UnicodeMap[] = { - 0x0041, /* kCellUpA */ - 0x0042, /* kCellUpB */ - 0x0043, /* kCellUpC */ - 0x0044, /* kCellUpD */ - 0x0045, /* kCellUpE */ - 0x0046, /* kCellUpF */ - 0x0047, /* kCellUpG */ - 0x0048, /* kCellUpH */ - 0x0049, /* kCellUpI */ - 0x004A, /* kCellUpJ */ - 0x004B, /* kCellUpK */ - 0x004C, /* kCellUpL */ - 0x004D, /* kCellUpM */ - 0x004E, /* kCellUpN */ - 0x004F, /* kCellUpO */ - 0x0050, /* kCellUpP */ - 0x0051, /* kCellUpQ */ - 0x0052, /* kCellUpR */ - 0x0053, /* kCellUpS */ - 0x0054, /* kCellUpT */ - 0x0055, /* kCellUpU */ - 0x0056, /* kCellUpV */ - 0x0057, /* kCellUpW */ - 0x0058, /* kCellUpX */ - 0x0059, /* kCellUpY */ - 0x005A, /* kCellUpZ */ - 0x0061, /* kCellLoA */ - 0x0062, /* kCellLoB */ - 0x0063, /* kCellLoC */ - 0x0064, /* kCellLoD */ - 0x0065, /* kCellLoE */ - 0x0066, /* kCellLoF */ - 0x0067, /* kCellLoG */ - 0x0068, /* kCellLoH */ - 0x0069, /* kCellLoI */ - 0x006A, /* kCellLoJ */ - 0x006B, /* kCellLoK */ - 0x006C, /* kCellLoL */ - 0x006D, /* kCellLoM */ - 0x006E, /* kCellLoN */ - 0x006F, /* kCellLoO */ - 0x0070, /* kCellLoP */ - 0x0071, /* kCellLoQ */ - 0x0072, /* kCellLoR */ - 0x0073, /* kCellLoS */ - 0x0074, /* kCellLoT */ - 0x0075, /* kCellLoU */ - 0x0076, /* kCellLoV */ - 0x0077, /* kCellLoW */ - 0x0078, /* kCellLoX */ - 0x0079, /* kCellLoY */ - 0x007A, /* kCellLoZ */ - 0x0030, /* kCellDigit0 */ - 0x0031, /* kCellDigit1 */ - 0x0032, /* kCellDigit2 */ - 0x0033, /* kCellDigit3 */ - 0x0034, /* kCellDigit4 */ - 0x0035, /* kCellDigit5 */ - 0x0036, /* kCellDigit6 */ - 0x0037, /* kCellDigit7 */ - 0x0038, /* kCellDigit8 */ - 0x0039, /* kCellDigit9 */ - 0x0021, /* kCellExclamation */ - 0x0026, /* kCellAmpersand */ - 0x0027, /* kCellApostrophe */ - 0x0028, /* kCellLeftParen */ - 0x0029, /* kCellRightParen */ - 0x002C, /* kCellComma */ - 0x002D, /* kCellHyphen */ - 0x002E, /* kCellPeriod */ - 0x002F, /* kCellSlash */ - 0x003A, /* kCellColon */ - 0x003B, /* kCellSemicolon */ - 0x003F, /* kCellQuestion */ - 0x2026, /* kCellEllipsis */ - 0x005F, /* kCellUnderscore */ - 0x201C, /* kCellLeftDQuote */ - 0x201D, /* kCellRightDQuote */ - 0x2018, /* kCellLeftSQuote */ - 0x2019, /* kCellRightSQuote */ - 0x00A9, /* kCellCopyright */ - 0x0020, /* kCellSpace */ - -#if NeedIntlChars - 0x00C4, /* kCellUpADiaeresis */ - 0x00C5, /* kCellUpARing */ - 0x00C7, /* kCellUpCCedilla */ - 0x00C9, /* kCellUpEAcute */ - 0x00D1, /* kCellUpNTilde */ - 0x00D6, /* kCellUpODiaeresis */ - 0x00DC, /* kCellUpUDiaeresis */ - 0x00E1, /* kCellLoAAcute */ - 0x00E0, /* kCellLoAGrave */ - 0x00E2, /* kCellLoACircumflex */ - 0x00E4, /* kCellLoADiaeresis */ - 0x00E3, /* kCellLoATilde */ - 0x00E5, /* kCellLoARing */ - 0x00E7, /* kCellLoCCedilla */ - 0x00E9, /* kCellLoEAcute */ - 0x00E8, /* kCellLoEGrave */ - 0x00EA, /* kCellLoECircumflex */ - 0x00EB, /* kCellLoEDiaeresis */ - 0x00ED, /* kCellLoIAcute */ - 0x00EC, /* kCellLoIGrave */ - 0x00EE, /* kCellLoICircumflex */ - 0x00EF, /* kCellLoIDiaeresis */ - 0x00F1, /* kCellLoNTilde */ - 0x00F3, /* kCellLoOAcute */ - 0x00F2, /* kCellLoOGrave */ - 0x00F4, /* kCellLoOCircumflex */ - 0x00F6, /* kCellLoODiaeresis */ - 0x00F5, /* kCellLoOTilde */ - 0x00FA, /* kCellLoUAcute */ - 0x00F9, /* kCellLoUGrave */ - 0x00FB, /* kCellLoUCircumflex */ - 0x00FC, /* kCellLoUDiaeresis */ - - 0x00C6, /* kCellUpAE */ - 0x00D8, /* kCellUpOStroke */ - - 0x00E6, /* kCellLoAE */ - 0x00F8, /* kCellLoOStroke */ - 0x00BF, /* kCellInvQuestion */ - 0x00A1, /* kCellInvExclam */ - - 0x00C0, /* kCellUpAGrave */ - 0x00C3, /* kCellUpATilde */ - 0x00D5, /* kCellUpOTilde */ - 0x0152, /* kCellUpLigatureOE */ - 0x0153, /* kCellLoLigatureOE */ - - 0x00FF, /* kCellLoYDiaeresis */ - 0x0178, /* kCellUpYDiaeresis */ - - 0x00C2, /* kCellUpACircumflex */ - 0x00CA, /* kCellUpECircumflex */ - 0x00C1, /* kCellUpAAcute */ - 0x00CB, /* kCellUpEDiaeresis */ - 0x00C8, /* kCellUpEGrave */ - 0x00CD, /* kCellUpIAcute */ - 0x00CE, /* kCellUpICircumflex */ - 0x00CF, /* kCellUpIDiaeresis */ - 0x00CC, /* kCellUpIGrave */ - 0x00D3, /* kCellUpOAcute */ - 0x00D4, /* kCellUpOCircumflex */ - - 0x00D2, /* kCellUpOGrave */ - 0x00DA, /* kCellUpUAcute */ - 0x00DB, /* kCellUpUCircumflex */ - 0x00D9, /* kCellUpUGrave */ - 0x00DF, /* kCellSharpS */ - - 0x0104, /* kCellUpACedille */ - 0x0105, /* kCellLoACedille */ - 0x0106, /* kCellUpCAcute */ - 0x0107, /* kCellLoCAcute */ - 0x0118, /* kCellUpECedille */ - 0x0119, /* kCellLoECedille */ - 0x0141, /* kCellUpLBar */ - 0x0142, /* kCellLoLBar */ - 0x0143, /* kCellUpNAcute */ - 0x0144, /* kCellLoNAcute */ - 0x015A, /* kCellUpSAcute */ - 0x015B, /* kCellLoSAcute */ - 0x0179, /* kCellUpZAcute */ - 0x017A, /* kCellLoZAcute */ - 0x017B, /* kCellUpZDot */ - 0x017C, /* kCellLoZDot */ -#endif - - '\0' /* just so last above line can end in ',' */ -}; -#endif - -LOCALVAR blnr SpeedStopped = falseblnr; - -LOCALVAR blnr RunInBackground = (WantInitRunInBackground != 0); - -#if VarFullScreen -LOCALVAR blnr WantFullScreen = (WantInitFullScreen != 0); -#endif - -#if EnableMagnify -LOCALVAR blnr WantMagnify = (WantInitMagnify != 0); -#endif - -#if NeedRequestInsertDisk -LOCALVAR blnr RequestInsertDisk = falseblnr; -#endif - -#if UseControlKeys -LOCALVAR blnr ControlKeyPressed = falseblnr; -#endif - -LOCALFUNC char * GetSubstitutionStr(char x) -{ - char *s; - - switch (x) { - case 'w': - s = kStrHomePage; - break; - case 'y': - s = kStrCopyrightYear; - break; - case 'p': - s = kStrAppName; - break; - case 'v': - s = kAppVariationStr; - break; - case 'r': - s = RomFileName; - break; -#if UseControlKeys - case 'k': - if (ControlKeyPressed) { - s = kStrPressed; - } else { - s = kStrReleased; - } - break; -#endif -#if EnableMagnify - case 'g': - if (WantMagnify) { - s = kStrOn; - } else { - s = kStrOff; - } - break; -#endif -#if VarFullScreen - case 'f': - if (WantFullScreen) { - s = kStrOn; - } else { - s = kStrOff; - } - break; -#endif - case 'b': - if (RunInBackground) { - s = kStrOn; - } else { - s = kStrOff; - } - break; - case 'h': - if (SpeedStopped) { - s = kStrStoppedOn; - } else { - s = kStrStoppedOff; - } - break; -#if EnableAutoSlow - case 'l': - if (WantNotAutoSlow) { - s = kStrStoppedOff; - } else { - s = kStrStoppedOn; - } - break; -#endif - case 's': - switch (SpeedValue) { - case 0: - s = "1x"; - break; - case 1: - s = "2x"; - break; - case 2: - s = "4x"; - break; - case 3: - s = "8x"; - break; - case 4: - s = "16x"; - break; - case 5: - s = "32x"; - break; - default: - s = kStrSpeedValueAllOut; - break; - } - break; - default: - s = "???"; - break; - } - return s; -} - -#define ClStrMaxLength 512 - -LOCALPROC ClStrAppendChar(int *L0, ui3b *r, ui3b c) -{ - unsigned short L = *L0; - - if (ClStrMaxLength != L) { - r[L] = c; - L++; - *L0 = L; - } -} - -LOCALPROC ClStrAppendSubstCStr(int *L, ui3b *r, char *s) -{ - char *p = s; - char c; - ui3b x; - - while ((c = *p++) != 0) { - if (c == '^') { - if ((c = *p++) == 0) { - return; /* oops, unexpected end of string, abort */ - } else if (c == '^') { - ClStrAppendChar(L, r, c); - } else { - ClStrAppendSubstCStr(L, r, GetSubstitutionStr(c)); - } - } else if (c == ';') { - switch (*p++) { - case 'g': x = kCellCopyright; break; - case 'l': - switch (*p++) { - case 'a': x = kCellApostrophe; break; - case 'l': x = kCellEllipsis; break; - case 's': x = kCellSemicolon; break; -#if NeedIntlChars - case 'E': x = kCellUpAE; break; - case 'e': x = kCellLoAE; break; -#endif - default: return; break; - } - break; - case '[': x = kCellLeftDQuote; break; - case '{': x = kCellRightDQuote; break; - case ']': x = kCellLeftSQuote; break; - case '}': x = kCellRightSQuote; break; -#if NeedIntlChars - case '?': x = kCellInvQuestion; break; - case 'A': x = kCellUpARing; break; - case 'C': x = kCellUpCCedilla; break; - case 'O': x = kCellUpOStroke; break; - case 'Q': x = kCellUpLigatureOE; break; - case '`': - switch (*p++) { - case 'A': x = kCellUpAGrave; break; - case 'E': x = kCellUpEGrave; break; - case 'I': x = kCellUpIGrave; break; - case 'O': x = kCellUpOGrave; break; - case 'U': x = kCellUpUGrave; break; - case 'a': x = kCellLoAGrave; break; - case 'e': x = kCellLoEGrave; break; - case 'i': x = kCellLoIGrave; break; - case 'o': x = kCellLoOGrave; break; - case 'u': x = kCellLoUGrave; break; - default: return; break; - } - break; - case 'a': x = kCellLoARing; break; - case 'c': x = kCellLoCCedilla; break; - case 'd': - switch (*p++) { - case 'A': x = kCellUpACedille; break; - case 'a': x = kCellLoACedille; break; - case 'E': x = kCellUpECedille; break; - case 'e': x = kCellLoECedille; break; - case 'L': x = kCellUpLBar; break; - case 'l': x = kCellLoLBar; break; - case 'Z': x = kCellUpZDot; break; - case 'z': x = kCellLoZDot; break; - default: return; break; - } - break; - case 'e': - switch (*p++) { - case 'A': x = kCellUpAAcute; break; - case 'E': x = kCellUpEAcute; break; - case 'I': x = kCellUpIAcute; break; - case 'O': x = kCellUpOAcute; break; - case 'U': x = kCellUpUAcute; break; - case 'a': x = kCellLoAAcute; break; - case 'e': x = kCellLoEAcute; break; - case 'i': x = kCellLoIAcute; break; - case 'o': x = kCellLoOAcute; break; - case 'u': x = kCellLoUAcute; break; - - case 'C': x = kCellUpCAcute; break; - case 'c': x = kCellLoCAcute; break; - case 'N': x = kCellUpNAcute; break; - case 'n': x = kCellLoNAcute; break; - case 'S': x = kCellUpSAcute; break; - case 's': x = kCellLoSAcute; break; - case 'Z': x = kCellUpZAcute; break; - case 'z': x = kCellLoZAcute; break; - - default: return; break; - } - break; - case 'i': - switch (*p++) { - case 'A': x = kCellUpACircumflex; break; - case 'E': x = kCellUpECircumflex; break; - case 'I': x = kCellUpICircumflex; break; - case 'O': x = kCellUpOCircumflex; break; - case 'U': x = kCellUpUCircumflex; break; - case 'a': x = kCellLoACircumflex; break; - case 'e': x = kCellLoECircumflex; break; - case 'i': x = kCellLoICircumflex; break; - case 'o': x = kCellLoOCircumflex; break; - case 'u': x = kCellLoUCircumflex; break; - default: return; break; - } - break; - case 'n': - switch (*p++) { - case 'A': x = kCellUpATilde; break; - case 'N': x = kCellUpNTilde; break; - case 'O': x = kCellUpOTilde; break; - case 'a': x = kCellLoATilde; break; - case 'n': x = kCellLoNTilde; break; - case 'o': x = kCellLoOTilde; break; - default: return; break; - } - break; - case 'o': x = kCellLoOStroke; break; - case 'q': x = kCellLoLigatureOE; break; - case 's': x = kCellSharpS; break; - case 'u': - switch (*p++) { - case 'A': x = kCellUpADiaeresis; break; - case 'E': x = kCellUpEDiaeresis; break; - case 'I': x = kCellUpIDiaeresis; break; - case 'O': x = kCellUpODiaeresis; break; - case 'U': x = kCellUpUDiaeresis; break; - case 'Y': x = kCellUpYDiaeresis; break; - case 'a': x = kCellLoADiaeresis; break; - case 'e': x = kCellLoEDiaeresis; break; - case 'i': x = kCellLoIDiaeresis; break; - case 'o': x = kCellLoODiaeresis; break; - case 'u': x = kCellLoUDiaeresis; break; - case 'y': x = kCellLoYDiaeresis; break; - default: return; break; - } - break; -#endif - default: - return; - /* - oops, unexpected char, - maybe end of string, abort - */ - break; - } - ClStrAppendChar(L, r, x); - } else { - switch (c) { - case 'A': x = kCellUpA; break; - case 'B': x = kCellUpB; break; - case 'C': x = kCellUpC; break; - case 'D': x = kCellUpD; break; - case 'E': x = kCellUpE; break; - case 'F': x = kCellUpF; break; - case 'G': x = kCellUpG; break; - case 'H': x = kCellUpH; break; - case 'I': x = kCellUpI; break; - case 'J': x = kCellUpJ; break; - case 'K': x = kCellUpK; break; - case 'L': x = kCellUpL; break; - case 'M': x = kCellUpM; break; - case 'N': x = kCellUpN; break; - case 'O': x = kCellUpO; break; - case 'P': x = kCellUpP; break; - case 'Q': x = kCellUpQ; break; - case 'R': x = kCellUpR; break; - case 'S': x = kCellUpS; break; - case 'T': x = kCellUpT; break; - case 'U': x = kCellUpU; break; - case 'V': x = kCellUpV; break; - case 'W': x = kCellUpW; break; - case 'X': x = kCellUpX; break; - case 'Y': x = kCellUpY; break; - case 'Z': x = kCellUpZ; break; - case 'a': x = kCellLoA; break; - case 'b': x = kCellLoB; break; - case 'c': x = kCellLoC; break; - case 'd': x = kCellLoD; break; - case 'e': x = kCellLoE; break; - case 'f': x = kCellLoF; break; - case 'g': x = kCellLoG; break; - case 'h': x = kCellLoH; break; - case 'i': x = kCellLoI; break; - case 'j': x = kCellLoJ; break; - case 'k': x = kCellLoK; break; - case 'l': x = kCellLoL; break; - case 'm': x = kCellLoM; break; - case 'n': x = kCellLoN; break; - case 'o': x = kCellLoO; break; - case 'p': x = kCellLoP; break; - case 'q': x = kCellLoQ; break; - case 'r': x = kCellLoR; break; - case 's': x = kCellLoS; break; - case 't': x = kCellLoT; break; - case 'u': x = kCellLoU; break; - case 'v': x = kCellLoV; break; - case 'w': x = kCellLoW; break; - case 'x': x = kCellLoX; break; - case 'y': x = kCellLoY; break; - case 'z': x = kCellLoZ; break; - case '0': x = kCellDigit0; break; - case '1': x = kCellDigit1; break; - case '2': x = kCellDigit2; break; - case '3': x = kCellDigit3; break; - case '4': x = kCellDigit4; break; - case '5': x = kCellDigit5; break; - case '6': x = kCellDigit6; break; - case '7': x = kCellDigit7; break; - case '8': x = kCellDigit8; break; - case '9': x = kCellDigit9; break; - case '!': x = kCellExclamation; break; - case '&': x = kCellAmpersand; break; - case '(': x = kCellLeftParen; break; - case ')': x = kCellRightParen; break; - case ',': x = kCellComma; break; - case '-': x = kCellHyphen; break; - case '.': x = kCellPeriod; break; - case '/': x = kCellSlash; break; - case ':': x = kCellColon; break; - case ';': x = kCellSemicolon; break; - case '?': x = kCellQuestion; break; - case '_': x = kCellUnderscore; break; - default: x = kCellSpace; break; - } - ClStrAppendChar(L, r, x); - } - } -} - -LOCALPROC ClStrFromSubstCStr(int *L, ui3b *r, char *s) -{ - *L = 0; - ClStrAppendSubstCStr(L, r, s); -} +/* INTLCHAR.h Copyright (C) 2010 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* InterNaTionAL CHARacters */ /* master copy of private font data */ /* Data in commments: Mini vMac Cell name Mac Roman windows-1252 code page Unicode plain ascii ClStrAppendSubstCStr encoding HTML character entity */ LOCALVAR const ui3b CellData[] = { /* kCellUpA 101 0x41 0x0041 'A' 'A' A */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpB 102 0x42 0x0042 'B' 'B' B */ 0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x7C, 0x00, 0x00, 0x00, 0x00, /* kCellUpC 103 0x43 0x0043 'C' 'C' C */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x40, 0x40, 0x40, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpD 104 0x44 0x0044 'D' 'D' D */ 0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7C, 0x00, 0x00, 0x00, 0x00, /* kCellUpE 105 0x45 0x0045 'E' 'E' E */ 0x00, 0x00, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellUpF 106 0x46 0x0046 'F' 'F' F */ 0x00, 0x00, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* kCellUpG 107 0x47 0x0047 'G' 'G' G */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x40, 0x40, 0x4E, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpH 110 0x48 0x0048 'H' 'H' H */ 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpI 111 0x49 0x0049 'I' 'I' I */ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellUpJ 112 0x4A 0x004A 'J' 'J' J */ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpK 113 0x4B 0x004B 'K' 'K' K */ 0x00, 0x00, 0x00, 0x42, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpL 114 0x4C 0x004C 'L' 'L' L */ 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellUpM 115 0x4D 0x004D 'M' 'M' M */ 0x00, 0x00, 0x00, 0x82, 0xC6, 0xAA, 0x92, 0x82, 0x82, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00, /* kCellUpN 116 0x4E 0x004E 'N' 'N' N */ 0x00, 0x00, 0x00, 0x42, 0x42, 0x62, 0x52, 0x4A, 0x46, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpO 117 0x4F 0x004F 'O' 'O' O */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpP 120 0x50 0x0050 'P' 'P' P */ 0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x7C, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* kCellUpQ 121 0x51 0x0051 'Q' 'Q' Q */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x10, 0x0C, 0x00, 0x00, /* kCellUpR 122 0x52 0x0052 'R' 'R' R */ 0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpS 123 0x53 0x0053 'S' 'S' S */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x40, 0x40, 0x3C, 0x02, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpT 124 0x54 0x0054 'T' 'T' T */ 0x00, 0x00, 0x00, 0x7F, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellUpU 125 0x55 0x0055 'U' 'U' U */ 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpV 126 0x56 0x0056 'V' 'V' V */ 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x44, 0x48, 0x50, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, /* kCellUpW 127 0x57 0x0057 'W' 'W' W */ 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x5A, 0x66, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpX 130 0x58 0x0058 'X' 'X' X */ 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x24, 0x18, 0x24, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpY 131 0x59 0x0059 'Y' 'Y' Y */ 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellUpZ 132 0x5A 0x005A 'Z' 'Z' Z */ 0x00, 0x00, 0x00, 0x7E, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellLoA 141 0x61 0x0061 'a' 'a' a */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoB 142 0x62 0x0062 'b' 'b' b */ 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x7C, 0x00, 0x00, 0x00, 0x00, /* kCellLoC 143 0x63 0x0063 'c' 'c' c */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x40, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoD 144 0x64 0x0064 'd' 'd' d */ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x3E, 0x42, 0x42, 0x42, 0x42, 0x3E, 0x00, 0x00, 0x00, 0x00, /* kCellLoE 145 0x65 0x0065 'e' 'e' e */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoF 146 0x66 0x0066 'f' 'f' f */ 0x00, 0x00, 0x00, 0x0E, 0x10, 0x10, 0x3C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* kCellLoG 147 0x67 0x0067 'g' 'g' g */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x42, 0x42, 0x42, 0x42, 0x3E, 0x02, 0x42, 0x3C, 0x00, /* kCellLoH 150 0x68 0x0068 'h' 'h' h */ 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellLoI 151 0x69 0x0069 'i' 'i' i */ 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* kCellLoJ 152 0x6A 0x006A 'j' 'j' j */ 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x70, 0x00, /* kCellLoK 153 0x6B 0x006B 'k' 'k' k */ 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x44, 0x48, 0x70, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellLoL 154 0x6C 0x006C 'l' 'l' l */ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellLoM 155 0x6D 0x006D 'm' 'm' m */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x92, 0x92, 0x92, 0x92, 0x92, 0x00, 0x00, 0x00, 0x00, /* kCellLoN 156 0x6E 0x006E 'n' 'n' n */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellLoO 157 0x6F 0x006F 'o' 'o' o */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoP 160 0x70 0x0070 'p' 'p' p */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x7C, 0x40, 0x40, 0x00, 0x00, /* kCellLoQ 161 0x71 0x0071 'q' 'q' q */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x42, 0x42, 0x42, 0x42, 0x3E, 0x02, 0x02, 0x00, 0x00, /* kCellLoR 162 0x72 0x0072 'r' 'r' r */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5C, 0x62, 0x42, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, /* kCellLoS 163 0x73 0x0073 's' 's' s */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x3C, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoT 164 0x74 0x0074 't' 't' t */ 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x78, 0x20, 0x20, 0x20, 0x20, 0x1C, 0x00, 0x00, 0x00, 0x00, /* kCellLoU 165 0x75 0x0075 'u' 'u' u */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoV 166 0x76 0x0076 'v' 'v' v */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x44, 0x48, 0x50, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, /* kCellLoW 167 0x77 0x0077 'w' 'w' w */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x92, 0x92, 0x92, 0x92, 0x6C, 0x00, 0x00, 0x00, 0x00, /* kCellLoX 170 0x78 0x0078 'x' 'x' x */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellLoY 171 0x79 0x0079 'y' 'y' y */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3E, 0x02, 0x42, 0x3C, 0x00, /* kCellLoZ 172 0x7A 0x007A 'z' 'z' z */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x04, 0x08, 0x10, 0x20, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellDigit0 060 0x30 0x0030 '0' '0' 0 */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellDigit1 061 0x31 0x0031 '1' '1' 1 */ 0x00, 0x00, 0x00, 0x08, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellDigit2 062 0x32 0x0032 '2' '2' 2 */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellDigit3 063 0x33 0x0033 '3' '3' 3 */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x02, 0x0C, 0x02, 0x02, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellDigit4 064 0x34 0x0034 '4' '4' 4 */ 0x00, 0x00, 0x00, 0x04, 0x0C, 0x14, 0x24, 0x7E, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, /* kCellDigit5 065 0x35 0x0035 '5' '5' 5 */ 0x00, 0x00, 0x00, 0x7E, 0x40, 0x40, 0x7C, 0x02, 0x02, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellDigit6 066 0x36 0x0036 '6' '6' 6 */ 0x00, 0x00, 0x00, 0x1C, 0x20, 0x40, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellDigit7 067 0x37 0x0037 '7' '7' 7 */ 0x00, 0x00, 0x00, 0x7E, 0x02, 0x02, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellDigit8 070 0x38 0x0038 '8' '8' 8 */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellDigit9 071 0x39 0x0039 '9' '9' 9 */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3E, 0x02, 0x04, 0x38, 0x00, 0x00, 0x00, 0x00, /* kCellExclamation 041 0x21 0x0021 '!' '!' ! */ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellAmpersand 046 0x26 0x0026 '&' '&' amp */ 0x00, 0x00, 0x00, 0x30, 0x48, 0x48, 0x50, 0x20, 0x50, 0x4A, 0x44, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellApostrophe 047 0x27 0x0027 '\047' ';la' apos */ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellLeftParen 050 0x28 0x0028 '(' '(' ( */ 0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, /* kCellRightParen 051 0x29 0x0029 ')' ')' ) */ 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, /* kCellComma 054 0x2C 0x002C ',' ',' , */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x10, 0x00, 0x00, /* kCellHyphen 055 0x2D 0x002D '-' '-' - */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellPeriod 056 0x2E 0x002E '.' '.' . */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellSlash 057 0x2F 0x002F '/' '/' / */ 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x00, 0x00, 0x00, /* kCellColon 072 0x3A 0x003A ':' ':' : */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellSemicolon 073 0x3B 0x003B ';' ';ls' #59 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08, 0x10, 0x00, 0x00, /* kCellQuestion 077 0x3F 0x003F '?' '?' ? */ 0x00, 0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* kCellEllipsis 311 0x85 0x2026 '_' ';ll' #8230 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, /* kCellUnderscore 137 0x5F 0x005F '_' '_' _ */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, /* kCellLeftDQuote 322 0x93 0x201C '"' ';[' ldquo */ 0x00, 0x00, 0x00, 0x24, 0x48, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellRightDQuote 323 0x94 0x201D '"' ';{' rdquo */ 0x00, 0x00, 0x00, 0x36, 0x12, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellLeftSQuote 324 0x91 0x2018 '\047' ';]' lsquo */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellRightSQuote 325 0x92 0x2019 '\047' ';}' rsquo */ 0x00, 0x00, 0x00, 0x18, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellCopyright 251 0xA9 0x00A9 'c' ';g' copy */ 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x9A, 0xA2, 0xA2, 0x9A, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, /* kCellSpace 040 0x20 0x0020 '\040' '' #32 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, #if NeedIntlChars /* kCellUpADiaeresis 200 0xC4 0x00C4 'A' ';uA' Auml */ 0x00, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpARing 201 0xC5 0x00C5 'A' ';A' Aring */ 0x3C, 0x42, 0x42, 0x3C, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpCCedilla 202 0xC7 0x00C7 'C' ';C' Ccedil */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x40, 0x40, 0x40, 0x40, 0x42, 0x3C, 0x08, 0x08, 0x10, 0x00, /* kCellUpEAcute 203 0xC9 0x00C9 'E' ';eE' Eacute */ 0x08, 0x10, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellUpNTilde 204 0xD1 0x00D1 'N' ';nN' Ntilde */ 0x32, 0x4C, 0x00, 0x42, 0x42, 0x62, 0x52, 0x4A, 0x46, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpODiaeresis 205 0xD6 0x00D6 'O' ';uO' Ouml */ 0x00, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpUDiaeresis 206 0xDC 0x00DC 'U' ';uU' Uuml */ 0x00, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoAAcute 207 0xE1 0x00E1 'a' ';ea' aacute */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3E, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoAGrave 210 0xE0 0x00E0 'a' ';`a' agrave */ 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3E, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoACircumflex 211 0xE2 0x00E2 'a' ';ia' acirc */ 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3E, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoADiaeresis 212 0xE4 0x00E4 'a' ';ua' auml */ 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x3E, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoATilde 213 0xE3 0x00E3 'a' ';na' atilde */ 0x00, 0x00, 0x00, 0x32, 0x4C, 0x00, 0x3E, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoARing 214 0xE5 0x00E5 'a' ';a' aring */ 0x00, 0x00, 0x18, 0x24, 0x24, 0x18, 0x3E, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoCCedilla 215 0xE7 0x00E7 'c' ';c' ccedil */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x40, 0x40, 0x42, 0x3C, 0x08, 0x08, 0x10, 0x00, /* kCellLoEAcute 216 0xE9 0x00E9 'e' ';ee' eacute */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3C, 0x42, 0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoEGrave 217 0xE8 0x00E8 'e' ';`e' egrave */ 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3C, 0x42, 0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoECircumflex 220 0xEA 0x00EA 'e' ';ie' ecirc */ 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3C, 0x42, 0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoEDiaeresis 221 0xEB 0x00EB 'e' ';ue' euml */ 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x3C, 0x42, 0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoIAcute 222 0xED 0x00ED 'i' ';ei' iacute */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* kCellLoIGrave 223 0xEC 0x00EC 'i' ';`i' igrave */ 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* kCellLoICircumflex 224 0xEE 0x00EE 'i' ';ii' icirc */ 0x00, 0x00, 0x00, 0x10, 0x28, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* kCellLoIDiaeresis 225 0xEF 0x00EF 'i' ';ui' iuml */ 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* kCellLoNTilde 226 0xF1 0x00F1 'n' ';nn' ntilde */ 0x00, 0x00, 0x00, 0x32, 0x4C, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellLoOAcute 227 0xF3 0x00F3 'o' ';eo' oacute */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoOGrave 230 0xF2 0x00F2 'o' ';`o' ograve */ 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoOCircumflex 231 0xF4 0x00F4 'o' ';io' ocirc */ 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoODiaeresis 232 0xF6 0x00F6 'o' ';uo' ouml */ 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoOTilde 233 0xF5 0x00F5 'o' ';no' otilde */ 0x00, 0x00, 0x00, 0x32, 0x4C, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoUAcute 234 0xFA 0x00FA 'u' ';eu' uacute */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoUGrave 235 0xF9 0x00F9 'u' ';`u' ugrave */ 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoUCircumflex 236 0xFB 0x00FB 'u' ';iu' ucirc */ 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellLoUDiaeresis 237 0xFC 0x00FC 'u' ';uu' uuml */ 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00, /* kCellUpAE 256 0xC6 0x00C6 '?' ';lE' AElig */ 0x00, 0x00, 0x00, 0x3E, 0x48, 0x48, 0x48, 0x7C, 0x48, 0x48, 0x48, 0x4E, 0x00, 0x00, 0x00, 0x00, /* kCellUpOStroke 257 0xD8 0x00D8 'O' ';O' Oslash */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x46, 0x5A, 0x62, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoAE 276 0xE6 0x00E6 '?' ';le' aelig */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x52, 0x5E, 0x50, 0x52, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoOStroke 277 0xF8 0x00F8 'o' ';o' oslash */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x46, 0x5A, 0x62, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellInvQuestion 300 0xBF 0x00BF '?' ';?' iquest */ 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x20, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, /* kCellInvExclam 301 0xA1 0x00A1 '!' ';1' iexcl */ 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellUpAGrave 313 0xC0 0x00C0 'A' ';`A' Agrave */ 0x10, 0x08, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpATilde 314 0xC3 0x00C3 'A' ';nA' Atilde */ 0x32, 0x4C, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpOTilde 315 0xD5 0x00D5 'O' ';nO' Otilde */ 0x32, 0x4C, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpLigatureOE 316 0x8C 0x0152 '?' ';Q' OElig */ 0x00, 0x00, 0x00, 0x3E, 0x48, 0x48, 0x48, 0x4E, 0x48, 0x48, 0x48, 0x3E, 0x00, 0x00, 0x00, 0x00, /* kCellLoLigatureOE 317 0x9C 0x0153 '?' ';q' oelig */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x52, 0x5E, 0x50, 0x52, 0x2C, 0x00, 0x00, 0x00, 0x00, /* kCellLoYDiaeresis 330 0xFF 0x00FF 'y' ';uy' yuml */ 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3E, 0x02, 0x42, 0x3C, 0x00, /* kCellUpYDiaeresis 331 0x9F 0x0178 'Y' ';uY' Yuml */ 0x00, 0x14, 0x00, 0x22, 0x22, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellUpACircumflex 345 0xC2 0x00C2 'A' ';iA' Acirc */ 0x18, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpECircumflex 346 0xCA 0x00CA 'E' ';iE' Ecirc */ 0x18, 0x24, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellUpAAcute 347 0xC1 0x00C1 'A' ';eA' Aacute */ 0x08, 0x10, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpEDiaeresis 350 0xCB 0x00CB 'E' ';uE' Euml */ 0x00, 0x24, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellUpEGrave 351 0xC8 0x00C8 'E' ';`E' Egrave */ 0x10, 0x08, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellUpIAcute 352 0xCD 0x00CD 'A' ';eI' Iacute */ 0x04, 0x08, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x00, /* kCellUpICircumflex 353 0xCE 0x00CE 'I' ';iI' Icirc */ 0x08, 0x14, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x00, /* kCellUpIDiaeresis 354 0xCF 0x00CF 'I' ';uI' Iuml */ 0x00, 0x14, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x00, /* kCellUpIGrave 355 0xCC 0x00CC 'I' ';`I' Igrave */ 0x10, 0x08, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x00, /* kCellUpOAcute 356 0xD3 0x00D3 'O' ';eO' Oacute */ 0x08, 0x10, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpOCircumflex 357 0xD4 0x00D4 'O' ';iO' Ocirc */ 0x18, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpOGrave 361 0xD2 0x00D2 'O' ';`O' Ograve */ 0x10, 0x08, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpUAcute 362 0xDA 0x00DA 'U' ';eU' Uacute */ 0x08, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpUCircumflex 363 0xDB 0x00DB 'U' ';iU' Ucirc */ 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpUGrave 364 0xD9 0x00D9 'U' ';`U' Ugrave */ 0x10, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellSharpS 247 0xDF 0x00DF 'B' ';s' szlig */ 0x00, 0x00, 0x00, 0x1C, 0x22, 0x42, 0x44, 0x44, 0x42, 0x42, 0x42, 0x5C, 0x40, 0x00, 0x00, 0x00, /* kCellUpACedille 260 ? 0x0104 'A' ';dA' #260 */ 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42, 0x04, 0x04, 0x02, 0x00, /* kCellLoACedille 261 ? 0x0105 'a' ';da' #261 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x04, 0x04, 0x02, 0x00, /* kCellUpCAcute 262 ? 0x0106 'C' ';eC' #262 */ 0x08, 0x10, 0x00, 0x3C, 0x42, 0x42, 0x40, 0x40, 0x40, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoCAcute 263 ? 0x0107 'c' ';ec' #263 */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3C, 0x42, 0x40, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpECedille 264 ? 0x0118 'E' ';dE' #280 */ 0x00, 0x00, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x7E, 0x04, 0x04, 0x02, 0x00, /* kCellLoECedille 265 ? 0x0119 'e' ';de' #281 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x7E, 0x40, 0x42, 0x3C, 0x08, 0x08, 0x04, 0x00, /* kCellUpLBar 266 ? 0x0141 'L' ';dL' #321 */ 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x60, 0x40, 0xC0, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellLoLBar 267 ? 0x0142 'l' ';dl' #322 */ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x0C, 0x08, 0x18, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* kCellUpNAcute 270 ? 0x0143 'N' ';eN' #323 */ 0x08, 0x10, 0x00, 0x42, 0x42, 0x62, 0x52, 0x4A, 0x46, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellLoNAcute 271 ? 0x0144 'n' ';en' #324 */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, /* kCellUpSAcute 272 ? 0x015A 'S' ';eS' #346 */ 0x08, 0x10, 0x00, 0x3C, 0x42, 0x40, 0x40, 0x3C, 0x02, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellLoSAcute 273 ? 0x015B 's' ';es' #347 */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3C, 0x42, 0x3C, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, /* kCellUpZAcute 274 ? 0x0179 'Z' ';eZ' #377 */ 0x08, 0x10, 0x00, 0x7E, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellLoZAcute 275 ? 0x017A 'z' ';ez' #378 */ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x7E, 0x04, 0x08, 0x10, 0x20, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellUpZDot 276 ? 0x017B 'Z' ';dZ' #379 */ 0x10, 0x00, 0x00, 0x7E, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00, /* kCellLoZDot 277 ? 0x017C 'z' ';dz' #380 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x7E, 0x04, 0x08, 0x10, 0x20, 0x7E, 0x00, 0x00, 0x00, 0x00, #endif /* kCellUpperLeft */ 0xFF, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* kCellUpperMiddle */ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellMiddleLeft */ 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* kCellMiddleLeft */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* kCellMiddleRight */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* kCellLowerLeft */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFF, /* kCellLowerMiddle */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, /* kCellLowerRight */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, /* kCellGraySep */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellIcon00 */ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, /* kCellIcon01 */ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x18, 0x18, /* kCellIcon02 */ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x18, 0x30, /* kCellIcon03 */ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0x90, 0x90, 0x90, /* kCellIcon10 */ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* kCellIcon11 */ 0x18, 0x18, 0x19, 0x1B, 0x1E, 0x1C, 0x18, 0x10, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellIcon12 */ 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, /* kCellIcon13 */ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, /* kCellIcon20 */ 0x08, 0x08, 0x08, 0x07, 0x04, 0x04, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellIcon21 */ 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellIcon22 */ 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* kCellIcon23 */ 0x10, 0x10, 0x10, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, #if EnableAltKeysMode /* kInsertText00 */ 0xFF, 0x80, 0x80, 0x80, 0x80, 0x83, 0x80, 0x80, 0x80, 0x80, 0x83, 0x80, 0x80, 0x80, 0x80, 0xFF, /* kInsertText01 */ 0xFF, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x19, 0x1B, 0x1E, 0x1C, 0x18, 0x10, 0x00, 0x00, 0xFF, /* kInsertText02 */ 0xFF, 0x00, 0x00, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, /* kInsertText03 */ 0xFF, 0x01, 0x01, 0x01, 0x01, 0xC1, 0x01, 0x01, 0x01, 0x01, 0xC1, 0x01, 0x01, 0x01, 0x01, 0xFF, /* kInsertText04 */ 0xFF, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0x00, 0xFF, #endif #if EnableDemoMsg /* kCellDemo0 */ 0xFF, 0x80, 0x80, 0x80, 0x80, 0x83, 0x80, 0x80, 0x80, 0x80, 0x83, 0x80, 0x80, 0x80, 0x80, 0xFF, /* kCellDemo1 */ 0xFF, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7C, 0x00, 0x00, 0x00, 0xFF, /* kCellDemo2 */ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0xFF, /* kCellDemo3 */ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x92, 0x92, 0x92, 0x92, 0x92, 0x00, 0x00, 0x00, 0xFF, /* kCellDemo4 */ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0xFF, /* kCellDemo5 */ 0xFF, 0x01, 0x01, 0x01, 0x01, 0xC1, 0x01, 0x01, 0x01, 0x01, 0xC1, 0x01, 0x01, 0x01, 0x01, 0xFF, /* kCellDemo6 */ 0xFF, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0x00, 0xFF, /* kCellDemo7 */ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, #endif 0x00 /* just so last above line can end in ',' */ }; enum { kCellUpA, kCellUpB, kCellUpC, kCellUpD, kCellUpE, kCellUpF, kCellUpG, kCellUpH, kCellUpI, kCellUpJ, kCellUpK, kCellUpL, kCellUpM, kCellUpN, kCellUpO, kCellUpP, kCellUpQ, kCellUpR, kCellUpS, kCellUpT, kCellUpU, kCellUpV, kCellUpW, kCellUpX, kCellUpY, kCellUpZ, kCellLoA, kCellLoB, kCellLoC, kCellLoD, kCellLoE, kCellLoF, kCellLoG, kCellLoH, kCellLoI, kCellLoJ, kCellLoK, kCellLoL, kCellLoM, kCellLoN, kCellLoO, kCellLoP, kCellLoQ, kCellLoR, kCellLoS, kCellLoT, kCellLoU, kCellLoV, kCellLoW, kCellLoX, kCellLoY, kCellLoZ, kCellDigit0, kCellDigit1, kCellDigit2, kCellDigit3, kCellDigit4, kCellDigit5, kCellDigit6, kCellDigit7, kCellDigit8, kCellDigit9, kCellExclamation, kCellAmpersand, kCellApostrophe, kCellLeftParen, kCellRightParen, kCellComma, kCellHyphen, kCellPeriod, kCellSlash, kCellColon, kCellSemicolon, kCellQuestion, kCellEllipsis, kCellUnderscore, kCellLeftDQuote, kCellRightDQuote, kCellLeftSQuote, kCellRightSQuote, kCellCopyright, kCellSpace, #if NeedIntlChars kCellUpADiaeresis, kCellUpARing, kCellUpCCedilla, kCellUpEAcute, kCellUpNTilde, kCellUpODiaeresis, kCellUpUDiaeresis, kCellLoAAcute, kCellLoAGrave, kCellLoACircumflex, kCellLoADiaeresis, kCellLoATilde, kCellLoARing, kCellLoCCedilla, kCellLoEAcute, kCellLoEGrave, kCellLoECircumflex, kCellLoEDiaeresis, kCellLoIAcute, kCellLoIGrave, kCellLoICircumflex, kCellLoIDiaeresis, kCellLoNTilde, kCellLoOAcute, kCellLoOGrave, kCellLoOCircumflex, kCellLoODiaeresis, kCellLoOTilde, kCellLoUAcute, kCellLoUGrave, kCellLoUCircumflex, kCellLoUDiaeresis, kCellUpAE, kCellUpOStroke, kCellLoAE, kCellLoOStroke, kCellInvQuestion, kCellInvExclam, kCellUpAGrave, kCellUpATilde, kCellUpOTilde, kCellUpLigatureOE, kCellLoLigatureOE, kCellLoYDiaeresis, kCellUpYDiaeresis, kCellUpACircumflex, kCellUpECircumflex, kCellUpAAcute, kCellUpEDiaeresis, kCellUpEGrave, kCellUpIAcute, kCellUpICircumflex, kCellUpIDiaeresis, kCellUpIGrave, kCellUpOAcute, kCellUpOCircumflex, kCellUpOGrave, kCellUpUAcute, kCellUpUCircumflex, kCellUpUGrave, kCellSharpS, kCellUpACedille, kCellLoACedille, kCellUpCAcute, kCellLoCAcute, kCellUpECedille, kCellLoECedille, kCellUpLBar, kCellLoLBar, kCellUpNAcute, kCellLoNAcute, kCellUpSAcute, kCellLoSAcute, kCellUpZAcute, kCellLoZAcute, kCellUpZDot, kCellLoZDot, #endif kCellUpperLeft, kCellUpperMiddle, kCellUpperRight, kCellMiddleLeft, kCellMiddleRight, kCellLowerLeft, kCellLowerMiddle, kCellLowerRight, kCellGraySep, kCellIcon00, kCellIcon01, kCellIcon02, kCellIcon03, kCellIcon10, kCellIcon11, kCellIcon12, kCellIcon13, kCellIcon20, kCellIcon21, kCellIcon22, kCellIcon23, #if EnableAltKeysMode kInsertText00, kInsertText01, kInsertText02, kInsertText03, kInsertText04, #endif #if EnableDemoMsg kCellDemo0, kCellDemo1, kCellDemo2, kCellDemo3, kCellDemo4, kCellDemo5, kCellDemo6, kCellDemo7, #endif kNumCells }; #if UseActvCode && 0 #define UseActvFile 1 #else #define UseActvFile 0 #endif #ifndef NeedCell2MacAsciiMap #if UseActvCode || EnableDemoMsg #define NeedCell2MacAsciiMap 1 #else #define NeedCell2MacAsciiMap 0 #endif #endif #if NeedCell2MacAsciiMap /* Mac Roman character set */ LOCALVAR const char Cell2MacAsciiMap[] = { '\101', /* kCellUpA */ '\102', /* kCellUpB */ '\103', /* kCellUpC */ '\104', /* kCellUpD */ '\105', /* kCellUpE */ '\106', /* kCellUpF */ '\107', /* kCellUpG */ '\110', /* kCellUpH */ '\111', /* kCellUpI */ '\112', /* kCellUpJ */ '\113', /* kCellUpK */ '\114', /* kCellUpL */ '\115', /* kCellUpM */ '\116', /* kCellUpN */ '\117', /* kCellUpO */ '\120', /* kCellUpP */ '\121', /* kCellUpQ */ '\122', /* kCellUpR */ '\123', /* kCellUpS */ '\124', /* kCellUpT */ '\125', /* kCellUpU */ '\126', /* kCellUpV */ '\127', /* kCellUpW */ '\130', /* kCellUpX */ '\131', /* kCellUpY */ '\132', /* kCellUpZ */ '\141', /* kCellLoA */ '\142', /* kCellLoB */ '\143', /* kCellLoC */ '\144', /* kCellLoD */ '\145', /* kCellLoE */ '\146', /* kCellLoF */ '\147', /* kCellLoG */ '\150', /* kCellLoH */ '\151', /* kCellLoI */ '\152', /* kCellLoJ */ '\153', /* kCellLoK */ '\154', /* kCellLoL */ '\155', /* kCellLoM */ '\156', /* kCellLoN */ '\157', /* kCellLoO */ '\160', /* kCellLoP */ '\161', /* kCellLoQ */ '\162', /* kCellLoR */ '\163', /* kCellLoS */ '\164', /* kCellLoT */ '\165', /* kCellLoU */ '\166', /* kCellLoV */ '\167', /* kCellLoW */ '\170', /* kCellLoX */ '\171', /* kCellLoY */ '\172', /* kCellLoZ */ '\060', /* kCellDigit0 */ '\061', /* kCellDigit1 */ '\062', /* kCellDigit2 */ '\063', /* kCellDigit3 */ '\064', /* kCellDigit4 */ '\065', /* kCellDigit5 */ '\066', /* kCellDigit6 */ '\067', /* kCellDigit7 */ '\070', /* kCellDigit8 */ '\071', /* kCellDigit9 */ '\041', /* kCellExclamation */ '\046', /* kCellAmpersand */ '\047', /* kCellApostrophe */ '\050', /* kCellLeftParen */ '\051', /* kCellRightParen */ '\054', /* kCellComma */ '\055', /* kCellHyphen */ '\056', /* kCellPeriod */ '\057', /* kCellSlash */ '\072', /* kCellColon */ '\073', /* kCellSemicolon */ '\077', /* kCellQuestion */ '\311', /* kCellEllipsis */ '\137', /* kCellUnderscore */ '\322', /* kCellLeftDQuote */ '\323', /* kCellRightDQuote */ '\324', /* kCellLeftSQuote */ '\325', /* kCellRightSQuote */ '\251', /* kCellCopyright */ '\040', /* kCellSpace */ #if NeedIntlChars '\200', /* kCellUpADiaeresis */ '\201', /* kCellUpARing */ '\202', /* kCellUpCCedilla */ '\203', /* kCellUpEAcute */ '\204', /* kCellUpNTilde */ '\205', /* kCellUpODiaeresis */ '\206', /* kCellUpUDiaeresis */ '\207', /* kCellLoAAcute */ '\210', /* kCellLoAGrave */ '\211', /* kCellLoACircumflex */ '\212', /* kCellLoADiaeresis */ '\213', /* kCellLoATilde */ '\214', /* kCellLoARing */ '\215', /* kCellLoCCedilla */ '\216', /* kCellLoEAcute */ '\217', /* kCellLoEGrave */ '\220', /* kCellLoECircumflex */ '\221', /* kCellLoEDiaeresis */ '\222', /* kCellLoIAcute */ '\223', /* kCellLoIGrave */ '\224', /* kCellLoICircumflex */ '\225', /* kCellLoIDiaeresis */ '\226', /* kCellLoNTilde */ '\227', /* kCellLoOAcute */ '\230', /* kCellLoOGrave */ '\231', /* kCellLoOCircumflex */ '\232', /* kCellLoODiaeresis */ '\233', /* kCellLoOTilde */ '\234', /* kCellLoUAcute */ '\235', /* kCellLoUGrave */ '\236', /* kCellLoUCircumflex */ '\237', /* kCellLoUDiaeresis */ '\256', /* kCellUpAE */ '\257', /* kCellUpOStroke */ '\276', /* kCellLoAE */ '\277', /* kCellLoOStroke */ '\300', /* kCellInvQuestion */ '\301', /* kCellInvExclam */ '\313', /* kCellUpAGrave */ '\314', /* kCellUpATilde */ '\315', /* kCellUpOTilde */ '\316', /* kCellUpLigatureOE */ '\317', /* kCellLoLigatureOE */ '\330', /* kCellLoYDiaeresis */ '\331', /* kCellUpYDiaeresis */ '\345', /* kCellUpACircumflex */ '\346', /* kCellUpECircumflex */ '\347', /* kCellUpAAcute */ '\350', /* kCellUpEDiaeresis */ '\351', /* kCellUpEGrave */ '\352', /* kCellUpIAcute */ '\353', /* kCellUpICircumflex */ '\354', /* kCellUpIDiaeresis */ '\355', /* kCellUpIGrave */ '\356', /* kCellUpOAcute */ '\357', /* kCellUpOCircumflex */ '\361', /* kCellUpOGrave */ '\362', /* kCellUpUAcute */ '\363', /* kCellUpUCircumflex */ '\364', /* kCellUpUGrave */ '\247', /* kCellSharpS */ '\260', /* kCellUpACedille */ '\261', /* kCellLoACedille */ '\262', /* kCellUpCAcute */ '\263', /* kCellLoCAcute */ '\264', /* kCellUpECedille */ '\265', /* kCellLoECedille */ '\266', /* kCellUpLBar */ '\267', /* kCellLoLBar */ '\270', /* kCellUpNAcute */ '\271', /* kCellLoNAcute */ '\272', /* kCellUpSAcute */ '\273', /* kCellLoSAcute */ '\274', /* kCellUpZAcute */ '\275', /* kCellLoZAcute */ '\276', /* kCellUpZDot */ '\277', /* kCellLoZDot */ #endif '\0' /* just so last above line can end in ',' */ }; #endif #ifndef NeedCell2WinAsciiMap #define NeedCell2WinAsciiMap 0 #endif #if NeedCell2WinAsciiMap /* Windows character set (windows-1252 code page) */ LOCALVAR const ui3b Cell2WinAsciiMap[] = { 0x41, /* kCellUpA */ 0x42, /* kCellUpB */ 0x43, /* kCellUpC */ 0x44, /* kCellUpD */ 0x45, /* kCellUpE */ 0x46, /* kCellUpF */ 0x47, /* kCellUpG */ 0x48, /* kCellUpH */ 0x49, /* kCellUpI */ 0x4A, /* kCellUpJ */ 0x4B, /* kCellUpK */ 0x4C, /* kCellUpL */ 0x4D, /* kCellUpM */ 0x4E, /* kCellUpN */ 0x4F, /* kCellUpO */ 0x50, /* kCellUpP */ 0x51, /* kCellUpQ */ 0x52, /* kCellUpR */ 0x53, /* kCellUpS */ 0x54, /* kCellUpT */ 0x55, /* kCellUpU */ 0x56, /* kCellUpV */ 0x57, /* kCellUpW */ 0x58, /* kCellUpX */ 0x59, /* kCellUpY */ 0x5A, /* kCellUpZ */ 0x61, /* kCellLoA */ 0x62, /* kCellLoB */ 0x63, /* kCellLoC */ 0x64, /* kCellLoD */ 0x65, /* kCellLoE */ 0x66, /* kCellLoF */ 0x67, /* kCellLoG */ 0x68, /* kCellLoH */ 0x69, /* kCellLoI */ 0x6A, /* kCellLoJ */ 0x6B, /* kCellLoK */ 0x6C, /* kCellLoL */ 0x6D, /* kCellLoM */ 0x6E, /* kCellLoN */ 0x6F, /* kCellLoO */ 0x70, /* kCellLoP */ 0x71, /* kCellLoQ */ 0x72, /* kCellLoR */ 0x73, /* kCellLoS */ 0x74, /* kCellLoT */ 0x75, /* kCellLoU */ 0x76, /* kCellLoV */ 0x77, /* kCellLoW */ 0x78, /* kCellLoX */ 0x79, /* kCellLoY */ 0x7A, /* kCellLoZ */ 0x30, /* kCellDigit0 */ 0x31, /* kCellDigit1 */ 0x32, /* kCellDigit2 */ 0x33, /* kCellDigit3 */ 0x34, /* kCellDigit4 */ 0x35, /* kCellDigit5 */ 0x36, /* kCellDigit6 */ 0x37, /* kCellDigit7 */ 0x38, /* kCellDigit8 */ 0x39, /* kCellDigit9 */ 0x21, /* kCellExclamation */ 0x26, /* kCellAmpersand */ 0x27, /* kCellApostrophe */ 0x28, /* kCellLeftParen */ 0x29, /* kCellRightParen */ 0x2C, /* kCellComma */ 0x2D, /* kCellHyphen */ 0x2E, /* kCellPeriod */ 0x2F, /* kCellSlash */ 0x3A, /* kCellColon */ 0x3B, /* kCellSemicolon */ 0x3F, /* kCellQuestion */ 0x85, /* kCellEllipsis */ 0x5F, /* kCellUnderscore */ 0x93, /* kCellLeftDQuote */ 0x94, /* kCellRightDQuote */ 0x91, /* kCellLeftSQuote */ 0x92, /* kCellRightSQuote */ 0xA9, /* kCellCopyright */ 0x20, /* kCellSpace */ #if NeedIntlChars 0xC4, /* kCellUpADiaeresis */ 0xC5, /* kCellUpARing */ 0xC7, /* kCellUpCCedilla */ 0xC9, /* kCellUpEAcute */ 0xD1, /* kCellUpNTilde */ 0xD6, /* kCellUpODiaeresis */ 0xDC, /* kCellUpUDiaeresis */ 0xE1, /* kCellLoAAcute */ 0xE0, /* kCellLoAGrave */ 0xE2, /* kCellLoACircumflex */ 0xE4, /* kCellLoADiaeresis */ 0xE3, /* kCellLoATilde */ 0xE5, /* kCellLoARing */ 0xE7, /* kCellLoCCedilla */ 0xE9, /* kCellLoEAcute */ 0xE8, /* kCellLoEGrave */ 0xEA, /* kCellLoECircumflex */ 0xEB, /* kCellLoEDiaeresis */ 0xED, /* kCellLoIAcute */ 0xEC, /* kCellLoIGrave */ 0xEE, /* kCellLoICircumflex */ 0xEF, /* kCellLoIDiaeresis */ 0xF1, /* kCellLoNTilde */ 0xF3, /* kCellLoOAcute */ 0xF2, /* kCellLoOGrave */ 0xF4, /* kCellLoOCircumflex */ 0xF6, /* kCellLoODiaeresis */ 0xF5, /* kCellLoOTilde */ 0xFA, /* kCellLoUAcute */ 0xF9, /* kCellLoUGrave */ 0xFB, /* kCellLoUCircumflex */ 0xFC, /* kCellLoUDiaeresis */ 0xC6, /* kCellUpAE */ 0xD8, /* kCellUpOStroke */ 0xE6, /* kCellLoAE */ 0xF8, /* kCellLoOStroke */ 0xBF, /* kCellInvQuestion */ 0xA1, /* kCellInvExclam */ 0xC0, /* kCellUpAGrave */ 0xC3, /* kCellUpATilde */ 0xD5, /* kCellUpOTilde */ 0x8C, /* kCellUpLigatureOE */ 0x9C, /* kCellLoLigatureOE */ 0xFF, /* kCellLoYDiaeresis */ 0x9F, /* kCellUpYDiaeresis */ 0xC2, /* kCellUpACircumflex */ 0xCA, /* kCellUpECircumflex */ 0xC1, /* kCellUpAAcute */ 0xCB, /* kCellUpEDiaeresis */ 0xC8, /* kCellUpEGrave */ 0xCD, /* kCellUpIAcute */ 0xCE, /* kCellUpICircumflex */ 0xCF, /* kCellUpIDiaeresis */ 0xCC, /* kCellUpIGrave */ 0xD3, /* kCellUpOAcute */ 0xD4, /* kCellUpOCircumflex */ 0xD2, /* kCellUpOGrave */ 0xDA, /* kCellUpUAcute */ 0xDB, /* kCellUpUCircumflex */ 0xD9, /* kCellUpUGrave */ 0xDF, /* kCellSharpS */ 0x41, /* kCellUpACedille */ 0x61, /* kCellLoACedille */ 0x43, /* kCellUpCAcute */ 0x63, /* kCellLoCAcute */ 0x45, /* kCellUpECedille */ 0x65, /* kCellLoECedille */ 0x4C, /* kCellUpLBar */ 0x6C, /* kCellLoLBar */ 0x4E, /* kCellUpNAcute */ 0x6E, /* kCellLoNAcute */ 0x53, /* kCellUpSAcute */ 0x73, /* kCellLoSAcute */ 0x5A, /* kCellUpZAcute */ 0x7A, /* kCellLoZAcute */ 0x5A, /* kCellUpZDot */ 0x7A, /* kCellLoZDot */ #endif '\0' /* just so last above line can end in ',' */ }; #endif #ifndef NeedCell2PlainAsciiMap #define NeedCell2PlainAsciiMap 0 #endif #if NeedCell2PlainAsciiMap /* Plain ascii - remove accents when possible */ LOCALVAR const char Cell2PlainAsciiMap[] = { 'A', /* kCellUpA */ 'B', /* kCellUpB */ 'C', /* kCellUpC */ 'D', /* kCellUpD */ 'E', /* kCellUpE */ 'F', /* kCellUpF */ 'G', /* kCellUpG */ 'H', /* kCellUpH */ 'I', /* kCellUpI */ 'J', /* kCellUpJ */ 'K', /* kCellUpK */ 'L', /* kCellUpL */ 'M', /* kCellUpM */ 'N', /* kCellUpN */ 'O', /* kCellUpO */ 'P', /* kCellUpP */ 'Q', /* kCellUpQ */ 'R', /* kCellUpR */ 'S', /* kCellUpS */ 'T', /* kCellUpT */ 'U', /* kCellUpU */ 'V', /* kCellUpV */ 'W', /* kCellUpW */ 'X', /* kCellUpX */ 'Y', /* kCellUpY */ 'Z', /* kCellUpZ */ 'a', /* kCellLoA */ 'b', /* kCellLoB */ 'c', /* kCellLoC */ 'd', /* kCellLoD */ 'e', /* kCellLoE */ 'f', /* kCellLoF */ 'g', /* kCellLoG */ 'h', /* kCellLoH */ 'i', /* kCellLoI */ 'j', /* kCellLoJ */ 'k', /* kCellLoK */ 'l', /* kCellLoL */ 'm', /* kCellLoM */ 'n', /* kCellLoN */ 'o', /* kCellLoO */ 'p', /* kCellLoP */ 'q', /* kCellLoQ */ 'r', /* kCellLoR */ 's', /* kCellLoS */ 't', /* kCellLoT */ 'u', /* kCellLoU */ 'v', /* kCellLoV */ 'w', /* kCellLoW */ 'x', /* kCellLoX */ 'y', /* kCellLoY */ 'z', /* kCellLoZ */ '0', /* kCellDigit0 */ '1', /* kCellDigit1 */ '2', /* kCellDigit2 */ '3', /* kCellDigit3 */ '4', /* kCellDigit4 */ '5', /* kCellDigit5 */ '6', /* kCellDigit6 */ '7', /* kCellDigit7 */ '8', /* kCellDigit8 */ '9', /* kCellDigit9 */ '!', /* kCellExclamation */ '&', /* kCellAmpersand */ '\047', /* kCellApostrophe */ '(', /* kCellLeftParen */ ')', /* kCellRightParen */ ',', /* kCellComma */ '-', /* kCellHyphen */ '.', /* kCellPeriod */ '/', /* kCellSlash */ ':', /* kCellColon */ ';', /* kCellSemicolon */ '?', /* kCellQuestion */ '_', /* kCellEllipsis */ '_', /* kCellUnderscore */ '"', /* kCellLeftDQuote */ '"', /* kCellRightDQuote */ '\047', /* kCellLeftSQuote */ '\047', /* kCellRightSQuote */ 'c', /* kCellCopyright */ ' ', /* kCellSpace */ #if NeedIntlChars 'A', /* kCellUpADiaeresis */ 'A', /* kCellUpARing */ 'C', /* kCellUpCCedilla */ 'E', /* kCellUpEAcute */ 'N', /* kCellUpNTilde */ 'O', /* kCellUpODiaeresis */ 'U', /* kCellUpUDiaeresis */ 'a', /* kCellLoAAcute */ 'a', /* kCellLoAGrave */ 'a', /* kCellLoACircumflex */ 'a', /* kCellLoADiaeresis */ 'a', /* kCellLoATilde */ 'a', /* kCellLoARing */ 'c', /* kCellLoCCedilla */ 'e', /* kCellLoEAcute */ 'e', /* kCellLoEGrave */ 'e', /* kCellLoECircumflex */ 'e', /* kCellLoEDiaeresis */ 'i', /* kCellLoIAcute */ 'i', /* kCellLoIGrave */ 'i', /* kCellLoICircumflex */ 'i', /* kCellLoIDiaeresis */ 'n', /* kCellLoNTilde */ 'o', /* kCellLoOAcute */ 'o', /* kCellLoOGrave */ 'o', /* kCellLoOCircumflex */ 'o', /* kCellLoODiaeresis */ 'o', /* kCellLoOTilde */ 'u', /* kCellLoUAcute */ 'u', /* kCellLoUGrave */ 'u', /* kCellLoUCircumflex */ 'u', /* kCellLoUDiaeresis */ '?', /* kCellUpAE */ 'O', /* kCellUpOStroke */ '?', /* kCellLoAE */ 'o', /* kCellLoOStroke */ '?', /* kCellInvQuestion */ '!', /* kCellInvExclam */ 'A', /* kCellUpAGrave */ 'A', /* kCellUpATilde */ 'O', /* kCellUpOTilde */ '?', /* kCellUpLigatureOE */ '?', /* kCellLoLigatureOE */ 'y', /* kCellLoYDiaeresis */ 'Y', /* kCellUpYDiaeresis */ 'A', /* kCellUpACircumflex */ 'E', /* kCellUpECircumflex */ 'A', /* kCellUpAAcute */ 'E', /* kCellUpEDiaeresis */ 'E', /* kCellUpEGrave */ 'A', /* kCellUpIAcute */ 'I', /* kCellUpICircumflex */ 'I', /* kCellUpIDiaeresis */ 'I', /* kCellUpIGrave */ 'O', /* kCellUpOAcute */ 'O', /* kCellUpOCircumflex */ 'O', /* kCellUpOGrave */ 'U', /* kCellUpUAcute */ 'U', /* kCellUpUCircumflex */ 'U', /* kCellUpUGrave */ 'B', /* kCellSharpS */ 'A', /* kCellUpACedille */ 'a', /* kCellLoACedille */ 'C', /* kCellUpCAcute */ 'c', /* kCellLoCAcute */ 'E', /* kCellUpECedille */ 'e', /* kCellLoECedille */ 'L', /* kCellUpLBar */ 'l', /* kCellLoLBar */ 'N', /* kCellUpNAcute */ 'n', /* kCellLoNAcute */ 'S', /* kCellUpSAcute */ 's', /* kCellLoSAcute */ 'Z', /* kCellUpZAcute */ 'z', /* kCellLoZAcute */ 'Z', /* kCellUpZDot */ 'z', /* kCellLoZDot */ #endif '\0' /* just so last above line can end in ',' */ }; #endif #ifndef NeedCell2UnicodeMap #define NeedCell2UnicodeMap 0 #endif #if NeedCell2UnicodeMap /* Unicode character set */ LOCALVAR const ui4b Cell2UnicodeMap[] = { 0x0041, /* kCellUpA */ 0x0042, /* kCellUpB */ 0x0043, /* kCellUpC */ 0x0044, /* kCellUpD */ 0x0045, /* kCellUpE */ 0x0046, /* kCellUpF */ 0x0047, /* kCellUpG */ 0x0048, /* kCellUpH */ 0x0049, /* kCellUpI */ 0x004A, /* kCellUpJ */ 0x004B, /* kCellUpK */ 0x004C, /* kCellUpL */ 0x004D, /* kCellUpM */ 0x004E, /* kCellUpN */ 0x004F, /* kCellUpO */ 0x0050, /* kCellUpP */ 0x0051, /* kCellUpQ */ 0x0052, /* kCellUpR */ 0x0053, /* kCellUpS */ 0x0054, /* kCellUpT */ 0x0055, /* kCellUpU */ 0x0056, /* kCellUpV */ 0x0057, /* kCellUpW */ 0x0058, /* kCellUpX */ 0x0059, /* kCellUpY */ 0x005A, /* kCellUpZ */ 0x0061, /* kCellLoA */ 0x0062, /* kCellLoB */ 0x0063, /* kCellLoC */ 0x0064, /* kCellLoD */ 0x0065, /* kCellLoE */ 0x0066, /* kCellLoF */ 0x0067, /* kCellLoG */ 0x0068, /* kCellLoH */ 0x0069, /* kCellLoI */ 0x006A, /* kCellLoJ */ 0x006B, /* kCellLoK */ 0x006C, /* kCellLoL */ 0x006D, /* kCellLoM */ 0x006E, /* kCellLoN */ 0x006F, /* kCellLoO */ 0x0070, /* kCellLoP */ 0x0071, /* kCellLoQ */ 0x0072, /* kCellLoR */ 0x0073, /* kCellLoS */ 0x0074, /* kCellLoT */ 0x0075, /* kCellLoU */ 0x0076, /* kCellLoV */ 0x0077, /* kCellLoW */ 0x0078, /* kCellLoX */ 0x0079, /* kCellLoY */ 0x007A, /* kCellLoZ */ 0x0030, /* kCellDigit0 */ 0x0031, /* kCellDigit1 */ 0x0032, /* kCellDigit2 */ 0x0033, /* kCellDigit3 */ 0x0034, /* kCellDigit4 */ 0x0035, /* kCellDigit5 */ 0x0036, /* kCellDigit6 */ 0x0037, /* kCellDigit7 */ 0x0038, /* kCellDigit8 */ 0x0039, /* kCellDigit9 */ 0x0021, /* kCellExclamation */ 0x0026, /* kCellAmpersand */ 0x0027, /* kCellApostrophe */ 0x0028, /* kCellLeftParen */ 0x0029, /* kCellRightParen */ 0x002C, /* kCellComma */ 0x002D, /* kCellHyphen */ 0x002E, /* kCellPeriod */ 0x002F, /* kCellSlash */ 0x003A, /* kCellColon */ 0x003B, /* kCellSemicolon */ 0x003F, /* kCellQuestion */ 0x2026, /* kCellEllipsis */ 0x005F, /* kCellUnderscore */ 0x201C, /* kCellLeftDQuote */ 0x201D, /* kCellRightDQuote */ 0x2018, /* kCellLeftSQuote */ 0x2019, /* kCellRightSQuote */ 0x00A9, /* kCellCopyright */ 0x0020, /* kCellSpace */ #if NeedIntlChars 0x00C4, /* kCellUpADiaeresis */ 0x00C5, /* kCellUpARing */ 0x00C7, /* kCellUpCCedilla */ 0x00C9, /* kCellUpEAcute */ 0x00D1, /* kCellUpNTilde */ 0x00D6, /* kCellUpODiaeresis */ 0x00DC, /* kCellUpUDiaeresis */ 0x00E1, /* kCellLoAAcute */ 0x00E0, /* kCellLoAGrave */ 0x00E2, /* kCellLoACircumflex */ 0x00E4, /* kCellLoADiaeresis */ 0x00E3, /* kCellLoATilde */ 0x00E5, /* kCellLoARing */ 0x00E7, /* kCellLoCCedilla */ 0x00E9, /* kCellLoEAcute */ 0x00E8, /* kCellLoEGrave */ 0x00EA, /* kCellLoECircumflex */ 0x00EB, /* kCellLoEDiaeresis */ 0x00ED, /* kCellLoIAcute */ 0x00EC, /* kCellLoIGrave */ 0x00EE, /* kCellLoICircumflex */ 0x00EF, /* kCellLoIDiaeresis */ 0x00F1, /* kCellLoNTilde */ 0x00F3, /* kCellLoOAcute */ 0x00F2, /* kCellLoOGrave */ 0x00F4, /* kCellLoOCircumflex */ 0x00F6, /* kCellLoODiaeresis */ 0x00F5, /* kCellLoOTilde */ 0x00FA, /* kCellLoUAcute */ 0x00F9, /* kCellLoUGrave */ 0x00FB, /* kCellLoUCircumflex */ 0x00FC, /* kCellLoUDiaeresis */ 0x00C6, /* kCellUpAE */ 0x00D8, /* kCellUpOStroke */ 0x00E6, /* kCellLoAE */ 0x00F8, /* kCellLoOStroke */ 0x00BF, /* kCellInvQuestion */ 0x00A1, /* kCellInvExclam */ 0x00C0, /* kCellUpAGrave */ 0x00C3, /* kCellUpATilde */ 0x00D5, /* kCellUpOTilde */ 0x0152, /* kCellUpLigatureOE */ 0x0153, /* kCellLoLigatureOE */ 0x00FF, /* kCellLoYDiaeresis */ 0x0178, /* kCellUpYDiaeresis */ 0x00C2, /* kCellUpACircumflex */ 0x00CA, /* kCellUpECircumflex */ 0x00C1, /* kCellUpAAcute */ 0x00CB, /* kCellUpEDiaeresis */ 0x00C8, /* kCellUpEGrave */ 0x00CD, /* kCellUpIAcute */ 0x00CE, /* kCellUpICircumflex */ 0x00CF, /* kCellUpIDiaeresis */ 0x00CC, /* kCellUpIGrave */ 0x00D3, /* kCellUpOAcute */ 0x00D4, /* kCellUpOCircumflex */ 0x00D2, /* kCellUpOGrave */ 0x00DA, /* kCellUpUAcute */ 0x00DB, /* kCellUpUCircumflex */ 0x00D9, /* kCellUpUGrave */ 0x00DF, /* kCellSharpS */ 0x0104, /* kCellUpACedille */ 0x0105, /* kCellLoACedille */ 0x0106, /* kCellUpCAcute */ 0x0107, /* kCellLoCAcute */ 0x0118, /* kCellUpECedille */ 0x0119, /* kCellLoECedille */ 0x0141, /* kCellUpLBar */ 0x0142, /* kCellLoLBar */ 0x0143, /* kCellUpNAcute */ 0x0144, /* kCellLoNAcute */ 0x015A, /* kCellUpSAcute */ 0x015B, /* kCellLoSAcute */ 0x0179, /* kCellUpZAcute */ 0x017A, /* kCellLoZAcute */ 0x017B, /* kCellUpZDot */ 0x017C, /* kCellLoZDot */ #endif '\0' /* just so last above line can end in ',' */ }; #endif LOCALVAR blnr SpeedStopped = falseblnr; LOCALVAR blnr RunInBackground = (WantInitRunInBackground != 0); #if VarFullScreen LOCALVAR blnr WantFullScreen = (WantInitFullScreen != 0); #endif #if EnableMagnify LOCALVAR blnr WantMagnify = (WantInitMagnify != 0); #endif #if NeedRequestInsertDisk LOCALVAR blnr RequestInsertDisk = falseblnr; #endif #if UseControlKeys LOCALVAR blnr ControlKeyPressed = falseblnr; #endif LOCALFUNC char * GetSubstitutionStr(char x) { char *s; switch (x) { case 'w': s = kStrHomePage; break; case 'y': s = kStrCopyrightYear; break; case 'p': s = kStrAppName; break; case 'v': s = kAppVariationStr; break; case 'r': s = RomFileName; break; #if UseControlKeys case 'k': if (ControlKeyPressed) { s = kStrPressed; } else { s = kStrReleased; } break; #endif #if EnableMagnify case 'g': if (WantMagnify) { s = kStrOn; } else { s = kStrOff; } break; #endif #if VarFullScreen case 'f': if (WantFullScreen) { s = kStrOn; } else { s = kStrOff; } break; #endif case 'b': if (RunInBackground) { s = kStrOn; } else { s = kStrOff; } break; case 'h': if (SpeedStopped) { s = kStrStoppedOn; } else { s = kStrStoppedOff; } break; #if EnableAutoSlow case 'l': if (WantNotAutoSlow) { s = kStrStoppedOff; } else { s = kStrStoppedOn; } break; #endif case 's': switch (SpeedValue) { case 0: s = "1x"; break; case 1: s = "2x"; break; case 2: s = "4x"; break; case 3: s = "8x"; break; case 4: s = "16x"; break; case 5: s = "32x"; break; default: s = kStrSpeedValueAllOut; break; } break; default: s = "???"; break; } return s; } #define ClStrMaxLength 512 LOCALPROC ClStrAppendChar(int *L0, ui3b *r, ui3b c) { unsigned short L = *L0; if (ClStrMaxLength != L) { r[L] = c; L++; *L0 = L; } } LOCALPROC ClStrAppendSubstCStr(int *L, ui3b *r, char *s) { char *p = s; char c; ui3b x; while ((c = *p++) != 0) { if (c == '^') { if ((c = *p++) == 0) { return; /* oops, unexpected end of string, abort */ } else if (c == '^') { ClStrAppendChar(L, r, c); } else { ClStrAppendSubstCStr(L, r, GetSubstitutionStr(c)); } } else if (c == ';') { switch (*p++) { case 'g': x = kCellCopyright; break; case 'l': switch (*p++) { case 'a': x = kCellApostrophe; break; case 'l': x = kCellEllipsis; break; case 's': x = kCellSemicolon; break; #if NeedIntlChars case 'E': x = kCellUpAE; break; case 'e': x = kCellLoAE; break; #endif default: return; break; } break; case '[': x = kCellLeftDQuote; break; case '{': x = kCellRightDQuote; break; case ']': x = kCellLeftSQuote; break; case '}': x = kCellRightSQuote; break; #if NeedIntlChars case '?': x = kCellInvQuestion; break; case 'A': x = kCellUpARing; break; case 'C': x = kCellUpCCedilla; break; case 'O': x = kCellUpOStroke; break; case 'Q': x = kCellUpLigatureOE; break; case '`': switch (*p++) { case 'A': x = kCellUpAGrave; break; case 'E': x = kCellUpEGrave; break; case 'I': x = kCellUpIGrave; break; case 'O': x = kCellUpOGrave; break; case 'U': x = kCellUpUGrave; break; case 'a': x = kCellLoAGrave; break; case 'e': x = kCellLoEGrave; break; case 'i': x = kCellLoIGrave; break; case 'o': x = kCellLoOGrave; break; case 'u': x = kCellLoUGrave; break; default: return; break; } break; case 'a': x = kCellLoARing; break; case 'c': x = kCellLoCCedilla; break; case 'd': switch (*p++) { case 'A': x = kCellUpACedille; break; case 'a': x = kCellLoACedille; break; case 'E': x = kCellUpECedille; break; case 'e': x = kCellLoECedille; break; case 'L': x = kCellUpLBar; break; case 'l': x = kCellLoLBar; break; case 'Z': x = kCellUpZDot; break; case 'z': x = kCellLoZDot; break; default: return; break; } break; case 'e': switch (*p++) { case 'A': x = kCellUpAAcute; break; case 'E': x = kCellUpEAcute; break; case 'I': x = kCellUpIAcute; break; case 'O': x = kCellUpOAcute; break; case 'U': x = kCellUpUAcute; break; case 'a': x = kCellLoAAcute; break; case 'e': x = kCellLoEAcute; break; case 'i': x = kCellLoIAcute; break; case 'o': x = kCellLoOAcute; break; case 'u': x = kCellLoUAcute; break; case 'C': x = kCellUpCAcute; break; case 'c': x = kCellLoCAcute; break; case 'N': x = kCellUpNAcute; break; case 'n': x = kCellLoNAcute; break; case 'S': x = kCellUpSAcute; break; case 's': x = kCellLoSAcute; break; case 'Z': x = kCellUpZAcute; break; case 'z': x = kCellLoZAcute; break; default: return; break; } break; case 'i': switch (*p++) { case 'A': x = kCellUpACircumflex; break; case 'E': x = kCellUpECircumflex; break; case 'I': x = kCellUpICircumflex; break; case 'O': x = kCellUpOCircumflex; break; case 'U': x = kCellUpUCircumflex; break; case 'a': x = kCellLoACircumflex; break; case 'e': x = kCellLoECircumflex; break; case 'i': x = kCellLoICircumflex; break; case 'o': x = kCellLoOCircumflex; break; case 'u': x = kCellLoUCircumflex; break; default: return; break; } break; case 'n': switch (*p++) { case 'A': x = kCellUpATilde; break; case 'N': x = kCellUpNTilde; break; case 'O': x = kCellUpOTilde; break; case 'a': x = kCellLoATilde; break; case 'n': x = kCellLoNTilde; break; case 'o': x = kCellLoOTilde; break; default: return; break; } break; case 'o': x = kCellLoOStroke; break; case 'q': x = kCellLoLigatureOE; break; case 's': x = kCellSharpS; break; case 'u': switch (*p++) { case 'A': x = kCellUpADiaeresis; break; case 'E': x = kCellUpEDiaeresis; break; case 'I': x = kCellUpIDiaeresis; break; case 'O': x = kCellUpODiaeresis; break; case 'U': x = kCellUpUDiaeresis; break; case 'Y': x = kCellUpYDiaeresis; break; case 'a': x = kCellLoADiaeresis; break; case 'e': x = kCellLoEDiaeresis; break; case 'i': x = kCellLoIDiaeresis; break; case 'o': x = kCellLoODiaeresis; break; case 'u': x = kCellLoUDiaeresis; break; case 'y': x = kCellLoYDiaeresis; break; default: return; break; } break; #endif default: return; /* oops, unexpected char, maybe end of string, abort */ break; } ClStrAppendChar(L, r, x); } else { switch (c) { case 'A': x = kCellUpA; break; case 'B': x = kCellUpB; break; case 'C': x = kCellUpC; break; case 'D': x = kCellUpD; break; case 'E': x = kCellUpE; break; case 'F': x = kCellUpF; break; case 'G': x = kCellUpG; break; case 'H': x = kCellUpH; break; case 'I': x = kCellUpI; break; case 'J': x = kCellUpJ; break; case 'K': x = kCellUpK; break; case 'L': x = kCellUpL; break; case 'M': x = kCellUpM; break; case 'N': x = kCellUpN; break; case 'O': x = kCellUpO; break; case 'P': x = kCellUpP; break; case 'Q': x = kCellUpQ; break; case 'R': x = kCellUpR; break; case 'S': x = kCellUpS; break; case 'T': x = kCellUpT; break; case 'U': x = kCellUpU; break; case 'V': x = kCellUpV; break; case 'W': x = kCellUpW; break; case 'X': x = kCellUpX; break; case 'Y': x = kCellUpY; break; case 'Z': x = kCellUpZ; break; case 'a': x = kCellLoA; break; case 'b': x = kCellLoB; break; case 'c': x = kCellLoC; break; case 'd': x = kCellLoD; break; case 'e': x = kCellLoE; break; case 'f': x = kCellLoF; break; case 'g': x = kCellLoG; break; case 'h': x = kCellLoH; break; case 'i': x = kCellLoI; break; case 'j': x = kCellLoJ; break; case 'k': x = kCellLoK; break; case 'l': x = kCellLoL; break; case 'm': x = kCellLoM; break; case 'n': x = kCellLoN; break; case 'o': x = kCellLoO; break; case 'p': x = kCellLoP; break; case 'q': x = kCellLoQ; break; case 'r': x = kCellLoR; break; case 's': x = kCellLoS; break; case 't': x = kCellLoT; break; case 'u': x = kCellLoU; break; case 'v': x = kCellLoV; break; case 'w': x = kCellLoW; break; case 'x': x = kCellLoX; break; case 'y': x = kCellLoY; break; case 'z': x = kCellLoZ; break; case '0': x = kCellDigit0; break; case '1': x = kCellDigit1; break; case '2': x = kCellDigit2; break; case '3': x = kCellDigit3; break; case '4': x = kCellDigit4; break; case '5': x = kCellDigit5; break; case '6': x = kCellDigit6; break; case '7': x = kCellDigit7; break; case '8': x = kCellDigit8; break; case '9': x = kCellDigit9; break; case '!': x = kCellExclamation; break; case '&': x = kCellAmpersand; break; case '(': x = kCellLeftParen; break; case ')': x = kCellRightParen; break; case ',': x = kCellComma; break; case '-': x = kCellHyphen; break; case '.': x = kCellPeriod; break; case '/': x = kCellSlash; break; case ':': x = kCellColon; break; case ';': x = kCellSemicolon; break; case '?': x = kCellQuestion; break; case '_': x = kCellUnderscore; break; default: x = kCellSpace; break; } ClStrAppendChar(L, r, x); } } } LOCALPROC ClStrFromSubstCStr(int *L, ui3b *r, char *s) { *L = 0; ClStrAppendSubstCStr(L, r, s); } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/IWMEMDEV.c b/Mini vMac/mnvm_core/IWMEMDEV.c index 31c89d5..93a06d2 100755 --- a/Mini vMac/mnvm_core/IWMEMDEV.c +++ b/Mini vMac/mnvm_core/IWMEMDEV.c @@ -1,210 +1 @@ -/* - IWMEVDEV.c - - Copyright (C) 2006 Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - Integrated Woz Machine EMulated DEVice - - Emulates the IWM found in the Mac Plus. - - This code is adapted from "IWM.c" in vMac by Philip Cummins. -*/ - -/* - This is the emulation for the IWM, the Integrated Woz Machine. - It's basically a serial to parallel converter with some timing - in-built into it to perform handshaking. Emulation so far just - includes Status and Mode Register Accesses. -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" - -#include "MYOSGLUE.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" -#endif - -#include "IWMEMDEV.h" - -#define kph0L 0x00 /* CA0 off (0) */ -#define kph0H 0x01 /* CA0 on (1) */ -#define kph1L 0x02 /* CA1 off (0) */ -#define kph1H 0x03 /* CA1 on (1) */ -#define kph2L 0x04 /* CA2 off (0) */ -#define kph2H 0x05 /* CA2 on (1) */ -#define kph3L 0x06 /* LSTRB off (low) */ -#define kph3H 0x07 /* LSTRB on (high) */ -#define kmtrOff 0x08 /* disk enable off */ -#define kmtrOn 0x09 /* disk enable on */ -#define kintDrive 0x0A /* select internal drive */ -#define kextDrive 0x0B /* select external drive */ -#define kq6L 0x0C /* Q6 off */ -#define kq6H 0x0D /* Q6 on */ -#define kq7L 0x0E /* Q7 off */ -#define kq7H 0x0F /* Q7 on */ - -#define kph0 0x01 -#define kph1 0x02 -#define kph2 0x04 -#define kph3 0x08 -#define kmtr 0x10 -#define kdrv 0x20 -#define kq6 0x40 -#define kq7 0x80 - -typedef struct -{ - ui3b DataIn; /* Read Data Register */ - ui3b Handshake; /* Read Handshake Register */ - ui3b Status; /* Read Status Register */ - ui3b Mode; - /* Drive Off : Write Mode Register */ - /* Drive On : Write Data Register */ - ui3b DataOut; /* Write Data Register */ - ui3b Lines; /* Used to Access Disk Drive Registers */ -} IWM_Ty; - -IWM_Ty IWM; - -GLOBALPROC IWM_Reset(void) -{ - IWM.DataIn = IWM.Handshake = IWM.Status = IWM.Mode = - IWM.DataOut = IWM.Lines = 0; -} - -typedef enum {On, Off} Mode_Ty; - -LOCALPROC IWM_Set_Lines(ui3b line, Mode_Ty the_mode) -{ - if (the_mode == Off) { - IWM.Lines &= (0xFF - line); - } else { - IWM.Lines |= line; - } -} - -LOCALFUNC ui3b IWM_Read_Reg(void) -{ - switch ((IWM.Lines & (kq6 + kq7)) >> 6) { - case 0 : -#if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx) - /* don't report */ -#else - ReportAbnormal("IWM Data Read"); -#endif -#ifdef _IWM_Debug - printf("IWM Data Read\n"); -#endif - return IWM.DataIn; - break; - case 1 : -#ifdef _IWM_Debug - printf("IWM Status Read\n"); -#endif - return IWM.Status; - break; - case 2 : - ReportAbnormal("IWM Handshake Read"); -#ifdef _IWM_Debug - printf("IWM Handshake Read\n"); -#endif - return IWM.Handshake; - break; - case 3 : - default : - /* - should alway be in 0-3, - but compiler warnings don't know that - */ - return 0; - break; - } -} - -LOCALPROC IWM_Write_Reg(ui3b in) -{ - if (((IWM.Lines & kmtr) >> 4) == 0) { -#ifdef _IWM_Debug - printf("IWM Mode Register Write\n"); -#endif - IWM.Mode = in; - IWM.Status = ((IWM.Status & 0xE0) + (IWM.Mode & 0x1F)); - } -} - -GLOBALFUNC ui5b IWM_Access(ui5b Data, blnr WriteMem, CPTR addr) -{ - switch (addr) { - case kph0L : - IWM_Set_Lines(kph0, Off); - break; - case kph0H : - IWM_Set_Lines(kph0, On); - break; - case kph1L : - IWM_Set_Lines(kph1, Off); - break; - case kph1H : - IWM_Set_Lines(kph1, On); - break; - case kph2L : - IWM_Set_Lines(kph2, Off); - break; - case kph2H : - IWM_Set_Lines(kph2, On); - break; - case kph3L : - IWM_Set_Lines(kph3, Off); - break; - case kph3H : - IWM_Set_Lines(kph3, On); - break; - case kmtrOff : - IWM.Status &= 0xDF; - IWM_Set_Lines(kmtr, Off); - break; - case kmtrOn : - IWM.Status |= 0x20; - IWM_Set_Lines(kmtr, On); - break; - case kintDrive : - IWM_Set_Lines(kdrv, Off); - break; - case kextDrive : - IWM_Set_Lines(kdrv, On); - break; - case kq6L : - IWM_Set_Lines(kq6, Off); - break; - case kq6H : - IWM_Set_Lines(kq6, On); - break; - case kq7L : - if (! WriteMem) { - Data = IWM_Read_Reg(); - } - IWM_Set_Lines(kq7, Off); - break; - case kq7H : - if (WriteMem) { - IWM_Write_Reg(Data); - } - IWM_Set_Lines(kq7, On); - break; - } - - return Data; -} +/* IWMEVDEV.c Copyright (C) 2006 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* Integrated Woz Machine EMulated DEVice Emulates the IWM found in the Mac Plus. This code is adapted from "IWM.c" in vMac by Philip Cummins. */ /* This is the emulation for the IWM, the Integrated Woz Machine. It's basically a serial to parallel converter with some timing in-built into it to perform handshaking. Emulation so far just includes Status and Mode Register Accesses. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif #include "IWMEMDEV.h" /* ReportAbnormalID unused 0x0603 - 0x06FF */ #define kph0L 0x00 /* CA0 off (0) */ #define kph0H 0x01 /* CA0 on (1) */ #define kph1L 0x02 /* CA1 off (0) */ #define kph1H 0x03 /* CA1 on (1) */ #define kph2L 0x04 /* CA2 off (0) */ #define kph2H 0x05 /* CA2 on (1) */ #define kph3L 0x06 /* LSTRB off (low) */ #define kph3H 0x07 /* LSTRB on (high) */ #define kmtrOff 0x08 /* disk enable off */ #define kmtrOn 0x09 /* disk enable on */ #define kintDrive 0x0A /* select internal drive */ #define kextDrive 0x0B /* select external drive */ #define kq6L 0x0C /* Q6 off */ #define kq6H 0x0D /* Q6 on */ #define kq7L 0x0E /* Q7 off */ #define kq7H 0x0F /* Q7 on */ #define kph0 0x01 #define kph1 0x02 #define kph2 0x04 #define kph3 0x08 #define kmtr 0x10 #define kdrv 0x20 #define kq6 0x40 #define kq7 0x80 typedef struct { ui3b DataIn; /* Read Data Register */ ui3b Handshake; /* Read Handshake Register */ ui3b Status; /* Read Status Register */ ui3b Mode; /* Drive Off : Write Mode Register */ /* Drive On : Write Data Register */ ui3b DataOut; /* Write Data Register */ ui3b Lines; /* Used to Access Disk Drive Registers */ } IWM_Ty; IWM_Ty IWM; GLOBALPROC IWM_Reset(void) { IWM.DataIn = IWM.Handshake = IWM.Status = IWM.Mode = IWM.DataOut = IWM.Lines = 0; } typedef enum {On, Off} Mode_Ty; LOCALPROC IWM_Set_Lines(ui3b line, Mode_Ty the_mode) { if (the_mode == Off) { IWM.Lines &= (0xFF - line); } else { IWM.Lines |= line; } } LOCALFUNC ui3b IWM_Read_Reg(void) { switch ((IWM.Lines & (kq6 + kq7)) >> 6) { case 0 : #if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx) /* don't report */ #else ReportAbnormalID(0x0601, "IWM Data Read"); #endif #ifdef _IWM_Debug printf("IWM Data Read\n"); #endif return IWM.DataIn; break; case 1 : #ifdef _IWM_Debug printf("IWM Status Read\n"); #endif return IWM.Status; break; case 2 : ReportAbnormalID(0x0602, "IWM Handshake Read"); #ifdef _IWM_Debug printf("IWM Handshake Read\n"); #endif return IWM.Handshake; break; case 3 : default : /* should alway be in 0-3, but compiler warnings don't know that */ return 0; break; } } LOCALPROC IWM_Write_Reg(ui3b in) { if (((IWM.Lines & kmtr) >> 4) == 0) { #ifdef _IWM_Debug printf("IWM Mode Register Write\n"); #endif IWM.Mode = in; IWM.Status = ((IWM.Status & 0xE0) + (IWM.Mode & 0x1F)); } } GLOBALFUNC ui5b IWM_Access(ui5b Data, blnr WriteMem, CPTR addr) { switch (addr) { case kph0L : IWM_Set_Lines(kph0, Off); break; case kph0H : IWM_Set_Lines(kph0, On); break; case kph1L : IWM_Set_Lines(kph1, Off); break; case kph1H : IWM_Set_Lines(kph1, On); break; case kph2L : IWM_Set_Lines(kph2, Off); break; case kph2H : IWM_Set_Lines(kph2, On); break; case kph3L : IWM_Set_Lines(kph3, Off); break; case kph3H : IWM_Set_Lines(kph3, On); break; case kmtrOff : IWM.Status &= 0xDF; IWM_Set_Lines(kmtr, Off); break; case kmtrOn : IWM.Status |= 0x20; IWM_Set_Lines(kmtr, On); break; case kintDrive : IWM_Set_Lines(kdrv, Off); break; case kextDrive : IWM_Set_Lines(kdrv, On); break; case kq6L : IWM_Set_Lines(kq6, Off); break; case kq6H : IWM_Set_Lines(kq6, On); break; case kq7L : if (! WriteMem) { Data = IWM_Read_Reg(); } IWM_Set_Lines(kq7, Off); break; case kq7H : if (WriteMem) { IWM_Write_Reg(Data); } IWM_Set_Lines(kq7, On); break; } return Data; } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/IWMEMDEV.h b/Mini vMac/mnvm_core/IWMEMDEV.h index 5bfea53..7205b8c 100755 --- a/Mini vMac/mnvm_core/IWMEMDEV.h +++ b/Mini vMac/mnvm_core/IWMEMDEV.h @@ -1,25 +1 @@ -/* - IWMEVDEV.h - - Copyright (C) 2004 Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef IWMEVDEV_H -#error "header already included" -#else -#define IWMEVDEV_H -#endif - -EXPORTPROC IWM_Reset(void); - -EXPORTFUNC ui5b IWM_Access(ui5b Data, blnr WriteMem, CPTR addr); +/* IWMEVDEV.h Copyright (C) 2004 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef IWMEVDEV_H #error "header already included" #else #define IWMEVDEV_H #endif EXPORTPROC IWM_Reset(void); EXPORTFUNC ui5b IWM_Access(ui5b Data, blnr WriteMem, CPTR addr); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/KBRDEMDV.c b/Mini vMac/mnvm_core/KBRDEMDV.c index b33ab0f..1571bc6 100755 --- a/Mini vMac/mnvm_core/KBRDEMDV.c +++ b/Mini vMac/mnvm_core/KBRDEMDV.c @@ -1,208 +1 @@ -/* - KBRDEMDV.c - - Copyright (C) 2006 Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - KeyBoaRD EMulated DeVice - - Emulation of the keyboard in the Mac Plus. - - This code adapted from "Keyboard.c" in vMac by Philip Cummins. -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" -#include "MYOSGLUE.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" -#endif - -#include "KBRDEMDV.h" - -#ifdef _VIA_Debug -#include -#endif - -IMPORTPROC KYBD_ShiftOutData(ui3b v); -IMPORTFUNC ui3b KYBD_ShiftInData(void); - -enum { - kKybdStateIdle, - kKybdStateRecievingCommand, - kKybdStateRecievedCommand, - kKybdStateRecievingEndCommand, - - kKybdStates -}; - -LOCALVAR int KybdState = kKybdStateIdle; - -LOCALVAR blnr HaveKeyBoardResult = falseblnr; -LOCALVAR ui3b KeyBoardResult; - -LOCALPROC GotKeyBoardData(ui3b v) -{ - if (KybdState != kKybdStateIdle) { - HaveKeyBoardResult = trueblnr; - KeyBoardResult = v; - } else { - KYBD_ShiftOutData(v); - VIA1_iCB2 = 1; - } -} - -LOCALVAR ui3b InstantCommandData = 0x7B; - -LOCALFUNC blnr AttemptToFinishInquiry(void) -{ - int i; - blnr KeyDown; - ui3b Keyboard_Data; - - if (FindKeyEvent(&i, &KeyDown)) { - if (i < 64) { - Keyboard_Data = i << 1; - if (! KeyDown) { - Keyboard_Data += 128; - } - } else { - Keyboard_Data = 121; - InstantCommandData = (i - 64) << 1; - if (! KeyDown) { - InstantCommandData += 128; - } - } - GotKeyBoardData(Keyboard_Data); - return trueblnr; - } else { - return falseblnr; - } -} - -#define MaxKeyboardWait 16 /* in 60ths of a second */ - /* - Code in the mac rom will reset the keyboard if - it hasn't been heard from in 32/60th of a second. - So time out and send something before that - to keep connection. - */ - -LOCALVAR int InquiryCommandTimer = 0; - -GLOBALPROC DoKybd_ReceiveCommand(void) -{ - if (KybdState != kKybdStateRecievingCommand) { - ReportAbnormal("KybdState != kKybdStateRecievingCommand"); - } else { - ui3b in = KYBD_ShiftInData(); - - KybdState = kKybdStateRecievedCommand; - - switch (in) { - case 0x10 : /* Inquiry Command */ - if (! AttemptToFinishInquiry()) { - InquiryCommandTimer = MaxKeyboardWait; - } - break; - case 0x14 : /* Instant Command */ - GotKeyBoardData(InstantCommandData); - InstantCommandData = 0x7B; - break; - case 0x16 : /* Model Command */ - GotKeyBoardData(0x0b /* 0x01 */); - /* Test value, means Model 0, no extra devices */ - /* - Fixed by Hoshi Takanori - - it uses the proper keyboard type now - */ - break; - case 0x36 : /* Test Command */ - GotKeyBoardData(0x7D); - break; - case 0x00: - GotKeyBoardData(0); - break; - default : - /* Debugger(); */ - GotKeyBoardData(0); - break; - } - } -} - -GLOBALPROC DoKybd_ReceiveEndCommand(void) -{ - if (KybdState != kKybdStateRecievingEndCommand) { - ReportAbnormal("KybdState != kKybdStateRecievingEndCommand"); - } else { - KybdState = kKybdStateIdle; -#ifdef _VIA_Debug - fprintf(stderr, "enter DoKybd_ReceiveEndCommand\n"); -#endif - if (HaveKeyBoardResult) { -#ifdef _VIA_Debug - fprintf(stderr, "HaveKeyBoardResult: %d\n", KeyBoardResult); -#endif - HaveKeyBoardResult = falseblnr; - KYBD_ShiftOutData(KeyBoardResult); - VIA1_iCB2 = 1; - } - } -} - -GLOBALPROC Kybd_DataLineChngNtfy(void) -{ - switch (KybdState) { - case kKybdStateIdle: - if (VIA1_iCB2 == 0) { - KybdState = kKybdStateRecievingCommand; -#ifdef _VIA_Debug - fprintf(stderr, "posting kICT_Kybd_ReceiveCommand\n"); -#endif - ICT_add(kICT_Kybd_ReceiveCommand, - 6800UL * kCycleScale / 64 * kMyClockMult); - - if (InquiryCommandTimer != 0) { - InquiryCommandTimer = 0; /* abort Inquiry */ - } - } - break; - case kKybdStateRecievedCommand: - if (VIA1_iCB2 == 1) { - KybdState = kKybdStateRecievingEndCommand; -#ifdef _VIA_Debug - fprintf(stderr, - "posting kICT_Kybd_ReceiveEndCommand\n"); -#endif - ICT_add(kICT_Kybd_ReceiveEndCommand, - 6800UL * kCycleScale / 64 * kMyClockMult); - } - break; - } -} - -GLOBALPROC KeyBoard_Update(void) -{ - if (InquiryCommandTimer != 0) { - if (AttemptToFinishInquiry()) { - InquiryCommandTimer = 0; - } else { - --InquiryCommandTimer; - if (InquiryCommandTimer == 0) { - GotKeyBoardData(0x7B); - } - } - } -} +/* KBRDEMDV.c Copyright (C) 2006 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* KeyBoaRD EMulated DeVice Emulation of the keyboard in the Mac Plus. This code adapted from "Keyboard.c" in vMac by Philip Cummins. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif #include "KBRDEMDV.h" #ifdef _VIA_Debug #include #endif /* ReportAbnormalID unused 0x0B03 - 0x0BFF */ IMPORTPROC KYBD_ShiftOutData(ui3b v); IMPORTFUNC ui3b KYBD_ShiftInData(void); enum { kKybdStateIdle, kKybdStateRecievingCommand, kKybdStateRecievedCommand, kKybdStateRecievingEndCommand, kKybdStates }; LOCALVAR int KybdState = kKybdStateIdle; LOCALVAR blnr HaveKeyBoardResult = falseblnr; LOCALVAR ui3b KeyBoardResult; LOCALPROC GotKeyBoardData(ui3b v) { if (KybdState != kKybdStateIdle) { HaveKeyBoardResult = trueblnr; KeyBoardResult = v; } else { KYBD_ShiftOutData(v); VIA1_iCB2 = 1; } } LOCALVAR ui3b InstantCommandData = 0x7B; LOCALFUNC blnr AttemptToFinishInquiry(void) { int i; blnr KeyDown; ui3b Keyboard_Data; if (FindKeyEvent(&i, &KeyDown)) { if (i < 64) { Keyboard_Data = i << 1; if (! KeyDown) { Keyboard_Data += 128; } } else { Keyboard_Data = 121; InstantCommandData = (i - 64) << 1; if (! KeyDown) { InstantCommandData += 128; } } GotKeyBoardData(Keyboard_Data); return trueblnr; } else { return falseblnr; } } #define MaxKeyboardWait 16 /* in 60ths of a second */ /* Code in the mac rom will reset the keyboard if it hasn't been heard from in 32/60th of a second. So time out and send something before that to keep connection. */ LOCALVAR int InquiryCommandTimer = 0; GLOBALPROC DoKybd_ReceiveCommand(void) { if (KybdState != kKybdStateRecievingCommand) { ReportAbnormalID(0x0B01, "KybdState != kKybdStateRecievingCommand"); } else { ui3b in = KYBD_ShiftInData(); KybdState = kKybdStateRecievedCommand; switch (in) { case 0x10 : /* Inquiry Command */ if (! AttemptToFinishInquiry()) { InquiryCommandTimer = MaxKeyboardWait; } break; case 0x14 : /* Instant Command */ GotKeyBoardData(InstantCommandData); InstantCommandData = 0x7B; break; case 0x16 : /* Model Command */ GotKeyBoardData(0x0b /* 0x01 */); /* Test value, means Model 0, no extra devices */ /* Fixed by Hoshi Takanori - it uses the proper keyboard type now */ break; case 0x36 : /* Test Command */ GotKeyBoardData(0x7D); break; case 0x00: GotKeyBoardData(0); break; default : /* Debugger(); */ GotKeyBoardData(0); break; } } } GLOBALPROC DoKybd_ReceiveEndCommand(void) { if (KybdState != kKybdStateRecievingEndCommand) { ReportAbnormalID(0x0B02, "KybdState != kKybdStateRecievingEndCommand"); } else { KybdState = kKybdStateIdle; #ifdef _VIA_Debug fprintf(stderr, "enter DoKybd_ReceiveEndCommand\n"); #endif if (HaveKeyBoardResult) { #ifdef _VIA_Debug fprintf(stderr, "HaveKeyBoardResult: %d\n", KeyBoardResult); #endif HaveKeyBoardResult = falseblnr; KYBD_ShiftOutData(KeyBoardResult); VIA1_iCB2 = 1; } } } GLOBALPROC Kybd_DataLineChngNtfy(void) { switch (KybdState) { case kKybdStateIdle: if (VIA1_iCB2 == 0) { KybdState = kKybdStateRecievingCommand; #ifdef _VIA_Debug fprintf(stderr, "posting kICT_Kybd_ReceiveCommand\n"); #endif ICT_add(kICT_Kybd_ReceiveCommand, 6800UL * kCycleScale / 64 * kMyClockMult); if (InquiryCommandTimer != 0) { InquiryCommandTimer = 0; /* abort Inquiry */ } } break; case kKybdStateRecievedCommand: if (VIA1_iCB2 == 1) { KybdState = kKybdStateRecievingEndCommand; #ifdef _VIA_Debug fprintf(stderr, "posting kICT_Kybd_ReceiveEndCommand\n"); #endif ICT_add(kICT_Kybd_ReceiveEndCommand, 6800UL * kCycleScale / 64 * kMyClockMult); } break; } } GLOBALPROC KeyBoard_Update(void) { if (InquiryCommandTimer != 0) { if (AttemptToFinishInquiry()) { InquiryCommandTimer = 0; } else { --InquiryCommandTimer; if (InquiryCommandTimer == 0) { GotKeyBoardData(0x7B); } } } } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/KBRDEMDV.h b/Mini vMac/mnvm_core/KBRDEMDV.h index c068804..f33401d 100755 --- a/Mini vMac/mnvm_core/KBRDEMDV.h +++ b/Mini vMac/mnvm_core/KBRDEMDV.h @@ -1,27 +1 @@ -/* - KBRDEMDV.h - - Copyright (C) 2003 Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef KBRDEMDV_H -#error "header already included" -#else -#define KBRDEMDV_H -#endif - - -EXPORTPROC Kybd_DataLineChngNtfy(void); -EXPORTPROC DoKybd_ReceiveEndCommand(void); -EXPORTPROC DoKybd_ReceiveCommand(void); -EXPORTPROC KeyBoard_Update(void); +/* KBRDEMDV.h Copyright (C) 2003 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef KBRDEMDV_H #error "header already included" #else #define KBRDEMDV_H #endif EXPORTPROC Kybd_DataLineChngNtfy(void); EXPORTPROC DoKybd_ReceiveEndCommand(void); EXPORTPROC DoKybd_ReceiveCommand(void); EXPORTPROC KeyBoard_Update(void); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/M68KITAB.c b/Mini vMac/mnvm_core/M68KITAB.c index b707a99..076dffc 100755 --- a/Mini vMac/mnvm_core/M68KITAB.c +++ b/Mini vMac/mnvm_core/M68KITAB.c @@ -1,2722 +1 @@ -/* - M68KITAB.c - - Copyright (C) 2007 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - Motorola 68K Instructions TABle -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" -#endif - -#include "MYOSGLUE.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" - -#include "M68KITAB.h" - -struct WorkR { - /* expected size : 8 bytes */ - ui5b opcode; - ui5b opsize; - ui4r MainClass; -#if WantCycByPriOp - ui4r Cycles; -#endif - DecOpR DecOp; -}; -typedef struct WorkR WorkR; - -#define b76(p) ((p->opcode >> 6) & 3) -#define b8(p) ((p->opcode >> 8) & 1) -#define mode(p) ((p->opcode >> 3) & 7) -#define reg(p) (p->opcode & 7) -#define md6(p) ((p->opcode >> 6) & 7) -#define rg9(p) ((p->opcode >> 9) & 7) - -enum { - kAddrValidAny, - kAddrValidData, - kAddrValidDataAlt, - kAddrValidControl, - kAddrValidControlAlt, - kAddrValidAltMem, - - kNumAddrValids -}; - -#define kAddrValidMaskAny (1 << kAddrValidAny) -#define kAddrValidMaskData (1 << kAddrValidData) -#define kAddrValidMaskDataAlt (1 << kAddrValidDataAlt) -#define kAddrValidMaskControl (1 << kAddrValidControl) -#define kAddrValidMaskControlAlt (1 << kAddrValidControlAlt) -#define kAddrValidMaskAltMem (1 << kAddrValidAltMem) - -#define CheckInSet(v, m) (0 != ((1 << (v)) & (m))) - -#define kMyAvgCycPerInstr (10 * kCycleScale + (40 * kCycleScale / 64)) - -LOCALFUNC MayNotInline ui3r GetArgkRegSz(WorkR *p) -{ - ui3r CurArgk; - - switch (p->opsize) { - case 1: - CurArgk = kArgkRegB; - break; - case 2: - default: /* keep compiler happy */ - CurArgk = kArgkRegW; - break; - case 4: - CurArgk = kArgkRegL; - break; - } - - return CurArgk; -} - -LOCALFUNC MayNotInline ui3r GetArgkMemSz(WorkR *p) -{ - ui3r CurArgk; - - switch (p->opsize) { - case 1: - CurArgk = kArgkMemB; - break; - case 2: - default: /* keep compiler happy */ - CurArgk = kArgkMemW; - break; - case 4: - CurArgk = kArgkMemL; - break; - } - - return CurArgk; -} - -#if WantCycByPriOp -LOCALFUNC MayNotInline ui4r OpEACalcCyc(WorkR *p, ui3r m, ui3r r) -{ - ui4r v; - - switch (m) { - case 0: - case 1: - v = 0; - break; - case 2: - v = ((4 == p->opsize) - ? (8 * kCycleScale + 2 * RdAvgXtraCyc) - : (4 * kCycleScale + RdAvgXtraCyc)); - break; - case 3: - v = ((4 == p->opsize) - ? (8 * kCycleScale + 2 * RdAvgXtraCyc) - : (4 * kCycleScale + RdAvgXtraCyc)); - break; - case 4: - v = ((4 == p->opsize) - ? (10 * kCycleScale + 2 * RdAvgXtraCyc) - : (6 * kCycleScale + RdAvgXtraCyc)); - break; - case 5: - v = ((4 == p->opsize) - ? (12 * kCycleScale + 3 * RdAvgXtraCyc) - : (8 * kCycleScale + 2 * RdAvgXtraCyc)); - break; - case 6: - v = ((4 == p->opsize) - ? (14 * kCycleScale + 3 * RdAvgXtraCyc) - : (10 * kCycleScale + 2 * RdAvgXtraCyc)); - break; - case 7: - switch (r) { - case 0: - v = ((4 == p->opsize) - ? (12 * kCycleScale + 3 * RdAvgXtraCyc) - : (8 * kCycleScale + 2 * RdAvgXtraCyc)); - break; - case 1: - v = ((4 == p->opsize) - ? (16 * kCycleScale + 4 * RdAvgXtraCyc) - : (12 * kCycleScale + 3 * RdAvgXtraCyc)); - break; - case 2: - v = ((4 == p->opsize) - ? (12 * kCycleScale + 3 * RdAvgXtraCyc) - : (8 * kCycleScale + 2 * RdAvgXtraCyc)); - break; - case 3: - v = ((4 == p->opsize) - ? (14 * kCycleScale + 3 * RdAvgXtraCyc) - : (10 * kCycleScale + 2 * RdAvgXtraCyc)); - break; - case 4: - v = ((4 == p->opsize) - ? (8 * kCycleScale + 2 * RdAvgXtraCyc) - : (4 * kCycleScale + RdAvgXtraCyc)); - break; - default: - v = 0; - break; - } - break; - default: /* keep compiler happy */ - v = 0; - break; - } - - return v; -} -#endif - -#if WantCycByPriOp -LOCALFUNC MayNotInline ui4r OpEADestCalcCyc(WorkR *p, ui3r m, ui3r r) -{ - ui4r v; - - switch (m) { - case 0: - case 1: - v = 0; - break; - case 2: - v = ((4 == p->opsize) - ? (8 * kCycleScale + 2 * WrAvgXtraCyc) - : (4 * kCycleScale + WrAvgXtraCyc)); - break; - case 3: - v = ((4 == p->opsize) - ? (8 * kCycleScale + 2 * WrAvgXtraCyc) - : (4 * kCycleScale + WrAvgXtraCyc)); - break; - case 4: - v = ((4 == p->opsize) - ? (8 * kCycleScale + 2 * WrAvgXtraCyc) - : (4 * kCycleScale + WrAvgXtraCyc)); - break; - case 5: - v = ((4 == p->opsize) - ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) - : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc)); - break; - case 6: - v = ((4 == p->opsize) - ? (14 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) - : (10 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc)); - break; - case 7: - switch (r) { - case 0: - v = ((4 == p->opsize) - ? (12 * kCycleScale - + RdAvgXtraCyc + 2 * WrAvgXtraCyc) - : (8 * kCycleScale - + RdAvgXtraCyc + WrAvgXtraCyc)); - break; - case 1: - v = ((4 == p->opsize) - ? (16 * kCycleScale - + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc) - : (12 * kCycleScale - + 2 * RdAvgXtraCyc + WrAvgXtraCyc)); - break; - default: - v = 0; - break; - } - break; - default: /* keep compiler happy */ - v = 0; - break; - } - - return v; -} -#endif - -LOCALPROC SetDcoArgFields(WorkR *p, blnr src, - ui3r CurAMd, ui3r CurArgk, ui3r CurArgDat) -{ - ui5b *pv = src ? (&p->DecOp.B) : (&p->DecOp.A); - ui5r v = *pv; - - SetDcoFldArgDat(v, CurArgDat); - SetDcoFldAMd(v, CurAMd); - SetDcoFldArgk(v, CurArgk); - - *pv = v; -} - -LOCALFUNC MayNotInline blnr CheckValidAddrMode(WorkR *p, - ui3r m, ui3r r, ui3r v, blnr src) -{ - ui3r CurAMd = 0; /* init to keep compiler happy */ - ui3r CurArgk = 0; /* init to keep compiler happy */ - ui3r CurArgDat = 0; - blnr IsOk; - - switch (m) { - case 0: - CurAMd = kAMdReg; - CurArgk = GetArgkRegSz(p); - CurArgDat = r; - IsOk = CheckInSet(v, - kAddrValidMaskAny | kAddrValidMaskData - | kAddrValidMaskDataAlt); - break; - case 1: - CurAMd = kAMdReg; - CurArgk = GetArgkRegSz(p); - CurArgDat = r + 8; - IsOk = CheckInSet(v, kAddrValidMaskAny); - break; - case 2: - CurAMd = kAMdIndirect; - CurArgk = GetArgkMemSz(p); - CurArgDat = r + 8; - IsOk = CheckInSet(v, - kAddrValidMaskAny | kAddrValidMaskData - | kAddrValidMaskDataAlt | kAddrValidMaskControl - | kAddrValidMaskControlAlt | kAddrValidMaskAltMem); - break; - case 3: - switch (p->opsize) { - case 1: - if (7 == r) { - CurAMd = kAMdAPosIncW; - } else { - CurAMd = kAMdAPosIncB; - } - break; - case 2: - default: /* keep compiler happy */ - CurAMd = kAMdAPosIncW; - break; - case 4: - CurAMd = kAMdAPosIncL; - break; - } - CurArgk = GetArgkMemSz(p); - CurArgDat = r + 8; - IsOk = CheckInSet(v, - kAddrValidMaskAny | kAddrValidMaskData - | kAddrValidMaskDataAlt | kAddrValidMaskAltMem); - break; - case 4: - switch (p->opsize) { - case 1: - if (7 == r) { - CurAMd = kAMdAPreDecW; - } else { - CurAMd = kAMdAPreDecB; - } - break; - case 2: - default: /* keep compiler happy */ - CurAMd = kAMdAPreDecW; - break; - case 4: - CurAMd = kAMdAPreDecL; - break; - } - CurArgk = GetArgkMemSz(p); - CurArgDat = r + 8; - IsOk = CheckInSet(v, - kAddrValidMaskAny | kAddrValidMaskData - | kAddrValidMaskDataAlt | kAddrValidMaskAltMem); - break; - case 5: - CurAMd = kAMdADisp; - CurArgk = GetArgkMemSz(p); - CurArgDat = r + 8; - IsOk = CheckInSet(v, - kAddrValidMaskAny | kAddrValidMaskData - | kAddrValidMaskDataAlt | kAddrValidMaskControl - | kAddrValidMaskControlAlt | kAddrValidMaskAltMem); - break; - case 6: - CurAMd = kAMdAIndex; - CurArgk = GetArgkMemSz(p); - CurArgDat = r + 8; - IsOk = CheckInSet(v, - kAddrValidMaskAny | kAddrValidMaskData - | kAddrValidMaskDataAlt | kAddrValidMaskControl - | kAddrValidMaskControlAlt | kAddrValidMaskAltMem); - break; - case 7: - switch (r) { - case 0: - CurAMd = kAMdAbsW; - CurArgk = GetArgkMemSz(p); - IsOk = CheckInSet(v, - kAddrValidMaskAny | kAddrValidMaskData - | kAddrValidMaskDataAlt - | kAddrValidMaskControl - | kAddrValidMaskControlAlt - | kAddrValidMaskAltMem); - break; - case 1: - CurAMd = kAMdAbsL; - CurArgk = GetArgkMemSz(p); - IsOk = CheckInSet(v, - kAddrValidMaskAny | kAddrValidMaskData - | kAddrValidMaskDataAlt - | kAddrValidMaskControl - | kAddrValidMaskControlAlt - | kAddrValidMaskAltMem); - break; - case 2: - CurAMd = kAMdPCDisp; - CurArgk = GetArgkMemSz(p); - IsOk = CheckInSet(v, - kAddrValidMaskAny | kAddrValidMaskData - | kAddrValidMaskControl); - break; - case 3: - CurAMd = kAMdPCIndex; - CurArgk = GetArgkMemSz(p); - IsOk = CheckInSet(v, - kAddrValidMaskAny | kAddrValidMaskData - | kAddrValidMaskControl); - break; - case 4: - switch (p->opsize) { - case 1: - CurAMd = kAMdImmedB; - break; - case 2: - default: /* keep compiler happy */ - CurAMd = kAMdImmedW; - break; - case 4: - CurAMd = kAMdImmedL; - break; - } - CurArgk = kArgkCnst; - IsOk = CheckInSet(v, - kAddrValidMaskAny | kAddrValidMaskData); - break; - default: - IsOk = falseblnr; - break; - } - break; - default: /* keep compiler happy */ - IsOk = falseblnr; - break; - } - - if (IsOk) { - SetDcoArgFields(p, src, CurAMd, CurArgk, CurArgDat); - } - - return IsOk; -} - -#if WantCycByPriOp -LOCALFUNC MayNotInline blnr LeaPeaEACalcCyc(WorkR *p, ui3r m, ui3r r) -{ - ui4r v; - - UnusedParam(p); - switch (m) { - case 2: - v = 0; - break; - case 5: - v = (4 * kCycleScale + RdAvgXtraCyc); - break; - case 6: - v = (8 * kCycleScale + RdAvgXtraCyc); - break; - case 7: - switch (r) { - case 0: - v = (4 * kCycleScale + RdAvgXtraCyc); - break; - case 1: - v = (8 * kCycleScale + 2 * RdAvgXtraCyc); - break; - case 2: - v = (4 * kCycleScale + RdAvgXtraCyc); - break; - case 3: - v = (8 * kCycleScale + RdAvgXtraCyc); - break; - default: - v = 0; - break; - } - break; - default: /* keep compiler happy */ - v = 0; - break; - } - - return v; -} -#endif - -LOCALFUNC blnr IsValidAddrMode(WorkR *p) -{ - return CheckValidAddrMode(p, - mode(p), reg(p), kAddrValidAny, falseblnr); -} - -LOCALFUNC MayNotInline blnr CheckDataAltAddrMode(WorkR *p) -{ - return CheckValidAddrMode(p, - mode(p), reg(p), kAddrValidDataAlt, falseblnr); -} - -LOCALFUNC MayNotInline blnr CheckDataAddrMode(WorkR *p) -{ - return CheckValidAddrMode(p, - mode(p), reg(p), kAddrValidData, falseblnr); -} - -LOCALFUNC MayNotInline blnr CheckControlAddrMode(WorkR *p) -{ - return CheckValidAddrMode(p, - mode(p), reg(p), kAddrValidControl, falseblnr); -} - -LOCALFUNC MayNotInline blnr CheckControlAltAddrMode(WorkR *p) -{ - return CheckValidAddrMode(p, - mode(p), reg(p), kAddrValidControlAlt, falseblnr); -} - -LOCALFUNC MayNotInline blnr CheckAltMemAddrMode(WorkR *p) -{ - return CheckValidAddrMode(p, - mode(p), reg(p), kAddrValidAltMem, falseblnr); -} - -LOCALPROC FindOpSizeFromb76(WorkR *p) -{ - p->opsize = 1 << b76(p); -#if 0 - switch (b76(p)) { - case 0 : - p->opsize = 1; - break; - case 1 : - p->opsize = 2; - break; - case 2 : - p->opsize = 4; - break; - } -#endif -} - -LOCALFUNC ui3r OpSizeOffset(WorkR *p) -{ - ui3r v; - - switch (p->opsize) { - case 1 : - v = 0; - break; - case 2 : - v = 1; - break; - case 4 : - default : - v = 2; - break; - } - - return v; -} - - -LOCALFUNC ui5r octdat(ui5r x) -{ - if (x == 0) { - return 8; - } else { - return x; - } -} - -LOCALPROC MayInline DeCode0(WorkR *p) -{ - if (b8(p) == 1) { - if (mode(p) == 1) { - /* MoveP 0000ddd1mm001aaa */ -#if WantCycByPriOp - switch (b76(p)) { - case 0: - p->Cycles = (16 * kCycleScale + 4 * RdAvgXtraCyc); - break; - case 1: - p->Cycles = (24 * kCycleScale + 6 * RdAvgXtraCyc); - break; - case 2: - p->Cycles = (16 * kCycleScale - + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); - break; - case 3: - default: /* keep compiler happy */ - p->Cycles = (24 * kCycleScale - + 2 * RdAvgXtraCyc + 4 * WrAvgXtraCyc); - break; - } -#endif - p->MainClass = kIKindMoveP; - } else { - /* dynamic bit, Opcode = 0000ddd1ttmmmrrr */ - if (mode(p) == 0) { -#if WantCycByPriOp - switch (b76(p)) { - case 0: /* BTst */ - p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); - break; - case 1: /* BChg */ - p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); - break; - case 2: /* BClr */ - p->Cycles = (10 * kCycleScale + RdAvgXtraCyc); - break; - case 3: /* BSet */ - p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); - break; - } -#endif - p->MainClass = kIKindBitOpDD; - } else { - if (b76(p) == 0) { /* BTst */ - if (CheckDataAddrMode(p)) { -#if WantCycByPriOp - p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindBitOpDM; - } - } else { - if (CheckDataAltAddrMode(p)) { -#if WantCycByPriOp - p->Cycles = (8 * kCycleScale - + RdAvgXtraCyc + WrAvgXtraCyc); - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindBitOpDM; - } - } - } - } - } else { - if (rg9(p) == 4) { - /* static bit 00001010ssmmmrrr */ - if (mode(p) == 0) { -#if WantCycByPriOp - switch (b76(p)) { - case 0: /* BTst */ - p->Cycles = - (10 * kCycleScale + 2 * RdAvgXtraCyc); - break; - case 1: /* BChg */ - p->Cycles = - (12 * kCycleScale + 2 * RdAvgXtraCyc); - break; - case 2: /* BClr */ - p->Cycles = - (14 * kCycleScale + 2 * RdAvgXtraCyc); - break; - case 3: /* BSet */ - p->Cycles = - (12 * kCycleScale + 2 * RdAvgXtraCyc); - break; - } -#endif - p->MainClass = kIKindBitOpND; - } else { - if (b76(p) == 0) { /* BTst */ - if ((mode(p) == 7) && (reg(p) == 4)) { - p->MainClass = kIKindIllegal; - } else { - if (CheckDataAddrMode(p)) { -#if WantCycByPriOp - p->Cycles = - (8 * kCycleScale + 2 * RdAvgXtraCyc); - p->Cycles += - OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindBitOpNM; - } - } - } else { - if (CheckDataAltAddrMode(p)) { -#if WantCycByPriOp - p->Cycles = (12 * kCycleScale - + 2 * RdAvgXtraCyc + WrAvgXtraCyc); - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindBitOpNM; - } - } - } - } else - if (b76(p) == 3) { -#if Use68020 - if (rg9(p) < 3) { - /* CHK2 or CMP2 00000ss011mmmrrr */ - if (CheckControlAddrMode(p)) { -#if WantCycByPriOp - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindCHK2orCMP2; - } - } else - if (rg9(p) >= 5) { - if ((mode(p) == 7) && (reg(p) == 4)) { - /* CAS2 00001ss011111100 */ - p->MainClass = kIKindCAS2; - } else { - /* CAS 00001ss011mmmrrr */ - p->MainClass = kIKindCAS; - } - } else - if (rg9(p) == 3) { - /* CALLM or RTM 0000011011mmmrrr */ - p->MainClass = kIKindCallMorRtm; - } else -#endif - { - p->MainClass = kIKindIllegal; - } - } else - if (rg9(p) == 6) { - /* CMPI 00001100ssmmmrrr */ -#if 0 - if (CheckDataAltAddrMode(p)) { - p->MainClass = kIKindCmpI; - } -#endif - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, 7, 4, kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, - mode(p), reg(p), kAddrValidDataAlt, falseblnr)) - { -#if WantCycByPriOp - if (0 == mode(p)) { - p->Cycles = (4 == p->opsize) - ? (14 * kCycleScale + 3 * RdAvgXtraCyc) - : (8 * kCycleScale + 2 * RdAvgXtraCyc); - } else { - p->Cycles = (4 == p->opsize) - ? (12 * kCycleScale + 3 * RdAvgXtraCyc) - : (8 * kCycleScale + 2 * RdAvgXtraCyc); - } - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindCmpB + OpSizeOffset(p); - } - } else if (rg9(p) == 7) { -#if Use68020 - /* MoveS 00001110ssmmmrrr */ - if (CheckAltMemAddrMode(p)) { -#if WantCycByPriOp - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindMoveS; - } -#else - p->MainClass = kIKindIllegal; -#endif - } else { - if ((mode(p) == 7) && (reg(p) == 4)) { - switch (rg9(p)) { - case 0: - case 1: - case 5: -#if WantCycByPriOp - p->Cycles = - (20 * kCycleScale + 3 * RdAvgXtraCyc); -#endif - p->MainClass = kIKindBinOpStatusCCR; - break; - default: - p->MainClass = kIKindIllegal; - break; - } - } else { - switch (rg9(p)) { - case 0: -#if 0 - if (CheckDataAltAddrMode(p)) { - p->MainClass = kIKindOrI; - } -#endif - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, 7, 4, - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidDataAlt, falseblnr)) - { -#if WantCycByPriOp - if (0 != mode(p)) { - p->Cycles = (4 == p->opsize) - ? (20 * kCycleScale - + 3 * RdAvgXtraCyc - + 2 * WrAvgXtraCyc) - : (12 * kCycleScale - + 2 * RdAvgXtraCyc - + WrAvgXtraCyc); - } else { - p->Cycles = (4 == p->opsize) - ? (16 * kCycleScale - + 3 * RdAvgXtraCyc) - : (8 * kCycleScale - + 2 * RdAvgXtraCyc); - } - p->Cycles += - OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindOrI; - } - break; - case 1: -#if 0 - if (CheckDataAltAddrMode(p)) { - p->MainClass = kIKindAndI; - } -#endif - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, 7, 4, - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidDataAlt, falseblnr)) - { -#if WantCycByPriOp - if (0 != mode(p)) { - p->Cycles = (4 == p->opsize) - ? (20 * kCycleScale - + 3 * RdAvgXtraCyc - + 2 * WrAvgXtraCyc) - : (12 * kCycleScale - + 2 * RdAvgXtraCyc - + WrAvgXtraCyc); - } else { - p->Cycles = (4 == p->opsize) - ? (14 * kCycleScale - + 3 * RdAvgXtraCyc) - : (8 * kCycleScale - + 2 * RdAvgXtraCyc); - } - p->Cycles += - OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindAndI; - } - break; - case 2: -#if 0 - if (CheckDataAltAddrMode(p)) { - p->MainClass = kIKindSubI; - } -#endif - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, 7, 4, - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidDataAlt, falseblnr)) - { -#if WantCycByPriOp - if (0 != mode(p)) { - p->Cycles = (4 == p->opsize) - ? (20 * kCycleScale - + 3 * RdAvgXtraCyc - + 2 * WrAvgXtraCyc) - : (12 * kCycleScale - + 2 * RdAvgXtraCyc - + WrAvgXtraCyc); - } else { - p->Cycles = (4 == p->opsize) - ? (16 * kCycleScale - + 3 * RdAvgXtraCyc) - : (8 * kCycleScale - + 2 * RdAvgXtraCyc); - } - p->Cycles += - OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindSubB + OpSizeOffset(p); - } - break; - case 3: -#if 0 - if (CheckDataAltAddrMode(p)) { - p->MainClass = kIKindAddI; - } -#endif - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, 7, 4, - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidDataAlt, falseblnr)) - { -#if WantCycByPriOp - if (0 != mode(p)) { - p->Cycles = (4 == p->opsize) - ? (20 * kCycleScale - + 3 * RdAvgXtraCyc - + 2 * WrAvgXtraCyc) - : (12 * kCycleScale - + 2 * RdAvgXtraCyc - + WrAvgXtraCyc); - } else { - p->Cycles = (4 == p->opsize) - ? (16 * kCycleScale - + 3 * RdAvgXtraCyc) - : (8 * kCycleScale - + 2 * RdAvgXtraCyc); - } - p->Cycles += - OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindAddB + OpSizeOffset(p); - } - break; - case 5: -#if 0 - if (CheckDataAltAddrMode(p)) { - p->MainClass = kIKindEorI; - } -#endif - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, 7, 4, - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidDataAlt, falseblnr)) - { -#if WantCycByPriOp - if (0 != mode(p)) { - p->Cycles = (4 == p->opsize) - ? (20 * kCycleScale - + 3 * RdAvgXtraCyc - + 2 * WrAvgXtraCyc) - : (12 * kCycleScale - + 2 * RdAvgXtraCyc - + WrAvgXtraCyc); - } else { - p->Cycles = (4 == p->opsize) - ? (16 * kCycleScale - + 3 * RdAvgXtraCyc) - : (8 * kCycleScale - + 2 * RdAvgXtraCyc); - } - p->Cycles += - OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindEorI; - } - break; - default: - /* for compiler. should be 0, 1, 2, 3, or 5 */ - p->MainClass = kIKindIllegal; - break; - } - } - } - } -} - -LOCALPROC MayInline DeCode1(WorkR *p) -{ - p->opsize = 1; - if (md6(p) == 1) { /* MOVEA */ - p->MainClass = kIKindIllegal; - } else if (mode(p) == 1) { - /* not allowed for byte sized move */ - p->MainClass = kIKindIllegal; - } else { - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, md6(p), rg9(p), - kAddrValidDataAlt, falseblnr)) - { -#if WantCycByPriOp - p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); - p->Cycles += OpEADestCalcCyc(p, md6(p), rg9(p)); -#endif - p->MainClass = kIKindMoveB; - } - } -} - -LOCALPROC MayInline DeCode2(WorkR *p) -{ - p->opsize = 4; - if (md6(p) == 1) { /* MOVEA */ - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, 1, rg9(p), - kAddrValidAny, falseblnr)) - { -#if WantCycByPriOp - p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindMoveAL; - } - } else { - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, md6(p), rg9(p), - kAddrValidDataAlt, falseblnr)) - { -#if WantCycByPriOp - p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); - p->Cycles += OpEADestCalcCyc(p, md6(p), rg9(p)); -#endif - p->MainClass = kIKindMoveL; - } - } -} - -LOCALPROC MayInline DeCode3(WorkR *p) -{ - p->opsize = 2; - if (md6(p) == 1) { /* MOVEA */ - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, 1, rg9(p), - kAddrValidAny, falseblnr)) - { -#if WantCycByPriOp - p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindMoveAW; - } - } else { - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, md6(p), rg9(p), - kAddrValidDataAlt, falseblnr)) - { -#if WantCycByPriOp - p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); - p->Cycles += OpEADestCalcCyc(p, md6(p), rg9(p)); -#endif - p->MainClass = kIKindMoveW; - } - } -} - -#if WantCycByPriOp - -#if WantCloserCyc -#define MoveAvgN 0 -#else -#define MoveAvgN 3 -#endif - -LOCALFUNC MayNotInline ui4r MoveMEACalcCyc(WorkR *p, ui3r m, ui3r r) -{ - ui4r v; - - UnusedParam(p); - switch (m) { - case 2: - case 3: - case 4: - v = (8 * kCycleScale + 2 * RdAvgXtraCyc); - break; - case 5: - v = (12 * kCycleScale + 3 * RdAvgXtraCyc); - break; - case 6: - v = (14 * kCycleScale + 3 * RdAvgXtraCyc); - break; - case 7: - switch (r) { - case 0: - v = (12 * kCycleScale + 3 * RdAvgXtraCyc); - break; - case 1: - v = (16 * kCycleScale + 4 * RdAvgXtraCyc); - break; - default: - v = 0; - break; - } - break; - default: /* keep compiler happy */ - v = 0; - break; - } - - return v; -} - -#endif - -LOCALPROC MayInline DeCode4(WorkR *p) -{ - if (b8(p) != 0) { - switch (b76(p)) { - case 0: -#if Use68020 - /* Chk.L 0100ddd100mmmrrr */ - if (CheckDataAddrMode(p)) { -#if WantCycByPriOp - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindChkL; - } -#else - p->MainClass = kIKindIllegal; -#endif - break; - case 1: - p->MainClass = kIKindIllegal; - break; - case 2: - /* Chk.W 0100ddd110mmmrrr */ - if (CheckDataAddrMode(p)) { -#if WantCycByPriOp - p->Cycles = (10 * kCycleScale + RdAvgXtraCyc); - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindChkW; - } - break; - case 3: - default: /* keep compiler happy */ -#if Use68020 - if ((0 == mode(p)) && (4 == rg9(p))) { - p->MainClass = kIKindEXTBL; - } else -#endif - { - /* Lea 0100aaa111mmmrrr */ - if (CheckControlAddrMode(p)) { -#if WantCycByPriOp - p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); - p->Cycles += - LeaPeaEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindLea; - } - } - break; - } - } else { - switch (rg9(p)) { - case 0: - if (b76(p) != 3) { - /* NegX 01000000ssmmmrrr */ - FindOpSizeFromb76(p); - if (CheckDataAltAddrMode(p)) { -#if WantCycByPriOp - if (0 != mode(p)) { - p->Cycles = (4 == p->opsize) - ? (12 * kCycleScale - + RdAvgXtraCyc + 2 * WrAvgXtraCyc) - : (8 * kCycleScale - + RdAvgXtraCyc + WrAvgXtraCyc); - } else { - p->Cycles = (4 == p->opsize) - ? (6 * kCycleScale + RdAvgXtraCyc) - : (4 * kCycleScale + RdAvgXtraCyc); - } - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindNegXB + OpSizeOffset(p); - } - } else { -#if Use68020 -/* reference seems incorrect to say not for 68000 */ -#endif - /* Move from SR 0100000011mmmrrr */ - if (CheckDataAltAddrMode(p)) { -#if WantCycByPriOp - p->Cycles = - (12 * kCycleScale + 2 * RdAvgXtraCyc); - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindMoveSREa; - } - } - break; - case 1: - if (b76(p) != 3) { - /* Clr 01000010ssmmmrrr */ - FindOpSizeFromb76(p); - if (CheckDataAltAddrMode(p)) { -#if WantCycByPriOp - if (0 != mode(p)) { - p->Cycles = (4 == p->opsize) - ? (12 * kCycleScale - + RdAvgXtraCyc + 2 * WrAvgXtraCyc) - : (8 * kCycleScale - + RdAvgXtraCyc + WrAvgXtraCyc); - } else { - p->Cycles = (4 == p->opsize) - ? (6 * kCycleScale + RdAvgXtraCyc) - : (4 * kCycleScale + RdAvgXtraCyc); - } - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindClr; - } - } else { -#if Use68020 - /* Move from CCR 0100001011mmmrrr */ - if (CheckDataAltAddrMode(p)) { -#if WantCycByPriOp - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindMoveCCREa; - } -#else - p->MainClass = kIKindIllegal; -#endif - } - break; - case 2: - if (b76(p) != 3) { - /* Neg 01000100ssmmmrrr */ - FindOpSizeFromb76(p); - if (CheckDataAltAddrMode(p)) { -#if WantCycByPriOp - if (0 != mode(p)) { - p->Cycles = (4 == p->opsize) - ? (12 * kCycleScale - + RdAvgXtraCyc + 2 * WrAvgXtraCyc) - : (8 * kCycleScale - + RdAvgXtraCyc + WrAvgXtraCyc); - } else { - p->Cycles = (4 == p->opsize) - ? (6 * kCycleScale + RdAvgXtraCyc) - : (4 * kCycleScale + RdAvgXtraCyc); - } - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindNegB + OpSizeOffset(p); - } - } else { - /* Move to CCR 0100010011mmmrrr */ - if (CheckDataAddrMode(p)) { -#if WantCycByPriOp - p->Cycles = (12 * kCycleScale + RdAvgXtraCyc); - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindMoveEaCCR; - } - } - break; - case 3: - if (b76(p) != 3) { - /* Not 01000110ssmmmrrr */ - FindOpSizeFromb76(p); - if (CheckDataAltAddrMode(p)) { -#if WantCycByPriOp - if (0 != mode(p)) { - p->Cycles = (4 == p->opsize) - ? (12 * kCycleScale - + RdAvgXtraCyc + 2 * WrAvgXtraCyc) - : (8 * kCycleScale - + RdAvgXtraCyc + WrAvgXtraCyc); - } else { - p->Cycles = (4 == p->opsize) - ? (6 * kCycleScale + RdAvgXtraCyc) - : (4 * kCycleScale + RdAvgXtraCyc); - } - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindNot; - } - } else { - /* Move from SR 0100011011mmmrrr */ - if (CheckDataAddrMode(p)) { -#if WantCycByPriOp - if (0 != mode(p)) { - p->Cycles = (8 * kCycleScale - + RdAvgXtraCyc + WrAvgXtraCyc); - } else { - p->Cycles = - (6 * kCycleScale + RdAvgXtraCyc); - } - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindMoveEaSR; - } - } - break; - case 4: - switch (b76(p)) { - case 0: -#if Use68020 - if (mode(p) == 1) { - /* Link.L 0100100000001rrr */ - p->MainClass = kIKindLinkL; - } else -#endif - { - /* Nbcd 0100100000mmmrrr */ - if (CheckDataAltAddrMode(p)) { -#if WantCycByPriOp - if (0 != mode(p)) { - p->Cycles = (8 * kCycleScale - + RdAvgXtraCyc + WrAvgXtraCyc); - } else { - p->Cycles = (6 * kCycleScale - + RdAvgXtraCyc); - } - p->Cycles += - OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindNbcd; - } - } - break; - case 1: - if (mode(p) == 0) { - /* Swap 0100100001000rrr */ -#if WantCycByPriOp - p->Cycles = - (4 * kCycleScale + RdAvgXtraCyc); -#endif - p->MainClass = kIKindSwap; - } else -#if Use68020 - if (mode(p) == 1) { - p->MainClass = kIKindBkpt; - } else -#endif - { - /* PEA 0100100001mmmrrr */ - if (CheckControlAddrMode(p)) { -#if WantCycByPriOp - p->Cycles = (12 * kCycleScale - + RdAvgXtraCyc - + 2 * WrAvgXtraCyc); - p->Cycles += - LeaPeaEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindPEA; - } - } - break; - case 2: - if (mode(p) == 0) { - /* EXT.W */ -#if WantCycByPriOp - p->Cycles = - (4 * kCycleScale + RdAvgXtraCyc); -#endif - p->MainClass = kIKindEXTW; - } else { - /* MOVEM reg to mem 01001d001ssmmmrrr */ - if (mode(p) == 4) { -#if WantCycByPriOp - p->Cycles = - MoveMEACalcCyc(p, mode(p), reg(p)); - p->Cycles += MoveAvgN * 4 * kCycleScale - + MoveAvgN * WrAvgXtraCyc; -#endif - p->MainClass = kIKindMOVEMRmMW; - } else { - if (CheckControlAltAddrMode(p)) { -#if WantCycByPriOp - p->Cycles = MoveMEACalcCyc(p, - mode(p), reg(p)); - p->Cycles += - MoveAvgN * 4 * kCycleScale - + MoveAvgN * WrAvgXtraCyc; -#endif - p->MainClass = kIKindMOVEMrm; - } - } - } - break; - case 3: - default: /* keep compiler happy */ - if (mode(p) == 0) { - /* EXT.L */ -#if WantCycByPriOp - p->Cycles = - (4 * kCycleScale + RdAvgXtraCyc); -#endif - p->MainClass = kIKindEXTL; - } else { - /* MOVEM reg to mem 01001d001ssmmmrrr */ - if (mode(p) == 4) { -#if WantCycByPriOp - p->Cycles = MoveMEACalcCyc(p, - mode(p), reg(p)); - p->Cycles += MoveAvgN * 8 * kCycleScale - + MoveAvgN * 2 * WrAvgXtraCyc; -#endif - p->MainClass = kIKindMOVEMRmML; - } else { - if (CheckControlAltAddrMode(p)) { -#if WantCycByPriOp - p->Cycles = MoveMEACalcCyc(p, - mode(p), reg(p)); - p->Cycles += - MoveAvgN * 8 * kCycleScale - + MoveAvgN * 2 * WrAvgXtraCyc; -#endif - p->MainClass = kIKindMOVEMrm; - } - } - } - break; - } - break; - case 5: - if (b76(p) == 3) { - if ((mode(p) == 7) && (reg(p) == 4)) { - /* the ILLEGAL instruction */ - p->MainClass = kIKindIllegal; - } else { - /* Tas 0100101011mmmrrr */ - if (CheckDataAltAddrMode(p)) { -#if WantCycByPriOp - if (0 != mode(p)) { - p->Cycles = (14 * kCycleScale - + 2 * RdAvgXtraCyc + WrAvgXtraCyc); - } else { - p->Cycles = (4 * kCycleScale - + RdAvgXtraCyc); - } - p->Cycles += - OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindTas; - } - } - } else { - /* Tst 01001010ssmmmrrr */ - FindOpSizeFromb76(p); - if (b76(p) == 0) { - if (CheckDataAltAddrMode(p)) { -#if WantCycByPriOp - p->Cycles = - (4 * kCycleScale + RdAvgXtraCyc); - p->Cycles += - OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindTst; - } - } else { - if (IsValidAddrMode(p)) { -#if WantCycByPriOp - p->Cycles = - (4 * kCycleScale + RdAvgXtraCyc); - p->Cycles += - OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindTst; - } - } - } - break; - case 6: - if (((p->opcode >> 7) & 1) == 1) { - /* MOVEM mem to reg 0100110011smmmrrr */ - FindOpSizeFromb76(p); - if (mode(p) == 3) { -#if WantCycByPriOp - p->Cycles = 4 * kCycleScale + RdAvgXtraCyc; - p->Cycles += MoveMEACalcCyc(p, mode(p), reg(p)); - if (4 == p->opsize) { - p->Cycles += MoveAvgN * 8 * kCycleScale - + 2 * MoveAvgN * RdAvgXtraCyc; - } else { - p->Cycles += MoveAvgN * 4 * kCycleScale - + MoveAvgN * RdAvgXtraCyc; - } -#endif - if (b76(p) == 2) { - p->MainClass = kIKindMOVEMApRW; - } else { - p->MainClass = kIKindMOVEMApRL; - } - } else { - if (CheckControlAddrMode(p)) { -#if WantCycByPriOp - p->Cycles = 4 * kCycleScale + RdAvgXtraCyc; - p->Cycles += MoveMEACalcCyc(p, - mode(p), reg(p)); - if (4 == p->opsize) { - p->Cycles += MoveAvgN * 8 * kCycleScale - + 2 * MoveAvgN * RdAvgXtraCyc; - } else { - p->Cycles += MoveAvgN * 4 * kCycleScale - + MoveAvgN * RdAvgXtraCyc; - } -#endif - p->MainClass = kIKindMOVEMmr; - } - } - } else { -#if Use68020 - if (((p->opcode >> 6) & 1) == 1) { - /* DIVU 0100110001mmmrrr 0rrr0s0000000rrr */ - /* DIVS 0100110001mmmrrr 0rrr1s0000000rrr */ - p->MainClass = kIKindDivL; - } else { - /* MULU 0100110000mmmrrr 0rrr0s0000000rrr */ - /* MULS 0100110000mmmrrr 0rrr1s0000000rrr */ - p->MainClass = kIKindMulL; - } -#else - p->MainClass = kIKindIllegal; -#endif - } - break; - case 7: - default: /* keep compiler happy */ - switch (b76(p)) { - case 0: - p->MainClass = kIKindIllegal; - break; - case 1: - switch (mode(p)) { - case 0: - case 1: - /* Trap 010011100100vvvv */ -#if WantCycByPriOp - p->Cycles = (34 * kCycleScale - + 4 * RdAvgXtraCyc - + 3 * WrAvgXtraCyc); -#endif - p->MainClass = kIKindTrap; - break; - case 2: - /* Link */ -#if WantCycByPriOp - p->Cycles = (16 * kCycleScale - + 2 * RdAvgXtraCyc - + 2 * WrAvgXtraCyc); -#endif - if (reg(p) == 6) { - p->MainClass = kIKindLinkA6; - } else { - p->MainClass = kIKindLink; - } - break; - case 3: - /* Unlk */ -#if WantCycByPriOp - p->Cycles = (12 * kCycleScale - + 3 * RdAvgXtraCyc); -#endif - if (reg(p) == 6) { - p->MainClass = kIKindUnlkA6; - } else { - p->MainClass = kIKindUnlk; - } - break; - case 4: - /* MOVE USP 0100111001100aaa */ -#if WantCycByPriOp - p->Cycles = - (4 * kCycleScale + RdAvgXtraCyc); -#endif - p->MainClass = kIKindMoveRUSP; - break; - case 5: - /* MOVE USP 0100111001101aaa */ -#if WantCycByPriOp - p->Cycles = - (4 * kCycleScale + RdAvgXtraCyc); -#endif - p->MainClass = kIKindMoveUSPR; - break; - case 6: - switch (reg(p)) { - case 0: - /* Reset 0100111001100000 */ -#if WantCycByPriOp - p->Cycles = (132 * kCycleScale - + RdAvgXtraCyc); -#endif - p->MainClass = kIKindReset; - break; - case 1: - /* Nop = 0100111001110001 */ -#if WantCycByPriOp - p->Cycles = (4 * kCycleScale - + RdAvgXtraCyc); -#endif - p->MainClass = kIKindNop; - break; - case 2: - /* Stop 0100111001110010 */ -#if WantCycByPriOp - p->Cycles = (4 * kCycleScale); -#endif - p->MainClass = kIKindStop; - break; - case 3: - /* Rte 0100111001110011 */ -#if WantCycByPriOp - p->Cycles = (20 * kCycleScale - + 5 * RdAvgXtraCyc); -#endif - p->MainClass = kIKindRte; - break; - case 4: - /* Rtd 0100111001110100 */ -#if Use68020 - p->MainClass = kIKindRtd; -#else - p->MainClass = kIKindIllegal; -#endif - break; - case 5: - /* Rts 0100111001110101 */ -#if WantCycByPriOp - p->Cycles = (16 * kCycleScale - + 4 * RdAvgXtraCyc); -#endif - p->MainClass = kIKindRts; - break; - case 6: - /* TrapV 0100111001110110 */ -#if WantCycByPriOp - p->Cycles = (4 * kCycleScale - + RdAvgXtraCyc); -#endif - p->MainClass = kIKindTrapV; - break; - case 7: - default: /* keep compiler happy */ - /* Rtr 0100111001110111 */ -#if WantCycByPriOp - p->Cycles = (20 * kCycleScale - + 2 * RdAvgXtraCyc); -#endif - p->MainClass = kIKindRtr; - break; - } - break; - case 7: - default: /* keep compiler happy */ -#if Use68020 - /* MOVEC 010011100111101m */ - p->MainClass = kIKindMoveC; -#else - p->MainClass = kIKindIllegal; -#endif - break; - } - break; - case 2: - /* Jsr 0100111010mmmrrr */ - if (CheckControlAddrMode(p)) { -#if WantCycByPriOp - switch (mode(p)) { - case 2: - p->Cycles = (16 * kCycleScale - + 2 * RdAvgXtraCyc - + 2 * WrAvgXtraCyc); - break; - case 5: - p->Cycles = (18 * kCycleScale - + 2 * RdAvgXtraCyc - + 2 * WrAvgXtraCyc); - break; - case 6: - p->Cycles = (22 * kCycleScale - + 2 * RdAvgXtraCyc - + 2 * WrAvgXtraCyc); - break; - case 7: - default: /* keep compiler happy */ - switch (reg(p)) { - case 0: - p->Cycles = - (18 * kCycleScale - + 2 * RdAvgXtraCyc - + 2 * WrAvgXtraCyc); - break; - case 1: - p->Cycles = - (20 * kCycleScale - + 3 * RdAvgXtraCyc - + 2 * WrAvgXtraCyc); - break; - case 2: - p->Cycles = - (18 * kCycleScale - + 2 * RdAvgXtraCyc - + 2 * WrAvgXtraCyc); - break; - case 3: - default: - /* keep compiler happy */ - p->Cycles = - (22 * kCycleScale - + 2 * RdAvgXtraCyc - + 2 * WrAvgXtraCyc); - break; - } - break; - } -#endif - p->MainClass = kIKindJsr; - } - break; - case 3: - default: /* keep compiler happy */ - /* JMP 0100111011mmmrrr */ - if (CheckControlAddrMode(p)) { -#if WantCycByPriOp - switch (mode(p)) { - case 2: - p->Cycles = (8 * kCycleScale - + 2 * RdAvgXtraCyc); - break; - case 5: - p->Cycles = (10 * kCycleScale - + 2 * RdAvgXtraCyc); - break; - case 6: - p->Cycles = (14 * kCycleScale - + 2 * RdAvgXtraCyc); - break; - case 7: - default: /* keep compiler happy */ - switch (reg(p)) { - case 0: - p->Cycles = - (10 * kCycleScale - + 2 * RdAvgXtraCyc); - break; - case 1: - p->Cycles = - (12 * kCycleScale - + 3 * RdAvgXtraCyc); - break; - case 2: - p->Cycles = - (10 * kCycleScale - + 2 * RdAvgXtraCyc); - break; - case 3: - default: - /* keep compiler happy */ - p->Cycles = - (14 * kCycleScale - + 3 * RdAvgXtraCyc); - break; - } - break; - } -#endif - p->MainClass = kIKindJmp; - } - break; - } - break; - } - } -} - -LOCALPROC MayInline DeCode5(WorkR *p) -{ - if (b76(p) == 3) { - if (mode(p) == 1) { - /* DBcc 0101cccc11001ddd */ -#if WantCycByPriOp -#if WantCloserCyc - p->Cycles = 0; -#else - p->Cycles = (11 * kCycleScale + 2 * RdAvgXtraCyc); - /* - average of cc true 12(2/0), - cc false taken 10(2/0), - and not 14(3/0) - */ -#endif -#endif - if (1 == ((p->opcode >> 8) & 15)) { - p->MainClass = kIKindDBF; - } else { - p->MainClass = kIKindDBcc; - } - } else { -#if Use68020 - if ((mode(p) == 7) && (reg(p) >= 2)) { - /* TRAPcc 0101cccc11111sss */ - p->MainClass = kIKindTRAPcc; - } else -#endif - { - p->opsize = 1; - /* Scc 0101cccc11mmmrrr */ - if (CheckDataAltAddrMode(p)) { -#if WantCycByPriOp - if (0 != mode(p)) { - p->Cycles = (8 * kCycleScale - + RdAvgXtraCyc + WrAvgXtraCyc); - } else { -#if WantCloserCyc - p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); -#else - p->Cycles = (5 * kCycleScale + RdAvgXtraCyc); - /* 4 when false, 6 when true */ -#endif - } - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindScc; - } - } - } - } else { - if (mode(p) == 1) { - p->opsize = b8(p) * 2 + 2; - SetDcoArgFields(p, trueblnr, kAMdDat4, - kArgkCnst, octdat(rg9(p))); - SetDcoArgFields(p, falseblnr, kAMdReg, - kArgkRegL, reg(p) + 8); - /* always long, regardless of opsize */ - if (b8(p) == 0) { -#if WantCycByPriOp - p->Cycles = (4 == p->opsize) - ? (8 * kCycleScale + RdAvgXtraCyc) - : (4 * kCycleScale + RdAvgXtraCyc); -#endif - p->MainClass = kIKindAddQA; /* AddQA 0101nnn0ss001rrr */ - } else { -#if WantCycByPriOp - p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); -#endif - p->MainClass = kIKindSubQA; /* SubQA 0101nnn1ss001rrr */ - } - } else { - FindOpSizeFromb76(p); - SetDcoArgFields(p, trueblnr, kAMdDat4, - kArgkCnst, octdat(rg9(p))); - if (CheckValidAddrMode(p, - mode(p), reg(p), kAddrValidDataAlt, falseblnr)) - { -#if WantCycByPriOp - if (0 != mode(p)) { - p->Cycles = (4 == p->opsize) - ? (12 * kCycleScale - + RdAvgXtraCyc + 2 * WrAvgXtraCyc) - : (8 * kCycleScale - + RdAvgXtraCyc + WrAvgXtraCyc); - } else { - p->Cycles = (4 == p->opsize) - ? (8 * kCycleScale + RdAvgXtraCyc) - : (4 * kCycleScale + RdAvgXtraCyc); - } - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - if (b8(p) == 0) { - /* AddQ 0101nnn0ssmmmrrr */ -#if 0 - if (CheckDataAltAddrMode(p)) { - p->MainClass = kIKindAddQ; - } -#endif - p->MainClass = kIKindAddB + OpSizeOffset(p); - } else { - /* SubQ 0101nnn1ssmmmrrr */ -#if 0 - if (CheckDataAltAddrMode(p)) { - p->MainClass = kIKindSubQ; - } -#endif - p->MainClass = kIKindSubB + OpSizeOffset(p); - } - } - } - } -} - -LOCALPROC MayInline DeCode6(WorkR *p) -{ - ui5b cond = (p->opcode >> 8) & 15; - - if (cond == 1) { - /* Bsr 01100001nnnnnnnn */ -#if WantCycByPriOp - p->Cycles = (18 * kCycleScale - + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); -#endif - if (0 == (p->opcode & 255)) { - p->MainClass = kIKindBsrW; - } else -#if Use68020 - if (255 == (p->opcode & 255)) { - p->MainClass = kIKindBsrL; - } else -#endif - { - p->MainClass = kIKindBsrB; - } - } else if (cond == 0) { - /* Bra 01100000nnnnnnnn */ -#if WantCycByPriOp - p->Cycles = (10 * kCycleScale + 2 * RdAvgXtraCyc); -#endif - if (0 == (p->opcode & 255)) { - p->MainClass = kIKindBraW; - } else -#if Use68020 - if (255 == (p->opcode & 255)) { - p->MainClass = kIKindBraL; - } else -#endif - { - p->MainClass = kIKindBraB; - } - } else { - /* Bcc 0110ccccnnnnnnnn */ - if (0 == (p->opcode & 255)) { -#if WantCycByPriOp -#if WantCloserCyc - p->Cycles = 0; -#else - p->Cycles = (11 * kCycleScale + 2 * RdAvgXtraCyc); - /* average of branch taken 10(2/0) and not 12(2/0) */ -#endif -#endif - p->MainClass = kIKindBccW; - } else -#if Use68020 - if (255 == (p->opcode & 255)) { - p->MainClass = kIKindBccL; - } else -#endif - { -#if WantCycByPriOp -#if WantCloserCyc - p->Cycles = 0; -#else - p->Cycles = (9 * kCycleScale - + RdAvgXtraCyc + (RdAvgXtraCyc / 2)); - /* average of branch taken 10(2/0) and not 8(1/0) */ -#endif -#endif - p->MainClass = kIKindBccB; - } - } -} - -LOCALPROC MayInline DeCode7(WorkR *p) -{ - if (b8(p) == 0) { - p->opsize = 4; -#if WantCycByPriOp - p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); -#endif - p->MainClass = kIKindMoveQ; - } else { - p->MainClass = kIKindIllegal; - } -} - -LOCALPROC MayInline DeCode8(WorkR *p) -{ - if (b76(p) == 3) { - p->opsize = 2; - if (CheckDataAddrMode(p)) { - if (b8(p) == 0) { - /* DivU 1000ddd011mmmrrr */ -#if WantCycByPriOp - p->Cycles = RdAvgXtraCyc; - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#if ! WantCloserCyc - p->Cycles += 133 * kCycleScale; - /* - worse case 140, less than ten percent - different from best case - */ -#endif -#endif - p->MainClass = kIKindDivU; - } else { - /* DivS 1000ddd111mmmrrr */ -#if WantCycByPriOp - p->Cycles = RdAvgXtraCyc; - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#if ! WantCloserCyc - p->Cycles += 150 * kCycleScale; - /* - worse case 158, less than ten percent different - from best case - */ -#endif -#endif - p->MainClass = kIKindDivS; - } - } - } else { - if (b8(p) == 0) { - /* OR 1000ddd0ssmmmrrr */ -#if 0 - if (CheckDataAddrMode(p)) { - p->MainClass = kIKindOrEaD; - } -#endif - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidData, trueblnr)) - if (CheckValidAddrMode(p, 0, rg9(p), - kAddrValidAny, falseblnr)) - { -#if WantCycByPriOp - if (4 == p->opsize) { - if ((mode(p) < 2) - || ((7 == mode(p)) && (reg(p) == 4))) - { - p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); - } else { - p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); - } - } else { - p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); - } - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindOrEaD; - } - } else { - if (mode(p) < 2) { - switch (b76(p)) { - case 0: - /* SBCD 1000xxx10000mxxx */ -#if WantCycByPriOp - if (0 != mode(p)) { - p->Cycles = (18 * kCycleScale - + 3 * RdAvgXtraCyc + WrAvgXtraCyc); - } else { - p->Cycles = (6 * kCycleScale - + RdAvgXtraCyc); - } -#endif - if (mode(p) == 0) { - p->MainClass = kIKindSbcdr; - } else { - p->MainClass = kIKindSbcdm; - } - break; -#if Use68020 - case 1: - /* PACK 1000rrr10100mrrr */ - p->MainClass = kIKindPack; - break; - case 2: - /* UNPK 1000rrr11000mrrr */ - p->MainClass = kIKindUnpk; - break; -#endif - default: - p->MainClass = kIKindIllegal; - break; - } - } else { - /* OR 1000ddd1ssmmmrrr */ -#if 0 - if (CheckDataAltAddrMode(p)) { - p->MainClass = kIKindOrDEa; - } -#endif - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, 0, rg9(p), - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidAltMem, falseblnr)) - { -#if WantCycByPriOp - p->Cycles = (4 == p->opsize) - ? (12 * kCycleScale - + RdAvgXtraCyc + 2 * WrAvgXtraCyc) - : (8 * kCycleScale - + RdAvgXtraCyc + WrAvgXtraCyc); - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindOrDEa; - } - } - } - } -} - -LOCALPROC MayInline DeCode9(WorkR *p) -{ - if (b76(p) == 3) { - /* SUBA 1001dddm11mmmrrr */ -#if 0 - if (IsValidAddrMode(p)) { - p->MainClass = kIKindSubA; - } -#endif - p->opsize = b8(p) * 2 + 2; - SetDcoArgFields(p, falseblnr, kAMdReg, kArgkRegL, rg9(p) + 8); - /* always long, regardless of opsize */ - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidAny, trueblnr)) - { -#if WantCycByPriOp - if (4 == p->opsize) { - if ((mode(p) < 2) || ((7 == mode(p)) && (reg(p) == 4))) - { - p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); - } else { - p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); - } - } else { - p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); - } - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindSubA; - } - } else { - if (b8(p) == 0) { - /* SUB 1001ddd0ssmmmrrr */ -#if 0 - if (IsValidAddrMode(p)) { - p->MainClass = kIKindSubEaR; - } -#endif - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, 0, rg9(p), - kAddrValidAny, falseblnr)) - { -#if WantCycByPriOp - if (4 == p->opsize) { - if ((mode(p) < 2) - || ((7 == mode(p)) && (reg(p) == 4))) - { - p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); - } else { - p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); - } - } else { - p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); - } - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindSubB + OpSizeOffset(p); - } - } else { - if (mode(p) == 0) { - /* SUBX 1001ddd1ss000rrr */ - /* p->MainClass = kIKindSubXd; */ - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, 0, reg(p), - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, 0, rg9(p), - kAddrValidAny, falseblnr)) - { -#if WantCycByPriOp - p->Cycles = (4 == p->opsize) - ? (8 * kCycleScale + RdAvgXtraCyc) - : (4 * kCycleScale + RdAvgXtraCyc); -#endif - p->MainClass = kIKindSubXB + OpSizeOffset(p); - } - } else if (mode(p) == 1) { - /* SUBX 1001ddd1ss001rrr */ - /* p->MainClass = kIKindSubXm; */ - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, 4, reg(p), - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, 4, rg9(p), - kAddrValidAny, falseblnr)) - { -#if WantCycByPriOp - p->Cycles = (4 == p->opsize) - ? (30 * kCycleScale - + 5 * RdAvgXtraCyc + 2 * WrAvgXtraCyc) - : (18 * kCycleScale - + 3 * RdAvgXtraCyc + 1 * WrAvgXtraCyc); -#endif - p->MainClass = kIKindSubXB + OpSizeOffset(p); - } - } else { - /* SUB 1001ddd1ssmmmrrr */ -#if 0 - if (CheckAltMemAddrMode(p)) { - p->MainClass = kIKindSubREa; - } -#endif - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, 0, rg9(p), - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, mode(p), - reg(p), kAddrValidAltMem, falseblnr)) - { -#if WantCycByPriOp - p->Cycles = (4 == p->opsize) - ? (12 * kCycleScale - + RdAvgXtraCyc + 2 * WrAvgXtraCyc) - : (8 * kCycleScale - + RdAvgXtraCyc + WrAvgXtraCyc); - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindSubB + OpSizeOffset(p); - } - } - } - } -} - -LOCALPROC MayInline DeCodeA(WorkR *p) -{ -#if WantCycByPriOp - p->Cycles = (34 * kCycleScale - + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); -#endif - p->MainClass = kIKindA; -} - -LOCALPROC MayInline DeCodeB(WorkR *p) -{ - if (b76(p) == 3) { - /* CMPA 1011ddds11mmmrrr */ -#if 0 - if (IsValidAddrMode(p)) { - p->MainClass = kIKindCmpA; - } -#endif - p->opsize = b8(p) * 2 + 2; - SetDcoArgFields(p, falseblnr, kAMdReg, kArgkRegL, rg9(p) + 8); - /* always long, regardless of opsize */ - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidAny, trueblnr)) - { -#if WantCycByPriOp - p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindCmpA; - } - } else if (b8(p) == 1) { - if (mode(p) == 1) { - /* CmpM 1011ddd1ss001rrr */ -#if 0 - p->MainClass = kIKindCmpM; -#endif - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, 3, reg(p), - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, 3, rg9(p), - kAddrValidAny, falseblnr)) - { -#if WantCycByPriOp - p->Cycles = (4 == p->opsize) - ? (20 * kCycleScale + 5 * RdAvgXtraCyc) - : (12 * kCycleScale + 3 * RdAvgXtraCyc); -#endif - p->MainClass = kIKindCmpB + OpSizeOffset(p); - } - } else { -#if 0 - /* Eor 1011ddd1ssmmmrrr */ - if (CheckDataAltAddrMode(p)) { - p->MainClass = kIKindEor; - } -#endif - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, 0, rg9(p), - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidDataAlt, falseblnr)) - { -#if WantCycByPriOp - if (0 != mode(p)) { - p->Cycles = (4 == p->opsize) - ? (12 * kCycleScale - + RdAvgXtraCyc + 2 * WrAvgXtraCyc) - : (8 * kCycleScale - + RdAvgXtraCyc + WrAvgXtraCyc); - } else { - p->Cycles = (4 == p->opsize) - ? (8 * kCycleScale + RdAvgXtraCyc) - : (4 * kCycleScale + RdAvgXtraCyc); - } - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindEor; - } - } - } else { - /* Cmp 1011ddd0ssmmmrrr */ -#if 0 - if (IsValidAddrMode(p)) { - p->MainClass = kIKindCmp; - } -#endif - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, 0, rg9(p), - kAddrValidAny, falseblnr)) - { -#if WantCycByPriOp - p->Cycles = (4 == p->opsize) - ? (6 * kCycleScale + RdAvgXtraCyc) - : (4 * kCycleScale + RdAvgXtraCyc); - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindCmpB + OpSizeOffset(p); - } - } -} - -LOCALPROC MayInline DeCodeC(WorkR *p) -{ - if (b76(p) == 3) { - p->opsize = 2; - if (CheckDataAddrMode(p)) { -#if WantCycByPriOp -#if WantCloserCyc - p->Cycles = (38 * kCycleScale + RdAvgXtraCyc); -#else - p->Cycles = (54 * kCycleScale + RdAvgXtraCyc); - /* worst case 70, best case 38 */ -#endif - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - if (b8(p) == 0) { - /* MulU 1100ddd011mmmrrr */ - p->MainClass = kIKindMulU; - } else { - /* MulS 1100ddd111mmmrrr */ - p->MainClass = kIKindMulS; - } - } - } else { - if (b8(p) == 0) { - /* And 1100ddd0ssmmmrrr */ -#if 0 - if (CheckDataAddrMode(p)) { - p->MainClass = kIKindAndEaD; - } -#endif - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidData, trueblnr)) - if (CheckValidAddrMode(p, 0, rg9(p), - kAddrValidAny, falseblnr)) - { -#if WantCycByPriOp - if (4 == p->opsize) { - if ((mode(p) < 2) - || ((7 == mode(p)) && (reg(p) == 4))) - { - p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); - } else { - p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); - } - } else { - p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); - } - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindAndEaD; - } - } else { - if (mode(p) < 2) { - switch (b76(p)) { - case 0: - /* ABCD 1100ddd10000mrrr */ -#if WantCycByPriOp - if (0 != mode(p)) { - p->Cycles = (18 * kCycleScale - + 3 * RdAvgXtraCyc + WrAvgXtraCyc); - } else { - p->Cycles = (6 * kCycleScale - + RdAvgXtraCyc); - } -#endif - if (mode(p) == 0) { - p->MainClass = kIKindAbcdr; - } else { - p->MainClass = kIKindAbcdm; - } - break; - case 1: - /* Exg 1100ddd10100trrr */ -#if WantCycByPriOp - p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); -#endif - if (mode(p) == 0) { - p->MainClass = kIKindExgdd; - } else { - p->MainClass = kIKindExgaa; - } - break; - case 2: - default: /* keep compiler happy */ - if (mode(p) == 0) { - p->MainClass = kIKindIllegal; - } else { - /* Exg 1100ddd110001rrr */ -#if WantCycByPriOp - p->Cycles = (6 * kCycleScale - + RdAvgXtraCyc); -#endif - p->MainClass = kIKindExgda; - } - break; - } - } else { - /* And 1100ddd1ssmmmrrr */ -#if 0 - if (CheckAltMemAddrMode(p)) { - p->MainClass = kIKindAndDEa; - } -#endif - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, 0, rg9(p), - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidAltMem, falseblnr)) - { -#if WantCycByPriOp - p->Cycles = (4 == p->opsize) - ? (12 * kCycleScale - + RdAvgXtraCyc + 2 * WrAvgXtraCyc) - : (8 * kCycleScale - + RdAvgXtraCyc + WrAvgXtraCyc); - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindAndDEa; - } - } - } - } -} - -LOCALPROC MayInline DeCodeD(WorkR *p) -{ - if (b76(p) == 3) { - /* ADDA 1101dddm11mmmrrr */ - p->opsize = b8(p) * 2 + 2; - SetDcoArgFields(p, falseblnr, kAMdReg, kArgkRegL, rg9(p) + 8); - /* always long, regardless of opsize */ - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidAny, trueblnr)) - { -#if WantCycByPriOp - if (4 == p->opsize) { - if ((mode(p) < 2) || ((7 == mode(p)) && (reg(p) == 4))) - { - p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); - } else { - p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); - } - } else { - p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); - } - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindAddA; - } - } else { - if (b8(p) == 0) { - /* ADD 1101ddd0ssmmmrrr */ - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, 0, rg9(p), - kAddrValidAny, falseblnr)) - { -#if WantCycByPriOp - if (4 == p->opsize) { - if ((mode(p) < 2) - || ((7 == mode(p)) && (reg(p) == 4))) - { - p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); - } else { - p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); - } - } else { - p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); - } - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindAddB + OpSizeOffset(p); - } - } else { - if (mode(p) == 0) { - /* ADDX 1101ddd1ss000rrr */ - /* p->MainClass = kIKindAddXd; */ - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, 0, reg(p), - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, 0, rg9(p), - kAddrValidAny, falseblnr)) - { -#if WantCycByPriOp - p->Cycles = (4 == p->opsize) - ? (8 * kCycleScale + RdAvgXtraCyc) - : (4 * kCycleScale + RdAvgXtraCyc); -#endif - p->MainClass = kIKindAddXB + OpSizeOffset(p); - } - } else if (mode(p) == 1) { - /* p->MainClass = kIKindAddXm; */ - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, 4, reg(p), - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, 4, rg9(p), - kAddrValidAny, falseblnr)) - { -#if WantCycByPriOp - p->Cycles = (4 == p->opsize) - ? (30 * kCycleScale - + 5 * RdAvgXtraCyc + 2 * WrAvgXtraCyc) - : (18 * kCycleScale - + 3 * RdAvgXtraCyc + 1 * WrAvgXtraCyc); -#endif - p->MainClass = kIKindAddXB + OpSizeOffset(p); - } - } else { - /* ADD 1101ddd1ssmmmrrr */ - FindOpSizeFromb76(p); - if (CheckValidAddrMode(p, 0, rg9(p), - kAddrValidAny, trueblnr)) - if (CheckValidAddrMode(p, mode(p), reg(p), - kAddrValidAltMem, falseblnr)) - { -#if WantCycByPriOp - p->Cycles = (4 == p->opsize) - ? (12 * kCycleScale - + RdAvgXtraCyc + 2 * WrAvgXtraCyc) - : (8 * kCycleScale - + RdAvgXtraCyc + WrAvgXtraCyc); - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindAddB + OpSizeOffset(p); - } - } - } - } -} - -LOCALPROC MayInline DeCodeE(WorkR *p) -{ - if (b76(p) == 3) { - if ((p->opcode & 0x0800) != 0) { -#if Use68020 - /* 11101???11mmmrrr */ - switch (mode(p)) { - case 1: - case 3: - case 4: - default: /* keep compiler happy */ - p->MainClass = kIKindIllegal; - break; - case 0: - case 2: - case 5: - case 6: - p->MainClass = kIKindBitField; - break; - case 7: - switch (reg(p)) { - case 0: - case 1: - p->MainClass = kIKindBitField; - break; - case 2: - case 3: - switch ((p->opcode >> 8) & 7) { - case 0: /* BFTST */ - case 1: /* BFEXTU */ - case 3: /* BFEXTS */ - case 5: /* BFFFO */ - p->MainClass = kIKindBitField; - break; - default: - p->MainClass = kIKindIllegal; - break; - } - break; - default: - p->MainClass = kIKindIllegal; - break; - } - break; - } -#else - p->MainClass = kIKindIllegal; -#endif - } else { - /* 11100ttd11mmmddd */ - if (CheckAltMemAddrMode(p)) { -#if WantCycByPriOp - p->Cycles = (8 * kCycleScale - + RdAvgXtraCyc + WrAvgXtraCyc); - p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); -#endif - p->MainClass = kIKindRolopNM; - } - } - } else { - if (mode(p) < 4) { - /* 1110cccdss0ttddd */ -#if WantCycByPriOp - p->Cycles = (octdat(rg9(p)) * (2 * kCycleScale)) - + ((4 == p->opsize) - ? (8 * kCycleScale + RdAvgXtraCyc) - : (6 * kCycleScale + RdAvgXtraCyc)); -#endif - p->MainClass = kIKindRolopND; - } else { - /* 1110rrrdss1ttddd */ -#if WantCycByPriOp -#if WantCloserCyc - p->Cycles = (4 == p->opsize) - ? (8 * kCycleScale + RdAvgXtraCyc) - : (6 * kCycleScale + RdAvgXtraCyc); -#else - p->Cycles = (4 == p->opsize) - ? ((8 * kCycleScale) - + RdAvgXtraCyc + (8 * (2 * kCycleScale))) - /* say average shift count of 8 */ - : ((6 * kCycleScale) - + RdAvgXtraCyc + (4 * (2 * kCycleScale))); - /* say average shift count of 4 */ -#endif -#endif - p->MainClass = kIKindRolopDD; - } - } -} - -LOCALPROC MayInline DeCodeF(WorkR *p) -{ -#if WantCycByPriOp - p->Cycles = - (34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); -#endif - p->MainClass = kIKindF; -} - -LOCALPROC DeCodeOneOp(WorkR *p) -{ - switch (p->opcode >> 12) { - case 0x0: - DeCode0(p); - break; - case 0x1: - DeCode1(p); - break; - case 0x2: - DeCode2(p); - break; - case 0x3: - DeCode3(p); - break; - case 0x4: - DeCode4(p); - break; - case 0x5: - DeCode5(p); - break; - case 0x6: - DeCode6(p); - break; - case 0x7: - DeCode7(p); - break; - case 0x8: - DeCode8(p); - break; - case 0x9: - DeCode9(p); - break; - case 0xA: - DeCodeA(p); - break; - case 0xB: - DeCodeB(p); - break; - case 0xC: - DeCodeC(p); - break; - case 0xD: - DeCodeD(p); - break; - case 0xE: - DeCodeE(p); - break; - case 0xF: - default: /* keep compiler happy */ - DeCodeF(p); - break; - } - - if (kIKindIllegal == p->MainClass) { -#if WantCycByPriOp - p->Cycles = (34 * kCycleScale - + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); -#endif - SetDcoSrcAMd(&p->DecOp, 0); - SetDcoSrcArgk(&p->DecOp, 0); - SetDcoSrcArgDat(&p->DecOp, 0); - SetDcoDstAMd(&p->DecOp, 0); - SetDcoDstArgk(&p->DecOp, 0); - SetDcoDstArgDat(&p->DecOp, 0); - } - - SetDcoMainClas(&p->DecOp, p->MainClass); -#if WantCycByPriOp - SetDcoCycles(&p->DecOp, p->Cycles); -#else - SetDcoCycles(&p->DecOp, kMyAvgCycPerInstr); -#endif -} - -GLOBALPROC M68KITAB_setup(DecOpR *p) -{ - ui5b i; - WorkR r; - - for (i = 0; i < (ui5b)256 * 256; ++i) { - r.opcode = i; - r.MainClass = kIKindIllegal; - - r.DecOp.A = 0; - r.DecOp.B = 0; -#if WantCycByPriOp - r.Cycles = kMyAvgCycPerInstr; -#endif - - DeCodeOneOp(&r); - - p[i].A = r.DecOp.A; - p[i].B = r.DecOp.B; - } -} +/* M68KITAB.c Copyright (C) 2007 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* Motorola 68K Instructions TABle */ #ifndef AllFiles #include "SYSDEPNS.h" #endif #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "M68KITAB.h" struct WorkR { /* expected size : 8 bytes */ ui5b opcode; ui5b opsize; ui4r MainClass; #if WantCycByPriOp ui4r Cycles; #endif DecOpR DecOp; }; typedef struct WorkR WorkR; #define b76(p) ((p->opcode >> 6) & 3) #define b8(p) ((p->opcode >> 8) & 1) #define mode(p) ((p->opcode >> 3) & 7) #define reg(p) (p->opcode & 7) #define md6(p) ((p->opcode >> 6) & 7) #define rg9(p) ((p->opcode >> 9) & 7) enum { kAddrValidAny, kAddrValidData, kAddrValidDataAlt, kAddrValidControl, kAddrValidControlAlt, kAddrValidAltMem, kAddrValidDataNoCn, /* no constants (immediate data) */ kNumAddrValids }; #define kAddrValidMaskAny (1 << kAddrValidAny) #define kAddrValidMaskData (1 << kAddrValidData) #define kAddrValidMaskDataAlt (1 << kAddrValidDataAlt) #define kAddrValidMaskControl (1 << kAddrValidControl) #define kAddrValidMaskControlAlt (1 << kAddrValidControlAlt) #define kAddrValidMaskAltMem (1 << kAddrValidAltMem) #define kAddrValidMaskDataNoCn (1 << kAddrValidDataNoCn) #define CheckInSet(v, m) (0 != ((1 << (v)) & (m))) #define kMyAvgCycPerInstr (10 * kCycleScale + (40 * kCycleScale / 64)) LOCALFUNC ui3r GetAMdRegSz(WorkR *p) { ui3r CurAMd; switch (p->opsize) { case 1: CurAMd = kAMdRegB; break; case 2: default: /* keep compiler happy */ CurAMd = kAMdRegW; break; case 4: CurAMd = kAMdRegL; break; } return CurAMd; } LOCALFUNC ui3r GetAMdIndirectSz(WorkR *p) { ui3r CurAMd; switch (p->opsize) { case 1: CurAMd = kAMdIndirectB; break; case 2: default: /* keep compiler happy */ CurAMd = kAMdIndirectW; break; case 4: CurAMd = kAMdIndirectL; break; } return CurAMd; } #if WantCycByPriOp LOCALFUNC ui4r OpEACalcCyc(WorkR *p, ui3r m, ui3r r) { ui4r v; switch (m) { case 0: case 1: v = 0; break; case 2: v = ((4 == p->opsize) ? (8 * kCycleScale + 2 * RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc)); break; case 3: v = ((4 == p->opsize) ? (8 * kCycleScale + 2 * RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc)); break; case 4: v = ((4 == p->opsize) ? (10 * kCycleScale + 2 * RdAvgXtraCyc) : (6 * kCycleScale + RdAvgXtraCyc)); break; case 5: v = ((4 == p->opsize) ? (12 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc)); break; case 6: v = ((4 == p->opsize) ? (14 * kCycleScale + 3 * RdAvgXtraCyc) : (10 * kCycleScale + 2 * RdAvgXtraCyc)); break; case 7: switch (r) { case 0: v = ((4 == p->opsize) ? (12 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc)); break; case 1: v = ((4 == p->opsize) ? (16 * kCycleScale + 4 * RdAvgXtraCyc) : (12 * kCycleScale + 3 * RdAvgXtraCyc)); break; case 2: v = ((4 == p->opsize) ? (12 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc)); break; case 3: v = ((4 == p->opsize) ? (14 * kCycleScale + 3 * RdAvgXtraCyc) : (10 * kCycleScale + 2 * RdAvgXtraCyc)); break; case 4: v = ((4 == p->opsize) ? (8 * kCycleScale + 2 * RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc)); break; default: v = 0; break; } break; default: /* keep compiler happy */ v = 0; break; } return v; } #endif #if WantCycByPriOp LOCALFUNC ui4r OpEADestCalcCyc(WorkR *p, ui3r m, ui3r r) { ui4r v; switch (m) { case 0: case 1: v = 0; break; case 2: v = ((4 == p->opsize) ? (8 * kCycleScale + 2 * WrAvgXtraCyc) : (4 * kCycleScale + WrAvgXtraCyc)); break; case 3: v = ((4 == p->opsize) ? (8 * kCycleScale + 2 * WrAvgXtraCyc) : (4 * kCycleScale + WrAvgXtraCyc)); break; case 4: v = ((4 == p->opsize) ? (8 * kCycleScale + 2 * WrAvgXtraCyc) : (4 * kCycleScale + WrAvgXtraCyc)); break; case 5: v = ((4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc)); break; case 6: v = ((4 == p->opsize) ? (14 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (10 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc)); break; case 7: switch (r) { case 0: v = ((4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc)); break; case 1: v = ((4 == p->opsize) ? (16 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (12 * kCycleScale + 2 * RdAvgXtraCyc + WrAvgXtraCyc)); break; default: v = 0; break; } break; default: /* keep compiler happy */ v = 0; break; } return v; } #endif LOCALPROC SetDcoArgFields(WorkR *p, blnr src, ui3r CurAMd, ui3r CurArgDat) { if (src) { p->DecOp.y.v[0].AMd = CurAMd; p->DecOp.y.v[0].ArgDat = CurArgDat; } else { p->DecOp.y.v[1].AMd = CurAMd; p->DecOp.y.v[1].ArgDat = CurArgDat; } } LOCALFUNC blnr CheckValidAddrMode(WorkR *p, ui3r m, ui3r r, ui3r v, blnr src) { ui3r CurAMd = 0; /* init to keep compiler happy */ ui3r CurArgDat = 0; blnr IsOk; switch (m) { case 0: CurAMd = GetAMdRegSz(p); CurArgDat = r; IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskDataAlt | kAddrValidMaskDataNoCn); break; case 1: CurAMd = GetAMdRegSz(p); CurArgDat = r + 8; IsOk = CheckInSet(v, kAddrValidMaskAny); break; case 2: CurAMd = GetAMdIndirectSz(p); CurArgDat = r + 8; IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskDataAlt | kAddrValidMaskControl | kAddrValidMaskControlAlt | kAddrValidMaskAltMem | kAddrValidMaskDataNoCn); break; case 3: switch (p->opsize) { case 1: if (7 == r) { CurAMd = kAMdAPosInc7B; } else { CurAMd = kAMdAPosIncB; } break; case 2: default: /* keep compiler happy */ CurAMd = kAMdAPosIncW; break; case 4: CurAMd = kAMdAPosIncL; break; } CurArgDat = r + 8; IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskDataAlt | kAddrValidMaskAltMem | kAddrValidMaskDataNoCn); break; case 4: switch (p->opsize) { case 1: if (7 == r) { CurAMd = kAMdAPreDec7B; } else { CurAMd = kAMdAPreDecB; } break; case 2: default: /* keep compiler happy */ CurAMd = kAMdAPreDecW; break; case 4: CurAMd = kAMdAPreDecL; break; } CurArgDat = r + 8; IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskDataAlt | kAddrValidMaskAltMem | kAddrValidMaskDataNoCn); break; case 5: switch (p->opsize) { case 1: CurAMd = kAMdADispB; break; case 2: default: /* keep compiler happy */ CurAMd = kAMdADispW; break; case 4: CurAMd = kAMdADispL; break; } CurArgDat = r + 8; IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskDataAlt | kAddrValidMaskControl | kAddrValidMaskControlAlt | kAddrValidMaskAltMem | kAddrValidMaskDataNoCn); break; case 6: switch (p->opsize) { case 1: CurAMd = kAMdAIndexB; break; case 2: default: /* keep compiler happy */ CurAMd = kAMdAIndexW; break; case 4: CurAMd = kAMdAIndexL; break; } CurArgDat = r + 8; IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskDataAlt | kAddrValidMaskControl | kAddrValidMaskControlAlt | kAddrValidMaskAltMem | kAddrValidMaskDataNoCn); break; case 7: switch (r) { case 0: switch (p->opsize) { case 1: CurAMd = kAMdAbsWB; break; case 2: default: /* keep compiler happy */ CurAMd = kAMdAbsWW; break; case 4: CurAMd = kAMdAbsWL; break; } IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskDataAlt | kAddrValidMaskControl | kAddrValidMaskControlAlt | kAddrValidMaskAltMem | kAddrValidMaskDataNoCn); break; case 1: switch (p->opsize) { case 1: CurAMd = kAMdAbsLB; break; case 2: default: /* keep compiler happy */ CurAMd = kAMdAbsLW; break; case 4: CurAMd = kAMdAbsLL; break; } IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskDataAlt | kAddrValidMaskControl | kAddrValidMaskControlAlt | kAddrValidMaskAltMem | kAddrValidMaskDataNoCn); break; case 2: switch (p->opsize) { case 1: CurAMd = kAMdPCDispB; break; case 2: default: /* keep compiler happy */ CurAMd = kAMdPCDispW; break; case 4: CurAMd = kAMdPCDispL; break; } IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskControl | kAddrValidMaskDataNoCn); break; case 3: switch (p->opsize) { case 1: CurAMd = kAMdPCIndexB; break; case 2: default: /* keep compiler happy */ CurAMd = kAMdPCIndexW; break; case 4: CurAMd = kAMdPCIndexL; break; } IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData | kAddrValidMaskControl | kAddrValidMaskDataNoCn); break; case 4: switch (p->opsize) { case 1: CurAMd = kAMdImmedB; break; case 2: default: /* keep compiler happy */ CurAMd = kAMdImmedW; break; case 4: CurAMd = kAMdImmedL; break; } IsOk = CheckInSet(v, kAddrValidMaskAny | kAddrValidMaskData); break; default: IsOk = falseblnr; break; } break; default: /* keep compiler happy */ IsOk = falseblnr; break; } if (IsOk) { SetDcoArgFields(p, src, CurAMd, CurArgDat); } return IsOk; } #if WantCycByPriOp LOCALFUNC blnr LeaPeaEACalcCyc(WorkR *p, ui3r m, ui3r r) { ui4r v; UnusedParam(p); switch (m) { case 2: v = 0; break; case 5: v = (4 * kCycleScale + RdAvgXtraCyc); break; case 6: v = (8 * kCycleScale + RdAvgXtraCyc); break; case 7: switch (r) { case 0: v = (4 * kCycleScale + RdAvgXtraCyc); break; case 1: v = (8 * kCycleScale + 2 * RdAvgXtraCyc); break; case 2: v = (4 * kCycleScale + RdAvgXtraCyc); break; case 3: v = (8 * kCycleScale + RdAvgXtraCyc); break; default: v = 0; break; } break; default: /* keep compiler happy */ v = 0; break; } return v; } #endif LOCALFUNC blnr IsValidAddrMode(WorkR *p) { return CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, falseblnr); } LOCALFUNC blnr CheckDataAltAddrMode(WorkR *p) { return CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr); } LOCALFUNC blnr CheckDataAddrMode(WorkR *p) { return CheckValidAddrMode(p, mode(p), reg(p), kAddrValidData, falseblnr); } LOCALFUNC blnr CheckControlAddrMode(WorkR *p) { return CheckValidAddrMode(p, mode(p), reg(p), kAddrValidControl, falseblnr); } LOCALFUNC blnr CheckControlAltAddrMode(WorkR *p) { return CheckValidAddrMode(p, mode(p), reg(p), kAddrValidControlAlt, falseblnr); } LOCALFUNC blnr CheckAltMemAddrMode(WorkR *p) { return CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAltMem, falseblnr); } LOCALPROC FindOpSizeFromb76(WorkR *p) { p->opsize = 1 << b76(p); #if 0 switch (b76(p)) { case 0 : p->opsize = 1; break; case 1 : p->opsize = 2; break; case 2 : p->opsize = 4; break; } #endif } LOCALFUNC ui3r OpSizeOffset(WorkR *p) { ui3r v; switch (p->opsize) { case 1 : v = 0; break; case 2 : v = 1; break; case 4 : default : v = 2; break; } return v; } LOCALFUNC ui5r octdat(ui5r x) { if (x == 0) { return 8; } else { return x; } } LOCALPROCUSEDONCE DeCode0(WorkR *p) { if (b8(p) == 1) { if (mode(p) == 1) { /* MoveP 0000ddd1mm001aaa */ #if WantCycByPriOp switch (b76(p)) { case 0: p->Cycles = (16 * kCycleScale + 4 * RdAvgXtraCyc); break; case 1: p->Cycles = (24 * kCycleScale + 6 * RdAvgXtraCyc); break; case 2: p->Cycles = (16 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); break; case 3: default: /* keep compiler happy */ p->Cycles = (24 * kCycleScale + 2 * RdAvgXtraCyc + 4 * WrAvgXtraCyc); break; } #endif if (CheckValidAddrMode(p, 1, reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { p->MainClass = kIKindMoveP0 + b76(p); } } else { /* dynamic bit, Opcode = 0000ddd1ttmmmrrr */ if (mode(p) == 0) { p->opsize = 4; #if WantCycByPriOp switch (b76(p)) { case 0: /* BTst */ p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); break; case 1: /* BChg */ p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); break; case 2: /* BClr */ p->Cycles = (10 * kCycleScale + RdAvgXtraCyc); break; case 3: /* BSet */ p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); break; } #endif p->MainClass = kIKindBTstL + b76(p); SetDcoArgFields(p, trueblnr, kAMdRegL, rg9(p)); SetDcoArgFields(p, falseblnr, kAMdRegL, reg(p)); } else { p->opsize = 1; p->MainClass = kIKindBTstB + b76(p); SetDcoArgFields(p, trueblnr, kAMdRegB, rg9(p)); if (b76(p) == 0) { /* BTst */ if (CheckDataAddrMode(p)) { #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif } } else { if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp p->Cycles = (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif } } } } } else { if (rg9(p) == 4) { /* static bit 00001010ssmmmrrr */ if (mode(p) == 0) { p->opsize = 4; #if WantCycByPriOp switch (b76(p)) { case 0: /* BTst */ p->Cycles = (10 * kCycleScale + 2 * RdAvgXtraCyc); break; case 1: /* BChg */ p->Cycles = (12 * kCycleScale + 2 * RdAvgXtraCyc); break; case 2: /* BClr */ p->Cycles = (14 * kCycleScale + 2 * RdAvgXtraCyc); break; case 3: /* BSet */ p->Cycles = (12 * kCycleScale + 2 * RdAvgXtraCyc); break; } #endif SetDcoArgFields(p, trueblnr, kAMdImmedB, 0); SetDcoArgFields(p, falseblnr, kAMdRegL, reg(p)); p->MainClass = kIKindBTstL + b76(p); } else { p->opsize = 1; SetDcoArgFields(p, trueblnr, kAMdImmedB, 0); p->MainClass = kIKindBTstB + b76(p); if (b76(p) == 0) { /* BTst */ if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataNoCn, falseblnr)) { #if WantCycByPriOp p->Cycles = (8 * kCycleScale + 2 * RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif } } else { if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp p->Cycles = (12 * kCycleScale + 2 * RdAvgXtraCyc + WrAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif } } } } else if (b76(p) == 3) { #if Use68020 if (rg9(p) < 3) { /* CHK2 or CMP2 00000ss011mmmrrr */ switch ((p->opcode >> 9) & 3) { case 0 : p->opsize = 1; break; case 1 : p->opsize = 2; break; case 2 : p->opsize = 4; break; } p->DecOp.y.v[0].ArgDat = p->opsize; /* size */ if (CheckControlAddrMode(p)) { #if WantCycByPriOp p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindCHK2orCMP2; } } else if (rg9(p) >= 5) { switch ((p->opcode >> 9) & 3) { case 1 : p->opsize = 1; break; case 2 : p->opsize = 2; break; case 3 : p->opsize = 4; break; } p->DecOp.y.v[0].ArgDat = p->opsize; if ((mode(p) == 7) && (reg(p) == 4)) { /* CAS2 00001ss011111100 */ p->MainClass = kIKindCAS2; } else { /* CAS 00001ss011mmmrrr */ if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindCAS; } } } else if (rg9(p) == 3) { /* CALLM or RTM 0000011011mmmrrr */ p->MainClass = kIKindCallMorRtm; } else #endif { p->MainClass = kIKindIllegal; } } else if (rg9(p) == 6) { /* CMPI 00001100ssmmmrrr */ #if 0 if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindCmpI; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 7, 4, kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataNoCn, falseblnr)) { #if WantCycByPriOp if (0 == mode(p)) { p->Cycles = (4 == p->opsize) ? (14 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindCmpB + OpSizeOffset(p); } } else if (rg9(p) == 7) { #if Use68020 /* MoveS 00001110ssmmmrrr */ FindOpSizeFromb76(p); p->DecOp.y.v[0].ArgDat = p->opsize; if (CheckAltMemAddrMode(p)) { #if WantCycByPriOp p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindMoveS; } #else p->MainClass = kIKindIllegal; #endif } else { if ((mode(p) == 7) && (reg(p) == 4)) { switch (rg9(p)) { case 0: #if WantCycByPriOp p->Cycles = (20 * kCycleScale + 3 * RdAvgXtraCyc); #endif p->MainClass = (0 != b76(p)) ? kIKindOrISR : kIKindOrICCR; break; case 1: #if WantCycByPriOp p->Cycles = (20 * kCycleScale + 3 * RdAvgXtraCyc); #endif p->MainClass = (0 != b76(p)) ? kIKindAndISR : kIKindAndICCR; break; case 5: #if WantCycByPriOp p->Cycles = (20 * kCycleScale + 3 * RdAvgXtraCyc); #endif p->MainClass = (0 != b76(p)) ? kIKindEorISR : kIKindEorICCR; break; default: p->MainClass = kIKindIllegal; break; } } else { switch (rg9(p)) { case 0: #if 0 if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindOrI; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 7, 4, kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (20 * kCycleScale + 3 * RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (12 * kCycleScale + 2 * RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (16 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindOrI; } break; case 1: #if 0 if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindAndI; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 7, 4, kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (20 * kCycleScale + 3 * RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (12 * kCycleScale + 2 * RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (14 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindAndI; } break; case 2: #if 0 if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindSubI; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 7, 4, kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (20 * kCycleScale + 3 * RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (12 * kCycleScale + 2 * RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (16 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindSubB + OpSizeOffset(p); } break; case 3: #if 0 if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindAddI; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 7, 4, kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (20 * kCycleScale + 3 * RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (12 * kCycleScale + 2 * RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (16 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindAddB + OpSizeOffset(p); } break; case 5: #if 0 if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindEorI; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 7, 4, kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (20 * kCycleScale + 3 * RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (12 * kCycleScale + 2 * RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (16 * kCycleScale + 3 * RdAvgXtraCyc) : (8 * kCycleScale + 2 * RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindEorI; } break; default: /* for compiler. should be 0, 1, 2, 3, or 5 */ p->MainClass = kIKindIllegal; break; } } } } } LOCALPROCUSEDONCE DeCode1(WorkR *p) { p->opsize = 1; if (md6(p) == 1) { /* MOVEA */ p->MainClass = kIKindIllegal; } else if (mode(p) == 1) { /* not allowed for byte sized move */ p->MainClass = kIKindIllegal; } else { if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, md6(p), rg9(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); p->Cycles += OpEADestCalcCyc(p, md6(p), rg9(p)); #endif p->MainClass = kIKindMoveB; } } } LOCALPROCUSEDONCE DeCode2(WorkR *p) { p->opsize = 4; if (md6(p) == 1) { /* MOVEA */ if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 1, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindMoveAL; p->DecOp.y.v[1].ArgDat = rg9(p); } } else { if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, md6(p), rg9(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); p->Cycles += OpEADestCalcCyc(p, md6(p), rg9(p)); #endif p->MainClass = kIKindMoveL; } } } LOCALPROCUSEDONCE DeCode3(WorkR *p) { p->opsize = 2; if (md6(p) == 1) { /* MOVEA */ if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 1, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindMoveAW; p->DecOp.y.v[1].ArgDat = rg9(p); } } else { if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, md6(p), rg9(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); p->Cycles += OpEADestCalcCyc(p, md6(p), rg9(p)); #endif p->MainClass = kIKindMoveW; } } } #if WantCycByPriOp #if WantCloserCyc #define MoveAvgN 0 #else #define MoveAvgN 3 #endif LOCALFUNC ui4r MoveMEACalcCyc(WorkR *p, ui3r m, ui3r r) { ui4r v; UnusedParam(p); switch (m) { case 2: case 3: case 4: v = (8 * kCycleScale + 2 * RdAvgXtraCyc); break; case 5: v = (12 * kCycleScale + 3 * RdAvgXtraCyc); break; case 6: v = (14 * kCycleScale + 3 * RdAvgXtraCyc); break; case 7: switch (r) { case 0: v = (12 * kCycleScale + 3 * RdAvgXtraCyc); break; case 1: v = (16 * kCycleScale + 4 * RdAvgXtraCyc); break; default: v = 0; break; } break; default: /* keep compiler happy */ v = 0; break; } return v; } #endif LOCALPROCUSEDONCE DeCode4(WorkR *p) { if (b8(p) != 0) { switch (b76(p)) { case 0: #if Use68020 /* Chk.L 0100ddd100mmmrrr */ p->opsize = 4; if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidData, falseblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, trueblnr)) { #if WantCycByPriOp p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindChkL; } #else p->MainClass = kIKindIllegal; #endif break; case 1: p->MainClass = kIKindIllegal; break; case 2: /* Chk.W 0100ddd110mmmrrr */ p->opsize = 2; if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidData, falseblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, trueblnr)) { #if WantCycByPriOp p->Cycles = (10 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindChkW; } break; case 3: default: /* keep compiler happy */ #if Use68020 if ((0 == mode(p)) && (4 == rg9(p))) { /* EXTB.L */ SetDcoArgFields(p, falseblnr, kAMdRegL, reg(p)); p->MainClass = kIKindEXTBL; } else #endif { /* Lea 0100aaa111mmmrrr */ if (CheckControlAddrMode(p)) { #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += LeaPeaEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindLea; p->DecOp.y.v[0].ArgDat = rg9(p); } } break; } } else { switch (rg9(p)) { case 0: if (b76(p) != 3) { /* NegX 01000000ssmmmrrr */ FindOpSizeFromb76(p); if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (6 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindNegXB + OpSizeOffset(p); } } else { #if Use68020 /* reference seems incorrect to say not for 68000 */ #endif /* Move from SR 0100000011mmmrrr */ p->opsize = 2; if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp p->Cycles = (12 * kCycleScale + 2 * RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindMoveSREa; } } break; case 1: if (b76(p) != 3) { /* Clr 01000010ssmmmrrr */ FindOpSizeFromb76(p); if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (6 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindClr; } } else { #if Use68020 /* Move from CCR 0100001011mmmrrr */ p->opsize = 2; if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindMoveCCREa; } #else p->MainClass = kIKindIllegal; #endif } break; case 2: if (b76(p) != 3) { /* Neg 01000100ssmmmrrr */ FindOpSizeFromb76(p); if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (6 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindNegB + OpSizeOffset(p); } } else { /* Move to CCR 0100010011mmmrrr */ p->opsize = 2; if (CheckDataAddrMode(p)) { #if WantCycByPriOp p->Cycles = (12 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindMoveEaCCR; } } break; case 3: if (b76(p) != 3) { /* Not 01000110ssmmmrrr */ FindOpSizeFromb76(p); if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (6 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindNot; } } else { /* Move from SR 0100011011mmmrrr */ p->opsize = 2; if (CheckDataAddrMode(p)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindMoveEaSR; } } break; case 4: switch (b76(p)) { case 0: #if Use68020 if (mode(p) == 1) { /* Link.L 0100100000001rrr */ SetDcoArgFields(p, falseblnr, kAMdRegL, reg(p) + 8); p->MainClass = kIKindLinkL; } else #endif { /* Nbcd 0100100000mmmrrr */ p->opsize = 1; if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindNbcd; } } break; case 1: if (mode(p) == 0) { /* Swap 0100100001000rrr */ #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindSwap; SetDcoArgFields(p, falseblnr, kAMdRegL, reg(p)); } else #if Use68020 if (mode(p) == 1) { p->MainClass = kIKindBkpt; } else #endif { /* PEA 0100100001mmmrrr */ if (CheckControlAddrMode(p)) { #if WantCycByPriOp p->Cycles = (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc); p->Cycles += LeaPeaEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindPEA; } } break; case 2: if (mode(p) == 0) { /* EXT.W */ #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); #endif SetDcoArgFields(p, falseblnr, kAMdRegW, reg(p)); p->MainClass = kIKindEXTW; } else { /* MOVEM reg to mem 01001d001ssmmmrrr */ p->opsize = 2; if (mode(p) == 4) { #if WantCycByPriOp p->Cycles = MoveMEACalcCyc(p, mode(p), reg(p)); p->Cycles += MoveAvgN * 4 * kCycleScale + MoveAvgN * WrAvgXtraCyc; #endif SetDcoArgFields(p, falseblnr, kAMdAPreDecL, reg(p) + 8); p->MainClass = kIKindMOVEMRmMW; } else { if (CheckControlAltAddrMode(p)) { #if WantCycByPriOp p->Cycles = MoveMEACalcCyc(p, mode(p), reg(p)); p->Cycles += MoveAvgN * 4 * kCycleScale + MoveAvgN * WrAvgXtraCyc; #endif p->MainClass = kIKindMOVEMrmW; } } } break; case 3: default: /* keep compiler happy */ if (mode(p) == 0) { /* EXT.L */ #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); #endif SetDcoArgFields(p, falseblnr, kAMdRegL, reg(p)); p->MainClass = kIKindEXTL; } else { /* MOVEM reg to mem 01001d001ssmmmrrr */ #if WantCycByPriOp p->Cycles = MoveMEACalcCyc(p, mode(p), reg(p)); p->Cycles += MoveAvgN * 8 * kCycleScale + MoveAvgN * 2 * WrAvgXtraCyc; #endif p->opsize = 4; if (mode(p) == 4) { SetDcoArgFields(p, falseblnr, kAMdAPreDecL, reg(p) + 8); p->MainClass = kIKindMOVEMRmML; } else { if (CheckControlAltAddrMode(p)) { p->MainClass = kIKindMOVEMrmL; } } } break; } break; case 5: if (b76(p) == 3) { if ((mode(p) == 7) && (reg(p) == 4)) { /* the ILLEGAL instruction */ p->MainClass = kIKindIllegal; } else { /* Tas 0100101011mmmrrr */ p->opsize = 1; if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (14 * kCycleScale + 2 * RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindTas; } } } else { /* Tst 01001010ssmmmrrr */ FindOpSizeFromb76(p); if (b76(p) == 0) { if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindTst; } } else { if (IsValidAddrMode(p)) { #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindTst; } } } break; case 6: if (((p->opcode >> 7) & 1) == 1) { /* MOVEM mem to reg 0100110011smmmrrr */ p->opsize = 2 * b76(p) - 2; if (mode(p) == 3) { #if WantCycByPriOp p->Cycles = 4 * kCycleScale + RdAvgXtraCyc; p->Cycles += MoveMEACalcCyc(p, mode(p), reg(p)); if (4 == p->opsize) { p->Cycles += MoveAvgN * 8 * kCycleScale + 2 * MoveAvgN * RdAvgXtraCyc; } else { p->Cycles += MoveAvgN * 4 * kCycleScale + MoveAvgN * RdAvgXtraCyc; } #endif SetDcoArgFields(p, falseblnr, kAMdAPosIncL, reg(p) + 8); if (b76(p) == 2) { p->MainClass = kIKindMOVEMApRW; } else { p->MainClass = kIKindMOVEMApRL; } } else { if (CheckControlAddrMode(p)) { #if WantCycByPriOp p->Cycles = 4 * kCycleScale + RdAvgXtraCyc; p->Cycles += MoveMEACalcCyc(p, mode(p), reg(p)); if (4 == p->opsize) { p->Cycles += MoveAvgN * 8 * kCycleScale + 2 * MoveAvgN * RdAvgXtraCyc; } else { p->Cycles += MoveAvgN * 4 * kCycleScale + MoveAvgN * RdAvgXtraCyc; } #endif if (4 == p->opsize) { p->MainClass = kIKindMOVEMmrL; } else { p->MainClass = kIKindMOVEMmrW; } } } } else { #if Use68020 p->opsize = 4; if (CheckDataAddrMode(p)) { if (((p->opcode >> 6) & 1) == 1) { /* DIVU 0100110001mmmrrr 0rrr0s0000000rrr */ /* DIVS 0100110001mmmrrr 0rrr1s0000000rrr */ p->MainClass = kIKindDivL; } else { /* MULU 0100110000mmmrrr 0rrr0s0000000rrr */ /* MULS 0100110000mmmrrr 0rrr1s0000000rrr */ p->MainClass = kIKindMulL; } } #else p->MainClass = kIKindIllegal; #endif } break; case 7: default: /* keep compiler happy */ switch (b76(p)) { case 0: p->MainClass = kIKindIllegal; break; case 1: switch (mode(p)) { case 0: case 1: /* Trap 010011100100vvvv */ #if WantCycByPriOp p->Cycles = (34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif SetDcoArgFields(p, falseblnr, kAMdDat4, (p->opcode & 15) + 32); p->MainClass = kIKindTrap; break; case 2: /* Link */ #if WantCycByPriOp p->Cycles = (16 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); #endif SetDcoArgFields(p, falseblnr, kAMdRegL, reg(p) + 8); if (reg(p) == 6) { p->MainClass = kIKindLinkA6; } else { p->MainClass = kIKindLink; } break; case 3: /* Unlk */ #if WantCycByPriOp p->Cycles = (12 * kCycleScale + 3 * RdAvgXtraCyc); #endif SetDcoArgFields(p, falseblnr, kAMdRegL, reg(p) + 8); if (reg(p) == 6) { p->MainClass = kIKindUnlkA6; } else { p->MainClass = kIKindUnlk; } break; case 4: /* MOVE USP 0100111001100aaa */ #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); #endif SetDcoArgFields(p, falseblnr, kAMdRegL, reg(p) + 8); p->MainClass = kIKindMoveRUSP; break; case 5: /* MOVE USP 0100111001101aaa */ #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); #endif SetDcoArgFields(p, falseblnr, kAMdRegL, reg(p) + 8); p->MainClass = kIKindMoveUSPR; break; case 6: switch (reg(p)) { case 0: /* Reset 0100111001100000 */ #if WantCycByPriOp p->Cycles = (132 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindReset; break; case 1: /* Nop = 0100111001110001 */ #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindNop; break; case 2: /* Stop 0100111001110010 */ #if WantCycByPriOp p->Cycles = (4 * kCycleScale); #endif p->MainClass = kIKindStop; break; case 3: /* Rte 0100111001110011 */ #if WantCycByPriOp p->Cycles = (20 * kCycleScale + 5 * RdAvgXtraCyc); #endif p->MainClass = kIKindRte; break; case 4: /* Rtd 0100111001110100 */ #if Use68020 p->MainClass = kIKindRtd; #else p->MainClass = kIKindIllegal; #endif break; case 5: /* Rts 0100111001110101 */ #if WantCycByPriOp p->Cycles = (16 * kCycleScale + 4 * RdAvgXtraCyc); #endif p->MainClass = kIKindRts; break; case 6: /* TrapV 0100111001110110 */ #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindTrapV; break; case 7: default: /* keep compiler happy */ /* Rtr 0100111001110111 */ #if WantCycByPriOp p->Cycles = (20 * kCycleScale + 2 * RdAvgXtraCyc); #endif p->MainClass = kIKindRtr; break; } break; case 7: default: /* keep compiler happy */ #if Use68020 /* MOVEC 010011100111101m */ switch (reg(p)) { case 2: p->MainClass = kIKindMoveCEa; break; case 3: p->MainClass = kIKindMoveEaC; break; default: p->MainClass = kIKindIllegal; break; } #else p->MainClass = kIKindIllegal; #endif break; } break; case 2: /* Jsr 0100111010mmmrrr */ if (CheckControlAddrMode(p)) { #if WantCycByPriOp switch (mode(p)) { case 2: p->Cycles = (16 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); break; case 5: p->Cycles = (18 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); break; case 6: p->Cycles = (22 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); break; case 7: default: /* keep compiler happy */ switch (reg(p)) { case 0: p->Cycles = (18 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); break; case 1: p->Cycles = (20 * kCycleScale + 3 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); break; case 2: p->Cycles = (18 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); break; case 3: default: /* keep compiler happy */ p->Cycles = (22 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); break; } break; } #endif p->MainClass = kIKindJsr; } break; case 3: default: /* keep compiler happy */ /* JMP 0100111011mmmrrr */ if (CheckControlAddrMode(p)) { #if WantCycByPriOp switch (mode(p)) { case 2: p->Cycles = (8 * kCycleScale + 2 * RdAvgXtraCyc); break; case 5: p->Cycles = (10 * kCycleScale + 2 * RdAvgXtraCyc); break; case 6: p->Cycles = (14 * kCycleScale + 2 * RdAvgXtraCyc); break; case 7: default: /* keep compiler happy */ switch (reg(p)) { case 0: p->Cycles = (10 * kCycleScale + 2 * RdAvgXtraCyc); break; case 1: p->Cycles = (12 * kCycleScale + 3 * RdAvgXtraCyc); break; case 2: p->Cycles = (10 * kCycleScale + 2 * RdAvgXtraCyc); break; case 3: default: /* keep compiler happy */ p->Cycles = (14 * kCycleScale + 3 * RdAvgXtraCyc); break; } break; } #endif p->MainClass = kIKindJmp; } break; } break; } } } LOCALPROCUSEDONCE DeCode5(WorkR *p) { if (b76(p) == 3) { p->DecOp.y.v[0].ArgDat = (p->opcode >> 8) & 15; if (mode(p) == 1) { /* DBcc 0101cccc11001ddd */ #if WantCycByPriOp #if WantCloserCyc p->Cycles = 0; #else p->Cycles = (11 * kCycleScale + 2 * RdAvgXtraCyc); /* average of cc true 12(2/0), cc false taken 10(2/0), and not 14(3/0) */ #endif #endif SetDcoArgFields(p, falseblnr, kAMdRegW, reg(p)); if (1 == ((p->opcode >> 8) & 15)) { p->MainClass = kIKindDBF; } else { p->MainClass = kIKindDBcc; } } else { #if Use68020 if ((mode(p) == 7) && (reg(p) >= 2)) { /* TRAPcc 0101cccc11111sss */ p->DecOp.y.v[0].ArgDat = reg(p); p->MainClass = kIKindTRAPcc; } else #endif { p->opsize = 1; /* Scc 0101cccc11mmmrrr */ if (CheckDataAltAddrMode(p)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); } else { #if WantCloserCyc p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); #else p->Cycles = (5 * kCycleScale + RdAvgXtraCyc); /* 4 when false, 6 when true */ #endif } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindScc; } } } } else { if (mode(p) == 1) { p->opsize = b8(p) * 2 + 2; SetDcoArgFields(p, trueblnr, kAMdDat4, octdat(rg9(p))); SetDcoArgFields(p, falseblnr, kAMdRegL, reg(p) + 8); /* always long, regardless of opsize */ if (b8(p) == 0) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (8 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindAddQA; /* AddQA 0101nnn0ss001rrr */ } else { #if WantCycByPriOp p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindSubQA; /* SubQA 0101nnn1ss001rrr */ } } else { FindOpSizeFromb76(p); SetDcoArgFields(p, trueblnr, kAMdDat4, octdat(rg9(p))); if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (8 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif if (b8(p) == 0) { /* AddQ 0101nnn0ssmmmrrr */ #if 0 if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindAddQ; } #endif p->MainClass = kIKindAddB + OpSizeOffset(p); } else { /* SubQ 0101nnn1ssmmmrrr */ #if 0 if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindSubQ; } #endif p->MainClass = kIKindSubB + OpSizeOffset(p); } } } } } LOCALPROCUSEDONCE DeCode6(WorkR *p) { ui5b cond = (p->opcode >> 8) & 15; if (cond == 1) { /* Bsr 01100001nnnnnnnn */ #if WantCycByPriOp p->Cycles = (18 * kCycleScale + 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc); #endif if (0 == (p->opcode & 255)) { p->MainClass = kIKindBsrW; } else #if Use68020 if (255 == (p->opcode & 255)) { p->MainClass = kIKindBsrL; } else #endif { p->MainClass = kIKindBsrB; p->DecOp.y.v[1].ArgDat = p->opcode & 255; } } else if (cond == 0) { /* Bra 01100000nnnnnnnn */ #if WantCycByPriOp p->Cycles = (10 * kCycleScale + 2 * RdAvgXtraCyc); #endif if (0 == (p->opcode & 255)) { p->MainClass = kIKindBraW; } else #if Use68020 if (255 == (p->opcode & 255)) { p->MainClass = kIKindBraL; } else #endif { p->MainClass = kIKindBraB; p->DecOp.y.v[1].ArgDat = p->opcode & 255; } } else { p->DecOp.y.v[0].ArgDat = cond; /* Bcc 0110ccccnnnnnnnn */ if (0 == (p->opcode & 255)) { #if WantCycByPriOp #if WantCloserCyc p->Cycles = 0; #else p->Cycles = (11 * kCycleScale + 2 * RdAvgXtraCyc); /* average of branch taken 10(2/0) and not 12(2/0) */ #endif #endif p->MainClass = kIKindBccW; } else #if Use68020 if (255 == (p->opcode & 255)) { p->MainClass = kIKindBccL; } else #endif { #if WantCycByPriOp #if WantCloserCyc p->Cycles = 0; #else p->Cycles = (9 * kCycleScale + RdAvgXtraCyc + (RdAvgXtraCyc / 2)); /* average of branch taken 10(2/0) and not 8(1/0) */ #endif #endif p->MainClass = kIKindBccB; p->DecOp.y.v[1].ArgDat = p->opcode & 255; } } } LOCALPROCUSEDONCE DeCode7(WorkR *p) { if (b8(p) == 0) { p->opsize = 4; #if WantCycByPriOp p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindMoveQ; p->DecOp.y.v[0].ArgDat = p->opcode & 255; p->DecOp.y.v[1].ArgDat = rg9(p); } else { p->MainClass = kIKindIllegal; } } LOCALPROCUSEDONCE DeCode8(WorkR *p) { if (b76(p) == 3) { p->opsize = 2; if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidData, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { if (b8(p) == 0) { /* DivU 1000ddd011mmmrrr */ #if WantCycByPriOp p->Cycles = RdAvgXtraCyc; p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #if ! WantCloserCyc p->Cycles += 133 * kCycleScale; /* worse case 140, less than ten percent different from best case */ #endif #endif p->MainClass = kIKindDivU; } else { /* DivS 1000ddd111mmmrrr */ #if WantCycByPriOp p->Cycles = RdAvgXtraCyc; p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #if ! WantCloserCyc p->Cycles += 150 * kCycleScale; /* worse case 158, less than ten percent different from best case */ #endif #endif p->MainClass = kIKindDivS; } } } else { if (b8(p) == 0) { /* OR 1000ddd0ssmmmrrr */ #if 0 if (CheckDataAddrMode(p)) { p->MainClass = kIKindOrEaD; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidData, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp if (4 == p->opsize) { if ((mode(p) < 2) || ((7 == mode(p)) && (reg(p) == 4))) { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } } else { p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindOrEaD; } } else { if (mode(p) < 2) { switch (b76(p)) { case 0: /* SBCD 1000xxx10000mxxx */ #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (18 * kCycleScale + 3 * RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } #endif p->opsize = 1; if (mode(p) == 0) { if (CheckValidAddrMode(p, 0, reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { p->MainClass = kIKindSbcd; } } else { if (CheckValidAddrMode(p, 4, reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 4, rg9(p), kAddrValidAny, falseblnr)) { p->MainClass = kIKindSbcd; } } break; #if Use68020 case 1: /* PACK 1000rrr10100mrrr */ if (mode(p) == 0) { p->opsize = 2; if (CheckValidAddrMode(p, 0, reg(p), kAddrValidAny, trueblnr)) { p->opsize = 1; if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { p->MainClass = kIKindPack; } } } else { p->opsize = 2; if (CheckValidAddrMode(p, 4, reg(p), kAddrValidAny, trueblnr)) { p->opsize = 1; if (CheckValidAddrMode(p, 4, rg9(p), kAddrValidAny, falseblnr)) { p->MainClass = kIKindPack; } } } break; case 2: /* UNPK 1000rrr11000mrrr */ if (mode(p) == 0) { p->opsize = 1; if (CheckValidAddrMode(p, 0, reg(p), kAddrValidAny, trueblnr)) { p->opsize = 2; if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { p->MainClass = kIKindUnpk; } } } else { p->opsize = 1; if (CheckValidAddrMode(p, 4, reg(p), kAddrValidAny, trueblnr)) { p->opsize = 2; if (CheckValidAddrMode(p, 4, rg9(p), kAddrValidAny, falseblnr)) { p->MainClass = kIKindUnpk; } } } break; #endif default: p->MainClass = kIKindIllegal; break; } } else { /* OR 1000ddd1ssmmmrrr */ #if 0 if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindOrDEa; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAltMem, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindOrDEa; } } } } } LOCALPROCUSEDONCE DeCode9(WorkR *p) { if (b76(p) == 3) { /* SUBA 1001dddm11mmmrrr */ #if 0 if (IsValidAddrMode(p)) { p->MainClass = kIKindSubA; } #endif p->opsize = b8(p) * 2 + 2; SetDcoArgFields(p, falseblnr, kAMdRegL, rg9(p) + 8); /* always long, regardless of opsize */ if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) { #if WantCycByPriOp if (4 == p->opsize) { if ((mode(p) < 2) || ((7 == mode(p)) && (reg(p) == 4))) { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } } else { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindSubA; } } else { if (b8(p) == 0) { /* SUB 1001ddd0ssmmmrrr */ #if 0 if (IsValidAddrMode(p)) { p->MainClass = kIKindSubEaR; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp if (4 == p->opsize) { if ((mode(p) < 2) || ((7 == mode(p)) && (reg(p) == 4))) { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } } else { p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindSubB + OpSizeOffset(p); } } else { if (mode(p) == 0) { /* SUBX 1001ddd1ss000rrr */ /* p->MainClass = kIKindSubXd; */ FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 0, reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (8 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindSubXB + OpSizeOffset(p); } } else if (mode(p) == 1) { /* SUBX 1001ddd1ss001rrr */ /* p->MainClass = kIKindSubXm; */ FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 4, reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 4, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (30 * kCycleScale + 5 * RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (18 * kCycleScale + 3 * RdAvgXtraCyc + 1 * WrAvgXtraCyc); #endif p->MainClass = kIKindSubXB + OpSizeOffset(p); } } else { /* SUB 1001ddd1ssmmmrrr */ #if 0 if (CheckAltMemAddrMode(p)) { p->MainClass = kIKindSubREa; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAltMem, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindSubB + OpSizeOffset(p); } } } } } LOCALPROCUSEDONCE DeCodeA(WorkR *p) { #if WantCycByPriOp p->Cycles = (34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif p->MainClass = kIKindA; } LOCALPROCUSEDONCE DeCodeB(WorkR *p) { if (b76(p) == 3) { /* CMPA 1011ddds11mmmrrr */ #if 0 if (IsValidAddrMode(p)) { p->MainClass = kIKindCmpA; } #endif p->opsize = b8(p) * 2 + 2; SetDcoArgFields(p, falseblnr, kAMdRegL, rg9(p) + 8); /* always long, regardless of opsize */ if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) { #if WantCycByPriOp p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindCmpA; } } else if (b8(p) == 1) { if (mode(p) == 1) { /* CmpM 1011ddd1ss001rrr */ #if 0 p->MainClass = kIKindCmpM; #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 3, reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 3, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (20 * kCycleScale + 5 * RdAvgXtraCyc) : (12 * kCycleScale + 3 * RdAvgXtraCyc); #endif p->MainClass = kIKindCmpB + OpSizeOffset(p); } } else { #if 0 /* Eor 1011ddd1ssmmmrrr */ if (CheckDataAltAddrMode(p)) { p->MainClass = kIKindEor; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidDataAlt, falseblnr)) { #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (4 == p->opsize) ? (8 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindEor; } } } else { /* Cmp 1011ddd0ssmmmrrr */ #if 0 if (IsValidAddrMode(p)) { p->MainClass = kIKindCmp; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (6 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindCmpB + OpSizeOffset(p); } } } LOCALPROCUSEDONCE DeCodeC(WorkR *p) { if (b76(p) == 3) { p->opsize = 2; if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidData, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp #if WantCloserCyc p->Cycles = (38 * kCycleScale + RdAvgXtraCyc); #else p->Cycles = (54 * kCycleScale + RdAvgXtraCyc); /* worst case 70, best case 38 */ #endif p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif if (b8(p) == 0) { /* MulU 1100ddd011mmmrrr */ p->MainClass = kIKindMulU; } else { /* MulS 1100ddd111mmmrrr */ p->MainClass = kIKindMulS; } } } else { if (b8(p) == 0) { /* And 1100ddd0ssmmmrrr */ #if 0 if (CheckDataAddrMode(p)) { p->MainClass = kIKindAndEaD; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidData, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp if (4 == p->opsize) { if ((mode(p) < 2) || ((7 == mode(p)) && (reg(p) == 4))) { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } } else { p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindAndEaD; } } else { if (mode(p) < 2) { switch (b76(p)) { case 0: /* ABCD 1100ddd10000mrrr */ #if WantCycByPriOp if (0 != mode(p)) { p->Cycles = (18 * kCycleScale + 3 * RdAvgXtraCyc + WrAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } #endif p->opsize = 1; if (mode(p) == 0) { if (CheckValidAddrMode(p, 0, reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { p->MainClass = kIKindAbcd; } } else { if (CheckValidAddrMode(p, 4, reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 4, rg9(p), kAddrValidAny, falseblnr)) { p->MainClass = kIKindAbcd; } } break; case 1: /* Exg 1100ddd10100trrr */ #if WantCycByPriOp p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); #endif p->opsize = 4; if (mode(p) == 0) { if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 0, reg(p), kAddrValidAny, falseblnr)) { p->MainClass = kIKindExg; } } else { if (CheckValidAddrMode(p, 1, rg9(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 1, reg(p), kAddrValidAny, falseblnr)) { p->MainClass = kIKindExg; } } break; case 2: default: /* keep compiler happy */ if (mode(p) == 0) { p->MainClass = kIKindIllegal; } else { /* Exg 1100ddd110001rrr */ #if WantCycByPriOp p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); #endif if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 1, reg(p), kAddrValidAny, falseblnr)) { p->MainClass = kIKindExg; } } break; } } else { /* And 1100ddd1ssmmmrrr */ #if 0 if (CheckAltMemAddrMode(p)) { p->MainClass = kIKindAndDEa; } #endif FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAltMem, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindAndDEa; } } } } } LOCALPROCUSEDONCE DeCodeD(WorkR *p) { if (b76(p) == 3) { /* ADDA 1101dddm11mmmrrr */ p->opsize = b8(p) * 2 + 2; SetDcoArgFields(p, falseblnr, kAMdRegL, rg9(p) + 8); /* always long, regardless of opsize */ if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) { #if WantCycByPriOp if (4 == p->opsize) { if ((mode(p) < 2) || ((7 == mode(p)) && (reg(p) == 4))) { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } } else { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindAddA; } } else { if (b8(p) == 0) { /* ADD 1101ddd0ssmmmrrr */ FindOpSizeFromb76(p); if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp if (4 == p->opsize) { if ((mode(p) < 2) || ((7 == mode(p)) && (reg(p) == 4))) { p->Cycles = (8 * kCycleScale + RdAvgXtraCyc); } else { p->Cycles = (6 * kCycleScale + RdAvgXtraCyc); } } else { p->Cycles = (4 * kCycleScale + RdAvgXtraCyc); } p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindAddB + OpSizeOffset(p); } } else { if (mode(p) == 0) { /* ADDX 1101ddd1ss000rrr */ /* p->MainClass = kIKindAddXd; */ FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 0, reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (8 * kCycleScale + RdAvgXtraCyc) : (4 * kCycleScale + RdAvgXtraCyc); #endif p->MainClass = kIKindAddXB + OpSizeOffset(p); } } else if (mode(p) == 1) { /* p->MainClass = kIKindAddXm; */ FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 4, reg(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 4, rg9(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (30 * kCycleScale + 5 * RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (18 * kCycleScale + 3 * RdAvgXtraCyc + 1 * WrAvgXtraCyc); #endif p->MainClass = kIKindAddXB + OpSizeOffset(p); } } else { /* ADD 1101ddd1ssmmmrrr */ FindOpSizeFromb76(p); if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, mode(p), reg(p), kAddrValidAltMem, falseblnr)) { #if WantCycByPriOp p->Cycles = (4 == p->opsize) ? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc) : (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = kIKindAddB + OpSizeOffset(p); } } } } } LOCALFUNC ui5r rolops(WorkR *p, ui5r x) { ui5r binop; binop = (x << 1); if (! b8(p)) { binop++; /* 'R' */ } /* else 'L' */ return kIKindAslB + 3 * binop + OpSizeOffset(p); } LOCALPROCUSEDONCE DeCodeE(WorkR *p) { if (b76(p) == 3) { if ((p->opcode & 0x0800) != 0) { #if Use68020 /* 11101???11mmmrrr */ p->DecOp.y.v[0].AMd = mode(p); p->DecOp.y.v[0].ArgDat = (p->opcode >> 8) & 7; if (0 == mode(p)) { SetDcoArgFields(p, falseblnr, kAMdRegL, reg(p)); p->MainClass = kIKindBitField; } else { switch ((p->opcode >> 8) & 7) { case 0: /* BFTST */ case 1: /* BFEXTU */ case 3: /* BFEXTS */ case 5: /* BFFFO */ if (CheckControlAddrMode(p)) { p->MainClass = kIKindBitField; } break; default: /* BFCHG, BFCLR, BFSET, BFINS */ if (CheckControlAltAddrMode(p)) { p->MainClass = kIKindBitField; } break; } } #else p->MainClass = kIKindIllegal; #endif } else { p->opsize = 2; /* 11100ttd11mmmddd */ if (CheckAltMemAddrMode(p)) { #if WantCycByPriOp p->Cycles = (6 * kCycleScale #if ! WantCloserCyc + 2 * kCycleScale #endif + RdAvgXtraCyc + WrAvgXtraCyc); p->Cycles += OpEACalcCyc(p, mode(p), reg(p)); #endif p->MainClass = rolops(p, rg9(p)); SetDcoArgFields(p, trueblnr, kAMdDat4, 1); } } } else { FindOpSizeFromb76(p); if (mode(p) < 4) { /* 1110cccdss0ttddd */ if (CheckValidAddrMode(p, 0, reg(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp p->Cycles = ((4 == p->opsize) ? (8 * kCycleScale + RdAvgXtraCyc) : (6 * kCycleScale + RdAvgXtraCyc)) #if ! WantCloserCyc + (octdat(rg9(p)) * (2 * kCycleScale)) #endif ; #endif p->MainClass = rolops(p, mode(p) & 3); SetDcoArgFields(p, trueblnr, kAMdDat4, octdat(rg9(p))); } } else { /* 1110rrrdss1ttddd */ if (CheckValidAddrMode(p, 0, rg9(p), kAddrValidAny, trueblnr)) if (CheckValidAddrMode(p, 0, reg(p), kAddrValidAny, falseblnr)) { #if WantCycByPriOp #if WantCloserCyc p->Cycles = ((4 == p->opsize) ? (8 * kCycleScale + RdAvgXtraCyc) : (6 * kCycleScale + RdAvgXtraCyc)); #else p->Cycles = (4 == p->opsize) ? ((8 * kCycleScale) + RdAvgXtraCyc + (8 * (2 * kCycleScale))) /* say average shift count of 8 */ : ((6 * kCycleScale) + RdAvgXtraCyc + (4 * (2 * kCycleScale))); /* say average shift count of 4 */ #endif #endif p->MainClass = rolops(p, mode(p) & 3); } } } } LOCALPROCUSEDONCE DeCodeF(WorkR *p) { #if WantCycByPriOp p->Cycles = (34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif p->DecOp.y.v[0].AMd = (p->opcode >> 8) & 0xFF; p->DecOp.y.v[0].ArgDat = (p->opcode ) & 0xFF; #if EmMMU || EmFPU switch (rg9(p)) { #if EmMMU case 0: p->MainClass = kIKindMMU; break; #endif #if EmFPU case 1: switch (md6(p)) { case 0: p->MainClass = kIKindFPUmd60; break; case 1: if (mode(p) == 1) { p->MainClass = kIKindFPUDBcc; } else if (mode(p) == 7) { p->MainClass = kIKindFPUTrapcc; } else { p->MainClass = kIKindFPUScc; } break; case 2: p->MainClass = kIKindFPUFBccW; break; case 3: p->MainClass = kIKindFPUFBccL; break; case 4: p->MainClass = kIKindFPUSave; break; case 5: p->MainClass = kIKindFPURestore; break; default: p->MainClass = kIKindFPUdflt; break; } break; #endif default: p->MainClass = kIKindFdflt; break; } #else p->MainClass = kIKindFdflt; #endif } LOCALPROC DeCodeOneOp(WorkR *p) { switch (p->opcode >> 12) { case 0x0: DeCode0(p); break; case 0x1: DeCode1(p); break; case 0x2: DeCode2(p); break; case 0x3: DeCode3(p); break; case 0x4: DeCode4(p); break; case 0x5: DeCode5(p); break; case 0x6: DeCode6(p); break; case 0x7: DeCode7(p); break; case 0x8: DeCode8(p); break; case 0x9: DeCode9(p); break; case 0xA: DeCodeA(p); break; case 0xB: DeCodeB(p); break; case 0xC: DeCodeC(p); break; case 0xD: DeCodeD(p); break; case 0xE: DeCodeE(p); break; case 0xF: default: /* keep compiler happy */ DeCodeF(p); break; } if (kIKindIllegal == p->MainClass) { #if WantCycByPriOp p->Cycles = (34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif p->DecOp.y.v[0].AMd = 0; p->DecOp.y.v[0].ArgDat = 0; p->DecOp.y.v[1].AMd = 0; p->DecOp.y.v[1].ArgDat = 0; } SetDcoMainClas(&(p->DecOp), p->MainClass); #if WantCycByPriOp SetDcoCycles(&(p->DecOp), p->Cycles); #else SetDcoCycles(&(p->DecOp), kMyAvgCycPerInstr); #endif } GLOBALPROC M68KITAB_setup(DecOpR *p) { ui5b i; WorkR r; for (i = 0; i < (ui5b)256 * 256; ++i) { r.opcode = i; r.MainClass = kIKindIllegal; r.DecOp.y.v[0].AMd = 0; r.DecOp.y.v[0].ArgDat = 0; r.DecOp.y.v[1].AMd = 0; r.DecOp.y.v[1].ArgDat = 0; #if WantCycByPriOp r.Cycles = kMyAvgCycPerInstr; #endif DeCodeOneOp(&r); p[i] = r.DecOp; } } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/M68KITAB.h b/Mini vMac/mnvm_core/M68KITAB.h index 52b050d..5cfffca 100755 --- a/Mini vMac/mnvm_core/M68KITAB.h +++ b/Mini vMac/mnvm_core/M68KITAB.h @@ -1,234 +1 @@ -/* - M68KITAB.h - - Copyright (C) 2007, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef M68KITAB_H -#error "header already included" -#else -#define M68KITAB_H -#endif - -enum { - kIKindTst, - kIKindCmpB, - kIKindCmpW, - kIKindCmpL, - kIKindBccB, - kIKindBccW, - kIKindBraB, - kIKindBraW, - kIKindDBcc, - kIKindDBF, - kIKindSwap, - kIKindMoveL, - kIKindMoveW, - kIKindMoveB, - kIKindMoveAL, - kIKindMoveAW, - kIKindMoveQ, - kIKindAddB, - kIKindAddW, - kIKindAddL, - kIKindSubB, - kIKindSubW, - kIKindSubL, - kIKindLea, - kIKindPEA, - kIKindA, - kIKindBsrB, - kIKindBsrW, - kIKindJsr, - kIKindLinkA6, - kIKindMOVEMRmML, - kIKindMOVEMApRL, - kIKindUnlkA6, - kIKindRts, - kIKindJmp, - kIKindClr, - kIKindAddA, - kIKindAddQA, - kIKindSubA, - kIKindSubQA, - kIKindCmpA, - kIKindAddXB, - kIKindAddXW, - kIKindAddXL, - kIKindSubXB, - kIKindSubXW, - kIKindSubXL, - kIKindRolopNM, - kIKindRolopND, - kIKindRolopDD, - kIKindBitOpDD, - kIKindBitOpDM, - kIKindBitOpND, - kIKindBitOpNM, - kIKindAndI, - kIKindAndEaD, - kIKindAndDEa, - kIKindOrI, - kIKindOrDEa, - kIKindOrEaD, - kIKindEor, - kIKindEorI, - kIKindNot, - kIKindScc, - kIKindNegXB, - kIKindNegXW, - kIKindNegXL, - kIKindNegB, - kIKindNegW, - kIKindNegL, - kIKindEXTW, - kIKindEXTL, - kIKindMulU, - kIKindMulS, - kIKindDivU, - kIKindDivS, - kIKindExgdd, - kIKindExgaa, - kIKindExgda, - kIKindMoveCCREa, - kIKindMoveEaCCR, - kIKindMoveSREa, - kIKindMoveEaSR, - kIKindBinOpStatusCCR, - kIKindMOVEMApRW, - kIKindMOVEMRmMW, - kIKindMOVEMrm, - kIKindMOVEMmr, - kIKindAbcdr, - kIKindAbcdm, - kIKindSbcdr, - kIKindSbcdm, - kIKindNbcd, - kIKindRte, - kIKindNop, - kIKindMoveP, - kIKindIllegal, - kIKindChkW, - kIKindTrap, - kIKindTrapV, - kIKindRtr, - kIKindLink, - kIKindUnlk, - kIKindMoveRUSP, - kIKindMoveUSPR, - kIKindTas, - kIKindF, - kIKindCallMorRtm, - kIKindStop, - kIKindReset, - -#if Use68020 - kIKindBraL, - kIKindBccL, - kIKindBsrL, - kIKindEXTBL, - kIKindTRAPcc, - kIKindChkL, - kIKindBkpt, - kIKindDivL, - kIKindMulL, - kIKindRtd, - kIKindMoveC, - kIKindLinkL, - kIKindPack, - kIKindUnpk, - kIKindCHK2orCMP2, - kIKindCAS2, - kIKindCAS, - kIKindMoveS, - kIKindBitField, -#endif - - kNumIKinds -}; - -enum { - kAMdReg, - kAMdIndirect, - kAMdAPosIncB, - kAMdAPosIncW, - kAMdAPosIncL, - kAMdAPreDecB, - kAMdAPreDecW, - kAMdAPreDecL, - kAMdADisp, - kAMdAIndex, - kAMdAbsW, - kAMdAbsL, - kAMdPCDisp, - kAMdPCIndex, - kAMdImmedB, - kAMdImmedW, - kAMdImmedL, - kAMdDat4, - - kNumAMds -}; - -enum { - kArgkRegB, - kArgkRegW, - kArgkRegL, - kArgkMemB, - kArgkMemW, - kArgkMemL, - kArgkCnst, - - kNumArgks -}; - -struct DecOpR { - /* expected size : 8 bytes */ - ui5b A; - ui5b B; -}; -typedef struct DecOpR DecOpR; - -#define GetUi5rField(v, shift, sz) \ - (((v) >> (shift)) & ((1UL << (sz)) - 1)) -#define SetUi5rField(v, shift, sz, x) \ - (v) = (((v) & ~ (((1UL << (sz)) - 1) << (shift))) \ - | (((x) & ((1UL << (sz)) - 1)) << (shift))) - -#define GetDcoFldAMd(f) (GetUi5rField((f), 16, 8)) -#define GetDcoFldArgk(f) (GetUi5rField((f), 24, 4)) -#define GetDcoFldArgDat(f) (GetUi5rField((f), 28, 4)) - -#define SetDcoFldAMd(f, x) SetUi5rField((f), 16, 8, x) -#define SetDcoFldArgk(f, x) SetUi5rField((f), 24, 4, x) -#define SetDcoFldArgDat(f, x) SetUi5rField((f), 28, 4, x) - -#define GetDcoMainClas(p) (GetUi5rField((p)->A, 0, 16)) -#define GetDcoDstAMd(p) (GetDcoFldAMd((p)->A)) -#define GetDcoDstArgk(p) (GetDcoFldArgk((p)->A)) -#define GetDcoDstArgDat(p) (GetDcoFldArgDat((p)->A)) -#define GetDcoSrcAMd(p) (GetDcoFldAMd((p)->B)) -#define GetDcoSrcArgk(p) (GetDcoFldArgk((p)->B)) -#define GetDcoSrcArgDat(p) (GetDcoFldArgDat((p)->B)) -#define GetDcoCycles(p) (GetUi5rField((p)->B, 0, 16)) - -#define SetDcoMainClas(p, x) SetUi5rField((p)->A, 0, 16, x) -#define SetDcoDstAMd(p, x) SetDcoFldAMd((p)->A, x) -#define SetDcoDstArgk(p, x) SetDcoFldArgk((p)->A, x) -#define SetDcoDstArgDat(p, x) SetDcoFldArgDat((p)->A, x) -#define SetDcoSrcAMd(p, x) SetDcoFldAMd((p)->B, x) -#define SetDcoSrcArgk(p, x) SetDcoFldArgk((p)->B, x) -#define SetDcoSrcArgDat(p, x) SetDcoFldArgDat((p)->B, x) -#define SetDcoCycles(p, x) SetUi5rField((p)->B, 0, 16, x) - -EXPORTPROC M68KITAB_setup(DecOpR *p); +/* M68KITAB.h Copyright (C) 2007, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef M68KITAB_H #error "header already included" #else #define M68KITAB_H #endif enum { kIKindTst, kIKindCmpB, kIKindCmpW, kIKindCmpL, kIKindBccB, kIKindBccW, kIKindBraB, kIKindBraW, kIKindDBcc, kIKindDBF, kIKindSwap, kIKindMoveL, kIKindMoveW, kIKindMoveB, kIKindMoveAL, kIKindMoveAW, kIKindMoveQ, kIKindAddB, kIKindAddW, kIKindAddL, kIKindSubB, kIKindSubW, kIKindSubL, kIKindLea, kIKindPEA, kIKindA, kIKindBsrB, kIKindBsrW, kIKindJsr, kIKindLinkA6, kIKindMOVEMRmML, kIKindMOVEMApRL, kIKindUnlkA6, kIKindRts, kIKindJmp, kIKindClr, kIKindAddA, kIKindAddQA, kIKindSubA, kIKindSubQA, kIKindCmpA, kIKindAddXB, kIKindAddXW, kIKindAddXL, kIKindSubXB, kIKindSubXW, kIKindSubXL, kIKindAslB, kIKindAslW, kIKindAslL, kIKindAsrB, kIKindAsrW, kIKindAsrL, kIKindLslB, kIKindLslW, kIKindLslL, kIKindLsrB, kIKindLsrW, kIKindLsrL, kIKindRxlB, kIKindRxlW, kIKindRxlL, kIKindRxrB, kIKindRxrW, kIKindRxrL, kIKindRolB, kIKindRolW, kIKindRolL, kIKindRorB, kIKindRorW, kIKindRorL, kIKindBTstB, kIKindBChgB, kIKindBClrB, kIKindBSetB, kIKindBTstL, kIKindBChgL, kIKindBClrL, kIKindBSetL, kIKindAndI, kIKindAndEaD, kIKindAndDEa, kIKindOrI, kIKindOrDEa, kIKindOrEaD, kIKindEor, kIKindEorI, kIKindNot, kIKindScc, kIKindNegXB, kIKindNegXW, kIKindNegXL, kIKindNegB, kIKindNegW, kIKindNegL, kIKindEXTW, kIKindEXTL, kIKindMulU, kIKindMulS, kIKindDivU, kIKindDivS, kIKindExg, kIKindMoveEaCCR, kIKindMoveSREa, kIKindMoveEaSR, kIKindOrISR, kIKindAndISR, kIKindEorISR, kIKindOrICCR, kIKindAndICCR, kIKindEorICCR, kIKindMOVEMApRW, kIKindMOVEMRmMW, kIKindMOVEMrmW, kIKindMOVEMrmL, kIKindMOVEMmrW, kIKindMOVEMmrL, kIKindAbcd, kIKindSbcd, kIKindNbcd, kIKindRte, kIKindNop, kIKindMoveP0, kIKindMoveP1, kIKindMoveP2, kIKindMoveP3, kIKindIllegal, kIKindChkW, kIKindTrap, kIKindTrapV, kIKindRtr, kIKindLink, kIKindUnlk, kIKindMoveRUSP, kIKindMoveUSPR, kIKindTas, kIKindFdflt, kIKindStop, kIKindReset, #if Use68020 kIKindCallMorRtm, kIKindBraL, kIKindBccL, kIKindBsrL, kIKindEXTBL, kIKindTRAPcc, kIKindChkL, kIKindBkpt, kIKindDivL, kIKindMulL, kIKindRtd, kIKindMoveCCREa, kIKindMoveCEa, kIKindMoveEaC, kIKindLinkL, kIKindPack, kIKindUnpk, kIKindCHK2orCMP2, kIKindCAS2, kIKindCAS, kIKindMoveS, kIKindBitField, #endif #if EmMMU kIKindMMU, #endif #if EmFPU kIKindFPUmd60, kIKindFPUDBcc, kIKindFPUTrapcc, kIKindFPUScc, kIKindFPUFBccW, kIKindFPUFBccL, kIKindFPUSave, kIKindFPURestore, kIKindFPUdflt, #endif kNumIKinds }; enum { kAMdRegB, kAMdRegW, kAMdRegL, kAMdIndirectB, kAMdIndirectW, kAMdIndirectL, kAMdAPosIncB, kAMdAPosIncW, kAMdAPosIncL, kAMdAPosInc7B, kAMdAPreDecB, kAMdAPreDecW, kAMdAPreDecL, kAMdAPreDec7B, kAMdADispB, kAMdADispW, kAMdADispL, kAMdAIndexB, kAMdAIndexW, kAMdAIndexL, kAMdAbsWB, kAMdAbsWW, kAMdAbsWL, kAMdAbsLB, kAMdAbsLW, kAMdAbsLL, kAMdPCDispB, kAMdPCDispW, kAMdPCDispL, kAMdPCIndexB, kAMdPCIndexW, kAMdPCIndexL, kAMdImmedB, kAMdImmedW, kAMdImmedL, kAMdDat4, kNumAMds }; struct DecOpXR { /* expected size : 4 bytes */ ui4b MainClas; ui4b Cycles; }; typedef struct DecOpXR DecOpXR; struct DecArgR { /* expected size : 2 bytes */ ui3b AMd; ui3b ArgDat; }; typedef struct DecArgR DecArgR; struct DecOpYR { /* expected size : 4 bytes */ DecArgR v[2]; }; typedef struct DecOpYR DecOpYR; struct DecOpR { /* expected size : 8 bytes */ DecOpXR x; DecOpYR y; } my_align_8; typedef struct DecOpR DecOpR; #define GetDcoCycles(p) ((p)->x.Cycles) #define SetDcoMainClas(p, xx) ((p)->x.MainClas = (xx)) #define SetDcoCycles(p, xx) ((p)->x.Cycles = (xx)) EXPORTPROC M68KITAB_setup(DecOpR *p); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/MINEM68K.c b/Mini vMac/mnvm_core/MINEM68K.c index c6a37f7..a6c2121 100755 --- a/Mini vMac/mnvm_core/MINEM68K.c +++ b/Mini vMac/mnvm_core/MINEM68K.c @@ -1,5107 +1 @@ -/* - MINEM68K.c - - Copyright (C) 2009 Bernd Schmidt, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - MINimum EMulator of 68K cpu - - This code descends from a simple 68000 emulator that I - (Paul C. Pratt) wrote long ago. That emulator ran on a 680x0, - and used the cpu it ran on to do some of the work. This - descendent fills in those holes with code from the - Un*x Amiga Emulator by Bernd Schmidt, as found being used in vMac. - - This emulator is about 10 times smaller than the UAE, - at the cost of being 2 to 3 times slower. - - FPU Emulation added 9/12/2009 by Ross Martin - (this code now located in "FPCPEMDV.h") -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" - -#include "MYOSGLUE.h" -#include "ENDIANAC.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" - -#include "M68KITAB.h" - -#if WantDisasm -#include "DISAM68K.h" -#endif -#endif - -#include "MINEM68K.h" - -typedef unsigned char flagtype; - - -/* Memory Address Translation Cache record */ - -struct MATCr { - ui5r cmpmask; - ui5r cmpvalu; - ui5r usemask; - ui3p usebase; -}; -typedef struct MATCr MATCr; -typedef MATCr *MATCp; - -/* - This variable was introduced because a program could do a Bcc from - within chip memory to a location within expansion memory. With a - pointer variable the program counter would point to the wrong - location. With this variable unset the program counter is always - correct, but programs will run slower (about 4%). - Usually, you'll want to have this defined. - - vMac REQUIRES this. It allows for fun things like Restart. -*/ - -#ifndef USE_POINTER -#define USE_POINTER 1 -#endif - -#define AKMemory 0 -#define AKRegister 1 -#define AKConstant 2 - -union ArgAddrT { - ui5r mem; - ui5r *rga; -}; -typedef union ArgAddrT ArgAddrT; - -LOCALVAR struct regstruct -{ - ui5r regs[16]; /* Data and Address registers */ - ui5r pc; /* Program Counter */ - CPTR usp; /* User Stack Pointer */ - CPTR isp; /* Interrupt Stack Pointer */ -#if Use68020 - CPTR msp; /* Master Stack Pointer */ -#endif - - /* Status Register */ - ui5r intmask; /* bits 10-8 : interrupt priority mask */ - flagtype t1; /* bit 15: Trace mode 1 */ -#if Use68020 - flagtype t0; /* bit 14: Trace mode 0 */ -#endif - flagtype s; /* bit 13: Supervisor or user privilege level */ -#if Use68020 - flagtype m; /* bit 12: Master or interrupt mode */ -#endif - flagtype x; /* bit 4: eXtend */ - flagtype n; /* bit 3: Negative */ - flagtype z; /* bit 2: Zero */ - flagtype v; /* bit 1: oVerflow */ - flagtype c; /* bit 0: Carry */ - - flagtype TracePending; - flagtype ExternalInterruptPending; -#if 0 - flagtype ResetPending; -#endif - ui3b *fIPL; - -#if Use68020 - ui5b sfc; /* Source Function Code register */ - ui5b dfc; /* Destination Function Code register */ - ui5b vbr; /* Vector Base Register */ - ui5b cacr; /* Cache Control Register */ - /* - bit 0 : Enable Cache - bit 1 : Freeze Cache - bit 2 : Clear Entry In Cache (write only) - bit 3 : Clear Cache (write only) - */ - ui5b caar; /* Cache Address Register */ -#endif - MATCr MATCrdB; - MATCr MATCwrB; - MATCr MATCrdW; - MATCr MATCwrW; - MATCr MATCex; - ATTep HeadATTel; - DecOpR CurDecOp; - - -#if USE_POINTER - ui3p pc_p; - ui3p pc_oldp; -#endif - ui5b opsize; - ui5b ArgKind; - ArgAddrT ArgAddr; - ui5b SrcVal; - ui5b opcode; - si5r MaxCyclesToGo; - si5r MoreCyclesToGo; - si5r ResidualCycles; - ui3b fakeword[2]; - -#define disp_table_sz (256 * 256) -#if SmallGlobals - DecOpR *disp_table; -#else - DecOpR disp_table[disp_table_sz]; -#endif -} regs; - -#define ui5r_MSBisSet(x) (((si5r)(x)) < 0) - -#define ZFLG regs.z -#define NFLG regs.n -#define CFLG regs.c -#define VFLG regs.v -#define XFLG regs.x - -LOCALFUNC ui4b m68k_getCR(void) -{ - return (XFLG << 4) | (NFLG << 3) | (ZFLG << 2) - | (VFLG << 1) | CFLG; -} - -LOCALFUNC MayInline void m68k_setCR(ui4b newcr) -{ - XFLG = (newcr >> 4) & 1; - NFLG = (newcr >> 3) & 1; - ZFLG = (newcr >> 2) & 1; - VFLG = (newcr >> 1) & 1; - CFLG = newcr & 1; -} - -LOCALFUNC MayInline blnr cctrue(void) -{ - switch ((regs.opcode >> 8) & 15) { - case 0: return trueblnr; /* T */ - case 1: return falseblnr; /* F */ - case 2: return (! CFLG) && (! ZFLG); /* HI */ - case 3: return CFLG || ZFLG; /* LS */ - case 4: return ! CFLG; /* CC */ - case 5: return CFLG; /* CS */ - case 6: return ! ZFLG; /* NE */ - case 7: return ZFLG; /* EQ */ - case 8: return ! VFLG; /* VC */ - case 9: return VFLG; /* VS */ - case 10: return ! NFLG; /* PL */ - case 11: return NFLG; /* MI */ - case 12: return NFLG == VFLG; /* GE */ - case 13: return NFLG != VFLG; /* LT */ - case 14: return (! ZFLG) && (NFLG == VFLG); /* GT */ - case 15: return ZFLG || (NFLG != VFLG); /* LE */ - default: return falseblnr; /* shouldn't get here */ - } -} - -LOCALPROC ALU_CmpB(ui5r srcvalue, ui5r dstvalue) -{ - ui5r result0 = dstvalue - srcvalue; - ui5r result1 = ui5r_FromUByte(dstvalue) - ui5r_FromUByte(srcvalue); - ui5r result = ui5r_FromSByte(result0); - - ZFLG = (result == 0); - NFLG = ui5r_MSBisSet(result); - VFLG = (((result0 >> 1) ^ result0) >> 7) & 1; - CFLG = (result1 >> 8) & 1; -} - -LOCALPROC ALU_CmpW(ui5r srcvalue, ui5r dstvalue) -{ - ui5r result0 = dstvalue - srcvalue; - ui5r result1 = ui5r_FromUWord(dstvalue) - ui5r_FromUWord(srcvalue); - ui5r result = ui5r_FromSWord(result0); - - ZFLG = (result == 0); - NFLG = ui5r_MSBisSet(result); - VFLG = (((result0 >> 1) ^ result0) >> 15) & 1; - CFLG = (result1 >> 16) & 1; -} - -LOCALPROC ALU_CmpL(ui5r srcvalue, ui5r dstvalue) -{ - ui5r result = ui5r_FromSLong(dstvalue - srcvalue); - - int flgs = ui5r_MSBisSet(srcvalue); - int flgo = ui5r_MSBisSet(dstvalue); - ZFLG = (result == 0); - NFLG = ui5r_MSBisSet(result); - VFLG = (flgs != flgo) && (NFLG != flgo); - CFLG = (flgs && ! flgo) || (NFLG && ((! flgo) || flgs)); -} - -LOCALFUNC ui5r ALU_AddB(ui5r srcvalue, ui5r dstvalue) -{ - ui5r result0 = dstvalue + srcvalue; - ui5r result1 = ui5r_FromUByte(dstvalue) + ui5r_FromUByte(srcvalue); - ui5r result = ui5r_FromSByte(result0); - - ZFLG = (result == 0); - NFLG = ui5r_MSBisSet(result); - VFLG = (((result0 >> 1) ^ result0) >> 7) & 1; - XFLG = CFLG = (result1 >> 8); - - return result; -} - -LOCALFUNC ui5r ALU_AddW(ui5r srcvalue, ui5r dstvalue) -{ - ui5r result0 = dstvalue + srcvalue; - ui5r result1 = ui5r_FromUWord(dstvalue) + ui5r_FromUWord(srcvalue); - ui5r result = ui5r_FromSWord(result0); - - ZFLG = (result == 0); - NFLG = ui5r_MSBisSet(result); - VFLG = (((result0 >> 1) ^ result0) >> 15) & 1; - XFLG = CFLG = (result1 >> 16); - - return result; -} - -LOCALFUNC ui5r ALU_AddL(ui5r srcvalue, ui5r dstvalue) -{ - ui5r result = ui5r_FromSLong(dstvalue + srcvalue); - - int flgs = ui5r_MSBisSet(srcvalue); - int flgo = ui5r_MSBisSet(dstvalue); - ZFLG = (result == 0); - NFLG = ui5r_MSBisSet(result); - VFLG = (flgs && flgo && ! NFLG) || ((! flgs) && (! flgo) && NFLG); - XFLG = CFLG = (flgs && flgo) || ((! NFLG) && (flgo || flgs)); - - return result; -} - -LOCALFUNC ui5r ALU_SubB(ui5r srcvalue, ui5r dstvalue) -{ - ui5r result0 = dstvalue - srcvalue; - ui5r result1 = ui5r_FromUByte(dstvalue) - ui5r_FromUByte(srcvalue); - ui5r result = ui5r_FromSByte(result0); - - ZFLG = (result == 0); - NFLG = ui5r_MSBisSet(result); - VFLG = (((result0 >> 1) ^ result0) >> 7) & 1; - XFLG = CFLG = (result1 >> 8) & 1; - - return result; -} - -LOCALFUNC ui5r ALU_SubW(ui5r srcvalue, ui5r dstvalue) -{ - ui5r result0 = dstvalue - srcvalue; - ui5r result1 = ui5r_FromUWord(dstvalue) - ui5r_FromUWord(srcvalue); - ui5r result = ui5r_FromSWord(result0); - - ZFLG = (result == 0); - NFLG = ui5r_MSBisSet(result); - VFLG = (((result0 >> 1) ^ result0) >> 15) & 1; - XFLG = CFLG = (result1 >> 16) & 1; - - return result; -} - -LOCALFUNC ui5r ALU_SubL(ui5r srcvalue, ui5r dstvalue) -{ - ui5r result = ui5r_FromSLong(dstvalue - srcvalue); - - int flgs = ui5r_MSBisSet(srcvalue); - int flgo = ui5r_MSBisSet(dstvalue); - ZFLG = (result == 0); - NFLG = ui5r_MSBisSet(result); - VFLG = (flgs != flgo) && (NFLG != flgo); - XFLG = CFLG = (flgs && ! flgo) || (NFLG && ((! flgo) || flgs)); - - return result; -} - -LOCALFUNC ui5r ALU_NegB(ui5r dstvalue) -{ - ui5r result = ui5r_FromSByte(0 - dstvalue); - - int flgs = ui5r_MSBisSet(dstvalue); - ZFLG = (result == 0); - NFLG = ui5r_MSBisSet(result); - VFLG = (flgs && NFLG); - XFLG = CFLG = (flgs || NFLG); - - return result; -} - -LOCALFUNC ui5r ALU_NegW(ui5r dstvalue) -{ - ui5r result = ui5r_FromSWord(0 - dstvalue); - - int flgs = ui5r_MSBisSet(dstvalue); - ZFLG = (result == 0); - NFLG = ui5r_MSBisSet(result); - VFLG = (flgs && NFLG); - XFLG = CFLG = (flgs || NFLG); - - return result; -} - -LOCALFUNC ui5r ALU_NegL(ui5r dstvalue) -{ - ui5r result = ui5r_FromSLong(0 - dstvalue); - - int flgs = ui5r_MSBisSet(dstvalue); - ZFLG = (result == 0); - NFLG = ui5r_MSBisSet(result); - VFLG = (flgs && NFLG); - XFLG = CFLG = (flgs || NFLG); - - return result; -} - -LOCALFUNC ui5r ALU_NegXB(ui5r dstvalue) -{ - ui5r result = ui5r_FromSByte(0 - dstvalue - (XFLG ? 1 : 0)); - - int flgs = ui5r_MSBisSet(dstvalue); - if (result != 0) { - ZFLG = 0; - } - NFLG = ui5r_MSBisSet(result); - VFLG = (flgs && NFLG); - XFLG = CFLG = (flgs || NFLG); - - return result; -} - -LOCALFUNC ui5r ALU_NegXW(ui5r dstvalue) -{ - ui5r result = ui5r_FromSWord(0 - dstvalue - (XFLG ? 1 : 0)); - - int flgs = ui5r_MSBisSet(dstvalue); - if (result != 0) { - ZFLG = 0; - } - NFLG = ui5r_MSBisSet(result); - VFLG = (flgs && NFLG); - XFLG = CFLG = (flgs || NFLG); - - return result; -} - -LOCALFUNC ui5r ALU_NegXL(ui5r dstvalue) -{ - ui5r result = ui5r_FromSLong(0 - dstvalue - (XFLG ? 1 : 0)); - - int flgs = ui5r_MSBisSet(dstvalue); - if (result != 0) { - ZFLG = 0; - } - NFLG = ui5r_MSBisSet(result); - VFLG = (flgs && NFLG); - XFLG = CFLG = (flgs || NFLG); - - return result; -} - -LOCALPROC SetCCRforAddX(ui5r srcvalue, ui5r dstvalue, ui5r result) -{ - int flgs = ui5r_MSBisSet(srcvalue); - int flgo = ui5r_MSBisSet(dstvalue); - if (result != 0) { - ZFLG = 0; - } - NFLG = ui5r_MSBisSet(result); - XFLG = CFLG = (flgs && flgo) || ((! NFLG) && (flgo || flgs)); - VFLG = (flgs && flgo && ! NFLG) || ((! flgs) && (! flgo) && NFLG); -} - -LOCALFUNC ui5r ALU_AddXB(ui5r srcvalue, ui5r dstvalue) -{ - ui5r result = ui5r_FromSByte(dstvalue + srcvalue + (XFLG ? 1 : 0)); - - SetCCRforAddX(srcvalue, dstvalue, result); - - return result; -} - -LOCALFUNC ui5r ALU_AddXW(ui5r srcvalue, ui5r dstvalue) -{ - ui5r result = ui5r_FromSWord(dstvalue + srcvalue + (XFLG ? 1 : 0)); - - SetCCRforAddX(srcvalue, dstvalue, result); - - return result; -} - -LOCALFUNC ui5r ALU_AddXL(ui5r srcvalue, ui5r dstvalue) -{ - ui5r result = ui5r_FromSLong(dstvalue + srcvalue + (XFLG ? 1 : 0)); - - SetCCRforAddX(srcvalue, dstvalue, result); - - return result; -} - -LOCALPROC SetCCRforSubX(ui5r srcvalue, ui5r dstvalue, ui5r result) -{ - int flgs = ui5r_MSBisSet(srcvalue); - int flgo = ui5r_MSBisSet(dstvalue); - if (result != 0) { - ZFLG = 0; - } - NFLG = ui5r_MSBisSet(result); - VFLG = ((! flgs) && flgo && (! NFLG)) || (flgs && (! flgo) && NFLG); - XFLG = CFLG = (flgs && (! flgo)) || (NFLG && ((! flgo) || flgs)); -} - -LOCALFUNC ui5r ALU_SubXB(ui5r srcvalue, ui5r dstvalue) -{ - ui5r result = ui5r_FromSByte(dstvalue - srcvalue - (XFLG ? 1 : 0)); - - SetCCRforSubX(srcvalue, dstvalue, result); - - return result; -} - -LOCALFUNC ui5r ALU_SubXW(ui5r srcvalue, ui5r dstvalue) -{ - ui5r result = ui5r_FromSWord(dstvalue - srcvalue - (XFLG ? 1 : 0)); - - SetCCRforSubX(srcvalue, dstvalue, result); - - return result; -} - -LOCALFUNC ui5r ALU_SubXL(ui5r srcvalue, ui5r dstvalue) -{ - ui5r result = ui5r_FromSLong(dstvalue - srcvalue - (XFLG ? 1 : 0)); - - SetCCRforSubX(srcvalue, dstvalue, result); - - return result; -} - - -#define m68k_logExceptions (dbglog_HAVE && 0) - - -GLOBALFUNC ATTep FindATTel(CPTR addr) -{ - ATTep prev; - ATTep p; - - p = regs.HeadATTel; - if ((addr & p->cmpmask) != p->cmpvalu) { - do { - prev = p; - p = p->Next; - } while ((addr & p->cmpmask) != p->cmpvalu); - - { - ATTep next = p->Next; - - if (nullpr == next) { - /* don't move the end guard */ - } else { - /* move to first */ - prev->Next = next; - p->Next = regs.HeadATTel; - regs.HeadATTel = p; - } - } - } - - return p; -} - -LOCALPROC SetUpMATC( - MATCp CurMATC, - ATTep p) -{ - CurMATC->cmpmask = p->cmpmask; - CurMATC->usemask = p->usemask; - CurMATC->cmpvalu = p->cmpvalu; - CurMATC->usebase = p->usebase; -} - -LOCALFUNC ui5r get_byte_ext(CPTR addr) -{ - ATTep p; - ui3p m; - ui5r AccFlags; - ui5r Data; - -Label_Retry: - p = FindATTel(addr); - AccFlags = p->Access; - - if (0 != (AccFlags & kATTA_readreadymask)) { - SetUpMATC(®s.MATCrdB, p); - m = p->usebase + (addr & p->usemask); - - Data = *m; - } else if (0 != (AccFlags & kATTA_mmdvmask)) { - Data = MMDV_Access(p, 0, falseblnr, trueblnr, addr); - } else if (0 != (AccFlags & kATTA_ntfymask)) { - if (MemAccessNtfy(p)) { - goto Label_Retry; - } else { - Data = 0; /* fail */ - } - } else { - Data = 0; /* fail */ - } - - return ui5r_FromSByte(Data); -} - -LOCALFUNC MayNotInline ui5r get_byte(CPTR addr) -{ - ui3p m = (addr & regs.MATCrdB.usemask) + regs.MATCrdB.usebase; - - if ((addr & regs.MATCrdB.cmpmask) == regs.MATCrdB.cmpvalu) { - return ui5r_FromSByte(*m); - } else { - return get_byte_ext(addr); - } -} - -LOCALPROC put_byte_ext(CPTR addr, ui5r b) -{ - ATTep p; - ui3p m; - ui5r AccFlags; - -Label_Retry: - p = FindATTel(addr); - AccFlags = p->Access; - - if (0 != (AccFlags & kATTA_writereadymask)) { - SetUpMATC(®s.MATCwrB, p); - m = p->usebase + (addr & p->usemask); - *m = b; - } else if (0 != (AccFlags & kATTA_mmdvmask)) { - (void) MMDV_Access(p, b & 0x00FF, trueblnr, trueblnr, addr); - } else if (0 != (AccFlags & kATTA_ntfymask)) { - if (MemAccessNtfy(p)) { - goto Label_Retry; - } else { - /* fail */ - } - } else { - /* fail */ - } -} - -LOCALPROC MayNotInline put_byte(CPTR addr, ui5r b) -{ - ui3p m = (addr & regs.MATCwrB.usemask) + regs.MATCwrB.usebase; - if ((addr & regs.MATCwrB.cmpmask) == regs.MATCwrB.cmpvalu) { - *m = b; - } else { - put_byte_ext(addr, b); - } -} - -LOCALFUNC ui5r get_word_ext(CPTR addr) -{ - ui5r Data; - - if (0 != (addr & 0x01)) { - ui5r hi = get_byte(addr); - ui5r lo = get_byte(addr + 1); - Data = ((hi << 8) & 0x0000FF00) - | (lo & 0x000000FF); - } else { - ATTep p; - ui3p m; - ui5r AccFlags; - -Label_Retry: - p = FindATTel(addr); - AccFlags = p->Access; - - if (0 != (AccFlags & kATTA_readreadymask)) { - SetUpMATC(®s.MATCrdW, p); - regs.MATCrdW.cmpmask |= 0x01; - m = p->usebase + (addr & p->usemask); - Data = do_get_mem_word(m); - } else if (0 != (AccFlags & kATTA_mmdvmask)) { - Data = MMDV_Access(p, 0, falseblnr, falseblnr, addr); - } else if (0 != (AccFlags & kATTA_ntfymask)) { - if (MemAccessNtfy(p)) { - goto Label_Retry; - } else { - Data = 0; /* fail */ - } - } else { - Data = 0; /* fail */ - } - } - - return ui5r_FromSWord(Data); -} - -LOCALFUNC MayNotInline ui5r get_word(CPTR addr) -{ - ui3p m = (addr & regs.MATCrdW.usemask) + regs.MATCrdW.usebase; - if ((addr & regs.MATCrdW.cmpmask) == regs.MATCrdW.cmpvalu) { - return ui5r_FromSWord(do_get_mem_word(m)); - } else { - return get_word_ext(addr); - } -} - -LOCALPROC put_word_ext(CPTR addr, ui5r w) -{ - if (0 != (addr & 0x01)) { - put_byte(addr, w >> 8); - put_byte(addr + 1, w); - } else { - ATTep p; - ui3p m; - ui5r AccFlags; - -Label_Retry: - p = FindATTel(addr); - AccFlags = p->Access; - - if (0 != (AccFlags & kATTA_writereadymask)) { - SetUpMATC(®s.MATCwrW, p); - regs.MATCwrW.cmpmask |= 0x01; - m = p->usebase + (addr & p->usemask); - do_put_mem_word(m, w); - } else if (0 != (AccFlags & kATTA_mmdvmask)) { - (void) MMDV_Access(p, w & 0x0000FFFF, - trueblnr, falseblnr, addr); - } else if (0 != (AccFlags & kATTA_ntfymask)) { - if (MemAccessNtfy(p)) { - goto Label_Retry; - } else { - /* fail */ - } - } else { - /* fail */ - } - } -} - -LOCALPROC MayNotInline put_word(CPTR addr, ui5r w) -{ - ui3p m = (addr & regs.MATCwrW.usemask) + regs.MATCwrW.usebase; - if ((addr & regs.MATCwrW.cmpmask) == regs.MATCwrW.cmpvalu) { - do_put_mem_word(m, w); - } else { - put_word_ext(addr, w); - } -} - -LOCALFUNC ui5r get_long_ext(CPTR addr) -{ - ui5r hi = get_word(addr); - ui5r lo = get_word(addr + 2); - ui5r Data = ((hi << 16) & 0xFFFF0000) - | (lo & 0x0000FFFF); - - return ui5r_FromSLong(Data); -} - -LOCALFUNC MayNotInline ui5r get_long(CPTR addr) -{ - CPTR addr2 = addr + 2; - ui3p m = (addr & regs.MATCrdW.usemask) + regs.MATCrdW.usebase; - ui3p m2 = (addr2 & regs.MATCrdW.usemask) + regs.MATCrdW.usebase; - if (((addr & regs.MATCrdW.cmpmask) == regs.MATCrdW.cmpvalu) - && ((addr2 & regs.MATCrdW.cmpmask) == regs.MATCrdW.cmpvalu)) - { - ui5r hi = do_get_mem_word(m); - ui5r lo = do_get_mem_word(m2); - ui5r Data = ((hi << 16) & 0xFFFF0000) - | (lo & 0x0000FFFF); - - return ui5r_FromSLong(Data); - } else { - return get_long_ext(addr); - } -} - -LOCALPROC put_long_ext(CPTR addr, ui5r l) -{ - put_word(addr, l >> 16); - put_word(addr + 2, l); -} - -LOCALPROC MayNotInline put_long(CPTR addr, ui5r l) -{ - CPTR addr2 = addr + 2; - ui3p m = (addr & regs.MATCwrW.usemask) + regs.MATCwrW.usebase; - ui3p m2 = (addr2 & regs.MATCwrW.usemask) + regs.MATCwrW.usebase; - if (((addr & regs.MATCwrW.cmpmask) == regs.MATCwrW.cmpvalu) - && ((addr2 & regs.MATCwrW.cmpmask) == regs.MATCwrW.cmpvalu)) - { - do_put_mem_word(m, l >> 16); - do_put_mem_word(m2, l); - } else { - put_long_ext(addr, l); - } -} - - -#if ! USE_POINTER -LOCALFUNC ui4r get_pc_word_ext(void) -{ - ui4r Data; - CPTR addr = regs.pc; - - if (0 != (addr & 0x01)) { - Data = 0; /* fail */ - /* should be an error, if had way to return it */ -#if 0 - ui4r hi = get_byte(addr); - ui4r lo = get_byte(addr + 1); - Data = ((hi << 8) & 0x0000FF00) - | (lo & 0x000000FF); -#endif - } else { - ATTep p; - ui3p m; - ui5r AccFlags; - -Label_Retry: - p = FindATTel(addr); - AccFlags = p->Access; - - if (0 != (AccFlags & kATTA_readreadymask)) { - SetUpMATC(®s.MATCex, p); - regs.MATCex.cmpmask |= 0x01; - m = p->usebase + (addr & p->usemask); - Data = do_get_mem_word(m); - } else - /* - no, don't run from device - if (0 != (AccFlags & kATTA_mmdvmask)) { - Data = MMDV_Access(p, 0, falseblnr, falseblnr, addr); - } else - */ - if (0 != (AccFlags & kATTA_ntfymask)) { - if (MemAccessNtfy(p)) { - goto Label_Retry; - } else { - Data = 0; /* fail */ - } - } else { - Data = 0; /* fail */ - } - } - - return Data; -} -#endif - -LOCALFUNC MayInline ui4r nextiword(void) -/* NOT sign extended */ -{ -#if USE_POINTER - ui4r r = do_get_mem_word(regs.pc_p); - regs.pc_p += 2; - return r; -#else - ui3p m; - ui4r Data; - CPTR addr = regs.pc; - - m = (addr & regs.MATCex.usemask) + regs.MATCex.usebase; - if ((addr & regs.MATCex.cmpmask) == regs.MATCex.cmpvalu) { - Data = do_get_mem_word(m); - } else { - Data = get_pc_word_ext(); - } - regs.pc = addr + 2; - return Data; -#endif -} - -LOCALFUNC MayInline ui3r nextibyte(void) -{ -#if USE_POINTER - ui3r r = do_get_mem_byte(regs.pc_p + 1); - regs.pc_p += 2; - return r; -#else - return (ui3b) nextiword(); -#endif -} - -LOCALFUNC MayInline ui5r nextilong(void) -{ -#if USE_POINTER - ui5r r = do_get_mem_long(regs.pc_p); - regs.pc_p += 4; -#else - ui5r hi = nextiword(); - ui5r lo = nextiword(); - ui5r r = ((hi << 16) & 0xFFFF0000) - | (lo & 0x0000FFFF); -#endif - return r; -} - -LOCALFUNC MayInline void BackupPC(void) -{ -#if USE_POINTER - regs.pc_p -= 2; -#else - regs.pc -= 2; -#endif -} - -LOCALFUNC MayInline void SkipiWord(void) -{ -#if USE_POINTER - regs.pc_p += 2; -#else - regs.pc += 2; -#endif -} - -#if Use68020 -LOCALFUNC MayInline void SkipiLong(void) -{ -#if USE_POINTER - regs.pc_p += 4; -#else - regs.pc += 4; -#endif -} -#endif - -#ifndef WantDumpAJump -#define WantDumpAJump 0 -#endif - -#if WantDumpAJump -LOCALPROC DumpAJump(CPTR toaddr) -{ -#if USE_POINTER - CPTR fromaddr = regs.pc + (regs.pc_p - regs.pc_oldp); - if ((toaddr > fromaddr) || (toaddr < regs.pc)) -#else - CPTR fromaddr = regs.pc; -#endif - { - dbglog_writeHex(fromaddr); - dbglog_writeCStr(","); - dbglog_writeHex(toaddr); - dbglog_writeReturn(); - } -} -#endif - -#if USE_POINTER -LOCALFUNC ui3p get_pc_real_address(CPTR addr) -{ - ui3p v; - ATTep p; - -Label_Retry: - p = FindATTel(addr); - if (0 == (p->Access & kATTA_readreadymask)) - { - if (0 != (p->Access & kATTA_ntfymask)) { - if (MemAccessNtfy(p)) { - goto Label_Retry; - } - } - /* in trouble if get here */ - /* ReportAbnormal("get_pc_real_address fails"); */ - v = regs.fakeword; - regs.MATCex.cmpmask = 0; - regs.MATCex.cmpvalu = 0xFFFFFFFF; - } else { - SetUpMATC(®s.MATCex, p); - v = (addr & p->usemask) + p->usebase; - } - - return v; -} -#endif - -LOCALFUNC MayInline void m68k_setpc(CPTR newpc) -{ -#if WantDumpAJump - DumpAJump(newpc); -#endif - -#if 0 - if (newpc == 0xBD50 /* 401AB4 */) { - /* Debugger(); */ - /* Exception(5); */ /* try and get macsbug */ - } -#endif - -#if USE_POINTER - { - ui3p m; - - m = (newpc & regs.MATCex.usemask) + regs.MATCex.usebase; - if ((newpc & regs.MATCex.cmpmask) != regs.MATCex.cmpvalu) - { - m = get_pc_real_address(newpc); - } - - regs.pc_p = regs.pc_oldp = m; - } -#endif - - regs.pc = newpc; -} - -LOCALFUNC MayInline CPTR m68k_getpc(void) -{ -#if USE_POINTER - return regs.pc + (regs.pc_p - regs.pc_oldp); -#else - return regs.pc; -#endif -} - -LOCALFUNC ui4b m68k_getSR(void) -{ - return (regs.t1 << 15) -#if Use68020 - | (regs.t0 << 14) -#endif - | (regs.s << 13) -#if Use68020 - | (regs.m << 12) -#endif - | (regs.intmask << 8) - | m68k_getCR(); -} - -LOCALPROC NeedToGetOut(void) -{ - if (regs.MaxCyclesToGo <= 0) { - /* - already have gotten out, and exception processing has - caused another exception, such as because a bad - stack pointer pointing to a memory mapped device. - */ - } else { - regs.MoreCyclesToGo += regs.MaxCyclesToGo; - /* not counting the current instruction */ - regs.MaxCyclesToGo = 0; - } -} - -LOCALPROC SetExternalInterruptPending(void) -{ - regs.ExternalInterruptPending = trueblnr; - NeedToGetOut(); -} - -#define m68k_dreg(num) (regs.regs[(num)]) -#define m68k_areg(num) (regs.regs[(num) + 8]) - -LOCALPROC m68k_setSR(ui4r newsr) -{ - CPTR *pnewstk; - CPTR *poldstk = regs.s ? ( -#if Use68020 - regs.m ? ®s.msp : -#endif - ®s.isp) : ®s.usp; - ui5r oldintmask = regs.intmask; - - m68k_setCR(newsr); - regs.t1 = (newsr >> 15) & 1; -#if Use68020 - regs.t0 = (newsr >> 14) & 1; - if (regs.t0) { - ReportAbnormal("t0 flag set in m68k_setSR"); - } -#endif - regs.s = (newsr >> 13) & 1; -#if Use68020 - regs.m = (newsr >> 12) & 1; - if (regs.m) { - ReportAbnormal("m flag set in m68k_setSR"); - } -#endif - regs.intmask = (newsr >> 8) & 7; - - pnewstk = regs.s ? ( -#if Use68020 - regs.m ? ®s.msp : -#endif - ®s.isp) : ®s.usp; - - if (poldstk != pnewstk) { - *poldstk = m68k_areg(7); - m68k_areg(7) = *pnewstk; - } - - if (regs.intmask != oldintmask) { - SetExternalInterruptPending(); - } - - if (regs.t1) { - NeedToGetOut(); - } else { - /* regs.TracePending = falseblnr; */ - } -} - -#ifndef FastRelativeJump -#define FastRelativeJump (1 && USE_POINTER) -#endif - -LOCALPROC ExceptionTo(CPTR newpc -#if Use68020 - , int nr -#endif - ) -{ - ui4b saveSR = m68k_getSR(); - - if (! regs.s) { - regs.usp = m68k_areg(7); - m68k_areg(7) = -#if Use68020 - regs.m ? regs.msp : -#endif - regs.isp; - regs.s = 1; - } -#if Use68020 - switch (nr) { - case 5: /* Zero Divide */ - case 6: /* CHK, CHK2 */ - case 7: /* cpTRAPcc, TRAPCcc, TRAPv */ - case 9: /* Trace */ - m68k_areg(7) -= 4; - put_long(m68k_areg(7), m68k_getpc()); - m68k_areg(7) -= 2; - put_word(m68k_areg(7), 0x2000 + nr * 4); - break; - default: - m68k_areg(7) -= 2; - put_word(m68k_areg(7), nr * 4); - break; - } - /* if regs.m should make throw away stack frame */ -#endif - m68k_areg(7) -= 4; - put_long(m68k_areg(7), m68k_getpc()); - m68k_areg(7) -= 2; - put_word(m68k_areg(7), saveSR); - m68k_setpc(newpc); - regs.t1 = 0; -#if Use68020 - regs.t0 = 0; - regs.m = 0; -#endif - regs.TracePending = falseblnr; -} - -LOCALPROC Exception(int nr) -{ - ExceptionTo(get_long(4 * nr -#if Use68020 - + regs.vbr -#endif - ) -#if Use68020 - , nr -#endif - ); -} - -LOCALFUNC MayNotInline ui5b get_disp_ea(ui5b base) -{ - ui4b dp = nextiword(); - int regno = (dp >> 12) & 0x0F; - si5b regd = regs.regs[regno]; - if ((dp & 0x0800) == 0) { - regd = (si5b)(si4b)regd; - } -#if Use68020 - regd <<= (dp >> 9) & 3; -#if ExtraAbnormalReports - if (((dp >> 9) & 3) != 0) { - /* ReportAbnormal("Have scale in Extension Word"); */ - /* apparently can happen in Sys 7.5.5 boot on 68000 */ - } -#endif - if (dp & 0x0100) { - if ((dp & 0x80) != 0) { - base = 0; - /* ReportAbnormal("Extension Word: suppress base"); */ - /* used by Sys 7.5.5 boot */ - } - if ((dp & 0x40) != 0) { - regd = 0; - /* ReportAbnormal("Extension Word: suppress regd"); */ - /* used by Mac II boot */ - } - - switch ((dp >> 4) & 0x03) { - case 0: - /* reserved */ - ReportAbnormal("Extension Word: dp reserved"); - break; - case 1: - /* no displacement */ - /* ReportAbnormal("Extension Word: no displacement"); */ - /* used by Sys 7.5.5 boot */ - break; - case 2: - base += (si5b)(si4b)nextiword(); - /* - ReportAbnormal("Extension Word: word displacement"); - */ - /* used by Sys 7.5.5 boot */ - break; - case 3: - base += nextilong(); - /* - ReportAbnormal("Extension Word: long displacement"); - */ - /* used by Mac II boot from system 6.0.8? */ - break; - } - - if ((dp & 0x03) == 0) { - base += regd; - if ((dp & 0x04) != 0) { - ReportAbnormal("Extension Word: reserved dp form"); - } - /* ReportAbnormal("Extension Word: noindex"); */ - /* used by Sys 7.5.5 boot */ - } else { - if ((dp & 0x04) != 0) { - base = get_long(base); - base += regd; - /* ReportAbnormal("Extension Word: postindex"); */ - /* used by Sys 7.5.5 boot */ - } else { - base += regd; - base = get_long(base); - /* ReportAbnormal("Extension Word: preindex"); */ - /* used by Sys 7.5.5 boot */ - } - switch (dp & 0x03) { - case 1: - /* null outer displacement */ - /* - ReportAbnormal( - "Extension Word: null outer displacement"); - */ - /* used by Sys 7.5.5 boot */ - break; - case 2: - base += (si5b)(si4b)nextiword(); - /* - ReportAbnormal( - "Extension Word: word outer displacement"); - */ - /* used by Mac II boot from system 6.0.8? */ - break; - case 3: - base += nextilong(); - /* - ReportAbnormal( - "Extension Word: long outer displacement"); - */ - /* used by Mac II boot from system 6.0.8? */ - break; - } - } - - return base; - } else -#endif - { - return base + (si3b)(dp) + regd; - } -} - - -LOCALFUNC MayNotInline ArgAddrT DecodeSrcDst(ui5r f) -{ - ui5r *p; - ArgAddrT v; - - switch (GetDcoFldAMd(f)) { - case kAMdReg : - v.rga = ®s.regs[GetDcoFldArgDat(f)]; - break; - case kAMdIndirect : - p = ®s.regs[GetDcoFldArgDat(f)]; - v.mem = *p; - break; - case kAMdAPosIncB : - p = ®s.regs[GetDcoFldArgDat(f)]; - v.mem = *p; - *p += 1; - break; - case kAMdAPosIncW : - p = ®s.regs[GetDcoFldArgDat(f)]; - v.mem = *p; - *p += 2; - break; - case kAMdAPosIncL : - p = ®s.regs[GetDcoFldArgDat(f)]; - v.mem = *p; - *p += 4; - break; - case kAMdAPreDecB : - p = ®s.regs[GetDcoFldArgDat(f)]; - *p -= 1; - v.mem = *p; - break; - case kAMdAPreDecW : - p = ®s.regs[GetDcoFldArgDat(f)]; - *p -= 2; - v.mem = *p; - break; - case kAMdAPreDecL : - p = ®s.regs[GetDcoFldArgDat(f)]; - *p -= 4; - v.mem = *p; - break; - case kAMdADisp : - p = ®s.regs[GetDcoFldArgDat(f)]; - v.mem = *p + ui5r_FromSWord(nextiword()); - break; - case kAMdAIndex : - p = ®s.regs[GetDcoFldArgDat(f)]; - v.mem = get_disp_ea(*p); - break; - case kAMdAbsW : - v.mem = ui5r_FromSWord(nextiword()); - break; - case kAMdAbsL : - v.mem = nextilong(); - break; - case kAMdPCDisp : - v.mem = m68k_getpc(); - v.mem += ui5r_FromSWord(nextiword()); - break; - case kAMdPCIndex : - v.mem = get_disp_ea(m68k_getpc()); - break; - case kAMdImmedB : - v.mem = ui5r_FromSByte(nextibyte()); - break; - case kAMdImmedW : - v.mem = ui5r_FromSWord(nextiword()); - break; - case kAMdImmedL : - v.mem = ui5r_FromSLong(nextilong()); - break; - case kAMdDat4 : - default: /* make compiler happy, should not happen */ - v.mem = GetDcoFldArgDat(f); - break; - } - - return v; -} - -LOCALFUNC MayNotInline ui5r GetSrcDstValue(ui5r f, ArgAddrT addr) -{ - ui5r v; - - switch (GetDcoFldArgk(f)) { - case kArgkRegB: - v = ui5r_FromSByte(*addr.rga); - break; - case kArgkRegW: - v = ui5r_FromSWord(*addr.rga); - break; - case kArgkRegL: - v = ui5r_FromSLong(*addr.rga); - break; - case kArgkMemB: - v = get_byte(addr.mem); - break; - case kArgkMemW: - v = get_word(addr.mem); - break; - case kArgkMemL: - v = get_long(addr.mem); - break; - case kArgkCnst: - default: /* for compiler. shouldn't be any other cases */ - v = addr.mem; - break; - } - - return v; -} - -LOCALPROC MayNotInline SetSrcDstValue(ui5r f, ArgAddrT addr, ui5r v) -{ - switch (GetDcoFldArgk(f)) { - case kArgkRegB: - *addr.rga = (*addr.rga & ~ 0xff) | ((v) & 0xff); - break; - case kArgkRegW: - *addr.rga = (*addr.rga & ~ 0xffff) | ((v) & 0xffff); - break; - case kArgkRegL: - *addr.rga = v; - break; - case kArgkMemB: - put_byte(addr.mem, v); - break; - case kArgkMemW: - put_word(addr.mem, v); - break; - case kArgkMemL: - put_long(addr.mem, v); - break; - default: /* for compiler. shouldn't be any other cases */ - break; - } -} - -LOCALFUNC MayInline ArgAddrT DecodeSrc(void) -{ - return DecodeSrcDst(regs.CurDecOp.B); -} - -LOCALFUNC MayInline ui5r GetSrcValue(ArgAddrT addr) -{ - return GetSrcDstValue(regs.CurDecOp.B, addr); -} - -LOCALFUNC MayInline ArgAddrT DecodeDst(void) -{ - return DecodeSrcDst(regs.CurDecOp.A); -} - -LOCALFUNC MayInline ui5r GetDstValue(ArgAddrT addr) -{ - return GetSrcDstValue(regs.CurDecOp.A, addr); -} - -LOCALPROC MayInline SetDstValue(ArgAddrT addr, ui5r v) -{ - SetSrcDstValue(regs.CurDecOp.A, addr, v); -} - -LOCALFUNC MayNotInline ui5r DecodeSrcDstGet(void) -{ - ArgAddrT SrcAddr = DecodeSrc(); - ui5r srcvalue = GetSrcValue(SrcAddr); - ArgAddrT DstAddr = DecodeDst(); - ui5r dstvalue = GetDstValue(DstAddr); - - regs.SrcVal = srcvalue; - regs.ArgAddr = DstAddr; - - return dstvalue; -} - -LOCALFUNC MayNotInline ui5r DecodeDstGet(void) -{ - ArgAddrT DstAddr = DecodeDst(); - ui5r dstvalue = GetDstValue(DstAddr); - - regs.ArgAddr = DstAddr; - - return dstvalue; -} - -LOCALPROC MayNotInline SetDstArgValue(ui5r v) -{ - SetDstValue(regs.ArgAddr, v); -} - -LOCALPROCUSEDONCE DoCodeTst(void) -{ - /* Tst 01001010ssmmmrrr */ - - ArgAddrT DstAddr = DecodeDst(); - ui5r srcvalue = GetDstValue(DstAddr); - - VFLG = CFLG = 0; - ZFLG = (srcvalue == 0); - NFLG = ui5r_MSBisSet(srcvalue); -} - -LOCALPROCUSEDONCE DoCodeCmpB(void) -{ - ui5r dstvalue = DecodeSrcDstGet(); - ALU_CmpB(regs.SrcVal, dstvalue); -} - -LOCALPROCUSEDONCE DoCodeCmpW(void) -{ - ui5r dstvalue = DecodeSrcDstGet(); - ALU_CmpW(regs.SrcVal, dstvalue); -} - -LOCALPROCUSEDONCE DoCodeCmpL(void) -{ - ui5r dstvalue = DecodeSrcDstGet(); - ALU_CmpL(regs.SrcVal, dstvalue); -} - -LOCALPROCUSEDONCE DoCodeBraB(void) -{ - ui5b src = ((ui5b)regs.opcode) & 255; -#if FastRelativeJump - ui3p s = regs.pc_p; -#else - ui5r s = m68k_getpc(); -#endif - - s += (si3b)(ui3b)src; - -#if FastRelativeJump - regs.pc_p = s; -#else - m68k_setpc(s); -#endif -} - -LOCALPROCUSEDONCE DoCodeBraW(void) -{ -#if FastRelativeJump - ui3p s = regs.pc_p; -#else - ui5r s = m68k_getpc(); -#endif - - s += (si4b)(ui4b)nextiword(); - -#if FastRelativeJump - regs.pc_p = s; -#else - m68k_setpc(s); -#endif -} - -#if Use68020 -LOCALPROCUSEDONCE DoCodeBraL(void) -{ -#if FastRelativeJump - ui3p s = regs.pc_p; -#else - ui5r s = m68k_getpc(); -#endif - - s += (si5b)(ui5b)nextilong(); - - /* Bra 0110ccccnnnnnnnn */ -#if FastRelativeJump - regs.pc_p = s; -#else - m68k_setpc(s); -#endif -} -#endif - -LOCALPROCUSEDONCE DoCodeBccB(void) -{ - /* Bcc 0110ccccnnnnnnnn */ - if (cctrue()) { -#if WantCloserCyc - regs.MaxCyclesToGo -= (10 * kCycleScale + 2 * RdAvgXtraCyc); -#endif - DoCodeBraB(); - } else { -#if WantCloserCyc - regs.MaxCyclesToGo -= (8 * kCycleScale + RdAvgXtraCyc); -#endif - /* do nothing */ - } -} - -LOCALPROCUSEDONCE DoCodeBccW(void) -{ - /* Bcc 0110ccccnnnnnnnn */ - if (cctrue()) { -#if WantCloserCyc - regs.MaxCyclesToGo -= (10 * kCycleScale + 2 * RdAvgXtraCyc); -#endif - DoCodeBraW(); - } else { -#if WantCloserCyc - regs.MaxCyclesToGo -= (12 * kCycleScale + 2 * RdAvgXtraCyc); -#endif - SkipiWord(); - } -} - -#if Use68020 -LOCALPROCUSEDONCE DoCodeBccL(void) -{ - /* Bcc 0110ccccnnnnnnnn */ - if (cctrue()) { - DoCodeBraL(); - } else { - SkipiLong(); - } -} -#endif - -#define reg (regs.opcode & 7) -#define rg9 ((regs.opcode >> 9) & 7) - -LOCALPROCUSEDONCE DoCodeDBcc(void) -{ - /* DBcc 0101cccc11001ddd */ - - ui5r dstvalue; -#if FastRelativeJump - ui3p srcvalue = regs.pc_p; -#else - ui5r srcvalue = m68k_getpc(); -#endif - - srcvalue += (si4b)(ui4b)nextiword(); - if (cctrue()) { -#if WantCloserCyc - regs.MaxCyclesToGo -= (12 * kCycleScale + 2 * RdAvgXtraCyc); -#endif - } else { - dstvalue = ui5r_FromSWord(m68k_dreg(reg)); - --dstvalue; - m68k_dreg(reg) = (m68k_dreg(reg) & ~ 0xffff) - | ((dstvalue) & 0xffff); - if ((si5b)dstvalue == -1) { -#if WantCloserCyc - regs.MaxCyclesToGo -= (14 * kCycleScale + 3 * RdAvgXtraCyc); -#endif - } else { -#if WantCloserCyc - regs.MaxCyclesToGo -= (10 * kCycleScale + 2 * RdAvgXtraCyc); -#endif -#if FastRelativeJump - regs.pc_p = srcvalue; -#else - m68k_setpc(srcvalue); -#endif - } - } -} - -LOCALPROCUSEDONCE DoCodeSwap(void) -{ - /* Swap 0100100001000rrr */ - ui5r srcreg = reg; - ui5r src = m68k_dreg(srcreg); - ui5r dst = ui5r_FromSLong(((src >> 16) & 0xFFFF) - | ((src & 0xFFFF) << 16)); - VFLG = CFLG = 0; - ZFLG = (dst == 0); - NFLG = ui5r_MSBisSet(dst); - m68k_dreg(srcreg) = dst; -} - -LOCALPROCUSEDONCE DoCodeMove(void) -{ - ArgAddrT SrcAddr = DecodeSrc(); - ui5r src = GetSrcValue(SrcAddr); - ArgAddrT DstAddr = DecodeDst(); - - VFLG = CFLG = 0; - ZFLG = (src == 0); - NFLG = ui5r_MSBisSet(src); - SetDstValue(DstAddr, src); -} - -LOCALPROC DoCodeMoveA(void) /* MOVE */ -{ - ArgAddrT SrcAddr; - ui5r src; - - SrcAddr = DecodeSrc(); - src = GetSrcValue(SrcAddr); - m68k_areg(rg9) = src; -} - -LOCALPROCUSEDONCE DoCodeMoveQ(void) -{ - /* MoveQ 0111ddd0nnnnnnnn */ - ui5r src = ui5r_FromSByte(regs.opcode); - ui5r dstreg = rg9; - VFLG = CFLG = 0; - ZFLG = (src == 0); - NFLG = ui5r_MSBisSet(src); - m68k_dreg(dstreg) = src; -} - -LOCALPROCUSEDONCE DoCodeAddB(void) -{ - ui5r dstvalue = DecodeSrcDstGet(); - SetDstArgValue(ALU_AddB(regs.SrcVal, dstvalue)); -} - -LOCALPROCUSEDONCE DoCodeAddW(void) -{ - ui5r dstvalue = DecodeSrcDstGet(); - SetDstArgValue(ALU_AddW(regs.SrcVal, dstvalue)); -} - -LOCALPROCUSEDONCE DoCodeAddL(void) -{ - ui5r dstvalue = DecodeSrcDstGet(); - SetDstArgValue(ALU_AddL(regs.SrcVal, dstvalue)); -} - -LOCALPROCUSEDONCE DoCodeSubB(void) -{ - ui5r dstvalue = DecodeSrcDstGet(); - SetDstArgValue(ALU_SubB(regs.SrcVal, dstvalue)); -} - -LOCALPROCUSEDONCE DoCodeSubW(void) -{ - ui5r dstvalue = DecodeSrcDstGet(); - SetDstArgValue(ALU_SubW(regs.SrcVal, dstvalue)); -} - -LOCALPROCUSEDONCE DoCodeSubL(void) -{ - ui5r dstvalue = DecodeSrcDstGet(); - SetDstArgValue(ALU_SubL(regs.SrcVal, dstvalue)); -} - -LOCALPROCUSEDONCE DoCodeLea(void) -{ - ArgAddrT DstAddr; - /* Lea 0100aaa111mmmrrr */ - DstAddr = DecodeDst(); - m68k_areg(rg9) = DstAddr.mem; -} - -LOCALPROCUSEDONCE DoCodePEA(void) -{ - ArgAddrT DstAddr; - /* PEA 0100100001mmmrrr */ - DstAddr = DecodeDst(); - m68k_areg(7) -= 4; - put_long(m68k_areg(7), DstAddr.mem); -} - -LOCALPROCUSEDONCE DoCodeA(void) -{ - BackupPC(); - Exception(0xA); -} - -LOCALPROCUSEDONCE DoCodeBsrB(void) -{ - ui5b src = ((ui5b)regs.opcode) & 255; -#if FastRelativeJump - ui3p s = regs.pc_p; -#else - ui5r s = m68k_getpc(); -#endif - - s += (si3b)(ui3b)src; - - m68k_areg(7) -= 4; - put_long(m68k_areg(7), m68k_getpc()); -#if FastRelativeJump - regs.pc_p = s; -#else - m68k_setpc(s); -#endif -} - -LOCALPROCUSEDONCE DoCodeBsrW(void) -{ -#if FastRelativeJump - ui3p s = regs.pc_p; -#else - ui5r s = m68k_getpc(); -#endif - - s += (si4b)(ui4b)nextiword(); - - m68k_areg(7) -= 4; - put_long(m68k_areg(7), m68k_getpc()); -#if FastRelativeJump - regs.pc_p = s; -#else - m68k_setpc(s); -#endif -} - -#if Use68020 -LOCALPROCUSEDONCE DoCodeBsrL(void) -{ -#if FastRelativeJump - ui3p s = regs.pc_p; -#else - ui5r s = m68k_getpc(); -#endif - - s += (si5b)(ui5b)nextilong(); - /* ReportAbnormal("long branch in DoCode6"); */ - /* Used by various Apps */ - - m68k_areg(7) -= 4; - put_long(m68k_areg(7), m68k_getpc()); -#if FastRelativeJump - regs.pc_p = s; -#else - m68k_setpc(s); -#endif -} -#endif - -LOCALPROCUSEDONCE DoCodeJsr(void) -{ - /* Jsr 0100111010mmmrrr */ - ArgAddrT DstAddr = DecodeDst(); - m68k_areg(7) -= 4; - put_long(m68k_areg(7), m68k_getpc()); - m68k_setpc(DstAddr.mem); -} - -LOCALPROCUSEDONCE DoCodeLinkA6(void) -{ - CPTR stackp = m68k_areg(7); - stackp -= 4; - put_long(stackp, m68k_areg(6)); - m68k_areg(6) = stackp; - m68k_areg(7) = stackp + ui5r_FromSWord(nextiword()); -} - -LOCALPROCUSEDONCE DoCodeMOVEMRmML(void) -{ - /* MOVEM reg to mem 01001000111100rrr */ - si4b z; - ui5r regmask = nextiword(); - ui5r p = m68k_areg(reg); - -#if Use68020 - { - int n = 0; - - for (z = 0; z < 16; ++z) { - if ((regmask & (1 << z)) != 0) { - n++; - } - } - m68k_areg(reg) = p - n * 4; - } -#endif - for (z = 16; --z >= 0; ) { - if ((regmask & (1 << (15 - z))) != 0) { -#if WantCloserCyc - regs.MaxCyclesToGo -= (8 * kCycleScale + 2 * WrAvgXtraCyc); -#endif - p -= 4; - put_long(p, regs.regs[z]); - } - } -#if ! Use68020 - m68k_areg(reg) = p; -#endif -} - -LOCALPROCUSEDONCE DoCodeMOVEMApRL(void) -{ - /* MOVEM mem to reg 01001100111011rrr */ - si4b z; - ui5r regmask = nextiword(); - ui5r p = m68k_areg(reg); - - for (z = 0; z < 16; ++z) { - if ((regmask & (1 << z)) != 0) { -#if WantCloserCyc - regs.MaxCyclesToGo -= (8 * kCycleScale + 2 * RdAvgXtraCyc); -#endif - regs.regs[z] = get_long(p); - p += 4; - } - } - m68k_areg(reg) = p; -} - -LOCALPROCUSEDONCE DoCodeUnlkA6(void) -{ - ui5r src = m68k_areg(6); - m68k_areg(6) = get_long(src); - m68k_areg(7) = src + 4; -} - -LOCALPROCUSEDONCE DoCodeRts(void) -{ - /* Rts 0100111001110101 */ - ui5r NewPC = get_long(m68k_areg(7)); - m68k_areg(7) += 4; - m68k_setpc(NewPC); -} - -LOCALPROCUSEDONCE DoCodeJmp(void) -{ - /* JMP 0100111011mmmrrr */ - ArgAddrT DstAddr = DecodeDst(); - m68k_setpc(DstAddr.mem); -} - -LOCALPROCUSEDONCE DoCodeClr(void) -{ - /* Clr 01000010ssmmmrrr */ - - ArgAddrT DstAddr = DecodeDst(); - VFLG = CFLG = 0; - ZFLG = 1; - NFLG = 0; - SetDstValue(DstAddr, 0); -} - -LOCALPROCUSEDONCE DoCodeAddA(void) -{ - /* ADDA 1101dddm11mmmrrr */ - ui5r dstvalue = DecodeSrcDstGet(); - - dstvalue += regs.SrcVal; - SetDstArgValue(dstvalue); -} - -LOCALPROCUSEDONCE DoCodeSubA(void) -{ - ui5r dstvalue = DecodeSrcDstGet(); - - dstvalue -= regs.SrcVal; - SetDstArgValue(dstvalue); -} - -LOCALPROCUSEDONCE DoCodeCmpA(void) -{ - ui5r dstvalue = DecodeSrcDstGet(); - - { - int flgs = ui5r_MSBisSet(regs.SrcVal); - int flgo = ui5r_MSBisSet(dstvalue); - dstvalue -= regs.SrcVal; - dstvalue = ui5r_FromSLong(dstvalue); - ZFLG = (dstvalue == 0); - NFLG = ui5r_MSBisSet(dstvalue); - VFLG = (flgs != flgo) && (NFLG != flgo); - CFLG = (flgs && ! flgo) || (NFLG && ((! flgo) || flgs)); - } -} - -LOCALPROCUSEDONCE DoCodeAddXB(void) -{ - ui5r dstvalue = DecodeSrcDstGet(); - SetDstArgValue(ALU_AddXB(regs.SrcVal, dstvalue)); -} - -LOCALPROCUSEDONCE DoCodeAddXW(void) -{ - ui5r dstvalue = DecodeSrcDstGet(); - SetDstArgValue(ALU_AddXW(regs.SrcVal, dstvalue)); -} - -LOCALPROCUSEDONCE DoCodeAddXL(void) -{ - ui5r dstvalue = DecodeSrcDstGet(); - SetDstArgValue(ALU_AddXL(regs.SrcVal, dstvalue)); -} - -LOCALPROCUSEDONCE DoCodeSubXB(void) -{ - ui5r dstvalue = DecodeSrcDstGet(); - SetDstArgValue(ALU_SubXB(regs.SrcVal, dstvalue)); -} - -LOCALPROCUSEDONCE DoCodeSubXW(void) -{ - ui5r dstvalue = DecodeSrcDstGet(); - SetDstArgValue(ALU_SubXW(regs.SrcVal, dstvalue)); -} - -LOCALPROCUSEDONCE DoCodeSubXL(void) -{ - ui5r dstvalue = DecodeSrcDstGet(); - SetDstArgValue(ALU_SubXL(regs.SrcVal, dstvalue)); -} - -LOCALPROC SetArgKindReg(ui5b thereg) -{ - regs.ArgKind = AKRegister; - regs.ArgAddr.rga = ®s.regs[thereg]; -} - -LOCALPROC MayNotInline DecodeModeRegister(ui5b themode, ui5b thereg) -{ - switch (themode) { - case 0 : - SetArgKindReg(thereg); - break; - case 1 : - SetArgKindReg(thereg + 8); - break; - case 2 : - regs.ArgKind = AKMemory; - regs.ArgAddr.mem = m68k_areg(thereg); - break; - case 3 : - regs.ArgKind = AKMemory; - regs.ArgAddr.mem = m68k_areg(thereg); - if ((thereg == 7) && (regs.opsize == 1)) { - m68k_areg(thereg) += 2; - } else { - m68k_areg(thereg) += regs.opsize; - } - break; - case 4 : - regs.ArgKind = AKMemory; - if ((thereg == 7) && (regs.opsize == 1)) { - m68k_areg(thereg) -= 2; - } else { - m68k_areg(thereg) -= regs.opsize; - } - regs.ArgAddr.mem = m68k_areg(thereg); - break; - case 5 : - regs.ArgKind = AKMemory; - regs.ArgAddr.mem = m68k_areg(thereg) - + ui5r_FromSWord(nextiword()); - break; - case 6 : - regs.ArgKind = AKMemory; - regs.ArgAddr.mem = get_disp_ea(m68k_areg(thereg)); - break; - case 7 : - switch (thereg) { - case 0 : - regs.ArgKind = AKMemory; - regs.ArgAddr.mem = ui5r_FromSWord(nextiword()); - break; - case 1 : - regs.ArgKind = AKMemory; - regs.ArgAddr.mem = nextilong(); - break; - case 2 : - regs.ArgKind = AKMemory; - regs.ArgAddr.mem = m68k_getpc(); - regs.ArgAddr.mem += ui5r_FromSWord(nextiword()); - break; - case 3 : - regs.ArgKind = AKMemory; - regs.ArgAddr.mem = get_disp_ea(m68k_getpc()); - break; - case 4 : - regs.ArgKind = AKConstant; - if (regs.opsize == 2) { - regs.ArgAddr.mem = ui5r_FromSWord(nextiword()); - } else if (regs.opsize < 2) { - regs.ArgAddr.mem = ui5r_FromSByte(nextibyte()); - } else { - regs.ArgAddr.mem = ui5r_FromSLong(nextilong()); - } - break; - } - break; - case 8 : - regs.ArgKind = AKConstant; - regs.ArgAddr.mem = thereg; - break; - } -} - -LOCALFUNC ui5r GetArgValue(void) -{ - ui5r v; - - switch (regs.ArgKind) { - case AKMemory: - if (regs.opsize == 2) { - v = get_word(regs.ArgAddr.mem); - } else if (regs.opsize < 2) { - v = get_byte(regs.ArgAddr.mem); - } else { - v = get_long(regs.ArgAddr.mem); - } - break; - case AKRegister: - v = *regs.ArgAddr.rga; - if (regs.opsize == 2) { - v = ui5r_FromSWord(v); - } else if (regs.opsize < 2) { - v = ui5r_FromSByte(v); - } else { - v = ui5r_FromSLong(v); - } - break; - case AKConstant: - default: /* for compiler. shouldn't be any other cases */ - v = regs.ArgAddr.mem; - break; - } - return v; -} - -LOCALPROC SetArgValue(ui5r v) -{ - if (regs.ArgKind == AKRegister) { - if (regs.opsize == 2) { - *regs.ArgAddr.rga = - (*regs.ArgAddr.rga & ~ 0xffff) | ((v) & 0xffff); - } else if (regs.opsize < 2) { - *regs.ArgAddr.rga = - (*regs.ArgAddr.rga & ~ 0xff) | ((v) & 0xff); - } else { - *regs.ArgAddr.rga = v; - } - } else { - /* must be AKMemory */ - /* should not get here for AKConstant */ - if (regs.opsize == 2) { - put_word(regs.ArgAddr.mem, v); - } else if (regs.opsize < 2) { - put_byte(regs.ArgAddr.mem, v); - } else { - put_long(regs.ArgAddr.mem, v); - } - } -} - -#define b76 ((regs.opcode >> 6) & 3) -#define b8 ((regs.opcode >> 8) & 1) -#define mode ((regs.opcode >> 3) & 7) -#define md6 ((regs.opcode >> 6) & 7) - -LOCALPROC FindOpSizeFromb76(void) -{ - regs.opsize = 1 << b76; -#if 0 - switch (b76) { - case 0 : - regs.opsize = 1; - break; - case 1 : - regs.opsize = 2; - break; - case 2 : - regs.opsize = 4; - break; - } -#endif -} - -LOCALFUNC ui5r octdat(ui5r x) -{ - if (x == 0) { - return 8; - } else { - return x; - } -} - -#define extendopsizedstvalue() \ - if (regs.opsize == 2) {\ - dstvalue = ui5r_FromSWord(dstvalue);\ - } else if (regs.opsize < 2) {\ - dstvalue = ui5r_FromSByte(dstvalue);\ - } else {\ - dstvalue = ui5r_FromSLong(dstvalue);\ - } - -#define unextendopsizedstvalue() \ - if (regs.opsize == 2) {\ - dstvalue = ui5r_FromUWord(dstvalue);\ - } else if (regs.opsize < 2) {\ - dstvalue = ui5r_FromUByte(dstvalue);\ - } else {\ - dstvalue = ui5r_FromULong(dstvalue);\ - } - -#define BinOpASL 0 -#define BinOpASR 1 -#define BinOpLSL 2 -#define BinOpLSR 3 -#define BinOpRXL 4 -#define BinOpRXR 5 -#define BinOpROL 6 -#define BinOpROR 7 - -LOCALPROC DoBinOp1(ui5r srcvalue, ui5r binop) -{ - ui5r dstvalue; - ui5r cnt = srcvalue & 63; - - dstvalue = GetArgValue(); - switch (binop) { - case BinOpASL: - { - ui5r dstvalue0 = dstvalue; - ui5r comparevalue; - if (! cnt) { - VFLG = 0; - CFLG = 0; - } else { - if (cnt > 32) { - dstvalue = 0; - } else { - dstvalue = dstvalue << (cnt - 1); - } - extendopsizedstvalue(); - CFLG = XFLG = ui5r_MSBisSet(dstvalue); - dstvalue = dstvalue << 1; - extendopsizedstvalue(); - } - if (ui5r_MSBisSet(dstvalue)) { - comparevalue = - ((- dstvalue) >> cnt); - } else { - comparevalue = dstvalue >> cnt; - } - VFLG = (comparevalue != dstvalue0); - ZFLG = (dstvalue == 0); - NFLG = ui5r_MSBisSet(dstvalue); - } - break; - case BinOpASR: - { - NFLG = ui5r_MSBisSet(dstvalue); - VFLG = 0; - if (! cnt) { - CFLG = 0; - } else { - if (NFLG) { - dstvalue = (~ dstvalue); - } - unextendopsizedstvalue(); - if (cnt > 32) { - dstvalue = 0; - } else { - dstvalue = dstvalue >> (cnt - 1); - } - CFLG = (dstvalue & 1) != 0; - dstvalue = dstvalue >> 1; - if (NFLG) { - CFLG = ! CFLG; - dstvalue = (~ dstvalue); - } - XFLG = CFLG; - } - ZFLG = (dstvalue == 0); - } - break; - case BinOpLSL: - { - if (! cnt) { - CFLG = 0; - } else { - if (cnt > 32) { - dstvalue = 0; - } else { - dstvalue = dstvalue << (cnt - 1); - } - extendopsizedstvalue(); - CFLG = XFLG = ui5r_MSBisSet(dstvalue); - dstvalue = dstvalue << 1; - extendopsizedstvalue(); - } - ZFLG = (dstvalue == 0); - NFLG = ui5r_MSBisSet(dstvalue); - VFLG = 0; - } - break; - case BinOpLSR: - { - if (! cnt) { - CFLG = 0; - } else { - unextendopsizedstvalue(); - if (cnt > 32) { - dstvalue = 0; - } else { - dstvalue = dstvalue >> (cnt - 1); - } - CFLG = XFLG = (dstvalue & 1) != 0; - dstvalue = dstvalue >> 1; - } - ZFLG = (dstvalue == 0); - NFLG = ui5r_MSBisSet(dstvalue); - /* if cnt != 0, always false */ - VFLG = 0; - } - break; - case BinOpROL: - { - if (! cnt) { - CFLG = 0; - } else { - for (; cnt; --cnt) { - CFLG = ui5r_MSBisSet(dstvalue); - dstvalue = dstvalue << 1; - if (CFLG) { - dstvalue = dstvalue | 1; - } - extendopsizedstvalue(); - } - } - ZFLG = (dstvalue == 0); - NFLG = ui5r_MSBisSet(dstvalue); - VFLG = 0; - } - break; - case BinOpRXL: - { - if (! cnt) { - CFLG = XFLG; - } else { - for (; cnt; --cnt) { - CFLG = ui5r_MSBisSet(dstvalue); - dstvalue = dstvalue << 1; - if (XFLG) { - dstvalue = dstvalue | 1; - } - extendopsizedstvalue(); - XFLG = CFLG; - } - } - ZFLG = (dstvalue == 0); - NFLG = ui5r_MSBisSet(dstvalue); - VFLG = 0; - } - break; - case BinOpROR: - { - ui5r cmask = (ui5r)1 << (regs.opsize * 8 - 1); - if (! cnt) { - CFLG = 0; - } else { - unextendopsizedstvalue(); - for (; cnt; --cnt) { - CFLG = (dstvalue & 1) != 0; - dstvalue = dstvalue >> 1; - if (CFLG) { - dstvalue = dstvalue | cmask; - } - } - extendopsizedstvalue(); - } - ZFLG = (dstvalue == 0); - NFLG = ui5r_MSBisSet(dstvalue); - VFLG = 0; - } - break; - case BinOpRXR: - { - ui5r cmask = (ui5r)1 << (regs.opsize * 8 - 1); - if (! cnt) { - CFLG = XFLG; - } else { - unextendopsizedstvalue(); - for (; cnt; --cnt) { - CFLG = (dstvalue & 1) != 0; - dstvalue = dstvalue >> 1; - if (XFLG) { - dstvalue = dstvalue | cmask; - } - XFLG = CFLG; - } - extendopsizedstvalue(); - } - ZFLG = (dstvalue == 0); - NFLG = ui5r_MSBisSet(dstvalue); - VFLG = 0; - } - break; - default: - /* should not get here */ - break; - } - SetArgValue(dstvalue); -} - -LOCALFUNC ui5r rolops(ui5r x) -{ - ui5r binop; - - binop = (x << 1); - if (! b8) { - binop++; /* 'R' */ - } /* else 'L' */ - return binop; -} - -LOCALPROCUSEDONCE DoCodeRolopNM(void) -{ - regs.opsize = 2; - DecodeModeRegister(mode, reg); - DoBinOp1(1, rolops(rg9)); -} - -LOCALPROCUSEDONCE DoCodeRolopND(void) -{ - /* 1110cccdss0ttddd */ - FindOpSizeFromb76(); - SetArgKindReg(reg); - DoBinOp1(octdat(rg9), rolops(mode & 3)); -} - -LOCALPROCUSEDONCE DoCodeRolopDD(void) -{ - /* 1110rrrdss1ttddd */ - ui5r srcvalue; - FindOpSizeFromb76(); - SetArgKindReg(rg9); - srcvalue = GetArgValue(); - SetArgKindReg(reg); -#if WantCloserCyc - regs.MaxCyclesToGo -= ((srcvalue & 63) * 2 * kCycleScale); -#endif - DoBinOp1(srcvalue, rolops(mode & 3)); -} - -#define BinOpBTst 0 -#define BinOpBChg 1 -#define BinOpBClr 2 -#define BinOpBSet 3 - -LOCALPROC DoBinBitOp1(ui5r srcvalue) -{ - ui5r dstvalue; - ui5r binop; - - dstvalue = GetArgValue(); - - ZFLG = ((dstvalue & ((ui5r)1 << srcvalue)) == 0); - binop = b76; - if (binop != BinOpBTst) { - switch (binop) { - case BinOpBChg: - dstvalue ^= (1 << srcvalue); - break; - case BinOpBClr: - dstvalue &= ~ (1 << srcvalue); - break; - case BinOpBSet: - dstvalue |= (1 << srcvalue); - break; - default: - /* should not get here */ - break; - } - SetArgValue(dstvalue); - } -} - -LOCALPROCUSEDONCE DoCodeBitOpDD(void) -{ - /* dynamic bit, Opcode = 0000ddd1tt000rrr */ - ui5r srcvalue = (ui5r_FromSByte(m68k_dreg(rg9))) & 31; - regs.opsize = 4; - SetArgKindReg(reg); - DoBinBitOp1(srcvalue); -} - -LOCALPROCUSEDONCE DoCodeBitOpDM(void) -{ - /* dynamic bit, Opcode = 0000ddd1ttmmmrrr */ - ui5r srcvalue = (ui5r_FromSByte(m68k_dreg(rg9))) & 7; - regs.opsize = 1; - DecodeModeRegister(mode, reg); - DoBinBitOp1(srcvalue); -} - -LOCALPROCUSEDONCE DoCodeBitOpND(void) -{ - /* static bit 00001010tt000rrr */ - ui5r srcvalue = (ui5r_FromSByte(nextibyte())) & 31; - regs.opsize = 4; - SetArgKindReg(reg); - DoBinBitOp1(srcvalue); -} - -LOCALPROCUSEDONCE DoCodeBitOpNM(void) -{ - /* static bit 00001010ttmmmrrr */ - ui5r srcvalue = (ui5r_FromSByte(nextibyte())) & 7; - regs.opsize = 1; - DecodeModeRegister(mode, reg); - DoBinBitOp1(srcvalue); -} - -LOCALPROCUSEDONCE DoCodeAnd(void) -{ - /* DoBinOpAnd(DecodeI_xxxxxxxxssmmmrrr()); */ - ui5r dstvalue = DecodeSrcDstGet(); - - dstvalue &= regs.SrcVal; - /* - don't need to extend, since excess high - bits all the same as desired high bit. - */ - VFLG = CFLG = 0; - ZFLG = (dstvalue == 0); - NFLG = ui5r_MSBisSet(dstvalue); - - SetDstArgValue(dstvalue); -} - -LOCALPROCUSEDONCE DoCodeOr(void) -{ - /* DoBinOr(DecodeI_xxxxxxxxssmmmrrr()); */ - ui5r dstvalue = DecodeSrcDstGet(); - - dstvalue |= regs.SrcVal; - /* - don't need to extend, since excess high - bits all the same as desired high bit. - */ - VFLG = CFLG = 0; - ZFLG = (dstvalue == 0); - NFLG = ui5r_MSBisSet(dstvalue); - - SetDstArgValue(dstvalue); -} - -LOCALPROCUSEDONCE DoCodeEor(void) -{ - /* Eor 1011ddd1ssmmmrrr */ - /* DoBinOpEor(DecodeDEa_xxxxdddxssmmmrrr()); */ - ui5r dstvalue = DecodeSrcDstGet(); - - dstvalue ^= regs.SrcVal; - /* - don't need to extend, since excess high - bits all the same as desired high bit. - */ - VFLG = CFLG = 0; - ZFLG = (dstvalue == 0); - NFLG = ui5r_MSBisSet(dstvalue); - - SetDstArgValue(dstvalue); -} - -LOCALPROCUSEDONCE DoCodeNot(void) -{ - /* Not 01000110ssmmmrrr */ - ui5r dstvalue = DecodeDstGet(); - - dstvalue = ~ dstvalue; - ZFLG = (dstvalue == 0); - NFLG = ui5r_MSBisSet(dstvalue); - VFLG = CFLG = 0; - - SetDstArgValue(dstvalue); -} - -LOCALPROCUSEDONCE DoCodeScc(void) -{ - /* Scc 0101cccc11mmmrrr */ - regs.opsize = 1; - DecodeModeRegister(mode, reg); - if (cctrue()) { -#if WantCloserCyc - if (mode == 0) { - regs.MaxCyclesToGo -= (2 * kCycleScale); - } -#endif - SetArgValue(0xff); - } else { - SetArgValue(0); - } -} - -LOCALPROCUSEDONCE DoCodeEXTL(void) -{ - /* EXT.L */ - ui5r srcreg = reg; - ui5r src = m68k_dreg(srcreg); - ui5r dst = ui5r_FromSWord(src); - VFLG = CFLG = 0; - ZFLG = (dst == 0); - NFLG = ui5r_MSBisSet(dst); - m68k_dreg(srcreg) = dst; -} - -LOCALPROCUSEDONCE DoCodeEXTW(void) -{ - /* EXT.W */ - ui5r srcreg = reg; - ui5r src = m68k_dreg(srcreg); - ui5r dst = ui5r_FromSByte(src); - VFLG = CFLG = 0; - ZFLG = (dst == 0); - NFLG = ui5r_MSBisSet(dst); - m68k_dreg(srcreg) = (m68k_dreg(srcreg) & ~ 0xffff) | (dst & 0xffff); -} - -LOCALPROCUSEDONCE DoCodeNegB(void) -{ - ui5r dstvalue = DecodeDstGet(); - SetDstArgValue(ALU_NegB(dstvalue)); -} - -LOCALPROCUSEDONCE DoCodeNegW(void) -{ - ui5r dstvalue = DecodeDstGet(); - SetDstArgValue(ALU_NegW(dstvalue)); -} - -LOCALPROCUSEDONCE DoCodeNegL(void) -{ - ui5r dstvalue = DecodeDstGet(); - SetDstArgValue(ALU_NegL(dstvalue)); -} - -LOCALPROCUSEDONCE DoCodeNegXB(void) -{ - ui5r dstvalue = DecodeDstGet(); - SetDstArgValue(ALU_NegXB(dstvalue)); -} - -LOCALPROCUSEDONCE DoCodeNegXW(void) -{ - ui5r dstvalue = DecodeDstGet(); - SetDstArgValue(ALU_NegXW(dstvalue)); -} - -LOCALPROCUSEDONCE DoCodeNegXL(void) -{ - ui5r dstvalue = DecodeDstGet(); - SetDstArgValue(ALU_NegXL(dstvalue)); -} - -LOCALPROCUSEDONCE DoCodeMulU(void) -{ - /* MulU 1100ddd011mmmrrr */ - ui5r srcvalue; - ui5r dstvalue; - - regs.opsize = 2; - DecodeModeRegister(mode, reg); - srcvalue = GetArgValue(); - dstvalue = ui5r_FromSLong(ui5r_FromUWord(regs.regs[rg9]) - * ui5r_FromUWord(srcvalue)); -#if WantCloserCyc - { - ui5r v = srcvalue; - - while (v != 0) { - if ((v & 1) != 0) { - regs.MaxCyclesToGo -= (2 * kCycleScale); - } - v >>= 1; - } - } -#endif - VFLG = CFLG = 0; - ZFLG = (dstvalue == 0); - NFLG = ui5r_MSBisSet(dstvalue); - regs.regs[rg9] = dstvalue; -} - -LOCALPROCUSEDONCE DoCodeMulS(void) -{ - /* MulS 1100ddd111mmmrrr */ - ui5r srcvalue; - ui5r dstvalue; - - regs.opsize = 2; - DecodeModeRegister(mode, reg); - srcvalue = GetArgValue(); - dstvalue = ui5r_FromSLong((si5b)(si4b)regs.regs[rg9] - * (si5b)(si4b)srcvalue); -#if WantCloserCyc - { - ui5r v = (srcvalue << 1); - - while (v != 0) { - if ((v & 1) != ((v >> 1) & 1)) { - regs.MaxCyclesToGo -= (2 * kCycleScale); - } - v >>= 1; - } - } -#endif - VFLG = CFLG = 0; - ZFLG = (dstvalue == 0); - NFLG = ui5r_MSBisSet(dstvalue); - regs.regs[rg9] = dstvalue; -} - -LOCALPROCUSEDONCE DoCodeDivU(void) -{ - /* DivU 1000ddd011mmmrrr */ - ui5r srcvalue; - ui5r dstvalue; - - regs.opsize = 2; - DecodeModeRegister(mode, reg); - srcvalue = GetArgValue(); - dstvalue = regs.regs[rg9]; - if (srcvalue == 0) { -#if WantCloserCyc - regs.MaxCyclesToGo -= - (38 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); -#endif - Exception(5); -#if m68k_logExceptions - dbglog_StartLine(); - dbglog_writeCStr("*** zero devide exception"); - dbglog_writeReturn(); -#endif - } else { - ui5b newv = (ui5b)dstvalue / (ui5b)(ui4b)srcvalue; - ui5b rem = (ui5b)dstvalue % (ui5b)(ui4b)srcvalue; -#if WantCloserCyc - regs.MaxCyclesToGo -= (133 * kCycleScale); -#endif - if (newv > 0xffff) { - VFLG = NFLG = 1; - CFLG = 0; - } else { - VFLG = CFLG = 0; - ZFLG = ((si4b)(newv)) == 0; - NFLG = ((si4b)(newv)) < 0; - newv = (newv & 0xffff) | ((ui5b)rem << 16); - dstvalue = newv; - } - } - regs.regs[rg9] = dstvalue; -} - -LOCALPROCUSEDONCE DoCodeDivS(void) -{ - /* DivS 1000ddd111mmmrrr */ - ui5r srcvalue; - ui5r dstvalue; - - regs.opsize = 2; - DecodeModeRegister(mode, reg); - srcvalue = GetArgValue(); - dstvalue = regs.regs[rg9]; - if (srcvalue == 0) { -#if WantCloserCyc - regs.MaxCyclesToGo -= - (38 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); -#endif - Exception(5); -#if m68k_logExceptions - dbglog_StartLine(); - dbglog_writeCStr("*** zero devide exception"); - dbglog_writeReturn(); -#endif - } else { - si5b newv = (si5b)dstvalue / (si5b)(si4b)srcvalue; - ui4b rem = (si5b)dstvalue % (si5b)(si4b)srcvalue; -#if WantCloserCyc - regs.MaxCyclesToGo -= (150 * kCycleScale); -#endif - if (((newv & 0xffff8000) != 0) && - ((newv & 0xffff8000) != 0xffff8000)) - { - VFLG = NFLG = 1; - CFLG = 0; - } else { - if (((si4b)rem < 0) != ((si5b)dstvalue < 0)) { - rem = - rem; - } - VFLG = CFLG = 0; - ZFLG = ((si4b)(newv)) == 0; - NFLG = ((si4b)(newv)) < 0; - newv = (newv & 0xffff) | ((ui5b)rem << 16); - dstvalue = newv; - } - } - regs.regs[rg9] = dstvalue; -} - -LOCALPROCUSEDONCE DoCodeExgdd(void) -{ - /* Exg 1100ddd101000rrr, opsize = 4 */ - ui5r srcreg = rg9; - ui5r dstreg = reg; - ui5r src = m68k_dreg(srcreg); - ui5r dst = m68k_dreg(dstreg); - m68k_dreg(srcreg) = dst; - m68k_dreg(dstreg) = src; -} - -LOCALPROCUSEDONCE DoCodeExgaa(void) -{ - /* Exg 1100ddd101001rrr, opsize = 4 */ - ui5r srcreg = rg9; - ui5r dstreg = reg; - ui5r src = m68k_areg(srcreg); - ui5r dst = m68k_areg(dstreg); - m68k_areg(srcreg) = dst; - m68k_areg(dstreg) = src; -} - -LOCALPROCUSEDONCE DoCodeExgda(void) -{ - /* Exg 1100ddd110001rrr, opsize = 4 */ - ui5r srcreg = rg9; - ui5r dstreg = reg; - ui5r src = m68k_dreg(srcreg); - ui5r dst = m68k_areg(dstreg); - m68k_dreg(srcreg) = dst; - m68k_areg(dstreg) = src; -} - -LOCALPROCUSEDONCE DoCodeMoveCCREa(void) -{ - /* Move from CCR 0100001011mmmrrr */ -#if ! Use68020 - ReportAbnormal("Move from CCR"); -#endif - regs.opsize = 2; - DecodeModeRegister(mode, reg); - SetArgValue(m68k_getSR() & 0xFF); -} - -LOCALPROCUSEDONCE DoCodeMoveEaCR(void) -{ - /* 0100010011mmmrrr */ - regs.opsize = 2; - DecodeModeRegister(mode, reg); - m68k_setCR(GetArgValue()); -} - -LOCALPROCUSEDONCE DoCodeMoveSREa(void) -{ - /* Move from SR 0100000011mmmrrr */ - regs.opsize = 2; - DecodeModeRegister(mode, reg); - SetArgValue(m68k_getSR()); -} - -LOCALPROCUSEDONCE DoCodeMoveEaSR(void) -{ - /* 0100011011mmmrrr */ - regs.opsize = 2; - DecodeModeRegister(mode, reg); - m68k_setSR(GetArgValue()); -} - -LOCALPROC DoPrivilegeViolation(void) -{ -#if WantCloserCyc - regs.MaxCyclesToGo += GetDcoCycles(®s.CurDecOp); - regs.MaxCyclesToGo -= - (34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); -#endif - BackupPC(); - Exception(8); -} - -LOCALPROC DoBinOpStatusCCR(void) -{ - blnr IsStatus = (b76 != 0); - ui5r srcvalue; - ui5r dstvalue; - - FindOpSizeFromb76(); - if (IsStatus && (! regs.s)) { - DoPrivilegeViolation(); - } else { - srcvalue = ui5r_FromSWord(nextiword()); - dstvalue = m68k_getSR(); - switch (rg9) { - case 0 : - dstvalue |= srcvalue; - break; - case 1 : - dstvalue &= srcvalue; - break; - case 5 : - dstvalue ^= srcvalue; - break; - default: /* should not happen */ - break; - } - if (IsStatus) { - m68k_setSR(dstvalue); - } else { - m68k_setCR(dstvalue); - } - } -} - -LOCALPROCUSEDONCE DoCodeMOVEMApRW(void) -{ - /* MOVEM mem to reg 01001100110011rrr */ - si4b z; - ui5r regmask = nextiword(); - ui5r p = m68k_areg(reg); - - for (z = 0; z < 16; ++z) { - if ((regmask & (1 << z)) != 0) { -#if WantCloserCyc - regs.MaxCyclesToGo -= (4 * kCycleScale + RdAvgXtraCyc); -#endif - regs.regs[z] = get_word(p); - p += 2; - } - } - m68k_areg(reg) = p; -} - -LOCALPROCUSEDONCE DoCodeMOVEMRmMW(void) -{ - /* MOVEM reg to mem 01001000110100rrr */ - si4b z; - ui5r regmask = nextiword(); - ui5r p = m68k_areg(reg); - -#if Use68020 - { - int n = 0; - - for (z = 0; z < 16; ++z) { - if ((regmask & (1 << z)) != 0) { - n++; - } - } - m68k_areg(reg) = p - n * 2; - } -#endif - for (z = 16; --z >= 0; ) { - if ((regmask & (1 << (15 - z))) != 0) { -#if WantCloserCyc - regs.MaxCyclesToGo -= (4 * kCycleScale + WrAvgXtraCyc); -#endif - p -= 2; - put_word(p, regs.regs[z]); - } - } -#if ! Use68020 - m68k_areg(reg) = p; -#endif -} - -LOCALPROC reglist(si4b direction, ui5b m1, ui5b r1) -{ - si4b z; - ui5r p; - ui5r regmask; - - regmask = nextiword(); - regs.opsize = 2 * b76 - 2; - DecodeModeRegister(m1, r1); - p = regs.ArgAddr.mem; - if (direction == 0) { - if (regs.opsize == 2) { - for (z = 0; z < 16; ++z) { - if ((regmask & (1 << z)) != 0) { -#if WantCloserCyc - regs.MaxCyclesToGo -= - (4 * kCycleScale + WrAvgXtraCyc); -#endif - put_word(p, regs.regs[z]); - p += 2; - } - } - } else { - for (z = 0; z < 16; ++z) { - if ((regmask & (1 << z)) != 0) { -#if WantCloserCyc - regs.MaxCyclesToGo -= - (8 * kCycleScale + 2 * WrAvgXtraCyc); -#endif - put_long(p, regs.regs[z]); - p += 4; - } - } - } - } else { - if (regs.opsize == 2) { - for (z = 0; z < 16; ++z) { - if ((regmask & (1 << z)) != 0) { -#if WantCloserCyc - regs.MaxCyclesToGo -= - (4 * kCycleScale + RdAvgXtraCyc); -#endif - regs.regs[z] = get_word(p); - p += 2; - } - } - } else { - for (z = 0; z < 16; ++z) { - if ((regmask & (1 << z)) != 0) { -#if WantCloserCyc - regs.MaxCyclesToGo -= - (8 * kCycleScale + 2 * RdAvgXtraCyc); -#endif - regs.regs[z] = get_long(p); - p += 4; - } - } - } - } -} - -LOCALPROCUSEDONCE DoCodeMOVEMrm(void) -{ - /* MOVEM reg to mem 010010001ssmmmrrr */ - reglist(0, mode, reg); -} - -LOCALPROCUSEDONCE DoCodeMOVEMmr(void) -{ - /* MOVEM mem to reg 0100110011smmmrrr */ - reglist(1, mode, reg); -} - -LOCALPROC DoBinOpAbcd(ui5b m1, ui5b r1, ui5b m2, ui5b r2) -{ - ui5r srcvalue; - ui5r dstvalue; - - regs.opsize = 1; - DecodeModeRegister(m1, r1); - srcvalue = GetArgValue(); - DecodeModeRegister(m2, r2); - dstvalue = GetArgValue(); - { - /* if (regs.opsize != 1) a bug */ - int flgs = ui5r_MSBisSet(srcvalue); - int flgo = ui5r_MSBisSet(dstvalue); - ui4b newv_lo = - (srcvalue & 0xF) + (dstvalue & 0xF) + (XFLG ? 1 : 0); - ui4b newv_hi = (srcvalue & 0xF0) + (dstvalue & 0xF0); - ui4b newv; - - if (newv_lo > 9) { - newv_lo += 6; - } - newv = newv_hi + newv_lo; - CFLG = XFLG = (newv & 0x1F0) > 0x90; - if (CFLG) { - newv += 0x60; - } - dstvalue = ui5r_FromSByte(newv); - if (dstvalue != 0) { - ZFLG = 0; - } - NFLG = ui5r_MSBisSet(dstvalue); - VFLG = (flgs != flgo) && (NFLG != flgo); - /* - but according to my reference book, - VFLG is Undefined for ABCD - */ - } - SetArgValue(dstvalue); -} - -LOCALPROCUSEDONCE DoCodeAbcdr(void) -{ - /* ABCD 1100ddd100000rrr */ - DoBinOpAbcd(0, reg, 0, rg9); -} - -LOCALPROCUSEDONCE DoCodeAbcdm(void) -{ - /* ABCD 1100ddd100001rrr */ - DoBinOpAbcd(4, reg, 4, rg9); -} - -LOCALPROC DoBinOpSbcd(ui5b m1, ui5b r1, ui5b m2, ui5b r2) -{ - ui5r srcvalue; - ui5r dstvalue; - - regs.opsize = 1; - DecodeModeRegister(m1, r1); - srcvalue = GetArgValue(); - DecodeModeRegister(m2, r2); - dstvalue = GetArgValue(); - { - int flgs = ui5r_MSBisSet(srcvalue); - int flgo = ui5r_MSBisSet(dstvalue); - ui4b newv_lo = - (dstvalue & 0xF) - (srcvalue & 0xF) - (XFLG ? 1 : 0); - ui4b newv_hi = (dstvalue & 0xF0) - (srcvalue & 0xF0); - ui4b newv; - - if (newv_lo > 9) { - newv_lo -= 6; - newv_hi -= 0x10; - } - newv = newv_hi + (newv_lo & 0xF); - CFLG = XFLG = (newv_hi & 0x1F0) > 0x90; - if (CFLG) { - newv -= 0x60; - } - dstvalue = ui5r_FromSByte(newv); - if (dstvalue != 0) { - ZFLG = 0; - } - NFLG = ui5r_MSBisSet(dstvalue); - VFLG = (flgs != flgo) && (NFLG != flgo); - /* - but according to my reference book, - VFLG is Undefined for SBCD - */ - } - SetArgValue(dstvalue); -} - -LOCALPROCUSEDONCE DoCodeSbcdr(void) -{ - /* SBCD 1000xxx100000xxx */ - DoBinOpSbcd(0, reg, 0, rg9); -} - -LOCALPROCUSEDONCE DoCodeSbcdm(void) -{ - /* SBCD 1000xxx100001xxx */ - DoBinOpSbcd(4, reg, 4, rg9); -} - -LOCALPROCUSEDONCE DoCodeNbcd(void) -{ - /* Nbcd 0100100000mmmrrr */ - ui5r dstvalue; - - regs.opsize = 1; - DecodeModeRegister(mode, reg); - dstvalue = GetArgValue(); - { - ui4b newv_lo = - (dstvalue & 0xF) - (XFLG ? 1 : 0); - ui4b newv_hi = - (dstvalue & 0xF0); - ui4b newv; - - if (newv_lo > 9) { - newv_lo -= 6; - newv_hi -= 0x10; - } - newv = newv_hi + (newv_lo & 0xF); - CFLG = XFLG = (newv_hi & 0x1F0) > 0x90; - if (CFLG) { - newv -= 0x60; - } - - dstvalue = ui5r_FromSByte(newv); - NFLG = ui5r_MSBisSet(dstvalue); - if (dstvalue != 0) { - ZFLG = 0; - } - } - SetArgValue(dstvalue); -} - -LOCALPROCUSEDONCE DoCodeRte(void) -{ - /* Rte 0100111001110011 */ - if (! regs.s) { - DoPrivilegeViolation(); - } else { - ui5r NewPC; - CPTR stackp = m68k_areg(7); - ui5r NewSR = get_word(stackp); - stackp += 2; - NewPC = get_long(stackp); - stackp += 4; - -#if Use68020 - { - ui4b format = get_word(stackp); - stackp += 2; - - switch ((format >> 12) & 0x0F) { - case 0: - /* ReportAbnormal("rte stack frame format 0"); */ - break; - case 1: - ReportAbnormal("rte stack frame format 1"); - NewPC = m68k_getpc() - 2; - /* rerun instruction */ - break; - case 2: - ReportAbnormal("rte stack frame format 2"); - stackp += 4; - break; - case 9: - ReportAbnormal("rte stack frame format 9"); - stackp += 12; - break; - case 10: - ReportAbnormal("rte stack frame format 10"); - stackp += 24; - break; - case 11: - ReportAbnormal("rte stack frame format 11"); - stackp += 84; - break; - default: - ReportAbnormal("unknown rte stack frame format"); - Exception(14); - return; - break; - } - } -#endif - m68k_areg(7) = stackp; - m68k_setSR(NewSR); - m68k_setpc(NewPC); - } -} - -LOCALPROCUSEDONCE DoCodeNop(void) -{ - /* Nop 0100111001110001 */ -} - -LOCALPROCUSEDONCE DoCodeMoveP(void) -{ - /* MoveP 0000ddd1mm001aaa */ - ui5r TheReg = reg; - ui5r TheRg9 = rg9; - ui5r Displacement = nextiword(); - /* shouldn't this sign extend ? */ - CPTR memp = m68k_areg(TheReg) + Displacement; - -#if 0 - if ((Displacement & 0x00008000) != 0) { - /* **** for testing only **** */ - BackupPC(); - op_illg(); - } -#endif - - switch (b76) { - case 0: - { - ui4b val = ((get_byte(memp) & 0x00FF) << 8) - | (get_byte(memp + 2) & 0x00FF); - - m68k_dreg(TheRg9) = - (m68k_dreg(TheRg9) & ~ 0xffff) | (val & 0xffff); - } - break; - case 1: - { - ui5b val = ((get_byte(memp) & 0x00FF) << 24) - | ((get_byte(memp + 2) & 0x00FF) << 16) - | ((get_byte(memp + 4) & 0x00FF) << 8) - | (get_byte(memp + 6) & 0x00FF); - - m68k_dreg(TheRg9) = val; - } - break; - case 2: - { - si4b src = m68k_dreg(TheRg9); - - put_byte(memp, src >> 8); - put_byte(memp + 2, src); - } - break; - case 3: - { - si5b src = m68k_dreg(TheRg9); - - put_byte(memp, src >> 24); - put_byte(memp + 2, src >> 16); - put_byte(memp + 4, src >> 8); - put_byte(memp + 6, src); - } - break; - } -} - -LOCALPROC op_illg(void) -{ - BackupPC(); - Exception(4); -} - -LOCALPROC DoCheck(void) -{ - ui5r srcvalue; - ui5r dstvalue; - - DecodeModeRegister(mode, reg); - srcvalue = GetArgValue(); - DecodeModeRegister(0, rg9); - dstvalue = GetArgValue(); - if (ui5r_MSBisSet(dstvalue)) { -#if WantCloserCyc - regs.MaxCyclesToGo -= - (30 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); -#endif - NFLG = 1; - Exception(6); - } else if (((si5r)dstvalue) > ((si5r)srcvalue)) { -#if WantCloserCyc - regs.MaxCyclesToGo -= - (30 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); -#endif - NFLG = 0; - Exception(6); - } -} - -LOCALPROCUSEDONCE DoCodeChkW(void) -{ - /* Chk.W 0100ddd110mmmrrr */ - regs.opsize = 2; - DoCheck(); -} - -LOCALPROCUSEDONCE DoCodeTrap(void) -{ - /* Trap 010011100100vvvv */ - Exception((regs.opcode & 15) + 32); -} - -LOCALPROCUSEDONCE DoCodeTrapV(void) -{ - /* TrapV 0100111001110110 */ - if (VFLG) { -#if WantCloserCyc - regs.MaxCyclesToGo += GetDcoCycles(®s.CurDecOp); - regs.MaxCyclesToGo -= - (34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); -#endif - Exception(7); - } -} - -LOCALPROCUSEDONCE DoCodeRtr(void) -{ - /* Rtr 0100111001110111 */ - ui5r NewPC; - CPTR stackp = m68k_areg(7); - ui5r NewCR = get_word(stackp); - stackp += 2; - NewPC = get_long(stackp); - stackp += 4; - m68k_areg(7) = stackp; - m68k_setCR(NewCR); - m68k_setpc(NewPC); -} - -LOCALPROCUSEDONCE DoCodeLink(void) -{ - ui5r srcreg = reg; - CPTR stackp = m68k_areg(7); - stackp -= 4; - m68k_areg(7) = stackp; /* only matters if srcreg == 7 */ - put_long(stackp, m68k_areg(srcreg)); - m68k_areg(srcreg) = stackp; - m68k_areg(7) += ui5r_FromSWord(nextiword()); -} - -LOCALPROCUSEDONCE DoCodeUnlk(void) -{ - ui5r srcreg = reg; - if (srcreg != 7) { - ui5r src = m68k_areg(srcreg); - m68k_areg(srcreg) = get_long(src); - m68k_areg(7) = src + 4; - } else { - /* wouldn't expect this to happen */ - m68k_areg(7) = get_long(m68k_areg(7)) + 4; - } -} - -LOCALPROCUSEDONCE DoCodeMoveRUSP(void) -{ - /* MOVE USP 0100111001100aaa */ - if (! regs.s) { - DoPrivilegeViolation(); - } else { - regs.usp = m68k_areg(reg); - } -} - -LOCALPROCUSEDONCE DoCodeMoveUSPR(void) -{ - /* MOVE USP 0100111001101aaa */ - if (! regs.s) { - DoPrivilegeViolation(); - } else { - m68k_areg(reg) = regs.usp; - } -} - -LOCALPROCUSEDONCE DoCodeTas(void) -{ - /* Tas 0100101011mmmrrr */ - ui5r dstvalue; - - regs.opsize = 1; - DecodeModeRegister(mode, reg); - dstvalue = GetArgValue(); - - { - ZFLG = (dstvalue == 0); - NFLG = ui5r_MSBisSet(dstvalue); - VFLG = CFLG = 0; - dstvalue |= 0x80; - } - SetArgValue(dstvalue); -} - -LOCALPROC DoCodeFdefault(void) -{ - BackupPC(); - Exception(0xB); -} - -#if EmMMU -LOCALPROCUSEDONCE DoCodeMMU(void) -{ - /* - Emulate enough of MMU for System 7.5.5 universal - to boot on Mac Plus 68020. There is one - spurious "PMOVE TC, (A0)". - And implement a few more PMOVE operations seen - when running Disk Copy 6.3.3 and MacsBug. - */ - if (regs.opcode == 0xF010) { - ui4b ew = (int)nextiword(); - if (ew == 0x4200) { - /* PMOVE TC, (A0) */ - /* fprintf(stderr, "0xF010 0x4200\n"); */ - regs.opsize = 4; - DecodeModeRegister(mode, reg); - SetArgValue(0); - return; - } else if ((ew == 0x4E00) || (ew == 0x4A00)) { - /* PMOVE CRP, (A0) and PMOVE SRP, (A0) */ - /* fprintf(stderr, "0xF010 %x\n", ew); */ - regs.opsize = 4; - DecodeModeRegister(mode, reg); - SetArgValue(0x7FFF0001); - regs.ArgAddr.mem += 4; - SetArgValue(0); - return; - } else if (ew == 0x6200) { - /* PMOVE MMUSR, (A0) */ - /* fprintf(stderr, "0xF010 %x\n", ew); */ - regs.opsize = 2; - DecodeModeRegister(mode, reg); - SetArgValue(0); - return; - } - /* fprintf(stderr, "extensions %x\n", ew); */ - BackupPC(); - } - /* fprintf(stderr, "opcode %x\n", (int)regs.opcode); */ - ReportAbnormal("MMU op"); - DoCodeFdefault(); -} -#endif - -#if EmFPU - -#if 0 -#include "FPMATHNT.h" -#else -#include "FPMATHEM.h" -#endif - -#include "FPCPEMDV.h" - -#endif - -LOCALPROCUSEDONCE DoCodeF(void) -{ - /* ReportAbnormal("DoCodeF"); */ -#if EmMMU - if (0 == rg9) { - DoCodeMMU(); - } else -#endif -#if EmFPU - if (1 == rg9) { - DoCodeFPU(); - } else -#endif - { - DoCodeFdefault(); - } -} - -LOCALPROCUSEDONCE DoCodeCallMorRtm(void) -{ - /* CALLM or RTM 0000011011mmmrrr */ - ReportAbnormal("CALLM or RTM instruction"); -} - -LOCALPROC m68k_setstopped(void) -{ - /* not implemented. doesn't seemed to be used on Mac Plus */ - Exception(4); /* fake an illegal instruction */ -} - -LOCALPROCUSEDONCE DoCodeStop(void) -{ - /* Stop 0100111001110010 */ - if (! regs.s) { - DoPrivilegeViolation(); - } else { - m68k_setSR(nextiword()); - m68k_setstopped(); - } -} - -LOCALPROCUSEDONCE DoCodeReset(void) -{ - /* Reset 0100111001100000 */ - if (! regs.s) { - DoPrivilegeViolation(); - } else { - customreset(); - } -} - -#if Use68020 -LOCALPROCUSEDONCE DoCodeEXTBL(void) -{ - /* EXTB.L */ - ui5r srcreg = reg; - ui5r src = m68k_dreg(srcreg); - ui5r dst = ui5r_FromSByte(src); - VFLG = CFLG = 0; - ZFLG = (dst == 0); - NFLG = ui5r_MSBisSet(dst); - m68k_dreg(srcreg) = dst; -} -#endif - -#if Use68020 -LOCALPROC DoCHK2orCMP2(void) -{ - /* CHK2 or CMP2 00000ss011mmmrrr */ - ui5r regv; - ui5r lower; - ui5r upper; - ui5r extra = nextiword(); - - /* ReportAbnormal("CHK2 or CMP2 instruction"); */ - switch ((regs.opcode >> 9) & 3) { - case 0: - regs.opsize = 1; - break; - case 1: - regs.opsize = 2; - break; - case 2: - regs.opsize = 4; - break; - default: - ReportAbnormal("illegal opsize in CHK2 or CMP2"); - break; - } - if ((extra & 0x8000) == 0) { - DecodeModeRegister(0, (extra >> 12) & 0x07); - regv = GetArgValue(); - } else { - regv = ui5r_FromSLong(m68k_areg((extra >> 12) & 0x07)); - } - DecodeModeRegister(mode, reg); - /* regs.ArgKind == AKMemory, otherwise illegal and don't get here */ - lower = GetArgValue(); - regs.ArgAddr.mem += regs.opsize; - upper = GetArgValue(); - - ZFLG = (upper == regv) || (lower == regv); - CFLG = (((si5r)lower) <= ((si5r)upper)) - ? (((si5r)regv) < ((si5r)lower) - || ((si5r)regv) > ((si5r)upper)) - : (((si5r)regv) > ((si5r)upper) - || ((si5r)regv) < ((si5r)lower)); - if ((extra & 0x800) && CFLG) { - Exception(6); - } -} -#endif - -#if Use68020 -LOCALPROC DoCAS(void) -{ - /* CAS 00001ss011mmmrrr */ - ui5r srcvalue; - ui5r dstvalue; - - ui4b src = nextiword(); - int ru = (src >> 6) & 7; - int rc = src & 7; - - ReportAbnormal("CAS instruction"); - switch ((regs.opcode >> 9) & 3) { - case 1 : - regs.opsize = 1; - break; - case 2 : - regs.opsize = 2; - break; - case 3 : - regs.opsize = 4; - break; - } - - DecodeModeRegister(0, rc); - srcvalue = GetArgValue(); - DecodeModeRegister(mode, reg); - dstvalue = GetArgValue(); - { - int flgs = ((si5b)srcvalue) < 0; - int flgo = ((si5b)dstvalue) < 0; - ui5r newv = dstvalue - srcvalue; - if (regs.opsize == 1) { - newv = ui5r_FromSByte(newv); - } else if (regs.opsize == 2) { - newv = ui5r_FromSWord(newv); - } else { - newv = ui5r_FromSLong(newv); - } - ZFLG = (((si5b)newv) == 0); - NFLG = (((si5b)newv) < 0); - VFLG = (flgs != flgo) && (NFLG != flgo); - CFLG = (flgs && ! flgo) || (NFLG && ((! flgo) || flgs)); - if (ZFLG) { - SetArgValue(m68k_dreg(ru)); - } else { - DecodeModeRegister(0, rc); - SetArgValue(dstvalue); - } - } -} -#endif - -#if Use68020 -LOCALPROC DoCAS2(void) -{ - /* CAS2 00001ss011111100 */ - ui5b extra = nextilong(); - int dc2 = extra & 7; - int du2 = (extra >> 6) & 7; - int dc1 = (extra >> 16) & 7; - int du1 = (extra >> 22) & 7; - CPTR rn1 = regs.regs[(extra >> 28) & 0x0F]; - CPTR rn2 = regs.regs[(extra >> 12) & 0x0F]; - si5b src = m68k_dreg(dc1); - si5r dst1; - si5r dst2; - - ReportAbnormal("DoCAS2 instruction"); - switch ((regs.opcode >> 9) & 3) { - case 1 : - op_illg(); - return; - break; - case 2 : - regs.opsize = 2; - break; - case 3 : - regs.opsize = 4; - break; - } - if (regs.opsize == 2) { - dst1 = get_word(rn1); - dst2 = get_word(rn2); - src = (si5b)(si4b)src; - } else { - dst1 = get_long(rn1); - dst2 = get_long(rn2); - } - { - int flgs = src < 0; - int flgo = dst1 < 0; - si5b newv = dst1 - src; - if (regs.opsize == 2) { - newv = (ui4b)newv; - } - ZFLG = (newv == 0); - NFLG = (newv < 0); - VFLG = (flgs != flgo) && (NFLG != flgo); - CFLG = (flgs && ! flgo) || (NFLG && ((! flgo) || flgs)); - if (ZFLG) { - src = m68k_dreg(dc2); - if (regs.opsize == 2) { - src = (si5b)(si4b)src; - } - flgs = src < 0; - flgo = dst2 < 0; - newv = dst2 - src; - if (regs.opsize == 2) { - newv = (ui4b)newv; - } - ZFLG = (newv == 0); - NFLG = (newv < 0); - VFLG = (flgs != flgo) && (NFLG != flgo); - CFLG = (flgs && ! flgo) || (NFLG && ((! flgo) || flgs)); - if (ZFLG) { - if (regs.opsize == 2) { - put_word(rn1, m68k_dreg(du1)); - put_word(rn2, m68k_dreg(du2)); - } else { - put_word(rn1, m68k_dreg(du1)); - put_word(rn2, m68k_dreg(du2)); - } - } - } - } - if (! ZFLG) { - if (regs.opsize == 2) { - m68k_dreg(du1) = - (m68k_dreg(du1) & ~ 0xffff) | ((ui5b)dst1 & 0xffff); - m68k_dreg(du2) = - (m68k_dreg(du2) & ~ 0xffff) | ((ui5b)dst2 & 0xffff); - } else { - m68k_dreg(du1) = dst1; - m68k_dreg(du2) = dst2; - } - } -} -#endif - -#if Use68020 -LOCALPROC DoMOVES(void) -{ - /* MoveS 00001110ssmmmrrr */ - ReportAbnormal("MoveS instruction"); - if (! regs.s) { - DoPrivilegeViolation(); - } else { - ui4b extra = nextiword(); - FindOpSizeFromb76(); - DecodeModeRegister(mode, reg); - if (extra & 0x0800) { - ui5b src = regs.regs[(extra >> 12) & 0x0F]; - SetArgValue(src); - } else { - ui5b rr = (extra >> 12) & 7; - si5b srcvalue = GetArgValue(); - if (extra & 0x8000) { - m68k_areg(rr) = srcvalue; - } else { - DecodeModeRegister(0, rr); - SetArgValue(srcvalue); - } - } - } -} -#endif - -#define ui5b_lo(x) ((x) & 0x0000FFFF) -#define ui5b_hi(x) (((x) >> 16) & 0x0000FFFF) - -#if Use68020 -struct ui6r0 { - ui5b hi; - ui5b lo; -}; -typedef struct ui6r0 ui6r0; -#endif - -#if Use68020 -LOCALPROC Ui6r_Negate(ui6r0 *v) -{ - v->hi = ~ v->hi; - v->lo = - v->lo; - if (v->lo == 0) { - v->hi++; - } -} -#endif - -#if Use68020 -LOCALFUNC blnr Ui6r_IsZero(ui6r0 *v) -{ - return (v->hi == 0) && (v->lo == 0); -} -#endif - -#if Use68020 -LOCALFUNC blnr Ui6r_IsNeg(ui6r0 *v) -{ - return ((si5b)v->hi) < 0; -} -#endif - -#if Use68020 -LOCALPROC mul_unsigned(ui5b src1, ui5b src2, ui6r0 *dst) -{ - ui5b src1_lo = ui5b_lo(src1); - ui5b src2_lo = ui5b_lo(src2); - ui5b src1_hi = ui5b_hi(src1); - ui5b src2_hi = ui5b_hi(src2); - - ui5b r0 = src1_lo * src2_lo; - ui5b r1 = src1_hi * src2_lo; - ui5b r2 = src1_lo * src2_hi; - ui5b r3 = src1_hi * src2_hi; - - ui5b ra1 = ui5b_hi(r0) + ui5b_lo(r1) + ui5b_lo(r2); - - dst->lo = (ui5b_lo(ra1) << 16) | ui5b_lo(r0); - dst->hi = ui5b_hi(ra1) + ui5b_hi(r1) + ui5b_hi(r2) + r3; -} -#endif - -#if Use68020 -LOCALFUNC blnr div_unsigned(ui6r0 *src, ui5b div, - ui5b *quot, ui5b *rem) -{ - int i; - ui5b q = 0; - ui5b cbit = 0; - ui5b src_hi = src->hi; - ui5b src_lo = src->lo; - - if (div <= src_hi) { - return trueblnr; - } - for (i = 0 ; i < 32 ; i++) { - cbit = src_hi & 0x80000000ul; - src_hi <<= 1; - if (src_lo & 0x80000000ul) { - src_hi++; - } - src_lo <<= 1; - q = q << 1; - if (cbit || div <= src_hi) { - q |= 1; - src_hi -= div; - } - } - *quot = q; - *rem = src_hi; - return falseblnr; -} -#endif - -#if Use68020 -LOCALPROC DoMulL(void) -{ - ui6r0 dst; - ui5r srcvalue; - ui4b extra = nextiword(); - ui5b r2 = (extra >> 12) & 7; - ui5b dstvalue = m68k_dreg(r2); - - DecodeModeRegister(mode, reg); - srcvalue = GetArgValue(); - - if (extra & 0x800) { - /* MULS.L - signed */ - - si5b src1 = (si5b)srcvalue; - si5b src2 = (si5b)dstvalue; - flagtype s1 = src1 < 0; - flagtype s2 = src2 < 0; - flagtype sr = s1 != s2; - - /* ReportAbnormal("MULS.L"); */ - /* used by Sys 7.5.5 boot extensions */ - if (s1) { - src1 = - src1; - } - if (s2) { - src2 = - src2; - } - mul_unsigned((ui5b)src1, (ui5b)src2, &dst); - if (sr) { - Ui6r_Negate(&dst); - } - VFLG = CFLG = 0; - ZFLG = Ui6r_IsZero(&dst); - NFLG = Ui6r_IsNeg(&dst); - if (extra & 0x400) { - m68k_dreg(extra & 7) = dst.hi; - } else { - if ((dst.lo & 0x80000000) != 0) { - if ((dst.hi & 0xffffffff) != 0xffffffff) { - VFLG = 1; - } - } else { - if (dst.hi != 0) { - VFLG = 1; - } - } - } - } else { - /* MULU.L - unsigned */ - - /* ReportAbnormal("MULU.U"); */ - /* Used by various Apps */ - - mul_unsigned(srcvalue, dstvalue, &dst); - - VFLG = CFLG = 0; - ZFLG = Ui6r_IsZero(&dst); - NFLG = Ui6r_IsNeg(&dst); - if (extra & 0x400) { - m68k_dreg(extra & 7) = dst.hi; - } else { - if (dst.hi != 0) { - VFLG = 1; - } - } - } - m68k_dreg(r2) = dst.lo; -} -#endif - -#if Use68020 -LOCALPROC DoDivL(void) -{ - ui6r0 v2; - ui5b src; - ui5b quot; - ui5b rem; - ui4b extra = nextiword(); - ui5b rDr = extra & 7; - ui5b rDq = (extra >> 12) & 7; - - DecodeModeRegister(mode, reg); - src = (ui5b)(si5b)GetArgValue(); - - if (src == 0) { - Exception(5); -#if m68k_logExceptions - dbglog_StartLine(); - dbglog_writeCStr("*** zero devide exception"); - dbglog_writeReturn(); -#endif - return; - } - if (0 != (extra & 0x0800)) { - /* signed variant */ - flagtype sr; - flagtype s2; - flagtype s1 = ((si5b)src < 0); - - v2.lo = (si5b)m68k_dreg(rDq); - if (extra & 0x0400) { - v2.hi = (si5b)m68k_dreg(rDr); - } else { - v2.hi = ((si5b)v2.lo) < 0 ? -1 : 0; - } - s2 = Ui6r_IsNeg(&v2); - sr = (s1 != s2); - if (s2) { - Ui6r_Negate(&v2); - } - if (s1) { - src = - src; - } - if (div_unsigned(&v2, src, ", &rem) - || (sr ? quot > 0x80000000 : quot > 0x7fffffff)) - { - VFLG = NFLG = 1; - CFLG = 0; - } else { - if (sr) { - quot = - quot; - } - if (((si5b)rem < 0) != s2) { - rem = - rem; - } - VFLG = CFLG = 0; - ZFLG = ((si5b)quot) == 0; - NFLG = ((si5b)quot) < 0; - m68k_dreg(rDr) = rem; - m68k_dreg(rDq) = quot; - } - } else { - /* unsigned */ - - v2.lo = (ui5b)m68k_dreg(rDq); - if (extra & 0x400) { - v2.hi = (ui5b)m68k_dreg(rDr); - } else { - v2.hi = 0; - } - if (div_unsigned(&v2, src, ", &rem)) { - VFLG = NFLG = 1; - CFLG = 0; - } else { - VFLG = CFLG = 0; - ZFLG = ((si5b)quot) == 0; - NFLG = ((si5b)quot) < 0; - m68k_dreg(rDr) = rem; - m68k_dreg(rDq) = quot; - } - } -} -#endif - -#if Use68020 -LOCALPROC DoMoveToControl(void) -{ - if (! regs.s) { - DoPrivilegeViolation(); - } else { - ui4b src = nextiword(); - int regno = (src >> 12) & 0x0F; - ui5b v = regs.regs[regno]; - - switch (src & 0x0FFF) { - case 0x0000: - regs.sfc = v & 7; - /* ReportAbnormal("DoMoveToControl: sfc"); */ - /* happens on entering macsbug */ - break; - case 0x0001: - regs.dfc = v & 7; - /* ReportAbnormal("DoMoveToControl: dfc"); */ - break; - case 0x0002: - regs.cacr = v & 0x3; - /* ReportAbnormal("DoMoveToControl: cacr"); */ - /* used by Sys 7.5.5 boot */ - break; - case 0x0800: - regs.usp = v; - ReportAbnormal("DoMoveToControl: usp"); - break; - case 0x0801: - regs.vbr = v; - /* ReportAbnormal("DoMoveToControl: vbr"); */ - /* happens on entering macsbug */ - break; - case 0x0802: - regs.caar = v &0xfc; - /* ReportAbnormal("DoMoveToControl: caar"); */ - /* happens on entering macsbug */ - break; - case 0x0803: - regs.msp = v; - if (regs.m == 1) { - m68k_areg(7) = regs.msp; - } - /* ReportAbnormal("DoMoveToControl: msp"); */ - /* happens on entering macsbug */ - break; - case 0x0804: - regs.isp = v; - if (regs.m == 0) { - m68k_areg(7) = regs.isp; - } - ReportAbnormal("DoMoveToControl: isp"); - break; - default: - op_illg(); - ReportAbnormal("DoMoveToControl: unknown reg"); - break; - } - } -} -#endif - -#if Use68020 -LOCALPROC DoMoveFromControl(void) -{ - if (! regs.s) { - DoPrivilegeViolation(); - } else { - ui5b v; - ui4b src = nextiword(); - int regno = (src >> 12) & 0x0F; - - switch (src & 0x0FFF) { - case 0x0000: - v = regs.sfc; - /* ReportAbnormal("DoMoveFromControl: sfc"); */ - /* happens on entering macsbug */ - break; - case 0x0001: - v = regs.dfc; - /* ReportAbnormal("DoMoveFromControl: dfc"); */ - /* happens on entering macsbug */ - break; - case 0x0002: - v = regs.cacr; - /* ReportAbnormal("DoMoveFromControl: cacr"); */ - /* used by Sys 7.5.5 boot */ - break; - case 0x0800: - v = regs.usp; - ReportAbnormal("DoMoveFromControl: usp"); - break; - case 0x0801: - v = regs.vbr; - /* ReportAbnormal("DoMoveFromControl: vbr"); */ - /* happens on entering macsbug */ - break; - case 0x0802: - v = regs.caar; - /* ReportAbnormal("DoMoveFromControl: caar"); */ - /* happens on entering macsbug */ - break; - case 0x0803: - v = (regs.m == 1) - ? m68k_areg(7) - : regs.msp; - /* ReportAbnormal("DoMoveFromControl: msp"); */ - /* happens on entering macsbug */ - break; - case 0x0804: - v = (regs.m == 0) - ? m68k_areg(7) - : regs.isp; - ReportAbnormal("DoMoveFromControl: isp"); - break; - default: - v = 0; - ReportAbnormal("DoMoveFromControl: unknown reg"); - op_illg(); - break; - } - regs.regs[regno] = v; - } -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DoCodeMoveC(void) -{ - /* MOVEC 010011100111101m */ - /* ReportAbnormal("MOVEC"); */ - switch (reg) { - case 2: - DoMoveFromControl(); - break; - case 3: - DoMoveToControl(); - break; - default: - op_illg(); - break; - } -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DoCodeChkL(void) -{ - /* Chk.L 0100ddd100mmmrrr */ - ReportAbnormal("CHK.L instruction"); - regs.opsize = 4; - DoCheck(); -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DoCodeBkpt(void) -{ - /* BKPT 0100100001001rrr */ - ReportAbnormal("BKPT instruction"); - op_illg(); -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DoCodeDivL(void) -{ - regs.opsize = 4; - /* DIVU 0100110001mmmrrr 0rrr0s0000000rrr */ - /* DIVS 0100110001mmmrrr 0rrr1s0000000rrr */ - /* ReportAbnormal("DIVS/DIVU long"); */ - DoDivL(); -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DoCodeMulL(void) -{ - regs.opsize = 4; - /* MULU 0100110000mmmrrr 0rrr0s0000000rrr */ - /* MULS 0100110000mmmrrr 0rrr1s0000000rrr */ - DoMulL(); -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DoCodeRtd(void) -{ - /* Rtd 0100111001110100 */ - ui5r NewPC = get_long(m68k_areg(7)); - si5b offs = (si5b)(si4b)nextiword(); - /* ReportAbnormal("RTD"); */ - /* used by Sys 7.5.5 boot */ - m68k_areg(7) += (4 + offs); - m68k_setpc(NewPC); -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DoCodeLinkL(void) -{ - /* Link.L 0100100000001rrr */ - - ui5b srcreg = reg; - CPTR stackp = m68k_areg(7); - - ReportAbnormal("Link.L"); - - stackp -= 4; - m68k_areg(7) = stackp; /* only matters if srcreg == 7 */ - put_long(stackp, m68k_areg(srcreg)); - m68k_areg(srcreg) = stackp; - m68k_areg(7) += (si5b)nextilong(); -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DoCodeTRAPcc(void) -{ - /* TRAPcc 0101cccc11111sss */ - /* ReportAbnormal("TRAPcc"); */ - switch (reg) { - case 2: - ReportAbnormal("TRAPcc word data"); - (void) nextiword(); - break; - case 3: - ReportAbnormal("TRAPcc long data"); - (void) nextilong(); - break; - case 4: - /* no optional data */ - break; - default: - ReportAbnormal("TRAPcc illegal format"); - op_illg(); - break; - } - if (cctrue()) { - ReportAbnormal("TRAPcc trapping"); - Exception(7); - /* pc pushed onto stack wrong */ - } -} -#endif - -#if Use68020 -LOCALPROC DoUNPK(void) -{ - ui5r val; - ui5r m1 = ((regs.opcode >> 3) & 1) << 2; - ui5r srcreg = reg; - ui5r dstreg = rg9; - ui5r offs = ui5r_FromSWord(nextiword()); - - regs.opsize = 1; - DecodeModeRegister(m1, srcreg); - val = GetArgValue(); - - val = (((val & 0xF0) << 4) | (val & 0x0F)) + offs; - - regs.opsize = 2; - DecodeModeRegister(m1, dstreg); - SetArgValue(val); -} -#endif - -#if Use68020 -LOCALPROC DoPACK(void) -{ - ui5r val; - ui5r m1 = ((regs.opcode >> 3) & 1) << 2; - ui5r srcreg = reg; - ui5r dstreg = rg9; - ui5r offs = ui5r_FromSWord(nextiword()); - - regs.opsize = 2; - DecodeModeRegister(m1, srcreg); - val = GetArgValue(); - - val += offs; - val = ((val >> 4) & 0xf0) | (val & 0xf); - - regs.opsize = 1; - DecodeModeRegister(m1, dstreg); - SetArgValue(val); -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DoCodePack(void) -{ - ReportAbnormal("PACK"); - DoPACK(); -} -#endif - -#if Use68020 -LOCALPROCUSEDONCE DoCodeUnpk(void) -{ - ReportAbnormal("UNPK"); - DoUNPK(); -} -#endif - -#if Use68020 -LOCALPROC DoBitField(void) -{ - ui5b tmp; - ui5b newtmp; - si5b dsta; - ui5b bf0; - ui3b bf1; - ui5b dstreg = regs.opcode & 7; - ui4b extra = nextiword(); - si5b offset = ((extra & 0x0800) != 0) - ? m68k_dreg((extra >> 6) & 7) - : ((extra >> 6) & 0x1f); - ui5b width = ((extra & 0x0020) != 0) - ? m68k_dreg(extra & 7) - : extra; - ui3b bfa[5]; - ui5b offwid; - - /* ReportAbnormal("Bit Field operator"); */ - /* width = ((width - 1) & 0x1f) + 1; */ /* 0 -> 32 */ - width &= 0x001F; /* except width == 0 really means 32 */ - if (mode == 0) { - bf0 = m68k_dreg(dstreg); - offset &= 0x1f; - tmp = bf0; - if (0 != offset) { - tmp = (tmp << offset) | (tmp >> (32 - offset)); - } - } else { - DecodeModeRegister(mode, reg); - /* - regs.ArgKind == AKMemory, - otherwise illegal and don't get here - */ - dsta = regs.ArgAddr.mem; - dsta += - (offset >> 3) | (offset & 0x80000000 ? ~ 0x1fffffff : 0); - offset &= 7; - offwid = offset + ((width == 0) ? 32 : width); - - /* if (offwid > 0) */ { - bf1 = get_byte(dsta); - bfa[0] = bf1; - tmp = ((ui5b)bf1) << (24 + offset); - } - if (offwid > 8) { - bf1 = get_byte(dsta + 1); - bfa[1] = bf1; - tmp |= ((ui5b)bf1) << (16 + offset); - } - if (offwid > 16) { - bf1 = get_byte(dsta + 2); - bfa[2] = bf1; - tmp |= ((ui5r)bf1) << (8 + offset); - } - if (offwid > 24) { - bf1 = get_byte(dsta + 3); - bfa[3] = bf1; - tmp |= ((ui5r)bf1) << (offset); - } - if (offwid > 32) { - bf1 = get_byte(dsta + 4); - bfa[4] = bf1; - tmp |= ((ui5r)bf1) >> (8 - offset); - } - } - - NFLG = ((si5b)tmp) < 0; - if (width != 0) { - tmp >>= (32 - width); - } - ZFLG = tmp == 0; - VFLG = 0; - CFLG = 0; - - newtmp = tmp; - - switch ((regs.opcode >> 8) & 7) { - case 0: /* BFTST */ - /* do nothing */ - break; - case 1: /* BFEXTU */ - m68k_dreg((extra >> 12) & 7) = tmp; - break; - case 2: /* BFCHG */ - newtmp = ~ newtmp; - if (width != 0) { - newtmp &= ((1 << width) - 1); - } - break; - case 3: /* BFEXTS */ - if (NFLG) { - m68k_dreg((extra >> 12) & 7) = tmp - | ((width == 0) ? 0 : (-1 << width)); - } else { - m68k_dreg((extra >> 12) & 7) = tmp; - } - break; - case 4: /* BFCLR */ - newtmp = 0; - break; - case 5: /* BFFFO */ - { - ui5b mask = 1 << ((width == 0) ? 31 : (width - 1)); - si5b i = offset; - - while ((0 != mask) && (0 == (tmp & mask))) { - mask >>= 1; - i++; - } - m68k_dreg((extra >> 12) & 7) = i; - } - break; - case 6: /* BFSET */ - newtmp = (width == 0) ? ~ 0 : ((1 << width) - 1); - break; - case 7: /* BFINS */ - newtmp = m68k_dreg((extra >> 12) & 7); - if (width != 0) { - newtmp &= ((1 << width) - 1); - } - break; - } - - if (newtmp != tmp) { - - if (width != 0) { - newtmp <<= (32 - width); - } - - if (mode == 0) { - ui5b mask = ~ 0; - - if (width != 0) { - mask <<= (32 - width); - } - - if (0 != offset) { - newtmp = (newtmp >> offset) | (newtmp << (32 - offset)); - mask = (mask >> offset) | (mask << (32 - offset)); - } - - bf0 = (bf0 & ~ mask) | (newtmp); - m68k_dreg(dstreg) = bf0; - } else { - - /* if (offwid > 0) */ { - ui3b mask = ~ (0xFF >> offset); - - bf1 = newtmp >> (24 + offset); - if (offwid < 8) { - mask |= (0xFF >> offwid); - } - if (mask != 0) { - bf1 |= bfa[0] & mask; - } - put_byte(dsta + 0, bf1); - } - if (offwid > 8) { - bf1 = newtmp >> (16 + offset); - if (offwid < 16) { - bf1 |= (bfa[1] & (0xFF >> (offwid - 8))); - } - put_byte(dsta + 1, bf1); - } - if (offwid > 16) { - bf1 = newtmp >> (8 + offset); - if (offwid < 24) { - bf1 |= (bfa[2] & (0xFF >> (offwid - 16))); - } - put_byte(dsta + 2, bf1); - } - if (offwid > 24) { - bf1 = newtmp >> (offset); - if (offwid < 32) { - bf1 |= (bfa[3] & (0xFF >> (offwid - 24))); - } - put_byte(dsta + 3, bf1); - } - if (offwid > 32) { - bf1 = newtmp << (8 - offset); - bf1 |= (bfa[4] & (0xFF >> (offwid - 32))); - put_byte(dsta + 4, bf1); - } - } - } -} -#endif - -#ifndef WantDumpTable -#define WantDumpTable 0 -#endif - -#if WantDumpTable -LOCALVAR ui5b DumpTable[kNumIKinds]; - -LOCALPROC InitDumpTable(void) -{ - si5b i; - - for (i = 0; i < kNumIKinds; ++i) { - DumpTable[i] = 0; - } -} - -LOCALPROC DumpATable(ui5b *p, ui5b n) -{ - si5b i; - - for (i = 0; i < n; ++i) { - dbglog_writeNum(p[i]); - dbglog_writeReturn(); - } -} - -EXPORTPROC DoDumpTable(void); -GLOBALPROC DoDumpTable(void) -{ - DumpATable(DumpTable, kNumIKinds); -} -#endif - -LOCALPROC m68k_go_MaxCycles(void) -{ - /* - Main loop of emulator. - - Always execute at least one instruction, - even if regs.MaxInstructionsToGo == 0. - Needed for trace flag to work. - */ - - do { - -#if WantDisasm - DisasmOneOrSave(m68k_getpc()); -#endif - - regs.opcode = nextiword(); - - regs.CurDecOp = regs.disp_table[regs.opcode]; -#if WantDumpTable - DumpTable[GetDcoMainClas(®s.CurDecOp)] ++; -#endif - regs.MaxCyclesToGo -= GetDcoCycles(®s.CurDecOp); - - switch (GetDcoMainClas(®s.CurDecOp)) { - case kIKindTst : - DoCodeTst(); - break; - case kIKindCmpB : - DoCodeCmpB(); - break; - case kIKindCmpW : - DoCodeCmpW(); - break; - case kIKindCmpL : - DoCodeCmpL(); - break; - case kIKindBccB : - DoCodeBccB(); - break; - case kIKindBccW : - DoCodeBccW(); - break; -#if Use68020 - case kIKindBccL : - DoCodeBccL(); - break; -#endif - case kIKindBraB : - DoCodeBraB(); - break; - case kIKindBraW : - DoCodeBraW(); - break; -#if Use68020 - case kIKindBraL : - DoCodeBraL(); - break; -#endif - case kIKindDBcc : - DoCodeDBcc(); - break; - case kIKindDBF : - DoCodeDBcc(); - break; - case kIKindSwap : - DoCodeSwap(); - break; - case kIKindMoveL : - DoCodeMove(); - break; - case kIKindMoveW : - DoCodeMove(); - break; - case kIKindMoveB : - DoCodeMove(); - break; - case kIKindMoveAL : - DoCodeMoveA(); - break; - case kIKindMoveAW : - DoCodeMoveA(); - break; - case kIKindMoveQ: - DoCodeMoveQ(); - break; - case kIKindAddB : - DoCodeAddB(); - break; - case kIKindAddW : - DoCodeAddW(); - break; - case kIKindAddL : - DoCodeAddL(); - break; - case kIKindSubB : - DoCodeSubB(); - break; - case kIKindSubW : - DoCodeSubW(); - break; - case kIKindSubL : - DoCodeSubL(); - break; - case kIKindLea : - DoCodeLea(); - break; - case kIKindPEA : - DoCodePEA(); - break; - case kIKindA : - DoCodeA(); - break; - case kIKindBsrB : - DoCodeBsrB(); - break; - case kIKindBsrW : - DoCodeBsrW(); - break; -#if Use68020 - case kIKindBsrL : - DoCodeBsrL(); - break; -#endif - case kIKindJsr : - DoCodeJsr(); - break; - case kIKindLinkA6 : - DoCodeLinkA6(); - break; - case kIKindMOVEMRmML : - DoCodeMOVEMRmML(); - break; - case kIKindMOVEMApRL : - DoCodeMOVEMApRL(); - break; - case kIKindUnlkA6 : - DoCodeUnlkA6(); - break; - case kIKindRts : - DoCodeRts(); - break; - case kIKindJmp : - DoCodeJmp(); - break; - case kIKindClr : - DoCodeClr(); - break; - case kIKindAddA : - DoCodeAddA(); - break; - case kIKindAddQA : - DoCodeAddA(); - /* DoCodeAddQA(); */ - break; - case kIKindSubA : - DoCodeSubA(); - break; - case kIKindSubQA : - DoCodeSubA(); - /* DoCodeSubQA(); */ - break; - case kIKindCmpA : - DoCodeCmpA(); - break; - case kIKindAddXB : - DoCodeAddXB(); - break; - case kIKindAddXW : - DoCodeAddXW(); - break; - case kIKindAddXL : - DoCodeAddXL(); - break; - case kIKindSubXB : - DoCodeSubXB(); - break; - case kIKindSubXW : - DoCodeSubXW(); - break; - case kIKindSubXL : - DoCodeSubXL(); - break; - - case kIKindRolopNM : - DoCodeRolopNM(); - break; - case kIKindRolopND : - DoCodeRolopND(); - break; - case kIKindRolopDD : - DoCodeRolopDD(); - break; - case kIKindBitOpDD : - DoCodeBitOpDD(); - break; - case kIKindBitOpDM : - DoCodeBitOpDM(); - break; - case kIKindBitOpND : - DoCodeBitOpND(); - break; - case kIKindBitOpNM : - DoCodeBitOpNM(); - break; - - case kIKindAndI : - DoCodeAnd(); - /* DoCodeAndI(); */ - break; - case kIKindAndEaD : - DoCodeAnd(); - /* DoCodeAndEaD(); */ - break; - case kIKindAndDEa : - DoCodeAnd(); - /* DoCodeAndDEa(); */ - break; - case kIKindOrI : - DoCodeOr(); - break; - case kIKindOrEaD : - /* DoCodeOrEaD(); */ - DoCodeOr(); - break; - case kIKindOrDEa : - /* DoCodeOrDEa(); */ - DoCodeOr(); - break; - case kIKindEor : - DoCodeEor(); - break; - case kIKindEorI : - DoCodeEor(); - break; - case kIKindNot : - DoCodeNot(); - break; - - case kIKindScc : - DoCodeScc(); - break; - case kIKindEXTL : - DoCodeEXTL(); - break; - case kIKindEXTW : - DoCodeEXTW(); - break; - case kIKindNegB : - DoCodeNegB(); - break; - case kIKindNegW : - DoCodeNegW(); - break; - case kIKindNegL : - DoCodeNegL(); - break; - case kIKindNegXB : - DoCodeNegXB(); - break; - case kIKindNegXW : - DoCodeNegXW(); - break; - case kIKindNegXL : - DoCodeNegXL(); - break; - - case kIKindMulU : - DoCodeMulU(); - break; - case kIKindMulS : - DoCodeMulS(); - break; - case kIKindDivU : - DoCodeDivU(); - break; - case kIKindDivS : - DoCodeDivS(); - break; - case kIKindExgdd : - DoCodeExgdd(); - break; - case kIKindExgaa : - DoCodeExgaa(); - break; - case kIKindExgda : - DoCodeExgda(); - break; - - case kIKindMoveCCREa : - DoCodeMoveCCREa(); - break; - case kIKindMoveEaCCR : - DoCodeMoveEaCR(); - break; - case kIKindMoveSREa : - DoCodeMoveSREa(); - break; - case kIKindMoveEaSR : - DoCodeMoveEaSR(); - break; - case kIKindBinOpStatusCCR : - DoBinOpStatusCCR(); - break; - - case kIKindMOVEMApRW : - DoCodeMOVEMApRW(); - break; - case kIKindMOVEMRmMW : - DoCodeMOVEMRmMW(); - break; - case kIKindMOVEMrm : - DoCodeMOVEMrm(); - break; - case kIKindMOVEMmr : - DoCodeMOVEMmr(); - break; - - case kIKindAbcdr : - DoCodeAbcdr(); - break; - case kIKindAbcdm : - DoCodeAbcdm(); - break; - case kIKindSbcdr : - DoCodeSbcdr(); - break; - case kIKindSbcdm : - DoCodeSbcdm(); - break; - case kIKindNbcd : - DoCodeNbcd(); - break; - - case kIKindRte : - DoCodeRte(); - break; - case kIKindNop : - DoCodeNop(); - break; - case kIKindMoveP : - DoCodeMoveP(); - break; - case kIKindIllegal : - op_illg(); - break; - - case kIKindChkW : - DoCodeChkW(); - break; - case kIKindTrap : - DoCodeTrap(); - break; - case kIKindTrapV : - DoCodeTrapV(); - break; - case kIKindRtr : - DoCodeRtr(); - break; - case kIKindLink : - DoCodeLink(); - break; - case kIKindUnlk : - DoCodeUnlk(); - break; - case kIKindMoveRUSP : - DoCodeMoveRUSP(); - break; - case kIKindMoveUSPR : - DoCodeMoveUSPR(); - break; - case kIKindTas : - DoCodeTas(); - break; - case kIKindF : - DoCodeF(); - break; - case kIKindCallMorRtm : - DoCodeCallMorRtm(); - break; - case kIKindStop : - DoCodeStop(); - break; - case kIKindReset : - DoCodeReset(); - break; -#if Use68020 - case kIKindEXTBL : - DoCodeEXTBL(); - break; - case kIKindTRAPcc : - DoCodeTRAPcc(); - break; - case kIKindChkL : - DoCodeChkL(); - break; - case kIKindBkpt : - DoCodeBkpt(); - break; - case kIKindDivL : - DoCodeDivL(); - break; - case kIKindMulL : - DoCodeMulL(); - break; - case kIKindRtd : - DoCodeRtd(); - break; - case kIKindMoveC : - DoCodeMoveC(); - break; - case kIKindLinkL : - DoCodeLinkL(); - break; - case kIKindPack : - DoCodePack(); - break; - case kIKindUnpk : - DoCodeUnpk(); - break; - case kIKindCHK2orCMP2 : - DoCHK2orCMP2(); - break; - case kIKindCAS2 : - DoCAS2(); - break; - case kIKindCAS : - DoCAS(); - break; - case kIKindMoveS : - DoMOVES(); - break; - case kIKindBitField : - DoBitField(); - break; -#endif - } - } while (regs.MaxCyclesToGo > 0); -} - -GLOBALFUNC si5r GetCyclesRemaining(void) -{ - return regs.MoreCyclesToGo + regs.MaxCyclesToGo; -} - -GLOBALPROC SetCyclesRemaining(si5r n) -{ - if (regs.MaxCyclesToGo >= n) { - regs.MoreCyclesToGo = 0; - regs.MaxCyclesToGo = n; - } else { - regs.MoreCyclesToGo = n - regs.MaxCyclesToGo; - } -} - -GLOBALFUNC ui3r get_vm_byte(CPTR addr) -{ - return (ui3b) get_byte(addr); -} - -GLOBALFUNC ui4r get_vm_word(CPTR addr) -{ - return (ui4b) get_word(addr); -} - -GLOBALFUNC ui5r get_vm_long(CPTR addr) -{ - return (ui5b) get_long(addr); -} - -GLOBALPROC put_vm_byte(CPTR addr, ui3r b) -{ - put_byte(addr, ui5r_FromSByte(b)); -} - -GLOBALPROC put_vm_word(CPTR addr, ui4r w) -{ - put_word(addr, ui5r_FromSWord(w)); -} - -GLOBALPROC put_vm_long(CPTR addr, ui5r l) -{ - put_long(addr, ui5r_FromSLong(l)); -} - -GLOBALPROC SetHeadATTel(ATTep p) -{ - regs.MATCrdB.cmpmask = 0; - regs.MATCrdB.cmpvalu = 0xFFFFFFFF; - regs.MATCwrB.cmpmask = 0; - regs.MATCwrB.cmpvalu = 0xFFFFFFFF; - regs.MATCrdW.cmpmask = 0; - regs.MATCrdW.cmpvalu = 0xFFFFFFFF; - regs.MATCwrW.cmpmask = 0; - regs.MATCwrW.cmpvalu = 0xFFFFFFFF; - regs.MATCex.cmpmask = 0; - regs.MATCex.cmpvalu = 0xFFFFFFFF; - regs.HeadATTel = p; -} - -LOCALPROC do_trace(void) -{ - regs.TracePending = trueblnr; - NeedToGetOut(); -} - -GLOBALPROC DiskInsertedPsuedoException(CPTR newpc, ui5b data) -{ - ExceptionTo(newpc -#if Use68020 - , 0 -#endif - ); - m68k_areg(7) -= 4; - put_long(m68k_areg(7), data); -} - -LOCALPROC DoCheckExternalInterruptPending(void) -{ - ui3r level = *regs.fIPL; - if ((level > regs.intmask) || (level == 7)) { -#if WantCloserCyc - regs.MaxCyclesToGo -= - (44 * kCycleScale + 5 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); -#endif - Exception(24 + level); - regs.intmask = level; - } -} - -GLOBALPROC m68k_IPLchangeNtfy(void) -{ - ui3r level = *regs.fIPL; - if ((level > regs.intmask) || (level == 7)) { - SetExternalInterruptPending(); - } -} - -#if WantDumpTable -FORWARDPROC InitDumpTable(void); -#endif - -GLOBALPROC m68k_reset(void) -{ -#if WantDumpTable - InitDumpTable(); -#endif - regs.MaxCyclesToGo = 0; - regs.MoreCyclesToGo = 0; - regs.ResidualCycles = 0; - - do_put_mem_word(regs.fakeword, 0x4AFC); - /* illegal instruction opcode */ - -#if 0 - regs.ResetPending = trueblnr; - NeedToGetOut(); -#else -/* Sets the MC68000 reset jump vector... */ - m68k_setpc(get_long(0x00000004)); - -/* Sets the initial stack vector... */ - m68k_areg(7) = get_long(0x00000000); - - regs.s = 1; -#if Use68020 - regs.m = 0; - regs.t0 = 0; -#endif - regs.t1 = 0; - ZFLG = CFLG = NFLG = VFLG = 0; - regs.ExternalInterruptPending = falseblnr; - regs.TracePending = falseblnr; - regs.intmask = 7; - -#if Use68020 - regs.sfc = 0; - regs.dfc = 0; - regs.vbr = 0; - regs.cacr = 0; - regs.caar = 0; -#endif -#endif -} - -#if SmallGlobals -GLOBALPROC MINEM68K_ReserveAlloc(void) -{ - ReserveAllocOneBlock((ui3p *)®s.disp_table, - disp_table_sz * 8, 6, falseblnr); -} -#endif - -GLOBALPROC MINEM68K_Init( - ui3b *fIPL) -{ - regs.fIPL = fIPL; - - M68KITAB_setup(regs.disp_table); -} - -GLOBALPROC m68k_go_nCycles(ui5b n) -{ - regs.MaxCyclesToGo += (n + regs.ResidualCycles); - while (regs.MaxCyclesToGo > 0) { - -#if 0 - if (regs.ResetPending) { - m68k_DoReset(); - } -#endif - if (regs.TracePending) { -#if WantCloserCyc - regs.MaxCyclesToGo -= (34 * kCycleScale - + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); -#endif - Exception(9); - } - if (regs.ExternalInterruptPending) { - regs.ExternalInterruptPending = falseblnr; - DoCheckExternalInterruptPending(); - } - if (regs.t1) { - do_trace(); - } - m68k_go_MaxCycles(); - regs.MaxCyclesToGo += regs.MoreCyclesToGo; - regs.MoreCyclesToGo = 0; - } - - regs.ResidualCycles = regs.MaxCyclesToGo; - regs.MaxCyclesToGo = 0; -} +/* MINEM68K.c Copyright (C) 2009 Bernd Schmidt, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* EMulator of 68K cpu with GENeric c code (not assembly) This code descends from a simple 68000 emulator that I (Paul C. Pratt) wrote long ago. That emulator ran on a 680x0, and used the cpu it ran on to do some of the work. This descendent fills in those holes with code from the Un*x Amiga Emulator by Bernd Schmidt, as found being used in vMac. This emulator is about 10 times smaller than the UAE, at the cost of being 2 to 3 times slower. FPU Emulation added 9/12/2009 by Ross Martin (this code now located in "FPCPEMDV.h") */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "ENDIANAC.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "M68KITAB.h" #if WantDisasm #include "DISAM68K.h" #endif #endif #include "MINEM68K.h" /* ReportAbnormalID unused 0x0123 - 0x01FF */ #ifndef DisableLazyFlagAll #define DisableLazyFlagAll 0 #endif /* useful for debugging, to tell if an observed bug is being cause by lazy flag evaluation stuff. Can also disable parts of it individually: */ #ifndef ForceFlagsEval #if DisableLazyFlagAll #define ForceFlagsEval 1 #else #define ForceFlagsEval 0 #endif #endif #ifndef UseLazyZ #if DisableLazyFlagAll || ForceFlagsEval #define UseLazyZ 0 #else #define UseLazyZ 1 #endif #endif #ifndef UseLazyCC #if DisableLazyFlagAll #define UseLazyCC 0 #else #define UseLazyCC 1 #endif #endif typedef unsigned char flagtype; /* must be 0 or 1, not boolean */ /* Memory Address Translation Cache record */ struct MATCr { ui5r cmpmask; ui5r cmpvalu; ui5r usemask; ui3p usebase; }; typedef struct MATCr MATCr; typedef MATCr *MATCp; #ifndef USE_PCLIMIT #define USE_PCLIMIT 1 #endif #define AKMemory 0 #define AKRegister 1 union ArgAddrT { ui5r mem; ui5r *rga; }; typedef union ArgAddrT ArgAddrT; enum { kLazyFlagsDefault, kLazyFlagsTstB, kLazyFlagsTstW, kLazyFlagsTstL, kLazyFlagsCmpB, kLazyFlagsCmpW, kLazyFlagsCmpL, kLazyFlagsSubB, kLazyFlagsSubW, kLazyFlagsSubL, kLazyFlagsAddB, kLazyFlagsAddW, kLazyFlagsAddL, kLazyFlagsNegB, kLazyFlagsNegW, kLazyFlagsNegL, kLazyFlagsAsrB, kLazyFlagsAsrW, kLazyFlagsAsrL, kLazyFlagsAslB, kLazyFlagsAslW, kLazyFlagsAslL, #if UseLazyZ kLazyFlagsZSet, #endif kNumLazyFlagsKinds }; typedef void (my_reg_call *ArgSetDstP)(ui5r f); #define FasterAlignedL 0 /* If most long memory access is long aligned, this should be faster. But on the Mac, this doesn't seem to be the case, so an unpredictable branch slows it down. */ #ifndef HaveGlbReg #define HaveGlbReg 0 #endif LOCALVAR struct regstruct { ui5r regs[16]; /* Data and Address registers */ ui3p pc_p; ui3p pc_pHi; si5rr MaxCyclesToGo; #if WantCloserCyc DecOpR *CurDecOp; #endif DecOpYR CurDecOpY; ui3r LazyFlagKind; ui3r LazyXFlagKind; #if UseLazyZ ui3r LazyFlagZSavedKind; #endif ui5r LazyFlagArgSrc; ui5r LazyFlagArgDst; ui5r LazyXFlagArgSrc; ui5r LazyXFlagArgDst; ArgAddrT ArgAddr; ArgSetDstP ArgSetDst; ui5b SrcVal; ui3p pc_pLo; ui5r pc; /* Program Counter */ MATCr MATCrdB; MATCr MATCwrB; MATCr MATCrdW; MATCr MATCwrW; #if FasterAlignedL MATCr MATCrdL; MATCr MATCwrL; #endif ATTep HeadATTel; si5r MoreCyclesToGo; si5r ResidualCycles; ui3b fakeword[2]; /* Status Register */ ui5r intmask; /* bits 10-8 : interrupt priority mask */ flagtype t1; /* bit 15: Trace mode 1 */ #if Use68020 flagtype t0; /* bit 14: Trace mode 0 */ #endif flagtype s; /* bit 13: Supervisor or user privilege level */ #if Use68020 flagtype m; /* bit 12: Master or interrupt mode */ #endif flagtype x; /* bit 4: eXtend */ flagtype n; /* bit 3: Negative */ flagtype z; /* bit 2: Zero */ flagtype v; /* bit 1: oVerflow */ flagtype c; /* bit 0: Carry */ #if EmMMU | EmFPU ui5b ArgKind; #endif blnr TracePending; blnr ExternalInterruptPending; #if 0 blnr ResetPending; #endif ui3b *fIPL; #ifdef r_regs struct regstruct *save_regs; #endif CPTR usp; /* User Stack Pointer */ CPTR isp; /* Interrupt Stack Pointer */ #if Use68020 CPTR msp; /* Master Stack Pointer */ ui5b sfc; /* Source Function Code register */ ui5b dfc; /* Destination Function Code register */ ui5b vbr; /* Vector Base Register */ ui5b cacr; /* Cache Control Register */ /* bit 0 : Enable Cache bit 1 : Freeze Cache bit 2 : Clear Entry In Cache (write only) bit 3 : Clear Cache (write only) */ ui5b caar; /* Cache Address Register */ #endif #define disp_table_sz (256 * 256) #if SmallGlobals DecOpR *disp_table; #else DecOpR disp_table[disp_table_sz]; #endif } regs; #define ui5r_MSBisSet(x) (((si5r)(x)) < 0) #define Bool2Bit(x) ((x) ? 1 : 0) #ifdef r_regs register struct regstruct *g_regs asm (r_regs); #define V_regs (*g_regs) #else #define V_regs regs #endif #ifdef r_pc_p register ui3p g_pc_p asm (r_pc_p); #define V_pc_p g_pc_p #else #define V_pc_p V_regs.pc_p #endif #ifdef r_MaxCyclesToGo register si5rr g_MaxCyclesToGo asm (r_MaxCyclesToGo); #define V_MaxCyclesToGo g_MaxCyclesToGo #else #define V_MaxCyclesToGo V_regs.MaxCyclesToGo #endif #ifdef r_pc_pHi register ui3p g_pc_pHi asm (r_pc_pHi); #define V_pc_pHi g_pc_pHi #else #define V_pc_pHi V_regs.pc_pHi #endif #define ZFLG V_regs.z #define NFLG V_regs.n #define CFLG V_regs.c #define VFLG V_regs.v #define XFLG V_regs.x #define m68k_dreg(num) (V_regs.regs[(num)]) #define m68k_areg(num) (V_regs.regs[(num) + 8]) #ifndef WantDumpTable #define WantDumpTable 0 #endif #if WantDumpTable LOCALVAR ui5b DumpTable[kNumIKinds]; #endif #if USE_PCLIMIT FORWARDPROC Recalc_PC_Block(void); FORWARDFUNC ui5r my_reg_call Recalc_PC_BlockReturnUi5r(ui5r v); #endif LOCALINLINEFUNC ui4r nextiword(void) /* NOT sign extended */ { ui4r r = do_get_mem_word(V_pc_p); V_pc_p += 2; #if USE_PCLIMIT if (my_cond_rare(V_pc_p >= V_pc_pHi)) { Recalc_PC_Block(); } #endif return r; } LOCALINLINEFUNC ui5r nextiSByte(void) { ui5r r = ui5r_FromSByte(do_get_mem_byte(V_pc_p + 1)); V_pc_p += 2; #if USE_PCLIMIT if (my_cond_rare(V_pc_p >= V_pc_pHi)) { return Recalc_PC_BlockReturnUi5r(r); } #endif return r; } LOCALINLINEFUNC ui5r nextiSWord(void) /* NOT sign extended */ { ui5r r = ui5r_FromSWord(do_get_mem_word(V_pc_p)); V_pc_p += 2; #if USE_PCLIMIT if (my_cond_rare(V_pc_p >= V_pc_pHi)) { return Recalc_PC_BlockReturnUi5r(r); } #endif return r; } FORWARDFUNC ui5r nextilong_ext(void); LOCALINLINEFUNC ui5r nextilong(void) { ui5r r = do_get_mem_long(V_pc_p); V_pc_p += 4; #if USE_PCLIMIT /* could be two words in different blocks */ if (my_cond_rare(V_pc_p >= V_pc_pHi)) { r = nextilong_ext(); } #endif return r; } LOCALINLINEPROC BackupPC(void) { V_pc_p -= 2; #if USE_PCLIMIT if (my_cond_rare(V_pc_p < V_regs.pc_pLo)) { Recalc_PC_Block(); } #endif } LOCALINLINEFUNC CPTR m68k_getpc(void) { return V_regs.pc + (V_pc_p - V_regs.pc_pLo); } FORWARDPROC DoCodeTst(void); FORWARDPROC DoCodeCmpB(void); FORWARDPROC DoCodeCmpW(void); FORWARDPROC DoCodeCmpL(void); FORWARDPROC DoCodeBccB(void); FORWARDPROC DoCodeBccW(void); FORWARDPROC DoCodeBraB(void); FORWARDPROC DoCodeBraW(void); FORWARDPROC DoCodeDBcc(void); FORWARDPROC DoCodeDBF(void); FORWARDPROC DoCodeSwap(void); FORWARDPROC DoCodeMoveL(void); FORWARDPROC DoCodeMoveW(void); FORWARDPROC DoCodeMoveB(void); FORWARDPROC DoCodeMoveA(void); FORWARDPROC DoCodeMoveQ(void); FORWARDPROC DoCodeAddB(void); FORWARDPROC DoCodeAddW(void); FORWARDPROC DoCodeAddL(void); FORWARDPROC DoCodeSubB(void); FORWARDPROC DoCodeSubW(void); FORWARDPROC DoCodeSubL(void); FORWARDPROC DoCodeLea(void); FORWARDPROC DoCodePEA(void); FORWARDPROC DoCodeA(void); FORWARDPROC DoCodeBsrB(void); FORWARDPROC DoCodeBsrW(void); FORWARDPROC DoCodeJsr(void); FORWARDPROC DoCodeLinkA6(void); FORWARDPROC DoCodeMOVEMRmML(void); FORWARDPROC DoCodeMOVEMApRL(void); FORWARDPROC DoCodeUnlkA6(void); FORWARDPROC DoCodeRts(void); FORWARDPROC DoCodeJmp(void); FORWARDPROC DoCodeClr(void); FORWARDPROC DoCodeAddA(void); FORWARDPROC DoCodeSubA(void); FORWARDPROC DoCodeCmpA(void); FORWARDPROC DoCodeAddXB(void); FORWARDPROC DoCodeAddXW(void); FORWARDPROC DoCodeAddXL(void); FORWARDPROC DoCodeSubXB(void); FORWARDPROC DoCodeSubXW(void); FORWARDPROC DoCodeSubXL(void); FORWARDPROC DoCodeAslB(void); FORWARDPROC DoCodeAslW(void); FORWARDPROC DoCodeAslL(void); FORWARDPROC DoCodeAsrB(void); FORWARDPROC DoCodeAsrW(void); FORWARDPROC DoCodeAsrL(void); FORWARDPROC DoCodeLslB(void); FORWARDPROC DoCodeLslW(void); FORWARDPROC DoCodeLslL(void); FORWARDPROC DoCodeLsrB(void); FORWARDPROC DoCodeLsrW(void); FORWARDPROC DoCodeLsrL(void); FORWARDPROC DoCodeRxlB(void); FORWARDPROC DoCodeRxlW(void); FORWARDPROC DoCodeRxlL(void); FORWARDPROC DoCodeRxrB(void); FORWARDPROC DoCodeRxrW(void); FORWARDPROC DoCodeRxrL(void); FORWARDPROC DoCodeRolB(void); FORWARDPROC DoCodeRolW(void); FORWARDPROC DoCodeRolL(void); FORWARDPROC DoCodeRorB(void); FORWARDPROC DoCodeRorW(void); FORWARDPROC DoCodeRorL(void); FORWARDPROC DoCodeBTstB(void); FORWARDPROC DoCodeBChgB(void); FORWARDPROC DoCodeBClrB(void); FORWARDPROC DoCodeBSetB(void); FORWARDPROC DoCodeBTstL(void); FORWARDPROC DoCodeBChgL(void); FORWARDPROC DoCodeBClrL(void); FORWARDPROC DoCodeBSetL(void); FORWARDPROC DoCodeAnd(void); FORWARDPROC DoCodeOr(void); FORWARDPROC DoCodeEor(void); FORWARDPROC DoCodeNot(void); FORWARDPROC DoCodeScc(void); FORWARDPROC DoCodeNegXB(void); FORWARDPROC DoCodeNegXW(void); FORWARDPROC DoCodeNegXL(void); FORWARDPROC DoCodeNegB(void); FORWARDPROC DoCodeNegW(void); FORWARDPROC DoCodeNegL(void); FORWARDPROC DoCodeEXTW(void); FORWARDPROC DoCodeEXTL(void); FORWARDPROC DoCodeMulU(void); FORWARDPROC DoCodeMulS(void); FORWARDPROC DoCodeDivU(void); FORWARDPROC DoCodeDivS(void); FORWARDPROC DoCodeExg(void); FORWARDPROC DoCodeMoveEaCR(void); FORWARDPROC DoCodeMoveSREa(void); FORWARDPROC DoCodeMoveEaSR(void); FORWARDPROC DoCodeOrISR(void); FORWARDPROC DoCodeAndISR(void); FORWARDPROC DoCodeEorISR(void); FORWARDPROC DoCodeOrICCR(void); FORWARDPROC DoCodeAndICCR(void); FORWARDPROC DoCodeEorICCR(void); FORWARDPROC DoCodeMOVEMApRW(void); FORWARDPROC DoCodeMOVEMRmMW(void); FORWARDPROC DoCodeMOVEMrmW(void); FORWARDPROC DoCodeMOVEMrmL(void); FORWARDPROC DoCodeMOVEMmrW(void); FORWARDPROC DoCodeMOVEMmrL(void); FORWARDPROC DoCodeAbcd(void); FORWARDPROC DoCodeSbcd(void); FORWARDPROC DoCodeNbcd(void); FORWARDPROC DoCodeRte(void); FORWARDPROC DoCodeNop(void); FORWARDPROC DoCodeMoveP0(void); FORWARDPROC DoCodeMoveP1(void); FORWARDPROC DoCodeMoveP2(void); FORWARDPROC DoCodeMoveP3(void); FORWARDPROC op_illg(void); FORWARDPROC DoCodeChk(void); FORWARDPROC DoCodeTrap(void); FORWARDPROC DoCodeTrapV(void); FORWARDPROC DoCodeRtr(void); FORWARDPROC DoCodeLink(void); FORWARDPROC DoCodeUnlk(void); FORWARDPROC DoCodeMoveRUSP(void); FORWARDPROC DoCodeMoveUSPR(void); FORWARDPROC DoCodeTas(void); FORWARDPROC DoCodeFdefault(void); FORWARDPROC DoCodeStop(void); FORWARDPROC DoCodeReset(void); #if Use68020 FORWARDPROC DoCodeCallMorRtm(void); FORWARDPROC DoCodeBraL(void); FORWARDPROC DoCodeBccL(void); FORWARDPROC DoCodeBsrL(void); FORWARDPROC DoCodeEXTBL(void); FORWARDPROC DoCodeTRAPcc(void); FORWARDPROC DoCodeBkpt(void); FORWARDPROC DoCodeDivL(void); FORWARDPROC DoCodeMulL(void); FORWARDPROC DoCodeRtd(void); FORWARDPROC DoCodeMoveCCREa(void); FORWARDPROC DoMoveFromControl(void); FORWARDPROC DoMoveToControl(void); FORWARDPROC DoCodeLinkL(void); FORWARDPROC DoCodePack(void); FORWARDPROC DoCodeUnpk(void); FORWARDPROC DoCHK2orCMP2(void); FORWARDPROC DoCAS2(void); FORWARDPROC DoCAS(void); FORWARDPROC DoMOVES(void); FORWARDPROC DoBitField(void); #endif #if EmMMU FORWARDPROC DoCodeMMU(void); #endif #if EmFPU FORWARDPROC DoCodeFPU_md60(void); FORWARDPROC DoCodeFPU_DBcc(void); FORWARDPROC DoCodeFPU_Trapcc(void); FORWARDPROC DoCodeFPU_Scc(void); FORWARDPROC DoCodeFPU_FBccW(void); FORWARDPROC DoCodeFPU_FBccL(void); FORWARDPROC DoCodeFPU_Save(void); FORWARDPROC DoCodeFPU_Restore(void); FORWARDPROC DoCodeFPU_dflt(void); #endif typedef void (*func_pointer_t)(void); LOCALVAR const func_pointer_t OpDispatch[kNumIKinds + 1] = { DoCodeTst /* kIKindTst */, DoCodeCmpB /* kIKindCmpB */, DoCodeCmpW /* kIKindCmpW */, DoCodeCmpL /* kIKindCmpL */, DoCodeBccB /* kIKindBccB */, DoCodeBccW /* kIKindBccW */, DoCodeBraB /* kIKindBraB */, DoCodeBraW /* kIKindBraW */, DoCodeDBcc /* kIKindDBcc */, DoCodeDBF /* kIKindDBF */, DoCodeSwap /* kIKindSwap */, DoCodeMoveL /* kIKindMoveL */, DoCodeMoveW /* kIKindMoveW */, DoCodeMoveB /* kIKindMoveB */, DoCodeMoveA /* kIKindMoveAL */, DoCodeMoveA /* kIKindMoveAW */, DoCodeMoveQ /* kIKindMoveQ */, DoCodeAddB /* kIKindAddB */, DoCodeAddW /* kIKindAddW */, DoCodeAddL /* kIKindAddL */, DoCodeSubB /* kIKindSubB */, DoCodeSubW /* kIKindSubW */, DoCodeSubL /* kIKindSubL */, DoCodeLea /* kIKindLea */, DoCodePEA /* kIKindPEA */, DoCodeA /* kIKindA */, DoCodeBsrB /* kIKindBsrB */, DoCodeBsrW /* kIKindBsrW */, DoCodeJsr /* kIKindJsr */, DoCodeLinkA6 /* kIKindLinkA6 */, DoCodeMOVEMRmML /* kIKindMOVEMRmML */, DoCodeMOVEMApRL /* kIKindMOVEMApRL */, DoCodeUnlkA6 /* kIKindUnlkA6 */, DoCodeRts /* kIKindRts */, DoCodeJmp /* kIKindJmp */, DoCodeClr /* kIKindClr */, DoCodeAddA /* kIKindAddA */, DoCodeAddA /* kIKindAddQA */, DoCodeSubA /* kIKindSubA */, DoCodeSubA /* kIKindSubQA */, DoCodeCmpA /* kIKindCmpA */, DoCodeAddXB /* kIKindAddXB */, DoCodeAddXW /* kIKindAddXW */, DoCodeAddXL /* kIKindAddXL */, DoCodeSubXB /* kIKindSubXB */, DoCodeSubXW /* kIKindSubXW */, DoCodeSubXL /* kIKindSubXL */, DoCodeAslB /* kIKindAslB */, DoCodeAslW /* kIKindAslW */, DoCodeAslL /* kIKindAslL */, DoCodeAsrB /* kIKindAsrB */, DoCodeAsrW /* kIKindAsrW */, DoCodeAsrL /* kIKindAsrL */, DoCodeLslB /* kIKindLslB */, DoCodeLslW /* kIKindLslW */, DoCodeLslL /* kIKindLslL */, DoCodeLsrB /* kIKindLsrB */, DoCodeLsrW /* kIKindLsrW */, DoCodeLsrL /* kIKindLsrL */, DoCodeRxlB /* kIKindRxlB */, DoCodeRxlW /* kIKindRxlW */, DoCodeRxlL /* kIKindRxlL */, DoCodeRxrB /* kIKindRxrB */, DoCodeRxrW /* kIKindRxrW */, DoCodeRxrL /* kIKindRxrL */, DoCodeRolB /* kIKindRolB */, DoCodeRolW /* kIKindRolW */, DoCodeRolL /* kIKindRolL */, DoCodeRorB /* kIKindRorB */, DoCodeRorW /* kIKindRorW */, DoCodeRorL /* kIKindRorL */, DoCodeBTstB /* kIKindBTstB */, DoCodeBChgB /* kIKindBChgB */, DoCodeBClrB /* kIKindBClrB */, DoCodeBSetB /* kIKindBSetB */, DoCodeBTstL /* kIKindBTstL */, DoCodeBChgL /* kIKindBChgL */, DoCodeBClrL /* kIKindBClrL */, DoCodeBSetL /* kIKindBSetL */, DoCodeAnd /* kIKindAndI */, DoCodeAnd /* kIKindAndEaD */, DoCodeAnd /* kIKindAndDEa */, DoCodeOr /* kIKindOrI */, DoCodeOr /* kIKindOrDEa */, DoCodeOr /* kIKindOrEaD */, DoCodeEor /* kIKindEor */, DoCodeEor /* kIKindEorI */, DoCodeNot /* kIKindNot */, DoCodeScc /* kIKindScc */, DoCodeNegXB /* kIKindNegXB */, DoCodeNegXW /* kIKindNegXW */, DoCodeNegXL /* kIKindNegXL */, DoCodeNegB /* kIKindNegB */, DoCodeNegW /* kIKindNegW */, DoCodeNegL /* kIKindNegL */, DoCodeEXTW /* kIKindEXTW */, DoCodeEXTL /* kIKindEXTL */, DoCodeMulU /* kIKindMulU */, DoCodeMulS /* kIKindMulS */, DoCodeDivU /* kIKindDivU */, DoCodeDivS /* kIKindDivS */, DoCodeExg /* kIKindExg */, DoCodeMoveEaCR /* kIKindMoveEaCCR */, DoCodeMoveSREa /* kIKindMoveSREa */, DoCodeMoveEaSR /* kIKindMoveEaSR */, DoCodeOrISR /* kIKindOrISR */, DoCodeAndISR /* kIKindAndISR */, DoCodeEorISR /* kIKindEorISR */, DoCodeOrICCR /* kIKindOrICCR */, DoCodeAndICCR /* kIKindAndICCR */, DoCodeEorICCR /* kIKindEorICCR */, DoCodeMOVEMApRW /* kIKindMOVEMApRW */, DoCodeMOVEMRmMW /* kIKindMOVEMRmMW */, DoCodeMOVEMrmW /* kIKindMOVEMrmW */, DoCodeMOVEMrmL /* kIKindMOVEMrmL */, DoCodeMOVEMmrW /* kIKindMOVEMmrW */, DoCodeMOVEMmrL /* kIKindMOVEMmrL */, DoCodeAbcd /* kIKindAbcd */, DoCodeSbcd /* kIKindSbcd */, DoCodeNbcd /* kIKindNbcd */, DoCodeRte /* kIKindRte */, DoCodeNop /* kIKindNop */, DoCodeMoveP0 /* kIKindMoveP0 */, DoCodeMoveP1 /* kIKindMoveP1 */, DoCodeMoveP2 /* kIKindMoveP2 */, DoCodeMoveP3 /* kIKindMoveP3 */, op_illg /* kIKindIllegal */, DoCodeChk /* kIKindChkW */, DoCodeTrap /* kIKindTrap */, DoCodeTrapV /* kIKindTrapV */, DoCodeRtr /* kIKindRtr */, DoCodeLink /* kIKindLink */, DoCodeUnlk /* kIKindUnlk */, DoCodeMoveRUSP /* kIKindMoveRUSP */, DoCodeMoveUSPR /* kIKindMoveUSPR */, DoCodeTas /* kIKindTas */, DoCodeFdefault /* kIKindFdflt */, DoCodeStop /* kIKindStop */, DoCodeReset /* kIKindReset */, #if Use68020 DoCodeCallMorRtm /* kIKindCallMorRtm */, DoCodeBraL /* kIKindBraL */, DoCodeBccL /* kIKindBccL */, DoCodeBsrL /* kIKindBsrL */, DoCodeEXTBL /* kIKindEXTBL */, DoCodeTRAPcc /* kIKindTRAPcc */, DoCodeChk /* kIKindChkL */, DoCodeBkpt /* kIKindBkpt */, DoCodeDivL /* kIKindDivL */, DoCodeMulL /* kIKindMulL */, DoCodeRtd /* kIKindRtd */, DoCodeMoveCCREa /* kIKindMoveCCREa */, DoMoveFromControl /* kIKindMoveCEa */, DoMoveToControl /* kIKindMoveEaC */, DoCodeLinkL /* kIKindLinkL */, DoCodePack /* kIKindPack */, DoCodeUnpk /* kIKindUnpk */, DoCHK2orCMP2 /* kIKindCHK2orCMP2 */, DoCAS2 /* kIKindCAS2 */, DoCAS /* kIKindCAS */, DoMOVES /* kIKindMoveS */, DoBitField /* kIKindBitField */, #endif #if EmMMU DoCodeMMU /* kIKindMMU */, #endif #if EmFPU DoCodeFPU_md60 /* kIKindFPUmd60 */, DoCodeFPU_DBcc /* kIKindFPUDBcc */, DoCodeFPU_Trapcc /* kIKindFPUTrapcc */, DoCodeFPU_Scc /* kIKindFPUScc */, DoCodeFPU_FBccW /* kIKindFPUFBccW */, DoCodeFPU_FBccL /* kIKindFPUFBccL */, DoCodeFPU_Save /* kIKindFPUSave */, DoCodeFPU_Restore /* kIKindFPURestore */, DoCodeFPU_dflt /* kIKindFPUdflt */, #endif 0 }; LOCALPROC m68k_go_MaxCycles(void) { ui5r opcode; DecOpR *p; ui4rr MainClas; ui4rr Cycles; DecOpYR y; func_pointer_t d; /* Main loop of emulator. Always execute at least one instruction, even if V_regs.MaxInstructionsToGo == 0. Needed for trace flag to work. */ goto label_enter; do { V_regs.CurDecOpY = y; d(); label_enter: #if WantDisasm DisasmOneOrSave(m68k_getpc()); #endif opcode = nextiword(); p = &V_regs.disp_table[opcode]; #if WantCloserCyc V_regs.CurDecOp = p; #endif MainClas = p->x.MainClas; Cycles = p->x.Cycles; y = p->y; #if WantDumpTable DumpTable[MainClas] ++; #endif d = OpDispatch[MainClas]; } while (((si5rr)(V_MaxCyclesToGo -= Cycles)) > 0); V_regs.CurDecOpY = y; d(); } FORWARDFUNC ui5r my_reg_call get_byte_ext(CPTR addr); LOCALFUNC ui5r my_reg_call get_byte(CPTR addr) { ui3p m = (addr & V_regs.MATCrdB.usemask) + V_regs.MATCrdB.usebase; if ((addr & V_regs.MATCrdB.cmpmask) == V_regs.MATCrdB.cmpvalu) { return ui5r_FromSByte(*m); } else { return get_byte_ext(addr); } } FORWARDPROC my_reg_call put_byte_ext(CPTR addr, ui5r b); LOCALPROC my_reg_call put_byte(CPTR addr, ui5r b) { ui3p m = (addr & V_regs.MATCwrB.usemask) + V_regs.MATCwrB.usebase; if ((addr & V_regs.MATCwrB.cmpmask) == V_regs.MATCwrB.cmpvalu) { *m = b; } else { put_byte_ext(addr, b); } } FORWARDFUNC ui5r my_reg_call get_word_ext(CPTR addr); LOCALFUNC ui5r my_reg_call get_word(CPTR addr) { ui3p m = (addr & V_regs.MATCrdW.usemask) + V_regs.MATCrdW.usebase; if ((addr & V_regs.MATCrdW.cmpmask) == V_regs.MATCrdW.cmpvalu) { return ui5r_FromSWord(do_get_mem_word(m)); } else { return get_word_ext(addr); } } FORWARDPROC my_reg_call put_word_ext(CPTR addr, ui5r w); LOCALPROC my_reg_call put_word(CPTR addr, ui5r w) { ui3p m = (addr & V_regs.MATCwrW.usemask) + V_regs.MATCwrW.usebase; if ((addr & V_regs.MATCwrW.cmpmask) == V_regs.MATCwrW.cmpvalu) { do_put_mem_word(m, w); } else { put_word_ext(addr, w); } } FORWARDFUNC ui5r my_reg_call get_long_misaligned_ext(CPTR addr); LOCALFUNC ui5r my_reg_call get_long_misaligned(CPTR addr) { CPTR addr2 = addr + 2; ui3p m = (addr & V_regs.MATCrdW.usemask) + V_regs.MATCrdW.usebase; ui3p m2 = (addr2 & V_regs.MATCrdW.usemask) + V_regs.MATCrdW.usebase; if (((addr & V_regs.MATCrdW.cmpmask) == V_regs.MATCrdW.cmpvalu) && ((addr2 & V_regs.MATCrdW.cmpmask) == V_regs.MATCrdW.cmpvalu)) { ui5r hi = do_get_mem_word(m); ui5r lo = do_get_mem_word(m2); ui5r Data = ((hi << 16) & 0xFFFF0000) | (lo & 0x0000FFFF); return ui5r_FromSLong(Data); } else { return get_long_misaligned_ext(addr); } } #if FasterAlignedL FORWARDFUNC ui5r my_reg_call get_long_ext(CPTR addr); #endif #if FasterAlignedL LOCALFUNC ui5r my_reg_call get_long(CPTR addr) { if (0 == (addr & 0x03)) { ui3p m = (addr & V_regs.MATCrdL.usemask) + V_regs.MATCrdL.usebase; if ((addr & V_regs.MATCrdL.cmpmask) == V_regs.MATCrdL.cmpvalu) { return ui5r_FromSLong(do_get_mem_long(m)); } else { return get_long_ext(addr); } } else { return get_long_misaligned(addr); } } #else #define get_long get_long_misaligned #endif FORWARDPROC my_reg_call put_long_misaligned_ext(CPTR addr, ui5r l); LOCALPROC my_reg_call put_long_misaligned(CPTR addr, ui5r l) { CPTR addr2 = addr + 2; ui3p m = (addr & V_regs.MATCwrW.usemask) + V_regs.MATCwrW.usebase; ui3p m2 = (addr2 & V_regs.MATCwrW.usemask) + V_regs.MATCwrW.usebase; if (((addr & V_regs.MATCwrW.cmpmask) == V_regs.MATCwrW.cmpvalu) && ((addr2 & V_regs.MATCwrW.cmpmask) == V_regs.MATCwrW.cmpvalu)) { do_put_mem_word(m, l >> 16); do_put_mem_word(m2, l); } else { put_long_misaligned_ext(addr, l); } } #if FasterAlignedL FORWARDPROC my_reg_call put_long_ext(CPTR addr, ui5r l); #endif #if FasterAlignedL LOCALPROC my_reg_call put_long(CPTR addr, ui5r l) { if (0 == (addr & 0x03)) { ui3p m = (addr & V_regs.MATCwrL.usemask) + V_regs.MATCwrL.usebase; if ((addr & V_regs.MATCwrL.cmpmask) == V_regs.MATCwrL.cmpvalu) { do_put_mem_long(m, l); } else { put_long_ext(addr, l); } } else { put_long_misaligned(addr, l); } } #else #define put_long put_long_misaligned #endif LOCALFUNC ui5b my_reg_call get_disp_ea(ui5b base) { ui4b dp = nextiword(); int regno = (dp >> 12) & 0x0F; si5b regd = V_regs.regs[regno]; if ((dp & 0x0800) == 0) { regd = (si5b)(si4b)regd; } #if Use68020 regd <<= (dp >> 9) & 3; #if ExtraAbnormalReports if (((dp >> 9) & 3) != 0) { /* ReportAbnormal("Have scale in Extension Word"); */ /* apparently can happen in Sys 7.5.5 boot on 68000 */ } #endif if (dp & 0x0100) { if ((dp & 0x80) != 0) { base = 0; /* ReportAbnormal("Extension Word: suppress base"); */ /* used by Sys 7.5.5 boot */ } if ((dp & 0x40) != 0) { regd = 0; /* ReportAbnormal("Extension Word: suppress regd"); */ /* used by Mac II boot */ } switch ((dp >> 4) & 0x03) { case 0: /* reserved */ ReportAbnormalID(0x0101, "Extension Word: dp reserved"); break; case 1: /* no displacement */ /* ReportAbnormal("Extension Word: no displacement"); */ /* used by Sys 7.5.5 boot */ break; case 2: base += nextiSWord(); /* ReportAbnormal("Extension Word: word displacement"); */ /* used by Sys 7.5.5 boot */ break; case 3: base += nextilong(); /* ReportAbnormal("Extension Word: long displacement"); */ /* used by Mac II boot from system 6.0.8? */ break; } if ((dp & 0x03) == 0) { base += regd; if ((dp & 0x04) != 0) { ReportAbnormalID(0x0102, "Extension Word: reserved dp form"); } /* ReportAbnormal("Extension Word: noindex"); */ /* used by Sys 7.5.5 boot */ } else { if ((dp & 0x04) != 0) { base = get_long(base); base += regd; /* ReportAbnormal("Extension Word: postindex"); */ /* used by Sys 7.5.5 boot */ } else { base += regd; base = get_long(base); /* ReportAbnormal("Extension Word: preindex"); */ /* used by Sys 7.5.5 boot */ } switch (dp & 0x03) { case 1: /* null outer displacement */ /* ReportAbnormal( "Extension Word: null outer displacement"); */ /* used by Sys 7.5.5 boot */ break; case 2: base += nextiSWord(); /* ReportAbnormal( "Extension Word: word outer displacement"); */ /* used by Mac II boot from system 6.0.8? */ break; case 3: base += nextilong(); /* ReportAbnormal( "Extension Word: long outer displacement"); */ /* used by Mac II boot from system 6.0.8? */ break; } } return base; } else #endif { return base + (si3b)(dp) + regd; } } LOCALFUNC ui5r my_reg_call DecodeAddr_Indirect(ui3rr ArgDat) { return V_regs.regs[ArgDat]; } LOCALFUNC ui5r my_reg_call DecodeAddr_APosIncB(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p; *p = a + 1; return a; } LOCALFUNC ui5r my_reg_call DecodeAddr_APosIncW(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p; *p = a + 2; return a; } LOCALFUNC ui5r my_reg_call DecodeAddr_APosIncL(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p; *p = a + 4; return a; } LOCALFUNC ui5r my_reg_call DecodeAddr_APreDecB(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p - 1; *p = a; return a; } LOCALFUNC ui5r my_reg_call DecodeAddr_APreDecW(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p - 2; *p = a; return a; } LOCALFUNC ui5r my_reg_call DecodeAddr_APreDecL(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p - 4; *p = a; return a; } LOCALFUNC ui5r my_reg_call DecodeAddr_ADisp(ui3rr ArgDat) { return V_regs.regs[ArgDat] + nextiSWord(); } LOCALFUNC ui5r my_reg_call DecodeAddr_AIndex(ui3rr ArgDat) { return get_disp_ea(V_regs.regs[ArgDat]); } LOCALFUNC ui5r my_reg_call DecodeAddr_AbsW(ui3rr ArgDat) { UnusedParam(ArgDat); return nextiSWord(); } LOCALFUNC ui5r my_reg_call DecodeAddr_AbsL(ui3rr ArgDat) { UnusedParam(ArgDat); return nextilong(); } LOCALFUNC ui5r my_reg_call DecodeAddr_PCDisp(ui3rr ArgDat) { CPTR pc = m68k_getpc(); UnusedParam(ArgDat); return pc + nextiSWord(); } LOCALFUNC ui5r my_reg_call DecodeAddr_PCIndex(ui3rr ArgDat) { UnusedParam(ArgDat); return get_disp_ea(m68k_getpc()); } typedef ui5r (my_reg_call *DecodeAddrP)(ui3rr ArgDat); LOCALVAR const DecodeAddrP DecodeAddrDispatch[kNumAMds] = { (DecodeAddrP)nullpr /* kAMdRegB */, (DecodeAddrP)nullpr /* kAMdRegW */, (DecodeAddrP)nullpr /* kAMdRegL */, DecodeAddr_Indirect /* kAMdIndirectB */, DecodeAddr_Indirect /* kAMdIndirectW */, DecodeAddr_Indirect /* kAMdIndirectL */, DecodeAddr_APosIncB /* kAMdAPosIncB */, DecodeAddr_APosIncW /* kAMdAPosIncW */, DecodeAddr_APosIncL /* kAMdAPosIncL */, DecodeAddr_APosIncW /* kAMdAPosInc7B */, DecodeAddr_APreDecB /* kAMdAPreDecB */, DecodeAddr_APreDecW /* kAMdAPreDecW */, DecodeAddr_APreDecL /* kAMdAPreDecL */, DecodeAddr_APreDecW /* kAMdAPreDec7B */, DecodeAddr_ADisp /* kAMdADispB */, DecodeAddr_ADisp /* kAMdADispW */, DecodeAddr_ADisp /* kAMdADispL */, DecodeAddr_AIndex /* kAMdAIndexB */, DecodeAddr_AIndex /* kAMdAIndexW */, DecodeAddr_AIndex /* kAMdAIndexL */, DecodeAddr_AbsW /* kAMdAbsWB */, DecodeAddr_AbsW /* kAMdAbsWW */, DecodeAddr_AbsW /* kAMdAbsWL */, DecodeAddr_AbsL /* kAMdAbsLB */, DecodeAddr_AbsL /* kAMdAbsLW */, DecodeAddr_AbsL /* kAMdAbsLL */, DecodeAddr_PCDisp /* kAMdPCDispB */, DecodeAddr_PCDisp /* kAMdPCDispW */, DecodeAddr_PCDisp /* kAMdPCDispL */, DecodeAddr_PCIndex /* kAMdPCIndexB */, DecodeAddr_PCIndex /* kAMdPCIndexW */, DecodeAddr_PCIndex /* kAMdPCIndexL */, (DecodeAddrP)nullpr /* kAMdImmedB */, (DecodeAddrP)nullpr /* kAMdImmedW */, (DecodeAddrP)nullpr /* kAMdImmedL */, (DecodeAddrP)nullpr /* kAMdDat4 */ }; LOCALINLINEFUNC ui5r DecodeAddrSrcDst(DecArgR *f) { return (DecodeAddrDispatch[f->AMd])(f->ArgDat); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_RegB(ui3rr ArgDat) { return ui5r_FromSByte(V_regs.regs[ArgDat]); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_RegW(ui3rr ArgDat) { return ui5r_FromSWord(V_regs.regs[ArgDat]); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_RegL(ui3rr ArgDat) { return ui5r_FromSLong(V_regs.regs[ArgDat]); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_IndirectB(ui3rr ArgDat) { return get_byte(V_regs.regs[ArgDat]); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_IndirectW(ui3rr ArgDat) { return get_word(V_regs.regs[ArgDat]); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_IndirectL(ui3rr ArgDat) { return get_long(V_regs.regs[ArgDat]); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_APosIncB(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p; *p = a + 1; return get_byte(a); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_APosIncW(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p; *p = a + 2; return get_word(a); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_APosIncL(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p; *p = a + 4; return get_long(a); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_APosInc7B(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p; *p = a + 2; return get_byte(a); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_APreDecB(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p - 1; *p = a; return get_byte(a); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_APreDecW(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p - 2; *p = a; return get_word(a); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_APreDecL(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p - 4; *p = a; return get_long(a); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_APreDec7B(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p - 2; *p = a; return get_byte(a); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_ADispB(ui3rr ArgDat) { return get_byte(DecodeAddr_ADisp(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_ADispW(ui3rr ArgDat) { return get_word(DecodeAddr_ADisp(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_ADispL(ui3rr ArgDat) { return get_long(DecodeAddr_ADisp(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_AIndexB(ui3rr ArgDat) { return get_byte(get_disp_ea(V_regs.regs[ArgDat])); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_AIndexW(ui3rr ArgDat) { return get_word(get_disp_ea(V_regs.regs[ArgDat])); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_AIndexL(ui3rr ArgDat) { return get_long(get_disp_ea(V_regs.regs[ArgDat])); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_AbsWB(ui3rr ArgDat) { return get_byte(DecodeAddr_AbsW(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_AbsWW(ui3rr ArgDat) { return get_word(DecodeAddr_AbsW(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_AbsWL(ui3rr ArgDat) { return get_long(DecodeAddr_AbsW(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_AbsLB(ui3rr ArgDat) { return get_byte(DecodeAddr_AbsL(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_AbsLW(ui3rr ArgDat) { return get_word(DecodeAddr_AbsL(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_AbsLL(ui3rr ArgDat) { return get_long(DecodeAddr_AbsL(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_PCDispB(ui3rr ArgDat) { return get_byte(DecodeAddr_PCDisp(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_PCDispW(ui3rr ArgDat) { return get_word(DecodeAddr_PCDisp(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_PCDispL(ui3rr ArgDat) { return get_long(DecodeAddr_PCDisp(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_PCIndexB(ui3rr ArgDat) { return get_byte(DecodeAddr_PCIndex(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_PCIndexW(ui3rr ArgDat) { return get_word(DecodeAddr_PCIndex(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_PCIndexL(ui3rr ArgDat) { return get_long(DecodeAddr_PCIndex(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_ImmedB(ui3rr ArgDat) { UnusedParam(ArgDat); return nextiSByte(); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_ImmedW(ui3rr ArgDat) { UnusedParam(ArgDat); return nextiSWord(); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_ImmedL(ui3rr ArgDat) { UnusedParam(ArgDat); return ui5r_FromSLong(nextilong()); } LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_Dat4(ui3rr ArgDat) { return ArgDat; } typedef ui5r (my_reg_call *DecodeGetSrcDstP)(ui3rr ArgDat); LOCALVAR const DecodeGetSrcDstP DecodeGetSrcDstDispatch[kNumAMds] = { DecodeGetSrcDst_RegB /* kAMdRegB */, DecodeGetSrcDst_RegW /* kAMdRegW */, DecodeGetSrcDst_RegL /* kAMdRegL */, DecodeGetSrcDst_IndirectB /* kAMdIndirectB */, DecodeGetSrcDst_IndirectW /* kAMdIndirectW */, DecodeGetSrcDst_IndirectL /* kAMdIndirectL */, DecodeGetSrcDst_APosIncB /* kAMdAPosIncB */, DecodeGetSrcDst_APosIncW /* kAMdAPosIncW */, DecodeGetSrcDst_APosIncL /* kAMdAPosIncL */, DecodeGetSrcDst_APosInc7B /* kAMdAPosInc7B */, DecodeGetSrcDst_APreDecB /* kAMdAPreDecB */, DecodeGetSrcDst_APreDecW /* kAMdAPreDecW */, DecodeGetSrcDst_APreDecL /* kAMdAPreDecL */, DecodeGetSrcDst_APreDec7B /* kAMdAPreDec7B */, DecodeGetSrcDst_ADispB /* kAMdADispB */, DecodeGetSrcDst_ADispW /* kAMdADispW */, DecodeGetSrcDst_ADispL /* kAMdADispL */, DecodeGetSrcDst_AIndexB /* kAMdAIndexB */, DecodeGetSrcDst_AIndexW /* kAMdAIndexW */, DecodeGetSrcDst_AIndexL /* kAMdAIndexL */, DecodeGetSrcDst_AbsWB /* kAMdAbsWB */, DecodeGetSrcDst_AbsWW /* kAMdAbsWW */, DecodeGetSrcDst_AbsWL /* kAMdAbsWL */, DecodeGetSrcDst_AbsLB /* kAMdAbsLB */, DecodeGetSrcDst_AbsLW /* kAMdAbsLW */, DecodeGetSrcDst_AbsLL /* kAMdAbsLL */, DecodeGetSrcDst_PCDispB /* kAMdPCDispB */, DecodeGetSrcDst_PCDispW /* kAMdPCDispW */, DecodeGetSrcDst_PCDispL /* kAMdPCDispL */, DecodeGetSrcDst_PCIndexB /* kAMdPCIndexB */, DecodeGetSrcDst_PCIndexW /* kAMdPCIndexW */, DecodeGetSrcDst_PCIndexL /* kAMdPCIndexL */, DecodeGetSrcDst_ImmedB /* kAMdImmedB */, DecodeGetSrcDst_ImmedW /* kAMdImmedW */, DecodeGetSrcDst_ImmedL /* kAMdImmedL */, DecodeGetSrcDst_Dat4 /* kAMdDat4 */ }; LOCALINLINEFUNC ui5r DecodeGetSrcDst(DecArgR *f) { return (DecodeGetSrcDstDispatch[f->AMd])(f->ArgDat); } LOCALPROC my_reg_call DecodeSetSrcDst_RegB(ui5r v, ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; #if LittleEndianUnaligned *(ui3b *)p = v; #else *p = (*p & ~ 0xff) | ((v) & 0xff); #endif } LOCALPROC my_reg_call DecodeSetSrcDst_RegW(ui5r v, ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; #if LittleEndianUnaligned *(ui4b *)p = v; #else *p = (*p & ~ 0xffff) | ((v) & 0xffff); #endif } LOCALPROC my_reg_call DecodeSetSrcDst_RegL(ui5r v, ui3rr ArgDat) { V_regs.regs[ArgDat] = v; } LOCALPROC my_reg_call DecodeSetSrcDst_IndirectB(ui5r v, ui3rr ArgDat) { put_byte(V_regs.regs[ArgDat], v); } LOCALPROC my_reg_call DecodeSetSrcDst_IndirectW(ui5r v, ui3rr ArgDat) { put_word(V_regs.regs[ArgDat], v); } LOCALPROC my_reg_call DecodeSetSrcDst_IndirectL(ui5r v, ui3rr ArgDat) { put_long(V_regs.regs[ArgDat], v); } LOCALPROC my_reg_call DecodeSetSrcDst_APosIncB(ui5r v, ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p; *p = a + 1; put_byte(a, v); } LOCALPROC my_reg_call DecodeSetSrcDst_APosIncW(ui5r v, ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p; *p = a + 2; put_word(a, v); } LOCALPROC my_reg_call DecodeSetSrcDst_APosIncL(ui5r v, ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p; *p = a + 4; put_long(a, v); } LOCALPROC my_reg_call DecodeSetSrcDst_APosInc7B(ui5r v, ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p; *p = a + 2; put_byte(a, v); } LOCALPROC my_reg_call DecodeSetSrcDst_APreDecB(ui5r v, ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p - 1; *p = a; put_byte(a, v); } LOCALPROC my_reg_call DecodeSetSrcDst_APreDecW(ui5r v, ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p - 2; *p = a; put_word(a, v); } LOCALPROC my_reg_call DecodeSetSrcDst_APreDecL(ui5r v, ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p - 4; *p = a; put_long(a, v); } LOCALPROC my_reg_call DecodeSetSrcDst_APreDec7B(ui5r v, ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p - 2; *p = a; put_byte(a, v); } LOCALPROC my_reg_call DecodeSetSrcDst_ADispB(ui5r v, ui3rr ArgDat) { put_byte(V_regs.regs[ArgDat] + nextiSWord(), v); } LOCALPROC my_reg_call DecodeSetSrcDst_ADispW(ui5r v, ui3rr ArgDat) { put_word(V_regs.regs[ArgDat] + nextiSWord(), v); } LOCALPROC my_reg_call DecodeSetSrcDst_ADispL(ui5r v, ui3rr ArgDat) { put_long(V_regs.regs[ArgDat] + nextiSWord(), v); } LOCALPROC my_reg_call DecodeSetSrcDst_AIndexB(ui5r v, ui3rr ArgDat) { put_byte(get_disp_ea(V_regs.regs[ArgDat]), v); } LOCALPROC my_reg_call DecodeSetSrcDst_AIndexW(ui5r v, ui3rr ArgDat) { put_word(get_disp_ea(V_regs.regs[ArgDat]), v); } LOCALPROC my_reg_call DecodeSetSrcDst_AIndexL(ui5r v, ui3rr ArgDat) { put_long(get_disp_ea(V_regs.regs[ArgDat]), v); } LOCALPROC my_reg_call DecodeSetSrcDst_AbsWB(ui5r v, ui3rr ArgDat) { put_byte(DecodeAddr_AbsW(ArgDat), v); } LOCALPROC my_reg_call DecodeSetSrcDst_AbsWW(ui5r v, ui3rr ArgDat) { put_word(DecodeAddr_AbsW(ArgDat), v); } LOCALPROC my_reg_call DecodeSetSrcDst_AbsWL(ui5r v, ui3rr ArgDat) { put_long(DecodeAddr_AbsW(ArgDat), v); } LOCALPROC my_reg_call DecodeSetSrcDst_AbsLB(ui5r v, ui3rr ArgDat) { put_byte(DecodeAddr_AbsL(ArgDat), v); } LOCALPROC my_reg_call DecodeSetSrcDst_AbsLW(ui5r v, ui3rr ArgDat) { put_word(DecodeAddr_AbsL(ArgDat), v); } LOCALPROC my_reg_call DecodeSetSrcDst_AbsLL(ui5r v, ui3rr ArgDat) { put_long(DecodeAddr_AbsL(ArgDat), v); } LOCALPROC my_reg_call DecodeSetSrcDst_PCDispB(ui5r v, ui3rr ArgDat) { put_byte(DecodeAddr_PCDisp(ArgDat), v); } LOCALPROC my_reg_call DecodeSetSrcDst_PCDispW(ui5r v, ui3rr ArgDat) { put_word(DecodeAddr_PCDisp(ArgDat), v); } LOCALPROC my_reg_call DecodeSetSrcDst_PCDispL(ui5r v, ui3rr ArgDat) { put_long(DecodeAddr_PCDisp(ArgDat), v); } LOCALPROC my_reg_call DecodeSetSrcDst_PCIndexB(ui5r v, ui3rr ArgDat) { put_byte(DecodeAddr_PCIndex(ArgDat), v); } LOCALPROC my_reg_call DecodeSetSrcDst_PCIndexW(ui5r v, ui3rr ArgDat) { put_word(DecodeAddr_PCIndex(ArgDat), v); } LOCALPROC my_reg_call DecodeSetSrcDst_PCIndexL(ui5r v, ui3rr ArgDat) { put_long(DecodeAddr_PCIndex(ArgDat), v); } typedef void (my_reg_call *DecodeSetSrcDstP)(ui5r v, ui3rr ArgDat); LOCALVAR const DecodeSetSrcDstP DecodeSetSrcDstDispatch[kNumAMds] = { DecodeSetSrcDst_RegB /* kAMdRegB */, DecodeSetSrcDst_RegW /* kAMdRegW */, DecodeSetSrcDst_RegL /* kAMdRegL */, DecodeSetSrcDst_IndirectB /* kAMdIndirectB */, DecodeSetSrcDst_IndirectW /* kAMdIndirectW */, DecodeSetSrcDst_IndirectL /* kAMdIndirectL*/, DecodeSetSrcDst_APosIncB /* kAMdAPosIncB */, DecodeSetSrcDst_APosIncW /* kAMdAPosIncW */, DecodeSetSrcDst_APosIncL /* kAMdAPosIncL */, DecodeSetSrcDst_APosInc7B /* kAMdAPosInc7B */, DecodeSetSrcDst_APreDecB /* kAMdAPreDecB */, DecodeSetSrcDst_APreDecW /* kAMdAPreDecW */, DecodeSetSrcDst_APreDecL /* kAMdAPreDecL */, DecodeSetSrcDst_APreDec7B /* kAMdAPreDec7B */, DecodeSetSrcDst_ADispB /* kAMdADispB */, DecodeSetSrcDst_ADispW /* kAMdADispW */, DecodeSetSrcDst_ADispL /* kAMdADispL */, DecodeSetSrcDst_AIndexB /* kAMdAIndexB */, DecodeSetSrcDst_AIndexW /* kAMdAIndexW */, DecodeSetSrcDst_AIndexL /* kAMdAIndexL */, DecodeSetSrcDst_AbsWB /* kAMdAbsWB */, DecodeSetSrcDst_AbsWW /* kAMdAbsWW */, DecodeSetSrcDst_AbsWL /* kAMdAbsWL */, DecodeSetSrcDst_AbsLB /* kAMdAbsLB */, DecodeSetSrcDst_AbsLW /* kAMdAbsLW */, DecodeSetSrcDst_AbsLL /* kAMdAbsLL */, DecodeSetSrcDst_PCDispB /* kAMdPCDispB */, DecodeSetSrcDst_PCDispW /* kAMdPCDispW */, DecodeSetSrcDst_PCDispL /* kAMdPCDispL */, DecodeSetSrcDst_PCIndexB /* kAMdPCIndexB */, DecodeSetSrcDst_PCIndexW /* kAMdPCIndexW */, DecodeSetSrcDst_PCIndexL /* kAMdPCIndexL */, (DecodeSetSrcDstP)nullpr /* kAMdImmedB */, (DecodeSetSrcDstP)nullpr /* kAMdImmedW */, (DecodeSetSrcDstP)nullpr /* kAMdImmedL */, (DecodeSetSrcDstP)nullpr /* kAMdDat4 */ }; LOCALINLINEPROC DecodeSetSrcDst(ui5r v, DecArgR *f) { (DecodeSetSrcDstDispatch[f->AMd])(v, f->ArgDat); } LOCALPROC my_reg_call ArgSetDstRegBValue(ui5r v) { ui5r *p = V_regs.ArgAddr.rga; #if LittleEndianUnaligned *(ui3b *)p = v; #else *p = (*p & ~ 0xff) | ((v) & 0xff); #endif } LOCALPROC my_reg_call ArgSetDstRegWValue(ui5r v) { ui5r *p = V_regs.ArgAddr.rga; #if LittleEndianUnaligned *(ui4b *)p = v; #else *p = (*p & ~ 0xffff) | ((v) & 0xffff); #endif } LOCALPROC my_reg_call ArgSetDstRegLValue(ui5r v) { ui5r *p = V_regs.ArgAddr.rga; *p = v; } LOCALPROC my_reg_call ArgSetDstMemBValue(ui5r v) { put_byte(V_regs.ArgAddr.mem, v); } LOCALPROC my_reg_call ArgSetDstMemWValue(ui5r v) { put_word(V_regs.ArgAddr.mem, v); } LOCALPROC my_reg_call ArgSetDstMemLValue(ui5r v) { put_long(V_regs.ArgAddr.mem, v); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_RegB(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; V_regs.ArgAddr.rga = p; V_regs.ArgSetDst = ArgSetDstRegBValue; return ui5r_FromSByte(*p); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_RegW(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; V_regs.ArgAddr.rga = p; V_regs.ArgSetDst = ArgSetDstRegWValue; return ui5r_FromSWord(*p); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_RegL(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; V_regs.ArgAddr.rga = p; V_regs.ArgSetDst = ArgSetDstRegLValue; return ui5r_FromSLong(*p); } LOCALFUNC ui5r my_reg_call getarg_byte(ui5r a) { V_regs.ArgAddr.mem = a; V_regs.ArgSetDst = ArgSetDstMemBValue; return get_byte(a); } LOCALFUNC ui5r my_reg_call getarg_word(ui5r a) { V_regs.ArgAddr.mem = a; V_regs.ArgSetDst = ArgSetDstMemWValue; return get_word(a); } LOCALFUNC ui5r my_reg_call getarg_long(ui5r a) { V_regs.ArgAddr.mem = a; V_regs.ArgSetDst = ArgSetDstMemLValue; return get_long(a); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_IndirectB(ui3rr ArgDat) { return getarg_byte(V_regs.regs[ArgDat]); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_IndirectW(ui3rr ArgDat) { return getarg_word(V_regs.regs[ArgDat]); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_IndirectL(ui3rr ArgDat) { return getarg_long(V_regs.regs[ArgDat]); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_APosIncB(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p; *p = a + 1; return getarg_byte(a); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_APosIncW(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p; *p = a + 2; return getarg_word(a); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_APosIncL(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p; *p = a + 4; return getarg_long(a); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_APosInc7B(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p; *p = a + 2; return getarg_byte(a); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_APreDecB(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p - 1; *p = a; return getarg_byte(a); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_APreDecW(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p - 2; *p = a; return getarg_word(a); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_APreDecL(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p - 4; *p = a; return getarg_long(a); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_APreDec7B(ui3rr ArgDat) { ui5r *p = &V_regs.regs[ArgDat]; ui5r a = *p - 2; *p = a; return getarg_byte(a); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_ADispB(ui3rr ArgDat) { return getarg_byte(V_regs.regs[ArgDat] + nextiSWord()); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_ADispW(ui3rr ArgDat) { return getarg_word(V_regs.regs[ArgDat] + nextiSWord()); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_ADispL(ui3rr ArgDat) { return getarg_long(V_regs.regs[ArgDat] + nextiSWord()); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_AIndexB(ui3rr ArgDat) { return getarg_byte(get_disp_ea(V_regs.regs[ArgDat])); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_AIndexW(ui3rr ArgDat) { return getarg_word(get_disp_ea(V_regs.regs[ArgDat])); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_AIndexL(ui3rr ArgDat) { return getarg_long(get_disp_ea(V_regs.regs[ArgDat])); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_AbsWB(ui3rr ArgDat) { return getarg_byte(DecodeAddr_AbsW(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_AbsWW(ui3rr ArgDat) { return getarg_word(DecodeAddr_AbsW(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_AbsWL(ui3rr ArgDat) { return getarg_long(DecodeAddr_AbsW(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_AbsLB(ui3rr ArgDat) { return getarg_byte(DecodeAddr_AbsL(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_AbsLW(ui3rr ArgDat) { return getarg_word(DecodeAddr_AbsL(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_AbsLL(ui3rr ArgDat) { return getarg_long(DecodeAddr_AbsL(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_PCDispB(ui3rr ArgDat) { return getarg_byte(DecodeAddr_PCDisp(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_PCDispW(ui3rr ArgDat) { return getarg_word(DecodeAddr_PCDisp(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_PCDispL(ui3rr ArgDat) { return getarg_long(DecodeAddr_PCDisp(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_PCIndexB(ui3rr ArgDat) { return getarg_byte(DecodeAddr_PCIndex(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_PCIndexW(ui3rr ArgDat) { return getarg_word(DecodeAddr_PCIndex(ArgDat)); } LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_PCIndexL(ui3rr ArgDat) { return getarg_long(DecodeAddr_PCIndex(ArgDat)); } typedef ui5r (my_reg_call *DecodeGetSetSrcDstP)(ui3rr ArgDat); LOCALVAR const DecodeGetSetSrcDstP DecodeGetSetSrcDstDispatch[kNumAMds] = { DecodeGetSetSrcDst_RegB /* kAMdRegB */, DecodeGetSetSrcDst_RegW /* kAMdRegW */, DecodeGetSetSrcDst_RegL /* kAMdRegL */, DecodeGetSetSrcDst_IndirectB /* kAMdIndirectB */, DecodeGetSetSrcDst_IndirectW /* kAMdIndirectW */, DecodeGetSetSrcDst_IndirectL /* kAMdIndirectL*/, DecodeGetSetSrcDst_APosIncB /* kAMdAPosIncB */, DecodeGetSetSrcDst_APosIncW /* kAMdAPosIncW */, DecodeGetSetSrcDst_APosIncL /* kAMdAPosIncL */, DecodeGetSetSrcDst_APosInc7B /* kAMdAPosInc7B */, DecodeGetSetSrcDst_APreDecB /* kAMdAPreDecB */, DecodeGetSetSrcDst_APreDecW /* kAMdAPreDecW */, DecodeGetSetSrcDst_APreDecL /* kAMdAPreDecL */, DecodeGetSetSrcDst_APreDec7B /* kAMdAPreDec7B */, DecodeGetSetSrcDst_ADispB /* kAMdADispB */, DecodeGetSetSrcDst_ADispW /* kAMdADispW */, DecodeGetSetSrcDst_ADispL /* kAMdADispL */, DecodeGetSetSrcDst_AIndexB /* kAMdAIndexB */, DecodeGetSetSrcDst_AIndexW /* kAMdAIndexW */, DecodeGetSetSrcDst_AIndexL /* kAMdAIndexL */, DecodeGetSetSrcDst_AbsWB /* kAMdAbsWB */, DecodeGetSetSrcDst_AbsWW /* kAMdAbsWW */, DecodeGetSetSrcDst_AbsWL /* kAMdAbsWL */, DecodeGetSetSrcDst_AbsLB /* kAMdAbsLB */, DecodeGetSetSrcDst_AbsLW /* kAMdAbsLW */, DecodeGetSetSrcDst_AbsLL /* kAMdAbsLL */, DecodeGetSetSrcDst_PCDispB /* kAMdPCDispB */, DecodeGetSetSrcDst_PCDispW /* kAMdPCDispW */, DecodeGetSetSrcDst_PCDispL /* kAMdPCDispL */, DecodeGetSetSrcDst_PCIndexB /* kAMdPCIndexB */, DecodeGetSetSrcDst_PCIndexW /* kAMdPCIndexW */, DecodeGetSetSrcDst_PCIndexL /* kAMdPCIndexL */, (DecodeGetSetSrcDstP)nullpr /* kAMdImmedB */, (DecodeGetSetSrcDstP)nullpr /* kAMdImmedW */, (DecodeGetSetSrcDstP)nullpr /* kAMdImmedL */, (DecodeGetSetSrcDstP)nullpr /* kAMdDat4 */ }; LOCALINLINEFUNC ui5r DecodeGetSetSrcDst(DecArgR *f) { return (DecodeGetSetSrcDstDispatch[f->AMd])(f->ArgDat); } LOCALINLINEFUNC ui5r DecodeDst(void) { return DecodeAddrSrcDst(&V_regs.CurDecOpY.v[1]); } LOCALINLINEFUNC ui5r DecodeGetSetDstValue(void) { return DecodeGetSetSrcDst(&V_regs.CurDecOpY.v[1]); } LOCALINLINEPROC ArgSetDstValue(ui5r v) { V_regs.ArgSetDst(v); } LOCALINLINEPROC DecodeSetDstValue(ui5r v) { DecodeSetSrcDst(v, &V_regs.CurDecOpY.v[1]); } LOCALINLINEFUNC ui5r DecodeGetSrcValue(void) { return DecodeGetSrcDst(&V_regs.CurDecOpY.v[0]); } LOCALINLINEFUNC ui5r DecodeGetDstValue(void) { return DecodeGetSrcDst(&V_regs.CurDecOpY.v[1]); } LOCALINLINEFUNC ui5r DecodeGetSrcSetDstValue(void) { V_regs.SrcVal = DecodeGetSrcValue(); return DecodeGetSetDstValue(); } LOCALINLINEFUNC ui5r DecodeGetSrcGetDstValue(void) { V_regs.SrcVal = DecodeGetSrcValue(); return DecodeGetDstValue(); } typedef void (*cond_actP)(void); LOCALPROC my_reg_call cctrue_T(cond_actP t_act, cond_actP f_act) { UnusedParam(f_act); t_act(); } LOCALPROC my_reg_call cctrue_F(cond_actP t_act, cond_actP f_act) { UnusedParam(t_act); f_act(); } LOCALPROC my_reg_call cctrue_HI(cond_actP t_act, cond_actP f_act) { if (0 == (CFLG | ZFLG)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_LS(cond_actP t_act, cond_actP f_act) { if (0 != (CFLG | ZFLG)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CC(cond_actP t_act, cond_actP f_act) { if (0 == (CFLG)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CS(cond_actP t_act, cond_actP f_act) { if (0 != (CFLG)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_NE(cond_actP t_act, cond_actP f_act) { if (0 == (ZFLG)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_EQ(cond_actP t_act, cond_actP f_act) { if (0 != (ZFLG)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_VC(cond_actP t_act, cond_actP f_act) { if (0 == (VFLG)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_VS(cond_actP t_act, cond_actP f_act) { if (0 != (VFLG)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_PL(cond_actP t_act, cond_actP f_act) { if (0 == (NFLG)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_MI(cond_actP t_act, cond_actP f_act) { if (0 != (NFLG)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_GE(cond_actP t_act, cond_actP f_act) { if (0 == (NFLG ^ VFLG)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_LT(cond_actP t_act, cond_actP f_act) { if (0 != (NFLG ^ VFLG)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_GT(cond_actP t_act, cond_actP f_act) { if (0 == (ZFLG | (NFLG ^ VFLG))) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_LE(cond_actP t_act, cond_actP f_act) { if (0 != (ZFLG | (NFLG ^ VFLG))) { t_act(); } else { f_act(); } } #if Have_ASR #define Ui5rASR(x, s) ((ui5r)(((si5r)(x)) >> (s))) #else LOCALFUNC ui5r Ui5rASR(ui5r x, ui5r s) { ui5r v; if (ui5r_MSBisSet(x)) { v = ~ ((~ x) >> s); } else { v = x >> s; } return v; } #endif #if UseLazyCC LOCALPROC my_reg_call cctrue_TstL_HI(cond_actP t_act, cond_actP f_act) { if (((ui5b)V_regs.LazyFlagArgDst) > ((ui5b)0)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_TstL_LS(cond_actP t_act, cond_actP f_act) { if (((ui5b)V_regs.LazyFlagArgDst) <= ((ui5b)0)) { t_act(); } else { f_act(); } } #if 0 /* always true */ LOCALPROC my_reg_call cctrue_TstL_CC(cond_actP t_act, cond_actP f_act) { if (((ui5b)V_regs.LazyFlagArgDst) >= ((ui5b)0)) { t_act(); } else { f_act(); } } #endif #if 0 /* always false */ LOCALPROC my_reg_call cctrue_TstL_CS(cond_actP t_act, cond_actP f_act) { if (((ui5b)V_regs.LazyFlagArgDst) < ((ui5b)0)) { t_act(); } else { f_act(); } } #endif LOCALPROC my_reg_call cctrue_TstL_NE(cond_actP t_act, cond_actP f_act) { if (V_regs.LazyFlagArgDst != 0) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_TstL_EQ(cond_actP t_act, cond_actP f_act) { if (V_regs.LazyFlagArgDst == 0) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_TstL_PL(cond_actP t_act, cond_actP f_act) { if (((si5b)(V_regs.LazyFlagArgDst)) >= 0) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_TstL_MI(cond_actP t_act, cond_actP f_act) { if (((si5b)(V_regs.LazyFlagArgDst)) < 0) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_TstL_GE(cond_actP t_act, cond_actP f_act) { if (((si5b)V_regs.LazyFlagArgDst) >= ((si5b)0)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_TstL_LT(cond_actP t_act, cond_actP f_act) { if (((si5b)V_regs.LazyFlagArgDst) < ((si5b)0)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_TstL_GT(cond_actP t_act, cond_actP f_act) { if (((si5b)V_regs.LazyFlagArgDst) > ((si5b)0)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_TstL_LE(cond_actP t_act, cond_actP f_act) { if (((si5b)V_regs.LazyFlagArgDst) <= ((si5b)0)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpB_HI(cond_actP t_act, cond_actP f_act) { if (((ui3b)V_regs.LazyFlagArgDst) > ((ui3b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpB_LS(cond_actP t_act, cond_actP f_act) { if (((ui3b)V_regs.LazyFlagArgDst) <= ((ui3b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpB_CC(cond_actP t_act, cond_actP f_act) { if (((ui3b)V_regs.LazyFlagArgDst) >= ((ui3b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpB_CS(cond_actP t_act, cond_actP f_act) { if (((ui3b)V_regs.LazyFlagArgDst) < ((ui3b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpB_NE(cond_actP t_act, cond_actP f_act) { if (((ui3b)V_regs.LazyFlagArgDst) != ((ui3b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpB_EQ(cond_actP t_act, cond_actP f_act) { if (((ui3b)V_regs.LazyFlagArgDst) == ((ui3b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpB_PL(cond_actP t_act, cond_actP f_act) { if (((si3b)(V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc)) >= 0) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpB_MI(cond_actP t_act, cond_actP f_act) { if (((si3b)(V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc)) < 0) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpB_GE(cond_actP t_act, cond_actP f_act) { if (((si3b)V_regs.LazyFlagArgDst) >= ((si3b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpB_LT(cond_actP t_act, cond_actP f_act) { if (((si3b)V_regs.LazyFlagArgDst) < ((si3b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpB_GT(cond_actP t_act, cond_actP f_act) { if (((si3b)V_regs.LazyFlagArgDst) > ((si3b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpB_LE(cond_actP t_act, cond_actP f_act) { if (((si3b)V_regs.LazyFlagArgDst) <= ((si3b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpW_HI(cond_actP t_act, cond_actP f_act) { if (((ui4b)V_regs.LazyFlagArgDst) > ((ui4b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpW_LS(cond_actP t_act, cond_actP f_act) { if (((ui4b)V_regs.LazyFlagArgDst) <= ((ui4b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpW_CC(cond_actP t_act, cond_actP f_act) { if (((ui4b)V_regs.LazyFlagArgDst) >= ((ui4b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpW_CS(cond_actP t_act, cond_actP f_act) { if (((ui4b)V_regs.LazyFlagArgDst) < ((ui4b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpW_NE(cond_actP t_act, cond_actP f_act) { if (((ui4b)V_regs.LazyFlagArgDst) != ((ui4b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpW_EQ(cond_actP t_act, cond_actP f_act) { if (((ui4b)V_regs.LazyFlagArgDst) == ((ui4b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpW_PL(cond_actP t_act, cond_actP f_act) { if (((si4b)(V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc)) >= 0) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpW_MI(cond_actP t_act, cond_actP f_act) { if (((si4b)(V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc)) < 0) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpW_GE(cond_actP t_act, cond_actP f_act) { if (((si4b)V_regs.LazyFlagArgDst) >= ((si4b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpW_LT(cond_actP t_act, cond_actP f_act) { if (((si4b)V_regs.LazyFlagArgDst) < ((si4b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpW_GT(cond_actP t_act, cond_actP f_act) { if (((si4b)V_regs.LazyFlagArgDst) > ((si4b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpW_LE(cond_actP t_act, cond_actP f_act) { if (((si4b)V_regs.LazyFlagArgDst) <= ((si4b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpL_HI(cond_actP t_act, cond_actP f_act) { if (((ui5b)V_regs.LazyFlagArgDst) > ((ui5b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpL_LS(cond_actP t_act, cond_actP f_act) { if (((ui5b)V_regs.LazyFlagArgDst) <= ((ui5b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpL_CC(cond_actP t_act, cond_actP f_act) { if (((ui5b)V_regs.LazyFlagArgDst) >= ((ui5b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpL_CS(cond_actP t_act, cond_actP f_act) { if (((ui5b)V_regs.LazyFlagArgDst) < ((ui5b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpL_NE(cond_actP t_act, cond_actP f_act) { if (V_regs.LazyFlagArgDst != V_regs.LazyFlagArgSrc) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpL_EQ(cond_actP t_act, cond_actP f_act) { if (V_regs.LazyFlagArgDst == V_regs.LazyFlagArgSrc) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpL_PL(cond_actP t_act, cond_actP f_act) { if ((((si5b)(V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc)) >= 0)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpL_MI(cond_actP t_act, cond_actP f_act) { if ((((si5b)(V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc)) < 0)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpL_GE(cond_actP t_act, cond_actP f_act) { if (((si5b)V_regs.LazyFlagArgDst) >= ((si5b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpL_LT(cond_actP t_act, cond_actP f_act) { if (((si5b)V_regs.LazyFlagArgDst) < ((si5b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpL_GT(cond_actP t_act, cond_actP f_act) { if (((si5b)V_regs.LazyFlagArgDst) > ((si5b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_CmpL_LE(cond_actP t_act, cond_actP f_act) { if (((si5b)V_regs.LazyFlagArgDst) <= ((si5b)V_regs.LazyFlagArgSrc)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_Asr_CC(cond_actP t_act, cond_actP f_act) { if (0 == ((V_regs.LazyFlagArgDst >> (V_regs.LazyFlagArgSrc - 1)) & 1)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_Asr_CS(cond_actP t_act, cond_actP f_act) { if (0 != ((V_regs.LazyFlagArgDst >> (V_regs.LazyFlagArgSrc - 1)) & 1)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_AslB_CC(cond_actP t_act, cond_actP f_act) { if (0 == ((V_regs.LazyFlagArgDst >> (8 - V_regs.LazyFlagArgSrc)) & 1)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_AslB_CS(cond_actP t_act, cond_actP f_act) { if (0 != ((V_regs.LazyFlagArgDst >> (8 - V_regs.LazyFlagArgSrc)) & 1)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_AslB_VC(cond_actP t_act, cond_actP f_act) { ui5r cnt = V_regs.LazyFlagArgSrc; ui5r dst = ui5r_FromSByte(V_regs.LazyFlagArgDst << cnt); if (Ui5rASR(dst, cnt) == V_regs.LazyFlagArgDst) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_AslB_VS(cond_actP t_act, cond_actP f_act) { ui5r cnt = V_regs.LazyFlagArgSrc; ui5r dst = ui5r_FromSByte(V_regs.LazyFlagArgDst << cnt); if (Ui5rASR(dst, cnt) != V_regs.LazyFlagArgDst) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_AslW_CC(cond_actP t_act, cond_actP f_act) { if (0 == ((V_regs.LazyFlagArgDst >> (16 - V_regs.LazyFlagArgSrc)) & 1)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_AslW_CS(cond_actP t_act, cond_actP f_act) { if (0 != ((V_regs.LazyFlagArgDst >> (16 - V_regs.LazyFlagArgSrc)) & 1)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_AslW_VC(cond_actP t_act, cond_actP f_act) { ui5r cnt = V_regs.LazyFlagArgSrc; ui5r dst = ui5r_FromSWord(V_regs.LazyFlagArgDst << cnt); if (Ui5rASR(dst, cnt) == V_regs.LazyFlagArgDst) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_AslW_VS(cond_actP t_act, cond_actP f_act) { ui5r cnt = V_regs.LazyFlagArgSrc; ui5r dst = ui5r_FromSWord(V_regs.LazyFlagArgDst << cnt); if (Ui5rASR(dst, cnt) != V_regs.LazyFlagArgDst) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_AslL_CC(cond_actP t_act, cond_actP f_act) { if (0 == ((V_regs.LazyFlagArgDst >> (32 - V_regs.LazyFlagArgSrc)) & 1)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_AslL_CS(cond_actP t_act, cond_actP f_act) { if (0 != ((V_regs.LazyFlagArgDst >> (32 - V_regs.LazyFlagArgSrc)) & 1)) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_AslL_VC(cond_actP t_act, cond_actP f_act) { ui5r cnt = V_regs.LazyFlagArgSrc; ui5r dst = ui5r_FromSLong(V_regs.LazyFlagArgDst << cnt); if (Ui5rASR(dst, cnt) == V_regs.LazyFlagArgDst) { t_act(); } else { f_act(); } } LOCALPROC my_reg_call cctrue_AslL_VS(cond_actP t_act, cond_actP f_act) { ui5r cnt = V_regs.LazyFlagArgSrc; ui5r dst = ui5r_FromSLong(V_regs.LazyFlagArgDst << cnt); if (Ui5rASR(dst, cnt) != V_regs.LazyFlagArgDst) { t_act(); } else { f_act(); } } FORWARDPROC my_reg_call cctrue_Dflt(cond_actP t_act, cond_actP f_act); #endif /* UseLazyCC */ #if UseLazyCC #define CCdispSz (16 * kNumLazyFlagsKinds) #else #define CCdispSz kNumLazyFlagsKinds #endif typedef void (my_reg_call *cctrueP)(cond_actP t_act, cond_actP f_act); LOCALVAR const cctrueP cctrueDispatch[CCdispSz + 1] = { cctrue_T /* kLazyFlagsDefault T */, cctrue_F /* kLazyFlagsDefault F */, cctrue_HI /* kLazyFlagsDefault HI */, cctrue_LS /* kLazyFlagsDefault LS */, cctrue_CC /* kLazyFlagsDefault CC */, cctrue_CS /* kLazyFlagsDefault CS */, cctrue_NE /* kLazyFlagsDefault NE */, cctrue_EQ /* kLazyFlagsDefault EQ */, cctrue_VC /* kLazyFlagsDefault VC */, cctrue_VS /* kLazyFlagsDefault VS */, cctrue_PL /* kLazyFlagsDefault PL */, cctrue_MI /* kLazyFlagsDefault MI */, cctrue_GE /* kLazyFlagsDefault GE */, cctrue_LT /* kLazyFlagsDefault LT */, cctrue_GT /* kLazyFlagsDefault GT */, cctrue_LE /* kLazyFlagsDefault LE */, #if UseLazyCC cctrue_T /* kLazyFlagsTstB T */, cctrue_F /* kLazyFlagsTstB F */, cctrue_Dflt /* kLazyFlagsTstB HI */, cctrue_Dflt /* kLazyFlagsTstB LS */, cctrue_Dflt /* kLazyFlagsTstB CC */, cctrue_Dflt /* kLazyFlagsTstB CS */, cctrue_Dflt /* kLazyFlagsTstB NE */, cctrue_Dflt /* kLazyFlagsTstB EQ */, cctrue_Dflt /* kLazyFlagsTstB VC */, cctrue_Dflt /* kLazyFlagsTstB VS */, cctrue_Dflt /* kLazyFlagsTstB PL */, cctrue_Dflt /* kLazyFlagsTstB MI */, cctrue_Dflt /* kLazyFlagsTstB GE */, cctrue_Dflt /* kLazyFlagsTstB LT */, cctrue_Dflt /* kLazyFlagsTstB GT */, cctrue_Dflt /* kLazyFlagsTstB LE */, cctrue_T /* kLazyFlagsTstW T */, cctrue_F /* kLazyFlagsTstW F */, cctrue_Dflt /* kLazyFlagsTstW HI */, cctrue_Dflt /* kLazyFlagsTstW LS */, cctrue_Dflt /* kLazyFlagsTstW CC */, cctrue_Dflt /* kLazyFlagsTstW CS */, cctrue_Dflt /* kLazyFlagsTstW NE */, cctrue_Dflt /* kLazyFlagsTstW EQ */, cctrue_Dflt /* kLazyFlagsTstW VC */, cctrue_Dflt /* kLazyFlagsTstW VS */, cctrue_Dflt /* kLazyFlagsTstW PL */, cctrue_Dflt /* kLazyFlagsTstW MI */, cctrue_Dflt /* kLazyFlagsTstW GE */, cctrue_Dflt /* kLazyFlagsTstW LT */, cctrue_Dflt /* kLazyFlagsTstW GT */, cctrue_Dflt /* kLazyFlagsTstW LE */, cctrue_T /* kLazyFlagsTstL T */, cctrue_F /* kLazyFlagsTstL F */, cctrue_TstL_HI /* kLazyFlagsTstL HI */, cctrue_TstL_LS /* kLazyFlagsTstL LS */, cctrue_T /* cctrue_TstL_CC */ /* kLazyFlagsTstL CC */, cctrue_F /* cctrue_TstL_CS */ /* kLazyFlagsTstL CS */, cctrue_TstL_NE /* kLazyFlagsTstL NE */, cctrue_TstL_EQ /* kLazyFlagsTstL EQ */, cctrue_T /* cctrue_Dflt */ /* kLazyFlagsTstL VC */, cctrue_F /* cctrue_Dflt */ /* kLazyFlagsTstL VS */, cctrue_TstL_PL /* kLazyFlagsTstL PL */, cctrue_TstL_MI /* kLazyFlagsTstL MI */, cctrue_TstL_GE /* kLazyFlagsTstL GE */, cctrue_TstL_LT /* kLazyFlagsTstL LT */, cctrue_TstL_GT /* kLazyFlagsTstL GT */, cctrue_TstL_LE /* kLazyFlagsTstL LE */, cctrue_T /* kLazyFlagsCmpB T */, cctrue_F /* kLazyFlagsCmpB F */, cctrue_CmpB_HI /* kLazyFlagsCmpB HI */, cctrue_CmpB_LS /* kLazyFlagsCmpB LS */, cctrue_CmpB_CC /* kLazyFlagsCmpB CC */, cctrue_CmpB_CS /* kLazyFlagsCmpB CS */, cctrue_CmpB_NE /* kLazyFlagsCmpB NE */, cctrue_CmpB_EQ /* kLazyFlagsCmpB EQ */, cctrue_Dflt /* kLazyFlagsCmpB VC */, cctrue_Dflt /* kLazyFlagsCmpB VS */, cctrue_CmpB_PL /* kLazyFlagsCmpB PL */, cctrue_CmpB_MI /* kLazyFlagsCmpB MI */, cctrue_CmpB_GE /* kLazyFlagsCmpB GE */, cctrue_CmpB_LT /* kLazyFlagsCmpB LT */, cctrue_CmpB_GT /* kLazyFlagsCmpB GT */, cctrue_CmpB_LE /* kLazyFlagsCmpB LE */, cctrue_T /* kLazyFlagsCmpW T */, cctrue_F /* kLazyFlagsCmpW F */, cctrue_CmpW_HI /* kLazyFlagsCmpW HI */, cctrue_CmpW_LS /* kLazyFlagsCmpW LS */, cctrue_CmpW_CC /* kLazyFlagsCmpW CC */, cctrue_CmpW_CS /* kLazyFlagsCmpW CS */, cctrue_CmpW_NE /* kLazyFlagsCmpW NE */, cctrue_CmpW_EQ /* kLazyFlagsCmpW EQ */, cctrue_Dflt /* kLazyFlagsCmpW VC */, cctrue_Dflt /* kLazyFlagsCmpW VS */, cctrue_CmpW_PL /* kLazyFlagsCmpW PL */, cctrue_CmpW_MI /* kLazyFlagsCmpW MI */, cctrue_CmpW_GE /* kLazyFlagsCmpW GE */, cctrue_CmpW_LT /* kLazyFlagsCmpW LT */, cctrue_CmpW_GT /* kLazyFlagsCmpW GT */, cctrue_CmpW_LE /* kLazyFlagsCmpW LE */, cctrue_T /* kLazyFlagsCmpL T */, cctrue_F /* kLazyFlagsCmpL F */, cctrue_CmpL_HI /* kLazyFlagsCmpL HI */, cctrue_CmpL_LS /* kLazyFlagsCmpL LS */, cctrue_CmpL_CC /* kLazyFlagsCmpL CC */, cctrue_CmpL_CS /* kLazyFlagsCmpL CS */, cctrue_CmpL_NE /* kLazyFlagsCmpL NE */, cctrue_CmpL_EQ /* kLazyFlagsCmpL EQ */, cctrue_Dflt /* kLazyFlagsCmpL VC */, cctrue_Dflt /* kLazyFlagsCmpL VS */, cctrue_CmpL_PL /* kLazyFlagsCmpL PL */, cctrue_CmpL_MI /* kLazyFlagsCmpL MI */, cctrue_CmpL_GE /* kLazyFlagsCmpL GE */, cctrue_CmpL_LT /* kLazyFlagsCmpL LT */, cctrue_CmpL_GT /* kLazyFlagsCmpL GT */, cctrue_CmpL_LE /* kLazyFlagsCmpL LE */, cctrue_T /* kLazyFlagsSubB T */, cctrue_F /* kLazyFlagsSubB F */, cctrue_CmpB_HI /* kLazyFlagsSubB HI */, cctrue_CmpB_LS /* kLazyFlagsSubB LS */, cctrue_CmpB_CC /* kLazyFlagsSubB CC */, cctrue_CmpB_CS /* kLazyFlagsSubB CS */, cctrue_CmpB_NE /* kLazyFlagsSubB NE */, cctrue_CmpB_EQ /* kLazyFlagsSubB EQ */, cctrue_Dflt /* kLazyFlagsSubB VC */, cctrue_Dflt /* kLazyFlagsSubB VS */, cctrue_CmpB_PL /* kLazyFlagsSubB PL */, cctrue_CmpB_MI /* kLazyFlagsSubB MI */, cctrue_CmpB_GE /* kLazyFlagsSubB GE */, cctrue_CmpB_LT /* kLazyFlagsSubB LT */, cctrue_CmpB_GT /* kLazyFlagsSubB GT */, cctrue_CmpB_LE /* kLazyFlagsSubB LE */, cctrue_T /* kLazyFlagsSubW T */, cctrue_F /* kLazyFlagsSubW F */, cctrue_CmpW_HI /* kLazyFlagsSubW HI */, cctrue_CmpW_LS /* kLazyFlagsSubW LS */, cctrue_CmpW_CC /* kLazyFlagsSubW CC */, cctrue_CmpW_CS /* kLazyFlagsSubW CS */, cctrue_CmpW_NE /* kLazyFlagsSubW NE */, cctrue_CmpW_EQ /* kLazyFlagsSubW EQ */, cctrue_Dflt /* kLazyFlagsSubW VC */, cctrue_Dflt /* kLazyFlagsSubW VS */, cctrue_CmpW_PL /* kLazyFlagsSubW PL */, cctrue_CmpW_MI /* kLazyFlagsSubW MI */, cctrue_CmpW_GE /* kLazyFlagsSubW GE */, cctrue_CmpW_LT /* kLazyFlagsSubW LT */, cctrue_CmpW_GT /* kLazyFlagsSubW GT */, cctrue_CmpW_LE /* kLazyFlagsSubW LE */, cctrue_T /* kLazyFlagsSubL T */, cctrue_F /* kLazyFlagsSubL F */, cctrue_CmpL_HI /* kLazyFlagsSubL HI */, cctrue_CmpL_LS /* kLazyFlagsSubL LS */, cctrue_CmpL_CC /* kLazyFlagsSubL CC */, cctrue_CmpL_CS /* kLazyFlagsSubL CS */, cctrue_CmpL_NE /* kLazyFlagsSubL NE */, cctrue_CmpL_EQ /* kLazyFlagsSubL EQ */, cctrue_Dflt /* kLazyFlagsSubL VC */, cctrue_Dflt /* kLazyFlagsSubL VS */, cctrue_CmpL_PL /* kLazyFlagsSubL PL */, cctrue_CmpL_MI /* kLazyFlagsSubL MI */, cctrue_CmpL_GE /* kLazyFlagsSubL GE */, cctrue_CmpL_LT /* kLazyFlagsSubL LT */, cctrue_CmpL_GT /* kLazyFlagsSubL GT */, cctrue_CmpL_LE /* kLazyFlagsSubL LE */, cctrue_T /* kLazyFlagsAddB T */, cctrue_F /* kLazyFlagsAddB F */, cctrue_Dflt /* kLazyFlagsAddB HI */, cctrue_Dflt /* kLazyFlagsAddB LS */, cctrue_Dflt /* kLazyFlagsAddB CC */, cctrue_Dflt /* kLazyFlagsAddB CS */, cctrue_Dflt /* kLazyFlagsAddB NE */, cctrue_Dflt /* kLazyFlagsAddB EQ */, cctrue_Dflt /* kLazyFlagsAddB VC */, cctrue_Dflt /* kLazyFlagsAddB VS */, cctrue_Dflt /* kLazyFlagsAddB PL */, cctrue_Dflt /* kLazyFlagsAddB MI */, cctrue_Dflt /* kLazyFlagsAddB GE */, cctrue_Dflt /* kLazyFlagsAddB LT */, cctrue_Dflt /* kLazyFlagsAddB GT */, cctrue_Dflt /* kLazyFlagsAddB LE */, cctrue_T /* kLazyFlagsAddW T */, cctrue_F /* kLazyFlagsAddW F */, cctrue_Dflt /* kLazyFlagsAddW HI */, cctrue_Dflt /* kLazyFlagsAddW LS */, cctrue_Dflt /* kLazyFlagsAddW CC */, cctrue_Dflt /* kLazyFlagsAddW CS */, cctrue_Dflt /* kLazyFlagsAddW NE */, cctrue_Dflt /* kLazyFlagsAddW EQ */, cctrue_Dflt /* kLazyFlagsAddW VC */, cctrue_Dflt /* kLazyFlagsAddW VS */, cctrue_Dflt /* kLazyFlagsAddW PL */, cctrue_Dflt /* kLazyFlagsAddW MI */, cctrue_Dflt /* kLazyFlagsAddW GE */, cctrue_Dflt /* kLazyFlagsAddW LT */, cctrue_Dflt /* kLazyFlagsAddW GT */, cctrue_Dflt /* kLazyFlagsAddW LE */, cctrue_T /* kLazyFlagsAddL T */, cctrue_F /* kLazyFlagsAddL F */, cctrue_Dflt /* kLazyFlagsAddL HI */, cctrue_Dflt /* kLazyFlagsAddL LS */, cctrue_Dflt /* kLazyFlagsAddL CC */, cctrue_Dflt /* kLazyFlagsAddL CS */, cctrue_Dflt /* kLazyFlagsAddL NE */, cctrue_Dflt /* kLazyFlagsAddL EQ */, cctrue_Dflt /* kLazyFlagsAddL VC */, cctrue_Dflt /* kLazyFlagsAddL VS */, cctrue_Dflt /* kLazyFlagsAddL PL */, cctrue_Dflt /* kLazyFlagsAddL MI */, cctrue_Dflt /* kLazyFlagsAddL GE */, cctrue_Dflt /* kLazyFlagsAddL LT */, cctrue_Dflt /* kLazyFlagsAddL GT */, cctrue_Dflt /* kLazyFlagsAddL LE */, cctrue_T /* kLazyFlagsNegB T */, cctrue_F /* kLazyFlagsNegB F */, cctrue_Dflt /* kLazyFlagsNegB HI */, cctrue_Dflt /* kLazyFlagsNegB LS */, cctrue_Dflt /* kLazyFlagsNegB CC */, cctrue_Dflt /* kLazyFlagsNegB CS */, cctrue_Dflt /* kLazyFlagsNegB NE */, cctrue_Dflt /* kLazyFlagsNegB EQ */, cctrue_Dflt /* kLazyFlagsNegB VC */, cctrue_Dflt /* kLazyFlagsNegB VS */, cctrue_Dflt /* kLazyFlagsNegB PL */, cctrue_Dflt /* kLazyFlagsNegB MI */, cctrue_Dflt /* kLazyFlagsNegB GE */, cctrue_Dflt /* kLazyFlagsNegB LT */, cctrue_Dflt /* kLazyFlagsNegB GT */, cctrue_Dflt /* kLazyFlagsNegB LE */, cctrue_T /* kLazyFlagsNegW T */, cctrue_F /* kLazyFlagsNegW F */, cctrue_Dflt /* kLazyFlagsNegW HI */, cctrue_Dflt /* kLazyFlagsNegW LS */, cctrue_Dflt /* kLazyFlagsNegW CC */, cctrue_Dflt /* kLazyFlagsNegW CS */, cctrue_Dflt /* kLazyFlagsNegW NE */, cctrue_Dflt /* kLazyFlagsNegW EQ */, cctrue_Dflt /* kLazyFlagsNegW VC */, cctrue_Dflt /* kLazyFlagsNegW VS */, cctrue_Dflt /* kLazyFlagsNegW PL */, cctrue_Dflt /* kLazyFlagsNegW MI */, cctrue_Dflt /* kLazyFlagsNegW GE */, cctrue_Dflt /* kLazyFlagsNegW LT */, cctrue_Dflt /* kLazyFlagsNegW GT */, cctrue_Dflt /* kLazyFlagsNegW LE */, cctrue_T /* kLazyFlagsNegL T */, cctrue_F /* kLazyFlagsNegL F */, cctrue_Dflt /* kLazyFlagsNegL HI */, cctrue_Dflt /* kLazyFlagsNegL LS */, cctrue_Dflt /* kLazyFlagsNegL CC */, cctrue_Dflt /* kLazyFlagsNegL CS */, cctrue_Dflt /* kLazyFlagsNegL NE */, cctrue_Dflt /* kLazyFlagsNegL EQ */, cctrue_Dflt /* kLazyFlagsNegL VC */, cctrue_Dflt /* kLazyFlagsNegL VS */, cctrue_Dflt /* kLazyFlagsNegL PL */, cctrue_Dflt /* kLazyFlagsNegL MI */, cctrue_Dflt /* kLazyFlagsNegL GE */, cctrue_Dflt /* kLazyFlagsNegL LT */, cctrue_Dflt /* kLazyFlagsNegL GT */, cctrue_Dflt /* kLazyFlagsNegL LE */, cctrue_T /* kLazyFlagsAsrB T */, cctrue_F /* kLazyFlagsAsrB F */, cctrue_Dflt /* kLazyFlagsAsrB HI */, cctrue_Dflt /* kLazyFlagsAsrB LS */, cctrue_Asr_CC /* kLazyFlagsAsrB CC */, cctrue_Asr_CS /* kLazyFlagsAsrB CS */, cctrue_Dflt /* kLazyFlagsAsrB NE */, cctrue_Dflt /* kLazyFlagsAsrB EQ */, cctrue_Dflt /* kLazyFlagsAsrB VC */, cctrue_Dflt /* kLazyFlagsAsrB VS */, cctrue_Dflt /* kLazyFlagsAsrB PL */, cctrue_Dflt /* kLazyFlagsAsrB MI */, cctrue_Dflt /* kLazyFlagsAsrB GE */, cctrue_Dflt /* kLazyFlagsAsrB LT */, cctrue_Dflt /* kLazyFlagsAsrB GT */, cctrue_Dflt /* kLazyFlagsAsrB LE */, cctrue_T /* kLazyFlagsAsrW T */, cctrue_F /* kLazyFlagsAsrW F */, cctrue_Dflt /* kLazyFlagsAsrW HI */, cctrue_Dflt /* kLazyFlagsAsrW LS */, cctrue_Asr_CC /* kLazyFlagsAsrW CC */, cctrue_Asr_CS /* kLazyFlagsAsrW CS */, cctrue_Dflt /* kLazyFlagsAsrW NE */, cctrue_Dflt /* kLazyFlagsAsrW EQ */, cctrue_Dflt /* kLazyFlagsAsrW VC */, cctrue_Dflt /* kLazyFlagsAsrW VS */, cctrue_Dflt /* kLazyFlagsAsrW PL */, cctrue_Dflt /* kLazyFlagsAsrW MI */, cctrue_Dflt /* kLazyFlagsAsrW GE */, cctrue_Dflt /* kLazyFlagsAsrW LT */, cctrue_Dflt /* kLazyFlagsAsrW GT */, cctrue_Dflt /* kLazyFlagsAsrW LE */, cctrue_T /* kLazyFlagsAsrL T */, cctrue_F /* kLazyFlagsAsrL F */, cctrue_Dflt /* kLazyFlagsAsrL HI */, cctrue_Dflt /* kLazyFlagsAsrL LS */, cctrue_Asr_CC /* kLazyFlagsAsrL CC */, cctrue_Asr_CS /* kLazyFlagsAsrL CS */, cctrue_Dflt /* kLazyFlagsAsrL NE */, cctrue_Dflt /* kLazyFlagsAsrL EQ */, cctrue_Dflt /* kLazyFlagsAsrL VC */, cctrue_Dflt /* kLazyFlagsAsrL VS */, cctrue_Dflt /* kLazyFlagsAsrL PL */, cctrue_Dflt /* kLazyFlagsAsrL MI */, cctrue_Dflt /* kLazyFlagsAsrL GE */, cctrue_Dflt /* kLazyFlagsAsrL LT */, cctrue_Dflt /* kLazyFlagsAsrL GT */, cctrue_Dflt /* kLazyFlagsAsrL LE */, cctrue_T /* kLazyFlagsAslB T */, cctrue_F /* kLazyFlagsAslB F */, cctrue_Dflt /* kLazyFlagsAslB HI */, cctrue_Dflt /* kLazyFlagsAslB LS */, cctrue_AslB_CC /* kLazyFlagsAslB CC */, cctrue_AslB_CS /* kLazyFlagsAslB CS */, cctrue_Dflt /* kLazyFlagsAslB NE */, cctrue_Dflt /* kLazyFlagsAslB EQ */, cctrue_AslB_VC /* kLazyFlagsAslB VC */, cctrue_AslB_VS /* kLazyFlagsAslB VS */, cctrue_Dflt /* kLazyFlagsAslB PL */, cctrue_Dflt /* kLazyFlagsAslB MI */, cctrue_Dflt /* kLazyFlagsAslB GE */, cctrue_Dflt /* kLazyFlagsAslB LT */, cctrue_Dflt /* kLazyFlagsAslB GT */, cctrue_Dflt /* kLazyFlagsAslB LE */, cctrue_T /* kLazyFlagsAslW T */, cctrue_F /* kLazyFlagsAslW F */, cctrue_Dflt /* kLazyFlagsAslW HI */, cctrue_Dflt /* kLazyFlagsAslW LS */, cctrue_AslW_CC /* kLazyFlagsAslW CC */, cctrue_AslW_CS /* kLazyFlagsAslW CS */, cctrue_Dflt /* kLazyFlagsAslW NE */, cctrue_Dflt /* kLazyFlagsAslW EQ */, cctrue_AslW_VC /* kLazyFlagsAslW VC */, cctrue_AslW_VS /* kLazyFlagsAslW VS */, cctrue_Dflt /* kLazyFlagsAslW PL */, cctrue_Dflt /* kLazyFlagsAslW MI */, cctrue_Dflt /* kLazyFlagsAslW GE */, cctrue_Dflt /* kLazyFlagsAslW LT */, cctrue_Dflt /* kLazyFlagsAslW GT */, cctrue_Dflt /* kLazyFlagsAslW LE */, cctrue_T /* kLazyFlagsAslL T */, cctrue_F /* kLazyFlagsAslL F */, cctrue_Dflt /* kLazyFlagsAslL HI */, cctrue_Dflt /* kLazyFlagsAslL LS */, cctrue_AslL_CC /* kLazyFlagsAslL CC */, cctrue_AslL_CS /* kLazyFlagsAslL CS */, cctrue_Dflt /* kLazyFlagsAslL NE */, cctrue_Dflt /* kLazyFlagsAslL EQ */, cctrue_AslL_VC /* kLazyFlagsAslL VC */, cctrue_AslL_VS /* kLazyFlagsAslL VS */, cctrue_Dflt /* kLazyFlagsAslL PL */, cctrue_Dflt /* kLazyFlagsAslL MI */, cctrue_Dflt /* kLazyFlagsAslL GE */, cctrue_Dflt /* kLazyFlagsAslL LT */, cctrue_Dflt /* kLazyFlagsAslL GT */, cctrue_Dflt /* kLazyFlagsAslL LE */, #if UseLazyZ cctrue_T /* kLazyFlagsZSet T */, cctrue_F /* kLazyFlagsZSet F */, cctrue_Dflt /* kLazyFlagsZSet HI */, cctrue_Dflt /* kLazyFlagsZSet LS */, cctrue_Dflt /* kLazyFlagsZSet CC */, cctrue_Dflt /* kLazyFlagsZSet CS */, cctrue_NE /* kLazyFlagsZSet NE */, cctrue_EQ /* kLazyFlagsZSet EQ */, cctrue_Dflt /* kLazyFlagsZSet VC */, cctrue_Dflt /* kLazyFlagsZSet VS */, cctrue_Dflt /* kLazyFlagsZSet PL */, cctrue_Dflt /* kLazyFlagsZSet MI */, cctrue_Dflt /* kLazyFlagsZSet GE */, cctrue_Dflt /* kLazyFlagsZSet LT */, cctrue_Dflt /* kLazyFlagsZSet GT */, cctrue_Dflt /* kLazyFlagsZSet LE */, #endif #endif /* UseLazyCC */ 0 }; #if UseLazyCC LOCALINLINEPROC cctrue(cond_actP t_act, cond_actP f_act) { (cctrueDispatch[V_regs.LazyFlagKind * 16 + V_regs.CurDecOpY.v[0].ArgDat])(t_act, f_act); } #endif LOCALPROC NeedDefaultLazyXFlagSubB(void) { XFLG = Bool2Bit(((ui3b)V_regs.LazyXFlagArgDst) < ((ui3b)V_regs.LazyXFlagArgSrc)); V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyXFlagSubW(void) { XFLG = Bool2Bit(((ui4b)V_regs.LazyXFlagArgDst) < ((ui4b)V_regs.LazyXFlagArgSrc)); V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyXFlagSubL(void) { XFLG = Bool2Bit(((ui5b)V_regs.LazyXFlagArgDst) < ((ui5b)V_regs.LazyXFlagArgSrc)); V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyXFlagAddB(void) { ui3b src = (ui3b)V_regs.LazyXFlagArgSrc; ui3b dst = (ui3b)V_regs.LazyXFlagArgDst; ui3b result = dst + src; XFLG = Bool2Bit(result < src); V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyXFlagAddW(void) { ui4b src = (ui4b)V_regs.LazyXFlagArgSrc; ui4b dst = (ui4b)V_regs.LazyXFlagArgDst; ui4b result = dst + src; XFLG = Bool2Bit(result < src); V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyXFlagAddL(void) { ui5b src = (ui5b)V_regs.LazyXFlagArgSrc; ui5b dst = (ui5b)V_regs.LazyXFlagArgDst; ui5b result = dst + src; XFLG = Bool2Bit(result < src); V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyXFlagNegB(void) { XFLG = Bool2Bit(((ui3b)0) < ((ui3b)V_regs.LazyXFlagArgDst)); V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyXFlagNegW(void) { XFLG = Bool2Bit(((ui4b)0) < ((ui4b)V_regs.LazyXFlagArgDst)); V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyXFlagNegL(void) { XFLG = Bool2Bit(((ui5b)0) < ((ui5b)V_regs.LazyXFlagArgDst)); V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyXFlagAsr(void) { ui5r cnt = V_regs.LazyFlagArgSrc; ui5r dst = V_regs.LazyFlagArgDst; XFLG = ((dst >> (cnt - 1)) & 1); V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyXFlagAslB(void) { XFLG = (V_regs.LazyFlagArgDst >> (8 - V_regs.LazyFlagArgSrc)) & 1; V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyXFlagAslW(void) { XFLG = (V_regs.LazyFlagArgDst >> (16 - V_regs.LazyFlagArgSrc)) & 1; V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyXFlagAslL(void) { XFLG = (V_regs.LazyFlagArgDst >> (32 - V_regs.LazyFlagArgSrc)) & 1; V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyXFlagDefault(void) { } typedef void (*NeedLazyFlagP)(void); LOCALVAR const NeedLazyFlagP NeedLazyXFlagDispatch[kNumLazyFlagsKinds + 1] = { NeedDefaultLazyXFlagDefault /* kLazyFlagsDefault */, 0 /* kLazyFlagsTstB */, 0 /* kLazyFlagsTstW */, 0 /* kLazyFlagsTstL */, 0 /* kLazyFlagsCmpB */, 0 /* kLazyFlagsCmpW */, 0 /* kLazyFlagsCmpL */, NeedDefaultLazyXFlagSubB /* kLazyFlagsSubB */, NeedDefaultLazyXFlagSubW /* kLazyFlagsSubW */, NeedDefaultLazyXFlagSubL /* kLazyFlagsSubL */, NeedDefaultLazyXFlagAddB /* kLazyFlagsAddB */, NeedDefaultLazyXFlagAddW /* kLazyFlagsAddW */, NeedDefaultLazyXFlagAddL /* kLazyFlagsAddL */, NeedDefaultLazyXFlagNegB /* kLazyFlagsNegB */, NeedDefaultLazyXFlagNegW /* kLazyFlagsNegW */, NeedDefaultLazyXFlagNegL /* kLazyFlagsNegL */, NeedDefaultLazyXFlagAsr /* kLazyFlagsAsrB */, NeedDefaultLazyXFlagAsr /* kLazyFlagsAsrW */, NeedDefaultLazyXFlagAsr /* kLazyFlagsAsrL */, NeedDefaultLazyXFlagAslB /* kLazyFlagsAslB */, NeedDefaultLazyXFlagAslW /* kLazyFlagsAslW */, NeedDefaultLazyXFlagAslL /* kLazyFlagsAslL */, #if UseLazyZ 0 /* kLazyFlagsZSet */, #endif 0 }; LOCALPROC NeedDefaultLazyXFlag(void) { #if ForceFlagsEval if (kLazyFlagsDefault != V_regs.LazyXFlagKind) { ReportAbnormalID(0x0103, "not kLazyFlagsDefault in NeedDefaultLazyXFlag"); } #else (NeedLazyXFlagDispatch[V_regs.LazyXFlagKind])(); #endif } LOCALPROC NeedDefaultLazyFlagsTstL(void) { ui5r dst = V_regs.LazyFlagArgDst; VFLG = CFLG = 0; ZFLG = Bool2Bit(dst == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dst)); V_regs.LazyFlagKind = kLazyFlagsDefault; NeedDefaultLazyXFlag(); } LOCALPROC NeedDefaultLazyFlagsCmpB(void) { ui5r src = V_regs.LazyFlagArgSrc; ui5r dst = V_regs.LazyFlagArgDst; ui5r result0 = dst - src; ui5r result1 = ui5r_FromUByte(dst) - ui5r_FromUByte(src); ui5r result = ui5r_FromSByte(result0); ZFLG = Bool2Bit(result == 0); NFLG = Bool2Bit(ui5r_MSBisSet(result)); VFLG = (((result0 >> 1) ^ result0) >> 7) & 1; CFLG = (result1 >> 8) & 1; V_regs.LazyFlagKind = kLazyFlagsDefault; NeedDefaultLazyXFlag(); } LOCALPROC NeedDefaultLazyFlagsCmpW(void) { ui5r result0 = V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc; ui5r result = ui5r_FromSWord(result0); ZFLG = Bool2Bit(result == 0); NFLG = Bool2Bit(ui5r_MSBisSet(result)); VFLG = (((result0 >> 1) ^ result0) >> 15) & 1; { ui5r result1 = ui5r_FromUWord(V_regs.LazyFlagArgDst) - ui5r_FromUWord(V_regs.LazyFlagArgSrc); CFLG = (result1 >> 16) & 1; } V_regs.LazyFlagKind = kLazyFlagsDefault; NeedDefaultLazyXFlag(); } LOCALPROC NeedDefaultLazyFlagsCmpL(void) { ui5r src = V_regs.LazyFlagArgSrc; ui5r dst = V_regs.LazyFlagArgDst; ui5r result = ui5r_FromSLong(dst - src); ZFLG = Bool2Bit(result == 0); { flagtype flgn = Bool2Bit(ui5r_MSBisSet(result)); flagtype flgs = Bool2Bit(ui5r_MSBisSet(src)); flagtype flgo = Bool2Bit(ui5r_MSBisSet(dst)) ^ 1; flagtype flgsando = flgs & flgo; flagtype flgsoro = flgs | flgo; NFLG = flgn; VFLG = ((flgn | flgsoro) ^ 1) | (flgn & flgsando); CFLG = flgsando | (flgn & flgsoro); } V_regs.LazyFlagKind = kLazyFlagsDefault; NeedDefaultLazyXFlag(); } LOCALPROC NeedDefaultLazyFlagsSubB(void) { ui5r src = V_regs.LazyFlagArgSrc; ui5r dst = V_regs.LazyFlagArgDst; ui5r result0 = dst - src; ui5r result1 = ui5r_FromUByte(dst) - ui5r_FromUByte(src); ui5r result = ui5r_FromSByte(result0); ZFLG = Bool2Bit(result == 0); NFLG = Bool2Bit(ui5r_MSBisSet(result)); VFLG = (((result0 >> 1) ^ result0) >> 7) & 1; CFLG = (result1 >> 8) & 1; XFLG = CFLG; V_regs.LazyFlagKind = kLazyFlagsDefault; V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyFlagsSubW(void) { ui5r result0 = V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc; ui5r result = ui5r_FromSWord(result0); ZFLG = Bool2Bit(result == 0); NFLG = Bool2Bit(ui5r_MSBisSet(result)); VFLG = (((result0 >> 1) ^ result0) >> 15) & 1; { ui5r result1 = ui5r_FromUWord(V_regs.LazyFlagArgDst) - ui5r_FromUWord(V_regs.LazyFlagArgSrc); CFLG = (result1 >> 16) & 1; } XFLG = CFLG; V_regs.LazyFlagKind = kLazyFlagsDefault; V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyFlagsSubL(void) { ui5r src = V_regs.LazyFlagArgSrc; ui5r dst = V_regs.LazyFlagArgDst; ui5r result = ui5r_FromSLong(dst - src); ZFLG = Bool2Bit(result == 0); { flagtype flgn = Bool2Bit(ui5r_MSBisSet(result)); flagtype flgs = Bool2Bit(ui5r_MSBisSet(src)); flagtype flgo = Bool2Bit(ui5r_MSBisSet(dst)) ^ 1; flagtype flgsando = flgs & flgo; flagtype flgsoro = flgs | flgo; NFLG = flgn; VFLG = ((flgn | flgsoro) ^ 1) | (flgn & flgsando); CFLG = flgsando | (flgn & flgsoro); } XFLG = CFLG; V_regs.LazyFlagKind = kLazyFlagsDefault; V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyFlagsAddB(void) { ui5r src = V_regs.LazyFlagArgSrc; ui5r dst = V_regs.LazyFlagArgDst; ui5r result0 = dst + src; ui5r result1 = ui5r_FromUByte(dst) + ui5r_FromUByte(src); ui5r result = ui5r_FromSByte(result0); ZFLG = Bool2Bit(result == 0); NFLG = Bool2Bit(ui5r_MSBisSet(result)); VFLG = (((result0 >> 1) ^ result0) >> 7) & 1; CFLG = (result1 >> 8); XFLG = CFLG; V_regs.LazyFlagKind = kLazyFlagsDefault; V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyFlagsAddW(void) { ui5r src = V_regs.LazyFlagArgSrc; ui5r dst = V_regs.LazyFlagArgDst; ui5r result0 = dst + src; ui5r result1 = ui5r_FromUWord(dst) + ui5r_FromUWord(src); ui5r result = ui5r_FromSWord(result0); ZFLG = Bool2Bit(result == 0); NFLG = Bool2Bit(ui5r_MSBisSet(result)); VFLG = (((result0 >> 1) ^ result0) >> 15) & 1; CFLG = (result1 >> 16); XFLG = CFLG; V_regs.LazyFlagKind = kLazyFlagsDefault; V_regs.LazyXFlagKind = kLazyFlagsDefault; } #if 0 LOCALPROC NeedDefaultLazyFlagsAddCommon(ui5r result) { ZFLG = Bool2Bit(result == 0); { flagtype flgn = Bool2Bit(ui5r_MSBisSet(result)); flagtype flgs = Bool2Bit(ui5r_MSBisSet(V_regs.LazyFlagArgSrc)); flagtype flgo = Bool2Bit(ui5r_MSBisSet(V_regs.LazyFlagArgDst)); flagtype flgsando = flgs & flgo; flagtype flgsoro = flgs | flgo; NFLG = flgn; flgn ^= 1; VFLG = ((flgn | flgsoro) ^ 1) | (flgn & flgsando); CFLG = flgsando | (flgn & flgsoro); } XFLG = CFLG; V_regs.LazyFlagKind = kLazyFlagsDefault; V_regs.LazyXFlagKind = kLazyFlagsDefault; } #endif LOCALPROC NeedDefaultLazyFlagsAddL(void) { #if 1 ui5r src = V_regs.LazyFlagArgSrc; ui5r dst = V_regs.LazyFlagArgDst; ui5r result = ui5r_FromSLong(dst + src); ZFLG = Bool2Bit(result == 0); NFLG = Bool2Bit(ui5r_MSBisSet(result)); { ui5r result1; ui5r result0; ui5r MidCarry = (ui5r_FromUWord(dst) + ui5r_FromUWord(src)) >> 16; dst >>= 16; src >>= 16; result1 = ui5r_FromUWord(dst) + ui5r_FromUWord(src) + MidCarry; CFLG = (result1 >> 16); result0 = ui5r_FromSWord(dst) + ui5r_FromSWord(src) + MidCarry; VFLG = (((result0 >> 1) ^ result0) >> 15) & 1; } XFLG = CFLG; V_regs.LazyFlagKind = kLazyFlagsDefault; V_regs.LazyXFlagKind = kLazyFlagsDefault; #else ui5r result = ui5r_FromSLong(V_regs.LazyFlagArgDst + V_regs.LazyFlagArgSrc); NeedDefaultLazyFlagsAddCommon(result); #endif } LOCALPROC NeedDefaultLazyFlagsNegCommon(ui5r dstvalue, ui5r result) { flagtype flgs = Bool2Bit(ui5r_MSBisSet(dstvalue)); flagtype flgn = Bool2Bit(ui5r_MSBisSet(result)); ZFLG = Bool2Bit(result == 0); NFLG = flgn; VFLG = flgs & flgn; CFLG = flgs | flgn; XFLG = CFLG; V_regs.LazyFlagKind = kLazyFlagsDefault; V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyFlagsNegB(void) { ui5r dstvalue = V_regs.LazyFlagArgDst; ui5r result = ui5r_FromSByte(0 - dstvalue); NeedDefaultLazyFlagsNegCommon(dstvalue, result); } LOCALPROC NeedDefaultLazyFlagsNegW(void) { ui5r dstvalue = V_regs.LazyFlagArgDst; ui5r result = ui5r_FromSWord(0 - dstvalue); NeedDefaultLazyFlagsNegCommon(dstvalue, result); } LOCALPROC NeedDefaultLazyFlagsNegL(void) { ui5r dstvalue = V_regs.LazyFlagArgDst; ui5r result = ui5r_FromSLong(0 - dstvalue); NeedDefaultLazyFlagsNegCommon(dstvalue, result); } LOCALPROC NeedDefaultLazyFlagsAsr(void) { ui5r cnt = V_regs.LazyFlagArgSrc; ui5r dst = V_regs.LazyFlagArgDst; NFLG = Bool2Bit(ui5r_MSBisSet(dst)); VFLG = 0; CFLG = ((dst >> (cnt - 1)) & 1); dst = Ui5rASR(dst, cnt); ZFLG = Bool2Bit(dst == 0); XFLG = CFLG; V_regs.LazyXFlagKind = kLazyFlagsDefault; V_regs.LazyFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyFlagsAslB(void) { ui5r cnt = V_regs.LazyFlagArgSrc; ui5r dst = V_regs.LazyFlagArgDst; ui5r dstvalue0 = dst; ui5r comparevalue; dst = dst << (cnt - 1); dst = ui5r_FromSByte(dst); CFLG = Bool2Bit(ui5r_MSBisSet(dst)); dst = dst << 1; dst = ui5r_FromSByte(dst); comparevalue = Ui5rASR(dst, cnt); VFLG = Bool2Bit(comparevalue != dstvalue0); ZFLG = Bool2Bit(dst == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dst)); XFLG = CFLG; V_regs.LazyFlagKind = kLazyFlagsDefault; V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyFlagsAslW(void) { ui5r cnt = V_regs.LazyFlagArgSrc; ui5r dst = V_regs.LazyFlagArgDst; ui5r dstvalue0 = dst; ui5r comparevalue; dst = dst << (cnt - 1); dst = ui5r_FromSWord(dst); CFLG = Bool2Bit(ui5r_MSBisSet(dst)); dst = dst << 1; dst = ui5r_FromSWord(dst); comparevalue = Ui5rASR(dst, cnt); VFLG = Bool2Bit(comparevalue != dstvalue0); ZFLG = Bool2Bit(dst == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dst)); XFLG = CFLG; V_regs.LazyFlagKind = kLazyFlagsDefault; V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALPROC NeedDefaultLazyFlagsAslL(void) { ui5r cnt = V_regs.LazyFlagArgSrc; ui5r dst = V_regs.LazyFlagArgDst; ui5r dstvalue0 = dst; ui5r comparevalue; dst = dst << (cnt - 1); dst = ui5r_FromSLong(dst); CFLG = Bool2Bit(ui5r_MSBisSet(dst)); dst = dst << 1; dst = ui5r_FromSLong(dst); comparevalue = Ui5rASR(dst, cnt); VFLG = Bool2Bit(comparevalue != dstvalue0); ZFLG = Bool2Bit(dst == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dst)); XFLG = CFLG; V_regs.LazyFlagKind = kLazyFlagsDefault; V_regs.LazyXFlagKind = kLazyFlagsDefault; } #if UseLazyZ FORWARDPROC NeedDefaultLazyFlagsZSet(void); #endif LOCALVAR const NeedLazyFlagP NeedLazyFlagDispatch[kNumLazyFlagsKinds + 1] = { NeedDefaultLazyXFlag /* kLazyFlagsDefault */, 0 /* kLazyFlagsTstB */, 0 /* kLazyFlagsTstW */, NeedDefaultLazyFlagsTstL /* kLazyFlagsTstL */, NeedDefaultLazyFlagsCmpB /* kLazyFlagsCmpB */, NeedDefaultLazyFlagsCmpW /* kLazyFlagsCmpW */, NeedDefaultLazyFlagsCmpL /* kLazyFlagsCmpL */, NeedDefaultLazyFlagsSubB /* kLazyFlagsSubB */, NeedDefaultLazyFlagsSubW /* kLazyFlagsSubW */, NeedDefaultLazyFlagsSubL /* kLazyFlagsSubL */, NeedDefaultLazyFlagsAddB /* kLazyFlagsAddB */, NeedDefaultLazyFlagsAddW /* kLazyFlagsAddW */, NeedDefaultLazyFlagsAddL /* kLazyFlagsAddL */, NeedDefaultLazyFlagsNegB /* kLazyFlagsNegB */, NeedDefaultLazyFlagsNegW /* kLazyFlagsNegW */, NeedDefaultLazyFlagsNegL /* kLazyFlagsNegL */, NeedDefaultLazyFlagsAsr /* kLazyFlagsAsrB */, NeedDefaultLazyFlagsAsr /* kLazyFlagsAsrW */, NeedDefaultLazyFlagsAsr /* kLazyFlagsAsrL */, NeedDefaultLazyFlagsAslB /* kLazyFlagsAslB */, NeedDefaultLazyFlagsAslW /* kLazyFlagsAslW */, NeedDefaultLazyFlagsAslL /* kLazyFlagsAslL */, #if UseLazyZ NeedDefaultLazyFlagsZSet /* kLazyFlagsZSet */, #endif 0 }; LOCALPROC NeedDefaultLazyAllFlags0(void) { (NeedLazyFlagDispatch[V_regs.LazyFlagKind])(); } #if ForceFlagsEval LOCALPROC NeedDefaultLazyAllFlags(void) { if (kLazyFlagsDefault != V_regs.LazyFlagKind) { ReportAbnormalID(0x0104, "not kLazyFlagsDefault in NeedDefaultLazyAllFlags"); #if dbglog_HAVE dbglog_writelnNum("LazyFlagKind", V_regs.LazyFlagKind); #endif } } #else #define NeedDefaultLazyAllFlags NeedDefaultLazyAllFlags0 #endif #if ForceFlagsEval #define HaveSetUpFlags NeedDefaultLazyAllFlags0 #else #define HaveSetUpFlags() #endif #if UseLazyZ LOCALPROC NeedDefaultLazyFlagsZSet(void) { flagtype SaveZFLG = ZFLG; V_regs.LazyFlagKind = V_regs.LazyFlagZSavedKind; NeedDefaultLazyAllFlags(); ZFLG = SaveZFLG; } #endif #if UseLazyCC LOCALPROC my_reg_call cctrue_Dflt(cond_actP t_act, cond_actP f_act) { NeedDefaultLazyAllFlags(); cctrue(t_act, f_act); } #endif #if ! UseLazyCC LOCALINLINEPROC cctrue(cond_actP t_act, cond_actP f_act) { NeedDefaultLazyAllFlags(); (cctrueDispatch[V_regs.CurDecOpY.v[0].ArgDat])(t_act, f_act); } #endif #define LOCALIPROC LOCALPROC /* LOCALPROCUSEDONCE */ LOCALIPROC DoCodeCmpB(void) { ui5r dstvalue = DecodeGetSrcGetDstValue(); V_regs.LazyFlagKind = kLazyFlagsCmpB; V_regs.LazyFlagArgSrc = V_regs.SrcVal; V_regs.LazyFlagArgDst = dstvalue; HaveSetUpFlags(); } LOCALIPROC DoCodeCmpW(void) { ui5r dstvalue = DecodeGetSrcGetDstValue(); V_regs.LazyFlagKind = kLazyFlagsCmpW; V_regs.LazyFlagArgSrc = V_regs.SrcVal; V_regs.LazyFlagArgDst = dstvalue; HaveSetUpFlags(); } LOCALIPROC DoCodeCmpL(void) { ui5r dstvalue = DecodeGetSrcGetDstValue(); V_regs.LazyFlagKind = kLazyFlagsCmpL; V_regs.LazyFlagArgSrc = V_regs.SrcVal; V_regs.LazyFlagArgDst = dstvalue; HaveSetUpFlags(); } LOCALIPROC DoCodeMoveL(void) { ui5r src = DecodeGetSrcValue(); V_regs.LazyFlagKind = kLazyFlagsTstL; V_regs.LazyFlagArgDst = src; HaveSetUpFlags(); DecodeSetDstValue(src); } LOCALIPROC DoCodeMoveW(void) { ui5r src = DecodeGetSrcValue(); V_regs.LazyFlagKind = kLazyFlagsTstL; V_regs.LazyFlagArgDst = src; HaveSetUpFlags(); DecodeSetDstValue(src); } LOCALIPROC DoCodeMoveB(void) { ui5r src = DecodeGetSrcValue(); V_regs.LazyFlagKind = kLazyFlagsTstL; V_regs.LazyFlagArgDst = src; HaveSetUpFlags(); DecodeSetDstValue(src); } LOCALIPROC DoCodeTst(void) { /* Tst 01001010ssmmmrrr */ ui5r srcvalue = DecodeGetDstValue(); V_regs.LazyFlagKind = kLazyFlagsTstL; V_regs.LazyFlagArgDst = srcvalue; HaveSetUpFlags(); } LOCALIPROC DoCodeBraB(void) { si5r offset = (si5r)(si3b)(ui3b)(V_regs.CurDecOpY.v[1].ArgDat); ui3p s = V_pc_p + offset; V_pc_p = s; #if USE_PCLIMIT if (my_cond_rare(s >= V_pc_pHi) || my_cond_rare(s < V_regs.pc_pLo)) { Recalc_PC_Block(); } #endif } LOCALIPROC DoCodeBraW(void) { si5r offset = (si5r)(si4b)(ui4b)do_get_mem_word(V_pc_p); /* note that pc not incremented here */ ui3p s = V_pc_p + offset; V_pc_p = s; #if USE_PCLIMIT if (my_cond_rare(s >= V_pc_pHi) || my_cond_rare(s < V_regs.pc_pLo)) { Recalc_PC_Block(); } #endif } #if WantCloserCyc LOCALPROC DoCodeBccB_t(void) { V_MaxCyclesToGo -= (10 * kCycleScale + 2 * RdAvgXtraCyc); DoCodeBraB(); } #else #define DoCodeBccB_t DoCodeBraB #endif LOCALPROC DoCodeBccB_f(void) { #if WantCloserCyc V_MaxCyclesToGo -= (8 * kCycleScale + RdAvgXtraCyc); #endif /* do nothing */ } LOCALIPROC DoCodeBccB(void) { /* Bcc 0110ccccnnnnnnnn */ cctrue(DoCodeBccB_t, DoCodeBccB_f); } LOCALPROC SkipiWord(void) { V_pc_p += 2; #if USE_PCLIMIT if (my_cond_rare(V_pc_p >= V_pc_pHi)) { Recalc_PC_Block(); } #endif } #if WantCloserCyc LOCALPROC DoCodeBccW_t(void) { V_MaxCyclesToGo -= (10 * kCycleScale + 2 * RdAvgXtraCyc); DoCodeBraW(); } #else #define DoCodeBccW_t DoCodeBraW #endif #if WantCloserCyc LOCALPROC DoCodeBccW_f(void) { V_MaxCyclesToGo -= (12 * kCycleScale + 2 * RdAvgXtraCyc); SkipiWord(); } #else #define DoCodeBccW_f SkipiWord #endif LOCALIPROC DoCodeBccW(void) { /* Bcc 0110ccccnnnnnnnn */ cctrue(DoCodeBccW_t, DoCodeBccW_f); } LOCALIPROC DoCodeDBF(void) { /* DBcc 0101cccc11001ddd */ ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; ui5r dstvalue = ui5r_FromSWord(*dstp); --dstvalue; #if LittleEndianUnaligned *(ui4b *)dstp = dstvalue; #else *dstp = (*dstp & ~ 0xffff) | ((dstvalue) & 0xffff); #endif if ((si5b)dstvalue == -1) { #if WantCloserCyc V_MaxCyclesToGo -= (14 * kCycleScale + 3 * RdAvgXtraCyc); #endif SkipiWord(); } else { #if WantCloserCyc V_MaxCyclesToGo -= (10 * kCycleScale + 2 * RdAvgXtraCyc); #endif DoCodeBraW(); } } #if WantCloserCyc LOCALPROC DoCodeDBcc_t(void) { V_MaxCyclesToGo -= (12 * kCycleScale + 2 * RdAvgXtraCyc); SkipiWord(); } #else #define DoCodeDBcc_t SkipiWord #endif LOCALIPROC DoCodeDBcc(void) { /* DBcc 0101cccc11001ddd */ cctrue(DoCodeDBcc_t, DoCodeDBF); } LOCALIPROC DoCodeSwap(void) { /* Swap 0100100001000rrr */ ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; ui5r src = *dstp; ui5r dst = ui5r_FromSLong(((src >> 16) & 0xFFFF) | ((src & 0xFFFF) << 16)); V_regs.LazyFlagKind = kLazyFlagsTstL; V_regs.LazyFlagArgDst = dst; HaveSetUpFlags(); *dstp = dst; } LOCALIPROC DoCodeMoveA(void) /* MOVE */ { ui5r src = DecodeGetSrcValue(); ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; m68k_areg(dstreg) = src; } LOCALIPROC DoCodeMoveQ(void) { /* MoveQ 0111ddd0nnnnnnnn */ ui5r src = ui5r_FromSByte(V_regs.CurDecOpY.v[0].ArgDat); ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; V_regs.LazyFlagKind = kLazyFlagsTstL; V_regs.LazyFlagArgDst = src; HaveSetUpFlags(); m68k_dreg(dstreg) = src; } LOCALIPROC DoCodeAddB(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r srcvalue = V_regs.SrcVal; ui5r result = ui5r_FromSByte(dstvalue + srcvalue); V_regs.LazyFlagKind = kLazyFlagsAddB; V_regs.LazyFlagArgSrc = srcvalue; V_regs.LazyFlagArgDst = dstvalue; V_regs.LazyXFlagKind = kLazyFlagsAddB; V_regs.LazyXFlagArgSrc = srcvalue; V_regs.LazyXFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(result); } LOCALIPROC DoCodeAddW(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r srcvalue = V_regs.SrcVal; ui5r result = ui5r_FromSWord(dstvalue + srcvalue); V_regs.LazyFlagKind = kLazyFlagsAddW; V_regs.LazyFlagArgSrc = srcvalue; V_regs.LazyFlagArgDst = dstvalue; V_regs.LazyXFlagKind = kLazyFlagsAddW; V_regs.LazyXFlagArgSrc = srcvalue; V_regs.LazyXFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(result); } LOCALIPROC DoCodeAddL(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r srcvalue = V_regs.SrcVal; ui5r result = ui5r_FromSLong(dstvalue + srcvalue); V_regs.LazyFlagKind = kLazyFlagsAddL; V_regs.LazyFlagArgSrc = srcvalue; V_regs.LazyFlagArgDst = dstvalue; V_regs.LazyXFlagKind = kLazyFlagsAddL; V_regs.LazyXFlagArgSrc = srcvalue; V_regs.LazyXFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(result); } LOCALIPROC DoCodeSubB(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r srcvalue = V_regs.SrcVal; ui5r result = ui5r_FromSByte(dstvalue - srcvalue); V_regs.LazyFlagKind = kLazyFlagsSubB; V_regs.LazyFlagArgSrc = srcvalue; V_regs.LazyFlagArgDst = dstvalue; V_regs.LazyXFlagKind = kLazyFlagsSubB; V_regs.LazyXFlagArgSrc = srcvalue; V_regs.LazyXFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(result); } LOCALIPROC DoCodeSubW(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r srcvalue = V_regs.SrcVal; ui5r result = ui5r_FromSWord(dstvalue - srcvalue); V_regs.LazyFlagKind = kLazyFlagsSubW; V_regs.LazyFlagArgSrc = srcvalue; V_regs.LazyFlagArgDst = dstvalue; V_regs.LazyXFlagKind = kLazyFlagsSubW; V_regs.LazyXFlagArgSrc = srcvalue; V_regs.LazyXFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(result); } LOCALIPROC DoCodeSubL(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r srcvalue = V_regs.SrcVal; ui5r result = ui5r_FromSLong(dstvalue - srcvalue); V_regs.LazyFlagKind = kLazyFlagsSubL; V_regs.LazyFlagArgSrc = srcvalue; V_regs.LazyFlagArgDst = dstvalue; V_regs.LazyXFlagKind = kLazyFlagsSubL; V_regs.LazyXFlagArgSrc = srcvalue; V_regs.LazyXFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(result); } LOCALIPROC DoCodeLea(void) { /* Lea 0100aaa111mmmrrr */ ui5r DstAddr = DecodeDst(); ui5r dstreg = V_regs.CurDecOpY.v[0].ArgDat; m68k_areg(dstreg) = DstAddr; } LOCALIPROC DoCodePEA(void) { /* PEA 0100100001mmmrrr */ ui5r DstAddr = DecodeDst(); m68k_areg(7) -= 4; put_long(m68k_areg(7), DstAddr); } LOCALIPROC DoCodeBsrB(void) { m68k_areg(7) -= 4; put_long(m68k_areg(7), m68k_getpc()); DoCodeBraB(); } LOCALIPROC DoCodeBsrW(void) { m68k_areg(7) -= 4; put_long(m68k_areg(7), m68k_getpc() + 2); DoCodeBraW(); } #define m68k_logExceptions (dbglog_HAVE && 0) #ifndef WantDumpAJump #define WantDumpAJump 0 #endif #if WantDumpAJump LOCALPROCUSEDONCE DumpAJump(CPTR toaddr) { CPTR fromaddr = m68k_getpc(); if ((toaddr > fromaddr) || (toaddr < V_regs.pc)) { dbglog_writeHex(fromaddr); dbglog_writeCStr(","); dbglog_writeHex(toaddr); dbglog_writeReturn(); } } #endif LOCALPROC my_reg_call m68k_setpc(CPTR newpc) { #if WantDumpAJump DumpAJump(newpc); #endif #if 0 if (newpc == 0xBD50 /* 401AB4 */) { /* Debugger(); */ /* Exception(5); */ /* try and get macsbug */ } #endif V_pc_p = V_regs.pc_pLo + (newpc - V_regs.pc); if (my_cond_rare(V_pc_p >= V_pc_pHi) || my_cond_rare(V_pc_p < V_regs.pc_pLo)) { Recalc_PC_Block(); } } LOCALIPROC DoCodeJsr(void) { /* Jsr 0100111010mmmrrr */ ui5r DstAddr = DecodeDst(); m68k_areg(7) -= 4; put_long(m68k_areg(7), m68k_getpc()); m68k_setpc(DstAddr); } LOCALIPROC DoCodeLinkA6(void) { CPTR stackp = m68k_areg(7); stackp -= 4; put_long(stackp, m68k_areg(6)); m68k_areg(6) = stackp; m68k_areg(7) = stackp + nextiSWord(); } LOCALIPROC DoCodeUnlkA6(void) { ui5r src = m68k_areg(6); m68k_areg(6) = get_long(src); m68k_areg(7) = src + 4; } LOCALIPROC DoCodeRts(void) { /* Rts 0100111001110101 */ ui5r NewPC = get_long(m68k_areg(7)); m68k_areg(7) += 4; m68k_setpc(NewPC); } LOCALIPROC DoCodeJmp(void) { /* JMP 0100111011mmmrrr */ ui5r DstAddr = DecodeDst(); m68k_setpc(DstAddr); } LOCALIPROC DoCodeClr(void) { /* Clr 01000010ssmmmrrr */ V_regs.LazyFlagKind = kLazyFlagsTstL; V_regs.LazyFlagArgDst = 0; HaveSetUpFlags(); DecodeSetDstValue(0); } LOCALIPROC DoCodeAddA(void) { /* ADDA 1101dddm11mmmrrr */ ui5r dstvalue = DecodeGetSrcSetDstValue(); ArgSetDstValue(dstvalue + V_regs.SrcVal); } LOCALIPROC DoCodeSubA(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ArgSetDstValue(dstvalue - V_regs.SrcVal); } LOCALIPROC DoCodeCmpA(void) { ui5r dstvalue = DecodeGetSrcGetDstValue(); V_regs.LazyFlagKind = kLazyFlagsCmpL; V_regs.LazyFlagArgSrc = V_regs.SrcVal; V_regs.LazyFlagArgDst = dstvalue; HaveSetUpFlags(); } LOCALFUNC ui4rr m68k_getCR(void) { NeedDefaultLazyAllFlags(); return (XFLG << 4) | (NFLG << 3) | (ZFLG << 2) | (VFLG << 1) | CFLG; } LOCALPROC my_reg_call m68k_setCR(ui4rr newcr) { XFLG = (newcr >> 4) & 1; NFLG = (newcr >> 3) & 1; ZFLG = (newcr >> 2) & 1; VFLG = (newcr >> 1) & 1; CFLG = newcr & 1; V_regs.LazyFlagKind = kLazyFlagsDefault; V_regs.LazyXFlagKind = kLazyFlagsDefault; } LOCALFUNC ui4rr m68k_getSR(void) { return m68k_getCR() | (V_regs.t1 << 15) #if Use68020 | (V_regs.t0 << 14) #endif | (V_regs.s << 13) #if Use68020 | (V_regs.m << 12) #endif | (V_regs.intmask << 8); } LOCALPROC NeedToGetOut(void) { if (V_MaxCyclesToGo <= 0) { /* already have gotten out, and exception processing has caused another exception, such as because a bad stack pointer pointing to a memory mapped device. */ } else { V_regs.MoreCyclesToGo += V_MaxCyclesToGo; /* not counting the current instruction */ V_MaxCyclesToGo = 0; } } LOCALPROC SetExternalInterruptPending(void) { V_regs.ExternalInterruptPending = trueblnr; NeedToGetOut(); } LOCALPROC my_reg_call m68k_setSR(ui4rr newsr) { CPTR *pnewstk; CPTR *poldstk = (V_regs.s != 0) ? ( #if Use68020 (V_regs.m != 0) ? &V_regs.msp : #endif &V_regs.isp) : &V_regs.usp; ui5r oldintmask = V_regs.intmask; V_regs.t1 = (newsr >> 15) & 1; #if Use68020 V_regs.t0 = (newsr >> 14) & 1; if (V_regs.t0 != 0) { ReportAbnormalID(0x0105, "t0 flag set in m68k_setSR"); } #endif V_regs.s = (newsr >> 13) & 1; #if Use68020 V_regs.m = (newsr >> 12) & 1; if (V_regs.m != 0) { ReportAbnormalID(0x0106, "m flag set in m68k_setSR"); } #endif V_regs.intmask = (newsr >> 8) & 7; pnewstk = (V_regs.s != 0) ? ( #if Use68020 (V_regs.m != 0) ? &V_regs.msp : #endif &V_regs.isp) : &V_regs.usp; if (poldstk != pnewstk) { *poldstk = m68k_areg(7); m68k_areg(7) = *pnewstk; } if (V_regs.intmask != oldintmask) { SetExternalInterruptPending(); } if (V_regs.t1 != 0) { NeedToGetOut(); } else { /* V_regs.TracePending = falseblnr; */ } m68k_setCR(newsr); } LOCALPROC my_reg_call ExceptionTo(CPTR newpc #if Use68020 , int nr #endif ) { ui4rr saveSR = m68k_getSR(); if (0 == V_regs.s) { V_regs.usp = m68k_areg(7); m68k_areg(7) = #if Use68020 (V_regs.m != 0) ? V_regs.msp : #endif V_regs.isp; V_regs.s = 1; } #if Use68020 switch (nr) { case 5: /* Zero Divide */ case 6: /* CHK, CHK2 */ case 7: /* cpTRAPcc, TRAPCcc, TRAPv */ case 9: /* Trace */ m68k_areg(7) -= 4; put_long(m68k_areg(7), m68k_getpc()); m68k_areg(7) -= 2; put_word(m68k_areg(7), 0x2000 + nr * 4); break; default: m68k_areg(7) -= 2; put_word(m68k_areg(7), nr * 4); break; } /* if V_regs.m should make throw away stack frame */ #endif m68k_areg(7) -= 4; put_long(m68k_areg(7), m68k_getpc()); m68k_areg(7) -= 2; put_word(m68k_areg(7), saveSR); m68k_setpc(newpc); V_regs.t1 = 0; #if Use68020 V_regs.t0 = 0; V_regs.m = 0; #endif V_regs.TracePending = falseblnr; } LOCALPROC my_reg_call Exception(int nr) { ExceptionTo(get_long(4 * nr #if Use68020 + V_regs.vbr #endif ) #if Use68020 , nr #endif ); } LOCALIPROC DoCodeA(void) { BackupPC(); Exception(0xA); } LOCALFUNC ui4rr nextiword_nm(void) /* NOT sign extended */ { return nextiword(); } LOCALIPROC DoCodeMOVEMRmML(void) { /* MOVEM reg to mem 01001000111100rrr */ si4b z; ui5r regmask = nextiword_nm(); ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; ui5r p = *dstp; #if Use68020 { int n = 0; for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { n++; } } *dstp = p - n * 4; } #endif for (z = 16; --z >= 0; ) { if ((regmask & (1 << (15 - z))) != 0) { #if WantCloserCyc V_MaxCyclesToGo -= (8 * kCycleScale + 2 * WrAvgXtraCyc); #endif p -= 4; put_long(p, V_regs.regs[z]); } } #if ! Use68020 *dstp = p; #endif } LOCALIPROC DoCodeMOVEMApRL(void) { /* MOVEM mem to reg 01001100111011rrr */ si4b z; ui5r regmask = nextiword_nm(); ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; ui5r p = *dstp; for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { #if WantCloserCyc V_MaxCyclesToGo -= (8 * kCycleScale + 2 * RdAvgXtraCyc); #endif V_regs.regs[z] = get_long(p); p += 4; } } *dstp = p; } LOCALPROC my_reg_call SetCCRforAddX(ui5r dstvalue, ui5r srcvalue, ui5r result) { ZFLG &= Bool2Bit(result == 0); { flagtype flgs = Bool2Bit(ui5r_MSBisSet(srcvalue)); flagtype flgo = Bool2Bit(ui5r_MSBisSet(dstvalue)); flagtype flgsando = flgs & flgo; flagtype flgsoro = flgs | flgo; flagtype flgn = Bool2Bit(ui5r_MSBisSet(result)); NFLG = flgn; flgn ^= 1; VFLG = ((flgn | flgsoro) ^ 1) | (flgn & flgsando); XFLG = CFLG = flgsando | (flgn & flgsoro); } ArgSetDstValue(result); } LOCALIPROC DoCodeAddXB(void) { NeedDefaultLazyAllFlags(); { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r srcvalue = V_regs.SrcVal; ui5r result = ui5r_FromSByte(XFLG + dstvalue + srcvalue); SetCCRforAddX(dstvalue, srcvalue, result); } } LOCALIPROC DoCodeAddXW(void) { if ((kLazyFlagsDefault != V_regs.LazyFlagKind) || (kLazyFlagsDefault != V_regs.LazyXFlagKind)) { NeedDefaultLazyAllFlags(); } { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r srcvalue = V_regs.SrcVal; ui5r result = ui5r_FromSWord(XFLG + dstvalue + srcvalue); SetCCRforAddX(dstvalue, srcvalue, result); } } LOCALIPROC DoCodeAddXL(void) { if (kLazyFlagsAddL == V_regs.LazyFlagKind) { ui5r src = V_regs.LazyFlagArgSrc; ui5r dst = V_regs.LazyFlagArgDst; ui5r result = ui5r_FromULong(dst + src); ZFLG = Bool2Bit(result == 0); XFLG = Bool2Bit(result < src); V_regs.LazyFlagKind = kLazyFlagsDefault; V_regs.LazyXFlagKind = kLazyFlagsDefault; } else if ((kLazyFlagsDefault == V_regs.LazyFlagKind) && (kLazyFlagsDefault == V_regs.LazyXFlagKind)) { /* ok */ } else { NeedDefaultLazyAllFlags(); } { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r srcvalue = V_regs.SrcVal; ui5r result = ui5r_FromSLong(XFLG + dstvalue + srcvalue); SetCCRforAddX(dstvalue, srcvalue, result); } } LOCALPROC my_reg_call SetCCRforSubX(ui5r dstvalue, ui5r srcvalue, ui5r result) { ZFLG &= Bool2Bit(result == 0); { flagtype flgs = Bool2Bit(ui5r_MSBisSet(srcvalue)); flagtype flgo = Bool2Bit(ui5r_MSBisSet(dstvalue)) ^ 1; flagtype flgsando = flgs & flgo; flagtype flgsoro = flgs | flgo; flagtype flgn = Bool2Bit(ui5r_MSBisSet(result)); NFLG = flgn; VFLG = ((flgn | flgsoro) ^ 1) | (flgn & flgsando); XFLG = CFLG = flgsando | (flgn & flgsoro); } ArgSetDstValue(result); } LOCALIPROC DoCodeSubXB(void) { NeedDefaultLazyAllFlags(); { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r srcvalue = V_regs.SrcVal; ui5r result = ui5r_FromSByte(dstvalue - srcvalue - XFLG); SetCCRforSubX(dstvalue, srcvalue, result); } } LOCALIPROC DoCodeSubXW(void) { if ((kLazyFlagsDefault != V_regs.LazyFlagKind) || (kLazyFlagsDefault != V_regs.LazyXFlagKind)) { NeedDefaultLazyAllFlags(); } { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r srcvalue = V_regs.SrcVal; ui5r result = ui5r_FromSWord(dstvalue - srcvalue - XFLG); SetCCRforSubX(dstvalue, srcvalue, result); } } LOCALIPROC DoCodeSubXL(void) { if (kLazyFlagsSubL == V_regs.LazyFlagKind) { ui5r src = V_regs.LazyFlagArgSrc; ui5r dst = V_regs.LazyFlagArgDst; ui5r result = ui5r_FromSLong(dst - src); ZFLG = Bool2Bit(result == 0); XFLG = Bool2Bit(((ui5b)dst) < ((ui5b)src)); V_regs.LazyFlagKind = kLazyFlagsDefault; V_regs.LazyXFlagKind = kLazyFlagsDefault; } else if ((kLazyFlagsDefault == V_regs.LazyFlagKind) && (kLazyFlagsDefault == V_regs.LazyXFlagKind)) { /* ok */ } else { NeedDefaultLazyAllFlags(); } { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r srcvalue = V_regs.SrcVal; ui5r result = ui5r_FromSLong(dstvalue - srcvalue - XFLG); SetCCRforSubX(dstvalue, srcvalue, result); } } LOCALPROC my_reg_call DoCodeNullShift(ui5r dstvalue) { V_regs.LazyFlagKind = kLazyFlagsTstL; V_regs.LazyFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(dstvalue); } LOCALPROC DoCodeOverAsl(ui5r dstvalue) { XFLG = CFLG = 0; VFLG = Bool2Bit(0 != dstvalue); ZFLG = 1; NFLG = 0; V_regs.LazyXFlagKind = kLazyFlagsDefault; V_regs.LazyFlagKind = kLazyFlagsDefault; ArgSetDstValue(0); } LOCALPROC my_reg_call DoCodeMaxAsr(ui5r dstvalue) { XFLG = CFLG = dstvalue & 1; VFLG = Bool2Bit(0 != dstvalue); ZFLG = 1; NFLG = 0; V_regs.LazyXFlagKind = kLazyFlagsDefault; V_regs.LazyFlagKind = kLazyFlagsDefault; ArgSetDstValue(0); } LOCALIPROC DoCodeAslB(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r cnt = V_regs.SrcVal & 63; if (0 == cnt) { DoCodeNullShift(dstvalue); } else { #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif if (cnt >= 8) { if (cnt == 8) { DoCodeMaxAsr(dstvalue); } else { DoCodeOverAsl(dstvalue); } } else { ui5r result = ui5r_FromSByte(dstvalue << cnt); V_regs.LazyFlagKind = kLazyFlagsAslB; V_regs.LazyFlagArgSrc = cnt; V_regs.LazyFlagArgDst = dstvalue; V_regs.LazyXFlagKind = kLazyFlagsAslB; V_regs.LazyXFlagArgSrc = cnt; V_regs.LazyXFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(result); } } } LOCALIPROC DoCodeAslW(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r cnt = V_regs.SrcVal & 63; if (0 == cnt) { DoCodeNullShift(dstvalue); } else { #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif if (cnt >= 16) { if (cnt == 16) { DoCodeMaxAsr(dstvalue); } else { DoCodeOverAsl(dstvalue); } } else { ui5r result = ui5r_FromSWord(dstvalue << cnt); V_regs.LazyFlagKind = kLazyFlagsAslW; V_regs.LazyFlagArgSrc = cnt; V_regs.LazyFlagArgDst = dstvalue; V_regs.LazyXFlagKind = kLazyFlagsAslW; V_regs.LazyXFlagArgSrc = cnt; V_regs.LazyXFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(result); } } } LOCALIPROC DoCodeAslL(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r cnt = V_regs.SrcVal & 63; if (0 == cnt) { DoCodeNullShift(dstvalue); } else { #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif if (cnt >= 32) { if (cnt == 32) { DoCodeMaxAsr(dstvalue); } else { DoCodeOverAsl(dstvalue); } } else { ui5r result = ui5r_FromSLong(dstvalue << cnt); V_regs.LazyFlagKind = kLazyFlagsAslL; V_regs.LazyFlagArgSrc = cnt; V_regs.LazyFlagArgDst = dstvalue; V_regs.LazyXFlagKind = kLazyFlagsAslL; V_regs.LazyXFlagArgSrc = cnt; V_regs.LazyXFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(result); } } } LOCALPROC DoCodeOverShift(void) { XFLG = CFLG = 0; ZFLG = 1; NFLG = 0; VFLG = 0; V_regs.LazyXFlagKind = kLazyFlagsDefault; V_regs.LazyFlagKind = kLazyFlagsDefault; ArgSetDstValue(0); } LOCALPROC DoCodeOverShiftN(void) { NFLG = 1; VFLG = 0; CFLG = 1; XFLG = CFLG; ZFLG = 0; V_regs.LazyXFlagKind = kLazyFlagsDefault; V_regs.LazyFlagKind = kLazyFlagsDefault; ArgSetDstValue(~ 0); } LOCALPROC DoCodeOverAShift(ui5r dstvalue) { if (ui5r_MSBisSet(dstvalue)) { DoCodeOverShiftN(); } else { DoCodeOverShift(); } } LOCALIPROC DoCodeAsrB(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r cnt = V_regs.SrcVal & 63; if (0 == cnt) { DoCodeNullShift(dstvalue); } else { #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif if (cnt >= 8) { DoCodeOverAShift(dstvalue); } else { ui5r result = Ui5rASR(dstvalue, cnt); V_regs.LazyFlagKind = kLazyFlagsAsrB; V_regs.LazyFlagArgSrc = cnt; V_regs.LazyFlagArgDst = dstvalue; V_regs.LazyXFlagKind = kLazyFlagsAsrB; V_regs.LazyXFlagArgSrc = cnt; V_regs.LazyXFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(result); } } } LOCALIPROC DoCodeAsrW(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r cnt = V_regs.SrcVal & 63; if (0 == cnt) { DoCodeNullShift(dstvalue); } else { #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif if (cnt >= 16) { DoCodeOverAShift(dstvalue); } else { ui5r result = Ui5rASR(dstvalue, cnt); V_regs.LazyFlagKind = kLazyFlagsAsrW; V_regs.LazyFlagArgSrc = cnt; V_regs.LazyFlagArgDst = dstvalue; V_regs.LazyXFlagKind = kLazyFlagsAsrW; V_regs.LazyXFlagArgSrc = cnt; V_regs.LazyXFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(result); } } } LOCALIPROC DoCodeAsrL(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r cnt = V_regs.SrcVal & 63; if (0 == cnt) { DoCodeNullShift(dstvalue); } else { #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif if (cnt >= 32) { DoCodeOverAShift(dstvalue); } else { ui5r result = Ui5rASR(dstvalue, cnt); V_regs.LazyFlagKind = kLazyFlagsAsrL; V_regs.LazyFlagArgSrc = cnt; V_regs.LazyFlagArgDst = dstvalue; V_regs.LazyXFlagKind = kLazyFlagsAsrL; V_regs.LazyXFlagArgSrc = cnt; V_regs.LazyXFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(result); } } } LOCALPROC my_reg_call DoCodeMaxLslShift(ui5r dstvalue) { XFLG = CFLG = dstvalue & 1; ZFLG = 1; NFLG = 0; VFLG = 0; V_regs.LazyXFlagKind = kLazyFlagsDefault; V_regs.LazyFlagKind = kLazyFlagsDefault; ArgSetDstValue(0); } LOCALIPROC DoCodeLslB(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r cnt = V_regs.SrcVal & 63; if (0 == cnt) { DoCodeNullShift(dstvalue); } else { #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif if (cnt >= 8) { if (cnt == 8) { DoCodeMaxLslShift(dstvalue); } else { DoCodeOverShift(); } } else { CFLG = (dstvalue >> (8 - cnt)) & 1; dstvalue = dstvalue << cnt; dstvalue = ui5r_FromSByte(dstvalue); ZFLG = Bool2Bit(dstvalue == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); VFLG = 0; XFLG = CFLG; V_regs.LazyXFlagKind = kLazyFlagsDefault; V_regs.LazyFlagKind = kLazyFlagsDefault; ArgSetDstValue(dstvalue); } } } LOCALIPROC DoCodeLslW(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r cnt = V_regs.SrcVal & 63; if (0 == cnt) { DoCodeNullShift(dstvalue); } else { #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif if (cnt >= 16) { if (cnt == 16) { DoCodeMaxLslShift(dstvalue); } else { DoCodeOverShift(); } } else { CFLG = (dstvalue >> (16 - cnt)) & 1; dstvalue = dstvalue << cnt; dstvalue = ui5r_FromSWord(dstvalue); ZFLG = Bool2Bit(dstvalue == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); VFLG = 0; XFLG = CFLG; V_regs.LazyXFlagKind = kLazyFlagsDefault; V_regs.LazyFlagKind = kLazyFlagsDefault; ArgSetDstValue(dstvalue); } } } LOCALIPROC DoCodeLslL(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r cnt = V_regs.SrcVal & 63; if (0 == cnt) { DoCodeNullShift(dstvalue); } else { #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif if (cnt >= 32) { if (cnt == 32) { DoCodeMaxLslShift(dstvalue); } else { DoCodeOverShift(); } } else { CFLG = (dstvalue >> (32 - cnt)) & 1; dstvalue = dstvalue << cnt; dstvalue = ui5r_FromSLong(dstvalue); ZFLG = Bool2Bit(dstvalue == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); VFLG = 0; XFLG = CFLG; V_regs.LazyXFlagKind = kLazyFlagsDefault; V_regs.LazyFlagKind = kLazyFlagsDefault; ArgSetDstValue(dstvalue); } } } LOCALIPROC DoCodeLsrB(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r cnt = V_regs.SrcVal & 63; #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif if (0 == cnt) { DoCodeNullShift(dstvalue); } else if (cnt > 32) { DoCodeOverShift(); } else { dstvalue = ui5r_FromUByte(dstvalue); dstvalue = dstvalue >> (cnt - 1); CFLG = XFLG = (dstvalue & 1); dstvalue = dstvalue >> 1; ZFLG = Bool2Bit(dstvalue == 0); NFLG = 0 /* Bool2Bit(ui5r_MSBisSet(dstvalue)) */; /* if cnt != 0, always false */ VFLG = 0; V_regs.LazyXFlagKind = kLazyFlagsDefault; V_regs.LazyFlagKind = kLazyFlagsDefault; ArgSetDstValue(dstvalue); } } LOCALIPROC DoCodeLsrW(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r cnt = V_regs.SrcVal & 63; #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif if (0 == cnt) { DoCodeNullShift(dstvalue); } else if (cnt > 32) { DoCodeOverShift(); } else { dstvalue = ui5r_FromUWord(dstvalue); dstvalue = dstvalue >> (cnt - 1); CFLG = XFLG = (dstvalue & 1); dstvalue = dstvalue >> 1; ZFLG = Bool2Bit(dstvalue == 0); NFLG = 0 /* Bool2Bit(ui5r_MSBisSet(dstvalue)) */; /* if cnt != 0, always false */ VFLG = 0; V_regs.LazyXFlagKind = kLazyFlagsDefault; V_regs.LazyFlagKind = kLazyFlagsDefault; ArgSetDstValue(dstvalue); } } LOCALIPROC DoCodeLsrL(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r cnt = V_regs.SrcVal & 63; #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif if (0 == cnt) { DoCodeNullShift(dstvalue); } else if (cnt > 32) { DoCodeOverShift(); } else { dstvalue = ui5r_FromULong(dstvalue); dstvalue = dstvalue >> (cnt - 1); CFLG = XFLG = (dstvalue & 1); dstvalue = dstvalue >> 1; ZFLG = Bool2Bit(dstvalue == 0); NFLG = 0 /* Bool2Bit(ui5r_MSBisSet(dstvalue)) */; /* if cnt != 0, always false */ VFLG = 0; V_regs.LazyXFlagKind = kLazyFlagsDefault; V_regs.LazyFlagKind = kLazyFlagsDefault; ArgSetDstValue(dstvalue); } } LOCALFUNC ui5r DecodeGetSrcSetDstValueDfltFlags_nm(void) { NeedDefaultLazyAllFlags(); return DecodeGetSrcSetDstValue(); } LOCALPROC my_reg_call DoCodeNullXShift(ui5r dstvalue) { CFLG = XFLG; ZFLG = Bool2Bit(dstvalue == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); VFLG = 0; ArgSetDstValue(dstvalue); } LOCALIPROC DoCodeRxlB(void) { ui5r dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm(); ui5r cnt = V_regs.SrcVal & 63; if (0 == cnt) { DoCodeNullXShift(dstvalue); } else { #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif for (; cnt; --cnt) { CFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); dstvalue = (dstvalue << 1) | XFLG; dstvalue = ui5r_FromSByte(dstvalue); XFLG = CFLG; } ZFLG = Bool2Bit(dstvalue == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); VFLG = 0; ArgSetDstValue(dstvalue); } } LOCALIPROC DoCodeRxlW(void) { ui5r dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm(); ui5r cnt = V_regs.SrcVal & 63; if (0 == cnt) { DoCodeNullXShift(dstvalue); } else { #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif for (; cnt; --cnt) { CFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); dstvalue = (dstvalue << 1) | XFLG; dstvalue = ui5r_FromSWord(dstvalue); XFLG = CFLG; } ZFLG = Bool2Bit(dstvalue == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); VFLG = 0; ArgSetDstValue(dstvalue); } } LOCALIPROC DoCodeRxlL(void) { ui5r dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm(); ui5r cnt = V_regs.SrcVal & 63; if (0 == cnt) { DoCodeNullXShift(dstvalue); } else { #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif for (; cnt; --cnt) { CFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); dstvalue = (dstvalue << 1) | XFLG; dstvalue = ui5r_FromSLong(dstvalue); XFLG = CFLG; } ZFLG = Bool2Bit(dstvalue == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); VFLG = 0; ArgSetDstValue(dstvalue); } } LOCALIPROC DoCodeRxrB(void) { ui5r dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm(); ui5r cnt = V_regs.SrcVal & 63; if (0 == cnt) { DoCodeNullXShift(dstvalue); } else { #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif dstvalue = ui5r_FromUByte(dstvalue); for (; cnt; --cnt) { CFLG = dstvalue & 1; dstvalue = (dstvalue >> 1) | (((ui5r)XFLG) << 7); XFLG = CFLG; } dstvalue = ui5r_FromSByte(dstvalue); ZFLG = Bool2Bit(dstvalue == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); VFLG = 0; ArgSetDstValue(dstvalue); } } LOCALIPROC DoCodeRxrW(void) { ui5r dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm(); ui5r cnt = V_regs.SrcVal & 63; if (0 == cnt) { DoCodeNullXShift(dstvalue); } else { #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif dstvalue = ui5r_FromUWord(dstvalue); for (; cnt; --cnt) { CFLG = dstvalue & 1; dstvalue = (dstvalue >> 1) | (((ui5r)XFLG) << 15); XFLG = CFLG; } dstvalue = ui5r_FromSWord(dstvalue); ZFLG = Bool2Bit(dstvalue == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); VFLG = 0; ArgSetDstValue(dstvalue); } } LOCALIPROC DoCodeRxrL(void) { ui5r dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm(); ui5r cnt = V_regs.SrcVal & 63; if (0 == cnt) { DoCodeNullXShift(dstvalue); } else { #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif dstvalue = ui5r_FromULong(dstvalue); for (; cnt; --cnt) { CFLG = dstvalue & 1; dstvalue = (dstvalue >> 1) | (((ui5r)XFLG) << 31); XFLG = CFLG; } dstvalue = ui5r_FromSLong(dstvalue); ZFLG = Bool2Bit(dstvalue == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); VFLG = 0; ArgSetDstValue(dstvalue); } } LOCALIPROC DoCodeRolB(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r cnt = V_regs.SrcVal & 63; #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif if (0 == cnt) { DoCodeNullShift(dstvalue); } else { cnt &= 7; if (0 != cnt) { ui3b dst = (ui3b)dstvalue; dst = (dst >> (8 - cnt)) | ((dst & ((1 << (8 - cnt)) - 1)) << cnt); dstvalue = (ui5r)(si5r)(si3b)dst; } ZFLG = Bool2Bit(dstvalue == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); VFLG = 0; CFLG = (dstvalue & 1); V_regs.LazyFlagKind = kLazyFlagsDefault; ArgSetDstValue(dstvalue); } } LOCALIPROC DoCodeRolW(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r cnt = V_regs.SrcVal & 63; #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif if (0 == cnt) { DoCodeNullShift(dstvalue); } else { cnt &= 15; if (0 != cnt) { ui4b dst = (ui4b)dstvalue; dst = (dst >> (16 - cnt)) | ((dst & ((1 << (16 - cnt)) - 1)) << cnt); dstvalue = (ui5r)(si5r)(si4b)dst; } ZFLG = Bool2Bit(dstvalue == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); VFLG = 0; CFLG = (dstvalue & 1); V_regs.LazyFlagKind = kLazyFlagsDefault; ArgSetDstValue(dstvalue); } } LOCALIPROC DoCodeRolL(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r cnt = V_regs.SrcVal & 63; #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif if (0 == cnt) { DoCodeNullShift(dstvalue); } else { cnt &= 31; if (0 != cnt) { ui5b dst = (ui5b)dstvalue; dst = (dst >> (32 - cnt)) | ((dst & ((1 << (32 - cnt)) - 1)) << cnt); dstvalue = (ui5r)(si5r)(si5b)dst; } ZFLG = Bool2Bit(dstvalue == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); VFLG = 0; CFLG = (dstvalue & 1); V_regs.LazyFlagKind = kLazyFlagsDefault; ArgSetDstValue(dstvalue); } } LOCALIPROC DoCodeRorB(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r cnt = V_regs.SrcVal & 63; #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif if (0 == cnt) { DoCodeNullShift(dstvalue); } else { cnt &= 7; if (0 != cnt) { ui3b dst = (ui3b)dstvalue; dst = (dst >> cnt) | ((dst & ((1 << cnt) - 1)) << (8 - cnt)); dstvalue = (ui5r)(si5r)(si3b)dst; } ZFLG = Bool2Bit(dstvalue == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); VFLG = 0; CFLG = NFLG; V_regs.LazyFlagKind = kLazyFlagsDefault; ArgSetDstValue(dstvalue); } } LOCALIPROC DoCodeRorW(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r cnt = V_regs.SrcVal & 63; #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif if (0 == cnt) { DoCodeNullShift(dstvalue); } else { cnt &= 15; if (0 != cnt) { ui4b dst = (ui4b)dstvalue; dst = (dst >> cnt) | ((dst & ((1 << cnt) - 1)) << (16 - cnt)); dstvalue = (ui5r)(si5r)(si4b)dst; } ZFLG = Bool2Bit(dstvalue == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); VFLG = 0; CFLG = NFLG; V_regs.LazyFlagKind = kLazyFlagsDefault; ArgSetDstValue(dstvalue); } } LOCALIPROC DoCodeRorL(void) { ui5r dstvalue = DecodeGetSrcSetDstValue(); ui5r cnt = V_regs.SrcVal & 63; #if WantCloserCyc V_MaxCyclesToGo -= (cnt * 2 * kCycleScale); #endif if (0 == cnt) { DoCodeNullShift(dstvalue); } else { cnt &= 31; if (0 != cnt) { ui5b dst = (ui5b)dstvalue; dst = (dst >> cnt) | ((dst & ((1 << cnt) - 1)) << (32 - cnt)); dstvalue = (ui5r)(si5r)(si5b)dst; } ZFLG = Bool2Bit(dstvalue == 0); NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); VFLG = 0; CFLG = NFLG; V_regs.LazyFlagKind = kLazyFlagsDefault; ArgSetDstValue(dstvalue); } } #if UseLazyZ LOCALPROC WillSetZFLG(void) { if (kLazyFlagsZSet == V_regs.LazyFlagKind) { /* ok */ } else if (kLazyFlagsDefault == V_regs.LazyFlagKind) { /* also ok */ } else { V_regs.LazyFlagZSavedKind = V_regs.LazyFlagKind; V_regs.LazyFlagKind = kLazyFlagsZSet; } } #else #define WillSetZFLG NeedDefaultLazyAllFlags #endif LOCALINLINEFUNC ui5r DecodeGetSrcGetDstValueSetZ(void) { WillSetZFLG(); return DecodeGetSrcSetDstValue(); } LOCALIPROC DoCodeBTstB(void) { ui5r dstvalue = DecodeGetSrcGetDstValueSetZ(); ui5r srcvalue = V_regs.SrcVal & 7; ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1; } LOCALIPROC DoCodeBTstL(void) { ui5r dstvalue = DecodeGetSrcGetDstValueSetZ(); ui5r srcvalue = V_regs.SrcVal & 31; ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1; } LOCALINLINEFUNC ui5r DecodeGetSrcSetDstValueSetZ(void) { WillSetZFLG(); return DecodeGetSrcSetDstValue(); } LOCALIPROC DoCodeBChgB(void) { ui5r dstvalue = DecodeGetSrcSetDstValueSetZ(); ui5r srcvalue = V_regs.SrcVal & 7; ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1; dstvalue ^= (1 << srcvalue); ArgSetDstValue(dstvalue); } LOCALIPROC DoCodeBChgL(void) { ui5r dstvalue = DecodeGetSrcSetDstValueSetZ(); ui5r srcvalue = V_regs.SrcVal & 31; ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1; dstvalue ^= (1 << srcvalue); ArgSetDstValue(dstvalue); } LOCALIPROC DoCodeBClrB(void) { ui5r dstvalue = DecodeGetSrcSetDstValueSetZ(); ui5r srcvalue = V_regs.SrcVal & 7; ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1; dstvalue &= ~ (1 << srcvalue); ArgSetDstValue(dstvalue); } LOCALIPROC DoCodeBClrL(void) { ui5r dstvalue = DecodeGetSrcSetDstValueSetZ(); ui5r srcvalue = V_regs.SrcVal & 31; ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1; dstvalue &= ~ (1 << srcvalue); ArgSetDstValue(dstvalue); } LOCALIPROC DoCodeBSetB(void) { ui5r dstvalue = DecodeGetSrcSetDstValueSetZ(); ui5r srcvalue = V_regs.SrcVal & 7; ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1; dstvalue |= (1 << srcvalue); ArgSetDstValue(dstvalue); } LOCALIPROC DoCodeBSetL(void) { ui5r dstvalue = DecodeGetSrcSetDstValueSetZ(); ui5r srcvalue = V_regs.SrcVal & 31; ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1; dstvalue |= (1 << srcvalue); ArgSetDstValue(dstvalue); } LOCALIPROC DoCodeAnd(void) { /* DoBinOpAnd(DecodeI_xxxxxxxxssmmmrrr()); */ ui5r dstvalue = DecodeGetSrcSetDstValue(); dstvalue &= V_regs.SrcVal; /* don't need to extend, since excess high bits all the same as desired high bit. */ V_regs.LazyFlagKind = kLazyFlagsTstL; V_regs.LazyFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(dstvalue); } LOCALIPROC DoCodeOr(void) { /* DoBinOr(DecodeI_xxxxxxxxssmmmrrr()); */ ui5r dstvalue = DecodeGetSrcSetDstValue(); dstvalue |= V_regs.SrcVal; /* don't need to extend, since excess high bits all the same as desired high bit. */ V_regs.LazyFlagKind = kLazyFlagsTstL; V_regs.LazyFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(dstvalue); } LOCALIPROC DoCodeEor(void) { /* Eor 1011ddd1ssmmmrrr */ /* DoBinOpEor(DecodeDEa_xxxxdddxssmmmrrr()); */ ui5r dstvalue = DecodeGetSrcSetDstValue(); dstvalue ^= V_regs.SrcVal; /* don't need to extend, since excess high bits all the same as desired high bit. */ V_regs.LazyFlagKind = kLazyFlagsTstL; V_regs.LazyFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(dstvalue); } LOCALIPROC DoCodeNot(void) { /* Not 01000110ssmmmrrr */ ui5r dstvalue = DecodeGetSetDstValue(); dstvalue = ~ dstvalue; V_regs.LazyFlagKind = kLazyFlagsTstL; V_regs.LazyFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(dstvalue); } LOCALPROC DoCodeScc_t(void) { #if WantCloserCyc if (kAMdRegB == V_regs.CurDecOpY.v[1].AMd) { V_MaxCyclesToGo -= (2 * kCycleScale); } #endif DecodeSetDstValue(0xff); } LOCALPROC DoCodeScc_f(void) { DecodeSetDstValue(0); } LOCALIPROC DoCodeScc(void) { /* Scc 0101cccc11mmmrrr */ cctrue(DoCodeScc_t, DoCodeScc_f); } LOCALIPROC DoCodeEXTL(void) { /* EXT.L */ ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; ui5r dstvalue = ui5r_FromSWord(*dstp); V_regs.LazyFlagKind = kLazyFlagsTstL; V_regs.LazyFlagArgDst = dstvalue; HaveSetUpFlags(); *dstp = dstvalue; } LOCALIPROC DoCodeEXTW(void) { /* EXT.W */ ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; ui5r dstvalue = ui5r_FromSByte(*dstp); V_regs.LazyFlagKind = kLazyFlagsTstL; V_regs.LazyFlagArgDst = dstvalue; HaveSetUpFlags(); #if LittleEndianUnaligned *(ui4b *)dstp = dstvalue; #else *dstp = (*dstp & ~ 0xffff) | (dstvalue & 0xffff); #endif } LOCALIPROC DoCodeNegB(void) { ui5r dstvalue = DecodeGetSetDstValue(); ui5r result = ui5r_FromSByte(0 - dstvalue); V_regs.LazyFlagKind = kLazyFlagsNegB; V_regs.LazyFlagArgDst = dstvalue; V_regs.LazyXFlagKind = kLazyFlagsNegB; V_regs.LazyXFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(result); } LOCALIPROC DoCodeNegW(void) { ui5r dstvalue = DecodeGetSetDstValue(); ui5r result = ui5r_FromSWord(0 - dstvalue); V_regs.LazyFlagKind = kLazyFlagsNegW; V_regs.LazyFlagArgDst = dstvalue; V_regs.LazyXFlagKind = kLazyFlagsNegW; V_regs.LazyXFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(result); } LOCALIPROC DoCodeNegL(void) { ui5r dstvalue = DecodeGetSetDstValue(); ui5r result = ui5r_FromSLong(0 - dstvalue); V_regs.LazyFlagKind = kLazyFlagsNegL; V_regs.LazyFlagArgDst = dstvalue; V_regs.LazyXFlagKind = kLazyFlagsNegL; V_regs.LazyXFlagArgDst = dstvalue; HaveSetUpFlags(); ArgSetDstValue(result); } LOCALPROC my_reg_call SetCCRforNegX(ui5r dstvalue, ui5r result) { ZFLG &= Bool2Bit(result == 0); { flagtype flgs = Bool2Bit(ui5r_MSBisSet(dstvalue)); flagtype flgn = Bool2Bit(ui5r_MSBisSet(result)); NFLG = flgn; VFLG = flgs & flgn; XFLG = CFLG = flgs | flgn; } ArgSetDstValue(result); } LOCALIPROC DoCodeNegXB(void) { NeedDefaultLazyAllFlags(); { ui5r dstvalue = DecodeGetSetDstValue(); ui5r result = ui5r_FromSByte(0 - (XFLG + dstvalue)); SetCCRforNegX(dstvalue, result); } } LOCALIPROC DoCodeNegXW(void) { if ((kLazyFlagsDefault != V_regs.LazyFlagKind) || (kLazyFlagsDefault != V_regs.LazyXFlagKind)) { NeedDefaultLazyAllFlags(); } { ui5r dstvalue = DecodeGetSetDstValue(); ui5r result = ui5r_FromSWord(0 - (XFLG + dstvalue)); SetCCRforNegX(dstvalue, result); } } LOCALIPROC DoCodeNegXL(void) { if (kLazyFlagsNegL == V_regs.LazyFlagKind) { NeedDefaultLazyFlagsNegL(); } else if ((kLazyFlagsDefault == V_regs.LazyFlagKind) && (kLazyFlagsDefault == V_regs.LazyXFlagKind)) { /* ok */ } else { NeedDefaultLazyAllFlags(); } { ui5r dstvalue = DecodeGetSetDstValue(); ui5r result = ui5r_FromSLong(0 - (XFLG + dstvalue)); SetCCRforNegX(dstvalue, result); } } LOCALIPROC DoCodeMulU(void) { /* MulU 1100ddd011mmmrrr */ ui5r srcvalue = DecodeGetSrcValue(); ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; ui5r dstvalue = *dstp; dstvalue = ui5r_FromSLong(ui5r_FromUWord(dstvalue) * ui5r_FromUWord(srcvalue)); #if WantCloserCyc { ui5r v = srcvalue; while (v != 0) { if ((v & 1) != 0) { V_MaxCyclesToGo -= (2 * kCycleScale); } v >>= 1; } } #endif V_regs.LazyFlagKind = kLazyFlagsTstL; V_regs.LazyFlagArgDst = dstvalue; HaveSetUpFlags(); *dstp = dstvalue; } LOCALIPROC DoCodeMulS(void) { /* MulS 1100ddd111mmmrrr */ ui5r srcvalue = DecodeGetSrcValue(); ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; ui5r dstvalue = *dstp; dstvalue = ui5r_FromSLong((si5b)(si4b)dstvalue * (si5b)(si4b)srcvalue); #if WantCloserCyc { ui5r v = (srcvalue << 1); while (v != 0) { if ((v & 1) != ((v >> 1) & 1)) { V_MaxCyclesToGo -= (2 * kCycleScale); } v >>= 1; } } #endif V_regs.LazyFlagKind = kLazyFlagsTstL; V_regs.LazyFlagArgDst = dstvalue; HaveSetUpFlags(); *dstp = dstvalue; } LOCALIPROC DoCodeDivU(void) { /* DivU 1000ddd011mmmrrr */ ui5r srcvalue = DecodeGetSrcValue(); ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; ui5r dstvalue = *dstp; if (srcvalue == 0) { #if WantCloserCyc V_MaxCyclesToGo -= (38 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif Exception(5); #if m68k_logExceptions dbglog_WriteNote("*** zero devide exception"); #endif } else { ui5b newv = (ui5b)dstvalue / (ui5b)(ui4b)srcvalue; ui5b rem = (ui5b)dstvalue % (ui5b)(ui4b)srcvalue; #if WantCloserCyc V_MaxCyclesToGo -= (133 * kCycleScale); #endif if (newv > 0xffff) { NeedDefaultLazyAllFlags(); VFLG = NFLG = 1; CFLG = 0; } else { VFLG = CFLG = 0; ZFLG = Bool2Bit(((si4b)(newv)) == 0); NFLG = Bool2Bit(((si4b)(newv)) < 0); V_regs.LazyFlagKind = kLazyFlagsDefault; newv = (newv & 0xffff) | ((ui5b)rem << 16); dstvalue = newv; } } *dstp = dstvalue; } LOCALIPROC DoCodeDivS(void) { /* DivS 1000ddd111mmmrrr */ ui5r srcvalue = DecodeGetSrcValue(); ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; ui5r dstvalue = *dstp; if (srcvalue == 0) { #if WantCloserCyc V_MaxCyclesToGo -= (38 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif Exception(5); #if m68k_logExceptions dbglog_WriteNote("*** zero devide exception"); #endif } else { si5b newv = (si5b)dstvalue / (si5b)(si4b)srcvalue; ui4b rem = (si5b)dstvalue % (si5b)(si4b)srcvalue; #if WantCloserCyc V_MaxCyclesToGo -= (150 * kCycleScale); #endif if (((newv & 0xffff8000) != 0) && ((newv & 0xffff8000) != 0xffff8000)) { NeedDefaultLazyAllFlags(); VFLG = NFLG = 1; CFLG = 0; } else { if (((si4b)rem < 0) != ((si5b)dstvalue < 0)) { rem = - rem; } VFLG = CFLG = 0; ZFLG = Bool2Bit(((si4b)(newv)) == 0); NFLG = Bool2Bit(((si4b)(newv)) < 0); V_regs.LazyFlagKind = kLazyFlagsDefault; newv = (newv & 0xffff) | ((ui5b)rem << 16); dstvalue = newv; } } *dstp = dstvalue; } LOCALIPROC DoCodeExg(void) { /* Exg dd 1100ddd101000rrr, opsize = 4 */ /* Exg aa 1100ddd101001rrr, opsize = 4 */ /* Exg da 1100ddd110001rrr, opsize = 4 */ ui5r srcreg = V_regs.CurDecOpY.v[0].ArgDat; ui5r *srcp = &V_regs.regs[srcreg]; ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; ui5r srcvalue = *srcp; *srcp = *dstp; *dstp = srcvalue; } LOCALIPROC DoCodeMoveEaCR(void) { /* 0100010011mmmrrr */ m68k_setCR(DecodeGetDstValue()); } LOCALPROC DoPrivilegeViolation(void) { #if WantCloserCyc V_MaxCyclesToGo += GetDcoCycles(V_regs.CurDecOp); V_MaxCyclesToGo -= (34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif BackupPC(); Exception(8); #if m68k_logExceptions dbglog_WriteNote("*** Privilege Violation exception"); #endif } LOCALIPROC DoCodeMoveSREa(void) { /* Move from SR 0100000011mmmrrr */ #if Use68020 if (0 == V_regs.s) { DoPrivilegeViolation(); } else #endif { DecodeSetDstValue(m68k_getSR()); } } LOCALIPROC DoCodeMoveEaSR(void) { /* 0100011011mmmrrr */ if (0 == V_regs.s) { DoPrivilegeViolation(); } else { m68k_setSR(DecodeGetDstValue()); } } LOCALIPROC DoCodeOrISR(void) { if (0 == V_regs.s) { DoPrivilegeViolation(); } else { V_regs.SrcVal = nextiword_nm(); m68k_setSR(m68k_getSR() | V_regs.SrcVal); } } LOCALIPROC DoCodeAndISR(void) { if (0 == V_regs.s) { DoPrivilegeViolation(); } else { V_regs.SrcVal = nextiword_nm(); m68k_setSR(m68k_getSR() & V_regs.SrcVal); } } LOCALIPROC DoCodeEorISR(void) { if (0 == V_regs.s) { DoPrivilegeViolation(); } else { V_regs.SrcVal = nextiword_nm(); m68k_setSR(m68k_getSR() ^ V_regs.SrcVal); } } LOCALIPROC DoCodeOrICCR(void) { V_regs.SrcVal = nextiword_nm(); m68k_setCR(m68k_getCR() | V_regs.SrcVal); } LOCALIPROC DoCodeAndICCR(void) { V_regs.SrcVal = nextiword_nm(); m68k_setCR(m68k_getCR() & V_regs.SrcVal); } LOCALIPROC DoCodeEorICCR(void) { V_regs.SrcVal = nextiword_nm(); m68k_setCR(m68k_getCR() ^ V_regs.SrcVal); } LOCALIPROC DoCodeMOVEMApRW(void) { /* MOVEM mem to reg 01001100110011rrr */ si4b z; ui5r regmask = nextiword_nm(); ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; ui5r p = *dstp; for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { #if WantCloserCyc V_MaxCyclesToGo -= (4 * kCycleScale + RdAvgXtraCyc); #endif V_regs.regs[z] = get_word(p); p += 2; } } *dstp = p; } LOCALIPROC DoCodeMOVEMRmMW(void) { /* MOVEM reg to mem 01001000110100rrr */ si4b z; ui5r regmask = nextiword_nm(); ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; ui5r p = *dstp; #if Use68020 { int n = 0; for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { n++; } } *dstp = p - n * 2; } #endif for (z = 16; --z >= 0; ) { if ((regmask & (1 << (15 - z))) != 0) { #if WantCloserCyc V_MaxCyclesToGo -= (4 * kCycleScale + WrAvgXtraCyc); #endif p -= 2; put_word(p, V_regs.regs[z]); } } #if ! Use68020 *dstp = p; #endif } LOCALIPROC DoCodeMOVEMrmW(void) { /* MOVEM reg to mem 010010001ssmmmrrr */ si4b z; ui5r regmask = nextiword_nm(); ui5r p = DecodeDst(); for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { #if WantCloserCyc V_MaxCyclesToGo -= (4 * kCycleScale + WrAvgXtraCyc); #endif put_word(p, V_regs.regs[z]); p += 2; } } } LOCALIPROC DoCodeMOVEMrmL(void) { /* MOVEM reg to mem 010010001ssmmmrrr */ si4b z; ui5r regmask = nextiword_nm(); ui5r p = DecodeDst(); for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { #if WantCloserCyc V_MaxCyclesToGo -= (8 * kCycleScale + 2 * WrAvgXtraCyc); #endif put_long(p, V_regs.regs[z]); p += 4; } } } LOCALIPROC DoCodeMOVEMmrW(void) { /* MOVEM mem to reg 0100110011smmmrrr */ si4b z; ui5r regmask = nextiword_nm(); ui5r p = DecodeDst(); for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { #if WantCloserCyc V_MaxCyclesToGo -= (4 * kCycleScale + RdAvgXtraCyc); #endif V_regs.regs[z] = get_word(p); p += 2; } } } LOCALIPROC DoCodeMOVEMmrL(void) { /* MOVEM mem to reg 0100110011smmmrrr */ si4b z; ui5r regmask = nextiword_nm(); ui5r p = DecodeDst(); for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { #if WantCloserCyc V_MaxCyclesToGo -= (8 * kCycleScale + 2 * RdAvgXtraCyc); #endif V_regs.regs[z] = get_long(p); p += 4; } } } LOCALIPROC DoCodeAbcd(void) { /* ABCD r 1100ddd100000rrr */ /* ABCD m 1100ddd100001rrr */ ui5r dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm(); ui5r srcvalue = V_regs.SrcVal; { /* if (V_regs.opsize != 1) a bug */ int flgs = ui5r_MSBisSet(srcvalue); int flgo = ui5r_MSBisSet(dstvalue); ui4b newv_lo = (srcvalue & 0xF) + (dstvalue & 0xF) + XFLG; ui4b newv_hi = (srcvalue & 0xF0) + (dstvalue & 0xF0); ui4b newv; if (newv_lo > 9) { newv_lo += 6; } newv = newv_hi + newv_lo; CFLG = XFLG = Bool2Bit((newv & 0x1F0) > 0x90); if (CFLG != 0) { newv += 0x60; } dstvalue = ui5r_FromSByte(newv); if (dstvalue != 0) { ZFLG = 0; } NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); VFLG = Bool2Bit((flgs != flgo) && ((NFLG != 0) != flgo)); /* but according to my reference book, VFLG is Undefined for ABCD */ } ArgSetDstValue(dstvalue); } LOCALIPROC DoCodeSbcd(void) { ui5r dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm(); ui5r srcvalue = V_regs.SrcVal; { int flgs = ui5r_MSBisSet(srcvalue); int flgo = ui5r_MSBisSet(dstvalue); ui4b newv_lo = (dstvalue & 0xF) - (srcvalue & 0xF) - XFLG; ui4b newv_hi = (dstvalue & 0xF0) - (srcvalue & 0xF0); ui4b newv; if (newv_lo > 9) { newv_lo -= 6; newv_hi -= 0x10; } newv = newv_hi + (newv_lo & 0xF); CFLG = XFLG = Bool2Bit((newv_hi & 0x1F0) > 0x90); if (CFLG != 0) { newv -= 0x60; } dstvalue = ui5r_FromSByte(newv); if (dstvalue != 0) { ZFLG = 0; } NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); VFLG = Bool2Bit((flgs != flgo) && ((NFLG != 0) != flgo)); /* but according to my reference book, VFLG is Undefined for SBCD */ } ArgSetDstValue(dstvalue); } LOCALIPROC DoCodeNbcd(void) { /* Nbcd 0100100000mmmrrr */ ui5r dstvalue = DecodeGetSetDstValue(); NeedDefaultLazyAllFlags(); { ui4b newv_lo = - (dstvalue & 0xF) - XFLG; ui4b newv_hi = - (dstvalue & 0xF0); ui4b newv; if (newv_lo > 9) { newv_lo -= 6; newv_hi -= 0x10; } newv = newv_hi + (newv_lo & 0xF); CFLG = XFLG = Bool2Bit((newv_hi & 0x1F0) > 0x90); if (CFLG != 0) { newv -= 0x60; } dstvalue = ui5r_FromSByte(newv); NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue)); if (dstvalue != 0) { ZFLG = 0; } } ArgSetDstValue(dstvalue); } LOCALIPROC DoCodeRte(void) { /* Rte 0100111001110011 */ if (0 == V_regs.s) { DoPrivilegeViolation(); } else { ui5r NewPC; CPTR stackp = m68k_areg(7); ui5r NewSR = get_word(stackp); stackp += 2; NewPC = get_long(stackp); stackp += 4; #if Use68020 { ui4b format = get_word(stackp); stackp += 2; switch ((format >> 12) & 0x0F) { case 0: /* ReportAbnormal("rte stack frame format 0"); */ break; case 1: ReportAbnormalID(0x0107, "rte stack frame format 1"); NewPC = m68k_getpc() - 2; /* rerun instruction */ break; case 2: ReportAbnormalID(0x0108, "rte stack frame format 2"); stackp += 4; break; case 9: ReportAbnormalID(0x0109, "rte stack frame format 9"); stackp += 12; break; case 10: ReportAbnormalID(0x010A, "rte stack frame format 10"); stackp += 24; break; case 11: ReportAbnormalID(0x010B, "rte stack frame format 11"); stackp += 84; break; default: ReportAbnormalID(0x010C, "unknown rte stack frame format"); Exception(14); return; break; } } #endif m68k_areg(7) = stackp; m68k_setSR(NewSR); m68k_setpc(NewPC); } } LOCALIPROC DoCodeNop(void) { /* Nop 0100111001110001 */ } LOCALIPROC DoCodeMoveP0(void) { /* MoveP 0000ddd1mm001aaa */ ui5r srcreg = V_regs.CurDecOpY.v[0].ArgDat; ui5r *srcp = &V_regs.regs[srcreg]; ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; ui5r Displacement = nextiword_nm(); /* shouldn't this sign extend ? */ CPTR memp = *srcp + Displacement; ui4b val = ((get_byte(memp) & 0x00FF) << 8) | (get_byte(memp + 2) & 0x00FF); *dstp = (*dstp & ~ 0xffff) | (val & 0xffff); #if 0 if ((Displacement & 0x00008000) != 0) { /* **** for testing only **** */ BackupPC(); op_illg(); } #endif } LOCALIPROC DoCodeMoveP1(void) { /* MoveP 0000ddd1mm001aaa */ ui5r srcreg = V_regs.CurDecOpY.v[0].ArgDat; ui5r *srcp = &V_regs.regs[srcreg]; ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; ui5r Displacement = nextiword_nm(); /* shouldn't this sign extend ? */ CPTR memp = *srcp + Displacement; ui5b val = ((get_byte(memp) & 0x00FF) << 24) | ((get_byte(memp + 2) & 0x00FF) << 16) | ((get_byte(memp + 4) & 0x00FF) << 8) | (get_byte(memp + 6) & 0x00FF); *dstp = val; } LOCALIPROC DoCodeMoveP2(void) { /* MoveP 0000ddd1mm001aaa */ ui5r srcreg = V_regs.CurDecOpY.v[0].ArgDat; ui5r *srcp = &V_regs.regs[srcreg]; ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; ui5r Displacement = nextiword_nm(); /* shouldn't this sign extend ? */ CPTR memp = *srcp + Displacement; si4b val = *dstp; put_byte(memp, val >> 8); put_byte(memp + 2, val); } LOCALIPROC DoCodeMoveP3(void) { /* MoveP 0000ddd1mm001aaa */ ui5r srcreg = V_regs.CurDecOpY.v[0].ArgDat; ui5r *srcp = &V_regs.regs[srcreg]; ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; ui5r Displacement = nextiword_nm(); /* shouldn't this sign extend ? */ CPTR memp = *srcp + Displacement; si5b val = *dstp; put_byte(memp, val >> 24); put_byte(memp + 2, val >> 16); put_byte(memp + 4, val >> 8); put_byte(memp + 6, val); } LOCALPROC op_illg(void) { BackupPC(); Exception(4); #if m68k_logExceptions dbglog_WriteNote("*** illegal instruction exception"); #endif } LOCALIPROC DoCodeChk(void) { ui5r dstvalue = DecodeGetSrcGetDstValue(); ui5r srcvalue = V_regs.SrcVal; if (ui5r_MSBisSet(srcvalue)) { NeedDefaultLazyAllFlags(); #if WantCloserCyc V_MaxCyclesToGo -= (30 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif NFLG = 1; Exception(6); } else if (((si5r)srcvalue) > ((si5r)dstvalue)) { NeedDefaultLazyAllFlags(); #if WantCloserCyc V_MaxCyclesToGo -= (30 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif NFLG = 0; Exception(6); } } LOCALIPROC DoCodeTrap(void) { /* Trap 010011100100vvvv */ Exception(V_regs.CurDecOpY.v[1].ArgDat); } LOCALIPROC DoCodeTrapV(void) { /* TrapV 0100111001110110 */ NeedDefaultLazyAllFlags(); if (VFLG != 0) { #if WantCloserCyc V_MaxCyclesToGo += GetDcoCycles(V_regs.CurDecOp); V_MaxCyclesToGo -= (34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif Exception(7); } } LOCALIPROC DoCodeRtr(void) { /* Rtr 0100111001110111 */ ui5r NewPC; CPTR stackp = m68k_areg(7); ui5r NewCR = get_word(stackp); stackp += 2; NewPC = get_long(stackp); stackp += 4; m68k_areg(7) = stackp; m68k_setCR(NewCR); m68k_setpc(NewPC); } LOCALIPROC DoCodeLink(void) { ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; CPTR stackp = m68k_areg(7); stackp -= 4; m68k_areg(7) = stackp; /* only matters if dstreg == 7 + 8 */ put_long(stackp, *dstp); *dstp = stackp; m68k_areg(7) += ui5r_FromSWord(nextiword_nm()); } LOCALIPROC DoCodeUnlk(void) { ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; if (dstreg != 7 + 8) { ui5r src = *dstp; *dstp = get_long(src); m68k_areg(7) = src + 4; } else { /* wouldn't expect this to happen */ m68k_areg(7) = get_long(m68k_areg(7)) + 4; } } LOCALIPROC DoCodeMoveRUSP(void) { /* MOVE USP 0100111001100aaa */ if (0 == V_regs.s) { DoPrivilegeViolation(); } else { ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; V_regs.usp = *dstp; } } LOCALIPROC DoCodeMoveUSPR(void) { /* MOVE USP 0100111001101aaa */ if (0 == V_regs.s) { DoPrivilegeViolation(); } else { ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; *dstp = V_regs.usp; } } LOCALIPROC DoCodeTas(void) { /* Tas 0100101011mmmrrr */ ui5r dstvalue = DecodeGetSetDstValue(); V_regs.LazyFlagKind = kLazyFlagsTstL; V_regs.LazyFlagArgDst = dstvalue; HaveSetUpFlags(); dstvalue |= 0x80; ArgSetDstValue(dstvalue); } LOCALIPROC DoCodeFdefault(void) { BackupPC(); Exception(0xB); } LOCALPROC m68k_setstopped(void) { /* not implemented. doesn't seemed to be used on Mac Plus */ Exception(4); /* fake an illegal instruction */ #if m68k_logExceptions dbglog_WriteNote("*** set stopped"); #endif } LOCALIPROC DoCodeStop(void) { /* Stop 0100111001110010 */ if (0 == V_regs.s) { DoPrivilegeViolation(); } else { m68k_setSR(nextiword_nm()); m68k_setstopped(); } } FORWARDPROC local_customreset(void); LOCALIPROC DoCodeReset(void) { /* Reset 0100111001100000 */ if (0 == V_regs.s) { DoPrivilegeViolation(); } else { local_customreset(); } } #if Use68020 LOCALIPROC DoCodeCallMorRtm(void) { /* CALLM or RTM 0000011011mmmrrr */ ReportAbnormalID(0x010D, "CALLM or RTM instruction"); } #endif #if Use68020 LOCALIPROC DoCodeMoveCCREa(void) { /* Move from CCR 0100001011mmmrrr */ DecodeSetDstValue(m68k_getCR()); } #endif #if Use68020 LOCALIPROC DoCodeBraL(void) { /* Bra 0110ccccnnnnnnnn */ si5r offset = ((si5b)(ui5b)nextilong()) - 4; ui3p s = V_pc_p + offset; V_pc_p = s; #if USE_PCLIMIT if (my_cond_rare(s >= V_pc_pHi) || my_cond_rare(s < V_regs.pc_pLo)) { Recalc_PC_Block(); } #endif } #endif #if Use68020 LOCALPROC SkipiLong(void) { V_pc_p += 4; #if USE_PCLIMIT if (my_cond_rare(V_pc_p >= V_pc_pHi)) { Recalc_PC_Block(); } #endif } #endif #if Use68020 LOCALIPROC DoCodeBccL(void) { /* Bcc 0110ccccnnnnnnnn */ cctrue(DoCodeBraL, SkipiLong); } #endif #if Use68020 LOCALIPROC DoCodeBsrL(void) { si5r offset = ((si5b)(ui5b)nextilong()) - 4; ui3p s = V_pc_p + offset; m68k_areg(7) -= 4; put_long(m68k_areg(7), m68k_getpc()); V_pc_p = s; #if USE_PCLIMIT if (my_cond_rare(s >= V_pc_pHi) || my_cond_rare(s < V_regs.pc_pLo)) { Recalc_PC_Block(); } #endif /* ReportAbnormal("long branch in DoCode6"); */ /* Used by various Apps */ } #endif #if Use68020 LOCALIPROC DoCodeEXTBL(void) { /* EXTB.L */ ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; ui5r dstvalue = ui5r_FromSByte(*dstp); V_regs.LazyFlagKind = kLazyFlagsTstL; V_regs.LazyFlagArgDst = dstvalue; HaveSetUpFlags(); *dstp = dstvalue; } #endif #if Use68020 LOCALPROC DoCHK2orCMP2(void) { /* CHK2 or CMP2 00000ss011mmmrrr */ ui5r regv; ui5r lower; ui5r upper; ui5r extra = nextiword_nm(); ui5r DstAddr = DecodeDst(); ui5r srcreg = (extra >> 12) & 0x0F; ui5r *srcp = &V_regs.regs[srcreg]; /* ReportAbnormal("CHK2 or CMP2 instruction"); */ switch (V_regs.CurDecOpY.v[0].ArgDat) { case 1: if ((extra & 0x8000) == 0) { regv = ui5r_FromSByte(*srcp); } else { regv = ui5r_FromSLong(*srcp); } lower = get_byte(DstAddr); upper = get_byte(DstAddr + 1); break; case 2: if ((extra & 0x8000) == 0) { regv = ui5r_FromSWord(*srcp); } else { regv = ui5r_FromSLong(*srcp); } lower = get_word(DstAddr); upper = get_word(DstAddr + 2); break; default: #if ExtraAbnormalReports if (4 != V_regs.CurDecOpY.v[0].ArgDat) { ReportAbnormalID(0x010E, "illegal opsize in CHK2 or CMP2"); } #endif if ((extra & 0x8000) == 0) { regv = ui5r_FromSLong(*srcp); } else { regv = ui5r_FromSLong(*srcp); } lower = get_long(DstAddr); upper = get_long(DstAddr + 4); break; } NeedDefaultLazyAllFlags(); ZFLG = Bool2Bit((upper == regv) || (lower == regv)); CFLG = Bool2Bit((((si5r)lower) <= ((si5r)upper)) ? (((si5r)regv) < ((si5r)lower) || ((si5r)regv) > ((si5r)upper)) : (((si5r)regv) > ((si5r)upper) || ((si5r)regv) < ((si5r)lower))); if ((extra & 0x800) && (CFLG != 0)) { Exception(6); } } #endif #if Use68020 LOCALPROC DoCAS(void) { /* CAS 00001ss011mmmrrr */ ui5r srcvalue; ui5r dstvalue; ui4b src = nextiword_nm(); int ru = (src >> 6) & 7; int rc = src & 7; ReportAbnormalID(0x010F, "CAS instruction"); switch (V_regs.CurDecOpY.v[0].ArgDat) { case 1: srcvalue = ui5r_FromSByte(V_regs.regs[rc]); break; case 2: srcvalue = ui5r_FromSWord(V_regs.regs[rc]); break; default: #if ExtraAbnormalReports if (4 != V_regs.CurDecOpY.v[0].ArgDat) { ReportAbnormalID(0x0110, "illegal opsize in DoCAS"); } #endif srcvalue = ui5r_FromSLong(V_regs.regs[rc]); break; } dstvalue = DecodeGetSetDstValue(); { int flgs = ((si5b)srcvalue) < 0; int flgo = ((si5b)dstvalue) < 0; ui5r newv = dstvalue - srcvalue; if (V_regs.CurDecOpY.v[0].ArgDat == 1) { newv = ui5r_FromSByte(newv); } else if (V_regs.CurDecOpY.v[0].ArgDat == 2) { newv = ui5r_FromSWord(newv); } else { newv = ui5r_FromSLong(newv); } ZFLG = Bool2Bit(((si5b)newv) == 0); NFLG = Bool2Bit(((si5b)newv) < 0); VFLG = Bool2Bit((flgs != flgo) && ((NFLG != 0) != flgo)); CFLG = Bool2Bit( (flgs && ! flgo) || ((NFLG != 0) && ((! flgo) || flgs))); V_regs.LazyFlagKind = kLazyFlagsDefault; if (ZFLG != 0) { ArgSetDstValue(m68k_dreg(ru)); } else { V_regs.ArgAddr.rga = &V_regs.regs[rc]; if (V_regs.CurDecOpY.v[0].ArgDat == 2) { *V_regs.ArgAddr.rga = (*V_regs.ArgAddr.rga & ~ 0xffff) | ((dstvalue) & 0xffff); } else if (V_regs.CurDecOpY.v[0].ArgDat < 2) { *V_regs.ArgAddr.rga = (*V_regs.ArgAddr.rga & ~ 0xff) | ((dstvalue) & 0xff); } else { *V_regs.ArgAddr.rga = dstvalue; } } } } #endif #if Use68020 LOCALPROC DoCAS2(void) { /* CAS2 00001ss011111100 */ ui5b extra = nextilong(); int dc2 = extra & 7; int du2 = (extra >> 6) & 7; int dc1 = (extra >> 16) & 7; int du1 = (extra >> 22) & 7; CPTR rn1 = V_regs.regs[(extra >> 28) & 0x0F]; CPTR rn2 = V_regs.regs[(extra >> 12) & 0x0F]; si5b src = m68k_dreg(dc1); si5r dst1; si5r dst2; ReportAbnormalID(0x0111, "DoCAS2 instruction"); if (V_regs.CurDecOpY.v[0].ArgDat == 2) { dst1 = get_word(rn1); dst2 = get_word(rn2); src = (si5b)(si4b)src; } else { dst1 = get_long(rn1); dst2 = get_long(rn2); } { int flgs = src < 0; int flgo = dst1 < 0; si5b newv = dst1 - src; if (V_regs.CurDecOpY.v[0].ArgDat == 2) { newv = (ui4b)newv; } ZFLG = Bool2Bit(newv == 0); NFLG = Bool2Bit(newv < 0); VFLG = Bool2Bit((flgs != flgo) && ((NFLG != 0) != flgo)); CFLG = Bool2Bit( (flgs && ! flgo) || ((NFLG != 0) && ((! flgo) || flgs))); V_regs.LazyFlagKind = kLazyFlagsDefault; if (ZFLG != 0) { src = m68k_dreg(dc2); if (V_regs.CurDecOpY.v[0].ArgDat == 2) { src = (si5b)(si4b)src; } flgs = src < 0; flgo = dst2 < 0; newv = dst2 - src; if (V_regs.CurDecOpY.v[0].ArgDat == 2) { newv = (ui4b)newv; } ZFLG = Bool2Bit(newv == 0); NFLG = Bool2Bit(newv < 0); VFLG = Bool2Bit((flgs != flgo) && ((NFLG != 0) != flgo)); CFLG = Bool2Bit((flgs && ! flgo) || ((NFLG != 0) && ((! flgo) || flgs))); V_regs.LazyFlagKind = kLazyFlagsDefault; if (ZFLG != 0) { if (V_regs.CurDecOpY.v[0].ArgDat == 2) { put_word(rn1, m68k_dreg(du1)); put_word(rn2, m68k_dreg(du2)); } else { put_word(rn1, m68k_dreg(du1)); put_word(rn2, m68k_dreg(du2)); } } } } if (ZFLG == 0) { if (V_regs.CurDecOpY.v[0].ArgDat == 2) { m68k_dreg(du1) = (m68k_dreg(du1) & ~ 0xffff) | ((ui5b)dst1 & 0xffff); m68k_dreg(du2) = (m68k_dreg(du2) & ~ 0xffff) | ((ui5b)dst2 & 0xffff); } else { m68k_dreg(du1) = dst1; m68k_dreg(du2) = dst2; } } } #endif #if Use68020 LOCALPROC DoMOVES(void) { /* MoveS 00001110ssmmmrrr */ ReportAbnormalID(0x0112, "MoveS instruction"); if (0 == V_regs.s) { DoPrivilegeViolation(); } else { ui4b extra = nextiword_nm(); if (extra & 0x0800) { ui5b src = V_regs.regs[(extra >> 12) & 0x0F]; DecodeSetDstValue(src); } else { ui5r srcvalue = DecodeGetDstValue(); ui5b rr = (extra >> 12) & 7; if (extra & 0x8000) { m68k_areg(rr) = srcvalue; } else { V_regs.ArgAddr.rga = &V_regs.regs[rr]; if (V_regs.CurDecOpY.v[0].ArgDat == 2) { *V_regs.ArgAddr.rga = (*V_regs.ArgAddr.rga & ~ 0xffff) | ((srcvalue) & 0xffff); } else if (V_regs.CurDecOpY.v[0].ArgDat < 2) { *V_regs.ArgAddr.rga = (*V_regs.ArgAddr.rga & ~ 0xff) | ((srcvalue) & 0xff); } else { *V_regs.ArgAddr.rga = srcvalue; } } } } } #endif #define ui5b_lo(x) ((x) & 0x0000FFFF) #define ui5b_hi(x) (((x) >> 16) & 0x0000FFFF) #if Use68020 struct ui6r0 { ui5b hi; ui5b lo; }; typedef struct ui6r0 ui6r0; #endif #if Use68020 LOCALPROC Ui6r_Negate(ui6r0 *v) { v->hi = ~ v->hi; v->lo = - v->lo; if (v->lo == 0) { v->hi++; } } #endif #if Use68020 LOCALFUNC blnr my_reg_call Ui6r_IsZero(ui6r0 *v) { return (v->hi == 0) && (v->lo == 0); } #endif #if Use68020 LOCALFUNC blnr my_reg_call Ui6r_IsNeg(ui6r0 *v) { return ((si5b)v->hi) < 0; } #endif #if Use68020 LOCALPROC mul_unsigned(ui5b src1, ui5b src2, ui6r0 *dst) { ui5b src1_lo = ui5b_lo(src1); ui5b src2_lo = ui5b_lo(src2); ui5b src1_hi = ui5b_hi(src1); ui5b src2_hi = ui5b_hi(src2); ui5b r0 = src1_lo * src2_lo; ui5b r1 = src1_hi * src2_lo; ui5b r2 = src1_lo * src2_hi; ui5b r3 = src1_hi * src2_hi; ui5b ra1 = ui5b_hi(r0) + ui5b_lo(r1) + ui5b_lo(r2); dst->lo = (ui5b_lo(ra1) << 16) | ui5b_lo(r0); dst->hi = ui5b_hi(ra1) + ui5b_hi(r1) + ui5b_hi(r2) + r3; } #endif #if Use68020 LOCALFUNC blnr div_unsigned(ui6r0 *src, ui5b div, ui5b *quot, ui5b *rem) { int i; ui5b q = 0; ui5b cbit = 0; ui5b src_hi = src->hi; ui5b src_lo = src->lo; if (div <= src_hi) { return trueblnr; } for (i = 0 ; i < 32 ; i++) { cbit = src_hi & 0x80000000ul; src_hi <<= 1; if (src_lo & 0x80000000ul) { src_hi++; } src_lo <<= 1; q = q << 1; if (cbit || div <= src_hi) { q |= 1; src_hi -= div; } } *quot = q; *rem = src_hi; return falseblnr; } #endif #if Use68020 LOCALIPROC DoCodeMulL(void) { /* MULU 0100110000mmmrrr 0rrr0s0000000rrr */ /* MULS 0100110000mmmrrr 0rrr1s0000000rrr */ ui6r0 dst; ui4b extra = nextiword(); ui5b r2 = (extra >> 12) & 7; ui5b dstvalue = m68k_dreg(r2); ui5r srcvalue = DecodeGetDstValue(); if (extra & 0x800) { /* MULS.L - signed */ si5b src1 = (si5b)srcvalue; si5b src2 = (si5b)dstvalue; blnr s1 = src1 < 0; blnr s2 = src2 < 0; blnr sr = s1 != s2; /* ReportAbnormal("MULS.L"); */ /* used by Sys 7.5.5 boot extensions */ if (s1) { src1 = - src1; } if (s2) { src2 = - src2; } mul_unsigned((ui5b)src1, (ui5b)src2, &dst); if (sr) { Ui6r_Negate(&dst); } VFLG = CFLG = 0; ZFLG = Bool2Bit(Ui6r_IsZero(&dst)); NFLG = Bool2Bit(Ui6r_IsNeg(&dst)); V_regs.LazyFlagKind = kLazyFlagsDefault; if (extra & 0x400) { m68k_dreg(extra & 7) = dst.hi; } else { if ((dst.lo & 0x80000000) != 0) { if ((dst.hi & 0xffffffff) != 0xffffffff) { VFLG = 1; } } else { if (dst.hi != 0) { VFLG = 1; } } } } else { /* MULU.L - unsigned */ /* ReportAbnormal("MULU.U"); */ /* Used by various Apps */ mul_unsigned(srcvalue, dstvalue, &dst); VFLG = CFLG = 0; ZFLG = Bool2Bit(Ui6r_IsZero(&dst)); NFLG = Bool2Bit(Ui6r_IsNeg(&dst)); V_regs.LazyFlagKind = kLazyFlagsDefault; if (extra & 0x400) { m68k_dreg(extra & 7) = dst.hi; } else { if (dst.hi != 0) { VFLG = 1; } } } m68k_dreg(r2) = dst.lo; } #endif #if Use68020 LOCALIPROC DoCodeDivL(void) { /* DIVU 0100110001mmmrrr 0rrr0s0000000rrr */ /* DIVS 0100110001mmmrrr 0rrr1s0000000rrr */ /* ReportAbnormal("DIVS/DIVU long"); */ ui6r0 v2; ui5b quot; ui5b rem; ui4b extra = nextiword(); ui5b rDr = extra & 7; ui5b rDq = (extra >> 12) & 7; ui5r src = (ui5b)(si5b)DecodeGetDstValue(); if (src == 0) { Exception(5); #if m68k_logExceptions dbglog_WriteNote("*** zero devide exception"); #endif return; } if (0 != (extra & 0x0800)) { /* signed variant */ blnr sr; blnr s2; blnr s1 = ((si5b)src < 0); v2.lo = (si5b)m68k_dreg(rDq); if (extra & 0x0400) { v2.hi = (si5b)m68k_dreg(rDr); } else { v2.hi = ((si5b)v2.lo) < 0 ? -1 : 0; } s2 = Ui6r_IsNeg(&v2); sr = (s1 != s2); if (s2) { Ui6r_Negate(&v2); } if (s1) { src = - src; } if (div_unsigned(&v2, src, ", &rem) || (sr ? quot > 0x80000000 : quot > 0x7fffffff)) { NeedDefaultLazyAllFlags(); VFLG = NFLG = 1; CFLG = 0; } else { if (sr) { quot = - quot; } if (((si5b)rem < 0) != s2) { rem = - rem; } VFLG = CFLG = 0; ZFLG = Bool2Bit(((si5b)quot) == 0); NFLG = Bool2Bit(((si5b)quot) < 0); V_regs.LazyFlagKind = kLazyFlagsDefault; m68k_dreg(rDr) = rem; m68k_dreg(rDq) = quot; } } else { /* unsigned */ v2.lo = (ui5b)m68k_dreg(rDq); if (extra & 0x400) { v2.hi = (ui5b)m68k_dreg(rDr); } else { v2.hi = 0; } if (div_unsigned(&v2, src, ", &rem)) { NeedDefaultLazyAllFlags(); VFLG = NFLG = 1; CFLG = 0; } else { VFLG = CFLG = 0; ZFLG = Bool2Bit(((si5b)quot) == 0); NFLG = Bool2Bit(((si5b)quot) < 0); V_regs.LazyFlagKind = kLazyFlagsDefault; m68k_dreg(rDr) = rem; m68k_dreg(rDq) = quot; } } } #endif #if Use68020 LOCALIPROC DoMoveToControl(void) { if (0 == V_regs.s) { DoPrivilegeViolation(); } else { ui4b src = nextiword_nm(); int regno = (src >> 12) & 0x0F; ui5b v = V_regs.regs[regno]; switch (src & 0x0FFF) { case 0x0000: V_regs.sfc = v & 7; /* ReportAbnormal("DoMoveToControl: sfc"); */ /* happens on entering macsbug */ break; case 0x0001: V_regs.dfc = v & 7; /* ReportAbnormal("DoMoveToControl: dfc"); */ break; case 0x0002: V_regs.cacr = v & 0x3; /* ReportAbnormal("DoMoveToControl: cacr"); */ /* used by Sys 7.5.5 boot */ break; case 0x0800: V_regs.usp = v; ReportAbnormalID(0x0113, "DoMoveToControl: usp"); break; case 0x0801: V_regs.vbr = v; /* ReportAbnormal("DoMoveToControl: vbr"); */ /* happens on entering macsbug */ break; case 0x0802: V_regs.caar = v &0xfc; /* ReportAbnormal("DoMoveToControl: caar"); */ /* happens on entering macsbug */ break; case 0x0803: V_regs.msp = v; if (V_regs.m == 1) { m68k_areg(7) = V_regs.msp; } /* ReportAbnormal("DoMoveToControl: msp"); */ /* happens on entering macsbug */ break; case 0x0804: V_regs.isp = v; if (V_regs.m == 0) { m68k_areg(7) = V_regs.isp; } ReportAbnormalID(0x0114, "DoMoveToControl: isp"); break; default: op_illg(); ReportAbnormalID(0x0115, "DoMoveToControl: unknown reg"); break; } } } #endif #if Use68020 LOCALIPROC DoMoveFromControl(void) { if (0 == V_regs.s) { DoPrivilegeViolation(); } else { ui5b v; ui4b src = nextiword_nm(); int regno = (src >> 12) & 0x0F; switch (src & 0x0FFF) { case 0x0000: v = V_regs.sfc; /* ReportAbnormal("DoMoveFromControl: sfc"); */ /* happens on entering macsbug */ break; case 0x0001: v = V_regs.dfc; /* ReportAbnormal("DoMoveFromControl: dfc"); */ /* happens on entering macsbug */ break; case 0x0002: v = V_regs.cacr; /* ReportAbnormal("DoMoveFromControl: cacr"); */ /* used by Sys 7.5.5 boot */ break; case 0x0800: v = V_regs.usp; ReportAbnormalID(0x0116, "DoMoveFromControl: usp"); break; case 0x0801: v = V_regs.vbr; /* ReportAbnormal("DoMoveFromControl: vbr"); */ /* happens on entering macsbug */ break; case 0x0802: v = V_regs.caar; /* ReportAbnormal("DoMoveFromControl: caar"); */ /* happens on entering macsbug */ break; case 0x0803: v = (V_regs.m == 1) ? m68k_areg(7) : V_regs.msp; /* ReportAbnormal("DoMoveFromControl: msp"); */ /* happens on entering macsbug */ break; case 0x0804: v = (V_regs.m == 0) ? m68k_areg(7) : V_regs.isp; ReportAbnormalID(0x0117, "DoMoveFromControl: isp"); break; default: v = 0; ReportAbnormalID(0x0118, "DoMoveFromControl: unknown reg"); op_illg(); break; } V_regs.regs[regno] = v; } } #endif #if Use68020 LOCALIPROC DoCodeBkpt(void) { /* BKPT 0100100001001rrr */ ReportAbnormalID(0x0119, "BKPT instruction"); op_illg(); } #endif #if Use68020 LOCALIPROC DoCodeRtd(void) { /* Rtd 0100111001110100 */ ui5r NewPC = get_long(m68k_areg(7)); si5b offs = nextiSWord(); /* ReportAbnormal("RTD"); */ /* used by Sys 7.5.5 boot */ m68k_areg(7) += (4 + offs); m68k_setpc(NewPC); } #endif #if Use68020 LOCALIPROC DoCodeLinkL(void) { /* Link.L 0100100000001rrr */ ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui5r *dstp = &V_regs.regs[dstreg]; CPTR stackp = m68k_areg(7); ReportAbnormalID(0x011A, "Link.L"); stackp -= 4; m68k_areg(7) = stackp; /* only matters if dstreg == 7 + 8 */ put_long(stackp, *dstp); *dstp = stackp; m68k_areg(7) += (si5b)nextilong(); } #endif #if Use68020 LOCALPROC DoCodeTRAPcc_t(void) { ReportAbnormalID(0x011B, "TRAPcc trapping"); Exception(7); /* pc pushed onto stack wrong */ } #endif #if Use68020 LOCALPROC DoCodeTRAPcc_f(void) { } #endif #if Use68020 LOCALIPROC DoCodeTRAPcc(void) { /* TRAPcc 0101cccc11111sss */ /* ReportAbnormal("TRAPcc"); */ switch (V_regs.CurDecOpY.v[0].ArgDat) { case 2: ReportAbnormalID(0x011C, "TRAPcc word data"); SkipiWord(); break; case 3: ReportAbnormalID(0x011D, "TRAPcc long data"); SkipiLong(); break; case 4: /* ReportAbnormal("TRAPcc no data"); */ /* no optional data */ break; default: ReportAbnormalID(0x011E, "TRAPcc illegal format"); op_illg(); break; } cctrue(DoCodeTRAPcc_t, DoCodeTRAPcc_f); } #endif #if Use68020 LOCALIPROC DoCodePack(void) { ui5r offs = nextiSWord(); ui5r val = DecodeGetSrcValue(); ReportAbnormalID(0x011F, "PACK"); val += offs; val = ((val >> 4) & 0xf0) | (val & 0xf); DecodeSetDstValue(val); } #endif #if Use68020 LOCALIPROC DoCodeUnpk(void) { ui5r offs = nextiSWord(); ui5r val = DecodeGetSrcValue(); ReportAbnormalID(0x0120, "UNPK"); val = (((val & 0xF0) << 4) | (val & 0x0F)) + offs; DecodeSetDstValue(val); } #endif #if Use68020 LOCALIPROC DoBitField(void) { ui5b tmp; ui5b newtmp; si5b dsta; ui5b bf0; ui3b bf1; ui5b dstreg = V_regs.CurDecOpY.v[1].ArgDat; ui4b extra = nextiword(); si5b offset = ((extra & 0x0800) != 0) ? m68k_dreg((extra >> 6) & 7) : ((extra >> 6) & 0x1f); ui5b width = ((extra & 0x0020) != 0) ? m68k_dreg(extra & 7) : extra; ui3b bfa[5]; ui5b offwid; /* ReportAbnormal("Bit Field operator"); */ /* width = ((width - 1) & 0x1f) + 1; */ /* 0 -> 32 */ width &= 0x001F; /* except width == 0 really means 32 */ if (V_regs.CurDecOpY.v[0].AMd == 0) { bf0 = m68k_dreg(dstreg); offset &= 0x1f; tmp = bf0; if (0 != offset) { tmp = (tmp << offset) | (tmp >> (32 - offset)); } } else { /* V_regs.ArgKind == AKMemory, otherwise illegal and don't get here */ dsta = DecodeDst(); dsta += (offset >> 3) | (offset & 0x80000000 ? ~ 0x1fffffff : 0); offset &= 7; offwid = offset + ((width == 0) ? 32 : width); /* if (offwid > 0) */ { bf1 = get_byte(dsta); bfa[0] = bf1; tmp = ((ui5b)bf1) << (24 + offset); } if (offwid > 8) { bf1 = get_byte(dsta + 1); bfa[1] = bf1; tmp |= ((ui5b)bf1) << (16 + offset); } if (offwid > 16) { bf1 = get_byte(dsta + 2); bfa[2] = bf1; tmp |= ((ui5r)bf1) << (8 + offset); } if (offwid > 24) { bf1 = get_byte(dsta + 3); bfa[3] = bf1; tmp |= ((ui5r)bf1) << (offset); } if (offwid > 32) { bf1 = get_byte(dsta + 4); bfa[4] = bf1; tmp |= ((ui5r)bf1) >> (8 - offset); } } NFLG = Bool2Bit(((si5b)tmp) < 0); if (width != 0) { tmp >>= (32 - width); } ZFLG = tmp == 0; VFLG = 0; CFLG = 0; V_regs.LazyFlagKind = kLazyFlagsDefault; newtmp = tmp; switch (V_regs.CurDecOpY.v[0].ArgDat) { case 0: /* BFTST */ /* do nothing */ break; case 1: /* BFEXTU */ m68k_dreg((extra >> 12) & 7) = tmp; break; case 2: /* BFCHG */ newtmp = ~ newtmp; if (width != 0) { newtmp &= ((1 << width) - 1); } break; case 3: /* BFEXTS */ if (NFLG != 0) { m68k_dreg((extra >> 12) & 7) = tmp | ((width == 0) ? 0 : (-1 << width)); } else { m68k_dreg((extra >> 12) & 7) = tmp; } break; case 4: /* BFCLR */ newtmp = 0; break; case 5: /* BFFFO */ { ui5b mask = 1 << ((width == 0) ? 31 : (width - 1)); si5b i = offset; while ((0 != mask) && (0 == (tmp & mask))) { mask >>= 1; i++; } m68k_dreg((extra >> 12) & 7) = i; } break; case 6: /* BFSET */ newtmp = (width == 0) ? ~ 0 : ((1 << width) - 1); break; case 7: /* BFINS */ newtmp = m68k_dreg((extra >> 12) & 7); if (width != 0) { newtmp &= ((1 << width) - 1); } break; } if (newtmp != tmp) { if (width != 0) { newtmp <<= (32 - width); } if (V_regs.CurDecOpY.v[0].AMd == 0) { ui5b mask = ~ 0; if (width != 0) { mask <<= (32 - width); } if (0 != offset) { newtmp = (newtmp >> offset) | (newtmp << (32 - offset)); mask = (mask >> offset) | (mask << (32 - offset)); } bf0 = (bf0 & ~ mask) | (newtmp); m68k_dreg(dstreg) = bf0; } else { /* if (offwid > 0) */ { ui3b mask = ~ (0xFF >> offset); bf1 = newtmp >> (24 + offset); if (offwid < 8) { mask |= (0xFF >> offwid); } if (mask != 0) { bf1 |= bfa[0] & mask; } put_byte(dsta + 0, bf1); } if (offwid > 8) { bf1 = newtmp >> (16 + offset); if (offwid < 16) { bf1 |= (bfa[1] & (0xFF >> (offwid - 8))); } put_byte(dsta + 1, bf1); } if (offwid > 16) { bf1 = newtmp >> (8 + offset); if (offwid < 24) { bf1 |= (bfa[2] & (0xFF >> (offwid - 16))); } put_byte(dsta + 2, bf1); } if (offwid > 24) { bf1 = newtmp >> (offset); if (offwid < 32) { bf1 |= (bfa[3] & (0xFF >> (offwid - 24))); } put_byte(dsta + 3, bf1); } if (offwid > 32) { bf1 = newtmp << (8 - offset); bf1 |= (bfa[4] & (0xFF >> (offwid - 32))); put_byte(dsta + 4, bf1); } } } } #endif #if EmMMU | EmFPU LOCALFUNC blnr DecodeModeRegister(ui5b sz) { blnr IsOk; ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat; ui4r themode = (Dat >> 3) & 7; ui4r thereg = Dat & 7; switch (themode) { case 0 : V_regs.ArgKind = AKRegister; V_regs.ArgAddr.rga = &V_regs.regs[thereg]; IsOk = trueblnr; break; case 1 : V_regs.ArgKind = AKRegister; V_regs.ArgAddr.rga = &V_regs.regs[thereg + 8]; IsOk = trueblnr; break; case 2 : V_regs.ArgKind = AKMemory; V_regs.ArgAddr.mem = m68k_areg(thereg); IsOk = trueblnr; break; case 3 : V_regs.ArgKind = AKMemory; V_regs.ArgAddr.mem = m68k_areg(thereg); if ((thereg == 7) && (sz == 1)) { m68k_areg(thereg) += 2; } else { m68k_areg(thereg) += sz; } IsOk = trueblnr; break; case 4 : V_regs.ArgKind = AKMemory; if ((thereg == 7) && (sz == 1)) { m68k_areg(thereg) -= 2; } else { m68k_areg(thereg) -= sz; } V_regs.ArgAddr.mem = m68k_areg(thereg); IsOk = trueblnr; break; case 5 : V_regs.ArgKind = AKMemory; V_regs.ArgAddr.mem = m68k_areg(thereg) + nextiSWord(); IsOk = trueblnr; break; case 6 : V_regs.ArgKind = AKMemory; V_regs.ArgAddr.mem = get_disp_ea(m68k_areg(thereg)); IsOk = trueblnr; break; case 7 : switch (thereg) { case 0 : V_regs.ArgKind = AKMemory; V_regs.ArgAddr.mem = nextiSWord(); IsOk = trueblnr; break; case 1 : V_regs.ArgKind = AKMemory; V_regs.ArgAddr.mem = nextilong(); IsOk = trueblnr; break; case 2 : V_regs.ArgKind = AKMemory; V_regs.ArgAddr.mem = m68k_getpc(); V_regs.ArgAddr.mem += nextiSWord(); IsOk = trueblnr; break; case 3 : V_regs.ArgKind = AKMemory; V_regs.ArgAddr.mem = get_disp_ea(m68k_getpc()); IsOk = trueblnr; break; case 4 : V_regs.ArgKind = AKMemory; V_regs.ArgAddr.mem = m68k_getpc(); if (sz == 1) { ++V_regs.ArgAddr.mem; } m68k_setpc(V_regs.ArgAddr.mem + sz); IsOk = trueblnr; break; default: IsOk = falseblnr; break; } break; default: IsOk = falseblnr; break; } return IsOk; } #endif #if EmMMU | EmFPU LOCALFUNC ui5r GetArgValueL(void) { ui5r v; if (AKMemory == V_regs.ArgKind) { v = get_long(V_regs.ArgAddr.mem); } else { /* must be AKRegister */ v = ui5r_FromSLong(*V_regs.ArgAddr.rga); } return v; } #endif #if EmMMU | EmFPU LOCALFUNC ui5r GetArgValueW(void) { ui5r v; if (AKMemory == V_regs.ArgKind) { v = get_word(V_regs.ArgAddr.mem); } else { /* must be AKRegister */ v = ui5r_FromSWord(*V_regs.ArgAddr.rga); } return v; } #endif #if EmMMU | EmFPU LOCALFUNC ui5r GetArgValueB(void) { ui5r v; if (AKMemory == V_regs.ArgKind) { v = get_byte(V_regs.ArgAddr.mem); } else { /* must be AKRegister */ v = ui5r_FromSByte(*V_regs.ArgAddr.rga); } return v; } #endif #if EmMMU | EmFPU LOCALPROC SetArgValueL(ui5r v) { if (AKMemory == V_regs.ArgKind) { put_long(V_regs.ArgAddr.mem, v); } else { /* must be AKRegister */ *V_regs.ArgAddr.rga = v; } } #endif #if EmMMU | EmFPU LOCALPROC SetArgValueW(ui5r v) { if (AKMemory == V_regs.ArgKind) { put_word(V_regs.ArgAddr.mem, v); } else { /* must be AKRegister */ *V_regs.ArgAddr.rga = (*V_regs.ArgAddr.rga & ~ 0xffff) | ((v) & 0xffff); } } #endif #if EmMMU | EmFPU LOCALPROC SetArgValueB(ui5r v) { if (AKMemory == V_regs.ArgKind) { put_byte(V_regs.ArgAddr.mem, v); } else { /* must be AKRegister */ *V_regs.ArgAddr.rga = (*V_regs.ArgAddr.rga & ~ 0xff) | ((v) & 0xff); } } #endif #if EmMMU LOCALIPROC DoCodeMMU(void) { /* Emulate enough of MMU for System 7.5.5 universal to boot on Mac Plus 68020. There is one spurious "PMOVE TC, (A0)". And implement a few more PMOVE operations seen when running Disk Copy 6.3.3 and MacsBug. */ ui4r opcode = ((ui4r)(V_regs.CurDecOpY.v[0].AMd) << 8) | V_regs.CurDecOpY.v[0].ArgDat; if (opcode == 0xF010) { ui4b ew = (int)nextiword_nm(); if (ew == 0x4200) { /* PMOVE TC, (A0) */ /* fprintf(stderr, "0xF010 0x4200\n"); */ if (DecodeModeRegister(4)) { SetArgValueL(0); return; } } else if ((ew == 0x4E00) || (ew == 0x4A00)) { /* PMOVE CRP, (A0) and PMOVE SRP, (A0) */ /* fprintf(stderr, "0xF010 %x\n", ew); */ if (DecodeModeRegister(4)) { SetArgValueL(0x7FFF0001); V_regs.ArgAddr.mem += 4; SetArgValueL(0); return; } } else if (ew == 0x6200) { /* PMOVE MMUSR, (A0) */ /* fprintf(stderr, "0xF010 %x\n", ew); */ if (DecodeModeRegister(2)) { SetArgValueW(0); return; } } /* fprintf(stderr, "extensions %x\n", ew); */ BackupPC(); } /* fprintf(stderr, "opcode %x\n", (int)opcode); */ ReportAbnormalID(0x0121, "MMU op"); DoCodeFdefault(); } #endif #if EmFPU #include "FPMATHEM.h" #include "FPCPEMDV.h" #endif #if HaveGlbReg LOCALPROC Em_Swap(void) { #ifdef r_pc_p { ui3p t = g_pc_p; g_pc_p = regs.pc_p; regs.pc_p = t; } #endif #ifdef r_MaxCyclesToGo { si5rr t = g_MaxCyclesToGo; g_MaxCyclesToGo = regs.MaxCyclesToGo; regs.MaxCyclesToGo = t; } #endif #ifdef r_pc_pHi { ui3p t = g_pc_pHi; g_pc_pHi = regs.pc_pHi; regs.pc_pHi = t; } #endif #ifdef r_regs { struct regstruct *t = g_regs; g_regs = regs.save_regs; regs.save_regs = t; } #endif } #endif #if HaveGlbReg #define Em_Enter Em_Swap #else #define Em_Enter() #endif #if HaveGlbReg #define Em_Exit Em_Swap #else #define Em_Exit() #endif #if HaveGlbReg LOCALFUNC blnr LocalMemAccessNtfy(ATTep pT) { blnr v; Em_Exit(); v = MemAccessNtfy(pT); Em_Enter(); return v; } #else #define LocalMemAccessNtfy MemAccessNtfy #endif #if HaveGlbReg LOCALFUNC ui5b LocalMMDV_Access(ATTep p, ui5b Data, blnr WriteMem, blnr ByteSize, CPTR addr) { ui5b v; Em_Exit(); v = MMDV_Access(p, Data, WriteMem, ByteSize, addr); Em_Enter(); return v; } #else #define LocalMMDV_Access MMDV_Access #endif LOCALPROC local_customreset(void) { Em_Exit(); customreset(); Em_Enter(); } LOCALFUNC ATTep LocalFindATTel(CPTR addr) { ATTep prev; ATTep p; p = V_regs.HeadATTel; if ((addr & p->cmpmask) != p->cmpvalu) { do { prev = p; p = p->Next; } while ((addr & p->cmpmask) != p->cmpvalu); { ATTep next = p->Next; if (nullpr == next) { /* don't move the end guard */ } else { /* move to first */ prev->Next = next; p->Next = V_regs.HeadATTel; V_regs.HeadATTel = p; } } } return p; } LOCALPROC SetUpMATC( MATCp CurMATC, ATTep p) { CurMATC->cmpmask = p->cmpmask; CurMATC->usemask = p->usemask; CurMATC->cmpvalu = p->cmpvalu; CurMATC->usebase = p->usebase; } LOCALFUNC ui5r my_reg_call get_byte_ext(CPTR addr) { ATTep p; ui3p m; ui5r AccFlags; ui5r Data; Label_Retry: p = LocalFindATTel(addr); AccFlags = p->Access; if (0 != (AccFlags & kATTA_readreadymask)) { SetUpMATC(&V_regs.MATCrdB, p); m = p->usebase + (addr & p->usemask); Data = *m; } else if (0 != (AccFlags & kATTA_mmdvmask)) { Data = LocalMMDV_Access(p, 0, falseblnr, trueblnr, addr); } else if (0 != (AccFlags & kATTA_ntfymask)) { if (LocalMemAccessNtfy(p)) { goto Label_Retry; } else { Data = 0; /* fail */ } } else { Data = 0; /* fail */ } return ui5r_FromSByte(Data); } LOCALPROC my_reg_call put_byte_ext(CPTR addr, ui5r b) { ATTep p; ui3p m; ui5r AccFlags; Label_Retry: p = LocalFindATTel(addr); AccFlags = p->Access; if (0 != (AccFlags & kATTA_writereadymask)) { SetUpMATC(&V_regs.MATCwrB, p); m = p->usebase + (addr & p->usemask); *m = b; } else if (0 != (AccFlags & kATTA_mmdvmask)) { (void) LocalMMDV_Access(p, b & 0x00FF, trueblnr, trueblnr, addr); } else if (0 != (AccFlags & kATTA_ntfymask)) { if (LocalMemAccessNtfy(p)) { goto Label_Retry; } else { /* fail */ } } else { /* fail */ } } LOCALFUNC ui5r my_reg_call get_word_ext(CPTR addr) { ui5r Data; if (0 != (addr & 0x01)) { ui5r hi = get_byte(addr); ui5r lo = get_byte(addr + 1); Data = ((hi << 8) & 0x0000FF00) | (lo & 0x000000FF); } else { ATTep p; ui3p m; ui5r AccFlags; Label_Retry: p = LocalFindATTel(addr); AccFlags = p->Access; if (0 != (AccFlags & kATTA_readreadymask)) { SetUpMATC(&V_regs.MATCrdW, p); V_regs.MATCrdW.cmpmask |= 0x01; m = p->usebase + (addr & p->usemask); Data = do_get_mem_word(m); } else if (0 != (AccFlags & kATTA_mmdvmask)) { Data = LocalMMDV_Access(p, 0, falseblnr, falseblnr, addr); } else if (0 != (AccFlags & kATTA_ntfymask)) { if (LocalMemAccessNtfy(p)) { goto Label_Retry; } else { Data = 0; /* fail */ } } else { Data = 0; /* fail */ } } return ui5r_FromSWord(Data); } LOCALPROC my_reg_call put_word_ext(CPTR addr, ui5r w) { if (0 != (addr & 0x01)) { put_byte(addr, w >> 8); put_byte(addr + 1, w); } else { ATTep p; ui3p m; ui5r AccFlags; Label_Retry: p = LocalFindATTel(addr); AccFlags = p->Access; if (0 != (AccFlags & kATTA_writereadymask)) { SetUpMATC(&V_regs.MATCwrW, p); V_regs.MATCwrW.cmpmask |= 0x01; m = p->usebase + (addr & p->usemask); do_put_mem_word(m, w); } else if (0 != (AccFlags & kATTA_mmdvmask)) { (void) LocalMMDV_Access(p, w & 0x0000FFFF, trueblnr, falseblnr, addr); } else if (0 != (AccFlags & kATTA_ntfymask)) { if (LocalMemAccessNtfy(p)) { goto Label_Retry; } else { /* fail */ } } else { /* fail */ } } } LOCALFUNC ui5r my_reg_call get_long_misaligned_ext(CPTR addr) { ui5r hi = get_word(addr); ui5r lo = get_word(addr + 2); ui5r Data = ((hi << 16) & 0xFFFF0000) | (lo & 0x0000FFFF); return ui5r_FromSLong(Data); } LOCALPROC my_reg_call put_long_misaligned_ext(CPTR addr, ui5r l) { put_word(addr, l >> 16); put_word(addr + 2, l); } #if FasterAlignedL LOCALFUNC ui5r my_reg_call get_long_ext(CPTR addr) { ui5r Data; if (0 != (addr & 0x03)) { ui5r hi = get_word(addr); ui5r lo = get_word(addr + 2); Data = ((hi << 16) & 0xFFFF0000) | (lo & 0x0000FFFF); } else { ATTep p; ui3p m; ui5r AccFlags; Label_Retry: p = LocalFindATTel(addr); AccFlags = p->Access; if (0 != (AccFlags & kATTA_readreadymask)) { SetUpMATC(&V_regs.MATCrdL, p); V_regs.MATCrdL.cmpmask |= 0x03; m = p->usebase + (addr & p->usemask); Data = do_get_mem_long(m); } else if (0 != (AccFlags & kATTA_mmdvmask)) { ui5r hi = LocalMMDV_Access(p, 0, falseblnr, falseblnr, addr); ui5r lo = LocalMMDV_Access(p, 0, falseblnr, falseblnr, addr + 2); Data = ((hi << 16) & 0xFFFF0000) | (lo & 0x0000FFFF); } else if (0 != (AccFlags & kATTA_ntfymask)) { if (LocalMemAccessNtfy(p)) { goto Label_Retry; } else { Data = 0; /* fail */ } } else { Data = 0; /* fail */ } } return ui5r_FromSLong(Data); } #endif #if FasterAlignedL LOCALPROC my_reg_call put_long_ext(CPTR addr, ui5r l) { if (0 != (addr & 0x03)) { put_word(addr, l >> 16); put_word(addr + 2, l); } else { ATTep p; ui3p m; ui5r AccFlags; Label_Retry: p = LocalFindATTel(addr); AccFlags = p->Access; if (0 != (AccFlags & kATTA_writereadymask)) { SetUpMATC(&V_regs.MATCwrL, p); V_regs.MATCwrL.cmpmask |= 0x03; m = p->usebase + (addr & p->usemask); do_put_mem_long(m, l); } else if (0 != (AccFlags & kATTA_mmdvmask)) { (void) LocalMMDV_Access(p, (l >> 16) & 0x0000FFFF, trueblnr, falseblnr, addr); (void) LocalMMDV_Access(p, l & 0x0000FFFF, trueblnr, falseblnr, addr + 2); } else if (0 != (AccFlags & kATTA_ntfymask)) { if (LocalMemAccessNtfy(p)) { goto Label_Retry; } else { /* fail */ } } else { /* fail */ } } } #endif LOCALPROC Recalc_PC_Block(void) { ATTep p; CPTR curpc = m68k_getpc(); Label_Retry: p = LocalFindATTel(curpc); if (my_cond_rare(0 == (p->Access & kATTA_readreadymask))) { if (0 != (p->Access & kATTA_ntfymask)) { if (LocalMemAccessNtfy(p)) { goto Label_Retry; } } /* in trouble if get here */ #if ExtraAbnormalReports ReportAbnormalID(0x0122, "Recalc_PC_Block fails"); /* happens on Restart */ #endif V_regs.pc_pLo = V_regs.fakeword; V_pc_p = V_regs.pc_pLo; V_pc_pHi = V_regs.pc_pLo + 2; V_regs.pc = curpc; } else { ui5r m2 = p->usemask & ~ p->cmpmask; m2 = m2 & ~ (m2 + 1); V_pc_p = p->usebase + (curpc & p->usemask); V_regs.pc_pLo = V_pc_p - (curpc & m2); V_pc_pHi = V_regs.pc_pLo + m2 + 1; V_regs.pc = curpc - (V_pc_p - V_regs.pc_pLo); } } LOCALFUNC ui5r my_reg_call Recalc_PC_BlockReturnUi5r(ui5r v) { /* Used to prevent compiler from saving register on the stack in calling functions, when Recalc_PC_Block isn't being called. */ Recalc_PC_Block(); return v; } LOCALFUNC ui5r nextilong_ext(void) { ui5r r; V_pc_p -= 4; { ui5r hi = nextiword(); ui5r lo = nextiword(); r = ((hi << 16) & 0xFFFF0000) | (lo & 0x0000FFFF); } return r; } LOCALPROC DoCheckExternalInterruptPending(void) { ui3r level = *V_regs.fIPL; if ((level > V_regs.intmask) || (level == 7)) { #if WantCloserCyc V_MaxCyclesToGo -= (44 * kCycleScale + 5 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif Exception(24 + level); V_regs.intmask = level; } } LOCALPROC do_trace(void) { V_regs.TracePending = trueblnr; NeedToGetOut(); } GLOBALPROC m68k_go_nCycles(ui5b n) { Em_Enter(); V_MaxCyclesToGo += (n + V_regs.ResidualCycles); while (V_MaxCyclesToGo > 0) { #if 0 if (V_regs.ResetPending) { m68k_DoReset(); } #endif if (V_regs.TracePending) { #if WantCloserCyc V_MaxCyclesToGo -= (34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc); #endif Exception(9); } if (V_regs.ExternalInterruptPending) { V_regs.ExternalInterruptPending = falseblnr; DoCheckExternalInterruptPending(); } if (V_regs.t1 != 0) { do_trace(); } m68k_go_MaxCycles(); V_MaxCyclesToGo += V_regs.MoreCyclesToGo; V_regs.MoreCyclesToGo = 0; } V_regs.ResidualCycles = V_MaxCyclesToGo; V_MaxCyclesToGo = 0; Em_Exit(); } GLOBALFUNC si5r GetCyclesRemaining(void) { si5r v; Em_Enter(); v = V_regs.MoreCyclesToGo + V_MaxCyclesToGo; Em_Exit(); return v; } GLOBALPROC SetCyclesRemaining(si5r n) { Em_Enter(); if (V_MaxCyclesToGo >= n) { V_regs.MoreCyclesToGo = 0; V_MaxCyclesToGo = n; } else { V_regs.MoreCyclesToGo = n - V_MaxCyclesToGo; } Em_Exit(); } GLOBALFUNC ATTep FindATTel(CPTR addr) { ATTep v; Em_Enter(); v = LocalFindATTel(addr); Em_Exit(); return v; } GLOBALFUNC ui3r get_vm_byte(CPTR addr) { ui3r v; Em_Enter(); v = (ui3b) get_byte(addr); Em_Exit(); return v; } GLOBALFUNC ui4r get_vm_word(CPTR addr) { ui4r v; Em_Enter(); v = (ui4b) get_word(addr); Em_Exit(); return v; } GLOBALFUNC ui5r get_vm_long(CPTR addr) { ui5r v; Em_Enter(); v = (ui5b) get_long(addr); Em_Exit(); return v; } GLOBALPROC put_vm_byte(CPTR addr, ui3r b) { Em_Enter(); put_byte(addr, ui5r_FromSByte(b)); Em_Exit(); } GLOBALPROC put_vm_word(CPTR addr, ui4r w) { Em_Enter(); put_word(addr, ui5r_FromSWord(w)); Em_Exit(); } GLOBALPROC put_vm_long(CPTR addr, ui5r l) { Em_Enter(); put_long(addr, ui5r_FromSLong(l)); Em_Exit(); } GLOBALPROC SetHeadATTel(ATTep p) { Em_Enter(); V_regs.MATCrdB.cmpmask = 0; V_regs.MATCrdB.cmpvalu = 0xFFFFFFFF; V_regs.MATCwrB.cmpmask = 0; V_regs.MATCwrB.cmpvalu = 0xFFFFFFFF; V_regs.MATCrdW.cmpmask = 0; V_regs.MATCrdW.cmpvalu = 0xFFFFFFFF; V_regs.MATCwrW.cmpmask = 0; V_regs.MATCwrW.cmpvalu = 0xFFFFFFFF; #if FasterAlignedL V_regs.MATCrdL.cmpmask = 0; V_regs.MATCrdL.cmpvalu = 0xFFFFFFFF; V_regs.MATCwrL.cmpmask = 0; V_regs.MATCwrL.cmpvalu = 0xFFFFFFFF; #endif /* force Recalc_PC_Block soon */ V_regs.pc = m68k_getpc(); V_regs.pc_pLo = V_pc_p; V_pc_pHi = V_regs.pc_pLo + 2; V_regs.HeadATTel = p; Em_Exit(); } GLOBALPROC DiskInsertedPsuedoException(CPTR newpc, ui5b data) { Em_Enter(); ExceptionTo(newpc #if Use68020 , 0 #endif ); m68k_areg(7) -= 4; put_long(m68k_areg(7), data); Em_Exit(); } GLOBALPROC m68k_IPLchangeNtfy(void) { Em_Enter(); { ui3r level = *V_regs.fIPL; if ((level > V_regs.intmask) || (level == 7)) { SetExternalInterruptPending(); } } Em_Exit(); } #if WantDumpTable LOCALPROC InitDumpTable(void) { si5b i; for (i = 0; i < kNumIKinds; ++i) { DumpTable[i] = 0; } } LOCALPROC DumpATable(ui5b *p, ui5b n) { si5b i; for (i = 0; i < n; ++i) { dbglog_writeNum(p[i]); dbglog_writeReturn(); } } EXPORTPROC DoDumpTable(void); GLOBALPROC DoDumpTable(void) { DumpATable(DumpTable, kNumIKinds); } #endif GLOBALPROC m68k_reset(void) { Em_Enter(); #if WantDumpTable InitDumpTable(); #endif V_MaxCyclesToGo = 0; V_regs.MoreCyclesToGo = 0; V_regs.ResidualCycles = 0; V_pc_p = (ui3p)nullpr; V_pc_pHi = (ui3p)nullpr; V_regs.pc_pLo = (ui3p)nullpr; do_put_mem_word(V_regs.fakeword, 0x4AFC); /* illegal instruction opcode */ #if 0 V_regs.ResetPending = trueblnr; NeedToGetOut(); #else /* Sets the MC68000 reset jump vector... */ m68k_setpc(get_long(0x00000004)); /* Sets the initial stack vector... */ m68k_areg(7) = get_long(0x00000000); V_regs.s = 1; #if Use68020 V_regs.m = 0; V_regs.t0 = 0; #endif V_regs.t1 = 0; ZFLG = CFLG = NFLG = VFLG = 0; V_regs.LazyFlagKind = kLazyFlagsDefault; V_regs.LazyXFlagKind = kLazyFlagsDefault; V_regs.ExternalInterruptPending = falseblnr; V_regs.TracePending = falseblnr; V_regs.intmask = 7; #if Use68020 V_regs.sfc = 0; V_regs.dfc = 0; V_regs.vbr = 0; V_regs.cacr = 0; V_regs.caar = 0; #endif #endif Em_Exit(); } #if SmallGlobals GLOBALPROC MINEM68K_ReserveAlloc(void) { ReserveAllocOneBlock((ui3p *)®s.disp_table, disp_table_sz * 8, 6, falseblnr); } #endif GLOBALPROC MINEM68K_Init( ui3b *fIPL) { regs.fIPL = fIPL; #ifdef r_regs regs.save_regs = ®s; #endif M68KITAB_setup(regs.disp_table); } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/MINEM68K.h b/Mini vMac/mnvm_core/MINEM68K.h index 21b173d..47250ac 100755 --- a/Mini vMac/mnvm_core/MINEM68K.h +++ b/Mini vMac/mnvm_core/MINEM68K.h @@ -1,53 +1 @@ -/* - MINEM68K.h - - Copyright (C) 2004 Bernd Schmidt, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef MINEM68K_H -#error "header already included" -#else -#define MINEM68K_H -#endif - -EXPORTPROC MINEM68K_Init( - ui3b *fIPL); -#if SmallGlobals -EXPORTPROC MINEM68K_ReserveAlloc(void); -#endif - -EXPORTPROC m68k_IPLchangeNtfy(void); -EXPORTPROC DiskInsertedPsuedoException(CPTR newpc, ui5b data); -EXPORTPROC m68k_reset(void); - -EXPORTFUNC si5r GetCyclesRemaining(void); -EXPORTPROC SetCyclesRemaining(si5r n); - -EXPORTPROC m68k_go_nCycles(ui5b n); - -/* - general purpose access of address space - of emulated computer. (memory and - memory mapped hardware.) -*/ - -EXPORTFUNC ui3r get_vm_byte(CPTR addr); -EXPORTFUNC ui4r get_vm_word(CPTR addr); -EXPORTFUNC ui5r get_vm_long(CPTR addr); - -EXPORTPROC put_vm_byte(CPTR addr, ui3r b); -EXPORTPROC put_vm_word(CPTR addr, ui4r w); -EXPORTPROC put_vm_long(CPTR addr, ui5r l); - -EXPORTPROC SetHeadATTel(ATTep p); -EXPORTFUNC ATTep FindATTel(CPTR addr); +/* MINEM68K.h Copyright (C) 2004 Bernd Schmidt, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef MINEM68K_H #error "header already included" #else #define MINEM68K_H #endif EXPORTPROC MINEM68K_Init( ui3b *fIPL); #if SmallGlobals EXPORTPROC MINEM68K_ReserveAlloc(void); #endif EXPORTPROC m68k_IPLchangeNtfy(void); EXPORTPROC DiskInsertedPsuedoException(CPTR newpc, ui5b data); EXPORTPROC m68k_reset(void); EXPORTFUNC si5r GetCyclesRemaining(void); EXPORTPROC SetCyclesRemaining(si5r n); EXPORTPROC m68k_go_nCycles(ui5b n); /* general purpose access of address space of emulated computer. (memory and memory mapped hardware.) */ EXPORTFUNC ui3r get_vm_byte(CPTR addr); EXPORTFUNC ui4r get_vm_word(CPTR addr); EXPORTFUNC ui5r get_vm_long(CPTR addr); EXPORTPROC put_vm_byte(CPTR addr, ui3r b); EXPORTPROC put_vm_word(CPTR addr, ui4r w); EXPORTPROC put_vm_long(CPTR addr, ui5r l); EXPORTPROC SetHeadATTel(ATTep p); EXPORTFUNC ATTep FindATTel(CPTR addr); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/MOUSEMDV.c b/Mini vMac/mnvm_core/MOUSEMDV.c index af24191..190cd47 100755 --- a/Mini vMac/mnvm_core/MOUSEMDV.c +++ b/Mini vMac/mnvm_core/MOUSEMDV.c @@ -1,128 +1 @@ -/* - MOUSEMDV.c - - Copyright (C) 2006 Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - MOUSe EMulated DeVice - - Emulation of the mouse in the Mac Plus. - - This code descended from "Mouse-MacOS.c" in Richard F. Bannister's - Macintosh port of vMac, by Philip Cummins. -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" -#include "MYOSGLUE.h" -#include "ENDIANAC.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" -#include "SCCEMDEV.h" -#endif - -#include "MOUSEMDV.h" - -GLOBALPROC Mouse_Update(void) -{ -#if HaveMasterMyEvtQLock - if (0 != MasterMyEvtQLock) { - --MasterMyEvtQLock; - } -#endif - - /* - Check mouse position first. After mouse button or key event, - can't process another mouse position until following tick, - otherwise button or key will be in wrong place. - */ - - /* - if start doing this too soon after boot, - will mess up memory check - */ - if (Mouse_Enabled()) { - MyEvtQEl *p; - - if ( -#if HaveMasterMyEvtQLock - (0 == MasterMyEvtQLock) && -#endif - (nullpr != (p = MyEvtQOutP()))) - { -#if EmClassicKbrd -#if EnableMouseMotion - if (MyEvtQElKindMouseDelta == p->kind) { - - if ((p->u.pos.h != 0) || (p->u.pos.v != 0)) { - put_ram_word(0x0828, - get_ram_word(0x0828) + p->u.pos.v); - put_ram_word(0x082A, - get_ram_word(0x082A) + p->u.pos.h); - put_ram_byte(0x08CE, get_ram_byte(0x08CF)); - /* Tell MacOS to redraw the Mouse */ - } - MyEvtQOutDone(); - } else -#endif -#endif - if (MyEvtQElKindMousePos == p->kind) { - ui5r NewMouse = (p->u.pos.v << 16) | p->u.pos.h; - - if (get_ram_long(0x0828) != NewMouse) { - put_ram_long(0x0828, NewMouse); - /* Set Mouse Position */ - put_ram_long(0x082C, NewMouse); -#if EmClassicKbrd - put_ram_byte(0x08CE, get_ram_byte(0x08CF)); - /* Tell MacOS to redraw the Mouse */ -#else - put_ram_long(0x0830, NewMouse); - put_ram_byte(0x08CE, 0xFF); - /* Tell MacOS to redraw the Mouse */ -#endif - } - MyEvtQOutDone(); - } - } - } - -#if EmClassicKbrd - { - MyEvtQEl *p; - - if ( -#if HaveMasterMyEvtQLock - (0 == MasterMyEvtQLock) && -#endif - (nullpr != (p = MyEvtQOutP()))) - { - if (MyEvtQElKindMouseButton == p->kind) { - MouseBtnUp = p->u.press.down ? 0 : 1; - MyEvtQOutDone(); - MasterMyEvtQLock = 4; - } - } - } -#endif -} - -GLOBALPROC Mouse_EndTickNotify(void) -{ - if (Mouse_Enabled()) { - /* tell platform specific code where the mouse went */ - CurMouseV = get_ram_word(0x082C); - CurMouseH = get_ram_word(0x082E); - } -} +/* MOUSEMDV.c Copyright (C) 2006 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* MOUSe EMulated DeVice Emulation of the mouse in the Mac Plus. This code descended from "Mouse-MacOS.c" in Richard F. Bannister's Macintosh port of vMac, by Philip Cummins. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "ENDIANAC.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "SCCEMDEV.h" #include "MINEM68K.h" #endif #include "MOUSEMDV.h" GLOBALPROC Mouse_Update(void) { #if HaveMasterMyEvtQLock if (0 != MasterMyEvtQLock) { --MasterMyEvtQLock; } #endif /* Check mouse position first. After mouse button or key event, can't process another mouse position until following tick, otherwise button or key will be in wrong place. */ /* if start doing this too soon after boot, will mess up memory check */ if (Mouse_Enabled()) { MyEvtQEl *p; if ( #if HaveMasterMyEvtQLock (0 == MasterMyEvtQLock) && #endif (nullpr != (p = MyEvtQOutP()))) { #if EmClassicKbrd #if EnableMouseMotion if (MyEvtQElKindMouseDelta == p->kind) { if ((p->u.pos.h != 0) || (p->u.pos.v != 0)) { put_ram_word(0x0828, get_ram_word(0x0828) + p->u.pos.v); put_ram_word(0x082A, get_ram_word(0x082A) + p->u.pos.h); put_ram_byte(0x08CE, get_ram_byte(0x08CF)); /* Tell MacOS to redraw the Mouse */ } MyEvtQOutDone(); } else #endif #endif if (MyEvtQElKindMousePos == p->kind) { ui5r NewMouse = (p->u.pos.v << 16) | p->u.pos.h; if (get_ram_long(0x0828) != NewMouse) { put_ram_long(0x0828, NewMouse); /* Set Mouse Position */ put_ram_long(0x082C, NewMouse); #if EmClassicKbrd put_ram_byte(0x08CE, get_ram_byte(0x08CF)); /* Tell MacOS to redraw the Mouse */ #else put_ram_long(0x0830, NewMouse); put_ram_byte(0x08CE, 0xFF); /* Tell MacOS to redraw the Mouse */ #endif } MyEvtQOutDone(); } } } #if EmClassicKbrd { MyEvtQEl *p; if ( #if HaveMasterMyEvtQLock (0 == MasterMyEvtQLock) && #endif (nullpr != (p = MyEvtQOutP()))) { if (MyEvtQElKindMouseButton == p->kind) { MouseBtnUp = p->u.press.down ? 0 : 1; MyEvtQOutDone(); MasterMyEvtQLock = 4; } } } #endif } GLOBALPROC Mouse_EndTickNotify(void) { if (Mouse_Enabled()) { /* tell platform specific code where the mouse went */ CurMouseV = get_ram_word(0x082C); CurMouseH = get_ram_word(0x082E); } } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/MOUSEMDV.h b/Mini vMac/mnvm_core/MOUSEMDV.h index 109065b..95c3d90 100755 --- a/Mini vMac/mnvm_core/MOUSEMDV.h +++ b/Mini vMac/mnvm_core/MOUSEMDV.h @@ -1,24 +1 @@ -/* - MOUSEMDV.h - - Copyright (C) 2003 Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef MOUSEMDV_H -#error "header already included" -#else -#define MOUSEMDV_H -#endif - -EXPORTPROC Mouse_Update(void); -EXPORTPROC Mouse_EndTickNotify(void); +/* MOUSEMDV.h Copyright (C) 2003 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef MOUSEMDV_H #error "header already included" #else #define MOUSEMDV_H #endif EXPORTPROC Mouse_Update(void); EXPORTPROC Mouse_EndTickNotify(void); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/MYOSGLUE.h b/Mini vMac/mnvm_core/MYOSGLUE.h index ef97805..2465431 100755 --- a/Mini vMac/mnvm_core/MYOSGLUE.h +++ b/Mini vMac/mnvm_core/MYOSGLUE.h @@ -1,409 +1 @@ -/* - MYOSGLUE.h - - Copyright (C) 2006 Philip Cummins, Richard F. Bannister, - Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - MY Operating System GLUE. - - header file for operating system dependent code. - the same header is used for all platforms. - - This code is descended from Richard F. Bannister's Macintosh - port of vMac, by Philip Cummins. -*/ - -#ifdef MYOSGLUE_H -#ifndef AllFiles -#error "header already included" -#endif -#else -#define MYOSGLUE_H -#endif - - -EXPORTPROC WarnMsgCorruptedROM(void); -EXPORTPROC WarnMsgUnsupportedROM(void); -EXPORTPROC WarnMsgAbnormal(void); - -#if dbglog_HAVE -EXPORTPROC dbglog_writeCStr(char *s); -EXPORTPROC dbglog_writeReturn(void); -EXPORTPROC dbglog_writeHex(ui5r x); -EXPORTPROC dbglog_writeNum(ui5r x); -EXPORTPROC dbglog_writeMacChar(ui3r x); -EXPORTPROC dbglog_writeln(char *s); -EXPORTPROC dbglog_writelnNum(char *s, simr v); -#endif - -EXPORTPROC ReserveAllocOneBlock(ui3p *p, uimr n, ui3r align, - blnr FillOnes); - -EXPORTPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount); - - -EXPORTVAR(ui3p, ROM) - -/* - error codes returned by Mini vMac extensions - (passed back to the emulated 68k code). -*/ - -#define tMacErr ui4r - -#define mnvm_noErr ((tMacErr) 0x0000) - /* (ui4b) 0 - No Error */ -#define mnvm_miscErr ((tMacErr) 0xFFFF) - /* (ui4b) - 1 - Should probably replace these */ -#define mnvm_controlErr ((tMacErr) 0xFFEF) - /* (ui4b) - 17 - I/O System Errors */ -#define mnvm_statusErr ((tMacErr) 0xFFEE) - /* (ui4b) - 18 - Driver can't respond to Status call */ -#define mnvm_closErr ((tMacErr) 0xFFE8) - /* (ui4b) - 24 - I/O System Errors */ -#define mnvm_eofErr ((tMacErr) 0xFFD9) - /* (ui4b) - 39 - End of file */ -#define mnvm_tmfoErr ((tMacErr) 0xFFD6) - /* (ui4b) - 42 - too many files open */ -#define mnvm_fnfErr ((tMacErr) 0xFFD5) - /* (ui4b) - 43 - File not found */ -#define mnvm_wPrErr ((tMacErr) 0xFFD4) - /* (ui4b) - 44 - diskette is write protected */ -#define mnvm_vLckdErr ((tMacErr) 0xFFD2) - /* (ui4b) - 46 - volume is locked */ -#define mnvm_dupFNErr ((tMacErr) 0xFFD0) - /* (ui4b) - 48 - duplicate filename */ -#define mnvm_opWrErr ((tMacErr) 0xFFCF) - /* (ui4b) - 49 - file already open with with write permission */ -#define mnvm_paramErr ((tMacErr) 0xFFCE) - /* (ui4b) - 50 - error in parameter list */ -#define mnvm_permErr ((tMacErr) 0xFFCA) - /* (ui4b) - 54 - permissions error (on file open) */ -#define mnvm_nsDrvErr ((tMacErr) 0xFFC8) - /* (ui4b) - 56 - No Such Drive */ -#define mnvm_wrPermErr ((tMacErr) 0xFFC3) - /* (ui4b) - 61 - write permissions error */ -#define mnvm_offLinErr ((tMacErr) 0xFFBF) - /* (ui4b) - 65 - off-line drive */ -#define mnvm_dirNFErr ((tMacErr) 0xFF88) - /* (ui4b) - 120 - directory not found */ -#define mnvm_afpAccessDenied ((tMacErr) 0xEC78) - /* (ui4b) - 5000 - Insufficient access privileges for operation */ - -#if IncludePbufs - -#define tPbuf ui4r - -#define NotAPbuf ((tPbuf)0xFFFF) - -EXPORTFUNC tMacErr CheckPbuf(tPbuf Pbuf_No); -EXPORTFUNC tMacErr PbufGetSize(tPbuf Pbuf_No, ui5r *Count); - -EXPORTFUNC tMacErr PbufNew(ui5b count, tPbuf *r); -EXPORTPROC PbufDispose(tPbuf i); -EXPORTPROC PbufTransfer(ui3p Buffer, - tPbuf i, ui5r offset, ui5r count, blnr IsWrite); - -#endif - -#define tDrive ui4r - -EXPORTVAR(ui5b, vSonyWritableMask) -EXPORTVAR(ui5b, vSonyInsertedMask) - -#define vSonyIsInserted(Drive_No) \ - ((vSonyInsertedMask & ((ui5b)1 << (Drive_No))) != 0) - -EXPORTFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer, - tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, - ui5r *Sony_ActCount); -EXPORTFUNC tMacErr vSonyEject(tDrive Drive_No); -EXPORTFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count); - -EXPORTFUNC blnr AnyDiskInserted(void); -EXPORTPROC DiskRevokeWritable(tDrive Drive_No); - -#if IncludeSonyRawMode -EXPORTVAR(blnr, vSonyRawMode) -#endif - -#if IncludeSonyNew -EXPORTVAR(blnr, vSonyNewDiskWanted) -EXPORTVAR(ui5b, vSonyNewDiskSize) -EXPORTFUNC tMacErr vSonyEjectDelete(tDrive Drive_No); -#endif - -#if IncludeSonyNameNew -EXPORTVAR(tPbuf, vSonyNewDiskName) -#endif - -#if IncludeSonyGetName -EXPORTFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r); -#endif - -#if IncludeHostTextClipExchange -EXPORTFUNC tMacErr HTCEexport(tPbuf i); -EXPORTFUNC tMacErr HTCEimport(tPbuf *r); -#endif - -EXPORTVAR(ui5b, OnTrueTime); - -EXPORTVAR(ui5b, CurMacDateInSeconds) -EXPORTVAR(ui5b, CurMacLatitude) -EXPORTVAR(ui5b, CurMacLongitude) -EXPORTVAR(ui5b, CurMacDelta) - /* (dlsDelta << 24) | (gmtDelta & 0x00FFFFFF) */ - - -#define vMacScreenNumPixels \ - ((long)vMacScreenHeight * (long)vMacScreenWidth) -#define vMacScreenNumBits (vMacScreenNumPixels << vMacScreenDepth) -#define vMacScreenNumBytes (vMacScreenNumBits / 8) -#define vMacScreenBitWidth ((long)vMacScreenWidth << vMacScreenDepth) -#define vMacScreenByteWidth (vMacScreenBitWidth / 8) - -#define vMacScreenMonoNumBytes (vMacScreenNumPixels / 8) -#define vMacScreenMonoByteWidth ((long)vMacScreenWidth / 8) - -#if 0 != vMacScreenDepth -EXPORTVAR(blnr, UseColorMode) -EXPORTVAR(blnr, ColorModeWorks) -#endif - -#if 0 != vMacScreenDepth -EXPORTVAR(blnr, ColorMappingChanged) -#endif - -#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4) -#define CLUT_size (1 << (1 << vMacScreenDepth)) - -EXPORTVAR(ui4r, CLUT_reds[CLUT_size]) -EXPORTVAR(ui4r, CLUT_greens[CLUT_size]) -EXPORTVAR(ui4r, CLUT_blues[CLUT_size]) -#endif - -EXPORTVAR(blnr, EmVideoDisable); -EXPORTVAR(si3b, EmLagTime); - -EXPORTPROC Screen_OutputFrame(ui3p screencurrentbuff); -EXPORTPROC DoneWithDrawingForTick(void); - -EXPORTVAR(blnr, ForceMacOff) - -EXPORTVAR(blnr, WantMacInterrupt) - -EXPORTVAR(blnr, WantMacReset) - -EXPORTFUNC blnr ExtraTimeNotOver(void); - -EXPORTVAR(ui3b, SpeedValue) - -#if EnableAutoSlow -EXPORTVAR(blnr, WantNotAutoSlow) -#endif - -/* where emulated machine thinks mouse is */ -EXPORTVAR(ui4b, CurMouseV) -EXPORTVAR(ui4b, CurMouseH) - -#if EnableAutoSlow -EXPORTVAR(ui5r, QuietTime) -EXPORTVAR(ui5r, QuietSubTicks) - -#define QuietEnds() \ -{ \ - QuietTime = 0; \ - QuietSubTicks = 0; \ -} -#else -#define QuietEnds() -#endif - -#if 3 == kLn2SoundSampSz -#define trSoundSamp ui3r -#define tbSoundSamp ui3b -#define tpSoundSamp ui3p -#define kCenterSound 0x80 -#elif 4 == kLn2SoundSampSz -#define trSoundSamp ui4r -#define tbSoundSamp ui4b -#define tpSoundSamp ui4p -#define kCenterSound 0x8000 -#else -#error "unsupported kLn2SoundSampSz" -#endif - -#if MySoundEnabled - -EXPORTFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL); -EXPORTPROC MySound_EndWrite(ui4r actL); - -/* 370 samples per tick = 22,254.54 per second */ -#endif - -#if EmLocalTalk - -#define LT_TxBfMxSz 1024 -EXPORTVAR(ui3p, LT_TxBuffer) -EXPORTVAR(ui4r, LT_TxBuffSz) - -EXPORTPROC LT_TransmitPacket(void); - -EXPORTVAR(ui3p, LT_RxBuffer); -EXPORTVAR(ui5r, LT_RxBuffSz); - -EXPORTPROC LT_ReceivePacket(void); - -#endif - -EXPORTPROC WaitForNextTick(void); - -#define MyEvtQElKindKey 0 -#define MyEvtQElKindMouseButton 1 -#define MyEvtQElKindMousePos 2 -#define MyEvtQElKindMouseDelta 3 - -struct MyEvtQEl { - /* expected size : 8 bytes */ - ui3b kind; - ui3b pad[3]; - union { - struct { - ui3b down; - ui3b key; - } press; - struct { - ui4b h; - ui4b v; - } pos; - } u; -}; -typedef struct MyEvtQEl MyEvtQEl; - -EXPORTFUNC MyEvtQEl * MyEvtQOutP(void); -EXPORTPROC MyEvtQOutDone(void); - -#define MKC_A 0x00 -#define MKC_B 0x0B -#define MKC_C 0x08 -#define MKC_D 0x02 -#define MKC_E 0x0E -#define MKC_F 0x03 -#define MKC_G 0x05 -#define MKC_H 0x04 -#define MKC_I 0x22 -#define MKC_J 0x26 -#define MKC_K 0x28 -#define MKC_L 0x25 -#define MKC_M 0x2E -#define MKC_N 0x2D -#define MKC_O 0x1F -#define MKC_P 0x23 -#define MKC_Q 0x0C -#define MKC_R 0x0F -#define MKC_S 0x01 -#define MKC_T 0x11 -#define MKC_U 0x20 -#define MKC_V 0x09 -#define MKC_W 0x0D -#define MKC_X 0x07 -#define MKC_Y 0x10 -#define MKC_Z 0x06 - -#define MKC_1 0x12 -#define MKC_2 0x13 -#define MKC_3 0x14 -#define MKC_4 0x15 -#define MKC_5 0x17 -#define MKC_6 0x16 -#define MKC_7 0x1A -#define MKC_8 0x1C -#define MKC_9 0x19 -#define MKC_0 0x1D - -#define MKC_Command 0x37 -#define MKC_Shift 0x38 -#define MKC_CapsLock 0x39 -#define MKC_Option 0x3A - -#define MKC_Space 0x31 -#define MKC_Return 0x24 -#define MKC_BackSpace 0x33 -#define MKC_Tab 0x30 - -#define MKC_Left /* 0x46 */ 0x7B -#define MKC_Right /* 0x42 */ 0x7C -#define MKC_Down /* 0x48 */ 0x7D -#define MKC_Up /* 0x4D */ 0x7E - -#define MKC_Minus 0x1B -#define MKC_Equal 0x18 -#define MKC_BackSlash 0x2A -#define MKC_Comma 0x2B -#define MKC_Period 0x2F -#define MKC_Slash 0x2C -#define MKC_SemiColon 0x29 -#define MKC_SingleQuote 0x27 -#define MKC_LeftBracket 0x21 -#define MKC_RightBracket 0x1E -#define MKC_Grave 0x32 -#define MKC_Clear 0x47 -#define MKC_KPEqual 0x51 -#define MKC_KPDevide 0x4B -#define MKC_KPMultiply 0x43 -#define MKC_KPSubtract 0x4E -#define MKC_KPAdd 0x45 -#define MKC_Enter 0x4C - -#define MKC_KP1 0x53 -#define MKC_KP2 0x54 -#define MKC_KP3 0x55 -#define MKC_KP4 0x56 -#define MKC_KP5 0x57 -#define MKC_KP6 0x58 -#define MKC_KP7 0x59 -#define MKC_KP8 0x5B -#define MKC_KP9 0x5C -#define MKC_KP0 0x52 -#define MKC_Decimal 0x41 - -/* these aren't on the Mac Plus keyboard */ - -#define MKC_Control 0x3B -#define MKC_Escape 0x35 -#define MKC_F1 0x7a -#define MKC_F2 0x78 -#define MKC_F3 0x63 -#define MKC_F4 0x76 -#define MKC_F5 0x60 -#define MKC_F6 0x61 -#define MKC_F7 0x62 -#define MKC_F8 0x64 -#define MKC_F9 0x65 -#define MKC_F10 0x6d -#define MKC_F11 0x67 -#define MKC_F12 0x6f - -#define MKC_Home 0x73 -#define MKC_End 0x77 -#define MKC_PageUp 0x74 -#define MKC_PageDown 0x79 -#define MKC_Help 0x72 /* = Insert */ -#define MKC_ForwardDel 0x75 -#define MKC_Print 0x69 -#define MKC_ScrollLock 0x6B -#define MKC_Pause 0x71 - -#define MKC_AngleBracket 0x0A /* found on german keyboard */ +/* MYOSGLUE.h Copyright (C) 2006 Philip Cummins, Richard F. Bannister, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* MY Operating System GLUE. header file for operating system dependent code. the same header is used for all platforms. This code is descended from Richard F. Bannister's Macintosh port of vMac, by Philip Cummins. */ #ifdef MYOSGLUE_H #ifndef AllFiles #error "header already included" #endif #else #define MYOSGLUE_H #endif EXPORTOSGLUPROC WarnMsgCorruptedROM(void); EXPORTOSGLUPROC WarnMsgUnsupportedROM(void); EXPORTOSGLUPROC WarnMsgAbnormalID(ui4r id); #if dbglog_HAVE EXPORTOSGLUPROC dbglog_writeCStr(char *s); EXPORTOSGLUPROC dbglog_writeReturn(void); EXPORTOSGLUPROC dbglog_writeHex(ui5r x); EXPORTOSGLUPROC dbglog_writeNum(ui5r x); EXPORTOSGLUPROC dbglog_writeMacChar(ui3r x); EXPORTOSGLUPROC dbglog_writeln(char *s); EXPORTOSGLUPROC dbglog_writelnNum(char *s, simr v); #endif EXPORTOSGLUPROC ReserveAllocOneBlock(ui3p *p, uimr n, ui3r align, blnr FillOnes); EXPORTOSGLUPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount); EXPORTVAR(ui3p, ROM) /* error codes returned by Mini vMac extensions (passed back to the emulated 68k code). */ #define tMacErr ui4r #define mnvm_noErr ((tMacErr) 0x0000) /* (ui4b) 0 - No Error */ #define mnvm_miscErr ((tMacErr) 0xFFFF) /* (ui4b) - 1 - Should probably replace these */ #define mnvm_controlErr ((tMacErr) 0xFFEF) /* (ui4b) - 17 - I/O System Errors */ #define mnvm_statusErr ((tMacErr) 0xFFEE) /* (ui4b) - 18 - Driver can't respond to Status call */ #define mnvm_closErr ((tMacErr) 0xFFE8) /* (ui4b) - 24 - I/O System Errors */ #define mnvm_eofErr ((tMacErr) 0xFFD9) /* (ui4b) - 39 - End of file */ #define mnvm_tmfoErr ((tMacErr) 0xFFD6) /* (ui4b) - 42 - too many files open */ #define mnvm_fnfErr ((tMacErr) 0xFFD5) /* (ui4b) - 43 - File not found */ #define mnvm_wPrErr ((tMacErr) 0xFFD4) /* (ui4b) - 44 - diskette is write protected */ #define mnvm_vLckdErr ((tMacErr) 0xFFD2) /* (ui4b) - 46 - volume is locked */ #define mnvm_dupFNErr ((tMacErr) 0xFFD0) /* (ui4b) - 48 - duplicate filename */ #define mnvm_opWrErr ((tMacErr) 0xFFCF) /* (ui4b) - 49 - file already open with with write permission */ #define mnvm_paramErr ((tMacErr) 0xFFCE) /* (ui4b) - 50 - error in parameter list */ #define mnvm_permErr ((tMacErr) 0xFFCA) /* (ui4b) - 54 - permissions error (on file open) */ #define mnvm_nsDrvErr ((tMacErr) 0xFFC8) /* (ui4b) - 56 - No Such Drive */ #define mnvm_wrPermErr ((tMacErr) 0xFFC3) /* (ui4b) - 61 - write permissions error */ #define mnvm_offLinErr ((tMacErr) 0xFFBF) /* (ui4b) - 65 - off-line drive */ #define mnvm_dirNFErr ((tMacErr) 0xFF88) /* (ui4b) - 120 - directory not found */ #define mnvm_afpAccessDenied ((tMacErr) 0xEC78) /* (ui4b) - 5000 - Insufficient access privileges for operation */ #if IncludePbufs #define tPbuf ui4r #define NotAPbuf ((tPbuf)0xFFFF) EXPORTOSGLUFUNC tMacErr CheckPbuf(tPbuf Pbuf_No); EXPORTOSGLUFUNC tMacErr PbufGetSize(tPbuf Pbuf_No, ui5r *Count); EXPORTOSGLUFUNC tMacErr PbufNew(ui5b count, tPbuf *r); EXPORTOSGLUPROC PbufDispose(tPbuf i); EXPORTOSGLUPROC PbufTransfer(ui3p Buffer, tPbuf i, ui5r offset, ui5r count, blnr IsWrite); #endif #define tDrive ui4r EXPORTVAR(ui5b, vSonyWritableMask) EXPORTVAR(ui5b, vSonyInsertedMask) #define vSonyIsInserted(Drive_No) \ ((vSonyInsertedMask & ((ui5b)1 << (Drive_No))) != 0) EXPORTOSGLUFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer, tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, ui5r *Sony_ActCount); EXPORTOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No); EXPORTOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count); EXPORTOSGLUFUNC blnr AnyDiskInserted(void); EXPORTOSGLUPROC DiskRevokeWritable(tDrive Drive_No); #if IncludeSonyRawMode EXPORTVAR(blnr, vSonyRawMode) #endif #if IncludeSonyNew EXPORTVAR(blnr, vSonyNewDiskWanted) EXPORTVAR(ui5b, vSonyNewDiskSize) EXPORTOSGLUFUNC tMacErr vSonyEjectDelete(tDrive Drive_No); #endif #if IncludeSonyNameNew EXPORTVAR(tPbuf, vSonyNewDiskName) #endif #if IncludeSonyGetName EXPORTOSGLUFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r); #endif #if IncludeHostTextClipExchange EXPORTOSGLUFUNC tMacErr HTCEexport(tPbuf i); EXPORTOSGLUFUNC tMacErr HTCEimport(tPbuf *r); #endif EXPORTVAR(ui5b, OnTrueTime) EXPORTVAR(ui5b, CurMacDateInSeconds) EXPORTVAR(ui5b, CurMacLatitude) EXPORTVAR(ui5b, CurMacLongitude) EXPORTVAR(ui5b, CurMacDelta) /* (dlsDelta << 24) | (gmtDelta & 0x00FFFFFF) */ #define vMacScreenNumPixels \ ((long)vMacScreenHeight * (long)vMacScreenWidth) #define vMacScreenNumBits (vMacScreenNumPixels << vMacScreenDepth) #define vMacScreenNumBytes (vMacScreenNumBits / 8) #define vMacScreenBitWidth ((long)vMacScreenWidth << vMacScreenDepth) #define vMacScreenByteWidth (vMacScreenBitWidth / 8) #define vMacScreenMonoNumBytes (vMacScreenNumPixels / 8) #define vMacScreenMonoByteWidth ((long)vMacScreenWidth / 8) #if 0 != vMacScreenDepth EXPORTVAR(blnr, UseColorMode) EXPORTVAR(blnr, ColorModeWorks) #endif #if 0 != vMacScreenDepth EXPORTVAR(blnr, ColorMappingChanged) #endif #if (0 != vMacScreenDepth) && (vMacScreenDepth < 4) #define CLUT_size (1 << (1 << vMacScreenDepth)) EXPORTVAR(ui4r, CLUT_reds[CLUT_size]) EXPORTVAR(ui4r, CLUT_greens[CLUT_size]) EXPORTVAR(ui4r, CLUT_blues[CLUT_size]) #endif EXPORTVAR(blnr, EmVideoDisable) EXPORTVAR(si3b, EmLagTime) EXPORTOSGLUPROC Screen_OutputFrame(ui3p screencurrentbuff); EXPORTOSGLUPROC DoneWithDrawingForTick(void); EXPORTVAR(blnr, ForceMacOff) EXPORTVAR(blnr, WantMacInterrupt) EXPORTVAR(blnr, WantMacReset) EXPORTOSGLUFUNC blnr ExtraTimeNotOver(void); EXPORTVAR(ui3b, SpeedValue) #if EnableAutoSlow EXPORTVAR(blnr, WantNotAutoSlow) #endif /* where emulated machine thinks mouse is */ EXPORTVAR(ui4b, CurMouseV) EXPORTVAR(ui4b, CurMouseH) #if EnableAutoSlow EXPORTVAR(ui5r, QuietTime) EXPORTVAR(ui5r, QuietSubTicks) #define QuietEnds() \ { \ QuietTime = 0; \ QuietSubTicks = 0; \ } #else #define QuietEnds() #endif #if 3 == kLn2SoundSampSz #define trSoundSamp ui3r #define tbSoundSamp ui3b #define tpSoundSamp ui3p #define kCenterSound 0x80 #elif 4 == kLn2SoundSampSz #define trSoundSamp ui4r #define tbSoundSamp ui4b #define tpSoundSamp ui4p #define kCenterSound 0x8000 #else #error "unsupported kLn2SoundSampSz" #endif #if MySoundEnabled EXPORTOSGLUFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL); EXPORTOSGLUPROC MySound_EndWrite(ui4r actL); /* 370 samples per tick = 22,254.54 per second */ #endif #if EmLocalTalk #define LT_TxBfMxSz 1024 EXPORTVAR(ui3p, LT_TxBuffer) EXPORTVAR(ui4r, LT_TxBuffSz) EXPORTOSGLUPROC LT_TransmitPacket(void); EXPORTVAR(ui3p, LT_RxBuffer) EXPORTVAR(ui5r, LT_RxBuffSz) EXPORTOSGLUPROC LT_ReceivePacket(void); #endif EXPORTOSGLUPROC WaitForNextTick(void); #define MyEvtQElKindKey 0 #define MyEvtQElKindMouseButton 1 #define MyEvtQElKindMousePos 2 #define MyEvtQElKindMouseDelta 3 struct MyEvtQEl { /* expected size : 8 bytes */ ui3b kind; ui3b pad[3]; union { struct { ui3b down; ui3b key; } press; struct { ui4b h; ui4b v; } pos; } u; }; typedef struct MyEvtQEl MyEvtQEl; EXPORTOSGLUFUNC MyEvtQEl * MyEvtQOutP(void); EXPORTOSGLUPROC MyEvtQOutDone(void); #define MKC_A 0x00 #define MKC_B 0x0B #define MKC_C 0x08 #define MKC_D 0x02 #define MKC_E 0x0E #define MKC_F 0x03 #define MKC_G 0x05 #define MKC_H 0x04 #define MKC_I 0x22 #define MKC_J 0x26 #define MKC_K 0x28 #define MKC_L 0x25 #define MKC_M 0x2E #define MKC_N 0x2D #define MKC_O 0x1F #define MKC_P 0x23 #define MKC_Q 0x0C #define MKC_R 0x0F #define MKC_S 0x01 #define MKC_T 0x11 #define MKC_U 0x20 #define MKC_V 0x09 #define MKC_W 0x0D #define MKC_X 0x07 #define MKC_Y 0x10 #define MKC_Z 0x06 #define MKC_1 0x12 #define MKC_2 0x13 #define MKC_3 0x14 #define MKC_4 0x15 #define MKC_5 0x17 #define MKC_6 0x16 #define MKC_7 0x1A #define MKC_8 0x1C #define MKC_9 0x19 #define MKC_0 0x1D #define MKC_Command 0x37 #define MKC_Shift 0x38 #define MKC_CapsLock 0x39 #define MKC_Option 0x3A #define MKC_Space 0x31 #define MKC_Return 0x24 #define MKC_BackSpace 0x33 #define MKC_Tab 0x30 #define MKC_Left /* 0x46 */ 0x7B #define MKC_Right /* 0x42 */ 0x7C #define MKC_Down /* 0x48 */ 0x7D #define MKC_Up /* 0x4D */ 0x7E #define MKC_Minus 0x1B #define MKC_Equal 0x18 #define MKC_BackSlash 0x2A #define MKC_Comma 0x2B #define MKC_Period 0x2F #define MKC_Slash 0x2C #define MKC_SemiColon 0x29 #define MKC_SingleQuote 0x27 #define MKC_LeftBracket 0x21 #define MKC_RightBracket 0x1E #define MKC_Grave 0x32 #define MKC_Clear 0x47 #define MKC_KPEqual 0x51 #define MKC_KPDevide 0x4B #define MKC_KPMultiply 0x43 #define MKC_KPSubtract 0x4E #define MKC_KPAdd 0x45 #define MKC_Enter 0x4C #define MKC_KP1 0x53 #define MKC_KP2 0x54 #define MKC_KP3 0x55 #define MKC_KP4 0x56 #define MKC_KP5 0x57 #define MKC_KP6 0x58 #define MKC_KP7 0x59 #define MKC_KP8 0x5B #define MKC_KP9 0x5C #define MKC_KP0 0x52 #define MKC_Decimal 0x41 /* these aren't on the Mac Plus keyboard */ #define MKC_Control 0x3B #define MKC_Escape 0x35 #define MKC_F1 0x7a #define MKC_F2 0x78 #define MKC_F3 0x63 #define MKC_F4 0x76 #define MKC_F5 0x60 #define MKC_F6 0x61 #define MKC_F7 0x62 #define MKC_F8 0x64 #define MKC_F9 0x65 #define MKC_F10 0x6d #define MKC_F11 0x67 #define MKC_F12 0x6f #define MKC_Home 0x73 #define MKC_End 0x77 #define MKC_PageUp 0x74 #define MKC_PageDown 0x79 #define MKC_Help 0x72 /* = Insert */ #define MKC_ForwardDel 0x75 #define MKC_Print 0x69 #define MKC_ScrollLock 0x6B #define MKC_Pause 0x71 #define MKC_AngleBracket 0x0A /* found on german keyboard */ \ No newline at end of file diff --git a/Mini vMac/mnvm_core/PMUEMDEV.c b/Mini vMac/mnvm_core/PMUEMDEV.c index 4156207..1bc997b 100755 --- a/Mini vMac/mnvm_core/PMUEMDEV.c +++ b/Mini vMac/mnvm_core/PMUEMDEV.c @@ -1,430 +1 @@ -/* - PMUEMDEV.c - - Copyright (C) 2008 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - Power Management Unit EMulated DEVice -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" -#include "MYOSGLUE.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" -#include "VIAEMDEV.h" -#endif - -#include "PMUEMDEV.h" - -enum { - kPMUStateReadyForCommand, - kPMUStateRecievingLength, - kPMUStateRecievingBuffer, - kPMUStateRecievedCommand, - kPMUStateSendLength, - kPMUStateSendBuffer, - - kPMUStates -}; - -#define PMU_BuffSz 8 -LOCALVAR ui3b PMU_BuffA[PMU_BuffSz]; -LOCALVAR ui3p PMU_p; -LOCALVAR ui3r PMU_rem; -LOCALVAR ui3r PMU_i; - -LOCALVAR int PMUState = kPMUStateReadyForCommand; - -LOCALVAR ui3r PMU_CurCommand; -LOCALVAR ui3r PMU_SendNext; -LOCALVAR ui3r PMU_BuffL; - -LOCALPROC PmuStartSendResult(ui3r ResultCode, ui3r L) -{ - PMU_SendNext = ResultCode; - PMU_BuffL = L; - PMUState = kPMUStateSendLength; -} - -LOCALVAR ui3b PARAMRAM[128]; - -LOCALPROC PmuCheckCommandOp(void) -{ - switch (PMU_CurCommand) { - case 0x10: /* kPMUpowerCntl - power plane/clock control */ - break; - case 0x32: /* kPMUxPramWrite - write extended PRAM byte(s) */ - if (kPMUStateRecievingBuffer == PMUState) { - if (0 == PMU_i) { - if (PMU_BuffL >= 2) { - PMU_p = PMU_BuffA; - PMU_rem = 2; - } else { - ReportAbnormal( - "PMU_BuffL too small for kPMUxPramWrite"); - } - } else if (2 == PMU_i) { - if ((PMU_BuffA[1] + 2 == PMU_BuffL) - && (PMU_BuffA[0] + PMU_BuffA[1] <= 0x80)) - { - PMU_p = &PARAMRAM[PMU_BuffA[0]]; - PMU_rem = PMU_BuffA[1]; - } else { - ReportAbnormal("bad range for kPMUxPramWrite"); - } - } else { - ReportAbnormal("Wrong PMU_i for kPMUpramWrite"); - } - } else if (kPMUStateRecievedCommand == PMUState) { - /* already done */ - } - break; -#if 0 - case 0xE2: /* kPMUdownloadStatus - PRAM status */ - break; -#endif - case 0xE0: /* kPMUwritePmgrRAM - write to internal PMGR RAM */ - break; - case 0x21: /* kPMUpMgrADBoff - turn ADB auto-poll off */ - if (kPMUStateRecievedCommand == PMUState) { - if (0 != PMU_BuffL) { - ReportAbnormal("kPMUpMgrADBoff nonzero length"); - } - } - break; - case 0xEC: /* kPMUPmgrSelfTest - run the PMGR selftest */ - if (kPMUStateRecievedCommand == PMUState) { - PmuStartSendResult(0, 0); - } - break; - case 0x78: - /* kPMUreadINT - get PMGR interrupt data */ - case 0x68: - /* - kPMUbatteryRead - read battery/charger level and status - */ - case 0x7F: - /* - kPMUsleepReq - put the system to sleep (sleepSig='MATT') - */ - if (kPMUStateRecievedCommand == PMUState) { - PMU_BuffA[0] = 0; - PmuStartSendResult(0, 1); - } - break; - case 0xE8: /* kPMUreadPmgrRAM - read from internal PMGR RAM */ - if (kPMUStateRecievedCommand == PMUState) { - if ((3 == PMU_BuffL) - && (0 == PMU_BuffA[0]) - && (0xEE == PMU_BuffA[1]) - && (1 == PMU_BuffA[2])) - { - PMU_BuffA[0] = 1 << 5; - PmuStartSendResult(0, 1); - } else { - PMU_BuffA[0] = 0; - PmuStartSendResult(0, 1); - /* ReportAbnormal("Unknown kPMUreadPmgrRAM op"); */ - } - } - break; - case 0x3A: /* kPMUxPramRead - read extended PRAM byte(s) */ - if (kPMUStateRecievedCommand == PMUState) { - if ((2 == PMU_BuffL) - && (PMU_BuffA[0] + PMU_BuffA[1] <= 0x80)) - { - PMU_p = &PARAMRAM[PMU_BuffA[0]]; - PMU_rem = PMU_BuffA[1]; - PmuStartSendResult(0, PMU_rem); - } else { - ReportAbnormal("Unknown kPMUxPramRead op"); - } - } - break; - case 0x38: - /* kPMUtimeRead - read the time from the clock chip */ - if (kPMUStateRecievedCommand == PMUState) { - if (0 == PMU_BuffL) { - PMU_BuffA[0] = 0; - PMU_BuffA[1] = 0; - PMU_BuffA[2] = 0; - PMU_BuffA[3] = 0; - PmuStartSendResult(0, 4); - } else { - ReportAbnormal("Unknown kPMUtimeRead op"); - } - } - break; - case 0x31: - /* - kPMUpramWrite - write the original 20 bytes of PRAM - (Portable only) - */ - if (kPMUStateRecievedCommand == PMUState) { - if (20 == PMU_BuffL) { - /* done */ - } else { - ReportAbnormal("Unknown kPMUpramWrite op"); - } - } else if (kPMUStateRecievingBuffer == PMUState) { - if (20 == PMU_BuffL) { - if (0 == PMU_i) { - PMU_p = &PARAMRAM[16]; - PMU_rem = 16; - } else if (16 == PMU_i) { - PMU_p = &PARAMRAM[8]; - PMU_rem = 4; - } else { - ReportAbnormal("Wrong PMU_i for kPMUpramWrite"); - } - } - } - break; - case 0x39: - /* - kPMUpramRead - read the original 20 bytes of PRAM - (Portable only) - */ - if (kPMUStateRecievedCommand == PMUState) { - if (0 == PMU_BuffL) { - PmuStartSendResult(0, 20); - } else { - ReportAbnormal("Unknown kPMUpramRead op"); - } - } else if (kPMUStateSendBuffer == PMUState) { -#if 0 - { - int i; - - for (i = 0; i < PMU_BuffSz; ++i) { - PMU_BuffA[i] = 0; - } - } -#endif - if (0 == PMU_i) { - PMU_p = &PARAMRAM[16]; - PMU_rem = 16; - } else if (16 == PMU_i) { - PMU_p = &PARAMRAM[8]; - PMU_rem = 4; - } else { - ReportAbnormal("Wrong PMU_i for kPMUpramRead"); - } - } - break; - default: - if (kPMUStateRecievedCommand == PMUState) { - ReportAbnormal("Unknown PMU op"); -#if dbglog_HAVE - dbglog_writeCStr("Unknown PMU op "); - dbglog_writeHex(PMU_CurCommand); - dbglog_writeReturn(); - dbglog_writeCStr("PMU_BuffL = "); - dbglog_writeHex(PMU_BuffL); - dbglog_writeReturn(); - if (PMU_BuffL <= PMU_BuffSz) { - int i; - - for (i = 0; i < PMU_BuffL; ++i) { - dbglog_writeCStr("PMU_BuffA["); - dbglog_writeNum(i); - dbglog_writeCStr("] = "); - dbglog_writeHex(PMU_BuffA[i]); - dbglog_writeReturn(); - } - } -#endif - } - break; - } -} - -LOCALPROC LocBuffSetUpNextChunk(void) -{ - PMU_p = PMU_BuffA; - PMU_rem = PMU_BuffL - PMU_i; - if (PMU_rem >= PMU_BuffSz) { - PMU_rem = PMU_BuffSz; - } -} - -LOCALFUNC ui3r GetPMUbus(void) -{ - ui3r v; - - v = VIA1_iA7; - v <<= 1; - v |= VIA1_iA6; - v <<= 1; - v |= VIA1_iA5; - v <<= 1; - v |= VIA1_iA4; - v <<= 1; - v |= VIA1_iA3; - v <<= 1; - v |= VIA1_iA2; - v <<= 1; - v |= VIA1_iA1; - v <<= 1; - v |= VIA1_iA0; - - return v; -} - -LOCALPROC SetPMUbus(ui3r v) -{ - VIA1_iA0 = v & 0x01; - v >>= 1; - VIA1_iA1 = v & 0x01; - v >>= 1; - VIA1_iA2 = v & 0x01; - v >>= 1; - VIA1_iA3 = v & 0x01; - v >>= 1; - VIA1_iA4 = v & 0x01; - v >>= 1; - VIA1_iA5 = v & 0x01; - v >>= 1; - VIA1_iA6 = v & 0x01; - v >>= 1; - VIA1_iA7 = v & 0x01; -} - -LOCALVAR blnr PMU_Sending = falseblnr; - -LOCALPROC PmuCheckCommandCompletion(void) -{ - if (PMU_i == PMU_BuffL) { - PMUState = kPMUStateRecievedCommand; - PmuCheckCommandOp(); - if ((PMU_CurCommand & 0x08) == 0) { - PMUState = kPMUStateReadyForCommand; - SetPMUbus(0xFF); - } else { - if (PMUState != kPMUStateSendLength) { - PmuStartSendResult(0xFF, 0); - PMUState = kPMUStateSendLength; - } - PMU_i = 0; - PMU_Sending = trueblnr; - ICT_add(kICT_PMU_Task, - 20400UL * kCycleScale / 64 * kMyClockMult); - } - } -} - -GLOBALPROC PmuToReady_ChangeNtfy(void) -{ - if (PMU_Sending) { - PMU_Sending = falseblnr; - ReportAbnormal("PmuToReady_ChangeNtfy while PMU_Sending"); - PmuFromReady = 0; - } - switch (PMUState) { - case kPMUStateReadyForCommand: - if (! PmuToReady) { - PmuFromReady = 0; - } else { - PMU_CurCommand = GetPMUbus(); - PMUState = kPMUStateRecievingLength; - PmuFromReady = 1; - } - break; - case kPMUStateRecievingLength: - if (! PmuToReady) { - PmuFromReady = 0; - } else { - PMU_BuffL = GetPMUbus(); - PMU_i = 0; - PMU_rem = 0; - PMUState = kPMUStateRecievingBuffer; - PmuCheckCommandCompletion(); - PmuFromReady = 1; - } - break; - case kPMUStateRecievingBuffer: - if (! PmuToReady) { - PmuFromReady = 0; - } else { - ui3r v = GetPMUbus(); - if (0 == PMU_rem) { - PMU_p = nullpr; - PmuCheckCommandOp(); - if (nullpr == PMU_p) { - /* default handler */ - LocBuffSetUpNextChunk(); - } - } - if (nullpr == PMU_p) { - /* mini vmac bug if ever happens */ - ReportAbnormal( - "PMU_p null while kPMUStateRecievingBuffer"); - } - *PMU_p++ = v; - --PMU_rem; - ++PMU_i; - PmuCheckCommandCompletion(); - PmuFromReady = 1; - } - break; - case kPMUStateSendLength: - if (! PmuToReady) { - /* receiving */ - PmuFromReady = 1; - } else { - PMU_SendNext = PMU_BuffL; - PMUState = kPMUStateSendBuffer; - PMU_Sending = trueblnr; - ICT_add(kICT_PMU_Task, - 20400UL * kCycleScale / 64 * kMyClockMult); - } - break; - case kPMUStateSendBuffer: - if (! PmuToReady) { - /* receiving */ - PmuFromReady = 1; - } else { - if (PMU_i == PMU_BuffL) { - PMUState = kPMUStateReadyForCommand; - SetPMUbus(0xFF); - } else { - if (0 == PMU_rem) { - PMU_p = nullpr; - PmuCheckCommandOp(); - if (nullpr == PMU_p) { - /* default handler */ - LocBuffSetUpNextChunk(); - } - } - PMU_SendNext = *PMU_p++; - --PMU_rem; - ++PMU_i; - PMU_Sending = trueblnr; - ICT_add(kICT_PMU_Task, - 20400UL * kCycleScale / 64 * kMyClockMult); - } - } - break; - } -} - -GLOBALPROC PMU_DoTask(void) -{ - if (PMU_Sending) { - PMU_Sending = falseblnr; - SetPMUbus(PMU_SendNext); - PmuFromReady = 0; - } -} +/* PMUEMDEV.c Copyright (C) 2008 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* Power Management Unit EMulated DEVice */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "VIAEMDEV.h" #endif #include "PMUEMDEV.h" /* ReportAbnormalID unused 0x0E0E - 0x0EFF */ enum { kPMUStateReadyForCommand, kPMUStateRecievingLength, kPMUStateRecievingBuffer, kPMUStateRecievedCommand, kPMUStateSendLength, kPMUStateSendBuffer, kPMUStates }; #define PMU_BuffSz 8 LOCALVAR ui3b PMU_BuffA[PMU_BuffSz]; LOCALVAR ui3p PMU_p; LOCALVAR ui3r PMU_rem; LOCALVAR ui3r PMU_i; LOCALVAR int PMUState = kPMUStateReadyForCommand; LOCALVAR ui3r PMU_CurCommand; LOCALVAR ui3r PMU_SendNext; LOCALVAR ui3r PMU_BuffL; LOCALPROC PmuStartSendResult(ui3r ResultCode, ui3r L) { PMU_SendNext = ResultCode; PMU_BuffL = L; PMUState = kPMUStateSendLength; } LOCALVAR ui3b PARAMRAM[128]; LOCALPROC PmuCheckCommandOp(void) { switch (PMU_CurCommand) { case 0x10: /* kPMUpowerCntl - power plane/clock control */ break; case 0x32: /* kPMUxPramWrite - write extended PRAM byte(s) */ if (kPMUStateRecievingBuffer == PMUState) { if (0 == PMU_i) { if (PMU_BuffL >= 2) { PMU_p = PMU_BuffA; PMU_rem = 2; } else { ReportAbnormalID(0x0E01, "PMU_BuffL too small for kPMUxPramWrite"); } } else if (2 == PMU_i) { if ((PMU_BuffA[1] + 2 == PMU_BuffL) && (PMU_BuffA[0] + PMU_BuffA[1] <= 0x80)) { PMU_p = &PARAMRAM[PMU_BuffA[0]]; PMU_rem = PMU_BuffA[1]; } else { ReportAbnormalID(0x0E02, "bad range for kPMUxPramWrite"); } } else { ReportAbnormalID(0x0E03, "Wrong PMU_i for kPMUpramWrite"); } } else if (kPMUStateRecievedCommand == PMUState) { /* already done */ } break; #if 0 case 0xE2: /* kPMUdownloadStatus - PRAM status */ break; #endif case 0xE0: /* kPMUwritePmgrRAM - write to internal PMGR RAM */ break; case 0x21: /* kPMUpMgrADBoff - turn ADB auto-poll off */ if (kPMUStateRecievedCommand == PMUState) { if (0 != PMU_BuffL) { ReportAbnormalID(0x0E04, "kPMUpMgrADBoff nonzero length"); } } break; case 0xEC: /* kPMUPmgrSelfTest - run the PMGR selftest */ if (kPMUStateRecievedCommand == PMUState) { PmuStartSendResult(0, 0); } break; case 0x78: /* kPMUreadINT - get PMGR interrupt data */ case 0x68: /* kPMUbatteryRead - read battery/charger level and status */ case 0x7F: /* kPMUsleepReq - put the system to sleep (sleepSig='MATT') */ if (kPMUStateRecievedCommand == PMUState) { PMU_BuffA[0] = 0; PmuStartSendResult(0, 1); } break; case 0xE8: /* kPMUreadPmgrRAM - read from internal PMGR RAM */ if (kPMUStateRecievedCommand == PMUState) { if ((3 == PMU_BuffL) && (0 == PMU_BuffA[0]) && (0xEE == PMU_BuffA[1]) && (1 == PMU_BuffA[2])) { PMU_BuffA[0] = 1 << 5; PmuStartSendResult(0, 1); } else { PMU_BuffA[0] = 0; PmuStartSendResult(0, 1); /* ReportAbnormal("Unknown kPMUreadPmgrRAM op"); */ } } break; case 0x3A: /* kPMUxPramRead - read extended PRAM byte(s) */ if (kPMUStateRecievedCommand == PMUState) { if ((2 == PMU_BuffL) && (PMU_BuffA[0] + PMU_BuffA[1] <= 0x80)) { PMU_p = &PARAMRAM[PMU_BuffA[0]]; PMU_rem = PMU_BuffA[1]; PmuStartSendResult(0, PMU_rem); } else { ReportAbnormalID(0x0E05, "Unknown kPMUxPramRead op"); } } break; case 0x38: /* kPMUtimeRead - read the time from the clock chip */ if (kPMUStateRecievedCommand == PMUState) { if (0 == PMU_BuffL) { PMU_BuffA[0] = 0; PMU_BuffA[1] = 0; PMU_BuffA[2] = 0; PMU_BuffA[3] = 0; PmuStartSendResult(0, 4); } else { ReportAbnormalID(0x0E06, "Unknown kPMUtimeRead op"); } } break; case 0x31: /* kPMUpramWrite - write the original 20 bytes of PRAM (Portable only) */ if (kPMUStateRecievedCommand == PMUState) { if (20 == PMU_BuffL) { /* done */ } else { ReportAbnormalID(0x0E07, "Unknown kPMUpramWrite op"); } } else if (kPMUStateRecievingBuffer == PMUState) { if (20 == PMU_BuffL) { if (0 == PMU_i) { PMU_p = &PARAMRAM[16]; PMU_rem = 16; } else if (16 == PMU_i) { PMU_p = &PARAMRAM[8]; PMU_rem = 4; } else { ReportAbnormalID(0x0E08, "Wrong PMU_i for kPMUpramWrite"); } } } break; case 0x39: /* kPMUpramRead - read the original 20 bytes of PRAM (Portable only) */ if (kPMUStateRecievedCommand == PMUState) { if (0 == PMU_BuffL) { PmuStartSendResult(0, 20); } else { ReportAbnormalID(0x0E09, "Unknown kPMUpramRead op"); } } else if (kPMUStateSendBuffer == PMUState) { #if 0 { int i; for (i = 0; i < PMU_BuffSz; ++i) { PMU_BuffA[i] = 0; } } #endif if (0 == PMU_i) { PMU_p = &PARAMRAM[16]; PMU_rem = 16; } else if (16 == PMU_i) { PMU_p = &PARAMRAM[8]; PMU_rem = 4; } else { ReportAbnormalID(0x0E0A, "Wrong PMU_i for kPMUpramRead"); } } break; default: if (kPMUStateRecievedCommand == PMUState) { ReportAbnormalID(0x0E0B, "Unknown PMU op"); #if dbglog_HAVE dbglog_writeCStr("Unknown PMU op "); dbglog_writeHex(PMU_CurCommand); dbglog_writeReturn(); dbglog_writeCStr("PMU_BuffL = "); dbglog_writeHex(PMU_BuffL); dbglog_writeReturn(); if (PMU_BuffL <= PMU_BuffSz) { int i; for (i = 0; i < PMU_BuffL; ++i) { dbglog_writeCStr("PMU_BuffA["); dbglog_writeNum(i); dbglog_writeCStr("] = "); dbglog_writeHex(PMU_BuffA[i]); dbglog_writeReturn(); } } #endif } break; } } LOCALPROC LocBuffSetUpNextChunk(void) { PMU_p = PMU_BuffA; PMU_rem = PMU_BuffL - PMU_i; if (PMU_rem >= PMU_BuffSz) { PMU_rem = PMU_BuffSz; } } LOCALFUNC ui3r GetPMUbus(void) { ui3r v; v = VIA1_iA7; v <<= 1; v |= VIA1_iA6; v <<= 1; v |= VIA1_iA5; v <<= 1; v |= VIA1_iA4; v <<= 1; v |= VIA1_iA3; v <<= 1; v |= VIA1_iA2; v <<= 1; v |= VIA1_iA1; v <<= 1; v |= VIA1_iA0; return v; } LOCALPROC SetPMUbus(ui3r v) { VIA1_iA0 = v & 0x01; v >>= 1; VIA1_iA1 = v & 0x01; v >>= 1; VIA1_iA2 = v & 0x01; v >>= 1; VIA1_iA3 = v & 0x01; v >>= 1; VIA1_iA4 = v & 0x01; v >>= 1; VIA1_iA5 = v & 0x01; v >>= 1; VIA1_iA6 = v & 0x01; v >>= 1; VIA1_iA7 = v & 0x01; } LOCALVAR blnr PMU_Sending = falseblnr; LOCALPROC PmuCheckCommandCompletion(void) { if (PMU_i == PMU_BuffL) { PMUState = kPMUStateRecievedCommand; PmuCheckCommandOp(); if ((PMU_CurCommand & 0x08) == 0) { PMUState = kPMUStateReadyForCommand; SetPMUbus(0xFF); } else { if (PMUState != kPMUStateSendLength) { PmuStartSendResult(0xFF, 0); PMUState = kPMUStateSendLength; } PMU_i = 0; PMU_Sending = trueblnr; ICT_add(kICT_PMU_Task, 20400UL * kCycleScale / 64 * kMyClockMult); } } } GLOBALPROC PmuToReady_ChangeNtfy(void) { if (PMU_Sending) { PMU_Sending = falseblnr; ReportAbnormalID(0x0E0C, "PmuToReady_ChangeNtfy while PMU_Sending"); PmuFromReady = 0; } switch (PMUState) { case kPMUStateReadyForCommand: if (! PmuToReady) { PmuFromReady = 0; } else { PMU_CurCommand = GetPMUbus(); PMUState = kPMUStateRecievingLength; PmuFromReady = 1; } break; case kPMUStateRecievingLength: if (! PmuToReady) { PmuFromReady = 0; } else { PMU_BuffL = GetPMUbus(); PMU_i = 0; PMU_rem = 0; PMUState = kPMUStateRecievingBuffer; PmuCheckCommandCompletion(); PmuFromReady = 1; } break; case kPMUStateRecievingBuffer: if (! PmuToReady) { PmuFromReady = 0; } else { ui3r v = GetPMUbus(); if (0 == PMU_rem) { PMU_p = nullpr; PmuCheckCommandOp(); if (nullpr == PMU_p) { /* default handler */ LocBuffSetUpNextChunk(); } } if (nullpr == PMU_p) { /* mini vmac bug if ever happens */ ReportAbnormalID(0x0E0D, "PMU_p null while kPMUStateRecievingBuffer"); } *PMU_p++ = v; --PMU_rem; ++PMU_i; PmuCheckCommandCompletion(); PmuFromReady = 1; } break; case kPMUStateSendLength: if (! PmuToReady) { /* receiving */ PmuFromReady = 1; } else { PMU_SendNext = PMU_BuffL; PMUState = kPMUStateSendBuffer; PMU_Sending = trueblnr; ICT_add(kICT_PMU_Task, 20400UL * kCycleScale / 64 * kMyClockMult); } break; case kPMUStateSendBuffer: if (! PmuToReady) { /* receiving */ PmuFromReady = 1; } else { if (PMU_i == PMU_BuffL) { PMUState = kPMUStateReadyForCommand; SetPMUbus(0xFF); } else { if (0 == PMU_rem) { PMU_p = nullpr; PmuCheckCommandOp(); if (nullpr == PMU_p) { /* default handler */ LocBuffSetUpNextChunk(); } } PMU_SendNext = *PMU_p++; --PMU_rem; ++PMU_i; PMU_Sending = trueblnr; ICT_add(kICT_PMU_Task, 20400UL * kCycleScale / 64 * kMyClockMult); } } break; } } GLOBALPROC PMU_DoTask(void) { if (PMU_Sending) { PMU_Sending = falseblnr; SetPMUbus(PMU_SendNext); PmuFromReady = 0; } } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/PMUEMDEV.h b/Mini vMac/mnvm_core/PMUEMDEV.h index 22e5dfa..5e59d2a 100755 --- a/Mini vMac/mnvm_core/PMUEMDEV.h +++ b/Mini vMac/mnvm_core/PMUEMDEV.h @@ -1,24 +1 @@ -/* - PMUEMDEV.h - - Copyright (C) 2008 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef PMUEMDEV_H -#error "header already included" -#else -#define PMUEMDEV_H -#endif - -EXPORTPROC PmuToReady_ChangeNtfy(void); -EXPORTPROC PMU_DoTask(void); +/* PMUEMDEV.h Copyright (C) 2008 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef PMUEMDEV_H #error "header already included" #else #define PMUEMDEV_H #endif EXPORTPROC PmuToReady_ChangeNtfy(void); EXPORTPROC PMU_DoTask(void); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/PROGMAIN.c b/Mini vMac/mnvm_core/PROGMAIN.c index 3701f0d..9fe2b3a 100755 --- a/Mini vMac/mnvm_core/PROGMAIN.c +++ b/Mini vMac/mnvm_core/PROGMAIN.c @@ -1,562 +1 @@ -/* - PROGMAIN.c - - Copyright (C) 2009 Bernd Schmidt, Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - PROGram MAIN. -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" - -#include "MYOSGLUE.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" -#include "M68KITAB.h" -#include "MINEM68K.h" -#include "VIAEMDEV.h" -#if EmVIA2 -#include "VIA2EMDV.h" -#endif -#include "IWMEMDEV.h" -#include "SCCEMDEV.h" -#if EmRTC -#include "RTCEMDEV.h" -#endif -#include "ROMEMDEV.h" -#include "SCSIEMDV.h" -#include "SONYEMDV.h" -#include "SCRNEMDV.h" -#if EmVidCard -#include "VIDEMDEV.h" -#endif -#if EmClassicKbrd -#include "KBRDEMDV.h" -#elif EmPMU -#include "PMUEMDEV.h" -#else -#include "ADBEMDEV.h" -#endif -#if EmASC -#include "ASCEMDEV.h" -#else -#if MySoundEnabled && (CurEmMd != kEmMd_PB100) -#include "SNDEMDEV.h" -#endif -#endif -#include "MOUSEMDV.h" -#endif - - -#include "PROGMAIN.h" - -LOCALPROC EmulatedHardwareZap(void) -{ - Memory_Reset(); - ICT_Zap(); - IWM_Reset(); - SCC_Reset(); - SCSI_Reset(); - VIA1_Zap(); -#if EmVIA2 - VIA2_Zap(); -#endif - Sony_Reset(); - Extn_Reset(); - m68k_reset(); -} - -LOCALPROC DoMacReset(void) -{ - Sony_EjectAllDisks(); - EmulatedHardwareZap(); -} - -LOCALPROC InterruptReset_Update(void) -{ - SetInterruptButton(falseblnr); - /* - in case has been set. so only stays set - for 60th of a second. - */ - - if (WantMacInterrupt) { - SetInterruptButton(trueblnr); - WantMacInterrupt = falseblnr; - } - if (WantMacReset) { - DoMacReset(); - WantMacReset = falseblnr; - } -} - -LOCALPROC SubTickNotify(int SubTick) -{ -#if 0 - dbglog_writeCStr("ending sub tick "); - dbglog_writeNum(SubTick); - dbglog_writeReturn(); -#endif -#if EmASC - ASC_SubTick(SubTick); -#else -#if MySoundEnabled && (CurEmMd != kEmMd_PB100) - MacSound_SubTick(SubTick); -#else - UnusedParam(SubTick); -#endif -#endif -} - -#define CyclesScaledPerTick (130240UL * kMyClockMult * kCycleScale) -#define CyclesScaledPerSubTick (CyclesScaledPerTick / kNumSubTicks) - -LOCALVAR ui4r SubTickCounter; - -LOCALPROC SubTickTaskDo(void) -{ - SubTickNotify(SubTickCounter); - ++SubTickCounter; - if (SubTickCounter < (kNumSubTicks - 1)) { - /* - final SubTick handled by SubTickTaskEnd, - since CyclesScaledPerSubTick * kNumSubTicks - might not equal CyclesScaledPerTick. - */ - - ICT_add(kICT_SubTick, CyclesScaledPerSubTick); - } -} - -LOCALPROC SubTickTaskStart(void) -{ - SubTickCounter = 0; - ICT_add(kICT_SubTick, CyclesScaledPerSubTick); -} - -LOCALPROC SubTickTaskEnd(void) -{ - SubTickNotify(kNumSubTicks - 1); -} - -LOCALPROC SixtiethSecondNotify(void) -{ -#if dbglog_HAVE && 0 - dbglog_StartLine(); - dbglog_writeCStr("begin new Sixtieth"); - dbglog_writeReturn(); -#endif - Mouse_Update(); - InterruptReset_Update(); -#if EmClassicKbrd - KeyBoard_Update(); -#endif -#if EmADB - ADB_Update(); -#endif - - Sixtieth_PulseNtfy(); /* Vertical Blanking Interrupt */ - Sony_Update(); - -#if EmLocalTalk - LocalTalkTick(); -#endif -#if EmRTC - RTC_Interrupt(); -#endif -#if EmVidCard - Vid_Update(); -#endif - - SubTickTaskStart(); -} - -LOCALPROC SixtiethEndNotify(void) -{ - SubTickTaskEnd(); - Mouse_EndTickNotify(); - Screen_EndTickNotify(); -#if dbglog_HAVE && 0 - dbglog_StartLine(); - dbglog_writeCStr("end Sixtieth"); - dbglog_writeReturn(); -#endif -} - -LOCALPROC ExtraTimeBeginNotify(void) -{ -#if 0 - dbglog_writeCStr("begin extra time"); - dbglog_writeReturn(); -#endif - VIA1_ExtraTimeBegin(); -#if EmVIA2 - VIA2_ExtraTimeBegin(); -#endif -} - -LOCALPROC ExtraTimeEndNotify(void) -{ - VIA1_ExtraTimeEnd(); -#if EmVIA2 - VIA2_ExtraTimeEnd(); -#endif -#if 0 - dbglog_writeCStr("end extra time"); - dbglog_writeReturn(); -#endif -} - -GLOBALPROC EmulationReserveAlloc(void) -{ - ReserveAllocOneBlock(&RAM, - kRAM_Size + RAMSafetyMarginFudge, 5, falseblnr); -#if EmVidCard - ReserveAllocOneBlock(&VidROM, kVidROM_Size, 5, falseblnr); -#endif -#if IncludeVidMem - ReserveAllocOneBlock(&VidMem, - kVidMemRAM_Size + RAMSafetyMarginFudge, 5, trueblnr); -#endif -#if SmallGlobals - MINEM68K_ReserveAlloc(); -#endif -} - -LOCALFUNC blnr InitEmulation(void) -{ -#if EmRTC - if (RTC_Init()) -#endif - if (ROM_Init()) -#if EmVidCard - if (Vid_Init()) -#endif - if (AddrSpac_Init()) - { - EmulatedHardwareZap(); - return trueblnr; - } - return falseblnr; -} - -LOCALPROC ICT_DoTask(int taskid) -{ - switch (taskid) { - case kICT_SubTick: - SubTickTaskDo(); - break; -#if EmClassicKbrd - case kICT_Kybd_ReceiveEndCommand: - DoKybd_ReceiveEndCommand(); - break; - case kICT_Kybd_ReceiveCommand: - DoKybd_ReceiveCommand(); - break; -#endif -#if EmADB - case kICT_ADB_NewState: - ADB_DoNewState(); - break; -#endif -#if EmPMU - case kICT_PMU_Task: - PMU_DoTask(); - break; -#endif - case kICT_VIA1_Timer1Check: - VIA1_DoTimer1Check(); - break; - case kICT_VIA1_Timer2Check: - VIA1_DoTimer2Check(); - break; -#if EmVIA2 - case kICT_VIA2_Timer1Check: - VIA2_DoTimer1Check(); - break; - case kICT_VIA2_Timer2Check: - VIA2_DoTimer2Check(); - break; -#endif - default: - ReportAbnormal("unknown taskid in ICT_DoTask"); - break; - } -} - -LOCALPROC ICT_DoCurrentTasks(void) -{ - int i = 0; - uimr m = ICTactive; - - while (0 != m) { - if (0 != (m & 1)) { - if (i >= kNumICTs) { - /* shouldn't happen */ - ICTactive &= ((1 << kNumICTs) - 1); - m = 0; - } else if (ICTwhen[i] == NextiCount) { - ICTactive &= ~ (1 << i); -#ifdef _VIA_Debug - fprintf(stderr, "doing task %d, %d\n", NextiCount, i); -#endif - ICT_DoTask(i); - - /* - A Task may set the time of - any task, including itself. - But it cannot set any task - to execute immediately, so - one pass is sufficient. - */ - } - } - ++i; - m >>= 1; - } -} - -LOCALFUNC ui5b ICT_DoGetNext(ui5b maxn) -{ - int i = 0; - uimr m = ICTactive; - ui5b v = maxn; - - while (0 != m) { - if (0 != (m & 1)) { - if (i >= kNumICTs) { - /* shouldn't happen */ - m = 0; - } else { - ui5b d = ICTwhen[i] - NextiCount; - /* at this point d must be > 0 */ - if (d < v) { -#ifdef _VIA_Debug - fprintf(stderr, "coming task %d, %d, %d\n", - NextiCount, i, d); -#endif - v = d; - } - } - } - ++i; - m >>= 1; - } - - return v; -} - -LOCALPROC m68k_go_nCycles_1(ui5b n) -{ - ui5b n2; - ui5b StopiCount = NextiCount + n; - do { - ICT_DoCurrentTasks(); - n2 = ICT_DoGetNext(n); -#if dbglog_HAVE && 0 - dbglog_StartLine(); - dbglog_writeCStr("before m68k_go_nCycles, NextiCount:"); - dbglog_writeHex(NextiCount); - dbglog_writeCStr(", n2:"); - dbglog_writeHex(n2); - dbglog_writeCStr(", n:"); - dbglog_writeHex(n); - dbglog_writeReturn(); -#endif - NextiCount += n2; - m68k_go_nCycles(n2); - n = StopiCount - NextiCount; - } while (n != 0); -} - -LOCALVAR ui5b ExtraSubTicksToDo = 0; - -LOCALPROC DoEmulateOneTick(void) -{ -#if EnableAutoSlow - { - ui5r NewQuietTime = QuietTime + 1; - - if (NewQuietTime > QuietTime) { - /* if not overflow */ - QuietTime = NewQuietTime; - } - } -#endif -#if EnableAutoSlow - { - ui5r NewQuietSubTicks = QuietSubTicks + kNumSubTicks; - - if (NewQuietSubTicks > QuietSubTicks) { - /* if not overflow */ - QuietSubTicks = NewQuietSubTicks; - } - } -#endif - - SixtiethSecondNotify(); - - m68k_go_nCycles_1(CyclesScaledPerTick); - - SixtiethEndNotify(); - - if ((ui3b) -1 == SpeedValue) { - ExtraSubTicksToDo = (ui5b) -1; - } else { - ui5b ExtraAdd = (kNumSubTicks << SpeedValue) - kNumSubTicks; - ui5b ExtraLimit = ExtraAdd << 3; - - ExtraSubTicksToDo += ExtraAdd; - if (ExtraSubTicksToDo > ExtraLimit) { - ExtraSubTicksToDo = ExtraLimit; - } - } -} - -LOCALFUNC blnr MoreSubTicksToDo(void) -{ - blnr v = falseblnr; - - if (ExtraTimeNotOver() && (ExtraSubTicksToDo > 0)) { -#if EnableAutoSlow - if ((QuietSubTicks >= 16384) - && (QuietTime >= 34) - && ! WantNotAutoSlow) - { - ExtraSubTicksToDo = 0; - } else -#endif - { - v = trueblnr; - } - } - - return v; -} - -LOCALPROC DoEmulateExtraTime(void) -{ - /* - DoEmulateExtraTime is used for - anything over emulation speed - of 1x. It periodically calls - ExtraTimeNotOver and stops - when this returns false (or it - is finished with emulating the - extra time). - */ - - if (MoreSubTicksToDo()) { - ExtraTimeBeginNotify(); - do { -#if EnableAutoSlow - { - ui5r NewQuietSubTicks = QuietSubTicks + 1; - - if (NewQuietSubTicks > QuietSubTicks) { - /* if not overflow */ - QuietSubTicks = NewQuietSubTicks; - } - } -#endif - m68k_go_nCycles_1(CyclesScaledPerSubTick); - --ExtraSubTicksToDo; - } while (MoreSubTicksToDo()); - ExtraTimeEndNotify(); - } -} - -LOCALVAR ui5b CurEmulatedTime = 0; - /* - The number of ticks that have been - emulated so far. - - That is, the number of times - "DoEmulateOneTick" has been called. - */ - -LOCALPROC RunEmulatedTicksToTrueTime(void) -{ - /* - The general idea is to call DoEmulateOneTick - once per tick. - - But if emulation is lagging, we'll try to - catch up by calling DoEmulateOneTick multiple - times, unless we're too far behind, in - which case we forget it. - - If emulating one tick takes longer than - a tick we don't want to sit here - forever. So the maximum number of calls - to DoEmulateOneTick is determined at - the beginning, rather than just - calling DoEmulateOneTick until - CurEmulatedTime >= TrueEmulatedTime. - */ - - si3b n = OnTrueTime - CurEmulatedTime; - - if (n > 0) { - DoEmulateOneTick(); - ++CurEmulatedTime; - - DoneWithDrawingForTick(); - - if (n > 8) { - /* emulation not fast enough */ - n = 8; - CurEmulatedTime = OnTrueTime - n; - } - - if (ExtraTimeNotOver() && (--n > 0)) { - /* lagging, catch up */ - - EmVideoDisable = trueblnr; - - do { - DoEmulateOneTick(); - ++CurEmulatedTime; - } while (ExtraTimeNotOver() - && (--n > 0)); - - EmVideoDisable = falseblnr; - } - - EmLagTime = n; - } -} - -LOCALPROC MainEventLoop(void) -{ - for (; ; ) { - WaitForNextTick(); - if (ForceMacOff) { - return; - } - - RunEmulatedTicksToTrueTime(); - - DoEmulateExtraTime(); - } -} - -GLOBALPROC ProgramMain(void) -{ - if (InitEmulation()) - { - MainEventLoop(); - } -} +/* PROGMAIN.c Copyright (C) 2009 Bernd Schmidt, Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* PROGram MAIN. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "M68KITAB.h" #include "MINEM68K.h" #include "VIAEMDEV.h" #if EmVIA2 #include "VIA2EMDV.h" #endif #include "IWMEMDEV.h" #include "SCCEMDEV.h" #if EmRTC #include "RTCEMDEV.h" #endif #include "ROMEMDEV.h" #include "SCSIEMDV.h" #include "SONYEMDV.h" #include "SCRNEMDV.h" #if EmVidCard #include "VIDEMDEV.h" #endif #if EmClassicKbrd #include "KBRDEMDV.h" #elif EmPMU #include "PMUEMDEV.h" #else #include "ADBEMDEV.h" #endif #if EmASC #include "ASCEMDEV.h" #else #if MySoundEnabled && (CurEmMd != kEmMd_PB100) #include "SNDEMDEV.h" #endif #endif #include "MOUSEMDV.h" #endif #include "PROGMAIN.h" /* ReportAbnormalID unused 0x1002 - 0x10FF */ LOCALPROC EmulatedHardwareZap(void) { Memory_Reset(); ICT_Zap(); IWM_Reset(); SCC_Reset(); SCSI_Reset(); VIA1_Zap(); #if EmVIA2 VIA2_Zap(); #endif Sony_Reset(); Extn_Reset(); m68k_reset(); } LOCALPROC DoMacReset(void) { Sony_EjectAllDisks(); EmulatedHardwareZap(); } LOCALPROC InterruptReset_Update(void) { SetInterruptButton(falseblnr); /* in case has been set. so only stays set for 60th of a second. */ if (WantMacInterrupt) { SetInterruptButton(trueblnr); WantMacInterrupt = falseblnr; } if (WantMacReset) { DoMacReset(); WantMacReset = falseblnr; } } LOCALPROC SubTickNotify(int SubTick) { #if 0 dbglog_writeCStr("ending sub tick "); dbglog_writeNum(SubTick); dbglog_writeReturn(); #endif #if EmASC ASC_SubTick(SubTick); #else #if MySoundEnabled && (CurEmMd != kEmMd_PB100) MacSound_SubTick(SubTick); #else UnusedParam(SubTick); #endif #endif } #define CyclesScaledPerTick (130240UL * kMyClockMult * kCycleScale) #define CyclesScaledPerSubTick (CyclesScaledPerTick / kNumSubTicks) LOCALVAR ui4r SubTickCounter; LOCALPROC SubTickTaskDo(void) { SubTickNotify(SubTickCounter); ++SubTickCounter; if (SubTickCounter < (kNumSubTicks - 1)) { /* final SubTick handled by SubTickTaskEnd, since CyclesScaledPerSubTick * kNumSubTicks might not equal CyclesScaledPerTick. */ ICT_add(kICT_SubTick, CyclesScaledPerSubTick); } } LOCALPROC SubTickTaskStart(void) { SubTickCounter = 0; ICT_add(kICT_SubTick, CyclesScaledPerSubTick); } LOCALPROC SubTickTaskEnd(void) { SubTickNotify(kNumSubTicks - 1); } LOCALPROC SixtiethSecondNotify(void) { #if dbglog_HAVE && 0 dbglog_WriteNote("begin new Sixtieth"); #endif Mouse_Update(); InterruptReset_Update(); #if EmClassicKbrd KeyBoard_Update(); #endif #if EmADB ADB_Update(); #endif Sixtieth_PulseNtfy(); /* Vertical Blanking Interrupt */ Sony_Update(); #if EmLocalTalk LocalTalkTick(); #endif #if EmRTC RTC_Interrupt(); #endif #if EmVidCard Vid_Update(); #endif SubTickTaskStart(); } LOCALPROC SixtiethEndNotify(void) { SubTickTaskEnd(); Mouse_EndTickNotify(); Screen_EndTickNotify(); #if dbglog_HAVE && 0 dbglog_WriteNote("end Sixtieth"); #endif } LOCALPROC ExtraTimeBeginNotify(void) { #if 0 dbglog_writeCStr("begin extra time"); dbglog_writeReturn(); #endif VIA1_ExtraTimeBegin(); #if EmVIA2 VIA2_ExtraTimeBegin(); #endif } LOCALPROC ExtraTimeEndNotify(void) { VIA1_ExtraTimeEnd(); #if EmVIA2 VIA2_ExtraTimeEnd(); #endif #if 0 dbglog_writeCStr("end extra time"); dbglog_writeReturn(); #endif } GLOBALPROC EmulationReserveAlloc(void) { ReserveAllocOneBlock(&RAM, kRAM_Size + RAMSafetyMarginFudge, 5, falseblnr); #if EmVidCard ReserveAllocOneBlock(&VidROM, kVidROM_Size, 5, falseblnr); #endif #if IncludeVidMem ReserveAllocOneBlock(&VidMem, kVidMemRAM_Size + RAMSafetyMarginFudge, 5, trueblnr); #endif #if SmallGlobals MINEM68K_ReserveAlloc(); #endif } LOCALFUNC blnr InitEmulation(void) { #if EmRTC if (RTC_Init()) #endif if (ROM_Init()) #if EmVidCard if (Vid_Init()) #endif if (AddrSpac_Init()) { EmulatedHardwareZap(); return trueblnr; } return falseblnr; } LOCALPROC ICT_DoTask(int taskid) { switch (taskid) { case kICT_SubTick: SubTickTaskDo(); break; #if EmClassicKbrd case kICT_Kybd_ReceiveEndCommand: DoKybd_ReceiveEndCommand(); break; case kICT_Kybd_ReceiveCommand: DoKybd_ReceiveCommand(); break; #endif #if EmADB case kICT_ADB_NewState: ADB_DoNewState(); break; #endif #if EmPMU case kICT_PMU_Task: PMU_DoTask(); break; #endif case kICT_VIA1_Timer1Check: VIA1_DoTimer1Check(); break; case kICT_VIA1_Timer2Check: VIA1_DoTimer2Check(); break; #if EmVIA2 case kICT_VIA2_Timer1Check: VIA2_DoTimer1Check(); break; case kICT_VIA2_Timer2Check: VIA2_DoTimer2Check(); break; #endif default: ReportAbnormalID(0x1001, "unknown taskid in ICT_DoTask"); break; } } LOCALPROC ICT_DoCurrentTasks(void) { int i = 0; uimr m = ICTactive; while (0 != m) { if (0 != (m & 1)) { if (i >= kNumICTs) { /* shouldn't happen */ ICTactive &= ((1 << kNumICTs) - 1); m = 0; } else if (ICTwhen[i] == NextiCount) { ICTactive &= ~ (1 << i); #ifdef _VIA_Debug fprintf(stderr, "doing task %d, %d\n", NextiCount, i); #endif ICT_DoTask(i); /* A Task may set the time of any task, including itself. But it cannot set any task to execute immediately, so one pass is sufficient. */ } } ++i; m >>= 1; } } LOCALFUNC ui5b ICT_DoGetNext(ui5b maxn) { int i = 0; uimr m = ICTactive; ui5b v = maxn; while (0 != m) { if (0 != (m & 1)) { if (i >= kNumICTs) { /* shouldn't happen */ m = 0; } else { ui5b d = ICTwhen[i] - NextiCount; /* at this point d must be > 0 */ if (d < v) { #ifdef _VIA_Debug fprintf(stderr, "coming task %d, %d, %d\n", NextiCount, i, d); #endif v = d; } } } ++i; m >>= 1; } return v; } LOCALPROC m68k_go_nCycles_1(ui5b n) { ui5b n2; ui5b StopiCount = NextiCount + n; do { ICT_DoCurrentTasks(); n2 = ICT_DoGetNext(n); #if dbglog_HAVE && 0 dbglog_StartLine(); dbglog_writeCStr("before m68k_go_nCycles, NextiCount:"); dbglog_writeHex(NextiCount); dbglog_writeCStr(", n2:"); dbglog_writeHex(n2); dbglog_writeCStr(", n:"); dbglog_writeHex(n); dbglog_writeReturn(); #endif NextiCount += n2; m68k_go_nCycles(n2); n = StopiCount - NextiCount; } while (n != 0); } LOCALVAR ui5b ExtraSubTicksToDo = 0; LOCALPROC DoEmulateOneTick(void) { #if EnableAutoSlow { ui5r NewQuietTime = QuietTime + 1; if (NewQuietTime > QuietTime) { /* if not overflow */ QuietTime = NewQuietTime; } } #endif #if EnableAutoSlow { ui5r NewQuietSubTicks = QuietSubTicks + kNumSubTicks; if (NewQuietSubTicks > QuietSubTicks) { /* if not overflow */ QuietSubTicks = NewQuietSubTicks; } } #endif SixtiethSecondNotify(); m68k_go_nCycles_1(CyclesScaledPerTick); SixtiethEndNotify(); if ((ui3b) -1 == SpeedValue) { ExtraSubTicksToDo = (ui5b) -1; } else { ui5b ExtraAdd = (kNumSubTicks << SpeedValue) - kNumSubTicks; ui5b ExtraLimit = ExtraAdd << 3; ExtraSubTicksToDo += ExtraAdd; if (ExtraSubTicksToDo > ExtraLimit) { ExtraSubTicksToDo = ExtraLimit; } } } LOCALFUNC blnr MoreSubTicksToDo(void) { blnr v = falseblnr; if (ExtraTimeNotOver() && (ExtraSubTicksToDo > 0)) { #if EnableAutoSlow if ((QuietSubTicks >= 16384) && (QuietTime >= 34) && ! WantNotAutoSlow) { ExtraSubTicksToDo = 0; } else #endif { v = trueblnr; } } return v; } LOCALPROC DoEmulateExtraTime(void) { /* DoEmulateExtraTime is used for anything over emulation speed of 1x. It periodically calls ExtraTimeNotOver and stops when this returns false (or it is finished with emulating the extra time). */ if (MoreSubTicksToDo()) { ExtraTimeBeginNotify(); do { #if EnableAutoSlow { ui5r NewQuietSubTicks = QuietSubTicks + 1; if (NewQuietSubTicks > QuietSubTicks) { /* if not overflow */ QuietSubTicks = NewQuietSubTicks; } } #endif m68k_go_nCycles_1(CyclesScaledPerSubTick); --ExtraSubTicksToDo; } while (MoreSubTicksToDo()); ExtraTimeEndNotify(); } } LOCALVAR ui5b CurEmulatedTime = 0; /* The number of ticks that have been emulated so far. That is, the number of times "DoEmulateOneTick" has been called. */ LOCALPROC RunEmulatedTicksToTrueTime(void) { /* The general idea is to call DoEmulateOneTick once per tick. But if emulation is lagging, we'll try to catch up by calling DoEmulateOneTick multiple times, unless we're too far behind, in which case we forget it. If emulating one tick takes longer than a tick we don't want to sit here forever. So the maximum number of calls to DoEmulateOneTick is determined at the beginning, rather than just calling DoEmulateOneTick until CurEmulatedTime >= TrueEmulatedTime. */ si3b n = OnTrueTime - CurEmulatedTime; if (n > 0) { DoEmulateOneTick(); ++CurEmulatedTime; DoneWithDrawingForTick(); if (n > 8) { /* emulation not fast enough */ n = 8; CurEmulatedTime = OnTrueTime - n; } if (ExtraTimeNotOver() && (--n > 0)) { /* lagging, catch up */ EmVideoDisable = trueblnr; do { DoEmulateOneTick(); ++CurEmulatedTime; } while (ExtraTimeNotOver() && (--n > 0)); EmVideoDisable = falseblnr; } EmLagTime = n; } } LOCALPROC MainEventLoop(void) { for (; ; ) { WaitForNextTick(); if (ForceMacOff) { return; } RunEmulatedTicksToTrueTime(); DoEmulateExtraTime(); } } GLOBALPROC ProgramMain(void) { if (InitEmulation()) { MainEventLoop(); } } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/PROGMAIN.h b/Mini vMac/mnvm_core/PROGMAIN.h index 72c4b1c..9a3db71 100755 --- a/Mini vMac/mnvm_core/PROGMAIN.h +++ b/Mini vMac/mnvm_core/PROGMAIN.h @@ -1,25 +1 @@ -/* - PROGMAIN.h - - Copyright (C) 2009 Philip Cummins, Richard F. Bannister, - Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef PROGMAIN_H -#error "header already included" -#else -#define PROGMAIN_H -#endif - -EXPORTPROC EmulationReserveAlloc(void); -EXPORTPROC ProgramMain(void); +/* PROGMAIN.h Copyright (C) 2009 Philip Cummins, Richard F. Bannister, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef PROGMAIN_H #error "header already included" #else #define PROGMAIN_H #endif EXPORTPROC EmulationReserveAlloc(void); EXPORTPROC ProgramMain(void); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/ROMEMDEV.c b/Mini vMac/mnvm_core/ROMEMDEV.c index 3660aac..8edf6a1 100755 --- a/Mini vMac/mnvm_core/ROMEMDEV.c +++ b/Mini vMac/mnvm_core/ROMEMDEV.c @@ -1,325 +1 @@ -/* - ROMEMDEV.c - - Copyright (C) 2007 Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - Read Only Memory EMulated DEVice - - Checks the header of the loaded ROM image, and then patches - the ROM image. - - This code descended from "ROM.c" in vMac by Philip Cummins. -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" -#include "MYOSGLUE.h" -#include "ENDIANAC.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" -#endif - -#include "ROMEMDEV.h" - -#define UseSonyPatch \ - ((CurEmMd <= kEmMd_Classic) || (CurEmMd == kEmMd_II) \ - || (CurEmMd == kEmMd_IIx)) - -#define UseLargeScreenHack \ - (IncludeVidMem \ - && (CurEmMd != kEmMd_PB100) \ - && (CurEmMd != kEmMd_II) \ - && (CurEmMd != kEmMd_IIx)) - -#if UseSonyPatch -LOCALVAR const ui3b sony_driver[] = { -/* - Replacement for .Sony driver - 68k machine code, compiled from mydriver.a -*/ -0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xEE, 0x00, 0x18, 0x00, 0x24, 0x00, 0x4A, -0x00, 0x8A, 0x05, 0x2E, 0x53, 0x6F, 0x6E, 0x79, -0x48, 0xE7, 0x00, 0xC0, 0x55, 0x4F, 0x3F, 0x3C, -0x00, 0x01, 0x60, 0x30, 0x48, 0xE7, 0x00, 0xC0, -0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x02, 0x41, 0xFA, -0x01, 0x84, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, -0x5C, 0x4F, 0x30, 0x1F, 0x4C, 0xDF, 0x03, 0x00, -0x0C, 0x68, 0x00, 0x01, 0x00, 0x1A, 0x66, 0x1E, -0x4E, 0x75, 0x48, 0xE7, 0x00, 0xC0, 0x55, 0x4F, -0x3F, 0x3C, 0x00, 0x03, 0x41, 0xFA, 0x01, 0x5E, -0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, -0x30, 0x1F, 0x4C, 0xDF, 0x03, 0x00, 0x32, 0x28, -0x00, 0x06, 0x08, 0x01, 0x00, 0x09, 0x67, 0x0C, -0x4A, 0x40, 0x6F, 0x02, 0x42, 0x40, 0x31, 0x40, -0x00, 0x10, 0x4E, 0x75, 0x4A, 0x40, 0x6F, 0x04, -0x42, 0x40, 0x4E, 0x75, 0x2F, 0x38, 0x08, 0xFC, -0x4E, 0x75, 0x48, 0xE7, 0x00, 0xC0, 0x55, 0x4F, -0x3F, 0x3C, 0x00, 0x04, 0x41, 0xFA, 0x01, 0x1E, -0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, -0x30, 0x1F, 0x4C, 0xDF, 0x03, 0x00, 0x4E, 0x75, -0x48, 0xE7, 0xE0, 0xC0, 0x20, 0x2F, 0x00, 0x14, -0x59, 0x4F, 0x2F, 0x00, 0x55, 0x4F, 0x3F, 0x3C, -0x00, 0x08, 0x41, 0xFA, 0x00, 0xF8, 0x2F, 0x18, -0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, 0x32, 0x1F, -0x58, 0x4F, 0x20, 0x1F, 0x4A, 0x41, 0x66, 0x06, -0x30, 0x7C, 0x00, 0x07, 0xA0, 0x2F, 0x4C, 0xDF, -0x03, 0x07, 0x58, 0x4F, 0x4E, 0x73, 0x21, 0x40, -0x00, 0x06, 0x43, 0xF8, 0x03, 0x08, 0x4E, 0xF9, -0x00, 0x40, 0x0B, 0x20, 0x4E, 0x75, 0x48, 0xE7, -0x1F, 0x10, 0x48, 0xE7, 0x00, 0xC0, 0x5D, 0x4F, -0x3F, 0x3C, 0x00, 0x05, 0x41, 0xFA, 0x00, 0xB6, -0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, -0x30, 0x1F, 0x2E, 0x1F, 0x0C, 0x40, 0xFF, 0xCF, -0x66, 0x06, 0x42, 0x40, 0x60, 0x00, 0x00, 0x8E, -0x4A, 0x40, 0x66, 0x00, 0x00, 0x88, 0x20, 0x07, -0xA7, 0x1E, 0x26, 0x48, 0x20, 0x0B, 0x67, 0x00, -0x00, 0x86, 0x9E, 0xFC, 0x00, 0x10, 0x2F, 0x0B, -0x2F, 0x07, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x06, -0x41, 0xFA, 0x00, 0x7A, 0x2F, 0x18, 0x20, 0x50, -0x20, 0x8F, 0x5C, 0x4F, 0x30, 0x1F, 0x50, 0x4F, -0x2E, 0x1F, 0x76, 0x00, 0x36, 0x1F, 0x38, 0x1F, -0x3C, 0x1F, 0x3A, 0x1F, 0x26, 0x5F, 0x4A, 0x40, -0x66, 0x4A, 0x20, 0x0B, 0x67, 0x0E, 0x41, 0xFA, -0xFF, 0x8C, 0x27, 0x48, 0x00, 0x06, 0x20, 0x4B, -0xA0, 0x58, 0x60, 0x1A, 0x41, 0xFA, 0xFF, 0x70, -0x30, 0x3C, 0xA0, 0x4E, 0xA0, 0x47, 0x60, 0x0E, -0x20, 0x47, 0x30, 0x06, 0x48, 0x40, 0x30, 0x05, -0xA0, 0x4E, 0xDE, 0x83, 0x52, 0x46, 0x51, 0xCC, -0xFF, 0xF0, 0x48, 0x7A, 0xFF, 0x1C, 0x55, 0x4F, -0x3F, 0x3C, 0x00, 0x07, 0x41, 0xFA, 0x00, 0x1E, -0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, -0x30, 0x1F, 0x58, 0x4F, 0x4C, 0xDF, 0x03, 0x00, -0x4C, 0xDF, 0x08, 0xF8, 0x4E, 0x75, 0x30, 0x3C, -0xFF, 0xFF, 0x60, 0xF0 -}; -#endif - -#if UseSonyPatch -LOCALVAR const ui3b my_disk_icon[] = { - 0x7F, 0xFF, 0xFF, 0xF0, - 0x81, 0x00, 0x01, 0x08, - 0x81, 0x00, 0x71, 0x04, - 0x81, 0x00, 0x89, 0x02, - 0x81, 0x00, 0x89, 0x01, - 0x81, 0x00, 0x89, 0x01, - 0x81, 0x00, 0x89, 0x01, - 0x81, 0x00, 0x89, 0x01, - 0x81, 0x00, 0x89, 0x01, - 0x81, 0x00, 0x71, 0x01, - 0x81, 0x00, 0x01, 0x01, - 0x80, 0xFF, 0xFE, 0x01, - 0x80, 0x00, 0x00, 0x01, - 0x80, 0x00, 0x00, 0x01, - 0x80, 0x00, 0x00, 0x01, - 0x80, 0x00, 0x00, 0x01, - 0x83, 0xFF, 0xFF, 0xC1, - 0x84, 0x00, 0x00, 0x21, - 0x84, 0x00, 0x00, 0x21, - 0x84, 0x00, 0x00, 0x21, - 0x84, 0x00, 0x00, 0x21, - 0x84, 0x00, 0x00, 0x21, - 0x84, 0x06, 0x30, 0x21, - 0x84, 0x06, 0x60, 0x21, - 0x84, 0x06, 0xC0, 0x21, - 0x84, 0x07, 0x80, 0x21, - 0x84, 0x07, 0x00, 0x21, - 0x84, 0x06, 0x00, 0x21, - 0x84, 0x00, 0x00, 0x21, - 0x84, 0x00, 0x00, 0x21, - 0x84, 0x00, 0x00, 0x21, - 0x7F, 0xFF, 0xFF, 0xFE, - - /* mask */ - - 0x3F, 0xFF, 0xFF, 0xF0, - 0x7F, 0xFF, 0xFF, 0xF0, - 0xFF, 0xFF, 0xFF, 0xFC, - 0xFF, 0xFF, 0xFF, 0xFC, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0x7F, 0xFF, 0xFF, 0xFC, - 0x3F, 0xFF, 0xFF, 0xFC, - - /* empty pascal string */ - 0x00, 0x00, -}; -#endif - -#if CurEmMd <= kEmMd_128K -#define Sony_DriverBase 0x1690 -#elif CurEmMd <= kEmMd_Plus -#define Sony_DriverBase 0x17D30 -#elif CurEmMd <= kEmMd_Classic -#define Sony_DriverBase 0x34680 -#elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) -#define Sony_DriverBase 0x2D72C -#endif - -#define kVidMem_Base 0x00540000 - -#if UseSonyPatch -LOCALPROC Sony_Install(void) -{ - ui3p pto = Sony_DriverBase + ROM; - - MyMoveBytes((anyp)sony_driver, (anyp)pto, sizeof(sony_driver)); - pto += sizeof(sony_driver); - - do_put_mem_word(pto, kcom_callcheck); - pto += 2; - do_put_mem_word(pto, kExtnSony); - pto += 2; - do_put_mem_long(pto, kExtn_Block_Base); /* pokeaddr */ - pto += 4; - - my_disk_icon_addr = (pto - ROM) + kROM_Base; - MyMoveBytes((anyp)my_disk_icon, (anyp)pto, sizeof(my_disk_icon)); - pto += sizeof(my_disk_icon); - -#if UseLargeScreenHack - { - ui3p patchp = pto; - -#include "SCRNHACK.h" - } -#endif - - (void) pto; /* avoid warning about unused */ -} -#endif - -LOCALFUNC blnr Check_Checksum(ui5r CheckSum1) -{ - long int i; - ui5b CheckSum2 = 0; - ui3p p = 4 + ROM; - - for (i = (kCheckSumRom_Size - 4) >> 1; --i >= 0; ) { - CheckSum2 += do_get_mem_word(p); - p += 2; - } - return (CheckSum1 == CheckSum2); -} - -GLOBALFUNC blnr ROM_Init(void) -{ - ui5r CheckSum = do_get_mem_long(ROM); - - if (! Check_Checksum(CheckSum)) { - WarnMsgCorruptedROM(); - } else -#if CurEmMd <= kEmMd_128K - if (CheckSum == 0x28BA61CE) { - } else - if (CheckSum == 0x28BA4E50) { - } else -#elif CurEmMd <= kEmMd_Plus - if (CheckSum == 0x4D1EEEE1) { - /* Mac Plus ROM v 1, 'Lonely Hearts' */ - } else - if (CheckSum == 0x4D1EEAE1) { - /* Mac Plus ROM v 2, 'Lonely Heifers' */ - } else - if (CheckSum == 0x4D1F8172) { - /* Mac Plus ROM v 3, 'Loud Harmonicas' */ - } else -#elif CurEmMd <= kEmMd_SE - if (CheckSum == 0xB2E362A8) { - } else -#elif CurEmMd <= kEmMd_SEFDHD - if (CheckSum == 0xB306E171) { - } else -#elif CurEmMd <= kEmMd_Classic - if (CheckSum == 0xA49F9914) { - } else -#elif CurEmMd <= kEmMd_PB100 - if (CheckSum == 0x96645F9C) { - } else -#elif CurEmMd <= kEmMd_II - if (CheckSum == 0x9779D2C4) { - } else - if (CheckSum == 0x97221136) { - /* accept IIx ROM */ - } else -#elif CurEmMd <= kEmMd_IIx - if (CheckSum == 0x97221136) { - } else -#endif - { - WarnMsgUnsupportedROM(); - } - /* - Even if ROM is corrupt or unsupported, go ahead and - try to run anyway. It shouldn't do any harm. - */ - -/* skip the rom checksum */ -#if CurEmMd <= kEmMd_128K - do_put_mem_word(226 + ROM, 0x6004); -#elif CurEmMd <= kEmMd_Plus - do_put_mem_word(3450 + ROM, 0x6022); -#elif CurEmMd <= kEmMd_Classic - do_put_mem_word(7272 + ROM, 0x6008); -#elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) - do_put_mem_word(0x2AB0 + ROM, 0x6008); -#endif - -#if CurEmMd <= kEmMd_128K -#elif CurEmMd <= kEmMd_Plus - do_put_mem_word(3752 + ROM, 0x4E71); - /* shorten the ram check read */ - do_put_mem_word(3728 + ROM, 0x4E71); - /* shorten the ram check write */ -#elif CurEmMd <= kEmMd_Classic - do_put_mem_word(134 + ROM, 0x6002); - do_put_mem_word(286 + ROM, 0x6002); -#elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) - do_put_mem_word(0xEE + ROM, 0x6002); - do_put_mem_word(0x1AA + ROM, 0x6002); -#endif - - /* do_put_mem_word(862 + ROM, 0x4E71); */ /* shorten set memory */ - -#if UseSonyPatch - Sony_Install(); -#endif - - return trueblnr; -} +/* ROMEMDEV.c Copyright (C) 2007 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* Read Only Memory EMulated DEVice Checks the header of the loaded ROM image, and then patches the ROM image. This code descended from "ROM.c" in vMac by Philip Cummins. Support for "Twiggy" Mac by Mathew Hybler. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "ENDIANAC.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif #include "ROMEMDEV.h" #define UseSonyPatch \ ((CurEmMd <= kEmMd_Classic) || (CurEmMd == kEmMd_II) \ || (CurEmMd == kEmMd_IIx)) #ifndef UseLargeScreenHack #define UseLargeScreenHack 0 #endif #if UseSonyPatch LOCALVAR const ui3b sony_driver[] = { /* Replacement for .Sony driver 68k machine code, compiled from mydriver.a */ 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x18, 0x00, 0x24, 0x00, 0x4A, 0x00, 0x8A, 0x05, 0x2E, 0x53, 0x6F, 0x6E, 0x79, 0x48, 0xE7, 0x00, 0xC0, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x01, 0x60, 0x30, 0x48, 0xE7, 0x00, 0xC0, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x02, 0x41, 0xFA, 0x01, 0x84, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, 0x30, 0x1F, 0x4C, 0xDF, 0x03, 0x00, 0x0C, 0x68, 0x00, 0x01, 0x00, 0x1A, 0x66, 0x1E, 0x4E, 0x75, 0x48, 0xE7, 0x00, 0xC0, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x03, 0x41, 0xFA, 0x01, 0x5E, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, 0x30, 0x1F, 0x4C, 0xDF, 0x03, 0x00, 0x32, 0x28, 0x00, 0x06, 0x08, 0x01, 0x00, 0x09, 0x67, 0x0C, 0x4A, 0x40, 0x6F, 0x02, 0x42, 0x40, 0x31, 0x40, 0x00, 0x10, 0x4E, 0x75, 0x4A, 0x40, 0x6F, 0x04, 0x42, 0x40, 0x4E, 0x75, 0x2F, 0x38, 0x08, 0xFC, 0x4E, 0x75, 0x48, 0xE7, 0x00, 0xC0, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x04, 0x41, 0xFA, 0x01, 0x1E, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, 0x30, 0x1F, 0x4C, 0xDF, 0x03, 0x00, 0x4E, 0x75, 0x48, 0xE7, 0xE0, 0xC0, 0x20, 0x2F, 0x00, 0x14, 0x59, 0x4F, 0x2F, 0x00, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x08, 0x41, 0xFA, 0x00, 0xF8, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, 0x32, 0x1F, 0x58, 0x4F, 0x20, 0x1F, 0x4A, 0x41, 0x66, 0x06, 0x30, 0x7C, 0x00, 0x07, 0xA0, 0x2F, 0x4C, 0xDF, 0x03, 0x07, 0x58, 0x4F, 0x4E, 0x73, 0x21, 0x40, 0x00, 0x06, 0x43, 0xF8, 0x03, 0x08, 0x4E, 0xF9, 0x00, 0x40, 0x0B, 0x20, 0x4E, 0x75, 0x48, 0xE7, 0x1F, 0x10, 0x48, 0xE7, 0x00, 0xC0, 0x5D, 0x4F, 0x3F, 0x3C, 0x00, 0x05, 0x41, 0xFA, 0x00, 0xB6, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, 0x30, 0x1F, 0x2E, 0x1F, 0x0C, 0x40, 0xFF, 0xCF, 0x66, 0x06, 0x42, 0x40, 0x60, 0x00, 0x00, 0x8E, 0x4A, 0x40, 0x66, 0x00, 0x00, 0x88, 0x20, 0x07, 0xA7, 0x1E, 0x26, 0x48, 0x20, 0x0B, 0x67, 0x00, 0x00, 0x86, 0x9E, 0xFC, 0x00, 0x10, 0x2F, 0x0B, 0x2F, 0x07, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x06, 0x41, 0xFA, 0x00, 0x7A, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, 0x30, 0x1F, 0x50, 0x4F, 0x2E, 0x1F, 0x76, 0x00, 0x36, 0x1F, 0x38, 0x1F, 0x3C, 0x1F, 0x3A, 0x1F, 0x26, 0x5F, 0x4A, 0x40, 0x66, 0x4A, 0x20, 0x0B, 0x67, 0x0E, 0x41, 0xFA, 0xFF, 0x8C, 0x27, 0x48, 0x00, 0x06, 0x20, 0x4B, 0xA0, 0x58, 0x60, 0x1A, 0x41, 0xFA, 0xFF, 0x70, 0x30, 0x3C, 0xA0, 0x4E, 0xA0, 0x47, 0x60, 0x0E, 0x20, 0x47, 0x30, 0x06, 0x48, 0x40, 0x30, 0x05, 0xA0, 0x4E, 0xDE, 0x83, 0x52, 0x46, 0x51, 0xCC, 0xFF, 0xF0, 0x48, 0x7A, 0xFF, 0x1C, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x07, 0x41, 0xFA, 0x00, 0x1E, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, 0x30, 0x1F, 0x58, 0x4F, 0x4C, 0xDF, 0x03, 0x00, 0x4C, 0xDF, 0x08, 0xF8, 0x4E, 0x75, 0x30, 0x3C, 0xFF, 0xFF, 0x60, 0xF0 }; #endif #if UseSonyPatch LOCALVAR const ui3b my_disk_icon[] = { 0x7F, 0xFF, 0xFF, 0xF0, 0x81, 0x00, 0x01, 0x08, 0x81, 0x00, 0x71, 0x04, 0x81, 0x00, 0x89, 0x02, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x71, 0x01, 0x81, 0x00, 0x01, 0x01, 0x80, 0xFF, 0xFE, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x83, 0xFF, 0xFF, 0xC1, 0x84, 0x00, 0x00, 0x21, 0x84, 0x00, 0x00, 0x21, 0x84, 0x00, 0x00, 0x21, 0x84, 0x00, 0x00, 0x21, 0x84, 0x00, 0x00, 0x21, 0x84, 0x06, 0x30, 0x21, 0x84, 0x06, 0x60, 0x21, 0x84, 0x06, 0xC0, 0x21, 0x84, 0x07, 0x80, 0x21, 0x84, 0x07, 0x00, 0x21, 0x84, 0x06, 0x00, 0x21, 0x84, 0x00, 0x00, 0x21, 0x84, 0x00, 0x00, 0x21, 0x84, 0x00, 0x00, 0x21, 0x7F, 0xFF, 0xFF, 0xFE, /* mask */ 0x3F, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFC, /* empty pascal string */ 0x00, 0x00, }; #endif #if CurEmMd <= kEmMd_Twig43 #define Sony_DriverBase 0x1836 #elif CurEmMd <= kEmMd_Twiggy #define Sony_DriverBase 0x16E4 #elif CurEmMd <= kEmMd_128K #define Sony_DriverBase 0x1690 #elif CurEmMd <= kEmMd_Plus #define Sony_DriverBase 0x17D30 #elif CurEmMd <= kEmMd_Classic #define Sony_DriverBase 0x34680 #elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) #define Sony_DriverBase 0x2D72C #endif #define kVidMem_Base 0x00540000 #if UseSonyPatch LOCALPROC Sony_Install(void) { ui3p pto = Sony_DriverBase + ROM; MyMoveBytes((anyp)sony_driver, (anyp)pto, sizeof(sony_driver)); #if CurEmMd <= kEmMd_Twiggy do_put_mem_long(pto + 0x14, 0x4469736B); /* 'Disk' instead of 'Sony' */ #if CurEmMd <= kEmMd_Twig43 do_put_mem_word(pto + 0xEA, 0x0C8A); #else do_put_mem_word(pto + 0xEA, 0x0B74); #endif #endif pto += sizeof(sony_driver); do_put_mem_word(pto, kcom_callcheck); pto += 2; do_put_mem_word(pto, kExtnSony); pto += 2; do_put_mem_long(pto, kExtn_Block_Base); /* pokeaddr */ pto += 4; my_disk_icon_addr = (pto - ROM) + kROM_Base; MyMoveBytes((anyp)my_disk_icon, (anyp)pto, sizeof(my_disk_icon)); pto += sizeof(my_disk_icon); #if UseLargeScreenHack { ui3p patchp = pto; #include "SCRNHACK.h" } #endif (void) pto; /* avoid warning about unused */ } #endif #ifndef CheckRomCheckSum #define CheckRomCheckSum 1 #endif #ifndef DisableRomCheck #define DisableRomCheck 1 #endif #ifndef DisableRamTest #define DisableRamTest 1 #endif #if CheckRomCheckSum LOCALFUNC ui5r Calc_Checksum(void) { long int i; ui5b CheckSum = 0; ui3p p = 4 + ROM; for (i = (kCheckSumRom_Size - 4) >> 1; --i >= 0; ) { CheckSum += do_get_mem_word(p); p += 2; } return CheckSum; } #endif #ifdef CurAltHappyMac #include "HPMCHACK.h" #endif #ifdef ln2mtb LOCALPROC ROMscrambleForMTB(void) { si5r j; ui3p p = ROM; ui3p p2 = ROM + (1 << ln2mtb); for (j = kROM_Size / (1 << ln2mtb) / 2; --j >= 0; ) { si5r i; for (i = (1 << ln2mtb); --i >= 0; ) { ui3b t0 = *p; ui3b t1 = *p2; *p++ = t1; *p2++ = t0; } p += (1 << ln2mtb); p2 += (1 << ln2mtb); } } #endif GLOBALFUNC blnr ROM_Init(void) { #if CheckRomCheckSum ui5r CheckSum = Calc_Checksum(); #if CurEmMd >= kEmMd_Twiggy if (CheckSum != do_get_mem_long(ROM)) { WarnMsgCorruptedROM(); } else #endif #if CurEmMd <= kEmMd_Twig43 if (CheckSum == 0x27F4E04B) { } else #elif CurEmMd <= kEmMd_Twiggy if (CheckSum == 0x2884371D) { } else #elif CurEmMd <= kEmMd_128K if (CheckSum == 0x28BA61CE) { } else if (CheckSum == 0x28BA4E50) { } else #elif CurEmMd <= kEmMd_Plus if (CheckSum == 0x4D1EEEE1) { /* Mac Plus ROM v 1, 'Lonely Hearts' */ } else if (CheckSum == 0x4D1EEAE1) { /* Mac Plus ROM v 2, 'Lonely Heifers' */ } else if (CheckSum == 0x4D1F8172) { /* Mac Plus ROM v 3, 'Loud Harmonicas' */ } else #elif CurEmMd <= kEmMd_SE if (CheckSum == 0xB2E362A8) { } else #elif CurEmMd <= kEmMd_SEFDHD if (CheckSum == 0xB306E171) { } else #elif CurEmMd <= kEmMd_Classic if (CheckSum == 0xA49F9914) { } else #elif CurEmMd <= kEmMd_PB100 if (CheckSum == 0x96645F9C) { } else #elif CurEmMd <= kEmMd_II if (CheckSum == 0x9779D2C4) { } else if (CheckSum == 0x97221136) { /* accept IIx ROM */ } else #elif CurEmMd <= kEmMd_IIx if (CheckSum == 0x97221136) { } else #endif { WarnMsgUnsupportedROM(); } /* Even if ROM is corrupt or unsupported, go ahead and try to run anyway. It shouldn't do any harm. */ #endif /* CheckRomCheckSum */ #if DisableRomCheck /* skip the rom checksum */ #if CurEmMd <= kEmMd_Twig43 /* no checksum code */ #elif CurEmMd <= kEmMd_Twiggy do_put_mem_word(0x136 + ROM, 0x6004); #elif CurEmMd <= kEmMd_128K do_put_mem_word(0xE2 + ROM, 0x6004); #elif CurEmMd <= kEmMd_Plus do_put_mem_word(0xD7A + ROM, 0x6022); #elif CurEmMd <= kEmMd_Classic do_put_mem_word(0x1C68 + ROM, 0x6008); #elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) do_put_mem_word(0x2AB0 + ROM, 0x6008); #endif #endif /* DisableRomCheck */ #if DisableRamTest #if CurEmMd <= kEmMd_128K #elif CurEmMd <= kEmMd_Plus do_put_mem_word(3752 + ROM, 0x4E71); /* shorten the ram check read */ do_put_mem_word(3728 + ROM, 0x4E71); /* shorten the ram check write */ #elif CurEmMd <= kEmMd_Classic do_put_mem_word(134 + ROM, 0x6002); do_put_mem_word(286 + ROM, 0x6002); #elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) do_put_mem_word(0xEE + ROM, 0x6002); do_put_mem_word(0x1AA + ROM, 0x6002); #endif #endif /* DisableRamTest */ #ifdef CurAltHappyMac PatchHappyMac(); #endif /* do_put_mem_word(862 + ROM, 0x4E71); */ /* shorten set memory */ #if UseSonyPatch Sony_Install(); #endif #ifdef ln2mtb ROMscrambleForMTB(); #endif return trueblnr; } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/ROMEMDEV.h b/Mini vMac/mnvm_core/ROMEMDEV.h index 181f72d..d241a93 100755 --- a/Mini vMac/mnvm_core/ROMEMDEV.h +++ b/Mini vMac/mnvm_core/ROMEMDEV.h @@ -1,23 +1 @@ -/* - ROMEMDEV.h - - Copyright (C) 2003 Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef ROMEMDEV_H -#error "header already included" -#else -#define ROMEMDEV_H -#endif - -EXPORTFUNC blnr ROM_Init(void); +/* ROMEMDEV.h Copyright (C) 2003 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef ROMEMDEV_H #error "header already included" #else #define ROMEMDEV_H #endif EXPORTFUNC blnr ROM_Init(void); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/RTCEMDEV.c b/Mini vMac/mnvm_core/RTCEMDEV.c index 0390771..459356e 100755 --- a/Mini vMac/mnvm_core/RTCEMDEV.c +++ b/Mini vMac/mnvm_core/RTCEMDEV.c @@ -1,471 +1 @@ -/* - RTCEMDEV.c - - Copyright (C) 2003 Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - Real Time Clock EMulated DEVice - - Emulates the RTC found in the Mac Plus. - - This code adapted from "RTC.c" in vMac by Philip Cummins. -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" -#include "MYOSGLUE.h" -#include "ENDIANAC.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" -#endif - -/* define _RTC_Debug */ -#ifdef _RTC_Debug -#include -#endif - -#include "RTCEMDEV.h" - -#define HaveXPRAM (CurEmMd >= kEmMd_Plus) - -#if HaveXPRAM -#define PARAMRAMSize 256 -#else -#define PARAMRAMSize 20 -#endif - -#if HaveXPRAM -#define Group1Base 0x10 -#define Group2Base 0x08 -#else -#define Group1Base 0x00 -#define Group2Base 0x10 -#endif - -typedef struct -{ - /* RTC VIA Flags */ - ui3b WrProtect; - ui3b DataOut; - ui3b DataNextOut; - - /* RTC Data */ - ui3b ShiftData; - ui3b Counter; - ui3b Mode; - ui3b SavedCmd; -#if HaveXPRAM - ui3b Sector; -#endif - - /* RTC Registers */ - ui3b Seconds_1[4]; - ui3b PARAMRAM[PARAMRAMSize]; -} RTC_Ty; - -LOCALVAR RTC_Ty RTC; - -/* RTC Functions */ - -LOCALVAR ui5b LastRealDate; - -#ifndef RTCinitPRAM -#define RTCinitPRAM 1 -#endif - -#ifndef TrackSpeed /* in 0..4 */ -#define TrackSpeed 0 -#endif - -#ifndef AlarmOn /* in 0..1 */ -#define AlarmOn 0 -#endif - -#ifndef DiskCacheSz /* in 1,2,3,4,6,8,12 */ -/* actual cache size is DiskCacheSz * 32k */ -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) -#define DiskCacheSz 1 -#else -#define DiskCacheSz 4 -#endif -#endif - -#ifndef StartUpDisk /* in 0..1 */ -#define StartUpDisk 0 -#endif - -#ifndef DiskCacheOn /* in 0..1 */ -#define DiskCacheOn 0 -#endif - -#ifndef MouseScalingOn /* in 0..1 */ -#define MouseScalingOn 0 -#endif - -#define prb_fontHi 0 -#define prb_fontLo 2 -#define prb_kbdPrintHi (AutoKeyRate + (AutoKeyThresh << 4)) -#define prb_kbdPrintLo 0 -#define prb_volClickHi (SpeakerVol + (TrackSpeed << 3) + (AlarmOn << 7)) -#define prb_volClickLo (CaretBlinkTime + (DoubleClickTime << 4)) -#define prb_miscHi DiskCacheSz -#define prb_miscLo \ - ((MenuBlink << 2) + (StartUpDisk << 4) \ - + (DiskCacheOn << 5) + (MouseScalingOn << 6)) - -#if dbglog_HAVE && 0 -EXPORTPROC DumpRTC(void); - -GLOBALPROC DumpRTC(void) -{ - int Counter; - - dbglog_writeln("RTC Parameter RAM"); - for (Counter = 0; Counter < PARAMRAMSize; Counter++) { - dbglog_writeNum(Counter); - dbglog_writeCStr(", "); - dbglog_writeHex(RTC.PARAMRAM[Counter]); - dbglog_writeReturn(); - } -} -#endif - -GLOBALFUNC blnr RTC_Init(void) -{ - int Counter; - ui5b secs; - - RTC.Mode = RTC.ShiftData = RTC.Counter = 0; - RTC.DataOut = RTC.DataNextOut = 0; - RTC.WrProtect = falseblnr; - - secs = CurMacDateInSeconds; - LastRealDate = secs; - - RTC.Seconds_1[0] = secs & 0xFF; - RTC.Seconds_1[1] = (secs & 0xFF00) >> 8; - RTC.Seconds_1[2] = (secs & 0xFF0000) >> 16; - RTC.Seconds_1[3] = (secs & 0xFF000000) >> 24; - - for (Counter = 0; Counter < PARAMRAMSize; Counter++) { - RTC.PARAMRAM[Counter] = 0; - } - -#if RTCinitPRAM - RTC.PARAMRAM[0 + Group1Base] = 168; /* valid */ -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) - RTC.PARAMRAM[2 + Group1Base] = 1; - /* node id hint for printer port (AppleTalk) */ -#endif - RTC.PARAMRAM[3 + Group1Base] = 34; - /* - serial ports config bits: 4-7 A, 0-3 B - useFree 0 Use undefined - useATalk 1 AppleTalk - useAsync 2 Async - useExtClk 3 externally clocked - */ - - RTC.PARAMRAM[4 + Group1Base] = 204; /* portA, high */ - RTC.PARAMRAM[5 + Group1Base] = 10; /* portA, low */ - RTC.PARAMRAM[6 + Group1Base] = 204; /* portB, high */ - RTC.PARAMRAM[7 + Group1Base] = 10; /* portB, low */ - RTC.PARAMRAM[13 + Group1Base] = prb_fontLo; - RTC.PARAMRAM[14 + Group1Base] = prb_kbdPrintHi; -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) - RTC.PARAMRAM[15 + Group1Base] = 1; - /* - printer, if any, connected to modem port - because printer port used for appletalk. - */ -#endif - -#if prb_volClickHi != 0 - RTC.PARAMRAM[0 + Group2Base] = prb_volClickHi; -#endif - RTC.PARAMRAM[1 + Group2Base] = prb_volClickLo; - RTC.PARAMRAM[2 + Group2Base] = prb_miscHi; - RTC.PARAMRAM[3 + Group2Base] = prb_miscLo -#if 0 != vMacScreenDepth - | 0x80 -#endif - ; - -#if HaveXPRAM /* extended parameter ram initialized */ -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) - RTC.PARAMRAM[12] = 0x4e; - RTC.PARAMRAM[13] = 0x75; - RTC.PARAMRAM[14] = 0x4d; - RTC.PARAMRAM[15] = 0x63; -#else - RTC.PARAMRAM[12] = 0x42; - RTC.PARAMRAM[13] = 0x75; - RTC.PARAMRAM[14] = 0x67; - RTC.PARAMRAM[15] = 0x73; -#endif -#endif - -#if ((CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_Classic)) \ - || (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) - - RTC.PARAMRAM[0x01] = 0x80; - RTC.PARAMRAM[0x02] = 0x4F; -#endif -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) - RTC.PARAMRAM[0x03] = 0x48; - - /* video board id */ - RTC.PARAMRAM[0x46] = /* 0x42 */ 0x76; /* 'v' */ - RTC.PARAMRAM[0x47] = /* 0x32 */ 0x4D; /* 'M' */ - /* mode */ -#if 0 == vMacScreenDepth - RTC.PARAMRAM[0x48] = 0x80; -#else - RTC.PARAMRAM[0x48] = 0x80; - /* 0x81 doesn't quite work right at boot */ -#endif -#endif - -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) - RTC.PARAMRAM[0x77] = 0x01; -#endif - -#if ((CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_Classic)) \ - || (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) - - /* start up disk (encoded how?) */ - RTC.PARAMRAM[0x78] = 0x00; - RTC.PARAMRAM[0x79] = 0x01; - RTC.PARAMRAM[0x7A] = 0xFF; - RTC.PARAMRAM[0x7B] = 0xFE; -#endif - -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) - RTC.PARAMRAM[0x80] = 0x09; - RTC.PARAMRAM[0x81] = 0x80; -#endif - -#if HaveXPRAM /* extended parameter ram initialized */ - do_put_mem_long(&RTC.PARAMRAM[0xE4], CurMacLatitude); - do_put_mem_long(&RTC.PARAMRAM[0xE8], CurMacLongitude); - do_put_mem_long(&RTC.PARAMRAM[0xEC], CurMacDelta); -#endif - -#endif /* RTCinitPRAM */ - - return trueblnr; -} - -#ifdef RTC_OneSecond_PulseNtfy -IMPORTPROC RTC_OneSecond_PulseNtfy(void); -#endif - -GLOBALPROC RTC_Interrupt(void) -{ - ui5b Seconds = 0; - ui5b NewRealDate = CurMacDateInSeconds; - ui5b DateDelta = NewRealDate - LastRealDate; - - if (DateDelta != 0) { - Seconds = (RTC.Seconds_1[3] << 24) + (RTC.Seconds_1[2] << 16) - + (RTC.Seconds_1[1] << 8) + RTC.Seconds_1[0]; - Seconds += DateDelta; - RTC.Seconds_1[0] = Seconds & 0xFF; - RTC.Seconds_1[1] = (Seconds & 0xFF00) >> 8; - RTC.Seconds_1[2] = (Seconds & 0xFF0000) >> 16; - RTC.Seconds_1[3] = (Seconds & 0xFF000000) >> 24; - - LastRealDate = NewRealDate; - -#ifdef RTC_OneSecond_PulseNtfy - RTC_OneSecond_PulseNtfy(); -#endif - } -} - -LOCALFUNC ui3b RTC_Access_PRAM_Reg(ui3b Data, blnr WriteReg, ui3b t) -{ - if (WriteReg) { - if (! RTC.WrProtect) { - RTC.PARAMRAM[t] = Data; -#ifdef _RTC_Debug - printf("Writing Address %2x, Data %2x\n", t, Data); -#endif - } - } else { - Data = RTC.PARAMRAM[t]; - } - return Data; -} - -LOCALFUNC ui3b RTC_Access_Reg(ui3b Data, blnr WriteReg, ui3b TheCmd) -{ - ui3b t = (TheCmd & 0x7C) >> 2; - if (t < 8) { - if (WriteReg) { - if (! RTC.WrProtect) { - RTC.Seconds_1[t & 0x03] = Data; - } - } else { - Data = RTC.Seconds_1[t & 0x03]; - } - } else if (t < 12) { - Data = RTC_Access_PRAM_Reg(Data, WriteReg, - (t & 0x03) + Group2Base); - } else if (t < 16) { - if (WriteReg) { - switch (t) { - case 12 : - break; /* Test Write, do nothing */ - case 13 : - RTC.WrProtect = (Data & 0x80) != 0; - break; /* Write_Protect Register */ - default : - ReportAbnormal("Write RTC Reg unknown"); - break; - } - } else { - ReportAbnormal("Read RTC Reg unknown"); - } - } else { - Data = RTC_Access_PRAM_Reg(Data, WriteReg, - (t & 0x0F) + Group1Base); - } - return Data; -} - -LOCALPROC RTC_DoCmd(void) -{ - switch (RTC.Mode) { - case 0: /* This Byte is a RTC Command */ -#if HaveXPRAM - if ((RTC.ShiftData & 0x78) == 0x38) { /* Extended Command */ - RTC.SavedCmd = RTC.ShiftData; - RTC.Mode = 2; -#ifdef _RTC_Debug - printf("Extended command %2x\n", RTC.ShiftData); -#endif - } else -#endif - { - if ((RTC.ShiftData & 0x80) != 0x00) { /* Read Command */ - RTC.ShiftData = - RTC_Access_Reg(0, falseblnr, RTC.ShiftData); - RTC.DataNextOut = 1; - } else { /* Write Command */ - RTC.SavedCmd = RTC.ShiftData; - RTC.Mode = 1; - } - } - break; - case 1: /* This Byte is data for RTC Write */ - (void) RTC_Access_Reg(RTC.ShiftData, - trueblnr, RTC.SavedCmd); - RTC.Mode = 0; - break; -#if HaveXPRAM - case 2: /* This Byte is rest of Extended RTC command address */ -#ifdef _RTC_Debug - printf("Mode 2 %2x\n", RTC.ShiftData); -#endif - RTC.Sector = ((RTC.SavedCmd & 0x07) << 5) - | ((RTC.ShiftData & 0x7C) >> 2); - if ((RTC.SavedCmd & 0x80) != 0x00) { /* Read Command */ - RTC.ShiftData = RTC.PARAMRAM[RTC.Sector]; - RTC.DataNextOut = 1; - RTC.Mode = 0; -#ifdef _RTC_Debug - printf("Reading X Address %2x, Data %2x\n", - RTC.Sector, RTC.ShiftData); -#endif - } else { - RTC.Mode = 3; -#ifdef _RTC_Debug - printf("Writing X Address %2x\n", RTC.Sector); -#endif - } - break; - case 3: /* This Byte is data for an Extended RTC Write */ - (void) RTC_Access_PRAM_Reg(RTC.ShiftData, - trueblnr, RTC.Sector); - RTC.Mode = 0; - break; -#endif - } -} - -GLOBALPROC RTCunEnabled_ChangeNtfy(void) -{ - if (RTCunEnabled) { - /* abort anything going on */ - if (RTC.Counter != 0) { -#ifdef _RTC_Debug - printf("aborting, %2x\n", RTC.Counter); -#endif - ReportAbnormal("RTC aborting"); - } - RTC.Mode = 0; - RTC.DataOut = 0; - RTC.DataNextOut = 0; - RTC.ShiftData = 0; - RTC.Counter = 0; - } -} - -GLOBALPROC RTCclock_ChangeNtfy(void) -{ - if (! RTCunEnabled) { - if (RTCclock) { - RTC.DataOut = RTC.DataNextOut; - RTC.Counter = (RTC.Counter - 1) & 0x07; - if (RTC.DataOut) { - RTCdataLine = ((RTC.ShiftData >> RTC.Counter) & 0x01); - /* - should notify VIA if changed, so can check - data direction - */ - if (RTC.Counter == 0) { - RTC.DataNextOut = 0; - } - } else { - RTC.ShiftData = (RTC.ShiftData << 1) | RTCdataLine; - if (RTC.Counter == 0) { - RTC_DoCmd(); - } - } - } - } -} - -GLOBALPROC RTCdataLine_ChangeNtfy(void) -{ -#if dbglog_HAVE - if (RTC.DataOut) { - if (! RTC.DataNextOut) { - /* - ignore. The ROM doesn't read from the RTC the - way described in the Hardware Reference. - It reads the data after setting the clock to - one instead of before, and then immediately - changes the VIA direction. So the RTC - has no way of knowing to stop driving the - data line, which certainly can't really be - correct. - */ - } else { - ReportAbnormal("write RTC Data unexpected direction"); - } - } -#endif -} +/* RTCEMDEV.c Copyright (C) 2003 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* Real Time Clock EMulated DEVice Emulates the RTC found in the Mac Plus. This code adapted from "RTC.c" in vMac by Philip Cummins. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "ENDIANAC.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif /* define _RTC_Debug */ #ifdef _RTC_Debug #include #endif #include "RTCEMDEV.h" #define HaveXPRAM (CurEmMd >= kEmMd_Plus) /* ReportAbnormalID unused 0x0805 - 0x08FF */ #if HaveXPRAM #define PARAMRAMSize 256 #else #define PARAMRAMSize 20 #endif #if HaveXPRAM #define Group1Base 0x10 #define Group2Base 0x08 #else #define Group1Base 0x00 #define Group2Base 0x10 #endif typedef struct { /* RTC VIA Flags */ ui3b WrProtect; ui3b DataOut; ui3b DataNextOut; /* RTC Data */ ui3b ShiftData; ui3b Counter; ui3b Mode; ui3b SavedCmd; #if HaveXPRAM ui3b Sector; #endif /* RTC Registers */ ui3b Seconds_1[4]; ui3b PARAMRAM[PARAMRAMSize]; } RTC_Ty; LOCALVAR RTC_Ty RTC; /* RTC Functions */ LOCALVAR ui5b LastRealDate; #ifndef RTCinitPRAM #define RTCinitPRAM 1 #endif #ifndef TrackSpeed /* in 0..4 */ #define TrackSpeed 0 #endif #ifndef AlarmOn /* in 0..1 */ #define AlarmOn 0 #endif #ifndef DiskCacheSz /* in 1,2,3,4,6,8,12 */ /* actual cache size is DiskCacheSz * 32k */ #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) #define DiskCacheSz 1 #else #define DiskCacheSz 4 #endif #endif #ifndef StartUpDisk /* in 0..1 */ #define StartUpDisk 0 #endif #ifndef DiskCacheOn /* in 0..1 */ #define DiskCacheOn 0 #endif #ifndef MouseScalingOn /* in 0..1 */ #define MouseScalingOn 0 #endif #define prb_fontHi 0 #define prb_fontLo 2 #define prb_kbdPrintHi (AutoKeyRate + (AutoKeyThresh << 4)) #define prb_kbdPrintLo 0 #define prb_volClickHi (SpeakerVol + (TrackSpeed << 3) + (AlarmOn << 7)) #define prb_volClickLo (CaretBlinkTime + (DoubleClickTime << 4)) #define prb_miscHi DiskCacheSz #define prb_miscLo \ ((MenuBlink << 2) + (StartUpDisk << 4) \ + (DiskCacheOn << 5) + (MouseScalingOn << 6)) #if dbglog_HAVE && 0 EXPORTPROC DumpRTC(void); GLOBALPROC DumpRTC(void) { int Counter; dbglog_writeln("RTC Parameter RAM"); for (Counter = 0; Counter < PARAMRAMSize; Counter++) { dbglog_writeNum(Counter); dbglog_writeCStr(", "); dbglog_writeHex(RTC.PARAMRAM[Counter]); dbglog_writeReturn(); } } #endif GLOBALFUNC blnr RTC_Init(void) { int Counter; ui5b secs; RTC.Mode = RTC.ShiftData = RTC.Counter = 0; RTC.DataOut = RTC.DataNextOut = 0; RTC.WrProtect = falseblnr; secs = CurMacDateInSeconds; LastRealDate = secs; RTC.Seconds_1[0] = secs & 0xFF; RTC.Seconds_1[1] = (secs & 0xFF00) >> 8; RTC.Seconds_1[2] = (secs & 0xFF0000) >> 16; RTC.Seconds_1[3] = (secs & 0xFF000000) >> 24; for (Counter = 0; Counter < PARAMRAMSize; Counter++) { RTC.PARAMRAM[Counter] = 0; } #if RTCinitPRAM RTC.PARAMRAM[0 + Group1Base] = 168; /* valid */ #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) RTC.PARAMRAM[2 + Group1Base] = 1; /* node id hint for printer port (AppleTalk) */ #endif RTC.PARAMRAM[3 + Group1Base] = 34; /* serial ports config bits: 4-7 A, 0-3 B useFree 0 Use undefined useATalk 1 AppleTalk useAsync 2 Async useExtClk 3 externally clocked */ RTC.PARAMRAM[4 + Group1Base] = 204; /* portA, high */ RTC.PARAMRAM[5 + Group1Base] = 10; /* portA, low */ RTC.PARAMRAM[6 + Group1Base] = 204; /* portB, high */ RTC.PARAMRAM[7 + Group1Base] = 10; /* portB, low */ RTC.PARAMRAM[13 + Group1Base] = prb_fontLo; RTC.PARAMRAM[14 + Group1Base] = prb_kbdPrintHi; #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) RTC.PARAMRAM[15 + Group1Base] = 1; /* printer, if any, connected to modem port because printer port used for appletalk. */ #endif #if prb_volClickHi != 0 RTC.PARAMRAM[0 + Group2Base] = prb_volClickHi; #endif RTC.PARAMRAM[1 + Group2Base] = prb_volClickLo; RTC.PARAMRAM[2 + Group2Base] = prb_miscHi; RTC.PARAMRAM[3 + Group2Base] = prb_miscLo #if 0 != vMacScreenDepth | 0x80 #endif ; #if HaveXPRAM /* extended parameter ram initialized */ #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) RTC.PARAMRAM[12] = 0x4e; RTC.PARAMRAM[13] = 0x75; RTC.PARAMRAM[14] = 0x4d; RTC.PARAMRAM[15] = 0x63; #else RTC.PARAMRAM[12] = 0x42; RTC.PARAMRAM[13] = 0x75; RTC.PARAMRAM[14] = 0x67; RTC.PARAMRAM[15] = 0x73; #endif #endif #if ((CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_Classic)) \ || (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) RTC.PARAMRAM[0x01] = 0x80; RTC.PARAMRAM[0x02] = 0x4F; #endif #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) RTC.PARAMRAM[0x03] = 0x48; /* video board id */ RTC.PARAMRAM[0x46] = /* 0x42 */ 0x76; /* 'v' */ RTC.PARAMRAM[0x47] = /* 0x32 */ 0x4D; /* 'M' */ /* mode */ #if (0 == vMacScreenDepth) || (vMacScreenDepth >= 4) RTC.PARAMRAM[0x48] = 0x80; #else RTC.PARAMRAM[0x48] = 0x81; /* 0x81 doesn't quite work right at boot */ /* no, it seems to work now (?) */ /* but only if depth <= 3 */ #endif #endif #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) RTC.PARAMRAM[0x77] = 0x01; #endif #if ((CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_Classic)) \ || (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) /* start up disk (encoded how?) */ RTC.PARAMRAM[0x78] = 0x00; RTC.PARAMRAM[0x79] = 0x01; RTC.PARAMRAM[0x7A] = 0xFF; RTC.PARAMRAM[0x7B] = 0xFE; #endif #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) RTC.PARAMRAM[0x80] = 0x09; RTC.PARAMRAM[0x81] = 0x80; #endif #if HaveXPRAM /* extended parameter ram initialized */ do_put_mem_long(&RTC.PARAMRAM[0xE4], CurMacLatitude); do_put_mem_long(&RTC.PARAMRAM[0xE8], CurMacLongitude); do_put_mem_long(&RTC.PARAMRAM[0xEC], CurMacDelta); #endif #endif /* RTCinitPRAM */ return trueblnr; } #ifdef RTC_OneSecond_PulseNtfy IMPORTPROC RTC_OneSecond_PulseNtfy(void); #endif GLOBALPROC RTC_Interrupt(void) { ui5b Seconds = 0; ui5b NewRealDate = CurMacDateInSeconds; ui5b DateDelta = NewRealDate - LastRealDate; if (DateDelta != 0) { Seconds = (RTC.Seconds_1[3] << 24) + (RTC.Seconds_1[2] << 16) + (RTC.Seconds_1[1] << 8) + RTC.Seconds_1[0]; Seconds += DateDelta; RTC.Seconds_1[0] = Seconds & 0xFF; RTC.Seconds_1[1] = (Seconds & 0xFF00) >> 8; RTC.Seconds_1[2] = (Seconds & 0xFF0000) >> 16; RTC.Seconds_1[3] = (Seconds & 0xFF000000) >> 24; LastRealDate = NewRealDate; #ifdef RTC_OneSecond_PulseNtfy RTC_OneSecond_PulseNtfy(); #endif } } LOCALFUNC ui3b RTC_Access_PRAM_Reg(ui3b Data, blnr WriteReg, ui3b t) { if (WriteReg) { if (! RTC.WrProtect) { RTC.PARAMRAM[t] = Data; #ifdef _RTC_Debug printf("Writing Address %2x, Data %2x\n", t, Data); #endif } } else { Data = RTC.PARAMRAM[t]; } return Data; } LOCALFUNC ui3b RTC_Access_Reg(ui3b Data, blnr WriteReg, ui3b TheCmd) { ui3b t = (TheCmd & 0x7C) >> 2; if (t < 8) { if (WriteReg) { if (! RTC.WrProtect) { RTC.Seconds_1[t & 0x03] = Data; } } else { Data = RTC.Seconds_1[t & 0x03]; } } else if (t < 12) { Data = RTC_Access_PRAM_Reg(Data, WriteReg, (t & 0x03) + Group2Base); } else if (t < 16) { if (WriteReg) { switch (t) { case 12 : break; /* Test Write, do nothing */ case 13 : RTC.WrProtect = (Data & 0x80) != 0; break; /* Write_Protect Register */ default : ReportAbnormalID(0x0801, "Write RTC Reg unknown"); break; } } else { ReportAbnormalID(0x0802, "Read RTC Reg unknown"); } } else { Data = RTC_Access_PRAM_Reg(Data, WriteReg, (t & 0x0F) + Group1Base); } return Data; } LOCALPROC RTC_DoCmd(void) { switch (RTC.Mode) { case 0: /* This Byte is a RTC Command */ #if HaveXPRAM if ((RTC.ShiftData & 0x78) == 0x38) { /* Extended Command */ RTC.SavedCmd = RTC.ShiftData; RTC.Mode = 2; #ifdef _RTC_Debug printf("Extended command %2x\n", RTC.ShiftData); #endif } else #endif { if ((RTC.ShiftData & 0x80) != 0x00) { /* Read Command */ RTC.ShiftData = RTC_Access_Reg(0, falseblnr, RTC.ShiftData); RTC.DataNextOut = 1; } else { /* Write Command */ RTC.SavedCmd = RTC.ShiftData; RTC.Mode = 1; } } break; case 1: /* This Byte is data for RTC Write */ (void) RTC_Access_Reg(RTC.ShiftData, trueblnr, RTC.SavedCmd); RTC.Mode = 0; break; #if HaveXPRAM case 2: /* This Byte is rest of Extended RTC command address */ #ifdef _RTC_Debug printf("Mode 2 %2x\n", RTC.ShiftData); #endif RTC.Sector = ((RTC.SavedCmd & 0x07) << 5) | ((RTC.ShiftData & 0x7C) >> 2); if ((RTC.SavedCmd & 0x80) != 0x00) { /* Read Command */ RTC.ShiftData = RTC.PARAMRAM[RTC.Sector]; RTC.DataNextOut = 1; RTC.Mode = 0; #ifdef _RTC_Debug printf("Reading X Address %2x, Data %2x\n", RTC.Sector, RTC.ShiftData); #endif } else { RTC.Mode = 3; #ifdef _RTC_Debug printf("Writing X Address %2x\n", RTC.Sector); #endif } break; case 3: /* This Byte is data for an Extended RTC Write */ (void) RTC_Access_PRAM_Reg(RTC.ShiftData, trueblnr, RTC.Sector); RTC.Mode = 0; break; #endif } } GLOBALPROC RTCunEnabled_ChangeNtfy(void) { if (RTCunEnabled) { /* abort anything going on */ if (RTC.Counter != 0) { #ifdef _RTC_Debug printf("aborting, %2x\n", RTC.Counter); #endif ReportAbnormalID(0x0803, "RTC aborting"); } RTC.Mode = 0; RTC.DataOut = 0; RTC.DataNextOut = 0; RTC.ShiftData = 0; RTC.Counter = 0; } } GLOBALPROC RTCclock_ChangeNtfy(void) { if (! RTCunEnabled) { if (RTCclock) { RTC.DataOut = RTC.DataNextOut; RTC.Counter = (RTC.Counter - 1) & 0x07; if (RTC.DataOut) { RTCdataLine = ((RTC.ShiftData >> RTC.Counter) & 0x01); /* should notify VIA if changed, so can check data direction */ if (RTC.Counter == 0) { RTC.DataNextOut = 0; } } else { RTC.ShiftData = (RTC.ShiftData << 1) | RTCdataLine; if (RTC.Counter == 0) { RTC_DoCmd(); } } } } } GLOBALPROC RTCdataLine_ChangeNtfy(void) { #if dbglog_HAVE if (RTC.DataOut) { if (! RTC.DataNextOut) { /* ignore. The ROM doesn't read from the RTC the way described in the Hardware Reference. It reads the data after setting the clock to one instead of before, and then immediately changes the VIA direction. So the RTC has no way of knowing to stop driving the data line, which certainly can't really be correct. */ } else { ReportAbnormalID(0x0804, "write RTC Data unexpected direction"); } } #endif } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/RTCEMDEV.h b/Mini vMac/mnvm_core/RTCEMDEV.h index cb98b27..174a3e0 100755 --- a/Mini vMac/mnvm_core/RTCEMDEV.h +++ b/Mini vMac/mnvm_core/RTCEMDEV.h @@ -1,28 +1 @@ -/* - RTCEMDEV.h - - Copyright (C) 2003 Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef RTCEMDEV_H -#error "header already included" -#else -#define RTCEMDEV_H -#endif - -EXPORTFUNC blnr RTC_Init(void); -EXPORTPROC RTC_Interrupt(void); - -EXPORTPROC RTCunEnabled_ChangeNtfy(void); -EXPORTPROC RTCclock_ChangeNtfy(void); -EXPORTPROC RTCdataLine_ChangeNtfy(void); +/* RTCEMDEV.h Copyright (C) 2003 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef RTCEMDEV_H #error "header already included" #else #define RTCEMDEV_H #endif EXPORTFUNC blnr RTC_Init(void); EXPORTPROC RTC_Interrupt(void); EXPORTPROC RTCunEnabled_ChangeNtfy(void); EXPORTPROC RTCclock_ChangeNtfy(void); EXPORTPROC RTCdataLine_ChangeNtfy(void); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SCCEMDEV.c b/Mini vMac/mnvm_core/SCCEMDEV.c index 3071e5c..5f5afe9 100755 --- a/Mini vMac/mnvm_core/SCCEMDEV.c +++ b/Mini vMac/mnvm_core/SCCEMDEV.c @@ -1,2792 +1 @@ -/* - SCCEMDEV.c - - Copyright (C) 2012 Philip Cummins, Weston Pawlowski, - Michael Fort, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - Serial Communications Controller EMulated DEVice - - additions for LocalTalk networking support - Copyright 2011-2012, Michael Fort - enabled with "EmLocalTalk" - - -- original description: -- - - Emulates the Z8530 SCC found in the Mac Plus. - But only the minimum amount needed to emulate - normal operation in a Mac Plus with nothing - connected to the serial ports. - (and not even that much is complete yet) - - This code adapted from "SCC.c" in vMac by Philip Cummins. - With additional code by Weston Pawlowski from the Windows - port of vMac. - - Further information was found in the - "Zilog SCC/ESCC User's Manual". -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" - -#include "MYOSGLUE.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" -#endif - -#include "SCCEMDEV.h" - -#define SCC_dolog (dbglog_HAVE && 0) -#define SCC_TrackMore 0 - -/* Just to make things a little easier */ -#define Bit0 1 -#define Bit1 2 -#define Bit2 4 -#define Bit3 8 -#define Bit4 16 -#define Bit5 32 -#define Bit6 64 -#define Bit7 128 - -/* SCC Interrupts */ -#define SCC_A_Rx 8 /* Rx Char Available */ -#define SCC_A_Rx_Spec 7 /* Rx Special Condition */ -#define SCC_A_Tx_Empty 6 /* Tx Buffer Empty */ -#define SCC_A_Ext 5 /* External/Status Change */ -#define SCC_B_Rx 4 /* Rx Char Available */ -#define SCC_B_Rx_Spec 3 /* Rx Special Condition */ -#define SCC_B_Tx_Empty 2 /* Tx Buffer Empty */ -#define SCC_B_Ext 1 /* External/Status Change */ - -typedef struct { - blnr TxEnable; - blnr RxEnable; - blnr TxIE; /* Transmit Interrupt Enable */ - blnr TxUnderrun; - blnr SyncHunt; - blnr TxIP; /* Transmit Interrupt Pending */ -#if EmLocalTalk - ui3r RxBuff; -#endif -#if EmLocalTalk - /* otherwise TxBufferEmpty always true */ - /* - though should behave as went false - for an instant when write to transmit buffer - */ - blnr TxBufferEmpty; -#endif -#if EmLocalTalk || SCC_TrackMore - blnr ExtIE; -#endif -#if SCC_TrackMore - blnr WaitRqstEnbl; -#endif -#if SCC_TrackMore - blnr WaitRqstSlct; -#endif -#if SCC_TrackMore - blnr WaitRqstRT; -#endif -#if SCC_TrackMore - blnr PrtySpclCond; -#endif -#if SCC_TrackMore - blnr PrtyEnable; -#endif -#if SCC_TrackMore - blnr PrtyEven; -#endif -#if SCC_TrackMore - blnr RxCRCEnbl; -#endif -#if SCC_TrackMore - blnr TxCRCEnbl; -#endif -#if SCC_TrackMore - blnr RTSctrl; -#endif -#if SCC_TrackMore - blnr SndBrkCtrl; -#endif -#if SCC_TrackMore - blnr DTRctrl; -#endif -#if EmLocalTalk || SCC_TrackMore - blnr AddrSrchMd; -#endif -#if SCC_TrackMore - blnr SyncChrLdInhb; -#endif -#if SCC_TrackMore - ui3r ClockRate; -#endif -#if SCC_TrackMore - ui3r DataEncoding; -#endif -#if SCC_TrackMore - ui3r TRxCsrc; -#endif -#if SCC_TrackMore - ui3r TClkSlct; -#endif -#if SCC_TrackMore - ui3r RClkSlct; -#endif -#if SCC_TrackMore - ui3r RBitsPerChar; -#endif -#if SCC_TrackMore - ui3r TBitsPerChar; -#endif -#if EmLocalTalk || SCC_TrackMore - ui3r RxIntMode; -#endif -#if EmLocalTalk || SCC_TrackMore - blnr FirstChar; -#endif -#if EmLocalTalk || SCC_TrackMore - ui3r SyncMode; -#endif -#if SCC_TrackMore - ui3r StopBits; -#endif -#if 0 /* AllSent always true */ - blnr AllSent; -#endif -#if 0 /* CTS always false */ - blnr CTS; /* input pin, unattached, so false? */ -#endif -#if 0 /* DCD always false */ - blnr DCD; /* Data Carrier Detect */ - /* - input pin for mouse interrupts. but since - not emulating mouse this way, leave false. - */ -#endif -#if EmLocalTalk - /* otherwise RxChrAvail always false */ - blnr RxChrAvail; -#endif -#if 0 /* RxOverrun always false */ - blnr RxOverrun; -#endif -#if 0 /* CRCFramingErr always false */ - blnr CRCFramingErr; -#endif -#if EmLocalTalk - /* otherwise EndOfFrame always false */ - blnr EndOfFrame; -#endif -#if 0 /* ParityErr always false */ - blnr ParityErr; -#endif -#if 0 /* ZeroCount always false */ - blnr ZeroCount; -#endif -#if 0 /* BreakAbort always false */ - blnr BreakAbort; -#endif -#if 0 /* SyncHuntIE usually false */ - blnr SyncHuntIE; -#endif -#if SCC_TrackMore /* don't care about CTS_IE */ - blnr CTS_IE; -#endif -#if SCC_TrackMore - blnr CRCPreset; -#endif -#if SCC_TrackMore - blnr BRGEnbl; -#endif -#if 0 /* don't care about DCD_IE, always true */ - blnr DCD_IE; -#endif -#if SCC_TrackMore /* don't care about BreakAbortIE */ - blnr BreakAbortIE; -#endif -#if SCC_TrackMore /* don't care about Baud */ - ui3r BaudLo; - ui3r BaudHi; -#endif -} Channel_Ty; - -typedef struct { - Channel_Ty a[2]; /* 0 = channel A, 1 = channel B */ - int SCC_Interrupt_Type; - int PointerBits; - ui3b InterruptVector; - blnr MIE; /* master interrupt enable */ -#if SCC_TrackMore - blnr NoVectorSlct; -#endif -#if 0 /* StatusHiLo always false */ - blnr StatusHiLo; -#endif -} SCC_Ty; - -LOCALVAR SCC_Ty SCC; - -#if 0 -LOCALVAR int ReadPrint; -LOCALVAR int ReadModem; -#endif - -#if EmLocalTalk -static int rx_data_offset = 0; - /* when data pending, this is used */ -#endif - -EXPORTFUNC blnr SCC_InterruptsEnabled(void) -{ - return SCC.MIE; -} - -/* ---- */ - -/* Function used to update the interrupt state of the SCC */ -LOCALPROC CheckSCCInterruptFlag(void) -{ -#if 0 /* ReceiveAInterrupt always false */ - blnr ReceiveAInterrupt = falseblnr - /* - also dependeds on WR1, bits 3 and 4, but - this doesn't change that it's all false - */ -#if EmLocalTalk - /* otherwise RxChrAvail always false */ - | SCC.a[0].RxChrAvail -#endif -#if 0 /* RxOverrun always false */ - | SCC.a[0].RxOverrun -#endif -#if 0 /* CRCFramingErr always false */ - | SCC.a[0].CRCFramingErr -#endif -#if EmLocalTalk - /* otherwise EndOfFrame always false */ - | SCC.a[0].EndOfFrame -#endif -#if 0 /* ParityErr always false */ - | SCC.a[0].ParityErr -#endif - ; -#endif -#if 0 - blnr TransmitAInterrupt = SCC.a[0].TxBufferEmpty; - /* - but probably looking for transitions not - current value - */ -#endif -#if 0 - blnr ExtStatusAInterrupt = 0 -#if 0 /* ZeroCount always false */ - | SCC.a[0].ZeroCount -#endif - /* probably want transition for these, not value */ -#if 0 /* DCD always false */ - | SCC.a[0].DCD /* DCD IE always true */ -#endif -#if 0 /* CTS always false */ - | SCC.a[0].CTS /* would depend on CTS_IE */ -#endif - | SCC.a[0].SyncHunt /* SyncHuntIE usually false */ - | SCC.a[0].TxUnderrun /* Tx underrun/EOM IE always false */ -#if 0 /* BreakAbort always false */ - | SCC.a[0].BreakAbort -#endif - ; -#endif - ui3b NewSCCInterruptRequest; - -#if EmLocalTalk - blnr ReceiveBInterrupt = falseblnr; - blnr RxSpclBInterrupt = falseblnr - /* otherwise EndOfFrame always false */ - | SCC.a[1].EndOfFrame - ; -#endif - -#if EmLocalTalk - switch (SCC.a[1].RxIntMode) { - case 0: - /* disabled */ - RxSpclBInterrupt = falseblnr; - break; - case 1: - /* Rx INT on 1st char or special condition */ - if (SCC.a[1].RxChrAvail && SCC.a[1].FirstChar) { - ReceiveBInterrupt = trueblnr; - } - break; - case 2: - /* INT on all Rx char or special condition */ - if (SCC.a[1].RxChrAvail) { - ReceiveBInterrupt = trueblnr; - } - break; - case 3: - /* Rx INT on special condition only */ - break; - } -#endif - - /* Master Interrupt Enable */ - if (! SCC.MIE) { - SCC.SCC_Interrupt_Type = 0; - } else -#if 0 - /* External Interrupt Enable */ - if (SCC.a[1].ExtIE) { - /* DCD Interrupt Enable */ - if (SCC.a[1].DCD_IE && 0) { /* dcd unchanged */ - SCC.SCC_Interrupt_Type = ??; - } - } -#endif - if (SCC.a[0].TxIP && SCC.a[0].TxIE) { - SCC.SCC_Interrupt_Type = SCC_A_Tx_Empty; - } else -#if EmLocalTalk - if (ReceiveBInterrupt) { - SCC.SCC_Interrupt_Type = SCC_B_Rx; - } else - if (RxSpclBInterrupt) { - SCC.SCC_Interrupt_Type = SCC_B_Rx_Spec; - } else -#endif - if (SCC.a[1].TxIP && SCC.a[1].TxIE) { - SCC.SCC_Interrupt_Type = SCC_B_Tx_Empty; - } else - { - SCC.SCC_Interrupt_Type = 0; - } - - NewSCCInterruptRequest = (SCC.SCC_Interrupt_Type != 0) ? 1 : 0; - if (NewSCCInterruptRequest != SCCInterruptRequest) { -#if SCC_dolog - dbglog_WriteSetBool("SCCInterruptRequest change", - NewSCCInterruptRequest); - - dbglog_StartLine(); - dbglog_writeCStr("SCC.SCC_Interrupt_Type <- "); - dbglog_writeHex(SCC.SCC_Interrupt_Type); - dbglog_writeReturn(); -#endif - SCCInterruptRequest = NewSCCInterruptRequest; -#ifdef SCCinterruptChngNtfy - SCCinterruptChngNtfy(); -#endif - } -} - -LOCALPROC SCC_InitChannel(int chan) -{ - /* anything not done by ResetChannel */ - - SCC.a[chan].SyncHunt = trueblnr; -#if 0 /* DCD always false */ - SCC.a[chan].DCD = falseblnr; /* input pin, reset doesn't change */ -#endif -#if 0 /* CTS always false */ - SCC.a[chan].CTS = falseblnr; /* input pin, reset doesn't change */ -#endif -#if 0 /* AllSent always true */ - SCC.a[chan].AllSent = trueblnr; -#endif -#if SCC_TrackMore /* don't care about Baud */ - SCC.a[chan].BaudLo = 0; - SCC.a[chan].BaudHi = 0; -#endif -#if 0 /* BreakAbort always false */ - SCC.a[chan].BreakAbort = falseblnr; -#endif -#if SCC_TrackMore - SCC.a[chan].BRGEnbl = falseblnr; -#endif -#if SCC_TrackMore - SCC.a[chan].TRxCsrc = 0; -#endif -#if SCC_TrackMore - SCC.a[chan].TClkSlct = 1; -#endif -#if SCC_TrackMore - SCC.a[chan].RClkSlct = 0; -#endif -} - -LOCALPROC SCC_ResetChannel(int chan) -{ -/* RR 0 */ -#if EmLocalTalk - SCC.a[chan].RxBuff = 0; -#endif -#if EmLocalTalk - /* otherwise RxChrAvail always false */ - SCC.a[chan].RxChrAvail = falseblnr; -#endif -#if 0 /* ZeroCount always false */ - SCC.a[chan].ZeroCount = falseblnr; -#endif -#if EmLocalTalk - /* otherwise TxBufferEmpty always true */ - SCC.a[chan].TxBufferEmpty = trueblnr; -#endif - SCC.a[chan].TxUnderrun = trueblnr; -/* RR 1 */ -#if 0 /* ParityErr always false */ - SCC.a[chan].ParityErr = falseblnr; -#endif -#if 0 /* RxOverrun always false */ - SCC.a[chan].RxOverrun = falseblnr; -#endif -#if 0 /* CRCFramingErr always false */ - SCC.a[chan].CRCFramingErr = falseblnr; -#endif -#if EmLocalTalk - /* otherwise EndOfFrame always false */ - SCC.a[chan].EndOfFrame = falseblnr; -#endif -/* RR 3 */ -#if EmLocalTalk || SCC_TrackMore - SCC.a[chan].ExtIE = falseblnr; -#endif -#if SCC_TrackMore - SCC.a[chan].RxCRCEnbl = falseblnr; -#endif -#if SCC_TrackMore - SCC.a[chan].TxCRCEnbl = falseblnr; -#endif -#if SCC_TrackMore - SCC.a[chan].RTSctrl = falseblnr; -#endif -#if SCC_TrackMore - SCC.a[chan].SndBrkCtrl = falseblnr; -#endif -#if SCC_TrackMore - SCC.a[chan].DTRctrl = falseblnr; -#endif -#if EmLocalTalk || SCC_TrackMore - SCC.a[chan].AddrSrchMd = falseblnr; -#endif -#if SCC_TrackMore - SCC.a[chan].SyncChrLdInhb = falseblnr; -#endif -#if SCC_TrackMore - SCC.a[chan].WaitRqstEnbl = falseblnr; -#endif -#if SCC_TrackMore - SCC.a[chan].WaitRqstSlct = falseblnr; -#endif -#if SCC_TrackMore - SCC.a[chan].WaitRqstRT = falseblnr; -#endif -#if SCC_TrackMore - SCC.a[chan].PrtySpclCond = falseblnr; -#endif -#if SCC_TrackMore - SCC.a[chan].PrtyEnable = falseblnr; -#endif -#if SCC_TrackMore - SCC.a[chan].PrtyEven = falseblnr; -#endif -#if SCC_TrackMore - SCC.a[chan].ClockRate = 0; -#endif -#if SCC_TrackMore - SCC.a[chan].DataEncoding = 0; -#endif -#if SCC_TrackMore - SCC.a[chan].RBitsPerChar = 0; -#endif -#if SCC_TrackMore - SCC.a[chan].TBitsPerChar = 0; -#endif -#if EmLocalTalk || SCC_TrackMore - SCC.a[chan].RxIntMode = 0; -#endif -#if EmLocalTalk || SCC_TrackMore - SCC.a[chan].FirstChar = falseblnr; -#endif -#if EmLocalTalk || SCC_TrackMore - SCC.a[chan].SyncMode = 0; -#endif -#if SCC_TrackMore - SCC.a[chan].StopBits = 0; -#endif -#if SCC_TrackMore - SCC.NoVectorSlct = falseblnr; -#endif - SCC.a[chan].TxIP = falseblnr; - - SCC.a[chan].TxEnable = falseblnr; - SCC.a[chan].RxEnable = falseblnr; - SCC.a[chan].TxIE = falseblnr; - -#if 0 /* don't care about DCD_IE, always true */ - SCC.a[chan].DCD_IE = trueblnr; -#endif -#if SCC_TrackMore /* don't care about CTS_IE */ - SCC.a[chan].CTS_IE = trueblnr; -#endif -#if SCC_TrackMore - SCC.a[chan].CRCPreset = falseblnr; -#endif -#if 0 /* SyncHuntIE usually false */ - SCC.a[chan].SyncHuntIE = trueblnr; -#endif -#if SCC_TrackMore /* don't care about BreakAbortIE */ - SCC.a[chan].BreakAbortIE = trueblnr; -#endif - - SCC.PointerBits = 0; - -#if 0 - if (chan != 0) { - ReadPrint = 0; - } else { - ReadModem = 0; - } -#endif -} - -GLOBALPROC SCC_Reset(void) -{ - SCCwaitrq = 1; - - SCC.SCC_Interrupt_Type = 0; - - SCCInterruptRequest = 0; - SCC.PointerBits = 0; - SCC.MIE = falseblnr; - SCC.InterruptVector = 0; -#if 0 /* StatusHiLo always false */ - SCC.StatusHiLo = falseblnr; -#endif - - SCC_InitChannel(1); - SCC_InitChannel(0); - - SCC_ResetChannel(1); - SCC_ResetChannel(0); -} - - -#if EmLocalTalk - -LOCALVAR blnr CTSpacketPending = falseblnr; -LOCALVAR ui3r CTSpacketRxDA; -LOCALVAR ui3r CTSpacketRxSA; - -/* - Function used when all the tx data is sent to the SCC as indicated - by resetting the TX underrun/EOM latch. If the transmit packet is - a unicast RTS LAPD packet, we fake the corresponding CTS LAPD - packet. This is okay because it is only a collision avoidance - mechanism and the Ethernet device itself and BPF automatically - handle collision detection and retransmission. Besides this is - what a standard AppleTalk (LocalTalk to EtherTalk) bridge does. -*/ -LOCALPROC process_transmit(void) -{ - /* Check for LLAP packets, which we won't send */ - if (LT_TxBuffSz == 3) { - /* - We will automatically and immediately acknowledge - any non-broadcast RTS packets - */ - if ((LT_TxBuffer[0] != 0xFF) && (LT_TxBuffer[2] == 0x84)) { -#if SCC_dolog - dbglog_WriteNote("SCC LLAP packet in process_transmit"); -#endif - if (CTSpacketPending) { - ReportAbnormal( - "Already CTSpacketPending in process_transmit"); - } else { - CTSpacketRxDA = LT_TxBuffer[1]; /* rx da = tx sa */ - CTSpacketRxSA = LT_TxBuffer[0]; /* rx sa = tx da */ - CTSpacketPending = trueblnr; - } - } - } else { - LT_TransmitPacket(); - } -} - -LOCALPROC SCC_TxBuffPut(ui3r Data) -{ - /* Buffer the data in the transmit buffer */ - if (LT_TxBuffSz < LT_TxBfMxSz) { - LT_TxBuffer[LT_TxBuffSz] = Data; - ++LT_TxBuffSz; - } -} - -LOCALVAR ui3b MyCTSBuffer[4]; - -LOCALPROC GetCTSpacket(void) -{ - /* Get a single buffer worth of packets at a time */ - ui3p device_buffer = MyCTSBuffer; - -#if SCC_dolog - dbglog_WriteNote("SCC receiving CTS packet"); -#endif - /* Create the fake response from the other node */ - device_buffer[0] = CTSpacketRxDA; - device_buffer[1] = CTSpacketRxSA; - device_buffer[2] = 0x85; /* llap cts */ - - /* Start the receiver */ - LT_RxBuffer = device_buffer; - LT_RxBuffSz = 3; - - CTSpacketPending = falseblnr; -} - -/* - This function is called once all the normal packet bytes have been - received. -*/ -LOCALPROC rx_complete(void) -{ - if (SCC.a[1].EndOfFrame) { - ReportAbnormal("EndOfFrame true in rx_complete"); - } - if (! SCC.a[1].RxChrAvail) { - ReportAbnormal("RxChrAvail false in rx_complete"); - } - if (SCC.a[1].SyncHunt) { - ReportAbnormal("SyncHunt true in rx_complete"); - } - - /* - Need to wait for rx_eof_pending (end of frame) to clear before - preparing the next packet for receive. - */ - LT_RxBuffer = nullpr; - - SCC.a[1].EndOfFrame = trueblnr; -} - -LOCALPROC SCC_RxBuffAdvance(void) -{ - ui3r value; - - /* - From the manual: - "If status is checked, it must be done before the data is read, - because the act of reading the data pops both the data and - error FIFOs." - */ - - if (nullpr == LT_RxBuffer) { - value = 0x7E; - SCC.a[1].RxChrAvail = falseblnr; - } else { - if (rx_data_offset < LT_RxBuffSz) { - value = LT_RxBuffer[rx_data_offset]; - } else { - ui5r i = rx_data_offset - LT_RxBuffSz; - - /* if i==0 in first byte of CRC, have not got EOF yet */ - if (i == 1) { - rx_complete(); - } - - value = 0; - } - ++rx_data_offset; - } - - SCC.a[1].RxBuff = value; -} - -/* LLAP/SDLC address */ -LOCALVAR ui3b my_node_address = 0; - -LOCALPROC GetNextPacketForMe(void) -{ - unsigned char dst; - unsigned char src; - -label_retry: - LT_ReceivePacket(); - - if (nullpr != LT_RxBuffer) { -#if SCC_dolog - dbglog_WriteNote("SCC receiving packet from BPF"); -#endif - - /* Is this packet destined for me? */ - dst = LT_RxBuffer[0]; - src = LT_RxBuffer[1]; - if (src == my_node_address) { -#if SCC_dolog - dbglog_WriteNote("SCC ignore packet from myself"); -#endif - LT_RxBuffer = nullpr; - goto label_retry; - } else if ((dst == my_node_address) - || (dst == 0xFF) - || ! SCC.a[1].AddrSrchMd) - { - /* ok */ - } else { -#if SCC_dolog - dbglog_WriteNote("SCC ignore packet not for me"); -#endif - LT_RxBuffer = nullpr; - goto label_retry; - } - } -} - -/* - External function, called periodically, to poll for any new LTOE - packets. Any new packets are queued into the packet receipt queue. -*/ -GLOBALPROC LocalTalkTick(void) -{ - if (SCC.a[1].RxEnable - && (! SCC.a[1].RxChrAvail)) - { - if (nullpr != LT_RxBuffer) { -#if SCC_dolog - dbglog_WriteNote("SCC recover abandoned packet"); -#endif - } else { - if (CTSpacketPending) { - GetCTSpacket(); - } else { - GetNextPacketForMe(); - } - } - - if (nullpr != LT_RxBuffer) { - rx_data_offset = 0; - SCC.a[1].EndOfFrame = falseblnr; - SCC.a[1].RxChrAvail = trueblnr; - SCC.a[1].SyncHunt = falseblnr; - - SCC_RxBuffAdvance(); - /* We can update the rx interrupt if enabled */ - CheckSCCInterruptFlag(); - } - } -} - -#endif - - -#if 0 -LOCALPROC SCC_Interrupt(int Type) -{ - if (SCC.MIE) { /* Master Interrupt Enable */ - - if (Type > SCC.SCC_Interrupt_Type) { - SCC.SCC_Interrupt_Type = Type; - } - - CheckSCCInterruptFlag(); - } -} -#endif - -#if 0 -LOCALPROC SCC_Int(void) -{ - /* This should be called at regular intervals */ - - /* Turn off Sync/Hunt Mode */ - if (SCC.a[0].SyncHunt) { - SCC.a[0].SyncHunt = falseblnr; - -#ifdef _SCC_Debug2 - vMac_Message("SCC_Int: Disable Sync/Hunt on A"); -#endif - -#if 0 /* SyncHuntIE usually false */ - if (SCC.a[0].SyncHuntIE) { - SCC_Interrupt(SCC_A_Ext); - } -#endif - } - if (SCC.a[1].SyncHunt) { - SCC.a[1].SyncHunt = falseblnr; - -#ifdef _SCC_Debug2 - vMac_Message("SCC_Int: Disable Sync/Hunt on B"); -#endif - -#if 0 /* SyncHuntIE usually false */ - if (SCC.a[1].SyncHuntIE) { - SCC_Interrupt(SCC_B_Ext); - } -#endif - } - -#if 0 - /* Check for incoming data */ - if (ModemPort) - { - if (! SCC.a[0].RxEnable) { /* Rx Disabled */ - ReadModem = 0; - } - - if ((ModemBytes > 0) && (ModemCount > ModemBytes - 1)) - { - SCC.a[0].RxChrAvail = falseblnr; - ReadModem = ModemBytes = ModemCount = 0; - } - - if (ReadModem) { - ReadModem = 2; - - SCC.a[0].RxChrAvail = trueblnr; - - if (SCC.a[0].WR[0] & Bit5 - && ! (SCC.a[0].WR[0] & (Bit4 | Bit3))) - { - /* Int on next Rx char */ - SCC_Interrupt(SCC_A_Rx); - } else if (SCC.a[0].WR[1] & Bit3 - && ! (SCC.a[0].WR[1] & Bit4)) - { - /* Int on first Rx char */ - SCC_Interrupt(SCC_A_Rx); - } else if (SCC.a[0].WR[1] & Bit4 - && ! (SCC.a[0].WR[1] & Bit3)) - { - /* Int on all Rx chars */ - SCC_Interrupt(SCC_A_Rx); - } - } - } - if (PrintPort) { - if (! SCC.a[1].RxEnable) { - /* Rx Disabled */ - ReadPrint = 0; - } - - if ((PrintBytes > 0) && (PrintCount > PrintBytes - 1)) { - SCC.a[1].RxChrAvail = falseblnr; - ReadPrint = PrintBytes = PrintCount = 0; - } - - if (ReadPrint) { - ReadPrint = 2; - - SCC.a[1].RxChrAvail = trueblnr; - - if (SCC.a[1].WR[0] & Bit5 - && ! (SCC.a[1].WR[0] & (Bit4 | Bit3))) - { - /* Int on next Rx char */ - SCC_Interrupt(SCC_B_Rx); - } else if (SCC.a[1].WR[1] & Bit3 - && ! (SCC.a[1].WR[1] & Bit4)) - { - /* Int on first Rx char */ - SCC_Interrupt(SCC_B_Rx); - } else if (SCC.a[1].WR[1] & Bit4 - && ! (SCC.a[1].WR[1] & Bit3)) - { - /* Int on all Rx chars */ - SCC_Interrupt(SCC_B_Rx); - } - } - } -#endif -} -#endif - -#if SCC_dolog -LOCALPROC SCC_DbgLogChanStartLine(int chan) -{ - dbglog_StartLine(); - dbglog_writeCStr("SCC chan("); - if (chan) { - dbglog_writeCStr("B"); - } else { - dbglog_writeCStr("A"); - } - /* dbglog_writeHex(chan); */ - dbglog_writeCStr(")"); -} -#endif - -LOCALFUNC ui3r SCC_GetRR0(int chan) -{ - /* happens on boot always */ - - return 0 -#if 0 /* BreakAbort always false */ - | (SCC.a[chan].BreakAbort ? (1 << 7) : 0) -#endif - | (SCC.a[chan].TxUnderrun ? (1 << 6) : 0) -#if 0 /* CTS always false */ - | (SCC.a[chan].CTS ? (1 << 5) : 0) -#endif - | (SCC.a[chan].SyncHunt ? (1 << 4) : 0) -#if 0 /* DCD always false */ - | (SCC.a[chan].DCD ? (1 << 3) : 0) -#endif -#if EmLocalTalk - | (SCC.a[chan].TxBufferEmpty ? (1 << 2) : 0) -#else - /* otherwise TxBufferEmpty always true */ - | (1 << 2) -#endif -#if 0 /* ZeroCount always false */ - | (SCC.a[chan].ZeroCount ? (1 << 1) : 0) -#endif -#if EmLocalTalk - /* otherwise RxChrAvail always false */ - | (SCC.a[chan].RxChrAvail ? (1 << 0) : 0) -#endif - ; -} - -LOCALFUNC ui3r SCC_GetRR1(int chan) -{ - /* happens in MacCheck */ - - ui3r value; -#if ! EmLocalTalk - UnusedParam(chan); -#endif - - value = Bit2 | Bit1 -#if 0 /* AllSent always true */ - | (SCC.a[chan].AllSent ? (1 << 0) : 0) -#else - | Bit0 -#endif -#if 0 /* ParityErr always false */ - | (SCC.a[chan].ParityErr ? (1 << 4) : 0) -#endif -#if 0 /* RxOverrun always false */ - | (SCC.a[chan].RxOverrun ? (1 << 5) : 0) -#endif -#if 0 /* CRCFramingErr always false */ - | (SCC.a[chan].CRCFramingErr ? (1 << 6) : 0) -#endif -#if EmLocalTalk - /* otherwise EndOfFrame always false */ - | (SCC.a[chan].EndOfFrame ? (1 << 7) : 0) -#endif - ; - - return value; -} - -LOCALFUNC ui3r SCC_GetRR2(int chan) -{ - /* happens in MacCheck */ - /* happens in Print to ImageWriter */ - - ui3r value = SCC.InterruptVector; - - if (chan != 0) { /* B Channel */ -#if 0 /* StatusHiLo always false */ - if (SCC.StatusHiLo) { - /* Status High */ - value = value - & (Bit0 | Bit1 | Bit2 | Bit3 | Bit7); - - ReportAbnormal("Status high/low"); - switch (SCC.SCC_Interrupt_Type) { - case SCC_A_Rx: - value |= Bit4 | Bit5; - break; - - case SCC_A_Rx_Spec: - value |= Bit4 | Bit5 | Bit6; - break; - - case SCC_A_Tx_Empty: - value |= Bit4; - break; - - case SCC_A_Ext: - value |= Bit4 | Bit6; - break; - - case SCC_B_Rx: - value |= Bit5; - break; - - case SCC_B_Rx_Spec: - value |= Bit5 | Bit6; - break; - - case SCC_B_Tx_Empty: - value |= 0; - break; - - case SCC_B_Ext: - value |= Bit6; - break; - - default: - value |= Bit5 | Bit6; - break; - } - } else -#endif - { - /* Status Low */ - value = value - & (Bit0 | Bit4 | Bit5 | Bit6 | Bit7); - - switch (SCC.SCC_Interrupt_Type) { - case SCC_A_Rx: - value |= Bit3 | Bit2; - break; - - case SCC_A_Rx_Spec: - value |= Bit3 | Bit2 | Bit1; - break; - - case SCC_A_Tx_Empty: - value |= Bit3; - break; - - case SCC_A_Ext: - value |= Bit3 | Bit1; - break; - - case SCC_B_Rx: - value |= Bit2; - break; - - case SCC_B_Rx_Spec: - value |= Bit2 | Bit1; - break; - - case SCC_B_Tx_Empty: - value |= 0; - break; - - case SCC_B_Ext: - value |= Bit1; - break; - - default: - value |= Bit2 | Bit1; - break; - } - } - - /* SCC.SCC_Interrupt_Type = 0; */ - } - - return value; -} - -LOCALFUNC ui3r SCC_GetRR3(int chan) -{ - ui3r value = 0; - - UnusedParam(chan); - ReportAbnormal("RR 3"); - -#if 0 - if (chan == 0) { - value = 0 - | (SCC.a[1].TxIP ? (1 << 1) : 0) - | (SCC.a[0].TxIP ? (1 << 4) : 0) - ; - } else { - value = 0; - } -#endif - - return value; -} - -LOCALFUNC ui3r SCC_GetRR8(int chan) -{ - ui3r value = 0; - - /* Receive Buffer */ - /* happens on boot with appletalk on */ - if (SCC.a[chan].RxEnable) { -#if EmLocalTalk - if (0 != chan) { - /* - Check the receive state, handling a complete rx - if necessary - */ - value = SCC.a[1].RxBuff; - SCC.a[1].FirstChar = falseblnr; - SCC_RxBuffAdvance(); - } else { - value = 0x7E; - } -#else - /* Rx Enable */ -#if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx) - /* don't report */ -#else - ReportAbnormal("read rr8 when RxEnable"); -#endif - - /* Input 1 byte from Modem Port/Printer into Data */ -#endif - } else { - /* happens on boot with appletalk on */ - } - - return value; -} - -LOCALFUNC ui3r SCC_GetRR10(int chan) -{ - /* happens on boot with appletalk on */ - - ui3r value = 0; - UnusedParam(chan); - -#if 0 && EmLocalTalk - value = 2; -#endif - - return value; -} - -LOCALFUNC ui3r SCC_GetRR12(int chan) -{ - ui3r value = 0; - -#if ! SCC_TrackMore - UnusedParam(chan); -#endif - ReportAbnormal("RR 12"); - -#if SCC_TrackMore /* don't care about Baud */ - value = SCC.a[chan].BaudLo; -#endif - - return value; -} - -LOCALFUNC ui3r SCC_GetRR13(int chan) -{ - ui3r value = 0; - -#if ! SCC_TrackMore - UnusedParam(chan); -#endif - ReportAbnormal("RR 13"); - -#if SCC_TrackMore /* don't care about Baud */ - value = SCC.a[chan].BaudHi; -#endif - - return value; -} - -LOCALFUNC ui3r SCC_GetRR15(int chan) -{ - ui3r value = 0; - - UnusedParam(chan); - ReportAbnormal("RR 15"); - -#if 0 - value = 0 -#if 0 /* don't care about DCD_IE, always true */ - | (SCC.a[chan].DCD_IE ? Bit3 : 0) -#else - | Bit3 -#endif -#if 0 /* SyncHuntIE usually false */ - | (SCC.a[chan].SyncHuntIE ? Bit4 : 0) -#endif -#if SCC_TrackMore /* don't care about CTS_IE */ - | (SCC.a[chan].CTS_IE ? Bit5 : 0) -#endif -#if SCC_TrackMore /* don't care about BreakAbortIE */ - | (SCC.a[chan].BreakAbortIE ? Bit7 : 0) -#endif - ; -#endif - - return value; -} - -#if SCC_dolog -LOCALPROC SCC_DbgLogChanCmnd(int chan, char *s) -{ - SCC_DbgLogChanStartLine(chan); - dbglog_writeCStr(" "); - dbglog_writeCStr(s); - dbglog_writeReturn(); -} -#endif - -#if SCC_dolog -LOCALPROC SCC_DbgLogChanChngBit(int chan, char *s, blnr v) -{ - SCC_DbgLogChanStartLine(chan); - dbglog_writeCStr(" "); - dbglog_writeCStr(s); - dbglog_writeCStr(" <- "); - if (v) { - dbglog_writeCStr("1"); - } else { - dbglog_writeCStr("0"); - } - dbglog_writeReturn(); -} -#endif - -LOCALPROC SCC_PutWR0(ui3r Data, int chan) -/* - "CRC initialize, initialization commands for the various modes, - Register Pointers" -*/ -{ - switch ((Data >> 6) & 3) { - case 1: - ReportAbnormal("Reset Rx CRC Checker"); - break; - case 2: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, "Reset Tx CRC Generator"); -#endif - /* happens on boot with appletalk on */ - break; - case 3: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "Reset Tx Underrun/EOM Latch"); -#endif - /* happens on boot with appletalk on */ -#if EmLocalTalk - /* - This is the indication we are done transmitting - data for the current packet. - */ - process_transmit(); -#endif -#if 0 /* It seems to work better without this */ - if (SCC.a[chan].TxEnable) { - /* Tx Enabled */ - SCC.a[chan].TxUnderrun = falseblnr; - - if (SCC.a[chan].WR[10] & Bit2) { - /* Abort/Flag on Underrun */ - /* Send Abort */ - SCC.a[chan].TxUnderrun = trueblnr; -#if 0 /* TxBufferEmpty always true */ - SCC.a[chan].TxBufferEmpty = trueblnr; -#endif - - /* Send Flag */ - } - } -#endif - break; - case 0: - default: - /* Null Code */ - break; - } - SCC.PointerBits = Data & 0x07; - switch ((Data >> 3) & 7) { - case 1: /* Point High */ - SCC.PointerBits |= 8; - break; - case 2: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, "Reset Ext/Status Ints"); -#endif - /* happens on boot always */ - SCC.a[chan].SyncHunt = falseblnr; -#if 0 /* only in sync mode */ - SCC.a[chan].TxUnderrun = falseblnr; -#endif -#if 0 /* ZeroCount always false */ - SCC.a[chan].ZeroCount = falseblnr; -#endif -#if 0 /* BreakAbort always false */ - SCC.a[chan].BreakAbort = falseblnr; -#endif - break; - case 3: - ReportAbnormal("Send Abort (SDLC)"); -#if EmLocalTalk - SCC.a[chan].TxBufferEmpty = trueblnr; -#endif -#if 0 - SCC.a[chan].TxUnderrun = trueblnr; -#if 0 /* TxBufferEmpty always true */ - SCC.a[chan].TxBufferEmpty = trueblnr; -#endif -#endif - break; - case 4: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "Enable Int on next Rx char"); -#endif -#if EmLocalTalk || SCC_TrackMore - SCC.a[chan].FirstChar = trueblnr; -#endif - /* happens in MacCheck */ - break; - case 5: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, "Reset Tx Int Pending"); -#endif - /* happens in MacCheck */ - /* happens in Print to ImageWriter */ - SCC.a[chan].TxIP = falseblnr; - CheckSCCInterruptFlag(); - break; - case 6: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, "Error Reset"); -#endif - /* happens on boot with appletalk on */ -#if EmLocalTalk - SCC.a[chan].EndOfFrame = falseblnr; -#endif -#if 0 /* ParityErr always false */ - SCC.a[chan].ParityErr = falseblnr; -#endif -#if 0 /* RxOverrun always false */ - SCC.a[chan].RxOverrun = falseblnr; -#endif -#if 0 /* CRCFramingErr always false */ - SCC.a[chan].CRCFramingErr = falseblnr; -#endif - break; - case 7: - /* happens in "Network Watch" program (Cayman Systems) */ -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, "Reset Highest IUS"); -#endif - break; - case 0: - default: - /* Null Code */ - break; - } -} - -LOCALPROC SCC_PutWR1(ui3r Data, int chan) -/* - "Transmit/Receive interrupt and data transfer mode definition" -*/ -{ -#if EmLocalTalk || SCC_TrackMore - { - blnr NewExtIE = (Data & Bit0) != 0; - if (SCC.a[chan].ExtIE != NewExtIE) { - SCC.a[chan].ExtIE = NewExtIE; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, "EXT INT Enable", - NewExtIE); -#endif - /* - set to 1 on start up, set to 0 in MacCheck - and in Print to ImageWriter - */ - } - } -#endif - - { - blnr NewTxIE = (Data & Bit1) != 0; - if (SCC.a[chan].TxIE != NewTxIE) { -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, "Tx Int Enable", - NewTxIE); -#endif - /* happens in MacCheck */ - /* happens in Print to ImageWriter */ - SCC.a[chan].TxIE = NewTxIE; - CheckSCCInterruptFlag(); - } - } - -#if SCC_TrackMore - { - blnr NewPrtySpclCond = (Data & Bit2) != 0; - if (SCC.a[chan].PrtySpclCond != NewPrtySpclCond) { - SCC.a[chan].PrtySpclCond = NewPrtySpclCond; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, - "Parity is special condition", NewPrtySpclCond); -#endif - /* - set to 1 in MacCheck - and in Print to ImageWriter - */ - } - } -#endif - -#if EmLocalTalk || SCC_TrackMore - { - ui3r NewRxIntMode = (Data >> 3) & 3; - if (SCC.a[chan].RxIntMode != NewRxIntMode) { - SCC.a[chan].RxIntMode = NewRxIntMode; - - switch (NewRxIntMode) { - case 0: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, "Rx INT Disable"); -#endif - /* happens on boot always */ - break; - case 1: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "Rx INT on 1st char" - " or special condition"); -#endif - SCC.a[chan].FirstChar = trueblnr; - /* happens on boot with appletalk on */ - break; - case 2: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "INT on all Rx char" - " or special condition"); -#endif - /* happens in MacCheck */ - /* happens in Print to ImageWriter */ - break; - case 3: - ReportAbnormal( - "Rx INT on special condition only"); - break; - } - } - } -#endif - -#if SCC_TrackMore - { - blnr NewWaitRqstRT = (Data & Bit5) != 0; - if (SCC.a[chan].WaitRqstRT != NewWaitRqstRT) { - SCC.a[chan].WaitRqstRT = NewWaitRqstRT; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, - "Wait/DMA request on receive/transmit", - NewWaitRqstRT); -#endif - /* happens in MacCheck */ - } - } -#endif - -#if SCC_TrackMore - { - blnr NewWaitRqstSlct = (Data & Bit6) != 0; - if (SCC.a[chan].WaitRqstSlct != NewWaitRqstSlct) { - SCC.a[chan].WaitRqstSlct = NewWaitRqstSlct; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, - "Wait/DMA request function", NewWaitRqstSlct); -#endif - /* happens in MacCheck */ - } - } -#endif - -#if SCC_TrackMore - { - blnr NewWaitRqstEnbl = (Data & Bit7) != 0; - if (SCC.a[chan].WaitRqstEnbl != NewWaitRqstEnbl) { - SCC.a[chan].WaitRqstEnbl = NewWaitRqstEnbl; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, - "Wait/DMA request enable", NewWaitRqstEnbl); -#endif - /* happens in MacCheck */ - } - } -#endif -} - -LOCALPROC SCC_PutWR2(ui3r Data, int chan) -/* "Interrupt Vector (accessed through either channel)" */ -{ - /* - Only 1 interrupt vector for the SCC, which - is stored in channels A and B. B is modified - when read. - */ - - /* happens on boot always */ - -#if ! SCC_dolog - UnusedParam(chan); -#endif - - if (SCC.InterruptVector != Data) { -#if SCC_dolog - SCC_DbgLogChanStartLine(chan); - dbglog_writeCStr(" InterruptVector <- "); - dbglog_writeHex(Data); - dbglog_writeReturn(); -#endif - SCC.InterruptVector = Data; - } - if ((Data & Bit0) != 0) { /* interrupt vector 0 */ - ReportAbnormal("interrupt vector 0"); - } - if ((Data & Bit1) != 0) { /* interrupt vector 1 */ - ReportAbnormal("interrupt vector 1"); - } - if ((Data & Bit2) != 0) { /* interrupt vector 2 */ - ReportAbnormal("interrupt vector 2"); - } - if ((Data & Bit3) != 0) { /* interrupt vector 3 */ - ReportAbnormal("interrupt vector 3"); - } - if ((Data & Bit4) != 0) { /* interrupt vector 4 */ - /* happens on boot with appletalk on */ - } - if ((Data & Bit5) != 0) { /* interrupt vector 5 */ - /* happens on boot with appletalk on */ - } - if ((Data & Bit6) != 0) { /* interrupt vector 6 */ - ReportAbnormal("interrupt vector 6"); - } - if ((Data & Bit7) != 0) { /* interrupt vector 7 */ - ReportAbnormal("interrupt vector 7"); - } -} - -LOCALPROC SCC_PutWR3(ui3r Data, int chan) -/* "Receive parameters and control" */ -{ -#if SCC_TrackMore - { - ui3r NewRBitsPerChar = (Data >> 6) & 3; - if (SCC.a[chan].RBitsPerChar != NewRBitsPerChar) { - SCC.a[chan].RBitsPerChar = NewRBitsPerChar; - - switch (NewRBitsPerChar) { - case 0: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "Rx Bits/Character <- 5"); -#endif - break; - case 1: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "Rx Bits/Character <- 7"); -#endif - break; - case 2: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "Rx Bits/Character <- 6"); -#endif - break; - case 3: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "Rx Bits/Character <- 8"); -#endif - break; - } - } - } -#endif - - if ((Data & Bit5) != 0) { /* Auto Enables */ - /* - use DCD input as receiver enable, - and set RTS output when transmit buffer empty - */ - ReportAbnormal("Auto Enables"); - } - - if ((Data & Bit4) != 0) { /* Enter Hunt Mode */ -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, "Enter Hunt Mode"); -#endif - /* happens on boot with appletalk on */ - if (! (SCC.a[chan].SyncHunt)) { - SCC.a[chan].SyncHunt = trueblnr; - -#if 0 /* SyncHuntIE usually false */ - if (SCC.a[chan].SyncHuntIE) { - SCC_Interrupt((chan == 0) - ? SCC_A_Ext - : SCC_B_Ext); - } -#endif - } - } - -#if SCC_TrackMore - { - blnr NewRxCRCEnbl = (Data & Bit3) != 0; - if (SCC.a[chan].RxCRCEnbl != NewRxCRCEnbl) { - SCC.a[chan].RxCRCEnbl = NewRxCRCEnbl; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, - "Rx CRC Enable", NewRxCRCEnbl); -#endif - /* happens on boot with appletalk on */ - } - } -#endif - -#if EmLocalTalk || SCC_TrackMore - { - blnr NewAddrSrchMd = (Data & Bit2) != 0; - if (SCC.a[chan].AddrSrchMd != NewAddrSrchMd) { - SCC.a[chan].AddrSrchMd = NewAddrSrchMd; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, - "Addr Search Mode (SDLC)", NewAddrSrchMd); -#endif - /* happens on boot with appletalk on */ - } - } -#endif - -#if SCC_TrackMore - { - blnr NewSyncChrLdInhb = (Data & Bit1) != 0; - if (SCC.a[chan].SyncChrLdInhb != NewSyncChrLdInhb) { - SCC.a[chan].SyncChrLdInhb = NewSyncChrLdInhb; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, - "Sync Char Load Inhibit", NewSyncChrLdInhb); -#endif - /* happens on boot with appletalk on */ - } - } -#endif - - { - blnr NewRxEnable = (Data & Bit0) != 0; - if (SCC.a[chan].RxEnable != NewRxEnable) { - SCC.a[chan].RxEnable = NewRxEnable; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, - "Rx Enable", NewRxEnable); -#endif - /* true on boot with appletalk on */ - /* true on Print to ImageWriter */ - -#if EmLocalTalk - if (! NewRxEnable) { -#if SCC_dolog - if ((0 != chan) && (nullpr != LT_RxBuffer)) { - dbglog_WriteNote("SCC abandon packet"); - } -#endif - - /* - Go back into the idle state if we were - waiting for EOF - */ - SCC.a[chan].EndOfFrame = falseblnr; - SCC.a[chan].RxChrAvail = falseblnr; - SCC.a[chan].SyncHunt = trueblnr; - } else { - /* look for a packet */ - LocalTalkTick(); - } -#endif - } - } -} - -LOCALPROC SCC_PutWR4(ui3r Data, int chan) -/* "Transmit/Receive miscellaneous parameters and modes" */ -{ -#if ! (EmLocalTalk || SCC_TrackMore) - UnusedParam(Data); - UnusedParam(chan); -#endif - -#if SCC_TrackMore - { - blnr NewPrtyEnable = (Data & Bit0) != 0; - if (SCC.a[chan].PrtyEnable != NewPrtyEnable) { - SCC.a[chan].PrtyEnable = NewPrtyEnable; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, - "Parity Enable", NewPrtyEnable); -#endif - } - } -#endif - -#if SCC_TrackMore - { - blnr NewPrtyEven = (Data & Bit1) != 0; - if (SCC.a[chan].PrtyEven != NewPrtyEven) { - SCC.a[chan].PrtyEven = NewPrtyEven; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, - "Parity Enable", NewPrtyEven); -#endif - } - } -#endif - -#if SCC_TrackMore - { - ui3r NewStopBits = (Data >> 2) & 3; - if (SCC.a[chan].StopBits != NewStopBits) { - SCC.a[chan].StopBits = NewStopBits; - - /* SCC_SetStopBits(chan, NewStopBits); */ - switch (NewStopBits) { - case 0: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "Sync Modes Enable"); -#endif - break; - case 1: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, "1 Stop Bit"); -#endif - break; - case 2: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, "1 1/2 Stop Bits"); -#endif - break; - case 3: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, "2 Stop Bits"); -#endif - break; - } - } - } -#endif - -#if EmLocalTalk || SCC_TrackMore - { - ui3r NewSyncMode = (Data >> 4) & 3; - if (SCC.a[chan].SyncMode != NewSyncMode) { - SCC.a[chan].SyncMode = NewSyncMode; - - switch (NewSyncMode) { - case 0: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, "8 bit sync char"); -#endif - /* happens on boot always */ - break; - case 1: - ReportAbnormal("16 bit sync char"); - break; - case 2: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, "SDLC MODE"); -#endif - /* happens on boot with appletalk on */ -#if EmLocalTalk - SCC.a[chan].TxBufferEmpty = trueblnr; -#endif - break; - case 3: - ReportAbnormal("External sync mode"); - break; - } - } - } -#endif - -#if SCC_TrackMore - { - ui3r NewClockRate = (Data >> 6) & 3; - if (SCC.a[chan].ClockRate != NewClockRate) { - SCC.a[chan].ClockRate = NewClockRate; - - switch (NewClockRate) { - case 0: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "Clock Rate <- X1"); -#endif - /* happens on boot with appletalk on */ - break; - case 1: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "Clock Rate <- X16"); -#endif - /* happens on boot always */ - break; - case 2: - ReportAbnormal("Clock Rate <- X32"); - break; - case 3: - ReportAbnormal("Clock Rate <- X64"); - break; - } - } - } -#endif -} - -LOCALPROC SCC_PutWR5(ui3r Data, int chan) -/* "Transmit parameters and controls" */ -{ - /* happens on boot with appletalk on */ - /* happens in Print to ImageWriter */ - -#if SCC_TrackMore - { - blnr NewTxCRCEnbl = (Data & Bit0) != 0; - if (SCC.a[chan].TxCRCEnbl != NewTxCRCEnbl) { - SCC.a[chan].TxCRCEnbl = NewTxCRCEnbl; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, - "Tx CRC Enable", NewTxCRCEnbl); -#endif - /* both values on boot with appletalk on */ - } - } -#endif - -#if SCC_TrackMore - { - blnr NewRTSctrl = (Data & Bit1) != 0; - if (SCC.a[chan].RTSctrl != NewRTSctrl) { - SCC.a[chan].RTSctrl = NewRTSctrl; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, - "RTS Control", NewRTSctrl); -#endif - /* both values on boot with appletalk on */ - /* - value of Request To Send output pin, when - Auto Enable is off - */ - } - } -#endif - - if ((Data & Bit2) != 0) { /* SDLC/CRC-16 */ - ReportAbnormal("SDLC/CRC-16"); - } - - { - blnr NewTxEnable = (Data & Bit3) != 0; - if (SCC.a[chan].TxEnable != NewTxEnable) { - SCC.a[chan].TxEnable = NewTxEnable; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, - "Tx Enable", NewTxEnable); -#endif - - if (NewTxEnable) { - /* happens on boot with appletalk on */ - /* happens in Print to ImageWriter */ -#if EmLocalTalk - LT_TxBuffSz = 0; -#endif - } else { -#if EmLocalTalk - SCC.a[chan].TxBufferEmpty = trueblnr; -#endif - } - } - } - -#if SCC_TrackMore - { - blnr NewSndBrkCtrl = (Data & Bit4) != 0; - if (SCC.a[chan].SndBrkCtrl != NewSndBrkCtrl) { - SCC.a[chan].SndBrkCtrl = NewSndBrkCtrl; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, - "Send Break Control", NewSndBrkCtrl); -#endif - /* true in Print to LaserWriter 300 */ - } - } -#endif - -#if SCC_TrackMore - { - ui3r NewTBitsPerChar = (Data >> 5) & 3; - if (SCC.a[chan].TBitsPerChar != NewTBitsPerChar) { - SCC.a[chan].TBitsPerChar = NewTBitsPerChar; - - switch (NewTBitsPerChar) { - case 0: - ReportAbnormal("Tx Bits/Character <- 5"); - break; - case 1: - ReportAbnormal("Tx Bits/Character <- 7"); - break; - case 2: - ReportAbnormal("Tx Bits/Character <- 6"); - break; - case 3: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "Tx Bits/Character <- 8"); -#endif - /* happens on boot with appletalk on */ - /* happens in Print to ImageWriter */ - break; - } - } - } -#endif - -#if SCC_TrackMore - { - blnr NewDTRctrl = (Data & Bit7) != 0; - if (SCC.a[chan].DTRctrl != NewDTRctrl) { - SCC.a[chan].DTRctrl = NewDTRctrl; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, - "Data Terminal Ready Control", NewDTRctrl); -#endif - /* zero happens in MacCheck */ - /* - value of Data Terminal Ready output pin, - when WR14 D2 = 0 (DTR/request function) - */ - } - } -#endif -} - -LOCALPROC SCC_PutWR6(ui3r Data, int chan) -/* "Sync characters or SDLC address field" */ -{ - /* happens on boot with appletalk on */ - -#if ! (EmLocalTalk || SCC_dolog) - UnusedParam(Data); -#endif -#if ! SCC_dolog - UnusedParam(chan); -#endif - -#if SCC_dolog - SCC_DbgLogChanStartLine(chan); - dbglog_writeCStr(" Sync Char <- "); - dbglog_writeHex(Data); - dbglog_writeReturn(); -#endif - -#if EmLocalTalk - if (0 != Data) { - my_node_address = Data; - } -#endif -} - -LOCALPROC SCC_PutWR7(ui3r Data, int chan) -/* "Sync character or SDLC flag" */ -{ - /* happens on boot with appletalk on */ - -#if ! SCC_TrackMore - UnusedParam(Data); - UnusedParam(chan); -#endif - -#if SCC_TrackMore - if (2 == SCC.a[chan].SyncMode) { - if (0x7E != Data) { - ReportAbnormal( - "unexpect flag character for SDLC"); - } - } else { - ReportAbnormal("WR7 and not SDLC"); - } -#endif -} - -LOCALPROC SCC_PutWR8(ui3r Data, int chan) -/* "Transmit Buffer" */ -{ - /* happens on boot with appletalk on */ - /* happens in Print to ImageWriter */ - -#if ! (EmLocalTalk || SCC_dolog) - UnusedParam(Data); -#endif - -#if SCC_dolog - SCC_DbgLogChanStartLine(chan); - dbglog_writeCStr(" Transmit Buffer"); - dbglog_writeCStr(" <- "); - dbglog_writeHex(Data); - dbglog_writeCStr(" '"); - dbglog_writeMacChar(Data); - dbglog_writeCStr("'"); - dbglog_writeReturn(); -#endif - - if (SCC.a[chan].TxEnable) { /* Tx Enable */ - /* Output (Data) to Modem(B) or Printer(A) Port */ - - /* happens on boot with appletalk on */ -#if EmLocalTalk - if (chan != 0) { - SCC_TxBuffPut(Data); - } -#else -#if 0 /* TxBufferEmpty always true */ - SCC.a[chan].TxBufferEmpty = trueblnr; -#endif - SCC.a[chan].TxUnderrun = trueblnr; /* underrun ? */ -#endif - - SCC.a[chan].TxIP = trueblnr; - CheckSCCInterruptFlag(); - } else { - ReportAbnormal( - "write when Transmit Buffer not Enabled"); -#if 0 /* TxBufferEmpty always true */ - SCC.a[chan].TxBufferEmpty = falseblnr; -#endif - } -} - -LOCALPROC SCC_PutWR9(ui3r Data, int chan) -/* - "Master interrupt control and reset - (accessed through either channel)" -*/ -{ - /* Only 1 WR9 in the SCC */ - - UnusedParam(chan); - - if ((Data & Bit0) != 0) { /* VIS */ - ReportAbnormal("VIS"); - } - -#if SCC_TrackMore - { - blnr NewNoVectorSlct = (Data & Bit1) != 0; - if (SCC.NoVectorSlct != NewNoVectorSlct) { - SCC.NoVectorSlct = NewNoVectorSlct; -#if SCC_dolog - dbglog_WriteSetBool("SCC No Vector select", - NewNoVectorSlct); -#endif - /* has both values on boot always */ - } - } -#endif - - if ((Data & Bit2) != 0) { /* DLC */ - ReportAbnormal("DLC"); - } - - { - blnr NewMIE = (Data & Bit3) != 0; - /* has both values on boot always */ - if (SCC.MIE != NewMIE) { - SCC.MIE = NewMIE; -#if SCC_dolog - dbglog_WriteSetBool("SCC Master Interrupt Enable", - NewMIE); -#endif - CheckSCCInterruptFlag(); - } - } - -#if 0 /* StatusHiLo always false */ - SCC.StatusHiLo = (Data & Bit4) != 0; -#else - if ((Data & Bit4) != 0) { /* Status high/low */ - ReportAbnormal("Status high/low"); - } -#endif - if ((Data & Bit5) != 0) { /* WR9 b5 should be 0 */ - ReportAbnormal("WR9 b5 should be 0"); - } - - switch ((Data >> 6) & 3) { - case 1: -#if SCC_dolog - SCC_DbgLogChanCmnd(1, "Channel Reset"); -#endif - /* happens on boot always */ - SCC_ResetChannel(1); - CheckSCCInterruptFlag(); - break; - case 2: -#if SCC_dolog - SCC_DbgLogChanCmnd(0, "Channel Reset"); -#endif - /* happens on boot always */ - SCC_ResetChannel(0); - CheckSCCInterruptFlag(); - break; - case 3: -#if SCC_dolog - dbglog_WriteNote("SCC Force Hardware Reset"); -#endif -#if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx) - /* don't report */ -#else - ReportAbnormal("SCC_Reset"); -#endif - SCC_Reset(); - CheckSCCInterruptFlag(); - break; - case 0: /* No Reset */ - default: - break; - } -} - -LOCALPROC SCC_PutWR10(ui3r Data, int chan) -/* "Miscellaneous transmitter/receiver control bits" */ -{ - /* happens on boot with appletalk on */ - /* happens in Print to ImageWriter */ - -#if ! SCC_TrackMore - UnusedParam(chan); -#endif - - if ((Data & Bit0) != 0) { /* 6 bit/8 bit sync */ - ReportAbnormal("6 bit/8 bit sync"); - } - if ((Data & Bit1) != 0) { /* loop mode */ - ReportAbnormal("loop mode"); - } - if ((Data & Bit2) != 0) { /* abort/flag on underrun */ - ReportAbnormal("abort/flag on underrun"); - } - if ((Data & Bit3) != 0) { /* mark/flag idle */ - ReportAbnormal("mark/flag idle"); - } - if ((Data & Bit4) != 0) { /* go active on poll */ - ReportAbnormal("go active on poll"); - } - -#if SCC_TrackMore - { - ui3r NewDataEncoding = (Data >> 5) & 3; - if (SCC.a[chan].DataEncoding != NewDataEncoding) { - SCC.a[chan].DataEncoding = NewDataEncoding; - - switch (NewDataEncoding) { - case 0: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "Data Encoding <- NRZ"); -#endif - /* happens in MacCheck */ - /* happens in Print to ImageWriter */ - break; - case 1: - ReportAbnormal("Data Encoding <- NRZI"); - break; - case 2: - ReportAbnormal("Data Encoding <- FM1"); - break; - case 3: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "Data Encoding <- FM0"); -#endif - /* happens on boot with appletalk on */ - break; - } - } - } -#endif - -#if SCC_TrackMore - { - blnr NewCRCPreset = (Data & Bit7) != 0; - if (SCC.a[chan].CRCPreset != NewCRCPreset) { - SCC.a[chan].CRCPreset = NewCRCPreset; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, - "CRC preset I/O", NewCRCPreset); -#endif - /* false happens in MacCheck */ - /* true happens in Print to ImageWriter */ - } - } -#endif -} - -LOCALPROC SCC_PutWR11(ui3r Data, int chan) -/* "Clock mode control" */ -{ - /* happens on boot with appletalk on */ - /* happens in Print to ImageWriter */ - /* happens in MacCheck */ - -#if ! SCC_TrackMore - UnusedParam(chan); -#endif - -#if SCC_TrackMore - /* Transmit External Control Selection */ - { - ui3r NewTRxCsrc = Data & 3; - if (SCC.a[chan].TRxCsrc != NewTRxCsrc) { - SCC.a[chan].TRxCsrc = NewTRxCsrc; - - switch (NewTRxCsrc) { - case 0: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "TRxC OUT = XTAL output"); -#endif - /* happens on boot with appletalk on */ - /* happens in Print to ImageWriter */ - /* happens in MacCheck */ - break; - case 1: - ReportAbnormal("TRxC OUT = transmit clock"); - break; - case 2: - ReportAbnormal( - "TRxC OUT = BR generator output"); - break; - case 3: - ReportAbnormal("TRxC OUT = dpll output"); - break; - } - } - } -#endif - - if ((Data & Bit2) != 0) { - ReportAbnormal("TRxC O/I"); - } - -#if SCC_TrackMore - { - ui3r NewTClkSlct = (Data >> 3) & 3; - if (SCC.a[chan].TClkSlct != NewTClkSlct) { - SCC.a[chan].TClkSlct = NewTClkSlct; - - switch (NewTClkSlct) { - case 0: - ReportAbnormal("transmit clock = RTxC pin"); - break; - case 1: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "transmit clock = TRxC pin"); -#endif - /* happens in Print to LaserWriter 300 */ - break; - case 2: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "transmit clock = BR generator output"); -#endif - /* happens on boot with appletalk on */ - /* happens in Print to ImageWriter */ - /* happens in MacCheck */ - break; - case 3: - ReportAbnormal( - "transmit clock = dpll output"); - break; - } - } - } -#endif - -#if SCC_TrackMore - { - ui3r NewRClkSlct = (Data >> 5) & 3; - if (SCC.a[chan].RClkSlct != NewRClkSlct) { - SCC.a[chan].RClkSlct = NewRClkSlct; - - switch (NewRClkSlct) { - case 0: - ReportAbnormal("receive clock = RTxC pin"); - break; - case 1: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "receive clock = TRxC pin"); -#endif - /* happens in Print to LaserWriter 300 */ - break; - case 2: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "receive clock = BR generator output"); -#endif - /* happens in MacCheck */ - /* happens in Print to ImageWriter */ - break; - case 3: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, - "receive clock = dpll output"); -#endif - /* happens on boot with appletalk on */ - break; - } - } - } -#endif - - if ((Data & Bit7) != 0) { - ReportAbnormal("RTxC XTAL/NO XTAL"); - } -} - -LOCALPROC SCC_PutWR12(ui3r Data, int chan) -/* "Lower byte of baud rate generator time constant" */ -{ - /* happens on boot with appletalk on */ - /* happens in Print to ImageWriter */ - -#if ! SCC_TrackMore - UnusedParam(Data); - UnusedParam(chan); -#endif - -#if SCC_TrackMore /* don't care about Baud */ - if (SCC.a[chan].BaudLo != Data) { - SCC.a[chan].BaudLo = Data; - -#if SCC_dolog - SCC_DbgLogChanStartLine(chan); - dbglog_writeCStr(" BaudLo <- "); - dbglog_writeHex(Data); - dbglog_writeReturn(); -#endif - } -#endif - -#if 0 - SCC_SetBaud(chan, - SCC.a[chan].BaudLo + (SCC.a[chan].BaudHi << 8)); - /* 380: BaudRate = 300 */ - /* 94: BaudRate = 1200 */ - /* 46: BaudRate = 2400 */ - /* 22: BaudRate = 4800 */ - /* 10: BaudRate = 9600 */ - /* 4: BaudRate = 19200 */ - /* 1: BaudRate = 38400 */ - /* 0: BaudRate = 57600 */ -#endif -} - -LOCALPROC SCC_PutWR13(ui3r Data, int chan) -/* "Upper byte of baud rate generator time constant" */ -{ - /* happens on boot with appletalk on */ - /* happens in Print to ImageWriter */ - -#if ! SCC_TrackMore - UnusedParam(Data); - UnusedParam(chan); -#endif - -#if SCC_TrackMore /* don't care about Baud */ - if (SCC.a[chan].BaudHi != Data) { - SCC.a[chan].BaudHi = Data; - -#if SCC_dolog - SCC_DbgLogChanStartLine(chan); - dbglog_writeCStr(" BaudHi <- "); - dbglog_writeHex(Data); - dbglog_writeReturn(); -#endif - } -#endif - -#if 0 - SCC_SetBaud(chan, - SCC.a[chan].BaudLo + (SCC.a[chan].BaudHi << 8)); -#endif -} - -LOCALPROC SCC_PutWR14(ui3r Data, int chan) -/* "Miscellaneous control bits" */ -{ - /* happens on boot with appletalk on */ - -#if ! (SCC_TrackMore || SCC_dolog) - UnusedParam(chan); -#endif - -#if SCC_TrackMore - { - blnr NewBRGEnbl = (Data & Bit0) != 0; - if (SCC.a[chan].BRGEnbl != NewBRGEnbl) { - SCC.a[chan].BRGEnbl = NewBRGEnbl; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, - "BR generator enable", NewBRGEnbl); -#endif - /* both values on boot with appletalk on */ - /* true happens in Print to ImageWriter */ - } - } -#endif - - if ((Data & Bit1) != 0) { /* BR generator source */ - ReportAbnormal("BR generator source"); - } - if ((Data & Bit2) != 0) { /* DTR/request function */ - ReportAbnormal("DTR/request function"); - } - if ((Data & Bit3) != 0) { /* auto echo */ - ReportAbnormal("auto echo"); - } - if ((Data & Bit4) != 0) { /* local loopback */ - ReportAbnormal("local loopback"); - } - - switch ((Data >> 5) & 7) { - case 1: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, "enter search mode"); -#endif - /* happens on boot with appletalk on */ - break; - case 2: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, "reset missing clock"); -#endif - /* happens on boot with appletalk on */ - /* - should clear Bit 6 and Bit 7 of RR[10], but - since these are never set, don't need - to do anything - */ - break; - case 3: - ReportAbnormal("disable dpll"); - /* - should clear Bit 6 and Bit 7 of RR[10], but - since these are never set, don't need - to do anything - */ - break; - case 4: - ReportAbnormal("set source = br generator"); - break; - case 5: - ReportAbnormal("set source = RTxC"); - break; - case 6: -#if SCC_dolog - SCC_DbgLogChanCmnd(chan, "set FM mode"); -#endif - /* happens on boot with appletalk on */ - break; - case 7: - ReportAbnormal("set NRZI mode"); - break; - case 0: /* No Reset */ - default: - break; - } -} - -LOCALPROC SCC_PutWR15(ui3r Data, int chan) -/* "External/Status interrupt control" */ -{ - /* happens on boot always */ - -#if ! SCC_TrackMore - UnusedParam(chan); -#endif - - if ((Data & Bit0) != 0) { /* WR15 b0 should be 0 */ - ReportAbnormal("WR15 b0 should be 0"); - } - if ((Data & Bit1) != 0) { /* zero count IE */ - ReportAbnormal("zero count IE"); - } - if ((Data & Bit2) != 0) { /* WR15 b2 should be 0 */ - ReportAbnormal("WR15 b2 should be 0"); - } - -#if 0 /* don't care about DCD_IE, always true */ - SCC.a[chan].DCD_IE = (Data & Bit3) != 0; -#else - if ((Data & Bit3) == 0) { /* DCD_IE */ -#if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx) - /* don't report */ -#else - ReportAbnormal("not DCD IE"); -#endif - } -#endif - -#if 0 /* SyncHuntIE usually false */ - SCC.a[chan].SyncHuntIE = (Data & Bit4) != 0; -#else - if ((Data & Bit4) != 0) { - /* SYNC/HUNT IE */ - ReportAbnormal("SYNC/HUNT IE"); - } -#endif - -#if SCC_TrackMore /* don't care about CTS_IE */ - { - blnr NewCTS_IE = (Data & Bit5) != 0; - if (SCC.a[chan].CTS_IE != NewCTS_IE) { - SCC.a[chan].CTS_IE = NewCTS_IE; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, - "CTS IE", NewCTS_IE); -#endif - /* happens in MacCheck */ - /* happens in Print to ImageWriter */ - } - } -#endif - - if ((Data & Bit6) != 0) { /* Tx underrun/EOM IE */ - ReportAbnormal("Tx underrun/EOM IE"); - } - -#if SCC_TrackMore - { - blnr NewBreakAbortIE = (Data & Bit7) != 0; - if (SCC.a[chan].BreakAbortIE != NewBreakAbortIE) { - SCC.a[chan].BreakAbortIE = NewBreakAbortIE; -#if SCC_dolog - SCC_DbgLogChanChngBit(chan, - "BreakAbort IE", NewBreakAbortIE); -#endif - /* happens in MacCheck */ - /* happens in Print to ImageWriter */ - } - } -#endif -} - -LOCALFUNC ui3r SCC_GetReg(int chan, ui3r SCC_Reg) -{ - ui3r value; - - switch (SCC_Reg) { - case 0: - value = SCC_GetRR0(chan); - break; - case 1: - value = SCC_GetRR1(chan); - break; - case 2: - value = SCC_GetRR2(chan); - break; - case 3: - value = SCC_GetRR3(chan); - break; - case 4: - ReportAbnormal("RR 4"); /* same as RR0 */ - value = SCC_GetRR0(chan); - break; - case 5: - ReportAbnormal("RR 5"); /* same as RR1 */ - value = SCC_GetRR1(chan); - break; - case 6: - ReportAbnormal("RR 6"); /* same as RR2 */ - value = SCC_GetRR2(chan); - break; - case 7: - ReportAbnormal("RR 7"); /* same as RR3 */ - value = SCC_GetRR3(chan); - break; - case 8: - value = SCC_GetRR8(chan); - break; - case 9: - ReportAbnormal("RR 9"); /* same as RR13 */ - value = SCC_GetRR13(chan); - break; - case 10: - value = SCC_GetRR10(chan); - break; - case 11: - ReportAbnormal("RR 11"); /* same as RR15 */ - value = SCC_GetRR15(chan); - break; - case 12: - value = SCC_GetRR12(chan); - break; - case 13: - value = SCC_GetRR13(chan); - break; - case 14: - ReportAbnormal("RR 14"); - value = 0; - break; - case 15: - value = SCC_GetRR15(chan); - break; - default: - ReportAbnormal("unexpected SCC_Reg in SCC_GetReg"); - value = 0; - break; - } - -#if EmLocalTalk - /* - Always check to see if interrupt state changed after - ANY register access - */ - CheckSCCInterruptFlag(); -#endif - -#if SCC_dolog - SCC_DbgLogChanStartLine(chan); - dbglog_writeCStr(" RR["); - dbglog_writeHex(SCC_Reg); - dbglog_writeCStr("] -> "); - dbglog_writeHex(value); - dbglog_writeReturn(); -#endif - - return value; -} - -LOCALPROC SCC_PutReg(ui3r Data, int chan, ui3r SCC_Reg) -{ -#if SCC_dolog && 0 - SCC_DbgLogChanStartLine(chan); - dbglog_writeCStr(" WR["); - dbglog_writeHex(SCC_Reg); - dbglog_writeCStr("] <- "); - dbglog_writeHex(Data); - dbglog_writeReturn(); -#endif - - switch (SCC_Reg) { - case 0: - SCC_PutWR0(Data, chan); - break; - case 1: - SCC_PutWR1(Data, chan); - break; - case 2: - SCC_PutWR2(Data, chan); - break; - case 3: - SCC_PutWR3(Data, chan); - break; - case 4: - SCC_PutWR4(Data, chan); - break; - case 5: - SCC_PutWR5(Data, chan); - break; - case 6: - SCC_PutWR6(Data, chan); - break; - case 7: - SCC_PutWR7(Data, chan); - break; - case 8: - SCC_PutWR8(Data, chan); - break; - case 9: - SCC_PutWR9(Data, chan); - break; - case 10: - SCC_PutWR10(Data, chan); - break; - case 11: - SCC_PutWR11(Data, chan); - break; - case 12: - SCC_PutWR12(Data, chan); - break; - case 13: - SCC_PutWR13(Data, chan); - break; - case 14: - SCC_PutWR14(Data, chan); - break; - case 15: - SCC_PutWR15(Data, chan); - break; - default: - ReportAbnormal("unexpected SCC_Reg in SCC_PutReg"); - break; - } - -#if EmLocalTalk - /* - Always check to see if interrupt state changed after ANY - register access - */ - CheckSCCInterruptFlag(); -#endif -} - -GLOBALFUNC ui5b SCC_Access(ui5b Data, blnr WriteMem, CPTR addr) -{ -#if EmLocalTalk - /* - Determine channel, data, and access type from address. The bus - for the 8350 is non-standard, so the Macintosh connects address - bus lines to various signals on the 8350 as shown below. The - 68K will use the upper byte of the data bus for odd addresses, - and the 8350 is only wired to the upper byte, therefore use - only odd addresses or you risk resetting the 8350. - - 68k 8350 - ----- ------ - a1 a/b - a2 d/c - a21 wr/rd - */ -#endif - ui3b SCC_Reg; - int chan = (~ addr) & 1; /* 0=modem, 1=printer */ - if (((addr >> 1) & 1) == 0) { - /* Channel Control */ - SCC_Reg = SCC.PointerBits; - SCC.PointerBits = 0; - } else { - /* Channel Data */ - SCC_Reg = 8; - } - if (WriteMem) { - SCC_PutReg(Data, chan, SCC_Reg); - } else { - Data = SCC_GetReg(chan, SCC_Reg); - } - - return Data; -} +/* SCCEMDEV.c Copyright (C) 2012 Philip Cummins, Weston Pawlowski, Michael Fort, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* Serial Communications Controller EMulated DEVice additions for LocalTalk networking support Copyright 2011-2012, Michael Fort enabled with "EmLocalTalk" -- original description: -- Emulates the Z8530 SCC found in the Mac Plus. But only the minimum amount needed to emulate normal operation in a Mac Plus with nothing connected to the serial ports. (and not even that much is complete yet) This code adapted from "SCC.c" in vMac by Philip Cummins. With additional code by Weston Pawlowski from the Windows port of vMac. Further information was found in the "Zilog SCC/ESCC User's Manual". */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif #include "SCCEMDEV.h" /* ReportAbnormalID unused 0x0721, 0x0722, 0x074D - 0x07FF */ #define SCC_dolog (dbglog_HAVE && 0) #define SCC_TrackMore 0 /* Just to make things a little easier */ #define Bit0 1 #define Bit1 2 #define Bit2 4 #define Bit3 8 #define Bit4 16 #define Bit5 32 #define Bit6 64 #define Bit7 128 /* SCC Interrupts */ #define SCC_A_Rx 8 /* Rx Char Available */ #define SCC_A_Rx_Spec 7 /* Rx Special Condition */ #define SCC_A_Tx_Empty 6 /* Tx Buffer Empty */ #define SCC_A_Ext 5 /* External/Status Change */ #define SCC_B_Rx 4 /* Rx Char Available */ #define SCC_B_Rx_Spec 3 /* Rx Special Condition */ #define SCC_B_Tx_Empty 2 /* Tx Buffer Empty */ #define SCC_B_Ext 1 /* External/Status Change */ typedef struct { blnr TxEnable; blnr RxEnable; blnr TxIE; /* Transmit Interrupt Enable */ blnr TxUnderrun; blnr SyncHunt; blnr TxIP; /* Transmit Interrupt Pending */ #if EmLocalTalk ui3r RxBuff; #endif #if EmLocalTalk /* otherwise TxBufferEmpty always true */ /* though should behave as went false for an instant when write to transmit buffer */ blnr TxBufferEmpty; #endif #if EmLocalTalk || SCC_TrackMore blnr ExtIE; #endif #if SCC_TrackMore blnr WaitRqstEnbl; #endif #if SCC_TrackMore blnr WaitRqstSlct; #endif #if SCC_TrackMore blnr WaitRqstRT; #endif #if SCC_TrackMore blnr PrtySpclCond; #endif #if SCC_TrackMore blnr PrtyEnable; #endif #if SCC_TrackMore blnr PrtyEven; #endif #if SCC_TrackMore blnr RxCRCEnbl; #endif #if SCC_TrackMore blnr TxCRCEnbl; #endif #if SCC_TrackMore blnr RTSctrl; #endif #if SCC_TrackMore blnr SndBrkCtrl; #endif #if SCC_TrackMore blnr DTRctrl; #endif #if EmLocalTalk || SCC_TrackMore blnr AddrSrchMd; #endif #if SCC_TrackMore blnr SyncChrLdInhb; #endif #if SCC_TrackMore ui3r ClockRate; #endif #if SCC_TrackMore ui3r DataEncoding; #endif #if SCC_TrackMore ui3r TRxCsrc; #endif #if SCC_TrackMore ui3r TClkSlct; #endif #if SCC_TrackMore ui3r RClkSlct; #endif #if SCC_TrackMore ui3r RBitsPerChar; #endif #if SCC_TrackMore ui3r TBitsPerChar; #endif #if EmLocalTalk || SCC_TrackMore ui3r RxIntMode; #endif #if EmLocalTalk || SCC_TrackMore blnr FirstChar; #endif #if EmLocalTalk || SCC_TrackMore ui3r SyncMode; #endif #if SCC_TrackMore ui3r StopBits; #endif #if 0 /* AllSent always true */ blnr AllSent; #endif #if 0 /* CTS always false */ blnr CTS; /* input pin, unattached, so false? */ #endif #if 0 /* DCD always false */ blnr DCD; /* Data Carrier Detect */ /* input pin for mouse interrupts. but since not emulating mouse this way, leave false. */ #endif #if EmLocalTalk /* otherwise RxChrAvail always false */ blnr RxChrAvail; #endif #if 0 /* RxOverrun always false */ blnr RxOverrun; #endif #if 0 /* CRCFramingErr always false */ blnr CRCFramingErr; #endif #if EmLocalTalk /* otherwise EndOfFrame always false */ blnr EndOfFrame; #endif #if 0 /* ParityErr always false */ blnr ParityErr; #endif #if 0 /* ZeroCount always false */ blnr ZeroCount; #endif #if 0 /* BreakAbort always false */ blnr BreakAbort; #endif #if 0 /* SyncHuntIE usually false */ blnr SyncHuntIE; #endif #if SCC_TrackMore /* don't care about CTS_IE */ blnr CTS_IE; #endif #if SCC_TrackMore blnr CRCPreset; #endif #if SCC_TrackMore blnr BRGEnbl; #endif #if 0 /* don't care about DCD_IE, always true */ blnr DCD_IE; #endif #if SCC_TrackMore /* don't care about BreakAbortIE */ blnr BreakAbortIE; #endif #if SCC_TrackMore /* don't care about Baud */ ui3r BaudLo; ui3r BaudHi; #endif } Channel_Ty; typedef struct { Channel_Ty a[2]; /* 0 = channel A, 1 = channel B */ int SCC_Interrupt_Type; int PointerBits; ui3b InterruptVector; blnr MIE; /* master interrupt enable */ #if SCC_TrackMore blnr NoVectorSlct; #endif #if 0 /* StatusHiLo always false */ blnr StatusHiLo; #endif } SCC_Ty; LOCALVAR SCC_Ty SCC; #if 0 LOCALVAR int ReadPrint; LOCALVAR int ReadModem; #endif #if EmLocalTalk static int rx_data_offset = 0; /* when data pending, this is used */ #endif EXPORTFUNC blnr SCC_InterruptsEnabled(void) { return SCC.MIE; } /* ---- */ /* Function used to update the interrupt state of the SCC */ LOCALPROC CheckSCCInterruptFlag(void) { #if 0 /* ReceiveAInterrupt always false */ blnr ReceiveAInterrupt = falseblnr /* also dependeds on WR1, bits 3 and 4, but this doesn't change that it's all false */ #if EmLocalTalk /* otherwise RxChrAvail always false */ | SCC.a[0].RxChrAvail #endif #if 0 /* RxOverrun always false */ | SCC.a[0].RxOverrun #endif #if 0 /* CRCFramingErr always false */ | SCC.a[0].CRCFramingErr #endif #if EmLocalTalk /* otherwise EndOfFrame always false */ | SCC.a[0].EndOfFrame #endif #if 0 /* ParityErr always false */ | SCC.a[0].ParityErr #endif ; #endif #if 0 blnr TransmitAInterrupt = SCC.a[0].TxBufferEmpty; /* but probably looking for transitions not current value */ #endif #if 0 blnr ExtStatusAInterrupt = 0 #if 0 /* ZeroCount always false */ | SCC.a[0].ZeroCount #endif /* probably want transition for these, not value */ #if 0 /* DCD always false */ | SCC.a[0].DCD /* DCD IE always true */ #endif #if 0 /* CTS always false */ | SCC.a[0].CTS /* would depend on CTS_IE */ #endif | SCC.a[0].SyncHunt /* SyncHuntIE usually false */ | SCC.a[0].TxUnderrun /* Tx underrun/EOM IE always false */ #if 0 /* BreakAbort always false */ | SCC.a[0].BreakAbort #endif ; #endif ui3b NewSCCInterruptRequest; #if EmLocalTalk blnr ReceiveBInterrupt = falseblnr; blnr RxSpclBInterrupt = falseblnr /* otherwise EndOfFrame always false */ | SCC.a[1].EndOfFrame ; #endif #if EmLocalTalk switch (SCC.a[1].RxIntMode) { case 0: /* disabled */ RxSpclBInterrupt = falseblnr; break; case 1: /* Rx INT on 1st char or special condition */ if (SCC.a[1].RxChrAvail && SCC.a[1].FirstChar) { ReceiveBInterrupt = trueblnr; } break; case 2: /* INT on all Rx char or special condition */ if (SCC.a[1].RxChrAvail) { ReceiveBInterrupt = trueblnr; } break; case 3: /* Rx INT on special condition only */ break; } #endif /* Master Interrupt Enable */ if (! SCC.MIE) { SCC.SCC_Interrupt_Type = 0; } else #if 0 /* External Interrupt Enable */ if (SCC.a[1].ExtIE) { /* DCD Interrupt Enable */ if (SCC.a[1].DCD_IE && 0) { /* dcd unchanged */ SCC.SCC_Interrupt_Type = ??; } } #endif if (SCC.a[0].TxIP && SCC.a[0].TxIE) { SCC.SCC_Interrupt_Type = SCC_A_Tx_Empty; } else #if EmLocalTalk if (ReceiveBInterrupt) { SCC.SCC_Interrupt_Type = SCC_B_Rx; } else if (RxSpclBInterrupt) { SCC.SCC_Interrupt_Type = SCC_B_Rx_Spec; } else #endif if (SCC.a[1].TxIP && SCC.a[1].TxIE) { SCC.SCC_Interrupt_Type = SCC_B_Tx_Empty; } else { SCC.SCC_Interrupt_Type = 0; } NewSCCInterruptRequest = (SCC.SCC_Interrupt_Type != 0) ? 1 : 0; if (NewSCCInterruptRequest != SCCInterruptRequest) { #if SCC_dolog dbglog_WriteSetBool("SCCInterruptRequest change", NewSCCInterruptRequest); dbglog_StartLine(); dbglog_writeCStr("SCC.SCC_Interrupt_Type <- "); dbglog_writeHex(SCC.SCC_Interrupt_Type); dbglog_writeReturn(); #endif SCCInterruptRequest = NewSCCInterruptRequest; #ifdef SCCinterruptChngNtfy SCCinterruptChngNtfy(); #endif } } LOCALPROC SCC_InitChannel(int chan) { /* anything not done by ResetChannel */ SCC.a[chan].SyncHunt = trueblnr; #if 0 /* DCD always false */ SCC.a[chan].DCD = falseblnr; /* input pin, reset doesn't change */ #endif #if 0 /* CTS always false */ SCC.a[chan].CTS = falseblnr; /* input pin, reset doesn't change */ #endif #if 0 /* AllSent always true */ SCC.a[chan].AllSent = trueblnr; #endif #if SCC_TrackMore /* don't care about Baud */ SCC.a[chan].BaudLo = 0; SCC.a[chan].BaudHi = 0; #endif #if 0 /* BreakAbort always false */ SCC.a[chan].BreakAbort = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].BRGEnbl = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].TRxCsrc = 0; #endif #if SCC_TrackMore SCC.a[chan].TClkSlct = 1; #endif #if SCC_TrackMore SCC.a[chan].RClkSlct = 0; #endif } LOCALPROC SCC_ResetChannel(int chan) { /* RR 0 */ #if EmLocalTalk SCC.a[chan].RxBuff = 0; #endif #if EmLocalTalk /* otherwise RxChrAvail always false */ SCC.a[chan].RxChrAvail = falseblnr; #endif #if 0 /* ZeroCount always false */ SCC.a[chan].ZeroCount = falseblnr; #endif #if EmLocalTalk /* otherwise TxBufferEmpty always true */ SCC.a[chan].TxBufferEmpty = trueblnr; #endif SCC.a[chan].TxUnderrun = trueblnr; /* RR 1 */ #if 0 /* ParityErr always false */ SCC.a[chan].ParityErr = falseblnr; #endif #if 0 /* RxOverrun always false */ SCC.a[chan].RxOverrun = falseblnr; #endif #if 0 /* CRCFramingErr always false */ SCC.a[chan].CRCFramingErr = falseblnr; #endif #if EmLocalTalk /* otherwise EndOfFrame always false */ SCC.a[chan].EndOfFrame = falseblnr; #endif /* RR 3 */ #if EmLocalTalk || SCC_TrackMore SCC.a[chan].ExtIE = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].RxCRCEnbl = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].TxCRCEnbl = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].RTSctrl = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].SndBrkCtrl = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].DTRctrl = falseblnr; #endif #if EmLocalTalk || SCC_TrackMore SCC.a[chan].AddrSrchMd = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].SyncChrLdInhb = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].WaitRqstEnbl = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].WaitRqstSlct = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].WaitRqstRT = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].PrtySpclCond = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].PrtyEnable = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].PrtyEven = falseblnr; #endif #if SCC_TrackMore SCC.a[chan].ClockRate = 0; #endif #if SCC_TrackMore SCC.a[chan].DataEncoding = 0; #endif #if SCC_TrackMore SCC.a[chan].RBitsPerChar = 0; #endif #if SCC_TrackMore SCC.a[chan].TBitsPerChar = 0; #endif #if EmLocalTalk || SCC_TrackMore SCC.a[chan].RxIntMode = 0; #endif #if EmLocalTalk || SCC_TrackMore SCC.a[chan].FirstChar = falseblnr; #endif #if EmLocalTalk || SCC_TrackMore SCC.a[chan].SyncMode = 0; #endif #if SCC_TrackMore SCC.a[chan].StopBits = 0; #endif #if SCC_TrackMore SCC.NoVectorSlct = falseblnr; #endif SCC.a[chan].TxIP = falseblnr; SCC.a[chan].TxEnable = falseblnr; SCC.a[chan].RxEnable = falseblnr; SCC.a[chan].TxIE = falseblnr; #if 0 /* don't care about DCD_IE, always true */ SCC.a[chan].DCD_IE = trueblnr; #endif #if SCC_TrackMore /* don't care about CTS_IE */ SCC.a[chan].CTS_IE = trueblnr; #endif #if SCC_TrackMore SCC.a[chan].CRCPreset = falseblnr; #endif #if 0 /* SyncHuntIE usually false */ SCC.a[chan].SyncHuntIE = trueblnr; #endif #if SCC_TrackMore /* don't care about BreakAbortIE */ SCC.a[chan].BreakAbortIE = trueblnr; #endif SCC.PointerBits = 0; #if 0 if (chan != 0) { ReadPrint = 0; } else { ReadModem = 0; } #endif } GLOBALPROC SCC_Reset(void) { SCCwaitrq = 1; SCC.SCC_Interrupt_Type = 0; SCCInterruptRequest = 0; SCC.PointerBits = 0; SCC.MIE = falseblnr; SCC.InterruptVector = 0; #if 0 /* StatusHiLo always false */ SCC.StatusHiLo = falseblnr; #endif SCC_InitChannel(1); SCC_InitChannel(0); SCC_ResetChannel(1); SCC_ResetChannel(0); } #if EmLocalTalk LOCALVAR blnr CTSpacketPending = falseblnr; LOCALVAR ui3r CTSpacketRxDA; LOCALVAR ui3r CTSpacketRxSA; /* Function used when all the tx data is sent to the SCC as indicated by resetting the TX underrun/EOM latch. If the transmit packet is a unicast RTS LAPD packet, we fake the corresponding CTS LAPD packet. This is okay because it is only a collision avoidance mechanism and the Ethernet device itself and BPF automatically handle collision detection and retransmission. Besides this is what a standard AppleTalk (LocalTalk to EtherTalk) bridge does. */ LOCALPROC process_transmit(void) { /* Check for LLAP packets, which we won't send */ if (LT_TxBuffSz == 3) { /* We will automatically and immediately acknowledge any non-broadcast RTS packets */ if ((LT_TxBuffer[0] != 0xFF) && (LT_TxBuffer[2] == 0x84)) { #if SCC_dolog dbglog_WriteNote("SCC LLAP packet in process_transmit"); #endif if (CTSpacketPending) { ReportAbnormalID(0x0701, "Already CTSpacketPending in process_transmit"); } else { CTSpacketRxDA = LT_TxBuffer[1]; /* rx da = tx sa */ CTSpacketRxSA = LT_TxBuffer[0]; /* rx sa = tx da */ CTSpacketPending = trueblnr; } } } else { LT_TransmitPacket(); } } LOCALPROC SCC_TxBuffPut(ui3r Data) { /* Buffer the data in the transmit buffer */ if (LT_TxBuffSz < LT_TxBfMxSz) { LT_TxBuffer[LT_TxBuffSz] = Data; ++LT_TxBuffSz; } } LOCALVAR ui3b MyCTSBuffer[4]; LOCALPROC GetCTSpacket(void) { /* Get a single buffer worth of packets at a time */ ui3p device_buffer = MyCTSBuffer; #if SCC_dolog dbglog_WriteNote("SCC receiving CTS packet"); #endif /* Create the fake response from the other node */ device_buffer[0] = CTSpacketRxDA; device_buffer[1] = CTSpacketRxSA; device_buffer[2] = 0x85; /* llap cts */ /* Start the receiver */ LT_RxBuffer = device_buffer; LT_RxBuffSz = 3; CTSpacketPending = falseblnr; } /* This function is called once all the normal packet bytes have been received. */ LOCALPROC rx_complete(void) { if (SCC.a[1].EndOfFrame) { ReportAbnormalID(0x0702, "EndOfFrame true in rx_complete"); } if (! SCC.a[1].RxChrAvail) { ReportAbnormalID(0x0703, "RxChrAvail false in rx_complete"); } if (SCC.a[1].SyncHunt) { ReportAbnormalID(0x0704, "SyncHunt true in rx_complete"); } /* Need to wait for rx_eof_pending (end of frame) to clear before preparing the next packet for receive. */ LT_RxBuffer = nullpr; SCC.a[1].EndOfFrame = trueblnr; } LOCALPROC SCC_RxBuffAdvance(void) { ui3r value; /* From the manual: "If status is checked, it must be done before the data is read, because the act of reading the data pops both the data and error FIFOs." */ if (nullpr == LT_RxBuffer) { value = 0x7E; SCC.a[1].RxChrAvail = falseblnr; } else { if (rx_data_offset < LT_RxBuffSz) { value = LT_RxBuffer[rx_data_offset]; } else { ui5r i = rx_data_offset - LT_RxBuffSz; /* if i==0 in first byte of CRC, have not got EOF yet */ if (i == 1) { rx_complete(); } value = 0; } ++rx_data_offset; } SCC.a[1].RxBuff = value; } /* LLAP/SDLC address */ LOCALVAR ui3b my_node_address = 0; LOCALPROC GetNextPacketForMe(void) { unsigned char dst; unsigned char src; label_retry: LT_ReceivePacket(); if (nullpr != LT_RxBuffer) { #if SCC_dolog dbglog_WriteNote("SCC receiving packet from BPF"); #endif /* Is this packet destined for me? */ dst = LT_RxBuffer[0]; src = LT_RxBuffer[1]; if (src == my_node_address) { #if SCC_dolog dbglog_WriteNote("SCC ignore packet from myself"); #endif LT_RxBuffer = nullpr; goto label_retry; } else if ((dst == my_node_address) || (dst == 0xFF) || ! SCC.a[1].AddrSrchMd) { /* ok */ } else { #if SCC_dolog dbglog_WriteNote("SCC ignore packet not for me"); #endif LT_RxBuffer = nullpr; goto label_retry; } } } /* External function, called periodically, to poll for any new LTOE packets. Any new packets are queued into the packet receipt queue. */ GLOBALPROC LocalTalkTick(void) { if (SCC.a[1].RxEnable && (! SCC.a[1].RxChrAvail)) { if (nullpr != LT_RxBuffer) { #if SCC_dolog dbglog_WriteNote("SCC recover abandoned packet"); #endif } else { if (CTSpacketPending) { GetCTSpacket(); } else { GetNextPacketForMe(); } } if (nullpr != LT_RxBuffer) { rx_data_offset = 0; SCC.a[1].EndOfFrame = falseblnr; SCC.a[1].RxChrAvail = trueblnr; SCC.a[1].SyncHunt = falseblnr; SCC_RxBuffAdvance(); /* We can update the rx interrupt if enabled */ CheckSCCInterruptFlag(); } } } #endif #if 0 LOCALPROC SCC_Interrupt(int Type) { if (SCC.MIE) { /* Master Interrupt Enable */ if (Type > SCC.SCC_Interrupt_Type) { SCC.SCC_Interrupt_Type = Type; } CheckSCCInterruptFlag(); } } #endif #if 0 LOCALPROC SCC_Int(void) { /* This should be called at regular intervals */ /* Turn off Sync/Hunt Mode */ if (SCC.a[0].SyncHunt) { SCC.a[0].SyncHunt = falseblnr; #ifdef _SCC_Debug2 vMac_Message("SCC_Int: Disable Sync/Hunt on A"); #endif #if 0 /* SyncHuntIE usually false */ if (SCC.a[0].SyncHuntIE) { SCC_Interrupt(SCC_A_Ext); } #endif } if (SCC.a[1].SyncHunt) { SCC.a[1].SyncHunt = falseblnr; #ifdef _SCC_Debug2 vMac_Message("SCC_Int: Disable Sync/Hunt on B"); #endif #if 0 /* SyncHuntIE usually false */ if (SCC.a[1].SyncHuntIE) { SCC_Interrupt(SCC_B_Ext); } #endif } #if 0 /* Check for incoming data */ if (ModemPort) { if (! SCC.a[0].RxEnable) { /* Rx Disabled */ ReadModem = 0; } if ((ModemBytes > 0) && (ModemCount > ModemBytes - 1)) { SCC.a[0].RxChrAvail = falseblnr; ReadModem = ModemBytes = ModemCount = 0; } if (ReadModem) { ReadModem = 2; SCC.a[0].RxChrAvail = trueblnr; if (SCC.a[0].WR[0] & Bit5 && ! (SCC.a[0].WR[0] & (Bit4 | Bit3))) { /* Int on next Rx char */ SCC_Interrupt(SCC_A_Rx); } else if (SCC.a[0].WR[1] & Bit3 && ! (SCC.a[0].WR[1] & Bit4)) { /* Int on first Rx char */ SCC_Interrupt(SCC_A_Rx); } else if (SCC.a[0].WR[1] & Bit4 && ! (SCC.a[0].WR[1] & Bit3)) { /* Int on all Rx chars */ SCC_Interrupt(SCC_A_Rx); } } } if (PrintPort) { if (! SCC.a[1].RxEnable) { /* Rx Disabled */ ReadPrint = 0; } if ((PrintBytes > 0) && (PrintCount > PrintBytes - 1)) { SCC.a[1].RxChrAvail = falseblnr; ReadPrint = PrintBytes = PrintCount = 0; } if (ReadPrint) { ReadPrint = 2; SCC.a[1].RxChrAvail = trueblnr; if (SCC.a[1].WR[0] & Bit5 && ! (SCC.a[1].WR[0] & (Bit4 | Bit3))) { /* Int on next Rx char */ SCC_Interrupt(SCC_B_Rx); } else if (SCC.a[1].WR[1] & Bit3 && ! (SCC.a[1].WR[1] & Bit4)) { /* Int on first Rx char */ SCC_Interrupt(SCC_B_Rx); } else if (SCC.a[1].WR[1] & Bit4 && ! (SCC.a[1].WR[1] & Bit3)) { /* Int on all Rx chars */ SCC_Interrupt(SCC_B_Rx); } } } #endif } #endif #if SCC_dolog LOCALPROC SCC_DbgLogChanStartLine(int chan) { dbglog_StartLine(); dbglog_writeCStr("SCC chan("); if (chan) { dbglog_writeCStr("B"); } else { dbglog_writeCStr("A"); } /* dbglog_writeHex(chan); */ dbglog_writeCStr(")"); } #endif LOCALFUNC ui3r SCC_GetRR0(int chan) { /* happens on boot always */ return 0 #if 0 /* BreakAbort always false */ | (SCC.a[chan].BreakAbort ? (1 << 7) : 0) #endif | (SCC.a[chan].TxUnderrun ? (1 << 6) : 0) #if 0 /* CTS always false */ | (SCC.a[chan].CTS ? (1 << 5) : 0) #endif | (SCC.a[chan].SyncHunt ? (1 << 4) : 0) #if 0 /* DCD always false */ | (SCC.a[chan].DCD ? (1 << 3) : 0) #endif #if EmLocalTalk | (SCC.a[chan].TxBufferEmpty ? (1 << 2) : 0) #else /* otherwise TxBufferEmpty always true */ | (1 << 2) #endif #if 0 /* ZeroCount always false */ | (SCC.a[chan].ZeroCount ? (1 << 1) : 0) #endif #if EmLocalTalk /* otherwise RxChrAvail always false */ | (SCC.a[chan].RxChrAvail ? (1 << 0) : 0) #endif ; } LOCALFUNC ui3r SCC_GetRR1(int chan) { /* happens in MacCheck */ ui3r value; #if ! EmLocalTalk UnusedParam(chan); #endif value = Bit2 | Bit1 #if 0 /* AllSent always true */ | (SCC.a[chan].AllSent ? (1 << 0) : 0) #else | Bit0 #endif #if 0 /* ParityErr always false */ | (SCC.a[chan].ParityErr ? (1 << 4) : 0) #endif #if 0 /* RxOverrun always false */ | (SCC.a[chan].RxOverrun ? (1 << 5) : 0) #endif #if 0 /* CRCFramingErr always false */ | (SCC.a[chan].CRCFramingErr ? (1 << 6) : 0) #endif #if EmLocalTalk /* otherwise EndOfFrame always false */ | (SCC.a[chan].EndOfFrame ? (1 << 7) : 0) #endif ; return value; } LOCALFUNC ui3r SCC_GetRR2(int chan) { /* happens in MacCheck */ /* happens in Print to ImageWriter */ ui3r value = SCC.InterruptVector; if (chan != 0) { /* B Channel */ #if 0 /* StatusHiLo always false */ if (SCC.StatusHiLo) { /* Status High */ value = value & (Bit0 | Bit1 | Bit2 | Bit3 | Bit7); ReportAbnormalID(0x0705, "Status high/low"); switch (SCC.SCC_Interrupt_Type) { case SCC_A_Rx: value |= Bit4 | Bit5; break; case SCC_A_Rx_Spec: value |= Bit4 | Bit5 | Bit6; break; case SCC_A_Tx_Empty: value |= Bit4; break; case SCC_A_Ext: value |= Bit4 | Bit6; break; case SCC_B_Rx: value |= Bit5; break; case SCC_B_Rx_Spec: value |= Bit5 | Bit6; break; case SCC_B_Tx_Empty: value |= 0; break; case SCC_B_Ext: value |= Bit6; break; default: value |= Bit5 | Bit6; break; } } else #endif { /* Status Low */ value = value & (Bit0 | Bit4 | Bit5 | Bit6 | Bit7); switch (SCC.SCC_Interrupt_Type) { case SCC_A_Rx: value |= Bit3 | Bit2; break; case SCC_A_Rx_Spec: value |= Bit3 | Bit2 | Bit1; break; case SCC_A_Tx_Empty: value |= Bit3; break; case SCC_A_Ext: value |= Bit3 | Bit1; break; case SCC_B_Rx: value |= Bit2; break; case SCC_B_Rx_Spec: value |= Bit2 | Bit1; break; case SCC_B_Tx_Empty: value |= 0; break; case SCC_B_Ext: value |= Bit1; break; default: value |= Bit2 | Bit1; break; } } /* SCC.SCC_Interrupt_Type = 0; */ } return value; } LOCALFUNC ui3r SCC_GetRR3(int chan) { ui3r value = 0; UnusedParam(chan); ReportAbnormalID(0x0706, "RR 3"); #if 0 if (chan == 0) { value = 0 | (SCC.a[1].TxIP ? (1 << 1) : 0) | (SCC.a[0].TxIP ? (1 << 4) : 0) ; } else { value = 0; } #endif return value; } LOCALFUNC ui3r SCC_GetRR8(int chan) { ui3r value = 0; /* Receive Buffer */ /* happens on boot with appletalk on */ if (SCC.a[chan].RxEnable) { #if EmLocalTalk if (0 != chan) { /* Check the receive state, handling a complete rx if necessary */ value = SCC.a[1].RxBuff; SCC.a[1].FirstChar = falseblnr; SCC_RxBuffAdvance(); } else { value = 0x7E; } #else /* Rx Enable */ #if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx) /* don't report */ #else ReportAbnormalID(0x0707, "read rr8 when RxEnable"); #endif /* Input 1 byte from Modem Port/Printer into Data */ #endif } else { /* happens on boot with appletalk on */ } return value; } LOCALFUNC ui3r SCC_GetRR10(int chan) { /* happens on boot with appletalk on */ ui3r value = 0; UnusedParam(chan); #if 0 && EmLocalTalk value = 2; #endif return value; } LOCALFUNC ui3r SCC_GetRR12(int chan) { ui3r value = 0; #if ! SCC_TrackMore UnusedParam(chan); #endif ReportAbnormalID(0x0708, "RR 12"); #if SCC_TrackMore /* don't care about Baud */ value = SCC.a[chan].BaudLo; #endif return value; } LOCALFUNC ui3r SCC_GetRR13(int chan) { ui3r value = 0; #if ! SCC_TrackMore UnusedParam(chan); #endif ReportAbnormalID(0x0709, "RR 13"); #if SCC_TrackMore /* don't care about Baud */ value = SCC.a[chan].BaudHi; #endif return value; } LOCALFUNC ui3r SCC_GetRR15(int chan) { ui3r value = 0; UnusedParam(chan); ReportAbnormalID(0x070A, "RR 15"); #if 0 value = 0 #if 0 /* don't care about DCD_IE, always true */ | (SCC.a[chan].DCD_IE ? Bit3 : 0) #else | Bit3 #endif #if 0 /* SyncHuntIE usually false */ | (SCC.a[chan].SyncHuntIE ? Bit4 : 0) #endif #if SCC_TrackMore /* don't care about CTS_IE */ | (SCC.a[chan].CTS_IE ? Bit5 : 0) #endif #if SCC_TrackMore /* don't care about BreakAbortIE */ | (SCC.a[chan].BreakAbortIE ? Bit7 : 0) #endif ; #endif return value; } #if SCC_dolog LOCALPROC SCC_DbgLogChanCmnd(int chan, char *s) { SCC_DbgLogChanStartLine(chan); dbglog_writeCStr(" "); dbglog_writeCStr(s); dbglog_writeReturn(); } #endif #if SCC_dolog LOCALPROC SCC_DbgLogChanChngBit(int chan, char *s, blnr v) { SCC_DbgLogChanStartLine(chan); dbglog_writeCStr(" "); dbglog_writeCStr(s); dbglog_writeCStr(" <- "); if (v) { dbglog_writeCStr("1"); } else { dbglog_writeCStr("0"); } dbglog_writeReturn(); } #endif LOCALPROC SCC_PutWR0(ui3r Data, int chan) /* "CRC initialize, initialization commands for the various modes, Register Pointers" */ { switch ((Data >> 6) & 3) { case 1: ReportAbnormalID(0x070B, "Reset Rx CRC Checker"); break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Reset Tx CRC Generator"); #endif /* happens on boot with appletalk on */ break; case 3: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Reset Tx Underrun/EOM Latch"); #endif /* happens on boot with appletalk on */ #if EmLocalTalk /* This is the indication we are done transmitting data for the current packet. */ process_transmit(); #endif #if 0 /* It seems to work better without this */ if (SCC.a[chan].TxEnable) { /* Tx Enabled */ SCC.a[chan].TxUnderrun = falseblnr; if (SCC.a[chan].WR[10] & Bit2) { /* Abort/Flag on Underrun */ /* Send Abort */ SCC.a[chan].TxUnderrun = trueblnr; #if 0 /* TxBufferEmpty always true */ SCC.a[chan].TxBufferEmpty = trueblnr; #endif /* Send Flag */ } } #endif break; case 0: default: /* Null Code */ break; } SCC.PointerBits = Data & 0x07; switch ((Data >> 3) & 7) { case 1: /* Point High */ SCC.PointerBits |= 8; break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Reset Ext/Status Ints"); #endif /* happens on boot always */ SCC.a[chan].SyncHunt = falseblnr; #if 0 /* only in sync mode */ SCC.a[chan].TxUnderrun = falseblnr; #endif #if 0 /* ZeroCount always false */ SCC.a[chan].ZeroCount = falseblnr; #endif #if 0 /* BreakAbort always false */ SCC.a[chan].BreakAbort = falseblnr; #endif break; case 3: ReportAbnormalID(0x070C, "Send Abort (SDLC)"); #if EmLocalTalk SCC.a[chan].TxBufferEmpty = trueblnr; #endif #if 0 SCC.a[chan].TxUnderrun = trueblnr; #if 0 /* TxBufferEmpty always true */ SCC.a[chan].TxBufferEmpty = trueblnr; #endif #endif break; case 4: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Enable Int on next Rx char"); #endif #if EmLocalTalk || SCC_TrackMore SCC.a[chan].FirstChar = trueblnr; #endif /* happens in MacCheck */ break; case 5: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Reset Tx Int Pending"); #endif /* happens in MacCheck */ /* happens in Print to ImageWriter */ SCC.a[chan].TxIP = falseblnr; CheckSCCInterruptFlag(); break; case 6: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Error Reset"); #endif /* happens on boot with appletalk on */ #if EmLocalTalk SCC.a[chan].EndOfFrame = falseblnr; #endif #if 0 /* ParityErr always false */ SCC.a[chan].ParityErr = falseblnr; #endif #if 0 /* RxOverrun always false */ SCC.a[chan].RxOverrun = falseblnr; #endif #if 0 /* CRCFramingErr always false */ SCC.a[chan].CRCFramingErr = falseblnr; #endif break; case 7: /* happens in "Network Watch" program (Cayman Systems) */ #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Reset Highest IUS"); #endif break; case 0: default: /* Null Code */ break; } } LOCALPROC SCC_PutWR1(ui3r Data, int chan) /* "Transmit/Receive interrupt and data transfer mode definition" */ { #if EmLocalTalk || SCC_TrackMore { blnr NewExtIE = (Data & Bit0) != 0; if (SCC.a[chan].ExtIE != NewExtIE) { SCC.a[chan].ExtIE = NewExtIE; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "EXT INT Enable", NewExtIE); #endif /* set to 1 on start up, set to 0 in MacCheck and in Print to ImageWriter */ } } #endif { blnr NewTxIE = (Data & Bit1) != 0; if (SCC.a[chan].TxIE != NewTxIE) { #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Tx Int Enable", NewTxIE); #endif /* happens in MacCheck */ /* happens in Print to ImageWriter */ SCC.a[chan].TxIE = NewTxIE; CheckSCCInterruptFlag(); } } #if SCC_TrackMore { blnr NewPrtySpclCond = (Data & Bit2) != 0; if (SCC.a[chan].PrtySpclCond != NewPrtySpclCond) { SCC.a[chan].PrtySpclCond = NewPrtySpclCond; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Parity is special condition", NewPrtySpclCond); #endif /* set to 1 in MacCheck and in Print to ImageWriter */ } } #endif #if EmLocalTalk || SCC_TrackMore { ui3r NewRxIntMode = (Data >> 3) & 3; if (SCC.a[chan].RxIntMode != NewRxIntMode) { SCC.a[chan].RxIntMode = NewRxIntMode; switch (NewRxIntMode) { case 0: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Rx INT Disable"); #endif /* happens on boot always */ break; case 1: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Rx INT on 1st char" " or special condition"); #endif SCC.a[chan].FirstChar = trueblnr; /* happens on boot with appletalk on */ break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "INT on all Rx char" " or special condition"); #endif /* happens in MacCheck */ /* happens in Print to ImageWriter */ break; case 3: ReportAbnormalID(0x070D, "Rx INT on special condition only"); break; } } } #endif #if SCC_TrackMore { blnr NewWaitRqstRT = (Data & Bit5) != 0; if (SCC.a[chan].WaitRqstRT != NewWaitRqstRT) { SCC.a[chan].WaitRqstRT = NewWaitRqstRT; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Wait/DMA request on receive/transmit", NewWaitRqstRT); #endif /* happens in MacCheck */ } } #endif #if SCC_TrackMore { blnr NewWaitRqstSlct = (Data & Bit6) != 0; if (SCC.a[chan].WaitRqstSlct != NewWaitRqstSlct) { SCC.a[chan].WaitRqstSlct = NewWaitRqstSlct; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Wait/DMA request function", NewWaitRqstSlct); #endif /* happens in MacCheck */ } } #endif #if SCC_TrackMore { blnr NewWaitRqstEnbl = (Data & Bit7) != 0; if (SCC.a[chan].WaitRqstEnbl != NewWaitRqstEnbl) { SCC.a[chan].WaitRqstEnbl = NewWaitRqstEnbl; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Wait/DMA request enable", NewWaitRqstEnbl); #endif /* happens in MacCheck */ } } #endif } LOCALPROC SCC_PutWR2(ui3r Data, int chan) /* "Interrupt Vector (accessed through either channel)" */ { /* Only 1 interrupt vector for the SCC, which is stored in channels A and B. B is modified when read. */ /* happens on boot always */ #if ! SCC_dolog UnusedParam(chan); #endif if (SCC.InterruptVector != Data) { #if SCC_dolog SCC_DbgLogChanStartLine(chan); dbglog_writeCStr(" InterruptVector <- "); dbglog_writeHex(Data); dbglog_writeReturn(); #endif SCC.InterruptVector = Data; } if ((Data & Bit0) != 0) { /* interrupt vector 0 */ ReportAbnormalID(0x070E, "interrupt vector 0"); } if ((Data & Bit1) != 0) { /* interrupt vector 1 */ ReportAbnormalID(0x070F, "interrupt vector 1"); } if ((Data & Bit2) != 0) { /* interrupt vector 2 */ ReportAbnormalID(0x0710, "interrupt vector 2"); } if ((Data & Bit3) != 0) { /* interrupt vector 3 */ ReportAbnormalID(0x0711, "interrupt vector 3"); } if ((Data & Bit4) != 0) { /* interrupt vector 4 */ /* happens on boot with appletalk on */ } if ((Data & Bit5) != 0) { /* interrupt vector 5 */ /* happens on boot with appletalk on */ } if ((Data & Bit6) != 0) { /* interrupt vector 6 */ ReportAbnormalID(0x0712, "interrupt vector 6"); } if ((Data & Bit7) != 0) { /* interrupt vector 7 */ ReportAbnormalID(0x0713, "interrupt vector 7"); } } LOCALPROC SCC_PutWR3(ui3r Data, int chan) /* "Receive parameters and control" */ { #if SCC_TrackMore { ui3r NewRBitsPerChar = (Data >> 6) & 3; if (SCC.a[chan].RBitsPerChar != NewRBitsPerChar) { SCC.a[chan].RBitsPerChar = NewRBitsPerChar; switch (NewRBitsPerChar) { case 0: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Rx Bits/Character <- 5"); #endif break; case 1: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Rx Bits/Character <- 7"); #endif break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Rx Bits/Character <- 6"); #endif break; case 3: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Rx Bits/Character <- 8"); #endif break; } } } #endif if ((Data & Bit5) != 0) { /* Auto Enables */ /* use DCD input as receiver enable, and set RTS output when transmit buffer empty */ ReportAbnormalID(0x0714, "Auto Enables"); } if ((Data & Bit4) != 0) { /* Enter Hunt Mode */ #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Enter Hunt Mode"); #endif /* happens on boot with appletalk on */ if (! (SCC.a[chan].SyncHunt)) { SCC.a[chan].SyncHunt = trueblnr; #if 0 /* SyncHuntIE usually false */ if (SCC.a[chan].SyncHuntIE) { SCC_Interrupt((chan == 0) ? SCC_A_Ext : SCC_B_Ext); } #endif } } #if SCC_TrackMore { blnr NewRxCRCEnbl = (Data & Bit3) != 0; if (SCC.a[chan].RxCRCEnbl != NewRxCRCEnbl) { SCC.a[chan].RxCRCEnbl = NewRxCRCEnbl; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Rx CRC Enable", NewRxCRCEnbl); #endif /* happens on boot with appletalk on */ } } #endif #if EmLocalTalk || SCC_TrackMore { blnr NewAddrSrchMd = (Data & Bit2) != 0; if (SCC.a[chan].AddrSrchMd != NewAddrSrchMd) { SCC.a[chan].AddrSrchMd = NewAddrSrchMd; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Addr Search Mode (SDLC)", NewAddrSrchMd); #endif /* happens on boot with appletalk on */ } } #endif #if SCC_TrackMore { blnr NewSyncChrLdInhb = (Data & Bit1) != 0; if (SCC.a[chan].SyncChrLdInhb != NewSyncChrLdInhb) { SCC.a[chan].SyncChrLdInhb = NewSyncChrLdInhb; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Sync Char Load Inhibit", NewSyncChrLdInhb); #endif /* happens on boot with appletalk on */ } } #endif { blnr NewRxEnable = (Data & Bit0) != 0; if (SCC.a[chan].RxEnable != NewRxEnable) { SCC.a[chan].RxEnable = NewRxEnable; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Rx Enable", NewRxEnable); #endif /* true on boot with appletalk on */ /* true on Print to ImageWriter */ #if EmLocalTalk if (! NewRxEnable) { #if SCC_dolog if ((0 != chan) && (nullpr != LT_RxBuffer)) { dbglog_WriteNote("SCC abandon packet"); } #endif /* Go back into the idle state if we were waiting for EOF */ SCC.a[chan].EndOfFrame = falseblnr; SCC.a[chan].RxChrAvail = falseblnr; SCC.a[chan].SyncHunt = trueblnr; } else { /* look for a packet */ LocalTalkTick(); } #endif } } } LOCALPROC SCC_PutWR4(ui3r Data, int chan) /* "Transmit/Receive miscellaneous parameters and modes" */ { #if ! (EmLocalTalk || SCC_TrackMore) UnusedParam(Data); UnusedParam(chan); #endif #if SCC_TrackMore { blnr NewPrtyEnable = (Data & Bit0) != 0; if (SCC.a[chan].PrtyEnable != NewPrtyEnable) { SCC.a[chan].PrtyEnable = NewPrtyEnable; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Parity Enable", NewPrtyEnable); #endif } } #endif #if SCC_TrackMore { blnr NewPrtyEven = (Data & Bit1) != 0; if (SCC.a[chan].PrtyEven != NewPrtyEven) { SCC.a[chan].PrtyEven = NewPrtyEven; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Parity Enable", NewPrtyEven); #endif } } #endif #if SCC_TrackMore { ui3r NewStopBits = (Data >> 2) & 3; if (SCC.a[chan].StopBits != NewStopBits) { SCC.a[chan].StopBits = NewStopBits; /* SCC_SetStopBits(chan, NewStopBits); */ switch (NewStopBits) { case 0: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Sync Modes Enable"); #endif break; case 1: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "1 Stop Bit"); #endif break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "1 1/2 Stop Bits"); #endif break; case 3: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "2 Stop Bits"); #endif break; } } } #endif #if EmLocalTalk || SCC_TrackMore { ui3r NewSyncMode = (Data >> 4) & 3; if (SCC.a[chan].SyncMode != NewSyncMode) { SCC.a[chan].SyncMode = NewSyncMode; switch (NewSyncMode) { case 0: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "8 bit sync char"); #endif /* happens on boot always */ break; case 1: ReportAbnormalID(0x0715, "16 bit sync char"); break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "SDLC MODE"); #endif /* happens on boot with appletalk on */ #if EmLocalTalk SCC.a[chan].TxBufferEmpty = trueblnr; #endif break; case 3: ReportAbnormalID(0x0716, "External sync mode"); break; } } } #endif #if SCC_TrackMore { ui3r NewClockRate = (Data >> 6) & 3; if (SCC.a[chan].ClockRate != NewClockRate) { SCC.a[chan].ClockRate = NewClockRate; switch (NewClockRate) { case 0: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Clock Rate <- X1"); #endif /* happens on boot with appletalk on */ break; case 1: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Clock Rate <- X16"); #endif /* happens on boot always */ break; case 2: ReportAbnormalID(0x0717, "Clock Rate <- X32"); break; case 3: ReportAbnormalID(0x0718, "Clock Rate <- X64"); break; } } } #endif } LOCALPROC SCC_PutWR5(ui3r Data, int chan) /* "Transmit parameters and controls" */ { /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ #if SCC_TrackMore { blnr NewTxCRCEnbl = (Data & Bit0) != 0; if (SCC.a[chan].TxCRCEnbl != NewTxCRCEnbl) { SCC.a[chan].TxCRCEnbl = NewTxCRCEnbl; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Tx CRC Enable", NewTxCRCEnbl); #endif /* both values on boot with appletalk on */ } } #endif #if SCC_TrackMore { blnr NewRTSctrl = (Data & Bit1) != 0; if (SCC.a[chan].RTSctrl != NewRTSctrl) { SCC.a[chan].RTSctrl = NewRTSctrl; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "RTS Control", NewRTSctrl); #endif /* both values on boot with appletalk on */ /* value of Request To Send output pin, when Auto Enable is off */ } } #endif if ((Data & Bit2) != 0) { /* SDLC/CRC-16 */ ReportAbnormalID(0x0719, "SDLC/CRC-16"); } { blnr NewTxEnable = (Data & Bit3) != 0; if (SCC.a[chan].TxEnable != NewTxEnable) { SCC.a[chan].TxEnable = NewTxEnable; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Tx Enable", NewTxEnable); #endif if (NewTxEnable) { /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ #if EmLocalTalk LT_TxBuffSz = 0; #endif } else { #if EmLocalTalk SCC.a[chan].TxBufferEmpty = trueblnr; #endif } } } #if SCC_TrackMore { blnr NewSndBrkCtrl = (Data & Bit4) != 0; if (SCC.a[chan].SndBrkCtrl != NewSndBrkCtrl) { SCC.a[chan].SndBrkCtrl = NewSndBrkCtrl; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Send Break Control", NewSndBrkCtrl); #endif /* true in Print to LaserWriter 300 */ } } #endif #if SCC_TrackMore { ui3r NewTBitsPerChar = (Data >> 5) & 3; if (SCC.a[chan].TBitsPerChar != NewTBitsPerChar) { SCC.a[chan].TBitsPerChar = NewTBitsPerChar; switch (NewTBitsPerChar) { case 0: ReportAbnormalID(0x071A, "Tx Bits/Character <- 5"); break; case 1: ReportAbnormalID(0x071B, "Tx Bits/Character <- 7"); break; case 2: ReportAbnormalID(0x071C, "Tx Bits/Character <- 6"); break; case 3: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Tx Bits/Character <- 8"); #endif /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ break; } } } #endif #if SCC_TrackMore { blnr NewDTRctrl = (Data & Bit7) != 0; if (SCC.a[chan].DTRctrl != NewDTRctrl) { SCC.a[chan].DTRctrl = NewDTRctrl; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "Data Terminal Ready Control", NewDTRctrl); #endif /* zero happens in MacCheck */ /* value of Data Terminal Ready output pin, when WR14 D2 = 0 (DTR/request function) */ } } #endif } LOCALPROC SCC_PutWR6(ui3r Data, int chan) /* "Sync characters or SDLC address field" */ { /* happens on boot with appletalk on */ #if ! (EmLocalTalk || SCC_dolog) UnusedParam(Data); #endif #if ! SCC_dolog UnusedParam(chan); #endif #if SCC_dolog SCC_DbgLogChanStartLine(chan); dbglog_writeCStr(" Sync Char <- "); dbglog_writeHex(Data); dbglog_writeReturn(); #endif #if EmLocalTalk if (0 != Data) { my_node_address = Data; } #endif } LOCALPROC SCC_PutWR7(ui3r Data, int chan) /* "Sync character or SDLC flag" */ { /* happens on boot with appletalk on */ #if ! SCC_TrackMore UnusedParam(Data); UnusedParam(chan); #endif #if SCC_TrackMore if (2 == SCC.a[chan].SyncMode) { if (0x7E != Data) { ReportAbnormalID(0x071D, "unexpect flag character for SDLC"); } } else { ReportAbnormalID(0x071E, "WR7 and not SDLC"); } #endif } LOCALPROC SCC_PutWR8(ui3r Data, int chan) /* "Transmit Buffer" */ { /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ #if ! (EmLocalTalk || SCC_dolog) UnusedParam(Data); #endif #if SCC_dolog SCC_DbgLogChanStartLine(chan); dbglog_writeCStr(" Transmit Buffer"); dbglog_writeCStr(" <- "); dbglog_writeHex(Data); dbglog_writeCStr(" '"); dbglog_writeMacChar(Data); dbglog_writeCStr("'"); dbglog_writeReturn(); #endif if (SCC.a[chan].TxEnable) { /* Tx Enable */ /* Output (Data) to Modem(B) or Printer(A) Port */ /* happens on boot with appletalk on */ #if EmLocalTalk if (chan != 0) { SCC_TxBuffPut(Data); } #else #if 0 /* TxBufferEmpty always true */ SCC.a[chan].TxBufferEmpty = trueblnr; #endif SCC.a[chan].TxUnderrun = trueblnr; /* underrun ? */ #endif SCC.a[chan].TxIP = trueblnr; CheckSCCInterruptFlag(); } else { ReportAbnormalID(0x071F, "write when Transmit Buffer not Enabled"); #if 0 /* TxBufferEmpty always true */ SCC.a[chan].TxBufferEmpty = falseblnr; #endif } } LOCALPROC SCC_PutWR9(ui3r Data, int chan) /* "Master interrupt control and reset (accessed through either channel)" */ { /* Only 1 WR9 in the SCC */ UnusedParam(chan); if ((Data & Bit0) != 0) { /* VIS */ ReportAbnormalID(0x0720, "VIS"); } #if SCC_TrackMore { blnr NewNoVectorSlct = (Data & Bit1) != 0; if (SCC.NoVectorSlct != NewNoVectorSlct) { SCC.NoVectorSlct = NewNoVectorSlct; #if SCC_dolog dbglog_WriteSetBool("SCC No Vector select", NewNoVectorSlct); #endif /* has both values on boot always */ } } #endif if ((Data & Bit2) != 0) { /* DLC */ ReportAbnormalID(0x0723, "DLC"); } { blnr NewMIE = (Data & Bit3) != 0; /* has both values on boot always */ if (SCC.MIE != NewMIE) { SCC.MIE = NewMIE; #if SCC_dolog dbglog_WriteSetBool("SCC Master Interrupt Enable", NewMIE); #endif CheckSCCInterruptFlag(); } } #if 0 /* StatusHiLo always false */ SCC.StatusHiLo = (Data & Bit4) != 0; #else if ((Data & Bit4) != 0) { /* Status high/low */ ReportAbnormalID(0x0724, "Status high/low"); } #endif if ((Data & Bit5) != 0) { /* WR9 b5 should be 0 */ ReportAbnormalID(0x0725, "WR9 b5 should be 0"); } switch ((Data >> 6) & 3) { case 1: #if SCC_dolog SCC_DbgLogChanCmnd(1, "Channel Reset"); #endif /* happens on boot always */ SCC_ResetChannel(1); CheckSCCInterruptFlag(); break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(0, "Channel Reset"); #endif /* happens on boot always */ SCC_ResetChannel(0); CheckSCCInterruptFlag(); break; case 3: #if SCC_dolog dbglog_WriteNote("SCC Force Hardware Reset"); #endif #if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx) /* don't report */ #else ReportAbnormalID(0x0726, "SCC_Reset"); #endif SCC_Reset(); CheckSCCInterruptFlag(); break; case 0: /* No Reset */ default: break; } } LOCALPROC SCC_PutWR10(ui3r Data, int chan) /* "Miscellaneous transmitter/receiver control bits" */ { /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ #if ! SCC_TrackMore UnusedParam(chan); #endif if ((Data & Bit0) != 0) { /* 6 bit/8 bit sync */ ReportAbnormalID(0x0727, "6 bit/8 bit sync"); } if ((Data & Bit1) != 0) { /* loop mode */ ReportAbnormalID(0x0728, "loop mode"); } if ((Data & Bit2) != 0) { /* abort/flag on underrun */ ReportAbnormalID(0x0729, "abort/flag on underrun"); } if ((Data & Bit3) != 0) { /* mark/flag idle */ ReportAbnormalID(0x072A, "mark/flag idle"); } if ((Data & Bit4) != 0) { /* go active on poll */ ReportAbnormalID(0x072B, "go active on poll"); } #if SCC_TrackMore { ui3r NewDataEncoding = (Data >> 5) & 3; if (SCC.a[chan].DataEncoding != NewDataEncoding) { SCC.a[chan].DataEncoding = NewDataEncoding; switch (NewDataEncoding) { case 0: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Data Encoding <- NRZ"); #endif /* happens in MacCheck */ /* happens in Print to ImageWriter */ break; case 1: ReportAbnormalID(0x072C, "Data Encoding <- NRZI"); break; case 2: ReportAbnormalID(0x072D, "Data Encoding <- FM1"); break; case 3: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "Data Encoding <- FM0"); #endif /* happens on boot with appletalk on */ break; } } } #endif #if SCC_TrackMore { blnr NewCRCPreset = (Data & Bit7) != 0; if (SCC.a[chan].CRCPreset != NewCRCPreset) { SCC.a[chan].CRCPreset = NewCRCPreset; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "CRC preset I/O", NewCRCPreset); #endif /* false happens in MacCheck */ /* true happens in Print to ImageWriter */ } } #endif } LOCALPROC SCC_PutWR11(ui3r Data, int chan) /* "Clock mode control" */ { /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ /* happens in MacCheck */ #if ! SCC_TrackMore UnusedParam(chan); #endif #if SCC_TrackMore /* Transmit External Control Selection */ { ui3r NewTRxCsrc = Data & 3; if (SCC.a[chan].TRxCsrc != NewTRxCsrc) { SCC.a[chan].TRxCsrc = NewTRxCsrc; switch (NewTRxCsrc) { case 0: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "TRxC OUT = XTAL output"); #endif /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ /* happens in MacCheck */ break; case 1: ReportAbnormalID(0x072E, "TRxC OUT = transmit clock"); break; case 2: ReportAbnormalID(0x072F, "TRxC OUT = BR generator output"); break; case 3: ReportAbnormalID(0x0730, "TRxC OUT = dpll output"); break; } } } #endif if ((Data & Bit2) != 0) { ReportAbnormalID(0x0731, "TRxC O/I"); } #if SCC_TrackMore { ui3r NewTClkSlct = (Data >> 3) & 3; if (SCC.a[chan].TClkSlct != NewTClkSlct) { SCC.a[chan].TClkSlct = NewTClkSlct; switch (NewTClkSlct) { case 0: ReportAbnormalID(0x0732, "transmit clock = RTxC pin"); break; case 1: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "transmit clock = TRxC pin"); #endif /* happens in Print to LaserWriter 300 */ break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "transmit clock = BR generator output"); #endif /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ /* happens in MacCheck */ break; case 3: ReportAbnormalID(0x0733, "transmit clock = dpll output"); break; } } } #endif #if SCC_TrackMore { ui3r NewRClkSlct = (Data >> 5) & 3; if (SCC.a[chan].RClkSlct != NewRClkSlct) { SCC.a[chan].RClkSlct = NewRClkSlct; switch (NewRClkSlct) { case 0: ReportAbnormalID(0x0734, "receive clock = RTxC pin"); break; case 1: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "receive clock = TRxC pin"); #endif /* happens in Print to LaserWriter 300 */ break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "receive clock = BR generator output"); #endif /* happens in MacCheck */ /* happens in Print to ImageWriter */ break; case 3: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "receive clock = dpll output"); #endif /* happens on boot with appletalk on */ break; } } } #endif if ((Data & Bit7) != 0) { ReportAbnormalID(0x0735, "RTxC XTAL/NO XTAL"); } } LOCALPROC SCC_PutWR12(ui3r Data, int chan) /* "Lower byte of baud rate generator time constant" */ { /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ #if ! SCC_TrackMore UnusedParam(Data); UnusedParam(chan); #endif #if SCC_TrackMore /* don't care about Baud */ if (SCC.a[chan].BaudLo != Data) { SCC.a[chan].BaudLo = Data; #if SCC_dolog SCC_DbgLogChanStartLine(chan); dbglog_writeCStr(" BaudLo <- "); dbglog_writeHex(Data); dbglog_writeReturn(); #endif } #endif #if 0 SCC_SetBaud(chan, SCC.a[chan].BaudLo + (SCC.a[chan].BaudHi << 8)); /* 380: BaudRate = 300 */ /* 94: BaudRate = 1200 */ /* 46: BaudRate = 2400 */ /* 22: BaudRate = 4800 */ /* 10: BaudRate = 9600 */ /* 4: BaudRate = 19200 */ /* 1: BaudRate = 38400 */ /* 0: BaudRate = 57600 */ #endif } LOCALPROC SCC_PutWR13(ui3r Data, int chan) /* "Upper byte of baud rate generator time constant" */ { /* happens on boot with appletalk on */ /* happens in Print to ImageWriter */ #if ! SCC_TrackMore UnusedParam(Data); UnusedParam(chan); #endif #if SCC_TrackMore /* don't care about Baud */ if (SCC.a[chan].BaudHi != Data) { SCC.a[chan].BaudHi = Data; #if SCC_dolog SCC_DbgLogChanStartLine(chan); dbglog_writeCStr(" BaudHi <- "); dbglog_writeHex(Data); dbglog_writeReturn(); #endif } #endif #if 0 SCC_SetBaud(chan, SCC.a[chan].BaudLo + (SCC.a[chan].BaudHi << 8)); #endif } LOCALPROC SCC_PutWR14(ui3r Data, int chan) /* "Miscellaneous control bits" */ { /* happens on boot with appletalk on */ #if ! (SCC_TrackMore || SCC_dolog) UnusedParam(chan); #endif #if SCC_TrackMore { blnr NewBRGEnbl = (Data & Bit0) != 0; if (SCC.a[chan].BRGEnbl != NewBRGEnbl) { SCC.a[chan].BRGEnbl = NewBRGEnbl; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "BR generator enable", NewBRGEnbl); #endif /* both values on boot with appletalk on */ /* true happens in Print to ImageWriter */ } } #endif if ((Data & Bit1) != 0) { /* BR generator source */ ReportAbnormalID(0x0736, "BR generator source"); } if ((Data & Bit2) != 0) { /* DTR/request function */ ReportAbnormalID(0x0737, "DTR/request function"); } if ((Data & Bit3) != 0) { /* auto echo */ ReportAbnormalID(0x0738, "auto echo"); } if ((Data & Bit4) != 0) { /* local loopback */ ReportAbnormalID(0x0739, "local loopback"); } switch ((Data >> 5) & 7) { case 1: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "enter search mode"); #endif /* happens on boot with appletalk on */ break; case 2: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "reset missing clock"); #endif /* happens on boot with appletalk on */ /* should clear Bit 6 and Bit 7 of RR[10], but since these are never set, don't need to do anything */ break; case 3: ReportAbnormalID(0x073A, "disable dpll"); /* should clear Bit 6 and Bit 7 of RR[10], but since these are never set, don't need to do anything */ break; case 4: ReportAbnormalID(0x073B, "set source = br generator"); break; case 5: ReportAbnormalID(0x073C, "set source = RTxC"); break; case 6: #if SCC_dolog SCC_DbgLogChanCmnd(chan, "set FM mode"); #endif /* happens on boot with appletalk on */ break; case 7: ReportAbnormalID(0x073D, "set NRZI mode"); break; case 0: /* No Reset */ default: break; } } LOCALPROC SCC_PutWR15(ui3r Data, int chan) /* "External/Status interrupt control" */ { /* happens on boot always */ #if ! SCC_TrackMore UnusedParam(chan); #endif if ((Data & Bit0) != 0) { /* WR15 b0 should be 0 */ ReportAbnormalID(0x073E, "WR15 b0 should be 0"); } if ((Data & Bit1) != 0) { /* zero count IE */ ReportAbnormalID(0x073F, "zero count IE"); } if ((Data & Bit2) != 0) { /* WR15 b2 should be 0 */ ReportAbnormalID(0x0740, "WR15 b2 should be 0"); } #if 0 /* don't care about DCD_IE, always true */ SCC.a[chan].DCD_IE = (Data & Bit3) != 0; #else if ((Data & Bit3) == 0) { /* DCD_IE */ #if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx) /* don't report */ #else ReportAbnormalID(0x0741, "not DCD IE"); #endif } #endif #if 0 /* SyncHuntIE usually false */ SCC.a[chan].SyncHuntIE = (Data & Bit4) != 0; #else if ((Data & Bit4) != 0) { /* SYNC/HUNT IE */ ReportAbnormalID(0x0742, "SYNC/HUNT IE"); } #endif #if SCC_TrackMore /* don't care about CTS_IE */ { blnr NewCTS_IE = (Data & Bit5) != 0; if (SCC.a[chan].CTS_IE != NewCTS_IE) { SCC.a[chan].CTS_IE = NewCTS_IE; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "CTS IE", NewCTS_IE); #endif /* happens in MacCheck */ /* happens in Print to ImageWriter */ } } #endif if ((Data & Bit6) != 0) { /* Tx underrun/EOM IE */ ReportAbnormalID(0x0743, "Tx underrun/EOM IE"); } #if SCC_TrackMore { blnr NewBreakAbortIE = (Data & Bit7) != 0; if (SCC.a[chan].BreakAbortIE != NewBreakAbortIE) { SCC.a[chan].BreakAbortIE = NewBreakAbortIE; #if SCC_dolog SCC_DbgLogChanChngBit(chan, "BreakAbort IE", NewBreakAbortIE); #endif /* happens in MacCheck */ /* happens in Print to ImageWriter */ } } #endif } LOCALFUNC ui3r SCC_GetReg(int chan, ui3r SCC_Reg) { ui3r value; switch (SCC_Reg) { case 0: value = SCC_GetRR0(chan); break; case 1: value = SCC_GetRR1(chan); break; case 2: value = SCC_GetRR2(chan); break; case 3: value = SCC_GetRR3(chan); break; case 4: ReportAbnormalID(0x0744, "RR 4"); /* same as RR0 */ value = SCC_GetRR0(chan); break; case 5: ReportAbnormalID(0x0745, "RR 5"); /* same as RR1 */ value = SCC_GetRR1(chan); break; case 6: ReportAbnormalID(0x0746, "RR 6"); /* same as RR2 */ value = SCC_GetRR2(chan); break; case 7: ReportAbnormalID(0x0747, "RR 7"); /* same as RR3 */ value = SCC_GetRR3(chan); break; case 8: value = SCC_GetRR8(chan); break; case 9: ReportAbnormalID(0x0748, "RR 9"); /* same as RR13 */ value = SCC_GetRR13(chan); break; case 10: value = SCC_GetRR10(chan); break; case 11: ReportAbnormalID(0x0749, "RR 11"); /* same as RR15 */ value = SCC_GetRR15(chan); break; case 12: value = SCC_GetRR12(chan); break; case 13: value = SCC_GetRR13(chan); break; case 14: ReportAbnormalID(0x074A, "RR 14"); value = 0; break; case 15: value = SCC_GetRR15(chan); break; default: ReportAbnormalID(0x074B, "unexpected SCC_Reg in SCC_GetReg"); value = 0; break; } #if EmLocalTalk /* Always check to see if interrupt state changed after ANY register access */ CheckSCCInterruptFlag(); #endif #if SCC_dolog SCC_DbgLogChanStartLine(chan); dbglog_writeCStr(" RR["); dbglog_writeHex(SCC_Reg); dbglog_writeCStr("] -> "); dbglog_writeHex(value); dbglog_writeReturn(); #endif return value; } LOCALPROC SCC_PutReg(ui3r Data, int chan, ui3r SCC_Reg) { #if SCC_dolog && 0 SCC_DbgLogChanStartLine(chan); dbglog_writeCStr(" WR["); dbglog_writeHex(SCC_Reg); dbglog_writeCStr("] <- "); dbglog_writeHex(Data); dbglog_writeReturn(); #endif switch (SCC_Reg) { case 0: SCC_PutWR0(Data, chan); break; case 1: SCC_PutWR1(Data, chan); break; case 2: SCC_PutWR2(Data, chan); break; case 3: SCC_PutWR3(Data, chan); break; case 4: SCC_PutWR4(Data, chan); break; case 5: SCC_PutWR5(Data, chan); break; case 6: SCC_PutWR6(Data, chan); break; case 7: SCC_PutWR7(Data, chan); break; case 8: SCC_PutWR8(Data, chan); break; case 9: SCC_PutWR9(Data, chan); break; case 10: SCC_PutWR10(Data, chan); break; case 11: SCC_PutWR11(Data, chan); break; case 12: SCC_PutWR12(Data, chan); break; case 13: SCC_PutWR13(Data, chan); break; case 14: SCC_PutWR14(Data, chan); break; case 15: SCC_PutWR15(Data, chan); break; default: ReportAbnormalID(0x074C, "unexpected SCC_Reg in SCC_PutReg"); break; } #if EmLocalTalk /* Always check to see if interrupt state changed after ANY register access */ CheckSCCInterruptFlag(); #endif } GLOBALFUNC ui5b SCC_Access(ui5b Data, blnr WriteMem, CPTR addr) { #if EmLocalTalk /* Determine channel, data, and access type from address. The bus for the 8350 is non-standard, so the Macintosh connects address bus lines to various signals on the 8350 as shown below. The 68K will use the upper byte of the data bus for odd addresses, and the 8350 is only wired to the upper byte, therefore use only odd addresses or you risk resetting the 8350. 68k 8350 ----- ------ a1 a/b a2 d/c a21 wr/rd */ #endif ui3b SCC_Reg; int chan = (~ addr) & 1; /* 0=modem, 1=printer */ if (((addr >> 1) & 1) == 0) { /* Channel Control */ SCC_Reg = SCC.PointerBits; SCC.PointerBits = 0; } else { /* Channel Data */ SCC_Reg = 8; } if (WriteMem) { SCC_PutReg(Data, chan, SCC_Reg); } else { Data = SCC_GetReg(chan, SCC_Reg); } return Data; } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SCCEMDEV.h b/Mini vMac/mnvm_core/SCCEMDEV.h index 271108d..aaeb59e 100755 --- a/Mini vMac/mnvm_core/SCCEMDEV.h +++ b/Mini vMac/mnvm_core/SCCEMDEV.h @@ -1,32 +1 @@ -/* - SCCEMDEV.h - - Copyright (C) 2004 Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef SCCEMDEV_H -#error "header already included" -#else -#define SCCEMDEV_H -#endif - -EXPORTPROC SCC_Reset(void); - -EXPORTFUNC ui5b SCC_Access(ui5b Data, blnr WriteMem, CPTR addr); - -EXPORTFUNC blnr SCC_InterruptsEnabled(void); - -#if EmLocalTalk -EXPORTPROC LocalTalkTick(void); -EXPORTFUNC int InitLocalTalk(void); -#endif +/* SCCEMDEV.h Copyright (C) 2004 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef SCCEMDEV_H #error "header already included" #else #define SCCEMDEV_H #endif EXPORTPROC SCC_Reset(void); EXPORTFUNC ui5b SCC_Access(ui5b Data, blnr WriteMem, CPTR addr); EXPORTFUNC blnr SCC_InterruptsEnabled(void); #if EmLocalTalk EXPORTPROC LocalTalkTick(void); EXPORTFUNC int InitLocalTalk(void); #endif \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SCRNEMDV.c b/Mini vMac/mnvm_core/SCRNEMDV.c index 29221ab..367201d 100755 --- a/Mini vMac/mnvm_core/SCRNEMDV.c +++ b/Mini vMac/mnvm_core/SCRNEMDV.c @@ -1,59 +1 @@ -/* - SCRNEMDV.c - - Copyright (C) 2006 Philip Cummins, Richard F. Bannister, - Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - SCReeN EMulated DeVice - - Emulation of the screen in the Mac Plus. - - This code descended from "Screen-MacOS.c" in Richard F. Bannister's - Macintosh port of vMac, by Philip Cummins. -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" -#include "MYOSGLUE.h" -#include "ENDIANAC.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" -#endif - -#include "SCRNEMDV.h" - -#if ! IncludeVidMem -#define kMain_Offset 0x5900 -#define kAlternate_Offset 0xD900 -#define kMain_Buffer (kRAM_Size - kMain_Offset) -#define kAlternate_Buffer (kRAM_Size - kAlternate_Offset) -#endif - -GLOBALPROC Screen_EndTickNotify(void) -{ - ui3p screencurrentbuff; - -#if IncludeVidMem - screencurrentbuff = VidMem; -#else - if (SCRNvPage2 == 1) { - screencurrentbuff = get_ram_address(kMain_Buffer); - } else { - screencurrentbuff = get_ram_address(kAlternate_Buffer); - } -#endif - - Screen_OutputFrame(screencurrentbuff); -} +/* SCRNEMDV.c Copyright (C) 2006 Philip Cummins, Richard F. Bannister, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* SCReeN EMulated DeVice Emulation of the screen in the Mac Plus. This code descended from "Screen-MacOS.c" in Richard F. Bannister's Macintosh port of vMac, by Philip Cummins. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "ENDIANAC.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif #include "SCRNEMDV.h" #if ! IncludeVidMem #define kMain_Offset 0x5900 #define kAlternate_Offset 0xD900 #define kMain_Buffer (kRAM_Size - kMain_Offset) #define kAlternate_Buffer (kRAM_Size - kAlternate_Offset) #endif GLOBALPROC Screen_EndTickNotify(void) { ui3p screencurrentbuff; #if IncludeVidMem screencurrentbuff = VidMem; #else if (SCRNvPage2 == 1) { screencurrentbuff = get_ram_address(kMain_Buffer); } else { screencurrentbuff = get_ram_address(kAlternate_Buffer); } #endif Screen_OutputFrame(screencurrentbuff); } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SCRNEMDV.h b/Mini vMac/mnvm_core/SCRNEMDV.h index 5d6be2b..f005f54 100755 --- a/Mini vMac/mnvm_core/SCRNEMDV.h +++ b/Mini vMac/mnvm_core/SCRNEMDV.h @@ -1,24 +1 @@ -/* - SCRNEMDV.h - - Copyright (C) 2006 Philip Cummins, Richard F. Bannister, - Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef SCRNEMDV_H -#error "header already included" -#else -#define SCRNEMDV_H -#endif - -EXPORTPROC Screen_EndTickNotify(void); +/* SCRNEMDV.h Copyright (C) 2006 Philip Cummins, Richard F. Bannister, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef SCRNEMDV_H #error "header already included" #else #define SCRNEMDV_H #endif EXPORTPROC Screen_EndTickNotify(void); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SCRNHACK.h b/Mini vMac/mnvm_core/SCRNHACK.h index c3445c2..951c42c 100755 --- a/Mini vMac/mnvm_core/SCRNHACK.h +++ b/Mini vMac/mnvm_core/SCRNHACK.h @@ -1,397 +1 @@ -/* - SCRNHACK.h - - Copyright (C) 2007 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - SCReeN Hack - - Patch ROM to support other screen sizes. -*/ - - -#if CurEmMd <= kEmMd_128K - do_put_mem_long(112 + ROM, kVidMem_Base); - do_put_mem_long(260 + ROM, kVidMem_Base); - do_put_mem_long(292 + ROM, kVidMem_Base - + (((vMacScreenHeight / 4) * 2 + 9) * vMacScreenWidth - + (vMacScreenWidth / 2 - 24)) - / 8); - - /* sad mac, error code */ - do_put_mem_word(330 + ROM, vMacScreenWidth / 8); - do_put_mem_word(342 + ROM, vMacScreenWidth / 8); - do_put_mem_word(350 + ROM, vMacScreenWidth / 4 * 3 - 1); - /* sad mac, blink pixels */ - do_put_mem_word(358 + ROM, vMacScreenWidth - 4); - - do_put_mem_word(456 + ROM, - (vMacScreenHeight * vMacScreenWidth / 32) - 1 + 32); - - /* screen setup, main */ - { - pto = 862 + ROM; - do_put_mem_word(pto, 0x4EB9); /* JSR */ - pto += 2; - do_put_mem_long(pto, kROM_Base + (patchp - ROM)); - pto += 4; - - do_put_mem_word(patchp, 0x21FC); /* MOVE.L */ - patchp += 2; - do_put_mem_long(patchp, kVidMem_Base); /* kVidMem_Base */ - patchp += 4; - do_put_mem_word(patchp, 0x0824); /* (ScrnBase) */ - patchp += 2; - do_put_mem_word(patchp, 0x4E75); /* RTS */ - patchp += 2; - } - do_put_mem_word(892 + ROM, vMacScreenHeight - 1); - do_put_mem_word(894 + ROM, vMacScreenWidth - 1); - - /* blink floppy, disk icon */ - do_put_mem_long(1388 + ROM, kVidMem_Base - + (((vMacScreenHeight / 4) * 2 - 25) * vMacScreenWidth - + (vMacScreenWidth / 2 - 16)) - / 8); - /* blink floppy, question mark */ - do_put_mem_long(1406 + ROM, kVidMem_Base - + (((vMacScreenHeight / 4) * 2 - 10) * vMacScreenWidth - + (vMacScreenWidth / 2 - 8)) - / 8); - - /* blink floppy and sadmac, position */ - do_put_mem_word(1966 + ROM, vMacScreenWidth / 8 - 4); - do_put_mem_word(1982 + ROM, vMacScreenWidth / 8); - /* sad mac, mac icon */ - do_put_mem_long(2008 + ROM, kVidMem_Base - + (((vMacScreenHeight / 4) * 2 - 25) * vMacScreenWidth - + (vMacScreenWidth / 2 - 16)) - / 8); - /* sad mac, frown */ - do_put_mem_long(2020 + ROM, kVidMem_Base - + (((vMacScreenHeight / 4) * 2 - 19) * vMacScreenWidth - + (vMacScreenWidth / 2 - 8)) - / 8); - do_put_mem_word(2052 + ROM, vMacScreenWidth / 8 - 2); - - /* cursor handling */ -#if vMacScreenWidth >= 1024 - pto = 3448 + ROM; - do_put_mem_word(pto, 0x4EB9); /* JSR */ - pto += 2; - do_put_mem_long(pto, kROM_Base + (patchp - ROM)); - pto += 4; - - do_put_mem_word(patchp, 0x41F8); /* Lea.L (CrsrSave),A0 */ - patchp += 2; - do_put_mem_word(patchp, 0x088C); - patchp += 2; - do_put_mem_word(patchp, 0x203C); /* MOVE.L #$x,D0 */ - patchp += 2; - do_put_mem_long(patchp, (vMacScreenWidth / 8)); - patchp += 4; - do_put_mem_word(patchp, 0x4E75); /* RTS */ - patchp += 2; -#else - do_put_mem_word(3452 + ROM, 0x7000 + (vMacScreenWidth / 8)); -#endif - do_put_mem_word(3572 + ROM, vMacScreenWidth - 32); - do_put_mem_word(3578 + ROM, vMacScreenWidth - 32); - do_put_mem_word(3610 + ROM, vMacScreenHeight - 16); - do_put_mem_word(3616 + ROM, vMacScreenHeight); -#if vMacScreenWidth >= 1024 - pto = 3646 + ROM; - do_put_mem_word(pto, 0x4EB9); /* JSR */ - pto += 2; - do_put_mem_long(pto, kROM_Base + (patchp - ROM)); - pto += 4; - - do_put_mem_word(patchp, 0x2A3C); /* MOVE.L #$x,D5 */ - patchp += 2; - do_put_mem_long(patchp, (vMacScreenWidth / 8)); - patchp += 4; - do_put_mem_word(patchp, 0xC2C5); /* MulU D5,D1 */ - patchp += 2; - do_put_mem_word(patchp, 0xD3C1); /* AddA.L D1,A1 */ - patchp += 2; - do_put_mem_word(patchp, 0x4E75); /* RTS */ - patchp += 2; -#else - do_put_mem_word(3646 + ROM, 0x7A00 + (vMacScreenWidth / 8)); -#endif - - /* set up screen bitmap */ - do_put_mem_word(3832 + ROM, vMacScreenHeight); - do_put_mem_word(3838 + ROM, vMacScreenWidth); - /* do_put_mem_word(7810 + ROM, vMacScreenHeight); */ - -#elif CurEmMd <= kEmMd_Plus - - do_put_mem_long(138 + ROM, kVidMem_Base); - do_put_mem_long(326 + ROM, kVidMem_Base); - do_put_mem_long(356 + ROM, kVidMem_Base - + (((vMacScreenHeight / 4) * 2 + 9) * vMacScreenWidth - + (vMacScreenWidth / 2 - 24)) - / 8); - - /* sad mac, error code */ - do_put_mem_word(392 + ROM, vMacScreenWidth / 8); - do_put_mem_word(404 + ROM, vMacScreenWidth / 8); - do_put_mem_word(412 + ROM, vMacScreenWidth / 4 * 3 - 1); - /* sad mac, blink pixels */ - do_put_mem_long(420 + ROM, kVidMem_Base - + (((vMacScreenHeight / 4) * 2 + 17) * vMacScreenWidth - + (vMacScreenWidth / 2 - 8)) - / 8); - - do_put_mem_word(494 + ROM, - (vMacScreenHeight * vMacScreenWidth / 32) - 1); - - /* screen setup, main */ - { - pto = 1132 + ROM; - do_put_mem_word(pto, 0x4EB9); /* JSR */ - pto += 2; - do_put_mem_long(pto, kROM_Base + (patchp - ROM)); - pto += 4; - - do_put_mem_word(patchp, 0x21FC); /* MOVE.L */ - patchp += 2; - do_put_mem_long(patchp, kVidMem_Base); /* kVidMem_Base */ - patchp += 4; - do_put_mem_word(patchp, 0x0824); /* (ScrnBase) */ - patchp += 2; - do_put_mem_word(patchp, 0x4E75); /* RTS */ - patchp += 2; - } - do_put_mem_word(1140 + ROM, vMacScreenWidth / 8); - do_put_mem_word(1172 + ROM, vMacScreenHeight); - do_put_mem_word(1176 + ROM, vMacScreenWidth); - - /* blink floppy, disk icon */ - do_put_mem_long(2016 + ROM, kVidMem_Base - + (((vMacScreenHeight / 4) * 2 - 25) * vMacScreenWidth - + (vMacScreenWidth / 2 - 16)) - / 8); - /* blink floppy, question mark */ - do_put_mem_long(2034 + ROM, kVidMem_Base - + (((vMacScreenHeight / 4) * 2 - 10) * vMacScreenWidth - + (vMacScreenWidth / 2 - 8)) - / 8); - - do_put_mem_word(2574 + ROM, vMacScreenHeight); - do_put_mem_word(2576 + ROM, vMacScreenWidth); - - /* blink floppy and sadmac, position */ - do_put_mem_word(3810 + ROM, vMacScreenWidth / 8 - 4); - do_put_mem_word(3826 + ROM, vMacScreenWidth / 8); - /* sad mac, mac icon */ - do_put_mem_long(3852 + ROM, kVidMem_Base - + (((vMacScreenHeight / 4) * 2 - 25) * vMacScreenWidth - + (vMacScreenWidth / 2 - 16)) - / 8); - /* sad mac, frown */ - do_put_mem_long(3864 + ROM, kVidMem_Base - + (((vMacScreenHeight / 4) * 2 - 19) * vMacScreenWidth - + (vMacScreenWidth / 2 - 8)) - / 8); - do_put_mem_word(3894 + ROM, vMacScreenWidth / 8 - 2); - - /* cursor handling */ -#if vMacScreenWidth >= 1024 - pto = 7372 + ROM; - do_put_mem_word(pto, 0x4EB9); /* JSR */ - pto += 2; - do_put_mem_long(pto, kROM_Base + (patchp - ROM)); - pto += 4; - - do_put_mem_word(patchp, 0x41F8); /* Lea.L (CrsrSave), A0 */ - patchp += 2; - do_put_mem_word(patchp, 0x088C); - patchp += 2; - do_put_mem_word(patchp, 0x203C); /* MOVE.L #$x, D0 */ - patchp += 2; - do_put_mem_long(patchp, (vMacScreenWidth / 8)); - patchp += 4; - do_put_mem_word(patchp, 0x4E75); /* RTS */ - patchp += 2; -#else - do_put_mem_word(7376 + ROM, 0x7000 + (vMacScreenWidth / 8)); -#endif - do_put_mem_word(7496 + ROM, vMacScreenWidth - 32); - do_put_mem_word(7502 + ROM, vMacScreenWidth - 32); - do_put_mem_word(7534 + ROM, vMacScreenHeight - 16); - do_put_mem_word(7540 + ROM, vMacScreenHeight); -#if vMacScreenWidth >= 1024 - pto = 7570 + ROM; - do_put_mem_word(pto, 0x4EB9); /* JSR */ - pto += 2; - do_put_mem_long(pto, kROM_Base + (patchp - ROM)); - pto += 4; - - do_put_mem_word(patchp, 0x2A3C); /* MOVE.L #$x,D5 */ - patchp += 2; - do_put_mem_long(patchp, (vMacScreenWidth / 8)); - patchp += 4; - do_put_mem_word(patchp, 0xC2C5); /* MulU D5,D1 */ - patchp += 2; - do_put_mem_word(patchp, 0xD3C1); /* AddA.L D1,A1 */ - patchp += 2; - do_put_mem_word(patchp, 0x4E75); /* RTS */ - patchp += 2; -#else - do_put_mem_word(7570 + ROM, 0x7A00 + (vMacScreenWidth / 8)); -#endif - - /* set up screen bitmap */ - do_put_mem_word(7784 + ROM, vMacScreenHeight); - do_put_mem_word(7790 + ROM, vMacScreenWidth); - do_put_mem_word(7810 + ROM, vMacScreenHeight); - -#if 0 - /* - Haven't got these working. Alert outlines ok, but - not contents. Perhaps global position of contents - stored in system resource file. - */ - - /* perhaps switch disk alert */ - do_put_mem_word(10936 + ROM, vMacScreenHeight / 2 - 91); - do_put_mem_word(10938 + ROM, vMacScreenWidth / 2 - 136); - do_put_mem_word(10944 + ROM, vMacScreenHeight / 2 - 19); - do_put_mem_word(10946 + ROM, vMacScreenWidth / 2 + 149); - - do_put_mem_word(11008 + ROM, ?); - do_put_mem_word(11010 + ROM, ?); - - /* DSAlertRect */ - do_put_mem_word(4952 + ROM, vMacScreenHeight / 2 - 107); - do_put_mem_word(4954 + ROM, vMacScreenWidth / 2 - 236); - do_put_mem_word(4958 + ROM, vMacScreenHeight / 2 + 19); - do_put_mem_word(4960 + ROM, vMacScreenWidth / 2 + 236); - - do_put_mem_word(5212 + ROM, vMacScreenHeight / 2 - 101); - do_put_mem_word(5214 + ROM, vMacScreenWidth / 2 - 218); -#endif - -#elif CurEmMd <= kEmMd_Classic - - /* screen setup, main */ - { - pto = 1482 + ROM; - do_put_mem_word(pto, 0x4EB9); /* JSR */ - pto += 2; - do_put_mem_long(pto, kROM_Base + (patchp - ROM)); - pto += 4; - - do_put_mem_word(patchp, 0x21FC); /* MOVE.L */ - patchp += 2; - do_put_mem_long(patchp, kVidMem_Base); /* kVidMem_Base */ - patchp += 4; - do_put_mem_word(patchp, 0x0824); /* (ScrnBase) */ - patchp += 2; - do_put_mem_word(patchp, 0x4E75); /* RTS */ - patchp += 2; - } - do_put_mem_word(1490 + ROM, vMacScreenWidth / 8); - do_put_mem_word(1546 + ROM, vMacScreenHeight); - do_put_mem_word(1550 + ROM, vMacScreenWidth); - - do_put_mem_word(2252 + ROM, vMacScreenHeight); - do_put_mem_word(2254 + ROM, vMacScreenWidth); - - /* blink floppy, disk icon */ - do_put_mem_long(3916 + ROM, kVidMem_Base - + (((vMacScreenHeight / 4) * 2 - 25) * vMacScreenWidth - + (vMacScreenWidth / 2 - 16)) - / 8); - /* blink floppy, question mark */ - do_put_mem_long(3934 + ROM, kVidMem_Base - + (((vMacScreenHeight / 4) * 2 - 10) * vMacScreenWidth - + (vMacScreenWidth / 2 - 8)) - / 8); - - do_put_mem_long(4258 + ROM, kVidMem_Base); - do_put_mem_word(4264 + ROM, vMacScreenHeight); - do_put_mem_word(4268 + ROM, vMacScreenWidth); - do_put_mem_word(4272 + ROM, vMacScreenWidth / 8); - do_put_mem_long(4276 + ROM, vMacScreenNumBytes); - - /* sad mac, mac icon */ - do_put_mem_long(4490 + ROM, kVidMem_Base - + (((vMacScreenHeight / 4) * 2 - 25) * vMacScreenWidth - + (vMacScreenWidth / 2 - 16)) - / 8); - /* sad mac, frown */ - do_put_mem_long(4504 + ROM, kVidMem_Base - + (((vMacScreenHeight / 4) * 2 - 19) * vMacScreenWidth - + (vMacScreenWidth / 2 - 8)) - / 8); - do_put_mem_word(4528 + ROM, vMacScreenWidth / 8); - /* blink floppy and sadmac, position */ - do_put_mem_word(4568 + ROM, vMacScreenWidth / 8); - do_put_mem_word(4586 + ROM, vMacScreenWidth / 8); - - /* cursor handling */ -#if vMacScreenWidth >= 1024 - pto = 101886 + ROM; - do_put_mem_word(pto, 0x4EB9); /* JSR */ - pto += 2; - do_put_mem_long(pto, kROM_Base + (patchp - ROM)); - pto += 4; - - do_put_mem_word(patchp, 0x41F8); /* Lea.L (CrsrSave),A0 */ - patchp += 2; - do_put_mem_word(patchp, 0x088C); - patchp += 2; - do_put_mem_word(patchp, 0x203C); /* MOVE.L #$x,D0 */ - patchp += 2; - do_put_mem_long(patchp, (vMacScreenWidth / 8)); - patchp += 4; - do_put_mem_word(patchp, 0x4E75); /* RTS */ - patchp += 2; -#else - do_put_mem_word(101890 + ROM, 0x7000 + (vMacScreenWidth / 8)); -#endif - do_put_mem_word(102010 + ROM, vMacScreenWidth - 32); - do_put_mem_word(102016 + ROM, vMacScreenWidth - 32); - do_put_mem_word(102048 + ROM, vMacScreenHeight - 16); - do_put_mem_word(102054 + ROM, vMacScreenHeight); -#if vMacScreenWidth >= 1024 - pto = 102084 + ROM; - do_put_mem_word(pto, 0x4EB9); /* JSR */ - pto += 2; - do_put_mem_long(pto, kROM_Base + (patchp - ROM)); - pto += 4; - - do_put_mem_word(patchp, 0x2A3C); /* MOVE.L #$x, D5 */ - patchp += 2; - do_put_mem_long(patchp, (vMacScreenWidth / 8)); - patchp += 4; - do_put_mem_word(patchp, 0xC2C5); /* MulU D5, D1 */ - patchp += 2; - do_put_mem_word(patchp, 0xD3C1); /* AddA.L D1, A1 */ - patchp += 2; - do_put_mem_word(patchp, 0x4E75); /* RTS */ - patchp += 2; -#else - do_put_mem_word(102084 + ROM, 0x7A00 + (vMacScreenWidth / 8)); -#endif - - /* set up screen bitmap */ - do_put_mem_word(102298 + ROM, vMacScreenHeight); - do_put_mem_word(102304 + ROM, vMacScreenWidth); - do_put_mem_word(102324 + ROM, vMacScreenHeight); - -#endif +/* SCRNHACK.h Copyright (C) 2007 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* SCReeN Hack Patch ROM to support other screen sizes. */ #if CurEmMd <= kEmMd_128K do_put_mem_long(112 + ROM, kVidMem_Base); do_put_mem_long(260 + ROM, kVidMem_Base); do_put_mem_long(292 + ROM, kVidMem_Base + (((vMacScreenHeight / 4) * 2 + 9) * vMacScreenWidth + (vMacScreenWidth / 2 - 24)) / 8); /* sad mac, error code */ do_put_mem_word(330 + ROM, vMacScreenWidth / 8); do_put_mem_word(342 + ROM, vMacScreenWidth / 8); do_put_mem_word(350 + ROM, vMacScreenWidth / 4 * 3 - 1); /* sad mac, blink pixels */ do_put_mem_word(358 + ROM, vMacScreenWidth - 4); do_put_mem_word(456 + ROM, (vMacScreenHeight * vMacScreenWidth / 32) - 1 + 32); /* screen setup, main */ { pto = 862 + ROM; do_put_mem_word(pto, 0x4EB9); /* JSR */ pto += 2; do_put_mem_long(pto, kROM_Base + (patchp - ROM)); pto += 4; do_put_mem_word(patchp, 0x21FC); /* MOVE.L */ patchp += 2; do_put_mem_long(patchp, kVidMem_Base); /* kVidMem_Base */ patchp += 4; do_put_mem_word(patchp, 0x0824); /* (ScrnBase) */ patchp += 2; do_put_mem_word(patchp, 0x4E75); /* RTS */ patchp += 2; } do_put_mem_word(892 + ROM, vMacScreenHeight - 1); do_put_mem_word(894 + ROM, vMacScreenWidth - 1); /* blink floppy, disk icon */ do_put_mem_long(1388 + ROM, kVidMem_Base + (((vMacScreenHeight / 4) * 2 - 25) * vMacScreenWidth + (vMacScreenWidth / 2 - 16)) / 8); /* blink floppy, question mark */ do_put_mem_long(1406 + ROM, kVidMem_Base + (((vMacScreenHeight / 4) * 2 - 10) * vMacScreenWidth + (vMacScreenWidth / 2 - 8)) / 8); /* blink floppy and sadmac, position */ do_put_mem_word(1966 + ROM, vMacScreenWidth / 8 - 4); do_put_mem_word(1982 + ROM, vMacScreenWidth / 8); /* sad mac, mac icon */ do_put_mem_long(2008 + ROM, kVidMem_Base + (((vMacScreenHeight / 4) * 2 - 25) * vMacScreenWidth + (vMacScreenWidth / 2 - 16)) / 8); /* sad mac, frown */ do_put_mem_long(2020 + ROM, kVidMem_Base + (((vMacScreenHeight / 4) * 2 - 19) * vMacScreenWidth + (vMacScreenWidth / 2 - 8)) / 8); do_put_mem_word(2052 + ROM, vMacScreenWidth / 8 - 2); /* cursor handling */ #if vMacScreenWidth >= 1024 pto = 3448 + ROM; do_put_mem_word(pto, 0x4EB9); /* JSR */ pto += 2; do_put_mem_long(pto, kROM_Base + (patchp - ROM)); pto += 4; do_put_mem_word(patchp, 0x41F8); /* Lea.L (CrsrSave),A0 */ patchp += 2; do_put_mem_word(patchp, 0x088C); patchp += 2; do_put_mem_word(patchp, 0x203C); /* MOVE.L #$x,D0 */ patchp += 2; do_put_mem_long(patchp, (vMacScreenWidth / 8)); patchp += 4; do_put_mem_word(patchp, 0x4E75); /* RTS */ patchp += 2; #else do_put_mem_word(3452 + ROM, 0x7000 + (vMacScreenWidth / 8)); #endif do_put_mem_word(3572 + ROM, vMacScreenWidth - 32); do_put_mem_word(3578 + ROM, vMacScreenWidth - 32); do_put_mem_word(3610 + ROM, vMacScreenHeight - 16); do_put_mem_word(3616 + ROM, vMacScreenHeight); #if vMacScreenWidth >= 1024 pto = 3646 + ROM; do_put_mem_word(pto, 0x4EB9); /* JSR */ pto += 2; do_put_mem_long(pto, kROM_Base + (patchp - ROM)); pto += 4; do_put_mem_word(patchp, 0x2A3C); /* MOVE.L #$x,D5 */ patchp += 2; do_put_mem_long(patchp, (vMacScreenWidth / 8)); patchp += 4; do_put_mem_word(patchp, 0xC2C5); /* MulU D5,D1 */ patchp += 2; do_put_mem_word(patchp, 0xD3C1); /* AddA.L D1,A1 */ patchp += 2; do_put_mem_word(patchp, 0x4E75); /* RTS */ patchp += 2; #else do_put_mem_word(3646 + ROM, 0x7A00 + (vMacScreenWidth / 8)); #endif /* set up screen bitmap */ do_put_mem_word(3832 + ROM, vMacScreenHeight); do_put_mem_word(3838 + ROM, vMacScreenWidth); /* do_put_mem_word(7810 + ROM, vMacScreenHeight); */ #elif CurEmMd <= kEmMd_Plus do_put_mem_long(138 + ROM, kVidMem_Base); do_put_mem_long(326 + ROM, kVidMem_Base); do_put_mem_long(356 + ROM, kVidMem_Base + (((vMacScreenHeight / 4) * 2 + 9) * vMacScreenWidth + (vMacScreenWidth / 2 - 24)) / 8); /* sad mac, error code */ do_put_mem_word(392 + ROM, vMacScreenWidth / 8); do_put_mem_word(404 + ROM, vMacScreenWidth / 8); do_put_mem_word(412 + ROM, vMacScreenWidth / 4 * 3 - 1); /* sad mac, blink pixels */ do_put_mem_long(420 + ROM, kVidMem_Base + (((vMacScreenHeight / 4) * 2 + 17) * vMacScreenWidth + (vMacScreenWidth / 2 - 8)) / 8); do_put_mem_word(494 + ROM, (vMacScreenHeight * vMacScreenWidth / 32) - 1); /* screen setup, main */ { pto = 1132 + ROM; do_put_mem_word(pto, 0x4EB9); /* JSR */ pto += 2; do_put_mem_long(pto, kROM_Base + (patchp - ROM)); pto += 4; do_put_mem_word(patchp, 0x21FC); /* MOVE.L */ patchp += 2; do_put_mem_long(patchp, kVidMem_Base); /* kVidMem_Base */ patchp += 4; do_put_mem_word(patchp, 0x0824); /* (ScrnBase) */ patchp += 2; do_put_mem_word(patchp, 0x4E75); /* RTS */ patchp += 2; } do_put_mem_word(1140 + ROM, vMacScreenWidth / 8); do_put_mem_word(1172 + ROM, vMacScreenHeight); do_put_mem_word(1176 + ROM, vMacScreenWidth); /* blink floppy, disk icon */ do_put_mem_long(2016 + ROM, kVidMem_Base + (((vMacScreenHeight / 4) * 2 - 25) * vMacScreenWidth + (vMacScreenWidth / 2 - 16)) / 8); /* blink floppy, question mark */ do_put_mem_long(2034 + ROM, kVidMem_Base + (((vMacScreenHeight / 4) * 2 - 10) * vMacScreenWidth + (vMacScreenWidth / 2 - 8)) / 8); do_put_mem_word(2574 + ROM, vMacScreenHeight); do_put_mem_word(2576 + ROM, vMacScreenWidth); /* blink floppy and sadmac, position */ do_put_mem_word(3810 + ROM, vMacScreenWidth / 8 - 4); do_put_mem_word(3826 + ROM, vMacScreenWidth / 8); /* sad mac, mac icon */ do_put_mem_long(3852 + ROM, kVidMem_Base + (((vMacScreenHeight / 4) * 2 - 25) * vMacScreenWidth + (vMacScreenWidth / 2 - 16)) / 8); /* sad mac, frown */ do_put_mem_long(3864 + ROM, kVidMem_Base + (((vMacScreenHeight / 4) * 2 - 19) * vMacScreenWidth + (vMacScreenWidth / 2 - 8)) / 8); do_put_mem_word(3894 + ROM, vMacScreenWidth / 8 - 2); /* cursor handling */ #if vMacScreenWidth >= 1024 pto = 7372 + ROM; do_put_mem_word(pto, 0x4EB9); /* JSR */ pto += 2; do_put_mem_long(pto, kROM_Base + (patchp - ROM)); pto += 4; do_put_mem_word(patchp, 0x41F8); /* Lea.L (CrsrSave), A0 */ patchp += 2; do_put_mem_word(patchp, 0x088C); patchp += 2; do_put_mem_word(patchp, 0x203C); /* MOVE.L #$x, D0 */ patchp += 2; do_put_mem_long(patchp, (vMacScreenWidth / 8)); patchp += 4; do_put_mem_word(patchp, 0x4E75); /* RTS */ patchp += 2; #else do_put_mem_word(7376 + ROM, 0x7000 + (vMacScreenWidth / 8)); #endif do_put_mem_word(7496 + ROM, vMacScreenWidth - 32); do_put_mem_word(7502 + ROM, vMacScreenWidth - 32); do_put_mem_word(7534 + ROM, vMacScreenHeight - 16); do_put_mem_word(7540 + ROM, vMacScreenHeight); #if vMacScreenWidth >= 1024 pto = 7570 + ROM; do_put_mem_word(pto, 0x4EB9); /* JSR */ pto += 2; do_put_mem_long(pto, kROM_Base + (patchp - ROM)); pto += 4; do_put_mem_word(patchp, 0x2A3C); /* MOVE.L #$x,D5 */ patchp += 2; do_put_mem_long(patchp, (vMacScreenWidth / 8)); patchp += 4; do_put_mem_word(patchp, 0xC2C5); /* MulU D5,D1 */ patchp += 2; do_put_mem_word(patchp, 0xD3C1); /* AddA.L D1,A1 */ patchp += 2; do_put_mem_word(patchp, 0x4E75); /* RTS */ patchp += 2; #else do_put_mem_word(7570 + ROM, 0x7A00 + (vMacScreenWidth / 8)); #endif /* set up screen bitmap */ do_put_mem_word(7784 + ROM, vMacScreenHeight); do_put_mem_word(7790 + ROM, vMacScreenWidth); do_put_mem_word(7810 + ROM, vMacScreenHeight); #if 0 /* Haven't got these working. Alert outlines ok, but not contents. Perhaps global position of contents stored in system resource file. */ /* perhaps switch disk alert */ do_put_mem_word(10936 + ROM, vMacScreenHeight / 2 - 91); do_put_mem_word(10938 + ROM, vMacScreenWidth / 2 - 136); do_put_mem_word(10944 + ROM, vMacScreenHeight / 2 - 19); do_put_mem_word(10946 + ROM, vMacScreenWidth / 2 + 149); do_put_mem_word(11008 + ROM, ?); do_put_mem_word(11010 + ROM, ?); /* DSAlertRect */ do_put_mem_word(4952 + ROM, vMacScreenHeight / 2 - 107); do_put_mem_word(4954 + ROM, vMacScreenWidth / 2 - 236); do_put_mem_word(4958 + ROM, vMacScreenHeight / 2 + 19); do_put_mem_word(4960 + ROM, vMacScreenWidth / 2 + 236); do_put_mem_word(5212 + ROM, vMacScreenHeight / 2 - 101); do_put_mem_word(5214 + ROM, vMacScreenWidth / 2 - 218); #endif #elif CurEmMd <= kEmMd_Classic /* screen setup, main */ { pto = 1482 + ROM; do_put_mem_word(pto, 0x4EB9); /* JSR */ pto += 2; do_put_mem_long(pto, kROM_Base + (patchp - ROM)); pto += 4; do_put_mem_word(patchp, 0x21FC); /* MOVE.L */ patchp += 2; do_put_mem_long(patchp, kVidMem_Base); /* kVidMem_Base */ patchp += 4; do_put_mem_word(patchp, 0x0824); /* (ScrnBase) */ patchp += 2; do_put_mem_word(patchp, 0x4E75); /* RTS */ patchp += 2; } do_put_mem_word(1490 + ROM, vMacScreenWidth / 8); do_put_mem_word(1546 + ROM, vMacScreenHeight); do_put_mem_word(1550 + ROM, vMacScreenWidth); do_put_mem_word(2252 + ROM, vMacScreenHeight); do_put_mem_word(2254 + ROM, vMacScreenWidth); /* blink floppy, disk icon */ do_put_mem_long(3916 + ROM, kVidMem_Base + (((vMacScreenHeight / 4) * 2 - 25) * vMacScreenWidth + (vMacScreenWidth / 2 - 16)) / 8); /* blink floppy, question mark */ do_put_mem_long(3934 + ROM, kVidMem_Base + (((vMacScreenHeight / 4) * 2 - 10) * vMacScreenWidth + (vMacScreenWidth / 2 - 8)) / 8); do_put_mem_long(4258 + ROM, kVidMem_Base); do_put_mem_word(4264 + ROM, vMacScreenHeight); do_put_mem_word(4268 + ROM, vMacScreenWidth); do_put_mem_word(4272 + ROM, vMacScreenWidth / 8); do_put_mem_long(4276 + ROM, vMacScreenNumBytes); /* sad mac, mac icon */ do_put_mem_long(4490 + ROM, kVidMem_Base + (((vMacScreenHeight / 4) * 2 - 25) * vMacScreenWidth + (vMacScreenWidth / 2 - 16)) / 8); /* sad mac, frown */ do_put_mem_long(4504 + ROM, kVidMem_Base + (((vMacScreenHeight / 4) * 2 - 19) * vMacScreenWidth + (vMacScreenWidth / 2 - 8)) / 8); do_put_mem_word(4528 + ROM, vMacScreenWidth / 8); /* blink floppy and sadmac, position */ do_put_mem_word(4568 + ROM, vMacScreenWidth / 8); do_put_mem_word(4586 + ROM, vMacScreenWidth / 8); /* cursor handling */ #if vMacScreenWidth >= 1024 pto = 101886 + ROM; do_put_mem_word(pto, 0x4EB9); /* JSR */ pto += 2; do_put_mem_long(pto, kROM_Base + (patchp - ROM)); pto += 4; do_put_mem_word(patchp, 0x41F8); /* Lea.L (CrsrSave),A0 */ patchp += 2; do_put_mem_word(patchp, 0x088C); patchp += 2; do_put_mem_word(patchp, 0x203C); /* MOVE.L #$x,D0 */ patchp += 2; do_put_mem_long(patchp, (vMacScreenWidth / 8)); patchp += 4; do_put_mem_word(patchp, 0x4E75); /* RTS */ patchp += 2; #else do_put_mem_word(101890 + ROM, 0x7000 + (vMacScreenWidth / 8)); #endif do_put_mem_word(102010 + ROM, vMacScreenWidth - 32); do_put_mem_word(102016 + ROM, vMacScreenWidth - 32); do_put_mem_word(102048 + ROM, vMacScreenHeight - 16); do_put_mem_word(102054 + ROM, vMacScreenHeight); #if vMacScreenWidth >= 1024 pto = 102084 + ROM; do_put_mem_word(pto, 0x4EB9); /* JSR */ pto += 2; do_put_mem_long(pto, kROM_Base + (patchp - ROM)); pto += 4; do_put_mem_word(patchp, 0x2A3C); /* MOVE.L #$x, D5 */ patchp += 2; do_put_mem_long(patchp, (vMacScreenWidth / 8)); patchp += 4; do_put_mem_word(patchp, 0xC2C5); /* MulU D5, D1 */ patchp += 2; do_put_mem_word(patchp, 0xD3C1); /* AddA.L D1, A1 */ patchp += 2; do_put_mem_word(patchp, 0x4E75); /* RTS */ patchp += 2; #else do_put_mem_word(102084 + ROM, 0x7A00 + (vMacScreenWidth / 8)); #endif /* set up screen bitmap */ do_put_mem_word(102298 + ROM, vMacScreenHeight); do_put_mem_word(102304 + ROM, vMacScreenWidth); do_put_mem_word(102324 + ROM, vMacScreenHeight); #endif \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SCRNMAPR.h b/Mini vMac/mnvm_core/SCRNMAPR.h index 57716c4..d699f55 100755 --- a/Mini vMac/mnvm_core/SCRNMAPR.h +++ b/Mini vMac/mnvm_core/SCRNMAPR.h @@ -1,168 +1 @@ -/* - SCRNMAPR.h - - Copyright (C) 2012 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - SCReeN MAPpeR -*/ - -/* required arguments for this template */ - -#ifndef ScrnMapr_DoMap /* procedure to be created by this template */ -#error "ScrnMapr_DoMap not defined" -#endif -#ifndef ScrnMapr_Src -#error "ScrnMapr_Src not defined" -#endif -#ifndef ScrnMapr_Dst -#error "ScrnMapr_Dst not defined" -#endif -#ifndef ScrnMapr_SrcDepth -#error "ScrnMapr_SrcDepth not defined" -#endif -#ifndef ScrnMapr_DstDepth -#error "ScrnMapr_DstDepth not defined" -#endif -#ifndef ScrnMapr_Map -#error "ScrnMapr_Map not defined" -#endif - -/* optional argument for this template */ - -#ifndef ScrnMapr_Scale -#define ScrnMapr_Scale 1 -#endif - -/* check of parameters */ - -#if (ScrnMapr_SrcDepth < 0) || (ScrnMapr_SrcDepth > 3) -#error "bad ScrnMapr_SrcDepth" -#endif - -#if (ScrnMapr_DstDepth < ScrnMapr_SrcDepth) -#error "bad ScrnMapr_Dst" -#endif - -/* calculate a few things local to this template */ - -#define ScrnMapr_MapElSz \ - (ScrnMapr_Scale << (ScrnMapr_DstDepth - ScrnMapr_SrcDepth)) - -#if 0 == (ScrnMapr_MapElSz & 3) -#define ScrnMapr_TranT ui5b -#define ScrnMapr_TranLn2Sz 2 -#elif 0 == (ScrnMapr_MapElSz & 1) -#define ScrnMapr_TranT ui4b -#define ScrnMapr_TranLn2Sz 1 -#else -#define ScrnMapr_TranT ui3b -#define ScrnMapr_TranLn2Sz 0 -#endif - -#define ScrnMapr_TranN (ScrnMapr_MapElSz >> ScrnMapr_TranLn2Sz) - -#define ScrnMapr_ScrnWB (vMacScreenWidth >> (3 - ScrnMapr_SrcDepth)) - -/* now define the procedure */ - -LOCALPROC ScrnMapr_DoMap(si4b top, si4b left, - si4b bottom, si4b right) -{ - int i; - int j; -#if (ScrnMapr_TranN > 4) || (ScrnMapr_Scale > 2) - int k; -#endif - ui5r t0; - ScrnMapr_TranT *pMap; -#if ScrnMapr_Scale > 1 - ScrnMapr_TranT *p3; -#endif - - ui4r leftB = left >> (3 - ScrnMapr_SrcDepth); - ui4r rightB = (right + (1 << (3 - ScrnMapr_SrcDepth)) - 1) - >> (3 - ScrnMapr_SrcDepth); - ui4r jn = rightB - leftB; - ui4r SrcSkip = ScrnMapr_ScrnWB - jn; - ui3b *pSrc = ((ui3b *)ScrnMapr_Src) - + leftB + ScrnMapr_ScrnWB * (ui5r)top; - ScrnMapr_TranT *pDst = ((ScrnMapr_TranT *)ScrnMapr_Dst) - + ((leftB + ScrnMapr_ScrnWB * ScrnMapr_Scale * (ui5r)top) - * ScrnMapr_TranN); - ui5r DstSkip = SrcSkip * ScrnMapr_TranN; - - for (i = bottom - top; --i >= 0; ) { -#if ScrnMapr_Scale > 1 - p3 = pDst; -#endif - - for (j = jn; --j >= 0; ) { - t0 = *pSrc++; - pMap = - &((ScrnMapr_TranT *)ScrnMapr_Map)[t0 * ScrnMapr_TranN]; - -#if ScrnMapr_TranN > 4 - for (k = ScrnMapr_TranN; --k >= 0; ) { - *pDst++ = *pMap++; - } -#else - -#if ScrnMapr_TranN >= 2 - *pDst++ = *pMap++; -#endif -#if ScrnMapr_TranN >= 3 - *pDst++ = *pMap++; -#endif -#if ScrnMapr_TranN >= 4 - *pDst++ = *pMap++; -#endif - *pDst++ = *pMap; - -#endif /* ! ScrnMapr_TranN > 4 */ - - } - pSrc += SrcSkip; - pDst += DstSkip; - -#if ScrnMapr_Scale > 1 -#if ScrnMapr_Scale > 2 - for (k = ScrnMapr_Scale - 1; --k >= 0; ) -#endif - { - pMap = p3; - for (j = ScrnMapr_TranN * jn; --j >= 0; ) { - *pDst++ = *pMap++; - } - pDst += DstSkip; - } -#endif /* ScrnMapr_Scale > 1 */ - } -} - -/* undefine template locals and parameters */ - -#undef ScrnMapr_ScrnWB -#undef ScrnMapr_TranN -#undef ScrnMapr_TranLn2Sz -#undef ScrnMapr_TranT -#undef ScrnMapr_MapElSz - -#undef ScrnMapr_DoMap -#undef ScrnMapr_Src -#undef ScrnMapr_Dst -#undef ScrnMapr_SrcDepth -#undef ScrnMapr_DstDepth -#undef ScrnMapr_Map -#undef ScrnMapr_Scale +/* SCRNMAPR.h Copyright (C) 2012 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* SCReeN MAPpeR */ /* required arguments for this template */ #ifndef ScrnMapr_DoMap /* procedure to be created by this template */ #error "ScrnMapr_DoMap not defined" #endif #ifndef ScrnMapr_Src #error "ScrnMapr_Src not defined" #endif #ifndef ScrnMapr_Dst #error "ScrnMapr_Dst not defined" #endif #ifndef ScrnMapr_SrcDepth #error "ScrnMapr_SrcDepth not defined" #endif #ifndef ScrnMapr_DstDepth #error "ScrnMapr_DstDepth not defined" #endif #ifndef ScrnMapr_Map #error "ScrnMapr_Map not defined" #endif /* optional argument for this template */ #ifndef ScrnMapr_Scale #define ScrnMapr_Scale 1 #endif /* check of parameters */ #if (ScrnMapr_SrcDepth < 0) || (ScrnMapr_SrcDepth > 3) #error "bad ScrnMapr_SrcDepth" #endif #if (ScrnMapr_DstDepth < ScrnMapr_SrcDepth) #error "bad ScrnMapr_Dst" #endif /* calculate a few things local to this template */ #define ScrnMapr_MapElSz \ (ScrnMapr_Scale << (ScrnMapr_DstDepth - ScrnMapr_SrcDepth)) #if 0 == (ScrnMapr_MapElSz & 3) #define ScrnMapr_TranT ui5b #define ScrnMapr_TranLn2Sz 2 #elif 0 == (ScrnMapr_MapElSz & 1) #define ScrnMapr_TranT ui4b #define ScrnMapr_TranLn2Sz 1 #else #define ScrnMapr_TranT ui3b #define ScrnMapr_TranLn2Sz 0 #endif #define ScrnMapr_TranN (ScrnMapr_MapElSz >> ScrnMapr_TranLn2Sz) #define ScrnMapr_ScrnWB (vMacScreenWidth >> (3 - ScrnMapr_SrcDepth)) /* now define the procedure */ LOCALPROC ScrnMapr_DoMap(si4b top, si4b left, si4b bottom, si4b right) { int i; int j; #if (ScrnMapr_TranN > 4) || (ScrnMapr_Scale > 2) int k; #endif ui5r t0; ScrnMapr_TranT *pMap; #if ScrnMapr_Scale > 1 ScrnMapr_TranT *p3; #endif ui4r leftB = left >> (3 - ScrnMapr_SrcDepth); ui4r rightB = (right + (1 << (3 - ScrnMapr_SrcDepth)) - 1) >> (3 - ScrnMapr_SrcDepth); ui4r jn = rightB - leftB; ui4r SrcSkip = ScrnMapr_ScrnWB - jn; ui3b *pSrc = ((ui3b *)ScrnMapr_Src) + leftB + ScrnMapr_ScrnWB * (ui5r)top; ScrnMapr_TranT *pDst = ((ScrnMapr_TranT *)ScrnMapr_Dst) + ((leftB + ScrnMapr_ScrnWB * ScrnMapr_Scale * (ui5r)top) * ScrnMapr_TranN); ui5r DstSkip = SrcSkip * ScrnMapr_TranN; for (i = bottom - top; --i >= 0; ) { #if ScrnMapr_Scale > 1 p3 = pDst; #endif for (j = jn; --j >= 0; ) { t0 = *pSrc++; pMap = &((ScrnMapr_TranT *)ScrnMapr_Map)[t0 * ScrnMapr_TranN]; #if ScrnMapr_TranN > 4 for (k = ScrnMapr_TranN; --k >= 0; ) { *pDst++ = *pMap++; } #else #if ScrnMapr_TranN >= 2 *pDst++ = *pMap++; #endif #if ScrnMapr_TranN >= 3 *pDst++ = *pMap++; #endif #if ScrnMapr_TranN >= 4 *pDst++ = *pMap++; #endif *pDst++ = *pMap; #endif /* ! ScrnMapr_TranN > 4 */ } pSrc += SrcSkip; pDst += DstSkip; #if ScrnMapr_Scale > 1 #if ScrnMapr_Scale > 2 for (k = ScrnMapr_Scale - 1; --k >= 0; ) #endif { pMap = p3; for (j = ScrnMapr_TranN * jn; --j >= 0; ) { *pDst++ = *pMap++; } pDst += DstSkip; } #endif /* ScrnMapr_Scale > 1 */ } } /* undefine template locals and parameters */ #undef ScrnMapr_ScrnWB #undef ScrnMapr_TranN #undef ScrnMapr_TranLn2Sz #undef ScrnMapr_TranT #undef ScrnMapr_MapElSz #undef ScrnMapr_DoMap #undef ScrnMapr_Src #undef ScrnMapr_Dst #undef ScrnMapr_SrcDepth #undef ScrnMapr_DstDepth #undef ScrnMapr_Map #undef ScrnMapr_Scale \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SCRNTRNS.h b/Mini vMac/mnvm_core/SCRNTRNS.h index b7da6d8..c840fb0 100755 --- a/Mini vMac/mnvm_core/SCRNTRNS.h +++ b/Mini vMac/mnvm_core/SCRNTRNS.h @@ -1,161 +1 @@ -/* - SCRNTRNS.h - - Copyright (C) 2012 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - SCReeN TRaNSlater -*/ - -/* required arguments for this template */ - -#ifndef ScrnTrns_DoTrans /* procedure to be created by this template */ -#error "ScrnTrns_DoTrans not defined" -#endif -#ifndef ScrnTrns_Src -#error "ScrnTrns_Src not defined" -#endif -#ifndef ScrnTrns_Dst -#error "ScrnTrns_Dst not defined" -#endif -#ifndef ScrnTrns_SrcDepth -#error "ScrnTrns_SrcDepth not defined" -#endif -#ifndef ScrnTrns_DstDepth -#error "ScrnTrns_DstDepth not defined" -#endif - -/* optional argument for this template */ - -#ifndef ScrnTrns_Scale -#define ScrnTrns_Scale 1 -#endif - -#ifndef ScrnTrns_DstZLo -#define ScrnTrns_DstZLo 0 -#endif - -/* check of parameters */ - -#if (ScrnTrns_SrcDepth < 4) -#error "bad ScrnTrns_SrcDepth" -#endif - -#if (ScrnTrns_DstDepth < 4) -#error "bad ScrnTrns_Dst" -#endif - -/* now define the procedure */ - -LOCALPROC ScrnTrns_DoTrans(si4b top, si4b left, - si4b bottom, si4b right) -{ - int i; - int j; - ui5b t0; - ui5b t1; - ui4r jn = right - left; - ui4r SrcSkip = vMacScreenByteWidth - - (jn << (ScrnTrns_SrcDepth - 3)); - ui3b *pSrc = ((ui3b *)ScrnTrns_Src) - + (left << (ScrnTrns_SrcDepth - 3)) - + vMacScreenByteWidth * (ui5r)top; - ui5b *pDst = ((ui5b *)ScrnTrns_Dst) - + left * ScrnTrns_Scale - + (ui5r)vMacScreenWidth * ScrnTrns_Scale * ScrnTrns_Scale * top; - ui4r DstSkip = (vMacScreenWidth - jn) * ScrnTrns_Scale; -#if ScrnTrns_Scale > 1 - int k; - ui5b *p3; - ui5b *p4; -#endif - - for (i = bottom - top; --i >= 0; ) { -#if ScrnTrns_Scale > 1 - p3 = pDst; -#endif - - for (j = jn; --j >= 0; ) { -#if 4 == ScrnTrns_SrcDepth - t0 = do_get_mem_word(pSrc); - pSrc += 2; - t1 = -#if ScrnTrns_DstZLo - ((t0 & 0x7C00) << 17) | - ((t0 & 0x7000) << 12) | - ((t0 & 0x03E0) << 14) | - ((t0 & 0x0380) << 9) | - ((t0 & 0x001F) << 11) | - ((t0 & 0x001C) << 6); -#else - ((t0 & 0x7C00) << 9) | - ((t0 & 0x7000) << 4) | - ((t0 & 0x03E0) << 6) | - ((t0 & 0x0380) << 1) | - ((t0 & 0x001F) << 3) | - ((t0 & 0x001C) >> 2); -#endif -#if 0 - ((t0 & 0x7C00) << 1) | - ((t0 & 0x7000) >> 4) | - ((t0 & 0x03E0) << 14) | - ((t0 & 0x0380) << 9) | - ((t0 & 0x001F) << 27) | - ((t0 & 0x001C) << 22); -#endif - -#elif 5 == ScrnTrns_SrcDepth - t0 = do_get_mem_long(pSrc); - pSrc += 4; -#if ScrnTrns_DstZLo - t1 = t0 << 8; -#else - t1 = t0; -#endif -#endif - -#if ScrnTrns_Scale > 1 - for (k = ScrnTrns_Scale; --k >= 0; ) -#endif - { - *pDst++ = t1; - } - } - pSrc += SrcSkip; - pDst += DstSkip; - -#if ScrnTrns_Scale > 1 -#if ScrnTrns_Scale > 2 - for (k = ScrnTrns_Scale - 1; --k >= 0; ) -#endif - { - p4 = p3; - for (j = ScrnTrns_Scale * jn; --j >= 0; ) { - *pDst++ = *p4++; - } - pDst += DstSkip; - } -#endif /* ScrnTrns_Scale > 1 */ - } -} - -/* undefine template locals and parameters */ - -#undef ScrnTrns_DoTrans -#undef ScrnTrns_Src -#undef ScrnTrns_Dst -#undef ScrnTrns_SrcDepth -#undef ScrnTrns_DstDepth -#undef ScrnTrns_Scale -#undef ScrnTrns_DstZLo +/* SCRNTRNS.h Copyright (C) 2012 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* SCReeN TRaNSlater */ /* required arguments for this template */ #ifndef ScrnTrns_DoTrans /* procedure to be created by this template */ #error "ScrnTrns_DoTrans not defined" #endif #ifndef ScrnTrns_Src #error "ScrnTrns_Src not defined" #endif #ifndef ScrnTrns_Dst #error "ScrnTrns_Dst not defined" #endif #ifndef ScrnTrns_SrcDepth #error "ScrnTrns_SrcDepth not defined" #endif #ifndef ScrnTrns_DstDepth #error "ScrnTrns_DstDepth not defined" #endif /* optional argument for this template */ #ifndef ScrnTrns_Scale #define ScrnTrns_Scale 1 #endif #ifndef ScrnTrns_DstZLo #define ScrnTrns_DstZLo 0 #endif /* check of parameters */ #if (ScrnTrns_SrcDepth < 4) #error "bad ScrnTrns_SrcDepth" #endif #if (ScrnTrns_DstDepth < 4) #error "bad ScrnTrns_Dst" #endif /* now define the procedure */ LOCALPROC ScrnTrns_DoTrans(si4b top, si4b left, si4b bottom, si4b right) { int i; int j; ui5b t0; ui5b t1; ui4r jn = right - left; ui4r SrcSkip = vMacScreenByteWidth - (jn << (ScrnTrns_SrcDepth - 3)); ui3b *pSrc = ((ui3b *)ScrnTrns_Src) + (left << (ScrnTrns_SrcDepth - 3)) + vMacScreenByteWidth * (ui5r)top; ui5b *pDst = ((ui5b *)ScrnTrns_Dst) + left * ScrnTrns_Scale + (ui5r)vMacScreenWidth * ScrnTrns_Scale * ScrnTrns_Scale * top; ui4r DstSkip = (vMacScreenWidth - jn) * ScrnTrns_Scale; #if ScrnTrns_Scale > 1 int k; ui5b *p3; ui5b *p4; #endif for (i = bottom - top; --i >= 0; ) { #if ScrnTrns_Scale > 1 p3 = pDst; #endif for (j = jn; --j >= 0; ) { #if 4 == ScrnTrns_SrcDepth t0 = do_get_mem_word(pSrc); pSrc += 2; t1 = #if ScrnTrns_DstZLo ((t0 & 0x7C00) << 17) | ((t0 & 0x7000) << 12) | ((t0 & 0x03E0) << 14) | ((t0 & 0x0380) << 9) | ((t0 & 0x001F) << 11) | ((t0 & 0x001C) << 6); #else ((t0 & 0x7C00) << 9) | ((t0 & 0x7000) << 4) | ((t0 & 0x03E0) << 6) | ((t0 & 0x0380) << 1) | ((t0 & 0x001F) << 3) | ((t0 & 0x001C) >> 2); #endif #if 0 ((t0 & 0x7C00) << 1) | ((t0 & 0x7000) >> 4) | ((t0 & 0x03E0) << 14) | ((t0 & 0x0380) << 9) | ((t0 & 0x001F) << 27) | ((t0 & 0x001C) << 22); #endif #elif 5 == ScrnTrns_SrcDepth t0 = do_get_mem_long(pSrc); pSrc += 4; #if ScrnTrns_DstZLo t1 = t0 << 8; #else t1 = t0; #endif #endif #if ScrnTrns_Scale > 1 for (k = ScrnTrns_Scale; --k >= 0; ) #endif { *pDst++ = t1; } } pSrc += SrcSkip; pDst += DstSkip; #if ScrnTrns_Scale > 1 #if ScrnTrns_Scale > 2 for (k = ScrnTrns_Scale - 1; --k >= 0; ) #endif { p4 = p3; for (j = ScrnTrns_Scale * jn; --j >= 0; ) { *pDst++ = *p4++; } pDst += DstSkip; } #endif /* ScrnTrns_Scale > 1 */ } } /* undefine template locals and parameters */ #undef ScrnTrns_DoTrans #undef ScrnTrns_Src #undef ScrnTrns_Dst #undef ScrnTrns_SrcDepth #undef ScrnTrns_DstDepth #undef ScrnTrns_Scale #undef ScrnTrns_DstZLo \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SCSIEMDV.c b/Mini vMac/mnvm_core/SCSIEMDV.c index f2920c6..41d64ba 100755 --- a/Mini vMac/mnvm_core/SCSIEMDV.c +++ b/Mini vMac/mnvm_core/SCSIEMDV.c @@ -1,155 +1 @@ -/* - SCSIEMDV.c - - Copyright (C) 2004 Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - Small Computer System Interface EMulated DeVice - - Emulates the SCSI found in the Mac Plus. - - This code adapted from "SCSI.c" in vMac by Philip Cummins. -*/ - -/* NCR5380 chip emulation by Yoav Shadmi, 1998 */ - -#ifndef AllFiles -#include "SYSDEPNS.h" - -#include "ENDIANAC.h" -#include "MYOSGLUE.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" -#endif - -#include "SCSIEMDV.h" - -#define scsiRd 0x00 -#define scsiWr 0x01 - -#define sCDR 0x00 /* current scsi data register (r/o) */ -#define sODR 0x00 /* output data register (w/o) */ -#define sICR 0x02 /* initiator command register (r/w) */ -#define sMR 0x04 /* mode register (r/w) */ -#define sTCR 0x06 /* target command register (r/w) */ -#define sCSR 0x08 /* current SCSI bus status (r/o) */ -#define sSER 0x08 /* select enable register (w/o) */ -#define sBSR 0x0A /* bus and status register (r/o) */ -#define sDMAtx 0x0A /* start DMA send (w/o) */ -#define sIDR 0x0C /* input data register (r/o) */ -#define sTDMArx 0x0C /* start DMA target receive (w/o) */ -#define sRESET 0x0E /* reset parity/interrupt (r/o) */ -#define sIDMArx 0x0E /* start DMA initiator receive (w/o) */ - -#define kSCSI_Size 0x00010 - -LOCALVAR ui3b SCSI[kSCSI_Size]; - -GLOBALPROC SCSI_Reset(void) -{ - int i; - - for (i = 0; i < kSCSI_Size; i++) { - SCSI[i] = 0; - } -} - -LOCALPROC SCSI_BusReset(void) -{ - SCSI[scsiRd + sCDR] = 0; - SCSI[scsiWr + sODR] = 0; - SCSI[scsiRd + sICR] = 0x80; - SCSI[scsiWr + sICR] &= 0x80; - SCSI[scsiRd + sMR] &= 0x40; - SCSI[scsiWr + sMR] &= 0x40; - SCSI[scsiRd + sTCR] = 0; - SCSI[scsiWr + sTCR] = 0; - SCSI[scsiRd + sCSR] = 0x80; - SCSI[scsiWr + sSER] = 0; - SCSI[scsiRd + sBSR] = 0x10; - SCSI[scsiWr + sDMAtx] = 0; - SCSI[scsiRd + sIDR] = 0; - SCSI[scsiWr + sTDMArx] = 0; - SCSI[scsiRd + sRESET] = 0; - SCSI[scsiWr + sIDMArx] = 0; -#if 0 - SCSI[scsiRd + sODR + dackWr] = 0; - SCSI[scsiWr + sIDR + dackRd] = 0; -#endif - - /* The missing piece of the puzzle.. :) */ - put_ram_word(0xb22, get_ram_word(0xb22) | 0x8000); -} - -LOCALPROC SCSI_Check(void) -{ - /* - The arbitration select/reselect scenario - [stub.. doesn't really work...] - */ - if ((SCSI[scsiWr + sODR] >> 7) == 1) { - /* Check if the Mac tries to be an initiator */ - if ((SCSI[scsiWr + sMR] & 1) == 1) { - /* the Mac set arbitration in progress */ - /* - stub! tell the mac that there - is arbitration in progress... - */ - SCSI[scsiRd + sICR] |= 0x40; - /* ... that we didn't lose arbitration ... */ - SCSI[scsiRd + sICR] &= ~ 0x20; - /* - ... and that there isn't a higher priority ID present... - */ - SCSI[scsiRd + sCDR] = 0x00; - - /* - ... the arbitration and selection/reselection is - complete. the initiator tries to connect to the SCSI - device, fails and returns after timeout. - */ - } - } - - /* check the chip registers, AS SET BY THE CPU */ - if ((SCSI[scsiWr + sICR] >> 7) == 1) { - /* Check Assert RST */ - SCSI_BusReset(); - } else { - SCSI[scsiRd + sICR] &= ~ 0x80; - SCSI[scsiRd + sCSR] &= ~ 0x80; - } - - if ((SCSI[scsiWr + sICR] >> 2) == 1) { - /* Check Assert SEL */ - SCSI[scsiRd + sCSR] |= 0x02; - SCSI[scsiRd + sBSR] = 0x10; - } else { - SCSI[scsiRd + sCSR] &= ~ 0x02; - } -} - -GLOBALFUNC ui5b SCSI_Access(ui5b Data, blnr WriteMem, CPTR addr) -{ - if (addr < (kSCSI_Size / 2)) { - addr *= 2; - if (WriteMem) { - SCSI[addr + 1] = Data; - SCSI_Check(); - } else { - Data = SCSI[addr]; - } - } - return Data; -} +/* SCSIEMDV.c Copyright (C) 2004 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* Small Computer System Interface EMulated DeVice Emulates the SCSI found in the Mac Plus. This code adapted from "SCSI.c" in vMac by Philip Cummins. */ /* NCR5380 chip emulation by Yoav Shadmi, 1998 */ #ifndef AllFiles #include "SYSDEPNS.h" #include "ENDIANAC.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "MINEM68K.h" #endif #include "SCSIEMDV.h" #define scsiRd 0x00 #define scsiWr 0x01 #define sCDR 0x00 /* current scsi data register (r/o) */ #define sODR 0x00 /* output data register (w/o) */ #define sICR 0x02 /* initiator command register (r/w) */ #define sMR 0x04 /* mode register (r/w) */ #define sTCR 0x06 /* target command register (r/w) */ #define sCSR 0x08 /* current SCSI bus status (r/o) */ #define sSER 0x08 /* select enable register (w/o) */ #define sBSR 0x0A /* bus and status register (r/o) */ #define sDMAtx 0x0A /* start DMA send (w/o) */ #define sIDR 0x0C /* input data register (r/o) */ #define sTDMArx 0x0C /* start DMA target receive (w/o) */ #define sRESET 0x0E /* reset parity/interrupt (r/o) */ #define sIDMArx 0x0E /* start DMA initiator receive (w/o) */ #define kSCSI_Size 0x00010 LOCALVAR ui3b SCSI[kSCSI_Size]; GLOBALPROC SCSI_Reset(void) { int i; for (i = 0; i < kSCSI_Size; i++) { SCSI[i] = 0; } } LOCALPROC SCSI_BusReset(void) { SCSI[scsiRd + sCDR] = 0; SCSI[scsiWr + sODR] = 0; SCSI[scsiRd + sICR] = 0x80; SCSI[scsiWr + sICR] &= 0x80; SCSI[scsiRd + sMR] &= 0x40; SCSI[scsiWr + sMR] &= 0x40; SCSI[scsiRd + sTCR] = 0; SCSI[scsiWr + sTCR] = 0; SCSI[scsiRd + sCSR] = 0x80; SCSI[scsiWr + sSER] = 0; SCSI[scsiRd + sBSR] = 0x10; SCSI[scsiWr + sDMAtx] = 0; SCSI[scsiRd + sIDR] = 0; SCSI[scsiWr + sTDMArx] = 0; SCSI[scsiRd + sRESET] = 0; SCSI[scsiWr + sIDMArx] = 0; #if 0 SCSI[scsiRd + sODR + dackWr] = 0; SCSI[scsiWr + sIDR + dackRd] = 0; #endif /* The missing piece of the puzzle.. :) */ put_ram_word(0xb22, get_ram_word(0xb22) | 0x8000); } LOCALPROC SCSI_Check(void) { /* The arbitration select/reselect scenario [stub.. doesn't really work...] */ if ((SCSI[scsiWr + sODR] >> 7) == 1) { /* Check if the Mac tries to be an initiator */ if ((SCSI[scsiWr + sMR] & 1) == 1) { /* the Mac set arbitration in progress */ /* stub! tell the mac that there is arbitration in progress... */ SCSI[scsiRd + sICR] |= 0x40; /* ... that we didn't lose arbitration ... */ SCSI[scsiRd + sICR] &= ~ 0x20; /* ... and that there isn't a higher priority ID present... */ SCSI[scsiRd + sCDR] = 0x00; /* ... the arbitration and selection/reselection is complete. the initiator tries to connect to the SCSI device, fails and returns after timeout. */ } } /* check the chip registers, AS SET BY THE CPU */ if ((SCSI[scsiWr + sICR] >> 7) == 1) { /* Check Assert RST */ SCSI_BusReset(); } else { SCSI[scsiRd + sICR] &= ~ 0x80; SCSI[scsiRd + sCSR] &= ~ 0x80; } if ((SCSI[scsiWr + sICR] >> 2) == 1) { /* Check Assert SEL */ SCSI[scsiRd + sCSR] |= 0x02; SCSI[scsiRd + sBSR] = 0x10; } else { SCSI[scsiRd + sCSR] &= ~ 0x02; } } GLOBALFUNC ui5b SCSI_Access(ui5b Data, blnr WriteMem, CPTR addr) { if (addr < (kSCSI_Size / 2)) { addr *= 2; if (WriteMem) { SCSI[addr + 1] = Data; SCSI_Check(); } else { Data = SCSI[addr]; } } return Data; } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SCSIEMDV.h b/Mini vMac/mnvm_core/SCSIEMDV.h index 53005c6..b189024 100755 --- a/Mini vMac/mnvm_core/SCSIEMDV.h +++ b/Mini vMac/mnvm_core/SCSIEMDV.h @@ -1,25 +1 @@ -/* - SCSIEMDV.h - - Copyright (C) 2004 Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef SCSIEMDV_H -#error "header already included" -#else -#define SCSIEMDV_H -#endif - -EXPORTPROC SCSI_Reset(void); - -EXPORTFUNC ui5b SCSI_Access(ui5b Data, blnr WriteMem, CPTR addr); +/* SCSIEMDV.h Copyright (C) 2004 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef SCSIEMDV_H #error "header already included" #else #define SCSIEMDV_H #endif EXPORTPROC SCSI_Reset(void); EXPORTFUNC ui5b SCSI_Access(ui5b Data, blnr WriteMem, CPTR addr); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SGLUALSA.h b/Mini vMac/mnvm_core/SGLUALSA.h new file mode 100755 index 0000000..ae39ada --- /dev/null +++ b/Mini vMac/mnvm_core/SGLUALSA.h @@ -0,0 +1 @@ +/* SGLUALSA.h Copyright (C) 2012 Stephan Kochen, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* Sound GLUe for ALSA ALSA sound support by Stephan Kochen. */ #ifndef RaspbianWorkAround #define RaspbianWorkAround 0 #endif #if 0 #include "alsa/asoundlib.h" /* and link with "-lasound" */ #define My_snd_pcm_t snd_pcm_t #define My_snd_pcm_hw_params_t snd_pcm_hw_params_t #define My_snd_pcm_sw_params_t snd_pcm_sw_params_t #define My_snd_pcm_state_t snd_pcm_state_t #if RaspbianWorkAround #define My_snd_pcm_status_t snd_pcm_status_t #endif #define My_SND_PCM_STATE_OPEN SND_PCM_STATE_OPEN #define My_SND_PCM_STATE_SETUP SND_PCM_STATE_SETUP #define My_SND_PCM_STATE_PREPARED SND_PCM_STATE_PREPARED #define My_SND_PCM_STATE_RUNNING SND_PCM_STATE_RUNNING #define My_SND_PCM_STATE_XRUN SND_PCM_STATE_XRUN #define My_SND_PCM_STATE_DRAINING SND_PCM_STATE_DRAINING #define My_SND_PCM_STATE_PAUSED SND_PCM_STATE_PAUSED #define My_SND_PCM_STATE_SUSPENDED SND_PCM_STATE_SUSPENDED #define My_SND_PCM_STATE_DISCONNECTED SND_PCM_STATE_DISCONNECTED #define My_SND_PCM_STATE_LAST SND_PCM_STATE_LAST #define My_snd_pcm_stream_t snd_pcm_stream_t #define My_SND_PCM_STREAM_PLAYBACK SND_PCM_STREAM_PLAYBACK #define My_SND_PCM_STREAM_CAPTURE SND_PCM_STREAM_CAPTURE #define My_SND_PCM_STREAM_LAST SND_PCM_STREAM_LAST #define My_snd_pcm_access_t snd_pcm_access_t #define My_SND_PCM_ACCESS_MMAP_INTERLEAVED \ SND_PCM_ACCESS_MMAP_INTERLEAVED #define My_SND_PCM_ACCESS_MMAP_NONINTERLEAVED \ SND_PCM_ACCESS_MMAP_NONINTERLEAVED #define My_SND_PCM_ACCESS_MMAP_COMPLEX \ SND_PCM_ACCESS_MMAP_COMPLEX #define My_SND_PCM_ACCESS_RW_INTERLEAVED \ SND_PCM_ACCESS_RW_INTERLEAVED #define My_SND_PCM_ACCESS_RW_NONINTERLEAVED \ SND_PCM_ACCESS_RW_NONINTERLEAVED #define My_SND_PCM_ACCESS_LAST \ SND_PCM_ACCESS_LAST #define My_snd_pcm_format_t snd_pcm_format_t #define My_SND_PCM_FORMAT_UNKNOWN SND_PCM_FORMAT_UNKNOWN #define My_SND_PCM_FORMAT_S8 SND_PCM_FORMAT_S8 #define My_SND_PCM_FORMAT_U8 SND_PCM_FORMAT_U8 #define My_SND_PCM_FORMAT_S16_LE SND_PCM_FORMAT_S16_LE #define My_SND_PCM_FORMAT_S16_BE SND_PCM_FORMAT_S16_BE #define My_SND_PCM_FORMAT_U16_LE SND_PCM_FORMAT_U16_LE #define My_SND_PCM_FORMAT_U16_BE SND_PCM_FORMAT_U16_BE #define My_SND_PCM_FORMAT_S24_LE SND_PCM_FORMAT_S24_LE #define My_SND_PCM_FORMAT_S24_BE SND_PCM_FORMAT_S24_BE #define My_SND_PCM_FORMAT_U24_LE SND_PCM_FORMAT_U24_LE #define My_SND_PCM_FORMAT_U24_BE SND_PCM_FORMAT_U24_BE #define My_SND_PCM_FORMAT_S32_LE SND_PCM_FORMAT_S32_LE #define My_SND_PCM_FORMAT_S32_BE SND_PCM_FORMAT_S32_BE #define My_SND_PCM_FORMAT_U32_LE SND_PCM_FORMAT_U32_LE #define My_SND_PCM_FORMAT_U32_BE SND_PCM_FORMAT_U32_BE #define My_SND_PCM_FORMAT_FLOAT_LE SND_PCM_FORMAT_FLOAT_LE #define My_SND_PCM_FORMAT_FLOAT_BE SND_PCM_FORMAT_FLOAT_BE #define My_SND_PCM_FORMAT_FLOAT64_LE SND_PCM_FORMAT_FLOAT64_LE #define My_SND_PCM_FORMAT_FLOAT64_BE SND_PCM_FORMAT_FLOAT64_BE #define My_SND_PCM_FORMAT_IEC958_SUBFRAME_LE \ SND_PCM_FORMAT_IEC958_SUBFRAME_LE #define My_SND_PCM_FORMAT_IEC958_SUBFRAME_BE \ SND_PCM_FORMAT_IEC958_SUBFRAME_BE #define My_SND_PCM_FORMAT_MU_LAW SND_PCM_FORMAT_MU_LAW #define My_SND_PCM_FORMAT_A_LAW SND_PCM_FORMAT_A_LAW #define My_SND_PCM_FORMAT_IMA_ADPCM SND_PCM_FORMAT_IMA_ADPCM #define My_SND_PCM_FORMAT_MPEG SND_PCM_FORMAT_MPEG #define My_SND_PCM_FORMAT_GSM SND_PCM_FORMAT_GSM #define My_SND_PCM_FORMAT_SPECIAL SND_PCM_FORMAT_SPECIAL #define My_SND_PCM_FORMAT_S24_3LE SND_PCM_FORMAT_S24_3LE #define My_SND_PCM_FORMAT_S24_3BE SND_PCM_FORMAT_S24_3BE #define My_SND_PCM_FORMAT_U24_3LE SND_PCM_FORMAT_U24_3LE #define My_SND_PCM_FORMAT_U24_3BE SND_PCM_FORMAT_U24_3BE #define My_SND_PCM_FORMAT_S20_3LE SND_PCM_FORMAT_S20_3LE #define My_SND_PCM_FORMAT_S20_3BE SND_PCM_FORMAT_S20_3BE #define My_SND_PCM_FORMAT_U20_3LE SND_PCM_FORMAT_U20_3LE #define My_SND_PCM_FORMAT_U20_3BE SND_PCM_FORMAT_U20_3BE #define My_SND_PCM_FORMAT_S18_3LE SND_PCM_FORMAT_S18_3LE #define My_SND_PCM_FORMAT_S18_3BE SND_PCM_FORMAT_S18_3BE #define My_SND_PCM_FORMAT_U18_3LE SND_PCM_FORMAT_U18_3LE #define My_SND_PCM_FORMAT_U18_3BE SND_PCM_FORMAT_U18_3BE #define My_SND_PCM_FORMAT_LAST SND_PCM_FORMAT_LAST #define My_SND_PCM_FORMAT_S16 SND_PCM_FORMAT_S16 #define My_SND_PCM_FORMAT_U16 SND_PCM_FORMAT_U16 #define My_SND_PCM_FORMAT_S24 SND_PCM_FORMAT_S24 #define My_SND_PCM_FORMAT_U24 SND_PCM_FORMAT_U24 #define My_SND_PCM_FORMAT_S32 SND_PCM_FORMAT_S32 #define My_SND_PCM_FORMAT_U32 SND_PCM_FORMAT_U32 #define My_SND_PCM_FORMAT_FLOAT SND_PCM_FORMAT_FLOAT #define My_SND_PCM_FORMAT_FLOAT64 SND_PCM_FORMAT_FLOAT64 #define My_SND_PCM_FORMAT_IEC958_SUBFRAME SND_PCM_FORMAT_FLOAT64 #define My_snd_pcm_uframes_t snd_pcm_uframes_t #define My_snd_pcm_sframes_t snd_pcm_sframes_t #define My_SND_PCM_NONBLOCK SND_PCM_NONBLOCK #define My_snd_pcm_open snd_pcm_open #define HaveMy_snd_pcm_open() (1) #define My_snd_pcm_close snd_pcm_close #define HaveMy_snd_pcm_close() (1) #define My_snd_pcm_hw_params_malloc snd_pcm_hw_params_malloc #define HaveMy_snd_pcm_hw_params_malloc() (1) #define My_snd_pcm_hw_params_free snd_pcm_hw_params_free #define HaveMy_snd_pcm_hw_params_free() (1) #define My_snd_pcm_hw_params_any snd_pcm_hw_params_any #define HaveMy_snd_pcm_hw_params_any() (1) #define My_snd_pcm_hw_params_set_access snd_pcm_hw_params_set_access #define HaveMy_snd_pcm_hw_params_set_access() (1) #define My_snd_pcm_hw_params_set_format snd_pcm_hw_params_set_format #define HaveMy_snd_pcm_hw_params_set_format() (1) #define My_snd_pcm_hw_params_set_rate_near \ snd_pcm_hw_params_set_rate_near #define HaveMy_snd_pcm_hw_params_set_rate_near() (1) #define My_snd_pcm_hw_params_set_channels \ snd_pcm_hw_params_set_channels #define HaveMy_snd_pcm_hw_params_set_channels() (1) #define My_snd_pcm_hw_params_set_buffer_size_near \ snd_pcm_hw_params_set_buffer_size_near #define HaveMy_snd_pcm_hw_params_set_buffer_size_near() (1) #define My_snd_pcm_hw_params_set_period_size_near \ snd_pcm_hw_params_set_period_size_near #define HaveMy_snd_pcm_hw_params_set_period_size_near() (1) #define My_snd_pcm_hw_params snd_pcm_hw_params #define HaveMy_snd_pcm_hw_params() (1) #define My_snd_pcm_sw_params_malloc snd_pcm_sw_params_malloc #define HaveMy_snd_pcm_sw_params_malloc() (1) #define My_snd_pcm_sw_params_free snd_pcm_sw_params_free #define HaveMy_snd_pcm_sw_params_free() (1) #define My_snd_pcm_sw_params_current snd_pcm_sw_params_current #define HaveMy_snd_pcm_sw_params_current() (1) #define My_snd_pcm_sw_params_set_start_threshold \ snd_pcm_sw_params_set_start_threshold #define HaveMy_snd_pcm_sw_params_set_start_threshold() (1) #define My_snd_pcm_sw_params_set_avail_min \ snd_pcm_sw_params_set_avail_min #define HaveMy_snd_pcm_sw_params_set_avail_min() (1) #define My_snd_pcm_sw_params_set_xfer_align \ snd_pcm_sw_params_set_xfer_align #define HaveMy_snd_pcm_sw_params_set_xfer_align() (1) #define My_snd_pcm_sw_params snd_pcm_sw_params #define HaveMy_snd_pcm_sw_params() (1) #define My_snd_pcm_nonblock snd_pcm_nonblock #define HaveMy_snd_pcm_nonblock() (1) #define My_snd_pcm_state snd_pcm_state #define HaveMy_snd_pcm_state() (1) #define My_snd_pcm_prepare snd_pcm_prepare #define HaveMy_snd_pcm_prepare() (1) #define My_snd_pcm_start snd_pcm_start #define HaveMy_snd_pcm_start() (1) #define My_snd_pcm_resume snd_pcm_resume #define HaveMy_snd_pcm_resume() (1) #define My_snd_pcm_avail_update snd_pcm_avail_update #define HaveMy_snd_pcm_avail_update() (1) #define My_snd_pcm_writei snd_pcm_writei #define HaveMy_snd_pcm_writei() (1) #define My_snd_pcm_drop snd_pcm_drop #define HaveMy_snd_pcm_drop() (1) #if RaspbianWorkAround #define My_snd_pcm_status_malloc snd_pcm_status_malloc #define HaveMy_snd_pcm_status_malloc() (1) #define My_snd_pcm_status snd_pcm_status #define HaveMy_snd_pcm_status() (1) #define My_snd_pcm_status_get_avail snd_pcm_status_get_avail #define HaveMy_snd_pcm_status_get_avail() (1) #endif #define My_snd_strerror snd_strerror #define HaveMy_snd_strerror() (1) #define MyCloseAlsaLib() #else static void *alsa_handle = NULL; LOCALVAR blnr DidAlsaLib = falseblnr; LOCALFUNC blnr HaveAlsaLib(void) { if (! DidAlsaLib) { alsa_handle = dlopen("libasound.so.2", RTLD_NOW); if (NULL == alsa_handle) { fprintf(stderr, "dlopen libasound failed\n"); } DidAlsaLib = trueblnr; } return (alsa_handle != NULL); } LOCALPROC MyCloseAlsaLib(void) { if (NULL != alsa_handle) { if (0 != dlclose(alsa_handle)) { fprintf(stderr, "dlclose libasound failed\n"); } alsa_handle = NULL; } } /* PCM handle */ typedef struct My__snd_pcm My_snd_pcm_t; /* PCM hardware configuration space container */ typedef struct My__snd_pcm_hw_params My_snd_pcm_hw_params_t; /* PCM software configuration container */ typedef struct My__snd_pcm_sw_params My_snd_pcm_sw_params_t; #if RaspbianWorkAround /* PCM status container */ typedef struct My__snd_pcm_status My_snd_pcm_status_t; #endif /* PCM state */ typedef enum My__snd_pcm_state { /* Open */ My_SND_PCM_STATE_OPEN = 0, /* Setup installed */ My_SND_PCM_STATE_SETUP, /* Ready to start */ My_SND_PCM_STATE_PREPARED, /* Running */ My_SND_PCM_STATE_RUNNING, /* Stopped: underrun (playback) or overrun (capture) detected */ My_SND_PCM_STATE_XRUN, /* Draining: running (playback) or stopped (capture) */ My_SND_PCM_STATE_DRAINING, /* Paused */ My_SND_PCM_STATE_PAUSED, /* Hardware is suspended */ My_SND_PCM_STATE_SUSPENDED, /* Hardware is disconnected */ My_SND_PCM_STATE_DISCONNECTED, My_SND_PCM_STATE_LAST = My_SND_PCM_STATE_DISCONNECTED } My_snd_pcm_state_t; /* PCM stream (direction) */ typedef enum My__snd_pcm_stream { /* Playback stream */ My_SND_PCM_STREAM_PLAYBACK = 0, /* Capture stream */ My_SND_PCM_STREAM_CAPTURE, My_SND_PCM_STREAM_LAST = My_SND_PCM_STREAM_CAPTURE } My_snd_pcm_stream_t; /* PCM access type */ typedef enum My__snd_pcm_access { /* mmap access with simple interleaved channels */ My_SND_PCM_ACCESS_MMAP_INTERLEAVED = 0, /* mmap access with simple non interleaved channels */ My_SND_PCM_ACCESS_MMAP_NONINTERLEAVED, /* mmap access with complex placement */ My_SND_PCM_ACCESS_MMAP_COMPLEX, /* snd_pcm_readi/snd_pcm_writei access */ My_SND_PCM_ACCESS_RW_INTERLEAVED, /* snd_pcm_readn/snd_pcm_writen access */ My_SND_PCM_ACCESS_RW_NONINTERLEAVED, My_SND_PCM_ACCESS_LAST = My_SND_PCM_ACCESS_RW_NONINTERLEAVED } My_snd_pcm_access_t; /* PCM sample format */ typedef enum My__snd_pcm_format { /* Unknown */ My_SND_PCM_FORMAT_UNKNOWN = -1, /* Signed 8 bit */ My_SND_PCM_FORMAT_S8 = 0, /* Unsigned 8 bit */ My_SND_PCM_FORMAT_U8, /* Signed 16 bit Little Endian */ My_SND_PCM_FORMAT_S16_LE, /* Signed 16 bit Big Endian */ My_SND_PCM_FORMAT_S16_BE, /* Unsigned 16 bit Little Endian */ My_SND_PCM_FORMAT_U16_LE, /* Unsigned 16 bit Big Endian */ My_SND_PCM_FORMAT_U16_BE, /* Signed 24 bit Little Endian using low three bytes in 32-bit word */ My_SND_PCM_FORMAT_S24_LE, /* Signed 24 bit Big Endian using low three bytes in 32-bit word */ My_SND_PCM_FORMAT_S24_BE, /* Unsigned 24 bit Little Endian using low three bytes in 32-bit word */ My_SND_PCM_FORMAT_U24_LE, /* Unsigned 24 bit Big Endian using low three bytes in 32-bit word */ My_SND_PCM_FORMAT_U24_BE, /* Signed 32 bit Little Endian */ My_SND_PCM_FORMAT_S32_LE, /* Signed 32 bit Big Endian */ My_SND_PCM_FORMAT_S32_BE, /* Unsigned 32 bit Little Endian */ My_SND_PCM_FORMAT_U32_LE, /* Unsigned 32 bit Big Endian */ My_SND_PCM_FORMAT_U32_BE, /* Float 32 bit Little Endian, Range -1.0 to 1.0 */ My_SND_PCM_FORMAT_FLOAT_LE, /* Float 32 bit Big Endian, Range -1.0 to 1.0 */ My_SND_PCM_FORMAT_FLOAT_BE, /* Float 64 bit Little Endian, Range -1.0 to 1.0 */ My_SND_PCM_FORMAT_FLOAT64_LE, /* Float 64 bit Big Endian, Range -1.0 to 1.0 */ My_SND_PCM_FORMAT_FLOAT64_BE, /* IEC-958 Little Endian */ My_SND_PCM_FORMAT_IEC958_SUBFRAME_LE, /* IEC-958 Big Endian */ My_SND_PCM_FORMAT_IEC958_SUBFRAME_BE, /* Mu-Law */ My_SND_PCM_FORMAT_MU_LAW, /* A-Law */ My_SND_PCM_FORMAT_A_LAW, /* Ima-ADPCM */ My_SND_PCM_FORMAT_IMA_ADPCM, /* MPEG */ My_SND_PCM_FORMAT_MPEG, /* GSM */ My_SND_PCM_FORMAT_GSM, /* Special */ My_SND_PCM_FORMAT_SPECIAL = 31, /* Signed 24bit Little Endian in 3bytes format */ My_SND_PCM_FORMAT_S24_3LE = 32, /* Signed 24bit Big Endian in 3bytes format */ My_SND_PCM_FORMAT_S24_3BE, /* Unsigned 24bit Little Endian in 3bytes format */ My_SND_PCM_FORMAT_U24_3LE, /* Unsigned 24bit Big Endian in 3bytes format */ My_SND_PCM_FORMAT_U24_3BE, /* Signed 20bit Little Endian in 3bytes format */ My_SND_PCM_FORMAT_S20_3LE, /* Signed 20bit Big Endian in 3bytes format */ My_SND_PCM_FORMAT_S20_3BE, /* Unsigned 20bit Little Endian in 3bytes format */ My_SND_PCM_FORMAT_U20_3LE, /* Unsigned 20bit Big Endian in 3bytes format */ My_SND_PCM_FORMAT_U20_3BE, /* Signed 18bit Little Endian in 3bytes format */ My_SND_PCM_FORMAT_S18_3LE, /* Signed 18bit Big Endian in 3bytes format */ My_SND_PCM_FORMAT_S18_3BE, /* Unsigned 18bit Little Endian in 3bytes format */ My_SND_PCM_FORMAT_U18_3LE, /* Unsigned 18bit Big Endian in 3bytes format */ My_SND_PCM_FORMAT_U18_3BE, My_SND_PCM_FORMAT_LAST = My_SND_PCM_FORMAT_U18_3BE, #if __BYTE_ORDER == __LITTLE_ENDIAN /* Signed 16 bit CPU endian */ My_SND_PCM_FORMAT_S16 = My_SND_PCM_FORMAT_S16_LE, /* Unsigned 16 bit CPU endian */ My_SND_PCM_FORMAT_U16 = My_SND_PCM_FORMAT_U16_LE, /* Signed 24 bit CPU endian */ My_SND_PCM_FORMAT_S24 = My_SND_PCM_FORMAT_S24_LE, /* Unsigned 24 bit CPU endian */ My_SND_PCM_FORMAT_U24 = My_SND_PCM_FORMAT_U24_LE, /* Signed 32 bit CPU endian */ My_SND_PCM_FORMAT_S32 = My_SND_PCM_FORMAT_S32_LE, /* Unsigned 32 bit CPU endian */ My_SND_PCM_FORMAT_U32 = My_SND_PCM_FORMAT_U32_LE, /* Float 32 bit CPU endian */ My_SND_PCM_FORMAT_FLOAT = My_SND_PCM_FORMAT_FLOAT_LE, /* Float 64 bit CPU endian */ My_SND_PCM_FORMAT_FLOAT64 = My_SND_PCM_FORMAT_FLOAT64_LE, /* IEC-958 CPU Endian */ My_SND_PCM_FORMAT_IEC958_SUBFRAME = My_SND_PCM_FORMAT_IEC958_SUBFRAME_LE #elif __BYTE_ORDER == __BIG_ENDIAN /* Signed 16 bit CPU endian */ My_SND_PCM_FORMAT_S16 = My_SND_PCM_FORMAT_S16_BE, /* Unsigned 16 bit CPU endian */ My_SND_PCM_FORMAT_U16 = My_SND_PCM_FORMAT_U16_BE, /* Signed 24 bit CPU endian */ My_SND_PCM_FORMAT_S24 = My_SND_PCM_FORMAT_S24_BE, /* Unsigned 24 bit CPU endian */ My_SND_PCM_FORMAT_U24 = My_SND_PCM_FORMAT_U24_BE, /* Signed 32 bit CPU endian */ My_SND_PCM_FORMAT_S32 = My_SND_PCM_FORMAT_S32_BE, /* Unsigned 32 bit CPU endian */ My_SND_PCM_FORMAT_U32 = My_SND_PCM_FORMAT_U32_BE, /* Float 32 bit CPU endian */ My_SND_PCM_FORMAT_FLOAT = My_SND_PCM_FORMAT_FLOAT_BE, /* Float 64 bit CPU endian */ My_SND_PCM_FORMAT_FLOAT64 = My_SND_PCM_FORMAT_FLOAT64_BE, /* IEC-958 CPU Endian */ My_SND_PCM_FORMAT_IEC958_SUBFRAME = My_SND_PCM_FORMAT_IEC958_SUBFRAME_BE #else #error "Unknown endian" #endif } My_snd_pcm_format_t; /* Unsigned frames quantity */ typedef unsigned long My_snd_pcm_uframes_t; /* Signed frames quantity */ typedef long My_snd_pcm_sframes_t; /* Non blocking mode (flag for open mode) \hideinitializer */ #define My_SND_PCM_NONBLOCK 0x00000001 typedef int (*snd_pcm_open_ProcPtr) (My_snd_pcm_t **pcm, const char *name, My_snd_pcm_stream_t stream, int mode); LOCALVAR snd_pcm_open_ProcPtr My_snd_pcm_open = NULL; LOCALVAR blnr Did_snd_pcm_open = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_open(void) { if (! Did_snd_pcm_open) { if (HaveAlsaLib()) { My_snd_pcm_open = (snd_pcm_open_ProcPtr)dlsym(alsa_handle, "snd_pcm_open"); if (NULL == My_snd_pcm_open) { fprintf(stderr, "dlsym snd_pcm_open failed\n"); } } Did_snd_pcm_open = trueblnr; } return (My_snd_pcm_open != NULL); } typedef int (*snd_pcm_close_ProcPtr)(My_snd_pcm_t *pcm); LOCALVAR snd_pcm_close_ProcPtr My_snd_pcm_close = NULL; LOCALVAR blnr Did_snd_pcm_close = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_close(void) { if (! Did_snd_pcm_close) { if (HaveAlsaLib()) { My_snd_pcm_close = (snd_pcm_close_ProcPtr)dlsym(alsa_handle, "snd_pcm_close"); if (NULL == My_snd_pcm_close) { fprintf(stderr, "dlsym snd_pcm_close failed\n"); } } Did_snd_pcm_close = trueblnr; } return (My_snd_pcm_close != NULL); } typedef int (*snd_pcm_hw_params_malloc_ProcPtr) (My_snd_pcm_hw_params_t **ptr); LOCALVAR snd_pcm_hw_params_malloc_ProcPtr My_snd_pcm_hw_params_malloc = NULL; LOCALVAR blnr Did_snd_pcm_hw_params_malloc = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_hw_params_malloc(void) { if (! Did_snd_pcm_hw_params_malloc) { if (HaveAlsaLib()) { My_snd_pcm_hw_params_malloc = (snd_pcm_hw_params_malloc_ProcPtr) dlsym(alsa_handle, "snd_pcm_hw_params_malloc"); if (NULL == My_snd_pcm_hw_params_malloc) { fprintf(stderr, "dlsym snd_pcm_hw_params_malloc failed\n"); } } Did_snd_pcm_hw_params_malloc = trueblnr; } return (My_snd_pcm_hw_params_malloc != NULL); } typedef void (*snd_pcm_hw_params_free_ProcPtr) (My_snd_pcm_hw_params_t *obj); LOCALVAR snd_pcm_hw_params_free_ProcPtr My_snd_pcm_hw_params_free = NULL; LOCALVAR blnr Did_snd_pcm_hw_params_free = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_hw_params_free(void) { if (! Did_snd_pcm_hw_params_free) { if (HaveAlsaLib()) { My_snd_pcm_hw_params_free = (snd_pcm_hw_params_free_ProcPtr) dlsym(alsa_handle, "snd_pcm_hw_params_free"); if (NULL == My_snd_pcm_hw_params_free) { fprintf(stderr, "dlsym snd_pcm_hw_params_free failed\n"); } } Did_snd_pcm_hw_params_free = trueblnr; } return (My_snd_pcm_hw_params_free != NULL); } typedef int (*snd_pcm_hw_params_any_ProcPtr) (My_snd_pcm_t *pcm, My_snd_pcm_hw_params_t *params); LOCALVAR snd_pcm_hw_params_any_ProcPtr My_snd_pcm_hw_params_any = NULL; LOCALVAR blnr Did_snd_pcm_hw_params_any = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_hw_params_any(void) { if (! Did_snd_pcm_hw_params_any) { if (HaveAlsaLib()) { My_snd_pcm_hw_params_any = (snd_pcm_hw_params_any_ProcPtr) dlsym(alsa_handle, "snd_pcm_hw_params_any"); if (NULL == My_snd_pcm_hw_params_any) { fprintf(stderr, "dlsym snd_pcm_hw_params_any failed\n"); } } Did_snd_pcm_hw_params_any = trueblnr; } return (My_snd_pcm_hw_params_any != NULL); } typedef int (*snd_pcm_hw_params_set_access_ProcPtr) (My_snd_pcm_t *pcm, My_snd_pcm_hw_params_t *params, My_snd_pcm_access_t _access); LOCALVAR snd_pcm_hw_params_set_access_ProcPtr My_snd_pcm_hw_params_set_access = NULL; LOCALVAR blnr Did_snd_pcm_hw_params_set_access = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_hw_params_set_access(void) { if (! Did_snd_pcm_hw_params_set_access) { if (HaveAlsaLib()) { My_snd_pcm_hw_params_set_access = (snd_pcm_hw_params_set_access_ProcPtr) dlsym(alsa_handle, "snd_pcm_hw_params_set_access"); if (NULL == My_snd_pcm_hw_params_set_access) { fprintf(stderr, "dlsym snd_pcm_hw_params_set_access failed\n"); } } Did_snd_pcm_hw_params_set_access = trueblnr; } return (My_snd_pcm_hw_params_set_access != NULL); } typedef int (*snd_pcm_hw_params_set_format_ProcPtr) (My_snd_pcm_t *pcm, My_snd_pcm_hw_params_t *params, My_snd_pcm_format_t val); LOCALVAR snd_pcm_hw_params_set_format_ProcPtr My_snd_pcm_hw_params_set_format = NULL; LOCALVAR blnr Did_snd_pcm_hw_params_set_format = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_hw_params_set_format(void) { if (! Did_snd_pcm_hw_params_set_format) { if (HaveAlsaLib()) { My_snd_pcm_hw_params_set_format = (snd_pcm_hw_params_set_format_ProcPtr) dlsym(alsa_handle, "snd_pcm_hw_params_set_format"); if (NULL == My_snd_pcm_hw_params_set_format) { fprintf(stderr, "dlsym snd_pcm_hw_params_set_format failed\n"); } } Did_snd_pcm_hw_params_set_format = trueblnr; } return (My_snd_pcm_hw_params_set_format != NULL); } typedef int (*snd_pcm_hw_params_set_rate_near_ProcPtr) (My_snd_pcm_t *pcm, My_snd_pcm_hw_params_t *params, unsigned int *val, int *dir); LOCALVAR snd_pcm_hw_params_set_rate_near_ProcPtr My_snd_pcm_hw_params_set_rate_near = NULL; LOCALVAR blnr Did_snd_pcm_hw_params_set_rate_near = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_hw_params_set_rate_near(void) { if (! Did_snd_pcm_hw_params_set_rate_near) { if (HaveAlsaLib()) { My_snd_pcm_hw_params_set_rate_near = (snd_pcm_hw_params_set_rate_near_ProcPtr) dlsym(alsa_handle, "snd_pcm_hw_params_set_rate_near"); if (NULL == My_snd_pcm_hw_params_set_rate_near) { fprintf(stderr, "dlsym snd_pcm_hw_params_set_rate_near failed\n"); } } Did_snd_pcm_hw_params_set_rate_near = trueblnr; } return (My_snd_pcm_hw_params_set_rate_near != NULL); } typedef int (*snd_pcm_hw_params_set_channels_ProcPtr) (My_snd_pcm_t *pcm, My_snd_pcm_hw_params_t *params, unsigned int val); LOCALVAR snd_pcm_hw_params_set_channels_ProcPtr My_snd_pcm_hw_params_set_channels = NULL; LOCALVAR blnr Did_snd_pcm_hw_params_set_channels = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_hw_params_set_channels(void) { if (! Did_snd_pcm_hw_params_set_channels) { if (HaveAlsaLib()) { My_snd_pcm_hw_params_set_channels = (snd_pcm_hw_params_set_channels_ProcPtr) dlsym(alsa_handle, "snd_pcm_hw_params_set_channels"); if (NULL == My_snd_pcm_hw_params_set_channels) { fprintf(stderr, "dlsym snd_pcm_hw_params_set_channels failed\n"); } } Did_snd_pcm_hw_params_set_channels = trueblnr; } return (My_snd_pcm_hw_params_set_channels != NULL); } typedef int (*snd_pcm_hw_params_set_buffer_size_near_ProcPtr) (My_snd_pcm_t *pcm, My_snd_pcm_hw_params_t *params, My_snd_pcm_uframes_t *val); LOCALVAR snd_pcm_hw_params_set_buffer_size_near_ProcPtr My_snd_pcm_hw_params_set_buffer_size_near = NULL; LOCALVAR blnr Did_snd_pcm_hw_params_set_buffer_size_near = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_hw_params_set_buffer_size_near(void) { if (! Did_snd_pcm_hw_params_set_buffer_size_near) { if (HaveAlsaLib()) { My_snd_pcm_hw_params_set_buffer_size_near = (snd_pcm_hw_params_set_buffer_size_near_ProcPtr) dlsym(alsa_handle, "snd_pcm_hw_params_set_buffer_size_near"); if (NULL == My_snd_pcm_hw_params_set_buffer_size_near) { fprintf(stderr, "dlsym snd_pcm_hw_params_set_buffer_size_near" " failed\n"); } } Did_snd_pcm_hw_params_set_buffer_size_near = trueblnr; } return (My_snd_pcm_hw_params_set_buffer_size_near != NULL); } typedef int (*snd_pcm_hw_params_set_period_size_near_ProcPtr) (My_snd_pcm_t *pcm, My_snd_pcm_hw_params_t *params, My_snd_pcm_uframes_t *val, int *dir); LOCALVAR snd_pcm_hw_params_set_period_size_near_ProcPtr My_snd_pcm_hw_params_set_period_size_near = NULL; LOCALVAR blnr Did_snd_pcm_hw_params_set_period_size_near = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_hw_params_set_period_size_near(void) { if (! Did_snd_pcm_hw_params_set_period_size_near) { if (HaveAlsaLib()) { My_snd_pcm_hw_params_set_period_size_near = (snd_pcm_hw_params_set_period_size_near_ProcPtr) dlsym(alsa_handle, "snd_pcm_hw_params_set_period_size_near"); if (NULL == My_snd_pcm_hw_params_set_period_size_near) { fprintf(stderr, "dlsym snd_pcm_hw_params_set_period_size_near" " failed\n"); } } Did_snd_pcm_hw_params_set_period_size_near = trueblnr; } return (My_snd_pcm_hw_params_set_period_size_near != NULL); } typedef int (*snd_pcm_hw_params_ProcPtr) (My_snd_pcm_t *pcm, My_snd_pcm_hw_params_t *params); LOCALVAR snd_pcm_hw_params_ProcPtr My_snd_pcm_hw_params = NULL; LOCALVAR blnr Did_snd_pcm_hw_params = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_hw_params(void) { if (! Did_snd_pcm_hw_params) { if (HaveAlsaLib()) { My_snd_pcm_hw_params = (snd_pcm_hw_params_ProcPtr) dlsym(alsa_handle, "snd_pcm_hw_params"); if (NULL == My_snd_pcm_hw_params) { fprintf(stderr, "dlsym snd_pcm_hw_params failed\n"); } } Did_snd_pcm_hw_params = trueblnr; } return (My_snd_pcm_hw_params != NULL); } typedef int (*snd_pcm_sw_params_malloc_ProcPtr) (My_snd_pcm_sw_params_t **ptr); LOCALVAR snd_pcm_sw_params_malloc_ProcPtr My_snd_pcm_sw_params_malloc = NULL; LOCALVAR blnr Did_snd_pcm_sw_params_malloc = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_sw_params_malloc(void) { if (! Did_snd_pcm_sw_params_malloc) { if (HaveAlsaLib()) { My_snd_pcm_sw_params_malloc = (snd_pcm_sw_params_malloc_ProcPtr) dlsym(alsa_handle, "snd_pcm_sw_params_malloc"); if (NULL == My_snd_pcm_sw_params_malloc) { fprintf(stderr, "dlsym snd_pcm_sw_params_malloc failed\n"); } } Did_snd_pcm_sw_params_malloc = trueblnr; } return (My_snd_pcm_sw_params_malloc != NULL); } typedef void (*snd_pcm_sw_params_free_ProcPtr) (My_snd_pcm_sw_params_t *obj); LOCALVAR snd_pcm_sw_params_free_ProcPtr My_snd_pcm_sw_params_free = NULL; LOCALVAR blnr Did_snd_pcm_sw_params_free = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_sw_params_free(void) { if (! Did_snd_pcm_sw_params_free) { if (HaveAlsaLib()) { My_snd_pcm_sw_params_free = (snd_pcm_sw_params_free_ProcPtr) dlsym(alsa_handle, "snd_pcm_sw_params_free"); if (NULL == My_snd_pcm_sw_params_free) { fprintf(stderr, "dlsym snd_pcm_sw_params_free failed\n"); } } Did_snd_pcm_sw_params_free = trueblnr; } return (My_snd_pcm_sw_params_free != NULL); } typedef int (*snd_pcm_sw_params_current_ProcPtr) (My_snd_pcm_t *pcm, My_snd_pcm_sw_params_t *params); LOCALVAR snd_pcm_sw_params_current_ProcPtr My_snd_pcm_sw_params_current = NULL; LOCALVAR blnr Did_snd_pcm_sw_params_current = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_sw_params_current(void) { if (! Did_snd_pcm_sw_params_current) { if (HaveAlsaLib()) { My_snd_pcm_sw_params_current = (snd_pcm_sw_params_current_ProcPtr) dlsym(alsa_handle, "snd_pcm_sw_params_current"); if (NULL == My_snd_pcm_sw_params_current) { fprintf(stderr, "dlsym snd_pcm_sw_params_current failed\n"); } } Did_snd_pcm_sw_params_current = trueblnr; } return (My_snd_pcm_sw_params_current != NULL); } typedef int (*snd_pcm_sw_params_set_start_threshold_ProcPtr) (My_snd_pcm_t *pcm, My_snd_pcm_sw_params_t *params, My_snd_pcm_uframes_t val); LOCALVAR snd_pcm_sw_params_set_start_threshold_ProcPtr My_snd_pcm_sw_params_set_start_threshold = NULL; LOCALVAR blnr Did_snd_pcm_sw_params_set_start_threshold = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_sw_params_set_start_threshold(void) { if (! Did_snd_pcm_sw_params_set_start_threshold) { if (HaveAlsaLib()) { My_snd_pcm_sw_params_set_start_threshold = (snd_pcm_sw_params_set_start_threshold_ProcPtr) dlsym(alsa_handle, "snd_pcm_sw_params_set_start_threshold"); if (NULL == My_snd_pcm_sw_params_set_start_threshold) { fprintf(stderr, "dlsym snd_pcm_sw_params_set_start_threshold" " failed\n"); } } Did_snd_pcm_sw_params_set_start_threshold = trueblnr; } return (My_snd_pcm_sw_params_set_start_threshold != NULL); } typedef int (*snd_pcm_sw_params_set_avail_min_ProcPtr) (My_snd_pcm_t *pcm, My_snd_pcm_sw_params_t *params, My_snd_pcm_uframes_t val); LOCALVAR snd_pcm_sw_params_set_avail_min_ProcPtr My_snd_pcm_sw_params_set_avail_min = NULL; LOCALVAR blnr Did_snd_pcm_sw_params_set_avail_min = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_sw_params_set_avail_min(void) { if (! Did_snd_pcm_sw_params_set_avail_min) { if (HaveAlsaLib()) { My_snd_pcm_sw_params_set_avail_min = (snd_pcm_sw_params_set_avail_min_ProcPtr) dlsym(alsa_handle, "snd_pcm_sw_params_set_avail_min"); if (NULL == My_snd_pcm_sw_params_set_avail_min) { fprintf(stderr, "dlsym snd_pcm_sw_params_set_avail_min failed\n"); } } Did_snd_pcm_sw_params_set_avail_min = trueblnr; } return (My_snd_pcm_sw_params_set_avail_min != NULL); } typedef int (*snd_pcm_sw_params_set_xfer_align_ProcPtr) (My_snd_pcm_t *pcm, My_snd_pcm_sw_params_t *params, My_snd_pcm_uframes_t val); LOCALVAR snd_pcm_sw_params_set_xfer_align_ProcPtr My_snd_pcm_sw_params_set_xfer_align = NULL; LOCALVAR blnr Did_snd_pcm_sw_params_set_xfer_align = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_sw_params_set_xfer_align(void) { if (! Did_snd_pcm_sw_params_set_xfer_align) { if (HaveAlsaLib()) { My_snd_pcm_sw_params_set_xfer_align = (snd_pcm_sw_params_set_xfer_align_ProcPtr) dlsym(alsa_handle, "snd_pcm_sw_params_set_xfer_align"); if (NULL == My_snd_pcm_sw_params_set_xfer_align) { fprintf(stderr, "dlsym snd_pcm_sw_params_set_xfer_align failed\n"); } } Did_snd_pcm_sw_params_set_xfer_align = trueblnr; } return (My_snd_pcm_sw_params_set_xfer_align != NULL); } typedef int (*snd_pcm_sw_params_ProcPtr) (My_snd_pcm_t *pcm, My_snd_pcm_sw_params_t *params); LOCALVAR snd_pcm_sw_params_ProcPtr My_snd_pcm_sw_params = NULL; LOCALVAR blnr Did_snd_pcm_sw_params = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_sw_params(void) { if (! Did_snd_pcm_sw_params) { if (HaveAlsaLib()) { My_snd_pcm_sw_params = (snd_pcm_sw_params_ProcPtr) dlsym(alsa_handle, "snd_pcm_sw_params"); if (NULL == My_snd_pcm_sw_params) { fprintf(stderr, "dlsym snd_pcm_sw_params failed\n"); } } Did_snd_pcm_sw_params = trueblnr; } return (My_snd_pcm_sw_params != NULL); } typedef int (*snd_pcm_nonblock_ProcPtr) (My_snd_pcm_t *pcm, int nonblock); LOCALVAR snd_pcm_nonblock_ProcPtr My_snd_pcm_nonblock = NULL; LOCALVAR blnr Did_snd_pcm_nonblock = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_nonblock(void) { if (! Did_snd_pcm_nonblock) { if (HaveAlsaLib()) { My_snd_pcm_nonblock = (snd_pcm_nonblock_ProcPtr) dlsym(alsa_handle, "snd_pcm_nonblock"); if (NULL == My_snd_pcm_nonblock) { fprintf(stderr, "dlsym snd_pcm_nonblock failed\n"); } } Did_snd_pcm_nonblock = trueblnr; } return (My_snd_pcm_nonblock != NULL); } typedef My_snd_pcm_state_t (*snd_pcm_state_ProcPtr)(My_snd_pcm_t *pcm); LOCALVAR snd_pcm_state_ProcPtr My_snd_pcm_state = NULL; LOCALVAR blnr Did_snd_pcm_state = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_state(void) { if (! Did_snd_pcm_state) { if (HaveAlsaLib()) { My_snd_pcm_state = (snd_pcm_state_ProcPtr) dlsym(alsa_handle, "snd_pcm_state"); if (NULL == My_snd_pcm_state) { fprintf(stderr, "dlsym snd_pcm_state failed\n"); } } Did_snd_pcm_state = trueblnr; } return (My_snd_pcm_state != NULL); } typedef int (*snd_pcm_prepare_ProcPtr)(My_snd_pcm_t *pcm); LOCALVAR snd_pcm_prepare_ProcPtr My_snd_pcm_prepare = NULL; LOCALVAR blnr Did_snd_pcm_prepare = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_prepare(void) { if (! Did_snd_pcm_prepare) { if (HaveAlsaLib()) { My_snd_pcm_prepare = (snd_pcm_prepare_ProcPtr) dlsym(alsa_handle, "snd_pcm_prepare"); if (NULL == My_snd_pcm_prepare) { fprintf(stderr, "dlsym snd_pcm_prepare failed\n"); } } Did_snd_pcm_prepare = trueblnr; } return (My_snd_pcm_prepare != NULL); } typedef int (*snd_pcm_start_ProcPtr)(My_snd_pcm_t *pcm); LOCALVAR snd_pcm_start_ProcPtr My_snd_pcm_start = NULL; LOCALVAR blnr Did_snd_pcm_start = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_start(void) { if (! Did_snd_pcm_start) { if (HaveAlsaLib()) { My_snd_pcm_start = (snd_pcm_start_ProcPtr) dlsym(alsa_handle, "snd_pcm_start"); if (NULL == My_snd_pcm_start) { fprintf(stderr, "dlsym snd_pcm_start failed\n"); } } Did_snd_pcm_start = trueblnr; } return (My_snd_pcm_start != NULL); } typedef int (*snd_pcm_resume_ProcPtr)(My_snd_pcm_t *pcm); LOCALVAR snd_pcm_resume_ProcPtr My_snd_pcm_resume = NULL; LOCALVAR blnr Did_snd_pcm_resume = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_resume(void) { if (! Did_snd_pcm_resume) { if (HaveAlsaLib()) { My_snd_pcm_resume = (snd_pcm_resume_ProcPtr) dlsym(alsa_handle, "snd_pcm_resume"); if (NULL == My_snd_pcm_resume) { fprintf(stderr, "dlsym snd_pcm_resume failed\n"); } } Did_snd_pcm_resume = trueblnr; } return (My_snd_pcm_resume != NULL); } typedef My_snd_pcm_sframes_t (*snd_pcm_avail_update_ProcPtr) (My_snd_pcm_t *pcm); LOCALVAR snd_pcm_avail_update_ProcPtr My_snd_pcm_avail_update = NULL; LOCALVAR blnr Did_snd_pcm_avail_update = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_avail_update(void) { if (! Did_snd_pcm_avail_update) { if (HaveAlsaLib()) { My_snd_pcm_avail_update = (snd_pcm_avail_update_ProcPtr) dlsym(alsa_handle, "snd_pcm_avail_update"); if (NULL == My_snd_pcm_avail_update) { fprintf(stderr, "dlsym snd_pcm_avail_update failed\n"); } } Did_snd_pcm_avail_update = trueblnr; } return (My_snd_pcm_avail_update != NULL); } typedef My_snd_pcm_sframes_t (*snd_pcm_writei_ProcPtr) (My_snd_pcm_t *pcm, const void *buffer, My_snd_pcm_uframes_t size); LOCALVAR snd_pcm_writei_ProcPtr My_snd_pcm_writei = NULL; LOCALVAR blnr Did_snd_pcm_writei = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_writei(void) { if (! Did_snd_pcm_writei) { if (HaveAlsaLib()) { My_snd_pcm_writei = (snd_pcm_writei_ProcPtr) dlsym(alsa_handle, "snd_pcm_writei"); if (NULL == My_snd_pcm_writei) { fprintf(stderr, "dlsym snd_pcm_writei failed\n"); } } Did_snd_pcm_writei = trueblnr; } return (My_snd_pcm_writei != NULL); } typedef int (*snd_pcm_drop_ProcPtr)(My_snd_pcm_t *pcm); LOCALVAR snd_pcm_drop_ProcPtr My_snd_pcm_drop = NULL; LOCALVAR blnr Did_snd_pcm_drop = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_drop(void) { if (! Did_snd_pcm_drop) { if (HaveAlsaLib()) { My_snd_pcm_drop = (snd_pcm_drop_ProcPtr) dlsym(alsa_handle, "snd_pcm_drop"); if (NULL == My_snd_pcm_drop) { fprintf(stderr, "dlsym snd_pcm_drop failed\n"); } } Did_snd_pcm_drop = trueblnr; } return (My_snd_pcm_drop != NULL); } #if RaspbianWorkAround typedef int (*snd_pcm_status_malloc_ProcPtr) (My_snd_pcm_status_t **ptr); LOCALVAR snd_pcm_status_malloc_ProcPtr My_snd_pcm_status_malloc = NULL; LOCALVAR blnr Did_snd_pcm_status_malloc = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_status_malloc(void) { if (! Did_snd_pcm_status_malloc) { if (HaveAlsaLib()) { My_snd_pcm_status_malloc = (snd_pcm_status_malloc_ProcPtr) dlsym(alsa_handle, "snd_pcm_status_malloc"); if (NULL == My_snd_pcm_status_malloc) { fprintf(stderr, "dlsym snd_pcm_status_malloc failed\n"); } } Did_snd_pcm_status_malloc = trueblnr; } return (My_snd_pcm_status_malloc != NULL); } #endif #if RaspbianWorkAround typedef int (*snd_pcm_status_ProcPtr)(My_snd_pcm_t *pcm, My_snd_pcm_status_t *status); LOCALVAR snd_pcm_status_ProcPtr My_snd_pcm_status = NULL; LOCALVAR blnr Did_snd_pcm_status = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_status(void) { if (! Did_snd_pcm_status) { if (HaveAlsaLib()) { My_snd_pcm_status = (snd_pcm_status_ProcPtr) dlsym(alsa_handle, "snd_pcm_status"); if (NULL == My_snd_pcm_status) { fprintf(stderr, "dlsym snd_pcm_status failed\n"); } } Did_snd_pcm_status = trueblnr; } return (My_snd_pcm_status != NULL); } #endif #if RaspbianWorkAround typedef My_snd_pcm_uframes_t (*snd_pcm_status_get_avail_ProcPtr) (const My_snd_pcm_status_t *obj); LOCALVAR snd_pcm_status_get_avail_ProcPtr My_snd_pcm_status_get_avail = NULL; LOCALVAR blnr Did_snd_pcm_status_get_avail = falseblnr; LOCALFUNC blnr HaveMy_snd_pcm_status_get_avail(void) { if (! Did_snd_pcm_status_get_avail) { if (HaveAlsaLib()) { My_snd_pcm_status_get_avail = (snd_pcm_status_get_avail_ProcPtr) dlsym(alsa_handle, "snd_pcm_status_get_avail"); if (NULL == My_snd_pcm_status_get_avail) { fprintf(stderr, "dlsym snd_pcm_status_get_avail failed\n"); } } Did_snd_pcm_status_get_avail = trueblnr; } return (My_snd_pcm_status_get_avail != NULL); } #endif typedef const char * (*snd_strerror_ProcPtr)(int errnum); LOCALVAR snd_strerror_ProcPtr My_snd_strerror = NULL; LOCALVAR blnr Did_snd_strerror = falseblnr; LOCALFUNC blnr HaveMy_snd_strerror(void) { if (! Did_snd_strerror) { if (HaveAlsaLib()) { My_snd_strerror = (snd_strerror_ProcPtr) dlsym(alsa_handle, "snd_strerror"); if (NULL == My_snd_strerror) { fprintf(stderr, "dlsym snd_strerror failed\n"); } } Did_snd_strerror = trueblnr; } return (My_snd_strerror != NULL); } #endif /* The elaborate private buffer is mostly redundant since alsa has its own ring buffer. But using it keeps the code closer to the other ports. And anyway there is no guarantee just what size buffer you'll get from alsa. */ #if 4 == kLn2SoundSampSz LOCALPROC ConvertSoundBlockToNative(tpSoundSamp p) { int i; for (i = kOneBuffLen; --i >= 0; ) { *p++ -= 0x8000; } } #else #define ConvertSoundBlockToNative(p) #endif #define desired_alsa_buffer_size kAllBuffLen #define desired_alsa_period_size kOneBuffLen LOCALVAR char *alsadev_name = NULL; LOCALVAR My_snd_pcm_t *pcm_handle = NULL; LOCALVAR My_snd_pcm_uframes_t buffer_size; LOCALVAR My_snd_pcm_uframes_t period_size; LOCALVAR blnr MySound_StartPend = falseblnr; #if RaspbianWorkAround LOCALVAR My_snd_pcm_status_t *my_status = NULL; LOCALFUNC blnr HaveMyStatusAlloc(void) { if (NULL == my_status) { if (HaveMy_snd_pcm_status_malloc()) if (HaveMy_snd_pcm_status()) if (HaveMy_snd_pcm_status_get_avail()) { if (My_snd_pcm_status_malloc(&my_status) < 0) { my_status = NULL; /* just to make sure */ } else { /* snd_pcm_status_free(my_status); */ } } } return NULL != my_status; } #endif LOCALPROC MySound_WriteOut(void) { int retry_count = 32; label_retry: if (--retry_count > 0) { My_snd_pcm_sframes_t avail; int err; My_snd_pcm_state_t cur_state = My_snd_pcm_state(pcm_handle); if (My_SND_PCM_STATE_PREPARED == cur_state) { if (! MySound_StartPend) { if (TheFillOffset - ThePlayOffset >= kAllBuffLen) { MySound_StartPend = trueblnr; } } if (MySound_StartPend) { cur_state = My_SND_PCM_STATE_RUNNING; } } if (My_SND_PCM_STATE_RUNNING != cur_state) { switch (cur_state) { case My_SND_PCM_STATE_SETUP: case My_SND_PCM_STATE_XRUN: err = My_snd_pcm_prepare(pcm_handle); if (err < 0) { fprintf(stderr, "pcm prepare error: %s\n", My_snd_strerror(err)); } else { /* fprintf(stderr, "prepare succeeded\n"); */ goto label_retry; } break; case My_SND_PCM_STATE_SUSPENDED: err = My_snd_pcm_resume(pcm_handle); if (err < 0) { fprintf(stderr, "pcm resume error: %s\n", My_snd_strerror(err)); } else { /* fprintf(stderr, "resume succeeded\n"); */ goto label_retry; } break; case My_SND_PCM_STATE_DISCONNECTED: /* just abort ? */ break; case My_SND_PCM_STATE_PREPARED: /* leave */ break; default: fprintf(stderr, "unknown alsa pcm state\n"); break; } } else if ((avail = My_snd_pcm_avail_update(pcm_handle)) < 0) { fprintf(stderr, "pcm update error: %s\n", My_snd_strerror(avail)); } else { tpSoundSamp NextPlayPtr; ui4b PlayNowSize = 0; ui4b MaskedFillOffset = ThePlayOffset & kOneBuffMask; #if RaspbianWorkAround if ((avail > buffer_size) || (avail < 0)) { /* fprintf(stderr, "need avail workaround: %d\n", (int)avail); */ /* work around bug observed in Raspbian */ if (HaveMyStatusAlloc()) { if (My_snd_pcm_status(pcm_handle, my_status) >= 0) { avail = My_snd_pcm_status_get_avail(my_status); } } } #endif if (! MySound_StartPend) { My_snd_pcm_uframes_t used = buffer_size - avail; ui4b TotPendBuffs = used >> kLnOneBuffLen; if (TotPendBuffs < MinFilledSoundBuffs) { MinFilledSoundBuffs = TotPendBuffs; } /* fprintf(stderr, "buffer used %d\n", (int)used); */ } if (MaskedFillOffset != 0) { /* take care of left overs */ PlayNowSize = kOneBuffLen - MaskedFillOffset; NextPlayPtr = TheSoundBuffer + (ThePlayOffset & kAllBuffMask); } else if (0 != ((TheFillOffset - ThePlayOffset) >> kLnOneBuffLen)) { PlayNowSize = kOneBuffLen; NextPlayPtr = TheSoundBuffer + (ThePlayOffset & kAllBuffMask); } else { /* nothing to play now */ } if (PlayNowSize > avail) { /* This isn't supposed to be needed with nonblock mode. But in Ubuntu 7.04 running in Parallels, snd_pcm_writei seemed to block anyway. */ PlayNowSize = avail; } if (0 != PlayNowSize) { err = My_snd_pcm_writei( pcm_handle, NextPlayPtr, PlayNowSize); if (err < 0) { if ((- EAGAIN == err) || (- ESTRPIPE == err)) { /* buffer full, try again later */ /* fprintf(stderr, "pcm write: EAGAIN\n"); */ } else if (- EPIPE == err) { /* buffer seems to have emptied */ /* fprintf(stderr, "pcm write emptied\n"); */ goto label_retry; } else { fprintf(stderr, "pcm write error: %s\n", My_snd_strerror(err)); } } else { ThePlayOffset += err; goto label_retry; } } else if (MySound_StartPend) { MySound_StartPend = falseblnr; if ((err = My_snd_pcm_start(pcm_handle)) < 0) { fprintf(stderr, "pcm start error: %s\n", My_snd_strerror(err)); } } } } } LOCALPROC MySound_Start(void) { if (pcm_handle != NULL) { MySound_Start0(); } } LOCALPROC MySound_Stop(void) { if (pcm_handle != NULL) { My_snd_pcm_drop(pcm_handle); } } LOCALFUNC blnr HaveAlsaRoutines(void) { blnr IsOk = falseblnr; if (HaveMy_snd_pcm_open()) if (HaveMy_snd_pcm_close()) if (HaveMy_snd_pcm_hw_params_malloc()) if (HaveMy_snd_pcm_hw_params_free()) if (HaveMy_snd_pcm_hw_params_any()) if (HaveMy_snd_pcm_hw_params_set_access()) if (HaveMy_snd_pcm_hw_params_set_format()) if (HaveMy_snd_pcm_hw_params_set_rate_near()) if (HaveMy_snd_pcm_hw_params_set_channels()) if (HaveMy_snd_pcm_hw_params_set_buffer_size_near()) if (HaveMy_snd_pcm_hw_params_set_period_size_near()) if (HaveMy_snd_pcm_hw_params()) if (HaveMy_snd_pcm_sw_params_malloc()) if (HaveMy_snd_pcm_sw_params_free()) if (HaveMy_snd_pcm_sw_params_current()) if (HaveMy_snd_pcm_sw_params_set_start_threshold()) if (HaveMy_snd_pcm_sw_params_set_avail_min()) if (HaveMy_snd_pcm_sw_params()) if (HaveMy_snd_pcm_nonblock()) if (HaveMy_snd_pcm_state()) if (HaveMy_snd_pcm_prepare()) if (HaveMy_snd_pcm_start()) if (HaveMy_snd_pcm_resume()) if (HaveMy_snd_pcm_avail_update()) if (HaveMy_snd_pcm_writei()) if (HaveMy_snd_pcm_drop()) if (HaveMy_snd_strerror()) { IsOk = trueblnr; } return IsOk; } #if 4 == kLn2SoundSampSz #define MyDesiredFormat My_SND_PCM_FORMAT_S16 #else #define MyDesiredFormat My_SND_PCM_FORMAT_U8 #endif LOCALPROC MySound_Init0(void) { My_snd_pcm_hw_params_t *hw_params = NULL; My_snd_pcm_sw_params_t *sw_params = NULL; unsigned int rrate = SOUND_SAMPLERATE; int err; buffer_size = desired_alsa_buffer_size; period_size = desired_alsa_period_size; /* Open the sound device */ if (NULL == alsadev_name) { alsadev_name = getenv("AUDIODEV"); if (NULL == alsadev_name) { alsadev_name = strdup("default"); } } if ((err = My_snd_pcm_open(&pcm_handle, alsadev_name, My_SND_PCM_STREAM_PLAYBACK, My_SND_PCM_NONBLOCK)) < 0) { fprintf(stderr, "cannot open audio device %s (%s)\n", alsadev_name, My_snd_strerror(err)); pcm_handle = NULL; } else /* Set some hardware parameters */ if ((err = My_snd_pcm_hw_params_malloc(&hw_params)) < 0) { fprintf(stderr, "cannot allocate hardware parameter structure (%s)\n", My_snd_strerror(err)); hw_params = NULL; } else if ((err = My_snd_pcm_hw_params_any(pcm_handle, hw_params)) < 0) { fprintf(stderr, "cannot initialize hardware parameter structure (%s)\n", My_snd_strerror(err)); } else if ((err = My_snd_pcm_hw_params_set_access(pcm_handle, hw_params, My_SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf(stderr, "cannot set access type (%s)\n", My_snd_strerror(err)); } else if ((err = My_snd_pcm_hw_params_set_format(pcm_handle, hw_params, MyDesiredFormat)) < 0) { fprintf(stderr, "cannot set sample format (%s)\n", My_snd_strerror(err)); } else if ((err = My_snd_pcm_hw_params_set_rate_near(pcm_handle, hw_params, &rrate, NULL)) < 0) { fprintf(stderr, "cannot set sample rate (%s)\n", My_snd_strerror(err)); } else if ((err = My_snd_pcm_hw_params_set_channels(pcm_handle, hw_params, 1)) < 0) { fprintf(stderr, "cannot set channel count (%s)\n", My_snd_strerror(err)); } else if ((err = My_snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hw_params, &buffer_size)) < 0) { fprintf(stderr, "cannot set buffer size count (%s)\n", My_snd_strerror(err)); } else if ((err = My_snd_pcm_hw_params_set_period_size_near(pcm_handle, hw_params, &period_size, NULL)) < 0) { fprintf(stderr, "cannot set period size count (%s)\n", My_snd_strerror(err)); } else if ((err = My_snd_pcm_hw_params(pcm_handle, hw_params)) < 0) { fprintf(stderr, "cannot set parameters (%s)\n", My_snd_strerror(err)); } else { if (rrate != SOUND_SAMPLERATE) { fprintf(stderr, "Warning: sample rate is off by %i Hz\n", SOUND_SAMPLERATE - rrate); } #if 0 if (buffer_size != desired_alsa_buffer_size) { fprintf(stderr, "Warning: buffer size is off," " desired %li, actual %li\n", desired_alsa_buffer_size, buffer_size); } if (period_size != desired_alsa_period_size) { fprintf(stderr, "Warning: period size is off," " desired %li, actual %li\n", desired_alsa_period_size, period_size); } #endif My_snd_pcm_hw_params_free(hw_params); hw_params = NULL; /* Set some software parameters */ if ((err = My_snd_pcm_sw_params_malloc(&sw_params)) < 0) { fprintf(stderr, "cannot allocate software parameter structure (%s)\n", My_snd_strerror(err)); sw_params = NULL; } else if ((err = My_snd_pcm_sw_params_current(pcm_handle, sw_params)) < 0) { fprintf(stderr, "Unable to determine current" " sw_params for playback: %s\n", My_snd_strerror(err)); } else if ((err = My_snd_pcm_sw_params_set_start_threshold(pcm_handle, sw_params, 0x7FFFFFFF /* buffer_size - period_size */)) < 0) { fprintf(stderr, "Unable to set start threshold mode for playback: %s\n", My_snd_strerror(err)); } else #if 0 if ((err = My_snd_pcm_sw_params_set_avail_min(pcm_handle, sw_params, period_size)) < 0) { fprintf(stderr, "Unable to set avail min for playback: %s\n", My_snd_strerror(err)); } else #endif /* snd_pcm_sw_params_set_xfer_align deprecated, but call if available. According to one report, bad results in old version of alsa lib if not called. */ if (HaveMy_snd_pcm_sw_params_set_xfer_align() && ((err = My_snd_pcm_sw_params_set_xfer_align(pcm_handle, sw_params, 1)) < 0)) { fprintf(stderr, "Unable to set transfer align for playback: %s\n", My_snd_strerror(err)); } else if ((err = My_snd_pcm_sw_params(pcm_handle, sw_params)) < 0) { fprintf(stderr, "Unable to set sw params for playback: %s\n", My_snd_strerror(err)); } else { My_snd_pcm_sw_params_free(sw_params); sw_params = NULL; My_snd_pcm_nonblock(pcm_handle, 0); goto label_done; /* success */ } } /* clean up after failure */ if (sw_params != NULL) { My_snd_pcm_sw_params_free(sw_params); } if (hw_params != NULL) { My_snd_pcm_hw_params_free(hw_params); } if (pcm_handle != NULL) { My_snd_pcm_close(pcm_handle); pcm_handle = NULL; } label_done: ; } LOCALFUNC blnr MySound_Init(void) { if (HaveAlsaRoutines()) { MySound_Init0(); } return trueblnr; /* keep going, even if no sound */ } LOCALPROC MySound_UnInit(void) { if (NULL != pcm_handle) { if (HaveMy_snd_pcm_close()) { My_snd_pcm_close(pcm_handle); } pcm_handle = NULL; } MyCloseAlsaLib(); } GLOBALOSGLUPROC MySound_EndWrite(ui4r actL) { if (MySound_EndWrite0(actL)) { ConvertSoundBlockToNative(TheSoundBuffer + ((TheFillOffset - kOneBuffLen) & kAllBuffMask)); if (NULL != pcm_handle) { MySound_WriteOut(); } } } LOCALPROC MySound_SecondNotify(void) { if (NULL != pcm_handle) { MySound_SecondNotify0(); } } #define UsingAlsa 1 \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SGLUDDSP.h b/Mini vMac/mnvm_core/SGLUDDSP.h new file mode 100755 index 0000000..b09e22c --- /dev/null +++ b/Mini vMac/mnvm_core/SGLUDDSP.h @@ -0,0 +1 @@ +/* SGLUDDSP.h Copyright (C) 2012 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* Sound GLUe for "/Dev/DSP" OSS and related, accessed through "/dev/dsp" */ LOCALVAR int audio_fd = -1; LOCALVAR blnr audio_started; #if 4 == kLn2SoundSampSz LOCALPROC ConvertSoundBlockToNative(tpSoundSamp p) { int i; for (i = kOneBuffLen; --i >= 0; ) { *p++ -= 0x8000; } } #else #define ConvertSoundBlockToNative(p) #endif LOCALPROC MySound_WriteOut(void) { int retry_count = 32; label_retry: if (--retry_count > 0) { int err; struct audio_buf_info info; if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) != 0) { fprintf(stderr, "SNDCTL_DSP_GETOSPACE fails\n"); } else { tpSoundSamp NextPlayPtr; ui4b PlayNowSize = 0; ui4b MaskedFillOffset = ThePlayOffset & kOneBuffMask; ui4b PrivateBuffUsed = TheFillOffset - ThePlayOffset; int used = (info.fragstotal * info.fragsize) - info.bytes; if (audio_started) { ui4b TotPendBuffs = used >> kLnOneBuffSz; if (TotPendBuffs < MinFilledSoundBuffs) { MinFilledSoundBuffs = TotPendBuffs; } /* fprintf(stderr, "buffer used %d\n", (int)used); */ } else { if (PrivateBuffUsed >= kAllBuffLen - kOneBuffLen) { audio_started = trueblnr; } else { info.bytes = 0; } } if (MaskedFillOffset != 0) { /* take care of left overs */ PlayNowSize = kOneBuffLen - MaskedFillOffset; NextPlayPtr = TheSoundBuffer + (ThePlayOffset & kAllBuffMask); } else if (0 != ((TheFillOffset - ThePlayOffset) >> kLnOneBuffLen)) { PlayNowSize = kOneBuffLen; NextPlayPtr = TheSoundBuffer + (ThePlayOffset & kAllBuffMask); } else { /* nothing to play now */ } #if 4 == kLn2SoundSampSz PlayNowSize <<= 1; #endif if (PlayNowSize > info.bytes) { PlayNowSize = info.bytes; } if (0 != PlayNowSize) { err = write( audio_fd, NextPlayPtr, PlayNowSize); if (err < 0) { if (- EAGAIN == err) { /* buffer full, try again later */ fprintf(stderr, "pcm write: EAGAIN\n"); } else if (- EPIPE == err) { /* buffer seems to have emptied */ fprintf(stderr, "pcm write emptied\n"); goto label_retry; } else { fprintf(stderr, "audio_fd write error: %d\n", err); } } else { ThePlayOffset += err #if 4 == kLn2SoundSampSz >> 1 #endif ; goto label_retry; } } } } } LOCALPROC MySound_Start(void) { if (audio_fd >= 0) { MySound_Start0(); audio_started = falseblnr; } } LOCALPROC MySound_Stop(void) { if (audio_fd >= 0) { if (0 != ioctl(audio_fd, SNDCTL_DSP_RESET /* SNDCTL_DSP_HALT */, NULL)) { fprintf(stderr, "SNDCTL_DSP_RESET fails\n"); } } } #if 4 == kLn2SoundSampSz #define MyDesiredFormat AFMT_S16_NE #else #define MyDesiredFormat AFMT_U8 #endif LOCALFUNC blnr MySound_Init(void) { blnr IsOk = falseblnr; audio_fd = open(AudioDevPath, O_WRONLY, 0); if (audio_fd < 0) { fprintf(stderr, "open /dev/dsp fails: %d\n", audio_fd); } else { int fragment_value = (16 /* 16 fragments */ << 16) #if 4 == kLn2SoundSampSz | 10 /* of 1024 bytes */ #else | 9 /* of 512 bytes */ #endif ; int channels_value = 1; int fmt_value = MyDesiredFormat; int speed_value = SOUND_SAMPLERATE; /* fprintf(stderr, "open /dev/dsp works\n"); */ if (0 != ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_value)) { fprintf(stderr, "SNDCTL_DSP_SETFRAGMENT fails\n"); } else if ((0 != ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &channels_value)) || (channels_value != 1)) { fprintf(stderr, "SNDCTL_DSP_CHANNELS fails\n"); } else if ((0 != ioctl(audio_fd, SNDCTL_DSP_SETFMT, &fmt_value)) || (fmt_value != MyDesiredFormat)) { fprintf(stderr, "SNDCTL_DSP_SETFMT fails\n"); } else if ((0 != ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed_value)) || (speed_value != SOUND_SAMPLERATE)) { fprintf(stderr, "SNDCTL_DSP_SPEED fails\n"); } else { IsOk = trueblnr; } if (! IsOk) { (void) close(audio_fd); audio_fd = -1; } } return trueblnr; /* keep going, even if no sound */ } LOCALPROC MySound_UnInit(void) { if (audio_fd >= 0) { if (close(audio_fd) != 0) { fprintf(stderr, "close /dev/dsp fails\n"); } audio_fd = -1; } } GLOBALOSGLUPROC MySound_EndWrite(ui4r actL) { if (MySound_EndWrite0(actL)) { ConvertSoundBlockToNative(TheSoundBuffer + ((TheFillOffset - kOneBuffLen) & kAllBuffMask)); if (audio_fd >= 0) { MySound_WriteOut(); } } } LOCALPROC MySound_SecondNotify(void) { if (audio_fd >= 0) { MySound_SecondNotify0(); } } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SNDEMDEV.c b/Mini vMac/mnvm_core/SNDEMDEV.c index 3ed7b18..24f9dd4 100755 --- a/Mini vMac/mnvm_core/SNDEMDEV.c +++ b/Mini vMac/mnvm_core/SNDEMDEV.c @@ -1,213 +1 @@ -/* - SNDEMDEV.c - - Copyright (C) 2003 Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - SouND EMulated DEVice - - Emulation of Sound in the Mac Plus could go here. - - This code adapted from "Sound.c" in vMac by Philip Cummins. -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" - -#include "MYOSGLUE.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" -#endif - -#include "SNDEMDEV.h" - - -#if MySoundEnabled - -#define kSnd_Main_Offset 0x0300 -#define kSnd_Alt_Offset 0x5F00 - -#define kSnd_Main_Buffer (kRAM_Size - kSnd_Main_Offset) -#define kSnd_Alt_Buffer (kRAM_Size - kSnd_Alt_Offset) - -/* - approximate volume levels of vMac, so: - - x * vol_mult[SoundVolume] >> 16 - + vol_offset[SoundVolume] - = {approx} (x - kCenterSound) / (8 - SoundVolume) + kCenterSound; -*/ - -LOCALVAR const ui4b vol_mult[] = { - 8192, 9362, 10922, 13107, 16384, 21845, 32768 -}; - -LOCALVAR const trSoundSamp vol_offset[] = { -#if 3 == kLn2SoundSampSz - 112, 110, 107, 103, 96, 86, 64, 0 -#elif 4 == kLn2SoundSampSz - 28672, 28087, 27307, 26215, 24576, 21846, 16384, 0 -#else -#error "unsupported kLn2SoundSampSz" -#endif -}; - -LOCALVAR const ui4b SubTick_offset[kNumSubTicks] = { - 0, 25, 50, 90, 102, 115, 138, 161, - 185, 208, 231, 254, 277, 300, 323, 346 -}; - -LOCALVAR const ui3r SubTick_n[kNumSubTicks] = { - 25, 25, 40, 12, 13, 23, 23, 24, - 23, 23, 23, 23, 23, 23, 23, 24 -}; - -/* - One version of free form sound driver - spends around 18000 cycles writing - offsets 50 to 370, then around another 3000 - cycles writing 0 to 50. So be done - with 0 to 50 at end of second sixtieth. -*/ - -/* - Different in system 6.0.4: - spends around 23500 cycles writing - offsets 90 to 370, then around another 7500 - cycles writing 0 to 90. This is nastier, - because gets to be a very small gap - between where is being read and - where written. So read a bit in - advance for third subtick. -*/ - -/* - startup sound spends around 19500 cycles - writing offsets 0 to 370. presumably - writing offset 0 before it is read. -*/ - -LOCALVAR ui5b SoundInvertPhase = 0; -LOCALVAR ui4b SoundInvertState = 0; - -IMPORTFUNC ui4b GetSoundInvertTime(void); - -GLOBALPROC MacSound_SubTick(int SubTick) -{ - ui4r actL; - tpSoundSamp p; - ui4r i; - ui5b StartOffset = SubTick_offset[SubTick]; - ui4r n = SubTick_n[SubTick]; - unsigned long addy = -#ifdef SoundBuffer - (SoundBuffer == 0) ? kSnd_Alt_Buffer : -#endif - kSnd_Main_Buffer; - ui3p addr = addy + (2 * StartOffset) + RAM; - ui4b SoundInvertTime = GetSoundInvertTime(); - ui3b SoundVolume = SoundVolb0 - | (SoundVolb1 << 1) - | (SoundVolb2 << 2); - -#if dbglog_HAVE && 0 - dbglog_StartLine(); - dbglog_writeCStr("reading sound buffer "); - dbglog_writeHex(StartOffset); - dbglog_writeCStr(" to "); - dbglog_writeHex(StartOffset + n); - dbglog_writeReturn(); -#endif - -label_retry: - p = MySound_BeginWrite(n, &actL); - if (actL > 0) { - if (SoundDisable && (SoundInvertTime == 0)) { - for (i = 0; i < actL; i++) { -#if 0 - *p++ = 0x00; /* this is believed more accurate */ -#else - /* But this avoids more clicks. */ - *p++ = kCenterSound; -#endif - } - } else { - for (i = 0; i < actL; i++) { - /* Copy sound data, high byte of each word */ - *p++ = *addr -#if 4 == kLn2SoundSampSz - << 8 -#endif - ; - - /* Move the address on */ - addr += 2; - } - - if (SoundInvertTime != 0) { - ui5b PhaseIncr = (ui5b)SoundInvertTime * (ui5b)20; - p -= actL; - - for (i = 0; i < actL; i++) { - if (SoundInvertPhase < 704) { - ui5b OnPortion = 0; - ui5b LastPhase = 0; - do { - if (! SoundInvertState) { - OnPortion += - (SoundInvertPhase - LastPhase); - } - SoundInvertState = ! SoundInvertState; - LastPhase = SoundInvertPhase; - SoundInvertPhase += PhaseIncr; - } while (SoundInvertPhase < 704); - if (! SoundInvertState) { - OnPortion += 704 - LastPhase; - } - *p = (*p * OnPortion) / 704; - } else { - if (SoundInvertState) { - *p = 0; - } - } - SoundInvertPhase -= 704; - p++; - } - } - } - - if (SoundVolume < 7) { - /* - Usually have volume at 7, so this - is just for completeness. - */ - ui5b mult = (ui5b)vol_mult[SoundVolume]; - trSoundSamp offset = vol_offset[SoundVolume]; - - p -= actL; - for (i = 0; i < actL; i++) { - *p = (trSoundSamp)((ui5b)(*p) * mult >> 16) + offset; - ++p; - } - } - - MySound_EndWrite(actL); - n -= actL; - if (n > 0) { - goto label_retry; - } - } -} - -#endif +/* SNDEMDEV.c Copyright (C) 2003 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* SouND EMulated DEVice Emulation of Sound in the Mac Plus could go here. This code adapted from "Sound.c" in vMac by Philip Cummins. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "MINEM68K.h" #endif #include "SNDEMDEV.h" #if MySoundEnabled #define kSnd_Main_Offset 0x0300 #define kSnd_Alt_Offset 0x5F00 #define kSnd_Main_Buffer (kRAM_Size - kSnd_Main_Offset) #define kSnd_Alt_Buffer (kRAM_Size - kSnd_Alt_Offset) /* approximate volume levels of vMac, so: x * vol_mult[SoundVolume] >> 16 + vol_offset[SoundVolume] = {approx} (x - kCenterSound) / (8 - SoundVolume) + kCenterSound; */ LOCALVAR const ui4b vol_mult[] = { 8192, 9362, 10922, 13107, 16384, 21845, 32768 }; LOCALVAR const trSoundSamp vol_offset[] = { #if 3 == kLn2SoundSampSz 112, 110, 107, 103, 96, 86, 64, 0 #elif 4 == kLn2SoundSampSz 28672, 28087, 27307, 26215, 24576, 21846, 16384, 0 #else #error "unsupported kLn2SoundSampSz" #endif }; LOCALVAR const ui4b SubTick_offset[kNumSubTicks] = { 0, 25, 50, 90, 102, 115, 138, 161, 185, 208, 231, 254, 277, 300, 323, 346 }; LOCALVAR const ui3r SubTick_n[kNumSubTicks] = { 25, 25, 40, 12, 13, 23, 23, 24, 23, 23, 23, 23, 23, 23, 23, 24 }; /* One version of free form sound driver spends around 18000 cycles writing offsets 50 to 370, then around another 3000 cycles writing 0 to 50. So be done with 0 to 50 at end of second sixtieth. */ /* Different in system 6.0.4: spends around 23500 cycles writing offsets 90 to 370, then around another 7500 cycles writing 0 to 90. This is nastier, because gets to be a very small gap between where is being read and where written. So read a bit in advance for third subtick. */ /* startup sound spends around 19500 cycles writing offsets 0 to 370. presumably writing offset 0 before it is read. */ LOCALVAR ui5b SoundInvertPhase = 0; LOCALVAR ui4b SoundInvertState = 0; IMPORTFUNC ui4b GetSoundInvertTime(void); GLOBALPROC MacSound_SubTick(int SubTick) { ui4r actL; tpSoundSamp p; ui4r i; ui5b StartOffset = SubTick_offset[SubTick]; ui4r n = SubTick_n[SubTick]; unsigned long addy = #ifdef SoundBuffer (SoundBuffer == 0) ? kSnd_Alt_Buffer : #endif kSnd_Main_Buffer; #ifndef ln2mtb ui3p addr = addy + (2 * StartOffset) + RAM; #else CPTR addr = addy + (2 * StartOffset); #endif ui4b SoundInvertTime = GetSoundInvertTime(); ui3b SoundVolume = SoundVolb0 | (SoundVolb1 << 1) | (SoundVolb2 << 2); #if dbglog_HAVE && 0 dbglog_StartLine(); dbglog_writeCStr("reading sound buffer "); dbglog_writeHex(StartOffset); dbglog_writeCStr(" to "); dbglog_writeHex(StartOffset + n); dbglog_writeReturn(); #endif label_retry: p = MySound_BeginWrite(n, &actL); if (actL > 0) { if (SoundDisable && (SoundInvertTime == 0)) { for (i = 0; i < actL; i++) { #if 0 *p++ = 0x00; /* this is believed more accurate */ #else /* But this avoids more clicks. */ *p++ = kCenterSound; #endif } } else { for (i = 0; i < actL; i++) { /* Copy sound data, high byte of each word */ *p++ = #ifndef ln2mtb *addr #else get_vm_byte(addr) #endif #if 4 == kLn2SoundSampSz << 8 #endif ; /* Move the address on */ addr += 2; } if (SoundInvertTime != 0) { ui5b PhaseIncr = (ui5b)SoundInvertTime * (ui5b)20; p -= actL; for (i = 0; i < actL; i++) { if (SoundInvertPhase < 704) { ui5b OnPortion = 0; ui5b LastPhase = 0; do { if (! SoundInvertState) { OnPortion += (SoundInvertPhase - LastPhase); } SoundInvertState = ! SoundInvertState; LastPhase = SoundInvertPhase; SoundInvertPhase += PhaseIncr; } while (SoundInvertPhase < 704); if (! SoundInvertState) { OnPortion += 704 - LastPhase; } *p = (*p * OnPortion) / 704; } else { if (SoundInvertState) { *p = 0; } } SoundInvertPhase -= 704; p++; } } } if (SoundVolume < 7) { /* Usually have volume at 7, so this is just for completeness. */ ui5b mult = (ui5b)vol_mult[SoundVolume]; trSoundSamp offset = vol_offset[SoundVolume]; p -= actL; for (i = 0; i < actL; i++) { *p = (trSoundSamp)((ui5b)(*p) * mult >> 16) + offset; ++p; } } MySound_EndWrite(actL); n -= actL; if (n > 0) { goto label_retry; } } } #endif \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SNDEMDEV.h b/Mini vMac/mnvm_core/SNDEMDEV.h index a572136..ea8d2b1 100755 --- a/Mini vMac/mnvm_core/SNDEMDEV.h +++ b/Mini vMac/mnvm_core/SNDEMDEV.h @@ -1,25 +1 @@ -/* - SNDEMDEV.h - - Copyright (C) 2003 Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef SNDEMDEV_H -#error "header already included" -#else -#define SNDEMDEV_H -#endif - -#if MySoundEnabled -EXPORTPROC MacSound_SubTick(int SubTick); -#endif +/* SNDEMDEV.h Copyright (C) 2003 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef SNDEMDEV_H #error "header already included" #else #define SNDEMDEV_H #endif #if MySoundEnabled EXPORTPROC MacSound_SubTick(int SubTick); #endif \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SONYEMDV.c b/Mini vMac/mnvm_core/SONYEMDV.c index 96353f4..4f359bc 100755 --- a/Mini vMac/mnvm_core/SONYEMDV.c +++ b/Mini vMac/mnvm_core/SONYEMDV.c @@ -1,1463 +1 @@ -/* - SONYEMDV.c - - Copyright (C) 2009 Philip Cummins, Jesus A. Alvarez, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - SONY floppy disk EMulated DeVice - - The Sony hardware is not actually emulated. Instead the - ROM is patched to replace the Sony disk driver with - code that calls Mini vMac extensions implemented in - the file. - - Information neeeded to better support the Disk Copy 4.2 - format was found in libdc42.c of the Lisa Emulator Project - by Ray A. Arachelian, and adapted to Mini vMac - by Jesus A. Alvarez. -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" -#include "MYOSGLUE.h" -#include "ENDIANAC.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" -#include "MINEM68K.h" -#endif - -#include "SONYEMDV.h" - - -LOCALVAR ui5b vSonyMountedMask = 0; - -#define vSonyIsLocked(Drive_No) \ - ((vSonyWritableMask & ((ui5b)1 << (Drive_No))) == 0) -#define vSonyIsMounted(Drive_No) \ - ((vSonyMountedMask & ((ui5b)1 << (Drive_No))) != 0) - -LOCALFUNC blnr vSonyNextPendingInsert0(tDrive *Drive_No) -{ - /* find next drive to Mount */ - ui5b MountPending = vSonyInsertedMask & (~ vSonyMountedMask); - if (MountPending != 0) { - tDrive i; - for (i = 0; i < NumDrives; ++i) { - if ((MountPending & ((ui5b)1 << i)) != 0) { - *Drive_No = i; - return trueblnr; /* only one disk at a time */ - } - } - } - - return falseblnr; -} - -LOCALFUNC tMacErr CheckReadableDrive(tDrive Drive_No) -{ - tMacErr result; - - if (Drive_No >= NumDrives) { - result = mnvm_nsDrvErr; - } else if (! vSonyIsMounted(Drive_No)) { - result = mnvm_offLinErr; - } else { - result = mnvm_noErr; - } - - return result; -} - -LOCALFUNC tMacErr vSonyTransferVM(blnr IsWrite, - CPTR Buffera, tDrive Drive_No, - ui5r Sony_Start, ui5r Sony_Count, ui5r *Sony_ActCount) -{ - /* - Transfer data between emulated disk and emulated memory. Taking - into account that the emulated memory may not be contiguous in - real memory. (Though it generally is for macintosh emulation.) - */ - tMacErr result; - ui5b contig; - ui5r actual; - ui3p Buffer; - ui5r offset = Sony_Start; - ui5r n = Sony_Count; - -label_1: - if (0 == n) { - result = mnvm_noErr; - } else { - Buffer = get_real_address0(n, ! IsWrite, Buffera, &contig); - if (0 == contig) { - result = mnvm_miscErr; - } else { - result = vSonyTransfer(IsWrite, Buffer, Drive_No, - offset, contig, &actual); - offset += actual; - Buffera += actual; - n -= actual; - if (mnvm_noErr == result) { - goto label_1; - } - } - } - - if (nullpr != Sony_ActCount) { - *Sony_ActCount = Sony_Count - n; - } - return result; -} - -LOCALPROC MyMoveBytesVM(CPTR srcPtr, CPTR dstPtr, si5b byteCount) -{ - ui3p src; - ui3p dst; - ui5b contigSrc; - ui5b contigDst; - ui5r contig; - -label_1: - if (0 != byteCount) { - src = get_real_address0(byteCount, falseblnr, srcPtr, - &contigSrc); - dst = get_real_address0(byteCount, trueblnr, dstPtr, - &contigDst); - if ((0 == contigSrc) || (0 == contigDst)) { - ReportAbnormal("MyMoveBytesVM fails"); - } else { - contig = (contigSrc < contigDst) ? contigSrc : contigDst; - MyMoveBytes(src, dst, contig); - srcPtr += contig; - dstPtr += contig; - byteCount -= contig; - goto label_1; - } - } -} - -LOCALVAR ui5r ImageDataOffset[NumDrives]; - /* size of any header in disk image file */ -LOCALVAR ui5r ImageDataSize[NumDrives]; - /* size of disk image file contents */ - -#if Sony_SupportTags -LOCALVAR ui5r ImageTagOffset[NumDrives]; - /* offset to disk image file tags */ -#endif - -#if Sony_SupportDC42 -#define kDC42offset_diskName 0 -#define kDC42offset_dataSize 64 -#define kDC42offset_tagSize 68 -#define kDC42offset_dataChecksum 72 -#define kDC42offset_tagChecksum 76 -#define kDC42offset_diskFormat 80 -#define kDC42offset_formatByte 81 -#define kDC42offset_private 82 -#define kDC42offset_userData 84 -#endif - -#define ChecksumBlockSize 1024 - -#if Sony_SupportDC42 && Sony_WantChecksumsUpdated -LOCALFUNC tMacErr DC42BlockChecksum(tDrive Drive_No, - ui5r Sony_Start, ui5r Sony_Count, ui5r *r) -{ - tMacErr result; - ui5r n; - ui3b Buffer[ChecksumBlockSize]; - ui3b *p; - ui5b sum = 0; - ui5r offset = Sony_Start; - ui5r remaining = Sony_Count; - - while (0 != remaining) { - /* read a block */ - if (remaining > ChecksumBlockSize) { - n = ChecksumBlockSize; - } else { - n = remaining; - } - - result = vSonyTransfer(falseblnr, Buffer, Drive_No, offset, - n, nullpr); - if (mnvm_noErr != result) { - return result; - } - - offset += n; - remaining -= n; - - /* add to Checksum */ - p = Buffer; - n >>= 1; /* n = number of words */ - while (0 != n) { - --n; - /* ROR.l sum+word */ - sum += do_get_mem_word(p); - p += 2; - sum = (sum >> 1) | ((sum & 1) << 31); - } - } - - *r = sum; - return mnvm_noErr; -} -#endif - -#if Sony_SupportDC42 && Sony_WantChecksumsUpdated -#if Sony_SupportTags -#define SizeCheckSumsToUpdate 8 -#else -#define SizeCheckSumsToUpdate 4 -#endif -#endif - -#if Sony_WantChecksumsUpdated -LOCALPROC Drive_UpdateChecksums(tDrive Drive_No) -{ - if (! vSonyIsLocked(Drive_No)) { - ui5r DataOffset = ImageDataOffset[Drive_No]; -#if Sony_SupportDC42 - if (kDC42offset_userData == DataOffset) { - /* a disk copy 4.2 image */ - tMacErr result; - ui5r dataChecksum; - ui3b Buffer[SizeCheckSumsToUpdate]; - ui5r Sony_Count = SizeCheckSumsToUpdate; - ui5r DataSize = ImageDataSize[Drive_No]; - - /* Checksum image data */ - result = DC42BlockChecksum(Drive_No, - DataOffset, DataSize, &dataChecksum); - if (mnvm_noErr != result) { - ReportAbnormal("Failed to find dataChecksum"); - dataChecksum = 0; - } - do_put_mem_long(Buffer, dataChecksum); -#if Sony_SupportTags - { - ui5r tagChecksum; - ui5r TagOffset = ImageTagOffset[Drive_No]; - ui5r TagSize = - (0 == TagOffset) ? 0 : ((DataSize >> 9) * 12); - if (TagSize < 12) { - tagChecksum = 0; - } else { - /* - Checksum of tags doesn't include first block. - presumably because of bug in original disk - copy program. - */ - result = DC42BlockChecksum(Drive_No, - TagOffset + 12, TagSize - 12, &tagChecksum); - if (mnvm_noErr != result) { - ReportAbnormal("Failed to find tagChecksum"); - tagChecksum = 0; - } - } - do_put_mem_long(Buffer + 4, tagChecksum); - } -#endif - - /* write Checksums */ - vSonyTransfer(trueblnr, Buffer, Drive_No, - kDC42offset_dataChecksum, Sony_Count, nullpr); - } -#endif - } -} -#endif - -#define checkheaderoffset 0 -#define checkheadersize 128 - -#define Sony_SupportOtherFormats Sony_SupportDC42 - -LOCALFUNC tMacErr vSonyNextPendingInsert(tDrive *Drive_No) -{ - tDrive i; - tMacErr result; - ui5r L; - - if (! vSonyNextPendingInsert0(&i)) { - result = mnvm_nsDrvErr; - } else { - result = vSonyGetSize(i, &L); - if (mnvm_noErr == result) { - /* first, set up for default format */ - ui5r DataOffset = 0; - ui5r DataSize = L; -#if Sony_SupportTags - ui5r TagOffset = 0; -#endif - -#if Sony_SupportOtherFormats -#if IncludeSonyRawMode - if (! vSonyRawMode) -#endif - { - ui5r DataOffset0; - ui5r DataSize0; - ui5r TagOffset0; - ui5r TagSize0; - ui3b Temp[checkheadersize]; - ui5r Sony_Count = checkheadersize; - blnr gotFormat = falseblnr; - - result = vSonyTransfer(falseblnr, Temp, i, - checkheaderoffset, Sony_Count, nullpr); - if (mnvm_noErr == result) { -#if Sony_SupportDC42 - /* Detect Disk Copy 4.2 image */ - if (0x0100 == do_get_mem_word( - &Temp[kDC42offset_private])) - { - /* DC42 signature found, check sizes */ - DataSize0 = do_get_mem_long( - &Temp[kDC42offset_dataSize]); - TagSize0 = do_get_mem_long( - &Temp[kDC42offset_tagSize]); - DataOffset0 = kDC42offset_userData; - TagOffset0 = DataOffset0 + DataSize0; - if (L >= (TagOffset0 + TagSize0)) - if (0 == (DataSize0 & 0x01FF)) - if ((DataSize0 >> 9) >= 4) - if (Temp[kDC42offset_diskName] < 64) - /* length of pascal string */ - { - if (0 == TagSize0) { - /* no tags */ - gotFormat = trueblnr; - } else if ((DataSize0 >> 9) * 12 - == TagSize0) - { - /* 12 byte tags */ - gotFormat = trueblnr; - } - if (gotFormat) { -#if Sony_VerifyChecksums /* mostly useful to check the Checksum code */ - ui5r dataChecksum; - ui5r tagChecksum; - ui5r dataChecksum0 = do_get_mem_long( - &Temp[kDC42offset_dataChecksum]); - ui5r tagChecksum0 = do_get_mem_long( - &Temp[kDC42offset_tagChecksum]); - result = DC42BlockChecksum(i, - DataOffset0, DataSize0, - &dataChecksum); - if (TagSize0 >= 12) { - result = DC42BlockChecksum(i, - TagOffset0 + 12, TagSize0 - 12, - &tagChecksum); - } else { - tagChecksum = 0; - } - if (dataChecksum != dataChecksum0) { - ReportAbnormal("bad dataChecksum"); - } - if (tagChecksum != tagChecksum0) { - ReportAbnormal("bad tagChecksum"); - } -#endif - DataOffset = DataOffset0; - DataSize = DataSize0; -#if Sony_SupportTags - TagOffset = - (0 == TagSize0) ? 0 : TagOffset0; -#endif - -#if (! Sony_SupportTags) || (! Sony_WantChecksumsUpdated) - if (! vSonyIsLocked(i)) { -#if ! Sony_WantChecksumsUpdated - /* unconditionally revoke */ -#else - if (0 != TagSize0) -#endif - { - DiskRevokeWritable(i); - } - } -#endif - } - } - } -#endif /* Sony_SupportDC42 */ - } - } - if (mnvm_noErr == result) -#endif /* Sony_SupportOtherFormats */ - { - vSonyMountedMask |= ((ui5b)1 << i); - - ImageDataOffset[i] = DataOffset; - ImageDataSize[i] = DataSize; -#if Sony_SupportTags - ImageTagOffset[i] = TagOffset; -#endif - - *Drive_No = i; - } - } - - if (mnvm_noErr != result) { - (void) vSonyEject(i); - } - } - - return result; -} - -#define MinTicksBetweenInsert 60 - /* - if call PostEvent too frequently, insert events seem to get lost - */ - -LOCALVAR ui4r DelayUntilNextInsert; - -LOCALVAR CPTR MountCallBack = 0; - -/* This checks to see if a disk (image) has been inserted */ -GLOBALPROC Sony_Update (void) -{ - if (DelayUntilNextInsert != 0) { - --DelayUntilNextInsert; - } else { - if (MountCallBack != 0) { - tDrive i; - - if (mnvm_noErr == vSonyNextPendingInsert(&i)) { - ui5b data = i; - - if (vSonyIsLocked(i)) { - data |= ((ui5b)0x00FF) << 16; - } - - DiskInsertedPsuedoException(MountCallBack, data); - - DelayUntilNextInsert = MinTicksBetweenInsert; - } - } - } -} - -LOCALFUNC tMacErr Drive_Transfer(blnr IsWrite, CPTR Buffera, - tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, - ui5r *Sony_ActCount) -{ - tMacErr result; - - QuietEnds(); - - if (nullpr != Sony_ActCount) { - *Sony_ActCount = 0; - } - - result = CheckReadableDrive(Drive_No); - if (mnvm_noErr == result) { - if (IsWrite && vSonyIsLocked(Drive_No)) { - result = mnvm_vLckdErr; - } else { - ui5r DataSize = ImageDataSize[Drive_No]; - if (Sony_Start > DataSize) { - result = mnvm_eofErr; - } else { - blnr hit_eof = falseblnr; - ui5r L = DataSize - Sony_Start; - if (L >= Sony_Count) { - L = Sony_Count; - } else { - hit_eof = trueblnr; - } - result = vSonyTransferVM(IsWrite, Buffera, Drive_No, - ImageDataOffset[Drive_No] + Sony_Start, L, - Sony_ActCount); - if ((mnvm_noErr == result) && hit_eof) { - result = mnvm_eofErr; - } - } - } - } - - return result; -} - -LOCALVAR blnr QuitOnEject = falseblnr; - -GLOBALPROC Sony_SetQuitOnEject(void) -{ - QuitOnEject = trueblnr; -} - -LOCALFUNC tMacErr Drive_Eject(tDrive Drive_No) -{ - tMacErr result; - - result = CheckReadableDrive(Drive_No); - if (mnvm_noErr == result) { - vSonyMountedMask &= ~ ((ui5b)1 << Drive_No); -#if Sony_WantChecksumsUpdated - Drive_UpdateChecksums(Drive_No); -#endif - result = vSonyEject(Drive_No); - if (QuitOnEject != 0) { - if (! AnyDiskInserted()) { - ForceMacOff = trueblnr; - } - } - } - - return result; -} - -#if IncludeSonyNew -LOCALFUNC tMacErr Drive_EjectDelete(tDrive Drive_No) -{ - tMacErr result; - - result = CheckReadableDrive(Drive_No); - if (mnvm_noErr == result) { - if (vSonyIsLocked(Drive_No)) { - result = mnvm_vLckdErr; - } else { - vSonyMountedMask &= ~ ((ui5b)1 << Drive_No); - result = vSonyEjectDelete(Drive_No); - } - } - - return result; -} -#endif - -GLOBALPROC Sony_EjectAllDisks(void) -{ - tDrive i; - - vSonyMountedMask = 0; - for (i = 0; i < NumDrives; ++i) { - if (vSonyIsInserted(i)) { -#if Sony_WantChecksumsUpdated - Drive_UpdateChecksums(i); -#endif - (void) vSonyEject(i); - } - } -} - -GLOBALPROC Sony_Reset(void) -{ - DelayUntilNextInsert = 0; - QuitOnEject = falseblnr; - MountCallBack = 0; -} - -/* - Mini vMac extension for low level access to disk operations. -*/ - -#define kCmndDiskNDrives 1 -#define kCmndDiskRead 2 -#define kCmndDiskWrite 3 -#define kCmndDiskEject 4 -#define kCmndDiskGetSize 5 -#define kCmndDiskGetCallBack 6 -#define kCmndDiskSetCallBack 7 -#define kCmndDiskQuitOnEject 8 -#define kCmndDiskFeatures 9 -#define kCmndDiskNextPendingInsert 10 -#if IncludeSonyRawMode -#define kCmndDiskGetRawMode 11 -#define kCmndDiskSetRawMode 12 -#endif -#if IncludeSonyNew -#define kCmndDiskNew 13 -#define kCmndDiskGetNewWanted 14 -#define kCmndDiskEjectDelete 15 -#endif -#if IncludeSonyGetName -#define kCmndDiskGetName 16 -#endif - -#define kFeatureCmndDisk_RawMode 0 -#define kFeatureCmndDisk_New 1 -#define kFeatureCmndDisk_NewName 2 -#define kFeatureCmndDisk_GetName 3 - -#define kParamDiskNumDrives 8 -#define kParamDiskStart 8 -#define kParamDiskCount 12 -#define kParamDiskBuffer 16 -#define kParamDiskDrive_No 20 - -GLOBALPROC ExtnDisk_Access(CPTR p) -{ - tMacErr result = mnvm_controlErr; - - switch (get_vm_word(p + ExtnDat_commnd)) { - case kCmndVersion: - put_vm_word(p + ExtnDat_version, 2); - result = mnvm_noErr; - break; - case kCmndDiskNDrives: /* count drives */ - put_vm_word(p + kParamDiskNumDrives, NumDrives); - result = mnvm_noErr; - break; - case kCmndDiskRead: - { - ui5r Sony_ActCount; - CPTR Buffera = get_vm_long(p + kParamDiskBuffer); - tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No); - ui5r Sony_Start = get_vm_long(p + kParamDiskStart); - ui5r Sony_Count = get_vm_long(p + kParamDiskCount); - - result = Drive_Transfer(falseblnr, Buffera, Drive_No, - Sony_Start, Sony_Count, &Sony_ActCount); - - put_vm_long(p + kParamDiskCount, Sony_ActCount); - } - break; - case kCmndDiskWrite: - { - ui5r Sony_ActCount; - CPTR Buffera = get_vm_long(p + kParamDiskBuffer); - tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No); - ui5r Sony_Start = get_vm_long(p + kParamDiskStart); - ui5r Sony_Count = get_vm_long(p + kParamDiskCount); - - result = Drive_Transfer(trueblnr, Buffera, Drive_No, - Sony_Start, Sony_Count, &Sony_ActCount); - - put_vm_long(p + kParamDiskCount, Sony_ActCount); - } - break; - case kCmndDiskEject: - { - tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No); - result = Drive_Eject(Drive_No); - } - break; - case kCmndDiskGetSize: - { - tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No); - - result = CheckReadableDrive(Drive_No); - if (mnvm_noErr == result) { - put_vm_long(p + kParamDiskCount, - ImageDataSize[Drive_No]); - result = mnvm_noErr; - } - } - break; - case kCmndDiskGetCallBack: - put_vm_long(p + kParamDiskBuffer, MountCallBack); - result = mnvm_noErr; - break; - case kCmndDiskSetCallBack: - MountCallBack = get_vm_long(p + kParamDiskBuffer); - result = mnvm_noErr; - break; - case kCmndDiskQuitOnEject: - QuitOnEject = trueblnr; - result = mnvm_noErr; - break; - case kCmndDiskFeatures: - { - ui5r v = (0 -#if IncludeSonyRawMode - | ((ui5b)1 << kFeatureCmndDisk_RawMode) -#endif -#if IncludeSonyNew - | ((ui5b)1 << kFeatureCmndDisk_New) -#endif -#if IncludeSonyNameNew - | ((ui5b)1 << kFeatureCmndDisk_NewName) -#endif -#if IncludeSonyGetName - | ((ui5b)1 << kFeatureCmndDisk_GetName) -#endif - ); - - put_vm_long(p + ExtnDat_params + 0, v); - result = mnvm_noErr; - } - break; - case kCmndDiskNextPendingInsert: - { - tDrive i; - - result = vSonyNextPendingInsert(&i); - if (mnvm_noErr == result) { - put_vm_word(p + kParamDiskDrive_No, i); - } - } - break; -#if IncludeSonyRawMode - case kCmndDiskGetRawMode: - put_vm_word(p + kParamDiskBuffer, vSonyRawMode); - result = mnvm_noErr; - break; - case kCmndDiskSetRawMode: - vSonyRawMode = get_vm_word(p + kParamDiskBuffer); - result = mnvm_noErr; - break; -#endif -#if IncludeSonyNew - case kCmndDiskNew: - { - ui5b count = get_vm_long(p + ExtnDat_params + 0); - tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 4); - /* reserved word at offset 6, should be zero */ - - result = mnvm_noErr; - -#if IncludePbufs - if (Pbuf_No != NotAPbuf) { - result = CheckPbuf(Pbuf_No); - if (mnvm_noErr == result) { - vSonyNewDiskWanted = trueblnr; - vSonyNewDiskSize = count; -#if IncludeSonyNameNew - if (vSonyNewDiskName != NotAPbuf) { - PbufDispose(vSonyNewDiskName); - } - vSonyNewDiskName = Pbuf_No; -#else - PbufDispose(Pbuf_No); -#endif - } - } else -#endif - { - vSonyNewDiskWanted = trueblnr; - vSonyNewDiskSize = count; - } - } - break; - case kCmndDiskGetNewWanted: - put_vm_word(p + kParamDiskBuffer, vSonyNewDiskWanted); - result = mnvm_noErr; - break; - case kCmndDiskEjectDelete: - { - tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No); - result = Drive_EjectDelete(Drive_No); - } - break; -#endif -#if IncludeSonyGetName - case kCmndDiskGetName: - { - tDrive Drive_No = get_vm_word(p + ExtnDat_params + 0); - /* reserved word at offset 2, should be zero */ - result = CheckReadableDrive(Drive_No); - if (mnvm_noErr == result) { - tPbuf Pbuf_No; - result = vSonyGetName(Drive_No, &Pbuf_No); - put_vm_word(p + ExtnDat_params + 4, Pbuf_No); - } - } - break; -#endif - } - - put_vm_word(p + ExtnDat_result, result); -} - - -/* - Mini vMac extension that implements most of the logic - of the replacement disk driver patched into the emulated ROM. - (sony_driver in ROMEMDEV.c) - - This logic used to be completely contained in the 68k code - of the replacement driver, using only the low level - disk access extension. -*/ - -/* Sony Variable Drive Setting Offsets */ - -#define kTrack 0 /* Current Track */ -#define kWriteProt 2 /* FF if Write Protected, 00 if readable */ -#define kDiskInPlace 3 - /* - 00 = No Disk, 01 = Disk In, - 2 = MacOS Read, FC-FF = Just Ejected - */ -#define kInstalled 4 - /* 00 = Unknown, 01 = Installed, FF = Not Installed */ -#define kSides 5 - /* 00 if Single Sided Drive, FF if Doubled Sided Drive */ -#define kQLink 6 /* Link to Next Drive */ -#define kQType 10 /* Drive Type (0 = Size Saved, 1 = Very Large) */ -#define kQDriveNo 12 /* Drive Number (1 = Internal, 2 = External) */ -#define kQRefNum 14 - /* Driver Reference Number (-5 for .Sony, FFFB) */ -#define kQFSID 16 /* File System ID (0 = MacOS) */ -#define kQDrvSz 18 /* size, low-order word */ -#define kQDrvSz2 20 /* size, hi-order word */ - -#define kTwoSideFmt 18 - /* FF if double-sided format, 00 if single-sided format */ -#define kNewIntf 19 - /* FF if new 800K interface or 00 if old 400K interface */ -#define kDriveErrs 20 /* Drive Soft Errors */ - -/* Sony Driver Control Call csCodes */ - -#define kKillIO 1 -#define kVerifyDisk 5 -#define kFormatDisk 6 -#define kEjectDisk 7 -#define kSetTagBuffer 8 -#define kTrackCacheControl 9 -#define kGetIconID 20 -#define kDriveIcon 21 -#define kMediaIcon 22 -#define kDriveInfo 23 -#define kFormatCopy 21315 - -/* Sony Driver Status Call csCodes */ - -#define kReturnFormatList 6 -#define kDriveStatus 8 -#define kMFMStatus 10 -#define kDuplicatorVersionSupport 17494 - -/* Parameter Block Offsets */ - -#define kqLink 0 -#define kqType 4 -#define kioTrap 6 -#define kioCmdAddr 8 -#define kioCompletion 12 -#define kioResult 16 -#define kioNamePtr 18 -#define kioVRefNum 22 -#define kioRefNum 24 -#define kcsCode 26 -#define kcsParam 28 -#define kioBuffer 32 /* Buffer to store data into */ -#define kioReqCount 36 /* Requested Number of Bytes */ -#define kioActCount 40 /* Actual Number of Bytes obtained */ -#define kioPosMode 44 /* Positioning Mode */ -#define kioPosOffset 46 /* Position Offset */ - -/* Positioning Modes */ - -#define kfsAtMark 0 /* At Mark (Ignore PosOffset) */ -#define kfsFromStart 1 /* At Start (PosOffset is absolute) */ -#define kfsFromLEOF 2 /* From Logical End of File - PosOffset */ -#define kfsFromMark 3 /* At Mark + PosOffset */ - -/* Device Control Entry Offsets */ - -#define kdCtlPosition 16 - -#if 0 -struct MyDriverDat_R { - ui5b zeroes[4]; /* 0 */ - ui5b checkval; /* 16 */ - ui5b pokeaddr; /* 20 */ - ui4b NumDrives; /* 24 */ - ui4b DiskExtn; /* 26 */ - TMTask NullTask; /* 28 */ - /* total size must be <= FirstDriveVarsOffset */ -}; - -typedef struct MyDriverDat_R MyDriverDat_R; -#endif - -#define SonyVarsPtr 0x0134 - -#define FirstDriveVarsOffset 74 -#define EachDriveVarsSize 66 -#if CurEmMd <= kEmMd_128K -#define MinSonVarsSize 0x000000FA -#else -#define MinSonVarsSize 0x00000310 -#endif - -#define kcom_checkval 0x841339E2 - -#if Sony_SupportTags -LOCALVAR CPTR TheTagBuffer; -#endif - -LOCALFUNC ui5b DriveVarsLocation(tDrive Drive_No) -{ - CPTR SonyVars = get_vm_long(SonyVarsPtr); - - if (Drive_No < NumDrives) { - return SonyVars + FirstDriveVarsOffset - + EachDriveVarsSize * Drive_No; - } else { - return 0; - } -} - -LOCALFUNC tMacErr Sony_Mount(CPTR p) -{ - ui5b data = get_vm_long(p + ExtnDat_params + 0); - tMacErr result = mnvm_miscErr; - tDrive i = data & 0x0000FFFF; - CPTR dvl = DriveVarsLocation(i); - - if (0 == dvl) { - result = mnvm_nsDrvErr; - } else if (get_vm_byte(dvl + kDiskInPlace) == 0x00) { - ui5b L = ImageDataSize[i] >> 9; /* block count */ - - if ((L == 800) -#if CurEmMd > kEmMd_128K - || (L == 1600) -#endif - ) - { -#if CurEmMd <= kEmMd_128K - put_vm_byte(dvl + kTwoSideFmt, 0x00); - /* Drive i Single Format */ - put_vm_byte(dvl + kNewIntf, 0x00); - /* Drive i doesn't use new interface */ -#else - if (L == 800) { - put_vm_byte(dvl + kTwoSideFmt, 0x00); - /* Drive i Single Format */ - } else { - put_vm_byte(dvl + kTwoSideFmt, 0xFF); - /* Drive Double Format */ - } - put_vm_byte(dvl + kNewIntf, 0xFF); - /* Drive i uses new interface */ -#endif - put_vm_word(dvl + kQType, 0x00); /* Drive Type */ - put_vm_word(dvl + kDriveErrs, 0x0000); - /* Drive i has no errors */ - } else { - put_vm_word(dvl + kQRefNum, 0xFFFE); /* Driver */ - put_vm_word(dvl + kQType, 0x01); /* Drive Type */ - put_vm_word(dvl + kQDrvSz , L); - put_vm_word(dvl + kQDrvSz2, L >> 16); - } - - put_vm_byte(dvl + kWriteProt, data >> 16); - put_vm_byte(dvl + kDiskInPlace, 0x01); /* Drive Disk Inserted */ - - put_vm_long(p + ExtnDat_params + 4, i + 1); - /* PostEvent Disk Inserted eventMsg */ - result = mnvm_noErr; - } - /* else, if disk already in place, a mistake has been made */ - - return result; -} - -#if Sony_SupportTags -LOCALFUNC tMacErr Sony_PrimeTags(tDrive Drive_No, - ui5r Sony_Start, ui5r Sony_Count, blnr IsWrite) -{ - tMacErr result = mnvm_noErr; - ui5r TagOffset = ImageTagOffset[Drive_No]; - - if ((0 != TagOffset) && (Sony_Count > 0)) { - ui5r block = Sony_Start >> 9; - ui5r n = Sony_Count >> 9; /* is >= 1 if get here */ - - TagOffset += block * 12; - - if (0 != TheTagBuffer) { - ui5r count = 12 * n; - result = vSonyTransferVM(IsWrite, TheTagBuffer, Drive_No, - TagOffset, count, nullpr); - if (mnvm_noErr == result) { - MyMoveBytesVM(TheTagBuffer + count - 12, 0x02FC, 12); - } - } else { - if (! IsWrite) { - /* only need to read the last block tags */ - ui5r count = 12; - TagOffset += 12 * (n - 1); - result = vSonyTransferVM(falseblnr, 0x02FC, Drive_No, - TagOffset, count, nullpr); - } else { - ui5r count = 12; - ui4r BufTgFBkNum = get_vm_word(0x0302); - do { - put_vm_word(0x0302, BufTgFBkNum); - result = vSonyTransferVM(trueblnr, 0x02FC, Drive_No, - TagOffset, count, nullpr); - if (mnvm_noErr != result) { - goto label_fail; - } - BufTgFBkNum += 1; - TagOffset += 12; - } while (--n != 0); - } - } - } - -label_fail: - return result; -} -#endif - -/* Handles I/O to disks */ -LOCALFUNC tMacErr Sony_Prime(CPTR p) -{ - tMacErr result; - ui5r Sony_Count; - ui5r Sony_Start; - ui5r Sony_ActCount = 0; - CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 0); - CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 4); - tDrive Drive_No = get_vm_word(ParamBlk + kioVRefNum) - 1; - ui4r IOTrap = get_vm_word(ParamBlk + kioTrap); - CPTR dvl = DriveVarsLocation(Drive_No); - - if (0 == dvl) { - result = mnvm_nsDrvErr; - } else if (0xA002 != (IOTrap & 0xF0FE)) { - /* not read (0xA002) or write (0xA003) */ - result = mnvm_controlErr; - } else { - blnr IsWrite = (0 != (IOTrap & 0x0001)); - ui3b DiskInPlaceV = get_vm_byte(dvl + kDiskInPlace); - - if (DiskInPlaceV != 0x02) { - if (DiskInPlaceV == 0x01) { - put_vm_byte(dvl + kDiskInPlace, 0x02); /* Clamp Drive */ - } else { - result = mnvm_offLinErr; - goto label_fail; - /* - if don't check for this, will go right - ahead and boot off a disk that hasn't - been mounted yet by Sony_Update. - (disks other than the boot disk aren't - seen unless mounted by Sony_Update) - */ - } - } - -#if 0 - ui4r PosMode = get_vm_word(ParamBlk + kioPosMode); - - if (0 != (PosMode & 64)) { -#if ExtraAbnormalReports - /* - This is used when copy to floppy - disk with Finder. But not implemented - yet. - */ - ReportAbnormal("read verify mode requested"); -#endif - PosMode &= ~ 64; - } - - /* - Don't use the following code, because - according to Apple's Technical Note FL24 - the Device Manager takes care of this, - and puts the result in dCtlPosition. - (The RAMDisk example in Apple's sample - code serves to confirm this. Further - evidence found in Basilisk II emulator, - and disassembly of Mac Plus disk driver.) - */ - ui5r PosOffset = get_vm_long(ParamBlk + kioPosOffset); - switch (PosMode) { - case kfsAtMark: - Sony_Start = get_vm_long(DeviceCtl + kdCtlPosition); - break; - case kfsFromStart: - Sony_Start = PosOffset; - break; -#if 0 - /* - not valid for device driver. - actually only kfsFromStart seems to be used. - */ - case kfsFromLEOF: - Sony_Start = ImageDataSize[Drive_No] - + PosOffset; - break; -#endif - case kfsFromMark: - Sony_Start = PosOffset - + get_vm_long(DeviceCtl + kdCtlPosition); - break; - default: - ReportAbnormal("unknown PosMode"); - result = mnvm_paramErr; - goto label_fail; - break; - } -#endif - Sony_Start = get_vm_long(DeviceCtl + kdCtlPosition); - - Sony_Count = get_vm_long(ParamBlk + kioReqCount); - - if ((0 != (Sony_Start & 0x1FF)) - || (0 != (Sony_Count & 0x1FF))) - { - /* only whole blocks allowed */ - result = mnvm_paramErr; - } else if (IsWrite && (get_vm_byte(dvl + kWriteProt) != 0)) { - result = mnvm_wPrErr; - } else { - CPTR Buffera = get_vm_long(ParamBlk + kioBuffer); - result = Drive_Transfer(IsWrite, Buffera, Drive_No, - Sony_Start, Sony_Count, &Sony_ActCount); -#if Sony_SupportTags - if (mnvm_noErr == result) { - result = Sony_PrimeTags(Drive_No, - Sony_Start, Sony_Count, IsWrite); - } -#endif - put_vm_long(DeviceCtl + kdCtlPosition, - Sony_Start + Sony_ActCount); - } - } - -label_fail: - put_vm_word(ParamBlk + kioResult, result); - put_vm_long(ParamBlk + kioActCount, Sony_ActCount); - - if (mnvm_noErr != result) { - put_vm_word(0x0142 /* DskErr */, result); - } - return result; -} - -/* Implements control csCodes for the Sony driver */ -LOCALFUNC tMacErr Sony_Control(CPTR p) -{ - tMacErr result; - CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 0); - /* CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 4); */ - ui4r OpCode = get_vm_word(ParamBlk + kcsCode); - - if (kKillIO == OpCode) { - result = mnvm_miscErr; - } else if (kSetTagBuffer == OpCode) { -#if Sony_SupportTags - TheTagBuffer = get_vm_long(ParamBlk + kcsParam); - result = mnvm_noErr; -#else - result = mnvm_controlErr; -#endif - } else if (kTrackCacheControl == OpCode) { -#if CurEmMd <= kEmMd_128K - result = mnvm_controlErr; -#else -#if 0 - ui3r Arg1 = get_vm_byte(ParamBlk + kcsParam); - ui3r Arg2 = get_vm_byte(ParamBlk + kcsParam + 1); - if (0 == Arg1) { - /* disable track cache */ - } else { - /* enable track cache */ - } - if (Arg2 < 0) { - /* remove track cache */ - } else if (Arg2 > 0) { - /* install track cache */ - } -#endif - result = mnvm_noErr; - /* not implemented, but pretend we did it */ -#endif - } else { - tDrive Drive_No = get_vm_word(ParamBlk + kioVRefNum) - 1; - CPTR dvl = DriveVarsLocation(Drive_No); - - if (0 == dvl) { - result = mnvm_nsDrvErr; - } else if (get_vm_byte(dvl + kDiskInPlace) == 0) { - result = mnvm_offLinErr; - } else { - switch (OpCode) { - case kVerifyDisk : - result = mnvm_noErr; - break; - case kEjectDisk : - put_vm_byte(dvl + kWriteProt, 0x00); - /* Drive Writeable */ - put_vm_byte(dvl + kDiskInPlace, 0x00); - /* Drive No Disk */ -#if 0 - put_vm_byte(dvl + kTwoSideFmt, 0x00); - /* Drive Single Format (Initially) */ -#endif - put_vm_word(dvl + kQRefNum, 0xFFFB); - /* Drive i uses .Sony */ - - result = Drive_Eject(Drive_No); - break; - case kFormatDisk : - result = mnvm_noErr; - break; - case kDriveIcon : - if (get_vm_word(dvl + kQType) != 0) { - put_vm_long(ParamBlk + kcsParam, - my_disk_icon_addr); - result = mnvm_noErr; - } else { - result = mnvm_controlErr; - /* - Driver can't respond to - this Control call (-17) - */ - } - break; -#if CurEmMd >= kEmMd_SE - case kDriveInfo : - { - ui5b v; - - if (get_vm_word(dvl + kQType) != 0) { - v = 0x00000001; /* unspecified drive */ - } else { -#if CurEmMd <= kEmMd_128K - v = 0x00000002; /* 400K Drive */ -#else - v = 0x00000003; /* 800K Drive */ -#endif - } - if (Drive_No != 0) { - v += 0x00000900; - /* Secondary External Drive */ - } - put_vm_long(ParamBlk + kcsParam, v); - result = mnvm_noErr; /* No error (0) */ - } - break; -#endif - default : -#if ExtraAbnormalReports - if ((kGetIconID != OpCode) - && (kMediaIcon != OpCode) - && (kDriveInfo != OpCode)) - { - ReportAbnormal( - "unexpected OpCode in Sony_Control"); - } -#endif - result = mnvm_controlErr; - /* - Driver can't respond to - this Control call (-17) - */ - break; - } - } - } - - if (mnvm_noErr != result) { - put_vm_word(0x0142 /* DskErr */, result); - } - return result; -} - -/* Handles the DriveStatus call */ -LOCALFUNC tMacErr Sony_Status(CPTR p) -{ - tMacErr result; - CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 0); - /* CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 4); */ - ui4r OpCode = get_vm_word(ParamBlk + kcsCode); - - if (kDriveStatus == OpCode) { - tDrive Drive_No = get_vm_word(ParamBlk + kioVRefNum) - 1; - CPTR Src = DriveVarsLocation(Drive_No); - if (Src == 0) { - result = mnvm_nsDrvErr; - } else { - MyMoveBytesVM(Src, ParamBlk + kcsParam, 22); - result = mnvm_noErr; - } - } else { -#if ExtraAbnormalReports - if ((kReturnFormatList != OpCode) - && (kDuplicatorVersionSupport != OpCode)) - { - ReportAbnormal("unexpected OpCode in Sony_Control"); - } -#endif - result = mnvm_statusErr; - } - - if (mnvm_noErr != result) { - put_vm_word(0x0142 /* DskErr */, result); - } - return result; -} - -LOCALFUNC tMacErr Sony_Close(CPTR p) -{ -#if 0 - CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 0); - CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 4); -#endif - UnusedParam(p); - return mnvm_closErr; /* Can't Close Driver */ -} - -LOCALFUNC tMacErr Sony_OpenA(CPTR p) -{ - if (MountCallBack != 0) { - return mnvm_opWrErr; /* driver already open */ - } else { - ui5b L = FirstDriveVarsOffset + EachDriveVarsSize * NumDrives; - - if (L < MinSonVarsSize) { - L = MinSonVarsSize; - } - - put_vm_long(p + ExtnDat_params + 0, L); - - return mnvm_noErr; - } -} - -LOCALFUNC tMacErr Sony_OpenB(CPTR p) -{ - si4b i; - CPTR dvl; - - CPTR SonyVars = get_vm_long(p + ExtnDat_params + 4); - /* CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 24); (unused) */ -#if CurEmMd > kEmMd_128K - CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 28); -#endif - - put_vm_long(SonyVars + 16 /* checkval */, kcom_checkval); - put_vm_long(SonyVars + 20 /* pokeaddr */, kExtn_Block_Base); - put_vm_word(SonyVars + 24 /* NumDrives */, NumDrives); - put_vm_word(SonyVars + 26 /* DiskExtn */, kExtnDisk); - - put_vm_long(SonyVarsPtr, SonyVars); - - for (i = 0; (dvl = DriveVarsLocation(i)) != 0; ++i) { - put_vm_byte(dvl + kDiskInPlace, 0x00); /* Drive i No Disk */ - put_vm_byte(dvl + kInstalled, 0x01); /* Drive i Installed */ -#if CurEmMd <= kEmMd_128K - put_vm_byte(dvl + kSides, 0x00); - /* Drive i Single Sided */ -#else - put_vm_byte(dvl + kSides, 0xFF); - /* Drive i Double Sided */ -#endif - put_vm_word(dvl + kQDriveNo, i + 1); /* Drive i is Drive 1 */ - put_vm_word(dvl + kQRefNum, 0xFFFB); /* Drive i uses .Sony */ - } - - { - CPTR UTableBase = get_vm_long(0x011C); - - put_vm_long(UTableBase + 4 * 1, - get_vm_long(UTableBase + 4 * 4)); - /* use same drive for hard disk as used for sony floppies */ - } - -#if CurEmMd > kEmMd_128K - /* driver version in driver i/o queue header */ - put_vm_byte(DeviceCtl + 7, 1); -#endif - -#if CurEmMd <= kEmMd_128K - /* init Drive Queue */ - put_vm_word(0x308, 0); - put_vm_long(0x308 + 2, 0); - put_vm_long(0x308 + 6, 0); -#endif - - put_vm_long(p + ExtnDat_params + 8, - SonyVars + FirstDriveVarsOffset + kQLink); - put_vm_word(p + ExtnDat_params + 12, EachDriveVarsSize); - put_vm_word(p + ExtnDat_params + 14, NumDrives); - put_vm_word(p + ExtnDat_params + 16, 1); - put_vm_word(p + ExtnDat_params + 18, 0xFFFB); -#if CurEmMd <= kEmMd_128K - put_vm_long(p + ExtnDat_params + 20, 0); -#else - put_vm_long(p + ExtnDat_params + 20, SonyVars + 28 /* NullTask */); -#endif - -#if Sony_SupportTags - TheTagBuffer = 0; -#endif - - return mnvm_noErr; -} - -LOCALFUNC tMacErr Sony_OpenC(CPTR p) -{ - MountCallBack = get_vm_long(p + ExtnDat_params + 0) -#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) - | 0x40000000 -#endif - ; - return mnvm_noErr; -} - -#define kCmndSonyPrime 1 -#define kCmndSonyControl 2 -#define kCmndSonyStatus 3 -#define kCmndSonyClose 4 -#define kCmndSonyOpenA 5 -#define kCmndSonyOpenB 6 -#define kCmndSonyOpenC 7 -#define kCmndSonyMount 8 - -GLOBALPROC ExtnSony_Access(CPTR p) -{ - tMacErr result; - - switch (get_vm_word(p + ExtnDat_commnd)) { - case kCmndVersion: - put_vm_word(p + ExtnDat_version, 0); - result = mnvm_noErr; - break; - case kCmndSonyPrime: - result = Sony_Prime(p); - break; - case kCmndSonyControl: - result = Sony_Control(p); - break; - case kCmndSonyStatus: - result = Sony_Status(p); - break; - case kCmndSonyClose: - result = Sony_Close(p); - break; - case kCmndSonyOpenA: - result = Sony_OpenA(p); - break; - case kCmndSonyOpenB: - result = Sony_OpenB(p); - break; - case kCmndSonyOpenC: - result = Sony_OpenC(p); - break; - case kCmndSonyMount: - result = Sony_Mount(p); - break; - default: - result = mnvm_controlErr; - break; - } - - put_vm_word(p + ExtnDat_result, result); -} +/* SONYEMDV.c Copyright (C) 2009 Philip Cummins, Jesus A. Alvarez, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* SONY floppy disk EMulated DeVice The Sony hardware is not actually emulated. Instead the ROM is patched to replace the Sony disk driver with code that calls Mini vMac extensions implemented in the file. Information neeeded to better support the Disk Copy 4.2 format was found in libdc42.c of the Lisa Emulator Project by Ray A. Arachelian, and adapted to Mini vMac by Jesus A. Alvarez. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "ENDIANAC.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "MINEM68K.h" #endif #include "SONYEMDV.h" /* ReportAbnormalID unused 0x090B - 0x09FF */ LOCALVAR ui5b vSonyMountedMask = 0; #define vSonyIsLocked(Drive_No) \ ((vSonyWritableMask & ((ui5b)1 << (Drive_No))) == 0) #define vSonyIsMounted(Drive_No) \ ((vSonyMountedMask & ((ui5b)1 << (Drive_No))) != 0) LOCALFUNC blnr vSonyNextPendingInsert0(tDrive *Drive_No) { /* find next drive to Mount */ ui5b MountPending = vSonyInsertedMask & (~ vSonyMountedMask); if (MountPending != 0) { tDrive i; for (i = 0; i < NumDrives; ++i) { if ((MountPending & ((ui5b)1 << i)) != 0) { *Drive_No = i; return trueblnr; /* only one disk at a time */ } } } return falseblnr; } LOCALFUNC tMacErr CheckReadableDrive(tDrive Drive_No) { tMacErr result; if (Drive_No >= NumDrives) { result = mnvm_nsDrvErr; } else if (! vSonyIsMounted(Drive_No)) { result = mnvm_offLinErr; } else { result = mnvm_noErr; } return result; } LOCALFUNC tMacErr vSonyTransferVM(blnr IsWrite, CPTR Buffera, tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, ui5r *Sony_ActCount) { /* Transfer data between emulated disk and emulated memory. Taking into account that the emulated memory may not be contiguous in real memory. (Though it generally is for macintosh emulation.) */ tMacErr result; ui5b contig; ui5r actual; ui3p Buffer; ui5r offset = Sony_Start; ui5r n = Sony_Count; label_1: if (0 == n) { result = mnvm_noErr; } else { Buffer = get_real_address0(n, ! IsWrite, Buffera, &contig); if (0 == contig) { result = mnvm_miscErr; } else { result = vSonyTransfer(IsWrite, Buffer, Drive_No, offset, contig, &actual); offset += actual; Buffera += actual; n -= actual; if (mnvm_noErr == result) { goto label_1; } } } if (nullpr != Sony_ActCount) { *Sony_ActCount = Sony_Count - n; } return result; } LOCALPROC MyMoveBytesVM(CPTR srcPtr, CPTR dstPtr, si5b byteCount) { ui3p src; ui3p dst; ui5b contigSrc; ui5b contigDst; ui5r contig; label_1: if (0 != byteCount) { src = get_real_address0(byteCount, falseblnr, srcPtr, &contigSrc); dst = get_real_address0(byteCount, trueblnr, dstPtr, &contigDst); if ((0 == contigSrc) || (0 == contigDst)) { ReportAbnormalID(0x0901, "MyMoveBytesVM fails"); } else { contig = (contigSrc < contigDst) ? contigSrc : contigDst; MyMoveBytes(src, dst, contig); srcPtr += contig; dstPtr += contig; byteCount -= contig; goto label_1; } } } LOCALVAR ui5r ImageDataOffset[NumDrives]; /* size of any header in disk image file */ LOCALVAR ui5r ImageDataSize[NumDrives]; /* size of disk image file contents */ #if Sony_SupportTags LOCALVAR ui5r ImageTagOffset[NumDrives]; /* offset to disk image file tags */ #endif #if Sony_SupportDC42 #define kDC42offset_diskName 0 #define kDC42offset_dataSize 64 #define kDC42offset_tagSize 68 #define kDC42offset_dataChecksum 72 #define kDC42offset_tagChecksum 76 #define kDC42offset_diskFormat 80 #define kDC42offset_formatByte 81 #define kDC42offset_private 82 #define kDC42offset_userData 84 #endif #define ChecksumBlockSize 1024 #if Sony_SupportDC42 && Sony_WantChecksumsUpdated LOCALFUNC tMacErr DC42BlockChecksum(tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, ui5r *r) { tMacErr result; ui5r n; ui3b Buffer[ChecksumBlockSize]; ui3b *p; ui5b sum = 0; ui5r offset = Sony_Start; ui5r remaining = Sony_Count; while (0 != remaining) { /* read a block */ if (remaining > ChecksumBlockSize) { n = ChecksumBlockSize; } else { n = remaining; } result = vSonyTransfer(falseblnr, Buffer, Drive_No, offset, n, nullpr); if (mnvm_noErr != result) { return result; } offset += n; remaining -= n; /* add to Checksum */ p = Buffer; n >>= 1; /* n = number of words */ while (0 != n) { --n; /* ROR.l sum+word */ sum += do_get_mem_word(p); p += 2; sum = (sum >> 1) | ((sum & 1) << 31); } } *r = sum; return mnvm_noErr; } #endif #if Sony_SupportDC42 && Sony_WantChecksumsUpdated #if Sony_SupportTags #define SizeCheckSumsToUpdate 8 #else #define SizeCheckSumsToUpdate 4 #endif #endif #if Sony_WantChecksumsUpdated LOCALPROC Drive_UpdateChecksums(tDrive Drive_No) { if (! vSonyIsLocked(Drive_No)) { ui5r DataOffset = ImageDataOffset[Drive_No]; #if Sony_SupportDC42 if (kDC42offset_userData == DataOffset) { /* a disk copy 4.2 image */ tMacErr result; ui5r dataChecksum; ui3b Buffer[SizeCheckSumsToUpdate]; ui5r Sony_Count = SizeCheckSumsToUpdate; ui5r DataSize = ImageDataSize[Drive_No]; /* Checksum image data */ result = DC42BlockChecksum(Drive_No, DataOffset, DataSize, &dataChecksum); if (mnvm_noErr != result) { ReportAbnormalID(0x0902, "Failed to find dataChecksum"); dataChecksum = 0; } do_put_mem_long(Buffer, dataChecksum); #if Sony_SupportTags { ui5r tagChecksum; ui5r TagOffset = ImageTagOffset[Drive_No]; ui5r TagSize = (0 == TagOffset) ? 0 : ((DataSize >> 9) * 12); if (TagSize < 12) { tagChecksum = 0; } else { /* Checksum of tags doesn't include first block. presumably because of bug in original disk copy program. */ result = DC42BlockChecksum(Drive_No, TagOffset + 12, TagSize - 12, &tagChecksum); if (mnvm_noErr != result) { ReportAbnormalID(0x0903, "Failed to find tagChecksum"); tagChecksum = 0; } } do_put_mem_long(Buffer + 4, tagChecksum); } #endif /* write Checksums */ vSonyTransfer(trueblnr, Buffer, Drive_No, kDC42offset_dataChecksum, Sony_Count, nullpr); } #endif } } #endif #define checkheaderoffset 0 #define checkheadersize 128 #define Sony_SupportOtherFormats Sony_SupportDC42 LOCALFUNC tMacErr vSonyNextPendingInsert(tDrive *Drive_No) { tDrive i; tMacErr result; ui5r L; if (! vSonyNextPendingInsert0(&i)) { result = mnvm_nsDrvErr; } else { result = vSonyGetSize(i, &L); if (mnvm_noErr == result) { /* first, set up for default format */ ui5r DataOffset = 0; ui5r DataSize = L; #if Sony_SupportTags ui5r TagOffset = 0; #endif #if Sony_SupportOtherFormats #if IncludeSonyRawMode if (! vSonyRawMode) #endif { ui5r DataOffset0; ui5r DataSize0; ui5r TagOffset0; ui5r TagSize0; ui3b Temp[checkheadersize]; ui5r Sony_Count = checkheadersize; blnr gotFormat = falseblnr; result = vSonyTransfer(falseblnr, Temp, i, checkheaderoffset, Sony_Count, nullpr); if (mnvm_noErr == result) { #if Sony_SupportDC42 /* Detect Disk Copy 4.2 image */ if (0x0100 == do_get_mem_word( &Temp[kDC42offset_private])) { /* DC42 signature found, check sizes */ DataSize0 = do_get_mem_long( &Temp[kDC42offset_dataSize]); TagSize0 = do_get_mem_long( &Temp[kDC42offset_tagSize]); DataOffset0 = kDC42offset_userData; TagOffset0 = DataOffset0 + DataSize0; if (L >= (TagOffset0 + TagSize0)) if (0 == (DataSize0 & 0x01FF)) if ((DataSize0 >> 9) >= 4) if (Temp[kDC42offset_diskName] < 64) /* length of pascal string */ { if (0 == TagSize0) { /* no tags */ gotFormat = trueblnr; } else if ((DataSize0 >> 9) * 12 == TagSize0) { /* 12 byte tags */ gotFormat = trueblnr; } if (gotFormat) { #if Sony_VerifyChecksums /* mostly useful to check the Checksum code */ ui5r dataChecksum; ui5r tagChecksum; ui5r dataChecksum0 = do_get_mem_long( &Temp[kDC42offset_dataChecksum]); ui5r tagChecksum0 = do_get_mem_long( &Temp[kDC42offset_tagChecksum]); result = DC42BlockChecksum(i, DataOffset0, DataSize0, &dataChecksum); if (TagSize0 >= 12) { result = DC42BlockChecksum(i, TagOffset0 + 12, TagSize0 - 12, &tagChecksum); } else { tagChecksum = 0; } if (dataChecksum != dataChecksum0) { ReportAbnormalID(0x0904, "bad dataChecksum"); } if (tagChecksum != tagChecksum0) { ReportAbnormalID(0x0905, "bad tagChecksum"); } #endif DataOffset = DataOffset0; DataSize = DataSize0; #if Sony_SupportTags TagOffset = (0 == TagSize0) ? 0 : TagOffset0; #endif #if (! Sony_SupportTags) || (! Sony_WantChecksumsUpdated) if (! vSonyIsLocked(i)) { #if ! Sony_WantChecksumsUpdated /* unconditionally revoke */ #else if (0 != TagSize0) #endif { DiskRevokeWritable(i); } } #endif } } } #endif /* Sony_SupportDC42 */ } } if (mnvm_noErr == result) #endif /* Sony_SupportOtherFormats */ { vSonyMountedMask |= ((ui5b)1 << i); ImageDataOffset[i] = DataOffset; ImageDataSize[i] = DataSize; #if Sony_SupportTags ImageTagOffset[i] = TagOffset; #endif *Drive_No = i; } } if (mnvm_noErr != result) { (void) vSonyEject(i); } } return result; } #define MinTicksBetweenInsert 240 /* if call PostEvent too frequently, insert events seem to get lost */ LOCALVAR ui4r DelayUntilNextInsert; LOCALVAR CPTR MountCallBack = 0; /* This checks to see if a disk (image) has been inserted */ GLOBALPROC Sony_Update (void) { if (DelayUntilNextInsert != 0) { --DelayUntilNextInsert; } else { if (MountCallBack != 0) { tDrive i; if (mnvm_noErr == vSonyNextPendingInsert(&i)) { ui5b data = i; if (vSonyIsLocked(i)) { data |= ((ui5b)0x00FF) << 16; } DiskInsertedPsuedoException(MountCallBack, data); #if IncludeSonyRawMode if (! vSonyRawMode) #endif { DelayUntilNextInsert = MinTicksBetweenInsert; /* but usually will reach kDriveStatus first, where shorten delay. */ } } } } } LOCALFUNC tMacErr Drive_Transfer(blnr IsWrite, CPTR Buffera, tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, ui5r *Sony_ActCount) { tMacErr result; QuietEnds(); if (nullpr != Sony_ActCount) { *Sony_ActCount = 0; } result = CheckReadableDrive(Drive_No); if (mnvm_noErr == result) { if (IsWrite && vSonyIsLocked(Drive_No)) { result = mnvm_vLckdErr; } else { ui5r DataSize = ImageDataSize[Drive_No]; if (Sony_Start > DataSize) { result = mnvm_eofErr; } else { blnr hit_eof = falseblnr; ui5r L = DataSize - Sony_Start; if (L >= Sony_Count) { L = Sony_Count; } else { hit_eof = trueblnr; } result = vSonyTransferVM(IsWrite, Buffera, Drive_No, ImageDataOffset[Drive_No] + Sony_Start, L, Sony_ActCount); if ((mnvm_noErr == result) && hit_eof) { result = mnvm_eofErr; } } } } return result; } LOCALVAR blnr QuitOnEject = falseblnr; GLOBALPROC Sony_SetQuitOnEject(void) { QuitOnEject = trueblnr; } LOCALFUNC tMacErr Drive_Eject(tDrive Drive_No) { tMacErr result; result = CheckReadableDrive(Drive_No); if (mnvm_noErr == result) { vSonyMountedMask &= ~ ((ui5b)1 << Drive_No); #if Sony_WantChecksumsUpdated Drive_UpdateChecksums(Drive_No); #endif result = vSonyEject(Drive_No); if (QuitOnEject != 0) { if (! AnyDiskInserted()) { ForceMacOff = trueblnr; } } } return result; } #if IncludeSonyNew LOCALFUNC tMacErr Drive_EjectDelete(tDrive Drive_No) { tMacErr result; result = CheckReadableDrive(Drive_No); if (mnvm_noErr == result) { if (vSonyIsLocked(Drive_No)) { result = mnvm_vLckdErr; } else { vSonyMountedMask &= ~ ((ui5b)1 << Drive_No); result = vSonyEjectDelete(Drive_No); } } return result; } #endif GLOBALPROC Sony_EjectAllDisks(void) { tDrive i; vSonyMountedMask = 0; for (i = 0; i < NumDrives; ++i) { if (vSonyIsInserted(i)) { #if Sony_WantChecksumsUpdated Drive_UpdateChecksums(i); #endif (void) vSonyEject(i); } } } GLOBALPROC Sony_Reset(void) { DelayUntilNextInsert = 0; QuitOnEject = falseblnr; MountCallBack = 0; } /* Mini vMac extension for low level access to disk operations. */ #define kCmndDiskNDrives 1 #define kCmndDiskRead 2 #define kCmndDiskWrite 3 #define kCmndDiskEject 4 #define kCmndDiskGetSize 5 #define kCmndDiskGetCallBack 6 #define kCmndDiskSetCallBack 7 #define kCmndDiskQuitOnEject 8 #define kCmndDiskFeatures 9 #define kCmndDiskNextPendingInsert 10 #if IncludeSonyRawMode #define kCmndDiskGetRawMode 11 #define kCmndDiskSetRawMode 12 #endif #if IncludeSonyNew #define kCmndDiskNew 13 #define kCmndDiskGetNewWanted 14 #define kCmndDiskEjectDelete 15 #endif #if IncludeSonyGetName #define kCmndDiskGetName 16 #endif #define kFeatureCmndDisk_RawMode 0 #define kFeatureCmndDisk_New 1 #define kFeatureCmndDisk_NewName 2 #define kFeatureCmndDisk_GetName 3 #define kParamDiskNumDrives 8 #define kParamDiskStart 8 #define kParamDiskCount 12 #define kParamDiskBuffer 16 #define kParamDiskDrive_No 20 GLOBALPROC ExtnDisk_Access(CPTR p) { tMacErr result = mnvm_controlErr; switch (get_vm_word(p + ExtnDat_commnd)) { case kCmndVersion: put_vm_word(p + ExtnDat_version, 2); result = mnvm_noErr; break; case kCmndDiskNDrives: /* count drives */ put_vm_word(p + kParamDiskNumDrives, NumDrives); result = mnvm_noErr; break; case kCmndDiskRead: { ui5r Sony_ActCount; CPTR Buffera = get_vm_long(p + kParamDiskBuffer); tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No); ui5r Sony_Start = get_vm_long(p + kParamDiskStart); ui5r Sony_Count = get_vm_long(p + kParamDiskCount); result = Drive_Transfer(falseblnr, Buffera, Drive_No, Sony_Start, Sony_Count, &Sony_ActCount); put_vm_long(p + kParamDiskCount, Sony_ActCount); } break; case kCmndDiskWrite: { ui5r Sony_ActCount; CPTR Buffera = get_vm_long(p + kParamDiskBuffer); tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No); ui5r Sony_Start = get_vm_long(p + kParamDiskStart); ui5r Sony_Count = get_vm_long(p + kParamDiskCount); result = Drive_Transfer(trueblnr, Buffera, Drive_No, Sony_Start, Sony_Count, &Sony_ActCount); put_vm_long(p + kParamDiskCount, Sony_ActCount); } break; case kCmndDiskEject: { tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No); result = Drive_Eject(Drive_No); } break; case kCmndDiskGetSize: { tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No); result = CheckReadableDrive(Drive_No); if (mnvm_noErr == result) { put_vm_long(p + kParamDiskCount, ImageDataSize[Drive_No]); result = mnvm_noErr; } } break; case kCmndDiskGetCallBack: put_vm_long(p + kParamDiskBuffer, MountCallBack); result = mnvm_noErr; break; case kCmndDiskSetCallBack: MountCallBack = get_vm_long(p + kParamDiskBuffer); result = mnvm_noErr; break; case kCmndDiskQuitOnEject: QuitOnEject = trueblnr; result = mnvm_noErr; break; case kCmndDiskFeatures: { ui5r v = (0 #if IncludeSonyRawMode | ((ui5b)1 << kFeatureCmndDisk_RawMode) #endif #if IncludeSonyNew | ((ui5b)1 << kFeatureCmndDisk_New) #endif #if IncludeSonyNameNew | ((ui5b)1 << kFeatureCmndDisk_NewName) #endif #if IncludeSonyGetName | ((ui5b)1 << kFeatureCmndDisk_GetName) #endif ); put_vm_long(p + ExtnDat_params + 0, v); result = mnvm_noErr; } break; case kCmndDiskNextPendingInsert: { tDrive i; result = vSonyNextPendingInsert(&i); if (mnvm_noErr == result) { put_vm_word(p + kParamDiskDrive_No, i); } } break; #if IncludeSonyRawMode case kCmndDiskGetRawMode: put_vm_word(p + kParamDiskBuffer, vSonyRawMode); result = mnvm_noErr; break; case kCmndDiskSetRawMode: vSonyRawMode = get_vm_word(p + kParamDiskBuffer); result = mnvm_noErr; break; #endif #if IncludeSonyNew case kCmndDiskNew: { ui5b count = get_vm_long(p + ExtnDat_params + 0); tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 4); /* reserved word at offset 6, should be zero */ result = mnvm_noErr; #if IncludePbufs if (Pbuf_No != NotAPbuf) { result = CheckPbuf(Pbuf_No); if (mnvm_noErr == result) { vSonyNewDiskWanted = trueblnr; vSonyNewDiskSize = count; #if IncludeSonyNameNew if (vSonyNewDiskName != NotAPbuf) { PbufDispose(vSonyNewDiskName); } vSonyNewDiskName = Pbuf_No; #else PbufDispose(Pbuf_No); #endif } } else #endif { vSonyNewDiskWanted = trueblnr; vSonyNewDiskSize = count; } } break; case kCmndDiskGetNewWanted: put_vm_word(p + kParamDiskBuffer, vSonyNewDiskWanted); result = mnvm_noErr; break; case kCmndDiskEjectDelete: { tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No); result = Drive_EjectDelete(Drive_No); } break; #endif #if IncludeSonyGetName case kCmndDiskGetName: { tDrive Drive_No = get_vm_word(p + ExtnDat_params + 0); /* reserved word at offset 2, should be zero */ result = CheckReadableDrive(Drive_No); if (mnvm_noErr == result) { tPbuf Pbuf_No; result = vSonyGetName(Drive_No, &Pbuf_No); put_vm_word(p + ExtnDat_params + 4, Pbuf_No); } } break; #endif } put_vm_word(p + ExtnDat_result, result); } /* Mini vMac extension that implements most of the logic of the replacement disk driver patched into the emulated ROM. (sony_driver in ROMEMDEV.c) This logic used to be completely contained in the 68k code of the replacement driver, using only the low level disk access extension. */ /* Sony Variable Drive Setting Offsets */ #define kTrack 0 /* Current Track */ #define kWriteProt 2 /* FF if Write Protected, 00 if readable */ #define kDiskInPlace 3 /* 00 = No Disk, 01 = Disk In, 2 = MacOS Read, FC-FF = Just Ejected */ #define kInstalled 4 /* 00 = Unknown, 01 = Installed, FF = Not Installed */ #define kSides 5 /* 00 if Single Sided Drive, FF if Doubled Sided Drive */ #define kQLink 6 /* Link to Next Drive */ #define kQType 10 /* Drive Type (0 = Size Saved, 1 = Very Large) */ #define kQDriveNo 12 /* Drive Number (1 = Internal, 2 = External) */ #define kQRefNum 14 /* Driver Reference Number (-5 for .Sony, FFFB) */ #define kQFSID 16 /* File System ID (0 = MacOS) */ #define kQDrvSz 18 /* size, low-order word */ #define kQDrvSz2 20 /* size, hi-order word */ #define kTwoSideFmt 18 /* FF if double-sided format, 00 if single-sided format */ #define kNewIntf 19 /* FF if new 800K interface or 00 if old 400K interface */ #define kDriveErrs 20 /* Drive Soft Errors */ /* Sony Driver Control Call csCodes */ #define kKillIO 1 #define kVerifyDisk 5 #define kFormatDisk 6 #define kEjectDisk 7 #define kSetTagBuffer 8 #define kTrackCacheControl 9 #define kGetIconID 20 #define kDriveIcon 21 #define kMediaIcon 22 #define kDriveInfo 23 #define kFormatCopy 21315 /* Sony Driver Status Call csCodes */ #define kReturnFormatList 6 #define kDriveStatus 8 #define kMFMStatus 10 #define kDuplicatorVersionSupport 17494 /* Parameter Block Offsets */ #define kqLink 0 #define kqType 4 #define kioTrap 6 #define kioCmdAddr 8 #define kioCompletion 12 #define kioResult 16 #define kioNamePtr 18 #define kioVRefNum 22 #define kioRefNum 24 #define kcsCode 26 #define kcsParam 28 #define kioBuffer 32 /* Buffer to store data into */ #define kioReqCount 36 /* Requested Number of Bytes */ #define kioActCount 40 /* Actual Number of Bytes obtained */ #define kioPosMode 44 /* Positioning Mode */ #define kioPosOffset 46 /* Position Offset */ /* Positioning Modes */ #define kfsAtMark 0 /* At Mark (Ignore PosOffset) */ #define kfsFromStart 1 /* At Start (PosOffset is absolute) */ #define kfsFromLEOF 2 /* From Logical End of File - PosOffset */ #define kfsFromMark 3 /* At Mark + PosOffset */ /* Device Control Entry Offsets */ #define kdCtlPosition 16 #if 0 struct MyDriverDat_R { ui5b zeroes[4]; /* 0 */ ui5b checkval; /* 16 */ ui5b pokeaddr; /* 20 */ ui4b NumDrives; /* 24 */ ui4b DiskExtn; /* 26 */ TMTask NullTask; /* 28 */ /* total size must be <= FirstDriveVarsOffset */ }; typedef struct MyDriverDat_R MyDriverDat_R; #endif #if CurEmMd <= kEmMd_Twiggy #define SonyVarsPtr 0x0128 /* TwiggyVars, actually */ #if CurEmMd <= kEmMd_Twig43 #define MinSonVarsSize 0x000000FA #define FirstDriveVarsOffset 0x004A #define EachDriveVarsSize 0x0042 #else #define MinSonVarsSize 0x000000E6 #define FirstDriveVarsOffset 0x004C #define EachDriveVarsSize 0x002E #endif #else #define SonyVarsPtr 0x0134 #define FirstDriveVarsOffset 0x004A #define EachDriveVarsSize 0x0042 #if CurEmMd <= kEmMd_128K #define MinSonVarsSize 0x000000FA #else #define MinSonVarsSize 0x00000310 #endif #endif #define kcom_checkval 0x841339E2 #define Sony_dolog (dbglog_HAVE && 0) #if Sony_SupportTags LOCALVAR CPTR TheTagBuffer; #endif LOCALFUNC ui5b DriveVarsLocation(tDrive Drive_No) { CPTR SonyVars = get_vm_long(SonyVarsPtr); if (Drive_No < NumDrives) { return SonyVars + FirstDriveVarsOffset + EachDriveVarsSize * Drive_No; } else { return 0; } } LOCALFUNC tMacErr Sony_Mount(CPTR p) { ui5b data = get_vm_long(p + ExtnDat_params + 0); tMacErr result = mnvm_miscErr; tDrive i = data & 0x0000FFFF; CPTR dvl = DriveVarsLocation(i); if (0 == dvl) { #if Sony_dolog dbglog_WriteNote("Sony : Mount : no dvl"); #endif result = mnvm_nsDrvErr; } else if (get_vm_byte(dvl + kDiskInPlace) == 0x00) { ui5b L = ImageDataSize[i] >> 9; /* block count */ #if Sony_dolog dbglog_StartLine(); dbglog_writeCStr("Sony : Mount : Drive="); dbglog_writeHex(i); dbglog_writeCStr(", L="); dbglog_writeHex(L); dbglog_writeReturn(); #endif #if CurEmMd <= kEmMd_Twiggy if (L == 1702) { put_vm_byte(dvl + kTwoSideFmt, 0xFF); /* Drive i Single Format */ put_vm_byte(dvl + kNewIntf, 0x00); /* Drive i doesn't use new interface */ put_vm_word(dvl + kQType, 0x00); /* Drive Type */ put_vm_word(dvl + kDriveErrs, 0x0000); /* Drive i has no errors */ } else #else if ((L == 800) #if CurEmMd > kEmMd_128K || (L == 1600) #endif ) { #if CurEmMd <= kEmMd_128K put_vm_byte(dvl + kTwoSideFmt, 0x00); /* Drive i Single Format */ put_vm_byte(dvl + kNewIntf, 0x00); /* Drive i doesn't use new interface */ #else if (L == 800) { put_vm_byte(dvl + kTwoSideFmt, 0x00); /* Drive i Single Format */ } else { put_vm_byte(dvl + kTwoSideFmt, 0xFF); /* Drive Double Format */ } put_vm_byte(dvl + kNewIntf, 0xFF); /* Drive i uses new interface */ #endif put_vm_word(dvl + kQType, 0x00); /* Drive Type */ put_vm_word(dvl + kDriveErrs, 0x0000); /* Drive i has no errors */ } else #endif { put_vm_word(dvl + kQRefNum, 0xFFFE); /* Driver */ put_vm_word(dvl + kQType, 0x01); /* Drive Type */ put_vm_word(dvl + kQDrvSz , L); put_vm_word(dvl + kQDrvSz2, L >> 16); } #if CurEmMd <= kEmMd_Twiggy put_vm_word(dvl + kQFSID, 0x00); /* kQFSID must be 0 for 4.3T */ #endif put_vm_byte(dvl + kWriteProt, data >> 16); put_vm_byte(dvl + kDiskInPlace, 0x01); /* Drive Disk Inserted */ put_vm_long(p + ExtnDat_params + 4, i + 1); /* PostEvent Disk Inserted eventMsg */ result = mnvm_noErr; } else { /* disk already in place, a mistake has been made */ #if Sony_dolog dbglog_WriteNote("Sony : Mount : already in place"); #endif } return result; } #if Sony_SupportTags LOCALFUNC tMacErr Sony_PrimeTags(tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, blnr IsWrite) { tMacErr result = mnvm_noErr; ui5r TagOffset = ImageTagOffset[Drive_No]; if ((0 != TagOffset) && (Sony_Count > 0)) { ui5r block = Sony_Start >> 9; ui5r n = Sony_Count >> 9; /* is >= 1 if get here */ TagOffset += block * 12; if (0 != TheTagBuffer) { ui5r count = 12 * n; result = vSonyTransferVM(IsWrite, TheTagBuffer, Drive_No, TagOffset, count, nullpr); if (mnvm_noErr == result) { MyMoveBytesVM(TheTagBuffer + count - 12, 0x02FC, 12); } } else { if (! IsWrite) { /* only need to read the last block tags */ ui5r count = 12; TagOffset += 12 * (n - 1); result = vSonyTransferVM(falseblnr, 0x02FC, Drive_No, TagOffset, count, nullpr); } else { ui5r count = 12; ui4r BufTgFBkNum = get_vm_word(0x0302); do { put_vm_word(0x0302, BufTgFBkNum); result = vSonyTransferVM(trueblnr, 0x02FC, Drive_No, TagOffset, count, nullpr); if (mnvm_noErr != result) { goto label_fail; } BufTgFBkNum += 1; TagOffset += 12; } while (--n != 0); } } } label_fail: return result; } #endif /* Handles I/O to disks */ LOCALFUNC tMacErr Sony_Prime(CPTR p) { tMacErr result; ui5r Sony_Count; ui5r Sony_Start; ui5r Sony_ActCount = 0; CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 0); CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 4); tDrive Drive_No = get_vm_word(ParamBlk + kioVRefNum) - 1; ui4r IOTrap = get_vm_word(ParamBlk + kioTrap); CPTR dvl = DriveVarsLocation(Drive_No); if (0 == dvl) { #if Sony_dolog dbglog_WriteNote("Sony : Prime : no dvl"); #endif result = mnvm_nsDrvErr; } else #if CurEmMd >= kEmMd_Twiggy if (0xA002 != (IOTrap & 0xF0FE)) { #if Sony_dolog dbglog_WriteNote("Sony : Prime : " "not read (0xA002) or write (0xA003)"); #endif result = mnvm_controlErr; } else #endif { blnr IsWrite = (0 != (IOTrap & 0x0001)); ui3b DiskInPlaceV = get_vm_byte(dvl + kDiskInPlace); if (DiskInPlaceV != 0x02) { if (DiskInPlaceV == 0x01) { put_vm_byte(dvl + kDiskInPlace, 0x02); /* Clamp Drive */ } else { result = mnvm_offLinErr; goto label_fail; /* if don't check for this, will go right ahead and boot off a disk that hasn't been mounted yet by Sony_Update. (disks other than the boot disk aren't seen unless mounted by Sony_Update) */ } } #if 0 ui4r PosMode = get_vm_word(ParamBlk + kioPosMode); if (0 != (PosMode & 64)) { #if ExtraAbnormalReports /* This is used when copy to floppy disk with Finder. But not implemented yet. */ ReportAbnormalID(0x0906, "read verify mode requested"); #endif PosMode &= ~ 64; } /* Don't use the following code, because according to Apple's Technical Note FL24 the Device Manager takes care of this, and puts the result in dCtlPosition. (The RAMDisk example in Apple's sample code serves to confirm this. Further evidence found in Basilisk II emulator, and disassembly of Mac Plus disk driver.) */ ui5r PosOffset = get_vm_long(ParamBlk + kioPosOffset); switch (PosMode) { case kfsAtMark: Sony_Start = get_vm_long(DeviceCtl + kdCtlPosition); break; case kfsFromStart: Sony_Start = PosOffset; break; #if 0 /* not valid for device driver. actually only kfsFromStart seems to be used. */ case kfsFromLEOF: Sony_Start = ImageDataSize[Drive_No] + PosOffset; break; #endif case kfsFromMark: Sony_Start = PosOffset + get_vm_long(DeviceCtl + kdCtlPosition); break; default: ReportAbnormalID(0x0907, "unknown PosMode"); result = mnvm_paramErr; goto label_fail; break; } #endif Sony_Start = get_vm_long(DeviceCtl + kdCtlPosition); Sony_Count = get_vm_long(ParamBlk + kioReqCount); #if Sony_dolog dbglog_StartLine(); dbglog_writeCStr("Sony : Prime : Drive="); dbglog_writeHex(Drive_No); dbglog_writeCStr(", IsWrite="); dbglog_writeHex(IsWrite); dbglog_writeCStr(", Start="); dbglog_writeHex(Sony_Start); dbglog_writeCStr(", Count="); dbglog_writeHex(Sony_Count); dbglog_writeReturn(); #endif if ((0 != (Sony_Start & 0x1FF)) || (0 != (Sony_Count & 0x1FF))) { /* only whole blocks allowed */ #if ExtraAbnormalReports ReportAbnormalID(0x0908, "not blockwise in Sony_Prime"); #endif result = mnvm_paramErr; } else if (IsWrite && (get_vm_byte(dvl + kWriteProt) != 0)) { result = mnvm_wPrErr; } else { CPTR Buffera = get_vm_long(ParamBlk + kioBuffer); result = Drive_Transfer(IsWrite, Buffera, Drive_No, Sony_Start, Sony_Count, &Sony_ActCount); #if Sony_SupportTags if (mnvm_noErr == result) { result = Sony_PrimeTags(Drive_No, Sony_Start, Sony_Count, IsWrite); } #endif put_vm_long(DeviceCtl + kdCtlPosition, Sony_Start + Sony_ActCount); } } label_fail: put_vm_word(ParamBlk + kioResult, result); put_vm_long(ParamBlk + kioActCount, Sony_ActCount); if (mnvm_noErr != result) { put_vm_word(0x0142 /* DskErr */, result); } return result; } /* Implements control csCodes for the Sony driver */ LOCALFUNC tMacErr Sony_Control(CPTR p) { tMacErr result; CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 0); /* CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 4); */ ui4r OpCode = get_vm_word(ParamBlk + kcsCode); if (kKillIO == OpCode) { #if Sony_dolog dbglog_WriteNote("Sony : Control : kKillIO"); #endif result = mnvm_miscErr; } else if (kSetTagBuffer == OpCode) { #if Sony_dolog dbglog_WriteNote("Sony : Control : kSetTagBuffer"); #endif #if Sony_SupportTags TheTagBuffer = get_vm_long(ParamBlk + kcsParam); result = mnvm_noErr; #else result = mnvm_controlErr; #endif } else if (kTrackCacheControl == OpCode) { #if Sony_dolog dbglog_WriteNote("Sony : Control : kTrackCacheControl"); #endif #if CurEmMd <= kEmMd_128K result = mnvm_controlErr; #else #if 0 ui3r Arg1 = get_vm_byte(ParamBlk + kcsParam); ui3r Arg2 = get_vm_byte(ParamBlk + kcsParam + 1); if (0 == Arg1) { /* disable track cache */ } else { /* enable track cache */ } if (Arg2 < 0) { /* remove track cache */ } else if (Arg2 > 0) { /* install track cache */ } #endif result = mnvm_noErr; /* not implemented, but pretend we did it */ #endif } else { tDrive Drive_No = get_vm_word(ParamBlk + kioVRefNum) - 1; CPTR dvl = DriveVarsLocation(Drive_No); if (0 == dvl) { #if Sony_dolog dbglog_WriteNote("Sony : Control : no dvl"); #endif result = mnvm_nsDrvErr; } else if (get_vm_byte(dvl + kDiskInPlace) == 0) { #if Sony_dolog dbglog_WriteNote("Sony : Control : not DiskInPlace"); #endif result = mnvm_offLinErr; } else { switch (OpCode) { case kVerifyDisk : #if Sony_dolog dbglog_WriteNote("Sony : Control : kVerifyDisk"); #endif result = mnvm_noErr; break; case kEjectDisk : #if Sony_dolog dbglog_StartLine(); dbglog_writeCStr("Sony : Control : kEjectDisk : "); dbglog_writeHex(Drive_No); dbglog_writeReturn(); #endif put_vm_byte(dvl + kWriteProt, 0x00); /* Drive Writeable */ put_vm_byte(dvl + kDiskInPlace, 0x00); /* Drive No Disk */ #if 0 put_vm_byte(dvl + kTwoSideFmt, 0x00); /* Drive Single Format (Initially) */ #endif put_vm_word(dvl + kQRefNum, 0xFFFB); /* Drive i uses .Sony */ result = Drive_Eject(Drive_No); break; case kFormatDisk : #if Sony_dolog dbglog_StartLine(); dbglog_writeCStr("Sony : Control : kFormatDisk : "); dbglog_writeHex(Drive_No); dbglog_writeReturn(); #endif result = mnvm_noErr; break; case kDriveIcon : #if Sony_dolog dbglog_StartLine(); dbglog_writeCStr("Sony : Control : kDriveIcon : "); dbglog_writeHex(Drive_No); dbglog_writeReturn(); #endif if (get_vm_word(dvl + kQType) != 0) { put_vm_long(ParamBlk + kcsParam, my_disk_icon_addr); result = mnvm_noErr; } else { result = mnvm_controlErr; /* Driver can't respond to this Control call (-17) */ } break; #if CurEmMd >= kEmMd_SE case kDriveInfo : { ui5b v; #if Sony_dolog dbglog_StartLine(); dbglog_writeCStr( "Sony : Control : kDriveInfo : "); dbglog_writeHex(kDriveIcon); dbglog_writeReturn(); #endif if (get_vm_word(dvl + kQType) != 0) { v = 0x00000001; /* unspecified drive */ } else { #if CurEmMd <= kEmMd_128K v = 0x00000002; /* 400K Drive */ #else v = 0x00000003; /* 800K Drive */ #endif } if (Drive_No != 0) { v += 0x00000900; /* Secondary External Drive */ } put_vm_long(ParamBlk + kcsParam, v); result = mnvm_noErr; /* No error (0) */ } break; #endif default : #if Sony_dolog dbglog_StartLine(); dbglog_writeCStr("Sony : Control : OpCode : "); dbglog_writeHex(OpCode); dbglog_writeReturn(); #endif #if ExtraAbnormalReports if ((kGetIconID != OpCode) && (kMediaIcon != OpCode) && (kDriveInfo != OpCode)) { ReportAbnormalID(0x0909, "unexpected OpCode in Sony_Control"); } #endif result = mnvm_controlErr; /* Driver can't respond to this Control call (-17) */ break; } } } if (mnvm_noErr != result) { put_vm_word(0x0142 /* DskErr */, result); } return result; } /* Handles the DriveStatus call */ LOCALFUNC tMacErr Sony_Status(CPTR p) { tMacErr result; CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 0); /* CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 4); */ ui4r OpCode = get_vm_word(ParamBlk + kcsCode); #if Sony_dolog dbglog_StartLine(); dbglog_writeCStr("Sony : Sony_Status OpCode = "); dbglog_writeHex(OpCode); dbglog_writeReturn(); #endif if (kDriveStatus == OpCode) { tDrive Drive_No = get_vm_word(ParamBlk + kioVRefNum) - 1; CPTR Src = DriveVarsLocation(Drive_No); if (Src == 0) { result = mnvm_nsDrvErr; } else { if (DelayUntilNextInsert > 4) { DelayUntilNextInsert = 4; } MyMoveBytesVM(Src, ParamBlk + kcsParam, 22); result = mnvm_noErr; } } else { #if ExtraAbnormalReports if ((kReturnFormatList != OpCode) && (kDuplicatorVersionSupport != OpCode)) { ReportAbnormalID(0x090A, "unexpected OpCode in Sony_Control"); } #endif result = mnvm_statusErr; } if (mnvm_noErr != result) { put_vm_word(0x0142 /* DskErr */, result); } return result; } LOCALFUNC tMacErr Sony_Close(CPTR p) { #if 0 CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 0); CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 4); #endif UnusedParam(p); return mnvm_closErr; /* Can't Close Driver */ } LOCALFUNC tMacErr Sony_OpenA(CPTR p) { #if Sony_dolog dbglog_WriteNote("Sony : OpenA"); #endif if (MountCallBack != 0) { return mnvm_opWrErr; /* driver already open */ } else { ui5b L = FirstDriveVarsOffset + EachDriveVarsSize * NumDrives; if (L < MinSonVarsSize) { L = MinSonVarsSize; } put_vm_long(p + ExtnDat_params + 0, L); return mnvm_noErr; } } LOCALFUNC tMacErr Sony_OpenB(CPTR p) { si4b i; CPTR dvl; #if Sony_dolog dbglog_WriteNote("Sony : OpenB"); #endif CPTR SonyVars = get_vm_long(p + ExtnDat_params + 4); /* CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 24); (unused) */ #if CurEmMd > kEmMd_128K CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 28); #endif put_vm_long(SonyVars + 16 /* checkval */, kcom_checkval); put_vm_long(SonyVars + 20 /* pokeaddr */, kExtn_Block_Base); put_vm_word(SonyVars + 24 /* NumDrives */, NumDrives); put_vm_word(SonyVars + 26 /* DiskExtn */, kExtnDisk); put_vm_long(SonyVarsPtr, SonyVars); for (i = 0; (dvl = DriveVarsLocation(i)) != 0; ++i) { put_vm_byte(dvl + kDiskInPlace, 0x00); /* Drive i No Disk */ put_vm_byte(dvl + kInstalled, 0x01); /* Drive i Installed */ #if CurEmMd <= kEmMd_128K put_vm_byte(dvl + kSides, 0x00); /* Drive i Single Sided */ #else put_vm_byte(dvl + kSides, 0xFF); /* Drive i Double Sided */ #endif put_vm_word(dvl + kQDriveNo, i + 1); /* Drive i is Drive 1 */ put_vm_word(dvl + kQRefNum, 0xFFFB); /* Drive i uses .Sony */ } { CPTR UTableBase = get_vm_long(0x011C); put_vm_long(UTableBase + 4 * 1, get_vm_long(UTableBase + 4 * 4)); /* use same drive for hard disk as used for sony floppies */ } #if CurEmMd > kEmMd_128K /* driver version in driver i/o queue header */ put_vm_byte(DeviceCtl + 7, 1); #endif #if CurEmMd <= kEmMd_128K /* init Drive Queue */ put_vm_word(0x308, 0); put_vm_long(0x308 + 2, 0); put_vm_long(0x308 + 6, 0); #endif put_vm_long(p + ExtnDat_params + 8, SonyVars + FirstDriveVarsOffset + kQLink); put_vm_word(p + ExtnDat_params + 12, EachDriveVarsSize); put_vm_word(p + ExtnDat_params + 14, NumDrives); put_vm_word(p + ExtnDat_params + 16, 1); put_vm_word(p + ExtnDat_params + 18, 0xFFFB); #if CurEmMd <= kEmMd_128K put_vm_long(p + ExtnDat_params + 20, 0); #else put_vm_long(p + ExtnDat_params + 20, SonyVars + 28 /* NullTask */); #endif #if Sony_SupportTags TheTagBuffer = 0; #endif return mnvm_noErr; } LOCALFUNC tMacErr Sony_OpenC(CPTR p) { #if Sony_dolog dbglog_WriteNote("Sony : OpenC"); #endif MountCallBack = get_vm_long(p + ExtnDat_params + 0) #if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) | 0x40000000 #endif ; return mnvm_noErr; } #define kCmndSonyPrime 1 #define kCmndSonyControl 2 #define kCmndSonyStatus 3 #define kCmndSonyClose 4 #define kCmndSonyOpenA 5 #define kCmndSonyOpenB 6 #define kCmndSonyOpenC 7 #define kCmndSonyMount 8 GLOBALPROC ExtnSony_Access(CPTR p) { tMacErr result; switch (get_vm_word(p + ExtnDat_commnd)) { case kCmndVersion: put_vm_word(p + ExtnDat_version, 0); result = mnvm_noErr; break; case kCmndSonyPrime: result = Sony_Prime(p); break; case kCmndSonyControl: result = Sony_Control(p); break; case kCmndSonyStatus: result = Sony_Status(p); break; case kCmndSonyClose: result = Sony_Close(p); break; case kCmndSonyOpenA: result = Sony_OpenA(p); break; case kCmndSonyOpenB: result = Sony_OpenB(p); break; case kCmndSonyOpenC: result = Sony_OpenC(p); break; case kCmndSonyMount: result = Sony_Mount(p); break; default: result = mnvm_controlErr; break; } put_vm_word(p + ExtnDat_result, result); } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/SONYEMDV.h b/Mini vMac/mnvm_core/SONYEMDV.h index c3a4108..135fc1d 100755 --- a/Mini vMac/mnvm_core/SONYEMDV.h +++ b/Mini vMac/mnvm_core/SONYEMDV.h @@ -1,31 +1 @@ -/* - SONYEMDV.h - - Copyright (C) 2004 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef SONYEMDV_H -#error "header already included" -#else -#define SONYEMDV_H -#endif - -EXPORTPROC ExtnDisk_Access(CPTR p); -EXPORTPROC ExtnSony_Access(CPTR p); - -EXPORTPROC Sony_SetQuitOnEject(void); - -EXPORTPROC Sony_EjectAllDisks(void); -EXPORTPROC Sony_Reset(void); - -EXPORTPROC Sony_Update(void); +/* SONYEMDV.h Copyright (C) 2004 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef SONYEMDV_H #error "header already included" #else #define SONYEMDV_H #endif EXPORTPROC ExtnDisk_Access(CPTR p); EXPORTPROC ExtnSony_Access(CPTR p); EXPORTPROC Sony_SetQuitOnEject(void); EXPORTPROC Sony_EjectAllDisks(void); EXPORTPROC Sony_Reset(void); EXPORTPROC Sony_Update(void); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/STRCNENG.h b/Mini vMac/mnvm_core/STRCNENG.h new file mode 100755 index 0000000..bc1617b --- /dev/null +++ b/Mini vMac/mnvm_core/STRCNENG.h @@ -0,0 +1 @@ +/* STRCNENG.h Copyright (C) 2006 Paul C. Pratt, Pierre Lemieux You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* STRing CoNstants for ENGlish Pierre Lemieux provided some corrections and suggestions. */ #define kStrAboutTitle "About" #define kStrAboutMessage "To display information about this program, use the ;]A;} command of the ^p Control Mode. To learn about the Control Mode, see the ;[More Commands;ll;{ item in the ;[Special;{ menu." #define kStrMoreCommandsTitle "More commands are available in the ^p Control Mode." #define kStrMoreCommandsMessage "To enter the Control Mode, press and hold down the ;]control;} key. You will remain in the Control Mode until you release the ;]control;} key. Type ;]H;} in the Control Mode to list available commands." #define kStrTooManyImagesTitle "Too many Disk Images" #define kStrTooManyImagesMessage "I can not mount that many Disk Images. Try ejecting one." #define kStrImageInUseTitle "Disk Image in use" #define kStrImageInUseMessage "I can not mount the Disk Image because it is already in use by another application or already open in ^p." #define kStrOutOfMemTitle "Not enough Memory" #define kStrOutOfMemMessage "There is not enough memory available to launch ^p." #define kStrNoROMTitle "Unable to locate ROM image" #define kStrNoROMMessage "I can not find the ROM image file ;[^r;{. For more information, see: ;[^w;{." #define kStrCorruptedROMTitle "ROM checksum failed" #define kStrCorruptedROMMessage "The ROM image file ;[^r;{ may be corrupted." #define kStrUnsupportedROMTitle "Unsupported ROM" #define kStrUnsupportedROMMessage "The ROM image file ;[^r;{ loaded successfully, but I don;}t support this ROM version." #define kStrQuitWarningTitle "Please shut down the emulated computer before quitting." #define kStrQuitWarningMessage "To force ^p to quit, at the risk of corrupting the mounted disk image files, use the ;]Q;} command of the ^p Control Mode. To learn about the Control Mode, see the ;[More Commands;ll;{ item in the ;[Special;{ menu." #define kStrReportAbnormalTitle "Abnormal Situation" #define kStrReportAbnormalMessage "The emulated computer is attempting an operation that wasn;}t expected to happen in normal use." #define kStrBadArgTitle "Unknown argument" #define kStrBadArgMessage "I did not understand one of the command line arguments, and ignored it." #define kStrOpenFailTitle "Open failed" #define kStrOpenFailMessage "I could not open the disk image." #define kStrNoReadROMTitle "Unable to read ROM image" #define kStrNoReadROMMessage "I found the ROM image file ;[^r;{, but I can not read it." #define kStrShortROMTitle "ROM image too short" #define kStrShortROMMessage "The ROM image file ;[^r;{ is shorter than it should be." /* state of a boolean option */ #define kStrOn "on" #define kStrOff "off" /* state of a key */ #define kStrPressed "pressed" #define kStrReleased "released" /* state of Stopped */ #define kStrStoppedOn kStrOn #define kStrStoppedOff kStrOff /* About Screen */ #define kStrProgramInfo "^v" #define kStrSponsorIs "^v. This variation is made for:" #define kStrWorkOfMany "Copyright ^y. ^p contains the work of many people. This version is maintained by:" #define kStrForMoreInfo "For more information, see:" #define kStrLicense "^p is distributed under the terms of the GNU Public License, version 2." #define kStrDisclaimer " ^p is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;ls without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." /* Help Screen */ #define kStrHowToLeaveControl "To leave the Control Mode, release the ;]control;} key." #define kStrHowToPickACommand "Otherwise, type a letter. Available commands are:" #define kStrCmdAbout "About (version information)" #define kStrCmdOpenDiskImage "Open disk image;ll" #define kStrCmdQuit "Quit" #define kStrCmdSpeedControl "Speed control;ll (^s)" #define kStrCmdMagnifyToggle "Magnify toggle (^g)" #define kStrCmdFullScrnToggle "Full screen toggle (^f)" #define kStrCmdCtrlKeyToggle "emulated ;]control;} Key toggle (^k)" #define kStrCmdReset "Reset" #define kStrCmdInterrupt "Interrupt" #define kStrCmdHelp "Help (show this page)" /* Speed Control Screen */ #define kStrCurrentSpeed "Current speed: ^s" #define kStrSpeedAllOut "All out" #define kStrSpeedStopped "stopped toggle (^h)" #define kStrSpeedBackToggle "run in Background toggle (^b)" #define kStrSpeedAutoSlowToggle "autosloW toggle (^l)" #define kStrSpeedExit "Exit speed control" #define kStrNewSpeed "Speed: ^s" #define kStrSpeedValueAllOut kStrSpeedAllOut #define kStrNewStopped "Stopped is ^h." #define kStrNewRunInBack "Run in background is ^b." #define kStrNewAutoSlow "AutoSlow is ^l." #define kStrNewMagnify "Magnify is ^g." #define kStrNewFullScreen "Full Screen is ^f." #define kStrNewCntrlKey "Emulated ;]control;} key ^k." #define kStrCmdCancel "cancel" #define kStrConfirmReset "Are you sure you want to reset the emulated computer? Unsaved changes will be lost, and there is a risk of corrupting the mounted disk image files. Type a letter:" #define kStrResetDo "reset" #define kStrResetNo kStrCmdCancel #define kStrHaveReset "Have reset the emulated computer" #define kStrCancelledReset "Reset cancelled" #define kStrConfirmInterrupt "Are you sure you want to interrupt the emulated computer? This will invoke any installed debugger. Type a letter:" #define kStrInterruptDo "interrupt" #define kStrInterruptNo kStrCmdCancel #define kStrHaveInterrupted "Have interrupted the emulated computer" #define kStrCancelledInterrupt "Interrupt cancelled" #define kStrConfirmQuit "Are you sure you want to quit ^p? You should shut down the emulated computer before quitting to prevent corrupting the mounted disk image files. Type a letter:" #define kStrQuitDo "quit" #define kStrQuitNo kStrCmdCancel #define kStrCancelledQuit "Quit cancelled" #define kStrModeConfirmReset "Control Mode : Confirm Reset" #define kStrModeConfirmInterrupt "Control Mode : Confirm Interrupt" #define kStrModeConfirmQuit "Control Mode : Confirm Quit" #define kStrModeSpeedControl "Control Mode : Speed Control" #define kStrModeControlBase "Control Mode (Type ;]H;} for help)" #define kStrModeControlHelp "Control Mode" #define kStrModeMessage "Message (Type ;]C;} to continue)" #define kStrMenuFile "File" #define kStrMenuSpecial "Special" #define kStrMenuHelp "Help" #define kStrMenuItemAbout "About ^p" #define kStrMenuItemOpen "Open Disk Image" #define kStrMenuItemQuit "Quit" #define kStrMenuItemMore "More Commands" #define kStrAppMenuItemHide "Hide ^p" #define kStrAppMenuItemHideOthers "Hide Others" #define kStrAppMenuItemShowAll "Show All" #define kStrAppMenuItemQuit "Quit ^p" \ No newline at end of file diff --git a/Mini vMac/mnvm_core/STRCONST.h b/Mini vMac/mnvm_core/STRCONST.h deleted file mode 100755 index d913321..0000000 --- a/Mini vMac/mnvm_core/STRCONST.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - STRCONST.h - - Copyright (C) 2006 Paul C. Pratt, Pierre Lemieux - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - STRing CONSTants (for English) - - Pierre Lemieux provided some corrections and suggestions. -*/ - -#define kStrAboutTitle "About" -#define kStrAboutMessage "To display information about this program, use the ;]A;} command of the ^p Control Mode. To learn about the Control Mode, see the ;[More Commands;ll;{ item in the ;[Special;{ menu." - -#define kStrMoreCommandsTitle "More commands are available in the ^p Control Mode." -#define kStrMoreCommandsMessage "To enter the Control Mode, press and hold down the ;]control;} key. You will remain in the Control Mode until you release the ;]control;} key. Type ;]H;} in the Control Mode to list available commands." - -#define kStrTooManyImagesTitle "Too many Disk Images" -#define kStrTooManyImagesMessage "I can not mount that many Disk Images. Try ejecting one." - -#define kStrImageInUseTitle "Disk Image in use" -#define kStrImageInUseMessage "I can not mount the Disk Image because it is already in use by another application or already open in ^p." - -#define kStrOutOfMemTitle "Not enough Memory" -#define kStrOutOfMemMessage "There is not enough memory available to launch ^p." - -#define kStrNoROMTitle "Unable to locate ROM image" -#define kStrNoROMMessage "I can not find the ROM image file ;[^r;{. For more information, see: ;[^w;{." - -#define kStrCorruptedROMTitle "ROM checksum failed" -#define kStrCorruptedROMMessage "The ROM image file ;[^r;{ may be corrupted." - -#define kStrUnsupportedROMTitle "Unsupported ROM" -#define kStrUnsupportedROMMessage "The ROM image file ;[^r;{ loaded successfully, but I don;}t support this ROM version." - -#define kStrQuitWarningTitle "Please shut down the emulated computer before quitting." -#define kStrQuitWarningMessage "To force ^p to quit, at the risk of corrupting the mounted disk image files, use the ;]Q;} command of the ^p Control Mode. To learn about the Control Mode, see the ;[More Commands;ll;{ item in the ;[Special;{ menu." - -#define kStrReportAbnormalTitle "Abnormal Situation" -#define kStrReportAbnormalMessage "The emulated computer is attempting an operation that wasn;}t expected to happen in normal use." - -#define kStrBadArgTitle "Unknown argument" -#define kStrBadArgMessage "I did not understand one of the command line arguments, and ignored it." - -#define kStrOpenFailTitle "Open failed" -#define kStrOpenFailMessage "I could not open the disk image." - -#define kStrNoReadROMTitle "Unable to read ROM image" -#define kStrNoReadROMMessage "I found the ROM image file ;[^r;{, but I can not read it." - -#define kStrShortROMTitle "ROM image too short" -#define kStrShortROMMessage "The ROM image file ;[^r;{ is shorter than it should be." - -/* state of a boolean option */ -#define kStrOn "on" -#define kStrOff "off" - -/* state of a key */ -#define kStrPressed "pressed" -#define kStrReleased "released" - -/* state of Stopped */ -#define kStrStoppedOn kStrOn -#define kStrStoppedOff kStrOff - -/* About Screen */ -#define kStrProgramInfo "^v" -#define kStrSponsorIs "^v. This variation is made for:" -#define kStrWorkOfMany "Copyright ^y. ^p contains the work of many people. This version is maintained by:" -#define kStrForMoreInfo "For more information, see:" -#define kStrLicense "^p is distributed under the terms of the GNU Public License, version 2." -#define kStrDisclaimer " ^p is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;ls without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -/* Help Screen */ -#define kStrHowToLeaveControl "To leave the Control Mode, release the ;]control;} key." -#define kStrHowToPickACommand "Otherwise, type a letter. Available commands are:" -#define kStrCmdAbout "About (version information)" -#define kStrCmdOpenDiskImage "Open disk image;ll" -#define kStrCmdQuit "Quit" -#define kStrCmdSpeedControl "Speed control;ll (^s)" -#define kStrCmdMagnifyToggle "Magnify toggle (^g)" -#define kStrCmdFullScrnToggle "Full screen toggle (^f)" -#define kStrCmdCtrlKeyToggle "emulated ;]control;} Key toggle (^k)" -#define kStrCmdReset "Reset" -#define kStrCmdInterrupt "Interrupt" -#define kStrCmdHelp "Help (show this page)" - -/* Speed Control Screen */ -#define kStrCurrentSpeed "Current speed: ^s" -#define kStrSpeedAllOut "All out" -#define kStrSpeedStopped "stopped toggle (^h)" -#define kStrSpeedBackToggle "run in Background toggle (^b)" -#define kStrSpeedAutoSlowToggle "autosloW toggle (^l)" -#define kStrSpeedExit "Exit speed control" - -#define kStrNewSpeed "Speed: ^s" -#define kStrSpeedValueAllOut kStrSpeedAllOut - -#define kStrNewStopped "Stopped is ^h." -#define kStrNewRunInBack "Run in background is ^b." -#define kStrNewAutoSlow "AutoSlow is ^l." - -#define kStrNewMagnify "Magnify is ^g." - -#define kStrNewFullScreen "Full Screen is ^f." - -#define kStrNewCntrlKey "Emulated ;]control;} key ^k." - -#define kStrCmdCancel "cancel" - -#define kStrConfirmReset "Are you sure you want to reset the emulated computer? Unsaved changes will be lost, and there is a risk of corrupting the mounted disk image files. Type a letter:" -#define kStrResetDo "reset" -#define kStrResetNo kStrCmdCancel - -#define kStrHaveReset "Have reset the emulated computer" - -#define kStrCancelledReset "Reset cancelled" - -#define kStrConfirmInterrupt "Are you sure you want to interrupt the emulated computer? This will invoke any installed debugger. Type a letter:" -#define kStrInterruptDo "interrupt" -#define kStrInterruptNo kStrCmdCancel - -#define kStrHaveInterrupted "Have interrupted the emulated computer" - -#define kStrCancelledInterrupt "Interrupt cancelled" - -#define kStrConfirmQuit "Are you sure you want to quit ^p? You should shut down the emulated computer before quitting to prevent corrupting the mounted disk image files. Type a letter:" -#define kStrQuitDo "quit" -#define kStrQuitNo kStrCmdCancel - -#define kStrCancelledQuit "Quit cancelled" - -#define kStrModeConfirmReset "Control Mode : Confirm Reset" -#define kStrModeConfirmInterrupt "Control Mode : Confirm Interrupt" -#define kStrModeConfirmQuit "Control Mode : Confirm Quit" -#define kStrModeSpeedControl "Control Mode : Speed Control" -#define kStrModeControlBase "Control Mode (Type ;]H;} for help)" -#define kStrModeControlHelp "Control Mode" -#define kStrModeMessage "Message (Type ;]C;} to continue)" - -#define kStrMenuFile "File" -#define kStrMenuSpecial "Special" -#define kStrMenuHelp "Help" - -#define kStrMenuItemAbout "About ^p" -#define kStrMenuItemOpen "Open Disk Image" -#define kStrMenuItemQuit "Quit" -#define kStrMenuItemMore "More Commands" - -#define kStrAppMenuItemHide "Hide ^p" -#define kStrAppMenuItemHideOthers "Hide Others" -#define kStrAppMenuItemShowAll "Show All" -#define kStrAppMenuItemQuit "Quit ^p" diff --git a/Mini vMac/mnvm_core/SYSDEPNS.h b/Mini vMac/mnvm_core/SYSDEPNS.h index 9c83a59..ec60c27 100755 --- a/Mini vMac/mnvm_core/SYSDEPNS.h +++ b/Mini vMac/mnvm_core/SYSDEPNS.h @@ -1,80 +1 @@ -/* - SYSDEPNS.h - - Copyright (C) 2006 Bernd Schmidt, Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - SYStem DEPeNdencies. -*/ - -#ifdef SYSDEPNS_H -#error "header already included" -#else -#define SYSDEPNS_H -#endif - -#include "CNFGGLOB.h" - - -typedef ui3b *ui3p; -typedef ui4b *ui4p; -typedef ui5b *ui5p; - -/* - Largest efficiently supported - representation types. uimr should be - large enough to hold number of elements - of any array we will deal with. -*/ -typedef ui5r uimr; -typedef si5r simr; - -#define blnr int -#define trueblnr 1 -#define falseblnr 0 - -#define nullpr ((void *) 0) - -#define anyp ui3p - -/* pascal string, single byte characters */ -#define ps3p ui3p - -#define LOCALVAR static -#ifdef AllFiles -#define GLOBALVAR LOCALVAR -#define EXPORTVAR(t, v) -#else -#define GLOBALVAR -#define EXPORTVAR(t, v) extern t v; -#endif - -#define LOCALFUNC static -#define FORWARDFUNC LOCALFUNC -#ifdef AllFiles -#define GLOBALFUNC LOCALFUNC -#define EXPORTFUNC LOCALFUNC -#else -#define GLOBALFUNC -#define EXPORTFUNC extern -#endif -#define IMPORTFUNC EXPORTFUNC -#define TYPEDEFFUNC typedef - -#define LOCALPROC LOCALFUNC void -#define GLOBALPROC GLOBALFUNC void -#define EXPORTPROC EXPORTFUNC void -#define IMPORTPROC IMPORTFUNC void -#define FORWARDPROC FORWARDFUNC void -#define TYPEDEFPROC TYPEDEFFUNC void +/* SYSDEPNS.h Copyright (C) 2006 Bernd Schmidt, Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* SYStem DEPeNdencies. */ #ifdef SYSDEPNS_H #error "header already included" #else #define SYSDEPNS_H #endif #include "CNFGGLOB.h" typedef ui3b *ui3p; typedef ui4b *ui4p; typedef ui5b *ui5p; /* Largest efficiently supported representation types. uimr should be large enough to hold number of elements of any array we will deal with. */ typedef ui5r uimr; typedef si5r simr; #define blnr ui3r #define trueblnr 1 #define falseblnr 0 #define nullpr ((void *) 0) #define anyp ui3p /* pascal string, single byte characters */ #define ps3p ui3p #ifndef MayInline #define MayInline #endif #ifndef MayNotInline #define MayNotInline #endif #ifndef my_reg_call #define my_reg_call #endif #ifndef my_osglu_call #define my_osglu_call #endif #define LOCALVAR static #ifdef AllFiles #define GLOBALVAR LOCALVAR #define EXPORTVAR(t, v) #else #define GLOBALVAR #define EXPORTVAR(t, v) extern t v; #endif #define LOCALFUNC static MayNotInline #define FORWARDFUNC LOCALFUNC #ifdef AllFiles #define GLOBALFUNC LOCALFUNC #define EXPORTFUNC LOCALFUNC #else #define GLOBALFUNC MayNotInline #define EXPORTFUNC extern #endif #define IMPORTFUNC EXPORTFUNC #define TYPEDEFFUNC typedef #define LOCALPROC LOCALFUNC void #define GLOBALPROC GLOBALFUNC void #define EXPORTPROC EXPORTFUNC void #define IMPORTPROC IMPORTFUNC void #define FORWARDPROC FORWARDFUNC void #define TYPEDEFPROC TYPEDEFFUNC void #define LOCALINLINEFUNC static MayInline #define LOCALINLINEPROC LOCALINLINEFUNC void #define LOCALFUNCUSEDONCE LOCALINLINEFUNC #define LOCALPROCUSEDONCE LOCALINLINEPROC #define GLOBALOSGLUFUNC GLOBALFUNC my_osglu_call #define EXPORTOSGLUFUNC EXPORTFUNC my_osglu_call #define GLOBALOSGLUPROC GLOBALFUNC my_osglu_call void #define EXPORTOSGLUPROC EXPORTFUNC my_osglu_call void /* For functions in operating system glue that are called by rest of program. */ /* best type for ui4r that is probably in register (when compiler messes up otherwise) */ #ifndef BigEndianUnaligned #define BigEndianUnaligned 0 #endif #ifndef LittleEndianUnaligned #define LittleEndianUnaligned 0 #endif #ifndef ui3rr #define ui3rr ui3r #endif #ifndef ui4rr #define ui4rr ui4r #endif #ifndef si5rr #define si5rr si5r #endif #ifndef my_align_8 #define my_align_8 #endif #ifndef my_cond_rare #define my_cond_rare(x) (x) #endif #ifndef Have_ASR #define Have_ASR 0 #endif #ifndef HaveMySwapUi5r #define HaveMySwapUi5r 0 #endif \ No newline at end of file diff --git a/Mini vMac/mnvm_core/VIA2EMDV.c b/Mini vMac/mnvm_core/VIA2EMDV.c index 2c02999..60ae085 100755 --- a/Mini vMac/mnvm_core/VIA2EMDV.c +++ b/Mini vMac/mnvm_core/VIA2EMDV.c @@ -1,1215 +1 @@ -/* - VIA2EMDV.c - - Copyright (C) 2008 Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - Versatile Interface Adapter EMulated DEVice - - Emulates the VIA found in the Mac Plus. - - This code adapted from vMac by Philip Cummins. -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" - -#include "MYOSGLUE.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" -#endif - -#include "VIA2EMDV.h" - -#ifdef VIA2_iA0_ChangeNtfy -IMPORTPROC VIA2_iA0_ChangeNtfy(void); -#endif - -#ifdef VIA2_iA1_ChangeNtfy -IMPORTPROC VIA2_iA1_ChangeNtfy(void); -#endif - -#ifdef VIA2_iA2_ChangeNtfy -IMPORTPROC VIA2_iA2_ChangeNtfy(void); -#endif - -#ifdef VIA2_iA3_ChangeNtfy -IMPORTPROC VIA2_iA3_ChangeNtfy(void); -#endif - -#ifdef VIA2_iA4_ChangeNtfy -IMPORTPROC VIA2_iA4_ChangeNtfy(void); -#endif - -#ifdef VIA2_iA5_ChangeNtfy -IMPORTPROC VIA2_iA5_ChangeNtfy(void); -#endif - -#ifdef VIA2_iA6_ChangeNtfy -IMPORTPROC VIA2_iA6_ChangeNtfy(void); -#endif - -#ifdef VIA2_iA7_ChangeNtfy -IMPORTPROC VIA2_iA7_ChangeNtfy(void); -#endif - -#ifdef VIA2_iB0_ChangeNtfy -IMPORTPROC VIA2_iB0_ChangeNtfy(void); -#endif - -#ifdef VIA2_iB1_ChangeNtfy -IMPORTPROC VIA2_iB1_ChangeNtfy(void); -#endif - -#ifdef VIA2_iB2_ChangeNtfy -IMPORTPROC VIA2_iB2_ChangeNtfy(void); -#endif - -#ifdef VIA2_iB3_ChangeNtfy -IMPORTPROC VIA2_iB3_ChangeNtfy(void); -#endif - -#ifdef VIA2_iB4_ChangeNtfy -IMPORTPROC VIA2_iB4_ChangeNtfy(void); -#endif - -#ifdef VIA2_iB5_ChangeNtfy -IMPORTPROC VIA2_iB5_ChangeNtfy(void); -#endif - -#ifdef VIA2_iB6_ChangeNtfy -IMPORTPROC VIA2_iB6_ChangeNtfy(void); -#endif - -#ifdef VIA2_iB7_ChangeNtfy -IMPORTPROC VIA2_iB7_ChangeNtfy(void); -#endif - -#ifdef VIA2_iCB2_ChangeNtfy -IMPORTPROC VIA2_iCB2_ChangeNtfy(void); -#endif - -#define Ui3rPowOf2(p) (1 << (p)) -#define Ui3rTestBit(i, p) (((i) & Ui3rPowOf2(p)) != 0) - -#define VIA2_ORA_CanInOrOut (VIA2_ORA_CanIn | VIA2_ORA_CanOut) - -#if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 7) -#ifdef VIA2_iA7 -#error "VIA2_iA7 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 6) -#ifdef VIA2_iA6 -#error "VIA2_iA6 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 5) -#ifdef VIA2_iA5 -#error "VIA2_iA5 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 4) -#ifdef VIA2_iA4 -#error "VIA2_iA4 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 3) -#ifdef VIA2_iA3 -#error "VIA2_iA3 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 2) -#ifdef VIA2_iA2 -#error "VIA2_iA2 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 1) -#ifdef VIA2_iA1 -#error "VIA2_iA1 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 0) -#ifdef VIA2_iA0 -#error "VIA2_iA0 defined but not used" -#endif -#endif - -#define VIA2_ORB_CanInOrOut (VIA2_ORB_CanIn | VIA2_ORB_CanOut) - -#if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 7) -#ifdef VIA2_iB7 -#error "VIA2_iB7 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 6) -#ifdef VIA2_iB6 -#error "VIA2_iB6 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 5) -#ifdef VIA2_iB5 -#error "VIA2_iB5 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 4) -#ifdef VIA2_iB4 -#error "VIA2_iB4 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 3) -#ifdef VIA2_iB3 -#error "VIA2_iB3 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 2) -#ifdef VIA2_iB2 -#error "VIA2_iB2 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 1) -#ifdef VIA2_iB1 -#error "VIA2_iB1 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 0) -#ifdef VIA2_iB0 -#error "VIA2_iB0 defined but not used" -#endif -#endif - -typedef struct { - ui5b T1C_F; /* Timer 1 Counter Fixed Point */ - ui5b T2C_F; /* Timer 2 Counter Fixed Point */ - ui3b ORB; /* Buffer B */ - /* ui3b ORA_H; Buffer A with Handshake */ - ui3b DDR_B; /* Data Direction Register B */ - ui3b DDR_A; /* Data Direction Register A */ - ui3b T1L_L; /* Timer 1 Latch Low */ - ui3b T1L_H; /* Timer 1 Latch High */ - ui3b T2L_L; /* Timer 2 Latch Low */ - ui3b SR; /* Shift Register */ - ui3b ACR; /* Auxiliary Control Register */ - ui3b PCR; /* Peripheral Control Register */ - ui3b IFR; /* Interrupt Flag Register */ - ui3b IER; /* Interrupt Enable Register */ - ui3b ORA; /* Buffer A */ -} VIA2_Ty; - -LOCALVAR VIA2_Ty VIA2_D; - -#define kIntCA2 0 /* One_Second */ -#define kIntCA1 1 /* Vertical_Blanking */ -#define kIntSR 2 /* Keyboard_Data_Ready */ -#define kIntCB2 3 /* Keyboard_Data */ -#define kIntCB1 4 /* Keyboard_Clock */ -#define kIntT2 5 /* Timer_2 */ -#define kIntT1 6 /* Timer_1 */ - -#define VIA2_dolog (dbglog_HAVE && 0) - -/* VIA2_Get_ORA : VIA Get Port A Data */ -/* - This function queries VIA Port A interfaced hardware - about their status -*/ - -LOCALFUNC ui3b VIA2_Get_ORA(ui3b Selection) -{ - ui3b Value = (~ VIA2_ORA_CanIn) & Selection & VIA2_ORA_FloatVal; - -#if Ui3rTestBit(VIA2_ORA_CanIn, 7) - if (Ui3rTestBit(Selection, 7)) { - Value |= (VIA2_iA7 << 7); - } -#endif - -#if Ui3rTestBit(VIA2_ORA_CanIn, 6) - if (Ui3rTestBit(Selection, 6)) { - Value |= (VIA2_iA6 << 6); - } -#endif - -#if Ui3rTestBit(VIA2_ORA_CanIn, 5) - if (Ui3rTestBit(Selection, 5)) { - Value |= (VIA2_iA5 << 5); - } -#endif - -#if Ui3rTestBit(VIA2_ORA_CanIn, 4) - if (Ui3rTestBit(Selection, 4)) { - Value |= (VIA2_iA4 << 4); - } -#endif - -#if Ui3rTestBit(VIA2_ORA_CanIn, 3) - if (Ui3rTestBit(Selection, 3)) { - Value |= (VIA2_iA3 << 3); - } -#endif - -#if Ui3rTestBit(VIA2_ORA_CanIn, 2) - if (Ui3rTestBit(Selection, 2)) { - Value |= (VIA2_iA2 << 2); - } -#endif - -#if Ui3rTestBit(VIA2_ORA_CanIn, 1) - if (Ui3rTestBit(Selection, 1)) { - Value |= (VIA2_iA1 << 1); - } -#endif - -#if Ui3rTestBit(VIA2_ORA_CanIn, 0) - if (Ui3rTestBit(Selection, 0)) { - Value |= (VIA2_iA0 << 0); - } -#endif - - return Value; -} - -/* VIA2_Get_ORB : VIA Get Port B Data */ -/* - This function queries VIA Port B interfaced hardware - about their status -*/ - -LOCALFUNC ui3b VIA2_Get_ORB(ui3b Selection) -{ - ui3b Value = (~ VIA2_ORB_CanIn) & Selection & VIA2_ORB_FloatVal; - -#if Ui3rTestBit(VIA2_ORB_CanIn, 7) - if (Ui3rTestBit(Selection, 7)) { - Value |= (VIA2_iB7 << 7); - } -#endif - -#if Ui3rTestBit(VIA2_ORB_CanIn, 6) - if (Ui3rTestBit(Selection, 6)) { - Value |= (VIA2_iB6 << 6); - } -#endif - -#if Ui3rTestBit(VIA2_ORB_CanIn, 5) - if (Ui3rTestBit(Selection, 5)) { - Value |= (VIA2_iB5 << 5); - } -#endif - -#if Ui3rTestBit(VIA2_ORB_CanIn, 4) - if (Ui3rTestBit(Selection, 4)) { - Value |= (VIA2_iB4 << 4); - } -#endif - -#if Ui3rTestBit(VIA2_ORB_CanIn, 3) - if (Ui3rTestBit(Selection, 3)) { - Value |= (VIA2_iB3 << 3); - } -#endif - -#if Ui3rTestBit(VIA2_ORB_CanIn, 2) - if (Ui3rTestBit(Selection, 2)) { - Value |= (VIA2_iB2 << 2); - } -#endif - -#if Ui3rTestBit(VIA2_ORB_CanIn, 1) - if (Ui3rTestBit(Selection, 1)) { - Value |= (VIA2_iB1 << 1); - } -#endif - -#if Ui3rTestBit(VIA2_ORB_CanIn, 0) - if (Ui3rTestBit(Selection, 0)) { - Value |= (VIA2_iB0 << 0); - } -#endif - - return Value; -} - -#define ViaORcheckBit(p, x) \ - (Ui3rTestBit(Selection, p) && \ - ((v = (Data >> p) & 1) != x)) - -LOCALPROC VIA2_Put_ORA(ui3b Selection, ui3b Data) -{ -#if 0 != VIA2_ORA_CanOut - ui3b v; -#endif - -#if Ui3rTestBit(VIA2_ORA_CanOut, 7) - if (ViaORcheckBit(7, VIA2_iA7)) { - VIA2_iA7 = v; -#ifdef VIA2_iA7_ChangeNtfy - VIA2_iA7_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA2_ORA_CanOut, 6) - if (ViaORcheckBit(6, VIA2_iA6)) { - VIA2_iA6 = v; -#ifdef VIA2_iA6_ChangeNtfy - VIA2_iA6_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA2_ORA_CanOut, 5) - if (ViaORcheckBit(5, VIA2_iA5)) { - VIA2_iA5 = v; -#ifdef VIA2_iA5_ChangeNtfy - VIA2_iA5_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA2_ORA_CanOut, 4) - if (ViaORcheckBit(4, VIA2_iA4)) { - VIA2_iA4 = v; -#ifdef VIA2_iA4_ChangeNtfy - VIA2_iA4_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA2_ORA_CanOut, 3) - if (ViaORcheckBit(3, VIA2_iA3)) { - VIA2_iA3 = v; -#ifdef VIA2_iA3_ChangeNtfy - VIA2_iA3_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA2_ORA_CanOut, 2) - if (ViaORcheckBit(2, VIA2_iA2)) { - VIA2_iA2 = v; -#ifdef VIA2_iA2_ChangeNtfy - VIA2_iA2_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA2_ORA_CanOut, 1) - if (ViaORcheckBit(1, VIA2_iA1)) { - VIA2_iA1 = v; -#ifdef VIA2_iA1_ChangeNtfy - VIA2_iA1_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA2_ORA_CanOut, 0) - if (ViaORcheckBit(0, VIA2_iA0)) { - VIA2_iA0 = v; -#ifdef VIA2_iA0_ChangeNtfy - VIA2_iA0_ChangeNtfy(); -#endif - } -#endif -} - -LOCALPROC VIA2_Put_ORB(ui3b Selection, ui3b Data) -{ -#if 0 != VIA2_ORB_CanOut - ui3b v; -#endif - -#if Ui3rTestBit(VIA2_ORB_CanOut, 7) - if (ViaORcheckBit(7, VIA2_iB7)) { - VIA2_iB7 = v; -#ifdef VIA2_iB7_ChangeNtfy - VIA2_iB7_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA2_ORB_CanOut, 6) - if (ViaORcheckBit(6, VIA2_iB6)) { - VIA2_iB6 = v; -#ifdef VIA2_iB6_ChangeNtfy - VIA2_iB6_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA2_ORB_CanOut, 5) - if (ViaORcheckBit(5, VIA2_iB5)) { - VIA2_iB5 = v; -#ifdef VIA2_iB5_ChangeNtfy - VIA2_iB5_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA2_ORB_CanOut, 4) - if (ViaORcheckBit(4, VIA2_iB4)) { - VIA2_iB4 = v; -#ifdef VIA2_iB4_ChangeNtfy - VIA2_iB4_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA2_ORB_CanOut, 3) - if (ViaORcheckBit(3, VIA2_iB3)) { - VIA2_iB3 = v; -#ifdef VIA2_iB3_ChangeNtfy - VIA2_iB3_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA2_ORB_CanOut, 2) - if (ViaORcheckBit(2, VIA2_iB2)) { - VIA2_iB2 = v; -#ifdef VIA2_iB2_ChangeNtfy - VIA2_iB2_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA2_ORB_CanOut, 1) - if (ViaORcheckBit(1, VIA2_iB1)) { - VIA2_iB1 = v; -#ifdef VIA2_iB1_ChangeNtfy - VIA2_iB1_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA2_ORB_CanOut, 0) - if (ViaORcheckBit(0, VIA2_iB0)) { - VIA2_iB0 = v; -#ifdef VIA2_iB0_ChangeNtfy - VIA2_iB0_ChangeNtfy(); -#endif - } -#endif -} - -LOCALPROC VIA2_SetDDR_A(ui3b Data) -{ - ui3b floatbits = VIA2_D.DDR_A & ~ Data; - ui3b unfloatbits = Data & ~ VIA2_D.DDR_A; - - if (floatbits != 0) { - VIA2_Put_ORA(floatbits, VIA2_ORA_FloatVal); - } - VIA2_D.DDR_A = Data; - if (unfloatbits != 0) { - VIA2_Put_ORA(unfloatbits, VIA2_D.ORA); - } - if ((Data & ~ VIA2_ORA_CanOut) != 0) { - ReportAbnormal("Set VIA2_D.DDR_A unexpected direction"); - } -} - -LOCALPROC VIA2_SetDDR_B(ui3b Data) -{ - ui3b floatbits = VIA2_D.DDR_B & ~ Data; - ui3b unfloatbits = Data & ~ VIA2_D.DDR_B; - - if (floatbits != 0) { - VIA2_Put_ORB(floatbits, VIA2_ORB_FloatVal); - } - VIA2_D.DDR_B = Data; - if (unfloatbits != 0) { - VIA2_Put_ORB(unfloatbits, VIA2_D.ORB); - } - if ((Data & ~ VIA2_ORB_CanOut) != 0) { - ReportAbnormal("Set VIA2_D.DDR_B unexpected direction"); - } -} - - -LOCALPROC VIA2_CheckInterruptFlag(void) -{ - ui3b NewInterruptRequest = - ((VIA2_D.IFR & VIA2_D.IER) != 0) ? 1 : 0; - - if (NewInterruptRequest != VIA2_InterruptRequest) { - VIA2_InterruptRequest = NewInterruptRequest; -#ifdef VIA2_interruptChngNtfy - VIA2_interruptChngNtfy(); -#endif - } -} - - -LOCALVAR ui3b VIA2_T1_Active = 0; -LOCALVAR ui3b VIA2_T2_Active = 0; - -LOCALVAR blnr VIA2_T1IntReady = falseblnr; - -LOCALPROC VIA2_Clear(void) -{ - VIA2_D.ORA = 0; VIA2_D.DDR_A = 0; - VIA2_D.ORB = 0; VIA2_D.DDR_B = 0; - VIA2_D.T1L_L = VIA2_D.T1L_H = 0x00; - VIA2_D.T2L_L = 0x00; - VIA2_D.T1C_F = 0; - VIA2_D.T2C_F = 0; - VIA2_D.SR = VIA2_D.ACR = 0x00; - VIA2_D.PCR = VIA2_D.IFR = VIA2_D.IER = 0x00; - VIA2_T1_Active = VIA2_T2_Active = 0x00; - VIA2_T1IntReady = falseblnr; -} - -GLOBALPROC VIA2_Zap(void) -{ - VIA2_Clear(); - VIA2_InterruptRequest = 0; -} - -GLOBALPROC VIA2_Reset(void) -{ - VIA2_SetDDR_A(0); - VIA2_SetDDR_B(0); - - VIA2_Clear(); - - VIA2_CheckInterruptFlag(); -} - -LOCALPROC VIA2_SetInterruptFlag(ui3b VIA_Int) -{ - VIA2_D.IFR |= ((ui3b)1 << VIA_Int); - VIA2_CheckInterruptFlag(); -} - -LOCALPROC VIA2_ClrInterruptFlag(ui3b VIA_Int) -{ - VIA2_D.IFR &= ~ ((ui3b)1 << VIA_Int); - VIA2_CheckInterruptFlag(); -} - -#ifdef _VIA_Debug -#include -#endif - -GLOBALPROC VIA2_ShiftInData(ui3b v) -{ - /* - external hardware generates 8 pulses on CB1, - writes 8 bits to CB2 - */ - ui3b ShiftMode = (VIA2_D.ACR & 0x1C) >> 2; - if (ShiftMode != 3) { - if (ShiftMode == 0) { - /* happens on reset */ - } else { - ReportAbnormal("VIA Not ready to shift in"); - } - } else { - VIA2_D.SR = v; - VIA2_SetInterruptFlag(kIntSR); - VIA2_SetInterruptFlag(kIntCB1); - } -} - -GLOBALFUNC ui3b VIA2_ShiftOutData(void) -{ - /* - external hardware generates 8 pulses on CB1, - reads 8 bits from CB2 - */ - if (((VIA2_D.ACR & 0x1C) >> 2) != 7) { - ReportAbnormal("VIA Not ready to shift out"); - return 0; - } else { - VIA2_SetInterruptFlag(kIntSR); - VIA2_SetInterruptFlag(kIntCB1); - VIA2_iCB2 = (VIA2_D.SR & 1); - return VIA2_D.SR; - } -} - -#define CyclesPerViaTime (10 * kMyClockMult) -#define CyclesScaledPerViaTime (kCycleScale * CyclesPerViaTime) - -LOCALVAR blnr VIA2_T1Running = trueblnr; -LOCALVAR iCountt VIA2_T1LastTime = 0; - -GLOBALPROC VIA2_DoTimer1Check(void) -{ - if (VIA2_T1Running) { - iCountt NewTime = GetCuriCount(); - iCountt deltaTime = (NewTime - VIA2_T1LastTime); - if (deltaTime != 0) { - ui5b Temp = VIA2_D.T1C_F; /* Get Timer 1 Counter */ - ui5b deltaTemp = - (deltaTime / CyclesPerViaTime) << (16 - kLn2CycleScale); - /* may overflow */ - ui5b NewTemp = Temp - deltaTemp; - if ((deltaTime > (0x00010000UL * CyclesScaledPerViaTime)) - || ((Temp <= deltaTemp) && (Temp != 0))) - { - if ((VIA2_D.ACR & 0x40) != 0) { /* Free Running? */ - /* Reload Counter from Latches */ - ui4b v = (VIA2_D.T1L_H << 8) + VIA2_D.T1L_L; - ui4b ntrans = 1 + ((v == 0) ? 0 : - (((deltaTemp - Temp) / v) >> 16)); - NewTemp += (((ui5b)v * ntrans) << 16); -#if Ui3rTestBit(VIA2_ORB_CanOut, 7) - if ((VIA2_D.ACR & 0x80) != 0) { /* invert ? */ - if ((ntrans & 1) != 0) { - VIA2_iB7 ^= 1; -#ifdef VIA2_iB7_ChangeNtfy - VIA2_iB7_ChangeNtfy(); -#endif - } - } -#endif - VIA2_SetInterruptFlag(kIntT1); -#if VIA2_dolog && 1 - dbglog_StartLine(); - dbglog_writeCStr("VIA2 Timer 1 Interrupt"); - dbglog_writeReturn(); -#endif - } else { - if (VIA2_T1_Active == 1) { - VIA2_T1_Active = 0; - VIA2_SetInterruptFlag(kIntT1); -#if VIA2_dolog && 1 - dbglog_StartLine(); - dbglog_writeCStr("VIA2 Timer 1 Interrupt"); - dbglog_writeReturn(); -#endif - } - } - } - - VIA2_D.T1C_F = NewTemp; - VIA2_T1LastTime = NewTime; - } - - VIA2_T1IntReady = falseblnr; - if ((VIA2_D.IFR & (1 << kIntT1)) == 0) { - if (((VIA2_D.ACR & 0x40) != 0) || (VIA2_T1_Active == 1)) { - ui5b NewTemp = VIA2_D.T1C_F; /* Get Timer 1 Counter */ - ui5b NewTimer; -#ifdef _VIA_Debug - fprintf(stderr, "posting Timer1Check, %d, %d\n", - Temp, GetCuriCount()); -#endif - if (NewTemp == 0) { - NewTimer = (0x00010000UL * CyclesScaledPerViaTime); - } else { - NewTimer = - (1 + (NewTemp >> (16 - kLn2CycleScale))) - * CyclesPerViaTime; - } - ICT_add(kICT_VIA2_Timer1Check, NewTimer); - VIA2_T1IntReady = trueblnr; - } - } - } -} - -LOCALPROC CheckT1IntReady(void) -{ - if (VIA2_T1Running) { - blnr NewT1IntReady = falseblnr; - - if ((VIA2_D.IFR & (1 << kIntT1)) == 0) { - if (((VIA2_D.ACR & 0x40) != 0) || (VIA2_T1_Active == 1)) { - NewT1IntReady = trueblnr; - } - } - - if (VIA2_T1IntReady != NewT1IntReady) { - VIA2_T1IntReady = NewT1IntReady; - if (NewT1IntReady) { - VIA2_DoTimer1Check(); - } - } - } -} - -GLOBALFUNC ui4b VIA2_GetT1InvertTime(void) -{ - ui4b v; - - if ((VIA2_D.ACR & 0xC0) == 0xC0) { - v = (VIA2_D.T1L_H << 8) + VIA2_D.T1L_L; - } else { - v = 0; - } - return v; -} - -LOCALVAR blnr VIA2_T2Running = trueblnr; -LOCALVAR blnr VIA2_T2C_ShortTime = falseblnr; -LOCALVAR iCountt VIA2_T2LastTime = 0; - -GLOBALPROC VIA2_DoTimer2Check(void) -{ - if (VIA2_T2Running) { - iCountt NewTime = GetCuriCount(); - ui5b Temp = VIA2_D.T2C_F; /* Get Timer 2 Counter */ - iCountt deltaTime = (NewTime - VIA2_T2LastTime); - ui5b deltaTemp = (deltaTime / CyclesPerViaTime) - << (16 - kLn2CycleScale); /* may overflow */ - ui5b NewTemp = Temp - deltaTemp; - if (VIA2_T2_Active == 1) { - if ((deltaTime > (0x00010000UL * CyclesScaledPerViaTime)) - || ((Temp <= deltaTemp) && (Temp != 0))) - { - VIA2_T2C_ShortTime = falseblnr; - VIA2_T2_Active = 0; - VIA2_SetInterruptFlag(kIntT2); -#if VIA2_dolog && 1 - dbglog_StartLine(); - dbglog_writeCStr("VIA2 Timer 2 Interrupt"); - dbglog_writeReturn(); -#endif - } else { - ui5b NewTimer; -#ifdef _VIA_Debug - fprintf(stderr, "posting Timer2Check, %d, %d\n", - Temp, GetCuriCount()); -#endif - if (NewTemp == 0) { - NewTimer = (0x00010000UL * CyclesScaledPerViaTime); - } else { - NewTimer = (1 + (NewTemp >> (16 - kLn2CycleScale))) - * CyclesPerViaTime; - } - ICT_add(kICT_VIA2_Timer2Check, NewTimer); - } - } - VIA2_D.T2C_F = NewTemp; - VIA2_T2LastTime = NewTime; - } -} - -#define kORB 0x00 -#define kORA_H 0x01 -#define kDDR_B 0x02 -#define kDDR_A 0x03 -#define kT1C_L 0x04 -#define kT1C_H 0x05 -#define kT1L_L 0x06 -#define kT1L_H 0x07 -#define kT2_L 0x08 -#define kT2_H 0x09 -#define kSR 0x0A -#define kACR 0x0B -#define kPCR 0x0C -#define kIFR 0x0D -#define kIER 0x0E -#define kORA 0x0F - -GLOBALFUNC ui5b VIA2_Access(ui5b Data, blnr WriteMem, CPTR addr) -{ - switch (addr) { - case kORB : -#if VIA2_CB2modesAllowed != 0x01 - if ((VIA2_D.PCR & 0xE0) == 0) -#endif - { - VIA2_ClrInterruptFlag(kIntCB2); - } - VIA2_ClrInterruptFlag(kIntCB1); - if (WriteMem) { - VIA2_D.ORB = Data; - VIA2_Put_ORB(VIA2_D.DDR_B, VIA2_D.ORB); - } else { - Data = (VIA2_D.ORB & VIA2_D.DDR_B) - | VIA2_Get_ORB(~ VIA2_D.DDR_B); - } -#if VIA2_dolog && 1 - dbglog_Access("VIA2_Access kORB", Data, WriteMem); -#endif - break; - case kDDR_B : - if (WriteMem) { - VIA2_SetDDR_B(Data); - } else { - Data = VIA2_D.DDR_B; - } -#if VIA2_dolog && 1 - dbglog_Access("VIA2_Access kDDR_B", Data, WriteMem); -#endif - break; - case kDDR_A : - if (WriteMem) { - VIA2_SetDDR_A(Data); - } else { - Data = VIA2_D.DDR_A; - } -#if VIA2_dolog && 1 - dbglog_Access("VIA2_Access kDDR_A", Data, WriteMem); -#endif - break; - case kT1C_L : - if (WriteMem) { - VIA2_D.T1L_L = Data; - } else { - VIA2_ClrInterruptFlag(kIntT1); - VIA2_DoTimer1Check(); - Data = (VIA2_D.T1C_F & 0x00FF0000) >> 16; - } -#if VIA2_dolog && 1 - dbglog_Access("VIA2_Access kT1C_L", Data, WriteMem); -#endif - break; - case kT1C_H : - if (WriteMem) { - VIA2_D.T1L_H = Data; - VIA2_ClrInterruptFlag(kIntT1); - VIA2_D.T1C_F = (Data << 24) + (VIA2_D.T1L_L << 16); - if ((VIA2_D.ACR & 0x40) == 0) { - VIA2_T1_Active = 1; - } - VIA2_T1LastTime = GetCuriCount(); - VIA2_DoTimer1Check(); - } else { - VIA2_DoTimer1Check(); - Data = (VIA2_D.T1C_F & 0xFF000000) >> 24; - } -#if VIA2_dolog && 1 - dbglog_Access("VIA2_Access kT1C_H", Data, WriteMem); -#endif - break; - case kT1L_L : - if (WriteMem) { - VIA2_D.T1L_L = Data; - } else { - Data = VIA2_D.T1L_L; - } -#if VIA2_dolog && 1 - dbglog_Access("VIA2_Access kT1L_L", Data, WriteMem); -#endif - break; - case kT1L_H : - if (WriteMem) { - VIA2_D.T1L_H = Data; - } else { - Data = VIA2_D.T1L_H; - } -#if VIA2_dolog && 1 - dbglog_Access("VIA2_Access kT1L_H", Data, WriteMem); -#endif - break; - case kT2_L : - if (WriteMem) { - VIA2_D.T2L_L = Data; - } else { - VIA2_ClrInterruptFlag(kIntT2); - VIA2_DoTimer2Check(); - Data = (VIA2_D.T2C_F & 0x00FF0000) >> 16; - } -#if VIA2_dolog && 1 - dbglog_Access("VIA2_Access kT2_L", Data, WriteMem); -#endif - break; - case kT2_H : - if (WriteMem) { - VIA2_D.T2C_F = (Data << 24) + (VIA2_D.T2L_L << 16); - VIA2_ClrInterruptFlag(kIntT2); - VIA2_T2_Active = 1; - - if ((VIA2_D.T2C_F < (128UL << 16)) - && (VIA2_D.T2C_F != 0)) - { - VIA2_T2C_ShortTime = trueblnr; - VIA2_T2Running = trueblnr; - /* - Running too many instructions during - a short timer interval can crash when - playing sounds in System 7. So - in this case don't let timer pause. - */ - } - VIA2_T2LastTime = GetCuriCount(); - VIA2_DoTimer2Check(); - } else { - VIA2_DoTimer2Check(); - Data = (VIA2_D.T2C_F & 0xFF000000) >> 24; - } -#if VIA2_dolog && 1 - dbglog_Access("VIA2_Access kT2_H", Data, WriteMem); -#endif - break; - case kSR: -#ifdef _VIA_Debug - fprintf(stderr, "VIA2_D.SR: %d, %d, %d\n", - WriteMem, ((VIA2_D.ACR & 0x1C) >> 2), Data); -#endif - if (WriteMem) { - VIA2_D.SR = Data; - } - VIA2_ClrInterruptFlag(kIntSR); - switch ((VIA2_D.ACR & 0x1C) >> 2) { - case 3 : /* Shifting In */ - break; - case 6 : /* shift out under o2 clock */ - if ((! WriteMem) || (VIA2_D.SR != 0)) { - ReportAbnormal("VIA shift mode 6, non zero"); - } else { -#ifdef _VIA_Debug - fprintf(stderr, "posting Foo2Task\n"); -#endif - if (VIA2_iCB2 != 0) { - VIA2_iCB2 = 0; -#ifdef VIA2_iCB2_ChangeNtfy - VIA2_iCB2_ChangeNtfy(); -#endif - } - } -#if 0 /* possibly should do this. seems not to affect anything. */ - VIA2_SetInterruptFlag(kIntSR); /* don't wait */ -#endif - break; - case 7 : /* Shifting Out */ - break; - } - if (! WriteMem) { - Data = VIA2_D.SR; - } -#if VIA2_dolog && 1 - dbglog_Access("VIA2_Access kSR", Data, WriteMem); -#endif - break; - case kACR: - if (WriteMem) { -#if 1 - if ((VIA2_D.ACR & 0x10) != ((ui3b)Data & 0x10)) { - /* shift direction has changed */ - if ((Data & 0x10) == 0) { - /* - no longer an output, - set data to float value - */ - if (VIA2_iCB2 == 0) { - VIA2_iCB2 = 1; -#ifdef VIA2_iCB2_ChangeNtfy - VIA2_iCB2_ChangeNtfy(); -#endif - } - } - } -#endif - VIA2_D.ACR = Data; - if ((VIA2_D.ACR & 0x20) != 0) { - /* Not pulse counting? */ - ReportAbnormal( - "Set VIA2_D.ACR T2 Timer pulse counting"); - } - switch ((VIA2_D.ACR & 0xC0) >> 6) { - /* case 1: happens in early System 6 */ - case 2: - ReportAbnormal( - "Set VIA2_D.ACR T1 Timer mode 2"); - break; - } - CheckT1IntReady(); - switch ((VIA2_D.ACR & 0x1C) >> 2) { - case 0: /* this isn't sufficient */ - VIA2_ClrInterruptFlag(kIntSR); - break; - case 1: - case 2: - case 4: - case 5: - ReportAbnormal( - "Set VIA2_D.ACR shift mode 1,2,4,5"); - break; - default: - break; - } - if ((VIA2_D.ACR & 0x03) != 0) { - ReportAbnormal( - "Set VIA2_D.ACR T2 Timer latching enabled"); - } - } else { - Data = VIA2_D.ACR; - } -#if VIA2_dolog && 1 - dbglog_Access("VIA2_Access kACR", Data, WriteMem); -#endif - break; - case kPCR: - if (WriteMem) { - VIA2_D.PCR = Data; -#define Ui3rSetContains(s, i) (((s) & (1 << (i))) != 0) - if (! Ui3rSetContains(VIA2_CB2modesAllowed, - (VIA2_D.PCR >> 5) & 0x07)) - { - ReportAbnormal("Set VIA2_D.PCR CB2 Control mode?"); - } - if ((VIA2_D.PCR & 0x10) != 0) { - ReportAbnormal( - "Set VIA2_D.PCR CB1 INTERRUPT CONTROL?"); - } - if (! Ui3rSetContains(VIA2_CA2modesAllowed, - (VIA2_D.PCR >> 1) & 0x07)) - { - ReportAbnormal( - "Set VIA2_D.PCR CA2 INTERRUPT CONTROL?"); - } - if ((VIA2_D.PCR & 0x01) != 0) { - ReportAbnormal( - "Set VIA2_D.PCR CA1 INTERRUPT CONTROL?"); - } - } else { - Data = VIA2_D.PCR; - } -#if VIA2_dolog && 1 - dbglog_Access("VIA2_Access kPCR", Data, WriteMem); -#endif - break; - case kIFR: - if (WriteMem) { - VIA2_D.IFR = VIA2_D.IFR & ((~ Data) & 0x7F); - /* Clear Flag Bits */ - VIA2_CheckInterruptFlag(); - CheckT1IntReady(); - } else { - Data = VIA2_D.IFR; - if ((VIA2_D.IFR & VIA2_D.IER) != 0) { - Data |= 0x80; - } - } -#if VIA2_dolog && 1 - dbglog_Access("VIA2_Access kIFR", Data, WriteMem); -#endif - break; - case kIER : - if (WriteMem) { - if ((Data & 0x80) == 0) { - VIA2_D.IER = VIA2_D.IER & ((~ Data) & 0x7F); - /* Clear Enable Bits */ -#if 0 != VIA2_IER_Never0 - /* - of course, will be 0 initially, - this just checks not cleared later. - */ - if ((Data & VIA2_IER_Never0) != 0) { - ReportAbnormal("IER Never0 clr"); - } -#endif - } else { - VIA2_D.IER = VIA2_D.IER | (Data & 0x7F); - /* Set Enable Bits */ -#if 0 != VIA2_IER_Never1 - if ((VIA2_D.IER & VIA2_IER_Never1) != 0) { - ReportAbnormal("IER Never1 set"); - } -#endif - } - VIA2_CheckInterruptFlag(); - } else { - Data = VIA2_D.IER | 0x80; - } -#if VIA2_dolog && 1 - dbglog_Access("VIA2_Access kIER", Data, WriteMem); -#endif - break; - case kORA : - case kORA_H : - if ((VIA2_D.PCR & 0xE) == 0) { - VIA2_ClrInterruptFlag(kIntCA2); - } - VIA2_ClrInterruptFlag(kIntCA1); - if (WriteMem) { - VIA2_D.ORA = Data; - VIA2_Put_ORA(VIA2_D.DDR_A, VIA2_D.ORA); - } else { - Data = (VIA2_D.ORA & VIA2_D.DDR_A) - | VIA2_Get_ORA(~ VIA2_D.DDR_A); - } -#if VIA2_dolog && 1 - dbglog_Access("VIA2_Access kORA", Data, WriteMem); -#endif - break; - } - return Data; -} - -GLOBALPROC VIA2_ExtraTimeBegin(void) -{ - if (VIA2_T1Running) { - VIA2_DoTimer1Check(); /* run up to this moment */ - VIA2_T1Running = falseblnr; - } - if (VIA2_T2Running & (! VIA2_T2C_ShortTime)) { - VIA2_DoTimer2Check(); /* run up to this moment */ - VIA2_T2Running = falseblnr; - } -} - -GLOBALPROC VIA2_ExtraTimeEnd(void) -{ - if (! VIA2_T1Running) { - VIA2_T1Running = trueblnr; - VIA2_T1LastTime = GetCuriCount(); - VIA2_DoTimer1Check(); - } - if (! VIA2_T2Running) { - VIA2_T2Running = trueblnr; - VIA2_T2LastTime = GetCuriCount(); - VIA2_DoTimer2Check(); - } -} - -/* VIA Interrupt Interface */ - -#ifdef VIA2_iCA1_PulseNtfy -GLOBALPROC VIA2_iCA1_PulseNtfy(void) -{ - VIA2_SetInterruptFlag(kIntCA1); -} -#endif - -#ifdef VIA2_iCA2_PulseNtfy -GLOBALPROC VIA2_iCA2_PulseNtfy(void) -{ - VIA2_SetInterruptFlag(kIntCA2); -} -#endif - -#ifdef VIA2_iCB1_PulseNtfy -GLOBALPROC VIA2_iCB1_PulseNtfy(void) -{ - VIA2_SetInterruptFlag(kIntCB1); -} -#endif - -#ifdef VIA2_iCB2_PulseNtfy -GLOBALPROC VIA2_iCB2_PulseNtfy(void) -{ - VIA2_SetInterruptFlag(kIntCB2); -} -#endif +/* VIA2EMDV.c Copyright (C) 2008 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* Versatile Interface Adapter EMulated DEVice Emulates the VIA found in the Mac Plus. This code adapted from vMac by Philip Cummins. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif #include "VIA2EMDV.h" /* ReportAbnormalID unused 0x0510 - 0x05FF */ #ifdef VIA2_iA0_ChangeNtfy IMPORTPROC VIA2_iA0_ChangeNtfy(void); #endif #ifdef VIA2_iA1_ChangeNtfy IMPORTPROC VIA2_iA1_ChangeNtfy(void); #endif #ifdef VIA2_iA2_ChangeNtfy IMPORTPROC VIA2_iA2_ChangeNtfy(void); #endif #ifdef VIA2_iA3_ChangeNtfy IMPORTPROC VIA2_iA3_ChangeNtfy(void); #endif #ifdef VIA2_iA4_ChangeNtfy IMPORTPROC VIA2_iA4_ChangeNtfy(void); #endif #ifdef VIA2_iA5_ChangeNtfy IMPORTPROC VIA2_iA5_ChangeNtfy(void); #endif #ifdef VIA2_iA6_ChangeNtfy IMPORTPROC VIA2_iA6_ChangeNtfy(void); #endif #ifdef VIA2_iA7_ChangeNtfy IMPORTPROC VIA2_iA7_ChangeNtfy(void); #endif #ifdef VIA2_iB0_ChangeNtfy IMPORTPROC VIA2_iB0_ChangeNtfy(void); #endif #ifdef VIA2_iB1_ChangeNtfy IMPORTPROC VIA2_iB1_ChangeNtfy(void); #endif #ifdef VIA2_iB2_ChangeNtfy IMPORTPROC VIA2_iB2_ChangeNtfy(void); #endif #ifdef VIA2_iB3_ChangeNtfy IMPORTPROC VIA2_iB3_ChangeNtfy(void); #endif #ifdef VIA2_iB4_ChangeNtfy IMPORTPROC VIA2_iB4_ChangeNtfy(void); #endif #ifdef VIA2_iB5_ChangeNtfy IMPORTPROC VIA2_iB5_ChangeNtfy(void); #endif #ifdef VIA2_iB6_ChangeNtfy IMPORTPROC VIA2_iB6_ChangeNtfy(void); #endif #ifdef VIA2_iB7_ChangeNtfy IMPORTPROC VIA2_iB7_ChangeNtfy(void); #endif #ifdef VIA2_iCB2_ChangeNtfy IMPORTPROC VIA2_iCB2_ChangeNtfy(void); #endif #define Ui3rPowOf2(p) (1 << (p)) #define Ui3rTestBit(i, p) (((i) & Ui3rPowOf2(p)) != 0) #define VIA2_ORA_CanInOrOut (VIA2_ORA_CanIn | VIA2_ORA_CanOut) #if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 7) #ifdef VIA2_iA7 #error "VIA2_iA7 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 6) #ifdef VIA2_iA6 #error "VIA2_iA6 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 5) #ifdef VIA2_iA5 #error "VIA2_iA5 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 4) #ifdef VIA2_iA4 #error "VIA2_iA4 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 3) #ifdef VIA2_iA3 #error "VIA2_iA3 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 2) #ifdef VIA2_iA2 #error "VIA2_iA2 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 1) #ifdef VIA2_iA1 #error "VIA2_iA1 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 0) #ifdef VIA2_iA0 #error "VIA2_iA0 defined but not used" #endif #endif #define VIA2_ORB_CanInOrOut (VIA2_ORB_CanIn | VIA2_ORB_CanOut) #if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 7) #ifdef VIA2_iB7 #error "VIA2_iB7 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 6) #ifdef VIA2_iB6 #error "VIA2_iB6 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 5) #ifdef VIA2_iB5 #error "VIA2_iB5 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 4) #ifdef VIA2_iB4 #error "VIA2_iB4 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 3) #ifdef VIA2_iB3 #error "VIA2_iB3 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 2) #ifdef VIA2_iB2 #error "VIA2_iB2 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 1) #ifdef VIA2_iB1 #error "VIA2_iB1 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 0) #ifdef VIA2_iB0 #error "VIA2_iB0 defined but not used" #endif #endif typedef struct { ui5b T1C_F; /* Timer 1 Counter Fixed Point */ ui5b T2C_F; /* Timer 2 Counter Fixed Point */ ui3b ORB; /* Buffer B */ /* ui3b ORA_H; Buffer A with Handshake */ ui3b DDR_B; /* Data Direction Register B */ ui3b DDR_A; /* Data Direction Register A */ ui3b T1L_L; /* Timer 1 Latch Low */ ui3b T1L_H; /* Timer 1 Latch High */ ui3b T2L_L; /* Timer 2 Latch Low */ ui3b SR; /* Shift Register */ ui3b ACR; /* Auxiliary Control Register */ ui3b PCR; /* Peripheral Control Register */ ui3b IFR; /* Interrupt Flag Register */ ui3b IER; /* Interrupt Enable Register */ ui3b ORA; /* Buffer A */ } VIA2_Ty; LOCALVAR VIA2_Ty VIA2_D; #define kIntCA2 0 /* One_Second */ #define kIntCA1 1 /* Vertical_Blanking */ #define kIntSR 2 /* Keyboard_Data_Ready */ #define kIntCB2 3 /* Keyboard_Data */ #define kIntCB1 4 /* Keyboard_Clock */ #define kIntT2 5 /* Timer_2 */ #define kIntT1 6 /* Timer_1 */ #define VIA2_dolog (dbglog_HAVE && 0) /* VIA2_Get_ORA : VIA Get Port A Data */ /* This function queries VIA Port A interfaced hardware about their status */ LOCALFUNC ui3b VIA2_Get_ORA(ui3b Selection) { ui3b Value = (~ VIA2_ORA_CanIn) & Selection & VIA2_ORA_FloatVal; #if Ui3rTestBit(VIA2_ORA_CanIn, 7) if (Ui3rTestBit(Selection, 7)) { Value |= (VIA2_iA7 << 7); } #endif #if Ui3rTestBit(VIA2_ORA_CanIn, 6) if (Ui3rTestBit(Selection, 6)) { Value |= (VIA2_iA6 << 6); } #endif #if Ui3rTestBit(VIA2_ORA_CanIn, 5) if (Ui3rTestBit(Selection, 5)) { Value |= (VIA2_iA5 << 5); } #endif #if Ui3rTestBit(VIA2_ORA_CanIn, 4) if (Ui3rTestBit(Selection, 4)) { Value |= (VIA2_iA4 << 4); } #endif #if Ui3rTestBit(VIA2_ORA_CanIn, 3) if (Ui3rTestBit(Selection, 3)) { Value |= (VIA2_iA3 << 3); } #endif #if Ui3rTestBit(VIA2_ORA_CanIn, 2) if (Ui3rTestBit(Selection, 2)) { Value |= (VIA2_iA2 << 2); } #endif #if Ui3rTestBit(VIA2_ORA_CanIn, 1) if (Ui3rTestBit(Selection, 1)) { Value |= (VIA2_iA1 << 1); } #endif #if Ui3rTestBit(VIA2_ORA_CanIn, 0) if (Ui3rTestBit(Selection, 0)) { Value |= (VIA2_iA0 << 0); } #endif return Value; } /* VIA2_Get_ORB : VIA Get Port B Data */ /* This function queries VIA Port B interfaced hardware about their status */ LOCALFUNC ui3b VIA2_Get_ORB(ui3b Selection) { ui3b Value = (~ VIA2_ORB_CanIn) & Selection & VIA2_ORB_FloatVal; #if Ui3rTestBit(VIA2_ORB_CanIn, 7) if (Ui3rTestBit(Selection, 7)) { Value |= (VIA2_iB7 << 7); } #endif #if Ui3rTestBit(VIA2_ORB_CanIn, 6) if (Ui3rTestBit(Selection, 6)) { Value |= (VIA2_iB6 << 6); } #endif #if Ui3rTestBit(VIA2_ORB_CanIn, 5) if (Ui3rTestBit(Selection, 5)) { Value |= (VIA2_iB5 << 5); } #endif #if Ui3rTestBit(VIA2_ORB_CanIn, 4) if (Ui3rTestBit(Selection, 4)) { Value |= (VIA2_iB4 << 4); } #endif #if Ui3rTestBit(VIA2_ORB_CanIn, 3) if (Ui3rTestBit(Selection, 3)) { Value |= (VIA2_iB3 << 3); } #endif #if Ui3rTestBit(VIA2_ORB_CanIn, 2) if (Ui3rTestBit(Selection, 2)) { Value |= (VIA2_iB2 << 2); } #endif #if Ui3rTestBit(VIA2_ORB_CanIn, 1) if (Ui3rTestBit(Selection, 1)) { Value |= (VIA2_iB1 << 1); } #endif #if Ui3rTestBit(VIA2_ORB_CanIn, 0) if (Ui3rTestBit(Selection, 0)) { Value |= (VIA2_iB0 << 0); } #endif return Value; } #define ViaORcheckBit(p, x) \ (Ui3rTestBit(Selection, p) && \ ((v = (Data >> p) & 1) != x)) LOCALPROC VIA2_Put_ORA(ui3b Selection, ui3b Data) { #if 0 != VIA2_ORA_CanOut ui3b v; #endif #if Ui3rTestBit(VIA2_ORA_CanOut, 7) if (ViaORcheckBit(7, VIA2_iA7)) { VIA2_iA7 = v; #ifdef VIA2_iA7_ChangeNtfy VIA2_iA7_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA2_ORA_CanOut, 6) if (ViaORcheckBit(6, VIA2_iA6)) { VIA2_iA6 = v; #ifdef VIA2_iA6_ChangeNtfy VIA2_iA6_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA2_ORA_CanOut, 5) if (ViaORcheckBit(5, VIA2_iA5)) { VIA2_iA5 = v; #ifdef VIA2_iA5_ChangeNtfy VIA2_iA5_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA2_ORA_CanOut, 4) if (ViaORcheckBit(4, VIA2_iA4)) { VIA2_iA4 = v; #ifdef VIA2_iA4_ChangeNtfy VIA2_iA4_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA2_ORA_CanOut, 3) if (ViaORcheckBit(3, VIA2_iA3)) { VIA2_iA3 = v; #ifdef VIA2_iA3_ChangeNtfy VIA2_iA3_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA2_ORA_CanOut, 2) if (ViaORcheckBit(2, VIA2_iA2)) { VIA2_iA2 = v; #ifdef VIA2_iA2_ChangeNtfy VIA2_iA2_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA2_ORA_CanOut, 1) if (ViaORcheckBit(1, VIA2_iA1)) { VIA2_iA1 = v; #ifdef VIA2_iA1_ChangeNtfy VIA2_iA1_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA2_ORA_CanOut, 0) if (ViaORcheckBit(0, VIA2_iA0)) { VIA2_iA0 = v; #ifdef VIA2_iA0_ChangeNtfy VIA2_iA0_ChangeNtfy(); #endif } #endif } LOCALPROC VIA2_Put_ORB(ui3b Selection, ui3b Data) { #if 0 != VIA2_ORB_CanOut ui3b v; #endif #if Ui3rTestBit(VIA2_ORB_CanOut, 7) if (ViaORcheckBit(7, VIA2_iB7)) { VIA2_iB7 = v; #ifdef VIA2_iB7_ChangeNtfy VIA2_iB7_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA2_ORB_CanOut, 6) if (ViaORcheckBit(6, VIA2_iB6)) { VIA2_iB6 = v; #ifdef VIA2_iB6_ChangeNtfy VIA2_iB6_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA2_ORB_CanOut, 5) if (ViaORcheckBit(5, VIA2_iB5)) { VIA2_iB5 = v; #ifdef VIA2_iB5_ChangeNtfy VIA2_iB5_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA2_ORB_CanOut, 4) if (ViaORcheckBit(4, VIA2_iB4)) { VIA2_iB4 = v; #ifdef VIA2_iB4_ChangeNtfy VIA2_iB4_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA2_ORB_CanOut, 3) if (ViaORcheckBit(3, VIA2_iB3)) { VIA2_iB3 = v; #ifdef VIA2_iB3_ChangeNtfy VIA2_iB3_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA2_ORB_CanOut, 2) if (ViaORcheckBit(2, VIA2_iB2)) { VIA2_iB2 = v; #ifdef VIA2_iB2_ChangeNtfy VIA2_iB2_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA2_ORB_CanOut, 1) if (ViaORcheckBit(1, VIA2_iB1)) { VIA2_iB1 = v; #ifdef VIA2_iB1_ChangeNtfy VIA2_iB1_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA2_ORB_CanOut, 0) if (ViaORcheckBit(0, VIA2_iB0)) { VIA2_iB0 = v; #ifdef VIA2_iB0_ChangeNtfy VIA2_iB0_ChangeNtfy(); #endif } #endif } LOCALPROC VIA2_SetDDR_A(ui3b Data) { ui3b floatbits = VIA2_D.DDR_A & ~ Data; ui3b unfloatbits = Data & ~ VIA2_D.DDR_A; if (floatbits != 0) { VIA2_Put_ORA(floatbits, VIA2_ORA_FloatVal); } VIA2_D.DDR_A = Data; if (unfloatbits != 0) { VIA2_Put_ORA(unfloatbits, VIA2_D.ORA); } if ((Data & ~ VIA2_ORA_CanOut) != 0) { ReportAbnormalID(0x0501, "Set VIA2_D.DDR_A unexpected direction"); } } LOCALPROC VIA2_SetDDR_B(ui3b Data) { ui3b floatbits = VIA2_D.DDR_B & ~ Data; ui3b unfloatbits = Data & ~ VIA2_D.DDR_B; if (floatbits != 0) { VIA2_Put_ORB(floatbits, VIA2_ORB_FloatVal); } VIA2_D.DDR_B = Data; if (unfloatbits != 0) { VIA2_Put_ORB(unfloatbits, VIA2_D.ORB); } if ((Data & ~ VIA2_ORB_CanOut) != 0) { ReportAbnormalID(0x0502, "Set VIA2_D.DDR_B unexpected direction"); } } LOCALPROC VIA2_CheckInterruptFlag(void) { ui3b NewInterruptRequest = ((VIA2_D.IFR & VIA2_D.IER) != 0) ? 1 : 0; if (NewInterruptRequest != VIA2_InterruptRequest) { VIA2_InterruptRequest = NewInterruptRequest; #ifdef VIA2_interruptChngNtfy VIA2_interruptChngNtfy(); #endif } } LOCALVAR ui3b VIA2_T1_Active = 0; LOCALVAR ui3b VIA2_T2_Active = 0; LOCALVAR blnr VIA2_T1IntReady = falseblnr; LOCALPROC VIA2_Clear(void) { VIA2_D.ORA = 0; VIA2_D.DDR_A = 0; VIA2_D.ORB = 0; VIA2_D.DDR_B = 0; VIA2_D.T1L_L = VIA2_D.T1L_H = 0x00; VIA2_D.T2L_L = 0x00; VIA2_D.T1C_F = 0; VIA2_D.T2C_F = 0; VIA2_D.SR = VIA2_D.ACR = 0x00; VIA2_D.PCR = VIA2_D.IFR = VIA2_D.IER = 0x00; VIA2_T1_Active = VIA2_T2_Active = 0x00; VIA2_T1IntReady = falseblnr; } GLOBALPROC VIA2_Zap(void) { VIA2_Clear(); VIA2_InterruptRequest = 0; } GLOBALPROC VIA2_Reset(void) { VIA2_SetDDR_A(0); VIA2_SetDDR_B(0); VIA2_Clear(); VIA2_CheckInterruptFlag(); } LOCALPROC VIA2_SetInterruptFlag(ui3b VIA_Int) { VIA2_D.IFR |= ((ui3b)1 << VIA_Int); VIA2_CheckInterruptFlag(); } LOCALPROC VIA2_ClrInterruptFlag(ui3b VIA_Int) { VIA2_D.IFR &= ~ ((ui3b)1 << VIA_Int); VIA2_CheckInterruptFlag(); } #ifdef _VIA_Debug #include #endif GLOBALPROC VIA2_ShiftInData(ui3b v) { /* external hardware generates 8 pulses on CB1, writes 8 bits to CB2 */ ui3b ShiftMode = (VIA2_D.ACR & 0x1C) >> 2; if (ShiftMode != 3) { #if ExtraAbnormalReports if (ShiftMode == 0) { /* happens on reset */ } else { ReportAbnormalID(0x0503, "VIA Not ready to shift in"); /* Observed (rarely) in Crystal Quest played at 1x speed in "-t mc64". */ } #endif } else { VIA2_D.SR = v; VIA2_SetInterruptFlag(kIntSR); VIA2_SetInterruptFlag(kIntCB1); } } GLOBALFUNC ui3b VIA2_ShiftOutData(void) { /* external hardware generates 8 pulses on CB1, reads 8 bits from CB2 */ if (((VIA2_D.ACR & 0x1C) >> 2) != 7) { ReportAbnormalID(0x0504, "VIA Not ready to shift out"); return 0; } else { VIA2_SetInterruptFlag(kIntSR); VIA2_SetInterruptFlag(kIntCB1); VIA2_iCB2 = (VIA2_D.SR & 1); return VIA2_D.SR; } } #define CyclesPerViaTime (10 * kMyClockMult) #define CyclesScaledPerViaTime (kCycleScale * CyclesPerViaTime) LOCALVAR blnr VIA2_T1Running = trueblnr; LOCALVAR iCountt VIA2_T1LastTime = 0; GLOBALPROC VIA2_DoTimer1Check(void) { if (VIA2_T1Running) { iCountt NewTime = GetCuriCount(); iCountt deltaTime = (NewTime - VIA2_T1LastTime); if (deltaTime != 0) { ui5b Temp = VIA2_D.T1C_F; /* Get Timer 1 Counter */ ui5b deltaTemp = (deltaTime / CyclesPerViaTime) << (16 - kLn2CycleScale); /* may overflow */ ui5b NewTemp = Temp - deltaTemp; if ((deltaTime > (0x00010000UL * CyclesScaledPerViaTime)) || ((Temp <= deltaTemp) && (Temp != 0))) { if ((VIA2_D.ACR & 0x40) != 0) { /* Free Running? */ /* Reload Counter from Latches */ ui4b v = (VIA2_D.T1L_H << 8) + VIA2_D.T1L_L; ui4b ntrans = 1 + ((v == 0) ? 0 : (((deltaTemp - Temp) / v) >> 16)); NewTemp += (((ui5b)v * ntrans) << 16); #if Ui3rTestBit(VIA2_ORB_CanOut, 7) if ((VIA2_D.ACR & 0x80) != 0) { /* invert ? */ if ((ntrans & 1) != 0) { VIA2_iB7 ^= 1; #ifdef VIA2_iB7_ChangeNtfy VIA2_iB7_ChangeNtfy(); #endif } } #endif VIA2_SetInterruptFlag(kIntT1); #if VIA2_dolog && 1 dbglog_WriteNote("VIA2 Timer 1 Interrupt"); #endif } else { if (VIA2_T1_Active == 1) { VIA2_T1_Active = 0; VIA2_SetInterruptFlag(kIntT1); #if VIA2_dolog && 1 dbglog_WriteNote("VIA2 Timer 1 Interrupt"); #endif } } } VIA2_D.T1C_F = NewTemp; VIA2_T1LastTime = NewTime; } VIA2_T1IntReady = falseblnr; if ((VIA2_D.IFR & (1 << kIntT1)) == 0) { if (((VIA2_D.ACR & 0x40) != 0) || (VIA2_T1_Active == 1)) { ui5b NewTemp = VIA2_D.T1C_F; /* Get Timer 1 Counter */ ui5b NewTimer; #ifdef _VIA_Debug fprintf(stderr, "posting Timer1Check, %d, %d\n", Temp, GetCuriCount()); #endif if (NewTemp == 0) { NewTimer = (0x00010000UL * CyclesScaledPerViaTime); } else { NewTimer = (1 + (NewTemp >> (16 - kLn2CycleScale))) * CyclesPerViaTime; } ICT_add(kICT_VIA2_Timer1Check, NewTimer); VIA2_T1IntReady = trueblnr; } } } } LOCALPROC CheckT1IntReady(void) { if (VIA2_T1Running) { blnr NewT1IntReady = falseblnr; if ((VIA2_D.IFR & (1 << kIntT1)) == 0) { if (((VIA2_D.ACR & 0x40) != 0) || (VIA2_T1_Active == 1)) { NewT1IntReady = trueblnr; } } if (VIA2_T1IntReady != NewT1IntReady) { VIA2_T1IntReady = NewT1IntReady; if (NewT1IntReady) { VIA2_DoTimer1Check(); } } } } GLOBALFUNC ui4b VIA2_GetT1InvertTime(void) { ui4b v; if ((VIA2_D.ACR & 0xC0) == 0xC0) { v = (VIA2_D.T1L_H << 8) + VIA2_D.T1L_L; } else { v = 0; } return v; } LOCALVAR blnr VIA2_T2Running = trueblnr; LOCALVAR blnr VIA2_T2C_ShortTime = falseblnr; LOCALVAR iCountt VIA2_T2LastTime = 0; GLOBALPROC VIA2_DoTimer2Check(void) { if (VIA2_T2Running) { iCountt NewTime = GetCuriCount(); ui5b Temp = VIA2_D.T2C_F; /* Get Timer 2 Counter */ iCountt deltaTime = (NewTime - VIA2_T2LastTime); ui5b deltaTemp = (deltaTime / CyclesPerViaTime) << (16 - kLn2CycleScale); /* may overflow */ ui5b NewTemp = Temp - deltaTemp; if (VIA2_T2_Active == 1) { if ((deltaTime > (0x00010000UL * CyclesScaledPerViaTime)) || ((Temp <= deltaTemp) && (Temp != 0))) { VIA2_T2C_ShortTime = falseblnr; VIA2_T2_Active = 0; VIA2_SetInterruptFlag(kIntT2); #if VIA2_dolog && 1 dbglog_WriteNote("VIA2 Timer 2 Interrupt"); #endif } else { ui5b NewTimer; #ifdef _VIA_Debug fprintf(stderr, "posting Timer2Check, %d, %d\n", Temp, GetCuriCount()); #endif if (NewTemp == 0) { NewTimer = (0x00010000UL * CyclesScaledPerViaTime); } else { NewTimer = (1 + (NewTemp >> (16 - kLn2CycleScale))) * CyclesPerViaTime; } ICT_add(kICT_VIA2_Timer2Check, NewTimer); } } VIA2_D.T2C_F = NewTemp; VIA2_T2LastTime = NewTime; } } #define kORB 0x00 #define kORA_H 0x01 #define kDDR_B 0x02 #define kDDR_A 0x03 #define kT1C_L 0x04 #define kT1C_H 0x05 #define kT1L_L 0x06 #define kT1L_H 0x07 #define kT2_L 0x08 #define kT2_H 0x09 #define kSR 0x0A #define kACR 0x0B #define kPCR 0x0C #define kIFR 0x0D #define kIER 0x0E #define kORA 0x0F GLOBALFUNC ui5b VIA2_Access(ui5b Data, blnr WriteMem, CPTR addr) { switch (addr) { case kORB : #if VIA2_CB2modesAllowed != 0x01 if ((VIA2_D.PCR & 0xE0) == 0) #endif { VIA2_ClrInterruptFlag(kIntCB2); } VIA2_ClrInterruptFlag(kIntCB1); if (WriteMem) { VIA2_D.ORB = Data; VIA2_Put_ORB(VIA2_D.DDR_B, VIA2_D.ORB); } else { Data = (VIA2_D.ORB & VIA2_D.DDR_B) | VIA2_Get_ORB(~ VIA2_D.DDR_B); } #if VIA2_dolog && 1 dbglog_Access("VIA2_Access kORB", Data, WriteMem); #endif break; case kDDR_B : if (WriteMem) { VIA2_SetDDR_B(Data); } else { Data = VIA2_D.DDR_B; } #if VIA2_dolog && 1 dbglog_Access("VIA2_Access kDDR_B", Data, WriteMem); #endif break; case kDDR_A : if (WriteMem) { VIA2_SetDDR_A(Data); } else { Data = VIA2_D.DDR_A; } #if VIA2_dolog && 1 dbglog_Access("VIA2_Access kDDR_A", Data, WriteMem); #endif break; case kT1C_L : if (WriteMem) { VIA2_D.T1L_L = Data; } else { VIA2_ClrInterruptFlag(kIntT1); VIA2_DoTimer1Check(); Data = (VIA2_D.T1C_F & 0x00FF0000) >> 16; } #if VIA2_dolog && 1 dbglog_Access("VIA2_Access kT1C_L", Data, WriteMem); #endif break; case kT1C_H : if (WriteMem) { VIA2_D.T1L_H = Data; VIA2_ClrInterruptFlag(kIntT1); VIA2_D.T1C_F = (Data << 24) + (VIA2_D.T1L_L << 16); if ((VIA2_D.ACR & 0x40) == 0) { VIA2_T1_Active = 1; } VIA2_T1LastTime = GetCuriCount(); VIA2_DoTimer1Check(); } else { VIA2_DoTimer1Check(); Data = (VIA2_D.T1C_F & 0xFF000000) >> 24; } #if VIA2_dolog && 1 dbglog_Access("VIA2_Access kT1C_H", Data, WriteMem); #endif break; case kT1L_L : if (WriteMem) { VIA2_D.T1L_L = Data; } else { Data = VIA2_D.T1L_L; } #if VIA2_dolog && 1 dbglog_Access("VIA2_Access kT1L_L", Data, WriteMem); #endif break; case kT1L_H : if (WriteMem) { VIA2_D.T1L_H = Data; } else { Data = VIA2_D.T1L_H; } #if VIA2_dolog && 1 dbglog_Access("VIA2_Access kT1L_H", Data, WriteMem); #endif break; case kT2_L : if (WriteMem) { VIA2_D.T2L_L = Data; } else { VIA2_ClrInterruptFlag(kIntT2); VIA2_DoTimer2Check(); Data = (VIA2_D.T2C_F & 0x00FF0000) >> 16; } #if VIA2_dolog && 1 dbglog_Access("VIA2_Access kT2_L", Data, WriteMem); #endif break; case kT2_H : if (WriteMem) { VIA2_D.T2C_F = (Data << 24) + (VIA2_D.T2L_L << 16); VIA2_ClrInterruptFlag(kIntT2); VIA2_T2_Active = 1; if ((VIA2_D.T2C_F < (128UL << 16)) && (VIA2_D.T2C_F != 0)) { VIA2_T2C_ShortTime = trueblnr; VIA2_T2Running = trueblnr; /* Running too many instructions during a short timer interval can crash when playing sounds in System 7. So in this case don't let timer pause. */ } VIA2_T2LastTime = GetCuriCount(); VIA2_DoTimer2Check(); } else { VIA2_DoTimer2Check(); Data = (VIA2_D.T2C_F & 0xFF000000) >> 24; } #if VIA2_dolog && 1 dbglog_Access("VIA2_Access kT2_H", Data, WriteMem); #endif break; case kSR: #ifdef _VIA_Debug fprintf(stderr, "VIA2_D.SR: %d, %d, %d\n", WriteMem, ((VIA2_D.ACR & 0x1C) >> 2), Data); #endif if (WriteMem) { VIA2_D.SR = Data; } VIA2_ClrInterruptFlag(kIntSR); switch ((VIA2_D.ACR & 0x1C) >> 2) { case 3 : /* Shifting In */ break; case 6 : /* shift out under o2 clock */ if ((! WriteMem) || (VIA2_D.SR != 0)) { ReportAbnormalID(0x0505, "VIA shift mode 6, non zero"); } else { #ifdef _VIA_Debug fprintf(stderr, "posting Foo2Task\n"); #endif if (VIA2_iCB2 != 0) { VIA2_iCB2 = 0; #ifdef VIA2_iCB2_ChangeNtfy VIA2_iCB2_ChangeNtfy(); #endif } } #if 0 /* possibly should do this. seems not to affect anything. */ VIA2_SetInterruptFlag(kIntSR); /* don't wait */ #endif break; case 7 : /* Shifting Out */ break; } if (! WriteMem) { Data = VIA2_D.SR; } #if VIA2_dolog && 1 dbglog_Access("VIA2_Access kSR", Data, WriteMem); #endif break; case kACR: if (WriteMem) { #if 1 if ((VIA2_D.ACR & 0x10) != ((ui3b)Data & 0x10)) { /* shift direction has changed */ if ((Data & 0x10) == 0) { /* no longer an output, set data to float value */ if (VIA2_iCB2 == 0) { VIA2_iCB2 = 1; #ifdef VIA2_iCB2_ChangeNtfy VIA2_iCB2_ChangeNtfy(); #endif } } } #endif VIA2_D.ACR = Data; if ((VIA2_D.ACR & 0x20) != 0) { /* Not pulse counting? */ ReportAbnormalID(0x0506, "Set VIA2_D.ACR T2 Timer pulse counting"); } switch ((VIA2_D.ACR & 0xC0) >> 6) { /* case 1: happens in early System 6 */ case 2: ReportAbnormalID(0x0507, "Set VIA2_D.ACR T1 Timer mode 2"); break; } CheckT1IntReady(); switch ((VIA2_D.ACR & 0x1C) >> 2) { case 0: /* this isn't sufficient */ VIA2_ClrInterruptFlag(kIntSR); break; case 1: case 2: case 4: case 5: ReportAbnormalID(0x0508, "Set VIA2_D.ACR shift mode 1,2,4,5"); break; default: break; } if ((VIA2_D.ACR & 0x03) != 0) { ReportAbnormalID(0x0509, "Set VIA2_D.ACR T2 Timer latching enabled"); } } else { Data = VIA2_D.ACR; } #if VIA2_dolog && 1 dbglog_Access("VIA2_Access kACR", Data, WriteMem); #endif break; case kPCR: if (WriteMem) { VIA2_D.PCR = Data; #define Ui3rSetContains(s, i) (((s) & (1 << (i))) != 0) if (! Ui3rSetContains(VIA2_CB2modesAllowed, (VIA2_D.PCR >> 5) & 0x07)) { ReportAbnormalID(0x050A, "Set VIA2_D.PCR CB2 Control mode?"); } if ((VIA2_D.PCR & 0x10) != 0) { ReportAbnormalID(0x050B, "Set VIA2_D.PCR CB1 INTERRUPT CONTROL?"); } if (! Ui3rSetContains(VIA2_CA2modesAllowed, (VIA2_D.PCR >> 1) & 0x07)) { ReportAbnormalID(0x050C, "Set VIA2_D.PCR CA2 INTERRUPT CONTROL?"); } if ((VIA2_D.PCR & 0x01) != 0) { ReportAbnormalID(0x050D, "Set VIA2_D.PCR CA1 INTERRUPT CONTROL?"); } } else { Data = VIA2_D.PCR; } #if VIA2_dolog && 1 dbglog_Access("VIA2_Access kPCR", Data, WriteMem); #endif break; case kIFR: if (WriteMem) { VIA2_D.IFR = VIA2_D.IFR & ((~ Data) & 0x7F); /* Clear Flag Bits */ VIA2_CheckInterruptFlag(); CheckT1IntReady(); } else { Data = VIA2_D.IFR; if ((VIA2_D.IFR & VIA2_D.IER) != 0) { Data |= 0x80; } } #if VIA2_dolog && 1 dbglog_Access("VIA2_Access kIFR", Data, WriteMem); #endif break; case kIER : if (WriteMem) { if ((Data & 0x80) == 0) { VIA2_D.IER = VIA2_D.IER & ((~ Data) & 0x7F); /* Clear Enable Bits */ #if 0 != VIA2_IER_Never0 /* of course, will be 0 initially, this just checks not cleared later. */ if ((Data & VIA2_IER_Never0) != 0) { ReportAbnormalID(0x050E, "IER Never0 clr"); } #endif } else { VIA2_D.IER = VIA2_D.IER | (Data & 0x7F); /* Set Enable Bits */ #if 0 != VIA2_IER_Never1 if ((VIA2_D.IER & VIA2_IER_Never1) != 0) { ReportAbnormalID(0x050F, "IER Never1 set"); } #endif } VIA2_CheckInterruptFlag(); } else { Data = VIA2_D.IER | 0x80; } #if VIA2_dolog && 1 dbglog_Access("VIA2_Access kIER", Data, WriteMem); #endif break; case kORA : case kORA_H : if ((VIA2_D.PCR & 0xE) == 0) { VIA2_ClrInterruptFlag(kIntCA2); } VIA2_ClrInterruptFlag(kIntCA1); if (WriteMem) { VIA2_D.ORA = Data; VIA2_Put_ORA(VIA2_D.DDR_A, VIA2_D.ORA); } else { Data = (VIA2_D.ORA & VIA2_D.DDR_A) | VIA2_Get_ORA(~ VIA2_D.DDR_A); } #if VIA2_dolog && 1 dbglog_Access("VIA2_Access kORA", Data, WriteMem); #endif break; } return Data; } GLOBALPROC VIA2_ExtraTimeBegin(void) { if (VIA2_T1Running) { VIA2_DoTimer1Check(); /* run up to this moment */ VIA2_T1Running = falseblnr; } if (VIA2_T2Running & (! VIA2_T2C_ShortTime)) { VIA2_DoTimer2Check(); /* run up to this moment */ VIA2_T2Running = falseblnr; } } GLOBALPROC VIA2_ExtraTimeEnd(void) { if (! VIA2_T1Running) { VIA2_T1Running = trueblnr; VIA2_T1LastTime = GetCuriCount(); VIA2_DoTimer1Check(); } if (! VIA2_T2Running) { VIA2_T2Running = trueblnr; VIA2_T2LastTime = GetCuriCount(); VIA2_DoTimer2Check(); } } /* VIA Interrupt Interface */ #ifdef VIA2_iCA1_PulseNtfy GLOBALPROC VIA2_iCA1_PulseNtfy(void) { VIA2_SetInterruptFlag(kIntCA1); } #endif #ifdef VIA2_iCA2_PulseNtfy GLOBALPROC VIA2_iCA2_PulseNtfy(void) { VIA2_SetInterruptFlag(kIntCA2); } #endif #ifdef VIA2_iCB1_PulseNtfy GLOBALPROC VIA2_iCB1_PulseNtfy(void) { VIA2_SetInterruptFlag(kIntCB1); } #endif #ifdef VIA2_iCB2_PulseNtfy GLOBALPROC VIA2_iCB2_PulseNtfy(void) { VIA2_SetInterruptFlag(kIntCB2); } #endif \ No newline at end of file diff --git a/Mini vMac/mnvm_core/VIA2EMDV.h b/Mini vMac/mnvm_core/VIA2EMDV.h index 5141cb9..e929d36 100755 --- a/Mini vMac/mnvm_core/VIA2EMDV.h +++ b/Mini vMac/mnvm_core/VIA2EMDV.h @@ -1,48 +1 @@ -/* - VIA2EMDV.h - - Copyright (C) 2004 Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef VIA2EMDV_H -#error "header already included" -#else -#define VIA2EMDV_H -#endif - -EXPORTPROC VIA2_Zap(void); -EXPORTPROC VIA2_Reset(void); - -EXPORTFUNC ui5b VIA2_Access(ui5b Data, blnr WriteMem, CPTR addr); - -EXPORTPROC VIA2_ExtraTimeBegin(void); -EXPORTPROC VIA2_ExtraTimeEnd(void); -#ifdef VIA2_iCA1_PulseNtfy -EXPORTPROC VIA2_iCA1_PulseNtfy(void); -#endif -#ifdef VIA2_iCA2_PulseNtfy -EXPORTPROC VIA2_iCA2_PulseNtfy(void); -#endif -#ifdef VIA2_iCB1_PulseNtfy -EXPORTPROC VIA2_iCB1_PulseNtfy(void); -#endif -#ifdef VIA2_iCB2_PulseNtfy -EXPORTPROC VIA2_iCB2_PulseNtfy(void); -#endif -EXPORTPROC VIA2_DoTimer1Check(void); -EXPORTPROC VIA2_DoTimer2Check(void); - -EXPORTFUNC ui4b VIA2_GetT1InvertTime(void); - -EXPORTPROC VIA2_ShiftInData(ui3b v); -EXPORTFUNC ui3b VIA2_ShiftOutData(void); +/* VIA2EMDV.h Copyright (C) 2004 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef VIA2EMDV_H #error "header already included" #else #define VIA2EMDV_H #endif EXPORTPROC VIA2_Zap(void); EXPORTPROC VIA2_Reset(void); EXPORTFUNC ui5b VIA2_Access(ui5b Data, blnr WriteMem, CPTR addr); EXPORTPROC VIA2_ExtraTimeBegin(void); EXPORTPROC VIA2_ExtraTimeEnd(void); #ifdef VIA2_iCA1_PulseNtfy EXPORTPROC VIA2_iCA1_PulseNtfy(void); #endif #ifdef VIA2_iCA2_PulseNtfy EXPORTPROC VIA2_iCA2_PulseNtfy(void); #endif #ifdef VIA2_iCB1_PulseNtfy EXPORTPROC VIA2_iCB1_PulseNtfy(void); #endif #ifdef VIA2_iCB2_PulseNtfy EXPORTPROC VIA2_iCB2_PulseNtfy(void); #endif EXPORTPROC VIA2_DoTimer1Check(void); EXPORTPROC VIA2_DoTimer2Check(void); EXPORTFUNC ui4b VIA2_GetT1InvertTime(void); EXPORTPROC VIA2_ShiftInData(ui3b v); EXPORTFUNC ui3b VIA2_ShiftOutData(void); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/VIAEMDEV.c b/Mini vMac/mnvm_core/VIAEMDEV.c index b8c6a4f..ac29efc 100755 --- a/Mini vMac/mnvm_core/VIAEMDEV.c +++ b/Mini vMac/mnvm_core/VIAEMDEV.c @@ -1,1215 +1 @@ -/* - VIAEMDEV.c - - Copyright (C) 2008 Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - Versatile Interface Adapter EMulated DEVice - - Emulates the VIA found in the Mac Plus. - - This code adapted from vMac by Philip Cummins. -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" - -#include "MYOSGLUE.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" -#endif - -#include "VIAEMDEV.h" - -#ifdef VIA1_iA0_ChangeNtfy -IMPORTPROC VIA1_iA0_ChangeNtfy(void); -#endif - -#ifdef VIA1_iA1_ChangeNtfy -IMPORTPROC VIA1_iA1_ChangeNtfy(void); -#endif - -#ifdef VIA1_iA2_ChangeNtfy -IMPORTPROC VIA1_iA2_ChangeNtfy(void); -#endif - -#ifdef VIA1_iA3_ChangeNtfy -IMPORTPROC VIA1_iA3_ChangeNtfy(void); -#endif - -#ifdef VIA1_iA4_ChangeNtfy -IMPORTPROC VIA1_iA4_ChangeNtfy(void); -#endif - -#ifdef VIA1_iA5_ChangeNtfy -IMPORTPROC VIA1_iA5_ChangeNtfy(void); -#endif - -#ifdef VIA1_iA6_ChangeNtfy -IMPORTPROC VIA1_iA6_ChangeNtfy(void); -#endif - -#ifdef VIA1_iA7_ChangeNtfy -IMPORTPROC VIA1_iA7_ChangeNtfy(void); -#endif - -#ifdef VIA1_iB0_ChangeNtfy -IMPORTPROC VIA1_iB0_ChangeNtfy(void); -#endif - -#ifdef VIA1_iB1_ChangeNtfy -IMPORTPROC VIA1_iB1_ChangeNtfy(void); -#endif - -#ifdef VIA1_iB2_ChangeNtfy -IMPORTPROC VIA1_iB2_ChangeNtfy(void); -#endif - -#ifdef VIA1_iB3_ChangeNtfy -IMPORTPROC VIA1_iB3_ChangeNtfy(void); -#endif - -#ifdef VIA1_iB4_ChangeNtfy -IMPORTPROC VIA1_iB4_ChangeNtfy(void); -#endif - -#ifdef VIA1_iB5_ChangeNtfy -IMPORTPROC VIA1_iB5_ChangeNtfy(void); -#endif - -#ifdef VIA1_iB6_ChangeNtfy -IMPORTPROC VIA1_iB6_ChangeNtfy(void); -#endif - -#ifdef VIA1_iB7_ChangeNtfy -IMPORTPROC VIA1_iB7_ChangeNtfy(void); -#endif - -#ifdef VIA1_iCB2_ChangeNtfy -IMPORTPROC VIA1_iCB2_ChangeNtfy(void); -#endif - -#define Ui3rPowOf2(p) (1 << (p)) -#define Ui3rTestBit(i, p) (((i) & Ui3rPowOf2(p)) != 0) - -#define VIA1_ORA_CanInOrOut (VIA1_ORA_CanIn | VIA1_ORA_CanOut) - -#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 7) -#ifdef VIA1_iA7 -#error "VIA1_iA7 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 6) -#ifdef VIA1_iA6 -#error "VIA1_iA6 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 5) -#ifdef VIA1_iA5 -#error "VIA1_iA5 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 4) -#ifdef VIA1_iA4 -#error "VIA1_iA4 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 3) -#ifdef VIA1_iA3 -#error "VIA1_iA3 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 2) -#ifdef VIA1_iA2 -#error "VIA1_iA2 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 1) -#ifdef VIA1_iA1 -#error "VIA1_iA1 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 0) -#ifdef VIA1_iA0 -#error "VIA1_iA0 defined but not used" -#endif -#endif - -#define VIA1_ORB_CanInOrOut (VIA1_ORB_CanIn | VIA1_ORB_CanOut) - -#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 7) -#ifdef VIA1_iB7 -#error "VIA1_iB7 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 6) -#ifdef VIA1_iB6 -#error "VIA1_iB6 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 5) -#ifdef VIA1_iB5 -#error "VIA1_iB5 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 4) -#ifdef VIA1_iB4 -#error "VIA1_iB4 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 3) -#ifdef VIA1_iB3 -#error "VIA1_iB3 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 2) -#ifdef VIA1_iB2 -#error "VIA1_iB2 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 1) -#ifdef VIA1_iB1 -#error "VIA1_iB1 defined but not used" -#endif -#endif - -#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 0) -#ifdef VIA1_iB0 -#error "VIA1_iB0 defined but not used" -#endif -#endif - -typedef struct { - ui5b T1C_F; /* Timer 1 Counter Fixed Point */ - ui5b T2C_F; /* Timer 2 Counter Fixed Point */ - ui3b ORB; /* Buffer B */ - /* ui3b ORA_H; Buffer A with Handshake */ - ui3b DDR_B; /* Data Direction Register B */ - ui3b DDR_A; /* Data Direction Register A */ - ui3b T1L_L; /* Timer 1 Latch Low */ - ui3b T1L_H; /* Timer 1 Latch High */ - ui3b T2L_L; /* Timer 2 Latch Low */ - ui3b SR; /* Shift Register */ - ui3b ACR; /* Auxiliary Control Register */ - ui3b PCR; /* Peripheral Control Register */ - ui3b IFR; /* Interrupt Flag Register */ - ui3b IER; /* Interrupt Enable Register */ - ui3b ORA; /* Buffer A */ -} VIA1_Ty; - -LOCALVAR VIA1_Ty VIA1_D; - -#define kIntCA2 0 /* One_Second */ -#define kIntCA1 1 /* Vertical_Blanking */ -#define kIntSR 2 /* Keyboard_Data_Ready */ -#define kIntCB2 3 /* Keyboard_Data */ -#define kIntCB1 4 /* Keyboard_Clock */ -#define kIntT2 5 /* Timer_2 */ -#define kIntT1 6 /* Timer_1 */ - -#define VIA1_dolog (dbglog_HAVE && 0) - -/* VIA1_Get_ORA : VIA Get Port A Data */ -/* - This function queries VIA Port A interfaced hardware - about their status -*/ - -LOCALFUNC ui3b VIA1_Get_ORA(ui3b Selection) -{ - ui3b Value = (~ VIA1_ORA_CanIn) & Selection & VIA1_ORA_FloatVal; - -#if Ui3rTestBit(VIA1_ORA_CanIn, 7) - if (Ui3rTestBit(Selection, 7)) { - Value |= (VIA1_iA7 << 7); - } -#endif - -#if Ui3rTestBit(VIA1_ORA_CanIn, 6) - if (Ui3rTestBit(Selection, 6)) { - Value |= (VIA1_iA6 << 6); - } -#endif - -#if Ui3rTestBit(VIA1_ORA_CanIn, 5) - if (Ui3rTestBit(Selection, 5)) { - Value |= (VIA1_iA5 << 5); - } -#endif - -#if Ui3rTestBit(VIA1_ORA_CanIn, 4) - if (Ui3rTestBit(Selection, 4)) { - Value |= (VIA1_iA4 << 4); - } -#endif - -#if Ui3rTestBit(VIA1_ORA_CanIn, 3) - if (Ui3rTestBit(Selection, 3)) { - Value |= (VIA1_iA3 << 3); - } -#endif - -#if Ui3rTestBit(VIA1_ORA_CanIn, 2) - if (Ui3rTestBit(Selection, 2)) { - Value |= (VIA1_iA2 << 2); - } -#endif - -#if Ui3rTestBit(VIA1_ORA_CanIn, 1) - if (Ui3rTestBit(Selection, 1)) { - Value |= (VIA1_iA1 << 1); - } -#endif - -#if Ui3rTestBit(VIA1_ORA_CanIn, 0) - if (Ui3rTestBit(Selection, 0)) { - Value |= (VIA1_iA0 << 0); - } -#endif - - return Value; -} - -/* VIA1_Get_ORB : VIA Get Port B Data */ -/* - This function queries VIA Port B interfaced hardware - about their status -*/ - -LOCALFUNC ui3b VIA1_Get_ORB(ui3b Selection) -{ - ui3b Value = (~ VIA1_ORB_CanIn) & Selection & VIA1_ORB_FloatVal; - -#if Ui3rTestBit(VIA1_ORB_CanIn, 7) - if (Ui3rTestBit(Selection, 7)) { - Value |= (VIA1_iB7 << 7); - } -#endif - -#if Ui3rTestBit(VIA1_ORB_CanIn, 6) - if (Ui3rTestBit(Selection, 6)) { - Value |= (VIA1_iB6 << 6); - } -#endif - -#if Ui3rTestBit(VIA1_ORB_CanIn, 5) - if (Ui3rTestBit(Selection, 5)) { - Value |= (VIA1_iB5 << 5); - } -#endif - -#if Ui3rTestBit(VIA1_ORB_CanIn, 4) - if (Ui3rTestBit(Selection, 4)) { - Value |= (VIA1_iB4 << 4); - } -#endif - -#if Ui3rTestBit(VIA1_ORB_CanIn, 3) - if (Ui3rTestBit(Selection, 3)) { - Value |= (VIA1_iB3 << 3); - } -#endif - -#if Ui3rTestBit(VIA1_ORB_CanIn, 2) - if (Ui3rTestBit(Selection, 2)) { - Value |= (VIA1_iB2 << 2); - } -#endif - -#if Ui3rTestBit(VIA1_ORB_CanIn, 1) - if (Ui3rTestBit(Selection, 1)) { - Value |= (VIA1_iB1 << 1); - } -#endif - -#if Ui3rTestBit(VIA1_ORB_CanIn, 0) - if (Ui3rTestBit(Selection, 0)) { - Value |= (VIA1_iB0 << 0); - } -#endif - - return Value; -} - -#define ViaORcheckBit(p, x) \ - (Ui3rTestBit(Selection, p) && \ - ((v = (Data >> p) & 1) != x)) - -LOCALPROC VIA1_Put_ORA(ui3b Selection, ui3b Data) -{ -#if 0 != VIA1_ORA_CanOut - ui3b v; -#endif - -#if Ui3rTestBit(VIA1_ORA_CanOut, 7) - if (ViaORcheckBit(7, VIA1_iA7)) { - VIA1_iA7 = v; -#ifdef VIA1_iA7_ChangeNtfy - VIA1_iA7_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA1_ORA_CanOut, 6) - if (ViaORcheckBit(6, VIA1_iA6)) { - VIA1_iA6 = v; -#ifdef VIA1_iA6_ChangeNtfy - VIA1_iA6_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA1_ORA_CanOut, 5) - if (ViaORcheckBit(5, VIA1_iA5)) { - VIA1_iA5 = v; -#ifdef VIA1_iA5_ChangeNtfy - VIA1_iA5_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA1_ORA_CanOut, 4) - if (ViaORcheckBit(4, VIA1_iA4)) { - VIA1_iA4 = v; -#ifdef VIA1_iA4_ChangeNtfy - VIA1_iA4_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA1_ORA_CanOut, 3) - if (ViaORcheckBit(3, VIA1_iA3)) { - VIA1_iA3 = v; -#ifdef VIA1_iA3_ChangeNtfy - VIA1_iA3_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA1_ORA_CanOut, 2) - if (ViaORcheckBit(2, VIA1_iA2)) { - VIA1_iA2 = v; -#ifdef VIA1_iA2_ChangeNtfy - VIA1_iA2_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA1_ORA_CanOut, 1) - if (ViaORcheckBit(1, VIA1_iA1)) { - VIA1_iA1 = v; -#ifdef VIA1_iA1_ChangeNtfy - VIA1_iA1_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA1_ORA_CanOut, 0) - if (ViaORcheckBit(0, VIA1_iA0)) { - VIA1_iA0 = v; -#ifdef VIA1_iA0_ChangeNtfy - VIA1_iA0_ChangeNtfy(); -#endif - } -#endif -} - -LOCALPROC VIA1_Put_ORB(ui3b Selection, ui3b Data) -{ -#if 0 != VIA1_ORB_CanOut - ui3b v; -#endif - -#if Ui3rTestBit(VIA1_ORB_CanOut, 7) - if (ViaORcheckBit(7, VIA1_iB7)) { - VIA1_iB7 = v; -#ifdef VIA1_iB7_ChangeNtfy - VIA1_iB7_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA1_ORB_CanOut, 6) - if (ViaORcheckBit(6, VIA1_iB6)) { - VIA1_iB6 = v; -#ifdef VIA1_iB6_ChangeNtfy - VIA1_iB6_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA1_ORB_CanOut, 5) - if (ViaORcheckBit(5, VIA1_iB5)) { - VIA1_iB5 = v; -#ifdef VIA1_iB5_ChangeNtfy - VIA1_iB5_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA1_ORB_CanOut, 4) - if (ViaORcheckBit(4, VIA1_iB4)) { - VIA1_iB4 = v; -#ifdef VIA1_iB4_ChangeNtfy - VIA1_iB4_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA1_ORB_CanOut, 3) - if (ViaORcheckBit(3, VIA1_iB3)) { - VIA1_iB3 = v; -#ifdef VIA1_iB3_ChangeNtfy - VIA1_iB3_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA1_ORB_CanOut, 2) - if (ViaORcheckBit(2, VIA1_iB2)) { - VIA1_iB2 = v; -#ifdef VIA1_iB2_ChangeNtfy - VIA1_iB2_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA1_ORB_CanOut, 1) - if (ViaORcheckBit(1, VIA1_iB1)) { - VIA1_iB1 = v; -#ifdef VIA1_iB1_ChangeNtfy - VIA1_iB1_ChangeNtfy(); -#endif - } -#endif - -#if Ui3rTestBit(VIA1_ORB_CanOut, 0) - if (ViaORcheckBit(0, VIA1_iB0)) { - VIA1_iB0 = v; -#ifdef VIA1_iB0_ChangeNtfy - VIA1_iB0_ChangeNtfy(); -#endif - } -#endif -} - -LOCALPROC VIA1_SetDDR_A(ui3b Data) -{ - ui3b floatbits = VIA1_D.DDR_A & ~ Data; - ui3b unfloatbits = Data & ~ VIA1_D.DDR_A; - - if (floatbits != 0) { - VIA1_Put_ORA(floatbits, VIA1_ORA_FloatVal); - } - VIA1_D.DDR_A = Data; - if (unfloatbits != 0) { - VIA1_Put_ORA(unfloatbits, VIA1_D.ORA); - } - if ((Data & ~ VIA1_ORA_CanOut) != 0) { - ReportAbnormal("Set VIA1_D.DDR_A unexpected direction"); - } -} - -LOCALPROC VIA1_SetDDR_B(ui3b Data) -{ - ui3b floatbits = VIA1_D.DDR_B & ~ Data; - ui3b unfloatbits = Data & ~ VIA1_D.DDR_B; - - if (floatbits != 0) { - VIA1_Put_ORB(floatbits, VIA1_ORB_FloatVal); - } - VIA1_D.DDR_B = Data; - if (unfloatbits != 0) { - VIA1_Put_ORB(unfloatbits, VIA1_D.ORB); - } - if ((Data & ~ VIA1_ORB_CanOut) != 0) { - ReportAbnormal("Set VIA1_D.DDR_B unexpected direction"); - } -} - - -LOCALPROC VIA1_CheckInterruptFlag(void) -{ - ui3b NewInterruptRequest = - ((VIA1_D.IFR & VIA1_D.IER) != 0) ? 1 : 0; - - if (NewInterruptRequest != VIA1_InterruptRequest) { - VIA1_InterruptRequest = NewInterruptRequest; -#ifdef VIA1_interruptChngNtfy - VIA1_interruptChngNtfy(); -#endif - } -} - - -LOCALVAR ui3b VIA1_T1_Active = 0; -LOCALVAR ui3b VIA1_T2_Active = 0; - -LOCALVAR blnr VIA1_T1IntReady = falseblnr; - -LOCALPROC VIA1_Clear(void) -{ - VIA1_D.ORA = 0; VIA1_D.DDR_A = 0; - VIA1_D.ORB = 0; VIA1_D.DDR_B = 0; - VIA1_D.T1L_L = VIA1_D.T1L_H = 0x00; - VIA1_D.T2L_L = 0x00; - VIA1_D.T1C_F = 0; - VIA1_D.T2C_F = 0; - VIA1_D.SR = VIA1_D.ACR = 0x00; - VIA1_D.PCR = VIA1_D.IFR = VIA1_D.IER = 0x00; - VIA1_T1_Active = VIA1_T2_Active = 0x00; - VIA1_T1IntReady = falseblnr; -} - -GLOBALPROC VIA1_Zap(void) -{ - VIA1_Clear(); - VIA1_InterruptRequest = 0; -} - -GLOBALPROC VIA1_Reset(void) -{ - VIA1_SetDDR_A(0); - VIA1_SetDDR_B(0); - - VIA1_Clear(); - - VIA1_CheckInterruptFlag(); -} - -LOCALPROC VIA1_SetInterruptFlag(ui3b VIA_Int) -{ - VIA1_D.IFR |= ((ui3b)1 << VIA_Int); - VIA1_CheckInterruptFlag(); -} - -LOCALPROC VIA1_ClrInterruptFlag(ui3b VIA_Int) -{ - VIA1_D.IFR &= ~ ((ui3b)1 << VIA_Int); - VIA1_CheckInterruptFlag(); -} - -#ifdef _VIA_Debug -#include -#endif - -GLOBALPROC VIA1_ShiftInData(ui3b v) -{ - /* - external hardware generates 8 pulses on CB1, - writes 8 bits to CB2 - */ - ui3b ShiftMode = (VIA1_D.ACR & 0x1C) >> 2; - if (ShiftMode != 3) { - if (ShiftMode == 0) { - /* happens on reset */ - } else { - ReportAbnormal("VIA Not ready to shift in"); - } - } else { - VIA1_D.SR = v; - VIA1_SetInterruptFlag(kIntSR); - VIA1_SetInterruptFlag(kIntCB1); - } -} - -GLOBALFUNC ui3b VIA1_ShiftOutData(void) -{ - /* - external hardware generates 8 pulses on CB1, - reads 8 bits from CB2 - */ - if (((VIA1_D.ACR & 0x1C) >> 2) != 7) { - ReportAbnormal("VIA Not ready to shift out"); - return 0; - } else { - VIA1_SetInterruptFlag(kIntSR); - VIA1_SetInterruptFlag(kIntCB1); - VIA1_iCB2 = (VIA1_D.SR & 1); - return VIA1_D.SR; - } -} - -#define CyclesPerViaTime (10 * kMyClockMult) -#define CyclesScaledPerViaTime (kCycleScale * CyclesPerViaTime) - -LOCALVAR blnr VIA1_T1Running = trueblnr; -LOCALVAR iCountt VIA1_T1LastTime = 0; - -GLOBALPROC VIA1_DoTimer1Check(void) -{ - if (VIA1_T1Running) { - iCountt NewTime = GetCuriCount(); - iCountt deltaTime = (NewTime - VIA1_T1LastTime); - if (deltaTime != 0) { - ui5b Temp = VIA1_D.T1C_F; /* Get Timer 1 Counter */ - ui5b deltaTemp = - (deltaTime / CyclesPerViaTime) << (16 - kLn2CycleScale); - /* may overflow */ - ui5b NewTemp = Temp - deltaTemp; - if ((deltaTime > (0x00010000UL * CyclesScaledPerViaTime)) - || ((Temp <= deltaTemp) && (Temp != 0))) - { - if ((VIA1_D.ACR & 0x40) != 0) { /* Free Running? */ - /* Reload Counter from Latches */ - ui4b v = (VIA1_D.T1L_H << 8) + VIA1_D.T1L_L; - ui4b ntrans = 1 + ((v == 0) ? 0 : - (((deltaTemp - Temp) / v) >> 16)); - NewTemp += (((ui5b)v * ntrans) << 16); -#if Ui3rTestBit(VIA1_ORB_CanOut, 7) - if ((VIA1_D.ACR & 0x80) != 0) { /* invert ? */ - if ((ntrans & 1) != 0) { - VIA1_iB7 ^= 1; -#ifdef VIA1_iB7_ChangeNtfy - VIA1_iB7_ChangeNtfy(); -#endif - } - } -#endif - VIA1_SetInterruptFlag(kIntT1); -#if VIA1_dolog && 1 - dbglog_StartLine(); - dbglog_writeCStr("VIA1 Timer 1 Interrupt"); - dbglog_writeReturn(); -#endif - } else { - if (VIA1_T1_Active == 1) { - VIA1_T1_Active = 0; - VIA1_SetInterruptFlag(kIntT1); -#if VIA1_dolog && 1 - dbglog_StartLine(); - dbglog_writeCStr("VIA1 Timer 1 Interrupt"); - dbglog_writeReturn(); -#endif - } - } - } - - VIA1_D.T1C_F = NewTemp; - VIA1_T1LastTime = NewTime; - } - - VIA1_T1IntReady = falseblnr; - if ((VIA1_D.IFR & (1 << kIntT1)) == 0) { - if (((VIA1_D.ACR & 0x40) != 0) || (VIA1_T1_Active == 1)) { - ui5b NewTemp = VIA1_D.T1C_F; /* Get Timer 1 Counter */ - ui5b NewTimer; -#ifdef _VIA_Debug - fprintf(stderr, "posting Timer1Check, %d, %d\n", - Temp, GetCuriCount()); -#endif - if (NewTemp == 0) { - NewTimer = (0x00010000UL * CyclesScaledPerViaTime); - } else { - NewTimer = - (1 + (NewTemp >> (16 - kLn2CycleScale))) - * CyclesPerViaTime; - } - ICT_add(kICT_VIA1_Timer1Check, NewTimer); - VIA1_T1IntReady = trueblnr; - } - } - } -} - -LOCALPROC CheckT1IntReady(void) -{ - if (VIA1_T1Running) { - blnr NewT1IntReady = falseblnr; - - if ((VIA1_D.IFR & (1 << kIntT1)) == 0) { - if (((VIA1_D.ACR & 0x40) != 0) || (VIA1_T1_Active == 1)) { - NewT1IntReady = trueblnr; - } - } - - if (VIA1_T1IntReady != NewT1IntReady) { - VIA1_T1IntReady = NewT1IntReady; - if (NewT1IntReady) { - VIA1_DoTimer1Check(); - } - } - } -} - -GLOBALFUNC ui4b VIA1_GetT1InvertTime(void) -{ - ui4b v; - - if ((VIA1_D.ACR & 0xC0) == 0xC0) { - v = (VIA1_D.T1L_H << 8) + VIA1_D.T1L_L; - } else { - v = 0; - } - return v; -} - -LOCALVAR blnr VIA1_T2Running = trueblnr; -LOCALVAR blnr VIA1_T2C_ShortTime = falseblnr; -LOCALVAR iCountt VIA1_T2LastTime = 0; - -GLOBALPROC VIA1_DoTimer2Check(void) -{ - if (VIA1_T2Running) { - iCountt NewTime = GetCuriCount(); - ui5b Temp = VIA1_D.T2C_F; /* Get Timer 2 Counter */ - iCountt deltaTime = (NewTime - VIA1_T2LastTime); - ui5b deltaTemp = (deltaTime / CyclesPerViaTime) - << (16 - kLn2CycleScale); /* may overflow */ - ui5b NewTemp = Temp - deltaTemp; - if (VIA1_T2_Active == 1) { - if ((deltaTime > (0x00010000UL * CyclesScaledPerViaTime)) - || ((Temp <= deltaTemp) && (Temp != 0))) - { - VIA1_T2C_ShortTime = falseblnr; - VIA1_T2_Active = 0; - VIA1_SetInterruptFlag(kIntT2); -#if VIA1_dolog && 1 - dbglog_StartLine(); - dbglog_writeCStr("VIA1 Timer 2 Interrupt"); - dbglog_writeReturn(); -#endif - } else { - ui5b NewTimer; -#ifdef _VIA_Debug - fprintf(stderr, "posting Timer2Check, %d, %d\n", - Temp, GetCuriCount()); -#endif - if (NewTemp == 0) { - NewTimer = (0x00010000UL * CyclesScaledPerViaTime); - } else { - NewTimer = (1 + (NewTemp >> (16 - kLn2CycleScale))) - * CyclesPerViaTime; - } - ICT_add(kICT_VIA1_Timer2Check, NewTimer); - } - } - VIA1_D.T2C_F = NewTemp; - VIA1_T2LastTime = NewTime; - } -} - -#define kORB 0x00 -#define kORA_H 0x01 -#define kDDR_B 0x02 -#define kDDR_A 0x03 -#define kT1C_L 0x04 -#define kT1C_H 0x05 -#define kT1L_L 0x06 -#define kT1L_H 0x07 -#define kT2_L 0x08 -#define kT2_H 0x09 -#define kSR 0x0A -#define kACR 0x0B -#define kPCR 0x0C -#define kIFR 0x0D -#define kIER 0x0E -#define kORA 0x0F - -GLOBALFUNC ui5b VIA1_Access(ui5b Data, blnr WriteMem, CPTR addr) -{ - switch (addr) { - case kORB : -#if VIA1_CB2modesAllowed != 0x01 - if ((VIA1_D.PCR & 0xE0) == 0) -#endif - { - VIA1_ClrInterruptFlag(kIntCB2); - } - VIA1_ClrInterruptFlag(kIntCB1); - if (WriteMem) { - VIA1_D.ORB = Data; - VIA1_Put_ORB(VIA1_D.DDR_B, VIA1_D.ORB); - } else { - Data = (VIA1_D.ORB & VIA1_D.DDR_B) - | VIA1_Get_ORB(~ VIA1_D.DDR_B); - } -#if VIA1_dolog && 1 - dbglog_Access("VIA1_Access kORB", Data, WriteMem); -#endif - break; - case kDDR_B : - if (WriteMem) { - VIA1_SetDDR_B(Data); - } else { - Data = VIA1_D.DDR_B; - } -#if VIA1_dolog && 1 - dbglog_Access("VIA1_Access kDDR_B", Data, WriteMem); -#endif - break; - case kDDR_A : - if (WriteMem) { - VIA1_SetDDR_A(Data); - } else { - Data = VIA1_D.DDR_A; - } -#if VIA1_dolog && 1 - dbglog_Access("VIA1_Access kDDR_A", Data, WriteMem); -#endif - break; - case kT1C_L : - if (WriteMem) { - VIA1_D.T1L_L = Data; - } else { - VIA1_ClrInterruptFlag(kIntT1); - VIA1_DoTimer1Check(); - Data = (VIA1_D.T1C_F & 0x00FF0000) >> 16; - } -#if VIA1_dolog && 1 - dbglog_Access("VIA1_Access kT1C_L", Data, WriteMem); -#endif - break; - case kT1C_H : - if (WriteMem) { - VIA1_D.T1L_H = Data; - VIA1_ClrInterruptFlag(kIntT1); - VIA1_D.T1C_F = (Data << 24) + (VIA1_D.T1L_L << 16); - if ((VIA1_D.ACR & 0x40) == 0) { - VIA1_T1_Active = 1; - } - VIA1_T1LastTime = GetCuriCount(); - VIA1_DoTimer1Check(); - } else { - VIA1_DoTimer1Check(); - Data = (VIA1_D.T1C_F & 0xFF000000) >> 24; - } -#if VIA1_dolog && 1 - dbglog_Access("VIA1_Access kT1C_H", Data, WriteMem); -#endif - break; - case kT1L_L : - if (WriteMem) { - VIA1_D.T1L_L = Data; - } else { - Data = VIA1_D.T1L_L; - } -#if VIA1_dolog && 1 - dbglog_Access("VIA1_Access kT1L_L", Data, WriteMem); -#endif - break; - case kT1L_H : - if (WriteMem) { - VIA1_D.T1L_H = Data; - } else { - Data = VIA1_D.T1L_H; - } -#if VIA1_dolog && 1 - dbglog_Access("VIA1_Access kT1L_H", Data, WriteMem); -#endif - break; - case kT2_L : - if (WriteMem) { - VIA1_D.T2L_L = Data; - } else { - VIA1_ClrInterruptFlag(kIntT2); - VIA1_DoTimer2Check(); - Data = (VIA1_D.T2C_F & 0x00FF0000) >> 16; - } -#if VIA1_dolog && 1 - dbglog_Access("VIA1_Access kT2_L", Data, WriteMem); -#endif - break; - case kT2_H : - if (WriteMem) { - VIA1_D.T2C_F = (Data << 24) + (VIA1_D.T2L_L << 16); - VIA1_ClrInterruptFlag(kIntT2); - VIA1_T2_Active = 1; - - if ((VIA1_D.T2C_F < (128UL << 16)) - && (VIA1_D.T2C_F != 0)) - { - VIA1_T2C_ShortTime = trueblnr; - VIA1_T2Running = trueblnr; - /* - Running too many instructions during - a short timer interval can crash when - playing sounds in System 7. So - in this case don't let timer pause. - */ - } - VIA1_T2LastTime = GetCuriCount(); - VIA1_DoTimer2Check(); - } else { - VIA1_DoTimer2Check(); - Data = (VIA1_D.T2C_F & 0xFF000000) >> 24; - } -#if VIA1_dolog && 1 - dbglog_Access("VIA1_Access kT2_H", Data, WriteMem); -#endif - break; - case kSR: -#ifdef _VIA_Debug - fprintf(stderr, "VIA1_D.SR: %d, %d, %d\n", - WriteMem, ((VIA1_D.ACR & 0x1C) >> 2), Data); -#endif - if (WriteMem) { - VIA1_D.SR = Data; - } - VIA1_ClrInterruptFlag(kIntSR); - switch ((VIA1_D.ACR & 0x1C) >> 2) { - case 3 : /* Shifting In */ - break; - case 6 : /* shift out under o2 clock */ - if ((! WriteMem) || (VIA1_D.SR != 0)) { - ReportAbnormal("VIA shift mode 6, non zero"); - } else { -#ifdef _VIA_Debug - fprintf(stderr, "posting Foo2Task\n"); -#endif - if (VIA1_iCB2 != 0) { - VIA1_iCB2 = 0; -#ifdef VIA1_iCB2_ChangeNtfy - VIA1_iCB2_ChangeNtfy(); -#endif - } - } -#if 0 /* possibly should do this. seems not to affect anything. */ - VIA1_SetInterruptFlag(kIntSR); /* don't wait */ -#endif - break; - case 7 : /* Shifting Out */ - break; - } - if (! WriteMem) { - Data = VIA1_D.SR; - } -#if VIA1_dolog && 1 - dbglog_Access("VIA1_Access kSR", Data, WriteMem); -#endif - break; - case kACR: - if (WriteMem) { -#if 1 - if ((VIA1_D.ACR & 0x10) != ((ui3b)Data & 0x10)) { - /* shift direction has changed */ - if ((Data & 0x10) == 0) { - /* - no longer an output, - set data to float value - */ - if (VIA1_iCB2 == 0) { - VIA1_iCB2 = 1; -#ifdef VIA1_iCB2_ChangeNtfy - VIA1_iCB2_ChangeNtfy(); -#endif - } - } - } -#endif - VIA1_D.ACR = Data; - if ((VIA1_D.ACR & 0x20) != 0) { - /* Not pulse counting? */ - ReportAbnormal( - "Set VIA1_D.ACR T2 Timer pulse counting"); - } - switch ((VIA1_D.ACR & 0xC0) >> 6) { - /* case 1: happens in early System 6 */ - case 2: - ReportAbnormal( - "Set VIA1_D.ACR T1 Timer mode 2"); - break; - } - CheckT1IntReady(); - switch ((VIA1_D.ACR & 0x1C) >> 2) { - case 0: /* this isn't sufficient */ - VIA1_ClrInterruptFlag(kIntSR); - break; - case 1: - case 2: - case 4: - case 5: - ReportAbnormal( - "Set VIA1_D.ACR shift mode 1,2,4,5"); - break; - default: - break; - } - if ((VIA1_D.ACR & 0x03) != 0) { - ReportAbnormal( - "Set VIA1_D.ACR T2 Timer latching enabled"); - } - } else { - Data = VIA1_D.ACR; - } -#if VIA1_dolog && 1 - dbglog_Access("VIA1_Access kACR", Data, WriteMem); -#endif - break; - case kPCR: - if (WriteMem) { - VIA1_D.PCR = Data; -#define Ui3rSetContains(s, i) (((s) & (1 << (i))) != 0) - if (! Ui3rSetContains(VIA1_CB2modesAllowed, - (VIA1_D.PCR >> 5) & 0x07)) - { - ReportAbnormal("Set VIA1_D.PCR CB2 Control mode?"); - } - if ((VIA1_D.PCR & 0x10) != 0) { - ReportAbnormal( - "Set VIA1_D.PCR CB1 INTERRUPT CONTROL?"); - } - if (! Ui3rSetContains(VIA1_CA2modesAllowed, - (VIA1_D.PCR >> 1) & 0x07)) - { - ReportAbnormal( - "Set VIA1_D.PCR CA2 INTERRUPT CONTROL?"); - } - if ((VIA1_D.PCR & 0x01) != 0) { - ReportAbnormal( - "Set VIA1_D.PCR CA1 INTERRUPT CONTROL?"); - } - } else { - Data = VIA1_D.PCR; - } -#if VIA1_dolog && 1 - dbglog_Access("VIA1_Access kPCR", Data, WriteMem); -#endif - break; - case kIFR: - if (WriteMem) { - VIA1_D.IFR = VIA1_D.IFR & ((~ Data) & 0x7F); - /* Clear Flag Bits */ - VIA1_CheckInterruptFlag(); - CheckT1IntReady(); - } else { - Data = VIA1_D.IFR; - if ((VIA1_D.IFR & VIA1_D.IER) != 0) { - Data |= 0x80; - } - } -#if VIA1_dolog && 1 - dbglog_Access("VIA1_Access kIFR", Data, WriteMem); -#endif - break; - case kIER : - if (WriteMem) { - if ((Data & 0x80) == 0) { - VIA1_D.IER = VIA1_D.IER & ((~ Data) & 0x7F); - /* Clear Enable Bits */ -#if 0 != VIA1_IER_Never0 - /* - of course, will be 0 initially, - this just checks not cleared later. - */ - if ((Data & VIA1_IER_Never0) != 0) { - ReportAbnormal("IER Never0 clr"); - } -#endif - } else { - VIA1_D.IER = VIA1_D.IER | (Data & 0x7F); - /* Set Enable Bits */ -#if 0 != VIA1_IER_Never1 - if ((VIA1_D.IER & VIA1_IER_Never1) != 0) { - ReportAbnormal("IER Never1 set"); - } -#endif - } - VIA1_CheckInterruptFlag(); - } else { - Data = VIA1_D.IER | 0x80; - } -#if VIA1_dolog && 1 - dbglog_Access("VIA1_Access kIER", Data, WriteMem); -#endif - break; - case kORA : - case kORA_H : - if ((VIA1_D.PCR & 0xE) == 0) { - VIA1_ClrInterruptFlag(kIntCA2); - } - VIA1_ClrInterruptFlag(kIntCA1); - if (WriteMem) { - VIA1_D.ORA = Data; - VIA1_Put_ORA(VIA1_D.DDR_A, VIA1_D.ORA); - } else { - Data = (VIA1_D.ORA & VIA1_D.DDR_A) - | VIA1_Get_ORA(~ VIA1_D.DDR_A); - } -#if VIA1_dolog && 1 - dbglog_Access("VIA1_Access kORA", Data, WriteMem); -#endif - break; - } - return Data; -} - -GLOBALPROC VIA1_ExtraTimeBegin(void) -{ - if (VIA1_T1Running) { - VIA1_DoTimer1Check(); /* run up to this moment */ - VIA1_T1Running = falseblnr; - } - if (VIA1_T2Running & (! VIA1_T2C_ShortTime)) { - VIA1_DoTimer2Check(); /* run up to this moment */ - VIA1_T2Running = falseblnr; - } -} - -GLOBALPROC VIA1_ExtraTimeEnd(void) -{ - if (! VIA1_T1Running) { - VIA1_T1Running = trueblnr; - VIA1_T1LastTime = GetCuriCount(); - VIA1_DoTimer1Check(); - } - if (! VIA1_T2Running) { - VIA1_T2Running = trueblnr; - VIA1_T2LastTime = GetCuriCount(); - VIA1_DoTimer2Check(); - } -} - -/* VIA Interrupt Interface */ - -#ifdef VIA1_iCA1_PulseNtfy -GLOBALPROC VIA1_iCA1_PulseNtfy(void) -{ - VIA1_SetInterruptFlag(kIntCA1); -} -#endif - -#ifdef VIA1_iCA2_PulseNtfy -GLOBALPROC VIA1_iCA2_PulseNtfy(void) -{ - VIA1_SetInterruptFlag(kIntCA2); -} -#endif - -#ifdef VIA1_iCB1_PulseNtfy -GLOBALPROC VIA1_iCB1_PulseNtfy(void) -{ - VIA1_SetInterruptFlag(kIntCB1); -} -#endif - -#ifdef VIA1_iCB2_PulseNtfy -GLOBALPROC VIA1_iCB2_PulseNtfy(void) -{ - VIA1_SetInterruptFlag(kIntCB2); -} -#endif +/* VIAEMDEV.c Copyright (C) 2008 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* Versatile Interface Adapter EMulated DEVice Emulates the VIA found in the Mac Plus. This code adapted from vMac by Philip Cummins. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif #include "VIAEMDEV.h" /* ReportAbnormalID unused 0x0410 - 0x04FF */ #ifdef VIA1_iA0_ChangeNtfy IMPORTPROC VIA1_iA0_ChangeNtfy(void); #endif #ifdef VIA1_iA1_ChangeNtfy IMPORTPROC VIA1_iA1_ChangeNtfy(void); #endif #ifdef VIA1_iA2_ChangeNtfy IMPORTPROC VIA1_iA2_ChangeNtfy(void); #endif #ifdef VIA1_iA3_ChangeNtfy IMPORTPROC VIA1_iA3_ChangeNtfy(void); #endif #ifdef VIA1_iA4_ChangeNtfy IMPORTPROC VIA1_iA4_ChangeNtfy(void); #endif #ifdef VIA1_iA5_ChangeNtfy IMPORTPROC VIA1_iA5_ChangeNtfy(void); #endif #ifdef VIA1_iA6_ChangeNtfy IMPORTPROC VIA1_iA6_ChangeNtfy(void); #endif #ifdef VIA1_iA7_ChangeNtfy IMPORTPROC VIA1_iA7_ChangeNtfy(void); #endif #ifdef VIA1_iB0_ChangeNtfy IMPORTPROC VIA1_iB0_ChangeNtfy(void); #endif #ifdef VIA1_iB1_ChangeNtfy IMPORTPROC VIA1_iB1_ChangeNtfy(void); #endif #ifdef VIA1_iB2_ChangeNtfy IMPORTPROC VIA1_iB2_ChangeNtfy(void); #endif #ifdef VIA1_iB3_ChangeNtfy IMPORTPROC VIA1_iB3_ChangeNtfy(void); #endif #ifdef VIA1_iB4_ChangeNtfy IMPORTPROC VIA1_iB4_ChangeNtfy(void); #endif #ifdef VIA1_iB5_ChangeNtfy IMPORTPROC VIA1_iB5_ChangeNtfy(void); #endif #ifdef VIA1_iB6_ChangeNtfy IMPORTPROC VIA1_iB6_ChangeNtfy(void); #endif #ifdef VIA1_iB7_ChangeNtfy IMPORTPROC VIA1_iB7_ChangeNtfy(void); #endif #ifdef VIA1_iCB2_ChangeNtfy IMPORTPROC VIA1_iCB2_ChangeNtfy(void); #endif #define Ui3rPowOf2(p) (1 << (p)) #define Ui3rTestBit(i, p) (((i) & Ui3rPowOf2(p)) != 0) #define VIA1_ORA_CanInOrOut (VIA1_ORA_CanIn | VIA1_ORA_CanOut) #if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 7) #ifdef VIA1_iA7 #error "VIA1_iA7 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 6) #ifdef VIA1_iA6 #error "VIA1_iA6 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 5) #ifdef VIA1_iA5 #error "VIA1_iA5 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 4) #ifdef VIA1_iA4 #error "VIA1_iA4 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 3) #ifdef VIA1_iA3 #error "VIA1_iA3 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 2) #ifdef VIA1_iA2 #error "VIA1_iA2 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 1) #ifdef VIA1_iA1 #error "VIA1_iA1 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 0) #ifdef VIA1_iA0 #error "VIA1_iA0 defined but not used" #endif #endif #define VIA1_ORB_CanInOrOut (VIA1_ORB_CanIn | VIA1_ORB_CanOut) #if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 7) #ifdef VIA1_iB7 #error "VIA1_iB7 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 6) #ifdef VIA1_iB6 #error "VIA1_iB6 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 5) #ifdef VIA1_iB5 #error "VIA1_iB5 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 4) #ifdef VIA1_iB4 #error "VIA1_iB4 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 3) #ifdef VIA1_iB3 #error "VIA1_iB3 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 2) #ifdef VIA1_iB2 #error "VIA1_iB2 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 1) #ifdef VIA1_iB1 #error "VIA1_iB1 defined but not used" #endif #endif #if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 0) #ifdef VIA1_iB0 #error "VIA1_iB0 defined but not used" #endif #endif typedef struct { ui5b T1C_F; /* Timer 1 Counter Fixed Point */ ui5b T2C_F; /* Timer 2 Counter Fixed Point */ ui3b ORB; /* Buffer B */ /* ui3b ORA_H; Buffer A with Handshake */ ui3b DDR_B; /* Data Direction Register B */ ui3b DDR_A; /* Data Direction Register A */ ui3b T1L_L; /* Timer 1 Latch Low */ ui3b T1L_H; /* Timer 1 Latch High */ ui3b T2L_L; /* Timer 2 Latch Low */ ui3b SR; /* Shift Register */ ui3b ACR; /* Auxiliary Control Register */ ui3b PCR; /* Peripheral Control Register */ ui3b IFR; /* Interrupt Flag Register */ ui3b IER; /* Interrupt Enable Register */ ui3b ORA; /* Buffer A */ } VIA1_Ty; LOCALVAR VIA1_Ty VIA1_D; #define kIntCA2 0 /* One_Second */ #define kIntCA1 1 /* Vertical_Blanking */ #define kIntSR 2 /* Keyboard_Data_Ready */ #define kIntCB2 3 /* Keyboard_Data */ #define kIntCB1 4 /* Keyboard_Clock */ #define kIntT2 5 /* Timer_2 */ #define kIntT1 6 /* Timer_1 */ #define VIA1_dolog (dbglog_HAVE && 0) /* VIA1_Get_ORA : VIA Get Port A Data */ /* This function queries VIA Port A interfaced hardware about their status */ LOCALFUNC ui3b VIA1_Get_ORA(ui3b Selection) { ui3b Value = (~ VIA1_ORA_CanIn) & Selection & VIA1_ORA_FloatVal; #if Ui3rTestBit(VIA1_ORA_CanIn, 7) if (Ui3rTestBit(Selection, 7)) { Value |= (VIA1_iA7 << 7); } #endif #if Ui3rTestBit(VIA1_ORA_CanIn, 6) if (Ui3rTestBit(Selection, 6)) { Value |= (VIA1_iA6 << 6); } #endif #if Ui3rTestBit(VIA1_ORA_CanIn, 5) if (Ui3rTestBit(Selection, 5)) { Value |= (VIA1_iA5 << 5); } #endif #if Ui3rTestBit(VIA1_ORA_CanIn, 4) if (Ui3rTestBit(Selection, 4)) { Value |= (VIA1_iA4 << 4); } #endif #if Ui3rTestBit(VIA1_ORA_CanIn, 3) if (Ui3rTestBit(Selection, 3)) { Value |= (VIA1_iA3 << 3); } #endif #if Ui3rTestBit(VIA1_ORA_CanIn, 2) if (Ui3rTestBit(Selection, 2)) { Value |= (VIA1_iA2 << 2); } #endif #if Ui3rTestBit(VIA1_ORA_CanIn, 1) if (Ui3rTestBit(Selection, 1)) { Value |= (VIA1_iA1 << 1); } #endif #if Ui3rTestBit(VIA1_ORA_CanIn, 0) if (Ui3rTestBit(Selection, 0)) { Value |= (VIA1_iA0 << 0); } #endif return Value; } /* VIA1_Get_ORB : VIA Get Port B Data */ /* This function queries VIA Port B interfaced hardware about their status */ LOCALFUNC ui3b VIA1_Get_ORB(ui3b Selection) { ui3b Value = (~ VIA1_ORB_CanIn) & Selection & VIA1_ORB_FloatVal; #if Ui3rTestBit(VIA1_ORB_CanIn, 7) if (Ui3rTestBit(Selection, 7)) { Value |= (VIA1_iB7 << 7); } #endif #if Ui3rTestBit(VIA1_ORB_CanIn, 6) if (Ui3rTestBit(Selection, 6)) { Value |= (VIA1_iB6 << 6); } #endif #if Ui3rTestBit(VIA1_ORB_CanIn, 5) if (Ui3rTestBit(Selection, 5)) { Value |= (VIA1_iB5 << 5); } #endif #if Ui3rTestBit(VIA1_ORB_CanIn, 4) if (Ui3rTestBit(Selection, 4)) { Value |= (VIA1_iB4 << 4); } #endif #if Ui3rTestBit(VIA1_ORB_CanIn, 3) if (Ui3rTestBit(Selection, 3)) { Value |= (VIA1_iB3 << 3); } #endif #if Ui3rTestBit(VIA1_ORB_CanIn, 2) if (Ui3rTestBit(Selection, 2)) { Value |= (VIA1_iB2 << 2); } #endif #if Ui3rTestBit(VIA1_ORB_CanIn, 1) if (Ui3rTestBit(Selection, 1)) { Value |= (VIA1_iB1 << 1); } #endif #if Ui3rTestBit(VIA1_ORB_CanIn, 0) if (Ui3rTestBit(Selection, 0)) { Value |= (VIA1_iB0 << 0); } #endif return Value; } #define ViaORcheckBit(p, x) \ (Ui3rTestBit(Selection, p) && \ ((v = (Data >> p) & 1) != x)) LOCALPROC VIA1_Put_ORA(ui3b Selection, ui3b Data) { #if 0 != VIA1_ORA_CanOut ui3b v; #endif #if Ui3rTestBit(VIA1_ORA_CanOut, 7) if (ViaORcheckBit(7, VIA1_iA7)) { VIA1_iA7 = v; #ifdef VIA1_iA7_ChangeNtfy VIA1_iA7_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORA_CanOut, 6) if (ViaORcheckBit(6, VIA1_iA6)) { VIA1_iA6 = v; #ifdef VIA1_iA6_ChangeNtfy VIA1_iA6_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORA_CanOut, 5) if (ViaORcheckBit(5, VIA1_iA5)) { VIA1_iA5 = v; #ifdef VIA1_iA5_ChangeNtfy VIA1_iA5_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORA_CanOut, 4) if (ViaORcheckBit(4, VIA1_iA4)) { VIA1_iA4 = v; #ifdef VIA1_iA4_ChangeNtfy VIA1_iA4_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORA_CanOut, 3) if (ViaORcheckBit(3, VIA1_iA3)) { VIA1_iA3 = v; #ifdef VIA1_iA3_ChangeNtfy VIA1_iA3_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORA_CanOut, 2) if (ViaORcheckBit(2, VIA1_iA2)) { VIA1_iA2 = v; #ifdef VIA1_iA2_ChangeNtfy VIA1_iA2_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORA_CanOut, 1) if (ViaORcheckBit(1, VIA1_iA1)) { VIA1_iA1 = v; #ifdef VIA1_iA1_ChangeNtfy VIA1_iA1_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORA_CanOut, 0) if (ViaORcheckBit(0, VIA1_iA0)) { VIA1_iA0 = v; #ifdef VIA1_iA0_ChangeNtfy VIA1_iA0_ChangeNtfy(); #endif } #endif } LOCALPROC VIA1_Put_ORB(ui3b Selection, ui3b Data) { #if 0 != VIA1_ORB_CanOut ui3b v; #endif #if Ui3rTestBit(VIA1_ORB_CanOut, 7) if (ViaORcheckBit(7, VIA1_iB7)) { VIA1_iB7 = v; #ifdef VIA1_iB7_ChangeNtfy VIA1_iB7_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORB_CanOut, 6) if (ViaORcheckBit(6, VIA1_iB6)) { VIA1_iB6 = v; #ifdef VIA1_iB6_ChangeNtfy VIA1_iB6_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORB_CanOut, 5) if (ViaORcheckBit(5, VIA1_iB5)) { VIA1_iB5 = v; #ifdef VIA1_iB5_ChangeNtfy VIA1_iB5_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORB_CanOut, 4) if (ViaORcheckBit(4, VIA1_iB4)) { VIA1_iB4 = v; #ifdef VIA1_iB4_ChangeNtfy VIA1_iB4_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORB_CanOut, 3) if (ViaORcheckBit(3, VIA1_iB3)) { VIA1_iB3 = v; #ifdef VIA1_iB3_ChangeNtfy VIA1_iB3_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORB_CanOut, 2) if (ViaORcheckBit(2, VIA1_iB2)) { VIA1_iB2 = v; #ifdef VIA1_iB2_ChangeNtfy VIA1_iB2_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORB_CanOut, 1) if (ViaORcheckBit(1, VIA1_iB1)) { VIA1_iB1 = v; #ifdef VIA1_iB1_ChangeNtfy VIA1_iB1_ChangeNtfy(); #endif } #endif #if Ui3rTestBit(VIA1_ORB_CanOut, 0) if (ViaORcheckBit(0, VIA1_iB0)) { VIA1_iB0 = v; #ifdef VIA1_iB0_ChangeNtfy VIA1_iB0_ChangeNtfy(); #endif } #endif } LOCALPROC VIA1_SetDDR_A(ui3b Data) { ui3b floatbits = VIA1_D.DDR_A & ~ Data; ui3b unfloatbits = Data & ~ VIA1_D.DDR_A; if (floatbits != 0) { VIA1_Put_ORA(floatbits, VIA1_ORA_FloatVal); } VIA1_D.DDR_A = Data; if (unfloatbits != 0) { VIA1_Put_ORA(unfloatbits, VIA1_D.ORA); } if ((Data & ~ VIA1_ORA_CanOut) != 0) { ReportAbnormalID(0x0401, "Set VIA1_D.DDR_A unexpected direction"); } } LOCALPROC VIA1_SetDDR_B(ui3b Data) { ui3b floatbits = VIA1_D.DDR_B & ~ Data; ui3b unfloatbits = Data & ~ VIA1_D.DDR_B; if (floatbits != 0) { VIA1_Put_ORB(floatbits, VIA1_ORB_FloatVal); } VIA1_D.DDR_B = Data; if (unfloatbits != 0) { VIA1_Put_ORB(unfloatbits, VIA1_D.ORB); } if ((Data & ~ VIA1_ORB_CanOut) != 0) { ReportAbnormalID(0x0402, "Set VIA1_D.DDR_B unexpected direction"); } } LOCALPROC VIA1_CheckInterruptFlag(void) { ui3b NewInterruptRequest = ((VIA1_D.IFR & VIA1_D.IER) != 0) ? 1 : 0; if (NewInterruptRequest != VIA1_InterruptRequest) { VIA1_InterruptRequest = NewInterruptRequest; #ifdef VIA1_interruptChngNtfy VIA1_interruptChngNtfy(); #endif } } LOCALVAR ui3b VIA1_T1_Active = 0; LOCALVAR ui3b VIA1_T2_Active = 0; LOCALVAR blnr VIA1_T1IntReady = falseblnr; LOCALPROC VIA1_Clear(void) { VIA1_D.ORA = 0; VIA1_D.DDR_A = 0; VIA1_D.ORB = 0; VIA1_D.DDR_B = 0; VIA1_D.T1L_L = VIA1_D.T1L_H = 0x00; VIA1_D.T2L_L = 0x00; VIA1_D.T1C_F = 0; VIA1_D.T2C_F = 0; VIA1_D.SR = VIA1_D.ACR = 0x00; VIA1_D.PCR = VIA1_D.IFR = VIA1_D.IER = 0x00; VIA1_T1_Active = VIA1_T2_Active = 0x00; VIA1_T1IntReady = falseblnr; } GLOBALPROC VIA1_Zap(void) { VIA1_Clear(); VIA1_InterruptRequest = 0; } GLOBALPROC VIA1_Reset(void) { VIA1_SetDDR_A(0); VIA1_SetDDR_B(0); VIA1_Clear(); VIA1_CheckInterruptFlag(); } LOCALPROC VIA1_SetInterruptFlag(ui3b VIA_Int) { VIA1_D.IFR |= ((ui3b)1 << VIA_Int); VIA1_CheckInterruptFlag(); } LOCALPROC VIA1_ClrInterruptFlag(ui3b VIA_Int) { VIA1_D.IFR &= ~ ((ui3b)1 << VIA_Int); VIA1_CheckInterruptFlag(); } #ifdef _VIA_Debug #include #endif GLOBALPROC VIA1_ShiftInData(ui3b v) { /* external hardware generates 8 pulses on CB1, writes 8 bits to CB2 */ ui3b ShiftMode = (VIA1_D.ACR & 0x1C) >> 2; if (ShiftMode != 3) { #if ExtraAbnormalReports if (ShiftMode == 0) { /* happens on reset */ } else { ReportAbnormalID(0x0403, "VIA Not ready to shift in"); /* Observed (rarely) in Crystal Quest played at 1x speed in "-t mc64". */ } #endif } else { VIA1_D.SR = v; VIA1_SetInterruptFlag(kIntSR); VIA1_SetInterruptFlag(kIntCB1); } } GLOBALFUNC ui3b VIA1_ShiftOutData(void) { /* external hardware generates 8 pulses on CB1, reads 8 bits from CB2 */ if (((VIA1_D.ACR & 0x1C) >> 2) != 7) { ReportAbnormalID(0x0404, "VIA Not ready to shift out"); return 0; } else { VIA1_SetInterruptFlag(kIntSR); VIA1_SetInterruptFlag(kIntCB1); VIA1_iCB2 = (VIA1_D.SR & 1); return VIA1_D.SR; } } #define CyclesPerViaTime (10 * kMyClockMult) #define CyclesScaledPerViaTime (kCycleScale * CyclesPerViaTime) LOCALVAR blnr VIA1_T1Running = trueblnr; LOCALVAR iCountt VIA1_T1LastTime = 0; GLOBALPROC VIA1_DoTimer1Check(void) { if (VIA1_T1Running) { iCountt NewTime = GetCuriCount(); iCountt deltaTime = (NewTime - VIA1_T1LastTime); if (deltaTime != 0) { ui5b Temp = VIA1_D.T1C_F; /* Get Timer 1 Counter */ ui5b deltaTemp = (deltaTime / CyclesPerViaTime) << (16 - kLn2CycleScale); /* may overflow */ ui5b NewTemp = Temp - deltaTemp; if ((deltaTime > (0x00010000UL * CyclesScaledPerViaTime)) || ((Temp <= deltaTemp) && (Temp != 0))) { if ((VIA1_D.ACR & 0x40) != 0) { /* Free Running? */ /* Reload Counter from Latches */ ui4b v = (VIA1_D.T1L_H << 8) + VIA1_D.T1L_L; ui4b ntrans = 1 + ((v == 0) ? 0 : (((deltaTemp - Temp) / v) >> 16)); NewTemp += (((ui5b)v * ntrans) << 16); #if Ui3rTestBit(VIA1_ORB_CanOut, 7) if ((VIA1_D.ACR & 0x80) != 0) { /* invert ? */ if ((ntrans & 1) != 0) { VIA1_iB7 ^= 1; #ifdef VIA1_iB7_ChangeNtfy VIA1_iB7_ChangeNtfy(); #endif } } #endif VIA1_SetInterruptFlag(kIntT1); #if VIA1_dolog && 1 dbglog_WriteNote("VIA1 Timer 1 Interrupt"); #endif } else { if (VIA1_T1_Active == 1) { VIA1_T1_Active = 0; VIA1_SetInterruptFlag(kIntT1); #if VIA1_dolog && 1 dbglog_WriteNote("VIA1 Timer 1 Interrupt"); #endif } } } VIA1_D.T1C_F = NewTemp; VIA1_T1LastTime = NewTime; } VIA1_T1IntReady = falseblnr; if ((VIA1_D.IFR & (1 << kIntT1)) == 0) { if (((VIA1_D.ACR & 0x40) != 0) || (VIA1_T1_Active == 1)) { ui5b NewTemp = VIA1_D.T1C_F; /* Get Timer 1 Counter */ ui5b NewTimer; #ifdef _VIA_Debug fprintf(stderr, "posting Timer1Check, %d, %d\n", Temp, GetCuriCount()); #endif if (NewTemp == 0) { NewTimer = (0x00010000UL * CyclesScaledPerViaTime); } else { NewTimer = (1 + (NewTemp >> (16 - kLn2CycleScale))) * CyclesPerViaTime; } ICT_add(kICT_VIA1_Timer1Check, NewTimer); VIA1_T1IntReady = trueblnr; } } } } LOCALPROC CheckT1IntReady(void) { if (VIA1_T1Running) { blnr NewT1IntReady = falseblnr; if ((VIA1_D.IFR & (1 << kIntT1)) == 0) { if (((VIA1_D.ACR & 0x40) != 0) || (VIA1_T1_Active == 1)) { NewT1IntReady = trueblnr; } } if (VIA1_T1IntReady != NewT1IntReady) { VIA1_T1IntReady = NewT1IntReady; if (NewT1IntReady) { VIA1_DoTimer1Check(); } } } } GLOBALFUNC ui4b VIA1_GetT1InvertTime(void) { ui4b v; if ((VIA1_D.ACR & 0xC0) == 0xC0) { v = (VIA1_D.T1L_H << 8) + VIA1_D.T1L_L; } else { v = 0; } return v; } LOCALVAR blnr VIA1_T2Running = trueblnr; LOCALVAR blnr VIA1_T2C_ShortTime = falseblnr; LOCALVAR iCountt VIA1_T2LastTime = 0; GLOBALPROC VIA1_DoTimer2Check(void) { if (VIA1_T2Running) { iCountt NewTime = GetCuriCount(); ui5b Temp = VIA1_D.T2C_F; /* Get Timer 2 Counter */ iCountt deltaTime = (NewTime - VIA1_T2LastTime); ui5b deltaTemp = (deltaTime / CyclesPerViaTime) << (16 - kLn2CycleScale); /* may overflow */ ui5b NewTemp = Temp - deltaTemp; if (VIA1_T2_Active == 1) { if ((deltaTime > (0x00010000UL * CyclesScaledPerViaTime)) || ((Temp <= deltaTemp) && (Temp != 0))) { VIA1_T2C_ShortTime = falseblnr; VIA1_T2_Active = 0; VIA1_SetInterruptFlag(kIntT2); #if VIA1_dolog && 1 dbglog_WriteNote("VIA1 Timer 2 Interrupt"); #endif } else { ui5b NewTimer; #ifdef _VIA_Debug fprintf(stderr, "posting Timer2Check, %d, %d\n", Temp, GetCuriCount()); #endif if (NewTemp == 0) { NewTimer = (0x00010000UL * CyclesScaledPerViaTime); } else { NewTimer = (1 + (NewTemp >> (16 - kLn2CycleScale))) * CyclesPerViaTime; } ICT_add(kICT_VIA1_Timer2Check, NewTimer); } } VIA1_D.T2C_F = NewTemp; VIA1_T2LastTime = NewTime; } } #define kORB 0x00 #define kORA_H 0x01 #define kDDR_B 0x02 #define kDDR_A 0x03 #define kT1C_L 0x04 #define kT1C_H 0x05 #define kT1L_L 0x06 #define kT1L_H 0x07 #define kT2_L 0x08 #define kT2_H 0x09 #define kSR 0x0A #define kACR 0x0B #define kPCR 0x0C #define kIFR 0x0D #define kIER 0x0E #define kORA 0x0F GLOBALFUNC ui5b VIA1_Access(ui5b Data, blnr WriteMem, CPTR addr) { switch (addr) { case kORB : #if VIA1_CB2modesAllowed != 0x01 if ((VIA1_D.PCR & 0xE0) == 0) #endif { VIA1_ClrInterruptFlag(kIntCB2); } VIA1_ClrInterruptFlag(kIntCB1); if (WriteMem) { VIA1_D.ORB = Data; VIA1_Put_ORB(VIA1_D.DDR_B, VIA1_D.ORB); } else { Data = (VIA1_D.ORB & VIA1_D.DDR_B) | VIA1_Get_ORB(~ VIA1_D.DDR_B); } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kORB", Data, WriteMem); #endif break; case kDDR_B : if (WriteMem) { VIA1_SetDDR_B(Data); } else { Data = VIA1_D.DDR_B; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kDDR_B", Data, WriteMem); #endif break; case kDDR_A : if (WriteMem) { VIA1_SetDDR_A(Data); } else { Data = VIA1_D.DDR_A; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kDDR_A", Data, WriteMem); #endif break; case kT1C_L : if (WriteMem) { VIA1_D.T1L_L = Data; } else { VIA1_ClrInterruptFlag(kIntT1); VIA1_DoTimer1Check(); Data = (VIA1_D.T1C_F & 0x00FF0000) >> 16; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kT1C_L", Data, WriteMem); #endif break; case kT1C_H : if (WriteMem) { VIA1_D.T1L_H = Data; VIA1_ClrInterruptFlag(kIntT1); VIA1_D.T1C_F = (Data << 24) + (VIA1_D.T1L_L << 16); if ((VIA1_D.ACR & 0x40) == 0) { VIA1_T1_Active = 1; } VIA1_T1LastTime = GetCuriCount(); VIA1_DoTimer1Check(); } else { VIA1_DoTimer1Check(); Data = (VIA1_D.T1C_F & 0xFF000000) >> 24; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kT1C_H", Data, WriteMem); #endif break; case kT1L_L : if (WriteMem) { VIA1_D.T1L_L = Data; } else { Data = VIA1_D.T1L_L; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kT1L_L", Data, WriteMem); #endif break; case kT1L_H : if (WriteMem) { VIA1_D.T1L_H = Data; } else { Data = VIA1_D.T1L_H; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kT1L_H", Data, WriteMem); #endif break; case kT2_L : if (WriteMem) { VIA1_D.T2L_L = Data; } else { VIA1_ClrInterruptFlag(kIntT2); VIA1_DoTimer2Check(); Data = (VIA1_D.T2C_F & 0x00FF0000) >> 16; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kT2_L", Data, WriteMem); #endif break; case kT2_H : if (WriteMem) { VIA1_D.T2C_F = (Data << 24) + (VIA1_D.T2L_L << 16); VIA1_ClrInterruptFlag(kIntT2); VIA1_T2_Active = 1; if ((VIA1_D.T2C_F < (128UL << 16)) && (VIA1_D.T2C_F != 0)) { VIA1_T2C_ShortTime = trueblnr; VIA1_T2Running = trueblnr; /* Running too many instructions during a short timer interval can crash when playing sounds in System 7. So in this case don't let timer pause. */ } VIA1_T2LastTime = GetCuriCount(); VIA1_DoTimer2Check(); } else { VIA1_DoTimer2Check(); Data = (VIA1_D.T2C_F & 0xFF000000) >> 24; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kT2_H", Data, WriteMem); #endif break; case kSR: #ifdef _VIA_Debug fprintf(stderr, "VIA1_D.SR: %d, %d, %d\n", WriteMem, ((VIA1_D.ACR & 0x1C) >> 2), Data); #endif if (WriteMem) { VIA1_D.SR = Data; } VIA1_ClrInterruptFlag(kIntSR); switch ((VIA1_D.ACR & 0x1C) >> 2) { case 3 : /* Shifting In */ break; case 6 : /* shift out under o2 clock */ if ((! WriteMem) || (VIA1_D.SR != 0)) { ReportAbnormalID(0x0405, "VIA shift mode 6, non zero"); } else { #ifdef _VIA_Debug fprintf(stderr, "posting Foo2Task\n"); #endif if (VIA1_iCB2 != 0) { VIA1_iCB2 = 0; #ifdef VIA1_iCB2_ChangeNtfy VIA1_iCB2_ChangeNtfy(); #endif } } #if 0 /* possibly should do this. seems not to affect anything. */ VIA1_SetInterruptFlag(kIntSR); /* don't wait */ #endif break; case 7 : /* Shifting Out */ break; } if (! WriteMem) { Data = VIA1_D.SR; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kSR", Data, WriteMem); #endif break; case kACR: if (WriteMem) { #if 1 if ((VIA1_D.ACR & 0x10) != ((ui3b)Data & 0x10)) { /* shift direction has changed */ if ((Data & 0x10) == 0) { /* no longer an output, set data to float value */ if (VIA1_iCB2 == 0) { VIA1_iCB2 = 1; #ifdef VIA1_iCB2_ChangeNtfy VIA1_iCB2_ChangeNtfy(); #endif } } } #endif VIA1_D.ACR = Data; if ((VIA1_D.ACR & 0x20) != 0) { /* Not pulse counting? */ ReportAbnormalID(0x0406, "Set VIA1_D.ACR T2 Timer pulse counting"); } switch ((VIA1_D.ACR & 0xC0) >> 6) { /* case 1: happens in early System 6 */ case 2: ReportAbnormalID(0x0407, "Set VIA1_D.ACR T1 Timer mode 2"); break; } CheckT1IntReady(); switch ((VIA1_D.ACR & 0x1C) >> 2) { case 0: /* this isn't sufficient */ VIA1_ClrInterruptFlag(kIntSR); break; case 1: case 2: case 4: case 5: ReportAbnormalID(0x0408, "Set VIA1_D.ACR shift mode 1,2,4,5"); break; default: break; } if ((VIA1_D.ACR & 0x03) != 0) { ReportAbnormalID(0x0409, "Set VIA1_D.ACR T2 Timer latching enabled"); } } else { Data = VIA1_D.ACR; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kACR", Data, WriteMem); #endif break; case kPCR: if (WriteMem) { VIA1_D.PCR = Data; #define Ui3rSetContains(s, i) (((s) & (1 << (i))) != 0) if (! Ui3rSetContains(VIA1_CB2modesAllowed, (VIA1_D.PCR >> 5) & 0x07)) { ReportAbnormalID(0x040A, "Set VIA1_D.PCR CB2 Control mode?"); } if ((VIA1_D.PCR & 0x10) != 0) { ReportAbnormalID(0x040B, "Set VIA1_D.PCR CB1 INTERRUPT CONTROL?"); } if (! Ui3rSetContains(VIA1_CA2modesAllowed, (VIA1_D.PCR >> 1) & 0x07)) { ReportAbnormalID(0x040C, "Set VIA1_D.PCR CA2 INTERRUPT CONTROL?"); } if ((VIA1_D.PCR & 0x01) != 0) { ReportAbnormalID(0x040D, "Set VIA1_D.PCR CA1 INTERRUPT CONTROL?"); } } else { Data = VIA1_D.PCR; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kPCR", Data, WriteMem); #endif break; case kIFR: if (WriteMem) { VIA1_D.IFR = VIA1_D.IFR & ((~ Data) & 0x7F); /* Clear Flag Bits */ VIA1_CheckInterruptFlag(); CheckT1IntReady(); } else { Data = VIA1_D.IFR; if ((VIA1_D.IFR & VIA1_D.IER) != 0) { Data |= 0x80; } } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kIFR", Data, WriteMem); #endif break; case kIER : if (WriteMem) { if ((Data & 0x80) == 0) { VIA1_D.IER = VIA1_D.IER & ((~ Data) & 0x7F); /* Clear Enable Bits */ #if 0 != VIA1_IER_Never0 /* of course, will be 0 initially, this just checks not cleared later. */ if ((Data & VIA1_IER_Never0) != 0) { ReportAbnormalID(0x040E, "IER Never0 clr"); } #endif } else { VIA1_D.IER = VIA1_D.IER | (Data & 0x7F); /* Set Enable Bits */ #if 0 != VIA1_IER_Never1 if ((VIA1_D.IER & VIA1_IER_Never1) != 0) { ReportAbnormalID(0x040F, "IER Never1 set"); } #endif } VIA1_CheckInterruptFlag(); } else { Data = VIA1_D.IER | 0x80; } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kIER", Data, WriteMem); #endif break; case kORA : case kORA_H : if ((VIA1_D.PCR & 0xE) == 0) { VIA1_ClrInterruptFlag(kIntCA2); } VIA1_ClrInterruptFlag(kIntCA1); if (WriteMem) { VIA1_D.ORA = Data; VIA1_Put_ORA(VIA1_D.DDR_A, VIA1_D.ORA); } else { Data = (VIA1_D.ORA & VIA1_D.DDR_A) | VIA1_Get_ORA(~ VIA1_D.DDR_A); } #if VIA1_dolog && 1 dbglog_Access("VIA1_Access kORA", Data, WriteMem); #endif break; } return Data; } GLOBALPROC VIA1_ExtraTimeBegin(void) { if (VIA1_T1Running) { VIA1_DoTimer1Check(); /* run up to this moment */ VIA1_T1Running = falseblnr; } if (VIA1_T2Running & (! VIA1_T2C_ShortTime)) { VIA1_DoTimer2Check(); /* run up to this moment */ VIA1_T2Running = falseblnr; } } GLOBALPROC VIA1_ExtraTimeEnd(void) { if (! VIA1_T1Running) { VIA1_T1Running = trueblnr; VIA1_T1LastTime = GetCuriCount(); VIA1_DoTimer1Check(); } if (! VIA1_T2Running) { VIA1_T2Running = trueblnr; VIA1_T2LastTime = GetCuriCount(); VIA1_DoTimer2Check(); } } /* VIA Interrupt Interface */ #ifdef VIA1_iCA1_PulseNtfy GLOBALPROC VIA1_iCA1_PulseNtfy(void) { VIA1_SetInterruptFlag(kIntCA1); } #endif #ifdef VIA1_iCA2_PulseNtfy GLOBALPROC VIA1_iCA2_PulseNtfy(void) { VIA1_SetInterruptFlag(kIntCA2); } #endif #ifdef VIA1_iCB1_PulseNtfy GLOBALPROC VIA1_iCB1_PulseNtfy(void) { VIA1_SetInterruptFlag(kIntCB1); } #endif #ifdef VIA1_iCB2_PulseNtfy GLOBALPROC VIA1_iCB2_PulseNtfy(void) { VIA1_SetInterruptFlag(kIntCB2); } #endif \ No newline at end of file diff --git a/Mini vMac/mnvm_core/VIAEMDEV.h b/Mini vMac/mnvm_core/VIAEMDEV.h index f507e91..1773257 100755 --- a/Mini vMac/mnvm_core/VIAEMDEV.h +++ b/Mini vMac/mnvm_core/VIAEMDEV.h @@ -1,48 +1 @@ -/* - VIAEMDEV.h - - Copyright (C) 2004 Philip Cummins, Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef VIAEMDEV_H -#error "header already included" -#else -#define VIAEMDEV_H -#endif - -EXPORTPROC VIA1_Zap(void); -EXPORTPROC VIA1_Reset(void); - -EXPORTFUNC ui5b VIA1_Access(ui5b Data, blnr WriteMem, CPTR addr); - -EXPORTPROC VIA1_ExtraTimeBegin(void); -EXPORTPROC VIA1_ExtraTimeEnd(void); -#ifdef VIA1_iCA1_PulseNtfy -EXPORTPROC VIA1_iCA1_PulseNtfy(void); -#endif -#ifdef VIA1_iCA2_PulseNtfy -EXPORTPROC VIA1_iCA2_PulseNtfy(void); -#endif -#ifdef VIA1_iCB1_PulseNtfy -EXPORTPROC VIA1_iCB1_PulseNtfy(void); -#endif -#ifdef VIA1_iCB2_PulseNtfy -EXPORTPROC VIA1_iCB2_PulseNtfy(void); -#endif -EXPORTPROC VIA1_DoTimer1Check(void); -EXPORTPROC VIA1_DoTimer2Check(void); - -EXPORTFUNC ui4b VIA1_GetT1InvertTime(void); - -EXPORTPROC VIA1_ShiftInData(ui3b v); -EXPORTFUNC ui3b VIA1_ShiftOutData(void); +/* VIAEMDEV.h Copyright (C) 2004 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef VIAEMDEV_H #error "header already included" #else #define VIAEMDEV_H #endif EXPORTPROC VIA1_Zap(void); EXPORTPROC VIA1_Reset(void); EXPORTFUNC ui5b VIA1_Access(ui5b Data, blnr WriteMem, CPTR addr); EXPORTPROC VIA1_ExtraTimeBegin(void); EXPORTPROC VIA1_ExtraTimeEnd(void); #ifdef VIA1_iCA1_PulseNtfy EXPORTPROC VIA1_iCA1_PulseNtfy(void); #endif #ifdef VIA1_iCA2_PulseNtfy EXPORTPROC VIA1_iCA2_PulseNtfy(void); #endif #ifdef VIA1_iCB1_PulseNtfy EXPORTPROC VIA1_iCB1_PulseNtfy(void); #endif #ifdef VIA1_iCB2_PulseNtfy EXPORTPROC VIA1_iCB2_PulseNtfy(void); #endif EXPORTPROC VIA1_DoTimer1Check(void); EXPORTPROC VIA1_DoTimer2Check(void); EXPORTFUNC ui4b VIA1_GetT1InvertTime(void); EXPORTPROC VIA1_ShiftInData(ui3b v); EXPORTFUNC ui3b VIA1_ShiftOutData(void); \ No newline at end of file diff --git a/Mini vMac/mnvm_core/VIDEMDEV.c b/Mini vMac/mnvm_core/VIDEMDEV.c index 6379f78..4391399 100755 --- a/Mini vMac/mnvm_core/VIDEMDEV.c +++ b/Mini vMac/mnvm_core/VIDEMDEV.c @@ -1,746 +1 @@ -/* - VIDEMDEV.c - - Copyright (C) 2008 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -/* - VIDeo card EMulated DEVice - - Emulation of video card for Macintosh II. - - Written referring to: - Sample firmware code in "Designing Cards and Drivers - for Macintosh II and Macintosh SE", Apple Computer, - page 8-20. - - Basilisk II source code, especially slot_rom.cpp -*/ - -#ifndef AllFiles -#include "SYSDEPNS.h" -#include "MYOSGLUE.h" -#include "ENDIANAC.h" -#include "EMCONFIG.h" -#include "GLOBGLUE.h" -#include "MINEM68K.h" -#include "SONYEMDV.h" -#endif - -#include "VIDEMDEV.h" - -LOCALVAR const ui3b VidDrvr_contents[] = { -0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x2A, 0x00, 0x00, 0x00, 0xE2, 0x00, 0xEC, -0x00, 0xB6, 0x15, 0x2E, 0x44, 0x69, 0x73, 0x70, -0x6C, 0x61, 0x79, 0x5F, 0x56, 0x69, 0x64, 0x65, -0x6F, 0x5F, 0x53, 0x61, 0x6D, 0x70, 0x6C, 0x65, -0x00, 0x00, 0x24, 0x48, 0x26, 0x49, 0x70, 0x04, -0xA4, 0x40, 0x70, 0x04, 0xA7, 0x22, 0x66, 0x00, -0x00, 0x50, 0x27, 0x48, 0x00, 0x14, 0xA0, 0x29, -0x49, 0xFA, 0x00, 0x4A, 0x70, 0x10, 0xA7, 0x1E, -0x66, 0x00, 0x00, 0x3E, 0x31, 0x7C, 0x00, 0x06, -0x00, 0x04, 0x21, 0x4C, 0x00, 0x08, 0x21, 0x4B, -0x00, 0x0C, 0x70, 0x00, 0x10, 0x2B, 0x00, 0x28, -0xA0, 0x75, 0x66, 0x24, 0x22, 0x6B, 0x00, 0x14, -0x22, 0x51, 0x22, 0x88, 0x3F, 0x3C, 0x00, 0x01, -0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x03, 0x41, 0xFA, -0x00, 0x9C, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, -0xDE, 0xFC, 0x00, 0x0A, 0x70, 0x00, 0x60, 0x02, -0x70, 0xE9, 0x4E, 0x75, 0x2F, 0x08, 0x55, 0x4F, -0x3F, 0x3C, 0x00, 0x04, 0x41, 0xFA, 0x00, 0x7E, -0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x50, 0x4F, -0x20, 0x29, 0x00, 0x2A, 0xE1, 0x98, 0x02, 0x40, -0x00, 0x0F, 0x20, 0x78, 0x0D, 0x28, 0x4E, 0x90, -0x20, 0x5F, 0x70, 0x01, 0x4E, 0x75, 0x2F, 0x0B, -0x26, 0x69, 0x00, 0x14, 0x42, 0x67, 0x55, 0x4F, -0x3F, 0x3C, 0x00, 0x03, 0x41, 0xFA, 0x00, 0x4E, -0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0xDE, 0xFC, -0x00, 0x0A, 0x20, 0x53, 0x20, 0x50, 0xA0, 0x76, -0x20, 0x4B, 0xA0, 0x23, 0x70, 0x00, 0x26, 0x5F, -0x4E, 0x75, 0x2F, 0x08, 0x55, 0x4F, 0x3F, 0x3C, -0x00, 0x06, 0x60, 0x08, 0x2F, 0x08, 0x55, 0x4F, -0x3F, 0x3C, 0x00, 0x05, 0x41, 0xFA, 0x00, 0x1E, -0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, -0x30, 0x1F, 0x20, 0x5F, 0x08, 0x28, 0x00, 0x09, -0x00, 0x06, 0x67, 0x02, 0x4E, 0x75, 0x20, 0x78, -0x08, 0xFC, 0x4E, 0xD0 -}; - -LOCALPROC ChecksumSlotROM(void) -{ - /* Calculate CRC */ - /* assuming check sum field initialized to zero */ - int i; - ui3p p = VidROM; - ui5b crc = 0; - - for (i = kVidROM_Size; --i >= 0; ) { - crc = ((crc << 1) | (crc >> 31)) + *p++; - } - do_put_mem_long(p - 12, crc); -} - -LOCALVAR ui3p pPatch; - -LOCALPROC PatchAByte(ui3b v) -{ - *pPatch++ = v; -} - -LOCALPROC PatchAWord(ui4r v) -{ - PatchAByte(v >> 8); - PatchAByte(v & 0x00FF); -} - -LOCALPROC PatchALong(ui5r v) -{ - PatchAWord(v >> 16); - PatchAWord(v & 0x0000FFFF); -} - -#if 0 -LOCALPROC PatchAOSLstEntry0(ui3r Id, ui5r Offset) -{ - PatchALong((Id << 24) | (Offset & 0x00FFFFFF)); -} -#endif - -LOCALPROC PatchAOSLstEntry(ui3r Id, ui3p Offset) -{ - PatchALong((Id << 24) | ((Offset - pPatch) & 0x00FFFFFF)); -} - -LOCALFUNC ui3p ReservePatchOSLstEntry(void) -{ - ui3p v = pPatch; - pPatch += 4; - return v; -} - -LOCALPROC PatchAReservedOSLstEntry(ui3p p, ui3r Id) -{ - ui3p pPatchSave = pPatch; - pPatch = p; - PatchAOSLstEntry(Id, pPatchSave); - pPatch = pPatchSave; -} - -LOCALPROC PatchADatLstEntry(ui3r Id, ui5r Data) -{ - PatchALong((Id << 24) | (Data & 0x00FFFFFF)); -} - -LOCALPROC PatchAnEndOfLst(void) -{ - PatchADatLstEntry(0xFF /* endOfList */, 0x00000000); -} - -GLOBALFUNC blnr Vid_Init(void) -{ - int i; - ui5r UsedSoFar; - - ui3p pAt_sRsrcDir; - ui3p pTo_sRsrc_Board; - ui3p pTo_BoardType; - ui3p pTo_BoardName; - ui3p pTo_VenderInfo; - ui3p pTo_VendorID; - ui3p pTo_RevLevel; - ui3p pTo_PartNum; - ui3p pTo_sRsrc_Video; - ui3p pTo_VideoType; - ui3p pTo_VideoName; - ui3p pTo_MinorBase; - ui3p pTo_MinorLength; -#if 0 - ui3p pTo_MajorBase; - ui3p pTo_MajorLength; -#endif - ui3p pTo_VidDrvrDir; - ui3p pTo_sMacOS68020; - ui3p pTo_OneBitMode; - ui3p pTo_OneVidParams; -#if 0 != vMacScreenDepth - ui3p pTo_ColorBitMode = nullpr; - ui3p pTo_ColorVidParams; -#endif - - pPatch = VidROM; - - pAt_sRsrcDir = pPatch; - pTo_sRsrc_Board = ReservePatchOSLstEntry(); - pTo_sRsrc_Video = ReservePatchOSLstEntry(); - PatchAnEndOfLst(); - - PatchAReservedOSLstEntry(pTo_sRsrc_Board, 0x01 /* sRsrc_Board */); - pTo_BoardType = ReservePatchOSLstEntry(); - pTo_BoardName = ReservePatchOSLstEntry(); - PatchADatLstEntry(0x20 /* BoardId */, 0x0000764D); - /* 'vM', for Mini vMac */ - pTo_VenderInfo = ReservePatchOSLstEntry(); - PatchAnEndOfLst(); - - PatchAReservedOSLstEntry(pTo_BoardType, 0x01 /* sRsrcType */); - PatchAWord(0x0001); - PatchAWord(0x0000); - PatchAWord(0x0000); - PatchAWord(0x0000); - - PatchAReservedOSLstEntry(pTo_BoardName, 0x02 /* sRsrcName */); - /* - 'Mini vMac video card' as ascii c string - (null terminated), and - zero padded to end aligned long. - */ - PatchALong(0x4D696E69); - PatchALong(0x20764D61); - PatchALong(0x63207669); - PatchALong(0x64656F20); - PatchALong(0x63617264); - PatchALong(0x00000000); - - PatchAReservedOSLstEntry(pTo_VenderInfo, 0x24 /* vendorInfo */); - - pTo_VendorID = ReservePatchOSLstEntry(); - pTo_RevLevel = ReservePatchOSLstEntry(); - pTo_PartNum = ReservePatchOSLstEntry(); - PatchAnEndOfLst(); - - PatchAReservedOSLstEntry(pTo_VendorID, 0x01 /* vendorId */); - /* - 'Paul C. Pratt' as ascii c string - (null terminated), and - zero padded to end aligned long. - */ - PatchALong(0x5061756C); - PatchALong(0x20432E20); - PatchALong(0x50726174); - PatchALong(0x74000000); - - PatchAReservedOSLstEntry(pTo_RevLevel, 0x03 /* revLevel */); - /* - '1.0' as ascii c string - (null terminated), and - zero padded to end aligned long. - */ - PatchALong(0x312E3000); - - PatchAReservedOSLstEntry(pTo_PartNum, 0x04 /* partNum */); - /* - 'TFB-1' as ascii c string - (null terminated), and - zero padded to end aligned long. - */ - PatchALong(0x5446422D); - PatchALong(0x31000000); - - PatchAReservedOSLstEntry(pTo_sRsrc_Video, 0x80 /* sRsrc_Video */); - - pTo_VideoType = ReservePatchOSLstEntry(); - pTo_VideoName = ReservePatchOSLstEntry(); - pTo_VidDrvrDir = ReservePatchOSLstEntry(); - PatchADatLstEntry(0x08 /* sRsrcHWDevId */, 0x00000001); - pTo_MinorBase = ReservePatchOSLstEntry(); - pTo_MinorLength = ReservePatchOSLstEntry(); -#if 0 - pTo_MajorBase = ReservePatchOSLstEntry(); - pTo_MajorLength = ReservePatchOSLstEntry(); -#endif - pTo_OneBitMode = ReservePatchOSLstEntry(); -#if 0 != vMacScreenDepth - if (ColorModeWorks) { - pTo_ColorBitMode = ReservePatchOSLstEntry(); - } -#endif - PatchAnEndOfLst(); - - PatchAReservedOSLstEntry(pTo_VideoType, 0x01 /* sRsrcType */); - - PatchAWord(0x0003); /* catDisplay */ - PatchAWord(0x0001); /* typVideo */ - PatchAWord(0x0001); /* drSwApple */ - PatchAWord(0x0001); /* drHwTFB */ - - PatchAReservedOSLstEntry(pTo_VideoName, 0x02 /* sRsrcName */); - /* - 'Display_Video_Apple_TFB' as ascii c string - (null terminated), and - zero padded to end aligned long. - */ - PatchALong(0x44697370); - PatchALong(0x6C61795F); - PatchALong(0x56696465); - PatchALong(0x6F5F4170); - PatchALong(0x706C655F); - PatchALong(0x54464200); - - PatchAReservedOSLstEntry(pTo_MinorBase, 0x0A /* MinorBaseOS */); - PatchALong(0x00000000); - - PatchAReservedOSLstEntry(pTo_MinorLength, 0x0B /* MinorLength */); - PatchALong(kVidMemRAM_Size); - -#if 0 - PatchAReservedOSLstEntry(pTo_MajorBase, 0x0C /* MinorBaseOS */); - PatchALong(0x00000000); - - PatchAReservedOSLstEntry(pTo_MajorLength, 0x0D /* MinorLength */); - PatchALong(kVidMemRAM_Size); -#endif - - PatchAReservedOSLstEntry(pTo_VidDrvrDir, 0x04 /* sRsrcDrvrDir */); - pTo_sMacOS68020 = ReservePatchOSLstEntry(); - PatchAnEndOfLst(); - - PatchAReservedOSLstEntry(pTo_sMacOS68020, 0x02 /* sMacOS68020 */); - - PatchALong(4 + sizeof(VidDrvr_contents) + 8); - MyMoveBytes((ui3p)VidDrvr_contents, - pPatch, sizeof(VidDrvr_contents)); - pPatch += sizeof(VidDrvr_contents); - PatchAWord(kcom_callcheck); - PatchAWord(kExtnVideo); - PatchALong(kExtn_Block_Base); - - PatchAReservedOSLstEntry(pTo_OneBitMode, 0x80 /* oneBitMode */); - pTo_OneVidParams = ReservePatchOSLstEntry(); - PatchADatLstEntry(0x03 /* mVidParams */, 0x00000001); - PatchADatLstEntry(0x04 /* mDevType */, 0x00000000); - PatchAnEndOfLst(); - - PatchAReservedOSLstEntry(pTo_OneVidParams, 0x01 /* mVidParams */); - PatchALong(0x0000002E); /* physical Block Size */ - PatchALong(0x00000000); /* defmBaseOffset */ - PatchAWord(vMacScreenWidth / 8); - /* (Bounds.R-Bounds.L)*PixelSize/8 */ - PatchAWord(0x0000); /* Bounds.T */ - PatchAWord(0x0000); /* Bounds.L */ - PatchAWord(vMacScreenHeight); /* Bounds.B */ - PatchAWord(vMacScreenWidth); /* Bounds.R */ - PatchAWord(0x0000); /* bmVersion */ - PatchAWord(0x0000); /* packType not used */ - PatchALong(0x00000000); /* packSize not used */ - PatchALong(0x00480000); /* bmHRes */ - PatchALong(0x00480000); /* bmVRes */ - PatchAWord(0x0000); /* bmPixelType */ - PatchAWord(0x0001); /* bmPixelSize */ - PatchAWord(0x0001); /* bmCmpCount */ - PatchAWord(0x0001); /* bmCmpSize */ - PatchALong(0x00000000); /* bmPlaneBytes */ - -#if 0 != vMacScreenDepth - if (ColorModeWorks) { - - PatchAReservedOSLstEntry(pTo_ColorBitMode, 0x81); - pTo_ColorVidParams = ReservePatchOSLstEntry(); - PatchADatLstEntry(0x03 /* mVidParams */, 0x00000001); - PatchADatLstEntry(0x04 /* mDevType */, - (vMacScreenDepth < 4) ? 0x00000000 : 0x00000002); - /* 2 for direct devices, according to Basilisk II */ - PatchAnEndOfLst(); - - PatchAReservedOSLstEntry(pTo_ColorVidParams, 0x01); - PatchALong(0x0000002E); /* physical Block Size */ - PatchALong(0x00000000); /* defmBaseOffset */ - PatchAWord(vMacScreenByteWidth); - PatchAWord(0x0000); /* Bounds.T */ - PatchAWord(0x0000); /* Bounds.L */ - PatchAWord(vMacScreenHeight); /* Bounds.B */ - PatchAWord(vMacScreenWidth); /* Bounds.R */ - PatchAWord(0x0000); /* bmVersion */ - PatchAWord(0x0000); /* packType not used */ - PatchALong(0x00000000); /* packSize not used */ - PatchALong(0x00480000); /* bmHRes */ - PatchALong(0x00480000); /* bmVRes */ - PatchAWord((vMacScreenDepth < 4) ? 0x0000 : 0x0010); - /* bmPixelType */ - PatchAWord(1 << vMacScreenDepth); /* bmPixelSize */ - PatchAWord((vMacScreenDepth < 4) ? 0x0001 : 0x0003); - /* bmCmpCount */ -#if 4 == vMacScreenDepth - PatchAWord(0x0005); /* bmCmpSize */ -#elif 5 == vMacScreenDepth - PatchAWord(0x0008); /* bmCmpSize */ -#else - PatchAWord(1 << vMacScreenDepth); /* bmCmpSize */ -#endif - PatchALong(0x00000000); /* bmPlaneBytes */ - - } -#endif - - UsedSoFar = (pPatch - VidROM) + 20; - if (UsedSoFar > kVidROM_Size) { - ReportAbnormal("kVidROM_Size to small"); - return falseblnr; - } - - for (i = kVidROM_Size - UsedSoFar; --i >= 0; ) { - PatchAByte(0); - } - - pPatch = (kVidROM_Size - 20) + VidROM; - PatchALong((pAt_sRsrcDir - pPatch) & 0x00FFFFFF); - PatchALong(/* 0x0000041E */ kVidROM_Size); - PatchALong(0x00000000); - PatchAByte(0x01); - PatchAByte(0x01); - PatchALong(0x5A932BC7); - PatchAByte(0x00); - PatchAByte(0x0F); - - ChecksumSlotROM(); - -#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4) - CLUT_reds[0] = 0xFFFF; - CLUT_greens[0] = 0xFFFF; - CLUT_blues[0] = 0xFFFF; - CLUT_reds[CLUT_size - 1] = 0; - CLUT_greens[CLUT_size - 1] = 0; - CLUT_blues[CLUT_size - 1] = 0; -#endif - - return trueblnr; -} - -IMPORTPROC Vid_VBLinterrupt_PulseNotify(void); - -GLOBALPROC Vid_Update(void) -{ - if (! Vid_VBLintunenbl) { - Vid_VBLinterrupt = 0; - Vid_VBLinterrupt_PulseNotify(); - } -} - -LOCALFUNC ui4r Vid_GetMode(void) -{ - return -#if 0 != vMacScreenDepth - UseColorMode ? 129 : -#endif - 128; -} - -LOCALFUNC tMacErr Vid_SetMode(ui4r v) -{ -#if 0 == vMacScreenDepth - UnusedParam(v); -#else - if (UseColorMode != ((v != 128) && ColorModeWorks)) { - UseColorMode = ! UseColorMode; - ColorMappingChanged = trueblnr; - } -#endif - return mnvm_noErr; -} - -GLOBALFUNC ui4r Vid_Reset(void) -{ -#if 0 != vMacScreenDepth - UseColorMode = falseblnr; -#endif - return 128; -} - -#define kCmndVideoFeatures 1 -#define kCmndVideoGetIntEnbl 2 -#define kCmndVideoSetIntEnbl 3 -#define kCmndVideoClearInt 4 -#define kCmndVideoStatus 5 -#define kCmndVideoControl 6 - -#define CntrlParam_csCode 0x1A /* control/status code [word] */ -#define CntrlParam_csParam 0x1C /* operation-defined parameters */ - -#define VDPageInfo_csMode 0 -#define VDPageInfo_csPage 6 -#define VDPageInfo_csBaseAddr 8 - -#define VDSetEntryRecord_csTable 0 -#define VDSetEntryRecord_csStart 4 -#define VDSetEntryRecord_csCount 6 - -#define VDGammaRecord_csGTable 0 - -#define VidBaseAddr 0xF9900000 - /* appears to be completely ignored */ - -LOCALVAR blnr UseGrayTones = falseblnr; - -LOCALPROC FillScreenWithGrayPattern(void) -{ - int i; - int j; - ui5b *p1 = (ui5b *)VidMem; - -#if 0 != vMacScreenDepth - if (UseColorMode) { -#if 1 == vMacScreenDepth - ui5b pat = 0xCCCCCCCC; -#elif 2 == vMacScreenDepth - ui5b pat = 0xF0F0F0F0; -#elif 3 == vMacScreenDepth - ui5b pat = 0xFF00FF00; -#elif 4 == vMacScreenDepth - ui5b pat = 0x00007FFF; -#elif 5 == vMacScreenDepth - ui5b pat = 0x00000000; -#endif - for (i = vMacScreenHeight; --i >= 0; ) { - for (j = vMacScreenByteWidth >> 2; --j >= 0; ) { - *p1++ = pat; -#if 5 == vMacScreenDepth - pat = (~ pat) & 0x00FFFFFF; -#endif - } - pat = (~ pat) -#if 4 == vMacScreenDepth - & 0x7FFF7FFF -#elif 5 == vMacScreenDepth - & 0x00FFFFFF -#endif - ; - } - } else -#endif - { - ui5b pat = 0xAAAAAAAA; - - for (i = vMacScreenHeight; --i >= 0; ) { - for (j = vMacScreenMonoByteWidth >> 2; --j >= 0; ) { - *p1++ = pat; - } - pat = ~ pat; - } - } -} - -GLOBALPROC ExtnVideo_Access(CPTR p) -{ - tMacErr result = mnvm_controlErr; - - switch (get_vm_word(p + ExtnDat_commnd)) { - case kCmndVersion: - put_vm_word(p + ExtnDat_version, 1); - result = mnvm_noErr; - break; - case kCmndVideoGetIntEnbl: - put_vm_word(p + 8, - Vid_VBLintunenbl ? 0 : 1); - result = mnvm_noErr; - break; - case kCmndVideoSetIntEnbl: - Vid_VBLintunenbl = - (0 == get_vm_word(p + 8)) - ? 1 : 0; - result = mnvm_noErr; - break; - case kCmndVideoClearInt: - Vid_VBLinterrupt = 1; - result = mnvm_noErr; - break; - case kCmndVideoControl: - { - CPTR CntrlParams = get_vm_long(p + 8); - CPTR csParam = - get_vm_long(CntrlParams + CntrlParam_csParam); - ui4r csCode = - get_vm_word(CntrlParams + CntrlParam_csCode); - - switch (csCode) { - case 0: /* VidReset */ - put_vm_word(csParam + VDPageInfo_csMode, - Vid_GetMode()); - put_vm_word(csParam + VDPageInfo_csPage, 0); - /* page is always 0 */ - put_vm_long(csParam + VDPageInfo_csBaseAddr, - VidBaseAddr); - - result = mnvm_noErr; - break; - case 1: /* KillIO */ - result = mnvm_noErr; - break; - case 2: /* SetVidMode */ - if (0 != get_vm_word( - csParam + VDPageInfo_csPage)) - { - /* return mnvm_controlErr, page must be 0 */ - } else { - result = Vid_SetMode(get_vm_word( - csParam + VDPageInfo_csMode)); - put_vm_long(csParam + VDPageInfo_csBaseAddr, - VidBaseAddr); - } - break; - case 3: /* SetEntries */ -#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4) - if (UseColorMode) { - CPTR csTable = get_vm_long( - csParam + VDSetEntryRecord_csTable); - ui4r csStart = get_vm_word( - csParam + VDSetEntryRecord_csStart); - ui4r csCount = 1 + get_vm_word( - csParam + VDSetEntryRecord_csCount); - if (((ui4r) 0xFFFF) == csStart) { - ReportAbnormal( - "Indexed SetEntries not implemented"); - } else if (csStart + csCount > CLUT_size) { - result = mnvm_paramErr; - } else { - int i; - - for (i = 0; i < csCount; ++i) { - int j = i + csStart; - if (j == 0) { - /* ignore input, leave white */ - } else if (j == CLUT_size - 1) { - /* ignore input, leave black */ - } else { - ui4r r = - get_vm_word(csTable + 2); - ui4r g = - get_vm_word(csTable + 4); - ui4r b = - get_vm_word(csTable + 6); - CLUT_reds[j] = r; - CLUT_greens[j] = g; - CLUT_blues[j] = b; - } - csTable += 8; - } - ColorMappingChanged = trueblnr; - } - } else -#endif - { - /* not implemented */ - } - break; - case 4: /* SetGamma */ - { -#if 0 - CPTR csTable = get_vm_long( - csParam + VDGammaRecord_csGTable); - /* not implemented */ -#endif - } - break; - case 5: /* GrayScreen */ - { -#if 0 - ui4r csPage = get_vm_word( - csParam + VDPageInfo_csPage); - /* not implemented */ -#endif - FillScreenWithGrayPattern(); - result = mnvm_noErr; - } - break; - case 6: /* SetGray */ - { - ui3r csMode = get_vm_byte( - csParam + VDPageInfo_csMode); - /* - "Designing Cards and Drivers" book - says this is a word, but it seems - to be a byte. - */ - - UseGrayTones = (csMode != 0); - result = mnvm_noErr; - } - break; - } - } - break; - case kCmndVideoStatus: - { - CPTR CntrlParams = get_vm_long(p + 8); - CPTR csParam = get_vm_long( - CntrlParams + CntrlParam_csParam); - ui4r csCode = get_vm_word( - CntrlParams + CntrlParam_csCode); - - result = mnvm_statusErr; - switch (csCode) { - case 2: /* GetMode */ - put_vm_word(csParam + VDPageInfo_csMode, - Vid_GetMode()); - put_vm_word(csParam + VDPageInfo_csPage, 0); - /* page is always 0 */ - put_vm_long(csParam + VDPageInfo_csBaseAddr, - VidBaseAddr); - result = mnvm_noErr; - break; - case 3: /* GetEntries */ - { -#if 0 - CPTR csTable = get_vm_long( - csParam + VDSetEntryRecord_csTable); - put_vm_word( - csParam + VDSetEntryRecord_csStart, - csStart); - put_vm_word( - csParam + VDSetEntryRecord_csCount, - csCount); -#endif - ReportAbnormal( - "GetEntries not implemented"); - } - break; - case 4: /* GetPages */ - put_vm_word(csParam + VDPageInfo_csPage, 1); - /* always 1 page */ - result = mnvm_noErr; - break; - case 5: /* GetPageAddr */ - { - ui4r csPage = get_vm_word( - csParam + VDPageInfo_csPage); - if (0 != csPage) { - /* - return mnvm_statusErr, - page must be 0 - */ - } else { - put_vm_long( - csParam + VDPageInfo_csBaseAddr, - VidBaseAddr); - result = mnvm_noErr; - } - } - break; - case 6: /* GetGray */ - { - put_vm_word(csParam + VDPageInfo_csMode, - UseGrayTones ? 0x0100 : 0); - /* - "Designing Cards and Drivers" book - says this is a word, but it seems - to be a byte. - */ - result = mnvm_noErr; - } - break; - } - } - break; - } - - put_vm_word(p + ExtnDat_result, result); -} +/* VIDEMDEV.c Copyright (C) 2008 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* VIDeo card EMulated DEVice Emulation of video card for Macintosh II. Written referring to: Sample firmware code in "Designing Cards and Drivers for Macintosh II and Macintosh SE", Apple Computer, page 8-20. Basilisk II source code, especially slot_rom.cpp */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "ENDIANAC.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "MINEM68K.h" #include "SONYEMDV.h" #endif #include "VIDEMDEV.h" /* ReportAbnormalID unused 0x0A08 - 0x0AFF */ #define VID_dolog (dbglog_HAVE && 0) LOCALVAR const ui3b VidDrvr_contents[] = { 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0xE2, 0x00, 0xEC, 0x00, 0xB6, 0x15, 0x2E, 0x44, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x5F, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x5F, 0x53, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x00, 0x00, 0x24, 0x48, 0x26, 0x49, 0x70, 0x04, 0xA4, 0x40, 0x70, 0x04, 0xA7, 0x22, 0x66, 0x00, 0x00, 0x50, 0x27, 0x48, 0x00, 0x14, 0xA0, 0x29, 0x49, 0xFA, 0x00, 0x4A, 0x70, 0x10, 0xA7, 0x1E, 0x66, 0x00, 0x00, 0x3E, 0x31, 0x7C, 0x00, 0x06, 0x00, 0x04, 0x21, 0x4C, 0x00, 0x08, 0x21, 0x4B, 0x00, 0x0C, 0x70, 0x00, 0x10, 0x2B, 0x00, 0x28, 0xA0, 0x75, 0x66, 0x24, 0x22, 0x6B, 0x00, 0x14, 0x22, 0x51, 0x22, 0x88, 0x3F, 0x3C, 0x00, 0x01, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x03, 0x41, 0xFA, 0x00, 0x9C, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0xDE, 0xFC, 0x00, 0x0A, 0x70, 0x00, 0x60, 0x02, 0x70, 0xE9, 0x4E, 0x75, 0x2F, 0x08, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x04, 0x41, 0xFA, 0x00, 0x7E, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x50, 0x4F, 0x20, 0x29, 0x00, 0x2A, 0xE1, 0x98, 0x02, 0x40, 0x00, 0x0F, 0x20, 0x78, 0x0D, 0x28, 0x4E, 0x90, 0x20, 0x5F, 0x70, 0x01, 0x4E, 0x75, 0x2F, 0x0B, 0x26, 0x69, 0x00, 0x14, 0x42, 0x67, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x03, 0x41, 0xFA, 0x00, 0x4E, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0xDE, 0xFC, 0x00, 0x0A, 0x20, 0x53, 0x20, 0x50, 0xA0, 0x76, 0x20, 0x4B, 0xA0, 0x23, 0x70, 0x00, 0x26, 0x5F, 0x4E, 0x75, 0x2F, 0x08, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x06, 0x60, 0x08, 0x2F, 0x08, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x05, 0x41, 0xFA, 0x00, 0x1E, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, 0x30, 0x1F, 0x20, 0x5F, 0x08, 0x28, 0x00, 0x09, 0x00, 0x06, 0x67, 0x02, 0x4E, 0x75, 0x20, 0x78, 0x08, 0xFC, 0x4E, 0xD0 }; LOCALPROC ChecksumSlotROM(void) { /* Calculate CRC */ /* assuming check sum field initialized to zero */ int i; ui3p p = VidROM; ui5b crc = 0; for (i = kVidROM_Size; --i >= 0; ) { crc = ((crc << 1) | (crc >> 31)) + *p++; } do_put_mem_long(p - 12, crc); } LOCALVAR ui3p pPatch; LOCALPROC PatchAByte(ui3b v) { *pPatch++ = v; } LOCALPROC PatchAWord(ui4r v) { PatchAByte(v >> 8); PatchAByte(v & 0x00FF); } LOCALPROC PatchALong(ui5r v) { PatchAWord(v >> 16); PatchAWord(v & 0x0000FFFF); } #if 0 LOCALPROC PatchAOSLstEntry0(ui3r Id, ui5r Offset) { PatchALong((Id << 24) | (Offset & 0x00FFFFFF)); } #endif LOCALPROC PatchAOSLstEntry(ui3r Id, ui3p Offset) { PatchALong((Id << 24) | ((Offset - pPatch) & 0x00FFFFFF)); } LOCALFUNC ui3p ReservePatchOSLstEntry(void) { ui3p v = pPatch; pPatch += 4; return v; } LOCALPROC PatchAReservedOSLstEntry(ui3p p, ui3r Id) { ui3p pPatchSave = pPatch; pPatch = p; PatchAOSLstEntry(Id, pPatchSave); pPatch = pPatchSave; } LOCALPROC PatchADatLstEntry(ui3r Id, ui5r Data) { PatchALong((Id << 24) | (Data & 0x00FFFFFF)); } LOCALPROC PatchAnEndOfLst(void) { PatchADatLstEntry(0xFF /* endOfList */, 0x00000000); } GLOBALFUNC blnr Vid_Init(void) { int i; ui5r UsedSoFar; ui3p pAt_sRsrcDir; ui3p pTo_sRsrc_Board; ui3p pTo_BoardType; ui3p pTo_BoardName; ui3p pTo_VenderInfo; ui3p pTo_VendorID; ui3p pTo_RevLevel; ui3p pTo_PartNum; ui3p pTo_sRsrc_Video; ui3p pTo_VideoType; ui3p pTo_VideoName; ui3p pTo_MinorBase; ui3p pTo_MinorLength; #if 0 ui3p pTo_MajorBase; ui3p pTo_MajorLength; #endif ui3p pTo_VidDrvrDir; ui3p pTo_sMacOS68020; ui3p pTo_OneBitMode; ui3p pTo_OneVidParams; #if 0 != vMacScreenDepth ui3p pTo_ColorBitMode = nullpr; ui3p pTo_ColorVidParams; #endif pPatch = VidROM; pAt_sRsrcDir = pPatch; pTo_sRsrc_Board = ReservePatchOSLstEntry(); pTo_sRsrc_Video = ReservePatchOSLstEntry(); PatchAnEndOfLst(); PatchAReservedOSLstEntry(pTo_sRsrc_Board, 0x01 /* sRsrc_Board */); pTo_BoardType = ReservePatchOSLstEntry(); pTo_BoardName = ReservePatchOSLstEntry(); PatchADatLstEntry(0x20 /* BoardId */, 0x0000764D); /* 'vM', for Mini vMac */ pTo_VenderInfo = ReservePatchOSLstEntry(); PatchAnEndOfLst(); PatchAReservedOSLstEntry(pTo_BoardType, 0x01 /* sRsrcType */); PatchAWord(0x0001); PatchAWord(0x0000); PatchAWord(0x0000); PatchAWord(0x0000); PatchAReservedOSLstEntry(pTo_BoardName, 0x02 /* sRsrcName */); /* 'Mini vMac video card' as ascii c string (null terminated), and zero padded to end aligned long. */ PatchALong(0x4D696E69); PatchALong(0x20764D61); PatchALong(0x63207669); PatchALong(0x64656F20); PatchALong(0x63617264); PatchALong(0x00000000); PatchAReservedOSLstEntry(pTo_VenderInfo, 0x24 /* vendorInfo */); pTo_VendorID = ReservePatchOSLstEntry(); pTo_RevLevel = ReservePatchOSLstEntry(); pTo_PartNum = ReservePatchOSLstEntry(); PatchAnEndOfLst(); PatchAReservedOSLstEntry(pTo_VendorID, 0x01 /* vendorId */); /* 'Paul C. Pratt' as ascii c string (null terminated), and zero padded to end aligned long. */ PatchALong(0x5061756C); PatchALong(0x20432E20); PatchALong(0x50726174); PatchALong(0x74000000); PatchAReservedOSLstEntry(pTo_RevLevel, 0x03 /* revLevel */); /* '1.0' as ascii c string (null terminated), and zero padded to end aligned long. */ PatchALong(0x312E3000); PatchAReservedOSLstEntry(pTo_PartNum, 0x04 /* partNum */); /* 'TFB-1' as ascii c string (null terminated), and zero padded to end aligned long. */ PatchALong(0x5446422D); PatchALong(0x31000000); PatchAReservedOSLstEntry(pTo_sRsrc_Video, 0x80 /* sRsrc_Video */); pTo_VideoType = ReservePatchOSLstEntry(); pTo_VideoName = ReservePatchOSLstEntry(); pTo_VidDrvrDir = ReservePatchOSLstEntry(); PatchADatLstEntry(0x08 /* sRsrcHWDevId */, 0x00000001); pTo_MinorBase = ReservePatchOSLstEntry(); pTo_MinorLength = ReservePatchOSLstEntry(); #if 0 pTo_MajorBase = ReservePatchOSLstEntry(); pTo_MajorLength = ReservePatchOSLstEntry(); #endif pTo_OneBitMode = ReservePatchOSLstEntry(); #if 0 != vMacScreenDepth if (ColorModeWorks) { pTo_ColorBitMode = ReservePatchOSLstEntry(); } #endif PatchAnEndOfLst(); PatchAReservedOSLstEntry(pTo_VideoType, 0x01 /* sRsrcType */); PatchAWord(0x0003); /* catDisplay */ PatchAWord(0x0001); /* typVideo */ PatchAWord(0x0001); /* drSwApple */ PatchAWord(0x0001); /* drHwTFB */ PatchAReservedOSLstEntry(pTo_VideoName, 0x02 /* sRsrcName */); /* 'Display_Video_Apple_TFB' as ascii c string (null terminated), and zero padded to end aligned long. */ PatchALong(0x44697370); PatchALong(0x6C61795F); PatchALong(0x56696465); PatchALong(0x6F5F4170); PatchALong(0x706C655F); PatchALong(0x54464200); PatchAReservedOSLstEntry(pTo_MinorBase, 0x0A /* MinorBaseOS */); PatchALong(0x00000000); PatchAReservedOSLstEntry(pTo_MinorLength, 0x0B /* MinorLength */); PatchALong(kVidMemRAM_Size); #if 0 PatchAReservedOSLstEntry(pTo_MajorBase, 0x0C /* MinorBaseOS */); PatchALong(0x00000000); PatchAReservedOSLstEntry(pTo_MajorLength, 0x0D /* MinorLength */); PatchALong(kVidMemRAM_Size); #endif PatchAReservedOSLstEntry(pTo_VidDrvrDir, 0x04 /* sRsrcDrvrDir */); pTo_sMacOS68020 = ReservePatchOSLstEntry(); PatchAnEndOfLst(); PatchAReservedOSLstEntry(pTo_sMacOS68020, 0x02 /* sMacOS68020 */); PatchALong(4 + sizeof(VidDrvr_contents) + 8); MyMoveBytes((ui3p)VidDrvr_contents, pPatch, sizeof(VidDrvr_contents)); pPatch += sizeof(VidDrvr_contents); PatchAWord(kcom_callcheck); PatchAWord(kExtnVideo); PatchALong(kExtn_Block_Base); PatchAReservedOSLstEntry(pTo_OneBitMode, 0x80 /* oneBitMode */); pTo_OneVidParams = ReservePatchOSLstEntry(); PatchADatLstEntry(0x03 /* mVidParams */, 0x00000001); PatchADatLstEntry(0x04 /* mDevType */, 0x00000000); PatchAnEndOfLst(); PatchAReservedOSLstEntry(pTo_OneVidParams, 0x01 /* mVidParams */); PatchALong(0x0000002E); /* physical Block Size */ PatchALong(0x00000000); /* defmBaseOffset */ PatchAWord(vMacScreenWidth / 8); /* (Bounds.R-Bounds.L)*PixelSize/8 */ PatchAWord(0x0000); /* Bounds.T */ PatchAWord(0x0000); /* Bounds.L */ PatchAWord(vMacScreenHeight); /* Bounds.B */ PatchAWord(vMacScreenWidth); /* Bounds.R */ PatchAWord(0x0000); /* bmVersion */ PatchAWord(0x0000); /* packType not used */ PatchALong(0x00000000); /* packSize not used */ PatchALong(0x00480000); /* bmHRes */ PatchALong(0x00480000); /* bmVRes */ PatchAWord(0x0000); /* bmPixelType */ PatchAWord(0x0001); /* bmPixelSize */ PatchAWord(0x0001); /* bmCmpCount */ PatchAWord(0x0001); /* bmCmpSize */ PatchALong(0x00000000); /* bmPlaneBytes */ #if 0 != vMacScreenDepth if (ColorModeWorks) { PatchAReservedOSLstEntry(pTo_ColorBitMode, 0x81); pTo_ColorVidParams = ReservePatchOSLstEntry(); PatchADatLstEntry(0x03 /* mVidParams */, 0x00000001); PatchADatLstEntry(0x04 /* mDevType */, (vMacScreenDepth < 4) ? 0x00000000 : 0x00000002); /* 2 for direct devices, according to Basilisk II */ PatchAnEndOfLst(); PatchAReservedOSLstEntry(pTo_ColorVidParams, 0x01); PatchALong(0x0000002E); /* physical Block Size */ PatchALong(0x00000000); /* defmBaseOffset */ PatchAWord(vMacScreenByteWidth); PatchAWord(0x0000); /* Bounds.T */ PatchAWord(0x0000); /* Bounds.L */ PatchAWord(vMacScreenHeight); /* Bounds.B */ PatchAWord(vMacScreenWidth); /* Bounds.R */ PatchAWord(0x0000); /* bmVersion */ PatchAWord(0x0000); /* packType not used */ PatchALong(0x00000000); /* packSize not used */ PatchALong(0x00480000); /* bmHRes */ PatchALong(0x00480000); /* bmVRes */ PatchAWord((vMacScreenDepth < 4) ? 0x0000 : 0x0010); /* bmPixelType */ PatchAWord(1 << vMacScreenDepth); /* bmPixelSize */ PatchAWord((vMacScreenDepth < 4) ? 0x0001 : 0x0003); /* bmCmpCount */ #if 4 == vMacScreenDepth PatchAWord(0x0005); /* bmCmpSize */ #elif 5 == vMacScreenDepth PatchAWord(0x0008); /* bmCmpSize */ #else PatchAWord(1 << vMacScreenDepth); /* bmCmpSize */ #endif PatchALong(0x00000000); /* bmPlaneBytes */ } #endif UsedSoFar = (pPatch - VidROM) + 20; if (UsedSoFar > kVidROM_Size) { ReportAbnormalID(0x0A01, "kVidROM_Size to small"); return falseblnr; } for (i = kVidROM_Size - UsedSoFar; --i >= 0; ) { PatchAByte(0); } pPatch = (kVidROM_Size - 20) + VidROM; PatchALong((pAt_sRsrcDir - pPatch) & 0x00FFFFFF); PatchALong(/* 0x0000041E */ kVidROM_Size); PatchALong(0x00000000); PatchAByte(0x01); PatchAByte(0x01); PatchALong(0x5A932BC7); PatchAByte(0x00); PatchAByte(0x0F); ChecksumSlotROM(); #if (0 != vMacScreenDepth) && (vMacScreenDepth < 4) CLUT_reds[0] = 0xFFFF; CLUT_greens[0] = 0xFFFF; CLUT_blues[0] = 0xFFFF; CLUT_reds[CLUT_size - 1] = 0; CLUT_greens[CLUT_size - 1] = 0; CLUT_blues[CLUT_size - 1] = 0; #endif return trueblnr; } IMPORTPROC Vid_VBLinterrupt_PulseNotify(void); GLOBALPROC Vid_Update(void) { if (! Vid_VBLintunenbl) { Vid_VBLinterrupt = 0; Vid_VBLinterrupt_PulseNotify(); } } LOCALFUNC ui4r Vid_GetMode(void) { return #if 0 != vMacScreenDepth UseColorMode ? 129 : #endif 128; } LOCALFUNC tMacErr Vid_SetMode(ui4r v) { #if 0 == vMacScreenDepth UnusedParam(v); #else if (UseColorMode != ((v != 128) && ColorModeWorks)) { UseColorMode = ! UseColorMode; ColorMappingChanged = trueblnr; } #endif return mnvm_noErr; } GLOBALFUNC ui4r Vid_Reset(void) { #if 0 != vMacScreenDepth UseColorMode = falseblnr; #endif return 128; } #define kCmndVideoFeatures 1 #define kCmndVideoGetIntEnbl 2 #define kCmndVideoSetIntEnbl 3 #define kCmndVideoClearInt 4 #define kCmndVideoStatus 5 #define kCmndVideoControl 6 #define CntrlParam_csCode 0x1A /* control/status code [word] */ #define CntrlParam_csParam 0x1C /* operation-defined parameters */ #define VDPageInfo_csMode 0 #define VDPageInfo_csData 2 #define VDPageInfo_csPage 6 #define VDPageInfo_csBaseAddr 8 #define VDSetEntryRecord_csTable 0 #define VDSetEntryRecord_csStart 4 #define VDSetEntryRecord_csCount 6 #define VDGammaRecord_csGTable 0 #define VidBaseAddr 0xF9900000 /* appears to be completely ignored */ LOCALVAR blnr UseGrayTones = falseblnr; LOCALPROC FillScreenWithGrayPattern(void) { int i; int j; ui5b *p1 = (ui5b *)VidMem; #if 0 != vMacScreenDepth if (UseColorMode) { #if 1 == vMacScreenDepth ui5b pat = 0xCCCCCCCC; #elif 2 == vMacScreenDepth ui5b pat = 0xF0F0F0F0; #elif 3 == vMacScreenDepth ui5b pat = 0xFF00FF00; #elif 4 == vMacScreenDepth ui5b pat = 0x00007FFF; #elif 5 == vMacScreenDepth ui5b pat = 0x00000000; #endif for (i = vMacScreenHeight; --i >= 0; ) { for (j = vMacScreenByteWidth >> 2; --j >= 0; ) { *p1++ = pat; #if 5 == vMacScreenDepth pat = (~ pat) & 0x00FFFFFF; #endif } pat = (~ pat) #if 4 == vMacScreenDepth & 0x7FFF7FFF #elif 5 == vMacScreenDepth & 0x00FFFFFF #endif ; } } else #endif { ui5b pat = 0xAAAAAAAA; for (i = vMacScreenHeight; --i >= 0; ) { for (j = vMacScreenMonoByteWidth >> 2; --j >= 0; ) { *p1++ = pat; } pat = ~ pat; } } } GLOBALPROC ExtnVideo_Access(CPTR p) { tMacErr result = mnvm_controlErr; switch (get_vm_word(p + ExtnDat_commnd)) { case kCmndVersion: #if VID_dolog dbglog_WriteNote("Video_Access kCmndVersion"); #endif put_vm_word(p + ExtnDat_version, 1); result = mnvm_noErr; break; case kCmndVideoGetIntEnbl: #if VID_dolog dbglog_WriteNote("Video_Access kCmndVideoGetIntEnbl"); #endif put_vm_word(p + 8, Vid_VBLintunenbl ? 0 : 1); result = mnvm_noErr; break; case kCmndVideoSetIntEnbl: #if VID_dolog dbglog_WriteNote("Video_Access kCmndVideoSetIntEnbl"); #endif Vid_VBLintunenbl = (0 == get_vm_word(p + 8)) ? 1 : 0; result = mnvm_noErr; break; case kCmndVideoClearInt: #if VID_dolog && 0 /* frequent */ dbglog_WriteNote("Video_Access kCmndVideoClearInt"); #endif Vid_VBLinterrupt = 1; result = mnvm_noErr; break; case kCmndVideoControl: { CPTR CntrlParams = get_vm_long(p + 8); CPTR csParam = get_vm_long(CntrlParams + CntrlParam_csParam); ui4r csCode = get_vm_word(CntrlParams + CntrlParam_csCode); switch (csCode) { case 0: /* VidReset */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoControl, VidReset"); #endif put_vm_word(csParam + VDPageInfo_csMode, Vid_GetMode()); put_vm_word(csParam + VDPageInfo_csPage, 0); /* page is always 0 */ put_vm_long(csParam + VDPageInfo_csBaseAddr, VidBaseAddr); result = mnvm_noErr; break; case 1: /* KillIO */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoControl, KillIO"); #endif result = mnvm_noErr; break; case 2: /* SetVidMode */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoControl, " "SetVidMode"); #endif if (0 != get_vm_word( csParam + VDPageInfo_csPage)) { /* return mnvm_controlErr, page must be 0 */ ReportAbnormalID(0x0A02, "SetVidMode not page 0"); } else { result = Vid_SetMode(get_vm_word( csParam + VDPageInfo_csMode)); put_vm_long(csParam + VDPageInfo_csBaseAddr, VidBaseAddr); } break; case 3: /* SetEntries */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoControl, " "SetEntries"); #endif #if (0 != vMacScreenDepth) && (vMacScreenDepth < 4) if (UseColorMode) { CPTR csTable = get_vm_long( csParam + VDSetEntryRecord_csTable); ui4r csStart = get_vm_word( csParam + VDSetEntryRecord_csStart); ui4r csCount = 1 + get_vm_word( csParam + VDSetEntryRecord_csCount); if (((ui4r) 0xFFFF) == csStart) { int i; result = mnvm_noErr; for (i = 0; i < csCount; ++i) { ui4r j = get_vm_word(csTable + 0); if (j == 0) { /* ignore input, leave white */ } else if (j == CLUT_size - 1) { /* ignore input, leave black */ } else if (j >= CLUT_size) { /* out of range */ result = mnvm_paramErr; } else { ui4r r = get_vm_word(csTable + 2); ui4r g = get_vm_word(csTable + 4); ui4r b = get_vm_word(csTable + 6); CLUT_reds[j] = r; CLUT_greens[j] = g; CLUT_blues[j] = b; } csTable += 8; } ColorMappingChanged = trueblnr; } else if (csStart + csCount < csStart) { /* overflow */ result = mnvm_paramErr; } else if (csStart + csCount > CLUT_size) { result = mnvm_paramErr; } else { int i; for (i = 0; i < csCount; ++i) { int j = i + csStart; if (j == 0) { /* ignore input, leave white */ } else if (j == CLUT_size - 1) { /* ignore input, leave black */ } else { ui4r r = get_vm_word(csTable + 2); ui4r g = get_vm_word(csTable + 4); ui4r b = get_vm_word(csTable + 6); CLUT_reds[j] = r; CLUT_greens[j] = g; CLUT_blues[j] = b; } csTable += 8; } ColorMappingChanged = trueblnr; result = mnvm_noErr; } } else #endif { /* not implemented */ } break; case 4: /* SetGamma */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoControl, SetGamma"); #endif { #if 0 CPTR csTable = get_vm_long( csParam + VDGammaRecord_csGTable); /* not implemented */ #endif } #if 0 ReportAbnormalID(0x0A03, "Video_Access SetGamma not implemented"); #else result = mnvm_noErr; #endif break; case 5: /* GrayScreen */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoControl, " "GrayScreen"); #endif { #if 0 ui4r csPage = get_vm_word( csParam + VDPageInfo_csPage); /* not implemented */ #endif FillScreenWithGrayPattern(); result = mnvm_noErr; } break; case 6: /* SetGray */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoControl, SetGray"); #endif { ui3r csMode = get_vm_byte( csParam + VDPageInfo_csMode); /* "Designing Cards and Drivers" book says this is a word, but it seems to be a byte. */ UseGrayTones = (csMode != 0); result = mnvm_noErr; } break; case 9: /* SetDefaultMode */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoControl, " "SetDefaultMode"); #endif /* not handled yet */ /* seen when close Monitors control panel in system 7.5.5 */ break; case 16: /* SavePreferredConfiguration */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoControl, " "SavePreferredConfiguration"); #endif /* not handled yet */ /* seen when close Monitors control panel in system 7.5.5 */ break; default: ReportAbnormalID(0x0A04, "kCmndVideoControl, unknown csCode"); #if dbglog_HAVE dbglog_writelnNum("csCode", csCode); #endif break; } } break; case kCmndVideoStatus: { CPTR CntrlParams = get_vm_long(p + 8); CPTR csParam = get_vm_long( CntrlParams + CntrlParam_csParam); ui4r csCode = get_vm_word( CntrlParams + CntrlParam_csCode); result = mnvm_statusErr; switch (csCode) { case 2: /* GetMode */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoStatus, GetMode"); #endif put_vm_word(csParam + VDPageInfo_csMode, Vid_GetMode()); put_vm_word(csParam + VDPageInfo_csPage, 0); /* page is always 0 */ put_vm_long(csParam + VDPageInfo_csBaseAddr, VidBaseAddr); result = mnvm_noErr; break; case 3: /* GetEntries */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoStatus, " "GetEntries"); #endif { #if 0 CPTR csTable = get_vm_long( csParam + VDSetEntryRecord_csTable); put_vm_word( csParam + VDSetEntryRecord_csStart, csStart); put_vm_word( csParam + VDSetEntryRecord_csCount, csCount); #endif ReportAbnormalID(0x0A05, "GetEntries not implemented"); } break; case 4: /* GetPages */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoStatus, GetPages"); #endif put_vm_word(csParam + VDPageInfo_csPage, 1); /* always 1 page */ result = mnvm_noErr; break; case 5: /* GetPageAddr */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoStatus," " GetPageAddr"); #endif { ui4r csPage = get_vm_word( csParam + VDPageInfo_csPage); if (0 != csPage) { /* return mnvm_statusErr, page must be 0 */ } else { put_vm_long( csParam + VDPageInfo_csBaseAddr, VidBaseAddr); result = mnvm_noErr; } } break; case 6: /* GetGray */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoStatus, GetGray"); #endif put_vm_word(csParam + VDPageInfo_csMode, UseGrayTones ? 0x0100 : 0); /* "Designing Cards and Drivers" book says this is a word, but it seems to be a byte. */ result = mnvm_noErr; break; case 8: /* GetGamma */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoStatus, " "GetGamma"); #endif /* not handled yet */ /* seen when close Monitors control panel in system 7.5.5 */ break; case 9: /* GetDefaultMode */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoStatus, " "GetDefaultMode"); #endif /* not handled yet */ /* seen in System 7.5.5 boot */ break; case 10: /* GetCurrentMode */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoStatus, " "GetCurrentMode"); #endif #if 0 put_vm_word(csParam + VDPageInfo_csMode, Vid_GetMode()); put_vm_long(csParam + VDPageInfo_csData, 0); /* what is this ? */ put_vm_word(csParam + VDPageInfo_csPage, 0); /* page is always 0 */ put_vm_long(csParam + VDPageInfo_csBaseAddr, VidBaseAddr); result = mnvm_noErr; #endif break; case 12: /* GetConnection */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoStatus, " "GetConnection"); #endif /* not handled yet */ /* seen in System 7.5.5 boot */ break; case 13: /* GetCurrentMode */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoStatus, " "GetCurrentMode"); #endif /* not handled yet */ /* seen in System 7.5.5 boot */ break; case 14: /* GetModeBaseAddress */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoStatus, " "GetModeBaseAddress"); #endif /* not handled yet */ /* seen in System 7.5.5 Monitors control panel */ break; case 16: /* GetPreferredConfiguration */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoStatus, " "GetPreferredConfiguration"); #endif /* not handled yet */ /* seen in System 7.5.5 boot */ break; case 17: /* GetNextResolution */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoStatus, " "GetNextResolution"); #endif /* not handled yet */ /* seen in System 7.5.5 monitors control panel option button */ break; case 18: /* GetVideoParameters */ #if VID_dolog dbglog_WriteNote( "Video_Access kCmndVideoStatus, " "GetVideoParameters"); #endif /* not handled yet */ /* seen in System 7.5.5 boot */ break; default: ReportAbnormalID(0x0A06, "Video_Access kCmndVideoStatus, " "unknown csCode"); #if dbglog_HAVE dbglog_writelnNum("csCode", csCode); #endif break; } } break; default: ReportAbnormalID(0x0A07, "Video_Access, unknown commnd"); break; } put_vm_word(p + ExtnDat_result, result); } \ No newline at end of file diff --git a/Mini vMac/mnvm_core/VIDEMDEV.h b/Mini vMac/mnvm_core/VIDEMDEV.h index 4f574eb..5b6c685 100755 --- a/Mini vMac/mnvm_core/VIDEMDEV.h +++ b/Mini vMac/mnvm_core/VIDEMDEV.h @@ -1,27 +1 @@ -/* - VIDEMDEV.h - - Copyright (C) 2008 Paul C. Pratt - - You can redistribute this file and/or modify it under the terms - of version 2 of the GNU General Public License as published by - the Free Software Foundation. You should have received a copy - of the license along with this file; see the file COPYING. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - license for more details. -*/ - -#ifdef VIDEMDEV_H -#error "header already included" -#else -#define VIDEMDEV_H -#endif - -EXPORTFUNC blnr Vid_Init(void); -EXPORTFUNC ui4r Vid_Reset(void); -EXPORTPROC Vid_Update(void); - -EXPORTPROC ExtnVideo_Access(CPTR p); +/* VIDEMDEV.h Copyright (C) 2008 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #ifdef VIDEMDEV_H #error "header already included" #else #define VIDEMDEV_H #endif EXPORTFUNC blnr Vid_Init(void); EXPORTFUNC ui4r Vid_Reset(void); EXPORTPROC Vid_Update(void); EXPORTPROC ExtnVideo_Access(CPTR p); \ No newline at end of file