1 // license:BSD-3-Clause
2 // copyright-holders:Ryan Holtz
3 /***************************************************************************
4
5 arm7fe.c
6
7 Front-end for ARM7 DRC
8
9 ***************************************************************************/
10
11 #include "emu.h"
12 #include "arm7.h"
13
14
15 //**************************************************************************
16 // ARM7 FRONTEND
17 //**************************************************************************
18
19 // register flags 0
20 #define REGFLAG_R(n) (((n) == 0) ? 0 : (1 << (n)))
21
22 //-------------------------------------------------
23 // arm7_frontend - constructor
24 //-------------------------------------------------
25
arm7_frontend(arm7_cpu_device * arm7,uint32_t window_start,uint32_t window_end,uint32_t max_sequence)26 arm7_frontend::arm7_frontend(arm7_cpu_device *arm7, uint32_t window_start, uint32_t window_end, uint32_t max_sequence)
27 : drc_frontend(*arm7, window_start, window_end, max_sequence),
28 m_arm7(arm7)
29 {
30 }
31
32
33 //-------------------------------------------------
34 // describe_thumb - build a description of a
35 // thumb instruction
36 //-------------------------------------------------
37
describe_thumb(opcode_desc & desc,const opcode_desc * prev)38 bool arm7_frontend::describe_thumb(opcode_desc &desc, const opcode_desc *prev)
39 {
40 return false;
41 }
42
43 //-------------------------------------------------
44 // describe_ops_* - build a description of
45 // an ARM7 instruction
46 //-------------------------------------------------
47
describe_ops_0123(opcode_desc & desc,const opcode_desc * prev,uint32_t op)48 bool arm7_frontend::describe_ops_0123(opcode_desc &desc, const opcode_desc *prev, uint32_t op)
49 {
50 /* Branch and Exchange (BX) */
51 if ((op & 0x0ffffff0) == 0x012fff10) // BX
52 {
53 }
54 else if ((op & 0x0ff000f0) == 0x01600010) // CLZ - v5
55 {
56 }
57 else if ((op & 0x0ff000f0) == 0x01000050) // QADD - v5
58 {
59 }
60 else if ((op & 0x0ff000f0) == 0x01400050) // QDADD - v5
61 {
62 }
63 else if ((op & 0x0ff000f0) == 0x01200050) // QSUB - v5
64 {
65 }
66 else if ((op & 0x0ff000f0) == 0x01600050) // QDSUB - v5
67 {
68 }
69 else if ((op & 0x0ff00090) == 0x01000080) // SMLAxy - v5
70 {
71 }
72 else if ((op & 0x0ff00090) == 0x01400080) // SMLALxy - v5
73 {
74 }
75 else if ((op & 0x0ff00090) == 0x01600080) // SMULxy - v5
76 {
77 }
78 else if ((op & 0x0ff000b0) == 0x012000a0) // SMULWy - v5
79 {
80 }
81 else if ((op & 0x0ff000b0) == 0x01200080) // SMLAWy - v5
82 {
83 }
84 else if ((op & 0x0e000000) == 0 && (op & 0x80) && (op & 0x10)) // Multiply OR Swap OR Half Word Data Transfer
85 {
86 if (op & 0x60) // Half Word Data Transfer
87 {
88 //HandleHalfWordDT(op);
89 }
90 else if (op & 0x01000000) // Swap
91 {
92 //HandleSwap(op);
93 }
94 else // Multiply Or Multiply Long
95 {
96 if (op & 0x800000) // Multiply long
97 {
98 if (op & 0x00400000) // Signed multiply
99 {
100 //HandleSMulLong(op);
101 }
102 else // Unsigned multiply
103 {
104 //HandleUMulLong(op);
105 }
106 }
107 else // Multiply
108 {
109 //HandleMul(op);//
110 }
111 }
112 }
113 else if ((op & 0x0c000000) == 0) // Data Processing OR PSR Transfer
114 {
115 if (((op & 0x00100000) == 0) && ((op & 0x01800000) == 0x01000000)) // PSR Transfer
116
117 {
118 //HandlePSRTransfer(insn);
119 desc.cycles = 1;
120 }
121 else // Data processing
122 {
123 //HandleALU(insn);
124 }
125 }
126 return true;
127 }
128
describe_ops_4567(opcode_desc & desc,const opcode_desc * prev,uint32_t op)129 bool arm7_frontend::describe_ops_4567(opcode_desc &desc, const opcode_desc *prev, uint32_t op)
130 {
131 if (op & INSN_I)
132 {
133 /* Register Shift */
134 //off = decodeShift(op, nullptr);
135 }
136 else
137 {
138 /* Immediate Value */
139 //off = op & INSN_SDT_IMM;
140 }
141
142 uint32_t rn = (op & INSN_RN) >> INSN_RN_SHIFT;
143
144 if (op & INSN_SDT_P)
145 {
146 /* Pre-indexed addressing */
147 if ((get_mode32()) || (rn != eR15))
148 {
149 //rnv = (GetRegister(rn) + off);
150 }
151 else
152 {
153 //rnv = (GET_PC + off);
154 }
155
156 if (op & INSN_SDT_W)
157 {
158 //rnv_old = GetRegister(rn);
159 //SetRegister(rn, rnv);
160 }
161 else if (rn == eR15)
162 {
163 //rnv = rnv + 8;
164 }
165 }
166 else
167 {
168 /* Post-indexed addressing */
169 if (rn == eR15)
170 {
171 if (get_mode32())
172 {
173 //rnv = R15 + 8;
174 }
175 else
176 {
177 //rnv = GET_PC + 8;
178 }
179 }
180 else
181 {
182 //rnv = GetRegister(rn);
183 }
184 }
185
186 /* Do the transfer */
187 uint32_t rd = (op & INSN_RD) >> INSN_RD_SHIFT;
188 if (op & INSN_SDT_L)
189 {
190 /* Load */
191 if (op & INSN_SDT_B)
192 {
193 //uint32_t data = READ8(rnv);
194 //SetRegister(rd, data);
195 }
196 else
197 {
198 //uint32_t data = READ32(rnv);
199 if (rd == eR15)
200 {
201 //R15 = data - 4;
202 // LDR, PC takes 2S + 2N + 1I (5 total cycles)
203 desc.cycles = 5;
204 }
205 else
206 {
207 //SetRegister(rd, data);
208 }
209 }
210 }
211 else
212 {
213 /* Store */
214 if (op & INSN_SDT_B)
215 {
216 //WRITE8(rnv, (uint8_t) GetRegister(rd) & 0xffu);
217 }
218 else
219 {
220 //WRITE32(rnv, rd == eR15 ? R15 + 8 + 4 : GetRegister(rd)); // manual says STR rd = PC, +12
221 }
222 // Store takes only 2 N Cycles, so add + 1
223 desc.cycles = 2;
224 }
225
226 /* Do post-indexing writeback */
227 if (!(op & INSN_SDT_P)/* && (insn & INSN_SDT_W)*/)
228 {
229 if (rd == rn) {
230 //SetRegister(rn, GetRegister(rd));
231 }
232 else {
233 //SetRegister(rn, (rnv +/- off));
234 }
235 }
236 return true;
237 }
238
describe_ops_89(opcode_desc & desc,const opcode_desc * prev,uint32_t op)239 bool arm7_frontend::describe_ops_89(opcode_desc &desc, const opcode_desc *prev, uint32_t op)
240 {
241 if ((op & 0x005f0f00) == 0x004d0500)
242 {
243 // unsupported (armv6 onwards only)
244 //arm9ops_undef(insn);
245 //R15 += 4;
246 }
247 else if ((op & 0x00500f00) == 0x00100a00) /* Return From Exception (RFE) */
248 {
249 // unsupported (armv6 onwards only)
250 //arm9ops_undef(insn);
251 //R15 += 4;
252 }
253 else
254 {
255 //arm9ops_undef(insn);
256 //R15 += 4;
257 }
258 return false;
259 }
260
describe_ops_ab(opcode_desc & desc,const opcode_desc * prev,uint32_t op)261 bool arm7_frontend::describe_ops_ab(opcode_desc &desc, const opcode_desc *prev, uint32_t op)
262 {
263 // BLX
264 //HandleBranch(insn, true);
265 //set_cpsr(GET_CPSR|T_MASK);
266 return true;
267 }
268
describe_ops_cd(opcode_desc & desc,const opcode_desc * prev,uint32_t op)269 bool arm7_frontend::describe_ops_cd(opcode_desc &desc, const opcode_desc *prev, uint32_t op)
270 {
271 /* Additional coprocessor double register transfer */
272 if ((op & 0x00e00000) == 0x00400000)
273 {
274 // unsupported
275 //arm9ops_undef(insn);
276 //R15 += 4;
277 }
278 else
279 {
280 //arm9ops_undef(insn);
281 //R15 += 4;
282 }
283 return false;
284 }
285
describe_ops_e(opcode_desc & desc,const opcode_desc * prev,uint32_t op)286 bool arm7_frontend::describe_ops_e(opcode_desc &desc, const opcode_desc *prev, uint32_t op)
287 {
288 /* Additional coprocessor register transfer */
289 // unsupported
290 //arm9ops_undef(insn);
291 //R15 += 4;
292 return false;
293 }
294
describe_ops_f(opcode_desc & desc,const opcode_desc * prev,uint32_t op)295 bool arm7_frontend::describe_ops_f(opcode_desc &desc, const opcode_desc *prev, uint32_t op)
296 {
297 return false;
298 }
299
300 //-------------------------------------------------
301 // describe_arm9_ops_* - build a description of
302 // an ARM9 instruction
303 //-------------------------------------------------
304
describe_arm9_ops_1(opcode_desc & desc,const opcode_desc * prev,uint32_t op)305 bool describe_arm9_ops_1(opcode_desc &desc, const opcode_desc *prev, uint32_t op)
306 {
307 /* Change processor state (CPS) */
308 if ((op & 0x00f10020) == 0x00000000)
309 {
310 // unsupported (armv6 onwards only)
311 //arm9ops_undef(insn);
312 //R15 += 4;
313 }
314 else if ((op & 0x00ff00f0) == 0x00010000) /* set endianness (SETEND) */
315 {
316 // unsupported (armv6 onwards only)
317 //arm9ops_undef(insn);
318 //R15 += 4;
319 }
320 else
321 {
322 //arm9ops_undef(insn);
323 //R15 += 4;
324 }
325 return false;
326 }
327
describe_arm9_ops_57(opcode_desc & desc,const opcode_desc * prev,uint32_t op)328 bool describe_arm9_ops_57(opcode_desc &desc, const opcode_desc *prev, uint32_t op)
329 {
330 /* Cache Preload (PLD) */
331 if ((op & 0x0070f000) == 0x0050f000)
332 {
333 // unsupported (armv6 onwards only)
334 //arm9ops_undef(insn);
335 //R15 += 4;
336 }
337 else
338 {
339 //arm9ops_undef(insn);
340 //R15 += 4;
341 }
342 return false;
343 }
344
describe_arm9_ops_89(opcode_desc & desc,const opcode_desc * prev,uint32_t op)345 bool describe_arm9_ops_89(opcode_desc &desc, const opcode_desc *prev, uint32_t op)
346 {
347 return false;
348 }
349
describe_arm9_ops_ab(opcode_desc & desc,const opcode_desc * prev,uint32_t op)350 bool describe_arm9_ops_ab(opcode_desc &desc, const opcode_desc *prev, uint32_t op)
351 {
352 return false;
353 }
354
describe_arm9_ops_c(opcode_desc & desc,const opcode_desc * prev,uint32_t op)355 bool describe_arm9_ops_c(opcode_desc &desc, const opcode_desc *prev, uint32_t op)
356 {
357 return false;
358 }
359
describe_arm9_ops_e(opcode_desc & desc,const opcode_desc * prev,uint32_t op)360 bool describe_arm9_ops_e(opcode_desc &desc, const opcode_desc *prev, uint32_t op)
361 {
362 return false;
363 }
364
365
get_cpsr()366 uint32_t arm7_frontend::get_cpsr()
367 {
368 return m_arm7->m_r[eCPSR];
369 }
370
get_mode32()371 bool arm7_frontend::get_mode32()
372 {
373 return m_arm7->m_r[eCPSR] & SR_MODE32;
374 }
375
376 //-------------------------------------------------
377 // describe - build a description of a single
378 // instruction
379 //-------------------------------------------------
380
describe(opcode_desc & desc,const opcode_desc * prev)381 bool arm7_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
382 {
383 // compute the physical PC
384 const uint32_t cpsr = get_cpsr();
385 assert((desc.physpc & (T_IS_SET(cpsr) ? 1 : 3)) == 0);
386 if (!m_arm7->arm7_tlb_translate(desc.physpc, ARM7_TLB_ABORT_P | ARM7_TLB_READ))
387 {
388 // uh-oh: a page fault; leave the description empty and just if this is the first instruction, leave it empty and
389 // mark as needing to validate; otherwise, just end the sequence here
390 desc.flags |= OPFLAG_VALIDATE_TLB | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_COMPILER_PAGE_FAULT | OPFLAG_VIRTUAL_NOOP | OPFLAG_END_SEQUENCE;
391 return true;
392 }
393
394 if (T_IS_SET(cpsr))
395 {
396 return describe_thumb(desc, prev);
397 }
398
399 // fetch the opcode
400 uint32_t op = desc.opptr.l[0] = m_arm7->m_direct->read_dword(desc.physpc);
401
402 // all non-THUMB instructions are 4 bytes and default to 3 cycles each
403 desc.length = 4;
404 desc.cycles = 3;
405
406 // parse the instruction
407
408 int op_offset = 0;
409 if ((op >> INSN_COND_SHIFT) == COND_NV && m_arm7->m_archRev >= 5)
410 {
411 op_offset = 0x10;
412 }
413
414 switch (((op & 0xF000000) >> 24) + op_offset)
415 {
416 case 0x0: case 0x1: case 0x2: case 0x3:
417 return describe_ops_0123(desc, prev, op);
418
419 case 0x4: case 0x5: case 0x6: case 0x7:
420 return describe_ops_4567(desc, prev, op);
421
422 case 0x8: case 0x9:
423 return describe_ops_89(desc, prev, op);
424
425 case 0xa: case 0xb:
426 return describe_ops_ab(desc, prev, op);
427
428 case 0xc: case 0xd:
429 return describe_ops_cd(desc, prev, op);
430
431 case 0xe:
432 return describe_ops_e(desc, prev, op);
433
434 case 0xf:
435 return describe_ops_f(desc, prev, op);
436
437 case 0x11: // ARM9
438 return describe_arm9_ops_1(desc, prev, op);
439
440 case 0x15: case 0x17: // ARM9
441 return describe_arm9_ops_57(desc, prev, op);
442
443 case 0x18: case 0x19: // ARM9
444 return describe_arm9_ops_89(desc, prev, op);
445
446 case 0x1a: case 0x1b: // ARM9
447 return describe_arm9_ops_ab(desc, prev, op);
448
449 case 0x1c: // ARM9
450 return describe_arm9_ops_c(desc, prev, op);
451
452 case 0x1e: // ARM9
453 return describe_arm9_ops_e(desc, prev, op);
454
455 default:
456 return false;
457 }
458 }
459