src/emu/cpu/arm/arm.c
| r8617 | r8618 | |
| 20 | 20 | #include "arm.h" |
| 21 | 21 | |
| 22 | 22 | CPU_DISASSEMBLE( arm ); |
| 23 | CPU_DISASSEMBLE( arm_be ); |
| 23 | 24 | |
| 24 | 25 | #define READ8(addr) cpu_read8(cpustate,addr) |
| 25 | 26 | #define WRITE8(addr,data) cpu_write8(cpustate,addr,data) |
| r8617 | r8618 | |
| 254 | 255 | INLINE ARM_REGS *get_safe_token(running_device *device) |
| 255 | 256 | { |
| 256 | 257 | assert(device != NULL); |
| 257 | | assert(device->type() == ARM); |
| 258 | assert(device->type() == ARM || device->type() == ARM_BE); |
| 258 | 259 | return (ARM_REGS *)downcast<legacy_cpu_device *>(device)->token(); |
| 259 | 260 | } |
| 260 | 261 | |
| 261 | 262 | INLINE void cpu_write32( ARM_REGS* cpustate, int addr, UINT32 data ) |
| 262 | 263 | { |
| 263 | 264 | /* Unaligned writes are treated as normal writes */ |
| 264 | | memory_write_dword_32le(cpustate->program, addr&ADDRESS_MASK,data); |
| 265 | if ( cpustate->endian == ENDIANNESS_BIG ) |
| 266 | memory_write_dword_32be(cpustate->program, addr&ADDRESS_MASK,data); |
| 267 | else |
| 268 | memory_write_dword_32le(cpustate->program, addr&ADDRESS_MASK,data); |
| 265 | 269 | if (ARM_DEBUG_CORE && addr&3) logerror("%08x: Unaligned write %08x\n",R15,addr); |
| 266 | 270 | } |
| 267 | 271 | |
| 268 | 272 | INLINE void cpu_write8( ARM_REGS* cpustate, int addr, UINT8 data ) |
| 269 | 273 | { |
| 270 | | memory_write_byte_32le(cpustate->program,addr,data); |
| 274 | if ( cpustate->endian == ENDIANNESS_BIG ) |
| 275 | memory_write_byte_32be(cpustate->program,addr,data); |
| 276 | else |
| 277 | memory_write_byte_32le(cpustate->program,addr,data); |
| 271 | 278 | } |
| 272 | 279 | |
| 273 | 280 | INLINE UINT32 cpu_read32( ARM_REGS* cpustate, int addr ) |
| 274 | 281 | { |
| 275 | | UINT32 result = memory_read_dword_32le(cpustate->program,addr&ADDRESS_MASK); |
| 282 | UINT32 result; |
| 276 | 283 | |
| 284 | if ( cpustate->endian == ENDIANNESS_BIG ) |
| 285 | result = memory_read_dword_32be(cpustate->program,addr&ADDRESS_MASK); |
| 286 | else |
| 287 | result = memory_read_dword_32le(cpustate->program,addr&ADDRESS_MASK); |
| 288 | |
| 277 | 289 | /* Unaligned reads rotate the word, they never combine words */ |
| 278 | 290 | if (addr&3) { |
| 279 | 291 | if (ARM_DEBUG_CORE && addr&1) |
| r8617 | r8618 | |
| 292 | 304 | |
| 293 | 305 | INLINE UINT8 cpu_read8( ARM_REGS* cpustate, int addr ) |
| 294 | 306 | { |
| 295 | | return memory_read_byte_32le(cpustate->program, addr); |
| 307 | if ( cpustate->endian == ENDIANNESS_BIG ) |
| 308 | return memory_read_byte_32be(cpustate->program, addr); |
| 309 | else |
| 310 | return memory_read_byte_32le(cpustate->program, addr); |
| 296 | 311 | } |
| 297 | 312 | |
| 298 | 313 | INLINE UINT32 GetRegister( ARM_REGS* cpustate, int rIndex ) |
| r8617 | r8618 | |
| 312 | 327 | ARM_REGS *cpustate = get_safe_token(device); |
| 313 | 328 | |
| 314 | 329 | device_irq_callback save_irqcallback = cpustate->irq_callback; |
| 330 | endianness_t save_endian = cpustate->endian; |
| 331 | |
| 315 | 332 | memset(cpustate, 0, sizeof(ARM_REGS)); |
| 316 | 333 | cpustate->irq_callback = save_irqcallback; |
| 334 | cpustate->endian = save_endian; |
| 317 | 335 | cpustate->device = device; |
| 318 | 336 | cpustate->program = device->space(AS_PROGRAM); |
| 319 | 337 | |
| r8617 | r8618 | |
| 507 | 525 | state_save_register_device_item(device, 0, cpustate->endian); |
| 508 | 526 | } |
| 509 | 527 | |
| 528 | |
| 529 | static CPU_INIT( arm_be ) |
| 530 | { |
| 531 | ARM_REGS *cpustate = get_safe_token(device); |
| 532 | |
| 533 | cpustate->irq_callback = irqcallback; |
| 534 | cpustate->device = device; |
| 535 | cpustate->program = device->space(AS_PROGRAM); |
| 536 | cpustate->endian = ENDIANNESS_BIG; |
| 537 | |
| 538 | state_save_register_device_item_array(device, 0, cpustate->sArmRegister); |
| 539 | state_save_register_device_item_array(device, 0, cpustate->coproRegister); |
| 540 | state_save_register_device_item(device, 0, cpustate->pendingIrq); |
| 541 | state_save_register_device_item(device, 0, cpustate->pendingFiq); |
| 542 | state_save_register_device_item(device, 0, cpustate->endian); |
| 543 | } |
| 544 | |
| 545 | |
| 510 | 546 | /***************************************************************************/ |
| 511 | 547 | |
| 512 | 548 | static void HandleBranch( ARM_REGS* cpustate, UINT32 insn ) |
| r8617 | r8618 | |
| 596 | 632 | { |
| 597 | 633 | if (ARM_DEBUG_CORE && rd == eR15) |
| 598 | 634 | logerror("read byte R15 %08x\n", R15); |
| 599 | | SetRegister(cpustate, rd,(UINT32) READ8( ( cpustate->endian == ENDIANNESS_LITTLE ? rnv : (rnv ^ 0x03) ) ) ); |
| 635 | SetRegister(cpustate, rd,(UINT32) READ8(rnv) ); |
| 600 | 636 | } |
| 601 | 637 | else |
| 602 | 638 | { |
| r8617 | r8618 | |
| 619 | 655 | } |
| 620 | 656 | else |
| 621 | 657 | { |
| 622 | | UINT32 data = READ32(rnv); |
| 623 | | |
| 624 | | if ( cpustate->endian == ENDIANNESS_BIG ) |
| 625 | | { |
| 626 | | if ( rnv & 0x02 ) |
| 627 | | data = ( data >> 16 ) | ( data << 16 ); |
| 628 | | if ( rnv & 0x01 ) |
| 629 | | data = ( data >> 24 ) | ( data << 8 ); |
| 630 | | } |
| 631 | | SetRegister(cpustate, rd, data); |
| 658 | SetRegister(cpustate, rd, READ32(rnv)); |
| 632 | 659 | } |
| 633 | 660 | } |
| 634 | 661 | } |
| r8617 | r8618 | |
| 641 | 668 | if (ARM_DEBUG_CORE && rd==eR15) |
| 642 | 669 | logerror("Wrote R15 in byte mode\n"); |
| 643 | 670 | |
| 644 | | WRITE8( ( cpustate->endian == ENDIANNESS_LITTLE ? rnv : (rnv ^ 0x03) ), (UINT8) GetRegister(cpustate, rd) & 0xffu); |
| 671 | WRITE8(rnv, (UINT8) GetRegister(cpustate, rd) & 0xffu); |
| 645 | 672 | } |
| 646 | 673 | else |
| 647 | 674 | { |
| r8617 | r8618 | |
| 1388 | 1415 | } |
| 1389 | 1416 | |
| 1390 | 1417 | |
| 1391 | | void arm_set_endianness( legacy_cpu_device *device, endianness_t endianness ) |
| 1392 | | { |
| 1393 | | ARM_REGS *cpustate = get_safe_token(device); |
| 1394 | | |
| 1395 | | cpustate->endian = endianness; |
| 1396 | | } |
| 1397 | | |
| 1398 | 1418 | /************************************************************************** |
| 1399 | 1419 | * Generic set_info |
| 1400 | 1420 | **************************************************************************/ |
| r8617 | r8618 | |
| 1587 | 1607 | } |
| 1588 | 1608 | } |
| 1589 | 1609 | |
| 1610 | |
| 1611 | CPU_GET_INFO( arm_be ) |
| 1612 | { |
| 1613 | switch (state) |
| 1614 | { |
| 1615 | /* --- the following bits of info are returned as 64-bit signed integers --- */ |
| 1616 | case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break; |
| 1617 | |
| 1618 | /* --- the following bits of info are returned as pointers to data or functions --- */ |
| 1619 | case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(arm_be); break; |
| 1620 | case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(arm_be); break; |
| 1621 | |
| 1622 | /* --- the following bits of info are returned as NULL-terminated strings --- */ |
| 1623 | case DEVINFO_STR_NAME: strcpy(info->s, "ARM (big endian)"); break; |
| 1624 | |
| 1625 | default: CPU_GET_INFO_CALL(arm); break; |
| 1626 | } |
| 1627 | } |
| 1628 | |
| 1629 | |
| 1590 | 1630 | DEFINE_LEGACY_CPU_DEVICE(ARM, arm); |
| 1631 | DEFINE_LEGACY_CPU_DEVICE(ARM_BE, arm_be); |
| 1632 | |