diff options
Diffstat (limited to 'src/core/arm')
22 files changed, 5726 insertions, 6274 deletions
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 480c90e66..919da6737 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include "core/arm/skyeye_common/vfp/asm_vfp.h" | 9 | #include "core/arm/skyeye_common/vfp/asm_vfp.h" |
| 10 | 10 | ||
| 11 | namespace Core { | 11 | namespace Core { |
| 12 | struct ThreadContext; | 12 | struct ThreadContext; |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | /// Generic ARM11 CPU interface | 15 | /// Generic ARM11 CPU interface |
| @@ -141,10 +141,10 @@ public: | |||
| 141 | return num_instructions; | 141 | return num_instructions; |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | s64 down_count = 0; ///< A decreasing counter of remaining cycles before the next event, decreased by the cpu run loop | 144 | s64 down_count = 0; ///< A decreasing counter of remaining cycles before the next event, |
| 145 | /// decreased by the cpu run loop | ||
| 145 | 146 | ||
| 146 | protected: | 147 | protected: |
| 147 | |||
| 148 | /** | 148 | /** |
| 149 | * Executes the given number of instructions | 149 | * Executes the given number of instructions |
| 150 | * @param num_instructions Number of instructions to executes | 150 | * @param num_instructions Number of instructions to executes |
| @@ -152,6 +152,5 @@ protected: | |||
| 152 | virtual void ExecuteInstructions(int num_instructions) = 0; | 152 | virtual void ExecuteInstructions(int num_instructions) = 0; |
| 153 | 153 | ||
| 154 | private: | 154 | private: |
| 155 | |||
| 156 | u64 num_instructions = 0; ///< Number of instructions executed | 155 | u64 num_instructions = 0; ///< Number of instructions executed |
| 157 | }; | 156 | }; |
diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp index 5ad1f1c29..b3b9971e8 100644 --- a/src/core/arm/disassembler/arm_disasm.cpp +++ b/src/core/arm/disassembler/arm_disasm.cpp | |||
| @@ -9,401 +9,225 @@ | |||
| 9 | #include "core/arm/disassembler/arm_disasm.h" | 9 | #include "core/arm/disassembler/arm_disasm.h" |
| 10 | #include "core/arm/skyeye_common/armsupp.h" | 10 | #include "core/arm/skyeye_common/armsupp.h" |
| 11 | 11 | ||
| 12 | static const char *cond_names[] = { | 12 | static const char* cond_names[] = {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", |
| 13 | "eq", | 13 | "hi", "ls", "ge", "lt", "gt", "le", "", "RESERVED"}; |
| 14 | "ne", | 14 | |
| 15 | "cs", | 15 | static const char* opcode_names[] = { |
| 16 | "cc", | 16 | "invalid", "undefined", "adc", "add", "and", "b", "bl", "bic", |
| 17 | "mi", | 17 | "bkpt", "blx", "bx", "cdp", "clrex", "clz", "cmn", "cmp", |
| 18 | "pl", | 18 | "eor", "ldc", "ldm", "ldr", "ldrb", "ldrbt", "ldrex", "ldrexb", |
| 19 | "vs", | 19 | "ldrexd", "ldrexh", "ldrh", "ldrsb", "ldrsh", "ldrt", "mcr", "mla", |
| 20 | "vc", | 20 | "mov", "mrc", "mrs", "msr", "mul", "mvn", "nop", "orr", |
| 21 | "hi", | 21 | "pkh", "pld", "qadd16", "qadd8", "qasx", "qsax", "qsub16", "qsub8", |
| 22 | "ls", | 22 | "rev", "rev16", "revsh", "rsb", "rsc", "sadd16", "sadd8", "sasx", |
| 23 | "ge", | 23 | "sbc", "sel", "sev", "shadd16", "shadd8", "shasx", "shsax", "shsub16", |
| 24 | "lt", | 24 | "shsub8", "smlad", "smlal", "smlald", "smlsd", "smlsld", "smmla", "smmls", |
| 25 | "gt", | 25 | "smmul", "smuad", "smull", "smusd", "ssat", "ssat16", "ssax", "ssub16", |
| 26 | "le", | 26 | "ssub8", "stc", "stm", "str", "strb", "strbt", "strex", "strexb", |
| 27 | "", | 27 | "strexd", "strexh", "strh", "strt", "sub", "swi", "swp", "swpb", |
| 28 | "RESERVED" | 28 | "sxtab", "sxtab16", "sxtah", "sxtb", "sxtb16", "sxth", "teq", "tst", |
| 29 | }; | 29 | "uadd16", "uadd8", "uasx", "uhadd16", "uhadd8", "uhasx", "uhsax", "uhsub16", |
| 30 | 30 | "uhsub8", "umlal", "umull", "uqadd16", "uqadd8", "uqasx", "uqsax", "uqsub16", | |
| 31 | static const char *opcode_names[] = { | 31 | "uqsub8", "usad8", "usada8", "usat", "usat16", "usax", "usub16", "usub8", |
| 32 | "invalid", | 32 | "uxtab", "uxtab16", "uxtah", "uxtb", "uxtb16", "uxth", "wfe", "wfi", |
| 33 | "undefined", | ||
| 34 | "adc", | ||
| 35 | "add", | ||
| 36 | "and", | ||
| 37 | "b", | ||
| 38 | "bl", | ||
| 39 | "bic", | ||
| 40 | "bkpt", | ||
| 41 | "blx", | ||
| 42 | "bx", | ||
| 43 | "cdp", | ||
| 44 | "clrex", | ||
| 45 | "clz", | ||
| 46 | "cmn", | ||
| 47 | "cmp", | ||
| 48 | "eor", | ||
| 49 | "ldc", | ||
| 50 | "ldm", | ||
| 51 | "ldr", | ||
| 52 | "ldrb", | ||
| 53 | "ldrbt", | ||
| 54 | "ldrex", | ||
| 55 | "ldrexb", | ||
| 56 | "ldrexd", | ||
| 57 | "ldrexh", | ||
| 58 | "ldrh", | ||
| 59 | "ldrsb", | ||
| 60 | "ldrsh", | ||
| 61 | "ldrt", | ||
| 62 | "mcr", | ||
| 63 | "mla", | ||
| 64 | "mov", | ||
| 65 | "mrc", | ||
| 66 | "mrs", | ||
| 67 | "msr", | ||
| 68 | "mul", | ||
| 69 | "mvn", | ||
| 70 | "nop", | ||
| 71 | "orr", | ||
| 72 | "pkh", | ||
| 73 | "pld", | ||
| 74 | "qadd16", | ||
| 75 | "qadd8", | ||
| 76 | "qasx", | ||
| 77 | "qsax", | ||
| 78 | "qsub16", | ||
| 79 | "qsub8", | ||
| 80 | "rev", | ||
| 81 | "rev16", | ||
| 82 | "revsh", | ||
| 83 | "rsb", | ||
| 84 | "rsc", | ||
| 85 | "sadd16", | ||
| 86 | "sadd8", | ||
| 87 | "sasx", | ||
| 88 | "sbc", | ||
| 89 | "sel", | ||
| 90 | "sev", | ||
| 91 | "shadd16", | ||
| 92 | "shadd8", | ||
| 93 | "shasx", | ||
| 94 | "shsax", | ||
| 95 | "shsub16", | ||
| 96 | "shsub8", | ||
| 97 | "smlad", | ||
| 98 | "smlal", | ||
| 99 | "smlald", | ||
| 100 | "smlsd", | ||
| 101 | "smlsld", | ||
| 102 | "smmla", | ||
| 103 | "smmls", | ||
| 104 | "smmul", | ||
| 105 | "smuad", | ||
| 106 | "smull", | ||
| 107 | "smusd", | ||
| 108 | "ssat", | ||
| 109 | "ssat16", | ||
| 110 | "ssax", | ||
| 111 | "ssub16", | ||
| 112 | "ssub8", | ||
| 113 | "stc", | ||
| 114 | "stm", | ||
| 115 | "str", | ||
| 116 | "strb", | ||
| 117 | "strbt", | ||
| 118 | "strex", | ||
| 119 | "strexb", | ||
| 120 | "strexd", | ||
| 121 | "strexh", | ||
| 122 | "strh", | ||
| 123 | "strt", | ||
| 124 | "sub", | ||
| 125 | "swi", | ||
| 126 | "swp", | ||
| 127 | "swpb", | ||
| 128 | "sxtab", | ||
| 129 | "sxtab16", | ||
| 130 | "sxtah", | ||
| 131 | "sxtb", | ||
| 132 | "sxtb16", | ||
| 133 | "sxth", | ||
| 134 | "teq", | ||
| 135 | "tst", | ||
| 136 | "uadd16", | ||
| 137 | "uadd8", | ||
| 138 | "uasx", | ||
| 139 | "uhadd16", | ||
| 140 | "uhadd8", | ||
| 141 | "uhasx", | ||
| 142 | "uhsax", | ||
| 143 | "uhsub16", | ||
| 144 | "uhsub8", | ||
| 145 | "umlal", | ||
| 146 | "umull", | ||
| 147 | "uqadd16", | ||
| 148 | "uqadd8", | ||
| 149 | "uqasx", | ||
| 150 | "uqsax", | ||
| 151 | "uqsub16", | ||
| 152 | "uqsub8", | ||
| 153 | "usad8", | ||
| 154 | "usada8", | ||
| 155 | "usat", | ||
| 156 | "usat16", | ||
| 157 | "usax", | ||
| 158 | "usub16", | ||
| 159 | "usub8", | ||
| 160 | "uxtab", | ||
| 161 | "uxtab16", | ||
| 162 | "uxtah", | ||
| 163 | "uxtb", | ||
| 164 | "uxtb16", | ||
| 165 | "uxth", | ||
| 166 | "wfe", | ||
| 167 | "wfi", | ||
| 168 | "yield", | 33 | "yield", |
| 169 | 34 | ||
| 170 | "undefined", | 35 | "undefined", "adc", "add", "and", "asr", "b", "bic", "bkpt", |
| 171 | "adc", | 36 | "bl", "blx", "bx", "cmn", "cmp", "eor", "ldmia", "ldr", |
| 172 | "add", | 37 | "ldrb", "ldrh", "ldrsb", "ldrsh", "lsl", "lsr", "mov", "mul", |
| 173 | "and", | 38 | "mvn", "neg", "orr", "pop", "push", "ror", "sbc", "stmia", |
| 174 | "asr", | 39 | "str", "strb", "strh", "sub", "swi", "tst", |
| 175 | "b", | 40 | |
| 176 | "bic", | 41 | nullptr}; |
| 177 | "bkpt", | ||
| 178 | "bl", | ||
| 179 | "blx", | ||
| 180 | "bx", | ||
| 181 | "cmn", | ||
| 182 | "cmp", | ||
| 183 | "eor", | ||
| 184 | "ldmia", | ||
| 185 | "ldr", | ||
| 186 | "ldrb", | ||
| 187 | "ldrh", | ||
| 188 | "ldrsb", | ||
| 189 | "ldrsh", | ||
| 190 | "lsl", | ||
| 191 | "lsr", | ||
| 192 | "mov", | ||
| 193 | "mul", | ||
| 194 | "mvn", | ||
| 195 | "neg", | ||
| 196 | "orr", | ||
| 197 | "pop", | ||
| 198 | "push", | ||
| 199 | "ror", | ||
| 200 | "sbc", | ||
| 201 | "stmia", | ||
| 202 | "str", | ||
| 203 | "strb", | ||
| 204 | "strh", | ||
| 205 | "sub", | ||
| 206 | "swi", | ||
| 207 | "tst", | ||
| 208 | |||
| 209 | nullptr | ||
| 210 | }; | ||
| 211 | 42 | ||
| 212 | // Indexed by the shift type (bits 6-5) | 43 | // Indexed by the shift type (bits 6-5) |
| 213 | static const char *shift_names[] = { | 44 | static const char* shift_names[] = {"LSL", "LSR", "ASR", "ROR"}; |
| 214 | "LSL", | ||
| 215 | "LSR", | ||
| 216 | "ASR", | ||
| 217 | "ROR" | ||
| 218 | }; | ||
| 219 | 45 | ||
| 220 | static const char* cond_to_str(u32 cond) { | 46 | static const char* cond_to_str(u32 cond) { |
| 221 | return cond_names[cond]; | 47 | return cond_names[cond]; |
| 222 | } | 48 | } |
| 223 | 49 | ||
| 224 | std::string ARM_Disasm::Disassemble(u32 addr, u32 insn) | 50 | std::string ARM_Disasm::Disassemble(u32 addr, u32 insn) { |
| 225 | { | ||
| 226 | Opcode opcode = Decode(insn); | 51 | Opcode opcode = Decode(insn); |
| 227 | switch (opcode) { | 52 | switch (opcode) { |
| 228 | case OP_INVALID: | 53 | case OP_INVALID: |
| 229 | return "Invalid"; | 54 | return "Invalid"; |
| 230 | case OP_UNDEFINED: | 55 | case OP_UNDEFINED: |
| 231 | return "Undefined"; | 56 | return "Undefined"; |
| 232 | case OP_ADC: | 57 | case OP_ADC: |
| 233 | case OP_ADD: | 58 | case OP_ADD: |
| 234 | case OP_AND: | 59 | case OP_AND: |
| 235 | case OP_BIC: | 60 | case OP_BIC: |
| 236 | case OP_CMN: | 61 | case OP_CMN: |
| 237 | case OP_CMP: | 62 | case OP_CMP: |
| 238 | case OP_EOR: | 63 | case OP_EOR: |
| 239 | case OP_MOV: | 64 | case OP_MOV: |
| 240 | case OP_MVN: | 65 | case OP_MVN: |
| 241 | case OP_ORR: | 66 | case OP_ORR: |
| 242 | case OP_RSB: | 67 | case OP_RSB: |
| 243 | case OP_RSC: | 68 | case OP_RSC: |
| 244 | case OP_SBC: | 69 | case OP_SBC: |
| 245 | case OP_SUB: | 70 | case OP_SUB: |
| 246 | case OP_TEQ: | 71 | case OP_TEQ: |
| 247 | case OP_TST: | 72 | case OP_TST: |
| 248 | return DisassembleALU(opcode, insn); | 73 | return DisassembleALU(opcode, insn); |
| 249 | case OP_B: | 74 | case OP_B: |
| 250 | case OP_BL: | 75 | case OP_BL: |
| 251 | return DisassembleBranch(addr, opcode, insn); | 76 | return DisassembleBranch(addr, opcode, insn); |
| 252 | case OP_BKPT: | 77 | case OP_BKPT: |
| 253 | return DisassembleBKPT(insn); | 78 | return DisassembleBKPT(insn); |
| 254 | case OP_BLX: | 79 | case OP_BLX: |
| 255 | // not supported yet | 80 | // not supported yet |
| 256 | break; | 81 | break; |
| 257 | case OP_BX: | 82 | case OP_BX: |
| 258 | return DisassembleBX(insn); | 83 | return DisassembleBX(insn); |
| 259 | case OP_CDP: | 84 | case OP_CDP: |
| 260 | return "cdp"; | 85 | return "cdp"; |
| 261 | case OP_CLREX: | 86 | case OP_CLREX: |
| 262 | return "clrex"; | 87 | return "clrex"; |
| 263 | case OP_CLZ: | 88 | case OP_CLZ: |
| 264 | return DisassembleCLZ(insn); | 89 | return DisassembleCLZ(insn); |
| 265 | case OP_LDC: | 90 | case OP_LDC: |
| 266 | return "ldc"; | 91 | return "ldc"; |
| 267 | case OP_LDM: | 92 | case OP_LDM: |
| 268 | case OP_STM: | 93 | case OP_STM: |
| 269 | return DisassembleMemblock(opcode, insn); | 94 | return DisassembleMemblock(opcode, insn); |
| 270 | case OP_LDR: | 95 | case OP_LDR: |
| 271 | case OP_LDRB: | 96 | case OP_LDRB: |
| 272 | case OP_LDRBT: | 97 | case OP_LDRBT: |
| 273 | case OP_LDRT: | 98 | case OP_LDRT: |
| 274 | case OP_STR: | 99 | case OP_STR: |
| 275 | case OP_STRB: | 100 | case OP_STRB: |
| 276 | case OP_STRBT: | 101 | case OP_STRBT: |
| 277 | case OP_STRT: | 102 | case OP_STRT: |
| 278 | return DisassembleMem(insn); | 103 | return DisassembleMem(insn); |
| 279 | case OP_LDREX: | 104 | case OP_LDREX: |
| 280 | case OP_LDREXB: | 105 | case OP_LDREXB: |
| 281 | case OP_LDREXD: | 106 | case OP_LDREXD: |
| 282 | case OP_LDREXH: | 107 | case OP_LDREXH: |
| 283 | case OP_STREX: | 108 | case OP_STREX: |
| 284 | case OP_STREXB: | 109 | case OP_STREXB: |
| 285 | case OP_STREXD: | 110 | case OP_STREXD: |
| 286 | case OP_STREXH: | 111 | case OP_STREXH: |
| 287 | return DisassembleREX(opcode, insn); | 112 | return DisassembleREX(opcode, insn); |
| 288 | case OP_LDRH: | 113 | case OP_LDRH: |
| 289 | case OP_LDRSB: | 114 | case OP_LDRSB: |
| 290 | case OP_LDRSH: | 115 | case OP_LDRSH: |
| 291 | case OP_STRH: | 116 | case OP_STRH: |
| 292 | return DisassembleMemHalf(insn); | 117 | return DisassembleMemHalf(insn); |
| 293 | case OP_MCR: | 118 | case OP_MCR: |
| 294 | case OP_MRC: | 119 | case OP_MRC: |
| 295 | return DisassembleMCR(opcode, insn); | 120 | return DisassembleMCR(opcode, insn); |
| 296 | case OP_MLA: | 121 | case OP_MLA: |
| 297 | return DisassembleMLA(opcode, insn); | 122 | return DisassembleMLA(opcode, insn); |
| 298 | case OP_MRS: | 123 | case OP_MRS: |
| 299 | return DisassembleMRS(insn); | 124 | return DisassembleMRS(insn); |
| 300 | case OP_MSR: | 125 | case OP_MSR: |
| 301 | return DisassembleMSR(insn); | 126 | return DisassembleMSR(insn); |
| 302 | case OP_MUL: | 127 | case OP_MUL: |
| 303 | return DisassembleMUL(opcode, insn); | 128 | return DisassembleMUL(opcode, insn); |
| 304 | case OP_NOP: | 129 | case OP_NOP: |
| 305 | case OP_SEV: | 130 | case OP_SEV: |
| 306 | case OP_WFE: | 131 | case OP_WFE: |
| 307 | case OP_WFI: | 132 | case OP_WFI: |
| 308 | case OP_YIELD: | 133 | case OP_YIELD: |
| 309 | return DisassembleNoOperands(opcode, insn); | 134 | return DisassembleNoOperands(opcode, insn); |
| 310 | case OP_PKH: | 135 | case OP_PKH: |
| 311 | return DisassemblePKH(insn); | 136 | return DisassemblePKH(insn); |
| 312 | case OP_PLD: | 137 | case OP_PLD: |
| 313 | return DisassemblePLD(insn); | 138 | return DisassemblePLD(insn); |
| 314 | case OP_QADD16: | 139 | case OP_QADD16: |
| 315 | case OP_QADD8: | 140 | case OP_QADD8: |
| 316 | case OP_QASX: | 141 | case OP_QASX: |
| 317 | case OP_QSAX: | 142 | case OP_QSAX: |
| 318 | case OP_QSUB16: | 143 | case OP_QSUB16: |
| 319 | case OP_QSUB8: | 144 | case OP_QSUB8: |
| 320 | case OP_SADD16: | 145 | case OP_SADD16: |
| 321 | case OP_SADD8: | 146 | case OP_SADD8: |
| 322 | case OP_SASX: | 147 | case OP_SASX: |
| 323 | case OP_SHADD16: | 148 | case OP_SHADD16: |
| 324 | case OP_SHADD8: | 149 | case OP_SHADD8: |
| 325 | case OP_SHASX: | 150 | case OP_SHASX: |
| 326 | case OP_SHSAX: | 151 | case OP_SHSAX: |
| 327 | case OP_SHSUB16: | 152 | case OP_SHSUB16: |
| 328 | case OP_SHSUB8: | 153 | case OP_SHSUB8: |
| 329 | case OP_SSAX: | 154 | case OP_SSAX: |
| 330 | case OP_SSUB16: | 155 | case OP_SSUB16: |
| 331 | case OP_SSUB8: | 156 | case OP_SSUB8: |
| 332 | case OP_UADD16: | 157 | case OP_UADD16: |
| 333 | case OP_UADD8: | 158 | case OP_UADD8: |
| 334 | case OP_UASX: | 159 | case OP_UASX: |
| 335 | case OP_UHADD16: | 160 | case OP_UHADD16: |
| 336 | case OP_UHADD8: | 161 | case OP_UHADD8: |
| 337 | case OP_UHASX: | 162 | case OP_UHASX: |
| 338 | case OP_UHSAX: | 163 | case OP_UHSAX: |
| 339 | case OP_UHSUB16: | 164 | case OP_UHSUB16: |
| 340 | case OP_UHSUB8: | 165 | case OP_UHSUB8: |
| 341 | case OP_UQADD16: | 166 | case OP_UQADD16: |
| 342 | case OP_UQADD8: | 167 | case OP_UQADD8: |
| 343 | case OP_UQASX: | 168 | case OP_UQASX: |
| 344 | case OP_UQSAX: | 169 | case OP_UQSAX: |
| 345 | case OP_UQSUB16: | 170 | case OP_UQSUB16: |
| 346 | case OP_UQSUB8: | 171 | case OP_UQSUB8: |
| 347 | case OP_USAX: | 172 | case OP_USAX: |
| 348 | case OP_USUB16: | 173 | case OP_USUB16: |
| 349 | case OP_USUB8: | 174 | case OP_USUB8: |
| 350 | return DisassembleParallelAddSub(opcode, insn); | 175 | return DisassembleParallelAddSub(opcode, insn); |
| 351 | case OP_REV: | 176 | case OP_REV: |
| 352 | case OP_REV16: | 177 | case OP_REV16: |
| 353 | case OP_REVSH: | 178 | case OP_REVSH: |
| 354 | return DisassembleREV(opcode, insn); | 179 | return DisassembleREV(opcode, insn); |
| 355 | case OP_SEL: | 180 | case OP_SEL: |
| 356 | return DisassembleSEL(insn); | 181 | return DisassembleSEL(insn); |
| 357 | case OP_SMLAD: | 182 | case OP_SMLAD: |
| 358 | case OP_SMLALD: | 183 | case OP_SMLALD: |
| 359 | case OP_SMLSD: | 184 | case OP_SMLSD: |
| 360 | case OP_SMLSLD: | 185 | case OP_SMLSLD: |
| 361 | case OP_SMMLA: | 186 | case OP_SMMLA: |
| 362 | case OP_SMMLS: | 187 | case OP_SMMLS: |
| 363 | case OP_SMMUL: | 188 | case OP_SMMUL: |
| 364 | case OP_SMUAD: | 189 | case OP_SMUAD: |
| 365 | case OP_SMUSD: | 190 | case OP_SMUSD: |
| 366 | case OP_USAD8: | 191 | case OP_USAD8: |
| 367 | case OP_USADA8: | 192 | case OP_USADA8: |
| 368 | return DisassembleMediaMulDiv(opcode, insn); | 193 | return DisassembleMediaMulDiv(opcode, insn); |
| 369 | case OP_SSAT: | 194 | case OP_SSAT: |
| 370 | case OP_SSAT16: | 195 | case OP_SSAT16: |
| 371 | case OP_USAT: | 196 | case OP_USAT: |
| 372 | case OP_USAT16: | 197 | case OP_USAT16: |
| 373 | return DisassembleSAT(opcode, insn); | 198 | return DisassembleSAT(opcode, insn); |
| 374 | case OP_STC: | 199 | case OP_STC: |
| 375 | return "stc"; | 200 | return "stc"; |
| 376 | case OP_SWI: | 201 | case OP_SWI: |
| 377 | return DisassembleSWI(insn); | 202 | return DisassembleSWI(insn); |
| 378 | case OP_SWP: | 203 | case OP_SWP: |
| 379 | case OP_SWPB: | 204 | case OP_SWPB: |
| 380 | return DisassembleSWP(opcode, insn); | 205 | return DisassembleSWP(opcode, insn); |
| 381 | case OP_SXTAB: | 206 | case OP_SXTAB: |
| 382 | case OP_SXTAB16: | 207 | case OP_SXTAB16: |
| 383 | case OP_SXTAH: | 208 | case OP_SXTAH: |
| 384 | case OP_SXTB: | 209 | case OP_SXTB: |
| 385 | case OP_SXTB16: | 210 | case OP_SXTB16: |
| 386 | case OP_SXTH: | 211 | case OP_SXTH: |
| 387 | case OP_UXTAB: | 212 | case OP_UXTAB: |
| 388 | case OP_UXTAB16: | 213 | case OP_UXTAB16: |
| 389 | case OP_UXTAH: | 214 | case OP_UXTAH: |
| 390 | case OP_UXTB: | 215 | case OP_UXTB: |
| 391 | case OP_UXTB16: | 216 | case OP_UXTB16: |
| 392 | case OP_UXTH: | 217 | case OP_UXTH: |
| 393 | return DisassembleXT(opcode, insn); | 218 | return DisassembleXT(opcode, insn); |
| 394 | case OP_UMLAL: | 219 | case OP_UMLAL: |
| 395 | case OP_UMULL: | 220 | case OP_UMULL: |
| 396 | case OP_SMLAL: | 221 | case OP_SMLAL: |
| 397 | case OP_SMULL: | 222 | case OP_SMULL: |
| 398 | return DisassembleUMLAL(opcode, insn); | 223 | return DisassembleUMLAL(opcode, insn); |
| 399 | default: | 224 | default: |
| 400 | return "Error"; | 225 | return "Error"; |
| 401 | } | 226 | } |
| 402 | return nullptr; | 227 | return nullptr; |
| 403 | } | 228 | } |
| 404 | 229 | ||
| 405 | std::string ARM_Disasm::DisassembleALU(Opcode opcode, u32 insn) | 230 | std::string ARM_Disasm::DisassembleALU(Opcode opcode, u32 insn) { |
| 406 | { | ||
| 407 | static const u8 kNoOperand1 = 1; | 231 | static const u8 kNoOperand1 = 1; |
| 408 | static const u8 kNoDest = 2; | 232 | static const u8 kNoDest = 2; |
| 409 | static const u8 kNoSbit = 4; | 233 | static const u8 kNoSbit = 4; |
| @@ -421,18 +245,18 @@ std::string ARM_Disasm::DisassembleALU(Opcode opcode, u32 insn) | |||
| 421 | 245 | ||
| 422 | const char* opname = opcode_names[opcode]; | 246 | const char* opname = opcode_names[opcode]; |
| 423 | switch (opcode) { | 247 | switch (opcode) { |
| 424 | case OP_CMN: | 248 | case OP_CMN: |
| 425 | case OP_CMP: | 249 | case OP_CMP: |
| 426 | case OP_TEQ: | 250 | case OP_TEQ: |
| 427 | case OP_TST: | 251 | case OP_TST: |
| 428 | flags = kNoDest | kNoSbit; | 252 | flags = kNoDest | kNoSbit; |
| 429 | break; | 253 | break; |
| 430 | case OP_MOV: | 254 | case OP_MOV: |
| 431 | case OP_MVN: | 255 | case OP_MVN: |
| 432 | flags = kNoOperand1; | 256 | flags = kNoOperand1; |
| 433 | break; | 257 | break; |
| 434 | default: | 258 | default: |
| 435 | break; | 259 | break; |
| 436 | } | 260 | } |
| 437 | 261 | ||
| 438 | // The "mov" instruction ignores the first operand (rn). | 262 | // The "mov" instruction ignores the first operand (rn). |
| @@ -448,13 +272,13 @@ std::string ARM_Disasm::DisassembleALU(Opcode opcode, u32 insn) | |||
| 448 | rd_str = Common::StringFromFormat("r%d, ", rd); | 272 | rd_str = Common::StringFromFormat("r%d, ", rd); |
| 449 | } | 273 | } |
| 450 | 274 | ||
| 451 | const char *sbit_str = ""; | 275 | const char* sbit_str = ""; |
| 452 | if (bit_s && !(flags & kNoSbit)) | 276 | if (bit_s && !(flags & kNoSbit)) |
| 453 | sbit_str = "s"; | 277 | sbit_str = "s"; |
| 454 | 278 | ||
| 455 | if (is_immed) { | 279 | if (is_immed) { |
| 456 | return Common::StringFromFormat("%s%s%s\t%s%s#%u ; 0x%x", | 280 | return Common::StringFromFormat("%s%s%s\t%s%s#%u ; 0x%x", opname, cond_to_str(cond), |
| 457 | opname, cond_to_str(cond), sbit_str, rd_str.c_str(), rn_str.c_str(), immed, immed); | 281 | sbit_str, rd_str.c_str(), rn_str.c_str(), immed, immed); |
| 458 | } | 282 | } |
| 459 | 283 | ||
| 460 | u8 shift_is_reg = (insn >> 4) & 1; | 284 | u8 shift_is_reg = (insn >> 4) & 1; |
| @@ -468,30 +292,28 @@ std::string ARM_Disasm::DisassembleALU(Opcode opcode, u32 insn) | |||
| 468 | rotated_val = (rotated_val >> rotate2) | (rotated_val << (32 - rotate2)); | 292 | rotated_val = (rotated_val >> rotate2) | (rotated_val << (32 - rotate2)); |
| 469 | 293 | ||
| 470 | if (!shift_is_reg && shift_type == 0 && shift_amount == 0) { | 294 | if (!shift_is_reg && shift_type == 0 && shift_amount == 0) { |
| 471 | return Common::StringFromFormat("%s%s%s\t%s%sr%d", | 295 | return Common::StringFromFormat("%s%s%s\t%s%sr%d", opname, cond_to_str(cond), sbit_str, |
| 472 | opname, cond_to_str(cond), sbit_str, rd_str.c_str(), rn_str.c_str(), rm); | 296 | rd_str.c_str(), rn_str.c_str(), rm); |
| 473 | } | 297 | } |
| 474 | 298 | ||
| 475 | const char *shift_name = shift_names[shift_type]; | 299 | const char* shift_name = shift_names[shift_type]; |
| 476 | if (shift_is_reg) { | 300 | if (shift_is_reg) { |
| 477 | return Common::StringFromFormat("%s%s%s\t%s%sr%d, %s r%d", | 301 | return Common::StringFromFormat("%s%s%s\t%s%sr%d, %s r%d", opname, cond_to_str(cond), |
| 478 | opname, cond_to_str(cond), sbit_str, rd_str.c_str(), rn_str.c_str(), rm, | 302 | sbit_str, rd_str.c_str(), rn_str.c_str(), rm, shift_name, |
| 479 | shift_name, rs); | 303 | rs); |
| 480 | } | 304 | } |
| 481 | if (shift_amount == 0) { | 305 | if (shift_amount == 0) { |
| 482 | if (shift_type == 3) { | 306 | if (shift_type == 3) { |
| 483 | return Common::StringFromFormat("%s%s%s\t%s%sr%d, RRX", | 307 | return Common::StringFromFormat("%s%s%s\t%s%sr%d, RRX", opname, cond_to_str(cond), |
| 484 | opname, cond_to_str(cond), sbit_str, rd_str.c_str(), rn_str.c_str(), rm); | 308 | sbit_str, rd_str.c_str(), rn_str.c_str(), rm); |
| 485 | } | 309 | } |
| 486 | shift_amount = 32; | 310 | shift_amount = 32; |
| 487 | } | 311 | } |
| 488 | return Common::StringFromFormat("%s%s%s\t%s%sr%d, %s #%u", | 312 | return Common::StringFromFormat("%s%s%s\t%s%sr%d, %s #%u", opname, cond_to_str(cond), sbit_str, |
| 489 | opname, cond_to_str(cond), sbit_str, rd_str.c_str(), rn_str.c_str(), rm, | 313 | rd_str.c_str(), rn_str.c_str(), rm, shift_name, shift_amount); |
| 490 | shift_name, shift_amount); | ||
| 491 | } | 314 | } |
| 492 | 315 | ||
| 493 | std::string ARM_Disasm::DisassembleBranch(u32 addr, Opcode opcode, u32 insn) | 316 | std::string ARM_Disasm::DisassembleBranch(u32 addr, Opcode opcode, u32 insn) { |
| 494 | { | ||
| 495 | u8 cond = (insn >> 28) & 0xf; | 317 | u8 cond = (insn >> 28) & 0xf; |
| 496 | u32 offset = insn & 0xffffff; | 318 | u32 offset = insn & 0xffffff; |
| 497 | // Sign-extend the 24-bit offset | 319 | // Sign-extend the 24-bit offset |
| @@ -502,26 +324,23 @@ std::string ARM_Disasm::DisassembleBranch(u32 addr, Opcode opcode, u32 insn) | |||
| 502 | offset <<= 2; | 324 | offset <<= 2; |
| 503 | offset += 8; | 325 | offset += 8; |
| 504 | addr += offset; | 326 | addr += offset; |
| 505 | const char *opname = opcode_names[opcode]; | 327 | const char* opname = opcode_names[opcode]; |
| 506 | return Common::StringFromFormat("%s%s\t0x%x", opname, cond_to_str(cond), addr); | 328 | return Common::StringFromFormat("%s%s\t0x%x", opname, cond_to_str(cond), addr); |
| 507 | } | 329 | } |
| 508 | 330 | ||
| 509 | std::string ARM_Disasm::DisassembleBX(u32 insn) | 331 | std::string ARM_Disasm::DisassembleBX(u32 insn) { |
| 510 | { | ||
| 511 | u8 cond = (insn >> 28) & 0xf; | 332 | u8 cond = (insn >> 28) & 0xf; |
| 512 | u8 rn = insn & 0xf; | 333 | u8 rn = insn & 0xf; |
| 513 | return Common::StringFromFormat("bx%s\tr%d", cond_to_str(cond), rn); | 334 | return Common::StringFromFormat("bx%s\tr%d", cond_to_str(cond), rn); |
| 514 | } | 335 | } |
| 515 | 336 | ||
| 516 | std::string ARM_Disasm::DisassembleBKPT(u32 insn) | 337 | std::string ARM_Disasm::DisassembleBKPT(u32 insn) { |
| 517 | { | ||
| 518 | u8 cond = (insn >> 28) & 0xf; | 338 | u8 cond = (insn >> 28) & 0xf; |
| 519 | u32 immed = (((insn >> 8) & 0xfff) << 4) | (insn & 0xf); | 339 | u32 immed = (((insn >> 8) & 0xfff) << 4) | (insn & 0xf); |
| 520 | return Common::StringFromFormat("bkpt%s\t#%d", cond_to_str(cond), immed); | 340 | return Common::StringFromFormat("bkpt%s\t#%d", cond_to_str(cond), immed); |
| 521 | } | 341 | } |
| 522 | 342 | ||
| 523 | std::string ARM_Disasm::DisassembleCLZ(u32 insn) | 343 | std::string ARM_Disasm::DisassembleCLZ(u32 insn) { |
| 524 | { | ||
| 525 | u8 cond = (insn >> 28) & 0xf; | 344 | u8 cond = (insn >> 28) & 0xf; |
| 526 | u8 rd = (insn >> 12) & 0xf; | 345 | u8 rd = (insn >> 12) & 0xf; |
| 527 | u8 rm = insn & 0xf; | 346 | u8 rm = insn & 0xf; |
| @@ -545,9 +364,8 @@ std::string ARM_Disasm::DisassembleMediaMulDiv(Opcode opcode, u32 insn) { | |||
| 545 | } | 364 | } |
| 546 | 365 | ||
| 547 | std::string ext_reg = ""; | 366 | std::string ext_reg = ""; |
| 548 | std::unordered_set<Opcode, std::hash<int>> with_ext_reg = { | 367 | std::unordered_set<Opcode, std::hash<int>> with_ext_reg = {OP_SMLAD, OP_SMLSD, OP_SMMLA, |
| 549 | OP_SMLAD, OP_SMLSD, OP_SMMLA, OP_SMMLS, OP_USADA8 | 368 | OP_SMMLS, OP_USADA8}; |
| 550 | }; | ||
| 551 | if (with_ext_reg.find(opcode) != with_ext_reg.end()) | 369 | if (with_ext_reg.find(opcode) != with_ext_reg.end()) |
| 552 | ext_reg = Common::StringFromFormat(", r%u", ra); | 370 | ext_reg = Common::StringFromFormat(", r%u", ra); |
| 553 | 371 | ||
| @@ -560,8 +378,7 @@ std::string ARM_Disasm::DisassembleMediaMulDiv(Opcode opcode, u32 insn) { | |||
| 560 | ext_reg.c_str()); | 378 | ext_reg.c_str()); |
| 561 | } | 379 | } |
| 562 | 380 | ||
| 563 | std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, u32 insn) | 381 | std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, u32 insn) { |
| 564 | { | ||
| 565 | std::string tmp_list; | 382 | std::string tmp_list; |
| 566 | 383 | ||
| 567 | u8 cond = (insn >> 28) & 0xf; | 384 | u8 cond = (insn >> 28) & 0xf; |
| @@ -572,17 +389,17 @@ std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, u32 insn) | |||
| 572 | u8 rn = (insn >> 16) & 0xf; | 389 | u8 rn = (insn >> 16) & 0xf; |
| 573 | u16 reg_list = insn & 0xffff; | 390 | u16 reg_list = insn & 0xffff; |
| 574 | 391 | ||
| 575 | const char *opname = opcode_names[opcode]; | 392 | const char* opname = opcode_names[opcode]; |
| 576 | 393 | ||
| 577 | const char *bang = ""; | 394 | const char* bang = ""; |
| 578 | if (write_back) | 395 | if (write_back) |
| 579 | bang = "!"; | 396 | bang = "!"; |
| 580 | 397 | ||
| 581 | const char *carret = ""; | 398 | const char* carret = ""; |
| 582 | if (bit_s) | 399 | if (bit_s) |
| 583 | carret = "^"; | 400 | carret = "^"; |
| 584 | 401 | ||
| 585 | const char *comma = ""; | 402 | const char* comma = ""; |
| 586 | tmp_list[0] = 0; | 403 | tmp_list[0] = 0; |
| 587 | for (int ii = 0; ii < 16; ++ii) { | 404 | for (int ii = 0; ii < 16; ++ii) { |
| 588 | if (reg_list & (1 << ii)) { | 405 | if (reg_list & (1 << ii)) { |
| @@ -591,7 +408,7 @@ std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, u32 insn) | |||
| 591 | } | 408 | } |
| 592 | } | 409 | } |
| 593 | 410 | ||
| 594 | const char *addr_mode = ""; | 411 | const char* addr_mode = ""; |
| 595 | if (is_pre) { | 412 | if (is_pre) { |
| 596 | if (is_up) { | 413 | if (is_up) { |
| 597 | addr_mode = "ib"; | 414 | addr_mode = "ib"; |
| @@ -606,12 +423,11 @@ std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, u32 insn) | |||
| 606 | } | 423 | } |
| 607 | } | 424 | } |
| 608 | 425 | ||
| 609 | return Common::StringFromFormat("%s%s%s\tr%d%s, {%s}%s", | 426 | return Common::StringFromFormat("%s%s%s\tr%d%s, {%s}%s", opname, cond_to_str(cond), addr_mode, |
| 610 | opname, cond_to_str(cond), addr_mode, rn, bang, tmp_list.c_str(), carret); | 427 | rn, bang, tmp_list.c_str(), carret); |
| 611 | } | 428 | } |
| 612 | 429 | ||
| 613 | std::string ARM_Disasm::DisassembleMem(u32 insn) | 430 | std::string ARM_Disasm::DisassembleMem(u32 insn) { |
| 614 | { | ||
| 615 | u8 cond = (insn >> 28) & 0xf; | 431 | u8 cond = (insn >> 28) & 0xf; |
| 616 | u8 is_reg = (insn >> 25) & 0x1; | 432 | u8 is_reg = (insn >> 25) & 0x1; |
| 617 | u8 is_load = (insn >> 20) & 0x1; | 433 | u8 is_load = (insn >> 20) & 0x1; |
| @@ -623,38 +439,40 @@ std::string ARM_Disasm::DisassembleMem(u32 insn) | |||
| 623 | u8 rd = (insn >> 12) & 0xf; | 439 | u8 rd = (insn >> 12) & 0xf; |
| 624 | u16 offset = insn & 0xfff; | 440 | u16 offset = insn & 0xfff; |
| 625 | 441 | ||
| 626 | const char *opname = "ldr"; | 442 | const char* opname = "ldr"; |
| 627 | if (!is_load) | 443 | if (!is_load) |
| 628 | opname = "str"; | 444 | opname = "str"; |
| 629 | 445 | ||
| 630 | const char *bang = ""; | 446 | const char* bang = ""; |
| 631 | if (write_back) | 447 | if (write_back) |
| 632 | bang = "!"; | 448 | bang = "!"; |
| 633 | 449 | ||
| 634 | const char *minus = ""; | 450 | const char* minus = ""; |
| 635 | if (is_up == 0) | 451 | if (is_up == 0) |
| 636 | minus = "-"; | 452 | minus = "-"; |
| 637 | 453 | ||
| 638 | const char *byte = ""; | 454 | const char* byte = ""; |
| 639 | if (is_byte) | 455 | if (is_byte) |
| 640 | byte = "b"; | 456 | byte = "b"; |
| 641 | 457 | ||
| 642 | if (is_reg == 0) { | 458 | if (is_reg == 0) { |
| 643 | if (is_pre) { | 459 | if (is_pre) { |
| 644 | if (offset == 0) { | 460 | if (offset == 0) { |
| 645 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d]", | 461 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d]", opname, cond_to_str(cond), |
| 646 | opname, cond_to_str(cond), byte, rd, rn); | 462 | byte, rd, rn); |
| 647 | } else { | 463 | } else { |
| 648 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d, #%s%u]%s", | 464 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d, #%s%u]%s", opname, |
| 649 | opname, cond_to_str(cond), byte, rd, rn, minus, offset, bang); | 465 | cond_to_str(cond), byte, rd, rn, minus, offset, |
| 466 | bang); | ||
| 650 | } | 467 | } |
| 651 | } else { | 468 | } else { |
| 652 | const char *transfer = ""; | 469 | const char* transfer = ""; |
| 653 | if (write_back) | 470 | if (write_back) |
| 654 | transfer = "t"; | 471 | transfer = "t"; |
| 655 | 472 | ||
| 656 | return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], #%s%u", | 473 | return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], #%s%u", opname, |
| 657 | opname, cond_to_str(cond), byte, transfer, rd, rn, minus, offset); | 474 | cond_to_str(cond), byte, transfer, rd, rn, minus, |
| 475 | offset); | ||
| 658 | } | 476 | } |
| 659 | } | 477 | } |
| 660 | 478 | ||
| @@ -662,48 +480,47 @@ std::string ARM_Disasm::DisassembleMem(u32 insn) | |||
| 662 | u8 shift_type = (insn >> 5) & 0x3; | 480 | u8 shift_type = (insn >> 5) & 0x3; |
| 663 | u8 shift_amount = (insn >> 7) & 0x1f; | 481 | u8 shift_amount = (insn >> 7) & 0x1f; |
| 664 | 482 | ||
| 665 | const char *shift_name = shift_names[shift_type]; | 483 | const char* shift_name = shift_names[shift_type]; |
| 666 | 484 | ||
| 667 | if (is_pre) { | 485 | if (is_pre) { |
| 668 | if (shift_amount == 0) { | 486 | if (shift_amount == 0) { |
| 669 | if (shift_type == 0) { | 487 | if (shift_type == 0) { |
| 670 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d]%s", | 488 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d]%s", opname, |
| 671 | opname, cond_to_str(cond), byte, rd, rn, minus, rm, bang); | 489 | cond_to_str(cond), byte, rd, rn, minus, rm, bang); |
| 672 | } | 490 | } |
| 673 | if (shift_type == 3) { | 491 | if (shift_type == 3) { |
| 674 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d, RRX]%s", | 492 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d, RRX]%s", opname, |
| 675 | opname, cond_to_str(cond), byte, rd, rn, minus, rm, bang); | 493 | cond_to_str(cond), byte, rd, rn, minus, rm, bang); |
| 676 | } | 494 | } |
| 677 | shift_amount = 32; | 495 | shift_amount = 32; |
| 678 | } | 496 | } |
| 679 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d, %s #%u]%s", | 497 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d, %s #%u]%s", opname, |
| 680 | opname, cond_to_str(cond), byte, rd, rn, minus, rm, | 498 | cond_to_str(cond), byte, rd, rn, minus, rm, shift_name, |
| 681 | shift_name, shift_amount, bang); | 499 | shift_amount, bang); |
| 682 | } | 500 | } |
| 683 | 501 | ||
| 684 | const char *transfer = ""; | 502 | const char* transfer = ""; |
| 685 | if (write_back) | 503 | if (write_back) |
| 686 | transfer = "t"; | 504 | transfer = "t"; |
| 687 | 505 | ||
| 688 | if (shift_amount == 0) { | 506 | if (shift_amount == 0) { |
| 689 | if (shift_type == 0) { | 507 | if (shift_type == 0) { |
| 690 | return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d", | 508 | return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d", opname, |
| 691 | opname, cond_to_str(cond), byte, transfer, rd, rn, minus, rm); | 509 | cond_to_str(cond), byte, transfer, rd, rn, minus, rm); |
| 692 | } | 510 | } |
| 693 | if (shift_type == 3) { | 511 | if (shift_type == 3) { |
| 694 | return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d, RRX", | 512 | return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d, RRX", opname, |
| 695 | opname, cond_to_str(cond), byte, transfer, rd, rn, minus, rm); | 513 | cond_to_str(cond), byte, transfer, rd, rn, minus, rm); |
| 696 | } | 514 | } |
| 697 | shift_amount = 32; | 515 | shift_amount = 32; |
| 698 | } | 516 | } |
| 699 | 517 | ||
| 700 | return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d, %s #%u", | 518 | return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d, %s #%u", opname, |
| 701 | opname, cond_to_str(cond), byte, transfer, rd, rn, minus, rm, | 519 | cond_to_str(cond), byte, transfer, rd, rn, minus, rm, |
| 702 | shift_name, shift_amount); | 520 | shift_name, shift_amount); |
| 703 | } | 521 | } |
| 704 | 522 | ||
| 705 | std::string ARM_Disasm::DisassembleMemHalf(u32 insn) | 523 | std::string ARM_Disasm::DisassembleMemHalf(u32 insn) { |
| 706 | { | ||
| 707 | u8 cond = (insn >> 28) & 0xf; | 524 | u8 cond = (insn >> 28) & 0xf; |
| 708 | u8 is_load = (insn >> 20) & 0x1; | 525 | u8 is_load = (insn >> 20) & 0x1; |
| 709 | u8 write_back = (insn >> 21) & 0x1; | 526 | u8 write_back = (insn >> 21) & 0x1; |
| @@ -716,11 +533,11 @@ std::string ARM_Disasm::DisassembleMemHalf(u32 insn) | |||
| 716 | u8 rm = insn & 0xf; | 533 | u8 rm = insn & 0xf; |
| 717 | u8 offset = (((insn >> 8) & 0xf) << 4) | (insn & 0xf); | 534 | u8 offset = (((insn >> 8) & 0xf) << 4) | (insn & 0xf); |
| 718 | 535 | ||
| 719 | const char *opname = "ldr"; | 536 | const char* opname = "ldr"; |
| 720 | if (is_load == 0) | 537 | if (is_load == 0) |
| 721 | opname = "str"; | 538 | opname = "str"; |
| 722 | 539 | ||
| 723 | const char *width = ""; | 540 | const char* width = ""; |
| 724 | if (bits_65 == 1) | 541 | if (bits_65 == 1) |
| 725 | width = "h"; | 542 | width = "h"; |
| 726 | else if (bits_65 == 2) | 543 | else if (bits_65 == 2) |
| @@ -728,38 +545,39 @@ std::string ARM_Disasm::DisassembleMemHalf(u32 insn) | |||
| 728 | else | 545 | else |
| 729 | width = "sh"; | 546 | width = "sh"; |
| 730 | 547 | ||
| 731 | const char *bang = ""; | 548 | const char* bang = ""; |
| 732 | if (write_back) | 549 | if (write_back) |
| 733 | bang = "!"; | 550 | bang = "!"; |
| 734 | const char *minus = ""; | 551 | const char* minus = ""; |
| 735 | if (is_up == 0) | 552 | if (is_up == 0) |
| 736 | minus = "-"; | 553 | minus = "-"; |
| 737 | 554 | ||
| 738 | if (is_immed) { | 555 | if (is_immed) { |
| 739 | if (is_pre) { | 556 | if (is_pre) { |
| 740 | if (offset == 0) { | 557 | if (offset == 0) { |
| 741 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d]", opname, cond_to_str(cond), width, rd, rn); | 558 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d]", opname, cond_to_str(cond), |
| 559 | width, rd, rn); | ||
| 742 | } else { | 560 | } else { |
| 743 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d, #%s%u]%s", | 561 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d, #%s%u]%s", opname, |
| 744 | opname, cond_to_str(cond), width, rd, rn, minus, offset, bang); | 562 | cond_to_str(cond), width, rd, rn, minus, offset, |
| 563 | bang); | ||
| 745 | } | 564 | } |
| 746 | } else { | 565 | } else { |
| 747 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d], #%s%u", | 566 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d], #%s%u", opname, cond_to_str(cond), |
| 748 | opname, cond_to_str(cond), width, rd, rn, minus, offset); | 567 | width, rd, rn, minus, offset); |
| 749 | } | 568 | } |
| 750 | } | 569 | } |
| 751 | 570 | ||
| 752 | if (is_pre) { | 571 | if (is_pre) { |
| 753 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d]%s", | 572 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d]%s", opname, cond_to_str(cond), |
| 754 | opname, cond_to_str(cond), width, rd, rn, minus, rm, bang); | 573 | width, rd, rn, minus, rm, bang); |
| 755 | } else { | 574 | } else { |
| 756 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d], %sr%d", | 575 | return Common::StringFromFormat("%s%s%s\tr%d, [r%d], %sr%d", opname, cond_to_str(cond), |
| 757 | opname, cond_to_str(cond), width, rd, rn, minus, rm); | 576 | width, rd, rn, minus, rm); |
| 758 | } | 577 | } |
| 759 | } | 578 | } |
| 760 | 579 | ||
| 761 | std::string ARM_Disasm::DisassembleMCR(Opcode opcode, u32 insn) | 580 | std::string ARM_Disasm::DisassembleMCR(Opcode opcode, u32 insn) { |
| 762 | { | ||
| 763 | u8 cond = (insn >> 28) & 0xf; | 581 | u8 cond = (insn >> 28) & 0xf; |
| 764 | u8 crn = (insn >> 16) & 0xf; | 582 | u8 crn = (insn >> 16) & 0xf; |
| 765 | u8 crd = (insn >> 12) & 0xf; | 583 | u8 crd = (insn >> 12) & 0xf; |
| @@ -767,13 +585,12 @@ std::string ARM_Disasm::DisassembleMCR(Opcode opcode, u32 insn) | |||
| 767 | u8 opcode2 = (insn >> 5) & 0x7; | 585 | u8 opcode2 = (insn >> 5) & 0x7; |
| 768 | u8 crm = insn & 0xf; | 586 | u8 crm = insn & 0xf; |
| 769 | 587 | ||
| 770 | const char *opname = opcode_names[opcode]; | 588 | const char* opname = opcode_names[opcode]; |
| 771 | return Common::StringFromFormat("%s%s\t%d, 0, r%d, cr%d, cr%d, {%d}", | 589 | return Common::StringFromFormat("%s%s\t%d, 0, r%d, cr%d, cr%d, {%d}", opname, cond_to_str(cond), |
| 772 | opname, cond_to_str(cond), cpnum, crd, crn, crm, opcode2); | 590 | cpnum, crd, crn, crm, opcode2); |
| 773 | } | 591 | } |
| 774 | 592 | ||
| 775 | std::string ARM_Disasm::DisassembleMLA(Opcode opcode, u32 insn) | 593 | std::string ARM_Disasm::DisassembleMLA(Opcode opcode, u32 insn) { |
| 776 | { | ||
| 777 | u8 cond = (insn >> 28) & 0xf; | 594 | u8 cond = (insn >> 28) & 0xf; |
| 778 | u8 rd = (insn >> 16) & 0xf; | 595 | u8 rd = (insn >> 16) & 0xf; |
| 779 | u8 rn = (insn >> 12) & 0xf; | 596 | u8 rn = (insn >> 12) & 0xf; |
| @@ -781,13 +598,12 @@ std::string ARM_Disasm::DisassembleMLA(Opcode opcode, u32 insn) | |||
| 781 | u8 rm = insn & 0xf; | 598 | u8 rm = insn & 0xf; |
| 782 | u8 bit_s = (insn >> 20) & 1; | 599 | u8 bit_s = (insn >> 20) & 1; |
| 783 | 600 | ||
| 784 | const char *opname = opcode_names[opcode]; | 601 | const char* opname = opcode_names[opcode]; |
| 785 | return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d", | 602 | return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d", opname, cond_to_str(cond), |
| 786 | opname, cond_to_str(cond), bit_s ? "s" : "", rd, rm, rs, rn); | 603 | bit_s ? "s" : "", rd, rm, rs, rn); |
| 787 | } | 604 | } |
| 788 | 605 | ||
| 789 | std::string ARM_Disasm::DisassembleUMLAL(Opcode opcode, u32 insn) | 606 | std::string ARM_Disasm::DisassembleUMLAL(Opcode opcode, u32 insn) { |
| 790 | { | ||
| 791 | u8 cond = (insn >> 28) & 0xf; | 607 | u8 cond = (insn >> 28) & 0xf; |
| 792 | u8 rdhi = (insn >> 16) & 0xf; | 608 | u8 rdhi = (insn >> 16) & 0xf; |
| 793 | u8 rdlo = (insn >> 12) & 0xf; | 609 | u8 rdlo = (insn >> 12) & 0xf; |
| @@ -795,26 +611,24 @@ std::string ARM_Disasm::DisassembleUMLAL(Opcode opcode, u32 insn) | |||
| 795 | u8 rm = insn & 0xf; | 611 | u8 rm = insn & 0xf; |
| 796 | u8 bit_s = (insn >> 20) & 1; | 612 | u8 bit_s = (insn >> 20) & 1; |
| 797 | 613 | ||
| 798 | const char *opname = opcode_names[opcode]; | 614 | const char* opname = opcode_names[opcode]; |
| 799 | return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d", | 615 | return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d", opname, cond_to_str(cond), |
| 800 | opname, cond_to_str(cond), bit_s ? "s" : "", rdlo, rdhi, rm, rs); | 616 | bit_s ? "s" : "", rdlo, rdhi, rm, rs); |
| 801 | } | 617 | } |
| 802 | 618 | ||
| 803 | std::string ARM_Disasm::DisassembleMUL(Opcode opcode, u32 insn) | 619 | std::string ARM_Disasm::DisassembleMUL(Opcode opcode, u32 insn) { |
| 804 | { | ||
| 805 | u8 cond = (insn >> 28) & 0xf; | 620 | u8 cond = (insn >> 28) & 0xf; |
| 806 | u8 rd = (insn >> 16) & 0xf; | 621 | u8 rd = (insn >> 16) & 0xf; |
| 807 | u8 rs = (insn >> 8) & 0xf; | 622 | u8 rs = (insn >> 8) & 0xf; |
| 808 | u8 rm = insn & 0xf; | 623 | u8 rm = insn & 0xf; |
| 809 | u8 bit_s = (insn >> 20) & 1; | 624 | u8 bit_s = (insn >> 20) & 1; |
| 810 | 625 | ||
| 811 | const char *opname = opcode_names[opcode]; | 626 | const char* opname = opcode_names[opcode]; |
| 812 | return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d", | 627 | return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d", opname, cond_to_str(cond), |
| 813 | opname, cond_to_str(cond), bit_s ? "s" : "", rd, rm, rs); | 628 | bit_s ? "s" : "", rd, rm, rs); |
| 814 | } | 629 | } |
| 815 | 630 | ||
| 816 | std::string ARM_Disasm::DisassembleMRS(u32 insn) | 631 | std::string ARM_Disasm::DisassembleMRS(u32 insn) { |
| 817 | { | ||
| 818 | u8 cond = (insn >> 28) & 0xf; | 632 | u8 cond = (insn >> 28) & 0xf; |
| 819 | u8 rd = (insn >> 12) & 0xf; | 633 | u8 rd = (insn >> 12) & 0xf; |
| 820 | u8 ps = (insn >> 22) & 1; | 634 | u8 ps = (insn >> 22) & 1; |
| @@ -822,8 +636,7 @@ std::string ARM_Disasm::DisassembleMRS(u32 insn) | |||
| 822 | return Common::StringFromFormat("mrs%s\tr%d, %s", cond_to_str(cond), rd, ps ? "spsr" : "cpsr"); | 636 | return Common::StringFromFormat("mrs%s\tr%d, %s", cond_to_str(cond), rd, ps ? "spsr" : "cpsr"); |
| 823 | } | 637 | } |
| 824 | 638 | ||
| 825 | std::string ARM_Disasm::DisassembleMSR(u32 insn) | 639 | std::string ARM_Disasm::DisassembleMSR(u32 insn) { |
| 826 | { | ||
| 827 | char flags[8]; | 640 | char flags[8]; |
| 828 | int flag_index = 0; | 641 | int flag_index = 0; |
| 829 | u8 cond = (insn >> 28) & 0xf; | 642 | u8 cond = (insn >> 28) & 0xf; |
| @@ -846,18 +659,17 @@ std::string ARM_Disasm::DisassembleMSR(u32 insn) | |||
| 846 | u8 rotate = (insn >> 8) & 0xf; | 659 | u8 rotate = (insn >> 8) & 0xf; |
| 847 | u8 rotate2 = rotate << 1; | 660 | u8 rotate2 = rotate << 1; |
| 848 | u32 rotated_val = (immed >> rotate2) | (immed << (32 - rotate2)); | 661 | u32 rotated_val = (immed >> rotate2) | (immed << (32 - rotate2)); |
| 849 | return Common::StringFromFormat("msr%s\t%s_%s, #0x%x", | 662 | return Common::StringFromFormat("msr%s\t%s_%s, #0x%x", cond_to_str(cond), |
| 850 | cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rotated_val); | 663 | pd ? "spsr" : "cpsr", flags, rotated_val); |
| 851 | } | 664 | } |
| 852 | 665 | ||
| 853 | u8 rm = insn & 0xf; | 666 | u8 rm = insn & 0xf; |
| 854 | 667 | ||
| 855 | return Common::StringFromFormat("msr%s\t%s_%s, r%d", | 668 | return Common::StringFromFormat("msr%s\t%s_%s, r%d", cond_to_str(cond), pd ? "spsr" : "cpsr", |
| 856 | cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rm); | 669 | flags, rm); |
| 857 | } | 670 | } |
| 858 | 671 | ||
| 859 | std::string ARM_Disasm::DisassembleNoOperands(Opcode opcode, u32 insn) | 672 | std::string ARM_Disasm::DisassembleNoOperands(Opcode opcode, u32 insn) { |
| 860 | { | ||
| 861 | u32 cond = BITS(insn, 28, 31); | 673 | u32 cond = BITS(insn, 28, 31); |
| 862 | return Common::StringFromFormat("%s%s", opcode_names[opcode], cond_to_str(cond)); | 674 | return Common::StringFromFormat("%s%s", opcode_names[opcode], cond_to_str(cond)); |
| 863 | } | 675 | } |
| @@ -872,8 +684,7 @@ std::string ARM_Disasm::DisassembleParallelAddSub(Opcode opcode, u32 insn) { | |||
| 872 | rd, rn, rm); | 684 | rd, rn, rm); |
| 873 | } | 685 | } |
| 874 | 686 | ||
| 875 | std::string ARM_Disasm::DisassemblePKH(u32 insn) | 687 | std::string ARM_Disasm::DisassemblePKH(u32 insn) { |
| 876 | { | ||
| 877 | u32 cond = BITS(insn, 28, 31); | 688 | u32 cond = BITS(insn, 28, 31); |
| 878 | u32 rn = BITS(insn, 16, 19); | 689 | u32 rn = BITS(insn, 16, 19); |
| 879 | u32 rd = BITS(insn, 12, 15); | 690 | u32 rd = BITS(insn, 12, 15); |
| @@ -896,13 +707,12 @@ std::string ARM_Disasm::DisassemblePKH(u32 insn) | |||
| 896 | rd, rn, rm, shift.c_str()); | 707 | rd, rn, rm, shift.c_str()); |
| 897 | } | 708 | } |
| 898 | 709 | ||
| 899 | std::string ARM_Disasm::DisassemblePLD(u32 insn) | 710 | std::string ARM_Disasm::DisassemblePLD(u32 insn) { |
| 900 | { | ||
| 901 | u8 is_reg = (insn >> 25) & 0x1; | 711 | u8 is_reg = (insn >> 25) & 0x1; |
| 902 | u8 is_up = (insn >> 23) & 0x1; | 712 | u8 is_up = (insn >> 23) & 0x1; |
| 903 | u8 rn = (insn >> 16) & 0xf; | 713 | u8 rn = (insn >> 16) & 0xf; |
| 904 | 714 | ||
| 905 | const char *minus = ""; | 715 | const char* minus = ""; |
| 906 | if (is_up == 0) | 716 | if (is_up == 0) |
| 907 | minus = "-"; | 717 | minus = "-"; |
| 908 | 718 | ||
| @@ -924,8 +734,8 @@ std::string ARM_Disasm::DisassembleREV(Opcode opcode, u32 insn) { | |||
| 924 | u32 rd = BITS(insn, 12, 15); | 734 | u32 rd = BITS(insn, 12, 15); |
| 925 | u32 rm = BITS(insn, 0, 3); | 735 | u32 rm = BITS(insn, 0, 3); |
| 926 | 736 | ||
| 927 | return Common::StringFromFormat("%s%s\tr%u, r%u", opcode_names[opcode], cond_to_str(cond), | 737 | return Common::StringFromFormat("%s%s\tr%u, r%u", opcode_names[opcode], cond_to_str(cond), rd, |
| 928 | rd, rm); | 738 | rm); |
| 929 | } | 739 | } |
| 930 | 740 | ||
| 931 | std::string ARM_Disasm::DisassembleREX(Opcode opcode, u32 insn) { | 741 | std::string ARM_Disasm::DisassembleREX(Opcode opcode, u32 insn) { |
| @@ -935,26 +745,26 @@ std::string ARM_Disasm::DisassembleREX(Opcode opcode, u32 insn) { | |||
| 935 | u32 cond = BITS(insn, 28, 31); | 745 | u32 cond = BITS(insn, 28, 31); |
| 936 | 746 | ||
| 937 | switch (opcode) { | 747 | switch (opcode) { |
| 938 | case OP_STREX: | 748 | case OP_STREX: |
| 939 | case OP_STREXB: | 749 | case OP_STREXB: |
| 940 | case OP_STREXH: | 750 | case OP_STREXH: |
| 941 | return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode], | 751 | return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode], |
| 942 | cond_to_str(cond), rd, rt, rn); | 752 | cond_to_str(cond), rd, rt, rn); |
| 943 | case OP_STREXD: | 753 | case OP_STREXD: |
| 944 | return Common::StringFromFormat("%s%s\tr%d, r%d, r%d, [r%d]", opcode_names[opcode], | 754 | return Common::StringFromFormat("%s%s\tr%d, r%d, r%d, [r%d]", opcode_names[opcode], |
| 945 | cond_to_str(cond), rd, rt, rt + 1, rn); | 755 | cond_to_str(cond), rd, rt, rt + 1, rn); |
| 946 | 756 | ||
| 947 | // for LDREX instructions, rd corresponds to Rt from reference manual | 757 | // for LDREX instructions, rd corresponds to Rt from reference manual |
| 948 | case OP_LDREX: | 758 | case OP_LDREX: |
| 949 | case OP_LDREXB: | 759 | case OP_LDREXB: |
| 950 | case OP_LDREXH: | 760 | case OP_LDREXH: |
| 951 | return Common::StringFromFormat("%s%s\tr%d, [r%d]", opcode_names[opcode], | 761 | return Common::StringFromFormat("%s%s\tr%d, [r%d]", opcode_names[opcode], cond_to_str(cond), |
| 952 | cond_to_str(cond), rd, rn); | 762 | rd, rn); |
| 953 | case OP_LDREXD: | 763 | case OP_LDREXD: |
| 954 | return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode], | 764 | return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode], |
| 955 | cond_to_str(cond), rd, rd + 1, rn); | 765 | cond_to_str(cond), rd, rd + 1, rn); |
| 956 | default: | 766 | default: |
| 957 | return opcode_names[OP_UNDEFINED]; | 767 | return opcode_names[OP_UNDEFINED]; |
| 958 | } | 768 | } |
| 959 | } | 769 | } |
| 960 | 770 | ||
| @@ -982,8 +792,8 @@ std::string ARM_Disasm::DisassembleSAT(Opcode opcode, u32 insn) { | |||
| 982 | if (opcode == OP_SSAT || opcode == OP_SSAT16) | 792 | if (opcode == OP_SSAT || opcode == OP_SSAT16) |
| 983 | sat_imm++; | 793 | sat_imm++; |
| 984 | 794 | ||
| 985 | return Common::StringFromFormat("%s%s\tr%u, #%u, r%u%s", opcode_names[opcode], cond_to_str(cond), rd, | 795 | return Common::StringFromFormat("%s%s\tr%u, #%u, r%u%s", opcode_names[opcode], |
| 986 | sat_imm, rn, shift_part.c_str()); | 796 | cond_to_str(cond), rd, sat_imm, rn, shift_part.c_str()); |
| 987 | } | 797 | } |
| 988 | 798 | ||
| 989 | std::string ARM_Disasm::DisassembleSEL(u32 insn) { | 799 | std::string ARM_Disasm::DisassembleSEL(u32 insn) { |
| @@ -996,27 +806,24 @@ std::string ARM_Disasm::DisassembleSEL(u32 insn) { | |||
| 996 | rd, rn, rm); | 806 | rd, rn, rm); |
| 997 | } | 807 | } |
| 998 | 808 | ||
| 999 | std::string ARM_Disasm::DisassembleSWI(u32 insn) | 809 | std::string ARM_Disasm::DisassembleSWI(u32 insn) { |
| 1000 | { | ||
| 1001 | u8 cond = (insn >> 28) & 0xf; | 810 | u8 cond = (insn >> 28) & 0xf; |
| 1002 | u32 sysnum = insn & 0x00ffffff; | 811 | u32 sysnum = insn & 0x00ffffff; |
| 1003 | 812 | ||
| 1004 | return Common::StringFromFormat("swi%s 0x%x", cond_to_str(cond), sysnum); | 813 | return Common::StringFromFormat("swi%s 0x%x", cond_to_str(cond), sysnum); |
| 1005 | } | 814 | } |
| 1006 | 815 | ||
| 1007 | std::string ARM_Disasm::DisassembleSWP(Opcode opcode, u32 insn) | 816 | std::string ARM_Disasm::DisassembleSWP(Opcode opcode, u32 insn) { |
| 1008 | { | ||
| 1009 | u8 cond = (insn >> 28) & 0xf; | 817 | u8 cond = (insn >> 28) & 0xf; |
| 1010 | u8 rn = (insn >> 16) & 0xf; | 818 | u8 rn = (insn >> 16) & 0xf; |
| 1011 | u8 rd = (insn >> 12) & 0xf; | 819 | u8 rd = (insn >> 12) & 0xf; |
| 1012 | u8 rm = insn & 0xf; | 820 | u8 rm = insn & 0xf; |
| 1013 | 821 | ||
| 1014 | const char *opname = opcode_names[opcode]; | 822 | const char* opname = opcode_names[opcode]; |
| 1015 | return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opname, cond_to_str(cond), rd, rm, rn); | 823 | return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opname, cond_to_str(cond), rd, rm, rn); |
| 1016 | } | 824 | } |
| 1017 | 825 | ||
| 1018 | std::string ARM_Disasm::DisassembleXT(Opcode opcode, u32 insn) | 826 | std::string ARM_Disasm::DisassembleXT(Opcode opcode, u32 insn) { |
| 1019 | { | ||
| 1020 | u32 cond = BITS(insn, 28, 31); | 827 | u32 cond = BITS(insn, 28, 31); |
| 1021 | u32 rn = BITS(insn, 16, 19); | 828 | u32 rn = BITS(insn, 16, 19); |
| 1022 | u32 rd = BITS(insn, 12, 15); | 829 | u32 rd = BITS(insn, 12, 15); |
| @@ -1025,9 +832,7 @@ std::string ARM_Disasm::DisassembleXT(Opcode opcode, u32 insn) | |||
| 1025 | 832 | ||
| 1026 | std::string rn_part = ""; | 833 | std::string rn_part = ""; |
| 1027 | static std::unordered_set<Opcode, std::hash<int>> extend_with_add = { | 834 | static std::unordered_set<Opcode, std::hash<int>> extend_with_add = { |
| 1028 | OP_SXTAB, OP_SXTAB16, OP_SXTAH, | 835 | OP_SXTAB, OP_SXTAB16, OP_SXTAH, OP_UXTAB, OP_UXTAB16, OP_UXTAH}; |
| 1029 | OP_UXTAB, OP_UXTAB16, OP_UXTAH | ||
| 1030 | }; | ||
| 1031 | if (extend_with_add.find(opcode) != extend_with_add.end()) | 836 | if (extend_with_add.find(opcode) != extend_with_add.end()) |
| 1032 | rn_part = ", r" + std::to_string(rn); | 837 | rn_part = ", r" + std::to_string(rn); |
| 1033 | 838 | ||
| @@ -1042,14 +847,14 @@ std::string ARM_Disasm::DisassembleXT(Opcode opcode, u32 insn) | |||
| 1042 | Opcode ARM_Disasm::Decode(u32 insn) { | 847 | Opcode ARM_Disasm::Decode(u32 insn) { |
| 1043 | u32 bits27_26 = (insn >> 26) & 0x3; | 848 | u32 bits27_26 = (insn >> 26) & 0x3; |
| 1044 | switch (bits27_26) { | 849 | switch (bits27_26) { |
| 1045 | case 0x0: | 850 | case 0x0: |
| 1046 | return Decode00(insn); | 851 | return Decode00(insn); |
| 1047 | case 0x1: | 852 | case 0x1: |
| 1048 | return Decode01(insn); | 853 | return Decode01(insn); |
| 1049 | case 0x2: | 854 | case 0x2: |
| 1050 | return Decode10(insn); | 855 | return Decode10(insn); |
| 1051 | case 0x3: | 856 | case 0x3: |
| 1052 | return Decode11(insn); | 857 | return Decode11(insn); |
| 1053 | } | 858 | } |
| 1054 | return OP_INVALID; | 859 | return OP_INVALID; |
| 1055 | } | 860 | } |
| @@ -1198,28 +1003,28 @@ Opcode ARM_Disasm::DecodeSyncPrimitive(u32 insn) { | |||
| 1198 | u32 op = BITS(insn, 20, 23); | 1003 | u32 op = BITS(insn, 20, 23); |
| 1199 | u32 bit22 = BIT(insn, 22); | 1004 | u32 bit22 = BIT(insn, 22); |
| 1200 | switch (op) { | 1005 | switch (op) { |
| 1201 | case 0x0: | 1006 | case 0x0: |
| 1202 | if (bit22) | 1007 | if (bit22) |
| 1203 | return OP_SWPB; | 1008 | return OP_SWPB; |
| 1204 | return OP_SWP; | 1009 | return OP_SWP; |
| 1205 | case 0x8: | 1010 | case 0x8: |
| 1206 | return OP_STREX; | 1011 | return OP_STREX; |
| 1207 | case 0x9: | 1012 | case 0x9: |
| 1208 | return OP_LDREX; | 1013 | return OP_LDREX; |
| 1209 | case 0xA: | 1014 | case 0xA: |
| 1210 | return OP_STREXD; | 1015 | return OP_STREXD; |
| 1211 | case 0xB: | 1016 | case 0xB: |
| 1212 | return OP_LDREXD; | 1017 | return OP_LDREXD; |
| 1213 | case 0xC: | 1018 | case 0xC: |
| 1214 | return OP_STREXB; | 1019 | return OP_STREXB; |
| 1215 | case 0xD: | 1020 | case 0xD: |
| 1216 | return OP_LDREXB; | 1021 | return OP_LDREXB; |
| 1217 | case 0xE: | 1022 | case 0xE: |
| 1218 | return OP_STREXH; | 1023 | return OP_STREXH; |
| 1219 | case 0xF: | 1024 | case 0xF: |
| 1220 | return OP_LDREXH; | 1025 | return OP_LDREXH; |
| 1221 | default: | 1026 | default: |
| 1222 | return OP_UNDEFINED; | 1027 | return OP_UNDEFINED; |
| 1223 | } | 1028 | } |
| 1224 | } | 1029 | } |
| 1225 | 1030 | ||
| @@ -1240,27 +1045,14 @@ Opcode ARM_Disasm::DecodeParallelAddSub(u32 insn) { | |||
| 1240 | 1045 | ||
| 1241 | static std::vector<Opcode> opcodes = { | 1046 | static std::vector<Opcode> opcodes = { |
| 1242 | // op1 = 0 | 1047 | // op1 = 0 |
| 1243 | OP_SADD16, OP_UADD16, | 1048 | OP_SADD16, OP_UADD16, OP_SASX, OP_UASX, OP_SSAX, OP_USAX, OP_SSUB16, OP_USUB16, OP_SADD8, |
| 1244 | OP_SASX, OP_UASX, | 1049 | OP_UADD8, OP_SSUB8, OP_USUB8, |
| 1245 | OP_SSAX, OP_USAX, | ||
| 1246 | OP_SSUB16, OP_USUB16, | ||
| 1247 | OP_SADD8, OP_UADD8, | ||
| 1248 | OP_SSUB8, OP_USUB8, | ||
| 1249 | // op1 = 1 | 1050 | // op1 = 1 |
| 1250 | OP_QADD16, OP_UQADD16, | 1051 | OP_QADD16, OP_UQADD16, OP_QASX, OP_UQASX, OP_QSAX, OP_UQSAX, OP_QSUB16, OP_UQSUB16, |
| 1251 | OP_QASX, OP_UQASX, | 1052 | OP_QADD8, OP_UQADD8, OP_QSUB8, OP_UQSUB8, |
| 1252 | OP_QSAX, OP_UQSAX, | ||
| 1253 | OP_QSUB16, OP_UQSUB16, | ||
| 1254 | OP_QADD8, OP_UQADD8, | ||
| 1255 | OP_QSUB8, OP_UQSUB8, | ||
| 1256 | // op1 = 2 | 1053 | // op1 = 2 |
| 1257 | OP_SHADD16, OP_UHADD16, | 1054 | OP_SHADD16, OP_UHADD16, OP_SHASX, OP_UHASX, OP_SHSAX, OP_UHSAX, OP_SHSUB16, OP_UHSUB16, |
| 1258 | OP_SHASX, OP_UHASX, | 1055 | OP_SHADD8, OP_UHADD8, OP_SHSUB8, OP_UHSUB8}; |
| 1259 | OP_SHSAX, OP_UHSAX, | ||
| 1260 | OP_SHSUB16, OP_UHSUB16, | ||
| 1261 | OP_SHADD8, OP_UHADD8, | ||
| 1262 | OP_SHSUB8, OP_UHSUB8 | ||
| 1263 | }; | ||
| 1264 | 1056 | ||
| 1265 | u32 opcode_index = op1 * 12 + op2 * 2 + is_unsigned; | 1057 | u32 opcode_index = op1 * 12 + op2 * 2 + is_unsigned; |
| 1266 | return opcodes[opcode_index]; | 1058 | return opcodes[opcode_index]; |
| @@ -1272,66 +1064,66 @@ Opcode ARM_Disasm::DecodePackingSaturationReversal(u32 insn) { | |||
| 1272 | u32 op2 = BITS(insn, 5, 7); | 1064 | u32 op2 = BITS(insn, 5, 7); |
| 1273 | 1065 | ||
| 1274 | switch (op1) { | 1066 | switch (op1) { |
| 1275 | case 0x0: | 1067 | case 0x0: |
| 1276 | if (BIT(op2, 0) == 0) | 1068 | if (BIT(op2, 0) == 0) |
| 1277 | return OP_PKH; | 1069 | return OP_PKH; |
| 1278 | if (op2 == 0x3 && a != 0xf) | 1070 | if (op2 == 0x3 && a != 0xf) |
| 1279 | return OP_SXTAB16; | 1071 | return OP_SXTAB16; |
| 1280 | if (op2 == 0x3 && a == 0xf) | 1072 | if (op2 == 0x3 && a == 0xf) |
| 1281 | return OP_SXTB16; | 1073 | return OP_SXTB16; |
| 1282 | if (op2 == 0x5) | 1074 | if (op2 == 0x5) |
| 1283 | return OP_SEL; | 1075 | return OP_SEL; |
| 1284 | break; | 1076 | break; |
| 1285 | case 0x2: | 1077 | case 0x2: |
| 1286 | if (BIT(op2, 0) == 0) | 1078 | if (BIT(op2, 0) == 0) |
| 1287 | return OP_SSAT; | 1079 | return OP_SSAT; |
| 1288 | if (op2 == 0x1) | 1080 | if (op2 == 0x1) |
| 1289 | return OP_SSAT16; | 1081 | return OP_SSAT16; |
| 1290 | if (op2 == 0x3 && a != 0xf) | 1082 | if (op2 == 0x3 && a != 0xf) |
| 1291 | return OP_SXTAB; | 1083 | return OP_SXTAB; |
| 1292 | if (op2 == 0x3 && a == 0xf) | 1084 | if (op2 == 0x3 && a == 0xf) |
| 1293 | return OP_SXTB; | 1085 | return OP_SXTB; |
| 1294 | break; | 1086 | break; |
| 1295 | case 0x3: | 1087 | case 0x3: |
| 1296 | if (op2 == 0x1) | 1088 | if (op2 == 0x1) |
| 1297 | return OP_REV; | 1089 | return OP_REV; |
| 1298 | if (BIT(op2, 0) == 0) | 1090 | if (BIT(op2, 0) == 0) |
| 1299 | return OP_SSAT; | 1091 | return OP_SSAT; |
| 1300 | if (op2 == 0x3 && a != 0xf) | 1092 | if (op2 == 0x3 && a != 0xf) |
| 1301 | return OP_SXTAH; | 1093 | return OP_SXTAH; |
| 1302 | if (op2 == 0x3 && a == 0xf) | 1094 | if (op2 == 0x3 && a == 0xf) |
| 1303 | return OP_SXTH; | 1095 | return OP_SXTH; |
| 1304 | if (op2 == 0x5) | 1096 | if (op2 == 0x5) |
| 1305 | return OP_REV16; | 1097 | return OP_REV16; |
| 1306 | break; | 1098 | break; |
| 1307 | case 0x4: | 1099 | case 0x4: |
| 1308 | if (op2 == 0x3 && a != 0xf) | 1100 | if (op2 == 0x3 && a != 0xf) |
| 1309 | return OP_UXTAB16; | 1101 | return OP_UXTAB16; |
| 1310 | if (op2 == 0x3 && a == 0xf) | 1102 | if (op2 == 0x3 && a == 0xf) |
| 1311 | return OP_UXTB16; | 1103 | return OP_UXTB16; |
| 1312 | break; | 1104 | break; |
| 1313 | case 0x6: | 1105 | case 0x6: |
| 1314 | if (BIT(op2, 0) == 0) | 1106 | if (BIT(op2, 0) == 0) |
| 1315 | return OP_USAT; | 1107 | return OP_USAT; |
| 1316 | if (op2 == 0x1) | 1108 | if (op2 == 0x1) |
| 1317 | return OP_USAT16; | 1109 | return OP_USAT16; |
| 1318 | if (op2 == 0x3 && a != 0xf) | 1110 | if (op2 == 0x3 && a != 0xf) |
| 1319 | return OP_UXTAB; | 1111 | return OP_UXTAB; |
| 1320 | if (op2 == 0x3 && a == 0xf) | 1112 | if (op2 == 0x3 && a == 0xf) |
| 1321 | return OP_UXTB; | 1113 | return OP_UXTB; |
| 1322 | break; | 1114 | break; |
| 1323 | case 0x7: | 1115 | case 0x7: |
| 1324 | if (BIT(op2, 0) == 0) | 1116 | if (BIT(op2, 0) == 0) |
| 1325 | return OP_USAT; | 1117 | return OP_USAT; |
| 1326 | if (op2 == 0x3 && a != 0xf) | 1118 | if (op2 == 0x3 && a != 0xf) |
| 1327 | return OP_UXTAH; | 1119 | return OP_UXTAH; |
| 1328 | if (op2 == 0x3 && a == 0xf) | 1120 | if (op2 == 0x3 && a == 0xf) |
| 1329 | return OP_UXTH; | 1121 | return OP_UXTH; |
| 1330 | if (op2 == 0x5) | 1122 | if (op2 == 0x5) |
| 1331 | return OP_REVSH; | 1123 | return OP_REVSH; |
| 1332 | break; | 1124 | break; |
| 1333 | default: | 1125 | default: |
| 1334 | break; | 1126 | break; |
| 1335 | } | 1127 | } |
| 1336 | 1128 | ||
| 1337 | return OP_UNDEFINED; | 1129 | return OP_UNDEFINED; |
| @@ -1378,18 +1170,18 @@ Opcode ARM_Disasm::DecodeMSRImmAndHints(u32 insn) { | |||
| 1378 | 1170 | ||
| 1379 | if (op == 0 && op1 == 0) { | 1171 | if (op == 0 && op1 == 0) { |
| 1380 | switch (op2) { | 1172 | switch (op2) { |
| 1381 | case 0x0: | 1173 | case 0x0: |
| 1382 | return OP_NOP; | 1174 | return OP_NOP; |
| 1383 | case 0x1: | 1175 | case 0x1: |
| 1384 | return OP_YIELD; | 1176 | return OP_YIELD; |
| 1385 | case 0x2: | 1177 | case 0x2: |
| 1386 | return OP_WFE; | 1178 | return OP_WFE; |
| 1387 | case 0x3: | 1179 | case 0x3: |
| 1388 | return OP_WFI; | 1180 | return OP_WFI; |
| 1389 | case 0x4: | 1181 | case 0x4: |
| 1390 | return OP_SEV; | 1182 | return OP_SEV; |
| 1391 | default: | 1183 | default: |
| 1392 | return OP_UNDEFINED; | 1184 | return OP_UNDEFINED; |
| 1393 | } | 1185 | } |
| 1394 | } | 1186 | } |
| 1395 | 1187 | ||
| @@ -1402,37 +1194,37 @@ Opcode ARM_Disasm::DecodeMediaMulDiv(u32 insn) { | |||
| 1402 | u32 a = BITS(insn, 12, 15); | 1194 | u32 a = BITS(insn, 12, 15); |
| 1403 | 1195 | ||
| 1404 | switch (op1) { | 1196 | switch (op1) { |
| 1405 | case 0x0: | 1197 | case 0x0: |
| 1406 | if (op2_h == 0x0) { | 1198 | if (op2_h == 0x0) { |
| 1407 | if (a != 0xf) | 1199 | if (a != 0xf) |
| 1408 | return OP_SMLAD; | 1200 | return OP_SMLAD; |
| 1409 | else | 1201 | else |
| 1410 | return OP_SMUAD; | 1202 | return OP_SMUAD; |
| 1411 | } else if (op2_h == 0x1) { | 1203 | } else if (op2_h == 0x1) { |
| 1412 | if (a != 0xf) | 1204 | if (a != 0xf) |
| 1413 | return OP_SMLSD; | 1205 | return OP_SMLSD; |
| 1414 | else | 1206 | else |
| 1415 | return OP_SMUSD; | 1207 | return OP_SMUSD; |
| 1416 | } | 1208 | } |
| 1417 | break; | 1209 | break; |
| 1418 | case 0x4: | 1210 | case 0x4: |
| 1419 | if (op2_h == 0x0) | 1211 | if (op2_h == 0x0) |
| 1420 | return OP_SMLALD; | 1212 | return OP_SMLALD; |
| 1421 | else if (op2_h == 0x1) | 1213 | else if (op2_h == 0x1) |
| 1422 | return OP_SMLSLD; | 1214 | return OP_SMLSLD; |
| 1423 | break; | 1215 | break; |
| 1424 | case 0x5: | 1216 | case 0x5: |
| 1425 | if (op2_h == 0x0) { | 1217 | if (op2_h == 0x0) { |
| 1426 | if (a != 0xf) | 1218 | if (a != 0xf) |
| 1427 | return OP_SMMLA; | 1219 | return OP_SMMLA; |
| 1428 | else | 1220 | else |
| 1429 | return OP_SMMUL; | 1221 | return OP_SMMUL; |
| 1430 | } else if (op2_h == 0x3) { | 1222 | } else if (op2_h == 0x3) { |
| 1431 | return OP_SMMLS; | 1223 | return OP_SMMLS; |
| 1432 | } | 1224 | } |
| 1433 | break; | 1225 | break; |
| 1434 | default: | 1226 | default: |
| 1435 | break; | 1227 | break; |
| 1436 | } | 1228 | } |
| 1437 | 1229 | ||
| 1438 | return OP_UNDEFINED; | 1230 | return OP_UNDEFINED; |
| @@ -1444,23 +1236,23 @@ Opcode ARM_Disasm::DecodeMedia(u32 insn) { | |||
| 1444 | u32 op2 = BITS(insn, 5, 7); | 1236 | u32 op2 = BITS(insn, 5, 7); |
| 1445 | 1237 | ||
| 1446 | switch (BITS(op1, 3, 4)) { | 1238 | switch (BITS(op1, 3, 4)) { |
| 1447 | case 0x0: | 1239 | case 0x0: |
| 1448 | // unsigned and signed parallel addition and subtraction | 1240 | // unsigned and signed parallel addition and subtraction |
| 1449 | return DecodeParallelAddSub(insn); | 1241 | return DecodeParallelAddSub(insn); |
| 1450 | case 0x1: | 1242 | case 0x1: |
| 1451 | // Packing, unpacking, saturation, and reversal | 1243 | // Packing, unpacking, saturation, and reversal |
| 1452 | return DecodePackingSaturationReversal(insn); | 1244 | return DecodePackingSaturationReversal(insn); |
| 1453 | case 0x2: | 1245 | case 0x2: |
| 1454 | // Signed multiply, signed and unsigned divide | 1246 | // Signed multiply, signed and unsigned divide |
| 1455 | return DecodeMediaMulDiv(insn); | 1247 | return DecodeMediaMulDiv(insn); |
| 1456 | case 0x3: | 1248 | case 0x3: |
| 1457 | if (op2 == 0 && rd == 0xf) | 1249 | if (op2 == 0 && rd == 0xf) |
| 1458 | return OP_USAD8; | 1250 | return OP_USAD8; |
| 1459 | if (op2 == 0 && rd != 0xf) | 1251 | if (op2 == 0 && rd != 0xf) |
| 1460 | return OP_USADA8; | 1252 | return OP_USADA8; |
| 1461 | break; | 1253 | break; |
| 1462 | default: | 1254 | default: |
| 1463 | break; | 1255 | break; |
| 1464 | } | 1256 | } |
| 1465 | 1257 | ||
| 1466 | return OP_UNDEFINED; | 1258 | return OP_UNDEFINED; |
| @@ -1508,46 +1300,46 @@ Opcode ARM_Disasm::DecodeALU(u32 insn) { | |||
| 1508 | return OP_UNDEFINED; | 1300 | return OP_UNDEFINED; |
| 1509 | } | 1301 | } |
| 1510 | switch (opcode) { | 1302 | switch (opcode) { |
| 1511 | case 0x0: | 1303 | case 0x0: |
| 1512 | return OP_AND; | 1304 | return OP_AND; |
| 1513 | case 0x1: | 1305 | case 0x1: |
| 1514 | return OP_EOR; | 1306 | return OP_EOR; |
| 1515 | case 0x2: | 1307 | case 0x2: |
| 1516 | return OP_SUB; | 1308 | return OP_SUB; |
| 1517 | case 0x3: | 1309 | case 0x3: |
| 1518 | return OP_RSB; | 1310 | return OP_RSB; |
| 1519 | case 0x4: | 1311 | case 0x4: |
| 1520 | return OP_ADD; | 1312 | return OP_ADD; |
| 1521 | case 0x5: | 1313 | case 0x5: |
| 1522 | return OP_ADC; | 1314 | return OP_ADC; |
| 1523 | case 0x6: | 1315 | case 0x6: |
| 1524 | return OP_SBC; | 1316 | return OP_SBC; |
| 1525 | case 0x7: | 1317 | case 0x7: |
| 1526 | return OP_RSC; | 1318 | return OP_RSC; |
| 1527 | case 0x8: | 1319 | case 0x8: |
| 1528 | if (bit_s) | 1320 | if (bit_s) |
| 1529 | return OP_TST; | 1321 | return OP_TST; |
| 1530 | return OP_MRS; | 1322 | return OP_MRS; |
| 1531 | case 0x9: | 1323 | case 0x9: |
| 1532 | if (bit_s) | 1324 | if (bit_s) |
| 1533 | return OP_TEQ; | 1325 | return OP_TEQ; |
| 1534 | return OP_MSR; | 1326 | return OP_MSR; |
| 1535 | case 0xa: | 1327 | case 0xa: |
| 1536 | if (bit_s) | 1328 | if (bit_s) |
| 1537 | return OP_CMP; | 1329 | return OP_CMP; |
| 1538 | return OP_MRS; | 1330 | return OP_MRS; |
| 1539 | case 0xb: | 1331 | case 0xb: |
| 1540 | if (bit_s) | 1332 | if (bit_s) |
| 1541 | return OP_CMN; | 1333 | return OP_CMN; |
| 1542 | return OP_MSR; | 1334 | return OP_MSR; |
| 1543 | case 0xc: | 1335 | case 0xc: |
| 1544 | return OP_ORR; | 1336 | return OP_ORR; |
| 1545 | case 0xd: | 1337 | case 0xd: |
| 1546 | return OP_MOV; | 1338 | return OP_MOV; |
| 1547 | case 0xe: | 1339 | case 0xe: |
| 1548 | return OP_BIC; | 1340 | return OP_BIC; |
| 1549 | case 0xf: | 1341 | case 0xf: |
| 1550 | return OP_MVN; | 1342 | return OP_MVN; |
| 1551 | } | 1343 | } |
| 1552 | // Unreachable | 1344 | // Unreachable |
| 1553 | return OP_INVALID; | 1345 | return OP_INVALID; |
diff --git a/src/core/arm/disassembler/arm_disasm.h b/src/core/arm/disassembler/arm_disasm.h index 53d9c6a74..031f973d6 100644 --- a/src/core/arm/disassembler/arm_disasm.h +++ b/src/core/arm/disassembler/arm_disasm.h | |||
| @@ -187,53 +187,53 @@ enum Opcode { | |||
| 187 | OP_THUMB_SWI, | 187 | OP_THUMB_SWI, |
| 188 | OP_THUMB_TST, | 188 | OP_THUMB_TST, |
| 189 | 189 | ||
| 190 | OP_END // must be last | 190 | OP_END // must be last |
| 191 | }; | 191 | }; |
| 192 | 192 | ||
| 193 | class ARM_Disasm { | 193 | class ARM_Disasm { |
| 194 | public: | 194 | public: |
| 195 | static std::string Disassemble(u32 addr, u32 insn); | 195 | static std::string Disassemble(u32 addr, u32 insn); |
| 196 | static Opcode Decode(u32 insn); | 196 | static Opcode Decode(u32 insn); |
| 197 | 197 | ||
| 198 | private: | 198 | private: |
| 199 | static Opcode Decode00(u32 insn); | 199 | static Opcode Decode00(u32 insn); |
| 200 | static Opcode Decode01(u32 insn); | 200 | static Opcode Decode01(u32 insn); |
| 201 | static Opcode Decode10(u32 insn); | 201 | static Opcode Decode10(u32 insn); |
| 202 | static Opcode Decode11(u32 insn); | 202 | static Opcode Decode11(u32 insn); |
| 203 | static Opcode DecodeSyncPrimitive(u32 insn); | 203 | static Opcode DecodeSyncPrimitive(u32 insn); |
| 204 | static Opcode DecodeParallelAddSub(u32 insn); | 204 | static Opcode DecodeParallelAddSub(u32 insn); |
| 205 | static Opcode DecodePackingSaturationReversal(u32 insn); | 205 | static Opcode DecodePackingSaturationReversal(u32 insn); |
| 206 | static Opcode DecodeMUL(u32 insn); | 206 | static Opcode DecodeMUL(u32 insn); |
| 207 | static Opcode DecodeMSRImmAndHints(u32 insn); | 207 | static Opcode DecodeMSRImmAndHints(u32 insn); |
| 208 | static Opcode DecodeMediaMulDiv(u32 insn); | 208 | static Opcode DecodeMediaMulDiv(u32 insn); |
| 209 | static Opcode DecodeMedia(u32 insn); | 209 | static Opcode DecodeMedia(u32 insn); |
| 210 | static Opcode DecodeLDRH(u32 insn); | 210 | static Opcode DecodeLDRH(u32 insn); |
| 211 | static Opcode DecodeALU(u32 insn); | 211 | static Opcode DecodeALU(u32 insn); |
| 212 | 212 | ||
| 213 | static std::string DisassembleALU(Opcode opcode, u32 insn); | 213 | static std::string DisassembleALU(Opcode opcode, u32 insn); |
| 214 | static std::string DisassembleBranch(u32 addr, Opcode opcode, u32 insn); | 214 | static std::string DisassembleBranch(u32 addr, Opcode opcode, u32 insn); |
| 215 | static std::string DisassembleBX(u32 insn); | 215 | static std::string DisassembleBX(u32 insn); |
| 216 | static std::string DisassembleBKPT(u32 insn); | 216 | static std::string DisassembleBKPT(u32 insn); |
| 217 | static std::string DisassembleCLZ(u32 insn); | 217 | static std::string DisassembleCLZ(u32 insn); |
| 218 | static std::string DisassembleMediaMulDiv(Opcode opcode, u32 insn); | 218 | static std::string DisassembleMediaMulDiv(Opcode opcode, u32 insn); |
| 219 | static std::string DisassembleMemblock(Opcode opcode, u32 insn); | 219 | static std::string DisassembleMemblock(Opcode opcode, u32 insn); |
| 220 | static std::string DisassembleMem(u32 insn); | 220 | static std::string DisassembleMem(u32 insn); |
| 221 | static std::string DisassembleMemHalf(u32 insn); | 221 | static std::string DisassembleMemHalf(u32 insn); |
| 222 | static std::string DisassembleMCR(Opcode opcode, u32 insn); | 222 | static std::string DisassembleMCR(Opcode opcode, u32 insn); |
| 223 | static std::string DisassembleMLA(Opcode opcode, u32 insn); | 223 | static std::string DisassembleMLA(Opcode opcode, u32 insn); |
| 224 | static std::string DisassembleUMLAL(Opcode opcode, u32 insn); | 224 | static std::string DisassembleUMLAL(Opcode opcode, u32 insn); |
| 225 | static std::string DisassembleMUL(Opcode opcode, u32 insn); | 225 | static std::string DisassembleMUL(Opcode opcode, u32 insn); |
| 226 | static std::string DisassembleMRS(u32 insn); | 226 | static std::string DisassembleMRS(u32 insn); |
| 227 | static std::string DisassembleMSR(u32 insn); | 227 | static std::string DisassembleMSR(u32 insn); |
| 228 | static std::string DisassembleNoOperands(Opcode opcode, u32 insn); | 228 | static std::string DisassembleNoOperands(Opcode opcode, u32 insn); |
| 229 | static std::string DisassembleParallelAddSub(Opcode opcode, u32 insn); | 229 | static std::string DisassembleParallelAddSub(Opcode opcode, u32 insn); |
| 230 | static std::string DisassemblePKH(u32 insn); | 230 | static std::string DisassemblePKH(u32 insn); |
| 231 | static std::string DisassemblePLD(u32 insn); | 231 | static std::string DisassemblePLD(u32 insn); |
| 232 | static std::string DisassembleREV(Opcode opcode, u32 insn); | 232 | static std::string DisassembleREV(Opcode opcode, u32 insn); |
| 233 | static std::string DisassembleREX(Opcode opcode, u32 insn); | 233 | static std::string DisassembleREX(Opcode opcode, u32 insn); |
| 234 | static std::string DisassembleSAT(Opcode opcode, u32 insn); | 234 | static std::string DisassembleSAT(Opcode opcode, u32 insn); |
| 235 | static std::string DisassembleSEL(u32 insn); | 235 | static std::string DisassembleSEL(u32 insn); |
| 236 | static std::string DisassembleSWI(u32 insn); | 236 | static std::string DisassembleSWI(u32 insn); |
| 237 | static std::string DisassembleSWP(Opcode opcode, u32 insn); | 237 | static std::string DisassembleSWP(Opcode opcode, u32 insn); |
| 238 | static std::string DisassembleXT(Opcode opcode, u32 insn); | 238 | static std::string DisassembleXT(Opcode opcode, u32 insn); |
| 239 | }; | 239 | }; |
diff --git a/src/core/arm/disassembler/load_symbol_map.cpp b/src/core/arm/disassembler/load_symbol_map.cpp index eb20bf6f7..58e8e6fa1 100644 --- a/src/core/arm/disassembler/load_symbol_map.cpp +++ b/src/core/arm/disassembler/load_symbol_map.cpp | |||
| @@ -6,8 +6,8 @@ | |||
| 6 | #include <string> | 6 | #include <string> |
| 7 | #include <vector> | 7 | #include <vector> |
| 8 | 8 | ||
| 9 | #include "common/symbols.h" | ||
| 10 | #include "common/file_util.h" | 9 | #include "common/file_util.h" |
| 10 | #include "common/symbols.h" | ||
| 11 | 11 | ||
| 12 | #include "core/arm/disassembler/load_symbol_map.h" | 12 | #include "core/arm/disassembler/load_symbol_map.h" |
| 13 | 13 | ||
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp index 6dbc92b91..64dcaae08 100644 --- a/src/core/arm/dyncom/arm_dyncom_dec.cpp +++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp | |||
| @@ -430,12 +430,15 @@ ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) { | |||
| 430 | continue; | 430 | continue; |
| 431 | 431 | ||
| 432 | while (n) { | 432 | while (n) { |
| 433 | if (arm_instruction[i].content[base + 1] == 31 && arm_instruction[i].content[base] == 0) { | 433 | if (arm_instruction[i].content[base + 1] == 31 && |
| 434 | arm_instruction[i].content[base] == 0) { | ||
| 434 | // clrex | 435 | // clrex |
| 435 | if (instr != arm_instruction[i].content[base + 2]) { | 436 | if (instr != arm_instruction[i].content[base + 2]) { |
| 436 | break; | 437 | break; |
| 437 | } | 438 | } |
| 438 | } else if (BITS(instr, arm_instruction[i].content[base], arm_instruction[i].content[base + 1]) != arm_instruction[i].content[base + 2]) { | 439 | } else if (BITS(instr, arm_instruction[i].content[base], |
| 440 | arm_instruction[i].content[base + 1]) != | ||
| 441 | arm_instruction[i].content[base + 2]) { | ||
| 439 | break; | 442 | break; |
| 440 | } | 443 | } |
| 441 | base += 3; | 444 | base += 3; |
| @@ -451,7 +454,9 @@ ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) { | |||
| 451 | if (n != 0) { | 454 | if (n != 0) { |
| 452 | base = 0; | 455 | base = 0; |
| 453 | while (n) { | 456 | while (n) { |
| 454 | if (BITS(instr, arm_exclusion_code[i].content[base], arm_exclusion_code[i].content[base + 1]) != arm_exclusion_code[i].content[base + 2]) { | 457 | if (BITS(instr, arm_exclusion_code[i].content[base], |
| 458 | arm_exclusion_code[i].content[base + 1]) != | ||
| 459 | arm_exclusion_code[i].content[base + 2]) { | ||
| 455 | break; | 460 | break; |
| 456 | } | 461 | } |
| 457 | base += 3; | 462 | base += 3; |
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.h b/src/core/arm/dyncom/arm_dyncom_dec.h index d7170e0fc..2fb7ac37c 100644 --- a/src/core/arm/dyncom/arm_dyncom_dec.h +++ b/src/core/arm/dyncom/arm_dyncom_dec.h | |||
| @@ -6,15 +6,12 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | 8 | ||
| 9 | enum class ARMDecodeStatus { | 9 | enum class ARMDecodeStatus { SUCCESS, FAILURE }; |
| 10 | SUCCESS, | ||
| 11 | FAILURE | ||
| 12 | }; | ||
| 13 | 10 | ||
| 14 | ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx); | 11 | ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx); |
| 15 | 12 | ||
| 16 | struct InstructionSetEncodingItem { | 13 | struct InstructionSetEncodingItem { |
| 17 | const char *name; | 14 | const char* name; |
| 18 | int attribute_value; | 15 | int attribute_value; |
| 19 | int version; | 16 | int version; |
| 20 | u32 content[21]; | 17 | u32 content[21]; |
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index c8d45c6db..211d49edb 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp | |||
| @@ -11,29 +11,29 @@ | |||
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "common/microprofile.h" | 12 | #include "common/microprofile.h" |
| 13 | 13 | ||
| 14 | #include "core/memory.h" | ||
| 15 | #include "core/hle/svc.h" | ||
| 16 | #include "core/arm/disassembler/arm_disasm.h" | 14 | #include "core/arm/disassembler/arm_disasm.h" |
| 17 | #include "core/arm/dyncom/arm_dyncom_dec.h" | 15 | #include "core/arm/dyncom/arm_dyncom_dec.h" |
| 18 | #include "core/arm/dyncom/arm_dyncom_interpreter.h" | 16 | #include "core/arm/dyncom/arm_dyncom_interpreter.h" |
| 17 | #include "core/arm/dyncom/arm_dyncom_run.h" | ||
| 19 | #include "core/arm/dyncom/arm_dyncom_thumb.h" | 18 | #include "core/arm/dyncom/arm_dyncom_thumb.h" |
| 20 | #include "core/arm/dyncom/arm_dyncom_trans.h" | 19 | #include "core/arm/dyncom/arm_dyncom_trans.h" |
| 21 | #include "core/arm/dyncom/arm_dyncom_run.h" | ||
| 22 | #include "core/arm/skyeye_common/armstate.h" | 20 | #include "core/arm/skyeye_common/armstate.h" |
| 23 | #include "core/arm/skyeye_common/armsupp.h" | 21 | #include "core/arm/skyeye_common/armsupp.h" |
| 24 | #include "core/arm/skyeye_common/vfp/vfp.h" | 22 | #include "core/arm/skyeye_common/vfp/vfp.h" |
| 23 | #include "core/hle/svc.h" | ||
| 24 | #include "core/memory.h" | ||
| 25 | 25 | ||
| 26 | #include "core/gdbstub/gdbstub.h" | 26 | #include "core/gdbstub/gdbstub.h" |
| 27 | 27 | ||
| 28 | #define RM BITS(sht_oper, 0, 3) | 28 | #define RM BITS(sht_oper, 0, 3) |
| 29 | #define RS BITS(sht_oper, 8, 11) | 29 | #define RS BITS(sht_oper, 8, 11) |
| 30 | 30 | ||
| 31 | #define glue(x, y) x ## y | 31 | #define glue(x, y) x##y |
| 32 | #define DPO(s) glue(DataProcessingOperands, s) | 32 | #define DPO(s) glue(DataProcessingOperands, s) |
| 33 | #define ROTATE_RIGHT(n, i, l) ((n << (l - i)) | (n >> i)) | 33 | #define ROTATE_RIGHT(n, i, l) ((n << (l - i)) | (n >> i)) |
| 34 | #define ROTATE_LEFT(n, i, l) ((n >> (l - i)) | (n << i)) | 34 | #define ROTATE_LEFT(n, i, l) ((n >> (l - i)) | (n << i)) |
| 35 | #define ROTATE_RIGHT_32(n, i) ROTATE_RIGHT(n, i, 32) | 35 | #define ROTATE_RIGHT_32(n, i) ROTATE_RIGHT(n, i, 32) |
| 36 | #define ROTATE_LEFT_32(n, i) ROTATE_LEFT(n, i, 32) | 36 | #define ROTATE_LEFT_32(n, i) ROTATE_LEFT(n, i, 32) |
| 37 | 37 | ||
| 38 | static bool CondPassed(const ARMul_State* cpu, unsigned int cond) { | 38 | static bool CondPassed(const ARMul_State* cpu, unsigned int cond) { |
| 39 | const bool n_flag = cpu->NFlag != 0; | 39 | const bool n_flag = cpu->NFlag != 0; |
| @@ -232,17 +232,19 @@ static unsigned int DPO(RotateRightByRegister)(ARMul_State* cpu, unsigned int sh | |||
| 232 | return shifter_operand; | 232 | return shifter_operand; |
| 233 | } | 233 | } |
| 234 | 234 | ||
| 235 | #define DEBUG_MSG LOG_DEBUG(Core_ARM11, "inst is %x", inst); CITRA_IGNORE_EXIT(0) | 235 | #define DEBUG_MSG \ |
| 236 | LOG_DEBUG(Core_ARM11, "inst is %x", inst); \ | ||
| 237 | CITRA_IGNORE_EXIT(0) | ||
| 236 | 238 | ||
| 237 | #define LnSWoUB(s) glue(LnSWoUB, s) | 239 | #define LnSWoUB(s) glue(LnSWoUB, s) |
| 238 | #define MLnS(s) glue(MLnS, s) | 240 | #define MLnS(s) glue(MLnS, s) |
| 239 | #define LdnStM(s) glue(LdnStM, s) | 241 | #define LdnStM(s) glue(LdnStM, s) |
| 240 | 242 | ||
| 241 | #define W_BIT BIT(inst, 21) | 243 | #define W_BIT BIT(inst, 21) |
| 242 | #define U_BIT BIT(inst, 23) | 244 | #define U_BIT BIT(inst, 23) |
| 243 | #define I_BIT BIT(inst, 25) | 245 | #define I_BIT BIT(inst, 25) |
| 244 | #define P_BIT BIT(inst, 24) | 246 | #define P_BIT BIT(inst, 24) |
| 245 | #define OFFSET_12 BITS(inst, 0, 11) | 247 | #define OFFSET_12 BITS(inst, 0, 11) |
| 246 | 248 | ||
| 247 | static void LnSWoUB(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { | 249 | static void LnSWoUB(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { |
| 248 | unsigned int Rn = BITS(inst, 16, 19); | 250 | unsigned int Rn = BITS(inst, 16, 19); |
| @@ -271,7 +273,8 @@ static void LnSWoUB(RegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigne | |||
| 271 | virt_addr = addr; | 273 | virt_addr = addr; |
| 272 | } | 274 | } |
| 273 | 275 | ||
| 274 | static void LnSWoUB(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { | 276 | static void LnSWoUB(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst, |
| 277 | unsigned int& virt_addr) { | ||
| 275 | unsigned int Rn = BITS(inst, 16, 19); | 278 | unsigned int Rn = BITS(inst, 16, 19); |
| 276 | unsigned int addr = CHECK_READ_REG15_WA(cpu, Rn); | 279 | unsigned int addr = CHECK_READ_REG15_WA(cpu, Rn); |
| 277 | 280 | ||
| @@ -283,7 +286,8 @@ static void LnSWoUB(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst, u | |||
| 283 | virt_addr = addr; | 286 | virt_addr = addr; |
| 284 | } | 287 | } |
| 285 | 288 | ||
| 286 | static void LnSWoUB(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { | 289 | static void LnSWoUB(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst, |
| 290 | unsigned int& virt_addr) { | ||
| 287 | unsigned int Rn = BITS(inst, 16, 19); | 291 | unsigned int Rn = BITS(inst, 16, 19); |
| 288 | unsigned int addr; | 292 | unsigned int addr; |
| 289 | 293 | ||
| @@ -301,7 +305,7 @@ static void LnSWoUB(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst, un | |||
| 301 | static void MLnS(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { | 305 | static void MLnS(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { |
| 302 | unsigned int addr; | 306 | unsigned int addr; |
| 303 | unsigned int Rn = BITS(inst, 16, 19); | 307 | unsigned int Rn = BITS(inst, 16, 19); |
| 304 | unsigned int Rm = BITS(inst, 0, 3); | 308 | unsigned int Rm = BITS(inst, 0, 3); |
| 305 | unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); | 309 | unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); |
| 306 | unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); | 310 | unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); |
| 307 | 311 | ||
| @@ -316,7 +320,8 @@ static void MLnS(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsign | |||
| 316 | cpu->Reg[Rn] = addr; | 320 | cpu->Reg[Rn] = addr; |
| 317 | } | 321 | } |
| 318 | 322 | ||
| 319 | static void LnSWoUB(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { | 323 | static void LnSWoUB(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, |
| 324 | unsigned int& virt_addr) { | ||
| 320 | unsigned int Rn = BITS(inst, 16, 19); | 325 | unsigned int Rn = BITS(inst, 16, 19); |
| 321 | unsigned int Rm = BITS(inst, 0, 3); | 326 | unsigned int Rm = BITS(inst, 0, 3); |
| 322 | unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); | 327 | unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); |
| @@ -335,7 +340,8 @@ static void LnSWoUB(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, uns | |||
| 335 | } | 340 | } |
| 336 | } | 341 | } |
| 337 | 342 | ||
| 338 | static void LnSWoUB(ScaledRegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { | 343 | static void LnSWoUB(ScaledRegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, |
| 344 | unsigned int& virt_addr) { | ||
| 339 | unsigned int shift = BITS(inst, 5, 6); | 345 | unsigned int shift = BITS(inst, 5, 6); |
| 340 | unsigned int shift_imm = BITS(inst, 7, 11); | 346 | unsigned int shift_imm = BITS(inst, 7, 11); |
| 341 | unsigned int Rn = BITS(inst, 16, 19); | 347 | unsigned int Rn = BITS(inst, 16, 19); |
| @@ -386,7 +392,8 @@ static void LnSWoUB(ScaledRegisterPreIndexed)(ARMul_State* cpu, unsigned int ins | |||
| 386 | cpu->Reg[Rn] = addr; | 392 | cpu->Reg[Rn] = addr; |
| 387 | } | 393 | } |
| 388 | 394 | ||
| 389 | static void LnSWoUB(ScaledRegisterPostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { | 395 | static void LnSWoUB(ScaledRegisterPostIndexed)(ARMul_State* cpu, unsigned int inst, |
| 396 | unsigned int& virt_addr) { | ||
| 390 | unsigned int shift = BITS(inst, 5, 6); | 397 | unsigned int shift = BITS(inst, 5, 6); |
| 391 | unsigned int shift_imm = BITS(inst, 7, 11); | 398 | unsigned int shift_imm = BITS(inst, 7, 11); |
| 392 | unsigned int Rn = BITS(inst, 16, 19); | 399 | unsigned int Rn = BITS(inst, 16, 19); |
| @@ -435,9 +442,10 @@ static void LnSWoUB(ScaledRegisterPostIndexed)(ARMul_State* cpu, unsigned int in | |||
| 435 | } | 442 | } |
| 436 | } | 443 | } |
| 437 | 444 | ||
| 438 | static void LnSWoUB(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { | 445 | static void LnSWoUB(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst, |
| 446 | unsigned int& virt_addr) { | ||
| 439 | unsigned int Rn = BITS(inst, 16, 19); | 447 | unsigned int Rn = BITS(inst, 16, 19); |
| 440 | unsigned int Rm = BITS(inst, 0, 3); | 448 | unsigned int Rm = BITS(inst, 0, 3); |
| 441 | unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); | 449 | unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); |
| 442 | 450 | ||
| 443 | virt_addr = CHECK_READ_REG15_WA(cpu, Rn); | 451 | virt_addr = CHECK_READ_REG15_WA(cpu, Rn); |
| @@ -454,7 +462,7 @@ static void LnSWoUB(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst, un | |||
| 454 | static void MLnS(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { | 462 | static void MLnS(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { |
| 455 | unsigned int immedL = BITS(inst, 0, 3); | 463 | unsigned int immedL = BITS(inst, 0, 3); |
| 456 | unsigned int immedH = BITS(inst, 8, 11); | 464 | unsigned int immedH = BITS(inst, 8, 11); |
| 457 | unsigned int Rn = BITS(inst, 16, 19); | 465 | unsigned int Rn = BITS(inst, 16, 19); |
| 458 | unsigned int addr; | 466 | unsigned int addr; |
| 459 | 467 | ||
| 460 | unsigned int offset_8 = (immedH << 4) | immedL; | 468 | unsigned int offset_8 = (immedH << 4) | immedL; |
| @@ -470,7 +478,7 @@ static void MLnS(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned | |||
| 470 | static void MLnS(RegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { | 478 | static void MLnS(RegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { |
| 471 | unsigned int addr; | 479 | unsigned int addr; |
| 472 | unsigned int Rn = BITS(inst, 16, 19); | 480 | unsigned int Rn = BITS(inst, 16, 19); |
| 473 | unsigned int Rm = BITS(inst, 0, 3); | 481 | unsigned int Rm = BITS(inst, 0, 3); |
| 474 | unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); | 482 | unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); |
| 475 | unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); | 483 | unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); |
| 476 | 484 | ||
| @@ -482,10 +490,11 @@ static void MLnS(RegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned i | |||
| 482 | virt_addr = addr; | 490 | virt_addr = addr; |
| 483 | } | 491 | } |
| 484 | 492 | ||
| 485 | static void MLnS(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { | 493 | static void MLnS(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst, |
| 486 | unsigned int Rn = BITS(inst, 16, 19); | 494 | unsigned int& virt_addr) { |
| 487 | unsigned int immedH = BITS(inst, 8, 11); | 495 | unsigned int Rn = BITS(inst, 16, 19); |
| 488 | unsigned int immedL = BITS(inst, 0, 3); | 496 | unsigned int immedH = BITS(inst, 8, 11); |
| 497 | unsigned int immedL = BITS(inst, 0, 3); | ||
| 489 | unsigned int addr; | 498 | unsigned int addr; |
| 490 | unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); | 499 | unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); |
| 491 | unsigned int offset_8 = (immedH << 4) | immedL; | 500 | unsigned int offset_8 = (immedH << 4) | immedL; |
| @@ -501,10 +510,11 @@ static void MLnS(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst, unsig | |||
| 501 | cpu->Reg[Rn] = addr; | 510 | cpu->Reg[Rn] = addr; |
| 502 | } | 511 | } |
| 503 | 512 | ||
| 504 | static void MLnS(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { | 513 | static void MLnS(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst, |
| 505 | unsigned int Rn = BITS(inst, 16, 19); | 514 | unsigned int& virt_addr) { |
| 506 | unsigned int immedH = BITS(inst, 8, 11); | 515 | unsigned int Rn = BITS(inst, 16, 19); |
| 507 | unsigned int immedL = BITS(inst, 0, 3); | 516 | unsigned int immedH = BITS(inst, 8, 11); |
| 517 | unsigned int immedL = BITS(inst, 0, 3); | ||
| 508 | unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); | 518 | unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); |
| 509 | 519 | ||
| 510 | virt_addr = rn; | 520 | virt_addr = rn; |
| @@ -520,9 +530,10 @@ static void MLnS(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst, unsi | |||
| 520 | } | 530 | } |
| 521 | } | 531 | } |
| 522 | 532 | ||
| 523 | static void MLnS(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { | 533 | static void MLnS(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst, |
| 534 | unsigned int& virt_addr) { | ||
| 524 | unsigned int Rn = BITS(inst, 16, 19); | 535 | unsigned int Rn = BITS(inst, 16, 19); |
| 525 | unsigned int Rm = BITS(inst, 0, 3); | 536 | unsigned int Rm = BITS(inst, 0, 3); |
| 526 | unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); | 537 | unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); |
| 527 | 538 | ||
| 528 | virt_addr = CHECK_READ_REG15_WA(cpu, Rn); | 539 | virt_addr = CHECK_READ_REG15_WA(cpu, Rn); |
| @@ -541,7 +552,8 @@ static void LdnStM(DecrementBefore)(ARMul_State* cpu, unsigned int inst, unsigne | |||
| 541 | int count = 0; | 552 | int count = 0; |
| 542 | 553 | ||
| 543 | while (i) { | 554 | while (i) { |
| 544 | if (i & 1) count++; | 555 | if (i & 1) |
| 556 | count++; | ||
| 545 | i = i >> 1; | 557 | i = i >> 1; |
| 546 | } | 558 | } |
| 547 | 559 | ||
| @@ -557,7 +569,8 @@ static void LdnStM(IncrementBefore)(ARMul_State* cpu, unsigned int inst, unsigne | |||
| 557 | int count = 0; | 569 | int count = 0; |
| 558 | 570 | ||
| 559 | while (i) { | 571 | while (i) { |
| 560 | if (i & 1) count++; | 572 | if (i & 1) |
| 573 | count++; | ||
| 561 | i = i >> 1; | 574 | i = i >> 1; |
| 562 | } | 575 | } |
| 563 | 576 | ||
| @@ -572,8 +585,9 @@ static void LdnStM(IncrementAfter)(ARMul_State* cpu, unsigned int inst, unsigned | |||
| 572 | unsigned int i = BITS(inst, 0, 15); | 585 | unsigned int i = BITS(inst, 0, 15); |
| 573 | int count = 0; | 586 | int count = 0; |
| 574 | 587 | ||
| 575 | while(i) { | 588 | while (i) { |
| 576 | if (i & 1) count++; | 589 | if (i & 1) |
| 590 | count++; | ||
| 577 | i = i >> 1; | 591 | i = i >> 1; |
| 578 | } | 592 | } |
| 579 | 593 | ||
| @@ -587,8 +601,9 @@ static void LdnStM(DecrementAfter)(ARMul_State* cpu, unsigned int inst, unsigned | |||
| 587 | unsigned int Rn = BITS(inst, 16, 19); | 601 | unsigned int Rn = BITS(inst, 16, 19); |
| 588 | unsigned int i = BITS(inst, 0, 15); | 602 | unsigned int i = BITS(inst, 0, 15); |
| 589 | int count = 0; | 603 | int count = 0; |
| 590 | while(i) { | 604 | while (i) { |
| 591 | if(i & 1) count++; | 605 | if (i & 1) |
| 606 | count++; | ||
| 592 | i = i >> 1; | 607 | i = i >> 1; |
| 593 | } | 608 | } |
| 594 | unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); | 609 | unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); |
| @@ -601,7 +616,8 @@ static void LdnStM(DecrementAfter)(ARMul_State* cpu, unsigned int inst, unsigned | |||
| 601 | } | 616 | } |
| 602 | } | 617 | } |
| 603 | 618 | ||
| 604 | static void LnSWoUB(ScaledRegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { | 619 | static void LnSWoUB(ScaledRegisterOffset)(ARMul_State* cpu, unsigned int inst, |
| 620 | unsigned int& virt_addr) { | ||
| 605 | unsigned int shift = BITS(inst, 5, 6); | 621 | unsigned int shift = BITS(inst, 5, 6); |
| 606 | unsigned int shift_imm = BITS(inst, 7, 11); | 622 | unsigned int shift_imm = BITS(inst, 7, 11); |
| 607 | unsigned int Rn = BITS(inst, 16, 19); | 623 | unsigned int Rn = BITS(inst, 16, 19); |
| @@ -693,17 +709,23 @@ get_addr_fp_t GetAddressingOp(unsigned int inst) { | |||
| 693 | return LnSWoUB(RegisterPostIndexed); | 709 | return LnSWoUB(RegisterPostIndexed); |
| 694 | } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) { | 710 | } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) { |
| 695 | return LnSWoUB(ScaledRegisterPostIndexed); | 711 | return LnSWoUB(ScaledRegisterPostIndexed); |
| 696 | } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { | 712 | } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 && |
| 713 | BIT(inst, 4) == 1) { | ||
| 697 | return MLnS(ImmediateOffset); | 714 | return MLnS(ImmediateOffset); |
| 698 | } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { | 715 | } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 && |
| 716 | BIT(inst, 4) == 1) { | ||
| 699 | return MLnS(RegisterOffset); | 717 | return MLnS(RegisterOffset); |
| 700 | } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 3 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { | 718 | } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 3 && BIT(inst, 7) == 1 && |
| 719 | BIT(inst, 4) == 1) { | ||
| 701 | return MLnS(ImmediatePreIndexed); | 720 | return MLnS(ImmediatePreIndexed); |
| 702 | } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 1 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { | 721 | } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 1 && BIT(inst, 7) == 1 && |
| 722 | BIT(inst, 4) == 1) { | ||
| 703 | return MLnS(RegisterPreIndexed); | 723 | return MLnS(RegisterPreIndexed); |
| 704 | } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { | 724 | } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 && |
| 725 | BIT(inst, 4) == 1) { | ||
| 705 | return MLnS(ImmediatePostIndexed); | 726 | return MLnS(ImmediatePostIndexed); |
| 706 | } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { | 727 | } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 && |
| 728 | BIT(inst, 4) == 1) { | ||
| 707 | return MLnS(RegisterPostIndexed); | 729 | return MLnS(RegisterPostIndexed); |
| 708 | } else if (BITS(inst, 23, 27) == 0x11) { | 730 | } else if (BITS(inst, 23, 27) == 0x11) { |
| 709 | return LdnStM(IncrementAfter); | 731 | return LdnStM(IncrementAfter); |
| @@ -732,14 +754,12 @@ get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst) { | |||
| 732 | return nullptr; | 754 | return nullptr; |
| 733 | } | 755 | } |
| 734 | 756 | ||
| 735 | enum { | 757 | enum { FETCH_SUCCESS, FETCH_FAILURE }; |
| 736 | FETCH_SUCCESS, | ||
| 737 | FETCH_FAILURE | ||
| 738 | }; | ||
| 739 | 758 | ||
| 740 | static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_inst, u32* inst_size, ARM_INST_PTR* ptr_inst_base) { | 759 | static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_inst, u32* inst_size, |
| 760 | ARM_INST_PTR* ptr_inst_base) { | ||
| 741 | // Check if in Thumb mode | 761 | // Check if in Thumb mode |
| 742 | ThumbDecodeStatus ret = TranslateThumbInstruction (addr, inst, arm_inst, inst_size); | 762 | ThumbDecodeStatus ret = TranslateThumbInstruction(addr, inst, arm_inst, inst_size); |
| 743 | if (ret == ThumbDecodeStatus::BRANCH) { | 763 | if (ret == ThumbDecodeStatus::BRANCH) { |
| 744 | int inst_index; | 764 | int inst_index; |
| 745 | int table_length = arm_instruction_trans_len; | 765 | int table_length = arm_instruction_trans_len; |
| @@ -748,7 +768,7 @@ static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_ins | |||
| 748 | switch ((tinstr & 0xF800) >> 11) { | 768 | switch ((tinstr & 0xF800) >> 11) { |
| 749 | case 26: | 769 | case 26: |
| 750 | case 27: | 770 | case 27: |
| 751 | if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)){ | 771 | if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)) { |
| 752 | inst_index = table_length - 4; | 772 | inst_index = table_length - 4; |
| 753 | *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); | 773 | *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); |
| 754 | } else { | 774 | } else { |
| @@ -785,21 +805,21 @@ static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_ins | |||
| 785 | return ret; | 805 | return ret; |
| 786 | } | 806 | } |
| 787 | 807 | ||
| 788 | enum { | 808 | enum { KEEP_GOING, FETCH_EXCEPTION }; |
| 789 | KEEP_GOING, | ||
| 790 | FETCH_EXCEPTION | ||
| 791 | }; | ||
| 792 | 809 | ||
| 793 | MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64)); | 810 | MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64)); |
| 794 | 811 | ||
| 795 | static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr, ARM_INST_PTR& inst_base) { | 812 | static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr, |
| 813 | ARM_INST_PTR& inst_base) { | ||
| 796 | unsigned int inst_size = 4; | 814 | unsigned int inst_size = 4; |
| 797 | unsigned int inst = Memory::Read32(phys_addr & 0xFFFFFFFC); | 815 | unsigned int inst = Memory::Read32(phys_addr & 0xFFFFFFFC); |
| 798 | 816 | ||
| 799 | // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction | 817 | // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM |
| 818 | // instruction | ||
| 800 | if (cpu->TFlag) { | 819 | if (cpu->TFlag) { |
| 801 | u32 arm_inst; | 820 | u32 arm_inst; |
| 802 | ThumbDecodeStatus state = DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base); | 821 | ThumbDecodeStatus state = |
| 822 | DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base); | ||
| 803 | 823 | ||
| 804 | // We have translated the Thumb branch instruction in the Thumb decoder | 824 | // We have translated the Thumb branch instruction in the Thumb decoder |
| 805 | if (state == ThumbDecodeStatus::BRANCH) { | 825 | if (state == ThumbDecodeStatus::BRANCH) { |
| @@ -811,8 +831,10 @@ static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, cons | |||
| 811 | int idx; | 831 | int idx; |
| 812 | if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) { | 832 | if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) { |
| 813 | std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst); | 833 | std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst); |
| 814 | LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr, disasm.c_str(), inst); | 834 | LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr, |
| 815 | LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]); | 835 | disasm.c_str(), inst); |
| 836 | LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, | ||
| 837 | cpu->Reg[15]); | ||
| 816 | CITRA_IGNORE_EXIT(-1); | 838 | CITRA_IGNORE_EXIT(-1); |
| 817 | } | 839 | } |
| 818 | inst_base = arm_instruction_trans[idx](inst, idx); | 840 | inst_base = arm_instruction_trans[idx](inst, idx); |
| @@ -875,12 +897,25 @@ static int InterpreterTranslateSingle(ARMul_State* cpu, int& bb_start, u32 addr) | |||
| 875 | 897 | ||
| 876 | static int clz(unsigned int x) { | 898 | static int clz(unsigned int x) { |
| 877 | int n; | 899 | int n; |
| 878 | if (x == 0) return (32); | 900 | if (x == 0) |
| 901 | return (32); | ||
| 879 | n = 1; | 902 | n = 1; |
| 880 | if ((x >> 16) == 0) { n = n + 16; x = x << 16;} | 903 | if ((x >> 16) == 0) { |
| 881 | if ((x >> 24) == 0) { n = n + 8; x = x << 8;} | 904 | n = n + 16; |
| 882 | if ((x >> 28) == 0) { n = n + 4; x = x << 4;} | 905 | x = x << 16; |
| 883 | if ((x >> 30) == 0) { n = n + 2; x = x << 2;} | 906 | } |
| 907 | if ((x >> 24) == 0) { | ||
| 908 | n = n + 8; | ||
| 909 | x = x << 8; | ||
| 910 | } | ||
| 911 | if ((x >> 28) == 0) { | ||
| 912 | n = n + 4; | ||
| 913 | x = x << 4; | ||
| 914 | } | ||
| 915 | if ((x >> 30) == 0) { | ||
| 916 | n = n + 2; | ||
| 917 | x = x << 2; | ||
| 918 | } | ||
| 884 | n = n - (x >> 31); | 919 | n = n - (x >> 31); |
| 885 | return n; | 920 | return n; |
| 886 | } | 921 | } |
| @@ -892,310 +927,698 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 892 | 927 | ||
| 893 | GDBStub::BreakpointAddress breakpoint_data; | 928 | GDBStub::BreakpointAddress breakpoint_data; |
| 894 | 929 | ||
| 895 | #undef RM | 930 | #undef RM |
| 896 | #undef RS | 931 | #undef RS |
| 897 | 932 | ||
| 898 | #define CRn inst_cream->crn | 933 | #define CRn inst_cream->crn |
| 899 | #define OPCODE_1 inst_cream->opcode_1 | 934 | #define OPCODE_1 inst_cream->opcode_1 |
| 900 | #define OPCODE_2 inst_cream->opcode_2 | 935 | #define OPCODE_2 inst_cream->opcode_2 |
| 901 | #define CRm inst_cream->crm | 936 | #define CRm inst_cream->crm |
| 902 | #define RD cpu->Reg[inst_cream->Rd] | 937 | #define RD cpu->Reg[inst_cream->Rd] |
| 903 | #define RD2 cpu->Reg[inst_cream->Rd + 1] | 938 | #define RD2 cpu->Reg[inst_cream->Rd + 1] |
| 904 | #define RN cpu->Reg[inst_cream->Rn] | 939 | #define RN cpu->Reg[inst_cream->Rn] |
| 905 | #define RM cpu->Reg[inst_cream->Rm] | 940 | #define RM cpu->Reg[inst_cream->Rm] |
| 906 | #define RS cpu->Reg[inst_cream->Rs] | 941 | #define RS cpu->Reg[inst_cream->Rs] |
| 907 | #define RDHI cpu->Reg[inst_cream->RdHi] | 942 | #define RDHI cpu->Reg[inst_cream->RdHi] |
| 908 | #define RDLO cpu->Reg[inst_cream->RdLo] | 943 | #define RDLO cpu->Reg[inst_cream->RdLo] |
| 909 | #define LINK_RTN_ADDR (cpu->Reg[14] = cpu->Reg[15] + 4) | 944 | #define LINK_RTN_ADDR (cpu->Reg[14] = cpu->Reg[15] + 4) |
| 910 | #define SET_PC (cpu->Reg[15] = cpu->Reg[15] + 8 + inst_cream->signed_immed_24) | 945 | #define SET_PC (cpu->Reg[15] = cpu->Reg[15] + 8 + inst_cream->signed_immed_24) |
| 911 | #define SHIFTER_OPERAND inst_cream->shtop_func(cpu, inst_cream->shifter_operand) | 946 | #define SHIFTER_OPERAND inst_cream->shtop_func(cpu, inst_cream->shifter_operand) |
| 912 | 947 | ||
| 913 | #define FETCH_INST if (inst_base->br != TransExtData::NON_BRANCH) goto DISPATCH; \ | 948 | #define FETCH_INST \ |
| 914 | inst_base = (arm_inst *)&trans_cache_buf[ptr] | 949 | if (inst_base->br != TransExtData::NON_BRANCH) \ |
| 915 | 950 | goto DISPATCH; \ | |
| 916 | #define INC_PC(l) ptr += sizeof(arm_inst) + l | 951 | inst_base = (arm_inst*)&trans_cache_buf[ptr] |
| 917 | #define INC_PC_STUB ptr += sizeof(arm_inst) | 952 | |
| 918 | 953 | #define INC_PC(l) ptr += sizeof(arm_inst) + l | |
| 919 | #define GDB_BP_CHECK \ | 954 | #define INC_PC_STUB ptr += sizeof(arm_inst) |
| 920 | cpu->Cpsr &= ~(1 << 5); \ | 955 | |
| 921 | cpu->Cpsr |= cpu->TFlag << 5; \ | 956 | #define GDB_BP_CHECK \ |
| 922 | if (GDBStub::g_server_enabled) { \ | 957 | cpu->Cpsr &= ~(1 << 5); \ |
| 923 | if (GDBStub::IsMemoryBreak() || (breakpoint_data.type != GDBStub::BreakpointType::None && PC == breakpoint_data.address)) { \ | 958 | cpu->Cpsr |= cpu->TFlag << 5; \ |
| 924 | GDBStub::Break(); \ | 959 | if (GDBStub::g_server_enabled) { \ |
| 925 | goto END; \ | 960 | if (GDBStub::IsMemoryBreak() || (breakpoint_data.type != GDBStub::BreakpointType::None && \ |
| 926 | } \ | 961 | PC == breakpoint_data.address)) { \ |
| 962 | GDBStub::Break(); \ | ||
| 963 | goto END; \ | ||
| 964 | } \ | ||
| 927 | } | 965 | } |
| 928 | 966 | ||
| 929 | // GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a | 967 | // GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a |
| 930 | // clunky switch statement. | 968 | // clunky switch statement. |
| 931 | #if defined __GNUC__ || defined __clang__ | 969 | #if defined __GNUC__ || defined __clang__ |
| 932 | #define GOTO_NEXT_INST \ | 970 | #define GOTO_NEXT_INST \ |
| 933 | GDB_BP_CHECK; \ | 971 | GDB_BP_CHECK; \ |
| 934 | if (num_instrs >= cpu->NumInstrsToExecute) goto END; \ | 972 | if (num_instrs >= cpu->NumInstrsToExecute) \ |
| 935 | num_instrs++; \ | 973 | goto END; \ |
| 936 | goto *InstLabel[inst_base->idx] | 974 | num_instrs++; \ |
| 975 | goto* InstLabel[inst_base->idx] | ||
| 937 | #else | 976 | #else |
| 938 | #define GOTO_NEXT_INST \ | 977 | #define GOTO_NEXT_INST \ |
| 939 | GDB_BP_CHECK; \ | 978 | GDB_BP_CHECK; \ |
| 940 | if (num_instrs >= cpu->NumInstrsToExecute) goto END; \ | 979 | if (num_instrs >= cpu->NumInstrsToExecute) \ |
| 941 | num_instrs++; \ | 980 | goto END; \ |
| 942 | switch(inst_base->idx) { \ | 981 | num_instrs++; \ |
| 943 | case 0: goto VMLA_INST; \ | 982 | switch (inst_base->idx) { \ |
| 944 | case 1: goto VMLS_INST; \ | 983 | case 0: \ |
| 945 | case 2: goto VNMLA_INST; \ | 984 | goto VMLA_INST; \ |
| 946 | case 3: goto VNMLS_INST; \ | 985 | case 1: \ |
| 947 | case 4: goto VNMUL_INST; \ | 986 | goto VMLS_INST; \ |
| 948 | case 5: goto VMUL_INST; \ | 987 | case 2: \ |
| 949 | case 6: goto VADD_INST; \ | 988 | goto VNMLA_INST; \ |
| 950 | case 7: goto VSUB_INST; \ | 989 | case 3: \ |
| 951 | case 8: goto VDIV_INST; \ | 990 | goto VNMLS_INST; \ |
| 952 | case 9: goto VMOVI_INST; \ | 991 | case 4: \ |
| 953 | case 10: goto VMOVR_INST; \ | 992 | goto VNMUL_INST; \ |
| 954 | case 11: goto VABS_INST; \ | 993 | case 5: \ |
| 955 | case 12: goto VNEG_INST; \ | 994 | goto VMUL_INST; \ |
| 956 | case 13: goto VSQRT_INST; \ | 995 | case 6: \ |
| 957 | case 14: goto VCMP_INST; \ | 996 | goto VADD_INST; \ |
| 958 | case 15: goto VCMP2_INST; \ | 997 | case 7: \ |
| 959 | case 16: goto VCVTBDS_INST; \ | 998 | goto VSUB_INST; \ |
| 960 | case 17: goto VCVTBFF_INST; \ | 999 | case 8: \ |
| 961 | case 18: goto VCVTBFI_INST; \ | 1000 | goto VDIV_INST; \ |
| 962 | case 19: goto VMOVBRS_INST; \ | 1001 | case 9: \ |
| 963 | case 20: goto VMSR_INST; \ | 1002 | goto VMOVI_INST; \ |
| 964 | case 21: goto VMOVBRC_INST; \ | 1003 | case 10: \ |
| 965 | case 22: goto VMRS_INST; \ | 1004 | goto VMOVR_INST; \ |
| 966 | case 23: goto VMOVBCR_INST; \ | 1005 | case 11: \ |
| 967 | case 24: goto VMOVBRRSS_INST; \ | 1006 | goto VABS_INST; \ |
| 968 | case 25: goto VMOVBRRD_INST; \ | 1007 | case 12: \ |
| 969 | case 26: goto VSTR_INST; \ | 1008 | goto VNEG_INST; \ |
| 970 | case 27: goto VPUSH_INST; \ | 1009 | case 13: \ |
| 971 | case 28: goto VSTM_INST; \ | 1010 | goto VSQRT_INST; \ |
| 972 | case 29: goto VPOP_INST; \ | 1011 | case 14: \ |
| 973 | case 30: goto VLDR_INST; \ | 1012 | goto VCMP_INST; \ |
| 974 | case 31: goto VLDM_INST ; \ | 1013 | case 15: \ |
| 975 | case 32: goto SRS_INST; \ | 1014 | goto VCMP2_INST; \ |
| 976 | case 33: goto RFE_INST; \ | 1015 | case 16: \ |
| 977 | case 34: goto BKPT_INST; \ | 1016 | goto VCVTBDS_INST; \ |
| 978 | case 35: goto BLX_INST; \ | 1017 | case 17: \ |
| 979 | case 36: goto CPS_INST; \ | 1018 | goto VCVTBFF_INST; \ |
| 980 | case 37: goto PLD_INST; \ | 1019 | case 18: \ |
| 981 | case 38: goto SETEND_INST; \ | 1020 | goto VCVTBFI_INST; \ |
| 982 | case 39: goto CLREX_INST; \ | 1021 | case 19: \ |
| 983 | case 40: goto REV16_INST; \ | 1022 | goto VMOVBRS_INST; \ |
| 984 | case 41: goto USAD8_INST; \ | 1023 | case 20: \ |
| 985 | case 42: goto SXTB_INST; \ | 1024 | goto VMSR_INST; \ |
| 986 | case 43: goto UXTB_INST; \ | 1025 | case 21: \ |
| 987 | case 44: goto SXTH_INST; \ | 1026 | goto VMOVBRC_INST; \ |
| 988 | case 45: goto SXTB16_INST; \ | 1027 | case 22: \ |
| 989 | case 46: goto UXTH_INST; \ | 1028 | goto VMRS_INST; \ |
| 990 | case 47: goto UXTB16_INST; \ | 1029 | case 23: \ |
| 991 | case 48: goto CPY_INST; \ | 1030 | goto VMOVBCR_INST; \ |
| 992 | case 49: goto UXTAB_INST; \ | 1031 | case 24: \ |
| 993 | case 50: goto SSUB8_INST; \ | 1032 | goto VMOVBRRSS_INST; \ |
| 994 | case 51: goto SHSUB8_INST; \ | 1033 | case 25: \ |
| 995 | case 52: goto SSUBADDX_INST; \ | 1034 | goto VMOVBRRD_INST; \ |
| 996 | case 53: goto STREX_INST; \ | 1035 | case 26: \ |
| 997 | case 54: goto STREXB_INST; \ | 1036 | goto VSTR_INST; \ |
| 998 | case 55: goto SWP_INST; \ | 1037 | case 27: \ |
| 999 | case 56: goto SWPB_INST; \ | 1038 | goto VPUSH_INST; \ |
| 1000 | case 57: goto SSUB16_INST; \ | 1039 | case 28: \ |
| 1001 | case 58: goto SSAT16_INST; \ | 1040 | goto VSTM_INST; \ |
| 1002 | case 59: goto SHSUBADDX_INST; \ | 1041 | case 29: \ |
| 1003 | case 60: goto QSUBADDX_INST; \ | 1042 | goto VPOP_INST; \ |
| 1004 | case 61: goto SHADDSUBX_INST; \ | 1043 | case 30: \ |
| 1005 | case 62: goto SHADD8_INST; \ | 1044 | goto VLDR_INST; \ |
| 1006 | case 63: goto SHADD16_INST; \ | 1045 | case 31: \ |
| 1007 | case 64: goto SEL_INST; \ | 1046 | goto VLDM_INST; \ |
| 1008 | case 65: goto SADDSUBX_INST; \ | 1047 | case 32: \ |
| 1009 | case 66: goto SADD8_INST; \ | 1048 | goto SRS_INST; \ |
| 1010 | case 67: goto SADD16_INST; \ | 1049 | case 33: \ |
| 1011 | case 68: goto SHSUB16_INST; \ | 1050 | goto RFE_INST; \ |
| 1012 | case 69: goto UMAAL_INST; \ | 1051 | case 34: \ |
| 1013 | case 70: goto UXTAB16_INST; \ | 1052 | goto BKPT_INST; \ |
| 1014 | case 71: goto USUBADDX_INST; \ | 1053 | case 35: \ |
| 1015 | case 72: goto USUB8_INST; \ | 1054 | goto BLX_INST; \ |
| 1016 | case 73: goto USUB16_INST; \ | 1055 | case 36: \ |
| 1017 | case 74: goto USAT16_INST; \ | 1056 | goto CPS_INST; \ |
| 1018 | case 75: goto USADA8_INST; \ | 1057 | case 37: \ |
| 1019 | case 76: goto UQSUBADDX_INST; \ | 1058 | goto PLD_INST; \ |
| 1020 | case 77: goto UQSUB8_INST; \ | 1059 | case 38: \ |
| 1021 | case 78: goto UQSUB16_INST; \ | 1060 | goto SETEND_INST; \ |
| 1022 | case 79: goto UQADDSUBX_INST; \ | 1061 | case 39: \ |
| 1023 | case 80: goto UQADD8_INST; \ | 1062 | goto CLREX_INST; \ |
| 1024 | case 81: goto UQADD16_INST; \ | 1063 | case 40: \ |
| 1025 | case 82: goto SXTAB_INST; \ | 1064 | goto REV16_INST; \ |
| 1026 | case 83: goto UHSUBADDX_INST; \ | 1065 | case 41: \ |
| 1027 | case 84: goto UHSUB8_INST; \ | 1066 | goto USAD8_INST; \ |
| 1028 | case 85: goto UHSUB16_INST; \ | 1067 | case 42: \ |
| 1029 | case 86: goto UHADDSUBX_INST; \ | 1068 | goto SXTB_INST; \ |
| 1030 | case 87: goto UHADD8_INST; \ | 1069 | case 43: \ |
| 1031 | case 88: goto UHADD16_INST; \ | 1070 | goto UXTB_INST; \ |
| 1032 | case 89: goto UADDSUBX_INST; \ | 1071 | case 44: \ |
| 1033 | case 90: goto UADD8_INST; \ | 1072 | goto SXTH_INST; \ |
| 1034 | case 91: goto UADD16_INST; \ | 1073 | case 45: \ |
| 1035 | case 92: goto SXTAH_INST; \ | 1074 | goto SXTB16_INST; \ |
| 1036 | case 93: goto SXTAB16_INST; \ | 1075 | case 46: \ |
| 1037 | case 94: goto QADD8_INST; \ | 1076 | goto UXTH_INST; \ |
| 1038 | case 95: goto BXJ_INST; \ | 1077 | case 47: \ |
| 1039 | case 96: goto CLZ_INST; \ | 1078 | goto UXTB16_INST; \ |
| 1040 | case 97: goto UXTAH_INST; \ | 1079 | case 48: \ |
| 1041 | case 98: goto BX_INST; \ | 1080 | goto CPY_INST; \ |
| 1042 | case 99: goto REV_INST; \ | 1081 | case 49: \ |
| 1043 | case 100: goto BLX_INST; \ | 1082 | goto UXTAB_INST; \ |
| 1044 | case 101: goto REVSH_INST; \ | 1083 | case 50: \ |
| 1045 | case 102: goto QADD_INST; \ | 1084 | goto SSUB8_INST; \ |
| 1046 | case 103: goto QADD16_INST; \ | 1085 | case 51: \ |
| 1047 | case 104: goto QADDSUBX_INST; \ | 1086 | goto SHSUB8_INST; \ |
| 1048 | case 105: goto LDREX_INST; \ | 1087 | case 52: \ |
| 1049 | case 106: goto QDADD_INST; \ | 1088 | goto SSUBADDX_INST; \ |
| 1050 | case 107: goto QDSUB_INST; \ | 1089 | case 53: \ |
| 1051 | case 108: goto QSUB_INST; \ | 1090 | goto STREX_INST; \ |
| 1052 | case 109: goto LDREXB_INST; \ | 1091 | case 54: \ |
| 1053 | case 110: goto QSUB8_INST; \ | 1092 | goto STREXB_INST; \ |
| 1054 | case 111: goto QSUB16_INST; \ | 1093 | case 55: \ |
| 1055 | case 112: goto SMUAD_INST; \ | 1094 | goto SWP_INST; \ |
| 1056 | case 113: goto SMMUL_INST; \ | 1095 | case 56: \ |
| 1057 | case 114: goto SMUSD_INST; \ | 1096 | goto SWPB_INST; \ |
| 1058 | case 115: goto SMLSD_INST; \ | 1097 | case 57: \ |
| 1059 | case 116: goto SMLSLD_INST; \ | 1098 | goto SSUB16_INST; \ |
| 1060 | case 117: goto SMMLA_INST; \ | 1099 | case 58: \ |
| 1061 | case 118: goto SMMLS_INST; \ | 1100 | goto SSAT16_INST; \ |
| 1062 | case 119: goto SMLALD_INST; \ | 1101 | case 59: \ |
| 1063 | case 120: goto SMLAD_INST; \ | 1102 | goto SHSUBADDX_INST; \ |
| 1064 | case 121: goto SMLAW_INST; \ | 1103 | case 60: \ |
| 1065 | case 122: goto SMULW_INST; \ | 1104 | goto QSUBADDX_INST; \ |
| 1066 | case 123: goto PKHTB_INST; \ | 1105 | case 61: \ |
| 1067 | case 124: goto PKHBT_INST; \ | 1106 | goto SHADDSUBX_INST; \ |
| 1068 | case 125: goto SMUL_INST; \ | 1107 | case 62: \ |
| 1069 | case 126: goto SMLALXY_INST; \ | 1108 | goto SHADD8_INST; \ |
| 1070 | case 127: goto SMLA_INST; \ | 1109 | case 63: \ |
| 1071 | case 128: goto MCRR_INST; \ | 1110 | goto SHADD16_INST; \ |
| 1072 | case 129: goto MRRC_INST; \ | 1111 | case 64: \ |
| 1073 | case 130: goto CMP_INST; \ | 1112 | goto SEL_INST; \ |
| 1074 | case 131: goto TST_INST; \ | 1113 | case 65: \ |
| 1075 | case 132: goto TEQ_INST; \ | 1114 | goto SADDSUBX_INST; \ |
| 1076 | case 133: goto CMN_INST; \ | 1115 | case 66: \ |
| 1077 | case 134: goto SMULL_INST; \ | 1116 | goto SADD8_INST; \ |
| 1078 | case 135: goto UMULL_INST; \ | 1117 | case 67: \ |
| 1079 | case 136: goto UMLAL_INST; \ | 1118 | goto SADD16_INST; \ |
| 1080 | case 137: goto SMLAL_INST; \ | 1119 | case 68: \ |
| 1081 | case 138: goto MUL_INST; \ | 1120 | goto SHSUB16_INST; \ |
| 1082 | case 139: goto MLA_INST; \ | 1121 | case 69: \ |
| 1083 | case 140: goto SSAT_INST; \ | 1122 | goto UMAAL_INST; \ |
| 1084 | case 141: goto USAT_INST; \ | 1123 | case 70: \ |
| 1085 | case 142: goto MRS_INST; \ | 1124 | goto UXTAB16_INST; \ |
| 1086 | case 143: goto MSR_INST; \ | 1125 | case 71: \ |
| 1087 | case 144: goto AND_INST; \ | 1126 | goto USUBADDX_INST; \ |
| 1088 | case 145: goto BIC_INST; \ | 1127 | case 72: \ |
| 1089 | case 146: goto LDM_INST; \ | 1128 | goto USUB8_INST; \ |
| 1090 | case 147: goto EOR_INST; \ | 1129 | case 73: \ |
| 1091 | case 148: goto ADD_INST; \ | 1130 | goto USUB16_INST; \ |
| 1092 | case 149: goto RSB_INST; \ | 1131 | case 74: \ |
| 1093 | case 150: goto RSC_INST; \ | 1132 | goto USAT16_INST; \ |
| 1094 | case 151: goto SBC_INST; \ | 1133 | case 75: \ |
| 1095 | case 152: goto ADC_INST; \ | 1134 | goto USADA8_INST; \ |
| 1096 | case 153: goto SUB_INST; \ | 1135 | case 76: \ |
| 1097 | case 154: goto ORR_INST; \ | 1136 | goto UQSUBADDX_INST; \ |
| 1098 | case 155: goto MVN_INST; \ | 1137 | case 77: \ |
| 1099 | case 156: goto MOV_INST; \ | 1138 | goto UQSUB8_INST; \ |
| 1100 | case 157: goto STM_INST; \ | 1139 | case 78: \ |
| 1101 | case 158: goto LDM_INST; \ | 1140 | goto UQSUB16_INST; \ |
| 1102 | case 159: goto LDRSH_INST; \ | 1141 | case 79: \ |
| 1103 | case 160: goto STM_INST; \ | 1142 | goto UQADDSUBX_INST; \ |
| 1104 | case 161: goto LDM_INST; \ | 1143 | case 80: \ |
| 1105 | case 162: goto LDRSB_INST; \ | 1144 | goto UQADD8_INST; \ |
| 1106 | case 163: goto STRD_INST; \ | 1145 | case 81: \ |
| 1107 | case 164: goto LDRH_INST; \ | 1146 | goto UQADD16_INST; \ |
| 1108 | case 165: goto STRH_INST; \ | 1147 | case 82: \ |
| 1109 | case 166: goto LDRD_INST; \ | 1148 | goto SXTAB_INST; \ |
| 1110 | case 167: goto STRT_INST; \ | 1149 | case 83: \ |
| 1111 | case 168: goto STRBT_INST; \ | 1150 | goto UHSUBADDX_INST; \ |
| 1112 | case 169: goto LDRBT_INST; \ | 1151 | case 84: \ |
| 1113 | case 170: goto LDRT_INST; \ | 1152 | goto UHSUB8_INST; \ |
| 1114 | case 171: goto MRC_INST; \ | 1153 | case 85: \ |
| 1115 | case 172: goto MCR_INST; \ | 1154 | goto UHSUB16_INST; \ |
| 1116 | case 173: goto MSR_INST; \ | 1155 | case 86: \ |
| 1117 | case 174: goto MSR_INST; \ | 1156 | goto UHADDSUBX_INST; \ |
| 1118 | case 175: goto MSR_INST; \ | 1157 | case 87: \ |
| 1119 | case 176: goto MSR_INST; \ | 1158 | goto UHADD8_INST; \ |
| 1120 | case 177: goto MSR_INST; \ | 1159 | case 88: \ |
| 1121 | case 178: goto LDRB_INST; \ | 1160 | goto UHADD16_INST; \ |
| 1122 | case 179: goto STRB_INST; \ | 1161 | case 89: \ |
| 1123 | case 180: goto LDR_INST; \ | 1162 | goto UADDSUBX_INST; \ |
| 1124 | case 181: goto LDRCOND_INST ; \ | 1163 | case 90: \ |
| 1125 | case 182: goto STR_INST; \ | 1164 | goto UADD8_INST; \ |
| 1126 | case 183: goto CDP_INST; \ | 1165 | case 91: \ |
| 1127 | case 184: goto STC_INST; \ | 1166 | goto UADD16_INST; \ |
| 1128 | case 185: goto LDC_INST; \ | 1167 | case 92: \ |
| 1129 | case 186: goto LDREXD_INST; \ | 1168 | goto SXTAH_INST; \ |
| 1130 | case 187: goto STREXD_INST; \ | 1169 | case 93: \ |
| 1131 | case 188: goto LDREXH_INST; \ | 1170 | goto SXTAB16_INST; \ |
| 1132 | case 189: goto STREXH_INST; \ | 1171 | case 94: \ |
| 1133 | case 190: goto NOP_INST; \ | 1172 | goto QADD8_INST; \ |
| 1134 | case 191: goto YIELD_INST; \ | 1173 | case 95: \ |
| 1135 | case 192: goto WFE_INST; \ | 1174 | goto BXJ_INST; \ |
| 1136 | case 193: goto WFI_INST; \ | 1175 | case 96: \ |
| 1137 | case 194: goto SEV_INST; \ | 1176 | goto CLZ_INST; \ |
| 1138 | case 195: goto SWI_INST; \ | 1177 | case 97: \ |
| 1139 | case 196: goto BBL_INST; \ | 1178 | goto UXTAH_INST; \ |
| 1140 | case 197: goto B_2_THUMB ; \ | 1179 | case 98: \ |
| 1141 | case 198: goto B_COND_THUMB ; \ | 1180 | goto BX_INST; \ |
| 1142 | case 199: goto BL_1_THUMB ; \ | 1181 | case 99: \ |
| 1143 | case 200: goto BL_2_THUMB ; \ | 1182 | goto REV_INST; \ |
| 1144 | case 201: goto BLX_1_THUMB ; \ | 1183 | case 100: \ |
| 1145 | case 202: goto DISPATCH; \ | 1184 | goto BLX_INST; \ |
| 1146 | case 203: goto INIT_INST_LENGTH; \ | 1185 | case 101: \ |
| 1147 | case 204: goto END; \ | 1186 | goto REVSH_INST; \ |
| 1187 | case 102: \ | ||
| 1188 | goto QADD_INST; \ | ||
| 1189 | case 103: \ | ||
| 1190 | goto QADD16_INST; \ | ||
| 1191 | case 104: \ | ||
| 1192 | goto QADDSUBX_INST; \ | ||
| 1193 | case 105: \ | ||
| 1194 | goto LDREX_INST; \ | ||
| 1195 | case 106: \ | ||
| 1196 | goto QDADD_INST; \ | ||
| 1197 | case 107: \ | ||
| 1198 | goto QDSUB_INST; \ | ||
| 1199 | case 108: \ | ||
| 1200 | goto QSUB_INST; \ | ||
| 1201 | case 109: \ | ||
| 1202 | goto LDREXB_INST; \ | ||
| 1203 | case 110: \ | ||
| 1204 | goto QSUB8_INST; \ | ||
| 1205 | case 111: \ | ||
| 1206 | goto QSUB16_INST; \ | ||
| 1207 | case 112: \ | ||
| 1208 | goto SMUAD_INST; \ | ||
| 1209 | case 113: \ | ||
| 1210 | goto SMMUL_INST; \ | ||
| 1211 | case 114: \ | ||
| 1212 | goto SMUSD_INST; \ | ||
| 1213 | case 115: \ | ||
| 1214 | goto SMLSD_INST; \ | ||
| 1215 | case 116: \ | ||
| 1216 | goto SMLSLD_INST; \ | ||
| 1217 | case 117: \ | ||
| 1218 | goto SMMLA_INST; \ | ||
| 1219 | case 118: \ | ||
| 1220 | goto SMMLS_INST; \ | ||
| 1221 | case 119: \ | ||
| 1222 | goto SMLALD_INST; \ | ||
| 1223 | case 120: \ | ||
| 1224 | goto SMLAD_INST; \ | ||
| 1225 | case 121: \ | ||
| 1226 | goto SMLAW_INST; \ | ||
| 1227 | case 122: \ | ||
| 1228 | goto SMULW_INST; \ | ||
| 1229 | case 123: \ | ||
| 1230 | goto PKHTB_INST; \ | ||
| 1231 | case 124: \ | ||
| 1232 | goto PKHBT_INST; \ | ||
| 1233 | case 125: \ | ||
| 1234 | goto SMUL_INST; \ | ||
| 1235 | case 126: \ | ||
| 1236 | goto SMLALXY_INST; \ | ||
| 1237 | case 127: \ | ||
| 1238 | goto SMLA_INST; \ | ||
| 1239 | case 128: \ | ||
| 1240 | goto MCRR_INST; \ | ||
| 1241 | case 129: \ | ||
| 1242 | goto MRRC_INST; \ | ||
| 1243 | case 130: \ | ||
| 1244 | goto CMP_INST; \ | ||
| 1245 | case 131: \ | ||
| 1246 | goto TST_INST; \ | ||
| 1247 | case 132: \ | ||
| 1248 | goto TEQ_INST; \ | ||
| 1249 | case 133: \ | ||
| 1250 | goto CMN_INST; \ | ||
| 1251 | case 134: \ | ||
| 1252 | goto SMULL_INST; \ | ||
| 1253 | case 135: \ | ||
| 1254 | goto UMULL_INST; \ | ||
| 1255 | case 136: \ | ||
| 1256 | goto UMLAL_INST; \ | ||
| 1257 | case 137: \ | ||
| 1258 | goto SMLAL_INST; \ | ||
| 1259 | case 138: \ | ||
| 1260 | goto MUL_INST; \ | ||
| 1261 | case 139: \ | ||
| 1262 | goto MLA_INST; \ | ||
| 1263 | case 140: \ | ||
| 1264 | goto SSAT_INST; \ | ||
| 1265 | case 141: \ | ||
| 1266 | goto USAT_INST; \ | ||
| 1267 | case 142: \ | ||
| 1268 | goto MRS_INST; \ | ||
| 1269 | case 143: \ | ||
| 1270 | goto MSR_INST; \ | ||
| 1271 | case 144: \ | ||
| 1272 | goto AND_INST; \ | ||
| 1273 | case 145: \ | ||
| 1274 | goto BIC_INST; \ | ||
| 1275 | case 146: \ | ||
| 1276 | goto LDM_INST; \ | ||
| 1277 | case 147: \ | ||
| 1278 | goto EOR_INST; \ | ||
| 1279 | case 148: \ | ||
| 1280 | goto ADD_INST; \ | ||
| 1281 | case 149: \ | ||
| 1282 | goto RSB_INST; \ | ||
| 1283 | case 150: \ | ||
| 1284 | goto RSC_INST; \ | ||
| 1285 | case 151: \ | ||
| 1286 | goto SBC_INST; \ | ||
| 1287 | case 152: \ | ||
| 1288 | goto ADC_INST; \ | ||
| 1289 | case 153: \ | ||
| 1290 | goto SUB_INST; \ | ||
| 1291 | case 154: \ | ||
| 1292 | goto ORR_INST; \ | ||
| 1293 | case 155: \ | ||
| 1294 | goto MVN_INST; \ | ||
| 1295 | case 156: \ | ||
| 1296 | goto MOV_INST; \ | ||
| 1297 | case 157: \ | ||
| 1298 | goto STM_INST; \ | ||
| 1299 | case 158: \ | ||
| 1300 | goto LDM_INST; \ | ||
| 1301 | case 159: \ | ||
| 1302 | goto LDRSH_INST; \ | ||
| 1303 | case 160: \ | ||
| 1304 | goto STM_INST; \ | ||
| 1305 | case 161: \ | ||
| 1306 | goto LDM_INST; \ | ||
| 1307 | case 162: \ | ||
| 1308 | goto LDRSB_INST; \ | ||
| 1309 | case 163: \ | ||
| 1310 | goto STRD_INST; \ | ||
| 1311 | case 164: \ | ||
| 1312 | goto LDRH_INST; \ | ||
| 1313 | case 165: \ | ||
| 1314 | goto STRH_INST; \ | ||
| 1315 | case 166: \ | ||
| 1316 | goto LDRD_INST; \ | ||
| 1317 | case 167: \ | ||
| 1318 | goto STRT_INST; \ | ||
| 1319 | case 168: \ | ||
| 1320 | goto STRBT_INST; \ | ||
| 1321 | case 169: \ | ||
| 1322 | goto LDRBT_INST; \ | ||
| 1323 | case 170: \ | ||
| 1324 | goto LDRT_INST; \ | ||
| 1325 | case 171: \ | ||
| 1326 | goto MRC_INST; \ | ||
| 1327 | case 172: \ | ||
| 1328 | goto MCR_INST; \ | ||
| 1329 | case 173: \ | ||
| 1330 | goto MSR_INST; \ | ||
| 1331 | case 174: \ | ||
| 1332 | goto MSR_INST; \ | ||
| 1333 | case 175: \ | ||
| 1334 | goto MSR_INST; \ | ||
| 1335 | case 176: \ | ||
| 1336 | goto MSR_INST; \ | ||
| 1337 | case 177: \ | ||
| 1338 | goto MSR_INST; \ | ||
| 1339 | case 178: \ | ||
| 1340 | goto LDRB_INST; \ | ||
| 1341 | case 179: \ | ||
| 1342 | goto STRB_INST; \ | ||
| 1343 | case 180: \ | ||
| 1344 | goto LDR_INST; \ | ||
| 1345 | case 181: \ | ||
| 1346 | goto LDRCOND_INST; \ | ||
| 1347 | case 182: \ | ||
| 1348 | goto STR_INST; \ | ||
| 1349 | case 183: \ | ||
| 1350 | goto CDP_INST; \ | ||
| 1351 | case 184: \ | ||
| 1352 | goto STC_INST; \ | ||
| 1353 | case 185: \ | ||
| 1354 | goto LDC_INST; \ | ||
| 1355 | case 186: \ | ||
| 1356 | goto LDREXD_INST; \ | ||
| 1357 | case 187: \ | ||
| 1358 | goto STREXD_INST; \ | ||
| 1359 | case 188: \ | ||
| 1360 | goto LDREXH_INST; \ | ||
| 1361 | case 189: \ | ||
| 1362 | goto STREXH_INST; \ | ||
| 1363 | case 190: \ | ||
| 1364 | goto NOP_INST; \ | ||
| 1365 | case 191: \ | ||
| 1366 | goto YIELD_INST; \ | ||
| 1367 | case 192: \ | ||
| 1368 | goto WFE_INST; \ | ||
| 1369 | case 193: \ | ||
| 1370 | goto WFI_INST; \ | ||
| 1371 | case 194: \ | ||
| 1372 | goto SEV_INST; \ | ||
| 1373 | case 195: \ | ||
| 1374 | goto SWI_INST; \ | ||
| 1375 | case 196: \ | ||
| 1376 | goto BBL_INST; \ | ||
| 1377 | case 197: \ | ||
| 1378 | goto B_2_THUMB; \ | ||
| 1379 | case 198: \ | ||
| 1380 | goto B_COND_THUMB; \ | ||
| 1381 | case 199: \ | ||
| 1382 | goto BL_1_THUMB; \ | ||
| 1383 | case 200: \ | ||
| 1384 | goto BL_2_THUMB; \ | ||
| 1385 | case 201: \ | ||
| 1386 | goto BLX_1_THUMB; \ | ||
| 1387 | case 202: \ | ||
| 1388 | goto DISPATCH; \ | ||
| 1389 | case 203: \ | ||
| 1390 | goto INIT_INST_LENGTH; \ | ||
| 1391 | case 204: \ | ||
| 1392 | goto END; \ | ||
| 1148 | } | 1393 | } |
| 1149 | #endif | 1394 | #endif |
| 1150 | 1395 | ||
| 1151 | #define UPDATE_NFLAG(dst) (cpu->NFlag = BIT(dst, 31) ? 1 : 0) | 1396 | #define UPDATE_NFLAG(dst) (cpu->NFlag = BIT(dst, 31) ? 1 : 0) |
| 1152 | #define UPDATE_ZFLAG(dst) (cpu->ZFlag = dst ? 0 : 1) | 1397 | #define UPDATE_ZFLAG(dst) (cpu->ZFlag = dst ? 0 : 1) |
| 1153 | #define UPDATE_CFLAG_WITH_SC (cpu->CFlag = cpu->shifter_carry_out) | 1398 | #define UPDATE_CFLAG_WITH_SC (cpu->CFlag = cpu->shifter_carry_out) |
| 1154 | 1399 | ||
| 1155 | #define SAVE_NZCVT cpu->Cpsr = (cpu->Cpsr & 0x0fffffdf) | \ | 1400 | #define SAVE_NZCVT \ |
| 1156 | (cpu->NFlag << 31) | \ | 1401 | cpu->Cpsr = (cpu->Cpsr & 0x0fffffdf) | (cpu->NFlag << 31) | (cpu->ZFlag << 30) | \ |
| 1157 | (cpu->ZFlag << 30) | \ | 1402 | (cpu->CFlag << 29) | (cpu->VFlag << 28) | (cpu->TFlag << 5) |
| 1158 | (cpu->CFlag << 29) | \ | 1403 | #define LOAD_NZCVT \ |
| 1159 | (cpu->VFlag << 28) | \ | 1404 | cpu->NFlag = (cpu->Cpsr >> 31); \ |
| 1160 | (cpu->TFlag << 5) | 1405 | cpu->ZFlag = (cpu->Cpsr >> 30) & 1; \ |
| 1161 | #define LOAD_NZCVT cpu->NFlag = (cpu->Cpsr >> 31); \ | 1406 | cpu->CFlag = (cpu->Cpsr >> 29) & 1; \ |
| 1162 | cpu->ZFlag = (cpu->Cpsr >> 30) & 1; \ | 1407 | cpu->VFlag = (cpu->Cpsr >> 28) & 1; \ |
| 1163 | cpu->CFlag = (cpu->Cpsr >> 29) & 1; \ | 1408 | cpu->TFlag = (cpu->Cpsr >> 5) & 1; |
| 1164 | cpu->VFlag = (cpu->Cpsr >> 28) & 1; \ | 1409 | |
| 1165 | cpu->TFlag = (cpu->Cpsr >> 5) & 1; | 1410 | #define CurrentModeHasSPSR (cpu->Mode != SYSTEM32MODE) && (cpu->Mode != USER32MODE) |
| 1166 | 1411 | #define PC (cpu->Reg[15]) | |
| 1167 | #define CurrentModeHasSPSR (cpu->Mode != SYSTEM32MODE) && (cpu->Mode != USER32MODE) | 1412 | |
| 1168 | #define PC (cpu->Reg[15]) | 1413 | // GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback |
| 1169 | 1414 | // to a clunky switch statement. | |
| 1170 | // GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback | ||
| 1171 | // to a clunky switch statement. | ||
| 1172 | #if defined __GNUC__ || defined __clang__ | 1415 | #if defined __GNUC__ || defined __clang__ |
| 1173 | void *InstLabel[] = { | 1416 | void* InstLabel[] = {&&VMLA_INST, |
| 1174 | &&VMLA_INST, &&VMLS_INST, &&VNMLA_INST, &&VNMLS_INST, &&VNMUL_INST, &&VMUL_INST, &&VADD_INST, &&VSUB_INST, | 1417 | &&VMLS_INST, |
| 1175 | &&VDIV_INST, &&VMOVI_INST, &&VMOVR_INST, &&VABS_INST, &&VNEG_INST, &&VSQRT_INST, &&VCMP_INST, &&VCMP2_INST, &&VCVTBDS_INST, | 1418 | &&VNMLA_INST, |
| 1176 | &&VCVTBFF_INST, &&VCVTBFI_INST, &&VMOVBRS_INST, &&VMSR_INST, &&VMOVBRC_INST, &&VMRS_INST, &&VMOVBCR_INST, &&VMOVBRRSS_INST, | 1419 | &&VNMLS_INST, |
| 1177 | &&VMOVBRRD_INST, &&VSTR_INST, &&VPUSH_INST, &&VSTM_INST, &&VPOP_INST, &&VLDR_INST, &&VLDM_INST, | 1420 | &&VNMUL_INST, |
| 1178 | 1421 | &&VMUL_INST, | |
| 1179 | &&SRS_INST,&&RFE_INST,&&BKPT_INST,&&BLX_INST,&&CPS_INST,&&PLD_INST,&&SETEND_INST,&&CLREX_INST,&&REV16_INST,&&USAD8_INST,&&SXTB_INST, | 1422 | &&VADD_INST, |
| 1180 | &&UXTB_INST,&&SXTH_INST,&&SXTB16_INST,&&UXTH_INST,&&UXTB16_INST,&&CPY_INST,&&UXTAB_INST,&&SSUB8_INST,&&SHSUB8_INST,&&SSUBADDX_INST, | 1423 | &&VSUB_INST, |
| 1181 | &&STREX_INST,&&STREXB_INST,&&SWP_INST,&&SWPB_INST,&&SSUB16_INST,&&SSAT16_INST,&&SHSUBADDX_INST,&&QSUBADDX_INST,&&SHADDSUBX_INST, | 1424 | &&VDIV_INST, |
| 1182 | &&SHADD8_INST,&&SHADD16_INST,&&SEL_INST,&&SADDSUBX_INST,&&SADD8_INST,&&SADD16_INST,&&SHSUB16_INST,&&UMAAL_INST,&&UXTAB16_INST, | 1425 | &&VMOVI_INST, |
| 1183 | &&USUBADDX_INST,&&USUB8_INST,&&USUB16_INST,&&USAT16_INST,&&USADA8_INST,&&UQSUBADDX_INST,&&UQSUB8_INST,&&UQSUB16_INST, | 1426 | &&VMOVR_INST, |
| 1184 | &&UQADDSUBX_INST,&&UQADD8_INST,&&UQADD16_INST,&&SXTAB_INST,&&UHSUBADDX_INST,&&UHSUB8_INST,&&UHSUB16_INST,&&UHADDSUBX_INST,&&UHADD8_INST, | 1427 | &&VABS_INST, |
| 1185 | &&UHADD16_INST,&&UADDSUBX_INST,&&UADD8_INST,&&UADD16_INST,&&SXTAH_INST,&&SXTAB16_INST,&&QADD8_INST,&&BXJ_INST,&&CLZ_INST,&&UXTAH_INST, | 1428 | &&VNEG_INST, |
| 1186 | &&BX_INST,&&REV_INST,&&BLX_INST,&&REVSH_INST,&&QADD_INST,&&QADD16_INST,&&QADDSUBX_INST,&&LDREX_INST,&&QDADD_INST,&&QDSUB_INST, | 1429 | &&VSQRT_INST, |
| 1187 | &&QSUB_INST,&&LDREXB_INST,&&QSUB8_INST,&&QSUB16_INST,&&SMUAD_INST,&&SMMUL_INST,&&SMUSD_INST,&&SMLSD_INST,&&SMLSLD_INST,&&SMMLA_INST, | 1430 | &&VCMP_INST, |
| 1188 | &&SMMLS_INST,&&SMLALD_INST,&&SMLAD_INST,&&SMLAW_INST,&&SMULW_INST,&&PKHTB_INST,&&PKHBT_INST,&&SMUL_INST,&&SMLALXY_INST,&&SMLA_INST, | 1431 | &&VCMP2_INST, |
| 1189 | &&MCRR_INST,&&MRRC_INST,&&CMP_INST,&&TST_INST,&&TEQ_INST,&&CMN_INST,&&SMULL_INST,&&UMULL_INST,&&UMLAL_INST,&&SMLAL_INST,&&MUL_INST, | 1432 | &&VCVTBDS_INST, |
| 1190 | &&MLA_INST,&&SSAT_INST,&&USAT_INST,&&MRS_INST,&&MSR_INST,&&AND_INST,&&BIC_INST,&&LDM_INST,&&EOR_INST,&&ADD_INST,&&RSB_INST,&&RSC_INST, | 1433 | &&VCVTBFF_INST, |
| 1191 | &&SBC_INST,&&ADC_INST,&&SUB_INST,&&ORR_INST,&&MVN_INST,&&MOV_INST,&&STM_INST,&&LDM_INST,&&LDRSH_INST,&&STM_INST,&&LDM_INST,&&LDRSB_INST, | 1434 | &&VCVTBFI_INST, |
| 1192 | &&STRD_INST,&&LDRH_INST,&&STRH_INST,&&LDRD_INST,&&STRT_INST,&&STRBT_INST,&&LDRBT_INST,&&LDRT_INST,&&MRC_INST,&&MCR_INST, | 1435 | &&VMOVBRS_INST, |
| 1193 | &&MSR_INST, &&MSR_INST, &&MSR_INST, &&MSR_INST, &&MSR_INST, | 1436 | &&VMSR_INST, |
| 1194 | &&LDRB_INST,&&STRB_INST,&&LDR_INST,&&LDRCOND_INST, &&STR_INST,&&CDP_INST,&&STC_INST,&&LDC_INST, &&LDREXD_INST, | 1437 | &&VMOVBRC_INST, |
| 1195 | &&STREXD_INST,&&LDREXH_INST,&&STREXH_INST, &&NOP_INST, &&YIELD_INST, &&WFE_INST, &&WFI_INST, &&SEV_INST, &&SWI_INST,&&BBL_INST, | 1438 | &&VMRS_INST, |
| 1196 | &&B_2_THUMB, &&B_COND_THUMB,&&BL_1_THUMB, &&BL_2_THUMB, &&BLX_1_THUMB, &&DISPATCH, | 1439 | &&VMOVBCR_INST, |
| 1197 | &&INIT_INST_LENGTH,&&END | 1440 | &&VMOVBRRSS_INST, |
| 1198 | }; | 1441 | &&VMOVBRRD_INST, |
| 1442 | &&VSTR_INST, | ||
| 1443 | &&VPUSH_INST, | ||
| 1444 | &&VSTM_INST, | ||
| 1445 | &&VPOP_INST, | ||
| 1446 | &&VLDR_INST, | ||
| 1447 | &&VLDM_INST, | ||
| 1448 | |||
| 1449 | &&SRS_INST, | ||
| 1450 | &&RFE_INST, | ||
| 1451 | &&BKPT_INST, | ||
| 1452 | &&BLX_INST, | ||
| 1453 | &&CPS_INST, | ||
| 1454 | &&PLD_INST, | ||
| 1455 | &&SETEND_INST, | ||
| 1456 | &&CLREX_INST, | ||
| 1457 | &&REV16_INST, | ||
| 1458 | &&USAD8_INST, | ||
| 1459 | &&SXTB_INST, | ||
| 1460 | &&UXTB_INST, | ||
| 1461 | &&SXTH_INST, | ||
| 1462 | &&SXTB16_INST, | ||
| 1463 | &&UXTH_INST, | ||
| 1464 | &&UXTB16_INST, | ||
| 1465 | &&CPY_INST, | ||
| 1466 | &&UXTAB_INST, | ||
| 1467 | &&SSUB8_INST, | ||
| 1468 | &&SHSUB8_INST, | ||
| 1469 | &&SSUBADDX_INST, | ||
| 1470 | &&STREX_INST, | ||
| 1471 | &&STREXB_INST, | ||
| 1472 | &&SWP_INST, | ||
| 1473 | &&SWPB_INST, | ||
| 1474 | &&SSUB16_INST, | ||
| 1475 | &&SSAT16_INST, | ||
| 1476 | &&SHSUBADDX_INST, | ||
| 1477 | &&QSUBADDX_INST, | ||
| 1478 | &&SHADDSUBX_INST, | ||
| 1479 | &&SHADD8_INST, | ||
| 1480 | &&SHADD16_INST, | ||
| 1481 | &&SEL_INST, | ||
| 1482 | &&SADDSUBX_INST, | ||
| 1483 | &&SADD8_INST, | ||
| 1484 | &&SADD16_INST, | ||
| 1485 | &&SHSUB16_INST, | ||
| 1486 | &&UMAAL_INST, | ||
| 1487 | &&UXTAB16_INST, | ||
| 1488 | &&USUBADDX_INST, | ||
| 1489 | &&USUB8_INST, | ||
| 1490 | &&USUB16_INST, | ||
| 1491 | &&USAT16_INST, | ||
| 1492 | &&USADA8_INST, | ||
| 1493 | &&UQSUBADDX_INST, | ||
| 1494 | &&UQSUB8_INST, | ||
| 1495 | &&UQSUB16_INST, | ||
| 1496 | &&UQADDSUBX_INST, | ||
| 1497 | &&UQADD8_INST, | ||
| 1498 | &&UQADD16_INST, | ||
| 1499 | &&SXTAB_INST, | ||
| 1500 | &&UHSUBADDX_INST, | ||
| 1501 | &&UHSUB8_INST, | ||
| 1502 | &&UHSUB16_INST, | ||
| 1503 | &&UHADDSUBX_INST, | ||
| 1504 | &&UHADD8_INST, | ||
| 1505 | &&UHADD16_INST, | ||
| 1506 | &&UADDSUBX_INST, | ||
| 1507 | &&UADD8_INST, | ||
| 1508 | &&UADD16_INST, | ||
| 1509 | &&SXTAH_INST, | ||
| 1510 | &&SXTAB16_INST, | ||
| 1511 | &&QADD8_INST, | ||
| 1512 | &&BXJ_INST, | ||
| 1513 | &&CLZ_INST, | ||
| 1514 | &&UXTAH_INST, | ||
| 1515 | &&BX_INST, | ||
| 1516 | &&REV_INST, | ||
| 1517 | &&BLX_INST, | ||
| 1518 | &&REVSH_INST, | ||
| 1519 | &&QADD_INST, | ||
| 1520 | &&QADD16_INST, | ||
| 1521 | &&QADDSUBX_INST, | ||
| 1522 | &&LDREX_INST, | ||
| 1523 | &&QDADD_INST, | ||
| 1524 | &&QDSUB_INST, | ||
| 1525 | &&QSUB_INST, | ||
| 1526 | &&LDREXB_INST, | ||
| 1527 | &&QSUB8_INST, | ||
| 1528 | &&QSUB16_INST, | ||
| 1529 | &&SMUAD_INST, | ||
| 1530 | &&SMMUL_INST, | ||
| 1531 | &&SMUSD_INST, | ||
| 1532 | &&SMLSD_INST, | ||
| 1533 | &&SMLSLD_INST, | ||
| 1534 | &&SMMLA_INST, | ||
| 1535 | &&SMMLS_INST, | ||
| 1536 | &&SMLALD_INST, | ||
| 1537 | &&SMLAD_INST, | ||
| 1538 | &&SMLAW_INST, | ||
| 1539 | &&SMULW_INST, | ||
| 1540 | &&PKHTB_INST, | ||
| 1541 | &&PKHBT_INST, | ||
| 1542 | &&SMUL_INST, | ||
| 1543 | &&SMLALXY_INST, | ||
| 1544 | &&SMLA_INST, | ||
| 1545 | &&MCRR_INST, | ||
| 1546 | &&MRRC_INST, | ||
| 1547 | &&CMP_INST, | ||
| 1548 | &&TST_INST, | ||
| 1549 | &&TEQ_INST, | ||
| 1550 | &&CMN_INST, | ||
| 1551 | &&SMULL_INST, | ||
| 1552 | &&UMULL_INST, | ||
| 1553 | &&UMLAL_INST, | ||
| 1554 | &&SMLAL_INST, | ||
| 1555 | &&MUL_INST, | ||
| 1556 | &&MLA_INST, | ||
| 1557 | &&SSAT_INST, | ||
| 1558 | &&USAT_INST, | ||
| 1559 | &&MRS_INST, | ||
| 1560 | &&MSR_INST, | ||
| 1561 | &&AND_INST, | ||
| 1562 | &&BIC_INST, | ||
| 1563 | &&LDM_INST, | ||
| 1564 | &&EOR_INST, | ||
| 1565 | &&ADD_INST, | ||
| 1566 | &&RSB_INST, | ||
| 1567 | &&RSC_INST, | ||
| 1568 | &&SBC_INST, | ||
| 1569 | &&ADC_INST, | ||
| 1570 | &&SUB_INST, | ||
| 1571 | &&ORR_INST, | ||
| 1572 | &&MVN_INST, | ||
| 1573 | &&MOV_INST, | ||
| 1574 | &&STM_INST, | ||
| 1575 | &&LDM_INST, | ||
| 1576 | &&LDRSH_INST, | ||
| 1577 | &&STM_INST, | ||
| 1578 | &&LDM_INST, | ||
| 1579 | &&LDRSB_INST, | ||
| 1580 | &&STRD_INST, | ||
| 1581 | &&LDRH_INST, | ||
| 1582 | &&STRH_INST, | ||
| 1583 | &&LDRD_INST, | ||
| 1584 | &&STRT_INST, | ||
| 1585 | &&STRBT_INST, | ||
| 1586 | &&LDRBT_INST, | ||
| 1587 | &&LDRT_INST, | ||
| 1588 | &&MRC_INST, | ||
| 1589 | &&MCR_INST, | ||
| 1590 | &&MSR_INST, | ||
| 1591 | &&MSR_INST, | ||
| 1592 | &&MSR_INST, | ||
| 1593 | &&MSR_INST, | ||
| 1594 | &&MSR_INST, | ||
| 1595 | &&LDRB_INST, | ||
| 1596 | &&STRB_INST, | ||
| 1597 | &&LDR_INST, | ||
| 1598 | &&LDRCOND_INST, | ||
| 1599 | &&STR_INST, | ||
| 1600 | &&CDP_INST, | ||
| 1601 | &&STC_INST, | ||
| 1602 | &&LDC_INST, | ||
| 1603 | &&LDREXD_INST, | ||
| 1604 | &&STREXD_INST, | ||
| 1605 | &&LDREXH_INST, | ||
| 1606 | &&STREXH_INST, | ||
| 1607 | &&NOP_INST, | ||
| 1608 | &&YIELD_INST, | ||
| 1609 | &&WFE_INST, | ||
| 1610 | &&WFI_INST, | ||
| 1611 | &&SEV_INST, | ||
| 1612 | &&SWI_INST, | ||
| 1613 | &&BBL_INST, | ||
| 1614 | &&B_2_THUMB, | ||
| 1615 | &&B_COND_THUMB, | ||
| 1616 | &&BL_1_THUMB, | ||
| 1617 | &&BL_2_THUMB, | ||
| 1618 | &&BLX_1_THUMB, | ||
| 1619 | &&DISPATCH, | ||
| 1620 | &&INIT_INST_LENGTH, | ||
| 1621 | &&END}; | ||
| 1199 | #endif | 1622 | #endif |
| 1200 | arm_inst* inst_base; | 1623 | arm_inst* inst_base; |
| 1201 | unsigned int addr; | 1624 | unsigned int addr; |
| @@ -1204,516 +1627,517 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 1204 | int ptr; | 1627 | int ptr; |
| 1205 | 1628 | ||
| 1206 | LOAD_NZCVT; | 1629 | LOAD_NZCVT; |
| 1207 | DISPATCH: | 1630 | DISPATCH : { |
| 1208 | { | 1631 | if (!cpu->NirqSig) { |
| 1209 | if (!cpu->NirqSig) { | 1632 | if (!(cpu->Cpsr & 0x80)) { |
| 1210 | if (!(cpu->Cpsr & 0x80)) { | 1633 | goto END; |
| 1211 | goto END; | ||
| 1212 | } | ||
| 1213 | } | 1634 | } |
| 1635 | } | ||
| 1214 | 1636 | ||
| 1215 | if (cpu->TFlag) | 1637 | if (cpu->TFlag) |
| 1216 | cpu->Reg[15] &= 0xfffffffe; | 1638 | cpu->Reg[15] &= 0xfffffffe; |
| 1217 | else | 1639 | else |
| 1218 | cpu->Reg[15] &= 0xfffffffc; | 1640 | cpu->Reg[15] &= 0xfffffffc; |
| 1219 | 1641 | ||
| 1220 | // Find the cached instruction cream, otherwise translate it... | 1642 | // Find the cached instruction cream, otherwise translate it... |
| 1221 | auto itr = cpu->instruction_cache.find(cpu->Reg[15]); | 1643 | auto itr = cpu->instruction_cache.find(cpu->Reg[15]); |
| 1222 | if (itr != cpu->instruction_cache.end()) { | 1644 | if (itr != cpu->instruction_cache.end()) { |
| 1223 | ptr = itr->second; | 1645 | ptr = itr->second; |
| 1224 | } else if (cpu->NumInstrsToExecute != 1) { | 1646 | } else if (cpu->NumInstrsToExecute != 1) { |
| 1225 | if (InterpreterTranslateBlock(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION) | 1647 | if (InterpreterTranslateBlock(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION) |
| 1226 | goto END; | 1648 | goto END; |
| 1227 | } else { | 1649 | } else { |
| 1228 | if (InterpreterTranslateSingle(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION) | 1650 | if (InterpreterTranslateSingle(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION) |
| 1229 | goto END; | 1651 | goto END; |
| 1230 | } | 1652 | } |
| 1231 | 1653 | ||
| 1232 | // Find breakpoint if one exists within the block | 1654 | // Find breakpoint if one exists within the block |
| 1233 | if (GDBStub::g_server_enabled && GDBStub::IsConnected()) { | 1655 | if (GDBStub::g_server_enabled && GDBStub::IsConnected()) { |
| 1234 | breakpoint_data = GDBStub::GetNextBreakpointFromAddress(cpu->Reg[15], GDBStub::BreakpointType::Execute); | 1656 | breakpoint_data = |
| 1235 | } | 1657 | GDBStub::GetNextBreakpointFromAddress(cpu->Reg[15], GDBStub::BreakpointType::Execute); |
| 1658 | } | ||
| 1236 | 1659 | ||
| 1237 | inst_base = (arm_inst *)&trans_cache_buf[ptr]; | 1660 | inst_base = (arm_inst*)&trans_cache_buf[ptr]; |
| 1238 | GOTO_NEXT_INST; | 1661 | GOTO_NEXT_INST; |
| 1662 | } | ||
| 1663 | ADC_INST : { | ||
| 1664 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1665 | adc_inst* const inst_cream = (adc_inst*)inst_base->component; | ||
| 1666 | |||
| 1667 | u32 rn_val = RN; | ||
| 1668 | if (inst_cream->Rn == 15) | ||
| 1669 | rn_val += 2 * cpu->GetInstructionSize(); | ||
| 1670 | |||
| 1671 | bool carry; | ||
| 1672 | bool overflow; | ||
| 1673 | RD = AddWithCarry(rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); | ||
| 1674 | |||
| 1675 | if (inst_cream->S && (inst_cream->Rd == 15)) { | ||
| 1676 | if (CurrentModeHasSPSR) { | ||
| 1677 | cpu->Cpsr = cpu->Spsr_copy; | ||
| 1678 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); | ||
| 1679 | LOAD_NZCVT; | ||
| 1680 | } | ||
| 1681 | } else if (inst_cream->S) { | ||
| 1682 | UPDATE_NFLAG(RD); | ||
| 1683 | UPDATE_ZFLAG(RD); | ||
| 1684 | cpu->CFlag = carry; | ||
| 1685 | cpu->VFlag = overflow; | ||
| 1686 | } | ||
| 1687 | if (inst_cream->Rd == 15) { | ||
| 1688 | INC_PC(sizeof(adc_inst)); | ||
| 1689 | goto DISPATCH; | ||
| 1690 | } | ||
| 1239 | } | 1691 | } |
| 1240 | ADC_INST: | 1692 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1241 | { | 1693 | INC_PC(sizeof(adc_inst)); |
| 1242 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 1694 | FETCH_INST; |
| 1243 | adc_inst* const inst_cream = (adc_inst*)inst_base->component; | 1695 | GOTO_NEXT_INST; |
| 1696 | } | ||
| 1697 | ADD_INST : { | ||
| 1698 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1699 | add_inst* const inst_cream = (add_inst*)inst_base->component; | ||
| 1244 | 1700 | ||
| 1245 | u32 rn_val = RN; | 1701 | u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn); |
| 1246 | if (inst_cream->Rn == 15) | ||
| 1247 | rn_val += 2 * cpu->GetInstructionSize(); | ||
| 1248 | 1702 | ||
| 1249 | bool carry; | 1703 | bool carry; |
| 1250 | bool overflow; | 1704 | bool overflow; |
| 1251 | RD = AddWithCarry(rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); | 1705 | RD = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow); |
| 1252 | 1706 | ||
| 1253 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 1707 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 1254 | if (CurrentModeHasSPSR) { | 1708 | if (CurrentModeHasSPSR) { |
| 1255 | cpu->Cpsr = cpu->Spsr_copy; | 1709 | cpu->Cpsr = cpu->Spsr_copy; |
| 1256 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); | 1710 | cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); |
| 1257 | LOAD_NZCVT; | 1711 | LOAD_NZCVT; |
| 1258 | } | ||
| 1259 | } else if (inst_cream->S) { | ||
| 1260 | UPDATE_NFLAG(RD); | ||
| 1261 | UPDATE_ZFLAG(RD); | ||
| 1262 | cpu->CFlag = carry; | ||
| 1263 | cpu->VFlag = overflow; | ||
| 1264 | } | ||
| 1265 | if (inst_cream->Rd == 15) { | ||
| 1266 | INC_PC(sizeof(adc_inst)); | ||
| 1267 | goto DISPATCH; | ||
| 1268 | } | 1712 | } |
| 1713 | } else if (inst_cream->S) { | ||
| 1714 | UPDATE_NFLAG(RD); | ||
| 1715 | UPDATE_ZFLAG(RD); | ||
| 1716 | cpu->CFlag = carry; | ||
| 1717 | cpu->VFlag = overflow; | ||
| 1269 | } | 1718 | } |
| 1270 | cpu->Reg[15] += cpu->GetInstructionSize(); | 1719 | if (inst_cream->Rd == 15) { |
| 1271 | INC_PC(sizeof(adc_inst)); | 1720 | INC_PC(sizeof(add_inst)); |
| 1272 | FETCH_INST; | 1721 | goto DISPATCH; |
| 1273 | GOTO_NEXT_INST; | ||
| 1274 | } | ||
| 1275 | ADD_INST: | ||
| 1276 | { | ||
| 1277 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1278 | add_inst* const inst_cream = (add_inst*)inst_base->component; | ||
| 1279 | |||
| 1280 | u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn); | ||
| 1281 | |||
| 1282 | bool carry; | ||
| 1283 | bool overflow; | ||
| 1284 | RD = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow); | ||
| 1285 | |||
| 1286 | if (inst_cream->S && (inst_cream->Rd == 15)) { | ||
| 1287 | if (CurrentModeHasSPSR) { | ||
| 1288 | cpu->Cpsr = cpu->Spsr_copy; | ||
| 1289 | cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); | ||
| 1290 | LOAD_NZCVT; | ||
| 1291 | } | ||
| 1292 | } else if (inst_cream->S) { | ||
| 1293 | UPDATE_NFLAG(RD); | ||
| 1294 | UPDATE_ZFLAG(RD); | ||
| 1295 | cpu->CFlag = carry; | ||
| 1296 | cpu->VFlag = overflow; | ||
| 1297 | } | ||
| 1298 | if (inst_cream->Rd == 15) { | ||
| 1299 | INC_PC(sizeof(add_inst)); | ||
| 1300 | goto DISPATCH; | ||
| 1301 | } | ||
| 1302 | } | 1722 | } |
| 1303 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1304 | INC_PC(sizeof(add_inst)); | ||
| 1305 | FETCH_INST; | ||
| 1306 | GOTO_NEXT_INST; | ||
| 1307 | } | 1723 | } |
| 1308 | AND_INST: | 1724 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1309 | { | 1725 | INC_PC(sizeof(add_inst)); |
| 1310 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 1726 | FETCH_INST; |
| 1311 | and_inst* const inst_cream = (and_inst*)inst_base->component; | 1727 | GOTO_NEXT_INST; |
| 1728 | } | ||
| 1729 | AND_INST : { | ||
| 1730 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1731 | and_inst* const inst_cream = (and_inst*)inst_base->component; | ||
| 1312 | 1732 | ||
| 1313 | u32 lop = RN; | 1733 | u32 lop = RN; |
| 1314 | u32 rop = SHIFTER_OPERAND; | 1734 | u32 rop = SHIFTER_OPERAND; |
| 1315 | 1735 | ||
| 1316 | if (inst_cream->Rn == 15) | 1736 | if (inst_cream->Rn == 15) |
| 1317 | lop += 2 * cpu->GetInstructionSize(); | 1737 | lop += 2 * cpu->GetInstructionSize(); |
| 1318 | 1738 | ||
| 1319 | RD = lop & rop; | 1739 | RD = lop & rop; |
| 1320 | 1740 | ||
| 1321 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 1741 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 1322 | if (CurrentModeHasSPSR) { | 1742 | if (CurrentModeHasSPSR) { |
| 1323 | cpu->Cpsr = cpu->Spsr_copy; | 1743 | cpu->Cpsr = cpu->Spsr_copy; |
| 1324 | cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); | 1744 | cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); |
| 1325 | LOAD_NZCVT; | 1745 | LOAD_NZCVT; |
| 1326 | } | ||
| 1327 | } else if (inst_cream->S) { | ||
| 1328 | UPDATE_NFLAG(RD); | ||
| 1329 | UPDATE_ZFLAG(RD); | ||
| 1330 | UPDATE_CFLAG_WITH_SC; | ||
| 1331 | } | ||
| 1332 | if (inst_cream->Rd == 15) { | ||
| 1333 | INC_PC(sizeof(and_inst)); | ||
| 1334 | goto DISPATCH; | ||
| 1335 | } | 1746 | } |
| 1747 | } else if (inst_cream->S) { | ||
| 1748 | UPDATE_NFLAG(RD); | ||
| 1749 | UPDATE_ZFLAG(RD); | ||
| 1750 | UPDATE_CFLAG_WITH_SC; | ||
| 1336 | } | 1751 | } |
| 1337 | cpu->Reg[15] += cpu->GetInstructionSize(); | 1752 | if (inst_cream->Rd == 15) { |
| 1338 | INC_PC(sizeof(and_inst)); | 1753 | INC_PC(sizeof(and_inst)); |
| 1339 | FETCH_INST; | ||
| 1340 | GOTO_NEXT_INST; | ||
| 1341 | } | ||
| 1342 | BBL_INST: | ||
| 1343 | { | ||
| 1344 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | ||
| 1345 | bbl_inst *inst_cream = (bbl_inst *)inst_base->component; | ||
| 1346 | if (inst_cream->L) { | ||
| 1347 | LINK_RTN_ADDR; | ||
| 1348 | } | ||
| 1349 | SET_PC; | ||
| 1350 | INC_PC(sizeof(bbl_inst)); | ||
| 1351 | goto DISPATCH; | 1754 | goto DISPATCH; |
| 1352 | } | 1755 | } |
| 1353 | cpu->Reg[15] += cpu->GetInstructionSize(); | 1756 | } |
| 1757 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1758 | INC_PC(sizeof(and_inst)); | ||
| 1759 | FETCH_INST; | ||
| 1760 | GOTO_NEXT_INST; | ||
| 1761 | } | ||
| 1762 | BBL_INST : { | ||
| 1763 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | ||
| 1764 | bbl_inst* inst_cream = (bbl_inst*)inst_base->component; | ||
| 1765 | if (inst_cream->L) { | ||
| 1766 | LINK_RTN_ADDR; | ||
| 1767 | } | ||
| 1768 | SET_PC; | ||
| 1354 | INC_PC(sizeof(bbl_inst)); | 1769 | INC_PC(sizeof(bbl_inst)); |
| 1355 | goto DISPATCH; | 1770 | goto DISPATCH; |
| 1356 | } | 1771 | } |
| 1357 | BIC_INST: | 1772 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1358 | { | 1773 | INC_PC(sizeof(bbl_inst)); |
| 1359 | bic_inst *inst_cream = (bic_inst *)inst_base->component; | 1774 | goto DISPATCH; |
| 1360 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 1775 | } |
| 1361 | u32 lop = RN; | 1776 | BIC_INST : { |
| 1362 | if (inst_cream->Rn == 15) { | 1777 | bic_inst* inst_cream = (bic_inst*)inst_base->component; |
| 1363 | lop += 2 * cpu->GetInstructionSize(); | 1778 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 1364 | } | 1779 | u32 lop = RN; |
| 1365 | u32 rop = SHIFTER_OPERAND; | 1780 | if (inst_cream->Rn == 15) { |
| 1366 | RD = lop & (~rop); | 1781 | lop += 2 * cpu->GetInstructionSize(); |
| 1367 | if ((inst_cream->S) && (inst_cream->Rd == 15)) { | ||
| 1368 | if (CurrentModeHasSPSR) { | ||
| 1369 | cpu->Cpsr = cpu->Spsr_copy; | ||
| 1370 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); | ||
| 1371 | LOAD_NZCVT; | ||
| 1372 | } | ||
| 1373 | } else if (inst_cream->S) { | ||
| 1374 | UPDATE_NFLAG(RD); | ||
| 1375 | UPDATE_ZFLAG(RD); | ||
| 1376 | UPDATE_CFLAG_WITH_SC; | ||
| 1377 | } | ||
| 1378 | if (inst_cream->Rd == 15) { | ||
| 1379 | INC_PC(sizeof(bic_inst)); | ||
| 1380 | goto DISPATCH; | ||
| 1381 | } | ||
| 1382 | } | ||
| 1383 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1384 | INC_PC(sizeof(bic_inst)); | ||
| 1385 | FETCH_INST; | ||
| 1386 | GOTO_NEXT_INST; | ||
| 1387 | } | ||
| 1388 | BKPT_INST: | ||
| 1389 | { | ||
| 1390 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1391 | bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component; | ||
| 1392 | LOG_DEBUG(Core_ARM11, "Breakpoint instruction hit. Immediate: 0x%08X", inst_cream->imm); | ||
| 1393 | } | 1782 | } |
| 1394 | cpu->Reg[15] += cpu->GetInstructionSize(); | 1783 | u32 rop = SHIFTER_OPERAND; |
| 1395 | INC_PC(sizeof(bkpt_inst)); | 1784 | RD = lop & (~rop); |
| 1396 | FETCH_INST; | 1785 | if ((inst_cream->S) && (inst_cream->Rd == 15)) { |
| 1397 | GOTO_NEXT_INST; | 1786 | if (CurrentModeHasSPSR) { |
| 1398 | } | 1787 | cpu->Cpsr = cpu->Spsr_copy; |
| 1399 | BLX_INST: | 1788 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); |
| 1400 | { | 1789 | LOAD_NZCVT; |
| 1401 | blx_inst *inst_cream = (blx_inst *)inst_base->component; | ||
| 1402 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | ||
| 1403 | unsigned int inst = inst_cream->inst; | ||
| 1404 | if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) { | ||
| 1405 | const u32 jump_address = cpu->Reg[inst_cream->val.Rm]; | ||
| 1406 | cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize()); | ||
| 1407 | if(cpu->TFlag) | ||
| 1408 | cpu->Reg[14] |= 0x1; | ||
| 1409 | cpu->Reg[15] = jump_address & 0xfffffffe; | ||
| 1410 | cpu->TFlag = jump_address & 0x1; | ||
| 1411 | } else { | ||
| 1412 | cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize()); | ||
| 1413 | cpu->TFlag = 0x1; | ||
| 1414 | int signed_int = inst_cream->val.signed_immed_24; | ||
| 1415 | signed_int = (signed_int & 0x800000) ? (0x3F000000 | signed_int) : signed_int; | ||
| 1416 | signed_int = signed_int << 2; | ||
| 1417 | cpu->Reg[15] = cpu->Reg[15] + 8 + signed_int + (BIT(inst, 24) << 1); | ||
| 1418 | } | 1790 | } |
| 1419 | INC_PC(sizeof(blx_inst)); | 1791 | } else if (inst_cream->S) { |
| 1792 | UPDATE_NFLAG(RD); | ||
| 1793 | UPDATE_ZFLAG(RD); | ||
| 1794 | UPDATE_CFLAG_WITH_SC; | ||
| 1795 | } | ||
| 1796 | if (inst_cream->Rd == 15) { | ||
| 1797 | INC_PC(sizeof(bic_inst)); | ||
| 1420 | goto DISPATCH; | 1798 | goto DISPATCH; |
| 1421 | } | 1799 | } |
| 1422 | cpu->Reg[15] += cpu->GetInstructionSize(); | 1800 | } |
| 1801 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1802 | INC_PC(sizeof(bic_inst)); | ||
| 1803 | FETCH_INST; | ||
| 1804 | GOTO_NEXT_INST; | ||
| 1805 | } | ||
| 1806 | BKPT_INST : { | ||
| 1807 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1808 | bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component; | ||
| 1809 | LOG_DEBUG(Core_ARM11, "Breakpoint instruction hit. Immediate: 0x%08X", inst_cream->imm); | ||
| 1810 | } | ||
| 1811 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1812 | INC_PC(sizeof(bkpt_inst)); | ||
| 1813 | FETCH_INST; | ||
| 1814 | GOTO_NEXT_INST; | ||
| 1815 | } | ||
| 1816 | BLX_INST : { | ||
| 1817 | blx_inst* inst_cream = (blx_inst*)inst_base->component; | ||
| 1818 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | ||
| 1819 | unsigned int inst = inst_cream->inst; | ||
| 1820 | if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) { | ||
| 1821 | const u32 jump_address = cpu->Reg[inst_cream->val.Rm]; | ||
| 1822 | cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize()); | ||
| 1823 | if (cpu->TFlag) | ||
| 1824 | cpu->Reg[14] |= 0x1; | ||
| 1825 | cpu->Reg[15] = jump_address & 0xfffffffe; | ||
| 1826 | cpu->TFlag = jump_address & 0x1; | ||
| 1827 | } else { | ||
| 1828 | cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize()); | ||
| 1829 | cpu->TFlag = 0x1; | ||
| 1830 | int signed_int = inst_cream->val.signed_immed_24; | ||
| 1831 | signed_int = (signed_int & 0x800000) ? (0x3F000000 | signed_int) : signed_int; | ||
| 1832 | signed_int = signed_int << 2; | ||
| 1833 | cpu->Reg[15] = cpu->Reg[15] + 8 + signed_int + (BIT(inst, 24) << 1); | ||
| 1834 | } | ||
| 1423 | INC_PC(sizeof(blx_inst)); | 1835 | INC_PC(sizeof(blx_inst)); |
| 1424 | goto DISPATCH; | 1836 | goto DISPATCH; |
| 1425 | } | 1837 | } |
| 1838 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1839 | INC_PC(sizeof(blx_inst)); | ||
| 1840 | goto DISPATCH; | ||
| 1841 | } | ||
| 1426 | 1842 | ||
| 1427 | BX_INST: | 1843 | BX_INST: |
| 1428 | BXJ_INST: | 1844 | BXJ_INST : { |
| 1429 | { | 1845 | // Note that only the 'fail' case of BXJ is emulated. This is because |
| 1430 | // Note that only the 'fail' case of BXJ is emulated. This is because | 1846 | // the facilities for Jazelle emulation are not implemented. |
| 1431 | // the facilities for Jazelle emulation are not implemented. | 1847 | // |
| 1432 | // | 1848 | // According to the ARM documentation on BXJ, if setting the J bit in the APSR |
| 1433 | // According to the ARM documentation on BXJ, if setting the J bit in the APSR | 1849 | // fails, then BXJ functions identically like a regular BX instruction. |
| 1434 | // fails, then BXJ functions identically like a regular BX instruction. | 1850 | // |
| 1435 | // | 1851 | // This is sufficient for citra, as the CPU for the 3DS does not implement Jazelle. |
| 1436 | // This is sufficient for citra, as the CPU for the 3DS does not implement Jazelle. | ||
| 1437 | 1852 | ||
| 1438 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 1853 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 1439 | bx_inst* const inst_cream = (bx_inst*)inst_base->component; | 1854 | bx_inst* const inst_cream = (bx_inst*)inst_base->component; |
| 1440 | 1855 | ||
| 1441 | u32 address = RM; | 1856 | u32 address = RM; |
| 1442 | 1857 | ||
| 1443 | if (inst_cream->Rm == 15) | 1858 | if (inst_cream->Rm == 15) |
| 1444 | address += 2 * cpu->GetInstructionSize(); | 1859 | address += 2 * cpu->GetInstructionSize(); |
| 1445 | 1860 | ||
| 1446 | cpu->TFlag = address & 1; | 1861 | cpu->TFlag = address & 1; |
| 1447 | cpu->Reg[15] = address & 0xfffffffe; | 1862 | cpu->Reg[15] = address & 0xfffffffe; |
| 1448 | INC_PC(sizeof(bx_inst)); | ||
| 1449 | goto DISPATCH; | ||
| 1450 | } | ||
| 1451 | |||
| 1452 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1453 | INC_PC(sizeof(bx_inst)); | 1863 | INC_PC(sizeof(bx_inst)); |
| 1454 | goto DISPATCH; | 1864 | goto DISPATCH; |
| 1455 | } | 1865 | } |
| 1456 | 1866 | ||
| 1457 | CDP_INST: | 1867 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1458 | { | 1868 | INC_PC(sizeof(bx_inst)); |
| 1459 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 1869 | goto DISPATCH; |
| 1460 | // Undefined instruction here | 1870 | } |
| 1461 | cpu->NumInstrsToExecute = 0; | 1871 | |
| 1462 | return num_instrs; | 1872 | CDP_INST : { |
| 1873 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1874 | // Undefined instruction here | ||
| 1875 | cpu->NumInstrsToExecute = 0; | ||
| 1876 | return num_instrs; | ||
| 1877 | } | ||
| 1878 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1879 | INC_PC(sizeof(cdp_inst)); | ||
| 1880 | FETCH_INST; | ||
| 1881 | GOTO_NEXT_INST; | ||
| 1882 | } | ||
| 1883 | |||
| 1884 | CLREX_INST : { | ||
| 1885 | cpu->UnsetExclusiveMemoryAddress(); | ||
| 1886 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1887 | INC_PC(sizeof(clrex_inst)); | ||
| 1888 | FETCH_INST; | ||
| 1889 | GOTO_NEXT_INST; | ||
| 1890 | } | ||
| 1891 | CLZ_INST : { | ||
| 1892 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1893 | clz_inst* inst_cream = (clz_inst*)inst_base->component; | ||
| 1894 | RD = clz(RM); | ||
| 1895 | } | ||
| 1896 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1897 | INC_PC(sizeof(clz_inst)); | ||
| 1898 | FETCH_INST; | ||
| 1899 | GOTO_NEXT_INST; | ||
| 1900 | } | ||
| 1901 | CMN_INST : { | ||
| 1902 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1903 | cmn_inst* const inst_cream = (cmn_inst*)inst_base->component; | ||
| 1904 | |||
| 1905 | u32 rn_val = RN; | ||
| 1906 | if (inst_cream->Rn == 15) | ||
| 1907 | rn_val += 2 * cpu->GetInstructionSize(); | ||
| 1908 | |||
| 1909 | bool carry; | ||
| 1910 | bool overflow; | ||
| 1911 | u32 result = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow); | ||
| 1912 | |||
| 1913 | UPDATE_NFLAG(result); | ||
| 1914 | UPDATE_ZFLAG(result); | ||
| 1915 | cpu->CFlag = carry; | ||
| 1916 | cpu->VFlag = overflow; | ||
| 1917 | } | ||
| 1918 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1919 | INC_PC(sizeof(cmn_inst)); | ||
| 1920 | FETCH_INST; | ||
| 1921 | GOTO_NEXT_INST; | ||
| 1922 | } | ||
| 1923 | CMP_INST : { | ||
| 1924 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1925 | cmp_inst* const inst_cream = (cmp_inst*)inst_base->component; | ||
| 1926 | |||
| 1927 | u32 rn_val = RN; | ||
| 1928 | if (inst_cream->Rn == 15) | ||
| 1929 | rn_val += 2 * cpu->GetInstructionSize(); | ||
| 1930 | |||
| 1931 | bool carry; | ||
| 1932 | bool overflow; | ||
| 1933 | u32 result = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow); | ||
| 1934 | |||
| 1935 | UPDATE_NFLAG(result); | ||
| 1936 | UPDATE_ZFLAG(result); | ||
| 1937 | cpu->CFlag = carry; | ||
| 1938 | cpu->VFlag = overflow; | ||
| 1939 | } | ||
| 1940 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1941 | INC_PC(sizeof(cmp_inst)); | ||
| 1942 | FETCH_INST; | ||
| 1943 | GOTO_NEXT_INST; | ||
| 1944 | } | ||
| 1945 | CPS_INST : { | ||
| 1946 | cps_inst* inst_cream = (cps_inst*)inst_base->component; | ||
| 1947 | u32 aif_val = 0; | ||
| 1948 | u32 aif_mask = 0; | ||
| 1949 | if (cpu->InAPrivilegedMode()) { | ||
| 1950 | if (inst_cream->imod1) { | ||
| 1951 | if (inst_cream->A) { | ||
| 1952 | aif_val |= (inst_cream->imod0 << 8); | ||
| 1953 | aif_mask |= 1 << 8; | ||
| 1954 | } | ||
| 1955 | if (inst_cream->I) { | ||
| 1956 | aif_val |= (inst_cream->imod0 << 7); | ||
| 1957 | aif_mask |= 1 << 7; | ||
| 1958 | } | ||
| 1959 | if (inst_cream->F) { | ||
| 1960 | aif_val |= (inst_cream->imod0 << 6); | ||
| 1961 | aif_mask |= 1 << 6; | ||
| 1962 | } | ||
| 1963 | aif_mask = ~aif_mask; | ||
| 1964 | cpu->Cpsr = (cpu->Cpsr & aif_mask) | aif_val; | ||
| 1463 | } | 1965 | } |
| 1464 | cpu->Reg[15] += cpu->GetInstructionSize(); | 1966 | if (inst_cream->mmod) { |
| 1465 | INC_PC(sizeof(cdp_inst)); | 1967 | cpu->Cpsr = (cpu->Cpsr & 0xffffffe0) | inst_cream->mode; |
| 1466 | FETCH_INST; | 1968 | cpu->ChangePrivilegeMode(inst_cream->mode); |
| 1467 | GOTO_NEXT_INST; | ||
| 1468 | } | ||
| 1469 | |||
| 1470 | CLREX_INST: | ||
| 1471 | { | ||
| 1472 | cpu->UnsetExclusiveMemoryAddress(); | ||
| 1473 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1474 | INC_PC(sizeof(clrex_inst)); | ||
| 1475 | FETCH_INST; | ||
| 1476 | GOTO_NEXT_INST; | ||
| 1477 | } | ||
| 1478 | CLZ_INST: | ||
| 1479 | { | ||
| 1480 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1481 | clz_inst* inst_cream = (clz_inst*)inst_base->component; | ||
| 1482 | RD = clz(RM); | ||
| 1483 | } | 1969 | } |
| 1484 | cpu->Reg[15] += cpu->GetInstructionSize(); | 1970 | } |
| 1485 | INC_PC(sizeof(clz_inst)); | 1971 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1486 | FETCH_INST; | 1972 | INC_PC(sizeof(cps_inst)); |
| 1487 | GOTO_NEXT_INST; | 1973 | FETCH_INST; |
| 1488 | } | 1974 | GOTO_NEXT_INST; |
| 1489 | CMN_INST: | 1975 | } |
| 1490 | { | 1976 | CPY_INST : { |
| 1491 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 1977 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 1492 | cmn_inst* const inst_cream = (cmn_inst*)inst_base->component; | 1978 | mov_inst* inst_cream = (mov_inst*)inst_base->component; |
| 1493 | 1979 | ||
| 1494 | u32 rn_val = RN; | 1980 | RD = SHIFTER_OPERAND; |
| 1495 | if (inst_cream->Rn == 15) | 1981 | if (inst_cream->Rd == 15) { |
| 1496 | rn_val += 2 * cpu->GetInstructionSize(); | 1982 | INC_PC(sizeof(mov_inst)); |
| 1497 | 1983 | goto DISPATCH; | |
| 1498 | bool carry; | ||
| 1499 | bool overflow; | ||
| 1500 | u32 result = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow); | ||
| 1501 | |||
| 1502 | UPDATE_NFLAG(result); | ||
| 1503 | UPDATE_ZFLAG(result); | ||
| 1504 | cpu->CFlag = carry; | ||
| 1505 | cpu->VFlag = overflow; | ||
| 1506 | } | 1984 | } |
| 1507 | cpu->Reg[15] += cpu->GetInstructionSize(); | 1985 | } |
| 1508 | INC_PC(sizeof(cmn_inst)); | 1986 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1509 | FETCH_INST; | 1987 | INC_PC(sizeof(mov_inst)); |
| 1510 | GOTO_NEXT_INST; | 1988 | FETCH_INST; |
| 1511 | } | 1989 | GOTO_NEXT_INST; |
| 1512 | CMP_INST: | 1990 | } |
| 1513 | { | 1991 | EOR_INST : { |
| 1514 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 1992 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 1515 | cmp_inst* const inst_cream = (cmp_inst*)inst_base->component; | 1993 | eor_inst* inst_cream = (eor_inst*)inst_base->component; |
| 1516 | 1994 | ||
| 1517 | u32 rn_val = RN; | 1995 | u32 lop = RN; |
| 1518 | if (inst_cream->Rn == 15) | 1996 | if (inst_cream->Rn == 15) { |
| 1519 | rn_val += 2 * cpu->GetInstructionSize(); | 1997 | lop += 2 * cpu->GetInstructionSize(); |
| 1520 | |||
| 1521 | bool carry; | ||
| 1522 | bool overflow; | ||
| 1523 | u32 result = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow); | ||
| 1524 | |||
| 1525 | UPDATE_NFLAG(result); | ||
| 1526 | UPDATE_ZFLAG(result); | ||
| 1527 | cpu->CFlag = carry; | ||
| 1528 | cpu->VFlag = overflow; | ||
| 1529 | } | 1998 | } |
| 1530 | cpu->Reg[15] += cpu->GetInstructionSize(); | 1999 | u32 rop = SHIFTER_OPERAND; |
| 1531 | INC_PC(sizeof(cmp_inst)); | 2000 | RD = lop ^ rop; |
| 1532 | FETCH_INST; | 2001 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 1533 | GOTO_NEXT_INST; | 2002 | if (CurrentModeHasSPSR) { |
| 1534 | } | 2003 | cpu->Cpsr = cpu->Spsr_copy; |
| 1535 | CPS_INST: | 2004 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); |
| 1536 | { | 2005 | LOAD_NZCVT; |
| 1537 | cps_inst *inst_cream = (cps_inst *)inst_base->component; | ||
| 1538 | u32 aif_val = 0; | ||
| 1539 | u32 aif_mask = 0; | ||
| 1540 | if (cpu->InAPrivilegedMode()) { | ||
| 1541 | if (inst_cream->imod1) { | ||
| 1542 | if (inst_cream->A) { | ||
| 1543 | aif_val |= (inst_cream->imod0 << 8); | ||
| 1544 | aif_mask |= 1 << 8; | ||
| 1545 | } | ||
| 1546 | if (inst_cream->I) { | ||
| 1547 | aif_val |= (inst_cream->imod0 << 7); | ||
| 1548 | aif_mask |= 1 << 7; | ||
| 1549 | } | ||
| 1550 | if (inst_cream->F) { | ||
| 1551 | aif_val |= (inst_cream->imod0 << 6); | ||
| 1552 | aif_mask |= 1 << 6; | ||
| 1553 | } | ||
| 1554 | aif_mask = ~aif_mask; | ||
| 1555 | cpu->Cpsr = (cpu->Cpsr & aif_mask) | aif_val; | ||
| 1556 | } | ||
| 1557 | if (inst_cream->mmod) { | ||
| 1558 | cpu->Cpsr = (cpu->Cpsr & 0xffffffe0) | inst_cream->mode; | ||
| 1559 | cpu->ChangePrivilegeMode(inst_cream->mode); | ||
| 1560 | } | 2006 | } |
| 2007 | } else if (inst_cream->S) { | ||
| 2008 | UPDATE_NFLAG(RD); | ||
| 2009 | UPDATE_ZFLAG(RD); | ||
| 2010 | UPDATE_CFLAG_WITH_SC; | ||
| 2011 | } | ||
| 2012 | if (inst_cream->Rd == 15) { | ||
| 2013 | INC_PC(sizeof(eor_inst)); | ||
| 2014 | goto DISPATCH; | ||
| 1561 | } | 2015 | } |
| 1562 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1563 | INC_PC(sizeof(cps_inst)); | ||
| 1564 | FETCH_INST; | ||
| 1565 | GOTO_NEXT_INST; | ||
| 1566 | } | 2016 | } |
| 1567 | CPY_INST: | 2017 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1568 | { | 2018 | INC_PC(sizeof(eor_inst)); |
| 1569 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2019 | FETCH_INST; |
| 1570 | mov_inst* inst_cream = (mov_inst*)inst_base->component; | 2020 | GOTO_NEXT_INST; |
| 2021 | } | ||
| 2022 | LDC_INST : { | ||
| 2023 | // Instruction not implemented | ||
| 2024 | // LOG_CRITICAL(Core_ARM11, "unimplemented instruction"); | ||
| 2025 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2026 | INC_PC(sizeof(ldc_inst)); | ||
| 2027 | FETCH_INST; | ||
| 2028 | GOTO_NEXT_INST; | ||
| 2029 | } | ||
| 2030 | LDM_INST : { | ||
| 2031 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2032 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 2033 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 1571 | 2034 | ||
| 1572 | RD = SHIFTER_OPERAND; | 2035 | unsigned int inst = inst_cream->inst; |
| 1573 | if (inst_cream->Rd == 15) { | 2036 | if (BIT(inst, 22) && !BIT(inst, 15)) { |
| 1574 | INC_PC(sizeof(mov_inst)); | 2037 | for (int i = 0; i < 13; i++) { |
| 1575 | goto DISPATCH; | 2038 | if (BIT(inst, i)) { |
| 1576 | } | 2039 | cpu->Reg[i] = cpu->ReadMemory32(addr); |
| 1577 | } | 2040 | addr += 4; |
| 1578 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1579 | INC_PC(sizeof(mov_inst)); | ||
| 1580 | FETCH_INST; | ||
| 1581 | GOTO_NEXT_INST; | ||
| 1582 | } | ||
| 1583 | EOR_INST: | ||
| 1584 | { | ||
| 1585 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1586 | eor_inst* inst_cream = (eor_inst*)inst_base->component; | ||
| 1587 | |||
| 1588 | u32 lop = RN; | ||
| 1589 | if (inst_cream->Rn == 15) { | ||
| 1590 | lop += 2 * cpu->GetInstructionSize(); | ||
| 1591 | } | ||
| 1592 | u32 rop = SHIFTER_OPERAND; | ||
| 1593 | RD = lop ^ rop; | ||
| 1594 | if (inst_cream->S && (inst_cream->Rd == 15)) { | ||
| 1595 | if (CurrentModeHasSPSR) { | ||
| 1596 | cpu->Cpsr = cpu->Spsr_copy; | ||
| 1597 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); | ||
| 1598 | LOAD_NZCVT; | ||
| 1599 | } | 2041 | } |
| 1600 | } else if (inst_cream->S) { | ||
| 1601 | UPDATE_NFLAG(RD); | ||
| 1602 | UPDATE_ZFLAG(RD); | ||
| 1603 | UPDATE_CFLAG_WITH_SC; | ||
| 1604 | } | 2042 | } |
| 1605 | if (inst_cream->Rd == 15) { | 2043 | if (BIT(inst, 13)) { |
| 1606 | INC_PC(sizeof(eor_inst)); | 2044 | if (cpu->Mode == USER32MODE) |
| 1607 | goto DISPATCH; | 2045 | cpu->Reg[13] = cpu->ReadMemory32(addr); |
| 2046 | else | ||
| 2047 | cpu->Reg_usr[0] = cpu->ReadMemory32(addr); | ||
| 2048 | |||
| 2049 | addr += 4; | ||
| 1608 | } | 2050 | } |
| 1609 | } | 2051 | if (BIT(inst, 14)) { |
| 1610 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2052 | if (cpu->Mode == USER32MODE) |
| 1611 | INC_PC(sizeof(eor_inst)); | 2053 | cpu->Reg[14] = cpu->ReadMemory32(addr); |
| 1612 | FETCH_INST; | 2054 | else |
| 1613 | GOTO_NEXT_INST; | 2055 | cpu->Reg_usr[1] = cpu->ReadMemory32(addr); |
| 1614 | } | 2056 | |
| 1615 | LDC_INST: | 2057 | addr += 4; |
| 1616 | { | 2058 | } |
| 1617 | // Instruction not implemented | 2059 | } else if (!BIT(inst, 22)) { |
| 1618 | //LOG_CRITICAL(Core_ARM11, "unimplemented instruction"); | 2060 | for (int i = 0; i < 16; i++) { |
| 1619 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2061 | if (BIT(inst, i)) { |
| 1620 | INC_PC(sizeof(ldc_inst)); | 2062 | unsigned int ret = cpu->ReadMemory32(addr); |
| 1621 | FETCH_INST; | 2063 | |
| 1622 | GOTO_NEXT_INST; | 2064 | // For armv5t, should enter thumb when bits[0] is non-zero. |
| 1623 | } | 2065 | if (i == 15) { |
| 1624 | LDM_INST: | 2066 | cpu->TFlag = ret & 0x1; |
| 1625 | { | 2067 | ret &= 0xFFFFFFFE; |
| 1626 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1627 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 1628 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 1629 | |||
| 1630 | unsigned int inst = inst_cream->inst; | ||
| 1631 | if (BIT(inst, 22) && !BIT(inst, 15)) { | ||
| 1632 | for (int i = 0; i < 13; i++) { | ||
| 1633 | if(BIT(inst, i)) { | ||
| 1634 | cpu->Reg[i] = cpu->ReadMemory32(addr); | ||
| 1635 | addr += 4; | ||
| 1636 | } | 2068 | } |
| 1637 | } | ||
| 1638 | if (BIT(inst, 13)) { | ||
| 1639 | if (cpu->Mode == USER32MODE) | ||
| 1640 | cpu->Reg[13] = cpu->ReadMemory32(addr); | ||
| 1641 | else | ||
| 1642 | cpu->Reg_usr[0] = cpu->ReadMemory32(addr); | ||
| 1643 | 2069 | ||
| 2070 | cpu->Reg[i] = ret; | ||
| 1644 | addr += 4; | 2071 | addr += 4; |
| 1645 | } | 2072 | } |
| 1646 | if (BIT(inst, 14)) { | 2073 | } |
| 1647 | if (cpu->Mode == USER32MODE) | 2074 | } else if (BIT(inst, 22) && BIT(inst, 15)) { |
| 1648 | cpu->Reg[14] = cpu->ReadMemory32(addr); | 2075 | for (int i = 0; i < 15; i++) { |
| 1649 | else | 2076 | if (BIT(inst, i)) { |
| 1650 | cpu->Reg_usr[1] = cpu->ReadMemory32(addr); | 2077 | cpu->Reg[i] = cpu->ReadMemory32(addr); |
| 1651 | |||
| 1652 | addr += 4; | 2078 | addr += 4; |
| 1653 | } | 2079 | } |
| 1654 | } else if (!BIT(inst, 22)) { | ||
| 1655 | for(int i = 0; i < 16; i++ ){ | ||
| 1656 | if(BIT(inst, i)){ | ||
| 1657 | unsigned int ret = cpu->ReadMemory32(addr); | ||
| 1658 | |||
| 1659 | // For armv5t, should enter thumb when bits[0] is non-zero. | ||
| 1660 | if(i == 15){ | ||
| 1661 | cpu->TFlag = ret & 0x1; | ||
| 1662 | ret &= 0xFFFFFFFE; | ||
| 1663 | } | ||
| 1664 | |||
| 1665 | cpu->Reg[i] = ret; | ||
| 1666 | addr += 4; | ||
| 1667 | } | ||
| 1668 | } | ||
| 1669 | } else if (BIT(inst, 22) && BIT(inst, 15)) { | ||
| 1670 | for(int i = 0; i < 15; i++ ){ | ||
| 1671 | if(BIT(inst, i)){ | ||
| 1672 | cpu->Reg[i] = cpu->ReadMemory32(addr); | ||
| 1673 | addr += 4; | ||
| 1674 | } | ||
| 1675 | } | ||
| 1676 | |||
| 1677 | if (CurrentModeHasSPSR) { | ||
| 1678 | cpu->Cpsr = cpu->Spsr_copy; | ||
| 1679 | cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); | ||
| 1680 | LOAD_NZCVT; | ||
| 1681 | } | ||
| 1682 | |||
| 1683 | cpu->Reg[15] = cpu->ReadMemory32(addr); | ||
| 1684 | } | 2080 | } |
| 1685 | 2081 | ||
| 1686 | if (BIT(inst, 15)) { | 2082 | if (CurrentModeHasSPSR) { |
| 1687 | INC_PC(sizeof(ldst_inst)); | 2083 | cpu->Cpsr = cpu->Spsr_copy; |
| 1688 | goto DISPATCH; | 2084 | cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); |
| 2085 | LOAD_NZCVT; | ||
| 1689 | } | 2086 | } |
| 2087 | |||
| 2088 | cpu->Reg[15] = cpu->ReadMemory32(addr); | ||
| 2089 | } | ||
| 2090 | |||
| 2091 | if (BIT(inst, 15)) { | ||
| 2092 | INC_PC(sizeof(ldst_inst)); | ||
| 2093 | goto DISPATCH; | ||
| 1690 | } | 2094 | } |
| 1691 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1692 | INC_PC(sizeof(ldst_inst)); | ||
| 1693 | FETCH_INST; | ||
| 1694 | GOTO_NEXT_INST; | ||
| 1695 | } | 2095 | } |
| 1696 | SXTH_INST: | 2096 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1697 | { | 2097 | INC_PC(sizeof(ldst_inst)); |
| 1698 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2098 | FETCH_INST; |
| 1699 | sxth_inst* inst_cream = (sxth_inst*)inst_base->component; | 2099 | GOTO_NEXT_INST; |
| 2100 | } | ||
| 2101 | SXTH_INST : { | ||
| 2102 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2103 | sxth_inst* inst_cream = (sxth_inst*)inst_base->component; | ||
| 1700 | 2104 | ||
| 1701 | unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate); | 2105 | unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate); |
| 1702 | if (BIT(operand2, 15)) { | 2106 | if (BIT(operand2, 15)) { |
| 1703 | operand2 |= 0xffff0000; | 2107 | operand2 |= 0xffff0000; |
| 1704 | } else { | 2108 | } else { |
| 1705 | operand2 &= 0xffff; | 2109 | operand2 &= 0xffff; |
| 1706 | } | ||
| 1707 | RD = operand2; | ||
| 1708 | } | 2110 | } |
| 1709 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2111 | RD = operand2; |
| 1710 | INC_PC(sizeof(sxth_inst)); | 2112 | } |
| 1711 | FETCH_INST; | 2113 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1712 | GOTO_NEXT_INST; | 2114 | INC_PC(sizeof(sxth_inst)); |
| 1713 | } | 2115 | FETCH_INST; |
| 1714 | LDR_INST: | 2116 | GOTO_NEXT_INST; |
| 1715 | { | 2117 | } |
| 1716 | ldst_inst *inst_cream = (ldst_inst *)inst_base->component; | 2118 | LDR_INST : { |
| 2119 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 2120 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 2121 | |||
| 2122 | unsigned int value = cpu->ReadMemory32(addr); | ||
| 2123 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; | ||
| 2124 | |||
| 2125 | if (BITS(inst_cream->inst, 12, 15) == 15) { | ||
| 2126 | // For armv5t, should enter thumb when bits[0] is non-zero. | ||
| 2127 | cpu->TFlag = value & 0x1; | ||
| 2128 | cpu->Reg[15] &= 0xFFFFFFFE; | ||
| 2129 | INC_PC(sizeof(ldst_inst)); | ||
| 2130 | goto DISPATCH; | ||
| 2131 | } | ||
| 2132 | |||
| 2133 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2134 | INC_PC(sizeof(ldst_inst)); | ||
| 2135 | FETCH_INST; | ||
| 2136 | GOTO_NEXT_INST; | ||
| 2137 | } | ||
| 2138 | LDRCOND_INST : { | ||
| 2139 | if (CondPassed(cpu, inst_base->cond)) { | ||
| 2140 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 1717 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | 2141 | inst_cream->get_addr(cpu, inst_cream->inst, addr); |
| 1718 | 2142 | ||
| 1719 | unsigned int value = cpu->ReadMemory32(addr); | 2143 | unsigned int value = cpu->ReadMemory32(addr); |
| @@ -1726,2546 +2150,2433 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 1726 | INC_PC(sizeof(ldst_inst)); | 2150 | INC_PC(sizeof(ldst_inst)); |
| 1727 | goto DISPATCH; | 2151 | goto DISPATCH; |
| 1728 | } | 2152 | } |
| 2153 | } | ||
| 2154 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2155 | INC_PC(sizeof(ldst_inst)); | ||
| 2156 | FETCH_INST; | ||
| 2157 | GOTO_NEXT_INST; | ||
| 2158 | } | ||
| 2159 | UXTH_INST : { | ||
| 2160 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2161 | uxth_inst* inst_cream = (uxth_inst*)inst_base->component; | ||
| 2162 | RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff; | ||
| 2163 | } | ||
| 2164 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2165 | INC_PC(sizeof(uxth_inst)); | ||
| 2166 | FETCH_INST; | ||
| 2167 | GOTO_NEXT_INST; | ||
| 2168 | } | ||
| 2169 | UXTAH_INST : { | ||
| 2170 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2171 | uxtah_inst* inst_cream = (uxtah_inst*)inst_base->component; | ||
| 2172 | unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff; | ||
| 1729 | 2173 | ||
| 1730 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2174 | RD = RN + operand2; |
| 1731 | INC_PC(sizeof(ldst_inst)); | 2175 | } |
| 1732 | FETCH_INST; | 2176 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1733 | GOTO_NEXT_INST; | 2177 | INC_PC(sizeof(uxtah_inst)); |
| 1734 | } | 2178 | FETCH_INST; |
| 1735 | LDRCOND_INST: | 2179 | GOTO_NEXT_INST; |
| 1736 | { | 2180 | } |
| 1737 | if (CondPassed(cpu, inst_base->cond)) { | 2181 | LDRB_INST : { |
| 1738 | ldst_inst *inst_cream = (ldst_inst *)inst_base->component; | 2182 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 1739 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | 2183 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 1740 | 2184 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | |
| 1741 | unsigned int value = cpu->ReadMemory32(addr); | 2185 | |
| 1742 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; | 2186 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory8(addr); |
| 1743 | |||
| 1744 | if (BITS(inst_cream->inst, 12, 15) == 15) { | ||
| 1745 | // For armv5t, should enter thumb when bits[0] is non-zero. | ||
| 1746 | cpu->TFlag = value & 0x1; | ||
| 1747 | cpu->Reg[15] &= 0xFFFFFFFE; | ||
| 1748 | INC_PC(sizeof(ldst_inst)); | ||
| 1749 | goto DISPATCH; | ||
| 1750 | } | ||
| 1751 | } | ||
| 1752 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1753 | INC_PC(sizeof(ldst_inst)); | ||
| 1754 | FETCH_INST; | ||
| 1755 | GOTO_NEXT_INST; | ||
| 1756 | } | ||
| 1757 | UXTH_INST: | ||
| 1758 | { | ||
| 1759 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1760 | uxth_inst* inst_cream = (uxth_inst*)inst_base->component; | ||
| 1761 | RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff; | ||
| 1762 | } | ||
| 1763 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1764 | INC_PC(sizeof(uxth_inst)); | ||
| 1765 | FETCH_INST; | ||
| 1766 | GOTO_NEXT_INST; | ||
| 1767 | } | ||
| 1768 | UXTAH_INST: | ||
| 1769 | { | ||
| 1770 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1771 | uxtah_inst* inst_cream = (uxtah_inst*)inst_base->component; | ||
| 1772 | unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff; | ||
| 1773 | |||
| 1774 | RD = RN + operand2; | ||
| 1775 | } | ||
| 1776 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1777 | INC_PC(sizeof(uxtah_inst)); | ||
| 1778 | FETCH_INST; | ||
| 1779 | GOTO_NEXT_INST; | ||
| 1780 | } | ||
| 1781 | LDRB_INST: | ||
| 1782 | { | ||
| 1783 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1784 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 1785 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 1786 | |||
| 1787 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory8(addr); | ||
| 1788 | } | ||
| 1789 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1790 | INC_PC(sizeof(ldst_inst)); | ||
| 1791 | FETCH_INST; | ||
| 1792 | GOTO_NEXT_INST; | ||
| 1793 | } | 2187 | } |
| 1794 | LDRBT_INST: | 2188 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1795 | { | 2189 | INC_PC(sizeof(ldst_inst)); |
| 1796 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2190 | FETCH_INST; |
| 1797 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | 2191 | GOTO_NEXT_INST; |
| 1798 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | 2192 | } |
| 2193 | LDRBT_INST : { | ||
| 2194 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2195 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 2196 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 1799 | 2197 | ||
| 1800 | const u32 dest_index = BITS(inst_cream->inst, 12, 15); | 2198 | const u32 dest_index = BITS(inst_cream->inst, 12, 15); |
| 1801 | const u32 previous_mode = cpu->Mode; | 2199 | const u32 previous_mode = cpu->Mode; |
| 1802 | 2200 | ||
| 1803 | cpu->ChangePrivilegeMode(USER32MODE); | 2201 | cpu->ChangePrivilegeMode(USER32MODE); |
| 1804 | const u8 value = cpu->ReadMemory8(addr); | 2202 | const u8 value = cpu->ReadMemory8(addr); |
| 1805 | cpu->ChangePrivilegeMode(previous_mode); | 2203 | cpu->ChangePrivilegeMode(previous_mode); |
| 1806 | 2204 | ||
| 1807 | cpu->Reg[dest_index] = value; | 2205 | cpu->Reg[dest_index] = value; |
| 1808 | } | ||
| 1809 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1810 | INC_PC(sizeof(ldst_inst)); | ||
| 1811 | FETCH_INST; | ||
| 1812 | GOTO_NEXT_INST; | ||
| 1813 | } | ||
| 1814 | LDRD_INST: | ||
| 1815 | { | ||
| 1816 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1817 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 1818 | // Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 || addr[2] == 0) | ||
| 1819 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 1820 | |||
| 1821 | // The 3DS doesn't have LPAE (Large Physical Access Extension), so it | ||
| 1822 | // wouldn't do this as a single read. | ||
| 1823 | cpu->Reg[BITS(inst_cream->inst, 12, 15) + 0] = cpu->ReadMemory32(addr); | ||
| 1824 | cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = cpu->ReadMemory32(addr + 4); | ||
| 1825 | |||
| 1826 | // No dispatch since this operation should not modify R15 | ||
| 1827 | } | ||
| 1828 | cpu->Reg[15] += 4; | ||
| 1829 | INC_PC(sizeof(ldst_inst)); | ||
| 1830 | FETCH_INST; | ||
| 1831 | GOTO_NEXT_INST; | ||
| 1832 | } | 2206 | } |
| 2207 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2208 | INC_PC(sizeof(ldst_inst)); | ||
| 2209 | FETCH_INST; | ||
| 2210 | GOTO_NEXT_INST; | ||
| 2211 | } | ||
| 2212 | LDRD_INST : { | ||
| 2213 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2214 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 2215 | // Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 || | ||
| 2216 | // addr[2] == 0) | ||
| 2217 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 1833 | 2218 | ||
| 1834 | LDREX_INST: | 2219 | // The 3DS doesn't have LPAE (Large Physical Access Extension), so it |
| 1835 | { | 2220 | // wouldn't do this as a single read. |
| 1836 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2221 | cpu->Reg[BITS(inst_cream->inst, 12, 15) + 0] = cpu->ReadMemory32(addr); |
| 1837 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | 2222 | cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = cpu->ReadMemory32(addr + 4); |
| 1838 | unsigned int read_addr = RN; | ||
| 1839 | |||
| 1840 | cpu->SetExclusiveMemoryAddress(read_addr); | ||
| 1841 | 2223 | ||
| 1842 | RD = cpu->ReadMemory32(read_addr); | 2224 | // No dispatch since this operation should not modify R15 |
| 1843 | } | ||
| 1844 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1845 | INC_PC(sizeof(generic_arm_inst)); | ||
| 1846 | FETCH_INST; | ||
| 1847 | GOTO_NEXT_INST; | ||
| 1848 | } | 2225 | } |
| 1849 | LDREXB_INST: | 2226 | cpu->Reg[15] += 4; |
| 1850 | { | 2227 | INC_PC(sizeof(ldst_inst)); |
| 1851 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2228 | FETCH_INST; |
| 1852 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | 2229 | GOTO_NEXT_INST; |
| 1853 | unsigned int read_addr = RN; | 2230 | } |
| 1854 | 2231 | ||
| 1855 | cpu->SetExclusiveMemoryAddress(read_addr); | 2232 | LDREX_INST : { |
| 2233 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2234 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 2235 | unsigned int read_addr = RN; | ||
| 1856 | 2236 | ||
| 1857 | RD = cpu->ReadMemory8(read_addr); | 2237 | cpu->SetExclusiveMemoryAddress(read_addr); |
| 1858 | } | 2238 | |
| 1859 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2239 | RD = cpu->ReadMemory32(read_addr); |
| 1860 | INC_PC(sizeof(generic_arm_inst)); | ||
| 1861 | FETCH_INST; | ||
| 1862 | GOTO_NEXT_INST; | ||
| 1863 | } | 2240 | } |
| 1864 | LDREXH_INST: | 2241 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1865 | { | 2242 | INC_PC(sizeof(generic_arm_inst)); |
| 1866 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2243 | FETCH_INST; |
| 1867 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | 2244 | GOTO_NEXT_INST; |
| 1868 | unsigned int read_addr = RN; | 2245 | } |
| 2246 | LDREXB_INST : { | ||
| 2247 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2248 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 2249 | unsigned int read_addr = RN; | ||
| 1869 | 2250 | ||
| 1870 | cpu->SetExclusiveMemoryAddress(read_addr); | 2251 | cpu->SetExclusiveMemoryAddress(read_addr); |
| 1871 | 2252 | ||
| 1872 | RD = cpu->ReadMemory16(read_addr); | 2253 | RD = cpu->ReadMemory8(read_addr); |
| 1873 | } | ||
| 1874 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1875 | INC_PC(sizeof(generic_arm_inst)); | ||
| 1876 | FETCH_INST; | ||
| 1877 | GOTO_NEXT_INST; | ||
| 1878 | } | 2254 | } |
| 1879 | LDREXD_INST: | 2255 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1880 | { | 2256 | INC_PC(sizeof(generic_arm_inst)); |
| 1881 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2257 | FETCH_INST; |
| 1882 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | 2258 | GOTO_NEXT_INST; |
| 1883 | unsigned int read_addr = RN; | 2259 | } |
| 2260 | LDREXH_INST : { | ||
| 2261 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2262 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 2263 | unsigned int read_addr = RN; | ||
| 1884 | 2264 | ||
| 1885 | cpu->SetExclusiveMemoryAddress(read_addr); | 2265 | cpu->SetExclusiveMemoryAddress(read_addr); |
| 1886 | 2266 | ||
| 1887 | RD = cpu->ReadMemory32(read_addr); | 2267 | RD = cpu->ReadMemory16(read_addr); |
| 1888 | RD2 = cpu->ReadMemory32(read_addr + 4); | ||
| 1889 | } | ||
| 1890 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1891 | INC_PC(sizeof(generic_arm_inst)); | ||
| 1892 | FETCH_INST; | ||
| 1893 | GOTO_NEXT_INST; | ||
| 1894 | } | ||
| 1895 | LDRH_INST: | ||
| 1896 | { | ||
| 1897 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1898 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 1899 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 1900 | |||
| 1901 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory16(addr); | ||
| 1902 | } | ||
| 1903 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1904 | INC_PC(sizeof(ldst_inst)); | ||
| 1905 | FETCH_INST; | ||
| 1906 | GOTO_NEXT_INST; | ||
| 1907 | } | ||
| 1908 | LDRSB_INST: | ||
| 1909 | { | ||
| 1910 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1911 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 1912 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 1913 | unsigned int value = cpu->ReadMemory8(addr); | ||
| 1914 | if (BIT(value, 7)) { | ||
| 1915 | value |= 0xffffff00; | ||
| 1916 | } | ||
| 1917 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; | ||
| 1918 | } | ||
| 1919 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1920 | INC_PC(sizeof(ldst_inst)); | ||
| 1921 | FETCH_INST; | ||
| 1922 | GOTO_NEXT_INST; | ||
| 1923 | } | ||
| 1924 | LDRSH_INST: | ||
| 1925 | { | ||
| 1926 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1927 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 1928 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 1929 | |||
| 1930 | unsigned int value = cpu->ReadMemory16(addr); | ||
| 1931 | if (BIT(value, 15)) { | ||
| 1932 | value |= 0xffff0000; | ||
| 1933 | } | ||
| 1934 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; | ||
| 1935 | } | ||
| 1936 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 1937 | INC_PC(sizeof(ldst_inst)); | ||
| 1938 | FETCH_INST; | ||
| 1939 | GOTO_NEXT_INST; | ||
| 1940 | } | 2268 | } |
| 1941 | LDRT_INST: | 2269 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1942 | { | 2270 | INC_PC(sizeof(generic_arm_inst)); |
| 1943 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2271 | FETCH_INST; |
| 1944 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | 2272 | GOTO_NEXT_INST; |
| 1945 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | 2273 | } |
| 2274 | LDREXD_INST : { | ||
| 2275 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2276 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 2277 | unsigned int read_addr = RN; | ||
| 1946 | 2278 | ||
| 1947 | const u32 dest_index = BITS(inst_cream->inst, 12, 15); | 2279 | cpu->SetExclusiveMemoryAddress(read_addr); |
| 1948 | const u32 previous_mode = cpu->Mode; | ||
| 1949 | 2280 | ||
| 1950 | cpu->ChangePrivilegeMode(USER32MODE); | 2281 | RD = cpu->ReadMemory32(read_addr); |
| 1951 | const u32 value = cpu->ReadMemory32(addr); | 2282 | RD2 = cpu->ReadMemory32(read_addr + 4); |
| 1952 | cpu->ChangePrivilegeMode(previous_mode); | 2283 | } |
| 2284 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2285 | INC_PC(sizeof(generic_arm_inst)); | ||
| 2286 | FETCH_INST; | ||
| 2287 | GOTO_NEXT_INST; | ||
| 2288 | } | ||
| 2289 | LDRH_INST : { | ||
| 2290 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2291 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 2292 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 1953 | 2293 | ||
| 1954 | cpu->Reg[dest_index] = value; | 2294 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory16(addr); |
| 2295 | } | ||
| 2296 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2297 | INC_PC(sizeof(ldst_inst)); | ||
| 2298 | FETCH_INST; | ||
| 2299 | GOTO_NEXT_INST; | ||
| 2300 | } | ||
| 2301 | LDRSB_INST : { | ||
| 2302 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2303 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 2304 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 2305 | unsigned int value = cpu->ReadMemory8(addr); | ||
| 2306 | if (BIT(value, 7)) { | ||
| 2307 | value |= 0xffffff00; | ||
| 1955 | } | 2308 | } |
| 1956 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2309 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; |
| 1957 | INC_PC(sizeof(ldst_inst)); | ||
| 1958 | FETCH_INST; | ||
| 1959 | GOTO_NEXT_INST; | ||
| 1960 | } | 2310 | } |
| 1961 | MCR_INST: | 2311 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1962 | { | 2312 | INC_PC(sizeof(ldst_inst)); |
| 1963 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2313 | FETCH_INST; |
| 1964 | mcr_inst* inst_cream = (mcr_inst*)inst_base->component; | 2314 | GOTO_NEXT_INST; |
| 2315 | } | ||
| 2316 | LDRSH_INST : { | ||
| 2317 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2318 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 2319 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 1965 | 2320 | ||
| 1966 | unsigned int inst = inst_cream->inst; | 2321 | unsigned int value = cpu->ReadMemory16(addr); |
| 1967 | if (inst_cream->Rd == 15) { | 2322 | if (BIT(value, 15)) { |
| 1968 | DEBUG_MSG; | 2323 | value |= 0xffff0000; |
| 1969 | } else { | ||
| 1970 | if (inst_cream->cp_num == 15) | ||
| 1971 | cpu->WriteCP15Register(RD, CRn, OPCODE_1, CRm, OPCODE_2); | ||
| 1972 | } | ||
| 1973 | } | 2324 | } |
| 1974 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2325 | cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; |
| 1975 | INC_PC(sizeof(mcr_inst)); | ||
| 1976 | FETCH_INST; | ||
| 1977 | GOTO_NEXT_INST; | ||
| 1978 | } | 2326 | } |
| 2327 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2328 | INC_PC(sizeof(ldst_inst)); | ||
| 2329 | FETCH_INST; | ||
| 2330 | GOTO_NEXT_INST; | ||
| 2331 | } | ||
| 2332 | LDRT_INST : { | ||
| 2333 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2334 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 2335 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 2336 | |||
| 2337 | const u32 dest_index = BITS(inst_cream->inst, 12, 15); | ||
| 2338 | const u32 previous_mode = cpu->Mode; | ||
| 1979 | 2339 | ||
| 1980 | MCRR_INST: | 2340 | cpu->ChangePrivilegeMode(USER32MODE); |
| 1981 | { | 2341 | const u32 value = cpu->ReadMemory32(addr); |
| 1982 | // Stubbed, as the MPCore doesn't have any registers that are accessible | 2342 | cpu->ChangePrivilegeMode(previous_mode); |
| 1983 | // through this instruction. | ||
| 1984 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 1985 | mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component; | ||
| 1986 | 2343 | ||
| 1987 | LOG_ERROR(Core_ARM11, "MCRR executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u", | 2344 | cpu->Reg[dest_index] = value; |
| 1988 | inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2); | 2345 | } |
| 2346 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2347 | INC_PC(sizeof(ldst_inst)); | ||
| 2348 | FETCH_INST; | ||
| 2349 | GOTO_NEXT_INST; | ||
| 2350 | } | ||
| 2351 | MCR_INST : { | ||
| 2352 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2353 | mcr_inst* inst_cream = (mcr_inst*)inst_base->component; | ||
| 2354 | |||
| 2355 | unsigned int inst = inst_cream->inst; | ||
| 2356 | if (inst_cream->Rd == 15) { | ||
| 2357 | DEBUG_MSG; | ||
| 2358 | } else { | ||
| 2359 | if (inst_cream->cp_num == 15) | ||
| 2360 | cpu->WriteCP15Register(RD, CRn, OPCODE_1, CRm, OPCODE_2); | ||
| 1989 | } | 2361 | } |
| 2362 | } | ||
| 2363 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2364 | INC_PC(sizeof(mcr_inst)); | ||
| 2365 | FETCH_INST; | ||
| 2366 | GOTO_NEXT_INST; | ||
| 2367 | } | ||
| 2368 | |||
| 2369 | MCRR_INST : { | ||
| 2370 | // Stubbed, as the MPCore doesn't have any registers that are accessible | ||
| 2371 | // through this instruction. | ||
| 2372 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2373 | mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component; | ||
| 1990 | 2374 | ||
| 1991 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2375 | LOG_ERROR(Core_ARM11, "MCRR executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u", |
| 1992 | INC_PC(sizeof(mcrr_inst)); | 2376 | inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, |
| 1993 | FETCH_INST; | 2377 | inst_cream->rt2); |
| 1994 | GOTO_NEXT_INST; | ||
| 1995 | } | 2378 | } |
| 1996 | 2379 | ||
| 1997 | MLA_INST: | 2380 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1998 | { | 2381 | INC_PC(sizeof(mcrr_inst)); |
| 1999 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2382 | FETCH_INST; |
| 2000 | mla_inst* inst_cream = (mla_inst*)inst_base->component; | 2383 | GOTO_NEXT_INST; |
| 2384 | } | ||
| 2001 | 2385 | ||
| 2002 | u64 rm = RM; | 2386 | MLA_INST : { |
| 2003 | u64 rs = RS; | 2387 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 2004 | u64 rn = RN; | 2388 | mla_inst* inst_cream = (mla_inst*)inst_base->component; |
| 2005 | 2389 | ||
| 2006 | RD = static_cast<u32>((rm * rs + rn) & 0xffffffff); | 2390 | u64 rm = RM; |
| 2007 | if (inst_cream->S) { | 2391 | u64 rs = RS; |
| 2008 | UPDATE_NFLAG(RD); | 2392 | u64 rn = RN; |
| 2009 | UPDATE_ZFLAG(RD); | 2393 | |
| 2010 | } | 2394 | RD = static_cast<u32>((rm * rs + rn) & 0xffffffff); |
| 2395 | if (inst_cream->S) { | ||
| 2396 | UPDATE_NFLAG(RD); | ||
| 2397 | UPDATE_ZFLAG(RD); | ||
| 2011 | } | 2398 | } |
| 2012 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2399 | } |
| 2013 | INC_PC(sizeof(mla_inst)); | 2400 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 2014 | FETCH_INST; | 2401 | INC_PC(sizeof(mla_inst)); |
| 2015 | GOTO_NEXT_INST; | 2402 | FETCH_INST; |
| 2016 | } | 2403 | GOTO_NEXT_INST; |
| 2017 | MOV_INST: | 2404 | } |
| 2018 | { | 2405 | MOV_INST : { |
| 2019 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2406 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 2020 | mov_inst* inst_cream = (mov_inst*)inst_base->component; | 2407 | mov_inst* inst_cream = (mov_inst*)inst_base->component; |
| 2021 | 2408 | ||
| 2022 | RD = SHIFTER_OPERAND; | 2409 | RD = SHIFTER_OPERAND; |
| 2023 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 2410 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 2024 | if (CurrentModeHasSPSR) { | 2411 | if (CurrentModeHasSPSR) { |
| 2025 | cpu->Cpsr = cpu->Spsr_copy; | 2412 | cpu->Cpsr = cpu->Spsr_copy; |
| 2026 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); | 2413 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); |
| 2027 | LOAD_NZCVT; | 2414 | LOAD_NZCVT; |
| 2028 | } | ||
| 2029 | } else if (inst_cream->S) { | ||
| 2030 | UPDATE_NFLAG(RD); | ||
| 2031 | UPDATE_ZFLAG(RD); | ||
| 2032 | UPDATE_CFLAG_WITH_SC; | ||
| 2033 | } | ||
| 2034 | if (inst_cream->Rd == 15) { | ||
| 2035 | INC_PC(sizeof(mov_inst)); | ||
| 2036 | goto DISPATCH; | ||
| 2037 | } | 2415 | } |
| 2416 | } else if (inst_cream->S) { | ||
| 2417 | UPDATE_NFLAG(RD); | ||
| 2418 | UPDATE_ZFLAG(RD); | ||
| 2419 | UPDATE_CFLAG_WITH_SC; | ||
| 2038 | } | 2420 | } |
| 2039 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2421 | if (inst_cream->Rd == 15) { |
| 2040 | INC_PC(sizeof(mov_inst)); | 2422 | INC_PC(sizeof(mov_inst)); |
| 2041 | FETCH_INST; | 2423 | goto DISPATCH; |
| 2042 | GOTO_NEXT_INST; | ||
| 2043 | } | ||
| 2044 | MRC_INST: | ||
| 2045 | { | ||
| 2046 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2047 | mrc_inst* inst_cream = (mrc_inst*)inst_base->component; | ||
| 2048 | |||
| 2049 | if (inst_cream->cp_num == 15) { | ||
| 2050 | const uint32_t value = cpu->ReadCP15Register(CRn, OPCODE_1, CRm, OPCODE_2); | ||
| 2051 | |||
| 2052 | if (inst_cream->Rd == 15) { | ||
| 2053 | cpu->Cpsr = (cpu->Cpsr & ~0xF0000000) | (value & 0xF0000000); | ||
| 2054 | LOAD_NZCVT; | ||
| 2055 | } else { | ||
| 2056 | RD = value; | ||
| 2057 | } | ||
| 2058 | } | ||
| 2059 | } | 2424 | } |
| 2060 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2061 | INC_PC(sizeof(mrc_inst)); | ||
| 2062 | FETCH_INST; | ||
| 2063 | GOTO_NEXT_INST; | ||
| 2064 | } | 2425 | } |
| 2426 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2427 | INC_PC(sizeof(mov_inst)); | ||
| 2428 | FETCH_INST; | ||
| 2429 | GOTO_NEXT_INST; | ||
| 2430 | } | ||
| 2431 | MRC_INST : { | ||
| 2432 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2433 | mrc_inst* inst_cream = (mrc_inst*)inst_base->component; | ||
| 2065 | 2434 | ||
| 2066 | MRRC_INST: | 2435 | if (inst_cream->cp_num == 15) { |
| 2067 | { | 2436 | const uint32_t value = cpu->ReadCP15Register(CRn, OPCODE_1, CRm, OPCODE_2); |
| 2068 | // Stubbed, as the MPCore doesn't have any registers that are accessible | ||
| 2069 | // through this instruction. | ||
| 2070 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2071 | mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component; | ||
| 2072 | 2437 | ||
| 2073 | LOG_ERROR(Core_ARM11, "MRRC executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u", | 2438 | if (inst_cream->Rd == 15) { |
| 2074 | inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2); | 2439 | cpu->Cpsr = (cpu->Cpsr & ~0xF0000000) | (value & 0xF0000000); |
| 2440 | LOAD_NZCVT; | ||
| 2441 | } else { | ||
| 2442 | RD = value; | ||
| 2443 | } | ||
| 2075 | } | 2444 | } |
| 2445 | } | ||
| 2446 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2447 | INC_PC(sizeof(mrc_inst)); | ||
| 2448 | FETCH_INST; | ||
| 2449 | GOTO_NEXT_INST; | ||
| 2450 | } | ||
| 2451 | |||
| 2452 | MRRC_INST : { | ||
| 2453 | // Stubbed, as the MPCore doesn't have any registers that are accessible | ||
| 2454 | // through this instruction. | ||
| 2455 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2456 | mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component; | ||
| 2076 | 2457 | ||
| 2077 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2458 | LOG_ERROR(Core_ARM11, "MRRC executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u", |
| 2078 | INC_PC(sizeof(mcrr_inst)); | 2459 | inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, |
| 2079 | FETCH_INST; | 2460 | inst_cream->rt2); |
| 2080 | GOTO_NEXT_INST; | ||
| 2081 | } | 2461 | } |
| 2082 | 2462 | ||
| 2083 | MRS_INST: | 2463 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 2084 | { | 2464 | INC_PC(sizeof(mcrr_inst)); |
| 2085 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2465 | FETCH_INST; |
| 2086 | mrs_inst* inst_cream = (mrs_inst*)inst_base->component; | 2466 | GOTO_NEXT_INST; |
| 2467 | } | ||
| 2468 | |||
| 2469 | MRS_INST : { | ||
| 2470 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2471 | mrs_inst* inst_cream = (mrs_inst*)inst_base->component; | ||
| 2087 | 2472 | ||
| 2088 | if (inst_cream->R) { | 2473 | if (inst_cream->R) { |
| 2089 | RD = cpu->Spsr_copy; | 2474 | RD = cpu->Spsr_copy; |
| 2090 | } else { | 2475 | } else { |
| 2091 | SAVE_NZCVT; | 2476 | SAVE_NZCVT; |
| 2092 | RD = cpu->Cpsr; | 2477 | RD = cpu->Cpsr; |
| 2093 | } | ||
| 2094 | } | 2478 | } |
| 2095 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2479 | } |
| 2096 | INC_PC(sizeof(mrs_inst)); | 2480 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 2097 | FETCH_INST; | 2481 | INC_PC(sizeof(mrs_inst)); |
| 2098 | GOTO_NEXT_INST; | 2482 | FETCH_INST; |
| 2099 | } | 2483 | GOTO_NEXT_INST; |
| 2100 | MSR_INST: | 2484 | } |
| 2101 | { | 2485 | MSR_INST : { |
| 2102 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2486 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 2103 | msr_inst* inst_cream = (msr_inst*)inst_base->component; | 2487 | msr_inst* inst_cream = (msr_inst*)inst_base->component; |
| 2104 | const u32 UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020; | 2488 | const u32 UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020; |
| 2105 | unsigned int inst = inst_cream->inst; | 2489 | unsigned int inst = inst_cream->inst; |
| 2106 | unsigned int operand; | 2490 | unsigned int operand; |
| 2107 | 2491 | ||
| 2108 | if (BIT(inst, 25)) { | 2492 | if (BIT(inst, 25)) { |
| 2109 | int rot_imm = BITS(inst, 8, 11) * 2; | 2493 | int rot_imm = BITS(inst, 8, 11) * 2; |
| 2110 | operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm); | 2494 | operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm); |
| 2495 | } else { | ||
| 2496 | operand = cpu->Reg[BITS(inst, 0, 3)]; | ||
| 2497 | } | ||
| 2498 | u32 byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0) | | ||
| 2499 | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0); | ||
| 2500 | u32 mask = 0; | ||
| 2501 | if (!inst_cream->R) { | ||
| 2502 | if (cpu->InAPrivilegedMode()) { | ||
| 2503 | if ((operand & StateMask) != 0) { | ||
| 2504 | /// UNPREDICTABLE | ||
| 2505 | DEBUG_MSG; | ||
| 2506 | } else | ||
| 2507 | mask = byte_mask & (UserMask | PrivMask); | ||
| 2111 | } else { | 2508 | } else { |
| 2112 | operand = cpu->Reg[BITS(inst, 0, 3)]; | 2509 | mask = byte_mask & UserMask; |
| 2113 | } | 2510 | } |
| 2114 | u32 byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0) | 2511 | SAVE_NZCVT; |
| 2115 | | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0); | ||
| 2116 | u32 mask = 0; | ||
| 2117 | if (!inst_cream->R) { | ||
| 2118 | if (cpu->InAPrivilegedMode()) { | ||
| 2119 | if ((operand & StateMask) != 0) { | ||
| 2120 | /// UNPREDICTABLE | ||
| 2121 | DEBUG_MSG; | ||
| 2122 | } else | ||
| 2123 | mask = byte_mask & (UserMask | PrivMask); | ||
| 2124 | } else { | ||
| 2125 | mask = byte_mask & UserMask; | ||
| 2126 | } | ||
| 2127 | SAVE_NZCVT; | ||
| 2128 | 2512 | ||
| 2129 | cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask); | 2513 | cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask); |
| 2130 | cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); | 2514 | cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); |
| 2131 | LOAD_NZCVT; | 2515 | LOAD_NZCVT; |
| 2132 | } else { | 2516 | } else { |
| 2133 | if (CurrentModeHasSPSR) { | 2517 | if (CurrentModeHasSPSR) { |
| 2134 | mask = byte_mask & (UserMask | PrivMask | StateMask); | 2518 | mask = byte_mask & (UserMask | PrivMask | StateMask); |
| 2135 | cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask); | 2519 | cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask); |
| 2136 | } | ||
| 2137 | } | 2520 | } |
| 2138 | } | 2521 | } |
| 2139 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2522 | } |
| 2140 | INC_PC(sizeof(msr_inst)); | 2523 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 2141 | FETCH_INST; | 2524 | INC_PC(sizeof(msr_inst)); |
| 2142 | GOTO_NEXT_INST; | 2525 | FETCH_INST; |
| 2143 | } | 2526 | GOTO_NEXT_INST; |
| 2144 | MUL_INST: | 2527 | } |
| 2145 | { | 2528 | MUL_INST : { |
| 2146 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2529 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 2147 | mul_inst* inst_cream = (mul_inst*)inst_base->component; | 2530 | mul_inst* inst_cream = (mul_inst*)inst_base->component; |
| 2148 | 2531 | ||
| 2149 | u64 rm = RM; | 2532 | u64 rm = RM; |
| 2150 | u64 rs = RS; | 2533 | u64 rs = RS; |
| 2151 | RD = static_cast<u32>((rm * rs) & 0xffffffff); | 2534 | RD = static_cast<u32>((rm * rs) & 0xffffffff); |
| 2152 | if (inst_cream->S) { | 2535 | if (inst_cream->S) { |
| 2153 | UPDATE_NFLAG(RD); | 2536 | UPDATE_NFLAG(RD); |
| 2154 | UPDATE_ZFLAG(RD); | 2537 | UPDATE_ZFLAG(RD); |
| 2155 | } | ||
| 2156 | } | 2538 | } |
| 2157 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2539 | } |
| 2158 | INC_PC(sizeof(mul_inst)); | 2540 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 2159 | FETCH_INST; | 2541 | INC_PC(sizeof(mul_inst)); |
| 2160 | GOTO_NEXT_INST; | 2542 | FETCH_INST; |
| 2161 | } | 2543 | GOTO_NEXT_INST; |
| 2162 | MVN_INST: | 2544 | } |
| 2163 | { | 2545 | MVN_INST : { |
| 2164 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2546 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 2165 | mvn_inst* const inst_cream = (mvn_inst*)inst_base->component; | 2547 | mvn_inst* const inst_cream = (mvn_inst*)inst_base->component; |
| 2166 | 2548 | ||
| 2167 | RD = ~SHIFTER_OPERAND; | 2549 | RD = ~SHIFTER_OPERAND; |
| 2168 | 2550 | ||
| 2169 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 2551 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 2170 | if (CurrentModeHasSPSR) { | 2552 | if (CurrentModeHasSPSR) { |
| 2171 | cpu->Cpsr = cpu->Spsr_copy; | 2553 | cpu->Cpsr = cpu->Spsr_copy; |
| 2172 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); | 2554 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); |
| 2173 | LOAD_NZCVT; | 2555 | LOAD_NZCVT; |
| 2174 | } | ||
| 2175 | } else if (inst_cream->S) { | ||
| 2176 | UPDATE_NFLAG(RD); | ||
| 2177 | UPDATE_ZFLAG(RD); | ||
| 2178 | UPDATE_CFLAG_WITH_SC; | ||
| 2179 | } | ||
| 2180 | if (inst_cream->Rd == 15) { | ||
| 2181 | INC_PC(sizeof(mvn_inst)); | ||
| 2182 | goto DISPATCH; | ||
| 2183 | } | 2556 | } |
| 2557 | } else if (inst_cream->S) { | ||
| 2558 | UPDATE_NFLAG(RD); | ||
| 2559 | UPDATE_ZFLAG(RD); | ||
| 2560 | UPDATE_CFLAG_WITH_SC; | ||
| 2561 | } | ||
| 2562 | if (inst_cream->Rd == 15) { | ||
| 2563 | INC_PC(sizeof(mvn_inst)); | ||
| 2564 | goto DISPATCH; | ||
| 2184 | } | 2565 | } |
| 2185 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2186 | INC_PC(sizeof(mvn_inst)); | ||
| 2187 | FETCH_INST; | ||
| 2188 | GOTO_NEXT_INST; | ||
| 2189 | } | 2566 | } |
| 2190 | ORR_INST: | 2567 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 2191 | { | 2568 | INC_PC(sizeof(mvn_inst)); |
| 2192 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2569 | FETCH_INST; |
| 2193 | orr_inst* const inst_cream = (orr_inst*)inst_base->component; | 2570 | GOTO_NEXT_INST; |
| 2571 | } | ||
| 2572 | ORR_INST : { | ||
| 2573 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2574 | orr_inst* const inst_cream = (orr_inst*)inst_base->component; | ||
| 2194 | 2575 | ||
| 2195 | u32 lop = RN; | 2576 | u32 lop = RN; |
| 2196 | u32 rop = SHIFTER_OPERAND; | 2577 | u32 rop = SHIFTER_OPERAND; |
| 2197 | 2578 | ||
| 2198 | if (inst_cream->Rn == 15) | 2579 | if (inst_cream->Rn == 15) |
| 2199 | lop += 2 * cpu->GetInstructionSize(); | 2580 | lop += 2 * cpu->GetInstructionSize(); |
| 2200 | 2581 | ||
| 2201 | RD = lop | rop; | 2582 | RD = lop | rop; |
| 2202 | 2583 | ||
| 2203 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 2584 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 2204 | if (CurrentModeHasSPSR) { | 2585 | if (CurrentModeHasSPSR) { |
| 2205 | cpu->Cpsr = cpu->Spsr_copy; | 2586 | cpu->Cpsr = cpu->Spsr_copy; |
| 2206 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); | 2587 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); |
| 2207 | LOAD_NZCVT; | 2588 | LOAD_NZCVT; |
| 2208 | } | ||
| 2209 | } else if (inst_cream->S) { | ||
| 2210 | UPDATE_NFLAG(RD); | ||
| 2211 | UPDATE_ZFLAG(RD); | ||
| 2212 | UPDATE_CFLAG_WITH_SC; | ||
| 2213 | } | ||
| 2214 | if (inst_cream->Rd == 15) { | ||
| 2215 | INC_PC(sizeof(orr_inst)); | ||
| 2216 | goto DISPATCH; | ||
| 2217 | } | 2589 | } |
| 2590 | } else if (inst_cream->S) { | ||
| 2591 | UPDATE_NFLAG(RD); | ||
| 2592 | UPDATE_ZFLAG(RD); | ||
| 2593 | UPDATE_CFLAG_WITH_SC; | ||
| 2594 | } | ||
| 2595 | if (inst_cream->Rd == 15) { | ||
| 2596 | INC_PC(sizeof(orr_inst)); | ||
| 2597 | goto DISPATCH; | ||
| 2218 | } | 2598 | } |
| 2219 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2220 | INC_PC(sizeof(orr_inst)); | ||
| 2221 | FETCH_INST; | ||
| 2222 | GOTO_NEXT_INST; | ||
| 2223 | } | 2599 | } |
| 2600 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2601 | INC_PC(sizeof(orr_inst)); | ||
| 2602 | FETCH_INST; | ||
| 2603 | GOTO_NEXT_INST; | ||
| 2604 | } | ||
| 2605 | |||
| 2606 | NOP_INST : { | ||
| 2607 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2608 | INC_PC_STUB; | ||
| 2609 | FETCH_INST; | ||
| 2610 | GOTO_NEXT_INST; | ||
| 2611 | } | ||
| 2224 | 2612 | ||
| 2225 | NOP_INST: | 2613 | PKHBT_INST : { |
| 2226 | { | 2614 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 2227 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2615 | pkh_inst* inst_cream = (pkh_inst*)inst_base->component; |
| 2228 | INC_PC_STUB; | 2616 | RD = (RN & 0xFFFF) | ((RM << inst_cream->imm) & 0xFFFF0000); |
| 2229 | FETCH_INST; | ||
| 2230 | GOTO_NEXT_INST; | ||
| 2231 | } | 2617 | } |
| 2618 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2619 | INC_PC(sizeof(pkh_inst)); | ||
| 2620 | FETCH_INST; | ||
| 2621 | GOTO_NEXT_INST; | ||
| 2622 | } | ||
| 2232 | 2623 | ||
| 2233 | PKHBT_INST: | 2624 | PKHTB_INST : { |
| 2234 | { | 2625 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 2235 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2626 | pkh_inst* inst_cream = (pkh_inst*)inst_base->component; |
| 2236 | pkh_inst *inst_cream = (pkh_inst *)inst_base->component; | 2627 | int shift_imm = inst_cream->imm ? inst_cream->imm : 31; |
| 2237 | RD = (RN & 0xFFFF) | ((RM << inst_cream->imm) & 0xFFFF0000); | 2628 | RD = ((static_cast<s32>(RM) >> shift_imm) & 0xFFFF) | (RN & 0xFFFF0000); |
| 2238 | } | 2629 | } |
| 2239 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2630 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 2240 | INC_PC(sizeof(pkh_inst)); | 2631 | INC_PC(sizeof(pkh_inst)); |
| 2241 | FETCH_INST; | 2632 | FETCH_INST; |
| 2242 | GOTO_NEXT_INST; | 2633 | GOTO_NEXT_INST; |
| 2243 | } | 2634 | } |
| 2244 | |||
| 2245 | PKHTB_INST: | ||
| 2246 | { | ||
| 2247 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2248 | pkh_inst *inst_cream = (pkh_inst *)inst_base->component; | ||
| 2249 | int shift_imm = inst_cream->imm ? inst_cream->imm : 31; | ||
| 2250 | RD = ((static_cast<s32>(RM) >> shift_imm) & 0xFFFF) | (RN & 0xFFFF0000); | ||
| 2251 | } | ||
| 2252 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2253 | INC_PC(sizeof(pkh_inst)); | ||
| 2254 | FETCH_INST; | ||
| 2255 | GOTO_NEXT_INST; | ||
| 2256 | } | ||
| 2257 | |||
| 2258 | PLD_INST: | ||
| 2259 | { | ||
| 2260 | // Not implemented. PLD is a hint instruction, so it's optional. | ||
| 2261 | |||
| 2262 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2263 | INC_PC(sizeof(pld_inst)); | ||
| 2264 | FETCH_INST; | ||
| 2265 | GOTO_NEXT_INST; | ||
| 2266 | } | ||
| 2267 | |||
| 2268 | QADD_INST: | ||
| 2269 | QDADD_INST: | ||
| 2270 | QDSUB_INST: | ||
| 2271 | QSUB_INST: | ||
| 2272 | { | ||
| 2273 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2274 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 2275 | const u8 op1 = inst_cream->op1; | ||
| 2276 | const u32 rm_val = RM; | ||
| 2277 | const u32 rn_val = RN; | ||
| 2278 | 2635 | ||
| 2279 | u32 result = 0; | 2636 | PLD_INST : { |
| 2637 | // Not implemented. PLD is a hint instruction, so it's optional. | ||
| 2280 | 2638 | ||
| 2281 | // QADD | 2639 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 2282 | if (op1 == 0x00) { | 2640 | INC_PC(sizeof(pld_inst)); |
| 2283 | result = rm_val + rn_val; | 2641 | FETCH_INST; |
| 2642 | GOTO_NEXT_INST; | ||
| 2643 | } | ||
| 2284 | 2644 | ||
| 2285 | if (AddOverflow(rm_val, rn_val, result)) { | 2645 | QADD_INST: |
| 2286 | result = POS(result) ? 0x80000000 : 0x7FFFFFFF; | 2646 | QDADD_INST: |
| 2287 | cpu->Cpsr |= (1 << 27); | 2647 | QDSUB_INST: |
| 2288 | } | 2648 | QSUB_INST : { |
| 2289 | } | 2649 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 2290 | // QSUB | 2650 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; |
| 2291 | else if (op1 == 0x01) { | 2651 | const u8 op1 = inst_cream->op1; |
| 2292 | result = rm_val - rn_val; | 2652 | const u32 rm_val = RM; |
| 2653 | const u32 rn_val = RN; | ||
| 2293 | 2654 | ||
| 2294 | if (SubOverflow(rm_val, rn_val, result)) { | 2655 | u32 result = 0; |
| 2295 | result = POS(result) ? 0x80000000 : 0x7FFFFFFF; | ||
| 2296 | cpu->Cpsr |= (1 << 27); | ||
| 2297 | } | ||
| 2298 | } | ||
| 2299 | // QDADD | ||
| 2300 | else if (op1 == 0x02) { | ||
| 2301 | u32 mul = (rn_val * 2); | ||
| 2302 | 2656 | ||
| 2303 | if (AddOverflow(rn_val, rn_val, rn_val * 2)) { | 2657 | // QADD |
| 2304 | mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF; | 2658 | if (op1 == 0x00) { |
| 2305 | cpu->Cpsr |= (1 << 27); | 2659 | result = rm_val + rn_val; |
| 2306 | } | ||
| 2307 | 2660 | ||
| 2308 | result = mul + rm_val; | 2661 | if (AddOverflow(rm_val, rn_val, result)) { |
| 2662 | result = POS(result) ? 0x80000000 : 0x7FFFFFFF; | ||
| 2663 | cpu->Cpsr |= (1 << 27); | ||
| 2664 | } | ||
| 2665 | } | ||
| 2666 | // QSUB | ||
| 2667 | else if (op1 == 0x01) { | ||
| 2668 | result = rm_val - rn_val; | ||
| 2309 | 2669 | ||
| 2310 | if (AddOverflow(rm_val, mul, result)) { | 2670 | if (SubOverflow(rm_val, rn_val, result)) { |
| 2311 | result = POS(result) ? 0x80000000 : 0x7FFFFFFF; | 2671 | result = POS(result) ? 0x80000000 : 0x7FFFFFFF; |
| 2312 | cpu->Cpsr |= (1 << 27); | 2672 | cpu->Cpsr |= (1 << 27); |
| 2313 | } | ||
| 2314 | } | 2673 | } |
| 2315 | // QDSUB | 2674 | } |
| 2316 | else if (op1 == 0x03) { | 2675 | // QDADD |
| 2317 | u32 mul = (rn_val * 2); | 2676 | else if (op1 == 0x02) { |
| 2677 | u32 mul = (rn_val * 2); | ||
| 2318 | 2678 | ||
| 2319 | if (AddOverflow(rn_val, rn_val, mul)) { | 2679 | if (AddOverflow(rn_val, rn_val, rn_val * 2)) { |
| 2320 | mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF; | 2680 | mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF; |
| 2321 | cpu->Cpsr |= (1 << 27); | 2681 | cpu->Cpsr |= (1 << 27); |
| 2322 | } | 2682 | } |
| 2323 | 2683 | ||
| 2324 | result = rm_val - mul; | 2684 | result = mul + rm_val; |
| 2325 | 2685 | ||
| 2326 | if (SubOverflow(rm_val, mul, result)) { | 2686 | if (AddOverflow(rm_val, mul, result)) { |
| 2327 | result = POS(result) ? 0x80000000 : 0x7FFFFFFF; | 2687 | result = POS(result) ? 0x80000000 : 0x7FFFFFFF; |
| 2328 | cpu->Cpsr |= (1 << 27); | 2688 | cpu->Cpsr |= (1 << 27); |
| 2329 | } | ||
| 2330 | } | 2689 | } |
| 2331 | |||
| 2332 | RD = result; | ||
| 2333 | } | 2690 | } |
| 2691 | // QDSUB | ||
| 2692 | else if (op1 == 0x03) { | ||
| 2693 | u32 mul = (rn_val * 2); | ||
| 2334 | 2694 | ||
| 2335 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2695 | if (AddOverflow(rn_val, rn_val, mul)) { |
| 2336 | INC_PC(sizeof(generic_arm_inst)); | 2696 | mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF; |
| 2337 | FETCH_INST; | 2697 | cpu->Cpsr |= (1 << 27); |
| 2338 | GOTO_NEXT_INST; | ||
| 2339 | } | ||
| 2340 | |||
| 2341 | QADD8_INST: | ||
| 2342 | QADD16_INST: | ||
| 2343 | QADDSUBX_INST: | ||
| 2344 | QSUB8_INST: | ||
| 2345 | QSUB16_INST: | ||
| 2346 | QSUBADDX_INST: | ||
| 2347 | { | ||
| 2348 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2349 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 2350 | const u16 rm_lo = (RM & 0xFFFF); | ||
| 2351 | const u16 rm_hi = ((RM >> 16) & 0xFFFF); | ||
| 2352 | const u16 rn_lo = (RN & 0xFFFF); | ||
| 2353 | const u16 rn_hi = ((RN >> 16) & 0xFFFF); | ||
| 2354 | const u8 op2 = inst_cream->op2; | ||
| 2355 | |||
| 2356 | u16 lo_result = 0; | ||
| 2357 | u16 hi_result = 0; | ||
| 2358 | |||
| 2359 | // QADD16 | ||
| 2360 | if (op2 == 0x00) { | ||
| 2361 | lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo); | ||
| 2362 | hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi); | ||
| 2363 | } | ||
| 2364 | // QASX | ||
| 2365 | else if (op2 == 0x01) { | ||
| 2366 | lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi); | ||
| 2367 | hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo); | ||
| 2368 | } | ||
| 2369 | // QSAX | ||
| 2370 | else if (op2 == 0x02) { | ||
| 2371 | lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi); | ||
| 2372 | hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo); | ||
| 2373 | } | ||
| 2374 | // QSUB16 | ||
| 2375 | else if (op2 == 0x03) { | ||
| 2376 | lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo); | ||
| 2377 | hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_hi); | ||
| 2378 | } | ||
| 2379 | // QADD8 | ||
| 2380 | else if (op2 == 0x04) { | ||
| 2381 | lo_result = ARMul_SignedSaturatedAdd8(rn_lo & 0xFF, rm_lo & 0xFF) | | ||
| 2382 | ARMul_SignedSaturatedAdd8(rn_lo >> 8, rm_lo >> 8) << 8; | ||
| 2383 | hi_result = ARMul_SignedSaturatedAdd8(rn_hi & 0xFF, rm_hi & 0xFF) | | ||
| 2384 | ARMul_SignedSaturatedAdd8(rn_hi >> 8, rm_hi >> 8) << 8; | ||
| 2385 | } | 2698 | } |
| 2386 | // QSUB8 | 2699 | |
| 2387 | else if (op2 == 0x07) { | 2700 | result = rm_val - mul; |
| 2388 | lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) | | 2701 | |
| 2389 | ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8; | 2702 | if (SubOverflow(rm_val, mul, result)) { |
| 2390 | hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) | | 2703 | result = POS(result) ? 0x80000000 : 0x7FFFFFFF; |
| 2391 | ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8; | 2704 | cpu->Cpsr |= (1 << 27); |
| 2392 | } | 2705 | } |
| 2706 | } | ||
| 2393 | 2707 | ||
| 2394 | RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); | 2708 | RD = result; |
| 2709 | } | ||
| 2710 | |||
| 2711 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2712 | INC_PC(sizeof(generic_arm_inst)); | ||
| 2713 | FETCH_INST; | ||
| 2714 | GOTO_NEXT_INST; | ||
| 2715 | } | ||
| 2716 | |||
| 2717 | QADD8_INST: | ||
| 2718 | QADD16_INST: | ||
| 2719 | QADDSUBX_INST: | ||
| 2720 | QSUB8_INST: | ||
| 2721 | QSUB16_INST: | ||
| 2722 | QSUBADDX_INST : { | ||
| 2723 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2724 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 2725 | const u16 rm_lo = (RM & 0xFFFF); | ||
| 2726 | const u16 rm_hi = ((RM >> 16) & 0xFFFF); | ||
| 2727 | const u16 rn_lo = (RN & 0xFFFF); | ||
| 2728 | const u16 rn_hi = ((RN >> 16) & 0xFFFF); | ||
| 2729 | const u8 op2 = inst_cream->op2; | ||
| 2730 | |||
| 2731 | u16 lo_result = 0; | ||
| 2732 | u16 hi_result = 0; | ||
| 2733 | |||
| 2734 | // QADD16 | ||
| 2735 | if (op2 == 0x00) { | ||
| 2736 | lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo); | ||
| 2737 | hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi); | ||
| 2738 | } | ||
| 2739 | // QASX | ||
| 2740 | else if (op2 == 0x01) { | ||
| 2741 | lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi); | ||
| 2742 | hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo); | ||
| 2743 | } | ||
| 2744 | // QSAX | ||
| 2745 | else if (op2 == 0x02) { | ||
| 2746 | lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi); | ||
| 2747 | hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo); | ||
| 2748 | } | ||
| 2749 | // QSUB16 | ||
| 2750 | else if (op2 == 0x03) { | ||
| 2751 | lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo); | ||
| 2752 | hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_hi); | ||
| 2753 | } | ||
| 2754 | // QADD8 | ||
| 2755 | else if (op2 == 0x04) { | ||
| 2756 | lo_result = ARMul_SignedSaturatedAdd8(rn_lo & 0xFF, rm_lo & 0xFF) | | ||
| 2757 | ARMul_SignedSaturatedAdd8(rn_lo >> 8, rm_lo >> 8) << 8; | ||
| 2758 | hi_result = ARMul_SignedSaturatedAdd8(rn_hi & 0xFF, rm_hi & 0xFF) | | ||
| 2759 | ARMul_SignedSaturatedAdd8(rn_hi >> 8, rm_hi >> 8) << 8; | ||
| 2760 | } | ||
| 2761 | // QSUB8 | ||
| 2762 | else if (op2 == 0x07) { | ||
| 2763 | lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) | | ||
| 2764 | ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8; | ||
| 2765 | hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) | | ||
| 2766 | ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8; | ||
| 2395 | } | 2767 | } |
| 2396 | 2768 | ||
| 2397 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2769 | RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); |
| 2398 | INC_PC(sizeof(generic_arm_inst)); | ||
| 2399 | FETCH_INST; | ||
| 2400 | GOTO_NEXT_INST; | ||
| 2401 | } | 2770 | } |
| 2402 | 2771 | ||
| 2403 | REV_INST: | 2772 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 2404 | REV16_INST: | 2773 | INC_PC(sizeof(generic_arm_inst)); |
| 2405 | REVSH_INST: | 2774 | FETCH_INST; |
| 2406 | { | 2775 | GOTO_NEXT_INST; |
| 2776 | } | ||
| 2407 | 2777 | ||
| 2408 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2778 | REV_INST: |
| 2409 | rev_inst* const inst_cream = (rev_inst*)inst_base->component; | 2779 | REV16_INST: |
| 2780 | REVSH_INST : { | ||
| 2410 | 2781 | ||
| 2411 | const u8 op1 = inst_cream->op1; | 2782 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 2412 | const u8 op2 = inst_cream->op2; | 2783 | rev_inst* const inst_cream = (rev_inst*)inst_base->component; |
| 2413 | 2784 | ||
| 2414 | // REV | 2785 | const u8 op1 = inst_cream->op1; |
| 2415 | if (op1 == 0x03 && op2 == 0x01) { | 2786 | const u8 op2 = inst_cream->op2; |
| 2416 | RD = ((RM & 0xFF) << 24) | (((RM >> 8) & 0xFF) << 16) | (((RM >> 16) & 0xFF) << 8) | ((RM >> 24) & 0xFF); | ||
| 2417 | } | ||
| 2418 | // REV16 | ||
| 2419 | else if (op1 == 0x03 && op2 == 0x05) { | ||
| 2420 | RD = ((RM & 0xFF) << 8) | ((RM & 0xFF00) >> 8) | ((RM & 0xFF0000) << 8) | ((RM & 0xFF000000) >> 8); | ||
| 2421 | } | ||
| 2422 | // REVSH | ||
| 2423 | else if (op1 == 0x07 && op2 == 0x05) { | ||
| 2424 | RD = ((RM & 0xFF) << 8) | ((RM & 0xFF00) >> 8); | ||
| 2425 | if (RD & 0x8000) | ||
| 2426 | RD |= 0xffff0000; | ||
| 2427 | } | ||
| 2428 | } | ||
| 2429 | 2787 | ||
| 2430 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2788 | // REV |
| 2431 | INC_PC(sizeof(rev_inst)); | 2789 | if (op1 == 0x03 && op2 == 0x01) { |
| 2432 | FETCH_INST; | 2790 | RD = ((RM & 0xFF) << 24) | (((RM >> 8) & 0xFF) << 16) | (((RM >> 16) & 0xFF) << 8) | |
| 2433 | GOTO_NEXT_INST; | 2791 | ((RM >> 24) & 0xFF); |
| 2792 | } | ||
| 2793 | // REV16 | ||
| 2794 | else if (op1 == 0x03 && op2 == 0x05) { | ||
| 2795 | RD = ((RM & 0xFF) << 8) | ((RM & 0xFF00) >> 8) | ((RM & 0xFF0000) << 8) | | ||
| 2796 | ((RM & 0xFF000000) >> 8); | ||
| 2797 | } | ||
| 2798 | // REVSH | ||
| 2799 | else if (op1 == 0x07 && op2 == 0x05) { | ||
| 2800 | RD = ((RM & 0xFF) << 8) | ((RM & 0xFF00) >> 8); | ||
| 2801 | if (RD & 0x8000) | ||
| 2802 | RD |= 0xffff0000; | ||
| 2803 | } | ||
| 2434 | } | 2804 | } |
| 2435 | 2805 | ||
| 2436 | RFE_INST: | 2806 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 2437 | { | 2807 | INC_PC(sizeof(rev_inst)); |
| 2438 | // RFE is unconditional | 2808 | FETCH_INST; |
| 2439 | ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; | 2809 | GOTO_NEXT_INST; |
| 2810 | } | ||
| 2440 | 2811 | ||
| 2441 | u32 address = 0; | 2812 | RFE_INST : { |
| 2442 | inst_cream->get_addr(cpu, inst_cream->inst, address); | 2813 | // RFE is unconditional |
| 2814 | ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; | ||
| 2443 | 2815 | ||
| 2444 | cpu->Cpsr = cpu->ReadMemory32(address); | 2816 | u32 address = 0; |
| 2445 | cpu->Reg[15] = cpu->ReadMemory32(address + 4); | 2817 | inst_cream->get_addr(cpu, inst_cream->inst, address); |
| 2446 | 2818 | ||
| 2447 | INC_PC(sizeof(ldst_inst)); | 2819 | cpu->Cpsr = cpu->ReadMemory32(address); |
| 2448 | goto DISPATCH; | 2820 | cpu->Reg[15] = cpu->ReadMemory32(address + 4); |
| 2449 | } | ||
| 2450 | 2821 | ||
| 2451 | RSB_INST: | 2822 | INC_PC(sizeof(ldst_inst)); |
| 2452 | { | 2823 | goto DISPATCH; |
| 2453 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2824 | } |
| 2454 | rsb_inst* const inst_cream = (rsb_inst*)inst_base->component; | ||
| 2455 | 2825 | ||
| 2456 | u32 rn_val = RN; | 2826 | RSB_INST : { |
| 2457 | if (inst_cream->Rn == 15) | 2827 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 2458 | rn_val += 2 * cpu->GetInstructionSize(); | 2828 | rsb_inst* const inst_cream = (rsb_inst*)inst_base->component; |
| 2459 | 2829 | ||
| 2460 | bool carry; | 2830 | u32 rn_val = RN; |
| 2461 | bool overflow; | 2831 | if (inst_cream->Rn == 15) |
| 2462 | RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, 1, &carry, &overflow); | 2832 | rn_val += 2 * cpu->GetInstructionSize(); |
| 2463 | 2833 | ||
| 2464 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 2834 | bool carry; |
| 2465 | if (CurrentModeHasSPSR) { | 2835 | bool overflow; |
| 2466 | cpu->Cpsr = cpu->Spsr_copy; | 2836 | RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, 1, &carry, &overflow); |
| 2467 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); | 2837 | |
| 2468 | LOAD_NZCVT; | 2838 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 2469 | } | 2839 | if (CurrentModeHasSPSR) { |
| 2470 | } else if (inst_cream->S) { | 2840 | cpu->Cpsr = cpu->Spsr_copy; |
| 2471 | UPDATE_NFLAG(RD); | 2841 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); |
| 2472 | UPDATE_ZFLAG(RD); | 2842 | LOAD_NZCVT; |
| 2473 | cpu->CFlag = carry; | ||
| 2474 | cpu->VFlag = overflow; | ||
| 2475 | } | 2843 | } |
| 2476 | if (inst_cream->Rd == 15) { | 2844 | } else if (inst_cream->S) { |
| 2477 | INC_PC(sizeof(rsb_inst)); | 2845 | UPDATE_NFLAG(RD); |
| 2478 | goto DISPATCH; | 2846 | UPDATE_ZFLAG(RD); |
| 2847 | cpu->CFlag = carry; | ||
| 2848 | cpu->VFlag = overflow; | ||
| 2849 | } | ||
| 2850 | if (inst_cream->Rd == 15) { | ||
| 2851 | INC_PC(sizeof(rsb_inst)); | ||
| 2852 | goto DISPATCH; | ||
| 2853 | } | ||
| 2854 | } | ||
| 2855 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2856 | INC_PC(sizeof(rsb_inst)); | ||
| 2857 | FETCH_INST; | ||
| 2858 | GOTO_NEXT_INST; | ||
| 2859 | } | ||
| 2860 | RSC_INST : { | ||
| 2861 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2862 | rsc_inst* const inst_cream = (rsc_inst*)inst_base->component; | ||
| 2863 | |||
| 2864 | u32 rn_val = RN; | ||
| 2865 | if (inst_cream->Rn == 15) | ||
| 2866 | rn_val += 2 * cpu->GetInstructionSize(); | ||
| 2867 | |||
| 2868 | bool carry; | ||
| 2869 | bool overflow; | ||
| 2870 | RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); | ||
| 2871 | |||
| 2872 | if (inst_cream->S && (inst_cream->Rd == 15)) { | ||
| 2873 | if (CurrentModeHasSPSR) { | ||
| 2874 | cpu->Cpsr = cpu->Spsr_copy; | ||
| 2875 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); | ||
| 2876 | LOAD_NZCVT; | ||
| 2479 | } | 2877 | } |
| 2878 | } else if (inst_cream->S) { | ||
| 2879 | UPDATE_NFLAG(RD); | ||
| 2880 | UPDATE_ZFLAG(RD); | ||
| 2881 | cpu->CFlag = carry; | ||
| 2882 | cpu->VFlag = overflow; | ||
| 2480 | } | 2883 | } |
| 2481 | cpu->Reg[15] += cpu->GetInstructionSize(); | 2884 | if (inst_cream->Rd == 15) { |
| 2482 | INC_PC(sizeof(rsb_inst)); | 2885 | INC_PC(sizeof(rsc_inst)); |
| 2483 | FETCH_INST; | 2886 | goto DISPATCH; |
| 2484 | GOTO_NEXT_INST; | 2887 | } |
| 2485 | } | 2888 | } |
| 2486 | RSC_INST: | 2889 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 2487 | { | 2890 | INC_PC(sizeof(rsc_inst)); |
| 2488 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2891 | FETCH_INST; |
| 2489 | rsc_inst* const inst_cream = (rsc_inst*)inst_base->component; | 2892 | GOTO_NEXT_INST; |
| 2490 | 2893 | } | |
| 2491 | u32 rn_val = RN; | 2894 | |
| 2492 | if (inst_cream->Rn == 15) | 2895 | SADD8_INST: |
| 2493 | rn_val += 2 * cpu->GetInstructionSize(); | 2896 | SSUB8_INST: |
| 2494 | 2897 | SADD16_INST: | |
| 2495 | bool carry; | 2898 | SADDSUBX_INST: |
| 2496 | bool overflow; | 2899 | SSUBADDX_INST: |
| 2497 | RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); | 2900 | SSUB16_INST : { |
| 2498 | 2901 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | |
| 2499 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 2902 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; |
| 2500 | if (CurrentModeHasSPSR) { | 2903 | const u8 op2 = inst_cream->op2; |
| 2501 | cpu->Cpsr = cpu->Spsr_copy; | 2904 | |
| 2502 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); | 2905 | if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) { |
| 2503 | LOAD_NZCVT; | 2906 | const s16 rn_lo = (RN & 0xFFFF); |
| 2504 | } | 2907 | const s16 rn_hi = ((RN >> 16) & 0xFFFF); |
| 2505 | } else if (inst_cream->S) { | 2908 | const s16 rm_lo = (RM & 0xFFFF); |
| 2506 | UPDATE_NFLAG(RD); | 2909 | const s16 rm_hi = ((RM >> 16) & 0xFFFF); |
| 2507 | UPDATE_ZFLAG(RD); | 2910 | |
| 2508 | cpu->CFlag = carry; | 2911 | s32 lo_result = 0; |
| 2509 | cpu->VFlag = overflow; | 2912 | s32 hi_result = 0; |
| 2913 | |||
| 2914 | // SADD16 | ||
| 2915 | if (inst_cream->op2 == 0x00) { | ||
| 2916 | lo_result = (rn_lo + rm_lo); | ||
| 2917 | hi_result = (rn_hi + rm_hi); | ||
| 2510 | } | 2918 | } |
| 2511 | if (inst_cream->Rd == 15) { | 2919 | // SASX |
| 2512 | INC_PC(sizeof(rsc_inst)); | 2920 | else if (op2 == 0x01) { |
| 2513 | goto DISPATCH; | 2921 | lo_result = (rn_lo - rm_hi); |
| 2922 | hi_result = (rn_hi + rm_lo); | ||
| 2923 | } | ||
| 2924 | // SSAX | ||
| 2925 | else if (op2 == 0x02) { | ||
| 2926 | lo_result = (rn_lo + rm_hi); | ||
| 2927 | hi_result = (rn_hi - rm_lo); | ||
| 2928 | } | ||
| 2929 | // SSUB16 | ||
| 2930 | else if (op2 == 0x03) { | ||
| 2931 | lo_result = (rn_lo - rm_lo); | ||
| 2932 | hi_result = (rn_hi - rm_hi); | ||
| 2514 | } | 2933 | } |
| 2515 | } | ||
| 2516 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2517 | INC_PC(sizeof(rsc_inst)); | ||
| 2518 | FETCH_INST; | ||
| 2519 | GOTO_NEXT_INST; | ||
| 2520 | } | ||
| 2521 | |||
| 2522 | SADD8_INST: | ||
| 2523 | SSUB8_INST: | ||
| 2524 | SADD16_INST: | ||
| 2525 | SADDSUBX_INST: | ||
| 2526 | SSUBADDX_INST: | ||
| 2527 | SSUB16_INST: | ||
| 2528 | { | ||
| 2529 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2530 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 2531 | const u8 op2 = inst_cream->op2; | ||
| 2532 | |||
| 2533 | if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) { | ||
| 2534 | const s16 rn_lo = (RN & 0xFFFF); | ||
| 2535 | const s16 rn_hi = ((RN >> 16) & 0xFFFF); | ||
| 2536 | const s16 rm_lo = (RM & 0xFFFF); | ||
| 2537 | const s16 rm_hi = ((RM >> 16) & 0xFFFF); | ||
| 2538 | |||
| 2539 | s32 lo_result = 0; | ||
| 2540 | s32 hi_result = 0; | ||
| 2541 | |||
| 2542 | // SADD16 | ||
| 2543 | if (inst_cream->op2 == 0x00) { | ||
| 2544 | lo_result = (rn_lo + rm_lo); | ||
| 2545 | hi_result = (rn_hi + rm_hi); | ||
| 2546 | } | ||
| 2547 | // SASX | ||
| 2548 | else if (op2 == 0x01) { | ||
| 2549 | lo_result = (rn_lo - rm_hi); | ||
| 2550 | hi_result = (rn_hi + rm_lo); | ||
| 2551 | } | ||
| 2552 | // SSAX | ||
| 2553 | else if (op2 == 0x02) { | ||
| 2554 | lo_result = (rn_lo + rm_hi); | ||
| 2555 | hi_result = (rn_hi - rm_lo); | ||
| 2556 | } | ||
| 2557 | // SSUB16 | ||
| 2558 | else if (op2 == 0x03) { | ||
| 2559 | lo_result = (rn_lo - rm_lo); | ||
| 2560 | hi_result = (rn_hi - rm_hi); | ||
| 2561 | } | ||
| 2562 | 2934 | ||
| 2563 | RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); | 2935 | RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); |
| 2564 | 2936 | ||
| 2565 | if (lo_result >= 0) { | 2937 | if (lo_result >= 0) { |
| 2566 | cpu->Cpsr |= (1 << 16); | 2938 | cpu->Cpsr |= (1 << 16); |
| 2567 | cpu->Cpsr |= (1 << 17); | 2939 | cpu->Cpsr |= (1 << 17); |
| 2568 | } else { | 2940 | } else { |
| 2569 | cpu->Cpsr &= ~(1 << 16); | 2941 | cpu->Cpsr &= ~(1 << 16); |
| 2570 | cpu->Cpsr &= ~(1 << 17); | 2942 | cpu->Cpsr &= ~(1 << 17); |
| 2571 | } | 2943 | } |
| 2572 | 2944 | ||
| 2573 | if (hi_result >= 0) { | 2945 | if (hi_result >= 0) { |
| 2574 | cpu->Cpsr |= (1 << 18); | 2946 | cpu->Cpsr |= (1 << 18); |
| 2575 | cpu->Cpsr |= (1 << 19); | 2947 | cpu->Cpsr |= (1 << 19); |
| 2576 | } else { | 2948 | } else { |
| 2577 | cpu->Cpsr &= ~(1 << 18); | 2949 | cpu->Cpsr &= ~(1 << 18); |
| 2578 | cpu->Cpsr &= ~(1 << 19); | 2950 | cpu->Cpsr &= ~(1 << 19); |
| 2579 | } | 2951 | } |
| 2952 | } else if (op2 == 0x04 || op2 == 0x07) { | ||
| 2953 | s32 lo_val1, lo_val2; | ||
| 2954 | s32 hi_val1, hi_val2; | ||
| 2955 | |||
| 2956 | // SADD8 | ||
| 2957 | if (op2 == 0x04) { | ||
| 2958 | lo_val1 = (s32)(s8)(RN & 0xFF) + (s32)(s8)(RM & 0xFF); | ||
| 2959 | lo_val2 = (s32)(s8)((RN >> 8) & 0xFF) + (s32)(s8)((RM >> 8) & 0xFF); | ||
| 2960 | hi_val1 = (s32)(s8)((RN >> 16) & 0xFF) + (s32)(s8)((RM >> 16) & 0xFF); | ||
| 2961 | hi_val2 = (s32)(s8)((RN >> 24) & 0xFF) + (s32)(s8)((RM >> 24) & 0xFF); | ||
| 2962 | } | ||
| 2963 | // SSUB8 | ||
| 2964 | else { | ||
| 2965 | lo_val1 = (s32)(s8)(RN & 0xFF) - (s32)(s8)(RM & 0xFF); | ||
| 2966 | lo_val2 = (s32)(s8)((RN >> 8) & 0xFF) - (s32)(s8)((RM >> 8) & 0xFF); | ||
| 2967 | hi_val1 = (s32)(s8)((RN >> 16) & 0xFF) - (s32)(s8)((RM >> 16) & 0xFF); | ||
| 2968 | hi_val2 = (s32)(s8)((RN >> 24) & 0xFF) - (s32)(s8)((RM >> 24) & 0xFF); | ||
| 2580 | } | 2969 | } |
| 2581 | else if (op2 == 0x04 || op2 == 0x07) { | ||
| 2582 | s32 lo_val1, lo_val2; | ||
| 2583 | s32 hi_val1, hi_val2; | ||
| 2584 | |||
| 2585 | // SADD8 | ||
| 2586 | if (op2 == 0x04) { | ||
| 2587 | lo_val1 = (s32)(s8)(RN & 0xFF) + (s32)(s8)(RM & 0xFF); | ||
| 2588 | lo_val2 = (s32)(s8)((RN >> 8) & 0xFF) + (s32)(s8)((RM >> 8) & 0xFF); | ||
| 2589 | hi_val1 = (s32)(s8)((RN >> 16) & 0xFF) + (s32)(s8)((RM >> 16) & 0xFF); | ||
| 2590 | hi_val2 = (s32)(s8)((RN >> 24) & 0xFF) + (s32)(s8)((RM >> 24) & 0xFF); | ||
| 2591 | } | ||
| 2592 | // SSUB8 | ||
| 2593 | else { | ||
| 2594 | lo_val1 = (s32)(s8)(RN & 0xFF) - (s32)(s8)(RM & 0xFF); | ||
| 2595 | lo_val2 = (s32)(s8)((RN >> 8) & 0xFF) - (s32)(s8)((RM >> 8) & 0xFF); | ||
| 2596 | hi_val1 = (s32)(s8)((RN >> 16) & 0xFF) - (s32)(s8)((RM >> 16) & 0xFF); | ||
| 2597 | hi_val2 = (s32)(s8)((RN >> 24) & 0xFF) - (s32)(s8)((RM >> 24) & 0xFF); | ||
| 2598 | } | ||
| 2599 | 2970 | ||
| 2600 | RD = ((lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) | ((hi_val2 & 0xFF) << 24)); | 2971 | RD = ((lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) | |
| 2972 | ((hi_val2 & 0xFF) << 24)); | ||
| 2601 | 2973 | ||
| 2602 | if (lo_val1 >= 0) | 2974 | if (lo_val1 >= 0) |
| 2603 | cpu->Cpsr |= (1 << 16); | 2975 | cpu->Cpsr |= (1 << 16); |
| 2604 | else | 2976 | else |
| 2605 | cpu->Cpsr &= ~(1 << 16); | 2977 | cpu->Cpsr &= ~(1 << 16); |
| 2606 | 2978 | ||
| 2607 | if (lo_val2 >= 0) | 2979 | if (lo_val2 >= 0) |
| 2608 | cpu->Cpsr |= (1 << 17); | 2980 | cpu->Cpsr |= (1 << 17); |
| 2609 | else | 2981 | else |
| 2610 | cpu->Cpsr &= ~(1 << 17); | 2982 | cpu->Cpsr &= ~(1 << 17); |
| 2611 | 2983 | ||
| 2612 | if (hi_val1 >= 0) | 2984 | if (hi_val1 >= 0) |
| 2613 | cpu->Cpsr |= (1 << 18); | 2985 | cpu->Cpsr |= (1 << 18); |
| 2614 | else | 2986 | else |
| 2615 | cpu->Cpsr &= ~(1 << 18); | 2987 | cpu->Cpsr &= ~(1 << 18); |
| 2616 | 2988 | ||
| 2617 | if (hi_val2 >= 0) | 2989 | if (hi_val2 >= 0) |
| 2618 | cpu->Cpsr |= (1 << 19); | 2990 | cpu->Cpsr |= (1 << 19); |
| 2619 | else | 2991 | else |
| 2620 | cpu->Cpsr &= ~(1 << 19); | 2992 | cpu->Cpsr &= ~(1 << 19); |
| 2621 | } | ||
| 2622 | } | 2993 | } |
| 2623 | |||
| 2624 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2625 | INC_PC(sizeof(generic_arm_inst)); | ||
| 2626 | FETCH_INST; | ||
| 2627 | GOTO_NEXT_INST; | ||
| 2628 | } | 2994 | } |
| 2629 | 2995 | ||
| 2630 | SBC_INST: | 2996 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 2631 | { | 2997 | INC_PC(sizeof(generic_arm_inst)); |
| 2632 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 2998 | FETCH_INST; |
| 2633 | sbc_inst* const inst_cream = (sbc_inst*)inst_base->component; | 2999 | GOTO_NEXT_INST; |
| 3000 | } | ||
| 2634 | 3001 | ||
| 2635 | u32 rn_val = RN; | 3002 | SBC_INST : { |
| 2636 | if (inst_cream->Rn == 15) | 3003 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 2637 | rn_val += 2 * cpu->GetInstructionSize(); | 3004 | sbc_inst* const inst_cream = (sbc_inst*)inst_base->component; |
| 2638 | 3005 | ||
| 2639 | bool carry; | 3006 | u32 rn_val = RN; |
| 2640 | bool overflow; | 3007 | if (inst_cream->Rn == 15) |
| 2641 | RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); | 3008 | rn_val += 2 * cpu->GetInstructionSize(); |
| 2642 | 3009 | ||
| 2643 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 3010 | bool carry; |
| 2644 | if (CurrentModeHasSPSR) { | 3011 | bool overflow; |
| 2645 | cpu->Cpsr = cpu->Spsr_copy; | 3012 | RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); |
| 2646 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); | 3013 | |
| 2647 | LOAD_NZCVT; | 3014 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 2648 | } | 3015 | if (CurrentModeHasSPSR) { |
| 2649 | } else if (inst_cream->S) { | 3016 | cpu->Cpsr = cpu->Spsr_copy; |
| 2650 | UPDATE_NFLAG(RD); | 3017 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); |
| 2651 | UPDATE_ZFLAG(RD); | 3018 | LOAD_NZCVT; |
| 2652 | cpu->CFlag = carry; | ||
| 2653 | cpu->VFlag = overflow; | ||
| 2654 | } | ||
| 2655 | if (inst_cream->Rd == 15) { | ||
| 2656 | INC_PC(sizeof(sbc_inst)); | ||
| 2657 | goto DISPATCH; | ||
| 2658 | } | 3019 | } |
| 3020 | } else if (inst_cream->S) { | ||
| 3021 | UPDATE_NFLAG(RD); | ||
| 3022 | UPDATE_ZFLAG(RD); | ||
| 3023 | cpu->CFlag = carry; | ||
| 3024 | cpu->VFlag = overflow; | ||
| 3025 | } | ||
| 3026 | if (inst_cream->Rd == 15) { | ||
| 3027 | INC_PC(sizeof(sbc_inst)); | ||
| 3028 | goto DISPATCH; | ||
| 2659 | } | 3029 | } |
| 2660 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2661 | INC_PC(sizeof(sbc_inst)); | ||
| 2662 | FETCH_INST; | ||
| 2663 | GOTO_NEXT_INST; | ||
| 2664 | } | 3030 | } |
| 3031 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3032 | INC_PC(sizeof(sbc_inst)); | ||
| 3033 | FETCH_INST; | ||
| 3034 | GOTO_NEXT_INST; | ||
| 3035 | } | ||
| 2665 | 3036 | ||
| 2666 | SEL_INST: | 3037 | SEL_INST : { |
| 2667 | { | 3038 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 2668 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3039 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; |
| 2669 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 2670 | |||
| 2671 | const u32 to = RM; | ||
| 2672 | const u32 from = RN; | ||
| 2673 | const u32 cpsr = cpu->Cpsr; | ||
| 2674 | 3040 | ||
| 2675 | u32 result; | 3041 | const u32 to = RM; |
| 2676 | if (cpsr & (1 << 16)) | 3042 | const u32 from = RN; |
| 2677 | result = from & 0xff; | 3043 | const u32 cpsr = cpu->Cpsr; |
| 2678 | else | ||
| 2679 | result = to & 0xff; | ||
| 2680 | 3044 | ||
| 2681 | if (cpsr & (1 << 17)) | 3045 | u32 result; |
| 2682 | result |= from & 0x0000ff00; | 3046 | if (cpsr & (1 << 16)) |
| 2683 | else | 3047 | result = from & 0xff; |
| 2684 | result |= to & 0x0000ff00; | 3048 | else |
| 3049 | result = to & 0xff; | ||
| 2685 | 3050 | ||
| 2686 | if (cpsr & (1 << 18)) | 3051 | if (cpsr & (1 << 17)) |
| 2687 | result |= from & 0x00ff0000; | 3052 | result |= from & 0x0000ff00; |
| 2688 | else | 3053 | else |
| 2689 | result |= to & 0x00ff0000; | 3054 | result |= to & 0x0000ff00; |
| 2690 | 3055 | ||
| 2691 | if (cpsr & (1 << 19)) | 3056 | if (cpsr & (1 << 18)) |
| 2692 | result |= from & 0xff000000; | 3057 | result |= from & 0x00ff0000; |
| 2693 | else | 3058 | else |
| 2694 | result |= to & 0xff000000; | 3059 | result |= to & 0x00ff0000; |
| 2695 | 3060 | ||
| 2696 | RD = result; | 3061 | if (cpsr & (1 << 19)) |
| 2697 | } | 3062 | result |= from & 0xff000000; |
| 3063 | else | ||
| 3064 | result |= to & 0xff000000; | ||
| 2698 | 3065 | ||
| 2699 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3066 | RD = result; |
| 2700 | INC_PC(sizeof(generic_arm_inst)); | ||
| 2701 | FETCH_INST; | ||
| 2702 | GOTO_NEXT_INST; | ||
| 2703 | } | 3067 | } |
| 2704 | 3068 | ||
| 2705 | SETEND_INST: | 3069 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 2706 | { | 3070 | INC_PC(sizeof(generic_arm_inst)); |
| 2707 | // SETEND is unconditional | 3071 | FETCH_INST; |
| 2708 | setend_inst* const inst_cream = (setend_inst*)inst_base->component; | 3072 | GOTO_NEXT_INST; |
| 2709 | const bool big_endian = (inst_cream->set_bigend == 1); | 3073 | } |
| 2710 | 3074 | ||
| 2711 | if (big_endian) | 3075 | SETEND_INST : { |
| 2712 | cpu->Cpsr |= (1 << 9); | 3076 | // SETEND is unconditional |
| 2713 | else | 3077 | setend_inst* const inst_cream = (setend_inst*)inst_base->component; |
| 2714 | cpu->Cpsr &= ~(1 << 9); | 3078 | const bool big_endian = (inst_cream->set_bigend == 1); |
| 2715 | 3079 | ||
| 2716 | LOG_WARNING(Core_ARM11, "SETEND %s executed", big_endian ? "BE" : "LE"); | 3080 | if (big_endian) |
| 3081 | cpu->Cpsr |= (1 << 9); | ||
| 3082 | else | ||
| 3083 | cpu->Cpsr &= ~(1 << 9); | ||
| 2717 | 3084 | ||
| 2718 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3085 | LOG_WARNING(Core_ARM11, "SETEND %s executed", big_endian ? "BE" : "LE"); |
| 2719 | INC_PC(sizeof(setend_inst)); | ||
| 2720 | FETCH_INST; | ||
| 2721 | GOTO_NEXT_INST; | ||
| 2722 | } | ||
| 2723 | 3086 | ||
| 2724 | SEV_INST: | 3087 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 2725 | { | 3088 | INC_PC(sizeof(setend_inst)); |
| 2726 | // Stubbed, as SEV is a hint instruction. | 3089 | FETCH_INST; |
| 2727 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3090 | GOTO_NEXT_INST; |
| 2728 | LOG_TRACE(Core_ARM11, "SEV executed."); | 3091 | } |
| 2729 | } | ||
| 2730 | 3092 | ||
| 2731 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3093 | SEV_INST : { |
| 2732 | INC_PC_STUB; | 3094 | // Stubbed, as SEV is a hint instruction. |
| 2733 | FETCH_INST; | 3095 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 2734 | GOTO_NEXT_INST; | 3096 | LOG_TRACE(Core_ARM11, "SEV executed."); |
| 2735 | } | 3097 | } |
| 2736 | 3098 | ||
| 2737 | SHADD8_INST: | 3099 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 2738 | SHADD16_INST: | 3100 | INC_PC_STUB; |
| 2739 | SHADDSUBX_INST: | 3101 | FETCH_INST; |
| 2740 | SHSUB8_INST: | 3102 | GOTO_NEXT_INST; |
| 2741 | SHSUB16_INST: | 3103 | } |
| 2742 | SHSUBADDX_INST: | ||
| 2743 | { | ||
| 2744 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2745 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 2746 | 3104 | ||
| 2747 | const u8 op2 = inst_cream->op2; | 3105 | SHADD8_INST: |
| 2748 | const u32 rm_val = RM; | 3106 | SHADD16_INST: |
| 2749 | const u32 rn_val = RN; | 3107 | SHADDSUBX_INST: |
| 3108 | SHSUB8_INST: | ||
| 3109 | SHSUB16_INST: | ||
| 3110 | SHSUBADDX_INST : { | ||
| 3111 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3112 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 2750 | 3113 | ||
| 2751 | if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) { | 3114 | const u8 op2 = inst_cream->op2; |
| 2752 | s32 lo_result = 0; | 3115 | const u32 rm_val = RM; |
| 2753 | s32 hi_result = 0; | 3116 | const u32 rn_val = RN; |
| 2754 | 3117 | ||
| 2755 | // SHADD16 | 3118 | if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) { |
| 2756 | if (op2 == 0x00) { | 3119 | s32 lo_result = 0; |
| 2757 | lo_result = ((s16)(rn_val & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1; | 3120 | s32 hi_result = 0; |
| 2758 | hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1; | ||
| 2759 | } | ||
| 2760 | // SHASX | ||
| 2761 | else if (op2 == 0x01) { | ||
| 2762 | lo_result = ((s16)(rn_val & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1; | ||
| 2763 | hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1; | ||
| 2764 | } | ||
| 2765 | // SHSAX | ||
| 2766 | else if (op2 == 0x02) { | ||
| 2767 | lo_result = ((s16)(rn_val & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1; | ||
| 2768 | hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1; | ||
| 2769 | } | ||
| 2770 | // SHSUB16 | ||
| 2771 | else if (op2 == 0x03) { | ||
| 2772 | lo_result = ((s16)(rn_val & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1; | ||
| 2773 | hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1; | ||
| 2774 | } | ||
| 2775 | 3121 | ||
| 2776 | RD = ((lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16)); | 3122 | // SHADD16 |
| 3123 | if (op2 == 0x00) { | ||
| 3124 | lo_result = ((s16)(rn_val & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1; | ||
| 3125 | hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1; | ||
| 3126 | } | ||
| 3127 | // SHASX | ||
| 3128 | else if (op2 == 0x01) { | ||
| 3129 | lo_result = ((s16)(rn_val & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1; | ||
| 3130 | hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1; | ||
| 3131 | } | ||
| 3132 | // SHSAX | ||
| 3133 | else if (op2 == 0x02) { | ||
| 3134 | lo_result = ((s16)(rn_val & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1; | ||
| 3135 | hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1; | ||
| 3136 | } | ||
| 3137 | // SHSUB16 | ||
| 3138 | else if (op2 == 0x03) { | ||
| 3139 | lo_result = ((s16)(rn_val & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1; | ||
| 3140 | hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1; | ||
| 2777 | } | 3141 | } |
| 2778 | else if (op2 == 0x04 || op2 == 0x07) { | ||
| 2779 | s16 lo_val1, lo_val2; | ||
| 2780 | s16 hi_val1, hi_val2; | ||
| 2781 | 3142 | ||
| 2782 | // SHADD8 | 3143 | RD = ((lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16)); |
| 2783 | if (op2 == 0x04) { | 3144 | } else if (op2 == 0x04 || op2 == 0x07) { |
| 2784 | lo_val1 = ((s8)(rn_val & 0xFF) + (s8)(rm_val & 0xFF)) >> 1; | 3145 | s16 lo_val1, lo_val2; |
| 2785 | lo_val2 = ((s8)((rn_val >> 8) & 0xFF) + (s8)((rm_val >> 8) & 0xFF)) >> 1; | 3146 | s16 hi_val1, hi_val2; |
| 2786 | 3147 | ||
| 2787 | hi_val1 = ((s8)((rn_val >> 16) & 0xFF) + (s8)((rm_val >> 16) & 0xFF)) >> 1; | 3148 | // SHADD8 |
| 2788 | hi_val2 = ((s8)((rn_val >> 24) & 0xFF) + (s8)((rm_val >> 24) & 0xFF)) >> 1; | 3149 | if (op2 == 0x04) { |
| 2789 | } | 3150 | lo_val1 = ((s8)(rn_val & 0xFF) + (s8)(rm_val & 0xFF)) >> 1; |
| 2790 | // SHSUB8 | 3151 | lo_val2 = ((s8)((rn_val >> 8) & 0xFF) + (s8)((rm_val >> 8) & 0xFF)) >> 1; |
| 2791 | else { | ||
| 2792 | lo_val1 = ((s8)(rn_val & 0xFF) - (s8)(rm_val & 0xFF)) >> 1; | ||
| 2793 | lo_val2 = ((s8)((rn_val >> 8) & 0xFF) - (s8)((rm_val >> 8) & 0xFF)) >> 1; | ||
| 2794 | 3152 | ||
| 2795 | hi_val1 = ((s8)((rn_val >> 16) & 0xFF) - (s8)((rm_val >> 16) & 0xFF)) >> 1; | 3153 | hi_val1 = ((s8)((rn_val >> 16) & 0xFF) + (s8)((rm_val >> 16) & 0xFF)) >> 1; |
| 2796 | hi_val2 = ((s8)((rn_val >> 24) & 0xFF) - (s8)((rm_val >> 24) & 0xFF)) >> 1; | 3154 | hi_val2 = ((s8)((rn_val >> 24) & 0xFF) + (s8)((rm_val >> 24) & 0xFF)) >> 1; |
| 2797 | } | ||
| 2798 | |||
| 2799 | RD = (lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) | ((hi_val2 & 0xFF) << 24); | ||
| 2800 | } | 3155 | } |
| 2801 | } | 3156 | // SHSUB8 |
| 2802 | 3157 | else { | |
| 2803 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3158 | lo_val1 = ((s8)(rn_val & 0xFF) - (s8)(rm_val & 0xFF)) >> 1; |
| 2804 | INC_PC(sizeof(generic_arm_inst)); | 3159 | lo_val2 = ((s8)((rn_val >> 8) & 0xFF) - (s8)((rm_val >> 8) & 0xFF)) >> 1; |
| 2805 | FETCH_INST; | ||
| 2806 | GOTO_NEXT_INST; | ||
| 2807 | } | ||
| 2808 | |||
| 2809 | SMLA_INST: | ||
| 2810 | { | ||
| 2811 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2812 | smla_inst* inst_cream = (smla_inst*)inst_base->component; | ||
| 2813 | s32 operand1, operand2; | ||
| 2814 | if (inst_cream->x == 0) | ||
| 2815 | operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15); | ||
| 2816 | else | ||
| 2817 | operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31); | ||
| 2818 | 3160 | ||
| 2819 | if (inst_cream->y == 0) | 3161 | hi_val1 = ((s8)((rn_val >> 16) & 0xFF) - (s8)((rm_val >> 16) & 0xFF)) >> 1; |
| 2820 | operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15); | 3162 | hi_val2 = ((s8)((rn_val >> 24) & 0xFF) - (s8)((rm_val >> 24) & 0xFF)) >> 1; |
| 2821 | else | 3163 | } |
| 2822 | operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31); | ||
| 2823 | 3164 | ||
| 2824 | u32 product = operand1 * operand2; | 3165 | RD = (lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) | |
| 2825 | u32 result = product + RN; | 3166 | ((hi_val2 & 0xFF) << 24); |
| 2826 | if (AddOverflow(product, RN, result)) | ||
| 2827 | cpu->Cpsr |= (1 << 27); | ||
| 2828 | RD = result; | ||
| 2829 | } | 3167 | } |
| 2830 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2831 | INC_PC(sizeof(smla_inst)); | ||
| 2832 | FETCH_INST; | ||
| 2833 | GOTO_NEXT_INST; | ||
| 2834 | } | 3168 | } |
| 2835 | 3169 | ||
| 2836 | SMLAD_INST: | 3170 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 2837 | SMLSD_INST: | 3171 | INC_PC(sizeof(generic_arm_inst)); |
| 2838 | SMUAD_INST: | 3172 | FETCH_INST; |
| 2839 | SMUSD_INST: | 3173 | GOTO_NEXT_INST; |
| 2840 | { | 3174 | } |
| 2841 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 2842 | smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; | ||
| 2843 | const u8 op2 = inst_cream->op2; | ||
| 2844 | 3175 | ||
| 2845 | u32 rm_val = cpu->Reg[inst_cream->Rm]; | 3176 | SMLA_INST : { |
| 2846 | const u32 rn_val = cpu->Reg[inst_cream->Rn]; | 3177 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 3178 | smla_inst* inst_cream = (smla_inst*)inst_base->component; | ||
| 3179 | s32 operand1, operand2; | ||
| 3180 | if (inst_cream->x == 0) | ||
| 3181 | operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15); | ||
| 3182 | else | ||
| 3183 | operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31); | ||
| 2847 | 3184 | ||
| 2848 | if (inst_cream->m) | 3185 | if (inst_cream->y == 0) |
| 2849 | rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16)); | 3186 | operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15); |
| 3187 | else | ||
| 3188 | operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31); | ||
| 3189 | |||
| 3190 | u32 product = operand1 * operand2; | ||
| 3191 | u32 result = product + RN; | ||
| 3192 | if (AddOverflow(product, RN, result)) | ||
| 3193 | cpu->Cpsr |= (1 << 27); | ||
| 3194 | RD = result; | ||
| 3195 | } | ||
| 3196 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3197 | INC_PC(sizeof(smla_inst)); | ||
| 3198 | FETCH_INST; | ||
| 3199 | GOTO_NEXT_INST; | ||
| 3200 | } | ||
| 2850 | 3201 | ||
| 2851 | const s16 rm_lo = (rm_val & 0xFFFF); | 3202 | SMLAD_INST: |
| 2852 | const s16 rm_hi = ((rm_val >> 16) & 0xFFFF); | 3203 | SMLSD_INST: |
| 2853 | const s16 rn_lo = (rn_val & 0xFFFF); | 3204 | SMUAD_INST: |
| 2854 | const s16 rn_hi = ((rn_val >> 16) & 0xFFFF); | 3205 | SMUSD_INST : { |
| 3206 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3207 | smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; | ||
| 3208 | const u8 op2 = inst_cream->op2; | ||
| 2855 | 3209 | ||
| 2856 | const u32 product1 = (rn_lo * rm_lo); | 3210 | u32 rm_val = cpu->Reg[inst_cream->Rm]; |
| 2857 | const u32 product2 = (rn_hi * rm_hi); | 3211 | const u32 rn_val = cpu->Reg[inst_cream->Rn]; |
| 2858 | 3212 | ||
| 2859 | // SMUAD and SMLAD | 3213 | if (inst_cream->m) |
| 2860 | if (BIT(op2, 1) == 0) { | 3214 | rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16)); |
| 2861 | u32 rd_val = (product1 + product2); | ||
| 2862 | 3215 | ||
| 2863 | if (inst_cream->Ra != 15) { | 3216 | const s16 rm_lo = (rm_val & 0xFFFF); |
| 2864 | rd_val += cpu->Reg[inst_cream->Ra]; | 3217 | const s16 rm_hi = ((rm_val >> 16) & 0xFFFF); |
| 3218 | const s16 rn_lo = (rn_val & 0xFFFF); | ||
| 3219 | const s16 rn_hi = ((rn_val >> 16) & 0xFFFF); | ||
| 2865 | 3220 | ||
| 2866 | if (ARMul_AddOverflowQ(product1 + product2, cpu->Reg[inst_cream->Ra])) | 3221 | const u32 product1 = (rn_lo * rm_lo); |
| 2867 | cpu->Cpsr |= (1 << 27); | 3222 | const u32 product2 = (rn_hi * rm_hi); |
| 2868 | } | 3223 | |
| 3224 | // SMUAD and SMLAD | ||
| 3225 | if (BIT(op2, 1) == 0) { | ||
| 3226 | u32 rd_val = (product1 + product2); | ||
| 2869 | 3227 | ||
| 2870 | RD = rd_val; | 3228 | if (inst_cream->Ra != 15) { |
| 3229 | rd_val += cpu->Reg[inst_cream->Ra]; | ||
| 2871 | 3230 | ||
| 2872 | if (ARMul_AddOverflowQ(product1, product2)) | 3231 | if (ARMul_AddOverflowQ(product1 + product2, cpu->Reg[inst_cream->Ra])) |
| 2873 | cpu->Cpsr |= (1 << 27); | 3232 | cpu->Cpsr |= (1 << 27); |
| 2874 | } | 3233 | } |
| 2875 | // SMUSD and SMLSD | ||
| 2876 | else { | ||
| 2877 | u32 rd_val = (product1 - product2); | ||
| 2878 | 3234 | ||
| 2879 | if (inst_cream->Ra != 15) { | 3235 | RD = rd_val; |
| 2880 | rd_val += cpu->Reg[inst_cream->Ra]; | ||
| 2881 | 3236 | ||
| 2882 | if (ARMul_AddOverflowQ(product1 - product2, cpu->Reg[inst_cream->Ra])) | 3237 | if (ARMul_AddOverflowQ(product1, product2)) |
| 2883 | cpu->Cpsr |= (1 << 27); | 3238 | cpu->Cpsr |= (1 << 27); |
| 2884 | } | 3239 | } |
| 3240 | // SMUSD and SMLSD | ||
| 3241 | else { | ||
| 3242 | u32 rd_val = (product1 - product2); | ||
| 3243 | |||
| 3244 | if (inst_cream->Ra != 15) { | ||
| 3245 | rd_val += cpu->Reg[inst_cream->Ra]; | ||
| 2885 | 3246 | ||
| 2886 | RD = rd_val; | 3247 | if (ARMul_AddOverflowQ(product1 - product2, cpu->Reg[inst_cream->Ra])) |
| 3248 | cpu->Cpsr |= (1 << 27); | ||
| 2887 | } | 3249 | } |
| 2888 | } | ||
| 2889 | 3250 | ||
| 2890 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3251 | RD = rd_val; |
| 2891 | INC_PC(sizeof(smlad_inst)); | 3252 | } |
| 2892 | FETCH_INST; | ||
| 2893 | GOTO_NEXT_INST; | ||
| 2894 | } | 3253 | } |
| 2895 | 3254 | ||
| 2896 | SMLAL_INST: | 3255 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 2897 | { | 3256 | INC_PC(sizeof(smlad_inst)); |
| 2898 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3257 | FETCH_INST; |
| 2899 | umlal_inst* inst_cream = (umlal_inst*)inst_base->component; | 3258 | GOTO_NEXT_INST; |
| 2900 | long long int rm = RM; | 3259 | } |
| 2901 | long long int rs = RS; | 3260 | |
| 2902 | if (BIT(rm, 31)) { | 3261 | SMLAL_INST : { |
| 2903 | rm |= 0xffffffff00000000LL; | 3262 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 2904 | } | 3263 | umlal_inst* inst_cream = (umlal_inst*)inst_base->component; |
| 2905 | if (BIT(rs, 31)) { | 3264 | long long int rm = RM; |
| 2906 | rs |= 0xffffffff00000000LL; | 3265 | long long int rs = RS; |
| 2907 | } | 3266 | if (BIT(rm, 31)) { |
| 2908 | long long int rst = rm * rs; | 3267 | rm |= 0xffffffff00000000LL; |
| 2909 | long long int rdhi32 = RDHI; | ||
| 2910 | long long int hilo = (rdhi32 << 32) + RDLO; | ||
| 2911 | rst += hilo; | ||
| 2912 | RDLO = BITS(rst, 0, 31); | ||
| 2913 | RDHI = BITS(rst, 32, 63); | ||
| 2914 | if (inst_cream->S) { | ||
| 2915 | cpu->NFlag = BIT(RDHI, 31); | ||
| 2916 | cpu->ZFlag = (RDHI == 0 && RDLO == 0); | ||
| 2917 | } | ||
| 2918 | } | 3268 | } |
| 2919 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3269 | if (BIT(rs, 31)) { |
| 2920 | INC_PC(sizeof(umlal_inst)); | 3270 | rs |= 0xffffffff00000000LL; |
| 2921 | FETCH_INST; | 3271 | } |
| 2922 | GOTO_NEXT_INST; | 3272 | long long int rst = rm * rs; |
| 2923 | } | 3273 | long long int rdhi32 = RDHI; |
| 2924 | 3274 | long long int hilo = (rdhi32 << 32) + RDLO; | |
| 2925 | SMLALXY_INST: | 3275 | rst += hilo; |
| 2926 | { | 3276 | RDLO = BITS(rst, 0, 31); |
| 2927 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3277 | RDHI = BITS(rst, 32, 63); |
| 2928 | smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component; | 3278 | if (inst_cream->S) { |
| 2929 | 3279 | cpu->NFlag = BIT(RDHI, 31); | |
| 2930 | u64 operand1 = RN; | 3280 | cpu->ZFlag = (RDHI == 0 && RDLO == 0); |
| 2931 | u64 operand2 = RM; | ||
| 2932 | |||
| 2933 | if (inst_cream->x != 0) | ||
| 2934 | operand1 >>= 16; | ||
| 2935 | if (inst_cream->y != 0) | ||
| 2936 | operand2 >>= 16; | ||
| 2937 | operand1 &= 0xFFFF; | ||
| 2938 | if (operand1 & 0x8000) | ||
| 2939 | operand1 -= 65536; | ||
| 2940 | operand2 &= 0xFFFF; | ||
| 2941 | if (operand2 & 0x8000) | ||
| 2942 | operand2 -= 65536; | ||
| 2943 | |||
| 2944 | u64 dest = ((u64)RDHI << 32 | RDLO) + (operand1 * operand2); | ||
| 2945 | RDLO = (dest & 0xFFFFFFFF); | ||
| 2946 | RDHI = ((dest >> 32) & 0xFFFFFFFF); | ||
| 2947 | } | 3281 | } |
| 2948 | |||
| 2949 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 2950 | INC_PC(sizeof(smlalxy_inst)); | ||
| 2951 | FETCH_INST; | ||
| 2952 | GOTO_NEXT_INST; | ||
| 2953 | } | 3282 | } |
| 3283 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3284 | INC_PC(sizeof(umlal_inst)); | ||
| 3285 | FETCH_INST; | ||
| 3286 | GOTO_NEXT_INST; | ||
| 3287 | } | ||
| 2954 | 3288 | ||
| 2955 | SMLAW_INST: | 3289 | SMLALXY_INST : { |
| 2956 | { | 3290 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 2957 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3291 | smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component; |
| 2958 | smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; | 3292 | |
| 3293 | u64 operand1 = RN; | ||
| 3294 | u64 operand2 = RM; | ||
| 3295 | |||
| 3296 | if (inst_cream->x != 0) | ||
| 3297 | operand1 >>= 16; | ||
| 3298 | if (inst_cream->y != 0) | ||
| 3299 | operand2 >>= 16; | ||
| 3300 | operand1 &= 0xFFFF; | ||
| 3301 | if (operand1 & 0x8000) | ||
| 3302 | operand1 -= 65536; | ||
| 3303 | operand2 &= 0xFFFF; | ||
| 3304 | if (operand2 & 0x8000) | ||
| 3305 | operand2 -= 65536; | ||
| 3306 | |||
| 3307 | u64 dest = ((u64)RDHI << 32 | RDLO) + (operand1 * operand2); | ||
| 3308 | RDLO = (dest & 0xFFFFFFFF); | ||
| 3309 | RDHI = ((dest >> 32) & 0xFFFFFFFF); | ||
| 3310 | } | ||
| 3311 | |||
| 3312 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3313 | INC_PC(sizeof(smlalxy_inst)); | ||
| 3314 | FETCH_INST; | ||
| 3315 | GOTO_NEXT_INST; | ||
| 3316 | } | ||
| 2959 | 3317 | ||
| 2960 | const u32 rm_val = RM; | 3318 | SMLAW_INST : { |
| 2961 | const u32 rn_val = RN; | 3319 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 2962 | const u32 ra_val = cpu->Reg[inst_cream->Ra]; | 3320 | smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; |
| 2963 | const bool high = (inst_cream->m == 1); | ||
| 2964 | 3321 | ||
| 2965 | const s16 operand2 = (high) ? ((rm_val >> 16) & 0xFFFF) : (rm_val & 0xFFFF); | 3322 | const u32 rm_val = RM; |
| 2966 | const s64 result = (s64)(s32)rn_val * (s64)(s32)operand2 + ((s64)(s32)ra_val << 16); | 3323 | const u32 rn_val = RN; |
| 3324 | const u32 ra_val = cpu->Reg[inst_cream->Ra]; | ||
| 3325 | const bool high = (inst_cream->m == 1); | ||
| 2967 | 3326 | ||
| 2968 | RD = BITS(result, 16, 47); | 3327 | const s16 operand2 = (high) ? ((rm_val >> 16) & 0xFFFF) : (rm_val & 0xFFFF); |
| 3328 | const s64 result = (s64)(s32)rn_val * (s64)(s32)operand2 + ((s64)(s32)ra_val << 16); | ||
| 2969 | 3329 | ||
| 2970 | if ((result >> 16) != (s32)RD) | 3330 | RD = BITS(result, 16, 47); |
| 2971 | cpu->Cpsr |= (1 << 27); | ||
| 2972 | } | ||
| 2973 | 3331 | ||
| 2974 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3332 | if ((result >> 16) != (s32)RD) |
| 2975 | INC_PC(sizeof(smlad_inst)); | 3333 | cpu->Cpsr |= (1 << 27); |
| 2976 | FETCH_INST; | ||
| 2977 | GOTO_NEXT_INST; | ||
| 2978 | } | 3334 | } |
| 2979 | 3335 | ||
| 2980 | SMLALD_INST: | 3336 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 2981 | SMLSLD_INST: | 3337 | INC_PC(sizeof(smlad_inst)); |
| 2982 | { | 3338 | FETCH_INST; |
| 2983 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3339 | GOTO_NEXT_INST; |
| 2984 | smlald_inst* const inst_cream = (smlald_inst*)inst_base->component; | 3340 | } |
| 2985 | 3341 | ||
| 2986 | const bool do_swap = (inst_cream->swap == 1); | 3342 | SMLALD_INST: |
| 2987 | const u32 rdlo_val = RDLO; | 3343 | SMLSLD_INST : { |
| 2988 | const u32 rdhi_val = RDHI; | 3344 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 2989 | const u32 rn_val = RN; | 3345 | smlald_inst* const inst_cream = (smlald_inst*)inst_base->component; |
| 2990 | u32 rm_val = RM; | ||
| 2991 | 3346 | ||
| 2992 | if (do_swap) | 3347 | const bool do_swap = (inst_cream->swap == 1); |
| 2993 | rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16)); | 3348 | const u32 rdlo_val = RDLO; |
| 3349 | const u32 rdhi_val = RDHI; | ||
| 3350 | const u32 rn_val = RN; | ||
| 3351 | u32 rm_val = RM; | ||
| 2994 | 3352 | ||
| 2995 | const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF); | 3353 | if (do_swap) |
| 2996 | const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF); | 3354 | rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16)); |
| 2997 | s64 result; | ||
| 2998 | 3355 | ||
| 2999 | // SMLALD | 3356 | const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF); |
| 3000 | if (BIT(inst_cream->op2, 1) == 0) { | 3357 | const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF); |
| 3001 | result = (product1 + product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32)); | 3358 | s64 result; |
| 3002 | } | ||
| 3003 | // SMLSLD | ||
| 3004 | else { | ||
| 3005 | result = (product1 - product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32)); | ||
| 3006 | } | ||
| 3007 | 3359 | ||
| 3008 | RDLO = (result & 0xFFFFFFFF); | 3360 | // SMLALD |
| 3009 | RDHI = ((result >> 32) & 0xFFFFFFFF); | 3361 | if (BIT(inst_cream->op2, 1) == 0) { |
| 3362 | result = (product1 + product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32)); | ||
| 3363 | } | ||
| 3364 | // SMLSLD | ||
| 3365 | else { | ||
| 3366 | result = (product1 - product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32)); | ||
| 3010 | } | 3367 | } |
| 3011 | 3368 | ||
| 3012 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3369 | RDLO = (result & 0xFFFFFFFF); |
| 3013 | INC_PC(sizeof(smlald_inst)); | 3370 | RDHI = ((result >> 32) & 0xFFFFFFFF); |
| 3014 | FETCH_INST; | ||
| 3015 | GOTO_NEXT_INST; | ||
| 3016 | } | 3371 | } |
| 3017 | 3372 | ||
| 3018 | SMMLA_INST: | 3373 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 3019 | SMMLS_INST: | 3374 | INC_PC(sizeof(smlald_inst)); |
| 3020 | SMMUL_INST: | 3375 | FETCH_INST; |
| 3021 | { | 3376 | GOTO_NEXT_INST; |
| 3022 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3377 | } |
| 3023 | smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; | ||
| 3024 | |||
| 3025 | const u32 rm_val = RM; | ||
| 3026 | const u32 rn_val = RN; | ||
| 3027 | const bool do_round = (inst_cream->m == 1); | ||
| 3028 | 3378 | ||
| 3029 | // Assume SMMUL by default. | 3379 | SMMLA_INST: |
| 3030 | s64 result = (s64)(s32)rn_val * (s64)(s32)rm_val; | 3380 | SMMLS_INST: |
| 3381 | SMMUL_INST : { | ||
| 3382 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3383 | smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; | ||
| 3031 | 3384 | ||
| 3032 | if (inst_cream->Ra != 15) { | 3385 | const u32 rm_val = RM; |
| 3033 | const u32 ra_val = cpu->Reg[inst_cream->Ra]; | 3386 | const u32 rn_val = RN; |
| 3387 | const bool do_round = (inst_cream->m == 1); | ||
| 3034 | 3388 | ||
| 3035 | // SMMLA, otherwise SMMLS | 3389 | // Assume SMMUL by default. |
| 3036 | if (BIT(inst_cream->op2, 1) == 0) | 3390 | s64 result = (s64)(s32)rn_val * (s64)(s32)rm_val; |
| 3037 | result += ((s64)ra_val << 32); | ||
| 3038 | else | ||
| 3039 | result = ((s64)ra_val << 32) - result; | ||
| 3040 | } | ||
| 3041 | 3391 | ||
| 3042 | if (do_round) | 3392 | if (inst_cream->Ra != 15) { |
| 3043 | result += 0x80000000; | 3393 | const u32 ra_val = cpu->Reg[inst_cream->Ra]; |
| 3044 | 3394 | ||
| 3045 | RD = ((result >> 32) & 0xFFFFFFFF); | 3395 | // SMMLA, otherwise SMMLS |
| 3396 | if (BIT(inst_cream->op2, 1) == 0) | ||
| 3397 | result += ((s64)ra_val << 32); | ||
| 3398 | else | ||
| 3399 | result = ((s64)ra_val << 32) - result; | ||
| 3046 | } | 3400 | } |
| 3047 | 3401 | ||
| 3048 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3402 | if (do_round) |
| 3049 | INC_PC(sizeof(smlad_inst)); | 3403 | result += 0x80000000; |
| 3050 | FETCH_INST; | 3404 | |
| 3051 | GOTO_NEXT_INST; | 3405 | RD = ((result >> 32) & 0xFFFFFFFF); |
| 3052 | } | 3406 | } |
| 3053 | 3407 | ||
| 3054 | SMUL_INST: | 3408 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 3055 | { | 3409 | INC_PC(sizeof(smlad_inst)); |
| 3056 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3410 | FETCH_INST; |
| 3057 | smul_inst* inst_cream = (smul_inst*)inst_base->component; | 3411 | GOTO_NEXT_INST; |
| 3058 | u32 operand1, operand2; | 3412 | } |
| 3059 | if (inst_cream->x == 0) | ||
| 3060 | operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15); | ||
| 3061 | else | ||
| 3062 | operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31); | ||
| 3063 | 3413 | ||
| 3064 | if (inst_cream->y == 0) | 3414 | SMUL_INST : { |
| 3065 | operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15); | 3415 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 3066 | else | 3416 | smul_inst* inst_cream = (smul_inst*)inst_base->component; |
| 3067 | operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31); | 3417 | u32 operand1, operand2; |
| 3068 | RD = operand1 * operand2; | 3418 | if (inst_cream->x == 0) |
| 3419 | operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15); | ||
| 3420 | else | ||
| 3421 | operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31); | ||
| 3422 | |||
| 3423 | if (inst_cream->y == 0) | ||
| 3424 | operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15); | ||
| 3425 | else | ||
| 3426 | operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31); | ||
| 3427 | RD = operand1 * operand2; | ||
| 3428 | } | ||
| 3429 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3430 | INC_PC(sizeof(smul_inst)); | ||
| 3431 | FETCH_INST; | ||
| 3432 | GOTO_NEXT_INST; | ||
| 3433 | } | ||
| 3434 | SMULL_INST : { | ||
| 3435 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3436 | umull_inst* inst_cream = (umull_inst*)inst_base->component; | ||
| 3437 | s64 rm = RM; | ||
| 3438 | s64 rs = RS; | ||
| 3439 | if (BIT(rm, 31)) { | ||
| 3440 | rm |= 0xffffffff00000000LL; | ||
| 3069 | } | 3441 | } |
| 3070 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3442 | if (BIT(rs, 31)) { |
| 3071 | INC_PC(sizeof(smul_inst)); | 3443 | rs |= 0xffffffff00000000LL; |
| 3072 | FETCH_INST; | 3444 | } |
| 3073 | GOTO_NEXT_INST; | 3445 | s64 rst = rm * rs; |
| 3074 | } | 3446 | RDHI = BITS(rst, 32, 63); |
| 3075 | SMULL_INST: | 3447 | RDLO = BITS(rst, 0, 31); |
| 3076 | { | ||
| 3077 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3078 | umull_inst* inst_cream = (umull_inst*)inst_base->component; | ||
| 3079 | s64 rm = RM; | ||
| 3080 | s64 rs = RS; | ||
| 3081 | if (BIT(rm, 31)) { | ||
| 3082 | rm |= 0xffffffff00000000LL; | ||
| 3083 | } | ||
| 3084 | if (BIT(rs, 31)) { | ||
| 3085 | rs |= 0xffffffff00000000LL; | ||
| 3086 | } | ||
| 3087 | s64 rst = rm * rs; | ||
| 3088 | RDHI = BITS(rst, 32, 63); | ||
| 3089 | RDLO = BITS(rst, 0, 31); | ||
| 3090 | 3448 | ||
| 3091 | if (inst_cream->S) { | 3449 | if (inst_cream->S) { |
| 3092 | cpu->NFlag = BIT(RDHI, 31); | 3450 | cpu->NFlag = BIT(RDHI, 31); |
| 3093 | cpu->ZFlag = (RDHI == 0 && RDLO == 0); | 3451 | cpu->ZFlag = (RDHI == 0 && RDLO == 0); |
| 3094 | } | ||
| 3095 | } | 3452 | } |
| 3096 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3097 | INC_PC(sizeof(umull_inst)); | ||
| 3098 | FETCH_INST; | ||
| 3099 | GOTO_NEXT_INST; | ||
| 3100 | } | 3453 | } |
| 3454 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3455 | INC_PC(sizeof(umull_inst)); | ||
| 3456 | FETCH_INST; | ||
| 3457 | GOTO_NEXT_INST; | ||
| 3458 | } | ||
| 3101 | 3459 | ||
| 3102 | SMULW_INST: | 3460 | SMULW_INST : { |
| 3103 | { | 3461 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 3104 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3462 | smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; |
| 3105 | smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; | ||
| 3106 | 3463 | ||
| 3107 | s16 rm = (inst_cream->m == 1) ? ((RM >> 16) & 0xFFFF) : (RM & 0xFFFF); | 3464 | s16 rm = (inst_cream->m == 1) ? ((RM >> 16) & 0xFFFF) : (RM & 0xFFFF); |
| 3108 | 3465 | ||
| 3109 | s64 result = (s64)rm * (s64)(s32)RN; | 3466 | s64 result = (s64)rm * (s64)(s32)RN; |
| 3110 | RD = BITS(result, 16, 47); | 3467 | RD = BITS(result, 16, 47); |
| 3111 | } | ||
| 3112 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3113 | INC_PC(sizeof(smlad_inst)); | ||
| 3114 | FETCH_INST; | ||
| 3115 | GOTO_NEXT_INST; | ||
| 3116 | } | 3468 | } |
| 3469 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3470 | INC_PC(sizeof(smlad_inst)); | ||
| 3471 | FETCH_INST; | ||
| 3472 | GOTO_NEXT_INST; | ||
| 3473 | } | ||
| 3117 | 3474 | ||
| 3118 | SRS_INST: | 3475 | SRS_INST : { |
| 3119 | { | 3476 | // SRS is unconditional |
| 3120 | // SRS is unconditional | 3477 | ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; |
| 3121 | ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; | ||
| 3122 | 3478 | ||
| 3123 | u32 address = 0; | 3479 | u32 address = 0; |
| 3124 | inst_cream->get_addr(cpu, inst_cream->inst, address); | 3480 | inst_cream->get_addr(cpu, inst_cream->inst, address); |
| 3125 | 3481 | ||
| 3126 | cpu->WriteMemory32(address + 0, cpu->Reg[14]); | 3482 | cpu->WriteMemory32(address + 0, cpu->Reg[14]); |
| 3127 | cpu->WriteMemory32(address + 4, cpu->Spsr_copy); | 3483 | cpu->WriteMemory32(address + 4, cpu->Spsr_copy); |
| 3128 | 3484 | ||
| 3129 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3485 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 3130 | INC_PC(sizeof(ldst_inst)); | 3486 | INC_PC(sizeof(ldst_inst)); |
| 3131 | FETCH_INST; | 3487 | FETCH_INST; |
| 3132 | GOTO_NEXT_INST; | 3488 | GOTO_NEXT_INST; |
| 3133 | } | 3489 | } |
| 3134 | |||
| 3135 | SSAT_INST: | ||
| 3136 | { | ||
| 3137 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3138 | ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; | ||
| 3139 | 3490 | ||
| 3140 | u8 shift_type = inst_cream->shift_type; | 3491 | SSAT_INST : { |
| 3141 | u8 shift_amount = inst_cream->imm5; | 3492 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 3142 | u32 rn_val = RN; | 3493 | ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; |
| 3143 | 3494 | ||
| 3144 | // 32-bit ASR is encoded as an amount of 0. | 3495 | u8 shift_type = inst_cream->shift_type; |
| 3145 | if (shift_type == 1 && shift_amount == 0) | 3496 | u8 shift_amount = inst_cream->imm5; |
| 3146 | shift_amount = 31; | 3497 | u32 rn_val = RN; |
| 3147 | 3498 | ||
| 3148 | if (shift_type == 0) | 3499 | // 32-bit ASR is encoded as an amount of 0. |
| 3149 | rn_val <<= shift_amount; | 3500 | if (shift_type == 1 && shift_amount == 0) |
| 3150 | else if (shift_type == 1) | 3501 | shift_amount = 31; |
| 3151 | rn_val = ((s32)rn_val >> shift_amount); | ||
| 3152 | 3502 | ||
| 3153 | bool saturated = false; | 3503 | if (shift_type == 0) |
| 3154 | rn_val = ARMul_SignedSatQ(rn_val, inst_cream->sat_imm, &saturated); | 3504 | rn_val <<= shift_amount; |
| 3505 | else if (shift_type == 1) | ||
| 3506 | rn_val = ((s32)rn_val >> shift_amount); | ||
| 3155 | 3507 | ||
| 3156 | if (saturated) | 3508 | bool saturated = false; |
| 3157 | cpu->Cpsr |= (1 << 27); | 3509 | rn_val = ARMul_SignedSatQ(rn_val, inst_cream->sat_imm, &saturated); |
| 3158 | 3510 | ||
| 3159 | RD = rn_val; | 3511 | if (saturated) |
| 3160 | } | 3512 | cpu->Cpsr |= (1 << 27); |
| 3161 | 3513 | ||
| 3162 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3514 | RD = rn_val; |
| 3163 | INC_PC(sizeof(ssat_inst)); | ||
| 3164 | FETCH_INST; | ||
| 3165 | GOTO_NEXT_INST; | ||
| 3166 | } | 3515 | } |
| 3167 | 3516 | ||
| 3168 | SSAT16_INST: | 3517 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 3169 | { | 3518 | INC_PC(sizeof(ssat_inst)); |
| 3170 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3519 | FETCH_INST; |
| 3171 | ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; | 3520 | GOTO_NEXT_INST; |
| 3172 | const u8 saturate_to = inst_cream->sat_imm; | 3521 | } |
| 3173 | 3522 | ||
| 3174 | bool sat1 = false; | 3523 | SSAT16_INST : { |
| 3175 | bool sat2 = false; | 3524 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 3525 | ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; | ||
| 3526 | const u8 saturate_to = inst_cream->sat_imm; | ||
| 3176 | 3527 | ||
| 3177 | RD = (ARMul_SignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) | | 3528 | bool sat1 = false; |
| 3178 | ARMul_SignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16; | 3529 | bool sat2 = false; |
| 3179 | 3530 | ||
| 3180 | if (sat1 || sat2) | 3531 | RD = (ARMul_SignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) | |
| 3181 | cpu->Cpsr |= (1 << 27); | 3532 | ARMul_SignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16; |
| 3182 | } | ||
| 3183 | 3533 | ||
| 3184 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3534 | if (sat1 || sat2) |
| 3185 | INC_PC(sizeof(ssat_inst)); | 3535 | cpu->Cpsr |= (1 << 27); |
| 3186 | FETCH_INST; | 3536 | } |
| 3187 | GOTO_NEXT_INST; | ||
| 3188 | } | ||
| 3189 | |||
| 3190 | STC_INST: | ||
| 3191 | { | ||
| 3192 | // Instruction not implemented | ||
| 3193 | //LOG_CRITICAL(Core_ARM11, "unimplemented instruction"); | ||
| 3194 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3195 | INC_PC(sizeof(stc_inst)); | ||
| 3196 | FETCH_INST; | ||
| 3197 | GOTO_NEXT_INST; | ||
| 3198 | } | ||
| 3199 | STM_INST: | ||
| 3200 | { | ||
| 3201 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3202 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 3203 | unsigned int inst = inst_cream->inst; | ||
| 3204 | |||
| 3205 | unsigned int Rn = BITS(inst, 16, 19); | ||
| 3206 | unsigned int old_RN = cpu->Reg[Rn]; | ||
| 3207 | |||
| 3208 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 3209 | if (BIT(inst_cream->inst, 22) == 1) { | ||
| 3210 | for (int i = 0; i < 13; i++) { | ||
| 3211 | if (BIT(inst_cream->inst, i)) { | ||
| 3212 | cpu->WriteMemory32(addr, cpu->Reg[i]); | ||
| 3213 | addr += 4; | ||
| 3214 | } | ||
| 3215 | } | ||
| 3216 | if (BIT(inst_cream->inst, 13)) { | ||
| 3217 | if (cpu->Mode == USER32MODE) | ||
| 3218 | cpu->WriteMemory32(addr, cpu->Reg[13]); | ||
| 3219 | else | ||
| 3220 | cpu->WriteMemory32(addr, cpu->Reg_usr[0]); | ||
| 3221 | 3537 | ||
| 3538 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3539 | INC_PC(sizeof(ssat_inst)); | ||
| 3540 | FETCH_INST; | ||
| 3541 | GOTO_NEXT_INST; | ||
| 3542 | } | ||
| 3543 | |||
| 3544 | STC_INST : { | ||
| 3545 | // Instruction not implemented | ||
| 3546 | // LOG_CRITICAL(Core_ARM11, "unimplemented instruction"); | ||
| 3547 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3548 | INC_PC(sizeof(stc_inst)); | ||
| 3549 | FETCH_INST; | ||
| 3550 | GOTO_NEXT_INST; | ||
| 3551 | } | ||
| 3552 | STM_INST : { | ||
| 3553 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3554 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 3555 | unsigned int inst = inst_cream->inst; | ||
| 3556 | |||
| 3557 | unsigned int Rn = BITS(inst, 16, 19); | ||
| 3558 | unsigned int old_RN = cpu->Reg[Rn]; | ||
| 3559 | |||
| 3560 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 3561 | if (BIT(inst_cream->inst, 22) == 1) { | ||
| 3562 | for (int i = 0; i < 13; i++) { | ||
| 3563 | if (BIT(inst_cream->inst, i)) { | ||
| 3564 | cpu->WriteMemory32(addr, cpu->Reg[i]); | ||
| 3222 | addr += 4; | 3565 | addr += 4; |
| 3223 | } | 3566 | } |
| 3224 | if (BIT(inst_cream->inst, 14)) { | 3567 | } |
| 3225 | if (cpu->Mode == USER32MODE) | 3568 | if (BIT(inst_cream->inst, 13)) { |
| 3226 | cpu->WriteMemory32(addr, cpu->Reg[14]); | 3569 | if (cpu->Mode == USER32MODE) |
| 3570 | cpu->WriteMemory32(addr, cpu->Reg[13]); | ||
| 3571 | else | ||
| 3572 | cpu->WriteMemory32(addr, cpu->Reg_usr[0]); | ||
| 3573 | |||
| 3574 | addr += 4; | ||
| 3575 | } | ||
| 3576 | if (BIT(inst_cream->inst, 14)) { | ||
| 3577 | if (cpu->Mode == USER32MODE) | ||
| 3578 | cpu->WriteMemory32(addr, cpu->Reg[14]); | ||
| 3579 | else | ||
| 3580 | cpu->WriteMemory32(addr, cpu->Reg_usr[1]); | ||
| 3581 | |||
| 3582 | addr += 4; | ||
| 3583 | } | ||
| 3584 | if (BIT(inst_cream->inst, 15)) { | ||
| 3585 | cpu->WriteMemory32(addr, cpu->Reg[15] + 8); | ||
| 3586 | } | ||
| 3587 | } else { | ||
| 3588 | for (int i = 0; i < 15; i++) { | ||
| 3589 | if (BIT(inst_cream->inst, i)) { | ||
| 3590 | if (i == Rn) | ||
| 3591 | cpu->WriteMemory32(addr, old_RN); | ||
| 3227 | else | 3592 | else |
| 3228 | cpu->WriteMemory32(addr, cpu->Reg_usr[1]); | 3593 | cpu->WriteMemory32(addr, cpu->Reg[i]); |
| 3229 | 3594 | ||
| 3230 | addr += 4; | 3595 | addr += 4; |
| 3231 | } | 3596 | } |
| 3232 | if (BIT(inst_cream->inst, 15)) { | 3597 | } |
| 3233 | cpu->WriteMemory32(addr, cpu->Reg[15] + 8); | ||
| 3234 | } | ||
| 3235 | } else { | ||
| 3236 | for (int i = 0; i < 15; i++) { | ||
| 3237 | if (BIT(inst_cream->inst, i)) { | ||
| 3238 | if (i == Rn) | ||
| 3239 | cpu->WriteMemory32(addr, old_RN); | ||
| 3240 | else | ||
| 3241 | cpu->WriteMemory32(addr, cpu->Reg[i]); | ||
| 3242 | |||
| 3243 | addr += 4; | ||
| 3244 | } | ||
| 3245 | } | ||
| 3246 | 3598 | ||
| 3247 | // Check PC reg | 3599 | // Check PC reg |
| 3248 | if (BIT(inst_cream->inst, 15)) { | 3600 | if (BIT(inst_cream->inst, 15)) { |
| 3249 | cpu->WriteMemory32(addr, cpu->Reg[15] + 8); | 3601 | cpu->WriteMemory32(addr, cpu->Reg[15] + 8); |
| 3250 | } | ||
| 3251 | } | 3602 | } |
| 3252 | } | 3603 | } |
| 3253 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3254 | INC_PC(sizeof(ldst_inst)); | ||
| 3255 | FETCH_INST; | ||
| 3256 | GOTO_NEXT_INST; | ||
| 3257 | } | 3604 | } |
| 3258 | SXTB_INST: | 3605 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 3259 | { | 3606 | INC_PC(sizeof(ldst_inst)); |
| 3260 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3607 | FETCH_INST; |
| 3261 | sxtb_inst* inst_cream = (sxtb_inst*)inst_base->component; | 3608 | GOTO_NEXT_INST; |
| 3609 | } | ||
| 3610 | SXTB_INST : { | ||
| 3611 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3612 | sxtb_inst* inst_cream = (sxtb_inst*)inst_base->component; | ||
| 3262 | 3613 | ||
| 3263 | unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate); | 3614 | unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate); |
| 3264 | if (BIT(operand2, 7)) { | 3615 | if (BIT(operand2, 7)) { |
| 3265 | operand2 |= 0xffffff00; | 3616 | operand2 |= 0xffffff00; |
| 3266 | } else { | 3617 | } else { |
| 3267 | operand2 &= 0xff; | 3618 | operand2 &= 0xff; |
| 3268 | } | ||
| 3269 | RD = operand2; | ||
| 3270 | } | 3619 | } |
| 3271 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3620 | RD = operand2; |
| 3272 | INC_PC(sizeof(sxtb_inst)); | ||
| 3273 | FETCH_INST; | ||
| 3274 | GOTO_NEXT_INST; | ||
| 3275 | } | 3621 | } |
| 3276 | STR_INST: | 3622 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 3277 | { | 3623 | INC_PC(sizeof(sxtb_inst)); |
| 3278 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3624 | FETCH_INST; |
| 3279 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | 3625 | GOTO_NEXT_INST; |
| 3280 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | 3626 | } |
| 3627 | STR_INST : { | ||
| 3628 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3629 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 3630 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 3281 | 3631 | ||
| 3282 | unsigned int reg = BITS(inst_cream->inst, 12, 15); | 3632 | unsigned int reg = BITS(inst_cream->inst, 12, 15); |
| 3283 | unsigned int value = cpu->Reg[reg]; | 3633 | unsigned int value = cpu->Reg[reg]; |
| 3284 | 3634 | ||
| 3285 | if (reg == 15) | 3635 | if (reg == 15) |
| 3286 | value += 2 * cpu->GetInstructionSize(); | 3636 | value += 2 * cpu->GetInstructionSize(); |
| 3287 | 3637 | ||
| 3288 | cpu->WriteMemory32(addr, value); | 3638 | cpu->WriteMemory32(addr, value); |
| 3289 | } | ||
| 3290 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3291 | INC_PC(sizeof(ldst_inst)); | ||
| 3292 | FETCH_INST; | ||
| 3293 | GOTO_NEXT_INST; | ||
| 3294 | } | ||
| 3295 | UXTB_INST: | ||
| 3296 | { | ||
| 3297 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3298 | uxtb_inst* inst_cream = (uxtb_inst*)inst_base->component; | ||
| 3299 | RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff; | ||
| 3300 | } | ||
| 3301 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3302 | INC_PC(sizeof(uxtb_inst)); | ||
| 3303 | FETCH_INST; | ||
| 3304 | GOTO_NEXT_INST; | ||
| 3305 | } | ||
| 3306 | UXTAB_INST: | ||
| 3307 | { | ||
| 3308 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3309 | uxtab_inst* inst_cream = (uxtab_inst*)inst_base->component; | ||
| 3310 | |||
| 3311 | unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff; | ||
| 3312 | RD = RN + operand2; | ||
| 3313 | } | ||
| 3314 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3315 | INC_PC(sizeof(uxtab_inst)); | ||
| 3316 | FETCH_INST; | ||
| 3317 | GOTO_NEXT_INST; | ||
| 3318 | } | ||
| 3319 | STRB_INST: | ||
| 3320 | { | ||
| 3321 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3322 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 3323 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 3324 | unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; | ||
| 3325 | cpu->WriteMemory8(addr, value); | ||
| 3326 | } | ||
| 3327 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3328 | INC_PC(sizeof(ldst_inst)); | ||
| 3329 | FETCH_INST; | ||
| 3330 | GOTO_NEXT_INST; | ||
| 3331 | } | 3639 | } |
| 3332 | STRBT_INST: | 3640 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 3333 | { | 3641 | INC_PC(sizeof(ldst_inst)); |
| 3334 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3642 | FETCH_INST; |
| 3335 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | 3643 | GOTO_NEXT_INST; |
| 3336 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | 3644 | } |
| 3645 | UXTB_INST : { | ||
| 3646 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3647 | uxtb_inst* inst_cream = (uxtb_inst*)inst_base->component; | ||
| 3648 | RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff; | ||
| 3649 | } | ||
| 3650 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3651 | INC_PC(sizeof(uxtb_inst)); | ||
| 3652 | FETCH_INST; | ||
| 3653 | GOTO_NEXT_INST; | ||
| 3654 | } | ||
| 3655 | UXTAB_INST : { | ||
| 3656 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3657 | uxtab_inst* inst_cream = (uxtab_inst*)inst_base->component; | ||
| 3337 | 3658 | ||
| 3338 | const u32 previous_mode = cpu->Mode; | 3659 | unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff; |
| 3339 | const u32 value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; | 3660 | RD = RN + operand2; |
| 3661 | } | ||
| 3662 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3663 | INC_PC(sizeof(uxtab_inst)); | ||
| 3664 | FETCH_INST; | ||
| 3665 | GOTO_NEXT_INST; | ||
| 3666 | } | ||
| 3667 | STRB_INST : { | ||
| 3668 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3669 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 3670 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 3671 | unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; | ||
| 3672 | cpu->WriteMemory8(addr, value); | ||
| 3673 | } | ||
| 3674 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3675 | INC_PC(sizeof(ldst_inst)); | ||
| 3676 | FETCH_INST; | ||
| 3677 | GOTO_NEXT_INST; | ||
| 3678 | } | ||
| 3679 | STRBT_INST : { | ||
| 3680 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3681 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 3682 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 3340 | 3683 | ||
| 3341 | cpu->ChangePrivilegeMode(USER32MODE); | 3684 | const u32 previous_mode = cpu->Mode; |
| 3342 | cpu->WriteMemory8(addr, value); | 3685 | const u32 value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; |
| 3343 | cpu->ChangePrivilegeMode(previous_mode); | ||
| 3344 | } | ||
| 3345 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3346 | INC_PC(sizeof(ldst_inst)); | ||
| 3347 | FETCH_INST; | ||
| 3348 | GOTO_NEXT_INST; | ||
| 3349 | } | ||
| 3350 | STRD_INST: | ||
| 3351 | { | ||
| 3352 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3353 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 3354 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 3355 | |||
| 3356 | // The 3DS doesn't have the Large Physical Access Extension (LPAE) | ||
| 3357 | // so STRD wouldn't store these as a single write. | ||
| 3358 | cpu->WriteMemory32(addr + 0, cpu->Reg[BITS(inst_cream->inst, 12, 15)]); | ||
| 3359 | cpu->WriteMemory32(addr + 4, cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]); | ||
| 3360 | } | ||
| 3361 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3362 | INC_PC(sizeof(ldst_inst)); | ||
| 3363 | FETCH_INST; | ||
| 3364 | GOTO_NEXT_INST; | ||
| 3365 | } | ||
| 3366 | STREX_INST: | ||
| 3367 | { | ||
| 3368 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3369 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 3370 | unsigned int write_addr = cpu->Reg[inst_cream->Rn]; | ||
| 3371 | |||
| 3372 | if (cpu->IsExclusiveMemoryAccess(write_addr)) { | ||
| 3373 | cpu->UnsetExclusiveMemoryAddress(); | ||
| 3374 | cpu->WriteMemory32(write_addr, RM); | ||
| 3375 | RD = 0; | ||
| 3376 | } else { | ||
| 3377 | // Failed to write due to mutex access | ||
| 3378 | RD = 1; | ||
| 3379 | } | ||
| 3380 | } | ||
| 3381 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3382 | INC_PC(sizeof(generic_arm_inst)); | ||
| 3383 | FETCH_INST; | ||
| 3384 | GOTO_NEXT_INST; | ||
| 3385 | } | ||
| 3386 | STREXB_INST: | ||
| 3387 | { | ||
| 3388 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3389 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 3390 | unsigned int write_addr = cpu->Reg[inst_cream->Rn]; | ||
| 3391 | |||
| 3392 | if (cpu->IsExclusiveMemoryAccess(write_addr)) { | ||
| 3393 | cpu->UnsetExclusiveMemoryAddress(); | ||
| 3394 | cpu->WriteMemory8(write_addr, cpu->Reg[inst_cream->Rm]); | ||
| 3395 | RD = 0; | ||
| 3396 | } else { | ||
| 3397 | // Failed to write due to mutex access | ||
| 3398 | RD = 1; | ||
| 3399 | } | ||
| 3400 | } | ||
| 3401 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3402 | INC_PC(sizeof(generic_arm_inst)); | ||
| 3403 | FETCH_INST; | ||
| 3404 | GOTO_NEXT_INST; | ||
| 3405 | } | ||
| 3406 | STREXD_INST: | ||
| 3407 | { | ||
| 3408 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3409 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 3410 | unsigned int write_addr = cpu->Reg[inst_cream->Rn]; | ||
| 3411 | |||
| 3412 | if (cpu->IsExclusiveMemoryAccess(write_addr)) { | ||
| 3413 | cpu->UnsetExclusiveMemoryAddress(); | ||
| 3414 | |||
| 3415 | const u32 rt = cpu->Reg[inst_cream->Rm + 0]; | ||
| 3416 | const u32 rt2 = cpu->Reg[inst_cream->Rm + 1]; | ||
| 3417 | u64 value; | ||
| 3418 | |||
| 3419 | if (cpu->InBigEndianMode()) | ||
| 3420 | value = (((u64)rt << 32) | rt2); | ||
| 3421 | else | ||
| 3422 | value = (((u64)rt2 << 32) | rt); | ||
| 3423 | 3686 | ||
| 3424 | cpu->WriteMemory64(write_addr, value); | 3687 | cpu->ChangePrivilegeMode(USER32MODE); |
| 3425 | RD = 0; | 3688 | cpu->WriteMemory8(addr, value); |
| 3426 | } | 3689 | cpu->ChangePrivilegeMode(previous_mode); |
| 3427 | else { | 3690 | } |
| 3428 | // Failed to write due to mutex access | 3691 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 3429 | RD = 1; | 3692 | INC_PC(sizeof(ldst_inst)); |
| 3430 | } | 3693 | FETCH_INST; |
| 3431 | } | 3694 | GOTO_NEXT_INST; |
| 3432 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3695 | } |
| 3433 | INC_PC(sizeof(generic_arm_inst)); | 3696 | STRD_INST : { |
| 3434 | FETCH_INST; | 3697 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 3435 | GOTO_NEXT_INST; | 3698 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 3436 | } | 3699 | inst_cream->get_addr(cpu, inst_cream->inst, addr); |
| 3437 | STREXH_INST: | 3700 | |
| 3438 | { | 3701 | // The 3DS doesn't have the Large Physical Access Extension (LPAE) |
| 3439 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3702 | // so STRD wouldn't store these as a single write. |
| 3440 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | 3703 | cpu->WriteMemory32(addr + 0, cpu->Reg[BITS(inst_cream->inst, 12, 15)]); |
| 3441 | unsigned int write_addr = cpu->Reg[inst_cream->Rn]; | 3704 | cpu->WriteMemory32(addr + 4, cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]); |
| 3442 | 3705 | } | |
| 3443 | if (cpu->IsExclusiveMemoryAccess(write_addr)) { | 3706 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 3444 | cpu->UnsetExclusiveMemoryAddress(); | 3707 | INC_PC(sizeof(ldst_inst)); |
| 3445 | cpu->WriteMemory16(write_addr, RM); | 3708 | FETCH_INST; |
| 3446 | RD = 0; | 3709 | GOTO_NEXT_INST; |
| 3447 | } else { | 3710 | } |
| 3448 | // Failed to write due to mutex access | 3711 | STREX_INST : { |
| 3449 | RD = 1; | 3712 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 3450 | } | 3713 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |
| 3714 | unsigned int write_addr = cpu->Reg[inst_cream->Rn]; | ||
| 3715 | |||
| 3716 | if (cpu->IsExclusiveMemoryAccess(write_addr)) { | ||
| 3717 | cpu->UnsetExclusiveMemoryAddress(); | ||
| 3718 | cpu->WriteMemory32(write_addr, RM); | ||
| 3719 | RD = 0; | ||
| 3720 | } else { | ||
| 3721 | // Failed to write due to mutex access | ||
| 3722 | RD = 1; | ||
| 3451 | } | 3723 | } |
| 3452 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3724 | } |
| 3453 | INC_PC(sizeof(generic_arm_inst)); | 3725 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 3454 | FETCH_INST; | 3726 | INC_PC(sizeof(generic_arm_inst)); |
| 3455 | GOTO_NEXT_INST; | 3727 | FETCH_INST; |
| 3456 | } | 3728 | GOTO_NEXT_INST; |
| 3457 | STRH_INST: | 3729 | } |
| 3458 | { | 3730 | STREXB_INST : { |
| 3459 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3731 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 3460 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | 3732 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |
| 3461 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | 3733 | unsigned int write_addr = cpu->Reg[inst_cream->Rn]; |
| 3462 | 3734 | ||
| 3463 | unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff; | 3735 | if (cpu->IsExclusiveMemoryAccess(write_addr)) { |
| 3464 | cpu->WriteMemory16(addr, value); | 3736 | cpu->UnsetExclusiveMemoryAddress(); |
| 3737 | cpu->WriteMemory8(write_addr, cpu->Reg[inst_cream->Rm]); | ||
| 3738 | RD = 0; | ||
| 3739 | } else { | ||
| 3740 | // Failed to write due to mutex access | ||
| 3741 | RD = 1; | ||
| 3465 | } | 3742 | } |
| 3466 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3467 | INC_PC(sizeof(ldst_inst)); | ||
| 3468 | FETCH_INST; | ||
| 3469 | GOTO_NEXT_INST; | ||
| 3470 | } | 3743 | } |
| 3471 | STRT_INST: | 3744 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 3472 | { | 3745 | INC_PC(sizeof(generic_arm_inst)); |
| 3473 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3746 | FETCH_INST; |
| 3474 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | 3747 | GOTO_NEXT_INST; |
| 3475 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | 3748 | } |
| 3749 | STREXD_INST : { | ||
| 3750 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3751 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 3752 | unsigned int write_addr = cpu->Reg[inst_cream->Rn]; | ||
| 3476 | 3753 | ||
| 3477 | const u32 previous_mode = cpu->Mode; | 3754 | if (cpu->IsExclusiveMemoryAccess(write_addr)) { |
| 3478 | const u32 rt_index = BITS(inst_cream->inst, 12, 15); | 3755 | cpu->UnsetExclusiveMemoryAddress(); |
| 3479 | 3756 | ||
| 3480 | u32 value = cpu->Reg[rt_index]; | 3757 | const u32 rt = cpu->Reg[inst_cream->Rm + 0]; |
| 3481 | if (rt_index == 15) | 3758 | const u32 rt2 = cpu->Reg[inst_cream->Rm + 1]; |
| 3482 | value += 2 * cpu->GetInstructionSize(); | 3759 | u64 value; |
| 3483 | 3760 | ||
| 3484 | cpu->ChangePrivilegeMode(USER32MODE); | 3761 | if (cpu->InBigEndianMode()) |
| 3485 | cpu->WriteMemory32(addr, value); | 3762 | value = (((u64)rt << 32) | rt2); |
| 3486 | cpu->ChangePrivilegeMode(previous_mode); | 3763 | else |
| 3764 | value = (((u64)rt2 << 32) | rt); | ||
| 3765 | |||
| 3766 | cpu->WriteMemory64(write_addr, value); | ||
| 3767 | RD = 0; | ||
| 3768 | } else { | ||
| 3769 | // Failed to write due to mutex access | ||
| 3770 | RD = 1; | ||
| 3487 | } | 3771 | } |
| 3488 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3489 | INC_PC(sizeof(ldst_inst)); | ||
| 3490 | FETCH_INST; | ||
| 3491 | GOTO_NEXT_INST; | ||
| 3492 | } | 3772 | } |
| 3493 | SUB_INST: | 3773 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 3494 | { | 3774 | INC_PC(sizeof(generic_arm_inst)); |
| 3495 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3775 | FETCH_INST; |
| 3496 | sub_inst* const inst_cream = (sub_inst*)inst_base->component; | 3776 | GOTO_NEXT_INST; |
| 3777 | } | ||
| 3778 | STREXH_INST : { | ||
| 3779 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3780 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 3781 | unsigned int write_addr = cpu->Reg[inst_cream->Rn]; | ||
| 3782 | |||
| 3783 | if (cpu->IsExclusiveMemoryAccess(write_addr)) { | ||
| 3784 | cpu->UnsetExclusiveMemoryAddress(); | ||
| 3785 | cpu->WriteMemory16(write_addr, RM); | ||
| 3786 | RD = 0; | ||
| 3787 | } else { | ||
| 3788 | // Failed to write due to mutex access | ||
| 3789 | RD = 1; | ||
| 3790 | } | ||
| 3791 | } | ||
| 3792 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3793 | INC_PC(sizeof(generic_arm_inst)); | ||
| 3794 | FETCH_INST; | ||
| 3795 | GOTO_NEXT_INST; | ||
| 3796 | } | ||
| 3797 | STRH_INST : { | ||
| 3798 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3799 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 3800 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 3497 | 3801 | ||
| 3498 | u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn); | 3802 | unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff; |
| 3803 | cpu->WriteMemory16(addr, value); | ||
| 3804 | } | ||
| 3805 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3806 | INC_PC(sizeof(ldst_inst)); | ||
| 3807 | FETCH_INST; | ||
| 3808 | GOTO_NEXT_INST; | ||
| 3809 | } | ||
| 3810 | STRT_INST : { | ||
| 3811 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3812 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||
| 3813 | inst_cream->get_addr(cpu, inst_cream->inst, addr); | ||
| 3499 | 3814 | ||
| 3500 | bool carry; | 3815 | const u32 previous_mode = cpu->Mode; |
| 3501 | bool overflow; | 3816 | const u32 rt_index = BITS(inst_cream->inst, 12, 15); |
| 3502 | RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow); | ||
| 3503 | 3817 | ||
| 3504 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 3818 | u32 value = cpu->Reg[rt_index]; |
| 3505 | if (CurrentModeHasSPSR) { | 3819 | if (rt_index == 15) |
| 3506 | cpu->Cpsr = cpu->Spsr_copy; | 3820 | value += 2 * cpu->GetInstructionSize(); |
| 3507 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); | ||
| 3508 | LOAD_NZCVT; | ||
| 3509 | } | ||
| 3510 | } else if (inst_cream->S) { | ||
| 3511 | UPDATE_NFLAG(RD); | ||
| 3512 | UPDATE_ZFLAG(RD); | ||
| 3513 | cpu->CFlag = carry; | ||
| 3514 | cpu->VFlag = overflow; | ||
| 3515 | } | ||
| 3516 | if (inst_cream->Rd == 15) { | ||
| 3517 | INC_PC(sizeof(sub_inst)); | ||
| 3518 | goto DISPATCH; | ||
| 3519 | } | ||
| 3520 | } | ||
| 3521 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3522 | INC_PC(sizeof(sub_inst)); | ||
| 3523 | FETCH_INST; | ||
| 3524 | GOTO_NEXT_INST; | ||
| 3525 | } | ||
| 3526 | SWI_INST: | ||
| 3527 | { | ||
| 3528 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3529 | swi_inst* const inst_cream = (swi_inst*)inst_base->component; | ||
| 3530 | SVC::CallSVC(inst_cream->num & 0xFFFF); | ||
| 3531 | } | ||
| 3532 | 3821 | ||
| 3533 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3822 | cpu->ChangePrivilegeMode(USER32MODE); |
| 3534 | INC_PC(sizeof(swi_inst)); | 3823 | cpu->WriteMemory32(addr, value); |
| 3535 | FETCH_INST; | 3824 | cpu->ChangePrivilegeMode(previous_mode); |
| 3536 | GOTO_NEXT_INST; | ||
| 3537 | } | 3825 | } |
| 3538 | SWP_INST: | 3826 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 3539 | { | 3827 | INC_PC(sizeof(ldst_inst)); |
| 3540 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3828 | FETCH_INST; |
| 3541 | swp_inst* inst_cream = (swp_inst*)inst_base->component; | 3829 | GOTO_NEXT_INST; |
| 3830 | } | ||
| 3831 | SUB_INST : { | ||
| 3832 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3833 | sub_inst* const inst_cream = (sub_inst*)inst_base->component; | ||
| 3542 | 3834 | ||
| 3543 | addr = RN; | 3835 | u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn); |
| 3544 | unsigned int value = cpu->ReadMemory32(addr); | ||
| 3545 | cpu->WriteMemory32(addr, RM); | ||
| 3546 | 3836 | ||
| 3547 | RD = value; | 3837 | bool carry; |
| 3838 | bool overflow; | ||
| 3839 | RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow); | ||
| 3840 | |||
| 3841 | if (inst_cream->S && (inst_cream->Rd == 15)) { | ||
| 3842 | if (CurrentModeHasSPSR) { | ||
| 3843 | cpu->Cpsr = cpu->Spsr_copy; | ||
| 3844 | cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); | ||
| 3845 | LOAD_NZCVT; | ||
| 3846 | } | ||
| 3847 | } else if (inst_cream->S) { | ||
| 3848 | UPDATE_NFLAG(RD); | ||
| 3849 | UPDATE_ZFLAG(RD); | ||
| 3850 | cpu->CFlag = carry; | ||
| 3851 | cpu->VFlag = overflow; | ||
| 3548 | } | 3852 | } |
| 3549 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3853 | if (inst_cream->Rd == 15) { |
| 3550 | INC_PC(sizeof(swp_inst)); | 3854 | INC_PC(sizeof(sub_inst)); |
| 3551 | FETCH_INST; | 3855 | goto DISPATCH; |
| 3552 | GOTO_NEXT_INST; | ||
| 3553 | } | ||
| 3554 | SWPB_INST: | ||
| 3555 | { | ||
| 3556 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3557 | swp_inst* inst_cream = (swp_inst*)inst_base->component; | ||
| 3558 | addr = RN; | ||
| 3559 | unsigned int value = cpu->ReadMemory8(addr); | ||
| 3560 | cpu->WriteMemory8(addr, (RM & 0xFF)); | ||
| 3561 | RD = value; | ||
| 3562 | } | 3856 | } |
| 3563 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3564 | INC_PC(sizeof(swp_inst)); | ||
| 3565 | FETCH_INST; | ||
| 3566 | GOTO_NEXT_INST; | ||
| 3567 | } | 3857 | } |
| 3568 | SXTAB_INST: | 3858 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 3569 | { | 3859 | INC_PC(sizeof(sub_inst)); |
| 3570 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3860 | FETCH_INST; |
| 3571 | sxtab_inst* inst_cream = (sxtab_inst*)inst_base->component; | 3861 | GOTO_NEXT_INST; |
| 3862 | } | ||
| 3863 | SWI_INST : { | ||
| 3864 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3865 | swi_inst* const inst_cream = (swi_inst*)inst_base->component; | ||
| 3866 | SVC::CallSVC(inst_cream->num & 0xFFFF); | ||
| 3867 | } | ||
| 3572 | 3868 | ||
| 3573 | unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff; | 3869 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 3870 | INC_PC(sizeof(swi_inst)); | ||
| 3871 | FETCH_INST; | ||
| 3872 | GOTO_NEXT_INST; | ||
| 3873 | } | ||
| 3874 | SWP_INST : { | ||
| 3875 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3876 | swp_inst* inst_cream = (swp_inst*)inst_base->component; | ||
| 3574 | 3877 | ||
| 3575 | // Sign extend for byte | 3878 | addr = RN; |
| 3576 | operand2 = (0x80 & operand2)? (0xFFFFFF00 | operand2):operand2; | 3879 | unsigned int value = cpu->ReadMemory32(addr); |
| 3577 | RD = RN + operand2; | 3880 | cpu->WriteMemory32(addr, RM); |
| 3578 | } | ||
| 3579 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3580 | INC_PC(sizeof(uxtab_inst)); | ||
| 3581 | FETCH_INST; | ||
| 3582 | GOTO_NEXT_INST; | ||
| 3583 | } | ||
| 3584 | |||
| 3585 | SXTAB16_INST: | ||
| 3586 | SXTB16_INST: | ||
| 3587 | { | ||
| 3588 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3589 | sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component; | ||
| 3590 | |||
| 3591 | const u8 rotation = inst_cream->rotate * 8; | ||
| 3592 | u32 rm_val = RM; | ||
| 3593 | u32 rn_val = RN; | ||
| 3594 | |||
| 3595 | if (rotation) | ||
| 3596 | rm_val = ((rm_val << (32 - rotation)) | (rm_val >> rotation)); | ||
| 3597 | |||
| 3598 | // SXTB16 | ||
| 3599 | if (inst_cream->Rn == 15) { | ||
| 3600 | u32 lo = (u32)(s8)rm_val; | ||
| 3601 | u32 hi = (u32)(s8)(rm_val >> 16); | ||
| 3602 | RD = (lo | (hi << 16)); | ||
| 3603 | } | ||
| 3604 | // SXTAB16 | ||
| 3605 | else { | ||
| 3606 | u32 lo = (rn_val & 0xFFFF) + (u32)(s8)(rm_val & 0xFF); | ||
| 3607 | u32 hi = ((rn_val >> 16) & 0xFFFF) + (u32)(s8)((rm_val >> 16) & 0xFF); | ||
| 3608 | RD = (lo | (hi << 16)); | ||
| 3609 | } | ||
| 3610 | } | ||
| 3611 | 3881 | ||
| 3612 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3882 | RD = value; |
| 3613 | INC_PC(sizeof(sxtab_inst)); | ||
| 3614 | FETCH_INST; | ||
| 3615 | GOTO_NEXT_INST; | ||
| 3616 | } | 3883 | } |
| 3884 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3885 | INC_PC(sizeof(swp_inst)); | ||
| 3886 | FETCH_INST; | ||
| 3887 | GOTO_NEXT_INST; | ||
| 3888 | } | ||
| 3889 | SWPB_INST : { | ||
| 3890 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3891 | swp_inst* inst_cream = (swp_inst*)inst_base->component; | ||
| 3892 | addr = RN; | ||
| 3893 | unsigned int value = cpu->ReadMemory8(addr); | ||
| 3894 | cpu->WriteMemory8(addr, (RM & 0xFF)); | ||
| 3895 | RD = value; | ||
| 3896 | } | ||
| 3897 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3898 | INC_PC(sizeof(swp_inst)); | ||
| 3899 | FETCH_INST; | ||
| 3900 | GOTO_NEXT_INST; | ||
| 3901 | } | ||
| 3902 | SXTAB_INST : { | ||
| 3903 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3904 | sxtab_inst* inst_cream = (sxtab_inst*)inst_base->component; | ||
| 3617 | 3905 | ||
| 3618 | SXTAH_INST: | 3906 | unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff; |
| 3619 | { | ||
| 3620 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3621 | sxtah_inst* inst_cream = (sxtah_inst*)inst_base->component; | ||
| 3622 | 3907 | ||
| 3623 | unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff; | 3908 | // Sign extend for byte |
| 3624 | // Sign extend for half | 3909 | operand2 = (0x80 & operand2) ? (0xFFFFFF00 | operand2) : operand2; |
| 3625 | operand2 = (0x8000 & operand2) ? (0xFFFF0000 | operand2) : operand2; | 3910 | RD = RN + operand2; |
| 3626 | RD = RN + operand2; | ||
| 3627 | } | ||
| 3628 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3629 | INC_PC(sizeof(sxtah_inst)); | ||
| 3630 | FETCH_INST; | ||
| 3631 | GOTO_NEXT_INST; | ||
| 3632 | } | 3911 | } |
| 3912 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3913 | INC_PC(sizeof(uxtab_inst)); | ||
| 3914 | FETCH_INST; | ||
| 3915 | GOTO_NEXT_INST; | ||
| 3916 | } | ||
| 3633 | 3917 | ||
| 3634 | TEQ_INST: | 3918 | SXTAB16_INST: |
| 3635 | { | 3919 | SXTB16_INST : { |
| 3636 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 3920 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 3637 | teq_inst* const inst_cream = (teq_inst*)inst_base->component; | 3921 | sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component; |
| 3638 | |||
| 3639 | u32 lop = RN; | ||
| 3640 | u32 rop = SHIFTER_OPERAND; | ||
| 3641 | 3922 | ||
| 3642 | if (inst_cream->Rn == 15) | 3923 | const u8 rotation = inst_cream->rotate * 8; |
| 3643 | lop += cpu->GetInstructionSize() * 2; | 3924 | u32 rm_val = RM; |
| 3925 | u32 rn_val = RN; | ||
| 3644 | 3926 | ||
| 3645 | u32 result = lop ^ rop; | 3927 | if (rotation) |
| 3928 | rm_val = ((rm_val << (32 - rotation)) | (rm_val >> rotation)); | ||
| 3646 | 3929 | ||
| 3647 | UPDATE_NFLAG(result); | 3930 | // SXTB16 |
| 3648 | UPDATE_ZFLAG(result); | 3931 | if (inst_cream->Rn == 15) { |
| 3649 | UPDATE_CFLAG_WITH_SC; | 3932 | u32 lo = (u32)(s8)rm_val; |
| 3933 | u32 hi = (u32)(s8)(rm_val >> 16); | ||
| 3934 | RD = (lo | (hi << 16)); | ||
| 3935 | } | ||
| 3936 | // SXTAB16 | ||
| 3937 | else { | ||
| 3938 | u32 lo = (rn_val & 0xFFFF) + (u32)(s8)(rm_val & 0xFF); | ||
| 3939 | u32 hi = ((rn_val >> 16) & 0xFFFF) + (u32)(s8)((rm_val >> 16) & 0xFF); | ||
| 3940 | RD = (lo | (hi << 16)); | ||
| 3650 | } | 3941 | } |
| 3651 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3652 | INC_PC(sizeof(teq_inst)); | ||
| 3653 | FETCH_INST; | ||
| 3654 | GOTO_NEXT_INST; | ||
| 3655 | } | 3942 | } |
| 3656 | TST_INST: | ||
| 3657 | { | ||
| 3658 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3659 | tst_inst* const inst_cream = (tst_inst*)inst_base->component; | ||
| 3660 | 3943 | ||
| 3661 | u32 lop = RN; | 3944 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 3662 | u32 rop = SHIFTER_OPERAND; | 3945 | INC_PC(sizeof(sxtab_inst)); |
| 3663 | 3946 | FETCH_INST; | |
| 3664 | if (inst_cream->Rn == 15) | 3947 | GOTO_NEXT_INST; |
| 3665 | lop += cpu->GetInstructionSize() * 2; | 3948 | } |
| 3666 | 3949 | ||
| 3667 | u32 result = lop & rop; | 3950 | SXTAH_INST : { |
| 3951 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3952 | sxtah_inst* inst_cream = (sxtah_inst*)inst_base->component; | ||
| 3668 | 3953 | ||
| 3669 | UPDATE_NFLAG(result); | 3954 | unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff; |
| 3670 | UPDATE_ZFLAG(result); | 3955 | // Sign extend for half |
| 3671 | UPDATE_CFLAG_WITH_SC; | 3956 | operand2 = (0x8000 & operand2) ? (0xFFFF0000 | operand2) : operand2; |
| 3672 | } | 3957 | RD = RN + operand2; |
| 3673 | cpu->Reg[15] += cpu->GetInstructionSize(); | 3958 | } |
| 3674 | INC_PC(sizeof(tst_inst)); | 3959 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 3675 | FETCH_INST; | 3960 | INC_PC(sizeof(sxtah_inst)); |
| 3676 | GOTO_NEXT_INST; | 3961 | FETCH_INST; |
| 3677 | } | 3962 | GOTO_NEXT_INST; |
| 3678 | 3963 | } | |
| 3679 | UADD8_INST: | ||
| 3680 | UADD16_INST: | ||
| 3681 | UADDSUBX_INST: | ||
| 3682 | USUB8_INST: | ||
| 3683 | USUB16_INST: | ||
| 3684 | USUBADDX_INST: | ||
| 3685 | { | ||
| 3686 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3687 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 3688 | |||
| 3689 | const u8 op2 = inst_cream->op2; | ||
| 3690 | const u32 rm_val = RM; | ||
| 3691 | const u32 rn_val = RN; | ||
| 3692 | 3964 | ||
| 3693 | s32 lo_result = 0; | 3965 | TEQ_INST : { |
| 3694 | s32 hi_result = 0; | 3966 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 3967 | teq_inst* const inst_cream = (teq_inst*)inst_base->component; | ||
| 3695 | 3968 | ||
| 3696 | // UADD16 | 3969 | u32 lop = RN; |
| 3697 | if (op2 == 0x00) { | 3970 | u32 rop = SHIFTER_OPERAND; |
| 3698 | lo_result = (rn_val & 0xFFFF) + (rm_val & 0xFFFF); | ||
| 3699 | hi_result = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF); | ||
| 3700 | |||
| 3701 | if (lo_result & 0xFFFF0000) { | ||
| 3702 | cpu->Cpsr |= (1 << 16); | ||
| 3703 | cpu->Cpsr |= (1 << 17); | ||
| 3704 | } else { | ||
| 3705 | cpu->Cpsr &= ~(1 << 16); | ||
| 3706 | cpu->Cpsr &= ~(1 << 17); | ||
| 3707 | } | ||
| 3708 | 3971 | ||
| 3709 | if (hi_result & 0xFFFF0000) { | 3972 | if (inst_cream->Rn == 15) |
| 3710 | cpu->Cpsr |= (1 << 18); | 3973 | lop += cpu->GetInstructionSize() * 2; |
| 3711 | cpu->Cpsr |= (1 << 19); | ||
| 3712 | } else { | ||
| 3713 | cpu->Cpsr &= ~(1 << 18); | ||
| 3714 | cpu->Cpsr &= ~(1 << 19); | ||
| 3715 | } | ||
| 3716 | } | ||
| 3717 | // UASX | ||
| 3718 | else if (op2 == 0x01) { | ||
| 3719 | lo_result = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); | ||
| 3720 | hi_result = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF); | ||
| 3721 | |||
| 3722 | if (lo_result >= 0) { | ||
| 3723 | cpu->Cpsr |= (1 << 16); | ||
| 3724 | cpu->Cpsr |= (1 << 17); | ||
| 3725 | } else { | ||
| 3726 | cpu->Cpsr &= ~(1 << 16); | ||
| 3727 | cpu->Cpsr &= ~(1 << 17); | ||
| 3728 | } | ||
| 3729 | 3974 | ||
| 3730 | if (hi_result >= 0x10000) { | 3975 | u32 result = lop ^ rop; |
| 3731 | cpu->Cpsr |= (1 << 18); | ||
| 3732 | cpu->Cpsr |= (1 << 19); | ||
| 3733 | } else { | ||
| 3734 | cpu->Cpsr &= ~(1 << 18); | ||
| 3735 | cpu->Cpsr &= ~(1 << 19); | ||
| 3736 | } | ||
| 3737 | } | ||
| 3738 | // USAX | ||
| 3739 | else if (op2 == 0x02) { | ||
| 3740 | lo_result = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF); | ||
| 3741 | hi_result = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF); | ||
| 3742 | |||
| 3743 | if (lo_result >= 0x10000) { | ||
| 3744 | cpu->Cpsr |= (1 << 16); | ||
| 3745 | cpu->Cpsr |= (1 << 17); | ||
| 3746 | } else { | ||
| 3747 | cpu->Cpsr &= ~(1 << 16); | ||
| 3748 | cpu->Cpsr &= ~(1 << 17); | ||
| 3749 | } | ||
| 3750 | 3976 | ||
| 3751 | if (hi_result >= 0) { | 3977 | UPDATE_NFLAG(result); |
| 3752 | cpu->Cpsr |= (1 << 18); | 3978 | UPDATE_ZFLAG(result); |
| 3753 | cpu->Cpsr |= (1 << 19); | 3979 | UPDATE_CFLAG_WITH_SC; |
| 3754 | } else { | 3980 | } |
| 3755 | cpu->Cpsr &= ~(1 << 18); | 3981 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 3756 | cpu->Cpsr &= ~(1 << 19); | 3982 | INC_PC(sizeof(teq_inst)); |
| 3757 | } | 3983 | FETCH_INST; |
| 3758 | } | 3984 | GOTO_NEXT_INST; |
| 3759 | // USUB16 | 3985 | } |
| 3760 | else if (op2 == 0x03) { | 3986 | TST_INST : { |
| 3761 | lo_result = (rn_val & 0xFFFF) - (rm_val & 0xFFFF); | 3987 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 3762 | hi_result = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); | 3988 | tst_inst* const inst_cream = (tst_inst*)inst_base->component; |
| 3763 | |||
| 3764 | if ((lo_result & 0xFFFF0000) == 0) { | ||
| 3765 | cpu->Cpsr |= (1 << 16); | ||
| 3766 | cpu->Cpsr |= (1 << 17); | ||
| 3767 | } else { | ||
| 3768 | cpu->Cpsr &= ~(1 << 16); | ||
| 3769 | cpu->Cpsr &= ~(1 << 17); | ||
| 3770 | } | ||
| 3771 | 3989 | ||
| 3772 | if ((hi_result & 0xFFFF0000) == 0) { | 3990 | u32 lop = RN; |
| 3773 | cpu->Cpsr |= (1 << 18); | 3991 | u32 rop = SHIFTER_OPERAND; |
| 3774 | cpu->Cpsr |= (1 << 19); | ||
| 3775 | } else { | ||
| 3776 | cpu->Cpsr &= ~(1 << 18); | ||
| 3777 | cpu->Cpsr &= ~(1 << 19); | ||
| 3778 | } | ||
| 3779 | } | ||
| 3780 | // UADD8 | ||
| 3781 | else if (op2 == 0x04) { | ||
| 3782 | s16 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF); | ||
| 3783 | s16 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF); | ||
| 3784 | s16 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF); | ||
| 3785 | s16 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF); | ||
| 3786 | |||
| 3787 | if (sum1 >= 0x100) | ||
| 3788 | cpu->Cpsr |= (1 << 16); | ||
| 3789 | else | ||
| 3790 | cpu->Cpsr &= ~(1 << 16); | ||
| 3791 | 3992 | ||
| 3792 | if (sum2 >= 0x100) | 3993 | if (inst_cream->Rn == 15) |
| 3793 | cpu->Cpsr |= (1 << 17); | 3994 | lop += cpu->GetInstructionSize() * 2; |
| 3794 | else | ||
| 3795 | cpu->Cpsr &= ~(1 << 17); | ||
| 3796 | 3995 | ||
| 3797 | if (sum3 >= 0x100) | 3996 | u32 result = lop & rop; |
| 3798 | cpu->Cpsr |= (1 << 18); | ||
| 3799 | else | ||
| 3800 | cpu->Cpsr &= ~(1 << 18); | ||
| 3801 | 3997 | ||
| 3802 | if (sum4 >= 0x100) | 3998 | UPDATE_NFLAG(result); |
| 3803 | cpu->Cpsr |= (1 << 19); | 3999 | UPDATE_ZFLAG(result); |
| 3804 | else | 4000 | UPDATE_CFLAG_WITH_SC; |
| 3805 | cpu->Cpsr &= ~(1 << 19); | 4001 | } |
| 4002 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 4003 | INC_PC(sizeof(tst_inst)); | ||
| 4004 | FETCH_INST; | ||
| 4005 | GOTO_NEXT_INST; | ||
| 4006 | } | ||
| 3806 | 4007 | ||
| 3807 | lo_result = ((sum1 & 0xFF) | (sum2 & 0xFF) << 8); | 4008 | UADD8_INST: |
| 3808 | hi_result = ((sum3 & 0xFF) | (sum4 & 0xFF) << 8); | 4009 | UADD16_INST: |
| 4010 | UADDSUBX_INST: | ||
| 4011 | USUB8_INST: | ||
| 4012 | USUB16_INST: | ||
| 4013 | USUBADDX_INST : { | ||
| 4014 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 4015 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 4016 | |||
| 4017 | const u8 op2 = inst_cream->op2; | ||
| 4018 | const u32 rm_val = RM; | ||
| 4019 | const u32 rn_val = RN; | ||
| 4020 | |||
| 4021 | s32 lo_result = 0; | ||
| 4022 | s32 hi_result = 0; | ||
| 4023 | |||
| 4024 | // UADD16 | ||
| 4025 | if (op2 == 0x00) { | ||
| 4026 | lo_result = (rn_val & 0xFFFF) + (rm_val & 0xFFFF); | ||
| 4027 | hi_result = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF); | ||
| 4028 | |||
| 4029 | if (lo_result & 0xFFFF0000) { | ||
| 4030 | cpu->Cpsr |= (1 << 16); | ||
| 4031 | cpu->Cpsr |= (1 << 17); | ||
| 4032 | } else { | ||
| 4033 | cpu->Cpsr &= ~(1 << 16); | ||
| 4034 | cpu->Cpsr &= ~(1 << 17); | ||
| 3809 | } | 4035 | } |
| 3810 | // USUB8 | ||
| 3811 | else if (op2 == 0x07) { | ||
| 3812 | s16 diff1 = (rn_val & 0xFF) - (rm_val & 0xFF); | ||
| 3813 | s16 diff2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF); | ||
| 3814 | s16 diff3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF); | ||
| 3815 | s16 diff4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF); | ||
| 3816 | |||
| 3817 | if (diff1 >= 0) | ||
| 3818 | cpu->Cpsr |= (1 << 16); | ||
| 3819 | else | ||
| 3820 | cpu->Cpsr &= ~(1 << 16); | ||
| 3821 | 4036 | ||
| 3822 | if (diff2 >= 0) | 4037 | if (hi_result & 0xFFFF0000) { |
| 3823 | cpu->Cpsr |= (1 << 17); | 4038 | cpu->Cpsr |= (1 << 18); |
| 3824 | else | 4039 | cpu->Cpsr |= (1 << 19); |
| 3825 | cpu->Cpsr &= ~(1 << 17); | 4040 | } else { |
| 3826 | 4041 | cpu->Cpsr &= ~(1 << 18); | |
| 3827 | if (diff3 >= 0) | 4042 | cpu->Cpsr &= ~(1 << 19); |
| 3828 | cpu->Cpsr |= (1 << 18); | ||
| 3829 | else | ||
| 3830 | cpu->Cpsr &= ~(1 << 18); | ||
| 3831 | |||
| 3832 | if (diff4 >= 0) | ||
| 3833 | cpu->Cpsr |= (1 << 19); | ||
| 3834 | else | ||
| 3835 | cpu->Cpsr &= ~(1 << 19); | ||
| 3836 | |||
| 3837 | lo_result = (diff1 & 0xFF) | ((diff2 & 0xFF) << 8); | ||
| 3838 | hi_result = (diff3 & 0xFF) | ((diff4 & 0xFF) << 8); | ||
| 3839 | } | 4043 | } |
| 3840 | |||
| 3841 | RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); | ||
| 3842 | } | 4044 | } |
| 4045 | // UASX | ||
| 4046 | else if (op2 == 0x01) { | ||
| 4047 | lo_result = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); | ||
| 4048 | hi_result = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF); | ||
| 4049 | |||
| 4050 | if (lo_result >= 0) { | ||
| 4051 | cpu->Cpsr |= (1 << 16); | ||
| 4052 | cpu->Cpsr |= (1 << 17); | ||
| 4053 | } else { | ||
| 4054 | cpu->Cpsr &= ~(1 << 16); | ||
| 4055 | cpu->Cpsr &= ~(1 << 17); | ||
| 4056 | } | ||
| 3843 | 4057 | ||
| 3844 | cpu->Reg[15] += cpu->GetInstructionSize(); | 4058 | if (hi_result >= 0x10000) { |
| 3845 | INC_PC(sizeof(generic_arm_inst)); | 4059 | cpu->Cpsr |= (1 << 18); |
| 3846 | FETCH_INST; | 4060 | cpu->Cpsr |= (1 << 19); |
| 3847 | GOTO_NEXT_INST; | 4061 | } else { |
| 3848 | } | 4062 | cpu->Cpsr &= ~(1 << 18); |
| 3849 | 4063 | cpu->Cpsr &= ~(1 << 19); | |
| 3850 | UHADD8_INST: | 4064 | } |
| 3851 | UHADD16_INST: | 4065 | } |
| 3852 | UHADDSUBX_INST: | 4066 | // USAX |
| 3853 | UHSUBADDX_INST: | 4067 | else if (op2 == 0x02) { |
| 3854 | UHSUB8_INST: | 4068 | lo_result = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF); |
| 3855 | UHSUB16_INST: | 4069 | hi_result = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF); |
| 3856 | { | 4070 | |
| 3857 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 4071 | if (lo_result >= 0x10000) { |
| 3858 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | 4072 | cpu->Cpsr |= (1 << 16); |
| 3859 | const u32 rm_val = RM; | 4073 | cpu->Cpsr |= (1 << 17); |
| 3860 | const u32 rn_val = RN; | 4074 | } else { |
| 3861 | const u8 op2 = inst_cream->op2; | 4075 | cpu->Cpsr &= ~(1 << 16); |
| 3862 | 4076 | cpu->Cpsr &= ~(1 << 17); | |
| 3863 | if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) | ||
| 3864 | { | ||
| 3865 | u32 lo_val = 0; | ||
| 3866 | u32 hi_val = 0; | ||
| 3867 | |||
| 3868 | // UHADD16 | ||
| 3869 | if (op2 == 0x00) { | ||
| 3870 | lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF); | ||
| 3871 | hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF); | ||
| 3872 | } | ||
| 3873 | // UHASX | ||
| 3874 | else if (op2 == 0x01) { | ||
| 3875 | lo_val = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); | ||
| 3876 | hi_val = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF); | ||
| 3877 | } | ||
| 3878 | // UHSAX | ||
| 3879 | else if (op2 == 0x02) { | ||
| 3880 | lo_val = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF); | ||
| 3881 | hi_val = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF); | ||
| 3882 | } | ||
| 3883 | // UHSUB16 | ||
| 3884 | else if (op2 == 0x03) { | ||
| 3885 | lo_val = (rn_val & 0xFFFF) - (rm_val & 0xFFFF); | ||
| 3886 | hi_val = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); | ||
| 3887 | } | ||
| 3888 | |||
| 3889 | lo_val >>= 1; | ||
| 3890 | hi_val >>= 1; | ||
| 3891 | |||
| 3892 | RD = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16); | ||
| 3893 | } | 4077 | } |
| 3894 | else if (op2 == 0x04 || op2 == 0x07) { | ||
| 3895 | u32 sum1; | ||
| 3896 | u32 sum2; | ||
| 3897 | u32 sum3; | ||
| 3898 | u32 sum4; | ||
| 3899 | |||
| 3900 | // UHADD8 | ||
| 3901 | if (op2 == 0x04) { | ||
| 3902 | sum1 = (rn_val & 0xFF) + (rm_val & 0xFF); | ||
| 3903 | sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF); | ||
| 3904 | sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF); | ||
| 3905 | sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF); | ||
| 3906 | } | ||
| 3907 | // UHSUB8 | ||
| 3908 | else { | ||
| 3909 | sum1 = (rn_val & 0xFF) - (rm_val & 0xFF); | ||
| 3910 | sum2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF); | ||
| 3911 | sum3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF); | ||
| 3912 | sum4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF); | ||
| 3913 | } | ||
| 3914 | 4078 | ||
| 3915 | sum1 >>= 1; | 4079 | if (hi_result >= 0) { |
| 3916 | sum2 >>= 1; | 4080 | cpu->Cpsr |= (1 << 18); |
| 3917 | sum3 >>= 1; | 4081 | cpu->Cpsr |= (1 << 19); |
| 3918 | sum4 >>= 1; | 4082 | } else { |
| 4083 | cpu->Cpsr &= ~(1 << 18); | ||
| 4084 | cpu->Cpsr &= ~(1 << 19); | ||
| 4085 | } | ||
| 4086 | } | ||
| 4087 | // USUB16 | ||
| 4088 | else if (op2 == 0x03) { | ||
| 4089 | lo_result = (rn_val & 0xFFFF) - (rm_val & 0xFFFF); | ||
| 4090 | hi_result = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); | ||
| 4091 | |||
| 4092 | if ((lo_result & 0xFFFF0000) == 0) { | ||
| 4093 | cpu->Cpsr |= (1 << 16); | ||
| 4094 | cpu->Cpsr |= (1 << 17); | ||
| 4095 | } else { | ||
| 4096 | cpu->Cpsr &= ~(1 << 16); | ||
| 4097 | cpu->Cpsr &= ~(1 << 17); | ||
| 4098 | } | ||
| 3919 | 4099 | ||
| 3920 | RD = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) | ((sum4 & 0xFF) << 24); | 4100 | if ((hi_result & 0xFFFF0000) == 0) { |
| 4101 | cpu->Cpsr |= (1 << 18); | ||
| 4102 | cpu->Cpsr |= (1 << 19); | ||
| 4103 | } else { | ||
| 4104 | cpu->Cpsr &= ~(1 << 18); | ||
| 4105 | cpu->Cpsr &= ~(1 << 19); | ||
| 3921 | } | 4106 | } |
| 3922 | } | 4107 | } |
| 4108 | // UADD8 | ||
| 4109 | else if (op2 == 0x04) { | ||
| 4110 | s16 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF); | ||
| 4111 | s16 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF); | ||
| 4112 | s16 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF); | ||
| 4113 | s16 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF); | ||
| 4114 | |||
| 4115 | if (sum1 >= 0x100) | ||
| 4116 | cpu->Cpsr |= (1 << 16); | ||
| 4117 | else | ||
| 4118 | cpu->Cpsr &= ~(1 << 16); | ||
| 3923 | 4119 | ||
| 3924 | cpu->Reg[15] += cpu->GetInstructionSize(); | 4120 | if (sum2 >= 0x100) |
| 3925 | INC_PC(sizeof(generic_arm_inst)); | 4121 | cpu->Cpsr |= (1 << 17); |
| 3926 | FETCH_INST; | 4122 | else |
| 3927 | GOTO_NEXT_INST; | 4123 | cpu->Cpsr &= ~(1 << 17); |
| 3928 | } | ||
| 3929 | 4124 | ||
| 3930 | UMAAL_INST: | 4125 | if (sum3 >= 0x100) |
| 3931 | { | 4126 | cpu->Cpsr |= (1 << 18); |
| 3932 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 4127 | else |
| 3933 | umaal_inst* const inst_cream = (umaal_inst*)inst_base->component; | 4128 | cpu->Cpsr &= ~(1 << 18); |
| 3934 | const u64 rm = RM; | ||
| 3935 | const u64 rn = RN; | ||
| 3936 | const u64 rd_lo = RDLO; | ||
| 3937 | const u64 rd_hi = RDHI; | ||
| 3938 | const u64 result = (rm * rn) + rd_lo + rd_hi; | ||
| 3939 | 4129 | ||
| 3940 | RDLO = (result & 0xFFFFFFFF); | 4130 | if (sum4 >= 0x100) |
| 3941 | RDHI = ((result >> 32) & 0xFFFFFFFF); | 4131 | cpu->Cpsr |= (1 << 19); |
| 3942 | } | 4132 | else |
| 3943 | cpu->Reg[15] += cpu->GetInstructionSize(); | 4133 | cpu->Cpsr &= ~(1 << 19); |
| 3944 | INC_PC(sizeof(umaal_inst)); | 4134 | |
| 3945 | FETCH_INST; | 4135 | lo_result = ((sum1 & 0xFF) | (sum2 & 0xFF) << 8); |
| 3946 | GOTO_NEXT_INST; | 4136 | hi_result = ((sum3 & 0xFF) | (sum4 & 0xFF) << 8); |
| 3947 | } | ||
| 3948 | UMLAL_INST: | ||
| 3949 | { | ||
| 3950 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3951 | umlal_inst* inst_cream = (umlal_inst*)inst_base->component; | ||
| 3952 | unsigned long long int rm = RM; | ||
| 3953 | unsigned long long int rs = RS; | ||
| 3954 | unsigned long long int rst = rm * rs; | ||
| 3955 | unsigned long long int add = ((unsigned long long) RDHI)<<32; | ||
| 3956 | add += RDLO; | ||
| 3957 | rst += add; | ||
| 3958 | RDLO = BITS(rst, 0, 31); | ||
| 3959 | RDHI = BITS(rst, 32, 63); | ||
| 3960 | |||
| 3961 | if (inst_cream->S) { | ||
| 3962 | cpu->NFlag = BIT(RDHI, 31); | ||
| 3963 | cpu->ZFlag = (RDHI == 0 && RDLO == 0); | ||
| 3964 | } | ||
| 3965 | } | ||
| 3966 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 3967 | INC_PC(sizeof(umlal_inst)); | ||
| 3968 | FETCH_INST; | ||
| 3969 | GOTO_NEXT_INST; | ||
| 3970 | } | ||
| 3971 | UMULL_INST: | ||
| 3972 | { | ||
| 3973 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 3974 | umull_inst* inst_cream = (umull_inst*)inst_base->component; | ||
| 3975 | unsigned long long int rm = RM; | ||
| 3976 | unsigned long long int rs = RS; | ||
| 3977 | unsigned long long int rst = rm * rs; | ||
| 3978 | RDHI = BITS(rst, 32, 63); | ||
| 3979 | RDLO = BITS(rst, 0, 31); | ||
| 3980 | |||
| 3981 | if (inst_cream->S) { | ||
| 3982 | cpu->NFlag = BIT(RDHI, 31); | ||
| 3983 | cpu->ZFlag = (RDHI == 0 && RDLO == 0); | ||
| 3984 | } | ||
| 3985 | } | 4137 | } |
| 3986 | cpu->Reg[15] += cpu->GetInstructionSize(); | 4138 | // USUB8 |
| 3987 | INC_PC(sizeof(umull_inst)); | 4139 | else if (op2 == 0x07) { |
| 3988 | FETCH_INST; | 4140 | s16 diff1 = (rn_val & 0xFF) - (rm_val & 0xFF); |
| 3989 | GOTO_NEXT_INST; | 4141 | s16 diff2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF); |
| 3990 | } | 4142 | s16 diff3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF); |
| 3991 | B_2_THUMB: | 4143 | s16 diff4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF); |
| 3992 | { | 4144 | |
| 3993 | b_2_thumb* inst_cream = (b_2_thumb*)inst_base->component; | 4145 | if (diff1 >= 0) |
| 3994 | cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm; | 4146 | cpu->Cpsr |= (1 << 16); |
| 3995 | INC_PC(sizeof(b_2_thumb)); | 4147 | else |
| 3996 | goto DISPATCH; | 4148 | cpu->Cpsr &= ~(1 << 16); |
| 3997 | } | ||
| 3998 | B_COND_THUMB: | ||
| 3999 | { | ||
| 4000 | b_cond_thumb* inst_cream = (b_cond_thumb*)inst_base->component; | ||
| 4001 | 4149 | ||
| 4002 | if(CondPassed(cpu, inst_cream->cond)) | 4150 | if (diff2 >= 0) |
| 4003 | cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm; | 4151 | cpu->Cpsr |= (1 << 17); |
| 4004 | else | 4152 | else |
| 4005 | cpu->Reg[15] += 2; | 4153 | cpu->Cpsr &= ~(1 << 17); |
| 4006 | 4154 | ||
| 4007 | INC_PC(sizeof(b_cond_thumb)); | 4155 | if (diff3 >= 0) |
| 4008 | goto DISPATCH; | 4156 | cpu->Cpsr |= (1 << 18); |
| 4009 | } | 4157 | else |
| 4010 | BL_1_THUMB: | 4158 | cpu->Cpsr &= ~(1 << 18); |
| 4011 | { | ||
| 4012 | bl_1_thumb* inst_cream = (bl_1_thumb*)inst_base->component; | ||
| 4013 | cpu->Reg[14] = cpu->Reg[15] + 4 + inst_cream->imm; | ||
| 4014 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 4015 | INC_PC(sizeof(bl_1_thumb)); | ||
| 4016 | FETCH_INST; | ||
| 4017 | GOTO_NEXT_INST; | ||
| 4018 | } | ||
| 4019 | BL_2_THUMB: | ||
| 4020 | { | ||
| 4021 | bl_2_thumb* inst_cream = (bl_2_thumb*)inst_base->component; | ||
| 4022 | int tmp = ((cpu->Reg[15] + 2) | 1); | ||
| 4023 | cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm); | ||
| 4024 | cpu->Reg[14] = tmp; | ||
| 4025 | INC_PC(sizeof(bl_2_thumb)); | ||
| 4026 | goto DISPATCH; | ||
| 4027 | } | ||
| 4028 | BLX_1_THUMB: | ||
| 4029 | { | ||
| 4030 | // BLX 1 for armv5t and above | ||
| 4031 | u32 tmp = cpu->Reg[15]; | ||
| 4032 | blx_1_thumb* inst_cream = (blx_1_thumb*)inst_base->component; | ||
| 4033 | cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm) & 0xFFFFFFFC; | ||
| 4034 | cpu->Reg[14] = ((tmp + 2) | 1); | ||
| 4035 | cpu->TFlag = 0; | ||
| 4036 | INC_PC(sizeof(blx_1_thumb)); | ||
| 4037 | goto DISPATCH; | ||
| 4038 | } | ||
| 4039 | 4159 | ||
| 4040 | UQADD8_INST: | 4160 | if (diff4 >= 0) |
| 4041 | UQADD16_INST: | 4161 | cpu->Cpsr |= (1 << 19); |
| 4042 | UQADDSUBX_INST: | 4162 | else |
| 4043 | UQSUB8_INST: | 4163 | cpu->Cpsr &= ~(1 << 19); |
| 4044 | UQSUB16_INST: | ||
| 4045 | UQSUBADDX_INST: | ||
| 4046 | { | ||
| 4047 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 4048 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 4049 | 4164 | ||
| 4050 | const u8 op2 = inst_cream->op2; | 4165 | lo_result = (diff1 & 0xFF) | ((diff2 & 0xFF) << 8); |
| 4051 | const u32 rm_val = RM; | 4166 | hi_result = (diff3 & 0xFF) | ((diff4 & 0xFF) << 8); |
| 4052 | const u32 rn_val = RN; | 4167 | } |
| 4053 | 4168 | ||
| 4054 | u16 lo_val = 0; | 4169 | RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); |
| 4055 | u16 hi_val = 0; | 4170 | } |
| 4056 | 4171 | ||
| 4057 | // UQADD16 | 4172 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4173 | INC_PC(sizeof(generic_arm_inst)); | ||
| 4174 | FETCH_INST; | ||
| 4175 | GOTO_NEXT_INST; | ||
| 4176 | } | ||
| 4177 | |||
| 4178 | UHADD8_INST: | ||
| 4179 | UHADD16_INST: | ||
| 4180 | UHADDSUBX_INST: | ||
| 4181 | UHSUBADDX_INST: | ||
| 4182 | UHSUB8_INST: | ||
| 4183 | UHSUB16_INST : { | ||
| 4184 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 4185 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 4186 | const u32 rm_val = RM; | ||
| 4187 | const u32 rn_val = RN; | ||
| 4188 | const u8 op2 = inst_cream->op2; | ||
| 4189 | |||
| 4190 | if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) { | ||
| 4191 | u32 lo_val = 0; | ||
| 4192 | u32 hi_val = 0; | ||
| 4193 | |||
| 4194 | // UHADD16 | ||
| 4058 | if (op2 == 0x00) { | 4195 | if (op2 == 0x00) { |
| 4059 | lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF); | 4196 | lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF); |
| 4060 | hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); | 4197 | hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF); |
| 4061 | } | 4198 | } |
| 4062 | // UQASX | 4199 | // UHASX |
| 4063 | else if (op2 == 0x01) { | 4200 | else if (op2 == 0x01) { |
| 4064 | lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); | 4201 | lo_val = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); |
| 4065 | hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); | 4202 | hi_val = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF); |
| 4066 | } | 4203 | } |
| 4067 | // UQSAX | 4204 | // UHSAX |
| 4068 | else if (op2 == 0x02) { | 4205 | else if (op2 == 0x02) { |
| 4069 | lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); | 4206 | lo_val = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF); |
| 4070 | hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); | 4207 | hi_val = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF); |
| 4071 | } | 4208 | } |
| 4072 | // UQSUB16 | 4209 | // UHSUB16 |
| 4073 | else if (op2 == 0x03) { | 4210 | else if (op2 == 0x03) { |
| 4074 | lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF); | 4211 | lo_val = (rn_val & 0xFFFF) - (rm_val & 0xFFFF); |
| 4075 | hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); | 4212 | hi_val = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); |
| 4076 | } | 4213 | } |
| 4077 | // UQADD8 | 4214 | |
| 4078 | else if (op2 == 0x04) { | 4215 | lo_val >>= 1; |
| 4079 | lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) | | 4216 | hi_val >>= 1; |
| 4080 | ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8; | 4217 | |
| 4081 | hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) | | 4218 | RD = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16); |
| 4082 | ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8; | 4219 | } else if (op2 == 0x04 || op2 == 0x07) { |
| 4220 | u32 sum1; | ||
| 4221 | u32 sum2; | ||
| 4222 | u32 sum3; | ||
| 4223 | u32 sum4; | ||
| 4224 | |||
| 4225 | // UHADD8 | ||
| 4226 | if (op2 == 0x04) { | ||
| 4227 | sum1 = (rn_val & 0xFF) + (rm_val & 0xFF); | ||
| 4228 | sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF); | ||
| 4229 | sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF); | ||
| 4230 | sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF); | ||
| 4083 | } | 4231 | } |
| 4084 | // UQSUB8 | 4232 | // UHSUB8 |
| 4085 | else { | 4233 | else { |
| 4086 | lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) | | 4234 | sum1 = (rn_val & 0xFF) - (rm_val & 0xFF); |
| 4087 | ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8; | 4235 | sum2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF); |
| 4088 | hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) | | 4236 | sum3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF); |
| 4089 | ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8; | 4237 | sum4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF); |
| 4090 | } | 4238 | } |
| 4091 | 4239 | ||
| 4092 | RD = ((lo_val & 0xFFFF) | hi_val << 16); | 4240 | sum1 >>= 1; |
| 4241 | sum2 >>= 1; | ||
| 4242 | sum3 >>= 1; | ||
| 4243 | sum4 >>= 1; | ||
| 4244 | |||
| 4245 | RD = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) | | ||
| 4246 | ((sum4 & 0xFF) << 24); | ||
| 4093 | } | 4247 | } |
| 4248 | } | ||
| 4249 | |||
| 4250 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 4251 | INC_PC(sizeof(generic_arm_inst)); | ||
| 4252 | FETCH_INST; | ||
| 4253 | GOTO_NEXT_INST; | ||
| 4254 | } | ||
| 4094 | 4255 | ||
| 4095 | cpu->Reg[15] += cpu->GetInstructionSize(); | 4256 | UMAAL_INST : { |
| 4096 | INC_PC(sizeof(generic_arm_inst)); | 4257 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 4097 | FETCH_INST; | 4258 | umaal_inst* const inst_cream = (umaal_inst*)inst_base->component; |
| 4098 | GOTO_NEXT_INST; | 4259 | const u64 rm = RM; |
| 4260 | const u64 rn = RN; | ||
| 4261 | const u64 rd_lo = RDLO; | ||
| 4262 | const u64 rd_hi = RDHI; | ||
| 4263 | const u64 result = (rm * rn) + rd_lo + rd_hi; | ||
| 4264 | |||
| 4265 | RDLO = (result & 0xFFFFFFFF); | ||
| 4266 | RDHI = ((result >> 32) & 0xFFFFFFFF); | ||
| 4267 | } | ||
| 4268 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 4269 | INC_PC(sizeof(umaal_inst)); | ||
| 4270 | FETCH_INST; | ||
| 4271 | GOTO_NEXT_INST; | ||
| 4272 | } | ||
| 4273 | UMLAL_INST : { | ||
| 4274 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 4275 | umlal_inst* inst_cream = (umlal_inst*)inst_base->component; | ||
| 4276 | unsigned long long int rm = RM; | ||
| 4277 | unsigned long long int rs = RS; | ||
| 4278 | unsigned long long int rst = rm * rs; | ||
| 4279 | unsigned long long int add = ((unsigned long long)RDHI) << 32; | ||
| 4280 | add += RDLO; | ||
| 4281 | rst += add; | ||
| 4282 | RDLO = BITS(rst, 0, 31); | ||
| 4283 | RDHI = BITS(rst, 32, 63); | ||
| 4284 | |||
| 4285 | if (inst_cream->S) { | ||
| 4286 | cpu->NFlag = BIT(RDHI, 31); | ||
| 4287 | cpu->ZFlag = (RDHI == 0 && RDLO == 0); | ||
| 4288 | } | ||
| 4289 | } | ||
| 4290 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 4291 | INC_PC(sizeof(umlal_inst)); | ||
| 4292 | FETCH_INST; | ||
| 4293 | GOTO_NEXT_INST; | ||
| 4294 | } | ||
| 4295 | UMULL_INST : { | ||
| 4296 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 4297 | umull_inst* inst_cream = (umull_inst*)inst_base->component; | ||
| 4298 | unsigned long long int rm = RM; | ||
| 4299 | unsigned long long int rs = RS; | ||
| 4300 | unsigned long long int rst = rm * rs; | ||
| 4301 | RDHI = BITS(rst, 32, 63); | ||
| 4302 | RDLO = BITS(rst, 0, 31); | ||
| 4303 | |||
| 4304 | if (inst_cream->S) { | ||
| 4305 | cpu->NFlag = BIT(RDHI, 31); | ||
| 4306 | cpu->ZFlag = (RDHI == 0 && RDLO == 0); | ||
| 4307 | } | ||
| 4099 | } | 4308 | } |
| 4309 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 4310 | INC_PC(sizeof(umull_inst)); | ||
| 4311 | FETCH_INST; | ||
| 4312 | GOTO_NEXT_INST; | ||
| 4313 | } | ||
| 4314 | B_2_THUMB : { | ||
| 4315 | b_2_thumb* inst_cream = (b_2_thumb*)inst_base->component; | ||
| 4316 | cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm; | ||
| 4317 | INC_PC(sizeof(b_2_thumb)); | ||
| 4318 | goto DISPATCH; | ||
| 4319 | } | ||
| 4320 | B_COND_THUMB : { | ||
| 4321 | b_cond_thumb* inst_cream = (b_cond_thumb*)inst_base->component; | ||
| 4100 | 4322 | ||
| 4101 | USAD8_INST: | 4323 | if (CondPassed(cpu, inst_cream->cond)) |
| 4102 | USADA8_INST: | 4324 | cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm; |
| 4103 | { | 4325 | else |
| 4104 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 4326 | cpu->Reg[15] += 2; |
| 4105 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 4106 | 4327 | ||
| 4107 | const u8 ra_idx = inst_cream->Ra; | 4328 | INC_PC(sizeof(b_cond_thumb)); |
| 4108 | const u32 rm_val = RM; | 4329 | goto DISPATCH; |
| 4109 | const u32 rn_val = RN; | 4330 | } |
| 4331 | BL_1_THUMB : { | ||
| 4332 | bl_1_thumb* inst_cream = (bl_1_thumb*)inst_base->component; | ||
| 4333 | cpu->Reg[14] = cpu->Reg[15] + 4 + inst_cream->imm; | ||
| 4334 | cpu->Reg[15] += cpu->GetInstructionSize(); | ||
| 4335 | INC_PC(sizeof(bl_1_thumb)); | ||
| 4336 | FETCH_INST; | ||
| 4337 | GOTO_NEXT_INST; | ||
| 4338 | } | ||
| 4339 | BL_2_THUMB : { | ||
| 4340 | bl_2_thumb* inst_cream = (bl_2_thumb*)inst_base->component; | ||
| 4341 | int tmp = ((cpu->Reg[15] + 2) | 1); | ||
| 4342 | cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm); | ||
| 4343 | cpu->Reg[14] = tmp; | ||
| 4344 | INC_PC(sizeof(bl_2_thumb)); | ||
| 4345 | goto DISPATCH; | ||
| 4346 | } | ||
| 4347 | BLX_1_THUMB : { | ||
| 4348 | // BLX 1 for armv5t and above | ||
| 4349 | u32 tmp = cpu->Reg[15]; | ||
| 4350 | blx_1_thumb* inst_cream = (blx_1_thumb*)inst_base->component; | ||
| 4351 | cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm) & 0xFFFFFFFC; | ||
| 4352 | cpu->Reg[14] = ((tmp + 2) | 1); | ||
| 4353 | cpu->TFlag = 0; | ||
| 4354 | INC_PC(sizeof(blx_1_thumb)); | ||
| 4355 | goto DISPATCH; | ||
| 4356 | } | ||
| 4110 | 4357 | ||
| 4111 | const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF); | 4358 | UQADD8_INST: |
| 4112 | const u8 diff2 = ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF); | 4359 | UQADD16_INST: |
| 4113 | const u8 diff3 = ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF); | 4360 | UQADDSUBX_INST: |
| 4114 | const u8 diff4 = ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF); | 4361 | UQSUB8_INST: |
| 4362 | UQSUB16_INST: | ||
| 4363 | UQSUBADDX_INST : { | ||
| 4364 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | ||
| 4365 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 4366 | |||
| 4367 | const u8 op2 = inst_cream->op2; | ||
| 4368 | const u32 rm_val = RM; | ||
| 4369 | const u32 rn_val = RN; | ||
| 4370 | |||
| 4371 | u16 lo_val = 0; | ||
| 4372 | u16 hi_val = 0; | ||
| 4373 | |||
| 4374 | // UQADD16 | ||
| 4375 | if (op2 == 0x00) { | ||
| 4376 | lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF); | ||
| 4377 | hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); | ||
| 4378 | } | ||
| 4379 | // UQASX | ||
| 4380 | else if (op2 == 0x01) { | ||
| 4381 | lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); | ||
| 4382 | hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); | ||
| 4383 | } | ||
| 4384 | // UQSAX | ||
| 4385 | else if (op2 == 0x02) { | ||
| 4386 | lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); | ||
| 4387 | hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); | ||
| 4388 | } | ||
| 4389 | // UQSUB16 | ||
| 4390 | else if (op2 == 0x03) { | ||
| 4391 | lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF); | ||
| 4392 | hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); | ||
| 4393 | } | ||
| 4394 | // UQADD8 | ||
| 4395 | else if (op2 == 0x04) { | ||
| 4396 | lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) | | ||
| 4397 | ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8; | ||
| 4398 | hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) | | ||
| 4399 | ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8; | ||
| 4400 | } | ||
| 4401 | // UQSUB8 | ||
| 4402 | else { | ||
| 4403 | lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) | | ||
| 4404 | ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8; | ||
| 4405 | hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) | | ||
| 4406 | ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8; | ||
| 4407 | } | ||
| 4408 | |||
| 4409 | RD = ((lo_val & 0xFFFF) | hi_val << 16); | ||
| 4410 | } | ||
| 4115 | 4411 | ||
| 4116 | u32 finalDif = (diff1 + diff2 + diff3 + diff4); | 4412 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4413 | INC_PC(sizeof(generic_arm_inst)); | ||
| 4414 | FETCH_INST; | ||
| 4415 | GOTO_NEXT_INST; | ||
| 4416 | } | ||
| 4117 | 4417 | ||
| 4118 | // Op is USADA8 if true. | 4418 | USAD8_INST: |
| 4119 | if (ra_idx != 15) | 4419 | USADA8_INST : { |
| 4120 | finalDif += cpu->Reg[ra_idx]; | 4420 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 4421 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 4121 | 4422 | ||
| 4122 | RD = finalDif; | 4423 | const u8 ra_idx = inst_cream->Ra; |
| 4123 | } | 4424 | const u32 rm_val = RM; |
| 4425 | const u32 rn_val = RN; | ||
| 4426 | |||
| 4427 | const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF); | ||
| 4428 | const u8 diff2 = | ||
| 4429 | ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF); | ||
| 4430 | const u8 diff3 = | ||
| 4431 | ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF); | ||
| 4432 | const u8 diff4 = | ||
| 4433 | ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF); | ||
| 4124 | 4434 | ||
| 4125 | cpu->Reg[15] += cpu->GetInstructionSize(); | 4435 | u32 finalDif = (diff1 + diff2 + diff3 + diff4); |
| 4126 | INC_PC(sizeof(generic_arm_inst)); | 4436 | |
| 4127 | FETCH_INST; | 4437 | // Op is USADA8 if true. |
| 4128 | GOTO_NEXT_INST; | 4438 | if (ra_idx != 15) |
| 4439 | finalDif += cpu->Reg[ra_idx]; | ||
| 4440 | |||
| 4441 | RD = finalDif; | ||
| 4129 | } | 4442 | } |
| 4130 | 4443 | ||
| 4131 | USAT_INST: | 4444 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4132 | { | 4445 | INC_PC(sizeof(generic_arm_inst)); |
| 4133 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 4446 | FETCH_INST; |
| 4134 | ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; | 4447 | GOTO_NEXT_INST; |
| 4448 | } | ||
| 4135 | 4449 | ||
| 4136 | u8 shift_type = inst_cream->shift_type; | 4450 | USAT_INST : { |
| 4137 | u8 shift_amount = inst_cream->imm5; | 4451 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 4138 | u32 rn_val = RN; | 4452 | ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; |
| 4139 | 4453 | ||
| 4140 | // 32-bit ASR is encoded as an amount of 0. | 4454 | u8 shift_type = inst_cream->shift_type; |
| 4141 | if (shift_type == 1 && shift_amount == 0) | 4455 | u8 shift_amount = inst_cream->imm5; |
| 4142 | shift_amount = 31; | 4456 | u32 rn_val = RN; |
| 4143 | 4457 | ||
| 4144 | if (shift_type == 0) | 4458 | // 32-bit ASR is encoded as an amount of 0. |
| 4145 | rn_val <<= shift_amount; | 4459 | if (shift_type == 1 && shift_amount == 0) |
| 4146 | else if (shift_type == 1) | 4460 | shift_amount = 31; |
| 4147 | rn_val = ((s32)rn_val >> shift_amount); | ||
| 4148 | 4461 | ||
| 4149 | bool saturated = false; | 4462 | if (shift_type == 0) |
| 4150 | rn_val = ARMul_UnsignedSatQ(rn_val, inst_cream->sat_imm, &saturated); | 4463 | rn_val <<= shift_amount; |
| 4464 | else if (shift_type == 1) | ||
| 4465 | rn_val = ((s32)rn_val >> shift_amount); | ||
| 4151 | 4466 | ||
| 4152 | if (saturated) | 4467 | bool saturated = false; |
| 4153 | cpu->Cpsr |= (1 << 27); | 4468 | rn_val = ARMul_UnsignedSatQ(rn_val, inst_cream->sat_imm, &saturated); |
| 4154 | 4469 | ||
| 4155 | RD = rn_val; | 4470 | if (saturated) |
| 4156 | } | 4471 | cpu->Cpsr |= (1 << 27); |
| 4157 | 4472 | ||
| 4158 | cpu->Reg[15] += cpu->GetInstructionSize(); | 4473 | RD = rn_val; |
| 4159 | INC_PC(sizeof(ssat_inst)); | ||
| 4160 | FETCH_INST; | ||
| 4161 | GOTO_NEXT_INST; | ||
| 4162 | } | 4474 | } |
| 4163 | 4475 | ||
| 4164 | USAT16_INST: | 4476 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4165 | { | 4477 | INC_PC(sizeof(ssat_inst)); |
| 4166 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 4478 | FETCH_INST; |
| 4167 | ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; | 4479 | GOTO_NEXT_INST; |
| 4168 | const u8 saturate_to = inst_cream->sat_imm; | 4480 | } |
| 4169 | 4481 | ||
| 4170 | bool sat1 = false; | 4482 | USAT16_INST : { |
| 4171 | bool sat2 = false; | 4483 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 4484 | ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; | ||
| 4485 | const u8 saturate_to = inst_cream->sat_imm; | ||
| 4172 | 4486 | ||
| 4173 | RD = (ARMul_UnsignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) | | 4487 | bool sat1 = false; |
| 4174 | ARMul_UnsignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16; | 4488 | bool sat2 = false; |
| 4175 | 4489 | ||
| 4176 | if (sat1 || sat2) | 4490 | RD = (ARMul_UnsignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) | |
| 4177 | cpu->Cpsr |= (1 << 27); | 4491 | ARMul_UnsignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16; |
| 4178 | } | ||
| 4179 | 4492 | ||
| 4180 | cpu->Reg[15] += cpu->GetInstructionSize(); | 4493 | if (sat1 || sat2) |
| 4181 | INC_PC(sizeof(ssat_inst)); | 4494 | cpu->Cpsr |= (1 << 27); |
| 4182 | FETCH_INST; | ||
| 4183 | GOTO_NEXT_INST; | ||
| 4184 | } | 4495 | } |
| 4185 | 4496 | ||
| 4186 | UXTAB16_INST: | 4497 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4187 | UXTB16_INST: | 4498 | INC_PC(sizeof(ssat_inst)); |
| 4188 | { | 4499 | FETCH_INST; |
| 4189 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 4500 | GOTO_NEXT_INST; |
| 4190 | uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component; | 4501 | } |
| 4191 | 4502 | ||
| 4192 | const u8 rn_idx = inst_cream->Rn; | 4503 | UXTAB16_INST: |
| 4193 | const u32 rm_val = RM; | 4504 | UXTB16_INST : { |
| 4194 | const u32 rotation = inst_cream->rotate * 8; | 4505 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 4195 | const u32 rotated_rm = ((rm_val << (32 - rotation)) | (rm_val >> rotation)); | 4506 | uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component; |
| 4196 | 4507 | ||
| 4197 | // UXTB16, otherwise UXTAB16 | 4508 | const u8 rn_idx = inst_cream->Rn; |
| 4198 | if (rn_idx == 15) { | 4509 | const u32 rm_val = RM; |
| 4199 | RD = rotated_rm & 0x00FF00FF; | 4510 | const u32 rotation = inst_cream->rotate * 8; |
| 4200 | } else { | 4511 | const u32 rotated_rm = ((rm_val << (32 - rotation)) | (rm_val >> rotation)); |
| 4201 | const u32 rn_val = RN; | ||
| 4202 | const u8 lo_rotated = (rotated_rm & 0xFF); | ||
| 4203 | const u16 lo_result = (rn_val & 0xFFFF) + (u16)lo_rotated; | ||
| 4204 | const u8 hi_rotated = (rotated_rm >> 16) & 0xFF; | ||
| 4205 | const u16 hi_result = (rn_val >> 16) + (u16)hi_rotated; | ||
| 4206 | 4512 | ||
| 4207 | RD = ((hi_result << 16) | (lo_result & 0xFFFF)); | 4513 | // UXTB16, otherwise UXTAB16 |
| 4208 | } | 4514 | if (rn_idx == 15) { |
| 4209 | } | 4515 | RD = rotated_rm & 0x00FF00FF; |
| 4516 | } else { | ||
| 4517 | const u32 rn_val = RN; | ||
| 4518 | const u8 lo_rotated = (rotated_rm & 0xFF); | ||
| 4519 | const u16 lo_result = (rn_val & 0xFFFF) + (u16)lo_rotated; | ||
| 4520 | const u8 hi_rotated = (rotated_rm >> 16) & 0xFF; | ||
| 4521 | const u16 hi_result = (rn_val >> 16) + (u16)hi_rotated; | ||
| 4210 | 4522 | ||
| 4211 | cpu->Reg[15] += cpu->GetInstructionSize(); | 4523 | RD = ((hi_result << 16) | (lo_result & 0xFFFF)); |
| 4212 | INC_PC(sizeof(uxtab_inst)); | 4524 | } |
| 4213 | FETCH_INST; | ||
| 4214 | GOTO_NEXT_INST; | ||
| 4215 | } | 4525 | } |
| 4216 | 4526 | ||
| 4217 | WFE_INST: | 4527 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4218 | { | 4528 | INC_PC(sizeof(uxtab_inst)); |
| 4219 | // Stubbed, as WFE is a hint instruction. | 4529 | FETCH_INST; |
| 4220 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 4530 | GOTO_NEXT_INST; |
| 4221 | LOG_TRACE(Core_ARM11, "WFE executed."); | 4531 | } |
| 4222 | } | ||
| 4223 | 4532 | ||
| 4224 | cpu->Reg[15] += cpu->GetInstructionSize(); | 4533 | WFE_INST : { |
| 4225 | INC_PC_STUB; | 4534 | // Stubbed, as WFE is a hint instruction. |
| 4226 | FETCH_INST; | 4535 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 4227 | GOTO_NEXT_INST; | 4536 | LOG_TRACE(Core_ARM11, "WFE executed."); |
| 4228 | } | 4537 | } |
| 4229 | 4538 | ||
| 4230 | WFI_INST: | 4539 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4231 | { | 4540 | INC_PC_STUB; |
| 4232 | // Stubbed, as WFI is a hint instruction. | 4541 | FETCH_INST; |
| 4233 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 4542 | GOTO_NEXT_INST; |
| 4234 | LOG_TRACE(Core_ARM11, "WFI executed."); | 4543 | } |
| 4235 | } | ||
| 4236 | 4544 | ||
| 4237 | cpu->Reg[15] += cpu->GetInstructionSize(); | 4545 | WFI_INST : { |
| 4238 | INC_PC_STUB; | 4546 | // Stubbed, as WFI is a hint instruction. |
| 4239 | FETCH_INST; | 4547 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 4240 | GOTO_NEXT_INST; | 4548 | LOG_TRACE(Core_ARM11, "WFI executed."); |
| 4241 | } | 4549 | } |
| 4242 | 4550 | ||
| 4243 | YIELD_INST: | 4551 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4244 | { | 4552 | INC_PC_STUB; |
| 4245 | // Stubbed, as YIELD is a hint instruction. | 4553 | FETCH_INST; |
| 4246 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 4554 | GOTO_NEXT_INST; |
| 4247 | LOG_TRACE(Core_ARM11, "YIELD executed."); | 4555 | } |
| 4248 | } | ||
| 4249 | 4556 | ||
| 4250 | cpu->Reg[15] += cpu->GetInstructionSize(); | 4557 | YIELD_INST : { |
| 4251 | INC_PC_STUB; | 4558 | // Stubbed, as YIELD is a hint instruction. |
| 4252 | FETCH_INST; | 4559 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 4253 | GOTO_NEXT_INST; | 4560 | LOG_TRACE(Core_ARM11, "YIELD executed."); |
| 4254 | } | 4561 | } |
| 4255 | 4562 | ||
| 4256 | #define VFP_INTERPRETER_IMPL | 4563 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 4257 | #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" | 4564 | INC_PC_STUB; |
| 4258 | #undef VFP_INTERPRETER_IMPL | 4565 | FETCH_INST; |
| 4566 | GOTO_NEXT_INST; | ||
| 4567 | } | ||
| 4259 | 4568 | ||
| 4260 | END: | 4569 | #define VFP_INTERPRETER_IMPL |
| 4261 | { | 4570 | #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" |
| 4262 | SAVE_NZCVT; | 4571 | #undef VFP_INTERPRETER_IMPL |
| 4263 | cpu->NumInstrsToExecute = 0; | 4572 | |
| 4264 | return num_instrs; | 4573 | END : { |
| 4265 | } | 4574 | SAVE_NZCVT; |
| 4266 | INIT_INST_LENGTH: | 4575 | cpu->NumInstrsToExecute = 0; |
| 4267 | { | 4576 | return num_instrs; |
| 4268 | cpu->NumInstrsToExecute = 0; | 4577 | } |
| 4269 | return num_instrs; | 4578 | INIT_INST_LENGTH : { |
| 4270 | } | 4579 | cpu->NumInstrsToExecute = 0; |
| 4580 | return num_instrs; | ||
| 4581 | } | ||
| 4271 | } | 4582 | } |
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.cpp b/src/core/arm/dyncom/arm_dyncom_thumb.cpp index 3576370d1..2a3dd0f53 100644 --- a/src/core/arm/dyncom/arm_dyncom_thumb.cpp +++ b/src/core/arm/dyncom/arm_dyncom_thumb.cpp | |||
| @@ -21,50 +21,48 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3 | |||
| 21 | *ainstr = 0xDEADC0DE; // Debugging to catch non updates | 21 | *ainstr = 0xDEADC0DE; // Debugging to catch non updates |
| 22 | 22 | ||
| 23 | switch ((tinstr & 0xF800) >> 11) { | 23 | switch ((tinstr & 0xF800) >> 11) { |
| 24 | case 0: // LSL | 24 | case 0: // LSL |
| 25 | case 1: // LSR | 25 | case 1: // LSR |
| 26 | case 2: // ASR | 26 | case 2: // ASR |
| 27 | *ainstr = 0xE1B00000 // base opcode | 27 | *ainstr = 0xE1B00000 // base opcode |
| 28 | | ((tinstr & 0x1800) >> (11 - 5)) // shift type | 28 | | ((tinstr & 0x1800) >> (11 - 5)) // shift type |
| 29 | |((tinstr & 0x07C0) << (7 - 6)) // imm5 | 29 | | ((tinstr & 0x07C0) << (7 - 6)) // imm5 |
| 30 | |((tinstr & 0x0038) >> 3) // Rs | 30 | | ((tinstr & 0x0038) >> 3) // Rs |
| 31 | |((tinstr & 0x0007) << 12); // Rd | 31 | | ((tinstr & 0x0007) << 12); // Rd |
| 32 | break; | 32 | break; |
| 33 | 33 | ||
| 34 | case 3: // ADD/SUB | 34 | case 3: // ADD/SUB |
| 35 | { | 35 | { |
| 36 | static const u32 subset[4] = { | 36 | static const u32 subset[4] = { |
| 37 | 0xE0900000, // ADDS Rd,Rs,Rn | 37 | 0xE0900000, // ADDS Rd,Rs,Rn |
| 38 | 0xE0500000, // SUBS Rd,Rs,Rn | 38 | 0xE0500000, // SUBS Rd,Rs,Rn |
| 39 | 0xE2900000, // ADDS Rd,Rs,#imm3 | 39 | 0xE2900000, // ADDS Rd,Rs,#imm3 |
| 40 | 0xE2500000 // SUBS Rd,Rs,#imm3 | 40 | 0xE2500000 // SUBS Rd,Rs,#imm3 |
| 41 | }; | 41 | }; |
| 42 | // It is quicker indexing into a table, than performing switch or conditionals: | 42 | // It is quicker indexing into a table, than performing switch or conditionals: |
| 43 | *ainstr = subset[(tinstr & 0x0600) >> 9] // base opcode | 43 | *ainstr = subset[(tinstr & 0x0600) >> 9] // base opcode |
| 44 | |((tinstr & 0x01C0) >> 6) // Rn or imm3 | 44 | | ((tinstr & 0x01C0) >> 6) // Rn or imm3 |
| 45 | |((tinstr & 0x0038) << (16 - 3)) // Rs | 45 | | ((tinstr & 0x0038) << (16 - 3)) // Rs |
| 46 | |((tinstr & 0x0007) << (12 - 0)); // Rd | 46 | | ((tinstr & 0x0007) << (12 - 0)); // Rd |
| 47 | } | 47 | } break; |
| 48 | break; | ||
| 49 | 48 | ||
| 50 | case 4: // MOV | 49 | case 4: // MOV |
| 51 | case 5: // CMP | 50 | case 5: // CMP |
| 52 | case 6: // ADD | 51 | case 6: // ADD |
| 53 | case 7: // SUB | 52 | case 7: // SUB |
| 54 | { | 53 | { |
| 55 | static const u32 subset[4] = { | 54 | static const u32 subset[4] = { |
| 56 | 0xE3B00000, // MOVS Rd,#imm8 | 55 | 0xE3B00000, // MOVS Rd,#imm8 |
| 57 | 0xE3500000, // CMP Rd,#imm8 | 56 | 0xE3500000, // CMP Rd,#imm8 |
| 58 | 0xE2900000, // ADDS Rd,Rd,#imm8 | 57 | 0xE2900000, // ADDS Rd,Rd,#imm8 |
| 59 | 0xE2500000, // SUBS Rd,Rd,#imm8 | 58 | 0xE2500000, // SUBS Rd,Rd,#imm8 |
| 60 | }; | 59 | }; |
| 61 | 60 | ||
| 62 | *ainstr = subset[(tinstr & 0x1800) >> 11] // base opcode | 61 | *ainstr = subset[(tinstr & 0x1800) >> 11] // base opcode |
| 63 | |((tinstr & 0x00FF) >> 0) // imm8 | 62 | | ((tinstr & 0x00FF) >> 0) // imm8 |
| 64 | |((tinstr & 0x0700) << (16 - 8)) // Rn | 63 | | ((tinstr & 0x0700) << (16 - 8)) // Rn |
| 65 | |((tinstr & 0x0700) << (12 - 8)); // Rd | 64 | | ((tinstr & 0x0700) << (12 - 8)); // Rd |
| 66 | } | 65 | } break; |
| 67 | break; | ||
| 68 | 66 | ||
| 69 | case 8: // Arithmetic and high register transfers | 67 | case 8: // Arithmetic and high register transfers |
| 70 | 68 | ||
| @@ -73,56 +71,51 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3 | |||
| 73 | // large subset | 71 | // large subset |
| 74 | 72 | ||
| 75 | if ((tinstr & (1 << 10)) == 0) { | 73 | if ((tinstr & (1 << 10)) == 0) { |
| 76 | enum otype { | 74 | enum otype { t_norm, t_shift, t_neg, t_mul }; |
| 77 | t_norm, | ||
| 78 | t_shift, | ||
| 79 | t_neg, | ||
| 80 | t_mul | ||
| 81 | }; | ||
| 82 | 75 | ||
| 83 | static const struct { | 76 | static const struct { |
| 84 | u32 opcode; | 77 | u32 opcode; |
| 85 | otype type; | 78 | otype type; |
| 86 | } subset[16] = { | 79 | } subset[16] = { |
| 87 | { 0xE0100000, t_norm }, // ANDS Rd,Rd,Rs | 80 | {0xE0100000, t_norm}, // ANDS Rd,Rd,Rs |
| 88 | { 0xE0300000, t_norm }, // EORS Rd,Rd,Rs | 81 | {0xE0300000, t_norm}, // EORS Rd,Rd,Rs |
| 89 | { 0xE1B00010, t_shift }, // MOVS Rd,Rd,LSL Rs | 82 | {0xE1B00010, t_shift}, // MOVS Rd,Rd,LSL Rs |
| 90 | { 0xE1B00030, t_shift }, // MOVS Rd,Rd,LSR Rs | 83 | {0xE1B00030, t_shift}, // MOVS Rd,Rd,LSR Rs |
| 91 | { 0xE1B00050, t_shift }, // MOVS Rd,Rd,ASR Rs | 84 | {0xE1B00050, t_shift}, // MOVS Rd,Rd,ASR Rs |
| 92 | { 0xE0B00000, t_norm }, // ADCS Rd,Rd,Rs | 85 | {0xE0B00000, t_norm}, // ADCS Rd,Rd,Rs |
| 93 | { 0xE0D00000, t_norm }, // SBCS Rd,Rd,Rs | 86 | {0xE0D00000, t_norm}, // SBCS Rd,Rd,Rs |
| 94 | { 0xE1B00070, t_shift }, // MOVS Rd,Rd,ROR Rs | 87 | {0xE1B00070, t_shift}, // MOVS Rd,Rd,ROR Rs |
| 95 | { 0xE1100000, t_norm }, // TST Rd,Rs | 88 | {0xE1100000, t_norm}, // TST Rd,Rs |
| 96 | { 0xE2700000, t_neg }, // RSBS Rd,Rs,#0 | 89 | {0xE2700000, t_neg}, // RSBS Rd,Rs,#0 |
| 97 | { 0xE1500000, t_norm }, // CMP Rd,Rs | 90 | {0xE1500000, t_norm}, // CMP Rd,Rs |
| 98 | { 0xE1700000, t_norm }, // CMN Rd,Rs | 91 | {0xE1700000, t_norm}, // CMN Rd,Rs |
| 99 | { 0xE1900000, t_norm }, // ORRS Rd,Rd,Rs | 92 | {0xE1900000, t_norm}, // ORRS Rd,Rd,Rs |
| 100 | { 0xE0100090, t_mul }, // MULS Rd,Rd,Rs | 93 | {0xE0100090, t_mul}, // MULS Rd,Rd,Rs |
| 101 | { 0xE1D00000, t_norm }, // BICS Rd,Rd,Rs | 94 | {0xE1D00000, t_norm}, // BICS Rd,Rd,Rs |
| 102 | { 0xE1F00000, t_norm } // MVNS Rd,Rs | 95 | {0xE1F00000, t_norm} // MVNS Rd,Rs |
| 103 | }; | 96 | }; |
| 104 | 97 | ||
| 105 | *ainstr = subset[(tinstr & 0x03C0) >> 6].opcode; // base | 98 | *ainstr = subset[(tinstr & 0x03C0) >> 6].opcode; // base |
| 106 | 99 | ||
| 107 | switch (subset[(tinstr & 0x03C0) >> 6].type) { | 100 | switch (subset[(tinstr & 0x03C0) >> 6].type) { |
| 108 | case t_norm: | 101 | case t_norm: |
| 109 | *ainstr |= ((tinstr & 0x0007) << 16) // Rn | 102 | *ainstr |= ((tinstr & 0x0007) << 16) // Rn |
| 110 | |((tinstr & 0x0007) << 12) // Rd | 103 | | ((tinstr & 0x0007) << 12) // Rd |
| 111 | |((tinstr & 0x0038) >> 3); // Rs | 104 | | ((tinstr & 0x0038) >> 3); // Rs |
| 112 | break; | 105 | break; |
| 113 | case t_shift: | 106 | case t_shift: |
| 114 | *ainstr |= ((tinstr & 0x0007) << 12) // Rd | 107 | *ainstr |= ((tinstr & 0x0007) << 12) // Rd |
| 115 | |((tinstr & 0x0007) >> 0) // Rm | 108 | | ((tinstr & 0x0007) >> 0) // Rm |
| 116 | |((tinstr & 0x0038) << (8 - 3)); // Rs | 109 | | ((tinstr & 0x0038) << (8 - 3)); // Rs |
| 117 | break; | 110 | break; |
| 118 | case t_neg: | 111 | case t_neg: |
| 119 | *ainstr |= ((tinstr & 0x0007) << 12) // Rd | 112 | *ainstr |= ((tinstr & 0x0007) << 12) // Rd |
| 120 | |((tinstr & 0x0038) << (16 - 3)); // Rn | 113 | | ((tinstr & 0x0038) << (16 - 3)); // Rn |
| 121 | break; | 114 | break; |
| 122 | case t_mul: | 115 | case t_mul: |
| 123 | *ainstr |= ((tinstr & 0x0007) << 16) // Rd | 116 | *ainstr |= ((tinstr & 0x0007) << 16) // Rd |
| 124 | |((tinstr & 0x0007) << 8) // Rs | 117 | | ((tinstr & 0x0007) << 8) // Rs |
| 125 | |((tinstr & 0x0038) >> 3); // Rm | 118 | | ((tinstr & 0x0038) >> 3); // Rm |
| 126 | break; | 119 | break; |
| 127 | } | 120 | } |
| 128 | } else { | 121 | } else { |
| @@ -133,109 +126,106 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3 | |||
| 133 | Rd += 8; | 126 | Rd += 8; |
| 134 | 127 | ||
| 135 | switch ((tinstr & 0x03C0) >> 6) { | 128 | switch ((tinstr & 0x03C0) >> 6) { |
| 136 | case 0x0: // ADD Rd,Rd,Rs | 129 | case 0x0: // ADD Rd,Rd,Rs |
| 137 | case 0x1: // ADD Rd,Rd,Hs | 130 | case 0x1: // ADD Rd,Rd,Hs |
| 138 | case 0x2: // ADD Hd,Hd,Rs | 131 | case 0x2: // ADD Hd,Hd,Rs |
| 139 | case 0x3: // ADD Hd,Hd,Hs | 132 | case 0x3: // ADD Hd,Hd,Hs |
| 140 | *ainstr = 0xE0800000 // base | 133 | *ainstr = 0xE0800000 // base |
| 141 | | (Rd << 16) // Rn | 134 | | (Rd << 16) // Rn |
| 142 | |(Rd << 12) // Rd | 135 | | (Rd << 12) // Rd |
| 143 | |(Rs << 0); // Rm | 136 | | (Rs << 0); // Rm |
| 144 | break; | 137 | break; |
| 145 | case 0x4: // CMP Rd,Rs | 138 | case 0x4: // CMP Rd,Rs |
| 146 | case 0x5: // CMP Rd,Hs | 139 | case 0x5: // CMP Rd,Hs |
| 147 | case 0x6: // CMP Hd,Rs | 140 | case 0x6: // CMP Hd,Rs |
| 148 | case 0x7: // CMP Hd,Hs | 141 | case 0x7: // CMP Hd,Hs |
| 149 | *ainstr = 0xE1500000 // base | 142 | *ainstr = 0xE1500000 // base |
| 150 | | (Rd << 16) // Rn | 143 | | (Rd << 16) // Rn |
| 151 | |(Rs << 0); // Rm | 144 | | (Rs << 0); // Rm |
| 152 | break; | 145 | break; |
| 153 | case 0x8: // MOV Rd,Rs | 146 | case 0x8: // MOV Rd,Rs |
| 154 | case 0x9: // MOV Rd,Hs | 147 | case 0x9: // MOV Rd,Hs |
| 155 | case 0xA: // MOV Hd,Rs | 148 | case 0xA: // MOV Hd,Rs |
| 156 | case 0xB: // MOV Hd,Hs | 149 | case 0xB: // MOV Hd,Hs |
| 157 | *ainstr = 0xE1A00000 // base | 150 | *ainstr = 0xE1A00000 // base |
| 158 | |(Rd << 12) // Rd | 151 | | (Rd << 12) // Rd |
| 159 | |(Rs << 0); // Rm | 152 | | (Rs << 0); // Rm |
| 160 | break; | 153 | break; |
| 161 | case 0xC: // BX Rs | 154 | case 0xC: // BX Rs |
| 162 | case 0xD: // BX Hs | 155 | case 0xD: // BX Hs |
| 163 | *ainstr = 0xE12FFF10 // base | 156 | *ainstr = 0xE12FFF10 // base |
| 164 | | ((tinstr & 0x0078) >> 3); // Rd | 157 | | ((tinstr & 0x0078) >> 3); // Rd |
| 165 | break; | 158 | break; |
| 166 | case 0xE: // BLX | 159 | case 0xE: // BLX |
| 167 | case 0xF: // BLX | 160 | case 0xF: // BLX |
| 168 | *ainstr = 0xE1200030 // base | 161 | *ainstr = 0xE1200030 // base |
| 169 | | (Rs << 0); // Rm | 162 | | (Rs << 0); // Rm |
| 170 | break; | 163 | break; |
| 171 | } | 164 | } |
| 172 | } | 165 | } |
| 173 | break; | 166 | break; |
| 174 | 167 | ||
| 175 | case 9: // LDR Rd,[PC,#imm8] | 168 | case 9: // LDR Rd,[PC,#imm8] |
| 176 | *ainstr = 0xE59F0000 // base | 169 | *ainstr = 0xE59F0000 // base |
| 177 | | ((tinstr & 0x0700) << (12 - 8)) // Rd | 170 | | ((tinstr & 0x0700) << (12 - 8)) // Rd |
| 178 | |((tinstr & 0x00FF) << (2 - 0)); // off8 | 171 | | ((tinstr & 0x00FF) << (2 - 0)); // off8 |
| 179 | break; | 172 | break; |
| 180 | 173 | ||
| 181 | case 10: | 174 | case 10: |
| 182 | case 11: | 175 | case 11: { |
| 183 | { | 176 | static const u32 subset[8] = { |
| 184 | static const u32 subset[8] = { | 177 | 0xE7800000, // STR Rd,[Rb,Ro] |
| 185 | 0xE7800000, // STR Rd,[Rb,Ro] | 178 | 0xE18000B0, // STRH Rd,[Rb,Ro] |
| 186 | 0xE18000B0, // STRH Rd,[Rb,Ro] | 179 | 0xE7C00000, // STRB Rd,[Rb,Ro] |
| 187 | 0xE7C00000, // STRB Rd,[Rb,Ro] | 180 | 0xE19000D0, // LDRSB Rd,[Rb,Ro] |
| 188 | 0xE19000D0, // LDRSB Rd,[Rb,Ro] | 181 | 0xE7900000, // LDR Rd,[Rb,Ro] |
| 189 | 0xE7900000, // LDR Rd,[Rb,Ro] | 182 | 0xE19000B0, // LDRH Rd,[Rb,Ro] |
| 190 | 0xE19000B0, // LDRH Rd,[Rb,Ro] | 183 | 0xE7D00000, // LDRB Rd,[Rb,Ro] |
| 191 | 0xE7D00000, // LDRB Rd,[Rb,Ro] | 184 | 0xE19000F0 // LDRSH Rd,[Rb,Ro] |
| 192 | 0xE19000F0 // LDRSH Rd,[Rb,Ro] | 185 | }; |
| 193 | }; | 186 | |
| 194 | 187 | *ainstr = subset[(tinstr & 0xE00) >> 9] // base | |
| 195 | *ainstr = subset[(tinstr & 0xE00) >> 9] // base | 188 | | ((tinstr & 0x0007) << (12 - 0)) // Rd |
| 196 | |((tinstr & 0x0007) << (12 - 0)) // Rd | 189 | | ((tinstr & 0x0038) << (16 - 3)) // Rb |
| 197 | |((tinstr & 0x0038) << (16 - 3)) // Rb | 190 | | ((tinstr & 0x01C0) >> 6); // Ro |
| 198 | |((tinstr & 0x01C0) >> 6); // Ro | 191 | } break; |
| 199 | } | ||
| 200 | break; | ||
| 201 | 192 | ||
| 202 | case 12: // STR Rd,[Rb,#imm5] | 193 | case 12: // STR Rd,[Rb,#imm5] |
| 203 | case 13: // LDR Rd,[Rb,#imm5] | 194 | case 13: // LDR Rd,[Rb,#imm5] |
| 204 | case 14: // STRB Rd,[Rb,#imm5] | 195 | case 14: // STRB Rd,[Rb,#imm5] |
| 205 | case 15: // LDRB Rd,[Rb,#imm5] | 196 | case 15: // LDRB Rd,[Rb,#imm5] |
| 206 | { | 197 | { |
| 207 | static const u32 subset[4] = { | 198 | static const u32 subset[4] = { |
| 208 | 0xE5800000, // STR Rd,[Rb,#imm5] | 199 | 0xE5800000, // STR Rd,[Rb,#imm5] |
| 209 | 0xE5900000, // LDR Rd,[Rb,#imm5] | 200 | 0xE5900000, // LDR Rd,[Rb,#imm5] |
| 210 | 0xE5C00000, // STRB Rd,[Rb,#imm5] | 201 | 0xE5C00000, // STRB Rd,[Rb,#imm5] |
| 211 | 0xE5D00000 // LDRB Rd,[Rb,#imm5] | 202 | 0xE5D00000 // LDRB Rd,[Rb,#imm5] |
| 212 | }; | 203 | }; |
| 213 | // The offset range defends on whether we are transferring a byte or word value: | 204 | // The offset range defends on whether we are transferring a byte or word value: |
| 214 | *ainstr = subset[(tinstr & 0x1800) >> 11] // base | 205 | *ainstr = subset[(tinstr & 0x1800) >> 11] // base |
| 215 | |((tinstr & 0x0007) << (12 - 0)) // Rd | 206 | | ((tinstr & 0x0007) << (12 - 0)) // Rd |
| 216 | |((tinstr & 0x0038) << (16 - 3)) // Rb | 207 | | ((tinstr & 0x0038) << (16 - 3)) // Rb |
| 217 | |((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2))); // off5 | 208 | | ((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2))); // off5 |
| 218 | } | 209 | } break; |
| 210 | |||
| 211 | case 16: // STRH Rd,[Rb,#imm5] | ||
| 212 | case 17: // LDRH Rd,[Rb,#imm5] | ||
| 213 | *ainstr = ((tinstr & (1 << 11)) // base | ||
| 214 | ? 0xE1D000B0 // LDRH | ||
| 215 | : 0xE1C000B0) // STRH | ||
| 216 | | ((tinstr & 0x0007) << (12 - 0)) // Rd | ||
| 217 | | ((tinstr & 0x0038) << (16 - 3)) // Rb | ||
| 218 | | ((tinstr & 0x01C0) >> (6 - 1)) // off5, low nibble | ||
| 219 | | ((tinstr & 0x0600) >> (9 - 8)); // off5, high nibble | ||
| 219 | break; | 220 | break; |
| 220 | 221 | ||
| 221 | case 16: // STRH Rd,[Rb,#imm5] | 222 | case 18: // STR Rd,[SP,#imm8] |
| 222 | case 17: // LDRH Rd,[Rb,#imm5] | 223 | case 19: // LDR Rd,[SP,#imm8] |
| 223 | *ainstr = ((tinstr & (1 << 11)) // base | 224 | *ainstr = ((tinstr & (1 << 11)) // base |
| 224 | ? 0xE1D000B0 // LDRH | 225 | ? 0xE59D0000 // LDR |
| 225 | : 0xE1C000B0) // STRH | 226 | : 0xE58D0000) // STR |
| 226 | |((tinstr & 0x0007) << (12 - 0)) // Rd | 227 | | ((tinstr & 0x0700) << (12 - 8)) // Rd |
| 227 | |((tinstr & 0x0038) << (16 - 3)) // Rb | 228 | | ((tinstr & 0x00FF) << 2); // off8 |
| 228 | |((tinstr & 0x01C0) >> (6 - 1)) // off5, low nibble | ||
| 229 | |((tinstr & 0x0600) >> (9 - 8)); // off5, high nibble | ||
| 230 | break; | ||
| 231 | |||
| 232 | case 18: // STR Rd,[SP,#imm8] | ||
| 233 | case 19: // LDR Rd,[SP,#imm8] | ||
| 234 | *ainstr = ((tinstr & (1 << 11)) // base | ||
| 235 | ? 0xE59D0000 // LDR | ||
| 236 | : 0xE58D0000) // STR | ||
| 237 | |((tinstr & 0x0700) << (12 - 8)) // Rd | ||
| 238 | |((tinstr & 0x00FF) << 2); // off8 | ||
| 239 | break; | 229 | break; |
| 240 | 230 | ||
| 241 | case 20: // ADD Rd,PC,#imm8 | 231 | case 20: // ADD Rd,PC,#imm8 |
| @@ -246,14 +236,15 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3 | |||
| 246 | // NOTE: The PC value used here should by word aligned. We encode shift-left-by-2 in the | 236 | // NOTE: The PC value used here should by word aligned. We encode shift-left-by-2 in the |
| 247 | // rotate immediate field, so no shift of off8 is needed. | 237 | // rotate immediate field, so no shift of off8 is needed. |
| 248 | 238 | ||
| 249 | *ainstr = 0xE28F0F00 // base | 239 | *ainstr = 0xE28F0F00 // base |
| 250 | | ((tinstr & 0x0700) << (12 - 8)) // Rd | 240 | | ((tinstr & 0x0700) << (12 - 8)) // Rd |
| 251 | |(tinstr & 0x00FF); // off8 | 241 | | (tinstr & 0x00FF); // off8 |
| 252 | } else { | 242 | } else { |
| 253 | // We encode shift-left-by-2 in the rotate immediate field, so no shift of off8 is needed. | 243 | // We encode shift-left-by-2 in the rotate immediate field, so no shift of off8 is |
| 254 | *ainstr = 0xE28D0F00 // base | 244 | // needed. |
| 255 | | ((tinstr & 0x0700) << (12 - 8)) // Rd | 245 | *ainstr = 0xE28D0F00 // base |
| 256 | |(tinstr & 0x00FF); // off8 | 246 | | ((tinstr & 0x0700) << (12 - 8)) // Rd |
| 247 | | (tinstr & 0x00FF); // off8 | ||
| 257 | } | 248 | } |
| 258 | break; | 249 | break; |
| 259 | 250 | ||
| @@ -261,15 +252,15 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3 | |||
| 261 | case 23: | 252 | case 23: |
| 262 | if ((tinstr & 0x0F00) == 0x0000) { | 253 | if ((tinstr & 0x0F00) == 0x0000) { |
| 263 | // NOTE: The instruction contains a shift left of 2 equivalent (implemented as ROR #30): | 254 | // NOTE: The instruction contains a shift left of 2 equivalent (implemented as ROR #30): |
| 264 | *ainstr = ((tinstr & (1 << 7)) // base | 255 | *ainstr = ((tinstr & (1 << 7)) // base |
| 265 | ? 0xE24DDF00 // SUB | 256 | ? 0xE24DDF00 // SUB |
| 266 | : 0xE28DDF00) // ADD | 257 | : 0xE28DDF00) // ADD |
| 267 | |(tinstr & 0x007F); // off7 | 258 | | (tinstr & 0x007F); // off7 |
| 268 | } else if ((tinstr & 0x0F00) == 0x0e00) { | 259 | } else if ((tinstr & 0x0F00) == 0x0e00) { |
| 269 | // BKPT | 260 | // BKPT |
| 270 | *ainstr = 0xEF000000 // base | 261 | *ainstr = 0xEF000000 // base |
| 271 | | BITS(tinstr, 0, 3) // imm4 field; | 262 | | BITS(tinstr, 0, 3) // imm4 field; |
| 272 | | (BITS(tinstr, 4, 7) << 8); // beginning 4 bits of imm12 | 263 | | (BITS(tinstr, 4, 7) << 8); // beginning 4 bits of imm12 |
| 273 | } else if ((tinstr & 0x0F00) == 0x0200) { | 264 | } else if ((tinstr & 0x0F00) == 0x0200) { |
| 274 | static const u32 subset[4] = { | 265 | static const u32 subset[4] = { |
| 275 | 0xE6BF0070, // SXTH | 266 | 0xE6BF0070, // SXTH |
| @@ -278,21 +269,21 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3 | |||
| 278 | 0xE6EF0070, // UXTB | 269 | 0xE6EF0070, // UXTB |
| 279 | }; | 270 | }; |
| 280 | 271 | ||
| 281 | *ainstr = subset[BITS(tinstr, 6, 7)] // base | 272 | *ainstr = subset[BITS(tinstr, 6, 7)] // base |
| 282 | | (BITS(tinstr, 0, 2) << 12) // Rd | 273 | | (BITS(tinstr, 0, 2) << 12) // Rd |
| 283 | | BITS(tinstr, 3, 5); // Rm | 274 | | BITS(tinstr, 3, 5); // Rm |
| 284 | } else if ((tinstr & 0x0F00) == 0x600) { | 275 | } else if ((tinstr & 0x0F00) == 0x600) { |
| 285 | if (BIT(tinstr, 5) == 0) { | 276 | if (BIT(tinstr, 5) == 0) { |
| 286 | // SETEND | 277 | // SETEND |
| 287 | *ainstr = 0xF1010000 // base | 278 | *ainstr = 0xF1010000 // base |
| 288 | | (BIT(tinstr, 3) << 9); // endian specifier | 279 | | (BIT(tinstr, 3) << 9); // endian specifier |
| 289 | } else { | 280 | } else { |
| 290 | // CPS | 281 | // CPS |
| 291 | *ainstr = 0xF1080000 // base | 282 | *ainstr = 0xF1080000 // base |
| 292 | | (BIT(tinstr, 0) << 6) // fiq bit | 283 | | (BIT(tinstr, 0) << 6) // fiq bit |
| 293 | | (BIT(tinstr, 1) << 7) // irq bit | 284 | | (BIT(tinstr, 1) << 7) // irq bit |
| 294 | | (BIT(tinstr, 2) << 8) // abort bit | 285 | | (BIT(tinstr, 2) << 8) // abort bit |
| 295 | | (BIT(tinstr, 4) << 18); // enable bit | 286 | | (BIT(tinstr, 4) << 18); // enable bit |
| 296 | } | 287 | } |
| 297 | } else if ((tinstr & 0x0F00) == 0x0a00) { | 288 | } else if ((tinstr & 0x0F00) == 0x0a00) { |
| 298 | static const u32 subset[4] = { | 289 | static const u32 subset[4] = { |
| @@ -307,9 +298,9 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3 | |||
| 307 | if (subset_index == 2) { | 298 | if (subset_index == 2) { |
| 308 | valid = ThumbDecodeStatus::UNDEFINED; | 299 | valid = ThumbDecodeStatus::UNDEFINED; |
| 309 | } else { | 300 | } else { |
| 310 | *ainstr = subset[subset_index] // base | 301 | *ainstr = subset[subset_index] // base |
| 311 | | (BITS(tinstr, 0, 2) << 12) // Rd | 302 | | (BITS(tinstr, 0, 2) << 12) // Rd |
| 312 | | BITS(tinstr, 3, 5); // Rm | 303 | | BITS(tinstr, 3, 5); // Rm |
| 313 | } | 304 | } |
| 314 | } else { | 305 | } else { |
| 315 | static const u32 subset[4] = { | 306 | static const u32 subset[4] = { |
| @@ -319,14 +310,13 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3 | |||
| 319 | 0xE8BD8000 // LDMIA sp!,{rlist,pc} | 310 | 0xE8BD8000 // LDMIA sp!,{rlist,pc} |
| 320 | }; | 311 | }; |
| 321 | *ainstr = subset[((tinstr & (1 << 11)) >> 10) | ((tinstr & (1 << 8)) >> 8)] // base | 312 | *ainstr = subset[((tinstr & (1 << 11)) >> 10) | ((tinstr & (1 << 8)) >> 8)] // base |
| 322 | |(tinstr & 0x00FF); // mask8 | 313 | | (tinstr & 0x00FF); // mask8 |
| 323 | } | 314 | } |
| 324 | break; | 315 | break; |
| 325 | 316 | ||
| 326 | case 24: // STMIA | 317 | case 24: // STMIA |
| 327 | case 25: // LDMIA | 318 | case 25: // LDMIA |
| 328 | if (tinstr & (1 << 11)) | 319 | if (tinstr & (1 << 11)) { |
| 329 | { | ||
| 330 | unsigned int base = 0xE8900000; | 320 | unsigned int base = 0xE8900000; |
| 331 | unsigned int rn = BITS(tinstr, 8, 10); | 321 | unsigned int rn = BITS(tinstr, 8, 10); |
| 332 | 322 | ||
| @@ -334,15 +324,13 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3 | |||
| 334 | if ((tinstr & (1 << rn)) == 0) | 324 | if ((tinstr & (1 << rn)) == 0) |
| 335 | base |= (1 << 21); | 325 | base |= (1 << 21); |
| 336 | 326 | ||
| 337 | *ainstr = base // base (LDMIA) | 327 | *ainstr = base // base (LDMIA) |
| 338 | | (rn << 16) // Rn | 328 | | (rn << 16) // Rn |
| 339 | | (tinstr & 0x00FF); // Register list | 329 | | (tinstr & 0x00FF); // Register list |
| 340 | } | 330 | } else { |
| 341 | else | 331 | *ainstr = 0xE8A00000 // base (STMIA) |
| 342 | { | 332 | | (BITS(tinstr, 8, 10) << 16) // Rn |
| 343 | *ainstr = 0xE8A00000 // base (STMIA) | 333 | | (tinstr & 0x00FF); // Register list |
| 344 | | (BITS(tinstr, 8, 10) << 16) // Rn | ||
| 345 | | (tinstr & 0x00FF); // Register list | ||
| 346 | } | 334 | } |
| 347 | break; | 335 | break; |
| 348 | 336 | ||
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.h b/src/core/arm/dyncom/arm_dyncom_thumb.h index c1be3c735..231e48aa4 100644 --- a/src/core/arm/dyncom/arm_dyncom_thumb.h +++ b/src/core/arm/dyncom/arm_dyncom_thumb.h | |||
| @@ -29,9 +29,9 @@ | |||
| 29 | #include "common/common_types.h" | 29 | #include "common/common_types.h" |
| 30 | 30 | ||
| 31 | enum class ThumbDecodeStatus { | 31 | enum class ThumbDecodeStatus { |
| 32 | UNDEFINED, // Undefined Thumb instruction | 32 | UNDEFINED, // Undefined Thumb instruction |
| 33 | DECODED, // Instruction decoded to ARM equivalent | 33 | DECODED, // Instruction decoded to ARM equivalent |
| 34 | BRANCH, // Thumb branch (already processed) | 34 | BRANCH, // Thumb branch (already processed) |
| 35 | UNINITIALIZED, | 35 | UNINITIALIZED, |
| 36 | }; | 36 | }; |
| 37 | 37 | ||
diff --git a/src/core/arm/dyncom/arm_dyncom_trans.cpp b/src/core/arm/dyncom/arm_dyncom_trans.cpp index 00b42c246..e056d890c 100644 --- a/src/core/arm/dyncom/arm_dyncom_trans.cpp +++ b/src/core/arm/dyncom/arm_dyncom_trans.cpp | |||
| @@ -19,24 +19,23 @@ static void* AllocBuffer(size_t size) { | |||
| 19 | return static_cast<void*>(&trans_cache_buf[start]); | 19 | return static_cast<void*>(&trans_cache_buf[start]); |
| 20 | } | 20 | } |
| 21 | 21 | ||
| 22 | #define glue(x, y) x ## y | 22 | #define glue(x, y) x##y |
| 23 | #define INTERPRETER_TRANSLATE(s) glue(InterpreterTranslate_, s) | 23 | #define INTERPRETER_TRANSLATE(s) glue(InterpreterTranslate_, s) |
| 24 | 24 | ||
| 25 | shtop_fp_t GetShifterOp(unsigned int inst); | 25 | shtop_fp_t GetShifterOp(unsigned int inst); |
| 26 | get_addr_fp_t GetAddressingOp(unsigned int inst); | 26 | get_addr_fp_t GetAddressingOp(unsigned int inst); |
| 27 | get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst); | 27 | get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst); |
| 28 | 28 | ||
| 29 | static ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index) | 29 | static ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index) { |
| 30 | { | 30 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(adc_inst)); |
| 31 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(adc_inst)); | 31 | adc_inst* inst_cream = (adc_inst*)inst_base->component; |
| 32 | adc_inst *inst_cream = (adc_inst *)inst_base->component; | ||
| 33 | 32 | ||
| 34 | inst_base->cond = BITS(inst, 28, 31); | 33 | inst_base->cond = BITS(inst, 28, 31); |
| 35 | inst_base->idx = index; | 34 | inst_base->idx = index; |
| 36 | inst_base->br = TransExtData::NON_BRANCH; | 35 | inst_base->br = TransExtData::NON_BRANCH; |
| 37 | 36 | ||
| 38 | inst_cream->I = BIT(inst, 25); | 37 | inst_cream->I = BIT(inst, 25); |
| 39 | inst_cream->S = BIT(inst, 20); | 38 | inst_cream->S = BIT(inst, 20); |
| 40 | inst_cream->Rn = BITS(inst, 16, 19); | 39 | inst_cream->Rn = BITS(inst, 16, 19); |
| 41 | inst_cream->Rd = BITS(inst, 12, 15); | 40 | inst_cream->Rd = BITS(inst, 12, 15); |
| 42 | inst_cream->shifter_operand = BITS(inst, 0, 11); | 41 | inst_cream->shifter_operand = BITS(inst, 0, 11); |
| @@ -47,17 +46,16 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index) | |||
| 47 | 46 | ||
| 48 | return inst_base; | 47 | return inst_base; |
| 49 | } | 48 | } |
| 50 | static ARM_INST_PTR INTERPRETER_TRANSLATE(add)(unsigned int inst, int index) | 49 | static ARM_INST_PTR INTERPRETER_TRANSLATE(add)(unsigned int inst, int index) { |
| 51 | { | 50 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(add_inst)); |
| 52 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(add_inst)); | 51 | add_inst* inst_cream = (add_inst*)inst_base->component; |
| 53 | add_inst *inst_cream = (add_inst *)inst_base->component; | ||
| 54 | 52 | ||
| 55 | inst_base->cond = BITS(inst, 28, 31); | 53 | inst_base->cond = BITS(inst, 28, 31); |
| 56 | inst_base->idx = index; | 54 | inst_base->idx = index; |
| 57 | inst_base->br = TransExtData::NON_BRANCH; | 55 | inst_base->br = TransExtData::NON_BRANCH; |
| 58 | 56 | ||
| 59 | inst_cream->I = BIT(inst, 25); | 57 | inst_cream->I = BIT(inst, 25); |
| 60 | inst_cream->S = BIT(inst, 20); | 58 | inst_cream->S = BIT(inst, 20); |
| 61 | inst_cream->Rn = BITS(inst, 16, 19); | 59 | inst_cream->Rn = BITS(inst, 16, 19); |
| 62 | inst_cream->Rd = BITS(inst, 12, 15); | 60 | inst_cream->Rd = BITS(inst, 12, 15); |
| 63 | inst_cream->shifter_operand = BITS(inst, 0, 11); | 61 | inst_cream->shifter_operand = BITS(inst, 0, 11); |
| @@ -68,17 +66,16 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(add)(unsigned int inst, int index) | |||
| 68 | 66 | ||
| 69 | return inst_base; | 67 | return inst_base; |
| 70 | } | 68 | } |
| 71 | static ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index) | 69 | static ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index) { |
| 72 | { | 70 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(and_inst)); |
| 73 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(and_inst)); | 71 | and_inst* inst_cream = (and_inst*)inst_base->component; |
| 74 | and_inst *inst_cream = (and_inst *)inst_base->component; | ||
| 75 | 72 | ||
| 76 | inst_base->cond = BITS(inst, 28, 31); | 73 | inst_base->cond = BITS(inst, 28, 31); |
| 77 | inst_base->idx = index; | 74 | inst_base->idx = index; |
| 78 | inst_base->br = TransExtData::NON_BRANCH; | 75 | inst_base->br = TransExtData::NON_BRANCH; |
| 79 | 76 | ||
| 80 | inst_cream->I = BIT(inst, 25); | 77 | inst_cream->I = BIT(inst, 25); |
| 81 | inst_cream->S = BIT(inst, 20); | 78 | inst_cream->S = BIT(inst, 20); |
| 82 | inst_cream->Rn = BITS(inst, 16, 19); | 79 | inst_cream->Rn = BITS(inst, 16, 19); |
| 83 | inst_cream->Rd = BITS(inst, 12, 15); | 80 | inst_cream->Rd = BITS(inst, 12, 15); |
| 84 | inst_cream->shifter_operand = BITS(inst, 0, 11); | 81 | inst_cream->shifter_operand = BITS(inst, 0, 11); |
| @@ -89,37 +86,35 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index) | |||
| 89 | 86 | ||
| 90 | return inst_base; | 87 | return inst_base; |
| 91 | } | 88 | } |
| 92 | static ARM_INST_PTR INTERPRETER_TRANSLATE(bbl)(unsigned int inst, int index) | 89 | static ARM_INST_PTR INTERPRETER_TRANSLATE(bbl)(unsigned int inst, int index) { |
| 93 | { | 90 | #define POSBRANCH ((inst & 0x7fffff) << 2) |
| 94 | #define POSBRANCH ((inst & 0x7fffff) << 2) | 91 | #define NEGBRANCH ((0xff000000 | (inst & 0xffffff)) << 2) |
| 95 | #define NEGBRANCH ((0xff000000 |(inst & 0xffffff)) << 2) | ||
| 96 | 92 | ||
| 97 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bbl_inst)); | 93 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bbl_inst)); |
| 98 | bbl_inst *inst_cream = (bbl_inst *)inst_base->component; | 94 | bbl_inst* inst_cream = (bbl_inst*)inst_base->component; |
| 99 | 95 | ||
| 100 | inst_base->cond = BITS(inst, 28, 31); | 96 | inst_base->cond = BITS(inst, 28, 31); |
| 101 | inst_base->idx = index; | 97 | inst_base->idx = index; |
| 102 | inst_base->br = TransExtData::DIRECT_BRANCH; | 98 | inst_base->br = TransExtData::DIRECT_BRANCH; |
| 103 | 99 | ||
| 104 | if (BIT(inst, 24)) | 100 | if (BIT(inst, 24)) |
| 105 | inst_base->br = TransExtData::CALL; | 101 | inst_base->br = TransExtData::CALL; |
| 106 | 102 | ||
| 107 | inst_cream->L = BIT(inst, 24); | 103 | inst_cream->L = BIT(inst, 24); |
| 108 | inst_cream->signed_immed_24 = BIT(inst, 23) ? NEGBRANCH : POSBRANCH; | 104 | inst_cream->signed_immed_24 = BIT(inst, 23) ? NEGBRANCH : POSBRANCH; |
| 109 | 105 | ||
| 110 | return inst_base; | 106 | return inst_base; |
| 111 | } | 107 | } |
| 112 | static ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index) | 108 | static ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index) { |
| 113 | { | 109 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bic_inst)); |
| 114 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bic_inst)); | 110 | bic_inst* inst_cream = (bic_inst*)inst_base->component; |
| 115 | bic_inst *inst_cream = (bic_inst *)inst_base->component; | ||
| 116 | 111 | ||
| 117 | inst_base->cond = BITS(inst, 28, 31); | 112 | inst_base->cond = BITS(inst, 28, 31); |
| 118 | inst_base->idx = index; | 113 | inst_base->idx = index; |
| 119 | inst_base->br = TransExtData::NON_BRANCH; | 114 | inst_base->br = TransExtData::NON_BRANCH; |
| 120 | 115 | ||
| 121 | inst_cream->I = BIT(inst, 25); | 116 | inst_cream->I = BIT(inst, 25); |
| 122 | inst_cream->S = BIT(inst, 20); | 117 | inst_cream->S = BIT(inst, 20); |
| 123 | inst_cream->Rn = BITS(inst, 16, 19); | 118 | inst_cream->Rn = BITS(inst, 16, 19); |
| 124 | inst_cream->Rd = BITS(inst, 12, 15); | 119 | inst_cream->Rd = BITS(inst, 12, 15); |
| 125 | inst_cream->shifter_operand = BITS(inst, 0, 11); | 120 | inst_cream->shifter_operand = BITS(inst, 0, 11); |
| @@ -130,28 +125,26 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index) | |||
| 130 | return inst_base; | 125 | return inst_base; |
| 131 | } | 126 | } |
| 132 | 127 | ||
| 133 | static ARM_INST_PTR INTERPRETER_TRANSLATE(bkpt)(unsigned int inst, int index) | 128 | static ARM_INST_PTR INTERPRETER_TRANSLATE(bkpt)(unsigned int inst, int index) { |
| 134 | { | ||
| 135 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bkpt_inst)); | 129 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bkpt_inst)); |
| 136 | bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component; | 130 | bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component; |
| 137 | 131 | ||
| 138 | inst_base->cond = BITS(inst, 28, 31); | 132 | inst_base->cond = BITS(inst, 28, 31); |
| 139 | inst_base->idx = index; | 133 | inst_base->idx = index; |
| 140 | inst_base->br = TransExtData::NON_BRANCH; | 134 | inst_base->br = TransExtData::NON_BRANCH; |
| 141 | 135 | ||
| 142 | inst_cream->imm = (BITS(inst, 8, 19) << 4) | BITS(inst, 0, 3); | 136 | inst_cream->imm = (BITS(inst, 8, 19) << 4) | BITS(inst, 0, 3); |
| 143 | 137 | ||
| 144 | return inst_base; | 138 | return inst_base; |
| 145 | } | 139 | } |
| 146 | 140 | ||
| 147 | static ARM_INST_PTR INTERPRETER_TRANSLATE(blx)(unsigned int inst, int index) | 141 | static ARM_INST_PTR INTERPRETER_TRANSLATE(blx)(unsigned int inst, int index) { |
| 148 | { | 142 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(blx_inst)); |
| 149 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_inst)); | 143 | blx_inst* inst_cream = (blx_inst*)inst_base->component; |
| 150 | blx_inst *inst_cream = (blx_inst *)inst_base->component; | ||
| 151 | 144 | ||
| 152 | inst_base->cond = BITS(inst, 28, 31); | 145 | inst_base->cond = BITS(inst, 28, 31); |
| 153 | inst_base->idx = index; | 146 | inst_base->idx = index; |
| 154 | inst_base->br = TransExtData::INDIRECT_BRANCH; | 147 | inst_base->br = TransExtData::INDIRECT_BRANCH; |
| 155 | 148 | ||
| 156 | inst_cream->inst = inst; | 149 | inst_cream->inst = inst; |
| 157 | if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) { | 150 | if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) { |
| @@ -162,36 +155,34 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(blx)(unsigned int inst, int index) | |||
| 162 | 155 | ||
| 163 | return inst_base; | 156 | return inst_base; |
| 164 | } | 157 | } |
| 165 | static ARM_INST_PTR INTERPRETER_TRANSLATE(bx)(unsigned int inst, int index) | 158 | static ARM_INST_PTR INTERPRETER_TRANSLATE(bx)(unsigned int inst, int index) { |
| 166 | { | 159 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bx_inst)); |
| 167 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bx_inst)); | 160 | bx_inst* inst_cream = (bx_inst*)inst_base->component; |
| 168 | bx_inst *inst_cream = (bx_inst *)inst_base->component; | ||
| 169 | 161 | ||
| 170 | inst_base->cond = BITS(inst, 28, 31); | 162 | inst_base->cond = BITS(inst, 28, 31); |
| 171 | inst_base->idx = index; | 163 | inst_base->idx = index; |
| 172 | inst_base->br = TransExtData::INDIRECT_BRANCH; | 164 | inst_base->br = TransExtData::INDIRECT_BRANCH; |
| 173 | 165 | ||
| 174 | inst_cream->Rm = BITS(inst, 0, 3); | 166 | inst_cream->Rm = BITS(inst, 0, 3); |
| 175 | 167 | ||
| 176 | return inst_base; | 168 | return inst_base; |
| 177 | } | 169 | } |
| 178 | static ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index) | 170 | static ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index) { |
| 179 | { | ||
| 180 | return INTERPRETER_TRANSLATE(bx)(inst, index); | 171 | return INTERPRETER_TRANSLATE(bx)(inst, index); |
| 181 | } | 172 | } |
| 182 | 173 | ||
| 183 | static ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index) { | 174 | static ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index) { |
| 184 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cdp_inst)); | 175 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(cdp_inst)); |
| 185 | cdp_inst *inst_cream = (cdp_inst *)inst_base->component; | 176 | cdp_inst* inst_cream = (cdp_inst*)inst_base->component; |
| 186 | 177 | ||
| 187 | inst_base->cond = BITS(inst, 28, 31); | 178 | inst_base->cond = BITS(inst, 28, 31); |
| 188 | inst_base->idx = index; | 179 | inst_base->idx = index; |
| 189 | inst_base->br = TransExtData::NON_BRANCH; | 180 | inst_base->br = TransExtData::NON_BRANCH; |
| 190 | 181 | ||
| 191 | inst_cream->CRm = BITS(inst, 0, 3); | 182 | inst_cream->CRm = BITS(inst, 0, 3); |
| 192 | inst_cream->CRd = BITS(inst, 12, 15); | 183 | inst_cream->CRd = BITS(inst, 12, 15); |
| 193 | inst_cream->CRn = BITS(inst, 16, 19); | 184 | inst_cream->CRn = BITS(inst, 16, 19); |
| 194 | inst_cream->cp_num = BITS(inst, 8, 11); | 185 | inst_cream->cp_num = BITS(inst, 8, 11); |
| 195 | inst_cream->opcode_2 = BITS(inst, 5, 7); | 186 | inst_cream->opcode_2 = BITS(inst, 5, 7); |
| 196 | inst_cream->opcode_1 = BITS(inst, 20, 23); | 187 | inst_cream->opcode_1 = BITS(inst, 20, 23); |
| 197 | inst_cream->inst = inst; | 188 | inst_cream->inst = inst; |
| @@ -199,91 +190,85 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index) { | |||
| 199 | LOG_TRACE(Core_ARM11, "inst %x index %x", inst, index); | 190 | LOG_TRACE(Core_ARM11, "inst %x index %x", inst, index); |
| 200 | return inst_base; | 191 | return inst_base; |
| 201 | } | 192 | } |
| 202 | static ARM_INST_PTR INTERPRETER_TRANSLATE(clrex)(unsigned int inst, int index) | 193 | static ARM_INST_PTR INTERPRETER_TRANSLATE(clrex)(unsigned int inst, int index) { |
| 203 | { | 194 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(clrex_inst)); |
| 204 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clrex_inst)); | ||
| 205 | inst_base->cond = BITS(inst, 28, 31); | 195 | inst_base->cond = BITS(inst, 28, 31); |
| 206 | inst_base->idx = index; | 196 | inst_base->idx = index; |
| 207 | inst_base->br = TransExtData::NON_BRANCH; | 197 | inst_base->br = TransExtData::NON_BRANCH; |
| 208 | 198 | ||
| 209 | return inst_base; | 199 | return inst_base; |
| 210 | } | 200 | } |
| 211 | static ARM_INST_PTR INTERPRETER_TRANSLATE(clz)(unsigned int inst, int index) | 201 | static ARM_INST_PTR INTERPRETER_TRANSLATE(clz)(unsigned int inst, int index) { |
| 212 | { | 202 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(clz_inst)); |
| 213 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clz_inst)); | 203 | clz_inst* inst_cream = (clz_inst*)inst_base->component; |
| 214 | clz_inst *inst_cream = (clz_inst *)inst_base->component; | ||
| 215 | 204 | ||
| 216 | inst_base->cond = BITS(inst, 28, 31); | 205 | inst_base->cond = BITS(inst, 28, 31); |
| 217 | inst_base->idx = index; | 206 | inst_base->idx = index; |
| 218 | inst_base->br = TransExtData::NON_BRANCH; | 207 | inst_base->br = TransExtData::NON_BRANCH; |
| 219 | 208 | ||
| 220 | inst_cream->Rm = BITS(inst, 0, 3); | 209 | inst_cream->Rm = BITS(inst, 0, 3); |
| 221 | inst_cream->Rd = BITS(inst, 12, 15); | 210 | inst_cream->Rd = BITS(inst, 12, 15); |
| 222 | 211 | ||
| 223 | return inst_base; | 212 | return inst_base; |
| 224 | } | 213 | } |
| 225 | static ARM_INST_PTR INTERPRETER_TRANSLATE(cmn)(unsigned int inst, int index) | 214 | static ARM_INST_PTR INTERPRETER_TRANSLATE(cmn)(unsigned int inst, int index) { |
| 226 | { | 215 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(cmn_inst)); |
| 227 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmn_inst)); | 216 | cmn_inst* inst_cream = (cmn_inst*)inst_base->component; |
| 228 | cmn_inst *inst_cream = (cmn_inst *)inst_base->component; | ||
| 229 | 217 | ||
| 230 | inst_base->cond = BITS(inst, 28, 31); | 218 | inst_base->cond = BITS(inst, 28, 31); |
| 231 | inst_base->idx = index; | 219 | inst_base->idx = index; |
| 232 | inst_base->br = TransExtData::NON_BRANCH; | 220 | inst_base->br = TransExtData::NON_BRANCH; |
| 233 | 221 | ||
| 234 | inst_cream->I = BIT(inst, 25); | 222 | inst_cream->I = BIT(inst, 25); |
| 235 | inst_cream->Rn = BITS(inst, 16, 19); | 223 | inst_cream->Rn = BITS(inst, 16, 19); |
| 236 | inst_cream->shifter_operand = BITS(inst, 0, 11); | 224 | inst_cream->shifter_operand = BITS(inst, 0, 11); |
| 237 | inst_cream->shtop_func = GetShifterOp(inst); | 225 | inst_cream->shtop_func = GetShifterOp(inst); |
| 238 | 226 | ||
| 239 | return inst_base; | 227 | return inst_base; |
| 240 | } | 228 | } |
| 241 | static ARM_INST_PTR INTERPRETER_TRANSLATE(cmp)(unsigned int inst, int index) | 229 | static ARM_INST_PTR INTERPRETER_TRANSLATE(cmp)(unsigned int inst, int index) { |
| 242 | { | 230 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(cmp_inst)); |
| 243 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmp_inst)); | 231 | cmp_inst* inst_cream = (cmp_inst*)inst_base->component; |
| 244 | cmp_inst *inst_cream = (cmp_inst *)inst_base->component; | ||
| 245 | 232 | ||
| 246 | inst_base->cond = BITS(inst, 28, 31); | 233 | inst_base->cond = BITS(inst, 28, 31); |
| 247 | inst_base->idx = index; | 234 | inst_base->idx = index; |
| 248 | inst_base->br = TransExtData::NON_BRANCH; | 235 | inst_base->br = TransExtData::NON_BRANCH; |
| 249 | 236 | ||
| 250 | inst_cream->I = BIT(inst, 25); | 237 | inst_cream->I = BIT(inst, 25); |
| 251 | inst_cream->Rn = BITS(inst, 16, 19); | 238 | inst_cream->Rn = BITS(inst, 16, 19); |
| 252 | inst_cream->shifter_operand = BITS(inst, 0, 11); | 239 | inst_cream->shifter_operand = BITS(inst, 0, 11); |
| 253 | inst_cream->shtop_func = GetShifterOp(inst); | 240 | inst_cream->shtop_func = GetShifterOp(inst); |
| 254 | 241 | ||
| 255 | return inst_base; | 242 | return inst_base; |
| 256 | } | 243 | } |
| 257 | static ARM_INST_PTR INTERPRETER_TRANSLATE(cps)(unsigned int inst, int index) | 244 | static ARM_INST_PTR INTERPRETER_TRANSLATE(cps)(unsigned int inst, int index) { |
| 258 | { | 245 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(cps_inst)); |
| 259 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cps_inst)); | 246 | cps_inst* inst_cream = (cps_inst*)inst_base->component; |
| 260 | cps_inst *inst_cream = (cps_inst *)inst_base->component; | ||
| 261 | 247 | ||
| 262 | inst_base->cond = BITS(inst, 28, 31); | 248 | inst_base->cond = BITS(inst, 28, 31); |
| 263 | inst_base->idx = index; | 249 | inst_base->idx = index; |
| 264 | inst_base->br = TransExtData::NON_BRANCH; | 250 | inst_base->br = TransExtData::NON_BRANCH; |
| 265 | 251 | ||
| 266 | inst_cream->imod0 = BIT(inst, 18); | 252 | inst_cream->imod0 = BIT(inst, 18); |
| 267 | inst_cream->imod1 = BIT(inst, 19); | 253 | inst_cream->imod1 = BIT(inst, 19); |
| 268 | inst_cream->mmod = BIT(inst, 17); | 254 | inst_cream->mmod = BIT(inst, 17); |
| 269 | inst_cream->A = BIT(inst, 8); | 255 | inst_cream->A = BIT(inst, 8); |
| 270 | inst_cream->I = BIT(inst, 7); | 256 | inst_cream->I = BIT(inst, 7); |
| 271 | inst_cream->F = BIT(inst, 6); | 257 | inst_cream->F = BIT(inst, 6); |
| 272 | inst_cream->mode = BITS(inst, 0, 4); | 258 | inst_cream->mode = BITS(inst, 0, 4); |
| 273 | 259 | ||
| 274 | return inst_base; | 260 | return inst_base; |
| 275 | } | 261 | } |
| 276 | static ARM_INST_PTR INTERPRETER_TRANSLATE(cpy)(unsigned int inst, int index) | 262 | static ARM_INST_PTR INTERPRETER_TRANSLATE(cpy)(unsigned int inst, int index) { |
| 277 | { | 263 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst)); |
| 278 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst)); | 264 | mov_inst* inst_cream = (mov_inst*)inst_base->component; |
| 279 | mov_inst *inst_cream = (mov_inst *)inst_base->component; | ||
| 280 | 265 | ||
| 281 | inst_base->cond = BITS(inst, 28, 31); | 266 | inst_base->cond = BITS(inst, 28, 31); |
| 282 | inst_base->idx = index; | 267 | inst_base->idx = index; |
| 283 | inst_base->br = TransExtData::NON_BRANCH; | 268 | inst_base->br = TransExtData::NON_BRANCH; |
| 284 | 269 | ||
| 285 | inst_cream->I = BIT(inst, 25); | 270 | inst_cream->I = BIT(inst, 25); |
| 286 | inst_cream->S = BIT(inst, 20); | 271 | inst_cream->S = BIT(inst, 20); |
| 287 | inst_cream->Rd = BITS(inst, 12, 15); | 272 | inst_cream->Rd = BITS(inst, 12, 15); |
| 288 | inst_cream->shifter_operand = BITS(inst, 0, 11); | 273 | inst_cream->shifter_operand = BITS(inst, 0, 11); |
| 289 | inst_cream->shtop_func = GetShifterOp(inst); | 274 | inst_cream->shtop_func = GetShifterOp(inst); |
| @@ -293,17 +278,16 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(cpy)(unsigned int inst, int index) | |||
| 293 | } | 278 | } |
| 294 | return inst_base; | 279 | return inst_base; |
| 295 | } | 280 | } |
| 296 | static ARM_INST_PTR INTERPRETER_TRANSLATE(eor)(unsigned int inst, int index) | 281 | static ARM_INST_PTR INTERPRETER_TRANSLATE(eor)(unsigned int inst, int index) { |
| 297 | { | 282 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(eor_inst)); |
| 298 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(eor_inst)); | 283 | eor_inst* inst_cream = (eor_inst*)inst_base->component; |
| 299 | eor_inst *inst_cream = (eor_inst *)inst_base->component; | ||
| 300 | 284 | ||
| 301 | inst_base->cond = BITS(inst, 28, 31); | 285 | inst_base->cond = BITS(inst, 28, 31); |
| 302 | inst_base->idx = index; | 286 | inst_base->idx = index; |
| 303 | inst_base->br = TransExtData::NON_BRANCH; | 287 | inst_base->br = TransExtData::NON_BRANCH; |
| 304 | 288 | ||
| 305 | inst_cream->I = BIT(inst, 25); | 289 | inst_cream->I = BIT(inst, 25); |
| 306 | inst_cream->S = BIT(inst, 20); | 290 | inst_cream->S = BIT(inst, 20); |
| 307 | inst_cream->Rn = BITS(inst, 16, 19); | 291 | inst_cream->Rn = BITS(inst, 16, 19); |
| 308 | inst_cream->Rd = BITS(inst, 12, 15); | 292 | inst_cream->Rd = BITS(inst, 12, 15); |
| 309 | inst_cream->shifter_operand = BITS(inst, 0, 11); | 293 | inst_cream->shifter_operand = BITS(inst, 0, 11); |
| @@ -314,23 +298,21 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(eor)(unsigned int inst, int index) | |||
| 314 | 298 | ||
| 315 | return inst_base; | 299 | return inst_base; |
| 316 | } | 300 | } |
| 317 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldc)(unsigned int inst, int index) | 301 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldc)(unsigned int inst, int index) { |
| 318 | { | 302 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldc_inst)); |
| 319 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldc_inst)); | ||
| 320 | inst_base->cond = BITS(inst, 28, 31); | 303 | inst_base->cond = BITS(inst, 28, 31); |
| 321 | inst_base->idx = index; | 304 | inst_base->idx = index; |
| 322 | inst_base->br = TransExtData::NON_BRANCH; | 305 | inst_base->br = TransExtData::NON_BRANCH; |
| 323 | 306 | ||
| 324 | return inst_base; | 307 | return inst_base; |
| 325 | } | 308 | } |
| 326 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldm)(unsigned int inst, int index) | 309 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldm)(unsigned int inst, int index) { |
| 327 | { | 310 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); |
| 328 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); | 311 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 329 | ldst_inst *inst_cream = (ldst_inst *)inst_base->component; | ||
| 330 | 312 | ||
| 331 | inst_base->cond = BITS(inst, 28, 31); | 313 | inst_base->cond = BITS(inst, 28, 31); |
| 332 | inst_base->idx = index; | 314 | inst_base->idx = index; |
| 333 | inst_base->br = TransExtData::NON_BRANCH; | 315 | inst_base->br = TransExtData::NON_BRANCH; |
| 334 | 316 | ||
| 335 | inst_cream->inst = inst; | 317 | inst_cream->inst = inst; |
| 336 | inst_cream->get_addr = GetAddressingOp(inst); | 318 | inst_cream->get_addr = GetAddressingOp(inst); |
| @@ -340,29 +322,27 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldm)(unsigned int inst, int index) | |||
| 340 | } | 322 | } |
| 341 | return inst_base; | 323 | return inst_base; |
| 342 | } | 324 | } |
| 343 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sxth)(unsigned int inst, int index) | 325 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sxth)(unsigned int inst, int index) { |
| 344 | { | 326 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst)); |
| 345 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst)); | 327 | sxtb_inst* inst_cream = (sxtb_inst*)inst_base->component; |
| 346 | sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component; | ||
| 347 | 328 | ||
| 348 | inst_base->cond = BITS(inst, 28, 31); | 329 | inst_base->cond = BITS(inst, 28, 31); |
| 349 | inst_base->idx = index; | 330 | inst_base->idx = index; |
| 350 | inst_base->br = TransExtData::NON_BRANCH; | 331 | inst_base->br = TransExtData::NON_BRANCH; |
| 351 | 332 | ||
| 352 | inst_cream->Rd = BITS(inst, 12, 15); | 333 | inst_cream->Rd = BITS(inst, 12, 15); |
| 353 | inst_cream->Rm = BITS(inst, 0, 3); | 334 | inst_cream->Rm = BITS(inst, 0, 3); |
| 354 | inst_cream->rotate = BITS(inst, 10, 11); | 335 | inst_cream->rotate = BITS(inst, 10, 11); |
| 355 | 336 | ||
| 356 | return inst_base; | 337 | return inst_base; |
| 357 | } | 338 | } |
| 358 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldr)(unsigned int inst, int index) | 339 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldr)(unsigned int inst, int index) { |
| 359 | { | 340 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); |
| 360 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); | 341 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 361 | ldst_inst *inst_cream = (ldst_inst *)inst_base->component; | ||
| 362 | 342 | ||
| 363 | inst_base->cond = BITS(inst, 28, 31); | 343 | inst_base->cond = BITS(inst, 28, 31); |
| 364 | inst_base->idx = index; | 344 | inst_base->idx = index; |
| 365 | inst_base->br = TransExtData::NON_BRANCH; | 345 | inst_base->br = TransExtData::NON_BRANCH; |
| 366 | 346 | ||
| 367 | inst_cream->inst = inst; | 347 | inst_cream->inst = inst; |
| 368 | inst_cream->get_addr = GetAddressingOp(inst); | 348 | inst_cream->get_addr = GetAddressingOp(inst); |
| @@ -373,14 +353,13 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldr)(unsigned int inst, int index) | |||
| 373 | return inst_base; | 353 | return inst_base; |
| 374 | } | 354 | } |
| 375 | 355 | ||
| 376 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrcond)(unsigned int inst, int index) | 356 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrcond)(unsigned int inst, int index) { |
| 377 | { | 357 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); |
| 378 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); | 358 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 379 | ldst_inst *inst_cream = (ldst_inst *)inst_base->component; | ||
| 380 | 359 | ||
| 381 | inst_base->cond = BITS(inst, 28, 31); | 360 | inst_base->cond = BITS(inst, 28, 31); |
| 382 | inst_base->idx = index; | 361 | inst_base->idx = index; |
| 383 | inst_base->br = TransExtData::NON_BRANCH; | 362 | inst_base->br = TransExtData::NON_BRANCH; |
| 384 | 363 | ||
| 385 | inst_cream->inst = inst; | 364 | inst_cream->inst = inst; |
| 386 | inst_cream->get_addr = GetAddressingOp(inst); | 365 | inst_cream->get_addr = GetAddressingOp(inst); |
| @@ -391,155 +370,143 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrcond)(unsigned int inst, int index) | |||
| 391 | return inst_base; | 370 | return inst_base; |
| 392 | } | 371 | } |
| 393 | 372 | ||
| 394 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uxth)(unsigned int inst, int index) | 373 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uxth)(unsigned int inst, int index) { |
| 395 | { | 374 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst)); |
| 396 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst)); | 375 | uxth_inst* inst_cream = (uxth_inst*)inst_base->component; |
| 397 | uxth_inst *inst_cream = (uxth_inst *)inst_base->component; | ||
| 398 | 376 | ||
| 399 | inst_base->cond = BITS(inst, 28, 31); | 377 | inst_base->cond = BITS(inst, 28, 31); |
| 400 | inst_base->idx = index; | 378 | inst_base->idx = index; |
| 401 | inst_base->br = TransExtData::NON_BRANCH; | 379 | inst_base->br = TransExtData::NON_BRANCH; |
| 402 | 380 | ||
| 403 | inst_cream->Rd = BITS(inst, 12, 15); | 381 | inst_cream->Rd = BITS(inst, 12, 15); |
| 404 | inst_cream->rotate = BITS(inst, 10, 11); | 382 | inst_cream->rotate = BITS(inst, 10, 11); |
| 405 | inst_cream->Rm = BITS(inst, 0, 3); | 383 | inst_cream->Rm = BITS(inst, 0, 3); |
| 406 | 384 | ||
| 407 | return inst_base; | 385 | return inst_base; |
| 408 | } | 386 | } |
| 409 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtah)(unsigned int inst, int index) | 387 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtah)(unsigned int inst, int index) { |
| 410 | { | 388 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxtah_inst)); |
| 411 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtah_inst)); | 389 | uxtah_inst* inst_cream = (uxtah_inst*)inst_base->component; |
| 412 | uxtah_inst *inst_cream = (uxtah_inst *)inst_base->component; | ||
| 413 | 390 | ||
| 414 | inst_base->cond = BITS(inst, 28, 31); | 391 | inst_base->cond = BITS(inst, 28, 31); |
| 415 | inst_base->idx = index; | 392 | inst_base->idx = index; |
| 416 | inst_base->br = TransExtData::NON_BRANCH; | 393 | inst_base->br = TransExtData::NON_BRANCH; |
| 417 | 394 | ||
| 418 | inst_cream->Rn = BITS(inst, 16, 19); | 395 | inst_cream->Rn = BITS(inst, 16, 19); |
| 419 | inst_cream->Rd = BITS(inst, 12, 15); | 396 | inst_cream->Rd = BITS(inst, 12, 15); |
| 420 | inst_cream->rotate = BITS(inst, 10, 11); | 397 | inst_cream->rotate = BITS(inst, 10, 11); |
| 421 | inst_cream->Rm = BITS(inst, 0, 3); | 398 | inst_cream->Rm = BITS(inst, 0, 3); |
| 422 | 399 | ||
| 423 | return inst_base; | 400 | return inst_base; |
| 424 | } | 401 | } |
| 425 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index) | 402 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index) { |
| 426 | { | 403 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); |
| 427 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); | 404 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 428 | ldst_inst *inst_cream = (ldst_inst *)inst_base->component; | ||
| 429 | 405 | ||
| 430 | inst_base->cond = BITS(inst, 28, 31); | 406 | inst_base->cond = BITS(inst, 28, 31); |
| 431 | inst_base->idx = index; | 407 | inst_base->idx = index; |
| 432 | inst_base->br = TransExtData::NON_BRANCH; | 408 | inst_base->br = TransExtData::NON_BRANCH; |
| 433 | 409 | ||
| 434 | inst_cream->inst = inst; | 410 | inst_cream->inst = inst; |
| 435 | inst_cream->get_addr = GetAddressingOp(inst); | 411 | inst_cream->get_addr = GetAddressingOp(inst); |
| 436 | 412 | ||
| 437 | return inst_base; | 413 | return inst_base; |
| 438 | } | 414 | } |
| 439 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index) | 415 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index) { |
| 440 | { | ||
| 441 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); | 416 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); |
| 442 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | 417 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 443 | 418 | ||
| 444 | inst_base->cond = BITS(inst, 28, 31); | 419 | inst_base->cond = BITS(inst, 28, 31); |
| 445 | inst_base->idx = index; | 420 | inst_base->idx = index; |
| 446 | inst_base->br = TransExtData::NON_BRANCH; | 421 | inst_base->br = TransExtData::NON_BRANCH; |
| 447 | 422 | ||
| 448 | inst_cream->inst = inst; | 423 | inst_cream->inst = inst; |
| 449 | inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); | 424 | inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); |
| 450 | 425 | ||
| 451 | return inst_base; | 426 | return inst_base; |
| 452 | } | 427 | } |
| 453 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrd)(unsigned int inst, int index) | 428 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrd)(unsigned int inst, int index) { |
| 454 | { | 429 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); |
| 455 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); | 430 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 456 | ldst_inst *inst_cream = (ldst_inst *)inst_base->component; | ||
| 457 | 431 | ||
| 458 | inst_base->cond = BITS(inst, 28, 31); | 432 | inst_base->cond = BITS(inst, 28, 31); |
| 459 | inst_base->idx = index; | 433 | inst_base->idx = index; |
| 460 | inst_base->br = TransExtData::NON_BRANCH; | 434 | inst_base->br = TransExtData::NON_BRANCH; |
| 461 | 435 | ||
| 462 | inst_cream->inst = inst; | 436 | inst_cream->inst = inst; |
| 463 | inst_cream->get_addr = GetAddressingOp(inst); | 437 | inst_cream->get_addr = GetAddressingOp(inst); |
| 464 | 438 | ||
| 465 | return inst_base; | 439 | return inst_base; |
| 466 | } | 440 | } |
| 467 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrex)(unsigned int inst, int index) | 441 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrex)(unsigned int inst, int index) { |
| 468 | { | 442 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); |
| 469 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); | 443 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |
| 470 | generic_arm_inst *inst_cream = (generic_arm_inst *)inst_base->component; | ||
| 471 | 444 | ||
| 472 | inst_base->cond = BITS(inst, 28, 31); | 445 | inst_base->cond = BITS(inst, 28, 31); |
| 473 | inst_base->idx = index; | 446 | inst_base->idx = index; |
| 474 | inst_base->br = (BITS(inst, 12, 15) == 15) ? TransExtData::INDIRECT_BRANCH : TransExtData::NON_BRANCH; // Branch if dest is R15 | 447 | inst_base->br = (BITS(inst, 12, 15) == 15) ? TransExtData::INDIRECT_BRANCH |
| 448 | : TransExtData::NON_BRANCH; // Branch if dest is R15 | ||
| 475 | 449 | ||
| 476 | inst_cream->Rn = BITS(inst, 16, 19); | 450 | inst_cream->Rn = BITS(inst, 16, 19); |
| 477 | inst_cream->Rd = BITS(inst, 12, 15); | 451 | inst_cream->Rd = BITS(inst, 12, 15); |
| 478 | 452 | ||
| 479 | return inst_base; | 453 | return inst_base; |
| 480 | } | 454 | } |
| 481 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexb)(unsigned int inst, int index) | 455 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexb)(unsigned int inst, int index) { |
| 482 | { | ||
| 483 | return INTERPRETER_TRANSLATE(ldrex)(inst, index); | 456 | return INTERPRETER_TRANSLATE(ldrex)(inst, index); |
| 484 | } | 457 | } |
| 485 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexh)(unsigned int inst, int index) | 458 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexh)(unsigned int inst, int index) { |
| 486 | { | ||
| 487 | return INTERPRETER_TRANSLATE(ldrex)(inst, index); | 459 | return INTERPRETER_TRANSLATE(ldrex)(inst, index); |
| 488 | } | 460 | } |
| 489 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexd)(unsigned int inst, int index) | 461 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexd)(unsigned int inst, int index) { |
| 490 | { | ||
| 491 | return INTERPRETER_TRANSLATE(ldrex)(inst, index); | 462 | return INTERPRETER_TRANSLATE(ldrex)(inst, index); |
| 492 | } | 463 | } |
| 493 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index) | 464 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index) { |
| 494 | { | 465 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); |
| 495 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); | 466 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 496 | ldst_inst *inst_cream = (ldst_inst *)inst_base->component; | ||
| 497 | 467 | ||
| 498 | inst_base->cond = BITS(inst, 28, 31); | 468 | inst_base->cond = BITS(inst, 28, 31); |
| 499 | inst_base->idx = index; | 469 | inst_base->idx = index; |
| 500 | inst_base->br = TransExtData::NON_BRANCH; | 470 | inst_base->br = TransExtData::NON_BRANCH; |
| 501 | 471 | ||
| 502 | inst_cream->inst = inst; | 472 | inst_cream->inst = inst; |
| 503 | inst_cream->get_addr = GetAddressingOp(inst); | 473 | inst_cream->get_addr = GetAddressingOp(inst); |
| 504 | 474 | ||
| 505 | return inst_base; | 475 | return inst_base; |
| 506 | } | 476 | } |
| 507 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index) | 477 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index) { |
| 508 | { | 478 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); |
| 509 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); | 479 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 510 | ldst_inst *inst_cream = (ldst_inst *)inst_base->component; | ||
| 511 | 480 | ||
| 512 | inst_base->cond = BITS(inst, 28, 31); | 481 | inst_base->cond = BITS(inst, 28, 31); |
| 513 | inst_base->idx = index; | 482 | inst_base->idx = index; |
| 514 | inst_base->br = TransExtData::NON_BRANCH; | 483 | inst_base->br = TransExtData::NON_BRANCH; |
| 515 | 484 | ||
| 516 | inst_cream->inst = inst; | 485 | inst_cream->inst = inst; |
| 517 | inst_cream->get_addr = GetAddressingOp(inst); | 486 | inst_cream->get_addr = GetAddressingOp(inst); |
| 518 | 487 | ||
| 519 | return inst_base; | 488 | return inst_base; |
| 520 | } | 489 | } |
| 521 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index) | 490 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index) { |
| 522 | { | 491 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); |
| 523 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); | 492 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 524 | ldst_inst *inst_cream = (ldst_inst *)inst_base->component; | ||
| 525 | 493 | ||
| 526 | inst_base->cond = BITS(inst, 28, 31); | 494 | inst_base->cond = BITS(inst, 28, 31); |
| 527 | inst_base->idx = index; | 495 | inst_base->idx = index; |
| 528 | inst_base->br = TransExtData::NON_BRANCH; | 496 | inst_base->br = TransExtData::NON_BRANCH; |
| 529 | 497 | ||
| 530 | inst_cream->inst = inst; | 498 | inst_cream->inst = inst; |
| 531 | inst_cream->get_addr = GetAddressingOp(inst); | 499 | inst_cream->get_addr = GetAddressingOp(inst); |
| 532 | 500 | ||
| 533 | return inst_base; | 501 | return inst_base; |
| 534 | } | 502 | } |
| 535 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index) | 503 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index) { |
| 536 | { | ||
| 537 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); | 504 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); |
| 538 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | 505 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 539 | 506 | ||
| 540 | inst_base->cond = BITS(inst, 28, 31); | 507 | inst_base->cond = BITS(inst, 28, 31); |
| 541 | inst_base->idx = index; | 508 | inst_base->idx = index; |
| 542 | inst_base->br = TransExtData::NON_BRANCH; | 509 | inst_base->br = TransExtData::NON_BRANCH; |
| 543 | 510 | ||
| 544 | inst_cream->inst = inst; | 511 | inst_cream->inst = inst; |
| 545 | inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); | 512 | inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); |
| @@ -549,70 +516,66 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index) | |||
| 549 | } | 516 | } |
| 550 | return inst_base; | 517 | return inst_base; |
| 551 | } | 518 | } |
| 552 | static ARM_INST_PTR INTERPRETER_TRANSLATE(mcr)(unsigned int inst, int index) | 519 | static ARM_INST_PTR INTERPRETER_TRANSLATE(mcr)(unsigned int inst, int index) { |
| 553 | { | 520 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mcr_inst)); |
| 554 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mcr_inst)); | 521 | mcr_inst* inst_cream = (mcr_inst*)inst_base->component; |
| 555 | mcr_inst *inst_cream = (mcr_inst *)inst_base->component; | ||
| 556 | inst_base->cond = BITS(inst, 28, 31); | 522 | inst_base->cond = BITS(inst, 28, 31); |
| 557 | inst_base->idx = index; | 523 | inst_base->idx = index; |
| 558 | inst_base->br = TransExtData::NON_BRANCH; | 524 | inst_base->br = TransExtData::NON_BRANCH; |
| 559 | 525 | ||
| 560 | inst_cream->crn = BITS(inst, 16, 19); | 526 | inst_cream->crn = BITS(inst, 16, 19); |
| 561 | inst_cream->crm = BITS(inst, 0, 3); | 527 | inst_cream->crm = BITS(inst, 0, 3); |
| 562 | inst_cream->opcode_1 = BITS(inst, 21, 23); | 528 | inst_cream->opcode_1 = BITS(inst, 21, 23); |
| 563 | inst_cream->opcode_2 = BITS(inst, 5, 7); | 529 | inst_cream->opcode_2 = BITS(inst, 5, 7); |
| 564 | inst_cream->Rd = BITS(inst, 12, 15); | 530 | inst_cream->Rd = BITS(inst, 12, 15); |
| 565 | inst_cream->cp_num = BITS(inst, 8, 11); | 531 | inst_cream->cp_num = BITS(inst, 8, 11); |
| 566 | inst_cream->inst = inst; | 532 | inst_cream->inst = inst; |
| 567 | return inst_base; | 533 | return inst_base; |
| 568 | } | 534 | } |
| 569 | 535 | ||
| 570 | static ARM_INST_PTR INTERPRETER_TRANSLATE(mcrr)(unsigned int inst, int index) | 536 | static ARM_INST_PTR INTERPRETER_TRANSLATE(mcrr)(unsigned int inst, int index) { |
| 571 | { | ||
| 572 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mcrr_inst)); | 537 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mcrr_inst)); |
| 573 | mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component; | 538 | mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component; |
| 574 | 539 | ||
| 575 | inst_base->cond = BITS(inst, 28, 31); | 540 | inst_base->cond = BITS(inst, 28, 31); |
| 576 | inst_base->idx = index; | 541 | inst_base->idx = index; |
| 577 | inst_base->br = TransExtData::NON_BRANCH; | 542 | inst_base->br = TransExtData::NON_BRANCH; |
| 578 | 543 | ||
| 579 | inst_cream->crm = BITS(inst, 0, 3); | 544 | inst_cream->crm = BITS(inst, 0, 3); |
| 580 | inst_cream->opcode_1 = BITS(inst, 4, 7); | 545 | inst_cream->opcode_1 = BITS(inst, 4, 7); |
| 581 | inst_cream->cp_num = BITS(inst, 8, 11); | 546 | inst_cream->cp_num = BITS(inst, 8, 11); |
| 582 | inst_cream->rt = BITS(inst, 12, 15); | 547 | inst_cream->rt = BITS(inst, 12, 15); |
| 583 | inst_cream->rt2 = BITS(inst, 16, 19); | 548 | inst_cream->rt2 = BITS(inst, 16, 19); |
| 584 | 549 | ||
| 585 | return inst_base; | 550 | return inst_base; |
| 586 | } | 551 | } |
| 587 | 552 | ||
| 588 | static ARM_INST_PTR INTERPRETER_TRANSLATE(mla)(unsigned int inst, int index) | 553 | static ARM_INST_PTR INTERPRETER_TRANSLATE(mla)(unsigned int inst, int index) { |
| 589 | { | 554 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mla_inst)); |
| 590 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mla_inst)); | 555 | mla_inst* inst_cream = (mla_inst*)inst_base->component; |
| 591 | mla_inst *inst_cream = (mla_inst *)inst_base->component; | ||
| 592 | 556 | ||
| 593 | inst_base->cond = BITS(inst, 28, 31); | 557 | inst_base->cond = BITS(inst, 28, 31); |
| 594 | inst_base->idx = index; | 558 | inst_base->idx = index; |
| 595 | inst_base->br = TransExtData::NON_BRANCH; | 559 | inst_base->br = TransExtData::NON_BRANCH; |
| 596 | 560 | ||
| 597 | inst_cream->S = BIT(inst, 20); | 561 | inst_cream->S = BIT(inst, 20); |
| 598 | inst_cream->Rn = BITS(inst, 12, 15); | 562 | inst_cream->Rn = BITS(inst, 12, 15); |
| 599 | inst_cream->Rd = BITS(inst, 16, 19); | 563 | inst_cream->Rd = BITS(inst, 16, 19); |
| 600 | inst_cream->Rs = BITS(inst, 8, 11); | 564 | inst_cream->Rs = BITS(inst, 8, 11); |
| 601 | inst_cream->Rm = BITS(inst, 0, 3); | 565 | inst_cream->Rm = BITS(inst, 0, 3); |
| 602 | 566 | ||
| 603 | return inst_base; | 567 | return inst_base; |
| 604 | } | 568 | } |
| 605 | static ARM_INST_PTR INTERPRETER_TRANSLATE(mov)(unsigned int inst, int index) | 569 | static ARM_INST_PTR INTERPRETER_TRANSLATE(mov)(unsigned int inst, int index) { |
| 606 | { | 570 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst)); |
| 607 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst)); | 571 | mov_inst* inst_cream = (mov_inst*)inst_base->component; |
| 608 | mov_inst *inst_cream = (mov_inst *)inst_base->component; | ||
| 609 | 572 | ||
| 610 | inst_base->cond = BITS(inst, 28, 31); | 573 | inst_base->cond = BITS(inst, 28, 31); |
| 611 | inst_base->idx = index; | 574 | inst_base->idx = index; |
| 612 | inst_base->br = TransExtData::NON_BRANCH; | 575 | inst_base->br = TransExtData::NON_BRANCH; |
| 613 | 576 | ||
| 614 | inst_cream->I = BIT(inst, 25); | 577 | inst_cream->I = BIT(inst, 25); |
| 615 | inst_cream->S = BIT(inst, 20); | 578 | inst_cream->S = BIT(inst, 20); |
| 616 | inst_cream->Rd = BITS(inst, 12, 15); | 579 | inst_cream->Rd = BITS(inst, 12, 15); |
| 617 | inst_cream->shifter_operand = BITS(inst, 0, 11); | 580 | inst_cream->shifter_operand = BITS(inst, 0, 11); |
| 618 | inst_cream->shtop_func = GetShifterOp(inst); | 581 | inst_cream->shtop_func = GetShifterOp(inst); |
| @@ -622,85 +585,79 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(mov)(unsigned int inst, int index) | |||
| 622 | } | 585 | } |
| 623 | return inst_base; | 586 | return inst_base; |
| 624 | } | 587 | } |
| 625 | static ARM_INST_PTR INTERPRETER_TRANSLATE(mrc)(unsigned int inst, int index) | 588 | static ARM_INST_PTR INTERPRETER_TRANSLATE(mrc)(unsigned int inst, int index) { |
| 626 | { | 589 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mrc_inst)); |
| 627 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrc_inst)); | 590 | mrc_inst* inst_cream = (mrc_inst*)inst_base->component; |
| 628 | mrc_inst *inst_cream = (mrc_inst *)inst_base->component; | ||
| 629 | inst_base->cond = BITS(inst, 28, 31); | 591 | inst_base->cond = BITS(inst, 28, 31); |
| 630 | inst_base->idx = index; | 592 | inst_base->idx = index; |
| 631 | inst_base->br = TransExtData::NON_BRANCH; | 593 | inst_base->br = TransExtData::NON_BRANCH; |
| 632 | 594 | ||
| 633 | inst_cream->crn = BITS(inst, 16, 19); | 595 | inst_cream->crn = BITS(inst, 16, 19); |
| 634 | inst_cream->crm = BITS(inst, 0, 3); | 596 | inst_cream->crm = BITS(inst, 0, 3); |
| 635 | inst_cream->opcode_1 = BITS(inst, 21, 23); | 597 | inst_cream->opcode_1 = BITS(inst, 21, 23); |
| 636 | inst_cream->opcode_2 = BITS(inst, 5, 7); | 598 | inst_cream->opcode_2 = BITS(inst, 5, 7); |
| 637 | inst_cream->Rd = BITS(inst, 12, 15); | 599 | inst_cream->Rd = BITS(inst, 12, 15); |
| 638 | inst_cream->cp_num = BITS(inst, 8, 11); | 600 | inst_cream->cp_num = BITS(inst, 8, 11); |
| 639 | inst_cream->inst = inst; | 601 | inst_cream->inst = inst; |
| 640 | return inst_base; | 602 | return inst_base; |
| 641 | } | 603 | } |
| 642 | 604 | ||
| 643 | static ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index) | 605 | static ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index) { |
| 644 | { | ||
| 645 | return INTERPRETER_TRANSLATE(mcrr)(inst, index); | 606 | return INTERPRETER_TRANSLATE(mcrr)(inst, index); |
| 646 | } | 607 | } |
| 647 | 608 | ||
| 648 | static ARM_INST_PTR INTERPRETER_TRANSLATE(mrs)(unsigned int inst, int index) | 609 | static ARM_INST_PTR INTERPRETER_TRANSLATE(mrs)(unsigned int inst, int index) { |
| 649 | { | 610 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mrs_inst)); |
| 650 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrs_inst)); | 611 | mrs_inst* inst_cream = (mrs_inst*)inst_base->component; |
| 651 | mrs_inst *inst_cream = (mrs_inst *)inst_base->component; | ||
| 652 | 612 | ||
| 653 | inst_base->cond = BITS(inst, 28, 31); | 613 | inst_base->cond = BITS(inst, 28, 31); |
| 654 | inst_base->idx = index; | 614 | inst_base->idx = index; |
| 655 | inst_base->br = TransExtData::NON_BRANCH; | 615 | inst_base->br = TransExtData::NON_BRANCH; |
| 656 | 616 | ||
| 657 | inst_cream->Rd = BITS(inst, 12, 15); | 617 | inst_cream->Rd = BITS(inst, 12, 15); |
| 658 | inst_cream->R = BIT(inst, 22); | 618 | inst_cream->R = BIT(inst, 22); |
| 659 | 619 | ||
| 660 | return inst_base; | 620 | return inst_base; |
| 661 | } | 621 | } |
| 662 | static ARM_INST_PTR INTERPRETER_TRANSLATE(msr)(unsigned int inst, int index) | 622 | static ARM_INST_PTR INTERPRETER_TRANSLATE(msr)(unsigned int inst, int index) { |
| 663 | { | 623 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(msr_inst)); |
| 664 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(msr_inst)); | 624 | msr_inst* inst_cream = (msr_inst*)inst_base->component; |
| 665 | msr_inst *inst_cream = (msr_inst *)inst_base->component; | ||
| 666 | 625 | ||
| 667 | inst_base->cond = BITS(inst, 28, 31); | 626 | inst_base->cond = BITS(inst, 28, 31); |
| 668 | inst_base->idx = index; | 627 | inst_base->idx = index; |
| 669 | inst_base->br = TransExtData::NON_BRANCH; | 628 | inst_base->br = TransExtData::NON_BRANCH; |
| 670 | 629 | ||
| 671 | inst_cream->field_mask = BITS(inst, 16, 19); | 630 | inst_cream->field_mask = BITS(inst, 16, 19); |
| 672 | inst_cream->R = BIT(inst, 22); | 631 | inst_cream->R = BIT(inst, 22); |
| 673 | inst_cream->inst = inst; | 632 | inst_cream->inst = inst; |
| 674 | 633 | ||
| 675 | return inst_base; | 634 | return inst_base; |
| 676 | } | 635 | } |
| 677 | static ARM_INST_PTR INTERPRETER_TRANSLATE(mul)(unsigned int inst, int index) | 636 | static ARM_INST_PTR INTERPRETER_TRANSLATE(mul)(unsigned int inst, int index) { |
| 678 | { | 637 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mul_inst)); |
| 679 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mul_inst)); | 638 | mul_inst* inst_cream = (mul_inst*)inst_base->component; |
| 680 | mul_inst *inst_cream = (mul_inst *)inst_base->component; | ||
| 681 | 639 | ||
| 682 | inst_base->cond = BITS(inst, 28, 31); | 640 | inst_base->cond = BITS(inst, 28, 31); |
| 683 | inst_base->idx = index; | 641 | inst_base->idx = index; |
| 684 | inst_base->br = TransExtData::NON_BRANCH; | 642 | inst_base->br = TransExtData::NON_BRANCH; |
| 685 | 643 | ||
| 686 | inst_cream->S = BIT(inst, 20); | 644 | inst_cream->S = BIT(inst, 20); |
| 687 | inst_cream->Rm = BITS(inst, 0, 3); | 645 | inst_cream->Rm = BITS(inst, 0, 3); |
| 688 | inst_cream->Rs = BITS(inst, 8, 11); | 646 | inst_cream->Rs = BITS(inst, 8, 11); |
| 689 | inst_cream->Rd = BITS(inst, 16, 19); | 647 | inst_cream->Rd = BITS(inst, 16, 19); |
| 690 | 648 | ||
| 691 | return inst_base; | 649 | return inst_base; |
| 692 | } | 650 | } |
| 693 | static ARM_INST_PTR INTERPRETER_TRANSLATE(mvn)(unsigned int inst, int index) | 651 | static ARM_INST_PTR INTERPRETER_TRANSLATE(mvn)(unsigned int inst, int index) { |
| 694 | { | 652 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mvn_inst)); |
| 695 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mvn_inst)); | 653 | mvn_inst* inst_cream = (mvn_inst*)inst_base->component; |
| 696 | mvn_inst *inst_cream = (mvn_inst *)inst_base->component; | ||
| 697 | 654 | ||
| 698 | inst_base->cond = BITS(inst, 28, 31); | 655 | inst_base->cond = BITS(inst, 28, 31); |
| 699 | inst_base->idx = index; | 656 | inst_base->idx = index; |
| 700 | inst_base->br = TransExtData::NON_BRANCH; | 657 | inst_base->br = TransExtData::NON_BRANCH; |
| 701 | 658 | ||
| 702 | inst_cream->I = BIT(inst, 25); | 659 | inst_cream->I = BIT(inst, 25); |
| 703 | inst_cream->S = BIT(inst, 20); | 660 | inst_cream->S = BIT(inst, 20); |
| 704 | inst_cream->Rd = BITS(inst, 12, 15); | 661 | inst_cream->Rd = BITS(inst, 12, 15); |
| 705 | inst_cream->shifter_operand = BITS(inst, 0, 11); | 662 | inst_cream->shifter_operand = BITS(inst, 0, 11); |
| 706 | inst_cream->shtop_func = GetShifterOp(inst); | 663 | inst_cream->shtop_func = GetShifterOp(inst); |
| @@ -709,19 +666,17 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(mvn)(unsigned int inst, int index) | |||
| 709 | inst_base->br = TransExtData::INDIRECT_BRANCH; | 666 | inst_base->br = TransExtData::INDIRECT_BRANCH; |
| 710 | } | 667 | } |
| 711 | return inst_base; | 668 | return inst_base; |
| 712 | |||
| 713 | } | 669 | } |
| 714 | static ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index) | 670 | static ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index) { |
| 715 | { | 671 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(orr_inst)); |
| 716 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(orr_inst)); | 672 | orr_inst* inst_cream = (orr_inst*)inst_base->component; |
| 717 | orr_inst *inst_cream = (orr_inst *)inst_base->component; | ||
| 718 | 673 | ||
| 719 | inst_base->cond = BITS(inst, 28, 31); | 674 | inst_base->cond = BITS(inst, 28, 31); |
| 720 | inst_base->idx = index; | 675 | inst_base->idx = index; |
| 721 | inst_base->br = TransExtData::NON_BRANCH; | 676 | inst_base->br = TransExtData::NON_BRANCH; |
| 722 | 677 | ||
| 723 | inst_cream->I = BIT(inst, 25); | 678 | inst_cream->I = BIT(inst, 25); |
| 724 | inst_cream->S = BIT(inst, 20); | 679 | inst_cream->S = BIT(inst, 20); |
| 725 | inst_cream->Rd = BITS(inst, 12, 15); | 680 | inst_cream->Rd = BITS(inst, 12, 15); |
| 726 | inst_cream->Rn = BITS(inst, 16, 19); | 681 | inst_cream->Rn = BITS(inst, 16, 19); |
| 727 | inst_cream->shifter_operand = BITS(inst, 0, 11); | 682 | inst_cream->shifter_operand = BITS(inst, 0, 11); |
| @@ -734,150 +689,132 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index) | |||
| 734 | } | 689 | } |
| 735 | 690 | ||
| 736 | // NOP introduced in ARMv6K. | 691 | // NOP introduced in ARMv6K. |
| 737 | static ARM_INST_PTR INTERPRETER_TRANSLATE(nop)(unsigned int inst, int index) | 692 | static ARM_INST_PTR INTERPRETER_TRANSLATE(nop)(unsigned int inst, int index) { |
| 738 | { | ||
| 739 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); | 693 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); |
| 740 | 694 | ||
| 741 | inst_base->cond = BITS(inst, 28, 31); | 695 | inst_base->cond = BITS(inst, 28, 31); |
| 742 | inst_base->idx = index; | 696 | inst_base->idx = index; |
| 743 | inst_base->br = TransExtData::NON_BRANCH; | 697 | inst_base->br = TransExtData::NON_BRANCH; |
| 744 | 698 | ||
| 745 | return inst_base; | 699 | return inst_base; |
| 746 | } | 700 | } |
| 747 | 701 | ||
| 748 | static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhbt)(unsigned int inst, int index) | 702 | static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhbt)(unsigned int inst, int index) { |
| 749 | { | 703 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(pkh_inst)); |
| 750 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pkh_inst)); | 704 | pkh_inst* inst_cream = (pkh_inst*)inst_base->component; |
| 751 | pkh_inst *inst_cream = (pkh_inst *)inst_base->component; | ||
| 752 | 705 | ||
| 753 | inst_base->cond = BITS(inst, 28, 31); | 706 | inst_base->cond = BITS(inst, 28, 31); |
| 754 | inst_base->idx = index; | 707 | inst_base->idx = index; |
| 755 | inst_base->br = TransExtData::NON_BRANCH; | 708 | inst_base->br = TransExtData::NON_BRANCH; |
| 756 | 709 | ||
| 757 | inst_cream->Rd = BITS(inst, 12, 15); | 710 | inst_cream->Rd = BITS(inst, 12, 15); |
| 758 | inst_cream->Rn = BITS(inst, 16, 19); | 711 | inst_cream->Rn = BITS(inst, 16, 19); |
| 759 | inst_cream->Rm = BITS(inst, 0, 3); | 712 | inst_cream->Rm = BITS(inst, 0, 3); |
| 760 | inst_cream->imm = BITS(inst, 7, 11); | 713 | inst_cream->imm = BITS(inst, 7, 11); |
| 761 | 714 | ||
| 762 | return inst_base; | 715 | return inst_base; |
| 763 | } | 716 | } |
| 764 | 717 | ||
| 765 | static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index) | 718 | static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index) { |
| 766 | { | ||
| 767 | return INTERPRETER_TRANSLATE(pkhbt)(inst, index); | 719 | return INTERPRETER_TRANSLATE(pkhbt)(inst, index); |
| 768 | } | 720 | } |
| 769 | 721 | ||
| 770 | static ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index) | 722 | static ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index) { |
| 771 | { | 723 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(pld_inst)); |
| 772 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pld_inst)); | ||
| 773 | 724 | ||
| 774 | inst_base->cond = BITS(inst, 28, 31); | 725 | inst_base->cond = BITS(inst, 28, 31); |
| 775 | inst_base->idx = index; | 726 | inst_base->idx = index; |
| 776 | inst_base->br = TransExtData::NON_BRANCH; | 727 | inst_base->br = TransExtData::NON_BRANCH; |
| 777 | 728 | ||
| 778 | return inst_base; | 729 | return inst_base; |
| 779 | } | 730 | } |
| 780 | 731 | ||
| 781 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) | 732 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) { |
| 782 | { | ||
| 783 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); | 733 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); |
| 784 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | 734 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; |
| 785 | 735 | ||
| 786 | inst_base->cond = BITS(inst, 28, 31); | 736 | inst_base->cond = BITS(inst, 28, 31); |
| 787 | inst_base->idx = index; | 737 | inst_base->idx = index; |
| 788 | inst_base->br = TransExtData::NON_BRANCH; | 738 | inst_base->br = TransExtData::NON_BRANCH; |
| 789 | 739 | ||
| 790 | inst_cream->op1 = BITS(inst, 21, 22); | 740 | inst_cream->op1 = BITS(inst, 21, 22); |
| 791 | inst_cream->Rm = BITS(inst, 0, 3); | 741 | inst_cream->Rm = BITS(inst, 0, 3); |
| 792 | inst_cream->Rn = BITS(inst, 16, 19); | 742 | inst_cream->Rn = BITS(inst, 16, 19); |
| 793 | inst_cream->Rd = BITS(inst, 12, 15); | 743 | inst_cream->Rd = BITS(inst, 12, 15); |
| 794 | 744 | ||
| 795 | return inst_base; | 745 | return inst_base; |
| 796 | } | 746 | } |
| 797 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) | 747 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) { |
| 798 | { | ||
| 799 | return INTERPRETER_TRANSLATE(qadd)(inst, index); | 748 | return INTERPRETER_TRANSLATE(qadd)(inst, index); |
| 800 | } | 749 | } |
| 801 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) | 750 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) { |
| 802 | { | ||
| 803 | return INTERPRETER_TRANSLATE(qadd)(inst, index); | 751 | return INTERPRETER_TRANSLATE(qadd)(inst, index); |
| 804 | } | 752 | } |
| 805 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) | 753 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) { |
| 806 | { | ||
| 807 | return INTERPRETER_TRANSLATE(qadd)(inst, index); | 754 | return INTERPRETER_TRANSLATE(qadd)(inst, index); |
| 808 | } | 755 | } |
| 809 | 756 | ||
| 810 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index) | 757 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index) { |
| 811 | { | ||
| 812 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); | 758 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); |
| 813 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | 759 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; |
| 814 | 760 | ||
| 815 | inst_base->cond = BITS(inst, 28, 31); | 761 | inst_base->cond = BITS(inst, 28, 31); |
| 816 | inst_base->idx = index; | 762 | inst_base->idx = index; |
| 817 | inst_base->br = TransExtData::NON_BRANCH; | 763 | inst_base->br = TransExtData::NON_BRANCH; |
| 818 | 764 | ||
| 819 | inst_cream->Rm = BITS(inst, 0, 3); | 765 | inst_cream->Rm = BITS(inst, 0, 3); |
| 820 | inst_cream->Rn = BITS(inst, 16, 19); | 766 | inst_cream->Rn = BITS(inst, 16, 19); |
| 821 | inst_cream->Rd = BITS(inst, 12, 15); | 767 | inst_cream->Rd = BITS(inst, 12, 15); |
| 822 | inst_cream->op1 = BITS(inst, 20, 21); | 768 | inst_cream->op1 = BITS(inst, 20, 21); |
| 823 | inst_cream->op2 = BITS(inst, 5, 7); | 769 | inst_cream->op2 = BITS(inst, 5, 7); |
| 824 | 770 | ||
| 825 | return inst_base; | 771 | return inst_base; |
| 826 | } | 772 | } |
| 827 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index) | 773 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index) { |
| 828 | { | ||
| 829 | return INTERPRETER_TRANSLATE(qadd8)(inst, index); | 774 | return INTERPRETER_TRANSLATE(qadd8)(inst, index); |
| 830 | } | 775 | } |
| 831 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index) | 776 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index) { |
| 832 | { | ||
| 833 | return INTERPRETER_TRANSLATE(qadd8)(inst, index); | 777 | return INTERPRETER_TRANSLATE(qadd8)(inst, index); |
| 834 | } | 778 | } |
| 835 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index) | 779 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index) { |
| 836 | { | ||
| 837 | return INTERPRETER_TRANSLATE(qadd8)(inst, index); | 780 | return INTERPRETER_TRANSLATE(qadd8)(inst, index); |
| 838 | } | 781 | } |
| 839 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index) | 782 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index) { |
| 840 | { | ||
| 841 | return INTERPRETER_TRANSLATE(qadd8)(inst, index); | 783 | return INTERPRETER_TRANSLATE(qadd8)(inst, index); |
| 842 | } | 784 | } |
| 843 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index) | 785 | static ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index) { |
| 844 | { | ||
| 845 | return INTERPRETER_TRANSLATE(qadd8)(inst, index); | 786 | return INTERPRETER_TRANSLATE(qadd8)(inst, index); |
| 846 | } | 787 | } |
| 847 | 788 | ||
| 848 | static ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index) | 789 | static ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index) { |
| 849 | { | ||
| 850 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst)); | 790 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst)); |
| 851 | rev_inst* const inst_cream = (rev_inst*)inst_base->component; | 791 | rev_inst* const inst_cream = (rev_inst*)inst_base->component; |
| 852 | 792 | ||
| 853 | inst_base->cond = BITS(inst, 28, 31); | 793 | inst_base->cond = BITS(inst, 28, 31); |
| 854 | inst_base->idx = index; | 794 | inst_base->idx = index; |
| 855 | inst_base->br = TransExtData::NON_BRANCH; | 795 | inst_base->br = TransExtData::NON_BRANCH; |
| 856 | 796 | ||
| 857 | inst_cream->Rm = BITS(inst, 0, 3); | 797 | inst_cream->Rm = BITS(inst, 0, 3); |
| 858 | inst_cream->Rd = BITS(inst, 12, 15); | 798 | inst_cream->Rd = BITS(inst, 12, 15); |
| 859 | inst_cream->op1 = BITS(inst, 20, 22); | 799 | inst_cream->op1 = BITS(inst, 20, 22); |
| 860 | inst_cream->op2 = BITS(inst, 5, 7); | 800 | inst_cream->op2 = BITS(inst, 5, 7); |
| 861 | 801 | ||
| 862 | return inst_base; | 802 | return inst_base; |
| 863 | } | 803 | } |
| 864 | static ARM_INST_PTR INTERPRETER_TRANSLATE(rev16)(unsigned int inst, int index) | 804 | static ARM_INST_PTR INTERPRETER_TRANSLATE(rev16)(unsigned int inst, int index) { |
| 865 | { | ||
| 866 | return INTERPRETER_TRANSLATE(rev)(inst, index); | 805 | return INTERPRETER_TRANSLATE(rev)(inst, index); |
| 867 | } | 806 | } |
| 868 | static ARM_INST_PTR INTERPRETER_TRANSLATE(revsh)(unsigned int inst, int index) | 807 | static ARM_INST_PTR INTERPRETER_TRANSLATE(revsh)(unsigned int inst, int index) { |
| 869 | { | 808 | return INTERPRETER_TRANSLATE(rev)(inst, index); |
| 870 | return INTERPRETER_TRANSLATE(rev)(inst, index); | ||
| 871 | } | 809 | } |
| 872 | 810 | ||
| 873 | static ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index) | 811 | static ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index) { |
| 874 | { | ||
| 875 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); | 812 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); |
| 876 | ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; | 813 | ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; |
| 877 | 814 | ||
| 878 | inst_base->cond = AL; | 815 | inst_base->cond = AL; |
| 879 | inst_base->idx = index; | 816 | inst_base->idx = index; |
| 880 | inst_base->br = TransExtData::INDIRECT_BRANCH; | 817 | inst_base->br = TransExtData::INDIRECT_BRANCH; |
| 881 | 818 | ||
| 882 | inst_cream->inst = inst; | 819 | inst_cream->inst = inst; |
| 883 | inst_cream->get_addr = GetAddressingOp(inst); | 820 | inst_cream->get_addr = GetAddressingOp(inst); |
| @@ -885,17 +822,16 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index) | |||
| 885 | return inst_base; | 822 | return inst_base; |
| 886 | } | 823 | } |
| 887 | 824 | ||
| 888 | static ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index) | 825 | static ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index) { |
| 889 | { | 826 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(rsb_inst)); |
| 890 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsb_inst)); | 827 | rsb_inst* inst_cream = (rsb_inst*)inst_base->component; |
| 891 | rsb_inst *inst_cream = (rsb_inst *)inst_base->component; | ||
| 892 | 828 | ||
| 893 | inst_base->cond = BITS(inst, 28, 31); | 829 | inst_base->cond = BITS(inst, 28, 31); |
| 894 | inst_base->idx = index; | 830 | inst_base->idx = index; |
| 895 | inst_base->br = TransExtData::NON_BRANCH; | 831 | inst_base->br = TransExtData::NON_BRANCH; |
| 896 | 832 | ||
| 897 | inst_cream->I = BIT(inst, 25); | 833 | inst_cream->I = BIT(inst, 25); |
| 898 | inst_cream->S = BIT(inst, 20); | 834 | inst_cream->S = BIT(inst, 20); |
| 899 | inst_cream->Rn = BITS(inst, 16, 19); | 835 | inst_cream->Rn = BITS(inst, 16, 19); |
| 900 | inst_cream->Rd = BITS(inst, 12, 15); | 836 | inst_cream->Rd = BITS(inst, 12, 15); |
| 901 | inst_cream->shifter_operand = BITS(inst, 0, 11); | 837 | inst_cream->shifter_operand = BITS(inst, 0, 11); |
| @@ -906,17 +842,16 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index) | |||
| 906 | 842 | ||
| 907 | return inst_base; | 843 | return inst_base; |
| 908 | } | 844 | } |
| 909 | static ARM_INST_PTR INTERPRETER_TRANSLATE(rsc)(unsigned int inst, int index) | 845 | static ARM_INST_PTR INTERPRETER_TRANSLATE(rsc)(unsigned int inst, int index) { |
| 910 | { | 846 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(rsc_inst)); |
| 911 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsc_inst)); | 847 | rsc_inst* inst_cream = (rsc_inst*)inst_base->component; |
| 912 | rsc_inst *inst_cream = (rsc_inst *)inst_base->component; | ||
| 913 | 848 | ||
| 914 | inst_base->cond = BITS(inst, 28, 31); | 849 | inst_base->cond = BITS(inst, 28, 31); |
| 915 | inst_base->idx = index; | 850 | inst_base->idx = index; |
| 916 | inst_base->br = TransExtData::NON_BRANCH; | 851 | inst_base->br = TransExtData::NON_BRANCH; |
| 917 | 852 | ||
| 918 | inst_cream->I = BIT(inst, 25); | 853 | inst_cream->I = BIT(inst, 25); |
| 919 | inst_cream->S = BIT(inst, 20); | 854 | inst_cream->S = BIT(inst, 20); |
| 920 | inst_cream->Rn = BITS(inst, 16, 19); | 855 | inst_cream->Rn = BITS(inst, 16, 19); |
| 921 | inst_cream->Rd = BITS(inst, 12, 15); | 856 | inst_cream->Rd = BITS(inst, 12, 15); |
| 922 | inst_cream->shifter_operand = BITS(inst, 0, 11); | 857 | inst_cream->shifter_operand = BITS(inst, 0, 11); |
| @@ -927,55 +862,48 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(rsc)(unsigned int inst, int index) | |||
| 927 | 862 | ||
| 928 | return inst_base; | 863 | return inst_base; |
| 929 | } | 864 | } |
| 930 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd8)(unsigned int inst, int index) | 865 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd8)(unsigned int inst, int index) { |
| 931 | { | ||
| 932 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); | 866 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); |
| 933 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | 867 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; |
| 934 | 868 | ||
| 935 | inst_base->cond = BITS(inst, 28, 31); | 869 | inst_base->cond = BITS(inst, 28, 31); |
| 936 | inst_base->idx = index; | 870 | inst_base->idx = index; |
| 937 | inst_base->br = TransExtData::NON_BRANCH; | 871 | inst_base->br = TransExtData::NON_BRANCH; |
| 938 | 872 | ||
| 939 | inst_cream->Rm = BITS(inst, 0, 3); | 873 | inst_cream->Rm = BITS(inst, 0, 3); |
| 940 | inst_cream->Rn = BITS(inst, 16, 19); | 874 | inst_cream->Rn = BITS(inst, 16, 19); |
| 941 | inst_cream->Rd = BITS(inst, 12, 15); | 875 | inst_cream->Rd = BITS(inst, 12, 15); |
| 942 | inst_cream->op1 = BITS(inst, 20, 21); | 876 | inst_cream->op1 = BITS(inst, 20, 21); |
| 943 | inst_cream->op2 = BITS(inst, 5, 7); | 877 | inst_cream->op2 = BITS(inst, 5, 7); |
| 944 | 878 | ||
| 945 | return inst_base; | 879 | return inst_base; |
| 946 | } | 880 | } |
| 947 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd16)(unsigned int inst, int index) | 881 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd16)(unsigned int inst, int index) { |
| 948 | { | ||
| 949 | return INTERPRETER_TRANSLATE(sadd8)(inst, index); | 882 | return INTERPRETER_TRANSLATE(sadd8)(inst, index); |
| 950 | } | 883 | } |
| 951 | static ARM_INST_PTR INTERPRETER_TRANSLATE(saddsubx)(unsigned int inst, int index) | 884 | static ARM_INST_PTR INTERPRETER_TRANSLATE(saddsubx)(unsigned int inst, int index) { |
| 952 | { | ||
| 953 | return INTERPRETER_TRANSLATE(sadd8)(inst, index); | 885 | return INTERPRETER_TRANSLATE(sadd8)(inst, index); |
| 954 | } | 886 | } |
| 955 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub8)(unsigned int inst, int index) | 887 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub8)(unsigned int inst, int index) { |
| 956 | { | ||
| 957 | return INTERPRETER_TRANSLATE(sadd8)(inst, index); | 888 | return INTERPRETER_TRANSLATE(sadd8)(inst, index); |
| 958 | } | 889 | } |
| 959 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub16)(unsigned int inst, int index) | 890 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub16)(unsigned int inst, int index) { |
| 960 | { | ||
| 961 | return INTERPRETER_TRANSLATE(sadd8)(inst, index); | 891 | return INTERPRETER_TRANSLATE(sadd8)(inst, index); |
| 962 | } | 892 | } |
| 963 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ssubaddx)(unsigned int inst, int index) | 893 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ssubaddx)(unsigned int inst, int index) { |
| 964 | { | ||
| 965 | return INTERPRETER_TRANSLATE(sadd8)(inst, index); | 894 | return INTERPRETER_TRANSLATE(sadd8)(inst, index); |
| 966 | } | 895 | } |
| 967 | 896 | ||
| 968 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sbc)(unsigned int inst, int index) | 897 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sbc)(unsigned int inst, int index) { |
| 969 | { | 898 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sbc_inst)); |
| 970 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sbc_inst)); | 899 | sbc_inst* inst_cream = (sbc_inst*)inst_base->component; |
| 971 | sbc_inst *inst_cream = (sbc_inst *)inst_base->component; | ||
| 972 | 900 | ||
| 973 | inst_base->cond = BITS(inst, 28, 31); | 901 | inst_base->cond = BITS(inst, 28, 31); |
| 974 | inst_base->idx = index; | 902 | inst_base->idx = index; |
| 975 | inst_base->br = TransExtData::NON_BRANCH; | 903 | inst_base->br = TransExtData::NON_BRANCH; |
| 976 | 904 | ||
| 977 | inst_cream->I = BIT(inst, 25); | 905 | inst_cream->I = BIT(inst, 25); |
| 978 | inst_cream->S = BIT(inst, 20); | 906 | inst_cream->S = BIT(inst, 20); |
| 979 | inst_cream->Rn = BITS(inst, 16, 19); | 907 | inst_cream->Rn = BITS(inst, 16, 19); |
| 980 | inst_cream->Rd = BITS(inst, 12, 15); | 908 | inst_cream->Rd = BITS(inst, 12, 15); |
| 981 | inst_cream->shifter_operand = BITS(inst, 0, 11); | 909 | inst_cream->shifter_operand = BITS(inst, 0, 11); |
| @@ -986,98 +914,88 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(sbc)(unsigned int inst, int index) | |||
| 986 | 914 | ||
| 987 | return inst_base; | 915 | return inst_base; |
| 988 | } | 916 | } |
| 989 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index) | 917 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index) { |
| 990 | { | ||
| 991 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); | 918 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); |
| 992 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | 919 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; |
| 993 | 920 | ||
| 994 | inst_base->cond = BITS(inst, 28, 31); | 921 | inst_base->cond = BITS(inst, 28, 31); |
| 995 | inst_base->idx = index; | 922 | inst_base->idx = index; |
| 996 | inst_base->br = TransExtData::NON_BRANCH; | 923 | inst_base->br = TransExtData::NON_BRANCH; |
| 997 | 924 | ||
| 998 | inst_cream->Rm = BITS(inst, 0, 3); | 925 | inst_cream->Rm = BITS(inst, 0, 3); |
| 999 | inst_cream->Rn = BITS(inst, 16, 19); | 926 | inst_cream->Rn = BITS(inst, 16, 19); |
| 1000 | inst_cream->Rd = BITS(inst, 12, 15); | 927 | inst_cream->Rd = BITS(inst, 12, 15); |
| 1001 | inst_cream->op1 = BITS(inst, 20, 22); | 928 | inst_cream->op1 = BITS(inst, 20, 22); |
| 1002 | inst_cream->op2 = BITS(inst, 5, 7); | 929 | inst_cream->op2 = BITS(inst, 5, 7); |
| 1003 | 930 | ||
| 1004 | return inst_base; | 931 | return inst_base; |
| 1005 | } | 932 | } |
| 1006 | 933 | ||
| 1007 | static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index) | 934 | static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index) { |
| 1008 | { | ||
| 1009 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(setend_inst)); | 935 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(setend_inst)); |
| 1010 | setend_inst* const inst_cream = (setend_inst*)inst_base->component; | 936 | setend_inst* const inst_cream = (setend_inst*)inst_base->component; |
| 1011 | 937 | ||
| 1012 | inst_base->cond = AL; | 938 | inst_base->cond = AL; |
| 1013 | inst_base->idx = index; | 939 | inst_base->idx = index; |
| 1014 | inst_base->br = TransExtData::NON_BRANCH; | 940 | inst_base->br = TransExtData::NON_BRANCH; |
| 1015 | 941 | ||
| 1016 | inst_cream->set_bigend = BIT(inst, 9); | 942 | inst_cream->set_bigend = BIT(inst, 9); |
| 1017 | 943 | ||
| 1018 | return inst_base; | 944 | return inst_base; |
| 1019 | } | 945 | } |
| 1020 | 946 | ||
| 1021 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sev)(unsigned int inst, int index) | 947 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sev)(unsigned int inst, int index) { |
| 1022 | { | ||
| 1023 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); | 948 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); |
| 1024 | 949 | ||
| 1025 | inst_base->cond = BITS(inst, 28, 31); | 950 | inst_base->cond = BITS(inst, 28, 31); |
| 1026 | inst_base->idx = index; | 951 | inst_base->idx = index; |
| 1027 | inst_base->br = TransExtData::NON_BRANCH; | 952 | inst_base->br = TransExtData::NON_BRANCH; |
| 1028 | 953 | ||
| 1029 | return inst_base; | 954 | return inst_base; |
| 1030 | } | 955 | } |
| 1031 | 956 | ||
| 1032 | static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index) | 957 | static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index) { |
| 1033 | { | ||
| 1034 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); | 958 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); |
| 1035 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | 959 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; |
| 1036 | 960 | ||
| 1037 | inst_base->cond = BITS(inst, 28, 31); | 961 | inst_base->cond = BITS(inst, 28, 31); |
| 1038 | inst_base->idx = index; | 962 | inst_base->idx = index; |
| 1039 | inst_base->br = TransExtData::NON_BRANCH; | 963 | inst_base->br = TransExtData::NON_BRANCH; |
| 1040 | 964 | ||
| 1041 | inst_cream->op1 = BITS(inst, 20, 21); | 965 | inst_cream->op1 = BITS(inst, 20, 21); |
| 1042 | inst_cream->op2 = BITS(inst, 5, 7); | 966 | inst_cream->op2 = BITS(inst, 5, 7); |
| 1043 | inst_cream->Rm = BITS(inst, 0, 3); | 967 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1044 | inst_cream->Rn = BITS(inst, 16, 19); | 968 | inst_cream->Rn = BITS(inst, 16, 19); |
| 1045 | inst_cream->Rd = BITS(inst, 12, 15); | 969 | inst_cream->Rd = BITS(inst, 12, 15); |
| 1046 | 970 | ||
| 1047 | return inst_base; | 971 | return inst_base; |
| 1048 | } | 972 | } |
| 1049 | static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd16)(unsigned int inst, int index) | 973 | static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd16)(unsigned int inst, int index) { |
| 1050 | { | ||
| 1051 | return INTERPRETER_TRANSLATE(shadd8)(inst, index); | 974 | return INTERPRETER_TRANSLATE(shadd8)(inst, index); |
| 1052 | } | 975 | } |
| 1053 | static ARM_INST_PTR INTERPRETER_TRANSLATE(shaddsubx)(unsigned int inst, int index) | 976 | static ARM_INST_PTR INTERPRETER_TRANSLATE(shaddsubx)(unsigned int inst, int index) { |
| 1054 | { | ||
| 1055 | return INTERPRETER_TRANSLATE(shadd8)(inst, index); | 977 | return INTERPRETER_TRANSLATE(shadd8)(inst, index); |
| 1056 | } | 978 | } |
| 1057 | static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub8)(unsigned int inst, int index) | 979 | static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub8)(unsigned int inst, int index) { |
| 1058 | { | ||
| 1059 | return INTERPRETER_TRANSLATE(shadd8)(inst, index); | 980 | return INTERPRETER_TRANSLATE(shadd8)(inst, index); |
| 1060 | } | 981 | } |
| 1061 | static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub16)(unsigned int inst, int index) | 982 | static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub16)(unsigned int inst, int index) { |
| 1062 | { | ||
| 1063 | return INTERPRETER_TRANSLATE(shadd8)(inst, index); | 983 | return INTERPRETER_TRANSLATE(shadd8)(inst, index); |
| 1064 | } | 984 | } |
| 1065 | static ARM_INST_PTR INTERPRETER_TRANSLATE(shsubaddx)(unsigned int inst, int index) | 985 | static ARM_INST_PTR INTERPRETER_TRANSLATE(shsubaddx)(unsigned int inst, int index) { |
| 1066 | { | ||
| 1067 | return INTERPRETER_TRANSLATE(shadd8)(inst, index); | 986 | return INTERPRETER_TRANSLATE(shadd8)(inst, index); |
| 1068 | } | 987 | } |
| 1069 | 988 | ||
| 1070 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index) | 989 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index) { |
| 1071 | { | 990 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smla_inst)); |
| 1072 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smla_inst)); | 991 | smla_inst* inst_cream = (smla_inst*)inst_base->component; |
| 1073 | smla_inst *inst_cream = (smla_inst *)inst_base->component; | ||
| 1074 | 992 | ||
| 1075 | inst_base->cond = BITS(inst, 28, 31); | 993 | inst_base->cond = BITS(inst, 28, 31); |
| 1076 | inst_base->idx = index; | 994 | inst_base->idx = index; |
| 1077 | inst_base->br = TransExtData::NON_BRANCH; | 995 | inst_base->br = TransExtData::NON_BRANCH; |
| 1078 | 996 | ||
| 1079 | inst_cream->x = BIT(inst, 5); | 997 | inst_cream->x = BIT(inst, 5); |
| 1080 | inst_cream->y = BIT(inst, 6); | 998 | inst_cream->y = BIT(inst, 6); |
| 1081 | inst_cream->Rm = BITS(inst, 0, 3); | 999 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1082 | inst_cream->Rs = BITS(inst, 8, 11); | 1000 | inst_cream->Rs = BITS(inst, 8, 11); |
| 1083 | inst_cream->Rd = BITS(inst, 16, 19); | 1001 | inst_cream->Rd = BITS(inst, 16, 19); |
| @@ -1086,192 +1004,176 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index) | |||
| 1086 | return inst_base; | 1004 | return inst_base; |
| 1087 | } | 1005 | } |
| 1088 | 1006 | ||
| 1089 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smlad)(unsigned int inst, int index) | 1007 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smlad)(unsigned int inst, int index) { |
| 1090 | { | ||
| 1091 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); | 1008 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); |
| 1092 | smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; | 1009 | smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; |
| 1093 | 1010 | ||
| 1094 | inst_base->cond = BITS(inst, 28, 31); | 1011 | inst_base->cond = BITS(inst, 28, 31); |
| 1095 | inst_base->idx = index; | 1012 | inst_base->idx = index; |
| 1096 | inst_base->br = TransExtData::NON_BRANCH; | 1013 | inst_base->br = TransExtData::NON_BRANCH; |
| 1097 | 1014 | ||
| 1098 | inst_cream->m = BIT(inst, 5); | 1015 | inst_cream->m = BIT(inst, 5); |
| 1099 | inst_cream->Rn = BITS(inst, 0, 3); | 1016 | inst_cream->Rn = BITS(inst, 0, 3); |
| 1100 | inst_cream->Rm = BITS(inst, 8, 11); | 1017 | inst_cream->Rm = BITS(inst, 8, 11); |
| 1101 | inst_cream->Rd = BITS(inst, 16, 19); | 1018 | inst_cream->Rd = BITS(inst, 16, 19); |
| 1102 | inst_cream->Ra = BITS(inst, 12, 15); | 1019 | inst_cream->Ra = BITS(inst, 12, 15); |
| 1103 | inst_cream->op1 = BITS(inst, 20, 22); | 1020 | inst_cream->op1 = BITS(inst, 20, 22); |
| 1104 | inst_cream->op2 = BITS(inst, 5, 7); | 1021 | inst_cream->op2 = BITS(inst, 5, 7); |
| 1105 | 1022 | ||
| 1106 | return inst_base; | 1023 | return inst_base; |
| 1107 | } | 1024 | } |
| 1108 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smuad)(unsigned int inst, int index) | 1025 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smuad)(unsigned int inst, int index) { |
| 1109 | { | ||
| 1110 | return INTERPRETER_TRANSLATE(smlad)(inst, index); | 1026 | return INTERPRETER_TRANSLATE(smlad)(inst, index); |
| 1111 | } | 1027 | } |
| 1112 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smusd)(unsigned int inst, int index) | 1028 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smusd)(unsigned int inst, int index) { |
| 1113 | { | ||
| 1114 | return INTERPRETER_TRANSLATE(smlad)(inst, index); | 1029 | return INTERPRETER_TRANSLATE(smlad)(inst, index); |
| 1115 | } | 1030 | } |
| 1116 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsd)(unsigned int inst, int index) | 1031 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsd)(unsigned int inst, int index) { |
| 1117 | { | ||
| 1118 | return INTERPRETER_TRANSLATE(smlad)(inst, index); | 1032 | return INTERPRETER_TRANSLATE(smlad)(inst, index); |
| 1119 | } | 1033 | } |
| 1120 | 1034 | ||
| 1121 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smlal)(unsigned int inst, int index) | 1035 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smlal)(unsigned int inst, int index) { |
| 1122 | { | 1036 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst)); |
| 1123 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst)); | 1037 | umlal_inst* inst_cream = (umlal_inst*)inst_base->component; |
| 1124 | umlal_inst *inst_cream = (umlal_inst *)inst_base->component; | ||
| 1125 | 1038 | ||
| 1126 | inst_base->cond = BITS(inst, 28, 31); | 1039 | inst_base->cond = BITS(inst, 28, 31); |
| 1127 | inst_base->idx = index; | 1040 | inst_base->idx = index; |
| 1128 | inst_base->br = TransExtData::NON_BRANCH; | 1041 | inst_base->br = TransExtData::NON_BRANCH; |
| 1129 | 1042 | ||
| 1130 | inst_cream->S = BIT(inst, 20); | 1043 | inst_cream->S = BIT(inst, 20); |
| 1131 | inst_cream->Rm = BITS(inst, 0, 3); | 1044 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1132 | inst_cream->Rs = BITS(inst, 8, 11); | 1045 | inst_cream->Rs = BITS(inst, 8, 11); |
| 1133 | inst_cream->RdHi = BITS(inst, 16, 19); | 1046 | inst_cream->RdHi = BITS(inst, 16, 19); |
| 1134 | inst_cream->RdLo = BITS(inst, 12, 15); | 1047 | inst_cream->RdLo = BITS(inst, 12, 15); |
| 1135 | 1048 | ||
| 1136 | return inst_base; | 1049 | return inst_base; |
| 1137 | } | 1050 | } |
| 1138 | 1051 | ||
| 1139 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index) | 1052 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index) { |
| 1140 | { | ||
| 1141 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlalxy_inst)); | 1053 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlalxy_inst)); |
| 1142 | smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component; | 1054 | smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component; |
| 1143 | 1055 | ||
| 1144 | inst_base->cond = BITS(inst, 28, 31); | 1056 | inst_base->cond = BITS(inst, 28, 31); |
| 1145 | inst_base->idx = index; | 1057 | inst_base->idx = index; |
| 1146 | inst_base->br = TransExtData::NON_BRANCH; | 1058 | inst_base->br = TransExtData::NON_BRANCH; |
| 1147 | 1059 | ||
| 1148 | inst_cream->x = BIT(inst, 5); | 1060 | inst_cream->x = BIT(inst, 5); |
| 1149 | inst_cream->y = BIT(inst, 6); | 1061 | inst_cream->y = BIT(inst, 6); |
| 1150 | inst_cream->RdLo = BITS(inst, 12, 15); | 1062 | inst_cream->RdLo = BITS(inst, 12, 15); |
| 1151 | inst_cream->RdHi = BITS(inst, 16, 19); | 1063 | inst_cream->RdHi = BITS(inst, 16, 19); |
| 1152 | inst_cream->Rn = BITS(inst, 0, 4); | 1064 | inst_cream->Rn = BITS(inst, 0, 4); |
| 1153 | inst_cream->Rm = BITS(inst, 8, 11); | 1065 | inst_cream->Rm = BITS(inst, 8, 11); |
| 1154 | 1066 | ||
| 1155 | return inst_base; | 1067 | return inst_base; |
| 1156 | } | 1068 | } |
| 1157 | 1069 | ||
| 1158 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index) | 1070 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index) { |
| 1159 | { | ||
| 1160 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); | 1071 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); |
| 1161 | smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; | 1072 | smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; |
| 1162 | 1073 | ||
| 1163 | inst_base->cond = BITS(inst, 28, 31); | 1074 | inst_base->cond = BITS(inst, 28, 31); |
| 1164 | inst_base->idx = index; | 1075 | inst_base->idx = index; |
| 1165 | inst_base->br = TransExtData::NON_BRANCH; | 1076 | inst_base->br = TransExtData::NON_BRANCH; |
| 1166 | 1077 | ||
| 1167 | inst_cream->Ra = BITS(inst, 12, 15); | 1078 | inst_cream->Ra = BITS(inst, 12, 15); |
| 1168 | inst_cream->Rm = BITS(inst, 8, 11); | 1079 | inst_cream->Rm = BITS(inst, 8, 11); |
| 1169 | inst_cream->Rn = BITS(inst, 0, 3); | 1080 | inst_cream->Rn = BITS(inst, 0, 3); |
| 1170 | inst_cream->Rd = BITS(inst, 16, 19); | 1081 | inst_cream->Rd = BITS(inst, 16, 19); |
| 1171 | inst_cream->m = BIT(inst, 6); | 1082 | inst_cream->m = BIT(inst, 6); |
| 1172 | 1083 | ||
| 1173 | return inst_base; | 1084 | return inst_base; |
| 1174 | } | 1085 | } |
| 1175 | 1086 | ||
| 1176 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index) | 1087 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index) { |
| 1177 | { | ||
| 1178 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlald_inst)); | 1088 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlald_inst)); |
| 1179 | smlald_inst* const inst_cream = (smlald_inst*)inst_base->component; | 1089 | smlald_inst* const inst_cream = (smlald_inst*)inst_base->component; |
| 1180 | 1090 | ||
| 1181 | inst_base->cond = BITS(inst, 28, 31); | 1091 | inst_base->cond = BITS(inst, 28, 31); |
| 1182 | inst_base->idx = index; | 1092 | inst_base->idx = index; |
| 1183 | inst_base->br = TransExtData::NON_BRANCH; | 1093 | inst_base->br = TransExtData::NON_BRANCH; |
| 1184 | 1094 | ||
| 1185 | inst_cream->Rm = BITS(inst, 8, 11); | 1095 | inst_cream->Rm = BITS(inst, 8, 11); |
| 1186 | inst_cream->Rn = BITS(inst, 0, 3); | 1096 | inst_cream->Rn = BITS(inst, 0, 3); |
| 1187 | inst_cream->RdLo = BITS(inst, 12, 15); | 1097 | inst_cream->RdLo = BITS(inst, 12, 15); |
| 1188 | inst_cream->RdHi = BITS(inst, 16, 19); | 1098 | inst_cream->RdHi = BITS(inst, 16, 19); |
| 1189 | inst_cream->swap = BIT(inst, 5); | 1099 | inst_cream->swap = BIT(inst, 5); |
| 1190 | inst_cream->op1 = BITS(inst, 20, 22); | 1100 | inst_cream->op1 = BITS(inst, 20, 22); |
| 1191 | inst_cream->op2 = BITS(inst, 5, 7); | 1101 | inst_cream->op2 = BITS(inst, 5, 7); |
| 1192 | 1102 | ||
| 1193 | return inst_base; | 1103 | return inst_base; |
| 1194 | } | 1104 | } |
| 1195 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsld)(unsigned int inst, int index) | 1105 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsld)(unsigned int inst, int index) { |
| 1196 | { | ||
| 1197 | return INTERPRETER_TRANSLATE(smlald)(inst, index); | 1106 | return INTERPRETER_TRANSLATE(smlald)(inst, index); |
| 1198 | } | 1107 | } |
| 1199 | 1108 | ||
| 1200 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smmla)(unsigned int inst, int index) | 1109 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smmla)(unsigned int inst, int index) { |
| 1201 | { | ||
| 1202 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); | 1110 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); |
| 1203 | smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; | 1111 | smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; |
| 1204 | 1112 | ||
| 1205 | inst_base->cond = BITS(inst, 28, 31); | 1113 | inst_base->cond = BITS(inst, 28, 31); |
| 1206 | inst_base->idx = index; | 1114 | inst_base->idx = index; |
| 1207 | inst_base->br = TransExtData::NON_BRANCH; | 1115 | inst_base->br = TransExtData::NON_BRANCH; |
| 1208 | 1116 | ||
| 1209 | inst_cream->m = BIT(inst, 5); | 1117 | inst_cream->m = BIT(inst, 5); |
| 1210 | inst_cream->Ra = BITS(inst, 12, 15); | 1118 | inst_cream->Ra = BITS(inst, 12, 15); |
| 1211 | inst_cream->Rm = BITS(inst, 8, 11); | 1119 | inst_cream->Rm = BITS(inst, 8, 11); |
| 1212 | inst_cream->Rn = BITS(inst, 0, 3); | 1120 | inst_cream->Rn = BITS(inst, 0, 3); |
| 1213 | inst_cream->Rd = BITS(inst, 16, 19); | 1121 | inst_cream->Rd = BITS(inst, 16, 19); |
| 1214 | inst_cream->op1 = BITS(inst, 20, 22); | 1122 | inst_cream->op1 = BITS(inst, 20, 22); |
| 1215 | inst_cream->op2 = BITS(inst, 5, 7); | 1123 | inst_cream->op2 = BITS(inst, 5, 7); |
| 1216 | 1124 | ||
| 1217 | return inst_base; | 1125 | return inst_base; |
| 1218 | } | 1126 | } |
| 1219 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smmls)(unsigned int inst, int index) | 1127 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smmls)(unsigned int inst, int index) { |
| 1220 | { | ||
| 1221 | return INTERPRETER_TRANSLATE(smmla)(inst, index); | 1128 | return INTERPRETER_TRANSLATE(smmla)(inst, index); |
| 1222 | } | 1129 | } |
| 1223 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smmul)(unsigned int inst, int index) | 1130 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smmul)(unsigned int inst, int index) { |
| 1224 | { | ||
| 1225 | return INTERPRETER_TRANSLATE(smmla)(inst, index); | 1131 | return INTERPRETER_TRANSLATE(smmla)(inst, index); |
| 1226 | } | 1132 | } |
| 1227 | 1133 | ||
| 1228 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smul)(unsigned int inst, int index) | 1134 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smul)(unsigned int inst, int index) { |
| 1229 | { | 1135 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smul_inst)); |
| 1230 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smul_inst)); | 1136 | smul_inst* inst_cream = (smul_inst*)inst_base->component; |
| 1231 | smul_inst *inst_cream = (smul_inst *)inst_base->component; | ||
| 1232 | 1137 | ||
| 1233 | inst_base->cond = BITS(inst, 28, 31); | 1138 | inst_base->cond = BITS(inst, 28, 31); |
| 1234 | inst_base->idx = index; | 1139 | inst_base->idx = index; |
| 1235 | inst_base->br = TransExtData::NON_BRANCH; | 1140 | inst_base->br = TransExtData::NON_BRANCH; |
| 1236 | 1141 | ||
| 1237 | inst_cream->Rd = BITS(inst, 16, 19); | 1142 | inst_cream->Rd = BITS(inst, 16, 19); |
| 1238 | inst_cream->Rs = BITS(inst, 8, 11); | 1143 | inst_cream->Rs = BITS(inst, 8, 11); |
| 1239 | inst_cream->Rm = BITS(inst, 0, 3); | 1144 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1240 | 1145 | ||
| 1241 | inst_cream->x = BIT(inst, 5); | 1146 | inst_cream->x = BIT(inst, 5); |
| 1242 | inst_cream->y = BIT(inst, 6); | 1147 | inst_cream->y = BIT(inst, 6); |
| 1243 | 1148 | ||
| 1244 | return inst_base; | 1149 | return inst_base; |
| 1245 | |||
| 1246 | } | 1150 | } |
| 1247 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smull)(unsigned int inst, int index) | 1151 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smull)(unsigned int inst, int index) { |
| 1248 | { | 1152 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst)); |
| 1249 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst)); | 1153 | umull_inst* inst_cream = (umull_inst*)inst_base->component; |
| 1250 | umull_inst *inst_cream = (umull_inst *)inst_base->component; | ||
| 1251 | 1154 | ||
| 1252 | inst_base->cond = BITS(inst, 28, 31); | 1155 | inst_base->cond = BITS(inst, 28, 31); |
| 1253 | inst_base->idx = index; | 1156 | inst_base->idx = index; |
| 1254 | inst_base->br = TransExtData::NON_BRANCH; | 1157 | inst_base->br = TransExtData::NON_BRANCH; |
| 1255 | 1158 | ||
| 1256 | inst_cream->S = BIT(inst, 20); | 1159 | inst_cream->S = BIT(inst, 20); |
| 1257 | inst_cream->Rm = BITS(inst, 0, 3); | 1160 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1258 | inst_cream->Rs = BITS(inst, 8, 11); | 1161 | inst_cream->Rs = BITS(inst, 8, 11); |
| 1259 | inst_cream->RdHi = BITS(inst, 16, 19); | 1162 | inst_cream->RdHi = BITS(inst, 16, 19); |
| 1260 | inst_cream->RdLo = BITS(inst, 12, 15); | 1163 | inst_cream->RdLo = BITS(inst, 12, 15); |
| 1261 | 1164 | ||
| 1262 | return inst_base; | 1165 | return inst_base; |
| 1263 | } | 1166 | } |
| 1264 | 1167 | ||
| 1265 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index) | 1168 | static ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index) { |
| 1266 | { | 1169 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); |
| 1267 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); | 1170 | smlad_inst* inst_cream = (smlad_inst*)inst_base->component; |
| 1268 | smlad_inst *inst_cream = (smlad_inst *)inst_base->component; | ||
| 1269 | 1171 | ||
| 1270 | inst_base->cond = BITS(inst, 28, 31); | 1172 | inst_base->cond = BITS(inst, 28, 31); |
| 1271 | inst_base->idx = index; | 1173 | inst_base->idx = index; |
| 1272 | inst_base->br = TransExtData::NON_BRANCH; | 1174 | inst_base->br = TransExtData::NON_BRANCH; |
| 1273 | 1175 | ||
| 1274 | inst_cream->m = BIT(inst, 6); | 1176 | inst_cream->m = BIT(inst, 6); |
| 1275 | inst_cream->Rm = BITS(inst, 8, 11); | 1177 | inst_cream->Rm = BITS(inst, 8, 11); |
| 1276 | inst_cream->Rn = BITS(inst, 0, 3); | 1178 | inst_cream->Rn = BITS(inst, 0, 3); |
| 1277 | inst_cream->Rd = BITS(inst, 16, 19); | 1179 | inst_cream->Rd = BITS(inst, 16, 19); |
| @@ -1279,29 +1181,27 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index) | |||
| 1279 | return inst_base; | 1181 | return inst_base; |
| 1280 | } | 1182 | } |
| 1281 | 1183 | ||
| 1282 | static ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index) | 1184 | static ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index) { |
| 1283 | { | ||
| 1284 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); | 1185 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); |
| 1285 | ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; | 1186 | ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; |
| 1286 | 1187 | ||
| 1287 | inst_base->cond = AL; | 1188 | inst_base->cond = AL; |
| 1288 | inst_base->idx = index; | 1189 | inst_base->idx = index; |
| 1289 | inst_base->br = TransExtData::NON_BRANCH; | 1190 | inst_base->br = TransExtData::NON_BRANCH; |
| 1290 | 1191 | ||
| 1291 | inst_cream->inst = inst; | 1192 | inst_cream->inst = inst; |
| 1292 | inst_cream->get_addr = GetAddressingOp(inst); | 1193 | inst_cream->get_addr = GetAddressingOp(inst); |
| 1293 | 1194 | ||
| 1294 | return inst_base; | 1195 | return inst_base; |
| 1295 | } | 1196 | } |
| 1296 | 1197 | ||
| 1297 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index) | 1198 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index) { |
| 1298 | { | ||
| 1299 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst)); | 1199 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst)); |
| 1300 | ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; | 1200 | ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; |
| 1301 | 1201 | ||
| 1302 | inst_base->cond = BITS(inst, 28, 31); | 1202 | inst_base->cond = BITS(inst, 28, 31); |
| 1303 | inst_base->idx = index; | 1203 | inst_base->idx = index; |
| 1304 | inst_base->br = TransExtData::NON_BRANCH; | 1204 | inst_base->br = TransExtData::NON_BRANCH; |
| 1305 | 1205 | ||
| 1306 | inst_cream->Rn = BITS(inst, 0, 3); | 1206 | inst_cream->Rn = BITS(inst, 0, 3); |
| 1307 | inst_cream->Rd = BITS(inst, 12, 15); | 1207 | inst_cream->Rd = BITS(inst, 12, 15); |
| @@ -1311,211 +1211,195 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index) | |||
| 1311 | 1211 | ||
| 1312 | return inst_base; | 1212 | return inst_base; |
| 1313 | } | 1213 | } |
| 1314 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat16)(unsigned int inst, int index) | 1214 | static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat16)(unsigned int inst, int index) { |
| 1315 | { | ||
| 1316 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst)); | 1215 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst)); |
| 1317 | ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; | 1216 | ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; |
| 1318 | 1217 | ||
| 1319 | inst_base->cond = BITS(inst, 28, 31); | 1218 | inst_base->cond = BITS(inst, 28, 31); |
| 1320 | inst_base->idx = index; | 1219 | inst_base->idx = index; |
| 1321 | inst_base->br = TransExtData::NON_BRANCH; | 1220 | inst_base->br = TransExtData::NON_BRANCH; |
| 1322 | 1221 | ||
| 1323 | inst_cream->Rn = BITS(inst, 0, 3); | 1222 | inst_cream->Rn = BITS(inst, 0, 3); |
| 1324 | inst_cream->Rd = BITS(inst, 12, 15); | 1223 | inst_cream->Rd = BITS(inst, 12, 15); |
| 1325 | inst_cream->sat_imm = BITS(inst, 16, 19); | 1224 | inst_cream->sat_imm = BITS(inst, 16, 19); |
| 1326 | 1225 | ||
| 1327 | return inst_base; | 1226 | return inst_base; |
| 1328 | } | 1227 | } |
| 1329 | 1228 | ||
| 1330 | static ARM_INST_PTR INTERPRETER_TRANSLATE(stc)(unsigned int inst, int index) | 1229 | static ARM_INST_PTR INTERPRETER_TRANSLATE(stc)(unsigned int inst, int index) { |
| 1331 | { | 1230 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(stc_inst)); |
| 1332 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(stc_inst)); | ||
| 1333 | inst_base->cond = BITS(inst, 28, 31); | 1231 | inst_base->cond = BITS(inst, 28, 31); |
| 1334 | inst_base->idx = index; | 1232 | inst_base->idx = index; |
| 1335 | inst_base->br = TransExtData::NON_BRANCH; | 1233 | inst_base->br = TransExtData::NON_BRANCH; |
| 1336 | 1234 | ||
| 1337 | return inst_base; | 1235 | return inst_base; |
| 1338 | } | 1236 | } |
| 1339 | static ARM_INST_PTR INTERPRETER_TRANSLATE(stm)(unsigned int inst, int index) | 1237 | static ARM_INST_PTR INTERPRETER_TRANSLATE(stm)(unsigned int inst, int index) { |
| 1340 | { | 1238 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); |
| 1341 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); | 1239 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 1342 | ldst_inst *inst_cream = (ldst_inst *)inst_base->component; | ||
| 1343 | 1240 | ||
| 1344 | inst_base->cond = BITS(inst, 28, 31); | 1241 | inst_base->cond = BITS(inst, 28, 31); |
| 1345 | inst_base->idx = index; | 1242 | inst_base->idx = index; |
| 1346 | inst_base->br = TransExtData::NON_BRANCH; | 1243 | inst_base->br = TransExtData::NON_BRANCH; |
| 1347 | 1244 | ||
| 1348 | inst_cream->inst = inst; | 1245 | inst_cream->inst = inst; |
| 1349 | inst_cream->get_addr = GetAddressingOp(inst); | 1246 | inst_cream->get_addr = GetAddressingOp(inst); |
| 1350 | return inst_base; | 1247 | return inst_base; |
| 1351 | } | 1248 | } |
| 1352 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb)(unsigned int inst, int index) | 1249 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb)(unsigned int inst, int index) { |
| 1353 | { | 1250 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst)); |
| 1354 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst)); | 1251 | sxtb_inst* inst_cream = (sxtb_inst*)inst_base->component; |
| 1355 | sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component; | ||
| 1356 | 1252 | ||
| 1357 | inst_base->cond = BITS(inst, 28, 31); | 1253 | inst_base->cond = BITS(inst, 28, 31); |
| 1358 | inst_base->idx = index; | 1254 | inst_base->idx = index; |
| 1359 | inst_base->br = TransExtData::NON_BRANCH; | 1255 | inst_base->br = TransExtData::NON_BRANCH; |
| 1360 | 1256 | ||
| 1361 | inst_cream->Rd = BITS(inst, 12, 15); | 1257 | inst_cream->Rd = BITS(inst, 12, 15); |
| 1362 | inst_cream->Rm = BITS(inst, 0, 3); | 1258 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1363 | inst_cream->rotate = BITS(inst, 10, 11); | 1259 | inst_cream->rotate = BITS(inst, 10, 11); |
| 1364 | 1260 | ||
| 1365 | return inst_base; | 1261 | return inst_base; |
| 1366 | } | 1262 | } |
| 1367 | static ARM_INST_PTR INTERPRETER_TRANSLATE(str)(unsigned int inst, int index) | 1263 | static ARM_INST_PTR INTERPRETER_TRANSLATE(str)(unsigned int inst, int index) { |
| 1368 | { | 1264 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); |
| 1369 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); | 1265 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 1370 | ldst_inst *inst_cream = (ldst_inst *)inst_base->component; | ||
| 1371 | 1266 | ||
| 1372 | inst_base->cond = BITS(inst, 28, 31); | 1267 | inst_base->cond = BITS(inst, 28, 31); |
| 1373 | inst_base->idx = index; | 1268 | inst_base->idx = index; |
| 1374 | inst_base->br = TransExtData::NON_BRANCH; | 1269 | inst_base->br = TransExtData::NON_BRANCH; |
| 1375 | 1270 | ||
| 1376 | inst_cream->inst = inst; | 1271 | inst_cream->inst = inst; |
| 1377 | inst_cream->get_addr = GetAddressingOp(inst); | 1272 | inst_cream->get_addr = GetAddressingOp(inst); |
| 1378 | 1273 | ||
| 1379 | return inst_base; | 1274 | return inst_base; |
| 1380 | } | 1275 | } |
| 1381 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb)(unsigned int inst, int index) | 1276 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb)(unsigned int inst, int index) { |
| 1382 | { | 1277 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst)); |
| 1383 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst)); | 1278 | uxth_inst* inst_cream = (uxth_inst*)inst_base->component; |
| 1384 | uxth_inst *inst_cream = (uxth_inst *)inst_base->component; | ||
| 1385 | 1279 | ||
| 1386 | inst_base->cond = BITS(inst, 28, 31); | 1280 | inst_base->cond = BITS(inst, 28, 31); |
| 1387 | inst_base->idx = index; | 1281 | inst_base->idx = index; |
| 1388 | inst_base->br = TransExtData::NON_BRANCH; | 1282 | inst_base->br = TransExtData::NON_BRANCH; |
| 1389 | 1283 | ||
| 1390 | inst_cream->Rd = BITS(inst, 12, 15); | 1284 | inst_cream->Rd = BITS(inst, 12, 15); |
| 1391 | inst_cream->rotate = BITS(inst, 10, 11); | 1285 | inst_cream->rotate = BITS(inst, 10, 11); |
| 1392 | inst_cream->Rm = BITS(inst, 0, 3); | 1286 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1393 | 1287 | ||
| 1394 | return inst_base; | 1288 | return inst_base; |
| 1395 | } | 1289 | } |
| 1396 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab)(unsigned int inst, int index) | 1290 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab)(unsigned int inst, int index) { |
| 1397 | { | 1291 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst)); |
| 1398 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst)); | 1292 | uxtab_inst* inst_cream = (uxtab_inst*)inst_base->component; |
| 1399 | uxtab_inst *inst_cream = (uxtab_inst *)inst_base->component; | ||
| 1400 | 1293 | ||
| 1401 | inst_base->cond = BITS(inst, 28, 31); | 1294 | inst_base->cond = BITS(inst, 28, 31); |
| 1402 | inst_base->idx = index; | 1295 | inst_base->idx = index; |
| 1403 | inst_base->br = TransExtData::NON_BRANCH; | 1296 | inst_base->br = TransExtData::NON_BRANCH; |
| 1404 | 1297 | ||
| 1405 | inst_cream->Rd = BITS(inst, 12, 15); | 1298 | inst_cream->Rd = BITS(inst, 12, 15); |
| 1406 | inst_cream->rotate = BITS(inst, 10, 11); | 1299 | inst_cream->rotate = BITS(inst, 10, 11); |
| 1407 | inst_cream->Rm = BITS(inst, 0, 3); | 1300 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1408 | inst_cream->Rn = BITS(inst, 16, 19); | 1301 | inst_cream->Rn = BITS(inst, 16, 19); |
| 1409 | 1302 | ||
| 1410 | return inst_base; | 1303 | return inst_base; |
| 1411 | } | 1304 | } |
| 1412 | static ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index) | 1305 | static ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index) { |
| 1413 | { | 1306 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); |
| 1414 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); | 1307 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 1415 | ldst_inst *inst_cream = (ldst_inst *)inst_base->component; | ||
| 1416 | 1308 | ||
| 1417 | inst_base->cond = BITS(inst, 28, 31); | 1309 | inst_base->cond = BITS(inst, 28, 31); |
| 1418 | inst_base->idx = index; | 1310 | inst_base->idx = index; |
| 1419 | inst_base->br = TransExtData::NON_BRANCH; | 1311 | inst_base->br = TransExtData::NON_BRANCH; |
| 1420 | 1312 | ||
| 1421 | inst_cream->inst = inst; | 1313 | inst_cream->inst = inst; |
| 1422 | inst_cream->get_addr = GetAddressingOp(inst); | 1314 | inst_cream->get_addr = GetAddressingOp(inst); |
| 1423 | 1315 | ||
| 1424 | return inst_base; | 1316 | return inst_base; |
| 1425 | } | 1317 | } |
| 1426 | static ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index) | 1318 | static ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index) { |
| 1427 | { | ||
| 1428 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); | 1319 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); |
| 1429 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | 1320 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 1430 | 1321 | ||
| 1431 | inst_base->cond = BITS(inst, 28, 31); | 1322 | inst_base->cond = BITS(inst, 28, 31); |
| 1432 | inst_base->idx = index; | 1323 | inst_base->idx = index; |
| 1433 | inst_base->br = TransExtData::NON_BRANCH; | 1324 | inst_base->br = TransExtData::NON_BRANCH; |
| 1434 | 1325 | ||
| 1435 | inst_cream->inst = inst; | 1326 | inst_cream->inst = inst; |
| 1436 | inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); | 1327 | inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); |
| 1437 | 1328 | ||
| 1438 | return inst_base; | 1329 | return inst_base; |
| 1439 | } | 1330 | } |
| 1440 | static ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index){ | 1331 | static ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index) { |
| 1441 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); | 1332 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); |
| 1442 | ldst_inst *inst_cream = (ldst_inst *)inst_base->component; | 1333 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 1443 | 1334 | ||
| 1444 | inst_base->cond = BITS(inst, 28, 31); | 1335 | inst_base->cond = BITS(inst, 28, 31); |
| 1445 | inst_base->idx = index; | 1336 | inst_base->idx = index; |
| 1446 | inst_base->br = TransExtData::NON_BRANCH; | 1337 | inst_base->br = TransExtData::NON_BRANCH; |
| 1447 | 1338 | ||
| 1448 | inst_cream->inst = inst; | 1339 | inst_cream->inst = inst; |
| 1449 | inst_cream->get_addr = GetAddressingOp(inst); | 1340 | inst_cream->get_addr = GetAddressingOp(inst); |
| 1450 | 1341 | ||
| 1451 | return inst_base; | 1342 | return inst_base; |
| 1452 | } | 1343 | } |
| 1453 | static ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index) | 1344 | static ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index) { |
| 1454 | { | 1345 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); |
| 1455 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); | 1346 | generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |
| 1456 | generic_arm_inst *inst_cream = (generic_arm_inst *)inst_base->component; | ||
| 1457 | 1347 | ||
| 1458 | inst_base->cond = BITS(inst, 28, 31); | 1348 | inst_base->cond = BITS(inst, 28, 31); |
| 1459 | inst_base->idx = index; | 1349 | inst_base->idx = index; |
| 1460 | inst_base->br = TransExtData::NON_BRANCH; | 1350 | inst_base->br = TransExtData::NON_BRANCH; |
| 1461 | 1351 | ||
| 1462 | inst_cream->Rn = BITS(inst, 16, 19); | 1352 | inst_cream->Rn = BITS(inst, 16, 19); |
| 1463 | inst_cream->Rd = BITS(inst, 12, 15); | 1353 | inst_cream->Rd = BITS(inst, 12, 15); |
| 1464 | inst_cream->Rm = BITS(inst, 0, 3); | 1354 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1465 | 1355 | ||
| 1466 | return inst_base; | 1356 | return inst_base; |
| 1467 | } | 1357 | } |
| 1468 | static ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index) | 1358 | static ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index) { |
| 1469 | { | ||
| 1470 | return INTERPRETER_TRANSLATE(strex)(inst, index); | 1359 | return INTERPRETER_TRANSLATE(strex)(inst, index); |
| 1471 | } | 1360 | } |
| 1472 | static ARM_INST_PTR INTERPRETER_TRANSLATE(strexh)(unsigned int inst, int index) | 1361 | static ARM_INST_PTR INTERPRETER_TRANSLATE(strexh)(unsigned int inst, int index) { |
| 1473 | { | ||
| 1474 | return INTERPRETER_TRANSLATE(strex)(inst, index); | 1362 | return INTERPRETER_TRANSLATE(strex)(inst, index); |
| 1475 | } | 1363 | } |
| 1476 | static ARM_INST_PTR INTERPRETER_TRANSLATE(strexd)(unsigned int inst, int index) | 1364 | static ARM_INST_PTR INTERPRETER_TRANSLATE(strexd)(unsigned int inst, int index) { |
| 1477 | { | ||
| 1478 | return INTERPRETER_TRANSLATE(strex)(inst, index); | 1365 | return INTERPRETER_TRANSLATE(strex)(inst, index); |
| 1479 | } | 1366 | } |
| 1480 | static ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index) | 1367 | static ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index) { |
| 1481 | { | 1368 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); |
| 1482 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); | 1369 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 1483 | ldst_inst *inst_cream = (ldst_inst *)inst_base->component; | ||
| 1484 | 1370 | ||
| 1485 | inst_base->cond = BITS(inst, 28, 31); | 1371 | inst_base->cond = BITS(inst, 28, 31); |
| 1486 | inst_base->idx = index; | 1372 | inst_base->idx = index; |
| 1487 | inst_base->br = TransExtData::NON_BRANCH; | 1373 | inst_base->br = TransExtData::NON_BRANCH; |
| 1488 | 1374 | ||
| 1489 | inst_cream->inst = inst; | 1375 | inst_cream->inst = inst; |
| 1490 | inst_cream->get_addr = GetAddressingOp(inst); | 1376 | inst_cream->get_addr = GetAddressingOp(inst); |
| 1491 | 1377 | ||
| 1492 | return inst_base; | 1378 | return inst_base; |
| 1493 | } | 1379 | } |
| 1494 | static ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index) | 1380 | static ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index) { |
| 1495 | { | ||
| 1496 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); | 1381 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); |
| 1497 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | 1382 | ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |
| 1498 | 1383 | ||
| 1499 | inst_base->cond = BITS(inst, 28, 31); | 1384 | inst_base->cond = BITS(inst, 28, 31); |
| 1500 | inst_base->idx = index; | 1385 | inst_base->idx = index; |
| 1501 | inst_base->br = TransExtData::NON_BRANCH; | 1386 | inst_base->br = TransExtData::NON_BRANCH; |
| 1502 | 1387 | ||
| 1503 | inst_cream->inst = inst; | 1388 | inst_cream->inst = inst; |
| 1504 | inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); | 1389 | inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); |
| 1505 | 1390 | ||
| 1506 | return inst_base; | 1391 | return inst_base; |
| 1507 | } | 1392 | } |
| 1508 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index) | 1393 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index) { |
| 1509 | { | 1394 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sub_inst)); |
| 1510 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sub_inst)); | 1395 | sub_inst* inst_cream = (sub_inst*)inst_base->component; |
| 1511 | sub_inst *inst_cream = (sub_inst *)inst_base->component; | ||
| 1512 | 1396 | ||
| 1513 | inst_base->cond = BITS(inst, 28, 31); | 1397 | inst_base->cond = BITS(inst, 28, 31); |
| 1514 | inst_base->idx = index; | 1398 | inst_base->idx = index; |
| 1515 | inst_base->br = TransExtData::NON_BRANCH; | 1399 | inst_base->br = TransExtData::NON_BRANCH; |
| 1516 | 1400 | ||
| 1517 | inst_cream->I = BIT(inst, 25); | 1401 | inst_cream->I = BIT(inst, 25); |
| 1518 | inst_cream->S = BIT(inst, 20); | 1402 | inst_cream->S = BIT(inst, 20); |
| 1519 | inst_cream->Rn = BITS(inst, 16, 19); | 1403 | inst_cream->Rn = BITS(inst, 16, 19); |
| 1520 | inst_cream->Rd = BITS(inst, 12, 15); | 1404 | inst_cream->Rd = BITS(inst, 12, 15); |
| 1521 | inst_cream->shifter_operand = BITS(inst, 0, 11); | 1405 | inst_cream->shifter_operand = BITS(inst, 0, 11); |
| @@ -1526,71 +1410,68 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index) | |||
| 1526 | 1410 | ||
| 1527 | return inst_base; | 1411 | return inst_base; |
| 1528 | } | 1412 | } |
| 1529 | static ARM_INST_PTR INTERPRETER_TRANSLATE(swi)(unsigned int inst, int index) | 1413 | static ARM_INST_PTR INTERPRETER_TRANSLATE(swi)(unsigned int inst, int index) { |
| 1530 | { | 1414 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(swi_inst)); |
| 1531 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swi_inst)); | 1415 | swi_inst* inst_cream = (swi_inst*)inst_base->component; |
| 1532 | swi_inst *inst_cream = (swi_inst *)inst_base->component; | ||
| 1533 | 1416 | ||
| 1534 | inst_base->cond = BITS(inst, 28, 31); | 1417 | inst_base->cond = BITS(inst, 28, 31); |
| 1535 | inst_base->idx = index; | 1418 | inst_base->idx = index; |
| 1536 | inst_base->br = TransExtData::NON_BRANCH; | 1419 | inst_base->br = TransExtData::NON_BRANCH; |
| 1537 | 1420 | ||
| 1538 | inst_cream->num = BITS(inst, 0, 23); | 1421 | inst_cream->num = BITS(inst, 0, 23); |
| 1539 | return inst_base; | 1422 | return inst_base; |
| 1540 | } | 1423 | } |
| 1541 | static ARM_INST_PTR INTERPRETER_TRANSLATE(swp)(unsigned int inst, int index) | 1424 | static ARM_INST_PTR INTERPRETER_TRANSLATE(swp)(unsigned int inst, int index) { |
| 1542 | { | 1425 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst)); |
| 1543 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst)); | 1426 | swp_inst* inst_cream = (swp_inst*)inst_base->component; |
| 1544 | swp_inst *inst_cream = (swp_inst *)inst_base->component; | ||
| 1545 | 1427 | ||
| 1546 | inst_base->cond = BITS(inst, 28, 31); | 1428 | inst_base->cond = BITS(inst, 28, 31); |
| 1547 | inst_base->idx = index; | 1429 | inst_base->idx = index; |
| 1548 | inst_base->br = TransExtData::NON_BRANCH; | 1430 | inst_base->br = TransExtData::NON_BRANCH; |
| 1549 | 1431 | ||
| 1550 | inst_cream->Rn = BITS(inst, 16, 19); | 1432 | inst_cream->Rn = BITS(inst, 16, 19); |
| 1551 | inst_cream->Rd = BITS(inst, 12, 15); | 1433 | inst_cream->Rd = BITS(inst, 12, 15); |
| 1552 | inst_cream->Rm = BITS(inst, 0, 3); | 1434 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1553 | 1435 | ||
| 1554 | return inst_base; | 1436 | return inst_base; |
| 1555 | } | 1437 | } |
| 1556 | static ARM_INST_PTR INTERPRETER_TRANSLATE(swpb)(unsigned int inst, int index){ | 1438 | static ARM_INST_PTR INTERPRETER_TRANSLATE(swpb)(unsigned int inst, int index) { |
| 1557 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst)); | 1439 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst)); |
| 1558 | swp_inst *inst_cream = (swp_inst *)inst_base->component; | 1440 | swp_inst* inst_cream = (swp_inst*)inst_base->component; |
| 1559 | 1441 | ||
| 1560 | inst_base->cond = BITS(inst, 28, 31); | 1442 | inst_base->cond = BITS(inst, 28, 31); |
| 1561 | inst_base->idx = index; | 1443 | inst_base->idx = index; |
| 1562 | inst_base->br = TransExtData::NON_BRANCH; | 1444 | inst_base->br = TransExtData::NON_BRANCH; |
| 1563 | 1445 | ||
| 1564 | inst_cream->Rn = BITS(inst, 16, 19); | 1446 | inst_cream->Rn = BITS(inst, 16, 19); |
| 1565 | inst_cream->Rd = BITS(inst, 12, 15); | 1447 | inst_cream->Rd = BITS(inst, 12, 15); |
| 1566 | inst_cream->Rm = BITS(inst, 0, 3); | 1448 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1567 | 1449 | ||
| 1568 | return inst_base; | 1450 | return inst_base; |
| 1569 | } | 1451 | } |
| 1570 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab)(unsigned int inst, int index){ | 1452 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab)(unsigned int inst, int index) { |
| 1571 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst)); | 1453 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst)); |
| 1572 | sxtab_inst *inst_cream = (sxtab_inst *)inst_base->component; | 1454 | sxtab_inst* inst_cream = (sxtab_inst*)inst_base->component; |
| 1573 | 1455 | ||
| 1574 | inst_base->cond = BITS(inst, 28, 31); | 1456 | inst_base->cond = BITS(inst, 28, 31); |
| 1575 | inst_base->idx = index; | 1457 | inst_base->idx = index; |
| 1576 | inst_base->br = TransExtData::NON_BRANCH; | 1458 | inst_base->br = TransExtData::NON_BRANCH; |
| 1577 | 1459 | ||
| 1578 | inst_cream->Rd = BITS(inst, 12, 15); | 1460 | inst_cream->Rd = BITS(inst, 12, 15); |
| 1579 | inst_cream->rotate = BITS(inst, 10, 11); | 1461 | inst_cream->rotate = BITS(inst, 10, 11); |
| 1580 | inst_cream->Rm = BITS(inst, 0, 3); | 1462 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1581 | inst_cream->Rn = BITS(inst, 16, 19); | 1463 | inst_cream->Rn = BITS(inst, 16, 19); |
| 1582 | 1464 | ||
| 1583 | return inst_base; | 1465 | return inst_base; |
| 1584 | } | 1466 | } |
| 1585 | 1467 | ||
| 1586 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab16)(unsigned int inst, int index) | 1468 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab16)(unsigned int inst, int index) { |
| 1587 | { | ||
| 1588 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst)); | 1469 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst)); |
| 1589 | sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component; | 1470 | sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component; |
| 1590 | 1471 | ||
| 1591 | inst_base->cond = BITS(inst, 28, 31); | 1472 | inst_base->cond = BITS(inst, 28, 31); |
| 1592 | inst_base->idx = index; | 1473 | inst_base->idx = index; |
| 1593 | inst_base->br = TransExtData::NON_BRANCH; | 1474 | inst_base->br = TransExtData::NON_BRANCH; |
| 1594 | 1475 | ||
| 1595 | inst_cream->Rm = BITS(inst, 0, 3); | 1476 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1596 | inst_cream->Rn = BITS(inst, 16, 19); | 1477 | inst_cream->Rn = BITS(inst, 16, 19); |
| @@ -1599,54 +1480,51 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab16)(unsigned int inst, int index) | |||
| 1599 | 1480 | ||
| 1600 | return inst_base; | 1481 | return inst_base; |
| 1601 | } | 1482 | } |
| 1602 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb16)(unsigned int inst, int index) | 1483 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb16)(unsigned int inst, int index) { |
| 1603 | { | ||
| 1604 | return INTERPRETER_TRANSLATE(sxtab16)(inst, index); | 1484 | return INTERPRETER_TRANSLATE(sxtab16)(inst, index); |
| 1605 | } | 1485 | } |
| 1606 | 1486 | ||
| 1607 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtah)(unsigned int inst, int index) { | 1487 | static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtah)(unsigned int inst, int index) { |
| 1608 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtah_inst)); | 1488 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtah_inst)); |
| 1609 | sxtah_inst *inst_cream = (sxtah_inst *)inst_base->component; | 1489 | sxtah_inst* inst_cream = (sxtah_inst*)inst_base->component; |
| 1610 | 1490 | ||
| 1611 | inst_base->cond = BITS(inst, 28, 31); | 1491 | inst_base->cond = BITS(inst, 28, 31); |
| 1612 | inst_base->idx = index; | 1492 | inst_base->idx = index; |
| 1613 | inst_base->br = TransExtData::NON_BRANCH; | 1493 | inst_base->br = TransExtData::NON_BRANCH; |
| 1614 | 1494 | ||
| 1615 | inst_cream->Rd = BITS(inst, 12, 15); | 1495 | inst_cream->Rd = BITS(inst, 12, 15); |
| 1616 | inst_cream->rotate = BITS(inst, 10, 11); | 1496 | inst_cream->rotate = BITS(inst, 10, 11); |
| 1617 | inst_cream->Rm = BITS(inst, 0, 3); | 1497 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1618 | inst_cream->Rn = BITS(inst, 16, 19); | 1498 | inst_cream->Rn = BITS(inst, 16, 19); |
| 1619 | 1499 | ||
| 1620 | return inst_base; | 1500 | return inst_base; |
| 1621 | } | 1501 | } |
| 1622 | 1502 | ||
| 1623 | static ARM_INST_PTR INTERPRETER_TRANSLATE(teq)(unsigned int inst, int index) | 1503 | static ARM_INST_PTR INTERPRETER_TRANSLATE(teq)(unsigned int inst, int index) { |
| 1624 | { | 1504 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(teq_inst)); |
| 1625 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(teq_inst)); | 1505 | teq_inst* inst_cream = (teq_inst*)inst_base->component; |
| 1626 | teq_inst *inst_cream = (teq_inst *)inst_base->component; | ||
| 1627 | 1506 | ||
| 1628 | inst_base->cond = BITS(inst, 28, 31); | 1507 | inst_base->cond = BITS(inst, 28, 31); |
| 1629 | inst_base->idx = index; | 1508 | inst_base->idx = index; |
| 1630 | inst_base->br = TransExtData::NON_BRANCH; | 1509 | inst_base->br = TransExtData::NON_BRANCH; |
| 1631 | 1510 | ||
| 1632 | inst_cream->I = BIT(inst, 25); | 1511 | inst_cream->I = BIT(inst, 25); |
| 1633 | inst_cream->Rn = BITS(inst, 16, 19); | 1512 | inst_cream->Rn = BITS(inst, 16, 19); |
| 1634 | inst_cream->shifter_operand = BITS(inst, 0, 11); | 1513 | inst_cream->shifter_operand = BITS(inst, 0, 11); |
| 1635 | inst_cream->shtop_func = GetShifterOp(inst); | 1514 | inst_cream->shtop_func = GetShifterOp(inst); |
| 1636 | 1515 | ||
| 1637 | return inst_base; | 1516 | return inst_base; |
| 1638 | } | 1517 | } |
| 1639 | static ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index) | 1518 | static ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index) { |
| 1640 | { | 1519 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(tst_inst)); |
| 1641 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(tst_inst)); | 1520 | tst_inst* inst_cream = (tst_inst*)inst_base->component; |
| 1642 | tst_inst *inst_cream = (tst_inst *)inst_base->component; | ||
| 1643 | 1521 | ||
| 1644 | inst_base->cond = BITS(inst, 28, 31); | 1522 | inst_base->cond = BITS(inst, 28, 31); |
| 1645 | inst_base->idx = index; | 1523 | inst_base->idx = index; |
| 1646 | inst_base->br = TransExtData::NON_BRANCH; | 1524 | inst_base->br = TransExtData::NON_BRANCH; |
| 1647 | 1525 | ||
| 1648 | inst_cream->I = BIT(inst, 25); | 1526 | inst_cream->I = BIT(inst, 25); |
| 1649 | inst_cream->S = BIT(inst, 20); | 1527 | inst_cream->S = BIT(inst, 20); |
| 1650 | inst_cream->Rn = BITS(inst, 16, 19); | 1528 | inst_cream->Rn = BITS(inst, 16, 19); |
| 1651 | inst_cream->Rd = BITS(inst, 12, 15); | 1529 | inst_cream->Rd = BITS(inst, 12, 15); |
| 1652 | inst_cream->shifter_operand = BITS(inst, 0, 11); | 1530 | inst_cream->shifter_operand = BITS(inst, 0, 11); |
| @@ -1655,309 +1533,274 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index) | |||
| 1655 | return inst_base; | 1533 | return inst_base; |
| 1656 | } | 1534 | } |
| 1657 | 1535 | ||
| 1658 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd8)(unsigned int inst, int index) | 1536 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd8)(unsigned int inst, int index) { |
| 1659 | { | ||
| 1660 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); | 1537 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); |
| 1661 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | 1538 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; |
| 1662 | 1539 | ||
| 1663 | inst_base->cond = BITS(inst, 28, 31); | 1540 | inst_base->cond = BITS(inst, 28, 31); |
| 1664 | inst_base->idx = index; | 1541 | inst_base->idx = index; |
| 1665 | inst_base->br = TransExtData::NON_BRANCH; | 1542 | inst_base->br = TransExtData::NON_BRANCH; |
| 1666 | 1543 | ||
| 1667 | inst_cream->op1 = BITS(inst, 20, 21); | 1544 | inst_cream->op1 = BITS(inst, 20, 21); |
| 1668 | inst_cream->op2 = BITS(inst, 5, 7); | 1545 | inst_cream->op2 = BITS(inst, 5, 7); |
| 1669 | inst_cream->Rm = BITS(inst, 0, 3); | 1546 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1670 | inst_cream->Rn = BITS(inst, 16, 19); | 1547 | inst_cream->Rn = BITS(inst, 16, 19); |
| 1671 | inst_cream->Rd = BITS(inst, 12, 15); | 1548 | inst_cream->Rd = BITS(inst, 12, 15); |
| 1672 | 1549 | ||
| 1673 | return inst_base; | 1550 | return inst_base; |
| 1674 | } | 1551 | } |
| 1675 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index) | 1552 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index) { |
| 1676 | { | ||
| 1677 | return INTERPRETER_TRANSLATE(uadd8)(inst, index); | 1553 | return INTERPRETER_TRANSLATE(uadd8)(inst, index); |
| 1678 | } | 1554 | } |
| 1679 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uaddsubx)(unsigned int inst, int index) | 1555 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uaddsubx)(unsigned int inst, int index) { |
| 1680 | { | ||
| 1681 | return INTERPRETER_TRANSLATE(uadd8)(inst, index); | 1556 | return INTERPRETER_TRANSLATE(uadd8)(inst, index); |
| 1682 | } | 1557 | } |
| 1683 | static ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index) | 1558 | static ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index) { |
| 1684 | { | ||
| 1685 | return INTERPRETER_TRANSLATE(uadd8)(inst, index); | 1559 | return INTERPRETER_TRANSLATE(uadd8)(inst, index); |
| 1686 | } | 1560 | } |
| 1687 | static ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index) | 1561 | static ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index) { |
| 1688 | { | ||
| 1689 | return INTERPRETER_TRANSLATE(uadd8)(inst, index); | 1562 | return INTERPRETER_TRANSLATE(uadd8)(inst, index); |
| 1690 | } | 1563 | } |
| 1691 | static ARM_INST_PTR INTERPRETER_TRANSLATE(usubaddx)(unsigned int inst, int index) | 1564 | static ARM_INST_PTR INTERPRETER_TRANSLATE(usubaddx)(unsigned int inst, int index) { |
| 1692 | { | ||
| 1693 | return INTERPRETER_TRANSLATE(uadd8)(inst, index); | 1565 | return INTERPRETER_TRANSLATE(uadd8)(inst, index); |
| 1694 | } | 1566 | } |
| 1695 | 1567 | ||
| 1696 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd8)(unsigned int inst, int index) | 1568 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd8)(unsigned int inst, int index) { |
| 1697 | { | ||
| 1698 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); | 1569 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); |
| 1699 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | 1570 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; |
| 1700 | 1571 | ||
| 1701 | inst_base->cond = BITS(inst, 28, 31); | 1572 | inst_base->cond = BITS(inst, 28, 31); |
| 1702 | inst_base->idx = index; | 1573 | inst_base->idx = index; |
| 1703 | inst_base->br = TransExtData::NON_BRANCH; | 1574 | inst_base->br = TransExtData::NON_BRANCH; |
| 1704 | 1575 | ||
| 1705 | inst_cream->op1 = BITS(inst, 20, 21); | 1576 | inst_cream->op1 = BITS(inst, 20, 21); |
| 1706 | inst_cream->op2 = BITS(inst, 5, 7); | 1577 | inst_cream->op2 = BITS(inst, 5, 7); |
| 1707 | inst_cream->Rm = BITS(inst, 0, 3); | 1578 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1708 | inst_cream->Rn = BITS(inst, 16, 19); | 1579 | inst_cream->Rn = BITS(inst, 16, 19); |
| 1709 | inst_cream->Rd = BITS(inst, 12, 15); | 1580 | inst_cream->Rd = BITS(inst, 12, 15); |
| 1710 | 1581 | ||
| 1711 | return inst_base; | 1582 | return inst_base; |
| 1712 | } | 1583 | } |
| 1713 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index) | 1584 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index) { |
| 1714 | { | ||
| 1715 | return INTERPRETER_TRANSLATE(uhadd8)(inst, index); | 1585 | return INTERPRETER_TRANSLATE(uhadd8)(inst, index); |
| 1716 | } | 1586 | } |
| 1717 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index) | 1587 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index) { |
| 1718 | { | ||
| 1719 | return INTERPRETER_TRANSLATE(uhadd8)(inst, index); | 1588 | return INTERPRETER_TRANSLATE(uhadd8)(inst, index); |
| 1720 | } | 1589 | } |
| 1721 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index) | 1590 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index) { |
| 1722 | { | ||
| 1723 | return INTERPRETER_TRANSLATE(uhadd8)(inst, index); | 1591 | return INTERPRETER_TRANSLATE(uhadd8)(inst, index); |
| 1724 | } | 1592 | } |
| 1725 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index) | 1593 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index) { |
| 1726 | { | ||
| 1727 | return INTERPRETER_TRANSLATE(uhadd8)(inst, index); | 1594 | return INTERPRETER_TRANSLATE(uhadd8)(inst, index); |
| 1728 | } | 1595 | } |
| 1729 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index) | 1596 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index) { |
| 1730 | { | ||
| 1731 | return INTERPRETER_TRANSLATE(uhadd8)(inst, index); | 1597 | return INTERPRETER_TRANSLATE(uhadd8)(inst, index); |
| 1732 | } | 1598 | } |
| 1733 | static ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index) | 1599 | static ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index) { |
| 1734 | { | ||
| 1735 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umaal_inst)); | 1600 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umaal_inst)); |
| 1736 | umaal_inst* const inst_cream = (umaal_inst*)inst_base->component; | 1601 | umaal_inst* const inst_cream = (umaal_inst*)inst_base->component; |
| 1737 | 1602 | ||
| 1738 | inst_base->cond = BITS(inst, 28, 31); | 1603 | inst_base->cond = BITS(inst, 28, 31); |
| 1739 | inst_base->idx = index; | 1604 | inst_base->idx = index; |
| 1740 | inst_base->br = TransExtData::NON_BRANCH; | 1605 | inst_base->br = TransExtData::NON_BRANCH; |
| 1741 | 1606 | ||
| 1742 | inst_cream->Rm = BITS(inst, 8, 11); | 1607 | inst_cream->Rm = BITS(inst, 8, 11); |
| 1743 | inst_cream->Rn = BITS(inst, 0, 3); | 1608 | inst_cream->Rn = BITS(inst, 0, 3); |
| 1744 | inst_cream->RdLo = BITS(inst, 12, 15); | 1609 | inst_cream->RdLo = BITS(inst, 12, 15); |
| 1745 | inst_cream->RdHi = BITS(inst, 16, 19); | 1610 | inst_cream->RdHi = BITS(inst, 16, 19); |
| 1746 | 1611 | ||
| 1747 | return inst_base; | 1612 | return inst_base; |
| 1748 | } | 1613 | } |
| 1749 | static ARM_INST_PTR INTERPRETER_TRANSLATE(umlal)(unsigned int inst, int index) | 1614 | static ARM_INST_PTR INTERPRETER_TRANSLATE(umlal)(unsigned int inst, int index) { |
| 1750 | { | 1615 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst)); |
| 1751 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst)); | 1616 | umlal_inst* inst_cream = (umlal_inst*)inst_base->component; |
| 1752 | umlal_inst *inst_cream = (umlal_inst *)inst_base->component; | ||
| 1753 | 1617 | ||
| 1754 | inst_base->cond = BITS(inst, 28, 31); | 1618 | inst_base->cond = BITS(inst, 28, 31); |
| 1755 | inst_base->idx = index; | 1619 | inst_base->idx = index; |
| 1756 | inst_base->br = TransExtData::NON_BRANCH; | 1620 | inst_base->br = TransExtData::NON_BRANCH; |
| 1757 | 1621 | ||
| 1758 | inst_cream->S = BIT(inst, 20); | 1622 | inst_cream->S = BIT(inst, 20); |
| 1759 | inst_cream->Rm = BITS(inst, 0, 3); | 1623 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1760 | inst_cream->Rs = BITS(inst, 8, 11); | 1624 | inst_cream->Rs = BITS(inst, 8, 11); |
| 1761 | inst_cream->RdHi = BITS(inst, 16, 19); | 1625 | inst_cream->RdHi = BITS(inst, 16, 19); |
| 1762 | inst_cream->RdLo = BITS(inst, 12, 15); | 1626 | inst_cream->RdLo = BITS(inst, 12, 15); |
| 1763 | 1627 | ||
| 1764 | return inst_base; | 1628 | return inst_base; |
| 1765 | } | 1629 | } |
| 1766 | static ARM_INST_PTR INTERPRETER_TRANSLATE(umull)(unsigned int inst, int index) | 1630 | static ARM_INST_PTR INTERPRETER_TRANSLATE(umull)(unsigned int inst, int index) { |
| 1767 | { | 1631 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst)); |
| 1768 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst)); | 1632 | umull_inst* inst_cream = (umull_inst*)inst_base->component; |
| 1769 | umull_inst *inst_cream = (umull_inst *)inst_base->component; | ||
| 1770 | 1633 | ||
| 1771 | inst_base->cond = BITS(inst, 28, 31); | 1634 | inst_base->cond = BITS(inst, 28, 31); |
| 1772 | inst_base->idx = index; | 1635 | inst_base->idx = index; |
| 1773 | inst_base->br = TransExtData::NON_BRANCH; | 1636 | inst_base->br = TransExtData::NON_BRANCH; |
| 1774 | 1637 | ||
| 1775 | inst_cream->S = BIT(inst, 20); | 1638 | inst_cream->S = BIT(inst, 20); |
| 1776 | inst_cream->Rm = BITS(inst, 0, 3); | 1639 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1777 | inst_cream->Rs = BITS(inst, 8, 11); | 1640 | inst_cream->Rs = BITS(inst, 8, 11); |
| 1778 | inst_cream->RdHi = BITS(inst, 16, 19); | 1641 | inst_cream->RdHi = BITS(inst, 16, 19); |
| 1779 | inst_cream->RdLo = BITS(inst, 12, 15); | 1642 | inst_cream->RdLo = BITS(inst, 12, 15); |
| 1780 | 1643 | ||
| 1781 | return inst_base; | 1644 | return inst_base; |
| 1782 | } | 1645 | } |
| 1783 | 1646 | ||
| 1784 | static ARM_INST_PTR INTERPRETER_TRANSLATE(b_2_thumb)(unsigned int tinst, int index) | 1647 | static ARM_INST_PTR INTERPRETER_TRANSLATE(b_2_thumb)(unsigned int tinst, int index) { |
| 1785 | { | 1648 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(b_2_thumb)); |
| 1786 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_2_thumb)); | 1649 | b_2_thumb* inst_cream = (b_2_thumb*)inst_base->component; |
| 1787 | b_2_thumb *inst_cream = (b_2_thumb *)inst_base->component; | ||
| 1788 | 1650 | ||
| 1789 | inst_cream->imm = ((tinst & 0x3FF) << 1) | ((tinst & (1 << 10)) ? 0xFFFFF800 : 0); | 1651 | inst_cream->imm = ((tinst & 0x3FF) << 1) | ((tinst & (1 << 10)) ? 0xFFFFF800 : 0); |
| 1790 | 1652 | ||
| 1791 | inst_base->idx = index; | 1653 | inst_base->idx = index; |
| 1792 | inst_base->br = TransExtData::DIRECT_BRANCH; | 1654 | inst_base->br = TransExtData::DIRECT_BRANCH; |
| 1793 | 1655 | ||
| 1794 | return inst_base; | 1656 | return inst_base; |
| 1795 | } | 1657 | } |
| 1796 | 1658 | ||
| 1797 | static ARM_INST_PTR INTERPRETER_TRANSLATE(b_cond_thumb)(unsigned int tinst, int index) | 1659 | static ARM_INST_PTR INTERPRETER_TRANSLATE(b_cond_thumb)(unsigned int tinst, int index) { |
| 1798 | { | 1660 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(b_cond_thumb)); |
| 1799 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_cond_thumb)); | 1661 | b_cond_thumb* inst_cream = (b_cond_thumb*)inst_base->component; |
| 1800 | b_cond_thumb *inst_cream = (b_cond_thumb *)inst_base->component; | ||
| 1801 | 1662 | ||
| 1802 | inst_cream->imm = (((tinst & 0x7F) << 1) | ((tinst & (1 << 7)) ? 0xFFFFFF00 : 0)); | 1663 | inst_cream->imm = (((tinst & 0x7F) << 1) | ((tinst & (1 << 7)) ? 0xFFFFFF00 : 0)); |
| 1803 | inst_cream->cond = ((tinst >> 8) & 0xf); | 1664 | inst_cream->cond = ((tinst >> 8) & 0xf); |
| 1804 | inst_base->idx = index; | 1665 | inst_base->idx = index; |
| 1805 | inst_base->br = TransExtData::DIRECT_BRANCH; | 1666 | inst_base->br = TransExtData::DIRECT_BRANCH; |
| 1806 | 1667 | ||
| 1807 | return inst_base; | 1668 | return inst_base; |
| 1808 | } | 1669 | } |
| 1809 | 1670 | ||
| 1810 | static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_1_thumb)(unsigned int tinst, int index) | 1671 | static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_1_thumb)(unsigned int tinst, int index) { |
| 1811 | { | 1672 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bl_1_thumb)); |
| 1812 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_1_thumb)); | 1673 | bl_1_thumb* inst_cream = (bl_1_thumb*)inst_base->component; |
| 1813 | bl_1_thumb *inst_cream = (bl_1_thumb *)inst_base->component; | ||
| 1814 | 1674 | ||
| 1815 | inst_cream->imm = (((tinst & 0x07FF) << 12) | ((tinst & (1 << 10)) ? 0xFF800000 : 0)); | 1675 | inst_cream->imm = (((tinst & 0x07FF) << 12) | ((tinst & (1 << 10)) ? 0xFF800000 : 0)); |
| 1816 | 1676 | ||
| 1817 | inst_base->idx = index; | 1677 | inst_base->idx = index; |
| 1818 | inst_base->br = TransExtData::NON_BRANCH; | 1678 | inst_base->br = TransExtData::NON_BRANCH; |
| 1819 | return inst_base; | 1679 | return inst_base; |
| 1820 | } | 1680 | } |
| 1821 | static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_2_thumb)(unsigned int tinst, int index) | 1681 | static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_2_thumb)(unsigned int tinst, int index) { |
| 1822 | { | 1682 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bl_2_thumb)); |
| 1823 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_2_thumb)); | 1683 | bl_2_thumb* inst_cream = (bl_2_thumb*)inst_base->component; |
| 1824 | bl_2_thumb *inst_cream = (bl_2_thumb *)inst_base->component; | ||
| 1825 | 1684 | ||
| 1826 | inst_cream->imm = (tinst & 0x07FF) << 1; | 1685 | inst_cream->imm = (tinst & 0x07FF) << 1; |
| 1827 | 1686 | ||
| 1828 | inst_base->idx = index; | 1687 | inst_base->idx = index; |
| 1829 | inst_base->br = TransExtData::DIRECT_BRANCH; | 1688 | inst_base->br = TransExtData::DIRECT_BRANCH; |
| 1830 | return inst_base; | 1689 | return inst_base; |
| 1831 | } | 1690 | } |
| 1832 | static ARM_INST_PTR INTERPRETER_TRANSLATE(blx_1_thumb)(unsigned int tinst, int index) | 1691 | static ARM_INST_PTR INTERPRETER_TRANSLATE(blx_1_thumb)(unsigned int tinst, int index) { |
| 1833 | { | 1692 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(blx_1_thumb)); |
| 1834 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_1_thumb)); | 1693 | blx_1_thumb* inst_cream = (blx_1_thumb*)inst_base->component; |
| 1835 | blx_1_thumb *inst_cream = (blx_1_thumb *)inst_base->component; | ||
| 1836 | 1694 | ||
| 1837 | inst_cream->imm = (tinst & 0x07FF) << 1; | 1695 | inst_cream->imm = (tinst & 0x07FF) << 1; |
| 1838 | inst_cream->instr = tinst; | 1696 | inst_cream->instr = tinst; |
| 1839 | 1697 | ||
| 1840 | inst_base->idx = index; | 1698 | inst_base->idx = index; |
| 1841 | inst_base->br = TransExtData::DIRECT_BRANCH; | 1699 | inst_base->br = TransExtData::DIRECT_BRANCH; |
| 1842 | return inst_base; | 1700 | return inst_base; |
| 1843 | } | 1701 | } |
| 1844 | 1702 | ||
| 1845 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index) | 1703 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index) { |
| 1846 | { | ||
| 1847 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); | 1704 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); |
| 1848 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | 1705 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; |
| 1849 | 1706 | ||
| 1850 | inst_base->cond = BITS(inst, 28, 31); | 1707 | inst_base->cond = BITS(inst, 28, 31); |
| 1851 | inst_base->idx = index; | 1708 | inst_base->idx = index; |
| 1852 | inst_base->br = TransExtData::NON_BRANCH; | 1709 | inst_base->br = TransExtData::NON_BRANCH; |
| 1853 | 1710 | ||
| 1854 | inst_cream->Rm = BITS(inst, 0, 3); | 1711 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1855 | inst_cream->Rn = BITS(inst, 16, 19); | 1712 | inst_cream->Rn = BITS(inst, 16, 19); |
| 1856 | inst_cream->Rd = BITS(inst, 12, 15); | 1713 | inst_cream->Rd = BITS(inst, 12, 15); |
| 1857 | inst_cream->op1 = BITS(inst, 20, 21); | 1714 | inst_cream->op1 = BITS(inst, 20, 21); |
| 1858 | inst_cream->op2 = BITS(inst, 5, 7); | 1715 | inst_cream->op2 = BITS(inst, 5, 7); |
| 1859 | 1716 | ||
| 1860 | return inst_base; | 1717 | return inst_base; |
| 1861 | } | 1718 | } |
| 1862 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index) | 1719 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index) { |
| 1863 | { | ||
| 1864 | return INTERPRETER_TRANSLATE(uqadd8)(inst, index); | 1720 | return INTERPRETER_TRANSLATE(uqadd8)(inst, index); |
| 1865 | } | 1721 | } |
| 1866 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index) | 1722 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index) { |
| 1867 | { | ||
| 1868 | return INTERPRETER_TRANSLATE(uqadd8)(inst, index); | 1723 | return INTERPRETER_TRANSLATE(uqadd8)(inst, index); |
| 1869 | } | 1724 | } |
| 1870 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index) | 1725 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index) { |
| 1871 | { | ||
| 1872 | return INTERPRETER_TRANSLATE(uqadd8)(inst, index); | 1726 | return INTERPRETER_TRANSLATE(uqadd8)(inst, index); |
| 1873 | } | 1727 | } |
| 1874 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index) | 1728 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index) { |
| 1875 | { | ||
| 1876 | return INTERPRETER_TRANSLATE(uqadd8)(inst, index); | 1729 | return INTERPRETER_TRANSLATE(uqadd8)(inst, index); |
| 1877 | } | 1730 | } |
| 1878 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index) | 1731 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index) { |
| 1879 | { | ||
| 1880 | return INTERPRETER_TRANSLATE(uqadd8)(inst, index); | 1732 | return INTERPRETER_TRANSLATE(uqadd8)(inst, index); |
| 1881 | } | 1733 | } |
| 1882 | static ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index) | 1734 | static ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index) { |
| 1883 | { | ||
| 1884 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); | 1735 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); |
| 1885 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | 1736 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; |
| 1886 | 1737 | ||
| 1887 | inst_base->cond = BITS(inst, 28, 31); | 1738 | inst_base->cond = BITS(inst, 28, 31); |
| 1888 | inst_base->idx = index; | 1739 | inst_base->idx = index; |
| 1889 | inst_base->br = TransExtData::NON_BRANCH; | 1740 | inst_base->br = TransExtData::NON_BRANCH; |
| 1890 | 1741 | ||
| 1891 | inst_cream->op1 = BITS(inst, 20, 24); | 1742 | inst_cream->op1 = BITS(inst, 20, 24); |
| 1892 | inst_cream->op2 = BITS(inst, 5, 7); | 1743 | inst_cream->op2 = BITS(inst, 5, 7); |
| 1893 | inst_cream->Rd = BITS(inst, 16, 19); | 1744 | inst_cream->Rd = BITS(inst, 16, 19); |
| 1894 | inst_cream->Rm = BITS(inst, 8, 11); | 1745 | inst_cream->Rm = BITS(inst, 8, 11); |
| 1895 | inst_cream->Rn = BITS(inst, 0, 3); | 1746 | inst_cream->Rn = BITS(inst, 0, 3); |
| 1896 | inst_cream->Ra = BITS(inst, 12, 15); | 1747 | inst_cream->Ra = BITS(inst, 12, 15); |
| 1897 | 1748 | ||
| 1898 | return inst_base; | 1749 | return inst_base; |
| 1899 | } | 1750 | } |
| 1900 | static ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index) | 1751 | static ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index) { |
| 1901 | { | ||
| 1902 | return INTERPRETER_TRANSLATE(usada8)(inst, index); | 1752 | return INTERPRETER_TRANSLATE(usada8)(inst, index); |
| 1903 | } | 1753 | } |
| 1904 | static ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index) | 1754 | static ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index) { |
| 1905 | { | ||
| 1906 | return INTERPRETER_TRANSLATE(ssat)(inst, index); | 1755 | return INTERPRETER_TRANSLATE(ssat)(inst, index); |
| 1907 | } | 1756 | } |
| 1908 | static ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index) | 1757 | static ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index) { |
| 1909 | { | ||
| 1910 | return INTERPRETER_TRANSLATE(ssat16)(inst, index); | 1758 | return INTERPRETER_TRANSLATE(ssat16)(inst, index); |
| 1911 | } | 1759 | } |
| 1912 | 1760 | ||
| 1913 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab16)(unsigned int inst, int index) | 1761 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab16)(unsigned int inst, int index) { |
| 1914 | { | ||
| 1915 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst)); | 1762 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst)); |
| 1916 | uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component; | 1763 | uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component; |
| 1917 | 1764 | ||
| 1918 | inst_base->cond = BITS(inst, 28, 31); | 1765 | inst_base->cond = BITS(inst, 28, 31); |
| 1919 | inst_base->idx = index; | 1766 | inst_base->idx = index; |
| 1920 | inst_base->br = TransExtData::NON_BRANCH; | 1767 | inst_base->br = TransExtData::NON_BRANCH; |
| 1921 | 1768 | ||
| 1922 | inst_cream->Rm = BITS(inst, 0, 3); | 1769 | inst_cream->Rm = BITS(inst, 0, 3); |
| 1923 | inst_cream->Rn = BITS(inst, 16, 19); | 1770 | inst_cream->Rn = BITS(inst, 16, 19); |
| 1924 | inst_cream->Rd = BITS(inst, 12, 15); | 1771 | inst_cream->Rd = BITS(inst, 12, 15); |
| 1925 | inst_cream->rotate = BITS(inst, 10, 11); | 1772 | inst_cream->rotate = BITS(inst, 10, 11); |
| 1926 | 1773 | ||
| 1927 | return inst_base; | 1774 | return inst_base; |
| 1928 | } | 1775 | } |
| 1929 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index) | 1776 | static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index) { |
| 1930 | { | ||
| 1931 | return INTERPRETER_TRANSLATE(uxtab16)(inst, index); | 1777 | return INTERPRETER_TRANSLATE(uxtab16)(inst, index); |
| 1932 | } | 1778 | } |
| 1933 | 1779 | ||
| 1934 | static ARM_INST_PTR INTERPRETER_TRANSLATE(wfe)(unsigned int inst, int index) | 1780 | static ARM_INST_PTR INTERPRETER_TRANSLATE(wfe)(unsigned int inst, int index) { |
| 1935 | { | ||
| 1936 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); | 1781 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); |
| 1937 | 1782 | ||
| 1938 | inst_base->cond = BITS(inst, 28, 31); | 1783 | inst_base->cond = BITS(inst, 28, 31); |
| 1939 | inst_base->idx = index; | 1784 | inst_base->idx = index; |
| 1940 | inst_base->br = TransExtData::NON_BRANCH; | 1785 | inst_base->br = TransExtData::NON_BRANCH; |
| 1941 | 1786 | ||
| 1942 | return inst_base; | 1787 | return inst_base; |
| 1943 | } | 1788 | } |
| 1944 | static ARM_INST_PTR INTERPRETER_TRANSLATE(wfi)(unsigned int inst, int index) | 1789 | static ARM_INST_PTR INTERPRETER_TRANSLATE(wfi)(unsigned int inst, int index) { |
| 1945 | { | ||
| 1946 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); | 1790 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); |
| 1947 | 1791 | ||
| 1948 | inst_base->cond = BITS(inst, 28, 31); | 1792 | inst_base->cond = BITS(inst, 28, 31); |
| 1949 | inst_base->idx = index; | 1793 | inst_base->idx = index; |
| 1950 | inst_base->br = TransExtData::NON_BRANCH; | 1794 | inst_base->br = TransExtData::NON_BRANCH; |
| 1951 | 1795 | ||
| 1952 | return inst_base; | 1796 | return inst_base; |
| 1953 | } | 1797 | } |
| 1954 | static ARM_INST_PTR INTERPRETER_TRANSLATE(yield)(unsigned int inst, int index) | 1798 | static ARM_INST_PTR INTERPRETER_TRANSLATE(yield)(unsigned int inst, int index) { |
| 1955 | { | ||
| 1956 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); | 1799 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); |
| 1957 | 1800 | ||
| 1958 | inst_base->cond = BITS(inst, 28, 31); | 1801 | inst_base->cond = BITS(inst, 28, 31); |
| 1959 | inst_base->idx = index; | 1802 | inst_base->idx = index; |
| 1960 | inst_base->br = TransExtData::NON_BRANCH; | 1803 | inst_base->br = TransExtData::NON_BRANCH; |
| 1961 | 1804 | ||
| 1962 | return inst_base; | 1805 | return inst_base; |
| 1963 | } | 1806 | } |
| @@ -1968,211 +1811,78 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(yield)(unsigned int inst, int index) | |||
| 1968 | #undef VFP_INTERPRETER_TRANS | 1811 | #undef VFP_INTERPRETER_TRANS |
| 1969 | 1812 | ||
| 1970 | const transop_fp_t arm_instruction_trans[] = { | 1813 | const transop_fp_t arm_instruction_trans[] = { |
| 1971 | INTERPRETER_TRANSLATE(vmla), | 1814 | INTERPRETER_TRANSLATE(vmla), INTERPRETER_TRANSLATE(vmls), INTERPRETER_TRANSLATE(vnmla), |
| 1972 | INTERPRETER_TRANSLATE(vmls), | 1815 | INTERPRETER_TRANSLATE(vnmls), INTERPRETER_TRANSLATE(vnmul), INTERPRETER_TRANSLATE(vmul), |
| 1973 | INTERPRETER_TRANSLATE(vnmla), | 1816 | INTERPRETER_TRANSLATE(vadd), INTERPRETER_TRANSLATE(vsub), INTERPRETER_TRANSLATE(vdiv), |
| 1974 | INTERPRETER_TRANSLATE(vnmls), | 1817 | INTERPRETER_TRANSLATE(vmovi), INTERPRETER_TRANSLATE(vmovr), INTERPRETER_TRANSLATE(vabs), |
| 1975 | INTERPRETER_TRANSLATE(vnmul), | 1818 | INTERPRETER_TRANSLATE(vneg), INTERPRETER_TRANSLATE(vsqrt), INTERPRETER_TRANSLATE(vcmp), |
| 1976 | INTERPRETER_TRANSLATE(vmul), | 1819 | INTERPRETER_TRANSLATE(vcmp2), INTERPRETER_TRANSLATE(vcvtbds), INTERPRETER_TRANSLATE(vcvtbff), |
| 1977 | INTERPRETER_TRANSLATE(vadd), | 1820 | INTERPRETER_TRANSLATE(vcvtbfi), INTERPRETER_TRANSLATE(vmovbrs), INTERPRETER_TRANSLATE(vmsr), |
| 1978 | INTERPRETER_TRANSLATE(vsub), | 1821 | INTERPRETER_TRANSLATE(vmovbrc), INTERPRETER_TRANSLATE(vmrs), INTERPRETER_TRANSLATE(vmovbcr), |
| 1979 | INTERPRETER_TRANSLATE(vdiv), | 1822 | INTERPRETER_TRANSLATE(vmovbrrss), INTERPRETER_TRANSLATE(vmovbrrd), INTERPRETER_TRANSLATE(vstr), |
| 1980 | INTERPRETER_TRANSLATE(vmovi), | 1823 | INTERPRETER_TRANSLATE(vpush), INTERPRETER_TRANSLATE(vstm), INTERPRETER_TRANSLATE(vpop), |
| 1981 | INTERPRETER_TRANSLATE(vmovr), | 1824 | INTERPRETER_TRANSLATE(vldr), INTERPRETER_TRANSLATE(vldm), |
| 1982 | INTERPRETER_TRANSLATE(vabs), | 1825 | |
| 1983 | INTERPRETER_TRANSLATE(vneg), | 1826 | INTERPRETER_TRANSLATE(srs), INTERPRETER_TRANSLATE(rfe), INTERPRETER_TRANSLATE(bkpt), |
| 1984 | INTERPRETER_TRANSLATE(vsqrt), | 1827 | INTERPRETER_TRANSLATE(blx), INTERPRETER_TRANSLATE(cps), INTERPRETER_TRANSLATE(pld), |
| 1985 | INTERPRETER_TRANSLATE(vcmp), | 1828 | INTERPRETER_TRANSLATE(setend), INTERPRETER_TRANSLATE(clrex), INTERPRETER_TRANSLATE(rev16), |
| 1986 | INTERPRETER_TRANSLATE(vcmp2), | 1829 | INTERPRETER_TRANSLATE(usad8), INTERPRETER_TRANSLATE(sxtb), INTERPRETER_TRANSLATE(uxtb), |
| 1987 | INTERPRETER_TRANSLATE(vcvtbds), | 1830 | INTERPRETER_TRANSLATE(sxth), INTERPRETER_TRANSLATE(sxtb16), INTERPRETER_TRANSLATE(uxth), |
| 1988 | INTERPRETER_TRANSLATE(vcvtbff), | 1831 | INTERPRETER_TRANSLATE(uxtb16), INTERPRETER_TRANSLATE(cpy), INTERPRETER_TRANSLATE(uxtab), |
| 1989 | INTERPRETER_TRANSLATE(vcvtbfi), | 1832 | INTERPRETER_TRANSLATE(ssub8), INTERPRETER_TRANSLATE(shsub8), INTERPRETER_TRANSLATE(ssubaddx), |
| 1990 | INTERPRETER_TRANSLATE(vmovbrs), | 1833 | INTERPRETER_TRANSLATE(strex), INTERPRETER_TRANSLATE(strexb), INTERPRETER_TRANSLATE(swp), |
| 1991 | INTERPRETER_TRANSLATE(vmsr), | 1834 | INTERPRETER_TRANSLATE(swpb), INTERPRETER_TRANSLATE(ssub16), INTERPRETER_TRANSLATE(ssat16), |
| 1992 | INTERPRETER_TRANSLATE(vmovbrc), | 1835 | INTERPRETER_TRANSLATE(shsubaddx), INTERPRETER_TRANSLATE(qsubaddx), |
| 1993 | INTERPRETER_TRANSLATE(vmrs), | 1836 | INTERPRETER_TRANSLATE(shaddsubx), INTERPRETER_TRANSLATE(shadd8), INTERPRETER_TRANSLATE(shadd16), |
| 1994 | INTERPRETER_TRANSLATE(vmovbcr), | 1837 | INTERPRETER_TRANSLATE(sel), INTERPRETER_TRANSLATE(saddsubx), INTERPRETER_TRANSLATE(sadd8), |
| 1995 | INTERPRETER_TRANSLATE(vmovbrrss), | 1838 | INTERPRETER_TRANSLATE(sadd16), INTERPRETER_TRANSLATE(shsub16), INTERPRETER_TRANSLATE(umaal), |
| 1996 | INTERPRETER_TRANSLATE(vmovbrrd), | 1839 | INTERPRETER_TRANSLATE(uxtab16), INTERPRETER_TRANSLATE(usubaddx), INTERPRETER_TRANSLATE(usub8), |
| 1997 | INTERPRETER_TRANSLATE(vstr), | 1840 | INTERPRETER_TRANSLATE(usub16), INTERPRETER_TRANSLATE(usat16), INTERPRETER_TRANSLATE(usada8), |
| 1998 | INTERPRETER_TRANSLATE(vpush), | 1841 | INTERPRETER_TRANSLATE(uqsubaddx), INTERPRETER_TRANSLATE(uqsub8), INTERPRETER_TRANSLATE(uqsub16), |
| 1999 | INTERPRETER_TRANSLATE(vstm), | 1842 | INTERPRETER_TRANSLATE(uqaddsubx), INTERPRETER_TRANSLATE(uqadd8), INTERPRETER_TRANSLATE(uqadd16), |
| 2000 | INTERPRETER_TRANSLATE(vpop), | 1843 | INTERPRETER_TRANSLATE(sxtab), INTERPRETER_TRANSLATE(uhsubaddx), INTERPRETER_TRANSLATE(uhsub8), |
| 2001 | INTERPRETER_TRANSLATE(vldr), | 1844 | INTERPRETER_TRANSLATE(uhsub16), INTERPRETER_TRANSLATE(uhaddsubx), INTERPRETER_TRANSLATE(uhadd8), |
| 2002 | INTERPRETER_TRANSLATE(vldm), | 1845 | INTERPRETER_TRANSLATE(uhadd16), INTERPRETER_TRANSLATE(uaddsubx), INTERPRETER_TRANSLATE(uadd8), |
| 2003 | 1846 | INTERPRETER_TRANSLATE(uadd16), INTERPRETER_TRANSLATE(sxtah), INTERPRETER_TRANSLATE(sxtab16), | |
| 2004 | INTERPRETER_TRANSLATE(srs), | 1847 | INTERPRETER_TRANSLATE(qadd8), INTERPRETER_TRANSLATE(bxj), INTERPRETER_TRANSLATE(clz), |
| 2005 | INTERPRETER_TRANSLATE(rfe), | 1848 | INTERPRETER_TRANSLATE(uxtah), INTERPRETER_TRANSLATE(bx), INTERPRETER_TRANSLATE(rev), |
| 2006 | INTERPRETER_TRANSLATE(bkpt), | 1849 | INTERPRETER_TRANSLATE(blx), INTERPRETER_TRANSLATE(revsh), INTERPRETER_TRANSLATE(qadd), |
| 2007 | INTERPRETER_TRANSLATE(blx), | 1850 | INTERPRETER_TRANSLATE(qadd16), INTERPRETER_TRANSLATE(qaddsubx), INTERPRETER_TRANSLATE(ldrex), |
| 2008 | INTERPRETER_TRANSLATE(cps), | 1851 | INTERPRETER_TRANSLATE(qdadd), INTERPRETER_TRANSLATE(qdsub), INTERPRETER_TRANSLATE(qsub), |
| 2009 | INTERPRETER_TRANSLATE(pld), | 1852 | INTERPRETER_TRANSLATE(ldrexb), INTERPRETER_TRANSLATE(qsub8), INTERPRETER_TRANSLATE(qsub16), |
| 2010 | INTERPRETER_TRANSLATE(setend), | 1853 | INTERPRETER_TRANSLATE(smuad), INTERPRETER_TRANSLATE(smmul), INTERPRETER_TRANSLATE(smusd), |
| 2011 | INTERPRETER_TRANSLATE(clrex), | 1854 | INTERPRETER_TRANSLATE(smlsd), INTERPRETER_TRANSLATE(smlsld), INTERPRETER_TRANSLATE(smmla), |
| 2012 | INTERPRETER_TRANSLATE(rev16), | 1855 | INTERPRETER_TRANSLATE(smmls), INTERPRETER_TRANSLATE(smlald), INTERPRETER_TRANSLATE(smlad), |
| 2013 | INTERPRETER_TRANSLATE(usad8), | 1856 | INTERPRETER_TRANSLATE(smlaw), INTERPRETER_TRANSLATE(smulw), INTERPRETER_TRANSLATE(pkhtb), |
| 2014 | INTERPRETER_TRANSLATE(sxtb), | 1857 | INTERPRETER_TRANSLATE(pkhbt), INTERPRETER_TRANSLATE(smul), INTERPRETER_TRANSLATE(smlalxy), |
| 2015 | INTERPRETER_TRANSLATE(uxtb), | 1858 | INTERPRETER_TRANSLATE(smla), INTERPRETER_TRANSLATE(mcrr), INTERPRETER_TRANSLATE(mrrc), |
| 2016 | INTERPRETER_TRANSLATE(sxth), | 1859 | INTERPRETER_TRANSLATE(cmp), INTERPRETER_TRANSLATE(tst), INTERPRETER_TRANSLATE(teq), |
| 2017 | INTERPRETER_TRANSLATE(sxtb16), | 1860 | INTERPRETER_TRANSLATE(cmn), INTERPRETER_TRANSLATE(smull), INTERPRETER_TRANSLATE(umull), |
| 2018 | INTERPRETER_TRANSLATE(uxth), | 1861 | INTERPRETER_TRANSLATE(umlal), INTERPRETER_TRANSLATE(smlal), INTERPRETER_TRANSLATE(mul), |
| 2019 | INTERPRETER_TRANSLATE(uxtb16), | 1862 | INTERPRETER_TRANSLATE(mla), INTERPRETER_TRANSLATE(ssat), INTERPRETER_TRANSLATE(usat), |
| 2020 | INTERPRETER_TRANSLATE(cpy), | 1863 | INTERPRETER_TRANSLATE(mrs), INTERPRETER_TRANSLATE(msr), INTERPRETER_TRANSLATE(and), |
| 2021 | INTERPRETER_TRANSLATE(uxtab), | 1864 | INTERPRETER_TRANSLATE(bic), INTERPRETER_TRANSLATE(ldm), INTERPRETER_TRANSLATE(eor), |
| 2022 | INTERPRETER_TRANSLATE(ssub8), | 1865 | INTERPRETER_TRANSLATE(add), INTERPRETER_TRANSLATE(rsb), INTERPRETER_TRANSLATE(rsc), |
| 2023 | INTERPRETER_TRANSLATE(shsub8), | 1866 | INTERPRETER_TRANSLATE(sbc), INTERPRETER_TRANSLATE(adc), INTERPRETER_TRANSLATE(sub), |
| 2024 | INTERPRETER_TRANSLATE(ssubaddx), | 1867 | INTERPRETER_TRANSLATE(orr), INTERPRETER_TRANSLATE(mvn), INTERPRETER_TRANSLATE(mov), |
| 2025 | INTERPRETER_TRANSLATE(strex), | 1868 | INTERPRETER_TRANSLATE(stm), INTERPRETER_TRANSLATE(ldm), INTERPRETER_TRANSLATE(ldrsh), |
| 2026 | INTERPRETER_TRANSLATE(strexb), | 1869 | INTERPRETER_TRANSLATE(stm), INTERPRETER_TRANSLATE(ldm), INTERPRETER_TRANSLATE(ldrsb), |
| 2027 | INTERPRETER_TRANSLATE(swp), | 1870 | INTERPRETER_TRANSLATE(strd), INTERPRETER_TRANSLATE(ldrh), INTERPRETER_TRANSLATE(strh), |
| 2028 | INTERPRETER_TRANSLATE(swpb), | 1871 | INTERPRETER_TRANSLATE(ldrd), INTERPRETER_TRANSLATE(strt), INTERPRETER_TRANSLATE(strbt), |
| 2029 | INTERPRETER_TRANSLATE(ssub16), | 1872 | INTERPRETER_TRANSLATE(ldrbt), INTERPRETER_TRANSLATE(ldrt), INTERPRETER_TRANSLATE(mrc), |
| 2030 | INTERPRETER_TRANSLATE(ssat16), | 1873 | INTERPRETER_TRANSLATE(mcr), INTERPRETER_TRANSLATE(msr), INTERPRETER_TRANSLATE(msr), |
| 2031 | INTERPRETER_TRANSLATE(shsubaddx), | 1874 | INTERPRETER_TRANSLATE(msr), INTERPRETER_TRANSLATE(msr), INTERPRETER_TRANSLATE(msr), |
| 2032 | INTERPRETER_TRANSLATE(qsubaddx), | 1875 | INTERPRETER_TRANSLATE(ldrb), INTERPRETER_TRANSLATE(strb), INTERPRETER_TRANSLATE(ldr), |
| 2033 | INTERPRETER_TRANSLATE(shaddsubx), | 1876 | INTERPRETER_TRANSLATE(ldrcond), INTERPRETER_TRANSLATE(str), INTERPRETER_TRANSLATE(cdp), |
| 2034 | INTERPRETER_TRANSLATE(shadd8), | 1877 | INTERPRETER_TRANSLATE(stc), INTERPRETER_TRANSLATE(ldc), INTERPRETER_TRANSLATE(ldrexd), |
| 2035 | INTERPRETER_TRANSLATE(shadd16), | 1878 | INTERPRETER_TRANSLATE(strexd), INTERPRETER_TRANSLATE(ldrexh), INTERPRETER_TRANSLATE(strexh), |
| 2036 | INTERPRETER_TRANSLATE(sel), | 1879 | INTERPRETER_TRANSLATE(nop), INTERPRETER_TRANSLATE(yield), INTERPRETER_TRANSLATE(wfe), |
| 2037 | INTERPRETER_TRANSLATE(saddsubx), | 1880 | INTERPRETER_TRANSLATE(wfi), INTERPRETER_TRANSLATE(sev), INTERPRETER_TRANSLATE(swi), |
| 2038 | INTERPRETER_TRANSLATE(sadd8), | ||
| 2039 | INTERPRETER_TRANSLATE(sadd16), | ||
| 2040 | INTERPRETER_TRANSLATE(shsub16), | ||
| 2041 | INTERPRETER_TRANSLATE(umaal), | ||
| 2042 | INTERPRETER_TRANSLATE(uxtab16), | ||
| 2043 | INTERPRETER_TRANSLATE(usubaddx), | ||
| 2044 | INTERPRETER_TRANSLATE(usub8), | ||
| 2045 | INTERPRETER_TRANSLATE(usub16), | ||
| 2046 | INTERPRETER_TRANSLATE(usat16), | ||
| 2047 | INTERPRETER_TRANSLATE(usada8), | ||
| 2048 | INTERPRETER_TRANSLATE(uqsubaddx), | ||
| 2049 | INTERPRETER_TRANSLATE(uqsub8), | ||
| 2050 | INTERPRETER_TRANSLATE(uqsub16), | ||
| 2051 | INTERPRETER_TRANSLATE(uqaddsubx), | ||
| 2052 | INTERPRETER_TRANSLATE(uqadd8), | ||
| 2053 | INTERPRETER_TRANSLATE(uqadd16), | ||
| 2054 | INTERPRETER_TRANSLATE(sxtab), | ||
| 2055 | INTERPRETER_TRANSLATE(uhsubaddx), | ||
| 2056 | INTERPRETER_TRANSLATE(uhsub8), | ||
| 2057 | INTERPRETER_TRANSLATE(uhsub16), | ||
| 2058 | INTERPRETER_TRANSLATE(uhaddsubx), | ||
| 2059 | INTERPRETER_TRANSLATE(uhadd8), | ||
| 2060 | INTERPRETER_TRANSLATE(uhadd16), | ||
| 2061 | INTERPRETER_TRANSLATE(uaddsubx), | ||
| 2062 | INTERPRETER_TRANSLATE(uadd8), | ||
| 2063 | INTERPRETER_TRANSLATE(uadd16), | ||
| 2064 | INTERPRETER_TRANSLATE(sxtah), | ||
| 2065 | INTERPRETER_TRANSLATE(sxtab16), | ||
| 2066 | INTERPRETER_TRANSLATE(qadd8), | ||
| 2067 | INTERPRETER_TRANSLATE(bxj), | ||
| 2068 | INTERPRETER_TRANSLATE(clz), | ||
| 2069 | INTERPRETER_TRANSLATE(uxtah), | ||
| 2070 | INTERPRETER_TRANSLATE(bx), | ||
| 2071 | INTERPRETER_TRANSLATE(rev), | ||
| 2072 | INTERPRETER_TRANSLATE(blx), | ||
| 2073 | INTERPRETER_TRANSLATE(revsh), | ||
| 2074 | INTERPRETER_TRANSLATE(qadd), | ||
| 2075 | INTERPRETER_TRANSLATE(qadd16), | ||
| 2076 | INTERPRETER_TRANSLATE(qaddsubx), | ||
| 2077 | INTERPRETER_TRANSLATE(ldrex), | ||
| 2078 | INTERPRETER_TRANSLATE(qdadd), | ||
| 2079 | INTERPRETER_TRANSLATE(qdsub), | ||
| 2080 | INTERPRETER_TRANSLATE(qsub), | ||
| 2081 | INTERPRETER_TRANSLATE(ldrexb), | ||
| 2082 | INTERPRETER_TRANSLATE(qsub8), | ||
| 2083 | INTERPRETER_TRANSLATE(qsub16), | ||
| 2084 | INTERPRETER_TRANSLATE(smuad), | ||
| 2085 | INTERPRETER_TRANSLATE(smmul), | ||
| 2086 | INTERPRETER_TRANSLATE(smusd), | ||
| 2087 | INTERPRETER_TRANSLATE(smlsd), | ||
| 2088 | INTERPRETER_TRANSLATE(smlsld), | ||
| 2089 | INTERPRETER_TRANSLATE(smmla), | ||
| 2090 | INTERPRETER_TRANSLATE(smmls), | ||
| 2091 | INTERPRETER_TRANSLATE(smlald), | ||
| 2092 | INTERPRETER_TRANSLATE(smlad), | ||
| 2093 | INTERPRETER_TRANSLATE(smlaw), | ||
| 2094 | INTERPRETER_TRANSLATE(smulw), | ||
| 2095 | INTERPRETER_TRANSLATE(pkhtb), | ||
| 2096 | INTERPRETER_TRANSLATE(pkhbt), | ||
| 2097 | INTERPRETER_TRANSLATE(smul), | ||
| 2098 | INTERPRETER_TRANSLATE(smlalxy), | ||
| 2099 | INTERPRETER_TRANSLATE(smla), | ||
| 2100 | INTERPRETER_TRANSLATE(mcrr), | ||
| 2101 | INTERPRETER_TRANSLATE(mrrc), | ||
| 2102 | INTERPRETER_TRANSLATE(cmp), | ||
| 2103 | INTERPRETER_TRANSLATE(tst), | ||
| 2104 | INTERPRETER_TRANSLATE(teq), | ||
| 2105 | INTERPRETER_TRANSLATE(cmn), | ||
| 2106 | INTERPRETER_TRANSLATE(smull), | ||
| 2107 | INTERPRETER_TRANSLATE(umull), | ||
| 2108 | INTERPRETER_TRANSLATE(umlal), | ||
| 2109 | INTERPRETER_TRANSLATE(smlal), | ||
| 2110 | INTERPRETER_TRANSLATE(mul), | ||
| 2111 | INTERPRETER_TRANSLATE(mla), | ||
| 2112 | INTERPRETER_TRANSLATE(ssat), | ||
| 2113 | INTERPRETER_TRANSLATE(usat), | ||
| 2114 | INTERPRETER_TRANSLATE(mrs), | ||
| 2115 | INTERPRETER_TRANSLATE(msr), | ||
| 2116 | INTERPRETER_TRANSLATE(and), | ||
| 2117 | INTERPRETER_TRANSLATE(bic), | ||
| 2118 | INTERPRETER_TRANSLATE(ldm), | ||
| 2119 | INTERPRETER_TRANSLATE(eor), | ||
| 2120 | INTERPRETER_TRANSLATE(add), | ||
| 2121 | INTERPRETER_TRANSLATE(rsb), | ||
| 2122 | INTERPRETER_TRANSLATE(rsc), | ||
| 2123 | INTERPRETER_TRANSLATE(sbc), | ||
| 2124 | INTERPRETER_TRANSLATE(adc), | ||
| 2125 | INTERPRETER_TRANSLATE(sub), | ||
| 2126 | INTERPRETER_TRANSLATE(orr), | ||
| 2127 | INTERPRETER_TRANSLATE(mvn), | ||
| 2128 | INTERPRETER_TRANSLATE(mov), | ||
| 2129 | INTERPRETER_TRANSLATE(stm), | ||
| 2130 | INTERPRETER_TRANSLATE(ldm), | ||
| 2131 | INTERPRETER_TRANSLATE(ldrsh), | ||
| 2132 | INTERPRETER_TRANSLATE(stm), | ||
| 2133 | INTERPRETER_TRANSLATE(ldm), | ||
| 2134 | INTERPRETER_TRANSLATE(ldrsb), | ||
| 2135 | INTERPRETER_TRANSLATE(strd), | ||
| 2136 | INTERPRETER_TRANSLATE(ldrh), | ||
| 2137 | INTERPRETER_TRANSLATE(strh), | ||
| 2138 | INTERPRETER_TRANSLATE(ldrd), | ||
| 2139 | INTERPRETER_TRANSLATE(strt), | ||
| 2140 | INTERPRETER_TRANSLATE(strbt), | ||
| 2141 | INTERPRETER_TRANSLATE(ldrbt), | ||
| 2142 | INTERPRETER_TRANSLATE(ldrt), | ||
| 2143 | INTERPRETER_TRANSLATE(mrc), | ||
| 2144 | INTERPRETER_TRANSLATE(mcr), | ||
| 2145 | INTERPRETER_TRANSLATE(msr), | ||
| 2146 | INTERPRETER_TRANSLATE(msr), | ||
| 2147 | INTERPRETER_TRANSLATE(msr), | ||
| 2148 | INTERPRETER_TRANSLATE(msr), | ||
| 2149 | INTERPRETER_TRANSLATE(msr), | ||
| 2150 | INTERPRETER_TRANSLATE(ldrb), | ||
| 2151 | INTERPRETER_TRANSLATE(strb), | ||
| 2152 | INTERPRETER_TRANSLATE(ldr), | ||
| 2153 | INTERPRETER_TRANSLATE(ldrcond), | ||
| 2154 | INTERPRETER_TRANSLATE(str), | ||
| 2155 | INTERPRETER_TRANSLATE(cdp), | ||
| 2156 | INTERPRETER_TRANSLATE(stc), | ||
| 2157 | INTERPRETER_TRANSLATE(ldc), | ||
| 2158 | INTERPRETER_TRANSLATE(ldrexd), | ||
| 2159 | INTERPRETER_TRANSLATE(strexd), | ||
| 2160 | INTERPRETER_TRANSLATE(ldrexh), | ||
| 2161 | INTERPRETER_TRANSLATE(strexh), | ||
| 2162 | INTERPRETER_TRANSLATE(nop), | ||
| 2163 | INTERPRETER_TRANSLATE(yield), | ||
| 2164 | INTERPRETER_TRANSLATE(wfe), | ||
| 2165 | INTERPRETER_TRANSLATE(wfi), | ||
| 2166 | INTERPRETER_TRANSLATE(sev), | ||
| 2167 | INTERPRETER_TRANSLATE(swi), | ||
| 2168 | INTERPRETER_TRANSLATE(bbl), | 1881 | INTERPRETER_TRANSLATE(bbl), |
| 2169 | 1882 | ||
| 2170 | // All the thumb instructions should be placed the end of table | 1883 | // All the thumb instructions should be placed the end of table |
| 2171 | INTERPRETER_TRANSLATE(b_2_thumb), | 1884 | INTERPRETER_TRANSLATE(b_2_thumb), INTERPRETER_TRANSLATE(b_cond_thumb), |
| 2172 | INTERPRETER_TRANSLATE(b_cond_thumb), | 1885 | INTERPRETER_TRANSLATE(bl_1_thumb), INTERPRETER_TRANSLATE(bl_2_thumb), |
| 2173 | INTERPRETER_TRANSLATE(bl_1_thumb), | 1886 | INTERPRETER_TRANSLATE(blx_1_thumb)}; |
| 2174 | INTERPRETER_TRANSLATE(bl_2_thumb), | ||
| 2175 | INTERPRETER_TRANSLATE(blx_1_thumb) | ||
| 2176 | }; | ||
| 2177 | 1887 | ||
| 2178 | const size_t arm_instruction_trans_len = sizeof(arm_instruction_trans) / sizeof(transop_fp_t); | 1888 | const size_t arm_instruction_trans_len = sizeof(arm_instruction_trans) / sizeof(transop_fp_t); |
diff --git a/src/core/arm/dyncom/arm_dyncom_trans.h b/src/core/arm/dyncom/arm_dyncom_trans.h index 7af71f4e3..6fdb3d248 100644 --- a/src/core/arm/dyncom/arm_dyncom_trans.h +++ b/src/core/arm/dyncom/arm_dyncom_trans.h | |||
| @@ -2,15 +2,15 @@ struct ARMul_State; | |||
| 2 | typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper); | 2 | typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper); |
| 3 | 3 | ||
| 4 | enum class TransExtData { | 4 | enum class TransExtData { |
| 5 | COND = (1 << 0), | 5 | COND = (1 << 0), |
| 6 | NON_BRANCH = (1 << 1), | 6 | NON_BRANCH = (1 << 1), |
| 7 | DIRECT_BRANCH = (1 << 2), | 7 | DIRECT_BRANCH = (1 << 2), |
| 8 | INDIRECT_BRANCH = (1 << 3), | 8 | INDIRECT_BRANCH = (1 << 3), |
| 9 | CALL = (1 << 4), | 9 | CALL = (1 << 4), |
| 10 | RET = (1 << 5), | 10 | RET = (1 << 5), |
| 11 | END_OF_PAGE = (1 << 6), | 11 | END_OF_PAGE = (1 << 6), |
| 12 | THUMB = (1 << 7), | 12 | THUMB = (1 << 7), |
| 13 | SINGLE_STEP = (1 << 8) | 13 | SINGLE_STEP = (1 << 8) |
| 14 | }; | 14 | }; |
| 15 | 15 | ||
| 16 | struct arm_inst { | 16 | struct arm_inst { |
| @@ -106,8 +106,7 @@ struct cps_inst { | |||
| 106 | unsigned int mode; | 106 | unsigned int mode; |
| 107 | }; | 107 | }; |
| 108 | 108 | ||
| 109 | struct clrex_inst { | 109 | struct clrex_inst {}; |
| 110 | }; | ||
| 111 | 110 | ||
| 112 | struct cpy_inst { | 111 | struct cpy_inst { |
| 113 | unsigned int Rm; | 112 | unsigned int Rm; |
| @@ -163,11 +162,9 @@ struct bkpt_inst { | |||
| 163 | u32 imm; | 162 | u32 imm; |
| 164 | }; | 163 | }; |
| 165 | 164 | ||
| 166 | struct stc_inst { | 165 | struct stc_inst {}; |
| 167 | }; | ||
| 168 | 166 | ||
| 169 | struct ldc_inst { | 167 | struct ldc_inst {}; |
| 170 | }; | ||
| 171 | 168 | ||
| 172 | struct swi_inst { | 169 | struct swi_inst { |
| 173 | unsigned int num; | 170 | unsigned int num; |
| @@ -369,8 +366,7 @@ struct msr_inst { | |||
| 369 | unsigned int inst; | 366 | unsigned int inst; |
| 370 | }; | 367 | }; |
| 371 | 368 | ||
| 372 | struct pld_inst { | 369 | struct pld_inst {}; |
| 373 | }; | ||
| 374 | 370 | ||
| 375 | struct sxtb_inst { | 371 | struct sxtb_inst { |
| 376 | unsigned int Rd; | 372 | unsigned int Rd; |
| @@ -475,7 +471,7 @@ struct pkh_inst { | |||
| 475 | #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" | 471 | #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" |
| 476 | #undef VFP_INTERPRETER_STRUCT | 472 | #undef VFP_INTERPRETER_STRUCT |
| 477 | 473 | ||
| 478 | typedef void (*get_addr_fp_t)(ARMul_State *cpu, unsigned int inst, unsigned int &virt_addr); | 474 | typedef void (*get_addr_fp_t)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr); |
| 479 | 475 | ||
| 480 | struct ldst_inst { | 476 | struct ldst_inst { |
| 481 | unsigned int inst; | 477 | unsigned int inst; |
diff --git a/src/core/arm/skyeye_common/arm_regformat.h b/src/core/arm/skyeye_common/arm_regformat.h index 38fa97ab9..706195a05 100644 --- a/src/core/arm/skyeye_common/arm_regformat.h +++ b/src/core/arm/skyeye_common/arm_regformat.h | |||
| @@ -16,7 +16,7 @@ enum { | |||
| 16 | R12, | 16 | R12, |
| 17 | R13, | 17 | R13, |
| 18 | LR, | 18 | LR, |
| 19 | R15, //PC, | 19 | R15, // PC, |
| 20 | CPSR_REG, | 20 | CPSR_REG, |
| 21 | SPSR_REG, | 21 | SPSR_REG, |
| 22 | 22 | ||
diff --git a/src/core/arm/skyeye_common/armstate.cpp b/src/core/arm/skyeye_common/armstate.cpp index 5550c112e..59329c656 100644 --- a/src/core/arm/skyeye_common/armstate.cpp +++ b/src/core/arm/skyeye_common/armstate.cpp | |||
| @@ -2,22 +2,20 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "core/arm/skyeye_common/armstate.h" | ||
| 5 | #include <algorithm> | 6 | #include <algorithm> |
| 6 | #include "common/swap.h" | ||
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | #include "core/memory.h" | 8 | #include "common/swap.h" |
| 9 | #include "core/arm/skyeye_common/armstate.h" | ||
| 10 | #include "core/arm/skyeye_common/vfp/vfp.h" | 9 | #include "core/arm/skyeye_common/vfp/vfp.h" |
| 11 | #include "core/gdbstub/gdbstub.h" | 10 | #include "core/gdbstub/gdbstub.h" |
| 11 | #include "core/memory.h" | ||
| 12 | 12 | ||
| 13 | ARMul_State::ARMul_State(PrivilegeMode initial_mode) | 13 | ARMul_State::ARMul_State(PrivilegeMode initial_mode) { |
| 14 | { | ||
| 15 | Reset(); | 14 | Reset(); |
| 16 | ChangePrivilegeMode(initial_mode); | 15 | ChangePrivilegeMode(initial_mode); |
| 17 | } | 16 | } |
| 18 | 17 | ||
| 19 | void ARMul_State::ChangePrivilegeMode(u32 new_mode) | 18 | void ARMul_State::ChangePrivilegeMode(u32 new_mode) { |
| 20 | { | ||
| 21 | if (Mode == new_mode) | 19 | if (Mode == new_mode) |
| 22 | return; | 20 | return; |
| 23 | 21 | ||
| @@ -103,8 +101,7 @@ void ARMul_State::ChangePrivilegeMode(u32 new_mode) | |||
| 103 | } | 101 | } |
| 104 | 102 | ||
| 105 | // Performs a reset | 103 | // Performs a reset |
| 106 | void ARMul_State::Reset() | 104 | void ARMul_State::Reset() { |
| 107 | { | ||
| 108 | VFPInit(this); | 105 | VFPInit(this); |
| 109 | 106 | ||
| 110 | // Set stack pointer to the top of the stack | 107 | // Set stack pointer to the top of the stack |
| @@ -128,8 +125,7 @@ void ARMul_State::Reset() | |||
| 128 | } | 125 | } |
| 129 | 126 | ||
| 130 | // Resets certain MPCore CP15 values to their ARM-defined reset values. | 127 | // Resets certain MPCore CP15 values to their ARM-defined reset values. |
| 131 | void ARMul_State::ResetMPCoreCP15Registers() | 128 | void ARMul_State::ResetMPCoreCP15Registers() { |
| 132 | { | ||
| 133 | // c0 | 129 | // c0 |
| 134 | CP15[CP15_MAIN_ID] = 0x410FB024; | 130 | CP15[CP15_MAIN_ID] = 0x410FB024; |
| 135 | CP15[CP15_TLB_TYPE] = 0x00000800; | 131 | CP15[CP15_TLB_TYPE] = 0x00000800; |
| @@ -185,23 +181,20 @@ void ARMul_State::ResetMPCoreCP15Registers() | |||
| 185 | CP15[CP15_TLB_DEBUG_CONTROL] = 0x00000000; | 181 | CP15[CP15_TLB_DEBUG_CONTROL] = 0x00000000; |
| 186 | } | 182 | } |
| 187 | 183 | ||
| 188 | static void CheckMemoryBreakpoint(u32 address, GDBStub::BreakpointType type) | 184 | static void CheckMemoryBreakpoint(u32 address, GDBStub::BreakpointType type) { |
| 189 | { | ||
| 190 | if (GDBStub::g_server_enabled && GDBStub::CheckBreakpoint(address, type)) { | 185 | if (GDBStub::g_server_enabled && GDBStub::CheckBreakpoint(address, type)) { |
| 191 | LOG_DEBUG(Debug, "Found memory breakpoint @ %08x", address); | 186 | LOG_DEBUG(Debug, "Found memory breakpoint @ %08x", address); |
| 192 | GDBStub::Break(true); | 187 | GDBStub::Break(true); |
| 193 | } | 188 | } |
| 194 | } | 189 | } |
| 195 | 190 | ||
| 196 | u8 ARMul_State::ReadMemory8(u32 address) const | 191 | u8 ARMul_State::ReadMemory8(u32 address) const { |
| 197 | { | ||
| 198 | CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); | 192 | CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); |
| 199 | 193 | ||
| 200 | return Memory::Read8(address); | 194 | return Memory::Read8(address); |
| 201 | } | 195 | } |
| 202 | 196 | ||
| 203 | u16 ARMul_State::ReadMemory16(u32 address) const | 197 | u16 ARMul_State::ReadMemory16(u32 address) const { |
| 204 | { | ||
| 205 | CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); | 198 | CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); |
| 206 | 199 | ||
| 207 | u16 data = Memory::Read16(address); | 200 | u16 data = Memory::Read16(address); |
| @@ -212,8 +205,7 @@ u16 ARMul_State::ReadMemory16(u32 address) const | |||
| 212 | return data; | 205 | return data; |
| 213 | } | 206 | } |
| 214 | 207 | ||
| 215 | u32 ARMul_State::ReadMemory32(u32 address) const | 208 | u32 ARMul_State::ReadMemory32(u32 address) const { |
| 216 | { | ||
| 217 | CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); | 209 | CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); |
| 218 | 210 | ||
| 219 | u32 data = Memory::Read32(address); | 211 | u32 data = Memory::Read32(address); |
| @@ -224,8 +216,7 @@ u32 ARMul_State::ReadMemory32(u32 address) const | |||
| 224 | return data; | 216 | return data; |
| 225 | } | 217 | } |
| 226 | 218 | ||
| 227 | u64 ARMul_State::ReadMemory64(u32 address) const | 219 | u64 ARMul_State::ReadMemory64(u32 address) const { |
| 228 | { | ||
| 229 | CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); | 220 | CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); |
| 230 | 221 | ||
| 231 | u64 data = Memory::Read64(address); | 222 | u64 data = Memory::Read64(address); |
| @@ -236,15 +227,13 @@ u64 ARMul_State::ReadMemory64(u32 address) const | |||
| 236 | return data; | 227 | return data; |
| 237 | } | 228 | } |
| 238 | 229 | ||
| 239 | void ARMul_State::WriteMemory8(u32 address, u8 data) | 230 | void ARMul_State::WriteMemory8(u32 address, u8 data) { |
| 240 | { | ||
| 241 | CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); | 231 | CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); |
| 242 | 232 | ||
| 243 | Memory::Write8(address, data); | 233 | Memory::Write8(address, data); |
| 244 | } | 234 | } |
| 245 | 235 | ||
| 246 | void ARMul_State::WriteMemory16(u32 address, u16 data) | 236 | void ARMul_State::WriteMemory16(u32 address, u16 data) { |
| 247 | { | ||
| 248 | CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); | 237 | CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); |
| 249 | 238 | ||
| 250 | if (InBigEndianMode()) | 239 | if (InBigEndianMode()) |
| @@ -253,8 +242,7 @@ void ARMul_State::WriteMemory16(u32 address, u16 data) | |||
| 253 | Memory::Write16(address, data); | 242 | Memory::Write16(address, data); |
| 254 | } | 243 | } |
| 255 | 244 | ||
| 256 | void ARMul_State::WriteMemory32(u32 address, u32 data) | 245 | void ARMul_State::WriteMemory32(u32 address, u32 data) { |
| 257 | { | ||
| 258 | CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); | 246 | CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); |
| 259 | 247 | ||
| 260 | if (InBigEndianMode()) | 248 | if (InBigEndianMode()) |
| @@ -263,8 +251,7 @@ void ARMul_State::WriteMemory32(u32 address, u32 data) | |||
| 263 | Memory::Write32(address, data); | 251 | Memory::Write32(address, data); |
| 264 | } | 252 | } |
| 265 | 253 | ||
| 266 | void ARMul_State::WriteMemory64(u32 address, u64 data) | 254 | void ARMul_State::WriteMemory64(u32 address, u64 data) { |
| 267 | { | ||
| 268 | CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); | 255 | CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); |
| 269 | 256 | ||
| 270 | if (InBigEndianMode()) | 257 | if (InBigEndianMode()) |
| @@ -273,15 +260,12 @@ void ARMul_State::WriteMemory64(u32 address, u64 data) | |||
| 273 | Memory::Write64(address, data); | 260 | Memory::Write64(address, data); |
| 274 | } | 261 | } |
| 275 | 262 | ||
| 276 | |||
| 277 | // Reads from the CP15 registers. Used with implementation of the MRC instruction. | 263 | // Reads from the CP15 registers. Used with implementation of the MRC instruction. |
| 278 | // Note that since the 3DS does not have the hypervisor extensions, these registers | 264 | // Note that since the 3DS does not have the hypervisor extensions, these registers |
| 279 | // are not implemented. | 265 | // are not implemented. |
| 280 | u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const | 266 | u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const { |
| 281 | { | ||
| 282 | // Unprivileged registers | 267 | // Unprivileged registers |
| 283 | if (crn == 13 && opcode_1 == 0 && crm == 0) | 268 | if (crn == 13 && opcode_1 == 0 && crm == 0) { |
| 284 | { | ||
| 285 | if (opcode_2 == 2) | 269 | if (opcode_2 == 2) |
| 286 | return CP15[CP15_THREAD_UPRW]; | 270 | return CP15[CP15_THREAD_UPRW]; |
| 287 | 271 | ||
| @@ -289,12 +273,9 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) | |||
| 289 | return CP15[CP15_THREAD_URO]; | 273 | return CP15[CP15_THREAD_URO]; |
| 290 | } | 274 | } |
| 291 | 275 | ||
| 292 | if (InAPrivilegedMode()) | 276 | if (InAPrivilegedMode()) { |
| 293 | { | 277 | if (crn == 0 && opcode_1 == 0) { |
| 294 | if (crn == 0 && opcode_1 == 0) | 278 | if (crm == 0) { |
| 295 | { | ||
| 296 | if (crm == 0) | ||
| 297 | { | ||
| 298 | if (opcode_2 == 0) | 279 | if (opcode_2 == 0) |
| 299 | return CP15[CP15_MAIN_ID]; | 280 | return CP15[CP15_MAIN_ID]; |
| 300 | 281 | ||
| @@ -306,9 +287,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) | |||
| 306 | 287 | ||
| 307 | if (opcode_2 == 5) | 288 | if (opcode_2 == 5) |
| 308 | return CP15[CP15_CPU_ID]; | 289 | return CP15[CP15_CPU_ID]; |
| 309 | } | 290 | } else if (crm == 1) { |
| 310 | else if (crm == 1) | ||
| 311 | { | ||
| 312 | if (opcode_2 == 0) | 291 | if (opcode_2 == 0) |
| 313 | return CP15[CP15_PROCESSOR_FEATURE_0]; | 292 | return CP15[CP15_PROCESSOR_FEATURE_0]; |
| 314 | 293 | ||
| @@ -329,9 +308,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) | |||
| 329 | 308 | ||
| 330 | if (opcode_2 == 7) | 309 | if (opcode_2 == 7) |
| 331 | return CP15[CP15_MEMORY_MODEL_FEATURE_3]; | 310 | return CP15[CP15_MEMORY_MODEL_FEATURE_3]; |
| 332 | } | 311 | } else if (crm == 2) { |
| 333 | else if (crm == 2) | ||
| 334 | { | ||
| 335 | if (opcode_2 == 0) | 312 | if (opcode_2 == 0) |
| 336 | return CP15[CP15_ISA_FEATURE_0]; | 313 | return CP15[CP15_ISA_FEATURE_0]; |
| 337 | 314 | ||
| @@ -349,8 +326,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) | |||
| 349 | } | 326 | } |
| 350 | } | 327 | } |
| 351 | 328 | ||
| 352 | if (crn == 1 && opcode_1 == 0 && crm == 0) | 329 | if (crn == 1 && opcode_1 == 0 && crm == 0) { |
| 353 | { | ||
| 354 | if (opcode_2 == 0) | 330 | if (opcode_2 == 0) |
| 355 | return CP15[CP15_CONTROL]; | 331 | return CP15[CP15_CONTROL]; |
| 356 | 332 | ||
| @@ -361,8 +337,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) | |||
| 361 | return CP15[CP15_COPROCESSOR_ACCESS_CONTROL]; | 337 | return CP15[CP15_COPROCESSOR_ACCESS_CONTROL]; |
| 362 | } | 338 | } |
| 363 | 339 | ||
| 364 | if (crn == 2 && opcode_1 == 0 && crm == 0) | 340 | if (crn == 2 && opcode_1 == 0 && crm == 0) { |
| 365 | { | ||
| 366 | if (opcode_2 == 0) | 341 | if (opcode_2 == 0) |
| 367 | return CP15[CP15_TRANSLATION_BASE_TABLE_0]; | 342 | return CP15[CP15_TRANSLATION_BASE_TABLE_0]; |
| 368 | 343 | ||
| @@ -376,8 +351,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) | |||
| 376 | if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | 351 | if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) |
| 377 | return CP15[CP15_DOMAIN_ACCESS_CONTROL]; | 352 | return CP15[CP15_DOMAIN_ACCESS_CONTROL]; |
| 378 | 353 | ||
| 379 | if (crn == 5 && opcode_1 == 0 && crm == 0) | 354 | if (crn == 5 && opcode_1 == 0 && crm == 0) { |
| 380 | { | ||
| 381 | if (opcode_2 == 0) | 355 | if (opcode_2 == 0) |
| 382 | return CP15[CP15_FAULT_STATUS]; | 356 | return CP15[CP15_FAULT_STATUS]; |
| 383 | 357 | ||
| @@ -385,8 +359,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) | |||
| 385 | return CP15[CP15_INSTR_FAULT_STATUS]; | 359 | return CP15[CP15_INSTR_FAULT_STATUS]; |
| 386 | } | 360 | } |
| 387 | 361 | ||
| 388 | if (crn == 6 && opcode_1 == 0 && crm == 0) | 362 | if (crn == 6 && opcode_1 == 0 && crm == 0) { |
| 389 | { | ||
| 390 | if (opcode_2 == 0) | 363 | if (opcode_2 == 0) |
| 391 | return CP15[CP15_FAULT_ADDRESS]; | 364 | return CP15[CP15_FAULT_ADDRESS]; |
| 392 | 365 | ||
| @@ -400,13 +373,11 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) | |||
| 400 | if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | 373 | if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) |
| 401 | return CP15[CP15_DATA_CACHE_LOCKDOWN]; | 374 | return CP15[CP15_DATA_CACHE_LOCKDOWN]; |
| 402 | 375 | ||
| 403 | if (crn == 10 && opcode_1 == 0) | 376 | if (crn == 10 && opcode_1 == 0) { |
| 404 | { | ||
| 405 | if (crm == 0 && opcode_2 == 0) | 377 | if (crm == 0 && opcode_2 == 0) |
| 406 | return CP15[CP15_TLB_LOCKDOWN]; | 378 | return CP15[CP15_TLB_LOCKDOWN]; |
| 407 | 379 | ||
| 408 | if (crm == 2) | 380 | if (crm == 2) { |
| 409 | { | ||
| 410 | if (opcode_2 == 0) | 381 | if (opcode_2 == 0) |
| 411 | return CP15[CP15_PRIMARY_REGION_REMAP]; | 382 | return CP15[CP15_PRIMARY_REGION_REMAP]; |
| 412 | 383 | ||
| @@ -415,8 +386,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) | |||
| 415 | } | 386 | } |
| 416 | } | 387 | } |
| 417 | 388 | ||
| 418 | if (crn == 13 && crm == 0) | 389 | if (crn == 13 && crm == 0) { |
| 419 | { | ||
| 420 | if (opcode_2 == 0) | 390 | if (opcode_2 == 0) |
| 421 | return CP15[CP15_PID]; | 391 | return CP15[CP15_PID]; |
| 422 | 392 | ||
| @@ -427,10 +397,8 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) | |||
| 427 | return CP15[CP15_THREAD_PRW]; | 397 | return CP15[CP15_THREAD_PRW]; |
| 428 | } | 398 | } |
| 429 | 399 | ||
| 430 | if (crn == 15) | 400 | if (crn == 15) { |
| 431 | { | 401 | if (opcode_1 == 0 && crm == 12) { |
| 432 | if (opcode_1 == 0 && crm == 12) | ||
| 433 | { | ||
| 434 | if (opcode_2 == 0) | 402 | if (opcode_2 == 0) |
| 435 | return CP15[CP15_PERFORMANCE_MONITOR_CONTROL]; | 403 | return CP15[CP15_PERFORMANCE_MONITOR_CONTROL]; |
| 436 | 404 | ||
| @@ -444,8 +412,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) | |||
| 444 | return CP15[CP15_COUNT_1]; | 412 | return CP15[CP15_COUNT_1]; |
| 445 | } | 413 | } |
| 446 | 414 | ||
| 447 | if (opcode_1 == 5 && opcode_2 == 2) | 415 | if (opcode_1 == 5 && opcode_2 == 2) { |
| 448 | { | ||
| 449 | if (crm == 5) | 416 | if (crm == 5) |
| 450 | return CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS]; | 417 | return CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS]; |
| 451 | 418 | ||
| @@ -461,66 +428,49 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) | |||
| 461 | } | 428 | } |
| 462 | } | 429 | } |
| 463 | 430 | ||
| 464 | LOG_ERROR(Core_ARM11, "MRC CRn=%u, CRm=%u, OP1=%u OP2=%u is not implemented. Returning zero.", crn, crm, opcode_1, opcode_2); | 431 | LOG_ERROR(Core_ARM11, "MRC CRn=%u, CRm=%u, OP1=%u OP2=%u is not implemented. Returning zero.", |
| 432 | crn, crm, opcode_1, opcode_2); | ||
| 465 | return 0; | 433 | return 0; |
| 466 | } | 434 | } |
| 467 | 435 | ||
| 468 | // Write to the CP15 registers. Used with implementation of the MCR instruction. | 436 | // Write to the CP15 registers. Used with implementation of the MCR instruction. |
| 469 | // Note that since the 3DS does not have the hypervisor extensions, these registers | 437 | // Note that since the 3DS does not have the hypervisor extensions, these registers |
| 470 | // are not implemented. | 438 | // are not implemented. |
| 471 | void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) | 439 | void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) { |
| 472 | { | 440 | if (InAPrivilegedMode()) { |
| 473 | if (InAPrivilegedMode()) | 441 | if (crn == 1 && opcode_1 == 0 && crm == 0) { |
| 474 | { | ||
| 475 | if (crn == 1 && opcode_1 == 0 && crm == 0) | ||
| 476 | { | ||
| 477 | if (opcode_2 == 0) | 442 | if (opcode_2 == 0) |
| 478 | CP15[CP15_CONTROL] = value; | 443 | CP15[CP15_CONTROL] = value; |
| 479 | else if (opcode_2 == 1) | 444 | else if (opcode_2 == 1) |
| 480 | CP15[CP15_AUXILIARY_CONTROL] = value; | 445 | CP15[CP15_AUXILIARY_CONTROL] = value; |
| 481 | else if (opcode_2 == 2) | 446 | else if (opcode_2 == 2) |
| 482 | CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = value; | 447 | CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = value; |
| 483 | } | 448 | } else if (crn == 2 && opcode_1 == 0 && crm == 0) { |
| 484 | else if (crn == 2 && opcode_1 == 0 && crm == 0) | ||
| 485 | { | ||
| 486 | if (opcode_2 == 0) | 449 | if (opcode_2 == 0) |
| 487 | CP15[CP15_TRANSLATION_BASE_TABLE_0] = value; | 450 | CP15[CP15_TRANSLATION_BASE_TABLE_0] = value; |
| 488 | else if (opcode_2 == 1) | 451 | else if (opcode_2 == 1) |
| 489 | CP15[CP15_TRANSLATION_BASE_TABLE_1] = value; | 452 | CP15[CP15_TRANSLATION_BASE_TABLE_1] = value; |
| 490 | else if (opcode_2 == 2) | 453 | else if (opcode_2 == 2) |
| 491 | CP15[CP15_TRANSLATION_BASE_CONTROL] = value; | 454 | CP15[CP15_TRANSLATION_BASE_CONTROL] = value; |
| 492 | } | 455 | } else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) { |
| 493 | else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | ||
| 494 | { | ||
| 495 | CP15[CP15_DOMAIN_ACCESS_CONTROL] = value; | 456 | CP15[CP15_DOMAIN_ACCESS_CONTROL] = value; |
| 496 | } | 457 | } else if (crn == 5 && opcode_1 == 0 && crm == 0) { |
| 497 | else if (crn == 5 && opcode_1 == 0 && crm == 0) | ||
| 498 | { | ||
| 499 | if (opcode_2 == 0) | 458 | if (opcode_2 == 0) |
| 500 | CP15[CP15_FAULT_STATUS] = value; | 459 | CP15[CP15_FAULT_STATUS] = value; |
| 501 | else if (opcode_2 == 1) | 460 | else if (opcode_2 == 1) |
| 502 | CP15[CP15_INSTR_FAULT_STATUS] = value; | 461 | CP15[CP15_INSTR_FAULT_STATUS] = value; |
| 503 | } | 462 | } else if (crn == 6 && opcode_1 == 0 && crm == 0) { |
| 504 | else if (crn == 6 && opcode_1 == 0 && crm == 0) | ||
| 505 | { | ||
| 506 | if (opcode_2 == 0) | 463 | if (opcode_2 == 0) |
| 507 | CP15[CP15_FAULT_ADDRESS] = value; | 464 | CP15[CP15_FAULT_ADDRESS] = value; |
| 508 | else if (opcode_2 == 1) | 465 | else if (opcode_2 == 1) |
| 509 | CP15[CP15_WFAR] = value; | 466 | CP15[CP15_WFAR] = value; |
| 510 | } | 467 | } else if (crn == 7 && opcode_1 == 0) { |
| 511 | else if (crn == 7 && opcode_1 == 0) | 468 | if (crm == 0 && opcode_2 == 4) { |
| 512 | { | ||
| 513 | if (crm == 0 && opcode_2 == 4) | ||
| 514 | { | ||
| 515 | CP15[CP15_WAIT_FOR_INTERRUPT] = value; | 469 | CP15[CP15_WAIT_FOR_INTERRUPT] = value; |
| 516 | } | 470 | } else if (crm == 4 && opcode_2 == 0) { |
| 517 | else if (crm == 4 && opcode_2 == 0) | ||
| 518 | { | ||
| 519 | // NOTE: Not entirely accurate. This should do permission checks. | 471 | // NOTE: Not entirely accurate. This should do permission checks. |
| 520 | CP15[CP15_PHYS_ADDRESS] = Memory::VirtualToPhysicalAddress(value); | 472 | CP15[CP15_PHYS_ADDRESS] = Memory::VirtualToPhysicalAddress(value); |
| 521 | } | 473 | } else if (crm == 5) { |
| 522 | else if (crm == 5) | ||
| 523 | { | ||
| 524 | if (opcode_2 == 0) | 474 | if (opcode_2 == 0) |
| 525 | CP15[CP15_INVALIDATE_INSTR_CACHE] = value; | 475 | CP15[CP15_INVALIDATE_INSTR_CACHE] = value; |
| 526 | else if (opcode_2 == 1) | 476 | else if (opcode_2 == 1) |
| @@ -531,31 +481,23 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u | |||
| 531 | CP15[CP15_FLUSH_BRANCH_TARGET_CACHE] = value; | 481 | CP15[CP15_FLUSH_BRANCH_TARGET_CACHE] = value; |
| 532 | else if (opcode_2 == 7) | 482 | else if (opcode_2 == 7) |
| 533 | CP15[CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY] = value; | 483 | CP15[CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY] = value; |
| 534 | } | 484 | } else if (crm == 6) { |
| 535 | else if (crm == 6) | ||
| 536 | { | ||
| 537 | if (opcode_2 == 0) | 485 | if (opcode_2 == 0) |
| 538 | CP15[CP15_INVALIDATE_DATA_CACHE] = value; | 486 | CP15[CP15_INVALIDATE_DATA_CACHE] = value; |
| 539 | else if (opcode_2 == 1) | 487 | else if (opcode_2 == 1) |
| 540 | CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value; | 488 | CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value; |
| 541 | else if (opcode_2 == 2) | 489 | else if (opcode_2 == 2) |
| 542 | CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; | 490 | CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; |
| 543 | } | 491 | } else if (crm == 7 && opcode_2 == 0) { |
| 544 | else if (crm == 7 && opcode_2 == 0) | ||
| 545 | { | ||
| 546 | CP15[CP15_INVALIDATE_DATA_AND_INSTR_CACHE] = value; | 492 | CP15[CP15_INVALIDATE_DATA_AND_INSTR_CACHE] = value; |
| 547 | } | 493 | } else if (crm == 10) { |
| 548 | else if (crm == 10) | ||
| 549 | { | ||
| 550 | if (opcode_2 == 0) | 494 | if (opcode_2 == 0) |
| 551 | CP15[CP15_CLEAN_DATA_CACHE] = value; | 495 | CP15[CP15_CLEAN_DATA_CACHE] = value; |
| 552 | else if (opcode_2 == 1) | 496 | else if (opcode_2 == 1) |
| 553 | CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_MVA] = value; | 497 | CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_MVA] = value; |
| 554 | else if (opcode_2 == 2) | 498 | else if (opcode_2 == 2) |
| 555 | CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX] = value; | 499 | CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX] = value; |
| 556 | } | 500 | } else if (crm == 14) { |
| 557 | else if (crm == 14) | ||
| 558 | { | ||
| 559 | if (opcode_2 == 0) | 501 | if (opcode_2 == 0) |
| 560 | CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE] = value; | 502 | CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE] = value; |
| 561 | else if (opcode_2 == 1) | 503 | else if (opcode_2 == 1) |
| @@ -563,11 +505,8 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u | |||
| 563 | else if (opcode_2 == 2) | 505 | else if (opcode_2 == 2) |
| 564 | CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; | 506 | CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; |
| 565 | } | 507 | } |
| 566 | } | 508 | } else if (crn == 8 && opcode_1 == 0) { |
| 567 | else if (crn == 8 && opcode_1 == 0) | 509 | if (crm == 5) { |
| 568 | { | ||
| 569 | if (crm == 5) | ||
| 570 | { | ||
| 571 | if (opcode_2 == 0) | 510 | if (opcode_2 == 0) |
| 572 | CP15[CP15_INVALIDATE_ITLB] = value; | 511 | CP15[CP15_INVALIDATE_ITLB] = value; |
| 573 | else if (opcode_2 == 1) | 512 | else if (opcode_2 == 1) |
| @@ -576,9 +515,7 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u | |||
| 576 | CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH] = value; | 515 | CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH] = value; |
| 577 | else if (opcode_2 == 3) | 516 | else if (opcode_2 == 3) |
| 578 | CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_MVA] = value; | 517 | CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_MVA] = value; |
| 579 | } | 518 | } else if (crm == 6) { |
| 580 | else if (crm == 6) | ||
| 581 | { | ||
| 582 | if (opcode_2 == 0) | 519 | if (opcode_2 == 0) |
| 583 | CP15[CP15_INVALIDATE_DTLB] = value; | 520 | CP15[CP15_INVALIDATE_DTLB] = value; |
| 584 | else if (opcode_2 == 1) | 521 | else if (opcode_2 == 1) |
| @@ -587,9 +524,7 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u | |||
| 587 | CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH] = value; | 524 | CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH] = value; |
| 588 | else if (opcode_2 == 3) | 525 | else if (opcode_2 == 3) |
| 589 | CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_MVA] = value; | 526 | CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_MVA] = value; |
| 590 | } | 527 | } else if (crm == 7) { |
| 591 | else if (crm == 7) | ||
| 592 | { | ||
| 593 | if (opcode_2 == 0) | 528 | if (opcode_2 == 0) |
| 594 | CP15[CP15_INVALIDATE_UTLB] = value; | 529 | CP15[CP15_INVALIDATE_UTLB] = value; |
| 595 | else if (opcode_2 == 1) | 530 | else if (opcode_2 == 1) |
| @@ -599,27 +534,18 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u | |||
| 599 | else if (opcode_2 == 3) | 534 | else if (opcode_2 == 3) |
| 600 | CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_MVA] = value; | 535 | CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_MVA] = value; |
| 601 | } | 536 | } |
| 602 | } | 537 | } else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) { |
| 603 | else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | ||
| 604 | { | ||
| 605 | CP15[CP15_DATA_CACHE_LOCKDOWN] = value; | 538 | CP15[CP15_DATA_CACHE_LOCKDOWN] = value; |
| 606 | } | 539 | } else if (crn == 10 && opcode_1 == 0) { |
| 607 | else if (crn == 10 && opcode_1 == 0) | 540 | if (crm == 0 && opcode_2 == 0) { |
| 608 | { | ||
| 609 | if (crm == 0 && opcode_2 == 0) | ||
| 610 | { | ||
| 611 | CP15[CP15_TLB_LOCKDOWN] = value; | 541 | CP15[CP15_TLB_LOCKDOWN] = value; |
| 612 | } | 542 | } else if (crm == 2) { |
| 613 | else if (crm == 2) | ||
| 614 | { | ||
| 615 | if (opcode_2 == 0) | 543 | if (opcode_2 == 0) |
| 616 | CP15[CP15_PRIMARY_REGION_REMAP] = value; | 544 | CP15[CP15_PRIMARY_REGION_REMAP] = value; |
| 617 | else if (opcode_2 == 1) | 545 | else if (opcode_2 == 1) |
| 618 | CP15[CP15_NORMAL_REGION_REMAP] = value; | 546 | CP15[CP15_NORMAL_REGION_REMAP] = value; |
| 619 | } | 547 | } |
| 620 | } | 548 | } else if (crn == 13 && opcode_1 == 0 && crm == 0) { |
| 621 | else if (crn == 13 && opcode_1 == 0 && crm == 0) | ||
| 622 | { | ||
| 623 | if (opcode_2 == 0) | 549 | if (opcode_2 == 0) |
| 624 | CP15[CP15_PID] = value; | 550 | CP15[CP15_PID] = value; |
| 625 | else if (opcode_2 == 1) | 551 | else if (opcode_2 == 1) |
| @@ -628,11 +554,8 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u | |||
| 628 | CP15[CP15_THREAD_URO] = value; | 554 | CP15[CP15_THREAD_URO] = value; |
| 629 | else if (opcode_2 == 4) | 555 | else if (opcode_2 == 4) |
| 630 | CP15[CP15_THREAD_PRW] = value; | 556 | CP15[CP15_THREAD_PRW] = value; |
| 631 | } | 557 | } else if (crn == 15) { |
| 632 | else if (crn == 15) | 558 | if (opcode_1 == 0 && crm == 12) { |
| 633 | { | ||
| 634 | if (opcode_1 == 0 && crm == 12) | ||
| 635 | { | ||
| 636 | if (opcode_2 == 0) | 559 | if (opcode_2 == 0) |
| 637 | CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = value; | 560 | CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = value; |
| 638 | else if (opcode_2 == 1) | 561 | else if (opcode_2 == 1) |
| @@ -641,50 +564,34 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u | |||
| 641 | CP15[CP15_COUNT_0] = value; | 564 | CP15[CP15_COUNT_0] = value; |
| 642 | else if (opcode_2 == 3) | 565 | else if (opcode_2 == 3) |
| 643 | CP15[CP15_COUNT_1] = value; | 566 | CP15[CP15_COUNT_1] = value; |
| 644 | } | 567 | } else if (opcode_1 == 5) { |
| 645 | else if (opcode_1 == 5) | 568 | if (crm == 4) { |
| 646 | { | ||
| 647 | if (crm == 4) | ||
| 648 | { | ||
| 649 | if (opcode_2 == 2) | 569 | if (opcode_2 == 2) |
| 650 | CP15[CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY] = value; | 570 | CP15[CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY] = value; |
| 651 | else if (opcode_2 == 4) | 571 | else if (opcode_2 == 4) |
| 652 | CP15[CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY] = value; | 572 | CP15[CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY] = value; |
| 653 | } | 573 | } else if (crm == 5 && opcode_2 == 2) { |
| 654 | else if (crm == 5 && opcode_2 == 2) | ||
| 655 | { | ||
| 656 | CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = value; | 574 | CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = value; |
| 657 | } | 575 | } else if (crm == 6 && opcode_2 == 2) { |
| 658 | else if (crm == 6 && opcode_2 == 2) | ||
| 659 | { | ||
| 660 | CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = value; | 576 | CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = value; |
| 661 | } | 577 | } else if (crm == 7 && opcode_2 == 2) { |
| 662 | else if (crm == 7 && opcode_2 == 2) | ||
| 663 | { | ||
| 664 | CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = value; | 578 | CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = value; |
| 665 | } | 579 | } |
| 666 | } | 580 | } else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) { |
| 667 | else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) | ||
| 668 | { | ||
| 669 | CP15[CP15_TLB_DEBUG_CONTROL] = value; | 581 | CP15[CP15_TLB_DEBUG_CONTROL] = value; |
| 670 | } | 582 | } |
| 671 | } | 583 | } |
| 672 | } | 584 | } |
| 673 | 585 | ||
| 674 | // Unprivileged registers | 586 | // Unprivileged registers |
| 675 | if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4) | 587 | if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4) { |
| 676 | { | ||
| 677 | CP15[CP15_FLUSH_PREFETCH_BUFFER] = value; | 588 | CP15[CP15_FLUSH_PREFETCH_BUFFER] = value; |
| 678 | } | 589 | } else if (crn == 7 && opcode_1 == 0 && crm == 10) { |
| 679 | else if (crn == 7 && opcode_1 == 0 && crm == 10) | ||
| 680 | { | ||
| 681 | if (opcode_2 == 4) | 590 | if (opcode_2 == 4) |
| 682 | CP15[CP15_DATA_SYNC_BARRIER] = value; | 591 | CP15[CP15_DATA_SYNC_BARRIER] = value; |
| 683 | else if (opcode_2 == 5) | 592 | else if (opcode_2 == 5) |
| 684 | CP15[CP15_DATA_MEMORY_BARRIER] = value; | 593 | CP15[CP15_DATA_MEMORY_BARRIER] = value; |
| 685 | } | 594 | } else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2) { |
| 686 | else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2) | ||
| 687 | { | ||
| 688 | CP15[CP15_THREAD_UPRW] = value; | 595 | CP15[CP15_THREAD_UPRW] = value; |
| 689 | } | 596 | } |
| 690 | } | 597 | } |
diff --git a/src/core/arm/skyeye_common/armstate.h b/src/core/arm/skyeye_common/armstate.h index d42ff2669..66567c285 100644 --- a/src/core/arm/skyeye_common/armstate.h +++ b/src/core/arm/skyeye_common/armstate.h | |||
| @@ -24,75 +24,70 @@ | |||
| 24 | #include "core/arm/skyeye_common/arm_regformat.h" | 24 | #include "core/arm/skyeye_common/arm_regformat.h" |
| 25 | 25 | ||
| 26 | // Signal levels | 26 | // Signal levels |
| 27 | enum { | 27 | enum { LOW = 0, HIGH = 1, LOWHIGH = 1, HIGHLOW = 2 }; |
| 28 | LOW = 0, | ||
| 29 | HIGH = 1, | ||
| 30 | LOWHIGH = 1, | ||
| 31 | HIGHLOW = 2 | ||
| 32 | }; | ||
| 33 | 28 | ||
| 34 | // Cache types | 29 | // Cache types |
| 35 | enum { | 30 | enum { |
| 36 | NONCACHE = 0, | 31 | NONCACHE = 0, |
| 37 | DATACACHE = 1, | 32 | DATACACHE = 1, |
| 38 | INSTCACHE = 2, | 33 | INSTCACHE = 2, |
| 39 | }; | 34 | }; |
| 40 | 35 | ||
| 41 | // ARM privilege modes | 36 | // ARM privilege modes |
| 42 | enum PrivilegeMode { | 37 | enum PrivilegeMode { |
| 43 | USER32MODE = 16, | 38 | USER32MODE = 16, |
| 44 | FIQ32MODE = 17, | 39 | FIQ32MODE = 17, |
| 45 | IRQ32MODE = 18, | 40 | IRQ32MODE = 18, |
| 46 | SVC32MODE = 19, | 41 | SVC32MODE = 19, |
| 47 | ABORT32MODE = 23, | 42 | ABORT32MODE = 23, |
| 48 | UNDEF32MODE = 27, | 43 | UNDEF32MODE = 27, |
| 49 | SYSTEM32MODE = 31 | 44 | SYSTEM32MODE = 31 |
| 50 | }; | 45 | }; |
| 51 | 46 | ||
| 52 | // ARM privilege mode register banks | 47 | // ARM privilege mode register banks |
| 53 | enum { | 48 | enum { |
| 54 | USERBANK = 0, | 49 | USERBANK = 0, |
| 55 | FIQBANK = 1, | 50 | FIQBANK = 1, |
| 56 | IRQBANK = 2, | 51 | IRQBANK = 2, |
| 57 | SVCBANK = 3, | 52 | SVCBANK = 3, |
| 58 | ABORTBANK = 4, | 53 | ABORTBANK = 4, |
| 59 | UNDEFBANK = 5, | 54 | UNDEFBANK = 5, |
| 60 | DUMMYBANK = 6, | 55 | DUMMYBANK = 6, |
| 61 | SYSTEMBANK = 7 | 56 | SYSTEMBANK = 7 |
| 62 | }; | 57 | }; |
| 63 | 58 | ||
| 64 | // Hardware vector addresses | 59 | // Hardware vector addresses |
| 65 | enum { | 60 | enum { |
| 66 | ARMResetV = 0, | 61 | ARMResetV = 0, |
| 67 | ARMUndefinedInstrV = 4, | 62 | ARMUndefinedInstrV = 4, |
| 68 | ARMSWIV = 8, | 63 | ARMSWIV = 8, |
| 69 | ARMPrefetchAbortV = 12, | 64 | ARMPrefetchAbortV = 12, |
| 70 | ARMDataAbortV = 16, | 65 | ARMDataAbortV = 16, |
| 71 | ARMAddrExceptnV = 20, | 66 | ARMAddrExceptnV = 20, |
| 72 | ARMIRQV = 24, | 67 | ARMIRQV = 24, |
| 73 | ARMFIQV = 28, | 68 | ARMFIQV = 28, |
| 74 | ARMErrorV = 32, // This is an offset, not an address! | 69 | ARMErrorV = 32, // This is an offset, not an address! |
| 75 | 70 | ||
| 76 | ARMul_ResetV = ARMResetV, | 71 | ARMul_ResetV = ARMResetV, |
| 77 | ARMul_UndefinedInstrV = ARMUndefinedInstrV, | 72 | ARMul_UndefinedInstrV = ARMUndefinedInstrV, |
| 78 | ARMul_SWIV = ARMSWIV, | 73 | ARMul_SWIV = ARMSWIV, |
| 79 | ARMul_PrefetchAbortV = ARMPrefetchAbortV, | 74 | ARMul_PrefetchAbortV = ARMPrefetchAbortV, |
| 80 | ARMul_DataAbortV = ARMDataAbortV, | 75 | ARMul_DataAbortV = ARMDataAbortV, |
| 81 | ARMul_AddrExceptnV = ARMAddrExceptnV, | 76 | ARMul_AddrExceptnV = ARMAddrExceptnV, |
| 82 | ARMul_IRQV = ARMIRQV, | 77 | ARMul_IRQV = ARMIRQV, |
| 83 | ARMul_FIQV = ARMFIQV | 78 | ARMul_FIQV = ARMFIQV |
| 84 | }; | 79 | }; |
| 85 | 80 | ||
| 86 | // Coprocessor status values | 81 | // Coprocessor status values |
| 87 | enum { | 82 | enum { |
| 88 | ARMul_FIRST = 0, | 83 | ARMul_FIRST = 0, |
| 89 | ARMul_TRANSFER = 1, | 84 | ARMul_TRANSFER = 1, |
| 90 | ARMul_BUSY = 2, | 85 | ARMul_BUSY = 2, |
| 91 | ARMul_DATA = 3, | 86 | ARMul_DATA = 3, |
| 92 | ARMul_INTERRUPT = 4, | 87 | ARMul_INTERRUPT = 4, |
| 93 | ARMul_DONE = 0, | 88 | ARMul_DONE = 0, |
| 94 | ARMul_CANT = 1, | 89 | ARMul_CANT = 1, |
| 95 | ARMul_INC = 3 | 90 | ARMul_INC = 3 |
| 96 | }; | 91 | }; |
| 97 | 92 | ||
| 98 | // Instruction condition codes | 93 | // Instruction condition codes |
| @@ -136,15 +131,13 @@ enum : u32 { | |||
| 136 | 131 | ||
| 137 | // Values for Emulate. | 132 | // Values for Emulate. |
| 138 | enum { | 133 | enum { |
| 139 | STOP = 0, // Stop | 134 | STOP = 0, // Stop |
| 140 | CHANGEMODE = 1, // Change mode | 135 | CHANGEMODE = 1, // Change mode |
| 141 | ONCE = 2, // Execute just one iteration | 136 | ONCE = 2, // Execute just one iteration |
| 142 | RUN = 3 // Continuous execution | 137 | RUN = 3 // Continuous execution |
| 143 | }; | 138 | }; |
| 144 | 139 | ||
| 145 | 140 | struct ARMul_State final { | |
| 146 | struct ARMul_State final | ||
| 147 | { | ||
| 148 | public: | 141 | public: |
| 149 | explicit ARMul_State(PrivilegeMode initial_mode); | 142 | explicit ARMul_State(PrivilegeMode initial_mode); |
| 150 | 143 | ||
| @@ -193,7 +186,7 @@ public: | |||
| 193 | return TFlag ? 2 : 4; | 186 | return TFlag ? 2 : 4; |
| 194 | } | 187 | } |
| 195 | 188 | ||
| 196 | std::array<u32, 16> Reg{}; // The current register file | 189 | std::array<u32, 16> Reg{}; // The current register file |
| 197 | std::array<u32, 2> Reg_usr{}; | 190 | std::array<u32, 2> Reg_usr{}; |
| 198 | std::array<u32, 2> Reg_svc{}; // R13_SVC R14_SVC | 191 | std::array<u32, 2> Reg_svc{}; // R13_SVC R14_SVC |
| 199 | std::array<u32, 2> Reg_abort{}; // R13_ABORT R14_ABORT | 192 | std::array<u32, 2> Reg_abort{}; // R13_ABORT R14_ABORT |
| @@ -216,8 +209,8 @@ public: | |||
| 216 | u32 Spsr_copy; | 209 | u32 Spsr_copy; |
| 217 | u32 phys_pc; | 210 | u32 phys_pc; |
| 218 | 211 | ||
| 219 | u32 Mode; // The current mode | 212 | u32 Mode; // The current mode |
| 220 | u32 Bank; // The current register bank | 213 | u32 Bank; // The current register bank |
| 221 | 214 | ||
| 222 | u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed | 215 | u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed |
| 223 | unsigned int shifter_carry_out; | 216 | unsigned int shifter_carry_out; |
| @@ -243,8 +236,10 @@ public: | |||
| 243 | private: | 236 | private: |
| 244 | void ResetMPCoreCP15Registers(); | 237 | void ResetMPCoreCP15Registers(); |
| 245 | 238 | ||
| 246 | // Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag. | 239 | // Defines a reservation granule of 2 words, which protects the first 2 words starting at the |
| 247 | // This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to | 240 | // tag. |
| 241 | // This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough | ||
| 242 | // to | ||
| 248 | // support LDR/STREXD. | 243 | // support LDR/STREXD. |
| 249 | static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8; | 244 | static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8; |
| 250 | 245 | ||
diff --git a/src/core/arm/skyeye_common/armsupp.cpp b/src/core/arm/skyeye_common/armsupp.cpp index 883713e86..e70be29a7 100644 --- a/src/core/arm/skyeye_common/armsupp.cpp +++ b/src/core/arm/skyeye_common/armsupp.cpp | |||
| @@ -22,8 +22,7 @@ | |||
| 22 | #include "core/arm/skyeye_common/armsupp.h" | 22 | #include "core/arm/skyeye_common/armsupp.h" |
| 23 | 23 | ||
| 24 | // Unsigned sum of absolute difference | 24 | // Unsigned sum of absolute difference |
| 25 | u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) | 25 | u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) { |
| 26 | { | ||
| 27 | if (left > right) | 26 | if (left > right) |
| 28 | return left - right; | 27 | return left - right; |
| 29 | 28 | ||
| @@ -31,8 +30,8 @@ u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) | |||
| 31 | } | 30 | } |
| 32 | 31 | ||
| 33 | // Add with carry, indicates if a carry-out or signed overflow occurred. | 32 | // Add with carry, indicates if a carry-out or signed overflow occurred. |
| 34 | u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bool* overflow_occurred) | 33 | u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, |
| 35 | { | 34 | bool* overflow_occurred) { |
| 36 | u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in; | 35 | u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in; |
| 37 | s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in; | 36 | s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in; |
| 38 | u64 result = (unsigned_sum & 0xFFFFFFFF); | 37 | u64 result = (unsigned_sum & 0xFFFFFFFF); |
| @@ -47,22 +46,17 @@ u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bo | |||
| 47 | } | 46 | } |
| 48 | 47 | ||
| 49 | // Compute whether an addition of A and B, giving RESULT, overflowed. | 48 | // Compute whether an addition of A and B, giving RESULT, overflowed. |
| 50 | bool AddOverflow(u32 a, u32 b, u32 result) | 49 | bool AddOverflow(u32 a, u32 b, u32 result) { |
| 51 | { | 50 | return ((NEG(a) && NEG(b) && POS(result)) || (POS(a) && POS(b) && NEG(result))); |
| 52 | return ((NEG(a) && NEG(b) && POS(result)) || | ||
| 53 | (POS(a) && POS(b) && NEG(result))); | ||
| 54 | } | 51 | } |
| 55 | 52 | ||
| 56 | // Compute whether a subtraction of A and B, giving RESULT, overflowed. | 53 | // Compute whether a subtraction of A and B, giving RESULT, overflowed. |
| 57 | bool SubOverflow(u32 a, u32 b, u32 result) | 54 | bool SubOverflow(u32 a, u32 b, u32 result) { |
| 58 | { | 55 | return ((NEG(a) && POS(b) && POS(result)) || (POS(a) && NEG(b) && NEG(result))); |
| 59 | return ((NEG(a) && POS(b) && POS(result)) || | ||
| 60 | (POS(a) && NEG(b) && NEG(result))); | ||
| 61 | } | 56 | } |
| 62 | 57 | ||
| 63 | // Returns true if the Q flag should be set as a result of overflow. | 58 | // Returns true if the Q flag should be set as a result of overflow. |
| 64 | bool ARMul_AddOverflowQ(u32 a, u32 b) | 59 | bool ARMul_AddOverflowQ(u32 a, u32 b) { |
| 65 | { | ||
| 66 | u32 result = a + b; | 60 | u32 result = a + b; |
| 67 | if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0) | 61 | if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0) |
| 68 | return true; | 62 | return true; |
| @@ -71,8 +65,7 @@ bool ARMul_AddOverflowQ(u32 a, u32 b) | |||
| 71 | } | 65 | } |
| 72 | 66 | ||
| 73 | // 8-bit signed saturated addition | 67 | // 8-bit signed saturated addition |
| 74 | u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) | 68 | u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) { |
| 75 | { | ||
| 76 | u8 result = left + right; | 69 | u8 result = left + right; |
| 77 | 70 | ||
| 78 | if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) { | 71 | if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) { |
| @@ -86,8 +79,7 @@ u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) | |||
| 86 | } | 79 | } |
| 87 | 80 | ||
| 88 | // 8-bit signed saturated subtraction | 81 | // 8-bit signed saturated subtraction |
| 89 | u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) | 82 | u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) { |
| 90 | { | ||
| 91 | u8 result = left - right; | 83 | u8 result = left - right; |
| 92 | 84 | ||
| 93 | if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) { | 85 | if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) { |
| @@ -101,8 +93,7 @@ u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) | |||
| 101 | } | 93 | } |
| 102 | 94 | ||
| 103 | // 16-bit signed saturated addition | 95 | // 16-bit signed saturated addition |
| 104 | u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) | 96 | u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) { |
| 105 | { | ||
| 106 | u16 result = left + right; | 97 | u16 result = left + right; |
| 107 | 98 | ||
| 108 | if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) { | 99 | if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) { |
| @@ -116,8 +107,7 @@ u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) | |||
| 116 | } | 107 | } |
| 117 | 108 | ||
| 118 | // 16-bit signed saturated subtraction | 109 | // 16-bit signed saturated subtraction |
| 119 | u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) | 110 | u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) { |
| 120 | { | ||
| 121 | u16 result = left - right; | 111 | u16 result = left - right; |
| 122 | 112 | ||
| 123 | if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) { | 113 | if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) { |
| @@ -131,8 +121,7 @@ u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) | |||
| 131 | } | 121 | } |
| 132 | 122 | ||
| 133 | // 8-bit unsigned saturated addition | 123 | // 8-bit unsigned saturated addition |
| 134 | u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) | 124 | u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) { |
| 135 | { | ||
| 136 | u8 result = left + right; | 125 | u8 result = left + right; |
| 137 | 126 | ||
| 138 | if (result < left) | 127 | if (result < left) |
| @@ -142,8 +131,7 @@ u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) | |||
| 142 | } | 131 | } |
| 143 | 132 | ||
| 144 | // 16-bit unsigned saturated addition | 133 | // 16-bit unsigned saturated addition |
| 145 | u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) | 134 | u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) { |
| 146 | { | ||
| 147 | u16 result = left + right; | 135 | u16 result = left + right; |
| 148 | 136 | ||
| 149 | if (result < left) | 137 | if (result < left) |
| @@ -153,8 +141,7 @@ u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) | |||
| 153 | } | 141 | } |
| 154 | 142 | ||
| 155 | // 8-bit unsigned saturated subtraction | 143 | // 8-bit unsigned saturated subtraction |
| 156 | u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) | 144 | u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) { |
| 157 | { | ||
| 158 | if (left <= right) | 145 | if (left <= right) |
| 159 | return 0; | 146 | return 0; |
| 160 | 147 | ||
| @@ -162,8 +149,7 @@ u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) | |||
| 162 | } | 149 | } |
| 163 | 150 | ||
| 164 | // 16-bit unsigned saturated subtraction | 151 | // 16-bit unsigned saturated subtraction |
| 165 | u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) | 152 | u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) { |
| 166 | { | ||
| 167 | if (left <= right) | 153 | if (left <= right) |
| 168 | return 0; | 154 | return 0; |
| 169 | 155 | ||
| @@ -171,16 +157,14 @@ u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) | |||
| 171 | } | 157 | } |
| 172 | 158 | ||
| 173 | // Signed saturation. | 159 | // Signed saturation. |
| 174 | u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred) | 160 | u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred) { |
| 175 | { | ||
| 176 | const u32 max = (1 << shift) - 1; | 161 | const u32 max = (1 << shift) - 1; |
| 177 | const s32 top = (value >> shift); | 162 | const s32 top = (value >> shift); |
| 178 | 163 | ||
| 179 | if (top > 0) { | 164 | if (top > 0) { |
| 180 | *saturation_occurred = true; | 165 | *saturation_occurred = true; |
| 181 | return max; | 166 | return max; |
| 182 | } | 167 | } else if (top < -1) { |
| 183 | else if (top < -1) { | ||
| 184 | *saturation_occurred = true; | 168 | *saturation_occurred = true; |
| 185 | return ~max; | 169 | return ~max; |
| 186 | } | 170 | } |
| @@ -190,8 +174,7 @@ u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred) | |||
| 190 | } | 174 | } |
| 191 | 175 | ||
| 192 | // Unsigned saturation | 176 | // Unsigned saturation |
| 193 | u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred) | 177 | u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred) { |
| 194 | { | ||
| 195 | const u32 max = (1 << shift) - 1; | 178 | const u32 max = (1 << shift) - 1; |
| 196 | 179 | ||
| 197 | if (value < 0) { | 180 | if (value < 0) { |
diff --git a/src/core/arm/skyeye_common/armsupp.h b/src/core/arm/skyeye_common/armsupp.h index 391309fa8..bf9299c07 100644 --- a/src/core/arm/skyeye_common/armsupp.h +++ b/src/core/arm/skyeye_common/armsupp.h | |||
| @@ -9,8 +9,8 @@ | |||
| 9 | #define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1)) | 9 | #define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1)) |
| 10 | #define BIT(s, n) ((s >> (n)) & 1) | 10 | #define BIT(s, n) ((s >> (n)) & 1) |
| 11 | 11 | ||
| 12 | #define POS(i) ( (~(i)) >> 31 ) | 12 | #define POS(i) ((~(i)) >> 31) |
| 13 | #define NEG(i) ( (i) >> 31 ) | 13 | #define NEG(i) ((i) >> 31) |
| 14 | 14 | ||
| 15 | bool AddOverflow(u32, u32, u32); | 15 | bool AddOverflow(u32, u32, u32); |
| 16 | bool SubOverflow(u32, u32, u32); | 16 | bool SubOverflow(u32, u32, u32); |
diff --git a/src/core/arm/skyeye_common/vfp/asm_vfp.h b/src/core/arm/skyeye_common/vfp/asm_vfp.h index 1187924f4..15b2394eb 100644 --- a/src/core/arm/skyeye_common/vfp/asm_vfp.h +++ b/src/core/arm/skyeye_common/vfp/asm_vfp.h | |||
| @@ -10,74 +10,74 @@ | |||
| 10 | // ARM11 MPCore FPSID Information | 10 | // ARM11 MPCore FPSID Information |
| 11 | // Note that these are used as values and not as flags. | 11 | // Note that these are used as values and not as flags. |
| 12 | enum : u32 { | 12 | enum : u32 { |
| 13 | VFP_FPSID_IMPLMEN = 0x41, // Implementation code. Should be the same as cp15 0 c0 0 | 13 | VFP_FPSID_IMPLMEN = 0x41, // Implementation code. Should be the same as cp15 0 c0 0 |
| 14 | VFP_FPSID_SW = 0, // Software emulation bit value | 14 | VFP_FPSID_SW = 0, // Software emulation bit value |
| 15 | VFP_FPSID_SUBARCH = 0x1, // Subarchitecture version number | 15 | VFP_FPSID_SUBARCH = 0x1, // Subarchitecture version number |
| 16 | VFP_FPSID_PARTNUM = 0x20, // Part number | 16 | VFP_FPSID_PARTNUM = 0x20, // Part number |
| 17 | VFP_FPSID_VARIANT = 0xB, // Variant number | 17 | VFP_FPSID_VARIANT = 0xB, // Variant number |
| 18 | VFP_FPSID_REVISION = 0x4 // Revision number | 18 | VFP_FPSID_REVISION = 0x4 // Revision number |
| 19 | }; | 19 | }; |
| 20 | 20 | ||
| 21 | // FPEXC bits | 21 | // FPEXC bits |
| 22 | enum : u32 { | 22 | enum : u32 { |
| 23 | FPEXC_EX = (1U << 31U), | 23 | FPEXC_EX = (1U << 31U), |
| 24 | FPEXC_EN = (1 << 30), | 24 | FPEXC_EN = (1 << 30), |
| 25 | FPEXC_DEX = (1 << 29), | 25 | FPEXC_DEX = (1 << 29), |
| 26 | FPEXC_FP2V = (1 << 28), | 26 | FPEXC_FP2V = (1 << 28), |
| 27 | FPEXC_VV = (1 << 27), | 27 | FPEXC_VV = (1 << 27), |
| 28 | FPEXC_TFV = (1 << 26), | 28 | FPEXC_TFV = (1 << 26), |
| 29 | FPEXC_LENGTH_BIT = (8), | 29 | FPEXC_LENGTH_BIT = (8), |
| 30 | FPEXC_LENGTH_MASK = (7 << FPEXC_LENGTH_BIT), | 30 | FPEXC_LENGTH_MASK = (7 << FPEXC_LENGTH_BIT), |
| 31 | FPEXC_IDF = (1 << 7), | 31 | FPEXC_IDF = (1 << 7), |
| 32 | FPEXC_IXF = (1 << 4), | 32 | FPEXC_IXF = (1 << 4), |
| 33 | FPEXC_UFF = (1 << 3), | 33 | FPEXC_UFF = (1 << 3), |
| 34 | FPEXC_OFF = (1 << 2), | 34 | FPEXC_OFF = (1 << 2), |
| 35 | FPEXC_DZF = (1 << 1), | 35 | FPEXC_DZF = (1 << 1), |
| 36 | FPEXC_IOF = (1 << 0), | 36 | FPEXC_IOF = (1 << 0), |
| 37 | FPEXC_TRAP_MASK = (FPEXC_IDF|FPEXC_IXF|FPEXC_UFF|FPEXC_OFF|FPEXC_DZF|FPEXC_IOF) | 37 | FPEXC_TRAP_MASK = (FPEXC_IDF | FPEXC_IXF | FPEXC_UFF | FPEXC_OFF | FPEXC_DZF | FPEXC_IOF) |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | // FPSCR Flags | 40 | // FPSCR Flags |
| 41 | enum : u32 { | 41 | enum : u32 { |
| 42 | FPSCR_NFLAG = (1U << 31U), // Negative condition flag | 42 | FPSCR_NFLAG = (1U << 31U), // Negative condition flag |
| 43 | FPSCR_ZFLAG = (1 << 30), // Zero condition flag | 43 | FPSCR_ZFLAG = (1 << 30), // Zero condition flag |
| 44 | FPSCR_CFLAG = (1 << 29), // Carry condition flag | 44 | FPSCR_CFLAG = (1 << 29), // Carry condition flag |
| 45 | FPSCR_VFLAG = (1 << 28), // Overflow condition flag | 45 | FPSCR_VFLAG = (1 << 28), // Overflow condition flag |
| 46 | 46 | ||
| 47 | FPSCR_QC = (1 << 27), // Cumulative saturation bit | 47 | FPSCR_QC = (1 << 27), // Cumulative saturation bit |
| 48 | FPSCR_AHP = (1 << 26), // Alternative half-precision control bit | 48 | FPSCR_AHP = (1 << 26), // Alternative half-precision control bit |
| 49 | FPSCR_DEFAULT_NAN = (1 << 25), // Default NaN mode control bit | 49 | FPSCR_DEFAULT_NAN = (1 << 25), // Default NaN mode control bit |
| 50 | FPSCR_FLUSH_TO_ZERO = (1 << 24), // Flush-to-zero mode control bit | 50 | FPSCR_FLUSH_TO_ZERO = (1 << 24), // Flush-to-zero mode control bit |
| 51 | FPSCR_RMODE_MASK = (3 << 22), // Rounding Mode bit mask | 51 | FPSCR_RMODE_MASK = (3 << 22), // Rounding Mode bit mask |
| 52 | FPSCR_STRIDE_MASK = (3 << 20), // Vector stride bit mask | 52 | FPSCR_STRIDE_MASK = (3 << 20), // Vector stride bit mask |
| 53 | FPSCR_LENGTH_MASK = (7 << 16), // Vector length bit mask | 53 | FPSCR_LENGTH_MASK = (7 << 16), // Vector length bit mask |
| 54 | 54 | ||
| 55 | FPSCR_IDE = (1 << 15), // Input Denormal exception trap enable. | 55 | FPSCR_IDE = (1 << 15), // Input Denormal exception trap enable. |
| 56 | FPSCR_IXE = (1 << 12), // Inexact exception trap enable | 56 | FPSCR_IXE = (1 << 12), // Inexact exception trap enable |
| 57 | FPSCR_UFE = (1 << 11), // Undeflow exception trap enable | 57 | FPSCR_UFE = (1 << 11), // Undeflow exception trap enable |
| 58 | FPSCR_OFE = (1 << 10), // Overflow exception trap enable | 58 | FPSCR_OFE = (1 << 10), // Overflow exception trap enable |
| 59 | FPSCR_DZE = (1 << 9), // Division by Zero exception trap enable | 59 | FPSCR_DZE = (1 << 9), // Division by Zero exception trap enable |
| 60 | FPSCR_IOE = (1 << 8), // Invalid Operation exception trap enable | 60 | FPSCR_IOE = (1 << 8), // Invalid Operation exception trap enable |
| 61 | 61 | ||
| 62 | FPSCR_IDC = (1 << 7), // Input Denormal cumulative exception bit | 62 | FPSCR_IDC = (1 << 7), // Input Denormal cumulative exception bit |
| 63 | FPSCR_IXC = (1 << 4), // Inexact cumulative exception bit | 63 | FPSCR_IXC = (1 << 4), // Inexact cumulative exception bit |
| 64 | FPSCR_UFC = (1 << 3), // Undeflow cumulative exception bit | 64 | FPSCR_UFC = (1 << 3), // Undeflow cumulative exception bit |
| 65 | FPSCR_OFC = (1 << 2), // Overflow cumulative exception bit | 65 | FPSCR_OFC = (1 << 2), // Overflow cumulative exception bit |
| 66 | FPSCR_DZC = (1 << 1), // Division by Zero cumulative exception bit | 66 | FPSCR_DZC = (1 << 1), // Division by Zero cumulative exception bit |
| 67 | FPSCR_IOC = (1 << 0), // Invalid Operation cumulative exception bit | 67 | FPSCR_IOC = (1 << 0), // Invalid Operation cumulative exception bit |
| 68 | }; | 68 | }; |
| 69 | 69 | ||
| 70 | // FPSCR bit offsets | 70 | // FPSCR bit offsets |
| 71 | enum : u32 { | 71 | enum : u32 { |
| 72 | FPSCR_RMODE_BIT = 22, | 72 | FPSCR_RMODE_BIT = 22, |
| 73 | FPSCR_STRIDE_BIT = 20, | 73 | FPSCR_STRIDE_BIT = 20, |
| 74 | FPSCR_LENGTH_BIT = 16, | 74 | FPSCR_LENGTH_BIT = 16, |
| 75 | }; | 75 | }; |
| 76 | 76 | ||
| 77 | // FPSCR rounding modes | 77 | // FPSCR rounding modes |
| 78 | enum : u32 { | 78 | enum : u32 { |
| 79 | FPSCR_ROUND_NEAREST = (0 << 22), | 79 | FPSCR_ROUND_NEAREST = (0 << 22), |
| 80 | FPSCR_ROUND_PLUSINF = (1 << 22), | 80 | FPSCR_ROUND_PLUSINF = (1 << 22), |
| 81 | FPSCR_ROUND_MINUSINF = (2 << 22), | 81 | FPSCR_ROUND_MINUSINF = (2 << 22), |
| 82 | FPSCR_ROUND_TOZERO = (3 << 22) | 82 | FPSCR_ROUND_TOZERO = (3 << 22) |
| 83 | }; | 83 | }; |
diff --git a/src/core/arm/skyeye_common/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp index a27a7e194..859937645 100644 --- a/src/core/arm/skyeye_common/vfp/vfp.cpp +++ b/src/core/arm/skyeye_common/vfp/vfp.cpp | |||
| @@ -28,15 +28,14 @@ | |||
| 28 | #include "core/arm/skyeye_common/vfp/asm_vfp.h" | 28 | #include "core/arm/skyeye_common/vfp/asm_vfp.h" |
| 29 | #include "core/arm/skyeye_common/vfp/vfp.h" | 29 | #include "core/arm/skyeye_common/vfp/vfp.h" |
| 30 | 30 | ||
| 31 | void VFPInit(ARMul_State* state) | 31 | void VFPInit(ARMul_State* state) { |
| 32 | { | 32 | state->VFP[VFP_FPSID] = VFP_FPSID_IMPLMEN << 24 | VFP_FPSID_SW << 23 | VFP_FPSID_SUBARCH << 16 | |
| 33 | state->VFP[VFP_FPSID] = VFP_FPSID_IMPLMEN<<24 | VFP_FPSID_SW<<23 | VFP_FPSID_SUBARCH<<16 | | 33 | VFP_FPSID_PARTNUM << 8 | VFP_FPSID_VARIANT << 4 | VFP_FPSID_REVISION; |
| 34 | VFP_FPSID_PARTNUM<<8 | VFP_FPSID_VARIANT<<4 | VFP_FPSID_REVISION; | ||
| 35 | state->VFP[VFP_FPEXC] = 0; | 34 | state->VFP[VFP_FPEXC] = 0; |
| 36 | state->VFP[VFP_FPSCR] = 0; | 35 | state->VFP[VFP_FPSCR] = 0; |
| 37 | 36 | ||
| 38 | // ARM11 MPCore instruction register reset values. | 37 | // ARM11 MPCore instruction register reset values. |
| 39 | state->VFP[VFP_FPINST] = 0xEE000A00; | 38 | state->VFP[VFP_FPINST] = 0xEE000A00; |
| 40 | state->VFP[VFP_FPINST2] = 0; | 39 | state->VFP[VFP_FPINST2] = 0; |
| 41 | 40 | ||
| 42 | // ARM11 MPCore feature register values. | 41 | // ARM11 MPCore feature register values. |
| @@ -44,104 +43,80 @@ void VFPInit(ARMul_State* state) | |||
| 44 | state->VFP[VFP_MVFR1] = 0; | 43 | state->VFP[VFP_MVFR1] = 0; |
| 45 | } | 44 | } |
| 46 | 45 | ||
| 47 | void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value) | 46 | void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value) { |
| 48 | { | 47 | if (to_arm) { |
| 49 | if (to_arm) | ||
| 50 | { | ||
| 51 | *value = state->ExtReg[n]; | 48 | *value = state->ExtReg[n]; |
| 52 | } | 49 | } else { |
| 53 | else | ||
| 54 | { | ||
| 55 | state->ExtReg[n] = *value; | 50 | state->ExtReg[n] = *value; |
| 56 | } | 51 | } |
| 57 | } | 52 | } |
| 58 | 53 | ||
| 59 | void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) | 54 | void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) { |
| 60 | { | 55 | if (to_arm) { |
| 61 | if (to_arm) | 56 | *value2 = state->ExtReg[n * 2 + 1]; |
| 62 | { | 57 | *value1 = state->ExtReg[n * 2]; |
| 63 | *value2 = state->ExtReg[n*2+1]; | 58 | } else { |
| 64 | *value1 = state->ExtReg[n*2]; | 59 | state->ExtReg[n * 2 + 1] = *value2; |
| 65 | } | 60 | state->ExtReg[n * 2] = *value1; |
| 66 | else | ||
| 67 | { | ||
| 68 | state->ExtReg[n*2+1] = *value2; | ||
| 69 | state->ExtReg[n*2] = *value1; | ||
| 70 | } | 61 | } |
| 71 | } | 62 | } |
| 72 | void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) | 63 | void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) { |
| 73 | { | 64 | if (to_arm) { |
| 74 | if (to_arm) | 65 | *value1 = state->ExtReg[n + 0]; |
| 75 | { | 66 | *value2 = state->ExtReg[n + 1]; |
| 76 | *value1 = state->ExtReg[n+0]; | 67 | } else { |
| 77 | *value2 = state->ExtReg[n+1]; | 68 | state->ExtReg[n + 0] = *value1; |
| 78 | } | 69 | state->ExtReg[n + 1] = *value2; |
| 79 | else | ||
| 80 | { | ||
| 81 | state->ExtReg[n+0] = *value1; | ||
| 82 | state->ExtReg[n+1] = *value2; | ||
| 83 | } | 70 | } |
| 84 | } | 71 | } |
| 85 | 72 | ||
| 86 | void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm) | 73 | void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm) { |
| 87 | { | 74 | if (single) { |
| 88 | if (single) | ||
| 89 | { | ||
| 90 | state->ExtReg[d] = imm; | 75 | state->ExtReg[d] = imm; |
| 91 | } | 76 | } else { |
| 92 | else | ||
| 93 | { | ||
| 94 | /* Check endian please */ | 77 | /* Check endian please */ |
| 95 | state->ExtReg[d*2+1] = imm; | 78 | state->ExtReg[d * 2 + 1] = imm; |
| 96 | state->ExtReg[d*2] = 0; | 79 | state->ExtReg[d * 2] = 0; |
| 97 | } | 80 | } |
| 98 | } | 81 | } |
| 99 | void VMOVR(ARMul_State* state, u32 single, u32 d, u32 m) | 82 | void VMOVR(ARMul_State* state, u32 single, u32 d, u32 m) { |
| 100 | { | 83 | if (single) { |
| 101 | if (single) | ||
| 102 | { | ||
| 103 | state->ExtReg[d] = state->ExtReg[m]; | 84 | state->ExtReg[d] = state->ExtReg[m]; |
| 104 | } | 85 | } else { |
| 105 | else | ||
| 106 | { | ||
| 107 | /* Check endian please */ | 86 | /* Check endian please */ |
| 108 | state->ExtReg[d*2+1] = state->ExtReg[m*2+1]; | 87 | state->ExtReg[d * 2 + 1] = state->ExtReg[m * 2 + 1]; |
| 109 | state->ExtReg[d*2] = state->ExtReg[m*2]; | 88 | state->ExtReg[d * 2] = state->ExtReg[m * 2]; |
| 110 | } | 89 | } |
| 111 | } | 90 | } |
| 112 | 91 | ||
| 113 | /* Miscellaneous functions */ | 92 | /* Miscellaneous functions */ |
| 114 | s32 vfp_get_float(ARMul_State* state, unsigned int reg) | 93 | s32 vfp_get_float(ARMul_State* state, unsigned int reg) { |
| 115 | { | ||
| 116 | LOG_TRACE(Core_ARM11, "VFP get float: s%d=[%08x]", reg, state->ExtReg[reg]); | 94 | LOG_TRACE(Core_ARM11, "VFP get float: s%d=[%08x]", reg, state->ExtReg[reg]); |
| 117 | return state->ExtReg[reg]; | 95 | return state->ExtReg[reg]; |
| 118 | } | 96 | } |
| 119 | 97 | ||
| 120 | void vfp_put_float(ARMul_State* state, s32 val, unsigned int reg) | 98 | void vfp_put_float(ARMul_State* state, s32 val, unsigned int reg) { |
| 121 | { | ||
| 122 | LOG_TRACE(Core_ARM11, "VFP put float: s%d <= [%08x]", reg, val); | 99 | LOG_TRACE(Core_ARM11, "VFP put float: s%d <= [%08x]", reg, val); |
| 123 | state->ExtReg[reg] = val; | 100 | state->ExtReg[reg] = val; |
| 124 | } | 101 | } |
| 125 | 102 | ||
| 126 | u64 vfp_get_double(ARMul_State* state, unsigned int reg) | 103 | u64 vfp_get_double(ARMul_State* state, unsigned int reg) { |
| 127 | { | 104 | u64 result = ((u64)state->ExtReg[reg * 2 + 1]) << 32 | state->ExtReg[reg * 2]; |
| 128 | u64 result = ((u64) state->ExtReg[reg*2+1])<<32 | state->ExtReg[reg*2]; | ||
| 129 | LOG_TRACE(Core_ARM11, "VFP get double: s[%d-%d]=[%016llx]", reg * 2 + 1, reg * 2, result); | 105 | LOG_TRACE(Core_ARM11, "VFP get double: s[%d-%d]=[%016llx]", reg * 2 + 1, reg * 2, result); |
| 130 | return result; | 106 | return result; |
| 131 | } | 107 | } |
| 132 | 108 | ||
| 133 | void vfp_put_double(ARMul_State* state, u64 val, unsigned int reg) | 109 | void vfp_put_double(ARMul_State* state, u64 val, unsigned int reg) { |
| 134 | { | 110 | LOG_TRACE(Core_ARM11, "VFP put double: s[%d-%d] <= [%08x-%08x]", reg * 2 + 1, reg * 2, |
| 135 | LOG_TRACE(Core_ARM11, "VFP put double: s[%d-%d] <= [%08x-%08x]", reg * 2 + 1, reg * 2, (u32)(val >> 32), (u32)(val & 0xffffffff)); | 111 | (u32)(val >> 32), (u32)(val & 0xffffffff)); |
| 136 | state->ExtReg[reg*2] = (u32) (val & 0xffffffff); | 112 | state->ExtReg[reg * 2] = (u32)(val & 0xffffffff); |
| 137 | state->ExtReg[reg*2+1] = (u32) (val>>32); | 113 | state->ExtReg[reg * 2 + 1] = (u32)(val >> 32); |
| 138 | } | 114 | } |
| 139 | 115 | ||
| 140 | /* | 116 | /* |
| 141 | * Process bitmask of exception conditions. (from vfpmodule.c) | 117 | * Process bitmask of exception conditions. (from vfpmodule.c) |
| 142 | */ | 118 | */ |
| 143 | void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr) | 119 | void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr) { |
| 144 | { | ||
| 145 | LOG_TRACE(Core_ARM11, "VFP: raising exceptions %08x", exceptions); | 120 | LOG_TRACE(Core_ARM11, "VFP: raising exceptions %08x", exceptions); |
| 146 | 121 | ||
| 147 | if (exceptions == VFP_EXCEPTION_ERROR) { | 122 | if (exceptions == VFP_EXCEPTION_ERROR) { |
| @@ -154,8 +129,8 @@ void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpsc | |||
| 154 | * Comparison instructions always return at least one of | 129 | * Comparison instructions always return at least one of |
| 155 | * these flags set. | 130 | * these flags set. |
| 156 | */ | 131 | */ |
| 157 | if (exceptions & (FPSCR_NFLAG|FPSCR_ZFLAG|FPSCR_CFLAG|FPSCR_VFLAG)) | 132 | if (exceptions & (FPSCR_NFLAG | FPSCR_ZFLAG | FPSCR_CFLAG | FPSCR_VFLAG)) |
| 158 | fpscr &= ~(FPSCR_NFLAG|FPSCR_ZFLAG|FPSCR_CFLAG|FPSCR_VFLAG); | 133 | fpscr &= ~(FPSCR_NFLAG | FPSCR_ZFLAG | FPSCR_CFLAG | FPSCR_VFLAG); |
| 159 | 134 | ||
| 160 | fpscr |= exceptions; | 135 | fpscr |= exceptions; |
| 161 | 136 | ||
diff --git a/src/core/arm/skyeye_common/vfp/vfp_helper.h b/src/core/arm/skyeye_common/vfp/vfp_helper.h index 68714800c..5e14345ce 100644 --- a/src/core/arm/skyeye_common/vfp/vfp_helper.h +++ b/src/core/arm/skyeye_common/vfp/vfp_helper.h | |||
| @@ -37,56 +37,56 @@ | |||
| 37 | #include "core/arm/skyeye_common/armstate.h" | 37 | #include "core/arm/skyeye_common/armstate.h" |
| 38 | #include "core/arm/skyeye_common/vfp/asm_vfp.h" | 38 | #include "core/arm/skyeye_common/vfp/asm_vfp.h" |
| 39 | 39 | ||
| 40 | #define do_div(n, base) {n/=base;} | 40 | #define do_div(n, base) \ |
| 41 | { n /= base; } | ||
| 41 | 42 | ||
| 42 | enum : u32 { | 43 | enum : u32 { |
| 43 | FOP_MASK = 0x00b00040, | 44 | FOP_MASK = 0x00b00040, |
| 44 | FOP_FMAC = 0x00000000, | 45 | FOP_FMAC = 0x00000000, |
| 45 | FOP_FNMAC = 0x00000040, | 46 | FOP_FNMAC = 0x00000040, |
| 46 | FOP_FMSC = 0x00100000, | 47 | FOP_FMSC = 0x00100000, |
| 47 | FOP_FNMSC = 0x00100040, | 48 | FOP_FNMSC = 0x00100040, |
| 48 | FOP_FMUL = 0x00200000, | 49 | FOP_FMUL = 0x00200000, |
| 49 | FOP_FNMUL = 0x00200040, | 50 | FOP_FNMUL = 0x00200040, |
| 50 | FOP_FADD = 0x00300000, | 51 | FOP_FADD = 0x00300000, |
| 51 | FOP_FSUB = 0x00300040, | 52 | FOP_FSUB = 0x00300040, |
| 52 | FOP_FDIV = 0x00800000, | 53 | FOP_FDIV = 0x00800000, |
| 53 | FOP_EXT = 0x00b00040 | 54 | FOP_EXT = 0x00b00040 |
| 54 | }; | 55 | }; |
| 55 | 56 | ||
| 56 | #define FOP_TO_IDX(inst) ((inst & 0x00b00000) >> 20 | (inst & (1 << 6)) >> 4) | 57 | #define FOP_TO_IDX(inst) ((inst & 0x00b00000) >> 20 | (inst & (1 << 6)) >> 4) |
| 57 | 58 | ||
| 58 | enum : u32 { | 59 | enum : u32 { |
| 59 | FEXT_MASK = 0x000f0080, | 60 | FEXT_MASK = 0x000f0080, |
| 60 | FEXT_FCPY = 0x00000000, | 61 | FEXT_FCPY = 0x00000000, |
| 61 | FEXT_FABS = 0x00000080, | 62 | FEXT_FABS = 0x00000080, |
| 62 | FEXT_FNEG = 0x00010000, | 63 | FEXT_FNEG = 0x00010000, |
| 63 | FEXT_FSQRT = 0x00010080, | 64 | FEXT_FSQRT = 0x00010080, |
| 64 | FEXT_FCMP = 0x00040000, | 65 | FEXT_FCMP = 0x00040000, |
| 65 | FEXT_FCMPE = 0x00040080, | 66 | FEXT_FCMPE = 0x00040080, |
| 66 | FEXT_FCMPZ = 0x00050000, | 67 | FEXT_FCMPZ = 0x00050000, |
| 67 | FEXT_FCMPEZ = 0x00050080, | 68 | FEXT_FCMPEZ = 0x00050080, |
| 68 | FEXT_FCVT = 0x00070080, | 69 | FEXT_FCVT = 0x00070080, |
| 69 | FEXT_FUITO = 0x00080000, | 70 | FEXT_FUITO = 0x00080000, |
| 70 | FEXT_FSITO = 0x00080080, | 71 | FEXT_FSITO = 0x00080080, |
| 71 | FEXT_FTOUI = 0x000c0000, | 72 | FEXT_FTOUI = 0x000c0000, |
| 72 | FEXT_FTOUIZ = 0x000c0080, | 73 | FEXT_FTOUIZ = 0x000c0080, |
| 73 | FEXT_FTOSI = 0x000d0000, | 74 | FEXT_FTOSI = 0x000d0000, |
| 74 | FEXT_FTOSIZ = 0x000d0080 | 75 | FEXT_FTOSIZ = 0x000d0080 |
| 75 | }; | 76 | }; |
| 76 | 77 | ||
| 77 | #define FEXT_TO_IDX(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7) | 78 | #define FEXT_TO_IDX(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7) |
| 78 | 79 | ||
| 79 | #define vfp_get_sd(inst) ((inst & 0x0000f000) >> 11 | (inst & (1 << 22)) >> 22) | 80 | #define vfp_get_sd(inst) ((inst & 0x0000f000) >> 11 | (inst & (1 << 22)) >> 22) |
| 80 | #define vfp_get_dd(inst) ((inst & 0x0000f000) >> 12 | (inst & (1 << 22)) >> 18) | 81 | #define vfp_get_dd(inst) ((inst & 0x0000f000) >> 12 | (inst & (1 << 22)) >> 18) |
| 81 | #define vfp_get_sm(inst) ((inst & 0x0000000f) << 1 | (inst & (1 << 5)) >> 5) | 82 | #define vfp_get_sm(inst) ((inst & 0x0000000f) << 1 | (inst & (1 << 5)) >> 5) |
| 82 | #define vfp_get_dm(inst) ((inst & 0x0000000f) | (inst & (1 << 5)) >> 1) | 83 | #define vfp_get_dm(inst) ((inst & 0x0000000f) | (inst & (1 << 5)) >> 1) |
| 83 | #define vfp_get_sn(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7) | 84 | #define vfp_get_sn(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7) |
| 84 | #define vfp_get_dn(inst) ((inst & 0x000f0000) >> 16 | (inst & (1 << 7)) >> 3) | 85 | #define vfp_get_dn(inst) ((inst & 0x000f0000) >> 16 | (inst & (1 << 7)) >> 3) |
| 85 | 86 | ||
| 86 | #define vfp_single(inst) (((inst) & 0x0000f00) == 0xa00) | 87 | #define vfp_single(inst) (((inst)&0x0000f00) == 0xa00) |
| 87 | 88 | ||
| 88 | inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift) | 89 | inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift) { |
| 89 | { | ||
| 90 | if (shift) { | 90 | if (shift) { |
| 91 | if (shift < 32) | 91 | if (shift < 32) |
| 92 | val = val >> shift | ((val << (32 - shift)) != 0); | 92 | val = val >> shift | ((val << (32 - shift)) != 0); |
| @@ -96,8 +96,7 @@ inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift) | |||
| 96 | return val; | 96 | return val; |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift) | 99 | inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift) { |
| 100 | { | ||
| 101 | if (shift) { | 100 | if (shift) { |
| 102 | if (shift < 64) | 101 | if (shift < 64) |
| 103 | val = val >> shift | ((val << (64 - shift)) != 0); | 102 | val = val >> shift | ((val << (64 - shift)) != 0); |
| @@ -107,8 +106,7 @@ inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift) | |||
| 107 | return val; | 106 | return val; |
| 108 | } | 107 | } |
| 109 | 108 | ||
| 110 | inline u32 vfp_hi64to32jamming(u64 val) | 109 | inline u32 vfp_hi64to32jamming(u64 val) { |
| 111 | { | ||
| 112 | u32 v; | 110 | u32 v; |
| 113 | u32 highval = val >> 32; | 111 | u32 highval = val >> 32; |
| 114 | u32 lowval = val & 0xffffffff; | 112 | u32 lowval = val & 0xffffffff; |
| @@ -121,24 +119,21 @@ inline u32 vfp_hi64to32jamming(u64 val) | |||
| 121 | return v; | 119 | return v; |
| 122 | } | 120 | } |
| 123 | 121 | ||
| 124 | inline void add128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml) | 122 | inline void add128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml) { |
| 125 | { | ||
| 126 | *resl = nl + ml; | 123 | *resl = nl + ml; |
| 127 | *resh = nh + mh; | 124 | *resh = nh + mh; |
| 128 | if (*resl < nl) | 125 | if (*resl < nl) |
| 129 | *resh += 1; | 126 | *resh += 1; |
| 130 | } | 127 | } |
| 131 | 128 | ||
| 132 | inline void sub128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml) | 129 | inline void sub128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml) { |
| 133 | { | ||
| 134 | *resl = nl - ml; | 130 | *resl = nl - ml; |
| 135 | *resh = nh - mh; | 131 | *resh = nh - mh; |
| 136 | if (*resl > nl) | 132 | if (*resl > nl) |
| 137 | *resh -= 1; | 133 | *resh -= 1; |
| 138 | } | 134 | } |
| 139 | 135 | ||
| 140 | inline void mul64to128(u64* resh, u64* resl, u64 n, u64 m) | 136 | inline void mul64to128(u64* resh, u64* resl, u64 n, u64 m) { |
| 141 | { | ||
| 142 | u32 nh, nl, mh, ml; | 137 | u32 nh, nl, mh, ml; |
| 143 | u64 rh, rma, rmb, rl; | 138 | u64 rh, rma, rmb, rl; |
| 144 | 139 | ||
| @@ -164,21 +159,18 @@ inline void mul64to128(u64* resh, u64* resl, u64 n, u64 m) | |||
| 164 | *resh = rh; | 159 | *resh = rh; |
| 165 | } | 160 | } |
| 166 | 161 | ||
| 167 | inline void shift64left(u64* resh, u64* resl, u64 n) | 162 | inline void shift64left(u64* resh, u64* resl, u64 n) { |
| 168 | { | ||
| 169 | *resh = n >> 63; | 163 | *resh = n >> 63; |
| 170 | *resl = n << 1; | 164 | *resl = n << 1; |
| 171 | } | 165 | } |
| 172 | 166 | ||
| 173 | inline u64 vfp_hi64multiply64(u64 n, u64 m) | 167 | inline u64 vfp_hi64multiply64(u64 n, u64 m) { |
| 174 | { | ||
| 175 | u64 rh, rl; | 168 | u64 rh, rl; |
| 176 | mul64to128(&rh, &rl, n, m); | 169 | mul64to128(&rh, &rl, n, m); |
| 177 | return rh | (rl != 0); | 170 | return rh | (rl != 0); |
| 178 | } | 171 | } |
| 179 | 172 | ||
| 180 | inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m) | 173 | inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m) { |
| 181 | { | ||
| 182 | u64 mh, ml, remh, reml, termh, terml, z; | 174 | u64 mh, ml, remh, reml, termh, terml, z; |
| 183 | 175 | ||
| 184 | if (nh >= m) | 176 | if (nh >= m) |
| @@ -213,9 +205,9 @@ inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m) | |||
| 213 | 205 | ||
| 214 | // Single-precision | 206 | // Single-precision |
| 215 | struct vfp_single { | 207 | struct vfp_single { |
| 216 | s16 exponent; | 208 | s16 exponent; |
| 217 | u16 sign; | 209 | u16 sign; |
| 218 | u32 significand; | 210 | u32 significand; |
| 219 | }; | 211 | }; |
| 220 | 212 | ||
| 221 | // VFP_SINGLE_MANTISSA_BITS - number of bits in the mantissa | 213 | // VFP_SINGLE_MANTISSA_BITS - number of bits in the mantissa |
| @@ -224,33 +216,33 @@ struct vfp_single { | |||
| 224 | // which are not propagated to the float upon packing. | 216 | // which are not propagated to the float upon packing. |
| 225 | #define VFP_SINGLE_MANTISSA_BITS (23) | 217 | #define VFP_SINGLE_MANTISSA_BITS (23) |
| 226 | #define VFP_SINGLE_EXPONENT_BITS (8) | 218 | #define VFP_SINGLE_EXPONENT_BITS (8) |
| 227 | #define VFP_SINGLE_LOW_BITS (32 - VFP_SINGLE_MANTISSA_BITS - 2) | 219 | #define VFP_SINGLE_LOW_BITS (32 - VFP_SINGLE_MANTISSA_BITS - 2) |
| 228 | #define VFP_SINGLE_LOW_BITS_MASK ((1 << VFP_SINGLE_LOW_BITS) - 1) | 220 | #define VFP_SINGLE_LOW_BITS_MASK ((1 << VFP_SINGLE_LOW_BITS) - 1) |
| 229 | 221 | ||
| 230 | // The bit in an unpacked float which indicates that it is a quiet NaN | 222 | // The bit in an unpacked float which indicates that it is a quiet NaN |
| 231 | #define VFP_SINGLE_SIGNIFICAND_QNAN (1 << (VFP_SINGLE_MANTISSA_BITS - 1 + VFP_SINGLE_LOW_BITS)) | 223 | #define VFP_SINGLE_SIGNIFICAND_QNAN (1 << (VFP_SINGLE_MANTISSA_BITS - 1 + VFP_SINGLE_LOW_BITS)) |
| 232 | 224 | ||
| 233 | // Operations on packed single-precision numbers | 225 | // Operations on packed single-precision numbers |
| 234 | #define vfp_single_packed_sign(v) ((v) & 0x80000000) | 226 | #define vfp_single_packed_sign(v) ((v)&0x80000000) |
| 235 | #define vfp_single_packed_negate(v) ((v) ^ 0x80000000) | 227 | #define vfp_single_packed_negate(v) ((v) ^ 0x80000000) |
| 236 | #define vfp_single_packed_abs(v) ((v) & ~0x80000000) | 228 | #define vfp_single_packed_abs(v) ((v) & ~0x80000000) |
| 237 | #define vfp_single_packed_exponent(v) (((v) >> VFP_SINGLE_MANTISSA_BITS) & ((1 << VFP_SINGLE_EXPONENT_BITS) - 1)) | 229 | #define vfp_single_packed_exponent(v) \ |
| 230 | (((v) >> VFP_SINGLE_MANTISSA_BITS) & ((1 << VFP_SINGLE_EXPONENT_BITS) - 1)) | ||
| 238 | #define vfp_single_packed_mantissa(v) ((v) & ((1 << VFP_SINGLE_MANTISSA_BITS) - 1)) | 231 | #define vfp_single_packed_mantissa(v) ((v) & ((1 << VFP_SINGLE_MANTISSA_BITS) - 1)) |
| 239 | 232 | ||
| 240 | enum : u32 { | 233 | enum : u32 { |
| 241 | VFP_NUMBER = (1 << 0), | 234 | VFP_NUMBER = (1 << 0), |
| 242 | VFP_ZERO = (1 << 1), | 235 | VFP_ZERO = (1 << 1), |
| 243 | VFP_DENORMAL = (1 << 2), | 236 | VFP_DENORMAL = (1 << 2), |
| 244 | VFP_INFINITY = (1 << 3), | 237 | VFP_INFINITY = (1 << 3), |
| 245 | VFP_NAN = (1 << 4), | 238 | VFP_NAN = (1 << 4), |
| 246 | VFP_NAN_SIGNAL = (1 << 5), | 239 | VFP_NAN_SIGNAL = (1 << 5), |
| 247 | 240 | ||
| 248 | VFP_QNAN = (VFP_NAN), | 241 | VFP_QNAN = (VFP_NAN), |
| 249 | VFP_SNAN = (VFP_NAN|VFP_NAN_SIGNAL) | 242 | VFP_SNAN = (VFP_NAN | VFP_NAN_SIGNAL) |
| 250 | }; | 243 | }; |
| 251 | 244 | ||
| 252 | inline int vfp_single_type(const vfp_single* s) | 245 | inline int vfp_single_type(const vfp_single* s) { |
| 253 | { | ||
| 254 | int type = VFP_NUMBER; | 246 | int type = VFP_NUMBER; |
| 255 | if (s->exponent == 255) { | 247 | if (s->exponent == 255) { |
| 256 | if (s->significand == 0) | 248 | if (s->significand == 0) |
| @@ -271,11 +263,9 @@ inline int vfp_single_type(const vfp_single* s) | |||
| 271 | // Unpack a single-precision float. Note that this returns the magnitude | 263 | // Unpack a single-precision float. Note that this returns the magnitude |
| 272 | // of the single-precision float mantissa with the 1. if necessary, | 264 | // of the single-precision float mantissa with the 1. if necessary, |
| 273 | // aligned to bit 30. | 265 | // aligned to bit 30. |
| 274 | inline u32 vfp_single_unpack(vfp_single* s, s32 val, u32 fpscr) | 266 | inline u32 vfp_single_unpack(vfp_single* s, s32 val, u32 fpscr) { |
| 275 | { | ||
| 276 | u32 exceptions = 0; | 267 | u32 exceptions = 0; |
| 277 | s->sign = vfp_single_packed_sign(val) >> 16, | 268 | s->sign = vfp_single_packed_sign(val) >> 16, s->exponent = vfp_single_packed_exponent(val); |
| 278 | s->exponent = vfp_single_packed_exponent(val); | ||
| 279 | 269 | ||
| 280 | u32 significand = ((u32)val << (32 - VFP_SINGLE_MANTISSA_BITS)) >> 2; | 270 | u32 significand = ((u32)val << (32 - VFP_SINGLE_MANTISSA_BITS)) >> 2; |
| 281 | if (s->exponent && s->exponent != 255) | 271 | if (s->exponent && s->exponent != 255) |
| @@ -295,22 +285,20 @@ inline u32 vfp_single_unpack(vfp_single* s, s32 val, u32 fpscr) | |||
| 295 | 285 | ||
| 296 | // Re-pack a single-precision float. This assumes that the float is | 286 | // Re-pack a single-precision float. This assumes that the float is |
| 297 | // already normalised such that the MSB is bit 30, _not_ bit 31. | 287 | // already normalised such that the MSB is bit 30, _not_ bit 31. |
| 298 | inline s32 vfp_single_pack(const vfp_single* s) | 288 | inline s32 vfp_single_pack(const vfp_single* s) { |
| 299 | { | 289 | u32 val = (s->sign << 16) + (s->exponent << VFP_SINGLE_MANTISSA_BITS) + |
| 300 | u32 val = (s->sign << 16) + | ||
| 301 | (s->exponent << VFP_SINGLE_MANTISSA_BITS) + | ||
| 302 | (s->significand >> VFP_SINGLE_LOW_BITS); | 290 | (s->significand >> VFP_SINGLE_LOW_BITS); |
| 303 | return (s32)val; | 291 | return (s32)val; |
| 304 | } | 292 | } |
| 305 | 293 | ||
| 306 | 294 | u32 vfp_single_normaliseround(ARMul_State* state, int sd, vfp_single* vs, u32 fpscr, | |
| 307 | u32 vfp_single_normaliseround(ARMul_State* state, int sd, vfp_single* vs, u32 fpscr, const char* func); | 295 | const char* func); |
| 308 | 296 | ||
| 309 | // Double-precision | 297 | // Double-precision |
| 310 | struct vfp_double { | 298 | struct vfp_double { |
| 311 | s16 exponent; | 299 | s16 exponent; |
| 312 | u16 sign; | 300 | u16 sign; |
| 313 | u64 significand; | 301 | u64 significand; |
| 314 | }; | 302 | }; |
| 315 | 303 | ||
| 316 | // VFP_REG_ZERO is a special register number for vfp_get_double | 304 | // VFP_REG_ZERO is a special register number for vfp_get_double |
| @@ -324,21 +312,21 @@ struct vfp_double { | |||
| 324 | 312 | ||
| 325 | #define VFP_DOUBLE_MANTISSA_BITS (52) | 313 | #define VFP_DOUBLE_MANTISSA_BITS (52) |
| 326 | #define VFP_DOUBLE_EXPONENT_BITS (11) | 314 | #define VFP_DOUBLE_EXPONENT_BITS (11) |
| 327 | #define VFP_DOUBLE_LOW_BITS (64 - VFP_DOUBLE_MANTISSA_BITS - 2) | 315 | #define VFP_DOUBLE_LOW_BITS (64 - VFP_DOUBLE_MANTISSA_BITS - 2) |
| 328 | #define VFP_DOUBLE_LOW_BITS_MASK ((1 << VFP_DOUBLE_LOW_BITS) - 1) | 316 | #define VFP_DOUBLE_LOW_BITS_MASK ((1 << VFP_DOUBLE_LOW_BITS) - 1) |
| 329 | 317 | ||
| 330 | // The bit in an unpacked double which indicates that it is a quiet NaN | 318 | // The bit in an unpacked double which indicates that it is a quiet NaN |
| 331 | #define VFP_DOUBLE_SIGNIFICAND_QNAN (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1 + VFP_DOUBLE_LOW_BITS)) | 319 | #define VFP_DOUBLE_SIGNIFICAND_QNAN (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1 + VFP_DOUBLE_LOW_BITS)) |
| 332 | 320 | ||
| 333 | // Operations on packed single-precision numbers | 321 | // Operations on packed single-precision numbers |
| 334 | #define vfp_double_packed_sign(v) ((v) & (1ULL << 63)) | 322 | #define vfp_double_packed_sign(v) ((v) & (1ULL << 63)) |
| 335 | #define vfp_double_packed_negate(v) ((v) ^ (1ULL << 63)) | 323 | #define vfp_double_packed_negate(v) ((v) ^ (1ULL << 63)) |
| 336 | #define vfp_double_packed_abs(v) ((v) & ~(1ULL << 63)) | 324 | #define vfp_double_packed_abs(v) ((v) & ~(1ULL << 63)) |
| 337 | #define vfp_double_packed_exponent(v) (((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1)) | 325 | #define vfp_double_packed_exponent(v) \ |
| 326 | (((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1)) | ||
| 338 | #define vfp_double_packed_mantissa(v) ((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1)) | 327 | #define vfp_double_packed_mantissa(v) ((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1)) |
| 339 | 328 | ||
| 340 | inline int vfp_double_type(const vfp_double* s) | 329 | inline int vfp_double_type(const vfp_double* s) { |
| 341 | { | ||
| 342 | int type = VFP_NUMBER; | 330 | int type = VFP_NUMBER; |
| 343 | if (s->exponent == 2047) { | 331 | if (s->exponent == 2047) { |
| 344 | if (s->significand == 0) | 332 | if (s->significand == 0) |
| @@ -359,8 +347,7 @@ inline int vfp_double_type(const vfp_double* s) | |||
| 359 | // Unpack a double-precision float. Note that this returns the magnitude | 347 | // Unpack a double-precision float. Note that this returns the magnitude |
| 360 | // of the double-precision float mantissa with the 1. if necessary, | 348 | // of the double-precision float mantissa with the 1. if necessary, |
| 361 | // aligned to bit 62. | 349 | // aligned to bit 62. |
| 362 | inline u32 vfp_double_unpack(vfp_double* s, s64 val, u32 fpscr) | 350 | inline u32 vfp_double_unpack(vfp_double* s, s64 val, u32 fpscr) { |
| 363 | { | ||
| 364 | u32 exceptions = 0; | 351 | u32 exceptions = 0; |
| 365 | s->sign = vfp_double_packed_sign(val) >> 48; | 352 | s->sign = vfp_double_packed_sign(val) >> 48; |
| 366 | s->exponent = vfp_double_packed_exponent(val); | 353 | s->exponent = vfp_double_packed_exponent(val); |
| @@ -383,10 +370,8 @@ inline u32 vfp_double_unpack(vfp_double* s, s64 val, u32 fpscr) | |||
| 383 | 370 | ||
| 384 | // Re-pack a double-precision float. This assumes that the float is | 371 | // Re-pack a double-precision float. This assumes that the float is |
| 385 | // already normalised such that the MSB is bit 30, _not_ bit 31. | 372 | // already normalised such that the MSB is bit 30, _not_ bit 31. |
| 386 | inline s64 vfp_double_pack(const vfp_double* s) | 373 | inline s64 vfp_double_pack(const vfp_double* s) { |
| 387 | { | 374 | u64 val = ((u64)s->sign << 48) + ((u64)s->exponent << VFP_DOUBLE_MANTISSA_BITS) + |
| 388 | u64 val = ((u64)s->sign << 48) + | ||
| 389 | ((u64)s->exponent << VFP_DOUBLE_MANTISSA_BITS) + | ||
| 390 | (s->significand >> VFP_DOUBLE_LOW_BITS); | 375 | (s->significand >> VFP_DOUBLE_LOW_BITS); |
| 391 | return (s64)val; | 376 | return (s64)val; |
| 392 | } | 377 | } |
| @@ -407,20 +392,14 @@ u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand); | |||
| 407 | // OP_SD - The instruction exceptionally writes to a single precision result. | 392 | // OP_SD - The instruction exceptionally writes to a single precision result. |
| 408 | // OP_DD - The instruction exceptionally writes to a double precision result. | 393 | // OP_DD - The instruction exceptionally writes to a double precision result. |
| 409 | // OP_SM - The instruction exceptionally reads from a single precision operand. | 394 | // OP_SM - The instruction exceptionally reads from a single precision operand. |
| 410 | enum : u32 { | 395 | enum : u32 { OP_SCALAR = (1 << 0), OP_SD = (1 << 1), OP_DD = (1 << 1), OP_SM = (1 << 2) }; |
| 411 | OP_SCALAR = (1 << 0), | ||
| 412 | OP_SD = (1 << 1), | ||
| 413 | OP_DD = (1 << 1), | ||
| 414 | OP_SM = (1 << 2) | ||
| 415 | }; | ||
| 416 | 396 | ||
| 417 | struct op { | 397 | struct op { |
| 418 | u32 (* const fn)(ARMul_State* state, int dd, int dn, int dm, u32 fpscr); | 398 | u32 (*const fn)(ARMul_State* state, int dd, int dn, int dm, u32 fpscr); |
| 419 | u32 flags; | 399 | u32 flags; |
| 420 | }; | 400 | }; |
| 421 | 401 | ||
| 422 | inline u32 fls(u32 x) | 402 | inline u32 fls(u32 x) { |
| 423 | { | ||
| 424 | int r = 32; | 403 | int r = 32; |
| 425 | 404 | ||
| 426 | if (!x) | 405 | if (!x) |
| @@ -446,9 +425,9 @@ inline u32 fls(u32 x) | |||
| 446 | r -= 1; | 425 | r -= 1; |
| 447 | } | 426 | } |
| 448 | return r; | 427 | return r; |
| 449 | |||
| 450 | } | 428 | } |
| 451 | 429 | ||
| 452 | u32 vfp_double_multiply(vfp_double* vdd, vfp_double* vdn, vfp_double* vdm, u32 fpscr); | 430 | u32 vfp_double_multiply(vfp_double* vdd, vfp_double* vdn, vfp_double* vdm, u32 fpscr); |
| 453 | u32 vfp_double_add(vfp_double* vdd, vfp_double* vdn, vfp_double *vdm, u32 fpscr); | 431 | u32 vfp_double_add(vfp_double* vdd, vfp_double* vdn, vfp_double* vdm, u32 fpscr); |
| 454 | u32 vfp_double_normaliseround(ARMul_State* state, int dd, vfp_double* vd, u32 fpscr, const char* func); | 432 | u32 vfp_double_normaliseround(ARMul_State* state, int dd, vfp_double* vd, u32 fpscr, |
| 433 | const char* func); | ||
diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp index 1d5641810..4d89743e7 100644 --- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp | |||
| @@ -51,26 +51,22 @@ | |||
| 51 | * =========================================================================== | 51 | * =========================================================================== |
| 52 | */ | 52 | */ |
| 53 | 53 | ||
| 54 | #include "core/arm/skyeye_common/vfp/vfp.h" | ||
| 54 | #include <algorithm> | 55 | #include <algorithm> |
| 55 | #include "common/logging/log.h" | 56 | #include "common/logging/log.h" |
| 56 | #include "core/arm/skyeye_common/vfp/vfp.h" | ||
| 57 | #include "core/arm/skyeye_common/vfp/vfp_helper.h" | ||
| 58 | #include "core/arm/skyeye_common/vfp/asm_vfp.h" | 57 | #include "core/arm/skyeye_common/vfp/asm_vfp.h" |
| 58 | #include "core/arm/skyeye_common/vfp/vfp_helper.h" | ||
| 59 | 59 | ||
| 60 | static struct vfp_double vfp_double_default_qnan = { | 60 | static struct vfp_double vfp_double_default_qnan = { |
| 61 | 2047, | 61 | 2047, 0, VFP_DOUBLE_SIGNIFICAND_QNAN, |
| 62 | 0, | ||
| 63 | VFP_DOUBLE_SIGNIFICAND_QNAN, | ||
| 64 | }; | 62 | }; |
| 65 | 63 | ||
| 66 | static void vfp_double_dump(const char *str, struct vfp_double *d) | 64 | static void vfp_double_dump(const char* str, struct vfp_double* d) { |
| 67 | { | 65 | LOG_TRACE(Core_ARM11, "VFP: %s: sign=%d exponent=%d significand=%016llx", str, d->sign != 0, |
| 68 | LOG_TRACE(Core_ARM11, "VFP: %s: sign=%d exponent=%d significand=%016llx", | 66 | d->exponent, d->significand); |
| 69 | str, d->sign != 0, d->exponent, d->significand); | ||
| 70 | } | 67 | } |
| 71 | 68 | ||
| 72 | static void vfp_double_normalise_denormal(struct vfp_double *vd) | 69 | static void vfp_double_normalise_denormal(struct vfp_double* vd) { |
| 73 | { | ||
| 74 | int bits = 31 - fls((u32)(vd->significand >> 32)); | 70 | int bits = 31 - fls((u32)(vd->significand >> 32)); |
| 75 | if (bits == 31) | 71 | if (bits == 31) |
| 76 | bits = 63 - fls((u32)vd->significand); | 72 | bits = 63 - fls((u32)vd->significand); |
| @@ -85,8 +81,8 @@ static void vfp_double_normalise_denormal(struct vfp_double *vd) | |||
| 85 | vfp_double_dump("normalise_denormal: out", vd); | 81 | vfp_double_dump("normalise_denormal: out", vd); |
| 86 | } | 82 | } |
| 87 | 83 | ||
| 88 | u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, u32 fpscr, const char *func) | 84 | u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double* vd, u32 fpscr, |
| 89 | { | 85 | const char* func) { |
| 90 | u64 significand, incr; | 86 | u64 significand, incr; |
| 91 | int exponent, shift, underflow; | 87 | int exponent, shift, underflow; |
| 92 | u32 rmode; | 88 | u32 rmode; |
| @@ -193,7 +189,7 @@ u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, | |||
| 193 | vd->exponent = 2045; | 189 | vd->exponent = 2045; |
| 194 | vd->significand = 0x7fffffffffffffffULL; | 190 | vd->significand = 0x7fffffffffffffffULL; |
| 195 | } else { | 191 | } else { |
| 196 | vd->exponent = 2047; /* infinity */ | 192 | vd->exponent = 2047; /* infinity */ |
| 197 | vd->significand = 0; | 193 | vd->significand = 0; |
| 198 | } | 194 | } |
| 199 | } else { | 195 | } else { |
| @@ -211,8 +207,7 @@ pack: | |||
| 211 | vfp_double_dump("pack: final", vd); | 207 | vfp_double_dump("pack: final", vd); |
| 212 | { | 208 | { |
| 213 | s64 d = vfp_double_pack(vd); | 209 | s64 d = vfp_double_pack(vd); |
| 214 | LOG_TRACE(Core_ARM11, "VFP: %s: d(d%d)=%016llx exceptions=%08x", func, | 210 | LOG_TRACE(Core_ARM11, "VFP: %s: d(d%d)=%016llx exceptions=%08x", func, dd, d, exceptions); |
| 215 | dd, d, exceptions); | ||
| 216 | vfp_put_double(state, d, dd); | 211 | vfp_put_double(state, d, dd); |
| 217 | } | 212 | } |
| 218 | return exceptions; | 213 | return exceptions; |
| @@ -222,11 +217,9 @@ pack: | |||
| 222 | * Propagate the NaN, setting exceptions if it is signalling. | 217 | * Propagate the NaN, setting exceptions if it is signalling. |
| 223 | * 'n' is always a NaN. 'm' may be a number, NaN or infinity. | 218 | * 'n' is always a NaN. 'm' may be a number, NaN or infinity. |
| 224 | */ | 219 | */ |
| 225 | static u32 | 220 | static u32 vfp_propagate_nan(struct vfp_double* vdd, struct vfp_double* vdn, struct vfp_double* vdm, |
| 226 | vfp_propagate_nan(struct vfp_double *vdd, struct vfp_double *vdn, | 221 | u32 fpscr) { |
| 227 | struct vfp_double *vdm, u32 fpscr) | 222 | struct vfp_double* nan; |
| 228 | { | ||
| 229 | struct vfp_double *nan; | ||
| 230 | int tn, tm = 0; | 223 | int tn, tm = 0; |
| 231 | 224 | ||
| 232 | tn = vfp_double_type(vdn); | 225 | tn = vfp_double_type(vdn); |
| @@ -266,29 +259,25 @@ vfp_propagate_nan(struct vfp_double *vdd, struct vfp_double *vdn, | |||
| 266 | /* | 259 | /* |
| 267 | * Extended operations | 260 | * Extended operations |
| 268 | */ | 261 | */ |
| 269 | static u32 vfp_double_fabs(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) | 262 | static u32 vfp_double_fabs(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) { |
| 270 | { | ||
| 271 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); | 263 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); |
| 272 | vfp_put_double(state, vfp_double_packed_abs(vfp_get_double(state, dm)), dd); | 264 | vfp_put_double(state, vfp_double_packed_abs(vfp_get_double(state, dm)), dd); |
| 273 | return 0; | 265 | return 0; |
| 274 | } | 266 | } |
| 275 | 267 | ||
| 276 | static u32 vfp_double_fcpy(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) | 268 | static u32 vfp_double_fcpy(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) { |
| 277 | { | ||
| 278 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); | 269 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); |
| 279 | vfp_put_double(state, vfp_get_double(state, dm), dd); | 270 | vfp_put_double(state, vfp_get_double(state, dm), dd); |
| 280 | return 0; | 271 | return 0; |
| 281 | } | 272 | } |
| 282 | 273 | ||
| 283 | static u32 vfp_double_fneg(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) | 274 | static u32 vfp_double_fneg(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) { |
| 284 | { | ||
| 285 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); | 275 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); |
| 286 | vfp_put_double(state, vfp_double_packed_negate(vfp_get_double(state, dm)), dd); | 276 | vfp_put_double(state, vfp_double_packed_negate(vfp_get_double(state, dm)), dd); |
| 287 | return 0; | 277 | return 0; |
| 288 | } | 278 | } |
| 289 | 279 | ||
| 290 | static u32 vfp_double_fsqrt(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) | 280 | static u32 vfp_double_fsqrt(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) { |
| 291 | { | ||
| 292 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); | 281 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); |
| 293 | vfp_double vdm, vdd, *vdp; | 282 | vfp_double vdm, vdd, *vdp; |
| 294 | int ret, tm; | 283 | int ret, tm; |
| @@ -297,17 +286,17 @@ static u32 vfp_double_fsqrt(ARMul_State* state, int dd, int unused, int dm, u32 | |||
| 297 | exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); | 286 | exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); |
| 298 | 287 | ||
| 299 | tm = vfp_double_type(&vdm); | 288 | tm = vfp_double_type(&vdm); |
| 300 | if (tm & (VFP_NAN|VFP_INFINITY)) { | 289 | if (tm & (VFP_NAN | VFP_INFINITY)) { |
| 301 | vdp = &vdd; | 290 | vdp = &vdd; |
| 302 | 291 | ||
| 303 | if (tm & VFP_NAN) | 292 | if (tm & VFP_NAN) |
| 304 | ret = vfp_propagate_nan(vdp, &vdm, nullptr, fpscr); | 293 | ret = vfp_propagate_nan(vdp, &vdm, nullptr, fpscr); |
| 305 | else if (vdm.sign == 0) { | 294 | else if (vdm.sign == 0) { |
| 306 | sqrt_copy: | 295 | sqrt_copy: |
| 307 | vdp = &vdm; | 296 | vdp = &vdm; |
| 308 | ret = 0; | 297 | ret = 0; |
| 309 | } else { | 298 | } else { |
| 310 | sqrt_invalid: | 299 | sqrt_invalid: |
| 311 | vdp = &vfp_double_default_qnan; | 300 | vdp = &vfp_double_default_qnan; |
| 312 | ret = FPSCR_IOC; | 301 | ret = FPSCR_IOC; |
| 313 | } | 302 | } |
| @@ -381,8 +370,7 @@ sqrt_invalid: | |||
| 381 | * Greater than := C | 370 | * Greater than := C |
| 382 | * Unordered := CV | 371 | * Unordered := CV |
| 383 | */ | 372 | */ |
| 384 | static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u32 fpscr) | 373 | static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u32 fpscr) { |
| 385 | { | ||
| 386 | s64 d, m; | 374 | s64 d, m; |
| 387 | u32 ret = 0; | 375 | u32 ret = 0; |
| 388 | 376 | ||
| @@ -390,7 +378,8 @@ static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u | |||
| 390 | m = vfp_get_double(state, dm); | 378 | m = vfp_get_double(state, dm); |
| 391 | if (vfp_double_packed_exponent(m) == 2047 && vfp_double_packed_mantissa(m)) { | 379 | if (vfp_double_packed_exponent(m) == 2047 && vfp_double_packed_mantissa(m)) { |
| 392 | ret |= FPSCR_CFLAG | FPSCR_VFLAG; | 380 | ret |= FPSCR_CFLAG | FPSCR_VFLAG; |
| 393 | if (signal_on_qnan || !(vfp_double_packed_mantissa(m) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1)))) | 381 | if (signal_on_qnan || |
| 382 | !(vfp_double_packed_mantissa(m) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1)))) | ||
| 394 | /* | 383 | /* |
| 395 | * Signalling NaN, or signalling on quiet NaN | 384 | * Signalling NaN, or signalling on quiet NaN |
| 396 | */ | 385 | */ |
| @@ -400,7 +389,8 @@ static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u | |||
| 400 | d = vfp_get_double(state, dd); | 389 | d = vfp_get_double(state, dd); |
| 401 | if (vfp_double_packed_exponent(d) == 2047 && vfp_double_packed_mantissa(d)) { | 390 | if (vfp_double_packed_exponent(d) == 2047 && vfp_double_packed_mantissa(d)) { |
| 402 | ret |= FPSCR_CFLAG | FPSCR_VFLAG; | 391 | ret |= FPSCR_CFLAG | FPSCR_VFLAG; |
| 403 | if (signal_on_qnan || !(vfp_double_packed_mantissa(d) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1)))) | 392 | if (signal_on_qnan || |
| 393 | !(vfp_double_packed_mantissa(d) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1)))) | ||
| 404 | /* | 394 | /* |
| 405 | * Signalling NaN, or signalling on quiet NaN | 395 | * Signalling NaN, or signalling on quiet NaN |
| 406 | */ | 396 | */ |
| @@ -408,13 +398,13 @@ static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u | |||
| 408 | } | 398 | } |
| 409 | 399 | ||
| 410 | if (ret == 0) { | 400 | if (ret == 0) { |
| 411 | //printf("In %s, d=%lld, m =%lld\n ", __FUNCTION__, d, m); | 401 | // printf("In %s, d=%lld, m =%lld\n ", __FUNCTION__, d, m); |
| 412 | if (d == m || vfp_double_packed_abs(d | m) == 0) { | 402 | if (d == m || vfp_double_packed_abs(d | m) == 0) { |
| 413 | /* | 403 | /* |
| 414 | * equal | 404 | * equal |
| 415 | */ | 405 | */ |
| 416 | ret |= FPSCR_ZFLAG | FPSCR_CFLAG; | 406 | ret |= FPSCR_ZFLAG | FPSCR_CFLAG; |
| 417 | //printf("In %s,1 ret=0x%x\n", __FUNCTION__, ret); | 407 | // printf("In %s,1 ret=0x%x\n", __FUNCTION__, ret); |
| 418 | } else if (vfp_double_packed_sign(d ^ m)) { | 408 | } else if (vfp_double_packed_sign(d ^ m)) { |
| 419 | /* | 409 | /* |
| 420 | * different signs | 410 | * different signs |
| @@ -446,32 +436,27 @@ static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u | |||
| 446 | return ret; | 436 | return ret; |
| 447 | } | 437 | } |
| 448 | 438 | ||
| 449 | static u32 vfp_double_fcmp(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) | 439 | static u32 vfp_double_fcmp(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) { |
| 450 | { | ||
| 451 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); | 440 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); |
| 452 | return vfp_compare(state, dd, 0, dm, fpscr); | 441 | return vfp_compare(state, dd, 0, dm, fpscr); |
| 453 | } | 442 | } |
| 454 | 443 | ||
| 455 | static u32 vfp_double_fcmpe(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) | 444 | static u32 vfp_double_fcmpe(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) { |
| 456 | { | ||
| 457 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); | 445 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); |
| 458 | return vfp_compare(state, dd, 1, dm, fpscr); | 446 | return vfp_compare(state, dd, 1, dm, fpscr); |
| 459 | } | 447 | } |
| 460 | 448 | ||
| 461 | static u32 vfp_double_fcmpz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) | 449 | static u32 vfp_double_fcmpz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) { |
| 462 | { | ||
| 463 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); | 450 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); |
| 464 | return vfp_compare(state, dd, 0, VFP_REG_ZERO, fpscr); | 451 | return vfp_compare(state, dd, 0, VFP_REG_ZERO, fpscr); |
| 465 | } | 452 | } |
| 466 | 453 | ||
| 467 | static u32 vfp_double_fcmpez(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) | 454 | static u32 vfp_double_fcmpez(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) { |
| 468 | { | ||
| 469 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); | 455 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); |
| 470 | return vfp_compare(state, dd, 1, VFP_REG_ZERO, fpscr); | 456 | return vfp_compare(state, dd, 1, VFP_REG_ZERO, fpscr); |
| 471 | } | 457 | } |
| 472 | 458 | ||
| 473 | static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) | 459 | static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) { |
| 474 | { | ||
| 475 | struct vfp_double vdm; | 460 | struct vfp_double vdm; |
| 476 | struct vfp_single vsd; | 461 | struct vfp_single vsd; |
| 477 | int tm; | 462 | int tm; |
| @@ -497,7 +482,7 @@ static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32 | |||
| 497 | /* | 482 | /* |
| 498 | * If we have an infinity or a NaN, the exponent must be 255 | 483 | * If we have an infinity or a NaN, the exponent must be 255 |
| 499 | */ | 484 | */ |
| 500 | if (tm & (VFP_INFINITY|VFP_NAN)) { | 485 | if (tm & (VFP_INFINITY | VFP_NAN)) { |
| 501 | vsd.exponent = 255; | 486 | vsd.exponent = 255; |
| 502 | if (tm == VFP_QNAN) | 487 | if (tm == VFP_QNAN) |
| 503 | vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN; | 488 | vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN; |
| @@ -515,8 +500,7 @@ pack_nan: | |||
| 515 | return exceptions; | 500 | return exceptions; |
| 516 | } | 501 | } |
| 517 | 502 | ||
| 518 | static u32 vfp_double_fuito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) | 503 | static u32 vfp_double_fuito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) { |
| 519 | { | ||
| 520 | struct vfp_double vdm; | 504 | struct vfp_double vdm; |
| 521 | u32 exceptions = 0; | 505 | u32 exceptions = 0; |
| 522 | u32 m = vfp_get_float(state, dm); | 506 | u32 m = vfp_get_float(state, dm); |
| @@ -530,8 +514,7 @@ static u32 vfp_double_fuito(ARMul_State* state, int dd, int unused, int dm, u32 | |||
| 530 | return exceptions; | 514 | return exceptions; |
| 531 | } | 515 | } |
| 532 | 516 | ||
| 533 | static u32 vfp_double_fsito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) | 517 | static u32 vfp_double_fsito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) { |
| 534 | { | ||
| 535 | struct vfp_double vdm; | 518 | struct vfp_double vdm; |
| 536 | u32 exceptions = 0; | 519 | u32 exceptions = 0; |
| 537 | u32 m = vfp_get_float(state, dm); | 520 | u32 m = vfp_get_float(state, dm); |
| @@ -545,8 +528,7 @@ static u32 vfp_double_fsito(ARMul_State* state, int dd, int unused, int dm, u32 | |||
| 545 | return exceptions; | 528 | return exceptions; |
| 546 | } | 529 | } |
| 547 | 530 | ||
| 548 | static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) | 531 | static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) { |
| 549 | { | ||
| 550 | struct vfp_double vdm; | 532 | struct vfp_double vdm; |
| 551 | u32 d, exceptions = 0; | 533 | u32 d, exceptions = 0; |
| 552 | int rmode = fpscr & FPSCR_RMODE_MASK; | 534 | int rmode = fpscr & FPSCR_RMODE_MASK; |
| @@ -628,14 +610,13 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 | |||
| 628 | return exceptions; | 610 | return exceptions; |
| 629 | } | 611 | } |
| 630 | 612 | ||
| 631 | static u32 vfp_double_ftouiz(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) | 613 | static u32 vfp_double_ftouiz(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) { |
| 632 | { | ||
| 633 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); | 614 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); |
| 634 | return vfp_double_ftoui(state, sd, unused, dm, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); | 615 | return vfp_double_ftoui(state, sd, unused, dm, |
| 616 | (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); | ||
| 635 | } | 617 | } |
| 636 | 618 | ||
| 637 | static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) | 619 | static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) { |
| 638 | { | ||
| 639 | struct vfp_double vdm; | 620 | struct vfp_double vdm; |
| 640 | u32 d, exceptions = 0; | 621 | u32 d, exceptions = 0; |
| 641 | int rmode = fpscr & FPSCR_RMODE_MASK; | 622 | int rmode = fpscr & FPSCR_RMODE_MASK; |
| @@ -661,7 +642,7 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 | |||
| 661 | d = ~d; | 642 | d = ~d; |
| 662 | exceptions |= FPSCR_IOC; | 643 | exceptions |= FPSCR_IOC; |
| 663 | } else if (vdm.exponent >= 1023) { | 644 | } else if (vdm.exponent >= 1023) { |
| 664 | int shift = 1023 + 63 - vdm.exponent; /* 58 */ | 645 | int shift = 1023 + 63 - vdm.exponent; /* 58 */ |
| 665 | u64 rem, incr = 0; | 646 | u64 rem, incr = 0; |
| 666 | 647 | ||
| 667 | d = (u32)((vdm.significand << 1) >> shift); | 648 | d = (u32)((vdm.significand << 1) >> shift); |
| @@ -712,48 +693,46 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 | |||
| 712 | return exceptions; | 693 | return exceptions; |
| 713 | } | 694 | } |
| 714 | 695 | ||
| 715 | static u32 vfp_double_ftosiz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) | 696 | static u32 vfp_double_ftosiz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) { |
| 716 | { | ||
| 717 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); | 697 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); |
| 718 | return vfp_double_ftosi(state, dd, unused, dm, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); | 698 | return vfp_double_ftosi(state, dd, unused, dm, |
| 699 | (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); | ||
| 719 | } | 700 | } |
| 720 | 701 | ||
| 721 | static struct op fops_ext[] = { | 702 | static struct op fops_ext[] = { |
| 722 | { vfp_double_fcpy, 0 }, //0x00000000 - FEXT_FCPY | 703 | {vfp_double_fcpy, 0}, // 0x00000000 - FEXT_FCPY |
| 723 | { vfp_double_fabs, 0 }, //0x00000001 - FEXT_FABS | 704 | {vfp_double_fabs, 0}, // 0x00000001 - FEXT_FABS |
| 724 | { vfp_double_fneg, 0 }, //0x00000002 - FEXT_FNEG | 705 | {vfp_double_fneg, 0}, // 0x00000002 - FEXT_FNEG |
| 725 | { vfp_double_fsqrt, 0 }, //0x00000003 - FEXT_FSQRT | 706 | {vfp_double_fsqrt, 0}, // 0x00000003 - FEXT_FSQRT |
| 726 | { nullptr, 0 }, | 707 | {nullptr, 0}, |
| 727 | { nullptr, 0 }, | 708 | {nullptr, 0}, |
| 728 | { nullptr, 0 }, | 709 | {nullptr, 0}, |
| 729 | { nullptr, 0 }, | 710 | {nullptr, 0}, |
| 730 | { vfp_double_fcmp, OP_SCALAR }, //0x00000008 - FEXT_FCMP | 711 | {vfp_double_fcmp, OP_SCALAR}, // 0x00000008 - FEXT_FCMP |
| 731 | { vfp_double_fcmpe, OP_SCALAR }, //0x00000009 - FEXT_FCMPE | 712 | {vfp_double_fcmpe, OP_SCALAR}, // 0x00000009 - FEXT_FCMPE |
| 732 | { vfp_double_fcmpz, OP_SCALAR }, //0x0000000A - FEXT_FCMPZ | 713 | {vfp_double_fcmpz, OP_SCALAR}, // 0x0000000A - FEXT_FCMPZ |
| 733 | { vfp_double_fcmpez, OP_SCALAR }, //0x0000000B - FEXT_FCMPEZ | 714 | {vfp_double_fcmpez, OP_SCALAR}, // 0x0000000B - FEXT_FCMPEZ |
| 734 | { nullptr, 0 }, | 715 | {nullptr, 0}, |
| 735 | { nullptr, 0 }, | 716 | {nullptr, 0}, |
| 736 | { nullptr, 0 }, | 717 | {nullptr, 0}, |
| 737 | { vfp_double_fcvts, OP_SCALAR|OP_DD }, //0x0000000F - FEXT_FCVT | 718 | {vfp_double_fcvts, OP_SCALAR | OP_DD}, // 0x0000000F - FEXT_FCVT |
| 738 | { vfp_double_fuito, OP_SCALAR|OP_SM }, //0x00000010 - FEXT_FUITO | 719 | {vfp_double_fuito, OP_SCALAR | OP_SM}, // 0x00000010 - FEXT_FUITO |
| 739 | { vfp_double_fsito, OP_SCALAR|OP_SM }, //0x00000011 - FEXT_FSITO | 720 | {vfp_double_fsito, OP_SCALAR | OP_SM}, // 0x00000011 - FEXT_FSITO |
| 740 | { nullptr, 0 }, | 721 | {nullptr, 0}, |
| 741 | { nullptr, 0 }, | 722 | {nullptr, 0}, |
| 742 | { nullptr, 0 }, | 723 | {nullptr, 0}, |
| 743 | { nullptr, 0 }, | 724 | {nullptr, 0}, |
| 744 | { nullptr, 0 }, | 725 | {nullptr, 0}, |
| 745 | { nullptr, 0 }, | 726 | {nullptr, 0}, |
| 746 | { vfp_double_ftoui, OP_SCALAR|OP_SD }, //0x00000018 - FEXT_FTOUI | 727 | {vfp_double_ftoui, OP_SCALAR | OP_SD}, // 0x00000018 - FEXT_FTOUI |
| 747 | { vfp_double_ftouiz, OP_SCALAR|OP_SD }, //0x00000019 - FEXT_FTOUIZ | 728 | {vfp_double_ftouiz, OP_SCALAR | OP_SD}, // 0x00000019 - FEXT_FTOUIZ |
| 748 | { vfp_double_ftosi, OP_SCALAR|OP_SD }, //0x0000001A - FEXT_FTOSI | 729 | {vfp_double_ftosi, OP_SCALAR | OP_SD}, // 0x0000001A - FEXT_FTOSI |
| 749 | { vfp_double_ftosiz, OP_SCALAR|OP_SD }, //0x0000001B - FEXT_FTOSIZ | 730 | {vfp_double_ftosiz, OP_SCALAR | OP_SD}, // 0x0000001B - FEXT_FTOSIZ |
| 750 | }; | 731 | }; |
| 751 | 732 | ||
| 752 | static u32 | 733 | static u32 vfp_double_fadd_nonnumber(struct vfp_double* vdd, struct vfp_double* vdn, |
| 753 | vfp_double_fadd_nonnumber(struct vfp_double *vdd, struct vfp_double *vdn, | 734 | struct vfp_double* vdm, u32 fpscr) { |
| 754 | struct vfp_double *vdm, u32 fpscr) | 735 | struct vfp_double* vdp; |
| 755 | { | ||
| 756 | struct vfp_double *vdp; | ||
| 757 | u32 exceptions = 0; | 736 | u32 exceptions = 0; |
| 758 | int tn, tm; | 737 | int tn, tm; |
| 759 | 738 | ||
| @@ -791,13 +770,12 @@ vfp_double_fadd_nonnumber(struct vfp_double *vdd, struct vfp_double *vdn, | |||
| 791 | return exceptions; | 770 | return exceptions; |
| 792 | } | 771 | } |
| 793 | 772 | ||
| 794 | u32 vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,struct vfp_double *vdm, u32 fpscr) | 773 | u32 vfp_double_add(struct vfp_double* vdd, struct vfp_double* vdn, struct vfp_double* vdm, |
| 795 | { | 774 | u32 fpscr) { |
| 796 | u32 exp_diff; | 775 | u32 exp_diff; |
| 797 | u64 m_sig; | 776 | u64 m_sig; |
| 798 | 777 | ||
| 799 | if (vdn->significand & (1ULL << 63) || | 778 | if (vdn->significand & (1ULL << 63) || vdm->significand & (1ULL << 63)) { |
| 800 | vdm->significand & (1ULL << 63)) { | ||
| 801 | LOG_INFO(Core_ARM11, "VFP: bad FP values in %s", __func__); | 779 | LOG_INFO(Core_ARM11, "VFP: bad FP values in %s", __func__); |
| 802 | vfp_double_dump("VDN", vdn); | 780 | vfp_double_dump("VDN", vdn); |
| 803 | vfp_double_dump("VDM", vdm); | 781 | vfp_double_dump("VDM", vdm); |
| @@ -841,8 +819,7 @@ u32 vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,struct vfp_dou | |||
| 841 | vdd->sign = vfp_sign_negate(vdd->sign); | 819 | vdd->sign = vfp_sign_negate(vdd->sign); |
| 842 | m_sig = (~m_sig + 1); | 820 | m_sig = (~m_sig + 1); |
| 843 | } else if (m_sig == 0) { | 821 | } else if (m_sig == 0) { |
| 844 | vdd->sign = (fpscr & FPSCR_RMODE_MASK) == | 822 | vdd->sign = (fpscr & FPSCR_RMODE_MASK) == FPSCR_ROUND_MINUSINF ? 0x8000 : 0; |
| 845 | FPSCR_ROUND_MINUSINF ? 0x8000 : 0; | ||
| 846 | } | 823 | } |
| 847 | } else { | 824 | } else { |
| 848 | m_sig += vdn->significand; | 825 | m_sig += vdn->significand; |
| @@ -852,10 +829,8 @@ u32 vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,struct vfp_dou | |||
| 852 | return 0; | 829 | return 0; |
| 853 | } | 830 | } |
| 854 | 831 | ||
| 855 | u32 | 832 | u32 vfp_double_multiply(struct vfp_double* vdd, struct vfp_double* vdn, struct vfp_double* vdm, |
| 856 | vfp_double_multiply(struct vfp_double *vdd, struct vfp_double *vdn, | 833 | u32 fpscr) { |
| 857 | struct vfp_double *vdm, u32 fpscr) | ||
| 858 | { | ||
| 859 | vfp_double_dump("VDN", vdn); | 834 | vfp_double_dump("VDN", vdn); |
| 860 | vfp_double_dump("VDM", vdm); | 835 | vfp_double_dump("VDM", vdm); |
| 861 | 836 | ||
| @@ -908,12 +883,11 @@ vfp_double_multiply(struct vfp_double *vdd, struct vfp_double *vdn, | |||
| 908 | return 0; | 883 | return 0; |
| 909 | } | 884 | } |
| 910 | 885 | ||
| 911 | #define NEG_MULTIPLY (1 << 0) | 886 | #define NEG_MULTIPLY (1 << 0) |
| 912 | #define NEG_SUBTRACT (1 << 1) | 887 | #define NEG_SUBTRACT (1 << 1) |
| 913 | 888 | ||
| 914 | static u32 | 889 | static u32 vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 fpscr, |
| 915 | vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 fpscr, u32 negate, const char *func) | 890 | u32 negate, const char* func) { |
| 916 | { | ||
| 917 | struct vfp_double vdd, vdp, vdn, vdm; | 891 | struct vfp_double vdd, vdp, vdn, vdm; |
| 918 | u32 exceptions = 0; | 892 | u32 exceptions = 0; |
| 919 | 893 | ||
| @@ -949,8 +923,7 @@ vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 f | |||
| 949 | /* | 923 | /* |
| 950 | * sd = sd + (sn * sm) | 924 | * sd = sd + (sn * sm) |
| 951 | */ | 925 | */ |
| 952 | static u32 vfp_double_fmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) | 926 | static u32 vfp_double_fmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) { |
| 953 | { | ||
| 954 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); | 927 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); |
| 955 | return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, 0, "fmac"); | 928 | return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, 0, "fmac"); |
| 956 | } | 929 | } |
| @@ -958,8 +931,7 @@ static u32 vfp_double_fmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr | |||
| 958 | /* | 931 | /* |
| 959 | * sd = sd - (sn * sm) | 932 | * sd = sd - (sn * sm) |
| 960 | */ | 933 | */ |
| 961 | static u32 vfp_double_fnmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) | 934 | static u32 vfp_double_fnmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) { |
| 962 | { | ||
| 963 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); | 935 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); |
| 964 | return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_MULTIPLY, "fnmac"); | 936 | return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_MULTIPLY, "fnmac"); |
| 965 | } | 937 | } |
| @@ -967,8 +939,7 @@ static u32 vfp_double_fnmac(ARMul_State* state, int dd, int dn, int dm, u32 fpsc | |||
| 967 | /* | 939 | /* |
| 968 | * sd = -sd + (sn * sm) | 940 | * sd = -sd + (sn * sm) |
| 969 | */ | 941 | */ |
| 970 | static u32 vfp_double_fmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) | 942 | static u32 vfp_double_fmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) { |
| 971 | { | ||
| 972 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); | 943 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); |
| 973 | return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT, "fmsc"); | 944 | return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT, "fmsc"); |
| 974 | } | 945 | } |
| @@ -976,17 +947,16 @@ static u32 vfp_double_fmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr | |||
| 976 | /* | 947 | /* |
| 977 | * sd = -sd - (sn * sm) | 948 | * sd = -sd - (sn * sm) |
| 978 | */ | 949 | */ |
| 979 | static u32 vfp_double_fnmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) | 950 | static u32 vfp_double_fnmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) { |
| 980 | { | ||
| 981 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); | 951 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); |
| 982 | return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc"); | 952 | return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, |
| 953 | "fnmsc"); | ||
| 983 | } | 954 | } |
| 984 | 955 | ||
| 985 | /* | 956 | /* |
| 986 | * sd = sn * sm | 957 | * sd = sn * sm |
| 987 | */ | 958 | */ |
| 988 | static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) | 959 | static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) { |
| 989 | { | ||
| 990 | struct vfp_double vdd, vdn, vdm; | 960 | struct vfp_double vdd, vdn, vdm; |
| 991 | u32 exceptions = 0; | 961 | u32 exceptions = 0; |
| 992 | 962 | ||
| @@ -1008,8 +978,7 @@ static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr | |||
| 1008 | /* | 978 | /* |
| 1009 | * sd = -(sn * sm) | 979 | * sd = -(sn * sm) |
| 1010 | */ | 980 | */ |
| 1011 | static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) | 981 | static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) { |
| 1012 | { | ||
| 1013 | struct vfp_double vdd, vdn, vdm; | 982 | struct vfp_double vdd, vdn, vdm; |
| 1014 | u32 exceptions = 0; | 983 | u32 exceptions = 0; |
| 1015 | 984 | ||
| @@ -1032,8 +1001,7 @@ static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpsc | |||
| 1032 | /* | 1001 | /* |
| 1033 | * sd = sn + sm | 1002 | * sd = sn + sm |
| 1034 | */ | 1003 | */ |
| 1035 | static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) | 1004 | static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) { |
| 1036 | { | ||
| 1037 | struct vfp_double vdd, vdn, vdm; | 1005 | struct vfp_double vdd, vdn, vdm; |
| 1038 | u32 exceptions = 0; | 1006 | u32 exceptions = 0; |
| 1039 | 1007 | ||
| @@ -1055,8 +1023,7 @@ static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr | |||
| 1055 | /* | 1023 | /* |
| 1056 | * sd = sn - sm | 1024 | * sd = sn - sm |
| 1057 | */ | 1025 | */ |
| 1058 | static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) | 1026 | static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) { |
| 1059 | { | ||
| 1060 | struct vfp_double vdd, vdn, vdm; | 1027 | struct vfp_double vdd, vdn, vdm; |
| 1061 | u32 exceptions = 0; | 1028 | u32 exceptions = 0; |
| 1062 | 1029 | ||
| @@ -1083,8 +1050,7 @@ static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr | |||
| 1083 | /* | 1050 | /* |
| 1084 | * sd = sn / sm | 1051 | * sd = sn / sm |
| 1085 | */ | 1052 | */ |
| 1086 | static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) | 1053 | static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) { |
| 1087 | { | ||
| 1088 | struct vfp_double vdd, vdn, vdm; | 1054 | struct vfp_double vdd, vdn, vdm; |
| 1089 | u32 exceptions = 0; | 1055 | u32 exceptions = 0; |
| 1090 | int tm, tn; | 1056 | int tm, tn; |
| @@ -1114,7 +1080,7 @@ static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr | |||
| 1114 | * If n and m are infinity, the result is invalid | 1080 | * If n and m are infinity, the result is invalid |
| 1115 | * If n and m are zero, the result is invalid | 1081 | * If n and m are zero, the result is invalid |
| 1116 | */ | 1082 | */ |
| 1117 | if (tm & tn & (VFP_INFINITY|VFP_ZERO)) | 1083 | if (tm & tn & (VFP_INFINITY | VFP_ZERO)) |
| 1118 | goto invalid; | 1084 | goto invalid; |
| 1119 | 1085 | ||
| 1120 | /* | 1086 | /* |
| @@ -1193,29 +1159,22 @@ invalid: | |||
| 1193 | } | 1159 | } |
| 1194 | 1160 | ||
| 1195 | static struct op fops[] = { | 1161 | static struct op fops[] = { |
| 1196 | { vfp_double_fmac, 0 }, | 1162 | {vfp_double_fmac, 0}, {vfp_double_fmsc, 0}, {vfp_double_fmul, 0}, |
| 1197 | { vfp_double_fmsc, 0 }, | 1163 | {vfp_double_fadd, 0}, {vfp_double_fnmac, 0}, {vfp_double_fnmsc, 0}, |
| 1198 | { vfp_double_fmul, 0 }, | 1164 | {vfp_double_fnmul, 0}, {vfp_double_fsub, 0}, {vfp_double_fdiv, 0}, |
| 1199 | { vfp_double_fadd, 0 }, | ||
| 1200 | { vfp_double_fnmac, 0 }, | ||
| 1201 | { vfp_double_fnmsc, 0 }, | ||
| 1202 | { vfp_double_fnmul, 0 }, | ||
| 1203 | { vfp_double_fsub, 0 }, | ||
| 1204 | { vfp_double_fdiv, 0 }, | ||
| 1205 | }; | 1165 | }; |
| 1206 | 1166 | ||
| 1207 | #define FREG_BANK(x) ((x) & 0x0c) | 1167 | #define FREG_BANK(x) ((x)&0x0c) |
| 1208 | #define FREG_IDX(x) ((x) & 3) | 1168 | #define FREG_IDX(x) ((x)&3) |
| 1209 | 1169 | ||
| 1210 | u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr) | 1170 | u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr) { |
| 1211 | { | ||
| 1212 | u32 op = inst & FOP_MASK; | 1171 | u32 op = inst & FOP_MASK; |
| 1213 | u32 exceptions = 0; | 1172 | u32 exceptions = 0; |
| 1214 | unsigned int dest; | 1173 | unsigned int dest; |
| 1215 | unsigned int dn = vfp_get_dn(inst); | 1174 | unsigned int dn = vfp_get_dn(inst); |
| 1216 | unsigned int dm; | 1175 | unsigned int dm; |
| 1217 | unsigned int vecitr, veclen, vecstride; | 1176 | unsigned int vecitr, veclen, vecstride; |
| 1218 | struct op *fop; | 1177 | struct op* fop; |
| 1219 | 1178 | ||
| 1220 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); | 1179 | LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); |
| 1221 | vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK)); | 1180 | vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK)); |
| @@ -1249,7 +1208,7 @@ u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr) | |||
| 1249 | veclen = fpscr & FPSCR_LENGTH_MASK; | 1208 | veclen = fpscr & FPSCR_LENGTH_MASK; |
| 1250 | 1209 | ||
| 1251 | LOG_TRACE(Core_ARM11, "VFP: vecstride=%u veclen=%u", vecstride, | 1210 | LOG_TRACE(Core_ARM11, "VFP: vecstride=%u veclen=%u", vecstride, |
| 1252 | (veclen >> FPSCR_LENGTH_BIT) + 1); | 1211 | (veclen >> FPSCR_LENGTH_BIT) + 1); |
| 1253 | 1212 | ||
| 1254 | if (!fop->fn) { | 1213 | if (!fop->fn) { |
| 1255 | printf("VFP: could not find double op %d\n", FEXT_TO_IDX(inst)); | 1214 | printf("VFP: could not find double op %d\n", FEXT_TO_IDX(inst)); |
| @@ -1262,17 +1221,14 @@ u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr) | |||
| 1262 | 1221 | ||
| 1263 | type = (fop->flags & OP_SD) ? 's' : 'd'; | 1222 | type = (fop->flags & OP_SD) ? 's' : 'd'; |
| 1264 | if (op == FOP_EXT) | 1223 | if (op == FOP_EXT) |
| 1265 | LOG_TRACE(Core_ARM11, "VFP: itr%d (%c%u) = op[%u] (d%u)", | 1224 | LOG_TRACE(Core_ARM11, "VFP: itr%d (%c%u) = op[%u] (d%u)", vecitr >> FPSCR_LENGTH_BIT, |
| 1266 | vecitr >> FPSCR_LENGTH_BIT, | 1225 | type, dest, dn, dm); |
| 1267 | type, dest, dn, dm); | ||
| 1268 | else | 1226 | else |
| 1269 | LOG_TRACE(Core_ARM11, "VFP: itr%d (%c%u) = (d%u) op[%u] (d%u)", | 1227 | LOG_TRACE(Core_ARM11, "VFP: itr%d (%c%u) = (d%u) op[%u] (d%u)", |
| 1270 | vecitr >> FPSCR_LENGTH_BIT, | 1228 | vecitr >> FPSCR_LENGTH_BIT, type, dest, dn, FOP_TO_IDX(op), dm); |
| 1271 | type, dest, dn, FOP_TO_IDX(op), dm); | ||
| 1272 | 1229 | ||
| 1273 | except = fop->fn(state, dest, dn, dm, fpscr); | 1230 | except = fop->fn(state, dest, dn, dm, fpscr); |
| 1274 | LOG_TRACE(Core_ARM11, "VFP: itr%d: exceptions=%08x", | 1231 | LOG_TRACE(Core_ARM11, "VFP: itr%d: exceptions=%08x", vecitr >> FPSCR_LENGTH_BIT, except); |
| 1275 | vecitr >> FPSCR_LENGTH_BIT, except); | ||
| 1276 | 1232 | ||
| 1277 | exceptions |= except; | 1233 | exceptions |= except; |
| 1278 | 1234 | ||
diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp index 1a98d0114..a66dc1016 100644 --- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp | |||
| @@ -19,14 +19,13 @@ struct vmla_inst { | |||
| 19 | }; | 19 | }; |
| 20 | #endif | 20 | #endif |
| 21 | #ifdef VFP_INTERPRETER_TRANS | 21 | #ifdef VFP_INTERPRETER_TRANS |
| 22 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmla)(unsigned int inst, int index) | 22 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmla)(unsigned int inst, int index) { |
| 23 | { | 23 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmla_inst)); |
| 24 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmla_inst)); | 24 | vmla_inst* inst_cream = (vmla_inst*)inst_base->component; |
| 25 | vmla_inst *inst_cream = (vmla_inst *)inst_base->component; | ||
| 26 | 25 | ||
| 27 | inst_base->cond = BITS(inst, 28, 31); | 26 | inst_base->cond = BITS(inst, 28, 31); |
| 28 | inst_base->idx = index; | 27 | inst_base->idx = index; |
| 29 | inst_base->br = TransExtData::NON_BRANCH; | 28 | inst_base->br = TransExtData::NON_BRANCH; |
| 30 | 29 | ||
| 31 | inst_cream->dp_operation = BIT(inst, 8); | 30 | inst_cream->dp_operation = BIT(inst, 8); |
| 32 | inst_cream->instr = inst; | 31 | inst_cream->instr = inst; |
| @@ -35,12 +34,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmla)(unsigned int inst, int index) | |||
| 35 | } | 34 | } |
| 36 | #endif | 35 | #endif |
| 37 | #ifdef VFP_INTERPRETER_IMPL | 36 | #ifdef VFP_INTERPRETER_IMPL |
| 38 | VMLA_INST: | 37 | VMLA_INST : { |
| 39 | { | ||
| 40 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 38 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 41 | CHECK_VFP_ENABLED; | 39 | CHECK_VFP_ENABLED; |
| 42 | 40 | ||
| 43 | vmla_inst *inst_cream = (vmla_inst *)inst_base->component; | 41 | vmla_inst* inst_cream = (vmla_inst*)inst_base->component; |
| 44 | 42 | ||
| 45 | int ret; | 43 | int ret; |
| 46 | 44 | ||
| @@ -68,14 +66,13 @@ struct vmls_inst { | |||
| 68 | }; | 66 | }; |
| 69 | #endif | 67 | #endif |
| 70 | #ifdef VFP_INTERPRETER_TRANS | 68 | #ifdef VFP_INTERPRETER_TRANS |
| 71 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmls)(unsigned int inst, int index) | 69 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmls)(unsigned int inst, int index) { |
| 72 | { | 70 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmls_inst)); |
| 73 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmls_inst)); | 71 | vmls_inst* inst_cream = (vmls_inst*)inst_base->component; |
| 74 | vmls_inst *inst_cream = (vmls_inst *)inst_base->component; | ||
| 75 | 72 | ||
| 76 | inst_base->cond = BITS(inst, 28, 31); | 73 | inst_base->cond = BITS(inst, 28, 31); |
| 77 | inst_base->idx = index; | 74 | inst_base->idx = index; |
| 78 | inst_base->br = TransExtData::NON_BRANCH; | 75 | inst_base->br = TransExtData::NON_BRANCH; |
| 79 | 76 | ||
| 80 | inst_cream->dp_operation = BIT(inst, 8); | 77 | inst_cream->dp_operation = BIT(inst, 8); |
| 81 | inst_cream->instr = inst; | 78 | inst_cream->instr = inst; |
| @@ -84,12 +81,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmls)(unsigned int inst, int index) | |||
| 84 | } | 81 | } |
| 85 | #endif | 82 | #endif |
| 86 | #ifdef VFP_INTERPRETER_IMPL | 83 | #ifdef VFP_INTERPRETER_IMPL |
| 87 | VMLS_INST: | 84 | VMLS_INST : { |
| 88 | { | ||
| 89 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 85 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 90 | CHECK_VFP_ENABLED; | 86 | CHECK_VFP_ENABLED; |
| 91 | 87 | ||
| 92 | vmls_inst *inst_cream = (vmls_inst *)inst_base->component; | 88 | vmls_inst* inst_cream = (vmls_inst*)inst_base->component; |
| 93 | 89 | ||
| 94 | int ret; | 90 | int ret; |
| 95 | 91 | ||
| @@ -117,14 +113,13 @@ struct vnmla_inst { | |||
| 117 | }; | 113 | }; |
| 118 | #endif | 114 | #endif |
| 119 | #ifdef VFP_INTERPRETER_TRANS | 115 | #ifdef VFP_INTERPRETER_TRANS |
| 120 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmla)(unsigned int inst, int index) | 116 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmla)(unsigned int inst, int index) { |
| 121 | { | 117 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vnmla_inst)); |
| 122 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vnmla_inst)); | 118 | vnmla_inst* inst_cream = (vnmla_inst*)inst_base->component; |
| 123 | vnmla_inst *inst_cream = (vnmla_inst *)inst_base->component; | ||
| 124 | 119 | ||
| 125 | inst_base->cond = BITS(inst, 28, 31); | 120 | inst_base->cond = BITS(inst, 28, 31); |
| 126 | inst_base->idx = index; | 121 | inst_base->idx = index; |
| 127 | inst_base->br = TransExtData::NON_BRANCH; | 122 | inst_base->br = TransExtData::NON_BRANCH; |
| 128 | 123 | ||
| 129 | inst_cream->dp_operation = BIT(inst, 8); | 124 | inst_cream->dp_operation = BIT(inst, 8); |
| 130 | inst_cream->instr = inst; | 125 | inst_cream->instr = inst; |
| @@ -133,12 +128,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmla)(unsigned int inst, int index) | |||
| 133 | } | 128 | } |
| 134 | #endif | 129 | #endif |
| 135 | #ifdef VFP_INTERPRETER_IMPL | 130 | #ifdef VFP_INTERPRETER_IMPL |
| 136 | VNMLA_INST: | 131 | VNMLA_INST : { |
| 137 | { | ||
| 138 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 132 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 139 | CHECK_VFP_ENABLED; | 133 | CHECK_VFP_ENABLED; |
| 140 | 134 | ||
| 141 | vnmla_inst *inst_cream = (vnmla_inst *)inst_base->component; | 135 | vnmla_inst* inst_cream = (vnmla_inst*)inst_base->component; |
| 142 | 136 | ||
| 143 | int ret; | 137 | int ret; |
| 144 | 138 | ||
| @@ -167,14 +161,13 @@ struct vnmls_inst { | |||
| 167 | }; | 161 | }; |
| 168 | #endif | 162 | #endif |
| 169 | #ifdef VFP_INTERPRETER_TRANS | 163 | #ifdef VFP_INTERPRETER_TRANS |
| 170 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmls)(unsigned int inst, int index) | 164 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmls)(unsigned int inst, int index) { |
| 171 | { | 165 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vnmls_inst)); |
| 172 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vnmls_inst)); | 166 | vnmls_inst* inst_cream = (vnmls_inst*)inst_base->component; |
| 173 | vnmls_inst *inst_cream = (vnmls_inst *)inst_base->component; | ||
| 174 | 167 | ||
| 175 | inst_base->cond = BITS(inst, 28, 31); | 168 | inst_base->cond = BITS(inst, 28, 31); |
| 176 | inst_base->idx = index; | 169 | inst_base->idx = index; |
| 177 | inst_base->br = TransExtData::NON_BRANCH; | 170 | inst_base->br = TransExtData::NON_BRANCH; |
| 178 | 171 | ||
| 179 | inst_cream->dp_operation = BIT(inst, 8); | 172 | inst_cream->dp_operation = BIT(inst, 8); |
| 180 | inst_cream->instr = inst; | 173 | inst_cream->instr = inst; |
| @@ -183,12 +176,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmls)(unsigned int inst, int index) | |||
| 183 | } | 176 | } |
| 184 | #endif | 177 | #endif |
| 185 | #ifdef VFP_INTERPRETER_IMPL | 178 | #ifdef VFP_INTERPRETER_IMPL |
| 186 | VNMLS_INST: | 179 | VNMLS_INST : { |
| 187 | { | ||
| 188 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 180 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 189 | CHECK_VFP_ENABLED; | 181 | CHECK_VFP_ENABLED; |
| 190 | 182 | ||
| 191 | vnmls_inst *inst_cream = (vnmls_inst *)inst_base->component; | 183 | vnmls_inst* inst_cream = (vnmls_inst*)inst_base->component; |
| 192 | 184 | ||
| 193 | int ret; | 185 | int ret; |
| 194 | 186 | ||
| @@ -216,14 +208,13 @@ struct vnmul_inst { | |||
| 216 | }; | 208 | }; |
| 217 | #endif | 209 | #endif |
| 218 | #ifdef VFP_INTERPRETER_TRANS | 210 | #ifdef VFP_INTERPRETER_TRANS |
| 219 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmul)(unsigned int inst, int index) | 211 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmul)(unsigned int inst, int index) { |
| 220 | { | 212 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vnmul_inst)); |
| 221 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vnmul_inst)); | 213 | vnmul_inst* inst_cream = (vnmul_inst*)inst_base->component; |
| 222 | vnmul_inst *inst_cream = (vnmul_inst *)inst_base->component; | ||
| 223 | 214 | ||
| 224 | inst_base->cond = BITS(inst, 28, 31); | 215 | inst_base->cond = BITS(inst, 28, 31); |
| 225 | inst_base->idx = index; | 216 | inst_base->idx = index; |
| 226 | inst_base->br = TransExtData::NON_BRANCH; | 217 | inst_base->br = TransExtData::NON_BRANCH; |
| 227 | 218 | ||
| 228 | inst_cream->dp_operation = BIT(inst, 8); | 219 | inst_cream->dp_operation = BIT(inst, 8); |
| 229 | inst_cream->instr = inst; | 220 | inst_cream->instr = inst; |
| @@ -232,12 +223,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmul)(unsigned int inst, int index) | |||
| 232 | } | 223 | } |
| 233 | #endif | 224 | #endif |
| 234 | #ifdef VFP_INTERPRETER_IMPL | 225 | #ifdef VFP_INTERPRETER_IMPL |
| 235 | VNMUL_INST: | 226 | VNMUL_INST : { |
| 236 | { | ||
| 237 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 227 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 238 | CHECK_VFP_ENABLED; | 228 | CHECK_VFP_ENABLED; |
| 239 | 229 | ||
| 240 | vnmul_inst *inst_cream = (vnmul_inst *)inst_base->component; | 230 | vnmul_inst* inst_cream = (vnmul_inst*)inst_base->component; |
| 241 | 231 | ||
| 242 | int ret; | 232 | int ret; |
| 243 | 233 | ||
| @@ -265,14 +255,13 @@ struct vmul_inst { | |||
| 265 | }; | 255 | }; |
| 266 | #endif | 256 | #endif |
| 267 | #ifdef VFP_INTERPRETER_TRANS | 257 | #ifdef VFP_INTERPRETER_TRANS |
| 268 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmul)(unsigned int inst, int index) | 258 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmul)(unsigned int inst, int index) { |
| 269 | { | 259 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmul_inst)); |
| 270 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmul_inst)); | 260 | vmul_inst* inst_cream = (vmul_inst*)inst_base->component; |
| 271 | vmul_inst *inst_cream = (vmul_inst *)inst_base->component; | ||
| 272 | 261 | ||
| 273 | inst_base->cond = BITS(inst, 28, 31); | 262 | inst_base->cond = BITS(inst, 28, 31); |
| 274 | inst_base->idx = index; | 263 | inst_base->idx = index; |
| 275 | inst_base->br = TransExtData::NON_BRANCH; | 264 | inst_base->br = TransExtData::NON_BRANCH; |
| 276 | 265 | ||
| 277 | inst_cream->dp_operation = BIT(inst, 8); | 266 | inst_cream->dp_operation = BIT(inst, 8); |
| 278 | inst_cream->instr = inst; | 267 | inst_cream->instr = inst; |
| @@ -281,12 +270,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmul)(unsigned int inst, int index) | |||
| 281 | } | 270 | } |
| 282 | #endif | 271 | #endif |
| 283 | #ifdef VFP_INTERPRETER_IMPL | 272 | #ifdef VFP_INTERPRETER_IMPL |
| 284 | VMUL_INST: | 273 | VMUL_INST : { |
| 285 | { | ||
| 286 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 274 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 287 | CHECK_VFP_ENABLED; | 275 | CHECK_VFP_ENABLED; |
| 288 | 276 | ||
| 289 | vmul_inst *inst_cream = (vmul_inst *)inst_base->component; | 277 | vmul_inst* inst_cream = (vmul_inst*)inst_base->component; |
| 290 | 278 | ||
| 291 | int ret; | 279 | int ret; |
| 292 | 280 | ||
| @@ -314,14 +302,13 @@ struct vadd_inst { | |||
| 314 | }; | 302 | }; |
| 315 | #endif | 303 | #endif |
| 316 | #ifdef VFP_INTERPRETER_TRANS | 304 | #ifdef VFP_INTERPRETER_TRANS |
| 317 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vadd)(unsigned int inst, int index) | 305 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vadd)(unsigned int inst, int index) { |
| 318 | { | 306 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vadd_inst)); |
| 319 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vadd_inst)); | 307 | vadd_inst* inst_cream = (vadd_inst*)inst_base->component; |
| 320 | vadd_inst *inst_cream = (vadd_inst *)inst_base->component; | ||
| 321 | 308 | ||
| 322 | inst_base->cond = BITS(inst, 28, 31); | 309 | inst_base->cond = BITS(inst, 28, 31); |
| 323 | inst_base->idx = index; | 310 | inst_base->idx = index; |
| 324 | inst_base->br = TransExtData::NON_BRANCH; | 311 | inst_base->br = TransExtData::NON_BRANCH; |
| 325 | 312 | ||
| 326 | inst_cream->dp_operation = BIT(inst, 8); | 313 | inst_cream->dp_operation = BIT(inst, 8); |
| 327 | inst_cream->instr = inst; | 314 | inst_cream->instr = inst; |
| @@ -330,12 +317,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vadd)(unsigned int inst, int index) | |||
| 330 | } | 317 | } |
| 331 | #endif | 318 | #endif |
| 332 | #ifdef VFP_INTERPRETER_IMPL | 319 | #ifdef VFP_INTERPRETER_IMPL |
| 333 | VADD_INST: | 320 | VADD_INST : { |
| 334 | { | ||
| 335 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 321 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 336 | CHECK_VFP_ENABLED; | 322 | CHECK_VFP_ENABLED; |
| 337 | 323 | ||
| 338 | vadd_inst *inst_cream = (vadd_inst *)inst_base->component; | 324 | vadd_inst* inst_cream = (vadd_inst*)inst_base->component; |
| 339 | 325 | ||
| 340 | int ret; | 326 | int ret; |
| 341 | 327 | ||
| @@ -363,14 +349,13 @@ struct vsub_inst { | |||
| 363 | }; | 349 | }; |
| 364 | #endif | 350 | #endif |
| 365 | #ifdef VFP_INTERPRETER_TRANS | 351 | #ifdef VFP_INTERPRETER_TRANS |
| 366 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vsub)(unsigned int inst, int index) | 352 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vsub)(unsigned int inst, int index) { |
| 367 | { | 353 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vsub_inst)); |
| 368 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vsub_inst)); | 354 | vsub_inst* inst_cream = (vsub_inst*)inst_base->component; |
| 369 | vsub_inst *inst_cream = (vsub_inst *)inst_base->component; | ||
| 370 | 355 | ||
| 371 | inst_base->cond = BITS(inst, 28, 31); | 356 | inst_base->cond = BITS(inst, 28, 31); |
| 372 | inst_base->idx = index; | 357 | inst_base->idx = index; |
| 373 | inst_base->br = TransExtData::NON_BRANCH; | 358 | inst_base->br = TransExtData::NON_BRANCH; |
| 374 | 359 | ||
| 375 | inst_cream->dp_operation = BIT(inst, 8); | 360 | inst_cream->dp_operation = BIT(inst, 8); |
| 376 | inst_cream->instr = inst; | 361 | inst_cream->instr = inst; |
| @@ -379,12 +364,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vsub)(unsigned int inst, int index) | |||
| 379 | } | 364 | } |
| 380 | #endif | 365 | #endif |
| 381 | #ifdef VFP_INTERPRETER_IMPL | 366 | #ifdef VFP_INTERPRETER_IMPL |
| 382 | VSUB_INST: | 367 | VSUB_INST : { |
| 383 | { | ||
| 384 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 368 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 385 | CHECK_VFP_ENABLED; | 369 | CHECK_VFP_ENABLED; |
| 386 | 370 | ||
| 387 | vsub_inst *inst_cream = (vsub_inst *)inst_base->component; | 371 | vsub_inst* inst_cream = (vsub_inst*)inst_base->component; |
| 388 | 372 | ||
| 389 | int ret; | 373 | int ret; |
| 390 | 374 | ||
| @@ -412,14 +396,13 @@ struct vdiv_inst { | |||
| 412 | }; | 396 | }; |
| 413 | #endif | 397 | #endif |
| 414 | #ifdef VFP_INTERPRETER_TRANS | 398 | #ifdef VFP_INTERPRETER_TRANS |
| 415 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vdiv)(unsigned int inst, int index) | 399 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vdiv)(unsigned int inst, int index) { |
| 416 | { | 400 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vdiv_inst)); |
| 417 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vdiv_inst)); | 401 | vdiv_inst* inst_cream = (vdiv_inst*)inst_base->component; |
| 418 | vdiv_inst *inst_cream = (vdiv_inst *)inst_base->component; | ||
| 419 | 402 | ||
| 420 | inst_base->cond = BITS(inst, 28, 31); | 403 | inst_base->cond = BITS(inst, 28, 31); |
| 421 | inst_base->idx = index; | 404 | inst_base->idx = index; |
| 422 | inst_base->br = TransExtData::NON_BRANCH; | 405 | inst_base->br = TransExtData::NON_BRANCH; |
| 423 | 406 | ||
| 424 | inst_cream->dp_operation = BIT(inst, 8); | 407 | inst_cream->dp_operation = BIT(inst, 8); |
| 425 | inst_cream->instr = inst; | 408 | inst_cream->instr = inst; |
| @@ -428,12 +411,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vdiv)(unsigned int inst, int index) | |||
| 428 | } | 411 | } |
| 429 | #endif | 412 | #endif |
| 430 | #ifdef VFP_INTERPRETER_IMPL | 413 | #ifdef VFP_INTERPRETER_IMPL |
| 431 | VDIV_INST: | 414 | VDIV_INST : { |
| 432 | { | ||
| 433 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 415 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 434 | CHECK_VFP_ENABLED; | 416 | CHECK_VFP_ENABLED; |
| 435 | 417 | ||
| 436 | vdiv_inst *inst_cream = (vdiv_inst *)inst_base->component; | 418 | vdiv_inst* inst_cream = (vdiv_inst*)inst_base->component; |
| 437 | 419 | ||
| 438 | int ret; | 420 | int ret; |
| 439 | 421 | ||
| @@ -463,32 +445,33 @@ struct vmovi_inst { | |||
| 463 | }; | 445 | }; |
| 464 | #endif | 446 | #endif |
| 465 | #ifdef VFP_INTERPRETER_TRANS | 447 | #ifdef VFP_INTERPRETER_TRANS |
| 466 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovi)(unsigned int inst, int index) | 448 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovi)(unsigned int inst, int index) { |
| 467 | { | 449 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovi_inst)); |
| 468 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovi_inst)); | 450 | vmovi_inst* inst_cream = (vmovi_inst*)inst_base->component; |
| 469 | vmovi_inst *inst_cream = (vmovi_inst *)inst_base->component; | ||
| 470 | 451 | ||
| 471 | inst_base->cond = BITS(inst, 28, 31); | 452 | inst_base->cond = BITS(inst, 28, 31); |
| 472 | inst_base->idx = index; | 453 | inst_base->idx = index; |
| 473 | inst_base->br = TransExtData::NON_BRANCH; | 454 | inst_base->br = TransExtData::NON_BRANCH; |
| 474 | 455 | ||
| 475 | inst_cream->single = BIT(inst, 8) == 0; | 456 | inst_cream->single = BIT(inst, 8) == 0; |
| 476 | inst_cream->d = (inst_cream->single ? BITS(inst,12,15)<<1 | BIT(inst,22) : BITS(inst,12,15) | BIT(inst,22)<<4); | 457 | inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22) |
| 458 | : BITS(inst, 12, 15) | BIT(inst, 22) << 4); | ||
| 477 | unsigned int imm8 = BITS(inst, 16, 19) << 4 | BITS(inst, 0, 3); | 459 | unsigned int imm8 = BITS(inst, 16, 19) << 4 | BITS(inst, 0, 3); |
| 478 | if (inst_cream->single) | 460 | if (inst_cream->single) |
| 479 | inst_cream->imm = BIT(imm8, 7)<<31 | (BIT(imm8, 6)==0)<<30 | (BIT(imm8, 6) ? 0x1f : 0)<<25 | BITS(imm8, 0, 5)<<19; | 461 | inst_cream->imm = BIT(imm8, 7) << 31 | (BIT(imm8, 6) == 0) << 30 | |
| 462 | (BIT(imm8, 6) ? 0x1f : 0) << 25 | BITS(imm8, 0, 5) << 19; | ||
| 480 | else | 463 | else |
| 481 | inst_cream->imm = BIT(imm8, 7)<<31 | (BIT(imm8, 6)==0)<<30 | (BIT(imm8, 6) ? 0xff : 0)<<22 | BITS(imm8, 0, 5)<<16; | 464 | inst_cream->imm = BIT(imm8, 7) << 31 | (BIT(imm8, 6) == 0) << 30 | |
| 465 | (BIT(imm8, 6) ? 0xff : 0) << 22 | BITS(imm8, 0, 5) << 16; | ||
| 482 | return inst_base; | 466 | return inst_base; |
| 483 | } | 467 | } |
| 484 | #endif | 468 | #endif |
| 485 | #ifdef VFP_INTERPRETER_IMPL | 469 | #ifdef VFP_INTERPRETER_IMPL |
| 486 | VMOVI_INST: | 470 | VMOVI_INST : { |
| 487 | { | ||
| 488 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 471 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 489 | CHECK_VFP_ENABLED; | 472 | CHECK_VFP_ENABLED; |
| 490 | 473 | ||
| 491 | vmovi_inst *inst_cream = (vmovi_inst *)inst_base->component; | 474 | vmovi_inst* inst_cream = (vmovi_inst*)inst_base->component; |
| 492 | 475 | ||
| 493 | VMOVI(cpu, inst_cream->single, inst_cream->d, inst_cream->imm); | 476 | VMOVI(cpu, inst_cream->single, inst_cream->d, inst_cream->imm); |
| 494 | } | 477 | } |
| @@ -511,28 +494,28 @@ struct vmovr_inst { | |||
| 511 | }; | 494 | }; |
| 512 | #endif | 495 | #endif |
| 513 | #ifdef VFP_INTERPRETER_TRANS | 496 | #ifdef VFP_INTERPRETER_TRANS |
| 514 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovr)(unsigned int inst, int index) | 497 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovr)(unsigned int inst, int index) { |
| 515 | { | 498 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovr_inst)); |
| 516 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovr_inst)); | 499 | vmovr_inst* inst_cream = (vmovr_inst*)inst_base->component; |
| 517 | vmovr_inst *inst_cream = (vmovr_inst *)inst_base->component; | ||
| 518 | 500 | ||
| 519 | inst_base->cond = BITS(inst, 28, 31); | 501 | inst_base->cond = BITS(inst, 28, 31); |
| 520 | inst_base->idx = index; | 502 | inst_base->idx = index; |
| 521 | inst_base->br = TransExtData::NON_BRANCH; | 503 | inst_base->br = TransExtData::NON_BRANCH; |
| 522 | 504 | ||
| 523 | inst_cream->single = BIT(inst, 8) == 0; | 505 | inst_cream->single = BIT(inst, 8) == 0; |
| 524 | inst_cream->d = (inst_cream->single ? BITS(inst,12,15)<<1 | BIT(inst,22) : BITS(inst,12,15) | BIT(inst,22)<<4); | 506 | inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22) |
| 525 | inst_cream->m = (inst_cream->single ? BITS(inst, 0, 3)<<1 | BIT(inst, 5) : BITS(inst, 0, 3) | BIT(inst, 5)<<4); | 507 | : BITS(inst, 12, 15) | BIT(inst, 22) << 4); |
| 508 | inst_cream->m = (inst_cream->single ? BITS(inst, 0, 3) << 1 | BIT(inst, 5) | ||
| 509 | : BITS(inst, 0, 3) | BIT(inst, 5) << 4); | ||
| 526 | return inst_base; | 510 | return inst_base; |
| 527 | } | 511 | } |
| 528 | #endif | 512 | #endif |
| 529 | #ifdef VFP_INTERPRETER_IMPL | 513 | #ifdef VFP_INTERPRETER_IMPL |
| 530 | VMOVR_INST: | 514 | VMOVR_INST : { |
| 531 | { | ||
| 532 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 515 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 533 | CHECK_VFP_ENABLED; | 516 | CHECK_VFP_ENABLED; |
| 534 | 517 | ||
| 535 | vmovr_inst *inst_cream = (vmovr_inst *)inst_base->component; | 518 | vmovr_inst* inst_cream = (vmovr_inst*)inst_base->component; |
| 536 | 519 | ||
| 537 | VMOVR(cpu, inst_cream->single, inst_cream->d, inst_cream->m); | 520 | VMOVR(cpu, inst_cream->single, inst_cream->d, inst_cream->m); |
| 538 | } | 521 | } |
| @@ -553,14 +536,13 @@ typedef struct _vabs_inst { | |||
| 553 | } vabs_inst; | 536 | } vabs_inst; |
| 554 | #endif | 537 | #endif |
| 555 | #ifdef VFP_INTERPRETER_TRANS | 538 | #ifdef VFP_INTERPRETER_TRANS |
| 556 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vabs)(unsigned int inst, int index) | 539 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vabs)(unsigned int inst, int index) { |
| 557 | { | 540 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vabs_inst)); |
| 558 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vabs_inst)); | 541 | vabs_inst* inst_cream = (vabs_inst*)inst_base->component; |
| 559 | vabs_inst *inst_cream = (vabs_inst *)inst_base->component; | ||
| 560 | 542 | ||
| 561 | inst_base->cond = BITS(inst, 28, 31); | 543 | inst_base->cond = BITS(inst, 28, 31); |
| 562 | inst_base->idx = index; | 544 | inst_base->idx = index; |
| 563 | inst_base->br = TransExtData::NON_BRANCH; | 545 | inst_base->br = TransExtData::NON_BRANCH; |
| 564 | 546 | ||
| 565 | inst_cream->dp_operation = BIT(inst, 8); | 547 | inst_cream->dp_operation = BIT(inst, 8); |
| 566 | inst_cream->instr = inst; | 548 | inst_cream->instr = inst; |
| @@ -569,12 +551,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vabs)(unsigned int inst, int index) | |||
| 569 | } | 551 | } |
| 570 | #endif | 552 | #endif |
| 571 | #ifdef VFP_INTERPRETER_IMPL | 553 | #ifdef VFP_INTERPRETER_IMPL |
| 572 | VABS_INST: | 554 | VABS_INST : { |
| 573 | { | ||
| 574 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 555 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 575 | CHECK_VFP_ENABLED; | 556 | CHECK_VFP_ENABLED; |
| 576 | 557 | ||
| 577 | vabs_inst *inst_cream = (vabs_inst *)inst_base->component; | 558 | vabs_inst* inst_cream = (vabs_inst*)inst_base->component; |
| 578 | 559 | ||
| 579 | int ret; | 560 | int ret; |
| 580 | 561 | ||
| @@ -603,14 +584,13 @@ struct vneg_inst { | |||
| 603 | }; | 584 | }; |
| 604 | #endif | 585 | #endif |
| 605 | #ifdef VFP_INTERPRETER_TRANS | 586 | #ifdef VFP_INTERPRETER_TRANS |
| 606 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vneg)(unsigned int inst, int index) | 587 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vneg)(unsigned int inst, int index) { |
| 607 | { | 588 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vneg_inst)); |
| 608 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vneg_inst)); | 589 | vneg_inst* inst_cream = (vneg_inst*)inst_base->component; |
| 609 | vneg_inst *inst_cream = (vneg_inst *)inst_base->component; | ||
| 610 | 590 | ||
| 611 | inst_base->cond = BITS(inst, 28, 31); | 591 | inst_base->cond = BITS(inst, 28, 31); |
| 612 | inst_base->idx = index; | 592 | inst_base->idx = index; |
| 613 | inst_base->br = TransExtData::NON_BRANCH; | 593 | inst_base->br = TransExtData::NON_BRANCH; |
| 614 | 594 | ||
| 615 | inst_cream->dp_operation = BIT(inst, 8); | 595 | inst_cream->dp_operation = BIT(inst, 8); |
| 616 | inst_cream->instr = inst; | 596 | inst_cream->instr = inst; |
| @@ -619,12 +599,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vneg)(unsigned int inst, int index) | |||
| 619 | } | 599 | } |
| 620 | #endif | 600 | #endif |
| 621 | #ifdef VFP_INTERPRETER_IMPL | 601 | #ifdef VFP_INTERPRETER_IMPL |
| 622 | VNEG_INST: | 602 | VNEG_INST : { |
| 623 | { | ||
| 624 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 603 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 625 | CHECK_VFP_ENABLED; | 604 | CHECK_VFP_ENABLED; |
| 626 | 605 | ||
| 627 | vneg_inst *inst_cream = (vneg_inst *)inst_base->component; | 606 | vneg_inst* inst_cream = (vneg_inst*)inst_base->component; |
| 628 | 607 | ||
| 629 | int ret; | 608 | int ret; |
| 630 | 609 | ||
| @@ -652,14 +631,13 @@ struct vsqrt_inst { | |||
| 652 | }; | 631 | }; |
| 653 | #endif | 632 | #endif |
| 654 | #ifdef VFP_INTERPRETER_TRANS | 633 | #ifdef VFP_INTERPRETER_TRANS |
| 655 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vsqrt)(unsigned int inst, int index) | 634 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vsqrt)(unsigned int inst, int index) { |
| 656 | { | 635 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vsqrt_inst)); |
| 657 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vsqrt_inst)); | 636 | vsqrt_inst* inst_cream = (vsqrt_inst*)inst_base->component; |
| 658 | vsqrt_inst *inst_cream = (vsqrt_inst *)inst_base->component; | ||
| 659 | 637 | ||
| 660 | inst_base->cond = BITS(inst, 28, 31); | 638 | inst_base->cond = BITS(inst, 28, 31); |
| 661 | inst_base->idx = index; | 639 | inst_base->idx = index; |
| 662 | inst_base->br = TransExtData::NON_BRANCH; | 640 | inst_base->br = TransExtData::NON_BRANCH; |
| 663 | 641 | ||
| 664 | inst_cream->dp_operation = BIT(inst, 8); | 642 | inst_cream->dp_operation = BIT(inst, 8); |
| 665 | inst_cream->instr = inst; | 643 | inst_cream->instr = inst; |
| @@ -668,12 +646,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vsqrt)(unsigned int inst, int index) | |||
| 668 | } | 646 | } |
| 669 | #endif | 647 | #endif |
| 670 | #ifdef VFP_INTERPRETER_IMPL | 648 | #ifdef VFP_INTERPRETER_IMPL |
| 671 | VSQRT_INST: | 649 | VSQRT_INST : { |
| 672 | { | ||
| 673 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 650 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 674 | CHECK_VFP_ENABLED; | 651 | CHECK_VFP_ENABLED; |
| 675 | 652 | ||
| 676 | vsqrt_inst *inst_cream = (vsqrt_inst *)inst_base->component; | 653 | vsqrt_inst* inst_cream = (vsqrt_inst*)inst_base->component; |
| 677 | 654 | ||
| 678 | int ret; | 655 | int ret; |
| 679 | 656 | ||
| @@ -701,14 +678,13 @@ struct vcmp_inst { | |||
| 701 | }; | 678 | }; |
| 702 | #endif | 679 | #endif |
| 703 | #ifdef VFP_INTERPRETER_TRANS | 680 | #ifdef VFP_INTERPRETER_TRANS |
| 704 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp)(unsigned int inst, int index) | 681 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp)(unsigned int inst, int index) { |
| 705 | { | 682 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vcmp_inst)); |
| 706 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcmp_inst)); | 683 | vcmp_inst* inst_cream = (vcmp_inst*)inst_base->component; |
| 707 | vcmp_inst *inst_cream = (vcmp_inst *)inst_base->component; | ||
| 708 | 684 | ||
| 709 | inst_base->cond = BITS(inst, 28, 31); | 685 | inst_base->cond = BITS(inst, 28, 31); |
| 710 | inst_base->idx = index; | 686 | inst_base->idx = index; |
| 711 | inst_base->br = TransExtData::NON_BRANCH; | 687 | inst_base->br = TransExtData::NON_BRANCH; |
| 712 | 688 | ||
| 713 | inst_cream->dp_operation = BIT(inst, 8); | 689 | inst_cream->dp_operation = BIT(inst, 8); |
| 714 | inst_cream->instr = inst; | 690 | inst_cream->instr = inst; |
| @@ -717,12 +693,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp)(unsigned int inst, int index) | |||
| 717 | } | 693 | } |
| 718 | #endif | 694 | #endif |
| 719 | #ifdef VFP_INTERPRETER_IMPL | 695 | #ifdef VFP_INTERPRETER_IMPL |
| 720 | VCMP_INST: | 696 | VCMP_INST : { |
| 721 | { | ||
| 722 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 697 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 723 | CHECK_VFP_ENABLED; | 698 | CHECK_VFP_ENABLED; |
| 724 | 699 | ||
| 725 | vcmp_inst *inst_cream = (vcmp_inst *)inst_base->component; | 700 | vcmp_inst* inst_cream = (vcmp_inst*)inst_base->component; |
| 726 | 701 | ||
| 727 | int ret; | 702 | int ret; |
| 728 | 703 | ||
| @@ -750,14 +725,13 @@ struct vcmp2_inst { | |||
| 750 | }; | 725 | }; |
| 751 | #endif | 726 | #endif |
| 752 | #ifdef VFP_INTERPRETER_TRANS | 727 | #ifdef VFP_INTERPRETER_TRANS |
| 753 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp2)(unsigned int inst, int index) | 728 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp2)(unsigned int inst, int index) { |
| 754 | { | 729 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vcmp2_inst)); |
| 755 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcmp2_inst)); | 730 | vcmp2_inst* inst_cream = (vcmp2_inst*)inst_base->component; |
| 756 | vcmp2_inst *inst_cream = (vcmp2_inst *)inst_base->component; | ||
| 757 | 731 | ||
| 758 | inst_base->cond = BITS(inst, 28, 31); | 732 | inst_base->cond = BITS(inst, 28, 31); |
| 759 | inst_base->idx = index; | 733 | inst_base->idx = index; |
| 760 | inst_base->br = TransExtData::NON_BRANCH; | 734 | inst_base->br = TransExtData::NON_BRANCH; |
| 761 | 735 | ||
| 762 | inst_cream->dp_operation = BIT(inst, 8); | 736 | inst_cream->dp_operation = BIT(inst, 8); |
| 763 | inst_cream->instr = inst; | 737 | inst_cream->instr = inst; |
| @@ -766,12 +740,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp2)(unsigned int inst, int index) | |||
| 766 | } | 740 | } |
| 767 | #endif | 741 | #endif |
| 768 | #ifdef VFP_INTERPRETER_IMPL | 742 | #ifdef VFP_INTERPRETER_IMPL |
| 769 | VCMP2_INST: | 743 | VCMP2_INST : { |
| 770 | { | ||
| 771 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 744 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 772 | CHECK_VFP_ENABLED; | 745 | CHECK_VFP_ENABLED; |
| 773 | 746 | ||
| 774 | vcmp2_inst *inst_cream = (vcmp2_inst *)inst_base->component; | 747 | vcmp2_inst* inst_cream = (vcmp2_inst*)inst_base->component; |
| 775 | 748 | ||
| 776 | int ret; | 749 | int ret; |
| 777 | 750 | ||
| @@ -799,14 +772,13 @@ struct vcvtbds_inst { | |||
| 799 | }; | 772 | }; |
| 800 | #endif | 773 | #endif |
| 801 | #ifdef VFP_INTERPRETER_TRANS | 774 | #ifdef VFP_INTERPRETER_TRANS |
| 802 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbds)(unsigned int inst, int index) | 775 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbds)(unsigned int inst, int index) { |
| 803 | { | 776 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbds_inst)); |
| 804 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbds_inst)); | 777 | vcvtbds_inst* inst_cream = (vcvtbds_inst*)inst_base->component; |
| 805 | vcvtbds_inst *inst_cream = (vcvtbds_inst *)inst_base->component; | ||
| 806 | 778 | ||
| 807 | inst_base->cond = BITS(inst, 28, 31); | 779 | inst_base->cond = BITS(inst, 28, 31); |
| 808 | inst_base->idx = index; | 780 | inst_base->idx = index; |
| 809 | inst_base->br = TransExtData::NON_BRANCH; | 781 | inst_base->br = TransExtData::NON_BRANCH; |
| 810 | 782 | ||
| 811 | inst_cream->dp_operation = BIT(inst, 8); | 783 | inst_cream->dp_operation = BIT(inst, 8); |
| 812 | inst_cream->instr = inst; | 784 | inst_cream->instr = inst; |
| @@ -815,12 +787,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbds)(unsigned int inst, int index) | |||
| 815 | } | 787 | } |
| 816 | #endif | 788 | #endif |
| 817 | #ifdef VFP_INTERPRETER_IMPL | 789 | #ifdef VFP_INTERPRETER_IMPL |
| 818 | VCVTBDS_INST: | 790 | VCVTBDS_INST : { |
| 819 | { | ||
| 820 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 791 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 821 | CHECK_VFP_ENABLED; | 792 | CHECK_VFP_ENABLED; |
| 822 | 793 | ||
| 823 | vcvtbds_inst *inst_cream = (vcvtbds_inst *)inst_base->component; | 794 | vcvtbds_inst* inst_cream = (vcvtbds_inst*)inst_base->component; |
| 824 | 795 | ||
| 825 | int ret; | 796 | int ret; |
| 826 | 797 | ||
| @@ -848,16 +819,15 @@ struct vcvtbff_inst { | |||
| 848 | }; | 819 | }; |
| 849 | #endif | 820 | #endif |
| 850 | #ifdef VFP_INTERPRETER_TRANS | 821 | #ifdef VFP_INTERPRETER_TRANS |
| 851 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbff)(unsigned int inst, int index) | 822 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbff)(unsigned int inst, int index) { |
| 852 | { | ||
| 853 | VFP_DEBUG_UNTESTED(VCVTBFF); | 823 | VFP_DEBUG_UNTESTED(VCVTBFF); |
| 854 | 824 | ||
| 855 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbff_inst)); | 825 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbff_inst)); |
| 856 | vcvtbff_inst *inst_cream = (vcvtbff_inst *)inst_base->component; | 826 | vcvtbff_inst* inst_cream = (vcvtbff_inst*)inst_base->component; |
| 857 | 827 | ||
| 858 | inst_base->cond = BITS(inst, 28, 31); | 828 | inst_base->cond = BITS(inst, 28, 31); |
| 859 | inst_base->idx = index; | 829 | inst_base->idx = index; |
| 860 | inst_base->br = TransExtData::NON_BRANCH; | 830 | inst_base->br = TransExtData::NON_BRANCH; |
| 861 | 831 | ||
| 862 | inst_cream->dp_operation = BIT(inst, 8); | 832 | inst_cream->dp_operation = BIT(inst, 8); |
| 863 | inst_cream->instr = inst; | 833 | inst_cream->instr = inst; |
| @@ -866,12 +836,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbff)(unsigned int inst, int index) | |||
| 866 | } | 836 | } |
| 867 | #endif | 837 | #endif |
| 868 | #ifdef VFP_INTERPRETER_IMPL | 838 | #ifdef VFP_INTERPRETER_IMPL |
| 869 | VCVTBFF_INST: | 839 | VCVTBFF_INST : { |
| 870 | { | ||
| 871 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 840 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 872 | CHECK_VFP_ENABLED; | 841 | CHECK_VFP_ENABLED; |
| 873 | 842 | ||
| 874 | vcvtbff_inst *inst_cream = (vcvtbff_inst *)inst_base->component; | 843 | vcvtbff_inst* inst_cream = (vcvtbff_inst*)inst_base->component; |
| 875 | 844 | ||
| 876 | int ret; | 845 | int ret; |
| 877 | 846 | ||
| @@ -899,14 +868,13 @@ struct vcvtbfi_inst { | |||
| 899 | }; | 868 | }; |
| 900 | #endif | 869 | #endif |
| 901 | #ifdef VFP_INTERPRETER_TRANS | 870 | #ifdef VFP_INTERPRETER_TRANS |
| 902 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbfi)(unsigned int inst, int index) | 871 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbfi)(unsigned int inst, int index) { |
| 903 | { | 872 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbfi_inst)); |
| 904 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbfi_inst)); | 873 | vcvtbfi_inst* inst_cream = (vcvtbfi_inst*)inst_base->component; |
| 905 | vcvtbfi_inst *inst_cream = (vcvtbfi_inst *)inst_base->component; | ||
| 906 | 874 | ||
| 907 | inst_base->cond = BITS(inst, 28, 31); | 875 | inst_base->cond = BITS(inst, 28, 31); |
| 908 | inst_base->idx = index; | 876 | inst_base->idx = index; |
| 909 | inst_base->br = TransExtData::NON_BRANCH; | 877 | inst_base->br = TransExtData::NON_BRANCH; |
| 910 | 878 | ||
| 911 | inst_cream->dp_operation = BIT(inst, 8); | 879 | inst_cream->dp_operation = BIT(inst, 8); |
| 912 | inst_cream->instr = inst; | 880 | inst_cream->instr = inst; |
| @@ -915,12 +883,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbfi)(unsigned int inst, int index) | |||
| 915 | } | 883 | } |
| 916 | #endif | 884 | #endif |
| 917 | #ifdef VFP_INTERPRETER_IMPL | 885 | #ifdef VFP_INTERPRETER_IMPL |
| 918 | VCVTBFI_INST: | 886 | VCVTBFI_INST : { |
| 919 | { | ||
| 920 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 887 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 921 | CHECK_VFP_ENABLED; | 888 | CHECK_VFP_ENABLED; |
| 922 | 889 | ||
| 923 | vcvtbfi_inst *inst_cream = (vcvtbfi_inst *)inst_base->component; | 890 | vcvtbfi_inst* inst_cream = (vcvtbfi_inst*)inst_base->component; |
| 924 | 891 | ||
| 925 | int ret; | 892 | int ret; |
| 926 | 893 | ||
| @@ -955,29 +922,27 @@ struct vmovbrs_inst { | |||
| 955 | }; | 922 | }; |
| 956 | #endif | 923 | #endif |
| 957 | #ifdef VFP_INTERPRETER_TRANS | 924 | #ifdef VFP_INTERPRETER_TRANS |
| 958 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrs)(unsigned int inst, int index) | 925 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrs)(unsigned int inst, int index) { |
| 959 | { | 926 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrs_inst)); |
| 960 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrs_inst)); | 927 | vmovbrs_inst* inst_cream = (vmovbrs_inst*)inst_base->component; |
| 961 | vmovbrs_inst *inst_cream = (vmovbrs_inst *)inst_base->component; | ||
| 962 | 928 | ||
| 963 | inst_base->cond = BITS(inst, 28, 31); | 929 | inst_base->cond = BITS(inst, 28, 31); |
| 964 | inst_base->idx = index; | 930 | inst_base->idx = index; |
| 965 | inst_base->br = TransExtData::NON_BRANCH; | 931 | inst_base->br = TransExtData::NON_BRANCH; |
| 966 | 932 | ||
| 967 | inst_cream->to_arm = BIT(inst, 20) == 1; | 933 | inst_cream->to_arm = BIT(inst, 20) == 1; |
| 968 | inst_cream->t = BITS(inst, 12, 15); | 934 | inst_cream->t = BITS(inst, 12, 15); |
| 969 | inst_cream->n = BIT(inst, 7) | BITS(inst, 16, 19)<<1; | 935 | inst_cream->n = BIT(inst, 7) | BITS(inst, 16, 19) << 1; |
| 970 | 936 | ||
| 971 | return inst_base; | 937 | return inst_base; |
| 972 | } | 938 | } |
| 973 | #endif | 939 | #endif |
| 974 | #ifdef VFP_INTERPRETER_IMPL | 940 | #ifdef VFP_INTERPRETER_IMPL |
| 975 | VMOVBRS_INST: | 941 | VMOVBRS_INST : { |
| 976 | { | ||
| 977 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 942 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 978 | CHECK_VFP_ENABLED; | 943 | CHECK_VFP_ENABLED; |
| 979 | 944 | ||
| 980 | vmovbrs_inst *inst_cream = (vmovbrs_inst *)inst_base->component; | 945 | vmovbrs_inst* inst_cream = (vmovbrs_inst*)inst_base->component; |
| 981 | 946 | ||
| 982 | VMOVBRS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->n, &(cpu->Reg[inst_cream->t])); | 947 | VMOVBRS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->n, &(cpu->Reg[inst_cream->t])); |
| 983 | } | 948 | } |
| @@ -999,24 +964,22 @@ struct vmsr_inst { | |||
| 999 | }; | 964 | }; |
| 1000 | #endif | 965 | #endif |
| 1001 | #ifdef VFP_INTERPRETER_TRANS | 966 | #ifdef VFP_INTERPRETER_TRANS |
| 1002 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmsr)(unsigned int inst, int index) | 967 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmsr)(unsigned int inst, int index) { |
| 1003 | { | 968 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmsr_inst)); |
| 1004 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmsr_inst)); | 969 | vmsr_inst* inst_cream = (vmsr_inst*)inst_base->component; |
| 1005 | vmsr_inst *inst_cream = (vmsr_inst *)inst_base->component; | ||
| 1006 | 970 | ||
| 1007 | inst_base->cond = BITS(inst, 28, 31); | 971 | inst_base->cond = BITS(inst, 28, 31); |
| 1008 | inst_base->idx = index; | 972 | inst_base->idx = index; |
| 1009 | inst_base->br = TransExtData::NON_BRANCH; | 973 | inst_base->br = TransExtData::NON_BRANCH; |
| 1010 | 974 | ||
| 1011 | inst_cream->reg = BITS(inst, 16, 19); | 975 | inst_cream->reg = BITS(inst, 16, 19); |
| 1012 | inst_cream->Rt = BITS(inst, 12, 15); | 976 | inst_cream->Rt = BITS(inst, 12, 15); |
| 1013 | 977 | ||
| 1014 | return inst_base; | 978 | return inst_base; |
| 1015 | } | 979 | } |
| 1016 | #endif | 980 | #endif |
| 1017 | #ifdef VFP_INTERPRETER_IMPL | 981 | #ifdef VFP_INTERPRETER_IMPL |
| 1018 | VMSR_INST: | 982 | VMSR_INST : { |
| 1019 | { | ||
| 1020 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 983 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 1021 | /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled , | 984 | /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled , |
| 1022 | and in privileged mode */ | 985 | and in privileged mode */ |
| @@ -1026,14 +989,11 @@ VMSR_INST: | |||
| 1026 | vmsr_inst* const inst_cream = (vmsr_inst*)inst_base->component; | 989 | vmsr_inst* const inst_cream = (vmsr_inst*)inst_base->component; |
| 1027 | 990 | ||
| 1028 | unsigned int reg = inst_cream->reg; | 991 | unsigned int reg = inst_cream->reg; |
| 1029 | unsigned int rt = inst_cream->Rt; | 992 | unsigned int rt = inst_cream->Rt; |
| 1030 | 993 | ||
| 1031 | if (reg == 1) | 994 | if (reg == 1) { |
| 1032 | { | ||
| 1033 | cpu->VFP[VFP_FPSCR] = cpu->Reg[rt]; | 995 | cpu->VFP[VFP_FPSCR] = cpu->Reg[rt]; |
| 1034 | } | 996 | } else if (cpu->InAPrivilegedMode()) { |
| 1035 | else if (cpu->InAPrivilegedMode()) | ||
| 1036 | { | ||
| 1037 | if (reg == 8) | 997 | if (reg == 8) |
| 1038 | cpu->VFP[VFP_FPEXC] = cpu->Reg[rt]; | 998 | cpu->VFP[VFP_FPEXC] = cpu->Reg[rt]; |
| 1039 | else if (reg == 9) | 999 | else if (reg == 9) |
| @@ -1062,17 +1022,16 @@ struct vmovbrc_inst { | |||
| 1062 | }; | 1022 | }; |
| 1063 | #endif | 1023 | #endif |
| 1064 | #ifdef VFP_INTERPRETER_TRANS | 1024 | #ifdef VFP_INTERPRETER_TRANS |
| 1065 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrc)(unsigned int inst, int index) | 1025 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrc)(unsigned int inst, int index) { |
| 1066 | { | 1026 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrc_inst)); |
| 1067 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrc_inst)); | 1027 | vmovbrc_inst* inst_cream = (vmovbrc_inst*)inst_base->component; |
| 1068 | vmovbrc_inst *inst_cream = (vmovbrc_inst *)inst_base->component; | ||
| 1069 | 1028 | ||
| 1070 | inst_base->cond = BITS(inst, 28, 31); | 1029 | inst_base->cond = BITS(inst, 28, 31); |
| 1071 | inst_base->idx = index; | 1030 | inst_base->idx = index; |
| 1072 | inst_base->br = TransExtData::NON_BRANCH; | 1031 | inst_base->br = TransExtData::NON_BRANCH; |
| 1073 | 1032 | ||
| 1074 | inst_cream->d = BITS(inst, 16, 19)|BIT(inst, 7)<<4; | 1033 | inst_cream->d = BITS(inst, 16, 19) | BIT(inst, 7) << 4; |
| 1075 | inst_cream->t = BITS(inst, 12, 15); | 1034 | inst_cream->t = BITS(inst, 12, 15); |
| 1076 | /* VFP variant of instruction */ | 1035 | /* VFP variant of instruction */ |
| 1077 | inst_cream->esize = 32; | 1036 | inst_cream->esize = 32; |
| 1078 | inst_cream->index = BIT(inst, 21); | 1037 | inst_cream->index = BIT(inst, 21); |
| @@ -1081,8 +1040,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrc)(unsigned int inst, int index) | |||
| 1081 | } | 1040 | } |
| 1082 | #endif | 1041 | #endif |
| 1083 | #ifdef VFP_INTERPRETER_IMPL | 1042 | #ifdef VFP_INTERPRETER_IMPL |
| 1084 | VMOVBRC_INST: | 1043 | VMOVBRC_INST : { |
| 1085 | { | ||
| 1086 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 1044 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 1087 | CHECK_VFP_ENABLED; | 1045 | CHECK_VFP_ENABLED; |
| 1088 | 1046 | ||
| @@ -1108,24 +1066,22 @@ struct vmrs_inst { | |||
| 1108 | }; | 1066 | }; |
| 1109 | #endif | 1067 | #endif |
| 1110 | #ifdef VFP_INTERPRETER_TRANS | 1068 | #ifdef VFP_INTERPRETER_TRANS |
| 1111 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmrs)(unsigned int inst, int index) | 1069 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmrs)(unsigned int inst, int index) { |
| 1112 | { | 1070 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmrs_inst)); |
| 1113 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmrs_inst)); | 1071 | vmrs_inst* inst_cream = (vmrs_inst*)inst_base->component; |
| 1114 | vmrs_inst *inst_cream = (vmrs_inst *)inst_base->component; | ||
| 1115 | 1072 | ||
| 1116 | inst_base->cond = BITS(inst, 28, 31); | 1073 | inst_base->cond = BITS(inst, 28, 31); |
| 1117 | inst_base->idx = index; | 1074 | inst_base->idx = index; |
| 1118 | inst_base->br = TransExtData::NON_BRANCH; | 1075 | inst_base->br = TransExtData::NON_BRANCH; |
| 1119 | 1076 | ||
| 1120 | inst_cream->reg = BITS(inst, 16, 19); | 1077 | inst_cream->reg = BITS(inst, 16, 19); |
| 1121 | inst_cream->Rt = BITS(inst, 12, 15); | 1078 | inst_cream->Rt = BITS(inst, 12, 15); |
| 1122 | 1079 | ||
| 1123 | return inst_base; | 1080 | return inst_base; |
| 1124 | } | 1081 | } |
| 1125 | #endif | 1082 | #endif |
| 1126 | #ifdef VFP_INTERPRETER_IMPL | 1083 | #ifdef VFP_INTERPRETER_IMPL |
| 1127 | VMRS_INST: | 1084 | VMRS_INST : { |
| 1128 | { | ||
| 1129 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 1085 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 1130 | /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled, | 1086 | /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled, |
| 1131 | and in privileged mode */ | 1087 | and in privileged mode */ |
| @@ -1135,36 +1091,25 @@ VMRS_INST: | |||
| 1135 | vmrs_inst* const inst_cream = (vmrs_inst*)inst_base->component; | 1091 | vmrs_inst* const inst_cream = (vmrs_inst*)inst_base->component; |
| 1136 | 1092 | ||
| 1137 | unsigned int reg = inst_cream->reg; | 1093 | unsigned int reg = inst_cream->reg; |
| 1138 | unsigned int rt = inst_cream->Rt; | 1094 | unsigned int rt = inst_cream->Rt; |
| 1139 | 1095 | ||
| 1140 | if (reg == 1) // FPSCR | 1096 | if (reg == 1) // FPSCR |
| 1141 | { | 1097 | { |
| 1142 | if (rt != 15) | 1098 | if (rt != 15) { |
| 1143 | { | ||
| 1144 | cpu->Reg[rt] = cpu->VFP[VFP_FPSCR]; | 1099 | cpu->Reg[rt] = cpu->VFP[VFP_FPSCR]; |
| 1145 | } | 1100 | } else { |
| 1146 | else | ||
| 1147 | { | ||
| 1148 | cpu->NFlag = (cpu->VFP[VFP_FPSCR] >> 31) & 1; | 1101 | cpu->NFlag = (cpu->VFP[VFP_FPSCR] >> 31) & 1; |
| 1149 | cpu->ZFlag = (cpu->VFP[VFP_FPSCR] >> 30) & 1; | 1102 | cpu->ZFlag = (cpu->VFP[VFP_FPSCR] >> 30) & 1; |
| 1150 | cpu->CFlag = (cpu->VFP[VFP_FPSCR] >> 29) & 1; | 1103 | cpu->CFlag = (cpu->VFP[VFP_FPSCR] >> 29) & 1; |
| 1151 | cpu->VFlag = (cpu->VFP[VFP_FPSCR] >> 28) & 1; | 1104 | cpu->VFlag = (cpu->VFP[VFP_FPSCR] >> 28) & 1; |
| 1152 | } | 1105 | } |
| 1153 | } | 1106 | } else if (reg == 0) { |
| 1154 | else if (reg == 0) | ||
| 1155 | { | ||
| 1156 | cpu->Reg[rt] = cpu->VFP[VFP_FPSID]; | 1107 | cpu->Reg[rt] = cpu->VFP[VFP_FPSID]; |
| 1157 | } | 1108 | } else if (reg == 6) { |
| 1158 | else if (reg == 6) | ||
| 1159 | { | ||
| 1160 | cpu->Reg[rt] = cpu->VFP[VFP_MVFR1]; | 1109 | cpu->Reg[rt] = cpu->VFP[VFP_MVFR1]; |
| 1161 | } | 1110 | } else if (reg == 7) { |
| 1162 | else if (reg == 7) | ||
| 1163 | { | ||
| 1164 | cpu->Reg[rt] = cpu->VFP[VFP_MVFR0]; | 1111 | cpu->Reg[rt] = cpu->VFP[VFP_MVFR0]; |
| 1165 | } | 1112 | } else if (cpu->InAPrivilegedMode()) { |
| 1166 | else if (cpu->InAPrivilegedMode()) | ||
| 1167 | { | ||
| 1168 | if (reg == 8) | 1113 | if (reg == 8) |
| 1169 | cpu->Reg[rt] = cpu->VFP[VFP_FPEXC]; | 1114 | cpu->Reg[rt] = cpu->VFP[VFP_FPEXC]; |
| 1170 | else if (reg == 9) | 1115 | else if (reg == 9) |
| @@ -1193,17 +1138,16 @@ struct vmovbcr_inst { | |||
| 1193 | }; | 1138 | }; |
| 1194 | #endif | 1139 | #endif |
| 1195 | #ifdef VFP_INTERPRETER_TRANS | 1140 | #ifdef VFP_INTERPRETER_TRANS |
| 1196 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbcr)(unsigned int inst, int index) | 1141 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbcr)(unsigned int inst, int index) { |
| 1197 | { | 1142 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbcr_inst)); |
| 1198 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbcr_inst)); | 1143 | vmovbcr_inst* inst_cream = (vmovbcr_inst*)inst_base->component; |
| 1199 | vmovbcr_inst *inst_cream = (vmovbcr_inst *)inst_base->component; | ||
| 1200 | 1144 | ||
| 1201 | inst_base->cond = BITS(inst, 28, 31); | 1145 | inst_base->cond = BITS(inst, 28, 31); |
| 1202 | inst_base->idx = index; | 1146 | inst_base->idx = index; |
| 1203 | inst_base->br = TransExtData::NON_BRANCH; | 1147 | inst_base->br = TransExtData::NON_BRANCH; |
| 1204 | 1148 | ||
| 1205 | inst_cream->d = BITS(inst, 16, 19)|BIT(inst, 7)<<4; | 1149 | inst_cream->d = BITS(inst, 16, 19) | BIT(inst, 7) << 4; |
| 1206 | inst_cream->t = BITS(inst, 12, 15); | 1150 | inst_cream->t = BITS(inst, 12, 15); |
| 1207 | /* VFP variant of instruction */ | 1151 | /* VFP variant of instruction */ |
| 1208 | inst_cream->esize = 32; | 1152 | inst_cream->esize = 32; |
| 1209 | inst_cream->index = BIT(inst, 21); | 1153 | inst_cream->index = BIT(inst, 21); |
| @@ -1212,12 +1156,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbcr)(unsigned int inst, int index) | |||
| 1212 | } | 1156 | } |
| 1213 | #endif | 1157 | #endif |
| 1214 | #ifdef VFP_INTERPRETER_IMPL | 1158 | #ifdef VFP_INTERPRETER_IMPL |
| 1215 | VMOVBCR_INST: | 1159 | VMOVBCR_INST : { |
| 1216 | { | ||
| 1217 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 1160 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 1218 | CHECK_VFP_ENABLED; | 1161 | CHECK_VFP_ENABLED; |
| 1219 | 1162 | ||
| 1220 | vmovbcr_inst* const inst_cream = (vmovbcr_inst*) inst_base->component; | 1163 | vmovbcr_inst* const inst_cream = (vmovbcr_inst*)inst_base->component; |
| 1221 | 1164 | ||
| 1222 | cpu->Reg[inst_cream->t] = cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index]; | 1165 | cpu->Reg[inst_cream->t] = cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index]; |
| 1223 | } | 1166 | } |
| @@ -1246,33 +1189,31 @@ struct vmovbrrss_inst { | |||
| 1246 | }; | 1189 | }; |
| 1247 | #endif | 1190 | #endif |
| 1248 | #ifdef VFP_INTERPRETER_TRANS | 1191 | #ifdef VFP_INTERPRETER_TRANS |
| 1249 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrss)(unsigned int inst, int index) | 1192 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrss)(unsigned int inst, int index) { |
| 1250 | { | 1193 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrrss_inst)); |
| 1251 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrrss_inst)); | 1194 | vmovbrrss_inst* inst_cream = (vmovbrrss_inst*)inst_base->component; |
| 1252 | vmovbrrss_inst *inst_cream = (vmovbrrss_inst *)inst_base->component; | ||
| 1253 | 1195 | ||
| 1254 | inst_base->cond = BITS(inst, 28, 31); | 1196 | inst_base->cond = BITS(inst, 28, 31); |
| 1255 | inst_base->idx = index; | 1197 | inst_base->idx = index; |
| 1256 | inst_base->br = TransExtData::NON_BRANCH; | 1198 | inst_base->br = TransExtData::NON_BRANCH; |
| 1257 | 1199 | ||
| 1258 | inst_cream->to_arm = BIT(inst, 20) == 1; | 1200 | inst_cream->to_arm = BIT(inst, 20) == 1; |
| 1259 | inst_cream->t = BITS(inst, 12, 15); | 1201 | inst_cream->t = BITS(inst, 12, 15); |
| 1260 | inst_cream->t2 = BITS(inst, 16, 19); | 1202 | inst_cream->t2 = BITS(inst, 16, 19); |
| 1261 | inst_cream->m = BITS(inst, 0, 3)<<1|BIT(inst, 5); | 1203 | inst_cream->m = BITS(inst, 0, 3) << 1 | BIT(inst, 5); |
| 1262 | 1204 | ||
| 1263 | return inst_base; | 1205 | return inst_base; |
| 1264 | } | 1206 | } |
| 1265 | #endif | 1207 | #endif |
| 1266 | #ifdef VFP_INTERPRETER_IMPL | 1208 | #ifdef VFP_INTERPRETER_IMPL |
| 1267 | VMOVBRRSS_INST: | 1209 | VMOVBRRSS_INST : { |
| 1268 | { | ||
| 1269 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 1210 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 1270 | CHECK_VFP_ENABLED; | 1211 | CHECK_VFP_ENABLED; |
| 1271 | 1212 | ||
| 1272 | vmovbrrss_inst* const inst_cream = (vmovbrrss_inst*)inst_base->component; | 1213 | vmovbrrss_inst* const inst_cream = (vmovbrrss_inst*)inst_base->component; |
| 1273 | 1214 | ||
| 1274 | VMOVBRRSS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m, | 1215 | VMOVBRRSS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m, |
| 1275 | &cpu->Reg[inst_cream->t], &cpu->Reg[inst_cream->t2]); | 1216 | &cpu->Reg[inst_cream->t], &cpu->Reg[inst_cream->t2]); |
| 1276 | } | 1217 | } |
| 1277 | cpu->Reg[15] += cpu->GetInstructionSize(); | 1218 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1278 | INC_PC(sizeof(vmovbrrss_inst)); | 1219 | INC_PC(sizeof(vmovbrrss_inst)); |
| @@ -1294,33 +1235,31 @@ struct vmovbrrd_inst { | |||
| 1294 | }; | 1235 | }; |
| 1295 | #endif | 1236 | #endif |
| 1296 | #ifdef VFP_INTERPRETER_TRANS | 1237 | #ifdef VFP_INTERPRETER_TRANS |
| 1297 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrd)(unsigned int inst, int index) | 1238 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrd)(unsigned int inst, int index) { |
| 1298 | { | 1239 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrrd_inst)); |
| 1299 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrrd_inst)); | 1240 | vmovbrrd_inst* inst_cream = (vmovbrrd_inst*)inst_base->component; |
| 1300 | vmovbrrd_inst *inst_cream = (vmovbrrd_inst *)inst_base->component; | ||
| 1301 | 1241 | ||
| 1302 | inst_base->cond = BITS(inst, 28, 31); | 1242 | inst_base->cond = BITS(inst, 28, 31); |
| 1303 | inst_base->idx = index; | 1243 | inst_base->idx = index; |
| 1304 | inst_base->br = TransExtData::NON_BRANCH; | 1244 | inst_base->br = TransExtData::NON_BRANCH; |
| 1305 | 1245 | ||
| 1306 | inst_cream->to_arm = BIT(inst, 20) == 1; | 1246 | inst_cream->to_arm = BIT(inst, 20) == 1; |
| 1307 | inst_cream->t = BITS(inst, 12, 15); | 1247 | inst_cream->t = BITS(inst, 12, 15); |
| 1308 | inst_cream->t2 = BITS(inst, 16, 19); | 1248 | inst_cream->t2 = BITS(inst, 16, 19); |
| 1309 | inst_cream->m = BIT(inst, 5)<<4 | BITS(inst, 0, 3); | 1249 | inst_cream->m = BIT(inst, 5) << 4 | BITS(inst, 0, 3); |
| 1310 | 1250 | ||
| 1311 | return inst_base; | 1251 | return inst_base; |
| 1312 | } | 1252 | } |
| 1313 | #endif | 1253 | #endif |
| 1314 | #ifdef VFP_INTERPRETER_IMPL | 1254 | #ifdef VFP_INTERPRETER_IMPL |
| 1315 | VMOVBRRD_INST: | 1255 | VMOVBRRD_INST : { |
| 1316 | { | ||
| 1317 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 1256 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 1318 | CHECK_VFP_ENABLED; | 1257 | CHECK_VFP_ENABLED; |
| 1319 | 1258 | ||
| 1320 | vmovbrrd_inst *inst_cream = (vmovbrrd_inst *)inst_base->component; | 1259 | vmovbrrd_inst* inst_cream = (vmovbrrd_inst*)inst_base->component; |
| 1321 | 1260 | ||
| 1322 | VMOVBRRD(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m, | 1261 | VMOVBRRD(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m, |
| 1323 | &(cpu->Reg[inst_cream->t]), &(cpu->Reg[inst_cream->t2])); | 1262 | &(cpu->Reg[inst_cream->t]), &(cpu->Reg[inst_cream->t2])); |
| 1324 | } | 1263 | } |
| 1325 | cpu->Reg[15] += cpu->GetInstructionSize(); | 1264 | cpu->Reg[15] += cpu->GetInstructionSize(); |
| 1326 | INC_PC(sizeof(vmovbrrd_inst)); | 1265 | INC_PC(sizeof(vmovbrrd_inst)); |
| @@ -1347,43 +1286,40 @@ struct vstr_inst { | |||
| 1347 | }; | 1286 | }; |
| 1348 | #endif | 1287 | #endif |
| 1349 | #ifdef VFP_INTERPRETER_TRANS | 1288 | #ifdef VFP_INTERPRETER_TRANS |
| 1350 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vstr)(unsigned int inst, int index) | 1289 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vstr)(unsigned int inst, int index) { |
| 1351 | { | 1290 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vstr_inst)); |
| 1352 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vstr_inst)); | 1291 | vstr_inst* inst_cream = (vstr_inst*)inst_base->component; |
| 1353 | vstr_inst *inst_cream = (vstr_inst *)inst_base->component; | ||
| 1354 | 1292 | ||
| 1355 | inst_base->cond = BITS(inst, 28, 31); | 1293 | inst_base->cond = BITS(inst, 28, 31); |
| 1356 | inst_base->idx = index; | 1294 | inst_base->idx = index; |
| 1357 | inst_base->br = TransExtData::NON_BRANCH; | 1295 | inst_base->br = TransExtData::NON_BRANCH; |
| 1358 | 1296 | ||
| 1359 | inst_cream->single = BIT(inst, 8) == 0; | 1297 | inst_cream->single = BIT(inst, 8) == 0; |
| 1360 | inst_cream->add = BIT(inst, 23); | 1298 | inst_cream->add = BIT(inst, 23); |
| 1361 | inst_cream->imm32 = BITS(inst, 0,7) << 2; | 1299 | inst_cream->imm32 = BITS(inst, 0, 7) << 2; |
| 1362 | inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4); | 1300 | inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22) |
| 1363 | inst_cream->n = BITS(inst, 16, 19); | 1301 | : BITS(inst, 12, 15) | BIT(inst, 22) << 4); |
| 1302 | inst_cream->n = BITS(inst, 16, 19); | ||
| 1364 | 1303 | ||
| 1365 | return inst_base; | 1304 | return inst_base; |
| 1366 | } | 1305 | } |
| 1367 | #endif | 1306 | #endif |
| 1368 | #ifdef VFP_INTERPRETER_IMPL | 1307 | #ifdef VFP_INTERPRETER_IMPL |
| 1369 | VSTR_INST: | 1308 | VSTR_INST : { |
| 1370 | { | ||
| 1371 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 1309 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 1372 | CHECK_VFP_ENABLED; | 1310 | CHECK_VFP_ENABLED; |
| 1373 | 1311 | ||
| 1374 | vstr_inst *inst_cream = (vstr_inst *)inst_base->component; | 1312 | vstr_inst* inst_cream = (vstr_inst*)inst_base->component; |
| 1375 | 1313 | ||
| 1376 | unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8 : cpu->Reg[inst_cream->n]); | 1314 | unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8 |
| 1315 | : cpu->Reg[inst_cream->n]); | ||
| 1377 | addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32); | 1316 | addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32); |
| 1378 | 1317 | ||
| 1379 | if (inst_cream->single) | 1318 | if (inst_cream->single) { |
| 1380 | { | ||
| 1381 | cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d]); | 1319 | cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d]); |
| 1382 | } | 1320 | } else { |
| 1383 | else | 1321 | const u32 word1 = cpu->ExtReg[inst_cream->d * 2 + 0]; |
| 1384 | { | 1322 | const u32 word2 = cpu->ExtReg[inst_cream->d * 2 + 1]; |
| 1385 | const u32 word1 = cpu->ExtReg[inst_cream->d*2+0]; | ||
| 1386 | const u32 word2 = cpu->ExtReg[inst_cream->d*2+1]; | ||
| 1387 | 1323 | ||
| 1388 | if (cpu->InBigEndianMode()) { | 1324 | if (cpu->InBigEndianMode()) { |
| 1389 | cpu->WriteMemory32(addr + 0, word2); | 1325 | cpu->WriteMemory32(addr + 0, word2); |
| @@ -1413,44 +1349,39 @@ struct vpush_inst { | |||
| 1413 | }; | 1349 | }; |
| 1414 | #endif | 1350 | #endif |
| 1415 | #ifdef VFP_INTERPRETER_TRANS | 1351 | #ifdef VFP_INTERPRETER_TRANS |
| 1416 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vpush)(unsigned int inst, int index) | 1352 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vpush)(unsigned int inst, int index) { |
| 1417 | { | 1353 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vpush_inst)); |
| 1418 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vpush_inst)); | 1354 | vpush_inst* inst_cream = (vpush_inst*)inst_base->component; |
| 1419 | vpush_inst *inst_cream = (vpush_inst *)inst_base->component; | ||
| 1420 | 1355 | ||
| 1421 | inst_base->cond = BITS(inst, 28, 31); | 1356 | inst_base->cond = BITS(inst, 28, 31); |
| 1422 | inst_base->idx = index; | 1357 | inst_base->idx = index; |
| 1423 | inst_base->br = TransExtData::NON_BRANCH; | 1358 | inst_base->br = TransExtData::NON_BRANCH; |
| 1424 | 1359 | ||
| 1425 | inst_cream->single = BIT(inst, 8) == 0; | 1360 | inst_cream->single = BIT(inst, 8) == 0; |
| 1426 | inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4); | 1361 | inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22) |
| 1427 | inst_cream->imm32 = BITS(inst, 0, 7)<<2; | 1362 | : BITS(inst, 12, 15) | BIT(inst, 22) << 4); |
| 1428 | inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7)); | 1363 | inst_cream->imm32 = BITS(inst, 0, 7) << 2; |
| 1364 | inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7)); | ||
| 1429 | 1365 | ||
| 1430 | return inst_base; | 1366 | return inst_base; |
| 1431 | } | 1367 | } |
| 1432 | #endif | 1368 | #endif |
| 1433 | #ifdef VFP_INTERPRETER_IMPL | 1369 | #ifdef VFP_INTERPRETER_IMPL |
| 1434 | VPUSH_INST: | 1370 | VPUSH_INST : { |
| 1435 | { | ||
| 1436 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 1371 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 1437 | CHECK_VFP_ENABLED; | 1372 | CHECK_VFP_ENABLED; |
| 1438 | 1373 | ||
| 1439 | vpush_inst *inst_cream = (vpush_inst *)inst_base->component; | 1374 | vpush_inst* inst_cream = (vpush_inst*)inst_base->component; |
| 1440 | 1375 | ||
| 1441 | addr = cpu->Reg[R13] - inst_cream->imm32; | 1376 | addr = cpu->Reg[R13] - inst_cream->imm32; |
| 1442 | 1377 | ||
| 1443 | for (unsigned int i = 0; i < inst_cream->regs; i++) | 1378 | for (unsigned int i = 0; i < inst_cream->regs; i++) { |
| 1444 | { | 1379 | if (inst_cream->single) { |
| 1445 | if (inst_cream->single) | 1380 | cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d + i]); |
| 1446 | { | ||
| 1447 | cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d+i]); | ||
| 1448 | addr += 4; | 1381 | addr += 4; |
| 1449 | } | 1382 | } else { |
| 1450 | else | 1383 | const u32 word1 = cpu->ExtReg[(inst_cream->d + i) * 2 + 0]; |
| 1451 | { | 1384 | const u32 word2 = cpu->ExtReg[(inst_cream->d + i) * 2 + 1]; |
| 1452 | const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0]; | ||
| 1453 | const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1]; | ||
| 1454 | 1385 | ||
| 1455 | if (cpu->InBigEndianMode()) { | 1386 | if (cpu->InBigEndianMode()) { |
| 1456 | cpu->WriteMemory32(addr + 0, word2); | 1387 | cpu->WriteMemory32(addr + 0, word2); |
| @@ -1488,28 +1419,28 @@ struct vstm_inst { | |||
| 1488 | }; | 1419 | }; |
| 1489 | #endif | 1420 | #endif |
| 1490 | #ifdef VFP_INTERPRETER_TRANS | 1421 | #ifdef VFP_INTERPRETER_TRANS |
| 1491 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vstm)(unsigned int inst, int index) | 1422 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vstm)(unsigned int inst, int index) { |
| 1492 | { | 1423 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vstm_inst)); |
| 1493 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vstm_inst)); | 1424 | vstm_inst* inst_cream = (vstm_inst*)inst_base->component; |
| 1494 | vstm_inst *inst_cream = (vstm_inst *)inst_base->component; | ||
| 1495 | 1425 | ||
| 1496 | inst_base->cond = BITS(inst, 28, 31); | 1426 | inst_base->cond = BITS(inst, 28, 31); |
| 1497 | inst_base->idx = index; | 1427 | inst_base->idx = index; |
| 1498 | inst_base->br = TransExtData::NON_BRANCH; | 1428 | inst_base->br = TransExtData::NON_BRANCH; |
| 1499 | 1429 | ||
| 1500 | inst_cream->single = BIT(inst, 8) == 0; | 1430 | inst_cream->single = BIT(inst, 8) == 0; |
| 1501 | inst_cream->add = BIT(inst, 23); | 1431 | inst_cream->add = BIT(inst, 23); |
| 1502 | inst_cream->wback = BIT(inst, 21); | 1432 | inst_cream->wback = BIT(inst, 21); |
| 1503 | inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4); | 1433 | inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22) |
| 1504 | inst_cream->n = BITS(inst, 16, 19); | 1434 | : BITS(inst, 12, 15) | BIT(inst, 22) << 4); |
| 1505 | inst_cream->imm32 = BITS(inst, 0, 7)<<2; | 1435 | inst_cream->n = BITS(inst, 16, 19); |
| 1506 | inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7)); | 1436 | inst_cream->imm32 = BITS(inst, 0, 7) << 2; |
| 1437 | inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7)); | ||
| 1507 | 1438 | ||
| 1508 | return inst_base; | 1439 | return inst_base; |
| 1509 | } | 1440 | } |
| 1510 | #endif | 1441 | #endif |
| 1511 | #ifdef VFP_INTERPRETER_IMPL | 1442 | #ifdef VFP_INTERPRETER_IMPL |
| 1512 | VSTM_INST: /* encoding 1 */ | 1443 | VSTM_INST : /* encoding 1 */ |
| 1513 | { | 1444 | { |
| 1514 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 1445 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 1515 | CHECK_VFP_ENABLED; | 1446 | CHECK_VFP_ENABLED; |
| @@ -1525,17 +1456,13 @@ VSTM_INST: /* encoding 1 */ | |||
| 1525 | if (inst_cream->add == 0) | 1456 | if (inst_cream->add == 0) |
| 1526 | address -= inst_cream->imm32; | 1457 | address -= inst_cream->imm32; |
| 1527 | 1458 | ||
| 1528 | for (unsigned int i = 0; i < inst_cream->regs; i++) | 1459 | for (unsigned int i = 0; i < inst_cream->regs; i++) { |
| 1529 | { | 1460 | if (inst_cream->single) { |
| 1530 | if (inst_cream->single) | 1461 | cpu->WriteMemory32(address, cpu->ExtReg[inst_cream->d + i]); |
| 1531 | { | ||
| 1532 | cpu->WriteMemory32(address, cpu->ExtReg[inst_cream->d+i]); | ||
| 1533 | address += 4; | 1462 | address += 4; |
| 1534 | } | 1463 | } else { |
| 1535 | else | 1464 | const u32 word1 = cpu->ExtReg[(inst_cream->d + i) * 2 + 0]; |
| 1536 | { | 1465 | const u32 word2 = cpu->ExtReg[(inst_cream->d + i) * 2 + 1]; |
| 1537 | const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0]; | ||
| 1538 | const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1]; | ||
| 1539 | 1466 | ||
| 1540 | if (cpu->InBigEndianMode()) { | 1467 | if (cpu->InBigEndianMode()) { |
| 1541 | cpu->WriteMemory32(address + 0, word2); | 1468 | cpu->WriteMemory32(address + 0, word2); |
| @@ -1549,8 +1476,9 @@ VSTM_INST: /* encoding 1 */ | |||
| 1549 | } | 1476 | } |
| 1550 | } | 1477 | } |
| 1551 | if (inst_cream->wback) { | 1478 | if (inst_cream->wback) { |
| 1552 | cpu->Reg[inst_cream->n] = (inst_cream->add ? cpu->Reg[inst_cream->n] + inst_cream->imm32 : | 1479 | cpu->Reg[inst_cream->n] = |
| 1553 | cpu->Reg[inst_cream->n] - inst_cream->imm32); | 1480 | (inst_cream->add ? cpu->Reg[inst_cream->n] + inst_cream->imm32 |
| 1481 | : cpu->Reg[inst_cream->n] - inst_cream->imm32); | ||
| 1554 | } | 1482 | } |
| 1555 | } | 1483 | } |
| 1556 | cpu->Reg[15] += 4; | 1484 | cpu->Reg[15] += 4; |
| @@ -1573,51 +1501,46 @@ struct vpop_inst { | |||
| 1573 | }; | 1501 | }; |
| 1574 | #endif | 1502 | #endif |
| 1575 | #ifdef VFP_INTERPRETER_TRANS | 1503 | #ifdef VFP_INTERPRETER_TRANS |
| 1576 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vpop)(unsigned int inst, int index) | 1504 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vpop)(unsigned int inst, int index) { |
| 1577 | { | 1505 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vpop_inst)); |
| 1578 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vpop_inst)); | 1506 | vpop_inst* inst_cream = (vpop_inst*)inst_base->component; |
| 1579 | vpop_inst *inst_cream = (vpop_inst *)inst_base->component; | ||
| 1580 | 1507 | ||
| 1581 | inst_base->cond = BITS(inst, 28, 31); | 1508 | inst_base->cond = BITS(inst, 28, 31); |
| 1582 | inst_base->idx = index; | 1509 | inst_base->idx = index; |
| 1583 | inst_base->br = TransExtData::NON_BRANCH; | 1510 | inst_base->br = TransExtData::NON_BRANCH; |
| 1584 | 1511 | ||
| 1585 | inst_cream->single = BIT(inst, 8) == 0; | 1512 | inst_cream->single = BIT(inst, 8) == 0; |
| 1586 | inst_cream->d = (inst_cream->single ? (BITS(inst, 12, 15)<<1)|BIT(inst, 22) : BITS(inst, 12, 15)|(BIT(inst, 22)<<4)); | 1513 | inst_cream->d = (inst_cream->single ? (BITS(inst, 12, 15) << 1) | BIT(inst, 22) |
| 1587 | inst_cream->imm32 = BITS(inst, 0, 7)<<2; | 1514 | : BITS(inst, 12, 15) | (BIT(inst, 22) << 4)); |
| 1588 | inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7)); | 1515 | inst_cream->imm32 = BITS(inst, 0, 7) << 2; |
| 1516 | inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7)); | ||
| 1589 | 1517 | ||
| 1590 | return inst_base; | 1518 | return inst_base; |
| 1591 | } | 1519 | } |
| 1592 | #endif | 1520 | #endif |
| 1593 | #ifdef VFP_INTERPRETER_IMPL | 1521 | #ifdef VFP_INTERPRETER_IMPL |
| 1594 | VPOP_INST: | 1522 | VPOP_INST : { |
| 1595 | { | ||
| 1596 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 1523 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 1597 | CHECK_VFP_ENABLED; | 1524 | CHECK_VFP_ENABLED; |
| 1598 | 1525 | ||
| 1599 | vpop_inst *inst_cream = (vpop_inst *)inst_base->component; | 1526 | vpop_inst* inst_cream = (vpop_inst*)inst_base->component; |
| 1600 | 1527 | ||
| 1601 | addr = cpu->Reg[R13]; | 1528 | addr = cpu->Reg[R13]; |
| 1602 | 1529 | ||
| 1603 | for (unsigned int i = 0; i < inst_cream->regs; i++) | 1530 | for (unsigned int i = 0; i < inst_cream->regs; i++) { |
| 1604 | { | 1531 | if (inst_cream->single) { |
| 1605 | if (inst_cream->single) | 1532 | cpu->ExtReg[inst_cream->d + i] = cpu->ReadMemory32(addr); |
| 1606 | { | ||
| 1607 | cpu->ExtReg[inst_cream->d+i] = cpu->ReadMemory32(addr); | ||
| 1608 | addr += 4; | 1533 | addr += 4; |
| 1609 | } | 1534 | } else { |
| 1610 | else | ||
| 1611 | { | ||
| 1612 | const u32 word1 = cpu->ReadMemory32(addr + 0); | 1535 | const u32 word1 = cpu->ReadMemory32(addr + 0); |
| 1613 | const u32 word2 = cpu->ReadMemory32(addr + 4); | 1536 | const u32 word2 = cpu->ReadMemory32(addr + 4); |
| 1614 | 1537 | ||
| 1615 | if (cpu->InBigEndianMode()) { | 1538 | if (cpu->InBigEndianMode()) { |
| 1616 | cpu->ExtReg[(inst_cream->d+i)*2+0] = word2; | 1539 | cpu->ExtReg[(inst_cream->d + i) * 2 + 0] = word2; |
| 1617 | cpu->ExtReg[(inst_cream->d+i)*2+1] = word1; | 1540 | cpu->ExtReg[(inst_cream->d + i) * 2 + 1] = word1; |
| 1618 | } else { | 1541 | } else { |
| 1619 | cpu->ExtReg[(inst_cream->d+i)*2+0] = word1; | 1542 | cpu->ExtReg[(inst_cream->d + i) * 2 + 0] = word1; |
| 1620 | cpu->ExtReg[(inst_cream->d+i)*2+1] = word2; | 1543 | cpu->ExtReg[(inst_cream->d + i) * 2 + 1] = word2; |
| 1621 | } | 1544 | } |
| 1622 | 1545 | ||
| 1623 | addr += 8; | 1546 | addr += 8; |
| @@ -1632,7 +1555,6 @@ VPOP_INST: | |||
| 1632 | } | 1555 | } |
| 1633 | #endif | 1556 | #endif |
| 1634 | 1557 | ||
| 1635 | |||
| 1636 | /* ----------------------------------------------------------------------- */ | 1558 | /* ----------------------------------------------------------------------- */ |
| 1637 | /* VLDR */ | 1559 | /* VLDR */ |
| 1638 | /* cond 1101 UD01 Rn-- Vd-- 101X imm8 imm8 */ | 1560 | /* cond 1101 UD01 Rn-- Vd-- 101X imm8 imm8 */ |
| @@ -1646,50 +1568,47 @@ struct vldr_inst { | |||
| 1646 | }; | 1568 | }; |
| 1647 | #endif | 1569 | #endif |
| 1648 | #ifdef VFP_INTERPRETER_TRANS | 1570 | #ifdef VFP_INTERPRETER_TRANS |
| 1649 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vldr)(unsigned int inst, int index) | 1571 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vldr)(unsigned int inst, int index) { |
| 1650 | { | 1572 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vldr_inst)); |
| 1651 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vldr_inst)); | 1573 | vldr_inst* inst_cream = (vldr_inst*)inst_base->component; |
| 1652 | vldr_inst *inst_cream = (vldr_inst *)inst_base->component; | ||
| 1653 | 1574 | ||
| 1654 | inst_base->cond = BITS(inst, 28, 31); | 1575 | inst_base->cond = BITS(inst, 28, 31); |
| 1655 | inst_base->idx = index; | 1576 | inst_base->idx = index; |
| 1656 | inst_base->br = TransExtData::NON_BRANCH; | 1577 | inst_base->br = TransExtData::NON_BRANCH; |
| 1657 | 1578 | ||
| 1658 | inst_cream->single = BIT(inst, 8) == 0; | 1579 | inst_cream->single = BIT(inst, 8) == 0; |
| 1659 | inst_cream->add = BIT(inst, 23); | 1580 | inst_cream->add = BIT(inst, 23); |
| 1660 | inst_cream->imm32 = BITS(inst, 0,7) << 2; | 1581 | inst_cream->imm32 = BITS(inst, 0, 7) << 2; |
| 1661 | inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4); | 1582 | inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22) |
| 1662 | inst_cream->n = BITS(inst, 16, 19); | 1583 | : BITS(inst, 12, 15) | BIT(inst, 22) << 4); |
| 1584 | inst_cream->n = BITS(inst, 16, 19); | ||
| 1663 | 1585 | ||
| 1664 | return inst_base; | 1586 | return inst_base; |
| 1665 | } | 1587 | } |
| 1666 | #endif | 1588 | #endif |
| 1667 | #ifdef VFP_INTERPRETER_IMPL | 1589 | #ifdef VFP_INTERPRETER_IMPL |
| 1668 | VLDR_INST: | 1590 | VLDR_INST : { |
| 1669 | { | ||
| 1670 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { | 1591 | if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { |
| 1671 | CHECK_VFP_ENABLED; | 1592 | CHECK_VFP_ENABLED; |
| 1672 | 1593 | ||
| 1673 | vldr_inst *inst_cream = (vldr_inst *)inst_base->component; | 1594 | vldr_inst* inst_cream = (vldr_inst*)inst_base->component; |
| 1674 | 1595 | ||
| 1675 | unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8 : cpu->Reg[inst_cream->n]); | 1596 | unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8 |
| 1597 | : cpu->Reg[inst_cream->n]); | ||
| 1676 | addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32); | 1598 | addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32); |
| 1677 | 1599 | ||
| 1678 | if (inst_cream->single) | 1600 | if (inst_cream->single) { |
| 1679 | { | ||
| 1680 | cpu->ExtReg[inst_cream->d] = cpu->ReadMemory32(addr); | 1601 | cpu->ExtReg[inst_cream->d] = cpu->ReadMemory32(addr); |
| 1681 | } | 1602 | } else { |
| 1682 | else | ||
| 1683 | { | ||
| 1684 | const u32 word1 = cpu->ReadMemory32(addr + 0); | 1603 | const u32 word1 = cpu->ReadMemory32(addr + 0); |
| 1685 | const u32 word2 = cpu->ReadMemory32(addr + 4); | 1604 | const u32 word2 = cpu->ReadMemory32(addr + 4); |
| 1686 | 1605 | ||
| 1687 | if (cpu->InBigEndianMode()) { | 1606 | if (cpu->InBigEndianMode()) { |
| 1688 | cpu->ExtReg[inst_cream->d*2+0] = word2; | 1607 | cpu->ExtReg[inst_cream->d * 2 + 0] = word2; |
| 1689 | cpu->ExtReg[inst_cream->d*2+1] = word1; | 1608 | cpu->ExtReg[inst_cream->d * 2 + 1] = word1; |
| 1690 | } else { | 1609 | } else { |
| 1691 | cpu->ExtReg[inst_cream->d*2+0] = word1; | 1610 | cpu->ExtReg[inst_cream->d * 2 + 0] = word1; |
| 1692 | cpu->ExtReg[inst_cream->d*2+1] = word2; | 1611 | cpu->ExtReg[inst_cream->d * 2 + 1] = word2; |
| 1693 | } | 1612 | } |
| 1694 | } | 1613 | } |
| 1695 | } | 1614 | } |
| @@ -1715,29 +1634,28 @@ struct vldm_inst { | |||
| 1715 | }; | 1634 | }; |
| 1716 | #endif | 1635 | #endif |
| 1717 | #ifdef VFP_INTERPRETER_TRANS | 1636 | #ifdef VFP_INTERPRETER_TRANS |
| 1718 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vldm)(unsigned int inst, int index) | 1637 | static ARM_INST_PTR INTERPRETER_TRANSLATE(vldm)(unsigned int inst, int index) { |
| 1719 | { | 1638 | arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vldm_inst)); |
| 1720 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vldm_inst)); | 1639 | vldm_inst* inst_cream = (vldm_inst*)inst_base->component; |
| 1721 | vldm_inst *inst_cream = (vldm_inst *)inst_base->component; | ||
| 1722 | 1640 | ||
| 1723 | inst_base->cond = BITS(inst, 28, 31); | 1641 | inst_base->cond = BITS(inst, 28, 31); |
| 1724 | inst_base->idx = index; | 1642 | inst_base->idx = index; |
| 1725 | inst_base->br = TransExtData::NON_BRANCH; | 1643 | inst_base->br = TransExtData::NON_BRANCH; |
| 1726 | 1644 | ||
| 1727 | inst_cream->single = BIT(inst, 8) == 0; | 1645 | inst_cream->single = BIT(inst, 8) == 0; |
| 1728 | inst_cream->add = BIT(inst, 23); | 1646 | inst_cream->add = BIT(inst, 23); |
| 1729 | inst_cream->wback = BIT(inst, 21); | 1647 | inst_cream->wback = BIT(inst, 21); |
| 1730 | inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4); | 1648 | inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22) |
| 1731 | inst_cream->n = BITS(inst, 16, 19); | 1649 | : BITS(inst, 12, 15) | BIT(inst, 22) << 4); |
| 1732 | inst_cream->imm32 = BITS(inst, 0, 7)<<2; | 1650 | inst_cream->n = BITS(inst, 16, 19); |
| 1733 | inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7)); | 1651 | inst_cream->imm32 = BITS(inst, 0, 7) << 2; |
| 1652 | inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7)); | ||
| 1734 | 1653 | ||
| 1735 | return inst_base; | 1654 | return inst_base; |
| 1736 | } | 1655 | } |
| 1737 | #endif | 1656 | #endif |
| 1738 | #ifdef VFP_INTERPRETER_IMPL | 1657 | #ifdef VFP_INTERPRETER_IMPL |
| 1739 | VLDM_INST: | 1658 | VLDM_INST : { |
| 1740 | { | ||
| 1741 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { | 1659 | if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { |
| 1742 | CHECK_VFP_ENABLED; | 1660 | CHECK_VFP_ENABLED; |
| 1743 | 1661 | ||
| @@ -1752,32 +1670,29 @@ VLDM_INST: | |||
| 1752 | if (inst_cream->add == 0) | 1670 | if (inst_cream->add == 0) |
| 1753 | address -= inst_cream->imm32; | 1671 | address -= inst_cream->imm32; |
| 1754 | 1672 | ||
| 1755 | for (unsigned int i = 0; i < inst_cream->regs; i++) | 1673 | for (unsigned int i = 0; i < inst_cream->regs; i++) { |
| 1756 | { | 1674 | if (inst_cream->single) { |
| 1757 | if (inst_cream->single) | 1675 | cpu->ExtReg[inst_cream->d + i] = cpu->ReadMemory32(address); |
| 1758 | { | ||
| 1759 | cpu->ExtReg[inst_cream->d+i] = cpu->ReadMemory32(address); | ||
| 1760 | address += 4; | 1676 | address += 4; |
| 1761 | } | 1677 | } else { |
| 1762 | else | ||
| 1763 | { | ||
| 1764 | const u32 word1 = cpu->ReadMemory32(address + 0); | 1678 | const u32 word1 = cpu->ReadMemory32(address + 0); |
| 1765 | const u32 word2 = cpu->ReadMemory32(address + 4); | 1679 | const u32 word2 = cpu->ReadMemory32(address + 4); |
| 1766 | 1680 | ||
| 1767 | if (cpu->InBigEndianMode()) { | 1681 | if (cpu->InBigEndianMode()) { |
| 1768 | cpu->ExtReg[(inst_cream->d+i)*2+0] = word2; | 1682 | cpu->ExtReg[(inst_cream->d + i) * 2 + 0] = word2; |
| 1769 | cpu->ExtReg[(inst_cream->d+i)*2+1] = word1; | 1683 | cpu->ExtReg[(inst_cream->d + i) * 2 + 1] = word1; |
| 1770 | } else { | 1684 | } else { |
| 1771 | cpu->ExtReg[(inst_cream->d+i)*2+0] = word1; | 1685 | cpu->ExtReg[(inst_cream->d + i) * 2 + 0] = word1; |
| 1772 | cpu->ExtReg[(inst_cream->d+i)*2+1] = word2; | 1686 | cpu->ExtReg[(inst_cream->d + i) * 2 + 1] = word2; |
| 1773 | } | 1687 | } |
| 1774 | 1688 | ||
| 1775 | address += 8; | 1689 | address += 8; |
| 1776 | } | 1690 | } |
| 1777 | } | 1691 | } |
| 1778 | if (inst_cream->wback) { | 1692 | if (inst_cream->wback) { |
| 1779 | cpu->Reg[inst_cream->n] = (inst_cream->add ? cpu->Reg[inst_cream->n] + inst_cream->imm32 : | 1693 | cpu->Reg[inst_cream->n] = |
| 1780 | cpu->Reg[inst_cream->n] - inst_cream->imm32); | 1694 | (inst_cream->add ? cpu->Reg[inst_cream->n] + inst_cream->imm32 |
| 1695 | : cpu->Reg[inst_cream->n] - inst_cream->imm32); | ||
| 1781 | } | 1696 | } |
| 1782 | } | 1697 | } |
| 1783 | cpu->Reg[15] += cpu->GetInstructionSize(); | 1698 | cpu->Reg[15] += cpu->GetInstructionSize(); |
diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp index 60264f9b3..3c21efe62 100644 --- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp | |||
| @@ -58,24 +58,20 @@ | |||
| 58 | #include "common/common_types.h" | 58 | #include "common/common_types.h" |
| 59 | #include "common/logging/log.h" | 59 | #include "common/logging/log.h" |
| 60 | 60 | ||
| 61 | #include "core/arm/skyeye_common/vfp/vfp_helper.h" | ||
| 62 | #include "core/arm/skyeye_common/vfp/asm_vfp.h" | 61 | #include "core/arm/skyeye_common/vfp/asm_vfp.h" |
| 63 | #include "core/arm/skyeye_common/vfp/vfp.h" | 62 | #include "core/arm/skyeye_common/vfp/vfp.h" |
| 63 | #include "core/arm/skyeye_common/vfp/vfp_helper.h" | ||
| 64 | 64 | ||
| 65 | static struct vfp_single vfp_single_default_qnan = { | 65 | static struct vfp_single vfp_single_default_qnan = { |
| 66 | 255, | 66 | 255, 0, VFP_SINGLE_SIGNIFICAND_QNAN, |
| 67 | 0, | ||
| 68 | VFP_SINGLE_SIGNIFICAND_QNAN, | ||
| 69 | }; | 67 | }; |
| 70 | 68 | ||
| 71 | static void vfp_single_dump(const char *str, struct vfp_single *s) | 69 | static void vfp_single_dump(const char* str, struct vfp_single* s) { |
| 72 | { | 70 | LOG_TRACE(Core_ARM11, "%s: sign=%d exponent=%d significand=%08x", str, s->sign != 0, |
| 73 | LOG_TRACE(Core_ARM11, "%s: sign=%d exponent=%d significand=%08x", | 71 | s->exponent, s->significand); |
| 74 | str, s->sign != 0, s->exponent, s->significand); | ||
| 75 | } | 72 | } |
| 76 | 73 | ||
| 77 | static void vfp_single_normalise_denormal(struct vfp_single *vs) | 74 | static void vfp_single_normalise_denormal(struct vfp_single* vs) { |
| 78 | { | ||
| 79 | int bits = 31 - fls(vs->significand); | 75 | int bits = 31 - fls(vs->significand); |
| 80 | 76 | ||
| 81 | vfp_single_dump("normalise_denormal: in", vs); | 77 | vfp_single_dump("normalise_denormal: in", vs); |
| @@ -88,9 +84,8 @@ static void vfp_single_normalise_denormal(struct vfp_single *vs) | |||
| 88 | vfp_single_dump("normalise_denormal: out", vs); | 84 | vfp_single_dump("normalise_denormal: out", vs); |
| 89 | } | 85 | } |
| 90 | 86 | ||
| 91 | 87 | u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single* vs, u32 fpscr, | |
| 92 | u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs, u32 fpscr, const char *func) | 88 | const char* func) { |
| 93 | { | ||
| 94 | u32 significand, incr, rmode; | 89 | u32 significand, incr, rmode; |
| 95 | int exponent, shift, underflow; | 90 | int exponent, shift, underflow; |
| 96 | u32 exceptions = 0; | 91 | u32 exceptions = 0; |
| @@ -199,7 +194,7 @@ u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs, | |||
| 199 | vs->exponent = 253; | 194 | vs->exponent = 253; |
| 200 | vs->significand = 0x7fffffff; | 195 | vs->significand = 0x7fffffff; |
| 201 | } else { | 196 | } else { |
| 202 | vs->exponent = 255; /* infinity */ | 197 | vs->exponent = 255; /* infinity */ |
| 203 | vs->significand = 0; | 198 | vs->significand = 0; |
| 204 | } | 199 | } |
| 205 | } else { | 200 | } else { |
| @@ -217,8 +212,7 @@ pack: | |||
| 217 | vfp_single_dump("pack: final", vs); | 212 | vfp_single_dump("pack: final", vs); |
| 218 | { | 213 | { |
| 219 | s32 d = vfp_single_pack(vs); | 214 | s32 d = vfp_single_pack(vs); |
| 220 | LOG_TRACE(Core_ARM11, "%s: d(s%d)=%08x exceptions=%08x", func, | 215 | LOG_TRACE(Core_ARM11, "%s: d(s%d)=%08x exceptions=%08x", func, sd, d, exceptions); |
| 221 | sd, d, exceptions); | ||
| 222 | vfp_put_float(state, d, sd); | 216 | vfp_put_float(state, d, sd); |
| 223 | } | 217 | } |
| 224 | 218 | ||
| @@ -229,11 +223,9 @@ pack: | |||
| 229 | * Propagate the NaN, setting exceptions if it is signalling. | 223 | * Propagate the NaN, setting exceptions if it is signalling. |
| 230 | * 'n' is always a NaN. 'm' may be a number, NaN or infinity. | 224 | * 'n' is always a NaN. 'm' may be a number, NaN or infinity. |
| 231 | */ | 225 | */ |
| 232 | static u32 | 226 | static u32 vfp_propagate_nan(struct vfp_single* vsd, struct vfp_single* vsn, struct vfp_single* vsm, |
| 233 | vfp_propagate_nan(struct vfp_single *vsd, struct vfp_single *vsn, | 227 | u32 fpscr) { |
| 234 | struct vfp_single *vsm, u32 fpscr) | 228 | struct vfp_single* nan; |
| 235 | { | ||
| 236 | struct vfp_single *nan; | ||
| 237 | int tn, tm = 0; | 229 | int tn, tm = 0; |
| 238 | 230 | ||
| 239 | tn = vfp_single_type(vsn); | 231 | tn = vfp_single_type(vsn); |
| @@ -270,40 +262,33 @@ vfp_propagate_nan(struct vfp_single *vsd, struct vfp_single *vsn, | |||
| 270 | return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : VFP_NAN_FLAG; | 262 | return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : VFP_NAN_FLAG; |
| 271 | } | 263 | } |
| 272 | 264 | ||
| 273 | |||
| 274 | /* | 265 | /* |
| 275 | * Extended operations | 266 | * Extended operations |
| 276 | */ | 267 | */ |
| 277 | static u32 vfp_single_fabs(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) | 268 | static u32 vfp_single_fabs(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { |
| 278 | { | ||
| 279 | vfp_put_float(state, vfp_single_packed_abs(m), sd); | 269 | vfp_put_float(state, vfp_single_packed_abs(m), sd); |
| 280 | return 0; | 270 | return 0; |
| 281 | } | 271 | } |
| 282 | 272 | ||
| 283 | static u32 vfp_single_fcpy(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) | 273 | static u32 vfp_single_fcpy(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { |
| 284 | { | ||
| 285 | vfp_put_float(state, m, sd); | 274 | vfp_put_float(state, m, sd); |
| 286 | return 0; | 275 | return 0; |
| 287 | } | 276 | } |
| 288 | 277 | ||
| 289 | static u32 vfp_single_fneg(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) | 278 | static u32 vfp_single_fneg(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { |
| 290 | { | ||
| 291 | vfp_put_float(state, vfp_single_packed_negate(m), sd); | 279 | vfp_put_float(state, vfp_single_packed_negate(m), sd); |
| 292 | return 0; | 280 | return 0; |
| 293 | } | 281 | } |
| 294 | 282 | ||
| 295 | static const u16 sqrt_oddadjust[] = { | 283 | static const u16 sqrt_oddadjust[] = {0x0004, 0x0022, 0x005d, 0x00b1, 0x011d, 0x019f, |
| 296 | 0x0004, 0x0022, 0x005d, 0x00b1, 0x011d, 0x019f, 0x0236, 0x02e0, | 284 | 0x0236, 0x02e0, 0x039c, 0x0468, 0x0545, 0x0631, |
| 297 | 0x039c, 0x0468, 0x0545, 0x0631, 0x072b, 0x0832, 0x0946, 0x0a67 | 285 | 0x072b, 0x0832, 0x0946, 0x0a67}; |
| 298 | }; | ||
| 299 | 286 | ||
| 300 | static const u16 sqrt_evenadjust[] = { | 287 | static const u16 sqrt_evenadjust[] = {0x0a2d, 0x08af, 0x075a, 0x0629, 0x051a, 0x0429, |
| 301 | 0x0a2d, 0x08af, 0x075a, 0x0629, 0x051a, 0x0429, 0x0356, 0x029e, | 288 | 0x0356, 0x029e, 0x0200, 0x0179, 0x0109, 0x00af, |
| 302 | 0x0200, 0x0179, 0x0109, 0x00af, 0x0068, 0x0034, 0x0012, 0x0002 | 289 | 0x0068, 0x0034, 0x0012, 0x0002}; |
| 303 | }; | ||
| 304 | 290 | ||
| 305 | u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand) | 291 | u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand) { |
| 306 | { | ||
| 307 | int index; | 292 | int index; |
| 308 | u32 z, a; | 293 | u32 z, a; |
| 309 | 294 | ||
| @@ -331,25 +316,24 @@ u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand) | |||
| 331 | } | 316 | } |
| 332 | } | 317 | } |
| 333 | 318 | ||
| 334 | static u32 vfp_single_fsqrt(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) | 319 | static u32 vfp_single_fsqrt(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { |
| 335 | { | ||
| 336 | struct vfp_single vsm, vsd, *vsp; | 320 | struct vfp_single vsm, vsd, *vsp; |
| 337 | int ret, tm; | 321 | int ret, tm; |
| 338 | u32 exceptions = 0; | 322 | u32 exceptions = 0; |
| 339 | 323 | ||
| 340 | exceptions |= vfp_single_unpack(&vsm, m, fpscr); | 324 | exceptions |= vfp_single_unpack(&vsm, m, fpscr); |
| 341 | tm = vfp_single_type(&vsm); | 325 | tm = vfp_single_type(&vsm); |
| 342 | if (tm & (VFP_NAN|VFP_INFINITY)) { | 326 | if (tm & (VFP_NAN | VFP_INFINITY)) { |
| 343 | vsp = &vsd; | 327 | vsp = &vsd; |
| 344 | 328 | ||
| 345 | if (tm & VFP_NAN) | 329 | if (tm & VFP_NAN) |
| 346 | ret = vfp_propagate_nan(vsp, &vsm, nullptr, fpscr); | 330 | ret = vfp_propagate_nan(vsp, &vsm, nullptr, fpscr); |
| 347 | else if (vsm.sign == 0) { | 331 | else if (vsm.sign == 0) { |
| 348 | sqrt_copy: | 332 | sqrt_copy: |
| 349 | vsp = &vsm; | 333 | vsp = &vsm; |
| 350 | ret = 0; | 334 | ret = 0; |
| 351 | } else { | 335 | } else { |
| 352 | sqrt_invalid: | 336 | sqrt_invalid: |
| 353 | vsp = &vfp_single_default_qnan; | 337 | vsp = &vfp_single_default_qnan; |
| 354 | ret = FPSCR_IOC; | 338 | ret = FPSCR_IOC; |
| 355 | } | 339 | } |
| @@ -420,15 +404,15 @@ sqrt_invalid: | |||
| 420 | * Greater than := C | 404 | * Greater than := C |
| 421 | * Unordered := CV | 405 | * Unordered := CV |
| 422 | */ | 406 | */ |
| 423 | static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u32 fpscr) | 407 | static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u32 fpscr) { |
| 424 | { | ||
| 425 | s32 d; | 408 | s32 d; |
| 426 | u32 ret = 0; | 409 | u32 ret = 0; |
| 427 | 410 | ||
| 428 | d = vfp_get_float(state, sd); | 411 | d = vfp_get_float(state, sd); |
| 429 | if (vfp_single_packed_exponent(m) == 255 && vfp_single_packed_mantissa(m)) { | 412 | if (vfp_single_packed_exponent(m) == 255 && vfp_single_packed_mantissa(m)) { |
| 430 | ret |= FPSCR_CFLAG | FPSCR_VFLAG; | 413 | ret |= FPSCR_CFLAG | FPSCR_VFLAG; |
| 431 | if (signal_on_qnan || !(vfp_single_packed_mantissa(m) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1)))) | 414 | if (signal_on_qnan || |
| 415 | !(vfp_single_packed_mantissa(m) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1)))) | ||
| 432 | /* | 416 | /* |
| 433 | * Signalling NaN, or signalling on quiet NaN | 417 | * Signalling NaN, or signalling on quiet NaN |
| 434 | */ | 418 | */ |
| @@ -437,7 +421,8 @@ static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u3 | |||
| 437 | 421 | ||
| 438 | if (vfp_single_packed_exponent(d) == 255 && vfp_single_packed_mantissa(d)) { | 422 | if (vfp_single_packed_exponent(d) == 255 && vfp_single_packed_mantissa(d)) { |
| 439 | ret |= FPSCR_CFLAG | FPSCR_VFLAG; | 423 | ret |= FPSCR_CFLAG | FPSCR_VFLAG; |
| 440 | if (signal_on_qnan || !(vfp_single_packed_mantissa(d) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1)))) | 424 | if (signal_on_qnan || |
| 425 | !(vfp_single_packed_mantissa(d) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1)))) | ||
| 441 | /* | 426 | /* |
| 442 | * Signalling NaN, or signalling on quiet NaN | 427 | * Signalling NaN, or signalling on quiet NaN |
| 443 | */ | 428 | */ |
| @@ -479,28 +464,23 @@ static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u3 | |||
| 479 | return ret; | 464 | return ret; |
| 480 | } | 465 | } |
| 481 | 466 | ||
| 482 | static u32 vfp_single_fcmp(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) | 467 | static u32 vfp_single_fcmp(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { |
| 483 | { | ||
| 484 | return vfp_compare(state, sd, 0, m, fpscr); | 468 | return vfp_compare(state, sd, 0, m, fpscr); |
| 485 | } | 469 | } |
| 486 | 470 | ||
| 487 | static u32 vfp_single_fcmpe(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) | 471 | static u32 vfp_single_fcmpe(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { |
| 488 | { | ||
| 489 | return vfp_compare(state, sd, 1, m, fpscr); | 472 | return vfp_compare(state, sd, 1, m, fpscr); |
| 490 | } | 473 | } |
| 491 | 474 | ||
| 492 | static u32 vfp_single_fcmpz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) | 475 | static u32 vfp_single_fcmpz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { |
| 493 | { | ||
| 494 | return vfp_compare(state, sd, 0, 0, fpscr); | 476 | return vfp_compare(state, sd, 0, 0, fpscr); |
| 495 | } | 477 | } |
| 496 | 478 | ||
| 497 | static u32 vfp_single_fcmpez(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) | 479 | static u32 vfp_single_fcmpez(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { |
| 498 | { | ||
| 499 | return vfp_compare(state, sd, 1, 0, fpscr); | 480 | return vfp_compare(state, sd, 1, 0, fpscr); |
| 500 | } | 481 | } |
| 501 | 482 | ||
| 502 | static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 fpscr) | 483 | static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 fpscr) { |
| 503 | { | ||
| 504 | struct vfp_single vsm; | 484 | struct vfp_single vsm; |
| 505 | struct vfp_double vdd; | 485 | struct vfp_double vdd; |
| 506 | int tm; | 486 | int tm; |
| @@ -525,7 +505,7 @@ static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 f | |||
| 525 | /* | 505 | /* |
| 526 | * If we have an infinity or NaN, the exponent must be 2047. | 506 | * If we have an infinity or NaN, the exponent must be 2047. |
| 527 | */ | 507 | */ |
| 528 | if (tm & (VFP_INFINITY|VFP_NAN)) { | 508 | if (tm & (VFP_INFINITY | VFP_NAN)) { |
| 529 | vdd.exponent = 2047; | 509 | vdd.exponent = 2047; |
| 530 | if (tm == VFP_QNAN) | 510 | if (tm == VFP_QNAN) |
| 531 | vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN; | 511 | vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN; |
| @@ -543,8 +523,7 @@ pack_nan: | |||
| 543 | return exceptions; | 523 | return exceptions; |
| 544 | } | 524 | } |
| 545 | 525 | ||
| 546 | static u32 vfp_single_fuito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) | 526 | static u32 vfp_single_fuito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { |
| 547 | { | ||
| 548 | struct vfp_single vs; | 527 | struct vfp_single vs; |
| 549 | u32 exceptions = 0; | 528 | u32 exceptions = 0; |
| 550 | 529 | ||
| @@ -556,8 +535,7 @@ static u32 vfp_single_fuito(ARMul_State* state, int sd, int unused, s32 m, u32 f | |||
| 556 | return exceptions; | 535 | return exceptions; |
| 557 | } | 536 | } |
| 558 | 537 | ||
| 559 | static u32 vfp_single_fsito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) | 538 | static u32 vfp_single_fsito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { |
| 560 | { | ||
| 561 | struct vfp_single vs; | 539 | struct vfp_single vs; |
| 562 | u32 exceptions = 0; | 540 | u32 exceptions = 0; |
| 563 | 541 | ||
| @@ -569,8 +547,7 @@ static u32 vfp_single_fsito(ARMul_State* state, int sd, int unused, s32 m, u32 f | |||
| 569 | return exceptions; | 547 | return exceptions; |
| 570 | } | 548 | } |
| 571 | 549 | ||
| 572 | static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) | 550 | static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { |
| 573 | { | ||
| 574 | struct vfp_single vsm; | 551 | struct vfp_single vsm; |
| 575 | u32 d, exceptions = 0; | 552 | u32 d, exceptions = 0; |
| 576 | int rmode = fpscr & FPSCR_RMODE_MASK; | 553 | int rmode = fpscr & FPSCR_RMODE_MASK; |
| @@ -656,13 +633,11 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f | |||
| 656 | return exceptions; | 633 | return exceptions; |
| 657 | } | 634 | } |
| 658 | 635 | ||
| 659 | static u32 vfp_single_ftouiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) | 636 | static u32 vfp_single_ftouiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { |
| 660 | { | ||
| 661 | return vfp_single_ftoui(state, sd, unused, m, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); | 637 | return vfp_single_ftoui(state, sd, unused, m, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); |
| 662 | } | 638 | } |
| 663 | 639 | ||
| 664 | static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) | 640 | static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { |
| 665 | { | ||
| 666 | struct vfp_single vsm; | 641 | struct vfp_single vsm; |
| 667 | u32 d, exceptions = 0; | 642 | u32 d, exceptions = 0; |
| 668 | int rmode = fpscr & FPSCR_RMODE_MASK; | 643 | int rmode = fpscr & FPSCR_RMODE_MASK; |
| @@ -739,51 +714,44 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f | |||
| 739 | return exceptions; | 714 | return exceptions; |
| 740 | } | 715 | } |
| 741 | 716 | ||
| 742 | static u32 vfp_single_ftosiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) | 717 | static u32 vfp_single_ftosiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { |
| 743 | { | ||
| 744 | return vfp_single_ftosi(state, sd, unused, m, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); | 718 | return vfp_single_ftosi(state, sd, unused, m, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); |
| 745 | } | 719 | } |
| 746 | 720 | ||
| 747 | static struct op fops_ext[] = { | 721 | static struct op fops_ext[] = { |
| 748 | { vfp_single_fcpy, 0 }, //0x00000000 - FEXT_FCPY | 722 | {vfp_single_fcpy, 0}, // 0x00000000 - FEXT_FCPY |
| 749 | { vfp_single_fabs, 0 }, //0x00000001 - FEXT_FABS | 723 | {vfp_single_fabs, 0}, // 0x00000001 - FEXT_FABS |
| 750 | { vfp_single_fneg, 0 }, //0x00000002 - FEXT_FNEG | 724 | {vfp_single_fneg, 0}, // 0x00000002 - FEXT_FNEG |
| 751 | { vfp_single_fsqrt, 0 }, //0x00000003 - FEXT_FSQRT | 725 | {vfp_single_fsqrt, 0}, // 0x00000003 - FEXT_FSQRT |
| 752 | { nullptr, 0 }, | 726 | {nullptr, 0}, |
| 753 | { nullptr, 0 }, | 727 | {nullptr, 0}, |
| 754 | { nullptr, 0 }, | 728 | {nullptr, 0}, |
| 755 | { nullptr, 0 }, | 729 | {nullptr, 0}, |
| 756 | { vfp_single_fcmp, OP_SCALAR }, //0x00000008 - FEXT_FCMP | 730 | {vfp_single_fcmp, OP_SCALAR}, // 0x00000008 - FEXT_FCMP |
| 757 | { vfp_single_fcmpe, OP_SCALAR }, //0x00000009 - FEXT_FCMPE | 731 | {vfp_single_fcmpe, OP_SCALAR}, // 0x00000009 - FEXT_FCMPE |
| 758 | { vfp_single_fcmpz, OP_SCALAR }, //0x0000000A - FEXT_FCMPZ | 732 | {vfp_single_fcmpz, OP_SCALAR}, // 0x0000000A - FEXT_FCMPZ |
| 759 | { vfp_single_fcmpez, OP_SCALAR }, //0x0000000B - FEXT_FCMPEZ | 733 | {vfp_single_fcmpez, OP_SCALAR}, // 0x0000000B - FEXT_FCMPEZ |
| 760 | { nullptr, 0 }, | 734 | {nullptr, 0}, |
| 761 | { nullptr, 0 }, | 735 | {nullptr, 0}, |
| 762 | { nullptr, 0 }, | 736 | {nullptr, 0}, |
| 763 | { vfp_single_fcvtd, OP_SCALAR|OP_DD }, //0x0000000F - FEXT_FCVT | 737 | {vfp_single_fcvtd, OP_SCALAR | OP_DD}, // 0x0000000F - FEXT_FCVT |
| 764 | { vfp_single_fuito, OP_SCALAR }, //0x00000010 - FEXT_FUITO | 738 | {vfp_single_fuito, OP_SCALAR}, // 0x00000010 - FEXT_FUITO |
| 765 | { vfp_single_fsito, OP_SCALAR }, //0x00000011 - FEXT_FSITO | 739 | {vfp_single_fsito, OP_SCALAR}, // 0x00000011 - FEXT_FSITO |
| 766 | { nullptr, 0 }, | 740 | {nullptr, 0}, |
| 767 | { nullptr, 0 }, | 741 | {nullptr, 0}, |
| 768 | { nullptr, 0 }, | 742 | {nullptr, 0}, |
| 769 | { nullptr, 0 }, | 743 | {nullptr, 0}, |
| 770 | { nullptr, 0 }, | 744 | {nullptr, 0}, |
| 771 | { nullptr, 0 }, | 745 | {nullptr, 0}, |
| 772 | { vfp_single_ftoui, OP_SCALAR }, //0x00000018 - FEXT_FTOUI | 746 | {vfp_single_ftoui, OP_SCALAR}, // 0x00000018 - FEXT_FTOUI |
| 773 | { vfp_single_ftouiz, OP_SCALAR }, //0x00000019 - FEXT_FTOUIZ | 747 | {vfp_single_ftouiz, OP_SCALAR}, // 0x00000019 - FEXT_FTOUIZ |
| 774 | { vfp_single_ftosi, OP_SCALAR }, //0x0000001A - FEXT_FTOSI | 748 | {vfp_single_ftosi, OP_SCALAR}, // 0x0000001A - FEXT_FTOSI |
| 775 | { vfp_single_ftosiz, OP_SCALAR }, //0x0000001B - FEXT_FTOSIZ | 749 | {vfp_single_ftosiz, OP_SCALAR}, // 0x0000001B - FEXT_FTOSIZ |
| 776 | }; | 750 | }; |
| 777 | 751 | ||
| 778 | 752 | static u32 vfp_single_fadd_nonnumber(struct vfp_single* vsd, struct vfp_single* vsn, | |
| 779 | 753 | struct vfp_single* vsm, u32 fpscr) { | |
| 780 | 754 | struct vfp_single* vsp; | |
| 781 | |||
| 782 | static u32 | ||
| 783 | vfp_single_fadd_nonnumber(struct vfp_single *vsd, struct vfp_single *vsn, | ||
| 784 | struct vfp_single *vsm, u32 fpscr) | ||
| 785 | { | ||
| 786 | struct vfp_single *vsp; | ||
| 787 | u32 exceptions = 0; | 755 | u32 exceptions = 0; |
| 788 | int tn, tm; | 756 | int tn, tm; |
| 789 | 757 | ||
| @@ -821,14 +789,11 @@ vfp_single_fadd_nonnumber(struct vfp_single *vsd, struct vfp_single *vsn, | |||
| 821 | return exceptions; | 789 | return exceptions; |
| 822 | } | 790 | } |
| 823 | 791 | ||
| 824 | static u32 | 792 | static u32 vfp_single_add(struct vfp_single* vsd, struct vfp_single* vsn, struct vfp_single* vsm, |
| 825 | vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn, | 793 | u32 fpscr) { |
| 826 | struct vfp_single *vsm, u32 fpscr) | ||
| 827 | { | ||
| 828 | u32 exp_diff, m_sig; | 794 | u32 exp_diff, m_sig; |
| 829 | 795 | ||
| 830 | if (vsn->significand & 0x80000000 || | 796 | if (vsn->significand & 0x80000000 || vsm->significand & 0x80000000) { |
| 831 | vsm->significand & 0x80000000) { | ||
| 832 | LOG_WARNING(Core_ARM11, "bad FP values"); | 797 | LOG_WARNING(Core_ARM11, "bad FP values"); |
| 833 | vfp_single_dump("VSN", vsn); | 798 | vfp_single_dump("VSN", vsn); |
| 834 | vfp_single_dump("VSM", vsm); | 799 | vfp_single_dump("VSM", vsm); |
| @@ -872,8 +837,7 @@ vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn, | |||
| 872 | vsd->sign = vfp_sign_negate(vsd->sign); | 837 | vsd->sign = vfp_sign_negate(vsd->sign); |
| 873 | m_sig = (~m_sig + 1); | 838 | m_sig = (~m_sig + 1); |
| 874 | } else if (m_sig == 0) { | 839 | } else if (m_sig == 0) { |
| 875 | vsd->sign = (fpscr & FPSCR_RMODE_MASK) == | 840 | vsd->sign = (fpscr & FPSCR_RMODE_MASK) == FPSCR_ROUND_MINUSINF ? 0x8000 : 0; |
| 876 | FPSCR_ROUND_MINUSINF ? 0x8000 : 0; | ||
| 877 | } | 841 | } |
| 878 | } else { | 842 | } else { |
| 879 | m_sig = vsn->significand + m_sig; | 843 | m_sig = vsn->significand + m_sig; |
| @@ -883,9 +847,8 @@ vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn, | |||
| 883 | return 0; | 847 | return 0; |
| 884 | } | 848 | } |
| 885 | 849 | ||
| 886 | static u32 | 850 | static u32 vfp_single_multiply(struct vfp_single* vsd, struct vfp_single* vsn, |
| 887 | vfp_single_multiply(struct vfp_single *vsd, struct vfp_single *vsn, struct vfp_single *vsm, u32 fpscr) | 851 | struct vfp_single* vsm, u32 fpscr) { |
| 888 | { | ||
| 889 | vfp_single_dump("VSN", vsn); | 852 | vfp_single_dump("VSN", vsn); |
| 890 | vfp_single_dump("VSM", vsm); | 853 | vfp_single_dump("VSM", vsm); |
| 891 | 854 | ||
| @@ -938,12 +901,11 @@ vfp_single_multiply(struct vfp_single *vsd, struct vfp_single *vsn, struct vfp_s | |||
| 938 | return 0; | 901 | return 0; |
| 939 | } | 902 | } |
| 940 | 903 | ||
| 941 | #define NEG_MULTIPLY (1 << 0) | 904 | #define NEG_MULTIPLY (1 << 0) |
| 942 | #define NEG_SUBTRACT (1 << 1) | 905 | #define NEG_SUBTRACT (1 << 1) |
| 943 | 906 | ||
| 944 | static u32 | 907 | static u32 vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr, |
| 945 | vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr, u32 negate, const char *func) | 908 | u32 negate, const char* func) { |
| 946 | { | ||
| 947 | vfp_single vsd, vsp, vsn, vsm; | 909 | vfp_single vsd, vsp, vsn, vsm; |
| 948 | u32 exceptions = 0; | 910 | u32 exceptions = 0; |
| 949 | s32 v; | 911 | s32 v; |
| @@ -985,8 +947,7 @@ vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fp | |||
| 985 | /* | 947 | /* |
| 986 | * sd = sd + (sn * sm) | 948 | * sd = sd + (sn * sm) |
| 987 | */ | 949 | */ |
| 988 | static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) | 950 | static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) { |
| 989 | { | ||
| 990 | u32 exceptions = 0; | 951 | u32 exceptions = 0; |
| 991 | LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd); | 952 | LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd); |
| 992 | exceptions |= vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, 0, "fmac"); | 953 | exceptions |= vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, 0, "fmac"); |
| @@ -996,8 +957,7 @@ static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) | |||
| 996 | /* | 957 | /* |
| 997 | * sd = sd - (sn * sm) | 958 | * sd = sd - (sn * sm) |
| 998 | */ | 959 | */ |
| 999 | static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) | 960 | static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) { |
| 1000 | { | ||
| 1001 | // TODO: this one has its arguments inverted, investigate. | 961 | // TODO: this one has its arguments inverted, investigate. |
| 1002 | LOG_TRACE(Core_ARM11, "s%u = %08x", sd, sn); | 962 | LOG_TRACE(Core_ARM11, "s%u = %08x", sd, sn); |
| 1003 | return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_MULTIPLY, "fnmac"); | 963 | return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_MULTIPLY, "fnmac"); |
| @@ -1006,8 +966,7 @@ static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr | |||
| 1006 | /* | 966 | /* |
| 1007 | * sd = -sd + (sn * sm) | 967 | * sd = -sd + (sn * sm) |
| 1008 | */ | 968 | */ |
| 1009 | static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) | 969 | static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) { |
| 1010 | { | ||
| 1011 | LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd); | 970 | LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd); |
| 1012 | return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT, "fmsc"); | 971 | return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT, "fmsc"); |
| 1013 | } | 972 | } |
| @@ -1015,17 +974,16 @@ static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) | |||
| 1015 | /* | 974 | /* |
| 1016 | * sd = -sd - (sn * sm) | 975 | * sd = -sd - (sn * sm) |
| 1017 | */ | 976 | */ |
| 1018 | static u32 vfp_single_fnmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) | 977 | static u32 vfp_single_fnmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) { |
| 1019 | { | ||
| 1020 | LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd); | 978 | LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd); |
| 1021 | return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc"); | 979 | return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, |
| 980 | "fnmsc"); | ||
| 1022 | } | 981 | } |
| 1023 | 982 | ||
| 1024 | /* | 983 | /* |
| 1025 | * sd = sn * sm | 984 | * sd = sn * sm |
| 1026 | */ | 985 | */ |
| 1027 | static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) | 986 | static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) { |
| 1028 | { | ||
| 1029 | struct vfp_single vsd, vsn, vsm; | 987 | struct vfp_single vsd, vsn, vsm; |
| 1030 | u32 exceptions = 0; | 988 | u32 exceptions = 0; |
| 1031 | s32 n = vfp_get_float(state, sn); | 989 | s32 n = vfp_get_float(state, sn); |
| @@ -1049,8 +1007,7 @@ static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) | |||
| 1049 | /* | 1007 | /* |
| 1050 | * sd = -(sn * sm) | 1008 | * sd = -(sn * sm) |
| 1051 | */ | 1009 | */ |
| 1052 | static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) | 1010 | static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) { |
| 1053 | { | ||
| 1054 | struct vfp_single vsd, vsn, vsm; | 1011 | struct vfp_single vsd, vsn, vsm; |
| 1055 | u32 exceptions = 0; | 1012 | u32 exceptions = 0; |
| 1056 | s32 n = vfp_get_float(state, sn); | 1013 | s32 n = vfp_get_float(state, sn); |
| @@ -1075,8 +1032,7 @@ static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr | |||
| 1075 | /* | 1032 | /* |
| 1076 | * sd = sn + sm | 1033 | * sd = sn + sm |
| 1077 | */ | 1034 | */ |
| 1078 | static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) | 1035 | static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) { |
| 1079 | { | ||
| 1080 | struct vfp_single vsd, vsn, vsm; | 1036 | struct vfp_single vsd, vsn, vsm; |
| 1081 | u32 exceptions = 0; | 1037 | u32 exceptions = 0; |
| 1082 | s32 n = vfp_get_float(state, sn); | 1038 | s32 n = vfp_get_float(state, sn); |
| @@ -1103,8 +1059,7 @@ static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) | |||
| 1103 | /* | 1059 | /* |
| 1104 | * sd = sn - sm | 1060 | * sd = sn - sm |
| 1105 | */ | 1061 | */ |
| 1106 | static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) | 1062 | static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) { |
| 1107 | { | ||
| 1108 | LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd); | 1063 | LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd); |
| 1109 | /* | 1064 | /* |
| 1110 | * Subtraction is addition with one sign inverted. | 1065 | * Subtraction is addition with one sign inverted. |
| @@ -1118,8 +1073,7 @@ static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) | |||
| 1118 | /* | 1073 | /* |
| 1119 | * sd = sn / sm | 1074 | * sd = sn / sm |
| 1120 | */ | 1075 | */ |
| 1121 | static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) | 1076 | static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) { |
| 1122 | { | ||
| 1123 | struct vfp_single vsd, vsn, vsm; | 1077 | struct vfp_single vsd, vsn, vsm; |
| 1124 | u32 exceptions = 0; | 1078 | u32 exceptions = 0; |
| 1125 | s32 n = vfp_get_float(state, sn); | 1079 | s32 n = vfp_get_float(state, sn); |
| @@ -1151,7 +1105,7 @@ static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) | |||
| 1151 | * If n and m are infinity, the result is invalid | 1105 | * If n and m are infinity, the result is invalid |
| 1152 | * If n and m are zero, the result is invalid | 1106 | * If n and m are zero, the result is invalid |
| 1153 | */ | 1107 | */ |
| 1154 | if (tm & tn & (VFP_INFINITY|VFP_ZERO)) | 1108 | if (tm & tn & (VFP_INFINITY | VFP_ZERO)) |
| 1155 | goto invalid; | 1109 | goto invalid; |
| 1156 | 1110 | ||
| 1157 | /* | 1111 | /* |
| @@ -1226,29 +1180,22 @@ invalid: | |||
| 1226 | } | 1180 | } |
| 1227 | 1181 | ||
| 1228 | static struct op fops[] = { | 1182 | static struct op fops[] = { |
| 1229 | { vfp_single_fmac, 0 }, | 1183 | {vfp_single_fmac, 0}, {vfp_single_fmsc, 0}, {vfp_single_fmul, 0}, |
| 1230 | { vfp_single_fmsc, 0 }, | 1184 | {vfp_single_fadd, 0}, {vfp_single_fnmac, 0}, {vfp_single_fnmsc, 0}, |
| 1231 | { vfp_single_fmul, 0 }, | 1185 | {vfp_single_fnmul, 0}, {vfp_single_fsub, 0}, {vfp_single_fdiv, 0}, |
| 1232 | { vfp_single_fadd, 0 }, | ||
| 1233 | { vfp_single_fnmac, 0 }, | ||
| 1234 | { vfp_single_fnmsc, 0 }, | ||
| 1235 | { vfp_single_fnmul, 0 }, | ||
| 1236 | { vfp_single_fsub, 0 }, | ||
| 1237 | { vfp_single_fdiv, 0 }, | ||
| 1238 | }; | 1186 | }; |
| 1239 | 1187 | ||
| 1240 | #define FREG_BANK(x) ((x) & 0x18) | 1188 | #define FREG_BANK(x) ((x)&0x18) |
| 1241 | #define FREG_IDX(x) ((x) & 7) | 1189 | #define FREG_IDX(x) ((x)&7) |
| 1242 | 1190 | ||
| 1243 | u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr) | 1191 | u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr) { |
| 1244 | { | ||
| 1245 | u32 op = inst & FOP_MASK; | 1192 | u32 op = inst & FOP_MASK; |
| 1246 | u32 exceptions = 0; | 1193 | u32 exceptions = 0; |
| 1247 | unsigned int dest; | 1194 | unsigned int dest; |
| 1248 | unsigned int sn = vfp_get_sn(inst); | 1195 | unsigned int sn = vfp_get_sn(inst); |
| 1249 | unsigned int sm = vfp_get_sm(inst); | 1196 | unsigned int sm = vfp_get_sm(inst); |
| 1250 | unsigned int vecitr, veclen, vecstride; | 1197 | unsigned int vecitr, veclen, vecstride; |
| 1251 | struct op *fop; | 1198 | struct op* fop; |
| 1252 | 1199 | ||
| 1253 | vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK); | 1200 | vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK); |
| 1254 | 1201 | ||
| @@ -1274,11 +1221,11 @@ u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr) | |||
| 1274 | else | 1221 | else |
| 1275 | veclen = fpscr & FPSCR_LENGTH_MASK; | 1222 | veclen = fpscr & FPSCR_LENGTH_MASK; |
| 1276 | 1223 | ||
| 1277 | LOG_TRACE(Core_ARM11, "vecstride=%u veclen=%u", vecstride, | 1224 | LOG_TRACE(Core_ARM11, "vecstride=%u veclen=%u", vecstride, (veclen >> FPSCR_LENGTH_BIT) + 1); |
| 1278 | (veclen >> FPSCR_LENGTH_BIT) + 1); | ||
| 1279 | 1225 | ||
| 1280 | if (!fop->fn) { | 1226 | if (!fop->fn) { |
| 1281 | LOG_CRITICAL(Core_ARM11, "could not find single op %d, inst=0x%x@0x%x", FEXT_TO_IDX(inst), inst, state->Reg[15]); | 1227 | LOG_CRITICAL(Core_ARM11, "could not find single op %d, inst=0x%x@0x%x", FEXT_TO_IDX(inst), |
| 1228 | inst, state->Reg[15]); | ||
| 1282 | Crash(); | 1229 | Crash(); |
| 1283 | goto invalid; | 1230 | goto invalid; |
| 1284 | } | 1231 | } |
| @@ -1290,17 +1237,14 @@ u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr) | |||
| 1290 | 1237 | ||
| 1291 | type = (fop->flags & OP_DD) ? 'd' : 's'; | 1238 | type = (fop->flags & OP_DD) ? 'd' : 's'; |
| 1292 | if (op == FOP_EXT) | 1239 | if (op == FOP_EXT) |
| 1293 | LOG_TRACE(Core_ARM11, "itr%d (%c%u) = op[%u] (s%u=%08x)", | 1240 | LOG_TRACE(Core_ARM11, "itr%d (%c%u) = op[%u] (s%u=%08x)", vecitr >> FPSCR_LENGTH_BIT, |
| 1294 | vecitr >> FPSCR_LENGTH_BIT, type, dest, sn, | 1241 | type, dest, sn, sm, m); |
| 1295 | sm, m); | ||
| 1296 | else | 1242 | else |
| 1297 | LOG_TRACE(Core_ARM11, "itr%d (%c%u) = (s%u) op[%u] (s%u=%08x)", | 1243 | LOG_TRACE(Core_ARM11, "itr%d (%c%u) = (s%u) op[%u] (s%u=%08x)", |
| 1298 | vecitr >> FPSCR_LENGTH_BIT, type, dest, sn, | 1244 | vecitr >> FPSCR_LENGTH_BIT, type, dest, sn, FOP_TO_IDX(op), sm, m); |
| 1299 | FOP_TO_IDX(op), sm, m); | ||
| 1300 | 1245 | ||
| 1301 | except = fop->fn(state, dest, sn, m, fpscr); | 1246 | except = fop->fn(state, dest, sn, m, fpscr); |
| 1302 | LOG_TRACE(Core_ARM11, "itr%d: exceptions=%08x", | 1247 | LOG_TRACE(Core_ARM11, "itr%d: exceptions=%08x", vecitr >> FPSCR_LENGTH_BIT, except); |
| 1303 | vecitr >> FPSCR_LENGTH_BIT, except); | ||
| 1304 | 1248 | ||
| 1305 | exceptions |= except; | 1249 | exceptions |= except; |
| 1306 | 1250 | ||