uint16_t HandleZone(uint16_t trap) { // FUNCTION HandleZone (h: Handle): THz; /* * on entry: * A0 Handle whose zone is to be found * * on exit: * A0 Pointer to handle’s heap zone * D0 Result code * */ uint32_t h = cpuGetAReg(0); Log("%04x HandleZone(%08x)\n", trap, h); if (HandleMap.find(h) == HandleMap.end()) { cpuSetAReg(0, 0); return SetMemError(MacOS::memWZErr); } cpuSetAReg(0, 0); return SetMemError(0); }
static void cpuFrameGroup1(UWO vector_offset, ULO pcPtr) { // save PC cpuSetAReg(7, cpuGetAReg(7) - 4); memoryWriteLong(pcPtr, cpuGetAReg(7)); // save SR cpuSetAReg(7, cpuGetAReg(7) - 2); memoryWriteWord((UWO)cpuGetSR(), cpuGetAReg(7)); }
static void cpuFrame4Words(UWO frame_code, UWO vector_offset, ULO pc) { // save vector_offset word cpuSetAReg(7, cpuGetAReg(7) - 2); memoryWriteWord(frame_code | vector_offset, cpuGetAReg(7)); // save PC cpuSetAReg(7, cpuGetAReg(7) - 4); memoryWriteLong(pc, cpuGetAReg(7)); // save SR cpuSetAReg(7, cpuGetAReg(7) - 2); memoryWriteWord((UWO)cpuGetSR(), cpuGetAReg(7)); }
static void cpuFrame2(UWO vector_offset, ULO pc) { // save inst address cpuSetAReg(7, cpuGetAReg(7) - 4); memoryWriteLong(cpuGetOriginalPC(), cpuGetAReg(7)); cpuFrame4Words(0x2000, vector_offset, pc); }
void cpuSetUpInterrupt(ULO new_interrupt_level) { UWO vector_offset = (UWO) (0x60 + new_interrupt_level*4); ULO vector_address = memoryReadLong(cpuGetVbr() + vector_offset); cpuActivateSSP(); // Switch to using ssp or msp. Loads a7 and preserves usp if we came from user-mode. cpuStackFrameGenerate(vector_offset, cpuGetPC()); // This will end up on msp if master is enabled, or on the ssp/isp if not. cpuSetSR(cpuGetSR() & 0x38ff); // Clear interrupt level cpuSetSR(cpuGetSR() | 0x2000); // Set supervisor mode cpuSetSR(cpuGetSR() | (UWO)(new_interrupt_level << 8)); // Set interrupt level #ifdef CPU_INSTRUCTION_LOGGING cpuCallInterruptLoggingFunc(new_interrupt_level, vector_address); #endif if (cpuGetModelMajor() >= 2 && cpuGetModelMajor() < 6) { if (cpuGetFlagMaster()) { // If the cpu was in master mode, preserve msp, and switch to using ssp (isp) in a7. ULO oldA7 = cpuGetAReg(7); cpuSetMspDirect(oldA7); cpuSetAReg(7, cpuGetSspDirect()); cpuFrame1(vector_offset, cpuGetPC()); // Make the throwaway frame on ssp/isp cpuSetSR(cpuGetSR() & 0xefff); // Clear master bit } } cpuInitializeFromNewPC(vector_address); cpuSetStop(FALSE); cpuSetRaiseInterrupt(FALSE); }
uint16_t Gestalt(uint16_t trap) { // FUNCTION Gestalt (selector: OSType; VAR response: LongInt): OSErr; /* * on entry: * D0 Selector code * * on exit: * A0 Response * D0 Result code * */ uint32_t selector = cpuGetDReg(0); uint32_t response; Log("%04x Gestalt('%s')\n", trap, ToolBox::TypeToString(selector).c_str()); auto iter = GestaltMap.find(selector); if (iter == GestaltMap.end()) return gestaltUndefSelectorErr; response = iter->second; cpuSetAReg(0, response); return 0; }
uint16_t NewHandle(uint16_t trap) { /* * on entry: * D0 Number of logical bytes requested * * on exit: * A0 Address of the new handle or NIL * D0 Result code * */ uint32_t hh = 0; uint16_t error; bool clear = trap & (1 << 9); //bool sys = trap & (1 << 10); uint32_t size = cpuGetDReg(0); Log("%04x NewHandle(%08x)\n", trap, size); error = Native::NewHandle(size, clear, hh); cpuSetAReg(0, hh); return error; }
uint16_t NewPtr(uint16_t trap) { /* * on entry: * D0 Number of logical bytes requested * * on exit: * A0 Address of the new block or NIL * D0 Result code * */ bool clear = trap & (1 << 9); //bool sys = trap & (1 << 10); uint32_t size = cpuGetDReg(0); Log("%04x NewPtr(%08x)\n", trap, size); // todo -- separate pools for sys vs non-sys? // todo -- NewPtr(0) -- null or empty ptr? uint32_t mcptr; uint16_t error; error = Native::NewPtr(size, clear, mcptr); cpuSetAReg(0, mcptr); return error; //SetMemError(error); }
uint16_t HandToHand(uint16_t trap) { /* * on entry: * A0 source Handle * * on exit: * A0 destination Handle * D0 Result code * */ uint32_t srcHandle = cpuGetAReg(0); Log("%04x HandToHand(%08x)\n", trap, srcHandle); auto iter = HandleMap.find(srcHandle); if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr); auto const info = iter->second; uint32_t destHandle; uint32_t destPtr; uint32_t d0 = Native::NewHandle(info.size, false, destHandle, destPtr); if (d0 == 0) { std::memmove(memoryPointer(destPtr), memoryPointer(info.address), info.size); } cpuSetAReg(0, destHandle); return d0; // SetMemError called by Native::NewHandle. }
uint16_t PtrToHand(uint16_t trap) { /* * on entry: * A0 source Pointer * D0 size * * on exit: * A0 destination pointer * D0 Result code * */ uint32_t mcptr = cpuGetAReg(0); uint32_t size = cpuGetDReg(0); Log("%04x PtrToHand(%08x, %08x)\n", trap, mcptr, size); uint32_t destHandle; uint32_t destPtr; uint32_t d0 = Native::NewHandle(size, false, destHandle, destPtr); if (d0 == 0) { std::memmove(memoryPointer(destPtr), memoryPointer(mcptr), size); } cpuSetAReg(0, destHandle); return d0; // SetMemError called by Native::NewHandle. }
static void cpuFrameGroup2(UWO vector_offset, ULO pcPtr) { // save PC cpuSetAReg(7, cpuGetAReg(7) - 4); memoryWriteLong(pcPtr, cpuGetAReg(7)); // save SR cpuSetAReg(7, cpuGetAReg(7) - 2); memoryWriteWord((UWO)cpuGetSR(), cpuGetAReg(7)); // fault address, skip ireg cpuSetAReg(7, cpuGetAReg(7) - 6); memoryWriteLong(memory_fault_address, cpuGetAReg(7)); cpuSetAReg(7, cpuGetAReg(7) - 2); memoryWriteLong(memory_fault_read << 4, cpuGetAReg(7)); }
/// <summary> /// Sets the interrupt stack pointer. ssp is used as isp. /// </summary> void cpuSetIspAutoMap(ULO new_isp) { if (cpuGetFlagSupervisor() && !cpuGetFlagMaster()) { cpuSetAReg(7, new_isp); } else { cpuSetSspDirect(new_isp); } }
uint16_t SwapDataCache() { // FUNCTION SwapDataCache (cacheEnable: Boolean): Boolean; // boolean value sent/returned via a0. // c.f. mpw DumpObj -m SWAPDATACACHE Interface.o uint16_t cacheEnable = cpuGetAReg(0) & 0xff; Log(" SwapDataCache(%02x)\n", cacheEnable); cpuSetAReg(0, 0); return 0; }
uint32_t PurgeSpace(uint16_t trap) { // PROCEDURE PurgeSpace (VAR total: LongInt; VAR contig: LongInt); /* * Registers on exit: * A0 Maximum number of contiguous bytes after purge * D0 Total free memory after purge */ Log("%04x PurgeSpace()\n", trap); SetMemError(0); cpuSetAReg(0, mplite_maxmem(&pool)); return mplite_freemem(&pool); }
uint16_t PtrAndHand(uint16_t trap) { // FUNCTION PtrAndHand (pntr: Ptr; hndl: Handle; size: LongInt): OSErr; /* * on entry: * A0 source Pointer * A1 dest Handle * D0 number of bytes to concatenate * * on exit: * A0 destination Handle * D0 Result code * */ uint32_t ptr = cpuGetAReg(0); uint32_t handle = cpuGetAReg(1); uint32_t size = cpuGetDReg(0); Log("%04x PtrAndHand(%08x, %08x, %08x)\n", trap, ptr, handle, size); cpuSetAReg(0, handle); uint32_t oldSize = 0; uint32_t d0; d0 = Native::GetHandleSize(handle, oldSize); if (d0) return d0; if ((uint64_t)oldSize + (uint64_t)size > UINT32_MAX) return SetMemError(MacOS::memFullErr); d0 = Native::SetHandleSize(handle, oldSize + size); if (d0) return d0; auto iter = HandleMap.find(handle); if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr); auto const info = iter->second; std::memmove(memoryPointer(info.address + oldSize), memoryPointer(ptr), size); return SetMemError(0); }
uint16_t GetZone(uint16_t trap) { // FUNCTION GetZone: THz; /* * on entry: * * on exit: * A0 Pointer to current heap zone * D0 Result code */ Log("%04x GetZone()\n", trap); cpuSetAReg(0, 0); return 0; }
uint32_t RecoverHandle(uint16_t trap) { // FUNCTION RecoverHandle (p: Ptr): Handle; /* * on entry: * A0 Master pointer * * on exit: * A0 Handle to master pointer’s relocatable block * D0 Unchanged * */ uint32_t p = cpuGetAReg(0); uint32_t hh = 0; Log("%04x RecoverHandle(%08x)\n", trap, p); uint16_t error = MacOS::memBCErr; for (const auto kv : HandleMap) { const HandleInfo &info = kv.second; if (!info.address) continue; uint32_t begin = info.address; uint32_t end = info.address + info.size; if (!info.size) end++; if (p >= begin && p < end) { hh = kv.first; error = MacOS::noErr; break; } } SetMemError(error); cpuSetAReg(0, hh); // return d0 register unchanged. return cpuGetDReg(0); }
ULO cpuActivateSSP(void) { ULO currentSP = cpuGetAReg(7); // check supervisor bit number (bit 13) within the system byte of the status register if (!cpuGetFlagSupervisor()) { // we are in user mode, thus save user stack pointer (USP) cpuSetUspDirect(currentSP); currentSP = cpuGetSspDirect(); if (cpuGetModelMajor() >= 2) { if (cpuGetFlagMaster()) { currentSP = cpuGetMspDirect(); } } cpuSetAReg(7, currentSP); } return currentSP; }
static void cpuFrame8(UWO vector_offset, ULO pc) { cpuSetAReg(7, cpuGetAReg(7) - 50); cpuFrame4Words(0x8000, vector_offset, pc); }
static void cpuFrameA(UWO vector_offset, ULO pc) { // save vector_offset offset cpuSetAReg(7, cpuGetAReg(7) - 24); cpuFrame4Words(0xa000, vector_offset, pc); }