diff options
Diffstat (limited to 'src')
22 files changed, 326 insertions, 7743 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index cc0deb004..aefbe3375 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -6,19 +6,10 @@ set(SRCS | |||
| 6 | arm/dyncom/arm_dyncom_interpreter.cpp | 6 | arm/dyncom/arm_dyncom_interpreter.cpp |
| 7 | arm/dyncom/arm_dyncom_run.cpp | 7 | arm/dyncom/arm_dyncom_run.cpp |
| 8 | arm/dyncom/arm_dyncom_thumb.cpp | 8 | arm/dyncom/arm_dyncom_thumb.cpp |
| 9 | arm/interpreter/mmu/arm1176jzf_s_mmu.cpp | ||
| 10 | arm/interpreter/mmu/cache.cpp | ||
| 11 | arm/interpreter/mmu/maverick.cpp | ||
| 12 | arm/interpreter/mmu/rb.cpp | ||
| 13 | arm/interpreter/mmu/sa_mmu.cpp | ||
| 14 | arm/interpreter/mmu/tlb.cpp | ||
| 15 | arm/interpreter/mmu/wb.cpp | ||
| 16 | arm/interpreter/mmu/xscale_copro.cpp | ||
| 17 | arm/interpreter/arm_interpreter.cpp | 9 | arm/interpreter/arm_interpreter.cpp |
| 18 | arm/interpreter/armcopro.cpp | 10 | arm/interpreter/armcopro.cpp |
| 19 | arm/interpreter/armemu.cpp | 11 | arm/interpreter/armemu.cpp |
| 20 | arm/interpreter/arminit.cpp | 12 | arm/interpreter/arminit.cpp |
| 21 | arm/interpreter/armmmu.cpp | ||
| 22 | arm/interpreter/armsupp.cpp | 13 | arm/interpreter/armsupp.cpp |
| 23 | arm/interpreter/armvirt.cpp | 14 | arm/interpreter/armvirt.cpp |
| 24 | arm/interpreter/thumbemu.cpp | 15 | arm/interpreter/thumbemu.cpp |
| @@ -72,12 +63,6 @@ set(HEADERS | |||
| 72 | arm/dyncom/arm_dyncom_run.h | 63 | arm/dyncom/arm_dyncom_run.h |
| 73 | arm/dyncom/arm_dyncom_thumb.h | 64 | arm/dyncom/arm_dyncom_thumb.h |
| 74 | arm/interpreter/arm_interpreter.h | 65 | arm/interpreter/arm_interpreter.h |
| 75 | arm/interpreter/mmu/arm1176jzf_s_mmu.h | ||
| 76 | arm/interpreter/mmu/cache.h | ||
| 77 | arm/interpreter/mmu/rb.h | ||
| 78 | arm/interpreter/mmu/sa_mmu.h | ||
| 79 | arm/interpreter/mmu/tlb.h | ||
| 80 | arm/interpreter/mmu/wb.h | ||
| 81 | arm/skyeye_common/arm_regformat.h | 66 | arm/skyeye_common/arm_regformat.h |
| 82 | arm/skyeye_common/armcpu.h | 67 | arm/skyeye_common/armcpu.h |
| 83 | arm/skyeye_common/armdefs.h | 68 | arm/skyeye_common/armdefs.h |
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp index 7a65669ef..669b612fc 100644 --- a/src/core/arm/dyncom/arm_dyncom.cpp +++ b/src/core/arm/dyncom/arm_dyncom.cpp | |||
| @@ -27,7 +27,6 @@ ARM_DynCom::ARM_DynCom() : ticks(0) { | |||
| 27 | 27 | ||
| 28 | ARMul_SelectProcessor(state.get(), ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop); | 28 | ARMul_SelectProcessor(state.get(), ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop); |
| 29 | state->lateabtSig = LOW; | 29 | state->lateabtSig = LOW; |
| 30 | mmu_init(state); | ||
| 31 | 30 | ||
| 32 | // Reset the core to initial state | 31 | // Reset the core to initial state |
| 33 | ARMul_CoProInit(state.get()); | 32 | ARMul_CoProInit(state.get()); |
diff --git a/src/core/arm/interpreter/arm_interpreter.cpp b/src/core/arm/interpreter/arm_interpreter.cpp index 6f6a5913c..ed4415082 100644 --- a/src/core/arm/interpreter/arm_interpreter.cpp +++ b/src/core/arm/interpreter/arm_interpreter.cpp | |||
| @@ -22,7 +22,6 @@ ARM_Interpreter::ARM_Interpreter() { | |||
| 22 | 22 | ||
| 23 | ARMul_SelectProcessor(state, ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop); | 23 | ARMul_SelectProcessor(state, ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop); |
| 24 | state->lateabtSig = LOW; | 24 | state->lateabtSig = LOW; |
| 25 | mmu_init(state); | ||
| 26 | 25 | ||
| 27 | // Reset the core to initial state | 26 | // Reset the core to initial state |
| 28 | ARMul_CoProInit(state); | 27 | ARMul_CoProInit(state); |
diff --git a/src/core/arm/interpreter/armcopro.cpp b/src/core/arm/interpreter/armcopro.cpp index 9de6651d4..b4ddc3d96 100644 --- a/src/core/arm/interpreter/armcopro.cpp +++ b/src/core/arm/interpreter/armcopro.cpp | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | along with this program; if not, write to the Free Software | 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. */ | 16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
| 17 | 17 | ||
| 18 | |||
| 19 | #include "core/arm/skyeye_common/armdefs.h" | 18 | #include "core/arm/skyeye_common/armdefs.h" |
| 20 | #include "core/arm/skyeye_common/armemu.h" | 19 | #include "core/arm/skyeye_common/armemu.h" |
| 21 | #include "core/arm/skyeye_common/vfp/vfp.h" | 20 | #include "core/arm/skyeye_common/vfp/vfp.h" |
| @@ -25,817 +24,302 @@ | |||
| 25 | //chy ------- | 24 | //chy ------- |
| 26 | //#include "iwmmxt.h" | 25 | //#include "iwmmxt.h" |
| 27 | 26 | ||
| 28 | |||
| 29 | //chy 2005-09-19 add CP6 MRC support (for get irq number and base) | ||
| 30 | extern unsigned xscale_cp6_mrc (ARMul_State * state, unsigned type, | ||
| 31 | ARMword instr, ARMword * data); | ||
| 32 | //chy 2005-09-19--------------- | ||
| 33 | |||
| 34 | extern unsigned xscale_cp13_init (ARMul_State * state); | ||
| 35 | extern unsigned xscale_cp13_exit (ARMul_State * state); | ||
| 36 | extern unsigned xscale_cp13_ldc (ARMul_State * state, unsigned type, | ||
| 37 | ARMword instr, ARMword data); | ||
| 38 | extern unsigned xscale_cp13_stc (ARMul_State * state, unsigned type, | ||
| 39 | ARMword instr, ARMword * data); | ||
| 40 | extern unsigned xscale_cp13_mrc (ARMul_State * state, unsigned type, | ||
| 41 | ARMword instr, ARMword * data); | ||
| 42 | extern unsigned xscale_cp13_mcr (ARMul_State * state, unsigned type, | ||
| 43 | ARMword instr, ARMword data); | ||
| 44 | extern unsigned xscale_cp13_cdp (ARMul_State * state, unsigned type, | ||
| 45 | ARMword instr); | ||
| 46 | extern unsigned xscale_cp13_read_reg (ARMul_State * state, unsigned reg, | ||
| 47 | ARMword * data); | ||
| 48 | extern unsigned xscale_cp13_write_reg (ARMul_State * state, unsigned reg, | ||
| 49 | ARMword data); | ||
| 50 | extern unsigned xscale_cp14_init (ARMul_State * state); | ||
| 51 | extern unsigned xscale_cp14_exit (ARMul_State * state); | ||
| 52 | extern unsigned xscale_cp14_ldc (ARMul_State * state, unsigned type, | ||
| 53 | ARMword instr, ARMword data); | ||
| 54 | extern unsigned xscale_cp14_stc (ARMul_State * state, unsigned type, | ||
| 55 | ARMword instr, ARMword * data); | ||
| 56 | extern unsigned xscale_cp14_mrc (ARMul_State * state, unsigned type, | ||
| 57 | ARMword instr, ARMword * data); | ||
| 58 | extern unsigned xscale_cp14_mcr (ARMul_State * state, unsigned type, | ||
| 59 | ARMword instr, ARMword data); | ||
| 60 | extern unsigned xscale_cp14_cdp (ARMul_State * state, unsigned type, | ||
| 61 | ARMword instr); | ||
| 62 | extern unsigned xscale_cp14_read_reg (ARMul_State * state, unsigned reg, | ||
| 63 | ARMword * data); | ||
| 64 | extern unsigned xscale_cp14_write_reg (ARMul_State * state, unsigned reg, | ||
| 65 | ARMword data); | ||
| 66 | extern unsigned xscale_cp15_init (ARMul_State * state); | ||
| 67 | extern unsigned xscale_cp15_exit (ARMul_State * state); | ||
| 68 | extern unsigned xscale_cp15_ldc (ARMul_State * state, unsigned type, | ||
| 69 | ARMword instr, ARMword data); | ||
| 70 | extern unsigned xscale_cp15_stc (ARMul_State * state, unsigned type, | ||
| 71 | ARMword instr, ARMword * data); | ||
| 72 | extern unsigned xscale_cp15_mrc (ARMul_State * state, unsigned type, | ||
| 73 | ARMword instr, ARMword * data); | ||
| 74 | extern unsigned xscale_cp15_mcr (ARMul_State * state, unsigned type, | ||
| 75 | ARMword instr, ARMword data); | ||
| 76 | extern unsigned xscale_cp15_cdp (ARMul_State * state, unsigned type, | ||
| 77 | ARMword instr); | ||
| 78 | extern unsigned xscale_cp15_read_reg (ARMul_State * state, unsigned reg, | ||
| 79 | ARMword * data); | ||
| 80 | extern unsigned xscale_cp15_write_reg (ARMul_State * state, unsigned reg, | ||
| 81 | ARMword data); | ||
| 82 | extern unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg, | ||
| 83 | unsigned cpnum); | ||
| 84 | |||
| 85 | /* Dummy Co-processors. */ | 27 | /* Dummy Co-processors. */ |
| 86 | 28 | ||
| 87 | static unsigned | 29 | static unsigned |
| 88 | NoCoPro3R (ARMul_State * state, | 30 | NoCoPro3R(ARMul_State * state, |
| 89 | unsigned a, ARMword b) | 31 | unsigned a, ARMword b) |
| 90 | { | 32 | { |
| 91 | return ARMul_CANT; | 33 | return ARMul_CANT; |
| 92 | } | 34 | } |
| 93 | 35 | ||
| 94 | static unsigned | 36 | static unsigned |
| 95 | NoCoPro4R (ARMul_State * state, | 37 | NoCoPro4R(ARMul_State * state, |
| 96 | unsigned a, | 38 | unsigned a, |
| 97 | ARMword b, ARMword c) | 39 | ARMword b, ARMword c) |
| 98 | { | 40 | { |
| 99 | return ARMul_CANT; | 41 | return ARMul_CANT; |
| 100 | } | 42 | } |
| 101 | 43 | ||
| 102 | static unsigned | 44 | static unsigned |
| 103 | NoCoPro4W (ARMul_State * state, | 45 | NoCoPro4W(ARMul_State * state, |
| 104 | unsigned a, | 46 | unsigned a, |
| 105 | ARMword b, ARMword * c) | 47 | ARMword b, ARMword * c) |
| 106 | { | 48 | { |
| 107 | return ARMul_CANT; | 49 | return ARMul_CANT; |
| 108 | } | 50 | } |
| 109 | 51 | ||
| 110 | static unsigned | 52 | static unsigned |
| 111 | NoCoPro5R (ARMul_State * state, | 53 | NoCoPro5R(ARMul_State * state, |
| 112 | unsigned a, | 54 | unsigned a, |
| 113 | ARMword b, | 55 | ARMword b, |
| 114 | ARMword c, ARMword d) | 56 | ARMword c, ARMword d) |
| 115 | { | 57 | { |
| 116 | return ARMul_CANT; | 58 | return ARMul_CANT; |
| 117 | } | 59 | } |
| 118 | 60 | ||
| 119 | static unsigned | 61 | static unsigned |
| 120 | NoCoPro5W (ARMul_State * state, | 62 | NoCoPro5W(ARMul_State * state, |
| 121 | unsigned a, | 63 | unsigned a, |
| 122 | ARMword b, | 64 | ARMword b, |
| 123 | ARMword * c, ARMword * d ) | 65 | ARMword * c, ARMword * d) |
| 124 | { | 66 | { |
| 125 | return ARMul_CANT; | 67 | return ARMul_CANT; |
| 126 | } | 68 | } |
| 127 | 69 | ||
| 128 | /* The XScale Co-processors. */ | 70 | /* The XScale Co-processors. */ |
| 129 | 71 | ||
| 130 | /* Coprocessor 15: System Control. */ | 72 | /* Coprocessor 15: System Control. */ |
| 131 | static void write_cp14_reg (unsigned, ARMword); | 73 | static void write_cp14_reg(unsigned, ARMword); |
| 132 | static ARMword read_cp14_reg (unsigned); | 74 | static ARMword read_cp14_reg(unsigned); |
| 133 | |||
| 134 | /* There are two sets of registers for copro 15. | ||
| 135 | One set is available when opcode_2 is 0 and | ||
| 136 | the other set when opcode_2 >= 1. */ | ||
| 137 | static ARMword XScale_cp15_opcode_2_is_0_Regs[16]; | ||
| 138 | static ARMword XScale_cp15_opcode_2_is_not_0_Regs[16]; | ||
| 139 | /* There are also a set of breakpoint registers | ||
| 140 | which are accessed via CRm instead of opcode_2. */ | ||
| 141 | static ARMword XScale_cp15_DBR1; | ||
| 142 | static ARMword XScale_cp15_DBCON; | ||
| 143 | static ARMword XScale_cp15_IBCR0; | ||
| 144 | static ARMword XScale_cp15_IBCR1; | ||
| 145 | |||
| 146 | static unsigned | ||
| 147 | XScale_cp15_init (ARMul_State * state) | ||
| 148 | { | ||
| 149 | int i; | ||
| 150 | |||
| 151 | for (i = 16; i--;) { | ||
| 152 | XScale_cp15_opcode_2_is_0_Regs[i] = 0; | ||
| 153 | XScale_cp15_opcode_2_is_not_0_Regs[i] = 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | /* Initialise the processor ID. */ | ||
| 157 | //chy 2003-03-24, is same as cpu id in skyeye_options.c | ||
| 158 | //XScale_cp15_opcode_2_is_0_Regs[0] = 0x69052000; | ||
| 159 | XScale_cp15_opcode_2_is_0_Regs[0] = 0x69050000; | ||
| 160 | |||
| 161 | /* Initialise the cache type. */ | ||
| 162 | XScale_cp15_opcode_2_is_not_0_Regs[0] = 0x0B1AA1AA; | ||
| 163 | |||
| 164 | /* Initialise the ARM Control Register. */ | ||
| 165 | XScale_cp15_opcode_2_is_0_Regs[1] = 0x00000078; | ||
| 166 | |||
| 167 | return No_exp; | ||
| 168 | } | ||
| 169 | |||
| 170 | /* Check an access to a register. */ | ||
| 171 | |||
| 172 | static unsigned | ||
| 173 | check_cp15_access (ARMul_State * state, | ||
| 174 | unsigned reg, | ||
| 175 | unsigned CRm, unsigned opcode_1, unsigned opcode_2) | ||
| 176 | { | ||
| 177 | /* Do not allow access to these register in USER mode. */ | ||
| 178 | //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode | ||
| 179 | if (state->Mode == USER26MODE || state->Mode == USER32MODE ) | ||
| 180 | return ARMul_CANT; | ||
| 181 | |||
| 182 | /* Opcode_1should be zero. */ | ||
| 183 | if (opcode_1 != 0) | ||
| 184 | return ARMul_CANT; | ||
| 185 | |||
| 186 | /* Different register have different access requirements. */ | ||
| 187 | switch (reg) { | ||
| 188 | case 0: | ||
| 189 | case 1: | ||
| 190 | /* CRm must be 0. Opcode_2 can be anything. */ | ||
| 191 | if (CRm != 0) | ||
| 192 | return ARMul_CANT; | ||
| 193 | break; | ||
| 194 | case 2: | ||
| 195 | case 3: | ||
| 196 | /* CRm must be 0. Opcode_2 must be zero. */ | ||
| 197 | if ((CRm != 0) || (opcode_2 != 0)) | ||
| 198 | return ARMul_CANT; | ||
| 199 | break; | ||
| 200 | case 4: | ||
| 201 | /* Access not allowed. */ | ||
| 202 | return ARMul_CANT; | ||
| 203 | case 5: | ||
| 204 | case 6: | ||
| 205 | /* Opcode_2 must be zero. CRm must be 0. */ | ||
| 206 | if ((CRm != 0) || (opcode_2 != 0)) | ||
| 207 | return ARMul_CANT; | ||
| 208 | break; | ||
| 209 | case 7: | ||
| 210 | /* Permissable combinations: | ||
| 211 | Opcode_2 CRm | ||
| 212 | 0 5 | ||
| 213 | 0 6 | ||
| 214 | 0 7 | ||
| 215 | 1 5 | ||
| 216 | 1 6 | ||
| 217 | 1 10 | ||
| 218 | 4 10 | ||
| 219 | 5 2 | ||
| 220 | 6 5 */ | ||
| 221 | switch (opcode_2) { | ||
| 222 | default: | ||
| 223 | return ARMul_CANT; | ||
| 224 | case 6: | ||
| 225 | if (CRm != 5) | ||
| 226 | return ARMul_CANT; | ||
| 227 | break; | ||
| 228 | case 5: | ||
| 229 | if (CRm != 2) | ||
| 230 | return ARMul_CANT; | ||
| 231 | break; | ||
| 232 | case 4: | ||
| 233 | if (CRm != 10) | ||
| 234 | return ARMul_CANT; | ||
| 235 | break; | ||
| 236 | case 1: | ||
| 237 | if ((CRm != 5) && (CRm != 6) && (CRm != 10)) | ||
| 238 | return ARMul_CANT; | ||
| 239 | break; | ||
| 240 | case 0: | ||
| 241 | if ((CRm < 5) || (CRm > 7)) | ||
| 242 | return ARMul_CANT; | ||
| 243 | break; | ||
| 244 | } | ||
| 245 | break; | ||
| 246 | |||
| 247 | case 8: | ||
| 248 | /* Permissable combinations: | ||
| 249 | Opcode_2 CRm | ||
| 250 | 0 5 | ||
| 251 | 0 6 | ||
| 252 | 0 7 | ||
| 253 | 1 5 | ||
| 254 | 1 6 */ | ||
| 255 | if (opcode_2 > 1) | ||
| 256 | return ARMul_CANT; | ||
| 257 | if ((CRm < 5) || (CRm > 7)) | ||
| 258 | return ARMul_CANT; | ||
| 259 | if (opcode_2 == 1 && CRm == 7) | ||
| 260 | return ARMul_CANT; | ||
| 261 | break; | ||
| 262 | case 9: | ||
| 263 | /* Opcode_2 must be zero or one. CRm must be 1 or 2. */ | ||
| 264 | if (((CRm != 0) && (CRm != 1)) | ||
| 265 | || ((opcode_2 != 1) && (opcode_2 != 2))) | ||
| 266 | return ARMul_CANT; | ||
| 267 | break; | ||
| 268 | case 10: | ||
| 269 | /* Opcode_2 must be zero or one. CRm must be 4 or 8. */ | ||
| 270 | if (((CRm != 0) && (CRm != 1)) | ||
| 271 | || ((opcode_2 != 4) && (opcode_2 != 8))) | ||
| 272 | return ARMul_CANT; | ||
| 273 | break; | ||
| 274 | case 11: | ||
| 275 | /* Access not allowed. */ | ||
| 276 | return ARMul_CANT; | ||
| 277 | case 12: | ||
| 278 | /* Access not allowed. */ | ||
| 279 | return ARMul_CANT; | ||
| 280 | case 13: | ||
| 281 | /* Opcode_2 must be zero. CRm must be 0. */ | ||
| 282 | if ((CRm != 0) || (opcode_2 != 0)) | ||
| 283 | return ARMul_CANT; | ||
| 284 | break; | ||
| 285 | case 14: | ||
| 286 | /* Opcode_2 must be 0. CRm must be 0, 3, 4, 8 or 9. */ | ||
| 287 | if (opcode_2 != 0) | ||
| 288 | return ARMul_CANT; | ||
| 289 | |||
| 290 | if ((CRm != 0) && (CRm != 3) && (CRm != 4) && (CRm != 8) | ||
| 291 | && (CRm != 9)) | ||
| 292 | return ARMul_CANT; | ||
| 293 | break; | ||
| 294 | case 15: | ||
| 295 | /* Opcode_2 must be zero. CRm must be 1. */ | ||
| 296 | if ((CRm != 1) || (opcode_2 != 0)) | ||
| 297 | return ARMul_CANT; | ||
| 298 | break; | ||
| 299 | default: | ||
| 300 | /* Should never happen. */ | ||
| 301 | return ARMul_CANT; | ||
| 302 | } | ||
| 303 | |||
| 304 | return ARMul_DONE; | ||
| 305 | } | ||
| 306 | |||
| 307 | /* Coprocessor 13: Interrupt Controller and Bus Controller. */ | ||
| 308 | |||
| 309 | /* There are two sets of registers for copro 13. | ||
| 310 | One set (of three registers) is available when CRm is 0 | ||
| 311 | and the other set (of six registers) when CRm is 1. */ | ||
| 312 | |||
| 313 | static ARMword XScale_cp13_CR0_Regs[16]; | ||
| 314 | static ARMword XScale_cp13_CR1_Regs[16]; | ||
| 315 | |||
| 316 | static unsigned | ||
| 317 | XScale_cp13_init (ARMul_State * state) | ||
| 318 | { | ||
| 319 | int i; | ||
| 320 | |||
| 321 | for (i = 16; i--;) { | ||
| 322 | XScale_cp13_CR0_Regs[i] = 0; | ||
| 323 | XScale_cp13_CR1_Regs[i] = 0; | ||
| 324 | } | ||
| 325 | |||
| 326 | return No_exp; | ||
| 327 | } | ||
| 328 | |||
| 329 | /* Check an access to a register. */ | ||
| 330 | |||
| 331 | static unsigned | ||
| 332 | check_cp13_access (ARMul_State * state, | ||
| 333 | unsigned reg, | ||
| 334 | unsigned CRm, unsigned opcode_1, unsigned opcode_2) | ||
| 335 | { | ||
| 336 | /* Do not allow access to these registers in USER mode. */ | ||
| 337 | //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode | ||
| 338 | if (state->Mode == USER26MODE || state->Mode == USER32MODE ) | ||
| 339 | return ARMul_CANT; | ||
| 340 | |||
| 341 | /* The opcodes should be zero. */ | ||
| 342 | if ((opcode_1 != 0) || (opcode_2 != 0)) | ||
| 343 | return ARMul_CANT; | ||
| 344 | |||
| 345 | /* Do not allow access to these register if bit | ||
| 346 | 13 of coprocessor 15's register 15 is zero. */ | ||
| 347 | if (!CP_ACCESS_ALLOWED (state, 13)) | ||
| 348 | return ARMul_CANT; | ||
| 349 | |||
| 350 | /* Registers 0, 4 and 8 are defined when CRm == 0. | ||
| 351 | Registers 0, 1, 4, 5, 6, 7, 8 are defined when CRm == 1. | ||
| 352 | For all other CRm values undefined behaviour results. */ | ||
| 353 | if (CRm == 0) { | ||
| 354 | if (reg == 0 || reg == 4 || reg == 8) | ||
| 355 | return ARMul_DONE; | ||
| 356 | } | ||
| 357 | else if (CRm == 1) { | ||
| 358 | if (reg == 0 || reg == 1 || (reg >= 4 && reg <= 8)) | ||
| 359 | return ARMul_DONE; | ||
| 360 | } | ||
| 361 | |||
| 362 | return ARMul_CANT; | ||
| 363 | } | ||
| 364 | |||
| 365 | /* Coprocessor 14: Performance Monitoring, Clock and Power management, | ||
| 366 | Software Debug. */ | ||
| 367 | |||
| 368 | static ARMword XScale_cp14_Regs[16]; | ||
| 369 | |||
| 370 | static unsigned | ||
| 371 | XScale_cp14_init (ARMul_State * state) | ||
| 372 | { | ||
| 373 | int i; | ||
| 374 | |||
| 375 | for (i = 16; i--;) | ||
| 376 | XScale_cp14_Regs[i] = 0; | ||
| 377 | |||
| 378 | return No_exp; | ||
| 379 | } | ||
| 380 | 75 | ||
| 381 | /* Check an access to a register. */ | 76 | /* Check an access to a register. */ |
| 382 | 77 | ||
| 383 | static unsigned | 78 | static unsigned |
| 384 | check_cp14_access (ARMul_State * state, | 79 | check_cp15_access(ARMul_State * state, |
| 385 | unsigned reg, | 80 | unsigned reg, |
| 386 | unsigned CRm, unsigned opcode1, unsigned opcode2) | 81 | unsigned CRm, unsigned opcode_1, unsigned opcode_2) |
| 387 | { | ||
| 388 | /* Not allowed to access these register in USER mode. */ | ||
| 389 | //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode | ||
| 390 | if (state->Mode == USER26MODE || state->Mode == USER32MODE ) | ||
| 391 | return ARMul_CANT; | ||
| 392 | |||
| 393 | /* CRm should be zero. */ | ||
| 394 | if (CRm != 0) | ||
| 395 | return ARMul_CANT; | ||
| 396 | |||
| 397 | /* OPcodes should be zero. */ | ||
| 398 | if (opcode1 != 0 || opcode2 != 0) | ||
| 399 | return ARMul_CANT; | ||
| 400 | |||
| 401 | /* Accessing registers 4 or 5 has unpredicatable results. */ | ||
| 402 | if (reg >= 4 && reg <= 5) | ||
| 403 | return ARMul_CANT; | ||
| 404 | |||
| 405 | return ARMul_DONE; | ||
| 406 | } | ||
| 407 | |||
| 408 | /* Here's ARMulator's MMU definition. A few things to note: | ||
| 409 | 1) It has eight registers, but only two are defined. | ||
| 410 | 2) You can only access its registers with MCR and MRC. | ||
| 411 | 3) MMU Register 0 (ID) returns 0x41440110 | ||
| 412 | 4) Register 1 only has 4 bits defined. Bits 0 to 3 are unused, bit 4 | ||
| 413 | controls 32/26 bit program space, bit 5 controls 32/26 bit data space, | ||
| 414 | bit 6 controls late abort timimg and bit 7 controls big/little endian. */ | ||
| 415 | |||
| 416 | static ARMword MMUReg[8]; | ||
| 417 | |||
| 418 | static unsigned | ||
| 419 | MMUInit (ARMul_State * state) | ||
| 420 | { | ||
| 421 | /* 2004-05-09 chy | ||
| 422 | ------------------------------------------------------------- | ||
| 423 | read ARM Architecture Reference Manual | ||
| 424 | 2.6.5 Data Abort | ||
| 425 | There are three Abort Model in ARM arch. | ||
| 426 | |||
| 427 | Early Abort Model: used in some ARMv3 and earlier implementations. In this | ||
| 428 | model, base register wirteback occurred for LDC,LDM,STC,STM instructions, and | ||
| 429 | the base register was unchanged for all other instructions. (oldest) | ||
| 430 | |||
| 431 | Base Restored Abort Model: If a Data Abort occurs in an instruction which | ||
| 432 | specifies base register writeback, the value in the base register is | ||
| 433 | unchanged. (strongarm, xscale) | ||
| 434 | |||
| 435 | Base Updated Abort Model: If a Data Abort occurs in an instruction which | ||
| 436 | specifies base register writeback, the base register writeback still occurs. | ||
| 437 | (arm720T) | ||
| 438 | |||
| 439 | read PART B | ||
| 440 | chap2 The System Control Coprocessor CP15 | ||
| 441 | 2.4 Register1:control register | ||
| 442 | L(bit 6): in some ARMv3 and earlier implementations, the abort model of the | ||
| 443 | processor could be configured: | ||
| 444 | 0=early Abort Model Selected(now obsolete) | ||
| 445 | 1=Late Abort Model selceted(same as Base Updated Abort Model) | ||
| 446 | |||
| 447 | on later processors, this bit reads as 1 and ignores writes. | ||
| 448 | ------------------------------------------------------------- | ||
| 449 | So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model) | ||
| 450 | if lateabtSig=0, then it means Base Restored Abort Model | ||
| 451 | because the ARMs which skyeye simulates are all belonged to ARMv4, | ||
| 452 | so I think MMUReg[1]'s bit 6 should always be 1 | ||
| 453 | |||
| 454 | */ | ||
| 455 | |||
| 456 | MMUReg[1] = state->prog32Sig << 4 | | ||
| 457 | state->data32Sig << 5 | 1 << 6 | state->bigendSig << 7; | ||
| 458 | //state->data32Sig << 5 | state->lateabtSig << 6 | state->bigendSig << 7; | ||
| 459 | |||
| 460 | |||
| 461 | NOTICE_LOG(ARM11, "ARMul_ConsolePrint: MMU present"); | ||
| 462 | |||
| 463 | return TRUE; | ||
| 464 | } | ||
| 465 | |||
| 466 | static unsigned | ||
| 467 | MMUMRC (ARMul_State * state, unsigned type, | ||
| 468 | ARMword instr, ARMword * value) | ||
| 469 | { | ||
| 470 | mmu_mrc (state, instr, value); | ||
| 471 | return (ARMul_DONE); | ||
| 472 | } | ||
| 473 | |||
| 474 | static unsigned | ||
| 475 | MMUMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value) | ||
| 476 | { | ||
| 477 | mmu_mcr (state, instr, value); | ||
| 478 | return (ARMul_DONE); | ||
| 479 | } | ||
| 480 | |||
| 481 | /* What follows is the Validation Suite Coprocessor. It uses two | ||
| 482 | co-processor numbers (4 and 5) and has the follwing functionality. | ||
| 483 | Sixteen registers. Both co-processor nuimbers can be used in an MCR | ||
| 484 | and MRC to access these registers. CP 4 can LDC and STC to and from | ||
| 485 | the registers. CP 4 and CP 5 CDP 0 will busy wait for the number of | ||
| 486 | cycles specified by a CP register. CP 5 CDP 1 issues a FIQ after a | ||
| 487 | number of cycles (specified in a CP register), CDP 2 issues an IRQW | ||
| 488 | in the same way, CDP 3 and 4 turn of the FIQ and IRQ source, and CDP 5 | ||
| 489 | stores a 32 bit time value in a CP register (actually it's the total | ||
| 490 | number of N, S, I, C and F cyles). */ | ||
| 491 | |||
| 492 | static ARMword ValReg[16]; | ||
| 493 | |||
| 494 | static unsigned | ||
| 495 | ValLDC (ARMul_State * state, | ||
| 496 | unsigned type, ARMword instr, ARMword data) | ||
| 497 | { | ||
| 498 | static unsigned words; | ||
| 499 | |||
| 500 | if (type != ARMul_DATA) | ||
| 501 | words = 0; | ||
| 502 | else { | ||
| 503 | ValReg[BITS (12, 15)] = data; | ||
| 504 | |||
| 505 | if (BIT (22)) | ||
| 506 | /* It's a long access, get two words. */ | ||
| 507 | if (words++ != 4) | ||
| 508 | return ARMul_INC; | ||
| 509 | } | ||
| 510 | |||
| 511 | return ARMul_DONE; | ||
| 512 | } | ||
| 513 | |||
| 514 | static unsigned | ||
| 515 | ValSTC (ARMul_State * state, | ||
| 516 | unsigned type, ARMword instr, ARMword * data) | ||
| 517 | { | ||
| 518 | static unsigned words; | ||
| 519 | |||
| 520 | if (type != ARMul_DATA) | ||
| 521 | words = 0; | ||
| 522 | else { | ||
| 523 | *data = ValReg[BITS (12, 15)]; | ||
| 524 | |||
| 525 | if (BIT (22)) | ||
| 526 | /* It's a long access, get two words. */ | ||
| 527 | if (words++ != 4) | ||
| 528 | return ARMul_INC; | ||
| 529 | } | ||
| 530 | |||
| 531 | return ARMul_DONE; | ||
| 532 | } | ||
| 533 | |||
| 534 | static unsigned | ||
| 535 | ValMRC (ARMul_State * state, | ||
| 536 | unsigned type, ARMword instr, ARMword * value) | ||
| 537 | { | ||
| 538 | *value = ValReg[BITS (16, 19)]; | ||
| 539 | |||
| 540 | return ARMul_DONE; | ||
| 541 | } | ||
| 542 | |||
| 543 | static unsigned | ||
| 544 | ValMCR (ARMul_State * state, | ||
| 545 | unsigned type, ARMword instr, ARMword value) | ||
| 546 | { | ||
| 547 | ValReg[BITS (16, 19)] = value; | ||
| 548 | |||
| 549 | return ARMul_DONE; | ||
| 550 | } | ||
| 551 | |||
| 552 | static unsigned | ||
| 553 | ValCDP (ARMul_State * state, unsigned type, ARMword instr) | ||
| 554 | { | ||
| 555 | static unsigned int finish = 0; | ||
| 556 | |||
| 557 | if (BITS (20, 23) != 0) | ||
| 558 | return ARMul_CANT; | ||
| 559 | |||
| 560 | if (type == ARMul_FIRST) { | ||
| 561 | ARMword howlong; | ||
| 562 | |||
| 563 | howlong = ValReg[BITS (0, 3)]; | ||
| 564 | |||
| 565 | /* First cycle of a busy wait. */ | ||
| 566 | finish = ARMul_Time (state) + howlong; | ||
| 567 | |||
| 568 | return howlong == 0 ? ARMul_DONE : ARMul_BUSY; | ||
| 569 | } | ||
| 570 | else if (type == ARMul_BUSY) { | ||
| 571 | if (ARMul_Time (state) >= finish) | ||
| 572 | return ARMul_DONE; | ||
| 573 | else | ||
| 574 | return ARMul_BUSY; | ||
| 575 | } | ||
| 576 | |||
| 577 | return ARMul_CANT; | ||
| 578 | } | ||
| 579 | |||
| 580 | static unsigned | ||
| 581 | DoAFIQ (ARMul_State * state) | ||
| 582 | { | ||
| 583 | state->NfiqSig = LOW; | ||
| 584 | return 0; | ||
| 585 | } | ||
| 586 | |||
| 587 | static unsigned | ||
| 588 | DoAIRQ (ARMul_State * state) | ||
| 589 | { | ||
| 590 | state->NirqSig = LOW; | ||
| 591 | return 0; | ||
| 592 | } | ||
| 593 | |||
| 594 | static unsigned | ||
| 595 | IntCDP (ARMul_State * state, unsigned type, ARMword instr) | ||
| 596 | { | 82 | { |
| 597 | static unsigned int finish; | 83 | /* Do not allow access to these register in USER mode. */ |
| 598 | ARMword howlong; | 84 | //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode |
| 599 | 85 | if (state->Mode == USER26MODE || state->Mode == USER32MODE) | |
| 600 | howlong = ValReg[BITS (0, 3)]; | 86 | return ARMul_CANT; |
| 601 | 87 | ||
| 602 | switch ((int) BITS (20, 23)) { | 88 | /* Opcode_1should be zero. */ |
| 603 | case 0: | 89 | if (opcode_1 != 0) |
| 604 | if (type == ARMul_FIRST) { | 90 | return ARMul_CANT; |
| 605 | /* First cycle of a busy wait. */ | 91 | |
| 606 | finish = ARMul_Time (state) + howlong; | 92 | /* Different register have different access requirements. */ |
| 607 | 93 | switch (reg) { | |
| 608 | return howlong == 0 ? ARMul_DONE : ARMul_BUSY; | 94 | case 0: |
| 609 | } | 95 | case 1: |
| 610 | else if (type == ARMul_BUSY) { | 96 | /* CRm must be 0. Opcode_2 can be anything. */ |
| 611 | if (ARMul_Time (state) >= finish) | 97 | if (CRm != 0) |
| 612 | return ARMul_DONE; | 98 | return ARMul_CANT; |
| 613 | else | 99 | break; |
| 614 | return ARMul_BUSY; | 100 | case 2: |
| 615 | } | 101 | case 3: |
| 616 | return ARMul_DONE; | 102 | /* CRm must be 0. Opcode_2 must be zero. */ |
| 617 | 103 | if ((CRm != 0) || (opcode_2 != 0)) | |
| 618 | case 1: | 104 | return ARMul_CANT; |
| 619 | if (howlong == 0) | 105 | break; |
| 620 | ARMul_Abort (state, ARMul_FIQV); | 106 | case 4: |
| 621 | else | 107 | /* Access not allowed. */ |
| 622 | ARMul_ScheduleEvent (state, howlong, DoAFIQ); | 108 | return ARMul_CANT; |
| 623 | return ARMul_DONE; | 109 | case 5: |
| 624 | 110 | case 6: | |
| 625 | case 2: | 111 | /* Opcode_2 must be zero. CRm must be 0. */ |
| 626 | if (howlong == 0) | 112 | if ((CRm != 0) || (opcode_2 != 0)) |
| 627 | ARMul_Abort (state, ARMul_IRQV); | 113 | return ARMul_CANT; |
| 628 | else | 114 | break; |
| 629 | ARMul_ScheduleEvent (state, howlong, DoAIRQ); | 115 | case 7: |
| 630 | return ARMul_DONE; | 116 | /* Permissable combinations: |
| 631 | 117 | Opcode_2 CRm | |
| 632 | case 3: | 118 | 0 5 |
| 633 | state->NfiqSig = HIGH; | 119 | 0 6 |
| 634 | return ARMul_DONE; | 120 | 0 7 |
| 635 | 121 | 1 5 | |
| 636 | case 4: | 122 | 1 6 |
| 637 | state->NirqSig = HIGH; | 123 | 1 10 |
| 638 | return ARMul_DONE; | 124 | 4 10 |
| 639 | 125 | 5 2 | |
| 640 | case 5: | 126 | 6 5 */ |
| 641 | ValReg[BITS (0, 3)] = ARMul_Time (state); | 127 | switch (opcode_2) { |
| 642 | return ARMul_DONE; | 128 | default: |
| 643 | } | 129 | return ARMul_CANT; |
| 644 | 130 | case 6: | |
| 645 | return ARMul_CANT; | 131 | if (CRm != 5) |
| 132 | return ARMul_CANT; | ||
| 133 | break; | ||
| 134 | case 5: | ||
| 135 | if (CRm != 2) | ||
| 136 | return ARMul_CANT; | ||
| 137 | break; | ||
| 138 | case 4: | ||
| 139 | if (CRm != 10) | ||
| 140 | return ARMul_CANT; | ||
| 141 | break; | ||
| 142 | case 1: | ||
| 143 | if ((CRm != 5) && (CRm != 6) && (CRm != 10)) | ||
| 144 | return ARMul_CANT; | ||
| 145 | break; | ||
| 146 | case 0: | ||
| 147 | if ((CRm < 5) || (CRm > 7)) | ||
| 148 | return ARMul_CANT; | ||
| 149 | break; | ||
| 150 | } | ||
| 151 | break; | ||
| 152 | |||
| 153 | case 8: | ||
| 154 | /* Permissable combinations: | ||
| 155 | Opcode_2 CRm | ||
| 156 | 0 5 | ||
| 157 | 0 6 | ||
| 158 | 0 7 | ||
| 159 | 1 5 | ||
| 160 | 1 6 */ | ||
| 161 | if (opcode_2 > 1) | ||
| 162 | return ARMul_CANT; | ||
| 163 | if ((CRm < 5) || (CRm > 7)) | ||
| 164 | return ARMul_CANT; | ||
| 165 | if (opcode_2 == 1 && CRm == 7) | ||
| 166 | return ARMul_CANT; | ||
| 167 | break; | ||
| 168 | case 9: | ||
| 169 | /* Opcode_2 must be zero or one. CRm must be 1 or 2. */ | ||
| 170 | if (((CRm != 0) && (CRm != 1)) | ||
| 171 | || ((opcode_2 != 1) && (opcode_2 != 2))) | ||
| 172 | return ARMul_CANT; | ||
| 173 | break; | ||
| 174 | case 10: | ||
| 175 | /* Opcode_2 must be zero or one. CRm must be 4 or 8. */ | ||
| 176 | if (((CRm != 0) && (CRm != 1)) | ||
| 177 | || ((opcode_2 != 4) && (opcode_2 != 8))) | ||
| 178 | return ARMul_CANT; | ||
| 179 | break; | ||
| 180 | case 11: | ||
| 181 | /* Access not allowed. */ | ||
| 182 | return ARMul_CANT; | ||
| 183 | case 12: | ||
| 184 | /* Access not allowed. */ | ||
| 185 | return ARMul_CANT; | ||
| 186 | case 13: | ||
| 187 | /* Opcode_2 must be zero. CRm must be 0. */ | ||
| 188 | if ((CRm != 0) || (opcode_2 != 0)) | ||
| 189 | return ARMul_CANT; | ||
| 190 | break; | ||
| 191 | case 14: | ||
| 192 | /* Opcode_2 must be 0. CRm must be 0, 3, 4, 8 or 9. */ | ||
| 193 | if (opcode_2 != 0) | ||
| 194 | return ARMul_CANT; | ||
| 195 | |||
| 196 | if ((CRm != 0) && (CRm != 3) && (CRm != 4) && (CRm != 8) | ||
| 197 | && (CRm != 9)) | ||
| 198 | return ARMul_CANT; | ||
| 199 | break; | ||
| 200 | case 15: | ||
| 201 | /* Opcode_2 must be zero. CRm must be 1. */ | ||
| 202 | if ((CRm != 1) || (opcode_2 != 0)) | ||
| 203 | return ARMul_CANT; | ||
| 204 | break; | ||
| 205 | default: | ||
| 206 | /* Should never happen. */ | ||
| 207 | return ARMul_CANT; | ||
| 208 | } | ||
| 209 | |||
| 210 | return ARMul_DONE; | ||
| 646 | } | 211 | } |
| 647 | 212 | ||
| 648 | /* Install co-processor instruction handlers in this routine. */ | 213 | /* Install co-processor instruction handlers in this routine. */ |
| 649 | 214 | ||
| 650 | unsigned | 215 | unsigned |
| 651 | ARMul_CoProInit (ARMul_State * state) | 216 | ARMul_CoProInit(ARMul_State * state) |
| 652 | { | 217 | { |
| 653 | unsigned int i; | 218 | unsigned int i; |
| 654 | 219 | ||
| 655 | /* Initialise tham all first. */ | 220 | /* Initialise tham all first. */ |
| 656 | for (i = 0; i < 16; i++) | 221 | for (i = 0; i < 16; i++) |
| 657 | ARMul_CoProDetach (state, i); | 222 | ARMul_CoProDetach(state, i); |
| 658 | 223 | ||
| 659 | /* Install CoPro Instruction handlers here. | 224 | /* Install CoPro Instruction handlers here. |
| 660 | The format is: | 225 | The format is: |
| 661 | ARMul_CoProAttach (state, CP Number, Init routine, Exit routine | 226 | ARMul_CoProAttach (state, CP Number, Init routine, Exit routine |
| 662 | LDC routine, STC routine, MRC routine, MCR routine, | 227 | LDC routine, STC routine, MRC routine, MCR routine, |
| 663 | CDP routine, Read Reg routine, Write Reg routine). */ | 228 | CDP routine, Read Reg routine, Write Reg routine). */ |
| 664 | if (state->is_ep9312) { | 229 | if (state->is_v6) { |
| 665 | ARMul_CoProAttach (state, 4, NULL, NULL, DSPLDC4, DSPSTC4, | 230 | ARMul_CoProAttach(state, 10, VFPInit, NULL, VFPLDC, VFPSTC, |
| 666 | DSPMRC4, DSPMCR4, NULL, NULL, DSPCDP4, NULL, NULL); | 231 | VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL); |
| 667 | ARMul_CoProAttach (state, 5, NULL, NULL, DSPLDC5, DSPSTC5, | 232 | ARMul_CoProAttach(state, 11, VFPInit, NULL, VFPLDC, VFPSTC, |
| 668 | DSPMRC5, DSPMCR5, NULL, NULL, DSPCDP5, NULL, NULL); | 233 | VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL); |
| 669 | ARMul_CoProAttach (state, 6, NULL, NULL, NULL, NULL, | 234 | |
| 670 | DSPMRC6, DSPMCR6, NULL, NULL, DSPCDP6, NULL, NULL); | 235 | /*ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL, |
| 671 | } | 236 | MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);*/ |
| 672 | else { | 237 | } |
| 673 | ARMul_CoProAttach (state, 4, NULL, NULL, ValLDC, ValSTC, | 238 | //chy 2003-09-03 do it in future!!!!???? |
| 674 | ValMRC, ValMCR, NULL, NULL, ValCDP, NULL, NULL); | ||
| 675 | |||
| 676 | ARMul_CoProAttach (state, 5, NULL, NULL, NULL, NULL, | ||
| 677 | ValMRC, ValMCR, NULL, NULL, IntCDP, NULL, NULL); | ||
| 678 | } | ||
| 679 | |||
| 680 | if (state->is_XScale) { | ||
| 681 | //chy 2005-09-19, for PXA27x's CP6 | ||
| 682 | if (state->is_pxa27x) { | ||
| 683 | ARMul_CoProAttach (state, 6, NULL, NULL, | ||
| 684 | NULL, NULL, xscale_cp6_mrc, | ||
| 685 | NULL, NULL, NULL, NULL, NULL, NULL); | ||
| 686 | } | ||
| 687 | //chy 2005-09-19 end------------- | ||
| 688 | ARMul_CoProAttach (state, 13, xscale_cp13_init, | ||
| 689 | xscale_cp13_exit, xscale_cp13_ldc, | ||
| 690 | xscale_cp13_stc, xscale_cp13_mrc, | ||
| 691 | xscale_cp13_mcr, NULL, NULL, xscale_cp13_cdp, | ||
| 692 | xscale_cp13_read_reg, | ||
| 693 | xscale_cp13_write_reg); | ||
| 694 | |||
| 695 | ARMul_CoProAttach (state, 14, xscale_cp14_init, | ||
| 696 | xscale_cp14_exit, xscale_cp14_ldc, | ||
| 697 | xscale_cp14_stc, xscale_cp14_mrc, | ||
| 698 | xscale_cp14_mcr, NULL, NULL, xscale_cp14_cdp, | ||
| 699 | xscale_cp14_read_reg, | ||
| 700 | xscale_cp14_write_reg); | ||
| 701 | //chy: 2003-08-24. | ||
| 702 | ARMul_CoProAttach (state, 15, xscale_cp15_init, | ||
| 703 | xscale_cp15_exit, xscale_cp15_ldc, | ||
| 704 | xscale_cp15_stc, xscale_cp15_mrc, | ||
| 705 | xscale_cp15_mcr, NULL, NULL, xscale_cp15_cdp, | ||
| 706 | xscale_cp15_read_reg, | ||
| 707 | xscale_cp15_write_reg); | ||
| 708 | } | ||
| 709 | else if (state->is_v6) { | ||
| 710 | ARMul_CoProAttach (state, 10, VFPInit, NULL, VFPLDC, VFPSTC, | ||
| 711 | VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL); | ||
| 712 | ARMul_CoProAttach (state, 11, VFPInit, NULL, VFPLDC, VFPSTC, | ||
| 713 | VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL); | ||
| 714 | |||
| 715 | ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL, | ||
| 716 | MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL); | ||
| 717 | } | ||
| 718 | else { //all except xscale | ||
| 719 | ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL, | ||
| 720 | // MMUMRC, MMUMCR, NULL, MMURead, MMUWrite); | ||
| 721 | MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL); | ||
| 722 | } | ||
| 723 | //chy 2003-09-03 do it in future!!!!???? | ||
| 724 | #if 0 | 239 | #if 0 |
| 725 | if (state->is_iWMMXt) { | 240 | if (state->is_iWMMXt) { |
| 726 | ARMul_CoProAttach (state, 0, NULL, NULL, IwmmxtLDC, IwmmxtSTC, | 241 | ARMul_CoProAttach(state, 0, NULL, NULL, IwmmxtLDC, IwmmxtSTC, |
| 727 | NULL, NULL, IwmmxtCDP, NULL, NULL); | 242 | NULL, NULL, IwmmxtCDP, NULL, NULL); |
| 728 | 243 | ||
| 729 | ARMul_CoProAttach (state, 1, NULL, NULL, NULL, NULL, | 244 | ARMul_CoProAttach(state, 1, NULL, NULL, NULL, NULL, |
| 730 | IwmmxtMRC, IwmmxtMCR, IwmmxtCDP, NULL, | 245 | IwmmxtMRC, IwmmxtMCR, IwmmxtCDP, NULL, |
| 731 | NULL); | 246 | NULL); |
| 732 | } | 247 | } |
| 733 | #endif | 248 | #endif |
| 734 | //----------------------------------------------------------------------------- | 249 | /* No handlers below here. */ |
| 735 | //chy 2004-05-25, found the user/system code visit CP 1,2, so I add below code. | 250 | |
| 736 | ARMul_CoProAttach (state, 1, NULL, NULL, NULL, NULL, | 251 | /* Call all the initialisation routines. */ |
| 737 | ValMRC, ValMCR, NULL, NULL, NULL, NULL, NULL); | 252 | for (i = 0; i < 16; i++) |
| 738 | ARMul_CoProAttach (state, 2, NULL, NULL, ValLDC, ValSTC, | 253 | if (state->CPInit[i]) |
| 739 | NULL, NULL, NULL, NULL, NULL, NULL, NULL); | 254 | (state->CPInit[i]) (state); |
| 740 | //------------------------------------------------------------------------------ | 255 | |
| 741 | /* No handlers below here. */ | 256 | return TRUE; |
| 742 | |||
| 743 | /* Call all the initialisation routines. */ | ||
| 744 | for (i = 0; i < 16; i++) | ||
| 745 | if (state->CPInit[i]) | ||
| 746 | (state->CPInit[i]) (state); | ||
| 747 | |||
| 748 | return TRUE; | ||
| 749 | } | 257 | } |
| 750 | 258 | ||
| 751 | /* Install co-processor finalisation routines in this routine. */ | 259 | /* Install co-processor finalisation routines in this routine. */ |
| 752 | 260 | ||
| 753 | void | 261 | void |
| 754 | ARMul_CoProExit (ARMul_State * state) | 262 | ARMul_CoProExit(ARMul_State * state) |
| 755 | { | 263 | { |
| 756 | register unsigned i; | 264 | register unsigned i; |
| 757 | 265 | ||
| 758 | for (i = 0; i < 16; i++) | 266 | for (i = 0; i < 16; i++) |
| 759 | if (state->CPExit[i]) | 267 | if (state->CPExit[i]) |
| 760 | (state->CPExit[i]) (state); | 268 | (state->CPExit[i]) (state); |
| 761 | 269 | ||
| 762 | for (i = 0; i < 16; i++) /* Detach all handlers. */ | 270 | for (i = 0; i < 16; i++) /* Detach all handlers. */ |
| 763 | ARMul_CoProDetach (state, i); | 271 | ARMul_CoProDetach(state, i); |
| 764 | } | 272 | } |
| 765 | 273 | ||
| 766 | /* Routines to hook Co-processors into ARMulator. */ | 274 | /* Routines to hook Co-processors into ARMulator. */ |
| 767 | 275 | ||
| 768 | void | 276 | void |
| 769 | ARMul_CoProAttach (ARMul_State * state, | 277 | ARMul_CoProAttach(ARMul_State * state, |
| 770 | unsigned number, | 278 | unsigned number, |
| 771 | ARMul_CPInits * init, | 279 | ARMul_CPInits * init, |
| 772 | ARMul_CPExits * exit, | 280 | ARMul_CPExits * exit, |
| 773 | ARMul_LDCs * ldc, | 281 | ARMul_LDCs * ldc, |
| 774 | ARMul_STCs * stc, | 282 | ARMul_STCs * stc, |
| 775 | ARMul_MRCs * mrc, | 283 | ARMul_MRCs * mrc, |
| 776 | ARMul_MCRs * mcr, | 284 | ARMul_MCRs * mcr, |
| 777 | ARMul_MRRCs * mrrc, | 285 | ARMul_MRRCs * mrrc, |
| 778 | ARMul_MCRRs * mcrr, | 286 | ARMul_MCRRs * mcrr, |
| 779 | ARMul_CDPs * cdp, | 287 | ARMul_CDPs * cdp, |
| 780 | ARMul_CPReads * read, ARMul_CPWrites * write) | 288 | ARMul_CPReads * read, ARMul_CPWrites * write) |
| 781 | { | ||
| 782 | if (init != NULL) | ||
| 783 | state->CPInit[number] = init; | ||
| 784 | if (exit != NULL) | ||
| 785 | state->CPExit[number] = exit; | ||
| 786 | if (ldc != NULL) | ||
| 787 | state->LDC[number] = ldc; | ||
| 788 | if (stc != NULL) | ||
| 789 | state->STC[number] = stc; | ||
| 790 | if (mrc != NULL) | ||
| 791 | state->MRC[number] = mrc; | ||
| 792 | if (mcr != NULL) | ||
| 793 | state->MCR[number] = mcr; | ||
| 794 | if (mrrc != NULL) | ||
| 795 | state->MRRC[number] = mrrc; | ||
| 796 | if (mcrr != NULL) | ||
| 797 | state->MCRR[number] = mcrr; | ||
| 798 | if (cdp != NULL) | ||
| 799 | state->CDP[number] = cdp; | ||
| 800 | if (read != NULL) | ||
| 801 | state->CPRead[number] = read; | ||
| 802 | if (write != NULL) | ||
| 803 | state->CPWrite[number] = write; | ||
| 804 | } | ||
| 805 | |||
| 806 | void | ||
| 807 | ARMul_CoProDetach (ARMul_State * state, unsigned number) | ||
| 808 | { | 289 | { |
| 809 | ARMul_CoProAttach (state, number, NULL, NULL, | 290 | if (init != NULL) |
| 810 | NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R, | 291 | state->CPInit[number] = init; |
| 811 | NoCoPro5W, NoCoPro5R, NoCoPro3R, NULL, NULL); | 292 | if (exit != NULL) |
| 812 | 293 | state->CPExit[number] = exit; | |
| 813 | state->CPInit[number] = NULL; | 294 | if (ldc != NULL) |
| 814 | state->CPExit[number] = NULL; | 295 | state->LDC[number] = ldc; |
| 815 | state->CPRead[number] = NULL; | 296 | if (stc != NULL) |
| 816 | state->CPWrite[number] = NULL; | 297 | state->STC[number] = stc; |
| 298 | if (mrc != NULL) | ||
| 299 | state->MRC[number] = mrc; | ||
| 300 | if (mcr != NULL) | ||
| 301 | state->MCR[number] = mcr; | ||
| 302 | if (mrrc != NULL) | ||
| 303 | state->MRRC[number] = mrrc; | ||
| 304 | if (mcrr != NULL) | ||
| 305 | state->MCRR[number] = mcrr; | ||
| 306 | if (cdp != NULL) | ||
| 307 | state->CDP[number] = cdp; | ||
| 308 | if (read != NULL) | ||
| 309 | state->CPRead[number] = read; | ||
| 310 | if (write != NULL) | ||
| 311 | state->CPWrite[number] = write; | ||
| 817 | } | 312 | } |
| 818 | 313 | ||
| 819 | //chy 2003-09-03:below funs just replace the old ones | ||
| 820 | |||
| 821 | /* Set the XScale FSR and FAR registers. */ | ||
| 822 | |||
| 823 | void | 314 | void |
| 824 | XScale_set_fsr_far (ARMul_State * state, ARMword fsr, ARMword _far) | 315 | ARMul_CoProDetach(ARMul_State * state, unsigned number) |
| 825 | { | ||
| 826 | //if (!state->is_XScale || (read_cp14_reg (10) & (1UL << 31)) == 0) | ||
| 827 | if (!state->is_XScale) | ||
| 828 | return; | ||
| 829 | //assume opcode2=0 crm =0 | ||
| 830 | xscale_cp15_write_reg (state, 5, fsr); | ||
| 831 | xscale_cp15_write_reg (state, 6, _far); | ||
| 832 | } | ||
| 833 | |||
| 834 | //chy 2003-09-03 seems 0 is CANT, 1 is DONE ???? | ||
| 835 | int | ||
| 836 | XScale_debug_moe (ARMul_State * state, int moe) | ||
| 837 | { | 316 | { |
| 838 | //chy 2003-09-03 , W/R CP14 reg, now it's no use ???? | 317 | ARMul_CoProAttach(state, number, NULL, NULL, |
| 839 | printf ("SKYEYE: XScale_debug_moe called !!!!\n"); | 318 | NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R, |
| 840 | return 1; | 319 | NoCoPro5W, NoCoPro5R, NoCoPro3R, NULL, NULL); |
| 320 | |||
| 321 | state->CPInit[number] = NULL; | ||
| 322 | state->CPExit[number] = NULL; | ||
| 323 | state->CPRead[number] = NULL; | ||
| 324 | state->CPWrite[number] = NULL; | ||
| 841 | } | 325 | } |
diff --git a/src/core/arm/interpreter/armmmu.cpp b/src/core/arm/interpreter/armmmu.cpp deleted file mode 100644 index 98fc17ddb..000000000 --- a/src/core/arm/interpreter/armmmu.cpp +++ /dev/null | |||
| @@ -1,238 +0,0 @@ | |||
| 1 | /* | ||
| 2 | armmmu.c - Memory Management Unit emulation. | ||
| 3 | ARMulator extensions for the ARM7100 family. | ||
| 4 | Copyright (C) 1999 Ben Williamson | ||
| 5 | |||
| 6 | This program is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 2 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | This program is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with this program; if not, write to the Free Software | ||
| 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <assert.h> | ||
| 22 | #include <string.h> | ||
| 23 | #include "core/arm/skyeye_common/armdefs.h" | ||
| 24 | /* two header for arm disassemble */ | ||
| 25 | //#include "skyeye_arch.h" | ||
| 26 | #include "core/arm/skyeye_common/armcpu.h" | ||
| 27 | |||
| 28 | |||
| 29 | extern mmu_ops_t xscale_mmu_ops; | ||
| 30 | exception_t arm_mmu_write(short size, u32 addr, uint32_t *value); | ||
| 31 | exception_t arm_mmu_read(short size, u32 addr, uint32_t *value); | ||
| 32 | #define MMU_OPS (state->mmu.ops) | ||
| 33 | ARMword skyeye_cachetype = -1; | ||
| 34 | |||
| 35 | int | ||
| 36 | mmu_init (ARMul_State * state) | ||
| 37 | { | ||
| 38 | int ret; | ||
| 39 | |||
| 40 | state->mmu.control = 0x70; | ||
| 41 | state->mmu.translation_table_base = 0xDEADC0DE; | ||
| 42 | state->mmu.domain_access_control = 0xDEADC0DE; | ||
| 43 | state->mmu.fault_status = 0; | ||
| 44 | state->mmu.fault_address = 0; | ||
| 45 | state->mmu.process_id = 0; | ||
| 46 | |||
| 47 | switch (state->cpu->cpu_val & state->cpu->cpu_mask) { | ||
| 48 | //case SA1100: | ||
| 49 | //case SA1110: | ||
| 50 | // NOTICE_LOG(ARM11, "SKYEYE: use sa11xx mmu ops\n"); | ||
| 51 | // state->mmu.ops = sa_mmu_ops; | ||
| 52 | // break; | ||
| 53 | //case PXA250: | ||
| 54 | //case PXA270: //xscale | ||
| 55 | // NOTICE_LOG(ARM11, "SKYEYE: use xscale mmu ops\n"); | ||
| 56 | // state->mmu.ops = xscale_mmu_ops; | ||
| 57 | // break; | ||
| 58 | //case 0x41807200: //arm720t | ||
| 59 | //case 0x41007700: //arm7tdmi | ||
| 60 | //case 0x41007100: //arm7100 | ||
| 61 | // NOTICE_LOG(ARM11, "SKYEYE: use arm7100 mmu ops\n"); | ||
| 62 | // state->mmu.ops = arm7100_mmu_ops; | ||
| 63 | // break; | ||
| 64 | //case 0x41009200: | ||
| 65 | // NOTICE_LOG(ARM11, "SKYEYE: use arm920t mmu ops\n"); | ||
| 66 | // state->mmu.ops = arm920t_mmu_ops; | ||
| 67 | // break; | ||
| 68 | //case 0x41069260: | ||
| 69 | // NOTICE_LOG(ARM11, "SKYEYE: use arm926ejs mmu ops\n"); | ||
| 70 | // state->mmu.ops = arm926ejs_mmu_ops; | ||
| 71 | // break; | ||
| 72 | /* case 0x560f5810: */ | ||
| 73 | case 0x0007b000: | ||
| 74 | NOTICE_LOG(ARM11, "SKYEYE: use arm11jzf-s mmu ops\n"); | ||
| 75 | state->mmu.ops = arm1176jzf_s_mmu_ops; | ||
| 76 | break; | ||
| 77 | |||
| 78 | default: | ||
| 79 | ERROR_LOG (ARM11, | ||
| 80 | "SKYEYE: armmmu.c : mmu_init: unknown cpu_val&cpu_mask 0x%x\n", | ||
| 81 | state->cpu->cpu_val & state->cpu->cpu_mask); | ||
| 82 | break; | ||
| 83 | |||
| 84 | }; | ||
| 85 | ret = state->mmu.ops.init (state); | ||
| 86 | state->mmu_inited = (ret == 0); | ||
| 87 | /* initialize mmu_read and mmu_write for disassemble */ | ||
| 88 | //skyeye_config_t *config = get_current_config(); | ||
| 89 | //generic_arch_t *arch_instance = get_arch_instance(config->arch->arch_name); | ||
| 90 | //arch_instance->mmu_read = arm_mmu_read; | ||
| 91 | //arch_instance->mmu_write = arm_mmu_write; | ||
| 92 | |||
| 93 | return ret; | ||
| 94 | } | ||
| 95 | |||
| 96 | int | ||
| 97 | mmu_reset (ARMul_State * state) | ||
| 98 | { | ||
| 99 | if (state->mmu_inited) | ||
| 100 | mmu_exit (state); | ||
| 101 | return mmu_init (state); | ||
| 102 | } | ||
| 103 | |||
| 104 | void | ||
| 105 | mmu_exit (ARMul_State * state) | ||
| 106 | { | ||
| 107 | MMU_OPS.exit (state); | ||
| 108 | state->mmu_inited = 0; | ||
| 109 | } | ||
| 110 | |||
| 111 | fault_t | ||
| 112 | mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data) | ||
| 113 | { | ||
| 114 | return MMU_OPS.read_byte (state, virt_addr, data); | ||
| 115 | }; | ||
| 116 | |||
| 117 | fault_t | ||
| 118 | mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data) | ||
| 119 | { | ||
| 120 | return MMU_OPS.read_halfword (state, virt_addr, data); | ||
| 121 | }; | ||
| 122 | |||
| 123 | fault_t | ||
| 124 | mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data) | ||
| 125 | { | ||
| 126 | return MMU_OPS.read_word (state, virt_addr, data); | ||
| 127 | }; | ||
| 128 | |||
| 129 | fault_t | ||
| 130 | mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data) | ||
| 131 | { | ||
| 132 | fault_t fault; | ||
| 133 | //static int count = 0; | ||
| 134 | //count ++; | ||
| 135 | fault = MMU_OPS.write_byte (state, virt_addr, data); | ||
| 136 | return fault; | ||
| 137 | } | ||
| 138 | |||
| 139 | fault_t | ||
| 140 | mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data) | ||
| 141 | { | ||
| 142 | fault_t fault; | ||
| 143 | //static int count = 0; | ||
| 144 | //count ++; | ||
| 145 | fault = MMU_OPS.write_halfword (state, virt_addr, data); | ||
| 146 | return fault; | ||
| 147 | } | ||
| 148 | |||
| 149 | fault_t | ||
| 150 | mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data) | ||
| 151 | { | ||
| 152 | fault_t fault; | ||
| 153 | fault = MMU_OPS.write_word (state, virt_addr, data); | ||
| 154 | |||
| 155 | /*used for debug for MMU* | ||
| 156 | |||
| 157 | if (!fault){ | ||
| 158 | ARMword tmp; | ||
| 159 | |||
| 160 | if (mmu_read_word(state, virt_addr, &tmp)){ | ||
| 161 | err_msg("load back\n"); | ||
| 162 | exit(-1); | ||
| 163 | }else{ | ||
| 164 | if (tmp != data){ | ||
| 165 | err_msg("load back not equal %d %x\n", count, virt_addr); | ||
| 166 | } | ||
| 167 | } | ||
| 168 | } | ||
| 169 | */ | ||
| 170 | |||
| 171 | return fault; | ||
| 172 | }; | ||
| 173 | |||
| 174 | fault_t | ||
| 175 | mmu_load_instr (ARMul_State * state, ARMword virt_addr, ARMword * instr) | ||
| 176 | { | ||
| 177 | return MMU_OPS.load_instr (state, virt_addr, instr); | ||
| 178 | } | ||
| 179 | |||
| 180 | ARMword | ||
| 181 | mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value) | ||
| 182 | { | ||
| 183 | return MMU_OPS.mrc (state, instr, value); | ||
| 184 | } | ||
| 185 | |||
| 186 | void | ||
| 187 | mmu_mcr (ARMul_State * state, ARMword instr, ARMword value) | ||
| 188 | { | ||
| 189 | MMU_OPS.mcr (state, instr, value); | ||
| 190 | } | ||
| 191 | |||
| 192 | /*ywc 20050416*/ | ||
| 193 | int | ||
| 194 | mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, ARMword * phys_addr) | ||
| 195 | { | ||
| 196 | return (MMU_OPS.v2p_dbct (state, virt_addr, phys_addr)); | ||
| 197 | } | ||
| 198 | |||
| 199 | // | ||
| 200 | // | ||
| 201 | ///* dis_mmu_read for disassemble */ | ||
| 202 | //exception_t arm_mmu_read(short size, uint32_t addr, uint32_t * value) | ||
| 203 | //{ | ||
| 204 | // ARMul_State *state; | ||
| 205 | // ARM_CPU_State *cpu = get_current_cpu(); | ||
| 206 | // state = &cpu->core[0]; | ||
| 207 | // switch(size){ | ||
| 208 | // case 8: | ||
| 209 | // MMU_OPS.read_byte (state, addr, value); | ||
| 210 | // break; | ||
| 211 | // case 16: | ||
| 212 | // case 32: | ||
| 213 | // break; | ||
| 214 | // default: | ||
| 215 | // ERROR_LOG(ARM11, "Error size %d", size); | ||
| 216 | // break; | ||
| 217 | // } | ||
| 218 | // return No_exp; | ||
| 219 | //} | ||
| 220 | ///* dis_mmu_write for disassemble */ | ||
| 221 | //exception_t arm_mmu_write(short size, uint32_t addr, uint32_t *value) | ||
| 222 | //{ | ||
| 223 | // ARMul_State *state; | ||
| 224 | // ARM_CPU_State *cpu = get_current_cpu(); | ||
| 225 | // state = &cpu->core[0]; | ||
| 226 | // switch(size){ | ||
| 227 | // case 8: | ||
| 228 | // MMU_OPS.write_byte (state, addr, value); | ||
| 229 | // break; | ||
| 230 | // case 16: | ||
| 231 | // case 32: | ||
| 232 | // break; | ||
| 233 | // default: | ||
| 234 | // printf("In %s error size %d Line %d\n", __func__, size, __LINE__); | ||
| 235 | // break; | ||
| 236 | // } | ||
| 237 | // return No_exp; | ||
| 238 | //} | ||
diff --git a/src/core/arm/interpreter/armvirt.cpp b/src/core/arm/interpreter/armvirt.cpp index eb3c86cb4..7845d1042 100644 --- a/src/core/arm/interpreter/armvirt.cpp +++ b/src/core/arm/interpreter/armvirt.cpp | |||
| @@ -24,657 +24,142 @@ freed as they might be needed again. A single area of memory may be | |||
| 24 | defined to generate aborts. */ | 24 | defined to generate aborts. */ |
| 25 | 25 | ||
| 26 | #include "core/arm/skyeye_common/armdefs.h" | 26 | #include "core/arm/skyeye_common/armdefs.h" |
| 27 | #include "core/arm/skyeye_common/skyeye_defs.h" | 27 | #include "core/arm/skyeye_common/armemu.h" |
| 28 | //#include "code_cov.h" | ||
| 29 | 28 | ||
| 30 | #ifdef VALIDATE /* for running the validate suite */ | 29 | #include "core/mem_map.h" |
| 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 | 30 | ||
| 91 | static fault_t | 31 | #define dumpstack 1 |
| 92 | GetWord (ARMul_State * state, ARMword address, ARMword * data) | 32 | #define dumpstacksize 0x10 |
| 93 | { | 33 | #define maxdmupaddr 0x0033a850 |
| 94 | fault_t fault; | ||
| 95 | 34 | ||
| 96 | fault = mmu_read_word (state, address, data); | 35 | /*ARMword ARMul_GetCPSR (ARMul_State * state) { |
| 97 | if (fault) { | 36 | return 0; |
| 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 | } | 37 | } |
| 132 | 38 | ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode) { | |
| 133 | //2003-07-10 chy: lyh change | 39 | return 0; |
| 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 | } | 40 | } |
| 41 | void ARMul_SetCPSR (ARMul_State * state, ARMword value) { | ||
| 146 | 42 | ||
| 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 | } | 43 | } |
| 44 | void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value) { | ||
| 162 | 45 | ||
| 163 | /***************************************************************************\ | 46 | }*/ |
| 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 | 47 | ||
| 171 | fault = mmu_write_halfword (state, address, data); | 48 | void ARMul_Icycles(ARMul_State * state, unsigned number, ARMword address) { |
| 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 | } | 49 | } |
| 178 | 50 | ||
| 179 | /***************************************************************************\ | 51 | void ARMul_Ccycles(ARMul_State * state, unsigned number, ARMword address) { |
| 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 | } | 52 | } |
| 224 | 53 | ||
| 225 | /***************************************************************************\ | 54 | ARMword ARMul_LoadInstrS(ARMul_State * state, ARMword address, ARMword isize) { |
| 226 | * Initialise the memory interface * | 55 | state->NumScycles++; |
| 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 | 56 | ||
| 334 | #ifdef HOURGLASS | 57 | #ifdef HOURGLASS |
| 335 | if ((state->NumScycles & HOURGLASS_RATE) == 0) { | 58 | if ((state->NumScycles & HOURGLASS_RATE) == 0) { |
| 336 | HOURGLASS; | 59 | HOURGLASS; |
| 337 | } | 60 | } |
| 338 | #endif | 61 | #endif |
| 339 | 62 | if (isize == 2) | |
| 340 | return ARMul_ReLoadInstr (state, address, isize); | 63 | return (u16)Memory::Read16(address); |
| 64 | else | ||
| 65 | return (u32)Memory::Read32(address); | ||
| 341 | } | 66 | } |
| 342 | 67 | ||
| 343 | /***************************************************************************\ | 68 | ARMword ARMul_LoadInstrN(ARMul_State * state, ARMword address, ARMword isize) { |
| 344 | * Load Instruction, Non Sequential Cycle * | 69 | state->NumNcycles++; |
| 345 | \***************************************************************************/ | ||
| 346 | |||
| 347 | ARMword | ||
| 348 | ARMul_LoadInstrN (ARMul_State * state, ARMword address, ARMword isize) | ||
| 349 | { | ||
| 350 | state->NumNcycles++; | ||
| 351 | 70 | ||
| 352 | return ARMul_ReLoadInstr (state, address, isize); | 71 | if (isize == 2) |
| 72 | return (u16)Memory::Read16(address); | ||
| 73 | else | ||
| 74 | return (u32)Memory::Read32(address); | ||
| 353 | } | 75 | } |
| 354 | 76 | ||
| 355 | /***************************************************************************\ | 77 | ARMword ARMul_ReLoadInstr(ARMul_State * state, ARMword address, ARMword isize) { |
| 356 | * Read Word (but don't tell anyone!) * | 78 | ARMword data; |
| 357 | \***************************************************************************/ | ||
| 358 | 79 | ||
| 359 | ARMword | 80 | if ((isize == 2) && (address & 0x2)) { |
| 360 | ARMul_ReadWord (ARMul_State * state, ARMword address) | 81 | ARMword lo; |
| 361 | { | 82 | lo = (u16)Memory::Read16(address); |
| 362 | ARMword data; | 83 | return lo; |
| 363 | fault_t fault; | 84 | } |
| 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 | 85 | ||
| 375 | fault = GetWord (state, address, &data); | 86 | data = (u32)Memory::Read32(address); |
| 376 | if (fault) { | 87 | return data; |
| 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 | } | 88 | } |
| 388 | 89 | ||
| 389 | /***************************************************************************\ | 90 | ARMword ARMul_ReadWord(ARMul_State * state, ARMword address) { |
| 390 | * Load Word, Sequential Cycle * | 91 | ARMword data; |
| 391 | \***************************************************************************/ | 92 | data = Memory::Read32(address); |
| 392 | 93 | return data; | |
| 393 | ARMword | ||
| 394 | ARMul_LoadWordS (ARMul_State * state, ARMword address) | ||
| 395 | { | ||
| 396 | state->NumScycles++; | ||
| 397 | |||
| 398 | return ARMul_ReadWord (state, address); | ||
| 399 | } | 94 | } |
| 400 | 95 | ||
| 401 | /***************************************************************************\ | 96 | ARMword ARMul_LoadWordS(ARMul_State * state, ARMword address) { |
| 402 | * Load Word, Non Sequential Cycle * | 97 | state->NumScycles++; |
| 403 | \***************************************************************************/ | 98 | return ARMul_ReadWord(state, address); |
| 404 | |||
| 405 | ARMword | ||
| 406 | ARMul_LoadWordN (ARMul_State * state, ARMword address) | ||
| 407 | { | ||
| 408 | state->NumNcycles++; | ||
| 409 | |||
| 410 | return ARMul_ReadWord (state, address); | ||
| 411 | } | 99 | } |
| 412 | 100 | ||
| 413 | /***************************************************************************\ | 101 | ARMword ARMul_LoadWordN(ARMul_State * state, ARMword address) { |
| 414 | * Load Halfword, (Non Sequential Cycle) * | 102 | state->NumNcycles++; |
| 415 | \***************************************************************************/ | 103 | return ARMul_ReadWord(state, address); |
| 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 | } | 104 | } |
| 440 | 105 | ||
| 441 | /***************************************************************************\ | 106 | ARMword ARMul_LoadHalfWord(ARMul_State * state, ARMword address) { |
| 442 | * Read Byte (but don't tell anyone!) * | 107 | state->NumNcycles++; |
| 443 | \***************************************************************************/ | 108 | return (u16)Memory::Read16(address);; |
| 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 | } | 109 | } |
| 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 | 110 | ||
| 511 | fault = PutWord (state, address, data); | 111 | ARMword ARMul_ReadByte(ARMul_State * state, ARMword address) { |
| 512 | if (fault) { | 112 | return (u8)Memory::Read8(address); |
| 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 | } | 113 | } |
| 523 | 114 | ||
| 524 | /***************************************************************************\ | 115 | ARMword ARMul_LoadByte(ARMul_State * state, ARMword address) { |
| 525 | * Store Word, Sequential Cycle * | 116 | state->NumNcycles++; |
| 526 | \***************************************************************************/ | 117 | return ARMul_ReadByte(state, address); |
| 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 | } | 118 | } |
| 535 | 119 | ||
| 536 | /***************************************************************************\ | 120 | void ARMul_StoreHalfWord(ARMul_State * state, ARMword address, ARMword data) { |
| 537 | * Store Word, Non Sequential Cycle * | 121 | state->NumNcycles++; |
| 538 | \***************************************************************************/ | 122 | Memory::Write16(address, data); |
| 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 | } | 123 | } |
| 547 | 124 | ||
| 548 | /***************************************************************************\ | 125 | void ARMul_StoreByte(ARMul_State * state, ARMword address, ARMword data) { |
| 549 | * Store HalfWord, (Non Sequential Cycle) * | 126 | state->NumNcycles++; |
| 550 | \***************************************************************************/ | 127 | ARMul_WriteByte(state, address, data); |
| 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 | } | 128 | } |
| 569 | 129 | ||
| 570 | //chy 2006-04-15 | 130 | ARMword ARMul_SwapWord(ARMul_State * state, ARMword address, ARMword data) { |
| 571 | int ARMul_ICE_WriteByte (ARMul_State * state, ARMword address, ARMword data) | 131 | ARMword temp; |
| 572 | { | 132 | state->NumNcycles++; |
| 573 | fault_t fault; | 133 | temp = ARMul_ReadWord(state, address); |
| 574 | fault = PutByte (state, address, data); | 134 | state->NumNcycles++; |
| 575 | if (fault) | 135 | Memory::Write32(address, data); |
| 576 | return 1; | 136 | return temp; |
| 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 | } | 137 | } |
| 600 | 138 | ||
| 601 | /***************************************************************************\ | 139 | ARMword ARMul_SwapByte(ARMul_State * state, ARMword address, ARMword data) { |
| 602 | * Store Byte, (Non Sequential Cycle) * | 140 | ARMword temp; |
| 603 | \***************************************************************************/ | 141 | temp = ARMul_LoadByte(state, address); |
| 604 | 142 | Memory::Write8(address, data); | |
| 605 | void | 143 | return temp; |
| 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 | } | 144 | } |
| 622 | 145 | ||
| 623 | /***************************************************************************\ | 146 | void ARMul_WriteWord(ARMul_State * state, ARMword address, ARMword data) { |
| 624 | * Swap Word, (Two Non Sequential Cycles) * | 147 | Memory::Write32(address, data); |
| 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 | } | 148 | } |
| 642 | 149 | ||
| 643 | /***************************************************************************\ | 150 | void ARMul_WriteByte(ARMul_State * state, ARMword address, ARMword data) |
| 644 | * Swap Byte, (Two Non Sequential Cycles) * | ||
| 645 | \***************************************************************************/ | ||
| 646 | |||
| 647 | ARMword | ||
| 648 | ARMul_SwapByte (ARMul_State * state, ARMword address, ARMword data) | ||
| 649 | { | 151 | { |
| 650 | ARMword temp; | 152 | Memory::Write8(address, data); |
| 651 | |||
| 652 | temp = ARMul_LoadByte (state, address); | ||
| 653 | ARMul_StoreByte (state, address, data); | ||
| 654 | |||
| 655 | return temp; | ||
| 656 | } | 153 | } |
| 657 | 154 | ||
| 658 | /***************************************************************************\ | 155 | void ARMul_StoreWordS(ARMul_State * state, ARMword address, ARMword data) |
| 659 | * Count I Cycles * | ||
| 660 | \***************************************************************************/ | ||
| 661 | |||
| 662 | void | ||
| 663 | ARMul_Icycles (ARMul_State * state, unsigned number, | ||
| 664 | ARMword address) | ||
| 665 | { | 156 | { |
| 666 | state->NumIcycles += number; | 157 | state->NumScycles++; |
| 667 | ARMul_CLEARABORT; | 158 | ARMul_WriteWord(state, address, data); |
| 668 | } | 159 | } |
| 669 | 160 | ||
| 670 | /***************************************************************************\ | 161 | void ARMul_StoreWordN(ARMul_State * state, ARMword address, ARMword data) |
| 671 | * Count C Cycles * | ||
| 672 | \***************************************************************************/ | ||
| 673 | |||
| 674 | void | ||
| 675 | ARMul_Ccycles (ARMul_State * state, unsigned number, | ||
| 676 | ARMword address) | ||
| 677 | { | 162 | { |
| 678 | state->NumCcycles += number; | 163 | state->NumNcycles++; |
| 679 | ARMul_CLEARABORT; | 164 | ARMul_WriteWord(state, address, data); |
| 680 | } | 165 | } |
diff --git a/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp b/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp deleted file mode 100644 index 07951e0e6..000000000 --- a/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.cpp +++ /dev/null | |||
| @@ -1,1132 +0,0 @@ | |||
| 1 | /* | ||
| 2 | arm1176jzf_s_mmu.c - ARM920T Memory Management Unit emulation. | ||
| 3 | Copyright (C) 2003 Skyeye Develop Group | ||
| 4 | for help please send mail to <skyeye-developer@lists.gro.clinux.org> | ||
| 5 | |||
| 6 | This program is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 2 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | This program is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with this program; if not, write to the Free Software | ||
| 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <assert.h> | ||
| 22 | #include <string.h> | ||
| 23 | #include <stdint.h> | ||
| 24 | |||
| 25 | #include "core/mem_map.h" | ||
| 26 | |||
| 27 | #include "core/arm/skyeye_common/skyeye_defs.h" | ||
| 28 | |||
| 29 | #include "core/arm/skyeye_common/armdefs.h" | ||
| 30 | //#include "bank_defs.h" | ||
| 31 | #if 0 | ||
| 32 | #define TLB_SIZE 1024 * 1024 | ||
| 33 | #define ASID 255 | ||
| 34 | static uint32_t tlb_entry_array[TLB_SIZE][ASID]; | ||
| 35 | static inline void invalidate_all_tlb(ARMul_State *state){ | ||
| 36 | memset(&tlb_entry_array[0], 0xFF, sizeof(uint32_t) * TLB_SIZE * ASID); | ||
| 37 | } | ||
| 38 | static inline void invalidate_by_mva(ARMul_State *state, ARMword va){ | ||
| 39 | memset(&tlb_entry_array[va >> 12][va & 0xFF], 0xFF, sizeof(uint32_t)); | ||
| 40 | return; | ||
| 41 | } | ||
| 42 | static inline void invalidate_by_asid(ARMul_State *state, ARMword asid){ | ||
| 43 | int i; | ||
| 44 | for(i = 0; i < TLB_SIZE; i++) | ||
| 45 | memset(&tlb_entry_array[i][asid & 0xFF], 0xFF, sizeof(uint32_t)); | ||
| 46 | return; | ||
| 47 | } | ||
| 48 | |||
| 49 | static uint32_t get_phys_page(ARMul_State* state, ARMword va){ | ||
| 50 | uint32_t phys_page = tlb_entry_array[va >> 12][state->mmu.context_id & 0xFF]; | ||
| 51 | //printf("In %s, for va=0x%x, page=0x%x\n", __func__, va, phys_page); | ||
| 52 | return phys_page; | ||
| 53 | } | ||
| 54 | |||
| 55 | static inline void insert_tlb(ARMul_State* state, ARMword va, ARMword pa){ | ||
| 56 | //printf("In %s, insert va=0x%x, pa=0x%x\n", __FUNCTION__, va, pa); | ||
| 57 | //printf("In %s, insert va=0x%x, va>>12=0x%x, pa=0x%x, pa>>12=0x%x\n", __FUNCTION__, va, va >> 12, pa, pa >> 12); | ||
| 58 | tlb_entry_array[va >> 12][state->mmu.context_id & 0xFF] = pa >> 12; | ||
| 59 | |||
| 60 | return; | ||
| 61 | } | ||
| 62 | #endif | ||
| 63 | #define BANK0_START 0x50000000 | ||
| 64 | static void* mem_ptr = NULL; | ||
| 65 | |||
| 66 | static int exclusive_detect(ARMul_State* state, ARMword addr){ | ||
| 67 | #if 0 | ||
| 68 | for(int i = 0; i < 128; i++){ | ||
| 69 | if(state->exclusive_tag_array[i] == addr) | ||
| 70 | return 0; | ||
| 71 | } | ||
| 72 | #endif | ||
| 73 | if(state->exclusive_tag_array[0] == addr) | ||
| 74 | return 0; | ||
| 75 | else | ||
| 76 | return -1; | ||
| 77 | } | ||
| 78 | |||
| 79 | static void add_exclusive_addr(ARMul_State* state, ARMword addr){ | ||
| 80 | #if 0 | ||
| 81 | for(int i = 0; i < 128; i++){ | ||
| 82 | if(state->exclusive_tag_array[i] == 0xffffffff){ | ||
| 83 | state->exclusive_tag_array[i] = addr; | ||
| 84 | //printf("In %s, add addr 0x%x\n", __func__, addr); | ||
| 85 | return; | ||
| 86 | } | ||
| 87 | } | ||
| 88 | printf("In %s ,can not monitor the addr, out of array\n", __FUNCTION__); | ||
| 89 | #endif | ||
| 90 | state->exclusive_tag_array[0] = addr; | ||
| 91 | return; | ||
| 92 | } | ||
| 93 | |||
| 94 | static void remove_exclusive(ARMul_State* state, ARMword addr){ | ||
| 95 | #if 0 | ||
| 96 | int i; | ||
| 97 | for(i = 0; i < 128; i++){ | ||
| 98 | if(state->exclusive_tag_array[i] == addr){ | ||
| 99 | state->exclusive_tag_array[i] = 0xffffffff; | ||
| 100 | //printf("In %s, remove addr 0x%x\n", __func__, addr); | ||
| 101 | return; | ||
| 102 | } | ||
| 103 | } | ||
| 104 | #endif | ||
| 105 | state->exclusive_tag_array[0] = 0xFFFFFFFF; | ||
| 106 | } | ||
| 107 | |||
| 108 | /* This function encodes table 8-2 Interpreting AP bits, | ||
| 109 | returning non-zero if access is allowed. */ | ||
| 110 | static int | ||
| 111 | check_perms (ARMul_State *state, int ap, int read) | ||
| 112 | { | ||
| 113 | int s, r, user; | ||
| 114 | |||
| 115 | s = state->mmu.control & CONTROL_SYSTEM; | ||
| 116 | r = state->mmu.control & CONTROL_ROM; | ||
| 117 | /* chy 2006-02-15 , should consider system mode, don't conside 26bit mode */ | ||
| 118 | // printf("ap is %x, user is %x, s is %x, read is %x\n", ap, user, s, read); | ||
| 119 | // printf("mode is %x\n", state->Mode); | ||
| 120 | user = (state->Mode == USER32MODE) || (state->Mode == USER26MODE) || (state->Mode == SYSTEM32MODE); | ||
| 121 | |||
| 122 | switch (ap) { | ||
| 123 | case 0: | ||
| 124 | return read && ((s && !user) || r); | ||
| 125 | case 1: | ||
| 126 | return !user; | ||
| 127 | case 2: | ||
| 128 | return read || !user; | ||
| 129 | case 3: | ||
| 130 | return 1; | ||
| 131 | } | ||
| 132 | return 0; | ||
| 133 | } | ||
| 134 | |||
| 135 | #if 0 | ||
| 136 | fault_t | ||
| 137 | check_access (ARMul_State *state, ARMword virt_addr, tlb_entry_t *tlb, | ||
| 138 | int read) | ||
| 139 | { | ||
| 140 | int access; | ||
| 141 | |||
| 142 | state->mmu.last_domain = tlb->domain; | ||
| 143 | access = (state->mmu.domain_access_control >> (tlb->domain * 2)) & 3; | ||
| 144 | if ((access == 0) || (access == 2)) { | ||
| 145 | /* It's unclear from the documentation whether this | ||
| 146 | should always raise a section domain fault, or if | ||
| 147 | it should be a page domain fault in the case of an | ||
| 148 | L1 that describes a page table. In the ARM710T | ||
| 149 | datasheets, "Figure 8-9: Sequence for checking faults" | ||
| 150 | seems to indicate the former, while "Table 8-4: Priority | ||
| 151 | encoding of fault status" gives a value for FS[3210] in | ||
| 152 | the event of a domain fault for a page. Hmm. */ | ||
| 153 | return SECTION_DOMAIN_FAULT; | ||
| 154 | } | ||
| 155 | if (access == 1) { | ||
| 156 | /* client access - check perms */ | ||
| 157 | int subpage, ap; | ||
| 158 | #if 0 | ||
| 159 | switch (tlb->mapping) { | ||
| 160 | /*ks 2004-05-09 | ||
| 161 | * only for XScale | ||
| 162 | * Extend Small Page(ESP) Format | ||
| 163 | * 31-12 bits the base addr of ESP | ||
| 164 | * 11-10 bits SBZ | ||
| 165 | * 9-6 bits TEX | ||
| 166 | * 5-4 bits AP | ||
| 167 | * 3 bit C | ||
| 168 | * 2 bit B | ||
| 169 | * 1-0 bits 11 | ||
| 170 | * */ | ||
| 171 | case TLB_ESMALLPAGE: /* xj */ | ||
| 172 | subpage = 0; | ||
| 173 | /* printf("TLB_ESMALLPAGE virt_addr=0x%x \n",virt_addr ); */ | ||
| 174 | break; | ||
| 175 | |||
| 176 | case TLB_TINYPAGE: | ||
| 177 | subpage = 0; | ||
| 178 | /* printf("TLB_TINYPAGE virt_addr=0x%x \n",virt_addr ); */ | ||
| 179 | break; | ||
| 180 | |||
| 181 | case TLB_SMALLPAGE: | ||
| 182 | subpage = (virt_addr >> 10) & 3; | ||
| 183 | break; | ||
| 184 | case TLB_LARGEPAGE: | ||
| 185 | subpage = (virt_addr >> 14) & 3; | ||
| 186 | break; | ||
| 187 | case TLB_SECTION: | ||
| 188 | subpage = 3; | ||
| 189 | break; | ||
| 190 | default: | ||
| 191 | assert (0); | ||
| 192 | subpage = 0; /* cleans a warning */ | ||
| 193 | } | ||
| 194 | ap = (tlb->perms >> (subpage * 2 + 4)) & 3; | ||
| 195 | if (!check_perms (state, ap, read)) { | ||
| 196 | if (tlb->mapping == TLB_SECTION) { | ||
| 197 | return SECTION_PERMISSION_FAULT; | ||
| 198 | } else { | ||
| 199 | return SUBPAGE_PERMISSION_FAULT; | ||
| 200 | } | ||
| 201 | } | ||
| 202 | #endif | ||
| 203 | } else { /* access == 3 */ | ||
| 204 | /* manager access - don't check perms */ | ||
| 205 | } | ||
| 206 | return NO_FAULT; | ||
| 207 | } | ||
| 208 | #endif | ||
| 209 | |||
| 210 | #if 0 | ||
| 211 | fault_t | ||
| 212 | mmu_translate (ARMul_State *state, ARMword virt_addr, ARMword *phys_addr) | ||
| 213 | #endif | ||
| 214 | |||
| 215 | /* ap: AP bits value. | ||
| 216 | * sop: section or page description 0:section 1:page | ||
| 217 | */ | ||
| 218 | fault_t | ||
| 219 | mmu_translate (ARMul_State *state, ARMword virt_addr, ARMword *phys_addr, int *ap, int *sop) | ||
| 220 | { | ||
| 221 | { | ||
| 222 | /* walk the translation tables */ | ||
| 223 | ARMword l1addr, l1desc; | ||
| 224 | if (state->mmu.translation_table_ctrl && virt_addr << state->mmu.translation_table_ctrl >> (32 - state->mmu.translation_table_ctrl - 1)) { | ||
| 225 | l1addr = state->mmu.translation_table_base1; | ||
| 226 | l1addr = (((l1addr >> 14) << 14) | (virt_addr >> 18)) & ~3; | ||
| 227 | } else { | ||
| 228 | l1addr = state->mmu.translation_table_base0; | ||
| 229 | l1addr = (((l1addr >> (14 - state->mmu.translation_table_ctrl)) << (14 - state->mmu.translation_table_ctrl)) | (virt_addr << state->mmu.translation_table_ctrl) >> (18 + state->mmu.translation_table_ctrl)) & ~3; | ||
| 230 | } | ||
| 231 | |||
| 232 | /* l1desc = mem_read_word (state, l1addr); */ | ||
| 233 | if (state->space.conf_obj != NULL) | ||
| 234 | state->space.read(state->space.conf_obj, l1addr, &l1desc, 4); | ||
| 235 | else | ||
| 236 | l1desc = Memory::Read32(l1addr); //mem_read_raw(32, l1addr, &l1desc); | ||
| 237 | |||
| 238 | #if 0 | ||
| 239 | if (virt_addr == 0xc000d2bc) { | ||
| 240 | printf("mmu_control is %x\n", state->mmu.translation_table_ctrl); | ||
| 241 | printf("mmu_table_0 is %x\n", state->mmu.translation_table_base0); | ||
| 242 | printf("mmu_table_1 is %x\n", state->mmu.translation_table_base1); | ||
| 243 | printf("l1addr is %x l1desc is %x\n", l1addr, l1desc); | ||
| 244 | // exit(-1); | ||
| 245 | } | ||
| 246 | #endif | ||
| 247 | switch (l1desc & 3) { | ||
| 248 | case 0: | ||
| 249 | case 3: | ||
| 250 | /* | ||
| 251 | * according to Figure 3-9 Sequence for checking faults in arm manual, | ||
| 252 | * section translation fault should be returned here. | ||
| 253 | */ | ||
| 254 | { | ||
| 255 | return SECTION_TRANSLATION_FAULT; | ||
| 256 | } | ||
| 257 | case 1: | ||
| 258 | /* coarse page table */ | ||
| 259 | { | ||
| 260 | ARMword l2addr, l2desc; | ||
| 261 | |||
| 262 | |||
| 263 | l2addr = l1desc & 0xFFFFFC00; | ||
| 264 | l2addr = (l2addr | | ||
| 265 | ((virt_addr & 0x000FF000) >> 10)) & | ||
| 266 | ~3; | ||
| 267 | if(state->space.conf_obj != NULL) | ||
| 268 | state->space.read(state->space.conf_obj, l2addr, &l2desc, 4); | ||
| 269 | else | ||
| 270 | l2desc = Memory::Read32(l2addr); //mem_read_raw(32, l2addr, &l2desc); | ||
| 271 | |||
| 272 | /* chy 2003-09-02 for xscale */ | ||
| 273 | *ap = (l2desc >> 4) & 0x3; | ||
| 274 | *sop = 1; /* page */ | ||
| 275 | |||
| 276 | switch (l2desc & 3) { | ||
| 277 | case 0: | ||
| 278 | return PAGE_TRANSLATION_FAULT; | ||
| 279 | break; | ||
| 280 | case 1: | ||
| 281 | *phys_addr = (l2desc & 0xFFFF0000) | (virt_addr & 0x0000FFFF); | ||
| 282 | break; | ||
| 283 | case 2: | ||
| 284 | case 3: | ||
| 285 | *phys_addr = (l2desc & 0xFFFFF000) | (virt_addr & 0x00000FFF); | ||
| 286 | break; | ||
| 287 | |||
| 288 | } | ||
| 289 | } | ||
| 290 | break; | ||
| 291 | case 2: | ||
| 292 | /* section */ | ||
| 293 | |||
| 294 | *ap = (l1desc >> 10) & 3; | ||
| 295 | *sop = 0; /* section */ | ||
| 296 | #if 0 | ||
| 297 | if (virt_addr == 0xc000d2bc) { | ||
| 298 | printf("mmu_control is %x\n", state->mmu.translation_table_ctrl); | ||
| 299 | printf("mmu_table_0 is %x\n", state->mmu.translation_table_base0); | ||
| 300 | printf("mmu_table_1 is %x\n", state->mmu.translation_table_base1); | ||
| 301 | printf("l1addr is %x l1desc is %x\n", l1addr, l1desc); | ||
| 302 | // printf("l2addr is %x l2desc is %x\n", l2addr, l2desc); | ||
| 303 | printf("ap is %x, sop is %x\n", *ap, *sop); | ||
| 304 | printf("mode is %d\n", state->Mode); | ||
| 305 | // exit(-1); | ||
| 306 | } | ||
| 307 | #endif | ||
| 308 | |||
| 309 | if (l1desc & 0x30000) | ||
| 310 | *phys_addr = (l1desc & 0xFF000000) | (virt_addr & 0x00FFFFFF); | ||
| 311 | else | ||
| 312 | *phys_addr = (l1desc & 0xFFF00000) | (virt_addr & 0x000FFFFF); | ||
| 313 | break; | ||
| 314 | } | ||
| 315 | } | ||
| 316 | return NO_FAULT; | ||
| 317 | } | ||
| 318 | |||
| 319 | |||
| 320 | static fault_t arm1176jzf_s_mmu_write (ARMul_State *state, ARMword va, | ||
| 321 | ARMword data, ARMword datatype); | ||
| 322 | static fault_t arm1176jzf_s_mmu_read (ARMul_State *state, ARMword va, | ||
| 323 | ARMword *data, ARMword datatype); | ||
| 324 | |||
| 325 | int | ||
| 326 | arm1176jzf_s_mmu_init (ARMul_State *state) | ||
| 327 | { | ||
| 328 | state->mmu.control = 0x50078; | ||
| 329 | state->mmu.translation_table_base = 0xDEADC0DE; | ||
| 330 | state->mmu.domain_access_control = 0xDEADC0DE; | ||
| 331 | state->mmu.fault_status = 0; | ||
| 332 | state->mmu.fault_address = 0; | ||
| 333 | state->mmu.process_id = 0; | ||
| 334 | state->mmu.context_id = 0; | ||
| 335 | state->mmu.thread_uro_id = 0; | ||
| 336 | //invalidate_all_tlb(state); | ||
| 337 | |||
| 338 | return No_exp; | ||
| 339 | } | ||
| 340 | |||
| 341 | void | ||
| 342 | arm1176jzf_s_mmu_exit (ARMul_State *state) | ||
| 343 | { | ||
| 344 | } | ||
| 345 | |||
| 346 | |||
| 347 | static fault_t | ||
| 348 | arm1176jzf_s_mmu_load_instr (ARMul_State *state, ARMword va, ARMword *instr) | ||
| 349 | { | ||
| 350 | fault_t fault; | ||
| 351 | int c; /* cache bit */ | ||
| 352 | ARMword pa; /* physical addr */ | ||
| 353 | ARMword perm; /* physical addr access permissions */ | ||
| 354 | int ap, sop; | ||
| 355 | |||
| 356 | static int debug_count = 0; /* used for debug */ | ||
| 357 | |||
| 358 | //DEBUG_LOG(ARM11, "va = %x\n", va); | ||
| 359 | |||
| 360 | va = mmu_pid_va_map (va); | ||
| 361 | if (MMU_Enabled) { | ||
| 362 | // printf("MMU enabled.\n"); | ||
| 363 | // sleep(1); | ||
| 364 | /* align check */ | ||
| 365 | if ((va & (WORD_SIZE - 1)) && MMU_Aligned) { | ||
| 366 | DEBUG_LOG(ARM11, "align\n"); | ||
| 367 | return ALIGNMENT_FAULT; | ||
| 368 | } else | ||
| 369 | va &= ~(WORD_SIZE - 1); | ||
| 370 | |||
| 371 | /* translate tlb */ | ||
| 372 | fault = mmu_translate (state, va, &pa, &ap, &sop); | ||
| 373 | if (fault) { | ||
| 374 | DEBUG_LOG(ARM11, "translate\n"); | ||
| 375 | printf("va=0x%x, icounter=%lld, fault=%d\n", va, state->NumInstrs, fault); | ||
| 376 | return fault; | ||
| 377 | } | ||
| 378 | |||
| 379 | |||
| 380 | /* no tlb, only check permission */ | ||
| 381 | if (!check_perms(state, ap, 1)) { | ||
| 382 | if (sop == 0) { | ||
| 383 | return SECTION_PERMISSION_FAULT; | ||
| 384 | } else { | ||
| 385 | return SUBPAGE_PERMISSION_FAULT; | ||
| 386 | } | ||
| 387 | } | ||
| 388 | |||
| 389 | #if 0 | ||
| 390 | /*check access */ | ||
| 391 | fault = check_access (state, va, tlb, 1); | ||
| 392 | if (fault) { | ||
| 393 | DEBUG_LOG(ARM11, "check_fault\n"); | ||
| 394 | return fault; | ||
| 395 | } | ||
| 396 | #endif | ||
| 397 | } | ||
| 398 | |||
| 399 | /*if MMU disabled or C flag is set alloc cache */ | ||
| 400 | if (MMU_Disabled) { | ||
| 401 | // printf("MMU disabled.\n"); | ||
| 402 | // sleep(1); | ||
| 403 | pa = va; | ||
| 404 | } | ||
| 405 | if(state->space.conf_obj == NULL) | ||
| 406 | state->space.read(state->space.conf_obj, pa, instr, 4); | ||
| 407 | else | ||
| 408 | *instr = Memory::Read32(pa); //mem_read_raw(32, pa, instr); | ||
| 409 | |||
| 410 | return NO_FAULT; | ||
| 411 | } | ||
| 412 | |||
| 413 | static fault_t | ||
| 414 | arm1176jzf_s_mmu_read_byte (ARMul_State *state, ARMword virt_addr, ARMword *data) | ||
| 415 | { | ||
| 416 | /* ARMword temp,offset; */ | ||
| 417 | fault_t fault; | ||
| 418 | fault = arm1176jzf_s_mmu_read (state, virt_addr, data, ARM_BYTE_TYPE); | ||
| 419 | return fault; | ||
| 420 | } | ||
| 421 | |||
| 422 | static fault_t | ||
| 423 | arm1176jzf_s_mmu_read_halfword (ARMul_State *state, ARMword virt_addr, | ||
| 424 | ARMword *data) | ||
| 425 | { | ||
| 426 | /* ARMword temp,offset; */ | ||
| 427 | fault_t fault; | ||
| 428 | fault = arm1176jzf_s_mmu_read (state, virt_addr, data, ARM_HALFWORD_TYPE); | ||
| 429 | return fault; | ||
| 430 | } | ||
| 431 | |||
| 432 | static fault_t | ||
| 433 | arm1176jzf_s_mmu_read_word (ARMul_State *state, ARMword virt_addr, ARMword *data) | ||
| 434 | { | ||
| 435 | return arm1176jzf_s_mmu_read (state, virt_addr, data, ARM_WORD_TYPE); | ||
| 436 | } | ||
| 437 | |||
| 438 | static fault_t | ||
| 439 | arm1176jzf_s_mmu_read (ARMul_State *state, ARMword va, ARMword *data, | ||
| 440 | ARMword datatype) | ||
| 441 | { | ||
| 442 | fault_t fault; | ||
| 443 | ARMword pa, real_va, temp, offset; | ||
| 444 | ARMword perm; /* physical addr access permissions */ | ||
| 445 | int ap, sop; | ||
| 446 | |||
| 447 | //DEBUG_LOG(ARM11, "va = %x\n", va); | ||
| 448 | |||
| 449 | va = mmu_pid_va_map (va); | ||
| 450 | real_va = va; | ||
| 451 | /* if MMU disabled, memory_read */ | ||
| 452 | if (MMU_Disabled) { | ||
| 453 | // printf("MMU disabled cpu_id:%x addr:%x.\n", state->mmu.process_id, va); | ||
| 454 | // sleep(1); | ||
| 455 | |||
| 456 | /* *data = mem_read_word(state, va); */ | ||
| 457 | if (datatype == ARM_BYTE_TYPE) | ||
| 458 | /* *data = mem_read_byte (state, va); */ | ||
| 459 | if(state->space.conf_obj != NULL) | ||
| 460 | state->space.read(state->space.conf_obj, va, data, 1); | ||
| 461 | else | ||
| 462 | *data = Memory::Read8(va); //mem_read_raw(8, va, data); | ||
| 463 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 464 | /* *data = mem_read_halfword (state, va); */ | ||
| 465 | if(state->space.conf_obj != NULL) | ||
| 466 | state->space.read(state->space.conf_obj, va, data, 2); | ||
| 467 | else | ||
| 468 | *data = Memory::Read16(va); //mem_read_raw(16, va, data); | ||
| 469 | else if (datatype == ARM_WORD_TYPE) | ||
| 470 | /* *data = mem_read_word (state, va); */ | ||
| 471 | if(state->space.conf_obj != NULL) | ||
| 472 | state->space.read(state->space.conf_obj, va, data, 4); | ||
| 473 | else | ||
| 474 | *data = Memory::Read32(va); //mem_read_raw(32, va, data); | ||
| 475 | else { | ||
| 476 | ERROR_LOG(ARM11, "SKYEYE:1 arm1176jzf_s_mmu_read error: unknown data type %d\n", datatype); | ||
| 477 | } | ||
| 478 | |||
| 479 | return NO_FAULT; | ||
| 480 | } | ||
| 481 | // printf("MMU enabled.\n"); | ||
| 482 | // sleep(1); | ||
| 483 | |||
| 484 | /* align check */ | ||
| 485 | if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) || | ||
| 486 | ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) { | ||
| 487 | DEBUG_LOG(ARM11, "align\n"); | ||
| 488 | return ALIGNMENT_FAULT; | ||
| 489 | } | ||
| 490 | |||
| 491 | /* va &= ~(WORD_SIZE - 1); */ | ||
| 492 | #if 0 | ||
| 493 | uint32_t page_base; | ||
| 494 | page_base = get_phys_page(state, va); | ||
| 495 | if((page_base & 0xFFF) == 0){ | ||
| 496 | pa = (page_base << 12) | (va & 0xFFF); | ||
| 497 | goto skip_translation; | ||
| 498 | } | ||
| 499 | #endif | ||
| 500 | /*translate va to tlb */ | ||
| 501 | #if 0 | ||
| 502 | fault = mmu_translate (state, va, ARM920T_D_TLB (), &tlb); | ||
| 503 | #endif | ||
| 504 | fault = mmu_translate (state, va, &pa, &ap, &sop); | ||
| 505 | #if 0 | ||
| 506 | if(va ==0xbebb1774 || state->Reg[15] == 0x400ff594){ | ||
| 507 | //printf("In %s, current=0x%x. mode is %x, pc=0x%x\n", __FUNCTION__, state->CurrInstr, state->Mode, state->Reg[15]); | ||
| 508 | printf("In %s, ap is %d, sop is %d, va=0x%x, pa=0x%x, fault=%d, data=0x%x\n", __FUNCTION__, ap, sop, va, pa, fault, data); | ||
| 509 | int i; | ||
| 510 | for(i = 0; i < 16; i++) | ||
| 511 | printf("Reg[%d]=0x%x\t", i, state->Reg[i]); | ||
| 512 | printf("\n"); | ||
| 513 | } | ||
| 514 | #endif | ||
| 515 | if (fault) { | ||
| 516 | DEBUG_LOG(ARM11, "translate\n"); | ||
| 517 | //printf("mmu read fault at %x\n", va); | ||
| 518 | //printf("fault is %d\n", fault); | ||
| 519 | return fault; | ||
| 520 | } | ||
| 521 | // printf("va is %x pa is %x\n", va, pa); | ||
| 522 | |||
| 523 | /* no tlb, only check permission */ | ||
| 524 | if (!check_perms(state, ap, 1)) { | ||
| 525 | if (sop == 0) { | ||
| 526 | return SECTION_PERMISSION_FAULT; | ||
| 527 | } else { | ||
| 528 | return SUBPAGE_PERMISSION_FAULT; | ||
| 529 | } | ||
| 530 | } | ||
| 531 | #if 0 | ||
| 532 | /*check access permission */ | ||
| 533 | fault = check_access (state, va, tlb, 1); | ||
| 534 | if (fault) | ||
| 535 | return fault; | ||
| 536 | #endif | ||
| 537 | |||
| 538 | //insert_tlb(state, va, pa); | ||
| 539 | skip_translation: | ||
| 540 | /* *data = mem_read_word(state, pa); */ | ||
| 541 | if (datatype == ARM_BYTE_TYPE) { | ||
| 542 | /* *data = mem_read_byte (state, pa | (real_va & 3)); */ | ||
| 543 | if(state->space.conf_obj != NULL) | ||
| 544 | state->space.read(state->space.conf_obj, pa | (real_va & 3), data, 1); | ||
| 545 | else | ||
| 546 | *data = Memory::Read8(pa | (real_va & 3)); //mem_read_raw(8, pa | (real_va & 3), data); | ||
| 547 | /* mem_read_raw(32, pa | (real_va & 3), data); */ | ||
| 548 | } else if (datatype == ARM_HALFWORD_TYPE) { | ||
| 549 | /* *data = mem_read_halfword (state, pa | (real_va & 2)); */ | ||
| 550 | if(state->space.conf_obj != NULL) | ||
| 551 | state->space.read(state->space.conf_obj, pa | (real_va & 3), data, 2); | ||
| 552 | else | ||
| 553 | *data = Memory::Read16(pa | (real_va & 3)); //mem_read_raw(16, pa | (real_va & 3), data); | ||
| 554 | /* mem_read_raw(32, pa | (real_va & 2), data); */ | ||
| 555 | } else if (datatype == ARM_WORD_TYPE) | ||
| 556 | /* *data = mem_read_word (state, pa); */ | ||
| 557 | if(state->space.conf_obj != NULL) | ||
| 558 | state->space.read(state->space.conf_obj, pa , data, 4); | ||
| 559 | else | ||
| 560 | *data = Memory::Read32(pa); //mem_read_raw(32, pa, data); | ||
| 561 | else { | ||
| 562 | ERROR_LOG(ARM11, "SKYEYE:2 arm1176jzf_s_mmu_read error: unknown data type %d\n", datatype); | ||
| 563 | } | ||
| 564 | if(0 && (va == 0x2869c)){ | ||
| 565 | printf("In %s, pa is %x va=0x%x, value is %x pc %x, instr=0x%x\n", __FUNCTION__, pa, va, *data, state->Reg[15], state->CurrInstr); | ||
| 566 | } | ||
| 567 | |||
| 568 | /* ldrex or ldrexb */ | ||
| 569 | if(((state->CurrInstr & 0x0FF000F0) == 0x01900090) || | ||
| 570 | ((state->CurrInstr & 0x0FF000F0) == 0x01d00090)){ | ||
| 571 | int rn = (state->CurrInstr & 0xF0000) >> 16; | ||
| 572 | if(state->Reg[rn] == va){ | ||
| 573 | add_exclusive_addr(state, pa | (real_va & 3)); | ||
| 574 | state->exclusive_access_state = 1; | ||
| 575 | } | ||
| 576 | } | ||
| 577 | #if 0 | ||
| 578 | if (state->pc == 0xc011a868) { | ||
| 579 | printf("pa is %x value is %x size is %x\n", pa, data, datatype); | ||
| 580 | printf("icounter is %lld\n", state->NumInstrs); | ||
| 581 | // exit(-1); | ||
| 582 | } | ||
| 583 | #endif | ||
| 584 | |||
| 585 | return NO_FAULT; | ||
| 586 | } | ||
| 587 | |||
| 588 | |||
| 589 | static fault_t | ||
| 590 | arm1176jzf_s_mmu_write_byte (ARMul_State *state, ARMword virt_addr, ARMword data) | ||
| 591 | { | ||
| 592 | return arm1176jzf_s_mmu_write (state, virt_addr, data, ARM_BYTE_TYPE); | ||
| 593 | } | ||
| 594 | |||
| 595 | static fault_t | ||
| 596 | arm1176jzf_s_mmu_write_halfword (ARMul_State *state, ARMword virt_addr, | ||
| 597 | ARMword data) | ||
| 598 | { | ||
| 599 | return arm1176jzf_s_mmu_write (state, virt_addr, data, ARM_HALFWORD_TYPE); | ||
| 600 | } | ||
| 601 | |||
| 602 | static fault_t | ||
| 603 | arm1176jzf_s_mmu_write_word (ARMul_State *state, ARMword virt_addr, ARMword data) | ||
| 604 | { | ||
| 605 | return arm1176jzf_s_mmu_write (state, virt_addr, data, ARM_WORD_TYPE); | ||
| 606 | } | ||
| 607 | |||
| 608 | |||
| 609 | |||
| 610 | static fault_t | ||
| 611 | arm1176jzf_s_mmu_write (ARMul_State *state, ARMword va, ARMword data, | ||
| 612 | ARMword datatype) | ||
| 613 | { | ||
| 614 | int b; | ||
| 615 | ARMword pa, real_va; | ||
| 616 | ARMword perm; /* physical addr access permissions */ | ||
| 617 | fault_t fault; | ||
| 618 | int ap, sop; | ||
| 619 | |||
| 620 | #if 0 | ||
| 621 | /8 for sky_printk debugger.*/ | ||
| 622 | if (va == 0xffffffff) { | ||
| 623 | putchar((char)data); | ||
| 624 | return 0; | ||
| 625 | } | ||
| 626 | if (va == 0xBfffffff) { | ||
| 627 | putchar((char)data); | ||
| 628 | return 0; | ||
| 629 | } | ||
| 630 | #endif | ||
| 631 | |||
| 632 | //DEBUG_LOG(ARM11, "va = %x, val = %x\n", va, data); | ||
| 633 | va = mmu_pid_va_map (va); | ||
| 634 | real_va = va; | ||
| 635 | |||
| 636 | if (MMU_Disabled) { | ||
| 637 | /* mem_write_word(state, va, data); */ | ||
| 638 | if (datatype == ARM_BYTE_TYPE) | ||
| 639 | /* mem_write_byte (state, va, data); */ | ||
| 640 | if(state->space.conf_obj != NULL) | ||
| 641 | state->space.write(state->space.conf_obj, va, &data, 1); | ||
| 642 | else | ||
| 643 | Memory::Write8(va, data); | ||
| 644 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 645 | /* mem_write_halfword (state, va, data); */ | ||
| 646 | if(state->space.conf_obj != NULL) | ||
| 647 | state->space.write(state->space.conf_obj, va, &data, 2); | ||
| 648 | else | ||
| 649 | Memory::Write16(va, data); | ||
| 650 | else if (datatype == ARM_WORD_TYPE) | ||
| 651 | /* mem_write_word (state, va, data); */ | ||
| 652 | if(state->space.conf_obj != NULL) | ||
| 653 | state->space.write(state->space.conf_obj, va, &data, 4); | ||
| 654 | else | ||
| 655 | Memory::Write32(va, data); | ||
| 656 | else { | ||
| 657 | ERROR_LOG (ARM11, "SKYEYE:1 arm1176jzf_s_mmu_write error: unknown data type %d\n", datatype); | ||
| 658 | } | ||
| 659 | goto finished_write; | ||
| 660 | //return 0; | ||
| 661 | } | ||
| 662 | /*align check */ | ||
| 663 | /* if ((va & (WORD_SIZE - 1)) && MMU_Aligned){ */ | ||
| 664 | if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) || | ||
| 665 | ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) { | ||
| 666 | DEBUG_LOG(ARM11, "align\n"); | ||
| 667 | return ALIGNMENT_FAULT; | ||
| 668 | } | ||
| 669 | va &= ~(WORD_SIZE - 1); | ||
| 670 | #if 0 | ||
| 671 | uint32_t page_base; | ||
| 672 | page_base = get_phys_page(state, va); | ||
| 673 | if((page_base & 0xFFF) == 0){ | ||
| 674 | pa = (page_base << 12) | (va & 0xFFF); | ||
| 675 | goto skip_translation; | ||
| 676 | } | ||
| 677 | #endif | ||
| 678 | /*tlb translate */ | ||
| 679 | fault = mmu_translate (state, va, &pa, &ap, &sop); | ||
| 680 | #if 0 | ||
| 681 | if(va ==0xbebb1774 || state->Reg[15] == 0x40102334){ | ||
| 682 | //printf("In %s, current=0x%x. mode is %x, pc=0x%x\n", __FUNCTION__, state->CurrInstr, state->Mode, state->Reg[15]); | ||
| 683 | printf("In %s, ap is %d, sop is %d, va=0x%x, pa=0x%x, fault=%d, data=0x%x\n", __FUNCTION__, ap, sop, va, pa, fault, data); | ||
| 684 | int i; | ||
| 685 | for(i = 0; i < 16; i++) | ||
| 686 | printf("Reg[%d]=0x%x\t", i, state->Reg[i]); | ||
| 687 | printf("\n"); | ||
| 688 | } | ||
| 689 | #endif | ||
| 690 | if (fault) { | ||
| 691 | DEBUG_LOG(ARM11, "translate\n"); | ||
| 692 | //printf("mmu write fault at %x\n", va); | ||
| 693 | return fault; | ||
| 694 | } | ||
| 695 | // printf("va is %x pa is %x\n", va, pa); | ||
| 696 | |||
| 697 | /* no tlb, only check permission */ | ||
| 698 | if (!check_perms(state, ap, 0)) { | ||
| 699 | if (sop == 0) { | ||
| 700 | return SECTION_PERMISSION_FAULT; | ||
| 701 | } else { | ||
| 702 | return SUBPAGE_PERMISSION_FAULT; | ||
| 703 | } | ||
| 704 | } | ||
| 705 | |||
| 706 | #if 0 | ||
| 707 | /* tlb check access */ | ||
| 708 | fault = check_access (state, va, tlb, 0); | ||
| 709 | if (fault) { | ||
| 710 | DEBUG_LOG(ARM11, "check_access\n"); | ||
| 711 | return fault; | ||
| 712 | } | ||
| 713 | #endif | ||
| 714 | #if 0 | ||
| 715 | if (pa <= 0x502860ff && (pa + 1 << datatype) > 0x502860ff) { | ||
| 716 | printf("pa is %x value is %x size is %x\n", pa, data, datatype); | ||
| 717 | } | ||
| 718 | #endif | ||
| 719 | #if 0 | ||
| 720 | if (state->pc == 0xc011a878) { | ||
| 721 | printf("write pa is %x value is %x size is %x\n", pa, data, datatype); | ||
| 722 | printf("icounter is %lld\n", state->NumInstrs); | ||
| 723 | exit(-1); | ||
| 724 | } | ||
| 725 | #endif | ||
| 726 | //insert_tlb(state, va, pa); | ||
| 727 | skip_translation: | ||
| 728 | /* strex */ | ||
| 729 | if(((state->CurrInstr & 0x0FF000F0) == 0x01800090) || | ||
| 730 | ((state->CurrInstr & 0x0FF000F0) == 0x01c00090)){ | ||
| 731 | /* failed , the address is monitord now. */ | ||
| 732 | int dest_reg = (state->CurrInstr & 0xF000) >> 12; | ||
| 733 | if((exclusive_detect(state, pa | (real_va & 3)) == 0) && (state->exclusive_access_state == 1)){ | ||
| 734 | remove_exclusive(state, pa | (real_va & 3)); | ||
| 735 | state->Reg[dest_reg] = 0; | ||
| 736 | state->exclusive_access_state = 0; | ||
| 737 | } | ||
| 738 | else{ | ||
| 739 | state->Reg[dest_reg] = 1; | ||
| 740 | //printf("In %s, try to strex a monitored address 0x%x\n", __FUNCTION__, pa); | ||
| 741 | return NO_FAULT; | ||
| 742 | } | ||
| 743 | } | ||
| 744 | |||
| 745 | if (datatype == ARM_BYTE_TYPE) { | ||
| 746 | /* mem_write_byte (state, | ||
| 747 | (pa | (real_va & 3)), | ||
| 748 | data); | ||
| 749 | */ | ||
| 750 | if(state->space.conf_obj != NULL) | ||
| 751 | state->space.write(state->space.conf_obj, (pa | (real_va & 3)), &data, 1); | ||
| 752 | else | ||
| 753 | Memory::Write8((pa | (real_va & 3)), data); | ||
| 754 | |||
| 755 | } else if (datatype == ARM_HALFWORD_TYPE) | ||
| 756 | /* mem_write_halfword (state, | ||
| 757 | (pa | | ||
| 758 | (real_va & 2)), | ||
| 759 | data); | ||
| 760 | */ | ||
| 761 | if(state->space.conf_obj != NULL) | ||
| 762 | state->space.write(state->space.conf_obj, (pa | (real_va & 3)), &data, 2); | ||
| 763 | else | ||
| 764 | Memory::Write16((pa | (real_va & 3)), data); | ||
| 765 | else if (datatype == ARM_WORD_TYPE) | ||
| 766 | /* mem_write_word (state, pa, data); */ | ||
| 767 | if(state->space.conf_obj != NULL) | ||
| 768 | state->space.write(state->space.conf_obj, pa, &data, 4); | ||
| 769 | else | ||
| 770 | Memory::Write32(pa, data); | ||
| 771 | #if 0 | ||
| 772 | if (state->NumInstrs > 236403) { | ||
| 773 | printf("write memory\n"); | ||
| 774 | printf("pa is %x value is %x size is %x\n", pa, data, datatype); | ||
| 775 | printf("icounter is %lld\n", state->NumInstrs); | ||
| 776 | } | ||
| 777 | #endif | ||
| 778 | finished_write: | ||
| 779 | #if DIFF_WRITE | ||
| 780 | if(state->icounter > state->debug_icounter){ | ||
| 781 | if(state->CurrWrite >= 17 ){ | ||
| 782 | printf("Wrong write array, 0x%x", state->CurrWrite); | ||
| 783 | exit(-1); | ||
| 784 | } | ||
| 785 | uint32 record_data = data; | ||
| 786 | if(datatype == ARM_BYTE_TYPE) | ||
| 787 | record_data &= 0xFF; | ||
| 788 | if(datatype == ARM_HALFWORD_TYPE) | ||
| 789 | record_data &= 0xFFFF; | ||
| 790 | |||
| 791 | state->WriteAddr[state->CurrWrite] = pa | (real_va & 3); | ||
| 792 | state->WriteData[state->CurrWrite] = record_data; | ||
| 793 | state->WritePc[state->CurrWrite] = state->Reg[15]; | ||
| 794 | state->CurrWrite++; | ||
| 795 | //printf("In %s, pc=0x%x, addr=0x%x, data=0x%x, CFlag=%d\n", __FUNCTION__, state->Reg[15], pa | (real_va & 3), record_data, state->CFlag); | ||
| 796 | } | ||
| 797 | #endif | ||
| 798 | |||
| 799 | return NO_FAULT; | ||
| 800 | } | ||
| 801 | |||
| 802 | ARMword | ||
| 803 | arm1176jzf_s_mmu_mrc (ARMul_State *state, ARMword instr, ARMword *value) | ||
| 804 | { | ||
| 805 | int creg = BITS (16, 19) & 0xf; | ||
| 806 | int OPC_1 = BITS (21, 23) & 0x7; | ||
| 807 | int OPC_2 = BITS (5, 7) & 0x7; | ||
| 808 | ARMword data; | ||
| 809 | |||
| 810 | switch (creg) { | ||
| 811 | case MMU_ID: | ||
| 812 | if (OPC_2 == 0) { | ||
| 813 | data = state->cpu->cpu_val; | ||
| 814 | } else if (OPC_2 == 1) { | ||
| 815 | /* Cache type: | ||
| 816 | * 000 0110 1 000 101 110 0 10 000 101 110 0 10 | ||
| 817 | * */ | ||
| 818 | data = 0x0D172172; | ||
| 819 | } | ||
| 820 | break; | ||
| 821 | case MMU_CONTROL: | ||
| 822 | /* | ||
| 823 | * 6:3 read as 1 | ||
| 824 | * 10 read as 0 | ||
| 825 | * 18,16 read as 1 | ||
| 826 | * */ | ||
| 827 | data = (state->mmu.control | 0x50078) & 0xFFFFFBFF; | ||
| 828 | break; | ||
| 829 | case MMU_TRANSLATION_TABLE_BASE: | ||
| 830 | #if 0 | ||
| 831 | data = state->mmu.translation_table_base; | ||
| 832 | #endif | ||
| 833 | switch (OPC_2) { | ||
| 834 | case 0: | ||
| 835 | data = state->mmu.translation_table_base0; | ||
| 836 | break; | ||
| 837 | case 1: | ||
| 838 | data = state->mmu.translation_table_base1; | ||
| 839 | break; | ||
| 840 | case 2: | ||
| 841 | data = state->mmu.translation_table_ctrl; | ||
| 842 | break; | ||
| 843 | default: | ||
| 844 | printf ("mmu_mrc read UNKNOWN - p15 c2 opcode2 %d\n", OPC_2); | ||
| 845 | break; | ||
| 846 | } | ||
| 847 | break; | ||
| 848 | case MMU_DOMAIN_ACCESS_CONTROL: | ||
| 849 | data = state->mmu.domain_access_control; | ||
| 850 | break; | ||
| 851 | case MMU_FAULT_STATUS: | ||
| 852 | /* OPC_2 = 0: data FSR value | ||
| 853 | * */ | ||
| 854 | if (OPC_2 == 0) | ||
| 855 | data = state->mmu.fault_status; | ||
| 856 | if (OPC_2 == 1) | ||
| 857 | data = state->mmu.fault_statusi; | ||
| 858 | break; | ||
| 859 | case MMU_FAULT_ADDRESS: | ||
| 860 | data = state->mmu.fault_address; | ||
| 861 | break; | ||
| 862 | case MMU_PID: | ||
| 863 | //data = state->mmu.process_id; | ||
| 864 | if(OPC_2 == 0) | ||
| 865 | data = state->mmu.process_id; | ||
| 866 | else if(OPC_2 == 1) | ||
| 867 | data = state->mmu.context_id; | ||
| 868 | else if(OPC_2 == 3){ | ||
| 869 | data = state->mmu.thread_uro_id; | ||
| 870 | } | ||
| 871 | else{ | ||
| 872 | printf ("mmu_mcr read UNKNOWN - reg %d\n", creg); | ||
| 873 | } | ||
| 874 | //printf("SKYEYE In %s, read pid 0x%x, OPC_2 %d, instr=0x%x\n", __FUNCTION__, data, OPC_2, instr); | ||
| 875 | //exit(-1); | ||
| 876 | break; | ||
| 877 | default: | ||
| 878 | printf ("mmu_mrc read UNKNOWN - reg %d\n", creg); | ||
| 879 | data = 0; | ||
| 880 | break; | ||
| 881 | } | ||
| 882 | /* printf("\t\t\t\t\tpc = 0x%08x\n", state->Reg[15]); */ | ||
| 883 | *value = data; | ||
| 884 | return data; | ||
| 885 | } | ||
| 886 | |||
| 887 | |||
| 888 | static ARMword | ||
| 889 | arm1176jzf_s_mmu_mcr (ARMul_State *state, ARMword instr, ARMword value) | ||
| 890 | { | ||
| 891 | int creg = BITS (16, 19) & 0xf; | ||
| 892 | int CRm = BITS (0, 3) & 0xf; | ||
| 893 | int OPC_1 = BITS (21, 23) & 0x7; | ||
| 894 | int OPC_2 = BITS (5, 7) & 0x7; | ||
| 895 | if (!strncmp (state->cpu->cpu_arch_name, "armv6", 5)) { | ||
| 896 | switch (creg) { | ||
| 897 | case MMU_CONTROL: | ||
| 898 | /* | ||
| 899 | * 6:3 read as 1 | ||
| 900 | * 10 read as 0 | ||
| 901 | * 18,16 read as 1 | ||
| 902 | * */ | ||
| 903 | if(OPC_2 == 0) | ||
| 904 | state->mmu.control = (value | 0x50078) & 0xFFFFFBFF; | ||
| 905 | else if(OPC_2 == 1) | ||
| 906 | state->mmu.auxiliary_control = value; | ||
| 907 | else if(OPC_2 == 2) | ||
| 908 | state->mmu.coprocessor_access_control = value; | ||
| 909 | else | ||
| 910 | fprintf(stderr, "In %s, wrong OPC_2 %d\n", __FUNCTION__, OPC_2); | ||
| 911 | break; | ||
| 912 | case MMU_TRANSLATION_TABLE_BASE: | ||
| 913 | switch (OPC_2) { | ||
| 914 | /* int i; */ | ||
| 915 | case 0: | ||
| 916 | #if 0 | ||
| 917 | /* TTBR0 */ | ||
| 918 | if (state->mmu.translation_table_ctrl & 0x7) { | ||
| 919 | for (i = 0; i <= state->mmu.translation_table_ctrl; i++) | ||
| 920 | state->mmu.translation_table_base0 &= ~(1 << (5 + i)); | ||
| 921 | } | ||
| 922 | #endif | ||
| 923 | state->mmu.translation_table_base0 = (value); | ||
| 924 | break; | ||
| 925 | case 1: | ||
| 926 | #if 0 | ||
| 927 | /* TTBR1 */ | ||
| 928 | if (state->mmu.translation_table_ctrl & 0x7) { | ||
| 929 | for (i = 0; i <= state->mmu.translation_table_ctrl; i++) | ||
| 930 | state->mmu.translation_table_base1 &= 1 << (5 + i); | ||
| 931 | } | ||
| 932 | #endif | ||
| 933 | state->mmu.translation_table_base1 = (value); | ||
| 934 | break; | ||
| 935 | case 2: | ||
| 936 | /* TTBC */ | ||
| 937 | state->mmu.translation_table_ctrl = value & 0x7; | ||
| 938 | break; | ||
| 939 | default: | ||
| 940 | printf ("mmu_mcr wrote UNKNOWN - cp15 c2 opcode2 %d\n", OPC_2); | ||
| 941 | break; | ||
| 942 | } | ||
| 943 | //printf("SKYEYE In %s, write TLB_BASE 0x%x OPC_2=%d instr=0x%x\n", __FUNCTION__, value, OPC_2, instr); | ||
| 944 | //invalidate_all_tlb(state); | ||
| 945 | break; | ||
| 946 | case MMU_DOMAIN_ACCESS_CONTROL: | ||
| 947 | /* printf("mmu_mcr wrote DACR "); */ | ||
| 948 | state->mmu.domain_access_control = value; | ||
| 949 | break; | ||
| 950 | |||
| 951 | case MMU_FAULT_STATUS: | ||
| 952 | if (OPC_2 == 0) | ||
| 953 | state->mmu.fault_status = value & 0xFF; | ||
| 954 | if (OPC_2 == 1) { | ||
| 955 | printf("set fault status instr\n"); | ||
| 956 | } | ||
| 957 | break; | ||
| 958 | case MMU_FAULT_ADDRESS: | ||
| 959 | state->mmu.fault_address = value; | ||
| 960 | break; | ||
| 961 | |||
| 962 | case MMU_CACHE_OPS: | ||
| 963 | break; | ||
| 964 | case MMU_TLB_OPS: | ||
| 965 | { | ||
| 966 | switch(CRm){ | ||
| 967 | case 5: /* ITLB */ | ||
| 968 | { | ||
| 969 | switch(OPC_2){ | ||
| 970 | case 0: /* invalidate all */ | ||
| 971 | //invalidate_all_tlb(state); | ||
| 972 | break; | ||
| 973 | case 1: /* invalidate by MVA */ | ||
| 974 | //invalidate_by_mva(state, value); | ||
| 975 | break; | ||
| 976 | case 2: /* invalidate by asid */ | ||
| 977 | //invalidate_by_asid(state, value); | ||
| 978 | break; | ||
| 979 | default: | ||
| 980 | printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg); | ||
| 981 | break; | ||
| 982 | } | ||
| 983 | break; | ||
| 984 | } | ||
| 985 | case 6: /* DTLB */ | ||
| 986 | { | ||
| 987 | switch(OPC_2){ | ||
| 988 | case 0: /* invalidate all */ | ||
| 989 | //invalidate_all_tlb(state); | ||
| 990 | break; | ||
| 991 | case 1: /* invalidate by MVA */ | ||
| 992 | //invalidate_by_mva(state, value); | ||
| 993 | break; | ||
| 994 | case 2: /* invalidate by asid */ | ||
| 995 | //invalidate_by_asid(state, value); | ||
| 996 | break; | ||
| 997 | default: | ||
| 998 | printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg); | ||
| 999 | break; | ||
| 1000 | } | ||
| 1001 | break; | ||
| 1002 | } | ||
| 1003 | case 7: /* Unified TLB */ | ||
| 1004 | { | ||
| 1005 | switch(OPC_2){ | ||
| 1006 | case 0: /* invalidate all */ | ||
| 1007 | //invalidate_all_tlb(state); | ||
| 1008 | break; | ||
| 1009 | case 1: /* invalidate by MVA */ | ||
| 1010 | //invalidate_by_mva(state, value); | ||
| 1011 | break; | ||
| 1012 | case 2: /* invalidate by asid */ | ||
| 1013 | //invalidate_by_asid(state, value); | ||
| 1014 | break; | ||
| 1015 | default: | ||
| 1016 | printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg); | ||
| 1017 | break; | ||
| 1018 | } | ||
| 1019 | break; | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | default: | ||
| 1023 | printf ("mmu_mcr wrote UNKNOWN - reg %d, CRm=%d\n", creg, CRm); | ||
| 1024 | break; | ||
| 1025 | } | ||
| 1026 | //printf("SKYEYE In %s, write TLB 0x%x OPC_1=%d, OPC_2=%d , CRm=%d instr=0x%x\n", __FUNCTION__, value, OPC_1, OPC_2, CRm, instr); | ||
| 1027 | } | ||
| 1028 | break; | ||
| 1029 | case MMU_CACHE_LOCKDOWN: | ||
| 1030 | /* | ||
| 1031 | * FIXME: cache lock down*/ | ||
| 1032 | break; | ||
| 1033 | case MMU_TLB_LOCKDOWN: | ||
| 1034 | printf("SKYEYE In %s, write TLB_LOCKDOWN 0x%x OPC_2=%d instr=0x%x\n", __FUNCTION__, value, OPC_2, instr); | ||
| 1035 | /* FIXME:tlb lock down */ | ||
| 1036 | break; | ||
| 1037 | case MMU_PID: | ||
| 1038 | //printf("SKYEYE In %s, write pid 0x%x OPC_2=%d instr=0x%x\n", __FUNCTION__, value, OPC_2, instr); | ||
| 1039 | //state->mmu.process_id = value; | ||
| 1040 | /*0:24 should be zero. */ | ||
| 1041 | //state->mmu.process_id = value & 0xfe000000; | ||
| 1042 | if(OPC_2 == 0) | ||
| 1043 | state->mmu.process_id = value; | ||
| 1044 | else if(OPC_2 == 1) | ||
| 1045 | state->mmu.context_id = value; | ||
| 1046 | else if(OPC_2 == 3){ | ||
| 1047 | state->mmu.thread_uro_id = value; | ||
| 1048 | } | ||
| 1049 | else{ | ||
| 1050 | printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg); | ||
| 1051 | } | ||
| 1052 | break; | ||
| 1053 | |||
| 1054 | default: | ||
| 1055 | printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg); | ||
| 1056 | break; | ||
| 1057 | } | ||
| 1058 | } | ||
| 1059 | |||
| 1060 | return No_exp; | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | ///* teawater add for arm2x86 2005.06.19------------------------------------------- */ | ||
| 1064 | //static int | ||
| 1065 | //arm1176jzf_s_mmu_v2p_dbct (ARMul_State *state, ARMword virt_addr, | ||
| 1066 | // ARMword *phys_addr) | ||
| 1067 | //{ | ||
| 1068 | // fault_t fault; | ||
| 1069 | // int ap, sop; | ||
| 1070 | // | ||
| 1071 | // ARMword perm; /* physical addr access permissions */ | ||
| 1072 | // virt_addr = mmu_pid_va_map (virt_addr); | ||
| 1073 | // if (MMU_Enabled) { | ||
| 1074 | // | ||
| 1075 | // /*align check */ | ||
| 1076 | // if ((virt_addr & (WORD_SIZE - 1)) && MMU_Aligned) { | ||
| 1077 | // DEBUG_LOG(ARM11, "align\n"); | ||
| 1078 | // return ALIGNMENT_FAULT; | ||
| 1079 | // } else | ||
| 1080 | // virt_addr &= ~(WORD_SIZE - 1); | ||
| 1081 | // | ||
| 1082 | // /*translate tlb */ | ||
| 1083 | // fault = mmu_translate (state, virt_addr, phys_addr, &ap, &sop); | ||
| 1084 | // if (fault) { | ||
| 1085 | // DEBUG_LOG(ARM11, "translate\n"); | ||
| 1086 | // return fault; | ||
| 1087 | // } | ||
| 1088 | // | ||
| 1089 | // /* permission check */ | ||
| 1090 | // if (!check_perms(state, ap, 1)) { | ||
| 1091 | // if (sop == 0) { | ||
| 1092 | // return SECTION_PERMISSION_FAULT; | ||
| 1093 | // } else { | ||
| 1094 | // return SUBPAGE_PERMISSION_FAULT; | ||
| 1095 | // } | ||
| 1096 | // } | ||
| 1097 | //#if 0 | ||
| 1098 | // /*check access */ | ||
| 1099 | // fault = check_access (state, virt_addr, tlb, 1); | ||
| 1100 | // if (fault) { | ||
| 1101 | // DEBUG_LOG(ARM11, "check_fault\n"); | ||
| 1102 | // return fault; | ||
| 1103 | // } | ||
| 1104 | //#endif | ||
| 1105 | // } | ||
| 1106 | // | ||
| 1107 | // if (MMU_Disabled) { | ||
| 1108 | // *phys_addr = virt_addr; | ||
| 1109 | // } | ||
| 1110 | // | ||
| 1111 | // return 0; | ||
| 1112 | //} | ||
| 1113 | |||
| 1114 | /* AJ2D-------------------------------------------------------------------------- */ | ||
| 1115 | |||
| 1116 | /*arm1176jzf-s mmu_ops_t*/ | ||
| 1117 | mmu_ops_t arm1176jzf_s_mmu_ops = { | ||
| 1118 | arm1176jzf_s_mmu_init, | ||
| 1119 | arm1176jzf_s_mmu_exit, | ||
| 1120 | arm1176jzf_s_mmu_read_byte, | ||
| 1121 | arm1176jzf_s_mmu_write_byte, | ||
| 1122 | arm1176jzf_s_mmu_read_halfword, | ||
| 1123 | arm1176jzf_s_mmu_write_halfword, | ||
| 1124 | arm1176jzf_s_mmu_read_word, | ||
| 1125 | arm1176jzf_s_mmu_write_word, | ||
| 1126 | arm1176jzf_s_mmu_load_instr, | ||
| 1127 | arm1176jzf_s_mmu_mcr, | ||
| 1128 | arm1176jzf_s_mmu_mrc | ||
| 1129 | /* teawater add for arm2x86 2005.06.19------------------------------------------- */ | ||
| 1130 | /* arm1176jzf_s_mmu_v2p_dbct, */ | ||
| 1131 | /* AJ2D-------------------------------------------------------------------------- */ | ||
| 1132 | }; | ||
diff --git a/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.h b/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.h deleted file mode 100644 index 299c6b46b..000000000 --- a/src/core/arm/interpreter/mmu/arm1176jzf_s_mmu.h +++ /dev/null | |||
| @@ -1,37 +0,0 @@ | |||
| 1 | /* | ||
| 2 | arm1176JZF-S_mmu.h - ARM1176JZF-S Memory Management Unit emulation. | ||
| 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 | |||
| 19 | #ifndef _ARM1176JZF_S_MMU_H_ | ||
| 20 | #define _ARM1176JZF_S_MMU_H_ | ||
| 21 | |||
| 22 | #if 0 | ||
| 23 | typedef struct arm1176jzf-s_mmu_s | ||
| 24 | { | ||
| 25 | tlb_t i_tlb; | ||
| 26 | cache_t i_cache; | ||
| 27 | |||
| 28 | tlb_t d_tlb; | ||
| 29 | cache_t d_cache; | ||
| 30 | wb_t wb_t; | ||
| 31 | } arm1176jzf-s_mmu_t; | ||
| 32 | #endif | ||
| 33 | extern mmu_ops_t arm1176jzf_s_mmu_ops; | ||
| 34 | |||
| 35 | ARMword | ||
| 36 | arm1176jzf_s_mmu_mrc (ARMul_State *state, ARMword instr, ARMword *value); | ||
| 37 | #endif /*_ARM1176JZF_S_MMU_H_*/ | ||
diff --git a/src/core/arm/interpreter/mmu/cache.cpp b/src/core/arm/interpreter/mmu/cache.cpp deleted file mode 100644 index cfbc31f1e..000000000 --- a/src/core/arm/interpreter/mmu/cache.cpp +++ /dev/null | |||
| @@ -1,370 +0,0 @@ | |||
| 1 | #include "core/arm/skyeye_common/armdefs.h" | ||
| 2 | |||
| 3 | /* mmu cache init | ||
| 4 | * | ||
| 5 | * @cache_t :cache_t to init | ||
| 6 | * @width :cache line width in byte | ||
| 7 | * @way :way of each cache set | ||
| 8 | * @set :cache set num | ||
| 9 | * | ||
| 10 | * $ -1: error | ||
| 11 | * 0: sucess | ||
| 12 | */ | ||
| 13 | int | ||
| 14 | mmu_cache_init (cache_s * cache_t, int width, int way, int set, int w_mode) | ||
| 15 | { | ||
| 16 | int i, j; | ||
| 17 | cache_set_t *sets; | ||
| 18 | cache_line_t *lines; | ||
| 19 | |||
| 20 | /*alloc cache set */ | ||
| 21 | sets = NULL; | ||
| 22 | lines = NULL; | ||
| 23 | //fprintf(stderr, "mmu_cache_init: mallloc beg size %d,sets 0x%x\n", sizeof(cache_set_t) * set,sets); | ||
| 24 | //exit(-1); | ||
| 25 | sets = (cache_set_t *) malloc (sizeof (cache_set_t) * set); | ||
| 26 | if (sets == NULL) { | ||
| 27 | ERROR_LOG(ARM11, "set malloc size %d\n", sizeof (cache_set_t) * set); | ||
| 28 | goto sets_error; | ||
| 29 | } | ||
| 30 | //fprintf(stderr, "mmu_cache_init: mallloc end sets 0x%x\n", sets); | ||
| 31 | cache_t->sets = sets; | ||
| 32 | |||
| 33 | /*init cache set */ | ||
| 34 | for (i = 0; i < set; i++) { | ||
| 35 | /*alloc cache line */ | ||
| 36 | lines = (cache_line_t *) malloc (sizeof (cache_line_t) * way); | ||
| 37 | if (lines == NULL) { | ||
| 38 | ERROR_LOG(ARM11, "line malloc size %d\n", | ||
| 39 | sizeof (cache_line_t) * way); | ||
| 40 | goto lines_error; | ||
| 41 | } | ||
| 42 | /*init cache line */ | ||
| 43 | for (j = 0; j < way; j++) { | ||
| 44 | lines[j].tag = 0; //invalid | ||
| 45 | lines[j].data = (ARMword *) malloc (width); | ||
| 46 | if (lines[j].data == NULL) { | ||
| 47 | ERROR_LOG(ARM11, "data alloc size %d\n", width); | ||
| 48 | goto data_error; | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | sets[i].lines = lines; | ||
| 53 | sets[i].cycle = 0; | ||
| 54 | |||
| 55 | } | ||
| 56 | cache_t->width = width; | ||
| 57 | cache_t->set = set; | ||
| 58 | cache_t->way = way; | ||
| 59 | cache_t->w_mode = w_mode; | ||
| 60 | return 0; | ||
| 61 | |||
| 62 | data_error: | ||
| 63 | /*free data */ | ||
| 64 | while (j-- > 0) | ||
| 65 | free (lines[j].data); | ||
| 66 | /*free data error line */ | ||
| 67 | free (lines); | ||
| 68 | lines_error: | ||
| 69 | /*free lines already alloced */ | ||
| 70 | while (i-- > 0) { | ||
| 71 | for (j = 0; j < way; j++) | ||
| 72 | free (sets[i].lines[j].data); | ||
| 73 | free (sets[i].lines); | ||
| 74 | } | ||
| 75 | /*free sets */ | ||
| 76 | free (sets); | ||
| 77 | sets_error: | ||
| 78 | return -1; | ||
| 79 | }; | ||
| 80 | |||
| 81 | /* free a cache_t's inner data, the ptr self is not freed, | ||
| 82 | * when needed do like below: | ||
| 83 | * mmu_cache_exit(cache); | ||
| 84 | * free(cache_t); | ||
| 85 | * | ||
| 86 | * @cache_t : the cache_t to free | ||
| 87 | */ | ||
| 88 | |||
| 89 | void | ||
| 90 | mmu_cache_exit (cache_s * cache_t) | ||
| 91 | { | ||
| 92 | int i, j; | ||
| 93 | cache_set_t *sets, *set; | ||
| 94 | cache_line_t *lines, *line; | ||
| 95 | |||
| 96 | /*free all set */ | ||
| 97 | sets = cache_t->sets; | ||
| 98 | for (set = sets, i = 0; i < cache_t->set; i++, set++) { | ||
| 99 | /*free all line */ | ||
| 100 | lines = set->lines; | ||
| 101 | for (line = lines, j = 0; j < cache_t->way; j++, line++) | ||
| 102 | free (line->data); | ||
| 103 | free (lines); | ||
| 104 | } | ||
| 105 | free (sets); | ||
| 106 | } | ||
| 107 | |||
| 108 | /* mmu cache search | ||
| 109 | * | ||
| 110 | * @state :ARMul_State | ||
| 111 | * @cache_t :cache_t to search | ||
| 112 | * @va :virtual address | ||
| 113 | * | ||
| 114 | * $ NULL: no cache match | ||
| 115 | * cache :cache matched | ||
| 116 | */ | ||
| 117 | cache_line_t * | ||
| 118 | mmu_cache_search (ARMul_State * state, cache_s * cache_t, ARMword va) | ||
| 119 | { | ||
| 120 | int i; | ||
| 121 | int set = va_cache_set (va, cache_t); | ||
| 122 | ARMword tag = va_cache_align (va, cache_t); | ||
| 123 | cache_line_t *cache; | ||
| 124 | |||
| 125 | cache_set_t *cache_set = cache_t->sets + set; | ||
| 126 | for (i = 0, cache = cache_set->lines; i < cache_t->way; i++, cache++) { | ||
| 127 | if ((cache->tag & TAG_VALID_FLAG) | ||
| 128 | && (tag == va_cache_align (cache->tag, cache_t))) | ||
| 129 | return cache; | ||
| 130 | } | ||
| 131 | return NULL; | ||
| 132 | } | ||
| 133 | |||
| 134 | /* mmu cache search by set/index | ||
| 135 | * | ||
| 136 | * @state :ARMul_State | ||
| 137 | * @cache_t :cache_t to search | ||
| 138 | * @index :set/index value. | ||
| 139 | * | ||
| 140 | * $ NULL: no cache match | ||
| 141 | * cache :cache matched | ||
| 142 | */ | ||
| 143 | cache_line_t * | ||
| 144 | mmu_cache_search_by_index (ARMul_State * state, cache_s * cache_t, | ||
| 145 | ARMword index) | ||
| 146 | { | ||
| 147 | int way = cache_t->way; | ||
| 148 | int set_v = index_cache_set (index, cache_t); | ||
| 149 | int i = 0, index_v = 0; | ||
| 150 | cache_set_t *set; | ||
| 151 | |||
| 152 | while ((way >>= 1) >= 1) | ||
| 153 | i++; | ||
| 154 | index_v = index >> (32 - i); | ||
| 155 | set = cache_t->sets + set_v; | ||
| 156 | |||
| 157 | return set->lines + index_v; | ||
| 158 | } | ||
| 159 | |||
| 160 | |||
| 161 | /* mmu cache alloc | ||
| 162 | * | ||
| 163 | * @state :ARMul_State | ||
| 164 | * @cache_t :cache_t to alloc from | ||
| 165 | * @va :virtual address that require cache alloc, need not cache aligned | ||
| 166 | * @pa :physical address of va | ||
| 167 | * | ||
| 168 | * $ cache_alloced, always alloc OK | ||
| 169 | */ | ||
| 170 | cache_line_t * | ||
| 171 | mmu_cache_alloc (ARMul_State * state, cache_s * cache_t, ARMword va, | ||
| 172 | ARMword pa) | ||
| 173 | { | ||
| 174 | cache_line_t *cache; | ||
| 175 | cache_set_t *set; | ||
| 176 | int i; | ||
| 177 | |||
| 178 | va = va_cache_align (va, cache_t); | ||
| 179 | pa = va_cache_align (pa, cache_t); | ||
| 180 | |||
| 181 | set = &cache_t->sets[va_cache_set (va, cache_t)]; | ||
| 182 | |||
| 183 | /*robin-round */ | ||
| 184 | cache = &set->lines[set->cycle++]; | ||
| 185 | if (set->cycle == cache_t->way) | ||
| 186 | set->cycle = 0; | ||
| 187 | |||
| 188 | if (cache_t->w_mode == CACHE_WRITE_BACK) { | ||
| 189 | ARMword t; | ||
| 190 | |||
| 191 | /*if cache valid, try to write back */ | ||
| 192 | if (cache->tag & TAG_VALID_FLAG) { | ||
| 193 | mmu_cache_write_back (state, cache_t, cache); | ||
| 194 | } | ||
| 195 | /*read in cache_line */ | ||
| 196 | t = pa; | ||
| 197 | for (i = 0; i < (cache_t->width >> WORD_SHT); | ||
| 198 | i++, t += WORD_SIZE) { | ||
| 199 | //cache->data[i] = mem_read_word (state, t); | ||
| 200 | bus_read(32, t, &cache->data[i]); | ||
| 201 | } | ||
| 202 | } | ||
| 203 | /*store tag and pa */ | ||
| 204 | cache->tag = va | TAG_VALID_FLAG; | ||
| 205 | cache->pa = pa; | ||
| 206 | |||
| 207 | return cache; | ||
| 208 | }; | ||
| 209 | |||
| 210 | /* mmu_cache_write_back write cache data to memory | ||
| 211 | * @state | ||
| 212 | * @cache_t :cache_t of the cache line | ||
| 213 | * @cache : cache line | ||
| 214 | */ | ||
| 215 | void | ||
| 216 | mmu_cache_write_back (ARMul_State * state, cache_s * cache_t, | ||
| 217 | cache_line_t * cache) | ||
| 218 | { | ||
| 219 | ARMword pa = cache->pa; | ||
| 220 | int nw = cache_t->width >> WORD_SHT; | ||
| 221 | ARMword *data = cache->data; | ||
| 222 | int i; | ||
| 223 | int t0, t1, t2; | ||
| 224 | |||
| 225 | if ((cache->tag & 1) == 0) | ||
| 226 | return; | ||
| 227 | |||
| 228 | switch (cache-> | ||
| 229 | tag & ~1 & (TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY)) { | ||
| 230 | case 0: | ||
| 231 | return; | ||
| 232 | case TAG_FIRST_HALF_DIRTY: | ||
| 233 | nw /= 2; | ||
| 234 | break; | ||
| 235 | case TAG_LAST_HALF_DIRTY: | ||
| 236 | nw /= 2; | ||
| 237 | pa += nw << WORD_SHT; | ||
| 238 | data += nw; | ||
| 239 | break; | ||
| 240 | case TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY: | ||
| 241 | break; | ||
| 242 | } | ||
| 243 | for (i = 0; i < nw; i++, data++, pa += WORD_SIZE) | ||
| 244 | //mem_write_word (state, pa, *data); | ||
| 245 | bus_write(32, pa, *data); | ||
| 246 | |||
| 247 | cache->tag &= ~(TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY); | ||
| 248 | }; | ||
| 249 | |||
| 250 | |||
| 251 | /* mmu_cache_clean: clean a cache of va in cache_t | ||
| 252 | * | ||
| 253 | * @state :ARMul_State | ||
| 254 | * @cache_t :cache_t to clean | ||
| 255 | * @va :virtaul address | ||
| 256 | */ | ||
| 257 | void | ||
| 258 | mmu_cache_clean (ARMul_State * state, cache_s * cache_t, ARMword va) | ||
| 259 | { | ||
| 260 | cache_line_t *cache; | ||
| 261 | |||
| 262 | cache = mmu_cache_search (state, cache_t, va); | ||
| 263 | if (cache) | ||
| 264 | mmu_cache_write_back (state, cache_t, cache); | ||
| 265 | } | ||
| 266 | |||
| 267 | /* mmu_cache_clean_by_index: clean a cache by set/index format value | ||
| 268 | * | ||
| 269 | * @state :ARMul_State | ||
| 270 | * @cache_t :cache_t to clean | ||
| 271 | * @va :set/index format value | ||
| 272 | */ | ||
| 273 | void | ||
| 274 | mmu_cache_clean_by_index (ARMul_State * state, cache_s * cache_t, | ||
| 275 | ARMword index) | ||
| 276 | { | ||
| 277 | cache_line_t *cache; | ||
| 278 | |||
| 279 | cache = mmu_cache_search_by_index (state, cache_t, index); | ||
| 280 | if (cache) | ||
| 281 | mmu_cache_write_back (state, cache_t, cache); | ||
| 282 | } | ||
| 283 | |||
| 284 | /* mmu_cache_invalidate : invalidate a cache of va | ||
| 285 | * | ||
| 286 | * @state :ARMul_State | ||
| 287 | * @cache_t :cache_t to invalid | ||
| 288 | * @va :virt_addr to invalid | ||
| 289 | */ | ||
| 290 | void | ||
| 291 | mmu_cache_invalidate (ARMul_State * state, cache_s * cache_t, ARMword va) | ||
| 292 | { | ||
| 293 | cache_line_t *cache; | ||
| 294 | |||
| 295 | cache = mmu_cache_search (state, cache_t, va); | ||
| 296 | if (cache) { | ||
| 297 | mmu_cache_write_back (state, cache_t, cache); | ||
| 298 | cache->tag = 0; | ||
| 299 | } | ||
| 300 | } | ||
| 301 | |||
| 302 | /* mmu_cache_invalidate_by_index : invalidate a cache by index format | ||
| 303 | * | ||
| 304 | * @state :ARMul_State | ||
| 305 | * @cache_t :cache_t to invalid | ||
| 306 | * @index :set/index data | ||
| 307 | */ | ||
| 308 | void | ||
| 309 | mmu_cache_invalidate_by_index (ARMul_State * state, cache_s * cache_t, | ||
| 310 | ARMword index) | ||
| 311 | { | ||
| 312 | cache_line_t *cache; | ||
| 313 | |||
| 314 | cache = mmu_cache_search_by_index (state, cache_t, index); | ||
| 315 | if (cache) { | ||
| 316 | mmu_cache_write_back (state, cache_t, cache); | ||
| 317 | cache->tag = 0; | ||
| 318 | } | ||
| 319 | } | ||
| 320 | |||
| 321 | /* mmu_cache_invalidate_all | ||
| 322 | * | ||
| 323 | * @state: | ||
| 324 | * @cache_t | ||
| 325 | * */ | ||
| 326 | void | ||
| 327 | mmu_cache_invalidate_all (ARMul_State * state, cache_s * cache_t) | ||
| 328 | { | ||
| 329 | int i, j; | ||
| 330 | cache_set_t *set; | ||
| 331 | cache_line_t *cache; | ||
| 332 | |||
| 333 | set = cache_t->sets; | ||
| 334 | for (i = 0; i < cache_t->set; i++, set++) { | ||
| 335 | cache = set->lines; | ||
| 336 | for (j = 0; j < cache_t->way; j++, cache++) { | ||
| 337 | mmu_cache_write_back (state, cache_t, cache); | ||
| 338 | cache->tag = 0; | ||
| 339 | } | ||
| 340 | } | ||
| 341 | }; | ||
| 342 | |||
| 343 | void | ||
| 344 | mmu_cache_soft_flush (ARMul_State * state, cache_s * cache_t, ARMword pa) | ||
| 345 | { | ||
| 346 | ARMword set, way; | ||
| 347 | cache_line_t *cache; | ||
| 348 | pa = (pa / cache_t->width); | ||
| 349 | way = pa & (cache_t->way - 1); | ||
| 350 | set = (pa / cache_t->way) & (cache_t->set - 1); | ||
| 351 | cache = &cache_t->sets[set].lines[way]; | ||
| 352 | |||
| 353 | mmu_cache_write_back (state, cache_t, cache); | ||
| 354 | cache->tag = 0; | ||
| 355 | } | ||
| 356 | |||
| 357 | cache_line_t* mmu_cache_dirty_cache(ARMul_State *state,cache_s *cache){ | ||
| 358 | int i; | ||
| 359 | int j; | ||
| 360 | cache_line_t *cache_line = NULL; | ||
| 361 | cache_set_t *cache_set = cache->sets; | ||
| 362 | int sets = cache->set; | ||
| 363 | for (i = 0; i < sets; i++){ | ||
| 364 | for(j = 0,cache_line = &cache_set[i].lines[0]; j < cache->way; j++,cache_line++){ | ||
| 365 | if((cache_line->tag & TAG_FIRST_HALF_DIRTY) || (cache_line->tag & TAG_LAST_HALF_DIRTY)) | ||
| 366 | return cache_line; | ||
| 367 | } | ||
| 368 | } | ||
| 369 | return NULL; | ||
| 370 | } | ||
diff --git a/src/core/arm/interpreter/mmu/cache.h b/src/core/arm/interpreter/mmu/cache.h deleted file mode 100644 index d308d9b87..000000000 --- a/src/core/arm/interpreter/mmu/cache.h +++ /dev/null | |||
| @@ -1,168 +0,0 @@ | |||
| 1 | #ifndef _MMU_CACHE_H_ | ||
| 2 | #define _MMU_CACHE_H_ | ||
| 3 | |||
| 4 | typedef struct cache_line_t | ||
| 5 | { | ||
| 6 | ARMword tag; /* cache line align address | | ||
| 7 | bit2: last half dirty | ||
| 8 | bit1: first half dirty | ||
| 9 | bit0: cache valid flag | ||
| 10 | */ | ||
| 11 | ARMword pa; /*physical address */ | ||
| 12 | ARMword *data; /*array of cached data */ | ||
| 13 | } cache_line_t; | ||
| 14 | #define TAG_VALID_FLAG 0x00000001 | ||
| 15 | #define TAG_FIRST_HALF_DIRTY 0x00000002 | ||
| 16 | #define TAG_LAST_HALF_DIRTY 0x00000004 | ||
| 17 | |||
| 18 | /*cache set association*/ | ||
| 19 | typedef struct cache_set_s | ||
| 20 | { | ||
| 21 | cache_line_t *lines; | ||
| 22 | int cycle; | ||
| 23 | } cache_set_t; | ||
| 24 | |||
| 25 | enum | ||
| 26 | { | ||
| 27 | CACHE_WRITE_BACK, | ||
| 28 | CACHE_WRITE_THROUGH, | ||
| 29 | }; | ||
| 30 | |||
| 31 | typedef struct cache_s | ||
| 32 | { | ||
| 33 | int width; /*bytes in a line */ | ||
| 34 | int way; /*way of set asscociate */ | ||
| 35 | int set; /*num of set */ | ||
| 36 | int w_mode; /*write back or write through */ | ||
| 37 | //int a_mode; /*alloc mode: random or round-bin*/ | ||
| 38 | cache_set_t *sets; | ||
| 39 | /**/} cache_s; | ||
| 40 | |||
| 41 | typedef struct cache_desc_s | ||
| 42 | { | ||
| 43 | int width; | ||
| 44 | int way; | ||
| 45 | int set; | ||
| 46 | int w_mode; | ||
| 47 | // int a_mode; | ||
| 48 | } cache_desc_t; | ||
| 49 | |||
| 50 | |||
| 51 | /*virtual address to cache set index*/ | ||
| 52 | #define va_cache_set(va, cache_t) \ | ||
| 53 | (((va) / (cache_t)->width) & ((cache_t)->set - 1)) | ||
| 54 | /*virtual address to cahce line aligned*/ | ||
| 55 | #define va_cache_align(va, cache_t) \ | ||
| 56 | ((va) & ~((cache_t)->width - 1)) | ||
| 57 | /*virtaul address to cache line word index*/ | ||
| 58 | #define va_cache_index(va, cache_t) \ | ||
| 59 | (((va) & ((cache_t)->width - 1)) >> WORD_SHT) | ||
| 60 | |||
| 61 | /*see Page 558 in arm manual*/ | ||
| 62 | /*set/index format value to cache set value*/ | ||
| 63 | #define index_cache_set(index, cache_t) \ | ||
| 64 | (((index) / (cache_t)->width) & ((cache_t)->set - 1)) | ||
| 65 | |||
| 66 | /*************************cache********************/ | ||
| 67 | /* mmu cache init | ||
| 68 | * | ||
| 69 | * @cache_t :cache_t to init | ||
| 70 | * @width :cache line width in byte | ||
| 71 | * @way :way of each cache set | ||
| 72 | * @set :cache set num | ||
| 73 | * @w_mode :cache w_mode | ||
| 74 | * | ||
| 75 | * $ -1: error | ||
| 76 | * 0: sucess | ||
| 77 | */ | ||
| 78 | int | ||
| 79 | mmu_cache_init (cache_s * cache_t, int width, int way, int set, int w_mode); | ||
| 80 | |||
| 81 | /* free a cache_t's inner data, the ptr self is not freed, | ||
| 82 | * when needed do like below: | ||
| 83 | * mmu_cache_exit(cache); | ||
| 84 | * free(cache_t); | ||
| 85 | * | ||
| 86 | * @cache_t : the cache_t to free | ||
| 87 | */ | ||
| 88 | void mmu_cache_exit (cache_s * cache_t); | ||
| 89 | |||
| 90 | /* mmu cache search | ||
| 91 | * | ||
| 92 | * @state :ARMul_State | ||
| 93 | * @cache_t :cache_t to search | ||
| 94 | * @va :virtual address | ||
| 95 | * | ||
| 96 | * $ NULL: no cache match | ||
| 97 | * cache :cache matched | ||
| 98 | * */ | ||
| 99 | cache_line_t *mmu_cache_search (ARMul_State * state, cache_s * cache_t, | ||
| 100 | ARMword va); | ||
| 101 | |||
| 102 | /* mmu cache search by set/index | ||
| 103 | * | ||
| 104 | * @state :ARMul_State | ||
| 105 | * @cache_t :cache_t to search | ||
| 106 | * @index :set/index value. | ||
| 107 | * | ||
| 108 | * $ NULL: no cache match | ||
| 109 | * cache :cache matched | ||
| 110 | * */ | ||
| 111 | |||
| 112 | cache_line_t *mmu_cache_search_by_index (ARMul_State * state, | ||
| 113 | cache_s * cache_t, ARMword index); | ||
| 114 | |||
| 115 | /* mmu cache alloc | ||
| 116 | * | ||
| 117 | * @state :ARMul_State | ||
| 118 | * @cache_t :cache_t to alloc from | ||
| 119 | * @va :virtual address that require cache alloc, need not cache aligned | ||
| 120 | * @pa :physical address of va | ||
| 121 | * | ||
| 122 | * $ cache_alloced, always alloc OK | ||
| 123 | */ | ||
| 124 | cache_line_t *mmu_cache_alloc (ARMul_State * state, cache_s * cache_t, | ||
| 125 | ARMword va, ARMword pa); | ||
| 126 | |||
| 127 | /* mmu_cache_write_back write cache data to memory | ||
| 128 | * | ||
| 129 | * @state: | ||
| 130 | * @cache_t :cache_t of the cache line | ||
| 131 | * @cache : cache line | ||
| 132 | */ | ||
| 133 | void | ||
| 134 | mmu_cache_write_back (ARMul_State * state, cache_s * cache_t, | ||
| 135 | cache_line_t * cache); | ||
| 136 | |||
| 137 | /* mmu_cache_clean: clean a cache of va in cache_t | ||
| 138 | * | ||
| 139 | * @state :ARMul_State | ||
| 140 | * @cache_t :cache_t to clean | ||
| 141 | * @va :virtaul address | ||
| 142 | */ | ||
| 143 | void mmu_cache_clean (ARMul_State * state, cache_s * cache_t, ARMword va); | ||
| 144 | void | ||
| 145 | mmu_cache_clean_by_index (ARMul_State * state, cache_s * cache_t, | ||
| 146 | ARMword index); | ||
| 147 | |||
| 148 | /* mmu_cache_invalidate : invalidate a cache of va | ||
| 149 | * | ||
| 150 | * @state :ARMul_State | ||
| 151 | * @cache_t :cache_t to invalid | ||
| 152 | * @va :virt_addr to invalid | ||
| 153 | */ | ||
| 154 | void | ||
| 155 | mmu_cache_invalidate (ARMul_State * state, cache_s * cache_t, ARMword va); | ||
| 156 | |||
| 157 | void | ||
| 158 | mmu_cache_invalidate_by_index (ARMul_State * state, cache_s * cache_t, | ||
| 159 | ARMword index); | ||
| 160 | |||
| 161 | void mmu_cache_invalidate_all (ARMul_State * state, cache_s * cache_t); | ||
| 162 | |||
| 163 | void | ||
| 164 | mmu_cache_soft_flush (ARMul_State * state, cache_s * cache_t, ARMword pa); | ||
| 165 | |||
| 166 | cache_line_t* mmu_cache_dirty_cache(ARMul_State * state, cache_s * cache_t); | ||
| 167 | |||
| 168 | #endif /*_MMU_CACHE_H_*/ | ||
diff --git a/src/core/arm/interpreter/mmu/maverick.cpp b/src/core/arm/interpreter/mmu/maverick.cpp deleted file mode 100644 index a07d4742b..000000000 --- a/src/core/arm/interpreter/mmu/maverick.cpp +++ /dev/null | |||
| @@ -1,1206 +0,0 @@ | |||
| 1 | /* maverick.c -- Cirrus/DSP co-processor interface. | ||
| 2 | Copyright (C) 2003 Free Software Foundation, Inc. | ||
| 3 | Contributed by Aldy Hernandez (aldyh@redhat.com). | ||
| 4 | |||
| 5 | This program is free software; you can redistribute it and/or modify | ||
| 6 | it under the terms of the GNU General Public License as published by | ||
| 7 | the Free Software Foundation; either version 2 of the License, or | ||
| 8 | (at your option) any later version. | ||
| 9 | |||
| 10 | This program is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | GNU General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU General Public License | ||
| 16 | along with this program; if not, write to the Free Software | ||
| 17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
| 18 | |||
| 19 | #include <assert.h> | ||
| 20 | |||
| 21 | #include "core/arm/skyeye_common/armdefs.h" | ||
| 22 | #include "core/arm/skyeye_common/armemu.h" | ||
| 23 | |||
| 24 | |||
| 25 | /*#define CIRRUS_DEBUG 1 */ | ||
| 26 | #if CIRRUS_DEBUG | ||
| 27 | # define printfdbg printf | ||
| 28 | #else | ||
| 29 | # define printfdbg printf_nothing | ||
| 30 | #endif | ||
| 31 | |||
| 32 | #define POS64(i) ( (~(i)) >> 63 ) | ||
| 33 | #define NEG64(i) ( (i) >> 63 ) | ||
| 34 | |||
| 35 | /* Define Co-Processor instruction handlers here. */ | ||
| 36 | |||
| 37 | /* Here's ARMulator's DSP definition. A few things to note: | ||
| 38 | 1) it has 16 64-bit registers and 4 72-bit accumulators | ||
| 39 | 2) you can only access its registers with MCR and MRC. */ | ||
| 40 | |||
| 41 | /* We can't define these in here because this file might not be linked | ||
| 42 | unless the target is arm9e-*. They are defined in wrapper.c. | ||
| 43 | Eventually the simulator should be made to handle any coprocessor | ||
| 44 | at run time. */ | ||
| 45 | struct maverick_regs | ||
| 46 | { | ||
| 47 | union | ||
| 48 | { | ||
| 49 | int i; | ||
| 50 | float f; | ||
| 51 | } upper; | ||
| 52 | |||
| 53 | union | ||
| 54 | { | ||
| 55 | int i; | ||
| 56 | float f; | ||
| 57 | } lower; | ||
| 58 | }; | ||
| 59 | |||
| 60 | union maverick_acc_regs | ||
| 61 | { | ||
| 62 | long double ld; /* Acc registers are 72-bits. */ | ||
| 63 | }; | ||
| 64 | |||
| 65 | struct maverick_regs DSPregs[16]; | ||
| 66 | union maverick_acc_regs DSPacc[4]; | ||
| 67 | ARMword DSPsc; | ||
| 68 | |||
| 69 | #define DEST_REG (BITS (12, 15)) | ||
| 70 | #define SRC1_REG (BITS (16, 19)) | ||
| 71 | #define SRC2_REG (BITS (0, 3)) | ||
| 72 | |||
| 73 | static int lsw_int_index, msw_int_index; | ||
| 74 | static int lsw_float_index, msw_float_index; | ||
| 75 | |||
| 76 | static double mv_getRegDouble (int); | ||
| 77 | static long long mv_getReg64int (int); | ||
| 78 | static void mv_setRegDouble (int, double val); | ||
| 79 | static void mv_setReg64int (int, long long val); | ||
| 80 | |||
| 81 | static union | ||
| 82 | { | ||
| 83 | double d; | ||
| 84 | long long ll; | ||
| 85 | int ints[2]; | ||
| 86 | } reg_conv; | ||
| 87 | |||
| 88 | static void | ||
| 89 | printf_nothing (const char *foo, ...) | ||
| 90 | { | ||
| 91 | } | ||
| 92 | |||
| 93 | static void | ||
| 94 | cirrus_not_implemented (const char *insn) | ||
| 95 | { | ||
| 96 | fprintf (stderr, "Cirrus instruction '%s' not implemented.\n", insn); | ||
| 97 | fprintf (stderr, "aborting!\n"); | ||
| 98 | |||
| 99 | // skyeye_exit (1); | ||
| 100 | } | ||
| 101 | |||
| 102 | static unsigned | ||
| 103 | DSPInit (ARMul_State * state) | ||
| 104 | { | ||
| 105 | NOTICE_LOG(ARM11, "ARMul_ConsolePrint: DSP present"); | ||
| 106 | return TRUE; | ||
| 107 | } | ||
| 108 | |||
| 109 | unsigned | ||
| 110 | DSPMRC4 (ARMul_State * state, | ||
| 111 | unsigned type, ARMword instr, ARMword * value) | ||
| 112 | { | ||
| 113 | switch (BITS (5, 7)) { | ||
| 114 | case 0: /* cfmvrdl */ | ||
| 115 | /* Move lower half of a DF stored in a DSP reg into an Arm reg. */ | ||
| 116 | printfdbg ("cfmvrdl\n"); | ||
| 117 | printfdbg ("\tlower half=0x%x\n", DSPregs[SRC1_REG].lower.i); | ||
| 118 | printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG)); | ||
| 119 | |||
| 120 | *value = (ARMword) DSPregs[SRC1_REG].lower.i; | ||
| 121 | break; | ||
| 122 | |||
| 123 | case 1: /* cfmvrdh */ | ||
| 124 | /* Move upper half of a DF stored in a DSP reg into an Arm reg. */ | ||
| 125 | printfdbg ("cfmvrdh\n"); | ||
| 126 | printfdbg ("\tupper half=0x%x\n", DSPregs[SRC1_REG].upper.i); | ||
| 127 | printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG)); | ||
| 128 | |||
| 129 | *value = (ARMword) DSPregs[SRC1_REG].upper.i; | ||
| 130 | break; | ||
| 131 | |||
| 132 | case 2: /* cfmvrs */ | ||
| 133 | /* Move SF from upper half of a DSP register to an Arm register. */ | ||
| 134 | *value = (ARMword) DSPregs[SRC1_REG].upper.i; | ||
| 135 | printfdbg ("cfmvrs = mvf%d <-- %f\n", | ||
| 136 | SRC1_REG, DSPregs[SRC1_REG].upper.f); | ||
| 137 | break; | ||
| 138 | |||
| 139 | #ifdef doesnt_work | ||
| 140 | case 4: /* cfcmps */ | ||
| 141 | { | ||
| 142 | float a, b; | ||
| 143 | int n, z, c, v; | ||
| 144 | |||
| 145 | a = DSPregs[SRC1_REG].upper.f; | ||
| 146 | b = DSPregs[SRC2_REG].upper.f; | ||
| 147 | |||
| 148 | printfdbg ("cfcmps\n"); | ||
| 149 | printfdbg ("\tcomparing %f and %f\n", a, b); | ||
| 150 | |||
| 151 | z = a == b; /* zero */ | ||
| 152 | n = a != b; /* negative */ | ||
| 153 | v = a > b; /* overflow */ | ||
| 154 | c = 0; /* carry */ | ||
| 155 | *value = (n << 31) | (z << 30) | (c << 29) | (v << | ||
| 156 | 28); | ||
| 157 | break; | ||
| 158 | } | ||
| 159 | |||
| 160 | case 5: /* cfcmpd */ | ||
| 161 | { | ||
| 162 | double a, b; | ||
| 163 | int n, z, c, v; | ||
| 164 | |||
| 165 | a = mv_getRegDouble (SRC1_REG); | ||
| 166 | b = mv_getRegDouble (SRC2_REG); | ||
| 167 | |||
| 168 | printfdbg ("cfcmpd\n"); | ||
| 169 | printfdbg ("\tcomparing %g and %g\n", a, b); | ||
| 170 | |||
| 171 | z = a == b; /* zero */ | ||
| 172 | n = a != b; /* negative */ | ||
| 173 | v = a > b; /* overflow */ | ||
| 174 | c = 0; /* carry */ | ||
| 175 | *value = (n << 31) | (z << 30) | (c << 29) | (v << | ||
| 176 | 28); | ||
| 177 | break; | ||
| 178 | } | ||
| 179 | #else | ||
| 180 | case 4: /* cfcmps */ | ||
| 181 | { | ||
| 182 | float a, b; | ||
| 183 | int n, z, c, v; | ||
| 184 | |||
| 185 | a = DSPregs[SRC1_REG].upper.f; | ||
| 186 | b = DSPregs[SRC2_REG].upper.f; | ||
| 187 | |||
| 188 | printfdbg ("cfcmps\n"); | ||
| 189 | printfdbg ("\tcomparing %f and %f\n", a, b); | ||
| 190 | |||
| 191 | z = a == b; /* zero */ | ||
| 192 | n = a < b; /* negative */ | ||
| 193 | c = a > b; /* carry */ | ||
| 194 | v = 0; /* fixme */ | ||
| 195 | printfdbg ("\tz = %d, n = %d\n", z, n); | ||
| 196 | *value = (n << 31) | (z << 30) | (c << 29) | (v << | ||
| 197 | 28); | ||
| 198 | break; | ||
| 199 | } | ||
| 200 | |||
| 201 | case 5: /* cfcmpd */ | ||
| 202 | { | ||
| 203 | double a, b; | ||
| 204 | int n, z, c, v; | ||
| 205 | |||
| 206 | a = mv_getRegDouble (SRC1_REG); | ||
| 207 | b = mv_getRegDouble (SRC2_REG); | ||
| 208 | |||
| 209 | printfdbg ("cfcmpd\n"); | ||
| 210 | printfdbg ("\tcomparing %g and %g\n", a, b); | ||
| 211 | |||
| 212 | z = a == b; /* zero */ | ||
| 213 | n = a < b; /* negative */ | ||
| 214 | c = a > b; /* carry */ | ||
| 215 | v = 0; /* fixme */ | ||
| 216 | *value = (n << 31) | (z << 30) | (c << 29) | (v << | ||
| 217 | 28); | ||
| 218 | break; | ||
| 219 | } | ||
| 220 | #endif | ||
| 221 | default: | ||
| 222 | fprintf (stderr, "unknown opcode in DSPMRC4 0x%x\n", instr); | ||
| 223 | cirrus_not_implemented ("unknown"); | ||
| 224 | break; | ||
| 225 | } | ||
| 226 | |||
| 227 | return ARMul_DONE; | ||
| 228 | } | ||
| 229 | |||
| 230 | unsigned | ||
| 231 | DSPMRC5 (ARMul_State * state, | ||
| 232 | unsigned type, ARMword instr, ARMword * value) | ||
| 233 | { | ||
| 234 | switch (BITS (5, 7)) { | ||
| 235 | case 0: /* cfmvr64l */ | ||
| 236 | /* Move lower half of 64bit int from Cirrus to Arm. */ | ||
| 237 | *value = (ARMword) DSPregs[SRC1_REG].lower.i; | ||
| 238 | printfdbg ("cfmvr64l ARM_REG = mvfx%d <-- %d\n", | ||
| 239 | DEST_REG, (int) *value); | ||
| 240 | break; | ||
| 241 | |||
| 242 | case 1: /* cfmvr64h */ | ||
| 243 | /* Move upper half of 64bit int from Cirrus to Arm. */ | ||
| 244 | *value = (ARMword) DSPregs[SRC1_REG].upper.i; | ||
| 245 | printfdbg ("cfmvr64h <-- %d\n", (int) *value); | ||
| 246 | break; | ||
| 247 | |||
| 248 | case 4: /* cfcmp32 */ | ||
| 249 | { | ||
| 250 | int res; | ||
| 251 | int n, z, c, v; | ||
| 252 | unsigned int a, b; | ||
| 253 | |||
| 254 | printfdbg ("cfcmp32 mvfx%d - mvfx%d\n", SRC1_REG, | ||
| 255 | SRC2_REG); | ||
| 256 | |||
| 257 | /* FIXME: see comment for cfcmps. */ | ||
| 258 | a = DSPregs[SRC1_REG].lower.i; | ||
| 259 | b = DSPregs[SRC2_REG].lower.i; | ||
| 260 | |||
| 261 | res = DSPregs[SRC1_REG].lower.i - | ||
| 262 | DSPregs[SRC2_REG].lower.i; | ||
| 263 | /* zero */ | ||
| 264 | z = res == 0; | ||
| 265 | /* negative */ | ||
| 266 | n = res < 0; | ||
| 267 | /* overflow */ | ||
| 268 | v = SubOverflow (DSPregs[SRC1_REG].lower.i, | ||
| 269 | DSPregs[SRC2_REG].lower.i, res); | ||
| 270 | /* carry */ | ||
| 271 | c = (NEG (a) && POS (b) || | ||
| 272 | (NEG (a) && POS (res)) || (POS (b) | ||
| 273 | && POS (res))); | ||
| 274 | |||
| 275 | *value = (n << 31) | (z << 30) | (c << 29) | (v << | ||
| 276 | 28); | ||
| 277 | break; | ||
| 278 | } | ||
| 279 | |||
| 280 | case 5: /* cfcmp64 */ | ||
| 281 | { | ||
| 282 | long long res; | ||
| 283 | int n, z, c, v; | ||
| 284 | unsigned long long a, b; | ||
| 285 | |||
| 286 | printfdbg ("cfcmp64 mvdx%d - mvdx%d\n", SRC1_REG, | ||
| 287 | SRC2_REG); | ||
| 288 | |||
| 289 | /* fixme: see comment for cfcmps. */ | ||
| 290 | |||
| 291 | a = mv_getReg64int (SRC1_REG); | ||
| 292 | b = mv_getReg64int (SRC2_REG); | ||
| 293 | |||
| 294 | res = mv_getReg64int (SRC1_REG) - | ||
| 295 | mv_getReg64int (SRC2_REG); | ||
| 296 | /* zero */ | ||
| 297 | z = res == 0; | ||
| 298 | /* negative */ | ||
| 299 | n = res < 0; | ||
| 300 | /* overflow */ | ||
| 301 | v = ((NEG64 (a) && POS64 (b) && POS64 (res)) | ||
| 302 | || (POS64 (a) && NEG64 (b) && NEG64 (res))); | ||
| 303 | /* carry */ | ||
| 304 | c = (NEG64 (a) && POS64 (b) || | ||
| 305 | (NEG64 (a) && POS64 (res)) || (POS64 (b) | ||
| 306 | && POS64 (res))); | ||
| 307 | |||
| 308 | *value = (n << 31) | (z << 30) | (c << 29) | (v << | ||
| 309 | 28); | ||
| 310 | break; | ||
| 311 | } | ||
| 312 | |||
| 313 | default: | ||
| 314 | fprintf (stderr, "unknown opcode in DSPMRC5 0x%x\n", instr); | ||
| 315 | cirrus_not_implemented ("unknown"); | ||
| 316 | break; | ||
| 317 | } | ||
| 318 | |||
| 319 | return ARMul_DONE; | ||
| 320 | } | ||
| 321 | |||
| 322 | unsigned | ||
| 323 | DSPMRC6 (ARMul_State * state, | ||
| 324 | unsigned type, ARMword instr, ARMword * value) | ||
| 325 | { | ||
| 326 | switch (BITS (5, 7)) { | ||
| 327 | case 0: /* cfmval32 */ | ||
| 328 | cirrus_not_implemented ("cfmval32"); | ||
| 329 | break; | ||
| 330 | |||
| 331 | case 1: /* cfmvam32 */ | ||
| 332 | cirrus_not_implemented ("cfmvam32"); | ||
| 333 | break; | ||
| 334 | |||
| 335 | case 2: /* cfmvah32 */ | ||
| 336 | cirrus_not_implemented ("cfmvah32"); | ||
| 337 | break; | ||
| 338 | |||
| 339 | case 3: /* cfmva32 */ | ||
| 340 | cirrus_not_implemented ("cfmva32"); | ||
| 341 | break; | ||
| 342 | |||
| 343 | case 4: /* cfmva64 */ | ||
| 344 | cirrus_not_implemented ("cfmva64"); | ||
| 345 | break; | ||
| 346 | |||
| 347 | case 5: /* cfmvsc32 */ | ||
| 348 | cirrus_not_implemented ("cfmvsc32"); | ||
| 349 | break; | ||
| 350 | |||
| 351 | default: | ||
| 352 | fprintf (stderr, "unknown opcode in DSPMRC6 0x%x\n", instr); | ||
| 353 | cirrus_not_implemented ("unknown"); | ||
| 354 | break; | ||
| 355 | } | ||
| 356 | |||
| 357 | return ARMul_DONE; | ||
| 358 | } | ||
| 359 | |||
| 360 | unsigned | ||
| 361 | DSPMCR4 (ARMul_State * state, | ||
| 362 | unsigned type, ARMword instr, ARMword value) | ||
| 363 | { | ||
| 364 | switch (BITS (5, 7)) { | ||
| 365 | case 0: /* cfmvdlr */ | ||
| 366 | /* Move the lower half of a DF value from an Arm register into | ||
| 367 | the lower half of a Cirrus register. */ | ||
| 368 | printfdbg ("cfmvdlr <-- 0x%x\n", (int) value); | ||
| 369 | DSPregs[SRC1_REG].lower.i = (int) value; | ||
| 370 | break; | ||
| 371 | |||
| 372 | case 1: /* cfmvdhr */ | ||
| 373 | /* Move the upper half of a DF value from an Arm register into | ||
| 374 | the upper half of a Cirrus register. */ | ||
| 375 | printfdbg ("cfmvdhr <-- 0x%x\n", (int) value); | ||
| 376 | DSPregs[SRC1_REG].upper.i = (int) value; | ||
| 377 | break; | ||
| 378 | |||
| 379 | case 2: /* cfmvsr */ | ||
| 380 | /* Move SF from Arm register into upper half of Cirrus register. */ | ||
| 381 | printfdbg ("cfmvsr <-- 0x%x\n", (int) value); | ||
| 382 | DSPregs[SRC1_REG].upper.i = (int) value; | ||
| 383 | break; | ||
| 384 | |||
| 385 | default: | ||
| 386 | fprintf (stderr, "unknown opcode in DSPMCR4 0x%x\n", instr); | ||
| 387 | cirrus_not_implemented ("unknown"); | ||
| 388 | break; | ||
| 389 | } | ||
| 390 | |||
| 391 | return ARMul_DONE; | ||
| 392 | } | ||
| 393 | |||
| 394 | unsigned | ||
| 395 | DSPMCR5 (ARMul_State * state, | ||
| 396 | unsigned type, ARMword instr, ARMword value) | ||
| 397 | { | ||
| 398 | union | ||
| 399 | { | ||
| 400 | int s; | ||
| 401 | unsigned int us; | ||
| 402 | } val; | ||
| 403 | |||
| 404 | switch (BITS (5, 7)) { | ||
| 405 | case 0: /* cfmv64lr */ | ||
| 406 | /* Move lower half of a 64bit int from an ARM register into the | ||
| 407 | lower half of a DSP register and sign extend it. */ | ||
| 408 | printfdbg ("cfmv64lr mvdx%d <-- 0x%x\n", SRC1_REG, | ||
| 409 | (int) value); | ||
| 410 | DSPregs[SRC1_REG].lower.i = (int) value; | ||
| 411 | break; | ||
| 412 | |||
| 413 | case 1: /* cfmv64hr */ | ||
| 414 | /* Move upper half of a 64bit int from an ARM register into the | ||
| 415 | upper half of a DSP register. */ | ||
| 416 | printfdbg ("cfmv64hr ARM_REG = mvfx%d <-- 0x%x\n", | ||
| 417 | SRC1_REG, (int) value); | ||
| 418 | DSPregs[SRC1_REG].upper.i = (int) value; | ||
| 419 | break; | ||
| 420 | |||
| 421 | case 2: /* cfrshl32 */ | ||
| 422 | printfdbg ("cfrshl32\n"); | ||
| 423 | val.us = value; | ||
| 424 | if (val.s > 0) | ||
| 425 | DSPregs[SRC2_REG].lower.i = | ||
| 426 | DSPregs[SRC1_REG].lower.i << value; | ||
| 427 | else | ||
| 428 | DSPregs[SRC2_REG].lower.i = | ||
| 429 | DSPregs[SRC1_REG].lower.i >> -value; | ||
| 430 | break; | ||
| 431 | |||
| 432 | case 3: /* cfrshl64 */ | ||
| 433 | printfdbg ("cfrshl64\n"); | ||
| 434 | val.us = value; | ||
| 435 | if (val.s > 0) | ||
| 436 | mv_setReg64int (SRC2_REG, | ||
| 437 | mv_getReg64int (SRC1_REG) << value); | ||
| 438 | else | ||
| 439 | mv_setReg64int (SRC2_REG, | ||
| 440 | mv_getReg64int (SRC1_REG) >> -value); | ||
| 441 | break; | ||
| 442 | |||
| 443 | default: | ||
| 444 | fprintf (stderr, "unknown opcode in DSPMCR5 0x%x\n", instr); | ||
| 445 | cirrus_not_implemented ("unknown"); | ||
| 446 | break; | ||
| 447 | } | ||
| 448 | |||
| 449 | return ARMul_DONE; | ||
| 450 | } | ||
| 451 | |||
| 452 | unsigned | ||
| 453 | DSPMCR6 (ARMul_State * state, | ||
| 454 | unsigned type, ARMword instr, ARMword value) | ||
| 455 | { | ||
| 456 | switch (BITS (5, 7)) { | ||
| 457 | case 0: /* cfmv32al */ | ||
| 458 | cirrus_not_implemented ("cfmv32al"); | ||
| 459 | break; | ||
| 460 | |||
| 461 | case 1: /* cfmv32am */ | ||
| 462 | cirrus_not_implemented ("cfmv32am"); | ||
| 463 | break; | ||
| 464 | |||
| 465 | case 2: /* cfmv32ah */ | ||
| 466 | cirrus_not_implemented ("cfmv32ah"); | ||
| 467 | break; | ||
| 468 | |||
| 469 | case 3: /* cfmv32a */ | ||
| 470 | cirrus_not_implemented ("cfmv32a"); | ||
| 471 | break; | ||
| 472 | |||
| 473 | case 4: /* cfmv64a */ | ||
| 474 | cirrus_not_implemented ("cfmv64a"); | ||
| 475 | break; | ||
| 476 | |||
| 477 | case 5: /* cfmv32sc */ | ||
| 478 | cirrus_not_implemented ("cfmv32sc"); | ||
| 479 | break; | ||
| 480 | |||
| 481 | default: | ||
| 482 | fprintf (stderr, "unknown opcode in DSPMCR6 0x%x\n", instr); | ||
| 483 | cirrus_not_implemented ("unknown"); | ||
| 484 | break; | ||
| 485 | } | ||
| 486 | |||
| 487 | return ARMul_DONE; | ||
| 488 | } | ||
| 489 | |||
| 490 | unsigned | ||
| 491 | DSPLDC4 (ARMul_State * state, | ||
| 492 | unsigned type, ARMword instr, ARMword data) | ||
| 493 | { | ||
| 494 | static unsigned words; | ||
| 495 | |||
| 496 | if (type != ARMul_DATA) { | ||
| 497 | words = 0; | ||
| 498 | return ARMul_DONE; | ||
| 499 | } | ||
| 500 | |||
| 501 | if (BIT (22)) { /* it's a long access, get two words */ | ||
| 502 | /* cfldrd */ | ||
| 503 | |||
| 504 | printfdbg | ||
| 505 | ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n", | ||
| 506 | data, words, state->bigendSig, DEST_REG); | ||
| 507 | |||
| 508 | if (words == 0) { | ||
| 509 | if (state->bigendSig) | ||
| 510 | DSPregs[DEST_REG].upper.i = (int) data; | ||
| 511 | else | ||
| 512 | DSPregs[DEST_REG].lower.i = (int) data; | ||
| 513 | } | ||
| 514 | else { | ||
| 515 | if (state->bigendSig) | ||
| 516 | DSPregs[DEST_REG].lower.i = (int) data; | ||
| 517 | else | ||
| 518 | DSPregs[DEST_REG].upper.i = (int) data; | ||
| 519 | } | ||
| 520 | |||
| 521 | ++words; | ||
| 522 | |||
| 523 | if (words == 2) { | ||
| 524 | printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG, | ||
| 525 | mv_getRegDouble (DEST_REG)); | ||
| 526 | |||
| 527 | return ARMul_DONE; | ||
| 528 | } | ||
| 529 | else | ||
| 530 | return ARMul_INC; | ||
| 531 | } | ||
| 532 | else { | ||
| 533 | /* Get just one word. */ | ||
| 534 | |||
| 535 | /* cfldrs */ | ||
| 536 | printfdbg ("cfldrs\n"); | ||
| 537 | |||
| 538 | DSPregs[DEST_REG].upper.i = (int) data; | ||
| 539 | |||
| 540 | printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG, | ||
| 541 | DSPregs[DEST_REG].upper.f); | ||
| 542 | |||
| 543 | return ARMul_DONE; | ||
| 544 | } | ||
| 545 | } | ||
| 546 | |||
| 547 | unsigned | ||
| 548 | DSPLDC5 (ARMul_State * state, | ||
| 549 | unsigned type, ARMword instr, ARMword data) | ||
| 550 | { | ||
| 551 | static unsigned words; | ||
| 552 | |||
| 553 | if (type != ARMul_DATA) { | ||
| 554 | words = 0; | ||
| 555 | return ARMul_DONE; | ||
| 556 | } | ||
| 557 | |||
| 558 | if (BIT (22)) { | ||
| 559 | /* It's a long access, get two words. */ | ||
| 560 | |||
| 561 | /* cfldr64 */ | ||
| 562 | printfdbg ("cfldr64: %d\n", data); | ||
| 563 | |||
| 564 | if (words == 0) { | ||
| 565 | if (state->bigendSig) | ||
| 566 | DSPregs[DEST_REG].upper.i = (int) data; | ||
| 567 | else | ||
| 568 | DSPregs[DEST_REG].lower.i = (int) data; | ||
| 569 | } | ||
| 570 | else { | ||
| 571 | if (state->bigendSig) | ||
| 572 | DSPregs[DEST_REG].lower.i = (int) data; | ||
| 573 | else | ||
| 574 | DSPregs[DEST_REG].upper.i = (int) data; | ||
| 575 | } | ||
| 576 | |||
| 577 | ++words; | ||
| 578 | |||
| 579 | if (words == 2) { | ||
| 580 | printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG, | ||
| 581 | mv_getReg64int (DEST_REG)); | ||
| 582 | |||
| 583 | return ARMul_DONE; | ||
| 584 | } | ||
| 585 | else | ||
| 586 | return ARMul_INC; | ||
| 587 | } | ||
| 588 | else { | ||
| 589 | /* Get just one word. */ | ||
| 590 | |||
| 591 | /* cfldr32 */ | ||
| 592 | printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG, (int) data); | ||
| 593 | |||
| 594 | /* 32bit ints should be sign extended to 64bits when loaded. */ | ||
| 595 | mv_setReg64int (DEST_REG, (long long) data); | ||
| 596 | |||
| 597 | return ARMul_DONE; | ||
| 598 | } | ||
| 599 | } | ||
| 600 | |||
| 601 | unsigned | ||
| 602 | DSPSTC4 (ARMul_State * state, | ||
| 603 | unsigned type, ARMword instr, ARMword * data) | ||
| 604 | { | ||
| 605 | static unsigned words; | ||
| 606 | |||
| 607 | if (type != ARMul_DATA) { | ||
| 608 | words = 0; | ||
| 609 | return ARMul_DONE; | ||
| 610 | } | ||
| 611 | |||
| 612 | if (BIT (22)) { | ||
| 613 | /* It's a long access, get two words. */ | ||
| 614 | /* cfstrd */ | ||
| 615 | printfdbg ("cfstrd\n"); | ||
| 616 | |||
| 617 | if (words == 0) { | ||
| 618 | if (state->bigendSig) | ||
| 619 | *data = (ARMword) DSPregs[DEST_REG].upper.i; | ||
| 620 | else | ||
| 621 | *data = (ARMword) DSPregs[DEST_REG].lower.i; | ||
| 622 | } | ||
| 623 | else { | ||
| 624 | if (state->bigendSig) | ||
| 625 | *data = (ARMword) DSPregs[DEST_REG].lower.i; | ||
| 626 | else | ||
| 627 | *data = (ARMword) DSPregs[DEST_REG].upper.i; | ||
| 628 | } | ||
| 629 | |||
| 630 | ++words; | ||
| 631 | |||
| 632 | if (words == 2) { | ||
| 633 | printfdbg ("\tmem = mvd%d = %g\n", DEST_REG, | ||
| 634 | mv_getRegDouble (DEST_REG)); | ||
| 635 | |||
| 636 | return ARMul_DONE; | ||
| 637 | } | ||
| 638 | else | ||
| 639 | return ARMul_INC; | ||
| 640 | } | ||
| 641 | else { | ||
| 642 | /* Get just one word. */ | ||
| 643 | /* cfstrs */ | ||
| 644 | printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG, | ||
| 645 | DSPregs[DEST_REG].upper.f); | ||
| 646 | |||
| 647 | *data = (ARMword) DSPregs[DEST_REG].upper.i; | ||
| 648 | |||
| 649 | return ARMul_DONE; | ||
| 650 | } | ||
| 651 | } | ||
| 652 | |||
| 653 | unsigned | ||
| 654 | DSPSTC5 (ARMul_State * state, | ||
| 655 | unsigned type, ARMword instr, ARMword * data) | ||
| 656 | { | ||
| 657 | static unsigned words; | ||
| 658 | |||
| 659 | if (type != ARMul_DATA) { | ||
| 660 | words = 0; | ||
| 661 | return ARMul_DONE; | ||
| 662 | } | ||
| 663 | |||
| 664 | if (BIT (22)) { | ||
| 665 | /* It's a long access, store two words. */ | ||
| 666 | /* cfstr64 */ | ||
| 667 | printfdbg ("cfstr64\n"); | ||
| 668 | |||
| 669 | if (words == 0) { | ||
| 670 | if (state->bigendSig) | ||
| 671 | *data = (ARMword) DSPregs[DEST_REG].upper.i; | ||
| 672 | else | ||
| 673 | *data = (ARMword) DSPregs[DEST_REG].lower.i; | ||
| 674 | } | ||
| 675 | else { | ||
| 676 | if (state->bigendSig) | ||
| 677 | *data = (ARMword) DSPregs[DEST_REG].lower.i; | ||
| 678 | else | ||
| 679 | *data = (ARMword) DSPregs[DEST_REG].upper.i; | ||
| 680 | } | ||
| 681 | |||
| 682 | ++words; | ||
| 683 | |||
| 684 | if (words == 2) { | ||
| 685 | printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG, | ||
| 686 | mv_getReg64int (DEST_REG)); | ||
| 687 | |||
| 688 | return ARMul_DONE; | ||
| 689 | } | ||
| 690 | else | ||
| 691 | return ARMul_INC; | ||
| 692 | } | ||
| 693 | else { | ||
| 694 | /* Store just one word. */ | ||
| 695 | /* cfstr32 */ | ||
| 696 | *data = (ARMword) DSPregs[DEST_REG].lower.i; | ||
| 697 | |||
| 698 | printfdbg ("cfstr32 MEM = %d\n", (int) *data); | ||
| 699 | |||
| 700 | return ARMul_DONE; | ||
| 701 | } | ||
| 702 | } | ||
| 703 | |||
| 704 | unsigned | ||
| 705 | DSPCDP4 (ARMul_State * state, unsigned type, ARMword instr) | ||
| 706 | { | ||
| 707 | int opcode2; | ||
| 708 | |||
| 709 | opcode2 = BITS (5, 7); | ||
| 710 | |||
| 711 | switch (BITS (20, 21)) { | ||
| 712 | case 0: | ||
| 713 | switch (opcode2) { | ||
| 714 | case 0: /* cfcpys */ | ||
| 715 | printfdbg ("cfcpys mvf%d = mvf%d = %f\n", | ||
| 716 | DEST_REG, SRC1_REG, | ||
| 717 | DSPregs[SRC1_REG].upper.f); | ||
| 718 | DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f; | ||
| 719 | break; | ||
| 720 | |||
| 721 | case 1: /* cfcpyd */ | ||
| 722 | printfdbg ("cfcpyd mvd%d = mvd%d = %g\n", | ||
| 723 | DEST_REG, SRC1_REG, | ||
| 724 | mv_getRegDouble (SRC1_REG)); | ||
| 725 | mv_setRegDouble (DEST_REG, | ||
| 726 | mv_getRegDouble (SRC1_REG)); | ||
| 727 | break; | ||
| 728 | |||
| 729 | case 2: /* cfcvtds */ | ||
| 730 | printfdbg ("cfcvtds mvf%d = (float) mvd%d = %f\n", | ||
| 731 | DEST_REG, SRC1_REG, | ||
| 732 | (float) mv_getRegDouble (SRC1_REG)); | ||
| 733 | DSPregs[DEST_REG].upper.f = | ||
| 734 | (float) mv_getRegDouble (SRC1_REG); | ||
| 735 | break; | ||
| 736 | |||
| 737 | case 3: /* cfcvtsd */ | ||
| 738 | printfdbg ("cfcvtsd mvd%d = mvf%d = %g\n", | ||
| 739 | DEST_REG, SRC1_REG, | ||
| 740 | (double) DSPregs[SRC1_REG].upper.f); | ||
| 741 | mv_setRegDouble (DEST_REG, | ||
| 742 | (double) DSPregs[SRC1_REG].upper.f); | ||
| 743 | break; | ||
| 744 | |||
| 745 | case 4: /* cfcvt32s */ | ||
| 746 | printfdbg ("cfcvt32s mvf%d = mvfx%d = %f\n", | ||
| 747 | DEST_REG, SRC1_REG, | ||
| 748 | (float) DSPregs[SRC1_REG].lower.i); | ||
| 749 | DSPregs[DEST_REG].upper.f = | ||
| 750 | (float) DSPregs[SRC1_REG].lower.i; | ||
| 751 | break; | ||
| 752 | |||
| 753 | case 5: /* cfcvt32d */ | ||
| 754 | printfdbg ("cfcvt32d mvd%d = mvfx%d = %g\n", | ||
| 755 | DEST_REG, SRC1_REG, | ||
| 756 | (double) DSPregs[SRC1_REG].lower.i); | ||
| 757 | mv_setRegDouble (DEST_REG, | ||
| 758 | (double) DSPregs[SRC1_REG].lower.i); | ||
| 759 | break; | ||
| 760 | |||
| 761 | case 6: /* cfcvt64s */ | ||
| 762 | printfdbg ("cfcvt64s mvf%d = mvdx%d = %f\n", | ||
| 763 | DEST_REG, SRC1_REG, | ||
| 764 | (float) mv_getReg64int (SRC1_REG)); | ||
| 765 | DSPregs[DEST_REG].upper.f = | ||
| 766 | (float) mv_getReg64int (SRC1_REG); | ||
| 767 | break; | ||
| 768 | |||
| 769 | case 7: /* cfcvt64d */ | ||
| 770 | printfdbg ("cfcvt64d mvd%d = mvdx%d = %g\n", | ||
| 771 | DEST_REG, SRC1_REG, | ||
| 772 | (double) mv_getReg64int (SRC1_REG)); | ||
| 773 | mv_setRegDouble (DEST_REG, | ||
| 774 | (double) mv_getReg64int (SRC1_REG)); | ||
| 775 | break; | ||
| 776 | } | ||
| 777 | break; | ||
| 778 | |||
| 779 | case 1: | ||
| 780 | switch (opcode2) { | ||
| 781 | case 0: /* cfmuls */ | ||
| 782 | printfdbg ("cfmuls mvf%d = mvf%d = %f\n", | ||
| 783 | DEST_REG, | ||
| 784 | SRC1_REG, | ||
| 785 | DSPregs[SRC1_REG].upper.f * | ||
| 786 | DSPregs[SRC2_REG].upper.f); | ||
| 787 | |||
| 788 | DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f | ||
| 789 | * DSPregs[SRC2_REG].upper.f; | ||
| 790 | break; | ||
| 791 | |||
| 792 | case 1: /* cfmuld */ | ||
| 793 | printfdbg ("cfmuld mvd%d = mvd%d = %g\n", | ||
| 794 | DEST_REG, | ||
| 795 | SRC1_REG, | ||
| 796 | mv_getRegDouble (SRC1_REG) * | ||
| 797 | mv_getRegDouble (SRC2_REG)); | ||
| 798 | |||
| 799 | mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG) | ||
| 800 | * mv_getRegDouble (SRC2_REG)); | ||
| 801 | break; | ||
| 802 | |||
| 803 | default: | ||
| 804 | fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", | ||
| 805 | instr); | ||
| 806 | cirrus_not_implemented ("unknown"); | ||
| 807 | break; | ||
| 808 | } | ||
| 809 | break; | ||
| 810 | |||
| 811 | case 3: | ||
| 812 | switch (opcode2) { | ||
| 813 | case 0: /* cfabss */ | ||
| 814 | DSPregs[DEST_REG].upper.f = | ||
| 815 | (DSPregs[SRC1_REG].upper.f < | ||
| 816 | 0.0F ? -DSPregs[SRC1_REG].upper. | ||
| 817 | f : DSPregs[SRC1_REG].upper.f); | ||
| 818 | printfdbg ("cfabss mvf%d = |mvf%d| = %f\n", DEST_REG, | ||
| 819 | SRC1_REG, DSPregs[DEST_REG].upper.f); | ||
| 820 | break; | ||
| 821 | |||
| 822 | case 1: /* cfabsd */ | ||
| 823 | mv_setRegDouble (DEST_REG, | ||
| 824 | (mv_getRegDouble (SRC1_REG) < 0.0 ? | ||
| 825 | -mv_getRegDouble (SRC1_REG) | ||
| 826 | : mv_getRegDouble (SRC1_REG))); | ||
| 827 | printfdbg ("cfabsd mvd%d = |mvd%d| = %g\n", | ||
| 828 | DEST_REG, SRC1_REG, | ||
| 829 | mv_getRegDouble (DEST_REG)); | ||
| 830 | break; | ||
| 831 | |||
| 832 | case 2: /* cfnegs */ | ||
| 833 | DSPregs[DEST_REG].upper.f = | ||
| 834 | -DSPregs[SRC1_REG].upper.f; | ||
| 835 | printfdbg ("cfnegs mvf%d = -mvf%d = %f\n", DEST_REG, | ||
| 836 | SRC1_REG, DSPregs[DEST_REG].upper.f); | ||
| 837 | break; | ||
| 838 | |||
| 839 | case 3: /* cfnegd */ | ||
| 840 | mv_setRegDouble (DEST_REG, | ||
| 841 | -mv_getRegDouble (SRC1_REG)); | ||
| 842 | printfdbg ("cfnegd mvd%d = -mvd%d = %g\n", DEST_REG, | ||
| 843 | mv_getRegDouble (DEST_REG)); | ||
| 844 | break; | ||
| 845 | |||
| 846 | case 4: /* cfadds */ | ||
| 847 | DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f | ||
| 848 | + DSPregs[SRC2_REG].upper.f; | ||
| 849 | printfdbg ("cfadds mvf%d = mvf%d + mvf%d = %f\n", | ||
| 850 | DEST_REG, SRC1_REG, SRC2_REG, | ||
| 851 | DSPregs[DEST_REG].upper.f); | ||
| 852 | break; | ||
| 853 | |||
| 854 | case 5: /* cfaddd */ | ||
| 855 | mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG) | ||
| 856 | + mv_getRegDouble (SRC2_REG)); | ||
| 857 | printfdbg ("cfaddd: mvd%d = mvd%d + mvd%d = %g\n", | ||
| 858 | DEST_REG, | ||
| 859 | SRC1_REG, SRC2_REG, | ||
| 860 | mv_getRegDouble (DEST_REG)); | ||
| 861 | break; | ||
| 862 | |||
| 863 | case 6: /* cfsubs */ | ||
| 864 | DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f | ||
| 865 | - DSPregs[SRC2_REG].upper.f; | ||
| 866 | printfdbg ("cfsubs: mvf%d = mvf%d - mvf%d = %f\n", | ||
| 867 | DEST_REG, SRC1_REG, SRC2_REG, | ||
| 868 | DSPregs[DEST_REG].upper.f); | ||
| 869 | break; | ||
| 870 | |||
| 871 | case 7: /* cfsubd */ | ||
| 872 | mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG) | ||
| 873 | - mv_getRegDouble (SRC2_REG)); | ||
| 874 | printfdbg ("cfsubd: mvd%d = mvd%d - mvd%d = %g\n", | ||
| 875 | DEST_REG, | ||
| 876 | SRC1_REG, SRC2_REG, | ||
| 877 | mv_getRegDouble (DEST_REG)); | ||
| 878 | break; | ||
| 879 | } | ||
| 880 | break; | ||
| 881 | |||
| 882 | default: | ||
| 883 | fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr); | ||
| 884 | cirrus_not_implemented ("unknown"); | ||
| 885 | break; | ||
| 886 | } | ||
| 887 | |||
| 888 | return ARMul_DONE; | ||
| 889 | } | ||
| 890 | |||
| 891 | unsigned | ||
| 892 | DSPCDP5 (ARMul_State * state, unsigned type, ARMword instr) | ||
| 893 | { | ||
| 894 | int opcode2; | ||
| 895 | char shift; | ||
| 896 | |||
| 897 | opcode2 = BITS (5, 7); | ||
| 898 | |||
| 899 | /* Shift constants are 7bit signed numbers in bits 0..3|5..7. */ | ||
| 900 | shift = BITS (0, 3) | (BITS (5, 7)) << 4; | ||
| 901 | if (shift & 0x40) | ||
| 902 | shift |= 0xc0; | ||
| 903 | |||
| 904 | switch (BITS (20, 21)) { | ||
| 905 | case 0: | ||
| 906 | /* cfsh32 */ | ||
| 907 | printfdbg ("cfsh32 %s amount=%d\n", | ||
| 908 | shift < 0 ? "right" : "left", shift); | ||
| 909 | if (shift < 0) | ||
| 910 | /* Negative shift is a right shift. */ | ||
| 911 | DSPregs[DEST_REG].lower.i = | ||
| 912 | DSPregs[SRC1_REG].lower.i >> -shift; | ||
| 913 | else | ||
| 914 | /* Positive shift is a left shift. */ | ||
| 915 | DSPregs[DEST_REG].lower.i = | ||
| 916 | DSPregs[SRC1_REG].lower.i << shift; | ||
| 917 | break; | ||
| 918 | |||
| 919 | case 1: | ||
| 920 | switch (opcode2) { | ||
| 921 | case 0: /* cfmul32 */ | ||
| 922 | DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i | ||
| 923 | * DSPregs[SRC2_REG].lower.i; | ||
| 924 | printfdbg ("cfmul32 mvfx%d = mvfx%d * mvfx%d = %d\n", | ||
| 925 | DEST_REG, SRC1_REG, SRC2_REG, | ||
| 926 | DSPregs[DEST_REG].lower.i); | ||
| 927 | break; | ||
| 928 | |||
| 929 | case 1: /* cfmul64 */ | ||
| 930 | mv_setReg64int (DEST_REG, mv_getReg64int (SRC1_REG) | ||
| 931 | * mv_getReg64int (SRC2_REG)); | ||
| 932 | printfdbg | ||
| 933 | ("cfmul64 mvdx%d = mvdx%d * mvdx%d = %lld\n", | ||
| 934 | DEST_REG, SRC1_REG, SRC2_REG, | ||
| 935 | mv_getReg64int (DEST_REG)); | ||
| 936 | break; | ||
| 937 | |||
| 938 | case 2: /* cfmac32 */ | ||
| 939 | DSPregs[DEST_REG].lower.i | ||
| 940 | += | ||
| 941 | DSPregs[SRC1_REG].lower.i * | ||
| 942 | DSPregs[SRC2_REG].lower.i; | ||
| 943 | printfdbg ("cfmac32 mvfx%d += mvfx%d * mvfx%d = %d\n", | ||
| 944 | DEST_REG, SRC1_REG, SRC2_REG, | ||
| 945 | DSPregs[DEST_REG].lower.i); | ||
| 946 | break; | ||
| 947 | |||
| 948 | case 3: /* cfmsc32 */ | ||
| 949 | DSPregs[DEST_REG].lower.i | ||
| 950 | -= | ||
| 951 | DSPregs[SRC1_REG].lower.i * | ||
| 952 | DSPregs[SRC2_REG].lower.i; | ||
| 953 | printfdbg ("cfmsc32 mvfx%d -= mvfx%d * mvfx%d = %d\n", | ||
| 954 | DEST_REG, SRC1_REG, SRC2_REG, | ||
| 955 | DSPregs[DEST_REG].lower.i); | ||
| 956 | break; | ||
| 957 | |||
| 958 | case 4: /* cfcvts32 */ | ||
| 959 | /* fixme: this should round */ | ||
| 960 | DSPregs[DEST_REG].lower.i = | ||
| 961 | (int) DSPregs[SRC1_REG].upper.f; | ||
| 962 | printfdbg ("cfcvts32 mvfx%d = mvf%d = %d\n", DEST_REG, | ||
| 963 | SRC1_REG, DSPregs[DEST_REG].lower.i); | ||
| 964 | break; | ||
| 965 | |||
| 966 | case 5: /* cfcvtd32 */ | ||
| 967 | /* fixme: this should round */ | ||
| 968 | DSPregs[DEST_REG].lower.i = | ||
| 969 | (int) mv_getRegDouble (SRC1_REG); | ||
| 970 | printfdbg ("cfcvtd32 mvdx%d = mvd%d = %d\n", DEST_REG, | ||
| 971 | SRC1_REG, DSPregs[DEST_REG].lower.i); | ||
| 972 | break; | ||
| 973 | |||
| 974 | case 6: /* cftruncs32 */ | ||
| 975 | DSPregs[DEST_REG].lower.i = | ||
| 976 | (int) DSPregs[SRC1_REG].upper.f; | ||
| 977 | printfdbg ("cftruncs32 mvfx%d = mvf%d = %d\n", | ||
| 978 | DEST_REG, SRC1_REG, | ||
| 979 | DSPregs[DEST_REG].lower.i); | ||
| 980 | break; | ||
| 981 | |||
| 982 | case 7: /* cftruncd32 */ | ||
| 983 | DSPregs[DEST_REG].lower.i = | ||
| 984 | (int) mv_getRegDouble (SRC1_REG); | ||
| 985 | printfdbg ("cftruncd32 mvfx%d = mvd%d = %d\n", | ||
| 986 | DEST_REG, SRC1_REG, | ||
| 987 | DSPregs[DEST_REG].lower.i); | ||
| 988 | break; | ||
| 989 | } | ||
| 990 | break; | ||
| 991 | |||
| 992 | case 2: | ||
| 993 | /* cfsh64 */ | ||
| 994 | printfdbg ("cfsh64\n"); | ||
| 995 | |||
| 996 | if (shift < 0) | ||
| 997 | /* Negative shift is a right shift. */ | ||
| 998 | mv_setReg64int (DEST_REG, | ||
| 999 | mv_getReg64int (SRC1_REG) >> -shift); | ||
| 1000 | else | ||
| 1001 | /* Positive shift is a left shift. */ | ||
| 1002 | mv_setReg64int (DEST_REG, | ||
| 1003 | mv_getReg64int (SRC1_REG) << shift); | ||
| 1004 | printfdbg ("\t%llx\n", mv_getReg64int (DEST_REG)); | ||
| 1005 | break; | ||
| 1006 | |||
| 1007 | case 3: | ||
| 1008 | switch (opcode2) { | ||
| 1009 | case 0: /* cfabs32 */ | ||
| 1010 | DSPregs[DEST_REG].lower.i = | ||
| 1011 | (DSPregs[SRC1_REG].lower.i < | ||
| 1012 | 0 ? -DSPregs[SRC1_REG].lower. | ||
| 1013 | i : DSPregs[SRC1_REG].lower.i); | ||
| 1014 | printfdbg ("cfabs32 mvfx%d = |mvfx%d| = %d\n", | ||
| 1015 | DEST_REG, SRC1_REG, SRC2_REG, | ||
| 1016 | DSPregs[DEST_REG].lower.i); | ||
| 1017 | break; | ||
| 1018 | |||
| 1019 | case 1: /* cfabs64 */ | ||
| 1020 | mv_setReg64int (DEST_REG, | ||
| 1021 | (mv_getReg64int (SRC1_REG) < 0 | ||
| 1022 | ? -mv_getReg64int (SRC1_REG) | ||
| 1023 | : mv_getReg64int (SRC1_REG))); | ||
| 1024 | printfdbg ("cfabs64 mvdx%d = |mvdx%d| = %lld\n", | ||
| 1025 | DEST_REG, SRC1_REG, SRC2_REG, | ||
| 1026 | mv_getReg64int (DEST_REG)); | ||
| 1027 | break; | ||
| 1028 | |||
| 1029 | case 2: /* cfneg32 */ | ||
| 1030 | DSPregs[DEST_REG].lower.i = | ||
| 1031 | -DSPregs[SRC1_REG].lower.i; | ||
| 1032 | printfdbg ("cfneg32 mvfx%d = -mvfx%d = %d\n", | ||
| 1033 | DEST_REG, SRC1_REG, SRC2_REG, | ||
| 1034 | DSPregs[DEST_REG].lower.i); | ||
| 1035 | break; | ||
| 1036 | |||
| 1037 | case 3: /* cfneg64 */ | ||
| 1038 | mv_setReg64int (DEST_REG, -mv_getReg64int (SRC1_REG)); | ||
| 1039 | printfdbg ("cfneg64 mvdx%d = -mvdx%d = %lld\n", | ||
| 1040 | DEST_REG, SRC1_REG, SRC2_REG, | ||
| 1041 | mv_getReg64int (DEST_REG)); | ||
| 1042 | break; | ||
| 1043 | |||
| 1044 | case 4: /* cfadd32 */ | ||
| 1045 | DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i | ||
| 1046 | + DSPregs[SRC2_REG].lower.i; | ||
| 1047 | printfdbg ("cfadd32 mvfx%d = mvfx%d + mvfx%d = %d\n", | ||
| 1048 | DEST_REG, SRC1_REG, SRC2_REG, | ||
| 1049 | DSPregs[DEST_REG].lower.i); | ||
| 1050 | break; | ||
| 1051 | |||
| 1052 | case 5: /* cfadd64 */ | ||
| 1053 | mv_setReg64int (DEST_REG, mv_getReg64int (SRC1_REG) | ||
| 1054 | + mv_getReg64int (SRC2_REG)); | ||
| 1055 | printfdbg | ||
| 1056 | ("cfadd64 mvdx%d = mvdx%d + mvdx%d = %lld\n", | ||
| 1057 | DEST_REG, SRC1_REG, SRC2_REG, | ||
| 1058 | mv_getReg64int (DEST_REG)); | ||
| 1059 | break; | ||
| 1060 | |||
| 1061 | case 6: /* cfsub32 */ | ||
| 1062 | DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i | ||
| 1063 | - DSPregs[SRC2_REG].lower.i; | ||
| 1064 | printfdbg ("cfsub32 mvfx%d = mvfx%d - mvfx%d = %d\n", | ||
| 1065 | DEST_REG, SRC1_REG, SRC2_REG, | ||
| 1066 | DSPregs[DEST_REG].lower.i); | ||
| 1067 | break; | ||
| 1068 | |||
| 1069 | case 7: /* cfsub64 */ | ||
| 1070 | mv_setReg64int (DEST_REG, mv_getReg64int (SRC1_REG) | ||
| 1071 | - mv_getReg64int (SRC2_REG)); | ||
| 1072 | printfdbg ("cfsub64 mvdx%d = mvdx%d - mvdx%d = %d\n", | ||
| 1073 | DEST_REG, SRC1_REG, SRC2_REG, | ||
| 1074 | mv_getReg64int (DEST_REG)); | ||
| 1075 | break; | ||
| 1076 | } | ||
| 1077 | break; | ||
| 1078 | |||
| 1079 | default: | ||
| 1080 | fprintf (stderr, "unknown opcode in DSPCDP5 0x%x\n", instr); | ||
| 1081 | cirrus_not_implemented ("unknown"); | ||
| 1082 | break; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | return ARMul_DONE; | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | unsigned | ||
| 1089 | DSPCDP6 (ARMul_State * state, unsigned type, ARMword instr) | ||
| 1090 | { | ||
| 1091 | int opcode2; | ||
| 1092 | |||
| 1093 | opcode2 = BITS (5, 7); | ||
| 1094 | |||
| 1095 | switch (BITS (20, 21)) { | ||
| 1096 | case 0: | ||
| 1097 | /* cfmadd32 */ | ||
| 1098 | cirrus_not_implemented ("cfmadd32"); | ||
| 1099 | break; | ||
| 1100 | |||
| 1101 | case 1: | ||
| 1102 | /* cfmsub32 */ | ||
| 1103 | cirrus_not_implemented ("cfmsub32"); | ||
| 1104 | break; | ||
| 1105 | |||
| 1106 | case 2: | ||
| 1107 | /* cfmadda32 */ | ||
| 1108 | cirrus_not_implemented ("cfmadda32"); | ||
| 1109 | break; | ||
| 1110 | |||
| 1111 | case 3: | ||
| 1112 | /* cfmsuba32 */ | ||
| 1113 | cirrus_not_implemented ("cfmsuba32"); | ||
| 1114 | break; | ||
| 1115 | |||
| 1116 | default: | ||
| 1117 | fprintf (stderr, "unknown opcode in DSPCDP6 0x%x\n", instr); | ||
| 1118 | } | ||
| 1119 | |||
| 1120 | return ARMul_DONE; | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | /* Conversion functions. | ||
| 1124 | |||
| 1125 | 32-bit integers are stored in the LOWER half of a 64-bit physical | ||
| 1126 | register. | ||
| 1127 | |||
| 1128 | Single precision floats are stored in the UPPER half of a 64-bit | ||
| 1129 | physical register. */ | ||
| 1130 | |||
| 1131 | static double | ||
| 1132 | mv_getRegDouble (int regnum) | ||
| 1133 | { | ||
| 1134 | reg_conv.ints[lsw_float_index] = DSPregs[regnum].upper.i; | ||
| 1135 | reg_conv.ints[msw_float_index] = DSPregs[regnum].lower.i; | ||
| 1136 | return reg_conv.d; | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | static void | ||
| 1140 | mv_setRegDouble (int regnum, double val) | ||
| 1141 | { | ||
| 1142 | reg_conv.d = val; | ||
| 1143 | DSPregs[regnum].upper.i = reg_conv.ints[lsw_float_index]; | ||
| 1144 | DSPregs[regnum].lower.i = reg_conv.ints[msw_float_index]; | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | static long long | ||
| 1148 | mv_getReg64int (int regnum) | ||
| 1149 | { | ||
| 1150 | reg_conv.ints[lsw_int_index] = DSPregs[regnum].lower.i; | ||
| 1151 | reg_conv.ints[msw_int_index] = DSPregs[regnum].upper.i; | ||
| 1152 | return reg_conv.ll; | ||
| 1153 | } | ||
| 1154 | |||
| 1155 | static void | ||
| 1156 | mv_setReg64int (int regnum, long long val) | ||
| 1157 | { | ||
| 1158 | reg_conv.ll = val; | ||
| 1159 | DSPregs[regnum].lower.i = reg_conv.ints[lsw_int_index]; | ||
| 1160 | DSPregs[regnum].upper.i = reg_conv.ints[msw_int_index]; | ||
| 1161 | } | ||
| 1162 | |||
| 1163 | /* Compute LSW in a double and a long long. */ | ||
| 1164 | |||
| 1165 | void | ||
| 1166 | mv_compute_host_endianness (ARMul_State * state) | ||
| 1167 | { | ||
| 1168 | static union | ||
| 1169 | { | ||
| 1170 | long long ll; | ||
| 1171 | int ints[2]; | ||
| 1172 | int i; | ||
| 1173 | double d; | ||
| 1174 | float floats[2]; | ||
| 1175 | float f; | ||
| 1176 | } conv; | ||
| 1177 | |||
| 1178 | /* Calculate where's the LSW in a 64bit int. */ | ||
| 1179 | conv.ll = 45; | ||
| 1180 | |||
| 1181 | if (conv.ints[0] == 0) { | ||
| 1182 | msw_int_index = 0; | ||
| 1183 | lsw_int_index = 1; | ||
| 1184 | } | ||
| 1185 | else { | ||
| 1186 | assert (conv.ints[1] == 0); | ||
| 1187 | msw_int_index = 1; | ||
| 1188 | lsw_int_index = 0; | ||
| 1189 | } | ||
| 1190 | |||
| 1191 | /* Calculate where's the LSW in a double. */ | ||
| 1192 | conv.d = 3.0; | ||
| 1193 | |||
| 1194 | if (conv.ints[0] == 0) { | ||
| 1195 | msw_float_index = 0; | ||
| 1196 | lsw_float_index = 1; | ||
| 1197 | } | ||
| 1198 | else { | ||
| 1199 | assert (conv.ints[1] == 0); | ||
| 1200 | msw_float_index = 1; | ||
| 1201 | lsw_float_index = 0; | ||
| 1202 | } | ||
| 1203 | |||
| 1204 | printfdbg ("lsw_int_index %d\n", lsw_int_index); | ||
| 1205 | printfdbg ("lsw_float_index %d\n", lsw_float_index); | ||
| 1206 | } | ||
diff --git a/src/core/arm/interpreter/mmu/rb.cpp b/src/core/arm/interpreter/mmu/rb.cpp deleted file mode 100644 index 600c9d8c8..000000000 --- a/src/core/arm/interpreter/mmu/rb.cpp +++ /dev/null | |||
| @@ -1,126 +0,0 @@ | |||
| 1 | #include "core/arm/skyeye_common/armdefs.h" | ||
| 2 | |||
| 3 | /*chy 2004-06-06, fix bug found by wenye@cs.ucsb.edu*/ | ||
| 4 | ARMword rb_masks[] = { | ||
| 5 | 0x0, //RB_INVALID | ||
| 6 | 4, //RB_1 | ||
| 7 | 16, //RB_4 | ||
| 8 | 32, //RB_8 | ||
| 9 | }; | ||
| 10 | |||
| 11 | /*mmu_rb_init | ||
| 12 | * @rb_t :rb_t to init | ||
| 13 | * @num :number of entry | ||
| 14 | * */ | ||
| 15 | int | ||
| 16 | mmu_rb_init (rb_s * rb_t, int num) | ||
| 17 | { | ||
| 18 | int i; | ||
| 19 | rb_entry_t *entrys; | ||
| 20 | |||
| 21 | entrys = (rb_entry_t *) malloc (sizeof (*entrys) * num); | ||
| 22 | if (entrys == NULL) { | ||
| 23 | printf ("SKYEYE:mmu_rb_init malloc error\n"); | ||
| 24 | return -1; | ||
| 25 | } | ||
| 26 | for (i = 0; i < num; i++) { | ||
| 27 | entrys[i].type = RB_INVALID; | ||
| 28 | entrys[i].fault = NO_FAULT; | ||
| 29 | } | ||
| 30 | |||
| 31 | rb_t->entrys = entrys; | ||
| 32 | rb_t->num = num; | ||
| 33 | return 0; | ||
| 34 | } | ||
| 35 | |||
| 36 | /*mmu_rb_exit*/ | ||
| 37 | void | ||
| 38 | mmu_rb_exit (rb_s * rb_t) | ||
| 39 | { | ||
| 40 | free (rb_t->entrys); | ||
| 41 | }; | ||
| 42 | |||
| 43 | /*mmu_rb_search | ||
| 44 | * @rb_t :rb_t to serach | ||
| 45 | * @va :va address to math | ||
| 46 | * | ||
| 47 | * $ NULL :not match | ||
| 48 | * NO-NULL: | ||
| 49 | * */ | ||
| 50 | rb_entry_t * | ||
| 51 | mmu_rb_search (rb_s * rb_t, ARMword va) | ||
| 52 | { | ||
| 53 | int i; | ||
| 54 | rb_entry_t *rb = rb_t->entrys; | ||
| 55 | |||
| 56 | DEBUG_LOG(ARM11, "va = %x\n", va); | ||
| 57 | for (i = 0; i < rb_t->num; i++, rb++) { | ||
| 58 | //2004-06-06 lyh bug from wenye@cs.ucsb.edu | ||
| 59 | if (rb->type) { | ||
| 60 | if ((va >= rb->va) | ||
| 61 | && (va < (rb->va + rb_masks[rb->type]))) | ||
| 62 | return rb; | ||
| 63 | } | ||
| 64 | } | ||
| 65 | return NULL; | ||
| 66 | }; | ||
| 67 | |||
| 68 | void | ||
| 69 | mmu_rb_invalidate_entry (rb_s * rb_t, int i) | ||
| 70 | { | ||
| 71 | rb_t->entrys[i].type = RB_INVALID; | ||
| 72 | } | ||
| 73 | |||
| 74 | void | ||
| 75 | mmu_rb_invalidate_all (rb_s * rb_t) | ||
| 76 | { | ||
| 77 | int i; | ||
| 78 | |||
| 79 | for (i = 0; i < rb_t->num; i++) | ||
| 80 | mmu_rb_invalidate_entry (rb_t, i); | ||
| 81 | }; | ||
| 82 | |||
| 83 | void | ||
| 84 | mmu_rb_load (ARMul_State * state, rb_s * rb_t, int i_rb, int type, ARMword va) | ||
| 85 | { | ||
| 86 | rb_entry_t *rb; | ||
| 87 | int i; | ||
| 88 | ARMword max_start, min_end; | ||
| 89 | fault_t fault; | ||
| 90 | tlb_entry_t *tlb; | ||
| 91 | |||
| 92 | /*align va according to type */ | ||
| 93 | va &= ~(rb_masks[type] - 1); | ||
| 94 | /*invalidate all RB match [va, va + rb_masks[type]] */ | ||
| 95 | for (rb = rb_t->entrys, i = 0; i < rb_t->num; i++, rb++) { | ||
| 96 | if (rb->type) { | ||
| 97 | max_start = max (va, rb->va); | ||
| 98 | min_end = | ||
| 99 | min (va + rb_masks[type], | ||
| 100 | rb->va + rb_masks[rb->type]); | ||
| 101 | if (max_start < min_end) | ||
| 102 | rb->type = RB_INVALID; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | /*load word */ | ||
| 106 | rb = &rb_t->entrys[i_rb]; | ||
| 107 | rb->type = type; | ||
| 108 | fault = translate (state, va, D_TLB (), &tlb); | ||
| 109 | if (fault) { | ||
| 110 | rb->fault = fault; | ||
| 111 | return; | ||
| 112 | } | ||
| 113 | fault = check_access (state, va, tlb, 1); | ||
| 114 | if (fault) { | ||
| 115 | rb->fault = fault; | ||
| 116 | return; | ||
| 117 | } | ||
| 118 | |||
| 119 | rb->fault = NO_FAULT; | ||
| 120 | va = tlb_va_to_pa (tlb, va); | ||
| 121 | //2004-06-06 lyh bug from wenye@cs.ucsb.edu | ||
| 122 | for (i = 0; i < (rb_masks[type] / 4); i++, va += WORD_SIZE) { | ||
| 123 | //rb->data[i] = mem_read_word (state, va); | ||
| 124 | bus_read(32, va, &rb->data[i]); | ||
| 125 | }; | ||
| 126 | } | ||
diff --git a/src/core/arm/interpreter/mmu/rb.h b/src/core/arm/interpreter/mmu/rb.h deleted file mode 100644 index 7bf0ebb26..000000000 --- a/src/core/arm/interpreter/mmu/rb.h +++ /dev/null | |||
| @@ -1,55 +0,0 @@ | |||
| 1 | #ifndef _MMU_RB_H | ||
| 2 | #define _MMU_RB_H | ||
| 3 | |||
| 4 | enum rb_type_t | ||
| 5 | { | ||
| 6 | RB_INVALID = 0, //invalid | ||
| 7 | RB_1, //1 word | ||
| 8 | RB_4, //4 word | ||
| 9 | RB_8, //8 word | ||
| 10 | }; | ||
| 11 | |||
| 12 | /*bytes of each rb_type*/ | ||
| 13 | extern ARMword rb_masks[]; | ||
| 14 | |||
| 15 | #define RB_WORD_NUM 8 | ||
| 16 | typedef struct rb_entry_s | ||
| 17 | { | ||
| 18 | ARMword data[RB_WORD_NUM]; //array to store data | ||
| 19 | ARMword va; //first word va | ||
| 20 | int type; //rb type | ||
| 21 | fault_t fault; //fault set by rb alloc | ||
| 22 | } rb_entry_t; | ||
| 23 | |||
| 24 | typedef struct rb_s | ||
| 25 | { | ||
| 26 | int num; | ||
| 27 | rb_entry_t *entrys; | ||
| 28 | } rb_s; | ||
| 29 | |||
| 30 | /*mmu_rb_init | ||
| 31 | * @rb_t :rb_t to init | ||
| 32 | * @num :number of entry | ||
| 33 | * */ | ||
| 34 | int mmu_rb_init (rb_s * rb_t, int num); | ||
| 35 | |||
| 36 | /*mmu_rb_exit*/ | ||
| 37 | void mmu_rb_exit (rb_s * rb_t); | ||
| 38 | |||
| 39 | |||
| 40 | /*mmu_rb_search | ||
| 41 | * @rb_t :rb_t to serach | ||
| 42 | * @va :va address to math | ||
| 43 | * | ||
| 44 | * $ NULL :not match | ||
| 45 | * NO-NULL: | ||
| 46 | * */ | ||
| 47 | rb_entry_t *mmu_rb_search (rb_s * rb_t, ARMword va); | ||
| 48 | |||
| 49 | |||
| 50 | void mmu_rb_invalidate_entry (rb_s * rb_t, int i); | ||
| 51 | void mmu_rb_invalidate_all (rb_s * rb_t); | ||
| 52 | void mmu_rb_load (ARMul_State * state, rb_s * rb_t, int i_rb, | ||
| 53 | int type, ARMword va); | ||
| 54 | |||
| 55 | #endif /*_MMU_RB_H_*/ | ||
diff --git a/src/core/arm/interpreter/mmu/sa_mmu.cpp b/src/core/arm/interpreter/mmu/sa_mmu.cpp deleted file mode 100644 index 27f9ec8e0..000000000 --- a/src/core/arm/interpreter/mmu/sa_mmu.cpp +++ /dev/null | |||
| @@ -1,864 +0,0 @@ | |||
| 1 | /* | ||
| 2 | armmmu.c - Memory Management Unit emulation. | ||
| 3 | ARMulator extensions for the ARM7100 family. | ||
| 4 | Copyright (C) 1999 Ben Williamson | ||
| 5 | |||
| 6 | This program is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 2 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | This program is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with this program; if not, write to the Free Software | ||
| 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <assert.h> | ||
| 22 | #include <string.h> | ||
| 23 | |||
| 24 | #include "core/arm/skyeye_common/armdefs.h" | ||
| 25 | |||
| 26 | /** | ||
| 27 | * The interface of read data from bus | ||
| 28 | */ | ||
| 29 | int bus_read(short size, int addr, uint32_t * value) { | ||
| 30 | ERROR_LOG(ARM11, "unimplemented bus_read"); | ||
| 31 | return 0; | ||
| 32 | } | ||
| 33 | |||
| 34 | /** | ||
| 35 | * The interface of write data from bus | ||
| 36 | */ | ||
| 37 | int bus_write(short size, int addr, uint32_t value) { | ||
| 38 | ERROR_LOG(ARM11, "unimplemented bus_write"); | ||
| 39 | return 0; | ||
| 40 | } | ||
| 41 | |||
| 42 | |||
| 43 | typedef struct sa_mmu_desc_s | ||
| 44 | { | ||
| 45 | int i_tlb; | ||
| 46 | cache_desc_t i_cache; | ||
| 47 | |||
| 48 | int d_tlb; | ||
| 49 | cache_desc_t main_d_cache; | ||
| 50 | cache_desc_t mini_d_cache; | ||
| 51 | int rb; | ||
| 52 | wb_desc_t wb; | ||
| 53 | } sa_mmu_desc_t; | ||
| 54 | |||
| 55 | static sa_mmu_desc_t sa11xx_mmu_desc = { | ||
| 56 | 32, | ||
| 57 | {32, 32, 16, CACHE_WRITE_BACK}, | ||
| 58 | |||
| 59 | 32, | ||
| 60 | {32, 32, 8, CACHE_WRITE_BACK}, | ||
| 61 | {32, 2, 8, CACHE_WRITE_BACK}, | ||
| 62 | 4, | ||
| 63 | //{8, 4}, for word size | ||
| 64 | {8, 16}, //for byte size, chy 2003-07-11 | ||
| 65 | }; | ||
| 66 | |||
| 67 | static fault_t sa_mmu_write (ARMul_State * state, ARMword va, ARMword data, | ||
| 68 | ARMword datatype); | ||
| 69 | static fault_t sa_mmu_read (ARMul_State * state, ARMword va, ARMword * data, | ||
| 70 | ARMword datatype); | ||
| 71 | static fault_t update_cache (ARMul_State * state, ARMword va, ARMword data, | ||
| 72 | ARMword datatype, cache_line_t * cache, | ||
| 73 | cache_s * cache_t, ARMword real_va); | ||
| 74 | |||
| 75 | void | ||
| 76 | mmu_wb_write_bytes (ARMul_State * state, wb_s * wb_t, ARMword pa, | ||
| 77 | ARMbyte * data, int n); | ||
| 78 | int | ||
| 79 | sa_mmu_init (ARMul_State * state) | ||
| 80 | { | ||
| 81 | sa_mmu_desc_t *desc; | ||
| 82 | cache_desc_t *c_desc; | ||
| 83 | |||
| 84 | state->mmu.control = 0x70; | ||
| 85 | state->mmu.translation_table_base = 0xDEADC0DE; | ||
| 86 | state->mmu.domain_access_control = 0xDEADC0DE; | ||
| 87 | state->mmu.fault_status = 0; | ||
| 88 | state->mmu.fault_address = 0; | ||
| 89 | state->mmu.process_id = 0; | ||
| 90 | |||
| 91 | desc = &sa11xx_mmu_desc; | ||
| 92 | if (mmu_tlb_init (I_TLB (), desc->i_tlb)) { | ||
| 93 | ERROR_LOG(ARM11, "i_tlb init %d\n", -1); | ||
| 94 | goto i_tlb_init_error; | ||
| 95 | } | ||
| 96 | |||
| 97 | c_desc = &desc->i_cache; | ||
| 98 | if (mmu_cache_init (I_CACHE (), c_desc->width, c_desc->way, | ||
| 99 | c_desc->set, c_desc->w_mode)) { | ||
| 100 | ERROR_LOG(ARM11, "i_cache init %d\n", -1); | ||
| 101 | goto i_cache_init_error; | ||
| 102 | } | ||
| 103 | |||
| 104 | if (mmu_tlb_init (D_TLB (), desc->d_tlb)) { | ||
| 105 | ERROR_LOG(ARM11, "d_tlb init %d\n", -1); | ||
| 106 | goto d_tlb_init_error; | ||
| 107 | } | ||
| 108 | |||
| 109 | c_desc = &desc->main_d_cache; | ||
| 110 | if (mmu_cache_init (MAIN_D_CACHE (), c_desc->width, c_desc->way, | ||
| 111 | c_desc->set, c_desc->w_mode)) { | ||
| 112 | ERROR_LOG(ARM11, "main_d_cache init %d\n", -1); | ||
| 113 | goto main_d_cache_init_error; | ||
| 114 | } | ||
| 115 | |||
| 116 | c_desc = &desc->mini_d_cache; | ||
| 117 | if (mmu_cache_init (MINI_D_CACHE (), c_desc->width, c_desc->way, | ||
| 118 | c_desc->set, c_desc->w_mode)) { | ||
| 119 | ERROR_LOG(ARM11, "mini_d_cache init %d\n", -1); | ||
| 120 | goto mini_d_cache_init_error; | ||
| 121 | } | ||
| 122 | |||
| 123 | if (mmu_wb_init (WB (), desc->wb.num, desc->wb.nb)) { | ||
| 124 | ERROR_LOG(ARM11, "wb init %d\n", -1); | ||
| 125 | goto wb_init_error; | ||
| 126 | } | ||
| 127 | |||
| 128 | if (mmu_rb_init (RB (), desc->rb)) { | ||
| 129 | ERROR_LOG(ARM11, "rb init %d\n", -1); | ||
| 130 | goto rb_init_error; | ||
| 131 | } | ||
| 132 | return 0; | ||
| 133 | |||
| 134 | rb_init_error: | ||
| 135 | mmu_wb_exit (WB ()); | ||
| 136 | wb_init_error: | ||
| 137 | mmu_cache_exit (MINI_D_CACHE ()); | ||
| 138 | mini_d_cache_init_error: | ||
| 139 | mmu_cache_exit (MAIN_D_CACHE ()); | ||
| 140 | main_d_cache_init_error: | ||
| 141 | mmu_tlb_exit (D_TLB ()); | ||
| 142 | d_tlb_init_error: | ||
| 143 | mmu_cache_exit (I_CACHE ()); | ||
| 144 | i_cache_init_error: | ||
| 145 | mmu_tlb_exit (I_TLB ()); | ||
| 146 | i_tlb_init_error: | ||
| 147 | return -1; | ||
| 148 | } | ||
| 149 | |||
| 150 | void | ||
| 151 | sa_mmu_exit (ARMul_State * state) | ||
| 152 | { | ||
| 153 | mmu_rb_exit (RB ()); | ||
| 154 | mmu_wb_exit (WB ()); | ||
| 155 | mmu_cache_exit (MINI_D_CACHE ()); | ||
| 156 | mmu_cache_exit (MAIN_D_CACHE ()); | ||
| 157 | mmu_tlb_exit (D_TLB ()); | ||
| 158 | mmu_cache_exit (I_CACHE ()); | ||
| 159 | mmu_tlb_exit (I_TLB ()); | ||
| 160 | }; | ||
| 161 | |||
| 162 | |||
| 163 | static fault_t | ||
| 164 | sa_mmu_load_instr (ARMul_State * state, ARMword va, ARMword * instr) | ||
| 165 | { | ||
| 166 | fault_t fault; | ||
| 167 | tlb_entry_t *tlb; | ||
| 168 | cache_line_t *cache; | ||
| 169 | int c; //cache bit | ||
| 170 | ARMword pa; //physical addr | ||
| 171 | |||
| 172 | static int debug_count = 0; //used for debug | ||
| 173 | |||
| 174 | DEBUG_LOG(ARM11, "va = %x\n", va); | ||
| 175 | |||
| 176 | va = mmu_pid_va_map (va); | ||
| 177 | if (MMU_Enabled) { | ||
| 178 | /*align check */ | ||
| 179 | if ((va & (WORD_SIZE - 1)) && MMU_Aligned) { | ||
| 180 | DEBUG_LOG(ARM11, "align\n"); | ||
| 181 | return ALIGNMENT_FAULT; | ||
| 182 | } | ||
| 183 | else | ||
| 184 | va &= ~(WORD_SIZE - 1); | ||
| 185 | |||
| 186 | /*translate tlb */ | ||
| 187 | fault = translate (state, va, I_TLB (), &tlb); | ||
| 188 | if (fault) { | ||
| 189 | DEBUG_LOG(ARM11, "translate\n"); | ||
| 190 | return fault; | ||
| 191 | } | ||
| 192 | |||
| 193 | /*check access */ | ||
| 194 | fault = check_access (state, va, tlb, 1); | ||
| 195 | if (fault) { | ||
| 196 | DEBUG_LOG(ARM11, "check_fault\n"); | ||
| 197 | return fault; | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | /*search cache no matter MMU enabled/disabled */ | ||
| 202 | cache = mmu_cache_search (state, I_CACHE (), va); | ||
| 203 | if (cache) { | ||
| 204 | *instr = cache->data[va_cache_index (va, I_CACHE ())]; | ||
| 205 | return NO_FAULT; | ||
| 206 | } | ||
| 207 | |||
| 208 | /*if MMU disabled or C flag is set alloc cache */ | ||
| 209 | if (MMU_Disabled) { | ||
| 210 | c = 1; | ||
| 211 | pa = va; | ||
| 212 | } | ||
| 213 | else { | ||
| 214 | c = tlb_c_flag (tlb); | ||
| 215 | pa = tlb_va_to_pa (tlb, va); | ||
| 216 | } | ||
| 217 | |||
| 218 | if (c) { | ||
| 219 | int index; | ||
| 220 | |||
| 221 | debug_count++; | ||
| 222 | cache = mmu_cache_alloc (state, I_CACHE (), va, pa); | ||
| 223 | index = va_cache_index (va, I_CACHE ()); | ||
| 224 | *instr = cache->data[va_cache_index (va, I_CACHE ())]; | ||
| 225 | } | ||
| 226 | else | ||
| 227 | //*instr = mem_read_word (state, pa); | ||
| 228 | bus_read(32, pa, instr); | ||
| 229 | |||
| 230 | return NO_FAULT; | ||
| 231 | }; | ||
| 232 | |||
| 233 | |||
| 234 | |||
| 235 | static fault_t | ||
| 236 | sa_mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data) | ||
| 237 | { | ||
| 238 | //ARMword temp,offset; | ||
| 239 | fault_t fault; | ||
| 240 | fault = sa_mmu_read (state, virt_addr, data, ARM_BYTE_TYPE); | ||
| 241 | return fault; | ||
| 242 | } | ||
| 243 | |||
| 244 | static fault_t | ||
| 245 | sa_mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data) | ||
| 246 | { | ||
| 247 | //ARMword temp,offset; | ||
| 248 | fault_t fault; | ||
| 249 | fault = sa_mmu_read (state, virt_addr, data, ARM_HALFWORD_TYPE); | ||
| 250 | return fault; | ||
| 251 | } | ||
| 252 | |||
| 253 | static fault_t | ||
| 254 | sa_mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data) | ||
| 255 | { | ||
| 256 | return sa_mmu_read (state, virt_addr, data, ARM_WORD_TYPE); | ||
| 257 | } | ||
| 258 | |||
| 259 | |||
| 260 | |||
| 261 | |||
| 262 | static fault_t | ||
| 263 | sa_mmu_read (ARMul_State * state, ARMword va, ARMword * data, | ||
| 264 | ARMword datatype) | ||
| 265 | { | ||
| 266 | fault_t fault; | ||
| 267 | rb_entry_t *rb; | ||
| 268 | tlb_entry_t *tlb; | ||
| 269 | cache_line_t *cache; | ||
| 270 | ARMword pa, real_va, temp, offset; | ||
| 271 | |||
| 272 | DEBUG_LOG(ARM11, "va = %x\n", va); | ||
| 273 | |||
| 274 | va = mmu_pid_va_map (va); | ||
| 275 | real_va = va; | ||
| 276 | /*if MMU disabled, memory_read */ | ||
| 277 | if (MMU_Disabled) { | ||
| 278 | //*data = mem_read_word(state, va); | ||
| 279 | if (datatype == ARM_BYTE_TYPE) | ||
| 280 | //*data = mem_read_byte (state, va); | ||
| 281 | bus_read(8, va, data); | ||
| 282 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 283 | //*data = mem_read_halfword (state, va); | ||
| 284 | bus_read(16, va, data); | ||
| 285 | else if (datatype == ARM_WORD_TYPE) | ||
| 286 | //*data = mem_read_word (state, va); | ||
| 287 | bus_read(32, va, data); | ||
| 288 | else { | ||
| 289 | printf ("SKYEYE:1 sa_mmu_read error: unknown data type %d\n", datatype); | ||
| 290 | // skyeye_exit (-1); | ||
| 291 | } | ||
| 292 | |||
| 293 | return NO_FAULT; | ||
| 294 | } | ||
| 295 | |||
| 296 | /*align check */ | ||
| 297 | if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) || | ||
| 298 | ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) { | ||
| 299 | DEBUG_LOG(ARM11, "align\n"); | ||
| 300 | return ALIGNMENT_FAULT; | ||
| 301 | } // else | ||
| 302 | |||
| 303 | va &= ~(WORD_SIZE - 1); | ||
| 304 | |||
| 305 | /*translate va to tlb */ | ||
| 306 | fault = translate (state, va, D_TLB (), &tlb); | ||
| 307 | if (fault) { | ||
| 308 | DEBUG_LOG(ARM11, "translate\n"); | ||
| 309 | return fault; | ||
| 310 | } | ||
| 311 | /*check access permission */ | ||
| 312 | fault = check_access (state, va, tlb, 1); | ||
| 313 | if (fault) | ||
| 314 | return fault; | ||
| 315 | /*search in read buffer */ | ||
| 316 | rb = mmu_rb_search (RB (), va); | ||
| 317 | if (rb) { | ||
| 318 | if (rb->fault) | ||
| 319 | return rb->fault; | ||
| 320 | *data = rb->data[(va & (rb_masks[rb->type] - 1)) >> WORD_SHT]; | ||
| 321 | goto datatrans; | ||
| 322 | //return 0; | ||
| 323 | }; | ||
| 324 | /*search main cache */ | ||
| 325 | cache = mmu_cache_search (state, MAIN_D_CACHE (), va); | ||
| 326 | if (cache) { | ||
| 327 | *data = cache->data[va_cache_index (va, MAIN_D_CACHE ())]; | ||
| 328 | goto datatrans; | ||
| 329 | //return 0; | ||
| 330 | } | ||
| 331 | /*search mini cache */ | ||
| 332 | cache = mmu_cache_search (state, MINI_D_CACHE (), va); | ||
| 333 | if (cache) { | ||
| 334 | *data = cache->data[va_cache_index (va, MINI_D_CACHE ())]; | ||
| 335 | goto datatrans; | ||
| 336 | //return 0; | ||
| 337 | } | ||
| 338 | |||
| 339 | /*get phy_addr */ | ||
| 340 | pa = tlb_va_to_pa (tlb, va); | ||
| 341 | if ((pa >= 0xe0000000) && (pa < 0xe8000000)) { | ||
| 342 | if (tlb_c_flag (tlb)) { | ||
| 343 | if (tlb_b_flag (tlb)) { | ||
| 344 | mmu_cache_soft_flush (state, MAIN_D_CACHE (), | ||
| 345 | pa); | ||
| 346 | } | ||
| 347 | else { | ||
| 348 | mmu_cache_soft_flush (state, MINI_D_CACHE (), | ||
| 349 | pa); | ||
| 350 | } | ||
| 351 | } | ||
| 352 | return NO_FAULT; | ||
| 353 | } | ||
| 354 | |||
| 355 | /*if Buffer, drain Write Buffer first */ | ||
| 356 | if (tlb_b_flag (tlb)) | ||
| 357 | mmu_wb_drain_all (state, WB ()); | ||
| 358 | |||
| 359 | /*alloc cache or mem_read */ | ||
| 360 | if (tlb_c_flag (tlb) && MMU_DCacheEnabled) { | ||
| 361 | cache_s *cache_t; | ||
| 362 | |||
| 363 | if (tlb_b_flag (tlb)) | ||
| 364 | cache_t = MAIN_D_CACHE (); | ||
| 365 | else | ||
| 366 | cache_t = MINI_D_CACHE (); | ||
| 367 | cache = mmu_cache_alloc (state, cache_t, va, pa); | ||
| 368 | *data = cache->data[va_cache_index (va, cache_t)]; | ||
| 369 | } | ||
| 370 | else { | ||
| 371 | //*data = mem_read_word(state, pa); | ||
| 372 | if (datatype == ARM_BYTE_TYPE) | ||
| 373 | //*data = mem_read_byte (state, pa | (real_va & 3)); | ||
| 374 | bus_read(8, pa | (real_va & 3), data); | ||
| 375 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 376 | //*data = mem_read_halfword (state, pa | (real_va & 2)); | ||
| 377 | bus_read(16, pa | (real_va & 2), data); | ||
| 378 | else if (datatype == ARM_WORD_TYPE) | ||
| 379 | //*data = mem_read_word (state, pa); | ||
| 380 | bus_read(32, pa, data); | ||
| 381 | else { | ||
| 382 | printf ("SKYEYE:2 sa_mmu_read error: unknown data type %d\n", datatype); | ||
| 383 | // skyeye_exit (-1); | ||
| 384 | } | ||
| 385 | return NO_FAULT; | ||
| 386 | } | ||
| 387 | |||
| 388 | |||
| 389 | datatrans: | ||
| 390 | if (datatype == ARM_HALFWORD_TYPE) { | ||
| 391 | temp = *data; | ||
| 392 | offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */ | ||
| 393 | *data = (temp >> offset) & 0xffff; | ||
| 394 | } | ||
| 395 | else if (datatype == ARM_BYTE_TYPE) { | ||
| 396 | temp = *data; | ||
| 397 | offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */ | ||
| 398 | *data = (temp >> offset & 0xffL); | ||
| 399 | } | ||
| 400 | end: | ||
| 401 | return NO_FAULT; | ||
| 402 | } | ||
| 403 | |||
| 404 | |||
| 405 | static fault_t | ||
| 406 | sa_mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data) | ||
| 407 | { | ||
| 408 | return sa_mmu_write (state, virt_addr, data, ARM_BYTE_TYPE); | ||
| 409 | } | ||
| 410 | |||
| 411 | static fault_t | ||
| 412 | sa_mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data) | ||
| 413 | { | ||
| 414 | return sa_mmu_write (state, virt_addr, data, ARM_HALFWORD_TYPE); | ||
| 415 | } | ||
| 416 | |||
| 417 | static fault_t | ||
| 418 | sa_mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data) | ||
| 419 | { | ||
| 420 | return sa_mmu_write (state, virt_addr, data, ARM_WORD_TYPE); | ||
| 421 | } | ||
| 422 | |||
| 423 | |||
| 424 | |||
| 425 | static fault_t | ||
| 426 | sa_mmu_write (ARMul_State * state, ARMword va, ARMword data, ARMword datatype) | ||
| 427 | { | ||
| 428 | tlb_entry_t *tlb; | ||
| 429 | cache_line_t *cache; | ||
| 430 | int b; | ||
| 431 | ARMword pa, real_va; | ||
| 432 | fault_t fault; | ||
| 433 | |||
| 434 | DEBUG_LOG(ARM11, "va = %x, val = %x\n", va, data); | ||
| 435 | va = mmu_pid_va_map (va); | ||
| 436 | real_va = va; | ||
| 437 | |||
| 438 | /*search instruction cache */ | ||
| 439 | cache = mmu_cache_search (state, I_CACHE (), va); | ||
| 440 | if (cache) { | ||
| 441 | update_cache (state, va, data, datatype, cache, I_CACHE (), | ||
| 442 | real_va); | ||
| 443 | } | ||
| 444 | |||
| 445 | if (MMU_Disabled) { | ||
| 446 | //mem_write_word(state, va, data); | ||
| 447 | if (datatype == ARM_BYTE_TYPE) | ||
| 448 | //mem_write_byte (state, va, data); | ||
| 449 | bus_write(8, va, data); | ||
| 450 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 451 | //mem_write_halfword (state, va, data); | ||
| 452 | bus_write(16, va, data); | ||
| 453 | else if (datatype == ARM_WORD_TYPE) | ||
| 454 | //mem_write_word (state, va, data); | ||
| 455 | bus_write(32, va, data); | ||
| 456 | else { | ||
| 457 | printf ("SKYEYE:1 sa_mmu_write error: unknown data type %d\n", datatype); | ||
| 458 | // skyeye_exit (-1); | ||
| 459 | } | ||
| 460 | |||
| 461 | return NO_FAULT; | ||
| 462 | } | ||
| 463 | /*align check */ | ||
| 464 | //if ((va & (WORD_SIZE - 1)) && MMU_Aligned){ | ||
| 465 | if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) || | ||
| 466 | ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) { | ||
| 467 | DEBUG_LOG(ARM11, "align\n"); | ||
| 468 | return ALIGNMENT_FAULT; | ||
| 469 | } //else | ||
| 470 | va &= ~(WORD_SIZE - 1); | ||
| 471 | /*tlb translate */ | ||
| 472 | fault = translate (state, va, D_TLB (), &tlb); | ||
| 473 | if (fault) { | ||
| 474 | DEBUG_LOG(ARM11, "translate\n"); | ||
| 475 | return fault; | ||
| 476 | } | ||
| 477 | /*tlb check access */ | ||
| 478 | fault = check_access (state, va, tlb, 0); | ||
| 479 | if (fault) { | ||
| 480 | DEBUG_LOG(ARM11, "check_access\n"); | ||
| 481 | return fault; | ||
| 482 | } | ||
| 483 | /*search main cache */ | ||
| 484 | cache = mmu_cache_search (state, MAIN_D_CACHE (), va); | ||
| 485 | if (cache) { | ||
| 486 | update_cache (state, va, data, datatype, cache, | ||
| 487 | MAIN_D_CACHE (), real_va); | ||
| 488 | } | ||
| 489 | else { | ||
| 490 | /*search mini cache */ | ||
| 491 | cache = mmu_cache_search (state, MINI_D_CACHE (), va); | ||
| 492 | if (cache) { | ||
| 493 | update_cache (state, va, data, datatype, cache, | ||
| 494 | MINI_D_CACHE (), real_va); | ||
| 495 | } | ||
| 496 | } | ||
| 497 | |||
| 498 | if (!cache) { | ||
| 499 | b = tlb_b_flag (tlb); | ||
| 500 | pa = tlb_va_to_pa (tlb, va); | ||
| 501 | if (b) { | ||
| 502 | if (MMU_WBEnabled) { | ||
| 503 | if (datatype == ARM_WORD_TYPE) | ||
| 504 | mmu_wb_write_bytes (state, WB (), pa, | ||
| 505 | (ARMbyte*)&data, 4); | ||
| 506 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 507 | mmu_wb_write_bytes (state, WB (), | ||
| 508 | (pa | | ||
| 509 | (real_va & 2)), | ||
| 510 | (ARMbyte*)&data, 2); | ||
| 511 | else if (datatype == ARM_BYTE_TYPE) | ||
| 512 | mmu_wb_write_bytes (state, WB (), | ||
| 513 | (pa | | ||
| 514 | (real_va & 3)), | ||
| 515 | (ARMbyte*)&data, 1); | ||
| 516 | |||
| 517 | } | ||
| 518 | else { | ||
| 519 | if (datatype == ARM_WORD_TYPE) | ||
| 520 | //mem_write_word (state, pa, data); | ||
| 521 | bus_write(32, pa, data); | ||
| 522 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 523 | /* | ||
| 524 | mem_write_halfword (state, | ||
| 525 | (pa | | ||
| 526 | (real_va & 2)), | ||
| 527 | data); | ||
| 528 | */ | ||
| 529 | bus_write(16, pa | (real_va & 2), data); | ||
| 530 | else if (datatype == ARM_BYTE_TYPE) | ||
| 531 | /* | ||
| 532 | mem_write_byte (state, | ||
| 533 | (pa | (real_va & 3)), | ||
| 534 | data); | ||
| 535 | */ | ||
| 536 | bus_write(8, pa | (real_va & 3), data); | ||
| 537 | } | ||
| 538 | } | ||
| 539 | else { | ||
| 540 | mmu_wb_drain_all (state, WB ()); | ||
| 541 | |||
| 542 | if (datatype == ARM_WORD_TYPE) | ||
| 543 | //mem_write_word (state, pa, data); | ||
| 544 | bus_write(32, pa, data); | ||
| 545 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 546 | /* | ||
| 547 | mem_write_halfword (state, | ||
| 548 | (pa | (real_va & 2)), | ||
| 549 | data); | ||
| 550 | */ | ||
| 551 | bus_write(16, pa | (real_va & 2), data); | ||
| 552 | else if (datatype == ARM_BYTE_TYPE) | ||
| 553 | /* | ||
| 554 | mem_write_byte (state, (pa | (real_va & 3)), | ||
| 555 | data); | ||
| 556 | */ | ||
| 557 | bus_write(8, pa | (real_va & 3), data); | ||
| 558 | } | ||
| 559 | } | ||
| 560 | return NO_FAULT; | ||
| 561 | } | ||
| 562 | |||
| 563 | static fault_t | ||
| 564 | update_cache (ARMul_State * state, ARMword va, ARMword data, ARMword datatype, | ||
| 565 | cache_line_t * cache, cache_s * cache_t, ARMword real_va) | ||
| 566 | { | ||
| 567 | ARMword temp, offset; | ||
| 568 | |||
| 569 | ARMword index = va_cache_index (va, cache_t); | ||
| 570 | |||
| 571 | //cache->data[index] = data; | ||
| 572 | |||
| 573 | if (datatype == ARM_WORD_TYPE) | ||
| 574 | cache->data[index] = data; | ||
| 575 | else if (datatype == ARM_HALFWORD_TYPE) { | ||
| 576 | temp = cache->data[index]; | ||
| 577 | offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */ | ||
| 578 | cache->data[index] = | ||
| 579 | (temp & ~(0xffffL << offset)) | ((data & 0xffffL) << | ||
| 580 | offset); | ||
| 581 | } | ||
| 582 | else if (datatype == ARM_BYTE_TYPE) { | ||
| 583 | temp = cache->data[index]; | ||
| 584 | offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */ | ||
| 585 | cache->data[index] = | ||
| 586 | (temp & ~(0xffL << offset)) | ((data & 0xffL) << | ||
| 587 | offset); | ||
| 588 | } | ||
| 589 | |||
| 590 | if (index < (cache_t->width >> (WORD_SHT + 1))) | ||
| 591 | cache->tag |= TAG_FIRST_HALF_DIRTY; | ||
| 592 | else | ||
| 593 | cache->tag |= TAG_LAST_HALF_DIRTY; | ||
| 594 | |||
| 595 | return NO_FAULT; | ||
| 596 | } | ||
| 597 | |||
| 598 | ARMword | ||
| 599 | sa_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value) | ||
| 600 | { | ||
| 601 | mmu_regnum_t creg = (mmu_regnum_t)(BITS (16, 19) & 15); | ||
| 602 | ARMword data; | ||
| 603 | |||
| 604 | switch (creg) { | ||
| 605 | case MMU_ID: | ||
| 606 | // printf("mmu_mrc read ID "); | ||
| 607 | data = 0x41007100; /* v3 */ | ||
| 608 | data = state->cpu->cpu_val; | ||
| 609 | break; | ||
| 610 | case MMU_CONTROL: | ||
| 611 | // printf("mmu_mrc read CONTROL"); | ||
| 612 | data = state->mmu.control; | ||
| 613 | break; | ||
| 614 | case MMU_TRANSLATION_TABLE_BASE: | ||
| 615 | // printf("mmu_mrc read TTB "); | ||
| 616 | data = state->mmu.translation_table_base; | ||
| 617 | break; | ||
| 618 | case MMU_DOMAIN_ACCESS_CONTROL: | ||
| 619 | // printf("mmu_mrc read DACR "); | ||
| 620 | data = state->mmu.domain_access_control; | ||
| 621 | break; | ||
| 622 | case MMU_FAULT_STATUS: | ||
| 623 | // printf("mmu_mrc read FSR "); | ||
| 624 | data = state->mmu.fault_status; | ||
| 625 | break; | ||
| 626 | case MMU_FAULT_ADDRESS: | ||
| 627 | // printf("mmu_mrc read FAR "); | ||
| 628 | data = state->mmu.fault_address; | ||
| 629 | break; | ||
| 630 | case MMU_PID: | ||
| 631 | data = state->mmu.process_id; | ||
| 632 | default: | ||
| 633 | printf ("mmu_mrc read UNKNOWN - reg %d\n", creg); | ||
| 634 | data = 0; | ||
| 635 | break; | ||
| 636 | } | ||
| 637 | // printf("\t\t\t\t\tpc = 0x%08x\n", state->Reg[15]); | ||
| 638 | *value = data; | ||
| 639 | return data; | ||
| 640 | } | ||
| 641 | |||
| 642 | void | ||
| 643 | sa_mmu_cache_ops (ARMul_State * state, ARMword instr, ARMword value) | ||
| 644 | { | ||
| 645 | int CRm, OPC_2; | ||
| 646 | |||
| 647 | CRm = BITS (0, 3); | ||
| 648 | OPC_2 = BITS (5, 7); | ||
| 649 | |||
| 650 | if (OPC_2 == 0 && CRm == 7) { | ||
| 651 | mmu_cache_invalidate_all (state, I_CACHE ()); | ||
| 652 | mmu_cache_invalidate_all (state, MAIN_D_CACHE ()); | ||
| 653 | mmu_cache_invalidate_all (state, MINI_D_CACHE ()); | ||
| 654 | return; | ||
| 655 | } | ||
| 656 | |||
| 657 | if (OPC_2 == 0 && CRm == 5) { | ||
| 658 | mmu_cache_invalidate_all (state, I_CACHE ()); | ||
| 659 | return; | ||
| 660 | } | ||
| 661 | |||
| 662 | if (OPC_2 == 0 && CRm == 6) { | ||
| 663 | mmu_cache_invalidate_all (state, MAIN_D_CACHE ()); | ||
| 664 | mmu_cache_invalidate_all (state, MINI_D_CACHE ()); | ||
| 665 | return; | ||
| 666 | } | ||
| 667 | |||
| 668 | if (OPC_2 == 1 && CRm == 6) { | ||
| 669 | mmu_cache_invalidate (state, MAIN_D_CACHE (), value); | ||
| 670 | mmu_cache_invalidate (state, MINI_D_CACHE (), value); | ||
| 671 | return; | ||
| 672 | } | ||
| 673 | |||
| 674 | if (OPC_2 == 1 && CRm == 0xa) { | ||
| 675 | mmu_cache_clean (state, MAIN_D_CACHE (), value); | ||
| 676 | mmu_cache_clean (state, MINI_D_CACHE (), value); | ||
| 677 | return; | ||
| 678 | } | ||
| 679 | |||
| 680 | if (OPC_2 == 4 && CRm == 0xa) { | ||
| 681 | mmu_wb_drain_all (state, WB ()); | ||
| 682 | return; | ||
| 683 | } | ||
| 684 | ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm); | ||
| 685 | } | ||
| 686 | |||
| 687 | static void | ||
| 688 | sa_mmu_tlb_ops (ARMul_State * state, ARMword instr, ARMword value) | ||
| 689 | { | ||
| 690 | int CRm, OPC_2; | ||
| 691 | |||
| 692 | CRm = BITS (0, 3); | ||
| 693 | OPC_2 = BITS (5, 7); | ||
| 694 | |||
| 695 | |||
| 696 | if (OPC_2 == 0 && CRm == 0x7) { | ||
| 697 | mmu_tlb_invalidate_all (state, I_TLB ()); | ||
| 698 | mmu_tlb_invalidate_all (state, D_TLB ()); | ||
| 699 | return; | ||
| 700 | } | ||
| 701 | |||
| 702 | if (OPC_2 == 0 && CRm == 0x5) { | ||
| 703 | mmu_tlb_invalidate_all (state, I_TLB ()); | ||
| 704 | return; | ||
| 705 | } | ||
| 706 | |||
| 707 | if (OPC_2 == 0 && CRm == 0x6) { | ||
| 708 | mmu_tlb_invalidate_all (state, D_TLB ()); | ||
| 709 | return; | ||
| 710 | } | ||
| 711 | |||
| 712 | if (OPC_2 == 1 && CRm == 0x6) { | ||
| 713 | mmu_tlb_invalidate_entry (state, D_TLB (), value); | ||
| 714 | return; | ||
| 715 | } | ||
| 716 | |||
| 717 | ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm); | ||
| 718 | } | ||
| 719 | |||
| 720 | static void | ||
| 721 | sa_mmu_rb_ops (ARMul_State * state, ARMword instr, ARMword value) | ||
| 722 | { | ||
| 723 | int CRm, OPC_2; | ||
| 724 | |||
| 725 | CRm = BITS (0, 3); | ||
| 726 | OPC_2 = BITS (5, 7); | ||
| 727 | |||
| 728 | if (OPC_2 == 0x0 && CRm == 0x0) { | ||
| 729 | mmu_rb_invalidate_all (RB ()); | ||
| 730 | return; | ||
| 731 | } | ||
| 732 | |||
| 733 | if (OPC_2 == 0x2) { | ||
| 734 | int idx = CRm & 0x3; | ||
| 735 | int type = ((CRm >> 2) & 0x3) + 1; | ||
| 736 | |||
| 737 | if ((idx < 4) && (type < 4)) | ||
| 738 | mmu_rb_load (state, RB (), idx, type, value); | ||
| 739 | return; | ||
| 740 | } | ||
| 741 | |||
| 742 | if ((OPC_2 == 1) && (CRm < 4)) { | ||
| 743 | mmu_rb_invalidate_entry (RB (), CRm); | ||
| 744 | return; | ||
| 745 | } | ||
| 746 | |||
| 747 | ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm); | ||
| 748 | } | ||
| 749 | |||
| 750 | static ARMword | ||
| 751 | sa_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value) | ||
| 752 | { | ||
| 753 | mmu_regnum_t creg = (mmu_regnum_t)(BITS (16, 19) & 15); | ||
| 754 | if (!strncmp (state->cpu->cpu_arch_name, "armv4", 5)) { | ||
| 755 | switch (creg) { | ||
| 756 | case MMU_CONTROL: | ||
| 757 | // printf("mmu_mcr wrote CONTROL "); | ||
| 758 | state->mmu.control = (value | 0x70) & 0xFFFD; | ||
| 759 | break; | ||
| 760 | case MMU_TRANSLATION_TABLE_BASE: | ||
| 761 | // printf("mmu_mcr wrote TTB "); | ||
| 762 | state->mmu.translation_table_base = | ||
| 763 | value & 0xFFFFC000; | ||
| 764 | break; | ||
| 765 | case MMU_DOMAIN_ACCESS_CONTROL: | ||
| 766 | // printf("mmu_mcr wrote DACR "); | ||
| 767 | state->mmu.domain_access_control = value; | ||
| 768 | break; | ||
| 769 | |||
| 770 | case MMU_FAULT_STATUS: | ||
| 771 | state->mmu.fault_status = value & 0xFF; | ||
| 772 | break; | ||
| 773 | case MMU_FAULT_ADDRESS: | ||
| 774 | state->mmu.fault_address = value; | ||
| 775 | break; | ||
| 776 | |||
| 777 | case MMU_CACHE_OPS: | ||
| 778 | sa_mmu_cache_ops (state, instr, value); | ||
| 779 | break; | ||
| 780 | case MMU_TLB_OPS: | ||
| 781 | sa_mmu_tlb_ops (state, instr, value); | ||
| 782 | break; | ||
| 783 | case MMU_SA_RB_OPS: | ||
| 784 | sa_mmu_rb_ops (state, instr, value); | ||
| 785 | break; | ||
| 786 | case MMU_SA_DEBUG: | ||
| 787 | break; | ||
| 788 | case MMU_SA_CP15_R15: | ||
| 789 | break; | ||
| 790 | case MMU_PID: | ||
| 791 | //2004-06-06 lyh, bug provided by wen ye wenye@cs.ucsb.edu | ||
| 792 | state->mmu.process_id = value & 0x7e000000; | ||
| 793 | break; | ||
| 794 | |||
| 795 | default: | ||
| 796 | printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg); | ||
| 797 | break; | ||
| 798 | } | ||
| 799 | } | ||
| 800 | return 0; | ||
| 801 | } | ||
| 802 | |||
| 803 | //teawater add for arm2x86 2005.06.24------------------------------------------- | ||
| 804 | static int | ||
| 805 | sa_mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, ARMword * phys_addr) | ||
| 806 | { | ||
| 807 | fault_t fault; | ||
| 808 | tlb_entry_t *tlb; | ||
| 809 | |||
| 810 | virt_addr = mmu_pid_va_map (virt_addr); | ||
| 811 | if (MMU_Enabled) { | ||
| 812 | |||
| 813 | /*align check */ | ||
| 814 | if ((virt_addr & (WORD_SIZE - 1)) && MMU_Aligned) { | ||
| 815 | DEBUG_LOG(ARM11, "align\n"); | ||
| 816 | return ALIGNMENT_FAULT; | ||
| 817 | } | ||
| 818 | else | ||
| 819 | virt_addr &= ~(WORD_SIZE - 1); | ||
| 820 | |||
| 821 | /*translate tlb */ | ||
| 822 | fault = translate (state, virt_addr, I_TLB (), &tlb); | ||
| 823 | if (fault) { | ||
| 824 | DEBUG_LOG(ARM11, "translate\n"); | ||
| 825 | return fault; | ||
| 826 | } | ||
| 827 | |||
| 828 | /*check access */ | ||
| 829 | fault = check_access (state, virt_addr, tlb, 1); | ||
| 830 | if (fault) { | ||
| 831 | DEBUG_LOG(ARM11, "check_fault\n"); | ||
| 832 | return fault; | ||
| 833 | } | ||
| 834 | } | ||
| 835 | |||
| 836 | if (MMU_Disabled) { | ||
| 837 | *phys_addr = virt_addr; | ||
| 838 | } | ||
| 839 | else { | ||
| 840 | *phys_addr = tlb_va_to_pa (tlb, virt_addr); | ||
| 841 | } | ||
| 842 | |||
| 843 | return (0); | ||
| 844 | } | ||
| 845 | |||
| 846 | //AJ2D-------------------------------------------------------------------------- | ||
| 847 | |||
| 848 | /*sa mmu_ops_t*/ | ||
| 849 | mmu_ops_t sa_mmu_ops = { | ||
| 850 | sa_mmu_init, | ||
| 851 | sa_mmu_exit, | ||
| 852 | sa_mmu_read_byte, | ||
| 853 | sa_mmu_write_byte, | ||
| 854 | sa_mmu_read_halfword, | ||
| 855 | sa_mmu_write_halfword, | ||
| 856 | sa_mmu_read_word, | ||
| 857 | sa_mmu_write_word, | ||
| 858 | sa_mmu_load_instr, | ||
| 859 | sa_mmu_mcr, | ||
| 860 | sa_mmu_mrc, | ||
| 861 | //teawater add for arm2x86 2005.06.24------------------------------------------- | ||
| 862 | sa_mmu_v2p_dbct, | ||
| 863 | //AJ2D-------------------------------------------------------------------------- | ||
| 864 | }; | ||
diff --git a/src/core/arm/interpreter/mmu/sa_mmu.h b/src/core/arm/interpreter/mmu/sa_mmu.h deleted file mode 100644 index 64b1c5470..000000000 --- a/src/core/arm/interpreter/mmu/sa_mmu.h +++ /dev/null | |||
| @@ -1,58 +0,0 @@ | |||
| 1 | /* | ||
| 2 | sa_mmu.h - StrongARM Memory Management Unit emulation. | ||
| 3 | ARMulator extensions for SkyEye. | ||
| 4 | <lyhost@263.net> | ||
| 5 | |||
| 6 | This program is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 2 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | This program is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with this program; if not, write to the Free Software | ||
| 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef _SA_MMU_H_ | ||
| 22 | #define _SA_MMU_H_ | ||
| 23 | |||
| 24 | |||
| 25 | /** | ||
| 26 | * The interface of read data from bus | ||
| 27 | */ | ||
| 28 | int bus_read(short size, int addr, uint32_t * value); | ||
| 29 | |||
| 30 | /** | ||
| 31 | * The interface of write data from bus | ||
| 32 | */ | ||
| 33 | int bus_write(short size, int addr, uint32_t value); | ||
| 34 | |||
| 35 | |||
| 36 | typedef struct sa_mmu_s | ||
| 37 | { | ||
| 38 | tlb_s i_tlb; | ||
| 39 | cache_s i_cache; | ||
| 40 | |||
| 41 | tlb_s d_tlb; | ||
| 42 | cache_s main_d_cache; | ||
| 43 | cache_s mini_d_cache; | ||
| 44 | rb_s rb_t; | ||
| 45 | wb_s wb_t; | ||
| 46 | } sa_mmu_t; | ||
| 47 | |||
| 48 | #define I_TLB() (&state->mmu.u.sa_mmu.i_tlb) | ||
| 49 | #define I_CACHE() (&state->mmu.u.sa_mmu.i_cache) | ||
| 50 | |||
| 51 | #define D_TLB() (&state->mmu.u.sa_mmu.d_tlb) | ||
| 52 | #define MAIN_D_CACHE() (&state->mmu.u.sa_mmu.main_d_cache) | ||
| 53 | #define MINI_D_CACHE() (&state->mmu.u.sa_mmu.mini_d_cache) | ||
| 54 | #define WB() (&state->mmu.u.sa_mmu.wb_t) | ||
| 55 | #define RB() (&state->mmu.u.sa_mmu.rb_t) | ||
| 56 | |||
| 57 | extern mmu_ops_t sa_mmu_ops; | ||
| 58 | #endif /*_SA_MMU_H_*/ | ||
diff --git a/src/core/arm/interpreter/mmu/tlb.cpp b/src/core/arm/interpreter/mmu/tlb.cpp deleted file mode 100644 index 88c2a8bc5..000000000 --- a/src/core/arm/interpreter/mmu/tlb.cpp +++ /dev/null | |||
| @@ -1,307 +0,0 @@ | |||
| 1 | #include <assert.h> | ||
| 2 | |||
| 3 | #include "core/arm/skyeye_common/armdefs.h" | ||
| 4 | |||
| 5 | ARMword tlb_masks[] = { | ||
| 6 | 0x00000000, /* TLB_INVALID */ | ||
| 7 | 0xFFFFF000, /* TLB_SMALLPAGE */ | ||
| 8 | 0xFFFF0000, /* TLB_LARGEPAGE */ | ||
| 9 | 0xFFF00000, /* TLB_SECTION */ | ||
| 10 | 0xFFFFF000, /*TLB_ESMALLPAGE, have TEX attirbute, only for XScale */ | ||
| 11 | 0xFFFFFC00 /* TLB_TINYPAGE */ | ||
| 12 | }; | ||
| 13 | |||
| 14 | /* This function encodes table 8-2 Interpreting AP bits, | ||
| 15 | returning non-zero if access is allowed. */ | ||
| 16 | static int | ||
| 17 | check_perms (ARMul_State * state, int ap, int read) | ||
| 18 | { | ||
| 19 | int s, r, user; | ||
| 20 | |||
| 21 | s = state->mmu.control & CONTROL_SYSTEM; | ||
| 22 | r = state->mmu.control & CONTROL_ROM; | ||
| 23 | //chy 2006-02-15 , should consider system mode, don't conside 26bit mode | ||
| 24 | user = (state->Mode == USER32MODE) || (state->Mode == USER26MODE) || (state->Mode == SYSTEM32MODE); | ||
| 25 | |||
| 26 | switch (ap) { | ||
| 27 | case 0: | ||
| 28 | return read && ((s && !user) || r); | ||
| 29 | case 1: | ||
| 30 | return !user; | ||
| 31 | case 2: | ||
| 32 | return read || !user; | ||
| 33 | case 3: | ||
| 34 | return 1; | ||
| 35 | } | ||
| 36 | return 0; | ||
| 37 | } | ||
| 38 | |||
| 39 | fault_t | ||
| 40 | check_access (ARMul_State * state, ARMword virt_addr, tlb_entry_t * tlb, | ||
| 41 | int read) | ||
| 42 | { | ||
| 43 | int access; | ||
| 44 | |||
| 45 | state->mmu.last_domain = tlb->domain; | ||
| 46 | access = (state->mmu.domain_access_control >> (tlb->domain * 2)) & 3; | ||
| 47 | if ((access == 0) || (access == 2)) { | ||
| 48 | /* It's unclear from the documentation whether this | ||
| 49 | should always raise a section domain fault, or if | ||
| 50 | it should be a page domain fault in the case of an | ||
| 51 | L1 that describes a page table. In the ARM710T | ||
| 52 | datasheets, "Figure 8-9: Sequence for checking faults" | ||
| 53 | seems to indicate the former, while "Table 8-4: Priority | ||
| 54 | encoding of fault status" gives a value for FS[3210] in | ||
| 55 | the event of a domain fault for a page. Hmm. */ | ||
| 56 | return SECTION_DOMAIN_FAULT; | ||
| 57 | } | ||
| 58 | if (access == 1) { | ||
| 59 | /* client access - check perms */ | ||
| 60 | int subpage, ap; | ||
| 61 | |||
| 62 | switch (tlb->mapping) { | ||
| 63 | /*ks 2004-05-09 | ||
| 64 | * only for XScale | ||
| 65 | * Extend Small Page(ESP) Format | ||
| 66 | * 31-12 bits the base addr of ESP | ||
| 67 | * 11-10 bits SBZ | ||
| 68 | * 9-6 bits TEX | ||
| 69 | * 5-4 bits AP | ||
| 70 | * 3 bit C | ||
| 71 | * 2 bit B | ||
| 72 | * 1-0 bits 11 | ||
| 73 | * */ | ||
| 74 | case TLB_ESMALLPAGE: //xj | ||
| 75 | subpage = 0; | ||
| 76 | //printf("TLB_ESMALLPAGE virt_addr=0x%x \n",virt_addr ); | ||
| 77 | break; | ||
| 78 | |||
| 79 | case TLB_TINYPAGE: | ||
| 80 | subpage = 0; | ||
| 81 | //printf("TLB_TINYPAGE virt_addr=0x%x \n",virt_addr ); | ||
| 82 | break; | ||
| 83 | |||
| 84 | case TLB_SMALLPAGE: | ||
| 85 | subpage = (virt_addr >> 10) & 3; | ||
| 86 | break; | ||
| 87 | case TLB_LARGEPAGE: | ||
| 88 | subpage = (virt_addr >> 14) & 3; | ||
| 89 | break; | ||
| 90 | case TLB_SECTION: | ||
| 91 | subpage = 3; | ||
| 92 | break; | ||
| 93 | default: | ||
| 94 | assert (0); | ||
| 95 | subpage = 0; /* cleans a warning */ | ||
| 96 | } | ||
| 97 | ap = (tlb->perms >> (subpage * 2 + 4)) & 3; | ||
| 98 | if (!check_perms (state, ap, read)) { | ||
| 99 | if (tlb->mapping == TLB_SECTION) { | ||
| 100 | return SECTION_PERMISSION_FAULT; | ||
| 101 | } | ||
| 102 | else { | ||
| 103 | return SUBPAGE_PERMISSION_FAULT; | ||
| 104 | } | ||
| 105 | } | ||
| 106 | } | ||
| 107 | else { /* access == 3 */ | ||
| 108 | /* manager access - don't check perms */ | ||
| 109 | } | ||
| 110 | return NO_FAULT; | ||
| 111 | } | ||
| 112 | |||
| 113 | fault_t | ||
| 114 | translate (ARMul_State * state, ARMword virt_addr, tlb_s * tlb_t, | ||
| 115 | tlb_entry_t ** tlb) | ||
| 116 | { | ||
| 117 | *tlb = mmu_tlb_search (state, tlb_t, virt_addr); | ||
| 118 | if (!*tlb) { | ||
| 119 | /* walk the translation tables */ | ||
| 120 | ARMword l1addr, l1desc; | ||
| 121 | tlb_entry_t entry; | ||
| 122 | |||
| 123 | l1addr = state->mmu.translation_table_base & 0xFFFFC000; | ||
| 124 | l1addr = (l1addr | (virt_addr >> 18)) & ~3; | ||
| 125 | //l1desc = mem_read_word (state, l1addr); | ||
| 126 | bus_read(32, l1addr, &l1desc); | ||
| 127 | switch (l1desc & 3) { | ||
| 128 | case 0: | ||
| 129 | /* | ||
| 130 | * according to Figure 3-9 Sequence for checking faults in arm manual, | ||
| 131 | * section translation fault should be returned here. | ||
| 132 | */ | ||
| 133 | { | ||
| 134 | return SECTION_TRANSLATION_FAULT; | ||
| 135 | } | ||
| 136 | case 3: | ||
| 137 | /* fine page table */ | ||
| 138 | // dcl 2006-01-08 | ||
| 139 | { | ||
| 140 | ARMword l2addr, l2desc; | ||
| 141 | |||
| 142 | l2addr = l1desc & 0xFFFFF000; | ||
| 143 | l2addr = (l2addr | | ||
| 144 | ((virt_addr & 0x000FFC00) >> 8)) & | ||
| 145 | ~3; | ||
| 146 | //l2desc = mem_read_word (state, l2addr); | ||
| 147 | bus_read(32, l2addr, &l2desc); | ||
| 148 | |||
| 149 | entry.virt_addr = virt_addr; | ||
| 150 | entry.phys_addr = l2desc; | ||
| 151 | entry.perms = l2desc & 0x00000FFC; | ||
| 152 | entry.domain = (l1desc >> 5) & 0x0000000F; | ||
| 153 | switch (l2desc & 3) { | ||
| 154 | case 0: | ||
| 155 | state->mmu.last_domain = entry.domain; | ||
| 156 | return PAGE_TRANSLATION_FAULT; | ||
| 157 | case 3: | ||
| 158 | entry.mapping = TLB_TINYPAGE; | ||
| 159 | break; | ||
| 160 | case 1: | ||
| 161 | // this is untested | ||
| 162 | entry.mapping = TLB_LARGEPAGE; | ||
| 163 | break; | ||
| 164 | case 2: | ||
| 165 | // this is untested | ||
| 166 | entry.mapping = TLB_SMALLPAGE; | ||
| 167 | break; | ||
| 168 | } | ||
| 169 | } | ||
| 170 | break; | ||
| 171 | case 1: | ||
| 172 | /* coarse page table */ | ||
| 173 | { | ||
| 174 | ARMword l2addr, l2desc; | ||
| 175 | |||
| 176 | l2addr = l1desc & 0xFFFFFC00; | ||
| 177 | l2addr = (l2addr | | ||
| 178 | ((virt_addr & 0x000FF000) >> 10)) & | ||
| 179 | ~3; | ||
| 180 | //l2desc = mem_read_word (state, l2addr); | ||
| 181 | bus_read(32, l2addr, &l2desc); | ||
| 182 | |||
| 183 | entry.virt_addr = virt_addr; | ||
| 184 | entry.phys_addr = l2desc; | ||
| 185 | entry.perms = l2desc & 0x00000FFC; | ||
| 186 | entry.domain = (l1desc >> 5) & 0x0000000F; | ||
| 187 | //printf("SKYEYE:PAGE virt_addr = %x,l1desc=%x,phys_addr=%x\n",virt_addr,l1desc,entry.phys_addr); | ||
| 188 | //chy 2003-09-02 for xscale | ||
| 189 | switch (l2desc & 3) { | ||
| 190 | case 0: | ||
| 191 | state->mmu.last_domain = entry.domain; | ||
| 192 | return PAGE_TRANSLATION_FAULT; | ||
| 193 | case 3: | ||
| 194 | if (!state->is_XScale) { | ||
| 195 | state->mmu.last_domain = | ||
| 196 | entry.domain; | ||
| 197 | return PAGE_TRANSLATION_FAULT; | ||
| 198 | }; | ||
| 199 | //ks 2004-05-09 xscale shold use Extend Small Page | ||
| 200 | //entry.mapping = TLB_SMALLPAGE; | ||
| 201 | entry.mapping = TLB_ESMALLPAGE; //xj | ||
| 202 | break; | ||
| 203 | case 1: | ||
| 204 | entry.mapping = TLB_LARGEPAGE; | ||
| 205 | break; | ||
| 206 | case 2: | ||
| 207 | entry.mapping = TLB_SMALLPAGE; | ||
| 208 | break; | ||
| 209 | } | ||
| 210 | } | ||
| 211 | break; | ||
| 212 | case 2: | ||
| 213 | /* section */ | ||
| 214 | //printf("SKYEYE:WARNING: not implement section mapping incompletely\n"); | ||
| 215 | //printf("SKYEYE:SECTION virt_addr = %x,l1desc=%x\n",virt_addr,l1desc); | ||
| 216 | //return SECTION_DOMAIN_FAULT; | ||
| 217 | //#if 0 | ||
| 218 | entry.virt_addr = virt_addr; | ||
| 219 | entry.phys_addr = l1desc; | ||
| 220 | entry.perms = l1desc & 0x00000C0C; | ||
| 221 | entry.domain = (l1desc >> 5) & 0x0000000F; | ||
| 222 | entry.mapping = TLB_SECTION; | ||
| 223 | break; | ||
| 224 | //#endif | ||
| 225 | } | ||
| 226 | entry.virt_addr &= tlb_masks[entry.mapping]; | ||
| 227 | entry.phys_addr &= tlb_masks[entry.mapping]; | ||
| 228 | |||
| 229 | /* place entry in the tlb */ | ||
| 230 | *tlb = &tlb_t->entrys[tlb_t->cycle]; | ||
| 231 | tlb_t->cycle = (tlb_t->cycle + 1) % tlb_t->num; | ||
| 232 | **tlb = entry; | ||
| 233 | } | ||
| 234 | state->mmu.last_domain = (*tlb)->domain; | ||
| 235 | return NO_FAULT; | ||
| 236 | } | ||
| 237 | |||
| 238 | int | ||
| 239 | mmu_tlb_init (tlb_s * tlb_t, int num) | ||
| 240 | { | ||
| 241 | tlb_entry_t *e; | ||
| 242 | int i; | ||
| 243 | |||
| 244 | e = (tlb_entry_t *) malloc (sizeof (*e) * num); | ||
| 245 | if (e == NULL) { | ||
| 246 | ERROR_LOG(ARM11, "malloc size %d\n", sizeof (*e) * num); | ||
| 247 | goto tlb_malloc_error; | ||
| 248 | } | ||
| 249 | tlb_t->entrys = e; | ||
| 250 | for (i = 0; i < num; i++, e++) | ||
| 251 | e->mapping = TLB_INVALID; | ||
| 252 | tlb_t->cycle = 0; | ||
| 253 | tlb_t->num = num; | ||
| 254 | return 0; | ||
| 255 | |||
| 256 | tlb_malloc_error: | ||
| 257 | return -1; | ||
| 258 | } | ||
| 259 | |||
| 260 | void | ||
| 261 | mmu_tlb_exit (tlb_s * tlb_t) | ||
| 262 | { | ||
| 263 | free (tlb_t->entrys); | ||
| 264 | }; | ||
| 265 | |||
| 266 | void | ||
| 267 | mmu_tlb_invalidate_all (ARMul_State * state, tlb_s * tlb_t) | ||
| 268 | { | ||
| 269 | int entry; | ||
| 270 | |||
| 271 | for (entry = 0; entry < tlb_t->num; entry++) { | ||
| 272 | tlb_t->entrys[entry].mapping = TLB_INVALID; | ||
| 273 | } | ||
| 274 | tlb_t->cycle = 0; | ||
| 275 | } | ||
| 276 | |||
| 277 | void | ||
| 278 | mmu_tlb_invalidate_entry (ARMul_State * state, tlb_s * tlb_t, ARMword addr) | ||
| 279 | { | ||
| 280 | tlb_entry_t *tlb; | ||
| 281 | |||
| 282 | tlb = mmu_tlb_search (state, tlb_t, addr); | ||
| 283 | if (tlb) { | ||
| 284 | tlb->mapping = TLB_INVALID; | ||
| 285 | } | ||
| 286 | } | ||
| 287 | |||
| 288 | tlb_entry_t * | ||
| 289 | mmu_tlb_search (ARMul_State * state, tlb_s * tlb_t, ARMword virt_addr) | ||
| 290 | { | ||
| 291 | int entry; | ||
| 292 | |||
| 293 | for (entry = 0; entry < tlb_t->num; entry++) { | ||
| 294 | tlb_entry_t *tlb; | ||
| 295 | ARMword mask; | ||
| 296 | |||
| 297 | tlb = &(tlb_t->entrys[entry]); | ||
| 298 | if (tlb->mapping == TLB_INVALID) { | ||
| 299 | continue; | ||
| 300 | } | ||
| 301 | mask = tlb_masks[tlb->mapping]; | ||
| 302 | if ((virt_addr & mask) == (tlb->virt_addr & mask)) { | ||
| 303 | return tlb; | ||
| 304 | } | ||
| 305 | } | ||
| 306 | return NULL; | ||
| 307 | } | ||
diff --git a/src/core/arm/interpreter/mmu/tlb.h b/src/core/arm/interpreter/mmu/tlb.h deleted file mode 100644 index 40856567b..000000000 --- a/src/core/arm/interpreter/mmu/tlb.h +++ /dev/null | |||
| @@ -1,87 +0,0 @@ | |||
| 1 | #ifndef _MMU_TLB_H_ | ||
| 2 | #define _MMU_TLB_H_ | ||
| 3 | |||
| 4 | typedef enum tlb_mapping_t | ||
| 5 | { | ||
| 6 | TLB_INVALID = 0, | ||
| 7 | TLB_SMALLPAGE = 1, | ||
| 8 | TLB_LARGEPAGE = 2, | ||
| 9 | TLB_SECTION = 3, | ||
| 10 | TLB_ESMALLPAGE = 4, | ||
| 11 | TLB_TINYPAGE = 5 | ||
| 12 | } tlb_mapping_t; | ||
| 13 | |||
| 14 | extern ARMword tlb_masks[]; | ||
| 15 | |||
| 16 | /* Permissions bits in a TLB entry: | ||
| 17 | * | ||
| 18 | * 31 12 11 10 9 8 7 6 5 4 3 2 1 0 | ||
| 19 | * +-------------+-----+-----+-----+-----+---+---+-------+ | ||
| 20 | * Page:| | ap3 | ap2 | ap1 | ap0 | C | B | | | ||
| 21 | * +-------------+-----+-----+-----+-----+---+---+-------+ | ||
| 22 | * | ||
| 23 | * 31 12 11 10 9 4 3 2 1 0 | ||
| 24 | * +-------------+-----+-----------------+---+---+-------+ | ||
| 25 | * Section: | | AP | | C | B | | | ||
| 26 | * +-------------+-----+-----------------+---+---+-------+ | ||
| 27 | */ | ||
| 28 | |||
| 29 | /* | ||
| 30 | section: | ||
| 31 | section base address [31:20] | ||
| 32 | AP - table 8-2, page 8-8 | ||
| 33 | domain | ||
| 34 | C,B | ||
| 35 | |||
| 36 | page: | ||
| 37 | page base address [31:16] or [31:12] | ||
| 38 | ap[3:0] | ||
| 39 | domain (from L1) | ||
| 40 | C,B | ||
| 41 | */ | ||
| 42 | |||
| 43 | |||
| 44 | typedef struct tlb_entry_t | ||
| 45 | { | ||
| 46 | ARMword virt_addr; | ||
| 47 | ARMword phys_addr; | ||
| 48 | ARMword perms; | ||
| 49 | ARMword domain; | ||
| 50 | tlb_mapping_t mapping; | ||
| 51 | } tlb_entry_t; | ||
| 52 | |||
| 53 | typedef struct tlb_s | ||
| 54 | { | ||
| 55 | int num; /*num of tlb entry */ | ||
| 56 | int cycle; /*current tlb cycle */ | ||
| 57 | tlb_entry_t *entrys; | ||
| 58 | } tlb_s; | ||
| 59 | |||
| 60 | |||
| 61 | #define tlb_c_flag(tlb) \ | ||
| 62 | ((tlb)->perms & 0x8) | ||
| 63 | #define tlb_b_flag(tlb) \ | ||
| 64 | ((tlb)->perms & 0x4) | ||
| 65 | |||
| 66 | #define tlb_va_to_pa(tlb, va) ((tlb->phys_addr & tlb_masks[tlb->mapping]) | (va & ~tlb_masks[tlb->mapping])) | ||
| 67 | fault_t | ||
| 68 | check_access (ARMul_State * state, ARMword virt_addr, tlb_entry_t * tlb, | ||
| 69 | int read); | ||
| 70 | |||
| 71 | fault_t | ||
| 72 | translate (ARMul_State * state, ARMword virt_addr, tlb_s * tlb_t, | ||
| 73 | tlb_entry_t ** tlb); | ||
| 74 | |||
| 75 | int mmu_tlb_init (tlb_s * tlb_t, int num); | ||
| 76 | |||
| 77 | void mmu_tlb_exit (tlb_s * tlb_t); | ||
| 78 | |||
| 79 | void mmu_tlb_invalidate_all (ARMul_State * state, tlb_s * tlb_t); | ||
| 80 | |||
| 81 | void | ||
| 82 | mmu_tlb_invalidate_entry (ARMul_State * state, tlb_s * tlb_t, ARMword addr); | ||
| 83 | |||
| 84 | tlb_entry_t *mmu_tlb_search (ARMul_State * state, tlb_s * tlb_t, | ||
| 85 | ARMword virt_addr); | ||
| 86 | |||
| 87 | #endif /*_MMU_TLB_H_*/ | ||
diff --git a/src/core/arm/interpreter/mmu/wb.cpp b/src/core/arm/interpreter/mmu/wb.cpp deleted file mode 100644 index 5ddda41ee..000000000 --- a/src/core/arm/interpreter/mmu/wb.cpp +++ /dev/null | |||
| @@ -1,149 +0,0 @@ | |||
| 1 | #include "core/arm/skyeye_common/armdefs.h" | ||
| 2 | |||
| 3 | /* wb_init | ||
| 4 | * @wb_t :wb_t to init | ||
| 5 | * @num :num of entrys | ||
| 6 | * @nb :num of byte of each entry | ||
| 7 | * | ||
| 8 | * $ -1:error | ||
| 9 | * 0:ok | ||
| 10 | * */ | ||
| 11 | int | ||
| 12 | mmu_wb_init (wb_s * wb_t, int num, int nb) | ||
| 13 | { | ||
| 14 | int i; | ||
| 15 | wb_entry_t *entrys, *wb; | ||
| 16 | |||
| 17 | entrys = (wb_entry_t *) malloc (sizeof (*entrys) * num); | ||
| 18 | if (entrys == NULL) { | ||
| 19 | ERROR_LOG(ARM11, "malloc size %d\n", sizeof (*entrys) * num); | ||
| 20 | goto entrys_malloc_error; | ||
| 21 | } | ||
| 22 | |||
| 23 | for (wb = entrys, i = 0; i < num; i++, wb++) { | ||
| 24 | /*chy 2004-06-06, fix bug found by wenye@cs.ucsb.edu */ | ||
| 25 | //wb->data = (ARMword *)malloc(sizeof(ARMword) * nb); | ||
| 26 | wb->data = (ARMbyte *) malloc (nb); | ||
| 27 | if (wb->data == NULL) { | ||
| 28 | ERROR_LOG(ARM11, "malloc size of %d\n", nb); | ||
| 29 | goto data_malloc_error; | ||
| 30 | } | ||
| 31 | |||
| 32 | }; | ||
| 33 | |||
| 34 | wb_t->first = wb_t->last = wb_t->used = 0; | ||
| 35 | wb_t->num = num; | ||
| 36 | wb_t->nb = nb; | ||
| 37 | wb_t->entrys = entrys; | ||
| 38 | return 0; | ||
| 39 | |||
| 40 | data_malloc_error: | ||
| 41 | while (--i >= 0) | ||
| 42 | free (entrys[i].data); | ||
| 43 | free (entrys); | ||
| 44 | entrys_malloc_error: | ||
| 45 | return -1; | ||
| 46 | }; | ||
| 47 | |||
| 48 | /* wb_exit | ||
| 49 | * @wb_t :wb_t to exit | ||
| 50 | * */ | ||
| 51 | void | ||
| 52 | mmu_wb_exit (wb_s * wb_t) | ||
| 53 | { | ||
| 54 | int i; | ||
| 55 | wb_entry_t *wb; | ||
| 56 | |||
| 57 | wb = wb_t->entrys; | ||
| 58 | for (i = 0; i < wb_t->num; i++, wb++) { | ||
| 59 | free (wb->data); | ||
| 60 | } | ||
| 61 | free (wb_t->entrys); | ||
| 62 | }; | ||
| 63 | |||
| 64 | /* wb_write_words :put words in Write Buffer | ||
| 65 | * @state: ARMul_State | ||
| 66 | * @wb_t: write buffer | ||
| 67 | * @pa: physical address | ||
| 68 | * @data: data ptr | ||
| 69 | * @n number of word to write | ||
| 70 | * | ||
| 71 | * Note: write buffer merge is not implemented, can be done late | ||
| 72 | * */ | ||
| 73 | void | ||
| 74 | mmu_wb_write_bytes (ARMul_State * state, wb_s * wb_t, ARMword pa, | ||
| 75 | ARMbyte * data, int n) | ||
| 76 | { | ||
| 77 | int i; | ||
| 78 | wb_entry_t *wb; | ||
| 79 | |||
| 80 | while (n) { | ||
| 81 | if (wb_t->num == wb_t->used) { | ||
| 82 | /*clean the last wb entry */ | ||
| 83 | ARMword t; | ||
| 84 | |||
| 85 | wb = &wb_t->entrys[wb_t->last]; | ||
| 86 | t = wb->pa; | ||
| 87 | for (i = 0; i < wb->nb; i++) { | ||
| 88 | //mem_write_byte (state, t, wb->data[i]); | ||
| 89 | bus_write(8, t, wb->data[i]); | ||
| 90 | //t += WORD_SIZE; | ||
| 91 | t++; | ||
| 92 | } | ||
| 93 | wb_t->last++; | ||
| 94 | if (wb_t->last == wb_t->num) | ||
| 95 | wb_t->last = 0; | ||
| 96 | wb_t->used--; | ||
| 97 | } | ||
| 98 | |||
| 99 | wb = &wb_t->entrys[wb_t->first]; | ||
| 100 | i = (n < wb_t->nb) ? n : wb_t->nb; | ||
| 101 | |||
| 102 | wb->pa = pa; | ||
| 103 | //pa += i << WORD_SHT; | ||
| 104 | pa += i; | ||
| 105 | |||
| 106 | wb->nb = i; | ||
| 107 | //memcpy(wb->data, data, i << WORD_SHT); | ||
| 108 | memcpy (wb->data, data, i); | ||
| 109 | data += i; | ||
| 110 | n -= i; | ||
| 111 | wb_t->first++; | ||
| 112 | if (wb_t->first == wb_t->num) | ||
| 113 | wb_t->first = 0; | ||
| 114 | wb_t->used++; | ||
| 115 | }; | ||
| 116 | //teawater add for set_dirty fflash cache function 2005.07.18------------------- | ||
| 117 | #ifdef DBCT | ||
| 118 | if (!skyeye_config.no_dbct) { | ||
| 119 | tb_setdirty (state, pa, NULL); | ||
| 120 | } | ||
| 121 | #endif | ||
| 122 | //AJ2D-------------------------------------------------------------------------- | ||
| 123 | } | ||
| 124 | |||
| 125 | /* wb_drain_all | ||
| 126 | * @wb_t wb_t to drain | ||
| 127 | * */ | ||
| 128 | void | ||
| 129 | mmu_wb_drain_all (ARMul_State * state, wb_s * wb_t) | ||
| 130 | { | ||
| 131 | ARMword pa; | ||
| 132 | wb_entry_t *wb; | ||
| 133 | int i; | ||
| 134 | |||
| 135 | while (wb_t->used) { | ||
| 136 | wb = &wb_t->entrys[wb_t->last]; | ||
| 137 | pa = wb->pa; | ||
| 138 | for (i = 0; i < wb->nb; i++) { | ||
| 139 | //mem_write_byte (state, pa, wb->data[i]); | ||
| 140 | bus_write(8, pa, wb->data[i]); | ||
| 141 | //pa += WORD_SIZE; | ||
| 142 | pa++; | ||
| 143 | } | ||
| 144 | wb_t->last++; | ||
| 145 | if (wb_t->last == wb_t->num) | ||
| 146 | wb_t->last = 0; | ||
| 147 | wb_t->used--; | ||
| 148 | }; | ||
| 149 | } | ||
diff --git a/src/core/arm/interpreter/mmu/wb.h b/src/core/arm/interpreter/mmu/wb.h deleted file mode 100644 index 8fb7de946..000000000 --- a/src/core/arm/interpreter/mmu/wb.h +++ /dev/null | |||
| @@ -1,63 +0,0 @@ | |||
| 1 | #ifndef _MMU_WB_H_ | ||
| 2 | #define _MMU_WB_H_ | ||
| 3 | |||
| 4 | typedef struct wb_entry_s | ||
| 5 | { | ||
| 6 | ARMword pa; //phy_addr | ||
| 7 | ARMbyte *data; //data | ||
| 8 | int nb; //number byte to write | ||
| 9 | } wb_entry_t; | ||
| 10 | |||
| 11 | typedef struct wb_s | ||
| 12 | { | ||
| 13 | int num; //number of wb_entry | ||
| 14 | int nb; //number of byte of each entry | ||
| 15 | int first; // | ||
| 16 | int last; // | ||
| 17 | int used; // | ||
| 18 | wb_entry_t *entrys; | ||
| 19 | } wb_s; | ||
| 20 | |||
| 21 | typedef struct wb_desc_s | ||
| 22 | { | ||
| 23 | int num; | ||
| 24 | int nb; | ||
| 25 | } wb_desc_t; | ||
| 26 | |||
| 27 | /* wb_init | ||
| 28 | * @wb_t :wb_t to init | ||
| 29 | * @num :num of entrys | ||
| 30 | * @nw :num of word of each entry | ||
| 31 | * | ||
| 32 | * $ -1:error | ||
| 33 | * 0:ok | ||
| 34 | * */ | ||
| 35 | int mmu_wb_init (wb_s * wb_t, int num, int nb); | ||
| 36 | |||
| 37 | |||
| 38 | /* wb_exit | ||
| 39 | * @wb_t :wb_t to exit | ||
| 40 | * */ | ||
| 41 | void mmu_wb_exit (wb_s * wb); | ||
| 42 | |||
| 43 | |||
| 44 | /* wb_write_bytes :put bytess in Write Buffer | ||
| 45 | * @state: ARMul_State | ||
| 46 | * @wb_t: write buffer | ||
| 47 | * @pa: physical address | ||
| 48 | * @data: data ptr | ||
| 49 | * @n number of byte to write | ||
| 50 | * | ||
| 51 | * Note: write buffer merge is not implemented, can be done late | ||
| 52 | * */ | ||
| 53 | void | ||
| 54 | mmu_wb_write_bytess (ARMul_State * state, wb_s * wb_t, ARMword pa, | ||
| 55 | ARMbyte * data, int n); | ||
| 56 | |||
| 57 | |||
| 58 | /* wb_drain_all | ||
| 59 | * @wb_t wb_t to drain | ||
| 60 | * */ | ||
| 61 | void mmu_wb_drain_all (ARMul_State * state, wb_s * wb_t); | ||
| 62 | |||
| 63 | #endif /*_MMU_WB_H_*/ | ||
diff --git a/src/core/arm/interpreter/mmu/xscale_copro.cpp b/src/core/arm/interpreter/mmu/xscale_copro.cpp deleted file mode 100644 index cf91fd933..000000000 --- a/src/core/arm/interpreter/mmu/xscale_copro.cpp +++ /dev/null | |||
| @@ -1,1391 +0,0 @@ | |||
| 1 | /* | ||
| 2 | armmmu.c - Memory Management Unit emulation. | ||
| 3 | ARMulator extensions for the ARM7100 family. | ||
| 4 | Copyright (C) 1999 Ben Williamson | ||
| 5 | |||
| 6 | This program is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 2 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | This program is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with this program; if not, write to the Free Software | ||
| 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <assert.h> | ||
| 22 | #include <string.h> | ||
| 23 | |||
| 24 | #include "core/arm/skyeye_common/armdefs.h" | ||
| 25 | #include "core/arm/skyeye_common/armemu.h" | ||
| 26 | |||
| 27 | /*#include "pxa.h" */ | ||
| 28 | |||
| 29 | /* chy 2005-09-19 */ | ||
| 30 | |||
| 31 | /* extern pxa270_io_t pxa270_io; */ | ||
| 32 | /* chy 2005-09-19 -----end */ | ||
| 33 | |||
| 34 | typedef struct xscale_mmu_desc_s | ||
| 35 | { | ||
| 36 | int i_tlb; | ||
| 37 | cache_desc_t i_cache; | ||
| 38 | |||
| 39 | int d_tlb; | ||
| 40 | cache_desc_t main_d_cache; | ||
| 41 | cache_desc_t mini_d_cache; | ||
| 42 | //int rb; xscale has no read buffer | ||
| 43 | wb_desc_t wb; | ||
| 44 | } xscale_mmu_desc_t; | ||
| 45 | |||
| 46 | static xscale_mmu_desc_t pxa_mmu_desc = { | ||
| 47 | 32, | ||
| 48 | {32, 32, 32, CACHE_WRITE_BACK}, | ||
| 49 | |||
| 50 | 32, | ||
| 51 | {32, 32, 32, CACHE_WRITE_BACK}, | ||
| 52 | {32, 2, 8, CACHE_WRITE_BACK}, | ||
| 53 | {8, 16}, //for byte size, | ||
| 54 | }; | ||
| 55 | |||
| 56 | //chy 2005-09-19 for cp6 | ||
| 57 | #define CR0_ICIP 0 | ||
| 58 | #define CR1_ICMR 1 | ||
| 59 | //chy 2005-09-19 ---end | ||
| 60 | //----------- for cp14----------------- | ||
| 61 | #define CCLKCFG 6 | ||
| 62 | #define PWRMODE 7 | ||
| 63 | typedef struct xscale_cp14_reg_s | ||
| 64 | { | ||
| 65 | unsigned cclkcfg; //reg6 | ||
| 66 | unsigned pwrmode; //reg7 | ||
| 67 | } xscale_cp14_reg_s; | ||
| 68 | |||
| 69 | xscale_cp14_reg_s pxa_cp14_regs; | ||
| 70 | |||
| 71 | //-------------------------------------- | ||
| 72 | |||
| 73 | static fault_t xscale_mmu_write (ARMul_State * state, ARMword va, | ||
| 74 | ARMword data, ARMword datatype); | ||
| 75 | static fault_t xscale_mmu_read (ARMul_State * state, ARMword va, | ||
| 76 | ARMword * data, ARMword datatype); | ||
| 77 | |||
| 78 | ARMword xscale_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value); | ||
| 79 | ARMword xscale_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value); | ||
| 80 | |||
| 81 | |||
| 82 | /* jeff add 2010.9.26 for pxa270 cp6*/ | ||
| 83 | #define PXA270_ICMR 0x40D00004 | ||
| 84 | #define PXA270_ICPR 0x40D00010 | ||
| 85 | #define PXA270_ICLR 0x40D00008 | ||
| 86 | //chy 2005-09-19 for xscale pxa27x cp6 | ||
| 87 | unsigned | ||
| 88 | xscale_cp6_mrc (ARMul_State * state, unsigned type, ARMword instr, | ||
| 89 | ARMword * data) | ||
| 90 | { | ||
| 91 | unsigned opcode_2 = BITS (5, 7); | ||
| 92 | unsigned CRm = BITS (0, 3); | ||
| 93 | unsigned reg = BITS (16, 19); | ||
| 94 | unsigned result; | ||
| 95 | |||
| 96 | //printf("SKYEYE: xscale_cp6_mrc:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n",opcode_2,CRm,reg,state->Reg[15], instr); | ||
| 97 | |||
| 98 | switch (reg) { | ||
| 99 | case CR0_ICIP: { // cp 6 reg 0 | ||
| 100 | //printf("cp6_mrc cr0 ICIP \n"); | ||
| 101 | /* *data = (pxa270_io.icmr & pxa270_io.icpr) & ~pxa270_io.iclr; */ | ||
| 102 | /* use bus_read get the pxa270 machine registers 2010.9.26 jeff*/ | ||
| 103 | int icmr, icpr, iclr; | ||
| 104 | bus_read(32, PXA270_ICMR, (uint32_t*)&icmr); | ||
| 105 | bus_read(32, PXA270_ICPR, (uint32_t*)&icpr); | ||
| 106 | bus_read(32, PXA270_ICLR, (uint32_t*)&iclr); | ||
| 107 | *data = (icmr & icpr) & ~iclr; | ||
| 108 | } | ||
| 109 | break; | ||
| 110 | case CR1_ICMR: { // cp 6 reg 1 | ||
| 111 | //printf("cp6_mrc cr1 ICMR\n"); | ||
| 112 | /* *data = pxa270_io.icmr; */ | ||
| 113 | int icmr; | ||
| 114 | /* use bus_read get the pxa270 machine registers 2010.9.26 jeff*/ | ||
| 115 | bus_read(32, PXA270_ICMR, (uint32_t*)&icmr); | ||
| 116 | *data = icmr; | ||
| 117 | } | ||
| 118 | break; | ||
| 119 | default: | ||
| 120 | *data = 0; | ||
| 121 | printf ("SKYEYE:cp6_mrc unknown cp6 regs!!!!!!\n"); | ||
| 122 | printf ("SKYEYE: xscale_cp6_mrc:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n", opcode_2, CRm, reg, state->Reg[15], instr); | ||
| 123 | break; | ||
| 124 | } | ||
| 125 | return 0; | ||
| 126 | } | ||
| 127 | |||
| 128 | //chy 2005-09-19 end | ||
| 129 | //xscale cp13 ---------------------------------------------------- | ||
| 130 | unsigned | ||
| 131 | xscale_cp13_init (ARMul_State * state) | ||
| 132 | { | ||
| 133 | //printf("SKYEYE: xscale_cp13_init: begin\n"); | ||
| 134 | return 0; | ||
| 135 | } | ||
| 136 | |||
| 137 | unsigned | ||
| 138 | xscale_cp13_exit (ARMul_State * state) | ||
| 139 | { | ||
| 140 | //printf("SKYEYE: xscale_cp13_exit: begin\n"); | ||
| 141 | return 0; | ||
| 142 | } | ||
| 143 | |||
| 144 | unsigned | ||
| 145 | xscale_cp13_ldc (ARMul_State * state, unsigned type, ARMword instr, | ||
| 146 | ARMword data) | ||
| 147 | { | ||
| 148 | printf ("SKYEYE: xscale_cp13_ldc: ERROR isn't existed,"); | ||
| 149 | SKYEYE_OUTREGS (stderr); | ||
| 150 | fprintf (stderr, "\n"); | ||
| 151 | // skyeye_exit (-1); | ||
| 152 | return 0; //No matter return value, only for compiler. | ||
| 153 | } | ||
| 154 | |||
| 155 | unsigned | ||
| 156 | xscale_cp13_stc (ARMul_State * state, unsigned type, ARMword instr, | ||
| 157 | ARMword * data) | ||
| 158 | { | ||
| 159 | printf ("SKYEYE: xscale_cp13_stc: ERROR isn't existed,"); | ||
| 160 | SKYEYE_OUTREGS (stderr); | ||
| 161 | fprintf (stderr, "\n"); | ||
| 162 | // skyeye_exit (-1); | ||
| 163 | return 0; //No matter return value, only for compiler. | ||
| 164 | } | ||
| 165 | |||
| 166 | unsigned | ||
| 167 | xscale_cp13_mrc (ARMul_State * state, unsigned type, ARMword instr, | ||
| 168 | ARMword * data) | ||
| 169 | { | ||
| 170 | printf ("SKYEYE: xscale_cp13_mrc: ERROR isn't existed,"); | ||
| 171 | SKYEYE_OUTREGS (stderr); | ||
| 172 | fprintf (stderr, "\n"); | ||
| 173 | // skyeye_exit (-1); | ||
| 174 | return 0; //No matter return value, only for compiler. | ||
| 175 | } | ||
| 176 | |||
| 177 | unsigned | ||
| 178 | xscale_cp13_mcr (ARMul_State * state, unsigned type, ARMword instr, | ||
| 179 | ARMword data) | ||
| 180 | { | ||
| 181 | printf ("SKYEYE: xscale_cp13_mcr: ERROR isn't existed,"); | ||
| 182 | SKYEYE_OUTREGS (stderr); | ||
| 183 | fprintf (stderr, "\n"); | ||
| 184 | // skyeye_exit (-1); | ||
| 185 | return 0; //No matter return value, only for compiler. | ||
| 186 | } | ||
| 187 | |||
| 188 | unsigned | ||
| 189 | xscale_cp13_cdp (ARMul_State * state, unsigned type, ARMword instr) | ||
| 190 | { | ||
| 191 | printf ("SKYEYE: xscale_cp13_cdp: ERROR isn't existed,"); | ||
| 192 | SKYEYE_OUTREGS (stderr); | ||
| 193 | fprintf (stderr, "\n"); | ||
| 194 | // skyeye_exit (-1); | ||
| 195 | return 0; //No matter return value, only for compiler. | ||
| 196 | } | ||
| 197 | |||
| 198 | unsigned | ||
| 199 | xscale_cp13_read_reg (ARMul_State * state, unsigned reg, ARMword * data) | ||
| 200 | { | ||
| 201 | printf ("SKYEYE: xscale_cp13_read_reg: ERROR isn't existed,"); | ||
| 202 | SKYEYE_OUTREGS (stderr); | ||
| 203 | fprintf (stderr, "\n"); | ||
| 204 | return 0; | ||
| 205 | //exit(-1); | ||
| 206 | } | ||
| 207 | |||
| 208 | unsigned | ||
| 209 | xscale_cp13_write_reg (ARMul_State * state, unsigned reg, ARMword data) | ||
| 210 | { | ||
| 211 | printf ("SKYEYE: xscale_cp13_write_reg: ERROR isn't existed,"); | ||
| 212 | SKYEYE_OUTREGS (stderr); | ||
| 213 | fprintf (stderr, "\n"); | ||
| 214 | // skyeye_exit (-1); | ||
| 215 | return 0; //No matter return value, only for compiler. | ||
| 216 | } | ||
| 217 | |||
| 218 | //------------------------------------------------------------------ | ||
| 219 | //xscale cp14 ---------------------------------------------------- | ||
| 220 | unsigned | ||
| 221 | xscale_cp14_init (ARMul_State * state) | ||
| 222 | { | ||
| 223 | //printf("SKYEYE: xscale_cp14_init: begin\n"); | ||
| 224 | pxa_cp14_regs.cclkcfg = 0; | ||
| 225 | pxa_cp14_regs.pwrmode = 0; | ||
| 226 | return 0; | ||
| 227 | } | ||
| 228 | |||
| 229 | unsigned | ||
| 230 | xscale_cp14_exit (ARMul_State * state) | ||
| 231 | { | ||
| 232 | //printf("SKYEYE: xscale_cp14_exit: begin\n"); | ||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | |||
| 236 | unsigned | ||
| 237 | xscale_cp14_ldc (ARMul_State * state, unsigned type, ARMword instr, | ||
| 238 | ARMword data) | ||
| 239 | { | ||
| 240 | printf ("SKYEYE: xscale_cp14_ldc: ERROR isn't existed, reg15 0x%x\n", | ||
| 241 | state->Reg[15]); | ||
| 242 | SKYEYE_OUTREGS (stderr); | ||
| 243 | // skyeye_exit (-1); | ||
| 244 | return 0; //No matter return value, only for compiler. | ||
| 245 | } | ||
| 246 | |||
| 247 | unsigned | ||
| 248 | xscale_cp14_stc (ARMul_State * state, unsigned type, ARMword instr, | ||
| 249 | ARMword * data) | ||
| 250 | { | ||
| 251 | printf ("SKYEYE: xscale_cp14_stc: ERROR isn't existed, reg15 0x%x\n", | ||
| 252 | state->Reg[15]); | ||
| 253 | SKYEYE_OUTREGS (stderr); | ||
| 254 | // skyeye_exit (-1); | ||
| 255 | return 0; //No matter return value, only for compiler. | ||
| 256 | } | ||
| 257 | |||
| 258 | unsigned | ||
| 259 | xscale_cp14_mrc (ARMul_State * state, unsigned type, ARMword instr, | ||
| 260 | ARMword * data) | ||
| 261 | { | ||
| 262 | unsigned opcode_2 = BITS (5, 7); | ||
| 263 | unsigned CRm = BITS (0, 3); | ||
| 264 | unsigned reg = BITS (16, 19); | ||
| 265 | unsigned result; | ||
| 266 | |||
| 267 | //printf("SKYEYE: xscale_cp14_mrc:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n",opcode_2,CRm,reg,\ | ||
| 268 | state->Reg[15], instr); | ||
| 269 | |||
| 270 | switch (reg) { | ||
| 271 | case CCLKCFG: // cp 14 reg 6 | ||
| 272 | //printf("cp14_mrc cclkcfg \n"); | ||
| 273 | *data = pxa_cp14_regs.cclkcfg; | ||
| 274 | break; | ||
| 275 | case PWRMODE: // cp 14 reg 7 | ||
| 276 | //printf("cp14_mrc pwrmode \n"); | ||
| 277 | *data = pxa_cp14_regs.pwrmode; | ||
| 278 | break; | ||
| 279 | default: | ||
| 280 | *data = 0; | ||
| 281 | printf ("SKYEYE:cp14_mrc unknown cp14 regs!!!!!!\n"); | ||
| 282 | break; | ||
| 283 | } | ||
| 284 | return 0; | ||
| 285 | } | ||
| 286 | unsigned xscale_cp14_mcr (ARMul_State * state, unsigned type, ARMword instr, | ||
| 287 | ARMword data) | ||
| 288 | { | ||
| 289 | unsigned opcode_2 = BITS (5, 7); | ||
| 290 | unsigned CRm = BITS (0, 3); | ||
| 291 | unsigned reg = BITS (16, 19); | ||
| 292 | unsigned result; | ||
| 293 | |||
| 294 | //printf("SKYEYE: xscale_cp14_mcr:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n",opcode_2,CRm,reg,\ | ||
| 295 | state->Reg[15], instr); | ||
| 296 | |||
| 297 | switch (reg) { | ||
| 298 | case CCLKCFG: // cp 14 reg 6 | ||
| 299 | //printf("cp14_mcr cclkcfg \n"); | ||
| 300 | pxa_cp14_regs.cclkcfg = data & 0xf; | ||
| 301 | break; | ||
| 302 | case PWRMODE: // cp 14 reg 7 | ||
| 303 | //printf("cp14_mcr pwrmode \n"); | ||
| 304 | pxa_cp14_regs.pwrmode = data & 0x3; | ||
| 305 | break; | ||
| 306 | default:printf ("SKYEYE: cp14_mcr unknown cp14 regs!!!!!!\n"); | ||
| 307 | break; | ||
| 308 | } | ||
| 309 | return 0; | ||
| 310 | } | ||
| 311 | unsigned xscale_cp14_cdp (ARMul_State * state, unsigned type, ARMword instr) | ||
| 312 | { | ||
| 313 | printf ("SKYEYE: xscale_cp14_cdp: ERROR isn't existed, reg15 0x%x\n", | ||
| 314 | state->Reg[15]); | ||
| 315 | SKYEYE_OUTREGS (stderr); | ||
| 316 | // skyeye_exit (-1); | ||
| 317 | return 0; //No matter return value, only for compiler. | ||
| 318 | } | ||
| 319 | unsigned xscale_cp14_read_reg (ARMul_State * state, unsigned reg, | ||
| 320 | ARMword * data) | ||
| 321 | { | ||
| 322 | printf ("SKYEYE: xscale_cp14_read_reg: ERROR isn't existed, reg15 0x%x\n", state->Reg[15]); | ||
| 323 | SKYEYE_OUTREGS (stderr); | ||
| 324 | // skyeye_exit (-1); | ||
| 325 | return 0; //No matter return value, only for compiler. | ||
| 326 | } | ||
| 327 | unsigned xscale_cp14_write_reg (ARMul_State * state, unsigned reg, | ||
| 328 | ARMword data) | ||
| 329 | { | ||
| 330 | printf ("SKYEYE: xscale_cp14_write_reg: ERROR isn't existed, reg15 0x%x\n", state->Reg[15]); | ||
| 331 | SKYEYE_OUTREGS (stderr); | ||
| 332 | // skyeye_exit (-1); | ||
| 333 | |||
| 334 | return 0; //No matter return value, only for compiler. | ||
| 335 | } | ||
| 336 | |||
| 337 | //------------------------------------------------------------------ | ||
| 338 | //cp15 ------------------------------------- | ||
| 339 | unsigned xscale_cp15_ldc (ARMul_State * state, unsigned type, ARMword instr, | ||
| 340 | ARMword data) | ||
| 341 | { | ||
| 342 | printf ("SKYEYE: xscale_cp15_ldc: ERROR isn't existed\n"); | ||
| 343 | SKYEYE_OUTREGS (stderr); | ||
| 344 | // skyeye_exit (-1); | ||
| 345 | |||
| 346 | return 0; //No matter return value, only for compiler. | ||
| 347 | } | ||
| 348 | unsigned xscale_cp15_stc (ARMul_State * state, unsigned type, ARMword instr, | ||
| 349 | ARMword * data) | ||
| 350 | { | ||
| 351 | printf ("SKYEYE: xscale_cp15_stc: ERROR isn't existed\n"); | ||
| 352 | SKYEYE_OUTREGS (stderr); | ||
| 353 | // skyeye_exit (-1); | ||
| 354 | |||
| 355 | return 0; //No matter return value, only for compiler. | ||
| 356 | } | ||
| 357 | unsigned xscale_cp15_cdp (ARMul_State * state, unsigned type, ARMword instr) | ||
| 358 | { | ||
| 359 | printf ("SKYEYE: xscale_cp15_cdp: ERROR isn't existed\n"); | ||
| 360 | SKYEYE_OUTREGS (stderr); | ||
| 361 | // skyeye_exit (-1); | ||
| 362 | |||
| 363 | return 0; //No matter return value, only for compiler. | ||
| 364 | } | ||
| 365 | unsigned xscale_cp15_read_reg (ARMul_State * state, unsigned reg, | ||
| 366 | ARMword * data) | ||
| 367 | { | ||
| 368 | //chy 2003-09-03: for xsacle_cp15_cp_access_allowed | ||
| 369 | if (reg == 15) { | ||
| 370 | *data = state->mmu.copro_access; | ||
| 371 | //printf("SKYEYE: xscale_cp15_read_reg: reg 0x%x,data %x\n",reg,*data); | ||
| 372 | return 0; | ||
| 373 | } | ||
| 374 | printf ("SKYEYE: xscale_cp15_read_reg: reg 0x%x, ERROR isn't existed\n", reg); | ||
| 375 | SKYEYE_OUTREGS (stderr); | ||
| 376 | // skyeye_exit (-1); | ||
| 377 | |||
| 378 | return 0; //No matter return value, only for compiler. | ||
| 379 | } | ||
| 380 | |||
| 381 | //chy 2003-09-03 used by macro CP_ACCESS_ALLOWED in armemu.h | ||
| 382 | unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg, | ||
| 383 | unsigned cpnum) | ||
| 384 | { | ||
| 385 | unsigned data; | ||
| 386 | |||
| 387 | xscale_cp15_read_reg (state, reg, &data); | ||
| 388 | //printf("SKYEYE: cp15_cp_access_allowed data %x, cpnum %x, result %x\n", data, cpnum, (data & 1<<cpnum)); | ||
| 389 | if (data & 1 << cpnum) | ||
| 390 | return 1; | ||
| 391 | else | ||
| 392 | return 0; | ||
| 393 | } | ||
| 394 | |||
| 395 | unsigned xscale_cp15_write_reg (ARMul_State * state, unsigned reg, | ||
| 396 | ARMword value) | ||
| 397 | { | ||
| 398 | switch (reg) { | ||
| 399 | case MMU_FAULT_STATUS: | ||
| 400 | //printf("SKYEYE:cp15_write_reg wrote FS val 0x%x \n",value); | ||
| 401 | state->mmu.fault_status = value & 0x6FF; | ||
| 402 | break; | ||
| 403 | case MMU_FAULT_ADDRESS: | ||
| 404 | //printf("SKYEYE:cp15_write_reg wrote FA val 0x%x \n",value); | ||
| 405 | state->mmu.fault_address = value; | ||
| 406 | break; | ||
| 407 | default: | ||
| 408 | printf ("SKYEYE: xscale_cp15_write_reg: reg 0x%x R15 %x ERROR isn't existed\n", reg, state->Reg[15]); | ||
| 409 | SKYEYE_OUTREGS (stderr); | ||
| 410 | // skyeye_exit (-1); | ||
| 411 | } | ||
| 412 | return 0; | ||
| 413 | } | ||
| 414 | |||
| 415 | unsigned | ||
| 416 | xscale_cp15_init (ARMul_State * state) | ||
| 417 | { | ||
| 418 | xscale_mmu_desc_t *desc; | ||
| 419 | cache_desc_t *c_desc; | ||
| 420 | |||
| 421 | state->mmu.control = 0; | ||
| 422 | state->mmu.translation_table_base = 0xDEADC0DE; | ||
| 423 | state->mmu.domain_access_control = 0xDEADC0DE; | ||
| 424 | state->mmu.fault_status = 0; | ||
| 425 | state->mmu.fault_address = 0; | ||
| 426 | state->mmu.process_id = 0; | ||
| 427 | state->mmu.cache_type = 0xB1AA1AA; //0000 1011 0001 1010 1010 0001 1010 1010 | ||
| 428 | state->mmu.aux_control = 0; | ||
| 429 | |||
| 430 | desc = &pxa_mmu_desc; | ||
| 431 | |||
| 432 | if (mmu_tlb_init (I_TLB (), desc->i_tlb)) { | ||
| 433 | ERROR_LOG(ARM11, "i_tlb init %d\n", -1); | ||
| 434 | goto i_tlb_init_error; | ||
| 435 | } | ||
| 436 | |||
| 437 | c_desc = &desc->i_cache; | ||
| 438 | if (mmu_cache_init (I_CACHE (), c_desc->width, c_desc->way, | ||
| 439 | c_desc->set, c_desc->w_mode)) { | ||
| 440 | ERROR_LOG(ARM11, "i_cache init %d\n", -1); | ||
| 441 | goto i_cache_init_error; | ||
| 442 | } | ||
| 443 | |||
| 444 | if (mmu_tlb_init (D_TLB (), desc->d_tlb)) { | ||
| 445 | ERROR_LOG(ARM11, "d_tlb init %d\n", -1); | ||
| 446 | goto d_tlb_init_error; | ||
| 447 | } | ||
| 448 | |||
| 449 | c_desc = &desc->main_d_cache; | ||
| 450 | if (mmu_cache_init (MAIN_D_CACHE (), c_desc->width, c_desc->way, | ||
| 451 | c_desc->set, c_desc->w_mode)) { | ||
| 452 | ERROR_LOG(ARM11, "main_d_cache init %d\n", -1); | ||
| 453 | goto main_d_cache_init_error; | ||
| 454 | } | ||
| 455 | |||
| 456 | c_desc = &desc->mini_d_cache; | ||
| 457 | if (mmu_cache_init (MINI_D_CACHE (), c_desc->width, c_desc->way, | ||
| 458 | c_desc->set, c_desc->w_mode)) { | ||
| 459 | ERROR_LOG(ARM11, "mini_d_cache init %d\n", -1); | ||
| 460 | goto mini_d_cache_init_error; | ||
| 461 | } | ||
| 462 | |||
| 463 | if (mmu_wb_init (WB (), desc->wb.num, desc->wb.nb)) { | ||
| 464 | ERROR_LOG(ARM11, "wb init %d\n", -1); | ||
| 465 | goto wb_init_error; | ||
| 466 | } | ||
| 467 | #if 0 | ||
| 468 | if (mmu_rb_init (RB (), desc->rb)) { | ||
| 469 | ERROR_LOG(ARM11, "rb init %d\n", -1); | ||
| 470 | goto rb_init_error; | ||
| 471 | } | ||
| 472 | #endif | ||
| 473 | |||
| 474 | return 0; | ||
| 475 | #if 0 | ||
| 476 | rb_init_error: | ||
| 477 | mmu_wb_exit (WB ()); | ||
| 478 | #endif | ||
| 479 | wb_init_error: | ||
| 480 | mmu_cache_exit (MINI_D_CACHE ()); | ||
| 481 | mini_d_cache_init_error: | ||
| 482 | mmu_cache_exit (MAIN_D_CACHE ()); | ||
| 483 | main_d_cache_init_error: | ||
| 484 | mmu_tlb_exit (D_TLB ()); | ||
| 485 | d_tlb_init_error: | ||
| 486 | mmu_cache_exit (I_CACHE ()); | ||
| 487 | i_cache_init_error: | ||
| 488 | mmu_tlb_exit (I_TLB ()); | ||
| 489 | i_tlb_init_error: | ||
| 490 | return -1; | ||
| 491 | } | ||
| 492 | |||
| 493 | unsigned | ||
| 494 | xscale_cp15_exit (ARMul_State * state) | ||
| 495 | { | ||
| 496 | //mmu_rb_exit(RB()); | ||
| 497 | mmu_wb_exit (WB ()); | ||
| 498 | mmu_cache_exit (MINI_D_CACHE ()); | ||
| 499 | mmu_cache_exit (MAIN_D_CACHE ()); | ||
| 500 | mmu_tlb_exit (D_TLB ()); | ||
| 501 | mmu_cache_exit (I_CACHE ()); | ||
| 502 | mmu_tlb_exit (I_TLB ()); | ||
| 503 | return 0; | ||
| 504 | }; | ||
| 505 | |||
| 506 | |||
| 507 | static fault_t | ||
| 508 | xscale_mmu_load_instr (ARMul_State * state, ARMword va, | ||
| 509 | ARMword * instr) | ||
| 510 | { | ||
| 511 | fault_t fault; | ||
| 512 | tlb_entry_t *tlb; | ||
| 513 | cache_line_t *cache; | ||
| 514 | int c; //cache bit | ||
| 515 | ARMword pa; //physical addr | ||
| 516 | |||
| 517 | static int debug_count = 0; //used for debug | ||
| 518 | |||
| 519 | DEBUG_LOG(ARM11, "va = %x\n", va); | ||
| 520 | |||
| 521 | va = mmu_pid_va_map (va); | ||
| 522 | if (MMU_Enabled) { | ||
| 523 | /*align check */ | ||
| 524 | if ((va & (INSN_SIZE - 1)) && MMU_Aligned) { | ||
| 525 | DEBUG_LOG(ARM11, "align\n"); | ||
| 526 | return ALIGNMENT_FAULT; | ||
| 527 | } | ||
| 528 | else | ||
| 529 | va &= ~(INSN_SIZE - 1); | ||
| 530 | |||
| 531 | /*translate tlb */ | ||
| 532 | fault = translate (state, va, I_TLB (), &tlb); | ||
| 533 | if (fault) { | ||
| 534 | DEBUG_LOG(ARM11, "translate\n"); | ||
| 535 | return fault; | ||
| 536 | } | ||
| 537 | |||
| 538 | /*check access */ | ||
| 539 | fault = check_access (state, va, tlb, 1); | ||
| 540 | if (fault) { | ||
| 541 | DEBUG_LOG(ARM11, "check_fault\n"); | ||
| 542 | return fault; | ||
| 543 | } | ||
| 544 | } | ||
| 545 | //chy 2003-09-02 for test, don't use cache ????? | ||
| 546 | #if 0 | ||
| 547 | /*search cache no matter MMU enabled/disabled */ | ||
| 548 | cache = mmu_cache_search (state, I_CACHE (), va); | ||
| 549 | if (cache) { | ||
| 550 | *instr = cache->data[va_cache_index (va, I_CACHE ())]; | ||
| 551 | return 0; | ||
| 552 | } | ||
| 553 | #endif | ||
| 554 | /*if MMU disabled or C flag is set alloc cache */ | ||
| 555 | if (MMU_Disabled) { | ||
| 556 | c = 1; | ||
| 557 | pa = va; | ||
| 558 | } | ||
| 559 | else { | ||
| 560 | c = tlb_c_flag (tlb); | ||
| 561 | pa = tlb_va_to_pa (tlb, va); | ||
| 562 | } | ||
| 563 | |||
| 564 | //chy 2003-09-03 only read mem, don't use cache now,will change later ???? | ||
| 565 | //*instr = mem_read_word (state, pa); | ||
| 566 | bus_read(32, pa, instr); | ||
| 567 | #if 0 | ||
| 568 | //----------------------------------------------------------- | ||
| 569 | //chy 2003-09-02 for test???? | ||
| 570 | if (pa >= 0xa01c8000 && pa <= 0xa01c8020) { | ||
| 571 | printf ("SKYEYE:load_instr: pa %x, va %x,instr %x, R15 %x\n", | ||
| 572 | pa, va, *instr, state->Reg[15]); | ||
| 573 | } | ||
| 574 | |||
| 575 | //---------------------------------------------------------------------- | ||
| 576 | #endif | ||
| 577 | return NO_FAULT; | ||
| 578 | |||
| 579 | if (c) { | ||
| 580 | int index; | ||
| 581 | |||
| 582 | debug_count++; | ||
| 583 | cache = mmu_cache_alloc (state, I_CACHE (), va, pa); | ||
| 584 | index = va_cache_index (va, I_CACHE ()); | ||
| 585 | *instr = cache->data[va_cache_index (va, I_CACHE ())]; | ||
| 586 | } | ||
| 587 | else | ||
| 588 | //*instr = mem_read_word (state, pa); | ||
| 589 | bus_read(32, pa, instr); | ||
| 590 | |||
| 591 | return NO_FAULT; | ||
| 592 | }; | ||
| 593 | |||
| 594 | |||
| 595 | |||
| 596 | static fault_t | ||
| 597 | xscale_mmu_read_byte (ARMul_State * state, ARMword virt_addr, | ||
| 598 | ARMword * data) | ||
| 599 | { | ||
| 600 | //ARMword temp,offset; | ||
| 601 | fault_t fault; | ||
| 602 | fault = xscale_mmu_read (state, virt_addr, data, ARM_BYTE_TYPE); | ||
| 603 | return fault; | ||
| 604 | } | ||
| 605 | |||
| 606 | static fault_t | ||
| 607 | xscale_mmu_read_halfword (ARMul_State * state, ARMword virt_addr, | ||
| 608 | ARMword * data) | ||
| 609 | { | ||
| 610 | //ARMword temp,offset; | ||
| 611 | fault_t fault; | ||
| 612 | fault = xscale_mmu_read (state, virt_addr, data, ARM_HALFWORD_TYPE); | ||
| 613 | return fault; | ||
| 614 | } | ||
| 615 | |||
| 616 | static fault_t | ||
| 617 | xscale_mmu_read_word (ARMul_State * state, ARMword virt_addr, | ||
| 618 | ARMword * data) | ||
| 619 | { | ||
| 620 | return xscale_mmu_read (state, virt_addr, data, ARM_WORD_TYPE); | ||
| 621 | } | ||
| 622 | |||
| 623 | |||
| 624 | |||
| 625 | |||
| 626 | static fault_t | ||
| 627 | xscale_mmu_read (ARMul_State * state, ARMword va, ARMword * data, | ||
| 628 | ARMword datatype) | ||
| 629 | { | ||
| 630 | fault_t fault; | ||
| 631 | // rb_entry_t *rb; | ||
| 632 | tlb_entry_t *tlb; | ||
| 633 | cache_line_t *cache; | ||
| 634 | ARMword pa, real_va, temp, offset; | ||
| 635 | //chy 2003-09-02 for test ???? | ||
| 636 | static unsigned chyst1 = 0, chyst2 = 0; | ||
| 637 | |||
| 638 | DEBUG_LOG(ARM11, "va = %x\n", va); | ||
| 639 | |||
| 640 | va = mmu_pid_va_map (va); | ||
| 641 | real_va = va; | ||
| 642 | /*if MMU disabled, memory_read */ | ||
| 643 | if (MMU_Disabled) { | ||
| 644 | //*data = mem_read_word(state, va); | ||
| 645 | if (datatype == ARM_BYTE_TYPE) | ||
| 646 | //*data = mem_read_byte (state, va); | ||
| 647 | bus_read(8, va, data); | ||
| 648 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 649 | //*data = mem_read_halfword (state, va); | ||
| 650 | bus_read(16, va, data); | ||
| 651 | else if (datatype == ARM_WORD_TYPE) | ||
| 652 | //*data = mem_read_word (state, va); | ||
| 653 | bus_read(32, va, data); | ||
| 654 | else { | ||
| 655 | printf ("SKYEYE:1 xscale_mmu_read error: unknown data type %d\n", datatype); | ||
| 656 | // skyeye_exit (-1); | ||
| 657 | } | ||
| 658 | |||
| 659 | return NO_FAULT; | ||
| 660 | } | ||
| 661 | |||
| 662 | /*align check */ | ||
| 663 | if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) || | ||
| 664 | ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) { | ||
| 665 | DEBUG_LOG(ARM11, "align\n"); | ||
| 666 | return ALIGNMENT_FAULT; | ||
| 667 | } // else | ||
| 668 | |||
| 669 | va &= ~(WORD_SIZE - 1); | ||
| 670 | |||
| 671 | /*translate va to tlb */ | ||
| 672 | fault = translate (state, va, D_TLB (), &tlb); | ||
| 673 | if (fault) { | ||
| 674 | DEBUG_LOG(ARM11, "translate\n"); | ||
| 675 | return fault; | ||
| 676 | } | ||
| 677 | /*check access permission */ | ||
| 678 | fault = check_access (state, va, tlb, 1); | ||
| 679 | if (fault) | ||
| 680 | return fault; | ||
| 681 | |||
| 682 | #if 0 | ||
| 683 | //------------------------------------------------ | ||
| 684 | //chy 2003-09-02 for test only ,should commit ???? | ||
| 685 | if (datatype == ARM_WORD_TYPE) { | ||
| 686 | if (real_va >= 0xffff0000 && real_va <= 0xffff0020) { | ||
| 687 | pa = tlb_va_to_pa (tlb, va); | ||
| 688 | *data = mem_read_word (state, pa); | ||
| 689 | chyst1++; | ||
| 690 | printf ("**SKYEYE:mmu_read word %d: pa %x, va %x, data %x, R15 %x\n", chyst1, pa, real_va, *data, state->Reg[15]); | ||
| 691 | /* | ||
| 692 | cache==mmu_cache_search(state,MAIN_D_CACHE(),va); | ||
| 693 | if(cache){ | ||
| 694 | *data = cache->data[va_cache_index(va, MAIN_D_CACHE())]; | ||
| 695 | printf("cached data %x\n",*data); | ||
| 696 | }else printf("no cached data\n"); | ||
| 697 | */ | ||
| 698 | } | ||
| 699 | } | ||
| 700 | //------------------------------------------------- | ||
| 701 | #endif | ||
| 702 | #if 0 | ||
| 703 | /*search in read buffer */ | ||
| 704 | rb = mmu_rb_search (RB (), va); | ||
| 705 | if (rb) { | ||
| 706 | if (rb->fault) | ||
| 707 | return rb->fault; | ||
| 708 | *data = rb->data[(va & (rb_masks[rb->type] - 1)) >> WORD_SHT]; | ||
| 709 | goto datatrans; | ||
| 710 | //return 0; | ||
| 711 | }; | ||
| 712 | #endif | ||
| 713 | |||
| 714 | /*2004-07-19 chy: add support of xscale MMU CacheDisabled option */ | ||
| 715 | if (MMU_CacheDisabled) { | ||
| 716 | //if(1){ can be used to test cache error | ||
| 717 | /*get phy_addr */ | ||
| 718 | pa = tlb_va_to_pa (tlb, real_va); | ||
| 719 | if (datatype == ARM_BYTE_TYPE) | ||
| 720 | //*data = mem_read_byte (state, pa); | ||
| 721 | bus_read(8, pa, data); | ||
| 722 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 723 | //*data = mem_read_halfword (state, pa); | ||
| 724 | bus_read(16, pa, data); | ||
| 725 | else if (datatype == ARM_WORD_TYPE) | ||
| 726 | //*data = mem_read_word (state, pa); | ||
| 727 | bus_read(32, pa, data); | ||
| 728 | else { | ||
| 729 | printf ("SKYEYE:MMU_CacheDisabled xscale_mmu_read error: unknown data type %d\n", datatype); | ||
| 730 | // skyeye_exit (-1); | ||
| 731 | } | ||
| 732 | return NO_FAULT; | ||
| 733 | } | ||
| 734 | |||
| 735 | |||
| 736 | /*search main cache */ | ||
| 737 | cache = mmu_cache_search (state, MAIN_D_CACHE (), va); | ||
| 738 | if (cache) { | ||
| 739 | *data = cache->data[va_cache_index (va, MAIN_D_CACHE ())]; | ||
| 740 | #if 0 | ||
| 741 | //------------------------------------------------------------------------ | ||
| 742 | //chy 2003-09-02 for test only ,should commit ???? | ||
| 743 | if (real_va >= 0xffff0000 && real_va <= 0xffff0020) { | ||
| 744 | pa = tlb_va_to_pa (tlb, va); | ||
| 745 | chyst2++; | ||
| 746 | printf ("**SKYEYE:mmu_read wordk:cache %d: pa %x, va %x, data %x, R15 %x\n", chyst2, pa, real_va, *data, state->Reg[15]); | ||
| 747 | } | ||
| 748 | //------------------------------------------------------------------- | ||
| 749 | #endif | ||
| 750 | goto datatrans; | ||
| 751 | //return 0; | ||
| 752 | } | ||
| 753 | //chy 2003-08-24, now maybe we don't need minidcache ???? | ||
| 754 | #if 0 | ||
| 755 | /*search mini cache */ | ||
| 756 | cache = mmu_cache_search (state, MINI_D_CACHE (), va); | ||
| 757 | if (cache) { | ||
| 758 | *data = cache->data[va_cache_index (va, MINI_D_CACHE ())]; | ||
| 759 | goto datatrans; | ||
| 760 | //return 0; | ||
| 761 | } | ||
| 762 | #endif | ||
| 763 | /*get phy_addr */ | ||
| 764 | pa = tlb_va_to_pa (tlb, va); | ||
| 765 | //chy 2003-08-24 , in xscale it means what ????? | ||
| 766 | #if 0 | ||
| 767 | if ((pa >= 0xe0000000) && (pa < 0xe8000000)) { | ||
| 768 | |||
| 769 | if (tlb_c_flag (tlb)) { | ||
| 770 | if (tlb_b_flag (tlb)) { | ||
| 771 | mmu_cache_soft_flush (state, MAIN_D_CACHE (), | ||
| 772 | pa); | ||
| 773 | } | ||
| 774 | else { | ||
| 775 | mmu_cache_soft_flush (state, MINI_D_CACHE (), | ||
| 776 | pa); | ||
| 777 | } | ||
| 778 | } | ||
| 779 | return 0; | ||
| 780 | } | ||
| 781 | #endif | ||
| 782 | //chy 2003-08-24, check phy addr | ||
| 783 | //ywc 2004-11-30, inactive this check because of using 0xc0000000 as the framebuffer start address | ||
| 784 | /* | ||
| 785 | if(pa >= 0xb0000000){ | ||
| 786 | printf("SKYEYE:xscale_mmu_read: phy address 0x%x error,reg[15] 0x%x\n",pa,state->Reg[15]); | ||
| 787 | return 0; | ||
| 788 | } | ||
| 789 | */ | ||
| 790 | |||
| 791 | //chy 2003-08-24, now maybe we don't need wb ???? | ||
| 792 | #if 0 | ||
| 793 | /*if Buffer, drain Write Buffer first */ | ||
| 794 | if (tlb_b_flag (tlb)) | ||
| 795 | mmu_wb_drain_all (state, WB ()); | ||
| 796 | #endif | ||
| 797 | /*alloc cache or mem_read */ | ||
| 798 | if (tlb_c_flag (tlb) && MMU_DCacheEnabled) { | ||
| 799 | cache_s *cache_t; | ||
| 800 | |||
| 801 | if (tlb_b_flag (tlb)) | ||
| 802 | cache_t = MAIN_D_CACHE (); | ||
| 803 | else | ||
| 804 | cache_t = MINI_D_CACHE (); | ||
| 805 | cache = mmu_cache_alloc (state, cache_t, va, pa); | ||
| 806 | *data = cache->data[va_cache_index (va, cache_t)]; | ||
| 807 | } | ||
| 808 | else { | ||
| 809 | //*data = mem_read_word(state, pa); | ||
| 810 | if (datatype == ARM_BYTE_TYPE) | ||
| 811 | //*data = mem_read_byte (state, pa | (real_va & 3)); | ||
| 812 | bus_read(8, pa | (real_va & 3), data); | ||
| 813 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 814 | //*data = mem_read_halfword (state, pa | (real_va & 2)); | ||
| 815 | bus_read(16, pa | (real_va & 2), data); | ||
| 816 | else if (datatype == ARM_WORD_TYPE) | ||
| 817 | //*data = mem_read_word (state, pa); | ||
| 818 | bus_read(32, pa, data); | ||
| 819 | else { | ||
| 820 | printf ("SKYEYE:2 xscale_mmu_read error: unknown data type %d\n", datatype); | ||
| 821 | // skyeye_exit (-1); | ||
| 822 | } | ||
| 823 | return NO_FAULT; | ||
| 824 | } | ||
| 825 | |||
| 826 | |||
| 827 | datatrans: | ||
| 828 | if (datatype == ARM_HALFWORD_TYPE) { | ||
| 829 | temp = *data; | ||
| 830 | offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */ | ||
| 831 | *data = (temp >> offset) & 0xffff; | ||
| 832 | } | ||
| 833 | else if (datatype == ARM_BYTE_TYPE) { | ||
| 834 | temp = *data; | ||
| 835 | offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */ | ||
| 836 | *data = (temp >> offset & 0xffL); | ||
| 837 | } | ||
| 838 | end: | ||
| 839 | return NO_FAULT; | ||
| 840 | } | ||
| 841 | |||
| 842 | |||
| 843 | static fault_t | ||
| 844 | xscale_mmu_write_byte (ARMul_State * state, ARMword virt_addr, | ||
| 845 | ARMword data) | ||
| 846 | { | ||
| 847 | return xscale_mmu_write (state, virt_addr, data, ARM_BYTE_TYPE); | ||
| 848 | } | ||
| 849 | |||
| 850 | static fault_t | ||
| 851 | xscale_mmu_write_halfword (ARMul_State * state, ARMword virt_addr, | ||
| 852 | ARMword data) | ||
| 853 | { | ||
| 854 | return xscale_mmu_write (state, virt_addr, data, ARM_HALFWORD_TYPE); | ||
| 855 | } | ||
| 856 | |||
| 857 | static fault_t | ||
| 858 | xscale_mmu_write_word (ARMul_State * state, ARMword virt_addr, | ||
| 859 | ARMword data) | ||
| 860 | { | ||
| 861 | return xscale_mmu_write (state, virt_addr, data, ARM_WORD_TYPE); | ||
| 862 | } | ||
| 863 | |||
| 864 | |||
| 865 | |||
| 866 | static fault_t | ||
| 867 | xscale_mmu_write (ARMul_State * state, ARMword va, ARMword data, | ||
| 868 | ARMword datatype) | ||
| 869 | { | ||
| 870 | tlb_entry_t *tlb; | ||
| 871 | cache_line_t *cache; | ||
| 872 | cache_s *cache_t; | ||
| 873 | int b; | ||
| 874 | ARMword pa, real_va, temp, offset; | ||
| 875 | fault_t fault; | ||
| 876 | |||
| 877 | ARMword index; | ||
| 878 | //chy 2003-09-02 for test ???? | ||
| 879 | // static unsigned chyst1=0,chyst2=0; | ||
| 880 | |||
| 881 | DEBUG_LOG(ARM11, "va = %x, val = %x\n", va, data); | ||
| 882 | va = mmu_pid_va_map (va); | ||
| 883 | real_va = va; | ||
| 884 | |||
| 885 | if (MMU_Disabled) { | ||
| 886 | //mem_write_word(state, va, data); | ||
| 887 | if (datatype == ARM_BYTE_TYPE) | ||
| 888 | //mem_write_byte (state, va, data); | ||
| 889 | bus_write(8, va, data); | ||
| 890 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 891 | //mem_write_halfword (state, va, data); | ||
| 892 | bus_write(16, va, data); | ||
| 893 | else if (datatype == ARM_WORD_TYPE) | ||
| 894 | //mem_write_word (state, va, data); | ||
| 895 | bus_write(32, va, data); | ||
| 896 | else { | ||
| 897 | printf ("SKYEYE:1 xscale_mmu_write error: unknown data type %d\n", datatype); | ||
| 898 | // skyeye_exit (-1); | ||
| 899 | } | ||
| 900 | |||
| 901 | return NO_FAULT; | ||
| 902 | } | ||
| 903 | /*align check */ | ||
| 904 | if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) || | ||
| 905 | ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) { | ||
| 906 | DEBUG_LOG(ARM11, "align\n"); | ||
| 907 | return ALIGNMENT_FAULT; | ||
| 908 | } //else | ||
| 909 | va &= ~(WORD_SIZE - 1); | ||
| 910 | /*tlb translate */ | ||
| 911 | fault = translate (state, va, D_TLB (), &tlb); | ||
| 912 | if (fault) { | ||
| 913 | DEBUG_LOG(ARM11, "translate\n"); | ||
| 914 | return fault; | ||
| 915 | } | ||
| 916 | /*tlb check access */ | ||
| 917 | fault = check_access (state, va, tlb, 0); | ||
| 918 | if (fault) { | ||
| 919 | DEBUG_LOG(ARM11, "check_access\n"); | ||
| 920 | return fault; | ||
| 921 | } | ||
| 922 | |||
| 923 | /*2004-07-19 chy: add support for xscale MMU_CacheDisabled */ | ||
| 924 | if (MMU_CacheDisabled) { | ||
| 925 | //if(1){ can be used to test the cache error | ||
| 926 | /*get phy_addr */ | ||
| 927 | pa = tlb_va_to_pa (tlb, real_va); | ||
| 928 | if (datatype == ARM_BYTE_TYPE) | ||
| 929 | //mem_write_byte (state, pa, data); | ||
| 930 | bus_write(8, pa, data); | ||
| 931 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 932 | //mem_write_halfword (state, pa, data); | ||
| 933 | bus_write(16, pa, data); | ||
| 934 | else if (datatype == ARM_WORD_TYPE) | ||
| 935 | //mem_write_word (state, pa, data); | ||
| 936 | bus_write(32, pa , data); | ||
| 937 | else { | ||
| 938 | printf ("SKYEYE:MMU_CacheDisabled xscale_mmu_write error: unknown data type %d\n", datatype); | ||
| 939 | // skyeye_exit (-1); | ||
| 940 | } | ||
| 941 | |||
| 942 | return NO_FAULT; | ||
| 943 | } | ||
| 944 | |||
| 945 | /*search main cache */ | ||
| 946 | b = tlb_b_flag (tlb); | ||
| 947 | pa = tlb_va_to_pa (tlb, va); | ||
| 948 | cache = mmu_cache_search (state, MAIN_D_CACHE (), va); | ||
| 949 | if (cache) { | ||
| 950 | cache_t = MAIN_D_CACHE (); | ||
| 951 | goto has_cache; | ||
| 952 | } | ||
| 953 | //chy 2003-08-24, now maybe we don't need minidcache ???? | ||
| 954 | #if 0 | ||
| 955 | /*search mini cache */ | ||
| 956 | cache = mmu_cache_search (state, MINI_D_CACHE (), va); | ||
| 957 | if (cache) { | ||
| 958 | cache_t = MINI_D_CACHE (); | ||
| 959 | goto has_cache; | ||
| 960 | } | ||
| 961 | #endif | ||
| 962 | b = tlb_b_flag (tlb); | ||
| 963 | pa = tlb_va_to_pa (tlb, va); | ||
| 964 | //chy 2003-08-24, check phy addr 0xa0000000, size 0x04000000 | ||
| 965 | //ywc 2004-11-30, inactive this check because of using 0xc0000000 as the framebuffer start address | ||
| 966 | /* | ||
| 967 | if(pa >= 0xb0000000){ | ||
| 968 | printf("SKYEYE:xscale_mmu_write phy address 0x%x error,reg[15] 0x%x\n",pa,state->Reg[15]); | ||
| 969 | return 0; | ||
| 970 | } | ||
| 971 | */ | ||
| 972 | |||
| 973 | //chy 2003-08-24, now maybe we don't need WB ???? | ||
| 974 | #if 0 | ||
| 975 | if (b) { | ||
| 976 | if (MMU_WBEnabled) { | ||
| 977 | if (datatype == ARM_WORD_TYPE) | ||
| 978 | mmu_wb_write_bytes (state, WB (), pa, &data, | ||
| 979 | 4); | ||
| 980 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 981 | mmu_wb_write_bytes (state, WB (), | ||
| 982 | (pa | (real_va & 2)), | ||
| 983 | &data, 2); | ||
| 984 | else if (datatype == ARM_BYTE_TYPE) | ||
| 985 | mmu_wb_write_bytes (state, WB (), | ||
| 986 | (pa | (real_va & 3)), | ||
| 987 | &data, 1); | ||
| 988 | |||
| 989 | } | ||
| 990 | else { | ||
| 991 | if (datatype == ARM_WORD_TYPE) | ||
| 992 | mem_write_word (state, pa, data); | ||
| 993 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 994 | mem_write_halfword (state, | ||
| 995 | (pa | (real_va & 2)), | ||
| 996 | data); | ||
| 997 | else if (datatype == ARM_BYTE_TYPE) | ||
| 998 | mem_write_byte (state, (pa | (real_va & 3)), | ||
| 999 | data); | ||
| 1000 | } | ||
| 1001 | } | ||
| 1002 | else { | ||
| 1003 | |||
| 1004 | mmu_wb_drain_all (state, WB ()); | ||
| 1005 | |||
| 1006 | if (datatype == ARM_WORD_TYPE) | ||
| 1007 | mem_write_word (state, pa, data); | ||
| 1008 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 1009 | mem_write_halfword (state, (pa | (real_va & 2)), | ||
| 1010 | data); | ||
| 1011 | else if (datatype == ARM_BYTE_TYPE) | ||
| 1012 | mem_write_byte (state, (pa | (real_va & 3)), data); | ||
| 1013 | } | ||
| 1014 | #endif | ||
| 1015 | //chy 2003-08-24, just write phy addr | ||
| 1016 | if (datatype == ARM_WORD_TYPE) | ||
| 1017 | //mem_write_word (state, pa, data); | ||
| 1018 | bus_write(32, pa, data); | ||
| 1019 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 1020 | //mem_write_halfword (state, (pa | (real_va & 2)), data); | ||
| 1021 | bus_write(16, pa | (real_va & 2), data); | ||
| 1022 | else if (datatype == ARM_BYTE_TYPE) | ||
| 1023 | //mem_write_byte (state, (pa | (real_va & 3)), data); | ||
| 1024 | bus_write(8, (pa | (real_va & 3)), data); | ||
| 1025 | #if 0 | ||
| 1026 | //------------------------------------------------------------- | ||
| 1027 | //chy 2003-09-02 for test ???? | ||
| 1028 | if (datatype == ARM_WORD_TYPE) { | ||
| 1029 | if (real_va >= 0xffff0000 && real_va <= 0xffff0020) { | ||
| 1030 | printf ("**SKYEYE:mmu_write word: pa %x, va %x, data %x, R15 %x \n", pa, real_va, data, state->Reg[15]); | ||
| 1031 | } | ||
| 1032 | } | ||
| 1033 | //-------------------------------------------------------------- | ||
| 1034 | #endif | ||
| 1035 | return NO_FAULT; | ||
| 1036 | |||
| 1037 | has_cache: | ||
| 1038 | index = va_cache_index (va, cache_t); | ||
| 1039 | //cache->data[index] = data; | ||
| 1040 | |||
| 1041 | if (datatype == ARM_WORD_TYPE) | ||
| 1042 | cache->data[index] = data; | ||
| 1043 | else if (datatype == ARM_HALFWORD_TYPE) { | ||
| 1044 | temp = cache->data[index]; | ||
| 1045 | offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */ | ||
| 1046 | cache->data[index] = | ||
| 1047 | (temp & ~(0xffffL << offset)) | ((data & 0xffffL) << | ||
| 1048 | offset); | ||
| 1049 | } | ||
| 1050 | else if (datatype == ARM_BYTE_TYPE) { | ||
| 1051 | temp = cache->data[index]; | ||
| 1052 | offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */ | ||
| 1053 | cache->data[index] = | ||
| 1054 | (temp & ~(0xffL << offset)) | ((data & 0xffL) << | ||
| 1055 | offset); | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | if (index < (cache_t->width >> (WORD_SHT + 1))) | ||
| 1059 | cache->tag |= TAG_FIRST_HALF_DIRTY; | ||
| 1060 | else | ||
| 1061 | cache->tag |= TAG_LAST_HALF_DIRTY; | ||
| 1062 | //------------------------------------------------------------- | ||
| 1063 | //chy 2003-09-03 be sure the changed value will be in memory as soon as possible, so I cache can get the newest value | ||
| 1064 | #if 0 | ||
| 1065 | { | ||
| 1066 | if (datatype == ARM_WORD_TYPE) | ||
| 1067 | mem_write_word (state, pa, data); | ||
| 1068 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 1069 | mem_write_halfword (state, (pa | (real_va & 2)), | ||
| 1070 | data); | ||
| 1071 | else if (datatype == ARM_BYTE_TYPE) | ||
| 1072 | mem_write_byte (state, (pa | (real_va & 3)), data); | ||
| 1073 | } | ||
| 1074 | #endif | ||
| 1075 | #if 0 | ||
| 1076 | //chy 2003-09-02 for test ???? | ||
| 1077 | if (datatype == ARM_WORD_TYPE) { | ||
| 1078 | if (real_va >= 0xffff0000 && real_va <= 0xffff0020) { | ||
| 1079 | printf ("**SKYEYE:mmu_write word:cache: pa %x, va %x, data %x, R15 %x\n", pa, real_va, data, state->Reg[15]); | ||
| 1080 | } | ||
| 1081 | } | ||
| 1082 | //------------------------------------------------------------- | ||
| 1083 | #endif | ||
| 1084 | if (datatype == ARM_WORD_TYPE) | ||
| 1085 | //mem_write_word (state, pa, data); | ||
| 1086 | bus_write(32, pa, data); | ||
| 1087 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 1088 | //mem_write_halfword (state, (pa | (real_va & 2)), data); | ||
| 1089 | bus_write(16, pa | (real_va & 2), data); | ||
| 1090 | else if (datatype == ARM_BYTE_TYPE) | ||
| 1091 | //mem_write_byte (state, (pa | (real_va & 3)), data); | ||
| 1092 | bus_write(8, (pa | (real_va & 3)), data); | ||
| 1093 | return NO_FAULT; | ||
| 1094 | } | ||
| 1095 | |||
| 1096 | ARMword xscale_cp15_mrc (ARMul_State * state, | ||
| 1097 | unsigned type, ARMword instr, ARMword * value) | ||
| 1098 | { | ||
| 1099 | return xscale_mmu_mrc (state, instr, value); | ||
| 1100 | } | ||
| 1101 | |||
| 1102 | ARMword xscale_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value) | ||
| 1103 | { | ||
| 1104 | ARMword data; | ||
| 1105 | unsigned opcode_2 = BITS (5, 7); | ||
| 1106 | unsigned CRm = BITS (0, 3); | ||
| 1107 | unsigned reg = BITS (16, 19); | ||
| 1108 | unsigned result; | ||
| 1109 | mmu_regnum_t creg = (mmu_regnum_t)reg; | ||
| 1110 | |||
| 1111 | /* | ||
| 1112 | printf("SKYEYE: xscale_cp15_mrc:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n",opcode_2,CRm,reg,\ | ||
| 1113 | state->Reg[15], instr); | ||
| 1114 | */ | ||
| 1115 | switch (creg) { | ||
| 1116 | case MMU_ID: //XSCALE_CP15 | ||
| 1117 | //printf("mmu_mrc read ID \n"); | ||
| 1118 | data = (opcode_2 ? state->mmu.cache_type : state->cpu-> | ||
| 1119 | cpu_val); | ||
| 1120 | break; | ||
| 1121 | case MMU_CONTROL: //XSCALE_CP15_AUX_CONTROL | ||
| 1122 | //printf("mmu_mrc read CONTROL \n"); | ||
| 1123 | data = (opcode_2 ? state->mmu.aux_control : state->mmu. | ||
| 1124 | control); | ||
| 1125 | break; | ||
| 1126 | case MMU_TRANSLATION_TABLE_BASE: | ||
| 1127 | //printf("mmu_mrc read TTB \n"); | ||
| 1128 | data = state->mmu.translation_table_base; | ||
| 1129 | break; | ||
| 1130 | case MMU_DOMAIN_ACCESS_CONTROL: | ||
| 1131 | //printf("mmu_mrc read DACR \n"); | ||
| 1132 | data = state->mmu.domain_access_control; | ||
| 1133 | break; | ||
| 1134 | case MMU_FAULT_STATUS: | ||
| 1135 | //printf("mmu_mrc read FSR \n"); | ||
| 1136 | data = state->mmu.fault_status; | ||
| 1137 | break; | ||
| 1138 | case MMU_FAULT_ADDRESS: | ||
| 1139 | //printf("mmu_mrc read FAR \n"); | ||
| 1140 | data = state->mmu.fault_address; | ||
| 1141 | break; | ||
| 1142 | case MMU_PID: | ||
| 1143 | //printf("mmu_mrc read PID \n"); | ||
| 1144 | data = state->mmu.process_id; | ||
| 1145 | case XSCALE_CP15_COPRO_ACCESS: | ||
| 1146 | //printf("xscale cp15 read coprocessor access\n"); | ||
| 1147 | data = state->mmu.copro_access; | ||
| 1148 | break; | ||
| 1149 | default: | ||
| 1150 | data = 0; | ||
| 1151 | printf ("SKYEYE: xscale_cp15_mrc read UNKNOWN - reg %d, pc 0x%x\n", creg, state->Reg[15]); | ||
| 1152 | // skyeye_exit (-1); | ||
| 1153 | break; | ||
| 1154 | } | ||
| 1155 | *value = data; | ||
| 1156 | //printf("SKYEYE: xscale_cp15_mrc:end value 0x%x\n",data); | ||
| 1157 | return ARMul_DONE; | ||
| 1158 | } | ||
| 1159 | |||
| 1160 | void xscale_cp15_cache_ops (ARMul_State * state, ARMword instr, ARMword value) | ||
| 1161 | { | ||
| 1162 | //chy: 2003-08-24 now, the BTB isn't simualted ....???? | ||
| 1163 | |||
| 1164 | unsigned CRm, OPC_2; | ||
| 1165 | |||
| 1166 | CRm = BITS (0, 3); | ||
| 1167 | OPC_2 = BITS (5, 7); | ||
| 1168 | //err_msg("SKYEYE: xscale cp15_cache_ops:OPC_2 = 0x%x CRm = 0x%x, Reg15 0x%x\n", OPC_2, CRm,state->Reg[15]); | ||
| 1169 | |||
| 1170 | if (OPC_2 == 0 && CRm == 7) { | ||
| 1171 | mmu_cache_invalidate_all (state, I_CACHE ()); | ||
| 1172 | mmu_cache_invalidate_all (state, MAIN_D_CACHE ()); | ||
| 1173 | return; | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | if (OPC_2 == 0 && CRm == 5) { | ||
| 1177 | mmu_cache_invalidate_all (state, I_CACHE ()); | ||
| 1178 | return; | ||
| 1179 | } | ||
| 1180 | if (OPC_2 == 1 && CRm == 5) { | ||
| 1181 | mmu_cache_invalidate (state, I_CACHE (), value); | ||
| 1182 | return; | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | if (OPC_2 == 0 && CRm == 6) { | ||
| 1186 | mmu_cache_invalidate_all (state, MAIN_D_CACHE ()); | ||
| 1187 | return; | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | if (OPC_2 == 1 && CRm == 6) { | ||
| 1191 | mmu_cache_invalidate (state, MAIN_D_CACHE (), value); | ||
| 1192 | return; | ||
| 1193 | } | ||
| 1194 | |||
| 1195 | if (OPC_2 == 1 && CRm == 0xa) { | ||
| 1196 | mmu_cache_clean (state, MAIN_D_CACHE (), value); | ||
| 1197 | return; | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | if (OPC_2 == 4 && CRm == 0xa) { | ||
| 1201 | mmu_wb_drain_all (state, WB ()); | ||
| 1202 | return; | ||
| 1203 | } | ||
| 1204 | |||
| 1205 | if (OPC_2 == 6 && CRm == 5) { | ||
| 1206 | //chy 2004-07-19 shoud fix in the future????!!!! | ||
| 1207 | //printf("SKYEYE: xscale_cp15_cache_ops:invalidate BTB CANT!!!!!!!!!!\n"); | ||
| 1208 | //exit(-1); | ||
| 1209 | return; | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | if (OPC_2 == 5 && CRm == 2) { | ||
| 1213 | //printf("SKYEYE: cp15_c_o: A L in D C, value %x, reg15 %x\n",value, state->Reg[15]); | ||
| 1214 | //exit(-1); | ||
| 1215 | //chy 2003-09-01 for test | ||
| 1216 | mmu_cache_invalidate_all (state, MAIN_D_CACHE ()); | ||
| 1217 | return; | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | ERROR_LOG(ARM11, "SKYEYE: xscale cp15_cache_ops:Unknown OPC_2 = 0x%x CRm = 0x%x, Reg15 0x%x\n", OPC_2, CRm, state->Reg[15]); | ||
| 1221 | // skyeye_exit (-1); | ||
| 1222 | } | ||
| 1223 | |||
| 1224 | static void | ||
| 1225 | xscale_cp15_tlb_ops (ARMul_State * state, ARMword instr, | ||
| 1226 | ARMword value) | ||
| 1227 | { | ||
| 1228 | int CRm, OPC_2; | ||
| 1229 | |||
| 1230 | CRm = BITS (0, 3); | ||
| 1231 | OPC_2 = BITS (5, 7); | ||
| 1232 | |||
| 1233 | |||
| 1234 | //err_msg("SKYEYE:xscale_cp15_tlb_ops:OPC_2 = 0x%x CRm = 0x%x,Reg[15] 0x%x\n", OPC_2, CRm,state->Reg[15]); | ||
| 1235 | if (OPC_2 == 0 && CRm == 0x7) { | ||
| 1236 | mmu_tlb_invalidate_all (state, I_TLB ()); | ||
| 1237 | mmu_tlb_invalidate_all (state, D_TLB ()); | ||
| 1238 | return; | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | if (OPC_2 == 0 && CRm == 0x5) { | ||
| 1242 | mmu_tlb_invalidate_all (state, I_TLB ()); | ||
| 1243 | return; | ||
| 1244 | } | ||
| 1245 | |||
| 1246 | if (OPC_2 == 1 && CRm == 0x5) { | ||
| 1247 | mmu_tlb_invalidate_entry (state, I_TLB (), value); | ||
| 1248 | return; | ||
| 1249 | } | ||
| 1250 | |||
| 1251 | if (OPC_2 == 0 && CRm == 0x6) { | ||
| 1252 | mmu_tlb_invalidate_all (state, D_TLB ()); | ||
| 1253 | return; | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | if (OPC_2 == 1 && CRm == 0x6) { | ||
| 1257 | mmu_tlb_invalidate_entry (state, D_TLB (), value); | ||
| 1258 | return; | ||
| 1259 | } | ||
| 1260 | |||
| 1261 | ERROR_LOG(ARM11, "SKYEYE:xscale_cp15_tlb_ops:Unknow OPC_2 = 0x%x CRm = 0x%x,Reg[15] 0x%x\n", OPC_2, CRm, state->Reg[15]); | ||
| 1262 | // skyeye_exit (-1); | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | |||
| 1266 | ARMword xscale_cp15_mcr (ARMul_State * state, | ||
| 1267 | unsigned type, ARMword instr, ARMword value) | ||
| 1268 | { | ||
| 1269 | return xscale_mmu_mcr (state, instr, value); | ||
| 1270 | } | ||
| 1271 | |||
| 1272 | ARMword xscale_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value) | ||
| 1273 | { | ||
| 1274 | ARMword data; | ||
| 1275 | unsigned opcode_2 = BITS (5, 7); | ||
| 1276 | unsigned CRm = BITS (0, 3); | ||
| 1277 | unsigned reg = BITS (16, 19); | ||
| 1278 | unsigned result; | ||
| 1279 | mmu_regnum_t creg = (mmu_regnum_t)reg; | ||
| 1280 | |||
| 1281 | //printf("SKYEYE: xscale_cp15_mcr: opcode_2 0x%x, CRm 0x%x, reg ox%x, value 0x%x, reg[15] 0x%x, instr 0x%x\n",opcode_2,CRm,reg, value, state->Reg[15], instr); | ||
| 1282 | |||
| 1283 | switch (creg) { | ||
| 1284 | case MMU_CONTROL: | ||
| 1285 | //printf("mmu_mcr wrote CONTROL val 0x%x \n",value); | ||
| 1286 | state->mmu.control = | ||
| 1287 | (opcode_2 ? (value & 0x33) : (value & 0x3FFF)); | ||
| 1288 | break; | ||
| 1289 | case MMU_TRANSLATION_TABLE_BASE: | ||
| 1290 | //printf("mmu_mcr wrote TTB val 0x%x \n",value); | ||
| 1291 | state->mmu.translation_table_base = value & 0xFFFFC000; | ||
| 1292 | break; | ||
| 1293 | case MMU_DOMAIN_ACCESS_CONTROL: | ||
| 1294 | //printf("mmu_mcr wrote DACR val 0x%x \n",value); | ||
| 1295 | state->mmu.domain_access_control = value; | ||
| 1296 | break; | ||
| 1297 | |||
| 1298 | case MMU_FAULT_STATUS: | ||
| 1299 | //printf("mmu_mcr wrote FS val 0x%x \n",value); | ||
| 1300 | state->mmu.fault_status = value & 0x6FF; | ||
| 1301 | break; | ||
| 1302 | case MMU_FAULT_ADDRESS: | ||
| 1303 | //printf("mmu_mcr wrote FA val 0x%x \n",value); | ||
| 1304 | state->mmu.fault_address = value; | ||
| 1305 | break; | ||
| 1306 | |||
| 1307 | case MMU_CACHE_OPS: | ||
| 1308 | // printf("mmu_mcr wrote CO val 0x%x \n",value); | ||
| 1309 | xscale_cp15_cache_ops (state, instr, value); | ||
| 1310 | break; | ||
| 1311 | case MMU_TLB_OPS: | ||
| 1312 | //printf("mmu_mcr wrote TO val 0x%x \n",value); | ||
| 1313 | xscale_cp15_tlb_ops (state, instr, value); | ||
| 1314 | break; | ||
| 1315 | case MMU_PID: | ||
| 1316 | //printf("mmu_mcr wrote PID val 0x%x \n",value); | ||
| 1317 | state->mmu.process_id = value & 0xfe000000; | ||
| 1318 | break; | ||
| 1319 | case XSCALE_CP15_COPRO_ACCESS: | ||
| 1320 | //printf("xscale cp15 write coprocessor access val 0x %x\n",value); | ||
| 1321 | state->mmu.copro_access = value & 0x3ff; | ||
| 1322 | break; | ||
| 1323 | |||
| 1324 | default: | ||
| 1325 | printf ("SKYEYE: xscale_cp15_mcr wrote UNKNOWN - reg %d, reg15 0x%x\n", creg, state->Reg[15]); | ||
| 1326 | break; | ||
| 1327 | } | ||
| 1328 | //printf("SKYEYE: xscale_cp15_mcr wrote val 0x%x\n", value); | ||
| 1329 | return 0; | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | //teawater add for arm2x86 2005.06.24------------------------------------------- | ||
| 1333 | static int xscale_mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, | ||
| 1334 | ARMword * phys_addr) | ||
| 1335 | { | ||
| 1336 | fault_t fault; | ||
| 1337 | tlb_entry_t *tlb; | ||
| 1338 | |||
| 1339 | virt_addr = mmu_pid_va_map (virt_addr); | ||
| 1340 | if (MMU_Enabled) { | ||
| 1341 | |||
| 1342 | /*align check */ | ||
| 1343 | if ((virt_addr & (WORD_SIZE - 1)) && MMU_Aligned) { | ||
| 1344 | DEBUG_LOG(ARM11, "align\n"); | ||
| 1345 | return ALIGNMENT_FAULT; | ||
| 1346 | } | ||
| 1347 | else | ||
| 1348 | virt_addr &= ~(WORD_SIZE - 1); | ||
| 1349 | |||
| 1350 | /*translate tlb */ | ||
| 1351 | fault = translate (state, virt_addr, I_TLB (), &tlb); | ||
| 1352 | if (fault) { | ||
| 1353 | DEBUG_LOG(ARM11, "translate\n"); | ||
| 1354 | return fault; | ||
| 1355 | } | ||
| 1356 | |||
| 1357 | /*check access */ | ||
| 1358 | fault = check_access (state, virt_addr, tlb, 1); | ||
| 1359 | if (fault) { | ||
| 1360 | DEBUG_LOG(ARM11, "check_fault\n"); | ||
| 1361 | return fault; | ||
| 1362 | } | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | if (MMU_Disabled) { | ||
| 1366 | *phys_addr = virt_addr; | ||
| 1367 | } | ||
| 1368 | else { | ||
| 1369 | *phys_addr = tlb_va_to_pa (tlb, virt_addr); | ||
| 1370 | } | ||
| 1371 | |||
| 1372 | return (0); | ||
| 1373 | } | ||
| 1374 | |||
| 1375 | //AJ2D-------------------------------------------------------------------------- | ||
| 1376 | |||
| 1377 | /*xscale mmu_ops_t*/ | ||
| 1378 | //mmu_ops_t xscale_mmu_ops = { | ||
| 1379 | // xscale_cp15_init, | ||
| 1380 | // xscale_cp15_exit, | ||
| 1381 | // xscale_mmu_read_byte, | ||
| 1382 | // xscale_mmu_write_byte, | ||
| 1383 | // xscale_mmu_read_halfword, | ||
| 1384 | // xscale_mmu_write_halfword, | ||
| 1385 | // xscale_mmu_read_word, | ||
| 1386 | // xscale_mmu_write_word, | ||
| 1387 | // xscale_mmu_load_instr, xscale_mmu_mcr, xscale_mmu_mrc, | ||
| 1388 | ////teawater add for arm2x86 2005.06.24------------------------------------------- | ||
| 1389 | // xscale_mmu_v2p_dbct, | ||
| 1390 | ////AJ2D-------------------------------------------------------------------------- | ||
| 1391 | //}; | ||
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h index fd574a7a1..8e71948c6 100644 --- a/src/core/arm/skyeye_common/armdefs.h +++ b/src/core/arm/skyeye_common/armdefs.h | |||
| @@ -367,7 +367,6 @@ So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model) | |||
| 367 | 367 | ||
| 368 | int verbose; /* non-zero means print various messages like the banner */ | 368 | int verbose; /* non-zero means print various messages like the banner */ |
| 369 | 369 | ||
| 370 | mmu_state_t mmu; | ||
| 371 | int mmu_inited; | 370 | int mmu_inited; |
| 372 | //mem_state_t mem; | 371 | //mem_state_t mem; |
| 373 | /*remove io_state to skyeye_mach_*.c files */ | 372 | /*remove io_state to skyeye_mach_*.c files */ |
diff --git a/src/core/arm/skyeye_common/armmmu.h b/src/core/arm/skyeye_common/armmmu.h index 818108c9c..30858f9ba 100644 --- a/src/core/arm/skyeye_common/armmmu.h +++ b/src/core/arm/skyeye_common/armmmu.h | |||
| @@ -134,121 +134,4 @@ typedef enum fault_t | |||
| 134 | 134 | ||
| 135 | } fault_t; | 135 | } fault_t; |
| 136 | 136 | ||
| 137 | typedef struct mmu_ops_s | ||
| 138 | { | ||
| 139 | /*initilization */ | ||
| 140 | int (*init) (ARMul_State * state); | ||
| 141 | /*free on exit */ | ||
| 142 | void (*exit) (ARMul_State * state); | ||
| 143 | /*read byte data */ | ||
| 144 | fault_t (*read_byte) (ARMul_State * state, ARMword va, | ||
| 145 | ARMword * data); | ||
| 146 | /*write byte data */ | ||
| 147 | fault_t (*write_byte) (ARMul_State * state, ARMword va, | ||
| 148 | ARMword data); | ||
| 149 | /*read halfword data */ | ||
| 150 | fault_t (*read_halfword) (ARMul_State * state, ARMword va, | ||
| 151 | ARMword * data); | ||
| 152 | /*write halfword data */ | ||
| 153 | fault_t (*write_halfword) (ARMul_State * state, ARMword va, | ||
| 154 | ARMword data); | ||
| 155 | /*read word data */ | ||
| 156 | fault_t (*read_word) (ARMul_State * state, ARMword va, | ||
| 157 | ARMword * data); | ||
| 158 | /*write word data */ | ||
| 159 | fault_t (*write_word) (ARMul_State * state, ARMword va, | ||
| 160 | ARMword data); | ||
| 161 | /*load instr */ | ||
| 162 | fault_t (*load_instr) (ARMul_State * state, ARMword va, | ||
| 163 | ARMword * instr); | ||
| 164 | /*mcr */ | ||
| 165 | ARMword (*mcr) (ARMul_State * state, ARMword instr, ARMword val); | ||
| 166 | /*mrc */ | ||
| 167 | ARMword (*mrc) (ARMul_State * state, ARMword instr, ARMword * val); | ||
| 168 | |||
| 169 | /*ywc 2005-04-16 convert virtual address to physics address */ | ||
| 170 | int (*v2p_dbct) (ARMul_State * state, ARMword virt_addr, | ||
| 171 | ARMword * phys_addr); | ||
| 172 | } mmu_ops_t; | ||
| 173 | |||
| 174 | |||
| 175 | #include "core/arm/interpreter/mmu/tlb.h" | ||
| 176 | #include "core/arm/interpreter/mmu/rb.h" | ||
| 177 | #include "core/arm/interpreter/mmu/wb.h" | ||
| 178 | #include "core/arm/interpreter/mmu/cache.h" | ||
| 179 | |||
| 180 | /*special process mmu.h*/ | ||
| 181 | #include "core/arm/interpreter/mmu/sa_mmu.h" | ||
| 182 | //#include "core/arm/interpreter/mmu/arm7100_mmu.h" | ||
| 183 | //#include "core/arm/interpreter/mmu/arm920t_mmu.h" | ||
| 184 | //#include "core/arm/interpreter/mmu/arm926ejs_mmu.h" | ||
| 185 | #include "core/arm/interpreter/mmu/arm1176jzf_s_mmu.h" | ||
| 186 | //#include "core/arm/interpreter/mmu/cortex_a9_mmu.h" | ||
| 187 | |||
| 188 | typedef struct mmu_state_t | ||
| 189 | { | ||
| 190 | ARMword control; | ||
| 191 | ARMword translation_table_base; | ||
| 192 | /* dyf 201-08-11 for arm1176 */ | ||
| 193 | ARMword auxiliary_control; | ||
| 194 | ARMword coprocessor_access_control; | ||
| 195 | ARMword translation_table_base0; | ||
| 196 | ARMword translation_table_base1; | ||
| 197 | ARMword translation_table_ctrl; | ||
| 198 | /* arm1176 end */ | ||
| 199 | |||
| 200 | ARMword domain_access_control; | ||
| 201 | ARMword fault_status; | ||
| 202 | ARMword fault_statusi; /* prefetch fault status */ | ||
| 203 | ARMword fault_address; | ||
| 204 | ARMword last_domain; | ||
| 205 | ARMword process_id; | ||
| 206 | ARMword context_id; | ||
| 207 | ARMword thread_uro_id; | ||
| 208 | ARMword cache_locked_down; | ||
| 209 | ARMword tlb_locked_down; | ||
| 210 | //chy 2003-08-24 for xscale | ||
| 211 | ARMword cache_type; // 0 | ||
| 212 | ARMword aux_control; // 1 | ||
| 213 | ARMword copro_access; // 15 | ||
| 214 | |||
| 215 | mmu_ops_t ops; | ||
| 216 | union | ||
| 217 | { | ||
| 218 | sa_mmu_t sa_mmu; | ||
| 219 | //arm7100_mmu_t arm7100_mmu; | ||
| 220 | //arm920t_mmu_t arm920t_mmu; | ||
| 221 | //arm926ejs_mmu_t arm926ejs_mmu; | ||
| 222 | } u; | ||
| 223 | } mmu_state_t; | ||
| 224 | |||
| 225 | int mmu_init (ARMul_State * state); | ||
| 226 | int mmu_reset (ARMul_State * state); | ||
| 227 | void mmu_exit (ARMul_State * state); | ||
| 228 | |||
| 229 | fault_t mmu_read_word (ARMul_State * state, ARMword virt_addr, | ||
| 230 | ARMword * data); | ||
| 231 | fault_t mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data); | ||
| 232 | fault_t mmu_load_instr (ARMul_State * state, ARMword virt_addr, | ||
| 233 | ARMword * instr); | ||
| 234 | |||
| 235 | ARMword mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value); | ||
| 236 | void mmu_mcr (ARMul_State * state, ARMword instr, ARMword value); | ||
| 237 | |||
| 238 | /*ywc 20050416*/ | ||
| 239 | int mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, | ||
| 240 | ARMword * phys_addr); | ||
| 241 | |||
| 242 | fault_t | ||
| 243 | mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data); | ||
| 244 | fault_t | ||
| 245 | mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data); | ||
| 246 | fault_t | ||
| 247 | mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data); | ||
| 248 | fault_t | ||
| 249 | mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data); | ||
| 250 | fault_t | ||
| 251 | mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data); | ||
| 252 | fault_t | ||
| 253 | mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data); | ||
| 254 | #endif /* _ARMMMU_H_ */ | 137 | #endif /* _ARMMMU_H_ */ |