diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/arm/arm_interface.h | 28 | ||||
| -rw-r--r-- | src/core/arm/disassembler/arm_disasm.cpp | 948 | ||||
| -rw-r--r-- | src/core/arm/disassembler/arm_disasm.h | 152 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom.cpp | 16 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom.h | 4 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 41 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/arm_regformat.h | 2 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/vfp/vfp.cpp | 17 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/vfp/vfpdouble.cpp | 9 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/vfp/vfpsingle.cpp | 9 | ||||
| -rw-r--r-- | src/core/settings.h | 1 | ||||
| -rw-r--r-- | src/core/tracer/citrace.h | 70 |
12 files changed, 1014 insertions, 283 deletions
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 85ed2c698..5cffe513c 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h | |||
| @@ -62,6 +62,34 @@ public: | |||
| 62 | virtual void SetReg(int index, u32 value) = 0; | 62 | virtual void SetReg(int index, u32 value) = 0; |
| 63 | 63 | ||
| 64 | /** | 64 | /** |
| 65 | * Gets the value of a VFP register | ||
| 66 | * @param index Register index (0-31) | ||
| 67 | * @return Returns the value in the register | ||
| 68 | */ | ||
| 69 | virtual u32 GetVFPReg(int index) const = 0; | ||
| 70 | |||
| 71 | /** | ||
| 72 | * Sets a VFP register to the given value | ||
| 73 | * @param index Register index (0-31) | ||
| 74 | * @param value Value to set register to | ||
| 75 | */ | ||
| 76 | virtual void SetVFPReg(int index, u32 value) = 0; | ||
| 77 | |||
| 78 | /** | ||
| 79 | * Gets the current value within a given VFP system register | ||
| 80 | * @param reg The VFP system register | ||
| 81 | * @return The value within the VFP system register | ||
| 82 | */ | ||
| 83 | virtual u32 GetVFPSystemReg(VFPSystemRegister reg) const = 0; | ||
| 84 | |||
| 85 | /** | ||
| 86 | * Sets the VFP system register to the given value | ||
| 87 | * @param reg The VFP system register | ||
| 88 | * @param value Value to set the VFP system register to | ||
| 89 | */ | ||
| 90 | virtual void SetVFPSystemReg(VFPSystemRegister reg, u32 value) = 0; | ||
| 91 | |||
| 92 | /** | ||
| 65 | * Get the current CPSR register | 93 | * Get the current CPSR register |
| 66 | * @return Returns the value of the CPSR register | 94 | * @return Returns the value of the CPSR register |
| 67 | */ | 95 | */ |
diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp index f6d44d85a..77af10b54 100644 --- a/src/core/arm/disassembler/arm_disasm.cpp +++ b/src/core/arm/disassembler/arm_disasm.cpp | |||
| @@ -1,9 +1,13 @@ | |||
| 1 | // Copyright 2006 The Android Open Source Project | 1 | // Copyright 2006 The Android Open Source Project |
| 2 | 2 | ||
| 3 | #include <string> | 3 | #include <string> |
| 4 | #include <unordered_set> | ||
| 4 | 5 | ||
| 6 | #include "common/common_types.h" | ||
| 5 | #include "common/string_util.h" | 7 | #include "common/string_util.h" |
| 8 | |||
| 6 | #include "core/arm/disassembler/arm_disasm.h" | 9 | #include "core/arm/disassembler/arm_disasm.h" |
| 10 | #include "core/arm/skyeye_common/armsupp.h" | ||
| 7 | 11 | ||
| 8 | static const char *cond_names[] = { | 12 | static const char *cond_names[] = { |
| 9 | "eq", | 13 | "eq", |
| @@ -37,6 +41,7 @@ static const char *opcode_names[] = { | |||
| 37 | "blx", | 41 | "blx", |
| 38 | "bx", | 42 | "bx", |
| 39 | "cdp", | 43 | "cdp", |
| 44 | "clrex", | ||
| 40 | "clz", | 45 | "clz", |
| 41 | "cmn", | 46 | "cmn", |
| 42 | "cmp", | 47 | "cmp", |
| @@ -46,6 +51,10 @@ static const char *opcode_names[] = { | |||
| 46 | "ldr", | 51 | "ldr", |
| 47 | "ldrb", | 52 | "ldrb", |
| 48 | "ldrbt", | 53 | "ldrbt", |
| 54 | "ldrex", | ||
| 55 | "ldrexb", | ||
| 56 | "ldrexd", | ||
| 57 | "ldrexh", | ||
| 49 | "ldrh", | 58 | "ldrh", |
| 50 | "ldrsb", | 59 | "ldrsb", |
| 51 | "ldrsh", | 60 | "ldrsh", |
| @@ -58,28 +67,105 @@ static const char *opcode_names[] = { | |||
| 58 | "msr", | 67 | "msr", |
| 59 | "mul", | 68 | "mul", |
| 60 | "mvn", | 69 | "mvn", |
| 70 | "nop", | ||
| 61 | "orr", | 71 | "orr", |
| 72 | "pkh", | ||
| 62 | "pld", | 73 | "pld", |
| 74 | "qadd16", | ||
| 75 | "qadd8", | ||
| 76 | "qasx", | ||
| 77 | "qsax", | ||
| 78 | "qsub16", | ||
| 79 | "qsub8", | ||
| 80 | "rev", | ||
| 81 | "rev16", | ||
| 82 | "revsh", | ||
| 63 | "rsb", | 83 | "rsb", |
| 64 | "rsc", | 84 | "rsc", |
| 85 | "sadd16", | ||
| 86 | "sadd8", | ||
| 87 | "sasx", | ||
| 65 | "sbc", | 88 | "sbc", |
| 89 | "sel", | ||
| 90 | "sev", | ||
| 91 | "shadd16", | ||
| 92 | "shadd8", | ||
| 93 | "shasx", | ||
| 94 | "shsax", | ||
| 95 | "shsub16", | ||
| 96 | "shsub8", | ||
| 97 | "smlad", | ||
| 66 | "smlal", | 98 | "smlal", |
| 99 | "smlald", | ||
| 100 | "smlsd", | ||
| 101 | "smlsld", | ||
| 102 | "smmla", | ||
| 103 | "smmls", | ||
| 104 | "smmul", | ||
| 105 | "smuad", | ||
| 67 | "smull", | 106 | "smull", |
| 107 | "smusd", | ||
| 108 | "ssat", | ||
| 109 | "ssat16", | ||
| 110 | "ssax", | ||
| 111 | "ssub16", | ||
| 112 | "ssub8", | ||
| 68 | "stc", | 113 | "stc", |
| 69 | "stm", | 114 | "stm", |
| 70 | "str", | 115 | "str", |
| 71 | "strb", | 116 | "strb", |
| 72 | "strbt", | 117 | "strbt", |
| 118 | "strex", | ||
| 119 | "strexb", | ||
| 120 | "strexd", | ||
| 121 | "strexh", | ||
| 73 | "strh", | 122 | "strh", |
| 74 | "strt", | 123 | "strt", |
| 75 | "sub", | 124 | "sub", |
| 76 | "swi", | 125 | "swi", |
| 77 | "swp", | 126 | "swp", |
| 78 | "swpb", | 127 | "swpb", |
| 128 | "sxtab", | ||
| 129 | "sxtab16", | ||
| 130 | "sxtah", | ||
| 131 | "sxtb", | ||
| 132 | "sxtb16", | ||
| 133 | "sxth", | ||
| 79 | "teq", | 134 | "teq", |
| 80 | "tst", | 135 | "tst", |
| 136 | "uadd16", | ||
| 137 | "uadd8", | ||
| 138 | "uasx", | ||
| 139 | "uhadd16", | ||
| 140 | "uhadd8", | ||
| 141 | "uhasx", | ||
| 142 | "uhsax", | ||
| 143 | "uhsub16", | ||
| 144 | "uhsub8", | ||
| 81 | "umlal", | 145 | "umlal", |
| 82 | "umull", | 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", | ||
| 83 | 169 | ||
| 84 | "undefined", | 170 | "undefined", |
| 85 | "adc", | 171 | "adc", |
| @@ -131,11 +217,11 @@ static const char *shift_names[] = { | |||
| 131 | "ROR" | 217 | "ROR" |
| 132 | }; | 218 | }; |
| 133 | 219 | ||
| 134 | static const char* cond_to_str(uint32_t cond) { | 220 | static const char* cond_to_str(u32 cond) { |
| 135 | return cond_names[cond]; | 221 | return cond_names[cond]; |
| 136 | } | 222 | } |
| 137 | 223 | ||
| 138 | std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) | 224 | std::string ARM_Disasm::Disassemble(u32 addr, u32 insn) |
| 139 | { | 225 | { |
| 140 | Opcode opcode = Decode(insn); | 226 | Opcode opcode = Decode(insn); |
| 141 | switch (opcode) { | 227 | switch (opcode) { |
| @@ -172,6 +258,8 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) | |||
| 172 | return DisassembleBX(insn); | 258 | return DisassembleBX(insn); |
| 173 | case OP_CDP: | 259 | case OP_CDP: |
| 174 | return "cdp"; | 260 | return "cdp"; |
| 261 | case OP_CLREX: | ||
| 262 | return "clrex"; | ||
| 175 | case OP_CLZ: | 263 | case OP_CLZ: |
| 176 | return DisassembleCLZ(insn); | 264 | return DisassembleCLZ(insn); |
| 177 | case OP_LDC: | 265 | case OP_LDC: |
| @@ -188,6 +276,15 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) | |||
| 188 | case OP_STRBT: | 276 | case OP_STRBT: |
| 189 | case OP_STRT: | 277 | case OP_STRT: |
| 190 | return DisassembleMem(insn); | 278 | return DisassembleMem(insn); |
| 279 | case OP_LDREX: | ||
| 280 | case OP_LDREXB: | ||
| 281 | case OP_LDREXD: | ||
| 282 | case OP_LDREXH: | ||
| 283 | case OP_STREX: | ||
| 284 | case OP_STREXB: | ||
| 285 | case OP_STREXD: | ||
| 286 | case OP_STREXH: | ||
| 287 | return DisassembleREX(opcode, insn); | ||
| 191 | case OP_LDRH: | 288 | case OP_LDRH: |
| 192 | case OP_LDRSB: | 289 | case OP_LDRSB: |
| 193 | case OP_LDRSH: | 290 | case OP_LDRSH: |
| @@ -204,8 +301,76 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) | |||
| 204 | return DisassembleMSR(insn); | 301 | return DisassembleMSR(insn); |
| 205 | case OP_MUL: | 302 | case OP_MUL: |
| 206 | return DisassembleMUL(opcode, insn); | 303 | return DisassembleMUL(opcode, insn); |
| 304 | case OP_NOP: | ||
| 305 | case OP_SEV: | ||
| 306 | case OP_WFE: | ||
| 307 | case OP_WFI: | ||
| 308 | case OP_YIELD: | ||
| 309 | return DisassembleNoOperands(opcode, insn); | ||
| 310 | case OP_PKH: | ||
| 311 | return DisassemblePKH(insn); | ||
| 207 | case OP_PLD: | 312 | case OP_PLD: |
| 208 | return DisassemblePLD(insn); | 313 | return DisassemblePLD(insn); |
| 314 | case OP_QADD16: | ||
| 315 | case OP_QADD8: | ||
| 316 | case OP_QASX: | ||
| 317 | case OP_QSAX: | ||
| 318 | case OP_QSUB16: | ||
| 319 | case OP_QSUB8: | ||
| 320 | case OP_SADD16: | ||
| 321 | case OP_SADD8: | ||
| 322 | case OP_SASX: | ||
| 323 | case OP_SHADD16: | ||
| 324 | case OP_SHADD8: | ||
| 325 | case OP_SHASX: | ||
| 326 | case OP_SHSAX: | ||
| 327 | case OP_SHSUB16: | ||
| 328 | case OP_SHSUB8: | ||
| 329 | case OP_SSAX: | ||
| 330 | case OP_SSUB16: | ||
| 331 | case OP_SSUB8: | ||
| 332 | case OP_UADD16: | ||
| 333 | case OP_UADD8: | ||
| 334 | case OP_UASX: | ||
| 335 | case OP_UHADD16: | ||
| 336 | case OP_UHADD8: | ||
| 337 | case OP_UHASX: | ||
| 338 | case OP_UHSAX: | ||
| 339 | case OP_UHSUB16: | ||
| 340 | case OP_UHSUB8: | ||
| 341 | case OP_UQADD16: | ||
| 342 | case OP_UQADD8: | ||
| 343 | case OP_UQASX: | ||
| 344 | case OP_UQSAX: | ||
| 345 | case OP_UQSUB16: | ||
| 346 | case OP_UQSUB8: | ||
| 347 | case OP_USAX: | ||
| 348 | case OP_USUB16: | ||
| 349 | case OP_USUB8: | ||
| 350 | return DisassembleParallelAddSub(opcode, insn); | ||
| 351 | case OP_REV: | ||
| 352 | case OP_REV16: | ||
| 353 | case OP_REVSH: | ||
| 354 | return DisassembleREV(opcode, insn); | ||
| 355 | case OP_SEL: | ||
| 356 | return DisassembleSEL(insn); | ||
| 357 | case OP_SMLAD: | ||
| 358 | case OP_SMLALD: | ||
| 359 | case OP_SMLSD: | ||
| 360 | case OP_SMLSLD: | ||
| 361 | case OP_SMMLA: | ||
| 362 | case OP_SMMLS: | ||
| 363 | case OP_SMMUL: | ||
| 364 | case OP_SMUAD: | ||
| 365 | case OP_SMUSD: | ||
| 366 | case OP_USAD8: | ||
| 367 | case OP_USADA8: | ||
| 368 | return DisassembleMediaMulDiv(opcode, insn); | ||
| 369 | case OP_SSAT: | ||
| 370 | case OP_SSAT16: | ||
| 371 | case OP_USAT: | ||
| 372 | case OP_USAT16: | ||
| 373 | return DisassembleSAT(opcode, insn); | ||
| 209 | case OP_STC: | 374 | case OP_STC: |
| 210 | return "stc"; | 375 | return "stc"; |
| 211 | case OP_SWI: | 376 | case OP_SWI: |
| @@ -213,6 +378,19 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) | |||
| 213 | case OP_SWP: | 378 | case OP_SWP: |
| 214 | case OP_SWPB: | 379 | case OP_SWPB: |
| 215 | return DisassembleSWP(opcode, insn); | 380 | return DisassembleSWP(opcode, insn); |
| 381 | case OP_SXTAB: | ||
| 382 | case OP_SXTAB16: | ||
| 383 | case OP_SXTAH: | ||
| 384 | case OP_SXTB: | ||
| 385 | case OP_SXTB16: | ||
| 386 | case OP_SXTH: | ||
| 387 | case OP_UXTAB: | ||
| 388 | case OP_UXTAB16: | ||
| 389 | case OP_UXTAH: | ||
| 390 | case OP_UXTB: | ||
| 391 | case OP_UXTB16: | ||
| 392 | case OP_UXTH: | ||
| 393 | return DisassembleXT(opcode, insn); | ||
| 216 | case OP_UMLAL: | 394 | case OP_UMLAL: |
| 217 | case OP_UMULL: | 395 | case OP_UMULL: |
| 218 | case OP_SMLAL: | 396 | case OP_SMLAL: |
| @@ -224,22 +402,22 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) | |||
| 224 | return NULL; | 402 | return NULL; |
| 225 | } | 403 | } |
| 226 | 404 | ||
| 227 | std::string ARM_Disasm::DisassembleALU(Opcode opcode, uint32_t insn) | 405 | std::string ARM_Disasm::DisassembleALU(Opcode opcode, u32 insn) |
| 228 | { | 406 | { |
| 229 | static const uint8_t kNoOperand1 = 1; | 407 | static const u8 kNoOperand1 = 1; |
| 230 | static const uint8_t kNoDest = 2; | 408 | static const u8 kNoDest = 2; |
| 231 | static const uint8_t kNoSbit = 4; | 409 | static const u8 kNoSbit = 4; |
| 232 | 410 | ||
| 233 | std::string rn_str; | 411 | std::string rn_str; |
| 234 | std::string rd_str; | 412 | std::string rd_str; |
| 235 | 413 | ||
| 236 | uint8_t flags = 0; | 414 | u8 flags = 0; |
| 237 | uint8_t cond = (insn >> 28) & 0xf; | 415 | u8 cond = (insn >> 28) & 0xf; |
| 238 | uint8_t is_immed = (insn >> 25) & 0x1; | 416 | u8 is_immed = (insn >> 25) & 0x1; |
| 239 | uint8_t bit_s = (insn >> 20) & 1; | 417 | u8 bit_s = (insn >> 20) & 1; |
| 240 | uint8_t rn = (insn >> 16) & 0xf; | 418 | u8 rn = (insn >> 16) & 0xf; |
| 241 | uint8_t rd = (insn >> 12) & 0xf; | 419 | u8 rd = (insn >> 12) & 0xf; |
| 242 | uint8_t immed = insn & 0xff; | 420 | u8 immed = insn & 0xff; |
| 243 | 421 | ||
| 244 | const char* opname = opcode_names[opcode]; | 422 | const char* opname = opcode_names[opcode]; |
| 245 | switch (opcode) { | 423 | switch (opcode) { |
| @@ -279,14 +457,14 @@ std::string ARM_Disasm::DisassembleALU(Opcode opcode, uint32_t insn) | |||
| 279 | opname, cond_to_str(cond), sbit_str, rd_str.c_str(), rn_str.c_str(), immed, immed); | 457 | opname, cond_to_str(cond), sbit_str, rd_str.c_str(), rn_str.c_str(), immed, immed); |
| 280 | } | 458 | } |
| 281 | 459 | ||
| 282 | uint8_t shift_is_reg = (insn >> 4) & 1; | 460 | u8 shift_is_reg = (insn >> 4) & 1; |
| 283 | uint8_t rotate = (insn >> 8) & 0xf; | 461 | u8 rotate = (insn >> 8) & 0xf; |
| 284 | uint8_t rm = insn & 0xf; | 462 | u8 rm = insn & 0xf; |
| 285 | uint8_t shift_type = (insn >> 5) & 0x3; | 463 | u8 shift_type = (insn >> 5) & 0x3; |
| 286 | uint8_t rs = (insn >> 8) & 0xf; | 464 | u8 rs = (insn >> 8) & 0xf; |
| 287 | uint8_t shift_amount = (insn >> 7) & 0x1f; | 465 | u8 shift_amount = (insn >> 7) & 0x1f; |
| 288 | uint32_t rotated_val = immed; | 466 | u32 rotated_val = immed; |
| 289 | uint8_t rotate2 = rotate << 1; | 467 | u8 rotate2 = rotate << 1; |
| 290 | rotated_val = (rotated_val >> rotate2) | (rotated_val << (32 - rotate2)); | 468 | rotated_val = (rotated_val >> rotate2) | (rotated_val << (32 - rotate2)); |
| 291 | 469 | ||
| 292 | if (!shift_is_reg && shift_type == 0 && shift_amount == 0) { | 470 | if (!shift_is_reg && shift_type == 0 && shift_amount == 0) { |
| @@ -312,10 +490,10 @@ std::string ARM_Disasm::DisassembleALU(Opcode opcode, uint32_t insn) | |||
| 312 | shift_name, shift_amount); | 490 | shift_name, shift_amount); |
| 313 | } | 491 | } |
| 314 | 492 | ||
| 315 | std::string ARM_Disasm::DisassembleBranch(uint32_t addr, Opcode opcode, uint32_t insn) | 493 | std::string ARM_Disasm::DisassembleBranch(u32 addr, Opcode opcode, u32 insn) |
| 316 | { | 494 | { |
| 317 | uint8_t cond = (insn >> 28) & 0xf; | 495 | u8 cond = (insn >> 28) & 0xf; |
| 318 | uint32_t offset = insn & 0xffffff; | 496 | u32 offset = insn & 0xffffff; |
| 319 | // Sign-extend the 24-bit offset | 497 | // Sign-extend the 24-bit offset |
| 320 | if ((offset >> 23) & 1) | 498 | if ((offset >> 23) & 1) |
| 321 | offset |= 0xff000000; | 499 | offset |= 0xff000000; |
| @@ -328,39 +506,71 @@ std::string ARM_Disasm::DisassembleBranch(uint32_t addr, Opcode opcode, uint32_t | |||
| 328 | return Common::StringFromFormat("%s%s\t0x%x", opname, cond_to_str(cond), addr); | 506 | return Common::StringFromFormat("%s%s\t0x%x", opname, cond_to_str(cond), addr); |
| 329 | } | 507 | } |
| 330 | 508 | ||
| 331 | std::string ARM_Disasm::DisassembleBX(uint32_t insn) | 509 | std::string ARM_Disasm::DisassembleBX(u32 insn) |
| 332 | { | 510 | { |
| 333 | uint8_t cond = (insn >> 28) & 0xf; | 511 | u8 cond = (insn >> 28) & 0xf; |
| 334 | uint8_t rn = insn & 0xf; | 512 | u8 rn = insn & 0xf; |
| 335 | return Common::StringFromFormat("bx%s\tr%d", cond_to_str(cond), rn); | 513 | return Common::StringFromFormat("bx%s\tr%d", cond_to_str(cond), rn); |
| 336 | } | 514 | } |
| 337 | 515 | ||
| 338 | std::string ARM_Disasm::DisassembleBKPT(uint32_t insn) | 516 | std::string ARM_Disasm::DisassembleBKPT(u32 insn) |
| 339 | { | 517 | { |
| 340 | uint8_t cond = (insn >> 28) & 0xf; | 518 | u8 cond = (insn >> 28) & 0xf; |
| 341 | uint32_t immed = (((insn >> 8) & 0xfff) << 4) | (insn & 0xf); | 519 | u32 immed = (((insn >> 8) & 0xfff) << 4) | (insn & 0xf); |
| 342 | return Common::StringFromFormat("bkpt%s\t#%d", cond_to_str(cond), immed); | 520 | return Common::StringFromFormat("bkpt%s\t#%d", cond_to_str(cond), immed); |
| 343 | } | 521 | } |
| 344 | 522 | ||
| 345 | std::string ARM_Disasm::DisassembleCLZ(uint32_t insn) | 523 | std::string ARM_Disasm::DisassembleCLZ(u32 insn) |
| 346 | { | 524 | { |
| 347 | uint8_t cond = (insn >> 28) & 0xf; | 525 | u8 cond = (insn >> 28) & 0xf; |
| 348 | uint8_t rd = (insn >> 12) & 0xf; | 526 | u8 rd = (insn >> 12) & 0xf; |
| 349 | uint8_t rm = insn & 0xf; | 527 | u8 rm = insn & 0xf; |
| 350 | return Common::StringFromFormat("clz%s\tr%d, r%d", cond_to_str(cond), rd, rm); | 528 | return Common::StringFromFormat("clz%s\tr%d, r%d", cond_to_str(cond), rd, rm); |
| 351 | } | 529 | } |
| 352 | 530 | ||
| 353 | std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, uint32_t insn) | 531 | std::string ARM_Disasm::DisassembleMediaMulDiv(Opcode opcode, u32 insn) { |
| 532 | u32 cond = BITS(insn, 28, 31); | ||
| 533 | u32 rd = BITS(insn, 16, 19); | ||
| 534 | u32 ra = BITS(insn, 12, 15); | ||
| 535 | u32 rm = BITS(insn, 8, 11); | ||
| 536 | u32 m = BIT(insn, 5); | ||
| 537 | u32 rn = BITS(insn, 0, 3); | ||
| 538 | |||
| 539 | std::string cross = ""; | ||
| 540 | if (m) { | ||
| 541 | if (opcode == OP_SMMLA || opcode == OP_SMMUL || opcode == OP_SMMLS) | ||
| 542 | cross = "r"; | ||
| 543 | else | ||
| 544 | cross = "x"; | ||
| 545 | } | ||
| 546 | |||
| 547 | std::string ext_reg = ""; | ||
| 548 | std::unordered_set<Opcode, std::hash<int>> with_ext_reg = { | ||
| 549 | OP_SMLAD, OP_SMLSD, OP_SMMLA, OP_SMMLS, OP_USADA8 | ||
| 550 | }; | ||
| 551 | if (with_ext_reg.find(opcode) != with_ext_reg.end()) | ||
| 552 | ext_reg = Common::StringFromFormat(", r%u", ra); | ||
| 553 | |||
| 554 | std::string rd_low = ""; | ||
| 555 | if (opcode == OP_SMLALD || opcode == OP_SMLSLD) | ||
| 556 | rd_low = Common::StringFromFormat("r%u, ", ra); | ||
| 557 | |||
| 558 | return Common::StringFromFormat("%s%s%s\t%sr%u, r%u, r%u%s", opcode_names[opcode], | ||
| 559 | cross.c_str(), cond_to_str(cond), rd_low.c_str(), rd, rn, rm, | ||
| 560 | ext_reg.c_str()); | ||
| 561 | } | ||
| 562 | |||
| 563 | std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, u32 insn) | ||
| 354 | { | 564 | { |
| 355 | std::string tmp_list; | 565 | std::string tmp_list; |
| 356 | 566 | ||
| 357 | uint8_t cond = (insn >> 28) & 0xf; | 567 | u8 cond = (insn >> 28) & 0xf; |
| 358 | uint8_t write_back = (insn >> 21) & 0x1; | 568 | u8 write_back = (insn >> 21) & 0x1; |
| 359 | uint8_t bit_s = (insn >> 22) & 0x1; | 569 | u8 bit_s = (insn >> 22) & 0x1; |
| 360 | uint8_t is_up = (insn >> 23) & 0x1; | 570 | u8 is_up = (insn >> 23) & 0x1; |
| 361 | uint8_t is_pre = (insn >> 24) & 0x1; | 571 | u8 is_pre = (insn >> 24) & 0x1; |
| 362 | uint8_t rn = (insn >> 16) & 0xf; | 572 | u8 rn = (insn >> 16) & 0xf; |
| 363 | uint16_t reg_list = insn & 0xffff; | 573 | u16 reg_list = insn & 0xffff; |
| 364 | 574 | ||
| 365 | const char *opname = opcode_names[opcode]; | 575 | const char *opname = opcode_names[opcode]; |
| 366 | 576 | ||
| @@ -400,18 +610,18 @@ std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, uint32_t insn) | |||
| 400 | opname, cond_to_str(cond), addr_mode, rn, bang, tmp_list.c_str(), carret); | 610 | opname, cond_to_str(cond), addr_mode, rn, bang, tmp_list.c_str(), carret); |
| 401 | } | 611 | } |
| 402 | 612 | ||
| 403 | std::string ARM_Disasm::DisassembleMem(uint32_t insn) | 613 | std::string ARM_Disasm::DisassembleMem(u32 insn) |
| 404 | { | 614 | { |
| 405 | uint8_t cond = (insn >> 28) & 0xf; | 615 | u8 cond = (insn >> 28) & 0xf; |
| 406 | uint8_t is_reg = (insn >> 25) & 0x1; | 616 | u8 is_reg = (insn >> 25) & 0x1; |
| 407 | uint8_t is_load = (insn >> 20) & 0x1; | 617 | u8 is_load = (insn >> 20) & 0x1; |
| 408 | uint8_t write_back = (insn >> 21) & 0x1; | 618 | u8 write_back = (insn >> 21) & 0x1; |
| 409 | uint8_t is_byte = (insn >> 22) & 0x1; | 619 | u8 is_byte = (insn >> 22) & 0x1; |
| 410 | uint8_t is_up = (insn >> 23) & 0x1; | 620 | u8 is_up = (insn >> 23) & 0x1; |
| 411 | uint8_t is_pre = (insn >> 24) & 0x1; | 621 | u8 is_pre = (insn >> 24) & 0x1; |
| 412 | uint8_t rn = (insn >> 16) & 0xf; | 622 | u8 rn = (insn >> 16) & 0xf; |
| 413 | uint8_t rd = (insn >> 12) & 0xf; | 623 | u8 rd = (insn >> 12) & 0xf; |
| 414 | uint16_t offset = insn & 0xfff; | 624 | u16 offset = insn & 0xfff; |
| 415 | 625 | ||
| 416 | const char *opname = "ldr"; | 626 | const char *opname = "ldr"; |
| 417 | if (!is_load) | 627 | if (!is_load) |
| @@ -448,9 +658,9 @@ std::string ARM_Disasm::DisassembleMem(uint32_t insn) | |||
| 448 | } | 658 | } |
| 449 | } | 659 | } |
| 450 | 660 | ||
| 451 | uint8_t rm = insn & 0xf; | 661 | u8 rm = insn & 0xf; |
| 452 | uint8_t shift_type = (insn >> 5) & 0x3; | 662 | u8 shift_type = (insn >> 5) & 0x3; |
| 453 | uint8_t shift_amount = (insn >> 7) & 0x1f; | 663 | u8 shift_amount = (insn >> 7) & 0x1f; |
| 454 | 664 | ||
| 455 | const char *shift_name = shift_names[shift_type]; | 665 | const char *shift_name = shift_names[shift_type]; |
| 456 | 666 | ||
| @@ -492,19 +702,19 @@ std::string ARM_Disasm::DisassembleMem(uint32_t insn) | |||
| 492 | shift_name, shift_amount); | 702 | shift_name, shift_amount); |
| 493 | } | 703 | } |
| 494 | 704 | ||
| 495 | std::string ARM_Disasm::DisassembleMemHalf(uint32_t insn) | 705 | std::string ARM_Disasm::DisassembleMemHalf(u32 insn) |
| 496 | { | 706 | { |
| 497 | uint8_t cond = (insn >> 28) & 0xf; | 707 | u8 cond = (insn >> 28) & 0xf; |
| 498 | uint8_t is_load = (insn >> 20) & 0x1; | 708 | u8 is_load = (insn >> 20) & 0x1; |
| 499 | uint8_t write_back = (insn >> 21) & 0x1; | 709 | u8 write_back = (insn >> 21) & 0x1; |
| 500 | uint8_t is_immed = (insn >> 22) & 0x1; | 710 | u8 is_immed = (insn >> 22) & 0x1; |
| 501 | uint8_t is_up = (insn >> 23) & 0x1; | 711 | u8 is_up = (insn >> 23) & 0x1; |
| 502 | uint8_t is_pre = (insn >> 24) & 0x1; | 712 | u8 is_pre = (insn >> 24) & 0x1; |
| 503 | uint8_t rn = (insn >> 16) & 0xf; | 713 | u8 rn = (insn >> 16) & 0xf; |
| 504 | uint8_t rd = (insn >> 12) & 0xf; | 714 | u8 rd = (insn >> 12) & 0xf; |
| 505 | uint8_t bits_65 = (insn >> 5) & 0x3; | 715 | u8 bits_65 = (insn >> 5) & 0x3; |
| 506 | uint8_t rm = insn & 0xf; | 716 | u8 rm = insn & 0xf; |
| 507 | uint8_t offset = (((insn >> 8) & 0xf) << 4) | (insn & 0xf); | 717 | u8 offset = (((insn >> 8) & 0xf) << 4) | (insn & 0xf); |
| 508 | 718 | ||
| 509 | const char *opname = "ldr"; | 719 | const char *opname = "ldr"; |
| 510 | if (is_load == 0) | 720 | if (is_load == 0) |
| @@ -548,78 +758,78 @@ std::string ARM_Disasm::DisassembleMemHalf(uint32_t insn) | |||
| 548 | } | 758 | } |
| 549 | } | 759 | } |
| 550 | 760 | ||
| 551 | std::string ARM_Disasm::DisassembleMCR(Opcode opcode, uint32_t insn) | 761 | std::string ARM_Disasm::DisassembleMCR(Opcode opcode, u32 insn) |
| 552 | { | 762 | { |
| 553 | uint8_t cond = (insn >> 28) & 0xf; | 763 | u8 cond = (insn >> 28) & 0xf; |
| 554 | uint8_t crn = (insn >> 16) & 0xf; | 764 | u8 crn = (insn >> 16) & 0xf; |
| 555 | uint8_t crd = (insn >> 12) & 0xf; | 765 | u8 crd = (insn >> 12) & 0xf; |
| 556 | uint8_t cpnum = (insn >> 8) & 0xf; | 766 | u8 cpnum = (insn >> 8) & 0xf; |
| 557 | uint8_t opcode2 = (insn >> 5) & 0x7; | 767 | u8 opcode2 = (insn >> 5) & 0x7; |
| 558 | uint8_t crm = insn & 0xf; | 768 | u8 crm = insn & 0xf; |
| 559 | 769 | ||
| 560 | const char *opname = opcode_names[opcode]; | 770 | const char *opname = opcode_names[opcode]; |
| 561 | return Common::StringFromFormat("%s%s\t%d, 0, r%d, cr%d, cr%d, {%d}", | 771 | return Common::StringFromFormat("%s%s\t%d, 0, r%d, cr%d, cr%d, {%d}", |
| 562 | opname, cond_to_str(cond), cpnum, crd, crn, crm, opcode2); | 772 | opname, cond_to_str(cond), cpnum, crd, crn, crm, opcode2); |
| 563 | } | 773 | } |
| 564 | 774 | ||
| 565 | std::string ARM_Disasm::DisassembleMLA(Opcode opcode, uint32_t insn) | 775 | std::string ARM_Disasm::DisassembleMLA(Opcode opcode, u32 insn) |
| 566 | { | 776 | { |
| 567 | uint8_t cond = (insn >> 28) & 0xf; | 777 | u8 cond = (insn >> 28) & 0xf; |
| 568 | uint8_t rd = (insn >> 16) & 0xf; | 778 | u8 rd = (insn >> 16) & 0xf; |
| 569 | uint8_t rn = (insn >> 12) & 0xf; | 779 | u8 rn = (insn >> 12) & 0xf; |
| 570 | uint8_t rs = (insn >> 8) & 0xf; | 780 | u8 rs = (insn >> 8) & 0xf; |
| 571 | uint8_t rm = insn & 0xf; | 781 | u8 rm = insn & 0xf; |
| 572 | uint8_t bit_s = (insn >> 20) & 1; | 782 | u8 bit_s = (insn >> 20) & 1; |
| 573 | 783 | ||
| 574 | const char *opname = opcode_names[opcode]; | 784 | const char *opname = opcode_names[opcode]; |
| 575 | return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d", | 785 | return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d", |
| 576 | opname, cond_to_str(cond), bit_s ? "s" : "", rd, rm, rs, rn); | 786 | opname, cond_to_str(cond), bit_s ? "s" : "", rd, rm, rs, rn); |
| 577 | } | 787 | } |
| 578 | 788 | ||
| 579 | std::string ARM_Disasm::DisassembleUMLAL(Opcode opcode, uint32_t insn) | 789 | std::string ARM_Disasm::DisassembleUMLAL(Opcode opcode, u32 insn) |
| 580 | { | 790 | { |
| 581 | uint8_t cond = (insn >> 28) & 0xf; | 791 | u8 cond = (insn >> 28) & 0xf; |
| 582 | uint8_t rdhi = (insn >> 16) & 0xf; | 792 | u8 rdhi = (insn >> 16) & 0xf; |
| 583 | uint8_t rdlo = (insn >> 12) & 0xf; | 793 | u8 rdlo = (insn >> 12) & 0xf; |
| 584 | uint8_t rs = (insn >> 8) & 0xf; | 794 | u8 rs = (insn >> 8) & 0xf; |
| 585 | uint8_t rm = insn & 0xf; | 795 | u8 rm = insn & 0xf; |
| 586 | uint8_t bit_s = (insn >> 20) & 1; | 796 | u8 bit_s = (insn >> 20) & 1; |
| 587 | 797 | ||
| 588 | const char *opname = opcode_names[opcode]; | 798 | const char *opname = opcode_names[opcode]; |
| 589 | return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d", | 799 | return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d", |
| 590 | opname, cond_to_str(cond), bit_s ? "s" : "", rdlo, rdhi, rm, rs); | 800 | opname, cond_to_str(cond), bit_s ? "s" : "", rdlo, rdhi, rm, rs); |
| 591 | } | 801 | } |
| 592 | 802 | ||
| 593 | std::string ARM_Disasm::DisassembleMUL(Opcode opcode, uint32_t insn) | 803 | std::string ARM_Disasm::DisassembleMUL(Opcode opcode, u32 insn) |
| 594 | { | 804 | { |
| 595 | uint8_t cond = (insn >> 28) & 0xf; | 805 | u8 cond = (insn >> 28) & 0xf; |
| 596 | uint8_t rd = (insn >> 16) & 0xf; | 806 | u8 rd = (insn >> 16) & 0xf; |
| 597 | uint8_t rs = (insn >> 8) & 0xf; | 807 | u8 rs = (insn >> 8) & 0xf; |
| 598 | uint8_t rm = insn & 0xf; | 808 | u8 rm = insn & 0xf; |
| 599 | uint8_t bit_s = (insn >> 20) & 1; | 809 | u8 bit_s = (insn >> 20) & 1; |
| 600 | 810 | ||
| 601 | const char *opname = opcode_names[opcode]; | 811 | const char *opname = opcode_names[opcode]; |
| 602 | return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d", | 812 | return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d", |
| 603 | opname, cond_to_str(cond), bit_s ? "s" : "", rd, rm, rs); | 813 | opname, cond_to_str(cond), bit_s ? "s" : "", rd, rm, rs); |
| 604 | } | 814 | } |
| 605 | 815 | ||
| 606 | std::string ARM_Disasm::DisassembleMRS(uint32_t insn) | 816 | std::string ARM_Disasm::DisassembleMRS(u32 insn) |
| 607 | { | 817 | { |
| 608 | uint8_t cond = (insn >> 28) & 0xf; | 818 | u8 cond = (insn >> 28) & 0xf; |
| 609 | uint8_t rd = (insn >> 12) & 0xf; | 819 | u8 rd = (insn >> 12) & 0xf; |
| 610 | uint8_t ps = (insn >> 22) & 1; | 820 | u8 ps = (insn >> 22) & 1; |
| 611 | 821 | ||
| 612 | return Common::StringFromFormat("mrs%s\tr%d, %s", cond_to_str(cond), rd, ps ? "spsr" : "cpsr"); | 822 | return Common::StringFromFormat("mrs%s\tr%d, %s", cond_to_str(cond), rd, ps ? "spsr" : "cpsr"); |
| 613 | } | 823 | } |
| 614 | 824 | ||
| 615 | std::string ARM_Disasm::DisassembleMSR(uint32_t insn) | 825 | std::string ARM_Disasm::DisassembleMSR(u32 insn) |
| 616 | { | 826 | { |
| 617 | char flags[8]; | 827 | char flags[8]; |
| 618 | int flag_index = 0; | 828 | int flag_index = 0; |
| 619 | uint8_t cond = (insn >> 28) & 0xf; | 829 | u8 cond = (insn >> 28) & 0xf; |
| 620 | uint8_t is_immed = (insn >> 25) & 0x1; | 830 | u8 is_immed = (insn >> 25) & 0x1; |
| 621 | uint8_t pd = (insn >> 22) & 1; | 831 | u8 pd = (insn >> 22) & 1; |
| 622 | uint8_t mask = (insn >> 16) & 0xf; | 832 | u8 mask = (insn >> 16) & 0xf; |
| 623 | 833 | ||
| 624 | if (mask & 1) | 834 | if (mask & 1) |
| 625 | flags[flag_index++] = 'c'; | 835 | flags[flag_index++] = 'c'; |
| @@ -632,36 +842,76 @@ std::string ARM_Disasm::DisassembleMSR(uint32_t insn) | |||
| 632 | flags[flag_index] = 0; | 842 | flags[flag_index] = 0; |
| 633 | 843 | ||
| 634 | if (is_immed) { | 844 | if (is_immed) { |
| 635 | uint32_t immed = insn & 0xff; | 845 | u32 immed = insn & 0xff; |
| 636 | uint8_t rotate = (insn >> 8) & 0xf; | 846 | u8 rotate = (insn >> 8) & 0xf; |
| 637 | uint8_t rotate2 = rotate << 1; | 847 | u8 rotate2 = rotate << 1; |
| 638 | uint32_t rotated_val = (immed >> rotate2) | (immed << (32 - rotate2)); | 848 | u32 rotated_val = (immed >> rotate2) | (immed << (32 - rotate2)); |
| 639 | return Common::StringFromFormat("msr%s\t%s_%s, #0x%x", | 849 | return Common::StringFromFormat("msr%s\t%s_%s, #0x%x", |
| 640 | cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rotated_val); | 850 | cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rotated_val); |
| 641 | } | 851 | } |
| 642 | 852 | ||
| 643 | uint8_t rm = insn & 0xf; | 853 | u8 rm = insn & 0xf; |
| 644 | 854 | ||
| 645 | return Common::StringFromFormat("msr%s\t%s_%s, r%d", | 855 | return Common::StringFromFormat("msr%s\t%s_%s, r%d", |
| 646 | cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rm); | 856 | cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rm); |
| 647 | } | 857 | } |
| 648 | 858 | ||
| 649 | std::string ARM_Disasm::DisassemblePLD(uint32_t insn) | 859 | std::string ARM_Disasm::DisassembleNoOperands(Opcode opcode, u32 insn) |
| 860 | { | ||
| 861 | u32 cond = BITS(insn, 28, 31); | ||
| 862 | return Common::StringFromFormat("%s%s", opcode_names[opcode], cond_to_str(cond)); | ||
| 863 | } | ||
| 864 | |||
| 865 | std::string ARM_Disasm::DisassembleParallelAddSub(Opcode opcode, u32 insn) { | ||
| 866 | u32 cond = BITS(insn, 28, 31); | ||
| 867 | u32 rn = BITS(insn, 16, 19); | ||
| 868 | u32 rd = BITS(insn, 12, 15); | ||
| 869 | u32 rm = BITS(insn, 0, 3); | ||
| 870 | |||
| 871 | return Common::StringFromFormat("%s%s\tr%u, r%u, r%u", opcode_names[opcode], cond_to_str(cond), | ||
| 872 | rd, rn, rm); | ||
| 873 | } | ||
| 874 | |||
| 875 | std::string ARM_Disasm::DisassemblePKH(u32 insn) | ||
| 876 | { | ||
| 877 | u32 cond = BITS(insn, 28, 31); | ||
| 878 | u32 rn = BITS(insn, 16, 19); | ||
| 879 | u32 rd = BITS(insn, 12, 15); | ||
| 880 | u32 imm5 = BITS(insn, 7, 11); | ||
| 881 | u32 tb = BIT(insn, 6); | ||
| 882 | u32 rm = BITS(insn, 0, 3); | ||
| 883 | |||
| 884 | std::string suffix = tb ? "tb" : "bt"; | ||
| 885 | std::string shift = ""; | ||
| 886 | |||
| 887 | if (tb && imm5 == 0) | ||
| 888 | imm5 = 32; | ||
| 889 | |||
| 890 | if (imm5 > 0) { | ||
| 891 | shift = tb ? ", ASR" : ", LSL"; | ||
| 892 | shift += " #" + std::to_string(imm5); | ||
| 893 | } | ||
| 894 | |||
| 895 | return Common::StringFromFormat("pkh%s%s\tr%u, r%u, r%u%s", suffix.c_str(), cond_to_str(cond), | ||
| 896 | rd, rn, rm, shift.c_str()); | ||
| 897 | } | ||
| 898 | |||
| 899 | std::string ARM_Disasm::DisassemblePLD(u32 insn) | ||
| 650 | { | 900 | { |
| 651 | uint8_t is_reg = (insn >> 25) & 0x1; | 901 | u8 is_reg = (insn >> 25) & 0x1; |
| 652 | uint8_t is_up = (insn >> 23) & 0x1; | 902 | u8 is_up = (insn >> 23) & 0x1; |
| 653 | uint8_t rn = (insn >> 16) & 0xf; | 903 | u8 rn = (insn >> 16) & 0xf; |
| 654 | 904 | ||
| 655 | const char *minus = ""; | 905 | const char *minus = ""; |
| 656 | if (is_up == 0) | 906 | if (is_up == 0) |
| 657 | minus = "-"; | 907 | minus = "-"; |
| 658 | 908 | ||
| 659 | if (is_reg) { | 909 | if (is_reg) { |
| 660 | uint8_t rm = insn & 0xf; | 910 | u8 rm = insn & 0xf; |
| 661 | return Common::StringFromFormat("pld\t[r%d, %sr%d]", rn, minus, rm); | 911 | return Common::StringFromFormat("pld\t[r%d, %sr%d]", rn, minus, rm); |
| 662 | } | 912 | } |
| 663 | 913 | ||
| 664 | uint16_t offset = insn & 0xfff; | 914 | u16 offset = insn & 0xfff; |
| 665 | if (offset == 0) { | 915 | if (offset == 0) { |
| 666 | return Common::StringFromFormat("pld\t[r%d]", rn); | 916 | return Common::StringFromFormat("pld\t[r%d]", rn); |
| 667 | } else { | 917 | } else { |
| @@ -669,27 +919,128 @@ std::string ARM_Disasm::DisassemblePLD(uint32_t insn) | |||
| 669 | } | 919 | } |
| 670 | } | 920 | } |
| 671 | 921 | ||
| 672 | std::string ARM_Disasm::DisassembleSWI(uint32_t insn) | 922 | std::string ARM_Disasm::DisassembleREV(Opcode opcode, u32 insn) { |
| 923 | u32 cond = BITS(insn, 28, 31); | ||
| 924 | u32 rd = BITS(insn, 12, 15); | ||
| 925 | u32 rm = BITS(insn, 0, 3); | ||
| 926 | |||
| 927 | return Common::StringFromFormat("%s%s\tr%u, r%u", opcode_names[opcode], cond_to_str(cond), | ||
| 928 | rd, rm); | ||
| 929 | } | ||
| 930 | |||
| 931 | std::string ARM_Disasm::DisassembleREX(Opcode opcode, u32 insn) { | ||
| 932 | u32 rn = BITS(insn, 16, 19); | ||
| 933 | u32 rd = BITS(insn, 12, 15); | ||
| 934 | u32 rt = BITS(insn, 0, 3); | ||
| 935 | u32 cond = BITS(insn, 28, 31); | ||
| 936 | |||
| 937 | switch (opcode) { | ||
| 938 | case OP_STREX: | ||
| 939 | case OP_STREXB: | ||
| 940 | case OP_STREXH: | ||
| 941 | return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode], | ||
| 942 | cond_to_str(cond), rd, rt, rn); | ||
| 943 | case OP_STREXD: | ||
| 944 | 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); | ||
| 946 | |||
| 947 | // for LDREX instructions, rd corresponds to Rt from reference manual | ||
| 948 | case OP_LDREX: | ||
| 949 | case OP_LDREXB: | ||
| 950 | case OP_LDREXH: | ||
| 951 | return Common::StringFromFormat("%s%s\tr%d, [r%d]", opcode_names[opcode], | ||
| 952 | cond_to_str(cond), rd, rn); | ||
| 953 | case OP_LDREXD: | ||
| 954 | return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode], | ||
| 955 | cond_to_str(cond), rd, rd + 1, rn); | ||
| 956 | default: | ||
| 957 | return opcode_names[OP_UNDEFINED]; | ||
| 958 | } | ||
| 959 | } | ||
| 960 | |||
| 961 | std::string ARM_Disasm::DisassembleSAT(Opcode opcode, u32 insn) { | ||
| 962 | u32 cond = BITS(insn, 28, 31); | ||
| 963 | u32 sat_imm = BITS(insn, 16, 20); | ||
| 964 | u32 rd = BITS(insn, 12, 15); | ||
| 965 | u32 imm5 = BITS(insn, 7, 11); | ||
| 966 | u32 sh = BIT(insn, 6); | ||
| 967 | u32 rn = BITS(insn, 0, 3); | ||
| 968 | |||
| 969 | std::string shift_part = ""; | ||
| 970 | bool opcode_has_shift = (opcode == OP_SSAT) || (opcode == OP_USAT); | ||
| 971 | if (opcode_has_shift && !(sh == 0 && imm5 == 0)) { | ||
| 972 | if (sh == 0) | ||
| 973 | shift_part += ", LSL #"; | ||
| 974 | else | ||
| 975 | shift_part += ", ASR #"; | ||
| 976 | |||
| 977 | if (imm5 == 0) | ||
| 978 | imm5 = 32; | ||
| 979 | shift_part += std::to_string(imm5); | ||
| 980 | } | ||
| 981 | |||
| 982 | if (opcode == OP_SSAT || opcode == OP_SSAT16) | ||
| 983 | sat_imm++; | ||
| 984 | |||
| 985 | return Common::StringFromFormat("%s%s\tr%u, #%u, r%u%s", opcode_names[opcode], cond_to_str(cond), rd, | ||
| 986 | sat_imm, rn, shift_part.c_str()); | ||
| 987 | } | ||
| 988 | |||
| 989 | std::string ARM_Disasm::DisassembleSEL(u32 insn) { | ||
| 990 | u32 cond = BITS(insn, 28, 31); | ||
| 991 | u32 rn = BITS(insn, 16, 19); | ||
| 992 | u32 rd = BITS(insn, 12, 15); | ||
| 993 | u32 rm = BITS(insn, 0, 3); | ||
| 994 | |||
| 995 | return Common::StringFromFormat("%s%s\tr%u, r%u, r%u", opcode_names[OP_SEL], cond_to_str(cond), | ||
| 996 | rd, rn, rm); | ||
| 997 | } | ||
| 998 | |||
| 999 | std::string ARM_Disasm::DisassembleSWI(u32 insn) | ||
| 673 | { | 1000 | { |
| 674 | uint8_t cond = (insn >> 28) & 0xf; | 1001 | u8 cond = (insn >> 28) & 0xf; |
| 675 | uint32_t sysnum = insn & 0x00ffffff; | 1002 | u32 sysnum = insn & 0x00ffffff; |
| 676 | 1003 | ||
| 677 | return Common::StringFromFormat("swi%s 0x%x", cond_to_str(cond), sysnum); | 1004 | return Common::StringFromFormat("swi%s 0x%x", cond_to_str(cond), sysnum); |
| 678 | } | 1005 | } |
| 679 | 1006 | ||
| 680 | std::string ARM_Disasm::DisassembleSWP(Opcode opcode, uint32_t insn) | 1007 | std::string ARM_Disasm::DisassembleSWP(Opcode opcode, u32 insn) |
| 681 | { | 1008 | { |
| 682 | uint8_t cond = (insn >> 28) & 0xf; | 1009 | u8 cond = (insn >> 28) & 0xf; |
| 683 | uint8_t rn = (insn >> 16) & 0xf; | 1010 | u8 rn = (insn >> 16) & 0xf; |
| 684 | uint8_t rd = (insn >> 12) & 0xf; | 1011 | u8 rd = (insn >> 12) & 0xf; |
| 685 | uint8_t rm = insn & 0xf; | 1012 | u8 rm = insn & 0xf; |
| 686 | 1013 | ||
| 687 | const char *opname = opcode_names[opcode]; | 1014 | const char *opname = opcode_names[opcode]; |
| 688 | return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opname, cond_to_str(cond), rd, rm, rn); | 1015 | return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opname, cond_to_str(cond), rd, rm, rn); |
| 689 | } | 1016 | } |
| 690 | 1017 | ||
| 691 | Opcode ARM_Disasm::Decode(uint32_t insn) { | 1018 | std::string ARM_Disasm::DisassembleXT(Opcode opcode, u32 insn) |
| 692 | uint32_t bits27_26 = (insn >> 26) & 0x3; | 1019 | { |
| 1020 | u32 cond = BITS(insn, 28, 31); | ||
| 1021 | u32 rn = BITS(insn, 16, 19); | ||
| 1022 | u32 rd = BITS(insn, 12, 15); | ||
| 1023 | u32 rotate = BITS(insn, 10, 11); | ||
| 1024 | u32 rm = BITS(insn, 0, 3); | ||
| 1025 | |||
| 1026 | std::string rn_part = ""; | ||
| 1027 | static std::unordered_set<Opcode, std::hash<int>> extend_with_add = { | ||
| 1028 | OP_SXTAB, OP_SXTAB16, OP_SXTAH, | ||
| 1029 | OP_UXTAB, OP_UXTAB16, OP_UXTAH | ||
| 1030 | }; | ||
| 1031 | if (extend_with_add.find(opcode) != extend_with_add.end()) | ||
| 1032 | rn_part = ", r" + std::to_string(rn); | ||
| 1033 | |||
| 1034 | std::string rotate_part = ""; | ||
| 1035 | if (rotate != 0) | ||
| 1036 | rotate_part = ", ROR #" + std::to_string(rotate << 3); | ||
| 1037 | |||
| 1038 | return Common::StringFromFormat("%s%s\tr%u%s, r%u%s", opcode_names[opcode], cond_to_str(cond), | ||
| 1039 | rd, rn_part.c_str(), rm, rotate_part.c_str()); | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | Opcode ARM_Disasm::Decode(u32 insn) { | ||
| 1043 | u32 bits27_26 = (insn >> 26) & 0x3; | ||
| 693 | switch (bits27_26) { | 1044 | switch (bits27_26) { |
| 694 | case 0x0: | 1045 | case 0x0: |
| 695 | return Decode00(insn); | 1046 | return Decode00(insn); |
| @@ -703,9 +1054,9 @@ Opcode ARM_Disasm::Decode(uint32_t insn) { | |||
| 703 | return OP_INVALID; | 1054 | return OP_INVALID; |
| 704 | } | 1055 | } |
| 705 | 1056 | ||
| 706 | Opcode ARM_Disasm::Decode00(uint32_t insn) { | 1057 | Opcode ARM_Disasm::Decode00(u32 insn) { |
| 707 | uint8_t bit25 = (insn >> 25) & 0x1; | 1058 | u8 bit25 = (insn >> 25) & 0x1; |
| 708 | uint8_t bit4 = (insn >> 4) & 0x1; | 1059 | u8 bit4 = (insn >> 4) & 0x1; |
| 709 | if (bit25 == 0 && bit4 == 1) { | 1060 | if (bit25 == 0 && bit4 == 1) { |
| 710 | if ((insn & 0x0ffffff0) == 0x012fff10) { | 1061 | if ((insn & 0x0ffffff0) == 0x012fff10) { |
| 711 | // Bx instruction | 1062 | // Bx instruction |
| @@ -719,41 +1070,48 @@ Opcode ARM_Disasm::Decode00(uint32_t insn) { | |||
| 719 | // Bkpt instruction | 1070 | // Bkpt instruction |
| 720 | return OP_BKPT; | 1071 | return OP_BKPT; |
| 721 | } | 1072 | } |
| 722 | uint32_t bits7_4 = (insn >> 4) & 0xf; | 1073 | u32 bits7_4 = (insn >> 4) & 0xf; |
| 723 | if (bits7_4 == 0x9) { | 1074 | if (bits7_4 == 0x9) { |
| 724 | if ((insn & 0x0ff00ff0) == 0x01000090) { | 1075 | u32 bit24 = BIT(insn, 24); |
| 725 | // Swp instruction | 1076 | if (bit24) { |
| 726 | uint8_t bit22 = (insn >> 22) & 0x1; | 1077 | return DecodeSyncPrimitive(insn); |
| 727 | if (bit22) | ||
| 728 | return OP_SWPB; | ||
| 729 | return OP_SWP; | ||
| 730 | } | 1078 | } |
| 731 | // One of the multiply instructions | 1079 | // One of the multiply instructions |
| 732 | return DecodeMUL(insn); | 1080 | return DecodeMUL(insn); |
| 733 | } | 1081 | } |
| 734 | 1082 | ||
| 735 | uint8_t bit7 = (insn >> 7) & 0x1; | 1083 | u8 bit7 = (insn >> 7) & 0x1; |
| 736 | if (bit7 == 1) { | 1084 | if (bit7 == 1) { |
| 737 | // One of the load/store halfword/byte instructions | 1085 | // One of the load/store halfword/byte instructions |
| 738 | return DecodeLDRH(insn); | 1086 | return DecodeLDRH(insn); |
| 739 | } | 1087 | } |
| 740 | } | 1088 | } |
| 741 | 1089 | ||
| 1090 | u32 op1 = BITS(insn, 20, 24); | ||
| 1091 | if (bit25 && (op1 == 0x12 || op1 == 0x16)) { | ||
| 1092 | // One of the MSR (immediate) and hints instructions | ||
| 1093 | return DecodeMSRImmAndHints(insn); | ||
| 1094 | } | ||
| 1095 | |||
| 742 | // One of the data processing instructions | 1096 | // One of the data processing instructions |
| 743 | return DecodeALU(insn); | 1097 | return DecodeALU(insn); |
| 744 | } | 1098 | } |
| 745 | 1099 | ||
| 746 | Opcode ARM_Disasm::Decode01(uint32_t insn) { | 1100 | Opcode ARM_Disasm::Decode01(u32 insn) { |
| 747 | uint8_t is_reg = (insn >> 25) & 0x1; | 1101 | u8 is_reg = (insn >> 25) & 0x1; |
| 748 | uint8_t bit4 = (insn >> 4) & 0x1; | 1102 | u8 bit4 = (insn >> 4) & 0x1; |
| 749 | if (is_reg == 1 && bit4 == 1) | 1103 | if (is_reg == 1 && bit4 == 1) |
| 750 | return OP_UNDEFINED; | 1104 | return DecodeMedia(insn); |
| 751 | uint8_t is_load = (insn >> 20) & 0x1; | 1105 | u8 is_load = (insn >> 20) & 0x1; |
| 752 | uint8_t is_byte = (insn >> 22) & 0x1; | 1106 | u8 is_byte = (insn >> 22) & 0x1; |
| 753 | if ((insn & 0xfd70f000) == 0xf550f000) { | 1107 | if ((insn & 0xfd70f000) == 0xf550f000) { |
| 754 | // Pre-load | 1108 | // Pre-load |
| 755 | return OP_PLD; | 1109 | return OP_PLD; |
| 756 | } | 1110 | } |
| 1111 | if (insn == 0xf57ff01f) { | ||
| 1112 | // Clear-Exclusive | ||
| 1113 | return OP_CLREX; | ||
| 1114 | } | ||
| 757 | if (is_load) { | 1115 | if (is_load) { |
| 758 | if (is_byte) { | 1116 | if (is_byte) { |
| 759 | // Load byte | 1117 | // Load byte |
| @@ -770,36 +1128,28 @@ Opcode ARM_Disasm::Decode01(uint32_t insn) { | |||
| 770 | return OP_STR; | 1128 | return OP_STR; |
| 771 | } | 1129 | } |
| 772 | 1130 | ||
| 773 | Opcode ARM_Disasm::Decode10(uint32_t insn) { | 1131 | Opcode ARM_Disasm::Decode10(u32 insn) { |
| 774 | uint8_t bit25 = (insn >> 25) & 0x1; | 1132 | u8 bit25 = (insn >> 25) & 0x1; |
| 775 | if (bit25 == 0) { | 1133 | if (bit25 == 0) { |
| 776 | // LDM/STM | 1134 | // LDM/STM |
| 777 | uint8_t is_load = (insn >> 20) & 0x1; | 1135 | u8 is_load = (insn >> 20) & 0x1; |
| 778 | if (is_load) | 1136 | if (is_load) |
| 779 | return OP_LDM; | 1137 | return OP_LDM; |
| 780 | return OP_STM; | 1138 | return OP_STM; |
| 781 | } | 1139 | } |
| 782 | // Branch or Branch with link | ||
| 783 | uint8_t is_link = (insn >> 24) & 1; | ||
| 784 | uint32_t offset = insn & 0xffffff; | ||
| 785 | 1140 | ||
| 786 | // Sign-extend the 24-bit offset | 1141 | // Branch with link |
| 787 | if ((offset >> 23) & 1) | 1142 | if ((insn >> 24) & 1) |
| 788 | offset |= 0xff000000; | 1143 | return OP_BL; |
| 789 | 1144 | ||
| 790 | // Pre-compute the left-shift and the prefetch offset | 1145 | return OP_B; |
| 791 | offset <<= 2; | ||
| 792 | offset += 8; | ||
| 793 | if (is_link == 0) | ||
| 794 | return OP_B; | ||
| 795 | return OP_BL; | ||
| 796 | } | 1146 | } |
| 797 | 1147 | ||
| 798 | Opcode ARM_Disasm::Decode11(uint32_t insn) { | 1148 | Opcode ARM_Disasm::Decode11(u32 insn) { |
| 799 | uint8_t bit25 = (insn >> 25) & 0x1; | 1149 | u8 bit25 = (insn >> 25) & 0x1; |
| 800 | if (bit25 == 0) { | 1150 | if (bit25 == 0) { |
| 801 | // LDC, SDC | 1151 | // LDC, SDC |
| 802 | uint8_t is_load = (insn >> 20) & 0x1; | 1152 | u8 is_load = (insn >> 20) & 0x1; |
| 803 | if (is_load) { | 1153 | if (is_load) { |
| 804 | // LDC | 1154 | // LDC |
| 805 | return OP_LDC; | 1155 | return OP_LDC; |
| @@ -808,18 +1158,18 @@ Opcode ARM_Disasm::Decode11(uint32_t insn) { | |||
| 808 | return OP_STC; | 1158 | return OP_STC; |
| 809 | } | 1159 | } |
| 810 | 1160 | ||
| 811 | uint8_t bit24 = (insn >> 24) & 0x1; | 1161 | u8 bit24 = (insn >> 24) & 0x1; |
| 812 | if (bit24 == 0x1) { | 1162 | if (bit24 == 0x1) { |
| 813 | // SWI | 1163 | // SWI |
| 814 | return OP_SWI; | 1164 | return OP_SWI; |
| 815 | } | 1165 | } |
| 816 | 1166 | ||
| 817 | uint8_t bit4 = (insn >> 4) & 0x1; | 1167 | u8 bit4 = (insn >> 4) & 0x1; |
| 818 | uint8_t cpnum = (insn >> 8) & 0xf; | 1168 | u8 cpnum = (insn >> 8) & 0xf; |
| 819 | 1169 | ||
| 820 | if (cpnum == 15) { | 1170 | if (cpnum == 15) { |
| 821 | // Special case for coprocessor 15 | 1171 | // Special case for coprocessor 15 |
| 822 | uint8_t opcode = (insn >> 21) & 0x7; | 1172 | u8 opcode = (insn >> 21) & 0x7; |
| 823 | if (bit4 == 0 || opcode != 0) { | 1173 | if (bit4 == 0 || opcode != 0) { |
| 824 | // This is an unexpected bit pattern. Create an undefined | 1174 | // This is an unexpected bit pattern. Create an undefined |
| 825 | // instruction in case this is ever executed. | 1175 | // instruction in case this is ever executed. |
| @@ -827,7 +1177,7 @@ Opcode ARM_Disasm::Decode11(uint32_t insn) { | |||
| 827 | } | 1177 | } |
| 828 | 1178 | ||
| 829 | // MRC, MCR | 1179 | // MRC, MCR |
| 830 | uint8_t is_mrc = (insn >> 20) & 0x1; | 1180 | u8 is_mrc = (insn >> 20) & 0x1; |
| 831 | if (is_mrc) | 1181 | if (is_mrc) |
| 832 | return OP_MRC; | 1182 | return OP_MRC; |
| 833 | return OP_MCR; | 1183 | return OP_MCR; |
| @@ -838,22 +1188,165 @@ Opcode ARM_Disasm::Decode11(uint32_t insn) { | |||
| 838 | return OP_CDP; | 1188 | return OP_CDP; |
| 839 | } | 1189 | } |
| 840 | // MRC, MCR | 1190 | // MRC, MCR |
| 841 | uint8_t is_mrc = (insn >> 20) & 0x1; | 1191 | u8 is_mrc = (insn >> 20) & 0x1; |
| 842 | if (is_mrc) | 1192 | if (is_mrc) |
| 843 | return OP_MRC; | 1193 | return OP_MRC; |
| 844 | return OP_MCR; | 1194 | return OP_MCR; |
| 845 | } | 1195 | } |
| 846 | 1196 | ||
| 847 | Opcode ARM_Disasm::DecodeMUL(uint32_t insn) { | 1197 | Opcode ARM_Disasm::DecodeSyncPrimitive(u32 insn) { |
| 848 | uint8_t bit24 = (insn >> 24) & 0x1; | 1198 | u32 op = BITS(insn, 20, 23); |
| 1199 | u32 bit22 = BIT(insn, 22); | ||
| 1200 | switch (op) { | ||
| 1201 | case 0x0: | ||
| 1202 | if (bit22) | ||
| 1203 | return OP_SWPB; | ||
| 1204 | return OP_SWP; | ||
| 1205 | case 0x8: | ||
| 1206 | return OP_STREX; | ||
| 1207 | case 0x9: | ||
| 1208 | return OP_LDREX; | ||
| 1209 | case 0xA: | ||
| 1210 | return OP_STREXD; | ||
| 1211 | case 0xB: | ||
| 1212 | return OP_LDREXD; | ||
| 1213 | case 0xC: | ||
| 1214 | return OP_STREXB; | ||
| 1215 | case 0xD: | ||
| 1216 | return OP_LDREXB; | ||
| 1217 | case 0xE: | ||
| 1218 | return OP_STREXH; | ||
| 1219 | case 0xF: | ||
| 1220 | return OP_LDREXH; | ||
| 1221 | default: | ||
| 1222 | return OP_UNDEFINED; | ||
| 1223 | } | ||
| 1224 | } | ||
| 1225 | |||
| 1226 | Opcode ARM_Disasm::DecodeParallelAddSub(u32 insn) { | ||
| 1227 | u32 op1 = BITS(insn, 20, 21); | ||
| 1228 | u32 op2 = BITS(insn, 5, 7); | ||
| 1229 | u32 is_unsigned = BIT(insn, 22); | ||
| 1230 | |||
| 1231 | if (op1 == 0x0 || op2 == 0x5 || op2 == 0x6) | ||
| 1232 | return OP_UNDEFINED; | ||
| 1233 | |||
| 1234 | // change op1 range from [1, 3] to range [0, 2] | ||
| 1235 | op1--; | ||
| 1236 | |||
| 1237 | // change op2 range from [0, 4] U {7} to range [0, 5] | ||
| 1238 | if (op2 == 0x7) | ||
| 1239 | op2 = 0x5; | ||
| 1240 | |||
| 1241 | static std::vector<Opcode> opcodes = { | ||
| 1242 | // op1 = 0 | ||
| 1243 | OP_SADD16, OP_UADD16, | ||
| 1244 | OP_SASX, OP_UASX, | ||
| 1245 | OP_SSAX, OP_USAX, | ||
| 1246 | OP_SSUB16, OP_USUB16, | ||
| 1247 | OP_SADD8, OP_UADD8, | ||
| 1248 | OP_SSUB8, OP_USUB8, | ||
| 1249 | // op1 = 1 | ||
| 1250 | OP_QADD16, OP_UQADD16, | ||
| 1251 | OP_QASX, OP_UQASX, | ||
| 1252 | OP_QSAX, OP_UQSAX, | ||
| 1253 | OP_QSUB16, OP_UQSUB16, | ||
| 1254 | OP_QADD8, OP_UQADD8, | ||
| 1255 | OP_QSUB8, OP_UQSUB8, | ||
| 1256 | // op1 = 2 | ||
| 1257 | OP_SHADD16, OP_UHADD16, | ||
| 1258 | OP_SHASX, OP_UHASX, | ||
| 1259 | OP_SHSAX, OP_UHSAX, | ||
| 1260 | OP_SHSUB16, OP_UHSUB16, | ||
| 1261 | OP_SHADD8, OP_UHADD8, | ||
| 1262 | OP_SHSUB8, OP_UHSUB8 | ||
| 1263 | }; | ||
| 1264 | |||
| 1265 | u32 opcode_index = op1 * 12 + op2 * 2 + is_unsigned; | ||
| 1266 | return opcodes[opcode_index]; | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | Opcode ARM_Disasm::DecodePackingSaturationReversal(u32 insn) { | ||
| 1270 | u32 op1 = BITS(insn, 20, 22); | ||
| 1271 | u32 a = BITS(insn, 16, 19); | ||
| 1272 | u32 op2 = BITS(insn, 5, 7); | ||
| 1273 | |||
| 1274 | switch (op1) { | ||
| 1275 | case 0x0: | ||
| 1276 | if (BIT(op2, 0) == 0) | ||
| 1277 | return OP_PKH; | ||
| 1278 | if (op2 == 0x3 && a != 0xf) | ||
| 1279 | return OP_SXTAB16; | ||
| 1280 | if (op2 == 0x3 && a == 0xf) | ||
| 1281 | return OP_SXTB16; | ||
| 1282 | if (op2 == 0x5) | ||
| 1283 | return OP_SEL; | ||
| 1284 | break; | ||
| 1285 | case 0x2: | ||
| 1286 | if (BIT(op2, 0) == 0) | ||
| 1287 | return OP_SSAT; | ||
| 1288 | if (op2 == 0x1) | ||
| 1289 | return OP_SSAT16; | ||
| 1290 | if (op2 == 0x3 && a != 0xf) | ||
| 1291 | return OP_SXTAB; | ||
| 1292 | if (op2 == 0x3 && a == 0xf) | ||
| 1293 | return OP_SXTB; | ||
| 1294 | break; | ||
| 1295 | case 0x3: | ||
| 1296 | if (op2 == 0x1) | ||
| 1297 | return OP_REV; | ||
| 1298 | if (BIT(op2, 0) == 0) | ||
| 1299 | return OP_SSAT; | ||
| 1300 | if (op2 == 0x3 && a != 0xf) | ||
| 1301 | return OP_SXTAH; | ||
| 1302 | if (op2 == 0x3 && a == 0xf) | ||
| 1303 | return OP_SXTH; | ||
| 1304 | if (op2 == 0x5) | ||
| 1305 | return OP_REV16; | ||
| 1306 | break; | ||
| 1307 | case 0x4: | ||
| 1308 | if (op2 == 0x3 && a != 0xf) | ||
| 1309 | return OP_UXTAB16; | ||
| 1310 | if (op2 == 0x3 && a == 0xf) | ||
| 1311 | return OP_UXTB16; | ||
| 1312 | break; | ||
| 1313 | case 0x6: | ||
| 1314 | if (BIT(op2, 0) == 0) | ||
| 1315 | return OP_USAT; | ||
| 1316 | if (op2 == 0x1) | ||
| 1317 | return OP_USAT16; | ||
| 1318 | if (op2 == 0x3 && a != 0xf) | ||
| 1319 | return OP_UXTAB; | ||
| 1320 | if (op2 == 0x3 && a == 0xf) | ||
| 1321 | return OP_UXTB; | ||
| 1322 | break; | ||
| 1323 | case 0x7: | ||
| 1324 | if (BIT(op2, 0) == 0) | ||
| 1325 | return OP_USAT; | ||
| 1326 | if (op2 == 0x3 && a != 0xf) | ||
| 1327 | return OP_UXTAH; | ||
| 1328 | if (op2 == 0x3 && a == 0xf) | ||
| 1329 | return OP_UXTH; | ||
| 1330 | if (op2 == 0x5) | ||
| 1331 | return OP_REVSH; | ||
| 1332 | break; | ||
| 1333 | default: | ||
| 1334 | break; | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | return OP_UNDEFINED; | ||
| 1338 | } | ||
| 1339 | |||
| 1340 | Opcode ARM_Disasm::DecodeMUL(u32 insn) { | ||
| 1341 | u8 bit24 = (insn >> 24) & 0x1; | ||
| 849 | if (bit24 != 0) { | 1342 | if (bit24 != 0) { |
| 850 | // This is an unexpected bit pattern. Create an undefined | 1343 | // This is an unexpected bit pattern. Create an undefined |
| 851 | // instruction in case this is ever executed. | 1344 | // instruction in case this is ever executed. |
| 852 | return OP_UNDEFINED; | 1345 | return OP_UNDEFINED; |
| 853 | } | 1346 | } |
| 854 | uint8_t bit23 = (insn >> 23) & 0x1; | 1347 | u8 bit23 = (insn >> 23) & 0x1; |
| 855 | uint8_t bit22_U = (insn >> 22) & 0x1; | 1348 | u8 bit22_U = (insn >> 22) & 0x1; |
| 856 | uint8_t bit21_A = (insn >> 21) & 0x1; | 1349 | u8 bit21_A = (insn >> 21) & 0x1; |
| 857 | if (bit23 == 0) { | 1350 | if (bit23 == 0) { |
| 858 | // 32-bit multiply | 1351 | // 32-bit multiply |
| 859 | if (bit22_U != 0) { | 1352 | if (bit22_U != 0) { |
| @@ -878,9 +1371,104 @@ Opcode ARM_Disasm::DecodeMUL(uint32_t insn) { | |||
| 878 | return OP_SMLAL; | 1371 | return OP_SMLAL; |
| 879 | } | 1372 | } |
| 880 | 1373 | ||
| 881 | Opcode ARM_Disasm::DecodeLDRH(uint32_t insn) { | 1374 | Opcode ARM_Disasm::DecodeMSRImmAndHints(u32 insn) { |
| 882 | uint8_t is_load = (insn >> 20) & 0x1; | 1375 | u32 op = BIT(insn, 22); |
| 883 | uint8_t bits_65 = (insn >> 5) & 0x3; | 1376 | u32 op1 = BITS(insn, 16, 19); |
| 1377 | u32 op2 = BITS(insn, 0, 7); | ||
| 1378 | |||
| 1379 | if (op == 0 && op1 == 0) { | ||
| 1380 | switch (op2) { | ||
| 1381 | case 0x0: | ||
| 1382 | return OP_NOP; | ||
| 1383 | case 0x1: | ||
| 1384 | return OP_YIELD; | ||
| 1385 | case 0x2: | ||
| 1386 | return OP_WFE; | ||
| 1387 | case 0x3: | ||
| 1388 | return OP_WFI; | ||
| 1389 | case 0x4: | ||
| 1390 | return OP_SEV; | ||
| 1391 | default: | ||
| 1392 | return OP_UNDEFINED; | ||
| 1393 | } | ||
| 1394 | } | ||
| 1395 | |||
| 1396 | return OP_MSR; | ||
| 1397 | } | ||
| 1398 | |||
| 1399 | Opcode ARM_Disasm::DecodeMediaMulDiv(u32 insn) { | ||
| 1400 | u32 op1 = BITS(insn, 20, 22); | ||
| 1401 | u32 op2_h = BITS(insn, 6, 7); | ||
| 1402 | u32 a = BITS(insn, 12, 15); | ||
| 1403 | |||
| 1404 | switch (op1) { | ||
| 1405 | case 0x0: | ||
| 1406 | if (op2_h == 0x0) { | ||
| 1407 | if (a != 0xf) | ||
| 1408 | return OP_SMLAD; | ||
| 1409 | else | ||
| 1410 | return OP_SMUAD; | ||
| 1411 | } else if (op2_h == 0x1) { | ||
| 1412 | if (a != 0xf) | ||
| 1413 | return OP_SMLSD; | ||
| 1414 | else | ||
| 1415 | return OP_SMUSD; | ||
| 1416 | } | ||
| 1417 | break; | ||
| 1418 | case 0x4: | ||
| 1419 | if (op2_h == 0x0) | ||
| 1420 | return OP_SMLALD; | ||
| 1421 | else if (op2_h == 0x1) | ||
| 1422 | return OP_SMLSLD; | ||
| 1423 | break; | ||
| 1424 | case 0x5: | ||
| 1425 | if (op2_h == 0x0) { | ||
| 1426 | if (a != 0xf) | ||
| 1427 | return OP_SMMLA; | ||
| 1428 | else | ||
| 1429 | return OP_SMMUL; | ||
| 1430 | } else if (op2_h == 0x3) { | ||
| 1431 | return OP_SMMLS; | ||
| 1432 | } | ||
| 1433 | break; | ||
| 1434 | default: | ||
| 1435 | break; | ||
| 1436 | } | ||
| 1437 | |||
| 1438 | return OP_UNDEFINED; | ||
| 1439 | } | ||
| 1440 | |||
| 1441 | Opcode ARM_Disasm::DecodeMedia(u32 insn) { | ||
| 1442 | u32 op1 = BITS(insn, 20, 24); | ||
| 1443 | u32 rd = BITS(insn, 12, 15); | ||
| 1444 | u32 op2 = BITS(insn, 5, 7); | ||
| 1445 | |||
| 1446 | switch (BITS(op1, 3, 4)) { | ||
| 1447 | case 0x0: | ||
| 1448 | // unsigned and signed parallel addition and subtraction | ||
| 1449 | return DecodeParallelAddSub(insn); | ||
| 1450 | case 0x1: | ||
| 1451 | // Packing, unpacking, saturation, and reversal | ||
| 1452 | return DecodePackingSaturationReversal(insn); | ||
| 1453 | case 0x2: | ||
| 1454 | // Signed multiply, signed and unsigned divide | ||
| 1455 | return DecodeMediaMulDiv(insn); | ||
| 1456 | case 0x3: | ||
| 1457 | if (op2 == 0 && rd == 0xf) | ||
| 1458 | return OP_USAD8; | ||
| 1459 | if (op2 == 0 && rd != 0xf) | ||
| 1460 | return OP_USADA8; | ||
| 1461 | break; | ||
| 1462 | default: | ||
| 1463 | break; | ||
| 1464 | } | ||
| 1465 | |||
| 1466 | return OP_UNDEFINED; | ||
| 1467 | } | ||
| 1468 | |||
| 1469 | Opcode ARM_Disasm::DecodeLDRH(u32 insn) { | ||
| 1470 | u8 is_load = (insn >> 20) & 0x1; | ||
| 1471 | u8 bits_65 = (insn >> 5) & 0x3; | ||
| 884 | if (is_load) { | 1472 | if (is_load) { |
| 885 | if (bits_65 == 0x1) { | 1473 | if (bits_65 == 0x1) { |
| 886 | // Load unsigned halfword | 1474 | // Load unsigned halfword |
| @@ -908,12 +1496,12 @@ Opcode ARM_Disasm::DecodeLDRH(uint32_t insn) { | |||
| 908 | return OP_STRH; | 1496 | return OP_STRH; |
| 909 | } | 1497 | } |
| 910 | 1498 | ||
| 911 | Opcode ARM_Disasm::DecodeALU(uint32_t insn) { | 1499 | Opcode ARM_Disasm::DecodeALU(u32 insn) { |
| 912 | uint8_t is_immed = (insn >> 25) & 0x1; | 1500 | u8 is_immed = (insn >> 25) & 0x1; |
| 913 | uint8_t opcode = (insn >> 21) & 0xf; | 1501 | u8 opcode = (insn >> 21) & 0xf; |
| 914 | uint8_t bit_s = (insn >> 20) & 1; | 1502 | u8 bit_s = (insn >> 20) & 1; |
| 915 | uint8_t shift_is_reg = (insn >> 4) & 1; | 1503 | u8 shift_is_reg = (insn >> 4) & 1; |
| 916 | uint8_t bit7 = (insn >> 7) & 1; | 1504 | u8 bit7 = (insn >> 7) & 1; |
| 917 | if (!is_immed && shift_is_reg && (bit7 != 0)) { | 1505 | if (!is_immed && shift_is_reg && (bit7 != 0)) { |
| 918 | // This is an unexpected bit pattern. Create an undefined | 1506 | // This is an unexpected bit pattern. Create an undefined |
| 919 | // instruction in case this is ever executed. | 1507 | // instruction in case this is ever executed. |
diff --git a/src/core/arm/disassembler/arm_disasm.h b/src/core/arm/disassembler/arm_disasm.h index f94bd4669..53d9c6a74 100644 --- a/src/core/arm/disassembler/arm_disasm.h +++ b/src/core/arm/disassembler/arm_disasm.h | |||
| @@ -2,9 +2,10 @@ | |||
| 2 | 2 | ||
| 3 | #pragma once | 3 | #pragma once |
| 4 | 4 | ||
| 5 | #include <cstdint> | ||
| 6 | #include <string> | 5 | #include <string> |
| 7 | 6 | ||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 8 | // Note: this list of opcodes must match the list used to initialize | 9 | // Note: this list of opcodes must match the list used to initialize |
| 9 | // the opflags[] array in opcode.cpp. | 10 | // the opflags[] array in opcode.cpp. |
| 10 | enum Opcode { | 11 | enum Opcode { |
| @@ -20,6 +21,7 @@ enum Opcode { | |||
| 20 | OP_BLX, | 21 | OP_BLX, |
| 21 | OP_BX, | 22 | OP_BX, |
| 22 | OP_CDP, | 23 | OP_CDP, |
| 24 | OP_CLREX, | ||
| 23 | OP_CLZ, | 25 | OP_CLZ, |
| 24 | OP_CMN, | 26 | OP_CMN, |
| 25 | OP_CMP, | 27 | OP_CMP, |
| @@ -29,6 +31,10 @@ enum Opcode { | |||
| 29 | OP_LDR, | 31 | OP_LDR, |
| 30 | OP_LDRB, | 32 | OP_LDRB, |
| 31 | OP_LDRBT, | 33 | OP_LDRBT, |
| 34 | OP_LDREX, | ||
| 35 | OP_LDREXB, | ||
| 36 | OP_LDREXD, | ||
| 37 | OP_LDREXH, | ||
| 32 | OP_LDRH, | 38 | OP_LDRH, |
| 33 | OP_LDRSB, | 39 | OP_LDRSB, |
| 34 | OP_LDRSH, | 40 | OP_LDRSH, |
| @@ -41,28 +47,105 @@ enum Opcode { | |||
| 41 | OP_MSR, | 47 | OP_MSR, |
| 42 | OP_MUL, | 48 | OP_MUL, |
| 43 | OP_MVN, | 49 | OP_MVN, |
| 50 | OP_NOP, | ||
| 44 | OP_ORR, | 51 | OP_ORR, |
| 52 | OP_PKH, | ||
| 45 | OP_PLD, | 53 | OP_PLD, |
| 54 | OP_QADD16, | ||
| 55 | OP_QADD8, | ||
| 56 | OP_QASX, | ||
| 57 | OP_QSAX, | ||
| 58 | OP_QSUB16, | ||
| 59 | OP_QSUB8, | ||
| 60 | OP_REV, | ||
| 61 | OP_REV16, | ||
| 62 | OP_REVSH, | ||
| 46 | OP_RSB, | 63 | OP_RSB, |
| 47 | OP_RSC, | 64 | OP_RSC, |
| 65 | OP_SADD16, | ||
| 66 | OP_SADD8, | ||
| 67 | OP_SASX, | ||
| 48 | OP_SBC, | 68 | OP_SBC, |
| 69 | OP_SEL, | ||
| 70 | OP_SEV, | ||
| 71 | OP_SHADD16, | ||
| 72 | OP_SHADD8, | ||
| 73 | OP_SHASX, | ||
| 74 | OP_SHSAX, | ||
| 75 | OP_SHSUB16, | ||
| 76 | OP_SHSUB8, | ||
| 77 | OP_SMLAD, | ||
| 49 | OP_SMLAL, | 78 | OP_SMLAL, |
| 79 | OP_SMLALD, | ||
| 80 | OP_SMLSD, | ||
| 81 | OP_SMLSLD, | ||
| 82 | OP_SMMLA, | ||
| 83 | OP_SMMLS, | ||
| 84 | OP_SMMUL, | ||
| 85 | OP_SMUAD, | ||
| 50 | OP_SMULL, | 86 | OP_SMULL, |
| 87 | OP_SMUSD, | ||
| 88 | OP_SSAT, | ||
| 89 | OP_SSAT16, | ||
| 90 | OP_SSAX, | ||
| 91 | OP_SSUB16, | ||
| 92 | OP_SSUB8, | ||
| 51 | OP_STC, | 93 | OP_STC, |
| 52 | OP_STM, | 94 | OP_STM, |
| 53 | OP_STR, | 95 | OP_STR, |
| 54 | OP_STRB, | 96 | OP_STRB, |
| 55 | OP_STRBT, | 97 | OP_STRBT, |
| 98 | OP_STREX, | ||
| 99 | OP_STREXB, | ||
| 100 | OP_STREXD, | ||
| 101 | OP_STREXH, | ||
| 56 | OP_STRH, | 102 | OP_STRH, |
| 57 | OP_STRT, | 103 | OP_STRT, |
| 58 | OP_SUB, | 104 | OP_SUB, |
| 59 | OP_SWI, | 105 | OP_SWI, |
| 60 | OP_SWP, | 106 | OP_SWP, |
| 61 | OP_SWPB, | 107 | OP_SWPB, |
| 108 | OP_SXTAB, | ||
| 109 | OP_SXTAB16, | ||
| 110 | OP_SXTAH, | ||
| 111 | OP_SXTB, | ||
| 112 | OP_SXTB16, | ||
| 113 | OP_SXTH, | ||
| 62 | OP_TEQ, | 114 | OP_TEQ, |
| 63 | OP_TST, | 115 | OP_TST, |
| 116 | OP_UADD16, | ||
| 117 | OP_UADD8, | ||
| 118 | OP_UASX, | ||
| 119 | OP_UHADD16, | ||
| 120 | OP_UHADD8, | ||
| 121 | OP_UHASX, | ||
| 122 | OP_UHSAX, | ||
| 123 | OP_UHSUB16, | ||
| 124 | OP_UHSUB8, | ||
| 64 | OP_UMLAL, | 125 | OP_UMLAL, |
| 65 | OP_UMULL, | 126 | OP_UMULL, |
| 127 | OP_UQADD16, | ||
| 128 | OP_UQADD8, | ||
| 129 | OP_UQASX, | ||
| 130 | OP_UQSAX, | ||
| 131 | OP_UQSUB16, | ||
| 132 | OP_UQSUB8, | ||
| 133 | OP_USAD8, | ||
| 134 | OP_USADA8, | ||
| 135 | OP_USAT, | ||
| 136 | OP_USAT16, | ||
| 137 | OP_USAX, | ||
| 138 | OP_USUB16, | ||
| 139 | OP_USUB8, | ||
| 140 | OP_UXTAB, | ||
| 141 | OP_UXTAB16, | ||
| 142 | OP_UXTAH, | ||
| 143 | OP_UXTB, | ||
| 144 | OP_UXTB16, | ||
| 145 | OP_UXTH, | ||
| 146 | OP_WFE, | ||
| 147 | OP_WFI, | ||
| 148 | OP_YIELD, | ||
| 66 | 149 | ||
| 67 | // Define thumb opcodes | 150 | // Define thumb opcodes |
| 68 | OP_THUMB_UNDEFINED, | 151 | OP_THUMB_UNDEFINED, |
| @@ -109,33 +192,48 @@ enum Opcode { | |||
| 109 | 192 | ||
| 110 | class ARM_Disasm { | 193 | class ARM_Disasm { |
| 111 | public: | 194 | public: |
| 112 | static std::string Disassemble(uint32_t addr, uint32_t insn); | 195 | static std::string Disassemble(u32 addr, u32 insn); |
| 113 | static Opcode Decode(uint32_t insn); | 196 | static Opcode Decode(u32 insn); |
| 114 | 197 | ||
| 115 | private: | 198 | private: |
| 116 | static Opcode Decode00(uint32_t insn); | 199 | static Opcode Decode00(u32 insn); |
| 117 | static Opcode Decode01(uint32_t insn); | 200 | static Opcode Decode01(u32 insn); |
| 118 | static Opcode Decode10(uint32_t insn); | 201 | static Opcode Decode10(u32 insn); |
| 119 | static Opcode Decode11(uint32_t insn); | 202 | static Opcode Decode11(u32 insn); |
| 120 | static Opcode DecodeMUL(uint32_t insn); | 203 | static Opcode DecodeSyncPrimitive(u32 insn); |
| 121 | static Opcode DecodeLDRH(uint32_t insn); | 204 | static Opcode DecodeParallelAddSub(u32 insn); |
| 122 | static Opcode DecodeALU(uint32_t insn); | 205 | static Opcode DecodePackingSaturationReversal(u32 insn); |
| 206 | static Opcode DecodeMUL(u32 insn); | ||
| 207 | static Opcode DecodeMSRImmAndHints(u32 insn); | ||
| 208 | static Opcode DecodeMediaMulDiv(u32 insn); | ||
| 209 | static Opcode DecodeMedia(u32 insn); | ||
| 210 | static Opcode DecodeLDRH(u32 insn); | ||
| 211 | static Opcode DecodeALU(u32 insn); | ||
| 123 | 212 | ||
| 124 | static std::string DisassembleALU(Opcode opcode, uint32_t insn); | 213 | static std::string DisassembleALU(Opcode opcode, u32 insn); |
| 125 | static std::string DisassembleBranch(uint32_t addr, Opcode opcode, uint32_t insn); | 214 | static std::string DisassembleBranch(u32 addr, Opcode opcode, u32 insn); |
| 126 | static std::string DisassembleBX(uint32_t insn); | 215 | static std::string DisassembleBX(u32 insn); |
| 127 | static std::string DisassembleBKPT(uint32_t insn); | 216 | static std::string DisassembleBKPT(u32 insn); |
| 128 | static std::string DisassembleCLZ(uint32_t insn); | 217 | static std::string DisassembleCLZ(u32 insn); |
| 129 | static std::string DisassembleMemblock(Opcode opcode, uint32_t insn); | 218 | static std::string DisassembleMediaMulDiv(Opcode opcode, u32 insn); |
| 130 | static std::string DisassembleMem(uint32_t insn); | 219 | static std::string DisassembleMemblock(Opcode opcode, u32 insn); |
| 131 | static std::string DisassembleMemHalf(uint32_t insn); | 220 | static std::string DisassembleMem(u32 insn); |
| 132 | static std::string DisassembleMCR(Opcode opcode, uint32_t insn); | 221 | static std::string DisassembleMemHalf(u32 insn); |
| 133 | static std::string DisassembleMLA(Opcode opcode, uint32_t insn); | 222 | static std::string DisassembleMCR(Opcode opcode, u32 insn); |
| 134 | static std::string DisassembleUMLAL(Opcode opcode, uint32_t insn); | 223 | static std::string DisassembleMLA(Opcode opcode, u32 insn); |
| 135 | static std::string DisassembleMUL(Opcode opcode, uint32_t insn); | 224 | static std::string DisassembleUMLAL(Opcode opcode, u32 insn); |
| 136 | static std::string DisassembleMRS(uint32_t insn); | 225 | static std::string DisassembleMUL(Opcode opcode, u32 insn); |
| 137 | static std::string DisassembleMSR(uint32_t insn); | 226 | static std::string DisassembleMRS(u32 insn); |
| 138 | static std::string DisassemblePLD(uint32_t insn); | 227 | static std::string DisassembleMSR(u32 insn); |
| 139 | static std::string DisassembleSWI(uint32_t insn); | 228 | static std::string DisassembleNoOperands(Opcode opcode, u32 insn); |
| 140 | static std::string DisassembleSWP(Opcode opcode, uint32_t insn); | 229 | static std::string DisassembleParallelAddSub(Opcode opcode, u32 insn); |
| 230 | static std::string DisassemblePKH(u32 insn); | ||
| 231 | static std::string DisassemblePLD(u32 insn); | ||
| 232 | static std::string DisassembleREV(Opcode opcode, u32 insn); | ||
| 233 | static std::string DisassembleREX(Opcode opcode, u32 insn); | ||
| 234 | static std::string DisassembleSAT(Opcode opcode, u32 insn); | ||
| 235 | static std::string DisassembleSEL(u32 insn); | ||
| 236 | static std::string DisassembleSWI(u32 insn); | ||
| 237 | static std::string DisassembleSWP(Opcode opcode, u32 insn); | ||
| 238 | static std::string DisassembleXT(Opcode opcode, u32 insn); | ||
| 141 | }; | 239 | }; |
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp index c665f706f..f3be2c857 100644 --- a/src/core/arm/dyncom/arm_dyncom.cpp +++ b/src/core/arm/dyncom/arm_dyncom.cpp | |||
| @@ -40,6 +40,22 @@ void ARM_DynCom::SetReg(int index, u32 value) { | |||
| 40 | state->Reg[index] = value; | 40 | state->Reg[index] = value; |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | u32 ARM_DynCom::GetVFPReg(int index) const { | ||
| 44 | return state->ExtReg[index]; | ||
| 45 | } | ||
| 46 | |||
| 47 | void ARM_DynCom::SetVFPReg(int index, u32 value) { | ||
| 48 | state->ExtReg[index] = value; | ||
| 49 | } | ||
| 50 | |||
| 51 | u32 ARM_DynCom::GetVFPSystemReg(VFPSystemRegister reg) const { | ||
| 52 | return state->VFP[reg]; | ||
| 53 | } | ||
| 54 | |||
| 55 | void ARM_DynCom::SetVFPSystemReg(VFPSystemRegister reg, u32 value) { | ||
| 56 | state->VFP[reg] = value; | ||
| 57 | } | ||
| 58 | |||
| 43 | u32 ARM_DynCom::GetCPSR() const { | 59 | u32 ARM_DynCom::GetCPSR() const { |
| 44 | return state->Cpsr; | 60 | return state->Cpsr; |
| 45 | } | 61 | } |
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h index 87ab6908a..3664fd728 100644 --- a/src/core/arm/dyncom/arm_dyncom.h +++ b/src/core/arm/dyncom/arm_dyncom.h | |||
| @@ -25,6 +25,10 @@ public: | |||
| 25 | u32 GetPC() const override; | 25 | u32 GetPC() const override; |
| 26 | u32 GetReg(int index) const override; | 26 | u32 GetReg(int index) const override; |
| 27 | void SetReg(int index, u32 value) override; | 27 | void SetReg(int index, u32 value) override; |
| 28 | u32 GetVFPReg(int index) const override; | ||
| 29 | void SetVFPReg(int index, u32 value) override; | ||
| 30 | u32 GetVFPSystemReg(VFPSystemRegister reg) const override; | ||
| 31 | void SetVFPSystemReg(VFPSystemRegister reg, u32 value) override; | ||
| 28 | u32 GetCPSR() const override; | 32 | u32 GetCPSR() const override; |
| 29 | void SetCPSR(u32 cpsr) override; | 33 | void SetCPSR(u32 cpsr) override; |
| 30 | u32 GetCP15Register(CP15Register reg) override; | 34 | u32 GetCP15Register(CP15Register reg) override; |
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index b88b74752..422e80b50 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <algorithm> | 7 | #include <algorithm> |
| 8 | #include <cstdio> | 8 | #include <cstdio> |
| 9 | 9 | ||
| 10 | #include "common/common_types.h" | ||
| 10 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 11 | #include "common/profiler.h" | 12 | #include "common/profiler.h" |
| 12 | 13 | ||
| @@ -759,8 +760,8 @@ struct bx_inst { | |||
| 759 | 760 | ||
| 760 | struct blx_inst { | 761 | struct blx_inst { |
| 761 | union { | 762 | union { |
| 762 | int32_t signed_immed_24; | 763 | s32 signed_immed_24; |
| 763 | uint32_t Rm; | 764 | u32 Rm; |
| 764 | } val; | 765 | } val; |
| 765 | unsigned int inst; | 766 | unsigned int inst; |
| 766 | }; | 767 | }; |
| @@ -3544,7 +3545,7 @@ static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { | |||
| 3544 | size++; | 3545 | size++; |
| 3545 | // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction | 3546 | // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction |
| 3546 | if (cpu->TFlag) { | 3547 | if (cpu->TFlag) { |
| 3547 | uint32_t arm_inst; | 3548 | u32 arm_inst; |
| 3548 | ThumbDecodeStatus state = DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base); | 3549 | ThumbDecodeStatus state = DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base); |
| 3549 | 3550 | ||
| 3550 | // We have translated the Thumb branch instruction in the Thumb decoder | 3551 | // We have translated the Thumb branch instruction in the Thumb decoder |
| @@ -4215,8 +4216,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4215 | CPS_INST: | 4216 | CPS_INST: |
| 4216 | { | 4217 | { |
| 4217 | cps_inst *inst_cream = (cps_inst *)inst_base->component; | 4218 | cps_inst *inst_cream = (cps_inst *)inst_base->component; |
| 4218 | uint32_t aif_val = 0; | 4219 | u32 aif_val = 0; |
| 4219 | uint32_t aif_mask = 0; | 4220 | u32 aif_mask = 0; |
| 4220 | if (cpu->InAPrivilegedMode()) { | 4221 | if (cpu->InAPrivilegedMode()) { |
| 4221 | if (inst_cream->imod1) { | 4222 | if (inst_cream->imod1) { |
| 4222 | if (inst_cream->A) { | 4223 | if (inst_cream->A) { |
| @@ -4710,11 +4711,11 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4710 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { | 4711 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 4711 | mla_inst* inst_cream = (mla_inst*)inst_base->component; | 4712 | mla_inst* inst_cream = (mla_inst*)inst_base->component; |
| 4712 | 4713 | ||
| 4713 | uint64_t rm = RM; | 4714 | u64 rm = RM; |
| 4714 | uint64_t rs = RS; | 4715 | u64 rs = RS; |
| 4715 | uint64_t rn = RN; | 4716 | u64 rn = RN; |
| 4716 | 4717 | ||
| 4717 | RD = static_cast<uint32_t>((rm * rs + rn) & 0xffffffff); | 4718 | RD = static_cast<u32>((rm * rs + rn) & 0xffffffff); |
| 4718 | if (inst_cream->S) { | 4719 | if (inst_cream->S) { |
| 4719 | UPDATE_NFLAG(RD); | 4720 | UPDATE_NFLAG(RD); |
| 4720 | UPDATE_ZFLAG(RD); | 4721 | UPDATE_ZFLAG(RD); |
| @@ -4819,7 +4820,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4819 | { | 4820 | { |
| 4820 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { | 4821 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 4821 | msr_inst* inst_cream = (msr_inst*)inst_base->component; | 4822 | msr_inst* inst_cream = (msr_inst*)inst_base->component; |
| 4822 | const uint32_t UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020; | 4823 | const u32 UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020; |
| 4823 | unsigned int inst = inst_cream->inst; | 4824 | unsigned int inst = inst_cream->inst; |
| 4824 | unsigned int operand; | 4825 | unsigned int operand; |
| 4825 | 4826 | ||
| @@ -4829,9 +4830,9 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4829 | } else { | 4830 | } else { |
| 4830 | operand = cpu->Reg[BITS(inst, 0, 3)]; | 4831 | operand = cpu->Reg[BITS(inst, 0, 3)]; |
| 4831 | } | 4832 | } |
| 4832 | uint32_t byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0) | 4833 | u32 byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0) |
| 4833 | | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0); | 4834 | | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0); |
| 4834 | uint32_t mask = 0; | 4835 | u32 mask = 0; |
| 4835 | if (!inst_cream->R) { | 4836 | if (!inst_cream->R) { |
| 4836 | if (cpu->InAPrivilegedMode()) { | 4837 | if (cpu->InAPrivilegedMode()) { |
| 4837 | if ((operand & StateMask) != 0) { | 4838 | if ((operand & StateMask) != 0) { |
| @@ -4864,9 +4865,9 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 4864 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { | 4865 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 4865 | mul_inst* inst_cream = (mul_inst*)inst_base->component; | 4866 | mul_inst* inst_cream = (mul_inst*)inst_base->component; |
| 4866 | 4867 | ||
| 4867 | uint64_t rm = RM; | 4868 | u64 rm = RM; |
| 4868 | uint64_t rs = RS; | 4869 | u64 rs = RS; |
| 4869 | RD = static_cast<uint32_t>((rm * rs) & 0xffffffff); | 4870 | RD = static_cast<u32>((rm * rs) & 0xffffffff); |
| 4870 | if (inst_cream->S) { | 4871 | if (inst_cream->S) { |
| 4871 | UPDATE_NFLAG(RD); | 4872 | UPDATE_NFLAG(RD); |
| 4872 | UPDATE_ZFLAG(RD); | 4873 | UPDATE_ZFLAG(RD); |
| @@ -5532,7 +5533,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5532 | { | 5533 | { |
| 5533 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { | 5534 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 5534 | smla_inst* inst_cream = (smla_inst*)inst_base->component; | 5535 | smla_inst* inst_cream = (smla_inst*)inst_base->component; |
| 5535 | int32_t operand1, operand2; | 5536 | s32 operand1, operand2; |
| 5536 | if (inst_cream->x == 0) | 5537 | if (inst_cream->x == 0) |
| 5537 | operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15); | 5538 | operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15); |
| 5538 | else | 5539 | else |
| @@ -5771,7 +5772,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5771 | { | 5772 | { |
| 5772 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { | 5773 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 5773 | smul_inst* inst_cream = (smul_inst*)inst_base->component; | 5774 | smul_inst* inst_cream = (smul_inst*)inst_base->component; |
| 5774 | uint32_t operand1, operand2; | 5775 | u32 operand1, operand2; |
| 5775 | if (inst_cream->x == 0) | 5776 | if (inst_cream->x == 0) |
| 5776 | operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15); | 5777 | operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15); |
| 5777 | else | 5778 | else |
| @@ -5792,15 +5793,15 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | |||
| 5792 | { | 5793 | { |
| 5793 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { | 5794 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 5794 | umull_inst* inst_cream = (umull_inst*)inst_base->component; | 5795 | umull_inst* inst_cream = (umull_inst*)inst_base->component; |
| 5795 | int64_t rm = RM; | 5796 | s64 rm = RM; |
| 5796 | int64_t rs = RS; | 5797 | s64 rs = RS; |
| 5797 | if (BIT(rm, 31)) { | 5798 | if (BIT(rm, 31)) { |
| 5798 | rm |= 0xffffffff00000000LL; | 5799 | rm |= 0xffffffff00000000LL; |
| 5799 | } | 5800 | } |
| 5800 | if (BIT(rs, 31)) { | 5801 | if (BIT(rs, 31)) { |
| 5801 | rs |= 0xffffffff00000000LL; | 5802 | rs |= 0xffffffff00000000LL; |
| 5802 | } | 5803 | } |
| 5803 | int64_t rst = rm * rs; | 5804 | s64 rst = rm * rs; |
| 5804 | RDHI = BITS(rst, 32, 63); | 5805 | RDHI = BITS(rst, 32, 63); |
| 5805 | RDLO = BITS(rst, 0, 31); | 5806 | RDLO = BITS(rst, 0, 31); |
| 5806 | 5807 | ||
diff --git a/src/core/arm/skyeye_common/arm_regformat.h b/src/core/arm/skyeye_common/arm_regformat.h index d1c721809..38fa97ab9 100644 --- a/src/core/arm/skyeye_common/arm_regformat.h +++ b/src/core/arm/skyeye_common/arm_regformat.h | |||
| @@ -55,7 +55,7 @@ enum { | |||
| 55 | }; | 55 | }; |
| 56 | 56 | ||
| 57 | // VFP system registers | 57 | // VFP system registers |
| 58 | enum { | 58 | enum VFPSystemRegister { |
| 59 | VFP_FPSID, | 59 | VFP_FPSID, |
| 60 | VFP_FPSCR, | 60 | VFP_FPSCR, |
| 61 | VFP_FPEXC, | 61 | VFP_FPEXC, |
diff --git a/src/core/arm/skyeye_common/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp index 26f303de4..0537135e2 100644 --- a/src/core/arm/skyeye_common/vfp/vfp.cpp +++ b/src/core/arm/skyeye_common/vfp/vfp.cpp | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | /* Note: this file handles interface with arm core and vfp registers */ | 21 | /* Note: this file handles interface with arm core and vfp registers */ |
| 22 | 22 | ||
| 23 | #include "common/common_funcs.h" | 23 | #include "common/common_funcs.h" |
| 24 | #include "common/common_types.h" | ||
| 24 | #include "common/logging/log.h" | 25 | #include "common/logging/log.h" |
| 25 | 26 | ||
| 26 | #include "core/arm/skyeye_common/armstate.h" | 27 | #include "core/arm/skyeye_common/armstate.h" |
| @@ -110,30 +111,30 @@ void VMOVR(ARMul_State* state, u32 single, u32 d, u32 m) | |||
| 110 | } | 111 | } |
| 111 | 112 | ||
| 112 | /* Miscellaneous functions */ | 113 | /* Miscellaneous functions */ |
| 113 | int32_t vfp_get_float(ARMul_State* state, unsigned int reg) | 114 | s32 vfp_get_float(ARMul_State* state, unsigned int reg) |
| 114 | { | 115 | { |
| 115 | LOG_TRACE(Core_ARM11, "VFP get float: s%d=[%08x]\n", reg, state->ExtReg[reg]); | 116 | LOG_TRACE(Core_ARM11, "VFP get float: s%d=[%08x]\n", reg, state->ExtReg[reg]); |
| 116 | return state->ExtReg[reg]; | 117 | return state->ExtReg[reg]; |
| 117 | } | 118 | } |
| 118 | 119 | ||
| 119 | void vfp_put_float(ARMul_State* state, int32_t val, unsigned int reg) | 120 | void vfp_put_float(ARMul_State* state, s32 val, unsigned int reg) |
| 120 | { | 121 | { |
| 121 | LOG_TRACE(Core_ARM11, "VFP put float: s%d <= [%08x]\n", reg, val); | 122 | LOG_TRACE(Core_ARM11, "VFP put float: s%d <= [%08x]\n", reg, val); |
| 122 | state->ExtReg[reg] = val; | 123 | state->ExtReg[reg] = val; |
| 123 | } | 124 | } |
| 124 | 125 | ||
| 125 | uint64_t vfp_get_double(ARMul_State* state, unsigned int reg) | 126 | u64 vfp_get_double(ARMul_State* state, unsigned int reg) |
| 126 | { | 127 | { |
| 127 | uint64_t result = ((uint64_t) state->ExtReg[reg*2+1])<<32 | state->ExtReg[reg*2]; | 128 | u64 result = ((u64) state->ExtReg[reg*2+1])<<32 | state->ExtReg[reg*2]; |
| 128 | LOG_TRACE(Core_ARM11, "VFP get double: s[%d-%d]=[%016llx]\n", reg * 2 + 1, reg * 2, result); | 129 | LOG_TRACE(Core_ARM11, "VFP get double: s[%d-%d]=[%016llx]\n", reg * 2 + 1, reg * 2, result); |
| 129 | return result; | 130 | return result; |
| 130 | } | 131 | } |
| 131 | 132 | ||
| 132 | void vfp_put_double(ARMul_State* state, uint64_t val, unsigned int reg) | 133 | void vfp_put_double(ARMul_State* state, u64 val, unsigned int reg) |
| 133 | { | 134 | { |
| 134 | LOG_TRACE(Core_ARM11, "VFP put double: s[%d-%d] <= [%08x-%08x]\n", reg * 2 + 1, reg * 2, (uint32_t)(val >> 32), (uint32_t)(val & 0xffffffff)); | 135 | LOG_TRACE(Core_ARM11, "VFP put double: s[%d-%d] <= [%08x-%08x]\n", reg * 2 + 1, reg * 2, (u32)(val >> 32), (u32)(val & 0xffffffff)); |
| 135 | state->ExtReg[reg*2] = (uint32_t) (val & 0xffffffff); | 136 | state->ExtReg[reg*2] = (u32) (val & 0xffffffff); |
| 136 | state->ExtReg[reg*2+1] = (uint32_t) (val>>32); | 137 | state->ExtReg[reg*2+1] = (u32) (val>>32); |
| 137 | } | 138 | } |
| 138 | 139 | ||
| 139 | /* | 140 | /* |
diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp index 1d844a66e..47a9fe804 100644 --- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp | |||
| @@ -51,6 +51,7 @@ | |||
| 51 | * =========================================================================== | 51 | * =========================================================================== |
| 52 | */ | 52 | */ |
| 53 | 53 | ||
| 54 | #include <algorithm> | ||
| 54 | #include "common/logging/log.h" | 55 | #include "common/logging/log.h" |
| 55 | #include "core/arm/skyeye_common/vfp/vfp.h" | 56 | #include "core/arm/skyeye_common/vfp/vfp.h" |
| 56 | #include "core/arm/skyeye_common/vfp/vfp_helper.h" | 57 | #include "core/arm/skyeye_common/vfp/vfp_helper.h" |
| @@ -785,9 +786,7 @@ u32 vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,struct vfp_dou | |||
| 785 | * This ensures that NaN propagation works correctly. | 786 | * This ensures that NaN propagation works correctly. |
| 786 | */ | 787 | */ |
| 787 | if (vdn->exponent < vdm->exponent) { | 788 | if (vdn->exponent < vdm->exponent) { |
| 788 | struct vfp_double *t = vdn; | 789 | std::swap(vdm, vdn); |
| 789 | vdn = vdm; | ||
| 790 | vdm = t; | ||
| 791 | } | 790 | } |
| 792 | 791 | ||
| 793 | /* | 792 | /* |
| @@ -843,9 +842,7 @@ vfp_double_multiply(struct vfp_double *vdd, struct vfp_double *vdn, | |||
| 843 | * This ensures that NaN propagation works correctly. | 842 | * This ensures that NaN propagation works correctly. |
| 844 | */ | 843 | */ |
| 845 | if (vdn->exponent < vdm->exponent) { | 844 | if (vdn->exponent < vdm->exponent) { |
| 846 | struct vfp_double *t = vdn; | 845 | std::swap(vdm, vdn); |
| 847 | vdn = vdm; | ||
| 848 | vdm = t; | ||
| 849 | LOG_TRACE(Core_ARM11, "VFP: swapping M <-> N\n"); | 846 | LOG_TRACE(Core_ARM11, "VFP: swapping M <-> N\n"); |
| 850 | } | 847 | } |
| 851 | 848 | ||
diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp index e5d339252..0fb3c3bf1 100644 --- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp | |||
| @@ -51,6 +51,7 @@ | |||
| 51 | * =========================================================================== | 51 | * =========================================================================== |
| 52 | */ | 52 | */ |
| 53 | 53 | ||
| 54 | #include <algorithm> | ||
| 54 | #include <cinttypes> | 55 | #include <cinttypes> |
| 55 | 56 | ||
| 56 | #include "common/common_funcs.h" | 57 | #include "common/common_funcs.h" |
| @@ -815,9 +816,7 @@ vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn, | |||
| 815 | * This ensures that NaN propagation works correctly. | 816 | * This ensures that NaN propagation works correctly. |
| 816 | */ | 817 | */ |
| 817 | if (vsn->exponent < vsm->exponent) { | 818 | if (vsn->exponent < vsm->exponent) { |
| 818 | struct vfp_single *t = vsn; | 819 | std::swap(vsm, vsn); |
| 819 | vsn = vsm; | ||
| 820 | vsm = t; | ||
| 821 | } | 820 | } |
| 822 | 821 | ||
| 823 | /* | 822 | /* |
| @@ -872,9 +871,7 @@ vfp_single_multiply(struct vfp_single *vsd, struct vfp_single *vsn, struct vfp_s | |||
| 872 | * This ensures that NaN propagation works correctly. | 871 | * This ensures that NaN propagation works correctly. |
| 873 | */ | 872 | */ |
| 874 | if (vsn->exponent < vsm->exponent) { | 873 | if (vsn->exponent < vsm->exponent) { |
| 875 | struct vfp_single *t = vsn; | 874 | std::swap(vsm, vsn); |
| 876 | vsn = vsm; | ||
| 877 | vsm = t; | ||
| 878 | LOG_TRACE(Core_ARM11, "swapping M <-> N"); | 875 | LOG_TRACE(Core_ARM11, "swapping M <-> N"); |
| 879 | } | 876 | } |
| 880 | 877 | ||
diff --git a/src/core/settings.h b/src/core/settings.h index 2775ee257..6ca0e1afc 100644 --- a/src/core/settings.h +++ b/src/core/settings.h | |||
| @@ -53,6 +53,7 @@ struct Values { | |||
| 53 | 53 | ||
| 54 | // Renderer | 54 | // Renderer |
| 55 | bool use_hw_renderer; | 55 | bool use_hw_renderer; |
| 56 | bool use_shader_jit; | ||
| 56 | 57 | ||
| 57 | float bg_red; | 58 | float bg_red; |
| 58 | float bg_green; | 59 | float bg_green; |
diff --git a/src/core/tracer/citrace.h b/src/core/tracer/citrace.h index 5deb6ce9e..709abdfb3 100644 --- a/src/core/tracer/citrace.h +++ b/src/core/tracer/citrace.h | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <cstdint> | 7 | #include "common/common_types.h" |
| 8 | 8 | ||
| 9 | namespace CiTrace { | 9 | namespace CiTrace { |
| 10 | 10 | ||
| @@ -17,38 +17,38 @@ struct CTHeader { | |||
| 17 | return "CiTr"; | 17 | return "CiTr"; |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | static uint32_t ExpectedVersion() { | 20 | static u32 ExpectedVersion() { |
| 21 | return 1; | 21 | return 1; |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | char magic[4]; | 24 | char magic[4]; |
| 25 | uint32_t version; | 25 | u32 version; |
| 26 | uint32_t header_size; | 26 | u32 header_size; |
| 27 | 27 | ||
| 28 | struct { | 28 | struct { |
| 29 | // NOTE: Register range sizes are technically hardware-constants, but the actual limits | 29 | // NOTE: Register range sizes are technically hardware-constants, but the actual limits |
| 30 | // aren't known. Hence we store the presumed limits along the offsets. | 30 | // aren't known. Hence we store the presumed limits along the offsets. |
| 31 | // Sizes are given in uint32_t units. | 31 | // Sizes are given in u32 units. |
| 32 | uint32_t gpu_registers; | 32 | u32 gpu_registers; |
| 33 | uint32_t gpu_registers_size; | 33 | u32 gpu_registers_size; |
| 34 | uint32_t lcd_registers; | 34 | u32 lcd_registers; |
| 35 | uint32_t lcd_registers_size; | 35 | u32 lcd_registers_size; |
| 36 | uint32_t pica_registers; | 36 | u32 pica_registers; |
| 37 | uint32_t pica_registers_size; | 37 | u32 pica_registers_size; |
| 38 | uint32_t default_attributes; | 38 | u32 default_attributes; |
| 39 | uint32_t default_attributes_size; | 39 | u32 default_attributes_size; |
| 40 | uint32_t vs_program_binary; | 40 | u32 vs_program_binary; |
| 41 | uint32_t vs_program_binary_size; | 41 | u32 vs_program_binary_size; |
| 42 | uint32_t vs_swizzle_data; | 42 | u32 vs_swizzle_data; |
| 43 | uint32_t vs_swizzle_data_size; | 43 | u32 vs_swizzle_data_size; |
| 44 | uint32_t vs_float_uniforms; | 44 | u32 vs_float_uniforms; |
| 45 | uint32_t vs_float_uniforms_size; | 45 | u32 vs_float_uniforms_size; |
| 46 | uint32_t gs_program_binary; | 46 | u32 gs_program_binary; |
| 47 | uint32_t gs_program_binary_size; | 47 | u32 gs_program_binary_size; |
| 48 | uint32_t gs_swizzle_data; | 48 | u32 gs_swizzle_data; |
| 49 | uint32_t gs_swizzle_data_size; | 49 | u32 gs_swizzle_data_size; |
| 50 | uint32_t gs_float_uniforms; | 50 | u32 gs_float_uniforms; |
| 51 | uint32_t gs_float_uniforms_size; | 51 | u32 gs_float_uniforms_size; |
| 52 | 52 | ||
| 53 | // Other things we might want to store here: | 53 | // Other things we might want to store here: |
| 54 | // - Initial framebuffer data, maybe even a full copy of FCRAM/VRAM | 54 | // - Initial framebuffer data, maybe even a full copy of FCRAM/VRAM |
| @@ -56,27 +56,27 @@ struct CTHeader { | |||
| 56 | // - Lookup tables for procedural textures | 56 | // - Lookup tables for procedural textures |
| 57 | } initial_state_offsets; | 57 | } initial_state_offsets; |
| 58 | 58 | ||
| 59 | uint32_t stream_offset; | 59 | u32 stream_offset; |
| 60 | uint32_t stream_size; | 60 | u32 stream_size; |
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | enum CTStreamElementType : uint32_t { | 63 | enum CTStreamElementType : u32 { |
| 64 | FrameMarker = 0xE1, | 64 | FrameMarker = 0xE1, |
| 65 | MemoryLoad = 0xE2, | 65 | MemoryLoad = 0xE2, |
| 66 | RegisterWrite = 0xE3, | 66 | RegisterWrite = 0xE3, |
| 67 | }; | 67 | }; |
| 68 | 68 | ||
| 69 | struct CTMemoryLoad { | 69 | struct CTMemoryLoad { |
| 70 | uint32_t file_offset; | 70 | u32 file_offset; |
| 71 | uint32_t size; | 71 | u32 size; |
| 72 | uint32_t physical_address; | 72 | u32 physical_address; |
| 73 | uint32_t pad; | 73 | u32 pad; |
| 74 | }; | 74 | }; |
| 75 | 75 | ||
| 76 | struct CTRegisterWrite { | 76 | struct CTRegisterWrite { |
| 77 | uint32_t physical_address; | 77 | u32 physical_address; |
| 78 | 78 | ||
| 79 | enum : uint32_t { | 79 | enum : u32 { |
| 80 | SIZE_8 = 0xD1, | 80 | SIZE_8 = 0xD1, |
| 81 | SIZE_16 = 0xD2, | 81 | SIZE_16 = 0xD2, |
| 82 | SIZE_32 = 0xD3, | 82 | SIZE_32 = 0xD3, |
| @@ -84,7 +84,7 @@ struct CTRegisterWrite { | |||
| 84 | } size; | 84 | } size; |
| 85 | 85 | ||
| 86 | // TODO: Make it clearer which bits of this member are used for sizes other than 32 bits | 86 | // TODO: Make it clearer which bits of this member are used for sizes other than 32 bits |
| 87 | uint64_t value; | 87 | u64 value; |
| 88 | }; | 88 | }; |
| 89 | 89 | ||
| 90 | struct CTStreamElement { | 90 | struct CTStreamElement { |