optimizations, bugfixes, uae works (but with timing glitches?)
[picodrive.git] / cpu / Cyclone / OpAny.cpp
CommitLineData
cc68a136 1\r
2#include "app.h"\r
3\r
4static unsigned char OpData[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};\r
5\r
6static unsigned short CPU_CALL OpRead16(unsigned int a)\r
7{\r
8 return (unsigned short)( (OpData[a&15]<<8) | OpData[(a+1)&15] );\r
9}\r
10\r
11// For opcode 'op' use handler 'use'\r
12void OpUse(int op,int use)\r
13{\r
14 char text[64]="";\r
15 CyJump[op]=use;\r
16\r
17 if (op!=use) return;\r
18\r
19 // Disassemble opcode\r
20 DisaPc=0;\r
21 DisaText=text;\r
22 DisaWord=OpRead16;\r
23\r
24 DisaGet();\r
25 ot(";@ ---------- [%.4x] %s uses Op%.4x ----------\n",op,text,use);\r
26}\r
27\r
ee5e024c 28void OpStart(int op, int sea, int tea, int op_changes_cycles, int supervisor_check)\r
cc68a136 29{\r
ee5e024c 30 int last_op_count=arm_op_count;\r
31\r
cc68a136 32 Cycles=0;\r
33 OpUse(op,op); // This opcode obviously uses this handler\r
34 ot("Op%.4x%s\n", op, ms?"":":");\r
ee5e024c 35\r
36 if (supervisor_check)\r
37 {\r
38 // checks for supervisor bit, if not set, jumps to SuperEnd()\r
39 // also sets r11 to SR high value, SuperChange() uses this\r
40 ot(" ldr r11,[r7,#0x44] ;@ Get SR high\n");\r
41 }\r
42 if ((sea >= 0x10 && sea != 0x3c) || (tea >= 0x10 && tea != 0x3c))\r
43 {\r
cfb3dfa0 44#if MEMHANDLERS_NEED_PREV_PC\r
b637c56a 45 ot(" str r4,[r7,#0x50] ;@ Save prev PC + 2\n");\r
a6785576 46#endif\r
47#if MEMHANDLERS_NEED_CYCLES\r
48 ot(" str r5,[r7,#0x5c] ;@ Save Cycles\n");\r
49#endif\r
a6785576 50 }\r
ee5e024c 51 if (supervisor_check)\r
52 {\r
53 ot(" tst r11,#0x20 ;@ Check we are in supervisor mode\n");\r
54 ot(" beq WrongPrivilegeMode ;@ No\n");\r
55 }\r
56 if ((sea >= 0x10 && sea != 0x3c) || (tea >= 0x10 && tea != 0x3c)) {\r
57#if MEMHANDLERS_CHANGE_CYCLES\r
58 if (op_changes_cycles)\r
59 ot(" mov r5,#0\n");\r
a6785576 60#endif\r
ee5e024c 61 }\r
62 if (last_op_count!=arm_op_count)\r
63 ot("\n");\r
cfb3dfa0 64 pc_dirty = 1;\r
cc68a136 65}\r
66\r
ee5e024c 67void OpEnd(int sea, int tea, int op_changes_cycles, int check_interrupt)\r
cc68a136 68{\r
ee5e024c 69 int did_fetch=0;\r
cfb3dfa0 70#if MEMHANDLERS_CHANGE_CYCLES\r
71 if ((sea >= 0x10 && sea != 0x3c) || (tea >= 0x10 && tea != 0x3c))\r
ee5e024c 72 {\r
73 if (op_changes_cycles)\r
74 {\r
75 ot(" ldr r0,[r7,#0x5c] ;@ Load Cycles\n");\r
76 ot(" ldrh r8,[r4],#2 ;@ Fetch next opcode\n");\r
77 ot(" add r5,r0,r5\n");\r
78 did_fetch=1;\r
79 }\r
80 else\r
81 {\r
82 ot(" ldr r5,[r7,#0x5c] ;@ Load Cycles\n");\r
83 }\r
84 }\r
cfb3dfa0 85#endif\r
ee5e024c 86 if (!did_fetch)\r
87 ot(" ldrh r8,[r4],#2 ;@ Fetch next opcode\n");\r
cc68a136 88 ot(" subs r5,r5,#%d ;@ Subtract cycles\n",Cycles);\r
ee5e024c 89 if (check_interrupt)\r
90 {\r
91 ot(" blt CycloneEnd\n");\r
92 ot(";@ CheckInterrupt:\n");\r
93 ot(" ldr r1,[r7,#0x44] ;@ Get SR high T_S__III and irq level\n");\r
94 ot(" movs r0,r1,lsr #24 ;@ Get IRQ level\n"); // same as ldrb r0,[r7,#0x47]\r
95 ot(" ldreq pc,[r6,r8,asl #2] ;@ Jump to next opcode handler\n");\r
96 ot(" cmp r0,#6 ;@ irq>6 ?\n");\r
97 ot(" andle r1,r1,#7 ;@ Get interrupt mask\n");\r
98 ot(" cmple r0,r1 ;@ irq<=6: Is irq<=mask ?\n");\r
99 ot(" ldrle pc,[r6,r8,asl #2] ;@ Jump to next opcode handler\n");\r
100 ot(" b CycloneDoInterruptGoBack\n");\r
101 }\r
102 else\r
103 {\r
104 ot(" ldrge pc,[r6,r8,asl #2] ;@ Jump to opcode handler\n");\r
105 ot(" b CycloneEnd\n");\r
106 }\r
cc68a136 107 ot("\n");\r
108}\r
109\r
85a36a57 110int OpBase(int op,int size,int sepa)\r
cc68a136 111{\r
112 int ea=op&0x3f; // Get Effective Address\r
113 if (ea<0x10) return sepa?(op&~0x7):(op&~0xf); // Use 1 handler for d0-d7 and a0-a7\r
85a36a57 114 if (size==0&&(ea==0x1f || ea==0x27)) return op; // Specific handler for (a7)+ and -(a7)\r
cc68a136 115 if (ea<0x38) return op&~7; // Use 1 handler for (a0)-(a7), etc...\r
116 return op;\r
117}\r
118\r
119// Get flags, trashes r2\r
120int OpGetFlags(int subtract,int xbit,int specialz)\r
121{\r
122 if (specialz) ot(" orr r2,r9,#0xb0000000 ;@ for old Z\n");\r
123\r
124 ot(" mrs r9,cpsr ;@ r9=flags\n");\r
125\r
126 if (specialz) ot(" andeq r9,r9,r2 ;@ fix Z\n");\r
127\r
128 if (subtract) ot(" eor r9,r9,#0x20000000 ;@ Invert carry\n");\r
129\r
130 if (xbit)\r
131 {\r
85a36a57 132 ot(" str r9,[r7,#0x4c] ;@ Save X bit\n");\r
cc68a136 133 }\r
134 return 0;\r
135}\r
136\r
137// -----------------------------------------------------------------\r
138\r
85a36a57 139int g_op;\r
140\r
cc68a136 141void OpAny(int op)\r
142{\r
143 memset(OpData,0x33,sizeof(OpData));\r
144 OpData[0]=(unsigned char)(op>>8);\r
145 OpData[1]=(unsigned char)op;\r
85a36a57 146 g_op=op;\r
147\r
148 if ((op&0xf100)==0x0000) OpArith(op); // +\r
149 if ((op&0xc000)==0x0000) OpMove(op); // +\r
150 if ((op&0xf5bf)==0x003c) OpArithSr(op); // + Ori/Andi/Eori $nnnn,sr\r
151 if ((op&0xf100)==0x0100) OpBtstReg(op); // +\r
152 if ((op&0xf138)==0x0108) OpMovep(op); // +\r
153 if ((op&0xff00)==0x0800) OpBtstImm(op); // +\r
154 if ((op&0xf900)==0x4000) OpNeg(op); // +\r
155 if ((op&0xf140)==0x4100) OpChk(op); // +\r
156 if ((op&0xf1c0)==0x41c0) OpLea(op); // +\r
157 if ((op&0xf9c0)==0x40c0) OpMoveSr(op); // +\r
158 if ((op&0xffc0)==0x4800) OpNbcd(op); // +\r
159 if ((op&0xfff8)==0x4840) OpSwap(op); // +\r
160 if ((op&0xffc0)==0x4840) OpPea(op); // +\r
161 if ((op&0xffb8)==0x4880) OpExt(op); // +\r
162 if ((op&0xfb80)==0x4880) OpMovem(op); // +\r
163 if ((op&0xff00)==0x4a00) OpTst(op); // +\r
164 if ((op&0xffc0)==0x4ac0) OpTas(op); // +\r
165 if ((op&0xfff0)==0x4e40) OpTrap(op); // +\r
166 if ((op&0xfff8)==0x4e50) OpLink(op); // +\r
167 if ((op&0xfff8)==0x4e58) OpUnlk(op); // +\r
168 if ((op&0xfff0)==0x4e60) OpMoveUsp(op); // +\r
169 if ((op&0xfff8)==0x4e70) Op4E70(op); // + Reset/Rts etc\r
170 if ((op&0xfffd)==0x4e70) OpStopReset(op);// +\r
171 if ((op&0xff80)==0x4e80) OpJsr(op); // +\r
172 if ((op&0xf000)==0x5000) OpAddq(op); // +\r
173 if ((op&0xf0c0)==0x50c0) OpSet(op); // +\r
174 if ((op&0xf0f8)==0x50c8) OpDbra(op); // +\r
175 if ((op&0xf000)==0x6000) OpBranch(op); // +\r
176 if ((op&0xf100)==0x7000) OpMoveq(op); // +\r
177 if ((op&0xa000)==0x8000) OpArithReg(op); // + Or/Sub/And/Add\r
178 if ((op&0xb1f0)==0x8100) OpAbcd(op); // +\r
179 if ((op&0xb0c0)==0x80c0) OpMul(op); // +\r
180 if ((op&0x90c0)==0x90c0) OpAritha(op); // +\r
181 if ((op&0xb130)==0x9100) OpAddx(op); // +\r
182 if ((op&0xf000)==0xb000) OpCmpEor(op); // +\r
183 if ((op&0xf138)==0xb108) OpCmpm(op); // +\r
184 if ((op&0xf130)==0xc100) OpExg(op); // +\r
185 if ((op&0xf000)==0xe000) OpAsr(op); // + Asr/l/Ror/l etc\r
186 if ((op&0xf8c0)==0xe0c0) OpAsrEa(op); // +\r
187\r
188 if (op==0xffff)\r
189 {\r
190 SuperEnd();\r
191 }\r
cc68a136 192}\r
85a36a57 193\r