From: notaz Date: Sat, 22 Jun 2013 16:16:11 +0000 (+0300) Subject: switch Cyclone to submodule on it's own git repo X-Git-Tag: v1.85~98 X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1b85bf1c2307c548a637f988eb69f615864f1685;p=picodrive.git switch Cyclone to submodule on it's own git repo that version also has it's license clearly stated by fdave --- diff --git a/.gitmodules b/.gitmodules index c003620..b27d2a1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "platform/libpicofe"] path = platform/libpicofe url = git://notaz.gp2x.de/~notaz/libpicofe.git +[submodule "cpu/cyclone"] + path = cpu/cyclone + url = git://notaz.gp2x.de/~notaz/cyclone68000.git diff --git a/cpu/Cyclone/Cyclone.h b/cpu/Cyclone/Cyclone.h deleted file mode 100644 index fc7695e..0000000 --- a/cpu/Cyclone/Cyclone.h +++ /dev/null @@ -1,97 +0,0 @@ - -// Cyclone 68000 Emulator - Header File - -// (c) Copyright 2004 Dave, All rights reserved. -// (c) 2005-2007 notaz -// Cyclone 68000 is free for non-commercial use. - -// For commercial use, separate licencing terms must be obtained. - - -#ifndef __CYCLONE_H__ -#define __CYCLONE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -extern int CycloneVer; // Version number of library - -struct Cyclone -{ - unsigned int d[8]; // [r7,#0x00] - unsigned int a[8]; // [r7,#0x20] - unsigned int pc; // [r7,#0x40] Memory Base (.membase) + 68k PC - unsigned char srh; // [r7,#0x44] Status Register high (T_S__III) - unsigned char unused; // [r7,#0x45] Unused - unsigned char flags; // [r7,#0x46] Flags (ARM order: ____NZCV) [68k order is XNZVC] - unsigned char irq; // [r7,#0x47] IRQ level - unsigned int osp; // [r7,#0x48] Other Stack Pointer (USP/SSP) - unsigned int xc; // [r7,#0x4c] Extend flag (bit29: ??X? _) - unsigned int prev_pc; // [r7,#0x50] Set to start address of currently executed opcode + 2 (if enabled in config.h) - unsigned int jumptab; // [r7,#0x54] Jump table pointer - int state_flags; // [r7,#0x58] bit: 0: stopped state, 1: trace state, 2: activity bit, 3: addr error, 4: fatal halt - int cycles; // [r7,#0x5c] Number of cycles to execute - 1. Updates to cycles left after CycloneRun() - int membase; // [r7,#0x60] Memory Base (ARM address minus 68000 address) - unsigned int (*checkpc)(unsigned int pc); // [r7,#0x64] called to recalc Memory Base+pc - unsigned int (*read8 )(unsigned int a); // [r7,#0x68] - unsigned int (*read16 )(unsigned int a); // [r7,#0x6c] - unsigned int (*read32 )(unsigned int a); // [r7,#0x70] - void (*write8 )(unsigned int a,unsigned char d); // [r7,#0x74] - void (*write16)(unsigned int a,unsigned short d); // [r7,#0x78] - void (*write32)(unsigned int a,unsigned int d); // [r7,#0x7c] - unsigned int (*fetch8 )(unsigned int a); // [r7,#0x80] - unsigned int (*fetch16)(unsigned int a); // [r7,#0x84] - unsigned int (*fetch32)(unsigned int a); // [r7,#0x88] - int (*IrqCallback)(int int_level); // [r7,#0x8c] optional irq callback function, see config.h - void (*ResetCallback)(void); // [r7,#0x90] if enabled in config.h, calls this whenever RESET opcode is encountered. - int (*UnrecognizedCallback)(void); // [r7,#0x94] if enabled in config.h, calls this whenever unrecognized opcode is encountered. - unsigned int internal[6]; // [r7,#0x98] reserved for internal use, do not change. -}; - -// Initialize. Used only if Cyclone was compiled with compressed jumptable, see config.h -void CycloneInit(void); - -// Reset -void CycloneReset(struct Cyclone *pcy); - -// Run cyclone. Cycles should be specified in context (pcy->cycles) -void CycloneRun(struct Cyclone *pcy); - -// Utility functions to get and set SR -void CycloneSetSr(struct Cyclone *pcy, unsigned int sr); -unsigned int CycloneGetSr(const struct Cyclone *pcy); - -// Generates irq exception if needed (if pcy->irq > mask). -// Returns cycles used for exception if it was generated, 0 otherwise. -int CycloneFlushIrq(struct Cyclone *pcy); - -// Functions for saving and restoring state. -// CycloneUnpack() uses checkpc(), so it must be initialized. -// save_buffer must point to buffer of 128 (0x80) bytes of size. -void CyclonePack(const struct Cyclone *pcy, void *save_buffer); -void CycloneUnpack(struct Cyclone *pcy, const void *save_buffer); - -// genesis: if 1, switch to normal TAS handlers -void CycloneSetRealTAS(int use_real); - - -// These values are special return values for IrqCallback. - -// Causes an interrupt autovector (0x18 + interrupt level) to be taken. -// This happens in a real 68K if VPA or AVEC is asserted during an interrupt -// acknowledge cycle instead of DTACK (the most common situation). -#define CYCLONE_INT_ACK_AUTOVECTOR -1 - -// Causes the spurious interrupt vector (0x18) to be taken -// This happens in a real 68K if BERR is asserted during the interrupt -// acknowledge cycle (i.e. no devices responded to the acknowledge). -#define CYCLONE_INT_ACK_SPURIOUS -2 - - -#ifdef __cplusplus -} // End of extern "C" -#endif - -#endif // __CYCLONE_H__ - diff --git a/cpu/Cyclone/Cyclone.txt b/cpu/Cyclone/Cyclone.txt deleted file mode 100644 index 3397118..0000000 --- a/cpu/Cyclone/Cyclone.txt +++ /dev/null @@ -1,627 +0,0 @@ - - _____ __ - / ___/__ __ ____ / /___ ___ ___ ___________________ - / /__ / // // __// // _ \ / _ \/ -_) ___________________ - \___/ \_, / \__//_/ \___//_//_/\__/ ___________________ - /___/ - ___________________ ____ ___ ___ ___ ___ - ___________________ / __// _ \ / _ \ / _ \ / _ \ - ___________________ / _ \/ _ // // // // // // / - \___/\___/ \___/ \___/ \___/ - -___________________________________________________________________________ - - Cyclone 68000 (c) Copyright 2004 Dave. Free for non-commercial use - - Homepage: http://www.finalburn.com/ - Dave's e-mail: emudave(atsymbol)googlemail.com - Replace (atsymbol) with @ - - Additional coding and bugfixes done by notaz, 2005-2007 - Homepage: http://notaz.gp2x.de - e-mail: notasas(atsymbol)gmail.com -___________________________________________________________________________ - - -About ------ - -Cyclone 68000 is an emulator for the 68000 microprocessor, written in ARM 32-bit assembly. -It is aimed at chips such as ARM7 and ARM9 cores, StrongARM and XScale, to interpret 68000 -code as fast as possible. It can emulate all 68000 instructions quite accurately, instruction -timing was synchronized with MAME's Musashi. Most 68k features are emulated (trace mode, -address errors), but prefetch is not emulated. - - -How to Compile --------------- - -Like Starscream and A68K, Cyclone uses a 'Core Creator' program which calculates and outputs -all possible 68000 Opcodes and a jump table into file called Cyclone.s or Cyclone.asm. -Only Cyclone.h and the mentioned .s or .asm file will be needed for your project, other files -are here to produce or test it. - -First unzip "Cyclone.zip" into a "Cyclone" directory. The next thing to do is to edit config.h -file to tune Cyclone for your project. There are lots of options in config.h, but all of them -are documented and have defaults. You should set a define value to 1 to enable option, and -to 0 to disable. - -After you are done with config.h, save it and compile Cyclone. If you are using Linux, Cygwin, -mingw or similar, you can simply cd to Cyclone/proj and type "make". If you are under Windows -and have Visual Studio installed, you can import cyclone.dsp in the proj/ directory and compile -it from there (this will produce cyclone.exe which you will have to run to get .s or .asm). -You can also use Microsoft command line compile tools by entering Cyclone/proj directory and -typing "nmake -f Makefile.win". Note that this step is done only to produce .s or .asm, and it -is done using native tools on your PC (not using cross-compiler or similar). - -The .s file is meant to be compiled with GNU assembler, and .asm with ARMASM.EXE -(the Microsoft ARM assembler). Once you have the file, you can add it to your -Makefile/project/whatever. - - -Adding to your project ----------------------- - -Compiling the .s or .asm (from previous step) for your target platform may require custom -build rules in your Makefile/project. - -If you use some gcc-based toolchain, you will need to add Cyclone.o to an object list in -the Makefile. GNU make will use "as" to build Cyclone.o from Cyclone.s by default, so -you may need to define correct cross-assembler by setting AS variable like this: - -AS = arm-linux-as - -This might be different in your case, basically it should be same prefix as for gcc. -You may also need to specify floating point type in your assembler flags for Cyclone.o -to link properly. This is done like this: - -ASFLAGS = -mfloat-abi=soft - -Note that Cyclone does not use floating points, this is just to make the linker happy. - - -If you are using Visual Studio, you may need to add "custom build step", which creates -Cyclone.obj from Cyclone.asm (asmasm.exe Cyclone.asm). Alternatively you can create -Cyclone.obj by using armasm once and then just add it to you project. - -Don't worry if this seem very minimal - its all you need to run as many 68000s as you want. -It works with both C and C++. - - -Byteswapped Memory ------------------- - -If you have used Starscream, A68K or Turbo68K or similar emulators you'll be familiar with this! - -Any memory which the 68000 can access directly must be have every two bytes swapped around. -This is to speed up 16-bit memory accesses, because the 68000 has Big-Endian memory -and ARM has Little-Endian memory (in most cases). - -Now you may think you only technically have to byteswap ROM, not RAM, because -16-bit RAM reads go through a memory handler and you could just return (mem[a]<<8) | mem[a+1]. - -This would work, but remember some systems can execute code from RAM as well as ROM, and -that would fail. -So it's best to use byteswapped ROM and RAM if the 68000 can access it directly. -It's also faster for the memory handlers, because you can do this: - - return *(unsigned short *)(mem+a) - - -Declaring Memory handlers -------------------------- - -Before you can reset or execute 68000 opcodes you must first set up a set of memory handlers. -There are 7 functions you have to set up per CPU, like this: - - static unsigned int MyCheckPc(unsigned int pc) - static unsigned char MyRead8 (unsigned int a) - static unsigned short MyRead16 (unsigned int a) - static unsigned int MyRead32 (unsigned int a) - static void MyWrite8 (unsigned int a,unsigned char d) - static void MyWrite16(unsigned int a,unsigned short d) - static void MyWrite32(unsigned int a,unsigned int d) - -You can think of these functions representing the 68000's memory bus. -The Read and Write functions are called whenever the 68000 reads or writes memory. -For example you might set MyRead8 like this: - - unsigned char MyRead8(unsigned int a) - { - a&=0xffffff; // Clip address to 24-bits - - if (a=0xe00000) return RamData[(a^1)&0xffff]; - return 0xff; // Out of range memory access - } - -The other 5 read/write functions are similar. I'll describe the CheckPc function later on. - - -Declaring a CPU Context ------------------------ - -To declare a CPU simple declare a struct Cyclone in your code (don't forget to include Cyclone.h). -For example to declare two 68000s: - - struct Cyclone MyCpu; - struct Cyclone MyCpu2; - -It's probably a good idea to initialize the memory to zero: - - memset(&MyCpu, 0,sizeof(MyCpu)); - memset(&MyCpu2,0,sizeof(MyCpu2)); - -Next point to your memory handlers: - - MyCpu.checkpc=MyCheckPc; - MyCpu.read8 =MyRead8; - MyCpu.read16 =MyRead16; - MyCpu.read32 =MyRead32; - MyCpu.write8 =MyWrite8; - MyCpu.write16=MyWrite16; - MyCpu.write32=MyWrite32; - -You also need to point the fetch handlers - for most systems out there you can just -point them at the read handlers: - MyCpu.fetch8 =MyRead8; - MyCpu.fetch16 =MyRead16; - MyCpu.fetch32 =MyRead32; - -( Why a different set of function pointers for fetch? - Well there are some systems, the main one being CPS2, which return different data - depending on whether the 'fetch' line on the 68000 bus is high or low. - If this is the case, you can set up different functions for fetch reads. - Generally though you don't need to. ) - -Now you are nearly ready to reset the 68000, except a few more functions, -one of them is: checkpc(). - - -The checkpc() function ----------------------- - -When Cyclone reads opcodes, it doesn't use a memory handler every time, this would be -far too slow, instead it uses a direct pointer to ARM memory. -For example if your Rom image was at 0x3000000 and the program counter was $206, -Cyclone's program counter would be 0x3000206. - -The difference between an ARM address and a 68000 address is also stored in a variable called -'membase'. In the above example it's 0x3000000. To retrieve the real 68k PC, Cyclone just -subtracts 'membase'. - -When a long jump happens, Cyclone calls checkpc(). If the PC is in a different bank, -for example Ram instead of Rom, change 'membase', recalculate the new PC and return it: - -static int MyCheckPc(unsigned int pc) -{ - pc-=MyCpu.membase; // Get the real program counter - - if (pc=0xff0000) MyCpu.membase=(int)RamMem-0xff0000; // Jump to Ram - - return MyCpu.membase+pc; // New program counter -} - -Notice that the membase is always ARM address minus 68000 address. - -The above example doesn't consider mirrored ram, but for an example of what to do see -PicoDrive (in Memory.c). - -The exact cases when checkpc() is called can be configured in config.h. - - -Initialization --------------- - -Add a call to CycloneInit(). This is really only needed to be called once at startup -if you enabled COMPRESS_JUMPTABLE in config.h, but you can add this in any case, -it won't hurt. - - -Almost there - Reset the 68000! -------------------------------- - -Cyclone doesn't provide a reset function, so next we need to Reset the 68000 to get -the initial Program Counter and Stack Pointer. This is obtained from addresses -000000 and 000004. - -Here is code which resets the 68000 (using your memory handlers): - - MyCpu.state_flags=0; // Go to default state (not stopped, halted, etc.) - MyCpu.srh=0x27; // Set supervisor mode - MyCpu.a[7]=MyCpu.read32(0); // Get Stack Pointer - MyCpu.membase=0; // Will be set by checkpc() - MyCpu.pc=MyCpu.checkpc(MyCpu.read32(4)); // Get Program Counter - -And that's ready to go. - - -Executing the 68000 -------------------- - -To execute the 68000, set the 'cycles' variable to the number of cycles you wish to execute, -and then call CycloneRun with a pointer to the Cyclone structure. - -e.g.: - // Execute 1000 cycles on the 68000: - MyCpu.cycles=1000; CycloneRun(&MyCpu); - -For each opcode, the number of cycles it took is subtracted and the function returns when -it reaches negative number. The result is stored back to MyCpu.cycles. - -e.g. - // Execute one instruction on the 68000: - MyCpu.cycles=0; CycloneRun(&MyCpu); - printf(" The opcode took %d cycles\n", -MyCpu.cycles); - -You should try to execute as many cycles as you can for maximum speed. -The number actually executed may be slightly more than requested, i.e. cycles may come -out with a small negative value: - -e.g. - int todo=12000000/60; // 12Mhz, for one 60hz frame - MyCpu.cycles=todo; CycloneRun(&MyCpu); - printf(" Actually executed %d cycles\n", todo-MyCpu.cycles); - -To calculate the number of cycles executed, use this formula: - Number of cycles requested - Cycle counter at the end - - -Interrupts ----------- - -Causing an interrupt is very simple, simply set the irq variable in the Cyclone structure -to the IRQ number. -To lower the IRQ line, set it to zero. - -e.g: - MyCpu.irq=6; // Interrupt level 6 - MyCpu.cycles=20000; CycloneRun(&MyCpu); - -Note that the interrupt is not actually processed until the next call to CycloneRun, -and the interrupt may not be taken until the 68000 interrupt mask is changed to allow it. - -If you need to force interrupt processing, you can use CycloneFlushIrq() function. -It is the same as doing - -MyCpu.cycles=0; CycloneRun(&MyCpu); - -but is better optimized and doesn't update .cycles (returns them instead). -This function can't be used from memory handlers and has no effect if interrupt is masked. - -The IRQ isn't checked on exiting from a memory handler. If you need to cause interrupt -check immediately, you should change cycle counter to 0 to cause a return from CycloneRun(), -and then call CycloneRun() again or just call CycloneFlushIrq(). Note that you need to -enable MEMHANDLERS_CHANGE_CYCLES in config.h for this to work. - -If you need to do something during the interrupt acknowledge (the moment when interrupt -is taken), you can set USE_INT_ACK_CALLBACK in config.h and specify IrqCallback function. -This function should update the IRQ level (.irq variable in context) and return the -interrupt vector number. But for most cases it should return special constant -CYCLONE_INT_ACK_AUTOVECTOR so that Cyclone uses autovectors, which is what most real -systems were doing. Another less commonly used option is to return CYCLONE_INT_ACK_SPURIOUS -for spurious interrupt. - - -Accessing Program Counter and registers ---------------------------------------- - -You can read most Cyclone's registers directly from the structure at any time. -However, the PC value, CCR and cycle counter are cached in ARM registers and can't -be accessed from memory handlers by default. They are written back and can be -accessed after execution. - -But if you need to access the mentioned registers during execution, you can set -MEMHANDLERS_NEED_* and MEMHANDLERS_CHANGE_* options in config.h - -The Program Counter, should you need to read or write it, is stored with membase -added on. So use this formula to calculate the real 68000 program counter: - - pc = MyCpu.pc - MyCpu.membase; - -For performance reasons Cyclone keeps the status register split into .srh -(status register "high" supervisor byte), .xc for the X flag, and .flags for remaining -CCR flags (in ARM order). To easily read/write the status register as normal 68k -16bit SR register, use CycloneGetSr() and CycloneSetSr() utility functions. - - -Emulating more than one CPU ---------------------------- - -Since everything is based on the structures, emulating more than one cpu at the same time -is just a matter of declaring more than one structures and timeslicing. You can emulate -as many 68000s as you want. -Just set up the memory handlers for each cpu and run each cpu for a certain number of cycles. - -e.g. - // Execute 1000 cycles on 68000 #1: - MyCpu.cycles=1000; CycloneRun(&MyCpu); - - // Execute 1000 cycles on 68000 #2: - MyCpu2.cycles=1000; CycloneRun(&MyCpu2); - - -Quick API reference -------------------- - -void CycloneInit(void); - Initializes Cyclone. Must be called if the jumptable is compressed, - doesn't matter otherwise. - -void CycloneRun(struct Cyclone *pcy); - Runs cyclone for pcy->cycles. Writes amount of cycles left back to - pcy->cycles (always negative). - -unsigned int CycloneGetSr(const struct Cyclone *pcy); - Reads status register in internal form from pcy, converts to standard 68k SR and returns it. - -void CycloneSetSr(struct Cyclone *pcy, unsigned int sr); - Takes standard 68k status register (sr), and updates Cyclone context with it. - -int CycloneFlushIrq(struct Cyclone *pcy); - If .irq is greater than IRQ mask in SR, or it is equal to 7 (NMI), processes interrupt - exception and returns number of cycles used. Otherwise, does nothing and returns 0. - -void CyclonePack(const struct Cyclone *pcy, void *save_buffer); - Writes Cyclone state to save_buffer. This allows to avoid all the trouble figuring what - actually needs to be saved from the Cyclone structure, as saving whole struct Cyclone - to a file will also save various pointers, which may become invalid after your program - is restarted, so simply reloading the structure will cause a crash. save_buffer size - should be 128 bytes (now it is really using less, but this allows future expansion). - -void CycloneUnpack(struct Cyclone *pcy, const void *save_buffer); - Reloads Cyclone state from save_buffer, which was previously saved by CyclonePack(). - This function uses checkpc() callback to rebase the PC, so .checkpc must be initialized - before calling it. - -Callbacks: - -.checkpc -unsigned int (*checkpc)(unsigned int pc); - This function is called when PC changes are performed in 68k code or because of exceptions. - It is passed ARM pointer and should return ARM pointer casted to int. It must also update - .membase if needed. See "The checkpc() function" section above. - -unsigned int (*read8 )(unsigned int a); -unsigned int (*read16 )(unsigned int a); -unsigned int (*read32 )(unsigned int a); - These are the read memory handler callbacks. They are called when 68k code reads from memory. - The parameter is a 68k address in data space, return value is a data value read. Data value - doesn't have to be masked to 8 or 16 bits for read8 or read16, Cyclone will do that itself - if needed. - -unsigned int (*fetch8 )(unsigned int a); -unsigned int (*fetch16)(unsigned int a); -unsigned int (*fetch32)(unsigned int a); - Same as above, but these are reads from program space (PC relative reads mostly). - -void (*write8 )(unsigned int a,unsigned char d); -void (*write16)(unsigned int a,unsigned short d); -void (*write32)(unsigned int a,unsigned int d); - These are called when 68k code writes to data space. d is the data value. - -int (*IrqCallback)(int int_level); - This function is called when Cyclone acknowledges an interrupt. The parameter is the IRQ - level being acknowledged, and return value is exception vector to use, or one of these special - values: CYCLONE_INT_ACK_AUTOVECTOR or CYCLONE_INT_ACK_SPURIOUS. Can be disabled in config.h. - See "Interrupts" section for more information. - -void (*ResetCallback)(void); - Cyclone will call this function if it encounters RESET 68k instruction. - Can be disabled in config.h. - -int (*UnrecognizedCallback)(void); - Cyclone will call this function if it encounters illegal instructions (including A-line and - F-line ones). Can be tuned / disabled in config.h. - - -Function codes --------------- - -Cyclone doesn't pass function codes to it's memory handlers, but they can be calculated: -FC2: just use supervisor state bit from status register (eg. (MyCpu.srh & 0x20) >> 5) -FC1: if we are in fetch* function, then 1, else 0. -FC0: if we are in read* or write*, then 1, else 0. -CPU state (all FC bits set) is active in IrqCallback function. - - -References ----------- - -These documents were used while writing Cyclone and should be useful for those who want to -understand deeper how the 68000 works. - -MOTOROLA M68000 FAMILY Programmer's Reference Manual -common name: 68kPM.pdf - -M68000 8-/16-/32-Bit Microprocessors User's Manual -common name: MC68000UM.pdf - -68000 Undocumented Behavior Notes by Bart Trzynadlowski -http://www.trzy.org/files/68knotes.txt - -Instruction prefetch on the Motorola 68000 processor by Jorge Cwik -http://pasti.fxatari.com/68kdocs/68kPrefetch.html - - -ARM Register Usage ------------------- - -See source code for up to date of register usage, however a summary is here: - - r0-3: Temporary registers - r4 : Current PC + Memory Base (i.e. pointer to next opcode) - r5 : Cycles remaining - r6 : Pointer to Opcode Jump table - r7 : Pointer to Cpu Context - r8 : Current Opcode - r10 : Flags (NZCV) in highest four bits - (r11 : Temporary register) - -Flags are mapped onto ARM flags whenever possible, which speeds up the processing of opcode. -r9 is not used intentionally, because AAPCS defines it as "platform register", so it's -reserved in some systems. - - -Thanks to... ------------- - -* All the previous code-generating assembler cpu core guys! - Who are iirc... Neill Corlett, Neil Bradley, Mike Coates, Darren Olafson - Karl Stenerud and Bart Trzynadlowski - -* Charles Macdonald, for researching just about every console ever -* MameDev+FBA, for keeping on going and going and going - - -What's New ----------- -v0.0099 notaz - * Cyclone no longer uses r9, because AAPCS defines it as "platform register", - so it's reserved in some systems. - * Made SPLIT_MOVEL_PD to affect MOVEM too. - -v0.0088 notaz - - Reduced amount of code in opcode handlers by ~23% by doing the following: - - Removed duplicate opcode handlers - - Optimized code to use less ARM instructions - - Merged some duplicate handler endings - + Cyclone now does better job avoiding pipeline interlocks. - + Replaced incorrect handler of DBT with proper one. - + Changed "MOVEA (An)+ An" behavior. - + Fixed flag behavior of ROXR, ASL, LSR and NBCD in certain situations. - Hopefully got them right now. - + Cyclone no longer sets most significant bits while pushing PC to stack. - Amiga Kickstart depends on this. - + Added optional trace mode emulation. - + Added optional address error emulation. - + Additional functionality added for MAME and other ports (see config.h). - + Added return value for IrqCallback to make it suitable for emulating devices which - pass the vector number during interrupt acknowledge cycle. For usual autovector - processing this function must return CYCLONE_INT_ACK_AUTOVECTOR, so those who are - upgrading must add "return CYCLONE_INT_ACK_AUTOVECTOR;" to their IrqCallback functions. - * Updated documentation. - -v0.0086 notaz - + Cyclone now can be customized to better suit your project, see config.h . - + Added an option to compress the jumptable at compile-time. Must call CycloneInit() - at runtime to decompress it if enabled (see config.h). - + Added missing CHK opcode handler (used by SeaQuest DSV). - + Added missing TAS opcode handler (Gargoyles,Bubba N Stix,...). As in real genesis, - memory write-back phase is ignored (but can be enabled in config.h if needed). - + Added missing NBCD and TRAPV opcode handlers. - + Added missing addressing mode for CMP/EOR. - + Added some minor optimizations. - - Removed 216 handlers for 2927 opcodes which were generated for invalid addressing modes. - + Fixed flags for ASL, NEG, NEGX, DIVU, ADDX, SUBX, ROXR. - + Bugs fixed in MOVEP, LINK, ADDQ, DIVS handlers. - * Undocumented flags for CHK, ABCD, SBCD and NBCD are now emulated the same way as in Musashi. - + Added Uninitialized Interrupt emulation. - + Altered timing for about half of opcodes to match Musashi's. - -v0.0082 Reesy - + Change cyclone to clear cycles before returning when halted - + Added Irq call back function. This allows emulators to be notified - when cyclone has taken an interrupt allowing them to set internal flags - which can help fix timing problems. - -v0.0081 notaz - + .asm version was broken and did not compile with armasm. Fixed. - + Finished implementing Stop opcode. Now it really stops the processor. - -v0.0080 notaz - + Added real cmpm opcode, it was using eor handler before this. - Fixes Dune and Sensible Soccer. - -v0.0078 notaz - note: these bugs were actually found Reesy, I reimplemented these by - using his changelog as a guide. - + Fixed a problem with divu which was using long divisor instead of word. - Fixes gear switching in Top Gear 2. - + Fixed btst opcode, The bit to test should shifted a max of 31 or 7 - depending on if a register or memory location is being tested. - + Fixed abcd,sbcd. They did bad decimal correction on invalid BCD numbers - Score counters in Streets of Rage level end work now. - + Changed flag handling of abcd,sbcd,addx,subx,asl,lsl,... - Some ops did not have flag handling at all. - Some ops must not change Z flag when result is zero, but they did. - Shift ops must not change X if shift count is zero, but they did. - There are probably still some flag problems left. - + Patially implemented Stop and Reset opcodes - Fixes Thunderforce IV - -v0.0075 notaz - + Added missing displacement addressing mode for movem (Fantastic Dizzy) - + Added OSP <-> A7 swapping code in opcodes, which change privilege mode - + Implemented privilege violation, line emulator and divide by zero exceptions - + Added negx opcode (Shining Force works!) - + Added overflow detection for divs/divu - -v0.0072 notaz - note: I could only get v0.0069 cyclone, so I had to implement these myself using Dave's - changelog as a guide. - + Fixed a problem with divs - remainder should be negative when divident is negative - + Added movep opcode (Sonic 3 works) - + Fixed a problem with DBcc incorrectly decrementing if the condition is true (Shadow of the Beast) - -v0.0069 - + Added SBCD and the flags for ABCD/SBCD. Score and time now works in games such as - Rolling Thunder 2, Ghouls 'N Ghosts - + Fixed a problem with addx and subx with 8-bit and 16-bit values. - Ghouls 'N' Ghosts now works! - -v0.0068 - + Added ABCD opcode (Streets of Rage works now!) - -v0.0067 - + Added dbCC (After Burner) - + Added asr EA (Sonic 1 Boss/Labyrinth Zone) - + Added andi/ori/eori ccr (Altered Beast) - + Added trap (After Burner) - + Added special case for move.b (a7)+ and -(a7), stepping by 2 - After Burner is playable! Eternal Champions shows more - + Fixed lsr.b/w zero flag (Ghostbusters) - Rolling Thunder 2 now works! - + Fixed N flag for .b and .w arithmetic. Golden Axe works! - -v0.0066 - + Fixed a stupid typo for exg (orr r10,r10, not orr r10,r8), which caused alignment - crashes on Strider - -v0.0065 - + Fixed a problem with immediate values - they weren't being shifted up correctly for some - opcodes. Spiderman works, After Burner shows a bit of graphics. - + Fixed a problem with EA:"110nnn" extension word. 32-bit offsets were being decoded as 8-bit - offsets by mistake. Castlevania Bloodlines seems fine now. - + Added exg opcode - + Fixed asr opcode (Sonic jumping left is fixed) - + Fixed a problem with the carry bit in rol.b (Marble Madness) - -v0.0064 - + Added rtr - + Fixed addq/subq.l (all An opcodes are 32-bit) (Road Rash) - + Fixed various little timings - -v0.0063 - + Added link/unlk opcodes - + Fixed various little timings - + Fixed a problem with dbCC opcode being emitted at set opcodes - + Improved long register access, the EA fetch now does ldr r0,[r7,r0,lsl #2] whenever - possible, saving 1 or 2 cycles on many opcodes, which should give a nice speed up. - + May have fixed N flag on ext opcode? - + Added dasm for link opcode. - -v0.0062 - * I was a bit too keen with the Arithmetic opcodes! Some of them should have been abcd, - exg and addx. Removed the incorrect opcodes, pending re-adding them as abcd, exg and addx. - + Changed unknown opcodes to act as nops. - Not very technical, but fun - a few more games show more graphics ;) - -v0.0060 - + Fixed divu (EA intro) - + Added sf (set false) opcode - SOR2 - * Todo: pea/link/unlk opcodes - -v0.0059: Added remainder to divide opcodes. - - diff --git a/cpu/Cyclone/Disa/Disa.c b/cpu/Cyclone/Disa/Disa.c deleted file mode 100644 index 190e36d..0000000 --- a/cpu/Cyclone/Disa/Disa.c +++ /dev/null @@ -1,886 +0,0 @@ - -// Dave's Disa 68000 Disassembler -#ifndef __GNUC__ -#pragma warning(disable:4115) -#endif -#include -#include -#include "Disa.h" - -unsigned int DisaPc=0; -char *DisaText=NULL; // Text buffer to write in -static char Tasm[]="bwl?"; -static char Comment[64]=""; -unsigned short (*DisaWord)(unsigned int a)=NULL; - -static unsigned int DisaLong(unsigned int a) -{ - unsigned int d=0; - if (DisaWord==NULL) return d; - - d= DisaWord(a)<<16; - d|=DisaWord(a+2)&0xffff; - return d; -} - -// Get text version of the effective address -int DisaGetEa(char *t,int ea,int size) -{ - ea&=0x3f; t[0]=0; - if ((ea&0x38)==0x00) { sprintf(t,"d%d",ea ); return 0; } // 000rrr - if ((ea&0x38)==0x08) { sprintf(t,"a%d",ea&7); return 0; } // 001rrr - if ((ea&0x38)==0x10) { sprintf(t,"(a%d)",ea&7); return 0; } // 010rrr - if ((ea&0x38)==0x18) { sprintf(t,"(a%d)+",ea&7); return 0; } // 011rrr - if ((ea&0x38)==0x20) { sprintf(t,"-(a%d)",ea&7); return 0; } // 100rrr - if ((ea&0x38)==0x28) { sprintf(t,"($%x,a%d)",DisaWord(DisaPc)&0xffff,ea&7); DisaPc+=2; return 0; } // 101rrr - - if ((ea&0x38)==0x30) - { - // 110nnn - An + Disp + D/An - int areg=0,ext=0,off=0,da=0,reg=0,wol=0,scale=0; - ext=DisaWord(DisaPc)&0xffff; - - areg=ea&7; - off=ext&0xff; da =ext&0x8000?'a':'d'; - reg=(ext>>12)&7; wol=ext&0x0800?'l':'w'; - scale=1<<((ext>>9)&3); - - if (scale<2) sprintf(t,"($%x,a%d,%c%d.%c)", off,areg,da,reg,wol); - else sprintf(t,"($%x,a%d,%c%d.%c*%d)",off,areg,da,reg,wol,scale); // 68020 - - DisaPc+=2; - return 0; - } - - if (ea==0x38) { sprintf(t,"$%x.w",DisaWord(DisaPc)&0xffff); DisaPc+=2; return 0; } // 111000 - Absolute short - if (ea==0x39) { sprintf(t,"$%x.l",DisaLong(DisaPc)); DisaPc+=4; return 0; } // 111001 - Absolute long - - if (ea==0x3a) - { - // 111010 - PC Relative - int ext=DisaWord(DisaPc)&0xffff; - sprintf(t,"($%x,pc)",ext); - sprintf(Comment,"; =%x",DisaPc+(short)ext); // Comment where pc+ext is - DisaPc+=2; - return 0; - } - - if (ea==0x3b) - { - // 111011 - PC Relative + D/An - int ext=0,off=0,da=0,reg=0,wol=0,scale=0; - ext=DisaWord(DisaPc)&0xffff; - - off=ext&0xff; da =ext&0x8000?'a':'d'; - reg=(ext>>12)&7; wol=ext&0x0800?'l':'w'; - scale=1<<((ext>>9)&3); - - if (scale<2) sprintf(t,"($%x,pc,%c%d.%c)", off,da,reg,wol); - else sprintf(t,"($%x,pc,%c%d.%c*%d)",off,da,reg,wol,scale); // 68020 - - sprintf(Comment,"; =%x",DisaPc+(char)off); // Comment where pc+ext is - DisaPc+=2; - return 0; - } - - if (ea==0x3c) - { - // 111100 - Immediate - switch (size) - { - case 0: sprintf(t,"#$%x",DisaWord(DisaPc)&0x00ff); DisaPc+=2; return 0; - case 1: sprintf(t,"#$%x",DisaWord(DisaPc)&0xffff); DisaPc+=2; return 0; - case 2: sprintf(t,"#$%x",DisaLong(DisaPc) ); DisaPc+=4; return 0; - } - return 1; - } - -// Unknown effective address - sprintf(t,"ea=(%d%d%d %d%d%d)", - (ea>>5)&1,(ea>>4)&1,(ea>>3)&1, - (ea>>2)&1,(ea>>1)&1, ea &1); - return 1; -} - -static void GetOffset(char *text) -{ - int off=(short)DisaWord(DisaPc); DisaPc+=2; - - if (off<0) sprintf(text,"-$%x",-off); - else sprintf(text,"$%x", off); -} - -// ================ Opcodes 0x0000+ ================ -static int DisaArithImm(int op) -{ - // Or/And/Sub/Add/Eor/Cmp Immediate 0000ttt0 xxDDDddd (tt=type, xx=size extension, DDDddd=Dest ea) - int dea=0; - char seat[64]="",deat[64]=""; - int type=0,size=0; - char *arith[8]={"or","and","sub","add","?","eor","cmp","?"}; - - type=(op>>9)&7; if (type==4 || type>=7) return 1; - size=(op>>6)&3; if (size>=3) return 1; - dea=op&0x3f; if (dea==0x3c) return 1; - - DisaGetEa(seat,0x3c,size); - DisaGetEa(deat,dea, size); - - sprintf(DisaText,"%si.%c %s, %s",arith[type],Tasm[size],seat,deat); - return 0; -} - -// ================ Opcodes 0x0108+ ================ -static int DisaMovep(int op) -{ - // movep.x (Aa),Dn - 0000nnn1 dx001aaa nn - int dn=0,dir=0,size=0,an=0; - char offset[32]=""; - - dn =(op>>9)&7; - dir =(op>>7)&1; - size=(op>>6)&1; size++; - an = op &7; - - GetOffset(offset); - if (dir) sprintf(DisaText,"movep.%c d%d, (%s,a%d)",Tasm[size],dn,offset,an); - else sprintf(DisaText,"movep.%c (%s,a%d), d%d",Tasm[size],offset,an,dn); - - return 0; -} - -// ================ Opcodes 0x007c+ ================ -static int DisaArithSr(int op) -{ - // Ori/Andi/Eori $nnnn,sr 0000t0tx 0s111100 - char *opcode[6]={"ori","andi","","","","eori"}; - char seat[64]=""; - int type=0,size=0; - - type=(op>>9)&5; - size=(op>>6)&1; - - DisaGetEa(seat,0x3c,size); - sprintf(DisaText,"%s.%c %s, %s", opcode[type], Tasm[size], seat, size?"sr":"ccr"); - - return 0; -} - -// ================ Opcodes 0x0100+ ================ -static int DisaBtstReg(int op) -{ - // Btst/Bchg/Bclr/Bset 0000nnn1 tteeeeee (nn=reg number, eeeeee=Dest ea) - int type=0; - int sea=0,dea=0; - char seat[64]="",deat[64]=""; - char *opcode[4]={"btst","bchg","bclr","bset"}; - - sea =(op>>9)&7; - type=(op>>6)&3; - dea= op&0x3f; - - if ((dea&0x38)==0x08) return 1; // movep - DisaGetEa(seat,sea,0); - DisaGetEa(deat,dea,0); - - sprintf(DisaText,"%s %s, %s",opcode[type],seat,deat); - return 0; -} - -// ================ Opcodes 0x0800+ ================ -static int DisaBtstImm(int op) -{ - // Btst/Bchg/Bclr/Bset 00001000 tteeeeee 00 nn (eeeeee=ea, nn=bit number) - int type=0; - char seat[64]="",deat[64]=""; - char *opcode[4]={"btst","bchg","bclr","bset"}; - - type=(op>>6)&3; - DisaGetEa(seat, 0x3c,0); - DisaGetEa(deat,op&0x3f,0); - - sprintf(DisaText,"%s %s, %s",opcode[type],seat,deat); - return 0; -} - -// ================ Opcodes 0x1000+ ================ -static int DisaMove(int op) -{ - // Move 00xxdddD DDssssss (xx=size extension, ssssss=Source EA, DDDddd=Dest ea) - int sea=0,dea=0; - char inst[64]="",seat[64]="",deat[64]=""; - char *movea=""; - int size=0; - - if ((op&0x01c0)==0x0040) movea="a"; // See if it's a movea opcode - - // Find size extension - switch (op&0x3000) - { - case 0x1000: size=0; break; - case 0x3000: size=1; break; - case 0x2000: size=2; break; - default: return 1; - } - - sea = op&0x003f; - DisaGetEa(seat,sea,size); - - dea =(op&0x01c0)>>3; - dea|=(op&0x0e00)>>9; - DisaGetEa(deat,dea,size); - - sprintf(inst,"move%s.%c",movea,Tasm[size]); - sprintf(DisaText,"%s %s, %s",inst,seat,deat); - return 0; -} - -// ================ Opcodes 0x4000+ ================ -static int DisaNeg(int op) -{ - // 01000tt0 xxeeeeee (tt=negx/clr/neg/not, xx=size, eeeeee=EA) - char eat[64]=""; - int type=0,size=0; - char *opcode[4]={"negx","clr","neg","not"}; - - type=(op>>9)&3; - size=(op>>6)&3; if (size>=3) return 1; - DisaGetEa(eat,op&0x3f,size); - - sprintf(DisaText,"%s.%c %s",opcode[type],Tasm[size],eat); - return 0; -} - -// ================ Opcodes 0x40c0+ ================ -static int DisaMoveSr(int op) -{ - // 01000tt0 11eeeeee (tt=type, xx=size, eeeeee=EA) - int type=0,ea=0; - char eat[64]=""; - - type=(op>>9)&3; - ea=op&0x3f; - DisaGetEa(eat,ea,1); - - switch (type) - { - default: sprintf(DisaText,"move sr, %s", eat); break; - case 1: sprintf(DisaText,"move ccr, %s",eat); break; - case 2: sprintf(DisaText,"move %s, ccr",eat); break; - case 3: sprintf(DisaText,"move %s, sr", eat); break; - } - return 0; -} - -static int OpChk(int op) -{ - int sea=0,dea=0; - char seat[64]="",deat[64]=""; - - sea=op&0x003f; - DisaGetEa(seat,sea,0); - - dea=(op>>9)&7; dea|=8; - DisaGetEa(deat,dea,2); - - sprintf(DisaText,"chk %s, %s",seat,deat); - return 0; -} - -// ================ Opcodes 0x41c0+ ================ -static int DisaLea(int op) -{ - // Lea 0100nnn1 11eeeeee (eeeeee=ea) - int sea=0,dea=0; - char seat[64]="",deat[64]=""; - - sea=op&0x003f; - DisaGetEa(seat,sea,0); - - dea=(op>>9)&7; dea|=8; - DisaGetEa(deat,dea,2); - - sprintf(DisaText,"lea %s, %s",seat,deat); - return 0; -} - -static int MakeRegList(char *list,int mask,int ea) -{ - int reverse=0,i=0,low=0,len=0; - - if ((ea&0x38)==0x20) reverse=1; // -(An), bitfield is reversed - - mask&=0xffff; list[0]=0; - - for (i=0;i<17;i++) - { - int bit=0; - - // Mask off bit i: - if (reverse) bit=0x8000>>i; else bit=1<0) if (list[len-1]=='/') list[len-1]=0; - return 0; -} - -// ================ Opcodes 0x4800+ ================ -static int DisaNbcd(int op) -{ - // Nbcd 01001000 00eeeeee (eeeeee=ea) - int ea=0; - char eat[64]=""; - - ea=op&0x003f; - DisaGetEa(eat,ea,0); - - sprintf(DisaText,"nbcd %s",eat); - return 0; -} - -// ================ Opcodes 0x4840+ ================ -static int DisaSwap(int op) -{ - // Swap, 01001000 01000nnn swap Dn - sprintf(DisaText,"swap d%d",op&7); - return 0; -} - -// ================ Opcodes 0x4850+ ================ -static int DisaPea(int op) -{ - // Pea 01001000 01eeeeee (eeeeee=ea) pea - int ea=0; - char eat[64]=""; - - ea=op&0x003f; if (ea<0x10) return 1; // swap opcode - DisaGetEa(eat,ea,2); - - sprintf(DisaText,"pea %s",eat); - return 0; -} - -// ================ Opcodes 0x4880+ ================ -static int DisaExt(int op) -{ - // Ext 01001000 1x000nnn (x=size, eeeeee=EA) - char eat[64]=""; - int size=0; - - size=(op>>6)&1; size++; - DisaGetEa(eat,op&0x3f,size); - - sprintf(DisaText,"ext.%c %s",Tasm[size],eat); - return 0; -} - -// ================ Opcodes 0x4890+ ================ -static int DisaMovem(int op) -{ - // Movem 01001d00 1xeeeeee regmask d=direction, x=size, eeeeee=EA - int dir=0,size=0; - int ea=0,mask=0; - char list[64]="",eat[64]=""; - - dir=(op>>10)&1; - size=((op>>6)&1)+1; - ea=op&0x3f; if (ea<0x10) return 1; // ext opcode - - mask=DisaWord(DisaPc)&0xffff; DisaPc+=2; - - MakeRegList(list,mask,ea); // Turn register mask into text - DisaGetEa(eat,ea,size); - - if (dir) sprintf(DisaText,"movem.%c %s, %s",Tasm[size],eat,list); - else sprintf(DisaText,"movem.%c %s, %s",Tasm[size],list,eat); - return 0; -} - -// ================ Opcodes 0x4e40+ ================ -static int DisaTrap(int op) -{ - sprintf(DisaText,"trap #%d",op&0xf); - return 0; -} - -// ================ Opcodes 0x4e50+ ================ -static int DisaLink(int op) -{ - // Link opcode, 01001110 01010nnn dd link An,#offset - char eat[64]=""; - char offset[32]=""; - - DisaGetEa(eat,(op&7)|8,0); - GetOffset(offset); - - sprintf(DisaText,"link %s,#%s",eat,offset); - - return 0; -} - -// ================ Opcodes 0x4e58+ ================ -static int DisaUnlk(int op) -{ - // Link opcode, 01001110 01011nnn dd unlk An - char eat[64]=""; - - DisaGetEa(eat,(op&7)|8,0); - sprintf(DisaText,"unlk %s",eat); - - return 0; -} - -// ================ Opcodes 0x4e60+ ================ -static int DisaMoveUsp(int op) -{ - // Move USP opcode, 01001110 0110dnnn move An to/from USP (d=direction) - int ea=0,dir=0; - char eat[64]=""; - - dir=(op>>3)&1; - ea=(op&7)|8; - DisaGetEa(eat,ea,0); - - if (dir) sprintf(DisaText,"move usp, %s",eat); - else sprintf(DisaText,"move %s, usp",eat); - return 0; -} - -// ================ Opcodes 0x4e70+ ================ -static int Disa4E70(int op) -{ - char *inst[8]={"reset","nop","stop","rte","rtd","rts","trapv","rtr"}; - int n=0; - - n=op&7; - - sprintf(DisaText,"%s",inst[n]); - - //todo - 'stop' with 16 bit data - - return 0; -} - -// ================ Opcodes 0x4a00+ ================ -static int DisaTst(int op) -{ - // Tst 01001010 xxeeeeee (eeeeee=ea) - int ea=0; - char eat[64]=""; - int size=0; - - ea=op&0x003f; - DisaGetEa(eat,ea,0); - size=(op>>6)&3; if (size>=3) return 1; - - sprintf(DisaText,"tst.%c %s",Tasm[size],eat); - return 0; -} - -static int DisaTas(int op) -{ - // Tas 01001010 11eeeeee (eeeeee=ea) - int ea=0; - char eat[64]=""; - - ea=op&0x003f; - DisaGetEa(eat,ea,0); - - sprintf(DisaText,"tas %s",eat); - return 0; -} - -// ================ Opcodes 0x4e80+ ================ -static int DisaJsr(int op) -{ - // Jsr/Jmp 0100 1110 1mEE Eeee (eeeeee=ea m=1=jmp) - int sea=0; - char seat[64]=""; - - sea=op&0x003f; - DisaGetEa(seat,sea,0); - - sprintf(DisaText,"j%s %s", op&0x40?"mp":"sr", seat); - return 0; -} - -// ================ Opcodes 0x5000+ ================ -static int DisaAddq(int op) -{ - // 0101nnnt xxeeeeee (nnn=#8,1-7 t=addq/subq xx=size, eeeeee=EA) - int num=0,type=0,size=0,ea=0; - char eat[64]=""; - - num =(op>>9)&7; if (num==0) num=8; - type=(op>>8)&1; - size=(op>>6)&3; if (size>=3) return 1; - ea = op&0x3f; - - DisaGetEa(eat,ea,size); - - sprintf(DisaText,"%s.%c #%d, %s",type?"subq":"addq",Tasm[size],num,eat); - return 0; -} - -// ================ Opcodes 0x50c0+ ================ -static int DisaSet(int op) -{ - // 0101cccc 11eeeeee (sxx ea) - static char *cond[16]= - {"t" ,"f", "hi","ls","cc","cs","ne","eq", - "vc","vs","pl","mi","ge","lt","gt","le"}; - char *cc=""; - int ea=0; - char eat[64]=""; - - cc=cond[(op>>8)&0xf]; // Get condition code - ea=op&0x3f; - if ((ea&0x38)==0x08) return 1; // dbra, not scc - - DisaGetEa(eat,ea,0); - sprintf(DisaText,"s%s %s",cc,eat); - return 0; -} - -// ================ Opcodes 0x50c8+ ================ -static int DisaDbra(int op) -{ - // 0101cccc 11001nnn offset (dbra/dbxx Rn,offset) - int dea=0; char deat[64]=""; - int pc=0,Offset=0; - - static char *BraCode[16]= - {"bt" ,"bra","bhi","bls","bcc","bcs","bne","beq", - "bvc","bvs","bpl","bmi","bge","blt","bgt","ble"}; - char *Bra=""; - - dea=op&7; - DisaGetEa(deat,dea,2); - - // Get condition code - Bra=BraCode[(op>>8)&0xf]; - - // Get offset - pc=DisaPc; - Offset=(short)DisaWord(DisaPc); DisaPc+=2; - - sprintf(DisaText,"d%s %s, %x",Bra,deat,pc+Offset); - return 0; -} - -// ================ Opcodes 0x6000+ ================ -static int DisaBranch(int op) -{ - // Branch 0110cccc nn (cccc=condition) - int pc=0,Offset=0; - - static char *BraCode[16]= - {"bra","bsr","bhi","bls","bcc","bcs","bne","beq", - "bvc","bvs","bpl","bmi","bge","blt","bgt","ble"}; - char *Bra=""; - - // Get condition code - Bra=BraCode[(op>>8)&0x0f]; - - // Get offset - pc=DisaPc; - Offset=(char)(op&0xff); - if (Offset== 0) { Offset=(short)DisaWord(DisaPc); DisaPc+=2; } - else if (Offset==-1) { Offset= DisaLong(DisaPc); DisaPc+=4; } - - sprintf(DisaText,"%s %x",Bra,pc+Offset); - return 0; -} - -// ================ Opcodes 0x7000+ ================ -static int DisaMoveq(int op) -{ - // Moveq 0111rrr0 nn (rrr=Dest register, nn=data) - - int dea=0; char deat[64]=""; - char *inst="moveq"; - int val=0; - - dea=(op>>9)&7; - DisaGetEa(deat,dea,2); - - val=(char)(op&0xff); - sprintf(DisaText,"%s #$%x, %s",inst,val,deat); - return 0; -} - -// ================ Opcodes 0x8000+ ================ -static int DisaArithReg(int op) -{ - // 1t0tnnnd xxeeeeee (tt=type:or/sub/and/add xx=size, eeeeee=EA) - int type=0,size=0,dir=0,rea=0,ea=0; - char reat[64]="",eat[64]=""; - char *opcode[]={"or","sub","","","and","add"}; - - type=(op>>12)&5; - rea =(op>> 9)&7; - dir =(op>> 8)&1; - size=(op>> 6)&3; if (size>=3) return 1; - ea = op&0x3f; - - if (dir && ea<0x10) return 1; // addx opcode - - DisaGetEa(reat,rea,size); - DisaGetEa( eat, ea,size); - - if (dir) sprintf(DisaText,"%s.%c %s, %s",opcode[type],Tasm[size],reat,eat); - else sprintf(DisaText,"%s.%c %s, %s",opcode[type],Tasm[size],eat,reat); - return 0; -} - -// ================ Opcodes 0x8100+ ================ -static int DisaAbcd(int op) -{ - // 1t00ddd1 0000asss - sbcd/abcd Ds,Dd or -(As),-(Ad) - int type=0; - int dn=0,addr=0,sn=0; - char *opcode[]={"sbcd","abcd"}; - - type=(op>>14)&1; - dn =(op>> 9)&7; - addr=(op>> 3)&1; - sn = op &7; - - if (addr) sprintf(DisaText,"%s -(a%d), -(a%d)",opcode[type],sn,dn); - else sprintf(DisaText,"%s d%d, d%d", opcode[type],sn,dn); - - return 0; -} - -// ================ Opcodes 0x80c0+ ================ -static int DisaMul(int op) -{ - // Div/Mul: 1m00nnns 11eeeeee (m=Mul, nnn=Register Dn, s=signed, eeeeee=EA) - int type=0,rea=0,sign=0,ea=0,size=1; - char reat[64]="",eat[64]=""; - char *opcode[2]={"div","mul"}; - - type=(op>>14)&1; // div/mul - rea =(op>> 9)&7; - sign=(op>> 8)&1; - ea = op&0x3f; - - DisaGetEa(reat,rea,size); - DisaGetEa( eat, ea,size); - - sprintf(DisaText,"%s%c.%c %s, %s",opcode[type],sign?'s':'u',Tasm[size],eat,reat); - return 0; -} - -// ================ Opcodes 0x90c0+ ================ -static int DisaAritha(int op) -{ - // Suba/Cmpa/Adda 1tt1nnnx 11eeeeee (tt=type, x=size, eeeeee=Source EA) - int type=0,size=0,sea=0,dea=0; - char seat[64]="",deat[64]=""; - char *aritha[4]={"suba","cmpa","adda",""}; - - type=(op>>13)&3; if (type>=3) return 1; - size=(op>>8)&1; size++; - dea =(op>>9)&7; dea|=8; // Dest=An - sea = op&0x003f; // Source - - DisaGetEa(seat,sea,size); - DisaGetEa(deat,dea,size); - - sprintf(DisaText,"%s.%c %s, %s",aritha[type],Tasm[size],seat,deat); - return 0; -} - -// ================ Opcodes 0xb000+ ================ -static int DisaCmpEor(int op) -{ - // Cmp/Eor 1011rrrt xxeeeeee (rrr=Dn, t=cmp/eor, xx=size extension, eeeeee=ea) - char reat[64]="",eat[64]=""; - int type=0,size=0; - - type=(op>>8)&1; - size=(op>>6)&3; if (size>=3) return 1; - DisaGetEa(reat,(op>>9)&7,size); - DisaGetEa(eat, op&0x3f, size); - - if (type) sprintf(DisaText,"eor.%c %s, %s",Tasm[size],reat,eat); - else sprintf(DisaText,"cmp.%c %s, %s",Tasm[size],eat,reat); - return 0; -} - -static int DisaCmpm(int op) -{ - char seat[64]="",deat[64]=""; - int type=0,size=0,sea,dea; - - type=(op>>8)&1; - size=(op>>6)&3; if (size>=3) return 1; - sea=(op&7)|0x18; - dea=(op>>9)&0x3f; - DisaGetEa(seat,sea,size); - DisaGetEa(deat,dea,size); - - sprintf(DisaText,"cmpm.%c %s, %s",Tasm[size],seat,deat); - return 0; -} - - -// ================ Opcodes 0xc140+ ================ -// 1100ttt1 01000sss exg ds,dt -// 1100ttt1 01001sss exg as,at -// 1100ttt1 10001sss exg as,dt -static int DisaExg(int op) -{ - int tr=0,type=0,sr=0; - - tr =(op>>9)&7; - type= op&0xf8; - sr = op&7; - - if (type==0x40) sprintf(DisaText,"exg d%d, d%d",sr,tr); - else if (type==0x48) sprintf(DisaText,"exg a%d, a%d",sr,tr); - else if (type==0x88) sprintf(DisaText,"exg a%d, d%d",sr,tr); - else return 1; - - return 0; -} - -// ================ Opcodes 0xd100+ ================ -static int DisaAddx(int op) -{ - // 1t01ddd1 xx000sss addx - int type=0,size=0,dea=0,sea=0,mem; - char deat[64]="",seat[64]=""; - char *opcode[6]={"","subx","","","","addx"}; - - type=(op>>12)&5; - dea =(op>> 9)&7; - size=(op>> 6)&3; if (size>=3) return 1; - sea = op&7; - mem = op&8; - if(mem) { sea+=0x20; dea+=0x20; } - - DisaGetEa(deat,dea,size); - DisaGetEa(seat,sea,size); - - sprintf(DisaText,"%s.%c %s, %s",opcode[type],Tasm[size],seat,deat); - return 0; -} - -// ================ Opcodes 0xe000+ ================ -static char *AsrName[4]={"as","ls","rox","ro"}; -static int DisaAsr(int op) -{ - // Asr/l/Ror/l etc - 1110cccd xxuttnnn - // (ccc=count, d=direction xx=size extension, u=use reg for count, tt=type, nnn=register Dn) - int count=0,dir=0,size=0,usereg=0,type=0,num=0; - - count =(op>>9)&7; - dir =(op>>8)&1; - size =(op>>6)&3; if (size>=3) return 1; // todo Asr EA - usereg=(op>>5)&1; - type =(op>>3)&3; - num = op &7; // Register number - - if (usereg==0) count=((count-1)&7)+1; // because ccc=000 means 8 - - sprintf(DisaText,"%s%c.%c %c%d, d%d", - AsrName[type], dir?'l':'r', Tasm[size], - usereg?'d':'#', count, num); - return 0; -} - -static int DisaAsrEa(int op) -{ - // Asr/l/Ror/l etc EA - 11100ttd 11eeeeee - int type=0,dir=0,size=1; - char eat[64]=""; - - type=(op>>9)&3; - dir =(op>>8)&1; - DisaGetEa(eat,op&0x3f,size); - - sprintf(DisaText,"%s%c.w %s", AsrName[type], dir?'l':'r', eat); - return 0; -} - -// ================================================================= - -static int TryOp(int op) -{ - if ((op&0xf100)==0x0000) DisaArithImm(op); // Ori/And/Sub/Add/Eor/Cmp Immediate - if ((op&0xf5bf)==0x003c) DisaArithSr(op); // Ori/Andi/Eori $nnnn,sr - if ((op&0xf100)==0x0100) DisaBtstReg(op); - if ((op&0xf138)==0x0108) DisaMovep(op); - if ((op&0xff00)==0x0800) DisaBtstImm(op); // Btst/Bchg/Bclr/Bset - if ((op&0xc000)==0x0000) DisaMove(op); - if ((op&0xf900)==0x4000) DisaNeg(op); // Negx/Clr/Neg/Not - if ((op&0xf140)==0x4100) OpChk(op); - if ((op&0xf1c0)==0x41c0) DisaLea(op); - if ((op&0xf9c0)==0x40c0) DisaMoveSr(op); - if ((op&0xffc0)==0x4800) DisaNbcd(op); - if ((op&0xfff8)==0x4840) DisaSwap(op); - if ((op&0xffc0)==0x4840) DisaPea(op); - if ((op&0xffb8)==0x4880) DisaExt(op); - if ((op&0xfb80)==0x4880) DisaMovem(op); - if ((op&0xff00)==0x4a00) DisaTst(op); - if ((op&0xffc0)==0x4ac0) DisaTas(op); - if ((op&0xfff0)==0x4e40) DisaTrap(op); - if ((op&0xfff8)==0x4e50) DisaLink(op); - if ((op&0xfff8)==0x4e58) DisaUnlk(op); - if ((op&0xfff0)==0x4e60) DisaMoveUsp(op); - if ((op&0xfff8)==0x4e70) Disa4E70(op); - if ((op&0xff80)==0x4e80) DisaJsr(op); - if ((op&0xf000)==0x5000) DisaAddq(op); - if ((op&0xf0c0)==0x50c0) DisaSet(op); - if ((op&0xf0f8)==0x50c8) DisaDbra(op); - if ((op&0xf000)==0x6000) DisaBranch(op); - if ((op&0xa000)==0x8000) DisaArithReg(op); // Or/Sub/And/Add - if ((op&0xb1f0)==0x8100) DisaAbcd(op); - if ((op&0xb130)==0x9100) DisaAddx(op); - if ((op&0xb0c0)==0x80c0) DisaMul(op); - if ((op&0xf100)==0x7000) DisaMoveq(op); - if ((op&0x90c0)==0x90c0) DisaAritha(op); - if ((op&0xf000)==0xb000) DisaCmpEor(op); - if ((op&0xf138)==0xb108) DisaCmpm(op); - if ((op&0xf130)==0xc100) DisaExg(op); - if ((op&0xf000)==0xe000) DisaAsr(op); - if ((op&0xf8c0)==0xe0c0) DisaAsrEa(op); - - // Unknown opcoode - return 0; -} - -int DisaGet() -{ - int op=0; - if (DisaWord==NULL) return 1; - - Comment[0]=0; - DisaText[0]=0; // Assume opcode unknown - - op=DisaWord(DisaPc)&0xffff; DisaPc+=2; - TryOp(op); - strcat(DisaText,Comment); - - // Unknown opcoode - return 0; -} diff --git a/cpu/Cyclone/Disa/Disa.h b/cpu/Cyclone/Disa/Disa.h deleted file mode 100644 index 1ef18fc..0000000 --- a/cpu/Cyclone/Disa/Disa.h +++ /dev/null @@ -1,18 +0,0 @@ - -// Dave's Disa 68000 Disassembler - -#ifdef __cplusplus -extern "C" { -#endif - -extern unsigned int DisaPc; -extern char *DisaText; // Text buffer to write in - -extern unsigned short (*DisaWord)(unsigned int a); -int DisaGetEa(char *t,int ea,int size); - -int DisaGet(); - -#ifdef __cplusplus -} // End of extern "C" -#endif diff --git a/cpu/Cyclone/Ea.cpp b/cpu/Cyclone/Ea.cpp deleted file mode 100644 index 4be33e1..0000000 --- a/cpu/Cyclone/Ea.cpp +++ /dev/null @@ -1,493 +0,0 @@ - -#include "app.h" - -int earead_check_addrerr = 1, eawrite_check_addrerr = 0; - -// some ops use non-standard cycle counts for EAs, so are listed here. -// all constants borrowed from the MUSASHI core by Karl Stenerud. - -/* Extra cycles for JMP instruction (000, 010) */ -int g_jmp_cycle_table[8] = -{ - 4, /* EA_MODE_AI */ - 6, /* EA_MODE_DI */ - 10, /* EA_MODE_IX */ - 6, /* EA_MODE_AW */ - 8, /* EA_MODE_AL */ - 6, /* EA_MODE_PCDI */ - 10, /* EA_MODE_PCIX */ - 0, /* EA_MODE_I */ -}; - -/* Extra cycles for JSR instruction (000, 010) */ -int g_jsr_cycle_table[8] = -{ - 4, /* EA_MODE_AI */ - 6, /* EA_MODE_DI */ - 10, /* EA_MODE_IX */ - 6, /* EA_MODE_AW */ - 8, /* EA_MODE_AL */ - 6, /* EA_MODE_PCDI */ - 10, /* EA_MODE_PCIX */ - 0, /* EA_MODE_I */ -}; - -/* Extra cycles for LEA instruction (000, 010) */ -int g_lea_cycle_table[8] = -{ - 4, /* EA_MODE_AI */ - 8, /* EA_MODE_DI */ - 12, /* EA_MODE_IX */ - 8, /* EA_MODE_AW */ - 12, /* EA_MODE_AL */ - 8, /* EA_MODE_PCDI */ - 12, /* EA_MODE_PCIX */ - 0, /* EA_MODE_I */ -}; - -/* Extra cycles for PEA instruction (000, 010) */ -int g_pea_cycle_table[8] = -{ - 6, /* EA_MODE_AI */ - 10, /* EA_MODE_DI */ - 14, /* EA_MODE_IX */ - 10, /* EA_MODE_AW */ - 14, /* EA_MODE_AL */ - 10, /* EA_MODE_PCDI */ - 14, /* EA_MODE_PCIX */ - 0, /* EA_MODE_I */ -}; - -/* Extra cycles for MOVEM instruction (000, 010) */ -int g_movem_cycle_table[8] = -{ - 0, /* EA_MODE_AI */ - 4, /* EA_MODE_DI */ - 6, /* EA_MODE_IX */ - 4, /* EA_MODE_AW */ - 8, /* EA_MODE_AL */ - 0, /* EA_MODE_PCDI */ - 0, /* EA_MODE_PCIX */ - 0, /* EA_MODE_I */ -}; - -// add nonstandard EA -int Ea_add_ns(int *tab, int ea) -{ - if(ea<0x10) return 0; - if((ea&0x38)==0x10) return tab[0]; // (An) (ai) - if(ea<0x28) return 0; - if(ea<0x30) return tab[1]; // ($nn,An) (di) - if(ea<0x38) return tab[2]; // ($nn,An,Rn) (ix) - if(ea==0x38) return tab[3]; // (aw) - if(ea==0x39) return tab[4]; // (al) - if(ea==0x3a) return tab[5]; // ($nn,PC) (pcdi) - if(ea==0x3b) return tab[6]; // ($nn,pc,Rn) (pcix) - if(ea==0x3c) return tab[7]; // #$nnnn (i) - return 0; -} - - -// --------------------------------------------------------------------------- -// Gets the offset of a register for an ea, and puts it in 'r' -// Shifted left by 'shift' -// Doesn't trash anything -static int EaCalcReg(int r,int ea,int mask,int forceor,int shift,int noshift=0) -{ - int i=0,low=0,needor=0; - int lsl=0; - - for (i=mask|0x8000; (i&1)==0; i>>=1) low++; // Find out how high up the EA mask is - mask&=0xf<=8) - { - needor=1; // Need to OR to access A0-7 - if ((g_op>>low)&8) { needor=0; mask|=8<0) ot("lsl #%d\n", lsl); - else ot("lsr #%d\n",-lsl); - } - - return 0; -} - -// EaCalc - ARM Register 'a' = Effective Address -// If ea>=0x10, trashes r0,r2 and r3, else nothing -// size values 0, 1, 2 ~ byte, word, long -// mask shows usable bits in r8 -int EaCalc(int a,int mask,int ea,int size,int top,int sign_extend) -{ - char text[32]=""; - int func=0; - - DisaPc=2; DisaGetEa(text,ea,size); // Get text version of the effective address - func=0x68+(size<<2); // Get correct read handler - - if (ea<0x10) - { - int noshift=0; - if (size>=2||(size==0&&(top||!sign_extend))) noshift=1; // Saves one opcode - - ot(";@ EaCalc : Get register index into r%d:\n",a); - - EaCalcReg(a,ea,mask,0,2,noshift); - return 0; - } - - ot(";@ EaCalc : Get '%s' into r%d:\n",text,a); - // (An), (An)+, -(An) - if (ea<0x28) - { - int step=1<>=1) low++; // Find out how high up the EA mask is - lsl=2-low; // Having a lsl #x here saves one opcode - if (lsl>=0) ot(" ldr r%d,[r7,r2,lsl #%i]\n",a,lsl); - else if (lsl<0) ot(" ldr r%d,[r7,r2,lsr #%i]\n",a,-lsl); - } - - if ((ea&0x38)==0x18) // (An)+ - { - ot(" add r3,r%d,#%d ;@ Post-increment An\n",a,step); - strr=3; - } - - if ((ea&0x38)==0x20) // -(An) - ot(" sub r%d,r%d,#%d ;@ Pre-decrement An\n",a,a,step); - - if ((ea&0x38)==0x18||(ea&0x38)==0x20) - { - if (ea==0x1f||ea==0x27) - { - ot(" str r%d,[r7,#0x3c] ;@ A7\n",strr); - } - else - { - if (lsl>=0) ot(" str r%d,[r7,r2,lsl #%i]\n",strr,lsl); - else if (lsl<0) ot(" str r%d,[r7,r2,lsr #%i]\n",strr,-lsl); - } - } - - if ((ea&0x38)==0x20) Cycles+=size<2 ? 6:10; // -(An) Extra cycles - else Cycles+=size<2 ? 4:8; // (An),(An)+ Extra cycles - return 0; - } - - if (ea<0x30) // ($nn,An) (di) - { - ot(" ldrsh r0,[r4],#2 ;@ Fetch offset\n"); pc_dirty=1; - EaCalcReg(2,8,mask,0,0); - ot(" ldr r2,[r7,r2,lsl #2]\n"); - ot(" add r%d,r0,r2 ;@ Add on offset\n",a); - Cycles+=size<2 ? 8:12; // Extra cycles - return 0; - } - - if (ea<0x38) // ($nn,An,Rn) (ix) - { - ot(";@ Get extension word into r3:\n"); - ot(" ldrh r3,[r4],#2 ;@ ($Disp,PC,Rn)\n"); pc_dirty=1; - ot(" mov r2,r3,lsr #10\n"); - ot(" tst r3,#0x0800 ;@ Is Rn Word or Long\n"); - ot(" and r2,r2,#0x3c ;@ r2=Index of Rn\n"); - ot(" ldreqsh r2,[r7,r2] ;@ r2=Rn.w\n"); - ot(" ldrne r2,[r7,r2] ;@ r2=Rn.l\n"); - ot(" mov r0,r3,asl #24 ;@ r0=Get 8-bit signed Disp\n"); - ot(" add r3,r2,r0,asr #24 ;@ r3=Disp+Rn\n"); - - EaCalcReg(2,8,mask,1,0); - ot(" ldr r2,[r7,r2,lsl #2]\n"); - ot(" add r%d,r2,r3 ;@ r%d=Disp+An+Rn\n",a,a); - Cycles+=size<2 ? 10:14; // Extra cycles - return 0; - } - - if (ea==0x38) // (aw) - { - ot(" ldrsh r%d,[r4],#2 ;@ Fetch Absolute Short address\n",a); pc_dirty=1; - Cycles+=size<2 ? 8:12; // Extra cycles - return 0; - } - - if (ea==0x39) // (al) - { - ot(" ldrh r2,[r4],#2 ;@ Fetch Absolute Long address\n"); - ot(" ldrh r0,[r4],#2\n"); pc_dirty=1; - ot(" orr r%d,r0,r2,lsl #16\n",a); - Cycles+=size<2 ? 12:16; // Extra cycles - return 0; - } - - if (ea==0x3a) // ($nn,PC) (pcdi) - { - ot(" ldr r0,[r7,#0x60] ;@ Get Memory base\n"); - ot(" sub r0,r4,r0 ;@ Real PC\n"); - ot(" ldrsh r2,[r4],#2 ;@ Fetch extension\n"); pc_dirty=1; - ot(" mov r0,r0,lsl #8\n"); - ot(" add r%d,r2,r0,asr #8 ;@ ($nn,PC)\n",a); - Cycles+=size<2 ? 8:12; // Extra cycles - return 0; - } - - if (ea==0x3b) // ($nn,pc,Rn) (pcix) - { - ot(" ldr r0,[r7,#0x60] ;@ Get Memory base\n"); - ot(" ldrh r3,[r4] ;@ Get extension word\n"); - ot(" sub r0,r4,r0 ;@ r0=PC\n"); - ot(" add r4,r4,#2\n"); pc_dirty=1; - ot(" mov r0,r0,asl #8 ;@ use only 24bits of PC\n"); - ot(" mov r2,r3,lsr #10\n"); - ot(" tst r3,#0x0800 ;@ Is Rn Word or Long\n"); - ot(" and r2,r2,#0x3c ;@ r2=Index of Rn\n"); - ot(" ldreqsh r2,[r7,r2] ;@ r2=Rn.w\n"); - ot(" ldrne r2,[r7,r2] ;@ r2=Rn.l\n"); - ot(" mov r3,r3,asl #24 ;@ r3=Get 8-bit signed Disp\n"); - ot(" add r2,r2,r3,asr #24 ;@ r2=Disp+Rn\n"); - ot(" add r%d,r2,r0,asr #8 ;@ r%d=Disp+PC+Rn\n",a,a); - Cycles+=size<2 ? 10:14; // Extra cycles - return 0; - } - - if (ea==0x3c) // #$nnnn (i) - { - if (size<2) - { - ot(" ldr%s r%d,[r4],#2 ;@ Fetch immediate value\n",Sarm[size&3],a); pc_dirty=1; - Cycles+=4; // Extra cycles - return 0; - } - - ot(" ldrh r2,[r4],#2 ;@ Fetch immediate value\n"); - ot(" ldrh r3,[r4],#2\n"); pc_dirty=1; - ot(" orr r%d,r3,r2,lsl #16\n",a); - Cycles+=8; // Extra cycles - return 0; - } - - return 1; -} - -// --------------------------------------------------------------------------- -// Read effective address in (ARM Register 'a') to ARM register 'v' -// 'a' and 'v' can be anything but 0 is generally best (for both) -// If (ea<0x10) nothing is trashed, else r0-r3 is trashed -// If 'top' is given, the ARM register v shifted to the top, e.g. 0xc000 -> 0xc0000000 -// If top is 0 and sign_extend is not, then ARM register v is sign extended, -// e.g. 0xc000 -> 0xffffc000 (else it may or may not be sign extended) - -int EaRead(int a,int v,int ea,int size,int mask,int top,int sign_extend) -{ - char text[32]=""; - int shift=0; - - shift=32-(8<=2||(size==0&&(top||!sign_extend))) { - if(mask) - for (i=mask|0x8000; (i&1)==0; i>>=1) low++; // Find out how high up the EA mask is - lsl=2-low; // Having a lsl #2 here saves one opcode - } - - if (top||!sign_extend) nsarm=3; - - ot(";@ EaRead : Read register[r%d] into r%d:\n",a,v); - - if (lsl>0) ot(" ldr%s r%d,[r7,r%d,lsl #%i]\n",Narm[nsarm],v,a,lsl); - else if (lsl<0) ot(" ldr%s r%d,[r7,r%d,lsr #%i]\n",Narm[nsarm],v,a,-lsl); - else ot(" ldr%s r%d,[r7,r%d]\n",Sarm[nsarm],v,a); - - if (top&&shift) ot(" mov r%d,r%d,asl #%d\n",v,v,shift); - - ot("\n"); return 0; - } - - ot(";@ EaRead : Read '%s' (address in r%d) into r%d:\n",text,a,v); - - if (ea==0x3c) - { - int asl=0; - - if (top) asl=shift; - - if (asl) ot(" mov r%d,r%d,asl #%d\n",v,a,asl); - else if (v!=a) ot(" mov r%d,r%d\n",v,a); - ot("\n"); return 0; - } - - if (ea>=0x3a && ea<=0x3b) MemHandler(2,size,a,earead_check_addrerr); // Fetch - else MemHandler(0,size,a,earead_check_addrerr); // Read - - // defaults to 1, as most things begins with a read - earead_check_addrerr=1; - - if (sign_extend) - { - int d_reg=0; - if (shift) { - ot(" mov r%d,r%d,asl #%d\n",v,d_reg,shift); - d_reg=v; - } - if (!top && shift) { - ot(" mov r%d,r%d,asr #%d\n",v,d_reg,shift); - d_reg=v; - } - if (d_reg != v) - ot(" mov r%d,r%d\n",v,d_reg); - } - else - { - if (top && shift) - ot(" mov r%d,r0,asl #%d\n",v,shift); - else if (v!=0) - ot(" mov r%d,r0\n",v); - } - - ot("\n"); return 0; -} - -// calculate EA and read -// if (ea < 0x10) nothing is trashed -// if (ea == 0x3c) r2 and r3 are trashed -// else r0-r3 are trashed -// size values 0, 1, 2 ~ byte, word, long -// r_ea is reg to store ea in (-1 means ea is not needed), r is dst reg -// if sign_extend is 0, non-32bit values will have MS bits undefined -int EaCalcRead(int r_ea,int r,int ea,int size,int mask,int sign_extend) -{ - if (ea<0x10) - { - if (r_ea==-1) - { - r_ea=r; - if (!sign_extend) size=2; - } - } - else if (ea==0x3c) // #imm - { - r_ea=r; - } - else - { - if (r_ea==-1) r_ea=0; - } - - EaCalc (r_ea,mask,ea,size,0,sign_extend); - EaRead (r_ea, r,ea,size,mask,0,sign_extend); - - return 0; -} - -int EaCalcReadNoSE(int r_ea,int r,int ea,int size,int mask) -{ - return EaCalcRead(r_ea,r,ea,size,mask,0); -} - -// Return 1 if we can read this ea -int EaCanRead(int ea,int size) -{ - if (size<0) - { - // LEA: - // These don't make sense?: - if (ea< 0x10) return 0; // Register - if (ea==0x3c) return 0; // Immediate - if (ea>=0x18 && ea<0x28) return 0; // Pre/Post inc/dec An - } - - if (ea<=0x3c) return 1; - return 0; -} - -// --------------------------------------------------------------------------- -// Write effective address (ARM Register 'a') with ARM register 'v' -// Trashes r0-r3,r12,lr; 'a' can be 0 or 2+, 'v' can be 1 or higher -// If a==0 and v==1 it's faster though. -int EaWrite(int a,int v,int ea,int size,int mask,int top,int sign_extend_ea) -{ - char text[32]=""; - int shift=0; - - if(a == 1) { printf("Error! EaWrite a==1 !\n"); return 1; } - - if (top) shift=32-(8<=2||(size==0&&(top||!sign_extend_ea))) { - if(mask) - for (i=mask|0x8000; (i&1)==0; i>>=1) low++; // Find out how high up the EA mask is - lsl=2-low; // Having a lsl #x here saves one opcode - } - - ot(";@ EaWrite: r%d into register[r%d]:\n",v,a); - if (shift) ot(" mov r%d,r%d,asr #%d\n",v,v,shift); - - if (lsl>0) ot(" str%s r%d,[r7,r%d,lsl #%i]\n",Narm[size&3],v,a,lsl); - else if (lsl<0) ot(" str%s r%d,[r7,r%d,lsr #%i]\n",Narm[size&3],v,a,-lsl); - else ot(" str%s r%d,[r7,r%d]\n",Narm[size&3],v,a); - - ot("\n"); return 0; - } - - ot(";@ EaWrite: Write r%d into '%s' (address in r%d):\n",v,text,a); - - if (ea==0x3c) { ot("Error! Write EA=0x%x\n\n",ea); return 1; } - - if (shift) ot(" mov r1,r%d,asr #%d\n",v,shift); - else if (v!=1) ot(" mov r1,r%d\n",v); - - MemHandler(1,size,a,eawrite_check_addrerr); // Call write handler - - // not check by default, because most cases are rmw and - // address was already checked before reading - eawrite_check_addrerr = 0; - - ot("\n"); return 0; -} - -// Return 1 if we can write this ea -int EaCanWrite(int ea) -{ - if (ea<=0x39) return 1; // 3b? - return 0; -} -// --------------------------------------------------------------------------- - -// Return 1 if EA is An reg -int EaAn(int ea) -{ - if((ea&0x38)==8) return 1; - return 0; -} - diff --git a/cpu/Cyclone/Main.cpp b/cpu/Cyclone/Main.cpp deleted file mode 100644 index 8f00bb1..0000000 --- a/cpu/Cyclone/Main.cpp +++ /dev/null @@ -1,1298 +0,0 @@ - -#include "app.h" - -static FILE *AsmFile=NULL; - -static int CycloneVer=0x0099; // Version number of library -int *CyJump=NULL; // Jump table -int ms=USE_MS_SYNTAX; // If non-zero, output in Microsoft ARMASM format -const char * const Narm[4]={ "b", "h","",""}; // Normal ARM Extensions for operand sizes 0,1,2 -const char * const Sarm[4]={"sb","sh","",""}; // Sign-extend ARM Extensions for operand sizes 0,1,2 -int Cycles; // Current cycles for opcode -int pc_dirty; // something changed PC during processing -int arm_op_count; - -// opcodes often used by games -static const unsigned short hot_opcodes[] = { - 0x6701, // beq $3 - 0x6601, // bne $3 - 0x51c8, // dbra Dn, $2 - 0x4a38, // tst.b $0.w - 0xd040, // add.w Dn, Dn - 0x4a79, // tst.w $0.l - 0x0240, // andi.w #$0, D0 - 0x2038, // move.l $0.w, D0 - 0xb0b8, // cmp.l $0.w, D0 - 0x6001, // bra $3 - 0x30c0, // move.w D0, (A0)+ - 0x3028, // move.w ($0,A0), D0 - 0x0c40, // cmpi.w #$0, D0 - 0x0c79, // cmpi.w #$0, $0.l - 0x4e75, // rts - 0x4e71, // nop - 0x3000, // move.w D0, D0 - 0x0839, // btst #$0, $0.l - 0x7000, // moveq #$0, D0 - 0x3040, // movea.w D0, A0 - 0x0838, // btst #$0, $0.w - 0x4a39, // tst.b $0.l - 0x33d8, // move.w (A0)+, $0.l - 0x6700, // beq $2 - 0xb038, // cmp.b $0.w, D0 - 0x3039, // move.w $0.l, D0 - 0x4840, // swap D0 - 0x6101, // bsr $3 - 0x6100, // bsr $2 - 0x5e40, // addq.w #7, D0 - 0x1039, // move.b $0.l, D0 - 0x20c0, // move.l D0, (A0)+ - 0x1018, // move.b (A0)+, D0 - 0x30d0, // move.w (A0), (A0)+ - 0x3080, // move.w D0, (A0) - 0x3018, // move.w (A0)+, D0 - 0xc040, // and.w D0, D0 - 0x3180, // move.w D0, (A0,D0.w) - 0x1198, // move.b (A0)+, (A0,D0.w) - 0x6501, // bcs $3 - 0x6500, // bcs $2 - 0x6401, // bcc $3 - 0x6a01, // bpl $3 - 0x41f0, // lea (A0,D0.w), A0 - 0x4a28, // tst.b ($0,A0) - 0x0828, // btst #$0, ($0,A0) - 0x0640, // addi.w #$0, D0 - 0x10c0, // move.b D0, (A0)+ - 0x10d8, // move.b (A0)+, (A0)+ -}; -#define hot_opcode_count (int)(sizeof(hot_opcodes) / sizeof(hot_opcodes[0])) - -static int is_op_hot(int op) -{ - int i; - for (i = 0; i < hot_opcode_count; i++) - if (op == hot_opcodes[i]) - return 1; - return 0; -} - -void ot(const char *format, ...) -{ - va_list valist; - int i, len; - - // notaz: stop me from leaving newlines in the middle of format string - // and generating bad code - for(i=0, len=strlen(format); i < len && format[i] != '\n'; i++); - if(i < len-1 && format[len-1] != '\n') printf("\nWARNING: possible improper newline placement:\n%s\n", format); - - if (format[0] == ' ' && format[1] == ' ' && format[2] != ' ' && format[2] != '.') - arm_op_count++; - - va_start(valist,format); - if (AsmFile) vfprintf(AsmFile,format,valist); - va_end(valist); -} - -void ltorg() -{ - if (ms) ot(" LTORG\n"); - else ot(" .ltorg\n"); -} - -#if (CYCLONE_FOR_GENESIS == 2) -// r12=ptr to tas in table, trashes r0,r1 -static void ChangeTAS(int norm) -{ - ot(" ldr r0,=Op4ad0%s\n",norm?"_":""); - ot(" mov r1,#8\n"); - ot("setrtas_loop%i0%s ;@ 4ad0-4ad7\n",norm,ms?"":":"); - ot(" subs r1,r1,#1\n"); - ot(" str r0,[r12],#4\n"); - ot(" bne setrtas_loop%i0\n",norm); - ot(" ldr r0,=Op4ad8%s\n",norm?"_":""); - ot(" mov r1,#7\n"); - ot("setrtas_loop%i1%s ;@ 4ad8-4ade\n",norm,ms?"":":"); - ot(" subs r1,r1,#1\n"); - ot(" str r0,[r12],#4\n"); - ot(" bne setrtas_loop%i1\n",norm); - ot(" ldr r0,=Op4adf%s\n",norm?"_":""); - ot(" str r0,[r12],#4\n"); - ot(" ldr r0,=Op4ae0%s\n",norm?"_":""); - ot(" mov r1,#7\n"); - ot("setrtas_loop%i2%s ;@ 4ae0-4ae6\n",norm,ms?"":":"); - ot(" subs r1,r1,#1\n"); - ot(" str r0,[r12],#4\n"); - ot(" bne setrtas_loop%i2\n",norm); - ot(" ldr r0,=Op4ae7%s\n",norm?"_":""); - ot(" str r0,[r12],#4\n"); - ot(" ldr r0,=Op4ae8%s\n",norm?"_":""); - ot(" mov r1,#8\n"); - ot("setrtas_loop%i3%s ;@ 4ae8-4aef\n",norm,ms?"":":"); - ot(" subs r1,r1,#1\n"); - ot(" str r0,[r12],#4\n"); - ot(" bne setrtas_loop%i3\n",norm); - ot(" ldr r0,=Op4af0%s\n",norm?"_":""); - ot(" mov r1,#8\n"); - ot("setrtas_loop%i4%s ;@ 4af0-4af7\n",norm,ms?"":":"); - ot(" subs r1,r1,#1\n"); - ot(" str r0,[r12],#4\n"); - ot(" bne setrtas_loop%i4\n",norm); - ot(" ldr r0,=Op4af8%s\n",norm?"_":""); - ot(" str r0,[r12],#4\n"); - ot(" ldr r0,=Op4af9%s\n",norm?"_":""); - ot(" str r0,[r12],#4\n"); -} -#endif - -#if EMULATE_ADDRESS_ERRORS_JUMP || EMULATE_ADDRESS_ERRORS_IO -static void AddressErrorWrapper(char rw, const char *dataprg, int iw) -{ - ot("ExceptionAddressError_%c_%s%s\n", rw, dataprg, ms?"":":"); - ot(" ldr r1,[r7,#0x44]\n"); - ot(" mov r6,#0x%02x\n", iw); - ot(" mov r11,r0\n"); - ot(" tst r1,#0x20\n"); - ot(" orrne r6,r6,#4\n"); - ot(" b ExceptionAddressError\n"); - ot("\n"); -} -#endif - -void FlushPC(void) -{ -#if MEMHANDLERS_NEED_PC - if (pc_dirty) - ot(" str r4,[r7,#0x40] ;@ Save PC\n"); -#endif - pc_dirty = 0; -} - -static void PrintFramework() -{ - int state_flags_to_check = 1; // stopped -#if EMULATE_TRACE - state_flags_to_check |= 2; // tracing -#endif -#if EMULATE_HALT - state_flags_to_check |= 0x10; // halted -#endif - - ot(";@ --------------------------- Framework --------------------------\n"); - if (ms) ot("CycloneRun\n"); - else ot("CycloneRun:\n"); - - ot(" stmdb sp!,{r4-r8,r10,r11,lr}\n"); - - ot(" mov r7,r0 ;@ r7 = Pointer to Cpu Context\n"); - ot(" ;@ r0-3 = Temporary registers\n"); - ot(" ldrb r10,[r7,#0x46] ;@ r10 = Flags (NZCV)\n"); - ot(" ldr r6,=CycloneJumpTab ;@ r6 = Opcode Jump table\n"); - ot(" ldr r5,[r7,#0x5c] ;@ r5 = Cycles\n"); - ot(" ldr r4,[r7,#0x40] ;@ r4 = Current PC + Memory Base\n"); - ot(" ;@ r8 = Current Opcode\n"); - ot(" ldr r1,[r7,#0x44] ;@ Get SR high T_S__III and irq level\n"); - ot(" mov r10,r10,lsl #28;@ r10 = Flags 0xf0000000, cpsr format\n"); - ot(" ;@ r11 = Source value / Memory Base\n"); - ot(" str r6,[r7,#0x54] ;@ make a copy to avoid literal pools\n"); - ot("\n"); -#if (CYCLONE_FOR_GENESIS == 2) || EMULATE_TRACE - ot(" mov r2,#0\n"); - ot(" str r2,[r7,#0x98] ;@ clear custom CycloneEnd\n"); -#endif - ot(";@ CheckInterrupt:\n"); - ot(" movs r0,r1,lsr #24 ;@ Get IRQ level\n"); // same as ldrb r0,[r7,#0x47] - ot(" beq NoInts0\n"); - ot(" cmp r0,#6 ;@ irq>6 ?\n"); - ot(" andle r1,r1,#7 ;@ Get interrupt mask\n"); - ot(" cmple r0,r1 ;@ irq<=6: Is irq<=mask ?\n"); - ot(" bgt CycloneDoInterrupt\n"); - ot("NoInts0%s\n", ms?"":":"); - ot("\n"); - ot(";@ Check if our processor is in special state\n"); - ot(";@ and jump to opcode handler if not\n"); - ot(" ldr r0,[r7,#0x58] ;@ state_flags\n"); - ot(" ldrh r8,[r4],#2 ;@ Fetch first opcode\n"); - ot(" tst r0,#0x%02x ;@ special state?\n", state_flags_to_check); - ot(" ldreq pc,[r6,r8,asl #2] ;@ Jump to opcode handler\n"); - ot("\n"); - ot("CycloneSpecial%s\n", ms?"":":"); -#if EMULATE_TRACE - ot(" tst r0,#2 ;@ tracing?\n"); - ot(" bne CycloneDoTrace\n"); -#endif - ot(";@ stopped or halted\n"); - ot(" mov r5,#0\n"); - ot(" str r5,[r7,#0x5C] ;@ eat all cycles\n"); - ot(" ldmia sp!,{r4-r8,r10,r11,pc} ;@ we are stopped, do nothing!\n"); - ot("\n"); - ot("\n"); - - ot(";@ We come back here after execution\n"); - ot("CycloneEnd%s\n", ms?"":":"); - ot(" sub r4,r4,#2\n"); - ot("CycloneEndNoBack%s\n", ms?"":":"); -#if (CYCLONE_FOR_GENESIS == 2) || EMULATE_TRACE - ot(" ldr r1,[r7,#0x98]\n"); - ot(" mov r10,r10,lsr #28\n"); - ot(" tst r1,r1\n"); - ot(" bxne r1 ;@ jump to alternative CycloneEnd\n"); -#else - ot(" mov r10,r10,lsr #28\n"); -#endif - ot(" str r4,[r7,#0x40] ;@ Save Current PC + Memory Base\n"); - ot(" str r5,[r7,#0x5c] ;@ Save Cycles\n"); - ot(" strb r10,[r7,#0x46] ;@ Save Flags (NZCV)\n"); - ot(" ldmia sp!,{r4-r8,r10,r11,pc}\n"); - ltorg(); - ot("\n"); - ot("\n"); - - ot("CycloneInit%s\n", ms?"":":"); -#if COMPRESS_JUMPTABLE - ot(";@ decompress jump table\n"); - ot(" ldr r12,=CycloneJumpTab\n"); - ot(" add r0,r12,#0xe000*4 ;@ ctrl code pointer\n"); - ot(" ldr r1,[r0,#-4]\n"); - ot(" tst r1,r1\n"); - ot(" movne pc,lr ;@ already uncompressed\n"); - ot(" add r3,r12,#0xa000*4 ;@ handler table pointer, r12=dest\n"); - ot("unc_loop%s\n", ms?"":":"); - ot(" ldrh r1,[r0],#2\n"); - ot(" and r2,r1,#0xf\n"); - ot(" bic r1,r1,#0xf\n"); - ot(" ldr r1,[r3,r1,lsr #2] ;@ r1=handler\n"); - ot(" cmp r2,#0xf\n"); - ot(" addeq r2,r2,#1 ;@ 0xf is really 0x10\n"); - ot(" tst r2,r2\n"); - ot(" ldreqh r2,[r0],#2 ;@ counter is in next word\n"); - ot(" tst r2,r2\n"); - ot(" beq unc_finish ;@ done decompressing\n"); - ot(" tst r1,r1\n"); - ot(" addeq r12,r12,r2,lsl #2 ;@ 0 handler means we should skip those bytes\n"); - ot(" beq unc_loop\n"); - ot("unc_loop_in%s\n", ms?"":":"); - ot(" subs r2,r2,#1\n"); - ot(" str r1,[r12],#4\n"); - ot(" bgt unc_loop_in\n"); - ot(" b unc_loop\n"); - ot("unc_finish%s\n", ms?"":":"); - ot(" ldr r12,=CycloneJumpTab\n"); - ot(" ;@ set a-line and f-line handlers\n"); - ot(" add r0,r12,#0xa000*4\n"); - ot(" ldr r1,[r0,#4] ;@ a-line handler\n"); - ot(" ldr r3,[r0,#8] ;@ f-line handler\n"); - ot(" mov r2,#0x1000\n"); - ot("unc_fill3%s\n", ms?"":":"); - ot(" subs r2,r2,#1\n"); - ot(" str r1,[r0],#4\n"); - ot(" bgt unc_fill3\n"); - ot(" add r0,r12,#0xf000*4\n"); - ot(" mov r2,#0x1000\n"); - ot("unc_fill4%s\n", ms?"":":"); - ot(" subs r2,r2,#1\n"); - ot(" str r3,[r0],#4\n"); - ot(" bgt unc_fill4\n"); - ot(" bx lr\n"); - ltorg(); -#else - ot(";@ do nothing\n"); - ot(" bx lr\n"); -#endif - ot("\n"); - - // -------------- - ot("CycloneReset%s\n", ms?"":":"); - ot(" stmfd sp!,{r7,lr}\n"); - ot(" mov r7,r0\n"); - ot(" mov r0,#0\n"); - ot(" str r0,[r7,#0x58] ;@ state_flags\n"); - ot(" str r0,[r7,#0x48] ;@ OSP\n"); - ot(" mov r1,#0x27 ;@ Supervisor mode\n"); - ot(" strb r1,[r7,#0x44] ;@ set SR high\n"); - ot(" strb r0,[r7,#0x47] ;@ IRQ\n"); - MemHandler(0,2); - ot(" str r0,[r7,#0x3c] ;@ Stack pointer\n"); - ot(" mov r0,#0\n"); - ot(" str r0,[r7,#0x60] ;@ Membase\n"); - ot(" mov r0,#4\n"); - MemHandler(0,2); -#ifdef MEMHANDLERS_DIRECT_PREFIX - ot(" bl %scheckpc ;@ Call checkpc()\n", MEMHANDLERS_DIRECT_PREFIX); -#else - ot(" mov lr,pc\n"); - ot(" ldr pc,[r7,#0x64] ;@ Call checkpc()\n"); -#endif - ot(" str r0,[r7,#0x40] ;@ PC + base\n"); - ot(" ldmfd sp!,{r7,pc}\n"); - ot("\n"); - - // -------------- - // 68k: XNZVC, ARM: NZCV - ot("CycloneSetSr%s\n", ms?"":":"); - ot(" mov r2,r1,lsr #8\n"); -// ot(" ldrb r3,[r0,#0x44] ;@ get SR high\n"); -// ot(" eor r3,r3,r2\n"); -// ot(" tst r3,#0x20\n"); -#if EMULATE_TRACE - ot(" and r2,r2,#0xa7 ;@ only defined bits\n"); -#else - ot(" and r2,r2,#0x27 ;@ only defined bits\n"); -#endif - ot(" strb r2,[r0,#0x44] ;@ set SR high\n"); - ot(" mov r2,r1,lsl #25\n"); - ot(" str r2,[r0,#0x4c] ;@ the X flag\n"); - ot(" bic r2,r1,#0xf3\n"); - ot(" tst r1,#1\n"); - ot(" orrne r2,r2,#2\n"); - ot(" tst r1,#2\n"); - ot(" orrne r2,r2,#1\n"); - ot(" strb r2,[r0,#0x46] ;@ flags\n"); - ot(" bx lr\n"); - ot("\n"); - - // -------------- - ot("CycloneGetSr%s\n", ms?"":":"); - ot(" ldrb r1,[r0,#0x46] ;@ flags\n"); - ot(" bic r2,r1,#0xf3\n"); - ot(" tst r1,#1\n"); - ot(" orrne r2,r2,#2\n"); - ot(" tst r1,#2\n"); - ot(" orrne r2,r2,#1\n"); - ot(" ldr r1,[r0,#0x4c] ;@ the X flag\n"); - ot(" tst r1,#0x20000000\n"); - ot(" orrne r2,r2,#0x10\n"); - ot(" ldrb r1,[r0,#0x44] ;@ the SR high\n"); - ot(" orr r0,r2,r1,lsl #8\n"); - ot(" bx lr\n"); - ot("\n"); - - // -------------- - ot("CyclonePack%s\n", ms?"":":"); - ot(" stmfd sp!,{r4,r5,lr}\n"); - ot(" mov r4,r0\n"); - ot(" mov r5,r1\n"); - ot(" mov r3,#16\n"); - ot(";@ 0x00-0x3f: DA registers\n"); - ot("c_pack_loop%s\n",ms?"":":"); - ot(" ldr r1,[r0],#4\n"); - ot(" subs r3,r3,#1\n"); - ot(" str r1,[r5],#4\n"); - ot(" bne c_pack_loop\n"); - ot(";@ 0x40: PC\n"); - ot(" ldr r0,[r4,#0x40] ;@ PC + Memory Base\n"); - ot(" ldr r1,[r4,#0x60] ;@ Memory base\n"); - ot(" sub r0,r0,r1\n"); - ot(" str r0,[r5],#4\n"); - ot(";@ 0x44: SR\n"); - ot(" mov r0,r4\n"); - ot(" bl CycloneGetSr\n"); - ot(" strh r0,[r5],#2\n"); - ot(";@ 0x46: IRQ level\n"); - ot(" ldrb r0,[r4,#0x47]\n"); - ot(" strb r0,[r5],#2\n"); - ot(";@ 0x48: other SP\n"); - ot(" ldr r0,[r4,#0x48]\n"); - ot(" str r0,[r5],#4\n"); - ot(";@ 0x4c: CPU state flags\n"); - ot(" ldr r0,[r4,#0x58]\n"); - ot(" str r0,[r5],#4\n"); - ot(" ldmfd sp!,{r4,r5,pc}\n"); - ot("\n"); - - // -------------- - ot("CycloneUnpack%s\n", ms?"":":"); - ot(" stmfd sp!,{r5,r7,lr}\n"); - ot(" mov r7,r0\n"); - ot(" movs r5,r1\n"); - ot(" beq c_unpack_do_pc\n"); - ot(" mov r3,#16\n"); - ot(";@ 0x00-0x3f: DA registers\n"); - ot("c_unpack_loop%s\n",ms?"":":"); - ot(" ldr r1,[r5],#4\n"); - ot(" subs r3,r3,#1\n"); - ot(" str r1,[r0],#4\n"); - ot(" bne c_unpack_loop\n"); - ot(";@ 0x40: PC\n"); - ot(" ldr r0,[r5],#4 ;@ PC\n"); - ot(" str r0,[r7,#0x40] ;@ handle later\n"); - ot(";@ 0x44: SR\n"); - ot(" ldrh r1,[r5],#2\n"); - ot(" mov r0,r7\n"); - ot(" bl CycloneSetSr\n"); - ot(";@ 0x46: IRQ level\n"); - ot(" ldrb r0,[r5],#2\n"); - ot(" strb r0,[r7,#0x47]\n"); - ot(";@ 0x48: other SP\n"); - ot(" ldr r0,[r5],#4\n"); - ot(" str r0,[r7,#0x48]\n"); - ot(";@ 0x4c: CPU state flags\n"); - ot(" ldr r0,[r5],#4\n"); - ot(" str r0,[r7,#0x58]\n"); - ot("c_unpack_do_pc%s\n",ms?"":":"); - ot(" ldr r0,[r7,#0x40] ;@ unbased PC\n"); -#if USE_CHECKPC_CALLBACK - ot(" mov r1,#0\n"); - ot(" str r1,[r7,#0x60] ;@ Memory base\n"); - #ifdef MEMHANDLERS_DIRECT_PREFIX - ot(" bl %scheckpc ;@ Call checkpc()\n", MEMHANDLERS_DIRECT_PREFIX); - #else - ot(" mov lr,pc\n"); - ot(" ldr pc,[r7,#0x64] ;@ Call checkpc()\n"); - #endif -#else - ot(" ldr r1,[r7,#0x60] ;@ Memory base\n"); - ot(" add r0,r0,r1 ;@ r0 = Memory Base + New PC\n"); -#endif - ot(" str r0,[r7,#0x40] ;@ PC + Memory Base\n"); - ot(" ldmfd sp!,{r5,r7,pc}\n"); - ot("\n"); - - // -------------- - ot("CycloneFlushIrq%s\n", ms?"":":"); - ot(" ldr r1,[r0,#0x44] ;@ Get SR high T_S__III and irq level\n"); - ot(" mov r2,r1,lsr #24 ;@ Get IRQ level\n"); // same as ldrb r0,[r7,#0x47] - ot(" cmp r2,#6 ;@ irq>6 ?\n"); - ot(" andle r1,r1,#7 ;@ Get interrupt mask\n"); - ot(" cmple r2,r1 ;@ irq<=6: Is irq<=mask ?\n"); - ot(" movle r0,#0\n"); - ot(" bxle lr ;@ no ints\n"); - ot("\n"); - ot(" stmdb sp!,{r4,r5,r7,r8,r10,r11,lr}\n"); - ot(" mov r7,r0\n"); - ot(" mov r0,r2\n"); - ot(" ldrb r10,[r7,#0x46] ;@ r10 = Flags (NZCV)\n"); - ot(" mov r5,#0\n"); - ot(" ldr r4,[r7,#0x40] ;@ r4 = Current PC + Memory Base\n"); - ot(" mov r10,r10,lsl #28 ;@ r10 = Flags 0xf0000000, cpsr format\n"); - ot(" adr r2,CycloneFlushIrqEnd\n"); - ot(" str r2,[r7,#0x98] ;@ set custom CycloneEnd\n"); - ot(" b CycloneDoInterrupt\n"); - ot("\n"); - ot("CycloneFlushIrqEnd%s\n", ms?"":":"); - ot(" rsb r0,r5,#0\n"); - ot(" str r4,[r7,#0x40] ;@ Save Current PC + Memory Base\n"); - ot(" strb r10,[r7,#0x46] ;@ Save Flags (NZCV)\n"); - ot(" ldmia sp!,{r4,r5,r7,r8,r10,r11,lr}\n"); - ot(" bx lr\n"); - ot("\n"); - ot("\n"); - - // -------------- - ot("CycloneSetRealTAS%s\n", ms?"":":"); -#if (CYCLONE_FOR_GENESIS == 2) - ot(" ldr r12,=CycloneJumpTab\n"); - ot(" tst r0,r0\n"); - ot(" add r12,r12,#0x4a00*4\n"); - ot(" add r12,r12,#0x00d0*4\n"); - ot(" beq setrtas_off\n"); - ChangeTAS(1); - ot(" bx lr\n"); - ot("setrtas_off%s\n",ms?"":":"); - ChangeTAS(0); - ot(" bx lr\n"); - ltorg(); -#else - ot(" bx lr\n"); -#endif - ot("\n"); - - // -------------- - ot(";@ DoInterrupt - r0=IRQ level\n"); - ot("CycloneDoInterruptGoBack%s\n", ms?"":":"); - ot(" sub r4,r4,#2\n"); - ot("CycloneDoInterrupt%s\n", ms?"":":"); - ot(" bic r8,r8,#0xff000000\n"); - ot(" orr r8,r8,r0,lsl #29 ;@ abuse r8\n"); - - // Steps are from "M68000 8-/16-/32-BIT MICROPROCESSORS USER'S MANUAL", p. 6-4 - // but their order is based on http://pasti.fxatari.com/68kdocs/68kPrefetch.html - // 1. Make a temporary copy of the status register and set the status register for exception processing. - ot(" ldr r2,[r7,#0x58] ;@ state flags\n"); - ot(" and r0,r0,#7\n"); - ot(" orr r3,r0,#0x20 ;@ Supervisor mode + IRQ level\n"); - ot(" bic r2,r2,#3 ;@ clear stopped and trace states\n"); -#if EMULATE_ADDRESS_ERRORS_JUMP || EMULATE_ADDRESS_ERRORS_IO - ot(" orr r2,r2,#4 ;@ set activity bit: 'not processing instruction'\n"); -#endif - ot(" str r2,[r7,#0x58]\n"); - ot(" ldrb r6,[r7,#0x44] ;@ Get old SR high, abuse r6\n"); - ot(" strb r3,[r7,#0x44] ;@ Put new SR high\n"); - ot("\n"); - - // 3. Save the current processor context. - ot(" ldr r1,[r7,#0x60] ;@ Get Memory base\n"); - ot(" ldr r11,[r7,#0x3c] ;@ Get A7\n"); - ot(" tst r6,#0x20\n"); - ot(";@ get our SP:\n"); - ot(" ldreq r2,[r7,#0x48] ;@ ...or OSP as our stack pointer\n"); - ot(" streq r11,[r7,#0x48]\n"); - ot(" moveq r11,r2\n"); - ot(";@ Push old PC onto stack\n"); - ot(" sub r0,r11,#4 ;@ Predecremented A7\n"); - ot(" sub r1,r4,r1 ;@ r1 = Old PC\n"); - MemHandler(1,2); - ot(";@ Push old SR:\n"); - ot(" ldr r0,[r7,#0x4c] ;@ X bit\n"); - ot(" mov r1,r10,lsr #28 ;@ ____NZCV\n"); - ot(" eor r2,r1,r1,ror #1 ;@ Bit 0=C^V\n"); - ot(" tst r2,#1 ;@ 1 if C!=V\n"); - ot(" eorne r1,r1,#3 ;@ ____NZVC\n"); - ot(" and r0,r0,#0x20000000\n"); - ot(" orr r1,r1,r0,lsr #25 ;@ ___XNZVC\n"); - ot(" orr r1,r1,r6,lsl #8 ;@ Include old SR high\n"); - ot(" sub r0,r11,#6 ;@ Predecrement A7\n"); - ot(" str r0,[r7,#0x3c] ;@ Save A7\n"); - MemHandler(1,1,0,0); // already checked for address error by prev MemHandler - ot("\n"); - - // 2. Obtain the exception vector. - ot(" mov r11,r8,lsr #29\n"); - ot(" mov r0,r11\n"); -#if USE_INT_ACK_CALLBACK - ot(";@ call IrqCallback if it is defined\n"); -#if INT_ACK_NEEDS_STUFF - ot(" str r4,[r7,#0x40] ;@ Save PC\n"); - ot(" mov r1,r10,lsr #28\n"); - ot(" strb r1,[r7,#0x46] ;@ Save Flags (NZCV)\n"); - ot(" str r5,[r7,#0x5c] ;@ Save Cycles\n"); -#endif - ot(" ldr r3,[r7,#0x8c] ;@ IrqCallback\n"); - ot(" add lr,pc,#4*3\n"); - ot(" tst r3,r3\n"); - ot(" streqb r3,[r7,#0x47] ;@ just clear IRQ if there is no callback\n"); - ot(" mvneq r0,#0 ;@ and simulate -1 return\n"); - ot(" bxne r3\n"); -#if INT_ACK_CHANGES_CYCLES - ot(" ldr r5,[r7,#0x5c] ;@ Load Cycles\n"); -#endif - ot(";@ get IRQ vector address:\n"); - ot(" cmn r0,#1 ;@ returned -1?\n"); - ot(" addeq r0,r11,#0x18 ;@ use autovector then\n"); - ot(" cmn r0,#2 ;@ returned -2?\n"); // should be safe as above add should never result in -2 - ot(" moveq r0,#0x18 ;@ use spurious interrupt then\n"); -#else // !USE_INT_ACK_CALLBACK - ot(";@ Clear irq:\n"); - ot(" mov r2,#0\n"); - ot(" strb r2,[r7,#0x47]\n"); - ot(" add r0,r0,#0x18 ;@ use autovector\n"); -#endif - ot(" mov r0,r0,lsl #2 ;@ get vector address\n"); - ot("\n"); - ot(" ldr r11,[r7,#0x60] ;@ Get Memory base\n"); - ot(";@ Read IRQ Vector:\n"); - MemHandler(0,2,0,0); - ot(" tst r0,r0 ;@ uninitialized int vector?\n"); - ot(" moveq r0,#0x3c\n"); - #ifdef MEMHANDLERS_DIRECT_PREFIX - ot(" bleq %sread32 ;@ Call read32(r0) handler\n", MEMHANDLERS_DIRECT_PREFIX); - #else - ot(" moveq lr,pc\n"); - ot(" ldreq pc,[r7,#0x70] ;@ Call read32(r0) handler\n"); - #endif -#if USE_CHECKPC_CALLBACK - ot(" add lr,pc,#4\n"); - ot(" add r0,r0,r11 ;@ r0 = Memory Base + New PC\n"); - #ifdef MEMHANDLERS_DIRECT_PREFIX - ot(" bl %scheckpc ;@ Call checkpc()\n", MEMHANDLERS_DIRECT_PREFIX); - #else - ot(" ldr pc,[r7,#0x64] ;@ Call checkpc()\n"); - #endif - #if EMULATE_ADDRESS_ERRORS_JUMP - ot(" mov r4,r0\n"); - #else - ot(" bic r4,r0,#1\n"); - #endif -#else - ot(" add r4,r0,r11 ;@ r4 = Memory Base + New PC\n"); - #if EMULATE_ADDRESS_ERRORS_JUMP - ot(" bic r4,r4,#1\n"); - #endif -#endif - ot("\n"); - - // 4. Obtain a new context and resume instruction processing. - // note: the obtain part was already done in previous steps -#if EMULATE_ADDRESS_ERRORS_JUMP - ot(" tst r4,#1\n"); - ot(" bne ExceptionAddressError_r_prg_r4\n"); -#endif - ot(" ldr r6,[r7,#0x54]\n"); - ot(" ldrh r8,[r4],#2 ;@ Fetch next opcode\n"); - ot(" subs r5,r5,#44 ;@ Subtract cycles\n"); - ot(" ldrge pc,[r6,r8,asl #2] ;@ Jump to opcode handler\n"); - ot(" b CycloneEnd\n"); - ot("\n"); - - // -------------- - // trashes all temp regs - ot("Exception%s\n", ms?"":":"); - ot(" ;@ Cause an Exception - Vector number in r0\n"); - ot(" mov r11,lr ;@ Preserve ARM return address\n"); - ot(" bic r8,r8,#0xff000000\n"); - ot(" orr r8,r8,r0,lsl #24 ;@ abuse r8\n"); - - // 1. Make a temporary copy of the status register and set the status register for exception processing. - ot(" ldr r6,[r7,#0x44] ;@ Get old SR high, abuse r6\n"); - ot(" ldr r2,[r7,#0x58] ;@ state flags\n"); - ot(" and r3,r6,#0x27 ;@ clear trace and unused flags\n"); - ot(" orr r3,r3,#0x20 ;@ set supervisor mode\n"); - ot(" bic r2,r2,#3 ;@ clear stopped and trace states\n"); - ot(" str r2,[r7,#0x58]\n"); - ot(" strb r3,[r7,#0x44] ;@ Put new SR high\n"); - ot("\n"); - - // 3. Save the current processor context. - ot(" ldr r0,[r7,#0x3c] ;@ Get A7\n"); - ot(" tst r6,#0x20\n"); - ot(";@ get our SP:\n"); - ot(" ldreq r2,[r7,#0x48] ;@ ...or OSP as our stack pointer\n"); - ot(" streq r0,[r7,#0x48]\n"); - ot(" moveq r0,r2\n"); - ot(";@ Push old PC onto stack\n"); - ot(" ldr r1,[r7,#0x60] ;@ Get Memory base\n"); - ot(" sub r0,r0,#4 ;@ Predecremented A7\n"); - ot(" str r0,[r7,#0x3c] ;@ Save A7\n"); - ot(" sub r1,r4,r1 ;@ r1 = Old PC\n"); - MemHandler(1,2); - ot(";@ Push old SR:\n"); - ot(" ldr r0,[r7,#0x4c] ;@ X bit\n"); - ot(" mov r1,r10,lsr #28 ;@ ____NZCV\n"); - ot(" eor r2,r1,r1,ror #1 ;@ Bit 0=C^V\n"); - ot(" tst r2,#1 ;@ 1 if C!=V\n"); - ot(" eorne r1,r1,#3 ;@ ____NZVC\n"); - ot(" and r0,r0,#0x20000000\n"); - ot(" orr r1,r1,r0,lsr #25 ;@ ___XNZVC\n"); - ot(" ldr r0,[r7,#0x3c] ;@ A7\n"); - ot(" orr r1,r1,r6,lsl #8 ;@ Include SR high\n"); - ot(" sub r0,r0,#2 ;@ Predecrement A7\n"); - ot(" str r0,[r7,#0x3c] ;@ Save A7\n"); - MemHandler(1,1,0,0); - ot("\n"); - - // 2. Obtain the exception vector - ot(";@ Read Exception Vector:\n"); - ot(" mov r0,r8,lsr #24\n"); - ot(" mov r0,r0,lsl #2\n"); - MemHandler(0,2,0,0); - ot(" ldr r3,[r7,#0x60] ;@ Get Memory base\n"); -#if USE_CHECKPC_CALLBACK - ot(" add lr,pc,#4\n"); - ot(" add r0,r0,r3 ;@ r0 = Memory Base + New PC\n"); - #ifdef MEMHANDLERS_DIRECT_PREFIX - ot(" bl %scheckpc ;@ Call checkpc()\n", MEMHANDLERS_DIRECT_PREFIX); - #else - ot(" ldr pc,[r7,#0x64] ;@ Call checkpc()\n"); - #endif - #if EMULATE_ADDRESS_ERRORS_JUMP - ot(" mov r4,r0\n"); - #else - ot(" bic r4,r0,#1\n"); - #endif -#else - ot(" add r4,r0,r3 ;@ r4 = Memory Base + New PC\n"); - #if EMULATE_ADDRESS_ERRORS_JUMP - ot(" bic r4,r4,#1\n"); - #endif -#endif - ot("\n"); - - // 4. Resume execution. -#if EMULATE_ADDRESS_ERRORS_JUMP - ot(" tst r4,#1\n"); - ot(" bne ExceptionAddressError_r_prg_r4\n"); -#endif - ot(" ldr r6,[r7,#0x54]\n"); - ot(" bx r11 ;@ Return\n"); - ot("\n"); - - // -------------- -#if EMULATE_ADDRESS_ERRORS_JUMP || EMULATE_ADDRESS_ERRORS_IO - // first some wrappers: I see no point inlining this code, - // as it will be executed in really rare cases. - AddressErrorWrapper('r', "data", 0x11); - AddressErrorWrapper('r', "prg", 0x12); - AddressErrorWrapper('w', "data", 0x01); - // there are no program writes - // cpu space is only for bus errors? - ot("ExceptionAddressError_r_prg_r4%s\n", ms?"":":"); - ot(" ldr r1,[r7,#0x44]\n"); - ot(" ldr r3,[r7,#0x60] ;@ Get Memory base\n"); - ot(" mov r6,#0x12\n"); - ot(" sub r11,r4,r3\n"); - ot(" tst r1,#0x20\n"); - ot(" orrne r6,r6,#4\n"); - ot("\n"); - - ot("ExceptionAddressError%s\n", ms?"":":"); - ot(";@ r6 - info word (without instruction/not bit), r11 - faulting address\n"); - - // 1. Make a temporary copy of the status register and set the status register for exception processing. - ot(" ldrb r0,[r7,#0x44] ;@ Get old SR high\n"); - ot(" ldr r2,[r7,#0x58] ;@ state flags\n"); - ot(" and r3,r0,#0x27 ;@ clear trace and unused flags\n"); - ot(" orr r3,r3,#0x20 ;@ set supervisor mode\n"); - ot(" strb r3,[r7,#0x44] ;@ Put new SR high\n"); - ot(" bic r2,r2,#3 ;@ clear stopped and trace states\n"); - ot(" tst r2,#4\n"); - ot(" orrne r6,r6,#8 ;@ complete info word\n"); - ot(" orr r2,r2,#4 ;@ set activity bit: 'not processing instruction'\n"); -#if EMULATE_HALT - ot(" tst r2,#8\n"); - ot(" orrne r2,r2,#0x10 ;@ HALT\n"); - ot(" orr r2,r2,#8 ;@ processing address error\n"); - ot(" str r2,[r7,#0x58]\n"); - ot(" movne r5,#0\n"); - ot(" bne CycloneEndNoBack ;@ bye bye\n"); -#else - ot(" str r2,[r7,#0x58]\n"); -#endif - ot(" and r10,r10,#0xf0000000\n"); - ot(" orr r10,r10,r0,lsl #4 ;@ some preparations for SR push\n"); - ot("\n"); - - // 3. Save the current processor context + additional information. - ot(" ldr r0,[r7,#0x3c] ;@ Get A7\n"); - ot(" tst r10,#0x200\n"); - ot(";@ get our SP:\n"); - ot(" ldreq r2,[r7,#0x48] ;@ ...or OSP as our stack pointer\n"); - ot(" streq r0,[r7,#0x48]\n"); - ot(" moveq r0,r2\n"); - // PC - ot(";@ Push old PC onto stack\n"); - ot(" ldr r1,[r7,#0x60] ;@ Get Memory base\n"); - ot(" sub r0,r0,#4 ;@ Predecremented A7\n"); - ot(" sub r1,r4,r1 ;@ r1 = Old PC\n"); - ot(" str r0,[r7,#0x3c] ;@ Save A7\n"); - MemHandler(1,2,0,EMULATE_HALT); - // SR - ot(";@ Push old SR:\n"); - ot(" ldr r0,[r7,#0x4c] ;@ X bit\n"); - ot(" mov r1,r10,ror #28 ;@ ____NZCV\n"); - ot(" eor r2,r1,r1,ror #1 ;@ Bit 0=C^V\n"); - ot(" tst r2,#1 ;@ 1 if C!=V\n"); - ot(" eorne r1,r1,#3 ;@ ____NZVC\n"); - ot(" and r0,r0,#0x20000000\n"); - ot(" orr r1,r1,r0,lsr #25 ;@ ___XNZVC\n"); - ot(" ldr r0,[r7,#0x3c] ;@ A7\n"); - ot(" and r10,r10,#0xf0000000\n"); - ot(" sub r0,r0,#2 ;@ Predecrement A7\n"); - ot(" str r0,[r7,#0x3c] ;@ Save A7\n"); - MemHandler(1,1,0,0); - // IR (instruction register) - ot(";@ Push IR:\n"); - ot(" ldr r0,[r7,#0x3c] ;@ A7\n"); - ot(" mov r1,r8\n"); - ot(" sub r0,r0,#2 ;@ Predecrement A7\n"); - ot(" str r0,[r7,#0x3c] ;@ Save A7\n"); - MemHandler(1,1,0,0); - // access address - ot(";@ Push address:\n"); - ot(" ldr r0,[r7,#0x3c] ;@ A7\n"); - ot(" mov r1,r11\n"); - ot(" sub r0,r0,#4 ;@ Predecrement A7\n"); - ot(" str r0,[r7,#0x3c] ;@ Save A7\n"); - MemHandler(1,2,0,0); - // information word - ot(";@ Push info word:\n"); - ot(" ldr r0,[r7,#0x3c] ;@ A7\n"); - ot(" mov r1,r6\n"); - ot(" sub r0,r0,#2 ;@ Predecrement A7\n"); - ot(" str r0,[r7,#0x3c] ;@ Save A7\n"); - MemHandler(1,1,0,0); - ot("\n"); - - // 2. Obtain the exception vector - ot(";@ Read Exception Vector:\n"); - ot(" mov r0,#0x0c\n"); - MemHandler(0,2,0,0); - ot(" ldr r3,[r7,#0x60] ;@ Get Memory base\n"); -#if USE_CHECKPC_CALLBACK - ot(" add lr,pc,#4\n"); - ot(" add r0,r0,r3 ;@ r0 = Memory Base + New PC\n"); - #ifdef MEMHANDLERS_DIRECT_PREFIX - ot(" bl %scheckpc ;@ Call checkpc()\n", MEMHANDLERS_DIRECT_PREFIX); - #else - ot(" ldr pc,[r7,#0x64] ;@ Call checkpc()\n"); - #endif - ot(" mov r4,r0\n"); -#else - ot(" add r4,r0,r3 ;@ r4 = Memory Base + New PC\n"); -#endif - ot("\n"); - -#if EMULATE_ADDRESS_ERRORS_JUMP && EMULATE_HALT - ot(" tst r4,#1\n"); - ot(" bne ExceptionAddressError_r_prg_r4\n"); -#else - ot(" bic r4,r4,#1\n"); -#endif - - // 4. Resume execution. - ot(" ldr r6,[r7,#0x54]\n"); - ot(" ldrh r8,[r4],#2 ;@ Fetch next opcode\n"); - ot(" subs r5,r5,#50 ;@ Subtract cycles\n"); - ot(" ldrge pc,[r6,r8,asl #2] ;@ Jump to opcode handler\n"); - ot(" b CycloneEnd\n"); - ot("\n"); -#endif - - // -------------- -#if EMULATE_TRACE - // expects srh and irq level in r1, next opcode already fetched to r8 - ot("CycloneDoTraceWithChecks%s\n", ms?"":":"); - ot(" ldr r0,[r7,#0x58]\n"); - ot(" cmp r5,#0\n"); - ot(" orr r0,r0,#2 ;@ go to trace mode\n"); - ot(" str r0,[r7,#0x58]\n"); - ot(" blt CycloneEnd\n"); // should take care of situation where we come here when already tracing - ot(";@ CheckInterrupt:\n"); - ot(" movs r0,r1,lsr #24 ;@ Get IRQ level\n"); - ot(" beq CycloneDoTrace\n"); - ot(" cmp r0,#6 ;@ irq>6 ?\n"); - ot(" andle r1,r1,#7 ;@ Get interrupt mask\n"); - ot(" cmple r0,r1 ;@ irq<=6: Is irq<=mask ?\n"); - ot(" bgt CycloneDoInterruptGoBack\n"); - ot("\n"); - - // expects next opcode to be already fetched to r8 - ot("CycloneDoTrace%s\n", ms?"":":"); - ot(" str r5,[r7,#0x9c] ;@ save cycles\n"); - ot(" ldr r1,[r7,#0x98]\n"); - ot(" mov r5,#0\n"); - ot(" str r1,[r7,#0xa0]\n"); - ot(" adr r0,TraceEnd\n"); - ot(" str r0,[r7,#0x98] ;@ store TraceEnd as CycloneEnd hadler\n"); - ot(" ldr pc,[r6,r8,asl #2] ;@ Jump to opcode handler\n"); - ot("\n"); - - ot("TraceEnd%s\n", ms?"":":"); - ot(" ldr r2,[r7,#0x58]\n"); - ot(" ldr r0,[r7,#0x9c] ;@ restore cycles\n"); - ot(" ldr r1,[r7,#0xa0] ;@ old CycloneEnd handler\n"); - ot(" mov r10,r10,lsl #28\n"); - ot(" add r5,r0,r5\n"); - ot(" str r1,[r7,#0x98]\n"); - ot(";@ still tracing?\n"); // exception might have happend - ot(" tst r2,#2\n"); - ot(" beq TraceDisabled\n"); - ot(";@ trace exception\n"); -#if EMULATE_ADDRESS_ERRORS_JUMP || EMULATE_ADDRESS_ERRORS_IO - ot(" ldr r1,[r7,#0x58]\n"); - ot(" mov r0,#9\n"); - ot(" orr r1,r1,#4 ;@ set activity bit: 'not processing instruction'\n"); - ot(" str r1,[r7,#0x58]\n"); -#else - ot(" mov r0,#9\n"); -#endif - ot(" bl Exception\n"); - ot(" ldrh r8,[r4],#2 ;@ Fetch next opcode\n"); - ot(" subs r5,r5,#34 ;@ Subtract cycles\n"); - ot(" ldrge pc,[r6,r8,asl #2] ;@ Jump to opcode handler\n"); - ot(" b CycloneEnd\n"); - ot("\n"); - ot("TraceDisabled%s\n", ms?"":":"); - ot(" ldrh r8,[r4],#2 ;@ Fetch next opcode\n"); - ot(" cmp r5,#0\n"); - ot(" ldrge pc,[r6,r8,asl #2] ;@ Jump to opcode handler\n"); - ot(" b CycloneEnd\n"); - ot("\n"); -#endif -} - -// --------------------------------------------------------------------------- -// Call Read(r0), Write(r0,r1) or Fetch(r0) -// Trashes r0-r3,r12,lr -int MemHandler(int type,int size,int addrreg,int need_addrerr_check) -{ - int func=0x68+type*0xc+(size<<2); // Find correct offset - char what[32]; - -#if MEMHANDLERS_NEED_FLAGS - ot(" mov r3,r10,lsr #28\n"); - ot(" strb r3,[r7,#0x46] ;@ Save Flags (NZCV)\n"); -#endif - FlushPC(); - -#if (MEMHANDLERS_ADDR_MASK & 0xff000000) - ot(" bic r0,r%i,#0x%08x\n", addrreg, MEMHANDLERS_ADDR_MASK & 0xff000000); - addrreg=0; -#endif -#if (MEMHANDLERS_ADDR_MASK & 0x00ff0000) - ot(" bic r0,r%i,#0x%08x\n", addrreg, MEMHANDLERS_ADDR_MASK & 0x00ff0000); - addrreg=0; -#endif -#if (MEMHANDLERS_ADDR_MASK & 0x0000ff00) - ot(" bic r0,r%i,#0x%08x\n", addrreg, MEMHANDLERS_ADDR_MASK & 0x0000ff00); - addrreg=0; -#endif -#if (MEMHANDLERS_ADDR_MASK & 0x000000ff) - ot(" bic r0,r%i,#0x%08x\n", addrreg, MEMHANDLERS_ADDR_MASK & 0x000000ff); - addrreg=0; -#endif - -#if EMULATE_ADDRESS_ERRORS_IO - if (size > 0 && need_addrerr_check) - { - ot(" add lr,pc,#4*%i\n", addrreg==0?2:3); // helps to prevent interlocks - if (addrreg != 0) ot(" mov r0,r%i\n", addrreg); - ot(" tst r0,#1 ;@ address error?\n"); - switch (type) { - case 0: ot(" bne ExceptionAddressError_r_data\n"); break; - case 1: ot(" bne ExceptionAddressError_w_data\n"); break; - case 2: ot(" bne ExceptionAddressError_r_prg\n"); break; - } - } - else -#endif - - sprintf(what, "%s%d", type==0 ? "read" : (type==1 ? "write" : "fetch"), 8<>12); fflush(stdout); } // Update progress - - if (!is_op_hot(op)) - OpAny(op); - } - - ot("\n"); - - printf("]\n"); -} - -// helper -static void ott(const char *str, int par, const char *nl, int nlp, int counter, int size) -{ - switch(size) { - case 0: if((counter&7)==0) ot(ms?" dcb ":" .byte "); break; - case 1: if((counter&7)==0) ot(ms?" dcw ":" .hword "); break; - case 2: if((counter&7)==0) ot(ms?" dcd ":" .long "); break; - } - ot(str, par); - if((counter&7)==7) ot(nl,nlp); else ot(","); -} - -static void PrintJumpTable() -{ - int i=0,op=0,len=0; - - ot(";@ -------------------------- Jump Table --------------------------\n"); - - // space for decompressed table - ot(ms?" area |.data|, data\n":" .data\n .align 4\n\n"); - -#if COMPRESS_JUMPTABLE - int handlers=0,reps=0,*indexes,ip,u,out; - // use some weird compression on the jump table - indexes=(int *)malloc(0x10000*4); - if(!indexes) { printf("ERROR: out of memory\n"); exit(1); } - len=0x10000; - - ot("CycloneJumpTab%s\n", ms?"":":"); - if(ms) { - for(i = 0; i < 0xa000/8; i++) - ot(" dcd 0,0,0,0,0,0,0,0\n"); - } else - ot(" .rept 0x%x\n .long 0,0,0,0,0,0,0,0\n .endr\n", 0xa000/8); - - // hanlers live in "a-line" part of the table - // first output nop,a-line,f-line handlers - ot(ms?" dcd Op____,Op__al,Op__fl,":" .long Op____,Op__al,Op__fl,"); - handlers=3; - - for(i=0;i=0; u--) if(op == CyJump[u]) break; // already done with this op? - if(u==-1 && op >= 0) { - ott("Op%.4x",op," ;@ %.4x\n",i,handlers,2); - indexes[op] = handlers; - handlers++; - } - } - if(handlers&7) { - fseek(AsmFile, -1, SEEK_CUR); // remove last comma - for(i = 8-(handlers&7); i > 0; i--) - ot(",000000"); - ot("\n"); - } - if(ms) { - for(i = (0x4000-handlers)/8; i > 0; i--) - ot(" dcd 0,0,0,0,0,0,0,0\n"); - } else { - ot(ms?"":" .rept 0x%x\n .long 0,0,0,0,0,0,0,0\n .endr\n", (0x4000-handlers)/8); - } - printf("total distinct hanlers: %i\n",handlers); - // output data - for(i=0,ip=0; i < 0xf000; i++, ip++) { - op=CyJump[i]; - if(op == -2) { - // it must skip a-line area, because we keep our data there - ott("0x%.4x", handlers<<4, "\n",0,ip++,1); - ott("0x%.4x", 0x1000, "\n",0,ip,1); - i+=0xfff; - continue; - } - for(reps=1; i < 0xf000; i++, reps++) if(op != CyJump[i+1]) break; - if(op>=0) out=indexes[op]<<4; else out=0; // unrecognised - if(reps <= 0xe || reps==0x10) { - if(reps!=0x10) out|=reps; else out|=0xf; // 0xf means 0x10 (0xf appeared to be unused anyway) - ott("0x%.4x", out, "\n",0,ip,1); - } else { - ott("0x%.4x", out, "\n",0,ip++,1); - ott("0x%.4x", reps,"\n",0,ip,1); - } - } - if(ip&1) ott("0x%.4x", 0, "\n",0,ip++,1); - if(ip&7) fseek(AsmFile, -1, SEEK_CUR); // remove last comma - if(ip&7) { - for(i = 8-(ip&7); i > 0; i--) - ot(",0x0000"); - } - ot("\n"); - if(ms) { - for(i = (0x2000-ip/2)/8+1; i > 0; i--) - ot(" dcd 0,0,0,0,0,0,0,0\n"); - } else { - ot(" .rept 0x%x\n .long 0,0,0,0,0,0,0,0\n .endr\n", (0x2000-ip/2)/8+1); - } - ot("\n"); - free(indexes); -#else - ot("CycloneJumpTab%s\n", ms?"":":"); - len=0xfffe; // Hmmm, armasm 2.50.8684 messes up with a 0x10000 long jump table - // notaz: same thing with GNU as 2.9-psion-98r2 (reloc overflow) - // this is due to COFF objects using only 2 bytes for reloc count - - for (i=0;i=0) ott("Op%.4x",op," ;@ %.4x\n",i-7,i,2); - else if(op==-2) ott("Op__al",0, " ;@ %.4x\n",i-7,i,2); - else if(op==-3) ott("Op__fl",0, " ;@ %.4x\n",i-7,i,2); - else ott("Op____",0, " ;@ %.4x\n",i-7,i,2); - } - if(i&7) fseek(AsmFile, -1, SEEK_CUR); // remove last comma - - ot("\n"); - ot(";@ notaz: we don't want to crash if we run into those 2 missing opcodes\n"); - ot(";@ so we leave this pattern to patch it later\n"); - ot("%s 0x78563412\n", ms?" dcd":" .long"); - ot("%s 0x56341290\n", ms?" dcd":" .long"); -#endif -} - -static int CycloneMake() -{ - int i; - const char *name="Cyclone.s"; - const char *globl=ms?"export":".global"; - - // Open the assembly file - if (ms) name="Cyclone.asm"; - AsmFile=fopen(name,"wt"); if (AsmFile==NULL) return 1; - - printf("Making %s...\n",name); - - ot("\n;@ Dave's Cyclone 68000 Emulator v%x.%.3x - Assembler Output\n\n",CycloneVer>>12,CycloneVer&0xfff); - - ot(";@ (c) Copyright 2003 Dave, All rights reserved.\n"); - ot(";@ some code (c) Copyright 2005-2007 notaz, All rights reserved.\n"); - ot(";@ Cyclone 68000 is free for non-commercial use.\n\n"); - ot(";@ For commercial use, separate licencing terms must be obtained.\n\n"); - - CyJump=(int *)malloc(0x40000); if (CyJump==NULL) return 1; - memset(CyJump,0xff,0x40000); // Init to -1 - for(i=0xa000; i<0xb000; i++) CyJump[i] = -2; // a-line emulation - for(i=0xf000; i<0x10000; i++) CyJump[i] = -3; // f-line emulation - - ot(ms?" area |.text|, code\n":" .text\n .align 4\n\n"); - ot(" %s CycloneInit\n",globl); - ot(" %s CycloneReset\n",globl); - ot(" %s CycloneRun\n",globl); - ot(" %s CycloneSetSr\n",globl); - ot(" %s CycloneGetSr\n",globl); - ot(" %s CycloneFlushIrq\n",globl); - ot(" %s CyclonePack\n",globl); - ot(" %s CycloneUnpack\n",globl); - ot(" %s CycloneVer\n",globl); -#if (CYCLONE_FOR_GENESIS == 2) - ot(" %s CycloneSetRealTAS\n",globl); - ot(" %s CycloneDoInterrupt\n",globl); - ot(" %s CycloneDoTrace\n",globl); - ot(" %s CycloneJumpTab\n",globl); - ot(" %s Op____\n",globl); - ot(" %s Op6001\n",globl); - ot(" %s Op6601\n",globl); - ot(" %s Op6701\n",globl); -#endif - ot("\n"); - ot(ms?"CycloneVer dcd 0x":"CycloneVer: .long 0x"); - ot("%.4x\n",CycloneVer); - ot("\n"); - - PrintFramework(); - arm_op_count = 0; - PrintOpcodes(); - printf("~%i ARM instructions used for opcode handlers\n", arm_op_count); - PrintJumpTable(); - - if (ms) ot(" END\n"); - - ot("\n\n;@ vim:filetype=armasm\n"); - - fclose(AsmFile); AsmFile=NULL; - -#if 0 - printf("Assembling...\n"); - // Assemble the file - if (ms) system("armasm Cyclone.asm"); - else system("as -o Cyclone.o Cyclone.s"); - printf("Done!\n\n"); -#endif - - free(CyJump); - return 0; -} - -int main() -{ - printf("\n Dave's Cyclone 68000 Emulator v%x.%.3x - Core Creator\n\n",CycloneVer>>12,CycloneVer&0xfff); - - // Make GAS or ARMASM version - CycloneMake(); - return 0; -} - diff --git a/cpu/Cyclone/OpAny.cpp b/cpu/Cyclone/OpAny.cpp deleted file mode 100644 index a50114a..0000000 --- a/cpu/Cyclone/OpAny.cpp +++ /dev/null @@ -1,207 +0,0 @@ - -#include "app.h" - -int opend_op_changes_cycles, opend_check_interrupt, opend_check_trace; - -static unsigned char OpData[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - -static unsigned short OpRead16(unsigned int a) -{ - return (unsigned short)( (OpData[a&15]<<8) | OpData[(a+1)&15] ); -} - -// For opcode 'op' use handler 'use' -void OpUse(int op,int use) -{ - char text[64]=""; - CyJump[op]=use; - - if (op!=use) return; - - // Disassemble opcode - DisaPc=0; - DisaText=text; - DisaWord=OpRead16; - - DisaGet(); - ot(";@ ---------- [%.4x] %s uses Op%.4x ----------\n",op,text,use); -} - -void OpStart(int op, int sea, int tea, int op_changes_cycles, int supervisor_check) -{ - int last_op_count=arm_op_count; - - Cycles=0; - OpUse(op,op); // This opcode obviously uses this handler - ot("Op%.4x%s\n", op, ms?"":":"); - - if (supervisor_check) - { - // checks for supervisor bit, if not set, jumps to SuperEnd() - // also sets r11 to SR high value, SuperChange() uses this - ot(" ldr r11,[r7,#0x44] ;@ Get SR high\n"); - } - if ((sea >= 0x10 && sea != 0x3c) || (tea >= 0x10 && tea != 0x3c)) - { -#if MEMHANDLERS_NEED_PREV_PC - ot(" str r4,[r7,#0x50] ;@ Save prev PC + 2\n"); -#endif -#if MEMHANDLERS_NEED_CYCLES - ot(" str r5,[r7,#0x5c] ;@ Save Cycles\n"); -#endif - } - if (supervisor_check) - { - ot(" tst r11,#0x20 ;@ Check we are in supervisor mode\n"); - ot(" beq WrongPrivilegeMode ;@ No\n"); - } - if ((sea >= 0x10 && sea != 0x3c) || (tea >= 0x10 && tea != 0x3c)) { -#if MEMHANDLERS_CHANGE_CYCLES - if (op_changes_cycles) - ot(" mov r5,#0\n"); -#endif - } - if (last_op_count!=arm_op_count) - ot("\n"); - pc_dirty = 1; - opend_op_changes_cycles = opend_check_interrupt = opend_check_trace = 0; -} - -void OpEnd(int sea, int tea) -{ - int did_fetch=0; - opend_check_trace = opend_check_trace && EMULATE_TRACE; -#if MEMHANDLERS_CHANGE_CYCLES - if ((sea >= 0x10 && sea != 0x3c) || (tea >= 0x10 && tea != 0x3c)) - { - if (opend_op_changes_cycles) - { - ot(" ldr r0,[r7,#0x5c] ;@ Load Cycles\n"); - ot(" ldrh r8,[r4],#2 ;@ Fetch next opcode\n"); - ot(" add r5,r0,r5\n"); - did_fetch=1; - } - else - { - ot(" ldr r5,[r7,#0x5c] ;@ Load Cycles\n"); - } - } -#endif - if (!did_fetch) - ot(" ldrh r8,[r4],#2 ;@ Fetch next opcode\n"); - if (opend_check_trace) - ot(" ldr r1,[r7,#0x44]\n"); - ot(" subs r5,r5,#%d ;@ Subtract cycles\n",Cycles); - if (opend_check_trace) - { - ot(";@ CheckTrace:\n"); - ot(" tst r1,#0x80\n"); - ot(" bne CycloneDoTraceWithChecks\n"); - ot(" cmp r5,#0\n"); - } - if (opend_check_interrupt) - { - ot(" blt CycloneEnd\n"); - ot(";@ CheckInterrupt:\n"); - if (!opend_check_trace) - ot(" ldr r1,[r7,#0x44]\n"); - ot(" movs r0,r1,lsr #24 ;@ Get IRQ level\n"); // same as ldrb r0,[r7,#0x47] - ot(" ldreq pc,[r6,r8,asl #2] ;@ Jump to next opcode handler\n"); - ot(" cmp r0,#6 ;@ irq>6 ?\n"); - ot(" andle r1,r1,#7 ;@ Get interrupt mask\n"); - ot(" cmple r0,r1 ;@ irq<=6: Is irq<=mask ?\n"); - ot(" ldrle pc,[r6,r8,asl #2] ;@ Jump to next opcode handler\n"); - ot(" b CycloneDoInterruptGoBack\n"); - } - else - { - ot(" ldrge pc,[r6,r8,asl #2] ;@ Jump to opcode handler\n"); - ot(" b CycloneEnd\n"); - } - ot("\n"); -} - -int OpBase(int op,int size,int sepa) -{ - int ea=op&0x3f; // Get Effective Address - if (ea<0x10) return sepa?(op&~0x7):(op&~0xf); // Use 1 handler for d0-d7 and a0-a7 - if (size==0&&(ea==0x1f || ea==0x27)) return op; // Specific handler for (a7)+ and -(a7) - if (ea<0x38) return op&~7; // Use 1 handler for (a0)-(a7), etc... - return op; -} - -// Get flags, trashes r2 -int OpGetFlags(int subtract,int xbit,int specialz) -{ - if (specialz) ot(" orr r2,r10,#0xb0000000 ;@ for old Z\n"); - - ot(" mrs r10,cpsr ;@ r10=flags\n"); - - if (specialz) ot(" andeq r10,r10,r2 ;@ fix Z\n"); - - if (subtract) ot(" eor r10,r10,#0x20000000 ;@ Invert carry\n"); - - if (xbit) - { - ot(" str r10,[r7,#0x4c] ;@ Save X bit\n"); - } - return 0; -} - -// ----------------------------------------------------------------- - -int g_op; - -void OpAny(int op) -{ - memset(OpData,0x33,sizeof(OpData)); - OpData[0]=(unsigned char)(op>>8); - OpData[1]=(unsigned char)op; - g_op=op; - - if ((op&0xf100)==0x0000) OpArith(op); // + - if ((op&0xc000)==0x0000) OpMove(op); // + - if ((op&0xf5bf)==0x003c) OpArithSr(op); // + Ori/Andi/Eori $nnnn,sr - if ((op&0xf100)==0x0100) OpBtstReg(op); // + - if ((op&0xf138)==0x0108) OpMovep(op); // + - if ((op&0xff00)==0x0800) OpBtstImm(op); // + - if ((op&0xf900)==0x4000) OpNeg(op); // + - if ((op&0xf140)==0x4100) OpChk(op); // + - if ((op&0xf1c0)==0x41c0) OpLea(op); // + - if ((op&0xf9c0)==0x40c0) OpMoveSr(op); // + - if ((op&0xffc0)==0x4800) OpNbcd(op); // + - if ((op&0xfff8)==0x4840) OpSwap(op); // + - if ((op&0xffc0)==0x4840) OpPea(op); // + - if ((op&0xffb8)==0x4880) OpExt(op); // + - if ((op&0xfb80)==0x4880) OpMovem(op); // + - if ((op&0xff00)==0x4a00) OpTst(op); // + - if ((op&0xffc0)==0x4ac0) OpTas(op); // + - if ((op&0xfff0)==0x4e40) OpTrap(op); // + - if ((op&0xfff8)==0x4e50) OpLink(op); // + - if ((op&0xfff8)==0x4e58) OpUnlk(op); // + - if ((op&0xfff0)==0x4e60) OpMoveUsp(op); // + - if ((op&0xfff8)==0x4e70) Op4E70(op); // + Reset/Rts etc - if ((op&0xfffd)==0x4e70) OpStopReset(op);// + - if ((op&0xff80)==0x4e80) OpJsr(op); // + - if ((op&0xf000)==0x5000) OpAddq(op); // + - if ((op&0xf0c0)==0x50c0) OpSet(op); // + - if ((op&0xf0f8)==0x50c8) OpDbra(op); // + - if ((op&0xf000)==0x6000) OpBranch(op); // + - if ((op&0xf100)==0x7000) OpMoveq(op); // + - if ((op&0xa000)==0x8000) OpArithReg(op); // + Or/Sub/And/Add - if ((op&0xb1f0)==0x8100) OpAbcd(op); // + - if ((op&0xb0c0)==0x80c0) OpMul(op); // + - if ((op&0x90c0)==0x90c0) OpAritha(op); // + - if ((op&0xb130)==0x9100) OpAddx(op); // + - if ((op&0xf000)==0xb000) OpCmpEor(op); // + - if ((op&0xf138)==0xb108) OpCmpm(op); // + - if ((op&0xf130)==0xc100) OpExg(op); // + - if ((op&0xf000)==0xe000) OpAsr(op); // + Asr/l/Ror/l etc - if ((op&0xf8c0)==0xe0c0) OpAsrEa(op); // + - - if (op==0xffff) - { - SuperEnd(); - } -} - diff --git a/cpu/Cyclone/OpArith.cpp b/cpu/Cyclone/OpArith.cpp deleted file mode 100644 index c05f5fd..0000000 --- a/cpu/Cyclone/OpArith.cpp +++ /dev/null @@ -1,819 +0,0 @@ - -#include "app.h" - -// --------------------- Opcodes 0x0000+ --------------------- -// Emit an Ori/And/Sub/Add/Eor/Cmp Immediate opcode, 0000ttt0 ssaaaaaa -int OpArith(int op) -{ - int type=0,size=0; - int sea=0,tea=0; - int use=0; - const char *shiftstr=""; - - // Get source and target EA - type=(op>>9)&7; if (type==4 || type>=7) return 1; - size=(op>>6)&3; if (size>=3) return 1; - sea= 0x003c; - tea=op&0x003f; - - // See if we can do this opcode: - if (EaCanRead(tea,size)==0) return 1; - if (EaCanWrite(tea)==0 || EaAn(tea)) return 1; - - use=OpBase(op,size); - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op, sea, tea); Cycles=4; - - // imm must be read first - EaCalcReadNoSE(-1,10,sea,size,0); - EaCalcReadNoSE((type!=6)?11:-1,0,tea,size,0x003f); - - if (size<2) shiftstr=(char *)(size?",asl #16":",asl #24"); - if (size<2) ot(" mov r10,r10,asl #%i\n",size?16:24); - - ot(";@ Do arithmetic:\n"); - - if (type==0) ot(" orr r1,r10,r0%s\n",shiftstr); - if (type==1) ot(" and r1,r10,r0%s\n",shiftstr); - if (type==2||type==6) - ot(" rsbs r1,r10,r0%s ;@ Defines NZCV\n",shiftstr); - if (type==3) ot(" adds r1,r10,r0%s ;@ Defines NZCV\n",shiftstr); - if (type==5) ot(" eor r1,r10,r0%s\n",shiftstr); - - if (type<2 || type==5) ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n"); // 0,1,5 - - if (type< 2) OpGetFlags(0,0); // Ori/And - if (type==2) OpGetFlags(1,1); // Sub: Subtract/X-bit - if (type==3) OpGetFlags(0,1); // Add: X-bit - if (type==5) OpGetFlags(0,0); // Eor - if (type==6) OpGetFlags(1,0); // Cmp: Subtract - ot("\n"); - - if (type!=6) - { - EaWrite(11, 1, tea,size,0x003f,1); - } - - // Correct cycles: - if (type==6) - { - if (size>=2 && tea<0x10) Cycles+=2; - } - else - { - if (size>=2) Cycles+=4; - if (tea>=8) Cycles+=4; - if (type==1 && size>=2 && tea<8) Cycles-=2; - } - - OpEnd(sea,tea); - - return 0; -} - -// --------------------- Opcodes 0x5000+ --------------------- -int OpAddq(int op) -{ - // 0101nnnt xxeeeeee (nnn=#8,1-7 t=addq/subq xx=size, eeeeee=EA) - int num=0,type=0,size=0,ea=0; - int use=0; - char count[16]=""; - int shift=0; - - num =(op>>9)&7; if (num==0) num=8; - type=(op>>8)&1; - size=(op>>6)&3; if (size>=3) return 1; - ea = op&0x3f; - - // See if we can do this opcode: - if (EaCanRead (ea,size)==0) return 1; - if (EaCanWrite(ea) ==0) return 1; - if (size == 0 && EaAn(ea) ) return 1; - - use=OpBase(op,size,1); - - if (num!=8) use|=0x0e00; // If num is not 8, use same handler - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,ea); - Cycles=ea<8?4:8; - if(type==0&&size==1) Cycles=ea<0x10?4:8; - if(size>=2) Cycles=ea<0x10?8:12; - - if (size>0 && (ea&0x38)==0x08) size=2; // addq.w #n,An is also 32-bit - - EaCalcReadNoSE(11,0,ea,size,0x003f); - - shift=32-(8<=0) sprintf(count,"r2,lsr #%d", lsr); - else sprintf(count,"r2,lsl #%d", -lsr); - - ot("\n"); - } - else - { - sprintf(count,"#0x%.4x",8<>12)&5; - rea =(op>> 9)&7; - dir =(op>> 8)&1; // er,re - size=(op>> 6)&3; if (size>=3) return 1; - ea = op&0x3f; - - if (dir && ea<0x10) return 1; // addx/subx opcode - - // See if we can do this opcode: - if (dir==0 && EaCanRead (ea,size)==0) return 1; - if (dir && EaCanWrite(ea)==0) return 1; - if ((size==0||!(type&1))&&EaAn(ea)) return 1; - - use=OpBase(op,size); - use&=~0x0e00; // Use same opcode for Dn - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,ea); Cycles=4; - - EaCalcReadNoSE(dir?11:-1,0,ea,size,0x003f); - - EaCalcReadNoSE(dir?-1:11,1,rea,size,0x0e00); - - ot(";@ Do arithmetic:\n"); - if (type==0) strop = "orr"; - if (type==1) strop = (char *) (dir ? "subs" : "rsbs"); - if (type==4) strop = "and"; - if (type==5) strop = "adds"; - - if (size==0) asl=",asl #24"; - if (size==1) asl=",asl #16"; - - if (size<2) ot(" mov r0,r0%s\n",asl); - ot(" %s r1,r0,r1%s\n",strop,asl); - - if ((type&1)==0) ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n"); - - OpGetFlags(type==1,type&1); // 1==subtract - ot("\n"); - - ot(";@ Save result:\n"); - if (size<2) ot(" mov r1,r1,asr #%d\n",size?16:24); - if (dir) EaWrite(11, 1, ea,size,0x003f,0,0); - else EaWrite(11, 1,rea,size,0x0e00,0,0); - - if(rea==ea) { - if(ea<8) Cycles=(size>=2)?8:4; else Cycles+=(size>=2)?26:14; - } else if(dir) { - Cycles+=4; - if(size>=2) Cycles+=4; - } else { - if(size>=2) { - Cycles+=2; - if(ea<0x10||ea==0x3c) Cycles+=2; - } - } - - OpEnd(ea); - - return 0; -} - -// --------------------- Opcodes 0x80c0+ --------------------- -int OpMul(int op) -{ - // Div/Mul: 1m00nnns 11eeeeee (m=Mul, nnn=Register Dn, s=signed, eeeeee=EA) - int type=0,rea=0,sign=0,ea=0; - int use=0; - - type=(op>>14)&1; // div/mul - rea =(op>> 9)&7; - sign=(op>> 8)&1; - ea = op&0x3f; - - // See if we can do this opcode: - if (EaCanRead(ea,1)==0||EaAn(ea)) return 1; - - use=OpBase(op,1); - use&=~0x0e00; // Use same for all registers - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,ea); - if(type) Cycles=54; - else Cycles=sign?158:140; - - EaCalcReadNoSE(-1,0,ea,1,0x003f); - - EaCalc(11,0x0e00,rea, 2); - EaRead(11, 2,rea, 2,0x0e00); - - ot(" movs r1,r0,asl #16\n"); - - if (type==0) // div - { - // the manual says C is always cleared, but neither Musashi nor FAME do that - //ot(" bic r10,r10,#0x20000000 ;@ always clear C\n"); - ot(" beq divzero%.4x ;@ division by zero\n",op); - ot("\n"); - - if (sign) - { - ot(" mov r12,#0 ;@ r12 = 1 or 2 if the result is negative\n"); - ot(" tst r2,r2\n"); - ot(" orrmi r12,r12,#2\n"); - ot(" rsbmi r2,r2,#0 ;@ Make r2 positive\n"); - ot("\n"); - ot(" movs r0,r1,asr #16\n"); - ot(" orrmi r12,r12,#1\n"); - ot(" rsbmi r0,r0,#0 ;@ Make r0 positive\n"); - ot("\n"); - ot(";@ detect the nasty 0x80000000 / -1 situation\n"); - ot(" mov r3,r2,asr #31\n"); - ot(" eors r3,r3,r1,asr #16\n"); - ot(" beq wrendofop%.4x\n",op); - } - else - { - ot(" mov r0,r1,lsr #16 ;@ use only 16 bits of divisor\n"); - } - - ot("\n"); - ot(";@ Divide r2 by r0\n"); - ot(" mov r3,#0\n"); - ot(" mov r1,r0\n"); - ot("\n"); - ot(";@ Shift up divisor till it's just less than numerator\n"); - ot("Shift%.4x%s\n",op,ms?"":":"); - ot(" cmp r1,r2,lsr #1\n"); - ot(" movls r1,r1,lsl #1\n"); - ot(" bcc Shift%.4x\n",op); - ot("\n"); - - ot("Divide%.4x%s\n",op,ms?"":":"); - ot(" cmp r2,r1\n"); - ot(" adc r3,r3,r3 ;@ Double r3 and add 1 if carry set\n"); - ot(" subcs r2,r2,r1\n"); - ot(" teq r1,r0\n"); - ot(" movne r1,r1,lsr #1\n"); - ot(" bne Divide%.4x\n",op); - ot("\n"); - ot(";@r3==quotient,r2==remainder\n"); - - if (sign) - { - // sign correction - ot(" and r1,r12,#1\n"); - ot(" teq r1,r12,lsr #1\n"); - ot(" rsbne r3,r3,#0 ;@ negate if quotient is negative\n"); - ot(" tst r12,#2\n"); - ot(" rsbne r2,r2,#0 ;@ negate the remainder if divident was negative\n"); - ot("\n"); - - // signed overflow check - ot(" mov r1,r3,asl #16\n"); - ot(" cmp r3,r1,asr #16 ;@ signed overflow?\n"); - ot(" orrne r10,r10,#0x10000000 ;@ set overflow flag\n"); - ot(" bne endofop%.4x ;@ overflow!\n",op); - ot("\n"); - ot("wrendofop%.4x%s\n",op,ms?"":":"); - } - else - { - // overflow check - ot(" movs r1,r3,lsr #16 ;@ check for overflow condition\n"); - ot(" orrne r10,r10,#0x10000000 ;@ set overflow flag\n"); - ot(" bne endofop%.4x ;@ overflow!\n",op); - ot("\n"); - } - - ot(" mov r1,r3,lsl #16 ;@ Clip to 16-bits\n"); - ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n"); - OpGetFlags(0,0); - - ot(" mov r1,r1,lsr #16\n"); - ot(" orr r1,r1,r2,lsl #16 ;@ Insert remainder\n"); - } - - if (type==1) - { - ot(";@ Get 16-bit signs right:\n"); - ot(" mov r0,r1,%s #16\n",sign?"asr":"lsr"); - ot(" mov r2,r2,lsl #16\n"); - ot(" mov r2,r2,%s #16\n",sign?"asr":"lsr"); - ot("\n"); - - ot(" mul r1,r2,r0\n"); - ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n"); - OpGetFlags(0,0); - } - ot("\n"); - - EaWrite(11, 1,rea, 2,0x0e00,1); - - if (type==0) ot("endofop%.4x%s\n",op,ms?"":":"); - OpEnd(ea); - - if (type==0) // div - { - ot("divzero%.4x%s\n",op,ms?"":":"); - ot(" mov r0,#5 ;@ Divide by zero\n"); - ot(" bl Exception\n"); - Cycles+=38; - OpEnd(ea); - ot("\n"); - } - - return 0; -} - -// Get X Bit into carry - trashes r2 -int GetXBit(int subtract) -{ - ot(";@ Get X bit:\n"); - ot(" ldr r2,[r7,#0x4c]\n"); - if (subtract) ot(" mvn r2,r2 ;@ Invert it\n"); - ot(" msr cpsr_flg,r2 ;@ Get into Carry\n"); - ot("\n"); - return 0; -} - -// --------------------- Opcodes 0x8100+ --------------------- -// 1t00ddd1 0000asss - sbcd/abcd Ds,Dd or -(As),-(Ad) -int OpAbcd(int op) -{ - int use=0; - int type=0,sea=0,mem=0,dea=0; - - type=(op>>14)&1; // sbcd/abcd - dea =(op>> 9)&7; - mem =(op>> 3)&1; - sea = op &7; - - if (mem) { sea|=0x20; dea|=0x20; } - - use=op&~0x0e07; // Use same opcode for all registers.. - if (sea==0x27) use|=0x0007; // ___x.b -(a7) - if (dea==0x27) use|=0x0e00; // ___x.b -(a7) - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,sea,dea); Cycles=6; - - if (mem) - { - ot(";@ Get src/dest EA vals\n"); - EaCalc (0,0x000f, sea,0,1); - EaRead (0, 6, sea,0,0x000f,1); - EaCalcReadNoSE(11,0,dea,0,0x0e00); - } - else - { - ot(";@ Get src/dest reg vals\n"); - EaCalcReadNoSE(-1,6,sea,0,0x0007); - EaCalcReadNoSE(11,0,dea,0,0x0e00); - ot(" mov r6,r6,asl #24\n"); - } - ot(" mov r1,r0,asl #24\n\n"); - - ot(" bic r10,r10,#0xb1000000 ;@ clear all flags except old Z\n"); - - if (type) - { - ot(" ldr r0,[r7,#0x4c] ;@ Get X bit\n"); - ot(" mov r3,#0x00f00000\n"); - ot(" and r2,r3,r1,lsr #4\n"); - ot(" tst r0,#0x20000000\n"); - ot(" and r0,r3,r6,lsr #4\n"); - ot(" add r0,r0,r2\n"); - ot(" addne r0,r0,#0x00100000\n"); -// ot(" tst r0,#0x00800000\n"); -// ot(" orreq r10,r10,#0x01000000 ;@ Undefined V behavior\n"); - ot(" cmp r0,#0x00900000\n"); - ot(" addhi r0,r0,#0x00600000 ;@ Decimal adjust units\n"); - - ot(" mov r2,r1,lsr #28\n"); - ot(" add r0,r0,r2,lsl #24\n"); - ot(" mov r2,r6,lsr #28\n"); - ot(" add r0,r0,r2,lsl #24\n"); - ot(" cmp r0,#0x09900000\n"); - ot(" orrhi r10,r10,#0x20000000 ;@ C\n"); - ot(" subhi r0,r0,#0x0a000000\n"); -// ot(" and r3,r10,r0,lsr #3 ;@ Undefined V behavior part II\n"); -// ot(" orr r10,r10,r3,lsl #4 ;@ V\n"); - ot(" movs r0,r0,lsl #4\n"); - ot(" orrmi r10,r10,#0x90000000 ;@ Undefined N+V behavior\n"); // this is what Musashi really does - ot(" bicne r10,r10,#0x40000000 ;@ Z flag\n"); - } - else - { - ot(" ldr r0,[r7,#0x4c] ;@ Get X bit\n"); - ot(" mov r3,#0x00f00000\n"); - ot(" and r2,r3,r6,lsr #4\n"); - ot(" tst r0,#0x20000000\n"); - ot(" and r0,r3,r1,lsr #4\n"); - ot(" sub r0,r0,r2\n"); - ot(" subne r0,r0,#0x00100000\n"); -// ot(" tst r0,#0x00800000\n"); -// ot(" orreq r10,r10,#0x01000000 ;@ Undefined V behavior\n"); - ot(" cmp r0,#0x00900000\n"); - ot(" subhi r0,r0,#0x00600000 ;@ Decimal adjust units\n"); - - ot(" mov r2,r1,lsr #28\n"); - ot(" add r0,r0,r2,lsl #24\n"); - ot(" mov r2,r6,lsr #28\n"); - ot(" sub r0,r0,r2,lsl #24\n"); - ot(" cmp r0,#0x09900000\n"); - ot(" orrhi r10,r10,#0xa0000000 ;@ N and C\n"); - ot(" addhi r0,r0,#0x0a000000\n"); -// ot(" and r3,r10,r0,lsr #3 ;@ Undefined V behavior part II\n"); -// ot(" orr r10,r10,r3,lsl #4 ;@ V\n"); - ot(" movs r0,r0,lsl #4\n"); -// ot(" orrmi r10,r10,#0x80000000 ;@ Undefined N behavior\n"); - ot(" bicne r10,r10,#0x40000000 ;@ Z flag\n"); - } - - ot(" str r10,[r7,#0x4c] ;@ Save X bit\n"); - ot("\n"); - - EaWrite(11, 0, dea,0,0x0e00,1); - - ot(" ldr r6,[r7,#0x54]\n"); - OpEnd(sea,dea); - - return 0; -} - -// 01001000 00eeeeee - nbcd -int OpNbcd(int op) -{ - int use=0; - int ea=0; - - ea=op&0x3f; - - if(EaCanWrite(ea)==0||EaAn(ea)) return 1; - - use=OpBase(op,0); - if(op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,ea); Cycles=6; - if(ea >= 8) Cycles+=2; - - EaCalcReadNoSE(6,0,ea,0,0x003f); - - // this is rewrite of Musashi's code - ot(" ldr r2,[r7,#0x4c]\n"); - ot(" bic r10,r10,#0xb0000000 ;@ clear all flags, except Z\n"); - ot(" mov r0,r0,asl #24\n"); - ot(" and r2,r2,#0x20000000\n"); - ot(" add r2,r0,r2,lsr #5 ;@ add X\n"); - ot(" rsb r11,r2,#0x9a000000 ;@ do arithmetic\n"); - - ot(" cmp r11,#0x9a000000\n"); - ot(" beq finish%.4x\n",op); - ot("\n"); - - ot(" mvn r3,r11,lsr #31 ;@ Undefined V behavior\n",op); - ot(" and r2,r11,#0x0f000000\n"); - ot(" cmp r2,#0x0a000000\n"); - ot(" andeq r11,r11,#0xf0000000\n"); - ot(" addeq r11,r11,#0x10000000\n"); - ot(" and r3,r3,r11,lsr #31 ;@ Undefined V behavior part II\n",op); - ot(" movs r1,r11,asr #24\n"); - ot(" bicne r10,r10,#0x40000000 ;@ Z\n"); - ot(" orr r10,r10,r3,lsl #28 ;@ save V\n",op); - ot(" orr r10,r10,#0x20000000 ;@ C\n"); - ot("\n"); - - EaWrite(6, 1, ea,0,0x3f,0,0); - - ot("finish%.4x%s\n",op,ms?"":":"); - ot(" tst r11,r11\n"); - ot(" orrmi r10,r10,#0x80000000 ;@ N\n"); - ot(" str r10,[r7,#0x4c] ;@ Save X\n"); - ot("\n"); - - ot(" ldr r6,[r7,#0x54]\n"); - OpEnd(ea); - - return 0; -} - -// --------------------- Opcodes 0x90c0+ --------------------- -// Suba/Cmpa/Adda 1tt1nnnx 11eeeeee (tt=type, x=size, eeeeee=Source EA) -int OpAritha(int op) -{ - int use=0; - int type=0,size=0,sea=0,dea=0; - const char *asr=""; - - // Suba/Cmpa/Adda/(invalid): - type=(op>>13)&3; if (type>=3) return 1; - - size=(op>>8)&1; size++; - dea=(op>>9)&7; dea|=8; // Dest=An - sea=op&0x003f; // Source - - // See if we can do this opcode: - if (EaCanRead(sea,size)==0) return 1; - - use=OpBase(op,size); - use&=~0x0e00; // Use same opcode for An - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,sea); Cycles=(size==2)?6:8; - if(size==2&&(sea<0x10||sea==0x3c)) Cycles+=2; - if(type==1) Cycles=6; - - // EA calculation order defines how situations like suba.w (A0)+, A0 get handled. - // different emus act differently in this situation, I couldn't fugure which is right behaviour. - //if (type == 1) - { - EaCalcReadNoSE(-1,0,sea,size,0x003f); - EaCalcReadNoSE(type!=1?11:-1,1,dea,2,0x0e00); - } -#if 0 - else - { - EaCalcReadNoSE(type!=1?11:-1,1,dea,2,0x0e00); - EaCalcReadNoSE(-1,0,sea,size,0x003f); - } -#endif - - if (size<2) ot(" mov r0,r0,asl #%d\n\n",size?16:24); - if (size<2) asr=(char *)(size?",asr #16":",asr #24"); - - if (type==0) ot(" sub r1,r1,r0%s\n",asr); - if (type==1) ot(" cmp r1,r0%s ;@ Defines NZCV\n",asr); - if (type==1) OpGetFlags(1,0); // Get Cmp flags - if (type==2) ot(" add r1,r1,r0%s\n",asr); - ot("\n"); - - if (type!=1) EaWrite(11, 1, dea,2,0x0e00); - - OpEnd(sea); - - return 0; -} - -// --------------------- Opcodes 0x9100+ --------------------- -// Emit a Subx/Addx opcode, 1t01ddd1 zz00rsss addx.z Ds,Dd -int OpAddx(int op) -{ - int use=0; - int type=0,size=0,dea=0,sea=0,mem=0; - const char *asl=""; - - type=(op>>14)&1; - dea =(op>> 9)&7; - size=(op>> 6)&3; if (size>=3) return 1; - sea = op&7; - mem =(op>> 3)&1; - - // See if we can do this opcode: - if (EaCanRead(sea,size)==0) return 1; - if (EaCanWrite(dea)==0) return 1; - - if (mem) { sea+=0x20; dea+=0x20; } - - use=op&~0x0e07; // Use same opcode for Dn - if (size==0&&sea==0x27) use|=0x0007; // ___x.b -(a7) - if (size==0&&dea==0x27) use|=0x0e00; // ___x.b -(a7) - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,sea,dea); Cycles=4; - if(size>=2) Cycles+=4; - if(sea>=0x10) Cycles+=2; - - if (mem) - { - ot(";@ Get src/dest EA vals\n"); - EaCalc (0,0x000f, sea,size,1); - EaRead (0, 6, sea,size,0x000f,1); - EaCalcReadNoSE(11,0,dea,size,0x0e00); - } - else - { - ot(";@ Get src/dest reg vals\n"); - EaCalcReadNoSE(-1,6,sea,size,0x0007); - EaCalcReadNoSE(11,0,dea,size,0x0e00); - if (size<2) ot(" mov r6,r6,asl #%d\n\n",size?16:24); - } - - if (size<2) asl=(char *)(size?",asl #16":",asl #24"); - - ot(";@ Do arithmetic:\n"); - GetXBit(type==0); - - if (type==1 && size<2) - { - ot(";@ Make sure the carry bit will tip the balance:\n"); - ot(" mvn r2,#0\n"); - ot(" orr r6,r6,r2,lsr #%i\n",(size==0)?8:16); - ot("\n"); - } - - if (type==0) ot(" rscs r1,r6,r0%s\n",asl); - if (type==1) ot(" adcs r1,r6,r0%s\n",asl); - ot(" orr r3,r10,#0xb0000000 ;@ for old Z\n"); - OpGetFlags(type==0,1,0); // subtract - if (size<2) { - ot(" movs r2,r1,lsr #%i\n", size?16:24); - ot(" orreq r10,r10,#0x40000000 ;@ add potentially missed Z\n"); - } - ot(" andeq r10,r10,r3 ;@ fix Z\n"); - ot("\n"); - - ot(";@ Save result:\n"); - EaWrite(11, 1, dea,size,0x0e00,1); - - ot(" ldr r6,[r7,#0x54]\n"); - OpEnd(sea,dea); - - return 0; -} - -// --------------------- Opcodes 0xb000+ --------------------- -// Emit a Cmp/Eor opcode, 1011rrrt xxeeeeee (rrr=Dn, t=cmp/eor, xx=size extension, eeeeee=ea) -int OpCmpEor(int op) -{ - int rea=0,eor=0; - int size=0,ea=0,use=0; - const char *asl=""; - - // Get EA and register EA - rea=(op>>9)&7; - eor=(op>>8)&1; - size=(op>>6)&3; if (size>=3) return 1; - ea=op&0x3f; - - if (eor && (ea>>3) == 1) return 1; // not a valid mode for eor - - // See if we can do this opcode: - if (EaCanRead(ea,size)==0) return 1; - if (eor && EaCanWrite(ea)==0) return 1; - if (EaAn(ea)&&(eor||size==0)) return 1; - - use=OpBase(op,size); - use&=~0x0e00; // Use 1 handler for register d0-7 - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,ea); Cycles=4; - if(eor) { - if(ea>8) Cycles+=4; - if(size>=2) Cycles+=4; - } else { - if(size>=2) Cycles+=2; - } - - ot(";@ Get EA into r11 and value into r0:\n"); - EaCalcReadNoSE(eor?11:-1,0,ea,size,0x003f); - - ot(";@ Get register operand into r1:\n"); - EaCalcReadNoSE(-1,1,rea,size,0x0e00); - - if (size<2) ot(" mov r0,r0,asl #%d\n\n",size?16:24); - if (size<2) asl=(char *)(size?",asl #16":",asl #24"); - - ot(";@ Do arithmetic:\n"); - if (eor==0) ot(" rsbs r1,r0,r1%s\n",asl); - if (eor) - { - ot(" eor r1,r0,r1%s\n",asl); - ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n"); - } - - OpGetFlags(eor==0,0); // Cmp like subtract - ot("\n"); - - if (eor) EaWrite(11, 1,ea,size,0x003f,1); - - OpEnd(ea); - return 0; -} - -// Emit a Cmpm opcode, 1011ddd1 xx001sss (rrr=Adst, xx=size extension, sss=Asrc) -int OpCmpm(int op) -{ - int size=0,sea=0,dea=0,use=0; - const char *asl=""; - - // get size, get EAs - size=(op>>6)&3; if (size>=3) return 1; - sea=(op&7)|0x18; - dea=(op>>9)&0x3f; - - use=op&~0x0e07; // Use 1 handler for all registers.. - if (size==0&&sea==0x1f) use|=0x0007; // ..except (a7)+ - if (size==0&&dea==0x1f) use|=0x0e00; - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,sea); Cycles=4; - - ot(";@ Get src operand into r11:\n"); - EaCalc (0,0x0007, sea,size,1); - EaRead (0, 11, sea,size,0x0007,1); - - ot(";@ Get dst operand into r0:\n"); - EaCalcReadNoSE(-1,0,dea,size,0x0e00); - - if (size<2) asl=(char *)(size?",asl #16":",asl #24"); - - ot(" rsbs r0,r11,r0%s\n",asl); - OpGetFlags(1,0); // Cmp like subtract - ot("\n"); - - OpEnd(sea); - return 0; -} - - -// Emit a Chk opcode, 0100ddd1 x0eeeeee (rrr=Dn, x=size extension, eeeeee=ea) -int OpChk(int op) -{ - int rea=0; - int size=0,ea=0,use=0; - - // Get EA and register EA - rea=(op>>9)&7; - if((op>>7)&1) - size=1; // word operation - else size=2; // long - ea=op&0x3f; - - if (EaAn(ea)) return 1; // not a valid mode - if (size!=1) return 1; // 000 variant only supports word - - // See if we can do this opcode: - if (EaCanRead(ea,size)==0) return 1; - - use=OpBase(op,size); - use&=~0x0e00; // Use 1 handler for register d0-7 - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,ea); Cycles=10; - - ot(";@ Get value into r0:\n"); - EaCalcReadNoSE(-1,0,ea,size,0x003f); - - ot(";@ Get register operand into r1:\n"); - EaCalcReadNoSE(-1,1,rea,size,0x0e00); - - if (size<2) ot(" mov r0,r0,asl #%d\n",size?16:24); - if (size<2) ot(" mov r1,r1,asl #%d\n\n",size?16:24); - - ot(";@ get flags, including undocumented ones\n"); - ot(" and r3,r10,#0x80000000\n"); - ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n"); - OpGetFlags(0,0); - - ot(";@ is reg negative?\n"); - ot(" bmi chktrap%.4x\n",op); - - ot(";@ Do arithmetic:\n"); - ot(" bic r10,r10,#0x80000000 ;@ N\n"); - ot(" cmp r1,r0\n"); - ot(" bgt chktrap%.4x\n",op); - - ot(";@ old N remains\n"); - ot(" orr r10,r10,r3\n"); - OpEnd(ea); - - ot("chktrap%.4x%s ;@ CHK exception:\n",op,ms?"":":"); - ot(" mov r0,#6\n"); - ot(" bl Exception\n"); - Cycles+=40; - OpEnd(ea); - - return 0; -} - diff --git a/cpu/Cyclone/OpBranch.cpp b/cpu/Cyclone/OpBranch.cpp deleted file mode 100644 index 63569da..0000000 --- a/cpu/Cyclone/OpBranch.cpp +++ /dev/null @@ -1,517 +0,0 @@ - -#include "app.h" - -// in/out address in r0, trashes all temp regs -static void CheckPc(void) -{ -#if USE_CHECKPC_CALLBACK - #ifdef MEMHANDLERS_DIRECT_PREFIX - ot(" bl %scheckpc ;@ Call checkpc()\n", MEMHANDLERS_DIRECT_PREFIX); - #else - ot(";@ Check Memory Base+pc\n"); - ot(" mov lr,pc\n"); - ot(" ldr pc,[r7,#0x64] ;@ Call checkpc()\n"); - ot("\n"); - #endif -#endif -} - -// Push 32-bit value in r1 - trashes r0-r3,r12,lr -void OpPush32() -{ - ot(";@ Push r1 onto stack\n"); - ot(" ldr r0,[r7,#0x3c]\n"); - ot(" sub r0,r0,#4 ;@ Predecrement A7\n"); - ot(" str r0,[r7,#0x3c] ;@ Save A7\n"); - MemHandler(1,2); - ot("\n"); -} - -// Push SR - trashes r0-r3,r12,lr -void OpPushSr(int high) -{ - ot(";@ Push SR:\n"); - OpFlagsToReg(high); - ot(" ldr r0,[r7,#0x3c]\n"); - ot(" sub r0,r0,#2 ;@ Predecrement A7\n"); - ot(" str r0,[r7,#0x3c] ;@ Save A7\n"); - MemHandler(1,1); - ot("\n"); -} - -// Pop SR - trashes r0-r3 -static void PopSr(int high) -{ - ot(";@ Pop SR:\n"); - ot(" ldr r0,[r7,#0x3c]\n"); - ot(" add r1,r0,#2 ;@ Postincrement A7\n"); - ot(" str r1,[r7,#0x3c] ;@ Save A7\n"); - MemHandler(0,1); - ot("\n"); - OpRegToFlags(high); -} - -// Pop PC - trashes r0-r3 -static void PopPc() -{ - ot(";@ Pop PC:\n"); - ot(" ldr r0,[r7,#0x3c]\n"); - ot(" add r1,r0,#4 ;@ Postincrement A7\n"); - ot(" str r1,[r7,#0x3c] ;@ Save A7\n"); - MemHandler(0,2); - ot(" ldr r1,[r7,#0x60] ;@ Get Memory base\n"); - ot(" add r0,r0,r1 ;@ Memory Base+PC\n"); - ot("\n"); - CheckPc(); -#if EMULATE_ADDRESS_ERRORS_JUMP - ot(" mov r4,r0\n"); -#else - ot(" bic r4,r0,#1\n"); -#endif -} - -int OpTrap(int op) -{ - int use=0; - - use=op&~0xf; - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,0x10); - ot(" and r0,r8,#0xf ;@ Get trap number\n"); - ot(" orr r0,r0,#0x20 ;@ 32+n\n"); - ot(" bl Exception\n"); - ot("\n"); - - Cycles=38; OpEnd(0x10); - - return 0; -} - -// --------------------- Opcodes 0x4e50+ --------------------- -int OpLink(int op) -{ - int use=0,reg; - - use=op&~7; - reg=op&7; - if (reg==7) use=op; - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,0x10); - - if(reg!=7) { - ot(";@ Get An\n"); - EaCalc(11, 7, 8, 2, 1); - EaRead(11, 1, 8, 2, 7, 1); - } - - ot(" ldr r0,[r7,#0x3c] ;@ Get A7\n"); - ot(" sub r0,r0,#4 ;@ A7-=4\n"); - ot(" mov r8,r0 ;@ abuse r8\n"); - if(reg==7) ot(" mov r1,r0\n"); - ot("\n"); - - ot(";@ Write An to Stack\n"); - MemHandler(1,2); - - ot(";@ Save to An\n"); - if(reg!=7) - EaWrite(11,8, 8, 2, 7, 1); - - ot(";@ Get offset:\n"); - EaCalc(0,0,0x3c,1); // abused r8 is ok because of imm EA - EaRead(0,0,0x3c,1,0); - - ot(" add r8,r8,r0 ;@ Add offset to A7\n"); - ot(" str r8,[r7,#0x3c]\n"); - ot("\n"); - - Cycles=16; - OpEnd(0x10); - return 0; -} - -// --------------------- Opcodes 0x4e58+ --------------------- -int OpUnlk(int op) -{ - int use=0; - - use=op&~7; - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,0x10); - - ot(";@ Get An\n"); - EaCalc(11, 0xf, 8, 2, 1); - EaRead(11, 0, 8, 2, 0xf, 1); - - ot(" add r8,r0,#4 ;@ A7+=4, abuse r8\n"); - ot("\n"); - ot(";@ Pop An from stack:\n"); - MemHandler(0,2); - ot("\n"); - ot(" str r8,[r7,#0x3c] ;@ Save A7\n"); - ot("\n"); - ot(";@ An = value from stack:\n"); - EaWrite(11, 0, 8, 2, 7, 1); - - Cycles=12; - OpEnd(0x10); - return 0; -} - -// --------------------- Opcodes 0x4e70+ --------------------- -// 01001110 01110ttt -int Op4E70(int op) -{ - int type=0; - - type=op&7; // reset/nop/stop/rte/rtd/rts/trapv/rtr - - switch (type) - { - case 1: // nop - OpStart(op); - Cycles=4; - OpEnd(); - return 0; - - case 3: // rte - OpStart(op,0x10,0,0,1); Cycles=20; - PopSr(1); - PopPc(); - ot(" ldr r1,[r7,#0x44] ;@ reload SR high\n"); - SuperChange(op,1); -#if EMULATE_ADDRESS_ERRORS_JUMP || EMULATE_ADDRESS_ERRORS_IO || EMULATE_HALT - ot(" ldr r1,[r7,#0x58]\n"); - ot(" bic r1,r1,#0x0c ;@ clear 'not processing instruction' and 'doing addr error' bits\n"); - ot(" str r1,[r7,#0x58]\n"); -#endif -#if EMULATE_ADDRESS_ERRORS_JUMP - ot(" tst r4,#1 ;@ address error?\n"); - ot(" bne ExceptionAddressError_r_prg_r4\n"); -#endif - opend_check_interrupt = 1; - opend_check_trace = 1; - OpEnd(0x10,0); - return 0; - - case 5: // rts - OpStart(op,0x10); Cycles=16; - PopPc(); -#if EMULATE_ADDRESS_ERRORS_JUMP - ot(" tst r4,#1 ;@ address error?\n"); - ot(" bne ExceptionAddressError_r_prg_r4\n"); -#endif - OpEnd(0x10); - return 0; - - case 6: // trapv - OpStart(op,0x10,0,1); Cycles=4; - ot(" tst r10,#0x10000000\n"); - ot(" subne r5,r5,#%i\n",34); - ot(" movne r0,#7 ;@ TRAPV exception\n"); - ot(" blne Exception\n"); - opend_op_changes_cycles = 1; - OpEnd(0x10,0); - return 0; - - case 7: // rtr - OpStart(op,0x10); Cycles=20; - PopSr(0); - PopPc(); -#if EMULATE_ADDRESS_ERRORS_JUMP - ot(" tst r4,#1 ;@ address error?\n"); - ot(" bne ExceptionAddressError_r_prg_r4\n"); -#endif - OpEnd(0x10); - return 0; - - default: - return 1; - } -} - -// --------------------- Opcodes 0x4e80+ --------------------- -// Emit a Jsr/Jmp opcode, 01001110 1meeeeee -int OpJsr(int op) -{ - int use=0; - int sea=0; - - sea=op&0x003f; - - // See if we can do this opcode: - if (EaCanRead(sea,-1)==0) return 1; - - use=OpBase(op,0); - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,(op&0x40)?0:0x10); - - ot(" ldr r11,[r7,#0x60] ;@ Get Memory base\n"); - ot("\n"); - EaCalc(12,0x003f,sea,0); - - ot(";@ Jump - Get new PC from r12\n"); - ot(" add r0,r12,r11 ;@ Memory Base + New PC\n"); - ot("\n"); - CheckPc(); - if (!(op&0x40)) - { - ot(" ldr r2,[r7,#0x3c]\n"); - ot(" sub r1,r4,r11 ;@ r1 = Old PC\n"); - } -#if EMULATE_ADDRESS_ERRORS_JUMP - // jsr prefetches next instruction before pushing old PC, - // according to http://pasti.fxatari.com/68kdocs/68kPrefetch.html - ot(" mov r4,r0\n"); - ot(" tst r4,#1 ;@ address error?\n"); - ot(" bne ExceptionAddressError_r_prg_r4\n"); -#else - ot(" bic r4,r0,#1\n"); -#endif - - if (!(op&0x40)) - { - ot(";@ Push old PC onto stack\n"); - ot(" sub r0,r2,#4 ;@ Predecrement A7\n"); - ot(" str r0,[r7,#0x3c] ;@ Save A7\n"); - MemHandler(1,2); - } - - Cycles=(op&0x40) ? 4 : 12; - Cycles+=Ea_add_ns((op&0x40) ? g_jmp_cycle_table : g_jsr_cycle_table, sea); - - OpEnd((op&0x40)?0:0x10); - - return 0; -} - -// --------------------- Opcodes 0x50c8+ --------------------- - -// ARM version of 68000 condition codes: -static const char * const Cond[16]= -{ - "", "", "hi","ls","cc","cs","ne","eq", - "vc","vs","pl","mi","ge","lt","gt","le" -}; - -// Emit a Dbra opcode, 0101cccc 11001nnn vv -int OpDbra(int op) -{ - int use=0; - int cc=0; - - use=op&~7; // Use same handler - cc=(op>>8)&15; - - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - OpStart(op); - - switch (cc) - { - case 0: // T - case 1: // F - break; - case 2: // hi - ot(" tst r10,#0x60000000 ;@ hi: !C && !Z\n"); - ot(" beq DbraTrue\n\n"); - break; - case 3: // ls - ot(" tst r10,#0x60000000 ;@ ls: C || Z\n"); - ot(" bne DbraTrue\n\n"); - break; - default: - ot(";@ Is the condition true?\n"); - ot(" msr cpsr_flg,r10 ;@ ARM flags = 68000 flags\n"); - ot(";@ If so, don't dbra\n"); - ot(" b%s DbraTrue\n\n",Cond[cc]); - break; - } - - if (cc!=0) - { - ot(";@ Decrement Dn.w\n"); - ot(" and r1,r8,#0x0007\n"); - ot(" mov r1,r1,lsl #2\n"); - ot(" ldrsh r0,[r7,r1]\n"); - ot(" sub r0,r0,#1\n"); - ot(" strh r0,[r7,r1]\n"); - ot("\n"); - - ot(";@ Check if Dn.w is -1\n"); - ot(" cmn r0,#1\n"); - -#if (USE_CHECKPC_CALLBACK && USE_CHECKPC_DBRA) || EMULATE_ADDRESS_ERRORS_JUMP - ot(" beq DbraMin1\n"); - ot("\n"); - - ot(";@ Get Branch offset:\n"); - ot(" ldrsh r0,[r4]\n"); - ot(" add r0,r4,r0 ;@ r0 = New PC\n"); - CheckPc(); -#if EMULATE_ADDRESS_ERRORS_JUMP - ot(" mov r4,r0\n"); - ot(" tst r4,#1 ;@ address error?\n"); - ot(" bne ExceptionAddressError_r_prg_r4\n"); -#else - ot(" bic r4,r0,#1\n"); -#endif -#else - ot("\n"); - ot(";@ Get Branch offset:\n"); - ot(" ldrnesh r0,[r4]\n"); - ot(" addeq r4,r4,#2 ;@ Skip branch offset\n"); - ot(" subeq r5,r5,#4 ;@ additional cycles\n"); - ot(" addne r4,r4,r0 ;@ r4 = New PC\n"); - ot(" bic r4,r4,#1\n"); // we do not emulate address errors - ot("\n"); -#endif - Cycles=12-2; - OpEnd(); - } - - //if (cc==0||cc>=2) - if (op==0x50c8) - { - ot(";@ condition true:\n"); - ot("DbraTrue%s\n", ms?"":":"); - ot(" add r4,r4,#2 ;@ Skip branch offset\n"); - ot("\n"); - Cycles=12; - OpEnd(); - } - -#if (USE_CHECKPC_CALLBACK && USE_CHECKPC_DBRA) || EMULATE_ADDRESS_ERRORS_JUMP - if (op==0x51c8) - { - ot(";@ Dn.w is -1:\n"); - ot("DbraMin1%s\n", ms?"":":"); - ot(" add r4,r4,#2 ;@ Skip branch offset\n"); - ot("\n"); - Cycles=12+2; - OpEnd(); - } -#endif - - return 0; -} - -// --------------------- Opcodes 0x6000+ --------------------- -// Emit a Branch opcode 0110cccc nn (cccc=condition) -int OpBranch(int op) -{ - int size=0,use=0,checkpc=0; - int offset=0; - int cc=0; - const char *asr_r11=""; - - offset=(char)(op&0xff); - cc=(op>>8)&15; - - // Special offsets: - if (offset==0) size=1; - if (offset==-1) size=2; - - if (size==2) size=0; // 000 model does not support long displacement - if (size) use=op; // 16-bit or 32-bit - else use=(op&0xff00)+1; // Use same opcode for all 8-bit branches - - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - OpStart(op,size?0x10:0); - Cycles=10; // Assume branch taken - - switch (cc) - { - case 0: // T - case 1: // F - break; - case 2: // hi - ot(" tst r10,#0x60000000 ;@ hi: !C && !Z\n"); - ot(" bne BccDontBranch%i\n\n",8<=2&&(op&0xff00)==0x6700) - { - ot("BccDontBranch%i%s\n", 8<>6)&3; // Btst/Bchg/Bclr/Bset - // Get source and target EA - sea=(op>>9)&7; - tea=op&0x003f; - if (tea<0x10) size=2; // For registers, 32-bits - - if ((tea&0x38)==0x08) return 1; // movep - - // See if we can do this opcode: - if (EaCanRead(tea,0)==0) return 1; - if (type>0) - { - if (EaCanWrite(tea)==0) return 1; - } - - use=OpBase(op,size); - use&=~0x0e00; // Use same handler for all registers - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,tea); - - if(type==1||type==3) { - Cycles=8; - } else { - Cycles=type?8:4; - if(size>=2) Cycles+=2; - } - - EaCalcReadNoSE(-1,11,sea,0,0x0e00); - - EaCalcReadNoSE((type>0)?8:-1,0,tea,size,0x003f); - - if (tea>=0x10) - ot(" and r11,r11,#7 ;@ mem - do mod 8\n"); // size always 0 - else ot(" and r11,r11,#31 ;@ reg - do mod 32\n"); // size always 2 - ot("\n"); - - ot(" mov r1,#1\n"); - ot(" tst r0,r1,lsl r11 ;@ Do arithmetic\n"); - ot(" bicne r10,r10,#0x40000000\n"); - ot(" orreq r10,r10,#0x40000000 ;@ Get Z flag\n"); - ot("\n"); - - if (type>0) - { - if (type==1) ot(" eor r1,r0,r1,lsl r11 ;@ Toggle bit\n"); - if (type==2) ot(" bic r1,r0,r1,lsl r11 ;@ Clear bit\n"); - if (type==3) ot(" orr r1,r0,r1,lsl r11 ;@ Set bit\n"); - ot("\n"); - EaWrite(8,1,tea,size,0x003f,0,0); - } - OpEnd(tea); - - return 0; -} - -// --------------------- Opcodes 0x0800+ --------------------- -// Emit a Btst/Bchg/Bclr/Bset (Immediate) opcode 00001000 ttaaaaaa nn -int OpBtstImm(int op) -{ - int type=0,sea=0,tea=0; - int use=0; - int size=0; - - type=(op>>6)&3; - // Get source and target EA - sea= 0x003c; - tea=op&0x003f; - if (tea<0x10) size=2; // For registers, 32-bits - - // See if we can do this opcode: - if (EaCanRead(tea,0)==0||EaAn(tea)||tea==0x3c) return 1; - if (type>0) - { - if (EaCanWrite(tea)==0) return 1; - } - - use=OpBase(op,size); - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,sea,tea); - - ot("\n"); - EaCalcReadNoSE(-1,0,sea,0,0); - ot(" mov r11,#1\n"); - ot(" bic r10,r10,#0x40000000 ;@ Blank Z flag\n"); - if (tea>=0x10) - ot(" and r0,r0,#7 ;@ mem - do mod 8\n"); // size always 0 - else ot(" and r0,r0,#0x1F ;@ reg - do mod 32\n"); // size always 2 - ot(" mov r11,r11,lsl r0 ;@ Make bit mask\n"); - ot("\n"); - - if(type==1||type==3) { - Cycles=12; - } else { - Cycles=type?12:8; - if(size>=2) Cycles+=2; - } - - EaCalcReadNoSE((type>0)?8:-1,0,tea,size,0x003f); - ot(" tst r0,r11 ;@ Do arithmetic\n"); - ot(" orreq r10,r10,#0x40000000 ;@ Get Z flag\n"); - ot("\n"); - - if (type>0) - { - if (type==1) ot(" eor r1,r0,r11 ;@ Toggle bit\n"); - if (type==2) ot(" bic r1,r0,r11 ;@ Clear bit\n"); - if (type==3) ot(" orr r1,r0,r11 ;@ Set bit\n"); - ot("\n"); - EaWrite(8, 1,tea,size,0x003f,0,0); -#if CYCLONE_FOR_GENESIS && !MEMHANDLERS_CHANGE_CYCLES - // this is a bit hacky (device handlers might modify cycles) - if (tea==0x38||tea==0x39) - ot(" ldr r5,[r7,#0x5c] ;@ Load Cycles\n"); -#endif - } - - OpEnd(sea,tea); - - return 0; -} - -// --------------------- Opcodes 0x4000+ --------------------- -int OpNeg(int op) -{ - // 01000tt0 xxeeeeee (tt=negx/clr/neg/not, xx=size, eeeeee=EA) - int type=0,size=0,ea=0,use=0; - - type=(op>>9)&3; - ea =op&0x003f; - size=(op>>6)&3; if (size>=3) return 1; - - // See if we can do this opcode: - if (EaCanRead (ea,size)==0||EaAn(ea)) return 1; - if (EaCanWrite(ea )==0) return 1; - - use=OpBase(op,size); - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,ea); Cycles=size<2?4:6; - if(ea >= 0x10) Cycles*=2; - - EaCalc (11,0x003f,ea,size,0,0); - - if (type!=1) EaRead (11,0,ea,size,0x003f,0,0); // Don't need to read for 'clr' (or do we, for a dummy read?) - if (type==1) ot("\n"); - - if (type==0) - { - ot(";@ Negx:\n"); - GetXBit(1); - if(size!=2) ot(" mov r0,r0,asl #%i\n",size?16:24); - ot(" rscs r1,r0,#0 ;@ do arithmetic\n"); - ot(" orr r3,r10,#0xb0000000 ;@ for old Z\n"); - OpGetFlags(1,1,0); - if(size!=2) { - ot(" movs r1,r1,asr #%i\n",size?16:24); - ot(" orreq r10,r10,#0x40000000 ;@ possily missed Z\n"); - } - ot(" andeq r10,r10,r3 ;@ fix Z\n"); - ot("\n"); - } - - if (type==1) - { - ot(";@ Clear:\n"); - ot(" mov r1,#0\n"); - ot(" mov r10,#0x40000000 ;@ NZCV=0100\n"); - ot("\n"); - } - - if (type==2) - { - ot(";@ Neg:\n"); - if(size!=2) ot(" mov r0,r0,asl #%i\n",size?16:24); - ot(" rsbs r1,r0,#0\n"); - OpGetFlags(1,1); - if(size!=2) ot(" mov r1,r1,asr #%i\n",size?16:24); - ot("\n"); - } - - if (type==3) - { - ot(";@ Not:\n"); - if(size!=2) { - ot(" mov r0,r0,asl #%i\n",size?16:24); - ot(" mvn r1,r0,asr #%i\n",size?16:24); - } - else - ot(" mvn r1,r0\n"); - ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n"); - OpGetFlags(0,0); - ot("\n"); - } - - if (type==1) eawrite_check_addrerr=1; - EaWrite(11, 1,ea,size,0x003f,0,0); - - OpEnd(ea); - - return 0; -} - -// --------------------- Opcodes 0x4840+ --------------------- -// Swap, 01001000 01000nnn swap Dn -int OpSwap(int op) -{ - int ea=0,use=0; - - ea=op&7; - use=op&~0x0007; // Use same opcode for all An - - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op); Cycles=4; - - EaCalc (11,0x0007,ea,2,1); - EaRead (11, 0,ea,2,0x0007,1); - - ot(" mov r1,r0,ror #16\n"); - ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n"); - OpGetFlags(0,0); - - EaWrite(11, 1,8,2,0x0007,1); - - OpEnd(); - - return 0; -} - -// --------------------- Opcodes 0x4a00+ --------------------- -// Emit a Tst opcode, 01001010 xxeeeeee -int OpTst(int op) -{ - int sea=0; - int size=0,use=0; - - sea=op&0x003f; - size=(op>>6)&3; if (size>=3) return 1; - - // See if we can do this opcode: - if (EaCanWrite(sea)==0||EaAn(sea)) return 1; - - use=OpBase(op,size); - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,sea); Cycles=4; - - EaCalc ( 0,0x003f,sea,size,1); - EaRead ( 0, 0,sea,size,0x003f,1); - - ot(" adds r0,r0,#0 ;@ Defines NZ, clears CV\n"); - ot(" mrs r10,cpsr ;@ r10=flags\n"); - ot("\n"); - - OpEnd(sea); - return 0; -} - -// --------------------- Opcodes 0x4880+ --------------------- -// Emit an Ext opcode, 01001000 1x000nnn -int OpExt(int op) -{ - int ea=0; - int size=0,use=0; - int shift=0; - - ea=op&0x0007; - size=(op>>6)&1; - shift=32-(8<>8)&15; - ea=op&0x003f; - - if ((ea&0x38)==0x08) return 1; // dbra, not scc - - // See if we can do this opcode: - if (EaCanWrite(ea)==0) return 1; - - use=OpBase(op,size); - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - changed_cycles=ea<8 && cc>=2; - OpStart(op,ea,0,changed_cycles); Cycles=8; - if (ea<8) Cycles=4; - - if (cc) - ot(" mov r1,#0\n"); - - switch (cc) - { - case 0: // T - ot(" mvn r1,#0\n"); - if (ea<8) Cycles+=2; - break; - case 1: // F - break; - case 2: // hi - ot(" tst r10,#0x60000000 ;@ hi: !C && !Z\n"); - ot(" mvneq r1,r1\n"); - if (ea<8) ot(" subeq r5,r5,#2 ;@ Extra cycles\n"); - break; - case 3: // ls - ot(" tst r10,#0x60000000 ;@ ls: C || Z\n"); - ot(" mvnne r1,r1\n"); - if (ea<8) ot(" subne r5,r5,#2 ;@ Extra cycles\n"); - break; - default: - ot(";@ Is the condition true?\n"); - ot(" msr cpsr_flg,r10 ;@ ARM flags = 68000 flags\n"); - ot(" mvn%s r1,r1\n",cond[cc]); - if (ea<8) ot(" sub%s r5,r5,#2 ;@ Extra cycles\n",cond[cc]); - break; - } - - ot("\n"); - - eawrite_check_addrerr=1; - EaCalc (0,0x003f, ea,size,0,0); - EaWrite(0, 1, ea,size,0x003f,0,0); - - opend_op_changes_cycles=changed_cycles; - OpEnd(ea,0); - return 0; -} - -// Emit a Asr/Lsr/Roxr/Ror opcode -static int EmitAsr(int op,int type,int dir,int count,int size,int usereg) -{ - char pct[8]=""; // count - int shift=32-(8<=1) sprintf(pct,"#%d",count); // Fixed count - - if (usereg) - { - ot(";@ Use Dn for count:\n"); - ot(" and r2,r8,#0x0e00\n"); - ot(" ldr r2,[r7,r2,lsr #7]\n"); - ot(" and r2,r2,#63\n"); - ot("\n"); - strcpy(pct,"r2"); - } - else if (count<0) - { - ot(" mov r2,r8,lsr #9 ;@ Get 'n'\n"); - ot(" and r2,r2,#7\n\n"); strcpy(pct,"r2"); - } - - // Take 2*n cycles: - if (count<0) ot(" sub r5,r5,r2,asl #1 ;@ Take 2*n cycles\n\n"); - else Cycles+=count<<1; - - if (type<2) - { - // Asr/Lsr - if (dir==0 && size<2) - { - ot(";@ For shift right, use loworder bits for the operation:\n"); - ot(" mov r0,r0,%s #%d\n",type?"lsr":"asr",32-(8<>9)&7; - dir =(op>>8)&1; - size =(op>>6)&3; - if (size>=3) return 1; // use OpAsrEa() - usereg=(op>>5)&1; - type =(op>>3)&3; - - if (usereg==0) count=((count-1)&7)+1; // because ccc=000 means 8 - - // Use the same opcode for target registers: - use=op&~0x0007; - - // As long as count is not 8, use the same opcode for all shift counts: - if (usereg==0 && count!=8 && !(count==1&&type==2)) { use|=0x0e00; count=-1; } - if (usereg) { use&=~0x0e00; count=-1; } // Use same opcode for all Dn - - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,ea,0,count<0); Cycles=size<2?6:8; - - EaCalc(11,0x0007, ea,size,1); - EaRead(11, 0, ea,size,0x0007,1); - - EmitAsr(op,type,dir,count, size,usereg); - - EaWrite(11, 0, ea,size,0x0007,1); - - opend_op_changes_cycles = (count<0); - OpEnd(ea,0); - - return 0; -} - -// Asr/Lsr/Roxr/Ror etc EA - 11100ttd 11eeeeee -int OpAsrEa(int op) -{ - int use=0,type=0,dir=0,ea=0,size=1; - - type=(op>>9)&3; - dir =(op>>8)&1; - ea = op&0x3f; - - if (ea<0x10) return 1; - // See if we can do this opcode: - if (EaCanRead(ea,0)==0) return 1; - if (EaCanWrite(ea)==0) return 1; - - use=OpBase(op,size); - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,ea); Cycles=6; // EmitAsr() will add 2 - - EaCalc (11,0x003f,ea,size,1); - EaRead (11, 0,ea,size,0x003f,1); - - EmitAsr(op,type,dir,1,size,0); - - EaWrite(11, 0,ea,size,0x003f,1); - - OpEnd(ea); - return 0; -} - -int OpTas(int op, int gen_special) -{ - int ea=0; - int use=0; - - ea=op&0x003f; - - // See if we can do this opcode: - if (EaCanWrite(ea)==0 || EaAn(ea)) return 1; - - use=OpBase(op,0); - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - if (!gen_special) OpStart(op,ea); - else - ot("Op%.4x_%s\n", op, ms?"":":"); - - Cycles=4; - if(ea>=8) Cycles+=10; - - EaCalc (11,0x003f,ea,0,1); - EaRead (11, 1,ea,0,0x003f,1); - - ot(" adds r1,r1,#0 ;@ Defines NZ, clears CV\n"); - OpGetFlags(0,0); - ot("\n"); - -#if CYCLONE_FOR_GENESIS - // the original Sega hardware ignores write-back phase (to memory only) - if (ea < 0x10 || gen_special) { -#endif - ot(" orr r1,r1,#0x80000000 ;@ set bit7\n"); - - EaWrite(11, 1,ea,0,0x003f,1); -#if CYCLONE_FOR_GENESIS - } -#endif - - OpEnd(ea); - -#if (CYCLONE_FOR_GENESIS == 2) - if (!gen_special && ea >= 0x10) { - OpTas(op, 1); - } -#endif - - return 0; -} - diff --git a/cpu/Cyclone/OpMove.cpp b/cpu/Cyclone/OpMove.cpp deleted file mode 100644 index 78adae5..0000000 --- a/cpu/Cyclone/OpMove.cpp +++ /dev/null @@ -1,685 +0,0 @@ - -#include "app.h" - - -// Pack our flags into r1, in SR/CCR register format -// trashes r0,r2 -void OpFlagsToReg(int high) -{ - ot(" ldr r0,[r7,#0x4c] ;@ X bit\n"); - ot(" mov r1,r10,lsr #28 ;@ ____NZCV\n"); - ot(" eor r2,r1,r1,ror #1 ;@ Bit 0=C^V\n"); - ot(" tst r2,#1 ;@ 1 if C!=V\n"); - ot(" eorne r1,r1,#3 ;@ ____NZVC\n"); - ot("\n"); - if (high) ot(" ldrb r2,[r7,#0x44] ;@ Include SR high\n"); - ot(" and r0,r0,#0x20000000\n"); - ot(" orr r1,r1,r0,lsr #25 ;@ ___XNZVC\n"); - if (high) ot(" orr r1,r1,r2,lsl #8\n"); - ot("\n"); -} - -// Convert SR/CRR register in r0 to our flags -// trashes r0,r1 -void OpRegToFlags(int high, int srh_reg) -{ - ot(" eor r1,r0,r0,ror #1 ;@ Bit 0=C^V\n"); - ot(" mov r2,r0,lsl #25\n"); - ot(" tst r1,#1 ;@ 1 if C!=V\n"); - ot(" eorne r0,r0,#3 ;@ ___XNZCV\n"); - ot(" str r2,[r7,#0x4c] ;@ Store X bit\n"); - ot(" mov r10,r0,lsl #28 ;@ r10=NZCV...\n"); - - if (high) - { - int mask=EMULATE_TRACE?0xa7:0x27; - ot(" mov r%i,r0,ror #8\n",srh_reg); - ot(" and r%i,r%i,#0x%02x ;@ only take defined bits\n",srh_reg,srh_reg,mask); - ot(" strb r%i,[r7,#0x44] ;@ Store SR high\n",srh_reg); - } - ot("\n"); -} - -void SuperEnd(void) -{ - ot(";@ ----------\n"); - ot(";@ tried execute privileged instruction in user mode\n"); - ot("WrongPrivilegeMode%s\n",ms?"":":"); -#if EMULATE_ADDRESS_ERRORS_JUMP || EMULATE_ADDRESS_ERRORS_IO - ot(" ldr r1,[r7,#0x58]\n"); - ot(" sub r4,r4,#2 ;@ last opcode wasn't executed - go back\n"); - ot(" orr r1,r1,#4 ;@ set activity bit: 'not processing instruction'\n"); - ot(" str r1,[r7,#0x58]\n"); -#else - ot(" sub r4,r4,#2 ;@ last opcode wasn't executed - go back\n"); -#endif - ot(" mov r0,#8 ;@ privilege violation\n"); - ot(" bl Exception\n"); - Cycles=34; - OpEnd(0); -} - -// does OSP and A7 swapping if needed -// new or old SR (not the one already in [r7,#0x44]) should be passed in r11 -// uses srh from srh_reg (loads if < 0), trashes r0,r11 -void SuperChange(int op,int srh_reg) -{ - ot(";@ A7 <-> OSP?\n"); - if (srh_reg < 0) { - ot(" ldr r0,[r7,#0x44] ;@ Get other SR high\n"); - srh_reg=0; - } - ot(" eor r0,r%i,r11\n",srh_reg); - ot(" tst r0,#0x20\n"); - ot(" beq no_sp_swap%.4x\n",op); - ot(" ;@ swap OSP and A7:\n"); - ot(" ldr r11,[r7,#0x3C] ;@ Get A7\n"); - ot(" ldr r0, [r7,#0x48] ;@ Get OSP\n"); - ot(" str r11,[r7,#0x48]\n"); - ot(" str r0, [r7,#0x3C]\n"); - ot("no_sp_swap%.4x%s\n", op, ms?"":":"); -} - - - -// --------------------- Opcodes 0x1000+ --------------------- -// Emit a Move opcode, 00xxdddd ddssssss -int OpMove(int op) -{ - int sea=0,tea=0; - int size=0,use=0; - int movea=0; - - // Get source and target EA - sea = op&0x003f; - tea =(op&0x01c0)>>3; - tea|=(op&0x0e00)>>9; - - if (tea>=8 && tea<0x10) movea=1; - - // Find size extension - switch (op&0x3000) - { - default: return 1; - case 0x1000: size=0; break; - case 0x3000: size=1; break; - case 0x2000: size=2; break; - } - - if (size<1 && (movea || EaAn(sea))) return 1; // move.b An,* and movea.b * are invalid - - // See if we can do this opcode: - if (EaCanRead (sea,size)==0) return 1; - if (EaCanWrite(tea )==0) return 1; - - use=OpBase(op,size); - if (tea<0x38) use&=~0x0e00; // Use same handler for register ?0-7 - - if (tea==0x1f || tea==0x27) use|=0x0e00; // Specific handler for (a7)+ and -(a7) - - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,sea,tea); Cycles=4; - - if (movea==0) - { - EaCalcRead(-1,0,sea,size,0x003f); - ot(" adds r1,r0,#0 ;@ Defines NZ, clears CV\n"); - ot(" mrs r10,cpsr ;@ r10=NZCV flags\n"); - ot("\n"); - } - else - { - EaCalcRead(-1,1,sea,size,0x003f); - size=2; // movea always expands to 32-bits - } - - eawrite_check_addrerr=1; -#if SPLIT_MOVEL_PD - if ((tea&0x38)==0x20 && size==2) { // -(An) - EaCalc (8,0x0e00,tea,size,0,0); - ot(" mov r11,r1\n"); - ot(" add r0,r8,#2\n"); - EaWrite(0, 1,tea,1,0x0e00,0,0); - EaWrite(8, 11,tea,1,0x0e00,1); - } - else -#endif - { - EaCalc (0,0x0e00,tea,size,0,0); - EaWrite(0, 1,tea,size,0x0e00,0,0); - } - -#if CYCLONE_FOR_GENESIS && !MEMHANDLERS_CHANGE_CYCLES - // this is a bit hacky (device handlers might modify cycles) - if (tea==0x39||((0x10<=tea&&tea<0x30)&&size>=1)) - ot(" ldr r5,[r7,#0x5c] ;@ Load Cycles\n"); -#endif - - if((tea&0x38)==0x20) Cycles-=2; // less cycles when dest is -(An) - - OpEnd(sea,tea); - return 0; -} - -// --------------------- Opcodes 0x41c0+ --------------------- -// Emit an Lea opcode, 0100nnn1 11aaaaaa -int OpLea(int op) -{ - int use=0; - int sea=0,tea=0; - - sea= op&0x003f; - tea=(op&0x0e00)>>9; tea|=8; - - if (EaCanRead(sea,-1)==0) return 1; // See if we can do this opcode - - use=OpBase(op,0); - use&=~0x0e00; // Also use 1 handler for target ?0-7 - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,sea,tea); - - eawrite_check_addrerr=1; - EaCalc (1,0x003f,sea,0); // Lea - EaCalc (0,0x0e00,tea,2); - EaWrite(0, 1,tea,2,0x0e00); - - Cycles=Ea_add_ns(g_lea_cycle_table,sea); - - OpEnd(sea,tea); - - return 0; -} - -// --------------------- Opcodes 0x40c0+ --------------------- -// Move SR opcode, 01000tt0 11aaaaaa move SR -int OpMoveSr(int op) -{ - int type=0,ea=0; - int use=0,size=1; - - type=(op>>9)&3; // from SR, from CCR, to CCR, to SR - ea=op&0x3f; - - if(EaAn(ea)) return 1; // can't use An regs - - switch(type) - { - case 0: - if (EaCanWrite(ea)==0) return 1; // See if we can do this opcode: - break; - - case 1: - return 1; // no such op in 68000 - - case 2: case 3: - if (EaCanRead(ea,size)==0) return 1; // See if we can do this opcode: - break; - } - - use=OpBase(op,size); - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - // 68000 model allows reading whole SR in user mode (but newer models don't) - OpStart(op,ea,0,0,type==3); - Cycles=12; - if (type==0) Cycles=(ea>=8)?8:6; - - if (type==0 || type==1) - { - eawrite_check_addrerr=1; - OpFlagsToReg(type==0); - EaCalc (0,0x003f,ea,size,0,0); - EaWrite(0, 1,ea,size,0x003f,0,0); - } - - if (type==2 || type==3) - { - EaCalcReadNoSE(-1,0,ea,size,0x003f); - OpRegToFlags(type==3,1); - if (type==3) { - SuperChange(op,1); - opend_check_interrupt = 1; - opend_check_trace = 1; - OpEnd(ea); - return 0; - } - } - - OpEnd(ea); - - return 0; -} - - -// Ori/Andi/Eori $nnnn,sr 0000t0t0 01111100 -int OpArithSr(int op) -{ - int type=0,ea=0; - int use=0,size=0; - int sr_mask=EMULATE_TRACE?0xa7:0x27; - - type=(op>>9)&5; if (type==4) return 1; - size=(op>>6)&1; // ccr or sr? - ea=0x3c; - - use=OpBase(op,size); - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,ea,0,0,size!=0); Cycles=16; - - EaCalcRead(-1,0,ea,size,0x003f); - - ot(" eor r1,r0,r0,ror #1 ;@ Bit 0=C^V\n"); - ot(" tst r1,#1 ;@ 1 if C!=V\n"); - ot(" eorne r0,r0,#3 ;@ ___XNZCV\n"); - ot(" ldr r2,[r7,#0x4c] ;@ Load old X bit\n"); - - // note: old srh is already in r11 (done by OpStart) - if (type==0) { - ot(" orr r10,r10,r0,lsl #28\n"); - ot(" orr r2,r2,r0,lsl #25 ;@ X bit\n"); - if (size!=0) { - ot(" orr r1,r11,r0,lsr #8\n"); - ot(" and r1,r1,#0x%02x ;@ mask-out unused bits\n",sr_mask); - } - } - if (type==1) { - ot(" and r10,r10,r0,lsl #28\n"); - ot(" and r2,r2,r0,lsl #25 ;@ X bit\n"); - if (size!=0) - ot(" and r1,r11,r0,lsr #8\n"); - } - if (type==5) { - ot(" eor r10,r10,r0,lsl #28\n"); - ot(" eor r2,r2,r0,lsl #25 ;@ X bit\n"); - if (size!=0) { - ot(" eor r1,r11,r0,lsr #8\n"); - ot(" and r1,r1,#0x%02x ;@ mask-out unused bits\n",sr_mask); - } - } - - ot(" str r2,[r7,#0x4c] ;@ Save X bit\n"); - if (size!=0) - ot(" strb r1,[r7,#0x44]\n"); - ot("\n"); - - // we can't enter supervisor mode, nor unmask irqs just by using OR - if (size!=0 && type!=0) { - SuperChange(op,1); - ot("\n"); - opend_check_interrupt = 1; - } - // also can't set trace bit with AND - if (size!=0 && type!=1) - opend_check_trace = 1; - - OpEnd(ea); - - return 0; -} - -// --------------------- Opcodes 0x4850+ --------------------- -// Emit an Pea opcode, 01001000 01aaaaaa -int OpPea(int op) -{ - int use=0; - int ea=0; - - ea=op&0x003f; if (ea<0x10) return 1; // Swap opcode - if (EaCanRead(ea,-1)==0) return 1; // See if we can do this opcode: - - use=OpBase(op,0); - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,ea); - - ot(" ldr r11,[r7,#0x3c]\n"); - EaCalc (1,0x003f, ea,0); - ot("\n"); - ot(" sub r0,r11,#4 ;@ Predecrement A7\n"); - ot(" str r0,[r7,#0x3c] ;@ Save A7\n"); - ot("\n"); - MemHandler(1,2); // Write 32-bit - ot("\n"); - - Cycles=6+Ea_add_ns(g_pea_cycle_table,ea); - - OpEnd(ea); - - return 0; -} - -// --------------------- Opcodes 0x4880+ --------------------- -// Emit a Movem opcode, 01001d00 1xeeeeee regmask -int OpMovem(int op) -{ - int size=0,ea=0,cea=0,dir=0; - int use=0,decr=0,change=0; - - size=((op>>6)&1)+1; // word, long - ea=op&0x003f; - dir=(op>>10)&1; // Direction (1==ea2reg) - - if (dir) { - if (ea<0x10 || ea>0x3b || (ea&0x38)==0x20) return 1; // Invalid EA - } else { - if (ea<0x10 || ea>0x39 || (ea&0x38)==0x18) return 1; - } - - if ((ea&0x38)==0x18 || (ea&0x38)==0x20) change=1; - if ((ea&0x38)==0x20) decr=1; // -(An), bitfield is decr - - cea=ea; if (change) cea=0x10; - - use=OpBase(op,size); - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,ea,0,1); - - ot(" ldrh r11,[r4],#2 ;@ r11=register mask\n"); - ot("\n"); - ot(";@ Get the address into r6:\n"); - EaCalc(6,0x003f,cea,size); - -#if !MEMHANDLERS_NEED_PREV_PC - // must save PC, need a spare register - ot(" str r4,[r7,#0x40] ;@ Save PC\n"); -#endif - - ot(";@ r4=Register Index*4:\n"); - if (decr) ot(" mov r4,#0x40 ;@ order reversed for -(An)\n"); - else ot(" mov r4,#-4\n"); - - ot("\n"); - ot(" tst r11,r11\n"); // sanity check - ot(" beq NoRegs%.4x\n",op); - -#if EMULATE_ADDRESS_ERRORS_IO - ot("\n"); - ot(" tst r6,#1 ;@ address error?\n"); - ot(" movne r0,r6\n"); - ot(" bne ExceptionAddressError_%c_data\n",dir?'r':'w'); -#endif - - ot("\n"); - ot("Movemloop%.4x%s\n",op, ms?"":":"); - ot(" add r4,r4,#%d ;@ r4=Next Register\n",decr?-4:4); - ot(" movs r11,r11,lsr #1\n"); - ot(" bcc Movemloop%.4x\n",op); - ot("\n"); - - if (decr) ot(" sub r6,r6,#%d ;@ Pre-decrement address\n",1<>3)&1; // Direction - use=op&~0x0007; // Use same opcode for all An - - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op,0,0,0,1); Cycles=4; - - if (dir) - { - eawrite_check_addrerr=1; - ot(" ldr r1,[r7,#0x48] ;@ Get from USP\n\n"); - EaCalc (0,0x000f,8,2,1); - EaWrite(0, 1,8,2,0x000f,1); - } - else - { - EaCalc (0,0x000f,8,2,1); - EaRead (0, 0,8,2,0x000f,1); - ot(" str r0,[r7,#0x48] ;@ Put in USP\n\n"); - } - - OpEnd(); - - return 0; -} - -// --------------------- Opcodes 0x7000+ --------------------- -// Emit a Move Quick opcode, 0111nnn0 dddddddd moveq #dd,Dn -int OpMoveq(int op) -{ - int use=0; - - use=op&0xf100; // Use same opcode for all values - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op); Cycles=4; - - ot(" movs r0,r8,asl #24\n"); - ot(" and r1,r8,#0x0e00\n"); - ot(" mov r0,r0,asr #24 ;@ Sign extended Quick value\n"); - ot(" mrs r10,cpsr ;@ r10=NZ flags\n"); - ot(" str r0,[r7,r1,lsr #7] ;@ Store into Dn\n"); - ot("\n"); - - OpEnd(); - - return 0; -} - -// --------------------- Opcodes 0xc140+ --------------------- -// Emit a Exchange opcode: -// 1100ttt1 01000sss exg ds,dt -// 1100ttt1 01001sss exg as,at -// 1100ttt1 10001sss exg as,dt -int OpExg(int op) -{ - int use=0,type=0; - - type=op&0xf8; - - if (type!=0x40 && type!=0x48 && type!=0x88) return 1; // Not an exg opcode - - use=op&0xf1f8; // Use same opcode for all values - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler - - OpStart(op); Cycles=6; - - ot(" and r2,r8,#0x0e00 ;@ Find T register\n"); - ot(" and r3,r8,#0x000f ;@ Find S register\n"); - if (type==0x48) ot(" orr r2,r2,#0x1000 ;@ T is an address register\n"); - ot("\n"); - ot(" ldr r0,[r7,r2,lsr #7] ;@ Get T\n"); - ot(" ldr r1,[r7,r3,lsl #2] ;@ Get S\n"); - ot("\n"); - ot(" str r0,[r7,r3,lsl #2] ;@ T->S\n"); - ot(" str r1,[r7,r2,lsr #7] ;@ S->T\n"); - ot("\n"); - - OpEnd(); - - return 0; -} - -// ------------------------- movep ------------------------------- -// 0000ddd1 0z001sss -// 0000sss1 1z001ddd (to mem) -int OpMovep(int op) -{ - int ea=0,rea=0; - int size=1,use=0,dir,aadd=0; - - use=op&0xf1f8; - if (op!=use) { OpUse(op,use); return 0; } // Use existing handler (for all dests, srcs) - - // Get EA - ea = (op&0x0007)|0x28; - rea= (op&0x0e00)>>9; - dir = (op>>7)&1; - - // Find size extension - if(op&0x0040) size=2; - - OpStart(op,ea); - - if(dir) // reg to mem - { - EaCalcReadNoSE(-1,11,rea,size,0x0e00); - - EaCalc(8,0x000f,ea,size); - if(size==2) { // if operand is long - ot(" mov r1,r11,lsr #24 ;@ first byte\n"); - EaWrite(8,1,ea,0,0x000f); // store first byte - ot(" add r0,r8,#%i\n",(aadd+=2)); - ot(" mov r1,r11,lsr #16 ;@ second byte\n"); - EaWrite(0,1,ea,0,0x000f); // store second byte - ot(" add r0,r8,#%i\n",(aadd+=2)); - } else { - ot(" mov r0,r8\n"); - } - ot(" mov r1,r11,lsr #8 ;@ first or third byte\n"); - EaWrite(0,1,ea,0,0x000f); - ot(" add r0,r8,#%i\n",(aadd+=2)); - ot(" and r1,r11,#0xff\n"); - EaWrite(0,1,ea,0,0x000f); - } - else // mem to reg - { - EaCalc(6,0x000f,ea,size,1); - EaRead(6,11,ea,0,0x000f,1); // read first byte - ot(" add r0,r6,#2\n"); - EaRead(0,1,ea,0,0x000f,1); // read second byte - if(size==2) { // if operand is long - ot(" orr r11,r11,r1,lsr #8 ;@ second byte\n"); - ot(" add r0,r6,#4\n"); - EaRead(0,1,ea,0,0x000f,1); - ot(" orr r11,r11,r1,lsr #16 ;@ third byte\n"); - ot(" add r0,r6,#6\n"); - EaRead(0,1,ea,0,0x000f,1); - ot(" orr r1,r11,r1,lsr #24 ;@ fourth byte\n"); - } else { - ot(" orr r1,r11,r1,lsr #8 ;@ second byte\n"); - } - // store the result - EaCalc(0,0x0e00,rea,size,1); - EaWrite(0,1,rea,size,0x0e00,1); - ot(" ldr r6,[r7,#0x54]\n"); - } - - Cycles=(size==2)?24:16; - OpEnd(ea); - - return 0; -} - -// Emit a Stop/Reset opcodes, 01001110 011100t0 imm -int OpStopReset(int op) -{ - int type=(op>>1)&1; // stop/reset - - OpStart(op,0,0,0,1); - - if(type) { - // copy immediate to SR, stop the CPU and eat all remaining cycles. - ot(" ldrh r0,[r4],#2 ;@ Fetch the immediate\n"); - OpRegToFlags(1); - SuperChange(op,0); - - ot("\n"); - - ot(" ldr r0,[r7,#0x58]\n"); - ot(" mov r5,#0 ;@ eat cycles\n"); - ot(" orr r0,r0,#1 ;@ stopped\n"); - ot(" str r0,[r7,#0x58]\n"); - ot("\n"); - - Cycles = 4; - ot("\n"); - } - else - { - Cycles = 132; -#if USE_RESET_CALLBACK - ot(" str r4,[r7,#0x40] ;@ Save PC\n"); - ot(" mov r1,r10,lsr #28\n"); - ot(" strb r1,[r7,#0x46] ;@ Save Flags (NZCV)\n"); - ot(" str r5,[r7,#0x5c] ;@ Save Cycles\n"); - ot(" ldr r11,[r7,#0x90] ;@ ResetCallback\n"); - ot(" tst r11,r11\n"); - ot(" movne lr,pc\n"); - ot(" bxne r11 ;@ call ResetCallback if it is defined\n"); - ot(" ldrb r10,[r7,#0x46] ;@ r10 = Load Flags (NZCV)\n"); - ot(" ldr r5,[r7,#0x5c] ;@ Load Cycles\n"); - ot(" ldr r4,[r7,#0x40] ;@ Load PC\n"); - ot(" mov r10,r10,lsl #28\n"); - ot("\n"); -#endif - } - - OpEnd(); - - return 0; -} - diff --git a/cpu/Cyclone/app.h b/cpu/Cyclone/app.h deleted file mode 100644 index 5e468c7..0000000 --- a/cpu/Cyclone/app.h +++ /dev/null @@ -1,111 +0,0 @@ - -#include -#include -#include -#include - -#ifndef CONFIG_FILE -#define CONFIG_FILE "config.h" -#endif -#include CONFIG_FILE - -// Disa.c -#include "Disa/Disa.h" - -// Ea.cpp -extern int earead_check_addrerr; -extern int eawrite_check_addrerr; -extern int g_jmp_cycle_table[]; -extern int g_jsr_cycle_table[]; -extern int g_lea_cycle_table[]; -extern int g_pea_cycle_table[]; -extern int g_movem_cycle_table[]; -int Ea_add_ns(int *tab, int ea); // add nonstandard EA cycles -int EaCalc(int a,int mask,int ea,int size,int top=0,int sign_extend=1); // 6 -int EaRead(int a,int v,int ea,int size,int mask,int top=0,int sign_extend=1); // 7 -int EaCalcRead(int r_ea,int r,int ea,int size,int mask,int sign_extend=1); // 6 -int EaCalcReadNoSE(int r_ea,int r,int ea,int size,int mask); -int EaCanRead(int ea,int size); -int EaWrite(int a,int v,int ea,int size,int mask,int top=0,int sign_extend_ea=1); -int EaCanWrite(int ea); -int EaAn(int ea); - -// Main.cpp -extern int *CyJump; // Jump table -extern int ms; // If non-zero, output in Microsoft ARMASM format -extern const char * const Narm[4]; // Normal ARM Extensions for operand sizes 0,1,2 -extern const char * const Sarm[4]; // Sign-extend ARM Extensions for operand sizes 0,1,2 -extern int Cycles; // Current cycles for opcode -extern int pc_dirty; // something changed PC during processing -extern int arm_op_count; // for stats -void ot(const char *format, ...); -void ltorg(); -int MemHandler(int type,int size,int addrreg=0,int need_addrerr_check=1); -void FlushPC(void); - -// OpAny.cpp -extern int g_op; -extern int opend_op_changes_cycles, opend_check_interrupt, opend_check_trace; -int OpGetFlags(int subtract,int xbit,int sprecialz=0); -void OpUse(int op,int use); -void OpStart(int op,int sea=0,int tea=0,int op_changes_cycles=0,int supervisor_check=0); -void OpEnd(int sea=0,int tea=0); -int OpBase(int op,int size,int sepa=0); -void OpAny(int op); - -//---------------------- -// OpArith.cpp -int OpArith(int op); -int OpLea(int op); -int OpAddq(int op); -int OpArithReg(int op); -int OpMul(int op); -int OpAbcd(int op); -int OpNbcd(int op); -int OpAritha(int op); -int OpAddx(int op); -int OpCmpEor(int op); -int OpCmpm(int op); -int OpChk(int op); -int GetXBit(int subtract); - -// OpBranch.cpp -void OpPush32(); -void OpPushSr(int high); -int OpTrap(int op); -int OpLink(int op); -int OpUnlk(int op); -int Op4E70(int op); -int OpJsr(int op); -int OpBranch(int op); -int OpDbra(int op); - -// OpLogic.cpp -int OpBtstReg(int op); -int OpBtstImm(int op); -int OpNeg(int op); -int OpSwap(int op); -int OpTst(int op); -int OpExt(int op); -int OpSet(int op); -int OpAsr(int op); -int OpAsrEa(int op); -int OpTas(int op, int gen_special=0); - -// OpMove.cpp -int OpMove(int op); -int OpLea(int op); -void OpFlagsToReg(int high); -void OpRegToFlags(int high,int srh_reg=0); -int OpMoveSr(int op); -int OpArithSr(int op); -int OpPea(int op); -int OpMovem(int op); -int OpMoveq(int op); -int OpMoveUsp(int op); -int OpExg(int op); -int OpMovep(int op); -int OpStopReset(int op); -void SuperEnd(void); -void SuperChange(int op,int srh_reg=-1); - diff --git a/cpu/Cyclone/config.h b/cpu/Cyclone/config.h deleted file mode 100644 index d73b5b5..0000000 --- a/cpu/Cyclone/config.h +++ /dev/null @@ -1,182 +0,0 @@ - - -/** - * Cyclone 68000 configuration file -**/ - - -/* - * If this option is enabled, Microsoft ARMASM compatible output is generated - * (output file - Cyclone.asm). Otherwise GNU as syntax is used (Cyclone.s). - */ -#define USE_MS_SYNTAX 0 - -/* - * Enable this option if you are going to use Cyclone to emulate Genesis / - * Mega Drive system. As VDP chip in these systems had control of the bus, - * several instructions were acting differently, for example TAS did'n have - * the write-back phase. That will be emulated, if this option is enabled. - */ -#define CYCLONE_FOR_GENESIS 0 - -/* - * This option compresses Cyclone's jumptable. Because of this the executable - * will be smaller and load slightly faster and less relocations will be needed. - * This also fixes the crash problem with 0xfffe and 0xffff opcodes. - * Warning: if you enable this, you MUST call CycloneInit() before calling - * CycloneRun(), or else it will crash. - */ -#define COMPRESS_JUMPTABLE 1 - -/* - * Address mask for memory hadlers. The bits set will be masked out of address - * parameter, which is passed to r/w memory handlers. - * Using 0xff000000 means that only 24 least significant bits should be used. - * Set to 0 if you want to mask unused address bits in the memory handlers yourself. - */ -#define MEMHANDLERS_ADDR_MASK 0 - -/* - * Cyclone keeps the 4 least significant bits of SR, PC+membase and it's cycle - * counter in ARM registers instead of the context for performance reasons. If you for - * any reason need to access them in your memory handlers, enable the options below, - * otherwise disable them to improve performance. - * - * MEMHANDLERS_NEED_PC updates .pc context field with PC value effective at the time - * when memhandler was called (opcode address + 2-10 bytes). - * MEMHANDLERS_NEED_PREV_PC updates .prev_pc context field to currently executed - * opcode address + 2. - * Note that .pc and .prev_pc values are always real pointers to memory, so you must - * subtract .membase to get M68k PC value. - * - * Warning: updating PC in memhandlers is dangerous, as Cyclone may internally - * increment the PC before fetching the next instruction and continue executing - * at wrong location. It's better to wait until Cyclone CycloneRun() finishes. - * - * Warning: if you enable MEMHANDLERS_CHANGE_CYCLES, you must also enable - * MEMHANDLERS_NEED_CYCLES, or else Cyclone will keep reloading the same cycle - * count and this will screw timing (if not cause a deadlock). - */ -#define MEMHANDLERS_NEED_PC 0 -#define MEMHANDLERS_NEED_PREV_PC 0 -#define MEMHANDLERS_NEED_FLAGS 0 -#define MEMHANDLERS_NEED_CYCLES 0 -#define MEMHANDLERS_CHANGE_PC 0 -#define MEMHANDLERS_CHANGE_FLAGS 0 -#define MEMHANDLERS_CHANGE_CYCLES 0 - -/* - * If the following macro is defined, Cyclone no longer calls read*, write*, - * fetch* and checkpc from it's context, it calls these functions directly - * instead, prefixed with prefix selected below. For example, if - * MEMHANDLERS_DIRECT_PREFIX is set to cyclone_, it will call cyclone_read8 - * on byte reads. - * This is to avoid indirect jumps, which are slower. It also saves one ARM - * instruction. - */ -/* MEMHANDLERS_DIRECT_PREFIX "cyclone_" */ - -/* - * If enabled, Cyclone will call .IrqCallback routine from it's context whenever it - * acknowledges an IRQ. IRQ level (.irq) is not cleared automatically, do this in your - * handler if needed. - * This function must either return vector number to use for interrupt exception, - * CYCLONE_INT_ACK_AUTOVECTOR to use autovector (this is the most common case), or - * CYCLONE_INT_ACK_SPURIOUS (least common case). - * If disabled, it simply uses appropriate autovector, clears the IRQ level and - * continues execution. - */ -#define USE_INT_ACK_CALLBACK 0 - -/* - * Enable this if you need old PC, flags or cycles; - * or you change cycles in your IrqCallback function. - */ -#define INT_ACK_NEEDS_STUFF 0 -#define INT_ACK_CHANGES_CYCLES 0 - -/* - * If enabled, .ResetCallback is called from the context, whenever RESET opcode is - * encountered. All context members are valid and can be changed. - * If disabled, RESET opcode acts as an NOP. - */ -#define USE_RESET_CALLBACK 0 - -/* - * If enabled, UnrecognizedCallback is called if an invalid opcode is - * encountered. All context members are valid and can be changed. The handler - * should return zero if you want Cyclone to gererate "Illegal Instruction" - * exception after this, or nonzero if not. In the later case you should change - * the PC by yourself, or else Cyclone will keep executing that opcode all over - * again. - * If disabled, "Illegal Instruction" exception is generated and execution is - * continued. - */ -#define USE_UNRECOGNIZED_CALLBACK 0 - -/* - * This option will also call UnrecognizedCallback for a-line and f-line - * (0xa*** and 0xf***) opcodes the same way as described above, only appropriate - * exceptions will be generated. - */ -#define USE_AFLINE_CALLBACK 0 - -/* - * This makes Cyclone to call checkpc from it's context whenever it changes the PC - * by a large value. It takes and should return the PC value in PC+membase form. - * The flags and cycle counter are not valid in this function. - */ -#define USE_CHECKPC_CALLBACK 1 - -/* - * This determines if checkpc() should be called after jumps when 8 and 16 bit - * displacement values were used. - */ -#define USE_CHECKPC_OFFSETBITS_16 1 -#define USE_CHECKPC_OFFSETBITS_8 0 - -/* - * Call checkpc() after DBcc jumps (which use 16bit displacement). Cyclone prior to - * 0.0087 never did that. - */ -#define USE_CHECKPC_DBRA 0 - -/* - * When this option is enabled Cyclone will do two word writes instead of one - * long write when handling MOVE.L or MOVEM.L with pre-decrementing destination, - * as described in Bart Trzynadlowski's doc (http://www.trzy.org/files/68knotes.txt). - * Enable this if you are emulating a 16 bit system. - */ -#define SPLIT_MOVEL_PD 1 - -/* - * Enable emulation of trace mode. Shouldn't cause any performance decrease, so it - * should be safe to keep this ON. - */ -#define EMULATE_TRACE 1 - -/* - * If enabled, address error exception will be generated if 68k code jumps to an - * odd address. Causes very small performance hit (2 ARM instructions for every - * emulated jump/return/exception in normal case). - * Note: checkpc() must not clear least significant bit of rebased address - * for this to work, as checks are performed after calling checkpc(). - */ -#define EMULATE_ADDRESS_ERRORS_JUMP 1 - -/* - * If enabled, address error exception will be generated if 68k code tries to - * access a word or longword at an odd address. The performance cost is also 2 ARM - * instructions per access (for address error checks). - */ -#define EMULATE_ADDRESS_ERRORS_IO 0 - -/* - * If an address error happens during another address error processing, - * the processor halts until it is reset (catastrophic system failure, as the manual - * states). This option enables halt emulation. - * Note that this might be not desired if it is known that emulated system should - * never reach this state. - */ -#define EMULATE_HALT 0 - diff --git a/cpu/Cyclone/config_mamegp2x.h b/cpu/Cyclone/config_mamegp2x.h deleted file mode 100644 index 253d271..0000000 --- a/cpu/Cyclone/config_mamegp2x.h +++ /dev/null @@ -1,44 +0,0 @@ - - -/** - * Cyclone 68000 configuration file - * - * Used for mamegp2x Cyclone build. - * See config.h in Cyclone directory for option descriptions. -**/ - - -#define USE_MS_SYNTAX 0 -#define CYCLONE_FOR_GENESIS 0 -#define COMPRESS_JUMPTABLE 1 -#define MEMHANDLERS_ADDR_MASK 0xff000000 - -#define MEMHANDLERS_NEED_PC 1 -#define MEMHANDLERS_NEED_PREV_PC 1 -#define MEMHANDLERS_NEED_FLAGS 0 -#define MEMHANDLERS_NEED_CYCLES 1 -#define MEMHANDLERS_CHANGE_PC 0 -#define MEMHANDLERS_CHANGE_FLAGS 0 -#define MEMHANDLERS_CHANGE_CYCLES 1 - -#define USE_INT_ACK_CALLBACK 1 - -#define INT_ACK_NEEDS_STUFF 0 -#define INT_ACK_CHANGES_CYCLES 0 - -#define USE_RESET_CALLBACK 0 -#define USE_UNRECOGNIZED_CALLBACK 0 -#define USE_AFLINE_CALLBACK 0 - -#define USE_CHECKPC_CALLBACK 1 -#define USE_CHECKPC_OFFSETBITS_16 1 -#define USE_CHECKPC_OFFSETBITS_8 0 -#define USE_CHECKPC_DBRA 0 - -#define SPLIT_MOVEL_PD 1 - -#define EMULATE_TRACE 1 -#define EMULATE_ADDRESS_ERRORS_JUMP 1 -#define EMULATE_ADDRESS_ERRORS_IO 0 -#define EMULATE_HALT 0 - diff --git a/cpu/Cyclone/config_uae4all.h b/cpu/Cyclone/config_uae4all.h deleted file mode 100644 index d10a2cb..0000000 --- a/cpu/Cyclone/config_uae4all.h +++ /dev/null @@ -1,44 +0,0 @@ - - -/** - * Cyclone 68000 configuration file - * - * Used for UAE4ALL Cyclone build. - * See config.h in Cyclone directory for option descriptions. -**/ - - -#define USE_MS_SYNTAX 0 -#define CYCLONE_FOR_GENESIS 0 -#define COMPRESS_JUMPTABLE 1 -#define MEMHANDLERS_ADDR_MASK 0 - -#define MEMHANDLERS_NEED_PC 1 -#define MEMHANDLERS_NEED_PREV_PC 0 -#define MEMHANDLERS_NEED_FLAGS 0 -#define MEMHANDLERS_NEED_CYCLES 1 -#define MEMHANDLERS_CHANGE_PC 0 -#define MEMHANDLERS_CHANGE_FLAGS 0 -#define MEMHANDLERS_CHANGE_CYCLES 1 - -#define USE_INT_ACK_CALLBACK 1 - -#define INT_ACK_NEEDS_STUFF 0 -#define INT_ACK_CHANGES_CYCLES 0 - -#define USE_RESET_CALLBACK 0 -#define USE_UNRECOGNIZED_CALLBACK 1 -#define USE_AFLINE_CALLBACK 1 - -#define USE_CHECKPC_CALLBACK 1 -#define USE_CHECKPC_OFFSETBITS_16 1 -#define USE_CHECKPC_OFFSETBITS_8 0 -#define USE_CHECKPC_DBRA 0 - -#define SPLIT_MOVEL_PD 1 - -#define EMULATE_TRACE 1 -#define EMULATE_ADDRESS_ERRORS_JUMP 1 -#define EMULATE_ADDRESS_ERRORS_IO 1 -#define EMULATE_HALT 0 - diff --git a/cpu/Cyclone/epoc/crash_cyclone.bin b/cpu/Cyclone/epoc/crash_cyclone.bin deleted file mode 100644 index 04c6bb2..0000000 Binary files a/cpu/Cyclone/epoc/crash_cyclone.bin and /dev/null differ diff --git a/cpu/Cyclone/epoc/patchtable_symb.c b/cpu/Cyclone/epoc/patchtable_symb.c deleted file mode 100644 index 6d6fd26..0000000 --- a/cpu/Cyclone/epoc/patchtable_symb.c +++ /dev/null @@ -1,150 +0,0 @@ -#include -#include -#include - - -typedef struct { - unsigned long _dontcare1[4]; - char signature[4]; // 'EPOC' - unsigned long iCpu; // 0x1000 = X86, 0x2000 = ARM, 0x4000 = M*Core - unsigned long iCheckSumCode; // sum of all 32 bit words in .text - unsigned long _dontcare3[5]; - unsigned long iCodeSize; // size of code, import address table, constant data and export dir |+30 - unsigned long _dontcare4[12]; - unsigned long iCodeOffset; // file offset to code section |+64 - unsigned long _dontcare5[2]; - unsigned long iCodeRelocOffset; // relocations for code and const |+70 - unsigned long iDataRelocOffset; // relocations for data - unsigned long iPriority; // priority of this process (EPriorityHigh=450) -} E32ImageHeader; - - -typedef struct { - unsigned long iSize; // size of this relocation section - unsigned long iNumberOfRelocs; // number of relocations in this section -} E32RelocSection; - - -typedef struct { - unsigned long base; - unsigned long size; -} reloc_page_header; - - -// E32Image relocation section consists of a number of pages -// every page has 8 byte header and a number or 16bit relocation entries -// entry format: -// 0x3000 | <12bit_reloc_offset> -// -// if we have page_header.base == 0x1000 and a reloc entry 0x3110, -// it means that 32bit value at offset 0x1110 of .text section -// is relocatable - -int main(int argc, char *argv[]) -{ - FILE *f = 0; - unsigned char pattern[8] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56 }; - unsigned char *buff, *p; - unsigned long patt_offset; // pattern offset in .text section - unsigned long size = 0, i, symbols, insert_pos, *handler; - unsigned short reloc_entry; - E32ImageHeader *header; - E32RelocSection *reloc_section; - reloc_page_header *reloc_page; - - if(argc != 3) { - printf("usage: %s \n\n", argv[0]); - printf("note: this was written to fix a problem caused by as v.2.9-psion-98r2 and shouldn't be used for anything else.\n", argv[0]); - return 1; - } - - f = fopen(argv[1], "rb+"); - if(!f) { - printf("%s: couldn't open %s\n", argv[0], argv[1]); - return 2; - } - - symbols = atoi(argv[2]); - - // read the file - fseek(f,0,SEEK_END); size=ftell(f); fseek(f,0,SEEK_SET); - buff = (unsigned char *) malloc(size); - fread(buff,1,size,f); - - header = (E32ImageHeader *) buff; - - if(strncmp(header->signature, "EPOC", 4) || header->iCpu != 0x2000) { - printf("%s: not a E32 executable image for ARM target.\n", argv[0]); - fclose(f); - free(buff); - return 2; - } - - // find the pattern - for(i = 0; i < size-8; i++) - if(memcmp(buff+i, pattern, 8) == 0) break; - if(i == size-8 || i < 4) { - printf("%s: failed to find the pattern.\n", argv[0]); - fclose(f); - free(buff); - return 3; - } - patt_offset = i - header->iCodeOffset; - - // find suitable reloc section - reloc_section = (E32RelocSection *) (buff + header->iCodeRelocOffset); - for(i = 0, p = buff+header->iCodeRelocOffset+8; i < reloc_section->iSize; ) { - reloc_page = (reloc_page_header *) p; - if(patt_offset - reloc_page->base >= 0 && patt_offset - reloc_page->base < 0x1000 - symbols*4) break; - i += reloc_page->size; - p += reloc_page->size; - } - - if(i >= reloc_section->iSize) { - printf("%s: suitable reloc section not found.\n", argv[0]); - fclose(f); - free(buff); - return 4; - } - - // now find the insert pos and update everything - insert_pos = p + reloc_page->size - buff; - reloc_page->size += symbols*2; - reloc_section->iSize += symbols*2; - reloc_section->iNumberOfRelocs += symbols; - header->iDataRelocOffset += symbols*2; // data reloc section is now also pushed a little - header->iPriority = 450; // let's boost our priority :) - - // replace the placeholders themselves - handler = (unsigned long *) (buff + patt_offset + header->iCodeOffset - 4); - for(i = 1; i <= symbols; i++) - *(handler+i) = *handler; - - // recalculate checksum - header->iCheckSumCode = 0; - for(i = 0, p = buff+header->iCodeOffset; i < header->iCodeSize; i+=4, p+=4) - header->iCheckSumCode += *(unsigned long *) p; - - // check for possible padding - if(!*(buff+insert_pos-1)) insert_pos -= 2; - - // write all this joy - fseek(f,0,SEEK_SET); - fwrite(buff, 1, insert_pos, f); - - // write new reloc entries - for(i = 0; i < symbols; i++) { - handler++; - reloc_entry = ((unsigned char *) handler - buff - reloc_page->base - header->iCodeOffset) | 0x3000; - fwrite(&reloc_entry, 1, 2, f); - } - - // write the remaining data - fwrite(buff+insert_pos, 1, size-insert_pos, f); - - // done at last! - fclose(f); - free(buff); - - return 0; -} diff --git a/cpu/Cyclone/epoc/patchtable_symb2.c b/cpu/Cyclone/epoc/patchtable_symb2.c deleted file mode 100644 index 28a1656..0000000 --- a/cpu/Cyclone/epoc/patchtable_symb2.c +++ /dev/null @@ -1,133 +0,0 @@ -#include -#include -#include - -#include - -#define symbols 2 - -int main(int argc, char *argv[]) -{ - FILE *f = 0; - unsigned char pattern[8] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56 }; - unsigned char *buff, *p; - unsigned long patt_offset; // pattern offset in .text section - unsigned long size = 0, i, insert_pos, *handler;//, symbols; - unsigned short reloc_entry; - IMAGE_BASE_RELOCATION *reloc_page; - IMAGE_DOS_HEADER *dos_header; - IMAGE_FILE_HEADER *file_header; - IMAGE_SECTION_HEADER *sect_header, *relocsect_header = 0, *codesect_header = 0; - - if(argc != 2) { - printf("usage: %s \n\n", argv[0]); - printf("note: this was written to fix a problem related to Cyclone and as v.2.9-psion-98r2 and shouldn't be used for anything else. See Readme.\n", argv[0]); - return 1; - } - - f = fopen(argv[1], "rb+"); - if(!f) { - printf("%s: couldn't open %s\n", argv[0], argv[1]); - return 2; - } - - //symbols = atoi(argv[2]); - - // read the file - fseek(f,0,SEEK_END); size=ftell(f); fseek(f,0,SEEK_SET); - buff = (unsigned char *) malloc(size); - fread(buff,1,size,f); - - dos_header = (IMAGE_DOS_HEADER *) buff; - file_header= (IMAGE_FILE_HEADER *) (buff+dos_header->e_lfanew+4); - sect_header= (IMAGE_SECTION_HEADER *) (buff+dos_header->e_lfanew+4+sizeof(IMAGE_FILE_HEADER)+sizeof(IMAGE_OPTIONAL_HEADER32)); - - if(size < 0x500 || dos_header->e_magic != IMAGE_DOS_SIGNATURE || - *(DWORD *)(buff+dos_header->e_lfanew) != IMAGE_NT_SIGNATURE || file_header->Machine != 0x0A00) { - printf("%s: not a PE executable image for ARM target.\n", argv[0]); - fclose(f); - free(buff); - return 2; - } - - // scan all sections for data and reloc sections - for(i = 0; i < file_header->NumberOfSections; i++, sect_header++) { - if(strncmp(sect_header->Name, ".text", 5) == 0) codesect_header = sect_header; - else if(strncmp(sect_header->Name, ".reloc", 6) == 0) relocsect_header = sect_header; - } - - if(!codesect_header || !relocsect_header) { - printf("%s: failed to find reloc and/or data section.\n", argv[0]); - fclose(f); - free(buff); - return 3; - } - - if(relocsect_header != sect_header-1) { - printf("%s: bug: reloc section is not last, this is unexpected and not supported.\n", argv[0]); - fclose(f); - free(buff); - return 4; - } - - // find the pattern - for(i = codesect_header->PointerToRawData; i < size-8; i+=2) - if(memcmp(buff+i, pattern, 8) == 0) break; - if(i == size-8 || i < 4) { - printf("%s: failed to find the pattern.\n", argv[0]); - fclose(f); - free(buff); - return 5; - } - - // calculate pattern offset in RVA (relative virtual address) - patt_offset = i - codesect_header->PointerToRawData + codesect_header->VirtualAddress; - - // replace the placeholders themselves - handler = (unsigned long *) (buff + i - 4); - for(i = 1; i <= symbols; i++) - *(handler+i) = *handler; - - // find suitable reloc section - for(i = 0, p = buff+relocsect_header->PointerToRawData; i < relocsect_header->SizeOfRawData; ) { - reloc_page = (IMAGE_BASE_RELOCATION *) p; - if(patt_offset - reloc_page->VirtualAddress >= 0 && patt_offset - reloc_page->VirtualAddress < 0x1000 - symbols*2) break; - i += reloc_page->SizeOfBlock; - p += reloc_page->SizeOfBlock; - } - - if(i >= relocsect_header->SizeOfRawData) { - printf("%s: suitable reloc section not found.\n", argv[0]); - fclose(f); - free(buff); - return 6; - } - - // now find the insert pos and update everything - insert_pos = p + reloc_page->SizeOfBlock - buff; - reloc_page->SizeOfBlock += symbols*2; - relocsect_header->SizeOfRawData += symbols*2; - - // check for possible padding - if(!*(buff+insert_pos-1)) insert_pos -= 2; - - // write all this joy - fseek(f,0,SEEK_SET); - fwrite(buff, 1, insert_pos, f); - - // write new reloc entries - for(i = 0; i < symbols; i++) { - handler++; - reloc_entry = (unsigned short)(((unsigned char *) handler - buff) - reloc_page->VirtualAddress - codesect_header->PointerToRawData + codesect_header->VirtualAddress) | 0x3000; // quite nasty - fwrite(&reloc_entry, 1, 2, f); - } - - // write the remaining data - fwrite(buff+insert_pos, 1, size-insert_pos, f); - - // done at last! - fclose(f); - free(buff); - - return 0; -} diff --git a/cpu/Cyclone/epoc/readme.txt b/cpu/Cyclone/epoc/readme.txt deleted file mode 100644 index 97410f6..0000000 --- a/cpu/Cyclone/epoc/readme.txt +++ /dev/null @@ -1,42 +0,0 @@ -*update* -Use the "compress jumtable" Cyclone config.h option to fix this issue -(no patcher will be needed then). - - -There is a problem with Cyclone on symbian platform: -GNU as generates COFF object files, which allow max of 0xFFFF (65535) relocation -entries. Cyclone uses a jumptable of 0x10000 (65536, 1 for every opcode-word) -antries. When the executable is loaded, all jumptable entries must be relocated -to point to right code location. Because of this limitation, Cyclone's jumptable is -incomplete (misses 2 entries), and if M68k opcodes 0xFFFE or 0xFFFF are ever -encoundered when emulating, your emulator will crash. - -I have written a little patcher to fix that. It writes those two missing entries and -marks them as relocatable. Placeholders must not be deleted just after the jumttable -in the Cyclone source code. - -This version works with intermediate PE executable, which is used both for APPs and EXEs, -and is produced by gcc toolkit just before running petran. So it's best to insert -this in your makefile, in the rule which builds your APP/EXE, just after last 'ld' -statement, for example: - -$(EPOCTRGUREL)\PICODRIVEN.APP : $(EPOCBLDUREL)\PICODRIVEN.in $(EPOCSTATLINKUREL)\EDLL.LIB $(LIBSUREL) - ... - ld -s -e _E32Dll -u _E32Dll --dll \ - "$(EPOCBLDUREL)\PICODRIVEN.exp" \ - -Map "$(EPOCTRGUREL)\PICODRIVEN.APP.map" -o "$(EPOCBLDUREL)\PICODRIVEN.APP" \ - "$(EPOCSTATLINKUREL)\EDLL.LIB" --whole-archive "$(EPOCBLDUREL)\PICODRIVEN.in" \ - --no-whole-archive $(LIBSUREL) $(USERLDFLAGS) - -$(ERASE) "$(EPOCBLDUREL)\PICODRIVEN.exp" - - patchtable_symb2 "$(EPOCBLDUREL)\PICODRIVEN.APP" - - petran "$(EPOCBLDUREL)\PICODRIVEN.APP" "$@" \ - -nocall -uid1 0x10000079 -uid2 0x100039ce -uid3 0x1000c193 - -$(ERASE) "$(EPOCBLDUREL)\PICODRIVEN.APP" - perl -S ecopyfile.pl "$@" "PICODRIVEN.APP" - - -This is also compatible with ECompXL. - -To test if this thing worked, you can load crash_cyclone.bin in your emulator. diff --git a/cpu/Cyclone/proj/Makefile b/cpu/Cyclone/proj/Makefile deleted file mode 100644 index 55e4486..0000000 --- a/cpu/Cyclone/proj/Makefile +++ /dev/null @@ -1,42 +0,0 @@ -CFLAGS = -Wall -ifdef CONFIG_FILE -CFLAGS += -DCONFIG_FILE=\"$(CONFIG_FILE)\" -endif - -all : cyclone.s - -cyclone.s : Cyclone.exe - ./Cyclone.exe - -Cyclone.exe : Main.o Ea.o OpAny.o OpArith.o OpBranch.o OpLogic.o Disa.o OpMove.o - $(CC) $^ -o $@ -lstdc++ - -Main.o : ../Main.cpp ../app.h - $(CC) $(CFLAGS) ../Main.cpp -c -o $@ - -Ea.o : ../Ea.cpp ../app.h - $(CC) $(CFLAGS) ../Ea.cpp -c -o $@ - -OpAny.o : ../OpAny.cpp ../app.h - $(CC) $(CFLAGS) ../OpAny.cpp -c -o $@ - -OpArith.o : ../OpArith.cpp ../app.h - $(CC) $(CFLAGS) ../OpArith.cpp -c -o $@ - -OpBranch.o : ../OpBranch.cpp ../app.h - $(CC) $(CFLAGS) ../OpBranch.cpp -c -o $@ - -OpLogic.o : ../OpLogic.cpp ../app.h - $(CC) $(CFLAGS) ../OpLogic.cpp -c -o $@ - -OpMove.o : ../OpMove.cpp ../app.h - $(CC) $(CFLAGS) ../OpMove.cpp -c -o $@ - -Disa.o : ../Disa/Disa.c ../Disa/Disa.h - $(CC) $(CFLAGS) ../Disa/Disa.c -c -o $@ - -../app.h : ../config.h - -clean : - $(RM) *.o Cyclone.exe Cyclone.s - diff --git a/cpu/Cyclone/proj/Makefile.win b/cpu/Cyclone/proj/Makefile.win deleted file mode 100644 index 758352b..0000000 --- a/cpu/Cyclone/proj/Makefile.win +++ /dev/null @@ -1,59 +0,0 @@ -# Makefile for MS Visual C - -CPP=cl.exe -CPP_PROJ=/nologo /W4 /O2 /D "_CRT_SECURE_NO_WARNINGS" /c - -LINK32=link.exe -LINK32_FLAGS=user32.lib /nologo /subsystem:console /machine:I386 /out:Cyclone.exe - - -ALL : cyclone.s - -cyclone.s : Cyclone.exe - Cyclone.exe - -Cyclone.exe : Main.obj Ea.obj OpAny.obj OpArith.obj OpBranch.obj OpLogic.obj Disa.obj OpMove.obj - $(LINK32) Main.obj Ea.obj OpAny.obj OpArith.obj OpBranch.obj OpLogic.obj Disa.obj OpMove.obj $(LINK32_FLAGS) - -Main.obj : ..\Main.cpp ..\app.h - $(CPP) $(CPP_PROJ) ..\Main.cpp - -Ea.obj : ..\Ea.cpp ..\app.h - $(CPP) $(CPP_PROJ) ..\Ea.cpp - -OpAny.obj : ..\OpAny.cpp ..\app.h - $(CPP) $(CPP_PROJ) ..\OpAny.cpp - -OpArith.obj : ..\OpArith.cpp ..\app.h - $(CPP) $(CPP_PROJ) ..\OpArith.cpp - -OpBranch.obj : ..\OpBranch.cpp ..\app.h - $(CPP) $(CPP_PROJ) ..\OpBranch.cpp - -OpLogic.obj : ..\OpLogic.cpp ..\app.h - $(CPP) $(CPP_PROJ) ..\OpLogic.cpp - -OpMove.obj : ..\OpMove.cpp ..\app.h - $(CPP) $(CPP_PROJ) ..\OpMove.cpp - -Disa.obj : ..\disa\Disa.c ..\disa\Disa.h - $(CPP) $(CPP_PROJ) ..\disa\Disa.c - -..\app.h : ..\config.h - - -CLEAN : - -@erase "Disa.obj" - -@erase "Ea.obj" - -@erase "Main.obj" - -@erase "OpAny.obj" - -@erase "OpArith.obj" - -@erase "OpBranch.obj" - -@erase "OpLogic.obj" - -@erase "OpMove.obj" - -@erase "vc60.idb" - -@erase "vc60.pch" - -@erase "Cyclone.exe" - -@erase "Cyclone.asm" - -@erase "Cyclone.s" - diff --git a/cpu/Cyclone/proj/cyclone.dsp b/cpu/Cyclone/proj/cyclone.dsp deleted file mode 100644 index 1e66725..0000000 --- a/cpu/Cyclone/proj/cyclone.dsp +++ /dev/null @@ -1,146 +0,0 @@ -# Microsoft Developer Studio Project File - Name="cyclone" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=cyclone - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "cyclone.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "cyclone.mak" CFG="cyclone - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "cyclone - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "cyclone - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "cyclone - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W4 /O2 /D "_CRT_SECURE_NO_WARNINGS" /c -# ADD CPP /nologo /W4 /O2 /D "_CRT_SECURE_NO_WARNINGS" /c -# ADD BASE RSC /l 0x427 /d "NDEBUG" -# ADD RSC /l 0x427 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"cyclone.exe" - -!ELSEIF "$(CFG)" == "cyclone - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W4 /O2 /D "_CRT_SECURE_NO_WARNINGS" /c -# ADD CPP /nologo /W4 /O2 /D "_CRT_SECURE_NO_WARNINGS" /c -# ADD BASE RSC /l 0x427 /d "_DEBUG" -# ADD RSC /l 0x427 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"cyclone.exe" /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "cyclone - Win32 Release" -# Name "cyclone - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\disa\Disa.c -# End Source File -# Begin Source File - -SOURCE=..\Ea.cpp -# End Source File -# Begin Source File - -SOURCE=..\Main.cpp -# End Source File -# Begin Source File - -SOURCE=..\OpAny.cpp -# End Source File -# Begin Source File - -SOURCE=..\OpArith.cpp -# End Source File -# Begin Source File - -SOURCE=..\OpBranch.cpp -# End Source File -# Begin Source File - -SOURCE=..\OpLogic.cpp -# End Source File -# Begin Source File - -SOURCE=..\OpMove.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=..\app.h -# End Source File -# Begin Source File - -SOURCE=..\config.h -# End Source File -# Begin Source File - -SOURCE=..\Cyclone.h -# End Source File -# Begin Source File - -SOURCE=..\disa\Disa.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/cpu/Cyclone/tests/crash_cyclone.bin b/cpu/Cyclone/tests/crash_cyclone.bin deleted file mode 100755 index dfa0276..0000000 Binary files a/cpu/Cyclone/tests/crash_cyclone.bin and /dev/null differ diff --git a/cpu/Cyclone/tests/test_abcd.bin b/cpu/Cyclone/tests/test_abcd.bin deleted file mode 100755 index fe25040..0000000 Binary files a/cpu/Cyclone/tests/test_abcd.bin and /dev/null differ diff --git a/cpu/Cyclone/tests/test_cmpm.bin b/cpu/Cyclone/tests/test_cmpm.bin deleted file mode 100755 index e761857..0000000 Binary files a/cpu/Cyclone/tests/test_cmpm.bin and /dev/null differ diff --git a/cpu/Cyclone/tests/test_div.bin b/cpu/Cyclone/tests/test_div.bin deleted file mode 100755 index 6e9cb77..0000000 Binary files a/cpu/Cyclone/tests/test_div.bin and /dev/null differ diff --git a/cpu/Cyclone/tests/test_misc.bin b/cpu/Cyclone/tests/test_misc.bin deleted file mode 100755 index b21b05d..0000000 Binary files a/cpu/Cyclone/tests/test_misc.bin and /dev/null differ diff --git a/cpu/Cyclone/tests/test_misc2_gen.c b/cpu/Cyclone/tests/test_misc2_gen.c deleted file mode 100644 index 108156b..0000000 --- a/cpu/Cyclone/tests/test_misc2_gen.c +++ /dev/null @@ -1,119 +0,0 @@ -#include -#include -#include - - -static FILE *f; - -#define bswap16(x) (x=(unsigned short)((x<<8)|(x>>8))) -#define bswap32(x) (x=((x<<24)|((x<<8)&0xff0000)|((x>>8)&0x00ff00)|((unsigned)x>>24))) - -static void write_op(unsigned short op, unsigned short word0, unsigned short word1, unsigned short word2) -{ - bswap16(op); - bswap16(word0); - bswap16(word1); - bswap16(word2); - - fwrite(&op, 1, sizeof(op), f); - fwrite(&word0, 1, sizeof(word0), f); - fwrite(&word1, 1, sizeof(word1), f); - fwrite(&word2, 1, sizeof(word2), f); -} - -static void write32(unsigned int a) -{ - bswap32(a); - fwrite(&a, 1, sizeof(a), f); -} - -static int op_check(unsigned short op) -{ - if ((op&0xf000) == 0x6000) return 0; // Bxx - if ((op&0xf0f8) == 0x50c8) return 0; // DBxx - if ((op&0xff80) == 0x4e80) return 0; // Jsr - if ((op&0xf000) == 0xa000) return 0; // a-line - if ((op&0xf000) == 0xf000) return 0; // f-line - if ((op&0xfff8)==0x4e70&&op!=0x4e71&&op!=0x4e76) return 0; // reset, rte, rts - - if ((op&0x3f) >= 0x28) op = (op&~0x3f) | (rand() % 0x28); - return 1; -} - -static unsigned short safe_rand(void) -{ - unsigned short op; - - /* avoid branch opcodes */ - do - { - op = rand(); - } - while (!op_check(op)); - - return op; -} - -int main() -{ - int i, op; - - srand(time(0)); - - f = fopen("test_misc2.bin", "wb"); - if (!f) return 1; - - write32(0x00ff8000); // stack - write32(0x300); // IP - - for (i=0x100/4-2; i; i--) - { - write32(0x200+i*4); // exception vectors - } - - for (i=0x100/4; i; i--) - { - write32(0); // pad - } - - for (i=0x100/4; i; i--) - { - write32(0x4e734e73); // fill with rte instructions - } - - for (op = 0; op < 0x10000; op++) - { - if ((op&0xf000) == 0x6000) // Bxx - { - if ((op&0x00ff) == 0) - write_op(op, 6, 0, 0); - } - else if ((op&0xf0f8)==0x50c8) // DBxx - { - write_op(op, 6, 0, 0); - } - else if ((op&0xff80)==0x4e80) // Jsr - { - int addr = 0x300 + op*8 + 8; - if ((op&0x3f) == 0x39) - write_op(op, addr >> 16, addr & 0xffff, 0); - } - else if ((op&0xf000)==0xa000 || (op&0xf000)==0xf000) // a-line, f-line - { - if (op != 0xa000 && op != 0xf000) continue; - } - else if ((op&0xfff8)==0x4e70&&op!=0x4e71&&op!=0x4e76); // rte, rts, stop, reset - else - { - write_op(op, safe_rand(), safe_rand(), safe_rand()); - } - } - - // jump to the beginning - write_op(0x4ef8, 0x300, 0x4ef8, 0x300); - write_op(0x4ef8, 0x300, 0x4ef8, 0x300); - - fclose(f); - return 0; -} - diff --git a/cpu/Cyclone/tests/test_negx.bin b/cpu/Cyclone/tests/test_negx.bin deleted file mode 100755 index 1f6e6cf..0000000 Binary files a/cpu/Cyclone/tests/test_negx.bin and /dev/null differ diff --git a/cpu/Cyclone/tests/test_rol.bin b/cpu/Cyclone/tests/test_rol.bin deleted file mode 100755 index 0cb0a41..0000000 Binary files a/cpu/Cyclone/tests/test_rol.bin and /dev/null differ diff --git a/cpu/Cyclone/tests/test_shift.bin b/cpu/Cyclone/tests/test_shift.bin deleted file mode 100755 index c364f21..0000000 Binary files a/cpu/Cyclone/tests/test_shift.bin and /dev/null differ diff --git a/cpu/Cyclone/tests/test_trace.bin b/cpu/Cyclone/tests/test_trace.bin deleted file mode 100755 index e9ca5fa..0000000 Binary files a/cpu/Cyclone/tests/test_trace.bin and /dev/null differ diff --git a/cpu/Cyclone/tests/test_trace.s b/cpu/Cyclone/tests/test_trace.s deleted file mode 100644 index b6d8421..0000000 --- a/cpu/Cyclone/tests/test_trace.s +++ /dev/null @@ -1,140 +0,0 @@ -| Processor: 68K -| Target Assembler: 680x0 Assembler by GNU project - -| ___________________________________________________________________________ - -| Segment type: Pure code -| segment "ROM" -dword_0: .long 0 | DATA XREF: ROM:00007244r - | sub_764E+3Eo ... - | initial interrupt stack pointer -dword_4: .long _start | DATA XREF: ROM:00007248r - | ROM:000142C2w - | reset initial PC -dword_8: .long 0x4DE | DATA XREF: sub_20050+B54w - .long 0x490 - .long 0x4AA | illegal instruction - .long 0x4C4 - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long _trace | trace - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x548 | Level 1 Interrupt Autovector - .long 0x548 | 2 = ext interrupt - .long 0x548 - .long 0x592 | 4 = horizontal interrupt? - .long 0x548 - .long 0x594 | 6 = verticai interrupt? - .long 0x552 -dword_80: .long 0x45C | DATA XREF: ROM:00152F29o - | trap vector table? trap 0? - .long 0x1738 - .long 0x171C - .long 0x1754 - .long 0x1700 - .long 0x556 - .long 0x57A - .long 0x548 - .long 0x548 - .long 0x7CE | 9 - .long 0x548 - .long 0x548 - .long 0x548 - .long 0x548 - .long 0x548 - .long 0x548 - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE - .long 0x4DE -aSegaGenesis: .ascii "SEGA GENESIS " | DATA XREF: ROM:00045C6Ao -aCSega1994_jul: .ascii "(C)SEGA 1994.JUL" -aDumpedByTsd: .ascii "Dumped By TSD " -aShiningForce2: .ascii "SHINING FORCE 2 " -aGmMk131500: .ascii "GM MK-1315 -00" - .word 0x8921 | checksum -aJ: .ascii "J " | IO_Support - .long 0 | Rom_Start_Adress -dword_1A4: .long 0x1FFFFF | DATA XREF: sub_28008+F66o - | Rom_End_Adress - .long 0xFF0000 | Ram_Start_Adress - .long 0xFFFFFF | Ram_End_Adress -aRaa: .ascii "RA° "<0>" "<0><1><0>" ?"<0xFF> | Modem_Infos - .ascii " " - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | -aU: .ascii "U " | Countries - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | - .byte 0x20 | -_trace: - nop - nop - rte - -.globl _start -_start: - move.l #0xFFFFFFFF, %d0 - move.l #0xFFFFFFFF, %d1 - move.w #0xa711, %sr - move.l #0x1, %d2 - move.l #0x8000, %d3 - negx.l %d0 - negx.l %d1 - move.w #0x270f, %sr - negx.b %d2 - negx.w %d3 -_loop: - bra _loop - - nop - nop - nop - nop diff --git a/cpu/Cyclone/tools/idle.h b/cpu/Cyclone/tools/idle.h deleted file mode 100644 index 254cc57..0000000 --- a/cpu/Cyclone/tools/idle.h +++ /dev/null @@ -1,3 +0,0 @@ - -void CycloneInitIdle(void); -void CycloneFinishIdle(void); diff --git a/cpu/Cyclone/tools/idle.s b/cpu/Cyclone/tools/idle.s deleted file mode 100644 index a8b7cca..0000000 --- a/cpu/Cyclone/tools/idle.s +++ /dev/null @@ -1,176 +0,0 @@ -@ vim:filetype=armasm - -@ ranges/opcodes (idle, normal): -@ 71xx, 73xx - bne.s (8bit offset) -@ 75xx, 77xx - beq.s (8bit offset) -@ 7dxx, 7fxx - bra.s (8bit offset) - -.data -.align 2 - -have_patches: - .word 0 - -.equ patch_desc_table_size, 10 - -patch_desc_table: - .word (0x71fa<<16) | 0x66fa, idle_detector_bcc8, idle_bne, Op6601 @ bne.s - .word (0x71f8<<16) | 0x66f8, idle_detector_bcc8, idle_bne, Op6601 @ bne.s - .word (0x71f6<<16) | 0x66f6, idle_detector_bcc8, idle_bne, Op6601 @ bne.s - .word (0x71f2<<16) | 0x66f2, idle_detector_bcc8, idle_bne, Op6601 @ bne.s - .word (0x75fa<<16) | 0x67fa, idle_detector_bcc8, idle_beq, Op6701 @ beq.s - .word (0x75f8<<16) | 0x67f8, idle_detector_bcc8, idle_beq, Op6701 @ beq.s - .word (0x75f6<<16) | 0x67f6, idle_detector_bcc8, idle_beq, Op6701 @ beq.s - .word (0x75f2<<16) | 0x67f2, idle_detector_bcc8, idle_beq, Op6701 @ beq.s - .word (0x7dfe<<16) | 0x60fe, idle_detector_bcc8, idle_bra, Op6001 @ bra.s - .word (0x7dfc<<16) | 0x60fc, idle_detector_bcc8, idle_bra, Op6001 @ bra.s - - -.text -.align 2 - - -.global CycloneInitIdle - -CycloneInitIdle: - ldr r3, =CycloneJumpTab - ldr r2, =patch_desc_table - mov r12,#patch_desc_table_size - -cii_loop: - ldrh r0, [r2] - ldr r1, [r2, #4] @ detector - str r1, [r3, r0, lsl #2] - ldrh r0, [r2, #2] - ldr r1, [r2, #8] @ idle - add r0, r3, r0, lsl #2 - str r1, [r0] - ldr r1, [r2, #12] @ normal - str r1, [r0, #0x800] - add r2, r2, #16 - subs r12,r12,#1 - bgt cii_loop - - ldr r0, =have_patches - mov r1, #1 - str r1, [r0] - bx lr - - -.global CycloneFinishIdle - -CycloneFinishIdle: - ldr r0, =have_patches - ldr r0, [r0] - tst r0, r0 - bxeq lr - - ldr r3, =CycloneJumpTab - ldr r2, =patch_desc_table - mov r12,#patch_desc_table_size - -cfi_loop: - ldrh r0, [r2] - ldr r1, [r2, #12] @ normal - str r1, [r3, r0, lsl #2] - ldrh r0, [r2, #2] - ldr r1, =Op____ - add r0, r3, r0, lsl #2 - str r1, [r0] - str r1, [r0, #0x800] - add r2, r2, #16 - subs r12,r12,#1 - bgt cfi_loop - - ldr r0, =have_patches - mov r1, #0 - str r1, [r0] - bx lr - - - -.macro inc_counter cond -@ ldr\cond r0, [r7, #0x60] -@ mov r11,lr -@ sub r0, r4, r0 -@ sub r0, r0, #2 -@ bl\cond SekRegisterIdleHit -@ mov lr, r11 -.endm - -idle_bra: - mov r5, #2 - inc_counter - b Op6001 - -idle_bne: - msr cpsr_flg, r10 - movne r5, #2 @ 2 is intentional due to strange timing issues - inc_counter ne - b Op6601 - -idle_beq: - msr cpsr_flg, r10 ;@ ARM flags = 68000 flags - moveq r5, #2 - inc_counter eq - b Op6701 - - -@ @@@ @ - -idle_detector_bcc8: - ldr r0, =(Pico+0x22208) @ Pico.m - ldr r1, =idledet_start_frame - ldr r0, [r0, #0x1c] @ ..frame_count - ldr r1, [r1] - cmp r0, r1 - blt exit_detector @ not yet - - mov r0, r8, asl #24 @ Shift 8-bit signed offset up... - add r0, r4, r0, asr #24 @ jump dest - bic r0, r0, #1 - - mov r1, #0 - sub r1, r1, r8, lsl #24 - mov r1, r1, lsr #24 - sub r1, r1, #2 - bic r1, r1, #1 - - bl SekIsIdleCode - tst r0, r0 - and r2, r8, #0x00ff - orr r2, r2, #0x7100 - orreq r2, r2, #0x0200 - mov r0, r8, lsr #8 - cmp r0, #0x66 - orrgt r2, r2, #0x0400 @ 67xx (beq) - orrlt r2, r2, #0x0c00 @ 60xx (bra) - - @ r2 = patch_opcode - sub r0, r4, #2 - ldrh r1, [r0] - mov r11,r2 - mov r3, r7 - bl SekRegisterIdlePatch - cmp r0, #1 @ 0 - ok to patch, 1 - no patch, 2 - remove detector - strlth r11,[r4, #-2] - ble exit_detector - - @ remove detector from Cyclone - mov r0, r8, lsr #8 - cmp r0, #0x66 - ldrlt r1, =Op6001 - ldreq r1, =Op6601 - ldrgt r1, =Op6701 - - ldr r3, =CycloneJumpTab - str r1, [r3, r8, lsl #2] - bx r1 - -exit_detector: - mov r0, r8, lsr #8 - cmp r0, #0x66 - blt Op6001 - beq Op6601 - b Op6701 - diff --git a/cpu/cyclone b/cpu/cyclone new file mode 160000 index 0000000..a6905b4 --- /dev/null +++ b/cpu/cyclone @@ -0,0 +1 @@ +Subproject commit a6905b4de17f4d772c7742065f2863b77ddf0b31 diff --git a/cpu/Cyclone/config_pico.h b/cpu/cyclone_config.h similarity index 100% rename from cpu/Cyclone/config_pico.h rename to cpu/cyclone_config.h