8a68e16e5c569e0c993f72240325cdcae1789721
[picodrive.git] / cpu / Cyclone / Cyclone.txt
1 \r
2       _____            __                                     \r
3      / ___/__ __ ____ / /___   ___  ___   ___________________ \r
4     / /__ / // // __// // _ \ / _ \/ -_) ___________________  \r
5     \___/ \_, / \__//_/ \___//_//_/\__/ ___________________   \r
6          /___/                                                \r
7          ___________________  ____ ___   ___   ___   ___      \r
8         ___________________  / __// _ \ / _ \ / _ \ / _ \     \r
9        ___________________  / _ \/ _  // // // // // // /     \r
10                             \___/\___/ \___/ \___/ \___/      \r
11                                                               \r
12 ___________________________________________________________________________\r
13 \r
14   Cyclone 68000 (c) Copyright 2004 Dave.   Free for non-commercial use\r
15 \r
16   Homepage: http://www.finalburn.com/\r
17   Dave's e-mail: emudave(atsymbol)googlemail.com\r
18   Replace (atsymbol) with @\r
19 \r
20   Additional coding and bugfixes done by notaz, 2005-2007\r
21   Homepage: http://mif.vu.lt/~grig2790/Cyclone/ , http://notaz.gp2x.de\r
22   e-mail: notasas(atsymbol)gmail.com\r
23 ___________________________________________________________________________\r
24 \r
25 \r
26 What is it?\r
27 -----------\r
28 \r
29 Cyclone 68000 is an emulator for the 68000 microprocessor, written in ARM 32-bit assembly.\r
30 It is aimed at chips such as ARM7 and ARM9 cores, StrongARM and XScale, to interpret 68000\r
31 code as fast as possible.\r
32 \r
33 Flags are mapped onto ARM flags whenever possible, which speeds up the processing of opcode.\r
34 \r
35 \r
36 What's New\r
37 ----------\r
38 v0.0087 notaz\r
39   - Reduced amount of code in opcode handlers by ~23% by doing the following:\r
40     - Removed duplicate opcode handlers\r
41     - Optimized code to use less ARM instructions\r
42     - Merged some duplicate handler endings\r
43   + Cyclone now does better job avoiding pipeline interlocks.\r
44   + Replaced incorrect handler of DBT with proper one.\r
45   + Changed "MOVEA (An)+ An" behaviour.\r
46   + Fixed flag behaviour of ROXR, ASL, LSR and NBCD in certain situations.\r
47     Hopefully got them right now.\r
48   + Cyclone no longer sets most significant bits while pushing PC to stack.\r
49     Amiga Kickstart depends on this.\r
50   + Additional functionality added for MAME and other ports (see config.h).\r
51 \r
52 v0.0086 notaz\r
53   + Cyclone now can be customized to better suit your project, see config.h .\r
54   + Added an option to compress the jumptable at compile-time. Must call CycloneInit()\r
55     at runtime to decompress it if enabled (see config.h).\r
56   + Added missing CHK opcode handler (used by SeaQuest DSV).\r
57   + Added missing TAS opcode handler (Gargoyles,Bubba N Stix,...). As in real genesis,\r
58     memory write-back phase is ignored (but can be enabled in config.h if needed).\r
59   + Added missing NBCD and TRAPV opcode handlers.\r
60   + Added missing addressing mode for CMP/EOR.\r
61   + Added some minor optimizations.\r
62   - Removed 216 handlers for 2927 opcodes which were generated for invalid addressing modes.\r
63   + Fixed flags for ASL, NEG, NEGX, DIVU, ADDX, SUBX, ROXR.\r
64   + Bugs fixed in MOVEP, LINK, ADDQ, DIVS handlers.\r
65   * Undocumented flags for CHK, ABCD, SBCD and NBCD are now emulated the same way as in Musashi.\r
66   + Added Uninitialized Interrupt emulation.\r
67   + Altered timing for about half of opcodes to match Musashi's.\r
68 \r
69 v0.0082 Reesy\r
70   + Change cyclone to clear cycles before returning when halted\r
71   + Added Irq call back function.  This allows emulators to be notified\r
72     when cyclone has taken an interrupt allowing them to set internal flags\r
73     which can help fix timing problems.\r
74 \r
75 v0.0081 notaz\r
76   + .asm version was broken and did not compile with armasm. Fixed.\r
77   + Finished implementing Stop opcode. Now it really stops the processor.\r
78 \r
79 v0.0080 notaz\r
80   + Added real cmpm opcode, it was using eor handler before this.\r
81     Fixes Dune and Sensible Soccer.\r
82 \r
83 v0.0078 notaz\r
84   note: these bugs were actually found Reesy, I reimplemented these by\r
85         using his changelog as a guide.\r
86   + Fixed a problem with divu which was using long divisor instead of word.\r
87     Fixes gear switching in Top Gear 2.\r
88   + Fixed btst opcode, The bit to test should shifted a max of 31 or 7\r
89     depending on if a register or memory location is being tested.\r
90   + Fixed abcd,sbcd. They did bad decimal correction on invalid BCD numbers\r
91     Score counters in Streets of Rage level end work now.\r
92   + Changed flag handling of abcd,sbcd,addx,subx,asl,lsl,...\r
93     Some ops did not have flag handling at all.\r
94     Some ops must not change Z flag when result is zero, but they did.\r
95     Shift ops must not change X if shift count is zero, but they did.\r
96     There are probably still some flag problems left.\r
97   + Patially implemented Stop and Reset opcodes - Fixes Thunderforce IV\r
98 \r
99 v0.0075 notaz\r
100   + Added missing displacement addressing mode for movem (Fantastic Dizzy)\r
101   + Added OSP <-> A7 swapping code in opcodes, which change privilege mode\r
102   + Implemented privilege violation, line emulator and divide by zero exceptions\r
103   + Added negx opcode (Shining Force works!)\r
104   + Added overflow detection for divs/divu\r
105 \r
106 v0.0072 notaz\r
107   note: I could only get v0.0069 cyclone, so I had to implement these myself using Dave's\r
108         changelog as a guide.\r
109   + Fixed a problem with divs - remainder should be negative when divident is negative\r
110   + Added movep opcode (Sonic 3 works)\r
111   + Fixed a problem with DBcc incorrectly decrementing if the condition is true (Shadow of the Beast)\r
112 \r
113 v0.0069\r
114   + Added SBCD and the flags for ABCD/SBCD. Score and time now works in games such as\r
115     Rolling Thunder 2, Ghouls 'N Ghosts\r
116   + Fixed a problem with addx and subx with 8-bit and 16-bit values.\r
117     Ghouls 'N' Ghosts now works!\r
118 \r
119 v0.0068\r
120   + Added ABCD opcode (Streets of Rage works now!)\r
121 \r
122 v0.0067\r
123   + Added dbCC (After Burner)\r
124   + Added asr EA (Sonic 1 Boss/Labyrinth Zone)\r
125   + Added andi/ori/eori ccr (Altered Beast)\r
126   + Added trap (After Burner)\r
127   + Added special case for move.b (a7)+ and -(a7), stepping by 2\r
128     After Burner is playable! Eternal Champions shows more\r
129   + Fixed lsr.b/w zero flag (Ghostbusters)\r
130     Rolling Thunder 2 now works!\r
131   + Fixed N flag for .b and .w arithmetic. Golden Axe works!\r
132 \r
133 v0.0066\r
134   + Fixed a stupid typo for exg (orr r10,r10, not orr r10,r8), which caused alignment\r
135     crashes on Strider\r
136 \r
137 v0.0065\r
138   + Fixed a problem with immediate values - they weren't being shifted up correctly for some\r
139     opcodes. Spiderman works, After Burner shows a bit of graphics.\r
140   + Fixed a problem with EA:"110nnn" extension word. 32-bit offsets were being decoded as 8-bit\r
141     offsets by mistake. Castlevania Bloodlines seems fine now.\r
142   + Added exg opcode\r
143   + Fixed asr opcode (Sonic jumping left is fixed)\r
144   + Fixed a problem with the carry bit in rol.b (Marble Madness)\r
145 \r
146 v0.0064\r
147   + Added rtr\r
148   + Fixed addq/subq.l (all An opcodes are 32-bit) (Road Rash)\r
149   + Fixed various little timings\r
150 \r
151 v0.0063\r
152   + Added link/unlk opcodes\r
153   + Fixed various little timings\r
154   + Fixed a problem with dbCC opcode being emitted at set opcodes\r
155   + Improved long register access, the EA fetch now does ldr r0,[r7,r0,lsl #2] whenever\r
156      possible, saving 1 or 2 cycles on many opcodes, which should give a nice speed up.\r
157   + May have fixed N flag on ext opcode?\r
158   + Added dasm for link opcode.\r
159 \r
160 v0.0062\r
161   * I was a bit too keen with the Arithmetic opcodes! Some of them should have been abcd,\r
162     exg and addx. Removed the incorrect opcodes, pending re-adding them as abcd, exg and addx.\r
163   + Changed unknown opcodes to act as nops.\r
164     Not very technical, but fun - a few more games show more graphics ;)\r
165 \r
166 v0.0060\r
167   + Fixed divu (EA intro)\r
168   + Added sf (set false) opcode - SOR2\r
169   * Todo: pea/link/unlk opcodes\r
170 \r
171 v0.0059: Added remainder to divide opcodes.\r
172 \r
173 \r
174 The new stuff\r
175 -------------\r
176 \r
177 Before using Cyclone, be sure to customize config.h to better suit your project. All options\r
178 are documented inside that file.\r
179 \r
180 IrqCallback has been changed a bit, unlike in previous version, it should not return anything.\r
181 If you need to change IRQ level, you can safely do that in your handler.\r
182 \r
183 Cyclone has changed quite a bit from the time when Dave stopped updating it, but the rest of\r
184 documentation still applies, so read it if you haven't done that yet. If you have, check the\r
185 "Accessing ..." parts.\r
186 \r
187 \r
188 ARM Register Usage\r
189 ------------------\r
190 \r
191 See source code for up to date of register usage, however a summary is here:\r
192 \r
193   r0-3: Temporary registers\r
194   r4  : Current PC + Memory Base (i.e. pointer to next opcode)\r
195   r5  : Cycles remaining\r
196   r6  : Pointer to Opcode Jump table\r
197   r7  : Pointer to Cpu Context\r
198   r8  : Current Opcode\r
199   r9  : Flags (NZCV) in highest four bits\r
200  (r10 : Temporary source value or Memory Base)\r
201  (r11 : Temporary register)\r
202 \r
203 \r
204 How to Compile\r
205 --------------\r
206 \r
207 Like Starscream and A68K, Cyclone uses a 'Core Creator' program which calculates and outputs\r
208 all possible 68000 Opcodes and a jump table into files called Cyclone.s and .asm\r
209 It then assembles these files into Cyclone.o and .obj\r
210 \r
211 Cyclone.o is the GCC assembled version and Cyclone.obj is the Microsoft assembled version.\r
212 \r
213 First unzip "Cyclone.zip" into a "Cyclone" directory.\r
214 If you are compiling for Windows CE, find ARMASM.EXE (the Microsoft ARM assembler) and\r
215 put it in the directory as well or put it on your path.\r
216 \r
217 Open up Cyclone.dsw in Visual Studio 6.0, compile and run the project.\r
218 Cyclone.obj and Cyclone.o will be created.\r
219 \r
220 \r
221 Compiling without Visual C++\r
222 ----------------------------\r
223 If you aren't using Visual C++, it still shouldn't be too hard to compile, just get a C compiler,\r
224 compile all the CPPs and C file, link them into an EXE, and run the exe.\r
225 \r
226   e.g. gcc Main.cpp OpAny.cpp OpArith.cpp OpBranch.cpp OpLogic.cpp OpMove.cpp Disa.c\r
227   Main.exe\r
228 \r
229 \r
230 Adding to your project\r
231 ----------------------\r
232 \r
233 To add Cyclone to you project, add Cyclone.o or obj, and include Cyclone.h\r
234 There is one structure: 'struct Cyclone', and one function: CycloneRun\r
235 \r
236 Don't worry if this seem very minimal - its all you need to run as many 68000s as you want.\r
237 It works with both C and C++.\r
238 \r
239 Byteswapped Memory\r
240 ------------------\r
241 \r
242 If you have used Starscream, A68K or Turbo68K or similar emulators you'll be familiar with this!\r
243 \r
244 Any memory which the 68000 can access directly must be have every two bytes swapped around.\r
245 This is to speed up 16-bit memory accesses, because the 68000 has Big-Endian memory\r
246 and ARM has Little-Endian memory.\r
247 \r
248 Now you may think you only technically have to byteswap ROM, not RAM, because\r
249 16-bit RAM reads go through a memory handler and you could just return (mem[a]<<8) | mem[a+1].\r
250 \r
251 This would work, but remember some systems can execute code from RAM as well as ROM, and\r
252 that would fail.\r
253 So it's best to use byteswapped ROM and RAM if the 68000 can access it directly.\r
254 It's also faster for the memory handlers, because you can do this:\r
255   \r
256   return *(unsigned short *)(mem+a)\r
257 \r
258 \r
259 Declaring Memory handlers\r
260 -------------------------\r
261 \r
262 Before you can reset or execute 68000 opcodes you must first set up a set of memory handlers.\r
263 There are 7 functions you have to set up per CPU, like this:\r
264 \r
265   static unsigned int   MyCheckPc(unsigned int pc)\r
266   static unsigned char  MyRead8  (unsigned int a)\r
267   static unsigned short MyRead16 (unsigned int a)\r
268   static unsigned int   MyRead32 (unsigned int a)\r
269   static void MyWrite8 (unsigned int a,unsigned char  d)\r
270   static void MyWrite16(unsigned int a,unsigned short d)\r
271   static void MyWrite32(unsigned int a,unsigned int   d)\r
272 \r
273 You can think of these functions representing the 68000's memory bus.\r
274 The Read and Write functions are called whenever the 68000 reads or writes memory.\r
275 For example you might set MyRead8 like this:\r
276 \r
277   unsigned char MyRead8(unsigned int a)\r
278   {\r
279     a&=0xffffff; // Clip address to 24-bits\r
280 \r
281     if (a<RomLength) return RomData[a^1]; // ^1 because the memory is byteswapped\r
282     if (a>=0xe00000) return RamData[(a^1)&0xffff];\r
283     return 0xff; // Out of range memory access\r
284   }\r
285 \r
286 The other 5 read/write functions are similar. I'll describe the CheckPc function later on.\r
287 \r
288 Declaring a CPU Context\r
289 -----------------------\r
290 \r
291 To declare a CPU simple declare a struct Cyclone in your code. For example to declare\r
292 two 68000s:\r
293 \r
294   struct Cyclone MyCpu;\r
295   struct Cyclone MyCpu2;\r
296 \r
297 It's probably a good idea to initialise the memory to zero:\r
298 \r
299   memset(&MyCpu, 0,sizeof(MyCpu));\r
300   memset(&MyCpu2,0,sizeof(MyCpu2));\r
301 \r
302 Next point to your memory handlers:\r
303 \r
304   MyCpu.checkpc=MyCheckPc;\r
305   MyCpu.read8  =MyRead8;\r
306   MyCpu.read16 =MyRead16;\r
307   MyCpu.read32 =MyRead32;\r
308   MyCpu.write8 =MyWrite8;\r
309   MyCpu.write16=MyWrite16;\r
310   MyCpu.write32=MyWrite32;\r
311 \r
312 You also need to point the fetch handlers - for most systems out there you can just\r
313 point them at the read handlers:\r
314   MyCpu.fetch8  =MyRead8;\r
315   MyCpu.fetch16 =MyRead16;\r
316   MyCpu.fetch32 =MyRead32;\r
317 \r
318 ( Why a different set of function pointers for fetch?\r
319   Well there are some systems, the main one being CPS2, which return different data\r
320   depending on whether the 'fetch' line on the 68000 bus is high or low.\r
321   If this is the case, you can set up different functions for fetch reads.\r
322   Generally though you don't need to. )\r
323 \r
324 Now you are nearly ready to reset the 68000, except you need one more function: checkpc().\r
325 \r
326 The checkpc() function\r
327 ----------------------\r
328 \r
329 When Cyclone reads opcodes, it doesn't use a memory handler every time, this would be\r
330 far too slow, instead it uses a direct pointer to ARM memory.\r
331 For example if your Rom image was at 0x3000000 and the program counter was $206,\r
332 Cyclone's program counter would be 0x3000206.\r
333 \r
334 The difference between an ARM address and a 68000 address is also stored in a variable called\r
335 'membase'. In the above example it's 0x3000000. To retrieve the real PC, Cyclone just\r
336 subtracts 'membase'.\r
337 \r
338 When a long jump happens, Cyclone calls checkpc(). If the PC is in a different bank,\r
339 for example Ram instead of Rom, change 'membase', recalculate the new PC and return it:\r
340 \r
341 static int MyCheckPc(unsigned int pc)\r
342 {\r
343   pc-=MyCpu.membase; // Get the real program counter\r
344 \r
345   if (pc<RomLength) MyCpu.membase=(int)RomMem;          // Jump to Rom\r
346   if (pc>=0xff0000) MyCpu.membase=(int)RamMem-0xff0000; // Jump to Ram\r
347 \r
348   return MyCpu.membase+pc; // New program counter\r
349 }\r
350 \r
351 Notice that the membase is always ARM address minus 68000 address.\r
352 \r
353 The above example doesn't consider mirrored ram, but for an example of what to do see\r
354 PicoDrive (in Memory.cpp).\r
355 \r
356 \r
357 Almost there - Reset the 68000!\r
358 -------------------------------\r
359 \r
360 Next we need to Reset the 68000 to get the initial Program Counter and Stack Pointer. This\r
361 is obtained from addresses 000000 and 000004.\r
362 \r
363 Here is code which resets the 68000 (using your memory handlers):\r
364 \r
365   MyCpu.srh=0x27; // Set supervisor mode\r
366   MyCpu.a[7]=MyCpu.read32(0); // Get Stack Pointer\r
367   MyCpu.membase=0;\r
368   MyCpu.pc=MyCpu.checkpc(MyCpu.read32(4)); // Get Program Counter\r
369 \r
370 And that's ready to go.\r
371 \r
372 \r
373 Executing the 68000\r
374 -------------------\r
375 \r
376 To execute the 68000, set the 'cycles' variable to the number of cycles you wish to execute,\r
377 and then call CycloneRun with a pointer to the Cyclone structure.\r
378 \r
379 e.g.:\r
380   // Execute 1000 cycles on the 68000:\r
381   MyCpu.cycles=1000; CycloneRun(&MyCpu);\r
382 \r
383 For each opcode, the number of cycles it took is subtracted and the function returns when\r
384 it reaches 0.\r
385 \r
386 e.g.\r
387   // Execute one instruction on the 68000:\r
388   MyCpu.cycles=0; CycloneRun(&MyCpu);\r
389   printf("  The opcode took %d cycles\n", -MyCpu.cycles);\r
390 \r
391 You should try to execute as many cycles as you can for maximum speed.\r
392 The number actually executed may be slightly more than requested, i.e. cycles may come\r
393 out with a small negative value:\r
394 \r
395 e.g.\r
396   int todo=12000000/60; // 12Mhz, for one 60hz frame\r
397   MyCpu.cycles=todo; CycloneRun(&MyCpu);\r
398   printf("  Actually executed %d cycles\n", todo-MyCpu.cycles);\r
399 \r
400 To calculate the number of cycles executed, use this formula:\r
401   Number of cycles requested - Cycle counter at the end\r
402 \r
403 \r
404 Interrupts\r
405 ----------\r
406 \r
407 Causing an interrupt is very simple, simply set the irq variable in the Cyclone structure\r
408 to the IRQ number.\r
409 To lower the IRQ line, set it to zero.\r
410 \r
411 e.g:\r
412   MyCpu.irq=6; // Interrupt level 6\r
413   MyCpu.cycles=20000; CycloneRun(&MyCpu);\r
414 \r
415 Note that the interrupt is not actually processed until the next call to CycloneRun,\r
416 and the interrupt may not be taken until the 68000 interrupt mask is changed to allow it.\r
417 \r
418 ( The IRQ isn't checked on exiting from a memory handler: I don't think this will cause\r
419   me any trouble because I've never needed to trigger an interrupt from a memory handler,\r
420   but if someone needs to, let me know...)\r
421 \r
422 \r
423 Accessing Cycle Counter\r
424 -----------------------\r
425 \r
426 The cycle counter in the Cyclone structure is not, by default, updated before\r
427 calling a memory handler, only at the end of an execution.\r
428 \r
429 *update*\r
430 Now this is configurable in config.h, there is no 'debug' variable.\r
431 \r
432 \r
433 Accessing Program Counter and registers\r
434 ---------------------------------------\r
435 \r
436 You can read Cyclone's registers directly from the structure at any time (as far as I know).\r
437 \r
438 The Program Counter, should you need to read or write it, is stored with membase\r
439 added on. So use this formula to calculate the real 68000 program counter:\r
440 \r
441   pc = MyCpu.pc - MyCpu.membase;\r
442 \r
443 The program counter is stored in r4 during execution, and isn't written back to the\r
444 structure until the end of execution, which means you can't read normally real it from\r
445 a memory handler.\r
446 \r
447 *update*\r
448 Now this is configurable in config.h, there is no 'debug' variable. You can even enable\r
449 access to SR if you need. However changing PC in memhandlers is still not safe, you should\r
450 better clear cycles, wait untill CycloneRun() returns and then do whatever you need.\r
451 \r
452 \r
453 Emulating more than one CPU\r
454 ---------------------------\r
455 \r
456 Since everything is based on the structures, emulating more than one cpu at the same time\r
457 is just a matter of declaring more than one structures and timeslicing. You can emulate\r
458 as many 68000s as you want.\r
459 Just set up the memory handlers for each cpu and run each cpu for a certain number of cycles.\r
460 \r
461 e.g.\r
462   // Execute 1000 cycles on 68000 #1:\r
463   MyCpu.cycles=1000; CycloneRun(&MyCpu);\r
464 \r
465   // Execute 1000 cycles on 68000 #2:\r
466   MyCpu2.cycles=1000; CycloneRun(&MyCpu2);\r
467 \r
468 \r
469 Thanks to...\r
470 ------------\r
471 \r
472 * All the previous code-generating assembler cpu core guys!\r
473   Who are iirc... Neill Corlett, Neil Bradley, Mike Coates, Darren Olafson\r
474     and Bart Trzynadlowski\r
475 \r
476 * Charles Macdonald, for researching just about every console ever\r
477 * MameDev+FBA, for keeping on going and going and going\r
478 \r
479 \r
480 -------------\r
481 \r
482 Dave  - 17th April 2004\r
483 notaz - 17th July 2006\r
484 \r
485 Homepage: http://www.finalburn.com/\r
486 Dave's e-mail: dev(atsymbol)finalburn.com\r
487 Replace (atsymbol) with @\r