/*=========================================================================*/ /* Fellow */ /* 68000 stack frame generation */ /* */ /* Author: Petter Schau */ /* */ /* Copyright (C) 1991, 1992, 1996 Free Software Foundation, Inc. */ /* */ /* 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, or (at your option) */ /* any later version. */ /* */ /* This program 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 */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software Foundation, */ /* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*=========================================================================*/ #include "defs.h" #include "CpuModule_Memory.h" #include "CpuModule.h" #include "CpuModule_Internal.h" /* Exception stack frame jmptables */ typedef void(*cpuStackFrameGenFunc)(uint16_t, uint32_t); static cpuStackFrameGenFunc cpu_stack_frame_gen_func[64]; static void cpuSetStackFrameGenFunc(uint32_t vector_no, cpuStackFrameGenFunc func) { cpu_stack_frame_gen_func[vector_no] = func; } /*======================================================================== Group 1 Frame format 000: All, except bus and address error ========================================================================*/ static void cpuFrameGroup1(uint16_t vector_offset, uint32_t pcPtr) { // save PC cpuSetAReg(7, cpuGetAReg(7) - 4); memoryWriteLong(pcPtr, cpuGetAReg(7)); // save SR cpuSetAReg(7, cpuGetAReg(7) - 2); memoryWriteWord((uint16_t)cpuGetSR(), cpuGetAReg(7)); } /*======================================================================== Group 2 Frame format 000: Bus and address error memory_fault_address contains the violating address memory_fault_read is TRUE if the access was a read ========================================================================*/ static void cpuFrameGroup2(uint16_t vector_offset, uint32_t pcPtr) { // save PC cpuSetAReg(7, cpuGetAReg(7) - 4); memoryWriteLong(pcPtr, cpuGetAReg(7)); // save SR cpuSetAReg(7, cpuGetAReg(7) - 2); memoryWriteWord((uint16_t)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)); } static void cpuFrame4Words(uint16_t frame_code, uint16_t vector_offset, uint32_t 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((uint16_t)cpuGetSR(), cpuGetAReg(7)); } /*======================================================================== Frame format $0, four word frame Stack words: ------------ SR PCHI PCLO 0000 Vector offset (4 upper bits are frame no., rest is vector offset) 010: All, except bus and address errors 020: Irq, Format error, Trap #N, Illegal inst., A-line, F-line, Priv. violation, copr preinst 030: Same as for 020 ========================================================================*/ static void cpuFrame0(uint16_t vector_offset, uint32_t pc) { cpuFrame4Words(0x0000, vector_offset, pc); } /*======================================================================== Frame format $1, 4 word throwaway frame Stack words: ------------ SR PCHI PCLO 0000 Vector offset (4 upper bits are frame no., rest is Vvctor offset) 020: Irq, second frame created 030: Same as for 020 040: Same as for 020 ========================================================================*/ void cpuFrame1(uint16_t vector_offset, uint32_t pc) { cpuFrame4Words(0x1000, vector_offset, pc); } /*======================================================================== Frame format $2 020: chk, chk2, cpTrapcc, trapcc, trapv, trace, zero divide, MMU config, copr postinst 030: Same as for 020 040: chk, chk2, FTrapcc, trapcc, trapv, trace, zero divide, address error, Unimplemented FPU inst. 060: Same as for 040 ========================================================================*/ static void cpuFrame2(uint16_t vector_offset, uint32_t pc) { // save inst address cpuSetAReg(7, cpuGetAReg(7) - 4); memoryWriteLong(cpuGetOriginalPC(), cpuGetAReg(7)); cpuFrame4Words(0x2000, vector_offset, pc); } /*======================================================================== Frame format $8 010: Bus and address error ========================================================================*/ static void cpuFrame8(uint16_t vector_offset, uint32_t pc) { cpuSetAReg(7, cpuGetAReg(7) - 50); cpuFrame4Words(0x8000, vector_offset, pc); } /*======================================================================== Frame format $A 020: Address or bus-error on instruction boundrary 030: Same as for 020 Will not set any values beyond the format/offset word Fellow will always generate this frame for bus/address errors ========================================================================*/ static void cpuFrameA(uint16_t vector_offset, uint32_t pc) { // save vector_offset offset cpuSetAReg(7, cpuGetAReg(7) - 24); cpuFrame4Words(0xa000, vector_offset, pc); } void cpuStackFrameGenerate(uint16_t vector_offset, uint32_t pc) { cpu_stack_frame_gen_func[vector_offset>>2](vector_offset, pc); } /*==================================*/ /* Initialize stack frame jmptables */ /*==================================*/ static void cpuStackFrameInitSetDefaultFunc(cpuStackFrameGenFunc default_func) { for (uint32_t i = 0; i < 64; i++) cpuSetStackFrameGenFunc(i, default_func); } static void cpuStackFrameInit000(void) { cpuStackFrameInitSetDefaultFunc(cpuFrameGroup1); cpuSetStackFrameGenFunc(2, cpuFrameGroup2); /* 2 - Bus error */ cpuSetStackFrameGenFunc(3, cpuFrameGroup2); /* 3 - Address error */ } static void cpuStackFrameInit010(void) { cpuStackFrameInitSetDefaultFunc(cpuFrame0); cpuSetStackFrameGenFunc(2, cpuFrame8); /* 2 - Bus error */ cpuSetStackFrameGenFunc(3, cpuFrame8); /* 3 - Address error */ } static void cpuStackFrameInit020(void) { cpuStackFrameInitSetDefaultFunc(cpuFrame0); cpuSetStackFrameGenFunc(2, cpuFrameA); /* 2 - Bus Error */ cpuSetStackFrameGenFunc(3, cpuFrameA); /* 3 - Addrss Error */ cpuSetStackFrameGenFunc(5, cpuFrame2); /* 5 - Zero Divide */ cpuSetStackFrameGenFunc(6, cpuFrame2); /* 6 - CHK, CHK2 */ cpuSetStackFrameGenFunc(7, cpuFrame2); /* 7 - TRAPV, TRAPcc, cpTRAPcc */ cpuSetStackFrameGenFunc(9, cpuFrame2); /* 9 - Trace */ } static void cpuStackFrameInit030(void) { cpuStackFrameInitSetDefaultFunc(cpuFrame0); cpuSetStackFrameGenFunc(2, cpuFrameA); /* 2 - Bus Error */ cpuSetStackFrameGenFunc(3, cpuFrameA); /* 3 - Addrss Error */ cpuSetStackFrameGenFunc(5, cpuFrame2); /* 5 - Zero Divide */ cpuSetStackFrameGenFunc(6, cpuFrame2); /* 6 - CHK, CHK2 */ cpuSetStackFrameGenFunc(7, cpuFrame2); /* 7 - TRAPV, TRAPcc, cpTRAPcc */ cpuSetStackFrameGenFunc(9, cpuFrame2); /* 9 - Trace */ } void cpuStackFrameInit(void) { switch (cpuGetModelMajor()) { case 0: cpuStackFrameInit000(); break; case 1: cpuStackFrameInit010(); break; case 2: cpuStackFrameInit020(); break; case 3: cpuStackFrameInit030(); break; } }