trunk/src/emu/cpu/arm/arm.c
| r24002 | r24003 | |
| 22 | 22 | CPU_DISASSEMBLE( arm ); |
| 23 | 23 | CPU_DISASSEMBLE( arm_be ); |
| 24 | 24 | |
| 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 | | |
| 30 | 25 | #define ARM_DEBUG_CORE 0 |
| 31 | 26 | #define ARM_DEBUG_COPRO 0 |
| 32 | 27 | |
| r24002 | r24003 | |
| 256 | 251 | void arm_cpu_device::cpu_write32( int addr, UINT32 data ) |
| 257 | 252 | { |
| 258 | 253 | /* Unaligned writes are treated as normal writes */ |
| 259 | | if ( m_endian == ENDIANNESS_BIG ) |
| 260 | | m_program->write_dword(addr&ADDRESS_MASK,data); |
| 261 | | else |
| 262 | | m_program->write_dword(addr&ADDRESS_MASK,data); |
| 254 | m_program->write_dword(addr&ADDRESS_MASK,data); |
| 263 | 255 | if (ARM_DEBUG_CORE && addr&3) logerror("%08x: Unaligned write %08x\n",R15,addr); |
| 264 | 256 | } |
| 265 | 257 | |
| 266 | 258 | void arm_cpu_device::cpu_write8( int addr, UINT8 data ) |
| 267 | 259 | { |
| 268 | | if ( m_endian == ENDIANNESS_BIG ) |
| 269 | | m_program->write_byte(addr,data); |
| 270 | | else |
| 271 | | m_program->write_byte(addr,data); |
| 260 | m_program->write_byte(addr,data); |
| 272 | 261 | } |
| 273 | 262 | |
| 274 | 263 | UINT32 arm_cpu_device::cpu_read32( int addr ) |
| 275 | 264 | { |
| 276 | | UINT32 result; |
| 265 | UINT32 result = m_program->read_dword(addr&ADDRESS_MASK); |
| 277 | 266 | |
| 278 | | if ( m_endian == ENDIANNESS_BIG ) |
| 279 | | result = m_program->read_dword(addr&ADDRESS_MASK); |
| 280 | | else |
| 281 | | result = m_program->read_dword(addr&ADDRESS_MASK); |
| 282 | | |
| 283 | 267 | /* Unaligned reads rotate the word, they never combine words */ |
| 284 | | if (addr&3) { |
| 268 | if (addr&3) |
| 269 | { |
| 285 | 270 | if (ARM_DEBUG_CORE && addr&1) |
| 286 | 271 | logerror("%08x: Unaligned byte read %08x\n",R15,addr); |
| 287 | 272 | |
| r24002 | r24003 | |
| 298 | 283 | |
| 299 | 284 | UINT8 arm_cpu_device::cpu_read8( int addr ) |
| 300 | 285 | { |
| 301 | | if ( m_endian == ENDIANNESS_BIG ) |
| 302 | | return m_program->read_byte(addr); |
| 303 | | else |
| 304 | | return m_program->read_byte(addr); |
| 286 | return m_program->read_byte(addr); |
| 305 | 287 | } |
| 306 | 288 | |
| 307 | 289 | UINT32 arm_cpu_device::GetRegister( int rIndex ) |
| r24002 | r24003 | |
| 470 | 452 | Undefined instruction |
| 471 | 453 | */ |
| 472 | 454 | |
| 473 | | if (m_pendingFiq && (pc&F_MASK)==0) { |
| 455 | if (m_pendingFiq && (pc&F_MASK)==0) |
| 456 | { |
| 474 | 457 | R15 = eARM_MODE_FIQ; /* Set FIQ mode so PC is saved to correct R14 bank */ |
| 475 | 458 | SetRegister( 14, pc ); /* save PC */ |
| 476 | 459 | R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|0x1c|eARM_MODE_FIQ|I_MASK|F_MASK; /* Mask both IRQ & FIRQ, set PC=0x1c */ |
| r24002 | r24003 | |
| 478 | 461 | return; |
| 479 | 462 | } |
| 480 | 463 | |
| 481 | | if (m_pendingIrq && (pc&I_MASK)==0) { |
| 464 | if (m_pendingIrq && (pc&I_MASK)==0) |
| 465 | { |
| 482 | 466 | R15 = eARM_MODE_IRQ; /* Set IRQ mode so PC is saved to correct R14 bank */ |
| 483 | 467 | SetRegister( 14, pc ); /* save PC */ |
| 484 | 468 | R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|0x18|eARM_MODE_IRQ|I_MASK|(pc&F_MASK); /* Mask only IRQ, set PC=0x18 */ |
| r24002 | r24003 | |
| 490 | 474 | |
| 491 | 475 | void arm_cpu_device::execute_set_input(int irqline, int state) |
| 492 | 476 | { |
| 493 | | switch (irqline) { |
| 477 | switch (irqline) |
| 478 | { |
| 494 | 479 | case ARM_IRQ_LINE: /* IRQ */ |
| 495 | 480 | if (state && (R15&0x3)!=eARM_MODE_IRQ) /* Don't allow nested IRQs */ |
| 496 | 481 | m_pendingIrq=1; |
| r24002 | r24003 | |
| 672 | 657 | { |
| 673 | 658 | if (ARM_DEBUG_CORE && rd == eR15) |
| 674 | 659 | logerror("read byte R15 %08x\n", R15); |
| 675 | | SetRegister(rd,(UINT32) READ8(rnv) ); |
| 660 | SetRegister(rd,(UINT32) cpu_read8(rnv) ); |
| 676 | 661 | } |
| 677 | 662 | else |
| 678 | 663 | { |
| 679 | 664 | if (rd == eR15) |
| 680 | 665 | { |
| 681 | | R15 = (READ32(rnv) & ADDRESS_MASK) | (R15 & PSR_MASK) | (R15 & MODE_MASK); |
| 666 | R15 = (cpu_read32(rnv) & ADDRESS_MASK) | (R15 & PSR_MASK) | (R15 & MODE_MASK); |
| 682 | 667 | |
| 683 | 668 | /* |
| 684 | 669 | The docs are explicit in that the bottom bits should be masked off |
| r24002 | r24003 | |
| 688 | 673 | |
| 689 | 674 | In other cases, 4 is subracted from R15 here to account for pipelining. |
| 690 | 675 | */ |
| 691 | | if ((READ32(rnv)&3)==0) |
| 676 | if ((cpu_read32(rnv)&3)==0) |
| 692 | 677 | R15 -= 4; |
| 693 | 678 | |
| 694 | 679 | m_icount -= S_CYCLE + N_CYCLE; |
| 695 | 680 | } |
| 696 | 681 | else |
| 697 | 682 | { |
| 698 | | SetRegister(rd, READ32(rnv)); |
| 683 | SetRegister(rd, cpu_read32(rnv)); |
| 699 | 684 | } |
| 700 | 685 | } |
| 701 | 686 | } |
| r24002 | r24003 | |
| 708 | 693 | if (ARM_DEBUG_CORE && rd==eR15) |
| 709 | 694 | logerror("Wrote R15 in byte mode\n"); |
| 710 | 695 | |
| 711 | | WRITE8(rnv, (UINT8) GetRegister(rd) & 0xffu); |
| 696 | cpu_write8(rnv, (UINT8) GetRegister(rd) & 0xffu); |
| 712 | 697 | } |
| 713 | 698 | else |
| 714 | 699 | { |
| 715 | 700 | if (ARM_DEBUG_CORE && rd==eR15) |
| 716 | 701 | logerror("Wrote R15 in 32bit mode\n"); |
| 717 | 702 | |
| 718 | | WRITE32(rnv, rd == eR15 ? R15 + 8 : GetRegister(rd)); |
| 703 | cpu_write32(rnv, rd == eR15 ? R15 + 8 : GetRegister(rd)); |
| 719 | 704 | } |
| 720 | 705 | } |
| 721 | 706 | |
| r24002 | r24003 | |
| 726 | 711 | { |
| 727 | 712 | /* Writeback is applied in pipeline, before value is read from mem, |
| 728 | 713 | so writeback is effectively ignored */ |
| 729 | | if (rd==rn) { |
| 714 | if (rd==rn) |
| 715 | { |
| 730 | 716 | SetRegister(rn,GetRegister(rd)); |
| 731 | 717 | } |
| 732 | | else { |
| 718 | else |
| 719 | { |
| 733 | 720 | if ((insn&INSN_SDT_W)!=0) |
| 734 | 721 | logerror("%08x: RegisterWritebackIncrement %d %d %d\n",R15,(insn & INSN_SDT_P)!=0,(insn&INSN_SDT_W)!=0,(insn & INSN_SDT_U)!=0); |
| 735 | 722 | |
| r24002 | r24003 | |
| 740 | 727 | { |
| 741 | 728 | /* Writeback is applied in pipeline, before value is read from mem, |
| 742 | 729 | so writeback is effectively ignored */ |
| 743 | | if (rd==rn) { |
| 730 | if (rd==rn) |
| 731 | { |
| 744 | 732 | SetRegister(rn,GetRegister(rd)); |
| 745 | 733 | } |
| 746 | | else { |
| 734 | else |
| 735 | { |
| 747 | 736 | SetRegister(rn,(rnv - off)); |
| 748 | 737 | |
| 749 | 738 | if ((insn&INSN_SDT_W)!=0) |
| r24002 | r24003 | |
| 1019 | 1008 | { |
| 1020 | 1009 | if( (pat>>i)&1 ) |
| 1021 | 1010 | { |
| 1022 | | if (i==15) { |
| 1011 | if (i==15) |
| 1012 | { |
| 1023 | 1013 | if (s) /* Pull full contents from stack */ |
| 1024 | | SetRegister( 15, READ32(rbv+=4) ); |
| 1014 | SetRegister( 15, cpu_read32(rbv+=4) ); |
| 1025 | 1015 | else /* Pull only address, preserve mode & status flags */ |
| 1026 | | SetRegister( 15, (R15&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK) | ((READ32(rbv+=4))&ADDRESS_MASK) ); |
| 1027 | | } else |
| 1028 | | SetRegister( i, READ32(rbv+=4) ); |
| 1016 | SetRegister( 15, (R15&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK) | ((cpu_read32(rbv+=4))&ADDRESS_MASK) ); |
| 1017 | } |
| 1018 | else |
| 1019 | SetRegister( i, cpu_read32(rbv+=4) ); |
| 1029 | 1020 | |
| 1030 | 1021 | result++; |
| 1031 | 1022 | } |
| r24002 | r24003 | |
| 1043 | 1034 | { |
| 1044 | 1035 | if( (pat>>i)&1 ) |
| 1045 | 1036 | { |
| 1046 | | if (i==15) { |
| 1037 | if (i==15) |
| 1038 | { |
| 1047 | 1039 | *defer=1; |
| 1048 | 1040 | if (s) /* Pull full contents from stack */ |
| 1049 | | *deferredR15=READ32(rbv-=4); |
| 1041 | *deferredR15=cpu_read32(rbv-=4); |
| 1050 | 1042 | else /* Pull only address, preserve mode & status flags */ |
| 1051 | | *deferredR15=(R15&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK) | ((READ32(rbv-=4))&ADDRESS_MASK); |
| 1043 | *deferredR15=(R15&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK) | ((cpu_read32(rbv-=4))&ADDRESS_MASK); |
| 1052 | 1044 | } |
| 1053 | 1045 | else |
| 1054 | | SetRegister( i, READ32(rbv -=4) ); |
| 1046 | SetRegister( i, cpu_read32(rbv -=4) ); |
| 1055 | 1047 | result++; |
| 1056 | 1048 | } |
| 1057 | 1049 | } |
| r24002 | r24003 | |
| 1071 | 1063 | if (ARM_DEBUG_CORE && i==15) /* R15 is plus 12 from address of STM */ |
| 1072 | 1064 | logerror("%08x: StoreInc on R15\n",R15); |
| 1073 | 1065 | |
| 1074 | | WRITE32( rbv += 4, GetRegister(i) ); |
| 1066 | cpu_write32( rbv += 4, GetRegister(i) ); |
| 1075 | 1067 | result++; |
| 1076 | 1068 | } |
| 1077 | 1069 | } |
| r24002 | r24003 | |
| 1091 | 1083 | if (ARM_DEBUG_CORE && i==15) /* R15 is plus 12 from address of STM */ |
| 1092 | 1084 | logerror("%08x: StoreDec on R15\n",R15); |
| 1093 | 1085 | |
| 1094 | | WRITE32( rbv -= 4, GetRegister(i) ); |
| 1086 | cpu_write32( rbv -= 4, GetRegister(i) ); |
| 1095 | 1087 | result++; |
| 1096 | 1088 | } |
| 1097 | 1089 | } |
| r24002 | r24003 | |
| 1120 | 1112 | |
| 1121 | 1113 | result = loadInc( insn & 0xffff, rbp, insn&INSN_BDT_S ); |
| 1122 | 1114 | |
| 1123 | | if (insn & 0x8000) { |
| 1115 | if (insn & 0x8000) |
| 1116 | { |
| 1124 | 1117 | R15-=4; |
| 1125 | 1118 | m_icount -= S_CYCLE + N_CYCLE; |
| 1126 | 1119 | } |
| r24002 | r24003 | |
| 1173 | 1166 | if (defer) |
| 1174 | 1167 | SetRegister(15, deferredR15); |
| 1175 | 1168 | |
| 1176 | | if (insn & 0x8000) { |
| 1169 | if (insn & 0x8000) |
| 1170 | { |
| 1177 | 1171 | m_icount -= S_CYCLE + N_CYCLE; |
| 1178 | 1172 | R15-=4; |
| 1179 | 1173 | } |
| r24002 | r24003 | |
| 1242 | 1236 | UINT32 rm = GetRegister( insn & INSN_OP2_RM ); |
| 1243 | 1237 | UINT32 t = (insn & INSN_OP2_SHIFT_TYPE) >> INSN_OP2_SHIFT_TYPE_SHIFT; |
| 1244 | 1238 | |
| 1245 | | if ((insn & INSN_OP2_RM)==0xf) { |
| 1239 | if ((insn & INSN_OP2_RM)==0xf) |
| 1240 | { |
| 1246 | 1241 | /* If hardwired shift, then PC is 8 bytes ahead, else if register shift |
| 1247 | 1242 | is used, then 12 bytes - TODO?? */ |
| 1248 | 1243 | rm+=8; |