diff options
| author | 2014-03-29 21:53:07 -0400 | |
|---|---|---|
| committer | 2014-03-29 21:53:07 -0400 | |
| commit | 6b255111d5c130e49846b1727302111f423cb157 (patch) | |
| tree | 335ba0e8c06480b4f8f777651e83525ba647317f /src | |
| parent | added a GetPointer function to Memory for use with ELF loading (diff) | |
| download | yuzu-6b255111d5c130e49846b1727302111f423cb157.tar.gz yuzu-6b255111d5c130e49846b1727302111f423cb157.tar.xz yuzu-6b255111d5c130e49846b1727302111f423cb157.zip | |
added various arm modules from skyeye to make project link OK
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/core.vcxproj | 8 | ||||
| -rw-r--r-- | src/core/core.vcxproj.filters | 20 | ||||
| -rw-r--r-- | src/core/src/arm/armemu.cpp | 21 | ||||
| -rw-r--r-- | src/core/src/arm/armemu.h | 15 | ||||
| -rw-r--r-- | src/core/src/arm/arminit.cpp | 163 | ||||
| -rw-r--r-- | src/core/src/arm/armmmu.cpp | 146 | ||||
| -rw-r--r-- | src/core/src/arm/armos.cpp | 742 | ||||
| -rw-r--r-- | src/core/src/arm/armsupp.cpp | 953 | ||||
| -rw-r--r-- | src/core/src/arm/armvirt.cpp | 680 |
9 files changed, 2582 insertions, 166 deletions
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index 9d6c28216..a774f9e4b 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj | |||
| @@ -139,9 +139,14 @@ | |||
| 139 | <ItemGroup> | 139 | <ItemGroup> |
| 140 | <ClCompile Include="src\arm\armemu.cpp" /> | 140 | <ClCompile Include="src\arm\armemu.cpp" /> |
| 141 | <ClCompile Include="src\arm\arminit.cpp" /> | 141 | <ClCompile Include="src\arm\arminit.cpp" /> |
| 142 | <ClCompile Include="src\arm\armmmu.cpp" /> | ||
| 143 | <ClCompile Include="src\arm\armos.cpp" /> | ||
| 144 | <ClCompile Include="src\arm\armsupp.cpp" /> | ||
| 145 | <ClCompile Include="src\arm\armvirt.cpp" /> | ||
| 142 | <ClCompile Include="src\arm\disassembler\arm_disasm.cpp" /> | 146 | <ClCompile Include="src\arm\disassembler\arm_disasm.cpp" /> |
| 143 | <ClCompile Include="src\core.cpp" /> | 147 | <ClCompile Include="src\core.cpp" /> |
| 144 | <ClCompile Include="src\core_timing.cpp" /> | 148 | <ClCompile Include="src\core_timing.cpp" /> |
| 149 | <ClCompile Include="src\elf\elf_reader.cpp" /> | ||
| 145 | <ClCompile Include="src\file_sys\directory_file_system.cpp" /> | 150 | <ClCompile Include="src\file_sys\directory_file_system.cpp" /> |
| 146 | <ClCompile Include="src\file_sys\meta_file_system.cpp" /> | 151 | <ClCompile Include="src\file_sys\meta_file_system.cpp" /> |
| 147 | <ClCompile Include="src\loader.cpp" /> | 152 | <ClCompile Include="src\loader.cpp" /> |
| @@ -165,7 +170,8 @@ | |||
| 165 | <ClInclude Include="src\arm\skyeye_defs.h" /> | 170 | <ClInclude Include="src\arm\skyeye_defs.h" /> |
| 166 | <ClInclude Include="src\core.h" /> | 171 | <ClInclude Include="src\core.h" /> |
| 167 | <ClInclude Include="src\core_timing.h" /> | 172 | <ClInclude Include="src\core_timing.h" /> |
| 168 | <ClInclude Include="src\elf\elf.h" /> | 173 | <ClInclude Include="src\elf\elf_reader.h" /> |
| 174 | <ClInclude Include="src\elf\elf_types.h" /> | ||
| 169 | <ClInclude Include="src\file_sys\directory_file_system.h" /> | 175 | <ClInclude Include="src\file_sys\directory_file_system.h" /> |
| 170 | <ClInclude Include="src\file_sys\file_sys.h" /> | 176 | <ClInclude Include="src\file_sys\file_sys.h" /> |
| 171 | <ClInclude Include="src\file_sys\meta_file_system.h" /> | 177 | <ClInclude Include="src\file_sys\meta_file_system.h" /> |
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters index 4d1ec576c..50d0cbc71 100644 --- a/src/core/core.vcxproj.filters +++ b/src/core/core.vcxproj.filters | |||
| @@ -22,6 +22,21 @@ | |||
| 22 | </ClCompile> | 22 | </ClCompile> |
| 23 | <ClCompile Include="src\system.cpp" /> | 23 | <ClCompile Include="src\system.cpp" /> |
| 24 | <ClCompile Include="src\core_timing.cpp" /> | 24 | <ClCompile Include="src\core_timing.cpp" /> |
| 25 | <ClCompile Include="src\elf\elf_reader.cpp"> | ||
| 26 | <Filter>elf</Filter> | ||
| 27 | </ClCompile> | ||
| 28 | <ClCompile Include="src\arm\armsupp.cpp"> | ||
| 29 | <Filter>arm</Filter> | ||
| 30 | </ClCompile> | ||
| 31 | <ClCompile Include="src\arm\armvirt.cpp"> | ||
| 32 | <Filter>arm</Filter> | ||
| 33 | </ClCompile> | ||
| 34 | <ClCompile Include="src\arm\armmmu.cpp"> | ||
| 35 | <Filter>arm</Filter> | ||
| 36 | </ClCompile> | ||
| 37 | <ClCompile Include="src\arm\armos.cpp"> | ||
| 38 | <Filter>arm</Filter> | ||
| 39 | </ClCompile> | ||
| 25 | </ItemGroup> | 40 | </ItemGroup> |
| 26 | <ItemGroup> | 41 | <ItemGroup> |
| 27 | <Filter Include="arm"> | 42 | <Filter Include="arm"> |
| @@ -94,7 +109,10 @@ | |||
| 94 | </ClInclude> | 109 | </ClInclude> |
| 95 | <ClInclude Include="src\system.h" /> | 110 | <ClInclude Include="src\system.h" /> |
| 96 | <ClInclude Include="src\core_timing.h" /> | 111 | <ClInclude Include="src\core_timing.h" /> |
| 97 | <ClInclude Include="src\elf\elf.h"> | 112 | <ClInclude Include="src\elf\elf_reader.h"> |
| 113 | <Filter>elf</Filter> | ||
| 114 | </ClInclude> | ||
| 115 | <ClInclude Include="src\elf\elf_types.h"> | ||
| 98 | <Filter>elf</Filter> | 116 | <Filter>elf</Filter> |
| 99 | </ClInclude> | 117 | </ClInclude> |
| 100 | </ItemGroup> | 118 | </ItemGroup> |
diff --git a/src/core/src/arm/armemu.cpp b/src/core/src/arm/armemu.cpp index e5c287236..362ae0fd1 100644 --- a/src/core/src/arm/armemu.cpp +++ b/src/core/src/arm/armemu.cpp | |||
| @@ -21,6 +21,19 @@ | |||
| 21 | #include "armemu.h" | 21 | #include "armemu.h" |
| 22 | #include "armos.h" | 22 | #include "armos.h" |
| 23 | 23 | ||
| 24 | void | ||
| 25 | XScale_set_fsr_far(ARMul_State * state, ARMword fsr, ARMword _far) | ||
| 26 | { | ||
| 27 | _dbg_assert_msg_(ARM11, false, "ImplementMe: XScale_set_fsr_far!"); | ||
| 28 | //if (!state->is_XScale || (read_cp14_reg(10) & (1UL << 31)) == 0) | ||
| 29 | // return; | ||
| 30 | // | ||
| 31 | //write_cp15_reg(state, 5, 0, 0, fsr); | ||
| 32 | //write_cp15_reg(state, 6, 0, 0, _far); | ||
| 33 | } | ||
| 34 | |||
| 35 | #define ARMul_Debug(x,y,z) 0 // Disabling this /bunnei | ||
| 36 | |||
| 24 | //#include "skyeye_callback.h" | 37 | //#include "skyeye_callback.h" |
| 25 | //#include "skyeye_bus.h" | 38 | //#include "skyeye_bus.h" |
| 26 | //#include "sim_control.h" | 39 | //#include "sim_control.h" |
| @@ -2174,10 +2187,10 @@ ARMul_Emulate26 (ARMul_State * state) | |||
| 2174 | (state, | 2187 | (state, |
| 2175 | ARMul_CP15_R5_MMU_EXCPT, | 2188 | ARMul_CP15_R5_MMU_EXCPT, |
| 2176 | pc); | 2189 | pc); |
| 2177 | if (!XScale_debug_moe | 2190 | //if (!XScale_debug_moe |
| 2178 | (state, | 2191 | // (state, |
| 2179 | ARMul_CP14_R10_MOE_BT)) | 2192 | // ARMul_CP14_R10_MOE_BT)) |
| 2180 | break; | 2193 | // break; // Disabled /bunnei |
| 2181 | } | 2194 | } |
| 2182 | 2195 | ||
| 2183 | /* Force the next instruction to be refetched. */ | 2196 | /* Force the next instruction to be refetched. */ |
diff --git a/src/core/src/arm/armemu.h b/src/core/src/arm/armemu.h index ae5c35aee..d4afa8e22 100644 --- a/src/core/src/arm/armemu.h +++ b/src/core/src/arm/armemu.h | |||
| @@ -73,6 +73,7 @@ extern ARMword isize; | |||
| 73 | #define ASSIGNT(res) state->TFlag = res | 73 | #define ASSIGNT(res) state->TFlag = res |
| 74 | #define INSN_SIZE (TFLAG ? 2 : 4) | 74 | #define INSN_SIZE (TFLAG ? 2 : 4) |
| 75 | #else | 75 | #else |
| 76 | #define TBIT (1L << 5) | ||
| 76 | #define INSN_SIZE 4 | 77 | #define INSN_SIZE 4 |
| 77 | #define TFLAG 0 | 78 | #define TFLAG 0 |
| 78 | #endif | 79 | #endif |
| @@ -229,12 +230,12 @@ extern ARMword isize; | |||
| 229 | } \ | 230 | } \ |
| 230 | while (0) | 231 | while (0) |
| 231 | 232 | ||
| 232 | #ifndef MODE32 | 233 | //#ifndef MODE32 |
| 233 | #define VECTORS 0x20 | 234 | #define VECTORS 0x20 |
| 234 | #define LEGALADDR 0x03ffffff | 235 | #define LEGALADDR 0x03ffffff |
| 235 | #define VECTORACCESS(address) (address < VECTORS && ARMul_MODE26BIT && state->prog32Sig) | 236 | #define VECTORACCESS(address) (address < VECTORS && ARMul_MODE26BIT && state->prog32Sig) |
| 236 | #define ADDREXCEPT(address) (address > LEGALADDR && !state->data32Sig) | 237 | #define ADDREXCEPT(address) (address > LEGALADDR && !state->data32Sig) |
| 237 | #endif | 238 | //#endif |
| 238 | 239 | ||
| 239 | #define INTERNALABORT(address) \ | 240 | #define INTERNALABORT(address) \ |
| 240 | do \ | 241 | do \ |
| @@ -409,10 +410,12 @@ extern ARMword isize; | |||
| 409 | || (! (STATE)->is_XScale) \ | 410 | || (! (STATE)->is_XScale) \ |
| 410 | || (read_cp15_reg (15, 0, 1) & (1 << (CP)))) | 411 | || (read_cp15_reg (15, 0, 1) & (1 << (CP)))) |
| 411 | */ | 412 | */ |
| 412 | #define CP_ACCESS_ALLOWED(STATE, CP) \ | 413 | //#define CP_ACCESS_ALLOWED(STATE, CP) \ |
| 413 | ( ((CP) >= 14) \ | 414 | // (((CP) >= 14) \ |
| 414 | || (! (STATE)->is_XScale) \ | 415 | // || (!(STATE)->is_XScale) \ |
| 415 | || (xscale_cp15_cp_access_allowed(STATE,15,CP))) | 416 | // || (xscale_cp15_cp_access_allowed(STATE, 15, CP))) |
| 417 | |||
| 418 | #define CP_ACCESS_ALLOWED(STATE, CP) false // Disabled coprocessor shit /bunnei | ||
| 416 | 419 | ||
| 417 | /* Macro to rotate n right by b bits. */ | 420 | /* Macro to rotate n right by b bits. */ |
| 418 | #define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b)))) | 421 | #define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b)))) |
diff --git a/src/core/src/arm/arminit.cpp b/src/core/src/arm/arminit.cpp index 9327f8f6a..d394be66c 100644 --- a/src/core/src/arm/arminit.cpp +++ b/src/core/src/arm/arminit.cpp | |||
| @@ -271,7 +271,7 @@ below line sould be in skyeye_mach_XXX.c 's XXX_mach_init function | |||
| 271 | 271 | ||
| 272 | /* Only initialse the coprocessor support once we | 272 | /* Only initialse the coprocessor support once we |
| 273 | know what kind of chip we are dealing with. */ | 273 | know what kind of chip we are dealing with. */ |
| 274 | ARMul_CoProInit (state); | 274 | //ARMul_CoProInit (state); Commented out /bunnei |
| 275 | 275 | ||
| 276 | } | 276 | } |
| 277 | 277 | ||
| @@ -318,7 +318,7 @@ ARMul_Reset (ARMul_State * state) | |||
| 318 | state->NumFcycles = 0; | 318 | state->NumFcycles = 0; |
| 319 | 319 | ||
| 320 | //fprintf(stderr,"armul_reset 3: state-> Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode); | 320 | //fprintf(stderr,"armul_reset 3: state-> Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode); |
| 321 | mmu_reset (state); | 321 | //mmu_reset (state); Commented out /bunnei |
| 322 | //fprintf(stderr,"armul_reset 4: state-> Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode); | 322 | //fprintf(stderr,"armul_reset 4: state-> Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode); |
| 323 | 323 | ||
| 324 | //mem_reset (state); /* move to memory/ram.c */ | 324 | //mem_reset (state); /* move to memory/ram.c */ |
| @@ -436,7 +436,8 @@ ARMul_DoProg (ARMul_State * state) | |||
| 436 | } | 436 | } |
| 437 | 437 | ||
| 438 | else { | 438 | else { |
| 439 | pc = ARMul_Emulate26 (state); | 439 | //pc = ARMul_Emulate26 (state); Commented out /bunnei |
| 440 | ERROR_LOG(ARM11, "Unsupported ARM 26-bit Mode!"); | ||
| 440 | } | 441 | } |
| 441 | //chy 2006-02-22, should test debugmode first | 442 | //chy 2006-02-22, should test debugmode first |
| 442 | //chy 2006-04-14, put below codes in ARMul_Emulate | 443 | //chy 2006-04-14, put below codes in ARMul_Emulate |
| @@ -489,8 +490,10 @@ ARMul_DoInstr (ARMul_State * state) | |||
| 489 | #endif | 490 | #endif |
| 490 | } | 491 | } |
| 491 | 492 | ||
| 492 | else | 493 | else { |
| 493 | pc = ARMul_Emulate26 (state); | 494 | //pc = ARMul_Emulate26 (state); Commented out /bunnei |
| 495 | ERROR_LOG(ARM11, "Unsupported ARM 26-bit Mode!"); | ||
| 496 | } | ||
| 494 | 497 | ||
| 495 | return (pc); | 498 | return (pc); |
| 496 | } | 499 | } |
| @@ -501,78 +504,78 @@ ARMul_DoInstr (ARMul_State * state) | |||
| 501 | * appropriate vector's memory address (0,4,8 ....) * | 504 | * appropriate vector's memory address (0,4,8 ....) * |
| 502 | \***************************************************************************/ | 505 | \***************************************************************************/ |
| 503 | 506 | ||
| 504 | //void | 507 | void |
| 505 | //ARMul_Abort (ARMul_State * state, ARMword vector) | 508 | ARMul_Abort (ARMul_State * state, ARMword vector) |
| 506 | //{ | 509 | { |
| 507 | // ARMword temp; | 510 | ARMword temp; |
| 508 | // int isize = INSN_SIZE; | 511 | int isize = INSN_SIZE; |
| 509 | // int esize = (TFLAG ? 0 : 4); | 512 | int esize = (TFLAG ? 0 : 4); |
| 510 | // int e2size = (TFLAG ? -4 : 0); | 513 | int e2size = (TFLAG ? -4 : 0); |
| 511 | // | 514 | |
| 512 | // state->Aborted = FALSE; | 515 | state->Aborted = FALSE; |
| 513 | // | 516 | |
| 514 | // if (state->prog32Sig) | 517 | if (state->prog32Sig) |
| 515 | // if (ARMul_MODE26BIT) | 518 | if (ARMul_MODE26BIT) |
| 516 | // temp = R15PC; | 519 | temp = R15PC; |
| 517 | // else | 520 | else |
| 518 | // temp = state->Reg[15]; | 521 | temp = state->Reg[15]; |
| 519 | // else | 522 | else |
| 520 | // temp = R15PC | ECC | ER15INT | EMODE; | 523 | temp = R15PC | ECC | ER15INT | EMODE; |
| 521 | // | 524 | |
| 522 | // switch (vector) { | 525 | switch (vector) { |
| 523 | // case ARMul_ResetV: /* RESET */ | 526 | case ARMul_ResetV: /* RESET */ |
| 524 | // SETABORT (INTBITS, state->prog32Sig ? SVC32MODE : SVC26MODE, | 527 | SETABORT (INTBITS, state->prog32Sig ? SVC32MODE : SVC26MODE, |
| 525 | // 0); | 528 | 0); |
| 526 | // break; | 529 | break; |
| 527 | // case ARMul_UndefinedInstrV: /* Undefined Instruction */ | 530 | case ARMul_UndefinedInstrV: /* Undefined Instruction */ |
| 528 | // SETABORT (IBIT, state->prog32Sig ? UNDEF32MODE : SVC26MODE, | 531 | SETABORT (IBIT, state->prog32Sig ? UNDEF32MODE : SVC26MODE, |
| 529 | // isize); | 532 | isize); |
| 530 | // break; | 533 | break; |
| 531 | // case ARMul_SWIV: /* Software Interrupt */ | 534 | case ARMul_SWIV: /* Software Interrupt */ |
| 532 | // SETABORT (IBIT, state->prog32Sig ? SVC32MODE : SVC26MODE, | 535 | SETABORT (IBIT, state->prog32Sig ? SVC32MODE : SVC26MODE, |
| 533 | // isize); | 536 | isize); |
| 534 | // break; | 537 | break; |
| 535 | // case ARMul_PrefetchAbortV: /* Prefetch Abort */ | 538 | case ARMul_PrefetchAbortV: /* Prefetch Abort */ |
| 536 | // state->AbortAddr = 1; | 539 | state->AbortAddr = 1; |
| 537 | // SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, | 540 | SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, |
| 538 | // esize); | 541 | esize); |
| 539 | // break; | 542 | break; |
| 540 | // case ARMul_DataAbortV: /* Data Abort */ | 543 | case ARMul_DataAbortV: /* Data Abort */ |
| 541 | // SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, | 544 | SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, |
| 542 | // e2size); | 545 | e2size); |
| 543 | // break; | 546 | break; |
| 544 | // case ARMul_AddrExceptnV: /* Address Exception */ | 547 | case ARMul_AddrExceptnV: /* Address Exception */ |
| 545 | // SETABORT (IBIT, SVC26MODE, isize); | 548 | SETABORT (IBIT, SVC26MODE, isize); |
| 546 | // break; | 549 | break; |
| 547 | // case ARMul_IRQV: /* IRQ */ | 550 | case ARMul_IRQV: /* IRQ */ |
| 548 | // //chy 2003-09-02 the if sentence seems no use | 551 | //chy 2003-09-02 the if sentence seems no use |
| 549 | //#if 0 | 552 | #if 0 |
| 550 | // if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp) | 553 | if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp) |
| 551 | // || (temp & ARMul_CP13_R0_IRQ)) | 554 | || (temp & ARMul_CP13_R0_IRQ)) |
| 552 | //#endif | 555 | #endif |
| 553 | // SETABORT (IBIT, | 556 | SETABORT (IBIT, |
| 554 | // state->prog32Sig ? IRQ32MODE : IRQ26MODE, | 557 | state->prog32Sig ? IRQ32MODE : IRQ26MODE, |
| 555 | // esize); | 558 | esize); |
| 556 | // break; | 559 | break; |
| 557 | // case ARMul_FIQV: /* FIQ */ | 560 | case ARMul_FIQV: /* FIQ */ |
| 558 | // //chy 2003-09-02 the if sentence seems no use | 561 | //chy 2003-09-02 the if sentence seems no use |
| 559 | //#if 0 | 562 | #if 0 |
| 560 | // if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp) | 563 | if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp) |
| 561 | // || (temp & ARMul_CP13_R0_FIQ)) | 564 | || (temp & ARMul_CP13_R0_FIQ)) |
| 562 | //#endif | 565 | #endif |
| 563 | // SETABORT (INTBITS, | 566 | SETABORT (INTBITS, |
| 564 | // state->prog32Sig ? FIQ32MODE : FIQ26MODE, | 567 | state->prog32Sig ? FIQ32MODE : FIQ26MODE, |
| 565 | // esize); | 568 | esize); |
| 566 | // break; | 569 | break; |
| 567 | // } | 570 | } |
| 568 | // | 571 | |
| 569 | // if (ARMul_MODE32BIT) { | 572 | if (ARMul_MODE32BIT) { |
| 570 | // if (state->mmu.control & CONTROL_VECTOR) | 573 | if (state->mmu.control & CONTROL_VECTOR) |
| 571 | // vector += 0xffff0000; //for v4 high exception address | 574 | vector += 0xffff0000; //for v4 high exception address |
| 572 | // if (state->vector_remap_flag) | 575 | if (state->vector_remap_flag) |
| 573 | // vector += state->vector_remap_addr; /* support some remap function in LPC processor */ | 576 | vector += state->vector_remap_addr; /* support some remap function in LPC processor */ |
| 574 | // ARMul_SetR15 (state, vector); | 577 | ARMul_SetR15 (state, vector); |
| 575 | // } | 578 | } |
| 576 | // else | 579 | else |
| 577 | // ARMul_SetR15 (state, R15CCINTMODE | vector); | 580 | ARMul_SetR15 (state, R15CCINTMODE | vector); |
| 578 | //} | 581 | } |
diff --git a/src/core/src/arm/armmmu.cpp b/src/core/src/arm/armmmu.cpp index 5ba81b52a..476f8051d 100644 --- a/src/core/src/arm/armmmu.cpp +++ b/src/core/src/arm/armmmu.cpp | |||
| @@ -45,55 +45,51 @@ mmu_init (ARMul_State * state) | |||
| 45 | state->mmu.process_id = 0; | 45 | state->mmu.process_id = 0; |
| 46 | 46 | ||
| 47 | switch (state->cpu->cpu_val & state->cpu->cpu_mask) { | 47 | switch (state->cpu->cpu_val & state->cpu->cpu_mask) { |
| 48 | case SA1100: | 48 | //case SA1100: |
| 49 | case SA1110: | 49 | //case SA1110: |
| 50 | SKYEYE_INFO("SKYEYE: use sa11xx mmu ops\n"); | 50 | // NOTICE_LOG(ARM11, "SKYEYE: use sa11xx mmu ops\n"); |
| 51 | state->mmu.ops = sa_mmu_ops; | 51 | // state->mmu.ops = sa_mmu_ops; |
| 52 | break; | 52 | // break; |
| 53 | case PXA250: | 53 | //case PXA250: |
| 54 | case PXA270: //xscale | 54 | //case PXA270: //xscale |
| 55 | SKYEYE_INFO ("SKYEYE: use xscale mmu ops\n"); | 55 | // NOTICE_LOG(ARM11, "SKYEYE: use xscale mmu ops\n"); |
| 56 | state->mmu.ops = xscale_mmu_ops; | 56 | // state->mmu.ops = xscale_mmu_ops; |
| 57 | break; | 57 | // break; |
| 58 | case 0x41807200: //arm720t | 58 | //case 0x41807200: //arm720t |
| 59 | case 0x41007700: //arm7tdmi | 59 | //case 0x41007700: //arm7tdmi |
| 60 | case 0x41007100: //arm7100 | 60 | //case 0x41007100: //arm7100 |
| 61 | SKYEYE_INFO ( "SKYEYE: use arm7100 mmu ops\n"); | 61 | // NOTICE_LOG(ARM11, "SKYEYE: use arm7100 mmu ops\n"); |
| 62 | state->mmu.ops = arm7100_mmu_ops; | 62 | // state->mmu.ops = arm7100_mmu_ops; |
| 63 | break; | 63 | // break; |
| 64 | case 0x41009200: | 64 | //case 0x41009200: |
| 65 | SKYEYE_INFO ("SKYEYE: use arm920t mmu ops\n"); | 65 | // NOTICE_LOG(ARM11, "SKYEYE: use arm920t mmu ops\n"); |
| 66 | state->mmu.ops = arm920t_mmu_ops; | 66 | // state->mmu.ops = arm920t_mmu_ops; |
| 67 | break; | 67 | // break; |
| 68 | case 0x41069260: | 68 | //case 0x41069260: |
| 69 | SKYEYE_INFO ("SKYEYE: use arm926ejs mmu ops\n"); | 69 | // NOTICE_LOG(ARM11, "SKYEYE: use arm926ejs mmu ops\n"); |
| 70 | state->mmu.ops = arm926ejs_mmu_ops; | 70 | // state->mmu.ops = arm926ejs_mmu_ops; |
| 71 | break; | 71 | // break; |
| 72 | /* case 0x560f5810: */ | 72 | /* case 0x560f5810: */ |
| 73 | case 0x0007b000: | 73 | case 0x0007b000: |
| 74 | SKYEYE_INFO ("SKYEYE: use arm11jzf-s mmu ops\n"); | 74 | NOTICE_LOG(ARM11, "SKYEYE: use arm11jzf-s mmu ops\n"); |
| 75 | state->mmu.ops = arm1176jzf_s_mmu_ops; | 75 | //state->mmu.ops = arm1176jzf_s_mmu_ops; |
| 76 | _dbg_assert_msg_(ARM11, false, "ImplementMe: arm1176jzf_s_mmu_ops!"); | ||
| 76 | break; | 77 | break; |
| 77 | 78 | ||
| 78 | case 0xc090: | ||
| 79 | SKYEYE_INFO ("SKYEYE: use cortex_a9 mmu ops\n"); | ||
| 80 | state->mmu.ops = cortex_a9_mmu_ops; | ||
| 81 | break; | ||
| 82 | default: | 79 | default: |
| 83 | fprintf (stderr, | 80 | ERROR_LOG (ARM11, |
| 84 | "SKYEYE: armmmu.c : mmu_init: unknown cpu_val&cpu_mask 0x%x\n", | 81 | "SKYEYE: armmmu.c : mmu_init: unknown cpu_val&cpu_mask 0x%x\n", |
| 85 | state->cpu->cpu_val & state->cpu->cpu_mask); | 82 | state->cpu->cpu_val & state->cpu->cpu_mask); |
| 86 | skyeye_exit (-1); | ||
| 87 | break; | 83 | break; |
| 88 | 84 | ||
| 89 | }; | 85 | }; |
| 90 | ret = state->mmu.ops.init (state); | 86 | ret = state->mmu.ops.init (state); |
| 91 | state->mmu_inited = (ret == 0); | 87 | state->mmu_inited = (ret == 0); |
| 92 | /* initialize mmu_read and mmu_write for disassemble */ | 88 | /* initialize mmu_read and mmu_write for disassemble */ |
| 93 | skyeye_config_t *config = get_current_config(); | 89 | //skyeye_config_t *config = get_current_config(); |
| 94 | generic_arch_t *arch_instance = get_arch_instance(config->arch->arch_name); | 90 | //generic_arch_t *arch_instance = get_arch_instance(config->arch->arch_name); |
| 95 | arch_instance->mmu_read = arm_mmu_read; | 91 | //arch_instance->mmu_read = arm_mmu_read; |
| 96 | arch_instance->mmu_write = arm_mmu_write; | 92 | //arch_instance->mmu_write = arm_mmu_write; |
| 97 | 93 | ||
| 98 | return ret; | 94 | return ret; |
| 99 | } | 95 | } |
| @@ -201,41 +197,43 @@ mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, ARMword * phys_addr) | |||
| 201 | return (MMU_OPS.v2p_dbct (state, virt_addr, phys_addr)); | 197 | return (MMU_OPS.v2p_dbct (state, virt_addr, phys_addr)); |
| 202 | } | 198 | } |
| 203 | 199 | ||
| 204 | /* dis_mmu_read for disassemble */ | 200 | // |
| 205 | exception_t arm_mmu_read(short size, generic_address_t addr, uint32_t * value) | 201 | // |
| 206 | { | 202 | ///* dis_mmu_read for disassemble */ |
| 207 | ARMul_State *state; | 203 | //exception_t arm_mmu_read(short size, uint32_t addr, uint32_t * value) |
| 208 | ARM_CPU_State *cpu = get_current_cpu(); | 204 | //{ |
| 209 | state = &cpu->core[0]; | 205 | // ARMul_State *state; |
| 210 | switch(size){ | 206 | // ARM_CPU_State *cpu = get_current_cpu(); |
| 211 | case 8: | 207 | // state = &cpu->core[0]; |
| 212 | MMU_OPS.read_byte (state, addr, value); | 208 | // switch(size){ |
| 213 | break; | 209 | // case 8: |
| 214 | case 16: | 210 | // MMU_OPS.read_byte (state, addr, value); |
| 215 | case 32: | 211 | // break; |
| 216 | break; | 212 | // case 16: |
| 217 | default: | 213 | // case 32: |
| 218 | printf("In %s error size %d Line %d\n", __func__, size, __LINE__); | 214 | // break; |
| 219 | break; | 215 | // default: |
| 220 | } | 216 | // ERROR_LOG(ARM11, "Error size %d", size); |
| 221 | return No_exp; | 217 | // break; |
| 222 | } | 218 | // } |
| 223 | /* dis_mmu_write for disassemble */ | 219 | // return No_exp; |
| 224 | exception_t arm_mmu_write(short size, generic_address_t addr, uint32_t *value) | 220 | //} |
| 225 | { | 221 | ///* dis_mmu_write for disassemble */ |
| 226 | ARMul_State *state; | 222 | //exception_t arm_mmu_write(short size, uint32_t addr, uint32_t *value) |
| 227 | ARM_CPU_State *cpu = get_current_cpu(); | 223 | //{ |
| 228 | state = &cpu->core[0]; | 224 | // ARMul_State *state; |
| 229 | switch(size){ | 225 | // ARM_CPU_State *cpu = get_current_cpu(); |
| 230 | case 8: | 226 | // state = &cpu->core[0]; |
| 231 | MMU_OPS.write_byte (state, addr, value); | 227 | // switch(size){ |
| 232 | break; | 228 | // case 8: |
| 233 | case 16: | 229 | // MMU_OPS.write_byte (state, addr, value); |
| 234 | case 32: | 230 | // break; |
| 235 | break; | 231 | // case 16: |
| 236 | default: | 232 | // case 32: |
| 237 | printf("In %s error size %d Line %d\n", __func__, size, __LINE__); | 233 | // break; |
| 238 | break; | 234 | // default: |
| 239 | } | 235 | // printf("In %s error size %d Line %d\n", __func__, size, __LINE__); |
| 240 | return No_exp; | 236 | // break; |
| 241 | } | 237 | // } |
| 238 | // return No_exp; | ||
| 239 | //} | ||
diff --git a/src/core/src/arm/armos.cpp b/src/core/src/arm/armos.cpp new file mode 100644 index 000000000..43484ee5f --- /dev/null +++ b/src/core/src/arm/armos.cpp | |||
| @@ -0,0 +1,742 @@ | |||
| 1 | /* armos.c -- ARMulator OS interface: ARM6 Instruction Emulator. | ||
| 2 | Copyright (C) 1994 Advanced RISC Machines Ltd. | ||
| 3 | |||
| 4 | This program is free software; you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation; either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program; if not, write to the Free Software | ||
| 16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
| 17 | |||
| 18 | /* This file contains a model of Demon, ARM Ltd's Debug Monitor, | ||
| 19 | including all the SWI's required to support the C library. The code in | ||
| 20 | it is not really for the faint-hearted (especially the abort handling | ||
| 21 | code), but it is a complete example. Defining NOOS will disable all the | ||
| 22 | fun, and definign VAILDATE will define SWI 1 to enter SVC mode, and SWI | ||
| 23 | 0x11 to halt the emulator. */ | ||
| 24 | |||
| 25 | //chy 2005-09-12 disable below line | ||
| 26 | //#include "config.h" | ||
| 27 | |||
| 28 | #include <time.h> | ||
| 29 | #include <errno.h> | ||
| 30 | #include <string.h> | ||
| 31 | #include "skyeye_defs.h" | ||
| 32 | #ifndef __USE_LARGEFILE64 | ||
| 33 | #define __USE_LARGEFILE64 /* When use 64 bit large file need define it! for stat64*/ | ||
| 34 | #endif | ||
| 35 | #include <fcntl.h> | ||
| 36 | #include <sys/stat.h> | ||
| 37 | |||
| 38 | |||
| 39 | #ifndef O_RDONLY | ||
| 40 | #define O_RDONLY 0 | ||
| 41 | #endif | ||
| 42 | #ifndef O_WRONLY | ||
| 43 | #define O_WRONLY 1 | ||
| 44 | #endif | ||
| 45 | #ifndef O_RDWR | ||
| 46 | #define O_RDWR 2 | ||
| 47 | #endif | ||
| 48 | #ifndef O_BINARY | ||
| 49 | #define O_BINARY 0 | ||
| 50 | #endif | ||
| 51 | |||
| 52 | #ifdef __STDC__ | ||
| 53 | #define unlink(s) remove(s) | ||
| 54 | #endif | ||
| 55 | |||
| 56 | #ifdef HAVE_UNISTD_H | ||
| 57 | #include <unistd.h> /* For SEEK_SET etc */ | ||
| 58 | #endif | ||
| 59 | |||
| 60 | #ifdef __riscos | ||
| 61 | extern int _fisatty (FILE *); | ||
| 62 | #define isatty_(f) _fisatty(f) | ||
| 63 | #else | ||
| 64 | #ifdef __ZTC__ | ||
| 65 | #include <io.h> | ||
| 66 | #define isatty_(f) isatty((f)->_file) | ||
| 67 | #else | ||
| 68 | #ifdef macintosh | ||
| 69 | #include <ioctl.h> | ||
| 70 | #define isatty_(f) (~ioctl ((f)->_file, FIOINTERACTIVE, NULL)) | ||
| 71 | #else | ||
| 72 | #define isatty_(f) isatty (fileno (f)) | ||
| 73 | #endif | ||
| 74 | #endif | ||
| 75 | #endif | ||
| 76 | |||
| 77 | #include "armdefs.h" | ||
| 78 | #include "armos.h" | ||
| 79 | #include "armemu.h" | ||
| 80 | |||
| 81 | #ifndef NOOS | ||
| 82 | #ifndef VALIDATE | ||
| 83 | /* #ifndef ASIM */ | ||
| 84 | //chy 2005-09-12 disable below line | ||
| 85 | //#include "armfpe.h" | ||
| 86 | /* #endif */ | ||
| 87 | #endif | ||
| 88 | #endif | ||
| 89 | |||
| 90 | #define DUMP_SYSCALL 0 | ||
| 91 | #define dump(...) do { if (DUMP_SYSCALL) printf(__VA_ARGS__); } while(0) | ||
| 92 | //#define debug(...) printf(__VA_ARGS__); | ||
| 93 | #define debug(...) ; | ||
| 94 | |||
| 95 | extern unsigned ARMul_OSHandleSWI (ARMul_State * state, ARMword number); | ||
| 96 | |||
| 97 | #ifndef FOPEN_MAX | ||
| 98 | #define FOPEN_MAX 64 | ||
| 99 | #endif | ||
| 100 | |||
| 101 | /***************************************************************************\ | ||
| 102 | * OS private Information * | ||
| 103 | \***************************************************************************/ | ||
| 104 | |||
| 105 | unsigned arm_dyncom_SWI(ARMul_State * state, ARMword number) | ||
| 106 | { | ||
| 107 | return ARMul_OSHandleSWI(state, number); | ||
| 108 | } | ||
| 109 | |||
| 110 | //mmap_area_t *mmap_global = NULL; | ||
| 111 | |||
| 112 | static int translate_open_mode[] = { | ||
| 113 | O_RDONLY, /* "r" */ | ||
| 114 | O_RDONLY + O_BINARY, /* "rb" */ | ||
| 115 | O_RDWR, /* "r+" */ | ||
| 116 | O_RDWR + O_BINARY, /* "r+b" */ | ||
| 117 | O_WRONLY + O_CREAT + O_TRUNC, /* "w" */ | ||
| 118 | O_WRONLY + O_BINARY + O_CREAT + O_TRUNC, /* "wb" */ | ||
| 119 | O_RDWR + O_CREAT + O_TRUNC, /* "w+" */ | ||
| 120 | O_RDWR + O_BINARY + O_CREAT + O_TRUNC, /* "w+b" */ | ||
| 121 | O_WRONLY + O_APPEND + O_CREAT, /* "a" */ | ||
| 122 | O_WRONLY + O_BINARY + O_APPEND + O_CREAT, /* "ab" */ | ||
| 123 | O_RDWR + O_APPEND + O_CREAT, /* "a+" */ | ||
| 124 | O_RDWR + O_BINARY + O_APPEND + O_CREAT /* "a+b" */ | ||
| 125 | }; | ||
| 126 | // | ||
| 127 | //static void | ||
| 128 | //SWIWrite0 (ARMul_State * state, ARMword addr) | ||
| 129 | //{ | ||
| 130 | // ARMword temp; | ||
| 131 | // | ||
| 132 | // //while ((temp = ARMul_ReadByte (state, addr++)) != 0) | ||
| 133 | // while(1){ | ||
| 134 | // mem_read(8, addr++, &temp); | ||
| 135 | // if(temp != 0) | ||
| 136 | // (void) fputc ((char) temp, stdout); | ||
| 137 | // else | ||
| 138 | // break; | ||
| 139 | // } | ||
| 140 | //} | ||
| 141 | // | ||
| 142 | //static void | ||
| 143 | //WriteCommandLineTo (ARMul_State * state, ARMword addr) | ||
| 144 | //{ | ||
| 145 | // ARMword temp; | ||
| 146 | // char *cptr = state->CommandLine; | ||
| 147 | // if (cptr == NULL) | ||
| 148 | // cptr = "\0"; | ||
| 149 | // do { | ||
| 150 | // temp = (ARMword) * cptr++; | ||
| 151 | // //ARMul_WriteByte (state, addr++, temp); | ||
| 152 | // mem_write(8, addr++, temp); | ||
| 153 | // } | ||
| 154 | // while (temp != 0); | ||
| 155 | //} | ||
| 156 | // | ||
| 157 | //static void | ||
| 158 | //SWIopen (ARMul_State * state, ARMword name, ARMword SWIflags) | ||
| 159 | //{ | ||
| 160 | // char dummy[2000]; | ||
| 161 | // int flags; | ||
| 162 | // int i; | ||
| 163 | // | ||
| 164 | // for (i = 0; (dummy[i] = ARMul_ReadByte (state, name + i)); i++); | ||
| 165 | // assert(SWIflags< (sizeof(translate_open_mode)/ sizeof(translate_open_mode[0]))); | ||
| 166 | // /* Now we need to decode the Demon open mode */ | ||
| 167 | // flags = translate_open_mode[SWIflags]; | ||
| 168 | // flags = SWIflags; | ||
| 169 | // | ||
| 170 | // /* Filename ":tt" is special: it denotes stdin/out */ | ||
| 171 | // if (strcmp (dummy, ":tt") == 0) { | ||
| 172 | // if (flags == O_RDONLY) /* opening tty "r" */ | ||
| 173 | // state->Reg[0] = 0; /* stdin */ | ||
| 174 | // else | ||
| 175 | // state->Reg[0] = 1; /* stdout */ | ||
| 176 | // } | ||
| 177 | // else { | ||
| 178 | // state->Reg[0] = (int) open (dummy, flags, 0666); | ||
| 179 | // } | ||
| 180 | //} | ||
| 181 | // | ||
| 182 | //static void | ||
| 183 | //SWIread (ARMul_State * state, ARMword f, ARMword ptr, ARMword len) | ||
| 184 | //{ | ||
| 185 | // int res; | ||
| 186 | // int i; | ||
| 187 | // char *local = (char*) malloc (len); | ||
| 188 | // | ||
| 189 | // if (local == NULL) { | ||
| 190 | // fprintf (stderr, | ||
| 191 | // "sim: Unable to read 0x%ulx bytes - out of memory\n", | ||
| 192 | // len); | ||
| 193 | // return; | ||
| 194 | // } | ||
| 195 | // | ||
| 196 | // res = read (f, local, len); | ||
| 197 | // if (res > 0) | ||
| 198 | // for (i = 0; i < res; i++) | ||
| 199 | // //ARMul_WriteByte (state, ptr + i, local[i]); | ||
| 200 | // mem_write(8, ptr + i, local[i]); | ||
| 201 | // free (local); | ||
| 202 | // //state->Reg[0] = res == -1 ? -1 : len - res; | ||
| 203 | // state->Reg[0] = res; | ||
| 204 | //} | ||
| 205 | // | ||
| 206 | //static void | ||
| 207 | //SWIwrite (ARMul_State * state, ARMword f, ARMword ptr, ARMword len) | ||
| 208 | //{ | ||
| 209 | // int res; | ||
| 210 | // ARMword i; | ||
| 211 | // char *local = malloc (len); | ||
| 212 | // | ||
| 213 | // if (local == NULL) { | ||
| 214 | // fprintf (stderr, | ||
| 215 | // "sim: Unable to write 0x%lx bytes - out of memory\n", | ||
| 216 | // (long unsigned int) len); | ||
| 217 | // return; | ||
| 218 | // } | ||
| 219 | // | ||
| 220 | // for (i = 0; i < len; i++){ | ||
| 221 | // //local[i] = ARMul_ReadByte (state, ptr + i); | ||
| 222 | // ARMword data; | ||
| 223 | // mem_read(8, ptr + i, &data); | ||
| 224 | // local[i] = data & 0xFF; | ||
| 225 | // } | ||
| 226 | // | ||
| 227 | // res = write (f, local, len); | ||
| 228 | // //state->Reg[0] = res == -1 ? -1 : len - res; | ||
| 229 | // state->Reg[0] = res; | ||
| 230 | // free (local); | ||
| 231 | //} | ||
| 232 | |||
| 233 | //static void | ||
| 234 | //SWIflen (ARMul_State * state, ARMword fh) | ||
| 235 | //{ | ||
| 236 | // ARMword addr; | ||
| 237 | // | ||
| 238 | // if (fh == 0 || fh > FOPEN_MAX) { | ||
| 239 | // state->Reg[0] = -1L; | ||
| 240 | // return; | ||
| 241 | // } | ||
| 242 | // | ||
| 243 | // addr = lseek (fh, 0, SEEK_CUR); | ||
| 244 | // | ||
| 245 | // state->Reg[0] = lseek (fh, 0L, SEEK_END); | ||
| 246 | // (void) lseek (fh, addr, SEEK_SET); | ||
| 247 | // | ||
| 248 | //} | ||
| 249 | |||
| 250 | /***************************************************************************\ | ||
| 251 | * The emulator calls this routine when a SWI instruction is encuntered. The * | ||
| 252 | * parameter passed is the SWI number (lower 24 bits of the instruction). * | ||
| 253 | \***************************************************************************/ | ||
| 254 | /* ahe-ykl information is retrieved from elf header and the starting value of | ||
| 255 | brk_static is in sky_info_t */ | ||
| 256 | |||
| 257 | /* brk static hold the value of brk */ | ||
| 258 | static uint32_t brk_static = -1; | ||
| 259 | |||
| 260 | unsigned | ||
| 261 | ARMul_OSHandleSWI (ARMul_State * state, ARMword number) | ||
| 262 | { | ||
| 263 | number &= 0xfffff; | ||
| 264 | ARMword addr, temp; | ||
| 265 | |||
| 266 | switch (number) { | ||
| 267 | // case SWI_Syscall: | ||
| 268 | // if (state->Reg[7] != 0) | ||
| 269 | // return ARMul_OSHandleSWI(state, state->Reg[7]); | ||
| 270 | // else | ||
| 271 | // return FALSE; | ||
| 272 | // case SWI_Read: | ||
| 273 | // SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]); | ||
| 274 | // return TRUE; | ||
| 275 | // | ||
| 276 | // case SWI_GetUID32: | ||
| 277 | // state->Reg[0] = getuid(); | ||
| 278 | // return TRUE; | ||
| 279 | // | ||
| 280 | // case SWI_GetGID32: | ||
| 281 | // state->Reg[0] = getgid(); | ||
| 282 | // return TRUE; | ||
| 283 | // | ||
| 284 | // case SWI_GetEUID32: | ||
| 285 | // state->Reg[0] = geteuid(); | ||
| 286 | // return TRUE; | ||
| 287 | // | ||
| 288 | // case SWI_GetEGID32: | ||
| 289 | // state->Reg[0] = getegid(); | ||
| 290 | // return TRUE; | ||
| 291 | // | ||
| 292 | // case SWI_Write: | ||
| 293 | // SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]); | ||
| 294 | // return TRUE; | ||
| 295 | // | ||
| 296 | // case SWI_Open: | ||
| 297 | // SWIopen (state, state->Reg[0], state->Reg[1]); | ||
| 298 | // return TRUE; | ||
| 299 | // | ||
| 300 | // case SWI_Close: | ||
| 301 | // state->Reg[0] = close (state->Reg[0]); | ||
| 302 | // return TRUE; | ||
| 303 | // | ||
| 304 | // case SWI_Seek:{ | ||
| 305 | // /* We must return non-zero for failure */ | ||
| 306 | // state->Reg[0] = | ||
| 307 | // lseek (state->Reg[0], state->Reg[1], | ||
| 308 | // SEEK_SET); | ||
| 309 | // return TRUE; | ||
| 310 | // } | ||
| 311 | // | ||
| 312 | // case SWI_ExitGroup: | ||
| 313 | // case SWI_Exit: | ||
| 314 | // { | ||
| 315 | // struct timeval tv; | ||
| 316 | // //gettimeofday(&tv,NULL); | ||
| 317 | // //printf("In %s, %d sec, %d usec\n", __FUNCTION__, tv.tv_sec, tv.tv_usec); | ||
| 318 | // printf("passed %d sec, %lld usec\n", get_clock_sec(), get_clock_us()); | ||
| 319 | // | ||
| 320 | // /* quit here */ | ||
| 321 | // run_command("quit"); | ||
| 322 | // return TRUE; | ||
| 323 | // } | ||
| 324 | // case SWI_Times:{ | ||
| 325 | // uint32_t dest = state->Reg[0]; | ||
| 326 | // struct tms now; | ||
| 327 | // struct target_tms32 nowret; | ||
| 328 | // | ||
| 329 | // uint32_t ret = times(&now); | ||
| 330 | // | ||
| 331 | // if (ret == -1){ | ||
| 332 | // debug("syscall %s error %d\n", "SWI_Times", ret); | ||
| 333 | // state->Reg[0] = ret; | ||
| 334 | // return FALSE; | ||
| 335 | // } | ||
| 336 | // | ||
| 337 | // nowret.tms_cstime = now.tms_cstime; | ||
| 338 | // nowret.tms_cutime = now.tms_cutime; | ||
| 339 | // nowret.tms_stime = now.tms_stime; | ||
| 340 | // nowret.tms_utime = now.tms_utime; | ||
| 341 | // | ||
| 342 | // uint32_t offset; | ||
| 343 | // for (offset = 0; offset < sizeof(nowret); offset++) { | ||
| 344 | // bus_write(8, dest + offset, *((uint8_t *) &nowret + offset)); | ||
| 345 | // } | ||
| 346 | // | ||
| 347 | // state->Reg[0] = ret; | ||
| 348 | // return TRUE; | ||
| 349 | // } | ||
| 350 | // | ||
| 351 | // case SWI_Gettimeofday: { | ||
| 352 | // uint32_t dest1 = state->Reg[0]; | ||
| 353 | // uint32_t dest2 = state->Reg[1]; // Unsure of this | ||
| 354 | // struct timeval val; | ||
| 355 | // struct timezone zone; | ||
| 356 | // struct target_timeval32 valret; | ||
| 357 | // struct target_timezone32 zoneret; | ||
| 358 | // | ||
| 359 | // uint32_t ret = gettimeofday(&val, &zone); | ||
| 360 | // valret.tv_sec = val.tv_sec; | ||
| 361 | // valret.tv_usec = val.tv_usec; | ||
| 362 | // zoneret.tz_dsttime = zoneret.tz_dsttime; | ||
| 363 | // zoneret.tz_minuteswest = zoneret.tz_minuteswest; | ||
| 364 | // | ||
| 365 | // if (ret == -1){ | ||
| 366 | // debug("syscall %s error %d\n", "SWI_Gettimeofday", ret); | ||
| 367 | // state->Reg[0] = ret; | ||
| 368 | // return FALSE; | ||
| 369 | // } | ||
| 370 | // | ||
| 371 | // uint32_t offset; | ||
| 372 | // if (dest1) { | ||
| 373 | // for (offset = 0; offset < sizeof(valret); offset++) { | ||
| 374 | // bus_write(8, dest1 + offset, *((uint8_t *) &valret + offset)); | ||
| 375 | // } | ||
| 376 | // state->Reg[0] = ret; | ||
| 377 | // } | ||
| 378 | // if (dest2) { | ||
| 379 | // for (offset = 0; offset < sizeof(zoneret); offset++) { | ||
| 380 | // bus_write(8, dest2 + offset, *((uint8_t *) &zoneret + offset)); | ||
| 381 | // } | ||
| 382 | // state->Reg[0] = ret; | ||
| 383 | // } | ||
| 384 | // | ||
| 385 | // return TRUE; | ||
| 386 | // } | ||
| 387 | // case SWI_Brk: | ||
| 388 | // /* initialize brk value */ | ||
| 389 | // /* suppose that brk_static doesn't reach 0xffffffff... */ | ||
| 390 | // if (brk_static == -1) { | ||
| 391 | // brk_static = (get_skyeye_pref()->info).brk; | ||
| 392 | // } | ||
| 393 | // | ||
| 394 | // /* FIXME there might be a need to do a mmap */ | ||
| 395 | // | ||
| 396 | // if(state->Reg[0]){ | ||
| 397 | // if (get_skyeye_exec_info()->mmap_access) { | ||
| 398 | // /* if new brk is greater than current brk, allocate memory */ | ||
| 399 | // if (state->Reg[0] > brk_static) { | ||
| 400 | // uint32_t ret = mmap( (void *) brk_static, state->Reg[0] - brk_static, | ||
| 401 | // PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0 ); | ||
| 402 | // if (ret != MAP_FAILED) | ||
| 403 | // brk_static = ret; | ||
| 404 | // } | ||
| 405 | // } | ||
| 406 | // brk_static = state->Reg[0]; | ||
| 407 | // //state->Reg[0] = 0; /* FIXME return value of brk set to be the address on success */ | ||
| 408 | // } else { | ||
| 409 | // state->Reg[0] = brk_static; | ||
| 410 | // } | ||
| 411 | // return TRUE; | ||
| 412 | // | ||
| 413 | // case SWI_Break: | ||
| 414 | // state->Emulate = FALSE; | ||
| 415 | // return TRUE; | ||
| 416 | // | ||
| 417 | // case SWI_Mmap:{ | ||
| 418 | // int addr = state->Reg[0]; | ||
| 419 | // int len = state->Reg[1]; | ||
| 420 | // int prot = state->Reg[2]; | ||
| 421 | // int flag = state->Reg[3]; | ||
| 422 | // int fd = state->Reg[4]; | ||
| 423 | // int offset = state->Reg[5]; | ||
| 424 | // mmap_area_t *area = new_mmap_area(addr, len); | ||
| 425 | // state->Reg[0] = area->bank.addr; | ||
| 426 | // //printf("syscall %d mmap(0x%x,%x,0x%x,0x%x,%d,0x%x) = 0x%x\n",\ | ||
| 427 | // SWI_Mmap, addr, len, prot, flag, fd, offset, state->Reg[0]); | ||
| 428 | // return TRUE; | ||
| 429 | // } | ||
| 430 | // | ||
| 431 | // case SWI_Munmap: | ||
| 432 | // state->Reg[0] = 0; | ||
| 433 | // return TRUE; | ||
| 434 | // | ||
| 435 | // case SWI_Mmap2:{ | ||
| 436 | // int addr = state->Reg[0]; | ||
| 437 | // int len = state->Reg[1]; | ||
| 438 | // int prot = state->Reg[2]; | ||
| 439 | // int flag = state->Reg[3]; | ||
| 440 | // int fd = state->Reg[4]; | ||
| 441 | // int offset = state->Reg[5] * 4096; /* page offset */ | ||
| 442 | // mmap_area_t *area = new_mmap_area(addr, len); | ||
| 443 | // state->Reg[0] = area->bank.addr; | ||
| 444 | // | ||
| 445 | // return TRUE; | ||
| 446 | // } | ||
| 447 | // | ||
| 448 | // case SWI_Breakpoint: | ||
| 449 | // //chy 2005-09-12 change below line | ||
| 450 | // //state->EndCondition = RDIError_BreakpointReached; | ||
| 451 | // //printf ("SKYEYE: in armos.c : should not come here!!!!\n"); | ||
| 452 | // state->EndCondition = 0; | ||
| 453 | // /*modified by ksh to support breakpoiont*/ | ||
| 454 | // state->Emulate = STOP; | ||
| 455 | // return (TRUE); | ||
| 456 | // case SWI_Uname: | ||
| 457 | // { | ||
| 458 | // struct utsname *uts = (uintptr_t) state->Reg[0]; /* uname should write data in this address */ | ||
| 459 | // struct utsname utsbuf; | ||
| 460 | // //printf("Uname size is %x\n", sizeof(utsbuf)); | ||
| 461 | // char *buf; | ||
| 462 | // uintptr_t sp ; /* used as a temporary address */ | ||
| 463 | // | ||
| 464 | //#define COPY_UTS_STRING(addr) \ | ||
| 465 | // buf = addr; \ | ||
| 466 | // while(*buf != NULL) { \ | ||
| 467 | // bus_write(8, sp, *buf); \ | ||
| 468 | // sp++; \ | ||
| 469 | // buf++; \ | ||
| 470 | // } | ||
| 471 | //#define COPY_UTS(field) /*printf("%s: %s at %p\n", #field, utsbuf.field, uts->field);*/ \ | ||
| 472 | // sp = (uintptr_t) uts->field; \ | ||
| 473 | // COPY_UTS_STRING((&utsbuf)->field); | ||
| 474 | // | ||
| 475 | // if (uname(&utsbuf) < 0) { | ||
| 476 | // printf("syscall uname: utsname error\n"); | ||
| 477 | // state->Reg[0] = -1; | ||
| 478 | // return FALSE; | ||
| 479 | // } | ||
| 480 | // | ||
| 481 | // /* FIXME for now, this is just the host system call | ||
| 482 | // Some data should be missing, as it depends on | ||
| 483 | // the version of utsname */ | ||
| 484 | // COPY_UTS(sysname); | ||
| 485 | // COPY_UTS(nodename); | ||
| 486 | // COPY_UTS(release); | ||
| 487 | // COPY_UTS(version); | ||
| 488 | // COPY_UTS(machine); | ||
| 489 | // | ||
| 490 | // state->Reg[0] = 0; | ||
| 491 | // return TRUE; | ||
| 492 | // } | ||
| 493 | // case SWI_Fcntl: | ||
| 494 | // { | ||
| 495 | // uint32_t fd = state->Reg[0]; | ||
| 496 | // uint32_t cmd = state->Reg[1]; | ||
| 497 | // uint32_t arg = state->Reg[2]; | ||
| 498 | // uint32_t ret; | ||
| 499 | // | ||
| 500 | // switch(cmd){ | ||
| 501 | // case (F_GETFD): | ||
| 502 | // { | ||
| 503 | // ret = fcntl(fd, cmd, arg); | ||
| 504 | // //printf("syscall fcntl for getfd not implemented, ret %d\n", ret); | ||
| 505 | // state->Reg[0] = ret; | ||
| 506 | // return FALSE; | ||
| 507 | // } | ||
| 508 | // default: | ||
| 509 | // break; | ||
| 510 | // } | ||
| 511 | // | ||
| 512 | // printf("syscall fcntl unimplemented fd %x cmd %x\n", fd, cmd); | ||
| 513 | // state->Reg[0] = -1; | ||
| 514 | // return FALSE; | ||
| 515 | // | ||
| 516 | // } | ||
| 517 | // case SWI_Fstat64: | ||
| 518 | // { | ||
| 519 | // uint32_t dest = state->Reg[1]; | ||
| 520 | // uint32_t fd = state->Reg[0]; | ||
| 521 | // struct stat64 statbuf; | ||
| 522 | // struct target_stat64 statret; | ||
| 523 | // memset(&statret, 0, sizeof(struct target_stat64)); | ||
| 524 | // uint32_t ret = fstat64(fd, &statbuf); | ||
| 525 | // | ||
| 526 | // if (ret == -1){ | ||
| 527 | // printf("syscall %s returned error\n", "SWI_Fstat"); | ||
| 528 | // state->Reg[0] = ret; | ||
| 529 | // return FALSE; | ||
| 530 | // } | ||
| 531 | // | ||
| 532 | // /* copy statbuf to the process memory space | ||
| 533 | // FIXME can't say if endian has an effect here */ | ||
| 534 | // uint32_t offset; | ||
| 535 | // //printf("Fstat system is size %x\n", sizeof(statbuf)); | ||
| 536 | // //printf("Fstat target is size %x\n", sizeof(statret)); | ||
| 537 | // | ||
| 538 | // /* we copy system structure data stat64 into arm fixed size structure target_stat64 */ | ||
| 539 | // statret.st_dev = statbuf.st_dev; | ||
| 540 | // statret.st_ino = statbuf.st_ino; | ||
| 541 | // statret.st_mode = statbuf.st_mode; | ||
| 542 | // statret.st_nlink = statbuf.st_nlink; | ||
| 543 | // statret.st_uid = statbuf.st_uid; | ||
| 544 | // statret.st_gid = statbuf.st_gid; | ||
| 545 | // statret.st_rdev = statbuf.st_rdev; | ||
| 546 | // statret.st_size = statbuf.st_size; | ||
| 547 | // statret.st_blksize = statbuf.st_blksize; | ||
| 548 | // statret.st_blocks = statbuf.st_blocks; | ||
| 549 | // statret.st32_atime = statbuf.st_atime; | ||
| 550 | // statret.st32_mtime = statbuf.st_mtime; | ||
| 551 | // statret.st32_ctime = statbuf.st_ctime; | ||
| 552 | // | ||
| 553 | // for (offset = 0; offset < sizeof(statret); offset++) { | ||
| 554 | // bus_write(8, dest + offset, *((uint8_t *) &statret + offset)); | ||
| 555 | // } | ||
| 556 | // | ||
| 557 | // state->Reg[0] = ret; | ||
| 558 | // return TRUE; | ||
| 559 | // } | ||
| 560 | // case SWI_Set_tls: | ||
| 561 | // { | ||
| 562 | // //printf("syscall set_tls unimplemented\n"); | ||
| 563 | // state->mmu.thread_uro_id = state->Reg[0]; | ||
| 564 | // state->CP15[CP15_THREAD_URO - CP15_BASE] = state->Reg[0]; | ||
| 565 | // state->Reg[0] = 0; | ||
| 566 | // return FALSE; | ||
| 567 | // } | ||
| 568 | //#if 0 | ||
| 569 | // case SWI_Clock: | ||
| 570 | // /* return number of centi-seconds... */ | ||
| 571 | // state->Reg[0] = | ||
| 572 | //#ifdef CLOCKS_PER_SEC | ||
| 573 | // (CLOCKS_PER_SEC >= 100) | ||
| 574 | // ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100)) | ||
| 575 | // : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC); | ||
| 576 | //#else | ||
| 577 | // /* presume unix... clock() returns microseconds */ | ||
| 578 | // (ARMword) (clock () / 10000); | ||
| 579 | //#endif | ||
| 580 | // return (TRUE); | ||
| 581 | // | ||
| 582 | // case SWI_Time: | ||
| 583 | // state->Reg[0] = (ARMword) time (NULL); | ||
| 584 | // return (TRUE); | ||
| 585 | // case SWI_Flen: | ||
| 586 | // SWIflen (state, state->Reg[0]); | ||
| 587 | // return (TRUE); | ||
| 588 | // | ||
| 589 | //#endif | ||
| 590 | default: | ||
| 591 | |||
| 592 | _dbg_assert_msg_(ARM11, false, "ImplementMe: ARMul_OSHandleSWI!"); | ||
| 593 | |||
| 594 | return (FALSE); | ||
| 595 | } | ||
| 596 | } | ||
| 597 | // | ||
| 598 | ///** | ||
| 599 | // * @brief For mmap syscall.A mmap_area is a memory bank. Get from ppc. | ||
| 600 | // */ | ||
| 601 | //static mmap_area_t* new_mmap_area(int sim_addr, int len){ | ||
| 602 | // mmap_area_t *area = (mmap_area_t *)malloc(sizeof(mmap_area_t)); | ||
| 603 | // if(area == NULL){ | ||
| 604 | // printf("error, failed %s\n",__FUNCTION__); | ||
| 605 | // exit(0); | ||
| 606 | // } | ||
| 607 | //#if FAST_MEMORY | ||
| 608 | // if (mmap_next_base == -1) | ||
| 609 | // { | ||
| 610 | // mmap_next_base = get_skyeye_exec_info()->brk; | ||
| 611 | // } | ||
| 612 | //#endif | ||
| 613 | // | ||
| 614 | // memset(area, 0x0, sizeof(mmap_area_t)); | ||
| 615 | // area->bank.addr = mmap_next_base; | ||
| 616 | // area->bank.len = len; | ||
| 617 | // area->bank.bank_write = mmap_mem_write; | ||
| 618 | // area->bank.bank_read = mmap_mem_read; | ||
| 619 | // area->bank.type = MEMTYPE_RAM; | ||
| 620 | // area->bank.objname = "mmap"; | ||
| 621 | // addr_mapping(&area->bank); | ||
| 622 | // | ||
| 623 | //#if FAST_MEMORY | ||
| 624 | // if (get_skyeye_exec_info()->mmap_access) | ||
| 625 | // { | ||
| 626 | // /* FIXME check proper flags */ | ||
| 627 | // /* FIXME we may delete the need of banks up there */ | ||
| 628 | // uint32_t ret = mmap(mmap_next_base, len, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | ||
| 629 | // mmap_next_base = ret; | ||
| 630 | // } | ||
| 631 | // area->mmap_addr = (uint8_t*)get_dma_addr(mmap_next_base); | ||
| 632 | //#else | ||
| 633 | // area->mmap_addr = malloc(len); | ||
| 634 | // if(area->mmap_addr == NULL){ | ||
| 635 | // printf("error mmap malloc\n"); | ||
| 636 | // exit(0); | ||
| 637 | // } | ||
| 638 | // memset(area->mmap_addr, 0x0, len); | ||
| 639 | //#endif | ||
| 640 | // | ||
| 641 | // area->next = NULL; | ||
| 642 | // if(mmap_global){ | ||
| 643 | // area->next = mmap_global->next; | ||
| 644 | // mmap_global->next = area; | ||
| 645 | // }else{ | ||
| 646 | // mmap_global = area; | ||
| 647 | // } | ||
| 648 | // mmap_next_base = mmap_next_base + len; | ||
| 649 | // return area; | ||
| 650 | //} | ||
| 651 | // | ||
| 652 | //static mmap_area_t *get_mmap_area(int addr){ | ||
| 653 | // mmap_area_t *tmp = mmap_global; | ||
| 654 | // while(tmp){ | ||
| 655 | // if ((tmp->bank.addr <= addr) && (tmp->bank.addr + tmp->bank.len > addr)){ | ||
| 656 | // return tmp; | ||
| 657 | // } | ||
| 658 | // tmp = tmp->next; | ||
| 659 | // } | ||
| 660 | // printf("cannot get mmap area:addr=0x%x\n", addr); | ||
| 661 | // return NULL; | ||
| 662 | //} | ||
| 663 | // | ||
| 664 | ///** | ||
| 665 | // * @brief the mmap_area bank write function. Get from ppc. | ||
| 666 | // * | ||
| 667 | // * @param size size to write, 8/16/32 | ||
| 668 | // * @param addr address to write | ||
| 669 | // * @param value value to write | ||
| 670 | // * | ||
| 671 | // * @return sucess return 1,otherwise 0. | ||
| 672 | // */ | ||
| 673 | //static char mmap_mem_write(short size, int addr, uint32_t value){ | ||
| 674 | // mmap_area_t *area_tmp = get_mmap_area(addr); | ||
| 675 | // mem_bank_t *bank_tmp = &area_tmp->bank; | ||
| 676 | // int offset = addr - bank_tmp->addr; | ||
| 677 | // switch(size){ | ||
| 678 | // case 8:{ | ||
| 679 | // //uint8_t value_endian = value; | ||
| 680 | // uint8_t value_endian = (uint8_t)value; | ||
| 681 | // *(uint8_t *)&(((char *)area_tmp->mmap_addr)[offset]) = value_endian; | ||
| 682 | // debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,value_endian); | ||
| 683 | // break; | ||
| 684 | // } | ||
| 685 | // case 16:{ | ||
| 686 | // //uint16_t value_endian = half_to_BE((uint16_t)value); | ||
| 687 | // uint16_t value_endian = ((uint16_t)value); | ||
| 688 | // *(uint16_t *)&(((char *)area_tmp->mmap_addr)[offset]) = value_endian; | ||
| 689 | // debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,value_endian); | ||
| 690 | // break; | ||
| 691 | // } | ||
| 692 | // case 32:{ | ||
| 693 | // //uint32_t value_endian = word_to_BE((uint32_t)value); | ||
| 694 | // uint32_t value_endian = ((uint32_t)value); | ||
| 695 | // *(uint32_t *)&(((char *)area_tmp->mmap_addr)[offset]) = value_endian; | ||
| 696 | // debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,value_endian); | ||
| 697 | // break; | ||
| 698 | // } | ||
| 699 | // default: | ||
| 700 | // printf("invalid size %d\n",size); | ||
| 701 | // return 0; | ||
| 702 | // } | ||
| 703 | // return 1; | ||
| 704 | //} | ||
| 705 | // | ||
| 706 | ///** | ||
| 707 | // * @brief the mmap_area bank read function. Get from ppc. | ||
| 708 | // * | ||
| 709 | // * @param size size to read, 8/16/32 | ||
| 710 | // * @param addr address to read | ||
| 711 | // * @param value value to read | ||
| 712 | // * | ||
| 713 | // * @return sucess return 1,otherwise 0. | ||
| 714 | // */ | ||
| 715 | //static char mmap_mem_read(short size, int addr, uint32_t * value){ | ||
| 716 | // mmap_area_t *area_tmp = get_mmap_area(addr); | ||
| 717 | // mem_bank_t *bank_tmp = &area_tmp->bank; | ||
| 718 | // int offset = addr - bank_tmp->addr; | ||
| 719 | // switch(size){ | ||
| 720 | // case 8:{ | ||
| 721 | // //*(uint8_t *)value = *(uint8_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]); | ||
| 722 | // *value = *(uint8_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]); | ||
| 723 | // debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,*(uint32_t*)value); | ||
| 724 | // break; | ||
| 725 | // } | ||
| 726 | // case 16:{ | ||
| 727 | // //*(uint16_t *)value = half_from_BE(*(uint16_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset])); | ||
| 728 | // *value = (*(uint16_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset])); | ||
| 729 | // debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,*(uint16_t*)value); | ||
| 730 | // break; | ||
| 731 | // } | ||
| 732 | // case 32: | ||
| 733 | // //*value = (uint32_t)word_from_BE(*(uint32_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset])); | ||
| 734 | // *value = (uint32_t)(*(uint32_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset])); | ||
| 735 | // debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,*(uint32_t*)value); | ||
| 736 | // break; | ||
| 737 | // default: | ||
| 738 | // printf("invalid size %d\n",size); | ||
| 739 | // return 0; | ||
| 740 | // } | ||
| 741 | // return 1; | ||
| 742 | //} | ||
diff --git a/src/core/src/arm/armsupp.cpp b/src/core/src/arm/armsupp.cpp new file mode 100644 index 000000000..c2b8399c9 --- /dev/null +++ b/src/core/src/arm/armsupp.cpp | |||
| @@ -0,0 +1,953 @@ | |||
| 1 | /* armsupp.c -- ARMulator support code: ARM6 Instruction Emulator. | ||
| 2 | Copyright (C) 1994 Advanced RISC Machines Ltd. | ||
| 3 | |||
| 4 | This program is free software; you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation; either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program; if not, write to the Free Software | ||
| 16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
| 17 | |||
| 18 | #include "armdefs.h" | ||
| 19 | #include "armemu.h" | ||
| 20 | //#include "ansidecl.h" | ||
| 21 | #include "skyeye_defs.h" | ||
| 22 | unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg, | ||
| 23 | unsigned cpnum); | ||
| 24 | //extern int skyeye_instr_debug; | ||
| 25 | /* Definitions for the support routines. */ | ||
| 26 | |||
| 27 | static ARMword ModeToBank (ARMword); | ||
| 28 | static void EnvokeList (ARMul_State *, unsigned int, unsigned int); | ||
| 29 | |||
| 30 | struct EventNode | ||
| 31 | { /* An event list node. */ | ||
| 32 | unsigned (*func) (ARMul_State *); /* The function to call. */ | ||
| 33 | struct EventNode *next; | ||
| 34 | }; | ||
| 35 | |||
| 36 | /* This routine returns the value of a register from a mode. */ | ||
| 37 | |||
| 38 | ARMword | ||
| 39 | ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg) | ||
| 40 | { | ||
| 41 | mode &= MODEBITS; | ||
| 42 | if (mode != state->Mode) | ||
| 43 | return (state->RegBank[ModeToBank ((ARMword) mode)][reg]); | ||
| 44 | else | ||
| 45 | return (state->Reg[reg]); | ||
| 46 | } | ||
| 47 | |||
| 48 | /* This routine sets the value of a register for a mode. */ | ||
| 49 | |||
| 50 | void | ||
| 51 | ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value) | ||
| 52 | { | ||
| 53 | mode &= MODEBITS; | ||
| 54 | if (mode != state->Mode) | ||
| 55 | state->RegBank[ModeToBank ((ARMword) mode)][reg] = value; | ||
| 56 | else | ||
| 57 | state->Reg[reg] = value; | ||
| 58 | } | ||
| 59 | |||
| 60 | /* This routine returns the value of the PC, mode independently. */ | ||
| 61 | |||
| 62 | ARMword | ||
| 63 | ARMul_GetPC (ARMul_State * state) | ||
| 64 | { | ||
| 65 | if (state->Mode > SVC26MODE) | ||
| 66 | return state->Reg[15]; | ||
| 67 | else | ||
| 68 | return R15PC; | ||
| 69 | } | ||
| 70 | |||
| 71 | /* This routine returns the value of the PC, mode independently. */ | ||
| 72 | |||
| 73 | ARMword | ||
| 74 | ARMul_GetNextPC (ARMul_State * state) | ||
| 75 | { | ||
| 76 | if (state->Mode > SVC26MODE) | ||
| 77 | return state->Reg[15] + isize; | ||
| 78 | else | ||
| 79 | return (state->Reg[15] + isize) & R15PCBITS; | ||
| 80 | } | ||
| 81 | |||
| 82 | /* This routine sets the value of the PC. */ | ||
| 83 | |||
| 84 | void | ||
| 85 | ARMul_SetPC (ARMul_State * state, ARMword value) | ||
| 86 | { | ||
| 87 | if (ARMul_MODE32BIT) | ||
| 88 | state->Reg[15] = value & PCBITS; | ||
| 89 | else | ||
| 90 | state->Reg[15] = R15CCINTMODE | (value & R15PCBITS); | ||
| 91 | FLUSHPIPE; | ||
| 92 | } | ||
| 93 | |||
| 94 | /* This routine returns the value of register 15, mode independently. */ | ||
| 95 | |||
| 96 | ARMword | ||
| 97 | ARMul_GetR15 (ARMul_State * state) | ||
| 98 | { | ||
| 99 | if (state->Mode > SVC26MODE) | ||
| 100 | return (state->Reg[15]); | ||
| 101 | else | ||
| 102 | return (R15PC | ECC | ER15INT | EMODE); | ||
| 103 | } | ||
| 104 | |||
| 105 | /* This routine sets the value of Register 15. */ | ||
| 106 | |||
| 107 | void | ||
| 108 | ARMul_SetR15 (ARMul_State * state, ARMword value) | ||
| 109 | { | ||
| 110 | if (ARMul_MODE32BIT) | ||
| 111 | state->Reg[15] = value & PCBITS; | ||
| 112 | else { | ||
| 113 | state->Reg[15] = value; | ||
| 114 | ARMul_R15Altered (state); | ||
| 115 | } | ||
| 116 | FLUSHPIPE; | ||
| 117 | } | ||
| 118 | |||
| 119 | /* This routine returns the value of the CPSR. */ | ||
| 120 | |||
| 121 | ARMword | ||
| 122 | ARMul_GetCPSR (ARMul_State * state) | ||
| 123 | { | ||
| 124 | //chy 2003-08-20: below is from gdb20030716, maybe isn't suitable for system simulator | ||
| 125 | //return (CPSR | state->Cpsr); for gdb20030716 | ||
| 126 | return (CPSR); //had be tested in old skyeye with gdb5.0-5.3 | ||
| 127 | } | ||
| 128 | |||
| 129 | /* This routine sets the value of the CPSR. */ | ||
| 130 | |||
| 131 | void | ||
| 132 | ARMul_SetCPSR (ARMul_State * state, ARMword value) | ||
| 133 | { | ||
| 134 | state->Cpsr = value; | ||
| 135 | ARMul_CPSRAltered (state); | ||
| 136 | } | ||
| 137 | |||
| 138 | /* This routine does all the nasty bits involved in a write to the CPSR, | ||
| 139 | including updating the register bank, given a MSR instruction. */ | ||
| 140 | |||
| 141 | void | ||
| 142 | ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs) | ||
| 143 | { | ||
| 144 | state->Cpsr = ARMul_GetCPSR (state); | ||
| 145 | //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode | ||
| 146 | if (state->Mode != USER26MODE && state->Mode != USER32MODE ) { | ||
| 147 | /* In user mode, only write flags. */ | ||
| 148 | if (BIT (16)) | ||
| 149 | SETPSR_C (state->Cpsr, rhs); | ||
| 150 | if (BIT (17)) | ||
| 151 | SETPSR_X (state->Cpsr, rhs); | ||
| 152 | if (BIT (18)) | ||
| 153 | SETPSR_S (state->Cpsr, rhs); | ||
| 154 | } | ||
| 155 | if (BIT (19)) | ||
| 156 | SETPSR_F (state->Cpsr, rhs); | ||
| 157 | ARMul_CPSRAltered (state); | ||
| 158 | } | ||
| 159 | |||
| 160 | /* Get an SPSR from the specified mode. */ | ||
| 161 | |||
| 162 | ARMword | ||
| 163 | ARMul_GetSPSR (ARMul_State * state, ARMword mode) | ||
| 164 | { | ||
| 165 | ARMword bank = ModeToBank (mode & MODEBITS); | ||
| 166 | |||
| 167 | if (!BANK_CAN_ACCESS_SPSR (bank)) | ||
| 168 | return ARMul_GetCPSR (state); | ||
| 169 | |||
| 170 | return state->Spsr[bank]; | ||
| 171 | } | ||
| 172 | |||
| 173 | /* This routine does a write to an SPSR. */ | ||
| 174 | |||
| 175 | void | ||
| 176 | ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value) | ||
| 177 | { | ||
| 178 | ARMword bank = ModeToBank (mode & MODEBITS); | ||
| 179 | |||
| 180 | if (BANK_CAN_ACCESS_SPSR (bank)) | ||
| 181 | state->Spsr[bank] = value; | ||
| 182 | } | ||
| 183 | |||
| 184 | /* This routine does a write to the current SPSR, given an MSR instruction. */ | ||
| 185 | |||
| 186 | void | ||
| 187 | ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs) | ||
| 188 | { | ||
| 189 | if (BANK_CAN_ACCESS_SPSR (state->Bank)) { | ||
| 190 | if (BIT (16)) | ||
| 191 | SETPSR_C (state->Spsr[state->Bank], rhs); | ||
| 192 | if (BIT (17)) | ||
| 193 | SETPSR_X (state->Spsr[state->Bank], rhs); | ||
| 194 | if (BIT (18)) | ||
| 195 | SETPSR_S (state->Spsr[state->Bank], rhs); | ||
| 196 | if (BIT (19)) | ||
| 197 | SETPSR_F (state->Spsr[state->Bank], rhs); | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | /* This routine updates the state of the emulator after the Cpsr has been | ||
| 202 | changed. Both the processor flags and register bank are updated. */ | ||
| 203 | |||
| 204 | void | ||
| 205 | ARMul_CPSRAltered (ARMul_State * state) | ||
| 206 | { | ||
| 207 | ARMword oldmode; | ||
| 208 | |||
| 209 | if (state->prog32Sig == LOW) | ||
| 210 | state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS); | ||
| 211 | |||
| 212 | oldmode = state->Mode; | ||
| 213 | |||
| 214 | if (state->Mode != (state->Cpsr & MODEBITS)) { | ||
| 215 | state->Mode = | ||
| 216 | ARMul_SwitchMode (state, state->Mode, | ||
| 217 | state->Cpsr & MODEBITS); | ||
| 218 | |||
| 219 | state->NtransSig = (state->Mode & 3) ? HIGH : LOW; | ||
| 220 | } | ||
| 221 | //state->Cpsr &= ~MODEBITS; | ||
| 222 | |||
| 223 | ASSIGNINT (state->Cpsr & INTBITS); | ||
| 224 | //state->Cpsr &= ~INTBITS; | ||
| 225 | ASSIGNN ((state->Cpsr & NBIT) != 0); | ||
| 226 | //state->Cpsr &= ~NBIT; | ||
| 227 | ASSIGNZ ((state->Cpsr & ZBIT) != 0); | ||
| 228 | //state->Cpsr &= ~ZBIT; | ||
| 229 | ASSIGNC ((state->Cpsr & CBIT) != 0); | ||
| 230 | //state->Cpsr &= ~CBIT; | ||
| 231 | ASSIGNV ((state->Cpsr & VBIT) != 0); | ||
| 232 | //state->Cpsr &= ~VBIT; | ||
| 233 | ASSIGNS ((state->Cpsr & SBIT) != 0); | ||
| 234 | //state->Cpsr &= ~SBIT; | ||
| 235 | #ifdef MODET | ||
| 236 | ASSIGNT ((state->Cpsr & TBIT) != 0); | ||
| 237 | //state->Cpsr &= ~TBIT; | ||
| 238 | #endif | ||
| 239 | |||
| 240 | if (oldmode > SVC26MODE) { | ||
| 241 | if (state->Mode <= SVC26MODE) { | ||
| 242 | state->Emulate = CHANGEMODE; | ||
| 243 | state->Reg[15] = ECC | ER15INT | EMODE | R15PC; | ||
| 244 | } | ||
| 245 | } | ||
| 246 | else { | ||
| 247 | if (state->Mode > SVC26MODE) { | ||
| 248 | state->Emulate = CHANGEMODE; | ||
| 249 | state->Reg[15] = R15PC; | ||
| 250 | } | ||
| 251 | else | ||
| 252 | state->Reg[15] = ECC | ER15INT | EMODE | R15PC; | ||
| 253 | } | ||
| 254 | } | ||
| 255 | |||
| 256 | /* This routine updates the state of the emulator after register 15 has | ||
| 257 | been changed. Both the processor flags and register bank are updated. | ||
| 258 | This routine should only be called from a 26 bit mode. */ | ||
| 259 | |||
| 260 | void | ||
| 261 | ARMul_R15Altered (ARMul_State * state) | ||
| 262 | { | ||
| 263 | if (state->Mode != R15MODE) { | ||
| 264 | state->Mode = ARMul_SwitchMode (state, state->Mode, R15MODE); | ||
| 265 | state->NtransSig = (state->Mode & 3) ? HIGH : LOW; | ||
| 266 | } | ||
| 267 | |||
| 268 | if (state->Mode > SVC26MODE) | ||
| 269 | state->Emulate = CHANGEMODE; | ||
| 270 | |||
| 271 | ASSIGNR15INT (R15INT); | ||
| 272 | |||
| 273 | ASSIGNN ((state->Reg[15] & NBIT) != 0); | ||
| 274 | ASSIGNZ ((state->Reg[15] & ZBIT) != 0); | ||
| 275 | ASSIGNC ((state->Reg[15] & CBIT) != 0); | ||
| 276 | ASSIGNV ((state->Reg[15] & VBIT) != 0); | ||
| 277 | } | ||
| 278 | |||
| 279 | /* This routine controls the saving and restoring of registers across mode | ||
| 280 | changes. The regbank matrix is largely unused, only rows 13 and 14 are | ||
| 281 | used across all modes, 8 to 14 are used for FIQ, all others use the USER | ||
| 282 | column. It's easier this way. old and new parameter are modes numbers. | ||
| 283 | Notice the side effect of changing the Bank variable. */ | ||
| 284 | |||
| 285 | ARMword | ||
| 286 | ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode) | ||
| 287 | { | ||
| 288 | unsigned i; | ||
| 289 | ARMword oldbank; | ||
| 290 | ARMword newbank; | ||
| 291 | static int revision_value = 53; | ||
| 292 | |||
| 293 | oldbank = ModeToBank (oldmode); | ||
| 294 | newbank = state->Bank = ModeToBank (newmode); | ||
| 295 | |||
| 296 | /* Do we really need to do it? */ | ||
| 297 | if (oldbank != newbank) { | ||
| 298 | if (oldbank == 3 && newbank == 2) { | ||
| 299 | //printf("icounter is %d PC is %x MODE CHANGED : %d --> %d\n", state->NumInstrs, state->pc, oldbank, newbank); | ||
| 300 | if (state->NumInstrs >= 5832487) { | ||
| 301 | // printf("%d, ", state->NumInstrs + revision_value); | ||
| 302 | // printf("revision_value : %d\n", revision_value); | ||
| 303 | revision_value ++; | ||
| 304 | } | ||
| 305 | } | ||
| 306 | /* Save away the old registers. */ | ||
| 307 | switch (oldbank) { | ||
| 308 | case USERBANK: | ||
| 309 | case IRQBANK: | ||
| 310 | case SVCBANK: | ||
| 311 | case ABORTBANK: | ||
| 312 | case UNDEFBANK: | ||
| 313 | if (newbank == FIQBANK) | ||
| 314 | for (i = 8; i < 13; i++) | ||
| 315 | state->RegBank[USERBANK][i] = | ||
| 316 | state->Reg[i]; | ||
| 317 | state->RegBank[oldbank][13] = state->Reg[13]; | ||
| 318 | state->RegBank[oldbank][14] = state->Reg[14]; | ||
| 319 | break; | ||
| 320 | case FIQBANK: | ||
| 321 | for (i = 8; i < 15; i++) | ||
| 322 | state->RegBank[FIQBANK][i] = state->Reg[i]; | ||
| 323 | break; | ||
| 324 | case DUMMYBANK: | ||
| 325 | for (i = 8; i < 15; i++) | ||
| 326 | state->RegBank[DUMMYBANK][i] = 0; | ||
| 327 | break; | ||
| 328 | default: | ||
| 329 | abort (); | ||
| 330 | } | ||
| 331 | |||
| 332 | /* Restore the new registers. */ | ||
| 333 | switch (newbank) { | ||
| 334 | case USERBANK: | ||
| 335 | case IRQBANK: | ||
| 336 | case SVCBANK: | ||
| 337 | case ABORTBANK: | ||
| 338 | case UNDEFBANK: | ||
| 339 | if (oldbank == FIQBANK) | ||
| 340 | for (i = 8; i < 13; i++) | ||
| 341 | state->Reg[i] = | ||
| 342 | state->RegBank[USERBANK][i]; | ||
| 343 | state->Reg[13] = state->RegBank[newbank][13]; | ||
| 344 | state->Reg[14] = state->RegBank[newbank][14]; | ||
| 345 | break; | ||
| 346 | case FIQBANK: | ||
| 347 | for (i = 8; i < 15; i++) | ||
| 348 | state->Reg[i] = state->RegBank[FIQBANK][i]; | ||
| 349 | break; | ||
| 350 | case DUMMYBANK: | ||
| 351 | for (i = 8; i < 15; i++) | ||
| 352 | state->Reg[i] = 0; | ||
| 353 | break; | ||
| 354 | default: | ||
| 355 | abort (); | ||
| 356 | } | ||
| 357 | } | ||
| 358 | |||
| 359 | return newmode; | ||
| 360 | } | ||
| 361 | |||
| 362 | /* Given a processor mode, this routine returns the | ||
| 363 | register bank that will be accessed in that mode. */ | ||
| 364 | |||
| 365 | static ARMword | ||
| 366 | ModeToBank (ARMword mode) | ||
| 367 | { | ||
| 368 | static ARMword bankofmode[] = { | ||
| 369 | USERBANK, FIQBANK, IRQBANK, SVCBANK, | ||
| 370 | DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, | ||
| 371 | DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, | ||
| 372 | DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, | ||
| 373 | USERBANK, FIQBANK, IRQBANK, SVCBANK, | ||
| 374 | DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK, | ||
| 375 | DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK, | ||
| 376 | DUMMYBANK, DUMMYBANK, DUMMYBANK, SYSTEMBANK | ||
| 377 | }; | ||
| 378 | |||
| 379 | if (mode >= (sizeof (bankofmode) / sizeof (bankofmode[0]))) | ||
| 380 | return DUMMYBANK; | ||
| 381 | |||
| 382 | return bankofmode[mode]; | ||
| 383 | } | ||
| 384 | |||
| 385 | /* Returns the register number of the nth register in a reg list. */ | ||
| 386 | |||
| 387 | unsigned | ||
| 388 | ARMul_NthReg (ARMword instr, unsigned number) | ||
| 389 | { | ||
| 390 | unsigned bit, upto; | ||
| 391 | |||
| 392 | for (bit = 0, upto = 0; upto <= number; bit++) | ||
| 393 | if (BIT (bit)) | ||
| 394 | upto++; | ||
| 395 | |||
| 396 | return (bit - 1); | ||
| 397 | } | ||
| 398 | |||
| 399 | /* Assigns the N and Z flags depending on the value of result. */ | ||
| 400 | |||
| 401 | void | ||
| 402 | ARMul_NegZero (ARMul_State * state, ARMword result) | ||
| 403 | { | ||
| 404 | if (NEG (result)) { | ||
| 405 | SETN; | ||
| 406 | CLEARZ; | ||
| 407 | } | ||
| 408 | else if (result == 0) { | ||
| 409 | CLEARN; | ||
| 410 | SETZ; | ||
| 411 | } | ||
| 412 | else { | ||
| 413 | CLEARN; | ||
| 414 | CLEARZ; | ||
| 415 | } | ||
| 416 | } | ||
| 417 | |||
| 418 | /* Compute whether an addition of A and B, giving RESULT, overflowed. */ | ||
| 419 | |||
| 420 | int | ||
| 421 | AddOverflow (ARMword a, ARMword b, ARMword result) | ||
| 422 | { | ||
| 423 | return ((NEG (a) && NEG (b) && POS (result)) | ||
| 424 | || (POS (a) && POS (b) && NEG (result))); | ||
| 425 | } | ||
| 426 | |||
| 427 | /* Compute whether a subtraction of A and B, giving RESULT, overflowed. */ | ||
| 428 | |||
| 429 | int | ||
| 430 | SubOverflow (ARMword a, ARMword b, ARMword result) | ||
| 431 | { | ||
| 432 | return ((NEG (a) && POS (b) && POS (result)) | ||
| 433 | || (POS (a) && NEG (b) && NEG (result))); | ||
| 434 | } | ||
| 435 | |||
| 436 | /* Assigns the C flag after an addition of a and b to give result. */ | ||
| 437 | |||
| 438 | void | ||
| 439 | ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result) | ||
| 440 | { | ||
| 441 | ASSIGNC ((NEG (a) && NEG (b)) || | ||
| 442 | (NEG (a) && POS (result)) || (NEG (b) && POS (result))); | ||
| 443 | } | ||
| 444 | |||
| 445 | /* Assigns the V flag after an addition of a and b to give result. */ | ||
| 446 | |||
| 447 | void | ||
| 448 | ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result) | ||
| 449 | { | ||
| 450 | ASSIGNV (AddOverflow (a, b, result)); | ||
| 451 | } | ||
| 452 | |||
| 453 | /* Assigns the C flag after an subtraction of a and b to give result. */ | ||
| 454 | |||
| 455 | void | ||
| 456 | ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result) | ||
| 457 | { | ||
| 458 | ASSIGNC ((NEG (a) && POS (b)) || | ||
| 459 | (NEG (a) && POS (result)) || (POS (b) && POS (result))); | ||
| 460 | } | ||
| 461 | |||
| 462 | /* Assigns the V flag after an subtraction of a and b to give result. */ | ||
| 463 | |||
| 464 | void | ||
| 465 | ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result) | ||
| 466 | { | ||
| 467 | ASSIGNV (SubOverflow (a, b, result)); | ||
| 468 | } | ||
| 469 | |||
| 470 | /* This function does the work of generating the addresses used in an | ||
| 471 | LDC instruction. The code here is always post-indexed, it's up to the | ||
| 472 | caller to get the input address correct and to handle base register | ||
| 473 | modification. It also handles the Busy-Waiting. */ | ||
| 474 | |||
| 475 | void | ||
| 476 | ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address) | ||
| 477 | { | ||
| 478 | unsigned cpab; | ||
| 479 | ARMword data; | ||
| 480 | |||
| 481 | UNDEF_LSCPCBaseWb; | ||
| 482 | //printf("SKYEYE ARMul_LDC, CPnum is %x, instr %x, addr %x\n",CPNum, instr, address); | ||
| 483 | /*chy 2004-05-23 should update this function in the future,should concern dataabort*/ | ||
| 484 | // chy 2004-05-25 , fix it now,so needn't printf | ||
| 485 | // printf("SKYEYE ARMul_LDC, should update this function!!!!!\n"); | ||
| 486 | //exit(-1); | ||
| 487 | |||
| 488 | if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||
| 489 | /* | ||
| 490 | printf | ||
| 491 | ("SKYEYE ARMul_LDC,NOT ALLOW, underinstr, CPnum is %x, instr %x, addr %x\n", | ||
| 492 | CPNum, instr, address); | ||
| 493 | */ | ||
| 494 | ARMul_UndefInstr (state, instr); | ||
| 495 | return; | ||
| 496 | } | ||
| 497 | |||
| 498 | if (ADDREXCEPT (address)) | ||
| 499 | INTERNALABORT (address); | ||
| 500 | |||
| 501 | cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0); | ||
| 502 | while (cpab == ARMul_BUSY) { | ||
| 503 | ARMul_Icycles (state, 1, 0); | ||
| 504 | |||
| 505 | if (IntPending (state)) { | ||
| 506 | cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT, | ||
| 507 | instr, 0); | ||
| 508 | return; | ||
| 509 | } | ||
| 510 | else | ||
| 511 | cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr, | ||
| 512 | 0); | ||
| 513 | } | ||
| 514 | if (cpab == ARMul_CANT) { | ||
| 515 | /* | ||
| 516 | printf | ||
| 517 | ("SKYEYE ARMul_LDC,NOT CAN, underinstr, CPnum is %x, instr %x, addr %x\n", | ||
| 518 | CPNum, instr, address); | ||
| 519 | */ | ||
| 520 | CPTAKEABORT; | ||
| 521 | return; | ||
| 522 | } | ||
| 523 | |||
| 524 | cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0); | ||
| 525 | data = ARMul_LoadWordN (state, address); | ||
| 526 | //chy 2004-05-25 | ||
| 527 | if (state->abortSig || state->Aborted) | ||
| 528 | goto L_ldc_takeabort; | ||
| 529 | |||
| 530 | BUSUSEDINCPCN; | ||
| 531 | //chy 2004-05-25 | ||
| 532 | /* | ||
| 533 | if (BIT (21)) | ||
| 534 | LSBase = state->Base; | ||
| 535 | */ | ||
| 536 | |||
| 537 | cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data); | ||
| 538 | |||
| 539 | while (cpab == ARMul_INC) { | ||
| 540 | address += 4; | ||
| 541 | data = ARMul_LoadWordN (state, address); | ||
| 542 | //chy 2004-05-25 | ||
| 543 | if (state->abortSig || state->Aborted) | ||
| 544 | goto L_ldc_takeabort; | ||
| 545 | |||
| 546 | cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data); | ||
| 547 | } | ||
| 548 | |||
| 549 | //chy 2004-05-25 | ||
| 550 | L_ldc_takeabort: | ||
| 551 | if (BIT (21)) { | ||
| 552 | if (! | ||
| 553 | ((state->abortSig || state->Aborted) | ||
| 554 | && state->lateabtSig == LOW)) | ||
| 555 | LSBase = state->Base; | ||
| 556 | } | ||
| 557 | |||
| 558 | if (state->abortSig || state->Aborted) | ||
| 559 | TAKEABORT; | ||
| 560 | } | ||
| 561 | |||
| 562 | /* This function does the work of generating the addresses used in an | ||
| 563 | STC instruction. The code here is always post-indexed, it's up to the | ||
| 564 | caller to get the input address correct and to handle base register | ||
| 565 | modification. It also handles the Busy-Waiting. */ | ||
| 566 | |||
| 567 | void | ||
| 568 | ARMul_STC (ARMul_State * state, ARMword instr, ARMword address) | ||
| 569 | { | ||
| 570 | unsigned cpab; | ||
| 571 | ARMword data; | ||
| 572 | |||
| 573 | UNDEF_LSCPCBaseWb; | ||
| 574 | |||
| 575 | //printf("SKYEYE ARMul_STC, CPnum is %x, instr %x, addr %x\n",CPNum, instr, address); | ||
| 576 | /*chy 2004-05-23 should update this function in the future,should concern dataabort */ | ||
| 577 | // skyeye_instr_debug=0;printf("SKYEYE debug end!!!!\n"); | ||
| 578 | // chy 2004-05-25 , fix it now,so needn't printf | ||
| 579 | // printf("SKYEYE ARMul_STC, should update this function!!!!!\n"); | ||
| 580 | |||
| 581 | //exit(-1); | ||
| 582 | if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||
| 583 | /* | ||
| 584 | printf | ||
| 585 | ("SKYEYE ARMul_STC,NOT ALLOW, undefinstr, CPnum is %x, instr %x, addr %x\n", | ||
| 586 | CPNum, instr, address); | ||
| 587 | */ | ||
| 588 | ARMul_UndefInstr (state, instr); | ||
| 589 | return; | ||
| 590 | } | ||
| 591 | |||
| 592 | if (ADDREXCEPT (address) || VECTORACCESS (address)) | ||
| 593 | INTERNALABORT (address); | ||
| 594 | |||
| 595 | cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data); | ||
| 596 | while (cpab == ARMul_BUSY) { | ||
| 597 | ARMul_Icycles (state, 1, 0); | ||
| 598 | if (IntPending (state)) { | ||
| 599 | cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT, | ||
| 600 | instr, 0); | ||
| 601 | return; | ||
| 602 | } | ||
| 603 | else | ||
| 604 | cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr, | ||
| 605 | &data); | ||
| 606 | } | ||
| 607 | |||
| 608 | if (cpab == ARMul_CANT) { | ||
| 609 | /* | ||
| 610 | printf | ||
| 611 | ("SKYEYE ARMul_STC,CANT, undefinstr, CPnum is %x, instr %x, addr %x\n", | ||
| 612 | CPNum, instr, address); | ||
| 613 | */ | ||
| 614 | CPTAKEABORT; | ||
| 615 | return; | ||
| 616 | } | ||
| 617 | #ifndef MODE32 | ||
| 618 | if (ADDREXCEPT (address) || VECTORACCESS (address)) | ||
| 619 | INTERNALABORT (address); | ||
| 620 | #endif | ||
| 621 | BUSUSEDINCPCN; | ||
| 622 | //chy 2004-05-25 | ||
| 623 | /* | ||
| 624 | if (BIT (21)) | ||
| 625 | LSBase = state->Base; | ||
| 626 | */ | ||
| 627 | cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data); | ||
| 628 | ARMul_StoreWordN (state, address, data); | ||
| 629 | //chy 2004-05-25 | ||
| 630 | if (state->abortSig || state->Aborted) | ||
| 631 | goto L_stc_takeabort; | ||
| 632 | |||
| 633 | while (cpab == ARMul_INC) { | ||
| 634 | address += 4; | ||
| 635 | cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data); | ||
| 636 | ARMul_StoreWordN (state, address, data); | ||
| 637 | //chy 2004-05-25 | ||
| 638 | if (state->abortSig || state->Aborted) | ||
| 639 | goto L_stc_takeabort; | ||
| 640 | } | ||
| 641 | //chy 2004-05-25 | ||
| 642 | L_stc_takeabort: | ||
| 643 | if (BIT (21)) { | ||
| 644 | if (! | ||
| 645 | ((state->abortSig || state->Aborted) | ||
| 646 | && state->lateabtSig == LOW)) | ||
| 647 | LSBase = state->Base; | ||
| 648 | } | ||
| 649 | |||
| 650 | if (state->abortSig || state->Aborted) | ||
| 651 | TAKEABORT; | ||
| 652 | } | ||
| 653 | |||
| 654 | /* This function does the Busy-Waiting for an MCR instruction. */ | ||
| 655 | |||
| 656 | void | ||
| 657 | ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source) | ||
| 658 | { | ||
| 659 | unsigned cpab; | ||
| 660 | |||
| 661 | //printf("SKYEYE ARMul_MCR, CPnum is %x, source %x\n",CPNum, source); | ||
| 662 | if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||
| 663 | //chy 2004-07-19 should fix in the future ????!!!! | ||
| 664 | //printf("SKYEYE ARMul_MCR, ACCESS_not ALLOWed, UndefinedInstr CPnum is %x, source %x\n",CPNum, source); | ||
| 665 | ARMul_UndefInstr (state, instr); | ||
| 666 | return; | ||
| 667 | } | ||
| 668 | |||
| 669 | cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source); | ||
| 670 | |||
| 671 | while (cpab == ARMul_BUSY) { | ||
| 672 | ARMul_Icycles (state, 1, 0); | ||
| 673 | |||
| 674 | if (IntPending (state)) { | ||
| 675 | cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, | ||
| 676 | instr, 0); | ||
| 677 | return; | ||
| 678 | } | ||
| 679 | else | ||
| 680 | cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, | ||
| 681 | source); | ||
| 682 | } | ||
| 683 | |||
| 684 | if (cpab == ARMul_CANT) { | ||
| 685 | printf ("SKYEYE ARMul_MCR, CANT, UndefinedInstr %x CPnum is %x, source %x\n", instr, CPNum, source); | ||
| 686 | ARMul_Abort (state, ARMul_UndefinedInstrV); | ||
| 687 | } | ||
| 688 | else { | ||
| 689 | BUSUSEDINCPCN; | ||
| 690 | ARMul_Ccycles (state, 1, 0); | ||
| 691 | } | ||
| 692 | } | ||
| 693 | |||
| 694 | /* This function does the Busy-Waiting for an MCRR instruction. */ | ||
| 695 | |||
| 696 | void | ||
| 697 | ARMul_MCRR (ARMul_State * state, ARMword instr, ARMword source1, ARMword source2) | ||
| 698 | { | ||
| 699 | unsigned cpab; | ||
| 700 | |||
| 701 | if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||
| 702 | ARMul_UndefInstr (state, instr); | ||
| 703 | return; | ||
| 704 | } | ||
| 705 | |||
| 706 | cpab = (state->MCRR[CPNum]) (state, ARMul_FIRST, instr, source1, source2); | ||
| 707 | |||
| 708 | while (cpab == ARMul_BUSY) { | ||
| 709 | ARMul_Icycles (state, 1, 0); | ||
| 710 | |||
| 711 | if (IntPending (state)) { | ||
| 712 | cpab = (state->MCRR[CPNum]) (state, ARMul_INTERRUPT, | ||
| 713 | instr, 0, 0); | ||
| 714 | return; | ||
| 715 | } | ||
| 716 | else | ||
| 717 | cpab = (state->MCRR[CPNum]) (state, ARMul_BUSY, instr, | ||
| 718 | source1, source2); | ||
| 719 | } | ||
| 720 | if (cpab == ARMul_CANT) { | ||
| 721 | printf ("In %s, CoProcesscor returned CANT, CPnum is %x, instr %x, source %x %x\n", __FUNCTION__, CPNum, instr, source1, source2); | ||
| 722 | ARMul_Abort (state, ARMul_UndefinedInstrV); | ||
| 723 | } | ||
| 724 | else { | ||
| 725 | BUSUSEDINCPCN; | ||
| 726 | ARMul_Ccycles (state, 1, 0); | ||
| 727 | } | ||
| 728 | } | ||
| 729 | |||
| 730 | /* This function does the Busy-Waiting for an MRC instruction. */ | ||
| 731 | |||
| 732 | ARMword | ||
| 733 | ARMul_MRC (ARMul_State * state, ARMword instr) | ||
| 734 | { | ||
| 735 | unsigned cpab; | ||
| 736 | ARMword result = 0; | ||
| 737 | |||
| 738 | //printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr); | ||
| 739 | if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||
| 740 | //chy 2004-07-19 should fix in the future????!!!! | ||
| 741 | //printf("SKYEYE ARMul_MRC,NOT ALLOWed UndefInstr CPnum is %x, instr %x\n",CPNum, instr); | ||
| 742 | ARMul_UndefInstr (state, instr); | ||
| 743 | return -1; | ||
| 744 | } | ||
| 745 | |||
| 746 | cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result); | ||
| 747 | while (cpab == ARMul_BUSY) { | ||
| 748 | ARMul_Icycles (state, 1, 0); | ||
| 749 | if (IntPending (state)) { | ||
| 750 | cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, | ||
| 751 | instr, 0); | ||
| 752 | return (0); | ||
| 753 | } | ||
| 754 | else | ||
| 755 | cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, | ||
| 756 | &result); | ||
| 757 | } | ||
| 758 | if (cpab == ARMul_CANT) { | ||
| 759 | printf ("SKYEYE ARMul_MRC,CANT UndefInstr CPnum is %x, instr %x\n", CPNum, instr); | ||
| 760 | ARMul_Abort (state, ARMul_UndefinedInstrV); | ||
| 761 | /* Parent will destroy the flags otherwise. */ | ||
| 762 | result = ECC; | ||
| 763 | } | ||
| 764 | else { | ||
| 765 | BUSUSEDINCPCN; | ||
| 766 | ARMul_Ccycles (state, 1, 0); | ||
| 767 | ARMul_Icycles (state, 1, 0); | ||
| 768 | } | ||
| 769 | |||
| 770 | return result; | ||
| 771 | } | ||
| 772 | |||
| 773 | /* This function does the Busy-Waiting for an MRRC instruction. (to verify) */ | ||
| 774 | |||
| 775 | void | ||
| 776 | ARMul_MRRC (ARMul_State * state, ARMword instr, ARMword * dest1, ARMword * dest2) | ||
| 777 | { | ||
| 778 | unsigned cpab; | ||
| 779 | ARMword result1 = 0; | ||
| 780 | ARMword result2 = 0; | ||
| 781 | |||
| 782 | if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||
| 783 | ARMul_UndefInstr (state, instr); | ||
| 784 | return; | ||
| 785 | } | ||
| 786 | |||
| 787 | cpab = (state->MRRC[CPNum]) (state, ARMul_FIRST, instr, &result1, &result2); | ||
| 788 | while (cpab == ARMul_BUSY) { | ||
| 789 | ARMul_Icycles (state, 1, 0); | ||
| 790 | if (IntPending (state)) { | ||
| 791 | cpab = (state->MRRC[CPNum]) (state, ARMul_INTERRUPT, | ||
| 792 | instr, 0, 0); | ||
| 793 | return; | ||
| 794 | } | ||
| 795 | else | ||
| 796 | cpab = (state->MRRC[CPNum]) (state, ARMul_BUSY, instr, | ||
| 797 | &result1, &result2); | ||
| 798 | } | ||
| 799 | if (cpab == ARMul_CANT) { | ||
| 800 | printf ("In %s, CoProcesscor returned CANT, CPnum is %x, instr %x\n", __FUNCTION__, CPNum, instr); | ||
| 801 | ARMul_Abort (state, ARMul_UndefinedInstrV); | ||
| 802 | } | ||
| 803 | else { | ||
| 804 | BUSUSEDINCPCN; | ||
| 805 | ARMul_Ccycles (state, 1, 0); | ||
| 806 | ARMul_Icycles (state, 1, 0); | ||
| 807 | } | ||
| 808 | |||
| 809 | *dest1 = result1; | ||
| 810 | *dest2 = result2; | ||
| 811 | } | ||
| 812 | |||
| 813 | /* This function does the Busy-Waiting for an CDP instruction. */ | ||
| 814 | |||
| 815 | void | ||
| 816 | ARMul_CDP (ARMul_State * state, ARMword instr) | ||
| 817 | { | ||
| 818 | unsigned cpab; | ||
| 819 | |||
| 820 | if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||
| 821 | ARMul_UndefInstr (state, instr); | ||
| 822 | return; | ||
| 823 | } | ||
| 824 | cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr); | ||
| 825 | while (cpab == ARMul_BUSY) { | ||
| 826 | ARMul_Icycles (state, 1, 0); | ||
| 827 | if (IntPending (state)) { | ||
| 828 | cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT, | ||
| 829 | instr); | ||
| 830 | return; | ||
| 831 | } | ||
| 832 | else | ||
| 833 | cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr); | ||
| 834 | } | ||
| 835 | if (cpab == ARMul_CANT) | ||
| 836 | ARMul_Abort (state, ARMul_UndefinedInstrV); | ||
| 837 | else | ||
| 838 | BUSUSEDN; | ||
| 839 | } | ||
| 840 | |||
| 841 | /* This function handles Undefined instructions, as CP isntruction. */ | ||
| 842 | |||
| 843 | void | ||
| 844 | ARMul_UndefInstr (ARMul_State * state, ARMword instr) | ||
| 845 | { | ||
| 846 | ERROR_LOG(ARM11, "Undefined instruction!! Instr: 0x%x", instr); | ||
| 847 | ARMul_Abort (state, ARMul_UndefinedInstrV); | ||
| 848 | } | ||
| 849 | |||
| 850 | /* Return TRUE if an interrupt is pending, FALSE otherwise. */ | ||
| 851 | |||
| 852 | unsigned | ||
| 853 | IntPending (ARMul_State * state) | ||
| 854 | { | ||
| 855 | /* Any exceptions. */ | ||
| 856 | if (state->NresetSig == LOW) { | ||
| 857 | ARMul_Abort (state, ARMul_ResetV); | ||
| 858 | return TRUE; | ||
| 859 | } | ||
| 860 | else if (!state->NfiqSig && !FFLAG) { | ||
| 861 | ARMul_Abort (state, ARMul_FIQV); | ||
| 862 | return TRUE; | ||
| 863 | } | ||
| 864 | else if (!state->NirqSig && !IFLAG) { | ||
| 865 | ARMul_Abort (state, ARMul_IRQV); | ||
| 866 | return TRUE; | ||
| 867 | } | ||
| 868 | |||
| 869 | return FALSE; | ||
| 870 | } | ||
| 871 | |||
| 872 | /* Align a word access to a non word boundary. */ | ||
| 873 | |||
| 874 | ARMword | ||
| 875 | ARMul_Align (ARMul_State *state, ARMword address, ARMword data) | ||
| 876 | { | ||
| 877 | /* This code assumes the address is really unaligned, | ||
| 878 | as a shift by 32 is undefined in C. */ | ||
| 879 | |||
| 880 | address = (address & 3) << 3; /* Get the word address. */ | ||
| 881 | return ((data >> address) | (data << (32 - address))); /* rot right */ | ||
| 882 | } | ||
| 883 | |||
| 884 | /* This routine is used to call another routine after a certain number of | ||
| 885 | cycles have been executed. The first parameter is the number of cycles | ||
| 886 | delay before the function is called, the second argument is a pointer | ||
| 887 | to the function. A delay of zero doesn't work, just call the function. */ | ||
| 888 | |||
| 889 | void | ||
| 890 | ARMul_ScheduleEvent (ARMul_State * state, unsigned int delay, | ||
| 891 | unsigned (*what) (ARMul_State *)) | ||
| 892 | { | ||
| 893 | unsigned int when; | ||
| 894 | struct EventNode *event; | ||
| 895 | |||
| 896 | if (state->EventSet++ == 0) | ||
| 897 | state->Now = ARMul_Time (state); | ||
| 898 | when = (state->Now + delay) % EVENTLISTSIZE; | ||
| 899 | event = (struct EventNode *) malloc (sizeof (struct EventNode)); | ||
| 900 | |||
| 901 | _dbg_assert_msg_(ARM11, event, "SKYEYE:ARMul_ScheduleEvent: malloc event error\n"); | ||
| 902 | |||
| 903 | event->func = what; | ||
| 904 | event->next = *(state->EventPtr + when); | ||
| 905 | *(state->EventPtr + when) = event; | ||
| 906 | } | ||
| 907 | |||
| 908 | /* This routine is called at the beginning of | ||
| 909 | every cycle, to envoke scheduled events. */ | ||
| 910 | |||
| 911 | void | ||
| 912 | ARMul_EnvokeEvent (ARMul_State * state) | ||
| 913 | { | ||
| 914 | static unsigned int then; | ||
| 915 | |||
| 916 | then = state->Now; | ||
| 917 | state->Now = ARMul_Time (state) % EVENTLISTSIZE; | ||
| 918 | if (then < state->Now) | ||
| 919 | /* Schedule events. */ | ||
| 920 | EnvokeList (state, then, state->Now); | ||
| 921 | else if (then > state->Now) { | ||
| 922 | /* Need to wrap around the list. */ | ||
| 923 | EnvokeList (state, then, EVENTLISTSIZE - 1L); | ||
| 924 | EnvokeList (state, 0L, state->Now); | ||
| 925 | } | ||
| 926 | } | ||
| 927 | |||
| 928 | /* Envokes all the entries in a range. */ | ||
| 929 | |||
| 930 | static void | ||
| 931 | EnvokeList (ARMul_State * state, unsigned int from, unsigned int to) | ||
| 932 | { | ||
| 933 | for (; from <= to; from++) { | ||
| 934 | struct EventNode *anevent; | ||
| 935 | |||
| 936 | anevent = *(state->EventPtr + from); | ||
| 937 | while (anevent) { | ||
| 938 | (anevent->func) (state); | ||
| 939 | state->EventSet--; | ||
| 940 | anevent = anevent->next; | ||
| 941 | } | ||
| 942 | *(state->EventPtr + from) = NULL; | ||
| 943 | } | ||
| 944 | } | ||
| 945 | |||
| 946 | /* This routine is returns the number of clock ticks since the last reset. */ | ||
| 947 | |||
| 948 | unsigned int | ||
| 949 | ARMul_Time (ARMul_State * state) | ||
| 950 | { | ||
| 951 | return (state->NumScycles + state->NumNcycles + | ||
| 952 | state->NumIcycles + state->NumCcycles + state->NumFcycles); | ||
| 953 | } | ||
diff --git a/src/core/src/arm/armvirt.cpp b/src/core/src/arm/armvirt.cpp new file mode 100644 index 000000000..a072b73be --- /dev/null +++ b/src/core/src/arm/armvirt.cpp | |||
| @@ -0,0 +1,680 @@ | |||
| 1 | /* armvirt.c -- ARMulator virtual memory interace: ARM6 Instruction Emulator. | ||
| 2 | Copyright (C) 1994 Advanced RISC Machines Ltd. | ||
| 3 | |||
| 4 | This program is free software; you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation; either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program; if not, write to the Free Software | ||
| 16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
| 17 | |||
| 18 | /* This file contains a complete ARMulator memory model, modelling a | ||
| 19 | "virtual memory" system. A much simpler model can be found in armfast.c, | ||
| 20 | and that model goes faster too, but has a fixed amount of memory. This | ||
| 21 | model's memory has 64K pages, allocated on demand from a 64K entry page | ||
| 22 | table. The routines PutWord and GetWord implement this. Pages are never | ||
| 23 | freed as they might be needed again. A single area of memory may be | ||
| 24 | defined to generate aborts. */ | ||
| 25 | |||
| 26 | #include "armdefs.h" | ||
| 27 | #include "skyeye_defs.h" | ||
| 28 | //#include "code_cov.h" | ||
| 29 | |||
| 30 | #ifdef VALIDATE /* for running the validate suite */ | ||
| 31 | #define TUBE 48 * 1024 * 1024 /* write a char on the screen */ | ||
| 32 | #define ABORTS 1 | ||
| 33 | #endif | ||
| 34 | |||
| 35 | /* #define ABORTS */ | ||
| 36 | |||
| 37 | #ifdef ABORTS /* the memory system will abort */ | ||
| 38 | /* For the old test suite Abort between 32 Kbytes and 32 Mbytes | ||
| 39 | For the new test suite Abort between 8 Mbytes and 26 Mbytes */ | ||
| 40 | /* #define LOWABORT 32 * 1024 | ||
| 41 | #define HIGHABORT 32 * 1024 * 1024 */ | ||
| 42 | #define LOWABORT 8 * 1024 * 1024 | ||
| 43 | #define HIGHABORT 26 * 1024 * 1024 | ||
| 44 | |||
| 45 | #endif | ||
| 46 | |||
| 47 | #define NUMPAGES 64 * 1024 | ||
| 48 | #define PAGESIZE 64 * 1024 | ||
| 49 | #define PAGEBITS 16 | ||
| 50 | #define OFFSETBITS 0xffff | ||
| 51 | //chy 2003-08-19: seems no use ???? | ||
| 52 | int SWI_vector_installed = FALSE; | ||
| 53 | extern ARMword skyeye_cachetype; | ||
| 54 | |||
| 55 | /***************************************************************************\ | ||
| 56 | * Get a byte into Virtual Memory, maybe allocating the page * | ||
| 57 | \***************************************************************************/ | ||
| 58 | static fault_t | ||
| 59 | GetByte (ARMul_State * state, ARMword address, ARMword * data) | ||
| 60 | { | ||
| 61 | fault_t fault; | ||
| 62 | |||
| 63 | fault = mmu_read_byte (state, address, data); | ||
| 64 | if (fault) { | ||
| 65 | //chy 2003-07-11: sometime has fault, but linux can continue running !!!!???? | ||
| 66 | // printf("SKYEYE: GetByte fault %d \n", fault); | ||
| 67 | } | ||
| 68 | return fault; | ||
| 69 | } | ||
| 70 | |||
| 71 | /***************************************************************************\ | ||
| 72 | * Get a halfword into Virtual Memory, maybe allocating the page * | ||
| 73 | \***************************************************************************/ | ||
| 74 | static fault_t | ||
| 75 | GetHalfWord (ARMul_State * state, ARMword address, ARMword * data) | ||
| 76 | { | ||
| 77 | fault_t fault; | ||
| 78 | |||
| 79 | fault = mmu_read_halfword (state, address, data); | ||
| 80 | if (fault) { | ||
| 81 | //chy 2003-07-11: sometime has fault, but linux can continue running !!!!???? | ||
| 82 | // printf("SKYEYE: GetHalfWord fault %d \n", fault); | ||
| 83 | } | ||
| 84 | return fault; | ||
| 85 | } | ||
| 86 | |||
| 87 | /***************************************************************************\ | ||
| 88 | * Get a Word from Virtual Memory, maybe allocating the page * | ||
| 89 | \***************************************************************************/ | ||
| 90 | |||
| 91 | static fault_t | ||
| 92 | GetWord (ARMul_State * state, ARMword address, ARMword * data) | ||
| 93 | { | ||
| 94 | fault_t fault; | ||
| 95 | |||
| 96 | fault = mmu_read_word (state, address, data); | ||
| 97 | if (fault) { | ||
| 98 | //chy 2003-07-11: sometime has fault, but linux can continue running !!!!???? | ||
| 99 | #if 0 | ||
| 100 | /* XXX */ extern int hack; | ||
| 101 | hack = 1; | ||
| 102 | #endif | ||
| 103 | #if 0 | ||
| 104 | printf ("mmu_read_word at 0x%08x: ", address); | ||
| 105 | switch (fault) { | ||
| 106 | case ALIGNMENT_FAULT: | ||
| 107 | printf ("ALIGNMENT_FAULT"); | ||
| 108 | break; | ||
| 109 | case SECTION_TRANSLATION_FAULT: | ||
| 110 | printf ("SECTION_TRANSLATION_FAULT"); | ||
| 111 | break; | ||
| 112 | case PAGE_TRANSLATION_FAULT: | ||
| 113 | printf ("PAGE_TRANSLATION_FAULT"); | ||
| 114 | break; | ||
| 115 | case SECTION_DOMAIN_FAULT: | ||
| 116 | printf ("SECTION_DOMAIN_FAULT"); | ||
| 117 | break; | ||
| 118 | case SECTION_PERMISSION_FAULT: | ||
| 119 | printf ("SECTION_PERMISSION_FAULT"); | ||
| 120 | break; | ||
| 121 | case SUBPAGE_PERMISSION_FAULT: | ||
| 122 | printf ("SUBPAGE_PERMISSION_FAULT"); | ||
| 123 | break; | ||
| 124 | default: | ||
| 125 | printf ("Unrecognized fault number!"); | ||
| 126 | } | ||
| 127 | printf ("\tpc = 0x%08x\n", state->Reg[15]); | ||
| 128 | #endif | ||
| 129 | } | ||
| 130 | return fault; | ||
| 131 | } | ||
| 132 | |||
| 133 | //2003-07-10 chy: lyh change | ||
| 134 | /****************************************************************************\ | ||
| 135 | * Load a Instrion Word into Virtual Memory * | ||
| 136 | \****************************************************************************/ | ||
| 137 | static fault_t | ||
| 138 | LoadInstr (ARMul_State * state, ARMword address, ARMword * instr) | ||
| 139 | { | ||
| 140 | fault_t fault; | ||
| 141 | fault = mmu_load_instr (state, address, instr); | ||
| 142 | return fault; | ||
| 143 | //if (fault) | ||
| 144 | // log_msg("load_instr fault = %d, address = %x\n", fault, address); | ||
| 145 | } | ||
| 146 | |||
| 147 | /***************************************************************************\ | ||
| 148 | * Put a byte into Virtual Memory, maybe allocating the page * | ||
| 149 | \***************************************************************************/ | ||
| 150 | static fault_t | ||
| 151 | PutByte (ARMul_State * state, ARMword address, ARMword data) | ||
| 152 | { | ||
| 153 | fault_t fault; | ||
| 154 | |||
| 155 | fault = mmu_write_byte (state, address, data); | ||
| 156 | if (fault) { | ||
| 157 | //chy 2003-07-11: sometime has fault, but linux can continue running !!!!???? | ||
| 158 | // printf("SKYEYE: PutByte fault %d \n", fault); | ||
| 159 | } | ||
| 160 | return fault; | ||
| 161 | } | ||
| 162 | |||
| 163 | /***************************************************************************\ | ||
| 164 | * Put a halfword into Virtual Memory, maybe allocating the page * | ||
| 165 | \***************************************************************************/ | ||
| 166 | static fault_t | ||
| 167 | PutHalfWord (ARMul_State * state, ARMword address, ARMword data) | ||
| 168 | { | ||
| 169 | fault_t fault; | ||
| 170 | |||
| 171 | fault = mmu_write_halfword (state, address, data); | ||
| 172 | if (fault) { | ||
| 173 | //chy 2003-07-11: sometime has fault, but linux can continue running !!!!???? | ||
| 174 | // printf("SKYEYE: PutHalfWord fault %d \n", fault); | ||
| 175 | } | ||
| 176 | return fault; | ||
| 177 | } | ||
| 178 | |||
| 179 | /***************************************************************************\ | ||
| 180 | * Put a Word into Virtual Memory, maybe allocating the page * | ||
| 181 | \***************************************************************************/ | ||
| 182 | |||
| 183 | static fault_t | ||
| 184 | PutWord (ARMul_State * state, ARMword address, ARMword data) | ||
| 185 | { | ||
| 186 | fault_t fault; | ||
| 187 | |||
| 188 | fault = mmu_write_word (state, address, data); | ||
| 189 | if (fault) { | ||
| 190 | //chy 2003-07-11: sometime has fault, but linux can continue running !!!!???? | ||
| 191 | #if 0 | ||
| 192 | /* XXX */ extern int hack; | ||
| 193 | hack = 1; | ||
| 194 | #endif | ||
| 195 | #if 0 | ||
| 196 | printf ("mmu_write_word at 0x%08x: ", address); | ||
| 197 | switch (fault) { | ||
| 198 | case ALIGNMENT_FAULT: | ||
| 199 | printf ("ALIGNMENT_FAULT"); | ||
| 200 | break; | ||
| 201 | case SECTION_TRANSLATION_FAULT: | ||
| 202 | printf ("SECTION_TRANSLATION_FAULT"); | ||
| 203 | break; | ||
| 204 | case PAGE_TRANSLATION_FAULT: | ||
| 205 | printf ("PAGE_TRANSLATION_FAULT"); | ||
| 206 | break; | ||
| 207 | case SECTION_DOMAIN_FAULT: | ||
| 208 | printf ("SECTION_DOMAIN_FAULT"); | ||
| 209 | break; | ||
| 210 | case SECTION_PERMISSION_FAULT: | ||
| 211 | printf ("SECTION_PERMISSION_FAULT"); | ||
| 212 | break; | ||
| 213 | case SUBPAGE_PERMISSION_FAULT: | ||
| 214 | printf ("SUBPAGE_PERMISSION_FAULT"); | ||
| 215 | break; | ||
| 216 | default: | ||
| 217 | printf ("Unrecognized fault number!"); | ||
| 218 | } | ||
| 219 | printf ("\tpc = 0x%08x\n", state->Reg[15]); | ||
| 220 | #endif | ||
| 221 | } | ||
| 222 | return fault; | ||
| 223 | } | ||
| 224 | |||
| 225 | /***************************************************************************\ | ||
| 226 | * Initialise the memory interface * | ||
| 227 | \***************************************************************************/ | ||
| 228 | |||
| 229 | unsigned | ||
| 230 | ARMul_MemoryInit (ARMul_State * state, unsigned int initmemsize) | ||
| 231 | { | ||
| 232 | return TRUE; | ||
| 233 | } | ||
| 234 | |||
| 235 | /***************************************************************************\ | ||
| 236 | * Remove the memory interface * | ||
| 237 | \***************************************************************************/ | ||
| 238 | |||
| 239 | void | ||
| 240 | ARMul_MemoryExit (ARMul_State * state) | ||
| 241 | { | ||
| 242 | } | ||
| 243 | |||
| 244 | /***************************************************************************\ | ||
| 245 | * ReLoad Instruction * | ||
| 246 | \***************************************************************************/ | ||
| 247 | |||
| 248 | ARMword | ||
| 249 | ARMul_ReLoadInstr (ARMul_State * state, ARMword address, ARMword isize) | ||
| 250 | { | ||
| 251 | ARMword data; | ||
| 252 | fault_t fault; | ||
| 253 | |||
| 254 | #ifdef ABORTS | ||
| 255 | if (address >= LOWABORT && address < HIGHABORT) { | ||
| 256 | ARMul_PREFETCHABORT (address); | ||
| 257 | return ARMul_ABORTWORD; | ||
| 258 | } | ||
| 259 | else { | ||
| 260 | ARMul_CLEARABORT; | ||
| 261 | } | ||
| 262 | #endif | ||
| 263 | #if 0 | ||
| 264 | /* do profiling for code coverage */ | ||
| 265 | if (skyeye_config.code_cov.prof_on) | ||
| 266 | cov_prof(EXEC_FLAG, address); | ||
| 267 | #endif | ||
| 268 | #if 1 | ||
| 269 | if ((isize == 2) && (address & 0x2)) { | ||
| 270 | ARMword lo, hi; | ||
| 271 | if (!(skyeye_cachetype == INSTCACHE)) | ||
| 272 | fault = GetHalfWord (state, address, &lo); | ||
| 273 | else | ||
| 274 | fault = LoadInstr (state, address, &lo); | ||
| 275 | #if 0 | ||
| 276 | if (!fault) { | ||
| 277 | if (!(skyeye_cachetype == INSTCACHE)) | ||
| 278 | fault = GetHalfWord (state, address + isize, &hi); | ||
| 279 | else | ||
| 280 | fault = LoadInstr (state, address + isize, &hi); | ||
| 281 | |||
| 282 | } | ||
| 283 | #endif | ||
| 284 | if (fault) { | ||
| 285 | ARMul_PREFETCHABORT (address); | ||
| 286 | return ARMul_ABORTWORD; | ||
| 287 | } | ||
| 288 | else { | ||
| 289 | ARMul_CLEARABORT; | ||
| 290 | } | ||
| 291 | return lo; | ||
| 292 | #if 0 | ||
| 293 | if (state->bigendSig == HIGH) | ||
| 294 | return (lo << 16) | (hi >> 16); | ||
| 295 | else | ||
| 296 | return ((hi & 0xFFFF) << 16) | (lo >> 16); | ||
| 297 | #endif | ||
| 298 | } | ||
| 299 | #endif | ||
| 300 | if (!(skyeye_cachetype == INSTCACHE)) | ||
| 301 | fault = GetWord (state, address, &data); | ||
| 302 | else | ||
| 303 | fault = LoadInstr (state, address, &data); | ||
| 304 | |||
| 305 | if (fault) { | ||
| 306 | |||
| 307 | /* dyf add for s3c6410 no instcache temporary 2010.9.17 */ | ||
| 308 | if (!(skyeye_cachetype == INSTCACHE)) { | ||
| 309 | /* set translation fault on prefetch abort */ | ||
| 310 | state->mmu.fault_statusi = fault & 0xFF; | ||
| 311 | state->mmu.fault_address = address; | ||
| 312 | } | ||
| 313 | /* add end */ | ||
| 314 | |||
| 315 | ARMul_PREFETCHABORT (address); | ||
| 316 | return ARMul_ABORTWORD; | ||
| 317 | } | ||
| 318 | else { | ||
| 319 | ARMul_CLEARABORT; | ||
| 320 | } | ||
| 321 | |||
| 322 | return data; | ||
| 323 | } | ||
| 324 | |||
| 325 | /***************************************************************************\ | ||
| 326 | * Load Instruction, Sequential Cycle * | ||
| 327 | \***************************************************************************/ | ||
| 328 | |||
| 329 | ARMword | ||
| 330 | ARMul_LoadInstrS (ARMul_State * state, ARMword address, ARMword isize) | ||
| 331 | { | ||
| 332 | state->NumScycles++; | ||
| 333 | |||
| 334 | #ifdef HOURGLASS | ||
| 335 | if ((state->NumScycles & HOURGLASS_RATE) == 0) { | ||
| 336 | HOURGLASS; | ||
| 337 | } | ||
| 338 | #endif | ||
| 339 | |||
| 340 | return ARMul_ReLoadInstr (state, address, isize); | ||
| 341 | } | ||
| 342 | |||
| 343 | /***************************************************************************\ | ||
| 344 | * Load Instruction, Non Sequential Cycle * | ||
| 345 | \***************************************************************************/ | ||
| 346 | |||
| 347 | ARMword | ||
| 348 | ARMul_LoadInstrN (ARMul_State * state, ARMword address, ARMword isize) | ||
| 349 | { | ||
| 350 | state->NumNcycles++; | ||
| 351 | |||
| 352 | return ARMul_ReLoadInstr (state, address, isize); | ||
| 353 | } | ||
| 354 | |||
| 355 | /***************************************************************************\ | ||
| 356 | * Read Word (but don't tell anyone!) * | ||
| 357 | \***************************************************************************/ | ||
| 358 | |||
| 359 | ARMword | ||
| 360 | ARMul_ReadWord (ARMul_State * state, ARMword address) | ||
| 361 | { | ||
| 362 | ARMword data; | ||
| 363 | fault_t fault; | ||
| 364 | |||
| 365 | #ifdef ABORTS | ||
| 366 | if (address >= LOWABORT && address < HIGHABORT) { | ||
| 367 | ARMul_DATAABORT (address); | ||
| 368 | return ARMul_ABORTWORD; | ||
| 369 | } | ||
| 370 | else { | ||
| 371 | ARMul_CLEARABORT; | ||
| 372 | } | ||
| 373 | #endif | ||
| 374 | |||
| 375 | fault = GetWord (state, address, &data); | ||
| 376 | if (fault) { | ||
| 377 | state->mmu.fault_status = | ||
| 378 | (fault | (state->mmu.last_domain << 4)) & 0xFF; | ||
| 379 | state->mmu.fault_address = address; | ||
| 380 | ARMul_DATAABORT (address); | ||
| 381 | return ARMul_ABORTWORD; | ||
| 382 | } | ||
| 383 | else { | ||
| 384 | ARMul_CLEARABORT; | ||
| 385 | } | ||
| 386 | return data; | ||
| 387 | } | ||
| 388 | |||
| 389 | /***************************************************************************\ | ||
| 390 | * Load Word, Sequential Cycle * | ||
| 391 | \***************************************************************************/ | ||
| 392 | |||
| 393 | ARMword | ||
| 394 | ARMul_LoadWordS (ARMul_State * state, ARMword address) | ||
| 395 | { | ||
| 396 | state->NumScycles++; | ||
| 397 | |||
| 398 | return ARMul_ReadWord (state, address); | ||
| 399 | } | ||
| 400 | |||
| 401 | /***************************************************************************\ | ||
| 402 | * Load Word, Non Sequential Cycle * | ||
| 403 | \***************************************************************************/ | ||
| 404 | |||
| 405 | ARMword | ||
| 406 | ARMul_LoadWordN (ARMul_State * state, ARMword address) | ||
| 407 | { | ||
| 408 | state->NumNcycles++; | ||
| 409 | |||
| 410 | return ARMul_ReadWord (state, address); | ||
| 411 | } | ||
| 412 | |||
| 413 | /***************************************************************************\ | ||
| 414 | * Load Halfword, (Non Sequential Cycle) * | ||
| 415 | \***************************************************************************/ | ||
| 416 | |||
| 417 | ARMword | ||
| 418 | ARMul_LoadHalfWord (ARMul_State * state, ARMword address) | ||
| 419 | { | ||
| 420 | ARMword data; | ||
| 421 | fault_t fault; | ||
| 422 | |||
| 423 | state->NumNcycles++; | ||
| 424 | fault = GetHalfWord (state, address, &data); | ||
| 425 | |||
| 426 | if (fault) { | ||
| 427 | state->mmu.fault_status = | ||
| 428 | (fault | (state->mmu.last_domain << 4)) & 0xFF; | ||
| 429 | state->mmu.fault_address = address; | ||
| 430 | ARMul_DATAABORT (address); | ||
| 431 | return ARMul_ABORTWORD; | ||
| 432 | } | ||
| 433 | else { | ||
| 434 | ARMul_CLEARABORT; | ||
| 435 | } | ||
| 436 | |||
| 437 | return data; | ||
| 438 | |||
| 439 | } | ||
| 440 | |||
| 441 | /***************************************************************************\ | ||
| 442 | * Read Byte (but don't tell anyone!) * | ||
| 443 | \***************************************************************************/ | ||
| 444 | int ARMul_ICE_ReadByte(ARMul_State * state, ARMword address, ARMword *presult) | ||
| 445 | { | ||
| 446 | ARMword data; | ||
| 447 | fault_t fault; | ||
| 448 | fault = GetByte (state, address, &data); | ||
| 449 | if (fault) { | ||
| 450 | *presult=-1; fault=ALIGNMENT_FAULT; return fault; | ||
| 451 | }else{ | ||
| 452 | *(char *)presult=(unsigned char)(data & 0xff); fault=NO_FAULT; return fault; | ||
| 453 | } | ||
| 454 | } | ||
| 455 | |||
| 456 | |||
| 457 | ARMword | ||
| 458 | ARMul_ReadByte (ARMul_State * state, ARMword address) | ||
| 459 | { | ||
| 460 | ARMword data; | ||
| 461 | fault_t fault; | ||
| 462 | |||
| 463 | fault = GetByte (state, address, &data); | ||
| 464 | |||
| 465 | if (fault) { | ||
| 466 | state->mmu.fault_status = | ||
| 467 | (fault | (state->mmu.last_domain << 4)) & 0xFF; | ||
| 468 | state->mmu.fault_address = address; | ||
| 469 | ARMul_DATAABORT (address); | ||
| 470 | return ARMul_ABORTWORD; | ||
| 471 | } | ||
| 472 | else { | ||
| 473 | ARMul_CLEARABORT; | ||
| 474 | } | ||
| 475 | |||
| 476 | return data; | ||
| 477 | |||
| 478 | } | ||
| 479 | |||
| 480 | /***************************************************************************\ | ||
| 481 | * Load Byte, (Non Sequential Cycle) * | ||
| 482 | \***************************************************************************/ | ||
| 483 | |||
| 484 | ARMword | ||
| 485 | ARMul_LoadByte (ARMul_State * state, ARMword address) | ||
| 486 | { | ||
| 487 | state->NumNcycles++; | ||
| 488 | |||
| 489 | return ARMul_ReadByte (state, address); | ||
| 490 | } | ||
| 491 | |||
| 492 | /***************************************************************************\ | ||
| 493 | * Write Word (but don't tell anyone!) * | ||
| 494 | \***************************************************************************/ | ||
| 495 | |||
| 496 | void | ||
| 497 | ARMul_WriteWord (ARMul_State * state, ARMword address, ARMword data) | ||
| 498 | { | ||
| 499 | fault_t fault; | ||
| 500 | |||
| 501 | #ifdef ABORTS | ||
| 502 | if (address >= LOWABORT && address < HIGHABORT) { | ||
| 503 | ARMul_DATAABORT (address); | ||
| 504 | return; | ||
| 505 | } | ||
| 506 | else { | ||
| 507 | ARMul_CLEARABORT; | ||
| 508 | } | ||
| 509 | #endif | ||
| 510 | |||
| 511 | fault = PutWord (state, address, data); | ||
| 512 | if (fault) { | ||
| 513 | state->mmu.fault_status = | ||
| 514 | (fault | (state->mmu.last_domain << 4)) & 0xFF; | ||
| 515 | state->mmu.fault_address = address; | ||
| 516 | ARMul_DATAABORT (address); | ||
| 517 | return; | ||
| 518 | } | ||
| 519 | else { | ||
| 520 | ARMul_CLEARABORT; | ||
| 521 | } | ||
| 522 | } | ||
| 523 | |||
| 524 | /***************************************************************************\ | ||
| 525 | * Store Word, Sequential Cycle * | ||
| 526 | \***************************************************************************/ | ||
| 527 | |||
| 528 | void | ||
| 529 | ARMul_StoreWordS (ARMul_State * state, ARMword address, ARMword data) | ||
| 530 | { | ||
| 531 | state->NumScycles++; | ||
| 532 | |||
| 533 | ARMul_WriteWord (state, address, data); | ||
| 534 | } | ||
| 535 | |||
| 536 | /***************************************************************************\ | ||
| 537 | * Store Word, Non Sequential Cycle * | ||
| 538 | \***************************************************************************/ | ||
| 539 | |||
| 540 | void | ||
| 541 | ARMul_StoreWordN (ARMul_State * state, ARMword address, ARMword data) | ||
| 542 | { | ||
| 543 | state->NumNcycles++; | ||
| 544 | |||
| 545 | ARMul_WriteWord (state, address, data); | ||
| 546 | } | ||
| 547 | |||
| 548 | /***************************************************************************\ | ||
| 549 | * Store HalfWord, (Non Sequential Cycle) * | ||
| 550 | \***************************************************************************/ | ||
| 551 | |||
| 552 | void | ||
| 553 | ARMul_StoreHalfWord (ARMul_State * state, ARMword address, ARMword data) | ||
| 554 | { | ||
| 555 | fault_t fault; | ||
| 556 | state->NumNcycles++; | ||
| 557 | fault = PutHalfWord (state, address, data); | ||
| 558 | if (fault) { | ||
| 559 | state->mmu.fault_status = | ||
| 560 | (fault | (state->mmu.last_domain << 4)) & 0xFF; | ||
| 561 | state->mmu.fault_address = address; | ||
| 562 | ARMul_DATAABORT (address); | ||
| 563 | return; | ||
| 564 | } | ||
| 565 | else { | ||
| 566 | ARMul_CLEARABORT; | ||
| 567 | } | ||
| 568 | } | ||
| 569 | |||
| 570 | //chy 2006-04-15 | ||
| 571 | int ARMul_ICE_WriteByte (ARMul_State * state, ARMword address, ARMword data) | ||
| 572 | { | ||
| 573 | fault_t fault; | ||
| 574 | fault = PutByte (state, address, data); | ||
| 575 | if (fault) | ||
| 576 | return 1; | ||
| 577 | else | ||
| 578 | return 0; | ||
| 579 | } | ||
| 580 | /***************************************************************************\ | ||
| 581 | * Write Byte (but don't tell anyone!) * | ||
| 582 | \***************************************************************************/ | ||
| 583 | //chy 2003-07-10, add real write byte fun | ||
| 584 | void | ||
| 585 | ARMul_WriteByte (ARMul_State * state, ARMword address, ARMword data) | ||
| 586 | { | ||
| 587 | fault_t fault; | ||
| 588 | fault = PutByte (state, address, data); | ||
| 589 | if (fault) { | ||
| 590 | state->mmu.fault_status = | ||
| 591 | (fault | (state->mmu.last_domain << 4)) & 0xFF; | ||
| 592 | state->mmu.fault_address = address; | ||
| 593 | ARMul_DATAABORT (address); | ||
| 594 | return; | ||
| 595 | } | ||
| 596 | else { | ||
| 597 | ARMul_CLEARABORT; | ||
| 598 | } | ||
| 599 | } | ||
| 600 | |||
| 601 | /***************************************************************************\ | ||
| 602 | * Store Byte, (Non Sequential Cycle) * | ||
| 603 | \***************************************************************************/ | ||
| 604 | |||
| 605 | void | ||
| 606 | ARMul_StoreByte (ARMul_State * state, ARMword address, ARMword data) | ||
| 607 | { | ||
| 608 | state->NumNcycles++; | ||
| 609 | |||
| 610 | #ifdef VALIDATE | ||
| 611 | if (address == TUBE) { | ||
| 612 | if (data == 4) | ||
| 613 | state->Emulate = FALSE; | ||
| 614 | else | ||
| 615 | (void) putc ((char) data, stderr); /* Write Char */ | ||
| 616 | return; | ||
| 617 | } | ||
| 618 | #endif | ||
| 619 | |||
| 620 | ARMul_WriteByte (state, address, data); | ||
| 621 | } | ||
| 622 | |||
| 623 | /***************************************************************************\ | ||
| 624 | * Swap Word, (Two Non Sequential Cycles) * | ||
| 625 | \***************************************************************************/ | ||
| 626 | |||
| 627 | ARMword | ||
| 628 | ARMul_SwapWord (ARMul_State * state, ARMword address, ARMword data) | ||
| 629 | { | ||
| 630 | ARMword temp; | ||
| 631 | |||
| 632 | state->NumNcycles++; | ||
| 633 | |||
| 634 | temp = ARMul_ReadWord (state, address); | ||
| 635 | |||
| 636 | state->NumNcycles++; | ||
| 637 | |||
| 638 | PutWord (state, address, data); | ||
| 639 | |||
| 640 | return temp; | ||
| 641 | } | ||
| 642 | |||
| 643 | /***************************************************************************\ | ||
| 644 | * Swap Byte, (Two Non Sequential Cycles) * | ||
| 645 | \***************************************************************************/ | ||
| 646 | |||
| 647 | ARMword | ||
| 648 | ARMul_SwapByte (ARMul_State * state, ARMword address, ARMword data) | ||
| 649 | { | ||
| 650 | ARMword temp; | ||
| 651 | |||
| 652 | temp = ARMul_LoadByte (state, address); | ||
| 653 | ARMul_StoreByte (state, address, data); | ||
| 654 | |||
| 655 | return temp; | ||
| 656 | } | ||
| 657 | |||
| 658 | /***************************************************************************\ | ||
| 659 | * Count I Cycles * | ||
| 660 | \***************************************************************************/ | ||
| 661 | |||
| 662 | void | ||
| 663 | ARMul_Icycles (ARMul_State * state, unsigned number, | ||
| 664 | ARMword address) | ||
| 665 | { | ||
| 666 | state->NumIcycles += number; | ||
| 667 | ARMul_CLEARABORT; | ||
| 668 | } | ||
| 669 | |||
| 670 | /***************************************************************************\ | ||
| 671 | * Count C Cycles * | ||
| 672 | \***************************************************************************/ | ||
| 673 | |||
| 674 | void | ||
| 675 | ARMul_Ccycles (ARMul_State * state, unsigned number, | ||
| 676 | ARMword address) | ||
| 677 | { | ||
| 678 | state->NumCcycles += number; | ||
| 679 | ARMul_CLEARABORT; | ||
| 680 | } | ||