trunk/src/emu/cpu/arm/arm.c
r23977 | r23978 | |
22 | 22 | CPU_DISASSEMBLE( arm ); |
23 | 23 | CPU_DISASSEMBLE( arm_be ); |
24 | 24 | |
25 | | #define READ8(addr) cpu_read8(cpustate,addr) |
26 | | #define WRITE8(addr,data) cpu_write8(cpustate,addr,data) |
27 | | #define READ32(addr) cpu_read32(cpustate,addr) |
28 | | #define WRITE32(addr,data) cpu_write32(cpustate,addr,data) |
| 25 | #define READ8(addr) cpu_read8(addr) |
| 26 | #define WRITE8(addr,data) cpu_write8(addr,data) |
| 27 | #define READ32(addr) cpu_read32(addr) |
| 28 | #define WRITE32(addr,data) cpu_write32(addr,data) |
29 | 29 | |
30 | 30 | #define ARM_DEBUG_CORE 0 |
31 | 31 | #define ARM_DEBUG_COPRO 0 |
r23977 | r23978 | |
125 | 125 | #define ADDRESS_MASK ((UINT32) 0x03fffffcu) |
126 | 126 | #define MODE_MASK ((UINT32) 0x00000003u) |
127 | 127 | |
128 | | #define R15 cpustate->sArmRegister[eR15] |
| 128 | #define R15 m_sArmRegister[eR15] |
129 | 129 | #define MODE (R15&0x03) |
130 | 130 | #define SIGN_BIT ((UINT32)(1<<31)) |
131 | 131 | #define SIGN_BITS_DIFFER(a,b) (((a)^(b)) >> 31) |
r23977 | r23978 | |
224 | 224 | #define ROL(v,s) (LSL((v),(s)) | (LSR((v),32u - (s)))) |
225 | 225 | #define ROR(v,s) (LSR((v),(s)) | (LSL((v),32u - (s)))) |
226 | 226 | |
227 | | /* Private Data */ |
228 | 227 | |
229 | | /* sArmRegister defines the CPU state */ |
230 | | struct ARM_REGS |
| 228 | /***************************************************************************/ |
| 229 | |
| 230 | const device_type ARM = &device_creator<arm_cpu_device>; |
| 231 | const device_type ARM_BE = &device_creator<arm_be_cpu_device>; |
| 232 | |
| 233 | |
| 234 | arm_cpu_device::arm_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 235 | : cpu_device(mconfig, ARM, "ARM", tag, owner, clock, "arm", __FILE__) |
| 236 | , m_program_config("program", ENDIANNESS_LITTLE, 32, 26, 0) |
| 237 | , m_endian(ENDIANNESS_LITTLE) |
231 | 238 | { |
232 | | int icount; |
233 | | UINT32 sArmRegister[kNumRegisters]; |
234 | | UINT32 coproRegister[16]; |
235 | | UINT8 pendingIrq; |
236 | | UINT8 pendingFiq; |
237 | | device_irq_acknowledge_callback irq_callback; |
238 | | legacy_cpu_device *device; |
239 | | address_space *program; |
240 | | direct_read_data *direct; |
241 | | endianness_t endian; |
242 | | }; |
| 239 | } |
243 | 240 | |
244 | | /* Prototypes */ |
245 | | static void HandleALU( ARM_REGS* cpustate, UINT32 insn); |
246 | | static void HandleMul( ARM_REGS* cpustate, UINT32 insn); |
247 | | static void HandleBranch( ARM_REGS* cpustate, UINT32 insn); |
248 | | static void HandleMemSingle( ARM_REGS* cpustate, UINT32 insn); |
249 | | static void HandleMemBlock( ARM_REGS* cpustate, UINT32 insn); |
250 | | static void HandleCoPro( ARM_REGS* cpustate, UINT32 insn); |
251 | | static UINT32 decodeShift( ARM_REGS* cpustate, UINT32 insn, UINT32 *pCarry); |
252 | | static void arm_check_irq_state(ARM_REGS* cpustate); |
253 | 241 | |
254 | | /***************************************************************************/ |
| 242 | arm_cpu_device::arm_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source, endianness_t endianness) |
| 243 | : cpu_device(mconfig, type, name, tag, owner, clock, shortname, source) |
| 244 | , m_program_config("program", endianness, 32, 26, 0) |
| 245 | , m_endian(endianness) |
| 246 | { |
| 247 | } |
255 | 248 | |
256 | | INLINE ARM_REGS *get_safe_token(device_t *device) |
| 249 | |
| 250 | arm_be_cpu_device::arm_be_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 251 | : arm_cpu_device(mconfig, ARM_BE, "ARM (big endian)", tag, owner, clock, "arm be", __FILE__, ENDIANNESS_BIG) |
257 | 252 | { |
258 | | assert(device != NULL); |
259 | | assert(device->type() == ARM || device->type() == ARM_BE); |
260 | | return (ARM_REGS *)downcast<legacy_cpu_device *>(device)->token(); |
261 | 253 | } |
262 | 254 | |
263 | | INLINE void cpu_write32( ARM_REGS* cpustate, int addr, UINT32 data ) |
| 255 | |
| 256 | void arm_cpu_device::cpu_write32( int addr, UINT32 data ) |
264 | 257 | { |
265 | 258 | /* Unaligned writes are treated as normal writes */ |
266 | | if ( cpustate->endian == ENDIANNESS_BIG ) |
267 | | cpustate->program->write_dword(addr&ADDRESS_MASK,data); |
| 259 | if ( m_endian == ENDIANNESS_BIG ) |
| 260 | m_program->write_dword(addr&ADDRESS_MASK,data); |
268 | 261 | else |
269 | | cpustate->program->write_dword(addr&ADDRESS_MASK,data); |
| 262 | m_program->write_dword(addr&ADDRESS_MASK,data); |
270 | 263 | if (ARM_DEBUG_CORE && addr&3) logerror("%08x: Unaligned write %08x\n",R15,addr); |
271 | 264 | } |
272 | 265 | |
273 | | INLINE void cpu_write8( ARM_REGS* cpustate, int addr, UINT8 data ) |
| 266 | void arm_cpu_device::cpu_write8( int addr, UINT8 data ) |
274 | 267 | { |
275 | | if ( cpustate->endian == ENDIANNESS_BIG ) |
276 | | cpustate->program->write_byte(addr,data); |
| 268 | if ( m_endian == ENDIANNESS_BIG ) |
| 269 | m_program->write_byte(addr,data); |
277 | 270 | else |
278 | | cpustate->program->write_byte(addr,data); |
| 271 | m_program->write_byte(addr,data); |
279 | 272 | } |
280 | 273 | |
281 | | INLINE UINT32 cpu_read32( ARM_REGS* cpustate, int addr ) |
| 274 | UINT32 arm_cpu_device::cpu_read32( int addr ) |
282 | 275 | { |
283 | 276 | UINT32 result; |
284 | 277 | |
285 | | if ( cpustate->endian == ENDIANNESS_BIG ) |
286 | | result = cpustate->program->read_dword(addr&ADDRESS_MASK); |
| 278 | if ( m_endian == ENDIANNESS_BIG ) |
| 279 | result = m_program->read_dword(addr&ADDRESS_MASK); |
287 | 280 | else |
288 | | result = cpustate->program->read_dword(addr&ADDRESS_MASK); |
| 281 | result = m_program->read_dword(addr&ADDRESS_MASK); |
289 | 282 | |
290 | 283 | /* Unaligned reads rotate the word, they never combine words */ |
291 | 284 | if (addr&3) { |
r23977 | r23978 | |
303 | 296 | return result; |
304 | 297 | } |
305 | 298 | |
306 | | INLINE UINT8 cpu_read8( ARM_REGS* cpustate, int addr ) |
| 299 | UINT8 arm_cpu_device::cpu_read8( int addr ) |
307 | 300 | { |
308 | | if ( cpustate->endian == ENDIANNESS_BIG ) |
309 | | return cpustate->program->read_byte(addr); |
| 301 | if ( m_endian == ENDIANNESS_BIG ) |
| 302 | return m_program->read_byte(addr); |
310 | 303 | else |
311 | | return cpustate->program->read_byte(addr); |
| 304 | return m_program->read_byte(addr); |
312 | 305 | } |
313 | 306 | |
314 | | INLINE UINT32 GetRegister( ARM_REGS* cpustate, int rIndex ) |
| 307 | UINT32 arm_cpu_device::GetRegister( int rIndex ) |
315 | 308 | { |
316 | | return cpustate->sArmRegister[sRegisterTable[MODE][rIndex]]; |
| 309 | return m_sArmRegister[sRegisterTable[MODE][rIndex]]; |
317 | 310 | } |
318 | 311 | |
319 | | INLINE void SetRegister( ARM_REGS* cpustate, int rIndex, UINT32 value ) |
| 312 | void arm_cpu_device::SetRegister( int rIndex, UINT32 value ) |
320 | 313 | { |
321 | | cpustate->sArmRegister[sRegisterTable[MODE][rIndex]] = value; |
| 314 | m_sArmRegister[sRegisterTable[MODE][rIndex]] = value; |
322 | 315 | } |
323 | 316 | |
324 | | INLINE UINT32 GetModeRegister( ARM_REGS* cpustate, int mode, int rIndex ) |
| 317 | UINT32 arm_cpu_device::GetModeRegister( int mode, int rIndex ) |
325 | 318 | { |
326 | | return cpustate->sArmRegister[sRegisterTable[mode][rIndex]]; |
| 319 | return m_sArmRegister[sRegisterTable[mode][rIndex]]; |
327 | 320 | } |
328 | 321 | |
329 | | INLINE void SetModeRegister( ARM_REGS* cpustate, int mode, int rIndex, UINT32 value ) |
| 322 | void arm_cpu_device::SetModeRegister( int mode, int rIndex, UINT32 value ) |
330 | 323 | { |
331 | | cpustate->sArmRegister[sRegisterTable[mode][rIndex]] = value; |
| 324 | m_sArmRegister[sRegisterTable[mode][rIndex]] = value; |
332 | 325 | } |
333 | 326 | |
334 | 327 | |
335 | 328 | /***************************************************************************/ |
336 | 329 | |
337 | | static CPU_RESET( arm ) |
| 330 | void arm_cpu_device::device_reset() |
338 | 331 | { |
339 | | ARM_REGS *cpustate = get_safe_token(device); |
| 332 | for ( int i = 0; i < 27; i++ ) |
| 333 | { |
| 334 | m_sArmRegister[i] = 0; |
| 335 | } |
| 336 | for ( int i = 0; i < 16; i++ ) |
| 337 | { |
| 338 | m_coproRegister[i] = 0; |
| 339 | } |
| 340 | m_pendingIrq = 0; |
| 341 | m_pendingFiq = 0; |
340 | 342 | |
341 | | device_irq_acknowledge_callback save_irqcallback = cpustate->irq_callback; |
342 | | endianness_t save_endian = cpustate->endian; |
343 | | |
344 | | memset(cpustate, 0, sizeof(ARM_REGS)); |
345 | | cpustate->irq_callback = save_irqcallback; |
346 | | cpustate->endian = save_endian; |
347 | | cpustate->device = device; |
348 | | cpustate->program = &device->space(AS_PROGRAM); |
349 | | cpustate->direct = &cpustate->program->direct(); |
350 | | |
351 | 343 | /* start up in SVC mode with interrupts disabled. */ |
352 | 344 | R15 = eARM_MODE_SVC|I_MASK|F_MASK; |
353 | 345 | } |
354 | 346 | |
355 | | static CPU_EXIT( arm ) |
356 | | { |
357 | | /* nothing to do here */ |
358 | | } |
359 | 347 | |
360 | | static CPU_EXECUTE( arm ) |
| 348 | void arm_cpu_device::execute_run() |
361 | 349 | { |
362 | 350 | UINT32 pc; |
363 | 351 | UINT32 insn; |
364 | | ARM_REGS *cpustate = get_safe_token(device); |
365 | 352 | |
366 | 353 | do |
367 | 354 | { |
368 | | debugger_instruction_hook(device, R15 & ADDRESS_MASK); |
| 355 | debugger_instruction_hook(this, R15 & ADDRESS_MASK); |
369 | 356 | |
370 | 357 | /* load instruction */ |
371 | 358 | pc = R15; |
372 | | insn = cpustate->direct->read_decrypted_dword( pc & ADDRESS_MASK ); |
| 359 | insn = m_direct->read_decrypted_dword( pc & ADDRESS_MASK ); |
373 | 360 | |
374 | 361 | switch (insn >> INSN_COND_SHIFT) |
375 | 362 | { |
r23977 | r23978 | |
421 | 408 | /* Condition satisfied, so decode the instruction */ |
422 | 409 | if ((insn & 0x0fc000f0u) == 0x00000090u) /* Multiplication */ |
423 | 410 | { |
424 | | HandleMul(cpustate, insn); |
| 411 | HandleMul(insn); |
425 | 412 | R15 += 4; |
426 | 413 | } |
427 | 414 | else if (!(insn & 0x0c000000u)) /* Data processing */ |
428 | 415 | { |
429 | | HandleALU(cpustate, insn); |
| 416 | HandleALU(insn); |
430 | 417 | } |
431 | 418 | else if ((insn & 0x0c000000u) == 0x04000000u) /* Single data access */ |
432 | 419 | { |
433 | | HandleMemSingle(cpustate, insn); |
| 420 | HandleMemSingle(insn); |
434 | 421 | R15 += 4; |
435 | 422 | } |
436 | 423 | else if ((insn & 0x0e000000u) == 0x08000000u ) /* Block data access */ |
437 | 424 | { |
438 | | HandleMemBlock(cpustate, insn); |
| 425 | HandleMemBlock(insn); |
439 | 426 | R15 += 4; |
440 | 427 | } |
441 | 428 | else if ((insn & 0x0e000000u) == 0x0a000000u) /* Branch */ |
442 | 429 | { |
443 | | HandleBranch(cpustate, insn); |
| 430 | HandleBranch(insn); |
444 | 431 | } |
445 | 432 | else if ((insn & 0x0f000000u) == 0x0e000000u) /* Coprocessor */ |
446 | 433 | { |
447 | | HandleCoPro(cpustate, insn); |
| 434 | HandleCoPro(insn); |
448 | 435 | R15 += 4; |
449 | 436 | } |
450 | 437 | else if ((insn & 0x0f000000u) == 0x0f000000u) /* Software interrupt */ |
451 | 438 | { |
452 | 439 | pc=R15+4; |
453 | 440 | R15 = eARM_MODE_SVC; /* Set SVC mode so PC is saved to correct R14 bank */ |
454 | | SetRegister( cpustate, 14, pc ); /* save PC */ |
| 441 | SetRegister( 14, pc ); /* save PC */ |
455 | 442 | R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|0x8|eARM_MODE_SVC|I_MASK|(pc&MODE_MASK); |
456 | | cpustate->icount -= 2 * S_CYCLE + N_CYCLE; |
| 443 | m_icount -= 2 * S_CYCLE + N_CYCLE; |
457 | 444 | } |
458 | 445 | else /* Undefined */ |
459 | 446 | { |
460 | 447 | logerror("%08x: Undefined instruction\n",R15); |
461 | 448 | L_Next: |
462 | | cpustate->icount -= S_CYCLE; |
| 449 | m_icount -= S_CYCLE; |
463 | 450 | R15 += 4; |
464 | 451 | } |
465 | 452 | |
466 | | arm_check_irq_state(cpustate); |
| 453 | arm_check_irq_state(); |
467 | 454 | |
468 | | } while( cpustate->icount > 0 ); |
| 455 | } while( m_icount > 0 ); |
469 | 456 | } /* arm_execute */ |
470 | 457 | |
471 | 458 | |
472 | | static void arm_check_irq_state(ARM_REGS* cpustate) |
| 459 | void arm_cpu_device::arm_check_irq_state() |
473 | 460 | { |
474 | 461 | UINT32 pc = R15+4; /* save old pc (already incremented in pipeline) */; |
475 | 462 | |
r23977 | r23978 | |
483 | 470 | Undefined instruction |
484 | 471 | */ |
485 | 472 | |
486 | | if (cpustate->pendingFiq && (pc&F_MASK)==0) { |
| 473 | if (m_pendingFiq && (pc&F_MASK)==0) { |
487 | 474 | R15 = eARM_MODE_FIQ; /* Set FIQ mode so PC is saved to correct R14 bank */ |
488 | | SetRegister( cpustate, 14, pc ); /* save PC */ |
| 475 | SetRegister( 14, pc ); /* save PC */ |
489 | 476 | R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|0x1c|eARM_MODE_FIQ|I_MASK|F_MASK; /* Mask both IRQ & FIRQ, set PC=0x1c */ |
490 | | cpustate->pendingFiq=0; |
| 477 | m_pendingFiq=0; |
491 | 478 | return; |
492 | 479 | } |
493 | 480 | |
494 | | if (cpustate->pendingIrq && (pc&I_MASK)==0) { |
| 481 | if (m_pendingIrq && (pc&I_MASK)==0) { |
495 | 482 | R15 = eARM_MODE_IRQ; /* Set IRQ mode so PC is saved to correct R14 bank */ |
496 | | SetRegister( cpustate, 14, pc ); /* save PC */ |
| 483 | SetRegister( 14, pc ); /* save PC */ |
497 | 484 | R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|0x18|eARM_MODE_IRQ|I_MASK|(pc&F_MASK); /* Mask only IRQ, set PC=0x18 */ |
498 | | cpustate->pendingIrq=0; |
| 485 | m_pendingIrq=0; |
499 | 486 | return; |
500 | 487 | } |
501 | 488 | } |
502 | 489 | |
503 | | static void set_irq_line(ARM_REGS* cpustate, int irqline, int state) |
| 490 | |
| 491 | void arm_cpu_device::execute_set_input(int irqline, int state) |
504 | 492 | { |
505 | 493 | switch (irqline) { |
506 | 494 | case ARM_IRQ_LINE: /* IRQ */ |
507 | 495 | if (state && (R15&0x3)!=eARM_MODE_IRQ) /* Don't allow nested IRQs */ |
508 | | cpustate->pendingIrq=1; |
| 496 | m_pendingIrq=1; |
509 | 497 | else |
510 | | cpustate->pendingIrq=0; |
| 498 | m_pendingIrq=0; |
511 | 499 | break; |
512 | 500 | |
513 | 501 | case ARM_FIRQ_LINE: /* FIRQ */ |
514 | 502 | if (state && (R15&0x3)!=eARM_MODE_FIQ) /* Don't allow nested FIRQs */ |
515 | | cpustate->pendingFiq=1; |
| 503 | m_pendingFiq=1; |
516 | 504 | else |
517 | | cpustate->pendingFiq=0; |
| 505 | m_pendingFiq=0; |
518 | 506 | break; |
519 | 507 | } |
520 | 508 | |
521 | | arm_check_irq_state(cpustate); |
| 509 | arm_check_irq_state(); |
522 | 510 | } |
523 | 511 | |
524 | | static CPU_INIT( arm ) |
| 512 | |
| 513 | void arm_cpu_device::device_start() |
525 | 514 | { |
526 | | ARM_REGS *cpustate = get_safe_token(device); |
| 515 | m_program = &space(AS_PROGRAM); |
| 516 | m_direct = &m_program->direct(); |
527 | 517 | |
528 | | cpustate->irq_callback = irqcallback; |
529 | | cpustate->device = device; |
530 | | cpustate->program = &device->space(AS_PROGRAM); |
531 | | cpustate->endian = ENDIANNESS_LITTLE; |
| 518 | save_item(NAME(m_sArmRegister)); |
| 519 | save_item(NAME(m_coproRegister)); |
| 520 | save_item(NAME(m_pendingIrq)); |
| 521 | save_item(NAME(m_pendingFiq)); |
532 | 522 | |
533 | | device->save_item(NAME(cpustate->sArmRegister)); |
534 | | device->save_item(NAME(cpustate->coproRegister)); |
535 | | device->save_item(NAME(cpustate->pendingIrq)); |
536 | | device->save_item(NAME(cpustate->pendingFiq)); |
| 523 | state_add( ARM32_PC, "PC", m_sArmRegister[15] ).mask(ADDRESS_MASK).formatstr("%08X"); |
| 524 | state_add( ARM32_R0, "R0", m_sArmRegister[ 0] ).formatstr("%08X"); |
| 525 | state_add( ARM32_R1, "R1", m_sArmRegister[ 1] ).formatstr("%08X"); |
| 526 | state_add( ARM32_R2, "R2", m_sArmRegister[ 2] ).formatstr("%08X"); |
| 527 | state_add( ARM32_R3, "R3", m_sArmRegister[ 3] ).formatstr("%08X"); |
| 528 | state_add( ARM32_R4, "R4", m_sArmRegister[ 4] ).formatstr("%08X"); |
| 529 | state_add( ARM32_R5, "R5", m_sArmRegister[ 5] ).formatstr("%08X"); |
| 530 | state_add( ARM32_R6, "R6", m_sArmRegister[ 6] ).formatstr("%08X"); |
| 531 | state_add( ARM32_R7, "R7", m_sArmRegister[ 7] ).formatstr("%08X"); |
| 532 | state_add( ARM32_R8, "R8", m_sArmRegister[ 8] ).formatstr("%08X"); |
| 533 | state_add( ARM32_R9, "R9", m_sArmRegister[ 9] ).formatstr("%08X"); |
| 534 | state_add( ARM32_R10, "R10", m_sArmRegister[10] ).formatstr("%08X"); |
| 535 | state_add( ARM32_R11, "R11", m_sArmRegister[11] ).formatstr("%08X"); |
| 536 | state_add( ARM32_R12, "R12", m_sArmRegister[12] ).formatstr("%08X"); |
| 537 | state_add( ARM32_R13, "R13", m_sArmRegister[13] ).formatstr("%08X"); |
| 538 | state_add( ARM32_R14, "R14", m_sArmRegister[14] ).formatstr("%08X"); |
| 539 | state_add( ARM32_R15, "R15", m_sArmRegister[15] ).formatstr("%08X"); |
| 540 | state_add( ARM32_FR8, "FR8", m_sArmRegister[eR8_FIQ] ).formatstr("%08X"); |
| 541 | state_add( ARM32_FR9, "FR9", m_sArmRegister[eR9_FIQ] ).formatstr("%08X"); |
| 542 | state_add( ARM32_FR10, "FR10", m_sArmRegister[eR10_FIQ] ).formatstr("%08X"); |
| 543 | state_add( ARM32_FR11, "FR11", m_sArmRegister[eR11_FIQ] ).formatstr("%08X"); |
| 544 | state_add( ARM32_FR12, "FR12", m_sArmRegister[eR12_FIQ] ).formatstr("%08X"); |
| 545 | state_add( ARM32_FR13, "FR13", m_sArmRegister[eR13_FIQ] ).formatstr("%08X"); |
| 546 | state_add( ARM32_FR14, "FR14", m_sArmRegister[eR14_FIQ] ).formatstr("%08X"); |
| 547 | state_add( ARM32_IR13, "IR13", m_sArmRegister[eR13_IRQ] ).formatstr("%08X"); |
| 548 | state_add( ARM32_IR14, "IR14", m_sArmRegister[eR14_IRQ] ).formatstr("%08X"); |
| 549 | state_add( ARM32_SR13, "SR13", m_sArmRegister[eR13_SVC] ).formatstr("%08X"); |
| 550 | state_add( ARM32_SR14, "SR14", m_sArmRegister[eR14_SVC] ).formatstr("%08X"); |
| 551 | |
| 552 | state_add(STATE_GENPC, "curpc", m_sArmRegister[15]).mask(ADDRESS_MASK).callimport().callexport().formatstr("%11s").noshow(); |
| 553 | state_add(STATE_GENFLAGS, "GENFLAGS", m_sArmRegister[15]).formatstr("%8s").noshow(); |
| 554 | |
| 555 | m_icountptr = &m_icount; |
537 | 556 | } |
538 | 557 | |
539 | 558 | |
540 | | static CPU_INIT( arm_be ) |
| 559 | void arm_cpu_device::state_string_export(const device_state_entry &entry, astring &string) |
541 | 560 | { |
542 | | ARM_REGS *cpustate = get_safe_token(device); |
| 561 | static const char *s[4] = { "USER", "FIRQ", "IRQ ", "SVC " }; |
543 | 562 | |
544 | | cpustate->irq_callback = irqcallback; |
545 | | cpustate->device = device; |
546 | | cpustate->program = &device->space(AS_PROGRAM); |
547 | | cpustate->endian = ENDIANNESS_BIG; |
548 | | |
549 | | device->save_item(NAME(cpustate->sArmRegister)); |
550 | | device->save_item(NAME(cpustate->coproRegister)); |
551 | | device->save_item(NAME(cpustate->pendingIrq)); |
552 | | device->save_item(NAME(cpustate->pendingFiq)); |
| 563 | switch (entry.index()) |
| 564 | { |
| 565 | case STATE_GENFLAGS: |
| 566 | string.printf("%c%c%c%c%c%c %s", |
| 567 | (m_sArmRegister[15] & N_MASK) ? 'N' : '-', |
| 568 | (m_sArmRegister[15] & Z_MASK) ? 'Z' : '-', |
| 569 | (m_sArmRegister[15] & C_MASK) ? 'C' : '-', |
| 570 | (m_sArmRegister[15] & V_MASK) ? 'V' : '-', |
| 571 | (m_sArmRegister[15] & I_MASK) ? 'I' : '-', |
| 572 | (m_sArmRegister[15] & F_MASK) ? 'F' : '-', |
| 573 | s[m_sArmRegister[15] & 3] ); |
| 574 | break; |
| 575 | } |
553 | 576 | } |
554 | 577 | |
555 | 578 | |
556 | 579 | /***************************************************************************/ |
557 | 580 | |
558 | | static void HandleBranch( ARM_REGS* cpustate, UINT32 insn ) |
| 581 | void arm_cpu_device::HandleBranch( UINT32 insn ) |
559 | 582 | { |
560 | 583 | UINT32 off = (insn & INSN_BRANCH) << 2; |
561 | 584 | |
562 | 585 | /* Save PC into LR if this is a branch with link */ |
563 | 586 | if (insn & INSN_BL) |
564 | 587 | { |
565 | | SetRegister(cpustate, 14,R15 + 4); |
| 588 | SetRegister(14,R15 + 4); |
566 | 589 | } |
567 | 590 | |
568 | 591 | /* Sign-extend the 24-bit offset in our calculations */ |
r23977 | r23978 | |
574 | 597 | { |
575 | 598 | R15 += off + 8; |
576 | 599 | } |
577 | | cpustate->icount -= 2 * S_CYCLE + N_CYCLE; |
| 600 | m_icount -= 2 * S_CYCLE + N_CYCLE; |
578 | 601 | } |
579 | 602 | |
580 | | static void HandleMemSingle( ARM_REGS* cpustate, UINT32 insn ) |
| 603 | |
| 604 | void arm_cpu_device::HandleMemSingle( UINT32 insn ) |
581 | 605 | { |
582 | 606 | UINT32 rn, rnv, off, rd; |
583 | 607 | |
584 | 608 | /* Fetch the offset */ |
585 | 609 | if (insn & INSN_I) |
586 | 610 | { |
587 | | off = decodeShift(cpustate, insn, NULL); |
| 611 | off = decodeShift(insn, NULL); |
588 | 612 | } |
589 | 613 | else |
590 | 614 | { |
r23977 | r23978 | |
602 | 626 | if (insn & INSN_SDT_U) |
603 | 627 | { |
604 | 628 | if (rn != eR15) |
605 | | rnv = (GetRegister(cpustate, rn) + off); |
| 629 | rnv = (GetRegister(rn) + off); |
606 | 630 | else |
607 | 631 | rnv = (R15 & ADDRESS_MASK) + off; |
608 | 632 | } |
609 | 633 | else |
610 | 634 | { |
611 | 635 | if (rn != eR15) |
612 | | rnv = (GetRegister(cpustate, rn) - off); |
| 636 | rnv = (GetRegister(rn) - off); |
613 | 637 | else |
614 | 638 | rnv = (R15 & ADDRESS_MASK) - off; |
615 | 639 | } |
616 | 640 | |
617 | 641 | if (insn & INSN_SDT_W) |
618 | 642 | { |
619 | | SetRegister(cpustate, rn,rnv); |
| 643 | SetRegister(rn,rnv); |
620 | 644 | if (ARM_DEBUG_CORE && rn == eR15) |
621 | 645 | logerror("writeback R15 %08x\n", R15); |
622 | 646 | } |
r23977 | r23978 | |
634 | 658 | } |
635 | 659 | else |
636 | 660 | { |
637 | | rnv = GetRegister(cpustate, rn); |
| 661 | rnv = GetRegister(rn); |
638 | 662 | } |
639 | 663 | } |
640 | 664 | |
r23977 | r23978 | |
643 | 667 | if (insn & INSN_SDT_L) |
644 | 668 | { |
645 | 669 | /* Load */ |
646 | | cpustate->icount -= S_CYCLE + I_CYCLE + N_CYCLE; |
| 670 | m_icount -= S_CYCLE + I_CYCLE + N_CYCLE; |
647 | 671 | if (insn & INSN_SDT_B) |
648 | 672 | { |
649 | 673 | if (ARM_DEBUG_CORE && rd == eR15) |
650 | 674 | logerror("read byte R15 %08x\n", R15); |
651 | | SetRegister(cpustate, rd,(UINT32) READ8(rnv) ); |
| 675 | SetRegister(rd,(UINT32) READ8(rnv) ); |
652 | 676 | } |
653 | 677 | else |
654 | 678 | { |
r23977 | r23978 | |
667 | 691 | if ((READ32(rnv)&3)==0) |
668 | 692 | R15 -= 4; |
669 | 693 | |
670 | | cpustate->icount -= S_CYCLE + N_CYCLE; |
| 694 | m_icount -= S_CYCLE + N_CYCLE; |
671 | 695 | } |
672 | 696 | else |
673 | 697 | { |
674 | | SetRegister(cpustate, rd, READ32(rnv)); |
| 698 | SetRegister(rd, READ32(rnv)); |
675 | 699 | } |
676 | 700 | } |
677 | 701 | } |
678 | 702 | else |
679 | 703 | { |
680 | 704 | /* Store */ |
681 | | cpustate->icount -= 2 * N_CYCLE; |
| 705 | m_icount -= 2 * N_CYCLE; |
682 | 706 | if (insn & INSN_SDT_B) |
683 | 707 | { |
684 | 708 | if (ARM_DEBUG_CORE && rd==eR15) |
685 | 709 | logerror("Wrote R15 in byte mode\n"); |
686 | 710 | |
687 | | WRITE8(rnv, (UINT8) GetRegister(cpustate, rd) & 0xffu); |
| 711 | WRITE8(rnv, (UINT8) GetRegister(rd) & 0xffu); |
688 | 712 | } |
689 | 713 | else |
690 | 714 | { |
691 | 715 | if (ARM_DEBUG_CORE && rd==eR15) |
692 | 716 | logerror("Wrote R15 in 32bit mode\n"); |
693 | 717 | |
694 | | WRITE32(rnv, rd == eR15 ? R15 + 8 : GetRegister(cpustate, rd)); |
| 718 | WRITE32(rnv, rd == eR15 ? R15 + 8 : GetRegister(rd)); |
695 | 719 | } |
696 | 720 | } |
697 | 721 | |
r23977 | r23978 | |
703 | 727 | /* Writeback is applied in pipeline, before value is read from mem, |
704 | 728 | so writeback is effectively ignored */ |
705 | 729 | if (rd==rn) { |
706 | | SetRegister(cpustate, rn,GetRegister(cpustate, rd)); |
| 730 | SetRegister(rn,GetRegister(rd)); |
707 | 731 | } |
708 | 732 | else { |
709 | 733 | if ((insn&INSN_SDT_W)!=0) |
710 | 734 | logerror("%08x: RegisterWritebackIncrement %d %d %d\n",R15,(insn & INSN_SDT_P)!=0,(insn&INSN_SDT_W)!=0,(insn & INSN_SDT_U)!=0); |
711 | 735 | |
712 | | SetRegister(cpustate, rn,(rnv + off)); |
| 736 | SetRegister(rn,(rnv + off)); |
713 | 737 | } |
714 | 738 | } |
715 | 739 | else |
r23977 | r23978 | |
717 | 741 | /* Writeback is applied in pipeline, before value is read from mem, |
718 | 742 | so writeback is effectively ignored */ |
719 | 743 | if (rd==rn) { |
720 | | SetRegister(cpustate, rn,GetRegister(cpustate, rd)); |
| 744 | SetRegister(rn,GetRegister(rd)); |
721 | 745 | } |
722 | 746 | else { |
723 | | SetRegister(cpustate, rn,(rnv - off)); |
| 747 | SetRegister(rn,(rnv - off)); |
724 | 748 | |
725 | 749 | if ((insn&INSN_SDT_W)!=0) |
726 | 750 | logerror("%08x: RegisterWritebackDecrement %d %d %d\n",R15,(insn & INSN_SDT_P)!=0,(insn&INSN_SDT_W)!=0,(insn & INSN_SDT_U)!=0); |
r23977 | r23978 | |
768 | 792 | | (((sc) != 0) << C_BIT)) + 4; \ |
769 | 793 | else R15 += 4; |
770 | 794 | |
771 | | static void HandleALU( ARM_REGS* cpustate, UINT32 insn ) |
| 795 | void arm_cpu_device::HandleALU( UINT32 insn ) |
772 | 796 | { |
773 | 797 | UINT32 op2, sc=0, rd, rn, opcode; |
774 | 798 | UINT32 by, rdn; |
775 | 799 | |
776 | 800 | opcode = (insn & INSN_OPCODE) >> INSN_OPCODE_SHIFT; |
777 | | cpustate->icount -= S_CYCLE; |
| 801 | m_icount -= S_CYCLE; |
778 | 802 | |
779 | 803 | rd = 0; |
780 | 804 | rn = 0; |
r23977 | r23978 | |
797 | 821 | } |
798 | 822 | else |
799 | 823 | { |
800 | | op2 = decodeShift(cpustate, insn, (insn & INSN_S) ? &sc : NULL); |
| 824 | op2 = decodeShift(insn, (insn & INSN_S) ? &sc : NULL); |
801 | 825 | |
802 | 826 | if (!(insn & INSN_S)) |
803 | 827 | sc=0; |
r23977 | r23978 | |
817 | 841 | } |
818 | 842 | else |
819 | 843 | { |
820 | | rn = GetRegister(cpustate, rn); |
| 844 | rn = GetRegister(rn); |
821 | 845 | } |
822 | 846 | } |
823 | 847 | |
r23977 | r23978 | |
888 | 912 | { |
889 | 913 | /* Merge the old NZCV flags into the new PC value */ |
890 | 914 | R15 = (rd & ADDRESS_MASK) | (R15 & PSR_MASK) | (R15 & IRQ_MASK) | (R15&MODE_MASK); |
891 | | cpustate->icount -= S_CYCLE + N_CYCLE; |
| 915 | m_icount -= S_CYCLE + N_CYCLE; |
892 | 916 | } |
893 | 917 | else |
894 | 918 | { |
r23977 | r23978 | |
897 | 921 | /* S Flag is set - update PSR & mode if in non-user mode only */ |
898 | 922 | if ((R15&MODE_MASK)!=0) |
899 | 923 | { |
900 | | SetRegister(cpustate,rdn,rd); |
| 924 | SetRegister(rdn,rd); |
901 | 925 | } |
902 | 926 | else |
903 | 927 | { |
904 | | SetRegister(cpustate, rdn,(rd&ADDRESS_MASK) | (rd&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK)); |
| 928 | SetRegister(rdn,(rd&ADDRESS_MASK) | (rd&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK)); |
905 | 929 | } |
906 | | cpustate->icount -= S_CYCLE + N_CYCLE; |
| 930 | m_icount -= S_CYCLE + N_CYCLE; |
907 | 931 | } |
908 | 932 | else |
909 | 933 | { |
910 | | SetRegister(cpustate,rdn,rd); |
| 934 | SetRegister(rdn,rd); |
911 | 935 | } |
912 | 936 | } |
913 | 937 | /* TST & TEQ can affect R15 (the condition code register) with the S bit set */ |
r23977 | r23978 | |
920 | 944 | // combine the flags from rd with the address from R15 |
921 | 945 | rd &= ~ADDRESS_MASK; |
922 | 946 | rd |= (R15 & ADDRESS_MASK); |
923 | | SetRegister(cpustate,rdn,rd); |
| 947 | SetRegister(rdn,rd); |
924 | 948 | } |
925 | 949 | else |
926 | 950 | { |
927 | 951 | // combine the flags from rd with the address from R15 |
928 | 952 | rd &= ~ADDRESS_MASK; // clear address part of RD |
929 | 953 | rd |= (R15 & ADDRESS_MASK); // RD = address part of R15 |
930 | | SetRegister(cpustate, rdn,(rd&ADDRESS_MASK) | (rd&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK)); |
| 954 | SetRegister(rdn,(rd&ADDRESS_MASK) | (rd&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK)); |
931 | 955 | } |
932 | | cpustate->icount -= S_CYCLE + N_CYCLE; |
| 956 | m_icount -= S_CYCLE + N_CYCLE; |
933 | 957 | } |
934 | 958 | } |
935 | 959 | |
936 | | static void HandleMul( ARM_REGS* cpustate, UINT32 insn) |
| 960 | void arm_cpu_device::HandleMul( UINT32 insn) |
937 | 961 | { |
938 | 962 | UINT32 r; |
939 | 963 | |
940 | | cpustate->icount -= S_CYCLE + I_CYCLE; |
| 964 | m_icount -= S_CYCLE + I_CYCLE; |
941 | 965 | /* should be: |
942 | 966 | Range of Rs Number of cycles |
943 | 967 | |
r23977 | r23978 | |
960 | 984 | */ |
961 | 985 | |
962 | 986 | /* Do the basic multiply of Rm and Rs */ |
963 | | r = GetRegister( cpustate, insn&INSN_MUL_RM ) * |
964 | | GetRegister( cpustate, (insn&INSN_MUL_RS)>>INSN_MUL_RS_SHIFT ); |
| 987 | r = GetRegister( insn&INSN_MUL_RM ) * |
| 988 | GetRegister( (insn&INSN_MUL_RS)>>INSN_MUL_RS_SHIFT ); |
965 | 989 | |
966 | 990 | if (ARM_DEBUG_CORE && ((insn&INSN_MUL_RM)==0xf |
967 | 991 | || ((insn&INSN_MUL_RS)>>INSN_MUL_RS_SHIFT )==0xf |
r23977 | r23978 | |
972 | 996 | /* Add on Rn if this is a MLA */ |
973 | 997 | if (insn & INSN_MUL_A) |
974 | 998 | { |
975 | | r += GetRegister(cpustate, (insn&INSN_MUL_RN)>>INSN_MUL_RN_SHIFT); |
| 999 | r += GetRegister((insn&INSN_MUL_RN)>>INSN_MUL_RN_SHIFT); |
976 | 1000 | } |
977 | 1001 | |
978 | 1002 | /* Write the result */ |
979 | | SetRegister(cpustate,(insn&INSN_MUL_RD)>>INSN_MUL_RD_SHIFT,r); |
| 1003 | SetRegister((insn&INSN_MUL_RD)>>INSN_MUL_RD_SHIFT,r); |
980 | 1004 | |
981 | 1005 | /* Set N and Z if asked */ |
982 | 1006 | if( insn & INSN_S ) |
r23977 | r23978 | |
985 | 1009 | } |
986 | 1010 | } |
987 | 1011 | |
988 | | static int loadInc ( ARM_REGS* cpustate, UINT32 pat, UINT32 rbv, UINT32 s) |
| 1012 | |
| 1013 | int arm_cpu_device::loadInc(UINT32 pat, UINT32 rbv, UINT32 s) |
989 | 1014 | { |
990 | 1015 | int i,result; |
991 | 1016 | |
r23977 | r23978 | |
996 | 1021 | { |
997 | 1022 | if (i==15) { |
998 | 1023 | if (s) /* Pull full contents from stack */ |
999 | | SetRegister( cpustate, 15, READ32(rbv+=4) ); |
| 1024 | SetRegister( 15, READ32(rbv+=4) ); |
1000 | 1025 | else /* Pull only address, preserve mode & status flags */ |
1001 | | SetRegister( cpustate, 15, (R15&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK) | ((READ32(rbv+=4))&ADDRESS_MASK) ); |
| 1026 | SetRegister( 15, (R15&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK) | ((READ32(rbv+=4))&ADDRESS_MASK) ); |
1002 | 1027 | } else |
1003 | | SetRegister( cpustate, i, READ32(rbv+=4) ); |
| 1028 | SetRegister( i, READ32(rbv+=4) ); |
1004 | 1029 | |
1005 | 1030 | result++; |
1006 | 1031 | } |
r23977 | r23978 | |
1008 | 1033 | return result; |
1009 | 1034 | } |
1010 | 1035 | |
1011 | | static int loadDec( ARM_REGS* cpustate, UINT32 pat, UINT32 rbv, UINT32 s, UINT32* deferredR15, int* defer) |
| 1036 | |
| 1037 | int arm_cpu_device::loadDec(UINT32 pat, UINT32 rbv, UINT32 s, UINT32* deferredR15, int* defer) |
1012 | 1038 | { |
1013 | 1039 | int i,result; |
1014 | 1040 | |
r23977 | r23978 | |
1025 | 1051 | *deferredR15=(R15&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK) | ((READ32(rbv-=4))&ADDRESS_MASK); |
1026 | 1052 | } |
1027 | 1053 | else |
1028 | | SetRegister( cpustate, i, READ32(rbv -=4) ); |
| 1054 | SetRegister( i, READ32(rbv -=4) ); |
1029 | 1055 | result++; |
1030 | 1056 | } |
1031 | 1057 | } |
1032 | 1058 | return result; |
1033 | 1059 | } |
1034 | 1060 | |
1035 | | static int storeInc( ARM_REGS* cpustate, UINT32 pat, UINT32 rbv) |
| 1061 | |
| 1062 | int arm_cpu_device::storeInc(UINT32 pat, UINT32 rbv) |
1036 | 1063 | { |
1037 | 1064 | int i,result; |
1038 | 1065 | |
r23977 | r23978 | |
1044 | 1071 | if (ARM_DEBUG_CORE && i==15) /* R15 is plus 12 from address of STM */ |
1045 | 1072 | logerror("%08x: StoreInc on R15\n",R15); |
1046 | 1073 | |
1047 | | WRITE32( rbv += 4, GetRegister(cpustate, i) ); |
| 1074 | WRITE32( rbv += 4, GetRegister(i) ); |
1048 | 1075 | result++; |
1049 | 1076 | } |
1050 | 1077 | } |
1051 | 1078 | return result; |
1052 | 1079 | } /* storeInc */ |
1053 | 1080 | |
1054 | | static int storeDec( ARM_REGS* cpustate, UINT32 pat, UINT32 rbv) |
| 1081 | |
| 1082 | int arm_cpu_device::storeDec(UINT32 pat, UINT32 rbv) |
1055 | 1083 | { |
1056 | 1084 | int i,result; |
1057 | 1085 | |
r23977 | r23978 | |
1063 | 1091 | if (ARM_DEBUG_CORE && i==15) /* R15 is plus 12 from address of STM */ |
1064 | 1092 | logerror("%08x: StoreDec on R15\n",R15); |
1065 | 1093 | |
1066 | | WRITE32( rbv -= 4, GetRegister(cpustate, i) ); |
| 1094 | WRITE32( rbv -= 4, GetRegister(i) ); |
1067 | 1095 | result++; |
1068 | 1096 | } |
1069 | 1097 | } |
1070 | 1098 | return result; |
1071 | 1099 | } /* storeDec */ |
1072 | 1100 | |
1073 | | static void HandleMemBlock( ARM_REGS* cpustate, UINT32 insn ) |
| 1101 | |
| 1102 | void arm_cpu_device::HandleMemBlock( UINT32 insn ) |
1074 | 1103 | { |
1075 | 1104 | UINT32 rb = (insn & INSN_RN) >> INSN_RN_SHIFT; |
1076 | | UINT32 rbp = GetRegister(cpustate, rb); |
| 1105 | UINT32 rbp = GetRegister(rb); |
1077 | 1106 | int result; |
1078 | 1107 | |
1079 | 1108 | if (ARM_DEBUG_CORE && insn & INSN_BDT_S) |
r23977 | r23978 | |
1089 | 1118 | /* Incrementing */ |
1090 | 1119 | if (!(insn & INSN_BDT_P)) rbp = rbp + (- 4); |
1091 | 1120 | |
1092 | | result = loadInc( cpustate, insn & 0xffff, rbp, insn&INSN_BDT_S ); |
| 1121 | result = loadInc( insn & 0xffff, rbp, insn&INSN_BDT_S ); |
1093 | 1122 | |
1094 | 1123 | if (insn & 0x8000) { |
1095 | 1124 | R15-=4; |
1096 | | cpustate->icount -= S_CYCLE + N_CYCLE; |
| 1125 | m_icount -= S_CYCLE + N_CYCLE; |
1097 | 1126 | } |
1098 | 1127 | |
1099 | 1128 | if (insn & INSN_BDT_W) |
r23977 | r23978 | |
1113 | 1142 | logerror("%08x: Illegal LDRM writeback to r15\n",R15); |
1114 | 1143 | |
1115 | 1144 | if ((insn&(1<<rb))==0) |
1116 | | SetModeRegister(cpustate, mode, rb, GetModeRegister(cpustate, mode, rb) + result * 4); |
| 1145 | SetModeRegister(mode, rb, GetModeRegister(mode, rb) + result * 4); |
1117 | 1146 | else if (ARM_DEBUG_CORE) |
1118 | 1147 | logerror("%08x: Illegal LDRM writeback to base register (%d)\n",R15, rb); |
1119 | 1148 | } |
r23977 | r23978 | |
1129 | 1158 | rbp = rbp - (- 4); |
1130 | 1159 | } |
1131 | 1160 | |
1132 | | result = loadDec( cpustate, insn&0xffff, rbp, insn&INSN_BDT_S, &deferredR15, &defer ); |
| 1161 | result = loadDec( insn&0xffff, rbp, insn&INSN_BDT_S, &deferredR15, &defer ); |
1133 | 1162 | |
1134 | 1163 | if (insn & INSN_BDT_W) |
1135 | 1164 | { |
1136 | 1165 | if (rb==0xf) |
1137 | 1166 | logerror("%08x: Illegal LDRM writeback to r15\n",R15); |
1138 | | SetRegister(cpustate,rb,GetRegister(cpustate, rb)-result*4); |
| 1167 | SetRegister(rb,GetRegister(rb)-result*4); |
1139 | 1168 | } |
1140 | 1169 | |
1141 | 1170 | // If R15 is pulled from memory we defer setting it until after writeback |
1142 | 1171 | // is performed, else we may writeback to the wrong context (ie, the new |
1143 | 1172 | // context if the mode has changed as a result of the R15 read) |
1144 | 1173 | if (defer) |
1145 | | SetRegister(cpustate, 15, deferredR15); |
| 1174 | SetRegister(15, deferredR15); |
1146 | 1175 | |
1147 | 1176 | if (insn & 0x8000) { |
1148 | | cpustate->icount -= S_CYCLE + N_CYCLE; |
| 1177 | m_icount -= S_CYCLE + N_CYCLE; |
1149 | 1178 | R15-=4; |
1150 | 1179 | } |
1151 | 1180 | } |
1152 | | cpustate->icount -= result * S_CYCLE + N_CYCLE + I_CYCLE; |
| 1181 | m_icount -= result * S_CYCLE + N_CYCLE + I_CYCLE; |
1153 | 1182 | } /* Loading */ |
1154 | 1183 | else |
1155 | 1184 | { |
r23977 | r23978 | |
1175 | 1204 | { |
1176 | 1205 | rbp = rbp + (- 4); |
1177 | 1206 | } |
1178 | | result = storeInc( cpustate, insn&0xffff, rbp ); |
| 1207 | result = storeInc( insn&0xffff, rbp ); |
1179 | 1208 | if( insn & INSN_BDT_W ) |
1180 | 1209 | { |
1181 | | SetRegister(cpustate,rb,GetRegister(cpustate, rb)+result*4); |
| 1210 | SetRegister(rb,GetRegister(rb)+result*4); |
1182 | 1211 | } |
1183 | 1212 | } |
1184 | 1213 | else |
r23977 | r23978 | |
1188 | 1217 | { |
1189 | 1218 | rbp = rbp - (- 4); |
1190 | 1219 | } |
1191 | | result = storeDec( cpustate, insn&0xffff, rbp ); |
| 1220 | result = storeDec( insn&0xffff, rbp ); |
1192 | 1221 | if( insn & INSN_BDT_W ) |
1193 | 1222 | { |
1194 | | SetRegister(cpustate,rb,GetRegister(cpustate, rb)-result*4); |
| 1223 | SetRegister(rb,GetRegister(rb)-result*4); |
1195 | 1224 | } |
1196 | 1225 | } |
1197 | 1226 | if( insn & (1<<eR15) ) |
1198 | 1227 | R15 -= 12; |
1199 | 1228 | |
1200 | | cpustate->icount -= (result - 1) * S_CYCLE + 2 * N_CYCLE; |
| 1229 | m_icount -= (result - 1) * S_CYCLE + 2 * N_CYCLE; |
1201 | 1230 | } |
1202 | 1231 | } /* HandleMemBlock */ |
1203 | 1232 | |
r23977 | r23978 | |
1207 | 1236 | * shifter carry output will manifest itself as @*carry == 0@ for carry clear |
1208 | 1237 | * and @*carry != 0@ for carry set. |
1209 | 1238 | */ |
1210 | | static UINT32 decodeShift( ARM_REGS* cpustate, UINT32 insn, UINT32 *pCarry) |
| 1239 | UINT32 arm_cpu_device::decodeShift(UINT32 insn, UINT32 *pCarry) |
1211 | 1240 | { |
1212 | 1241 | UINT32 k = (insn & INSN_OP2_SHIFT) >> INSN_OP2_SHIFT_SHIFT; |
1213 | | UINT32 rm = GetRegister( cpustate, insn & INSN_OP2_RM ); |
| 1242 | UINT32 rm = GetRegister( insn & INSN_OP2_RM ); |
1214 | 1243 | UINT32 t = (insn & INSN_OP2_SHIFT_TYPE) >> INSN_OP2_SHIFT_TYPE_SHIFT; |
1215 | 1244 | |
1216 | 1245 | if ((insn & INSN_OP2_RM)==0xf) { |
r23977 | r23978 | |
1222 | 1251 | /* All shift types ending in 1 are Rk, not #k */ |
1223 | 1252 | if( t & 1 ) |
1224 | 1253 | { |
1225 | | // logerror("%08x: RegShift %02x %02x\n",R15, k>>1,GetRegister(cpustate, k >> 1)); |
| 1254 | // logerror("%08x: RegShift %02x %02x\n",R15, k>>1,GetRegister(k >> 1)); |
1226 | 1255 | if (ARM_DEBUG_CORE && (insn&0x80)==0x80) |
1227 | 1256 | logerror("%08x: RegShift ERROR (p36)\n",R15); |
1228 | 1257 | |
1229 | 1258 | //see p35 for check on this |
1230 | | k = GetRegister(cpustate, k >> 1)&0x1f; |
1231 | | cpustate->icount -= S_CYCLE; |
| 1259 | k = GetRegister(k >> 1)&0x1f; |
| 1260 | m_icount -= S_CYCLE; |
1232 | 1261 | if( k == 0 ) /* Register shift by 0 is a no-op */ |
1233 | 1262 | { |
1234 | 1263 | // logerror("%08x: NO-OP Regshift\n",R15); |
r23977 | r23978 | |
1299 | 1328 | } /* decodeShift */ |
1300 | 1329 | |
1301 | 1330 | |
1302 | | static UINT32 BCDToDecimal(UINT32 value) |
| 1331 | UINT32 arm_cpu_device::BCDToDecimal(UINT32 value) |
1303 | 1332 | { |
1304 | 1333 | UINT32 accumulator = 0; |
1305 | 1334 | UINT32 multiplier = 1; |
r23977 | r23978 | |
1316 | 1345 | return accumulator; |
1317 | 1346 | } |
1318 | 1347 | |
1319 | | static UINT32 DecimalToBCD(UINT32 value) |
| 1348 | |
| 1349 | UINT32 arm_cpu_device::DecimalToBCD(UINT32 value) |
1320 | 1350 | { |
1321 | 1351 | UINT32 accumulator = 0; |
1322 | 1352 | UINT32 divisor = 10; |
r23977 | r23978 | |
1338 | 1368 | return accumulator; |
1339 | 1369 | } |
1340 | 1370 | |
1341 | | static void HandleCoPro( ARM_REGS* cpustate, UINT32 insn ) |
| 1371 | |
| 1372 | void arm_cpu_device::HandleCoPro( UINT32 insn ) |
1342 | 1373 | { |
1343 | 1374 | UINT32 rn=(insn>>12)&0xf; |
1344 | 1375 | UINT32 crn=(insn>>16)&0xf; |
1345 | 1376 | |
1346 | | cpustate->icount -= S_CYCLE; |
| 1377 | m_icount -= S_CYCLE; |
1347 | 1378 | |
1348 | 1379 | /* MRC - transfer copro register to main register */ |
1349 | 1380 | if( (insn&0x0f100010)==0x0e100010 ) |
1350 | 1381 | { |
1351 | | SetRegister(cpustate, rn, cpustate->coproRegister[crn]); |
| 1382 | SetRegister(rn, m_coproRegister[crn]); |
1352 | 1383 | |
1353 | 1384 | if (ARM_DEBUG_COPRO) |
1354 | | logerror("%08x: Copro read CR%d (%08x) to R%d\n", R15, crn, cpustate->coproRegister[crn], rn); |
| 1385 | logerror("%08x: Copro read CR%d (%08x) to R%d\n", R15, crn, m_coproRegister[crn], rn); |
1355 | 1386 | } |
1356 | 1387 | /* MCR - transfer main register to copro register */ |
1357 | 1388 | else if( (insn&0x0f100010)==0x0e000010 ) |
1358 | 1389 | { |
1359 | | cpustate->coproRegister[crn]=GetRegister(cpustate, rn); |
| 1390 | m_coproRegister[crn]=GetRegister(rn); |
1360 | 1391 | |
1361 | 1392 | /* Data East 156 copro specific - trigger BCD operation */ |
1362 | 1393 | if (crn==2) |
1363 | 1394 | { |
1364 | | if (cpustate->coproRegister[crn]==0) |
| 1395 | if (m_coproRegister[crn]==0) |
1365 | 1396 | { |
1366 | 1397 | /* Unpack BCD */ |
1367 | | int v0=BCDToDecimal(cpustate->coproRegister[0]); |
1368 | | int v1=BCDToDecimal(cpustate->coproRegister[1]); |
| 1398 | int v0=BCDToDecimal(m_coproRegister[0]); |
| 1399 | int v1=BCDToDecimal(m_coproRegister[1]); |
1369 | 1400 | |
1370 | 1401 | /* Repack vcd */ |
1371 | | cpustate->coproRegister[5]=DecimalToBCD(v0+v1); |
| 1402 | m_coproRegister[5]=DecimalToBCD(v0+v1); |
1372 | 1403 | |
1373 | 1404 | if (ARM_DEBUG_COPRO) |
1374 | | logerror("Cmd: Add 0 + 1, result in 5 (%08x + %08x == %08x)\n", v0, v1, cpustate->coproRegister[5]); |
| 1405 | logerror("Cmd: Add 0 + 1, result in 5 (%08x + %08x == %08x)\n", v0, v1, m_coproRegister[5]); |
1375 | 1406 | } |
1376 | | else if (cpustate->coproRegister[crn]==1) |
| 1407 | else if (m_coproRegister[crn]==1) |
1377 | 1408 | { |
1378 | 1409 | /* Unpack BCD */ |
1379 | | int v0=BCDToDecimal(cpustate->coproRegister[0]); |
1380 | | int v1=BCDToDecimal(cpustate->coproRegister[1]); |
| 1410 | int v0=BCDToDecimal(m_coproRegister[0]); |
| 1411 | int v1=BCDToDecimal(m_coproRegister[1]); |
1381 | 1412 | |
1382 | 1413 | /* Repack vcd */ |
1383 | | cpustate->coproRegister[5]=DecimalToBCD(v0*v1); |
| 1414 | m_coproRegister[5]=DecimalToBCD(v0*v1); |
1384 | 1415 | |
1385 | 1416 | if (ARM_DEBUG_COPRO) |
1386 | | logerror("Cmd: Multiply 0 * 1, result in 5 (%08x * %08x == %08x)\n", v0, v1, cpustate->coproRegister[5]); |
| 1417 | logerror("Cmd: Multiply 0 * 1, result in 5 (%08x * %08x == %08x)\n", v0, v1, m_coproRegister[5]); |
1387 | 1418 | } |
1388 | | else if (cpustate->coproRegister[crn]==3) |
| 1419 | else if (m_coproRegister[crn]==3) |
1389 | 1420 | { |
1390 | 1421 | /* Unpack BCD */ |
1391 | | int v0=BCDToDecimal(cpustate->coproRegister[0]); |
1392 | | int v1=BCDToDecimal(cpustate->coproRegister[1]); |
| 1422 | int v0=BCDToDecimal(m_coproRegister[0]); |
| 1423 | int v1=BCDToDecimal(m_coproRegister[1]); |
1393 | 1424 | |
1394 | 1425 | /* Repack vcd */ |
1395 | | cpustate->coproRegister[5]=DecimalToBCD(v0-v1); |
| 1426 | m_coproRegister[5]=DecimalToBCD(v0-v1); |
1396 | 1427 | |
1397 | 1428 | if (ARM_DEBUG_COPRO) |
1398 | | logerror("Cmd: Sub 0 - 1, result in 5 (%08x - %08x == %08x)\n", v0, v1, cpustate->coproRegister[5]); |
| 1429 | logerror("Cmd: Sub 0 - 1, result in 5 (%08x - %08x == %08x)\n", v0, v1, m_coproRegister[5]); |
1399 | 1430 | } |
1400 | 1431 | else |
1401 | 1432 | { |
1402 | | logerror("Unknown bcd copro command %08x\n", cpustate->coproRegister[crn]); |
| 1433 | logerror("Unknown bcd copro command %08x\n", m_coproRegister[crn]); |
1403 | 1434 | } |
1404 | 1435 | } |
1405 | 1436 | |
1406 | 1437 | if (ARM_DEBUG_COPRO) |
1407 | | logerror("%08x: Copro write R%d (%08x) to CR%d\n", R15, rn, GetRegister(cpustate, rn), crn); |
| 1438 | logerror("%08x: Copro write R%d (%08x) to CR%d\n", R15, rn, GetRegister(rn), crn); |
1408 | 1439 | } |
1409 | 1440 | /* CDP - perform copro operation */ |
1410 | 1441 | else if( (insn&0x0f000010)==0x0e000000 ) |
1411 | 1442 | { |
1412 | 1443 | /* Data East 156 copro specific divider - result in reg 3/4 */ |
1413 | | if (cpustate->coproRegister[1]) |
| 1444 | if (m_coproRegister[1]) |
1414 | 1445 | { |
1415 | | cpustate->coproRegister[3]=cpustate->coproRegister[0] / cpustate->coproRegister[1]; |
1416 | | cpustate->coproRegister[4]=cpustate->coproRegister[0] % cpustate->coproRegister[1]; |
| 1446 | m_coproRegister[3]=m_coproRegister[0] / m_coproRegister[1]; |
| 1447 | m_coproRegister[4]=m_coproRegister[0] % m_coproRegister[1]; |
1417 | 1448 | } |
1418 | 1449 | else |
1419 | 1450 | { |
1420 | 1451 | /* Unverified */ |
1421 | | cpustate->coproRegister[3]=0xffffffff; |
1422 | | cpustate->coproRegister[4]=0xffffffff; |
| 1452 | m_coproRegister[3]=0xffffffff; |
| 1453 | m_coproRegister[4]=0xffffffff; |
1423 | 1454 | } |
1424 | 1455 | |
1425 | 1456 | if (ARM_DEBUG_COPRO) |
1426 | | logerror("%08x: Copro cdp (%08x) (3==> %08x, 4==> %08x)\n", R15, insn, cpustate->coproRegister[3], cpustate->coproRegister[4]); |
| 1457 | logerror("%08x: Copro cdp (%08x) (3==> %08x, 4==> %08x)\n", R15, insn, m_coproRegister[3], m_coproRegister[4]); |
1427 | 1458 | } |
1428 | 1459 | else |
1429 | 1460 | { |
r23977 | r23978 | |
1432 | 1463 | } |
1433 | 1464 | |
1434 | 1465 | |
1435 | | /************************************************************************** |
1436 | | * Generic set_info |
1437 | | **************************************************************************/ |
1438 | | |
1439 | | static CPU_SET_INFO( arm ) |
| 1466 | offs_t arm_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) |
1440 | 1467 | { |
1441 | | ARM_REGS *cpustate = get_safe_token(device); |
1442 | | |
1443 | | switch (state) |
1444 | | { |
1445 | | /* --- the following bits of info are set as 64-bit signed integers --- */ |
1446 | | case CPUINFO_INT_INPUT_STATE + ARM_IRQ_LINE: set_irq_line(cpustate, ARM_IRQ_LINE, info->i); break; |
1447 | | case CPUINFO_INT_INPUT_STATE + ARM_FIRQ_LINE: set_irq_line(cpustate, ARM_FIRQ_LINE, info->i); break; |
1448 | | |
1449 | | case CPUINFO_INT_REGISTER + ARM32_R0: cpustate->sArmRegister[ 0]= info->i; break; |
1450 | | case CPUINFO_INT_REGISTER + ARM32_R1: cpustate->sArmRegister[ 1]= info->i; break; |
1451 | | case CPUINFO_INT_REGISTER + ARM32_R2: cpustate->sArmRegister[ 2]= info->i; break; |
1452 | | case CPUINFO_INT_REGISTER + ARM32_R3: cpustate->sArmRegister[ 3]= info->i; break; |
1453 | | case CPUINFO_INT_REGISTER + ARM32_R4: cpustate->sArmRegister[ 4]= info->i; break; |
1454 | | case CPUINFO_INT_REGISTER + ARM32_R5: cpustate->sArmRegister[ 5]= info->i; break; |
1455 | | case CPUINFO_INT_REGISTER + ARM32_R6: cpustate->sArmRegister[ 6]= info->i; break; |
1456 | | case CPUINFO_INT_REGISTER + ARM32_R7: cpustate->sArmRegister[ 7]= info->i; break; |
1457 | | case CPUINFO_INT_REGISTER + ARM32_R8: cpustate->sArmRegister[ 8]= info->i; break; |
1458 | | case CPUINFO_INT_REGISTER + ARM32_R9: cpustate->sArmRegister[ 9]= info->i; break; |
1459 | | case CPUINFO_INT_REGISTER + ARM32_R10: cpustate->sArmRegister[10]= info->i; break; |
1460 | | case CPUINFO_INT_REGISTER + ARM32_R11: cpustate->sArmRegister[11]= info->i; break; |
1461 | | case CPUINFO_INT_REGISTER + ARM32_R12: cpustate->sArmRegister[12]= info->i; break; |
1462 | | case CPUINFO_INT_REGISTER + ARM32_R13: cpustate->sArmRegister[13]= info->i; break; |
1463 | | case CPUINFO_INT_REGISTER + ARM32_R14: cpustate->sArmRegister[14]= info->i; break; |
1464 | | case CPUINFO_INT_REGISTER + ARM32_R15: cpustate->sArmRegister[15]= info->i; break; |
1465 | | case CPUINFO_INT_REGISTER + ARM32_FR8: cpustate->sArmRegister[eR8_FIQ] = info->i; break; |
1466 | | case CPUINFO_INT_REGISTER + ARM32_FR9: cpustate->sArmRegister[eR9_FIQ] = info->i; break; |
1467 | | case CPUINFO_INT_REGISTER + ARM32_FR10: cpustate->sArmRegister[eR10_FIQ] = info->i; break; |
1468 | | case CPUINFO_INT_REGISTER + ARM32_FR11: cpustate->sArmRegister[eR11_FIQ] = info->i; break; |
1469 | | case CPUINFO_INT_REGISTER + ARM32_FR12: cpustate->sArmRegister[eR12_FIQ] = info->i; break; |
1470 | | case CPUINFO_INT_REGISTER + ARM32_FR13: cpustate->sArmRegister[eR13_FIQ] = info->i; break; |
1471 | | case CPUINFO_INT_REGISTER + ARM32_FR14: cpustate->sArmRegister[eR14_FIQ] = info->i; break; |
1472 | | case CPUINFO_INT_REGISTER + ARM32_IR13: cpustate->sArmRegister[eR13_IRQ] = info->i; break; |
1473 | | case CPUINFO_INT_REGISTER + ARM32_IR14: cpustate->sArmRegister[eR14_IRQ] = info->i; break; |
1474 | | case CPUINFO_INT_REGISTER + ARM32_SR13: cpustate->sArmRegister[eR13_SVC] = info->i; break; |
1475 | | case CPUINFO_INT_REGISTER + ARM32_SR14: cpustate->sArmRegister[eR14_SVC] = info->i; break; |
1476 | | |
1477 | | case CPUINFO_INT_PC: |
1478 | | case CPUINFO_INT_REGISTER + ARM32_PC: R15 = (R15&~ADDRESS_MASK)|info->i; break; |
1479 | | case CPUINFO_INT_SP: SetRegister(cpustate,13,info->i); break; |
1480 | | } |
| 1468 | extern CPU_DISASSEMBLE( arm ); |
| 1469 | return CPU_DISASSEMBLE_NAME(arm)(this, buffer, pc, oprom, opram, options); |
1481 | 1470 | } |
1482 | 1471 | |
1483 | 1472 | |
1484 | | |
1485 | | /************************************************************************** |
1486 | | * Generic get_info |
1487 | | **************************************************************************/ |
1488 | | |
1489 | | CPU_GET_INFO( arm ) |
| 1473 | offs_t arm_be_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) |
1490 | 1474 | { |
1491 | | ARM_REGS *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL; |
1492 | | |
1493 | | switch (state) |
1494 | | { |
1495 | | /* --- the following bits of info are returned as 64-bit signed integers --- */ |
1496 | | case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(ARM_REGS); break; |
1497 | | case CPUINFO_INT_INPUT_LINES: info->i = 2; break; |
1498 | | case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; |
1499 | | case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break; |
1500 | | case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; |
1501 | | case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; |
1502 | | case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break; |
1503 | | case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break; |
1504 | | case CPUINFO_INT_MIN_CYCLES: info->i = 3; break; |
1505 | | case CPUINFO_INT_MAX_CYCLES: info->i = 4; break; |
1506 | | |
1507 | | case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break; |
1508 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 26; break; |
1509 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break; |
1510 | | case CPUINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break; |
1511 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break; |
1512 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break; |
1513 | | case CPUINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break; |
1514 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break; |
1515 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break; |
1516 | | |
1517 | | case CPUINFO_INT_INPUT_STATE + ARM_IRQ_LINE: info->i = cpustate->pendingIrq; break; |
1518 | | case CPUINFO_INT_INPUT_STATE + ARM_FIRQ_LINE: info->i = cpustate->pendingFiq; break; |
1519 | | |
1520 | | case CPUINFO_INT_PREVIOUSPC: info->i = 0; /* not implemented */ break; |
1521 | | case CPUINFO_INT_PC: |
1522 | | case CPUINFO_INT_REGISTER + ARM32_PC: info->i = cpustate->sArmRegister[15]&ADDRESS_MASK; break; |
1523 | | case CPUINFO_INT_SP: info->i = GetRegister(cpustate, 13); break; |
1524 | | |
1525 | | case CPUINFO_INT_REGISTER + ARM32_R0: info->i = cpustate->sArmRegister[ 0]; break; |
1526 | | case CPUINFO_INT_REGISTER + ARM32_R1: info->i = cpustate->sArmRegister[ 1]; break; |
1527 | | case CPUINFO_INT_REGISTER + ARM32_R2: info->i = cpustate->sArmRegister[ 2]; break; |
1528 | | case CPUINFO_INT_REGISTER + ARM32_R3: info->i = cpustate->sArmRegister[ 3]; break; |
1529 | | case CPUINFO_INT_REGISTER + ARM32_R4: info->i = cpustate->sArmRegister[ 4]; break; |
1530 | | case CPUINFO_INT_REGISTER + ARM32_R5: info->i = cpustate->sArmRegister[ 5]; break; |
1531 | | case CPUINFO_INT_REGISTER + ARM32_R6: info->i = cpustate->sArmRegister[ 6]; break; |
1532 | | case CPUINFO_INT_REGISTER + ARM32_R7: info->i = cpustate->sArmRegister[ 7]; break; |
1533 | | case CPUINFO_INT_REGISTER + ARM32_R8: info->i = cpustate->sArmRegister[ 8]; break; |
1534 | | case CPUINFO_INT_REGISTER + ARM32_R9: info->i = cpustate->sArmRegister[ 9]; break; |
1535 | | case CPUINFO_INT_REGISTER + ARM32_R10: info->i = cpustate->sArmRegister[10]; break; |
1536 | | case CPUINFO_INT_REGISTER + ARM32_R11: info->i = cpustate->sArmRegister[11]; break; |
1537 | | case CPUINFO_INT_REGISTER + ARM32_R12: info->i = cpustate->sArmRegister[12]; break; |
1538 | | case CPUINFO_INT_REGISTER + ARM32_R13: info->i = cpustate->sArmRegister[13]; break; |
1539 | | case CPUINFO_INT_REGISTER + ARM32_R14: info->i = cpustate->sArmRegister[14]; break; |
1540 | | case CPUINFO_INT_REGISTER + ARM32_R15: info->i = cpustate->sArmRegister[15]; break; |
1541 | | |
1542 | | case CPUINFO_INT_REGISTER + ARM32_FR8: info->i = cpustate->sArmRegister[eR8_FIQ]; break; |
1543 | | case CPUINFO_INT_REGISTER + ARM32_FR9: info->i = cpustate->sArmRegister[eR9_FIQ]; break; |
1544 | | case CPUINFO_INT_REGISTER + ARM32_FR10: info->i = cpustate->sArmRegister[eR10_FIQ]; break; |
1545 | | case CPUINFO_INT_REGISTER + ARM32_FR11: info->i = cpustate->sArmRegister[eR11_FIQ]; break; |
1546 | | case CPUINFO_INT_REGISTER + ARM32_FR12: info->i = cpustate->sArmRegister[eR12_FIQ]; break; |
1547 | | case CPUINFO_INT_REGISTER + ARM32_FR13: info->i = cpustate->sArmRegister[eR13_FIQ]; break; |
1548 | | case CPUINFO_INT_REGISTER + ARM32_FR14: info->i = cpustate->sArmRegister[eR14_FIQ]; break; |
1549 | | case CPUINFO_INT_REGISTER + ARM32_IR13: info->i = cpustate->sArmRegister[eR13_IRQ]; break; |
1550 | | case CPUINFO_INT_REGISTER + ARM32_IR14: info->i = cpustate->sArmRegister[eR14_IRQ]; break; |
1551 | | case CPUINFO_INT_REGISTER + ARM32_SR13: info->i = cpustate->sArmRegister[eR13_SVC]; break; |
1552 | | case CPUINFO_INT_REGISTER + ARM32_SR14: info->i = cpustate->sArmRegister[eR14_SVC]; break; |
1553 | | |
1554 | | /* --- the following bits of info are returned as pointers to data or functions --- */ |
1555 | | case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(arm); break; |
1556 | | case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(arm); break; |
1557 | | case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(arm); break; |
1558 | | case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(arm); break; |
1559 | | case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(arm); break; |
1560 | | case CPUINFO_FCT_BURN: info->burn = NULL; break; |
1561 | | case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(arm); break; |
1562 | | case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break; |
1563 | | |
1564 | | /* --- the following bits of info are returned as NULL-terminated strings --- */ |
1565 | | case CPUINFO_STR_NAME: strcpy(info->s, "ARM"); break; |
1566 | | case CPUINFO_STR_FAMILY: strcpy(info->s, "Acorn Risc Machine"); break; |
1567 | | case CPUINFO_STR_VERSION: strcpy(info->s, "1.3"); break; |
1568 | | case CPUINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; |
1569 | | case CPUINFO_STR_CREDITS: strcpy(info->s, "Copyright Bryan McPhail, bmcphail@tendril.co.uk"); break; |
1570 | | |
1571 | | case CPUINFO_STR_FLAGS: |
1572 | | sprintf(info->s, "%c%c%c%c%c%c", |
1573 | | (cpustate->sArmRegister[15] & N_MASK) ? 'N' : '-', |
1574 | | (cpustate->sArmRegister[15] & Z_MASK) ? 'Z' : '-', |
1575 | | (cpustate->sArmRegister[15] & C_MASK) ? 'C' : '-', |
1576 | | (cpustate->sArmRegister[15] & V_MASK) ? 'V' : '-', |
1577 | | (cpustate->sArmRegister[15] & I_MASK) ? 'I' : '-', |
1578 | | (cpustate->sArmRegister[15] & F_MASK) ? 'F' : '-'); |
1579 | | switch (cpustate->sArmRegister[15] & 3) |
1580 | | { |
1581 | | case 0: |
1582 | | strcat(info->s, " USER"); |
1583 | | break; |
1584 | | case 1: |
1585 | | strcat(info->s, " FIRQ"); |
1586 | | break; |
1587 | | case 2: |
1588 | | strcat(info->s, " IRQ "); |
1589 | | break; |
1590 | | default: |
1591 | | strcat(info->s, " SVC "); |
1592 | | break; |
1593 | | } |
1594 | | break; |
1595 | | |
1596 | | case CPUINFO_STR_REGISTER + ARM32_PC: sprintf( info->s, "PC :%08x", cpustate->sArmRegister[15]&ADDRESS_MASK ); break; |
1597 | | case CPUINFO_STR_REGISTER + ARM32_R0: sprintf( info->s, "R0 :%08x", cpustate->sArmRegister[ 0] ); break; |
1598 | | case CPUINFO_STR_REGISTER + ARM32_R1: sprintf( info->s, "R1 :%08x", cpustate->sArmRegister[ 1] ); break; |
1599 | | case CPUINFO_STR_REGISTER + ARM32_R2: sprintf( info->s, "R2 :%08x", cpustate->sArmRegister[ 2] ); break; |
1600 | | case CPUINFO_STR_REGISTER + ARM32_R3: sprintf( info->s, "R3 :%08x", cpustate->sArmRegister[ 3] ); break; |
1601 | | case CPUINFO_STR_REGISTER + ARM32_R4: sprintf( info->s, "R4 :%08x", cpustate->sArmRegister[ 4] ); break; |
1602 | | case CPUINFO_STR_REGISTER + ARM32_R5: sprintf( info->s, "R5 :%08x", cpustate->sArmRegister[ 5] ); break; |
1603 | | case CPUINFO_STR_REGISTER + ARM32_R6: sprintf( info->s, "R6 :%08x", cpustate->sArmRegister[ 6] ); break; |
1604 | | case CPUINFO_STR_REGISTER + ARM32_R7: sprintf( info->s, "R7 :%08x", cpustate->sArmRegister[ 7] ); break; |
1605 | | case CPUINFO_STR_REGISTER + ARM32_R8: sprintf( info->s, "R8 :%08x", cpustate->sArmRegister[ 8] ); break; |
1606 | | case CPUINFO_STR_REGISTER + ARM32_R9: sprintf( info->s, "R9 :%08x", cpustate->sArmRegister[ 9] ); break; |
1607 | | case CPUINFO_STR_REGISTER + ARM32_R10: sprintf( info->s, "R10 :%08x", cpustate->sArmRegister[10] ); break; |
1608 | | case CPUINFO_STR_REGISTER + ARM32_R11: sprintf( info->s, "R11 :%08x", cpustate->sArmRegister[11] ); break; |
1609 | | case CPUINFO_STR_REGISTER + ARM32_R12: sprintf( info->s, "R12 :%08x", cpustate->sArmRegister[12] ); break; |
1610 | | case CPUINFO_STR_REGISTER + ARM32_R13: sprintf( info->s, "R13 :%08x", cpustate->sArmRegister[13] ); break; |
1611 | | case CPUINFO_STR_REGISTER + ARM32_R14: sprintf( info->s, "R14 :%08x", cpustate->sArmRegister[14] ); break; |
1612 | | case CPUINFO_STR_REGISTER + ARM32_R15: sprintf( info->s, "R15 :%08x", cpustate->sArmRegister[15] ); break; |
1613 | | case CPUINFO_STR_REGISTER + ARM32_FR8: sprintf( info->s, "FR8 :%08x", cpustate->sArmRegister[eR8_FIQ] ); break; |
1614 | | case CPUINFO_STR_REGISTER + ARM32_FR9: sprintf( info->s, "FR9 :%08x", cpustate->sArmRegister[eR9_FIQ] ); break; |
1615 | | case CPUINFO_STR_REGISTER + ARM32_FR10: sprintf( info->s, "FR10:%08x", cpustate->sArmRegister[eR10_FIQ] ); break; |
1616 | | case CPUINFO_STR_REGISTER + ARM32_FR11: sprintf( info->s, "FR11:%08x", cpustate->sArmRegister[eR11_FIQ]); break; |
1617 | | case CPUINFO_STR_REGISTER + ARM32_FR12: sprintf( info->s, "FR12:%08x", cpustate->sArmRegister[eR12_FIQ] ); break; |
1618 | | case CPUINFO_STR_REGISTER + ARM32_FR13: sprintf( info->s, "FR13:%08x", cpustate->sArmRegister[eR13_FIQ] ); break; |
1619 | | case CPUINFO_STR_REGISTER + ARM32_FR14: sprintf( info->s, "FR14:%08x", cpustate->sArmRegister[eR14_FIQ] ); break; |
1620 | | case CPUINFO_STR_REGISTER + ARM32_IR13: sprintf( info->s, "IR13:%08x", cpustate->sArmRegister[eR13_IRQ] ); break; |
1621 | | case CPUINFO_STR_REGISTER + ARM32_IR14: sprintf( info->s, "IR14:%08x", cpustate->sArmRegister[eR14_IRQ] ); break; |
1622 | | case CPUINFO_STR_REGISTER + ARM32_SR13: sprintf( info->s, "SR13:%08x", cpustate->sArmRegister[eR13_SVC] ); break; |
1623 | | case CPUINFO_STR_REGISTER + ARM32_SR14: sprintf( info->s, "SR14:%08x", cpustate->sArmRegister[eR14_SVC] ); break; |
1624 | | } |
| 1475 | extern CPU_DISASSEMBLE( arm_be ); |
| 1476 | return CPU_DISASSEMBLE_NAME(arm_be)(this, buffer, pc, oprom, opram, options); |
1625 | 1477 | } |
1626 | 1478 | |
1627 | | |
1628 | | CPU_GET_INFO( arm_be ) |
1629 | | { |
1630 | | switch (state) |
1631 | | { |
1632 | | /* --- the following bits of info are returned as 64-bit signed integers --- */ |
1633 | | case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break; |
1634 | | |
1635 | | /* --- the following bits of info are returned as pointers to data or functions --- */ |
1636 | | case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(arm_be); break; |
1637 | | case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(arm_be); break; |
1638 | | |
1639 | | /* --- the following bits of info are returned as NULL-terminated strings --- */ |
1640 | | case CPUINFO_STR_NAME: strcpy(info->s, "ARM (big endian)"); break; |
1641 | | |
1642 | | default: CPU_GET_INFO_CALL(arm); break; |
1643 | | } |
1644 | | } |
1645 | | |
1646 | | |
1647 | | DEFINE_LEGACY_CPU_DEVICE(ARM, arm); |
1648 | | DEFINE_LEGACY_CPU_DEVICE(ARM_BE, arm_be); |