diff options
Diffstat (limited to 'src/core')
208 files changed, 10705 insertions, 10514 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 | ||
diff --git a/src/core/core.cpp b/src/core/core.cpp index a3834adae..4f9eca416 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -27,7 +27,8 @@ void RunLoop(int tight_loop) { | |||
| 27 | if (GDBStub::g_server_enabled) { | 27 | if (GDBStub::g_server_enabled) { |
| 28 | GDBStub::HandlePacket(); | 28 | GDBStub::HandlePacket(); |
| 29 | 29 | ||
| 30 | // If the loop is halted and we want to step, use a tiny (1) number of instructions to execute. | 30 | // If the loop is halted and we want to step, use a tiny (1) number of instructions to |
| 31 | // execute. | ||
| 31 | // Otherwise get out of the loop function. | 32 | // Otherwise get out of the loop function. |
| 32 | if (GDBStub::GetCpuHaltFlag()) { | 33 | if (GDBStub::GetCpuHaltFlag()) { |
| 33 | if (GDBStub::GetCpuStepFlag()) { | 34 | if (GDBStub::GetCpuStepFlag()) { |
| @@ -62,7 +63,7 @@ void SingleStep() { | |||
| 62 | } | 63 | } |
| 63 | 64 | ||
| 64 | /// Halt the core | 65 | /// Halt the core |
| 65 | void Halt(const char *msg) { | 66 | void Halt(const char* msg) { |
| 66 | // TODO(ShizZy): ImplementMe | 67 | // TODO(ShizZy): ImplementMe |
| 67 | } | 68 | } |
| 68 | 69 | ||
diff --git a/src/core/core.h b/src/core/core.h index ad26dca3f..ffbfa91c3 100644 --- a/src/core/core.h +++ b/src/core/core.h | |||
| @@ -40,13 +40,13 @@ void Start(); | |||
| 40 | * is not guaranteed to run, as this will be interrupted preemptively if a hardware update is | 40 | * is not guaranteed to run, as this will be interrupted preemptively if a hardware update is |
| 41 | * requested (e.g. on a thread switch). | 41 | * requested (e.g. on a thread switch). |
| 42 | */ | 42 | */ |
| 43 | void RunLoop(int tight_loop=1000); | 43 | void RunLoop(int tight_loop = 1000); |
| 44 | 44 | ||
| 45 | /// Step the CPU one instruction | 45 | /// Step the CPU one instruction |
| 46 | void SingleStep(); | 46 | void SingleStep(); |
| 47 | 47 | ||
| 48 | /// Halt the core | 48 | /// Halt the core |
| 49 | void Halt(const char *msg); | 49 | void Halt(const char* msg); |
| 50 | 50 | ||
| 51 | /// Kill the core | 51 | /// Kill the core |
| 52 | void Stop(); | 52 | void Stop(); |
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index aba22cdd1..b7b988cf1 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp | |||
| @@ -21,14 +21,13 @@ int g_clock_rate_arm11 = 268123480; | |||
| 21 | #define INITIAL_SLICE_LENGTH 20000 | 21 | #define INITIAL_SLICE_LENGTH 20000 |
| 22 | #define MAX_SLICE_LENGTH 100000000 | 22 | #define MAX_SLICE_LENGTH 100000000 |
| 23 | 23 | ||
| 24 | namespace CoreTiming | 24 | namespace CoreTiming { |
| 25 | { | 25 | struct EventType { |
| 26 | struct EventType | 26 | EventType() { |
| 27 | { | 27 | } |
| 28 | EventType() {} | ||
| 29 | 28 | ||
| 30 | EventType(TimedCallback cb, const char* n) | 29 | EventType(TimedCallback cb, const char* n) : callback(cb), name(n) { |
| 31 | : callback(cb), name(n) {} | 30 | } |
| 32 | 31 | ||
| 33 | TimedCallback callback; | 32 | TimedCallback callback; |
| 34 | const char* name; | 33 | const char* name; |
| @@ -36,8 +35,7 @@ struct EventType | |||
| 36 | 35 | ||
| 37 | static std::vector<EventType> event_types; | 36 | static std::vector<EventType> event_types; |
| 38 | 37 | ||
| 39 | struct BaseEvent | 38 | struct BaseEvent { |
| 40 | { | ||
| 41 | s64 time; | 39 | s64 time; |
| 42 | u64 userdata; | 40 | u64 userdata; |
| 43 | int type; | 41 | int type; |
| @@ -200,7 +198,6 @@ u64 GetIdleTicks() { | |||
| 200 | return (u64)idled_cycles; | 198 | return (u64)idled_cycles; |
| 201 | } | 199 | } |
| 202 | 200 | ||
| 203 | |||
| 204 | // This is to be called when outside threads, such as the graphics thread, wants to | 201 | // This is to be called when outside threads, such as the graphics thread, wants to |
| 205 | // schedule things to be executed on the main thread. | 202 | // schedule things to be executed on the main thread. |
| 206 | void ScheduleEvent_Threadsafe(s64 cycles_into_future, int event_type, u64 userdata) { | 203 | void ScheduleEvent_Threadsafe(s64 cycles_into_future, int event_type, u64 userdata) { |
| @@ -222,12 +219,11 @@ void ScheduleEvent_Threadsafe(s64 cycles_into_future, int event_type, u64 userda | |||
| 222 | // Same as ScheduleEvent_Threadsafe(0, ...) EXCEPT if we are already on the CPU thread | 219 | // Same as ScheduleEvent_Threadsafe(0, ...) EXCEPT if we are already on the CPU thread |
| 223 | // in which case the event will get handled immediately, before returning. | 220 | // in which case the event will get handled immediately, before returning. |
| 224 | void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata) { | 221 | void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata) { |
| 225 | if (false) //Core::IsCPUThread()) | 222 | if (false) // Core::IsCPUThread()) |
| 226 | { | 223 | { |
| 227 | std::lock_guard<std::recursive_mutex> lock(external_event_section); | 224 | std::lock_guard<std::recursive_mutex> lock(external_event_section); |
| 228 | event_types[event_type].callback(userdata, 0); | 225 | event_types[event_type].callback(userdata, 0); |
| 229 | } | 226 | } else |
| 230 | else | ||
| 231 | ScheduleEvent_Threadsafe(0, event_type, userdata); | 227 | ScheduleEvent_Threadsafe(0, event_type, userdata); |
| 232 | } | 228 | } |
| 233 | 229 | ||
| @@ -317,8 +313,7 @@ s64 UnscheduleThreadsafeEvent(int event_type, u64 userdata) { | |||
| 317 | } | 313 | } |
| 318 | } | 314 | } |
| 319 | 315 | ||
| 320 | if (!ts_first) | 316 | if (!ts_first) { |
| 321 | { | ||
| 322 | ts_last = nullptr; | 317 | ts_last = nullptr; |
| 323 | return result; | 318 | return result; |
| 324 | } | 319 | } |
| @@ -369,7 +364,7 @@ void RemoveEvent(int event_type) { | |||
| 369 | return; | 364 | return; |
| 370 | while (first) { | 365 | while (first) { |
| 371 | if (first->type == event_type) { | 366 | if (first->type == event_type) { |
| 372 | Event *next = first->next; | 367 | Event* next = first->next; |
| 373 | FreeEvent(first); | 368 | FreeEvent(first); |
| 374 | first = next; | 369 | first = next; |
| 375 | } else { | 370 | } else { |
| @@ -509,7 +504,8 @@ void Advance() { | |||
| 509 | void LogPendingEvents() { | 504 | void LogPendingEvents() { |
| 510 | Event* event = first; | 505 | Event* event = first; |
| 511 | while (event) { | 506 | while (event) { |
| 512 | //LOG_TRACE(Core_Timing, "PENDING: Now: %lld Pending: %lld Type: %d", globalTimer, next->time, next->type); | 507 | // LOG_TRACE(Core_Timing, "PENDING: Now: %lld Pending: %lld Type: %d", globalTimer, |
| 508 | // next->time, next->type); | ||
| 513 | event = event->next; | 509 | event = event->next; |
| 514 | } | 510 | } |
| 515 | } | 511 | } |
| @@ -531,7 +527,8 @@ void Idle(int max_idle) { | |||
| 531 | } | 527 | } |
| 532 | } | 528 | } |
| 533 | 529 | ||
| 534 | LOG_TRACE(Core_Timing, "Idle for %" PRId64 " cycles! (%f ms)", cycles_down, cycles_down / (float)(g_clock_rate_arm11 * 0.001f)); | 530 | LOG_TRACE(Core_Timing, "Idle for %" PRId64 " cycles! (%f ms)", cycles_down, |
| 531 | cycles_down / (float)(g_clock_rate_arm11 * 0.001f)); | ||
| 535 | 532 | ||
| 536 | idled_cycles += cycles_down; | 533 | idled_cycles += cycles_down; |
| 537 | Core::g_app_core->down_count -= cycles_down; | 534 | Core::g_app_core->down_count -= cycles_down; |
| @@ -551,7 +548,7 @@ std::string GetScheduledEventsSummary() { | |||
| 551 | if (!name) | 548 | if (!name) |
| 552 | name = "[unknown]"; | 549 | name = "[unknown]"; |
| 553 | text += Common::StringFromFormat("%s : %i %08x%08x\n", name, (int)event->time, | 550 | text += Common::StringFromFormat("%s : %i %08x%08x\n", name, (int)event->time, |
| 554 | (u32)(event->userdata >> 32), (u32)(event->userdata)); | 551 | (u32)(event->userdata >> 32), (u32)(event->userdata)); |
| 555 | event = event->next; | 552 | event = event->next; |
| 556 | } | 553 | } |
| 557 | return text; | 554 | return text; |
diff --git a/src/core/core_timing.h b/src/core/core_timing.h index 3d8a7d0c0..64fd8dcd0 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h | |||
| @@ -61,12 +61,11 @@ inline u64 cyclesToMs(s64 cycles) { | |||
| 61 | return cycles / (g_clock_rate_arm11 / 1000); | 61 | return cycles / (g_clock_rate_arm11 / 1000); |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | namespace CoreTiming | 64 | namespace CoreTiming { |
| 65 | { | ||
| 66 | void Init(); | 65 | void Init(); |
| 67 | void Shutdown(); | 66 | void Shutdown(); |
| 68 | 67 | ||
| 69 | typedef void(*MHzChangeCallback)(); | 68 | typedef void (*MHzChangeCallback)(); |
| 70 | typedef std::function<void(u64 userdata, int cycles_late)> TimedCallback; | 69 | typedef std::function<void(u64 userdata, int cycles_late)> TimedCallback; |
| 71 | 70 | ||
| 72 | u64 GetTicks(); | 71 | u64 GetTicks(); |
| @@ -81,7 +80,7 @@ u64 GetGlobalTimeUs(); | |||
| 81 | */ | 80 | */ |
| 82 | int RegisterEvent(const char* name, TimedCallback callback); | 81 | int RegisterEvent(const char* name, TimedCallback callback); |
| 83 | /// For save states. | 82 | /// For save states. |
| 84 | void RestoreRegisterEvent(int event_type, const char *name, TimedCallback callback); | 83 | void RestoreRegisterEvent(int event_type, const char* name, TimedCallback callback); |
| 85 | void UnregisterAllEvents(); | 84 | void UnregisterAllEvents(); |
| 86 | 85 | ||
| 87 | /// userdata MAY NOT CONTAIN POINTERS. userdata might get written and reloaded from disk, | 86 | /// userdata MAY NOT CONTAIN POINTERS. userdata might get written and reloaded from disk, |
| @@ -128,7 +127,7 @@ void ClearPendingEvents(); | |||
| 128 | void LogPendingEvents(); | 127 | void LogPendingEvents(); |
| 129 | 128 | ||
| 130 | /// Warning: not included in save states. | 129 | /// Warning: not included in save states. |
| 131 | void RegisterAdvanceCallback(void(*callback)(int cycles_executed)); | 130 | void RegisterAdvanceCallback(void (*callback)(int cycles_executed)); |
| 132 | void RegisterMHzChangeCallback(MHzChangeCallback callback); | 131 | void RegisterMHzChangeCallback(MHzChangeCallback callback); |
| 133 | 132 | ||
| 134 | std::string GetScheduledEventsSummary(); | 133 | std::string GetScheduledEventsSummary(); |
diff --git a/src/core/file_sys/archive_backend.cpp b/src/core/file_sys/archive_backend.cpp index cc0aa7022..6ea920ec1 100644 --- a/src/core/file_sys/archive_backend.cpp +++ b/src/core/file_sys/archive_backend.cpp | |||
| @@ -12,27 +12,23 @@ | |||
| 12 | #include "core/file_sys/archive_backend.h" | 12 | #include "core/file_sys/archive_backend.h" |
| 13 | #include "core/memory.h" | 13 | #include "core/memory.h" |
| 14 | 14 | ||
| 15 | |||
| 16 | namespace FileSys { | 15 | namespace FileSys { |
| 17 | 16 | ||
| 18 | Path::Path(LowPathType type, u32 size, u32 pointer) : type(type) { | 17 | Path::Path(LowPathType type, u32 size, u32 pointer) : type(type) { |
| 19 | switch (type) { | 18 | switch (type) { |
| 20 | case Binary: | 19 | case Binary: { |
| 21 | { | ||
| 22 | binary.resize(size); | 20 | binary.resize(size); |
| 23 | Memory::ReadBlock(pointer, binary.data(), binary.size()); | 21 | Memory::ReadBlock(pointer, binary.data(), binary.size()); |
| 24 | break; | 22 | break; |
| 25 | } | 23 | } |
| 26 | 24 | ||
| 27 | case Char: | 25 | case Char: { |
| 28 | { | ||
| 29 | string.resize(size - 1); // Data is always null-terminated. | 26 | string.resize(size - 1); // Data is always null-terminated. |
| 30 | Memory::ReadBlock(pointer, &string[0], string.size()); | 27 | Memory::ReadBlock(pointer, &string[0], string.size()); |
| 31 | break; | 28 | break; |
| 32 | } | 29 | } |
| 33 | 30 | ||
| 34 | case Wchar: | 31 | case Wchar: { |
| 35 | { | ||
| 36 | u16str.resize(size / 2 - 1); // Data is always null-terminated. | 32 | u16str.resize(size / 2 - 1); // Data is always null-terminated. |
| 37 | Memory::ReadBlock(pointer, &u16str[0], u16str.size() * sizeof(char16_t)); | 33 | Memory::ReadBlock(pointer, &u16str[0], u16str.size() * sizeof(char16_t)); |
| 38 | break; | 34 | break; |
| @@ -50,8 +46,7 @@ std::string Path::DebugStr() const { | |||
| 50 | return "[Invalid]"; | 46 | return "[Invalid]"; |
| 51 | case Empty: | 47 | case Empty: |
| 52 | return "[Empty]"; | 48 | return "[Empty]"; |
| 53 | case Binary: | 49 | case Binary: { |
| 54 | { | ||
| 55 | std::stringstream res; | 50 | std::stringstream res; |
| 56 | res << "[Binary: "; | 51 | res << "[Binary: "; |
| 57 | for (unsigned byte : binary) | 52 | for (unsigned byte : binary) |
| @@ -73,13 +68,13 @@ std::string Path::AsString() const { | |||
| 73 | case Wchar: | 68 | case Wchar: |
| 74 | return Common::UTF16ToUTF8(u16str); | 69 | return Common::UTF16ToUTF8(u16str); |
| 75 | case Empty: | 70 | case Empty: |
| 76 | return{}; | 71 | return {}; |
| 77 | case Invalid: | 72 | case Invalid: |
| 78 | case Binary: | 73 | case Binary: |
| 79 | default: | 74 | default: |
| 80 | // TODO(yuriks): Add assert | 75 | // TODO(yuriks): Add assert |
| 81 | LOG_ERROR(Service_FS, "LowPathType cannot be converted to string!"); | 76 | LOG_ERROR(Service_FS, "LowPathType cannot be converted to string!"); |
| 82 | return{}; | 77 | return {}; |
| 83 | } | 78 | } |
| 84 | } | 79 | } |
| 85 | 80 | ||
| @@ -90,12 +85,12 @@ std::u16string Path::AsU16Str() const { | |||
| 90 | case Wchar: | 85 | case Wchar: |
| 91 | return u16str; | 86 | return u16str; |
| 92 | case Empty: | 87 | case Empty: |
| 93 | return{}; | 88 | return {}; |
| 94 | case Invalid: | 89 | case Invalid: |
| 95 | case Binary: | 90 | case Binary: |
| 96 | // TODO(yuriks): Add assert | 91 | // TODO(yuriks): Add assert |
| 97 | LOG_ERROR(Service_FS, "LowPathType cannot be converted to u16string!"); | 92 | LOG_ERROR(Service_FS, "LowPathType cannot be converted to u16string!"); |
| 98 | return{}; | 93 | return {}; |
| 99 | } | 94 | } |
| 100 | } | 95 | } |
| 101 | 96 | ||
| @@ -105,25 +100,23 @@ std::vector<u8> Path::AsBinary() const { | |||
| 105 | return binary; | 100 | return binary; |
| 106 | case Char: | 101 | case Char: |
| 107 | return std::vector<u8>(string.begin(), string.end()); | 102 | return std::vector<u8>(string.begin(), string.end()); |
| 108 | case Wchar: | 103 | case Wchar: { |
| 109 | { | ||
| 110 | // use two u8 for each character of u16str | 104 | // use two u8 for each character of u16str |
| 111 | std::vector<u8> to_return(u16str.size() * 2); | 105 | std::vector<u8> to_return(u16str.size() * 2); |
| 112 | for (size_t i = 0; i < u16str.size(); ++i) { | 106 | for (size_t i = 0; i < u16str.size(); ++i) { |
| 113 | u16 tmp_char = u16str.at(i); | 107 | u16 tmp_char = u16str.at(i); |
| 114 | to_return[i*2] = (tmp_char & 0xFF00) >> 8; | 108 | to_return[i * 2] = (tmp_char & 0xFF00) >> 8; |
| 115 | to_return[i*2 + 1] = (tmp_char & 0x00FF); | 109 | to_return[i * 2 + 1] = (tmp_char & 0x00FF); |
| 116 | } | 110 | } |
| 117 | return to_return; | 111 | return to_return; |
| 118 | } | 112 | } |
| 119 | case Empty: | 113 | case Empty: |
| 120 | return{}; | 114 | return {}; |
| 121 | case Invalid: | 115 | case Invalid: |
| 122 | default: | 116 | default: |
| 123 | // TODO(yuriks): Add assert | 117 | // TODO(yuriks): Add assert |
| 124 | LOG_ERROR(Service_FS, "LowPathType cannot be converted to binary!"); | 118 | LOG_ERROR(Service_FS, "LowPathType cannot be converted to binary!"); |
| 125 | return{}; | 119 | return {}; |
| 126 | } | 120 | } |
| 127 | } | 121 | } |
| 128 | |||
| 129 | } | 122 | } |
diff --git a/src/core/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h index 5d91e47f3..79fde9710 100644 --- a/src/core/file_sys/archive_backend.h +++ b/src/core/file_sys/archive_backend.h | |||
| @@ -15,20 +15,13 @@ | |||
| 15 | 15 | ||
| 16 | #include "core/hle/result.h" | 16 | #include "core/hle/result.h" |
| 17 | 17 | ||
| 18 | |||
| 19 | namespace FileSys { | 18 | namespace FileSys { |
| 20 | 19 | ||
| 21 | class FileBackend; | 20 | class FileBackend; |
| 22 | class DirectoryBackend; | 21 | class DirectoryBackend; |
| 23 | 22 | ||
| 24 | // Path string type | 23 | // Path string type |
| 25 | enum LowPathType : u32 { | 24 | enum LowPathType : u32 { Invalid = 0, Empty = 1, Binary = 2, Char = 3, Wchar = 4 }; |
| 26 | Invalid = 0, | ||
| 27 | Empty = 1, | ||
| 28 | Binary = 2, | ||
| 29 | Char = 3, | ||
| 30 | Wchar = 4 | ||
| 31 | }; | ||
| 32 | 25 | ||
| 33 | union Mode { | 26 | union Mode { |
| 34 | u32 hex; | 27 | u32 hex; |
| @@ -39,12 +32,17 @@ union Mode { | |||
| 39 | 32 | ||
| 40 | class Path { | 33 | class Path { |
| 41 | public: | 34 | public: |
| 42 | Path() : type(Invalid) {} | 35 | Path() : type(Invalid) { |
| 43 | Path(const char* path) : type(Char), string(path) {} | 36 | } |
| 44 | Path(std::vector<u8> binary_data) : type(Binary), binary(std::move(binary_data)) {} | 37 | Path(const char* path) : type(Char), string(path) { |
| 38 | } | ||
| 39 | Path(std::vector<u8> binary_data) : type(Binary), binary(std::move(binary_data)) { | ||
| 40 | } | ||
| 45 | Path(LowPathType type, u32 size, u32 pointer); | 41 | Path(LowPathType type, u32 size, u32 pointer); |
| 46 | 42 | ||
| 47 | LowPathType GetType() const { return type; } | 43 | LowPathType GetType() const { |
| 44 | return type; | ||
| 45 | } | ||
| 48 | 46 | ||
| 49 | /** | 47 | /** |
| 50 | * Gets the string representation of the path for debugging | 48 | * Gets the string representation of the path for debugging |
| @@ -64,10 +62,14 @@ private: | |||
| 64 | }; | 62 | }; |
| 65 | 63 | ||
| 66 | struct ArchiveFormatInfo { | 64 | struct ArchiveFormatInfo { |
| 67 | u32_le total_size; ///< The pre-defined size of the archive, as specified in the Create or Format call | 65 | u32_le total_size; ///< The pre-defined size of the archive, as specified in the Create or |
| 68 | u32_le number_directories; ///< The pre-defined number of directories in the archive, as specified in the Create or Format call | 66 | /// Format call |
| 69 | u32_le number_files; ///< The pre-defined number of files in the archive, as specified in the Create or Format call | 67 | u32_le number_directories; ///< The pre-defined number of directories in the archive, as |
| 70 | u8 duplicate_data; ///< Whether the archive should duplicate the data, as specified in the Create or Format call | 68 | /// specified in the Create or Format call |
| 69 | u32_le number_files; ///< The pre-defined number of files in the archive, as specified in the | ||
| 70 | /// Create or Format call | ||
| 71 | u8 duplicate_data; ///< Whether the archive should duplicate the data, as specified in the | ||
| 72 | /// Create or Format call | ||
| 71 | }; | 73 | }; |
| 72 | static_assert(std::is_pod<ArchiveFormatInfo>::value, "ArchiveFormatInfo is not POD"); | 74 | static_assert(std::is_pod<ArchiveFormatInfo>::value, "ArchiveFormatInfo is not POD"); |
| 73 | 75 | ||
| @@ -87,7 +89,8 @@ public: | |||
| 87 | * @param mode Mode to open the file with | 89 | * @param mode Mode to open the file with |
| 88 | * @return Opened file, or error code | 90 | * @return Opened file, or error code |
| 89 | */ | 91 | */ |
| 90 | virtual ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path, const Mode mode) const = 0; | 92 | virtual ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path, |
| 93 | const Mode mode) const = 0; | ||
| 91 | 94 | ||
| 92 | /** | 95 | /** |
| 93 | * Delete a file specified by its path | 96 | * Delete a file specified by its path |
diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp index 1d9eaefcb..6b4af28bf 100644 --- a/src/core/file_sys/archive_extsavedata.cpp +++ b/src/core/file_sys/archive_extsavedata.cpp | |||
| @@ -30,10 +30,11 @@ std::string GetExtSaveDataPath(const std::string& mount_point, const Path& path) | |||
| 30 | 30 | ||
| 31 | std::string GetExtDataContainerPath(const std::string& mount_point, bool shared) { | 31 | std::string GetExtDataContainerPath(const std::string& mount_point, bool shared) { |
| 32 | if (shared) | 32 | if (shared) |
| 33 | return Common::StringFromFormat("%sdata/%s/extdata/", mount_point.c_str(), SYSTEM_ID.c_str()); | 33 | return Common::StringFromFormat("%sdata/%s/extdata/", mount_point.c_str(), |
| 34 | SYSTEM_ID.c_str()); | ||
| 34 | 35 | ||
| 35 | return Common::StringFromFormat("%sNintendo 3DS/%s/%s/extdata/", mount_point.c_str(), | 36 | return Common::StringFromFormat("%sNintendo 3DS/%s/%s/extdata/", mount_point.c_str(), |
| 36 | SYSTEM_ID.c_str(), SDCARD_ID.c_str()); | 37 | SYSTEM_ID.c_str(), SDCARD_ID.c_str()); |
| 37 | } | 38 | } |
| 38 | 39 | ||
| 39 | Path ConstructExtDataBinaryPath(u32 media_type, u32 high, u32 low) { | 40 | Path ConstructExtDataBinaryPath(u32 media_type, u32 high, u32 low) { |
| @@ -54,11 +55,12 @@ Path ConstructExtDataBinaryPath(u32 media_type, u32 high, u32 low) { | |||
| 54 | for (unsigned i = 0; i < 4; ++i) | 55 | for (unsigned i = 0; i < 4; ++i) |
| 55 | binary_path.push_back((high >> (8 * i)) & 0xFF); | 56 | binary_path.push_back((high >> (8 * i)) & 0xFF); |
| 56 | 57 | ||
| 57 | return { binary_path }; | 58 | return {binary_path}; |
| 58 | } | 59 | } |
| 59 | 60 | ||
| 60 | ArchiveFactory_ExtSaveData::ArchiveFactory_ExtSaveData(const std::string& mount_location, bool shared) | 61 | ArchiveFactory_ExtSaveData::ArchiveFactory_ExtSaveData(const std::string& mount_location, |
| 61 | : shared(shared), mount_point(GetExtDataContainerPath(mount_location, shared)) { | 62 | bool shared) |
| 63 | : shared(shared), mount_point(GetExtDataContainerPath(mount_location, shared)) { | ||
| 62 | LOG_INFO(Service_FS, "Directory %s set as base for ExtSaveData.", mount_point.c_str()); | 64 | LOG_INFO(Service_FS, "Directory %s set as base for ExtSaveData.", mount_point.c_str()); |
| 63 | } | 65 | } |
| 64 | 66 | ||
| @@ -88,7 +90,8 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(cons | |||
| 88 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | 90 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); |
| 89 | } | 91 | } |
| 90 | 92 | ||
| 91 | ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { | 93 | ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path, |
| 94 | const FileSys::ArchiveFormatInfo& format_info) { | ||
| 92 | // These folders are always created with the ExtSaveData | 95 | // These folders are always created with the ExtSaveData |
| 93 | std::string user_path = GetExtSaveDataPath(mount_point, path) + "user/"; | 96 | std::string user_path = GetExtSaveDataPath(mount_point, path) + "user/"; |
| 94 | std::string boss_path = GetExtSaveDataPath(mount_point, path) + "boss/"; | 97 | std::string boss_path = GetExtSaveDataPath(mount_point, path) + "boss/"; |
| @@ -115,7 +118,8 @@ ResultVal<ArchiveFormatInfo> ArchiveFactory_ExtSaveData::GetFormatInfo(const Pat | |||
| 115 | if (!file.IsOpen()) { | 118 | if (!file.IsOpen()) { |
| 116 | LOG_ERROR(Service_FS, "Could not open metadata information for archive"); | 119 | LOG_ERROR(Service_FS, "Could not open metadata information for archive"); |
| 117 | // TODO(Subv): Verify error code | 120 | // TODO(Subv): Verify error code |
| 118 | return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, ErrorSummary::InvalidState, ErrorLevel::Status); | 121 | return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, |
| 122 | ErrorSummary::InvalidState, ErrorLevel::Status); | ||
| 119 | } | 123 | } |
| 120 | 124 | ||
| 121 | ArchiveFormatInfo info = {}; | 125 | ArchiveFormatInfo info = {}; |
| @@ -123,7 +127,8 @@ ResultVal<ArchiveFormatInfo> ArchiveFactory_ExtSaveData::GetFormatInfo(const Pat | |||
| 123 | return MakeResult<ArchiveFormatInfo>(info); | 127 | return MakeResult<ArchiveFormatInfo>(info); |
| 124 | } | 128 | } |
| 125 | 129 | ||
| 126 | void ArchiveFactory_ExtSaveData::WriteIcon(const Path& path, const u8* icon_data, size_t icon_size) { | 130 | void ArchiveFactory_ExtSaveData::WriteIcon(const Path& path, const u8* icon_data, |
| 131 | size_t icon_size) { | ||
| 127 | std::string game_path = FileSys::GetExtSaveDataPath(GetMountPoint(), path); | 132 | std::string game_path = FileSys::GetExtSaveDataPath(GetMountPoint(), path); |
| 128 | FileUtil::IOFile icon_file(game_path + "icon", "wb"); | 133 | FileUtil::IOFile icon_file(game_path + "icon", "wb"); |
| 129 | icon_file.WriteBytes(icon_data, icon_size); | 134 | icon_file.WriteBytes(icon_data, icon_size); |
diff --git a/src/core/file_sys/archive_extsavedata.h b/src/core/file_sys/archive_extsavedata.h index e9a72850d..2b942817e 100644 --- a/src/core/file_sys/archive_extsavedata.h +++ b/src/core/file_sys/archive_extsavedata.h | |||
| @@ -28,13 +28,17 @@ public: | |||
| 28 | */ | 28 | */ |
| 29 | bool Initialize(); | 29 | bool Initialize(); |
| 30 | 30 | ||
| 31 | std::string GetName() const override { return "ExtSaveData"; } | 31 | std::string GetName() const override { |
| 32 | return "ExtSaveData"; | ||
| 33 | } | ||
| 32 | 34 | ||
| 33 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; | 35 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; |
| 34 | ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; | 36 | ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; |
| 35 | ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; | 37 | ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; |
| 36 | 38 | ||
| 37 | const std::string& GetMountPoint() const { return mount_point; } | 39 | const std::string& GetMountPoint() const { |
| 40 | return mount_point; | ||
| 41 | } | ||
| 38 | 42 | ||
| 39 | /** | 43 | /** |
| 40 | * Writes the SMDH icon of the ExtSaveData to file | 44 | * Writes the SMDH icon of the ExtSaveData to file |
| @@ -45,7 +49,8 @@ public: | |||
| 45 | void WriteIcon(const Path& path, const u8* icon_data, size_t icon_size); | 49 | void WriteIcon(const Path& path, const u8* icon_data, size_t icon_size); |
| 46 | 50 | ||
| 47 | private: | 51 | private: |
| 48 | bool shared; ///< Whether this archive represents an ExtSaveData archive or a SharedExtSaveData archive | 52 | bool shared; ///< Whether this archive represents an ExtSaveData archive or a SharedExtSaveData |
| 53 | /// archive | ||
| 49 | 54 | ||
| 50 | /** | 55 | /** |
| 51 | * This holds the full directory path for this archive, it is only set after a successful call | 56 | * This holds the full directory path for this archive, it is only set after a successful call |
| @@ -65,7 +70,8 @@ private: | |||
| 65 | std::string GetExtSaveDataPath(const std::string& mount_point, const Path& path); | 70 | std::string GetExtSaveDataPath(const std::string& mount_point, const Path& path); |
| 66 | 71 | ||
| 67 | /** | 72 | /** |
| 68 | * Constructs a path to the base folder to hold concrete ExtSaveData archives in the host file system. | 73 | * Constructs a path to the base folder to hold concrete ExtSaveData archives in the host file |
| 74 | * system. | ||
| 69 | * @param mount_point The base folder where this folder resides, ie. SDMC or NAND. | 75 | * @param mount_point The base folder where this folder resides, ie. SDMC or NAND. |
| 70 | * @param shared Whether this ExtSaveData container is for SharedExtSaveDatas or not. | 76 | * @param shared Whether this ExtSaveData container is for SharedExtSaveDatas or not. |
| 71 | * @returns The path to the base ExtSaveData archives' folder in the host file system | 77 | * @returns The path to the base ExtSaveData archives' folder in the host file system |
diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp index 38828b546..87455eb95 100644 --- a/src/core/file_sys/archive_romfs.cpp +++ b/src/core/file_sys/archive_romfs.cpp | |||
| @@ -28,11 +28,12 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_RomFS::Open(const Path | |||
| 28 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | 28 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | ResultCode ArchiveFactory_RomFS::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { | 31 | ResultCode ArchiveFactory_RomFS::Format(const Path& path, |
| 32 | const FileSys::ArchiveFormatInfo& format_info) { | ||
| 32 | LOG_ERROR(Service_FS, "Attempted to format a RomFS archive."); | 33 | LOG_ERROR(Service_FS, "Attempted to format a RomFS archive."); |
| 33 | // TODO: Verify error code | 34 | // TODO: Verify error code |
| 34 | return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, | 35 | return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported, |
| 35 | ErrorSummary::NotSupported, ErrorLevel::Permanent); | 36 | ErrorLevel::Permanent); |
| 36 | } | 37 | } |
| 37 | 38 | ||
| 38 | ResultVal<ArchiveFormatInfo> ArchiveFactory_RomFS::GetFormatInfo(const Path& path) const { | 39 | ResultVal<ArchiveFormatInfo> ArchiveFactory_RomFS::GetFormatInfo(const Path& path) const { |
diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h index c5a329122..3c68a6b1c 100644 --- a/src/core/file_sys/archive_romfs.h +++ b/src/core/file_sys/archive_romfs.h | |||
| @@ -24,7 +24,9 @@ class ArchiveFactory_RomFS final : public ArchiveFactory { | |||
| 24 | public: | 24 | public: |
| 25 | ArchiveFactory_RomFS(Loader::AppLoader& app_loader); | 25 | ArchiveFactory_RomFS(Loader::AppLoader& app_loader); |
| 26 | 26 | ||
| 27 | std::string GetName() const override { return "RomFS"; } | 27 | std::string GetName() const override { |
| 28 | return "RomFS"; | ||
| 29 | } | ||
| 28 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; | 30 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; |
| 29 | ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; | 31 | ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; |
| 30 | ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; | 32 | ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; |
diff --git a/src/core/file_sys/archive_savedata.cpp b/src/core/file_sys/archive_savedata.cpp index fd5711e14..9a264091f 100644 --- a/src/core/file_sys/archive_savedata.cpp +++ b/src/core/file_sys/archive_savedata.cpp | |||
| @@ -22,48 +22,55 @@ namespace FileSys { | |||
| 22 | 22 | ||
| 23 | static std::string GetSaveDataContainerPath(const std::string& sdmc_directory) { | 23 | static std::string GetSaveDataContainerPath(const std::string& sdmc_directory) { |
| 24 | return Common::StringFromFormat("%sNintendo 3DS/%s/%s/title/", sdmc_directory.c_str(), | 24 | return Common::StringFromFormat("%sNintendo 3DS/%s/%s/title/", sdmc_directory.c_str(), |
| 25 | SYSTEM_ID.c_str(), SDCARD_ID.c_str()); | 25 | SYSTEM_ID.c_str(), SDCARD_ID.c_str()); |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | static std::string GetSaveDataPath(const std::string& mount_location, u64 program_id) { | 28 | static std::string GetSaveDataPath(const std::string& mount_location, u64 program_id) { |
| 29 | u32 high = (u32)(program_id >> 32); | 29 | u32 high = (u32)(program_id >> 32); |
| 30 | u32 low = (u32)(program_id & 0xFFFFFFFF); | 30 | u32 low = (u32)(program_id & 0xFFFFFFFF); |
| 31 | return Common::StringFromFormat("%s%08x/%08x/data/00000001/", mount_location.c_str(), high, low); | 31 | return Common::StringFromFormat("%s%08x/%08x/data/00000001/", mount_location.c_str(), high, |
| 32 | low); | ||
| 32 | } | 33 | } |
| 33 | 34 | ||
| 34 | static std::string GetSaveDataMetadataPath(const std::string& mount_location, u64 program_id) { | 35 | static std::string GetSaveDataMetadataPath(const std::string& mount_location, u64 program_id) { |
| 35 | u32 high = (u32)(program_id >> 32); | 36 | u32 high = (u32)(program_id >> 32); |
| 36 | u32 low = (u32)(program_id & 0xFFFFFFFF); | 37 | u32 low = (u32)(program_id & 0xFFFFFFFF); |
| 37 | return Common::StringFromFormat("%s%08x/%08x/data/00000001.metadata", mount_location.c_str(), high, low); | 38 | return Common::StringFromFormat("%s%08x/%08x/data/00000001.metadata", mount_location.c_str(), |
| 39 | high, low); | ||
| 38 | } | 40 | } |
| 39 | 41 | ||
| 40 | ArchiveFactory_SaveData::ArchiveFactory_SaveData(const std::string& sdmc_directory) | 42 | ArchiveFactory_SaveData::ArchiveFactory_SaveData(const std::string& sdmc_directory) |
| 41 | : mount_point(GetSaveDataContainerPath(sdmc_directory)) { | 43 | : mount_point(GetSaveDataContainerPath(sdmc_directory)) { |
| 42 | LOG_INFO(Service_FS, "Directory %s set as SaveData.", this->mount_point.c_str()); | 44 | LOG_INFO(Service_FS, "Directory %s set as SaveData.", this->mount_point.c_str()); |
| 43 | } | 45 | } |
| 44 | 46 | ||
| 45 | ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const Path& path) { | 47 | ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const Path& path) { |
| 46 | std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_current_process->codeset->program_id); | 48 | std::string concrete_mount_point = |
| 49 | GetSaveDataPath(mount_point, Kernel::g_current_process->codeset->program_id); | ||
| 47 | if (!FileUtil::Exists(concrete_mount_point)) { | 50 | if (!FileUtil::Exists(concrete_mount_point)) { |
| 48 | // When a SaveData archive is created for the first time, it is not yet formatted | 51 | // When a SaveData archive is created for the first time, it is not yet formatted |
| 49 | // and the save file/directory structure expected by the game has not yet been initialized. | 52 | // and the save file/directory structure expected by the game has not yet been initialized. |
| 50 | // Returning the NotFormatted error code will signal the game to provision the SaveData archive | 53 | // Returning the NotFormatted error code will signal the game to provision the SaveData |
| 54 | // archive | ||
| 51 | // with the files and folders that it expects. | 55 | // with the files and folders that it expects. |
| 52 | return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, | 56 | return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, |
| 53 | ErrorSummary::InvalidState, ErrorLevel::Status); | 57 | ErrorSummary::InvalidState, ErrorLevel::Status); |
| 54 | } | 58 | } |
| 55 | 59 | ||
| 56 | auto archive = std::make_unique<DiskArchive>(std::move(concrete_mount_point)); | 60 | auto archive = std::make_unique<DiskArchive>(std::move(concrete_mount_point)); |
| 57 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | 61 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); |
| 58 | } | 62 | } |
| 59 | 63 | ||
| 60 | ResultCode ArchiveFactory_SaveData::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { | 64 | ResultCode ArchiveFactory_SaveData::Format(const Path& path, |
| 61 | std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_current_process->codeset->program_id); | 65 | const FileSys::ArchiveFormatInfo& format_info) { |
| 66 | std::string concrete_mount_point = | ||
| 67 | GetSaveDataPath(mount_point, Kernel::g_current_process->codeset->program_id); | ||
| 62 | FileUtil::DeleteDirRecursively(concrete_mount_point); | 68 | FileUtil::DeleteDirRecursively(concrete_mount_point); |
| 63 | FileUtil::CreateFullPath(concrete_mount_point); | 69 | FileUtil::CreateFullPath(concrete_mount_point); |
| 64 | 70 | ||
| 65 | // Write the format metadata | 71 | // Write the format metadata |
| 66 | std::string metadata_path = GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id); | 72 | std::string metadata_path = |
| 73 | GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id); | ||
| 67 | FileUtil::IOFile file(metadata_path, "wb"); | 74 | FileUtil::IOFile file(metadata_path, "wb"); |
| 68 | 75 | ||
| 69 | if (file.IsOpen()) { | 76 | if (file.IsOpen()) { |
| @@ -74,13 +81,15 @@ ResultCode ArchiveFactory_SaveData::Format(const Path& path, const FileSys::Arch | |||
| 74 | } | 81 | } |
| 75 | 82 | ||
| 76 | ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveData::GetFormatInfo(const Path& path) const { | 83 | ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveData::GetFormatInfo(const Path& path) const { |
| 77 | std::string metadata_path = GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id); | 84 | std::string metadata_path = |
| 85 | GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id); | ||
| 78 | FileUtil::IOFile file(metadata_path, "rb"); | 86 | FileUtil::IOFile file(metadata_path, "rb"); |
| 79 | 87 | ||
| 80 | if (!file.IsOpen()) { | 88 | if (!file.IsOpen()) { |
| 81 | LOG_ERROR(Service_FS, "Could not open metadata information for archive"); | 89 | LOG_ERROR(Service_FS, "Could not open metadata information for archive"); |
| 82 | // TODO(Subv): Verify error code | 90 | // TODO(Subv): Verify error code |
| 83 | return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, ErrorSummary::InvalidState, ErrorLevel::Status); | 91 | return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, |
| 92 | ErrorSummary::InvalidState, ErrorLevel::Status); | ||
| 84 | } | 93 | } |
| 85 | 94 | ||
| 86 | ArchiveFormatInfo info = {}; | 95 | ArchiveFormatInfo info = {}; |
diff --git a/src/core/file_sys/archive_savedata.h b/src/core/file_sys/archive_savedata.h index 7a5a24089..4ac324985 100644 --- a/src/core/file_sys/archive_savedata.h +++ b/src/core/file_sys/archive_savedata.h | |||
| @@ -20,7 +20,9 @@ class ArchiveFactory_SaveData final : public ArchiveFactory { | |||
| 20 | public: | 20 | public: |
| 21 | ArchiveFactory_SaveData(const std::string& mount_point); | 21 | ArchiveFactory_SaveData(const std::string& mount_point); |
| 22 | 22 | ||
| 23 | std::string GetName() const override { return "SaveData"; } | 23 | std::string GetName() const override { |
| 24 | return "SaveData"; | ||
| 25 | } | ||
| 24 | 26 | ||
| 25 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; | 27 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; |
| 26 | ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; | 28 | ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; |
diff --git a/src/core/file_sys/archive_savedatacheck.cpp b/src/core/file_sys/archive_savedatacheck.cpp index 9f65e5455..fd9b84302 100644 --- a/src/core/file_sys/archive_savedatacheck.cpp +++ b/src/core/file_sys/archive_savedatacheck.cpp | |||
| @@ -25,12 +25,12 @@ static std::string GetSaveDataCheckContainerPath(const std::string& nand_directo | |||
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | static std::string GetSaveDataCheckPath(const std::string& mount_point, u32 high, u32 low) { | 27 | static std::string GetSaveDataCheckPath(const std::string& mount_point, u32 high, u32 low) { |
| 28 | return Common::StringFromFormat("%s%08x/%08x/content/00000000.app.romfs", | 28 | return Common::StringFromFormat("%s%08x/%08x/content/00000000.app.romfs", mount_point.c_str(), |
| 29 | mount_point.c_str(), high, low); | 29 | high, low); |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | ArchiveFactory_SaveDataCheck::ArchiveFactory_SaveDataCheck(const std::string& nand_directory) : | 32 | ArchiveFactory_SaveDataCheck::ArchiveFactory_SaveDataCheck(const std::string& nand_directory) |
| 33 | mount_point(GetSaveDataCheckContainerPath(nand_directory)) { | 33 | : mount_point(GetSaveDataCheckContainerPath(nand_directory)) { |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveDataCheck::Open(const Path& path) { | 36 | ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveDataCheck::Open(const Path& path) { |
| @@ -48,11 +48,12 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveDataCheck::Open(co | |||
| 48 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | 48 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | ResultCode ArchiveFactory_SaveDataCheck::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { | 51 | ResultCode ArchiveFactory_SaveDataCheck::Format(const Path& path, |
| 52 | const FileSys::ArchiveFormatInfo& format_info) { | ||
| 52 | LOG_ERROR(Service_FS, "Attempted to format a SaveDataCheck archive."); | 53 | LOG_ERROR(Service_FS, "Attempted to format a SaveDataCheck archive."); |
| 53 | // TODO: Verify error code | 54 | // TODO: Verify error code |
| 54 | return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, | 55 | return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported, |
| 55 | ErrorSummary::NotSupported, ErrorLevel::Permanent); | 56 | ErrorLevel::Permanent); |
| 56 | } | 57 | } |
| 57 | 58 | ||
| 58 | ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveDataCheck::GetFormatInfo(const Path& path) const { | 59 | ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveDataCheck::GetFormatInfo(const Path& path) const { |
diff --git a/src/core/file_sys/archive_savedatacheck.h b/src/core/file_sys/archive_savedatacheck.h index ea2624d64..4a4259260 100644 --- a/src/core/file_sys/archive_savedatacheck.h +++ b/src/core/file_sys/archive_savedatacheck.h | |||
| @@ -20,7 +20,9 @@ class ArchiveFactory_SaveDataCheck final : public ArchiveFactory { | |||
| 20 | public: | 20 | public: |
| 21 | ArchiveFactory_SaveDataCheck(const std::string& mount_point); | 21 | ArchiveFactory_SaveDataCheck(const std::string& mount_point); |
| 22 | 22 | ||
| 23 | std::string GetName() const override { return "SaveDataCheck"; } | 23 | std::string GetName() const override { |
| 24 | return "SaveDataCheck"; | ||
| 25 | } | ||
| 24 | 26 | ||
| 25 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; | 27 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; |
| 26 | ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; | 28 | ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; |
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp index 9b218af58..c1a28df6c 100644 --- a/src/core/file_sys/archive_sdmc.cpp +++ b/src/core/file_sys/archive_sdmc.cpp | |||
| @@ -17,7 +17,8 @@ | |||
| 17 | 17 | ||
| 18 | namespace FileSys { | 18 | namespace FileSys { |
| 19 | 19 | ||
| 20 | ArchiveFactory_SDMC::ArchiveFactory_SDMC(const std::string& sdmc_directory) : sdmc_directory(sdmc_directory) { | 20 | ArchiveFactory_SDMC::ArchiveFactory_SDMC(const std::string& sdmc_directory) |
| 21 | : sdmc_directory(sdmc_directory) { | ||
| 21 | LOG_INFO(Service_FS, "Directory %s set as SDMC.", sdmc_directory.c_str()); | 22 | LOG_INFO(Service_FS, "Directory %s set as SDMC.", sdmc_directory.c_str()); |
| 22 | } | 23 | } |
| 23 | 24 | ||
| @@ -40,7 +41,8 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMC::Open(const Path& | |||
| 40 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | 41 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); |
| 41 | } | 42 | } |
| 42 | 43 | ||
| 43 | ResultCode ArchiveFactory_SDMC::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { | 44 | ResultCode ArchiveFactory_SDMC::Format(const Path& path, |
| 45 | const FileSys::ArchiveFormatInfo& format_info) { | ||
| 44 | // This is kind of an undesirable operation, so let's just ignore it. :) | 46 | // This is kind of an undesirable operation, so let's just ignore it. :) |
| 45 | return RESULT_SUCCESS; | 47 | return RESULT_SUCCESS; |
| 46 | } | 48 | } |
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h index 35c0f3725..2523c3979 100644 --- a/src/core/file_sys/archive_sdmc.h +++ b/src/core/file_sys/archive_sdmc.h | |||
| @@ -26,7 +26,9 @@ public: | |||
| 26 | */ | 26 | */ |
| 27 | bool Initialize(); | 27 | bool Initialize(); |
| 28 | 28 | ||
| 29 | std::string GetName() const override { return "SDMC"; } | 29 | std::string GetName() const override { |
| 30 | return "SDMC"; | ||
| 31 | } | ||
| 30 | 32 | ||
| 31 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; | 33 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; |
| 32 | ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; | 34 | ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; |
diff --git a/src/core/file_sys/archive_systemsavedata.cpp b/src/core/file_sys/archive_systemsavedata.cpp index 1bcc228a1..1fb858247 100644 --- a/src/core/file_sys/archive_systemsavedata.cpp +++ b/src/core/file_sys/archive_systemsavedata.cpp | |||
| @@ -45,11 +45,11 @@ Path ConstructSystemSaveDataBinaryPath(u32 high, u32 low) { | |||
| 45 | for (unsigned i = 0; i < 4; ++i) | 45 | for (unsigned i = 0; i < 4; ++i) |
| 46 | binary_path.push_back((low >> (8 * i)) & 0xFF); | 46 | binary_path.push_back((low >> (8 * i)) & 0xFF); |
| 47 | 47 | ||
| 48 | return { binary_path }; | 48 | return {binary_path}; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | ArchiveFactory_SystemSaveData::ArchiveFactory_SystemSaveData(const std::string& nand_path) | 51 | ArchiveFactory_SystemSaveData::ArchiveFactory_SystemSaveData(const std::string& nand_path) |
| 52 | : base_path(GetSystemSaveDataContainerPath(nand_path)) { | 52 | : base_path(GetSystemSaveDataContainerPath(nand_path)) { |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SystemSaveData::Open(const Path& path) { | 55 | ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SystemSaveData::Open(const Path& path) { |
| @@ -57,13 +57,14 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SystemSaveData::Open(c | |||
| 57 | if (!FileUtil::Exists(fullpath)) { | 57 | if (!FileUtil::Exists(fullpath)) { |
| 58 | // TODO(Subv): Check error code, this one is probably wrong | 58 | // TODO(Subv): Check error code, this one is probably wrong |
| 59 | return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, | 59 | return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, |
| 60 | ErrorSummary::InvalidState, ErrorLevel::Status); | 60 | ErrorSummary::InvalidState, ErrorLevel::Status); |
| 61 | } | 61 | } |
| 62 | auto archive = std::make_unique<DiskArchive>(fullpath); | 62 | auto archive = std::make_unique<DiskArchive>(fullpath); |
| 63 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | 63 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | ResultCode ArchiveFactory_SystemSaveData::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { | 66 | ResultCode ArchiveFactory_SystemSaveData::Format(const Path& path, |
| 67 | const FileSys::ArchiveFormatInfo& format_info) { | ||
| 67 | std::string fullpath = GetSystemSaveDataPath(base_path, path); | 68 | std::string fullpath = GetSystemSaveDataPath(base_path, path); |
| 68 | FileUtil::DeleteDirRecursively(fullpath); | 69 | FileUtil::DeleteDirRecursively(fullpath); |
| 69 | FileUtil::CreateFullPath(fullpath); | 70 | FileUtil::CreateFullPath(fullpath); |
diff --git a/src/core/file_sys/archive_systemsavedata.h b/src/core/file_sys/archive_systemsavedata.h index 2bc13d4ee..61a002a7d 100644 --- a/src/core/file_sys/archive_systemsavedata.h +++ b/src/core/file_sys/archive_systemsavedata.h | |||
| @@ -26,7 +26,9 @@ public: | |||
| 26 | ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; | 26 | ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; |
| 27 | ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; | 27 | ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; |
| 28 | 28 | ||
| 29 | std::string GetName() const override { return "SystemSaveData"; } | 29 | std::string GetName() const override { |
| 30 | return "SystemSaveData"; | ||
| 31 | } | ||
| 30 | 32 | ||
| 31 | private: | 33 | private: |
| 32 | std::string base_path; | 34 | std::string base_path; |
| @@ -42,7 +44,8 @@ private: | |||
| 42 | std::string GetSystemSaveDataPath(const std::string& mount_point, const Path& path); | 44 | std::string GetSystemSaveDataPath(const std::string& mount_point, const Path& path); |
| 43 | 45 | ||
| 44 | /** | 46 | /** |
| 45 | * Constructs a path to the base folder to hold concrete SystemSaveData archives in the host file system. | 47 | * Constructs a path to the base folder to hold concrete SystemSaveData archives in the host file |
| 48 | * system. | ||
| 46 | * @param mount_point The base folder where this folder resides, ie. SDMC or NAND. | 49 | * @param mount_point The base folder where this folder resides, ie. SDMC or NAND. |
| 47 | * @returns The path to the base SystemSaveData archives' folder in the host file system | 50 | * @returns The path to the base SystemSaveData archives' folder in the host file system |
| 48 | */ | 51 | */ |
diff --git a/src/core/file_sys/directory_backend.h b/src/core/file_sys/directory_backend.h index a25dc0cfa..c402ee60b 100644 --- a/src/core/file_sys/directory_backend.h +++ b/src/core/file_sys/directory_backend.h | |||
| @@ -19,15 +19,16 @@ const size_t FILENAME_LENGTH = 0x20C / 2; | |||
| 19 | struct Entry { | 19 | struct Entry { |
| 20 | char16_t filename[FILENAME_LENGTH]; // Entry name (UTF-16, null-terminated) | 20 | char16_t filename[FILENAME_LENGTH]; // Entry name (UTF-16, null-terminated) |
| 21 | std::array<char, 9> short_name; // 8.3 file name ('longfilename' -> 'LONGFI~1', null-terminated) | 21 | std::array<char, 9> short_name; // 8.3 file name ('longfilename' -> 'LONGFI~1', null-terminated) |
| 22 | char unknown1; // unknown (observed values: 0x0A, 0x70, 0xFD) | 22 | char unknown1; // unknown (observed values: 0x0A, 0x70, 0xFD) |
| 23 | std::array<char, 4> extension; // 8.3 file extension (set to spaces for directories, null-terminated) | 23 | std::array<char, 4> |
| 24 | char unknown2; // unknown (always 0x01) | 24 | extension; // 8.3 file extension (set to spaces for directories, null-terminated) |
| 25 | char unknown3; // unknown (0x00 or 0x08) | 25 | char unknown2; // unknown (always 0x01) |
| 26 | char unknown3; // unknown (0x00 or 0x08) | ||
| 26 | char is_directory; // directory flag | 27 | char is_directory; // directory flag |
| 27 | char is_hidden; // hidden flag | 28 | char is_hidden; // hidden flag |
| 28 | char is_archive; // archive flag | 29 | char is_archive; // archive flag |
| 29 | char is_read_only; // read-only flag | 30 | char is_read_only; // read-only flag |
| 30 | u64 file_size; // file size (for files only) | 31 | u64 file_size; // file size (for files only) |
| 31 | }; | 32 | }; |
| 32 | static_assert(sizeof(Entry) == 0x228, "Directory Entry struct isn't exactly 0x228 bytes long!"); | 33 | static_assert(sizeof(Entry) == 0x228, "Directory Entry struct isn't exactly 0x228 bytes long!"); |
| 33 | static_assert(offsetof(Entry, short_name) == 0x20C, "Wrong offset for short_name in Entry."); | 34 | static_assert(offsetof(Entry, short_name) == 0x20C, "Wrong offset for short_name in Entry."); |
| @@ -37,8 +38,10 @@ static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size i | |||
| 37 | 38 | ||
| 38 | class DirectoryBackend : NonCopyable { | 39 | class DirectoryBackend : NonCopyable { |
| 39 | public: | 40 | public: |
| 40 | DirectoryBackend() { } | 41 | DirectoryBackend() { |
| 41 | virtual ~DirectoryBackend() { } | 42 | } |
| 43 | virtual ~DirectoryBackend() { | ||
| 44 | } | ||
| 42 | 45 | ||
| 43 | /** | 46 | /** |
| 44 | * Open the directory | 47 | * Open the directory |
diff --git a/src/core/file_sys/disk_archive.cpp b/src/core/file_sys/disk_archive.cpp index 489cc96fb..c084303c1 100644 --- a/src/core/file_sys/disk_archive.cpp +++ b/src/core/file_sys/disk_archive.cpp | |||
| @@ -17,7 +17,8 @@ | |||
| 17 | 17 | ||
| 18 | namespace FileSys { | 18 | namespace FileSys { |
| 19 | 19 | ||
| 20 | ResultVal<std::unique_ptr<FileBackend>> DiskArchive::OpenFile(const Path& path, const Mode mode) const { | 20 | ResultVal<std::unique_ptr<FileBackend>> DiskArchive::OpenFile(const Path& path, |
| 21 | const Mode mode) const { | ||
| 21 | LOG_DEBUG(Service_FS, "called path=%s mode=%01X", path.DebugStr().c_str(), mode.hex); | 22 | LOG_DEBUG(Service_FS, "called path=%s mode=%01X", path.DebugStr().c_str(), mode.hex); |
| 22 | auto file = std::make_unique<DiskFile>(*this, path, mode); | 23 | auto file = std::make_unique<DiskFile>(*this, path, mode); |
| 23 | ResultCode result = file->Open(); | 24 | ResultCode result = file->Open(); |
| @@ -30,15 +31,18 @@ ResultCode DiskArchive::DeleteFile(const Path& path) const { | |||
| 30 | std::string file_path = mount_point + path.AsString(); | 31 | std::string file_path = mount_point + path.AsString(); |
| 31 | 32 | ||
| 32 | if (FileUtil::IsDirectory(file_path)) | 33 | if (FileUtil::IsDirectory(file_path)) |
| 33 | return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); | 34 | return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, |
| 35 | ErrorLevel::Status); | ||
| 34 | 36 | ||
| 35 | if (!FileUtil::Exists(file_path)) | 37 | if (!FileUtil::Exists(file_path)) |
| 36 | return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound, ErrorLevel::Status); | 38 | return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound, |
| 39 | ErrorLevel::Status); | ||
| 37 | 40 | ||
| 38 | if (FileUtil::Delete(file_path)) | 41 | if (FileUtil::Delete(file_path)) |
| 39 | return RESULT_SUCCESS; | 42 | return RESULT_SUCCESS; |
| 40 | 43 | ||
| 41 | return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); | 44 | return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, |
| 45 | ErrorLevel::Status); | ||
| 42 | } | 46 | } |
| 43 | 47 | ||
| 44 | bool DiskArchive::RenameFile(const Path& src_path, const Path& dest_path) const { | 48 | bool DiskArchive::RenameFile(const Path& src_path, const Path& dest_path) const { |
| @@ -53,10 +57,12 @@ ResultCode DiskArchive::CreateFile(const FileSys::Path& path, u64 size) const { | |||
| 53 | std::string full_path = mount_point + path.AsString(); | 57 | std::string full_path = mount_point + path.AsString(); |
| 54 | 58 | ||
| 55 | if (FileUtil::IsDirectory(full_path)) | 59 | if (FileUtil::IsDirectory(full_path)) |
| 56 | return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); | 60 | return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, |
| 61 | ErrorLevel::Status); | ||
| 57 | 62 | ||
| 58 | if (FileUtil::Exists(full_path)) | 63 | if (FileUtil::Exists(full_path)) |
| 59 | return ResultCode(ErrorDescription::FS_AlreadyExists, ErrorModule::FS, ErrorSummary::NothingHappened, ErrorLevel::Status); | 64 | return ResultCode(ErrorDescription::FS_AlreadyExists, ErrorModule::FS, |
| 65 | ErrorSummary::NothingHappened, ErrorLevel::Status); | ||
| 60 | 66 | ||
| 61 | if (size == 0) { | 67 | if (size == 0) { |
| 62 | FileUtil::CreateEmptyFile(full_path); | 68 | FileUtil::CreateEmptyFile(full_path); |
| @@ -69,10 +75,10 @@ ResultCode DiskArchive::CreateFile(const FileSys::Path& path, u64 size) const { | |||
| 69 | if (file.Seek(size - 1, SEEK_SET) && file.WriteBytes("", 1) == 1) | 75 | if (file.Seek(size - 1, SEEK_SET) && file.WriteBytes("", 1) == 1) |
| 70 | return RESULT_SUCCESS; | 76 | return RESULT_SUCCESS; |
| 71 | 77 | ||
| 72 | return ResultCode(ErrorDescription::TooLarge, ErrorModule::FS, ErrorSummary::OutOfResource, ErrorLevel::Info); | 78 | return ResultCode(ErrorDescription::TooLarge, ErrorModule::FS, ErrorSummary::OutOfResource, |
| 79 | ErrorLevel::Info); | ||
| 73 | } | 80 | } |
| 74 | 81 | ||
| 75 | |||
| 76 | bool DiskArchive::CreateDirectory(const Path& path) const { | 82 | bool DiskArchive::CreateDirectory(const Path& path) const { |
| 77 | return FileUtil::CreateDir(mount_point + path.AsString()); | 83 | return FileUtil::CreateDir(mount_point + path.AsString()); |
| 78 | } | 84 | } |
| @@ -106,17 +112,21 @@ DiskFile::DiskFile(const DiskArchive& archive, const Path& path, const Mode mode | |||
| 106 | 112 | ||
| 107 | ResultCode DiskFile::Open() { | 113 | ResultCode DiskFile::Open() { |
| 108 | if (FileUtil::IsDirectory(path)) | 114 | if (FileUtil::IsDirectory(path)) |
| 109 | return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); | 115 | return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, |
| 116 | ErrorLevel::Status); | ||
| 110 | 117 | ||
| 111 | // Specifying only the Create flag is invalid | 118 | // Specifying only the Create flag is invalid |
| 112 | if (mode.create_flag && !mode.read_flag && !mode.write_flag) { | 119 | if (mode.create_flag && !mode.read_flag && !mode.write_flag) { |
| 113 | return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); | 120 | return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS, |
| 121 | ErrorSummary::Canceled, ErrorLevel::Status); | ||
| 114 | } | 122 | } |
| 115 | 123 | ||
| 116 | if (!FileUtil::Exists(path)) { | 124 | if (!FileUtil::Exists(path)) { |
| 117 | if (!mode.create_flag) { | 125 | if (!mode.create_flag) { |
| 118 | LOG_ERROR(Service_FS, "Non-existing file %s can't be open without mode create.", path.c_str()); | 126 | LOG_ERROR(Service_FS, "Non-existing file %s can't be open without mode create.", |
| 119 | return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound, ErrorLevel::Status); | 127 | path.c_str()); |
| 128 | return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, | ||
| 129 | ErrorSummary::NotFound, ErrorLevel::Status); | ||
| 120 | } else { | 130 | } else { |
| 121 | // Create the file | 131 | // Create the file |
| 122 | FileUtil::CreateEmptyFile(path); | 132 | FileUtil::CreateEmptyFile(path); |
| @@ -135,20 +145,24 @@ ResultCode DiskFile::Open() { | |||
| 135 | file = std::make_unique<FileUtil::IOFile>(path, mode_string.c_str()); | 145 | file = std::make_unique<FileUtil::IOFile>(path, mode_string.c_str()); |
| 136 | if (file->IsOpen()) | 146 | if (file->IsOpen()) |
| 137 | return RESULT_SUCCESS; | 147 | return RESULT_SUCCESS; |
| 138 | return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound, ErrorLevel::Status); | 148 | return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound, |
| 149 | ErrorLevel::Status); | ||
| 139 | } | 150 | } |
| 140 | 151 | ||
| 141 | ResultVal<size_t> DiskFile::Read(const u64 offset, const size_t length, u8* buffer) const { | 152 | ResultVal<size_t> DiskFile::Read(const u64 offset, const size_t length, u8* buffer) const { |
| 142 | if (!mode.read_flag && !mode.write_flag) | 153 | if (!mode.read_flag && !mode.write_flag) |
| 143 | return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); | 154 | return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS, |
| 155 | ErrorSummary::Canceled, ErrorLevel::Status); | ||
| 144 | 156 | ||
| 145 | file->Seek(offset, SEEK_SET); | 157 | file->Seek(offset, SEEK_SET); |
| 146 | return MakeResult<size_t>(file->ReadBytes(buffer, length)); | 158 | return MakeResult<size_t>(file->ReadBytes(buffer, length)); |
| 147 | } | 159 | } |
| 148 | 160 | ||
| 149 | ResultVal<size_t> DiskFile::Write(const u64 offset, const size_t length, const bool flush, const u8* buffer) const { | 161 | ResultVal<size_t> DiskFile::Write(const u64 offset, const size_t length, const bool flush, |
| 162 | const u8* buffer) const { | ||
| 150 | if (!mode.write_flag) | 163 | if (!mode.write_flag) |
| 151 | return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); | 164 | return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS, |
| 165 | ErrorSummary::Canceled, ErrorLevel::Status); | ||
| 152 | 166 | ||
| 153 | file->Seek(offset, SEEK_SET); | 167 | file->Seek(offset, SEEK_SET); |
| 154 | size_t written = file->WriteBytes(buffer, length); | 168 | size_t written = file->WriteBytes(buffer, length); |
| @@ -198,7 +212,8 @@ u32 DiskDirectory::Read(const u32 count, Entry* entries) { | |||
| 198 | const std::string& filename = file.virtualName; | 212 | const std::string& filename = file.virtualName; |
| 199 | Entry& entry = entries[entries_read]; | 213 | Entry& entry = entries[entries_read]; |
| 200 | 214 | ||
| 201 | LOG_TRACE(Service_FS, "File %s: size=%llu dir=%d", filename.c_str(), file.size, file.isDirectory); | 215 | LOG_TRACE(Service_FS, "File %s: size=%llu dir=%d", filename.c_str(), file.size, |
| 216 | file.isDirectory); | ||
| 202 | 217 | ||
| 203 | // TODO(Link Mauve): use a proper conversion to UTF-16. | 218 | // TODO(Link Mauve): use a proper conversion to UTF-16. |
| 204 | for (size_t j = 0; j < FILENAME_LENGTH; ++j) { | 219 | for (size_t j = 0; j < FILENAME_LENGTH; ++j) { |
diff --git a/src/core/file_sys/disk_archive.h b/src/core/file_sys/disk_archive.h index b4cc2f702..3f620128f 100644 --- a/src/core/file_sys/disk_archive.h +++ b/src/core/file_sys/disk_archive.h | |||
| @@ -29,11 +29,15 @@ namespace FileSys { | |||
| 29 | */ | 29 | */ |
| 30 | class DiskArchive : public ArchiveBackend { | 30 | class DiskArchive : public ArchiveBackend { |
| 31 | public: | 31 | public: |
| 32 | DiskArchive(const std::string& mount_point_) : mount_point(mount_point_) {} | 32 | DiskArchive(const std::string& mount_point_) : mount_point(mount_point_) { |
| 33 | } | ||
| 33 | 34 | ||
| 34 | virtual std::string GetName() const override { return "DiskArchive: " + mount_point; } | 35 | virtual std::string GetName() const override { |
| 36 | return "DiskArchive: " + mount_point; | ||
| 37 | } | ||
| 35 | 38 | ||
| 36 | ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path, const Mode mode) const override; | 39 | ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path, |
| 40 | const Mode mode) const override; | ||
| 37 | ResultCode DeleteFile(const Path& path) const override; | 41 | ResultCode DeleteFile(const Path& path) const override; |
| 38 | bool RenameFile(const Path& src_path, const Path& dest_path) const override; | 42 | bool RenameFile(const Path& src_path, const Path& dest_path) const override; |
| 39 | bool DeleteDirectory(const Path& path) const override; | 43 | bool DeleteDirectory(const Path& path) const override; |
diff --git a/src/core/file_sys/file_backend.h b/src/core/file_sys/file_backend.h index 9137bbbad..9eae697c2 100644 --- a/src/core/file_sys/file_backend.h +++ b/src/core/file_sys/file_backend.h | |||
| @@ -16,8 +16,10 @@ namespace FileSys { | |||
| 16 | 16 | ||
| 17 | class FileBackend : NonCopyable { | 17 | class FileBackend : NonCopyable { |
| 18 | public: | 18 | public: |
| 19 | FileBackend() { } | 19 | FileBackend() { |
| 20 | virtual ~FileBackend() { } | 20 | } |
| 21 | virtual ~FileBackend() { | ||
| 22 | } | ||
| 21 | 23 | ||
| 22 | /** | 24 | /** |
| 23 | * Open the file | 25 | * Open the file |
| @@ -42,7 +44,8 @@ public: | |||
| 42 | * @param buffer Buffer to read data from | 44 | * @param buffer Buffer to read data from |
| 43 | * @return Number of bytes written, or error code | 45 | * @return Number of bytes written, or error code |
| 44 | */ | 46 | */ |
| 45 | virtual ResultVal<size_t> Write(u64 offset, size_t length, bool flush, const u8* buffer) const = 0; | 47 | virtual ResultVal<size_t> Write(u64 offset, size_t length, bool flush, |
| 48 | const u8* buffer) const = 0; | ||
| 46 | 49 | ||
| 47 | /** | 50 | /** |
| 48 | * Get the size of the file in bytes | 51 | * Get the size of the file in bytes |
diff --git a/src/core/file_sys/ivfc_archive.cpp b/src/core/file_sys/ivfc_archive.cpp index c61791ef7..235a962e9 100644 --- a/src/core/file_sys/ivfc_archive.cpp +++ b/src/core/file_sys/ivfc_archive.cpp | |||
| @@ -19,40 +19,49 @@ std::string IVFCArchive::GetName() const { | |||
| 19 | return "IVFC"; | 19 | return "IVFC"; |
| 20 | } | 20 | } |
| 21 | 21 | ||
| 22 | ResultVal<std::unique_ptr<FileBackend>> IVFCArchive::OpenFile(const Path& path, const Mode mode) const { | 22 | ResultVal<std::unique_ptr<FileBackend>> IVFCArchive::OpenFile(const Path& path, |
| 23 | return MakeResult<std::unique_ptr<FileBackend>>(std::make_unique<IVFCFile>(romfs_file, data_offset, data_size)); | 23 | const Mode mode) const { |
| 24 | return MakeResult<std::unique_ptr<FileBackend>>( | ||
| 25 | std::make_unique<IVFCFile>(romfs_file, data_offset, data_size)); | ||
| 24 | } | 26 | } |
| 25 | 27 | ||
| 26 | ResultCode IVFCArchive::DeleteFile(const Path& path) const { | 28 | ResultCode IVFCArchive::DeleteFile(const Path& path) const { |
| 27 | LOG_CRITICAL(Service_FS, "Attempted to delete a file from an IVFC archive (%s).", GetName().c_str()); | 29 | LOG_CRITICAL(Service_FS, "Attempted to delete a file from an IVFC archive (%s).", |
| 30 | GetName().c_str()); | ||
| 28 | // TODO(Subv): Verify error code | 31 | // TODO(Subv): Verify error code |
| 29 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, | 32 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, ErrorSummary::Canceled, |
| 30 | ErrorSummary::Canceled, ErrorLevel::Status); | 33 | ErrorLevel::Status); |
| 31 | } | 34 | } |
| 32 | 35 | ||
| 33 | bool IVFCArchive::RenameFile(const Path& src_path, const Path& dest_path) const { | 36 | bool IVFCArchive::RenameFile(const Path& src_path, const Path& dest_path) const { |
| 34 | LOG_CRITICAL(Service_FS, "Attempted to rename a file within an IVFC archive (%s).", GetName().c_str()); | 37 | LOG_CRITICAL(Service_FS, "Attempted to rename a file within an IVFC archive (%s).", |
| 38 | GetName().c_str()); | ||
| 35 | return false; | 39 | return false; |
| 36 | } | 40 | } |
| 37 | 41 | ||
| 38 | bool IVFCArchive::DeleteDirectory(const Path& path) const { | 42 | bool IVFCArchive::DeleteDirectory(const Path& path) const { |
| 39 | LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an IVFC archive (%s).", GetName().c_str()); | 43 | LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an IVFC archive (%s).", |
| 44 | GetName().c_str()); | ||
| 40 | return false; | 45 | return false; |
| 41 | } | 46 | } |
| 42 | 47 | ||
| 43 | ResultCode IVFCArchive::CreateFile(const Path& path, u64 size) const { | 48 | ResultCode IVFCArchive::CreateFile(const Path& path, u64 size) const { |
| 44 | LOG_CRITICAL(Service_FS, "Attempted to create a file in an IVFC archive (%s).", GetName().c_str()); | 49 | LOG_CRITICAL(Service_FS, "Attempted to create a file in an IVFC archive (%s).", |
| 50 | GetName().c_str()); | ||
| 45 | // TODO: Verify error code | 51 | // TODO: Verify error code |
| 46 | return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported, ErrorLevel::Permanent); | 52 | return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported, |
| 53 | ErrorLevel::Permanent); | ||
| 47 | } | 54 | } |
| 48 | 55 | ||
| 49 | bool IVFCArchive::CreateDirectory(const Path& path) const { | 56 | bool IVFCArchive::CreateDirectory(const Path& path) const { |
| 50 | LOG_CRITICAL(Service_FS, "Attempted to create a directory in an IVFC archive (%s).", GetName().c_str()); | 57 | LOG_CRITICAL(Service_FS, "Attempted to create a directory in an IVFC archive (%s).", |
| 58 | GetName().c_str()); | ||
| 51 | return false; | 59 | return false; |
| 52 | } | 60 | } |
| 53 | 61 | ||
| 54 | bool IVFCArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const { | 62 | bool IVFCArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const { |
| 55 | LOG_CRITICAL(Service_FS, "Attempted to rename a file within an IVFC archive (%s).", GetName().c_str()); | 63 | LOG_CRITICAL(Service_FS, "Attempted to rename a file within an IVFC archive (%s).", |
| 64 | GetName().c_str()); | ||
| 56 | return false; | 65 | return false; |
| 57 | } | 66 | } |
| 58 | 67 | ||
| @@ -75,7 +84,8 @@ ResultVal<size_t> IVFCFile::Read(const u64 offset, const size_t length, u8* buff | |||
| 75 | return MakeResult<size_t>(romfs_file->ReadBytes(buffer, read_length)); | 84 | return MakeResult<size_t>(romfs_file->ReadBytes(buffer, read_length)); |
| 76 | } | 85 | } |
| 77 | 86 | ||
| 78 | ResultVal<size_t> IVFCFile::Write(const u64 offset, const size_t length, const bool flush, const u8* buffer) const { | 87 | ResultVal<size_t> IVFCFile::Write(const u64 offset, const size_t length, const bool flush, |
| 88 | const u8* buffer) const { | ||
| 79 | LOG_ERROR(Service_FS, "Attempted to write to IVFC file"); | 89 | LOG_ERROR(Service_FS, "Attempted to write to IVFC file"); |
| 80 | // TODO(Subv): Find error code | 90 | // TODO(Subv): Find error code |
| 81 | return MakeResult<size_t>(0); | 91 | return MakeResult<size_t>(0); |
diff --git a/src/core/file_sys/ivfc_archive.h b/src/core/file_sys/ivfc_archive.h index 19d32dcca..dab1958f6 100644 --- a/src/core/file_sys/ivfc_archive.h +++ b/src/core/file_sys/ivfc_archive.h | |||
| @@ -30,11 +30,13 @@ namespace FileSys { | |||
| 30 | class IVFCArchive : public ArchiveBackend { | 30 | class IVFCArchive : public ArchiveBackend { |
| 31 | public: | 31 | public: |
| 32 | IVFCArchive(std::shared_ptr<FileUtil::IOFile> file, u64 offset, u64 size) | 32 | IVFCArchive(std::shared_ptr<FileUtil::IOFile> file, u64 offset, u64 size) |
| 33 | : romfs_file(file), data_offset(offset), data_size(size) {} | 33 | : romfs_file(file), data_offset(offset), data_size(size) { |
| 34 | } | ||
| 34 | 35 | ||
| 35 | std::string GetName() const override; | 36 | std::string GetName() const override; |
| 36 | 37 | ||
| 37 | ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path, const Mode mode) const override; | 38 | ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path, |
| 39 | const Mode mode) const override; | ||
| 38 | ResultCode DeleteFile(const Path& path) const override; | 40 | ResultCode DeleteFile(const Path& path) const override; |
| 39 | bool RenameFile(const Path& src_path, const Path& dest_path) const override; | 41 | bool RenameFile(const Path& src_path, const Path& dest_path) const override; |
| 40 | bool DeleteDirectory(const Path& path) const override; | 42 | bool DeleteDirectory(const Path& path) const override; |
| @@ -53,15 +55,21 @@ protected: | |||
| 53 | class IVFCFile : public FileBackend { | 55 | class IVFCFile : public FileBackend { |
| 54 | public: | 56 | public: |
| 55 | IVFCFile(std::shared_ptr<FileUtil::IOFile> file, u64 offset, u64 size) | 57 | IVFCFile(std::shared_ptr<FileUtil::IOFile> file, u64 offset, u64 size) |
| 56 | : romfs_file(file), data_offset(offset), data_size(size) {} | 58 | : romfs_file(file), data_offset(offset), data_size(size) { |
| 59 | } | ||
| 57 | 60 | ||
| 58 | ResultCode Open() override { return RESULT_SUCCESS; } | 61 | ResultCode Open() override { |
| 62 | return RESULT_SUCCESS; | ||
| 63 | } | ||
| 59 | ResultVal<size_t> Read(u64 offset, size_t length, u8* buffer) const override; | 64 | ResultVal<size_t> Read(u64 offset, size_t length, u8* buffer) const override; |
| 60 | ResultVal<size_t> Write(u64 offset, size_t length, bool flush, const u8* buffer) const override; | 65 | ResultVal<size_t> Write(u64 offset, size_t length, bool flush, const u8* buffer) const override; |
| 61 | u64 GetSize() const override; | 66 | u64 GetSize() const override; |
| 62 | bool SetSize(u64 size) const override; | 67 | bool SetSize(u64 size) const override; |
| 63 | bool Close() const override { return false; } | 68 | bool Close() const override { |
| 64 | void Flush() const override { } | 69 | return false; |
| 70 | } | ||
| 71 | void Flush() const override { | ||
| 72 | } | ||
| 65 | 73 | ||
| 66 | private: | 74 | private: |
| 67 | std::shared_ptr<FileUtil::IOFile> romfs_file; | 75 | std::shared_ptr<FileUtil::IOFile> romfs_file; |
| @@ -71,9 +79,15 @@ private: | |||
| 71 | 79 | ||
| 72 | class IVFCDirectory : public DirectoryBackend { | 80 | class IVFCDirectory : public DirectoryBackend { |
| 73 | public: | 81 | public: |
| 74 | bool Open() override { return false; } | 82 | bool Open() override { |
| 75 | u32 Read(const u32 count, Entry* entries) override { return 0; } | 83 | return false; |
| 76 | bool Close() const override { return false; } | 84 | } |
| 85 | u32 Read(const u32 count, Entry* entries) override { | ||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | bool Close() const override { | ||
| 89 | return false; | ||
| 90 | } | ||
| 77 | }; | 91 | }; |
| 78 | 92 | ||
| 79 | } // namespace FileSys | 93 | } // namespace FileSys |
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 28d403158..6d709bd15 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp | |||
| @@ -16,25 +16,25 @@ | |||
| 16 | 16 | ||
| 17 | #ifdef _MSC_VER | 17 | #ifdef _MSC_VER |
| 18 | #include <WinSock2.h> | 18 | #include <WinSock2.h> |
| 19 | #include <ws2tcpip.h> | ||
| 20 | #include <common/x64/abi.h> | 19 | #include <common/x64/abi.h> |
| 21 | #include <io.h> | 20 | #include <io.h> |
| 22 | #include <iphlpapi.h> | 21 | #include <iphlpapi.h> |
| 22 | #include <ws2tcpip.h> | ||
| 23 | #define SHUT_RDWR 2 | 23 | #define SHUT_RDWR 2 |
| 24 | #else | 24 | #else |
| 25 | #include <unistd.h> | 25 | #include <netinet/in.h> |
| 26 | #include <sys/select.h> | 26 | #include <sys/select.h> |
| 27 | #include <sys/socket.h> | 27 | #include <sys/socket.h> |
| 28 | #include <sys/un.h> | 28 | #include <sys/un.h> |
| 29 | #include <netinet/in.h> | 29 | #include <unistd.h> |
| 30 | #endif | 30 | #endif |
| 31 | 31 | ||
| 32 | #include "common/logging/log.h" | 32 | #include "common/logging/log.h" |
| 33 | #include "common/string_util.h" | 33 | #include "common/string_util.h" |
| 34 | #include "core/core.h" | ||
| 35 | #include "core/memory.h" | ||
| 36 | #include "core/arm/arm_interface.h" | 34 | #include "core/arm/arm_interface.h" |
| 35 | #include "core/core.h" | ||
| 37 | #include "core/gdbstub/gdbstub.h" | 36 | #include "core/gdbstub/gdbstub.h" |
| 37 | #include "core/memory.h" | ||
| 38 | 38 | ||
| 39 | const int GDB_BUFFER_SIZE = 10000; | 39 | const int GDB_BUFFER_SIZE = 10000; |
| 40 | 40 | ||
| @@ -64,7 +64,7 @@ const u32 FPSCR_REGISTER = 58; | |||
| 64 | // GDB also wants the l character at the start | 64 | // GDB also wants the l character at the start |
| 65 | // This XML defines what the registers are for this specific ARM device | 65 | // This XML defines what the registers are for this specific ARM device |
| 66 | static const char* target_xml = | 66 | static const char* target_xml = |
| 67 | R"(l<?xml version="1.0"?> | 67 | R"(l<?xml version="1.0"?> |
| 68 | <!DOCTYPE target SYSTEM "gdb-target.dtd"> | 68 | <!DOCTYPE target SYSTEM "gdb-target.dtd"> |
| 69 | <target version="1.0"> | 69 | <target version="1.0"> |
| 70 | <feature name="org.gnu.gdb.arm.core"> | 70 | <feature name="org.gnu.gdb.arm.core"> |
| @@ -297,7 +297,8 @@ static void RemoveBreakpoint(BreakpointType type, PAddr addr) { | |||
| 297 | 297 | ||
| 298 | auto bp = p.find(addr); | 298 | auto bp = p.find(addr); |
| 299 | if (bp != p.end()) { | 299 | if (bp != p.end()) { |
| 300 | LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: %08x bytes at %08x of type %d\n", bp->second.len, bp->second.addr, type); | 300 | LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: %08x bytes at %08x of type %d\n", |
| 301 | bp->second.len, bp->second.addr, type); | ||
| 301 | p.erase(addr); | 302 | p.erase(addr); |
| 302 | } | 303 | } |
| 303 | } | 304 | } |
| @@ -342,7 +343,9 @@ bool CheckBreakpoint(PAddr addr, BreakpointType type) { | |||
| 342 | } | 343 | } |
| 343 | 344 | ||
| 344 | if (bp->second.active && (addr >= bp->second.addr && addr < bp->second.addr + len)) { | 345 | if (bp->second.active && (addr >= bp->second.addr && addr < bp->second.addr + len)) { |
| 345 | LOG_DEBUG(Debug_GDBStub, "Found breakpoint type %d @ %08x, range: %08x - %08x (%d bytes)\n", type, addr, bp->second.addr, bp->second.addr + len, len); | 346 | LOG_DEBUG(Debug_GDBStub, |
| 347 | "Found breakpoint type %d @ %08x, range: %08x - %08x (%d bytes)\n", type, | ||
| 348 | addr, bp->second.addr, bp->second.addr + len, len); | ||
| 346 | return true; | 349 | return true; |
| 347 | } | 350 | } |
| 348 | } | 351 | } |
| @@ -408,12 +411,13 @@ static void HandleQuery() { | |||
| 408 | 411 | ||
| 409 | const char* query = reinterpret_cast<const char*>(command_buffer + 1); | 412 | const char* query = reinterpret_cast<const char*>(command_buffer + 1); |
| 410 | 413 | ||
| 411 | if (strcmp(query, "TStatus") == 0 ) { | 414 | if (strcmp(query, "TStatus") == 0) { |
| 412 | SendReply("T0"); | 415 | SendReply("T0"); |
| 413 | } else if (strncmp(query, "Supported:", strlen("Supported:")) == 0) { | 416 | } else if (strncmp(query, "Supported:", strlen("Supported:")) == 0) { |
| 414 | // PacketSize needs to be large enough for target xml | 417 | // PacketSize needs to be large enough for target xml |
| 415 | SendReply("PacketSize=800;qXfer:features:read+"); | 418 | SendReply("PacketSize=800;qXfer:features:read+"); |
| 416 | } else if (strncmp(query, "Xfer:features:read:target.xml:", strlen("Xfer:features:read:target.xml:")) == 0) { | 419 | } else if (strncmp(query, "Xfer:features:read:target.xml:", |
| 420 | strlen("Xfer:features:read:target.xml:")) == 0) { | ||
| 417 | SendReply(target_xml); | 421 | SendReply(target_xml); |
| 418 | } else { | 422 | } else { |
| 419 | SendReply(""); | 423 | SendReply(""); |
| @@ -422,10 +426,8 @@ static void HandleQuery() { | |||
| 422 | 426 | ||
| 423 | /// Handle set thread command from gdb client. | 427 | /// Handle set thread command from gdb client. |
| 424 | static void HandleSetThread() { | 428 | static void HandleSetThread() { |
| 425 | if (memcmp(command_buffer, "Hg0", 3) == 0 || | 429 | if (memcmp(command_buffer, "Hg0", 3) == 0 || memcmp(command_buffer, "Hc-1", 4) == 0 || |
| 426 | memcmp(command_buffer, "Hc-1", 4) == 0 || | 430 | memcmp(command_buffer, "Hc0", 4) == 0 || memcmp(command_buffer, "Hc1", 4) == 0) { |
| 427 | memcmp(command_buffer, "Hc0", 4) == 0 || | ||
| 428 | memcmp(command_buffer, "Hc1", 4) == 0) { | ||
| 429 | return SendReply("OK"); | 431 | return SendReply("OK"); |
| 430 | } | 432 | } |
| 431 | 433 | ||
| @@ -444,7 +446,9 @@ static void SendSignal(u32 signal) { | |||
| 444 | 446 | ||
| 445 | latest_signal = signal; | 447 | latest_signal = signal; |
| 446 | 448 | ||
| 447 | std::string buffer = Common::StringFromFormat("T%02x%02x:%08x;%02x:%08x;", latest_signal, 15, htonl(Core::g_app_core->GetPC()), 13, htonl(Core::g_app_core->GetReg(13))); | 449 | std::string buffer = Common::StringFromFormat("T%02x%02x:%08x;%02x:%08x;", latest_signal, 15, |
| 450 | htonl(Core::g_app_core->GetPC()), 13, | ||
| 451 | htonl(Core::g_app_core->GetReg(13))); | ||
| 448 | LOG_DEBUG(Debug_GDBStub, "Response: %s", buffer.c_str()); | 452 | LOG_DEBUG(Debug_GDBStub, "Response: %s", buffer.c_str()); |
| 449 | SendReply(buffer.c_str()); | 453 | SendReply(buffer.c_str()); |
| 450 | } | 454 | } |
| @@ -456,7 +460,7 @@ static void ReadCommand() { | |||
| 456 | 460 | ||
| 457 | u8 c = ReadByte(); | 461 | u8 c = ReadByte(); |
| 458 | if (c == '+') { | 462 | if (c == '+') { |
| 459 | //ignore ack | 463 | // ignore ack |
| 460 | return; | 464 | return; |
| 461 | } else if (c == 0x03) { | 465 | } else if (c == 0x03) { |
| 462 | LOG_INFO(Debug_GDBStub, "gdb: found break command\n"); | 466 | LOG_INFO(Debug_GDBStub, "gdb: found break command\n"); |
| @@ -483,8 +487,9 @@ static void ReadCommand() { | |||
| 483 | u8 checksum_calculated = CalculateChecksum(command_buffer, command_length); | 487 | u8 checksum_calculated = CalculateChecksum(command_buffer, command_length); |
| 484 | 488 | ||
| 485 | if (checksum_received != checksum_calculated) { | 489 | if (checksum_received != checksum_calculated) { |
| 486 | LOG_ERROR(Debug_GDBStub, "gdb: invalid checksum: calculated %02x and read %02x for $%s# (length: %d)\n", | 490 | LOG_ERROR(Debug_GDBStub, |
| 487 | checksum_calculated, checksum_received, command_buffer, command_length); | 491 | "gdb: invalid checksum: calculated %02x and read %02x for $%s# (length: %d)\n", |
| 492 | checksum_calculated, checksum_received, command_buffer, command_length); | ||
| 488 | 493 | ||
| 489 | command_length = 0; | 494 | command_length = 0; |
| 490 | 495 | ||
| @@ -534,7 +539,9 @@ static void ReadRegister() { | |||
| 534 | } else if (id == CPSR_REGISTER) { | 539 | } else if (id == CPSR_REGISTER) { |
| 535 | IntToGdbHex(reply, Core::g_app_core->GetCPSR()); | 540 | IntToGdbHex(reply, Core::g_app_core->GetCPSR()); |
| 536 | } else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) { | 541 | } else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) { |
| 537 | IntToGdbHex(reply, Core::g_app_core->GetVFPReg(id - CPSR_REGISTER - 1)); // VFP registers should start at 26, so one after CSPR_REGISTER | 542 | IntToGdbHex(reply, Core::g_app_core->GetVFPReg( |
| 543 | id - CPSR_REGISTER - | ||
| 544 | 1)); // VFP registers should start at 26, so one after CSPR_REGISTER | ||
| 538 | } else if (id == FPSCR_REGISTER) { | 545 | } else if (id == FPSCR_REGISTER) { |
| 539 | IntToGdbHex(reply, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR)); // Get FPSCR | 546 | IntToGdbHex(reply, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR)); // Get FPSCR |
| 540 | IntToGdbHex(reply + 8, 0); | 547 | IntToGdbHex(reply + 8, 0); |
| @@ -617,7 +624,8 @@ static void WriteRegisters() { | |||
| 617 | // Dummy FPA registers, ignore | 624 | // Dummy FPA registers, ignore |
| 618 | i += 2; | 625 | i += 2; |
| 619 | } else if (reg > CPSR_REGISTER && reg < FPSCR_REGISTER) { | 626 | } else if (reg > CPSR_REGISTER && reg < FPSCR_REGISTER) { |
| 620 | Core::g_app_core->SetVFPReg(reg - CPSR_REGISTER - 1, GdbHexToInt(buffer_ptr + i * CHAR_BIT)); | 627 | Core::g_app_core->SetVFPReg(reg - CPSR_REGISTER - 1, |
| 628 | GdbHexToInt(buffer_ptr + i * CHAR_BIT)); | ||
| 621 | i++; // Skip padding | 629 | i++; // Skip padding |
| 622 | } else if (reg == FPSCR_REGISTER) { | 630 | } else if (reg == FPSCR_REGISTER) { |
| 623 | Core::g_app_core->SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr + i * CHAR_BIT)); | 631 | Core::g_app_core->SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr + i * CHAR_BIT)); |
| @@ -631,12 +639,13 @@ static void WriteRegisters() { | |||
| 631 | static void ReadMemory() { | 639 | static void ReadMemory() { |
| 632 | static u8 reply[GDB_BUFFER_SIZE - 4]; | 640 | static u8 reply[GDB_BUFFER_SIZE - 4]; |
| 633 | 641 | ||
| 634 | auto start_offset = command_buffer+1; | 642 | auto start_offset = command_buffer + 1; |
| 635 | auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); | 643 | auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); |
| 636 | PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); | 644 | PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); |
| 637 | 645 | ||
| 638 | start_offset = addr_pos+1; | 646 | start_offset = addr_pos + 1; |
| 639 | u32 len = HexToInt(start_offset, static_cast<u32>((command_buffer + command_length) - start_offset)); | 647 | u32 len = |
| 648 | HexToInt(start_offset, static_cast<u32>((command_buffer + command_length) - start_offset)); | ||
| 640 | 649 | ||
| 641 | LOG_DEBUG(Debug_GDBStub, "gdb: addr: %08x len: %08x\n", addr, len); | 650 | LOG_DEBUG(Debug_GDBStub, "gdb: addr: %08x len: %08x\n", addr, len); |
| 642 | 651 | ||
| @@ -656,12 +665,12 @@ static void ReadMemory() { | |||
| 656 | 665 | ||
| 657 | /// Modify location in memory with data received from the gdb client. | 666 | /// Modify location in memory with data received from the gdb client. |
| 658 | static void WriteMemory() { | 667 | static void WriteMemory() { |
| 659 | auto start_offset = command_buffer+1; | 668 | auto start_offset = command_buffer + 1; |
| 660 | auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); | 669 | auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); |
| 661 | PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); | 670 | PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); |
| 662 | 671 | ||
| 663 | start_offset = addr_pos+1; | 672 | start_offset = addr_pos + 1; |
| 664 | auto len_pos = std::find(start_offset, command_buffer+command_length, ':'); | 673 | auto len_pos = std::find(start_offset, command_buffer + command_length, ':'); |
| 665 | u32 len = HexToInt(start_offset, static_cast<u32>(len_pos - start_offset)); | 674 | u32 len = HexToInt(start_offset, static_cast<u32>(len_pos - start_offset)); |
| 666 | 675 | ||
| 667 | u8* dst = Memory::GetPointer(addr); | 676 | u8* dst = Memory::GetPointer(addr); |
| @@ -720,9 +729,10 @@ static bool CommitBreakpoint(BreakpointType type, PAddr addr, u32 len) { | |||
| 720 | breakpoint.active = true; | 729 | breakpoint.active = true; |
| 721 | breakpoint.addr = addr; | 730 | breakpoint.addr = addr; |
| 722 | breakpoint.len = len; | 731 | breakpoint.len = len; |
| 723 | p.insert({ addr, breakpoint }); | 732 | p.insert({addr, breakpoint}); |
| 724 | 733 | ||
| 725 | LOG_DEBUG(Debug_GDBStub, "gdb: added %d breakpoint: %08x bytes at %08x\n", type, breakpoint.len, breakpoint.addr); | 734 | LOG_DEBUG(Debug_GDBStub, "gdb: added %d breakpoint: %08x bytes at %08x\n", type, breakpoint.len, |
| 735 | breakpoint.addr); | ||
| 726 | 736 | ||
| 727 | return true; | 737 | return true; |
| 728 | } | 738 | } |
| @@ -750,12 +760,13 @@ static void AddBreakpoint() { | |||
| 750 | return SendReply("E01"); | 760 | return SendReply("E01"); |
| 751 | } | 761 | } |
| 752 | 762 | ||
| 753 | auto start_offset = command_buffer+3; | 763 | auto start_offset = command_buffer + 3; |
| 754 | auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); | 764 | auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); |
| 755 | PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); | 765 | PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); |
| 756 | 766 | ||
| 757 | start_offset = addr_pos+1; | 767 | start_offset = addr_pos + 1; |
| 758 | u32 len = HexToInt(start_offset, static_cast<u32>((command_buffer + command_length) - start_offset)); | 768 | u32 len = |
| 769 | HexToInt(start_offset, static_cast<u32>((command_buffer + command_length) - start_offset)); | ||
| 759 | 770 | ||
| 760 | if (type == BreakpointType::Access) { | 771 | if (type == BreakpointType::Access) { |
| 761 | // Access is made up of Read and Write types, so add both breakpoints | 772 | // Access is made up of Read and Write types, so add both breakpoints |
| @@ -798,12 +809,13 @@ static void RemoveBreakpoint() { | |||
| 798 | return SendReply("E01"); | 809 | return SendReply("E01"); |
| 799 | } | 810 | } |
| 800 | 811 | ||
| 801 | auto start_offset = command_buffer+3; | 812 | auto start_offset = command_buffer + 3; |
| 802 | auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); | 813 | auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); |
| 803 | PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); | 814 | PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); |
| 804 | 815 | ||
| 805 | start_offset = addr_pos+1; | 816 | start_offset = addr_pos + 1; |
| 806 | u32 len = HexToInt(start_offset, static_cast<u32>((command_buffer + command_length) - start_offset)); | 817 | u32 len = |
| 818 | HexToInt(start_offset, static_cast<u32>((command_buffer + command_length) - start_offset)); | ||
| 807 | 819 | ||
| 808 | if (type == BreakpointType::Access) { | 820 | if (type == BreakpointType::Access) { |
| 809 | // Access is made up of Read and Write types, so add both breakpoints | 821 | // Access is made up of Read and Write types, so add both breakpoints |
| @@ -896,8 +908,7 @@ void ToggleServer(bool status) { | |||
| 896 | if (!IsConnected() && Core::g_sys_core != nullptr) { | 908 | if (!IsConnected() && Core::g_sys_core != nullptr) { |
| 897 | Init(); | 909 | Init(); |
| 898 | } | 910 | } |
| 899 | } | 911 | } else { |
| 900 | else { | ||
| 901 | // Stop server | 912 | // Stop server |
| 902 | if (IsConnected()) { | 913 | if (IsConnected()) { |
| 903 | Shutdown(); | 914 | Shutdown(); |
| @@ -943,7 +954,8 @@ static void Init(u16 port) { | |||
| 943 | 954 | ||
| 944 | // Set socket to SO_REUSEADDR so it can always bind on the same port | 955 | // Set socket to SO_REUSEADDR so it can always bind on the same port |
| 945 | int reuse_enabled = 1; | 956 | int reuse_enabled = 1; |
| 946 | if (setsockopt(tmpsock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse_enabled, sizeof(reuse_enabled)) < 0) { | 957 | if (setsockopt(tmpsock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse_enabled, |
| 958 | sizeof(reuse_enabled)) < 0) { | ||
| 947 | LOG_ERROR(Debug_GDBStub, "Failed to set gdb socket option"); | 959 | LOG_ERROR(Debug_GDBStub, "Failed to set gdb socket option"); |
| 948 | } | 960 | } |
| 949 | 961 | ||
| @@ -964,13 +976,13 @@ static void Init(u16 port) { | |||
| 964 | socklen_t client_addrlen = sizeof(saddr_client); | 976 | socklen_t client_addrlen = sizeof(saddr_client); |
| 965 | gdbserver_socket = accept(tmpsock, client_addr, &client_addrlen); | 977 | gdbserver_socket = accept(tmpsock, client_addr, &client_addrlen); |
| 966 | if (gdbserver_socket < 0) { | 978 | if (gdbserver_socket < 0) { |
| 967 | // In the case that we couldn't start the server for whatever reason, just start CPU execution like normal. | 979 | // In the case that we couldn't start the server for whatever reason, just start CPU |
| 980 | // execution like normal. | ||
| 968 | halt_loop = false; | 981 | halt_loop = false; |
| 969 | step_loop = false; | 982 | step_loop = false; |
| 970 | 983 | ||
| 971 | LOG_ERROR(Debug_GDBStub, "Failed to accept gdb client"); | 984 | LOG_ERROR(Debug_GDBStub, "Failed to accept gdb client"); |
| 972 | } | 985 | } else { |
| 973 | else { | ||
| 974 | LOG_INFO(Debug_GDBStub, "Client connected.\n"); | 986 | LOG_INFO(Debug_GDBStub, "Client connected.\n"); |
| 975 | saddr_client.sin_addr.s_addr = ntohl(saddr_client.sin_addr.s_addr); | 987 | saddr_client.sin_addr.s_addr = ntohl(saddr_client.sin_addr.s_addr); |
| 976 | } | 988 | } |
| @@ -1018,5 +1030,4 @@ bool GetCpuStepFlag() { | |||
| 1018 | void SetCpuStepFlag(bool is_step) { | 1030 | void SetCpuStepFlag(bool is_step) { |
| 1019 | step_loop = is_step; | 1031 | step_loop = is_step; |
| 1020 | } | 1032 | } |
| 1021 | |||
| 1022 | }; | 1033 | }; |
diff --git a/src/core/gdbstub/gdbstub.h b/src/core/gdbstub/gdbstub.h index 4f21da23b..fddc27a3e 100644 --- a/src/core/gdbstub/gdbstub.h +++ b/src/core/gdbstub/gdbstub.h | |||
| @@ -13,11 +13,11 @@ namespace GDBStub { | |||
| 13 | 13 | ||
| 14 | /// Breakpoint Method | 14 | /// Breakpoint Method |
| 15 | enum class BreakpointType { | 15 | enum class BreakpointType { |
| 16 | None, ///< None | 16 | None, ///< None |
| 17 | Execute, ///< Execution Breakpoint | 17 | Execute, ///< Execution Breakpoint |
| 18 | Read, ///< Read Breakpoint | 18 | Read, ///< Read Breakpoint |
| 19 | Write, ///< Write Breakpoint | 19 | Write, ///< Write Breakpoint |
| 20 | Access ///< Access (R/W) Breakpoint | 20 | Access ///< Access (R/W) Breakpoint |
| 21 | }; | 21 | }; |
| 22 | 22 | ||
| 23 | struct BreakpointAddress { | 23 | struct BreakpointAddress { |
| @@ -25,7 +25,8 @@ struct BreakpointAddress { | |||
| 25 | BreakpointType type; | 25 | BreakpointType type; |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | /// If set to false, the server will never be started and no gdbstub-related functions will be executed. | 28 | /// If set to false, the server will never be started and no gdbstub-related functions will be |
| 29 | /// executed. | ||
| 29 | extern std::atomic<bool> g_server_enabled; | 30 | extern std::atomic<bool> g_server_enabled; |
| 30 | 31 | ||
| 31 | /** | 32 | /** |
| @@ -92,5 +93,4 @@ bool GetCpuStepFlag(); | |||
| 92 | * @param is_step | 93 | * @param is_step |
| 93 | */ | 94 | */ |
| 94 | void SetCpuStepFlag(bool is_step); | 95 | void SetCpuStepFlag(bool is_step); |
| 95 | |||
| 96 | } | 96 | } |
diff --git a/src/core/hle/applets/applet.cpp b/src/core/hle/applets/applet.cpp index ccf35fa07..2b4bd939d 100644 --- a/src/core/hle/applets/applet.cpp +++ b/src/core/hle/applets/applet.cpp | |||
| @@ -23,23 +23,24 @@ | |||
| 23 | // Specializes std::hash for AppletId, so that we can use it in std::unordered_map. | 23 | // Specializes std::hash for AppletId, so that we can use it in std::unordered_map. |
| 24 | // Workaround for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970 | 24 | // Workaround for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970 |
| 25 | namespace std { | 25 | namespace std { |
| 26 | template <> | 26 | template <> |
| 27 | struct hash<Service::APT::AppletId> { | 27 | struct hash<Service::APT::AppletId> { |
| 28 | typedef Service::APT::AppletId argument_type; | 28 | typedef Service::APT::AppletId argument_type; |
| 29 | typedef std::size_t result_type; | 29 | typedef std::size_t result_type; |
| 30 | 30 | ||
| 31 | result_type operator()(const argument_type& id_code) const { | 31 | result_type operator()(const argument_type& id_code) const { |
| 32 | typedef std::underlying_type<argument_type>::type Type; | 32 | typedef std::underlying_type<argument_type>::type Type; |
| 33 | return std::hash<Type>()(static_cast<Type>(id_code)); | 33 | return std::hash<Type>()(static_cast<Type>(id_code)); |
| 34 | } | 34 | } |
| 35 | }; | 35 | }; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | namespace HLE { | 38 | namespace HLE { |
| 39 | namespace Applets { | 39 | namespace Applets { |
| 40 | 40 | ||
| 41 | static std::unordered_map<Service::APT::AppletId, std::shared_ptr<Applet>> applets; | 41 | static std::unordered_map<Service::APT::AppletId, std::shared_ptr<Applet>> applets; |
| 42 | static u32 applet_update_event = -1; ///< The CoreTiming event identifier for the Applet update callback. | 42 | static u32 applet_update_event = |
| 43 | -1; ///< The CoreTiming event identifier for the Applet update callback. | ||
| 43 | /// The interval at which the Applet update callback will be called, 16.6ms | 44 | /// The interval at which the Applet update callback will be called, 16.6ms |
| 44 | static const u64 applet_update_interval_us = 16666; | 45 | static const u64 applet_update_interval_us = 16666; |
| 45 | 46 | ||
| @@ -60,7 +61,8 @@ ResultCode Applet::Create(Service::APT::AppletId id) { | |||
| 60 | default: | 61 | default: |
| 61 | LOG_ERROR(Service_APT, "Could not create applet %u", id); | 62 | LOG_ERROR(Service_APT, "Could not create applet %u", id); |
| 62 | // TODO(Subv): Find the right error code | 63 | // TODO(Subv): Find the right error code |
| 63 | return ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotSupported, ErrorLevel::Permanent); | 64 | return ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, |
| 65 | ErrorSummary::NotSupported, ErrorLevel::Permanent); | ||
| 64 | } | 66 | } |
| 65 | 67 | ||
| 66 | return RESULT_SUCCESS; | 68 | return RESULT_SUCCESS; |
| @@ -84,7 +86,7 @@ static void AppletUpdateEvent(u64 applet_id, int cycles_late) { | |||
| 84 | // If the applet is still running after the last update, reschedule the event | 86 | // If the applet is still running after the last update, reschedule the event |
| 85 | if (applet->IsRunning()) { | 87 | if (applet->IsRunning()) { |
| 86 | CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us) - cycles_late, | 88 | CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us) - cycles_late, |
| 87 | applet_update_event, applet_id); | 89 | applet_update_event, applet_id); |
| 88 | } else { | 90 | } else { |
| 89 | // Otherwise the applet has terminated, in which case we should clean it up | 91 | // Otherwise the applet has terminated, in which case we should clean it up |
| 90 | applets[id] = nullptr; | 92 | applets[id] = nullptr; |
| @@ -96,7 +98,8 @@ ResultCode Applet::Start(const Service::APT::AppletStartupParameter& parameter) | |||
| 96 | if (result.IsError()) | 98 | if (result.IsError()) |
| 97 | return result; | 99 | return result; |
| 98 | // Schedule the update event | 100 | // Schedule the update event |
| 99 | CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us), applet_update_event, static_cast<u64>(id)); | 101 | CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us), applet_update_event, |
| 102 | static_cast<u64>(id)); | ||
| 100 | return result; | 103 | return result; |
| 101 | } | 104 | } |
| 102 | 105 | ||
| @@ -116,6 +119,5 @@ void Init() { | |||
| 116 | void Shutdown() { | 119 | void Shutdown() { |
| 117 | CoreTiming::RemoveEvent(applet_update_event); | 120 | CoreTiming::RemoveEvent(applet_update_event); |
| 118 | } | 121 | } |
| 119 | |||
| 120 | } | 122 | } |
| 121 | } // namespace | 123 | } // namespace |
diff --git a/src/core/hle/applets/applet.h b/src/core/hle/applets/applet.h index 754c6f7db..350a58594 100644 --- a/src/core/hle/applets/applet.h +++ b/src/core/hle/applets/applet.h | |||
| @@ -14,8 +14,10 @@ namespace Applets { | |||
| 14 | 14 | ||
| 15 | class Applet { | 15 | class Applet { |
| 16 | public: | 16 | public: |
| 17 | virtual ~Applet() { } | 17 | virtual ~Applet() { |
| 18 | Applet(Service::APT::AppletId id) : id(id) { } | 18 | } |
| 19 | Applet(Service::APT::AppletId id) : id(id) { | ||
| 20 | } | ||
| 19 | 21 | ||
| 20 | /** | 22 | /** |
| 21 | * Creates an instance of the Applet subclass identified by the parameter. | 23 | * Creates an instance of the Applet subclass identified by the parameter. |
| @@ -64,7 +66,7 @@ protected: | |||
| 64 | */ | 66 | */ |
| 65 | virtual ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) = 0; | 67 | virtual ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) = 0; |
| 66 | 68 | ||
| 67 | Service::APT::AppletId id; ///< Id of this Applet | 69 | Service::APT::AppletId id; ///< Id of this Applet |
| 68 | std::shared_ptr<std::vector<u8>> heap_memory; ///< Heap memory for this Applet | 70 | std::shared_ptr<std::vector<u8>> heap_memory; ///< Heap memory for this Applet |
| 69 | }; | 71 | }; |
| 70 | 72 | ||
| @@ -76,6 +78,5 @@ void Init(); | |||
| 76 | 78 | ||
| 77 | /// Shuts down the HLE applets | 79 | /// Shuts down the HLE applets |
| 78 | void Shutdown(); | 80 | void Shutdown(); |
| 79 | |||
| 80 | } | 81 | } |
| 81 | } // namespace | 82 | } // namespace |
diff --git a/src/core/hle/applets/erreula.cpp b/src/core/hle/applets/erreula.cpp index 92a4b2323..144d6a152 100644 --- a/src/core/hle/applets/erreula.cpp +++ b/src/core/hle/applets/erreula.cpp | |||
| @@ -18,7 +18,8 @@ ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& param | |||
| 18 | return ResultCode(-1); | 18 | return ResultCode(-1); |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory. | 21 | // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared |
| 22 | // memory. | ||
| 22 | // Create the SharedMemory that will hold the framebuffer data | 23 | // Create the SharedMemory that will hold the framebuffer data |
| 23 | Service::APT::CaptureBufferInfo capture_info; | 24 | Service::APT::CaptureBufferInfo capture_info; |
| 24 | ASSERT(sizeof(capture_info) == parameter.buffer.size()); | 25 | ASSERT(sizeof(capture_info) == parameter.buffer.size()); |
| @@ -30,9 +31,9 @@ ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& param | |||
| 30 | // Allocate a heap block of the required size for this applet. | 31 | // Allocate a heap block of the required size for this applet. |
| 31 | heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); | 32 | heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); |
| 32 | // Create a SharedMemory that directly points to this heap block. | 33 | // Create a SharedMemory that directly points to this heap block. |
| 33 | framebuffer_memory = Kernel::SharedMemory::CreateForApplet(heap_memory, 0, heap_memory->size(), | 34 | framebuffer_memory = Kernel::SharedMemory::CreateForApplet( |
| 34 | MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, | 35 | heap_memory, 0, heap_memory->size(), MemoryPermission::ReadWrite, |
| 35 | "ErrEula Memory"); | 36 | MemoryPermission::ReadWrite, "ErrEula Memory"); |
| 36 | 37 | ||
| 37 | // Send the response message with the newly created SharedMemory | 38 | // Send the response message with the newly created SharedMemory |
| 38 | Service::APT::MessageParameter result; | 39 | Service::APT::MessageParameter result; |
| @@ -49,7 +50,8 @@ ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& param | |||
| 49 | ResultCode ErrEula::StartImpl(const Service::APT::AppletStartupParameter& parameter) { | 50 | ResultCode ErrEula::StartImpl(const Service::APT::AppletStartupParameter& parameter) { |
| 50 | started = true; | 51 | started = true; |
| 51 | 52 | ||
| 52 | // TODO(Subv): Set the expected fields in the response buffer before resending it to the application. | 53 | // TODO(Subv): Set the expected fields in the response buffer before resending it to the |
| 54 | // application. | ||
| 53 | // TODO(Subv): Reverse the parameter format for the ErrEula applet | 55 | // TODO(Subv): Reverse the parameter format for the ErrEula applet |
| 54 | 56 | ||
| 55 | // Let the application know that we're closing | 57 | // Let the application know that we're closing |
diff --git a/src/core/hle/applets/erreula.h b/src/core/hle/applets/erreula.h index 9fe72ae07..dd1d1aee4 100644 --- a/src/core/hle/applets/erreula.h +++ b/src/core/hle/applets/erreula.h | |||
| @@ -12,16 +12,21 @@ namespace Applets { | |||
| 12 | 12 | ||
| 13 | class ErrEula final : public Applet { | 13 | class ErrEula final : public Applet { |
| 14 | public: | 14 | public: |
| 15 | explicit ErrEula(Service::APT::AppletId id): Applet(id) { } | 15 | explicit ErrEula(Service::APT::AppletId id) : Applet(id) { |
| 16 | } | ||
| 16 | 17 | ||
| 17 | ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; | 18 | ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; |
| 18 | ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; | 19 | ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; |
| 19 | void Update() override; | 20 | void Update() override; |
| 20 | bool IsRunning() const override { return started; } | 21 | bool IsRunning() const override { |
| 22 | return started; | ||
| 23 | } | ||
| 21 | 24 | ||
| 22 | /// This SharedMemory will be created when we receive the LibAppJustStarted message. | 25 | /// This SharedMemory will be created when we receive the LibAppJustStarted message. |
| 23 | /// It holds the framebuffer info retrieved by the application with GSPGPU::ImportDisplayCaptureInfo | 26 | /// It holds the framebuffer info retrieved by the application with |
| 27 | /// GSPGPU::ImportDisplayCaptureInfo | ||
| 24 | Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; | 28 | Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; |
| 29 | |||
| 25 | private: | 30 | private: |
| 26 | /// Whether this applet is currently running instead of the host application or not. | 31 | /// Whether this applet is currently running instead of the host application or not. |
| 27 | bool started = false; | 32 | bool started = false; |
diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp index 77f01d208..19e603eda 100644 --- a/src/core/hle/applets/mii_selector.cpp +++ b/src/core/hle/applets/mii_selector.cpp | |||
| @@ -29,7 +29,8 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p | |||
| 29 | return ResultCode(-1); | 29 | return ResultCode(-1); |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory. | 32 | // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared |
| 33 | // memory. | ||
| 33 | // Create the SharedMemory that will hold the framebuffer data | 34 | // Create the SharedMemory that will hold the framebuffer data |
| 34 | Service::APT::CaptureBufferInfo capture_info; | 35 | Service::APT::CaptureBufferInfo capture_info; |
| 35 | ASSERT(sizeof(capture_info) == parameter.buffer.size()); | 36 | ASSERT(sizeof(capture_info) == parameter.buffer.size()); |
| @@ -40,9 +41,9 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p | |||
| 40 | // Allocate a heap block of the required size for this applet. | 41 | // Allocate a heap block of the required size for this applet. |
| 41 | heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); | 42 | heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); |
| 42 | // Create a SharedMemory that directly points to this heap block. | 43 | // Create a SharedMemory that directly points to this heap block. |
| 43 | framebuffer_memory = Kernel::SharedMemory::CreateForApplet(heap_memory, 0, heap_memory->size(), | 44 | framebuffer_memory = Kernel::SharedMemory::CreateForApplet( |
| 44 | MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, | 45 | heap_memory, 0, heap_memory->size(), MemoryPermission::ReadWrite, |
| 45 | "MiiSelector Memory"); | 46 | MemoryPermission::ReadWrite, "MiiSelector Memory"); |
| 46 | 47 | ||
| 47 | // Send the response message with the newly created SharedMemory | 48 | // Send the response message with the newly created SharedMemory |
| 48 | Service::APT::MessageParameter result; | 49 | Service::APT::MessageParameter result; |
| @@ -59,12 +60,14 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p | |||
| 59 | ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& parameter) { | 60 | ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& parameter) { |
| 60 | started = true; | 61 | started = true; |
| 61 | 62 | ||
| 62 | // TODO(Subv): Set the expected fields in the response buffer before resending it to the application. | 63 | // TODO(Subv): Set the expected fields in the response buffer before resending it to the |
| 64 | // application. | ||
| 63 | // TODO(Subv): Reverse the parameter format for the Mii Selector | 65 | // TODO(Subv): Reverse the parameter format for the Mii Selector |
| 64 | 66 | ||
| 65 | memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); | 67 | memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); |
| 66 | 68 | ||
| 67 | // TODO(Subv): Find more about this structure, result code 0 is enough to let most games continue. | 69 | // TODO(Subv): Find more about this structure, result code 0 is enough to let most games |
| 70 | // continue. | ||
| 68 | MiiResult result; | 71 | MiiResult result; |
| 69 | memset(&result, 0, sizeof(result)); | 72 | memset(&result, 0, sizeof(result)); |
| 70 | result.result_code = 0; | 73 | result.result_code = 0; |
| @@ -84,6 +87,5 @@ ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& pa | |||
| 84 | 87 | ||
| 85 | void MiiSelector::Update() { | 88 | void MiiSelector::Update() { |
| 86 | } | 89 | } |
| 87 | |||
| 88 | } | 90 | } |
| 89 | } // namespace | 91 | } // namespace |
diff --git a/src/core/hle/applets/mii_selector.h b/src/core/hle/applets/mii_selector.h index 24e8e721d..dba4abc8d 100644 --- a/src/core/hle/applets/mii_selector.h +++ b/src/core/hle/applets/mii_selector.h | |||
| @@ -4,8 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/common_funcs.h" | 7 | #include "common/common_funcs.h" |
| 8 | #include "common/common_types.h" | ||
| 9 | 9 | ||
| 10 | #include "core/hle/applets/applet.h" | 10 | #include "core/hle/applets/applet.h" |
| 11 | #include "core/hle/kernel/kernel.h" | 11 | #include "core/hle/kernel/kernel.h" |
| @@ -17,28 +17,30 @@ namespace HLE { | |||
| 17 | namespace Applets { | 17 | namespace Applets { |
| 18 | 18 | ||
| 19 | struct MiiConfig { | 19 | struct MiiConfig { |
| 20 | u8 unk_000; | 20 | u8 unk_000; |
| 21 | u8 unk_001; | 21 | u8 unk_001; |
| 22 | u8 unk_002; | 22 | u8 unk_002; |
| 23 | u8 unk_003; | 23 | u8 unk_003; |
| 24 | u8 unk_004; | 24 | u8 unk_004; |
| 25 | INSERT_PADDING_BYTES(3); | 25 | INSERT_PADDING_BYTES(3); |
| 26 | u16 unk_008; | 26 | u16 unk_008; |
| 27 | INSERT_PADDING_BYTES(0x82); | 27 | INSERT_PADDING_BYTES(0x82); |
| 28 | u8 unk_08C; | 28 | u8 unk_08C; |
| 29 | INSERT_PADDING_BYTES(3); | 29 | INSERT_PADDING_BYTES(3); |
| 30 | u16 unk_090; | 30 | u16 unk_090; |
| 31 | INSERT_PADDING_BYTES(2); | 31 | INSERT_PADDING_BYTES(2); |
| 32 | u32 unk_094; | 32 | u32 unk_094; |
| 33 | u16 unk_098; | 33 | u16 unk_098; |
| 34 | u8 unk_09A[0x64]; | 34 | u8 unk_09A[0x64]; |
| 35 | u8 unk_0FE; | 35 | u8 unk_0FE; |
| 36 | u8 unk_0FF; | 36 | u8 unk_0FF; |
| 37 | u32 unk_100; | 37 | u32 unk_100; |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | static_assert(sizeof(MiiConfig) == 0x104, "MiiConfig structure has incorrect size"); | 40 | static_assert(sizeof(MiiConfig) == 0x104, "MiiConfig structure has incorrect size"); |
| 41 | #define ASSERT_REG_POSITION(field_name, position) static_assert(offsetof(MiiConfig, field_name) == position, "Field "#field_name" has invalid position") | 41 | #define ASSERT_REG_POSITION(field_name, position) \ |
| 42 | static_assert(offsetof(MiiConfig, field_name) == position, \ | ||
| 43 | "Field " #field_name " has invalid position") | ||
| 42 | ASSERT_REG_POSITION(unk_008, 0x08); | 44 | ASSERT_REG_POSITION(unk_008, 0x08); |
| 43 | ASSERT_REG_POSITION(unk_08C, 0x8C); | 45 | ASSERT_REG_POSITION(unk_08C, 0x8C); |
| 44 | ASSERT_REG_POSITION(unk_090, 0x90); | 46 | ASSERT_REG_POSITION(unk_090, 0x90); |
| @@ -55,22 +57,28 @@ struct MiiResult { | |||
| 55 | INSERT_PADDING_BYTES(2); | 57 | INSERT_PADDING_BYTES(2); |
| 56 | }; | 58 | }; |
| 57 | static_assert(sizeof(MiiResult) == 0x84, "MiiResult structure has incorrect size"); | 59 | static_assert(sizeof(MiiResult) == 0x84, "MiiResult structure has incorrect size"); |
| 58 | #define ASSERT_REG_POSITION(field_name, position) static_assert(offsetof(MiiResult, field_name) == position, "Field "#field_name" has invalid position") | 60 | #define ASSERT_REG_POSITION(field_name, position) \ |
| 61 | static_assert(offsetof(MiiResult, field_name) == position, \ | ||
| 62 | "Field " #field_name " has invalid position") | ||
| 59 | ASSERT_REG_POSITION(unk_0C, 0x0C); | 63 | ASSERT_REG_POSITION(unk_0C, 0x0C); |
| 60 | ASSERT_REG_POSITION(unk_6C, 0x6C); | 64 | ASSERT_REG_POSITION(unk_6C, 0x6C); |
| 61 | #undef ASSERT_REG_POSITION | 65 | #undef ASSERT_REG_POSITION |
| 62 | 66 | ||
| 63 | class MiiSelector final : public Applet { | 67 | class MiiSelector final : public Applet { |
| 64 | public: | 68 | public: |
| 65 | MiiSelector(Service::APT::AppletId id) : Applet(id), started(false) { } | 69 | MiiSelector(Service::APT::AppletId id) : Applet(id), started(false) { |
| 70 | } | ||
| 66 | 71 | ||
| 67 | ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; | 72 | ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; |
| 68 | ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; | 73 | ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; |
| 69 | void Update() override; | 74 | void Update() override; |
| 70 | bool IsRunning() const override { return started; } | 75 | bool IsRunning() const override { |
| 76 | return started; | ||
| 77 | } | ||
| 71 | 78 | ||
| 72 | /// This SharedMemory will be created when we receive the LibAppJustStarted message. | 79 | /// This SharedMemory will be created when we receive the LibAppJustStarted message. |
| 73 | /// It holds the framebuffer info retrieved by the application with GSPGPU::ImportDisplayCaptureInfo | 80 | /// It holds the framebuffer info retrieved by the application with |
| 81 | /// GSPGPU::ImportDisplayCaptureInfo | ||
| 74 | Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; | 82 | Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; |
| 75 | 83 | ||
| 76 | /// Whether this applet is currently running instead of the host application or not. | 84 | /// Whether this applet is currently running instead of the host application or not. |
| @@ -78,6 +86,5 @@ public: | |||
| 78 | 86 | ||
| 79 | MiiConfig config; | 87 | MiiConfig config; |
| 80 | }; | 88 | }; |
| 81 | |||
| 82 | } | 89 | } |
| 83 | } // namespace | 90 | } // namespace |
diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp index d87bf3d57..cf2775968 100644 --- a/src/core/hle/applets/swkbd.cpp +++ b/src/core/hle/applets/swkbd.cpp | |||
| @@ -12,9 +12,9 @@ | |||
| 12 | #include "core/hle/applets/swkbd.h" | 12 | #include "core/hle/applets/swkbd.h" |
| 13 | #include "core/hle/kernel/kernel.h" | 13 | #include "core/hle/kernel/kernel.h" |
| 14 | #include "core/hle/kernel/shared_memory.h" | 14 | #include "core/hle/kernel/shared_memory.h" |
| 15 | #include "core/hle/service/hid/hid.h" | ||
| 16 | #include "core/hle/service/gsp_gpu.h" | ||
| 17 | #include "core/hle/result.h" | 15 | #include "core/hle/result.h" |
| 16 | #include "core/hle/service/gsp_gpu.h" | ||
| 17 | #include "core/hle/service/hid/hid.h" | ||
| 18 | #include "core/memory.h" | 18 | #include "core/memory.h" |
| 19 | 19 | ||
| 20 | #include "video_core/video_core.h" | 20 | #include "video_core/video_core.h" |
| @@ -32,7 +32,8 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con | |||
| 32 | return ResultCode(-1); | 32 | return ResultCode(-1); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory. | 35 | // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared |
| 36 | // memory. | ||
| 36 | // Create the SharedMemory that will hold the framebuffer data | 37 | // Create the SharedMemory that will hold the framebuffer data |
| 37 | Service::APT::CaptureBufferInfo capture_info; | 38 | Service::APT::CaptureBufferInfo capture_info; |
| 38 | ASSERT(sizeof(capture_info) == parameter.buffer.size()); | 39 | ASSERT(sizeof(capture_info) == parameter.buffer.size()); |
| @@ -43,9 +44,9 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con | |||
| 43 | // Allocate a heap block of the required size for this applet. | 44 | // Allocate a heap block of the required size for this applet. |
| 44 | heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); | 45 | heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); |
| 45 | // Create a SharedMemory that directly points to this heap block. | 46 | // Create a SharedMemory that directly points to this heap block. |
| 46 | framebuffer_memory = Kernel::SharedMemory::CreateForApplet(heap_memory, 0, heap_memory->size(), | 47 | framebuffer_memory = Kernel::SharedMemory::CreateForApplet( |
| 47 | MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, | 48 | heap_memory, 0, heap_memory->size(), MemoryPermission::ReadWrite, |
| 48 | "SoftwareKeyboard Memory"); | 49 | MemoryPermission::ReadWrite, "SoftwareKeyboard Memory"); |
| 49 | 50 | ||
| 50 | // Send the response message with the newly created SharedMemory | 51 | // Send the response message with the newly created SharedMemory |
| 51 | Service::APT::MessageParameter result; | 52 | Service::APT::MessageParameter result; |
| @@ -60,10 +61,12 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con | |||
| 60 | } | 61 | } |
| 61 | 62 | ||
| 62 | ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter const& parameter) { | 63 | ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter const& parameter) { |
| 63 | ASSERT_MSG(parameter.buffer.size() == sizeof(config), "The size of the parameter (SoftwareKeyboardConfig) is wrong"); | 64 | ASSERT_MSG(parameter.buffer.size() == sizeof(config), |
| 65 | "The size of the parameter (SoftwareKeyboardConfig) is wrong"); | ||
| 64 | 66 | ||
| 65 | memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); | 67 | memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); |
| 66 | text_memory = boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object); | 68 | text_memory = |
| 69 | boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object); | ||
| 67 | 70 | ||
| 68 | // TODO(Subv): Verify if this is the correct behavior | 71 | // TODO(Subv): Verify if this is the correct behavior |
| 69 | memset(text_memory->GetPointer(), 0, text_memory->size); | 72 | memset(text_memory->GetPointer(), 0, text_memory->size); |
| @@ -115,6 +118,5 @@ void SoftwareKeyboard::Finalize() { | |||
| 115 | 118 | ||
| 116 | started = false; | 119 | started = false; |
| 117 | } | 120 | } |
| 118 | |||
| 119 | } | 121 | } |
| 120 | } // namespace | 122 | } // namespace |
diff --git a/src/core/hle/applets/swkbd.h b/src/core/hle/applets/swkbd.h index cf26a8fb7..f50673912 100644 --- a/src/core/hle/applets/swkbd.h +++ b/src/core/hle/applets/swkbd.h | |||
| @@ -4,8 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/common_funcs.h" | 7 | #include "common/common_funcs.h" |
| 8 | #include "common/common_types.h" | ||
| 9 | 9 | ||
| 10 | #include "core/hle/applets/applet.h" | 10 | #include "core/hle/applets/applet.h" |
| 11 | #include "core/hle/kernel/kernel.h" | 11 | #include "core/hle/kernel/kernel.h" |
| @@ -53,12 +53,15 @@ static_assert(sizeof(SoftwareKeyboardConfig) == 0x400, "Software Keyboard Config | |||
| 53 | 53 | ||
| 54 | class SoftwareKeyboard final : public Applet { | 54 | class SoftwareKeyboard final : public Applet { |
| 55 | public: | 55 | public: |
| 56 | SoftwareKeyboard(Service::APT::AppletId id) : Applet(id), started(false) { } | 56 | SoftwareKeyboard(Service::APT::AppletId id) : Applet(id), started(false) { |
| 57 | } | ||
| 57 | 58 | ||
| 58 | ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; | 59 | ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; |
| 59 | ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; | 60 | ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; |
| 60 | void Update() override; | 61 | void Update() override; |
| 61 | bool IsRunning() const override { return started; } | 62 | bool IsRunning() const override { |
| 63 | return started; | ||
| 64 | } | ||
| 62 | 65 | ||
| 63 | /** | 66 | /** |
| 64 | * Draws a keyboard to the current bottom screen framebuffer. | 67 | * Draws a keyboard to the current bottom screen framebuffer. |
| @@ -72,7 +75,8 @@ public: | |||
| 72 | void Finalize(); | 75 | void Finalize(); |
| 73 | 76 | ||
| 74 | /// This SharedMemory will be created when we receive the LibAppJustStarted message. | 77 | /// This SharedMemory will be created when we receive the LibAppJustStarted message. |
| 75 | /// It holds the framebuffer info retrieved by the application with GSPGPU::ImportDisplayCaptureInfo | 78 | /// It holds the framebuffer info retrieved by the application with |
| 79 | /// GSPGPU::ImportDisplayCaptureInfo | ||
| 76 | Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; | 80 | Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; |
| 77 | 81 | ||
| 78 | /// SharedMemory where the output text will be stored | 82 | /// SharedMemory where the output text will be stored |
| @@ -84,6 +88,5 @@ public: | |||
| 84 | /// Whether this applet is currently running instead of the host application or not. | 88 | /// Whether this applet is currently running instead of the host application or not. |
| 85 | bool started; | 89 | bool started; |
| 86 | }; | 90 | }; |
| 87 | |||
| 88 | } | 91 | } |
| 89 | } // namespace | 92 | } // namespace |
diff --git a/src/core/hle/config_mem.cpp b/src/core/hle/config_mem.cpp index ccd73cfcb..00efc179e 100644 --- a/src/core/hle/config_mem.cpp +++ b/src/core/hle/config_mem.cpp | |||
| @@ -2,8 +2,8 @@ | |||
| 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 <cstring> | ||
| 6 | #include "core/hle/config_mem.h" | 5 | #include "core/hle/config_mem.h" |
| 6 | #include <cstring> | ||
| 7 | 7 | ||
| 8 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 8 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 9 | 9 | ||
diff --git a/src/core/hle/config_mem.h b/src/core/hle/config_mem.h index 24a1254f2..50664dac6 100644 --- a/src/core/hle/config_mem.h +++ b/src/core/hle/config_mem.h | |||
| @@ -20,16 +20,16 @@ | |||
| 20 | namespace ConfigMem { | 20 | namespace ConfigMem { |
| 21 | 21 | ||
| 22 | struct ConfigMemDef { | 22 | struct ConfigMemDef { |
| 23 | u8 kernel_unk; // 0 | 23 | u8 kernel_unk; // 0 |
| 24 | u8 kernel_version_rev; // 1 | 24 | u8 kernel_version_rev; // 1 |
| 25 | u8 kernel_version_min; // 2 | 25 | u8 kernel_version_min; // 2 |
| 26 | u8 kernel_version_maj; // 3 | 26 | u8 kernel_version_maj; // 3 |
| 27 | u32_le update_flag; // 4 | 27 | u32_le update_flag; // 4 |
| 28 | u64_le ns_tid; // 8 | 28 | u64_le ns_tid; // 8 |
| 29 | u32_le sys_core_ver; // 10 | 29 | u32_le sys_core_ver; // 10 |
| 30 | u8 unit_info; // 14 | 30 | u8 unit_info; // 14 |
| 31 | u8 boot_firm; // 15 | 31 | u8 boot_firm; // 15 |
| 32 | u8 prev_firm; // 16 | 32 | u8 prev_firm; // 16 |
| 33 | INSERT_PADDING_BYTES(0x1); // 17 | 33 | INSERT_PADDING_BYTES(0x1); // 17 |
| 34 | u32_le ctr_sdk_ver; // 18 | 34 | u32_le ctr_sdk_ver; // 18 |
| 35 | INSERT_PADDING_BYTES(0x30 - 0x1C); // 1C | 35 | INSERT_PADDING_BYTES(0x30 - 0x1C); // 1C |
| @@ -39,15 +39,16 @@ struct ConfigMemDef { | |||
| 39 | u32_le sys_mem_alloc; // 44 | 39 | u32_le sys_mem_alloc; // 44 |
| 40 | u32_le base_mem_alloc; // 48 | 40 | u32_le base_mem_alloc; // 48 |
| 41 | INSERT_PADDING_BYTES(0x60 - 0x4C); // 4C | 41 | INSERT_PADDING_BYTES(0x60 - 0x4C); // 4C |
| 42 | u8 firm_unk; // 60 | 42 | u8 firm_unk; // 60 |
| 43 | u8 firm_version_rev; // 61 | 43 | u8 firm_version_rev; // 61 |
| 44 | u8 firm_version_min; // 62 | 44 | u8 firm_version_min; // 62 |
| 45 | u8 firm_version_maj; // 63 | 45 | u8 firm_version_maj; // 63 |
| 46 | u32_le firm_sys_core_ver; // 64 | 46 | u32_le firm_sys_core_ver; // 64 |
| 47 | u32_le firm_ctr_sdk_ver; // 68 | 47 | u32_le firm_ctr_sdk_ver; // 68 |
| 48 | INSERT_PADDING_BYTES(0x1000 - 0x6C); // 6C | 48 | INSERT_PADDING_BYTES(0x1000 - 0x6C); // 6C |
| 49 | }; | 49 | }; |
| 50 | static_assert(sizeof(ConfigMemDef) == Memory::CONFIG_MEMORY_SIZE, "Config Memory structure size is wrong"); | 50 | static_assert(sizeof(ConfigMemDef) == Memory::CONFIG_MEMORY_SIZE, |
| 51 | "Config Memory structure size is wrong"); | ||
| 51 | 52 | ||
| 52 | extern ConfigMemDef config_mem; | 53 | extern ConfigMemDef config_mem; |
| 53 | 54 | ||
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 8839ce482..d5d989c29 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h | |||
| @@ -7,14 +7,14 @@ | |||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | 8 | ||
| 9 | #include "core/arm/arm_interface.h" | 9 | #include "core/arm/arm_interface.h" |
| 10 | #include "core/memory.h" | ||
| 11 | #include "core/hle/hle.h" | 10 | #include "core/hle/hle.h" |
| 12 | #include "core/hle/result.h" | 11 | #include "core/hle/result.h" |
| 13 | #include "core/hle/svc.h" | 12 | #include "core/hle/svc.h" |
| 13 | #include "core/memory.h" | ||
| 14 | 14 | ||
| 15 | namespace HLE { | 15 | namespace HLE { |
| 16 | 16 | ||
| 17 | #define PARAM(n) Core::g_app_core->GetReg(n) | 17 | #define PARAM(n) Core::g_app_core->GetReg(n) |
| 18 | 18 | ||
| 19 | /// An invalid result code that is meant to be overwritten when a thread resumes from waiting | 19 | /// An invalid result code that is meant to be overwritten when a thread resumes from waiting |
| 20 | static const ResultCode RESULT_INVALID(0xDEADC0DE); | 20 | static const ResultCode RESULT_INVALID(0xDEADC0DE); |
| @@ -40,28 +40,33 @@ static inline void FuncReturn64(u64 res) { | |||
| 40 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 40 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 41 | // Function wrappers that return type ResultCode | 41 | // Function wrappers that return type ResultCode |
| 42 | 42 | ||
| 43 | template<ResultCode func(u32, u32, u32, u32)> void Wrap() { | 43 | template <ResultCode func(u32, u32, u32, u32)> |
| 44 | void Wrap() { | ||
| 44 | FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)).raw); | 45 | FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)).raw); |
| 45 | } | 46 | } |
| 46 | 47 | ||
| 47 | template<ResultCode func(u32*, u32, u32, u32, u32, u32)> void Wrap(){ | 48 | template <ResultCode func(u32*, u32, u32, u32, u32, u32)> |
| 49 | void Wrap() { | ||
| 48 | u32 param_1 = 0; | 50 | u32 param_1 = 0; |
| 49 | u32 retval = func(¶m_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; | 51 | u32 retval = func(¶m_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; |
| 50 | Core::g_app_core->SetReg(1, param_1); | 52 | Core::g_app_core->SetReg(1, param_1); |
| 51 | FuncReturn(retval); | 53 | FuncReturn(retval); |
| 52 | } | 54 | } |
| 53 | 55 | ||
| 54 | template<ResultCode func(u32*, s32, u32, u32, u32, s32)> void Wrap() { | 56 | template <ResultCode func(u32*, s32, u32, u32, u32, s32)> |
| 57 | void Wrap() { | ||
| 55 | u32 param_1 = 0; | 58 | u32 param_1 = 0; |
| 56 | u32 retval = func(¶m_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; | 59 | u32 retval = func(¶m_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; |
| 57 | Core::g_app_core->SetReg(1, param_1); | 60 | Core::g_app_core->SetReg(1, param_1); |
| 58 | FuncReturn(retval); | 61 | FuncReturn(retval); |
| 59 | } | 62 | } |
| 60 | 63 | ||
| 61 | template<ResultCode func(s32*, u32*, s32, bool, s64)> void Wrap() { | 64 | template <ResultCode func(s32*, u32*, s32, bool, s64)> |
| 65 | void Wrap() { | ||
| 62 | s32 param_1 = 0; | 66 | s32 param_1 = 0; |
| 63 | s32 retval = func(¶m_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2), | 67 | s32 retval = func(¶m_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2), |
| 64 | (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0))).raw; | 68 | (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0))) |
| 69 | .raw; | ||
| 65 | 70 | ||
| 66 | if (retval != RESULT_INVALID.raw) { | 71 | if (retval != RESULT_INVALID.raw) { |
| 67 | Core::g_app_core->SetReg(1, (u32)param_1); | 72 | Core::g_app_core->SetReg(1, (u32)param_1); |
| @@ -69,18 +74,22 @@ template<ResultCode func(s32*, u32*, s32, bool, s64)> void Wrap() { | |||
| 69 | } | 74 | } |
| 70 | } | 75 | } |
| 71 | 76 | ||
| 72 | template<ResultCode func(u32, u32, u32, u32, s64)> void Wrap() { | 77 | template <ResultCode func(u32, u32, u32, u32, s64)> |
| 73 | FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), (((s64)PARAM(5) << 32) | PARAM(4))).raw); | 78 | void Wrap() { |
| 79 | FuncReturn( | ||
| 80 | func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), (((s64)PARAM(5) << 32) | PARAM(4))).raw); | ||
| 74 | } | 81 | } |
| 75 | 82 | ||
| 76 | template<ResultCode func(u32*)> void Wrap(){ | 83 | template <ResultCode func(u32*)> |
| 84 | void Wrap() { | ||
| 77 | u32 param_1 = 0; | 85 | u32 param_1 = 0; |
| 78 | u32 retval = func(¶m_1).raw; | 86 | u32 retval = func(¶m_1).raw; |
| 79 | Core::g_app_core->SetReg(1, param_1); | 87 | Core::g_app_core->SetReg(1, param_1); |
| 80 | FuncReturn(retval); | 88 | FuncReturn(retval); |
| 81 | } | 89 | } |
| 82 | 90 | ||
| 83 | template<ResultCode func(u32, s64)> void Wrap() { | 91 | template <ResultCode func(u32, s64)> |
| 92 | void Wrap() { | ||
| 84 | s32 retval = func(PARAM(0), (((s64)PARAM(3) << 32) | PARAM(2))).raw; | 93 | s32 retval = func(PARAM(0), (((s64)PARAM(3) << 32) | PARAM(2))).raw; |
| 85 | 94 | ||
| 86 | if (retval != RESULT_INVALID.raw) { | 95 | if (retval != RESULT_INVALID.raw) { |
| @@ -88,7 +97,8 @@ template<ResultCode func(u32, s64)> void Wrap() { | |||
| 88 | } | 97 | } |
| 89 | } | 98 | } |
| 90 | 99 | ||
| 91 | template<ResultCode func(MemoryInfo*, PageInfo*, u32)> void Wrap() { | 100 | template <ResultCode func(MemoryInfo*, PageInfo*, u32)> |
| 101 | void Wrap() { | ||
| 92 | MemoryInfo memory_info = {}; | 102 | MemoryInfo memory_info = {}; |
| 93 | PageInfo page_info = {}; | 103 | PageInfo page_info = {}; |
| 94 | u32 retval = func(&memory_info, &page_info, PARAM(2)).raw; | 104 | u32 retval = func(&memory_info, &page_info, PARAM(2)).raw; |
| @@ -100,7 +110,8 @@ template<ResultCode func(MemoryInfo*, PageInfo*, u32)> void Wrap() { | |||
| 100 | FuncReturn(retval); | 110 | FuncReturn(retval); |
| 101 | } | 111 | } |
| 102 | 112 | ||
| 103 | template<ResultCode func(MemoryInfo*, PageInfo*, Handle, u32)> void Wrap() { | 113 | template <ResultCode func(MemoryInfo*, PageInfo*, Handle, u32)> |
| 114 | void Wrap() { | ||
| 104 | MemoryInfo memory_info = {}; | 115 | MemoryInfo memory_info = {}; |
| 105 | PageInfo page_info = {}; | 116 | PageInfo page_info = {}; |
| 106 | u32 retval = func(&memory_info, &page_info, PARAM(2), PARAM(3)).raw; | 117 | u32 retval = func(&memory_info, &page_info, PARAM(2), PARAM(3)).raw; |
| @@ -112,55 +123,65 @@ template<ResultCode func(MemoryInfo*, PageInfo*, Handle, u32)> void Wrap() { | |||
| 112 | FuncReturn(retval); | 123 | FuncReturn(retval); |
| 113 | } | 124 | } |
| 114 | 125 | ||
| 115 | template<ResultCode func(s32*, u32)> void Wrap(){ | 126 | template <ResultCode func(s32*, u32)> |
| 127 | void Wrap() { | ||
| 116 | s32 param_1 = 0; | 128 | s32 param_1 = 0; |
| 117 | u32 retval = func(¶m_1, PARAM(1)).raw; | 129 | u32 retval = func(¶m_1, PARAM(1)).raw; |
| 118 | Core::g_app_core->SetReg(1, param_1); | 130 | Core::g_app_core->SetReg(1, param_1); |
| 119 | FuncReturn(retval); | 131 | FuncReturn(retval); |
| 120 | } | 132 | } |
| 121 | 133 | ||
| 122 | template<ResultCode func(u32, s32)> void Wrap() { | 134 | template <ResultCode func(u32, s32)> |
| 135 | void Wrap() { | ||
| 123 | FuncReturn(func(PARAM(0), (s32)PARAM(1)).raw); | 136 | FuncReturn(func(PARAM(0), (s32)PARAM(1)).raw); |
| 124 | } | 137 | } |
| 125 | 138 | ||
| 126 | template<ResultCode func(u32*, u32)> void Wrap(){ | 139 | template <ResultCode func(u32*, u32)> |
| 140 | void Wrap() { | ||
| 127 | u32 param_1 = 0; | 141 | u32 param_1 = 0; |
| 128 | u32 retval = func(¶m_1, PARAM(1)).raw; | 142 | u32 retval = func(¶m_1, PARAM(1)).raw; |
| 129 | Core::g_app_core->SetReg(1, param_1); | 143 | Core::g_app_core->SetReg(1, param_1); |
| 130 | FuncReturn(retval); | 144 | FuncReturn(retval); |
| 131 | } | 145 | } |
| 132 | 146 | ||
| 133 | template<ResultCode func(u32)> void Wrap() { | 147 | template <ResultCode func(u32)> |
| 148 | void Wrap() { | ||
| 134 | FuncReturn(func(PARAM(0)).raw); | 149 | FuncReturn(func(PARAM(0)).raw); |
| 135 | } | 150 | } |
| 136 | 151 | ||
| 137 | template<ResultCode func(s64*, u32, u32*, u32)> void Wrap(){ | 152 | template <ResultCode func(s64*, u32, u32*, u32)> |
| 138 | FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), (u32*)Memory::GetPointer(PARAM(2)), | 153 | void Wrap() { |
| 139 | (s32)PARAM(3)).raw); | 154 | FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), |
| 155 | (u32*)Memory::GetPointer(PARAM(2)), (s32)PARAM(3)) | ||
| 156 | .raw); | ||
| 140 | } | 157 | } |
| 141 | 158 | ||
| 142 | template<ResultCode func(u32*, const char*)> void Wrap() { | 159 | template <ResultCode func(u32*, const char*)> |
| 160 | void Wrap() { | ||
| 143 | u32 param_1 = 0; | 161 | u32 param_1 = 0; |
| 144 | u32 retval = func(¶m_1, (char*)Memory::GetPointer(PARAM(1))).raw; | 162 | u32 retval = func(¶m_1, (char*)Memory::GetPointer(PARAM(1))).raw; |
| 145 | Core::g_app_core->SetReg(1, param_1); | 163 | Core::g_app_core->SetReg(1, param_1); |
| 146 | FuncReturn(retval); | 164 | FuncReturn(retval); |
| 147 | } | 165 | } |
| 148 | 166 | ||
| 149 | template<ResultCode func(u32*, s32, s32)> void Wrap() { | 167 | template <ResultCode func(u32*, s32, s32)> |
| 168 | void Wrap() { | ||
| 150 | u32 param_1 = 0; | 169 | u32 param_1 = 0; |
| 151 | u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw; | 170 | u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw; |
| 152 | Core::g_app_core->SetReg(1, param_1); | 171 | Core::g_app_core->SetReg(1, param_1); |
| 153 | FuncReturn(retval); | 172 | FuncReturn(retval); |
| 154 | } | 173 | } |
| 155 | 174 | ||
| 156 | template<ResultCode func(s32*, u32, s32)> void Wrap() { | 175 | template <ResultCode func(s32*, u32, s32)> |
| 176 | void Wrap() { | ||
| 157 | s32 param_1 = 0; | 177 | s32 param_1 = 0; |
| 158 | u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw; | 178 | u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw; |
| 159 | Core::g_app_core->SetReg(1, param_1); | 179 | Core::g_app_core->SetReg(1, param_1); |
| 160 | FuncReturn(retval); | 180 | FuncReturn(retval); |
| 161 | } | 181 | } |
| 162 | 182 | ||
| 163 | template<ResultCode func(s64*, u32, s32)> void Wrap() { | 183 | template <ResultCode func(s64*, u32, s32)> |
| 184 | void Wrap() { | ||
| 164 | s64 param_1 = 0; | 185 | s64 param_1 = 0; |
| 165 | u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw; | 186 | u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw; |
| 166 | Core::g_app_core->SetReg(1, (u32)param_1); | 187 | Core::g_app_core->SetReg(1, (u32)param_1); |
| @@ -168,7 +189,8 @@ template<ResultCode func(s64*, u32, s32)> void Wrap() { | |||
| 168 | FuncReturn(retval); | 189 | FuncReturn(retval); |
| 169 | } | 190 | } |
| 170 | 191 | ||
| 171 | template<ResultCode func(u32*, u32, u32, u32, u32)> void Wrap() { | 192 | template <ResultCode func(u32*, u32, u32, u32, u32)> |
| 193 | void Wrap() { | ||
| 172 | u32 param_1 = 0; | 194 | u32 param_1 = 0; |
| 173 | // The last parameter is passed in R0 instead of R4 | 195 | // The last parameter is passed in R0 instead of R4 |
| 174 | u32 retval = func(¶m_1, PARAM(1), PARAM(2), PARAM(3), PARAM(0)).raw; | 196 | u32 retval = func(¶m_1, PARAM(1), PARAM(2), PARAM(3), PARAM(0)).raw; |
| @@ -176,13 +198,15 @@ template<ResultCode func(u32*, u32, u32, u32, u32)> void Wrap() { | |||
| 176 | FuncReturn(retval); | 198 | FuncReturn(retval); |
| 177 | } | 199 | } |
| 178 | 200 | ||
| 179 | template<ResultCode func(u32, s64, s64)> void Wrap() { | 201 | template <ResultCode func(u32, s64, s64)> |
| 202 | void Wrap() { | ||
| 180 | s64 param1 = ((u64)PARAM(3) << 32) | PARAM(2); | 203 | s64 param1 = ((u64)PARAM(3) << 32) | PARAM(2); |
| 181 | s64 param2 = ((u64)PARAM(4) << 32) | PARAM(1); | 204 | s64 param2 = ((u64)PARAM(4) << 32) | PARAM(1); |
| 182 | FuncReturn(func(PARAM(0), param1, param2).raw); | 205 | FuncReturn(func(PARAM(0), param1, param2).raw); |
| 183 | } | 206 | } |
| 184 | 207 | ||
| 185 | template<ResultCode func(s64*, Handle, u32)> void Wrap() { | 208 | template <ResultCode func(s64*, Handle, u32)> |
| 209 | void Wrap() { | ||
| 186 | s64 param_1 = 0; | 210 | s64 param_1 = 0; |
| 187 | u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw; | 211 | u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw; |
| 188 | Core::g_app_core->SetReg(1, (u32)param_1); | 212 | Core::g_app_core->SetReg(1, (u32)param_1); |
| @@ -190,14 +214,18 @@ template<ResultCode func(s64*, Handle, u32)> void Wrap() { | |||
| 190 | FuncReturn(retval); | 214 | FuncReturn(retval); |
| 191 | } | 215 | } |
| 192 | 216 | ||
| 193 | template<ResultCode func(Handle, u32)> void Wrap() { | 217 | template <ResultCode func(Handle, u32)> |
| 218 | void Wrap() { | ||
| 194 | FuncReturn(func(PARAM(0), PARAM(1)).raw); | 219 | FuncReturn(func(PARAM(0), PARAM(1)).raw); |
| 195 | } | 220 | } |
| 196 | 221 | ||
| 197 | template<ResultCode func(Handle*, Handle*, const char*, u32)> void Wrap() { | 222 | template <ResultCode func(Handle*, Handle*, const char*, u32)> |
| 223 | void Wrap() { | ||
| 198 | Handle param_1 = 0; | 224 | Handle param_1 = 0; |
| 199 | Handle param_2 = 0; | 225 | Handle param_2 = 0; |
| 200 | u32 retval = func(¶m_1, ¶m_2, reinterpret_cast<const char*>(Memory::GetPointer(PARAM(2))), PARAM(3)).raw; | 226 | u32 retval = func(¶m_1, ¶m_2, |
| 227 | reinterpret_cast<const char*>(Memory::GetPointer(PARAM(2))), PARAM(3)) | ||
| 228 | .raw; | ||
| 201 | // The first out parameter is moved into R2 and the second is moved into R1. | 229 | // The first out parameter is moved into R2 and the second is moved into R1. |
| 202 | Core::g_app_core->SetReg(1, param_2); | 230 | Core::g_app_core->SetReg(1, param_2); |
| 203 | Core::g_app_core->SetReg(2, param_1); | 231 | Core::g_app_core->SetReg(2, param_1); |
| @@ -207,29 +235,34 @@ template<ResultCode func(Handle*, Handle*, const char*, u32)> void Wrap() { | |||
| 207 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 235 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 208 | // Function wrappers that return type u32 | 236 | // Function wrappers that return type u32 |
| 209 | 237 | ||
| 210 | template<u32 func()> void Wrap() { | 238 | template <u32 func()> |
| 239 | void Wrap() { | ||
| 211 | FuncReturn(func()); | 240 | FuncReturn(func()); |
| 212 | } | 241 | } |
| 213 | 242 | ||
| 214 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 243 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 215 | // Function wrappers that return type s64 | 244 | // Function wrappers that return type s64 |
| 216 | 245 | ||
| 217 | template<s64 func()> void Wrap() { | 246 | template <s64 func()> |
| 247 | void Wrap() { | ||
| 218 | FuncReturn64(func()); | 248 | FuncReturn64(func()); |
| 219 | } | 249 | } |
| 220 | 250 | ||
| 221 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 251 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 222 | /// Function wrappers that return type void | 252 | /// Function wrappers that return type void |
| 223 | 253 | ||
| 224 | template<void func(s64)> void Wrap() { | 254 | template <void func(s64)> |
| 255 | void Wrap() { | ||
| 225 | func(((s64)PARAM(1) << 32) | PARAM(0)); | 256 | func(((s64)PARAM(1) << 32) | PARAM(0)); |
| 226 | } | 257 | } |
| 227 | 258 | ||
| 228 | template<void func(const char*)> void Wrap() { | 259 | template <void func(const char*)> |
| 260 | void Wrap() { | ||
| 229 | func((char*)Memory::GetPointer(PARAM(0))); | 261 | func((char*)Memory::GetPointer(PARAM(0))); |
| 230 | } | 262 | } |
| 231 | 263 | ||
| 232 | template<void func(u8)> void Wrap() { | 264 | template <void func(u8)> |
| 265 | void Wrap() { | ||
| 233 | func((u8)PARAM(0)); | 266 | func((u8)PARAM(0)); |
| 234 | } | 267 | } |
| 235 | 268 | ||
diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp index 5c5373517..480a73e80 100644 --- a/src/core/hle/hle.cpp +++ b/src/core/hle/hle.cpp | |||
| @@ -15,13 +15,13 @@ | |||
| 15 | namespace { | 15 | namespace { |
| 16 | 16 | ||
| 17 | bool reschedule; ///< If true, immediately reschedules the CPU to a new thread | 17 | bool reschedule; ///< If true, immediately reschedules the CPU to a new thread |
| 18 | |||
| 19 | } | 18 | } |
| 20 | 19 | ||
| 21 | namespace HLE { | 20 | namespace HLE { |
| 22 | 21 | ||
| 23 | void Reschedule(const char *reason) { | 22 | void Reschedule(const char* reason) { |
| 24 | DEBUG_ASSERT_MSG(reason != nullptr && strlen(reason) < 256, "Reschedule: Invalid or too long reason."); | 23 | DEBUG_ASSERT_MSG(reason != nullptr && strlen(reason) < 256, |
| 24 | "Reschedule: Invalid or too long reason."); | ||
| 25 | 25 | ||
| 26 | // TODO(bunnei): It seems that games depend on some CPU execution time elapsing during HLE | 26 | // TODO(bunnei): It seems that games depend on some CPU execution time elapsing during HLE |
| 27 | // routines. This simulates that time by artificially advancing the number of CPU "ticks". | 27 | // routines. This simulates that time by artificially advancing the number of CPU "ticks". |
diff --git a/src/core/hle/hle.h b/src/core/hle/hle.h index 69ac0ade6..23859e129 100644 --- a/src/core/hle/hle.h +++ b/src/core/hle/hle.h | |||
| @@ -13,7 +13,7 @@ const Handle INVALID_HANDLE = 0; | |||
| 13 | 13 | ||
| 14 | namespace HLE { | 14 | namespace HLE { |
| 15 | 15 | ||
| 16 | void Reschedule(const char *reason); | 16 | void Reschedule(const char* reason); |
| 17 | bool IsReschedulePending(); | 17 | bool IsReschedulePending(); |
| 18 | void DoneRescheduling(); | 18 | void DoneRescheduling(); |
| 19 | 19 | ||
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 5c3c47acf..2ff652f13 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp | |||
| @@ -16,8 +16,10 @@ | |||
| 16 | 16 | ||
| 17 | namespace Kernel { | 17 | namespace Kernel { |
| 18 | 18 | ||
| 19 | AddressArbiter::AddressArbiter() {} | 19 | AddressArbiter::AddressArbiter() { |
| 20 | AddressArbiter::~AddressArbiter() {} | 20 | } |
| 21 | AddressArbiter::~AddressArbiter() { | ||
| 22 | } | ||
| 21 | 23 | ||
| 22 | SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) { | 24 | SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) { |
| 23 | SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter); | 25 | SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter); |
| @@ -28,7 +30,7 @@ SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) { | |||
| 28 | } | 30 | } |
| 29 | 31 | ||
| 30 | ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, | 32 | ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, |
| 31 | u64 nanoseconds) { | 33 | u64 nanoseconds) { |
| 32 | switch (type) { | 34 | switch (type) { |
| 33 | 35 | ||
| 34 | // Signal thread(s) waiting for arbitrate address... | 36 | // Signal thread(s) waiting for arbitrate address... |
| @@ -38,7 +40,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, | |||
| 38 | ArbitrateAllThreads(address); | 40 | ArbitrateAllThreads(address); |
| 39 | } else { | 41 | } else { |
| 40 | // Resume first N threads | 42 | // Resume first N threads |
| 41 | for(int i = 0; i < value; i++) | 43 | for (int i = 0; i < value; i++) |
| 42 | ArbitrateHighestPriorityThread(address); | 44 | ArbitrateHighestPriorityThread(address); |
| 43 | } | 45 | } |
| 44 | break; | 46 | break; |
| @@ -55,8 +57,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, | |||
| 55 | GetCurrentThread()->WakeAfterDelay(nanoseconds); | 57 | GetCurrentThread()->WakeAfterDelay(nanoseconds); |
| 56 | } | 58 | } |
| 57 | break; | 59 | break; |
| 58 | case ArbitrationType::DecrementAndWaitIfLessThan: | 60 | case ArbitrationType::DecrementAndWaitIfLessThan: { |
| 59 | { | ||
| 60 | s32 memory_value = Memory::Read32(address); | 61 | s32 memory_value = Memory::Read32(address); |
| 61 | if (memory_value < value) { | 62 | if (memory_value < value) { |
| 62 | // Only change the memory value if the thread should wait | 63 | // Only change the memory value if the thread should wait |
| @@ -65,8 +66,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, | |||
| 65 | } | 66 | } |
| 66 | break; | 67 | break; |
| 67 | } | 68 | } |
| 68 | case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: | 69 | case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: { |
| 69 | { | ||
| 70 | s32 memory_value = Memory::Read32(address); | 70 | s32 memory_value = Memory::Read32(address); |
| 71 | if (memory_value < value) { | 71 | if (memory_value < value) { |
| 72 | // Only change the memory value if the thread should wait | 72 | // Only change the memory value if the thread should wait |
| @@ -79,17 +79,19 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, | |||
| 79 | 79 | ||
| 80 | default: | 80 | default: |
| 81 | LOG_ERROR(Kernel, "unknown type=%d", type); | 81 | LOG_ERROR(Kernel, "unknown type=%d", type); |
| 82 | return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, ErrorSummary::WrongArgument, ErrorLevel::Usage); | 82 | return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, |
| 83 | ErrorSummary::WrongArgument, ErrorLevel::Usage); | ||
| 83 | } | 84 | } |
| 84 | 85 | ||
| 85 | HLE::Reschedule(__func__); | 86 | HLE::Reschedule(__func__); |
| 86 | 87 | ||
| 87 | // The calls that use a timeout seem to always return a Timeout error even if they did not put the thread to sleep | 88 | // The calls that use a timeout seem to always return a Timeout error even if they did not put |
| 89 | // the thread to sleep | ||
| 88 | if (type == ArbitrationType::WaitIfLessThanWithTimeout || | 90 | if (type == ArbitrationType::WaitIfLessThanWithTimeout || |
| 89 | type == ArbitrationType::DecrementAndWaitIfLessThanWithTimeout) { | 91 | type == ArbitrationType::DecrementAndWaitIfLessThanWithTimeout) { |
| 90 | 92 | ||
| 91 | return ResultCode(ErrorDescription::Timeout, ErrorModule::OS, | 93 | return ResultCode(ErrorDescription::Timeout, ErrorModule::OS, ErrorSummary::StatusChanged, |
| 92 | ErrorSummary::StatusChanged, ErrorLevel::Info); | 94 | ErrorLevel::Info); |
| 93 | } | 95 | } |
| 94 | return RESULT_SUCCESS; | 96 | return RESULT_SUCCESS; |
| 95 | } | 97 | } |
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h index 8f6a1a8df..1a03993b2 100644 --- a/src/core/hle/kernel/address_arbiter.h +++ b/src/core/hle/kernel/address_arbiter.h | |||
| @@ -36,13 +36,19 @@ public: | |||
| 36 | */ | 36 | */ |
| 37 | static SharedPtr<AddressArbiter> Create(std::string name = "Unknown"); | 37 | static SharedPtr<AddressArbiter> Create(std::string name = "Unknown"); |
| 38 | 38 | ||
| 39 | std::string GetTypeName() const override { return "Arbiter"; } | 39 | std::string GetTypeName() const override { |
| 40 | std::string GetName() const override { return name; } | 40 | return "Arbiter"; |
| 41 | } | ||
| 42 | std::string GetName() const override { | ||
| 43 | return name; | ||
| 44 | } | ||
| 41 | 45 | ||
| 42 | static const HandleType HANDLE_TYPE = HandleType::AddressArbiter; | 46 | static const HandleType HANDLE_TYPE = HandleType::AddressArbiter; |
| 43 | HandleType GetHandleType() const override { return HANDLE_TYPE; } | 47 | HandleType GetHandleType() const override { |
| 48 | return HANDLE_TYPE; | ||
| 49 | } | ||
| 44 | 50 | ||
| 45 | std::string name; ///< Name of address arbiter object (optional) | 51 | std::string name; ///< Name of address arbiter object (optional) |
| 46 | 52 | ||
| 47 | ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds); | 53 | ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds); |
| 48 | 54 | ||
diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp index 444ce8d45..5df769c6a 100644 --- a/src/core/hle/kernel/client_port.cpp +++ b/src/core/hle/kernel/client_port.cpp | |||
| @@ -10,7 +10,9 @@ | |||
| 10 | 10 | ||
| 11 | namespace Kernel { | 11 | namespace Kernel { |
| 12 | 12 | ||
| 13 | ClientPort::ClientPort() {} | 13 | ClientPort::ClientPort() { |
| 14 | ClientPort::~ClientPort() {} | 14 | } |
| 15 | ClientPort::~ClientPort() { | ||
| 16 | } | ||
| 15 | 17 | ||
| 16 | } // namespace | 18 | } // namespace |
diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h index 480b6ddae..70e0d56cc 100644 --- a/src/core/hle/kernel/client_port.h +++ b/src/core/hle/kernel/client_port.h | |||
| @@ -17,16 +17,22 @@ class ServerPort; | |||
| 17 | class ClientPort : public Object { | 17 | class ClientPort : public Object { |
| 18 | public: | 18 | public: |
| 19 | friend class ServerPort; | 19 | friend class ServerPort; |
| 20 | std::string GetTypeName() const override { return "ClientPort"; } | 20 | std::string GetTypeName() const override { |
| 21 | std::string GetName() const override { return name; } | 21 | return "ClientPort"; |
| 22 | } | ||
| 23 | std::string GetName() const override { | ||
| 24 | return name; | ||
| 25 | } | ||
| 22 | 26 | ||
| 23 | static const HandleType HANDLE_TYPE = HandleType::ClientPort; | 27 | static const HandleType HANDLE_TYPE = HandleType::ClientPort; |
| 24 | HandleType GetHandleType() const override { return HANDLE_TYPE; } | 28 | HandleType GetHandleType() const override { |
| 25 | 29 | return HANDLE_TYPE; | |
| 26 | SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port. | 30 | } |
| 27 | u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have | 31 | |
| 28 | u32 active_sessions; ///< Number of currently open sessions to this port | 32 | SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port. |
| 29 | std::string name; ///< Name of client port (optional) | 33 | u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have |
| 34 | u32 active_sessions; ///< Number of currently open sessions to this port | ||
| 35 | std::string name; ///< Name of client port (optional) | ||
| 30 | 36 | ||
| 31 | protected: | 37 | protected: |
| 32 | ClientPort(); | 38 | ClientPort(); |
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 2b7c6992a..63375818d 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp | |||
| @@ -2,20 +2,22 @@ | |||
| 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 <map> | ||
| 6 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <map> | ||
| 7 | #include <vector> | 7 | #include <vector> |
| 8 | 8 | ||
| 9 | #include "common/assert.h" | 9 | #include "common/assert.h" |
| 10 | 10 | ||
| 11 | #include "core/hle/kernel/kernel.h" | ||
| 12 | #include "core/hle/kernel/event.h" | 11 | #include "core/hle/kernel/event.h" |
| 12 | #include "core/hle/kernel/kernel.h" | ||
| 13 | #include "core/hle/kernel/thread.h" | 13 | #include "core/hle/kernel/thread.h" |
| 14 | 14 | ||
| 15 | namespace Kernel { | 15 | namespace Kernel { |
| 16 | 16 | ||
| 17 | Event::Event() {} | 17 | Event::Event() { |
| 18 | Event::~Event() {} | 18 | } |
| 19 | Event::~Event() { | ||
| 20 | } | ||
| 19 | 21 | ||
| 20 | SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) { | 22 | SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) { |
| 21 | SharedPtr<Event> evt(new Event); | 23 | SharedPtr<Event> evt(new Event); |
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index 73d0da419..e333a46ce 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h | |||
| @@ -16,7 +16,6 @@ enum class ResetType { | |||
| 16 | Pulse, | 16 | Pulse, |
| 17 | }; | 17 | }; |
| 18 | 18 | ||
| 19 | |||
| 20 | class Event final : public WaitObject { | 19 | class Event final : public WaitObject { |
| 21 | public: | 20 | public: |
| 22 | /** | 21 | /** |
| @@ -26,16 +25,22 @@ public: | |||
| 26 | */ | 25 | */ |
| 27 | static SharedPtr<Event> Create(ResetType reset_type, std::string name = "Unknown"); | 26 | static SharedPtr<Event> Create(ResetType reset_type, std::string name = "Unknown"); |
| 28 | 27 | ||
| 29 | std::string GetTypeName() const override { return "Event"; } | 28 | std::string GetTypeName() const override { |
| 30 | std::string GetName() const override { return name; } | 29 | return "Event"; |
| 30 | } | ||
| 31 | std::string GetName() const override { | ||
| 32 | return name; | ||
| 33 | } | ||
| 31 | 34 | ||
| 32 | static const HandleType HANDLE_TYPE = HandleType::Event; | 35 | static const HandleType HANDLE_TYPE = HandleType::Event; |
| 33 | HandleType GetHandleType() const override { return HANDLE_TYPE; } | 36 | HandleType GetHandleType() const override { |
| 37 | return HANDLE_TYPE; | ||
| 38 | } | ||
| 34 | 39 | ||
| 35 | ResetType reset_type; ///< Current ResetType | 40 | ResetType reset_type; ///< Current ResetType |
| 36 | 41 | ||
| 37 | bool signaled; ///< Whether the event has already been signaled | 42 | bool signaled; ///< Whether the event has already been signaled |
| 38 | std::string name; ///< Name of event (optional) | 43 | std::string name; ///< Name of event (optional) |
| 39 | 44 | ||
| 40 | bool ShouldWait() override; | 45 | bool ShouldWait() override; |
| 41 | void Acquire() override; | 46 | void Acquire() override; |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 7a401a965..1fd7c0326 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -61,7 +61,8 @@ ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) { | |||
| 61 | 61 | ||
| 62 | // Overflow count so it fits in the 15 bits dedicated to the generation in the handle. | 62 | // Overflow count so it fits in the 15 bits dedicated to the generation in the handle. |
| 63 | // CTR-OS doesn't use generation 0, so skip straight to 1. | 63 | // CTR-OS doesn't use generation 0, so skip straight to 1. |
| 64 | if (next_generation >= (1 << 15)) next_generation = 1; | 64 | if (next_generation >= (1 << 15)) |
| 65 | next_generation = 1; | ||
| 65 | 66 | ||
| 66 | generations[slot] = generation; | 67 | generations[slot] = generation; |
| 67 | objects[slot] = std::move(obj); | 68 | objects[slot] = std::move(obj); |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 27ba3f912..cc39652d5 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -23,48 +23,55 @@ class Thread; | |||
| 23 | 23 | ||
| 24 | // TODO: Verify code | 24 | // TODO: Verify code |
| 25 | const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel, | 25 | const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel, |
| 26 | ErrorSummary::OutOfResource, ErrorLevel::Temporary); | 26 | ErrorSummary::OutOfResource, ErrorLevel::Temporary); |
| 27 | // TOOD: Verify code | 27 | // TOOD: Verify code |
| 28 | const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel, | 28 | const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel, |
| 29 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); | 29 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); |
| 30 | 30 | ||
| 31 | enum KernelHandle : Handle { | 31 | enum KernelHandle : Handle { |
| 32 | CurrentThread = 0xFFFF8000, | 32 | CurrentThread = 0xFFFF8000, |
| 33 | CurrentProcess = 0xFFFF8001, | 33 | CurrentProcess = 0xFFFF8001, |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | enum class HandleType : u32 { | 36 | enum class HandleType : u32 { |
| 37 | Unknown = 0, | 37 | Unknown = 0, |
| 38 | 38 | ||
| 39 | Session = 2, | 39 | Session = 2, |
| 40 | Event = 3, | 40 | Event = 3, |
| 41 | Mutex = 4, | 41 | Mutex = 4, |
| 42 | SharedMemory = 5, | 42 | SharedMemory = 5, |
| 43 | Redirection = 6, | 43 | Redirection = 6, |
| 44 | Thread = 7, | 44 | Thread = 7, |
| 45 | Process = 8, | 45 | Process = 8, |
| 46 | AddressArbiter = 9, | 46 | AddressArbiter = 9, |
| 47 | Semaphore = 10, | 47 | Semaphore = 10, |
| 48 | Timer = 11, | 48 | Timer = 11, |
| 49 | ResourceLimit = 12, | 49 | ResourceLimit = 12, |
| 50 | CodeSet = 13, | 50 | CodeSet = 13, |
| 51 | ClientPort = 14, | 51 | ClientPort = 14, |
| 52 | ServerPort = 15, | 52 | ServerPort = 15, |
| 53 | }; | 53 | }; |
| 54 | 54 | ||
| 55 | enum { | 55 | enum { |
| 56 | DEFAULT_STACK_SIZE = 0x4000, | 56 | DEFAULT_STACK_SIZE = 0x4000, |
| 57 | }; | 57 | }; |
| 58 | 58 | ||
| 59 | class Object : NonCopyable { | 59 | class Object : NonCopyable { |
| 60 | public: | 60 | public: |
| 61 | virtual ~Object() {} | 61 | virtual ~Object() { |
| 62 | } | ||
| 62 | 63 | ||
| 63 | /// Returns a unique identifier for the object. For debugging purposes only. | 64 | /// Returns a unique identifier for the object. For debugging purposes only. |
| 64 | unsigned int GetObjectId() const { return object_id; } | 65 | unsigned int GetObjectId() const { |
| 66 | return object_id; | ||
| 67 | } | ||
| 65 | 68 | ||
| 66 | virtual std::string GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; } | 69 | virtual std::string GetTypeName() const { |
| 67 | virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; } | 70 | return "[BAD KERNEL OBJECT TYPE]"; |
| 71 | } | ||
| 72 | virtual std::string GetName() const { | ||
| 73 | return "[UNKNOWN KERNEL OBJECT]"; | ||
| 74 | } | ||
| 68 | virtual Kernel::HandleType GetHandleType() const = 0; | 75 | virtual Kernel::HandleType GetHandleType() const = 0; |
| 69 | 76 | ||
| 70 | /** | 77 | /** |
| @@ -122,7 +129,6 @@ using SharedPtr = boost::intrusive_ptr<T>; | |||
| 122 | /// Class that represents a Kernel object that a thread can be waiting on | 129 | /// Class that represents a Kernel object that a thread can be waiting on |
| 123 | class WaitObject : public Object { | 130 | class WaitObject : public Object { |
| 124 | public: | 131 | public: |
| 125 | |||
| 126 | /** | 132 | /** |
| 127 | * Check if the current thread should wait until the object is available | 133 | * Check if the current thread should wait until the object is available |
| 128 | * @return True if the current thread should wait due to this object being unavailable | 134 | * @return True if the current thread should wait due to this object being unavailable |
| @@ -247,8 +253,12 @@ private: | |||
| 247 | */ | 253 | */ |
| 248 | static const size_t MAX_COUNT = 4096; | 254 | static const size_t MAX_COUNT = 4096; |
| 249 | 255 | ||
| 250 | static u16 GetSlot(Handle handle) { return handle >> 15; } | 256 | static u16 GetSlot(Handle handle) { |
| 251 | static u16 GetGeneration(Handle handle) { return handle & 0x7FFF; } | 257 | return handle >> 15; |
| 258 | } | ||
| 259 | static u16 GetGeneration(Handle handle) { | ||
| 260 | return handle & 0x7FFF; | ||
| 261 | } | ||
| 252 | 262 | ||
| 253 | /// Stores the Object referenced by the handle or null if the slot is empty. | 263 | /// Stores the Object referenced by the handle or null if the slot is empty. |
| 254 | std::array<SharedPtr<Object>, MAX_COUNT> objects; | 264 | std::array<SharedPtr<Object>, MAX_COUNT> objects; |
diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp index 17ae87aef..89a72808a 100644 --- a/src/core/hle/kernel/memory.cpp +++ b/src/core/hle/kernel/memory.cpp | |||
| @@ -31,7 +31,7 @@ static MemoryRegionInfo memory_regions[3]; | |||
| 31 | static const u32 memory_region_sizes[8][3] = { | 31 | static const u32 memory_region_sizes[8][3] = { |
| 32 | // Old 3DS layouts | 32 | // Old 3DS layouts |
| 33 | {0x04000000, 0x02C00000, 0x01400000}, // 0 | 33 | {0x04000000, 0x02C00000, 0x01400000}, // 0 |
| 34 | { /* This appears to be unused. */ }, // 1 | 34 | {/* This appears to be unused. */}, // 1 |
| 35 | {0x06000000, 0x00C00000, 0x01400000}, // 2 | 35 | {0x06000000, 0x00C00000, 0x01400000}, // 2 |
| 36 | {0x05000000, 0x01C00000, 0x01400000}, // 3 | 36 | {0x05000000, 0x01C00000, 0x01400000}, // 3 |
| 37 | {0x04800000, 0x02400000, 0x01400000}, // 4 | 37 | {0x04800000, 0x02400000, 0x01400000}, // 4 |
| @@ -95,7 +95,6 @@ MemoryRegionInfo* GetMemoryRegion(MemoryRegion region) { | |||
| 95 | UNREACHABLE(); | 95 | UNREACHABLE(); |
| 96 | } | 96 | } |
| 97 | } | 97 | } |
| 98 | |||
| 99 | } | 98 | } |
| 100 | 99 | ||
| 101 | namespace Memory { | 100 | namespace Memory { |
| @@ -110,9 +109,8 @@ struct MemoryArea { | |||
| 110 | 109 | ||
| 111 | // We don't declare the IO regions in here since its handled by other means. | 110 | // We don't declare the IO regions in here since its handled by other means. |
| 112 | static MemoryArea memory_areas[] = { | 111 | static MemoryArea memory_areas[] = { |
| 113 | {VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM) | 112 | {VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM) |
| 114 | }; | 113 | }; |
| 115 | |||
| 116 | } | 114 | } |
| 117 | 115 | ||
| 118 | void Init() { | 116 | void Init() { |
| @@ -125,15 +123,21 @@ void InitLegacyAddressSpace(Kernel::VMManager& address_space) { | |||
| 125 | 123 | ||
| 126 | for (MemoryArea& area : memory_areas) { | 124 | for (MemoryArea& area : memory_areas) { |
| 127 | auto block = std::make_shared<std::vector<u8>>(area.size); | 125 | auto block = std::make_shared<std::vector<u8>>(area.size); |
| 128 | address_space.MapMemoryBlock(area.base, std::move(block), 0, area.size, MemoryState::Private).Unwrap(); | 126 | address_space |
| 127 | .MapMemoryBlock(area.base, std::move(block), 0, area.size, MemoryState::Private) | ||
| 128 | .Unwrap(); | ||
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | auto cfg_mem_vma = address_space.MapBackingMemory(CONFIG_MEMORY_VADDR, | 131 | auto cfg_mem_vma = address_space |
| 132 | (u8*)&ConfigMem::config_mem, CONFIG_MEMORY_SIZE, MemoryState::Shared).MoveFrom(); | 132 | .MapBackingMemory(CONFIG_MEMORY_VADDR, (u8*)&ConfigMem::config_mem, |
| 133 | CONFIG_MEMORY_SIZE, MemoryState::Shared) | ||
| 134 | .MoveFrom(); | ||
| 133 | address_space.Reprotect(cfg_mem_vma, VMAPermission::Read); | 135 | address_space.Reprotect(cfg_mem_vma, VMAPermission::Read); |
| 134 | 136 | ||
| 135 | auto shared_page_vma = address_space.MapBackingMemory(SHARED_PAGE_VADDR, | 137 | auto shared_page_vma = address_space |
| 136 | (u8*)&SharedPage::shared_page, SHARED_PAGE_SIZE, MemoryState::Shared).MoveFrom(); | 138 | .MapBackingMemory(SHARED_PAGE_VADDR, (u8*)&SharedPage::shared_page, |
| 139 | SHARED_PAGE_SIZE, MemoryState::Shared) | ||
| 140 | .MoveFrom(); | ||
| 137 | address_space.Reprotect(shared_page_vma, VMAPermission::Read); | 141 | address_space.Reprotect(shared_page_vma, VMAPermission::Read); |
| 138 | 142 | ||
| 139 | AudioCore::AddAddressSpace(address_space); | 143 | AudioCore::AddAddressSpace(address_space); |
diff --git a/src/core/hle/kernel/memory.h b/src/core/hle/kernel/memory.h index 091c1f89f..b941c24b6 100644 --- a/src/core/hle/kernel/memory.h +++ b/src/core/hle/kernel/memory.h | |||
| @@ -25,7 +25,6 @@ struct MemoryRegionInfo { | |||
| 25 | void MemoryInit(u32 mem_type); | 25 | void MemoryInit(u32 mem_type); |
| 26 | void MemoryShutdown(); | 26 | void MemoryShutdown(); |
| 27 | MemoryRegionInfo* GetMemoryRegion(MemoryRegion region); | 27 | MemoryRegionInfo* GetMemoryRegion(MemoryRegion region); |
| 28 | |||
| 29 | } | 28 | } |
| 30 | 29 | ||
| 31 | namespace Memory { | 30 | namespace Memory { |
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index edb97d324..f92810804 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp | |||
| @@ -33,8 +33,10 @@ void ReleaseThreadMutexes(Thread* thread) { | |||
| 33 | thread->held_mutexes.clear(); | 33 | thread->held_mutexes.clear(); |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | Mutex::Mutex() {} | 36 | Mutex::Mutex() { |
| 37 | Mutex::~Mutex() {} | 37 | } |
| 38 | Mutex::~Mutex() { | ||
| 39 | } | ||
| 38 | 40 | ||
| 39 | SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) { | 41 | SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) { |
| 40 | SharedPtr<Mutex> mutex(new Mutex); | 42 | SharedPtr<Mutex> mutex(new Mutex); |
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index 1746360e4..cf6a51fdf 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h | |||
| @@ -24,15 +24,21 @@ public: | |||
| 24 | */ | 24 | */ |
| 25 | static SharedPtr<Mutex> Create(bool initial_locked, std::string name = "Unknown"); | 25 | static SharedPtr<Mutex> Create(bool initial_locked, std::string name = "Unknown"); |
| 26 | 26 | ||
| 27 | std::string GetTypeName() const override { return "Mutex"; } | 27 | std::string GetTypeName() const override { |
| 28 | std::string GetName() const override { return name; } | 28 | return "Mutex"; |
| 29 | } | ||
| 30 | std::string GetName() const override { | ||
| 31 | return name; | ||
| 32 | } | ||
| 29 | 33 | ||
| 30 | static const HandleType HANDLE_TYPE = HandleType::Mutex; | 34 | static const HandleType HANDLE_TYPE = HandleType::Mutex; |
| 31 | HandleType GetHandleType() const override { return HANDLE_TYPE; } | 35 | HandleType GetHandleType() const override { |
| 36 | return HANDLE_TYPE; | ||
| 37 | } | ||
| 32 | 38 | ||
| 33 | int lock_count; ///< Number of times the mutex has been acquired | 39 | int lock_count; ///< Number of times the mutex has been acquired |
| 34 | std::string name; ///< Name of mutex (optional) | 40 | std::string name; ///< Name of mutex (optional) |
| 35 | SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex | 41 | SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex |
| 36 | 42 | ||
| 37 | bool ShouldWait() override; | 43 | bool ShouldWait() override; |
| 38 | void Acquire() override; | 44 | void Acquire() override; |
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 69302cc82..cc37e574c 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -26,8 +26,10 @@ SharedPtr<CodeSet> CodeSet::Create(std::string name, u64 program_id) { | |||
| 26 | return codeset; | 26 | return codeset; |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | CodeSet::CodeSet() {} | 29 | CodeSet::CodeSet() { |
| 30 | CodeSet::~CodeSet() {} | 30 | } |
| 31 | CodeSet::~CodeSet() { | ||
| 32 | } | ||
| 31 | 33 | ||
| 32 | u32 Process::next_process_id; | 34 | u32 Process::next_process_id; |
| 33 | 35 | ||
| @@ -60,7 +62,8 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) { | |||
| 60 | 62 | ||
| 61 | while (bits && index < svc_access_mask.size()) { | 63 | while (bits && index < svc_access_mask.size()) { |
| 62 | svc_access_mask.set(index, bits & 1); | 64 | svc_access_mask.set(index, bits & 1); |
| 63 | ++index; bits >>= 1; | 65 | ++index; |
| 66 | bits >>= 1; | ||
| 64 | } | 67 | } |
| 65 | } else if ((type & 0xFF0) == 0xFE0) { // 0x00FF | 68 | } else if ((type & 0xFF0) == 0xFE0) { // 0x00FF |
| 66 | // Handle table size | 69 | // Handle table size |
| @@ -70,11 +73,11 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) { | |||
| 70 | flags.raw = descriptor & 0xFFFF; | 73 | flags.raw = descriptor & 0xFFFF; |
| 71 | } else if ((type & 0xFFE) == 0xFF8) { // 0x001F | 74 | } else if ((type & 0xFFE) == 0xFF8) { // 0x001F |
| 72 | // Mapped memory range | 75 | // Mapped memory range |
| 73 | if (i+1 >= len || ((kernel_caps[i+1] >> 20) & 0xFFE) != 0xFF8) { | 76 | if (i + 1 >= len || ((kernel_caps[i + 1] >> 20) & 0xFFE) != 0xFF8) { |
| 74 | LOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored."); | 77 | LOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored."); |
| 75 | continue; | 78 | continue; |
| 76 | } | 79 | } |
| 77 | u32 end_desc = kernel_caps[i+1]; | 80 | u32 end_desc = kernel_caps[i + 1]; |
| 78 | ++i; // Skip over the second descriptor on the next iteration | 81 | ++i; // Skip over the second descriptor on the next iteration |
| 79 | 82 | ||
| 80 | AddressMapping mapping; | 83 | AddressMapping mapping; |
| @@ -107,23 +110,28 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) { | |||
| 107 | void Process::Run(s32 main_thread_priority, u32 stack_size) { | 110 | void Process::Run(s32 main_thread_priority, u32 stack_size) { |
| 108 | memory_region = GetMemoryRegion(flags.memory_region); | 111 | memory_region = GetMemoryRegion(flags.memory_region); |
| 109 | 112 | ||
| 110 | auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, MemoryState memory_state) { | 113 | auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, |
| 111 | auto vma = vm_manager.MapMemoryBlock(segment.addr, codeset->memory, | 114 | MemoryState memory_state) { |
| 112 | segment.offset, segment.size, memory_state).Unwrap(); | 115 | auto vma = vm_manager |
| 116 | .MapMemoryBlock(segment.addr, codeset->memory, segment.offset, segment.size, | ||
| 117 | memory_state) | ||
| 118 | .Unwrap(); | ||
| 113 | vm_manager.Reprotect(vma, permissions); | 119 | vm_manager.Reprotect(vma, permissions); |
| 114 | misc_memory_used += segment.size; | 120 | misc_memory_used += segment.size; |
| 115 | memory_region->used += segment.size; | 121 | memory_region->used += segment.size; |
| 116 | }; | 122 | }; |
| 117 | 123 | ||
| 118 | // Map CodeSet segments | 124 | // Map CodeSet segments |
| 119 | MapSegment(codeset->code, VMAPermission::ReadExecute, MemoryState::Code); | 125 | MapSegment(codeset->code, VMAPermission::ReadExecute, MemoryState::Code); |
| 120 | MapSegment(codeset->rodata, VMAPermission::Read, MemoryState::Code); | 126 | MapSegment(codeset->rodata, VMAPermission::Read, MemoryState::Code); |
| 121 | MapSegment(codeset->data, VMAPermission::ReadWrite, MemoryState::Private); | 127 | MapSegment(codeset->data, VMAPermission::ReadWrite, MemoryState::Private); |
| 122 | 128 | ||
| 123 | // Allocate and map stack | 129 | // Allocate and map stack |
| 124 | vm_manager.MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size, | 130 | vm_manager |
| 125 | std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, MemoryState::Locked | 131 | .MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size, |
| 126 | ).Unwrap(); | 132 | std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, |
| 133 | MemoryState::Locked) | ||
| 134 | .Unwrap(); | ||
| 127 | misc_memory_used += stack_size; | 135 | misc_memory_used += stack_size; |
| 128 | memory_region->used += stack_size; | 136 | memory_region->used += stack_size; |
| 129 | 137 | ||
| @@ -143,7 +151,8 @@ VAddr Process::GetLinearHeapLimit() const { | |||
| 143 | } | 151 | } |
| 144 | 152 | ||
| 145 | ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission perms) { | 153 | ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission perms) { |
| 146 | if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || target + size < target) { | 154 | if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || |
| 155 | target + size < target) { | ||
| 147 | return ERR_INVALID_ADDRESS; | 156 | return ERR_INVALID_ADDRESS; |
| 148 | } | 157 | } |
| 149 | 158 | ||
| @@ -166,7 +175,8 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per | |||
| 166 | } | 175 | } |
| 167 | ASSERT(heap_end - heap_start == heap_memory->size()); | 176 | ASSERT(heap_end - heap_start == heap_memory->size()); |
| 168 | 177 | ||
| 169 | CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, heap_memory, target - heap_start, size, MemoryState::Private)); | 178 | CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, heap_memory, target - heap_start, |
| 179 | size, MemoryState::Private)); | ||
| 170 | vm_manager.Reprotect(vma, perms); | 180 | vm_manager.Reprotect(vma, perms); |
| 171 | 181 | ||
| 172 | heap_used += size; | 182 | heap_used += size; |
| @@ -176,7 +186,8 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per | |||
| 176 | } | 186 | } |
| 177 | 187 | ||
| 178 | ResultCode Process::HeapFree(VAddr target, u32 size) { | 188 | ResultCode Process::HeapFree(VAddr target, u32 size) { |
| 179 | if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || target + size < target) { | 189 | if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || |
| 190 | target + size < target) { | ||
| 180 | return ERR_INVALID_ADDRESS; | 191 | return ERR_INVALID_ADDRESS; |
| 181 | } | 192 | } |
| 182 | 193 | ||
| @@ -185,7 +196,8 @@ ResultCode Process::HeapFree(VAddr target, u32 size) { | |||
| 185 | } | 196 | } |
| 186 | 197 | ||
| 187 | ResultCode result = vm_manager.UnmapRange(target, size); | 198 | ResultCode result = vm_manager.UnmapRange(target, size); |
| 188 | if (result.IsError()) return result; | 199 | if (result.IsError()) |
| 200 | return result; | ||
| 189 | 201 | ||
| 190 | heap_used -= size; | 202 | heap_used -= size; |
| 191 | memory_region->used -= size; | 203 | memory_region->used -= size; |
| @@ -203,8 +215,8 @@ ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission p | |||
| 203 | target = heap_end; | 215 | target = heap_end; |
| 204 | } | 216 | } |
| 205 | 217 | ||
| 206 | if (target < GetLinearHeapBase() || target + size > GetLinearHeapLimit() || | 218 | if (target < GetLinearHeapBase() || target + size > GetLinearHeapLimit() || target > heap_end || |
| 207 | target > heap_end || target + size < target) { | 219 | target + size < target) { |
| 208 | 220 | ||
| 209 | return ERR_INVALID_ADDRESS; | 221 | return ERR_INVALID_ADDRESS; |
| 210 | } | 222 | } |
| @@ -220,7 +232,8 @@ ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission p | |||
| 220 | // TODO(yuriks): As is, this lets processes map memory allocated by other processes from the | 232 | // TODO(yuriks): As is, this lets processes map memory allocated by other processes from the |
| 221 | // same region. It is unknown if or how the 3DS kernel checks against this. | 233 | // same region. It is unknown if or how the 3DS kernel checks against this. |
| 222 | size_t offset = target - GetLinearHeapBase(); | 234 | size_t offset = target - GetLinearHeapBase(); |
| 223 | CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, linheap_memory, offset, size, MemoryState::Continuous)); | 235 | CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, linheap_memory, offset, size, |
| 236 | MemoryState::Continuous)); | ||
| 224 | vm_manager.Reprotect(vma, perms); | 237 | vm_manager.Reprotect(vma, perms); |
| 225 | 238 | ||
| 226 | linear_heap_used += size; | 239 | linear_heap_used += size; |
| @@ -248,7 +261,8 @@ ResultCode Process::LinearFree(VAddr target, u32 size) { | |||
| 248 | } | 261 | } |
| 249 | 262 | ||
| 250 | ResultCode result = vm_manager.UnmapRange(target, size); | 263 | ResultCode result = vm_manager.UnmapRange(target, size); |
| 251 | if (result.IsError()) return result; | 264 | if (result.IsError()) |
| 265 | return result; | ||
| 252 | 266 | ||
| 253 | linear_heap_used -= size; | 267 | linear_heap_used -= size; |
| 254 | memory_region->used -= size; | 268 | memory_region->used -= size; |
| @@ -268,9 +282,10 @@ ResultCode Process::LinearFree(VAddr target, u32 size) { | |||
| 268 | return RESULT_SUCCESS; | 282 | return RESULT_SUCCESS; |
| 269 | } | 283 | } |
| 270 | 284 | ||
| 271 | Kernel::Process::Process() {} | 285 | Kernel::Process::Process() { |
| 272 | Kernel::Process::~Process() {} | 286 | } |
| 287 | Kernel::Process::~Process() { | ||
| 288 | } | ||
| 273 | 289 | ||
| 274 | SharedPtr<Process> g_current_process; | 290 | SharedPtr<Process> g_current_process; |
| 275 | |||
| 276 | } | 291 | } |
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index d781ef32c..070b2b558 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h | |||
| @@ -36,15 +36,18 @@ enum class MemoryRegion : u16 { | |||
| 36 | union ProcessFlags { | 36 | union ProcessFlags { |
| 37 | u16 raw; | 37 | u16 raw; |
| 38 | 38 | ||
| 39 | BitField< 0, 1, u16> allow_debug; ///< Allows other processes to attach to and debug this process. | 39 | BitField<0, 1, u16> |
| 40 | BitField< 1, 1, u16> force_debug; ///< Allows this process to attach to processes even if they don't have allow_debug set. | 40 | allow_debug; ///< Allows other processes to attach to and debug this process. |
| 41 | BitField< 2, 1, u16> allow_nonalphanum; | 41 | BitField<1, 1, u16> force_debug; ///< Allows this process to attach to processes even if they |
| 42 | BitField< 3, 1, u16> shared_page_writable; ///< Shared page is mapped with write permissions. | 42 | /// don't have allow_debug set. |
| 43 | BitField< 4, 1, u16> privileged_priority; ///< Can use priority levels higher than 24. | 43 | BitField<2, 1, u16> allow_nonalphanum; |
| 44 | BitField< 5, 1, u16> allow_main_args; | 44 | BitField<3, 1, u16> shared_page_writable; ///< Shared page is mapped with write permissions. |
| 45 | BitField< 6, 1, u16> shared_device_mem; | 45 | BitField<4, 1, u16> privileged_priority; ///< Can use priority levels higher than 24. |
| 46 | BitField< 7, 1, u16> runnable_on_sleep; | 46 | BitField<5, 1, u16> allow_main_args; |
| 47 | BitField< 8, 4, MemoryRegion> memory_region; ///< Default region for memory allocations for this process | 47 | BitField<6, 1, u16> shared_device_mem; |
| 48 | BitField<7, 1, u16> runnable_on_sleep; | ||
| 49 | BitField<8, 4, MemoryRegion> | ||
| 50 | memory_region; ///< Default region for memory allocations for this process | ||
| 48 | BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000). | 51 | BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000). |
| 49 | }; | 52 | }; |
| 50 | 53 | ||
| @@ -54,11 +57,17 @@ struct MemoryRegionInfo; | |||
| 54 | struct CodeSet final : public Object { | 57 | struct CodeSet final : public Object { |
| 55 | static SharedPtr<CodeSet> Create(std::string name, u64 program_id); | 58 | static SharedPtr<CodeSet> Create(std::string name, u64 program_id); |
| 56 | 59 | ||
| 57 | std::string GetTypeName() const override { return "CodeSet"; } | 60 | std::string GetTypeName() const override { |
| 58 | std::string GetName() const override { return name; } | 61 | return "CodeSet"; |
| 62 | } | ||
| 63 | std::string GetName() const override { | ||
| 64 | return name; | ||
| 65 | } | ||
| 59 | 66 | ||
| 60 | static const HandleType HANDLE_TYPE = HandleType::CodeSet; | 67 | static const HandleType HANDLE_TYPE = HandleType::CodeSet; |
| 61 | HandleType GetHandleType() const override { return HANDLE_TYPE; } | 68 | HandleType GetHandleType() const override { |
| 69 | return HANDLE_TYPE; | ||
| 70 | } | ||
| 62 | 71 | ||
| 63 | /// Name of the process | 72 | /// Name of the process |
| 64 | std::string name; | 73 | std::string name; |
| @@ -85,11 +94,17 @@ class Process final : public Object { | |||
| 85 | public: | 94 | public: |
| 86 | static SharedPtr<Process> Create(SharedPtr<CodeSet> code_set); | 95 | static SharedPtr<Process> Create(SharedPtr<CodeSet> code_set); |
| 87 | 96 | ||
| 88 | std::string GetTypeName() const override { return "Process"; } | 97 | std::string GetTypeName() const override { |
| 89 | std::string GetName() const override { return codeset->name; } | 98 | return "Process"; |
| 99 | } | ||
| 100 | std::string GetName() const override { | ||
| 101 | return codeset->name; | ||
| 102 | } | ||
| 90 | 103 | ||
| 91 | static const HandleType HANDLE_TYPE = HandleType::Process; | 104 | static const HandleType HANDLE_TYPE = HandleType::Process; |
| 92 | HandleType GetHandleType() const override { return HANDLE_TYPE; } | 105 | HandleType GetHandleType() const override { |
| 106 | return HANDLE_TYPE; | ||
| 107 | } | ||
| 93 | 108 | ||
| 94 | static u32 next_process_id; | 109 | static u32 next_process_id; |
| 95 | 110 | ||
| @@ -124,7 +139,6 @@ public: | |||
| 124 | */ | 139 | */ |
| 125 | void Run(s32 main_thread_priority, u32 stack_size); | 140 | void Run(s32 main_thread_priority, u32 stack_size); |
| 126 | 141 | ||
| 127 | |||
| 128 | /////////////////////////////////////////////////////////////////////////////////////////////// | 142 | /////////////////////////////////////////////////////////////////////////////////////////////// |
| 129 | // Memory Management | 143 | // Memory Management |
| 130 | 144 | ||
| @@ -144,7 +158,8 @@ public: | |||
| 144 | 158 | ||
| 145 | /// The Thread Local Storage area is allocated as processes create threads, | 159 | /// The Thread Local Storage area is allocated as processes create threads, |
| 146 | /// each TLS area is 0x200 bytes, so one page (0x1000) is split up in 8 parts, and each part | 160 | /// each TLS area is 0x200 bytes, so one page (0x1000) is split up in 8 parts, and each part |
| 147 | /// holds the TLS for a specific thread. This vector contains which parts are in use for each page as a bitmask. | 161 | /// holds the TLS for a specific thread. This vector contains which parts are in use for each |
| 162 | /// page as a bitmask. | ||
| 148 | /// This vector will grow as more pages are allocated for new threads. | 163 | /// This vector will grow as more pages are allocated for new threads. |
| 149 | std::vector<std::bitset<8>> tls_slots; | 164 | std::vector<std::bitset<8>> tls_slots; |
| 150 | 165 | ||
| @@ -164,5 +179,4 @@ private: | |||
| 164 | }; | 179 | }; |
| 165 | 180 | ||
| 166 | extern SharedPtr<Process> g_current_process; | 181 | extern SharedPtr<Process> g_current_process; |
| 167 | |||
| 168 | } | 182 | } |
diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp index 67dde08c2..7bd1c1e08 100644 --- a/src/core/hle/kernel/resource_limit.cpp +++ b/src/core/hle/kernel/resource_limit.cpp | |||
| @@ -12,8 +12,10 @@ namespace Kernel { | |||
| 12 | 12 | ||
| 13 | static SharedPtr<ResourceLimit> resource_limits[4]; | 13 | static SharedPtr<ResourceLimit> resource_limits[4]; |
| 14 | 14 | ||
| 15 | ResourceLimit::ResourceLimit() {} | 15 | ResourceLimit::ResourceLimit() { |
| 16 | ResourceLimit::~ResourceLimit() {} | 16 | } |
| 17 | ResourceLimit::~ResourceLimit() { | ||
| 18 | } | ||
| 17 | 19 | ||
| 18 | SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) { | 20 | SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) { |
| 19 | SharedPtr<ResourceLimit> resource_limit(new ResourceLimit); | 21 | SharedPtr<ResourceLimit> resource_limit(new ResourceLimit); |
| @@ -23,70 +25,69 @@ SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) { | |||
| 23 | } | 25 | } |
| 24 | 26 | ||
| 25 | SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) { | 27 | SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) { |
| 26 | switch (category) | 28 | switch (category) { |
| 27 | { | 29 | case ResourceLimitCategory::APPLICATION: |
| 28 | case ResourceLimitCategory::APPLICATION: | 30 | case ResourceLimitCategory::SYS_APPLET: |
| 29 | case ResourceLimitCategory::SYS_APPLET: | 31 | case ResourceLimitCategory::LIB_APPLET: |
| 30 | case ResourceLimitCategory::LIB_APPLET: | 32 | case ResourceLimitCategory::OTHER: |
| 31 | case ResourceLimitCategory::OTHER: | 33 | return resource_limits[static_cast<u8>(category)]; |
| 32 | return resource_limits[static_cast<u8>(category)]; | 34 | default: |
| 33 | default: | 35 | LOG_CRITICAL(Kernel, "Unknown resource limit category"); |
| 34 | LOG_CRITICAL(Kernel, "Unknown resource limit category"); | 36 | UNREACHABLE(); |
| 35 | UNREACHABLE(); | ||
| 36 | } | 37 | } |
| 37 | } | 38 | } |
| 38 | 39 | ||
| 39 | s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const { | 40 | s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const { |
| 40 | switch (resource) { | 41 | switch (resource) { |
| 41 | case COMMIT: | 42 | case COMMIT: |
| 42 | return current_commit; | 43 | return current_commit; |
| 43 | case THREAD: | 44 | case THREAD: |
| 44 | return current_threads; | 45 | return current_threads; |
| 45 | case EVENT: | 46 | case EVENT: |
| 46 | return current_events; | 47 | return current_events; |
| 47 | case MUTEX: | 48 | case MUTEX: |
| 48 | return current_mutexes; | 49 | return current_mutexes; |
| 49 | case SEMAPHORE: | 50 | case SEMAPHORE: |
| 50 | return current_semaphores; | 51 | return current_semaphores; |
| 51 | case TIMER: | 52 | case TIMER: |
| 52 | return current_timers; | 53 | return current_timers; |
| 53 | case SHARED_MEMORY: | 54 | case SHARED_MEMORY: |
| 54 | return current_shared_mems; | 55 | return current_shared_mems; |
| 55 | case ADDRESS_ARBITER: | 56 | case ADDRESS_ARBITER: |
| 56 | return current_address_arbiters; | 57 | return current_address_arbiters; |
| 57 | case CPU_TIME: | 58 | case CPU_TIME: |
| 58 | return current_cpu_time; | 59 | return current_cpu_time; |
| 59 | default: | 60 | default: |
| 60 | LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); | 61 | LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); |
| 61 | UNIMPLEMENTED(); | 62 | UNIMPLEMENTED(); |
| 62 | return 0; | 63 | return 0; |
| 63 | } | 64 | } |
| 64 | } | 65 | } |
| 65 | 66 | ||
| 66 | s32 ResourceLimit::GetMaxResourceValue(u32 resource) const { | 67 | s32 ResourceLimit::GetMaxResourceValue(u32 resource) const { |
| 67 | switch (resource) { | 68 | switch (resource) { |
| 68 | case COMMIT: | 69 | case COMMIT: |
| 69 | return max_commit; | 70 | return max_commit; |
| 70 | case THREAD: | 71 | case THREAD: |
| 71 | return max_threads; | 72 | return max_threads; |
| 72 | case EVENT: | 73 | case EVENT: |
| 73 | return max_events; | 74 | return max_events; |
| 74 | case MUTEX: | 75 | case MUTEX: |
| 75 | return max_mutexes; | 76 | return max_mutexes; |
| 76 | case SEMAPHORE: | 77 | case SEMAPHORE: |
| 77 | return max_semaphores; | 78 | return max_semaphores; |
| 78 | case TIMER: | 79 | case TIMER: |
| 79 | return max_timers; | 80 | return max_timers; |
| 80 | case SHARED_MEMORY: | 81 | case SHARED_MEMORY: |
| 81 | return max_shared_mems; | 82 | return max_shared_mems; |
| 82 | case ADDRESS_ARBITER: | 83 | case ADDRESS_ARBITER: |
| 83 | return max_address_arbiters; | 84 | return max_address_arbiters; |
| 84 | case CPU_TIME: | 85 | case CPU_TIME: |
| 85 | return max_cpu_time; | 86 | return max_cpu_time; |
| 86 | default: | 87 | default: |
| 87 | LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); | 88 | LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); |
| 88 | UNIMPLEMENTED(); | 89 | UNIMPLEMENTED(); |
| 89 | return 0; | 90 | return 0; |
| 90 | } | 91 | } |
| 91 | } | 92 | } |
| 92 | 93 | ||
| @@ -150,7 +151,6 @@ void ResourceLimitsInit() { | |||
| 150 | } | 151 | } |
| 151 | 152 | ||
| 152 | void ResourceLimitsShutdown() { | 153 | void ResourceLimitsShutdown() { |
| 153 | |||
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | } // namespace | 156 | } // namespace |
diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h index 1b8249c74..c08e744e6 100644 --- a/src/core/hle/kernel/resource_limit.h +++ b/src/core/hle/kernel/resource_limit.h | |||
| @@ -12,22 +12,22 @@ namespace Kernel { | |||
| 12 | 12 | ||
| 13 | enum class ResourceLimitCategory : u8 { | 13 | enum class ResourceLimitCategory : u8 { |
| 14 | APPLICATION = 0, | 14 | APPLICATION = 0, |
| 15 | SYS_APPLET = 1, | 15 | SYS_APPLET = 1, |
| 16 | LIB_APPLET = 2, | 16 | LIB_APPLET = 2, |
| 17 | OTHER = 3 | 17 | OTHER = 3 |
| 18 | }; | 18 | }; |
| 19 | 19 | ||
| 20 | enum ResourceTypes { | 20 | enum ResourceTypes { |
| 21 | PRIORITY = 0, | 21 | PRIORITY = 0, |
| 22 | COMMIT = 1, | 22 | COMMIT = 1, |
| 23 | THREAD = 2, | 23 | THREAD = 2, |
| 24 | EVENT = 3, | 24 | EVENT = 3, |
| 25 | MUTEX = 4, | 25 | MUTEX = 4, |
| 26 | SEMAPHORE = 5, | 26 | SEMAPHORE = 5, |
| 27 | TIMER = 6, | 27 | TIMER = 6, |
| 28 | SHARED_MEMORY = 7, | 28 | SHARED_MEMORY = 7, |
| 29 | ADDRESS_ARBITER = 8, | 29 | ADDRESS_ARBITER = 8, |
| 30 | CPU_TIME = 9, | 30 | CPU_TIME = 9, |
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| 33 | class ResourceLimit final : public Object { | 33 | class ResourceLimit final : public Object { |
| @@ -44,11 +44,17 @@ public: | |||
| 44 | */ | 44 | */ |
| 45 | static SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category); | 45 | static SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category); |
| 46 | 46 | ||
| 47 | std::string GetTypeName() const override { return "ResourceLimit"; } | 47 | std::string GetTypeName() const override { |
| 48 | std::string GetName() const override { return name; } | 48 | return "ResourceLimit"; |
| 49 | } | ||
| 50 | std::string GetName() const override { | ||
| 51 | return name; | ||
| 52 | } | ||
| 49 | 53 | ||
| 50 | static const HandleType HANDLE_TYPE = HandleType::ResourceLimit; | 54 | static const HandleType HANDLE_TYPE = HandleType::ResourceLimit; |
| 51 | HandleType GetHandleType() const override { return HANDLE_TYPE; } | 55 | HandleType GetHandleType() const override { |
| 56 | return HANDLE_TYPE; | ||
| 57 | } | ||
| 52 | 58 | ||
| 53 | /** | 59 | /** |
| 54 | * Gets the current value for the specified resource. | 60 | * Gets the current value for the specified resource. |
| @@ -85,10 +91,12 @@ public: | |||
| 85 | /// Max CPU time that the processes in this category can utilize | 91 | /// Max CPU time that the processes in this category can utilize |
| 86 | s32 max_cpu_time = 0; | 92 | s32 max_cpu_time = 0; |
| 87 | 93 | ||
| 88 | // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind that | 94 | // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind |
| 95 | // that | ||
| 89 | // APPLICATION resource limits should not be affected by the objects created by service modules. | 96 | // APPLICATION resource limits should not be affected by the objects created by service modules. |
| 90 | // Currently we have no way of distinguishing if a Create was called by the running application, | 97 | // Currently we have no way of distinguishing if a Create was called by the running application, |
| 91 | // or by a service module. Approach this once we have separated the service modules into their own processes | 98 | // or by a service module. Approach this once we have separated the service modules into their |
| 99 | // own processes | ||
| 92 | 100 | ||
| 93 | /// Current memory that the processes in this category are using | 101 | /// Current memory that the processes in this category are using |
| 94 | s32 current_commit = 0; | 102 | s32 current_commit = 0; |
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp index 4b359ed07..71e41079b 100644 --- a/src/core/hle/kernel/semaphore.cpp +++ b/src/core/hle/kernel/semaphore.cpp | |||
| @@ -10,11 +10,13 @@ | |||
| 10 | 10 | ||
| 11 | namespace Kernel { | 11 | namespace Kernel { |
| 12 | 12 | ||
| 13 | Semaphore::Semaphore() {} | 13 | Semaphore::Semaphore() { |
| 14 | Semaphore::~Semaphore() {} | 14 | } |
| 15 | Semaphore::~Semaphore() { | ||
| 16 | } | ||
| 15 | 17 | ||
| 16 | ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, | 18 | ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, |
| 17 | std::string name) { | 19 | std::string name) { |
| 18 | 20 | ||
| 19 | if (initial_count > max_count) | 21 | if (initial_count > max_count) |
| 20 | return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, | 22 | return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, |
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h index 390f5e495..ed7d9a85c 100644 --- a/src/core/hle/kernel/semaphore.h +++ b/src/core/hle/kernel/semaphore.h | |||
| @@ -23,17 +23,23 @@ public: | |||
| 23 | * @return The created semaphore | 23 | * @return The created semaphore |
| 24 | */ | 24 | */ |
| 25 | static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count, | 25 | static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count, |
| 26 | std::string name = "Unknown"); | 26 | std::string name = "Unknown"); |
| 27 | 27 | ||
| 28 | std::string GetTypeName() const override { return "Semaphore"; } | 28 | std::string GetTypeName() const override { |
| 29 | std::string GetName() const override { return name; } | 29 | return "Semaphore"; |
| 30 | } | ||
| 31 | std::string GetName() const override { | ||
| 32 | return name; | ||
| 33 | } | ||
| 30 | 34 | ||
| 31 | static const HandleType HANDLE_TYPE = HandleType::Semaphore; | 35 | static const HandleType HANDLE_TYPE = HandleType::Semaphore; |
| 32 | HandleType GetHandleType() const override { return HANDLE_TYPE; } | 36 | HandleType GetHandleType() const override { |
| 37 | return HANDLE_TYPE; | ||
| 38 | } | ||
| 33 | 39 | ||
| 34 | s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have | 40 | s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have |
| 35 | s32 available_count; ///< Number of free slots left in the semaphore | 41 | s32 available_count; ///< Number of free slots left in the semaphore |
| 36 | std::string name; ///< Name of semaphore (optional) | 42 | std::string name; ///< Name of semaphore (optional) |
| 37 | 43 | ||
| 38 | bool ShouldWait() override; | 44 | bool ShouldWait() override; |
| 39 | void Acquire() override; | 45 | void Acquire() override; |
diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp index fcc684a20..7c690fa7f 100644 --- a/src/core/hle/kernel/server_port.cpp +++ b/src/core/hle/kernel/server_port.cpp | |||
| @@ -13,8 +13,10 @@ | |||
| 13 | 13 | ||
| 14 | namespace Kernel { | 14 | namespace Kernel { |
| 15 | 15 | ||
| 16 | ServerPort::ServerPort() {} | 16 | ServerPort::ServerPort() { |
| 17 | ServerPort::~ServerPort() {} | 17 | } |
| 18 | ServerPort::~ServerPort() { | ||
| 19 | } | ||
| 18 | 20 | ||
| 19 | bool ServerPort::ShouldWait() { | 21 | bool ServerPort::ShouldWait() { |
| 20 | // If there are no pending sessions, we wait until a new one is added. | 22 | // If there are no pending sessions, we wait until a new one is added. |
| @@ -25,7 +27,8 @@ void ServerPort::Acquire() { | |||
| 25 | ASSERT_MSG(!ShouldWait(), "object unavailable!"); | 27 | ASSERT_MSG(!ShouldWait(), "object unavailable!"); |
| 26 | } | 28 | } |
| 27 | 29 | ||
| 28 | std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair(u32 max_sessions, std::string name) { | 30 | std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> |
| 31 | ServerPort::CreatePortPair(u32 max_sessions, std::string name) { | ||
| 29 | SharedPtr<ServerPort> server_port(new ServerPort); | 32 | SharedPtr<ServerPort> server_port(new ServerPort); |
| 30 | SharedPtr<ClientPort> client_port(new ClientPort); | 33 | SharedPtr<ClientPort> client_port(new ClientPort); |
| 31 | 34 | ||
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h index e9c972ce6..e43d48674 100644 --- a/src/core/hle/kernel/server_port.h +++ b/src/core/hle/kernel/server_port.h | |||
| @@ -23,17 +23,25 @@ public: | |||
| 23 | * @param name Optional name of the ports | 23 | * @param name Optional name of the ports |
| 24 | * @return The created port tuple | 24 | * @return The created port tuple |
| 25 | */ | 25 | */ |
| 26 | static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(u32 max_sessions, std::string name = "UnknownPort"); | 26 | static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> |
| 27 | CreatePortPair(u32 max_sessions, std::string name = "UnknownPort"); | ||
| 27 | 28 | ||
| 28 | std::string GetTypeName() const override { return "ServerPort"; } | 29 | std::string GetTypeName() const override { |
| 29 | std::string GetName() const override { return name; } | 30 | return "ServerPort"; |
| 31 | } | ||
| 32 | std::string GetName() const override { | ||
| 33 | return name; | ||
| 34 | } | ||
| 30 | 35 | ||
| 31 | static const HandleType HANDLE_TYPE = HandleType::ServerPort; | 36 | static const HandleType HANDLE_TYPE = HandleType::ServerPort; |
| 32 | HandleType GetHandleType() const override { return HANDLE_TYPE; } | 37 | HandleType GetHandleType() const override { |
| 38 | return HANDLE_TYPE; | ||
| 39 | } | ||
| 33 | 40 | ||
| 34 | std::string name; ///< Name of port (optional) | 41 | std::string name; ///< Name of port (optional) |
| 35 | 42 | ||
| 36 | std::vector<SharedPtr<WaitObject>> pending_sessions; ///< ServerSessions waiting to be accepted by the port | 43 | std::vector<SharedPtr<WaitObject>> |
| 44 | pending_sessions; ///< ServerSessions waiting to be accepted by the port | ||
| 37 | 45 | ||
| 38 | bool ShouldWait() override; | 46 | bool ShouldWait() override; |
| 39 | void Acquire() override; | 47 | void Acquire() override; |
diff --git a/src/core/hle/kernel/session.cpp b/src/core/hle/kernel/session.cpp index 0594967f8..61457845a 100644 --- a/src/core/hle/kernel/session.cpp +++ b/src/core/hle/kernel/session.cpp | |||
| @@ -7,7 +7,8 @@ | |||
| 7 | 7 | ||
| 8 | namespace Kernel { | 8 | namespace Kernel { |
| 9 | 9 | ||
| 10 | Session::Session() {} | 10 | Session::Session() { |
| 11 | Session::~Session() {} | 11 | } |
| 12 | 12 | Session::~Session() { | |
| 13 | } | ||
| 13 | } | 14 | } |
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h index 8ec889967..8e4e010b8 100644 --- a/src/core/hle/kernel/session.h +++ b/src/core/hle/kernel/session.h | |||
| @@ -19,12 +19,13 @@ namespace IPC { | |||
| 19 | enum DescriptorType : u32 { | 19 | enum DescriptorType : u32 { |
| 20 | // Buffer related desciptors types (mask : 0x0F) | 20 | // Buffer related desciptors types (mask : 0x0F) |
| 21 | StaticBuffer = 0x02, | 21 | StaticBuffer = 0x02, |
| 22 | PXIBuffer = 0x04, | 22 | PXIBuffer = 0x04, |
| 23 | MappedBuffer = 0x08, | 23 | MappedBuffer = 0x08, |
| 24 | // Handle related descriptors types (mask : 0x30, but need to check for buffer related descriptors first ) | 24 | // Handle related descriptors types (mask : 0x30, but need to check for buffer related |
| 25 | CopyHandle = 0x00, | 25 | // descriptors first ) |
| 26 | MoveHandle = 0x10, | 26 | CopyHandle = 0x00, |
| 27 | CallingPid = 0x20, | 27 | MoveHandle = 0x10, |
| 28 | CallingPid = 0x20, | ||
| 28 | }; | 29 | }; |
| 29 | 30 | ||
| 30 | /** | 31 | /** |
| @@ -34,24 +35,28 @@ enum DescriptorType : u32 { | |||
| 34 | * @param translate_params_size Size of the translate parameters in words. Up to 63. | 35 | * @param translate_params_size Size of the translate parameters in words. Up to 63. |
| 35 | * @return The created IPC header. | 36 | * @return The created IPC header. |
| 36 | * | 37 | * |
| 37 | * Normal parameters are sent directly to the process while the translate parameters might go through modifications and checks by the kernel. | 38 | * Normal parameters are sent directly to the process while the translate parameters might go |
| 39 | * through modifications and checks by the kernel. | ||
| 38 | * The translate parameters are described by headers generated with the IPC::*Desc functions. | 40 | * The translate parameters are described by headers generated with the IPC::*Desc functions. |
| 39 | * | 41 | * |
| 40 | * @note While #normal_params is equivalent to the number of normal parameters, #translate_params_size includes the size occupied by the translate parameters headers. | 42 | * @note While #normal_params is equivalent to the number of normal parameters, |
| 43 | * #translate_params_size includes the size occupied by the translate parameters headers. | ||
| 41 | */ | 44 | */ |
| 42 | constexpr u32 MakeHeader(u16 command_id, unsigned int normal_params, unsigned int translate_params_size) { | 45 | constexpr u32 MakeHeader(u16 command_id, unsigned int normal_params, |
| 43 | return (u32(command_id) << 16) | ((u32(normal_params) & 0x3F) << 6) | (u32(translate_params_size) & 0x3F); | 46 | unsigned int translate_params_size) { |
| 47 | return (u32(command_id) << 16) | ((u32(normal_params) & 0x3F) << 6) | | ||
| 48 | (u32(translate_params_size) & 0x3F); | ||
| 44 | } | 49 | } |
| 45 | 50 | ||
| 46 | union Header { | 51 | union Header { |
| 47 | u32 raw; | 52 | u32 raw; |
| 48 | BitField< 0, 6, u32> translate_params_size; | 53 | BitField<0, 6, u32> translate_params_size; |
| 49 | BitField< 6, 6, u32> normal_params; | 54 | BitField<6, 6, u32> normal_params; |
| 50 | BitField<16, 16, u32> command_id; | 55 | BitField<16, 16, u32> command_id; |
| 51 | }; | 56 | }; |
| 52 | 57 | ||
| 53 | inline Header ParseHeader(u32 header) { | 58 | inline Header ParseHeader(u32 header) { |
| 54 | return{ header }; | 59 | return {header}; |
| 55 | } | 60 | } |
| 56 | 61 | ||
| 57 | constexpr u32 MoveHandleDesc(u32 num_handles = 1) { | 62 | constexpr u32 MoveHandleDesc(u32 num_handles = 1) { |
| @@ -80,27 +85,29 @@ constexpr u32 StaticBufferDesc(u32 size, u8 buffer_id) { | |||
| 80 | 85 | ||
| 81 | union StaticBufferDescInfo { | 86 | union StaticBufferDescInfo { |
| 82 | u32 raw; | 87 | u32 raw; |
| 83 | BitField< 10, 4, u32> buffer_id; | 88 | BitField<10, 4, u32> buffer_id; |
| 84 | BitField< 14, 18, u32> size; | 89 | BitField<14, 18, u32> size; |
| 85 | }; | 90 | }; |
| 86 | 91 | ||
| 87 | inline StaticBufferDescInfo ParseStaticBufferDesc(const u32 desc) { | 92 | inline StaticBufferDescInfo ParseStaticBufferDesc(const u32 desc) { |
| 88 | return{ desc }; | 93 | return {desc}; |
| 89 | } | 94 | } |
| 90 | 95 | ||
| 91 | /** | 96 | /** |
| 92 | * @brief Creates a header describing a buffer to be sent over PXI. | 97 | * @brief Creates a header describing a buffer to be sent over PXI. |
| 93 | * @param size Size of the buffer. Max 0x00FFFFFF. | 98 | * @param size Size of the buffer. Max 0x00FFFFFF. |
| 94 | * @param buffer_id The Id of the buffer. Max 0xF. | 99 | * @param buffer_id The Id of the buffer. Max 0xF. |
| 95 | * @param is_read_only true if the buffer is read-only. If false, the buffer is considered to have read-write access. | 100 | * @param is_read_only true if the buffer is read-only. If false, the buffer is considered to have |
| 101 | * read-write access. | ||
| 96 | * @return The created PXI buffer header. | 102 | * @return The created PXI buffer header. |
| 97 | * | 103 | * |
| 98 | * The next value is a phys-address of a table located in the BASE memregion. | 104 | * The next value is a phys-address of a table located in the BASE memregion. |
| 99 | */ | 105 | */ |
| 100 | inline u32 PXIBufferDesc(u32 size, unsigned buffer_id, bool is_read_only) { | 106 | inline u32 PXIBufferDesc(u32 size, unsigned buffer_id, bool is_read_only) { |
| 101 | u32 type = PXIBuffer; | 107 | u32 type = PXIBuffer; |
| 102 | if (is_read_only) type |= 0x2; | 108 | if (is_read_only) |
| 103 | return type | (size << 8) | ((buffer_id & 0xF) << 4); | 109 | type |= 0x2; |
| 110 | return type | (size << 8) | ((buffer_id & 0xF) << 4); | ||
| 104 | } | 111 | } |
| 105 | 112 | ||
| 106 | enum MappedBufferPermissions { | 113 | enum MappedBufferPermissions { |
| @@ -115,12 +122,12 @@ constexpr u32 MappedBufferDesc(u32 size, MappedBufferPermissions perms) { | |||
| 115 | 122 | ||
| 116 | union MappedBufferDescInfo { | 123 | union MappedBufferDescInfo { |
| 117 | u32 raw; | 124 | u32 raw; |
| 118 | BitField< 4, 28, u32> size; | 125 | BitField<4, 28, u32> size; |
| 119 | BitField< 1, 2, MappedBufferPermissions> perms; | 126 | BitField<1, 2, MappedBufferPermissions> perms; |
| 120 | }; | 127 | }; |
| 121 | 128 | ||
| 122 | inline MappedBufferDescInfo ParseMappedBufferDesc(const u32 desc) { | 129 | inline MappedBufferDescInfo ParseMappedBufferDesc(const u32 desc) { |
| 123 | return{ desc }; | 130 | return {desc}; |
| 124 | } | 131 | } |
| 125 | 132 | ||
| 126 | inline DescriptorType GetDescriptorType(u32 descriptor) { | 133 | inline DescriptorType GetDescriptorType(u32 descriptor) { |
| @@ -153,7 +160,8 @@ static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of | |||
| 153 | * @return Pointer to command buffer | 160 | * @return Pointer to command buffer |
| 154 | */ | 161 | */ |
| 155 | inline u32* GetCommandBuffer(const int offset = 0) { | 162 | inline u32* GetCommandBuffer(const int offset = 0) { |
| 156 | return (u32*)Memory::GetPointer(GetCurrentThread()->GetTLSAddress() + kCommandHeaderOffset + offset); | 163 | return (u32*)Memory::GetPointer(GetCurrentThread()->GetTLSAddress() + kCommandHeaderOffset + |
| 164 | offset); | ||
| 157 | } | 165 | } |
| 158 | 166 | ||
| 159 | /** | 167 | /** |
| @@ -183,10 +191,14 @@ public: | |||
| 183 | Session(); | 191 | Session(); |
| 184 | ~Session() override; | 192 | ~Session() override; |
| 185 | 193 | ||
| 186 | std::string GetTypeName() const override { return "Session"; } | 194 | std::string GetTypeName() const override { |
| 195 | return "Session"; | ||
| 196 | } | ||
| 187 | 197 | ||
| 188 | static const HandleType HANDLE_TYPE = HandleType::Session; | 198 | static const HandleType HANDLE_TYPE = HandleType::Session; |
| 189 | HandleType GetHandleType() const override { return HANDLE_TYPE; } | 199 | HandleType GetHandleType() const override { |
| 200 | return HANDLE_TYPE; | ||
| 201 | } | ||
| 190 | 202 | ||
| 191 | /** | 203 | /** |
| 192 | * Handles a synchronous call to this session using HLE emulation. Emulated <-> emulated calls | 204 | * Handles a synchronous call to this session using HLE emulation. Emulated <-> emulated calls |
| @@ -205,5 +217,4 @@ public: | |||
| 205 | ASSERT_MSG(!ShouldWait(), "object unavailable!"); | 217 | ASSERT_MSG(!ShouldWait(), "object unavailable!"); |
| 206 | } | 218 | } |
| 207 | }; | 219 | }; |
| 208 | |||
| 209 | } | 220 | } |
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index 6a22c8986..74f40930c 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp | |||
| @@ -6,17 +6,21 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | 8 | ||
| 9 | #include "core/memory.h" | ||
| 10 | #include "core/hle/kernel/memory.h" | 9 | #include "core/hle/kernel/memory.h" |
| 11 | #include "core/hle/kernel/shared_memory.h" | 10 | #include "core/hle/kernel/shared_memory.h" |
| 11 | #include "core/memory.h" | ||
| 12 | 12 | ||
| 13 | namespace Kernel { | 13 | namespace Kernel { |
| 14 | 14 | ||
| 15 | SharedMemory::SharedMemory() {} | 15 | SharedMemory::SharedMemory() { |
| 16 | SharedMemory::~SharedMemory() {} | 16 | } |
| 17 | SharedMemory::~SharedMemory() { | ||
| 18 | } | ||
| 17 | 19 | ||
| 18 | SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u32 size, MemoryPermission permissions, | 20 | SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u32 size, |
| 19 | MemoryPermission other_permissions, VAddr address, MemoryRegion region, std::string name) { | 21 | MemoryPermission permissions, |
| 22 | MemoryPermission other_permissions, VAddr address, | ||
| 23 | MemoryRegion region, std::string name) { | ||
| 20 | SharedPtr<SharedMemory> shared_memory(new SharedMemory); | 24 | SharedPtr<SharedMemory> shared_memory(new SharedMemory); |
| 21 | 25 | ||
| 22 | shared_memory->owner_process = owner_process; | 26 | shared_memory->owner_process = owner_process; |
| @@ -31,7 +35,8 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u | |||
| 31 | MemoryRegionInfo* memory_region = GetMemoryRegion(region); | 35 | MemoryRegionInfo* memory_region = GetMemoryRegion(region); |
| 32 | auto& linheap_memory = memory_region->linear_heap_memory; | 36 | auto& linheap_memory = memory_region->linear_heap_memory; |
| 33 | 37 | ||
| 34 | ASSERT_MSG(linheap_memory->size() + size <= memory_region->size, "Not enough space in region to allocate shared memory!"); | 38 | ASSERT_MSG(linheap_memory->size() + size <= memory_region->size, |
| 39 | "Not enough space in region to allocate shared memory!"); | ||
| 35 | 40 | ||
| 36 | shared_memory->backing_block = linheap_memory; | 41 | shared_memory->backing_block = linheap_memory; |
| 37 | shared_memory->backing_block_offset = linheap_memory->size(); | 42 | shared_memory->backing_block_offset = linheap_memory->size(); |
| @@ -39,7 +44,8 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u | |||
| 39 | linheap_memory->insert(linheap_memory->end(), size, 0); | 44 | linheap_memory->insert(linheap_memory->end(), size, 0); |
| 40 | memory_region->used += size; | 45 | memory_region->used += size; |
| 41 | 46 | ||
| 42 | shared_memory->linear_heap_phys_address = Memory::FCRAM_PADDR + memory_region->base + shared_memory->backing_block_offset; | 47 | shared_memory->linear_heap_phys_address = |
| 48 | Memory::FCRAM_PADDR + memory_region->base + shared_memory->backing_block_offset; | ||
| 43 | 49 | ||
| 44 | // Increase the amount of used linear heap memory for the owner process. | 50 | // Increase the amount of used linear heap memory for the owner process. |
| 45 | if (shared_memory->owner_process != nullptr) { | 51 | if (shared_memory->owner_process != nullptr) { |
| @@ -51,18 +57,20 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u | |||
| 51 | Kernel::g_current_process->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get()); | 57 | Kernel::g_current_process->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get()); |
| 52 | } | 58 | } |
| 53 | } else { | 59 | } else { |
| 54 | // TODO(Subv): What happens if an application tries to create multiple memory blocks pointing to the same address? | 60 | // TODO(Subv): What happens if an application tries to create multiple memory blocks |
| 61 | // pointing to the same address? | ||
| 55 | auto& vm_manager = shared_memory->owner_process->vm_manager; | 62 | auto& vm_manager = shared_memory->owner_process->vm_manager; |
| 56 | // The memory is already available and mapped in the owner process. | 63 | // The memory is already available and mapped in the owner process. |
| 57 | auto vma = vm_manager.FindVMA(address)->second; | 64 | auto vma = vm_manager.FindVMA(address)->second; |
| 58 | // Copy it over to our own storage | 65 | // Copy it over to our own storage |
| 59 | shared_memory->backing_block = std::make_shared<std::vector<u8>>(vma.backing_block->data() + vma.offset, | 66 | shared_memory->backing_block = std::make_shared<std::vector<u8>>( |
| 60 | vma.backing_block->data() + vma.offset + size); | 67 | vma.backing_block->data() + vma.offset, vma.backing_block->data() + vma.offset + size); |
| 61 | shared_memory->backing_block_offset = 0; | 68 | shared_memory->backing_block_offset = 0; |
| 62 | // Unmap the existing pages | 69 | // Unmap the existing pages |
| 63 | vm_manager.UnmapRange(address, size); | 70 | vm_manager.UnmapRange(address, size); |
| 64 | // Map our own block into the address space | 71 | // Map our own block into the address space |
| 65 | vm_manager.MapMemoryBlock(address, shared_memory->backing_block, 0, size, MemoryState::Shared); | 72 | vm_manager.MapMemoryBlock(address, shared_memory->backing_block, 0, size, |
| 73 | MemoryState::Shared); | ||
| 66 | // Reprotect the block with the new permissions | 74 | // Reprotect the block with the new permissions |
| 67 | vm_manager.ReprotectRange(address, size, ConvertPermissions(permissions)); | 75 | vm_manager.ReprotectRange(address, size, ConvertPermissions(permissions)); |
| 68 | } | 76 | } |
| @@ -71,8 +79,11 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u | |||
| 71 | return shared_memory; | 79 | return shared_memory; |
| 72 | } | 80 | } |
| 73 | 81 | ||
| 74 | SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, u32 offset, u32 size, | 82 | SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, |
| 75 | MemoryPermission permissions, MemoryPermission other_permissions, std::string name) { | 83 | u32 offset, u32 size, |
| 84 | MemoryPermission permissions, | ||
| 85 | MemoryPermission other_permissions, | ||
| 86 | std::string name) { | ||
| 76 | SharedPtr<SharedMemory> shared_memory(new SharedMemory); | 87 | SharedPtr<SharedMemory> shared_memory(new SharedMemory); |
| 77 | 88 | ||
| 78 | shared_memory->owner_process = nullptr; | 89 | shared_memory->owner_process = nullptr; |
| @@ -88,27 +99,31 @@ SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vecto | |||
| 88 | } | 99 | } |
| 89 | 100 | ||
| 90 | ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermission permissions, | 101 | ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermission permissions, |
| 91 | MemoryPermission other_permissions) { | 102 | MemoryPermission other_permissions) { |
| 92 | 103 | ||
| 93 | MemoryPermission own_other_permissions = target_process == owner_process ? this->permissions : this->other_permissions; | 104 | MemoryPermission own_other_permissions = |
| 105 | target_process == owner_process ? this->permissions : this->other_permissions; | ||
| 94 | 106 | ||
| 95 | // Automatically allocated memory blocks can only be mapped with other_permissions = DontCare | 107 | // Automatically allocated memory blocks can only be mapped with other_permissions = DontCare |
| 96 | if (base_address == 0 && other_permissions != MemoryPermission::DontCare) { | 108 | if (base_address == 0 && other_permissions != MemoryPermission::DontCare) { |
| 97 | return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); | 109 | return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, |
| 110 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); | ||
| 98 | } | 111 | } |
| 99 | 112 | ||
| 100 | // Error out if the requested permissions don't match what the creator process allows. | 113 | // Error out if the requested permissions don't match what the creator process allows. |
| 101 | if (static_cast<u32>(permissions) & ~static_cast<u32>(own_other_permissions)) { | 114 | if (static_cast<u32>(permissions) & ~static_cast<u32>(own_other_permissions)) { |
| 102 | LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", | 115 | LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", |
| 103 | GetObjectId(), address, name.c_str()); | 116 | GetObjectId(), address, name.c_str()); |
| 104 | return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); | 117 | return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, |
| 118 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); | ||
| 105 | } | 119 | } |
| 106 | 120 | ||
| 107 | // Heap-backed memory blocks can not be mapped with other_permissions = DontCare | 121 | // Heap-backed memory blocks can not be mapped with other_permissions = DontCare |
| 108 | if (base_address != 0 && other_permissions == MemoryPermission::DontCare) { | 122 | if (base_address != 0 && other_permissions == MemoryPermission::DontCare) { |
| 109 | LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", | 123 | LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", |
| 110 | GetObjectId(), address, name.c_str()); | 124 | GetObjectId(), address, name.c_str()); |
| 111 | return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); | 125 | return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, |
| 126 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); | ||
| 112 | } | 127 | } |
| 113 | 128 | ||
| 114 | // Error out if the provided permissions are not compatible with what the creator process needs. | 129 | // Error out if the provided permissions are not compatible with what the creator process needs. |
| @@ -116,12 +131,14 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi | |||
| 116 | static_cast<u32>(this->permissions) & ~static_cast<u32>(other_permissions)) { | 131 | static_cast<u32>(this->permissions) & ~static_cast<u32>(other_permissions)) { |
| 117 | LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", | 132 | LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", |
| 118 | GetObjectId(), address, name.c_str()); | 133 | GetObjectId(), address, name.c_str()); |
| 119 | return ResultCode(ErrorDescription::WrongPermission, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); | 134 | return ResultCode(ErrorDescription::WrongPermission, ErrorModule::OS, |
| 135 | ErrorSummary::WrongArgument, ErrorLevel::Permanent); | ||
| 120 | } | 136 | } |
| 121 | 137 | ||
| 122 | // TODO(Subv): Check for the Shared Device Mem flag in the creator process. | 138 | // TODO(Subv): Check for the Shared Device Mem flag in the creator process. |
| 123 | /*if (was_created_with_shared_device_mem && address != 0) { | 139 | /*if (was_created_with_shared_device_mem && address != 0) { |
| 124 | return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); | 140 | return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, |
| 141 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); | ||
| 125 | }*/ | 142 | }*/ |
| 126 | 143 | ||
| 127 | // TODO(Subv): The same process that created a SharedMemory object | 144 | // TODO(Subv): The same process that created a SharedMemory object |
| @@ -144,23 +161,29 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi | |||
| 144 | } | 161 | } |
| 145 | 162 | ||
| 146 | // Map the memory block into the target process | 163 | // Map the memory block into the target process |
| 147 | auto result = target_process->vm_manager.MapMemoryBlock(target_address, backing_block, backing_block_offset, size, MemoryState::Shared); | 164 | auto result = target_process->vm_manager.MapMemoryBlock( |
| 165 | target_address, backing_block, backing_block_offset, size, MemoryState::Shared); | ||
| 148 | if (result.Failed()) { | 166 | if (result.Failed()) { |
| 149 | LOG_ERROR(Kernel, "cannot map id=%u, target_address=0x%08X name=%s, error mapping to virtual memory", | 167 | LOG_ERROR( |
| 150 | GetObjectId(), target_address, name.c_str()); | 168 | Kernel, |
| 169 | "cannot map id=%u, target_address=0x%08X name=%s, error mapping to virtual memory", | ||
| 170 | GetObjectId(), target_address, name.c_str()); | ||
| 151 | return result.Code(); | 171 | return result.Code(); |
| 152 | } | 172 | } |
| 153 | 173 | ||
| 154 | return target_process->vm_manager.ReprotectRange(target_address, size, ConvertPermissions(permissions)); | 174 | return target_process->vm_manager.ReprotectRange(target_address, size, |
| 175 | ConvertPermissions(permissions)); | ||
| 155 | } | 176 | } |
| 156 | 177 | ||
| 157 | ResultCode SharedMemory::Unmap(Process* target_process, VAddr address) { | 178 | ResultCode SharedMemory::Unmap(Process* target_process, VAddr address) { |
| 158 | // TODO(Subv): Verify what happens if the application tries to unmap an address that is not mapped to a SharedMemory. | 179 | // TODO(Subv): Verify what happens if the application tries to unmap an address that is not |
| 180 | // mapped to a SharedMemory. | ||
| 159 | return target_process->vm_manager.UnmapRange(address, size); | 181 | return target_process->vm_manager.UnmapRange(address, size); |
| 160 | } | 182 | } |
| 161 | 183 | ||
| 162 | VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) { | 184 | VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) { |
| 163 | u32 masked_permissions = static_cast<u32>(permission) & static_cast<u32>(MemoryPermission::ReadWriteExecute); | 185 | u32 masked_permissions = |
| 186 | static_cast<u32>(permission) & static_cast<u32>(MemoryPermission::ReadWriteExecute); | ||
| 164 | return static_cast<VMAPermission>(masked_permissions); | 187 | return static_cast<VMAPermission>(masked_permissions); |
| 165 | }; | 188 | }; |
| 166 | 189 | ||
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h index 0c404a9f8..afb142380 100644 --- a/src/core/hle/kernel/shared_memory.h +++ b/src/core/hle/kernel/shared_memory.h | |||
| @@ -16,15 +16,15 @@ namespace Kernel { | |||
| 16 | 16 | ||
| 17 | /// Permissions for mapped shared memory blocks | 17 | /// Permissions for mapped shared memory blocks |
| 18 | enum class MemoryPermission : u32 { | 18 | enum class MemoryPermission : u32 { |
| 19 | None = 0, | 19 | None = 0, |
| 20 | Read = (1u << 0), | 20 | Read = (1u << 0), |
| 21 | Write = (1u << 1), | 21 | Write = (1u << 1), |
| 22 | ReadWrite = (Read | Write), | 22 | ReadWrite = (Read | Write), |
| 23 | Execute = (1u << 2), | 23 | Execute = (1u << 2), |
| 24 | ReadExecute = (Read | Execute), | 24 | ReadExecute = (Read | Execute), |
| 25 | WriteExecute = (Write | Execute), | 25 | WriteExecute = (Write | Execute), |
| 26 | ReadWriteExecute = (Read | Write | Execute), | 26 | ReadWriteExecute = (Read | Write | Execute), |
| 27 | DontCare = (1u << 28) | 27 | DontCare = (1u << 28) |
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| 30 | class SharedMemory final : public Object { | 30 | class SharedMemory final : public Object { |
| @@ -34,13 +34,18 @@ public: | |||
| 34 | * @param owner_process Process that created this shared memory object. | 34 | * @param owner_process Process that created this shared memory object. |
| 35 | * @param size Size of the memory block. Must be page-aligned. | 35 | * @param size Size of the memory block. Must be page-aligned. |
| 36 | * @param permissions Permission restrictions applied to the process which created the block. | 36 | * @param permissions Permission restrictions applied to the process which created the block. |
| 37 | * @param other_permissions Permission restrictions applied to other processes mapping the block. | 37 | * @param other_permissions Permission restrictions applied to other processes mapping the |
| 38 | * block. | ||
| 38 | * @param address The address from which to map the Shared Memory. | 39 | * @param address The address from which to map the Shared Memory. |
| 39 | * @param region If the address is 0, the shared memory will be allocated in this region of the linear heap. | 40 | * @param region If the address is 0, the shared memory will be allocated in this region of the |
| 41 | * linear heap. | ||
| 40 | * @param name Optional object name, used for debugging purposes. | 42 | * @param name Optional object name, used for debugging purposes. |
| 41 | */ | 43 | */ |
| 42 | static SharedPtr<SharedMemory> Create(SharedPtr<Process> owner_process, u32 size, MemoryPermission permissions, | 44 | static SharedPtr<SharedMemory> Create(SharedPtr<Process> owner_process, u32 size, |
| 43 | MemoryPermission other_permissions, VAddr address = 0, MemoryRegion region = MemoryRegion::BASE, std::string name = "Unknown"); | 45 | MemoryPermission permissions, |
| 46 | MemoryPermission other_permissions, VAddr address = 0, | ||
| 47 | MemoryRegion region = MemoryRegion::BASE, | ||
| 48 | std::string name = "Unknown"); | ||
| 44 | 49 | ||
| 45 | /** | 50 | /** |
| 46 | * Creates a shared memory object from a block of memory managed by an HLE applet. | 51 | * Creates a shared memory object from a block of memory managed by an HLE applet. |
| @@ -48,17 +53,27 @@ public: | |||
| 48 | * @param offset The offset into the heap block that the SharedMemory will map. | 53 | * @param offset The offset into the heap block that the SharedMemory will map. |
| 49 | * @param size Size of the memory block. Must be page-aligned. | 54 | * @param size Size of the memory block. Must be page-aligned. |
| 50 | * @param permissions Permission restrictions applied to the process which created the block. | 55 | * @param permissions Permission restrictions applied to the process which created the block. |
| 51 | * @param other_permissions Permission restrictions applied to other processes mapping the block. | 56 | * @param other_permissions Permission restrictions applied to other processes mapping the |
| 57 | * block. | ||
| 52 | * @param name Optional object name, used for debugging purposes. | 58 | * @param name Optional object name, used for debugging purposes. |
| 53 | */ | 59 | */ |
| 54 | static SharedPtr<SharedMemory> CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, u32 offset, u32 size, | 60 | static SharedPtr<SharedMemory> CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, |
| 55 | MemoryPermission permissions, MemoryPermission other_permissions, std::string name = "Unknown Applet"); | 61 | u32 offset, u32 size, |
| 56 | 62 | MemoryPermission permissions, | |
| 57 | std::string GetTypeName() const override { return "SharedMemory"; } | 63 | MemoryPermission other_permissions, |
| 58 | std::string GetName() const override { return name; } | 64 | std::string name = "Unknown Applet"); |
| 65 | |||
| 66 | std::string GetTypeName() const override { | ||
| 67 | return "SharedMemory"; | ||
| 68 | } | ||
| 69 | std::string GetName() const override { | ||
| 70 | return name; | ||
| 71 | } | ||
| 59 | 72 | ||
| 60 | static const HandleType HANDLE_TYPE = HandleType::SharedMemory; | 73 | static const HandleType HANDLE_TYPE = HandleType::SharedMemory; |
| 61 | HandleType GetHandleType() const override { return HANDLE_TYPE; } | 74 | HandleType GetHandleType() const override { |
| 75 | return HANDLE_TYPE; | ||
| 76 | } | ||
| 62 | 77 | ||
| 63 | /** | 78 | /** |
| 64 | * Converts the specified MemoryPermission into the equivalent VMAPermission. | 79 | * Converts the specified MemoryPermission into the equivalent VMAPermission. |
| @@ -73,7 +88,8 @@ public: | |||
| 73 | * @param permissions Memory block map permissions (specified by SVC field) | 88 | * @param permissions Memory block map permissions (specified by SVC field) |
| 74 | * @param other_permissions Memory block map other permissions (specified by SVC field) | 89 | * @param other_permissions Memory block map other permissions (specified by SVC field) |
| 75 | */ | 90 | */ |
| 76 | ResultCode Map(Process* target_process, VAddr address, MemoryPermission permissions, MemoryPermission other_permissions); | 91 | ResultCode Map(Process* target_process, VAddr address, MemoryPermission permissions, |
| 92 | MemoryPermission other_permissions); | ||
| 77 | 93 | ||
| 78 | /** | 94 | /** |
| 79 | * Unmaps a shared memory block from the specified address in system memory | 95 | * Unmaps a shared memory block from the specified address in system memory |
| @@ -94,7 +110,8 @@ public: | |||
| 94 | SharedPtr<Process> owner_process; | 110 | SharedPtr<Process> owner_process; |
| 95 | /// Address of shared memory block in the owner process if specified. | 111 | /// Address of shared memory block in the owner process if specified. |
| 96 | VAddr base_address; | 112 | VAddr base_address; |
| 97 | /// Physical address of the shared memory block in the linear heap if no address was specified during creation. | 113 | /// Physical address of the shared memory block in the linear heap if no address was specified |
| 114 | /// during creation. | ||
| 98 | PAddr linear_heap_phys_address; | 115 | PAddr linear_heap_phys_address; |
| 99 | /// Backing memory for this shared memory block. | 116 | /// Backing memory for this shared memory block. |
| 100 | std::shared_ptr<std::vector<u8>> backing_block; | 117 | std::shared_ptr<std::vector<u8>> backing_block; |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index f1e5cf3cb..59272715f 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -18,10 +18,10 @@ | |||
| 18 | #include "core/core_timing.h" | 18 | #include "core/core_timing.h" |
| 19 | #include "core/hle/hle.h" | 19 | #include "core/hle/hle.h" |
| 20 | #include "core/hle/kernel/kernel.h" | 20 | #include "core/hle/kernel/kernel.h" |
| 21 | #include "core/hle/kernel/process.h" | ||
| 22 | #include "core/hle/kernel/thread.h" | ||
| 23 | #include "core/hle/kernel/memory.h" | 21 | #include "core/hle/kernel/memory.h" |
| 24 | #include "core/hle/kernel/mutex.h" | 22 | #include "core/hle/kernel/mutex.h" |
| 23 | #include "core/hle/kernel/process.h" | ||
| 24 | #include "core/hle/kernel/thread.h" | ||
| 25 | #include "core/hle/result.h" | 25 | #include "core/hle/result.h" |
| 26 | #include "core/memory.h" | 26 | #include "core/memory.h" |
| 27 | 27 | ||
| @@ -46,7 +46,7 @@ static Kernel::HandleTable wakeup_callback_handle_table; | |||
| 46 | static std::vector<SharedPtr<Thread>> thread_list; | 46 | static std::vector<SharedPtr<Thread>> thread_list; |
| 47 | 47 | ||
| 48 | // Lists only ready thread ids. | 48 | // Lists only ready thread ids. |
| 49 | static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST+1> ready_queue; | 49 | static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST + 1> ready_queue; |
| 50 | 50 | ||
| 51 | static Thread* current_thread; | 51 | static Thread* current_thread; |
| 52 | 52 | ||
| @@ -61,8 +61,10 @@ inline static u32 const NewThreadId() { | |||
| 61 | return next_thread_id++; | 61 | return next_thread_id++; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | Thread::Thread() {} | 64 | Thread::Thread() { |
| 65 | Thread::~Thread() {} | 65 | } |
| 66 | Thread::~Thread() { | ||
| 67 | } | ||
| 66 | 68 | ||
| 67 | Thread* GetCurrentThread() { | 69 | Thread* GetCurrentThread() { |
| 68 | return current_thread; | 70 | return current_thread; |
| @@ -103,7 +105,7 @@ void Thread::Stop() { | |||
| 103 | 105 | ||
| 104 | // Clean up thread from ready queue | 106 | // Clean up thread from ready queue |
| 105 | // This is only needed when the thread is termintated forcefully (SVC TerminateProcess) | 107 | // This is only needed when the thread is termintated forcefully (SVC TerminateProcess) |
| 106 | if (status == THREADSTATUS_READY){ | 108 | if (status == THREADSTATUS_READY) { |
| 107 | ready_queue.remove(current_priority, this); | 109 | ready_queue.remove(current_priority, this); |
| 108 | } | 110 | } |
| 109 | 111 | ||
| @@ -119,7 +121,8 @@ void Thread::Stop() { | |||
| 119 | 121 | ||
| 120 | // Mark the TLS slot in the thread's page as free. | 122 | // Mark the TLS slot in the thread's page as free. |
| 121 | u32 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE; | 123 | u32 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE; |
| 122 | u32 tls_slot = ((tls_address - Memory::TLS_AREA_VADDR) % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE; | 124 | u32 tls_slot = |
| 125 | ((tls_address - Memory::TLS_AREA_VADDR) % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE; | ||
| 123 | Kernel::g_current_process->tls_slots[tls_page].reset(tls_slot); | 126 | Kernel::g_current_process->tls_slots[tls_page].reset(tls_slot); |
| 124 | 127 | ||
| 125 | HLE::Reschedule(__func__); | 128 | HLE::Reschedule(__func__); |
| @@ -137,7 +140,7 @@ Thread* ArbitrateHighestPriorityThread(u32 address) { | |||
| 137 | if (thread == nullptr) | 140 | if (thread == nullptr) |
| 138 | continue; | 141 | continue; |
| 139 | 142 | ||
| 140 | if(thread->current_priority <= priority) { | 143 | if (thread->current_priority <= priority) { |
| 141 | highest_priority_thread = thread.get(); | 144 | highest_priority_thread = thread.get(); |
| 142 | priority = thread->current_priority; | 145 | priority = thread->current_priority; |
| 143 | } | 146 | } |
| @@ -170,7 +173,7 @@ static void PriorityBoostStarvedThreads() { | |||
| 170 | // on hardware. However, this is almost certainly not perfect, and the real CTR OS scheduler | 173 | // on hardware. However, this is almost certainly not perfect, and the real CTR OS scheduler |
| 171 | // should probably be reversed to verify this. | 174 | // should probably be reversed to verify this. |
| 172 | 175 | ||
| 173 | const u64 boost_timeout = 2000000; // Boost threads that have been ready for > this long | 176 | const u64 boost_timeout = 2000000; // Boost threads that have been ready for > this long |
| 174 | 177 | ||
| 175 | u64 delta = current_ticks - thread->last_running_ticks; | 178 | u64 delta = current_ticks - thread->last_running_ticks; |
| 176 | 179 | ||
| @@ -193,10 +196,12 @@ static std::tuple<u32*, u32*> GetWaitSynchTimeoutParameterRegister(Thread* threa | |||
| 193 | 196 | ||
| 194 | if ((thumb_mode && thumb_inst == 0xDF24) || (!thumb_mode && inst == 0x0F000024)) { | 197 | if ((thumb_mode && thumb_inst == 0xDF24) || (!thumb_mode && inst == 0x0F000024)) { |
| 195 | // svc #0x24 (WaitSynchronization1) | 198 | // svc #0x24 (WaitSynchronization1) |
| 196 | return std::make_tuple(&thread->context.cpu_registers[2], &thread->context.cpu_registers[3]); | 199 | return std::make_tuple(&thread->context.cpu_registers[2], |
| 200 | &thread->context.cpu_registers[3]); | ||
| 197 | } else if ((thumb_mode && thumb_inst == 0xDF25) || (!thumb_mode && inst == 0x0F000025)) { | 201 | } else if ((thumb_mode && thumb_inst == 0xDF25) || (!thumb_mode && inst == 0x0F000025)) { |
| 198 | // svc #0x25 (WaitSynchronizationN) | 202 | // svc #0x25 (WaitSynchronizationN) |
| 199 | return std::make_tuple(&thread->context.cpu_registers[0], &thread->context.cpu_registers[4]); | 203 | return std::make_tuple(&thread->context.cpu_registers[0], |
| 204 | &thread->context.cpu_registers[4]); | ||
| 200 | } | 205 | } |
| 201 | 206 | ||
| 202 | UNREACHABLE(); | 207 | UNREACHABLE(); |
| @@ -245,7 +250,8 @@ static void SwitchContext(Thread* new_thread) { | |||
| 245 | 250 | ||
| 246 | // Load context of new thread | 251 | // Load context of new thread |
| 247 | if (new_thread) { | 252 | if (new_thread) { |
| 248 | DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY, "Thread must be ready to become running."); | 253 | DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY, |
| 254 | "Thread must be ready to become running."); | ||
| 249 | 255 | ||
| 250 | // Cancel any outstanding wakeup events for this thread | 256 | // Cancel any outstanding wakeup events for this thread |
| 251 | CoreTiming::UnscheduleEvent(ThreadWakeupEventType, new_thread->callback_handle); | 257 | CoreTiming::UnscheduleEvent(ThreadWakeupEventType, new_thread->callback_handle); |
| @@ -263,7 +269,7 @@ static void SwitchContext(Thread* new_thread) { | |||
| 263 | new_thread->context.pc -= thumb_mode ? 2 : 4; | 269 | new_thread->context.pc -= thumb_mode ? 2 : 4; |
| 264 | 270 | ||
| 265 | // Get the register for timeout parameter | 271 | // Get the register for timeout parameter |
| 266 | u32* timeout_low, *timeout_high; | 272 | u32 *timeout_low, *timeout_high; |
| 267 | std::tie(timeout_low, timeout_high) = GetWaitSynchTimeoutParameterRegister(new_thread); | 273 | std::tie(timeout_low, timeout_high) = GetWaitSynchTimeoutParameterRegister(new_thread); |
| 268 | 274 | ||
| 269 | // Update the timeout parameter | 275 | // Update the timeout parameter |
| @@ -307,7 +313,7 @@ static Thread* PopNextReadyThread() { | |||
| 307 | // Otherwise just keep going with the current thread | 313 | // Otherwise just keep going with the current thread |
| 308 | next = thread; | 314 | next = thread; |
| 309 | } | 315 | } |
| 310 | } else { | 316 | } else { |
| 311 | next = ready_queue.pop_first(); | 317 | next = ready_queue.pop_first(); |
| 312 | } | 318 | } |
| 313 | 319 | ||
| @@ -321,7 +327,8 @@ void WaitCurrentThread_Sleep() { | |||
| 321 | HLE::Reschedule(__func__); | 327 | HLE::Reschedule(__func__); |
| 322 | } | 328 | } |
| 323 | 329 | ||
| 324 | void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, bool wait_set_output, bool wait_all) { | 330 | void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, |
| 331 | bool wait_set_output, bool wait_all) { | ||
| 325 | Thread* thread = GetCurrentThread(); | 332 | Thread* thread = GetCurrentThread(); |
| 326 | thread->wait_set_output = wait_set_output; | 333 | thread->wait_set_output = wait_set_output; |
| 327 | thread->wait_all = wait_all; | 334 | thread->wait_all = wait_all; |
| @@ -352,7 +359,8 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) { | |||
| 352 | 359 | ||
| 353 | if (thread->status == THREADSTATUS_WAIT_SYNCH || thread->status == THREADSTATUS_WAIT_ARB) { | 360 | if (thread->status == THREADSTATUS_WAIT_SYNCH || thread->status == THREADSTATUS_WAIT_ARB) { |
| 354 | thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS, | 361 | thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS, |
| 355 | ErrorSummary::StatusChanged, ErrorLevel::Info)); | 362 | ErrorSummary::StatusChanged, |
| 363 | ErrorLevel::Info)); | ||
| 356 | 364 | ||
| 357 | if (thread->wait_set_output) | 365 | if (thread->wait_set_output) |
| 358 | thread->SetWaitSynchronizationOutput(-1); | 366 | thread->SetWaitSynchronizationOutput(-1); |
| @@ -372,25 +380,25 @@ void Thread::WakeAfterDelay(s64 nanoseconds) { | |||
| 372 | 380 | ||
| 373 | void Thread::ResumeFromWait() { | 381 | void Thread::ResumeFromWait() { |
| 374 | switch (status) { | 382 | switch (status) { |
| 375 | case THREADSTATUS_WAIT_SYNCH: | 383 | case THREADSTATUS_WAIT_SYNCH: |
| 376 | case THREADSTATUS_WAIT_ARB: | 384 | case THREADSTATUS_WAIT_ARB: |
| 377 | case THREADSTATUS_WAIT_SLEEP: | 385 | case THREADSTATUS_WAIT_SLEEP: |
| 378 | break; | 386 | break; |
| 379 | 387 | ||
| 380 | case THREADSTATUS_READY: | 388 | case THREADSTATUS_READY: |
| 381 | // If the thread is waiting on multiple wait objects, it might be awoken more than once | 389 | // If the thread is waiting on multiple wait objects, it might be awoken more than once |
| 382 | // before actually resuming. We can ignore subsequent wakeups if the thread status has | 390 | // before actually resuming. We can ignore subsequent wakeups if the thread status has |
| 383 | // already been set to THREADSTATUS_READY. | 391 | // already been set to THREADSTATUS_READY. |
| 384 | return; | 392 | return; |
| 385 | 393 | ||
| 386 | case THREADSTATUS_RUNNING: | 394 | case THREADSTATUS_RUNNING: |
| 387 | DEBUG_ASSERT_MSG(false, "Thread with object id %u has already resumed.", GetObjectId()); | 395 | DEBUG_ASSERT_MSG(false, "Thread with object id %u has already resumed.", GetObjectId()); |
| 388 | return; | 396 | return; |
| 389 | case THREADSTATUS_DEAD: | 397 | case THREADSTATUS_DEAD: |
| 390 | // This should never happen, as threads must complete before being stopped. | 398 | // This should never happen, as threads must complete before being stopped. |
| 391 | DEBUG_ASSERT_MSG(false, "Thread with object id %u cannot be resumed because it's DEAD.", | 399 | DEBUG_ASSERT_MSG(false, "Thread with object id %u cannot be resumed because it's DEAD.", |
| 392 | GetObjectId()); | 400 | GetObjectId()); |
| 393 | return; | 401 | return; |
| 394 | } | 402 | } |
| 395 | 403 | ||
| 396 | ready_queue.push_back(current_priority, this); | 404 | ready_queue.push_back(current_priority, this); |
| @@ -405,7 +413,8 @@ static void DebugThreadQueue() { | |||
| 405 | if (!thread) { | 413 | if (!thread) { |
| 406 | LOG_DEBUG(Kernel, "Current: NO CURRENT THREAD"); | 414 | LOG_DEBUG(Kernel, "Current: NO CURRENT THREAD"); |
| 407 | } else { | 415 | } else { |
| 408 | LOG_DEBUG(Kernel, "0x%02X %u (current)", thread->current_priority, GetCurrentThread()->GetObjectId()); | 416 | LOG_DEBUG(Kernel, "0x%02X %u (current)", thread->current_priority, |
| 417 | GetCurrentThread()->GetObjectId()); | ||
| 409 | } | 418 | } |
| 410 | 419 | ||
| 411 | for (auto& t : thread_list) { | 420 | for (auto& t : thread_list) { |
| @@ -448,7 +457,8 @@ std::tuple<u32, u32, bool> GetFreeThreadLocalSlot(std::vector<std::bitset<8>>& t | |||
| 448 | * @param entry_point Address of entry point for execution | 457 | * @param entry_point Address of entry point for execution |
| 449 | * @param arg User argument for thread | 458 | * @param arg User argument for thread |
| 450 | */ | 459 | */ |
| 451 | static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) { | 460 | static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, |
| 461 | u32 arg) { | ||
| 452 | memset(&context, 0, sizeof(Core::ThreadContext)); | 462 | memset(&context, 0, sizeof(Core::ThreadContext)); |
| 453 | 463 | ||
| 454 | context.cpu_registers[0] = arg; | 464 | context.cpu_registers[0] = arg; |
| @@ -458,11 +468,11 @@ static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32 | |||
| 458 | } | 468 | } |
| 459 | 469 | ||
| 460 | ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority, | 470 | ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority, |
| 461 | u32 arg, s32 processor_id, VAddr stack_top) { | 471 | u32 arg, s32 processor_id, VAddr stack_top) { |
| 462 | if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { | 472 | if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { |
| 463 | s32 new_priority = MathUtil::Clamp<s32>(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); | 473 | s32 new_priority = MathUtil::Clamp<s32>(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); |
| 464 | LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", | 474 | LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", name.c_str(), |
| 465 | name.c_str(), priority, new_priority); | 475 | priority, new_priority); |
| 466 | // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm | 476 | // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm |
| 467 | // validity of this | 477 | // validity of this |
| 468 | priority = new_priority; | 478 | priority = new_priority; |
| @@ -472,7 +482,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | |||
| 472 | LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point); | 482 | LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point); |
| 473 | // TODO: Verify error | 483 | // TODO: Verify error |
| 474 | return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, | 484 | return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, |
| 475 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); | 485 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); |
| 476 | } | 486 | } |
| 477 | 487 | ||
| 478 | SharedPtr<Thread> thread(new Thread); | 488 | SharedPtr<Thread> thread(new Thread); |
| @@ -511,8 +521,10 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | |||
| 511 | auto& linheap_memory = memory_region->linear_heap_memory; | 521 | auto& linheap_memory = memory_region->linear_heap_memory; |
| 512 | 522 | ||
| 513 | if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) { | 523 | if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) { |
| 514 | LOG_ERROR(Kernel_SVC, "Not enough space in region to allocate a new TLS page for thread"); | 524 | LOG_ERROR(Kernel_SVC, |
| 515 | return ResultCode(ErrorDescription::OutOfMemory, ErrorModule::Kernel, ErrorSummary::OutOfResource, ErrorLevel::Permanent); | 525 | "Not enough space in region to allocate a new TLS page for thread"); |
| 526 | return ResultCode(ErrorDescription::OutOfMemory, ErrorModule::Kernel, | ||
| 527 | ErrorSummary::OutOfResource, ErrorLevel::Permanent); | ||
| 516 | } | 528 | } |
| 517 | 529 | ||
| 518 | u32 offset = linheap_memory->size(); | 530 | u32 offset = linheap_memory->size(); |
| @@ -537,7 +549,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | |||
| 537 | 549 | ||
| 538 | // Mark the slot as used | 550 | // Mark the slot as used |
| 539 | tls_slots[available_page].set(available_slot); | 551 | tls_slots[available_page].set(available_slot); |
| 540 | thread->tls_address = Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE + available_slot * Memory::TLS_ENTRY_SIZE; | 552 | thread->tls_address = Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE + |
| 553 | available_slot * Memory::TLS_ENTRY_SIZE; | ||
| 541 | 554 | ||
| 542 | // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used | 555 | // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used |
| 543 | // to initialize the context | 556 | // to initialize the context |
| @@ -551,10 +564,12 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | |||
| 551 | return MakeResult<SharedPtr<Thread>>(std::move(thread)); | 564 | return MakeResult<SharedPtr<Thread>>(std::move(thread)); |
| 552 | } | 565 | } |
| 553 | 566 | ||
| 554 | // TODO(peachum): Remove this. Range checking should be done, and an appropriate error should be returned. | 567 | // TODO(peachum): Remove this. Range checking should be done, and an appropriate error should be |
| 568 | // returned. | ||
| 555 | static void ClampPriority(const Thread* thread, s32* priority) { | 569 | static void ClampPriority(const Thread* thread, s32* priority) { |
| 556 | if (*priority < THREADPRIO_HIGHEST || *priority > THREADPRIO_LOWEST) { | 570 | if (*priority < THREADPRIO_HIGHEST || *priority > THREADPRIO_LOWEST) { |
| 557 | DEBUG_ASSERT_MSG(false, "Application passed an out of range priority. An error should be returned."); | 571 | DEBUG_ASSERT_MSG( |
| 572 | false, "Application passed an out of range priority. An error should be returned."); | ||
| 558 | 573 | ||
| 559 | s32 new_priority = MathUtil::Clamp<s32>(*priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); | 574 | s32 new_priority = MathUtil::Clamp<s32>(*priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); |
| 560 | LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", | 575 | LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", |
| @@ -586,12 +601,13 @@ SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) { | |||
| 586 | DEBUG_ASSERT(!GetCurrentThread()); | 601 | DEBUG_ASSERT(!GetCurrentThread()); |
| 587 | 602 | ||
| 588 | // Initialize new "main" thread | 603 | // Initialize new "main" thread |
| 589 | auto thread_res = Thread::Create("main", entry_point, priority, 0, | 604 | auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0, |
| 590 | THREADPROCESSORID_0, Memory::HEAP_VADDR_END); | 605 | Memory::HEAP_VADDR_END); |
| 591 | 606 | ||
| 592 | SharedPtr<Thread> thread = thread_res.MoveFrom(); | 607 | SharedPtr<Thread> thread = thread_res.MoveFrom(); |
| 593 | 608 | ||
| 594 | thread->context.fpscr = FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO | FPSCR_IXC; // 0x03C00010 | 609 | thread->context.fpscr = |
| 610 | FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO | FPSCR_IXC; // 0x03C00010 | ||
| 595 | 611 | ||
| 596 | // Run new "main" thread | 612 | // Run new "main" thread |
| 597 | SwitchContext(thread.get()); | 613 | SwitchContext(thread.get()); |
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index deab5d5a6..2ed5cf74e 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -17,29 +17,29 @@ | |||
| 17 | #include "core/hle/kernel/kernel.h" | 17 | #include "core/hle/kernel/kernel.h" |
| 18 | #include "core/hle/result.h" | 18 | #include "core/hle/result.h" |
| 19 | 19 | ||
| 20 | enum ThreadPriority : s32{ | 20 | enum ThreadPriority : s32 { |
| 21 | THREADPRIO_HIGHEST = 0, ///< Highest thread priority | 21 | THREADPRIO_HIGHEST = 0, ///< Highest thread priority |
| 22 | THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps | 22 | THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps |
| 23 | THREADPRIO_DEFAULT = 48, ///< Default thread priority for userland apps | 23 | THREADPRIO_DEFAULT = 48, ///< Default thread priority for userland apps |
| 24 | THREADPRIO_LOWEST = 63, ///< Lowest thread priority | 24 | THREADPRIO_LOWEST = 63, ///< Lowest thread priority |
| 25 | }; | 25 | }; |
| 26 | 26 | ||
| 27 | enum ThreadProcessorId : s32 { | 27 | enum ThreadProcessorId : s32 { |
| 28 | THREADPROCESSORID_DEFAULT = -2, ///< Run thread on default core specified by exheader | 28 | THREADPROCESSORID_DEFAULT = -2, ///< Run thread on default core specified by exheader |
| 29 | THREADPROCESSORID_ALL = -1, ///< Run thread on either core | 29 | THREADPROCESSORID_ALL = -1, ///< Run thread on either core |
| 30 | THREADPROCESSORID_0 = 0, ///< Run thread on core 0 (AppCore) | 30 | THREADPROCESSORID_0 = 0, ///< Run thread on core 0 (AppCore) |
| 31 | THREADPROCESSORID_1 = 1, ///< Run thread on core 1 (SysCore) | 31 | THREADPROCESSORID_1 = 1, ///< Run thread on core 1 (SysCore) |
| 32 | THREADPROCESSORID_MAX = 2, ///< Processor ID must be less than this | 32 | THREADPROCESSORID_MAX = 2, ///< Processor ID must be less than this |
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | enum ThreadStatus { | 35 | enum ThreadStatus { |
| 36 | THREADSTATUS_RUNNING, ///< Currently running | 36 | THREADSTATUS_RUNNING, ///< Currently running |
| 37 | THREADSTATUS_READY, ///< Ready to run | 37 | THREADSTATUS_READY, ///< Ready to run |
| 38 | THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter | 38 | THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter |
| 39 | THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC | 39 | THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC |
| 40 | THREADSTATUS_WAIT_SYNCH, ///< Waiting due to a WaitSynchronization SVC | 40 | THREADSTATUS_WAIT_SYNCH, ///< Waiting due to a WaitSynchronization SVC |
| 41 | THREADSTATUS_DORMANT, ///< Created but not yet made ready | 41 | THREADSTATUS_DORMANT, ///< Created but not yet made ready |
| 42 | THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated | 42 | THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated |
| 43 | }; | 43 | }; |
| 44 | 44 | ||
| 45 | namespace Kernel { | 45 | namespace Kernel { |
| @@ -60,13 +60,19 @@ public: | |||
| 60 | * @return A shared pointer to the newly created thread | 60 | * @return A shared pointer to the newly created thread |
| 61 | */ | 61 | */ |
| 62 | static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority, | 62 | static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority, |
| 63 | u32 arg, s32 processor_id, VAddr stack_top); | 63 | u32 arg, s32 processor_id, VAddr stack_top); |
| 64 | 64 | ||
| 65 | std::string GetName() const override { return name; } | 65 | std::string GetName() const override { |
| 66 | std::string GetTypeName() const override { return "Thread"; } | 66 | return name; |
| 67 | } | ||
| 68 | std::string GetTypeName() const override { | ||
| 69 | return "Thread"; | ||
| 70 | } | ||
| 67 | 71 | ||
| 68 | static const HandleType HANDLE_TYPE = HandleType::Thread; | 72 | static const HandleType HANDLE_TYPE = HandleType::Thread; |
| 69 | HandleType GetHandleType() const override { return HANDLE_TYPE; } | 73 | HandleType GetHandleType() const override { |
| 74 | return HANDLE_TYPE; | ||
| 75 | } | ||
| 70 | 76 | ||
| 71 | bool ShouldWait() override; | 77 | bool ShouldWait() override; |
| 72 | void Acquire() override; | 78 | void Acquire() override; |
| @@ -75,7 +81,9 @@ public: | |||
| 75 | * Gets the thread's current priority | 81 | * Gets the thread's current priority |
| 76 | * @return The current thread's priority | 82 | * @return The current thread's priority |
| 77 | */ | 83 | */ |
| 78 | s32 GetPriority() const { return current_priority; } | 84 | s32 GetPriority() const { |
| 85 | return current_priority; | ||
| 86 | } | ||
| 79 | 87 | ||
| 80 | /** | 88 | /** |
| 81 | * Sets the thread's current priority | 89 | * Sets the thread's current priority |
| @@ -93,7 +101,9 @@ public: | |||
| 93 | * Gets the thread's thread ID | 101 | * Gets the thread's thread ID |
| 94 | * @return The thread's ID | 102 | * @return The thread's ID |
| 95 | */ | 103 | */ |
| 96 | u32 GetThreadId() const { return thread_id; } | 104 | u32 GetThreadId() const { |
| 105 | return thread_id; | ||
| 106 | } | ||
| 97 | 107 | ||
| 98 | /** | 108 | /** |
| 99 | * Resumes a thread from waiting | 109 | * Resumes a thread from waiting |
| @@ -127,7 +137,9 @@ public: | |||
| 127 | * Returns the Thread Local Storage address of the current thread | 137 | * Returns the Thread Local Storage address of the current thread |
| 128 | * @returns VAddr of the thread's TLS | 138 | * @returns VAddr of the thread's TLS |
| 129 | */ | 139 | */ |
| 130 | VAddr GetTLSAddress() const { return tls_address; } | 140 | VAddr GetTLSAddress() const { |
| 141 | return tls_address; | ||
| 142 | } | ||
| 131 | 143 | ||
| 132 | Core::ThreadContext context; | 144 | Core::ThreadContext context; |
| 133 | 145 | ||
| @@ -137,8 +149,8 @@ public: | |||
| 137 | u32 entry_point; | 149 | u32 entry_point; |
| 138 | u32 stack_top; | 150 | u32 stack_top; |
| 139 | 151 | ||
| 140 | s32 nominal_priority; ///< Nominal thread priority, as set by the emulated application | 152 | s32 nominal_priority; ///< Nominal thread priority, as set by the emulated application |
| 141 | s32 current_priority; ///< Current thread priority, can be temporarily changed | 153 | s32 current_priority; ///< Current thread priority, can be temporarily changed |
| 142 | 154 | ||
| 143 | u64 last_running_ticks; ///< CPU tick when thread was last running | 155 | u64 last_running_ticks; ///< CPU tick when thread was last running |
| 144 | 156 | ||
| @@ -151,11 +163,11 @@ public: | |||
| 151 | /// Mutexes currently held by this thread, which will be released when it exits. | 163 | /// Mutexes currently held by this thread, which will be released when it exits. |
| 152 | boost::container::flat_set<SharedPtr<Mutex>> held_mutexes; | 164 | boost::container::flat_set<SharedPtr<Mutex>> held_mutexes; |
| 153 | 165 | ||
| 154 | SharedPtr<Process> owner_process; ///< Process that owns this thread | 166 | SharedPtr<Process> owner_process; ///< Process that owns this thread |
| 155 | std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on | 167 | std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on |
| 156 | VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address | 168 | VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address |
| 157 | bool wait_all; ///< True if the thread is waiting on all objects before resuming | 169 | bool wait_all; ///< True if the thread is waiting on all objects before resuming |
| 158 | bool wait_set_output; ///< True if the output parameter should be set on thread wakeup | 170 | bool wait_set_output; ///< True if the output parameter should be set on thread wakeup |
| 159 | 171 | ||
| 160 | std::string name; | 172 | std::string name; |
| 161 | 173 | ||
| @@ -205,10 +217,12 @@ void WaitCurrentThread_Sleep(); | |||
| 205 | /** | 217 | /** |
| 206 | * Waits the current thread from a WaitSynchronization call | 218 | * Waits the current thread from a WaitSynchronization call |
| 207 | * @param wait_objects Kernel objects that we are waiting on | 219 | * @param wait_objects Kernel objects that we are waiting on |
| 208 | * @param wait_set_output If true, set the output parameter on thread wakeup (for WaitSynchronizationN only) | 220 | * @param wait_set_output If true, set the output parameter on thread wakeup (for |
| 221 | * WaitSynchronizationN only) | ||
| 209 | * @param wait_all If true, wait on all objects before resuming (for WaitSynchronizationN only) | 222 | * @param wait_all If true, wait on all objects before resuming (for WaitSynchronizationN only) |
| 210 | */ | 223 | */ |
| 211 | void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, bool wait_set_output, bool wait_all); | 224 | void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, |
| 225 | bool wait_set_output, bool wait_all); | ||
| 212 | 226 | ||
| 213 | /** | 227 | /** |
| 214 | * Waits the current thread from an ArbitrateAddress call | 228 | * Waits the current thread from an ArbitrateAddress call |
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp index b8daaeede..255cb1aca 100644 --- a/src/core/hle/kernel/timer.cpp +++ b/src/core/hle/kernel/timer.cpp | |||
| @@ -9,8 +9,8 @@ | |||
| 9 | 9 | ||
| 10 | #include "core/core_timing.h" | 10 | #include "core/core_timing.h" |
| 11 | #include "core/hle/kernel/kernel.h" | 11 | #include "core/hle/kernel/kernel.h" |
| 12 | #include "core/hle/kernel/timer.h" | ||
| 13 | #include "core/hle/kernel/thread.h" | 12 | #include "core/hle/kernel/thread.h" |
| 13 | #include "core/hle/kernel/timer.h" | ||
| 14 | 14 | ||
| 15 | namespace Kernel { | 15 | namespace Kernel { |
| 16 | 16 | ||
| @@ -20,8 +20,10 @@ static int timer_callback_event_type; | |||
| 20 | // us to simply use a pool index or similar. | 20 | // us to simply use a pool index or similar. |
| 21 | static Kernel::HandleTable timer_callback_handle_table; | 21 | static Kernel::HandleTable timer_callback_handle_table; |
| 22 | 22 | ||
| 23 | Timer::Timer() {} | 23 | Timer::Timer() { |
| 24 | Timer::~Timer() {} | 24 | } |
| 25 | Timer::~Timer() { | ||
| 26 | } | ||
| 25 | 27 | ||
| 26 | SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) { | 28 | SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) { |
| 27 | SharedPtr<Timer> timer(new Timer); | 29 | SharedPtr<Timer> timer(new Timer); |
| @@ -41,7 +43,7 @@ bool Timer::ShouldWait() { | |||
| 41 | } | 43 | } |
| 42 | 44 | ||
| 43 | void Timer::Acquire() { | 45 | void Timer::Acquire() { |
| 44 | ASSERT_MSG( !ShouldWait(), "object unavailable!"); | 46 | ASSERT_MSG(!ShouldWait(), "object unavailable!"); |
| 45 | 47 | ||
| 46 | if (reset_type == ResetType::OneShot) | 48 | if (reset_type == ResetType::OneShot) |
| 47 | signaled = false; | 49 | signaled = false; |
| @@ -55,8 +57,8 @@ void Timer::Set(s64 initial, s64 interval) { | |||
| 55 | interval_delay = interval; | 57 | interval_delay = interval; |
| 56 | 58 | ||
| 57 | u64 initial_microseconds = initial / 1000; | 59 | u64 initial_microseconds = initial / 1000; |
| 58 | CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), | 60 | CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type, |
| 59 | timer_callback_event_type, callback_handle); | 61 | callback_handle); |
| 60 | 62 | ||
| 61 | HLE::Reschedule(__func__); | 63 | HLE::Reschedule(__func__); |
| 62 | } | 64 | } |
| @@ -73,7 +75,8 @@ void Timer::Clear() { | |||
| 73 | 75 | ||
| 74 | /// The timer callback event, called when a timer is fired | 76 | /// The timer callback event, called when a timer is fired |
| 75 | static void TimerCallback(u64 timer_handle, int cycles_late) { | 77 | static void TimerCallback(u64 timer_handle, int cycles_late) { |
| 76 | SharedPtr<Timer> timer = timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle)); | 78 | SharedPtr<Timer> timer = |
| 79 | timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle)); | ||
| 77 | 80 | ||
| 78 | if (timer == nullptr) { | 81 | if (timer == nullptr) { |
| 79 | LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08" PRIx64, timer_handle); | 82 | LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08" PRIx64, timer_handle); |
| @@ -91,7 +94,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) { | |||
| 91 | // Reschedule the timer with the interval delay | 94 | // Reschedule the timer with the interval delay |
| 92 | u64 interval_microseconds = timer->interval_delay / 1000; | 95 | u64 interval_microseconds = timer->interval_delay / 1000; |
| 93 | CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late, | 96 | CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late, |
| 94 | timer_callback_event_type, timer_handle); | 97 | timer_callback_event_type, timer_handle); |
| 95 | } | 98 | } |
| 96 | } | 99 | } |
| 97 | 100 | ||
diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h index b1db60e8f..97cd0d63c 100644 --- a/src/core/hle/kernel/timer.h +++ b/src/core/hle/kernel/timer.h | |||
| @@ -21,19 +21,25 @@ public: | |||
| 21 | */ | 21 | */ |
| 22 | static SharedPtr<Timer> Create(ResetType reset_type, std::string name = "Unknown"); | 22 | static SharedPtr<Timer> Create(ResetType reset_type, std::string name = "Unknown"); |
| 23 | 23 | ||
| 24 | std::string GetTypeName() const override { return "Timer"; } | 24 | std::string GetTypeName() const override { |
| 25 | std::string GetName() const override { return name; } | 25 | return "Timer"; |
| 26 | } | ||
| 27 | std::string GetName() const override { | ||
| 28 | return name; | ||
| 29 | } | ||
| 26 | 30 | ||
| 27 | static const HandleType HANDLE_TYPE = HandleType::Timer; | 31 | static const HandleType HANDLE_TYPE = HandleType::Timer; |
| 28 | HandleType GetHandleType() const override { return HANDLE_TYPE; } | 32 | HandleType GetHandleType() const override { |
| 33 | return HANDLE_TYPE; | ||
| 34 | } | ||
| 29 | 35 | ||
| 30 | ResetType reset_type; ///< The ResetType of this timer | 36 | ResetType reset_type; ///< The ResetType of this timer |
| 31 | 37 | ||
| 32 | bool signaled; ///< Whether the timer has been signaled or not | 38 | bool signaled; ///< Whether the timer has been signaled or not |
| 33 | std::string name; ///< Name of timer (optional) | 39 | std::string name; ///< Name of timer (optional) |
| 34 | 40 | ||
| 35 | u64 initial_delay; ///< The delay until the timer fires for the first time | 41 | u64 initial_delay; ///< The delay until the timer fires for the first time |
| 36 | u64 interval_delay; ///< The delay until the timer fires after the first time | 42 | u64 interval_delay; ///< The delay until the timer fires after the first time |
| 37 | 43 | ||
| 38 | bool ShouldWait() override; | 44 | bool ShouldWait() override; |
| 39 | void Acquire() override; | 45 | void Acquire() override; |
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 066146cff..4ad86cf48 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp | |||
| @@ -15,8 +15,8 @@ namespace Kernel { | |||
| 15 | 15 | ||
| 16 | static const char* GetMemoryStateName(MemoryState state) { | 16 | static const char* GetMemoryStateName(MemoryState state) { |
| 17 | static const char* names[] = { | 17 | static const char* names[] = { |
| 18 | "Free", "Reserved", "IO", "Static", "Code", "Private", "Shared", "Continuous", "Aliased", | 18 | "Free", "Reserved", "IO", "Static", "Code", "Private", |
| 19 | "Alias", "AliasCode", "Locked", | 19 | "Shared", "Continuous", "Aliased", "Alias", "AliasCode", "Locked", |
| 20 | }; | 20 | }; |
| 21 | 21 | ||
| 22 | return names[(int)state]; | 22 | return names[(int)state]; |
| @@ -24,13 +24,12 @@ static const char* GetMemoryStateName(MemoryState state) { | |||
| 24 | 24 | ||
| 25 | bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { | 25 | bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { |
| 26 | ASSERT(base + size == next.base); | 26 | ASSERT(base + size == next.base); |
| 27 | if (permissions != next.permissions || | 27 | if (permissions != next.permissions || meminfo_state != next.meminfo_state || |
| 28 | meminfo_state != next.meminfo_state || | 28 | type != next.type) { |
| 29 | type != next.type) { | ||
| 30 | return false; | 29 | return false; |
| 31 | } | 30 | } |
| 32 | if (type == VMAType::AllocatedMemoryBlock && | 31 | if (type == VMAType::AllocatedMemoryBlock && |
| 33 | (backing_block != next.backing_block || offset + size != next.offset)) { | 32 | (backing_block != next.backing_block || offset + size != next.offset)) { |
| 34 | return false; | 33 | return false; |
| 35 | } | 34 | } |
| 36 | if (type == VMAType::BackingMemory && backing_memory + size != next.backing_memory) { | 35 | if (type == VMAType::BackingMemory && backing_memory + size != next.backing_memory) { |
| @@ -70,7 +69,9 @@ VMManager::VMAHandle VMManager::FindVMA(VAddr target) const { | |||
| 70 | } | 69 | } |
| 71 | 70 | ||
| 72 | ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, | 71 | ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, |
| 73 | std::shared_ptr<std::vector<u8>> block, size_t offset, u32 size, MemoryState state) { | 72 | std::shared_ptr<std::vector<u8>> block, |
| 73 | size_t offset, u32 size, | ||
| 74 | MemoryState state) { | ||
| 74 | ASSERT(block != nullptr); | 75 | ASSERT(block != nullptr); |
| 75 | ASSERT(offset + size <= block->size()); | 76 | ASSERT(offset + size <= block->size()); |
| 76 | 77 | ||
| @@ -89,7 +90,8 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, | |||
| 89 | return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); | 90 | return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); |
| 90 | } | 91 | } |
| 91 | 92 | ||
| 92 | ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8 * memory, u32 size, MemoryState state) { | 93 | ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* memory, u32 size, |
| 94 | MemoryState state) { | ||
| 93 | ASSERT(memory != nullptr); | 95 | ASSERT(memory != nullptr); |
| 94 | 96 | ||
| 95 | // This is the appropriately sized VMA that will turn into our allocation. | 97 | // This is the appropriately sized VMA that will turn into our allocation. |
| @@ -106,7 +108,9 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8 * m | |||
| 106 | return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); | 108 | return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); |
| 107 | } | 109 | } |
| 108 | 110 | ||
| 109 | ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state, Memory::MMIORegionPointer mmio_handler) { | 111 | ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size, |
| 112 | MemoryState state, | ||
| 113 | Memory::MMIORegionPointer mmio_handler) { | ||
| 110 | // This is the appropriately sized VMA that will turn into our allocation. | 114 | // This is the appropriately sized VMA that will turn into our allocation. |
| 111 | CASCADE_RESULT(VMAIter vma_handle, CarveVMA(target, size)); | 115 | CASCADE_RESULT(VMAIter vma_handle, CarveVMA(target, size)); |
| 112 | VirtualMemoryArea& final_vma = vma_handle->second; | 116 | VirtualMemoryArea& final_vma = vma_handle->second; |
| @@ -191,15 +195,16 @@ void VMManager::RefreshMemoryBlockMappings(const std::vector<u8>* block) { | |||
| 191 | void VMManager::LogLayout(Log::Level log_level) const { | 195 | void VMManager::LogLayout(Log::Level log_level) const { |
| 192 | for (const auto& p : vma_map) { | 196 | for (const auto& p : vma_map) { |
| 193 | const VirtualMemoryArea& vma = p.second; | 197 | const VirtualMemoryArea& vma = p.second; |
| 194 | LOG_GENERIC(Log::Class::Kernel, log_level, "%08X - %08X size: %8X %c%c%c %s", | 198 | LOG_GENERIC(Log::Class::Kernel, log_level, "%08X - %08X size: %8X %c%c%c %s", vma.base, |
| 195 | vma.base, vma.base + vma.size, vma.size, | 199 | vma.base + vma.size, vma.size, |
| 196 | (u8)vma.permissions & (u8)VMAPermission::Read ? 'R' : '-', | 200 | (u8)vma.permissions & (u8)VMAPermission::Read ? 'R' : '-', |
| 197 | (u8)vma.permissions & (u8)VMAPermission::Write ? 'W' : '-', | 201 | (u8)vma.permissions & (u8)VMAPermission::Write ? 'W' : '-', |
| 198 | (u8)vma.permissions & (u8)VMAPermission::Execute ? 'X' : '-', GetMemoryStateName(vma.meminfo_state)); | 202 | (u8)vma.permissions & (u8)VMAPermission::Execute ? 'X' : '-', |
| 203 | GetMemoryStateName(vma.meminfo_state)); | ||
| 199 | } | 204 | } |
| 200 | } | 205 | } |
| 201 | 206 | ||
| 202 | VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle & iter) { | 207 | VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle& iter) { |
| 203 | // This uses a neat C++ trick to convert a const_iterator to a regular iterator, given | 208 | // This uses a neat C++ trick to convert a const_iterator to a regular iterator, given |
| 204 | // non-const access to its container. | 209 | // non-const access to its container. |
| 205 | return vma_map.erase(iter, iter); // Erases an empty range of elements | 210 | return vma_map.erase(iter, iter); // Erases an empty range of elements |
| @@ -337,5 +342,4 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) { | |||
| 337 | break; | 342 | break; |
| 338 | } | 343 | } |
| 339 | } | 344 | } |
| 340 | |||
| 341 | } | 345 | } |
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 91d40655b..fbcd9870f 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h | |||
| @@ -15,13 +15,13 @@ | |||
| 15 | 15 | ||
| 16 | namespace Kernel { | 16 | namespace Kernel { |
| 17 | 17 | ||
| 18 | const ResultCode ERR_INVALID_ADDRESS{ // 0xE0E01BF5 | 18 | const ResultCode ERR_INVALID_ADDRESS{// 0xE0E01BF5 |
| 19 | ErrorDescription::InvalidAddress, ErrorModule::OS, | 19 | ErrorDescription::InvalidAddress, ErrorModule::OS, |
| 20 | ErrorSummary::InvalidArgument, ErrorLevel::Usage}; | 20 | ErrorSummary::InvalidArgument, ErrorLevel::Usage}; |
| 21 | 21 | ||
| 22 | const ResultCode ERR_INVALID_ADDRESS_STATE{ // 0xE0A01BF5 | 22 | const ResultCode ERR_INVALID_ADDRESS_STATE{// 0xE0A01BF5 |
| 23 | ErrorDescription::InvalidAddress, ErrorModule::OS, | 23 | ErrorDescription::InvalidAddress, ErrorModule::OS, |
| 24 | ErrorSummary::InvalidState, ErrorLevel::Usage}; | 24 | ErrorSummary::InvalidState, ErrorLevel::Usage}; |
| 25 | 25 | ||
| 26 | enum class VMAType : u8 { | 26 | enum class VMAType : u8 { |
| 27 | /// VMA represents an unmapped region of the address space. | 27 | /// VMA represents an unmapped region of the address space. |
| @@ -115,7 +115,8 @@ class VMManager final { | |||
| 115 | // TODO(yuriks): Make page tables switchable to support multiple VMManagers | 115 | // TODO(yuriks): Make page tables switchable to support multiple VMManagers |
| 116 | public: | 116 | public: |
| 117 | /** | 117 | /** |
| 118 | * The maximum amount of address space managed by the kernel. Addresses above this are never used. | 118 | * The maximum amount of address space managed by the kernel. Addresses above this are never |
| 119 | * used. | ||
| 119 | * @note This is the limit used by the New 3DS kernel. Old 3DS used 0x20000000. | 120 | * @note This is the limit used by the New 3DS kernel. Old 3DS used 0x20000000. |
| 120 | */ | 121 | */ |
| 121 | static const u32 MAX_ADDRESS = 0x40000000; | 122 | static const u32 MAX_ADDRESS = 0x40000000; |
| @@ -151,7 +152,7 @@ public: | |||
| 151 | * @param state MemoryState tag to attach to the VMA. | 152 | * @param state MemoryState tag to attach to the VMA. |
| 152 | */ | 153 | */ |
| 153 | ResultVal<VMAHandle> MapMemoryBlock(VAddr target, std::shared_ptr<std::vector<u8>> block, | 154 | ResultVal<VMAHandle> MapMemoryBlock(VAddr target, std::shared_ptr<std::vector<u8>> block, |
| 154 | size_t offset, u32 size, MemoryState state); | 155 | size_t offset, u32 size, MemoryState state); |
| 155 | 156 | ||
| 156 | /** | 157 | /** |
| 157 | * Maps an unmanaged host memory pointer at a given address. | 158 | * Maps an unmanaged host memory pointer at a given address. |
| @@ -172,7 +173,8 @@ public: | |||
| 172 | * @param state MemoryState tag to attach to the VMA. | 173 | * @param state MemoryState tag to attach to the VMA. |
| 173 | * @param mmio_handler The handler that will implement read and write for this MMIO region. | 174 | * @param mmio_handler The handler that will implement read and write for this MMIO region. |
| 174 | */ | 175 | */ |
| 175 | ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state, Memory::MMIORegionPointer mmio_handler); | 176 | ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state, |
| 177 | Memory::MMIORegionPointer mmio_handler); | ||
| 176 | 178 | ||
| 177 | /// Unmaps a range of addresses, splitting VMAs as necessary. | 179 | /// Unmaps a range of addresses, splitting VMAs as necessary. |
| 178 | ResultCode UnmapRange(VAddr target, u32 size); | 180 | ResultCode UnmapRange(VAddr target, u32 size); |
| @@ -228,5 +230,4 @@ private: | |||
| 228 | /// Updates the pages corresponding to this VMA so they match the VMA's attributes. | 230 | /// Updates the pages corresponding to this VMA so they match the VMA's attributes. |
| 229 | void UpdatePageTableForVMA(const VirtualMemoryArea& vma); | 231 | void UpdatePageTableForVMA(const VirtualMemoryArea& vma); |
| 230 | }; | 232 | }; |
| 231 | |||
| 232 | } | 233 | } |
diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 268a8dad2..6e3dd9cd2 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h | |||
| @@ -26,7 +26,8 @@ enum class ErrorDescription : u32 { | |||
| 26 | FS_InvalidOpenFlags = 230, | 26 | FS_InvalidOpenFlags = 230, |
| 27 | FS_NotAFile = 250, | 27 | FS_NotAFile = 250, |
| 28 | FS_NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive | 28 | FS_NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive |
| 29 | OutofRangeOrMisalignedAddress = 513, // TODO(purpasmart): Check if this name fits its actual usage | 29 | OutofRangeOrMisalignedAddress = |
| 30 | 513, // TODO(purpasmart): Check if this name fits its actual usage | ||
| 30 | GPU_FirstInitialization = 519, | 31 | GPU_FirstInitialization = 519, |
| 31 | FS_InvalidPath = 702, | 32 | FS_InvalidPath = 702, |
| 32 | InvalidSection = 1000, | 33 | InvalidSection = 1000, |
| @@ -168,15 +169,15 @@ enum class ErrorSummary : u32 { | |||
| 168 | Success = 0, | 169 | Success = 0, |
| 169 | NothingHappened = 1, | 170 | NothingHappened = 1, |
| 170 | WouldBlock = 2, | 171 | WouldBlock = 2, |
| 171 | OutOfResource = 3, ///< There are no more kernel resources (memory, table slots) to | 172 | OutOfResource = 3, ///< There are no more kernel resources (memory, table slots) to |
| 172 | ///< execute the operation. | 173 | ///< execute the operation. |
| 173 | NotFound = 4, ///< A file or resource was not found. | 174 | NotFound = 4, ///< A file or resource was not found. |
| 174 | InvalidState = 5, | 175 | InvalidState = 5, |
| 175 | NotSupported = 6, ///< The operation is not supported or not implemented. | 176 | NotSupported = 6, ///< The operation is not supported or not implemented. |
| 176 | InvalidArgument = 7, ///< Returned when a passed argument is invalid in the current runtime | 177 | InvalidArgument = 7, ///< Returned when a passed argument is invalid in the current runtime |
| 177 | ///< context. (Invalid handle, out-of-bounds pointer or size, etc.) | 178 | ///< context. (Invalid handle, out-of-bounds pointer or size, etc.) |
| 178 | WrongArgument = 8, ///< Returned when a passed argument is in an incorrect format for use | 179 | WrongArgument = 8, ///< Returned when a passed argument is in an incorrect format for use |
| 179 | ///< with the function. (E.g. Invalid enum value) | 180 | ///< with the function. (E.g. Invalid enum value) |
| 180 | Canceled = 9, | 181 | Canceled = 9, |
| 181 | StatusChanged = 10, | 182 | StatusChanged = 10, |
| 182 | Internal = 11, | 183 | Internal = 11, |
| @@ -208,19 +209,25 @@ union ResultCode { | |||
| 208 | BitField<21, 6, ErrorSummary> summary; | 209 | BitField<21, 6, ErrorSummary> summary; |
| 209 | BitField<27, 5, ErrorLevel> level; | 210 | BitField<27, 5, ErrorLevel> level; |
| 210 | 211 | ||
| 211 | // The last bit of `level` is checked by apps and the kernel to determine if a result code is an error | 212 | // The last bit of `level` is checked by apps and the kernel to determine if a result code is an |
| 213 | // error | ||
| 212 | BitField<31, 1, u32> is_error; | 214 | BitField<31, 1, u32> is_error; |
| 213 | 215 | ||
| 214 | explicit ResultCode(u32 raw) : raw(raw) {} | 216 | explicit ResultCode(u32 raw) : raw(raw) { |
| 215 | ResultCode(ErrorDescription description_, ErrorModule module_, | 217 | } |
| 216 | ErrorSummary summary_, ErrorLevel level_) : raw(0) { | 218 | ResultCode(ErrorDescription description_, ErrorModule module_, ErrorSummary summary_, |
| 219 | ErrorLevel level_) | ||
| 220 | : raw(0) { | ||
| 217 | description.Assign(description_); | 221 | description.Assign(description_); |
| 218 | module.Assign(module_); | 222 | module.Assign(module_); |
| 219 | summary.Assign(summary_); | 223 | summary.Assign(summary_); |
| 220 | level.Assign(level_); | 224 | level.Assign(level_); |
| 221 | } | 225 | } |
| 222 | 226 | ||
| 223 | ResultCode& operator=(const ResultCode& o) { raw = o.raw; return *this; } | 227 | ResultCode& operator=(const ResultCode& o) { |
| 228 | raw = o.raw; | ||
| 229 | return *this; | ||
| 230 | } | ||
| 224 | 231 | ||
| 225 | bool IsSuccess() const { | 232 | bool IsSuccess() const { |
| 226 | return is_error == 0; | 233 | return is_error == 0; |
| @@ -246,8 +253,8 @@ const ResultCode RESULT_SUCCESS(0); | |||
| 246 | 253 | ||
| 247 | /// Might be returned instead of a dummy success for unimplemented APIs. | 254 | /// Might be returned instead of a dummy success for unimplemented APIs. |
| 248 | inline ResultCode UnimplementedFunction(ErrorModule module) { | 255 | inline ResultCode UnimplementedFunction(ErrorModule module) { |
| 249 | return ResultCode(ErrorDescription::NotImplemented, module, | 256 | return ResultCode(ErrorDescription::NotImplemented, module, ErrorSummary::NotSupported, |
| 250 | ErrorSummary::NotSupported, ErrorLevel::Permanent); | 257 | ErrorLevel::Permanent); |
| 251 | } | 258 | } |
| 252 | 259 | ||
| 253 | /** | 260 | /** |
| @@ -285,10 +292,9 @@ inline ResultCode UnimplementedFunction(ErrorModule module) { | |||
| 285 | template <typename T> | 292 | template <typename T> |
| 286 | class ResultVal { | 293 | class ResultVal { |
| 287 | public: | 294 | public: |
| 288 | /// Constructs an empty `ResultVal` with the given error code. The code must not be a success code. | 295 | /// Constructs an empty `ResultVal` with the given error code. The code must not be a success |
| 289 | ResultVal(ResultCode error_code = ResultCode(-1)) | 296 | /// code. |
| 290 | : result_code(error_code) | 297 | ResultVal(ResultCode error_code = ResultCode(-1)) : result_code(error_code) { |
| 291 | { | ||
| 292 | ASSERT(error_code.IsError()); | 298 | ASSERT(error_code.IsError()); |
| 293 | } | 299 | } |
| 294 | 300 | ||
| @@ -303,17 +309,13 @@ public: | |||
| 303 | return result; | 309 | return result; |
| 304 | } | 310 | } |
| 305 | 311 | ||
| 306 | ResultVal(const ResultVal& o) | 312 | ResultVal(const ResultVal& o) : result_code(o.result_code) { |
| 307 | : result_code(o.result_code) | ||
| 308 | { | ||
| 309 | if (!o.empty()) { | 313 | if (!o.empty()) { |
| 310 | new (&object) T(o.object); | 314 | new (&object) T(o.object); |
| 311 | } | 315 | } |
| 312 | } | 316 | } |
| 313 | 317 | ||
| 314 | ResultVal(ResultVal&& o) | 318 | ResultVal(ResultVal&& o) : result_code(o.result_code) { |
| 315 | : result_code(o.result_code) | ||
| 316 | { | ||
| 317 | if (!o.empty()) { | 319 | if (!o.empty()) { |
| 318 | new (&object) T(std::move(o.object)); | 320 | new (&object) T(std::move(o.object)); |
| 319 | } | 321 | } |
| @@ -357,19 +359,35 @@ public: | |||
| 357 | } | 359 | } |
| 358 | 360 | ||
| 359 | /// Returns true if the `ResultVal` contains an error code and no value. | 361 | /// Returns true if the `ResultVal` contains an error code and no value. |
| 360 | bool empty() const { return result_code.IsError(); } | 362 | bool empty() const { |
| 363 | return result_code.IsError(); | ||
| 364 | } | ||
| 361 | 365 | ||
| 362 | /// Returns true if the `ResultVal` contains a return value. | 366 | /// Returns true if the `ResultVal` contains a return value. |
| 363 | bool Succeeded() const { return result_code.IsSuccess(); } | 367 | bool Succeeded() const { |
| 368 | return result_code.IsSuccess(); | ||
| 369 | } | ||
| 364 | /// Returns true if the `ResultVal` contains an error code and no value. | 370 | /// Returns true if the `ResultVal` contains an error code and no value. |
| 365 | bool Failed() const { return empty(); } | 371 | bool Failed() const { |
| 372 | return empty(); | ||
| 373 | } | ||
| 366 | 374 | ||
| 367 | ResultCode Code() const { return result_code; } | 375 | ResultCode Code() const { |
| 376 | return result_code; | ||
| 377 | } | ||
| 368 | 378 | ||
| 369 | const T& operator* () const { return object; } | 379 | const T& operator*() const { |
| 370 | T& operator* () { return object; } | 380 | return object; |
| 371 | const T* operator->() const { return &object; } | 381 | } |
| 372 | T* operator->() { return &object; } | 382 | T& operator*() { |
| 383 | return object; | ||
| 384 | } | ||
| 385 | const T* operator->() const { | ||
| 386 | return &object; | ||
| 387 | } | ||
| 388 | T* operator->() { | ||
| 389 | return &object; | ||
| 390 | } | ||
| 373 | 391 | ||
| 374 | /// Returns the value contained in this `ResultVal`, or the supplied default if it is missing. | 392 | /// Returns the value contained in this `ResultVal`, or the supplied default if it is missing. |
| 375 | template <typename U> | 393 | template <typename U> |
| @@ -390,7 +408,9 @@ public: | |||
| 390 | private: | 408 | private: |
| 391 | // A union is used to allocate the storage for the value, while allowing us to construct and | 409 | // A union is used to allocate the storage for the value, while allowing us to construct and |
| 392 | // destruct it at will. | 410 | // destruct it at will. |
| 393 | union { T object; }; | 411 | union { |
| 412 | T object; | ||
| 413 | }; | ||
| 394 | ResultCode result_code; | 414 | ResultCode result_code; |
| 395 | }; | 415 | }; |
| 396 | 416 | ||
| @@ -409,8 +429,8 @@ ResultVal<T> MakeResult(Args&&... args) { | |||
| 409 | * variable declaration. If it fails the return code is returned from the current function. Thus it | 429 | * variable declaration. If it fails the return code is returned from the current function. Thus it |
| 410 | * can be used to cascade errors out, achieving something akin to exception handling. | 430 | * can be used to cascade errors out, achieving something akin to exception handling. |
| 411 | */ | 431 | */ |
| 412 | #define CASCADE_RESULT(target, source) \ | 432 | #define CASCADE_RESULT(target, source) \ |
| 413 | auto CONCAT2(check_result_L, __LINE__) = source; \ | 433 | auto CONCAT2(check_result_L, __LINE__) = source; \ |
| 414 | if (CONCAT2(check_result_L, __LINE__).Failed()) \ | 434 | if (CONCAT2(check_result_L, __LINE__).Failed()) \ |
| 415 | return CONCAT2(check_result_L, __LINE__).Code(); \ | 435 | return CONCAT2(check_result_L, __LINE__).Code(); \ |
| 416 | target = std::move(*CONCAT2(check_result_L, __LINE__)) | 436 | target = std::move(*CONCAT2(check_result_L, __LINE__)) |
diff --git a/src/core/hle/service/ac_u.cpp b/src/core/hle/service/ac_u.cpp index 5241dd3e7..887b57529 100644 --- a/src/core/hle/service/ac_u.cpp +++ b/src/core/hle/service/ac_u.cpp | |||
| @@ -47,7 +47,7 @@ static void GetWifiStatus(Service::Interface* self) { | |||
| 47 | // it returns a valid result without implementing full functionality. | 47 | // it returns a valid result without implementing full functionality. |
| 48 | 48 | ||
| 49 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 49 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 50 | cmd_buff[2] = 0; // Connection type set to none | 50 | cmd_buff[2] = 0; // Connection type set to none |
| 51 | 51 | ||
| 52 | LOG_WARNING(Service_AC, "(STUBBED) called"); | 52 | LOG_WARNING(Service_AC, "(STUBBED) called"); |
| 53 | } | 53 | } |
| @@ -62,29 +62,29 @@ static void IsConnected(Service::Interface* self) { | |||
| 62 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 62 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 63 | 63 | ||
| 64 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 64 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 65 | cmd_buff[2] = false; // Not connected to ac:u service | 65 | cmd_buff[2] = false; // Not connected to ac:u service |
| 66 | 66 | ||
| 67 | LOG_WARNING(Service_AC, "(STUBBED) called"); | 67 | LOG_WARNING(Service_AC, "(STUBBED) called"); |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | const Interface::FunctionInfo FunctionTable[] = { | 70 | const Interface::FunctionInfo FunctionTable[] = { |
| 71 | {0x00010000, nullptr, "CreateDefaultConfig"}, | 71 | {0x00010000, nullptr, "CreateDefaultConfig"}, |
| 72 | {0x00040006, nullptr, "ConnectAsync"}, | 72 | {0x00040006, nullptr, "ConnectAsync"}, |
| 73 | {0x00050002, nullptr, "GetConnectResult"}, | 73 | {0x00050002, nullptr, "GetConnectResult"}, |
| 74 | {0x00080004, CloseAsync, "CloseAsync"}, | 74 | {0x00080004, CloseAsync, "CloseAsync"}, |
| 75 | {0x00090002, nullptr, "GetCloseResult"}, | 75 | {0x00090002, nullptr, "GetCloseResult"}, |
| 76 | {0x000A0000, nullptr, "GetLastErrorCode"}, | 76 | {0x000A0000, nullptr, "GetLastErrorCode"}, |
| 77 | {0x000D0000, GetWifiStatus, "GetWifiStatus"}, | 77 | {0x000D0000, GetWifiStatus, "GetWifiStatus"}, |
| 78 | {0x000E0042, nullptr, "GetCurrentAPInfo"}, | 78 | {0x000E0042, nullptr, "GetCurrentAPInfo"}, |
| 79 | {0x00100042, nullptr, "GetCurrentNZoneInfo"}, | 79 | {0x00100042, nullptr, "GetCurrentNZoneInfo"}, |
| 80 | {0x00110042, nullptr, "GetNZoneApNumService"}, | 80 | {0x00110042, nullptr, "GetNZoneApNumService"}, |
| 81 | {0x00240042, nullptr, "AddDenyApType"}, | 81 | {0x00240042, nullptr, "AddDenyApType"}, |
| 82 | {0x00270002, nullptr, "GetInfraPriority"}, | 82 | {0x00270002, nullptr, "GetInfraPriority"}, |
| 83 | {0x002D0082, nullptr, "SetRequestEulaVersion"}, | 83 | {0x002D0082, nullptr, "SetRequestEulaVersion"}, |
| 84 | {0x00300004, nullptr, "RegisterDisconnectEvent"}, | 84 | {0x00300004, nullptr, "RegisterDisconnectEvent"}, |
| 85 | {0x003C0042, nullptr, "GetAPSSIDList"}, | 85 | {0x003C0042, nullptr, "GetAPSSIDList"}, |
| 86 | {0x003E0042, IsConnected, "IsConnected"}, | 86 | {0x003E0042, IsConnected, "IsConnected"}, |
| 87 | {0x00400042, nullptr, "SetClientVersion"}, | 87 | {0x00400042, nullptr, "SetClientVersion"}, |
| 88 | }; | 88 | }; |
| 89 | 89 | ||
| 90 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 90 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 3f71e7f2b..b653523a4 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -6,19 +6,19 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | 8 | ||
| 9 | #include "core/hle/service/service.h" | ||
| 10 | #include "core/hle/service/am/am.h" | 9 | #include "core/hle/service/am/am.h" |
| 11 | #include "core/hle/service/am/am_app.h" | 10 | #include "core/hle/service/am/am_app.h" |
| 12 | #include "core/hle/service/am/am_net.h" | 11 | #include "core/hle/service/am/am_net.h" |
| 13 | #include "core/hle/service/am/am_sys.h" | 12 | #include "core/hle/service/am/am_sys.h" |
| 14 | #include "core/hle/service/am/am_u.h" | 13 | #include "core/hle/service/am/am_u.h" |
| 14 | #include "core/hle/service/service.h" | ||
| 15 | 15 | ||
| 16 | namespace Service { | 16 | namespace Service { |
| 17 | namespace AM { | 17 | namespace AM { |
| 18 | 18 | ||
| 19 | static std::array<u32, 3> am_content_count = { 0, 0, 0 }; | 19 | static std::array<u32, 3> am_content_count = {0, 0, 0}; |
| 20 | static std::array<u32, 3> am_titles_count = { 0, 0, 0 }; | 20 | static std::array<u32, 3> am_titles_count = {0, 0, 0}; |
| 21 | static std::array<u32, 3> am_titles_list_count = { 0, 0, 0 }; | 21 | static std::array<u32, 3> am_titles_list_count = {0, 0, 0}; |
| 22 | static u32 am_ticket_count = 0; | 22 | static u32 am_ticket_count = 0; |
| 23 | static u32 am_ticket_list_count = 0; | 23 | static u32 am_ticket_list_count = 0; |
| 24 | 24 | ||
| @@ -29,7 +29,8 @@ void GetTitleCount(Service::Interface* self) { | |||
| 29 | 29 | ||
| 30 | cmd_buff[1] = RESULT_SUCCESS.raw; | 30 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 31 | cmd_buff[2] = am_titles_count[media_type]; | 31 | cmd_buff[2] = am_titles_count[media_type]; |
| 32 | LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_count=0x%08x", media_type, am_titles_count[media_type]); | 32 | LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_count=0x%08x", media_type, |
| 33 | am_titles_count[media_type]); | ||
| 33 | } | 34 | } |
| 34 | 35 | ||
| 35 | void FindContentInfos(Service::Interface* self) { | 36 | void FindContentInfos(Service::Interface* self) { |
| @@ -43,8 +44,10 @@ void FindContentInfos(Service::Interface* self) { | |||
| 43 | am_content_count[media_type] = cmd_buff[4]; | 44 | am_content_count[media_type] = cmd_buff[4]; |
| 44 | 45 | ||
| 45 | cmd_buff[1] = RESULT_SUCCESS.raw; | 46 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 46 | LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_id=0x%016llx, content_cound=%u, content_ids_pointer=0x%08x, content_info_pointer=0x%08x", | 47 | LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_id=0x%016llx, content_cound=%u, " |
| 47 | media_type, title_id, am_content_count[media_type], content_ids_pointer, content_info_pointer); | 48 | "content_ids_pointer=0x%08x, content_info_pointer=0x%08x", |
| 49 | media_type, title_id, am_content_count[media_type], content_ids_pointer, | ||
| 50 | content_info_pointer); | ||
| 48 | } | 51 | } |
| 49 | 52 | ||
| 50 | void ListContentInfos(Service::Interface* self) { | 53 | void ListContentInfos(Service::Interface* self) { |
| @@ -59,8 +62,10 @@ void ListContentInfos(Service::Interface* self) { | |||
| 59 | 62 | ||
| 60 | cmd_buff[1] = RESULT_SUCCESS.raw; | 63 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 61 | cmd_buff[2] = am_content_count[media_type]; | 64 | cmd_buff[2] = am_content_count[media_type]; |
| 62 | LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, content_count=%u, title_id=0x%016" PRIx64 ", start_index=0x%08x, content_info_pointer=0x%08X", | 65 | LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, content_count=%u, title_id=0x%016" PRIx64 |
| 63 | media_type, am_content_count[media_type], title_id, start_index, content_info_pointer); | 66 | ", start_index=0x%08x, content_info_pointer=0x%08X", |
| 67 | media_type, am_content_count[media_type], title_id, start_index, | ||
| 68 | content_info_pointer); | ||
| 64 | } | 69 | } |
| 65 | 70 | ||
| 66 | void DeleteContents(Service::Interface* self) { | 71 | void DeleteContents(Service::Interface* self) { |
| @@ -73,8 +78,9 @@ void DeleteContents(Service::Interface* self) { | |||
| 73 | am_content_count[media_type] = cmd_buff[4]; | 78 | am_content_count[media_type] = cmd_buff[4]; |
| 74 | 79 | ||
| 75 | cmd_buff[1] = RESULT_SUCCESS.raw; | 80 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 76 | LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_id=0x%016" PRIx64 ", content_count=%u, content_ids_pointer=0x%08x", | 81 | LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_id=0x%016" PRIx64 |
| 77 | media_type, title_id, am_content_count[media_type], content_ids_pointer); | 82 | ", content_count=%u, content_ids_pointer=0x%08x", |
| 83 | media_type, title_id, am_content_count[media_type], content_ids_pointer); | ||
| 78 | } | 84 | } |
| 79 | 85 | ||
| 80 | void GetTitleList(Service::Interface* self) { | 86 | void GetTitleList(Service::Interface* self) { |
| @@ -87,8 +93,10 @@ void GetTitleList(Service::Interface* self) { | |||
| 87 | 93 | ||
| 88 | cmd_buff[1] = RESULT_SUCCESS.raw; | 94 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 89 | cmd_buff[2] = am_titles_list_count[media_type]; | 95 | cmd_buff[2] = am_titles_list_count[media_type]; |
| 90 | LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, titles_list_count=0x%08X, title_ids_output_pointer=0x%08X", | 96 | LOG_WARNING( |
| 91 | media_type, am_titles_list_count[media_type], title_ids_output_pointer); | 97 | Service_AM, |
| 98 | "(STUBBED) media_type=%u, titles_list_count=0x%08X, title_ids_output_pointer=0x%08X", | ||
| 99 | media_type, am_titles_list_count[media_type], title_ids_output_pointer); | ||
| 92 | } | 100 | } |
| 93 | 101 | ||
| 94 | void GetTitleInfo(Service::Interface* self) { | 102 | void GetTitleInfo(Service::Interface* self) { |
| @@ -101,7 +109,8 @@ void GetTitleInfo(Service::Interface* self) { | |||
| 101 | am_titles_count[media_type] = cmd_buff[2]; | 109 | am_titles_count[media_type] = cmd_buff[2]; |
| 102 | 110 | ||
| 103 | cmd_buff[1] = RESULT_SUCCESS.raw; | 111 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 104 | LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, total_titles=0x%08X, title_id_list_pointer=0x%08X, title_list_pointer=0x%08X", | 112 | LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, total_titles=0x%08X, " |
| 113 | "title_id_list_pointer=0x%08X, title_list_pointer=0x%08X", | ||
| 105 | media_type, am_titles_count[media_type], title_id_list_pointer, title_list_pointer); | 114 | media_type, am_titles_count[media_type], title_id_list_pointer, title_list_pointer); |
| 106 | } | 115 | } |
| 107 | 116 | ||
| @@ -122,8 +131,9 @@ void ListDataTitleTicketInfos(Service::Interface* self) { | |||
| 122 | 131 | ||
| 123 | cmd_buff[1] = RESULT_SUCCESS.raw; | 132 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 124 | cmd_buff[2] = am_ticket_count; | 133 | cmd_buff[2] = am_ticket_count; |
| 125 | LOG_WARNING(Service_AM, "(STUBBED) ticket_count=0x%08X, title_id=0x%016" PRIx64 ", start_index=0x%08X, ticket_info_pointer=0x%08X", | 134 | LOG_WARNING(Service_AM, "(STUBBED) ticket_count=0x%08X, title_id=0x%016" PRIx64 |
| 126 | am_ticket_count, title_id, start_index, ticket_info_pointer); | 135 | ", start_index=0x%08X, ticket_info_pointer=0x%08X", |
| 136 | am_ticket_count, title_id, start_index, ticket_info_pointer); | ||
| 127 | } | 137 | } |
| 128 | 138 | ||
| 129 | void GetNumContentInfos(Service::Interface* self) { | 139 | void GetNumContentInfos(Service::Interface* self) { |
| @@ -140,7 +150,7 @@ void DeleteTicket(Service::Interface* self) { | |||
| 140 | u64 title_id = (static_cast<u64>(cmd_buff[2]) << 32) | cmd_buff[1]; | 150 | u64 title_id = (static_cast<u64>(cmd_buff[2]) << 32) | cmd_buff[1]; |
| 141 | 151 | ||
| 142 | cmd_buff[1] = RESULT_SUCCESS.raw; | 152 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 143 | LOG_WARNING(Service_AM, "(STUBBED) called title_id=0x%016" PRIx64 "",title_id); | 153 | LOG_WARNING(Service_AM, "(STUBBED) called title_id=0x%016" PRIx64 "", title_id); |
| 144 | } | 154 | } |
| 145 | 155 | ||
| 146 | void GetTicketCount(Service::Interface* self) { | 156 | void GetTicketCount(Service::Interface* self) { |
| @@ -148,7 +158,7 @@ void GetTicketCount(Service::Interface* self) { | |||
| 148 | 158 | ||
| 149 | cmd_buff[1] = RESULT_SUCCESS.raw; | 159 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 150 | cmd_buff[2] = am_ticket_count; | 160 | cmd_buff[2] = am_ticket_count; |
| 151 | LOG_WARNING(Service_AM, "(STUBBED) called ticket_count=0x%08x",am_ticket_count); | 161 | LOG_WARNING(Service_AM, "(STUBBED) called ticket_count=0x%08x", am_ticket_count); |
| 152 | } | 162 | } |
| 153 | 163 | ||
| 154 | void GetTicketList(Service::Interface* self) { | 164 | void GetTicketList(Service::Interface* self) { |
| @@ -161,8 +171,10 @@ void GetTicketList(Service::Interface* self) { | |||
| 161 | 171 | ||
| 162 | cmd_buff[1] = RESULT_SUCCESS.raw; | 172 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 163 | cmd_buff[2] = am_ticket_list_count; | 173 | cmd_buff[2] = am_ticket_list_count; |
| 164 | LOG_WARNING(Service_AM, "(STUBBED) ticket_list_count=0x%08x, num_of_skip=0x%08x, ticket_list_pointer=0x%08x", | 174 | LOG_WARNING( |
| 165 | am_ticket_list_count, num_of_skip, ticket_list_pointer); | 175 | Service_AM, |
| 176 | "(STUBBED) ticket_list_count=0x%08x, num_of_skip=0x%08x, ticket_list_pointer=0x%08x", | ||
| 177 | am_ticket_list_count, num_of_skip, ticket_list_pointer); | ||
| 166 | } | 178 | } |
| 167 | 179 | ||
| 168 | void Init() { | 180 | void Init() { |
| @@ -175,7 +187,6 @@ void Init() { | |||
| 175 | } | 187 | } |
| 176 | 188 | ||
| 177 | void Shutdown() { | 189 | void Shutdown() { |
| 178 | |||
| 179 | } | 190 | } |
| 180 | 191 | ||
| 181 | } // namespace AM | 192 | } // namespace AM |
diff --git a/src/core/hle/service/am/am_app.cpp b/src/core/hle/service/am/am_app.cpp index d27b3defd..bfc1ca6bd 100644 --- a/src/core/hle/service/am/am_app.cpp +++ b/src/core/hle/service/am/am_app.cpp | |||
| @@ -9,14 +9,14 @@ namespace Service { | |||
| 9 | namespace AM { | 9 | namespace AM { |
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = { |
| 12 | {0x100100C0, GetNumContentInfos, "GetNumContentInfos"}, | 12 | {0x100100C0, GetNumContentInfos, "GetNumContentInfos"}, |
| 13 | {0x10020104, FindContentInfos, "FindContentInfos"}, | 13 | {0x10020104, FindContentInfos, "FindContentInfos"}, |
| 14 | {0x10030142, ListContentInfos, "ListContentInfos"}, | 14 | {0x10030142, ListContentInfos, "ListContentInfos"}, |
| 15 | {0x10040102, DeleteContents, "DeleteContents"}, | 15 | {0x10040102, DeleteContents, "DeleteContents"}, |
| 16 | {0x10050084, GetDataTitleInfos, "GetDataTitleInfos"}, | 16 | {0x10050084, GetDataTitleInfos, "GetDataTitleInfos"}, |
| 17 | {0x10070102, ListDataTitleTicketInfos, "ListDataTitleTicketInfos"}, | 17 | {0x10070102, ListDataTitleTicketInfos, "ListDataTitleTicketInfos"}, |
| 18 | {0x100900C0, nullptr, "IsDataTitleInUse"}, | 18 | {0x100900C0, nullptr, "IsDataTitleInUse"}, |
| 19 | {0x100A0000, nullptr, "IsExternalTitleDatabaseInitialized"}, | 19 | {0x100A0000, nullptr, "IsExternalTitleDatabaseInitialized"}, |
| 20 | }; | 20 | }; |
| 21 | 21 | ||
| 22 | AM_APP_Interface::AM_APP_Interface() { | 22 | AM_APP_Interface::AM_APP_Interface() { |
diff --git a/src/core/hle/service/am/am_net.cpp b/src/core/hle/service/am/am_net.cpp index e75755245..3a597a34c 100644 --- a/src/core/hle/service/am/am_net.cpp +++ b/src/core/hle/service/am/am_net.cpp | |||
| @@ -9,61 +9,61 @@ namespace Service { | |||
| 9 | namespace AM { | 9 | namespace AM { |
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = { |
| 12 | {0x00010040, GetTitleCount, "GetTitleCount"}, | 12 | {0x00010040, GetTitleCount, "GetTitleCount"}, |
| 13 | {0x00020082, GetTitleList, "GetTitleList"}, | 13 | {0x00020082, GetTitleList, "GetTitleList"}, |
| 14 | {0x00030084, GetTitleInfo, "GetTitleInfo"}, | 14 | {0x00030084, GetTitleInfo, "GetTitleInfo"}, |
| 15 | {0x000400C0, nullptr, "DeleteApplicationTitle"}, | 15 | {0x000400C0, nullptr, "DeleteApplicationTitle"}, |
| 16 | {0x000500C0, nullptr, "GetTitleProductCode"}, | 16 | {0x000500C0, nullptr, "GetTitleProductCode"}, |
| 17 | {0x000600C0, nullptr, "GetTitleExtDataId"}, | 17 | {0x000600C0, nullptr, "GetTitleExtDataId"}, |
| 18 | {0x00070080, DeleteTicket, "DeleteTicket"}, | 18 | {0x00070080, DeleteTicket, "DeleteTicket"}, |
| 19 | {0x00080000, GetTicketCount, "GetTicketCount"}, | 19 | {0x00080000, GetTicketCount, "GetTicketCount"}, |
| 20 | {0x00090082, GetTicketList, "GetTicketList"}, | 20 | {0x00090082, GetTicketList, "GetTicketList"}, |
| 21 | {0x000A0000, nullptr, "GetDeviceID"}, | 21 | {0x000A0000, nullptr, "GetDeviceID"}, |
| 22 | {0x000D0084, nullptr, "GetPendingTitleInfo"}, | 22 | {0x000D0084, nullptr, "GetPendingTitleInfo"}, |
| 23 | {0x000E00C0, nullptr, "DeletePendingTitle"}, | 23 | {0x000E00C0, nullptr, "DeletePendingTitle"}, |
| 24 | {0x00140040, nullptr, "FinalizePendingTitles"}, | 24 | {0x00140040, nullptr, "FinalizePendingTitles"}, |
| 25 | {0x00150040, nullptr, "DeleteAllPendingTitles"}, | 25 | {0x00150040, nullptr, "DeleteAllPendingTitles"}, |
| 26 | {0x00180080, nullptr, "InitializeTitleDatabase"}, | 26 | {0x00180080, nullptr, "InitializeTitleDatabase"}, |
| 27 | {0x00190040, nullptr, "ReloadDBS"}, | 27 | {0x00190040, nullptr, "ReloadDBS"}, |
| 28 | {0x001A00C0, nullptr, "GetDSiWareExportSize"}, | 28 | {0x001A00C0, nullptr, "GetDSiWareExportSize"}, |
| 29 | {0x001B0144, nullptr, "ExportDSiWare"}, | 29 | {0x001B0144, nullptr, "ExportDSiWare"}, |
| 30 | {0x001C0084, nullptr, "ImportDSiWare"}, | 30 | {0x001C0084, nullptr, "ImportDSiWare"}, |
| 31 | {0x00230080, nullptr, "TitleIDListGetTotal2"}, | 31 | {0x00230080, nullptr, "TitleIDListGetTotal2"}, |
| 32 | {0x002400C2, nullptr, "GetTitleIDList2"}, | 32 | {0x002400C2, nullptr, "GetTitleIDList2"}, |
| 33 | {0x04010080, nullptr, "InstallFIRM"}, | 33 | {0x04010080, nullptr, "InstallFIRM"}, |
| 34 | {0x04020040, nullptr, "StartInstallCIADB0"}, | 34 | {0x04020040, nullptr, "StartInstallCIADB0"}, |
| 35 | {0x04030000, nullptr, "StartInstallCIADB1"}, | 35 | {0x04030000, nullptr, "StartInstallCIADB1"}, |
| 36 | {0x04040002, nullptr, "AbortCIAInstall"}, | 36 | {0x04040002, nullptr, "AbortCIAInstall"}, |
| 37 | {0x04050002, nullptr, "CloseCIAFinalizeInstall"}, | 37 | {0x04050002, nullptr, "CloseCIAFinalizeInstall"}, |
| 38 | {0x04060002, nullptr, "CloseCIA"}, | 38 | {0x04060002, nullptr, "CloseCIA"}, |
| 39 | {0x040700C2, nullptr, "FinalizeTitlesInstall"}, | 39 | {0x040700C2, nullptr, "FinalizeTitlesInstall"}, |
| 40 | {0x04080042, nullptr, "GetCiaFileInfo"}, | 40 | {0x04080042, nullptr, "GetCiaFileInfo"}, |
| 41 | {0x040E00C2, nullptr, "InstallTitlesFinish"}, | 41 | {0x040E00C2, nullptr, "InstallTitlesFinish"}, |
| 42 | {0x040F0000, nullptr, "InstallNATIVEFIRM"}, | 42 | {0x040F0000, nullptr, "InstallNATIVEFIRM"}, |
| 43 | {0x041000C0, nullptr, "DeleteTitle"}, | 43 | {0x041000C0, nullptr, "DeleteTitle"}, |
| 44 | {0x04120000, nullptr, "Initialize"}, | 44 | {0x04120000, nullptr, "Initialize"}, |
| 45 | {0x041700C0, nullptr, "MigrateAGBtoSAV"}, | 45 | {0x041700C0, nullptr, "MigrateAGBtoSAV"}, |
| 46 | {0x08010000, nullptr, "OpenTicket"}, | 46 | {0x08010000, nullptr, "OpenTicket"}, |
| 47 | {0x08020002, nullptr, "TicketAbortInstall"}, | 47 | {0x08020002, nullptr, "TicketAbortInstall"}, |
| 48 | {0x08030002, nullptr, "TicketFinalizeInstall"}, | 48 | {0x08030002, nullptr, "TicketFinalizeInstall"}, |
| 49 | {0x08040100, nullptr, "InstallTitleBegin"}, | 49 | {0x08040100, nullptr, "InstallTitleBegin"}, |
| 50 | {0x08050000, nullptr, "InstallTitleAbort"}, | 50 | {0x08050000, nullptr, "InstallTitleAbort"}, |
| 51 | {0x080600C0, nullptr, "InstallTitleResume"}, | 51 | {0x080600C0, nullptr, "InstallTitleResume"}, |
| 52 | {0x08070000, nullptr, "InstallTitleAbortTMD"}, | 52 | {0x08070000, nullptr, "InstallTitleAbortTMD"}, |
| 53 | {0x08080000, nullptr, "InstallTitleFinish"}, | 53 | {0x08080000, nullptr, "InstallTitleFinish"}, |
| 54 | {0x080A0000, nullptr, "OpenTMD"}, | 54 | {0x080A0000, nullptr, "OpenTMD"}, |
| 55 | {0x080B0002, nullptr, "TMDAbortInstall"}, | 55 | {0x080B0002, nullptr, "TMDAbortInstall"}, |
| 56 | {0x080C0042, nullptr, "TMDFinalizeInstall"}, | 56 | {0x080C0042, nullptr, "TMDFinalizeInstall"}, |
| 57 | {0x080E0040, nullptr, "OpenContentCreate"}, | 57 | {0x080E0040, nullptr, "OpenContentCreate"}, |
| 58 | {0x080F0002, nullptr, "ContentAbortInstall"}, | 58 | {0x080F0002, nullptr, "ContentAbortInstall"}, |
| 59 | {0x08100040, nullptr, "OpenContentResume"}, | 59 | {0x08100040, nullptr, "OpenContentResume"}, |
| 60 | {0x08120002, nullptr, "ContentFinalizeInstall"}, | 60 | {0x08120002, nullptr, "ContentFinalizeInstall"}, |
| 61 | {0x08130000, nullptr, "GetTotalContents"}, | 61 | {0x08130000, nullptr, "GetTotalContents"}, |
| 62 | {0x08140042, nullptr, "GetContentIndexes"}, | 62 | {0x08140042, nullptr, "GetContentIndexes"}, |
| 63 | {0x08150044, nullptr, "GetContentsInfo"}, | 63 | {0x08150044, nullptr, "GetContentsInfo"}, |
| 64 | {0x08180042, nullptr, "GetCTCert"}, | 64 | {0x08180042, nullptr, "GetCTCert"}, |
| 65 | {0x08190108, nullptr, "SetCertificates"}, | 65 | {0x08190108, nullptr, "SetCertificates"}, |
| 66 | {0x081B00C2, nullptr, "InstallTitlesFinish"}, | 66 | {0x081B00C2, nullptr, "InstallTitlesFinish"}, |
| 67 | }; | 67 | }; |
| 68 | 68 | ||
| 69 | AM_NET_Interface::AM_NET_Interface() { | 69 | AM_NET_Interface::AM_NET_Interface() { |
diff --git a/src/core/hle/service/am/am_sys.cpp b/src/core/hle/service/am/am_sys.cpp index 8bad5e1c9..8bb58cab7 100644 --- a/src/core/hle/service/am/am_sys.cpp +++ b/src/core/hle/service/am/am_sys.cpp | |||
| @@ -8,29 +8,27 @@ | |||
| 8 | namespace Service { | 8 | namespace Service { |
| 9 | namespace AM { | 9 | namespace AM { |
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = {{0x00010040, GetTitleCount, "GetTitleCount"}, |
| 12 | {0x00010040, GetTitleCount, "GetTitleCount"}, | 12 | {0x00020082, GetTitleList, "GetTitleList"}, |
| 13 | {0x00020082, GetTitleList, "GetTitleList"}, | 13 | {0x00030084, GetTitleInfo, "GetTitleInfo"}, |
| 14 | {0x00030084, GetTitleInfo, "GetTitleInfo"}, | 14 | {0x000400C0, nullptr, "DeleteApplicationTitle"}, |
| 15 | {0x000400C0, nullptr, "DeleteApplicationTitle"}, | 15 | {0x000500C0, nullptr, "GetTitleProductCode"}, |
| 16 | {0x000500C0, nullptr, "GetTitleProductCode"}, | 16 | {0x000600C0, nullptr, "GetTitleExtDataId"}, |
| 17 | {0x000600C0, nullptr, "GetTitleExtDataId"}, | 17 | {0x00070080, DeleteTicket, "DeleteTicket"}, |
| 18 | {0x00070080, DeleteTicket, "DeleteTicket"}, | 18 | {0x00080000, GetTicketCount, "GetTicketCount"}, |
| 19 | {0x00080000, GetTicketCount, "GetTicketCount"}, | 19 | {0x00090082, GetTicketList, "GetTicketList"}, |
| 20 | {0x00090082, GetTicketList, "GetTicketList"}, | 20 | {0x000A0000, nullptr, "GetDeviceID"}, |
| 21 | {0x000A0000, nullptr, "GetDeviceID"}, | 21 | {0x000D0084, nullptr, "GetPendingTitleInfo"}, |
| 22 | {0x000D0084, nullptr, "GetPendingTitleInfo"}, | 22 | {0x000E00C0, nullptr, "DeletePendingTitle"}, |
| 23 | {0x000E00C0, nullptr, "DeletePendingTitle"}, | 23 | {0x00140040, nullptr, "FinalizePendingTitles"}, |
| 24 | {0x00140040, nullptr, "FinalizePendingTitles"}, | 24 | {0x00150040, nullptr, "DeleteAllPendingTitles"}, |
| 25 | {0x00150040, nullptr, "DeleteAllPendingTitles"}, | 25 | {0x00180080, nullptr, "InitializeTitleDatabase"}, |
| 26 | {0x00180080, nullptr, "InitializeTitleDatabase"}, | 26 | {0x00190040, nullptr, "ReloadDBS"}, |
| 27 | {0x00190040, nullptr, "ReloadDBS"}, | 27 | {0x001A00C0, nullptr, "GetDSiWareExportSize"}, |
| 28 | {0x001A00C0, nullptr, "GetDSiWareExportSize"}, | 28 | {0x001B0144, nullptr, "ExportDSiWare"}, |
| 29 | {0x001B0144, nullptr, "ExportDSiWare"}, | 29 | {0x001C0084, nullptr, "ImportDSiWare"}, |
| 30 | {0x001C0084, nullptr, "ImportDSiWare"}, | 30 | {0x00230080, nullptr, "GetPendingTitleCount"}, |
| 31 | {0x00230080, nullptr, "GetPendingTitleCount"}, | 31 | {0x002400C2, nullptr, "GetPendingTitleList"}}; |
| 32 | {0x002400C2, nullptr, "GetPendingTitleList"} | ||
| 33 | }; | ||
| 34 | 32 | ||
| 35 | AM_SYS_Interface::AM_SYS_Interface() { | 33 | AM_SYS_Interface::AM_SYS_Interface() { |
| 36 | Register(FunctionTable); | 34 | Register(FunctionTable); |
diff --git a/src/core/hle/service/am/am_u.cpp b/src/core/hle/service/am/am_u.cpp index d583dd9e6..32d47741f 100644 --- a/src/core/hle/service/am/am_u.cpp +++ b/src/core/hle/service/am/am_u.cpp | |||
| @@ -8,42 +8,40 @@ | |||
| 8 | namespace Service { | 8 | namespace Service { |
| 9 | namespace AM { | 9 | namespace AM { |
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = {{0x00010040, GetTitleCount, "GetTitleCount"}, |
| 12 | {0x00010040, GetTitleCount, "GetTitleCount"}, | 12 | {0x00020082, GetTitleList, "GetTitleList"}, |
| 13 | {0x00020082, GetTitleList, "GetTitleList"}, | 13 | {0x00030084, GetTitleInfo, "GetTitleInfo"}, |
| 14 | {0x00030084, GetTitleInfo, "GetTitleInfo"}, | 14 | {0x000400C0, nullptr, "DeleteApplicationTitle"}, |
| 15 | {0x000400C0, nullptr, "DeleteApplicationTitle"}, | 15 | {0x000500C0, nullptr, "GetTitleProductCode"}, |
| 16 | {0x000500C0, nullptr, "GetTitleProductCode"}, | 16 | {0x000600C0, nullptr, "GetTitleExtDataId"}, |
| 17 | {0x000600C0, nullptr, "GetTitleExtDataId"}, | 17 | {0x00070080, DeleteTicket, "DeleteTicket"}, |
| 18 | {0x00070080, DeleteTicket, "DeleteTicket"}, | 18 | {0x00080000, GetTicketCount, "GetTicketCount"}, |
| 19 | {0x00080000, GetTicketCount, "GetTicketCount"}, | 19 | {0x00090082, GetTicketList, "GetTicketList"}, |
| 20 | {0x00090082, GetTicketList, "GetTicketList"}, | 20 | {0x000A0000, nullptr, "GetDeviceID"}, |
| 21 | {0x000A0000, nullptr, "GetDeviceID"}, | 21 | {0x000D0084, nullptr, "GetPendingTitleInfo"}, |
| 22 | {0x000D0084, nullptr, "GetPendingTitleInfo"}, | 22 | {0x000E00C0, nullptr, "DeletePendingTitle"}, |
| 23 | {0x000E00C0, nullptr, "DeletePendingTitle"}, | 23 | {0x00140040, nullptr, "FinalizePendingTitles"}, |
| 24 | {0x00140040, nullptr, "FinalizePendingTitles"}, | 24 | {0x00150040, nullptr, "DeleteAllPendingTitles"}, |
| 25 | {0x00150040, nullptr, "DeleteAllPendingTitles"}, | 25 | {0x00180080, nullptr, "InitializeTitleDatabase"}, |
| 26 | {0x00180080, nullptr, "InitializeTitleDatabase"}, | 26 | {0x00190040, nullptr, "ReloadDBS"}, |
| 27 | {0x00190040, nullptr, "ReloadDBS"}, | 27 | {0x001A00C0, nullptr, "GetDSiWareExportSize"}, |
| 28 | {0x001A00C0, nullptr, "GetDSiWareExportSize"}, | 28 | {0x001B0144, nullptr, "ExportDSiWare"}, |
| 29 | {0x001B0144, nullptr, "ExportDSiWare"}, | 29 | {0x001C0084, nullptr, "ImportDSiWare"}, |
| 30 | {0x001C0084, nullptr, "ImportDSiWare"}, | 30 | {0x00230080, nullptr, "TitleIDListGetTotal2"}, |
| 31 | {0x00230080, nullptr, "TitleIDListGetTotal2"}, | 31 | {0x002400C2, nullptr, "GetTitleIDList2"}, |
| 32 | {0x002400C2, nullptr, "GetTitleIDList2"}, | 32 | {0x04010080, nullptr, "InstallFIRM"}, |
| 33 | {0x04010080, nullptr, "InstallFIRM"}, | 33 | {0x04020040, nullptr, "StartInstallCIADB0"}, |
| 34 | {0x04020040, nullptr, "StartInstallCIADB0"}, | 34 | {0x04030000, nullptr, "StartInstallCIADB1"}, |
| 35 | {0x04030000, nullptr, "StartInstallCIADB1"}, | 35 | {0x04040002, nullptr, "AbortCIAInstall"}, |
| 36 | {0x04040002, nullptr, "AbortCIAInstall"}, | 36 | {0x04050002, nullptr, "CloseCIAFinalizeInstall"}, |
| 37 | {0x04050002, nullptr, "CloseCIAFinalizeInstall"}, | 37 | {0x04060002, nullptr, "CloseCIA"}, |
| 38 | {0x04060002, nullptr, "CloseCIA"}, | 38 | {0x040700C2, nullptr, "FinalizeTitlesInstall"}, |
| 39 | {0x040700C2, nullptr, "FinalizeTitlesInstall"}, | 39 | {0x04080042, nullptr, "GetCiaFileInfo"}, |
| 40 | {0x04080042, nullptr, "GetCiaFileInfo"}, | 40 | {0x040E00C2, nullptr, "InstallTitlesFinish"}, |
| 41 | {0x040E00C2, nullptr, "InstallTitlesFinish"}, | 41 | {0x040F0000, nullptr, "InstallNATIVEFIRM"}, |
| 42 | {0x040F0000, nullptr, "InstallNATIVEFIRM"}, | 42 | {0x041000C0, nullptr, "DeleteTitle"}, |
| 43 | {0x041000C0, nullptr, "DeleteTitle"}, | 43 | {0x04120000, nullptr, "Initialize"}, |
| 44 | {0x04120000, nullptr, "Initialize"}, | 44 | {0x041700C0, nullptr, "MigrateAGBtoSAV"}}; |
| 45 | {0x041700C0, nullptr, "MigrateAGBtoSAV"} | ||
| 46 | }; | ||
| 47 | 45 | ||
| 48 | AM_U_Interface::AM_U_Interface() { | 46 | AM_U_Interface::AM_U_Interface() { |
| 49 | Register(FunctionTable); | 47 | Register(FunctionTable); |
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 4d2956638..c798e8752 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | 8 | ||
| 9 | #include "core/hle/applets/applet.h" | 9 | #include "core/hle/applets/applet.h" |
| 10 | #include "core/hle/service/service.h" | ||
| 11 | #include "core/hle/service/apt/apt.h" | 10 | #include "core/hle/service/apt/apt.h" |
| 12 | #include "core/hle/service/apt/apt_a.h" | 11 | #include "core/hle/service/apt/apt_a.h" |
| 13 | #include "core/hle/service/apt/apt_s.h" | 12 | #include "core/hle/service/apt/apt_s.h" |
| @@ -15,6 +14,7 @@ | |||
| 15 | #include "core/hle/service/apt/bcfnt/bcfnt.h" | 14 | #include "core/hle/service/apt/bcfnt/bcfnt.h" |
| 16 | #include "core/hle/service/fs/archive.h" | 15 | #include "core/hle/service/fs/archive.h" |
| 17 | #include "core/hle/service/ptm/ptm.h" | 16 | #include "core/hle/service/ptm/ptm.h" |
| 17 | #include "core/hle/service/service.h" | ||
| 18 | 18 | ||
| 19 | #include "core/hle/kernel/event.h" | 19 | #include "core/hle/kernel/event.h" |
| 20 | #include "core/hle/kernel/mutex.h" | 20 | #include "core/hle/kernel/mutex.h" |
| @@ -30,7 +30,7 @@ static bool shared_font_relocated = false; | |||
| 30 | 30 | ||
| 31 | static Kernel::SharedPtr<Kernel::Mutex> lock; | 31 | static Kernel::SharedPtr<Kernel::Mutex> lock; |
| 32 | static Kernel::SharedPtr<Kernel::Event> notification_event; ///< APT notification event | 32 | static Kernel::SharedPtr<Kernel::Event> notification_event; ///< APT notification event |
| 33 | static Kernel::SharedPtr<Kernel::Event> parameter_event; ///< APT parameter event | 33 | static Kernel::SharedPtr<Kernel::Event> parameter_event; ///< APT parameter event |
| 34 | 34 | ||
| 35 | static u32 cpu_percent; ///< CPU time available to the running application | 35 | static u32 cpu_percent; ///< CPU time available to the running application |
| 36 | 36 | ||
| @@ -51,7 +51,7 @@ void SendParameter(const MessageParameter& parameter) { | |||
| 51 | void Initialize(Service::Interface* self) { | 51 | void Initialize(Service::Interface* self) { |
| 52 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 52 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 53 | u32 app_id = cmd_buff[1]; | 53 | u32 app_id = cmd_buff[1]; |
| 54 | u32 flags = cmd_buff[2]; | 54 | u32 flags = cmd_buff[2]; |
| 55 | 55 | ||
| 56 | cmd_buff[2] = IPC::CopyHandleDesc(2); | 56 | cmd_buff[2] = IPC::CopyHandleDesc(2); |
| 57 | cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom(); | 57 | cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom(); |
| @@ -75,20 +75,24 @@ void GetSharedFont(Service::Interface* self) { | |||
| 75 | if (!shared_font_mem) { | 75 | if (!shared_font_mem) { |
| 76 | LOG_ERROR(Service_APT, "shared font file missing - go dump it from your 3ds"); | 76 | LOG_ERROR(Service_APT, "shared font file missing - go dump it from your 3ds"); |
| 77 | cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2); | 77 | cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2); |
| 78 | cmd_buff[1] = -1; // TODO: Find the right error code | 78 | cmd_buff[1] = -1; // TODO: Find the right error code |
| 79 | return; | 79 | return; |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | // The shared font has to be relocated to the new address before being passed to the application. | 82 | // The shared font has to be relocated to the new address before being passed to the |
| 83 | VAddr target_address = Memory::PhysicalToVirtualAddress(shared_font_mem->linear_heap_phys_address); | 83 | // application. |
| 84 | VAddr target_address = | ||
| 85 | Memory::PhysicalToVirtualAddress(shared_font_mem->linear_heap_phys_address); | ||
| 84 | if (!shared_font_relocated) { | 86 | if (!shared_font_relocated) { |
| 85 | BCFNT::RelocateSharedFont(shared_font_mem, target_address); | 87 | BCFNT::RelocateSharedFont(shared_font_mem, target_address); |
| 86 | shared_font_relocated = true; | 88 | shared_font_relocated = true; |
| 87 | } | 89 | } |
| 88 | cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2); | 90 | cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2); |
| 89 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 91 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 90 | // Since the SharedMemory interface doesn't provide the address at which the memory was allocated, | 92 | // Since the SharedMemory interface doesn't provide the address at which the memory was |
| 91 | // the real APT service calculates this address by scanning the entire address space (using svcQueryMemory) | 93 | // allocated, |
| 94 | // the real APT service calculates this address by scanning the entire address space (using | ||
| 95 | // svcQueryMemory) | ||
| 92 | // and searches for an allocation of the same size as the Shared Font. | 96 | // and searches for an allocation of the same size as the Shared Font. |
| 93 | cmd_buff[2] = target_address; | 97 | cmd_buff[2] = target_address; |
| 94 | cmd_buff[3] = IPC::CopyHandleDesc(); | 98 | cmd_buff[3] = IPC::CopyHandleDesc(); |
| @@ -112,18 +116,19 @@ void GetLockHandle(Service::Interface* self) { | |||
| 112 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 116 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 113 | 117 | ||
| 114 | cmd_buff[2] = applet_attributes; // Applet Attributes, this value is passed to Enable. | 118 | cmd_buff[2] = applet_attributes; // Applet Attributes, this value is passed to Enable. |
| 115 | cmd_buff[3] = 0; // Least significant bit = power button state | 119 | cmd_buff[3] = 0; // Least significant bit = power button state |
| 116 | cmd_buff[4] = IPC::CopyHandleDesc(); | 120 | cmd_buff[4] = IPC::CopyHandleDesc(); |
| 117 | cmd_buff[5] = Kernel::g_handle_table.Create(lock).MoveFrom(); | 121 | cmd_buff[5] = Kernel::g_handle_table.Create(lock).MoveFrom(); |
| 118 | 122 | ||
| 119 | LOG_WARNING(Service_APT, "(STUBBED) called handle=0x%08X applet_attributes=0x%08X", cmd_buff[5], applet_attributes); | 123 | LOG_WARNING(Service_APT, "(STUBBED) called handle=0x%08X applet_attributes=0x%08X", cmd_buff[5], |
| 124 | applet_attributes); | ||
| 120 | } | 125 | } |
| 121 | 126 | ||
| 122 | void Enable(Service::Interface* self) { | 127 | void Enable(Service::Interface* self) { |
| 123 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 128 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 124 | u32 attributes = cmd_buff[1]; | 129 | u32 attributes = cmd_buff[1]; |
| 125 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 130 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 126 | parameter_event->Signal(); // Let the application know that it has been started | 131 | parameter_event->Signal(); // Let the application know that it has been started |
| 127 | LOG_WARNING(Service_APT, "(STUBBED) called attributes=0x%08X", attributes); | 132 | LOG_WARNING(Service_APT, "(STUBBED) called attributes=0x%08X", attributes); |
| 128 | } | 133 | } |
| 129 | 134 | ||
| @@ -133,7 +138,7 @@ void GetAppletManInfo(Service::Interface* self) { | |||
| 133 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 138 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 134 | cmd_buff[2] = 0; | 139 | cmd_buff[2] = 0; |
| 135 | cmd_buff[3] = 0; | 140 | cmd_buff[3] = 0; |
| 136 | cmd_buff[4] = static_cast<u32>(AppletId::HomeMenu); // Home menu AppID | 141 | cmd_buff[4] = static_cast<u32>(AppletId::HomeMenu); // Home menu AppID |
| 137 | cmd_buff[5] = static_cast<u32>(AppletId::Application); // TODO(purpasmart96): Do this correctly | 142 | cmd_buff[5] = static_cast<u32>(AppletId::Application); // TODO(purpasmart96): Do this correctly |
| 138 | 143 | ||
| 139 | LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk); | 144 | LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk); |
| @@ -159,23 +164,24 @@ void IsRegistered(Service::Interface* self) { | |||
| 159 | void InquireNotification(Service::Interface* self) { | 164 | void InquireNotification(Service::Interface* self) { |
| 160 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 165 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 161 | u32 app_id = cmd_buff[1]; | 166 | u32 app_id = cmd_buff[1]; |
| 162 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 167 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 163 | cmd_buff[2] = static_cast<u32>(SignalType::None); // Signal type | 168 | cmd_buff[2] = static_cast<u32>(SignalType::None); // Signal type |
| 164 | LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id); | 169 | LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id); |
| 165 | } | 170 | } |
| 166 | 171 | ||
| 167 | void SendParameter(Service::Interface* self) { | 172 | void SendParameter(Service::Interface* self) { |
| 168 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 173 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 169 | u32 src_app_id = cmd_buff[1]; | 174 | u32 src_app_id = cmd_buff[1]; |
| 170 | u32 dst_app_id = cmd_buff[2]; | 175 | u32 dst_app_id = cmd_buff[2]; |
| 171 | u32 signal_type = cmd_buff[3]; | 176 | u32 signal_type = cmd_buff[3]; |
| 172 | u32 buffer_size = cmd_buff[4]; | 177 | u32 buffer_size = cmd_buff[4]; |
| 173 | u32 value = cmd_buff[5]; | 178 | u32 value = cmd_buff[5]; |
| 174 | u32 handle = cmd_buff[6]; | 179 | u32 handle = cmd_buff[6]; |
| 175 | u32 size = cmd_buff[7]; | 180 | u32 size = cmd_buff[7]; |
| 176 | u32 buffer = cmd_buff[8]; | 181 | u32 buffer = cmd_buff[8]; |
| 177 | 182 | ||
| 178 | std::shared_ptr<HLE::Applets::Applet> dest_applet = HLE::Applets::Applet::Get(static_cast<AppletId>(dst_app_id)); | 183 | std::shared_ptr<HLE::Applets::Applet> dest_applet = |
| 184 | HLE::Applets::Applet::Get(static_cast<AppletId>(dst_app_id)); | ||
| 179 | 185 | ||
| 180 | if (dest_applet == nullptr) { | 186 | if (dest_applet == nullptr) { |
| 181 | LOG_ERROR(Service_APT, "Unknown applet id=0x%08X", dst_app_id); | 187 | LOG_ERROR(Service_APT, "Unknown applet id=0x%08X", dst_app_id); |
| @@ -193,9 +199,11 @@ void SendParameter(Service::Interface* self) { | |||
| 193 | 199 | ||
| 194 | cmd_buff[1] = dest_applet->ReceiveParameter(param).raw; | 200 | cmd_buff[1] = dest_applet->ReceiveParameter(param).raw; |
| 195 | 201 | ||
| 196 | LOG_WARNING(Service_APT, "(STUBBED) called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X," | 202 | LOG_WARNING( |
| 197 | "buffer_size=0x%08X, value=0x%08X, handle=0x%08X, size=0x%08X, in_param_buffer_ptr=0x%08X", | 203 | Service_APT, |
| 198 | src_app_id, dst_app_id, signal_type, buffer_size, value, handle, size, buffer); | 204 | "(STUBBED) called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X," |
| 205 | "buffer_size=0x%08X, value=0x%08X, handle=0x%08X, size=0x%08X, in_param_buffer_ptr=0x%08X", | ||
| 206 | src_app_id, dst_app_id, signal_type, buffer_size, value, handle, size, buffer); | ||
| 199 | } | 207 | } |
| 200 | 208 | ||
| 201 | void ReceiveParameter(Service::Interface* self) { | 209 | void ReceiveParameter(Service::Interface* self) { |
| @@ -206,7 +214,7 @@ void ReceiveParameter(Service::Interface* self) { | |||
| 206 | 214 | ||
| 207 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 215 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 208 | cmd_buff[2] = next_parameter.sender_id; | 216 | cmd_buff[2] = next_parameter.sender_id; |
| 209 | cmd_buff[3] = next_parameter.signal; // Signal type | 217 | cmd_buff[3] = next_parameter.signal; // Signal type |
| 210 | cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size | 218 | cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size |
| 211 | cmd_buff[5] = 0x10; | 219 | cmd_buff[5] = 0x10; |
| 212 | cmd_buff[6] = 0; | 220 | cmd_buff[6] = 0; |
| @@ -228,7 +236,7 @@ void GlanceParameter(Service::Interface* self) { | |||
| 228 | 236 | ||
| 229 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 237 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 230 | cmd_buff[2] = next_parameter.sender_id; | 238 | cmd_buff[2] = next_parameter.sender_id; |
| 231 | cmd_buff[3] = next_parameter.signal; // Signal type | 239 | cmd_buff[3] = next_parameter.signal; // Signal type |
| 232 | cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size | 240 | cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size |
| 233 | cmd_buff[5] = 0x10; | 241 | cmd_buff[5] = 0x10; |
| 234 | cmd_buff[6] = 0; | 242 | cmd_buff[6] = 0; |
| @@ -237,32 +245,34 @@ void GlanceParameter(Service::Interface* self) { | |||
| 237 | cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2; | 245 | cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2; |
| 238 | cmd_buff[8] = buffer; | 246 | cmd_buff[8] = buffer; |
| 239 | 247 | ||
| 240 | Memory::WriteBlock(buffer, next_parameter.buffer.data(), std::min(static_cast<size_t>(buffer_size), next_parameter.buffer.size())); | 248 | Memory::WriteBlock(buffer, next_parameter.buffer.data(), |
| 249 | std::min(static_cast<size_t>(buffer_size), next_parameter.buffer.size())); | ||
| 241 | 250 | ||
| 242 | LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); | 251 | LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); |
| 243 | } | 252 | } |
| 244 | 253 | ||
| 245 | void CancelParameter(Service::Interface* self) { | 254 | void CancelParameter(Service::Interface* self) { |
| 246 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 255 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 247 | u32 flag1 = cmd_buff[1]; | 256 | u32 flag1 = cmd_buff[1]; |
| 248 | u32 unk = cmd_buff[2]; | 257 | u32 unk = cmd_buff[2]; |
| 249 | u32 flag2 = cmd_buff[3]; | 258 | u32 flag2 = cmd_buff[3]; |
| 250 | u32 app_id = cmd_buff[4]; | 259 | u32 app_id = cmd_buff[4]; |
| 251 | 260 | ||
| 252 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 261 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 253 | cmd_buff[2] = 1; // Set to Success | 262 | cmd_buff[2] = 1; // Set to Success |
| 254 | 263 | ||
| 255 | LOG_WARNING(Service_APT, "(STUBBED) called flag1=0x%08X, unk=0x%08X, flag2=0x%08X, app_id=0x%08X", | 264 | LOG_WARNING(Service_APT, |
| 256 | flag1, unk, flag2, app_id); | 265 | "(STUBBED) called flag1=0x%08X, unk=0x%08X, flag2=0x%08X, app_id=0x%08X", flag1, |
| 266 | unk, flag2, app_id); | ||
| 257 | } | 267 | } |
| 258 | 268 | ||
| 259 | void PrepareToStartApplication(Service::Interface* self) { | 269 | void PrepareToStartApplication(Service::Interface* self) { |
| 260 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 270 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 261 | u32 title_info1 = cmd_buff[1]; | 271 | u32 title_info1 = cmd_buff[1]; |
| 262 | u32 title_info2 = cmd_buff[2]; | 272 | u32 title_info2 = cmd_buff[2]; |
| 263 | u32 title_info3 = cmd_buff[3]; | 273 | u32 title_info3 = cmd_buff[3]; |
| 264 | u32 title_info4 = cmd_buff[4]; | 274 | u32 title_info4 = cmd_buff[4]; |
| 265 | u32 flags = cmd_buff[5]; | 275 | u32 flags = cmd_buff[5]; |
| 266 | 276 | ||
| 267 | if (flags & 0x00000100) { | 277 | if (flags & 0x00000100) { |
| 268 | unknown_ns_state_field = 1; | 278 | unknown_ns_state_field = 1; |
| @@ -270,25 +280,28 @@ void PrepareToStartApplication(Service::Interface* self) { | |||
| 270 | 280 | ||
| 271 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 281 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 272 | 282 | ||
| 273 | LOG_WARNING(Service_APT, "(STUBBED) called title_info1=0x%08X, title_info2=0x%08X, title_info3=0x%08X," | 283 | LOG_WARNING(Service_APT, |
| 274 | "title_info4=0x%08X, flags=0x%08X", title_info1, title_info2, title_info3, title_info4, flags); | 284 | "(STUBBED) called title_info1=0x%08X, title_info2=0x%08X, title_info3=0x%08X," |
| 285 | "title_info4=0x%08X, flags=0x%08X", | ||
| 286 | title_info1, title_info2, title_info3, title_info4, flags); | ||
| 275 | } | 287 | } |
| 276 | 288 | ||
| 277 | void StartApplication(Service::Interface* self) { | 289 | void StartApplication(Service::Interface* self) { |
| 278 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 290 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 279 | u32 buffer1_size = cmd_buff[1]; | 291 | u32 buffer1_size = cmd_buff[1]; |
| 280 | u32 buffer2_size = cmd_buff[2]; | 292 | u32 buffer2_size = cmd_buff[2]; |
| 281 | u32 flag = cmd_buff[3]; | 293 | u32 flag = cmd_buff[3]; |
| 282 | u32 size1 = cmd_buff[4]; | 294 | u32 size1 = cmd_buff[4]; |
| 283 | u32 buffer1_ptr = cmd_buff[5]; | 295 | u32 buffer1_ptr = cmd_buff[5]; |
| 284 | u32 size2 = cmd_buff[6]; | 296 | u32 size2 = cmd_buff[6]; |
| 285 | u32 buffer2_ptr = cmd_buff[7]; | 297 | u32 buffer2_ptr = cmd_buff[7]; |
| 286 | 298 | ||
| 287 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 299 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 288 | 300 | ||
| 289 | LOG_WARNING(Service_APT, "(STUBBED) called buffer1_size=0x%08X, buffer2_size=0x%08X, flag=0x%08X," | 301 | LOG_WARNING(Service_APT, |
| 290 | "size1=0x%08X, buffer1_ptr=0x%08X, size2=0x%08X, buffer2_ptr=0x%08X", | 302 | "(STUBBED) called buffer1_size=0x%08X, buffer2_size=0x%08X, flag=0x%08X," |
| 291 | buffer1_size, buffer2_size, flag, size1, buffer1_ptr, size2, buffer2_ptr); | 303 | "size1=0x%08X, buffer1_ptr=0x%08X, size2=0x%08X, buffer2_ptr=0x%08X", |
| 304 | buffer1_size, buffer2_size, flag, size1, buffer1_ptr, size2, buffer2_ptr); | ||
| 292 | } | 305 | } |
| 293 | 306 | ||
| 294 | void AppletUtility(Service::Interface* self) { | 307 | void AppletUtility(Service::Interface* self) { |
| @@ -303,14 +316,15 @@ void AppletUtility(Service::Interface* self) { | |||
| 303 | 316 | ||
| 304 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 317 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 305 | 318 | ||
| 306 | LOG_WARNING(Service_APT, "(STUBBED) called command=0x%08X, buffer1_size=0x%08X, buffer2_size=0x%08X, " | 319 | LOG_WARNING(Service_APT, |
| 307 | "buffer1_addr=0x%08X, buffer2_addr=0x%08X", command, buffer1_size, buffer2_size, | 320 | "(STUBBED) called command=0x%08X, buffer1_size=0x%08X, buffer2_size=0x%08X, " |
| 308 | buffer1_addr, buffer2_addr); | 321 | "buffer1_addr=0x%08X, buffer2_addr=0x%08X", |
| 322 | command, buffer1_size, buffer2_size, buffer1_addr, buffer2_addr); | ||
| 309 | } | 323 | } |
| 310 | 324 | ||
| 311 | void SetAppCpuTimeLimit(Service::Interface* self) { | 325 | void SetAppCpuTimeLimit(Service::Interface* self) { |
| 312 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 326 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 313 | u32 value = cmd_buff[1]; | 327 | u32 value = cmd_buff[1]; |
| 314 | cpu_percent = cmd_buff[2]; | 328 | cpu_percent = cmd_buff[2]; |
| 315 | 329 | ||
| 316 | if (value != 1) { | 330 | if (value != 1) { |
| @@ -393,7 +407,8 @@ void SetScreenCapPostPermission(Service::Interface* self) { | |||
| 393 | 407 | ||
| 394 | cmd_buff[0] = IPC::MakeHeader(0x55, 1, 0); | 408 | cmd_buff[0] = IPC::MakeHeader(0x55, 1, 0); |
| 395 | cmd_buff[1] = RESULT_SUCCESS.raw; | 409 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 396 | LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u", screen_capture_post_permission); | 410 | LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u", |
| 411 | screen_capture_post_permission); | ||
| 397 | } | 412 | } |
| 398 | 413 | ||
| 399 | void GetScreenCapPostPermission(Service::Interface* self) { | 414 | void GetScreenCapPostPermission(Service::Interface* self) { |
| @@ -402,7 +417,8 @@ void GetScreenCapPostPermission(Service::Interface* self) { | |||
| 402 | cmd_buff[0] = IPC::MakeHeader(0x56, 2, 0); | 417 | cmd_buff[0] = IPC::MakeHeader(0x56, 2, 0); |
| 403 | cmd_buff[1] = RESULT_SUCCESS.raw; | 418 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 404 | cmd_buff[2] = static_cast<u32>(screen_capture_post_permission); | 419 | cmd_buff[2] = static_cast<u32>(screen_capture_post_permission); |
| 405 | LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u", screen_capture_post_permission); | 420 | LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u", |
| 421 | screen_capture_post_permission); | ||
| 406 | } | 422 | } |
| 407 | 423 | ||
| 408 | void GetAppletInfo(Service::Interface* self) { | 424 | void GetAppletInfo(Service::Interface* self) { |
| @@ -418,7 +434,8 @@ void GetAppletInfo(Service::Interface* self) { | |||
| 418 | cmd_buff[7] = 0; // Applet Attributes | 434 | cmd_buff[7] = 0; // Applet Attributes |
| 419 | } else { | 435 | } else { |
| 420 | cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, | 436 | cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, |
| 421 | ErrorSummary::NotFound, ErrorLevel::Status).raw; | 437 | ErrorSummary::NotFound, ErrorLevel::Status) |
| 438 | .raw; | ||
| 422 | } | 439 | } |
| 423 | LOG_WARNING(Service_APT, "(stubbed) called appid=%u", app_id); | 440 | LOG_WARNING(Service_APT, "(stubbed) called appid=%u", app_id); |
| 424 | } | 441 | } |
| @@ -429,11 +446,15 @@ void GetStartupArgument(Service::Interface* self) { | |||
| 429 | StartupArgumentType startup_argument_type = static_cast<StartupArgumentType>(cmd_buff[2]); | 446 | StartupArgumentType startup_argument_type = static_cast<StartupArgumentType>(cmd_buff[2]); |
| 430 | 447 | ||
| 431 | if (parameter_size >= 0x300) { | 448 | if (parameter_size >= 0x300) { |
| 432 | LOG_ERROR(Service_APT, "Parameter size is outside the valid range (capped to 0x300): parameter_size=0x%08x", parameter_size); | 449 | LOG_ERROR( |
| 450 | Service_APT, | ||
| 451 | "Parameter size is outside the valid range (capped to 0x300): parameter_size=0x%08x", | ||
| 452 | parameter_size); | ||
| 433 | return; | 453 | return; |
| 434 | } | 454 | } |
| 435 | 455 | ||
| 436 | LOG_WARNING(Service_APT,"(stubbed) called startup_argument_type=%u , parameter_size=0x%08x , parameter_value=0x%08x", | 456 | LOG_WARNING(Service_APT, "(stubbed) called startup_argument_type=%u , parameter_size=0x%08x , " |
| 457 | "parameter_value=0x%08x", | ||
| 437 | startup_argument_type, parameter_size, Memory::Read32(cmd_buff[41])); | 458 | startup_argument_type, parameter_size, Memory::Read32(cmd_buff[41])); |
| 438 | 459 | ||
| 439 | cmd_buff[1] = RESULT_SUCCESS.raw; | 460 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| @@ -484,8 +505,10 @@ void Init() { | |||
| 484 | if (file.IsOpen()) { | 505 | if (file.IsOpen()) { |
| 485 | // Create shared font memory object | 506 | // Create shared font memory object |
| 486 | using Kernel::MemoryPermission; | 507 | using Kernel::MemoryPermission; |
| 487 | shared_font_mem = Kernel::SharedMemory::Create(nullptr, 0x332000, // 3272 KB | 508 | shared_font_mem = |
| 488 | MemoryPermission::ReadWrite, MemoryPermission::Read, 0, Kernel::MemoryRegion::SYSTEM, "APT:SharedFont"); | 509 | Kernel::SharedMemory::Create(nullptr, 0x332000, // 3272 KB |
| 510 | MemoryPermission::ReadWrite, MemoryPermission::Read, 0, | ||
| 511 | Kernel::MemoryRegion::SYSTEM, "APT:SharedFont"); | ||
| 489 | // Read shared font data | 512 | // Read shared font data |
| 490 | file.ReadBytes(shared_font_mem->GetPointer(), file.GetSize()); | 513 | file.ReadBytes(shared_font_mem->GetPointer(), file.GetSize()); |
| 491 | } else { | 514 | } else { |
| @@ -497,7 +520,8 @@ void Init() { | |||
| 497 | 520 | ||
| 498 | cpu_percent = 0; | 521 | cpu_percent = 0; |
| 499 | unknown_ns_state_field = 0; | 522 | unknown_ns_state_field = 0; |
| 500 | screen_capture_post_permission = ScreencapPostPermission::CleanThePermission; // TODO(JamePeng): verify the initial value | 523 | screen_capture_post_permission = |
| 524 | ScreencapPostPermission::CleanThePermission; // TODO(JamePeng): verify the initial value | ||
| 501 | 525 | ||
| 502 | // TODO(bunnei): Check if these are created in Initialize or on APT process startup. | 526 | // TODO(bunnei): Check if these are created in Initialize or on APT process startup. |
| 503 | notification_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Notification"); | 527 | notification_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Notification"); |
diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index 077a6a316..fe8b8a7b8 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h | |||
| @@ -46,58 +46,58 @@ static_assert(sizeof(CaptureBufferInfo) == 0x20, "CaptureBufferInfo struct has i | |||
| 46 | 46 | ||
| 47 | /// Signals used by APT functions | 47 | /// Signals used by APT functions |
| 48 | enum class SignalType : u32 { | 48 | enum class SignalType : u32 { |
| 49 | None = 0x0, | 49 | None = 0x0, |
| 50 | AppJustStarted = 0x1, | 50 | AppJustStarted = 0x1, |
| 51 | LibAppJustStarted = 0x2, | 51 | LibAppJustStarted = 0x2, |
| 52 | LibAppFinished = 0x3, | 52 | LibAppFinished = 0x3, |
| 53 | LibAppClosed = 0xA, | 53 | LibAppClosed = 0xA, |
| 54 | ReturningToApp = 0xB, | 54 | ReturningToApp = 0xB, |
| 55 | ExitingApp = 0xC, | 55 | ExitingApp = 0xC, |
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | /// App Id's used by APT functions | 58 | /// App Id's used by APT functions |
| 59 | enum class AppletId : u32 { | 59 | enum class AppletId : u32 { |
| 60 | HomeMenu = 0x101, | 60 | HomeMenu = 0x101, |
| 61 | AlternateMenu = 0x103, | 61 | AlternateMenu = 0x103, |
| 62 | Camera = 0x110, | 62 | Camera = 0x110, |
| 63 | FriendsList = 0x112, | 63 | FriendsList = 0x112, |
| 64 | GameNotes = 0x113, | 64 | GameNotes = 0x113, |
| 65 | InternetBrowser = 0x114, | 65 | InternetBrowser = 0x114, |
| 66 | InstructionManual = 0x115, | 66 | InstructionManual = 0x115, |
| 67 | Notifications = 0x116, | 67 | Notifications = 0x116, |
| 68 | Miiverse = 0x117, | 68 | Miiverse = 0x117, |
| 69 | MiiversePost = 0x118, | 69 | MiiversePost = 0x118, |
| 70 | AmiiboSettings = 0x119, | 70 | AmiiboSettings = 0x119, |
| 71 | SoftwareKeyboard1 = 0x201, | 71 | SoftwareKeyboard1 = 0x201, |
| 72 | Ed1 = 0x202, | 72 | Ed1 = 0x202, |
| 73 | PnoteApp = 0x204, | 73 | PnoteApp = 0x204, |
| 74 | SnoteApp = 0x205, | 74 | SnoteApp = 0x205, |
| 75 | Error = 0x206, | 75 | Error = 0x206, |
| 76 | Mint = 0x207, | 76 | Mint = 0x207, |
| 77 | Extrapad = 0x208, | 77 | Extrapad = 0x208, |
| 78 | Memolib = 0x209, | 78 | Memolib = 0x209, |
| 79 | Application = 0x300, | 79 | Application = 0x300, |
| 80 | AnyLibraryApplet = 0x400, | 80 | AnyLibraryApplet = 0x400, |
| 81 | SoftwareKeyboard2 = 0x401, | 81 | SoftwareKeyboard2 = 0x401, |
| 82 | Ed2 = 0x402, | 82 | Ed2 = 0x402, |
| 83 | PnoteApp2 = 0x404, | 83 | PnoteApp2 = 0x404, |
| 84 | SnoteApp2 = 0x405, | 84 | SnoteApp2 = 0x405, |
| 85 | Error2 = 0x406, | 85 | Error2 = 0x406, |
| 86 | Mint2 = 0x407, | 86 | Mint2 = 0x407, |
| 87 | Extrapad2 = 0x408, | 87 | Extrapad2 = 0x408, |
| 88 | Memolib2 = 0x409, | 88 | Memolib2 = 0x409, |
| 89 | }; | 89 | }; |
| 90 | 90 | ||
| 91 | enum class StartupArgumentType : u32 { | 91 | enum class StartupArgumentType : u32 { |
| 92 | OtherApp = 0, | 92 | OtherApp = 0, |
| 93 | Restart = 1, | 93 | Restart = 1, |
| 94 | OtherMedia = 2, | 94 | OtherMedia = 2, |
| 95 | }; | 95 | }; |
| 96 | 96 | ||
| 97 | enum class ScreencapPostPermission : u32 { | 97 | enum class ScreencapPostPermission : u32 { |
| 98 | CleanThePermission = 0, //TODO(JamePeng): verify what "zero" means | 98 | CleanThePermission = 0, // TODO(JamePeng): verify what "zero" means |
| 99 | NoExplicitSetting = 1, | 99 | NoExplicitSetting = 1, |
| 100 | EnableScreenshotPostingToMiiverse = 2, | 100 | EnableScreenshotPostingToMiiverse = 2, |
| 101 | DisableScreenshotPostingToMiiverse = 3 | 101 | DisableScreenshotPostingToMiiverse = 3 |
| 102 | }; | 102 | }; |
| 103 | 103 | ||
| @@ -182,9 +182,12 @@ void GetAppletManInfo(Service::Interface* self); | |||
| 182 | void GetAppletInfo(Service::Interface* self); | 182 | void GetAppletInfo(Service::Interface* self); |
| 183 | 183 | ||
| 184 | /** | 184 | /** |
| 185 | * APT::IsRegistered service function. This returns whether the specified AppID is registered with NS yet. | 185 | * APT::IsRegistered service function. This returns whether the specified AppID is registered with |
| 186 | * An AppID is "registered" once the process associated with the AppID uses APT:Enable. Home Menu uses this | 186 | * NS yet. |
| 187 | * command to determine when the launched process is running and to determine when to stop using GSP etc, | 187 | * An AppID is "registered" once the process associated with the AppID uses APT:Enable. Home Menu |
| 188 | * uses this | ||
| 189 | * command to determine when the launched process is running and to determine when to stop using GSP | ||
| 190 | * etc, | ||
| 188 | * while displaying the "Nintendo 3DS" loading screen. | 191 | * while displaying the "Nintendo 3DS" loading screen. |
| 189 | * Inputs: | 192 | * Inputs: |
| 190 | * 1 : AppID | 193 | * 1 : AppID |
| @@ -260,9 +263,11 @@ void GlanceParameter(Service::Interface* self); | |||
| 260 | * clears the flag which indicates that parameter data is available | 263 | * clears the flag which indicates that parameter data is available |
| 261 | * (same flag cleared by APT:ReceiveParameter). | 264 | * (same flag cleared by APT:ReceiveParameter). |
| 262 | * Inputs: | 265 | * Inputs: |
| 263 | * 1 : Flag, when non-zero NS will compare the word after this one with a field in the NS state. | 266 | * 1 : Flag, when non-zero NS will compare the word after this one with a field in the NS |
| 267 | * state. | ||
| 264 | * 2 : Unknown, this is the same as the first unknown field returned by APT:ReceiveParameter. | 268 | * 2 : Unknown, this is the same as the first unknown field returned by APT:ReceiveParameter. |
| 265 | * 3 : Flag, when non-zero NS will compare the word after this one with a field in the NS state. | 269 | * 3 : Flag, when non-zero NS will compare the word after this one with a field in the NS |
| 270 | * state. | ||
| 266 | * 4 : AppID | 271 | * 4 : AppID |
| 267 | * Outputs: | 272 | * Outputs: |
| 268 | * 0 : Return header | 273 | * 0 : Return header |
diff --git a/src/core/hle/service/apt/apt_a.cpp b/src/core/hle/service/apt/apt_a.cpp index 6c44c491c..7d47d7675 100644 --- a/src/core/hle/service/apt/apt_a.cpp +++ b/src/core/hle/service/apt/apt_a.cpp | |||
| @@ -9,35 +9,34 @@ namespace Service { | |||
| 9 | namespace APT { | 9 | namespace APT { |
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = { |
| 12 | {0x00010040, GetLockHandle, "GetLockHandle?"}, | 12 | {0x00010040, GetLockHandle, "GetLockHandle?"}, |
| 13 | {0x00020080, Initialize, "Initialize?"}, | 13 | {0x00020080, Initialize, "Initialize?"}, |
| 14 | {0x00030040, Enable, "Enable?"}, | 14 | {0x00030040, Enable, "Enable?"}, |
| 15 | {0x00040040, nullptr, "Finalize?"}, | 15 | {0x00040040, nullptr, "Finalize?"}, |
| 16 | {0x00050040, GetAppletManInfo, "GetAppletManInfo"}, | 16 | {0x00050040, GetAppletManInfo, "GetAppletManInfo"}, |
| 17 | {0x00060040, GetAppletInfo, "GetAppletInfo"}, | 17 | {0x00060040, GetAppletInfo, "GetAppletInfo"}, |
| 18 | {0x00090040, IsRegistered, "IsRegistered"}, | 18 | {0x00090040, IsRegistered, "IsRegistered"}, |
| 19 | {0x000B0040, InquireNotification, "InquireNotification"}, | 19 | {0x000B0040, InquireNotification, "InquireNotification"}, |
| 20 | {0x000C0104, SendParameter, "SendParameter"}, | 20 | {0x000C0104, SendParameter, "SendParameter"}, |
| 21 | {0x000D0080, ReceiveParameter, "ReceiveParameter"}, | 21 | {0x000D0080, ReceiveParameter, "ReceiveParameter"}, |
| 22 | {0x000E0080, GlanceParameter, "GlanceParameter"}, | 22 | {0x000E0080, GlanceParameter, "GlanceParameter"}, |
| 23 | {0x000F0100, CancelParameter, "CancelParameter"}, | 23 | {0x000F0100, CancelParameter, "CancelParameter"}, |
| 24 | {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, | 24 | {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, |
| 25 | {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, | 25 | {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, |
| 26 | {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, | 26 | {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, |
| 27 | {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, | 27 | {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, |
| 28 | {0x003B0040, nullptr, "CancelLibraryApplet?"}, | 28 | {0x003B0040, nullptr, "CancelLibraryApplet?"}, |
| 29 | {0x003E0080, nullptr, "ReplySleepQuery"}, | 29 | {0x003E0080, nullptr, "ReplySleepQuery"}, |
| 30 | {0x00430040, NotifyToWait, "NotifyToWait?"}, | 30 | {0x00430040, NotifyToWait, "NotifyToWait?"}, |
| 31 | {0x00440000, GetSharedFont, "GetSharedFont?"}, | 31 | {0x00440000, GetSharedFont, "GetSharedFont?"}, |
| 32 | {0x004B00C2, AppletUtility, "AppletUtility?"}, | 32 | {0x004B00C2, AppletUtility, "AppletUtility?"}, |
| 33 | {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, | 33 | {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, |
| 34 | {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, | 34 | {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, |
| 35 | {0x00510080, GetStartupArgument, "GetStartupArgument"}, | 35 | {0x00510080, GetStartupArgument, "GetStartupArgument"}, |
| 36 | {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"}, | 36 | {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"}, |
| 37 | {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"}, | 37 | {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"}, |
| 38 | {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, | 38 | {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, |
| 39 | {0x01020000, CheckNew3DS, "CheckNew3DS"} | 39 | {0x01020000, CheckNew3DS, "CheckNew3DS"}}; |
| 40 | }; | ||
| 41 | 40 | ||
| 42 | APT_A_Interface::APT_A_Interface() { | 41 | APT_A_Interface::APT_A_Interface() { |
| 43 | Register(FunctionTable); | 42 | Register(FunctionTable); |
diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp index c70f2201f..76e71669c 100644 --- a/src/core/hle/service/apt/apt_s.cpp +++ b/src/core/hle/service/apt/apt_s.cpp | |||
| @@ -9,95 +9,94 @@ namespace Service { | |||
| 9 | namespace APT { | 9 | namespace APT { |
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = { |
| 12 | {0x00010040, GetLockHandle, "GetLockHandle"}, | 12 | {0x00010040, GetLockHandle, "GetLockHandle"}, |
| 13 | {0x00020080, Initialize, "Initialize"}, | 13 | {0x00020080, Initialize, "Initialize"}, |
| 14 | {0x00030040, Enable, "Enable"}, | 14 | {0x00030040, Enable, "Enable"}, |
| 15 | {0x00040040, nullptr, "Finalize"}, | 15 | {0x00040040, nullptr, "Finalize"}, |
| 16 | {0x00050040, GetAppletManInfo, "GetAppletManInfo"}, | 16 | {0x00050040, GetAppletManInfo, "GetAppletManInfo"}, |
| 17 | {0x00060040, GetAppletInfo, "GetAppletInfo"}, | 17 | {0x00060040, GetAppletInfo, "GetAppletInfo"}, |
| 18 | {0x00070000, nullptr, "GetLastSignaledAppletId"}, | 18 | {0x00070000, nullptr, "GetLastSignaledAppletId"}, |
| 19 | {0x00080000, nullptr, "CountRegisteredApplet"}, | 19 | {0x00080000, nullptr, "CountRegisteredApplet"}, |
| 20 | {0x00090040, nullptr, "IsRegistered"}, | 20 | {0x00090040, nullptr, "IsRegistered"}, |
| 21 | {0x000A0040, nullptr, "GetAttribute"}, | 21 | {0x000A0040, nullptr, "GetAttribute"}, |
| 22 | {0x000B0040, InquireNotification, "InquireNotification"}, | 22 | {0x000B0040, InquireNotification, "InquireNotification"}, |
| 23 | {0x000C0104, nullptr, "SendParameter"}, | 23 | {0x000C0104, nullptr, "SendParameter"}, |
| 24 | {0x000D0080, ReceiveParameter, "ReceiveParameter"}, | 24 | {0x000D0080, ReceiveParameter, "ReceiveParameter"}, |
| 25 | {0x000E0080, GlanceParameter, "GlanceParameter"}, | 25 | {0x000E0080, GlanceParameter, "GlanceParameter"}, |
| 26 | {0x000F0100, nullptr, "CancelParameter"}, | 26 | {0x000F0100, nullptr, "CancelParameter"}, |
| 27 | {0x001000C2, nullptr, "DebugFunc"}, | 27 | {0x001000C2, nullptr, "DebugFunc"}, |
| 28 | {0x001100C0, nullptr, "MapProgramIdForDebug"}, | 28 | {0x001100C0, nullptr, "MapProgramIdForDebug"}, |
| 29 | {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"}, | 29 | {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"}, |
| 30 | {0x00130000, nullptr, "GetPreparationState"}, | 30 | {0x00130000, nullptr, "GetPreparationState"}, |
| 31 | {0x00140040, nullptr, "SetPreparationState"}, | 31 | {0x00140040, nullptr, "SetPreparationState"}, |
| 32 | {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, | 32 | {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, |
| 33 | {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, | 33 | {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, |
| 34 | {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, | 34 | {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, |
| 35 | {0x00180040, PrepareToStartLibraryApplet,"PrepareToStartLibraryApplet"}, | 35 | {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, |
| 36 | {0x00190040, nullptr, "PrepareToStartSystemApplet"}, | 36 | {0x00190040, nullptr, "PrepareToStartSystemApplet"}, |
| 37 | {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, | 37 | {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, |
| 38 | {0x001B00C4, nullptr, "StartApplication"}, | 38 | {0x001B00C4, nullptr, "StartApplication"}, |
| 39 | {0x001C0000, nullptr, "WakeupApplication"}, | 39 | {0x001C0000, nullptr, "WakeupApplication"}, |
| 40 | {0x001D0000, nullptr, "CancelApplication"}, | 40 | {0x001D0000, nullptr, "CancelApplication"}, |
| 41 | {0x001E0084, nullptr, "StartLibraryApplet"}, | 41 | {0x001E0084, nullptr, "StartLibraryApplet"}, |
| 42 | {0x001F0084, nullptr, "StartSystemApplet"}, | 42 | {0x001F0084, nullptr, "StartSystemApplet"}, |
| 43 | {0x00200044, nullptr, "StartNewestHomeMenu"}, | 43 | {0x00200044, nullptr, "StartNewestHomeMenu"}, |
| 44 | {0x00210000, nullptr, "OrderToCloseApplication"}, | 44 | {0x00210000, nullptr, "OrderToCloseApplication"}, |
| 45 | {0x00220040, nullptr, "PrepareToCloseApplication"}, | 45 | {0x00220040, nullptr, "PrepareToCloseApplication"}, |
| 46 | {0x00230040, nullptr, "PrepareToJumpToApplication"}, | 46 | {0x00230040, nullptr, "PrepareToJumpToApplication"}, |
| 47 | {0x00240044, nullptr, "JumpToApplication"}, | 47 | {0x00240044, nullptr, "JumpToApplication"}, |
| 48 | {0x002500C0, nullptr, "PrepareToCloseLibraryApplet"}, | 48 | {0x002500C0, nullptr, "PrepareToCloseLibraryApplet"}, |
| 49 | {0x00260000, nullptr, "PrepareToCloseSystemApplet"}, | 49 | {0x00260000, nullptr, "PrepareToCloseSystemApplet"}, |
| 50 | {0x00270044, nullptr, "CloseApplication"}, | 50 | {0x00270044, nullptr, "CloseApplication"}, |
| 51 | {0x00280044, nullptr, "CloseLibraryApplet"}, | 51 | {0x00280044, nullptr, "CloseLibraryApplet"}, |
| 52 | {0x00290044, nullptr, "CloseSystemApplet"}, | 52 | {0x00290044, nullptr, "CloseSystemApplet"}, |
| 53 | {0x002A0000, nullptr, "OrderToCloseSystemApplet"}, | 53 | {0x002A0000, nullptr, "OrderToCloseSystemApplet"}, |
| 54 | {0x002B0000, nullptr, "PrepareToJumpToHomeMenu"}, | 54 | {0x002B0000, nullptr, "PrepareToJumpToHomeMenu"}, |
| 55 | {0x002C0044, nullptr, "JumpToHomeMenu"}, | 55 | {0x002C0044, nullptr, "JumpToHomeMenu"}, |
| 56 | {0x002D0000, nullptr, "PrepareToLeaveHomeMenu"}, | 56 | {0x002D0000, nullptr, "PrepareToLeaveHomeMenu"}, |
| 57 | {0x002E0044, nullptr, "LeaveHomeMenu"}, | 57 | {0x002E0044, nullptr, "LeaveHomeMenu"}, |
| 58 | {0x002F0040, nullptr, "PrepareToLeaveResidentApplet"}, | 58 | {0x002F0040, nullptr, "PrepareToLeaveResidentApplet"}, |
| 59 | {0x00300044, nullptr, "LeaveResidentApplet"}, | 59 | {0x00300044, nullptr, "LeaveResidentApplet"}, |
| 60 | {0x00310100, nullptr, "PrepareToDoApplicationJump"}, | 60 | {0x00310100, nullptr, "PrepareToDoApplicationJump"}, |
| 61 | {0x00320084, nullptr, "DoApplicationJump"}, | 61 | {0x00320084, nullptr, "DoApplicationJump"}, |
| 62 | {0x00330000, nullptr, "GetProgramIdOnApplicationJump"}, | 62 | {0x00330000, nullptr, "GetProgramIdOnApplicationJump"}, |
| 63 | {0x00340084, nullptr, "SendDeliverArg"}, | 63 | {0x00340084, nullptr, "SendDeliverArg"}, |
| 64 | {0x00350080, nullptr, "ReceiveDeliverArg"}, | 64 | {0x00350080, nullptr, "ReceiveDeliverArg"}, |
| 65 | {0x00360040, nullptr, "LoadSysMenuArg"}, | 65 | {0x00360040, nullptr, "LoadSysMenuArg"}, |
| 66 | {0x00370042, nullptr, "StoreSysMenuArg"}, | 66 | {0x00370042, nullptr, "StoreSysMenuArg"}, |
| 67 | {0x00380040, nullptr, "PreloadResidentApplet"}, | 67 | {0x00380040, nullptr, "PreloadResidentApplet"}, |
| 68 | {0x00390040, nullptr, "PrepareToStartResidentApplet"}, | 68 | {0x00390040, nullptr, "PrepareToStartResidentApplet"}, |
| 69 | {0x003A0044, nullptr, "StartResidentApplet"}, | 69 | {0x003A0044, nullptr, "StartResidentApplet"}, |
| 70 | {0x003B0040, nullptr, "CancelLibraryApplet"}, | 70 | {0x003B0040, nullptr, "CancelLibraryApplet"}, |
| 71 | {0x003C0042, nullptr, "SendDspSleep"}, | 71 | {0x003C0042, nullptr, "SendDspSleep"}, |
| 72 | {0x003D0042, nullptr, "SendDspWakeUp"}, | 72 | {0x003D0042, nullptr, "SendDspWakeUp"}, |
| 73 | {0x003E0080, nullptr, "ReplySleepQuery"}, | 73 | {0x003E0080, nullptr, "ReplySleepQuery"}, |
| 74 | {0x003F0040, nullptr, "ReplySleepNotificationComplete"}, | 74 | {0x003F0040, nullptr, "ReplySleepNotificationComplete"}, |
| 75 | {0x00400042, nullptr, "SendCaptureBufferInfo"}, | 75 | {0x00400042, nullptr, "SendCaptureBufferInfo"}, |
| 76 | {0x00410040, nullptr, "ReceiveCaptureBufferInfo"}, | 76 | {0x00410040, nullptr, "ReceiveCaptureBufferInfo"}, |
| 77 | {0x00420080, nullptr, "SleepSystem"}, | 77 | {0x00420080, nullptr, "SleepSystem"}, |
| 78 | {0x00430040, NotifyToWait, "NotifyToWait"}, | 78 | {0x00430040, NotifyToWait, "NotifyToWait"}, |
| 79 | {0x00440000, GetSharedFont, "GetSharedFont"}, | 79 | {0x00440000, GetSharedFont, "GetSharedFont"}, |
| 80 | {0x00450040, nullptr, "GetWirelessRebootInfo"}, | 80 | {0x00450040, nullptr, "GetWirelessRebootInfo"}, |
| 81 | {0x00460104, nullptr, "Wrap"}, | 81 | {0x00460104, nullptr, "Wrap"}, |
| 82 | {0x00470104, nullptr, "Unwrap"}, | 82 | {0x00470104, nullptr, "Unwrap"}, |
| 83 | {0x00480100, nullptr, "GetProgramInfo"}, | 83 | {0x00480100, nullptr, "GetProgramInfo"}, |
| 84 | {0x00490180, nullptr, "Reboot"}, | 84 | {0x00490180, nullptr, "Reboot"}, |
| 85 | {0x004A0040, nullptr, "GetCaptureInfo"}, | 85 | {0x004A0040, nullptr, "GetCaptureInfo"}, |
| 86 | {0x004B00C2, AppletUtility, "AppletUtility"}, | 86 | {0x004B00C2, AppletUtility, "AppletUtility"}, |
| 87 | {0x004C0000, nullptr, "SetFatalErrDispMode"}, | 87 | {0x004C0000, nullptr, "SetFatalErrDispMode"}, |
| 88 | {0x004D0080, nullptr, "GetAppletProgramInfo"}, | 88 | {0x004D0080, nullptr, "GetAppletProgramInfo"}, |
| 89 | {0x004E0000, nullptr, "HardwareResetAsync"}, | 89 | {0x004E0000, nullptr, "HardwareResetAsync"}, |
| 90 | {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, | 90 | {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, |
| 91 | {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, | 91 | {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, |
| 92 | {0x00510080, GetStartupArgument, "GetStartupArgument"}, | 92 | {0x00510080, GetStartupArgument, "GetStartupArgument"}, |
| 93 | {0x00520104, nullptr, "Wrap1"}, | 93 | {0x00520104, nullptr, "Wrap1"}, |
| 94 | {0x00530104, nullptr, "Unwrap1"}, | 94 | {0x00530104, nullptr, "Unwrap1"}, |
| 95 | {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"}, | 95 | {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"}, |
| 96 | {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"}, | 96 | {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"}, |
| 97 | {0x00580002, nullptr, "GetProgramID"}, | 97 | {0x00580002, nullptr, "GetProgramID"}, |
| 98 | {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, | 98 | {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, |
| 99 | {0x01020000, CheckNew3DS, "CheckNew3DS"} | 99 | {0x01020000, CheckNew3DS, "CheckNew3DS"}}; |
| 100 | }; | ||
| 101 | 100 | ||
| 102 | APT_S_Interface::APT_S_Interface() { | 101 | APT_S_Interface::APT_S_Interface() { |
| 103 | Register(FunctionTable); | 102 | Register(FunctionTable); |
diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp index 7bb804ffa..9c6223dd7 100644 --- a/src/core/hle/service/apt/apt_u.cpp +++ b/src/core/hle/service/apt/apt_u.cpp | |||
| @@ -9,95 +9,94 @@ namespace Service { | |||
| 9 | namespace APT { | 9 | namespace APT { |
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = { |
| 12 | {0x00010040, GetLockHandle, "GetLockHandle"}, | 12 | {0x00010040, GetLockHandle, "GetLockHandle"}, |
| 13 | {0x00020080, Initialize, "Initialize"}, | 13 | {0x00020080, Initialize, "Initialize"}, |
| 14 | {0x00030040, Enable, "Enable"}, | 14 | {0x00030040, Enable, "Enable"}, |
| 15 | {0x00040040, nullptr, "Finalize"}, | 15 | {0x00040040, nullptr, "Finalize"}, |
| 16 | {0x00050040, GetAppletManInfo, "GetAppletManInfo"}, | 16 | {0x00050040, GetAppletManInfo, "GetAppletManInfo"}, |
| 17 | {0x00060040, GetAppletInfo, "GetAppletInfo"}, | 17 | {0x00060040, GetAppletInfo, "GetAppletInfo"}, |
| 18 | {0x00070000, nullptr, "GetLastSignaledAppletId"}, | 18 | {0x00070000, nullptr, "GetLastSignaledAppletId"}, |
| 19 | {0x00080000, nullptr, "CountRegisteredApplet"}, | 19 | {0x00080000, nullptr, "CountRegisteredApplet"}, |
| 20 | {0x00090040, IsRegistered, "IsRegistered"}, | 20 | {0x00090040, IsRegistered, "IsRegistered"}, |
| 21 | {0x000A0040, nullptr, "GetAttribute"}, | 21 | {0x000A0040, nullptr, "GetAttribute"}, |
| 22 | {0x000B0040, InquireNotification, "InquireNotification"}, | 22 | {0x000B0040, InquireNotification, "InquireNotification"}, |
| 23 | {0x000C0104, SendParameter, "SendParameter"}, | 23 | {0x000C0104, SendParameter, "SendParameter"}, |
| 24 | {0x000D0080, ReceiveParameter, "ReceiveParameter"}, | 24 | {0x000D0080, ReceiveParameter, "ReceiveParameter"}, |
| 25 | {0x000E0080, GlanceParameter, "GlanceParameter"}, | 25 | {0x000E0080, GlanceParameter, "GlanceParameter"}, |
| 26 | {0x000F0100, CancelParameter, "CancelParameter"}, | 26 | {0x000F0100, CancelParameter, "CancelParameter"}, |
| 27 | {0x001000C2, nullptr, "DebugFunc"}, | 27 | {0x001000C2, nullptr, "DebugFunc"}, |
| 28 | {0x001100C0, nullptr, "MapProgramIdForDebug"}, | 28 | {0x001100C0, nullptr, "MapProgramIdForDebug"}, |
| 29 | {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"}, | 29 | {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"}, |
| 30 | {0x00130000, nullptr, "GetPreparationState"}, | 30 | {0x00130000, nullptr, "GetPreparationState"}, |
| 31 | {0x00140040, nullptr, "SetPreparationState"}, | 31 | {0x00140040, nullptr, "SetPreparationState"}, |
| 32 | {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, | 32 | {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, |
| 33 | {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, | 33 | {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, |
| 34 | {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, | 34 | {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, |
| 35 | {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, | 35 | {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, |
| 36 | {0x00190040, nullptr, "PrepareToStartSystemApplet"}, | 36 | {0x00190040, nullptr, "PrepareToStartSystemApplet"}, |
| 37 | {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, | 37 | {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, |
| 38 | {0x001B00C4, nullptr, "StartApplication"}, | 38 | {0x001B00C4, nullptr, "StartApplication"}, |
| 39 | {0x001C0000, nullptr, "WakeupApplication"}, | 39 | {0x001C0000, nullptr, "WakeupApplication"}, |
| 40 | {0x001D0000, nullptr, "CancelApplication"}, | 40 | {0x001D0000, nullptr, "CancelApplication"}, |
| 41 | {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, | 41 | {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, |
| 42 | {0x001F0084, nullptr, "StartSystemApplet"}, | 42 | {0x001F0084, nullptr, "StartSystemApplet"}, |
| 43 | {0x00200044, nullptr, "StartNewestHomeMenu"}, | 43 | {0x00200044, nullptr, "StartNewestHomeMenu"}, |
| 44 | {0x00210000, nullptr, "OrderToCloseApplication"}, | 44 | {0x00210000, nullptr, "OrderToCloseApplication"}, |
| 45 | {0x00220040, nullptr, "PrepareToCloseApplication"}, | 45 | {0x00220040, nullptr, "PrepareToCloseApplication"}, |
| 46 | {0x00230040, nullptr, "PrepareToJumpToApplication"}, | 46 | {0x00230040, nullptr, "PrepareToJumpToApplication"}, |
| 47 | {0x00240044, nullptr, "JumpToApplication"}, | 47 | {0x00240044, nullptr, "JumpToApplication"}, |
| 48 | {0x002500C0, nullptr, "PrepareToCloseLibraryApplet"}, | 48 | {0x002500C0, nullptr, "PrepareToCloseLibraryApplet"}, |
| 49 | {0x00260000, nullptr, "PrepareToCloseSystemApplet"}, | 49 | {0x00260000, nullptr, "PrepareToCloseSystemApplet"}, |
| 50 | {0x00270044, nullptr, "CloseApplication"}, | 50 | {0x00270044, nullptr, "CloseApplication"}, |
| 51 | {0x00280044, nullptr, "CloseLibraryApplet"}, | 51 | {0x00280044, nullptr, "CloseLibraryApplet"}, |
| 52 | {0x00290044, nullptr, "CloseSystemApplet"}, | 52 | {0x00290044, nullptr, "CloseSystemApplet"}, |
| 53 | {0x002A0000, nullptr, "OrderToCloseSystemApplet"}, | 53 | {0x002A0000, nullptr, "OrderToCloseSystemApplet"}, |
| 54 | {0x002B0000, nullptr, "PrepareToJumpToHomeMenu"}, | 54 | {0x002B0000, nullptr, "PrepareToJumpToHomeMenu"}, |
| 55 | {0x002C0044, nullptr, "JumpToHomeMenu"}, | 55 | {0x002C0044, nullptr, "JumpToHomeMenu"}, |
| 56 | {0x002D0000, nullptr, "PrepareToLeaveHomeMenu"}, | 56 | {0x002D0000, nullptr, "PrepareToLeaveHomeMenu"}, |
| 57 | {0x002E0044, nullptr, "LeaveHomeMenu"}, | 57 | {0x002E0044, nullptr, "LeaveHomeMenu"}, |
| 58 | {0x002F0040, nullptr, "PrepareToLeaveResidentApplet"}, | 58 | {0x002F0040, nullptr, "PrepareToLeaveResidentApplet"}, |
| 59 | {0x00300044, nullptr, "LeaveResidentApplet"}, | 59 | {0x00300044, nullptr, "LeaveResidentApplet"}, |
| 60 | {0x00310100, nullptr, "PrepareToDoApplicationJump"}, | 60 | {0x00310100, nullptr, "PrepareToDoApplicationJump"}, |
| 61 | {0x00320084, nullptr, "DoApplicationJump"}, | 61 | {0x00320084, nullptr, "DoApplicationJump"}, |
| 62 | {0x00330000, nullptr, "GetProgramIdOnApplicationJump"}, | 62 | {0x00330000, nullptr, "GetProgramIdOnApplicationJump"}, |
| 63 | {0x00340084, nullptr, "SendDeliverArg"}, | 63 | {0x00340084, nullptr, "SendDeliverArg"}, |
| 64 | {0x00350080, nullptr, "ReceiveDeliverArg"}, | 64 | {0x00350080, nullptr, "ReceiveDeliverArg"}, |
| 65 | {0x00360040, nullptr, "LoadSysMenuArg"}, | 65 | {0x00360040, nullptr, "LoadSysMenuArg"}, |
| 66 | {0x00370042, nullptr, "StoreSysMenuArg"}, | 66 | {0x00370042, nullptr, "StoreSysMenuArg"}, |
| 67 | {0x00380040, nullptr, "PreloadResidentApplet"}, | 67 | {0x00380040, nullptr, "PreloadResidentApplet"}, |
| 68 | {0x00390040, nullptr, "PrepareToStartResidentApplet"}, | 68 | {0x00390040, nullptr, "PrepareToStartResidentApplet"}, |
| 69 | {0x003A0044, nullptr, "StartResidentApplet"}, | 69 | {0x003A0044, nullptr, "StartResidentApplet"}, |
| 70 | {0x003B0040, nullptr, "CancelLibraryApplet"}, | 70 | {0x003B0040, nullptr, "CancelLibraryApplet"}, |
| 71 | {0x003C0042, nullptr, "SendDspSleep"}, | 71 | {0x003C0042, nullptr, "SendDspSleep"}, |
| 72 | {0x003D0042, nullptr, "SendDspWakeUp"}, | 72 | {0x003D0042, nullptr, "SendDspWakeUp"}, |
| 73 | {0x003E0080, nullptr, "ReplySleepQuery"}, | 73 | {0x003E0080, nullptr, "ReplySleepQuery"}, |
| 74 | {0x003F0040, nullptr, "ReplySleepNotificationComplete"}, | 74 | {0x003F0040, nullptr, "ReplySleepNotificationComplete"}, |
| 75 | {0x00400042, nullptr, "SendCaptureBufferInfo"}, | 75 | {0x00400042, nullptr, "SendCaptureBufferInfo"}, |
| 76 | {0x00410040, nullptr, "ReceiveCaptureBufferInfo"}, | 76 | {0x00410040, nullptr, "ReceiveCaptureBufferInfo"}, |
| 77 | {0x00420080, nullptr, "SleepSystem"}, | 77 | {0x00420080, nullptr, "SleepSystem"}, |
| 78 | {0x00430040, NotifyToWait, "NotifyToWait"}, | 78 | {0x00430040, NotifyToWait, "NotifyToWait"}, |
| 79 | {0x00440000, GetSharedFont, "GetSharedFont"}, | 79 | {0x00440000, GetSharedFont, "GetSharedFont"}, |
| 80 | {0x00450040, nullptr, "GetWirelessRebootInfo"}, | 80 | {0x00450040, nullptr, "GetWirelessRebootInfo"}, |
| 81 | {0x00460104, nullptr, "Wrap"}, | 81 | {0x00460104, nullptr, "Wrap"}, |
| 82 | {0x00470104, nullptr, "Unwrap"}, | 82 | {0x00470104, nullptr, "Unwrap"}, |
| 83 | {0x00480100, nullptr, "GetProgramInfo"}, | 83 | {0x00480100, nullptr, "GetProgramInfo"}, |
| 84 | {0x00490180, nullptr, "Reboot"}, | 84 | {0x00490180, nullptr, "Reboot"}, |
| 85 | {0x004A0040, nullptr, "GetCaptureInfo"}, | 85 | {0x004A0040, nullptr, "GetCaptureInfo"}, |
| 86 | {0x004B00C2, AppletUtility, "AppletUtility"}, | 86 | {0x004B00C2, AppletUtility, "AppletUtility"}, |
| 87 | {0x004C0000, nullptr, "SetFatalErrDispMode"}, | 87 | {0x004C0000, nullptr, "SetFatalErrDispMode"}, |
| 88 | {0x004D0080, nullptr, "GetAppletProgramInfo"}, | 88 | {0x004D0080, nullptr, "GetAppletProgramInfo"}, |
| 89 | {0x004E0000, nullptr, "HardwareResetAsync"}, | 89 | {0x004E0000, nullptr, "HardwareResetAsync"}, |
| 90 | {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, | 90 | {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, |
| 91 | {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, | 91 | {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, |
| 92 | {0x00510080, GetStartupArgument, "GetStartupArgument"}, | 92 | {0x00510080, GetStartupArgument, "GetStartupArgument"}, |
| 93 | {0x00520104, nullptr, "Wrap1"}, | 93 | {0x00520104, nullptr, "Wrap1"}, |
| 94 | {0x00530104, nullptr, "Unwrap1"}, | 94 | {0x00530104, nullptr, "Unwrap1"}, |
| 95 | {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"}, | 95 | {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"}, |
| 96 | {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"}, | 96 | {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"}, |
| 97 | {0x00580002, nullptr, "GetProgramID"}, | 97 | {0x00580002, nullptr, "GetProgramID"}, |
| 98 | {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, | 98 | {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, |
| 99 | {0x01020000, CheckNew3DS, "CheckNew3DS"} | 99 | {0x01020000, CheckNew3DS, "CheckNew3DS"}}; |
| 100 | }; | ||
| 101 | 100 | ||
| 102 | APT_U_Interface::APT_U_Interface() { | 101 | APT_U_Interface::APT_U_Interface() { |
| 103 | Register(FunctionTable); | 102 | Register(FunctionTable); |
diff --git a/src/core/hle/service/boss/boss.cpp b/src/core/hle/service/boss/boss.cpp index 419ec976e..867b31fbf 100644 --- a/src/core/hle/service/boss/boss.cpp +++ b/src/core/hle/service/boss/boss.cpp | |||
| @@ -2,10 +2,10 @@ | |||
| 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/hle/service/service.h" | ||
| 6 | #include "core/hle/service/boss/boss.h" | 5 | #include "core/hle/service/boss/boss.h" |
| 7 | #include "core/hle/service/boss/boss_p.h" | 6 | #include "core/hle/service/boss/boss_p.h" |
| 8 | #include "core/hle/service/boss/boss_u.h" | 7 | #include "core/hle/service/boss/boss_u.h" |
| 8 | #include "core/hle/service/service.h" | ||
| 9 | 9 | ||
| 10 | namespace Service { | 10 | namespace Service { |
| 11 | namespace BOSS { | 11 | namespace BOSS { |
diff --git a/src/core/hle/service/boss/boss_p.cpp b/src/core/hle/service/boss/boss_p.cpp index c498abe4e..dfee8d055 100644 --- a/src/core/hle/service/boss/boss_p.cpp +++ b/src/core/hle/service/boss/boss_p.cpp | |||
| @@ -11,7 +11,7 @@ namespace BOSS { | |||
| 11 | // const Interface::FunctionInfo FunctionTable[] = { }; | 11 | // const Interface::FunctionInfo FunctionTable[] = { }; |
| 12 | 12 | ||
| 13 | BOSS_P_Interface::BOSS_P_Interface() { | 13 | BOSS_P_Interface::BOSS_P_Interface() { |
| 14 | //Register(FunctionTable); | 14 | // Register(FunctionTable); |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | } // namespace BOSS | 17 | } // namespace BOSS |
diff --git a/src/core/hle/service/boss/boss_u.cpp b/src/core/hle/service/boss/boss_u.cpp index d59babe71..6affa23b1 100644 --- a/src/core/hle/service/boss/boss_u.cpp +++ b/src/core/hle/service/boss/boss_u.cpp | |||
| @@ -8,10 +8,10 @@ namespace Service { | |||
| 8 | namespace BOSS { | 8 | namespace BOSS { |
| 9 | 9 | ||
| 10 | const Interface::FunctionInfo FunctionTable[] = { | 10 | const Interface::FunctionInfo FunctionTable[] = { |
| 11 | {0x00020100, nullptr, "GetStorageInfo"}, | 11 | {0x00020100, nullptr, "GetStorageInfo"}, |
| 12 | {0x000C0082, nullptr, "UnregisterTask"}, | 12 | {0x000C0082, nullptr, "UnregisterTask"}, |
| 13 | {0x001E0042, nullptr, "CancelTask"}, | 13 | {0x001E0042, nullptr, "CancelTask"}, |
| 14 | {0x00330042, nullptr, "StartBgImmediate"}, | 14 | {0x00330042, nullptr, "StartBgImmediate"}, |
| 15 | }; | 15 | }; |
| 16 | 16 | ||
| 17 | BOSS_U_Interface::BOSS_U_Interface() { | 17 | BOSS_U_Interface::BOSS_U_Interface() { |
diff --git a/src/core/hle/service/cam/cam.cpp b/src/core/hle/service/cam/cam.cpp index 6edcf9610..ec1f9c749 100644 --- a/src/core/hle/service/cam/cam.cpp +++ b/src/core/hle/service/cam/cam.cpp | |||
| @@ -71,15 +71,15 @@ void GetBufferErrorInterruptEvent(Service::Interface* self) { | |||
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | void SetReceiving(Service::Interface* self) { | 73 | void SetReceiving(Service::Interface* self) { |
| 74 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 74 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 75 | 75 | ||
| 76 | VAddr dest = cmd_buff[1]; | 76 | VAddr dest = cmd_buff[1]; |
| 77 | u8 port = cmd_buff[2] & 0xFF; | 77 | u8 port = cmd_buff[2] & 0xFF; |
| 78 | u32 image_size = cmd_buff[3]; | 78 | u32 image_size = cmd_buff[3]; |
| 79 | u16 trans_unit = cmd_buff[4] & 0xFFFF; | 79 | u16 trans_unit = cmd_buff[4] & 0xFFFF; |
| 80 | 80 | ||
| 81 | Kernel::Event* completion_event = (Port)port == Port::Cam2 ? | 81 | Kernel::Event* completion_event = |
| 82 | completion_event_cam2.get() : completion_event_cam1.get(); | 82 | (Port)port == Port::Cam2 ? completion_event_cam2.get() : completion_event_cam1.get(); |
| 83 | 83 | ||
| 84 | completion_event->Signal(); | 84 | completion_event->Signal(); |
| 85 | 85 | ||
| @@ -89,36 +89,36 @@ void SetReceiving(Service::Interface* self) { | |||
| 89 | cmd_buff[3] = Kernel::g_handle_table.Create(completion_event).MoveFrom(); | 89 | cmd_buff[3] = Kernel::g_handle_table.Create(completion_event).MoveFrom(); |
| 90 | 90 | ||
| 91 | LOG_WARNING(Service_CAM, "(STUBBED) called, addr=0x%X, port=%d, image_size=%d, trans_unit=%d", | 91 | LOG_WARNING(Service_CAM, "(STUBBED) called, addr=0x%X, port=%d, image_size=%d, trans_unit=%d", |
| 92 | dest, port, image_size, trans_unit); | 92 | dest, port, image_size, trans_unit); |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | void SetTransferLines(Service::Interface* self) { | 95 | void SetTransferLines(Service::Interface* self) { |
| 96 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 96 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 97 | 97 | ||
| 98 | u8 port = cmd_buff[1] & 0xFF; | 98 | u8 port = cmd_buff[1] & 0xFF; |
| 99 | u16 transfer_lines = cmd_buff[2] & 0xFFFF; | 99 | u16 transfer_lines = cmd_buff[2] & 0xFFFF; |
| 100 | u16 width = cmd_buff[3] & 0xFFFF; | 100 | u16 width = cmd_buff[3] & 0xFFFF; |
| 101 | u16 height = cmd_buff[4] & 0xFFFF; | 101 | u16 height = cmd_buff[4] & 0xFFFF; |
| 102 | 102 | ||
| 103 | cmd_buff[0] = IPC::MakeHeader(0x9, 1, 0); | 103 | cmd_buff[0] = IPC::MakeHeader(0x9, 1, 0); |
| 104 | cmd_buff[1] = RESULT_SUCCESS.raw; | 104 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 105 | 105 | ||
| 106 | LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, lines=%d, width=%d, height=%d", | 106 | LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, lines=%d, width=%d, height=%d", port, |
| 107 | port, transfer_lines, width, height); | 107 | transfer_lines, width, height); |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | void GetMaxLines(Service::Interface* self) { | 110 | void GetMaxLines(Service::Interface* self) { |
| 111 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 111 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 112 | 112 | ||
| 113 | u16 width = cmd_buff[1] & 0xFFFF; | 113 | u16 width = cmd_buff[1] & 0xFFFF; |
| 114 | u16 height = cmd_buff[2] & 0xFFFF; | 114 | u16 height = cmd_buff[2] & 0xFFFF; |
| 115 | 115 | ||
| 116 | cmd_buff[0] = IPC::MakeHeader(0xA, 2, 0); | 116 | cmd_buff[0] = IPC::MakeHeader(0xA, 2, 0); |
| 117 | cmd_buff[1] = RESULT_SUCCESS.raw; | 117 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 118 | cmd_buff[2] = TRANSFER_BYTES / (2 * width); | 118 | cmd_buff[2] = TRANSFER_BYTES / (2 * width); |
| 119 | 119 | ||
| 120 | LOG_WARNING(Service_CAM, "(STUBBED) called, width=%d, height=%d, lines = %d", | 120 | LOG_WARNING(Service_CAM, "(STUBBED) called, width=%d, height=%d, lines = %d", width, height, |
| 121 | width, height, cmd_buff[2]); | 121 | cmd_buff[2]); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | void GetTransferBytes(Service::Interface* self) { | 124 | void GetTransferBytes(Service::Interface* self) { |
| @@ -136,7 +136,7 @@ void GetTransferBytes(Service::Interface* self) { | |||
| 136 | void SetTrimming(Service::Interface* self) { | 136 | void SetTrimming(Service::Interface* self) { |
| 137 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 137 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 138 | 138 | ||
| 139 | u8 port = cmd_buff[1] & 0xFF; | 139 | u8 port = cmd_buff[1] & 0xFF; |
| 140 | bool trim = (cmd_buff[2] & 0xFF) != 0; | 140 | bool trim = (cmd_buff[2] & 0xFF) != 0; |
| 141 | 141 | ||
| 142 | cmd_buff[0] = IPC::MakeHeader(0xE, 1, 0); | 142 | cmd_buff[0] = IPC::MakeHeader(0xE, 1, 0); |
| @@ -148,17 +148,17 @@ void SetTrimming(Service::Interface* self) { | |||
| 148 | void SetTrimmingParamsCenter(Service::Interface* self) { | 148 | void SetTrimmingParamsCenter(Service::Interface* self) { |
| 149 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 149 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 150 | 150 | ||
| 151 | u8 port = cmd_buff[1] & 0xFF; | 151 | u8 port = cmd_buff[1] & 0xFF; |
| 152 | s16 trimW = cmd_buff[2] & 0xFFFF; | 152 | s16 trimW = cmd_buff[2] & 0xFFFF; |
| 153 | s16 trimH = cmd_buff[3] & 0xFFFF; | 153 | s16 trimH = cmd_buff[3] & 0xFFFF; |
| 154 | s16 camW = cmd_buff[4] & 0xFFFF; | 154 | s16 camW = cmd_buff[4] & 0xFFFF; |
| 155 | s16 camH = cmd_buff[5] & 0xFFFF; | 155 | s16 camH = cmd_buff[5] & 0xFFFF; |
| 156 | 156 | ||
| 157 | cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0); | 157 | cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0); |
| 158 | cmd_buff[1] = RESULT_SUCCESS.raw; | 158 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 159 | 159 | ||
| 160 | LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, trimW=%d, trimH=%d, camW=%d, camH=%d", | 160 | LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, trimW=%d, trimH=%d, camW=%d, camH=%d", |
| 161 | port, trimW, trimH, camW, camH); | 161 | port, trimW, trimH, camW, camH); |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | void Activate(Service::Interface* self) { | 164 | void Activate(Service::Interface* self) { |
| @@ -169,36 +169,35 @@ void Activate(Service::Interface* self) { | |||
| 169 | cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0); | 169 | cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0); |
| 170 | cmd_buff[1] = RESULT_SUCCESS.raw; | 170 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 171 | 171 | ||
| 172 | LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d", | 172 | LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d", cam_select); |
| 173 | cam_select); | ||
| 174 | } | 173 | } |
| 175 | 174 | ||
| 176 | void FlipImage(Service::Interface* self) { | 175 | void FlipImage(Service::Interface* self) { |
| 177 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 176 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 178 | 177 | ||
| 179 | u8 cam_select = cmd_buff[1] & 0xFF; | 178 | u8 cam_select = cmd_buff[1] & 0xFF; |
| 180 | u8 flip = cmd_buff[2] & 0xFF; | 179 | u8 flip = cmd_buff[2] & 0xFF; |
| 181 | u8 context = cmd_buff[3] & 0xFF; | 180 | u8 context = cmd_buff[3] & 0xFF; |
| 182 | 181 | ||
| 183 | cmd_buff[0] = IPC::MakeHeader(0x1D, 1, 0); | 182 | cmd_buff[0] = IPC::MakeHeader(0x1D, 1, 0); |
| 184 | cmd_buff[1] = RESULT_SUCCESS.raw; | 183 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 185 | 184 | ||
| 186 | LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, flip=%d, context=%d", | 185 | LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, flip=%d, context=%d", cam_select, |
| 187 | cam_select, flip, context); | 186 | flip, context); |
| 188 | } | 187 | } |
| 189 | 188 | ||
| 190 | void SetSize(Service::Interface* self) { | 189 | void SetSize(Service::Interface* self) { |
| 191 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 190 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 192 | 191 | ||
| 193 | u8 cam_select = cmd_buff[1] & 0xFF; | 192 | u8 cam_select = cmd_buff[1] & 0xFF; |
| 194 | u8 size = cmd_buff[2] & 0xFF; | 193 | u8 size = cmd_buff[2] & 0xFF; |
| 195 | u8 context = cmd_buff[3] & 0xFF; | 194 | u8 context = cmd_buff[3] & 0xFF; |
| 196 | 195 | ||
| 197 | cmd_buff[0] = IPC::MakeHeader(0x1F, 1, 0); | 196 | cmd_buff[0] = IPC::MakeHeader(0x1F, 1, 0); |
| 198 | cmd_buff[1] = RESULT_SUCCESS.raw; | 197 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 199 | 198 | ||
| 200 | LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, size=%d, context=%d", | 199 | LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, size=%d, context=%d", cam_select, |
| 201 | cam_select, size, context); | 200 | size, context); |
| 202 | } | 201 | } |
| 203 | 202 | ||
| 204 | void SetFrameRate(Service::Interface* self) { | 203 | void SetFrameRate(Service::Interface* self) { |
| @@ -210,8 +209,8 @@ void SetFrameRate(Service::Interface* self) { | |||
| 210 | cmd_buff[0] = IPC::MakeHeader(0x20, 1, 0); | 209 | cmd_buff[0] = IPC::MakeHeader(0x20, 1, 0); |
| 211 | cmd_buff[1] = RESULT_SUCCESS.raw; | 210 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 212 | 211 | ||
| 213 | LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, frame_rate=%d", | 212 | LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, frame_rate=%d", cam_select, |
| 214 | cam_select, frame_rate); | 213 | frame_rate); |
| 215 | } | 214 | } |
| 216 | 215 | ||
| 217 | void GetStereoCameraCalibrationData(Service::Interface* self) { | 216 | void GetStereoCameraCalibrationData(Service::Interface* self) { |
| @@ -293,10 +292,14 @@ void Init() { | |||
| 293 | AddService(new CAM_S_Interface); | 292 | AddService(new CAM_S_Interface); |
| 294 | AddService(new CAM_U_Interface); | 293 | AddService(new CAM_U_Interface); |
| 295 | 294 | ||
| 296 | completion_event_cam1 = Kernel::Event::Create(ResetType::OneShot, "CAM_U::completion_event_cam1"); | 295 | completion_event_cam1 = |
| 297 | completion_event_cam2 = Kernel::Event::Create(ResetType::OneShot, "CAM_U::completion_event_cam2"); | 296 | Kernel::Event::Create(ResetType::OneShot, "CAM_U::completion_event_cam1"); |
| 298 | interrupt_error_event = Kernel::Event::Create(ResetType::OneShot, "CAM_U::interrupt_error_event"); | 297 | completion_event_cam2 = |
| 299 | vsync_interrupt_error_event = Kernel::Event::Create(ResetType::OneShot, "CAM_U::vsync_interrupt_error_event"); | 298 | Kernel::Event::Create(ResetType::OneShot, "CAM_U::completion_event_cam2"); |
| 299 | interrupt_error_event = | ||
| 300 | Kernel::Event::Create(ResetType::OneShot, "CAM_U::interrupt_error_event"); | ||
| 301 | vsync_interrupt_error_event = | ||
| 302 | Kernel::Event::Create(ResetType::OneShot, "CAM_U::vsync_interrupt_error_event"); | ||
| 300 | } | 303 | } |
| 301 | 304 | ||
| 302 | void Shutdown() { | 305 | void Shutdown() { |
diff --git a/src/core/hle/service/cam/cam.h b/src/core/hle/service/cam/cam.h index 2f4923728..a87183493 100644 --- a/src/core/hle/service/cam/cam.h +++ b/src/core/hle/service/cam/cam.h | |||
| @@ -14,12 +14,7 @@ | |||
| 14 | namespace Service { | 14 | namespace Service { |
| 15 | namespace CAM { | 15 | namespace CAM { |
| 16 | 16 | ||
| 17 | enum class Port : u8 { | 17 | enum class Port : u8 { None = 0, Cam1 = 1, Cam2 = 2, Both = Cam1 | Cam2 }; |
| 18 | None = 0, | ||
| 19 | Cam1 = 1, | ||
| 20 | Cam2 = 2, | ||
| 21 | Both = Cam1 | Cam2 | ||
| 22 | }; | ||
| 23 | 18 | ||
| 24 | enum class CameraSelect : u8 { | 19 | enum class CameraSelect : u8 { |
| 25 | None = 0, | 20 | None = 0, |
| @@ -32,28 +27,11 @@ enum class CameraSelect : u8 { | |||
| 32 | All = Out1 | In1 | Out2 | 27 | All = Out1 | In1 | Out2 |
| 33 | }; | 28 | }; |
| 34 | 29 | ||
| 35 | enum class Effect : u8 { | 30 | enum class Effect : u8 { None = 0, Mono = 1, Sepia = 2, Negative = 3, Negafilm = 4, Sepia01 = 5 }; |
| 36 | None = 0, | ||
| 37 | Mono = 1, | ||
| 38 | Sepia = 2, | ||
| 39 | Negative = 3, | ||
| 40 | Negafilm = 4, | ||
| 41 | Sepia01 = 5 | ||
| 42 | }; | ||
| 43 | 31 | ||
| 44 | enum class Context : u8 { | 32 | enum class Context : u8 { None = 0, A = 1, B = 2, Both = A | B }; |
| 45 | None = 0, | ||
| 46 | A = 1, | ||
| 47 | B = 2, | ||
| 48 | Both = A | B | ||
| 49 | }; | ||
| 50 | 33 | ||
| 51 | enum class Flip : u8 { | 34 | enum class Flip : u8 { None = 0, Horizontal = 1, Vertical = 2, Reverse = 3 }; |
| 52 | None = 0, | ||
| 53 | Horizontal = 1, | ||
| 54 | Vertical = 2, | ||
| 55 | Reverse = 3 | ||
| 56 | }; | ||
| 57 | 35 | ||
| 58 | enum class Size : u8 { | 36 | enum class Size : u8 { |
| 59 | VGA = 0, | 37 | VGA = 0, |
| @@ -83,11 +61,7 @@ enum class FrameRate : u8 { | |||
| 83 | Rate_30_To_10 = 12 | 61 | Rate_30_To_10 = 12 |
| 84 | }; | 62 | }; |
| 85 | 63 | ||
| 86 | enum class ShutterSoundType : u8 { | 64 | enum class ShutterSoundType : u8 { Normal = 0, Movie = 1, MovieEnd = 2 }; |
| 87 | Normal = 0, | ||
| 88 | Movie = 1, | ||
| 89 | MovieEnd = 2 | ||
| 90 | }; | ||
| 91 | 65 | ||
| 92 | enum class WhiteBalance : u8 { | 66 | enum class WhiteBalance : u8 { |
| 93 | BalanceAuto = 0, | 67 | BalanceAuto = 0, |
| @@ -106,13 +80,7 @@ enum class WhiteBalance : u8 { | |||
| 106 | BalanceShade = Balance7000K | 80 | BalanceShade = Balance7000K |
| 107 | }; | 81 | }; |
| 108 | 82 | ||
| 109 | enum class PhotoMode : u8 { | 83 | enum class PhotoMode : u8 { Normal = 0, Portrait = 1, Landscape = 2, Nightview = 3, Letter0 = 4 }; |
| 110 | Normal = 0, | ||
| 111 | Portrait = 1, | ||
| 112 | Landscape = 2, | ||
| 113 | Nightview = 3, | ||
| 114 | Letter0 = 4 | ||
| 115 | }; | ||
| 116 | 84 | ||
| 117 | enum class LensCorrection : u8 { | 85 | enum class LensCorrection : u8 { |
| 118 | Off = 0, | 86 | Off = 0, |
| @@ -140,21 +108,18 @@ enum class Contrast : u8 { | |||
| 140 | High = Pattern07 | 108 | High = Pattern07 |
| 141 | }; | 109 | }; |
| 142 | 110 | ||
| 143 | enum class OutputFormat : u8 { | 111 | enum class OutputFormat : u8 { YUV422 = 0, RGB565 = 1 }; |
| 144 | YUV422 = 0, | ||
| 145 | RGB565 = 1 | ||
| 146 | }; | ||
| 147 | 112 | ||
| 148 | /// Stereo camera calibration data. | 113 | /// Stereo camera calibration data. |
| 149 | struct StereoCameraCalibrationData { | 114 | struct StereoCameraCalibrationData { |
| 150 | u8 isValidRotationXY; ///< Bool indicating whether the X and Y rotation data is valid. | 115 | u8 isValidRotationXY; ///< Bool indicating whether the X and Y rotation data is valid. |
| 151 | INSERT_PADDING_BYTES(3); | 116 | INSERT_PADDING_BYTES(3); |
| 152 | float_le scale; ///< Scale to match the left camera image with the right. | 117 | float_le scale; ///< Scale to match the left camera image with the right. |
| 153 | float_le rotationZ; ///< Z axis rotation to match the left camera image with the right. | 118 | float_le rotationZ; ///< Z axis rotation to match the left camera image with the right. |
| 154 | float_le translationX; ///< X axis translation to match the left camera image with the right. | 119 | float_le translationX; ///< X axis translation to match the left camera image with the right. |
| 155 | float_le translationY; ///< Y axis translation to match the left camera image with the right. | 120 | float_le translationY; ///< Y axis translation to match the left camera image with the right. |
| 156 | float_le rotationX; ///< X axis rotation to match the left camera image with the right. | 121 | float_le rotationX; ///< X axis rotation to match the left camera image with the right. |
| 157 | float_le rotationY; ///< Y axis rotation to match the left camera image with the right. | 122 | float_le rotationY; ///< Y axis rotation to match the left camera image with the right. |
| 158 | float_le angleOfViewRight; ///< Right camera angle of view. | 123 | float_le angleOfViewRight; ///< Right camera angle of view. |
| 159 | float_le angleOfViewLeft; ///< Left camera angle of view. | 124 | float_le angleOfViewLeft; ///< Left camera angle of view. |
| 160 | float_le distanceToChart; ///< Distance between cameras and measurement chart. | 125 | float_le distanceToChart; ///< Distance between cameras and measurement chart. |
| @@ -163,7 +128,8 @@ struct StereoCameraCalibrationData { | |||
| 163 | s16_le imageHeight; ///< Image height. | 128 | s16_le imageHeight; ///< Image height. |
| 164 | INSERT_PADDING_BYTES(16); | 129 | INSERT_PADDING_BYTES(16); |
| 165 | }; | 130 | }; |
| 166 | static_assert(sizeof(StereoCameraCalibrationData) == 64, "StereoCameraCalibrationData structure size is wrong"); | 131 | static_assert(sizeof(StereoCameraCalibrationData) == 64, |
| 132 | "StereoCameraCalibrationData structure size is wrong"); | ||
| 167 | 133 | ||
| 168 | struct PackageParameterCameraSelect { | 134 | struct PackageParameterCameraSelect { |
| 169 | CameraSelect camera; | 135 | CameraSelect camera; |
| @@ -188,7 +154,8 @@ struct PackageParameterCameraSelect { | |||
| 188 | s16 auto_white_balance_window_height; | 154 | s16 auto_white_balance_window_height; |
| 189 | }; | 155 | }; |
| 190 | 156 | ||
| 191 | static_assert(sizeof(PackageParameterCameraSelect) == 28, "PackageParameterCameraSelect structure size is wrong"); | 157 | static_assert(sizeof(PackageParameterCameraSelect) == 28, |
| 158 | "PackageParameterCameraSelect structure size is wrong"); | ||
| 192 | 159 | ||
| 193 | /** | 160 | /** |
| 194 | * Unknown | 161 | * Unknown |
diff --git a/src/core/hle/service/cam/cam_c.cpp b/src/core/hle/service/cam/cam_c.cpp index 8fa7abc85..93b047c1a 100644 --- a/src/core/hle/service/cam/cam_c.cpp +++ b/src/core/hle/service/cam/cam_c.cpp | |||
| @@ -8,10 +8,10 @@ namespace Service { | |||
| 8 | namespace CAM { | 8 | namespace CAM { |
| 9 | 9 | ||
| 10 | // Empty arrays are illegal -- commented out until an entry is added. | 10 | // Empty arrays are illegal -- commented out until an entry is added. |
| 11 | //const Interface::FunctionInfo FunctionTable[] = { }; | 11 | // const Interface::FunctionInfo FunctionTable[] = { }; |
| 12 | 12 | ||
| 13 | CAM_C_Interface::CAM_C_Interface() { | 13 | CAM_C_Interface::CAM_C_Interface() { |
| 14 | //Register(FunctionTable); | 14 | // Register(FunctionTable); |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | } // namespace CAM | 17 | } // namespace CAM |
diff --git a/src/core/hle/service/cam/cam_q.cpp b/src/core/hle/service/cam/cam_q.cpp index d3ba91e9d..2ba853606 100644 --- a/src/core/hle/service/cam/cam_q.cpp +++ b/src/core/hle/service/cam/cam_q.cpp | |||
| @@ -8,10 +8,10 @@ namespace Service { | |||
| 8 | namespace CAM { | 8 | namespace CAM { |
| 9 | 9 | ||
| 10 | // Empty arrays are illegal -- commented out until an entry is added. | 10 | // Empty arrays are illegal -- commented out until an entry is added. |
| 11 | //const Interface::FunctionInfo FunctionTable[] = { }; | 11 | // const Interface::FunctionInfo FunctionTable[] = { }; |
| 12 | 12 | ||
| 13 | CAM_Q_Interface::CAM_Q_Interface() { | 13 | CAM_Q_Interface::CAM_Q_Interface() { |
| 14 | //Register(FunctionTable); | 14 | // Register(FunctionTable); |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | } // namespace CAM | 17 | } // namespace CAM |
diff --git a/src/core/hle/service/cam/cam_s.cpp b/src/core/hle/service/cam/cam_s.cpp index 2a13984d8..f1c6da587 100644 --- a/src/core/hle/service/cam/cam_s.cpp +++ b/src/core/hle/service/cam/cam_s.cpp | |||
| @@ -8,10 +8,10 @@ namespace Service { | |||
| 8 | namespace CAM { | 8 | namespace CAM { |
| 9 | 9 | ||
| 10 | // Empty arrays are illegal -- commented out until an entry is added. | 10 | // Empty arrays are illegal -- commented out until an entry is added. |
| 11 | //const Interface::FunctionInfo FunctionTable[] = { }; | 11 | // const Interface::FunctionInfo FunctionTable[] = { }; |
| 12 | 12 | ||
| 13 | CAM_S_Interface::CAM_S_Interface() { | 13 | CAM_S_Interface::CAM_S_Interface() { |
| 14 | //Register(FunctionTable); | 14 | // Register(FunctionTable); |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | } // namespace CAM | 17 | } // namespace CAM |
diff --git a/src/core/hle/service/cam/cam_u.cpp b/src/core/hle/service/cam/cam_u.cpp index a1070ebb2..af2123e5b 100644 --- a/src/core/hle/service/cam/cam_u.cpp +++ b/src/core/hle/service/cam/cam_u.cpp | |||
| @@ -9,68 +9,68 @@ namespace Service { | |||
| 9 | namespace CAM { | 9 | namespace CAM { |
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = { |
| 12 | {0x00010040, StartCapture, "StartCapture"}, | 12 | {0x00010040, StartCapture, "StartCapture"}, |
| 13 | {0x00020040, StopCapture, "StopCapture"}, | 13 | {0x00020040, StopCapture, "StopCapture"}, |
| 14 | {0x00030040, nullptr, "IsBusy"}, | 14 | {0x00030040, nullptr, "IsBusy"}, |
| 15 | {0x00040040, nullptr, "ClearBuffer"}, | 15 | {0x00040040, nullptr, "ClearBuffer"}, |
| 16 | {0x00050040, GetVsyncInterruptEvent, "GetVsyncInterruptEvent"}, | 16 | {0x00050040, GetVsyncInterruptEvent, "GetVsyncInterruptEvent"}, |
| 17 | {0x00060040, GetBufferErrorInterruptEvent, "GetBufferErrorInterruptEvent"}, | 17 | {0x00060040, GetBufferErrorInterruptEvent, "GetBufferErrorInterruptEvent"}, |
| 18 | {0x00070102, SetReceiving, "SetReceiving"}, | 18 | {0x00070102, SetReceiving, "SetReceiving"}, |
| 19 | {0x00080040, nullptr, "IsFinishedReceiving"}, | 19 | {0x00080040, nullptr, "IsFinishedReceiving"}, |
| 20 | {0x00090100, SetTransferLines, "SetTransferLines"}, | 20 | {0x00090100, SetTransferLines, "SetTransferLines"}, |
| 21 | {0x000A0080, GetMaxLines, "GetMaxLines"}, | 21 | {0x000A0080, GetMaxLines, "GetMaxLines"}, |
| 22 | {0x000B0100, nullptr, "SetTransferBytes"}, | 22 | {0x000B0100, nullptr, "SetTransferBytes"}, |
| 23 | {0x000C0040, GetTransferBytes, "GetTransferBytes"}, | 23 | {0x000C0040, GetTransferBytes, "GetTransferBytes"}, |
| 24 | {0x000D0080, nullptr, "GetMaxBytes"}, | 24 | {0x000D0080, nullptr, "GetMaxBytes"}, |
| 25 | {0x000E0080, SetTrimming, "SetTrimming"}, | 25 | {0x000E0080, SetTrimming, "SetTrimming"}, |
| 26 | {0x000F0040, nullptr, "IsTrimming"}, | 26 | {0x000F0040, nullptr, "IsTrimming"}, |
| 27 | {0x00100140, nullptr, "SetTrimmingParams"}, | 27 | {0x00100140, nullptr, "SetTrimmingParams"}, |
| 28 | {0x00110040, nullptr, "GetTrimmingParams"}, | 28 | {0x00110040, nullptr, "GetTrimmingParams"}, |
| 29 | {0x00120140, SetTrimmingParamsCenter, "SetTrimmingParamsCenter"}, | 29 | {0x00120140, SetTrimmingParamsCenter, "SetTrimmingParamsCenter"}, |
| 30 | {0x00130040, Activate, "Activate"}, | 30 | {0x00130040, Activate, "Activate"}, |
| 31 | {0x00140080, nullptr, "SwitchContext"}, | 31 | {0x00140080, nullptr, "SwitchContext"}, |
| 32 | {0x00150080, nullptr, "SetExposure"}, | 32 | {0x00150080, nullptr, "SetExposure"}, |
| 33 | {0x00160080, nullptr, "SetWhiteBalance"}, | 33 | {0x00160080, nullptr, "SetWhiteBalance"}, |
| 34 | {0x00170080, nullptr, "SetWhiteBalanceWithoutBaseUp"}, | 34 | {0x00170080, nullptr, "SetWhiteBalanceWithoutBaseUp"}, |
| 35 | {0x00180080, nullptr, "SetSharpness"}, | 35 | {0x00180080, nullptr, "SetSharpness"}, |
| 36 | {0x00190080, nullptr, "SetAutoExposure"}, | 36 | {0x00190080, nullptr, "SetAutoExposure"}, |
| 37 | {0x001A0040, nullptr, "IsAutoExposure"}, | 37 | {0x001A0040, nullptr, "IsAutoExposure"}, |
| 38 | {0x001B0080, nullptr, "SetAutoWhiteBalance"}, | 38 | {0x001B0080, nullptr, "SetAutoWhiteBalance"}, |
| 39 | {0x001C0040, nullptr, "IsAutoWhiteBalance"}, | 39 | {0x001C0040, nullptr, "IsAutoWhiteBalance"}, |
| 40 | {0x001D00C0, FlipImage, "FlipImage"}, | 40 | {0x001D00C0, FlipImage, "FlipImage"}, |
| 41 | {0x001E0200, nullptr, "SetDetailSize"}, | 41 | {0x001E0200, nullptr, "SetDetailSize"}, |
| 42 | {0x001F00C0, SetSize, "SetSize"}, | 42 | {0x001F00C0, SetSize, "SetSize"}, |
| 43 | {0x00200080, SetFrameRate, "SetFrameRate"}, | 43 | {0x00200080, SetFrameRate, "SetFrameRate"}, |
| 44 | {0x00210080, nullptr, "SetPhotoMode"}, | 44 | {0x00210080, nullptr, "SetPhotoMode"}, |
| 45 | {0x002200C0, nullptr, "SetEffect"}, | 45 | {0x002200C0, nullptr, "SetEffect"}, |
| 46 | {0x00230080, nullptr, "SetContrast"}, | 46 | {0x00230080, nullptr, "SetContrast"}, |
| 47 | {0x00240080, nullptr, "SetLensCorrection"}, | 47 | {0x00240080, nullptr, "SetLensCorrection"}, |
| 48 | {0x002500C0, nullptr, "SetOutputFormat"}, | 48 | {0x002500C0, nullptr, "SetOutputFormat"}, |
| 49 | {0x00260140, nullptr, "SetAutoExposureWindow"}, | 49 | {0x00260140, nullptr, "SetAutoExposureWindow"}, |
| 50 | {0x00270140, nullptr, "SetAutoWhiteBalanceWindow"}, | 50 | {0x00270140, nullptr, "SetAutoWhiteBalanceWindow"}, |
| 51 | {0x00280080, nullptr, "SetNoiseFilter"}, | 51 | {0x00280080, nullptr, "SetNoiseFilter"}, |
| 52 | {0x00290080, nullptr, "SynchronizeVsyncTiming"}, | 52 | {0x00290080, nullptr, "SynchronizeVsyncTiming"}, |
| 53 | {0x002A0080, nullptr, "GetLatestVsyncTiming"}, | 53 | {0x002A0080, nullptr, "GetLatestVsyncTiming"}, |
| 54 | {0x002B0000, GetStereoCameraCalibrationData, "GetStereoCameraCalibrationData"}, | 54 | {0x002B0000, GetStereoCameraCalibrationData, "GetStereoCameraCalibrationData"}, |
| 55 | {0x002C0400, nullptr, "SetStereoCameraCalibrationData"}, | 55 | {0x002C0400, nullptr, "SetStereoCameraCalibrationData"}, |
| 56 | {0x002D00C0, nullptr, "WriteRegisterI2c"}, | 56 | {0x002D00C0, nullptr, "WriteRegisterI2c"}, |
| 57 | {0x002E00C0, nullptr, "WriteMcuVariableI2c"}, | 57 | {0x002E00C0, nullptr, "WriteMcuVariableI2c"}, |
| 58 | {0x002F0080, nullptr, "ReadRegisterI2cExclusive"}, | 58 | {0x002F0080, nullptr, "ReadRegisterI2cExclusive"}, |
| 59 | {0x00300080, nullptr, "ReadMcuVariableI2cExclusive"}, | 59 | {0x00300080, nullptr, "ReadMcuVariableI2cExclusive"}, |
| 60 | {0x00310180, nullptr, "SetImageQualityCalibrationData"}, | 60 | {0x00310180, nullptr, "SetImageQualityCalibrationData"}, |
| 61 | {0x00320000, nullptr, "GetImageQualityCalibrationData"}, | 61 | {0x00320000, nullptr, "GetImageQualityCalibrationData"}, |
| 62 | {0x003302C0, nullptr, "SetPackageParameterWithoutContext"}, | 62 | {0x003302C0, nullptr, "SetPackageParameterWithoutContext"}, |
| 63 | {0x00340140, nullptr, "SetPackageParameterWithContext"}, | 63 | {0x00340140, nullptr, "SetPackageParameterWithContext"}, |
| 64 | {0x003501C0, nullptr, "SetPackageParameterWithContextDetail"}, | 64 | {0x003501C0, nullptr, "SetPackageParameterWithContextDetail"}, |
| 65 | {0x00360000, GetSuitableY2rStandardCoefficient, "GetSuitableY2rStandardCoefficient"}, | 65 | {0x00360000, GetSuitableY2rStandardCoefficient, "GetSuitableY2rStandardCoefficient"}, |
| 66 | {0x00370202, nullptr, "PlayShutterSoundWithWave"}, | 66 | {0x00370202, nullptr, "PlayShutterSoundWithWave"}, |
| 67 | {0x00380040, PlayShutterSound, "PlayShutterSound"}, | 67 | {0x00380040, PlayShutterSound, "PlayShutterSound"}, |
| 68 | {0x00390000, DriverInitialize, "DriverInitialize"}, | 68 | {0x00390000, DriverInitialize, "DriverInitialize"}, |
| 69 | {0x003A0000, DriverFinalize, "DriverFinalize"}, | 69 | {0x003A0000, DriverFinalize, "DriverFinalize"}, |
| 70 | {0x003B0000, nullptr, "GetActivatedCamera"}, | 70 | {0x003B0000, nullptr, "GetActivatedCamera"}, |
| 71 | {0x003C0000, nullptr, "GetSleepCamera"}, | 71 | {0x003C0000, nullptr, "GetSleepCamera"}, |
| 72 | {0x003D0040, nullptr, "SetSleepCamera"}, | 72 | {0x003D0040, nullptr, "SetSleepCamera"}, |
| 73 | {0x003E0040, nullptr, "SetBrightnessSynchronization"}, | 73 | {0x003E0040, nullptr, "SetBrightnessSynchronization"}, |
| 74 | }; | 74 | }; |
| 75 | 75 | ||
| 76 | CAM_U_Interface::CAM_U_Interface() { | 76 | CAM_U_Interface::CAM_U_Interface() { |
diff --git a/src/core/hle/service/cecd/cecd.cpp b/src/core/hle/service/cecd/cecd.cpp index 50c03495e..65a1d850b 100644 --- a/src/core/hle/service/cecd/cecd.cpp +++ b/src/core/hle/service/cecd/cecd.cpp | |||
| @@ -5,10 +5,10 @@ | |||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | 6 | ||
| 7 | #include "core/hle/kernel/event.h" | 7 | #include "core/hle/kernel/event.h" |
| 8 | #include "core/hle/service/service.h" | ||
| 9 | #include "core/hle/service/cecd/cecd.h" | 8 | #include "core/hle/service/cecd/cecd.h" |
| 10 | #include "core/hle/service/cecd/cecd_s.h" | 9 | #include "core/hle/service/cecd/cecd_s.h" |
| 11 | #include "core/hle/service/cecd/cecd_u.h" | 10 | #include "core/hle/service/cecd/cecd_u.h" |
| 11 | #include "core/hle/service/service.h" | ||
| 12 | 12 | ||
| 13 | namespace Service { | 13 | namespace Service { |
| 14 | namespace CECD { | 14 | namespace CECD { |
| @@ -28,7 +28,7 @@ void GetCecStateAbbreviated(Service::Interface* self) { | |||
| 28 | void GetCecInfoEventHandle(Service::Interface* self) { | 28 | void GetCecInfoEventHandle(Service::Interface* self) { |
| 29 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 29 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 30 | 30 | ||
| 31 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 31 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 32 | cmd_buff[3] = Kernel::g_handle_table.Create(cecinfo_event).MoveFrom(); // Event handle | 32 | cmd_buff[3] = Kernel::g_handle_table.Create(cecinfo_event).MoveFrom(); // Event handle |
| 33 | 33 | ||
| 34 | LOG_WARNING(Service_CECD, "(STUBBED) called"); | 34 | LOG_WARNING(Service_CECD, "(STUBBED) called"); |
| @@ -37,7 +37,7 @@ void GetCecInfoEventHandle(Service::Interface* self) { | |||
| 37 | void GetChangeStateEventHandle(Service::Interface* self) { | 37 | void GetChangeStateEventHandle(Service::Interface* self) { |
| 38 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 38 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 39 | 39 | ||
| 40 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 40 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 41 | cmd_buff[3] = Kernel::g_handle_table.Create(change_state_event).MoveFrom(); // Event handle | 41 | cmd_buff[3] = Kernel::g_handle_table.Create(change_state_event).MoveFrom(); // Event handle |
| 42 | 42 | ||
| 43 | LOG_WARNING(Service_CECD, "(STUBBED) called"); | 43 | LOG_WARNING(Service_CECD, "(STUBBED) called"); |
| @@ -48,7 +48,8 @@ void Init() { | |||
| 48 | AddService(new CECD_U_Interface); | 48 | AddService(new CECD_U_Interface); |
| 49 | 49 | ||
| 50 | cecinfo_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD_U::cecinfo_event"); | 50 | cecinfo_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD_U::cecinfo_event"); |
| 51 | change_state_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD_U::change_state_event"); | 51 | change_state_event = |
| 52 | Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD_U::change_state_event"); | ||
| 52 | } | 53 | } |
| 53 | 54 | ||
| 54 | void Shutdown() { | 55 | void Shutdown() { |
diff --git a/src/core/hle/service/cecd/cecd.h b/src/core/hle/service/cecd/cecd.h index 435611363..ea97f9266 100644 --- a/src/core/hle/service/cecd/cecd.h +++ b/src/core/hle/service/cecd/cecd.h | |||
| @@ -11,11 +11,13 @@ class Interface; | |||
| 11 | namespace CECD { | 11 | namespace CECD { |
| 12 | 12 | ||
| 13 | enum class CecStateAbbreviated { | 13 | enum class CecStateAbbreviated { |
| 14 | CEC_STATE_ABBREV_IDLE = 1, ///< Corresponds to CEC_STATE_IDLE | 14 | CEC_STATE_ABBREV_IDLE = 1, ///< Corresponds to CEC_STATE_IDLE |
| 15 | CEC_STATE_ABBREV_NOT_LOCAL = 2, ///< Corresponds to CEC_STATEs *FINISH*, *POST, and OVER_BOSS | 15 | CEC_STATE_ABBREV_NOT_LOCAL = 2, ///< Corresponds to CEC_STATEs *FINISH*, *POST, and OVER_BOSS |
| 16 | CEC_STATE_ABBREV_SCANNING = 3, ///< Corresponds to CEC_STATE_SCANNING | 16 | CEC_STATE_ABBREV_SCANNING = 3, ///< Corresponds to CEC_STATE_SCANNING |
| 17 | CEC_STATE_ABBREV_WLREADY = 4, ///< Corresponds to CEC_STATE_WIRELESS_READY when some unknown bool is true | 17 | CEC_STATE_ABBREV_WLREADY = |
| 18 | CEC_STATE_ABBREV_OTHER = 5, ///< Corresponds to CEC_STATEs besides *FINISH*, *POST, and OVER_BOSS and those listed here | 18 | 4, ///< Corresponds to CEC_STATE_WIRELESS_READY when some unknown bool is true |
| 19 | CEC_STATE_ABBREV_OTHER = 5, ///< Corresponds to CEC_STATEs besides *FINISH*, *POST, and | ||
| 20 | /// OVER_BOSS and those listed here | ||
| 19 | }; | 21 | }; |
| 20 | 22 | ||
| 21 | /** | 23 | /** |
diff --git a/src/core/hle/service/cecd/cecd_s.cpp b/src/core/hle/service/cecd/cecd_s.cpp index bfd821c07..7477b9320 100644 --- a/src/core/hle/service/cecd/cecd_s.cpp +++ b/src/core/hle/service/cecd/cecd_s.cpp | |||
| @@ -8,10 +8,10 @@ namespace Service { | |||
| 8 | namespace CECD { | 8 | namespace CECD { |
| 9 | 9 | ||
| 10 | // Empty arrays are illegal -- commented out until an entry is added. | 10 | // Empty arrays are illegal -- commented out until an entry is added. |
| 11 | //const Interface::FunctionInfo FunctionTable[] = { }; | 11 | // const Interface::FunctionInfo FunctionTable[] = { }; |
| 12 | 12 | ||
| 13 | CECD_S_Interface::CECD_S_Interface() { | 13 | CECD_S_Interface::CECD_S_Interface() { |
| 14 | //Register(FunctionTable); | 14 | // Register(FunctionTable); |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | } // namespace CECD | 17 | } // namespace CECD |
diff --git a/src/core/hle/service/cecd/cecd_u.cpp b/src/core/hle/service/cecd/cecd_u.cpp index be6d4d8f6..4b747de7b 100644 --- a/src/core/hle/service/cecd/cecd_u.cpp +++ b/src/core/hle/service/cecd/cecd_u.cpp | |||
| @@ -9,10 +9,10 @@ namespace Service { | |||
| 9 | namespace CECD { | 9 | namespace CECD { |
| 10 | 10 | ||
| 11 | static const Interface::FunctionInfo FunctionTable[] = { | 11 | static const Interface::FunctionInfo FunctionTable[] = { |
| 12 | {0x000E0000, GetCecStateAbbreviated, "GetCecStateAbbreviated"}, | 12 | {0x000E0000, GetCecStateAbbreviated, "GetCecStateAbbreviated"}, |
| 13 | {0x000F0000, GetCecInfoEventHandle, "GetCecInfoEventHandle"}, | 13 | {0x000F0000, GetCecInfoEventHandle, "GetCecInfoEventHandle"}, |
| 14 | {0x00100000, GetChangeStateEventHandle, "GetChangeStateEventHandle"}, | 14 | {0x00100000, GetChangeStateEventHandle, "GetChangeStateEventHandle"}, |
| 15 | {0x00120104, nullptr, "ReadSavedData"}, | 15 | {0x00120104, nullptr, "ReadSavedData"}, |
| 16 | }; | 16 | }; |
| 17 | 17 | ||
| 18 | CECD_U_Interface::CECD_U_Interface() { | 18 | CECD_U_Interface::CECD_U_Interface() { |
diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index a5dc47322..fe97a69d1 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | 11 | ||
| 12 | #include "core/file_sys/archive_systemsavedata.h" | 12 | #include "core/file_sys/archive_systemsavedata.h" |
| 13 | #include "core/file_sys/file_backend.h" | 13 | #include "core/file_sys/file_backend.h" |
| 14 | #include "core/settings.h" | ||
| 15 | #include "core/hle/result.h" | 14 | #include "core/hle/result.h" |
| 16 | #include "core/hle/service/cfg/cfg.h" | 15 | #include "core/hle/service/cfg/cfg.h" |
| 17 | #include "core/hle/service/cfg/cfg_i.h" | 16 | #include "core/hle/service/cfg/cfg_i.h" |
| @@ -19,6 +18,7 @@ | |||
| 19 | #include "core/hle/service/cfg/cfg_u.h" | 18 | #include "core/hle/service/cfg/cfg_u.h" |
| 20 | #include "core/hle/service/fs/archive.h" | 19 | #include "core/hle/service/fs/archive.h" |
| 21 | #include "core/hle/service/service.h" | 20 | #include "core/hle/service/service.h" |
| 21 | #include "core/settings.h" | ||
| 22 | 22 | ||
| 23 | namespace Service { | 23 | namespace Service { |
| 24 | namespace CFG { | 24 | namespace CFG { |
| @@ -33,25 +33,29 @@ namespace { | |||
| 33 | * contains information about the blocks in the file | 33 | * contains information about the blocks in the file |
| 34 | */ | 34 | */ |
| 35 | struct SaveFileConfig { | 35 | struct SaveFileConfig { |
| 36 | u16 total_entries; ///< The total number of set entries in the config file | 36 | u16 total_entries; ///< The total number of set entries in the config file |
| 37 | u16 data_entries_offset; ///< The offset where the data for the blocks start, this is hardcoded to 0x455C as per hardware | 37 | u16 data_entries_offset; ///< The offset where the data for the blocks start, this is hardcoded |
| 38 | SaveConfigBlockEntry block_entries[CONFIG_FILE_MAX_BLOCK_ENTRIES]; ///< The block headers, the maximum possible value is 1479 as per hardware | 38 | /// to 0x455C as per hardware |
| 39 | u32 unknown; ///< This field is unknown, possibly padding, 0 has been observed in hardware | 39 | SaveConfigBlockEntry block_entries[CONFIG_FILE_MAX_BLOCK_ENTRIES]; ///< The block headers, the |
| 40 | /// maximum possible value is | ||
| 41 | /// 1479 as per hardware | ||
| 42 | u32 unknown; ///< This field is unknown, possibly padding, 0 has been observed in hardware | ||
| 40 | }; | 43 | }; |
| 41 | static_assert(sizeof(SaveFileConfig) == 0x455C, "SaveFileConfig header must be exactly 0x455C bytes"); | 44 | static_assert(sizeof(SaveFileConfig) == 0x455C, |
| 45 | "SaveFileConfig header must be exactly 0x455C bytes"); | ||
| 42 | 46 | ||
| 43 | enum ConfigBlockID { | 47 | enum ConfigBlockID { |
| 44 | StereoCameraSettingsBlockID = 0x00050005, | 48 | StereoCameraSettingsBlockID = 0x00050005, |
| 45 | SoundOutputModeBlockID = 0x00070001, | 49 | SoundOutputModeBlockID = 0x00070001, |
| 46 | ConsoleUniqueIDBlockID = 0x00090001, | 50 | ConsoleUniqueIDBlockID = 0x00090001, |
| 47 | UsernameBlockID = 0x000A0000, | 51 | UsernameBlockID = 0x000A0000, |
| 48 | BirthdayBlockID = 0x000A0001, | 52 | BirthdayBlockID = 0x000A0001, |
| 49 | LanguageBlockID = 0x000A0002, | 53 | LanguageBlockID = 0x000A0002, |
| 50 | CountryInfoBlockID = 0x000B0000, | 54 | CountryInfoBlockID = 0x000B0000, |
| 51 | CountryNameBlockID = 0x000B0001, | 55 | CountryNameBlockID = 0x000B0001, |
| 52 | StateNameBlockID = 0x000B0002, | 56 | StateNameBlockID = 0x000B0002, |
| 53 | EULAVersionBlockID = 0x000D0000, | 57 | EULAVersionBlockID = 0x000D0000, |
| 54 | ConsoleModelBlockID = 0x000F0004, | 58 | ConsoleModelBlockID = 0x000F0004, |
| 55 | }; | 59 | }; |
| 56 | 60 | ||
| 57 | struct UsernameBlock { | 61 | struct UsernameBlock { |
| @@ -68,8 +72,8 @@ struct BirthdayBlock { | |||
| 68 | static_assert(sizeof(BirthdayBlock) == 2, "BirthdayBlock must be exactly 2 bytes"); | 72 | static_assert(sizeof(BirthdayBlock) == 2, "BirthdayBlock must be exactly 2 bytes"); |
| 69 | 73 | ||
| 70 | struct ConsoleModelInfo { | 74 | struct ConsoleModelInfo { |
| 71 | u8 model; ///< The console model (3DS, 2DS, etc) | 75 | u8 model; ///< The console model (3DS, 2DS, etc) |
| 72 | u8 unknown[3]; ///< Unknown data | 76 | u8 unknown[3]; ///< Unknown data |
| 73 | }; | 77 | }; |
| 74 | static_assert(sizeof(ConsoleModelInfo) == 4, "ConsoleModelInfo must be exactly 4 bytes"); | 78 | static_assert(sizeof(ConsoleModelInfo) == 4, "ConsoleModelInfo must be exactly 4 bytes"); |
| 75 | 79 | ||
| @@ -78,36 +82,36 @@ struct ConsoleCountryInfo { | |||
| 78 | u8 country_code; ///< The country code of the console | 82 | u8 country_code; ///< The country code of the console |
| 79 | }; | 83 | }; |
| 80 | static_assert(sizeof(ConsoleCountryInfo) == 4, "ConsoleCountryInfo must be exactly 4 bytes"); | 84 | static_assert(sizeof(ConsoleCountryInfo) == 4, "ConsoleCountryInfo must be exactly 4 bytes"); |
| 81 | |||
| 82 | } | 85 | } |
| 83 | 86 | ||
| 84 | static const u64 CFG_SAVE_ID = 0x00010017; | 87 | static const u64 CFG_SAVE_ID = 0x00010017; |
| 85 | static const u64 CONSOLE_UNIQUE_ID = 0xDEADC0DE; | 88 | static const u64 CONSOLE_UNIQUE_ID = 0xDEADC0DE; |
| 86 | static const ConsoleModelInfo CONSOLE_MODEL = { NINTENDO_3DS_XL, { 0, 0, 0 } }; | 89 | static const ConsoleModelInfo CONSOLE_MODEL = {NINTENDO_3DS_XL, {0, 0, 0}}; |
| 87 | static const u8 CONSOLE_LANGUAGE = LANGUAGE_EN; | 90 | static const u8 CONSOLE_LANGUAGE = LANGUAGE_EN; |
| 88 | static const UsernameBlock CONSOLE_USERNAME_BLOCK = { u"CITRA", 0, 0 }; | 91 | static const UsernameBlock CONSOLE_USERNAME_BLOCK = {u"CITRA", 0, 0}; |
| 89 | static const BirthdayBlock PROFILE_BIRTHDAY = { 3, 25 }; // March 25th, 2014 | 92 | static const BirthdayBlock PROFILE_BIRTHDAY = {3, 25}; // March 25th, 2014 |
| 90 | static const u8 SOUND_OUTPUT_MODE = SOUND_SURROUND; | 93 | static const u8 SOUND_OUTPUT_MODE = SOUND_SURROUND; |
| 91 | static const u8 UNITED_STATES_COUNTRY_ID = 49; | 94 | static const u8 UNITED_STATES_COUNTRY_ID = 49; |
| 92 | /// TODO(Subv): Find what the other bytes are | 95 | /// TODO(Subv): Find what the other bytes are |
| 93 | static const ConsoleCountryInfo COUNTRY_INFO = { { 0, 0, 0 }, UNITED_STATES_COUNTRY_ID }; | 96 | static const ConsoleCountryInfo COUNTRY_INFO = {{0, 0, 0}, UNITED_STATES_COUNTRY_ID}; |
| 94 | 97 | ||
| 95 | /** | 98 | /** |
| 96 | * TODO(Subv): Find out what this actually is, these values fix some NaN uniforms in some games, | 99 | * TODO(Subv): Find out what this actually is, these values fix some NaN uniforms in some games, |
| 97 | * for example Nintendo Zone | 100 | * for example Nintendo Zone |
| 98 | * Thanks Normmatt for providing this information | 101 | * Thanks Normmatt for providing this information |
| 99 | */ | 102 | */ |
| 100 | static const std::array<float, 8> STEREO_CAMERA_SETTINGS = {{ | 103 | static const std::array<float, 8> STEREO_CAMERA_SETTINGS = { |
| 101 | 62.0f, 289.0f, 76.80000305175781f, 46.08000183105469f, | 104 | {62.0f, 289.0f, 76.80000305175781f, 46.08000183105469f, 10.0f, 5.0f, 55.58000183105469f, |
| 102 | 10.0f, 5.0f, 55.58000183105469f, 21.56999969482422f | 105 | 21.56999969482422f}}; |
| 103 | }}; | 106 | static_assert(sizeof(STEREO_CAMERA_SETTINGS) == 0x20, |
| 104 | static_assert(sizeof(STEREO_CAMERA_SETTINGS) == 0x20, "STEREO_CAMERA_SETTINGS must be exactly 0x20 bytes"); | 107 | "STEREO_CAMERA_SETTINGS must be exactly 0x20 bytes"); |
| 105 | 108 | ||
| 106 | static const u32 CONFIG_SAVEFILE_SIZE = 0x8000; | 109 | static const u32 CONFIG_SAVEFILE_SIZE = 0x8000; |
| 107 | static std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer; | 110 | static std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer; |
| 108 | 111 | ||
| 109 | static Service::FS::ArchiveHandle cfg_system_save_data_archive; | 112 | static Service::FS::ArchiveHandle cfg_system_save_data_archive; |
| 110 | static const std::vector<u8> cfg_system_savedata_id = { 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x01, 0x00 }; | 113 | static const std::vector<u8> cfg_system_savedata_id = {0x00, 0x00, 0x00, 0x00, |
| 114 | 0x17, 0x00, 0x01, 0x00}; | ||
| 111 | 115 | ||
| 112 | void GetCountryCodeString(Service::Interface* self) { | 116 | void GetCountryCodeString(Service::Interface* self) { |
| 113 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 117 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| @@ -115,7 +119,9 @@ void GetCountryCodeString(Service::Interface* self) { | |||
| 115 | 119 | ||
| 116 | if (country_code_id >= country_codes.size() || 0 == country_codes[country_code_id]) { | 120 | if (country_code_id >= country_codes.size() || 0 == country_codes[country_code_id]) { |
| 117 | LOG_ERROR(Service_CFG, "requested country code id=%d is invalid", country_code_id); | 121 | LOG_ERROR(Service_CFG, "requested country code id=%d is invalid", country_code_id); |
| 118 | cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; | 122 | cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config, |
| 123 | ErrorSummary::WrongArgument, ErrorLevel::Permanent) | ||
| 124 | .raw; | ||
| 119 | return; | 125 | return; |
| 120 | } | 126 | } |
| 121 | 127 | ||
| @@ -139,8 +145,11 @@ void GetCountryCodeID(Service::Interface* self) { | |||
| 139 | } | 145 | } |
| 140 | 146 | ||
| 141 | if (0 == country_code_id) { | 147 | if (0 == country_code_id) { |
| 142 | LOG_ERROR(Service_CFG, "requested country code name=%c%c is invalid", country_code & 0xff, country_code >> 8); | 148 | LOG_ERROR(Service_CFG, "requested country code name=%c%c is invalid", country_code & 0xff, |
| 143 | cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; | 149 | country_code >> 8); |
| 150 | cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config, | ||
| 151 | ErrorSummary::WrongArgument, ErrorLevel::Permanent) | ||
| 152 | .raw; | ||
| 144 | cmd_buff[2] = 0xFFFF; | 153 | cmd_buff[2] = 0xFFFF; |
| 145 | return; | 154 | return; |
| 146 | } | 155 | } |
| @@ -185,8 +194,8 @@ void GetSystemModel(Service::Interface* self) { | |||
| 185 | u32 data; | 194 | u32 data; |
| 186 | 195 | ||
| 187 | // TODO(Subv): Find out the correct error codes | 196 | // TODO(Subv): Find out the correct error codes |
| 188 | cmd_buff[1] = Service::CFG::GetConfigInfoBlock(0x000F0004, 4, 0x8, | 197 | cmd_buff[1] = |
| 189 | reinterpret_cast<u8*>(&data)).raw; | 198 | Service::CFG::GetConfigInfoBlock(0x000F0004, 4, 0x8, reinterpret_cast<u8*>(&data)).raw; |
| 190 | cmd_buff[2] = data & 0xFF; | 199 | cmd_buff[2] = data & 0xFF; |
| 191 | } | 200 | } |
| 192 | 201 | ||
| @@ -195,8 +204,8 @@ void GetModelNintendo2DS(Service::Interface* self) { | |||
| 195 | u32 data; | 204 | u32 data; |
| 196 | 205 | ||
| 197 | // TODO(Subv): Find out the correct error codes | 206 | // TODO(Subv): Find out the correct error codes |
| 198 | cmd_buff[1] = Service::CFG::GetConfigInfoBlock(0x000F0004, 4, 0x8, | 207 | cmd_buff[1] = |
| 199 | reinterpret_cast<u8*>(&data)).raw; | 208 | Service::CFG::GetConfigInfoBlock(0x000F0004, 4, 0x8, reinterpret_cast<u8*>(&data)).raw; |
| 200 | 209 | ||
| 201 | u8 model = data & 0xFF; | 210 | u8 model = data & 0xFF; |
| 202 | if (model == Service::CFG::NINTENDO_2DS) | 211 | if (model == Service::CFG::NINTENDO_2DS) |
| @@ -267,24 +276,29 @@ static ResultVal<void*> GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 fl | |||
| 267 | // Read the header | 276 | // Read the header |
| 268 | SaveFileConfig* config = reinterpret_cast<SaveFileConfig*>(cfg_config_file_buffer.data()); | 277 | SaveFileConfig* config = reinterpret_cast<SaveFileConfig*>(cfg_config_file_buffer.data()); |
| 269 | 278 | ||
| 270 | auto itr = std::find_if(std::begin(config->block_entries), std::end(config->block_entries), | 279 | auto itr = |
| 271 | [&](const SaveConfigBlockEntry& entry) { | 280 | std::find_if(std::begin(config->block_entries), std::end(config->block_entries), |
| 272 | return entry.block_id == block_id; | 281 | [&](const SaveConfigBlockEntry& entry) { return entry.block_id == block_id; }); |
| 273 | }); | ||
| 274 | 282 | ||
| 275 | if (itr == std::end(config->block_entries)) { | 283 | if (itr == std::end(config->block_entries)) { |
| 276 | LOG_ERROR(Service_CFG, "Config block 0x%X with flags %u and size %u was not found", block_id, flag, size); | 284 | LOG_ERROR(Service_CFG, "Config block 0x%X with flags %u and size %u was not found", |
| 277 | return ResultCode(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent); | 285 | block_id, flag, size); |
| 286 | return ResultCode(ErrorDescription::NotFound, ErrorModule::Config, | ||
| 287 | ErrorSummary::WrongArgument, ErrorLevel::Permanent); | ||
| 278 | } | 288 | } |
| 279 | 289 | ||
| 280 | if ((itr->flags & flag) == 0) { | 290 | if ((itr->flags & flag) == 0) { |
| 281 | LOG_ERROR(Service_CFG, "Invalid flag %u for config block 0x%X with size %u", flag, block_id, size); | 291 | LOG_ERROR(Service_CFG, "Invalid flag %u for config block 0x%X with size %u", flag, block_id, |
| 282 | return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent); | 292 | size); |
| 293 | return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::Config, | ||
| 294 | ErrorSummary::WrongArgument, ErrorLevel::Permanent); | ||
| 283 | } | 295 | } |
| 284 | 296 | ||
| 285 | if (itr->size != size) { | 297 | if (itr->size != size) { |
| 286 | LOG_ERROR(Service_CFG, "Invalid size %u for config block 0x%X with flags %u", size, block_id, flag); | 298 | LOG_ERROR(Service_CFG, "Invalid size %u for config block 0x%X with flags %u", size, |
| 287 | return ResultCode(ErrorDescription::InvalidSize, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent); | 299 | block_id, flag); |
| 300 | return ResultCode(ErrorDescription::InvalidSize, ErrorModule::Config, | ||
| 301 | ErrorSummary::WrongArgument, ErrorLevel::Permanent); | ||
| 288 | } | 302 | } |
| 289 | 303 | ||
| 290 | void* pointer; | 304 | void* pointer; |
| @@ -318,7 +332,7 @@ ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* da | |||
| 318 | return ResultCode(-1); // TODO(Subv): Find the right error code | 332 | return ResultCode(-1); // TODO(Subv): Find the right error code |
| 319 | 333 | ||
| 320 | // Insert the block header with offset 0 for now | 334 | // Insert the block header with offset 0 for now |
| 321 | config->block_entries[config->total_entries] = { block_id, 0, size, flags }; | 335 | config->block_entries[config->total_entries] = {block_id, 0, size, flags}; |
| 322 | if (size > 4) { | 336 | if (size > 4) { |
| 323 | u32 offset = config->data_entries_offset; | 337 | u32 offset = config->data_entries_offset; |
| 324 | // Perform a search to locate the next offset for the new data | 338 | // Perform a search to locate the next offset for the new data |
| @@ -326,8 +340,7 @@ ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* da | |||
| 326 | for (int i = config->total_entries - 1; i >= 0; --i) { | 340 | for (int i = config->total_entries - 1; i >= 0; --i) { |
| 327 | // Ignore the blocks that don't have a separate data offset | 341 | // Ignore the blocks that don't have a separate data offset |
| 328 | if (config->block_entries[i].size > 4) { | 342 | if (config->block_entries[i].size > 4) { |
| 329 | offset = config->block_entries[i].offset_or_data + | 343 | offset = config->block_entries[i].offset_or_data + config->block_entries[i].size; |
| 330 | config->block_entries[i].size; | ||
| 331 | break; | 344 | break; |
| 332 | } | 345 | } |
| 333 | } | 346 | } |
| @@ -336,8 +349,7 @@ ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* da | |||
| 336 | 349 | ||
| 337 | // Write the data at the new offset | 350 | // Write the data at the new offset |
| 338 | memcpy(&cfg_config_file_buffer[offset], data, size); | 351 | memcpy(&cfg_config_file_buffer[offset], data, size); |
| 339 | } | 352 | } else { |
| 340 | else { | ||
| 341 | // The offset_or_data field in the header contains the data itself if it's 4 bytes or less | 353 | // The offset_or_data field in the header contains the data itself if it's 4 bytes or less |
| 342 | memcpy(&config->block_entries[config->total_entries].offset_or_data, data, size); | 354 | memcpy(&config->block_entries[config->total_entries].offset_or_data, data, size); |
| 343 | } | 355 | } |
| @@ -384,28 +396,40 @@ ResultCode FormatConfig() { | |||
| 384 | 396 | ||
| 385 | // 0x00030001 - Unknown | 397 | // 0x00030001 - Unknown |
| 386 | res = CreateConfigInfoBlk(0x00030001, 0x8, 0xE, zero_buffer); | 398 | res = CreateConfigInfoBlk(0x00030001, 0x8, 0xE, zero_buffer); |
| 387 | if (!res.IsSuccess()) return res; | 399 | if (!res.IsSuccess()) |
| 400 | return res; | ||
| 388 | 401 | ||
| 389 | res = CreateConfigInfoBlk(StereoCameraSettingsBlockID, sizeof(STEREO_CAMERA_SETTINGS), 0xE, STEREO_CAMERA_SETTINGS.data()); | 402 | res = CreateConfigInfoBlk(StereoCameraSettingsBlockID, sizeof(STEREO_CAMERA_SETTINGS), 0xE, |
| 390 | if (!res.IsSuccess()) return res; | 403 | STEREO_CAMERA_SETTINGS.data()); |
| 404 | if (!res.IsSuccess()) | ||
| 405 | return res; | ||
| 391 | 406 | ||
| 392 | res = CreateConfigInfoBlk(SoundOutputModeBlockID, sizeof(SOUND_OUTPUT_MODE), 0xE, &SOUND_OUTPUT_MODE); | 407 | res = CreateConfigInfoBlk(SoundOutputModeBlockID, sizeof(SOUND_OUTPUT_MODE), 0xE, |
| 393 | if (!res.IsSuccess()) return res; | 408 | &SOUND_OUTPUT_MODE); |
| 409 | if (!res.IsSuccess()) | ||
| 410 | return res; | ||
| 394 | 411 | ||
| 395 | res = CreateConfigInfoBlk(ConsoleUniqueIDBlockID, sizeof(CONSOLE_UNIQUE_ID), 0xE, &CONSOLE_UNIQUE_ID); | 412 | res = CreateConfigInfoBlk(ConsoleUniqueIDBlockID, sizeof(CONSOLE_UNIQUE_ID), 0xE, |
| 396 | if (!res.IsSuccess()) return res; | 413 | &CONSOLE_UNIQUE_ID); |
| 414 | if (!res.IsSuccess()) | ||
| 415 | return res; | ||
| 397 | 416 | ||
| 398 | res = CreateConfigInfoBlk(UsernameBlockID, sizeof(CONSOLE_USERNAME_BLOCK), 0xE, &CONSOLE_USERNAME_BLOCK); | 417 | res = CreateConfigInfoBlk(UsernameBlockID, sizeof(CONSOLE_USERNAME_BLOCK), 0xE, |
| 399 | if (!res.IsSuccess()) return res; | 418 | &CONSOLE_USERNAME_BLOCK); |
| 419 | if (!res.IsSuccess()) | ||
| 420 | return res; | ||
| 400 | 421 | ||
| 401 | res = CreateConfigInfoBlk(BirthdayBlockID, sizeof(PROFILE_BIRTHDAY), 0xE, &PROFILE_BIRTHDAY); | 422 | res = CreateConfigInfoBlk(BirthdayBlockID, sizeof(PROFILE_BIRTHDAY), 0xE, &PROFILE_BIRTHDAY); |
| 402 | if (!res.IsSuccess()) return res; | 423 | if (!res.IsSuccess()) |
| 424 | return res; | ||
| 403 | 425 | ||
| 404 | res = CreateConfigInfoBlk(LanguageBlockID, sizeof(CONSOLE_LANGUAGE), 0xE, &CONSOLE_LANGUAGE); | 426 | res = CreateConfigInfoBlk(LanguageBlockID, sizeof(CONSOLE_LANGUAGE), 0xE, &CONSOLE_LANGUAGE); |
| 405 | if (!res.IsSuccess()) return res; | 427 | if (!res.IsSuccess()) |
| 428 | return res; | ||
| 406 | 429 | ||
| 407 | res = CreateConfigInfoBlk(CountryInfoBlockID, sizeof(COUNTRY_INFO), 0xE, &COUNTRY_INFO); | 430 | res = CreateConfigInfoBlk(CountryInfoBlockID, sizeof(COUNTRY_INFO), 0xE, &COUNTRY_INFO); |
| 408 | if (!res.IsSuccess()) return res; | 431 | if (!res.IsSuccess()) |
| 432 | return res; | ||
| 409 | 433 | ||
| 410 | u16_le country_name_buffer[16][0x40] = {}; | 434 | u16_le country_name_buffer[16][0x40] = {}; |
| 411 | std::u16string region_name = Common::UTF8ToUTF16("Gensokyo"); | 435 | std::u16string region_name = Common::UTF8ToUTF16("Gensokyo"); |
| @@ -413,34 +437,44 @@ ResultCode FormatConfig() { | |||
| 413 | std::copy(region_name.cbegin(), region_name.cend(), country_name_buffer[i]); | 437 | std::copy(region_name.cbegin(), region_name.cend(), country_name_buffer[i]); |
| 414 | } | 438 | } |
| 415 | // 0x000B0001 - Localized names for the profile Country | 439 | // 0x000B0001 - Localized names for the profile Country |
| 416 | res = CreateConfigInfoBlk(CountryNameBlockID, sizeof(country_name_buffer), 0xE, country_name_buffer); | 440 | res = CreateConfigInfoBlk(CountryNameBlockID, sizeof(country_name_buffer), 0xE, |
| 417 | if (!res.IsSuccess()) return res; | 441 | country_name_buffer); |
| 442 | if (!res.IsSuccess()) | ||
| 443 | return res; | ||
| 418 | // 0x000B0002 - Localized names for the profile State/Province | 444 | // 0x000B0002 - Localized names for the profile State/Province |
| 419 | res = CreateConfigInfoBlk(StateNameBlockID, sizeof(country_name_buffer), 0xE, country_name_buffer); | 445 | res = CreateConfigInfoBlk(StateNameBlockID, sizeof(country_name_buffer), 0xE, |
| 420 | if (!res.IsSuccess()) return res; | 446 | country_name_buffer); |
| 447 | if (!res.IsSuccess()) | ||
| 448 | return res; | ||
| 421 | 449 | ||
| 422 | // 0x000B0003 - Unknown, related to country/address (zip code?) | 450 | // 0x000B0003 - Unknown, related to country/address (zip code?) |
| 423 | res = CreateConfigInfoBlk(0x000B0003, 0x4, 0xE, zero_buffer); | 451 | res = CreateConfigInfoBlk(0x000B0003, 0x4, 0xE, zero_buffer); |
| 424 | if (!res.IsSuccess()) return res; | 452 | if (!res.IsSuccess()) |
| 453 | return res; | ||
| 425 | 454 | ||
| 426 | // 0x000C0000 - Unknown | 455 | // 0x000C0000 - Unknown |
| 427 | res = CreateConfigInfoBlk(0x000C0000, 0xC0, 0xE, zero_buffer); | 456 | res = CreateConfigInfoBlk(0x000C0000, 0xC0, 0xE, zero_buffer); |
| 428 | if (!res.IsSuccess()) return res; | 457 | if (!res.IsSuccess()) |
| 458 | return res; | ||
| 429 | 459 | ||
| 430 | // 0x000C0001 - Unknown | 460 | // 0x000C0001 - Unknown |
| 431 | res = CreateConfigInfoBlk(0x000C0001, 0x14, 0xE, zero_buffer); | 461 | res = CreateConfigInfoBlk(0x000C0001, 0x14, 0xE, zero_buffer); |
| 432 | if (!res.IsSuccess()) return res; | 462 | if (!res.IsSuccess()) |
| 463 | return res; | ||
| 433 | 464 | ||
| 434 | // 0x000D0000 - Accepted EULA version | 465 | // 0x000D0000 - Accepted EULA version |
| 435 | res = CreateConfigInfoBlk(EULAVersionBlockID, 0x4, 0xE, zero_buffer); | 466 | res = CreateConfigInfoBlk(EULAVersionBlockID, 0x4, 0xE, zero_buffer); |
| 436 | if (!res.IsSuccess()) return res; | 467 | if (!res.IsSuccess()) |
| 468 | return res; | ||
| 437 | 469 | ||
| 438 | res = CreateConfigInfoBlk(ConsoleModelBlockID, sizeof(CONSOLE_MODEL), 0xC, &CONSOLE_MODEL); | 470 | res = CreateConfigInfoBlk(ConsoleModelBlockID, sizeof(CONSOLE_MODEL), 0xC, &CONSOLE_MODEL); |
| 439 | if (!res.IsSuccess()) return res; | 471 | if (!res.IsSuccess()) |
| 472 | return res; | ||
| 440 | 473 | ||
| 441 | // 0x00170000 - Unknown | 474 | // 0x00170000 - Unknown |
| 442 | res = CreateConfigInfoBlk(0x00170000, 0x4, 0xE, zero_buffer); | 475 | res = CreateConfigInfoBlk(0x00170000, 0x4, 0xE, zero_buffer); |
| 443 | if (!res.IsSuccess()) return res; | 476 | if (!res.IsSuccess()) |
| 477 | return res; | ||
| 444 | 478 | ||
| 445 | // Save the buffer to the file | 479 | // Save the buffer to the file |
| 446 | res = UpdateConfigNANDSavegame(); | 480 | res = UpdateConfigNANDSavegame(); |
| @@ -452,15 +486,18 @@ ResultCode FormatConfig() { | |||
| 452 | ResultCode LoadConfigNANDSaveFile() { | 486 | ResultCode LoadConfigNANDSaveFile() { |
| 453 | // Open the SystemSaveData archive 0x00010017 | 487 | // Open the SystemSaveData archive 0x00010017 |
| 454 | FileSys::Path archive_path(cfg_system_savedata_id); | 488 | FileSys::Path archive_path(cfg_system_savedata_id); |
| 455 | auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); | 489 | auto archive_result = |
| 490 | Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); | ||
| 456 | 491 | ||
| 457 | // If the archive didn't exist, create the files inside | 492 | // If the archive didn't exist, create the files inside |
| 458 | if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { | 493 | if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { |
| 459 | // Format the archive to create the directories | 494 | // Format the archive to create the directories |
| 460 | Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SystemSaveData, FileSys::ArchiveFormatInfo(), archive_path); | 495 | Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SystemSaveData, |
| 496 | FileSys::ArchiveFormatInfo(), archive_path); | ||
| 461 | 497 | ||
| 462 | // Open it again to get a valid archive now that the folder exists | 498 | // Open it again to get a valid archive now that the folder exists |
| 463 | archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); | 499 | archive_result = |
| 500 | Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); | ||
| 464 | } | 501 | } |
| 465 | 502 | ||
| 466 | ASSERT_MSG(archive_result.Succeeded(), "Could not open the CFG SystemSaveData archive!"); | 503 | ASSERT_MSG(archive_result.Succeeded(), "Could not open the CFG SystemSaveData archive!"); |
| @@ -515,7 +552,7 @@ std::u16string GetUsername() { | |||
| 515 | } | 552 | } |
| 516 | 553 | ||
| 517 | void SetBirthday(u8 month, u8 day) { | 554 | void SetBirthday(u8 month, u8 day) { |
| 518 | BirthdayBlock block = { month, day }; | 555 | BirthdayBlock block = {month, day}; |
| 519 | SetConfigInfoBlock(BirthdayBlockID, sizeof(block), 4, &block); | 556 | SetConfigInfoBlock(BirthdayBlockID, sizeof(block), 4, &block); |
| 520 | } | 557 | } |
| 521 | 558 | ||
diff --git a/src/core/hle/service/cfg/cfg.h b/src/core/hle/service/cfg/cfg.h index 18f60f4ca..8cb231d72 100644 --- a/src/core/hle/service/cfg/cfg.h +++ b/src/core/hle/service/cfg/cfg.h | |||
| @@ -40,16 +40,13 @@ enum SystemLanguage { | |||
| 40 | LANGUAGE_TW = 11 | 40 | LANGUAGE_TW = 11 |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | enum SoundOutputMode { | 43 | enum SoundOutputMode { SOUND_MONO = 0, SOUND_STEREO = 1, SOUND_SURROUND = 2 }; |
| 44 | SOUND_MONO = 0, | ||
| 45 | SOUND_STEREO = 1, | ||
| 46 | SOUND_SURROUND = 2 | ||
| 47 | }; | ||
| 48 | 44 | ||
| 49 | /// Block header in the config savedata file | 45 | /// Block header in the config savedata file |
| 50 | struct SaveConfigBlockEntry { | 46 | struct SaveConfigBlockEntry { |
| 51 | u32 block_id; ///< The id of the current block | 47 | u32 block_id; ///< The id of the current block |
| 52 | u32 offset_or_data; ///< This is the absolute offset to the block data if the size is greater than 4 bytes, otherwise it contains the data itself | 48 | u32 offset_or_data; ///< This is the absolute offset to the block data if the size is greater |
| 49 | /// than 4 bytes, otherwise it contains the data itself | ||
| 53 | u16 size; ///< The size of the block | 50 | u16 size; ///< The size of the block |
| 54 | u16 flags; ///< The flags of the block, possibly used for access control | 51 | u16 flags; ///< The flags of the block, possibly used for access control |
| 55 | }; | 52 | }; |
| @@ -244,7 +241,8 @@ ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output); | |||
| 244 | ResultCode SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input); | 241 | ResultCode SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input); |
| 245 | 242 | ||
| 246 | /** | 243 | /** |
| 247 | * Creates a block with the specified id and writes the input data to the cfg savegame buffer in memory. | 244 | * Creates a block with the specified id and writes the input data to the cfg savegame buffer in |
| 245 | * memory. | ||
| 248 | * The config savegame file in the filesystem is not updated. | 246 | * The config savegame file in the filesystem is not updated. |
| 249 | * @param block_id The id of the block we want to create | 247 | * @param block_id The id of the block we want to create |
| 250 | * @param size The size of the block we want to create | 248 | * @param size The size of the block we want to create |
diff --git a/src/core/hle/service/cfg/cfg_i.cpp b/src/core/hle/service/cfg/cfg_i.cpp index 8b0db785f..2ff52c8b8 100644 --- a/src/core/hle/service/cfg/cfg_i.cpp +++ b/src/core/hle/service/cfg/cfg_i.cpp | |||
| @@ -10,49 +10,49 @@ namespace CFG { | |||
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = { |
| 12 | // cfg common | 12 | // cfg common |
| 13 | {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"}, | 13 | {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"}, |
| 14 | {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"}, | 14 | {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"}, |
| 15 | {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"}, | 15 | {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"}, |
| 16 | {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"}, | 16 | {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"}, |
| 17 | {0x00050000, GetSystemModel, "GetSystemModel"}, | 17 | {0x00050000, GetSystemModel, "GetSystemModel"}, |
| 18 | {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"}, | 18 | {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"}, |
| 19 | {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, | 19 | {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, |
| 20 | {0x00080080, nullptr, "GoThroughTable"}, | 20 | {0x00080080, nullptr, "GoThroughTable"}, |
| 21 | {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, | 21 | {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, |
| 22 | {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, | 22 | {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, |
| 23 | // cfg:i | 23 | // cfg:i |
| 24 | {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, | 24 | {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, |
| 25 | {0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, | 25 | {0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, |
| 26 | {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, | 26 | {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, |
| 27 | {0x04040042, nullptr, "GetLocalFriendCodeSeedData"}, | 27 | {0x04040042, nullptr, "GetLocalFriendCodeSeedData"}, |
| 28 | {0x04050000, nullptr, "GetLocalFriendCodeSeed"}, | 28 | {0x04050000, nullptr, "GetLocalFriendCodeSeed"}, |
| 29 | {0x04060000, SecureInfoGetRegion, "SecureInfoGetRegion"}, | 29 | {0x04060000, SecureInfoGetRegion, "SecureInfoGetRegion"}, |
| 30 | {0x04070000, nullptr, "SecureInfoGetByte101"}, | 30 | {0x04070000, nullptr, "SecureInfoGetByte101"}, |
| 31 | {0x04080042, nullptr, "SecureInfoGetSerialNo"}, | 31 | {0x04080042, nullptr, "SecureInfoGetSerialNo"}, |
| 32 | {0x04090000, nullptr, "UpdateConfigBlk00040003"}, | 32 | {0x04090000, nullptr, "UpdateConfigBlk00040003"}, |
| 33 | {0x08010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, | 33 | {0x08010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, |
| 34 | {0x08020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, | 34 | {0x08020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, |
| 35 | {0x08030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, | 35 | {0x08030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, |
| 36 | {0x080400C2, nullptr, "CreateConfigInfoBlk"}, | 36 | {0x080400C2, nullptr, "CreateConfigInfoBlk"}, |
| 37 | {0x08050000, nullptr, "DeleteConfigNANDSavefile"}, | 37 | {0x08050000, nullptr, "DeleteConfigNANDSavefile"}, |
| 38 | {0x08060000, FormatConfig, "FormatConfig"}, | 38 | {0x08060000, FormatConfig, "FormatConfig"}, |
| 39 | {0x08080000, nullptr, "UpdateConfigBlk1"}, | 39 | {0x08080000, nullptr, "UpdateConfigBlk1"}, |
| 40 | {0x08090000, nullptr, "UpdateConfigBlk2"}, | 40 | {0x08090000, nullptr, "UpdateConfigBlk2"}, |
| 41 | {0x080A0000, nullptr, "UpdateConfigBlk3"}, | 41 | {0x080A0000, nullptr, "UpdateConfigBlk3"}, |
| 42 | {0x080B0082, nullptr, "SetGetLocalFriendCodeSeedData"}, | 42 | {0x080B0082, nullptr, "SetGetLocalFriendCodeSeedData"}, |
| 43 | {0x080C0042, nullptr, "SetLocalFriendCodeSeedSignature"}, | 43 | {0x080C0042, nullptr, "SetLocalFriendCodeSeedSignature"}, |
| 44 | {0x080D0000, nullptr, "DeleteCreateNANDLocalFriendCodeSeed"}, | 44 | {0x080D0000, nullptr, "DeleteCreateNANDLocalFriendCodeSeed"}, |
| 45 | {0x080E0000, nullptr, "VerifySigLocalFriendCodeSeed"}, | 45 | {0x080E0000, nullptr, "VerifySigLocalFriendCodeSeed"}, |
| 46 | {0x080F0042, nullptr, "GetLocalFriendCodeSeedData"}, | 46 | {0x080F0042, nullptr, "GetLocalFriendCodeSeedData"}, |
| 47 | {0x08100000, nullptr, "GetLocalFriendCodeSeed"}, | 47 | {0x08100000, nullptr, "GetLocalFriendCodeSeed"}, |
| 48 | {0x08110084, nullptr, "SetSecureInfo"}, | 48 | {0x08110084, nullptr, "SetSecureInfo"}, |
| 49 | {0x08120000, nullptr, "DeleteCreateNANDSecureInfo"}, | 49 | {0x08120000, nullptr, "DeleteCreateNANDSecureInfo"}, |
| 50 | {0x08130000, nullptr, "VerifySigSecureInfo"}, | 50 | {0x08130000, nullptr, "VerifySigSecureInfo"}, |
| 51 | {0x08140042, nullptr, "SecureInfoGetData"}, | 51 | {0x08140042, nullptr, "SecureInfoGetData"}, |
| 52 | {0x08150042, nullptr, "SecureInfoGetSignature"}, | 52 | {0x08150042, nullptr, "SecureInfoGetSignature"}, |
| 53 | {0x08160000, SecureInfoGetRegion, "SecureInfoGetRegion"}, | 53 | {0x08160000, SecureInfoGetRegion, "SecureInfoGetRegion"}, |
| 54 | {0x08170000, nullptr, "SecureInfoGetByte101"}, | 54 | {0x08170000, nullptr, "SecureInfoGetByte101"}, |
| 55 | {0x08180042, nullptr, "SecureInfoGetSerialNo"}, | 55 | {0x08180042, nullptr, "SecureInfoGetSerialNo"}, |
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | CFG_I_Interface::CFG_I_Interface() { | 58 | CFG_I_Interface::CFG_I_Interface() { |
diff --git a/src/core/hle/service/cfg/cfg_s.cpp b/src/core/hle/service/cfg/cfg_s.cpp index 12b458783..eed26dec7 100644 --- a/src/core/hle/service/cfg/cfg_s.cpp +++ b/src/core/hle/service/cfg/cfg_s.cpp | |||
| @@ -10,26 +10,26 @@ namespace CFG { | |||
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = { |
| 12 | // cfg common | 12 | // cfg common |
| 13 | {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"}, | 13 | {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"}, |
| 14 | {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"}, | 14 | {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"}, |
| 15 | {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"}, | 15 | {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"}, |
| 16 | {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"}, | 16 | {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"}, |
| 17 | {0x00050000, GetSystemModel, "GetSystemModel"}, | 17 | {0x00050000, GetSystemModel, "GetSystemModel"}, |
| 18 | {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"}, | 18 | {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"}, |
| 19 | {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, | 19 | {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, |
| 20 | {0x00080080, nullptr, "GoThroughTable"}, | 20 | {0x00080080, nullptr, "GoThroughTable"}, |
| 21 | {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, | 21 | {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, |
| 22 | {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, | 22 | {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, |
| 23 | // cfg:s | 23 | // cfg:s |
| 24 | {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, | 24 | {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, |
| 25 | {0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, | 25 | {0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, |
| 26 | {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, | 26 | {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, |
| 27 | {0x04040042, nullptr, "GetLocalFriendCodeSeedData"}, | 27 | {0x04040042, nullptr, "GetLocalFriendCodeSeedData"}, |
| 28 | {0x04050000, nullptr, "GetLocalFriendCodeSeed"}, | 28 | {0x04050000, nullptr, "GetLocalFriendCodeSeed"}, |
| 29 | {0x04060000, nullptr, "SecureInfoGetRegion"}, | 29 | {0x04060000, nullptr, "SecureInfoGetRegion"}, |
| 30 | {0x04070000, nullptr, "SecureInfoGetByte101"}, | 30 | {0x04070000, nullptr, "SecureInfoGetByte101"}, |
| 31 | {0x04080042, nullptr, "SecureInfoGetSerialNo"}, | 31 | {0x04080042, nullptr, "SecureInfoGetSerialNo"}, |
| 32 | {0x04090000, nullptr, "UpdateConfigBlk00040003"}, | 32 | {0x04090000, nullptr, "UpdateConfigBlk00040003"}, |
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | CFG_S_Interface::CFG_S_Interface() { | 35 | CFG_S_Interface::CFG_S_Interface() { |
diff --git a/src/core/hle/service/cfg/cfg_u.cpp b/src/core/hle/service/cfg/cfg_u.cpp index 606f7b2eb..f28217134 100644 --- a/src/core/hle/service/cfg/cfg_u.cpp +++ b/src/core/hle/service/cfg/cfg_u.cpp | |||
| @@ -10,16 +10,16 @@ namespace CFG { | |||
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = { |
| 12 | // cfg common | 12 | // cfg common |
| 13 | {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"}, | 13 | {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"}, |
| 14 | {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"}, | 14 | {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"}, |
| 15 | {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"}, | 15 | {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"}, |
| 16 | {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"}, | 16 | {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"}, |
| 17 | {0x00050000, GetSystemModel, "GetSystemModel"}, | 17 | {0x00050000, GetSystemModel, "GetSystemModel"}, |
| 18 | {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"}, | 18 | {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"}, |
| 19 | {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, | 19 | {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, |
| 20 | {0x00080080, nullptr, "GoThroughTable"}, | 20 | {0x00080080, nullptr, "GoThroughTable"}, |
| 21 | {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, | 21 | {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, |
| 22 | {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, | 22 | {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, |
| 23 | }; | 23 | }; |
| 24 | 24 | ||
| 25 | CFG_U_Interface::CFG_U_Interface() { | 25 | CFG_U_Interface::CFG_U_Interface() { |
diff --git a/src/core/hle/service/csnd_snd.cpp b/src/core/hle/service/csnd_snd.cpp index 913c8dc09..e777ea9d6 100644 --- a/src/core/hle/service/csnd_snd.cpp +++ b/src/core/hle/service/csnd_snd.cpp | |||
| @@ -2,12 +2,12 @@ | |||
| 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/hle/service/csnd_snd.h" | ||
| 5 | #include <cstring> | 6 | #include <cstring> |
| 6 | #include "common/alignment.h" | 7 | #include "common/alignment.h" |
| 7 | #include "core/hle/hle.h" | 8 | #include "core/hle/hle.h" |
| 8 | #include "core/hle/kernel/mutex.h" | 9 | #include "core/hle/kernel/mutex.h" |
| 9 | #include "core/hle/kernel/shared_memory.h" | 10 | #include "core/hle/kernel/shared_memory.h" |
| 10 | #include "core/hle/service/csnd_snd.h" | ||
| 11 | 11 | ||
| 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 13 | // Namespace CSND_SND | 13 | // Namespace CSND_SND |
| @@ -15,18 +15,18 @@ | |||
| 15 | namespace CSND_SND { | 15 | namespace CSND_SND { |
| 16 | 16 | ||
| 17 | const Interface::FunctionInfo FunctionTable[] = { | 17 | const Interface::FunctionInfo FunctionTable[] = { |
| 18 | {0x00010140, Initialize, "Initialize"}, | 18 | {0x00010140, Initialize, "Initialize"}, |
| 19 | {0x00020000, Shutdown, "Shutdown"}, | 19 | {0x00020000, Shutdown, "Shutdown"}, |
| 20 | {0x00030040, ExecuteType0Commands, "ExecuteType0Commands"}, | 20 | {0x00030040, ExecuteType0Commands, "ExecuteType0Commands"}, |
| 21 | {0x00040080, nullptr, "ExecuteType1Commands"}, | 21 | {0x00040080, nullptr, "ExecuteType1Commands"}, |
| 22 | {0x00050000, AcquireSoundChannels, "AcquireSoundChannels"}, | 22 | {0x00050000, AcquireSoundChannels, "AcquireSoundChannels"}, |
| 23 | {0x00060000, nullptr, "ReleaseSoundChannels"}, | 23 | {0x00060000, nullptr, "ReleaseSoundChannels"}, |
| 24 | {0x00070000, nullptr, "AcquireCaptureDevice"}, | 24 | {0x00070000, nullptr, "AcquireCaptureDevice"}, |
| 25 | {0x00080040, nullptr, "ReleaseCaptureDevice"}, | 25 | {0x00080040, nullptr, "ReleaseCaptureDevice"}, |
| 26 | {0x00090082, nullptr, "FlushDataCache"}, | 26 | {0x00090082, nullptr, "FlushDataCache"}, |
| 27 | {0x000A0082, nullptr, "StoreDataCache"}, | 27 | {0x000A0082, nullptr, "StoreDataCache"}, |
| 28 | {0x000B0082, nullptr, "InvalidateDataCache"}, | 28 | {0x000B0082, nullptr, "InvalidateDataCache"}, |
| 29 | {0x000C0000, nullptr, "Reset"}, | 29 | {0x000C0000, nullptr, "Reset"}, |
| 30 | }; | 30 | }; |
| 31 | 31 | ||
| 32 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 32 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -44,9 +44,9 @@ void Initialize(Service::Interface* self) { | |||
| 44 | 44 | ||
| 45 | u32 size = Common::AlignUp(cmd_buff[1], Memory::PAGE_SIZE); | 45 | u32 size = Common::AlignUp(cmd_buff[1], Memory::PAGE_SIZE); |
| 46 | using Kernel::MemoryPermission; | 46 | using Kernel::MemoryPermission; |
| 47 | shared_memory = Kernel::SharedMemory::Create(nullptr, size, | 47 | shared_memory = Kernel::SharedMemory::Create(nullptr, size, MemoryPermission::ReadWrite, |
| 48 | MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, | 48 | MemoryPermission::ReadWrite, 0, |
| 49 | 0, Kernel::MemoryRegion::BASE, "CSND:SharedMemory"); | 49 | Kernel::MemoryRegion::BASE, "CSND:SharedMemory"); |
| 50 | 50 | ||
| 51 | mutex = Kernel::Mutex::Create(false); | 51 | mutex = Kernel::Mutex::Create(false); |
| 52 | 52 | ||
| @@ -58,7 +58,7 @@ void Initialize(Service::Interface* self) { | |||
| 58 | 58 | ||
| 59 | void ExecuteType0Commands(Service::Interface* self) { | 59 | void ExecuteType0Commands(Service::Interface* self) { |
| 60 | u32* const cmd_buff = Kernel::GetCommandBuffer(); | 60 | u32* const cmd_buff = Kernel::GetCommandBuffer(); |
| 61 | u8* const ptr = shared_memory->GetPointer(cmd_buff[1]); | 61 | u8* const ptr = shared_memory->GetPointer(cmd_buff[1]); |
| 62 | 62 | ||
| 63 | if (shared_memory != nullptr && ptr != nullptr) { | 63 | if (shared_memory != nullptr && ptr != nullptr) { |
| 64 | Type0Command command; | 64 | Type0Command command; |
diff --git a/src/core/hle/service/csnd_snd.h b/src/core/hle/service/csnd_snd.h index e861f3327..a146d116b 100644 --- a/src/core/hle/service/csnd_snd.h +++ b/src/core/hle/service/csnd_snd.h | |||
| @@ -25,7 +25,7 @@ struct Type0Command { | |||
| 25 | u32 command_id; | 25 | u32 command_id; |
| 26 | u32 finished; | 26 | u32 finished; |
| 27 | u32 flags; | 27 | u32 flags; |
| 28 | u8 parameters[20]; | 28 | u8 parameters[20]; |
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | void Initialize(Service::Interface* self); | 31 | void Initialize(Service::Interface* self); |
diff --git a/src/core/hle/service/dlp/dlp.cpp b/src/core/hle/service/dlp/dlp.cpp index 7c8db794b..fd124e819 100644 --- a/src/core/hle/service/dlp/dlp.cpp +++ b/src/core/hle/service/dlp/dlp.cpp | |||
| @@ -2,11 +2,11 @@ | |||
| 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/hle/service/service.h" | ||
| 6 | #include "core/hle/service/dlp/dlp.h" | 5 | #include "core/hle/service/dlp/dlp.h" |
| 7 | #include "core/hle/service/dlp/dlp_clnt.h" | 6 | #include "core/hle/service/dlp/dlp_clnt.h" |
| 8 | #include "core/hle/service/dlp/dlp_fkcl.h" | 7 | #include "core/hle/service/dlp/dlp_fkcl.h" |
| 9 | #include "core/hle/service/dlp/dlp_srvr.h" | 8 | #include "core/hle/service/dlp/dlp_srvr.h" |
| 9 | #include "core/hle/service/service.h" | ||
| 10 | 10 | ||
| 11 | namespace Service { | 11 | namespace Service { |
| 12 | namespace DLP { | 12 | namespace DLP { |
diff --git a/src/core/hle/service/dlp/dlp_clnt.cpp b/src/core/hle/service/dlp/dlp_clnt.cpp index 0b31d47df..56f934b3f 100644 --- a/src/core/hle/service/dlp/dlp_clnt.cpp +++ b/src/core/hle/service/dlp/dlp_clnt.cpp | |||
| @@ -8,8 +8,7 @@ namespace Service { | |||
| 8 | namespace DLP { | 8 | namespace DLP { |
| 9 | 9 | ||
| 10 | const Interface::FunctionInfo FunctionTable[] = { | 10 | const Interface::FunctionInfo FunctionTable[] = { |
| 11 | {0x000100C3, nullptr, "Initialize"}, | 11 | {0x000100C3, nullptr, "Initialize"}, {0x00110000, nullptr, "GetWirelessRebootPassphrase"}, |
| 12 | {0x00110000, nullptr, "GetWirelessRebootPassphrase"}, | ||
| 13 | }; | 12 | }; |
| 14 | 13 | ||
| 15 | DLP_CLNT_Interface::DLP_CLNT_Interface() { | 14 | DLP_CLNT_Interface::DLP_CLNT_Interface() { |
diff --git a/src/core/hle/service/dlp/dlp_fkcl.cpp b/src/core/hle/service/dlp/dlp_fkcl.cpp index a845260e5..29b9d52e0 100644 --- a/src/core/hle/service/dlp/dlp_fkcl.cpp +++ b/src/core/hle/service/dlp/dlp_fkcl.cpp | |||
| @@ -8,8 +8,7 @@ namespace Service { | |||
| 8 | namespace DLP { | 8 | namespace DLP { |
| 9 | 9 | ||
| 10 | const Interface::FunctionInfo FunctionTable[] = { | 10 | const Interface::FunctionInfo FunctionTable[] = { |
| 11 | {0x00010083, nullptr, "Initialize"}, | 11 | {0x00010083, nullptr, "Initialize"}, {0x000F0000, nullptr, "GetWirelessRebootPassphrase"}, |
| 12 | {0x000F0000, nullptr, "GetWirelessRebootPassphrase"}, | ||
| 13 | }; | 12 | }; |
| 14 | 13 | ||
| 15 | DLP_FKCL_Interface::DLP_FKCL_Interface() { | 14 | DLP_FKCL_Interface::DLP_FKCL_Interface() { |
diff --git a/src/core/hle/service/dlp/dlp_srvr.cpp b/src/core/hle/service/dlp/dlp_srvr.cpp index da9b30f56..113f6a79f 100644 --- a/src/core/hle/service/dlp/dlp_srvr.cpp +++ b/src/core/hle/service/dlp/dlp_srvr.cpp | |||
| @@ -2,10 +2,10 @@ | |||
| 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/hle/service/dlp/dlp_srvr.h" | ||
| 5 | #include "common/common_types.h" | 6 | #include "common/common_types.h" |
| 6 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 7 | #include "core/hle/result.h" | 8 | #include "core/hle/result.h" |
| 8 | #include "core/hle/service/dlp/dlp_srvr.h" | ||
| 9 | 9 | ||
| 10 | namespace Service { | 10 | namespace Service { |
| 11 | namespace DLP { | 11 | namespace DLP { |
| @@ -20,10 +20,10 @@ static void unk_0x000E0040(Interface* self) { | |||
| 20 | } | 20 | } |
| 21 | 21 | ||
| 22 | const Interface::FunctionInfo FunctionTable[] = { | 22 | const Interface::FunctionInfo FunctionTable[] = { |
| 23 | {0x00010183, nullptr, "Initialize"}, | 23 | {0x00010183, nullptr, "Initialize"}, |
| 24 | {0x00020000, nullptr, "Finalize"}, | 24 | {0x00020000, nullptr, "Finalize"}, |
| 25 | {0x000800C0, nullptr, "SendWirelessRebootPassphrase"}, | 25 | {0x000800C0, nullptr, "SendWirelessRebootPassphrase"}, |
| 26 | {0x000E0040, unk_0x000E0040, "unk_0x000E0040"}, | 26 | {0x000E0040, unk_0x000E0040, "unk_0x000E0040"}, |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | DLP_SRVR_Interface::DLP_SRVR_Interface() { | 29 | DLP_SRVR_Interface::DLP_SRVR_Interface() { |
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index c8aadd9db..70e92c30c 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp | |||
| @@ -23,9 +23,7 @@ namespace DSP_DSP { | |||
| 23 | static Kernel::SharedPtr<Kernel::Event> semaphore_event; | 23 | static Kernel::SharedPtr<Kernel::Event> semaphore_event; |
| 24 | 24 | ||
| 25 | /// There are three types of interrupts | 25 | /// There are three types of interrupts |
| 26 | enum class InterruptType { | 26 | enum class InterruptType { Zero, One, Pipe }; |
| 27 | Zero, One, Pipe | ||
| 28 | }; | ||
| 29 | constexpr size_t NUM_INTERRUPT_TYPE = 3; | 27 | constexpr size_t NUM_INTERRUPT_TYPE = 3; |
| 30 | 28 | ||
| 31 | class InterruptEvents final { | 29 | class InterruptEvents final { |
| @@ -57,9 +55,8 @@ public: | |||
| 57 | // Actual service implementation only has 6 'slots' for interrupts. | 55 | // Actual service implementation only has 6 'slots' for interrupts. |
| 58 | constexpr size_t max_number_of_interrupt_events = 6; | 56 | constexpr size_t max_number_of_interrupt_events = 6; |
| 59 | 57 | ||
| 60 | size_t number = std::count_if(pipe.begin(), pipe.end(), [](const auto& evt) { | 58 | size_t number = |
| 61 | return evt != nullptr; | 59 | std::count_if(pipe.begin(), pipe.end(), [](const auto& evt) { return evt != nullptr; }); |
| 62 | }); | ||
| 63 | 60 | ||
| 64 | if (zero != nullptr) | 61 | if (zero != nullptr) |
| 65 | number++; | 62 | number++; |
| @@ -105,7 +102,8 @@ static void ConvertProcessAddressFromDspDram(Service::Interface* self) { | |||
| 105 | cmd_buff[0] = IPC::MakeHeader(0xC, 2, 0); | 102 | cmd_buff[0] = IPC::MakeHeader(0xC, 2, 0); |
| 106 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 103 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 107 | 104 | ||
| 108 | // TODO(merry): There is a per-region offset missing in this calculation (that seems to be always zero). | 105 | // TODO(merry): There is a per-region offset missing in this calculation (that seems to be |
| 106 | // always zero). | ||
| 109 | cmd_buff[2] = (addr << 1) + (Memory::DSP_RAM_VADDR + 0x40000); | 107 | cmd_buff[2] = (addr << 1) + (Memory::DSP_RAM_VADDR + 0x40000); |
| 110 | 108 | ||
| 111 | LOG_DEBUG(Service_DSP, "addr=0x%08X", addr); | 109 | LOG_DEBUG(Service_DSP, "addr=0x%08X", addr); |
| @@ -126,15 +124,15 @@ static void ConvertProcessAddressFromDspDram(Service::Interface* self) { | |||
| 126 | static void LoadComponent(Service::Interface* self) { | 124 | static void LoadComponent(Service::Interface* self) { |
| 127 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 125 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 128 | 126 | ||
| 129 | u32 size = cmd_buff[1]; | 127 | u32 size = cmd_buff[1]; |
| 130 | u32 prog_mask = cmd_buff[2]; | 128 | u32 prog_mask = cmd_buff[2]; |
| 131 | u32 data_mask = cmd_buff[3]; | 129 | u32 data_mask = cmd_buff[3]; |
| 132 | u32 desc = cmd_buff[4]; | 130 | u32 desc = cmd_buff[4]; |
| 133 | u32 buffer = cmd_buff[5]; | 131 | u32 buffer = cmd_buff[5]; |
| 134 | 132 | ||
| 135 | cmd_buff[0] = IPC::MakeHeader(0x11, 2, 2); | 133 | cmd_buff[0] = IPC::MakeHeader(0x11, 2, 2); |
| 136 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 134 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 137 | cmd_buff[2] = 1; // Pretend that we actually loaded the DSP firmware | 135 | cmd_buff[2] = 1; // Pretend that we actually loaded the DSP firmware |
| 138 | cmd_buff[3] = desc; | 136 | cmd_buff[3] = desc; |
| 139 | cmd_buff[4] = buffer; | 137 | cmd_buff[4] = buffer; |
| 140 | 138 | ||
| @@ -145,12 +143,15 @@ static void LoadComponent(Service::Interface* self) { | |||
| 145 | std::vector<u8> component_data(size); | 143 | std::vector<u8> component_data(size); |
| 146 | Memory::ReadBlock(buffer, component_data.data(), component_data.size()); | 144 | Memory::ReadBlock(buffer, component_data.data(), component_data.size()); |
| 147 | 145 | ||
| 148 | LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64, Common::ComputeHash64(component_data.data(), component_data.size())); | 146 | LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64, |
| 147 | Common::ComputeHash64(component_data.data(), component_data.size())); | ||
| 149 | // Some versions of the firmware have the location of DSP structures listed here. | 148 | // Some versions of the firmware have the location of DSP structures listed here. |
| 150 | ASSERT(size > 0x37C); | 149 | ASSERT(size > 0x37C); |
| 151 | LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64, Common::ComputeHash64(component_data.data() + 0x340, 60)); | 150 | LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64, |
| 151 | Common::ComputeHash64(component_data.data() + 0x340, 60)); | ||
| 152 | 152 | ||
| 153 | LOG_WARNING(Service_DSP, "(STUBBED) called size=0x%X, prog_mask=0x%08X, data_mask=0x%08X, buffer=0x%08X", | 153 | LOG_WARNING(Service_DSP, |
| 154 | "(STUBBED) called size=0x%X, prog_mask=0x%08X, data_mask=0x%08X, buffer=0x%08X", | ||
| 154 | size, prog_mask, data_mask, buffer); | 155 | size, prog_mask, data_mask, buffer); |
| 155 | } | 156 | } |
| 156 | 157 | ||
| @@ -187,13 +188,14 @@ static void GetSemaphoreEventHandle(Service::Interface* self) { | |||
| 187 | static void FlushDataCache(Service::Interface* self) { | 188 | static void FlushDataCache(Service::Interface* self) { |
| 188 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 189 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 189 | u32 address = cmd_buff[1]; | 190 | u32 address = cmd_buff[1]; |
| 190 | u32 size = cmd_buff[2]; | 191 | u32 size = cmd_buff[2]; |
| 191 | u32 process = cmd_buff[4]; | 192 | u32 process = cmd_buff[4]; |
| 192 | 193 | ||
| 193 | cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0); | 194 | cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0); |
| 194 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 195 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 195 | 196 | ||
| 196 | LOG_TRACE(Service_DSP, "called address=0x%08X, size=0x%X, process=0x%08X", address, size, process); | 197 | LOG_TRACE(Service_DSP, "called address=0x%08X, size=0x%X, process=0x%08X", address, size, |
| 198 | process); | ||
| 197 | } | 199 | } |
| 198 | 200 | ||
| 199 | /** | 201 | /** |
| @@ -224,23 +226,29 @@ static void RegisterInterruptEvents(Service::Interface* self) { | |||
| 224 | auto evt = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]); | 226 | auto evt = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]); |
| 225 | 227 | ||
| 226 | if (!evt) { | 228 | if (!evt) { |
| 227 | LOG_INFO(Service_DSP, "Invalid event handle! type=%u, pipe=%u, event_handle=0x%08X", type_index, pipe_index, event_handle); | 229 | LOG_INFO(Service_DSP, "Invalid event handle! type=%u, pipe=%u, event_handle=0x%08X", |
| 230 | type_index, pipe_index, event_handle); | ||
| 228 | ASSERT(false); // TODO: This should really be handled at an IPC translation layer. | 231 | ASSERT(false); // TODO: This should really be handled at an IPC translation layer. |
| 229 | } | 232 | } |
| 230 | 233 | ||
| 231 | if (interrupt_events.HasTooManyEventsRegistered()) { | 234 | if (interrupt_events.HasTooManyEventsRegistered()) { |
| 232 | LOG_INFO(Service_DSP, "Ran out of space to register interrupts (Attempted to register type=%u, pipe=%u, event_handle=0x%08X)", | 235 | LOG_INFO(Service_DSP, "Ran out of space to register interrupts (Attempted to register " |
| 236 | "type=%u, pipe=%u, event_handle=0x%08X)", | ||
| 233 | type_index, pipe_index, event_handle); | 237 | type_index, pipe_index, event_handle); |
| 234 | cmd_buff[1] = ResultCode(ErrorDescription::InvalidResultValue, ErrorModule::DSP, ErrorSummary::OutOfResource, ErrorLevel::Status).raw; | 238 | cmd_buff[1] = ResultCode(ErrorDescription::InvalidResultValue, ErrorModule::DSP, |
| 239 | ErrorSummary::OutOfResource, ErrorLevel::Status) | ||
| 240 | .raw; | ||
| 235 | return; | 241 | return; |
| 236 | } | 242 | } |
| 237 | 243 | ||
| 238 | interrupt_events.Get(type, pipe) = evt; | 244 | interrupt_events.Get(type, pipe) = evt; |
| 239 | LOG_INFO(Service_DSP, "Registered type=%u, pipe=%u, event_handle=0x%08X", type_index, pipe_index, event_handle); | 245 | LOG_INFO(Service_DSP, "Registered type=%u, pipe=%u, event_handle=0x%08X", type_index, |
| 246 | pipe_index, event_handle); | ||
| 240 | cmd_buff[1] = RESULT_SUCCESS.raw; | 247 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 241 | } else { | 248 | } else { |
| 242 | interrupt_events.Get(type, pipe) = nullptr; | 249 | interrupt_events.Get(type, pipe) = nullptr; |
| 243 | LOG_INFO(Service_DSP, "Unregistered interrupt=%u, channel=%u, event_handle=0x%08X", type_index, pipe_index, event_handle); | 250 | LOG_INFO(Service_DSP, "Unregistered interrupt=%u, channel=%u, event_handle=0x%08X", |
| 251 | type_index, pipe_index, event_handle); | ||
| 244 | cmd_buff[1] = RESULT_SUCCESS.raw; | 252 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 245 | } | 253 | } |
| 246 | } | 254 | } |
| @@ -282,13 +290,18 @@ static void WriteProcessPipe(Service::Interface* self) { | |||
| 282 | DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); | 290 | DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); |
| 283 | 291 | ||
| 284 | if (IPC::StaticBufferDesc(size, 1) != cmd_buff[3]) { | 292 | if (IPC::StaticBufferDesc(size, 1) != cmd_buff[3]) { |
| 285 | LOG_ERROR(Service_DSP, "IPC static buffer descriptor failed validation (0x%X). pipe=%u, size=0x%X, buffer=0x%08X", cmd_buff[3], pipe_index, size, buffer); | 293 | LOG_ERROR(Service_DSP, "IPC static buffer descriptor failed validation (0x%X). pipe=%u, " |
| 294 | "size=0x%X, buffer=0x%08X", | ||
| 295 | cmd_buff[3], pipe_index, size, buffer); | ||
| 286 | cmd_buff[0] = IPC::MakeHeader(0, 1, 0); | 296 | cmd_buff[0] = IPC::MakeHeader(0, 1, 0); |
| 287 | cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; | 297 | cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, |
| 298 | ErrorSummary::WrongArgument, ErrorLevel::Permanent) | ||
| 299 | .raw; | ||
| 288 | return; | 300 | return; |
| 289 | } | 301 | } |
| 290 | 302 | ||
| 291 | ASSERT_MSG(Memory::IsValidVirtualAddress(buffer), "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer); | 303 | ASSERT_MSG(Memory::IsValidVirtualAddress(buffer), |
| 304 | "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer); | ||
| 292 | 305 | ||
| 293 | std::vector<u8> message(size); | 306 | std::vector<u8> message(size); |
| 294 | for (u32 i = 0; i < size; i++) { | 307 | for (u32 i = 0; i < size; i++) { |
| @@ -327,7 +340,9 @@ static void ReadPipeIfPossible(Service::Interface* self) { | |||
| 327 | 340 | ||
| 328 | DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); | 341 | DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); |
| 329 | 342 | ||
| 330 | ASSERT_MSG(Memory::IsValidVirtualAddress(addr), "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr); | 343 | ASSERT_MSG(Memory::IsValidVirtualAddress(addr), |
| 344 | "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, | ||
| 345 | size, addr); | ||
| 331 | 346 | ||
| 332 | cmd_buff[0] = IPC::MakeHeader(0x10, 1, 2); | 347 | cmd_buff[0] = IPC::MakeHeader(0x10, 1, 2); |
| 333 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 348 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| @@ -343,7 +358,9 @@ static void ReadPipeIfPossible(Service::Interface* self) { | |||
| 343 | cmd_buff[3] = IPC::StaticBufferDesc(size, 0); | 358 | cmd_buff[3] = IPC::StaticBufferDesc(size, 0); |
| 344 | cmd_buff[4] = addr; | 359 | cmd_buff[4] = addr; |
| 345 | 360 | ||
| 346 | LOG_DEBUG(Service_DSP, "pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X", pipe_index, unknown, size, addr, cmd_buff[2]); | 361 | LOG_DEBUG(Service_DSP, |
| 362 | "pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X", | ||
| 363 | pipe_index, unknown, size, addr, cmd_buff[2]); | ||
| 347 | } | 364 | } |
| 348 | 365 | ||
| 349 | /** | 366 | /** |
| @@ -367,7 +384,9 @@ static void ReadPipe(Service::Interface* self) { | |||
| 367 | 384 | ||
| 368 | DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); | 385 | DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); |
| 369 | 386 | ||
| 370 | ASSERT_MSG(Memory::IsValidVirtualAddress(addr), "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr); | 387 | ASSERT_MSG(Memory::IsValidVirtualAddress(addr), |
| 388 | "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, | ||
| 389 | size, addr); | ||
| 371 | 390 | ||
| 372 | if (DSP::HLE::GetPipeReadableSize(pipe) >= size) { | 391 | if (DSP::HLE::GetPipeReadableSize(pipe) >= size) { |
| 373 | std::vector<u8> response = DSP::HLE::PipeRead(pipe, size); | 392 | std::vector<u8> response = DSP::HLE::PipeRead(pipe, size); |
| @@ -384,7 +403,9 @@ static void ReadPipe(Service::Interface* self) { | |||
| 384 | UNREACHABLE(); | 403 | UNREACHABLE(); |
| 385 | } | 404 | } |
| 386 | 405 | ||
| 387 | LOG_DEBUG(Service_DSP, "pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X", pipe_index, unknown, size, addr, cmd_buff[2]); | 406 | LOG_DEBUG(Service_DSP, |
| 407 | "pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X", | ||
| 408 | pipe_index, unknown, size, addr, cmd_buff[2]); | ||
| 388 | } | 409 | } |
| 389 | 410 | ||
| 390 | /** | 411 | /** |
| @@ -408,7 +429,8 @@ static void GetPipeReadableSize(Service::Interface* self) { | |||
| 408 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 429 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 409 | cmd_buff[2] = static_cast<u32>(DSP::HLE::GetPipeReadableSize(pipe)); | 430 | cmd_buff[2] = static_cast<u32>(DSP::HLE::GetPipeReadableSize(pipe)); |
| 410 | 431 | ||
| 411 | LOG_DEBUG(Service_DSP, "pipe=%u, unknown=0x%08X, return cmd_buff[2]=0x%08X", pipe_index, unknown, cmd_buff[2]); | 432 | LOG_DEBUG(Service_DSP, "pipe=%u, unknown=0x%08X, return cmd_buff[2]=0x%08X", pipe_index, |
| 433 | unknown, cmd_buff[2]); | ||
| 412 | } | 434 | } |
| 413 | 435 | ||
| 414 | /** | 436 | /** |
| @@ -443,7 +465,7 @@ static void GetHeadphoneStatus(Service::Interface* self) { | |||
| 443 | 465 | ||
| 444 | cmd_buff[0] = IPC::MakeHeader(0x1F, 2, 0); | 466 | cmd_buff[0] = IPC::MakeHeader(0x1F, 2, 0); |
| 445 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 467 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 446 | cmd_buff[2] = 0; // Not using headphones | 468 | cmd_buff[2] = 0; // Not using headphones |
| 447 | 469 | ||
| 448 | LOG_DEBUG(Service_DSP, "called"); | 470 | LOG_DEBUG(Service_DSP, "called"); |
| 449 | } | 471 | } |
| @@ -466,7 +488,8 @@ static void RecvData(Service::Interface* self) { | |||
| 466 | 488 | ||
| 467 | ASSERT_MSG(register_number == 0, "Unknown register_number %u", register_number); | 489 | ASSERT_MSG(register_number == 0, "Unknown register_number %u", register_number); |
| 468 | 490 | ||
| 469 | // Application reads this after requesting DSP shutdown, to verify the DSP has indeed shutdown or slept. | 491 | // Application reads this after requesting DSP shutdown, to verify the DSP has indeed shutdown |
| 492 | // or slept. | ||
| 470 | 493 | ||
| 471 | cmd_buff[0] = IPC::MakeHeader(0x1, 2, 0); | 494 | cmd_buff[0] = IPC::MakeHeader(0x1, 2, 0); |
| 472 | cmd_buff[1] = RESULT_SUCCESS.raw; | 495 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| @@ -512,39 +535,39 @@ static void RecvDataIsReady(Service::Interface* self) { | |||
| 512 | } | 535 | } |
| 513 | 536 | ||
| 514 | const Interface::FunctionInfo FunctionTable[] = { | 537 | const Interface::FunctionInfo FunctionTable[] = { |
| 515 | {0x00010040, RecvData, "RecvData"}, | 538 | {0x00010040, RecvData, "RecvData"}, |
| 516 | {0x00020040, RecvDataIsReady, "RecvDataIsReady"}, | 539 | {0x00020040, RecvDataIsReady, "RecvDataIsReady"}, |
| 517 | {0x00030080, nullptr, "SendData"}, | 540 | {0x00030080, nullptr, "SendData"}, |
| 518 | {0x00040040, nullptr, "SendDataIsEmpty"}, | 541 | {0x00040040, nullptr, "SendDataIsEmpty"}, |
| 519 | {0x000500C2, nullptr, "SendFifoEx"}, | 542 | {0x000500C2, nullptr, "SendFifoEx"}, |
| 520 | {0x000600C0, nullptr, "RecvFifoEx"}, | 543 | {0x000600C0, nullptr, "RecvFifoEx"}, |
| 521 | {0x00070040, SetSemaphore, "SetSemaphore"}, | 544 | {0x00070040, SetSemaphore, "SetSemaphore"}, |
| 522 | {0x00080000, nullptr, "GetSemaphore"}, | 545 | {0x00080000, nullptr, "GetSemaphore"}, |
| 523 | {0x00090040, nullptr, "ClearSemaphore"}, | 546 | {0x00090040, nullptr, "ClearSemaphore"}, |
| 524 | {0x000A0040, nullptr, "MaskSemaphore"}, | 547 | {0x000A0040, nullptr, "MaskSemaphore"}, |
| 525 | {0x000B0000, nullptr, "CheckSemaphoreRequest"}, | 548 | {0x000B0000, nullptr, "CheckSemaphoreRequest"}, |
| 526 | {0x000C0040, ConvertProcessAddressFromDspDram, "ConvertProcessAddressFromDspDram"}, | 549 | {0x000C0040, ConvertProcessAddressFromDspDram, "ConvertProcessAddressFromDspDram"}, |
| 527 | {0x000D0082, WriteProcessPipe, "WriteProcessPipe"}, | 550 | {0x000D0082, WriteProcessPipe, "WriteProcessPipe"}, |
| 528 | {0x000E00C0, ReadPipe, "ReadPipe"}, | 551 | {0x000E00C0, ReadPipe, "ReadPipe"}, |
| 529 | {0x000F0080, GetPipeReadableSize, "GetPipeReadableSize"}, | 552 | {0x000F0080, GetPipeReadableSize, "GetPipeReadableSize"}, |
| 530 | {0x001000C0, ReadPipeIfPossible, "ReadPipeIfPossible"}, | 553 | {0x001000C0, ReadPipeIfPossible, "ReadPipeIfPossible"}, |
| 531 | {0x001100C2, LoadComponent, "LoadComponent"}, | 554 | {0x001100C2, LoadComponent, "LoadComponent"}, |
| 532 | {0x00120000, nullptr, "UnloadComponent"}, | 555 | {0x00120000, nullptr, "UnloadComponent"}, |
| 533 | {0x00130082, FlushDataCache, "FlushDataCache"}, | 556 | {0x00130082, FlushDataCache, "FlushDataCache"}, |
| 534 | {0x00140082, nullptr, "InvalidateDCache"}, | 557 | {0x00140082, nullptr, "InvalidateDCache"}, |
| 535 | {0x00150082, RegisterInterruptEvents, "RegisterInterruptEvents"}, | 558 | {0x00150082, RegisterInterruptEvents, "RegisterInterruptEvents"}, |
| 536 | {0x00160000, GetSemaphoreEventHandle, "GetSemaphoreEventHandle"}, | 559 | {0x00160000, GetSemaphoreEventHandle, "GetSemaphoreEventHandle"}, |
| 537 | {0x00170040, SetSemaphoreMask, "SetSemaphoreMask"}, | 560 | {0x00170040, SetSemaphoreMask, "SetSemaphoreMask"}, |
| 538 | {0x00180040, nullptr, "GetPhysicalAddress"}, | 561 | {0x00180040, nullptr, "GetPhysicalAddress"}, |
| 539 | {0x00190040, nullptr, "GetVirtualAddress"}, | 562 | {0x00190040, nullptr, "GetVirtualAddress"}, |
| 540 | {0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"}, | 563 | {0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"}, |
| 541 | {0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"}, | 564 | {0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"}, |
| 542 | {0x001C0082, nullptr, "SetIirFilterEQ"}, | 565 | {0x001C0082, nullptr, "SetIirFilterEQ"}, |
| 543 | {0x001D00C0, nullptr, "ReadMultiEx_SPI2"}, | 566 | {0x001D00C0, nullptr, "ReadMultiEx_SPI2"}, |
| 544 | {0x001E00C2, nullptr, "WriteMultiEx_SPI2"}, | 567 | {0x001E00C2, nullptr, "WriteMultiEx_SPI2"}, |
| 545 | {0x001F0000, GetHeadphoneStatus, "GetHeadphoneStatus"}, | 568 | {0x001F0000, GetHeadphoneStatus, "GetHeadphoneStatus"}, |
| 546 | {0x00200040, nullptr, "ForceHeadphoneOut"}, | 569 | {0x00200040, nullptr, "ForceHeadphoneOut"}, |
| 547 | {0x00210000, nullptr, "GetIsDspOccupied"}, | 570 | {0x00210000, nullptr, "GetIsDspOccupied"}, |
| 548 | }; | 571 | }; |
| 549 | 572 | ||
| 550 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 573 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp index 5f9cf6e94..2cd8269de 100644 --- a/src/core/hle/service/err_f.cpp +++ b/src/core/hle/service/err_f.cpp | |||
| @@ -35,70 +35,70 @@ union ErrInfo { | |||
| 35 | u8 specifier; | 35 | u8 specifier; |
| 36 | 36 | ||
| 37 | struct { | 37 | struct { |
| 38 | u8 specifier; // 0x0 | 38 | u8 specifier; // 0x0 |
| 39 | u8 rev_high; // 0x1 | 39 | u8 rev_high; // 0x1 |
| 40 | u16 rev_low; // 0x2 | 40 | u16 rev_low; // 0x2 |
| 41 | RSL result_code; // 0x4 | 41 | RSL result_code; // 0x4 |
| 42 | u32 address; // 0x8 | 42 | u32 address; // 0x8 |
| 43 | INSERT_PADDING_BYTES(4); // 0xC | 43 | INSERT_PADDING_BYTES(4); // 0xC |
| 44 | u32 pid_low; // 0x10 | 44 | u32 pid_low; // 0x10 |
| 45 | u32 pid_high; // 0x14 | 45 | u32 pid_high; // 0x14 |
| 46 | u32 aid_low; // 0x18 | 46 | u32 aid_low; // 0x18 |
| 47 | u32 aid_high; // 0x1C | 47 | u32 aid_high; // 0x1C |
| 48 | } errtype1; | 48 | } errtype1; |
| 49 | 49 | ||
| 50 | struct { | 50 | struct { |
| 51 | u8 specifier; // 0x0 | 51 | u8 specifier; // 0x0 |
| 52 | u8 rev_high; // 0x1 | 52 | u8 rev_high; // 0x1 |
| 53 | u16 rev_low; // 0x2 | 53 | u16 rev_low; // 0x2 |
| 54 | INSERT_PADDING_BYTES(0xC); // 0x4 | 54 | INSERT_PADDING_BYTES(0xC); // 0x4 |
| 55 | u32 pid_low; // 0x10 | 55 | u32 pid_low; // 0x10 |
| 56 | u32 pid_high; // 0x14 | 56 | u32 pid_high; // 0x14 |
| 57 | u32 aid_low; // 0x18 | 57 | u32 aid_low; // 0x18 |
| 58 | u32 aid_high; // 0x1C | 58 | u32 aid_high; // 0x1C |
| 59 | u8 error_type; // 0x20 | 59 | u8 error_type; // 0x20 |
| 60 | INSERT_PADDING_BYTES(3); // 0x21 | 60 | INSERT_PADDING_BYTES(3); // 0x21 |
| 61 | u32 fault_status_reg; // 0x24 | 61 | u32 fault_status_reg; // 0x24 |
| 62 | u32 fault_addr; // 0x28 | 62 | u32 fault_addr; // 0x28 |
| 63 | u32 fpexc; // 0x2C | 63 | u32 fpexc; // 0x2C |
| 64 | u32 finst; // 0x30 | 64 | u32 finst; // 0x30 |
| 65 | u32 finst2; // 0x34 | 65 | u32 finst2; // 0x34 |
| 66 | INSERT_PADDING_BYTES(0x34); // 0x38 | 66 | INSERT_PADDING_BYTES(0x34); // 0x38 |
| 67 | u32 sp; // 0x6C | 67 | u32 sp; // 0x6C |
| 68 | u32 pc; // 0x70 | 68 | u32 pc; // 0x70 |
| 69 | u32 lr; // 0x74 | 69 | u32 lr; // 0x74 |
| 70 | u32 cpsr; // 0x78 | 70 | u32 cpsr; // 0x78 |
| 71 | } errtype3; | 71 | } errtype3; |
| 72 | 72 | ||
| 73 | struct { | 73 | struct { |
| 74 | u8 specifier; // 0x0 | 74 | u8 specifier; // 0x0 |
| 75 | u8 rev_high; // 0x1 | 75 | u8 rev_high; // 0x1 |
| 76 | u16 rev_low; // 0x2 | 76 | u16 rev_low; // 0x2 |
| 77 | RSL result_code; // 0x4 | 77 | RSL result_code; // 0x4 |
| 78 | INSERT_PADDING_BYTES(8); // 0x8 | 78 | INSERT_PADDING_BYTES(8); // 0x8 |
| 79 | u32 pid_low; // 0x10 | 79 | u32 pid_low; // 0x10 |
| 80 | u32 pid_high; // 0x14 | 80 | u32 pid_high; // 0x14 |
| 81 | u32 aid_low; // 0x18 | 81 | u32 aid_low; // 0x18 |
| 82 | u32 aid_high; // 0x1C | 82 | u32 aid_high; // 0x1C |
| 83 | char debug_string1[0x2E]; // 0x20 | 83 | char debug_string1[0x2E]; // 0x20 |
| 84 | char debug_string2[0x2E]; // 0x4E | 84 | char debug_string2[0x2E]; // 0x4E |
| 85 | } errtype4; | 85 | } errtype4; |
| 86 | }; | 86 | }; |
| 87 | 87 | ||
| 88 | enum { | 88 | enum { PrefetchAbort = 0, DataAbort = 1, UndefInstr = 2, VectorFP = 3 }; |
| 89 | PrefetchAbort = 0, | ||
| 90 | DataAbort = 1, | ||
| 91 | UndefInstr = 2, | ||
| 92 | VectorFP = 3 | ||
| 93 | }; | ||
| 94 | 89 | ||
| 95 | static std::string GetErrInfo3Type(u8 type_code) { | 90 | static std::string GetErrInfo3Type(u8 type_code) { |
| 96 | switch (type_code) { | 91 | switch (type_code) { |
| 97 | case PrefetchAbort: return "Prefetch Abort"; | 92 | case PrefetchAbort: |
| 98 | case DataAbort: return "Data Abort"; | 93 | return "Prefetch Abort"; |
| 99 | case UndefInstr: return "Undefined Instruction"; | 94 | case DataAbort: |
| 100 | case VectorFP: return "Vector Floating Point"; | 95 | return "Data Abort"; |
| 101 | default: return "unknown"; | 96 | case UndefInstr: |
| 97 | return "Undefined Instruction"; | ||
| 98 | case VectorFP: | ||
| 99 | return "Vector Floating Point"; | ||
| 100 | default: | ||
| 101 | return "unknown"; | ||
| 102 | } | 102 | } |
| 103 | } | 103 | } |
| 104 | 104 | ||
| @@ -110,8 +110,7 @@ static void ThrowFatalError(Service::Interface* self) { | |||
| 110 | 110 | ||
| 111 | switch (errinfo->specifier) { | 111 | switch (errinfo->specifier) { |
| 112 | case ErrSpecifier0: | 112 | case ErrSpecifier0: |
| 113 | case ErrSpecifier1: | 113 | case ErrSpecifier1: { |
| 114 | { | ||
| 115 | const auto& errtype = errinfo->errtype1; | 114 | const auto& errtype = errinfo->errtype1; |
| 116 | LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); | 115 | LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); |
| 117 | LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16)); | 116 | LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16)); |
| @@ -119,15 +118,14 @@ static void ThrowFatalError(Service::Interface* self) { | |||
| 119 | LOG_CRITICAL(Service_ERR, "ADR: 0x%08X", errtype.address); | 118 | LOG_CRITICAL(Service_ERR, "ADR: 0x%08X", errtype.address); |
| 120 | 119 | ||
| 121 | LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw); | 120 | LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw); |
| 122 | LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value()); | 121 | LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value()); |
| 123 | LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value()); | 122 | LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value()); |
| 124 | LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value()); | 123 | LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value()); |
| 125 | LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value()); | 124 | LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value()); |
| 126 | break; | 125 | break; |
| 127 | } | 126 | } |
| 128 | 127 | ||
| 129 | case ErrSpecifier3: | 128 | case ErrSpecifier3: { |
| 130 | { | ||
| 131 | const auto& errtype = errinfo->errtype3; | 129 | const auto& errtype = errinfo->errtype3; |
| 132 | LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); | 130 | LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); |
| 133 | LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16)); | 131 | LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16)); |
| @@ -154,18 +152,17 @@ static void ThrowFatalError(Service::Interface* self) { | |||
| 154 | break; | 152 | break; |
| 155 | } | 153 | } |
| 156 | 154 | ||
| 157 | case ErrSpecifier4: | 155 | case ErrSpecifier4: { |
| 158 | { | ||
| 159 | const auto& errtype = errinfo->errtype4; | 156 | const auto& errtype = errinfo->errtype4; |
| 160 | LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); | 157 | LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); |
| 161 | LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16)); | 158 | LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16)); |
| 162 | LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high); | 159 | LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high); |
| 163 | 160 | ||
| 164 | LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw); | 161 | LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw); |
| 165 | LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value()); | 162 | LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value()); |
| 166 | LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value()); | 163 | LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value()); |
| 167 | LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value()); | 164 | LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value()); |
| 168 | LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value()); | 165 | LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value()); |
| 169 | 166 | ||
| 170 | LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string1); | 167 | LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string1); |
| 171 | LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string2); | 168 | LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string2); |
| @@ -176,9 +173,7 @@ static void ThrowFatalError(Service::Interface* self) { | |||
| 176 | cmd_buff[1] = 0; // No error | 173 | cmd_buff[1] = 0; // No error |
| 177 | } | 174 | } |
| 178 | 175 | ||
| 179 | const Interface::FunctionInfo FunctionTable[] = { | 176 | const Interface::FunctionInfo FunctionTable[] = {{0x00010800, ThrowFatalError, "ThrowFatalError"}}; |
| 180 | {0x00010800, ThrowFatalError, "ThrowFatalError"} | ||
| 181 | }; | ||
| 182 | 177 | ||
| 183 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 178 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 184 | // Interface class | 179 | // Interface class |
diff --git a/src/core/hle/service/frd/frd.cpp b/src/core/hle/service/frd/frd.cpp index 29d144365..1e9fe178f 100644 --- a/src/core/hle/service/frd/frd.cpp +++ b/src/core/hle/service/frd/frd.cpp | |||
| @@ -4,10 +4,10 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/string_util.h" | 5 | #include "common/string_util.h" |
| 6 | 6 | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | #include "core/hle/service/frd/frd.h" | 7 | #include "core/hle/service/frd/frd.h" |
| 9 | #include "core/hle/service/frd/frd_a.h" | 8 | #include "core/hle/service/frd/frd_a.h" |
| 10 | #include "core/hle/service/frd/frd_u.h" | 9 | #include "core/hle/service/frd/frd_u.h" |
| 10 | #include "core/hle/service/service.h" | ||
| 11 | 11 | ||
| 12 | namespace Service { | 12 | namespace Service { |
| 13 | namespace FRD { | 13 | namespace FRD { |
| @@ -43,7 +43,7 @@ void GetFriendKeyList(Service::Interface* self) { | |||
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 45 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 46 | cmd_buff[2] = 0; // 0 friends | 46 | cmd_buff[2] = 0; // 0 friends |
| 47 | LOG_WARNING(Service_FRD, "(STUBBED) called, unknown=%d, frd_count=%d, frd_key_addr=0x%08X", | 47 | LOG_WARNING(Service_FRD, "(STUBBED) called, unknown=%d, frd_count=%d, frd_key_addr=0x%08X", |
| 48 | unknown, frd_count, frd_key_addr); | 48 | unknown, frd_count, frd_key_addr); |
| 49 | } | 49 | } |
| @@ -61,25 +61,27 @@ void GetFriendProfile(Service::Interface* self) { | |||
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 63 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 64 | LOG_WARNING(Service_FRD, "(STUBBED) called, count=%d, frd_key_addr=0x%08X, profiles_addr=0x%08X", | 64 | LOG_WARNING(Service_FRD, |
| 65 | count, frd_key_addr, profiles_addr); | 65 | "(STUBBED) called, count=%d, frd_key_addr=0x%08X, profiles_addr=0x%08X", count, |
| 66 | frd_key_addr, profiles_addr); | ||
| 66 | } | 67 | } |
| 67 | 68 | ||
| 68 | void GetFriendAttributeFlags(Service::Interface* self) { | 69 | void GetFriendAttributeFlags(Service::Interface* self) { |
| 69 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 70 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 70 | 71 | ||
| 71 | u32 count = cmd_buff[1]; | 72 | u32 count = cmd_buff[1]; |
| 72 | u32 frd_key_addr = cmd_buff[3]; | 73 | u32 frd_key_addr = cmd_buff[3]; |
| 73 | u32 attr_flags_addr = cmd_buff[65]; | 74 | u32 attr_flags_addr = cmd_buff[65]; |
| 74 | 75 | ||
| 75 | for (u32 i = 0; i < count; ++i) { | 76 | for (u32 i = 0; i < count; ++i) { |
| 76 | //TODO:(mailwl) figure out AttributeFlag size and zero all buffer. Assume 1 byte | 77 | // TODO:(mailwl) figure out AttributeFlag size and zero all buffer. Assume 1 byte |
| 77 | Memory::Write8(attr_flags_addr + i, 0); | 78 | Memory::Write8(attr_flags_addr + i, 0); |
| 78 | } | 79 | } |
| 79 | 80 | ||
| 80 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 81 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 81 | LOG_WARNING(Service_FRD, "(STUBBED) called, count=%d, frd_key_addr=0x%08X, attr_flags_addr=0x%08X", | 82 | LOG_WARNING(Service_FRD, |
| 82 | count, frd_key_addr, attr_flags_addr); | 83 | "(STUBBED) called, count=%d, frd_key_addr=0x%08X, attr_flags_addr=0x%08X", count, |
| 84 | frd_key_addr, attr_flags_addr); | ||
| 83 | } | 85 | } |
| 84 | 86 | ||
| 85 | void GetMyFriendKey(Service::Interface* self) { | 87 | void GetMyFriendKey(Service::Interface* self) { |
diff --git a/src/core/hle/service/frd/frd_a.cpp b/src/core/hle/service/frd/frd_a.cpp index 818d610f3..cfc37210b 100644 --- a/src/core/hle/service/frd/frd_a.cpp +++ b/src/core/hle/service/frd/frd_a.cpp | |||
| @@ -11,7 +11,7 @@ namespace FRD { | |||
| 11 | // const Interface::FunctionInfo FunctionTable[] = { }; | 11 | // const Interface::FunctionInfo FunctionTable[] = { }; |
| 12 | 12 | ||
| 13 | FRD_A_Interface::FRD_A_Interface() { | 13 | FRD_A_Interface::FRD_A_Interface() { |
| 14 | //Register(FunctionTable); | 14 | // Register(FunctionTable); |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | } // namespace FRD | 17 | } // namespace FRD |
diff --git a/src/core/hle/service/frd/frd_u.cpp b/src/core/hle/service/frd/frd_u.cpp index db8666416..bd1c9c16b 100644 --- a/src/core/hle/service/frd/frd_u.cpp +++ b/src/core/hle/service/frd/frd_u.cpp | |||
| @@ -9,59 +9,59 @@ namespace Service { | |||
| 9 | namespace FRD { | 9 | namespace FRD { |
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = { |
| 12 | {0x00010000, nullptr, "HasLoggedIn"}, | 12 | {0x00010000, nullptr, "HasLoggedIn"}, |
| 13 | {0x00020000, nullptr, "IsOnline"}, | 13 | {0x00020000, nullptr, "IsOnline"}, |
| 14 | {0x00030000, nullptr, "Login"}, | 14 | {0x00030000, nullptr, "Login"}, |
| 15 | {0x00040000, nullptr, "Logout"}, | 15 | {0x00040000, nullptr, "Logout"}, |
| 16 | {0x00050000, GetMyFriendKey, "GetMyFriendKey"}, | 16 | {0x00050000, GetMyFriendKey, "GetMyFriendKey"}, |
| 17 | {0x00060000, nullptr, "GetMyPreference"}, | 17 | {0x00060000, nullptr, "GetMyPreference"}, |
| 18 | {0x00070000, nullptr, "GetMyProfile"}, | 18 | {0x00070000, nullptr, "GetMyProfile"}, |
| 19 | {0x00080000, GetMyPresence, "GetMyPresence"}, | 19 | {0x00080000, GetMyPresence, "GetMyPresence"}, |
| 20 | {0x00090000, GetMyScreenName, "GetMyScreenName"}, | 20 | {0x00090000, GetMyScreenName, "GetMyScreenName"}, |
| 21 | {0x000A0000, nullptr, "GetMyMii"}, | 21 | {0x000A0000, nullptr, "GetMyMii"}, |
| 22 | {0x000B0000, nullptr, "GetMyLocalAccountId"}, | 22 | {0x000B0000, nullptr, "GetMyLocalAccountId"}, |
| 23 | {0x000C0000, nullptr, "GetMyPlayingGame"}, | 23 | {0x000C0000, nullptr, "GetMyPlayingGame"}, |
| 24 | {0x000D0000, nullptr, "GetMyFavoriteGame"}, | 24 | {0x000D0000, nullptr, "GetMyFavoriteGame"}, |
| 25 | {0x000E0000, nullptr, "GetMyNcPrincipalId"}, | 25 | {0x000E0000, nullptr, "GetMyNcPrincipalId"}, |
| 26 | {0x000F0000, nullptr, "GetMyComment"}, | 26 | {0x000F0000, nullptr, "GetMyComment"}, |
| 27 | {0x00100040, nullptr, "GetMyPassword"}, | 27 | {0x00100040, nullptr, "GetMyPassword"}, |
| 28 | {0x00110080, GetFriendKeyList, "GetFriendKeyList"}, | 28 | {0x00110080, GetFriendKeyList, "GetFriendKeyList"}, |
| 29 | {0x00120042, nullptr, "GetFriendPresence"}, | 29 | {0x00120042, nullptr, "GetFriendPresence"}, |
| 30 | {0x00130142, nullptr, "GetFriendScreenName"}, | 30 | {0x00130142, nullptr, "GetFriendScreenName"}, |
| 31 | {0x00140044, nullptr, "GetFriendMii"}, | 31 | {0x00140044, nullptr, "GetFriendMii"}, |
| 32 | {0x00150042, GetFriendProfile, "GetFriendProfile"}, | 32 | {0x00150042, GetFriendProfile, "GetFriendProfile"}, |
| 33 | {0x00160042, nullptr, "GetFriendRelationship"}, | 33 | {0x00160042, nullptr, "GetFriendRelationship"}, |
| 34 | {0x00170042, GetFriendAttributeFlags, "GetFriendAttributeFlags"}, | 34 | {0x00170042, GetFriendAttributeFlags, "GetFriendAttributeFlags"}, |
| 35 | {0x00180044, nullptr, "GetFriendPlayingGame"}, | 35 | {0x00180044, nullptr, "GetFriendPlayingGame"}, |
| 36 | {0x00190042, nullptr, "GetFriendFavoriteGame"}, | 36 | {0x00190042, nullptr, "GetFriendFavoriteGame"}, |
| 37 | {0x001A00C4, nullptr, "GetFriendInfo"}, | 37 | {0x001A00C4, nullptr, "GetFriendInfo"}, |
| 38 | {0x001B0080, nullptr, "IsIncludedInFriendList"}, | 38 | {0x001B0080, nullptr, "IsIncludedInFriendList"}, |
| 39 | {0x001C0042, nullptr, "UnscrambleLocalFriendCode"}, | 39 | {0x001C0042, nullptr, "UnscrambleLocalFriendCode"}, |
| 40 | {0x001D0002, nullptr, "UpdateGameModeDescription"}, | 40 | {0x001D0002, nullptr, "UpdateGameModeDescription"}, |
| 41 | {0x001E02C2, nullptr, "UpdateGameMode"}, | 41 | {0x001E02C2, nullptr, "UpdateGameMode"}, |
| 42 | {0x001F0042, nullptr, "SendInvitation"}, | 42 | {0x001F0042, nullptr, "SendInvitation"}, |
| 43 | {0x00200002, nullptr, "AttachToEventNotification"}, | 43 | {0x00200002, nullptr, "AttachToEventNotification"}, |
| 44 | {0x00210040, nullptr, "SetNotificationMask"}, | 44 | {0x00210040, nullptr, "SetNotificationMask"}, |
| 45 | {0x00220040, nullptr, "GetEventNotification"}, | 45 | {0x00220040, nullptr, "GetEventNotification"}, |
| 46 | {0x00230000, nullptr, "GetLastResponseResult"}, | 46 | {0x00230000, nullptr, "GetLastResponseResult"}, |
| 47 | {0x00240040, nullptr, "PrincipalIdToFriendCode"}, | 47 | {0x00240040, nullptr, "PrincipalIdToFriendCode"}, |
| 48 | {0x00250080, nullptr, "FriendCodeToPrincipalId"}, | 48 | {0x00250080, nullptr, "FriendCodeToPrincipalId"}, |
| 49 | {0x00260080, nullptr, "IsValidFriendCode"}, | 49 | {0x00260080, nullptr, "IsValidFriendCode"}, |
| 50 | {0x00270040, nullptr, "ResultToErrorCode"}, | 50 | {0x00270040, nullptr, "ResultToErrorCode"}, |
| 51 | {0x00280244, nullptr, "RequestGameAuthentication"}, | 51 | {0x00280244, nullptr, "RequestGameAuthentication"}, |
| 52 | {0x00290000, nullptr, "GetGameAuthenticationData"}, | 52 | {0x00290000, nullptr, "GetGameAuthenticationData"}, |
| 53 | {0x002A0204, nullptr, "RequestServiceLocator"}, | 53 | {0x002A0204, nullptr, "RequestServiceLocator"}, |
| 54 | {0x002B0000, nullptr, "GetServiceLocatorData"}, | 54 | {0x002B0000, nullptr, "GetServiceLocatorData"}, |
| 55 | {0x002C0002, nullptr, "DetectNatProperties"}, | 55 | {0x002C0002, nullptr, "DetectNatProperties"}, |
| 56 | {0x002D0000, nullptr, "GetNatProperties"}, | 56 | {0x002D0000, nullptr, "GetNatProperties"}, |
| 57 | {0x002E0000, nullptr, "GetServerTimeInterval"}, | 57 | {0x002E0000, nullptr, "GetServerTimeInterval"}, |
| 58 | {0x002F0040, nullptr, "AllowHalfAwake"}, | 58 | {0x002F0040, nullptr, "AllowHalfAwake"}, |
| 59 | {0x00300000, nullptr, "GetServerTypes"}, | 59 | {0x00300000, nullptr, "GetServerTypes"}, |
| 60 | {0x00310082, nullptr, "GetFriendComment"}, | 60 | {0x00310082, nullptr, "GetFriendComment"}, |
| 61 | {0x00320042, nullptr, "SetClientSdkVersion"}, | 61 | {0x00320042, nullptr, "SetClientSdkVersion"}, |
| 62 | {0x00330000, nullptr, "GetMyApproachContext"}, | 62 | {0x00330000, nullptr, "GetMyApproachContext"}, |
| 63 | {0x00340046, nullptr, "AddFriendWithApproach"}, | 63 | {0x00340046, nullptr, "AddFriendWithApproach"}, |
| 64 | {0x00350082, nullptr, "DecryptApproachContext"}, | 64 | {0x00350082, nullptr, "DecryptApproachContext"}, |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | FRD_U_Interface::FRD_U_Interface() { | 67 | FRD_U_Interface::FRD_U_Interface() { |
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index 4c7aaa7f2..1b851eade 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp | |||
| @@ -3,9 +3,9 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cstddef> | 5 | #include <cstddef> |
| 6 | #include <memory> | ||
| 6 | #include <system_error> | 7 | #include <system_error> |
| 7 | #include <type_traits> | 8 | #include <type_traits> |
| 8 | #include <memory> | ||
| 9 | #include <unordered_map> | 9 | #include <unordered_map> |
| 10 | #include <utility> | 10 | #include <utility> |
| 11 | 11 | ||
| @@ -25,25 +25,25 @@ | |||
| 25 | #include "core/file_sys/directory_backend.h" | 25 | #include "core/file_sys/directory_backend.h" |
| 26 | #include "core/file_sys/file_backend.h" | 26 | #include "core/file_sys/file_backend.h" |
| 27 | #include "core/hle/hle.h" | 27 | #include "core/hle/hle.h" |
| 28 | #include "core/hle/service/service.h" | 28 | #include "core/hle/result.h" |
| 29 | #include "core/hle/service/fs/archive.h" | 29 | #include "core/hle/service/fs/archive.h" |
| 30 | #include "core/hle/service/fs/fs_user.h" | 30 | #include "core/hle/service/fs/fs_user.h" |
| 31 | #include "core/hle/result.h" | 31 | #include "core/hle/service/service.h" |
| 32 | #include "core/memory.h" | 32 | #include "core/memory.h" |
| 33 | 33 | ||
| 34 | // Specializes std::hash for ArchiveIdCode, so that we can use it in std::unordered_map. | 34 | // Specializes std::hash for ArchiveIdCode, so that we can use it in std::unordered_map. |
| 35 | // Workaroung for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970 | 35 | // Workaroung for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970 |
| 36 | namespace std { | 36 | namespace std { |
| 37 | template <> | 37 | template <> |
| 38 | struct hash<Service::FS::ArchiveIdCode> { | 38 | struct hash<Service::FS::ArchiveIdCode> { |
| 39 | typedef Service::FS::ArchiveIdCode argument_type; | 39 | typedef Service::FS::ArchiveIdCode argument_type; |
| 40 | typedef std::size_t result_type; | 40 | typedef std::size_t result_type; |
| 41 | 41 | ||
| 42 | result_type operator()(const argument_type& id_code) const { | 42 | result_type operator()(const argument_type& id_code) const { |
| 43 | typedef std::underlying_type<argument_type>::type Type; | 43 | typedef std::underlying_type<argument_type>::type Type; |
| 44 | return std::hash<Type>()(static_cast<Type>(id_code)); | 44 | return std::hash<Type>()(static_cast<Type>(id_code)); |
| 45 | } | 45 | } |
| 46 | }; | 46 | }; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | /// TODO(Subv): Confirm length of these strings | 49 | /// TODO(Subv): Confirm length of these strings |
| @@ -56,197 +56,193 @@ namespace FS { | |||
| 56 | // TODO: Verify code | 56 | // TODO: Verify code |
| 57 | /// Returned when a function is passed an invalid handle. | 57 | /// Returned when a function is passed an invalid handle. |
| 58 | const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::FS, | 58 | const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::FS, |
| 59 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); | 59 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); |
| 60 | 60 | ||
| 61 | /// Returned when a function is passed an invalid archive handle. | 61 | /// Returned when a function is passed an invalid archive handle. |
| 62 | const ResultCode ERR_INVALID_ARCHIVE_HANDLE(ErrorDescription::FS_ArchiveNotMounted, ErrorModule::FS, | 62 | const ResultCode ERR_INVALID_ARCHIVE_HANDLE(ErrorDescription::FS_ArchiveNotMounted, ErrorModule::FS, |
| 63 | ErrorSummary::NotFound, ErrorLevel::Status); // 0xC8804465 | 63 | ErrorSummary::NotFound, |
| 64 | ErrorLevel::Status); // 0xC8804465 | ||
| 64 | 65 | ||
| 65 | // Command to access archive file | 66 | // Command to access archive file |
| 66 | enum class FileCommand : u32 { | 67 | enum class FileCommand : u32 { |
| 67 | Dummy1 = 0x000100C6, | 68 | Dummy1 = 0x000100C6, |
| 68 | Control = 0x040100C4, | 69 | Control = 0x040100C4, |
| 69 | OpenSubFile = 0x08010100, | 70 | OpenSubFile = 0x08010100, |
| 70 | Read = 0x080200C2, | 71 | Read = 0x080200C2, |
| 71 | Write = 0x08030102, | 72 | Write = 0x08030102, |
| 72 | GetSize = 0x08040000, | 73 | GetSize = 0x08040000, |
| 73 | SetSize = 0x08050080, | 74 | SetSize = 0x08050080, |
| 74 | GetAttributes = 0x08060000, | 75 | GetAttributes = 0x08060000, |
| 75 | SetAttributes = 0x08070040, | 76 | SetAttributes = 0x08070040, |
| 76 | Close = 0x08080000, | 77 | Close = 0x08080000, |
| 77 | Flush = 0x08090000, | 78 | Flush = 0x08090000, |
| 78 | SetPriority = 0x080A0040, | 79 | SetPriority = 0x080A0040, |
| 79 | GetPriority = 0x080B0000, | 80 | GetPriority = 0x080B0000, |
| 80 | OpenLinkFile = 0x080C0000, | 81 | OpenLinkFile = 0x080C0000, |
| 81 | }; | 82 | }; |
| 82 | 83 | ||
| 83 | // Command to access directory | 84 | // Command to access directory |
| 84 | enum class DirectoryCommand : u32 { | 85 | enum class DirectoryCommand : u32 { |
| 85 | Dummy1 = 0x000100C6, | 86 | Dummy1 = 0x000100C6, |
| 86 | Control = 0x040100C4, | 87 | Control = 0x040100C4, |
| 87 | Read = 0x08010042, | 88 | Read = 0x08010042, |
| 88 | Close = 0x08020000, | 89 | Close = 0x08020000, |
| 89 | }; | 90 | }; |
| 90 | 91 | ||
| 91 | File::File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path & path) | 92 | File::File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path) |
| 92 | : path(path), priority(0), backend(std::move(backend)) {} | 93 | : path(path), priority(0), backend(std::move(backend)) { |
| 94 | } | ||
| 93 | 95 | ||
| 94 | File::~File() {} | 96 | File::~File() { |
| 97 | } | ||
| 95 | 98 | ||
| 96 | ResultVal<bool> File::SyncRequest() { | 99 | ResultVal<bool> File::SyncRequest() { |
| 97 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 100 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 98 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); | 101 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); |
| 99 | switch (cmd) { | 102 | switch (cmd) { |
| 100 | 103 | ||
| 101 | // Read from file... | 104 | // Read from file... |
| 102 | case FileCommand::Read: | 105 | case FileCommand::Read: { |
| 103 | { | 106 | u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32; |
| 104 | u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32; | 107 | u32 length = cmd_buff[3]; |
| 105 | u32 length = cmd_buff[3]; | 108 | u32 address = cmd_buff[5]; |
| 106 | u32 address = cmd_buff[5]; | 109 | LOG_TRACE(Service_FS, "Read %s %s: offset=0x%llx length=%d address=0x%x", |
| 107 | LOG_TRACE(Service_FS, "Read %s %s: offset=0x%llx length=%d address=0x%x", | 110 | GetTypeName().c_str(), GetName().c_str(), offset, length, address); |
| 108 | GetTypeName().c_str(), GetName().c_str(), offset, length, address); | 111 | |
| 109 | 112 | if (offset + length > backend->GetSize()) { | |
| 110 | if (offset + length > backend->GetSize()) { | 113 | LOG_ERROR(Service_FS, |
| 111 | LOG_ERROR(Service_FS, "Reading from out of bounds offset=0x%llX length=0x%08X file_size=0x%llX", | 114 | "Reading from out of bounds offset=0x%llX length=0x%08X file_size=0x%llX", |
| 112 | offset, length, backend->GetSize()); | 115 | offset, length, backend->GetSize()); |
| 113 | } | ||
| 114 | |||
| 115 | std::vector<u8> data(length); | ||
| 116 | ResultVal<size_t> read = backend->Read(offset, data.size(), data.data()); | ||
| 117 | if (read.Failed()) { | ||
| 118 | cmd_buff[1] = read.Code().raw; | ||
| 119 | return read.Code(); | ||
| 120 | } | ||
| 121 | Memory::WriteBlock(address, data.data(), *read); | ||
| 122 | cmd_buff[2] = static_cast<u32>(*read); | ||
| 123 | break; | ||
| 124 | } | 116 | } |
| 125 | 117 | ||
| 126 | // Write to file... | 118 | std::vector<u8> data(length); |
| 127 | case FileCommand::Write: | 119 | ResultVal<size_t> read = backend->Read(offset, data.size(), data.data()); |
| 128 | { | 120 | if (read.Failed()) { |
| 129 | u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32; | 121 | cmd_buff[1] = read.Code().raw; |
| 130 | u32 length = cmd_buff[3]; | 122 | return read.Code(); |
| 131 | u32 flush = cmd_buff[4]; | ||
| 132 | u32 address = cmd_buff[6]; | ||
| 133 | LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x", | ||
| 134 | GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush); | ||
| 135 | |||
| 136 | std::vector<u8> data(length); | ||
| 137 | Memory::ReadBlock(address, data.data(), data.size()); | ||
| 138 | ResultVal<size_t> written = backend->Write(offset, data.size(), flush != 0, data.data()); | ||
| 139 | if (written.Failed()) { | ||
| 140 | cmd_buff[1] = written.Code().raw; | ||
| 141 | return written.Code(); | ||
| 142 | } | ||
| 143 | cmd_buff[2] = static_cast<u32>(*written); | ||
| 144 | break; | ||
| 145 | } | 123 | } |
| 124 | Memory::WriteBlock(address, data.data(), *read); | ||
| 125 | cmd_buff[2] = static_cast<u32>(*read); | ||
| 126 | break; | ||
| 127 | } | ||
| 146 | 128 | ||
| 147 | case FileCommand::GetSize: | 129 | // Write to file... |
| 148 | { | 130 | case FileCommand::Write: { |
| 149 | LOG_TRACE(Service_FS, "GetSize %s %s", GetTypeName().c_str(), GetName().c_str()); | 131 | u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32; |
| 150 | u64 size = backend->GetSize(); | 132 | u32 length = cmd_buff[3]; |
| 151 | cmd_buff[2] = (u32)size; | 133 | u32 flush = cmd_buff[4]; |
| 152 | cmd_buff[3] = size >> 32; | 134 | u32 address = cmd_buff[6]; |
| 153 | break; | 135 | LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x", |
| 136 | GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush); | ||
| 137 | |||
| 138 | std::vector<u8> data(length); | ||
| 139 | Memory::ReadBlock(address, data.data(), data.size()); | ||
| 140 | ResultVal<size_t> written = backend->Write(offset, data.size(), flush != 0, data.data()); | ||
| 141 | if (written.Failed()) { | ||
| 142 | cmd_buff[1] = written.Code().raw; | ||
| 143 | return written.Code(); | ||
| 154 | } | 144 | } |
| 145 | cmd_buff[2] = static_cast<u32>(*written); | ||
| 146 | break; | ||
| 147 | } | ||
| 155 | 148 | ||
| 156 | case FileCommand::SetSize: | 149 | case FileCommand::GetSize: { |
| 157 | { | 150 | LOG_TRACE(Service_FS, "GetSize %s %s", GetTypeName().c_str(), GetName().c_str()); |
| 158 | u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); | 151 | u64 size = backend->GetSize(); |
| 159 | LOG_TRACE(Service_FS, "SetSize %s %s size=%llu", | 152 | cmd_buff[2] = (u32)size; |
| 160 | GetTypeName().c_str(), GetName().c_str(), size); | 153 | cmd_buff[3] = size >> 32; |
| 161 | backend->SetSize(size); | 154 | break; |
| 162 | break; | 155 | } |
| 163 | } | ||
| 164 | 156 | ||
| 165 | case FileCommand::Close: | 157 | case FileCommand::SetSize: { |
| 166 | { | 158 | u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); |
| 167 | LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); | 159 | LOG_TRACE(Service_FS, "SetSize %s %s size=%llu", GetTypeName().c_str(), GetName().c_str(), |
| 168 | backend->Close(); | 160 | size); |
| 169 | break; | 161 | backend->SetSize(size); |
| 170 | } | 162 | break; |
| 163 | } | ||
| 171 | 164 | ||
| 172 | case FileCommand::Flush: | 165 | case FileCommand::Close: { |
| 173 | { | 166 | LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); |
| 174 | LOG_TRACE(Service_FS, "Flush"); | 167 | backend->Close(); |
| 175 | backend->Flush(); | 168 | break; |
| 176 | break; | 169 | } |
| 177 | } | ||
| 178 | 170 | ||
| 179 | case FileCommand::OpenLinkFile: | 171 | case FileCommand::Flush: { |
| 180 | { | 172 | LOG_TRACE(Service_FS, "Flush"); |
| 181 | LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str()); | 173 | backend->Flush(); |
| 182 | cmd_buff[3] = Kernel::g_handle_table.Create(this).ValueOr(INVALID_HANDLE); | 174 | break; |
| 183 | break; | 175 | } |
| 184 | } | ||
| 185 | 176 | ||
| 186 | case FileCommand::SetPriority: | 177 | case FileCommand::OpenLinkFile: { |
| 187 | { | 178 | LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str()); |
| 188 | priority = cmd_buff[1]; | 179 | cmd_buff[3] = Kernel::g_handle_table.Create(this).ValueOr(INVALID_HANDLE); |
| 189 | LOG_TRACE(Service_FS, "SetPriority %u", priority); | 180 | break; |
| 190 | break; | 181 | } |
| 191 | } | ||
| 192 | 182 | ||
| 193 | case FileCommand::GetPriority: | 183 | case FileCommand::SetPriority: { |
| 194 | { | 184 | priority = cmd_buff[1]; |
| 195 | cmd_buff[2] = priority; | 185 | LOG_TRACE(Service_FS, "SetPriority %u", priority); |
| 196 | LOG_TRACE(Service_FS, "GetPriority"); | 186 | break; |
| 197 | break; | 187 | } |
| 198 | } | ||
| 199 | 188 | ||
| 200 | // Unknown command... | 189 | case FileCommand::GetPriority: { |
| 201 | default: | 190 | cmd_buff[2] = priority; |
| 202 | LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); | 191 | LOG_TRACE(Service_FS, "GetPriority"); |
| 203 | ResultCode error = UnimplementedFunction(ErrorModule::FS); | 192 | break; |
| 204 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. | 193 | } |
| 205 | return error; | 194 | |
| 195 | // Unknown command... | ||
| 196 | default: | ||
| 197 | LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); | ||
| 198 | ResultCode error = UnimplementedFunction(ErrorModule::FS); | ||
| 199 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. | ||
| 200 | return error; | ||
| 206 | } | 201 | } |
| 207 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 202 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 208 | return MakeResult<bool>(false); | 203 | return MakeResult<bool>(false); |
| 209 | } | 204 | } |
| 210 | 205 | ||
| 211 | Directory::Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path & path) | 206 | Directory::Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, |
| 212 | : path(path), backend(std::move(backend)) {} | 207 | const FileSys::Path& path) |
| 208 | : path(path), backend(std::move(backend)) { | ||
| 209 | } | ||
| 213 | 210 | ||
| 214 | Directory::~Directory() {} | 211 | Directory::~Directory() { |
| 212 | } | ||
| 215 | 213 | ||
| 216 | ResultVal<bool> Directory::SyncRequest() { | 214 | ResultVal<bool> Directory::SyncRequest() { |
| 217 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 215 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 218 | DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); | 216 | DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); |
| 219 | switch (cmd) { | 217 | switch (cmd) { |
| 220 | 218 | ||
| 221 | // Read from directory... | 219 | // Read from directory... |
| 222 | case DirectoryCommand::Read: | 220 | case DirectoryCommand::Read: { |
| 223 | { | 221 | u32 count = cmd_buff[1]; |
| 224 | u32 count = cmd_buff[1]; | 222 | u32 address = cmd_buff[3]; |
| 225 | u32 address = cmd_buff[3]; | 223 | std::vector<FileSys::Entry> entries(count); |
| 226 | std::vector<FileSys::Entry> entries(count); | 224 | LOG_TRACE(Service_FS, "Read %s %s: count=%d", GetTypeName().c_str(), GetName().c_str(), |
| 227 | LOG_TRACE(Service_FS, "Read %s %s: count=%d", | 225 | count); |
| 228 | GetTypeName().c_str(), GetName().c_str(), count); | 226 | |
| 229 | 227 | // Number of entries actually read | |
| 230 | // Number of entries actually read | 228 | u32 read = backend->Read(entries.size(), entries.data()); |
| 231 | u32 read = backend->Read(entries.size(), entries.data()); | 229 | cmd_buff[2] = read; |
| 232 | cmd_buff[2] = read; | 230 | Memory::WriteBlock(address, entries.data(), read * sizeof(FileSys::Entry)); |
| 233 | Memory::WriteBlock(address, entries.data(), read * sizeof(FileSys::Entry)); | 231 | break; |
| 234 | break; | 232 | } |
| 235 | } | ||
| 236 | 233 | ||
| 237 | case DirectoryCommand::Close: | 234 | case DirectoryCommand::Close: { |
| 238 | { | 235 | LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); |
| 239 | LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); | 236 | backend->Close(); |
| 240 | backend->Close(); | 237 | break; |
| 241 | break; | 238 | } |
| 242 | } | ||
| 243 | 239 | ||
| 244 | // Unknown command... | 240 | // Unknown command... |
| 245 | default: | 241 | default: |
| 246 | LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); | 242 | LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); |
| 247 | ResultCode error = UnimplementedFunction(ErrorModule::FS); | 243 | ResultCode error = UnimplementedFunction(ErrorModule::FS); |
| 248 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. | 244 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. |
| 249 | return MakeResult<bool>(false); | 245 | return MakeResult<bool>(false); |
| 250 | } | 246 | } |
| 251 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 247 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 252 | return MakeResult<bool>(false); | 248 | return MakeResult<bool>(false); |
| @@ -280,8 +276,8 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi | |||
| 280 | auto itr = id_code_map.find(id_code); | 276 | auto itr = id_code_map.find(id_code); |
| 281 | if (itr == id_code_map.end()) { | 277 | if (itr == id_code_map.end()) { |
| 282 | // TODO: Verify error against hardware | 278 | // TODO: Verify error against hardware |
| 283 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, | 279 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, ErrorSummary::NotFound, |
| 284 | ErrorSummary::NotFound, ErrorLevel::Permanent); | 280 | ErrorLevel::Permanent); |
| 285 | } | 281 | } |
| 286 | 282 | ||
| 287 | CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path)); | 283 | CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path)); |
| @@ -303,19 +299,22 @@ ResultCode CloseArchive(ArchiveHandle handle) { | |||
| 303 | 299 | ||
| 304 | // TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in | 300 | // TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in |
| 305 | // http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22 | 301 | // http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22 |
| 306 | ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, ArchiveIdCode id_code) { | 302 | ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, |
| 303 | ArchiveIdCode id_code) { | ||
| 307 | auto result = id_code_map.emplace(id_code, std::move(factory)); | 304 | auto result = id_code_map.emplace(id_code, std::move(factory)); |
| 308 | 305 | ||
| 309 | bool inserted = result.second; | 306 | bool inserted = result.second; |
| 310 | ASSERT_MSG(inserted, "Tried to register more than one archive with same id code"); | 307 | ASSERT_MSG(inserted, "Tried to register more than one archive with same id code"); |
| 311 | 308 | ||
| 312 | auto& archive = result.first->second; | 309 | auto& archive = result.first->second; |
| 313 | LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(), id_code); | 310 | LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(), |
| 311 | id_code); | ||
| 314 | return RESULT_SUCCESS; | 312 | return RESULT_SUCCESS; |
| 315 | } | 313 | } |
| 316 | 314 | ||
| 317 | ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle, | 315 | ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle, |
| 318 | const FileSys::Path& path, const FileSys::Mode mode) { | 316 | const FileSys::Path& path, |
| 317 | const FileSys::Mode mode) { | ||
| 319 | ArchiveBackend* archive = GetArchive(archive_handle); | 318 | ArchiveBackend* archive = GetArchive(archive_handle); |
| 320 | if (archive == nullptr) | 319 | if (archive == nullptr) |
| 321 | return ERR_INVALID_ARCHIVE_HANDLE; | 320 | return ERR_INVALID_ARCHIVE_HANDLE; |
| @@ -336,8 +335,10 @@ ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Pa | |||
| 336 | return archive->DeleteFile(path); | 335 | return archive->DeleteFile(path); |
| 337 | } | 336 | } |
| 338 | 337 | ||
| 339 | ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, | 338 | ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, |
| 340 | ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { | 339 | const FileSys::Path& src_path, |
| 340 | ArchiveHandle dest_archive_handle, | ||
| 341 | const FileSys::Path& dest_path) { | ||
| 341 | ArchiveBackend* src_archive = GetArchive(src_archive_handle); | 342 | ArchiveBackend* src_archive = GetArchive(src_archive_handle); |
| 342 | ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); | 343 | ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); |
| 343 | if (src_archive == nullptr || dest_archive == nullptr) | 344 | if (src_archive == nullptr || dest_archive == nullptr) |
| @@ -368,7 +369,8 @@ ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy | |||
| 368 | ErrorSummary::Canceled, ErrorLevel::Status); | 369 | ErrorSummary::Canceled, ErrorLevel::Status); |
| 369 | } | 370 | } |
| 370 | 371 | ||
| 371 | ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u64 file_size) { | 372 | ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, |
| 373 | u64 file_size) { | ||
| 372 | ArchiveBackend* archive = GetArchive(archive_handle); | 374 | ArchiveBackend* archive = GetArchive(archive_handle); |
| 373 | if (archive == nullptr) | 375 | if (archive == nullptr) |
| 374 | return ERR_INVALID_ARCHIVE_HANDLE; | 376 | return ERR_INVALID_ARCHIVE_HANDLE; |
| @@ -387,8 +389,10 @@ ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy | |||
| 387 | ErrorSummary::Canceled, ErrorLevel::Status); | 389 | ErrorSummary::Canceled, ErrorLevel::Status); |
| 388 | } | 390 | } |
| 389 | 391 | ||
| 390 | ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, | 392 | ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, |
| 391 | ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { | 393 | const FileSys::Path& src_path, |
| 394 | ArchiveHandle dest_archive_handle, | ||
| 395 | const FileSys::Path& dest_path) { | ||
| 392 | ArchiveBackend* src_archive = GetArchive(src_archive_handle); | 396 | ArchiveBackend* src_archive = GetArchive(src_archive_handle); |
| 393 | ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); | 397 | ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); |
| 394 | if (src_archive == nullptr || dest_archive == nullptr) | 398 | if (src_archive == nullptr || dest_archive == nullptr) |
| @@ -409,15 +413,15 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons | |||
| 409 | } | 413 | } |
| 410 | 414 | ||
| 411 | ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, | 415 | ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, |
| 412 | const FileSys::Path& path) { | 416 | const FileSys::Path& path) { |
| 413 | ArchiveBackend* archive = GetArchive(archive_handle); | 417 | ArchiveBackend* archive = GetArchive(archive_handle); |
| 414 | if (archive == nullptr) | 418 | if (archive == nullptr) |
| 415 | return ERR_INVALID_ARCHIVE_HANDLE; | 419 | return ERR_INVALID_ARCHIVE_HANDLE; |
| 416 | 420 | ||
| 417 | std::unique_ptr<FileSys::DirectoryBackend> backend = archive->OpenDirectory(path); | 421 | std::unique_ptr<FileSys::DirectoryBackend> backend = archive->OpenDirectory(path); |
| 418 | if (backend == nullptr) { | 422 | if (backend == nullptr) { |
| 419 | return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, | 423 | return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound, |
| 420 | ErrorSummary::NotFound, ErrorLevel::Permanent); | 424 | ErrorLevel::Permanent); |
| 421 | } | 425 | } |
| 422 | 426 | ||
| 423 | auto directory = Kernel::SharedPtr<Directory>(new Directory(std::move(backend), path)); | 427 | auto directory = Kernel::SharedPtr<Directory>(new Directory(std::move(backend), path)); |
| @@ -431,7 +435,8 @@ ResultVal<u64> GetFreeBytesInArchive(ArchiveHandle archive_handle) { | |||
| 431 | return MakeResult<u64>(archive->GetFreeBytes()); | 435 | return MakeResult<u64>(archive->GetFreeBytes()); |
| 432 | } | 436 | } |
| 433 | 437 | ||
| 434 | ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info, const FileSys::Path& path) { | 438 | ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info, |
| 439 | const FileSys::Path& path) { | ||
| 435 | auto archive_itr = id_code_map.find(id_code); | 440 | auto archive_itr = id_code_map.find(id_code); |
| 436 | if (archive_itr == id_code_map.end()) { | 441 | if (archive_itr == id_code_map.end()) { |
| 437 | return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error | 442 | return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error |
| @@ -440,7 +445,8 @@ ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo | |||
| 440 | return archive_itr->second->Format(path, format_info); | 445 | return archive_itr->second->Format(path, format_info); |
| 441 | } | 446 | } |
| 442 | 447 | ||
| 443 | ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code, FileSys::Path& archive_path) { | 448 | ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code, |
| 449 | FileSys::Path& archive_path) { | ||
| 444 | auto archive = id_code_map.find(id_code); | 450 | auto archive = id_code_map.find(id_code); |
| 445 | if (archive == id_code_map.end()) { | 451 | if (archive == id_code_map.end()) { |
| 446 | return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error | 452 | return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error |
| @@ -449,11 +455,14 @@ ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code | |||
| 449 | return archive->second->GetFormatInfo(archive_path); | 455 | return archive->second->GetFormatInfo(archive_path); |
| 450 | } | 456 | } |
| 451 | 457 | ||
| 452 | ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, u32 icon_size, const FileSys::ArchiveFormatInfo& format_info) { | 458 | ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, |
| 459 | u32 icon_size, const FileSys::ArchiveFormatInfo& format_info) { | ||
| 453 | // Construct the binary path to the archive first | 460 | // Construct the binary path to the archive first |
| 454 | FileSys::Path path = FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low); | 461 | FileSys::Path path = |
| 462 | FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low); | ||
| 455 | 463 | ||
| 456 | auto archive = id_code_map.find(media_type == MediaType::NAND ? ArchiveIdCode::SharedExtSaveData : ArchiveIdCode::ExtSaveData); | 464 | auto archive = id_code_map.find(media_type == MediaType::NAND ? ArchiveIdCode::SharedExtSaveData |
| 465 | : ArchiveIdCode::ExtSaveData); | ||
| 457 | 466 | ||
| 458 | if (archive == id_code_map.end()) { | 467 | if (archive == id_code_map.end()) { |
| 459 | return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error | 468 | return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error |
| @@ -476,7 +485,8 @@ ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon | |||
| 476 | 485 | ||
| 477 | ResultCode DeleteExtSaveData(MediaType media_type, u32 high, u32 low) { | 486 | ResultCode DeleteExtSaveData(MediaType media_type, u32 high, u32 low) { |
| 478 | // Construct the binary path to the archive first | 487 | // Construct the binary path to the archive first |
| 479 | FileSys::Path path = FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low); | 488 | FileSys::Path path = |
| 489 | FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low); | ||
| 480 | 490 | ||
| 481 | std::string media_type_directory; | 491 | std::string media_type_directory; |
| 482 | if (media_type == MediaType::NAND) { | 492 | if (media_type == MediaType::NAND) { |
| @@ -489,7 +499,8 @@ ResultCode DeleteExtSaveData(MediaType media_type, u32 high, u32 low) { | |||
| 489 | } | 499 | } |
| 490 | 500 | ||
| 491 | // Delete all directories (/user, /boss) and the icon file. | 501 | // Delete all directories (/user, /boss) and the icon file. |
| 492 | std::string base_path = FileSys::GetExtDataContainerPath(media_type_directory, media_type == MediaType::NAND); | 502 | std::string base_path = |
| 503 | FileSys::GetExtDataContainerPath(media_type_directory, media_type == MediaType::NAND); | ||
| 493 | std::string extsavedata_path = FileSys::GetExtSaveDataPath(base_path, path); | 504 | std::string extsavedata_path = FileSys::GetExtSaveDataPath(base_path, path); |
| 494 | if (FileUtil::Exists(extsavedata_path) && !FileUtil::DeleteDirRecursively(extsavedata_path)) | 505 | if (FileUtil::Exists(extsavedata_path) && !FileUtil::DeleteDirRecursively(extsavedata_path)) |
| 495 | return ResultCode(-1); // TODO(Subv): Find the right error code | 506 | return ResultCode(-1); // TODO(Subv): Find the right error code |
| @@ -530,30 +541,36 @@ void RegisterArchiveTypes() { | |||
| 530 | if (sdmc_factory->Initialize()) | 541 | if (sdmc_factory->Initialize()) |
| 531 | RegisterArchiveType(std::move(sdmc_factory), ArchiveIdCode::SDMC); | 542 | RegisterArchiveType(std::move(sdmc_factory), ArchiveIdCode::SDMC); |
| 532 | else | 543 | else |
| 533 | LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); | 544 | LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", |
| 545 | sdmc_directory.c_str()); | ||
| 534 | 546 | ||
| 535 | // Create the SaveData archive | 547 | // Create the SaveData archive |
| 536 | auto savedata_factory = std::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory); | 548 | auto savedata_factory = std::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory); |
| 537 | RegisterArchiveType(std::move(savedata_factory), ArchiveIdCode::SaveData); | 549 | RegisterArchiveType(std::move(savedata_factory), ArchiveIdCode::SaveData); |
| 538 | 550 | ||
| 539 | auto extsavedata_factory = std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(sdmc_directory, false); | 551 | auto extsavedata_factory = |
| 552 | std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(sdmc_directory, false); | ||
| 540 | if (extsavedata_factory->Initialize()) | 553 | if (extsavedata_factory->Initialize()) |
| 541 | RegisterArchiveType(std::move(extsavedata_factory), ArchiveIdCode::ExtSaveData); | 554 | RegisterArchiveType(std::move(extsavedata_factory), ArchiveIdCode::ExtSaveData); |
| 542 | else | 555 | else |
| 543 | LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s", extsavedata_factory->GetMountPoint().c_str()); | 556 | LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s", |
| 557 | extsavedata_factory->GetMountPoint().c_str()); | ||
| 544 | 558 | ||
| 545 | auto sharedextsavedata_factory = std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(nand_directory, true); | 559 | auto sharedextsavedata_factory = |
| 560 | std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(nand_directory, true); | ||
| 546 | if (sharedextsavedata_factory->Initialize()) | 561 | if (sharedextsavedata_factory->Initialize()) |
| 547 | RegisterArchiveType(std::move(sharedextsavedata_factory), ArchiveIdCode::SharedExtSaveData); | 562 | RegisterArchiveType(std::move(sharedextsavedata_factory), ArchiveIdCode::SharedExtSaveData); |
| 548 | else | 563 | else |
| 549 | LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s", | 564 | LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s", |
| 550 | sharedextsavedata_factory->GetMountPoint().c_str()); | 565 | sharedextsavedata_factory->GetMountPoint().c_str()); |
| 551 | 566 | ||
| 552 | // Create the SaveDataCheck archive, basically a small variation of the RomFS archive | 567 | // Create the SaveDataCheck archive, basically a small variation of the RomFS archive |
| 553 | auto savedatacheck_factory = std::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory); | 568 | auto savedatacheck_factory = |
| 569 | std::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory); | ||
| 554 | RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck); | 570 | RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck); |
| 555 | 571 | ||
| 556 | auto systemsavedata_factory = std::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory); | 572 | auto systemsavedata_factory = |
| 573 | std::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory); | ||
| 557 | RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData); | 574 | RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData); |
| 558 | } | 575 | } |
| 559 | 576 | ||
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index f7a50a3a7..aad540ff9 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h | |||
| @@ -28,21 +28,18 @@ namespace FS { | |||
| 28 | 28 | ||
| 29 | /// Supported archive types | 29 | /// Supported archive types |
| 30 | enum class ArchiveIdCode : u32 { | 30 | enum class ArchiveIdCode : u32 { |
| 31 | RomFS = 0x00000003, | 31 | RomFS = 0x00000003, |
| 32 | SaveData = 0x00000004, | 32 | SaveData = 0x00000004, |
| 33 | ExtSaveData = 0x00000006, | 33 | ExtSaveData = 0x00000006, |
| 34 | SharedExtSaveData = 0x00000007, | 34 | SharedExtSaveData = 0x00000007, |
| 35 | SystemSaveData = 0x00000008, | 35 | SystemSaveData = 0x00000008, |
| 36 | SDMC = 0x00000009, | 36 | SDMC = 0x00000009, |
| 37 | SDMCWriteOnly = 0x0000000A, | 37 | SDMCWriteOnly = 0x0000000A, |
| 38 | SaveDataCheck = 0x2345678A, | 38 | SaveDataCheck = 0x2345678A, |
| 39 | }; | 39 | }; |
| 40 | 40 | ||
| 41 | /// Media types for the archives | 41 | /// Media types for the archives |
| 42 | enum class MediaType : u32 { | 42 | enum class MediaType : u32 { NAND = 0, SDMC = 1 }; |
| 43 | NAND = 0, | ||
| 44 | SDMC = 1 | ||
| 45 | }; | ||
| 46 | 43 | ||
| 47 | typedef u64 ArchiveHandle; | 44 | typedef u64 ArchiveHandle; |
| 48 | 45 | ||
| @@ -51,11 +48,13 @@ public: | |||
| 51 | File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path); | 48 | File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path); |
| 52 | ~File(); | 49 | ~File(); |
| 53 | 50 | ||
| 54 | std::string GetName() const override { return "Path: " + path.DebugStr(); } | 51 | std::string GetName() const override { |
| 52 | return "Path: " + path.DebugStr(); | ||
| 53 | } | ||
| 55 | ResultVal<bool> SyncRequest() override; | 54 | ResultVal<bool> SyncRequest() override; |
| 56 | 55 | ||
| 57 | FileSys::Path path; ///< Path of the file | 56 | FileSys::Path path; ///< Path of the file |
| 58 | u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means | 57 | u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means |
| 59 | std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface | 58 | std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface |
| 60 | }; | 59 | }; |
| 61 | 60 | ||
| @@ -64,10 +63,12 @@ public: | |||
| 64 | Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path); | 63 | Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path); |
| 65 | ~Directory(); | 64 | ~Directory(); |
| 66 | 65 | ||
| 67 | std::string GetName() const override { return "Directory: " + path.DebugStr(); } | 66 | std::string GetName() const override { |
| 67 | return "Directory: " + path.DebugStr(); | ||
| 68 | } | ||
| 68 | ResultVal<bool> SyncRequest() override; | 69 | ResultVal<bool> SyncRequest() override; |
| 69 | 70 | ||
| 70 | FileSys::Path path; ///< Path of the directory | 71 | FileSys::Path path; ///< Path of the directory |
| 71 | std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface | 72 | std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface |
| 72 | }; | 73 | }; |
| 73 | 74 | ||
| @@ -90,7 +91,8 @@ ResultCode CloseArchive(ArchiveHandle handle); | |||
| 90 | * @param factory File system backend interface to the archive | 91 | * @param factory File system backend interface to the archive |
| 91 | * @param id_code Id code used to access this type of archive | 92 | * @param id_code Id code used to access this type of archive |
| 92 | */ | 93 | */ |
| 93 | ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, ArchiveIdCode id_code); | 94 | ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, |
| 95 | ArchiveIdCode id_code); | ||
| 94 | 96 | ||
| 95 | /** | 97 | /** |
| 96 | * Open a File from an Archive | 98 | * Open a File from an Archive |
| @@ -100,7 +102,8 @@ ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factor | |||
| 100 | * @return The opened File object as a Session | 102 | * @return The opened File object as a Session |
| 101 | */ | 103 | */ |
| 102 | ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle, | 104 | ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle, |
| 103 | const FileSys::Path& path, const FileSys::Mode mode); | 105 | const FileSys::Path& path, |
| 106 | const FileSys::Mode mode); | ||
| 104 | 107 | ||
| 105 | /** | 108 | /** |
| 106 | * Delete a File from an Archive | 109 | * Delete a File from an Archive |
| @@ -118,8 +121,10 @@ ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Pa | |||
| 118 | * @param dest_path Path to the File inside of the destination Archive | 121 | * @param dest_path Path to the File inside of the destination Archive |
| 119 | * @return Whether rename succeeded | 122 | * @return Whether rename succeeded |
| 120 | */ | 123 | */ |
| 121 | ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, | 124 | ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, |
| 122 | ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path); | 125 | const FileSys::Path& src_path, |
| 126 | ArchiveHandle dest_archive_handle, | ||
| 127 | const FileSys::Path& dest_path); | ||
| 123 | 128 | ||
| 124 | /** | 129 | /** |
| 125 | * Delete a Directory from an Archive | 130 | * Delete a Directory from an Archive |
| @@ -136,7 +141,8 @@ ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy | |||
| 136 | * @param file_size The size of the new file, filled with zeroes | 141 | * @param file_size The size of the new file, filled with zeroes |
| 137 | * @return File creation result code | 142 | * @return File creation result code |
| 138 | */ | 143 | */ |
| 139 | ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u64 file_size); | 144 | ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, |
| 145 | u64 file_size); | ||
| 140 | 146 | ||
| 141 | /** | 147 | /** |
| 142 | * Create a Directory from an Archive | 148 | * Create a Directory from an Archive |
| @@ -154,8 +160,10 @@ ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy | |||
| 154 | * @param dest_path Path to the Directory inside of the destination Archive | 160 | * @param dest_path Path to the Directory inside of the destination Archive |
| 155 | * @return Whether rename succeeded | 161 | * @return Whether rename succeeded |
| 156 | */ | 162 | */ |
| 157 | ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, | 163 | ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, |
| 158 | ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path); | 164 | const FileSys::Path& src_path, |
| 165 | ArchiveHandle dest_archive_handle, | ||
| 166 | const FileSys::Path& dest_path); | ||
| 159 | 167 | ||
| 160 | /** | 168 | /** |
| 161 | * Open a Directory from an Archive | 169 | * Open a Directory from an Archive |
| @@ -164,7 +172,7 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons | |||
| 164 | * @return The opened Directory object as a Session | 172 | * @return The opened Directory object as a Session |
| 165 | */ | 173 | */ |
| 166 | ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, | 174 | ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, |
| 167 | const FileSys::Path& path); | 175 | const FileSys::Path& path); |
| 168 | 176 | ||
| 169 | /** | 177 | /** |
| 170 | * Get the free space in an Archive | 178 | * Get the free space in an Archive |
| @@ -181,7 +189,8 @@ ResultVal<u64> GetFreeBytesInArchive(ArchiveHandle archive_handle); | |||
| 181 | * @param path The path to the archive, if relevant. | 189 | * @param path The path to the archive, if relevant. |
| 182 | * @return ResultCode 0 on success or the corresponding code on error | 190 | * @return ResultCode 0 on success or the corresponding code on error |
| 183 | */ | 191 | */ |
| 184 | ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info, const FileSys::Path& path = FileSys::Path()); | 192 | ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info, |
| 193 | const FileSys::Path& path = FileSys::Path()); | ||
| 185 | 194 | ||
| 186 | /** | 195 | /** |
| 187 | * Retrieves the format info about the archive of the specified type and path. | 196 | * Retrieves the format info about the archive of the specified type and path. |
| @@ -190,7 +199,8 @@ ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo | |||
| 190 | * @param archive_path The path of the archive, if relevant | 199 | * @param archive_path The path of the archive, if relevant |
| 191 | * @return The format info of the archive, or the corresponding error code if failed. | 200 | * @return The format info of the archive, or the corresponding error code if failed. |
| 192 | */ | 201 | */ |
| 193 | ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code, FileSys::Path& archive_path); | 202 | ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code, |
| 203 | FileSys::Path& archive_path); | ||
| 194 | 204 | ||
| 195 | /** | 205 | /** |
| 196 | * Creates a blank SharedExtSaveData archive for the specified extdata ID | 206 | * Creates a blank SharedExtSaveData archive for the specified extdata ID |
| @@ -202,7 +212,8 @@ ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code | |||
| 202 | * @param format_info Format information about the new archive | 212 | * @param format_info Format information about the new archive |
| 203 | * @return ResultCode 0 on success or the corresponding code on error | 213 | * @return ResultCode 0 on success or the corresponding code on error |
| 204 | */ | 214 | */ |
| 205 | ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, u32 icon_size, const FileSys::ArchiveFormatInfo& format_info); | 215 | ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, |
| 216 | u32 icon_size, const FileSys::ArchiveFormatInfo& format_info); | ||
| 206 | 217 | ||
| 207 | /** | 218 | /** |
| 208 | * Deletes the SharedExtSaveData archive for the specified extdata ID | 219 | * Deletes the SharedExtSaveData archive for the specified extdata ID |
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index 937868747..a0adad634 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp | |||
| @@ -57,14 +57,16 @@ static void OpenFile(Service::Interface* self) { | |||
| 57 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 57 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 58 | 58 | ||
| 59 | ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); | 59 | ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); |
| 60 | auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); | 60 | auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); |
| 61 | u32 filename_size = cmd_buff[5]; | 61 | u32 filename_size = cmd_buff[5]; |
| 62 | FileSys::Mode mode; mode.hex = cmd_buff[6]; | 62 | FileSys::Mode mode; |
| 63 | u32 attributes = cmd_buff[7]; // TODO(Link Mauve): do something with those attributes. | 63 | mode.hex = cmd_buff[6]; |
| 64 | u32 filename_ptr = cmd_buff[9]; | 64 | u32 attributes = cmd_buff[7]; // TODO(Link Mauve): do something with those attributes. |
| 65 | u32 filename_ptr = cmd_buff[9]; | ||
| 65 | FileSys::Path file_path(filename_type, filename_size, filename_ptr); | 66 | FileSys::Path file_path(filename_type, filename_size, filename_ptr); |
| 66 | 67 | ||
| 67 | LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); | 68 | LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, |
| 69 | attributes); | ||
| 68 | 70 | ||
| 69 | ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(archive_handle, file_path, mode); | 71 | ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(archive_handle, file_path, mode); |
| 70 | cmd_buff[1] = file_res.Code().raw; | 72 | cmd_buff[1] = file_res.Code().raw; |
| @@ -98,24 +100,27 @@ static void OpenFile(Service::Interface* self) { | |||
| 98 | static void OpenFileDirectly(Service::Interface* self) { | 100 | static void OpenFileDirectly(Service::Interface* self) { |
| 99 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 101 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 100 | 102 | ||
| 101 | auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[2]); | 103 | auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[2]); |
| 102 | auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[3]); | 104 | auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[3]); |
| 103 | u32 archivename_size = cmd_buff[4]; | 105 | u32 archivename_size = cmd_buff[4]; |
| 104 | auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[5]); | 106 | auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[5]); |
| 105 | u32 filename_size = cmd_buff[6]; | 107 | u32 filename_size = cmd_buff[6]; |
| 106 | FileSys::Mode mode; mode.hex = cmd_buff[7]; | 108 | FileSys::Mode mode; |
| 107 | u32 attributes = cmd_buff[8]; // TODO(Link Mauve): do something with those attributes. | 109 | mode.hex = cmd_buff[7]; |
| 108 | u32 archivename_ptr = cmd_buff[10]; | 110 | u32 attributes = cmd_buff[8]; // TODO(Link Mauve): do something with those attributes. |
| 109 | u32 filename_ptr = cmd_buff[12]; | 111 | u32 archivename_ptr = cmd_buff[10]; |
| 112 | u32 filename_ptr = cmd_buff[12]; | ||
| 110 | FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); | 113 | FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); |
| 111 | FileSys::Path file_path(filename_type, filename_size, filename_ptr); | 114 | FileSys::Path file_path(filename_type, filename_size, filename_ptr); |
| 112 | 115 | ||
| 113 | LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s file_path=%s, mode=%u attributes=%d", | 116 | LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s file_path=%s, mode=%u attributes=%d", |
| 114 | archive_id, archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode.hex, attributes); | 117 | archive_id, archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode.hex, |
| 118 | attributes); | ||
| 115 | 119 | ||
| 116 | ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id, archive_path); | 120 | ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id, archive_path); |
| 117 | if (archive_handle.Failed()) { | 121 | if (archive_handle.Failed()) { |
| 118 | LOG_ERROR(Service_FS, "failed to get a handle for archive archive_id=0x%08X archive_path=%s", | 122 | LOG_ERROR(Service_FS, |
| 123 | "failed to get a handle for archive archive_id=0x%08X archive_path=%s", | ||
| 119 | archive_id, archive_path.DebugStr().c_str()); | 124 | archive_id, archive_path.DebugStr().c_str()); |
| 120 | cmd_buff[1] = archive_handle.Code().raw; | 125 | cmd_buff[1] = archive_handle.Code().raw; |
| 121 | cmd_buff[3] = 0; | 126 | cmd_buff[3] = 0; |
| @@ -149,14 +154,14 @@ static void DeleteFile(Service::Interface* self) { | |||
| 149 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 154 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 150 | 155 | ||
| 151 | ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); | 156 | ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); |
| 152 | auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); | 157 | auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); |
| 153 | u32 filename_size = cmd_buff[5]; | 158 | u32 filename_size = cmd_buff[5]; |
| 154 | u32 filename_ptr = cmd_buff[7]; | 159 | u32 filename_ptr = cmd_buff[7]; |
| 155 | 160 | ||
| 156 | FileSys::Path file_path(filename_type, filename_size, filename_ptr); | 161 | FileSys::Path file_path(filename_type, filename_size, filename_ptr); |
| 157 | 162 | ||
| 158 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", | 163 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", filename_type, filename_size, |
| 159 | filename_type, filename_size, file_path.DebugStr().c_str()); | 164 | file_path.DebugStr().c_str()); |
| 160 | 165 | ||
| 161 | cmd_buff[1] = DeleteFileFromArchive(archive_handle, file_path).raw; | 166 | cmd_buff[1] = DeleteFileFromArchive(archive_handle, file_path).raw; |
| 162 | } | 167 | } |
| @@ -181,22 +186,26 @@ static void RenameFile(Service::Interface* self) { | |||
| 181 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 186 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 182 | 187 | ||
| 183 | ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); | 188 | ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); |
| 184 | auto src_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); | 189 | auto src_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); |
| 185 | u32 src_filename_size = cmd_buff[5]; | 190 | u32 src_filename_size = cmd_buff[5]; |
| 186 | ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]);; | 191 | ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]); |
| 187 | auto dest_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[8]); | 192 | ; |
| 188 | u32 dest_filename_size = cmd_buff[9]; | 193 | auto dest_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[8]); |
| 189 | u32 src_filename_ptr = cmd_buff[11]; | 194 | u32 dest_filename_size = cmd_buff[9]; |
| 190 | u32 dest_filename_ptr = cmd_buff[13]; | 195 | u32 src_filename_ptr = cmd_buff[11]; |
| 196 | u32 dest_filename_ptr = cmd_buff[13]; | ||
| 191 | 197 | ||
| 192 | FileSys::Path src_file_path(src_filename_type, src_filename_size, src_filename_ptr); | 198 | FileSys::Path src_file_path(src_filename_type, src_filename_size, src_filename_ptr); |
| 193 | FileSys::Path dest_file_path(dest_filename_type, dest_filename_size, dest_filename_ptr); | 199 | FileSys::Path dest_file_path(dest_filename_type, dest_filename_size, dest_filename_ptr); |
| 194 | 200 | ||
| 195 | LOG_DEBUG(Service_FS, "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s", | 201 | LOG_DEBUG(Service_FS, |
| 202 | "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s", | ||
| 196 | src_filename_type, src_filename_size, src_file_path.DebugStr().c_str(), | 203 | src_filename_type, src_filename_size, src_file_path.DebugStr().c_str(), |
| 197 | dest_filename_type, dest_filename_size, dest_file_path.DebugStr().c_str()); | 204 | dest_filename_type, dest_filename_size, dest_file_path.DebugStr().c_str()); |
| 198 | 205 | ||
| 199 | cmd_buff[1] = RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle, dest_file_path).raw; | 206 | cmd_buff[1] = RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle, |
| 207 | dest_file_path) | ||
| 208 | .raw; | ||
| 200 | } | 209 | } |
| 201 | 210 | ||
| 202 | /* | 211 | /* |
| @@ -214,14 +223,14 @@ static void DeleteDirectory(Service::Interface* self) { | |||
| 214 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 223 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 215 | 224 | ||
| 216 | ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); | 225 | ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); |
| 217 | auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); | 226 | auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); |
| 218 | u32 dirname_size = cmd_buff[5]; | 227 | u32 dirname_size = cmd_buff[5]; |
| 219 | u32 dirname_ptr = cmd_buff[7]; | 228 | u32 dirname_ptr = cmd_buff[7]; |
| 220 | 229 | ||
| 221 | FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); | 230 | FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); |
| 222 | 231 | ||
| 223 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", | 232 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, |
| 224 | dirname_type, dirname_size, dir_path.DebugStr().c_str()); | 233 | dir_path.DebugStr().c_str()); |
| 225 | 234 | ||
| 226 | cmd_buff[1] = DeleteDirectoryFromArchive(archive_handle, dir_path).raw; | 235 | cmd_buff[1] = DeleteDirectoryFromArchive(archive_handle, dir_path).raw; |
| 227 | } | 236 | } |
| @@ -243,14 +252,15 @@ static void CreateFile(Service::Interface* self) { | |||
| 243 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 252 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 244 | 253 | ||
| 245 | ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); | 254 | ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); |
| 246 | auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); | 255 | auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); |
| 247 | u32 filename_size = cmd_buff[5]; | 256 | u32 filename_size = cmd_buff[5]; |
| 248 | u64 file_size = ((u64)cmd_buff[8] << 32) | cmd_buff[7]; | 257 | u64 file_size = ((u64)cmd_buff[8] << 32) | cmd_buff[7]; |
| 249 | u32 filename_ptr = cmd_buff[10]; | 258 | u32 filename_ptr = cmd_buff[10]; |
| 250 | 259 | ||
| 251 | FileSys::Path file_path(filename_type, filename_size, filename_ptr); | 260 | FileSys::Path file_path(filename_type, filename_size, filename_ptr); |
| 252 | 261 | ||
| 253 | LOG_DEBUG(Service_FS, "type=%d size=%llu data=%s", filename_type, file_size, file_path.DebugStr().c_str()); | 262 | LOG_DEBUG(Service_FS, "type=%d size=%llu data=%s", filename_type, file_size, |
| 263 | file_path.DebugStr().c_str()); | ||
| 254 | 264 | ||
| 255 | cmd_buff[1] = CreateFileInArchive(archive_handle, file_path, file_size).raw; | 265 | cmd_buff[1] = CreateFileInArchive(archive_handle, file_path, file_size).raw; |
| 256 | } | 266 | } |
| @@ -276,7 +286,8 @@ static void CreateDirectory(Service::Interface* self) { | |||
| 276 | 286 | ||
| 277 | FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); | 287 | FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); |
| 278 | 288 | ||
| 279 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); | 289 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, |
| 290 | dir_path.DebugStr().c_str()); | ||
| 280 | 291 | ||
| 281 | cmd_buff[1] = CreateDirectoryFromArchive(archive_handle, dir_path).raw; | 292 | cmd_buff[1] = CreateDirectoryFromArchive(archive_handle, dir_path).raw; |
| 282 | } | 293 | } |
| @@ -301,22 +312,25 @@ static void RenameDirectory(Service::Interface* self) { | |||
| 301 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 312 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 302 | 313 | ||
| 303 | ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); | 314 | ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); |
| 304 | auto src_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); | 315 | auto src_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); |
| 305 | u32 src_dirname_size = cmd_buff[5]; | 316 | u32 src_dirname_size = cmd_buff[5]; |
| 306 | ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]); | 317 | ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]); |
| 307 | auto dest_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[8]); | 318 | auto dest_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[8]); |
| 308 | u32 dest_dirname_size = cmd_buff[9]; | 319 | u32 dest_dirname_size = cmd_buff[9]; |
| 309 | u32 src_dirname_ptr = cmd_buff[11]; | 320 | u32 src_dirname_ptr = cmd_buff[11]; |
| 310 | u32 dest_dirname_ptr = cmd_buff[13]; | 321 | u32 dest_dirname_ptr = cmd_buff[13]; |
| 311 | 322 | ||
| 312 | FileSys::Path src_dir_path(src_dirname_type, src_dirname_size, src_dirname_ptr); | 323 | FileSys::Path src_dir_path(src_dirname_type, src_dirname_size, src_dirname_ptr); |
| 313 | FileSys::Path dest_dir_path(dest_dirname_type, dest_dirname_size, dest_dirname_ptr); | 324 | FileSys::Path dest_dir_path(dest_dirname_type, dest_dirname_size, dest_dirname_ptr); |
| 314 | 325 | ||
| 315 | LOG_DEBUG(Service_FS, "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s", | 326 | LOG_DEBUG(Service_FS, |
| 327 | "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s", | ||
| 316 | src_dirname_type, src_dirname_size, src_dir_path.DebugStr().c_str(), | 328 | src_dirname_type, src_dirname_size, src_dir_path.DebugStr().c_str(), |
| 317 | dest_dirname_type, dest_dirname_size, dest_dir_path.DebugStr().c_str()); | 329 | dest_dirname_type, dest_dirname_size, dest_dir_path.DebugStr().c_str()); |
| 318 | 330 | ||
| 319 | cmd_buff[1] = RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path, dest_archive_handle, dest_dir_path).raw; | 331 | cmd_buff[1] = RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path, |
| 332 | dest_archive_handle, dest_dir_path) | ||
| 333 | .raw; | ||
| 320 | } | 334 | } |
| 321 | 335 | ||
| 322 | /** | 336 | /** |
| @@ -342,7 +356,8 @@ static void OpenDirectory(Service::Interface* self) { | |||
| 342 | 356 | ||
| 343 | FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); | 357 | FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); |
| 344 | 358 | ||
| 345 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); | 359 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, |
| 360 | dir_path.DebugStr().c_str()); | ||
| 346 | 361 | ||
| 347 | ResultVal<SharedPtr<Directory>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path); | 362 | ResultVal<SharedPtr<Directory>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path); |
| 348 | cmd_buff[1] = dir_res.Code().raw; | 363 | cmd_buff[1] = dir_res.Code().raw; |
| @@ -370,13 +385,14 @@ static void OpenDirectory(Service::Interface* self) { | |||
| 370 | static void OpenArchive(Service::Interface* self) { | 385 | static void OpenArchive(Service::Interface* self) { |
| 371 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 386 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 372 | 387 | ||
| 373 | auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[1]); | 388 | auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[1]); |
| 374 | auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]); | 389 | auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]); |
| 375 | u32 archivename_size = cmd_buff[3]; | 390 | u32 archivename_size = cmd_buff[3]; |
| 376 | u32 archivename_ptr = cmd_buff[5]; | 391 | u32 archivename_ptr = cmd_buff[5]; |
| 377 | FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); | 392 | FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); |
| 378 | 393 | ||
| 379 | LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s", archive_id, archive_path.DebugStr().c_str()); | 394 | LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s", archive_id, |
| 395 | archive_path.DebugStr().c_str()); | ||
| 380 | 396 | ||
| 381 | ResultVal<ArchiveHandle> handle = OpenArchive(archive_id, archive_path); | 397 | ResultVal<ArchiveHandle> handle = OpenArchive(archive_id, archive_path); |
| 382 | cmd_buff[1] = handle.Code().raw; | 398 | cmd_buff[1] = handle.Code().raw; |
| @@ -385,7 +401,8 @@ static void OpenArchive(Service::Interface* self) { | |||
| 385 | cmd_buff[3] = (*handle >> 32) & 0xFFFFFFFF; | 401 | cmd_buff[3] = (*handle >> 32) & 0xFFFFFFFF; |
| 386 | } else { | 402 | } else { |
| 387 | cmd_buff[2] = cmd_buff[3] = 0; | 403 | cmd_buff[2] = cmd_buff[3] = 0; |
| 388 | LOG_ERROR(Service_FS, "failed to get a handle for archive archive_id=0x%08X archive_path=%s", | 404 | LOG_ERROR(Service_FS, |
| 405 | "failed to get a handle for archive archive_id=0x%08X archive_path=%s", | ||
| 389 | archive_id, archive_path.DebugStr().c_str()); | 406 | archive_id, archive_path.DebugStr().c_str()); |
| 390 | } | 407 | } |
| 391 | } | 408 | } |
| @@ -471,7 +488,8 @@ static void FormatSaveData(Service::Interface* self) { | |||
| 471 | if (archive_id != FS::ArchiveIdCode::SaveData) { | 488 | if (archive_id != FS::ArchiveIdCode::SaveData) { |
| 472 | LOG_ERROR(Service_FS, "tried to format an archive different than SaveData, %u", archive_id); | 489 | LOG_ERROR(Service_FS, "tried to format an archive different than SaveData, %u", archive_id); |
| 473 | cmd_buff[1] = ResultCode(ErrorDescription::FS_InvalidPath, ErrorModule::FS, | 490 | cmd_buff[1] = ResultCode(ErrorDescription::FS_InvalidPath, ErrorModule::FS, |
| 474 | ErrorSummary::InvalidArgument, ErrorLevel::Usage).raw; | 491 | ErrorSummary::InvalidArgument, ErrorLevel::Usage) |
| 492 | .raw; | ||
| 475 | return; | 493 | return; |
| 476 | } | 494 | } |
| 477 | 495 | ||
| @@ -571,18 +589,21 @@ static void CreateExtSaveData(Service::Interface* self) { | |||
| 571 | u32 icon_size = cmd_buff[9]; | 589 | u32 icon_size = cmd_buff[9]; |
| 572 | VAddr icon_buffer = cmd_buff[11]; | 590 | VAddr icon_buffer = cmd_buff[11]; |
| 573 | 591 | ||
| 574 | LOG_WARNING(Service_FS, "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X " | 592 | LOG_WARNING( |
| 575 | "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X " | 593 | Service_FS, |
| 576 | "icon_size=%08X icon_descriptor=%08X icon_buffer=%08X", save_high, save_low, | 594 | "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X " |
| 577 | cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7], cmd_buff[8], icon_size, | 595 | "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X " |
| 578 | cmd_buff[10], icon_buffer); | 596 | "icon_size=%08X icon_descriptor=%08X icon_buffer=%08X", |
| 597 | save_high, save_low, cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7], | ||
| 598 | cmd_buff[8], icon_size, cmd_buff[10], icon_buffer); | ||
| 579 | 599 | ||
| 580 | FileSys::ArchiveFormatInfo format_info; | 600 | FileSys::ArchiveFormatInfo format_info; |
| 581 | format_info.number_directories = cmd_buff[5]; | 601 | format_info.number_directories = cmd_buff[5]; |
| 582 | format_info.number_files = cmd_buff[6]; | 602 | format_info.number_files = cmd_buff[6]; |
| 583 | format_info.duplicate_data = false; | 603 | format_info.duplicate_data = false; |
| 584 | format_info.total_size = 0; | 604 | format_info.total_size = 0; |
| 585 | cmd_buff[1] = CreateExtSaveData(media_type, save_high, save_low, icon_buffer, icon_size, format_info).raw; | 605 | cmd_buff[1] = |
| 606 | CreateExtSaveData(media_type, save_high, save_low, icon_buffer, icon_size, format_info).raw; | ||
| 586 | } | 607 | } |
| 587 | 608 | ||
| 588 | /** | 609 | /** |
| @@ -604,7 +625,7 @@ static void DeleteExtSaveData(Service::Interface* self) { | |||
| 604 | u32 unknown = cmd_buff[4]; // TODO(Subv): Figure out what this is | 625 | u32 unknown = cmd_buff[4]; // TODO(Subv): Figure out what this is |
| 605 | 626 | ||
| 606 | LOG_WARNING(Service_FS, "(STUBBED) save_low=%08X save_high=%08X media_type=%08X unknown=%08X", | 627 | LOG_WARNING(Service_FS, "(STUBBED) save_low=%08X save_high=%08X media_type=%08X unknown=%08X", |
| 607 | save_low, save_high, cmd_buff[1] & 0xFF, unknown); | 628 | save_low, save_high, cmd_buff[1] & 0xFF, unknown); |
| 608 | 629 | ||
| 609 | cmd_buff[1] = DeleteExtSaveData(media_type, save_high, save_low).raw; | 630 | cmd_buff[1] = DeleteExtSaveData(media_type, save_high, save_low).raw; |
| 610 | } | 631 | } |
| @@ -662,10 +683,13 @@ static void CreateSystemSaveData(Service::Interface* self) { | |||
| 662 | u32 savedata_high = cmd_buff[1]; | 683 | u32 savedata_high = cmd_buff[1]; |
| 663 | u32 savedata_low = cmd_buff[2]; | 684 | u32 savedata_low = cmd_buff[2]; |
| 664 | 685 | ||
| 665 | LOG_WARNING(Service_FS, "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X " | 686 | LOG_WARNING( |
| 666 | "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X " | 687 | Service_FS, |
| 667 | "cmd_buff[9]=%08X", savedata_high, savedata_low, cmd_buff[3], cmd_buff[4], cmd_buff[5], | 688 | "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X " |
| 668 | cmd_buff[6], cmd_buff[7], cmd_buff[8], cmd_buff[9]); | 689 | "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X " |
| 690 | "cmd_buff[9]=%08X", | ||
| 691 | savedata_high, savedata_low, cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], | ||
| 692 | cmd_buff[7], cmd_buff[8], cmd_buff[9]); | ||
| 669 | 693 | ||
| 670 | cmd_buff[1] = CreateSystemSaveData(savedata_high, savedata_low).raw; | 694 | cmd_buff[1] = CreateSystemSaveData(savedata_high, savedata_low).raw; |
| 671 | } | 695 | } |
| @@ -692,10 +716,13 @@ static void CreateLegacySystemSaveData(Service::Interface* self) { | |||
| 692 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 716 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 693 | u32 savedata_id = cmd_buff[1]; | 717 | u32 savedata_id = cmd_buff[1]; |
| 694 | 718 | ||
| 695 | LOG_WARNING(Service_FS, "(STUBBED) savedata_id=%08X cmd_buff[3]=%08X " | 719 | LOG_WARNING( |
| 696 | "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X " | 720 | Service_FS, |
| 697 | "cmd_buff[9]=%08X", savedata_id, cmd_buff[3], cmd_buff[4], cmd_buff[5], | 721 | "(STUBBED) savedata_id=%08X cmd_buff[3]=%08X " |
| 698 | cmd_buff[6], cmd_buff[7], cmd_buff[8], cmd_buff[9]); | 722 | "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X " |
| 723 | "cmd_buff[9]=%08X", | ||
| 724 | savedata_id, cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7], cmd_buff[8], | ||
| 725 | cmd_buff[9]); | ||
| 699 | 726 | ||
| 700 | cmd_buff[0] = IPC::MakeHeader(0x810, 0x1, 0); | 727 | cmd_buff[0] = IPC::MakeHeader(0x810, 0x1, 0); |
| 701 | // With this command, the SystemSaveData always has save_high = 0 (Always created in the NAND) | 728 | // With this command, the SystemSaveData always has save_high = 0 (Always created in the NAND) |
| @@ -721,8 +748,8 @@ static void InitializeWithSdkVersion(Service::Interface* self) { | |||
| 721 | 748 | ||
| 722 | cmd_buff[1] = RESULT_SUCCESS.raw; | 749 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 723 | 750 | ||
| 724 | LOG_WARNING(Service_FS, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, unk3=0x%08X", | 751 | LOG_WARNING(Service_FS, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, unk3=0x%08X", unk1, unk2, |
| 725 | unk1, unk2, unk3); | 752 | unk3); |
| 726 | } | 753 | } |
| 727 | 754 | ||
| 728 | /** | 755 | /** |
| @@ -834,115 +861,114 @@ static void GetFormatInfo(Service::Interface* self) { | |||
| 834 | } | 861 | } |
| 835 | 862 | ||
| 836 | const Interface::FunctionInfo FunctionTable[] = { | 863 | const Interface::FunctionInfo FunctionTable[] = { |
| 837 | {0x000100C6, nullptr, "Dummy1"}, | 864 | {0x000100C6, nullptr, "Dummy1"}, |
| 838 | {0x040100C4, nullptr, "Control"}, | 865 | {0x040100C4, nullptr, "Control"}, |
| 839 | {0x08010002, Initialize, "Initialize"}, | 866 | {0x08010002, Initialize, "Initialize"}, |
| 840 | {0x080201C2, OpenFile, "OpenFile"}, | 867 | {0x080201C2, OpenFile, "OpenFile"}, |
| 841 | {0x08030204, OpenFileDirectly, "OpenFileDirectly"}, | 868 | {0x08030204, OpenFileDirectly, "OpenFileDirectly"}, |
| 842 | {0x08040142, DeleteFile, "DeleteFile"}, | 869 | {0x08040142, DeleteFile, "DeleteFile"}, |
| 843 | {0x08050244, RenameFile, "RenameFile"}, | 870 | {0x08050244, RenameFile, "RenameFile"}, |
| 844 | {0x08060142, DeleteDirectory, "DeleteDirectory"}, | 871 | {0x08060142, DeleteDirectory, "DeleteDirectory"}, |
| 845 | {0x08070142, nullptr, "DeleteDirectoryRecursively"}, | 872 | {0x08070142, nullptr, "DeleteDirectoryRecursively"}, |
| 846 | {0x08080202, CreateFile, "CreateFile"}, | 873 | {0x08080202, CreateFile, "CreateFile"}, |
| 847 | {0x08090182, CreateDirectory, "CreateDirectory"}, | 874 | {0x08090182, CreateDirectory, "CreateDirectory"}, |
| 848 | {0x080A0244, RenameDirectory, "RenameDirectory"}, | 875 | {0x080A0244, RenameDirectory, "RenameDirectory"}, |
| 849 | {0x080B0102, OpenDirectory, "OpenDirectory"}, | 876 | {0x080B0102, OpenDirectory, "OpenDirectory"}, |
| 850 | {0x080C00C2, OpenArchive, "OpenArchive"}, | 877 | {0x080C00C2, OpenArchive, "OpenArchive"}, |
| 851 | {0x080D0144, nullptr, "ControlArchive"}, | 878 | {0x080D0144, nullptr, "ControlArchive"}, |
| 852 | {0x080E0080, CloseArchive, "CloseArchive"}, | 879 | {0x080E0080, CloseArchive, "CloseArchive"}, |
| 853 | {0x080F0180, FormatThisUserSaveData, "FormatThisUserSaveData"}, | 880 | {0x080F0180, FormatThisUserSaveData, "FormatThisUserSaveData"}, |
| 854 | {0x08100200, CreateLegacySystemSaveData, "CreateLegacySystemSaveData"}, | 881 | {0x08100200, CreateLegacySystemSaveData, "CreateLegacySystemSaveData"}, |
| 855 | {0x08110040, nullptr, "DeleteSystemSaveData"}, | 882 | {0x08110040, nullptr, "DeleteSystemSaveData"}, |
| 856 | {0x08120080, GetFreeBytes, "GetFreeBytes"}, | 883 | {0x08120080, GetFreeBytes, "GetFreeBytes"}, |
| 857 | {0x08130000, nullptr, "GetCardType"}, | 884 | {0x08130000, nullptr, "GetCardType"}, |
| 858 | {0x08140000, nullptr, "GetSdmcArchiveResource"}, | 885 | {0x08140000, nullptr, "GetSdmcArchiveResource"}, |
| 859 | {0x08150000, nullptr, "GetNandArchiveResource"}, | 886 | {0x08150000, nullptr, "GetNandArchiveResource"}, |
| 860 | {0x08160000, nullptr, "GetSdmcFatfsError"}, | 887 | {0x08160000, nullptr, "GetSdmcFatfsError"}, |
| 861 | {0x08170000, IsSdmcDetected, "IsSdmcDetected"}, | 888 | {0x08170000, IsSdmcDetected, "IsSdmcDetected"}, |
| 862 | {0x08180000, IsSdmcWriteable, "IsSdmcWritable"}, | 889 | {0x08180000, IsSdmcWriteable, "IsSdmcWritable"}, |
| 863 | {0x08190042, nullptr, "GetSdmcCid"}, | 890 | {0x08190042, nullptr, "GetSdmcCid"}, |
| 864 | {0x081A0042, nullptr, "GetNandCid"}, | 891 | {0x081A0042, nullptr, "GetNandCid"}, |
| 865 | {0x081B0000, nullptr, "GetSdmcSpeedInfo"}, | 892 | {0x081B0000, nullptr, "GetSdmcSpeedInfo"}, |
| 866 | {0x081C0000, nullptr, "GetNandSpeedInfo"}, | 893 | {0x081C0000, nullptr, "GetNandSpeedInfo"}, |
| 867 | {0x081D0042, nullptr, "GetSdmcLog"}, | 894 | {0x081D0042, nullptr, "GetSdmcLog"}, |
| 868 | {0x081E0042, nullptr, "GetNandLog"}, | 895 | {0x081E0042, nullptr, "GetNandLog"}, |
| 869 | {0x081F0000, nullptr, "ClearSdmcLog"}, | 896 | {0x081F0000, nullptr, "ClearSdmcLog"}, |
| 870 | {0x08200000, nullptr, "ClearNandLog"}, | 897 | {0x08200000, nullptr, "ClearNandLog"}, |
| 871 | {0x08210000, CardSlotIsInserted, "CardSlotIsInserted"}, | 898 | {0x08210000, CardSlotIsInserted, "CardSlotIsInserted"}, |
| 872 | {0x08220000, nullptr, "CardSlotPowerOn"}, | 899 | {0x08220000, nullptr, "CardSlotPowerOn"}, |
| 873 | {0x08230000, nullptr, "CardSlotPowerOff"}, | 900 | {0x08230000, nullptr, "CardSlotPowerOff"}, |
| 874 | {0x08240000, nullptr, "CardSlotGetCardIFPowerStatus"}, | 901 | {0x08240000, nullptr, "CardSlotGetCardIFPowerStatus"}, |
| 875 | {0x08250040, nullptr, "CardNorDirectCommand"}, | 902 | {0x08250040, nullptr, "CardNorDirectCommand"}, |
| 876 | {0x08260080, nullptr, "CardNorDirectCommandWithAddress"}, | 903 | {0x08260080, nullptr, "CardNorDirectCommandWithAddress"}, |
| 877 | {0x08270082, nullptr, "CardNorDirectRead"}, | 904 | {0x08270082, nullptr, "CardNorDirectRead"}, |
| 878 | {0x082800C2, nullptr, "CardNorDirectReadWithAddress"}, | 905 | {0x082800C2, nullptr, "CardNorDirectReadWithAddress"}, |
| 879 | {0x08290082, nullptr, "CardNorDirectWrite"}, | 906 | {0x08290082, nullptr, "CardNorDirectWrite"}, |
| 880 | {0x082A00C2, nullptr, "CardNorDirectWriteWithAddress"}, | 907 | {0x082A00C2, nullptr, "CardNorDirectWriteWithAddress"}, |
| 881 | {0x082B00C2, nullptr, "CardNorDirectRead_4xIO"}, | 908 | {0x082B00C2, nullptr, "CardNorDirectRead_4xIO"}, |
| 882 | {0x082C0082, nullptr, "CardNorDirectCpuWriteWithoutVerify"}, | 909 | {0x082C0082, nullptr, "CardNorDirectCpuWriteWithoutVerify"}, |
| 883 | {0x082D0040, nullptr, "CardNorDirectSectorEraseWithoutVerify"}, | 910 | {0x082D0040, nullptr, "CardNorDirectSectorEraseWithoutVerify"}, |
| 884 | {0x082E0040, nullptr, "GetProductInfo"}, | 911 | {0x082E0040, nullptr, "GetProductInfo"}, |
| 885 | {0x082F0040, nullptr, "GetProgramLaunchInfo"}, | 912 | {0x082F0040, nullptr, "GetProgramLaunchInfo"}, |
| 886 | {0x08300182, nullptr, "CreateExtSaveData"}, | 913 | {0x08300182, nullptr, "CreateExtSaveData"}, |
| 887 | {0x08310180, nullptr, "CreateSharedExtSaveData"}, | 914 | {0x08310180, nullptr, "CreateSharedExtSaveData"}, |
| 888 | {0x08320102, nullptr, "ReadExtSaveDataIcon"}, | 915 | {0x08320102, nullptr, "ReadExtSaveDataIcon"}, |
| 889 | {0x08330082, nullptr, "EnumerateExtSaveData"}, | 916 | {0x08330082, nullptr, "EnumerateExtSaveData"}, |
| 890 | {0x08340082, nullptr, "EnumerateSharedExtSaveData"}, | 917 | {0x08340082, nullptr, "EnumerateSharedExtSaveData"}, |
| 891 | {0x08350080, nullptr, "DeleteExtSaveData"}, | 918 | {0x08350080, nullptr, "DeleteExtSaveData"}, |
| 892 | {0x08360080, nullptr, "DeleteSharedExtSaveData"}, | 919 | {0x08360080, nullptr, "DeleteSharedExtSaveData"}, |
| 893 | {0x08370040, nullptr, "SetCardSpiBaudRate"}, | 920 | {0x08370040, nullptr, "SetCardSpiBaudRate"}, |
| 894 | {0x08380040, nullptr, "SetCardSpiBusMode"}, | 921 | {0x08380040, nullptr, "SetCardSpiBusMode"}, |
| 895 | {0x08390000, nullptr, "SendInitializeInfoTo9"}, | 922 | {0x08390000, nullptr, "SendInitializeInfoTo9"}, |
| 896 | {0x083A0100, nullptr, "GetSpecialContentIndex"}, | 923 | {0x083A0100, nullptr, "GetSpecialContentIndex"}, |
| 897 | {0x083B00C2, nullptr, "GetLegacyRomHeader"}, | 924 | {0x083B00C2, nullptr, "GetLegacyRomHeader"}, |
| 898 | {0x083C00C2, nullptr, "GetLegacyBannerData"}, | 925 | {0x083C00C2, nullptr, "GetLegacyBannerData"}, |
| 899 | {0x083D0100, nullptr, "CheckAuthorityToAccessExtSaveData"}, | 926 | {0x083D0100, nullptr, "CheckAuthorityToAccessExtSaveData"}, |
| 900 | {0x083E00C2, nullptr, "QueryTotalQuotaSize"}, | 927 | {0x083E00C2, nullptr, "QueryTotalQuotaSize"}, |
| 901 | {0x083F00C0, nullptr, "GetExtDataBlockSize"}, | 928 | {0x083F00C0, nullptr, "GetExtDataBlockSize"}, |
| 902 | {0x08400040, nullptr, "AbnegateAccessRight"}, | 929 | {0x08400040, nullptr, "AbnegateAccessRight"}, |
| 903 | {0x08410000, nullptr, "DeleteSdmcRoot"}, | 930 | {0x08410000, nullptr, "DeleteSdmcRoot"}, |
| 904 | {0x08420040, nullptr, "DeleteAllExtSaveDataOnNand"}, | 931 | {0x08420040, nullptr, "DeleteAllExtSaveDataOnNand"}, |
| 905 | {0x08430000, nullptr, "InitializeCtrFileSystem"}, | 932 | {0x08430000, nullptr, "InitializeCtrFileSystem"}, |
| 906 | {0x08440000, nullptr, "CreateSeed"}, | 933 | {0x08440000, nullptr, "CreateSeed"}, |
| 907 | {0x084500C2, GetFormatInfo, "GetFormatInfo"}, | 934 | {0x084500C2, GetFormatInfo, "GetFormatInfo"}, |
| 908 | {0x08460102, nullptr, "GetLegacyRomHeader2"}, | 935 | {0x08460102, nullptr, "GetLegacyRomHeader2"}, |
| 909 | {0x08470180, nullptr, "FormatCtrCardUserSaveData"}, | 936 | {0x08470180, nullptr, "FormatCtrCardUserSaveData"}, |
| 910 | {0x08480042, nullptr, "GetSdmcCtrRootPath"}, | 937 | {0x08480042, nullptr, "GetSdmcCtrRootPath"}, |
| 911 | {0x08490040, GetArchiveResource, "GetArchiveResource"}, | 938 | {0x08490040, GetArchiveResource, "GetArchiveResource"}, |
| 912 | {0x084A0002, nullptr, "ExportIntegrityVerificationSeed"}, | 939 | {0x084A0002, nullptr, "ExportIntegrityVerificationSeed"}, |
| 913 | {0x084B0002, nullptr, "ImportIntegrityVerificationSeed"}, | 940 | {0x084B0002, nullptr, "ImportIntegrityVerificationSeed"}, |
| 914 | {0x084C0242, FormatSaveData, "FormatSaveData"}, | 941 | {0x084C0242, FormatSaveData, "FormatSaveData"}, |
| 915 | {0x084D0102, nullptr, "GetLegacySubBannerData"}, | 942 | {0x084D0102, nullptr, "GetLegacySubBannerData"}, |
| 916 | {0x084E0342, nullptr, "UpdateSha256Context"}, | 943 | {0x084E0342, nullptr, "UpdateSha256Context"}, |
| 917 | {0x084F0102, nullptr, "ReadSpecialFile"}, | 944 | {0x084F0102, nullptr, "ReadSpecialFile"}, |
| 918 | {0x08500040, nullptr, "GetSpecialFileSize"}, | 945 | {0x08500040, nullptr, "GetSpecialFileSize"}, |
| 919 | {0x08510242, CreateExtSaveData, "CreateExtSaveData"}, | 946 | {0x08510242, CreateExtSaveData, "CreateExtSaveData"}, |
| 920 | {0x08520100, DeleteExtSaveData, "DeleteExtSaveData"}, | 947 | {0x08520100, DeleteExtSaveData, "DeleteExtSaveData"}, |
| 921 | {0x08530142, nullptr, "ReadExtSaveDataIcon"}, | 948 | {0x08530142, nullptr, "ReadExtSaveDataIcon"}, |
| 922 | {0x085400C0, nullptr, "GetExtDataBlockSize"}, | 949 | {0x085400C0, nullptr, "GetExtDataBlockSize"}, |
| 923 | {0x08550102, nullptr, "EnumerateExtSaveData"}, | 950 | {0x08550102, nullptr, "EnumerateExtSaveData"}, |
| 924 | {0x08560240, CreateSystemSaveData, "CreateSystemSaveData"}, | 951 | {0x08560240, CreateSystemSaveData, "CreateSystemSaveData"}, |
| 925 | {0x08570080, DeleteSystemSaveData, "DeleteSystemSaveData"}, | 952 | {0x08570080, DeleteSystemSaveData, "DeleteSystemSaveData"}, |
| 926 | {0x08580000, nullptr, "StartDeviceMoveAsSource"}, | 953 | {0x08580000, nullptr, "StartDeviceMoveAsSource"}, |
| 927 | {0x08590200, nullptr, "StartDeviceMoveAsDestination"}, | 954 | {0x08590200, nullptr, "StartDeviceMoveAsDestination"}, |
| 928 | {0x085A00C0, nullptr, "SetArchivePriority"}, | 955 | {0x085A00C0, nullptr, "SetArchivePriority"}, |
| 929 | {0x085B0080, nullptr, "GetArchivePriority"}, | 956 | {0x085B0080, nullptr, "GetArchivePriority"}, |
| 930 | {0x085C00C0, nullptr, "SetCtrCardLatencyParameter"}, | 957 | {0x085C00C0, nullptr, "SetCtrCardLatencyParameter"}, |
| 931 | {0x085D01C0, nullptr, "SetFsCompatibilityInfo"}, | 958 | {0x085D01C0, nullptr, "SetFsCompatibilityInfo"}, |
| 932 | {0x085E0040, nullptr, "ResetCardCompatibilityParameter"}, | 959 | {0x085E0040, nullptr, "ResetCardCompatibilityParameter"}, |
| 933 | {0x085F0040, nullptr, "SwitchCleanupInvalidSaveData"}, | 960 | {0x085F0040, nullptr, "SwitchCleanupInvalidSaveData"}, |
| 934 | {0x08600042, nullptr, "EnumerateSystemSaveData"}, | 961 | {0x08600042, nullptr, "EnumerateSystemSaveData"}, |
| 935 | {0x08610042, InitializeWithSdkVersion, "InitializeWithSdkVersion"}, | 962 | {0x08610042, InitializeWithSdkVersion, "InitializeWithSdkVersion"}, |
| 936 | {0x08620040, SetPriority, "SetPriority"}, | 963 | {0x08620040, SetPriority, "SetPriority"}, |
| 937 | {0x08630000, GetPriority, "GetPriority"}, | 964 | {0x08630000, GetPriority, "GetPriority"}, |
| 938 | {0x08640000, nullptr, "GetNandInfo"}, | 965 | {0x08640000, nullptr, "GetNandInfo"}, |
| 939 | {0x08650140, nullptr, "SetSaveDataSecureValue"}, | 966 | {0x08650140, nullptr, "SetSaveDataSecureValue"}, |
| 940 | {0x086600C0, nullptr, "GetSaveDataSecureValue"}, | 967 | {0x086600C0, nullptr, "GetSaveDataSecureValue"}, |
| 941 | {0x086700C4, nullptr, "ControlSecureSave"}, | 968 | {0x086700C4, nullptr, "ControlSecureSave"}, |
| 942 | {0x08680000, nullptr, "GetMediaType"}, | 969 | {0x08680000, nullptr, "GetMediaType"}, |
| 943 | {0x08690000, nullptr, "GetNandEraseCount"}, | 970 | {0x08690000, nullptr, "GetNandEraseCount"}, |
| 944 | {0x086A0082, nullptr, "ReadNandReport"} | 971 | {0x086A0082, nullptr, "ReadNandReport"}}; |
| 945 | }; | ||
| 946 | 972 | ||
| 947 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 973 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 948 | // Interface class | 974 | // Interface class |
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index ec565f46d..b273aac47 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp | |||
| @@ -5,16 +5,16 @@ | |||
| 5 | #include "common/bit_field.h" | 5 | #include "common/bit_field.h" |
| 6 | #include "common/microprofile.h" | 6 | #include "common/microprofile.h" |
| 7 | 7 | ||
| 8 | #include "core/memory.h" | ||
| 9 | #include "core/hle/kernel/event.h" | 8 | #include "core/hle/kernel/event.h" |
| 10 | #include "core/hle/kernel/shared_memory.h" | 9 | #include "core/hle/kernel/shared_memory.h" |
| 11 | #include "core/hle/result.h" | 10 | #include "core/hle/result.h" |
| 12 | #include "core/hw/hw.h" | ||
| 13 | #include "core/hw/gpu.h" | 11 | #include "core/hw/gpu.h" |
| 12 | #include "core/hw/hw.h" | ||
| 14 | #include "core/hw/lcd.h" | 13 | #include "core/hw/lcd.h" |
| 14 | #include "core/memory.h" | ||
| 15 | 15 | ||
| 16 | #include "video_core/gpu_debugger.h" | ||
| 17 | #include "video_core/debug_utils/debug_utils.h" | 16 | #include "video_core/debug_utils/debug_utils.h" |
| 17 | #include "video_core/gpu_debugger.h" | ||
| 18 | 18 | ||
| 19 | #include "gsp_gpu.h" | 19 | #include "gsp_gpu.h" |
| 20 | 20 | ||
| @@ -29,12 +29,16 @@ const static u32 REGS_BEGIN = 0x1EB00000; | |||
| 29 | 29 | ||
| 30 | namespace GSP_GPU { | 30 | namespace GSP_GPU { |
| 31 | 31 | ||
| 32 | const ResultCode ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED(ErrorDescription::OutofRangeOrMisalignedAddress, ErrorModule::GX, | 32 | const ResultCode |
| 33 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02A01 | 33 | ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED(ErrorDescription::OutofRangeOrMisalignedAddress, |
| 34 | ErrorModule::GX, ErrorSummary::InvalidArgument, | ||
| 35 | ErrorLevel::Usage); // 0xE0E02A01 | ||
| 34 | const ResultCode ERR_GSP_REGS_MISALIGNED(ErrorDescription::MisalignedSize, ErrorModule::GX, | 36 | const ResultCode ERR_GSP_REGS_MISALIGNED(ErrorDescription::MisalignedSize, ErrorModule::GX, |
| 35 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02BF2 | 37 | ErrorSummary::InvalidArgument, |
| 38 | ErrorLevel::Usage); // 0xE0E02BF2 | ||
| 36 | const ResultCode ERR_GSP_REGS_INVALID_SIZE(ErrorDescription::InvalidSize, ErrorModule::GX, | 39 | const ResultCode ERR_GSP_REGS_INVALID_SIZE(ErrorDescription::InvalidSize, ErrorModule::GX, |
| 37 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02BEC | 40 | ErrorSummary::InvalidArgument, |
| 41 | ErrorLevel::Usage); // 0xE0E02BEC | ||
| 38 | 42 | ||
| 39 | /// Event triggered when GSP interrupt has been signalled | 43 | /// Event triggered when GSP interrupt has been signalled |
| 40 | Kernel::SharedPtr<Kernel::Event> g_interrupt_event; | 44 | Kernel::SharedPtr<Kernel::Event> g_interrupt_event; |
| @@ -73,7 +77,8 @@ static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) { | |||
| 73 | * @param data Data to be written | 77 | * @param data Data to be written |
| 74 | */ | 78 | */ |
| 75 | static void WriteSingleHWReg(u32 base_address, u32 data) { | 79 | static void WriteSingleHWReg(u32 base_address, u32 data) { |
| 76 | DEBUG_ASSERT_MSG((base_address & 3) == 0 && base_address < 0x420000, "Write address out of range or misaligned"); | 80 | DEBUG_ASSERT_MSG((base_address & 3) == 0 && base_address < 0x420000, |
| 81 | "Write address out of range or misaligned"); | ||
| 77 | HW::Write<u32>(base_address + REGS_BEGIN, data); | 82 | HW::Write<u32>(base_address + REGS_BEGIN, data); |
| 78 | } | 83 | } |
| 79 | 84 | ||
| @@ -90,7 +95,8 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, VAddr data_va | |||
| 90 | const u32 max_size_in_bytes = 0x80; | 95 | const u32 max_size_in_bytes = 0x80; |
| 91 | 96 | ||
| 92 | if (base_address & 3 || base_address >= 0x420000) { | 97 | if (base_address & 3 || base_address >= 0x420000) { |
| 93 | LOG_ERROR(Service_GSP, "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)", | 98 | LOG_ERROR(Service_GSP, |
| 99 | "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)", | ||
| 94 | base_address, size_in_bytes); | 100 | base_address, size_in_bytes); |
| 95 | return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED; | 101 | return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED; |
| 96 | } else if (size_in_bytes <= max_size_in_bytes) { | 102 | } else if (size_in_bytes <= max_size_in_bytes) { |
| @@ -124,12 +130,14 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, VAddr data_va | |||
| 124 | * @param masks A pointer to the masks | 130 | * @param masks A pointer to the masks |
| 125 | * @return RESULT_SUCCESS if the parameters are valid, error code otherwise | 131 | * @return RESULT_SUCCESS if the parameters are valid, error code otherwise |
| 126 | */ | 132 | */ |
| 127 | static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, VAddr data_vaddr, VAddr masks_vaddr) { | 133 | static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, VAddr data_vaddr, |
| 134 | VAddr masks_vaddr) { | ||
| 128 | // This magic number is verified to be done by the gsp module | 135 | // This magic number is verified to be done by the gsp module |
| 129 | const u32 max_size_in_bytes = 0x80; | 136 | const u32 max_size_in_bytes = 0x80; |
| 130 | 137 | ||
| 131 | if (base_address & 3 || base_address >= 0x420000) { | 138 | if (base_address & 3 || base_address >= 0x420000) { |
| 132 | LOG_ERROR(Service_GSP, "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)", | 139 | LOG_ERROR(Service_GSP, |
| 140 | "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)", | ||
| 133 | base_address, size_in_bytes); | 141 | base_address, size_in_bytes); |
| 134 | return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED; | 142 | return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED; |
| 135 | } else if (size_in_bytes <= max_size_in_bytes) { | 143 | } else if (size_in_bytes <= max_size_in_bytes) { |
| @@ -214,7 +222,8 @@ static void ReadHWRegs(Service::Interface* self) { | |||
| 214 | 222 | ||
| 215 | // TODO: Return proper error codes | 223 | // TODO: Return proper error codes |
| 216 | if (reg_addr + size >= 0x420000) { | 224 | if (reg_addr + size >= 0x420000) { |
| 217 | LOG_ERROR(Service_GSP, "Read address out of range! (address=0x%08x, size=0x%08x)", reg_addr, size); | 225 | LOG_ERROR(Service_GSP, "Read address out of range! (address=0x%08x, size=0x%08x)", reg_addr, |
| 226 | size); | ||
| 218 | return; | 227 | return; |
| 219 | } | 228 | } |
| 220 | 229 | ||
| @@ -243,22 +252,34 @@ ResultCode SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) { | |||
| 243 | PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left); | 252 | PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left); |
| 244 | PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right); | 253 | PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right); |
| 245 | if (info.active_fb == 0) { | 254 | if (info.active_fb == 0) { |
| 246 | WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), | 255 | WriteSingleHWReg( |
| 247 | phys_address_left); | 256 | base_address + |
| 248 | WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), | 257 | 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), |
| 249 | phys_address_right); | 258 | phys_address_left); |
| 259 | WriteSingleHWReg( | ||
| 260 | base_address + | ||
| 261 | 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), | ||
| 262 | phys_address_right); | ||
| 250 | } else { | 263 | } else { |
| 251 | WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), | 264 | WriteSingleHWReg( |
| 252 | phys_address_left); | 265 | base_address + |
| 253 | WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), | 266 | 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), |
| 254 | phys_address_right); | 267 | phys_address_left); |
| 268 | WriteSingleHWReg( | ||
| 269 | base_address + | ||
| 270 | 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), | ||
| 271 | phys_address_right); | ||
| 255 | } | 272 | } |
| 256 | WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), | 273 | WriteSingleHWReg(base_address + |
| 274 | 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), | ||
| 257 | info.stride); | 275 | info.stride); |
| 258 | WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), | 276 | WriteSingleHWReg( |
| 259 | info.format); | 277 | base_address + |
| 260 | WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), | 278 | 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), |
| 261 | info.shown_fb); | 279 | info.format); |
| 280 | WriteSingleHWReg( | ||
| 281 | base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), | ||
| 282 | info.shown_fb); | ||
| 262 | 283 | ||
| 263 | if (Pica::g_debug_context) | 284 | if (Pica::g_debug_context) |
| 264 | Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr); | 285 | Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr); |
| @@ -305,15 +326,15 @@ static void SetBufferSwap(Service::Interface* self) { | |||
| 305 | static void FlushDataCache(Service::Interface* self) { | 326 | static void FlushDataCache(Service::Interface* self) { |
| 306 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 327 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 307 | u32 address = cmd_buff[1]; | 328 | u32 address = cmd_buff[1]; |
| 308 | u32 size = cmd_buff[2]; | 329 | u32 size = cmd_buff[2]; |
| 309 | u32 process = cmd_buff[4]; | 330 | u32 process = cmd_buff[4]; |
| 310 | 331 | ||
| 311 | // TODO(purpasmart96): Verify return header on HW | 332 | // TODO(purpasmart96): Verify return header on HW |
| 312 | 333 | ||
| 313 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 334 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 314 | 335 | ||
| 315 | LOG_DEBUG(Service_GSP, "(STUBBED) called address=0x%08X, size=0x%08X, process=0x%08X", | 336 | LOG_DEBUG(Service_GSP, "(STUBBED) called address=0x%08X, size=0x%08X, process=0x%08X", address, |
| 316 | address, size, process); | 337 | size, process); |
| 317 | } | 338 | } |
| 318 | 339 | ||
| 319 | /** | 340 | /** |
| @@ -356,11 +377,12 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) { | |||
| 356 | // This specific code is required for a successful initialization, rather than 0 | 377 | // This specific code is required for a successful initialization, rather than 0 |
| 357 | first_initialization = false; | 378 | first_initialization = false; |
| 358 | cmd_buff[1] = ResultCode(ErrorDescription::GPU_FirstInitialization, ErrorModule::GX, | 379 | cmd_buff[1] = ResultCode(ErrorDescription::GPU_FirstInitialization, ErrorModule::GX, |
| 359 | ErrorSummary::Success, ErrorLevel::Success).raw; | 380 | ErrorSummary::Success, ErrorLevel::Success) |
| 381 | .raw; | ||
| 360 | } else { | 382 | } else { |
| 361 | cmd_buff[1] = RESULT_SUCCESS.raw; | 383 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 362 | } | 384 | } |
| 363 | cmd_buff[2] = g_thread_id++; // Thread ID | 385 | cmd_buff[2] = g_thread_id++; // Thread ID |
| 364 | cmd_buff[4] = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); // GSP shared memory | 386 | cmd_buff[4] = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); // GSP shared memory |
| 365 | 387 | ||
| 366 | g_interrupt_event->Signal(); // TODO(bunnei): Is this correct? | 388 | g_interrupt_event->Signal(); // TODO(bunnei): Is this correct? |
| @@ -416,7 +438,8 @@ void SignalInterrupt(InterruptId interrupt_id) { | |||
| 416 | // Update framebuffer information if requested | 438 | // Update framebuffer information if requested |
| 417 | // TODO(yuriks): Confirm where this code should be called. It is definitely updated without | 439 | // TODO(yuriks): Confirm where this code should be called. It is definitely updated without |
| 418 | // executing any GSP commands, only waiting on the event. | 440 | // executing any GSP commands, only waiting on the event. |
| 419 | int screen_id = (interrupt_id == InterruptId::PDC0) ? 0 : (interrupt_id == InterruptId::PDC1) ? 1 : -1; | 441 | int screen_id = |
| 442 | (interrupt_id == InterruptId::PDC0) ? 0 : (interrupt_id == InterruptId::PDC1) ? 1 : -1; | ||
| 420 | if (screen_id != -1) { | 443 | if (screen_id != -1) { |
| 421 | FrameBufferUpdate* info = GetFrameBufferInfo(thread_id, screen_id); | 444 | FrameBufferUpdate* info = GetFrameBufferInfo(thread_id, screen_id); |
| 422 | if (info->is_dirty) { | 445 | if (info->is_dirty) { |
| @@ -440,25 +463,27 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | |||
| 440 | switch (command.id) { | 463 | switch (command.id) { |
| 441 | 464 | ||
| 442 | // GX request DMA - typically used for copying memory from GSP heap to VRAM | 465 | // GX request DMA - typically used for copying memory from GSP heap to VRAM |
| 443 | case CommandId::REQUEST_DMA: | 466 | case CommandId::REQUEST_DMA: { |
| 444 | { | ||
| 445 | MICROPROFILE_SCOPE(GPU_GSP_DMA); | 467 | MICROPROFILE_SCOPE(GPU_GSP_DMA); |
| 446 | 468 | ||
| 447 | // TODO: Consider attempting rasterizer-accelerated surface blit if that usage is ever possible/likely | 469 | // TODO: Consider attempting rasterizer-accelerated surface blit if that usage is ever |
| 448 | Memory::RasterizerFlushRegion(Memory::VirtualToPhysicalAddress(command.dma_request.source_address), | 470 | // possible/likely |
| 449 | command.dma_request.size); | 471 | Memory::RasterizerFlushRegion( |
| 450 | Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(command.dma_request.dest_address), | 472 | Memory::VirtualToPhysicalAddress(command.dma_request.source_address), |
| 451 | command.dma_request.size); | 473 | command.dma_request.size); |
| 474 | Memory::RasterizerFlushAndInvalidateRegion( | ||
| 475 | Memory::VirtualToPhysicalAddress(command.dma_request.dest_address), | ||
| 476 | command.dma_request.size); | ||
| 452 | 477 | ||
| 453 | // TODO(Subv): These memory accesses should not go through the application's memory mapping. | 478 | // TODO(Subv): These memory accesses should not go through the application's memory mapping. |
| 454 | // They should go through the GSP module's memory mapping. | 479 | // They should go through the GSP module's memory mapping. |
| 455 | Memory::CopyBlock(command.dma_request.dest_address, command.dma_request.source_address, command.dma_request.size); | 480 | Memory::CopyBlock(command.dma_request.dest_address, command.dma_request.source_address, |
| 481 | command.dma_request.size); | ||
| 456 | SignalInterrupt(InterruptId::DMA); | 482 | SignalInterrupt(InterruptId::DMA); |
| 457 | break; | 483 | break; |
| 458 | } | 484 | } |
| 459 | // TODO: This will need some rework in the future. (why?) | 485 | // TODO: This will need some rework in the future. (why?) |
| 460 | case CommandId::SUBMIT_GPU_CMDLIST: | 486 | case CommandId::SUBMIT_GPU_CMDLIST: { |
| 461 | { | ||
| 462 | auto& params = command.submit_gpu_cmdlist; | 487 | auto& params = command.submit_gpu_cmdlist; |
| 463 | 488 | ||
| 464 | if (params.do_flush) { | 489 | if (params.do_flush) { |
| @@ -468,10 +493,12 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | |||
| 468 | } | 493 | } |
| 469 | 494 | ||
| 470 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.address)), | 495 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.address)), |
| 471 | Memory::VirtualToPhysicalAddress(params.address) >> 3); | 496 | Memory::VirtualToPhysicalAddress(params.address) >> 3); |
| 472 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.size)), params.size); | 497 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.size)), |
| 498 | params.size); | ||
| 473 | 499 | ||
| 474 | // TODO: Not sure if we are supposed to always write this .. seems to trigger processing though | 500 | // TODO: Not sure if we are supposed to always write this .. seems to trigger processing |
| 501 | // though | ||
| 475 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.trigger)), 1); | 502 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.trigger)), 1); |
| 476 | 503 | ||
| 477 | // TODO(yuriks): Figure out the meaning of the `flags` field. | 504 | // TODO(yuriks): Figure out the meaning of the `flags` field. |
| @@ -481,67 +508,70 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | |||
| 481 | 508 | ||
| 482 | // It's assumed that the two "blocks" behave equivalently. | 509 | // It's assumed that the two "blocks" behave equivalently. |
| 483 | // Presumably this is done simply to allow two memory fills to run in parallel. | 510 | // Presumably this is done simply to allow two memory fills to run in parallel. |
| 484 | case CommandId::SET_MEMORY_FILL: | 511 | case CommandId::SET_MEMORY_FILL: { |
| 485 | { | ||
| 486 | auto& params = command.memory_fill; | 512 | auto& params = command.memory_fill; |
| 487 | 513 | ||
| 488 | if (params.start1 != 0) { | 514 | if (params.start1 != 0) { |
| 489 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_start)), | 515 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_start)), |
| 490 | Memory::VirtualToPhysicalAddress(params.start1) >> 3); | 516 | Memory::VirtualToPhysicalAddress(params.start1) >> 3); |
| 491 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_end)), | 517 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_end)), |
| 492 | Memory::VirtualToPhysicalAddress(params.end1) >> 3); | 518 | Memory::VirtualToPhysicalAddress(params.end1) >> 3); |
| 493 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].value_32bit)), params.value1); | 519 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].value_32bit)), |
| 494 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].control)), params.control1); | 520 | params.value1); |
| 521 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].control)), | ||
| 522 | params.control1); | ||
| 495 | } | 523 | } |
| 496 | 524 | ||
| 497 | if (params.start2 != 0) { | 525 | if (params.start2 != 0) { |
| 498 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_start)), | 526 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_start)), |
| 499 | Memory::VirtualToPhysicalAddress(params.start2) >> 3); | 527 | Memory::VirtualToPhysicalAddress(params.start2) >> 3); |
| 500 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_end)), | 528 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_end)), |
| 501 | Memory::VirtualToPhysicalAddress(params.end2) >> 3); | 529 | Memory::VirtualToPhysicalAddress(params.end2) >> 3); |
| 502 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].value_32bit)), params.value2); | 530 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].value_32bit)), |
| 503 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].control)), params.control2); | 531 | params.value2); |
| 532 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].control)), | ||
| 533 | params.control2); | ||
| 504 | } | 534 | } |
| 505 | break; | 535 | break; |
| 506 | } | 536 | } |
| 507 | 537 | ||
| 508 | case CommandId::SET_DISPLAY_TRANSFER: | 538 | case CommandId::SET_DISPLAY_TRANSFER: { |
| 509 | { | ||
| 510 | auto& params = command.display_transfer; | 539 | auto& params = command.display_transfer; |
| 511 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_address)), | 540 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_address)), |
| 512 | Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3); | 541 | Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3); |
| 513 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_address)), | 542 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_address)), |
| 514 | Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3); | 543 | Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3); |
| 515 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_size)), params.in_buffer_size); | 544 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_size)), |
| 516 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_size)), params.out_buffer_size); | 545 | params.in_buffer_size); |
| 517 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.flags)), params.flags); | 546 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_size)), |
| 547 | params.out_buffer_size); | ||
| 548 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.flags)), | ||
| 549 | params.flags); | ||
| 518 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.trigger)), 1); | 550 | WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.trigger)), 1); |
| 519 | break; | 551 | break; |
| 520 | } | 552 | } |
| 521 | 553 | ||
| 522 | case CommandId::SET_TEXTURE_COPY: | 554 | case CommandId::SET_TEXTURE_COPY: { |
| 523 | { | ||
| 524 | auto& params = command.texture_copy; | 555 | auto& params = command.texture_copy; |
| 525 | WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.input_address), | 556 | WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.input_address), |
| 526 | Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3); | 557 | Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3); |
| 527 | WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.output_address), | 558 | WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.output_address), |
| 528 | Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3); | 559 | Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3); |
| 529 | WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.size), | 560 | WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.size), |
| 530 | params.size); | 561 | params.size); |
| 531 | WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.input_size), | 562 | WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.input_size), |
| 532 | params.in_width_gap); | 563 | params.in_width_gap); |
| 533 | WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.output_size), | 564 | WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.output_size), |
| 534 | params.out_width_gap); | 565 | params.out_width_gap); |
| 535 | WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.flags), | 566 | WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.flags), params.flags); |
| 536 | params.flags); | ||
| 537 | 567 | ||
| 538 | // NOTE: Actual GSP ORs 1 with current register instead of overwriting. Doesn't seem to matter. | 568 | // NOTE: Actual GSP ORs 1 with current register instead of overwriting. Doesn't seem to |
| 569 | // matter. | ||
| 539 | WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.trigger), 1); | 570 | WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.trigger), 1); |
| 540 | break; | 571 | break; |
| 541 | } | 572 | } |
| 542 | 573 | ||
| 543 | case CommandId::CACHE_FLUSH: | 574 | case CommandId::CACHE_FLUSH: { |
| 544 | { | ||
| 545 | // NOTE: Rasterizer flushing handled elsewhere in CPU read/write and other GPU handlers | 575 | // NOTE: Rasterizer flushing handled elsewhere in CPU read/write and other GPU handlers |
| 546 | // Use command.cache_flush.regions to implement this handler | 576 | // Use command.cache_flush.regions to implement this handler |
| 547 | break; | 577 | break; |
| @@ -552,7 +582,8 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | |||
| 552 | } | 582 | } |
| 553 | 583 | ||
| 554 | if (Pica::g_debug_context) | 584 | if (Pica::g_debug_context) |
| 555 | Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::GSPCommandProcessed, (void*)&command); | 585 | Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::GSPCommandProcessed, |
| 586 | (void*)&command); | ||
| 556 | } | 587 | } |
| 557 | 588 | ||
| 558 | /** | 589 | /** |
| @@ -575,7 +606,7 @@ static void SetLcdForceBlack(Service::Interface* self) { | |||
| 575 | // the color to black (all zero). | 606 | // the color to black (all zero). |
| 576 | data.is_enabled.Assign(enable_black); | 607 | data.is_enabled.Assign(enable_black); |
| 577 | 608 | ||
| 578 | LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_top), data.raw); // Top LCD | 609 | LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_top), data.raw); // Top LCD |
| 579 | LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_bottom), data.raw); // Bottom LCD | 610 | LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_bottom), data.raw); // Bottom LCD |
| 580 | 611 | ||
| 581 | cmd_buff[1] = RESULT_SUCCESS.raw; | 612 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| @@ -679,37 +710,37 @@ static void ReleaseRight(Service::Interface* self) { | |||
| 679 | } | 710 | } |
| 680 | 711 | ||
| 681 | const Interface::FunctionInfo FunctionTable[] = { | 712 | const Interface::FunctionInfo FunctionTable[] = { |
| 682 | {0x00010082, WriteHWRegs, "WriteHWRegs"}, | 713 | {0x00010082, WriteHWRegs, "WriteHWRegs"}, |
| 683 | {0x00020084, WriteHWRegsWithMask, "WriteHWRegsWithMask"}, | 714 | {0x00020084, WriteHWRegsWithMask, "WriteHWRegsWithMask"}, |
| 684 | {0x00030082, nullptr, "WriteHWRegRepeat"}, | 715 | {0x00030082, nullptr, "WriteHWRegRepeat"}, |
| 685 | {0x00040080, ReadHWRegs, "ReadHWRegs"}, | 716 | {0x00040080, ReadHWRegs, "ReadHWRegs"}, |
| 686 | {0x00050200, SetBufferSwap, "SetBufferSwap"}, | 717 | {0x00050200, SetBufferSwap, "SetBufferSwap"}, |
| 687 | {0x00060082, nullptr, "SetCommandList"}, | 718 | {0x00060082, nullptr, "SetCommandList"}, |
| 688 | {0x000700C2, nullptr, "RequestDma"}, | 719 | {0x000700C2, nullptr, "RequestDma"}, |
| 689 | {0x00080082, FlushDataCache, "FlushDataCache"}, | 720 | {0x00080082, FlushDataCache, "FlushDataCache"}, |
| 690 | {0x00090082, nullptr, "InvalidateDataCache"}, | 721 | {0x00090082, nullptr, "InvalidateDataCache"}, |
| 691 | {0x000A0044, nullptr, "RegisterInterruptEvents"}, | 722 | {0x000A0044, nullptr, "RegisterInterruptEvents"}, |
| 692 | {0x000B0040, SetLcdForceBlack, "SetLcdForceBlack"}, | 723 | {0x000B0040, SetLcdForceBlack, "SetLcdForceBlack"}, |
| 693 | {0x000C0000, TriggerCmdReqQueue, "TriggerCmdReqQueue"}, | 724 | {0x000C0000, TriggerCmdReqQueue, "TriggerCmdReqQueue"}, |
| 694 | {0x000D0140, nullptr, "SetDisplayTransfer"}, | 725 | {0x000D0140, nullptr, "SetDisplayTransfer"}, |
| 695 | {0x000E0180, nullptr, "SetTextureCopy"}, | 726 | {0x000E0180, nullptr, "SetTextureCopy"}, |
| 696 | {0x000F0200, nullptr, "SetMemoryFill"}, | 727 | {0x000F0200, nullptr, "SetMemoryFill"}, |
| 697 | {0x00100040, SetAxiConfigQoSMode, "SetAxiConfigQoSMode"}, | 728 | {0x00100040, SetAxiConfigQoSMode, "SetAxiConfigQoSMode"}, |
| 698 | {0x00110040, nullptr, "SetPerfLogMode"}, | 729 | {0x00110040, nullptr, "SetPerfLogMode"}, |
| 699 | {0x00120000, nullptr, "GetPerfLog"}, | 730 | {0x00120000, nullptr, "GetPerfLog"}, |
| 700 | {0x00130042, RegisterInterruptRelayQueue, "RegisterInterruptRelayQueue"}, | 731 | {0x00130042, RegisterInterruptRelayQueue, "RegisterInterruptRelayQueue"}, |
| 701 | {0x00140000, UnregisterInterruptRelayQueue, "UnregisterInterruptRelayQueue"}, | 732 | {0x00140000, UnregisterInterruptRelayQueue, "UnregisterInterruptRelayQueue"}, |
| 702 | {0x00150002, nullptr, "TryAcquireRight"}, | 733 | {0x00150002, nullptr, "TryAcquireRight"}, |
| 703 | {0x00160042, AcquireRight, "AcquireRight"}, | 734 | {0x00160042, AcquireRight, "AcquireRight"}, |
| 704 | {0x00170000, ReleaseRight, "ReleaseRight"}, | 735 | {0x00170000, ReleaseRight, "ReleaseRight"}, |
| 705 | {0x00180000, ImportDisplayCaptureInfo, "ImportDisplayCaptureInfo"}, | 736 | {0x00180000, ImportDisplayCaptureInfo, "ImportDisplayCaptureInfo"}, |
| 706 | {0x00190000, nullptr, "SaveVramSysArea"}, | 737 | {0x00190000, nullptr, "SaveVramSysArea"}, |
| 707 | {0x001A0000, nullptr, "RestoreVramSysArea"}, | 738 | {0x001A0000, nullptr, "RestoreVramSysArea"}, |
| 708 | {0x001B0000, nullptr, "ResetGpuCore"}, | 739 | {0x001B0000, nullptr, "ResetGpuCore"}, |
| 709 | {0x001C0040, nullptr, "SetLedForceOff"}, | 740 | {0x001C0040, nullptr, "SetLedForceOff"}, |
| 710 | {0x001D0040, nullptr, "SetTestCommand"}, | 741 | {0x001D0040, nullptr, "SetTestCommand"}, |
| 711 | {0x001E0080, nullptr, "SetInternalPriorities"}, | 742 | {0x001E0080, nullptr, "SetInternalPriorities"}, |
| 712 | {0x001F0082, nullptr, "StoreDataCache"}, | 743 | {0x001F0082, nullptr, "StoreDataCache"}, |
| 713 | }; | 744 | }; |
| 714 | 745 | ||
| 715 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 746 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -721,9 +752,9 @@ Interface::Interface() { | |||
| 721 | g_interrupt_event = nullptr; | 752 | g_interrupt_event = nullptr; |
| 722 | 753 | ||
| 723 | using Kernel::MemoryPermission; | 754 | using Kernel::MemoryPermission; |
| 724 | g_shared_memory = Kernel::SharedMemory::Create(nullptr, 0x1000, | 755 | g_shared_memory = Kernel::SharedMemory::Create(nullptr, 0x1000, MemoryPermission::ReadWrite, |
| 725 | MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, | 756 | MemoryPermission::ReadWrite, 0, |
| 726 | 0, Kernel::MemoryRegion::BASE, "GSP:SharedMemory"); | 757 | Kernel::MemoryRegion::BASE, "GSP:SharedMemory"); |
| 727 | 758 | ||
| 728 | g_thread_id = 0; | 759 | g_thread_id = 0; |
| 729 | gpu_right_acquired = false; | 760 | gpu_right_acquired = false; |
diff --git a/src/core/hle/service/gsp_gpu.h b/src/core/hle/service/gsp_gpu.h index 3b4b678a3..e028123f3 100644 --- a/src/core/hle/service/gsp_gpu.h +++ b/src/core/hle/service/gsp_gpu.h | |||
| @@ -20,30 +20,30 @@ namespace GSP_GPU { | |||
| 20 | 20 | ||
| 21 | /// GSP interrupt ID | 21 | /// GSP interrupt ID |
| 22 | enum class InterruptId : u8 { | 22 | enum class InterruptId : u8 { |
| 23 | PSC0 = 0x00, | 23 | PSC0 = 0x00, |
| 24 | PSC1 = 0x01, | 24 | PSC1 = 0x01, |
| 25 | PDC0 = 0x02, // Seems called every vertical screen line | 25 | PDC0 = 0x02, // Seems called every vertical screen line |
| 26 | PDC1 = 0x03, // Seems called every frame | 26 | PDC1 = 0x03, // Seems called every frame |
| 27 | PPF = 0x04, | 27 | PPF = 0x04, |
| 28 | P3D = 0x05, | 28 | P3D = 0x05, |
| 29 | DMA = 0x06, | 29 | DMA = 0x06, |
| 30 | }; | 30 | }; |
| 31 | 31 | ||
| 32 | /// GSP command ID | 32 | /// GSP command ID |
| 33 | enum class CommandId : u32 { | 33 | enum class CommandId : u32 { |
| 34 | REQUEST_DMA = 0x00, | 34 | REQUEST_DMA = 0x00, |
| 35 | /// Submits a commandlist for execution by the GPU. | 35 | /// Submits a commandlist for execution by the GPU. |
| 36 | SUBMIT_GPU_CMDLIST = 0x01, | 36 | SUBMIT_GPU_CMDLIST = 0x01, |
| 37 | 37 | ||
| 38 | // Fills a given memory range with a particular value | 38 | // Fills a given memory range with a particular value |
| 39 | SET_MEMORY_FILL = 0x02, | 39 | SET_MEMORY_FILL = 0x02, |
| 40 | 40 | ||
| 41 | // Copies an image and optionally performs color-conversion or scaling. | 41 | // Copies an image and optionally performs color-conversion or scaling. |
| 42 | // This is highly similar to the GameCube's EFB copy feature | 42 | // This is highly similar to the GameCube's EFB copy feature |
| 43 | SET_DISPLAY_TRANSFER = 0x03, | 43 | SET_DISPLAY_TRANSFER = 0x03, |
| 44 | 44 | ||
| 45 | // Conceptionally similar to SET_DISPLAY_TRANSFER and presumable uses the same hardware path | 45 | // Conceptionally similar to SET_DISPLAY_TRANSFER and presumable uses the same hardware path |
| 46 | SET_TEXTURE_COPY = 0x04, | 46 | SET_TEXTURE_COPY = 0x04, |
| 47 | /// Flushes up to 3 cache regions in a single command. | 47 | /// Flushes up to 3 cache regions in a single command. |
| 48 | CACHE_FLUSH = 0x05, | 48 | CACHE_FLUSH = 0x05, |
| 49 | }; | 49 | }; |
| @@ -61,19 +61,18 @@ struct InterruptRelayQueue { | |||
| 61 | u32 missed_PDC0; | 61 | u32 missed_PDC0; |
| 62 | u32 missed_PDC1; | 62 | u32 missed_PDC1; |
| 63 | 63 | ||
| 64 | InterruptId slot[0x34]; ///< Interrupt ID slots | 64 | InterruptId slot[0x34]; ///< Interrupt ID slots |
| 65 | }; | 65 | }; |
| 66 | static_assert(sizeof(InterruptRelayQueue) == 0x40, | 66 | static_assert(sizeof(InterruptRelayQueue) == 0x40, "InterruptRelayQueue struct has incorrect size"); |
| 67 | "InterruptRelayQueue struct has incorrect size"); | ||
| 68 | 67 | ||
| 69 | struct FrameBufferInfo { | 68 | struct FrameBufferInfo { |
| 70 | BitField<0, 1, u32> active_fb; // 0 = first, 1 = second | 69 | BitField<0, 1, u32> active_fb; // 0 = first, 1 = second |
| 71 | 70 | ||
| 72 | u32 address_left; | 71 | u32 address_left; |
| 73 | u32 address_right; | 72 | u32 address_right; |
| 74 | u32 stride; // maps to 0x1EF00X90 ? | 73 | u32 stride; // maps to 0x1EF00X90 ? |
| 75 | u32 format; // maps to 0x1EF00X70 ? | 74 | u32 format; // maps to 0x1EF00X70 ? |
| 76 | u32 shown_fb; // maps to 0x1EF00X78 ? | 75 | u32 shown_fb; // maps to 0x1EF00X78 ? |
| 77 | u32 unknown; | 76 | u32 unknown; |
| 78 | }; | 77 | }; |
| 79 | static_assert(sizeof(FrameBufferInfo) == 0x1c, "Struct has incorrect size"); | 78 | static_assert(sizeof(FrameBufferInfo) == 0x1c, "Struct has incorrect size"); |
| @@ -91,7 +90,8 @@ static_assert(sizeof(FrameBufferUpdate) == 0x40, "Struct has incorrect size"); | |||
| 91 | // TODO: Not sure if this padding is correct. | 90 | // TODO: Not sure if this padding is correct. |
| 92 | // Chances are the second block is stored at offset 0x24 rather than 0x20. | 91 | // Chances are the second block is stored at offset 0x24 rather than 0x20. |
| 93 | #ifndef _MSC_VER | 92 | #ifndef _MSC_VER |
| 94 | static_assert(offsetof(FrameBufferUpdate, framebuffer_info[1]) == 0x20, "FrameBufferInfo element has incorrect alignment"); | 93 | static_assert(offsetof(FrameBufferUpdate, framebuffer_info[1]) == 0x20, |
| 94 | "FrameBufferInfo element has incorrect alignment"); | ||
| 95 | #endif | 95 | #endif |
| 96 | 96 | ||
| 97 | /// GSP command | 97 | /// GSP command |
| @@ -163,13 +163,13 @@ struct CommandBuffer { | |||
| 163 | // Current command index. This index is updated by GSP module after loading the command | 163 | // Current command index. This index is updated by GSP module after loading the command |
| 164 | // data, right before the command is processed. When this index is updated by GSP module, | 164 | // data, right before the command is processed. When this index is updated by GSP module, |
| 165 | // the total commands field is decreased by one as well. | 165 | // the total commands field is decreased by one as well. |
| 166 | BitField<0,8,u32> index; | 166 | BitField<0, 8, u32> index; |
| 167 | 167 | ||
| 168 | // Total commands to process, must not be value 0 when GSP module handles commands. This | 168 | // Total commands to process, must not be value 0 when GSP module handles commands. This |
| 169 | // must be <=15 when writing a command to shared memory. This is incremented by the | 169 | // must be <=15 when writing a command to shared memory. This is incremented by the |
| 170 | // application when writing a command to shared memory, after increasing this value | 170 | // application when writing a command to shared memory, after increasing this value |
| 171 | // TriggerCmdReqQueue is only used if this field is value 1. | 171 | // TriggerCmdReqQueue is only used if this field is value 1. |
| 172 | BitField<8,8,u32> number_commands; | 172 | BitField<8, 8, u32> number_commands; |
| 173 | }; | 173 | }; |
| 174 | 174 | ||
| 175 | u32 unk[7]; | 175 | u32 unk[7]; |
diff --git a/src/core/hle/service/gsp_lcd.cpp b/src/core/hle/service/gsp_lcd.cpp index c700c21c5..3922cd197 100644 --- a/src/core/hle/service/gsp_lcd.cpp +++ b/src/core/hle/service/gsp_lcd.cpp | |||
| @@ -9,13 +9,11 @@ | |||
| 9 | 9 | ||
| 10 | namespace GSP_LCD { | 10 | namespace GSP_LCD { |
| 11 | 11 | ||
| 12 | const Interface::FunctionInfo FunctionTable[] = { | 12 | const Interface::FunctionInfo FunctionTable[] = {{0x000F0000, nullptr, "PowerOnAllBacklights"}, |
| 13 | {0x000F0000, nullptr, "PowerOnAllBacklights"}, | 13 | {0x00100000, nullptr, "PowerOffAllBacklights"}, |
| 14 | {0x00100000, nullptr, "PowerOffAllBacklights"}, | 14 | {0x00110040, nullptr, "PowerOnBacklight"}, |
| 15 | {0x00110040, nullptr, "PowerOnBacklight"}, | 15 | {0x00120040, nullptr, "PowerOffBacklight"}, |
| 16 | {0x00120040, nullptr, "PowerOffBacklight"}, | 16 | {0x00130040, nullptr, "SetLedForceOff"}}; |
| 17 | {0x00130040, nullptr, "SetLedForceOff"} | ||
| 18 | }; | ||
| 19 | 17 | ||
| 20 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 18 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 21 | // Interface class | 19 | // Interface class |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index cdec11388..d915a3105 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -4,13 +4,13 @@ | |||
| 4 | 4 | ||
| 5 | #include <cmath> | 5 | #include <cmath> |
| 6 | 6 | ||
| 7 | #include "common/logging/log.h" | ||
| 8 | #include "common/emu_window.h" | 7 | #include "common/emu_window.h" |
| 8 | #include "common/logging/log.h" | ||
| 9 | 9 | ||
| 10 | #include "core/hle/service/service.h" | ||
| 11 | #include "core/hle/service/hid/hid.h" | 10 | #include "core/hle/service/hid/hid.h" |
| 12 | #include "core/hle/service/hid/hid_spvr.h" | 11 | #include "core/hle/service/hid/hid_spvr.h" |
| 13 | #include "core/hle/service/hid/hid_user.h" | 12 | #include "core/hle/service/hid/hid_user.h" |
| 13 | #include "core/hle/service/service.h" | ||
| 14 | 14 | ||
| 15 | #include "core/core_timing.h" | 15 | #include "core/core_timing.h" |
| 16 | #include "core/hle/kernel/event.h" | 16 | #include "core/hle/kernel/event.h" |
| @@ -37,11 +37,14 @@ static u32 next_accelerometer_index; | |||
| 37 | static u32 next_gyroscope_index; | 37 | static u32 next_gyroscope_index; |
| 38 | 38 | ||
| 39 | static int enable_accelerometer_count = 0; // positive means enabled | 39 | static int enable_accelerometer_count = 0; // positive means enabled |
| 40 | static int enable_gyroscope_count = 0; // positive means enabled | 40 | static int enable_gyroscope_count = 0; // positive means enabled |
| 41 | 41 | ||
| 42 | static PadState GetCirclePadDirectionState(s16 circle_pad_x, s16 circle_pad_y) { | 42 | static PadState GetCirclePadDirectionState(s16 circle_pad_x, s16 circle_pad_y) { |
| 43 | constexpr float TAN30 = 0.577350269, TAN60 = 1 / TAN30; // 30 degree and 60 degree are angular thresholds for directions | 43 | constexpr float TAN30 = 0.577350269, |
| 44 | constexpr int CIRCLE_PAD_THRESHOLD_SQUARE = 40 * 40; // a circle pad radius greater than 40 will trigger circle pad direction | 44 | TAN60 = |
| 45 | 1 / TAN30; // 30 degree and 60 degree are angular thresholds for directions | ||
| 46 | constexpr int CIRCLE_PAD_THRESHOLD_SQUARE = | ||
| 47 | 40 * 40; // a circle pad radius greater than 40 will trigger circle pad direction | ||
| 45 | PadState state; | 48 | PadState state; |
| 46 | state.hex = 0; | 49 | state.hex = 0; |
| 47 | 50 | ||
| @@ -90,7 +93,7 @@ void Update() { | |||
| 90 | PadState old_state = mem->pad.entries[last_entry_index].current_state; | 93 | PadState old_state = mem->pad.entries[last_entry_index].current_state; |
| 91 | 94 | ||
| 92 | // Compute bitmask with 1s for bits different from the old state | 95 | // Compute bitmask with 1s for bits different from the old state |
| 93 | PadState changed = { { (state.hex ^ old_state.hex) } }; | 96 | PadState changed = {{(state.hex ^ old_state.hex)}}; |
| 94 | 97 | ||
| 95 | // Get the current Pad entry | 98 | // Get the current Pad entry |
| 96 | PadDataEntry& pad_entry = mem->pad.entries[mem->pad.index]; | 99 | PadDataEntry& pad_entry = mem->pad.entries[mem->pad.index]; |
| @@ -135,11 +138,13 @@ void Update() { | |||
| 135 | // Update accelerometer | 138 | // Update accelerometer |
| 136 | if (enable_accelerometer_count > 0) { | 139 | if (enable_accelerometer_count > 0) { |
| 137 | mem->accelerometer.index = next_accelerometer_index; | 140 | mem->accelerometer.index = next_accelerometer_index; |
| 138 | next_accelerometer_index = (next_accelerometer_index + 1) % mem->accelerometer.entries.size(); | 141 | next_accelerometer_index = |
| 142 | (next_accelerometer_index + 1) % mem->accelerometer.entries.size(); | ||
| 139 | 143 | ||
| 140 | AccelerometerDataEntry& accelerometer_entry = mem->accelerometer.entries[mem->accelerometer.index]; | 144 | AccelerometerDataEntry& accelerometer_entry = |
| 141 | std::tie(accelerometer_entry.x, accelerometer_entry.y, accelerometer_entry.z) | 145 | mem->accelerometer.entries[mem->accelerometer.index]; |
| 142 | = VideoCore::g_emu_window->GetAccelerometerState(); | 146 | std::tie(accelerometer_entry.x, accelerometer_entry.y, accelerometer_entry.z) = |
| 147 | VideoCore::g_emu_window->GetAccelerometerState(); | ||
| 143 | 148 | ||
| 144 | // Make up "raw" entry | 149 | // Make up "raw" entry |
| 145 | // TODO(wwylele): | 150 | // TODO(wwylele): |
| @@ -167,8 +172,8 @@ void Update() { | |||
| 167 | next_gyroscope_index = (next_gyroscope_index + 1) % mem->gyroscope.entries.size(); | 172 | next_gyroscope_index = (next_gyroscope_index + 1) % mem->gyroscope.entries.size(); |
| 168 | 173 | ||
| 169 | GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index]; | 174 | GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index]; |
| 170 | std::tie(gyroscope_entry.x, gyroscope_entry.y, gyroscope_entry.z) | 175 | std::tie(gyroscope_entry.x, gyroscope_entry.y, gyroscope_entry.z) = |
| 171 | = VideoCore::g_emu_window->GetGyroscopeState(); | 176 | VideoCore::g_emu_window->GetGyroscopeState(); |
| 172 | 177 | ||
| 173 | // Make up "raw" entry | 178 | // Make up "raw" entry |
| 174 | mem->gyroscope.raw_entry.x = gyroscope_entry.x; | 179 | mem->gyroscope.raw_entry.x = gyroscope_entry.x; |
| @@ -188,7 +193,7 @@ void Update() { | |||
| 188 | void GetIPCHandles(Service::Interface* self) { | 193 | void GetIPCHandles(Service::Interface* self) { |
| 189 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 194 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 190 | 195 | ||
| 191 | cmd_buff[1] = 0; // No error | 196 | cmd_buff[1] = 0; // No error |
| 192 | cmd_buff[2] = 0x14000000; // IPC Command Structure translate-header | 197 | cmd_buff[2] = 0x14000000; // IPC Command Structure translate-header |
| 193 | // TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling) | 198 | // TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling) |
| 194 | cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::shared_mem).MoveFrom(); | 199 | cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::shared_mem).MoveFrom(); |
| @@ -259,9 +264,7 @@ void GetGyroscopeLowCalibrateParam(Service::Interface* self) { | |||
| 259 | 264 | ||
| 260 | const s16 param_unit = 6700; // an approximate value taken from hw | 265 | const s16 param_unit = 6700; // an approximate value taken from hw |
| 261 | GyroscopeCalibrateParam param = { | 266 | GyroscopeCalibrateParam param = { |
| 262 | { 0, param_unit, -param_unit }, | 267 | {0, param_unit, -param_unit}, {0, param_unit, -param_unit}, {0, param_unit, -param_unit}, |
| 263 | { 0, param_unit, -param_unit }, | ||
| 264 | { 0, param_unit, -param_unit }, | ||
| 265 | }; | 268 | }; |
| 266 | memcpy(&cmd_buff[2], ¶m, sizeof(param)); | 269 | memcpy(&cmd_buff[2], ¶m, sizeof(param)); |
| 267 | 270 | ||
| @@ -286,9 +289,9 @@ void Init() { | |||
| 286 | AddService(new HID_SPVR_Interface); | 289 | AddService(new HID_SPVR_Interface); |
| 287 | 290 | ||
| 288 | using Kernel::MemoryPermission; | 291 | using Kernel::MemoryPermission; |
| 289 | shared_mem = SharedMemory::Create(nullptr, 0x1000, | 292 | shared_mem = |
| 290 | MemoryPermission::ReadWrite, MemoryPermission::Read, | 293 | SharedMemory::Create(nullptr, 0x1000, MemoryPermission::ReadWrite, MemoryPermission::Read, |
| 291 | 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory"); | 294 | 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory"); |
| 292 | 295 | ||
| 293 | next_pad_index = 0; | 296 | next_pad_index = 0; |
| 294 | next_touch_index = 0; | 297 | next_touch_index = 0; |
| @@ -296,9 +299,9 @@ void Init() { | |||
| 296 | // Create event handles | 299 | // Create event handles |
| 297 | event_pad_or_touch_1 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch1"); | 300 | event_pad_or_touch_1 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch1"); |
| 298 | event_pad_or_touch_2 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch2"); | 301 | event_pad_or_touch_2 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch2"); |
| 299 | event_accelerometer = Event::Create(ResetType::OneShot, "HID:EventAccelerometer"); | 302 | event_accelerometer = Event::Create(ResetType::OneShot, "HID:EventAccelerometer"); |
| 300 | event_gyroscope = Event::Create(ResetType::OneShot, "HID:EventGyroscope"); | 303 | event_gyroscope = Event::Create(ResetType::OneShot, "HID:EventGyroscope"); |
| 301 | event_debug_pad = Event::Create(ResetType::OneShot, "HID:EventDebugPad"); | 304 | event_debug_pad = Event::Create(ResetType::OneShot, "HID:EventDebugPad"); |
| 302 | } | 305 | } |
| 303 | 306 | ||
| 304 | void Shutdown() { | 307 | void Shutdown() { |
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 669b1f723..f54ffd8be 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h | |||
| @@ -9,10 +9,10 @@ | |||
| 9 | #ifndef _MSC_VER | 9 | #ifndef _MSC_VER |
| 10 | #include <cstddef> | 10 | #include <cstddef> |
| 11 | #endif | 11 | #endif |
| 12 | #include "core/settings.h" | ||
| 13 | #include "common/bit_field.h" | 12 | #include "common/bit_field.h" |
| 14 | #include "common/common_funcs.h" | 13 | #include "common/common_funcs.h" |
| 15 | #include "common/common_types.h" | 14 | #include "common/common_types.h" |
| 15 | #include "core/settings.h" | ||
| 16 | 16 | ||
| 17 | namespace Service { | 17 | namespace Service { |
| 18 | 18 | ||
| @@ -103,7 +103,7 @@ struct SharedMem { | |||
| 103 | struct { | 103 | struct { |
| 104 | s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 | 104 | s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 |
| 105 | s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks` | 105 | s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks` |
| 106 | u32 index; ///< Index of the last updated pad state entry | 106 | u32 index; ///< Index of the last updated pad state entry |
| 107 | 107 | ||
| 108 | INSERT_PADDING_WORDS(0x2); | 108 | INSERT_PADDING_WORDS(0x2); |
| 109 | 109 | ||
| @@ -121,7 +121,7 @@ struct SharedMem { | |||
| 121 | struct { | 121 | struct { |
| 122 | s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 | 122 | s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 |
| 123 | s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks` | 123 | s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks` |
| 124 | u32 index; ///< Index of the last updated touch entry | 124 | u32 index; ///< Index of the last updated touch entry |
| 125 | 125 | ||
| 126 | INSERT_PADDING_WORDS(0x1); | 126 | INSERT_PADDING_WORDS(0x1); |
| 127 | 127 | ||
| @@ -135,7 +135,7 @@ struct SharedMem { | |||
| 135 | struct { | 135 | struct { |
| 136 | s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 | 136 | s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 |
| 137 | s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks` | 137 | s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks` |
| 138 | u32 index; ///< Index of the last updated accelerometer entry | 138 | u32 index; ///< Index of the last updated accelerometer entry |
| 139 | 139 | ||
| 140 | INSERT_PADDING_WORDS(0x1); | 140 | INSERT_PADDING_WORDS(0x1); |
| 141 | 141 | ||
| @@ -149,7 +149,7 @@ struct SharedMem { | |||
| 149 | struct { | 149 | struct { |
| 150 | s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 | 150 | s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 |
| 151 | s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks` | 151 | s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks` |
| 152 | u32 index; ///< Index of the last updated accelerometer entry | 152 | u32 index; ///< Index of the last updated accelerometer entry |
| 153 | 153 | ||
| 154 | INSERT_PADDING_WORDS(0x1); | 154 | INSERT_PADDING_WORDS(0x1); |
| 155 | 155 | ||
| @@ -176,9 +176,9 @@ struct GyroscopeCalibrateParam { | |||
| 176 | // is technically allowed since C++11. This macro should be enabled once MSVC adds | 176 | // is technically allowed since C++11. This macro should be enabled once MSVC adds |
| 177 | // support for that. | 177 | // support for that. |
| 178 | #ifndef _MSC_VER | 178 | #ifndef _MSC_VER |
| 179 | #define ASSERT_REG_POSITION(field_name, position) \ | 179 | #define ASSERT_REG_POSITION(field_name, position) \ |
| 180 | static_assert(offsetof(SharedMem, field_name) == position * 4, \ | 180 | static_assert(offsetof(SharedMem, field_name) == position * 4, \ |
| 181 | "Field "#field_name" has invalid position") | 181 | "Field " #field_name " has invalid position") |
| 182 | 182 | ||
| 183 | ASSERT_REG_POSITION(pad.index_reset_ticks, 0x0); | 183 | ASSERT_REG_POSITION(pad.index_reset_ticks, 0x0); |
| 184 | ASSERT_REG_POSITION(touch.index_reset_ticks, 0x2A); | 184 | ASSERT_REG_POSITION(touch.index_reset_ticks, 0x2A); |
| @@ -187,33 +187,33 @@ ASSERT_REG_POSITION(touch.index_reset_ticks, 0x2A); | |||
| 187 | #endif // !defined(_MSC_VER) | 187 | #endif // !defined(_MSC_VER) |
| 188 | 188 | ||
| 189 | // Pre-defined PadStates for single button presses | 189 | // Pre-defined PadStates for single button presses |
| 190 | const PadState PAD_NONE = {{0}}; | 190 | const PadState PAD_NONE = {{0}}; |
| 191 | const PadState PAD_A = {{1u << 0}}; | 191 | const PadState PAD_A = {{1u << 0}}; |
| 192 | const PadState PAD_B = {{1u << 1}}; | 192 | const PadState PAD_B = {{1u << 1}}; |
| 193 | const PadState PAD_SELECT = {{1u << 2}}; | 193 | const PadState PAD_SELECT = {{1u << 2}}; |
| 194 | const PadState PAD_START = {{1u << 3}}; | 194 | const PadState PAD_START = {{1u << 3}}; |
| 195 | const PadState PAD_RIGHT = {{1u << 4}}; | 195 | const PadState PAD_RIGHT = {{1u << 4}}; |
| 196 | const PadState PAD_LEFT = {{1u << 5}}; | 196 | const PadState PAD_LEFT = {{1u << 5}}; |
| 197 | const PadState PAD_UP = {{1u << 6}}; | 197 | const PadState PAD_UP = {{1u << 6}}; |
| 198 | const PadState PAD_DOWN = {{1u << 7}}; | 198 | const PadState PAD_DOWN = {{1u << 7}}; |
| 199 | const PadState PAD_R = {{1u << 8}}; | 199 | const PadState PAD_R = {{1u << 8}}; |
| 200 | const PadState PAD_L = {{1u << 9}}; | 200 | const PadState PAD_L = {{1u << 9}}; |
| 201 | const PadState PAD_X = {{1u << 10}}; | 201 | const PadState PAD_X = {{1u << 10}}; |
| 202 | const PadState PAD_Y = {{1u << 11}}; | 202 | const PadState PAD_Y = {{1u << 11}}; |
| 203 | 203 | ||
| 204 | const PadState PAD_ZL = {{1u << 14}}; | 204 | const PadState PAD_ZL = {{1u << 14}}; |
| 205 | const PadState PAD_ZR = {{1u << 15}}; | 205 | const PadState PAD_ZR = {{1u << 15}}; |
| 206 | 206 | ||
| 207 | const PadState PAD_TOUCH = {{1u << 20}}; | 207 | const PadState PAD_TOUCH = {{1u << 20}}; |
| 208 | 208 | ||
| 209 | const PadState PAD_C_RIGHT = {{1u << 24}}; | 209 | const PadState PAD_C_RIGHT = {{1u << 24}}; |
| 210 | const PadState PAD_C_LEFT = {{1u << 25}}; | 210 | const PadState PAD_C_LEFT = {{1u << 25}}; |
| 211 | const PadState PAD_C_UP = {{1u << 26}}; | 211 | const PadState PAD_C_UP = {{1u << 26}}; |
| 212 | const PadState PAD_C_DOWN = {{1u << 27}}; | 212 | const PadState PAD_C_DOWN = {{1u << 27}}; |
| 213 | const PadState PAD_CIRCLE_RIGHT = {{1u << 28}}; | 213 | const PadState PAD_CIRCLE_RIGHT = {{1u << 28}}; |
| 214 | const PadState PAD_CIRCLE_LEFT = {{1u << 29}}; | 214 | const PadState PAD_CIRCLE_LEFT = {{1u << 29}}; |
| 215 | const PadState PAD_CIRCLE_UP = {{1u << 30}}; | 215 | const PadState PAD_CIRCLE_UP = {{1u << 30}}; |
| 216 | const PadState PAD_CIRCLE_DOWN = {{1u << 31}}; | 216 | const PadState PAD_CIRCLE_DOWN = {{1u << 31}}; |
| 217 | 217 | ||
| 218 | /** | 218 | /** |
| 219 | * HID::GetIPCHandles service function | 219 | * HID::GetIPCHandles service function |
| @@ -305,6 +305,5 @@ void Init(); | |||
| 305 | 305 | ||
| 306 | /// Shutdown HID service | 306 | /// Shutdown HID service |
| 307 | void Shutdown(); | 307 | void Shutdown(); |
| 308 | |||
| 309 | } | 308 | } |
| 310 | } | 309 | } |
diff --git a/src/core/hle/service/hid/hid_spvr.cpp b/src/core/hle/service/hid/hid_spvr.cpp index 046e65b11..09007e304 100644 --- a/src/core/hle/service/hid/hid_spvr.cpp +++ b/src/core/hle/service/hid/hid_spvr.cpp | |||
| @@ -9,16 +9,16 @@ namespace Service { | |||
| 9 | namespace HID { | 9 | namespace HID { |
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = { |
| 12 | {0x000A0000, GetIPCHandles, "GetIPCHandles"}, | 12 | {0x000A0000, GetIPCHandles, "GetIPCHandles"}, |
| 13 | {0x000B0000, nullptr, "StartAnalogStickCalibration"}, | 13 | {0x000B0000, nullptr, "StartAnalogStickCalibration"}, |
| 14 | {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"}, | 14 | {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"}, |
| 15 | {0x00110000, EnableAccelerometer, "EnableAccelerometer"}, | 15 | {0x00110000, EnableAccelerometer, "EnableAccelerometer"}, |
| 16 | {0x00120000, DisableAccelerometer, "DisableAccelerometer"}, | 16 | {0x00120000, DisableAccelerometer, "DisableAccelerometer"}, |
| 17 | {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"}, | 17 | {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"}, |
| 18 | {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"}, | 18 | {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"}, |
| 19 | {0x00150000, GetGyroscopeLowRawToDpsCoefficient, "GetGyroscopeLowRawToDpsCoefficient"}, | 19 | {0x00150000, GetGyroscopeLowRawToDpsCoefficient, "GetGyroscopeLowRawToDpsCoefficient"}, |
| 20 | {0x00160000, GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"}, | 20 | {0x00160000, GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"}, |
| 21 | {0x00170000, GetSoundVolume, "GetSoundVolume"}, | 21 | {0x00170000, GetSoundVolume, "GetSoundVolume"}, |
| 22 | }; | 22 | }; |
| 23 | 23 | ||
| 24 | HID_SPVR_Interface::HID_SPVR_Interface() { | 24 | HID_SPVR_Interface::HID_SPVR_Interface() { |
diff --git a/src/core/hle/service/hid/hid_user.cpp b/src/core/hle/service/hid/hid_user.cpp index bb157b83d..42591543c 100644 --- a/src/core/hle/service/hid/hid_user.cpp +++ b/src/core/hle/service/hid/hid_user.cpp | |||
| @@ -9,16 +9,16 @@ namespace Service { | |||
| 9 | namespace HID { | 9 | namespace HID { |
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = { |
| 12 | {0x000A0000, GetIPCHandles, "GetIPCHandles"}, | 12 | {0x000A0000, GetIPCHandles, "GetIPCHandles"}, |
| 13 | {0x000B0000, nullptr, "StartAnalogStickCalibration"}, | 13 | {0x000B0000, nullptr, "StartAnalogStickCalibration"}, |
| 14 | {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"}, | 14 | {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"}, |
| 15 | {0x00110000, EnableAccelerometer, "EnableAccelerometer"}, | 15 | {0x00110000, EnableAccelerometer, "EnableAccelerometer"}, |
| 16 | {0x00120000, DisableAccelerometer, "DisableAccelerometer"}, | 16 | {0x00120000, DisableAccelerometer, "DisableAccelerometer"}, |
| 17 | {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"}, | 17 | {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"}, |
| 18 | {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"}, | 18 | {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"}, |
| 19 | {0x00150000, GetGyroscopeLowRawToDpsCoefficient, "GetGyroscopeLowRawToDpsCoefficient"}, | 19 | {0x00150000, GetGyroscopeLowRawToDpsCoefficient, "GetGyroscopeLowRawToDpsCoefficient"}, |
| 20 | {0x00160000, GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"}, | 20 | {0x00160000, GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"}, |
| 21 | {0x00170000, GetSoundVolume, "GetSoundVolume"}, | 21 | {0x00170000, GetSoundVolume, "GetSoundVolume"}, |
| 22 | }; | 22 | }; |
| 23 | 23 | ||
| 24 | HID_U_Interface::HID_U_Interface() { | 24 | HID_U_Interface::HID_U_Interface() { |
diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index 0855ab227..3cf62a4b8 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp | |||
| @@ -10,56 +10,56 @@ | |||
| 10 | namespace HTTP_C { | 10 | namespace HTTP_C { |
| 11 | 11 | ||
| 12 | const Interface::FunctionInfo FunctionTable[] = { | 12 | const Interface::FunctionInfo FunctionTable[] = { |
| 13 | {0x00010044, nullptr, "Initialize"}, | 13 | {0x00010044, nullptr, "Initialize"}, |
| 14 | {0x00020082, nullptr, "CreateContext"}, | 14 | {0x00020082, nullptr, "CreateContext"}, |
| 15 | {0x00030040, nullptr, "CloseContext"}, | 15 | {0x00030040, nullptr, "CloseContext"}, |
| 16 | {0x00040040, nullptr, "CancelConnection"}, | 16 | {0x00040040, nullptr, "CancelConnection"}, |
| 17 | {0x00050040, nullptr, "GetRequestState"}, | 17 | {0x00050040, nullptr, "GetRequestState"}, |
| 18 | {0x00060040, nullptr, "GetDownloadSizeState"}, | 18 | {0x00060040, nullptr, "GetDownloadSizeState"}, |
| 19 | {0x00070040, nullptr, "GetRequestError"}, | 19 | {0x00070040, nullptr, "GetRequestError"}, |
| 20 | {0x00080042, nullptr, "InitializeConnectionSession"}, | 20 | {0x00080042, nullptr, "InitializeConnectionSession"}, |
| 21 | {0x00090040, nullptr, "BeginRequest"}, | 21 | {0x00090040, nullptr, "BeginRequest"}, |
| 22 | {0x000A0040, nullptr, "BeginRequestAsync"}, | 22 | {0x000A0040, nullptr, "BeginRequestAsync"}, |
| 23 | {0x000B0082, nullptr, "ReceiveData"}, | 23 | {0x000B0082, nullptr, "ReceiveData"}, |
| 24 | {0x000C0102, nullptr, "ReceiveDataTimeout"}, | 24 | {0x000C0102, nullptr, "ReceiveDataTimeout"}, |
| 25 | {0x000D0146, nullptr, "SetProxy"}, | 25 | {0x000D0146, nullptr, "SetProxy"}, |
| 26 | {0x000E0040, nullptr, "SetProxyDefault"}, | 26 | {0x000E0040, nullptr, "SetProxyDefault"}, |
| 27 | {0x000F00C4, nullptr, "SetBasicAuthorization"}, | 27 | {0x000F00C4, nullptr, "SetBasicAuthorization"}, |
| 28 | {0x00100080, nullptr, "SetSocketBufferSize"}, | 28 | {0x00100080, nullptr, "SetSocketBufferSize"}, |
| 29 | {0x001100C4, nullptr, "AddRequestHeader"}, | 29 | {0x001100C4, nullptr, "AddRequestHeader"}, |
| 30 | {0x001200C4, nullptr, "AddPostDataAscii"}, | 30 | {0x001200C4, nullptr, "AddPostDataAscii"}, |
| 31 | {0x001300C4, nullptr, "AddPostDataBinary"}, | 31 | {0x001300C4, nullptr, "AddPostDataBinary"}, |
| 32 | {0x00140082, nullptr, "AddPostDataRaw"}, | 32 | {0x00140082, nullptr, "AddPostDataRaw"}, |
| 33 | {0x00150080, nullptr, "SetPostDataType"}, | 33 | {0x00150080, nullptr, "SetPostDataType"}, |
| 34 | {0x001600C4, nullptr, "SendPostDataAscii"}, | 34 | {0x001600C4, nullptr, "SendPostDataAscii"}, |
| 35 | {0x00170144, nullptr, "SendPostDataAsciiTimeout"}, | 35 | {0x00170144, nullptr, "SendPostDataAsciiTimeout"}, |
| 36 | {0x001800C4, nullptr, "SendPostDataBinary"}, | 36 | {0x001800C4, nullptr, "SendPostDataBinary"}, |
| 37 | {0x00190144, nullptr, "SendPostDataBinaryTimeout"}, | 37 | {0x00190144, nullptr, "SendPostDataBinaryTimeout"}, |
| 38 | {0x001A0082, nullptr, "SendPostDataRaw"}, | 38 | {0x001A0082, nullptr, "SendPostDataRaw"}, |
| 39 | {0x001B0102, nullptr, "SendPOSTDataRawTimeout"}, | 39 | {0x001B0102, nullptr, "SendPOSTDataRawTimeout"}, |
| 40 | {0x001C0080, nullptr, "SetPostDataEncoding"}, | 40 | {0x001C0080, nullptr, "SetPostDataEncoding"}, |
| 41 | {0x001D0040, nullptr, "NotifyFinishSendPostData"}, | 41 | {0x001D0040, nullptr, "NotifyFinishSendPostData"}, |
| 42 | {0x001E00C4, nullptr, "GetResponseHeader"}, | 42 | {0x001E00C4, nullptr, "GetResponseHeader"}, |
| 43 | {0x001F0144, nullptr, "GetResponseHeaderTimeout"}, | 43 | {0x001F0144, nullptr, "GetResponseHeaderTimeout"}, |
| 44 | {0x00200082, nullptr, "GetResponseData"}, | 44 | {0x00200082, nullptr, "GetResponseData"}, |
| 45 | {0x00210102, nullptr, "GetResponseDataTimeout"}, | 45 | {0x00210102, nullptr, "GetResponseDataTimeout"}, |
| 46 | {0x00220040, nullptr, "GetResponseStatusCode"}, | 46 | {0x00220040, nullptr, "GetResponseStatusCode"}, |
| 47 | {0x002300C0, nullptr, "GetResponseStatusCodeTimeout"}, | 47 | {0x002300C0, nullptr, "GetResponseStatusCodeTimeout"}, |
| 48 | {0x00240082, nullptr, "AddTrustedRootCA"}, | 48 | {0x00240082, nullptr, "AddTrustedRootCA"}, |
| 49 | {0x00250080, nullptr, "AddDefaultCert"}, | 49 | {0x00250080, nullptr, "AddDefaultCert"}, |
| 50 | {0x00260080, nullptr, "SelectRootCertChain"}, | 50 | {0x00260080, nullptr, "SelectRootCertChain"}, |
| 51 | {0x002700C4, nullptr, "SetClientCert"}, | 51 | {0x002700C4, nullptr, "SetClientCert"}, |
| 52 | {0x002B0080, nullptr, "SetSSLOpt"}, | 52 | {0x002B0080, nullptr, "SetSSLOpt"}, |
| 53 | {0x002C0080, nullptr, "SetSSLClearOpt"}, | 53 | {0x002C0080, nullptr, "SetSSLClearOpt"}, |
| 54 | {0x002D0000, nullptr, "CreateRootCertChain"}, | 54 | {0x002D0000, nullptr, "CreateRootCertChain"}, |
| 55 | {0x002E0040, nullptr, "DestroyRootCertChain"}, | 55 | {0x002E0040, nullptr, "DestroyRootCertChain"}, |
| 56 | {0x002F0082, nullptr, "RootCertChainAddCert"}, | 56 | {0x002F0082, nullptr, "RootCertChainAddCert"}, |
| 57 | {0x00300080, nullptr, "RootCertChainAddDefaultCert"}, | 57 | {0x00300080, nullptr, "RootCertChainAddDefaultCert"}, |
| 58 | {0x00350186, nullptr, "SetDefaultProxy"}, | 58 | {0x00350186, nullptr, "SetDefaultProxy"}, |
| 59 | {0x00360000, nullptr, "ClearDNSCache"}, | 59 | {0x00360000, nullptr, "ClearDNSCache"}, |
| 60 | {0x00370080, nullptr, "SetKeepAlive"}, | 60 | {0x00370080, nullptr, "SetKeepAlive"}, |
| 61 | {0x003800C0, nullptr, "SetPostDataTypeSize"}, | 61 | {0x003800C0, nullptr, "SetPostDataTypeSize"}, |
| 62 | {0x00390000, nullptr, "Finalize"}, | 62 | {0x00390000, nullptr, "Finalize"}, |
| 63 | }; | 63 | }; |
| 64 | 64 | ||
| 65 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 65 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
diff --git a/src/core/hle/service/ir/ir.cpp b/src/core/hle/service/ir/ir.cpp index 079a87e48..fc048ae88 100644 --- a/src/core/hle/service/ir/ir.cpp +++ b/src/core/hle/service/ir/ir.cpp | |||
| @@ -5,11 +5,11 @@ | |||
| 5 | #include "core/hle/kernel/event.h" | 5 | #include "core/hle/kernel/event.h" |
| 6 | #include "core/hle/kernel/shared_memory.h" | 6 | #include "core/hle/kernel/shared_memory.h" |
| 7 | 7 | ||
| 8 | #include "core/hle/service/service.h" | ||
| 9 | #include "core/hle/service/ir/ir.h" | 8 | #include "core/hle/service/ir/ir.h" |
| 10 | #include "core/hle/service/ir/ir_rst.h" | 9 | #include "core/hle/service/ir/ir_rst.h" |
| 11 | #include "core/hle/service/ir/ir_u.h" | 10 | #include "core/hle/service/ir/ir_u.h" |
| 12 | #include "core/hle/service/ir/ir_user.h" | 11 | #include "core/hle/service/ir/ir_user.h" |
| 12 | #include "core/hle/service/service.h" | ||
| 13 | 13 | ||
| 14 | namespace Service { | 14 | namespace Service { |
| 15 | namespace IR { | 15 | namespace IR { |
| @@ -32,14 +32,14 @@ void InitializeIrNopShared(Interface* self) { | |||
| 32 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 32 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 33 | 33 | ||
| 34 | u32 transfer_buff_size = cmd_buff[1]; | 34 | u32 transfer_buff_size = cmd_buff[1]; |
| 35 | u32 recv_buff_size = cmd_buff[2]; | 35 | u32 recv_buff_size = cmd_buff[2]; |
| 36 | u32 unk1 = cmd_buff[3]; | 36 | u32 unk1 = cmd_buff[3]; |
| 37 | u32 send_buff_size = cmd_buff[4]; | 37 | u32 send_buff_size = cmd_buff[4]; |
| 38 | u32 unk2 = cmd_buff[5]; | 38 | u32 unk2 = cmd_buff[5]; |
| 39 | u8 baud_rate = cmd_buff[6] & 0xFF; | 39 | u8 baud_rate = cmd_buff[6] & 0xFF; |
| 40 | Handle handle = cmd_buff[8]; | 40 | Handle handle = cmd_buff[8]; |
| 41 | 41 | ||
| 42 | if(Kernel::g_handle_table.IsValid(handle)) { | 42 | if (Kernel::g_handle_table.IsValid(handle)) { |
| 43 | transfer_shared_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(handle); | 43 | transfer_shared_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(handle); |
| 44 | transfer_shared_memory->name = "IR:TransferSharedMemory"; | 44 | transfer_shared_memory->name = "IR:TransferSharedMemory"; |
| 45 | } | 45 | } |
| @@ -47,7 +47,7 @@ void InitializeIrNopShared(Interface* self) { | |||
| 47 | cmd_buff[1] = RESULT_SUCCESS.raw; | 47 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 48 | 48 | ||
| 49 | LOG_WARNING(Service_IR, "(STUBBED) called, transfer_buff_size=%d, recv_buff_size=%d, " | 49 | LOG_WARNING(Service_IR, "(STUBBED) called, transfer_buff_size=%d, recv_buff_size=%d, " |
| 50 | "unk1=%d, send_buff_size=%d, unk2=%d, baud_rate=%u, handle=0x%08X", | 50 | "unk1=%d, send_buff_size=%d, unk2=%d, baud_rate=%u, handle=0x%08X", |
| 51 | transfer_buff_size, recv_buff_size, unk1, send_buff_size, unk2, baud_rate, handle); | 51 | transfer_buff_size, recv_buff_size, unk1, send_buff_size, unk2, baud_rate, handle); |
| 52 | } | 52 | } |
| 53 | 53 | ||
| @@ -94,13 +94,13 @@ void Init() { | |||
| 94 | AddService(new IR_User_Interface); | 94 | AddService(new IR_User_Interface); |
| 95 | 95 | ||
| 96 | using Kernel::MemoryPermission; | 96 | using Kernel::MemoryPermission; |
| 97 | shared_memory = SharedMemory::Create(nullptr, 0x1000, | 97 | shared_memory = SharedMemory::Create(nullptr, 0x1000, Kernel::MemoryPermission::ReadWrite, |
| 98 | Kernel::MemoryPermission::ReadWrite, Kernel::MemoryPermission::ReadWrite, | 98 | Kernel::MemoryPermission::ReadWrite, 0, |
| 99 | 0, Kernel::MemoryRegion::BASE, "IR:SharedMemory"); | 99 | Kernel::MemoryRegion::BASE, "IR:SharedMemory"); |
| 100 | transfer_shared_memory = nullptr; | 100 | transfer_shared_memory = nullptr; |
| 101 | 101 | ||
| 102 | // Create event handle(s) | 102 | // Create event handle(s) |
| 103 | handle_event = Event::Create(ResetType::OneShot, "IR:HandleEvent"); | 103 | handle_event = Event::Create(ResetType::OneShot, "IR:HandleEvent"); |
| 104 | conn_status_event = Event::Create(ResetType::OneShot, "IR:ConnectionStatusEvent"); | 104 | conn_status_event = Event::Create(ResetType::OneShot, "IR:ConnectionStatusEvent"); |
| 105 | } | 105 | } |
| 106 | 106 | ||
diff --git a/src/core/hle/service/ir/ir_rst.cpp b/src/core/hle/service/ir/ir_rst.cpp index c0300f109..1f10ebd3d 100644 --- a/src/core/hle/service/ir/ir_rst.cpp +++ b/src/core/hle/service/ir/ir_rst.cpp | |||
| @@ -9,10 +9,10 @@ namespace Service { | |||
| 9 | namespace IR { | 9 | namespace IR { |
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = { |
| 12 | {0x00010000, GetHandles, "GetHandles"}, | 12 | {0x00010000, GetHandles, "GetHandles"}, |
| 13 | {0x00020080, nullptr, "Initialize"}, | 13 | {0x00020080, nullptr, "Initialize"}, |
| 14 | {0x00030000, nullptr, "Shutdown"}, | 14 | {0x00030000, nullptr, "Shutdown"}, |
| 15 | {0x00090000, nullptr, "WriteToTwoFields"}, | 15 | {0x00090000, nullptr, "WriteToTwoFields"}, |
| 16 | }; | 16 | }; |
| 17 | 17 | ||
| 18 | IR_RST_Interface::IR_RST_Interface() { | 18 | IR_RST_Interface::IR_RST_Interface() { |
diff --git a/src/core/hle/service/ir/ir_u.cpp b/src/core/hle/service/ir/ir_u.cpp index 96f76cb83..be4049da9 100644 --- a/src/core/hle/service/ir/ir_u.cpp +++ b/src/core/hle/service/ir/ir_u.cpp | |||
| @@ -8,24 +8,15 @@ namespace Service { | |||
| 8 | namespace IR { | 8 | namespace IR { |
| 9 | 9 | ||
| 10 | const Interface::FunctionInfo FunctionTable[] = { | 10 | const Interface::FunctionInfo FunctionTable[] = { |
| 11 | {0x00010000, nullptr, "Initialize"}, | 11 | {0x00010000, nullptr, "Initialize"}, {0x00020000, nullptr, "Shutdown"}, |
| 12 | {0x00020000, nullptr, "Shutdown"}, | 12 | {0x00030042, nullptr, "StartSendTransfer"}, {0x00040000, nullptr, "WaitSendTransfer"}, |
| 13 | {0x00030042, nullptr, "StartSendTransfer"}, | 13 | {0x000500C2, nullptr, "StartRecvTransfer"}, {0x00060000, nullptr, "WaitRecvTransfer"}, |
| 14 | {0x00040000, nullptr, "WaitSendTransfer"}, | 14 | {0x00070080, nullptr, "GetRecvTransferCount"}, {0x00080000, nullptr, "GetSendState"}, |
| 15 | {0x000500C2, nullptr, "StartRecvTransfer"}, | 15 | {0x00090040, nullptr, "SetBitRate"}, {0x000A0000, nullptr, "GetBitRate"}, |
| 16 | {0x00060000, nullptr, "WaitRecvTransfer"}, | 16 | {0x000B0040, nullptr, "SetIRLEDState"}, {0x000C0000, nullptr, "GetIRLEDRecvState"}, |
| 17 | {0x00070080, nullptr, "GetRecvTransferCount"}, | 17 | {0x000D0000, nullptr, "GetSendFinishedEvent"}, {0x000E0000, nullptr, "GetRecvFinishedEvent"}, |
| 18 | {0x00080000, nullptr, "GetSendState"}, | 18 | {0x000F0000, nullptr, "GetTransferState"}, {0x00100000, nullptr, "GetErrorStatus"}, |
| 19 | {0x00090040, nullptr, "SetBitRate"}, | 19 | {0x00110040, nullptr, "SetSleepModeActive"}, {0x00120040, nullptr, "SetSleepModeState"}, |
| 20 | {0x000A0000, nullptr, "GetBitRate"}, | ||
| 21 | {0x000B0040, nullptr, "SetIRLEDState"}, | ||
| 22 | {0x000C0000, nullptr, "GetIRLEDRecvState"}, | ||
| 23 | {0x000D0000, nullptr, "GetSendFinishedEvent"}, | ||
| 24 | {0x000E0000, nullptr, "GetRecvFinishedEvent"}, | ||
| 25 | {0x000F0000, nullptr, "GetTransferState"}, | ||
| 26 | {0x00100000, nullptr, "GetErrorStatus"}, | ||
| 27 | {0x00110040, nullptr, "SetSleepModeActive"}, | ||
| 28 | {0x00120040, nullptr, "SetSleepModeState"}, | ||
| 29 | }; | 20 | }; |
| 30 | 21 | ||
| 31 | IR_U_Interface::IR_U_Interface() { | 22 | IR_U_Interface::IR_U_Interface() { |
diff --git a/src/core/hle/service/ir/ir_user.cpp b/src/core/hle/service/ir/ir_user.cpp index 06a601029..6cff1d544 100644 --- a/src/core/hle/service/ir/ir_user.cpp +++ b/src/core/hle/service/ir/ir_user.cpp | |||
| @@ -9,32 +9,32 @@ namespace Service { | |||
| 9 | namespace IR { | 9 | namespace IR { |
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = { |
| 12 | {0x00010182, nullptr, "InitializeIrNop"}, | 12 | {0x00010182, nullptr, "InitializeIrNop"}, |
| 13 | {0x00020000, FinalizeIrNop, "FinalizeIrNop"}, | 13 | {0x00020000, FinalizeIrNop, "FinalizeIrNop"}, |
| 14 | {0x00030000, nullptr, "ClearReceiveBuffer"}, | 14 | {0x00030000, nullptr, "ClearReceiveBuffer"}, |
| 15 | {0x00040000, nullptr, "ClearSendBuffer"}, | 15 | {0x00040000, nullptr, "ClearSendBuffer"}, |
| 16 | {0x000500C0, nullptr, "WaitConnection"}, | 16 | {0x000500C0, nullptr, "WaitConnection"}, |
| 17 | {0x00060040, RequireConnection, "RequireConnection"}, | 17 | {0x00060040, RequireConnection, "RequireConnection"}, |
| 18 | {0x000702C0, nullptr, "AutoConnection"}, | 18 | {0x000702C0, nullptr, "AutoConnection"}, |
| 19 | {0x00080000, nullptr, "AnyConnection"}, | 19 | {0x00080000, nullptr, "AnyConnection"}, |
| 20 | {0x00090000, Disconnect, "Disconnect"}, | 20 | {0x00090000, Disconnect, "Disconnect"}, |
| 21 | {0x000A0000, nullptr, "GetReceiveEvent"}, | 21 | {0x000A0000, nullptr, "GetReceiveEvent"}, |
| 22 | {0x000B0000, nullptr, "GetSendEvent"}, | 22 | {0x000B0000, nullptr, "GetSendEvent"}, |
| 23 | {0x000C0000, GetConnectionStatusEvent, "GetConnectionStatusEvent"}, | 23 | {0x000C0000, GetConnectionStatusEvent, "GetConnectionStatusEvent"}, |
| 24 | {0x000D0042, nullptr, "SendIrNop"}, | 24 | {0x000D0042, nullptr, "SendIrNop"}, |
| 25 | {0x000E0042, nullptr, "SendIrNopLarge"}, | 25 | {0x000E0042, nullptr, "SendIrNopLarge"}, |
| 26 | {0x000F0040, nullptr, "ReceiveIrnop"}, | 26 | {0x000F0040, nullptr, "ReceiveIrnop"}, |
| 27 | {0x00100042, nullptr, "ReceiveIrnopLarge"}, | 27 | {0x00100042, nullptr, "ReceiveIrnopLarge"}, |
| 28 | {0x00110040, nullptr, "GetLatestReceiveErrorResult"}, | 28 | {0x00110040, nullptr, "GetLatestReceiveErrorResult"}, |
| 29 | {0x00120040, nullptr, "GetLatestSendErrorResult"}, | 29 | {0x00120040, nullptr, "GetLatestSendErrorResult"}, |
| 30 | {0x00130000, nullptr, "GetConnectionStatus"}, | 30 | {0x00130000, nullptr, "GetConnectionStatus"}, |
| 31 | {0x00140000, nullptr, "GetTryingToConnectStatus"}, | 31 | {0x00140000, nullptr, "GetTryingToConnectStatus"}, |
| 32 | {0x00150000, nullptr, "GetReceiveSizeFreeAndUsed"}, | 32 | {0x00150000, nullptr, "GetReceiveSizeFreeAndUsed"}, |
| 33 | {0x00160000, nullptr, "GetSendSizeFreeAndUsed"}, | 33 | {0x00160000, nullptr, "GetSendSizeFreeAndUsed"}, |
| 34 | {0x00170000, nullptr, "GetConnectionRole"}, | 34 | {0x00170000, nullptr, "GetConnectionRole"}, |
| 35 | {0x00180182, InitializeIrNopShared, "InitializeIrNopShared"}, | 35 | {0x00180182, InitializeIrNopShared, "InitializeIrNopShared"}, |
| 36 | {0x00190040, nullptr, "ReleaseReceivedData"}, | 36 | {0x00190040, nullptr, "ReleaseReceivedData"}, |
| 37 | {0x001A0040, nullptr, "SetOwnMachineId"}, | 37 | {0x001A0040, nullptr, "SetOwnMachineId"}, |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | IR_User_Interface::IR_User_Interface() { | 40 | IR_User_Interface::IR_User_Interface() { |
diff --git a/src/core/hle/service/ldr_ro/cro_helper.cpp b/src/core/hle/service/ldr_ro/cro_helper.cpp index 3d2a613ee..5757a4e64 100644 --- a/src/core/hle/service/ldr_ro/cro_helper.cpp +++ b/src/core/hle/service/ldr_ro/cro_helper.cpp | |||
| @@ -14,38 +14,29 @@ | |||
| 14 | namespace LDR_RO { | 14 | namespace LDR_RO { |
| 15 | 15 | ||
| 16 | static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F | 16 | static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F |
| 17 | ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument, ErrorLevel::Usage); | 17 | ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument, |
| 18 | ErrorLevel::Usage); | ||
| 18 | 19 | ||
| 19 | static ResultCode CROFormatError(u32 description) { | 20 | static ResultCode CROFormatError(u32 description) { |
| 20 | return ResultCode(static_cast<ErrorDescription>(description), ErrorModule::RO, ErrorSummary::WrongArgument, ErrorLevel::Permanent); | 21 | return ResultCode(static_cast<ErrorDescription>(description), ErrorModule::RO, |
| 22 | ErrorSummary::WrongArgument, ErrorLevel::Permanent); | ||
| 21 | } | 23 | } |
| 22 | 24 | ||
| 23 | const std::array<int, 17> CROHelper::ENTRY_SIZE {{ | 25 | const std::array<int, 17> CROHelper::ENTRY_SIZE{ |
| 24 | 1, // code | 26 | {1, // code |
| 25 | 1, // data | 27 | 1, // data |
| 26 | 1, // module name | 28 | 1, // module name |
| 27 | sizeof(SegmentEntry), | 29 | sizeof(SegmentEntry), sizeof(ExportNamedSymbolEntry), sizeof(ExportIndexedSymbolEntry), |
| 28 | sizeof(ExportNamedSymbolEntry), | 30 | 1, // export strings |
| 29 | sizeof(ExportIndexedSymbolEntry), | 31 | sizeof(ExportTreeEntry), sizeof(ImportModuleEntry), sizeof(ExternalRelocationEntry), |
| 30 | 1, // export strings | 32 | sizeof(ImportNamedSymbolEntry), sizeof(ImportIndexedSymbolEntry), |
| 31 | sizeof(ExportTreeEntry), | 33 | sizeof(ImportAnonymousSymbolEntry), |
| 32 | sizeof(ImportModuleEntry), | 34 | 1, // import strings |
| 33 | sizeof(ExternalRelocationEntry), | 35 | sizeof(StaticAnonymousSymbolEntry), sizeof(InternalRelocationEntry), |
| 34 | sizeof(ImportNamedSymbolEntry), | 36 | sizeof(StaticRelocationEntry)}}; |
| 35 | sizeof(ImportIndexedSymbolEntry), | 37 | |
| 36 | sizeof(ImportAnonymousSymbolEntry), | 38 | const std::array<CROHelper::HeaderField, 4> CROHelper::FIX_BARRIERS{ |
| 37 | 1, // import strings | 39 | {Fix0Barrier, Fix1Barrier, Fix2Barrier, Fix3Barrier}}; |
| 38 | sizeof(StaticAnonymousSymbolEntry), | ||
| 39 | sizeof(InternalRelocationEntry), | ||
| 40 | sizeof(StaticRelocationEntry) | ||
| 41 | }}; | ||
| 42 | |||
| 43 | const std::array<CROHelper::HeaderField, 4> CROHelper::FIX_BARRIERS {{ | ||
| 44 | Fix0Barrier, | ||
| 45 | Fix1Barrier, | ||
| 46 | Fix2Barrier, | ||
| 47 | Fix3Barrier | ||
| 48 | }}; | ||
| 49 | 40 | ||
| 50 | VAddr CROHelper::SegmentTagToAddress(SegmentTag segment_tag) const { | 41 | VAddr CROHelper::SegmentTagToAddress(SegmentTag segment_tag) const { |
| 51 | u32 segment_num = GetField(SegmentNum); | 42 | u32 segment_num = GetField(SegmentNum); |
| @@ -63,7 +54,7 @@ VAddr CROHelper::SegmentTagToAddress(SegmentTag segment_tag) const { | |||
| 63 | } | 54 | } |
| 64 | 55 | ||
| 65 | ResultCode CROHelper::ApplyRelocation(VAddr target_address, RelocationType relocation_type, | 56 | ResultCode CROHelper::ApplyRelocation(VAddr target_address, RelocationType relocation_type, |
| 66 | u32 addend, u32 symbol_address, u32 target_future_address) { | 57 | u32 addend, u32 symbol_address, u32 target_future_address) { |
| 67 | 58 | ||
| 68 | switch (relocation_type) { | 59 | switch (relocation_type) { |
| 69 | case RelocationType::Nothing: | 60 | case RelocationType::Nothing: |
| @@ -124,7 +115,8 @@ ResultCode CROHelper::ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool | |||
| 124 | return CROFormatError(0x12); | 115 | return CROFormatError(0x12); |
| 125 | } | 116 | } |
| 126 | 117 | ||
| 127 | ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend, symbol_address, relocation_target); | 118 | ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend, |
| 119 | symbol_address, relocation_target); | ||
| 128 | if (result.IsError()) { | 120 | if (result.IsError()) { |
| 129 | LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); | 121 | LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); |
| 130 | return result; | 122 | return result; |
| @@ -167,7 +159,7 @@ VAddr CROHelper::FindExportNamedSymbol(const std::string& name) const { | |||
| 167 | 159 | ||
| 168 | if (test_byte >= len) { | 160 | if (test_byte >= len) { |
| 169 | next.raw = entry.left.raw; | 161 | next.raw = entry.left.raw; |
| 170 | } else if((name[test_byte] >> test_bit_in_byte) & 1) { | 162 | } else if ((name[test_byte] >> test_bit_in_byte) & 1) { |
| 171 | next.raw = entry.right.raw; | 163 | next.raw = entry.right.raw; |
| 172 | } else { | 164 | } else { |
| 173 | next.raw = entry.left.raw; | 165 | next.raw = entry.left.raw; |
| @@ -212,26 +204,13 @@ ResultCode CROHelper::RebaseHeader(u32 cro_size) { | |||
| 212 | return error; | 204 | return error; |
| 213 | 205 | ||
| 214 | // verifies that all offsets are in the correct order | 206 | // verifies that all offsets are in the correct order |
| 215 | constexpr std::array<HeaderField, 18> OFFSET_ORDER = {{ | 207 | constexpr std::array<HeaderField, 18> OFFSET_ORDER = { |
| 216 | CodeOffset, | 208 | {CodeOffset, ModuleNameOffset, SegmentTableOffset, ExportNamedSymbolTableOffset, |
| 217 | ModuleNameOffset, | 209 | ExportTreeTableOffset, ExportIndexedSymbolTableOffset, ExportStringsOffset, |
| 218 | SegmentTableOffset, | 210 | ImportModuleTableOffset, ExternalRelocationTableOffset, ImportNamedSymbolTableOffset, |
| 219 | ExportNamedSymbolTableOffset, | 211 | ImportIndexedSymbolTableOffset, ImportAnonymousSymbolTableOffset, ImportStringsOffset, |
| 220 | ExportTreeTableOffset, | 212 | StaticAnonymousSymbolTableOffset, InternalRelocationTableOffset, |
| 221 | ExportIndexedSymbolTableOffset, | 213 | StaticRelocationTableOffset, DataOffset, FileSize}}; |
| 222 | ExportStringsOffset, | ||
| 223 | ImportModuleTableOffset, | ||
| 224 | ExternalRelocationTableOffset, | ||
| 225 | ImportNamedSymbolTableOffset, | ||
| 226 | ImportIndexedSymbolTableOffset, | ||
| 227 | ImportAnonymousSymbolTableOffset, | ||
| 228 | ImportStringsOffset, | ||
| 229 | StaticAnonymousSymbolTableOffset, | ||
| 230 | InternalRelocationTableOffset, | ||
| 231 | StaticRelocationTableOffset, | ||
| 232 | DataOffset, | ||
| 233 | FileSize | ||
| 234 | }}; | ||
| 235 | 214 | ||
| 236 | u32 prev_offset = GetField(OFFSET_ORDER[0]); | 215 | u32 prev_offset = GetField(OFFSET_ORDER[0]); |
| 237 | u32 cur_offset; | 216 | u32 cur_offset; |
| @@ -266,9 +245,9 @@ ResultCode CROHelper::RebaseHeader(u32 cro_size) { | |||
| 266 | return RESULT_SUCCESS; | 245 | return RESULT_SUCCESS; |
| 267 | } | 246 | } |
| 268 | 247 | ||
| 269 | ResultVal<VAddr> CROHelper::RebaseSegmentTable(u32 cro_size, | 248 | ResultVal<VAddr> CROHelper::RebaseSegmentTable(u32 cro_size, VAddr data_segment_address, |
| 270 | VAddr data_segment_address, u32 data_segment_size, | 249 | u32 data_segment_size, VAddr bss_segment_address, |
| 271 | VAddr bss_segment_address, u32 bss_segment_size) { | 250 | u32 bss_segment_size) { |
| 272 | 251 | ||
| 273 | u32 prev_data_segment = 0; | 252 | u32 prev_data_segment = 0; |
| 274 | u32 segment_num = GetField(SegmentNum); | 253 | u32 segment_num = GetField(SegmentNum); |
| @@ -309,8 +288,8 @@ ResultCode CROHelper::RebaseExportNamedSymbolTable() { | |||
| 309 | 288 | ||
| 310 | if (entry.name_offset != 0) { | 289 | if (entry.name_offset != 0) { |
| 311 | entry.name_offset += module_address; | 290 | entry.name_offset += module_address; |
| 312 | if (entry.name_offset < export_strings_offset | 291 | if (entry.name_offset < export_strings_offset || |
| 313 | || entry.name_offset >= export_strings_end) { | 292 | entry.name_offset >= export_strings_end) { |
| 314 | return CROFormatError(0x11); | 293 | return CROFormatError(0x11); |
| 315 | } | 294 | } |
| 316 | } | 295 | } |
| @@ -337,9 +316,13 @@ ResultCode CROHelper::RebaseImportModuleTable() { | |||
| 337 | VAddr import_strings_offset = GetField(ImportStringsOffset); | 316 | VAddr import_strings_offset = GetField(ImportStringsOffset); |
| 338 | VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize); | 317 | VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize); |
| 339 | VAddr import_indexed_symbol_table_offset = GetField(ImportIndexedSymbolTableOffset); | 318 | VAddr import_indexed_symbol_table_offset = GetField(ImportIndexedSymbolTableOffset); |
| 340 | VAddr index_import_table_end = import_indexed_symbol_table_offset + GetField(ImportIndexedSymbolNum) * sizeof(ImportIndexedSymbolEntry); | 319 | VAddr index_import_table_end = |
| 320 | import_indexed_symbol_table_offset + | ||
| 321 | GetField(ImportIndexedSymbolNum) * sizeof(ImportIndexedSymbolEntry); | ||
| 341 | VAddr import_anonymous_symbol_table_offset = GetField(ImportAnonymousSymbolTableOffset); | 322 | VAddr import_anonymous_symbol_table_offset = GetField(ImportAnonymousSymbolTableOffset); |
| 342 | VAddr offset_import_table_end = import_anonymous_symbol_table_offset + GetField(ImportAnonymousSymbolNum) * sizeof(ImportAnonymousSymbolEntry); | 323 | VAddr offset_import_table_end = |
| 324 | import_anonymous_symbol_table_offset + | ||
| 325 | GetField(ImportAnonymousSymbolNum) * sizeof(ImportAnonymousSymbolEntry); | ||
| 343 | 326 | ||
| 344 | u32 module_num = GetField(ImportModuleNum); | 327 | u32 module_num = GetField(ImportModuleNum); |
| 345 | for (u32 i = 0; i < module_num; ++i) { | 328 | for (u32 i = 0; i < module_num; ++i) { |
| @@ -348,24 +331,24 @@ ResultCode CROHelper::RebaseImportModuleTable() { | |||
| 348 | 331 | ||
| 349 | if (entry.name_offset != 0) { | 332 | if (entry.name_offset != 0) { |
| 350 | entry.name_offset += module_address; | 333 | entry.name_offset += module_address; |
| 351 | if (entry.name_offset < import_strings_offset | 334 | if (entry.name_offset < import_strings_offset || |
| 352 | || entry.name_offset >= import_strings_end) { | 335 | entry.name_offset >= import_strings_end) { |
| 353 | return CROFormatError(0x18); | 336 | return CROFormatError(0x18); |
| 354 | } | 337 | } |
| 355 | } | 338 | } |
| 356 | 339 | ||
| 357 | if (entry.import_indexed_symbol_table_offset != 0) { | 340 | if (entry.import_indexed_symbol_table_offset != 0) { |
| 358 | entry.import_indexed_symbol_table_offset += module_address; | 341 | entry.import_indexed_symbol_table_offset += module_address; |
| 359 | if (entry.import_indexed_symbol_table_offset < import_indexed_symbol_table_offset | 342 | if (entry.import_indexed_symbol_table_offset < import_indexed_symbol_table_offset || |
| 360 | || entry.import_indexed_symbol_table_offset > index_import_table_end) { | 343 | entry.import_indexed_symbol_table_offset > index_import_table_end) { |
| 361 | return CROFormatError(0x18); | 344 | return CROFormatError(0x18); |
| 362 | } | 345 | } |
| 363 | } | 346 | } |
| 364 | 347 | ||
| 365 | if (entry.import_anonymous_symbol_table_offset != 0) { | 348 | if (entry.import_anonymous_symbol_table_offset != 0) { |
| 366 | entry.import_anonymous_symbol_table_offset += module_address; | 349 | entry.import_anonymous_symbol_table_offset += module_address; |
| 367 | if (entry.import_anonymous_symbol_table_offset < import_anonymous_symbol_table_offset | 350 | if (entry.import_anonymous_symbol_table_offset < import_anonymous_symbol_table_offset || |
| 368 | || entry.import_anonymous_symbol_table_offset > offset_import_table_end) { | 351 | entry.import_anonymous_symbol_table_offset > offset_import_table_end) { |
| 369 | return CROFormatError(0x18); | 352 | return CROFormatError(0x18); |
| 370 | } | 353 | } |
| 371 | } | 354 | } |
| @@ -379,25 +362,27 @@ ResultCode CROHelper::RebaseImportNamedSymbolTable() { | |||
| 379 | VAddr import_strings_offset = GetField(ImportStringsOffset); | 362 | VAddr import_strings_offset = GetField(ImportStringsOffset); |
| 380 | VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize); | 363 | VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize); |
| 381 | VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); | 364 | VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); |
| 382 | VAddr external_relocation_table_end = external_relocation_table_offset + GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); | 365 | VAddr external_relocation_table_end = |
| 366 | external_relocation_table_offset + | ||
| 367 | GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); | ||
| 383 | 368 | ||
| 384 | u32 num = GetField(ImportNamedSymbolNum); | 369 | u32 num = GetField(ImportNamedSymbolNum); |
| 385 | for (u32 i = 0; i < num ; ++i) { | 370 | for (u32 i = 0; i < num; ++i) { |
| 386 | ImportNamedSymbolEntry entry; | 371 | ImportNamedSymbolEntry entry; |
| 387 | GetEntry(i, entry); | 372 | GetEntry(i, entry); |
| 388 | 373 | ||
| 389 | if (entry.name_offset != 0) { | 374 | if (entry.name_offset != 0) { |
| 390 | entry.name_offset += module_address; | 375 | entry.name_offset += module_address; |
| 391 | if (entry.name_offset < import_strings_offset | 376 | if (entry.name_offset < import_strings_offset || |
| 392 | || entry.name_offset >= import_strings_end) { | 377 | entry.name_offset >= import_strings_end) { |
| 393 | return CROFormatError(0x1B); | 378 | return CROFormatError(0x1B); |
| 394 | } | 379 | } |
| 395 | } | 380 | } |
| 396 | 381 | ||
| 397 | if (entry.relocation_batch_offset != 0) { | 382 | if (entry.relocation_batch_offset != 0) { |
| 398 | entry.relocation_batch_offset += module_address; | 383 | entry.relocation_batch_offset += module_address; |
| 399 | if (entry.relocation_batch_offset < external_relocation_table_offset | 384 | if (entry.relocation_batch_offset < external_relocation_table_offset || |
| 400 | || entry.relocation_batch_offset > external_relocation_table_end) { | 385 | entry.relocation_batch_offset > external_relocation_table_end) { |
| 401 | return CROFormatError(0x1B); | 386 | return CROFormatError(0x1B); |
| 402 | } | 387 | } |
| 403 | } | 388 | } |
| @@ -409,17 +394,19 @@ ResultCode CROHelper::RebaseImportNamedSymbolTable() { | |||
| 409 | 394 | ||
| 410 | ResultCode CROHelper::RebaseImportIndexedSymbolTable() { | 395 | ResultCode CROHelper::RebaseImportIndexedSymbolTable() { |
| 411 | VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); | 396 | VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); |
| 412 | VAddr external_relocation_table_end = external_relocation_table_offset + GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); | 397 | VAddr external_relocation_table_end = |
| 398 | external_relocation_table_offset + | ||
| 399 | GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); | ||
| 413 | 400 | ||
| 414 | u32 num = GetField(ImportIndexedSymbolNum); | 401 | u32 num = GetField(ImportIndexedSymbolNum); |
| 415 | for (u32 i = 0; i < num ; ++i) { | 402 | for (u32 i = 0; i < num; ++i) { |
| 416 | ImportIndexedSymbolEntry entry; | 403 | ImportIndexedSymbolEntry entry; |
| 417 | GetEntry(i, entry); | 404 | GetEntry(i, entry); |
| 418 | 405 | ||
| 419 | if (entry.relocation_batch_offset != 0) { | 406 | if (entry.relocation_batch_offset != 0) { |
| 420 | entry.relocation_batch_offset += module_address; | 407 | entry.relocation_batch_offset += module_address; |
| 421 | if (entry.relocation_batch_offset < external_relocation_table_offset | 408 | if (entry.relocation_batch_offset < external_relocation_table_offset || |
| 422 | || entry.relocation_batch_offset > external_relocation_table_end) { | 409 | entry.relocation_batch_offset > external_relocation_table_end) { |
| 423 | return CROFormatError(0x14); | 410 | return CROFormatError(0x14); |
| 424 | } | 411 | } |
| 425 | } | 412 | } |
| @@ -431,17 +418,19 @@ ResultCode CROHelper::RebaseImportIndexedSymbolTable() { | |||
| 431 | 418 | ||
| 432 | ResultCode CROHelper::RebaseImportAnonymousSymbolTable() { | 419 | ResultCode CROHelper::RebaseImportAnonymousSymbolTable() { |
| 433 | VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); | 420 | VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); |
| 434 | VAddr external_relocation_table_end = external_relocation_table_offset + GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); | 421 | VAddr external_relocation_table_end = |
| 422 | external_relocation_table_offset + | ||
| 423 | GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); | ||
| 435 | 424 | ||
| 436 | u32 num = GetField(ImportAnonymousSymbolNum); | 425 | u32 num = GetField(ImportAnonymousSymbolNum); |
| 437 | for (u32 i = 0; i < num ; ++i) { | 426 | for (u32 i = 0; i < num; ++i) { |
| 438 | ImportAnonymousSymbolEntry entry; | 427 | ImportAnonymousSymbolEntry entry; |
| 439 | GetEntry(i, entry); | 428 | GetEntry(i, entry); |
| 440 | 429 | ||
| 441 | if (entry.relocation_batch_offset != 0) { | 430 | if (entry.relocation_batch_offset != 0) { |
| 442 | entry.relocation_batch_offset += module_address; | 431 | entry.relocation_batch_offset += module_address; |
| 443 | if (entry.relocation_batch_offset < external_relocation_table_offset | 432 | if (entry.relocation_batch_offset < external_relocation_table_offset || |
| 444 | || entry.relocation_batch_offset > external_relocation_table_end) { | 433 | entry.relocation_batch_offset > external_relocation_table_end) { |
| 445 | return CROFormatError(0x17); | 434 | return CROFormatError(0x17); |
| 446 | } | 435 | } |
| 447 | } | 436 | } |
| @@ -475,7 +464,8 @@ ResultCode CROHelper::ResetExternalRelocations() { | |||
| 475 | return CROFormatError(0x12); | 464 | return CROFormatError(0x12); |
| 476 | } | 465 | } |
| 477 | 466 | ||
| 478 | ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend, unresolved_symbol, relocation_target); | 467 | ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend, |
| 468 | unresolved_symbol, relocation_target); | ||
| 479 | if (result.IsError()) { | 469 | if (result.IsError()) { |
| 480 | LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); | 470 | LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); |
| 481 | return result; | 471 | return result; |
| @@ -528,23 +518,27 @@ ResultCode CROHelper::ClearExternalRelocations() { | |||
| 528 | 518 | ||
| 529 | ResultCode CROHelper::ApplyStaticAnonymousSymbolToCRS(VAddr crs_address) { | 519 | ResultCode CROHelper::ApplyStaticAnonymousSymbolToCRS(VAddr crs_address) { |
| 530 | VAddr static_relocation_table_offset = GetField(StaticRelocationTableOffset); | 520 | VAddr static_relocation_table_offset = GetField(StaticRelocationTableOffset); |
| 531 | VAddr static_relocation_table_end = static_relocation_table_offset + GetField(StaticRelocationNum) * sizeof(StaticRelocationEntry); | 521 | VAddr static_relocation_table_end = |
| 522 | static_relocation_table_offset + | ||
| 523 | GetField(StaticRelocationNum) * sizeof(StaticRelocationEntry); | ||
| 532 | 524 | ||
| 533 | CROHelper crs(crs_address); | 525 | CROHelper crs(crs_address); |
| 534 | u32 offset_export_num = GetField(StaticAnonymousSymbolNum); | 526 | u32 offset_export_num = GetField(StaticAnonymousSymbolNum); |
| 535 | LOG_INFO(Service_LDR, "CRO \"%s\" exports %d static anonymous symbols", ModuleName().data(), offset_export_num); | 527 | LOG_INFO(Service_LDR, "CRO \"%s\" exports %d static anonymous symbols", ModuleName().data(), |
| 528 | offset_export_num); | ||
| 536 | for (u32 i = 0; i < offset_export_num; ++i) { | 529 | for (u32 i = 0; i < offset_export_num; ++i) { |
| 537 | StaticAnonymousSymbolEntry entry; | 530 | StaticAnonymousSymbolEntry entry; |
| 538 | GetEntry(i, entry); | 531 | GetEntry(i, entry); |
| 539 | u32 batch_address = entry.relocation_batch_offset + module_address; | 532 | u32 batch_address = entry.relocation_batch_offset + module_address; |
| 540 | 533 | ||
| 541 | if (batch_address < static_relocation_table_offset | 534 | if (batch_address < static_relocation_table_offset || |
| 542 | || batch_address > static_relocation_table_end) { | 535 | batch_address > static_relocation_table_end) { |
| 543 | return CROFormatError(0x16); | 536 | return CROFormatError(0x16); |
| 544 | } | 537 | } |
| 545 | 538 | ||
| 546 | u32 symbol_address = SegmentTagToAddress(entry.symbol_position); | 539 | u32 symbol_address = SegmentTagToAddress(entry.symbol_position); |
| 547 | LOG_TRACE(Service_LDR, "CRO \"%s\" exports 0x%08X to the static module", ModuleName().data(), symbol_address); | 540 | LOG_TRACE(Service_LDR, "CRO \"%s\" exports 0x%08X to the static module", |
| 541 | ModuleName().data(), symbol_address); | ||
| 548 | ResultCode result = crs.ApplyRelocationBatch(batch_address, symbol_address); | 542 | ResultCode result = crs.ApplyRelocationBatch(batch_address, symbol_address); |
| 549 | if (result.IsError()) { | 543 | if (result.IsError()) { |
| 550 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); | 544 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); |
| @@ -571,7 +565,8 @@ ResultCode CROHelper::ApplyInternalRelocations(u32 old_data_segment_address) { | |||
| 571 | 565 | ||
| 572 | if (target_segment.type == SegmentType::Data) { | 566 | if (target_segment.type == SegmentType::Data) { |
| 573 | // If the relocation is to the .data segment, we need to relocate it in the old buffer | 567 | // If the relocation is to the .data segment, we need to relocate it in the old buffer |
| 574 | target_address = old_data_segment_address + relocation.target_position.offset_into_segment; | 568 | target_address = |
| 569 | old_data_segment_address + relocation.target_position.offset_into_segment; | ||
| 575 | } else { | 570 | } else { |
| 576 | target_address = target_addressB; | 571 | target_address = target_addressB; |
| 577 | } | 572 | } |
| @@ -582,8 +577,10 @@ ResultCode CROHelper::ApplyInternalRelocations(u32 old_data_segment_address) { | |||
| 582 | 577 | ||
| 583 | SegmentEntry symbol_segment; | 578 | SegmentEntry symbol_segment; |
| 584 | GetEntry(relocation.symbol_segment, symbol_segment); | 579 | GetEntry(relocation.symbol_segment, symbol_segment); |
| 585 | LOG_TRACE(Service_LDR, "Internally relocates 0x%08X with 0x%08X", target_address, symbol_segment.offset); | 580 | LOG_TRACE(Service_LDR, "Internally relocates 0x%08X with 0x%08X", target_address, |
| 586 | ResultCode result = ApplyRelocation(target_address, relocation.type, relocation.addend, symbol_segment.offset, target_addressB); | 581 | symbol_segment.offset); |
| 582 | ResultCode result = ApplyRelocation(target_address, relocation.type, relocation.addend, | ||
| 583 | symbol_segment.offset, target_addressB); | ||
| 587 | if (result.IsError()) { | 584 | if (result.IsError()) { |
| 588 | LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); | 585 | LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); |
| 589 | return result; | 586 | return result; |
| @@ -734,25 +731,29 @@ ResultCode CROHelper::ApplyImportNamedSymbol(VAddr crs_address) { | |||
| 734 | Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); | 731 | Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); |
| 735 | 732 | ||
| 736 | if (!relocation_entry.is_batch_resolved) { | 733 | if (!relocation_entry.is_batch_resolved) { |
| 737 | ResultCode result = ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { | 734 | ResultCode result = |
| 738 | std::string symbol_name = Memory::ReadCString(entry.name_offset, import_strings_size); | 735 | ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { |
| 739 | u32 symbol_address = source.FindExportNamedSymbol(symbol_name); | 736 | std::string symbol_name = |
| 740 | 737 | Memory::ReadCString(entry.name_offset, import_strings_size); | |
| 741 | if (symbol_address != 0) { | 738 | u32 symbol_address = source.FindExportNamedSymbol(symbol_name); |
| 742 | LOG_TRACE(Service_LDR, "CRO \"%s\" imports \"%s\" from \"%s\"", | 739 | |
| 743 | ModuleName().data(), symbol_name.data(), source.ModuleName().data()); | 740 | if (symbol_address != 0) { |
| 744 | 741 | LOG_TRACE(Service_LDR, "CRO \"%s\" imports \"%s\" from \"%s\"", | |
| 745 | ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address); | 742 | ModuleName().data(), symbol_name.data(), |
| 746 | if (result.IsError()) { | 743 | source.ModuleName().data()); |
| 747 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); | 744 | |
| 748 | return result; | 745 | ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address); |
| 746 | if (result.IsError()) { | ||
| 747 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", | ||
| 748 | result.raw); | ||
| 749 | return result; | ||
| 750 | } | ||
| 751 | |||
| 752 | return MakeResult<bool>(false); | ||
| 749 | } | 753 | } |
| 750 | 754 | ||
| 751 | return MakeResult<bool>(false); | 755 | return MakeResult<bool>(true); |
| 752 | } | 756 | }); |
| 753 | |||
| 754 | return MakeResult<bool>(true); | ||
| 755 | }); | ||
| 756 | if (result.IsError()) { | 757 | if (result.IsError()) { |
| 757 | return result; | 758 | return result; |
| 758 | } | 759 | } |
| @@ -777,7 +778,6 @@ ResultCode CROHelper::ResetImportNamedSymbol() { | |||
| 777 | LOG_ERROR(Service_LDR, "Error reseting relocation batch %08X", result.raw); | 778 | LOG_ERROR(Service_LDR, "Error reseting relocation batch %08X", result.raw); |
| 778 | return result; | 779 | return result; |
| 779 | } | 780 | } |
| 780 | |||
| 781 | } | 781 | } |
| 782 | return RESULT_SUCCESS; | 782 | return RESULT_SUCCESS; |
| 783 | } | 783 | } |
| @@ -831,40 +831,47 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) { | |||
| 831 | GetEntry(i, entry); | 831 | GetEntry(i, entry); |
| 832 | std::string want_cro_name = Memory::ReadCString(entry.name_offset, import_strings_size); | 832 | std::string want_cro_name = Memory::ReadCString(entry.name_offset, import_strings_size); |
| 833 | 833 | ||
| 834 | ResultCode result = ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { | 834 | ResultCode result = |
| 835 | if (want_cro_name == source.ModuleName()) { | 835 | ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { |
| 836 | LOG_INFO(Service_LDR, "CRO \"%s\" imports %d indexed symbols from \"%s\"", | 836 | if (want_cro_name == source.ModuleName()) { |
| 837 | ModuleName().data(), entry.import_indexed_symbol_num, source.ModuleName().data()); | 837 | LOG_INFO(Service_LDR, "CRO \"%s\" imports %d indexed symbols from \"%s\"", |
| 838 | for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { | 838 | ModuleName().data(), entry.import_indexed_symbol_num, |
| 839 | ImportIndexedSymbolEntry im; | 839 | source.ModuleName().data()); |
| 840 | entry.GetImportIndexedSymbolEntry(j, im); | 840 | for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { |
| 841 | ExportIndexedSymbolEntry ex; | 841 | ImportIndexedSymbolEntry im; |
| 842 | source.GetEntry(im.index, ex); | 842 | entry.GetImportIndexedSymbolEntry(j, im); |
| 843 | u32 symbol_address = source.SegmentTagToAddress(ex.symbol_position); | 843 | ExportIndexedSymbolEntry ex; |
| 844 | LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address); | 844 | source.GetEntry(im.index, ex); |
| 845 | ResultCode result = ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); | 845 | u32 symbol_address = source.SegmentTagToAddress(ex.symbol_position); |
| 846 | if (result.IsError()) { | 846 | LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address); |
| 847 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); | 847 | ResultCode result = |
| 848 | return result; | 848 | ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); |
| 849 | if (result.IsError()) { | ||
| 850 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", | ||
| 851 | result.raw); | ||
| 852 | return result; | ||
| 853 | } | ||
| 849 | } | 854 | } |
| 850 | } | 855 | LOG_INFO(Service_LDR, "CRO \"%s\" imports %d anonymous symbols from \"%s\"", |
| 851 | LOG_INFO(Service_LDR, "CRO \"%s\" imports %d anonymous symbols from \"%s\"", | 856 | ModuleName().data(), entry.import_anonymous_symbol_num, |
| 852 | ModuleName().data(), entry.import_anonymous_symbol_num, source.ModuleName().data()); | 857 | source.ModuleName().data()); |
| 853 | for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { | 858 | for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { |
| 854 | ImportAnonymousSymbolEntry im; | 859 | ImportAnonymousSymbolEntry im; |
| 855 | entry.GetImportAnonymousSymbolEntry(j, im); | 860 | entry.GetImportAnonymousSymbolEntry(j, im); |
| 856 | u32 symbol_address = source.SegmentTagToAddress(im.symbol_position); | 861 | u32 symbol_address = source.SegmentTagToAddress(im.symbol_position); |
| 857 | LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address); | 862 | LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address); |
| 858 | ResultCode result = ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); | 863 | ResultCode result = |
| 859 | if (result.IsError()) { | 864 | ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); |
| 860 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); | 865 | if (result.IsError()) { |
| 861 | return result; | 866 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", |
| 867 | result.raw); | ||
| 868 | return result; | ||
| 869 | } | ||
| 862 | } | 870 | } |
| 871 | return MakeResult<bool>(false); | ||
| 863 | } | 872 | } |
| 864 | return MakeResult<bool>(false); | 873 | return MakeResult<bool>(true); |
| 865 | } | 874 | }); |
| 866 | return MakeResult<bool>(true); | ||
| 867 | }); | ||
| 868 | if (result.IsError()) { | 875 | if (result.IsError()) { |
| 869 | return result; | 876 | return result; |
| 870 | } | 877 | } |
| @@ -873,8 +880,8 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) { | |||
| 873 | } | 880 | } |
| 874 | 881 | ||
| 875 | ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) { | 882 | ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) { |
| 876 | LOG_DEBUG(Service_LDR, "CRO \"%s\" exports named symbols to \"%s\"", | 883 | LOG_DEBUG(Service_LDR, "CRO \"%s\" exports named symbols to \"%s\"", ModuleName().data(), |
| 877 | ModuleName().data(), target.ModuleName().data()); | 884 | target.ModuleName().data()); |
| 878 | u32 target_import_strings_size = target.GetField(ImportStringsSize); | 885 | u32 target_import_strings_size = target.GetField(ImportStringsSize); |
| 879 | u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum); | 886 | u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum); |
| 880 | for (u32 i = 0; i < target_symbol_import_num; ++i) { | 887 | for (u32 i = 0; i < target_symbol_import_num; ++i) { |
| @@ -885,7 +892,8 @@ ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) { | |||
| 885 | Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); | 892 | Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); |
| 886 | 893 | ||
| 887 | if (!relocation_entry.is_batch_resolved) { | 894 | if (!relocation_entry.is_batch_resolved) { |
| 888 | std::string symbol_name = Memory::ReadCString(entry.name_offset, target_import_strings_size); | 895 | std::string symbol_name = |
| 896 | Memory::ReadCString(entry.name_offset, target_import_strings_size); | ||
| 889 | u32 symbol_address = FindExportNamedSymbol(symbol_name); | 897 | u32 symbol_address = FindExportNamedSymbol(symbol_name); |
| 890 | if (symbol_address != 0) { | 898 | if (symbol_address != 0) { |
| 891 | LOG_TRACE(Service_LDR, " exports symbol \"%s\"", symbol_name.data()); | 899 | LOG_TRACE(Service_LDR, " exports symbol \"%s\"", symbol_name.data()); |
| @@ -901,8 +909,8 @@ ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) { | |||
| 901 | } | 909 | } |
| 902 | 910 | ||
| 903 | ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) { | 911 | ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) { |
| 904 | LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports named symbols to \"%s\"", | 912 | LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports named symbols to \"%s\"", ModuleName().data(), |
| 905 | ModuleName().data(), target.ModuleName().data()); | 913 | target.ModuleName().data()); |
| 906 | u32 unresolved_symbol = target.GetOnUnresolvedAddress(); | 914 | u32 unresolved_symbol = target.GetOnUnresolvedAddress(); |
| 907 | u32 target_import_strings_size = target.GetField(ImportStringsSize); | 915 | u32 target_import_strings_size = target.GetField(ImportStringsSize); |
| 908 | u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum); | 916 | u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum); |
| @@ -914,11 +922,13 @@ ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) { | |||
| 914 | Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); | 922 | Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); |
| 915 | 923 | ||
| 916 | if (relocation_entry.is_batch_resolved) { | 924 | if (relocation_entry.is_batch_resolved) { |
| 917 | std::string symbol_name = Memory::ReadCString(entry.name_offset, target_import_strings_size); | 925 | std::string symbol_name = |
| 926 | Memory::ReadCString(entry.name_offset, target_import_strings_size); | ||
| 918 | u32 symbol_address = FindExportNamedSymbol(symbol_name); | 927 | u32 symbol_address = FindExportNamedSymbol(symbol_name); |
| 919 | if (symbol_address != 0) { | 928 | if (symbol_address != 0) { |
| 920 | LOG_TRACE(Service_LDR, " unexports symbol \"%s\"", symbol_name.data()); | 929 | LOG_TRACE(Service_LDR, " unexports symbol \"%s\"", symbol_name.data()); |
| 921 | ResultCode result = target.ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); | 930 | ResultCode result = |
| 931 | target.ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); | ||
| 922 | if (result.IsError()) { | 932 | if (result.IsError()) { |
| 923 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); | 933 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); |
| 924 | return result; | 934 | return result; |
| @@ -940,8 +950,8 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) { | |||
| 940 | if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name) | 950 | if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name) |
| 941 | continue; | 951 | continue; |
| 942 | 952 | ||
| 943 | LOG_INFO(Service_LDR, "CRO \"%s\" exports %d indexed symbols to \"%s\"", | 953 | LOG_INFO(Service_LDR, "CRO \"%s\" exports %d indexed symbols to \"%s\"", module_name.data(), |
| 944 | module_name.data(), entry.import_indexed_symbol_num, target.ModuleName().data()); | 954 | entry.import_indexed_symbol_num, target.ModuleName().data()); |
| 945 | for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { | 955 | for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { |
| 946 | ImportIndexedSymbolEntry im; | 956 | ImportIndexedSymbolEntry im; |
| 947 | entry.GetImportIndexedSymbolEntry(j, im); | 957 | entry.GetImportIndexedSymbolEntry(j, im); |
| @@ -949,7 +959,8 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) { | |||
| 949 | GetEntry(im.index, ex); | 959 | GetEntry(im.index, ex); |
| 950 | u32 symbol_address = SegmentTagToAddress(ex.symbol_position); | 960 | u32 symbol_address = SegmentTagToAddress(ex.symbol_position); |
| 951 | LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address); | 961 | LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address); |
| 952 | ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); | 962 | ResultCode result = |
| 963 | target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); | ||
| 953 | if (result.IsError()) { | 964 | if (result.IsError()) { |
| 954 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); | 965 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); |
| 955 | return result; | 966 | return result; |
| @@ -957,13 +968,14 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) { | |||
| 957 | } | 968 | } |
| 958 | 969 | ||
| 959 | LOG_INFO(Service_LDR, "CRO \"%s\" exports %d anonymous symbols to \"%s\"", | 970 | LOG_INFO(Service_LDR, "CRO \"%s\" exports %d anonymous symbols to \"%s\"", |
| 960 | module_name.data(), entry.import_anonymous_symbol_num, target.ModuleName().data()); | 971 | module_name.data(), entry.import_anonymous_symbol_num, target.ModuleName().data()); |
| 961 | for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { | 972 | for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { |
| 962 | ImportAnonymousSymbolEntry im; | 973 | ImportAnonymousSymbolEntry im; |
| 963 | entry.GetImportAnonymousSymbolEntry(j, im); | 974 | entry.GetImportAnonymousSymbolEntry(j, im); |
| 964 | u32 symbol_address = SegmentTagToAddress(im.symbol_position); | 975 | u32 symbol_address = SegmentTagToAddress(im.symbol_position); |
| 965 | LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address); | 976 | LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address); |
| 966 | ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); | 977 | ResultCode result = |
| 978 | target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); | ||
| 967 | if (result.IsError()) { | 979 | if (result.IsError()) { |
| 968 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); | 980 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); |
| 969 | return result; | 981 | return result; |
| @@ -987,12 +999,13 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) { | |||
| 987 | if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name) | 999 | if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name) |
| 988 | continue; | 1000 | continue; |
| 989 | 1001 | ||
| 990 | LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports indexed symbols to \"%s\"", | 1002 | LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports indexed symbols to \"%s\"", module_name.data(), |
| 991 | module_name.data(), target.ModuleName().data()); | 1003 | target.ModuleName().data()); |
| 992 | for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { | 1004 | for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { |
| 993 | ImportIndexedSymbolEntry im; | 1005 | ImportIndexedSymbolEntry im; |
| 994 | entry.GetImportIndexedSymbolEntry(j, im); | 1006 | entry.GetImportIndexedSymbolEntry(j, im); |
| 995 | ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); | 1007 | ResultCode result = |
| 1008 | target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); | ||
| 996 | if (result.IsError()) { | 1009 | if (result.IsError()) { |
| 997 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); | 1010 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); |
| 998 | return result; | 1011 | return result; |
| @@ -1000,11 +1013,12 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) { | |||
| 1000 | } | 1013 | } |
| 1001 | 1014 | ||
| 1002 | LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports anonymous symbols to \"%s\"", | 1015 | LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports anonymous symbols to \"%s\"", |
| 1003 | module_name.data(), target.ModuleName().data()); | 1016 | module_name.data(), target.ModuleName().data()); |
| 1004 | for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { | 1017 | for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { |
| 1005 | ImportAnonymousSymbolEntry im; | 1018 | ImportAnonymousSymbolEntry im; |
| 1006 | entry.GetImportAnonymousSymbolEntry(j, im); | 1019 | entry.GetImportAnonymousSymbolEntry(j, im); |
| 1007 | ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); | 1020 | ResultCode result = |
| 1021 | target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); | ||
| 1008 | if (result.IsError()) { | 1022 | if (result.IsError()) { |
| 1009 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); | 1023 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); |
| 1010 | return result; | 1024 | return result; |
| @@ -1025,25 +1039,27 @@ ResultCode CROHelper::ApplyExitRelocations(VAddr crs_address) { | |||
| 1025 | ExternalRelocationEntry relocation_entry; | 1039 | ExternalRelocationEntry relocation_entry; |
| 1026 | Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); | 1040 | Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); |
| 1027 | 1041 | ||
| 1028 | if (Memory::ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit"){ | 1042 | if (Memory::ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit") { |
| 1029 | ResultCode result = ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { | 1043 | ResultCode result = |
| 1030 | u32 symbol_address = source.FindExportNamedSymbol("nnroAeabiAtexit_"); | 1044 | ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { |
| 1045 | u32 symbol_address = source.FindExportNamedSymbol("nnroAeabiAtexit_"); | ||
| 1031 | 1046 | ||
| 1032 | if (symbol_address != 0) { | 1047 | if (symbol_address != 0) { |
| 1033 | LOG_DEBUG(Service_LDR, "CRO \"%s\" import exit function from \"%s\"", | 1048 | LOG_DEBUG(Service_LDR, "CRO \"%s\" import exit function from \"%s\"", |
| 1034 | ModuleName().data(), source.ModuleName().data()); | 1049 | ModuleName().data(), source.ModuleName().data()); |
| 1035 | 1050 | ||
| 1036 | ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address); | 1051 | ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address); |
| 1037 | if (result.IsError()) { | 1052 | if (result.IsError()) { |
| 1038 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); | 1053 | LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", |
| 1039 | return result; | 1054 | result.raw); |
| 1040 | } | 1055 | return result; |
| 1056 | } | ||
| 1041 | 1057 | ||
| 1042 | return MakeResult<bool>(false); | 1058 | return MakeResult<bool>(false); |
| 1043 | } | 1059 | } |
| 1044 | 1060 | ||
| 1045 | return MakeResult<bool>(true); | 1061 | return MakeResult<bool>(true); |
| 1046 | }); | 1062 | }); |
| 1047 | if (result.IsError()) { | 1063 | if (result.IsError()) { |
| 1048 | LOG_ERROR(Service_LDR, "Error applying exit relocation %08X", result.raw); | 1064 | LOG_ERROR(Service_LDR, "Error applying exit relocation %08X", result.raw); |
| 1049 | return result; | 1065 | return result; |
| @@ -1070,9 +1086,9 @@ static ResultCode VerifyStringTableLength(VAddr address, u32 size) { | |||
| 1070 | return RESULT_SUCCESS; | 1086 | return RESULT_SUCCESS; |
| 1071 | } | 1087 | } |
| 1072 | 1088 | ||
| 1073 | ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, | 1089 | ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment_addresss, |
| 1074 | VAddr data_segment_addresss, u32 data_segment_size, | 1090 | u32 data_segment_size, VAddr bss_segment_address, u32 bss_segment_size, |
| 1075 | VAddr bss_segment_address, u32 bss_segment_size, bool is_crs) { | 1091 | bool is_crs) { |
| 1076 | 1092 | ||
| 1077 | ResultCode result = RebaseHeader(cro_size); | 1093 | ResultCode result = RebaseHeader(cro_size); |
| 1078 | if (result.IsError()) { | 1094 | if (result.IsError()) { |
| @@ -1088,9 +1104,8 @@ ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, | |||
| 1088 | 1104 | ||
| 1089 | u32 prev_data_segment_address = 0; | 1105 | u32 prev_data_segment_address = 0; |
| 1090 | if (!is_crs) { | 1106 | if (!is_crs) { |
| 1091 | auto result_val = RebaseSegmentTable(cro_size, | 1107 | auto result_val = RebaseSegmentTable(cro_size, data_segment_addresss, data_segment_size, |
| 1092 | data_segment_addresss, data_segment_size, | 1108 | bss_segment_address, bss_segment_size); |
| 1093 | bss_segment_address, bss_segment_size); | ||
| 1094 | if (result_val.Failed()) { | 1109 | if (result_val.Failed()) { |
| 1095 | LOG_ERROR(Service_LDR, "Error rebasing segment table %08X", result_val.Code().raw); | 1110 | LOG_ERROR(Service_LDR, "Error rebasing segment table %08X", result_val.Code().raw); |
| 1096 | return result_val.Code(); | 1111 | return result_val.Code(); |
| @@ -1374,7 +1389,8 @@ void CROHelper::Unregister(VAddr crs_address) { | |||
| 1374 | CROHelper next_head(crs.NextModule()), previous_head(crs.PreviousModule()); | 1389 | CROHelper next_head(crs.NextModule()), previous_head(crs.PreviousModule()); |
| 1375 | CROHelper next(NextModule()), previous(PreviousModule()); | 1390 | CROHelper next(NextModule()), previous(PreviousModule()); |
| 1376 | 1391 | ||
| 1377 | if (module_address == next_head.module_address || module_address == previous_head.module_address) { | 1392 | if (module_address == next_head.module_address || |
| 1393 | module_address == previous_head.module_address) { | ||
| 1378 | // removing head | 1394 | // removing head |
| 1379 | if (next.module_address) { | 1395 | if (next.module_address) { |
| 1380 | // the next is new head | 1396 | // the next is new head |
| @@ -1400,7 +1416,8 @@ void CROHelper::Unregister(VAddr crs_address) { | |||
| 1400 | // let head's previous point to the new tail | 1416 | // let head's previous point to the new tail |
| 1401 | if (next_head.module_address && next_head.PreviousModule() == module_address) { | 1417 | if (next_head.module_address && next_head.PreviousModule() == module_address) { |
| 1402 | next_head.SetPreviousModule(previous.module_address); | 1418 | next_head.SetPreviousModule(previous.module_address); |
| 1403 | } else if (previous_head.module_address && previous_head.PreviousModule() == module_address) { | 1419 | } else if (previous_head.module_address && |
| 1420 | previous_head.PreviousModule() == module_address) { | ||
| 1404 | previous_head.SetPreviousModule(previous.module_address); | 1421 | previous_head.SetPreviousModule(previous.module_address); |
| 1405 | } else { | 1422 | } else { |
| 1406 | UNREACHABLE(); | 1423 | UNREACHABLE(); |
| @@ -1419,9 +1436,9 @@ u32 CROHelper::GetFixEnd(u32 fix_level) const { | |||
| 1419 | u32 entry_size_i = 2; | 1436 | u32 entry_size_i = 2; |
| 1420 | int field = ModuleNameOffset; | 1437 | int field = ModuleNameOffset; |
| 1421 | while (true) { | 1438 | while (true) { |
| 1422 | end = std::max<u32>(end, | 1439 | end = std::max<u32>(end, GetField(static_cast<HeaderField>(field)) + |
| 1423 | GetField(static_cast<HeaderField>(field)) + | 1440 | GetField(static_cast<HeaderField>(field + 1)) * |
| 1424 | GetField(static_cast<HeaderField>(field + 1)) * ENTRY_SIZE[entry_size_i]); | 1441 | ENTRY_SIZE[entry_size_i]); |
| 1425 | 1442 | ||
| 1426 | ++entry_size_i; | 1443 | ++entry_size_i; |
| 1427 | field += 2; | 1444 | field += 2; |
diff --git a/src/core/hle/service/ldr_ro/cro_helper.h b/src/core/hle/service/ldr_ro/cro_helper.h index 34e357afd..e4457d4be 100644 --- a/src/core/hle/service/ldr_ro/cro_helper.h +++ b/src/core/hle/service/ldr_ro/cro_helper.h | |||
| @@ -10,8 +10,8 @@ | |||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/swap.h" | 11 | #include "common/swap.h" |
| 12 | 12 | ||
| 13 | #include "core/memory.h" | ||
| 14 | #include "core/hle/result.h" | 13 | #include "core/hle/result.h" |
| 14 | #include "core/memory.h" | ||
| 15 | 15 | ||
| 16 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 16 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 17 | // Namespace LDR_RO | 17 | // Namespace LDR_RO |
| @@ -21,14 +21,17 @@ namespace LDR_RO { | |||
| 21 | // GCC versions < 5.0 do not implement std::is_trivially_copyable. | 21 | // GCC versions < 5.0 do not implement std::is_trivially_copyable. |
| 22 | // Excluding MSVC because it has weird behaviour for std::is_trivially_copyable. | 22 | // Excluding MSVC because it has weird behaviour for std::is_trivially_copyable. |
| 23 | #if (__GNUC__ >= 5) || defined(__clang__) | 23 | #if (__GNUC__ >= 5) || defined(__clang__) |
| 24 | #define ASSERT_CRO_STRUCT(name, size) \ | 24 | #define ASSERT_CRO_STRUCT(name, size) \ |
| 25 | static_assert(std::is_standard_layout<name>::value, "CRO structure " #name " doesn't use standard layout"); \ | 25 | static_assert(std::is_standard_layout<name>::value, \ |
| 26 | static_assert(std::is_trivially_copyable<name>::value, "CRO structure " #name " isn't trivially copyable"); \ | 26 | "CRO structure " #name " doesn't use standard layout"); \ |
| 27 | static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name) | 27 | static_assert(std::is_trivially_copyable<name>::value, \ |
| 28 | "CRO structure " #name " isn't trivially copyable"); \ | ||
| 29 | static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name) | ||
| 28 | #else | 30 | #else |
| 29 | #define ASSERT_CRO_STRUCT(name, size) \ | 31 | #define ASSERT_CRO_STRUCT(name, size) \ |
| 30 | static_assert(std::is_standard_layout<name>::value, "CRO structure " #name " doesn't use standard layout"); \ | 32 | static_assert(std::is_standard_layout<name>::value, \ |
| 31 | static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name) | 33 | "CRO structure " #name " doesn't use standard layout"); \ |
| 34 | static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name) | ||
| 32 | #endif | 35 | #endif |
| 33 | 36 | ||
| 34 | static constexpr u32 CRO_HEADER_SIZE = 0x138; | 37 | static constexpr u32 CRO_HEADER_SIZE = 0x138; |
| @@ -59,9 +62,9 @@ public: | |||
| 59 | * @param is_crs true if the module itself is the static module | 62 | * @param is_crs true if the module itself is the static module |
| 60 | * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. | 63 | * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. |
| 61 | */ | 64 | */ |
| 62 | ResultCode Rebase(VAddr crs_address, u32 cro_size, | 65 | ResultCode Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment_addresss, |
| 63 | VAddr data_segment_addresss, u32 data_segment_size, | 66 | u32 data_segment_size, VAddr bss_segment_address, u32 bss_segment_size, |
| 64 | VAddr bss_segment_address, u32 bss_segment_size, bool is_crs); | 67 | bool is_crs); |
| 65 | 68 | ||
| 66 | /** | 69 | /** |
| 67 | * Unrebases the module. | 70 | * Unrebases the module. |
| @@ -148,8 +151,10 @@ private: | |||
| 148 | const VAddr module_address; ///< the virtual address of this module | 151 | const VAddr module_address; ///< the virtual address of this module |
| 149 | 152 | ||
| 150 | /** | 153 | /** |
| 151 | * Each item in this enum represents a u32 field in the header begin from address+0x80, successively. | 154 | * Each item in this enum represents a u32 field in the header begin from address+0x80, |
| 152 | * We don't directly use a struct here, to avoid GetPointer, reinterpret_cast, or Read/WriteBlock repeatedly. | 155 | * successively. |
| 156 | * We don't directly use a struct here, to avoid GetPointer, reinterpret_cast, or | ||
| 157 | * Read/WriteBlock repeatedly. | ||
| 153 | */ | 158 | */ |
| 154 | enum HeaderField { | 159 | enum HeaderField { |
| 155 | Magic = 0, | 160 | Magic = 0, |
| @@ -208,18 +213,20 @@ private: | |||
| 208 | Fix2Barrier = ImportModuleTableOffset, | 213 | Fix2Barrier = ImportModuleTableOffset, |
| 209 | Fix1Barrier = StaticAnonymousSymbolTableOffset, | 214 | Fix1Barrier = StaticAnonymousSymbolTableOffset, |
| 210 | }; | 215 | }; |
| 211 | static_assert(Fix0Barrier == (CRO_HEADER_SIZE - CRO_HASH_SIZE) / 4, "CRO Header fields are wrong!"); | 216 | static_assert(Fix0Barrier == (CRO_HEADER_SIZE - CRO_HASH_SIZE) / 4, |
| 217 | "CRO Header fields are wrong!"); | ||
| 212 | 218 | ||
| 213 | enum class SegmentType : u32 { | 219 | enum class SegmentType : u32 { |
| 214 | Code = 0, | 220 | Code = 0, |
| 215 | ROData = 1, | 221 | ROData = 1, |
| 216 | Data = 2, | 222 | Data = 2, |
| 217 | BSS = 3, | 223 | BSS = 3, |
| 218 | }; | 224 | }; |
| 219 | 225 | ||
| 220 | /** | 226 | /** |
| 221 | * Identifies a program location inside of a segment. | 227 | * Identifies a program location inside of a segment. |
| 222 | * Required to refer to program locations because individual segments may be relocated independently of each other. | 228 | * Required to refer to program locations because individual segments may be relocated |
| 229 | * independently of each other. | ||
| 223 | */ | 230 | */ |
| 224 | union SegmentTag { | 231 | union SegmentTag { |
| 225 | u32_le raw; | 232 | u32_le raw; |
| @@ -227,7 +234,8 @@ private: | |||
| 227 | BitField<4, 28, u32_le> offset_into_segment; | 234 | BitField<4, 28, u32_le> offset_into_segment; |
| 228 | 235 | ||
| 229 | SegmentTag() = default; | 236 | SegmentTag() = default; |
| 230 | explicit SegmentTag(u32 raw_) : raw(raw_) {} | 237 | explicit SegmentTag(u32 raw_) : raw(raw_) { |
| 238 | } | ||
| 231 | }; | 239 | }; |
| 232 | 240 | ||
| 233 | /// Information of a segment in this module. | 241 | /// Information of a segment in this module. |
| @@ -282,7 +290,7 @@ private: | |||
| 282 | 290 | ||
| 283 | /// Identifies an indexed symbol imported from another module. | 291 | /// Identifies an indexed symbol imported from another module. |
| 284 | struct ImportIndexedSymbolEntry { | 292 | struct ImportIndexedSymbolEntry { |
| 285 | u32_le index; // index of an ExportIndexedSymbolEntry in the exporting module | 293 | u32_le index; // index of an ExportIndexedSymbolEntry in the exporting module |
| 286 | u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable | 294 | u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable |
| 287 | 295 | ||
| 288 | static constexpr HeaderField TABLE_OFFSET_FIELD = ImportIndexedSymbolTableOffset; | 296 | static constexpr HeaderField TABLE_OFFSET_FIELD = ImportIndexedSymbolTableOffset; |
| @@ -291,8 +299,8 @@ private: | |||
| 291 | 299 | ||
| 292 | /// Identifies an anonymous symbol imported from another module. | 300 | /// Identifies an anonymous symbol imported from another module. |
| 293 | struct ImportAnonymousSymbolEntry { | 301 | struct ImportAnonymousSymbolEntry { |
| 294 | SegmentTag symbol_position; // in the exporting segment | 302 | SegmentTag symbol_position; // in the exporting segment |
| 295 | u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable | 303 | u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable |
| 296 | 304 | ||
| 297 | static constexpr HeaderField TABLE_OFFSET_FIELD = ImportAnonymousSymbolTableOffset; | 305 | static constexpr HeaderField TABLE_OFFSET_FIELD = ImportAnonymousSymbolTableOffset; |
| 298 | }; | 306 | }; |
| @@ -300,42 +308,47 @@ private: | |||
| 300 | 308 | ||
| 301 | /// Information of a imported module and symbols imported from it. | 309 | /// Information of a imported module and symbols imported from it. |
| 302 | struct ImportModuleEntry { | 310 | struct ImportModuleEntry { |
| 303 | u32_le name_offset; // pointing to a substring in ImportStrings | 311 | u32_le name_offset; // pointing to a substring in ImportStrings |
| 304 | u32_le import_indexed_symbol_table_offset; // pointing to a subtable in ImportIndexedSymbolTable | 312 | u32_le import_indexed_symbol_table_offset; // pointing to a subtable in |
| 313 | // ImportIndexedSymbolTable | ||
| 305 | u32_le import_indexed_symbol_num; | 314 | u32_le import_indexed_symbol_num; |
| 306 | u32_le import_anonymous_symbol_table_offset; // pointing to a subtable in ImportAnonymousSymbolTable | 315 | u32_le import_anonymous_symbol_table_offset; // pointing to a subtable in |
| 316 | // ImportAnonymousSymbolTable | ||
| 307 | u32_le import_anonymous_symbol_num; | 317 | u32_le import_anonymous_symbol_num; |
| 308 | 318 | ||
| 309 | static constexpr HeaderField TABLE_OFFSET_FIELD = ImportModuleTableOffset; | 319 | static constexpr HeaderField TABLE_OFFSET_FIELD = ImportModuleTableOffset; |
| 310 | 320 | ||
| 311 | void GetImportIndexedSymbolEntry(u32 index, ImportIndexedSymbolEntry& entry) { | 321 | void GetImportIndexedSymbolEntry(u32 index, ImportIndexedSymbolEntry& entry) { |
| 312 | Memory::ReadBlock(import_indexed_symbol_table_offset + index * sizeof(ImportIndexedSymbolEntry), | 322 | Memory::ReadBlock(import_indexed_symbol_table_offset + |
| 313 | &entry, sizeof(ImportIndexedSymbolEntry)); | 323 | index * sizeof(ImportIndexedSymbolEntry), |
| 324 | &entry, sizeof(ImportIndexedSymbolEntry)); | ||
| 314 | } | 325 | } |
| 315 | 326 | ||
| 316 | void GetImportAnonymousSymbolEntry(u32 index, ImportAnonymousSymbolEntry& entry) { | 327 | void GetImportAnonymousSymbolEntry(u32 index, ImportAnonymousSymbolEntry& entry) { |
| 317 | Memory::ReadBlock(import_anonymous_symbol_table_offset + index * sizeof(ImportAnonymousSymbolEntry), | 328 | Memory::ReadBlock(import_anonymous_symbol_table_offset + |
| 318 | &entry, sizeof(ImportAnonymousSymbolEntry)); | 329 | index * sizeof(ImportAnonymousSymbolEntry), |
| 330 | &entry, sizeof(ImportAnonymousSymbolEntry)); | ||
| 319 | } | 331 | } |
| 320 | }; | 332 | }; |
| 321 | ASSERT_CRO_STRUCT(ImportModuleEntry, 20); | 333 | ASSERT_CRO_STRUCT(ImportModuleEntry, 20); |
| 322 | 334 | ||
| 323 | enum class RelocationType : u8 { | 335 | enum class RelocationType : u8 { |
| 324 | Nothing = 0, | 336 | Nothing = 0, |
| 325 | AbsoluteAddress = 2, | 337 | AbsoluteAddress = 2, |
| 326 | RelativeAddress = 3, | 338 | RelativeAddress = 3, |
| 327 | ThumbBranch = 10, | 339 | ThumbBranch = 10, |
| 328 | ArmBranch = 28, | 340 | ArmBranch = 28, |
| 329 | ModifyArmBranch = 29, | 341 | ModifyArmBranch = 29, |
| 330 | AbsoluteAddress2 = 38, | 342 | AbsoluteAddress2 = 38, |
| 331 | AlignedRelativeAddress = 42, | 343 | AlignedRelativeAddress = 42, |
| 332 | }; | 344 | }; |
| 333 | 345 | ||
| 334 | struct RelocationEntry { | 346 | struct RelocationEntry { |
| 335 | SegmentTag target_position; // to self's segment as an ExternalRelocationEntry; to static module segment as a StaticRelocationEntry | 347 | SegmentTag target_position; // to self's segment as an ExternalRelocationEntry; to static |
| 348 | // module segment as a StaticRelocationEntry | ||
| 336 | RelocationType type; | 349 | RelocationType type; |
| 337 | u8 is_batch_end; | 350 | u8 is_batch_end; |
| 338 | u8 is_batch_resolved; // set at a batch beginning if the batch is resolved | 351 | u8 is_batch_resolved; // set at a batch beginning if the batch is resolved |
| 339 | INSERT_PADDING_BYTES(1); | 352 | INSERT_PADDING_BYTES(1); |
| 340 | u32_le addend; | 353 | u32_le addend; |
| 341 | }; | 354 | }; |
| @@ -366,8 +379,8 @@ private: | |||
| 366 | 379 | ||
| 367 | /// Identifies a special static anonymous symbol (no game is known using this). | 380 | /// Identifies a special static anonymous symbol (no game is known using this). |
| 368 | struct StaticAnonymousSymbolEntry { | 381 | struct StaticAnonymousSymbolEntry { |
| 369 | SegmentTag symbol_position; // to self's segment | 382 | SegmentTag symbol_position; // to self's segment |
| 370 | u32_le relocation_batch_offset; // pointing to a relocation batch in StaticRelocationTable | 383 | u32_le relocation_batch_offset; // pointing to a relocation batch in StaticRelocationTable |
| 371 | 384 | ||
| 372 | static constexpr HeaderField TABLE_OFFSET_FIELD = StaticAnonymousSymbolTableOffset; | 385 | static constexpr HeaderField TABLE_OFFSET_FIELD = StaticAnonymousSymbolTableOffset; |
| 373 | }; | 386 | }; |
| @@ -446,12 +459,15 @@ private: | |||
| 446 | } | 459 | } |
| 447 | 460 | ||
| 448 | /** | 461 | /** |
| 449 | * A helper function iterating over all registered auto-link modules, including the static module. | 462 | * A helper function iterating over all registered auto-link modules, including the static |
| 463 | * module. | ||
| 450 | * @param crs_address the virtual address of the static module | 464 | * @param crs_address the virtual address of the static module |
| 451 | * @param func a function object to operate on a module. It accepts one parameter | 465 | * @param func a function object to operate on a module. It accepts one parameter |
| 452 | * CROHelper and returns ResultVal<bool>. It should return true to continue the iteration, | 466 | * CROHelper and returns ResultVal<bool>. It should return true to continue the |
| 467 | * iteration, | ||
| 453 | * false to stop the iteration, or an error code (which will also stop the iteration). | 468 | * false to stop the iteration, or an error code (which will also stop the iteration). |
| 454 | * @returns ResultCode indicating the result of the operation, RESULT_SUCCESS if all iteration success, | 469 | * @returns ResultCode indicating the result of the operation, RESULT_SUCCESS if all iteration |
| 470 | * success, | ||
| 455 | * otherwise error code of the last iteration. | 471 | * otherwise error code of the last iteration. |
| 456 | */ | 472 | */ |
| 457 | template <typename FunctionObject> | 473 | template <typename FunctionObject> |
| @@ -477,8 +493,8 @@ private: | |||
| 477 | * Usually equals to target_address, but will be different for a target in .data segment | 493 | * Usually equals to target_address, but will be different for a target in .data segment |
| 478 | * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. | 494 | * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. |
| 479 | */ | 495 | */ |
| 480 | ResultCode ApplyRelocation(VAddr target_address, RelocationType relocation_type, | 496 | ResultCode ApplyRelocation(VAddr target_address, RelocationType relocation_type, u32 addend, |
| 481 | u32 addend, u32 symbol_address, u32 target_future_address); | 497 | u32 symbol_address, u32 target_future_address); |
| 482 | 498 | ||
| 483 | /** | 499 | /** |
| 484 | * Clears a relocation to zero | 500 | * Clears a relocation to zero |
| @@ -492,7 +508,8 @@ private: | |||
| 492 | * Applies or resets a batch of relocations | 508 | * Applies or resets a batch of relocations |
| 493 | * @param batch the virtual address of the first relocation in the batch | 509 | * @param batch the virtual address of the first relocation in the batch |
| 494 | * @param symbol_address the symbol address to be relocated with | 510 | * @param symbol_address the symbol address to be relocated with |
| 495 | * @param reset false to set the batch to resolved state, true to reset the batch to unresolved state | 511 | * @param reset false to set the batch to resolved state, true to reset the batch to unresolved |
| 512 | * state | ||
| 496 | * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. | 513 | * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. |
| 497 | */ | 514 | */ |
| 498 | ResultCode ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool reset = false); | 515 | ResultCode ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool reset = false); |
| @@ -507,7 +524,8 @@ private: | |||
| 507 | /** | 524 | /** |
| 508 | * Rebases offsets in module header according to module address. | 525 | * Rebases offsets in module header according to module address. |
| 509 | * @param cro_size the size of the CRO file | 526 | * @param cro_size the size of the CRO file |
| 510 | * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code. | 527 | * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error |
| 528 | * code. | ||
| 511 | */ | 529 | */ |
| 512 | ResultCode RebaseHeader(u32 cro_size); | 530 | ResultCode RebaseHeader(u32 cro_size); |
| 513 | 531 | ||
| @@ -520,43 +538,49 @@ private: | |||
| 520 | * @param bss_segment_size the buffer size for .bss segment | 538 | * @param bss_segment_size the buffer size for .bss segment |
| 521 | * @returns ResultVal<VAddr> with the virtual address of .data segment in CRO. | 539 | * @returns ResultVal<VAddr> with the virtual address of .data segment in CRO. |
| 522 | */ | 540 | */ |
| 523 | ResultVal<VAddr> RebaseSegmentTable(u32 cro_size, | 541 | ResultVal<VAddr> RebaseSegmentTable(u32 cro_size, VAddr data_segment_address, |
| 524 | VAddr data_segment_address, u32 data_segment_size, | 542 | u32 data_segment_size, VAddr bss_segment_address, |
| 525 | VAddr bss_segment_address, u32 bss_segment_size); | 543 | u32 bss_segment_size); |
| 526 | 544 | ||
| 527 | /** | 545 | /** |
| 528 | * Rebases offsets in exported named symbol table according to module address. | 546 | * Rebases offsets in exported named symbol table according to module address. |
| 529 | * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code. | 547 | * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error |
| 548 | * code. | ||
| 530 | */ | 549 | */ |
| 531 | ResultCode RebaseExportNamedSymbolTable(); | 550 | ResultCode RebaseExportNamedSymbolTable(); |
| 532 | 551 | ||
| 533 | /** | 552 | /** |
| 534 | * Verifies indices in export tree table. | 553 | * Verifies indices in export tree table. |
| 535 | * @returns ResultCode RESULT_SUCCESS if all indices are verified as valid, otherwise error code. | 554 | * @returns ResultCode RESULT_SUCCESS if all indices are verified as valid, otherwise error |
| 555 | * code. | ||
| 536 | */ | 556 | */ |
| 537 | ResultCode VerifyExportTreeTable() const; | 557 | ResultCode VerifyExportTreeTable() const; |
| 538 | 558 | ||
| 539 | /** | 559 | /** |
| 540 | * Rebases offsets in exported module table according to module address. | 560 | * Rebases offsets in exported module table according to module address. |
| 541 | * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code. | 561 | * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error |
| 562 | * code. | ||
| 542 | */ | 563 | */ |
| 543 | ResultCode RebaseImportModuleTable(); | 564 | ResultCode RebaseImportModuleTable(); |
| 544 | 565 | ||
| 545 | /** | 566 | /** |
| 546 | * Rebases offsets in imported named symbol table according to module address. | 567 | * Rebases offsets in imported named symbol table according to module address. |
| 547 | * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code. | 568 | * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error |
| 569 | * code. | ||
| 548 | */ | 570 | */ |
| 549 | ResultCode RebaseImportNamedSymbolTable(); | 571 | ResultCode RebaseImportNamedSymbolTable(); |
| 550 | 572 | ||
| 551 | /** | 573 | /** |
| 552 | * Rebases offsets in imported indexed symbol table according to module address. | 574 | * Rebases offsets in imported indexed symbol table according to module address. |
| 553 | * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code. | 575 | * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error |
| 576 | * code. | ||
| 554 | */ | 577 | */ |
| 555 | ResultCode RebaseImportIndexedSymbolTable(); | 578 | ResultCode RebaseImportIndexedSymbolTable(); |
| 556 | 579 | ||
| 557 | /** | 580 | /** |
| 558 | * Rebases offsets in imported anonymous symbol table according to module address. | 581 | * Rebases offsets in imported anonymous symbol table according to module address. |
| 559 | * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code. | 582 | * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error |
| 583 | * code. | ||
| 560 | */ | 584 | */ |
| 561 | ResultCode RebaseImportAnonymousSymbolTable(); | 585 | ResultCode RebaseImportAnonymousSymbolTable(); |
| 562 | 586 | ||
| @@ -621,7 +645,8 @@ private: | |||
| 621 | void UnrebaseHeader(); | 645 | void UnrebaseHeader(); |
| 622 | 646 | ||
| 623 | /** | 647 | /** |
| 624 | * Looks up all imported named symbols of this module in all registered auto-link modules, and resolves them if found. | 648 | * Looks up all imported named symbols of this module in all registered auto-link modules, and |
| 649 | * resolves them if found. | ||
| 625 | * @param crs_address the virtual address of the static module | 650 | * @param crs_address the virtual address of the static module |
| 626 | * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. | 651 | * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. |
| 627 | */ | 652 | */ |
| @@ -646,7 +671,8 @@ private: | |||
| 646 | ResultCode ResetImportAnonymousSymbol(); | 671 | ResultCode ResetImportAnonymousSymbol(); |
| 647 | 672 | ||
| 648 | /** | 673 | /** |
| 649 | * Finds registered auto-link modules that this module imports, and resolves indexed and anonymous symbols exported by them. | 674 | * Finds registered auto-link modules that this module imports, and resolves indexed and |
| 675 | * anonymous symbols exported by them. | ||
| 650 | * @param crs_address the virtual address of the static module | 676 | * @param crs_address the virtual address of the static module |
| 651 | * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. | 677 | * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. |
| 652 | */ | 678 | */ |
| @@ -667,7 +693,8 @@ private: | |||
| 667 | ResultCode ResetExportNamedSymbol(CROHelper target); | 693 | ResultCode ResetExportNamedSymbol(CROHelper target); |
| 668 | 694 | ||
| 669 | /** | 695 | /** |
| 670 | * Resolves imported indexed and anonymous symbols in the target module which imports this module. | 696 | * Resolves imported indexed and anonymous symbols in the target module which imports this |
| 697 | * module. | ||
| 671 | * @param target the module to resolve. | 698 | * @param target the module to resolve. |
| 672 | * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. | 699 | * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. |
| 673 | */ | 700 | */ |
diff --git a/src/core/hle/service/ldr_ro/ldr_ro.cpp b/src/core/hle/service/ldr_ro/ldr_ro.cpp index 8ba73ea8d..ae5d3921f 100644 --- a/src/core/hle/service/ldr_ro/ldr_ro.cpp +++ b/src/core/hle/service/ldr_ro/ldr_ro.cpp | |||
| @@ -18,24 +18,33 @@ | |||
| 18 | 18 | ||
| 19 | namespace LDR_RO { | 19 | namespace LDR_RO { |
| 20 | 20 | ||
| 21 | static const ResultCode ERROR_ALREADY_INITIALIZED = // 0xD9612FF9 | 21 | static const ResultCode ERROR_ALREADY_INITIALIZED = // 0xD9612FF9 |
| 22 | ResultCode(ErrorDescription::AlreadyInitialized, ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Permanent); | 22 | ResultCode(ErrorDescription::AlreadyInitialized, ErrorModule::RO, ErrorSummary::Internal, |
| 23 | static const ResultCode ERROR_NOT_INITIALIZED = // 0xD9612FF8 | 23 | ErrorLevel::Permanent); |
| 24 | ResultCode(ErrorDescription::NotInitialized, ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Permanent); | 24 | static const ResultCode ERROR_NOT_INITIALIZED = // 0xD9612FF8 |
| 25 | static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F | 25 | ResultCode(ErrorDescription::NotInitialized, ErrorModule::RO, ErrorSummary::Internal, |
| 26 | ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument, ErrorLevel::Usage); | 26 | ErrorLevel::Permanent); |
| 27 | static const ResultCode ERROR_MISALIGNED_ADDRESS = // 0xD9012FF1 | 27 | static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F |
| 28 | ResultCode(ErrorDescription::MisalignedAddress, ErrorModule::RO, ErrorSummary::WrongArgument, ErrorLevel::Permanent); | 28 | ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument, |
| 29 | static const ResultCode ERROR_MISALIGNED_SIZE = // 0xD9012FF2 | 29 | ErrorLevel::Usage); |
| 30 | ResultCode(ErrorDescription::MisalignedSize, ErrorModule::RO, ErrorSummary::WrongArgument, ErrorLevel::Permanent); | 30 | static const ResultCode ERROR_MISALIGNED_ADDRESS = // 0xD9012FF1 |
| 31 | static const ResultCode ERROR_ILLEGAL_ADDRESS = // 0xE1612C0F | 31 | ResultCode(ErrorDescription::MisalignedAddress, ErrorModule::RO, ErrorSummary::WrongArgument, |
| 32 | ResultCode(static_cast<ErrorDescription>(15), ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Usage); | 32 | ErrorLevel::Permanent); |
| 33 | static const ResultCode ERROR_INVALID_MEMORY_STATE = // 0xD8A12C08 | 33 | static const ResultCode ERROR_MISALIGNED_SIZE = // 0xD9012FF2 |
| 34 | ResultCode(static_cast<ErrorDescription>(8), ErrorModule::RO, ErrorSummary::InvalidState, ErrorLevel::Permanent); | 34 | ResultCode(ErrorDescription::MisalignedSize, ErrorModule::RO, ErrorSummary::WrongArgument, |
| 35 | static const ResultCode ERROR_NOT_LOADED = // 0xD8A12C0D | 35 | ErrorLevel::Permanent); |
| 36 | ResultCode(static_cast<ErrorDescription>(13), ErrorModule::RO, ErrorSummary::InvalidState, ErrorLevel::Permanent); | 36 | static const ResultCode ERROR_ILLEGAL_ADDRESS = // 0xE1612C0F |
| 37 | static const ResultCode ERROR_INVALID_DESCRIPTOR = // 0xD9001830 | 37 | ResultCode(static_cast<ErrorDescription>(15), ErrorModule::RO, ErrorSummary::Internal, |
| 38 | ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); | 38 | ErrorLevel::Usage); |
| 39 | static const ResultCode ERROR_INVALID_MEMORY_STATE = // 0xD8A12C08 | ||
| 40 | ResultCode(static_cast<ErrorDescription>(8), ErrorModule::RO, ErrorSummary::InvalidState, | ||
| 41 | ErrorLevel::Permanent); | ||
| 42 | static const ResultCode ERROR_NOT_LOADED = // 0xD8A12C0D | ||
| 43 | ResultCode(static_cast<ErrorDescription>(13), ErrorModule::RO, ErrorSummary::InvalidState, | ||
| 44 | ErrorLevel::Permanent); | ||
| 45 | static const ResultCode ERROR_INVALID_DESCRIPTOR = // 0xD9001830 | ||
| 46 | ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, | ||
| 47 | ErrorSummary::WrongArgument, ErrorLevel::Permanent); | ||
| 39 | 48 | ||
| 40 | static MemorySynchronizer memory_synchronizer; | 49 | static MemorySynchronizer memory_synchronizer; |
| 41 | 50 | ||
| @@ -44,10 +53,10 @@ static VAddr loaded_crs; ///< the virtual address of the static module | |||
| 44 | 53 | ||
| 45 | static bool VerifyBufferState(VAddr buffer_ptr, u32 size) { | 54 | static bool VerifyBufferState(VAddr buffer_ptr, u32 size) { |
| 46 | auto vma = Kernel::g_current_process->vm_manager.FindVMA(buffer_ptr); | 55 | auto vma = Kernel::g_current_process->vm_manager.FindVMA(buffer_ptr); |
| 47 | return vma != Kernel::g_current_process->vm_manager.vma_map.end() | 56 | return vma != Kernel::g_current_process->vm_manager.vma_map.end() && |
| 48 | && vma->second.base + vma->second.size >= buffer_ptr + size | 57 | vma->second.base + vma->second.size >= buffer_ptr + size && |
| 49 | && vma->second.permissions == Kernel::VMAPermission::ReadWrite | 58 | vma->second.permissions == Kernel::VMAPermission::ReadWrite && |
| 50 | && vma->second.meminfo_state == Kernel::MemoryState::Private; | 59 | vma->second.meminfo_state == Kernel::MemoryState::Private; |
| 51 | } | 60 | } |
| 52 | 61 | ||
| 53 | /** | 62 | /** |
| @@ -66,13 +75,14 @@ static bool VerifyBufferState(VAddr buffer_ptr, u32 size) { | |||
| 66 | static void Initialize(Service::Interface* self) { | 75 | static void Initialize(Service::Interface* self) { |
| 67 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 76 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 68 | VAddr crs_buffer_ptr = cmd_buff[1]; | 77 | VAddr crs_buffer_ptr = cmd_buff[1]; |
| 69 | u32 crs_size = cmd_buff[2]; | 78 | u32 crs_size = cmd_buff[2]; |
| 70 | VAddr crs_address = cmd_buff[3]; | 79 | VAddr crs_address = cmd_buff[3]; |
| 71 | u32 descriptor = cmd_buff[4]; | 80 | u32 descriptor = cmd_buff[4]; |
| 72 | u32 process = cmd_buff[5]; | 81 | u32 process = cmd_buff[5]; |
| 73 | 82 | ||
| 74 | LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, crs_address=0x%08X, crs_size=0x%X, descriptor=0x%08X, process=0x%08X", | 83 | LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, crs_address=0x%08X, crs_size=0x%X, " |
| 75 | crs_buffer_ptr, crs_address, crs_size, descriptor, process); | 84 | "descriptor=0x%08X, process=0x%08X", |
| 85 | crs_buffer_ptr, crs_address, crs_size, descriptor, process); | ||
| 76 | 86 | ||
| 77 | if (descriptor != 0) { | 87 | if (descriptor != 0) { |
| 78 | LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); | 88 | LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); |
| @@ -119,7 +129,8 @@ static void Initialize(Service::Interface* self) { | |||
| 119 | return; | 129 | return; |
| 120 | } | 130 | } |
| 121 | 131 | ||
| 122 | if (crs_address < Memory::PROCESS_IMAGE_VADDR || crs_address + crs_size > Memory::PROCESS_IMAGE_VADDR_END) { | 132 | if (crs_address < Memory::PROCESS_IMAGE_VADDR || |
| 133 | crs_address + crs_size > Memory::PROCESS_IMAGE_VADDR_END) { | ||
| 123 | LOG_ERROR(Service_LDR, "CRS mapping address is not in the process image region"); | 134 | LOG_ERROR(Service_LDR, "CRS mapping address is not in the process image region"); |
| 124 | cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw; | 135 | cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw; |
| 125 | return; | 136 | return; |
| @@ -131,14 +142,17 @@ static void Initialize(Service::Interface* self) { | |||
| 131 | // TODO(wwylele): should be memory aliasing | 142 | // TODO(wwylele): should be memory aliasing |
| 132 | std::shared_ptr<std::vector<u8>> crs_mem = std::make_shared<std::vector<u8>>(crs_size); | 143 | std::shared_ptr<std::vector<u8>> crs_mem = std::make_shared<std::vector<u8>>(crs_size); |
| 133 | Memory::ReadBlock(crs_buffer_ptr, crs_mem->data(), crs_size); | 144 | Memory::ReadBlock(crs_buffer_ptr, crs_mem->data(), crs_size); |
| 134 | result = Kernel::g_current_process->vm_manager.MapMemoryBlock(crs_address, crs_mem, 0, crs_size, Kernel::MemoryState::Code).Code(); | 145 | result = Kernel::g_current_process->vm_manager |
| 146 | .MapMemoryBlock(crs_address, crs_mem, 0, crs_size, Kernel::MemoryState::Code) | ||
| 147 | .Code(); | ||
| 135 | if (result.IsError()) { | 148 | if (result.IsError()) { |
| 136 | LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw); | 149 | LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw); |
| 137 | cmd_buff[1] = result.raw; | 150 | cmd_buff[1] = result.raw; |
| 138 | return; | 151 | return; |
| 139 | } | 152 | } |
| 140 | 153 | ||
| 141 | result = Kernel::g_current_process->vm_manager.ReprotectRange(crs_address, crs_size, Kernel::VMAPermission::Read); | 154 | result = Kernel::g_current_process->vm_manager.ReprotectRange(crs_address, crs_size, |
| 155 | Kernel::VMAPermission::Read); | ||
| 142 | if (result.IsError()) { | 156 | if (result.IsError()) { |
| 143 | LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); | 157 | LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); |
| 144 | cmd_buff[1] = result.raw; | 158 | cmd_buff[1] = result.raw; |
| @@ -186,9 +200,9 @@ static void Initialize(Service::Interface* self) { | |||
| 186 | static void LoadCRR(Service::Interface* self) { | 200 | static void LoadCRR(Service::Interface* self) { |
| 187 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 201 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 188 | u32 crr_buffer_ptr = cmd_buff[1]; | 202 | u32 crr_buffer_ptr = cmd_buff[1]; |
| 189 | u32 crr_size = cmd_buff[2]; | 203 | u32 crr_size = cmd_buff[2]; |
| 190 | u32 descriptor = cmd_buff[3]; | 204 | u32 descriptor = cmd_buff[3]; |
| 191 | u32 process = cmd_buff[4]; | 205 | u32 process = cmd_buff[4]; |
| 192 | 206 | ||
| 193 | if (descriptor != 0) { | 207 | if (descriptor != 0) { |
| 194 | LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); | 208 | LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); |
| @@ -200,7 +214,8 @@ static void LoadCRR(Service::Interface* self) { | |||
| 200 | cmd_buff[0] = IPC::MakeHeader(2, 1, 0); | 214 | cmd_buff[0] = IPC::MakeHeader(2, 1, 0); |
| 201 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 215 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 202 | 216 | ||
| 203 | LOG_WARNING(Service_LDR, "(STUBBED) called, crr_buffer_ptr=0x%08X, crr_size=0x%08X, descriptor=0x%08X, process=0x%08X", | 217 | LOG_WARNING(Service_LDR, "(STUBBED) called, crr_buffer_ptr=0x%08X, crr_size=0x%08X, " |
| 218 | "descriptor=0x%08X, process=0x%08X", | ||
| 204 | crr_buffer_ptr, crr_size, descriptor, process); | 219 | crr_buffer_ptr, crr_size, descriptor, process); |
| 205 | } | 220 | } |
| 206 | 221 | ||
| @@ -218,8 +233,8 @@ static void LoadCRR(Service::Interface* self) { | |||
| 218 | static void UnloadCRR(Service::Interface* self) { | 233 | static void UnloadCRR(Service::Interface* self) { |
| 219 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 234 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 220 | u32 crr_buffer_ptr = cmd_buff[1]; | 235 | u32 crr_buffer_ptr = cmd_buff[1]; |
| 221 | u32 descriptor = cmd_buff[2]; | 236 | u32 descriptor = cmd_buff[2]; |
| 222 | u32 process = cmd_buff[3]; | 237 | u32 process = cmd_buff[3]; |
| 223 | 238 | ||
| 224 | if (descriptor != 0) { | 239 | if (descriptor != 0) { |
| 225 | LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); | 240 | LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); |
| @@ -231,7 +246,8 @@ static void UnloadCRR(Service::Interface* self) { | |||
| 231 | cmd_buff[0] = IPC::MakeHeader(3, 1, 0); | 246 | cmd_buff[0] = IPC::MakeHeader(3, 1, 0); |
| 232 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 247 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 233 | 248 | ||
| 234 | LOG_WARNING(Service_LDR, "(STUBBED) called, crr_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X", | 249 | LOG_WARNING(Service_LDR, |
| 250 | "(STUBBED) called, crr_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X", | ||
| 235 | crr_buffer_ptr, descriptor, process); | 251 | crr_buffer_ptr, descriptor, process); |
| 236 | } | 252 | } |
| 237 | 253 | ||
| @@ -263,27 +279,28 @@ static void UnloadCRR(Service::Interface* self) { | |||
| 263 | */ | 279 | */ |
| 264 | static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { | 280 | static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { |
| 265 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 281 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 266 | VAddr cro_buffer_ptr = cmd_buff[1]; | 282 | VAddr cro_buffer_ptr = cmd_buff[1]; |
| 267 | VAddr cro_address = cmd_buff[2]; | 283 | VAddr cro_address = cmd_buff[2]; |
| 268 | u32 cro_size = cmd_buff[3]; | 284 | u32 cro_size = cmd_buff[3]; |
| 269 | VAddr data_segment_address = cmd_buff[4]; | 285 | VAddr data_segment_address = cmd_buff[4]; |
| 270 | u32 zero = cmd_buff[5]; | 286 | u32 zero = cmd_buff[5]; |
| 271 | u32 data_segment_size = cmd_buff[6]; | 287 | u32 data_segment_size = cmd_buff[6]; |
| 272 | u32 bss_segment_address = cmd_buff[7]; | 288 | u32 bss_segment_address = cmd_buff[7]; |
| 273 | u32 bss_segment_size = cmd_buff[8]; | 289 | u32 bss_segment_size = cmd_buff[8]; |
| 274 | bool auto_link = (cmd_buff[9] & 0xFF) != 0; | 290 | bool auto_link = (cmd_buff[9] & 0xFF) != 0; |
| 275 | u32 fix_level = cmd_buff[10]; | 291 | u32 fix_level = cmd_buff[10]; |
| 276 | VAddr crr_address = cmd_buff[11]; | 292 | VAddr crr_address = cmd_buff[11]; |
| 277 | u32 descriptor = cmd_buff[12]; | 293 | u32 descriptor = cmd_buff[12]; |
| 278 | u32 process = cmd_buff[13]; | 294 | u32 process = cmd_buff[13]; |
| 279 | 295 | ||
| 280 | LOG_DEBUG(Service_LDR, "called (%s), cro_buffer_ptr=0x%08X, cro_address=0x%08X, cro_size=0x%X, " | 296 | LOG_DEBUG(Service_LDR, |
| 281 | "data_segment_address=0x%08X, zero=%d, data_segment_size=0x%X, bss_segment_address=0x%08X, bss_segment_size=0x%X, " | 297 | "called (%s), cro_buffer_ptr=0x%08X, cro_address=0x%08X, cro_size=0x%X, " |
| 282 | "auto_link=%s, fix_level=%d, crr_address=0x%08X, descriptor=0x%08X, process=0x%08X", | 298 | "data_segment_address=0x%08X, zero=%d, data_segment_size=0x%X, " |
| 283 | link_on_load_bug_fix ? "new" : "old", cro_buffer_ptr, cro_address, cro_size, | 299 | "bss_segment_address=0x%08X, bss_segment_size=0x%X, " |
| 284 | data_segment_address, zero, data_segment_size, bss_segment_address, bss_segment_size, | 300 | "auto_link=%s, fix_level=%d, crr_address=0x%08X, descriptor=0x%08X, process=0x%08X", |
| 285 | auto_link ? "true" : "false", fix_level, crr_address, descriptor, process | 301 | link_on_load_bug_fix ? "new" : "old", cro_buffer_ptr, cro_address, cro_size, |
| 286 | ); | 302 | data_segment_address, zero, data_segment_size, bss_segment_address, bss_segment_size, |
| 303 | auto_link ? "true" : "false", fix_level, crr_address, descriptor, process); | ||
| 287 | 304 | ||
| 288 | if (descriptor != 0) { | 305 | if (descriptor != 0) { |
| 289 | LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); | 306 | LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); |
| @@ -330,8 +347,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { | |||
| 330 | return; | 347 | return; |
| 331 | } | 348 | } |
| 332 | 349 | ||
| 333 | if (cro_address < Memory::PROCESS_IMAGE_VADDR | 350 | if (cro_address < Memory::PROCESS_IMAGE_VADDR || |
| 334 | || cro_address + cro_size > Memory::PROCESS_IMAGE_VADDR_END) { | 351 | cro_address + cro_size > Memory::PROCESS_IMAGE_VADDR_END) { |
| 335 | LOG_ERROR(Service_LDR, "CRO mapping address is not in the process image region"); | 352 | LOG_ERROR(Service_LDR, "CRO mapping address is not in the process image region"); |
| 336 | cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw; | 353 | cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw; |
| 337 | return; | 354 | return; |
| @@ -339,7 +356,9 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { | |||
| 339 | 356 | ||
| 340 | if (zero) { | 357 | if (zero) { |
| 341 | LOG_ERROR(Service_LDR, "Zero is not zero %d", zero); | 358 | LOG_ERROR(Service_LDR, "Zero is not zero %d", zero); |
| 342 | cmd_buff[1] = ResultCode(static_cast<ErrorDescription>(29), ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Usage).raw; | 359 | cmd_buff[1] = ResultCode(static_cast<ErrorDescription>(29), ErrorModule::RO, |
| 360 | ErrorSummary::Internal, ErrorLevel::Usage) | ||
| 361 | .raw; | ||
| 343 | return; | 362 | return; |
| 344 | } | 363 | } |
| 345 | 364 | ||
| @@ -349,14 +368,17 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { | |||
| 349 | // TODO(wwylele): should be memory aliasing | 368 | // TODO(wwylele): should be memory aliasing |
| 350 | std::shared_ptr<std::vector<u8>> cro_mem = std::make_shared<std::vector<u8>>(cro_size); | 369 | std::shared_ptr<std::vector<u8>> cro_mem = std::make_shared<std::vector<u8>>(cro_size); |
| 351 | Memory::ReadBlock(cro_buffer_ptr, cro_mem->data(), cro_size); | 370 | Memory::ReadBlock(cro_buffer_ptr, cro_mem->data(), cro_size); |
| 352 | result = Kernel::g_current_process->vm_manager.MapMemoryBlock(cro_address, cro_mem, 0, cro_size, Kernel::MemoryState::Code).Code(); | 371 | result = Kernel::g_current_process->vm_manager |
| 372 | .MapMemoryBlock(cro_address, cro_mem, 0, cro_size, Kernel::MemoryState::Code) | ||
| 373 | .Code(); | ||
| 353 | if (result.IsError()) { | 374 | if (result.IsError()) { |
| 354 | LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw); | 375 | LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw); |
| 355 | cmd_buff[1] = result.raw; | 376 | cmd_buff[1] = result.raw; |
| 356 | return; | 377 | return; |
| 357 | } | 378 | } |
| 358 | 379 | ||
| 359 | result = Kernel::g_current_process->vm_manager.ReprotectRange(cro_address, cro_size, Kernel::VMAPermission::Read); | 380 | result = Kernel::g_current_process->vm_manager.ReprotectRange(cro_address, cro_size, |
| 381 | Kernel::VMAPermission::Read); | ||
| 360 | if (result.IsError()) { | 382 | if (result.IsError()) { |
| 361 | LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); | 383 | LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); |
| 362 | Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); | 384 | Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); |
| @@ -384,7 +406,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { | |||
| 384 | return; | 406 | return; |
| 385 | } | 407 | } |
| 386 | 408 | ||
| 387 | result = cro.Rebase(loaded_crs, cro_size, data_segment_address, data_segment_size, bss_segment_address, bss_segment_size, false); | 409 | result = cro.Rebase(loaded_crs, cro_size, data_segment_address, data_segment_size, |
| 410 | bss_segment_address, bss_segment_size, false); | ||
| 388 | if (result.IsError()) { | 411 | if (result.IsError()) { |
| 389 | LOG_ERROR(Service_LDR, "Error rebasing CRO %08X", result.raw); | 412 | LOG_ERROR(Service_LDR, "Error rebasing CRO %08X", result.raw); |
| 390 | Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); | 413 | Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); |
| @@ -409,7 +432,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { | |||
| 409 | // TODO(wwylele): verify the behaviour when buffer_ptr == address | 432 | // TODO(wwylele): verify the behaviour when buffer_ptr == address |
| 410 | if (cro_buffer_ptr != cro_address) { | 433 | if (cro_buffer_ptr != cro_address) { |
| 411 | if (fix_size != cro_size) { | 434 | if (fix_size != cro_size) { |
| 412 | result = Kernel::g_current_process->vm_manager.UnmapRange(cro_address + fix_size, cro_size - fix_size); | 435 | result = Kernel::g_current_process->vm_manager.UnmapRange(cro_address + fix_size, |
| 436 | cro_size - fix_size); | ||
| 413 | if (result.IsError()) { | 437 | if (result.IsError()) { |
| 414 | LOG_ERROR(Service_LDR, "Error unmapping memory block %08X", result.raw); | 438 | LOG_ERROR(Service_LDR, "Error unmapping memory block %08X", result.raw); |
| 415 | Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); | 439 | Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); |
| @@ -426,7 +450,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { | |||
| 426 | u32 exe_size; | 450 | u32 exe_size; |
| 427 | std::tie(exe_begin, exe_size) = cro.GetExecutablePages(); | 451 | std::tie(exe_begin, exe_size) = cro.GetExecutablePages(); |
| 428 | if (exe_begin) { | 452 | if (exe_begin) { |
| 429 | result = Kernel::g_current_process->vm_manager.ReprotectRange(exe_begin, exe_size, Kernel::VMAPermission::ReadExecute); | 453 | result = Kernel::g_current_process->vm_manager.ReprotectRange( |
| 454 | exe_begin, exe_size, Kernel::VMAPermission::ReadExecute); | ||
| 430 | if (result.IsError()) { | 455 | if (result.IsError()) { |
| 431 | LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); | 456 | LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); |
| 432 | Kernel::g_current_process->vm_manager.UnmapRange(cro_address, fix_size); | 457 | Kernel::g_current_process->vm_manager.UnmapRange(cro_address, fix_size); |
| @@ -437,8 +462,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { | |||
| 437 | 462 | ||
| 438 | Core::g_app_core->ClearInstructionCache(); | 463 | Core::g_app_core->ClearInstructionCache(); |
| 439 | 464 | ||
| 440 | LOG_INFO(Service_LDR, "CRO \"%s\" loaded at 0x%08X, fixed_end=0x%08X", | 465 | LOG_INFO(Service_LDR, "CRO \"%s\" loaded at 0x%08X, fixed_end=0x%08X", cro.ModuleName().data(), |
| 441 | cro.ModuleName().data(), cro_address, cro_address+fix_size); | 466 | cro_address, cro_address + fix_size); |
| 442 | 467 | ||
| 443 | cmd_buff[1] = RESULT_SUCCESS.raw; | 468 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 444 | cmd_buff[2] = fix_size; | 469 | cmd_buff[2] = fix_size; |
| @@ -464,14 +489,15 @@ static void LoadCRO(Service::Interface* self) { | |||
| 464 | */ | 489 | */ |
| 465 | static void UnloadCRO(Service::Interface* self) { | 490 | static void UnloadCRO(Service::Interface* self) { |
| 466 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 491 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 467 | VAddr cro_address = cmd_buff[1]; | 492 | VAddr cro_address = cmd_buff[1]; |
| 468 | u32 zero = cmd_buff[2]; | 493 | u32 zero = cmd_buff[2]; |
| 469 | VAddr cro_buffer_ptr = cmd_buff[3]; | 494 | VAddr cro_buffer_ptr = cmd_buff[3]; |
| 470 | u32 descriptor = cmd_buff[4]; | 495 | u32 descriptor = cmd_buff[4]; |
| 471 | u32 process = cmd_buff[5]; | 496 | u32 process = cmd_buff[5]; |
| 472 | 497 | ||
| 473 | LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, zero=%d, cro_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X", | 498 | LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, zero=%d, cro_buffer_ptr=0x%08X, " |
| 474 | cro_address, zero, cro_buffer_ptr, descriptor, process); | 499 | "descriptor=0x%08X, process=0x%08X", |
| 500 | cro_address, zero, cro_buffer_ptr, descriptor, process); | ||
| 475 | 501 | ||
| 476 | if (descriptor != 0) { | 502 | if (descriptor != 0) { |
| 477 | LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); | 503 | LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); |
| @@ -558,11 +584,11 @@ static void UnloadCRO(Service::Interface* self) { | |||
| 558 | static void LinkCRO(Service::Interface* self) { | 584 | static void LinkCRO(Service::Interface* self) { |
| 559 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 585 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 560 | VAddr cro_address = cmd_buff[1]; | 586 | VAddr cro_address = cmd_buff[1]; |
| 561 | u32 descriptor = cmd_buff[2]; | 587 | u32 descriptor = cmd_buff[2]; |
| 562 | u32 process = cmd_buff[3]; | 588 | u32 process = cmd_buff[3]; |
| 563 | 589 | ||
| 564 | LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X", | 590 | LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X", |
| 565 | cro_address, descriptor, process); | 591 | cro_address, descriptor, process); |
| 566 | 592 | ||
| 567 | if (descriptor != 0) { | 593 | if (descriptor != 0) { |
| 568 | LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); | 594 | LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); |
| @@ -620,11 +646,11 @@ static void LinkCRO(Service::Interface* self) { | |||
| 620 | static void UnlinkCRO(Service::Interface* self) { | 646 | static void UnlinkCRO(Service::Interface* self) { |
| 621 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 647 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 622 | VAddr cro_address = cmd_buff[1]; | 648 | VAddr cro_address = cmd_buff[1]; |
| 623 | u32 descriptor = cmd_buff[2]; | 649 | u32 descriptor = cmd_buff[2]; |
| 624 | u32 process = cmd_buff[3]; | 650 | u32 process = cmd_buff[3]; |
| 625 | 651 | ||
| 626 | LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X", | 652 | LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X", |
| 627 | cro_address, descriptor, process); | 653 | cro_address, descriptor, process); |
| 628 | 654 | ||
| 629 | if (descriptor != 0) { | 655 | if (descriptor != 0) { |
| 630 | LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); | 656 | LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); |
| @@ -682,11 +708,11 @@ static void UnlinkCRO(Service::Interface* self) { | |||
| 682 | static void Shutdown(Service::Interface* self) { | 708 | static void Shutdown(Service::Interface* self) { |
| 683 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 709 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 684 | VAddr crs_buffer_ptr = cmd_buff[1]; | 710 | VAddr crs_buffer_ptr = cmd_buff[1]; |
| 685 | u32 descriptor = cmd_buff[2]; | 711 | u32 descriptor = cmd_buff[2]; |
| 686 | u32 process = cmd_buff[3]; | 712 | u32 process = cmd_buff[3]; |
| 687 | 713 | ||
| 688 | LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X", | 714 | LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X", |
| 689 | crs_buffer_ptr, descriptor, process); | 715 | crs_buffer_ptr, descriptor, process); |
| 690 | 716 | ||
| 691 | if (descriptor != 0) { | 717 | if (descriptor != 0) { |
| 692 | LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); | 718 | LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); |
| @@ -724,15 +750,11 @@ static void Shutdown(Service::Interface* self) { | |||
| 724 | } | 750 | } |
| 725 | 751 | ||
| 726 | const Interface::FunctionInfo FunctionTable[] = { | 752 | const Interface::FunctionInfo FunctionTable[] = { |
| 727 | {0x000100C2, Initialize, "Initialize"}, | 753 | {0x000100C2, Initialize, "Initialize"}, {0x00020082, LoadCRR, "LoadCRR"}, |
| 728 | {0x00020082, LoadCRR, "LoadCRR"}, | 754 | {0x00030042, UnloadCRR, "UnloadCRR"}, {0x000402C2, LoadCRO<false>, "LoadCRO"}, |
| 729 | {0x00030042, UnloadCRR, "UnloadCRR"}, | 755 | {0x000500C2, UnloadCRO, "UnloadCRO"}, {0x00060042, LinkCRO, "LinkCRO"}, |
| 730 | {0x000402C2, LoadCRO<false>, "LoadCRO"}, | 756 | {0x00070042, UnlinkCRO, "UnlinkCRO"}, {0x00080042, Shutdown, "Shutdown"}, |
| 731 | {0x000500C2, UnloadCRO, "UnloadCRO"}, | 757 | {0x000902C2, LoadCRO<true>, "LoadCRO_New"}, |
| 732 | {0x00060042, LinkCRO, "LinkCRO"}, | ||
| 733 | {0x00070042, UnlinkCRO, "UnlinkCRO"}, | ||
| 734 | {0x00080042, Shutdown, "Shutdown"}, | ||
| 735 | {0x000902C2, LoadCRO<true>, "LoadCRO_New"}, | ||
| 736 | }; | 758 | }; |
| 737 | 759 | ||
| 738 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 760 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
diff --git a/src/core/hle/service/ldr_ro/memory_synchronizer.cpp b/src/core/hle/service/ldr_ro/memory_synchronizer.cpp index 4402876e6..aed6d3365 100644 --- a/src/core/hle/service/ldr_ro/memory_synchronizer.cpp +++ b/src/core/hle/service/ldr_ro/memory_synchronizer.cpp | |||
| @@ -14,9 +14,8 @@ | |||
| 14 | namespace LDR_RO { | 14 | namespace LDR_RO { |
| 15 | 15 | ||
| 16 | auto MemorySynchronizer::FindMemoryBlock(VAddr mapping, VAddr original) { | 16 | auto MemorySynchronizer::FindMemoryBlock(VAddr mapping, VAddr original) { |
| 17 | auto block = std::find_if(memory_blocks.begin(), memory_blocks.end(), [=](MemoryBlock& b){ | 17 | auto block = std::find_if(memory_blocks.begin(), memory_blocks.end(), |
| 18 | return b.original == original; | 18 | [=](MemoryBlock& b) { return b.original == original; }); |
| 19 | }); | ||
| 20 | ASSERT(block->mapping == mapping); | 19 | ASSERT(block->mapping == mapping); |
| 21 | return block; | 20 | return block; |
| 22 | } | 21 | } |
diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp index f792bc9cd..edd1ea97b 100644 --- a/src/core/hle/service/mic_u.cpp +++ b/src/core/hle/service/mic_u.cpp | |||
| @@ -10,22 +10,22 @@ | |||
| 10 | namespace MIC_U { | 10 | namespace MIC_U { |
| 11 | 11 | ||
| 12 | const Interface::FunctionInfo FunctionTable[] = { | 12 | const Interface::FunctionInfo FunctionTable[] = { |
| 13 | {0x00010042, nullptr, "MapSharedMem"}, | 13 | {0x00010042, nullptr, "MapSharedMem"}, |
| 14 | {0x00020000, nullptr, "UnmapSharedMem"}, | 14 | {0x00020000, nullptr, "UnmapSharedMem"}, |
| 15 | {0x00030140, nullptr, "Initialize"}, | 15 | {0x00030140, nullptr, "Initialize"}, |
| 16 | {0x00040040, nullptr, "AdjustSampling"}, | 16 | {0x00040040, nullptr, "AdjustSampling"}, |
| 17 | {0x00050000, nullptr, "StopSampling"}, | 17 | {0x00050000, nullptr, "StopSampling"}, |
| 18 | {0x00060000, nullptr, "IsSampling"}, | 18 | {0x00060000, nullptr, "IsSampling"}, |
| 19 | {0x00070000, nullptr, "GetEventHandle"}, | 19 | {0x00070000, nullptr, "GetEventHandle"}, |
| 20 | {0x00080040, nullptr, "SetGain"}, | 20 | {0x00080040, nullptr, "SetGain"}, |
| 21 | {0x00090000, nullptr, "GetGain"}, | 21 | {0x00090000, nullptr, "GetGain"}, |
| 22 | {0x000A0040, nullptr, "SetPower"}, | 22 | {0x000A0040, nullptr, "SetPower"}, |
| 23 | {0x000B0000, nullptr, "GetPower"}, | 23 | {0x000B0000, nullptr, "GetPower"}, |
| 24 | {0x000C0042, nullptr, "size"}, | 24 | {0x000C0042, nullptr, "size"}, |
| 25 | {0x000D0040, nullptr, "SetClamp"}, | 25 | {0x000D0040, nullptr, "SetClamp"}, |
| 26 | {0x000E0000, nullptr, "GetClamp"}, | 26 | {0x000E0000, nullptr, "GetClamp"}, |
| 27 | {0x000F0040, nullptr, "SetAllowShellClosed"}, | 27 | {0x000F0040, nullptr, "SetAllowShellClosed"}, |
| 28 | {0x00100040, nullptr, "unknown_input2"}, | 28 | {0x00100040, nullptr, "unknown_input2"}, |
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 31 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
diff --git a/src/core/hle/service/ndm/ndm.cpp b/src/core/hle/service/ndm/ndm.cpp index bc9c3413d..9f1536aef 100644 --- a/src/core/hle/service/ndm/ndm.cpp +++ b/src/core/hle/service/ndm/ndm.cpp | |||
| @@ -2,23 +2,21 @@ | |||
| 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/hle/service/ndm/ndm.h" | ||
| 5 | #include "common/common_types.h" | 6 | #include "common/common_types.h" |
| 6 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 7 | #include "core/hle/service/service.h" | ||
| 8 | #include "core/hle/service/ndm/ndm.h" | ||
| 9 | #include "core/hle/service/ndm/ndm_u.h" | 8 | #include "core/hle/service/ndm/ndm_u.h" |
| 9 | #include "core/hle/service/service.h" | ||
| 10 | 10 | ||
| 11 | namespace Service { | 11 | namespace Service { |
| 12 | namespace NDM { | 12 | namespace NDM { |
| 13 | 13 | ||
| 14 | enum : u32 { | 14 | enum : u32 { DEFAULT_RETRY_INTERVAL = 10, DEFAULT_SCAN_INTERVAL = 30 }; |
| 15 | DEFAULT_RETRY_INTERVAL = 10, | ||
| 16 | DEFAULT_SCAN_INTERVAL = 30 | ||
| 17 | }; | ||
| 18 | 15 | ||
| 19 | static DaemonMask daemon_bit_mask = DaemonMask::Default; | 16 | static DaemonMask daemon_bit_mask = DaemonMask::Default; |
| 20 | static DaemonMask default_daemon_bit_mask = DaemonMask::Default; | 17 | static DaemonMask default_daemon_bit_mask = DaemonMask::Default; |
| 21 | static std::array<DaemonStatus, 4> daemon_status = { DaemonStatus::Idle, DaemonStatus::Idle, DaemonStatus::Idle, DaemonStatus::Idle }; | 18 | static std::array<DaemonStatus, 4> daemon_status = {DaemonStatus::Idle, DaemonStatus::Idle, |
| 19 | DaemonStatus::Idle, DaemonStatus::Idle}; | ||
| 22 | static ExclusiveState exclusive_state = ExclusiveState::None; | 20 | static ExclusiveState exclusive_state = ExclusiveState::None; |
| 23 | static u32 scan_interval = DEFAULT_SCAN_INTERVAL; | 21 | static u32 scan_interval = DEFAULT_SCAN_INTERVAL; |
| 24 | static u32 retry_interval = DEFAULT_RETRY_INTERVAL; | 22 | static u32 retry_interval = DEFAULT_RETRY_INTERVAL; |
| @@ -72,7 +70,8 @@ void UnlockState(Service::Interface* self) { | |||
| 72 | void SuspendDaemons(Service::Interface* self) { | 70 | void SuspendDaemons(Service::Interface* self) { |
| 73 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 71 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 74 | u32 bit_mask = cmd_buff[1] & 0xF; | 72 | u32 bit_mask = cmd_buff[1] & 0xF; |
| 75 | daemon_bit_mask = static_cast<DaemonMask>(static_cast<u32>(default_daemon_bit_mask) & ~bit_mask); | 73 | daemon_bit_mask = |
| 74 | static_cast<DaemonMask>(static_cast<u32>(default_daemon_bit_mask) & ~bit_mask); | ||
| 76 | for (size_t index = 0; index < daemon_status.size(); ++index) { | 75 | for (size_t index = 0; index < daemon_status.size(); ++index) { |
| 77 | if (bit_mask & (1 << index)) { | 76 | if (bit_mask & (1 << index)) { |
| 78 | daemon_status[index] = DaemonStatus::Suspended; | 77 | daemon_status[index] = DaemonStatus::Suspended; |
| @@ -229,8 +228,7 @@ void Init() { | |||
| 229 | } | 228 | } |
| 230 | 229 | ||
| 231 | void Shutdown() { | 230 | void Shutdown() { |
| 232 | |||
| 233 | } | 231 | } |
| 234 | 232 | ||
| 235 | }// namespace NDM | 233 | } // namespace NDM |
| 236 | }// namespace Service | 234 | } // namespace Service |
diff --git a/src/core/hle/service/ndm/ndm.h b/src/core/hle/service/ndm/ndm.h index 5c2b968dc..fb574541d 100644 --- a/src/core/hle/service/ndm/ndm.h +++ b/src/core/hle/service/ndm/ndm.h | |||
| @@ -12,36 +12,26 @@ class Interface; | |||
| 12 | 12 | ||
| 13 | namespace NDM { | 13 | namespace NDM { |
| 14 | 14 | ||
| 15 | enum class Daemon : u32 { | 15 | enum class Daemon : u32 { Cec = 0, Boss = 1, Nim = 2, Friend = 3 }; |
| 16 | Cec = 0, | ||
| 17 | Boss = 1, | ||
| 18 | Nim = 2, | ||
| 19 | Friend = 3 | ||
| 20 | }; | ||
| 21 | 16 | ||
| 22 | enum class DaemonMask : u32 { | 17 | enum class DaemonMask : u32 { |
| 23 | None = 0, | 18 | None = 0, |
| 24 | Cec = (1 << static_cast<u32>(Daemon::Cec)), | 19 | Cec = (1 << static_cast<u32>(Daemon::Cec)), |
| 25 | Boss = (1 << static_cast<u32>(Daemon::Boss)), | 20 | Boss = (1 << static_cast<u32>(Daemon::Boss)), |
| 26 | Nim = (1 << static_cast<u32>(Daemon::Nim)), | 21 | Nim = (1 << static_cast<u32>(Daemon::Nim)), |
| 27 | Friend = (1 << static_cast<u32>(Daemon::Friend)), | 22 | Friend = (1 << static_cast<u32>(Daemon::Friend)), |
| 28 | Default = Cec | Friend, | 23 | Default = Cec | Friend, |
| 29 | All = Cec | Boss | Nim | Friend | 24 | All = Cec | Boss | Nim | Friend |
| 30 | }; | 25 | }; |
| 31 | 26 | ||
| 32 | enum class DaemonStatus : u32 { | 27 | enum class DaemonStatus : u32 { Busy = 0, Idle = 1, Suspending = 2, Suspended = 3 }; |
| 33 | Busy = 0, | ||
| 34 | Idle = 1, | ||
| 35 | Suspending = 2, | ||
| 36 | Suspended = 3 | ||
| 37 | }; | ||
| 38 | 28 | ||
| 39 | enum class ExclusiveState : u32 { | 29 | enum class ExclusiveState : u32 { |
| 40 | None = 0, | 30 | None = 0, |
| 41 | Infrastructure = 1, | 31 | Infrastructure = 1, |
| 42 | LocalCommunications = 2, | 32 | LocalCommunications = 2, |
| 43 | Streetpass = 3, | 33 | Streetpass = 3, |
| 44 | StreetpassData = 4, | 34 | StreetpassData = 4, |
| 45 | }; | 35 | }; |
| 46 | 36 | ||
| 47 | /** | 37 | /** |
| @@ -205,7 +195,6 @@ void SetRetryInterval(Service::Interface* self); | |||
| 205 | */ | 195 | */ |
| 206 | void GetRetryInterval(Service::Interface* self); | 196 | void GetRetryInterval(Service::Interface* self); |
| 207 | 197 | ||
| 208 | |||
| 209 | /** | 198 | /** |
| 210 | * NDM::OverrideDefaultDaemons service function | 199 | * NDM::OverrideDefaultDaemons service function |
| 211 | * Inputs: | 200 | * Inputs: |
| @@ -233,7 +222,8 @@ void ResetDefaultDaemons(Service::Interface* self); | |||
| 233 | * 1 : Result, 0 on success, otherwise error code | 222 | * 1 : Result, 0 on success, otherwise error code |
| 234 | * 2 : Daemon bit mask | 223 | * 2 : Daemon bit mask |
| 235 | * Note: | 224 | * Note: |
| 236 | * Gets the current default daemon bit mask. The default value is (DAEMONMASK_CEC | DAEMONMASK_FRIENDS) | 225 | * Gets the current default daemon bit mask. The default value is (DAEMONMASK_CEC | |
| 226 | * DAEMONMASK_FRIENDS) | ||
| 237 | */ | 227 | */ |
| 238 | void GetDefaultDaemons(Service::Interface* self); | 228 | void GetDefaultDaemons(Service::Interface* self); |
| 239 | 229 | ||
| @@ -252,5 +242,5 @@ void Init(); | |||
| 252 | /// Shutdown NDM service | 242 | /// Shutdown NDM service |
| 253 | void Shutdown(); | 243 | void Shutdown(); |
| 254 | 244 | ||
| 255 | }// namespace NDM | 245 | } // namespace NDM |
| 256 | }// namespace Service | 246 | } // namespace Service |
diff --git a/src/core/hle/service/ndm/ndm_u.cpp b/src/core/hle/service/ndm/ndm_u.cpp index 3ff0744ee..f5c7a341a 100644 --- a/src/core/hle/service/ndm/ndm_u.cpp +++ b/src/core/hle/service/ndm/ndm_u.cpp | |||
| @@ -9,28 +9,28 @@ namespace Service { | |||
| 9 | namespace NDM { | 9 | namespace NDM { |
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = { |
| 12 | {0x00010042, EnterExclusiveState, "EnterExclusiveState"}, | 12 | {0x00010042, EnterExclusiveState, "EnterExclusiveState"}, |
| 13 | {0x00020002, LeaveExclusiveState, "LeaveExclusiveState"}, | 13 | {0x00020002, LeaveExclusiveState, "LeaveExclusiveState"}, |
| 14 | {0x00030000, QueryExclusiveMode, "QueryExclusiveMode"}, | 14 | {0x00030000, QueryExclusiveMode, "QueryExclusiveMode"}, |
| 15 | {0x00040002, LockState, "LockState"}, | 15 | {0x00040002, LockState, "LockState"}, |
| 16 | {0x00050002, UnlockState, "UnlockState"}, | 16 | {0x00050002, UnlockState, "UnlockState"}, |
| 17 | {0x00060040, SuspendDaemons, "SuspendDaemons"}, | 17 | {0x00060040, SuspendDaemons, "SuspendDaemons"}, |
| 18 | {0x00070040, ResumeDaemons, "ResumeDaemons"}, | 18 | {0x00070040, ResumeDaemons, "ResumeDaemons"}, |
| 19 | {0x00080040, SuspendScheduler, "SuspendScheduler"}, | 19 | {0x00080040, SuspendScheduler, "SuspendScheduler"}, |
| 20 | {0x00090000, ResumeScheduler, "ResumeScheduler"}, | 20 | {0x00090000, ResumeScheduler, "ResumeScheduler"}, |
| 21 | {0x000A0000, nullptr, "GetCurrentState"}, | 21 | {0x000A0000, nullptr, "GetCurrentState"}, |
| 22 | {0x000B0000, nullptr, "GetTargetState"}, | 22 | {0x000B0000, nullptr, "GetTargetState"}, |
| 23 | {0x000C0000, nullptr, "<Stubbed>"}, | 23 | {0x000C0000, nullptr, "<Stubbed>"}, |
| 24 | {0x000D0040, QueryStatus, "QueryStatus"}, | 24 | {0x000D0040, QueryStatus, "QueryStatus"}, |
| 25 | {0x000E0040, GetDaemonDisableCount, "GetDaemonDisableCount"}, | 25 | {0x000E0040, GetDaemonDisableCount, "GetDaemonDisableCount"}, |
| 26 | {0x000F0000, GetSchedulerDisableCount,"GetSchedulerDisableCount"}, | 26 | {0x000F0000, GetSchedulerDisableCount, "GetSchedulerDisableCount"}, |
| 27 | {0x00100040, SetScanInterval, "SetScanInterval"}, | 27 | {0x00100040, SetScanInterval, "SetScanInterval"}, |
| 28 | {0x00110000, GetScanInterval, "GetScanInterval"}, | 28 | {0x00110000, GetScanInterval, "GetScanInterval"}, |
| 29 | {0x00120040, SetRetryInterval, "SetRetryInterval"}, | 29 | {0x00120040, SetRetryInterval, "SetRetryInterval"}, |
| 30 | {0x00130000, GetRetryInterval, "GetRetryInterval"}, | 30 | {0x00130000, GetRetryInterval, "GetRetryInterval"}, |
| 31 | {0x00140040, OverrideDefaultDaemons, "OverrideDefaultDaemons"}, | 31 | {0x00140040, OverrideDefaultDaemons, "OverrideDefaultDaemons"}, |
| 32 | {0x00150000, ResetDefaultDaemons, "ResetDefaultDaemons"}, | 32 | {0x00150000, ResetDefaultDaemons, "ResetDefaultDaemons"}, |
| 33 | {0x00160000, GetDefaultDaemons, "GetDefaultDaemons"}, | 33 | {0x00160000, GetDefaultDaemons, "GetDefaultDaemons"}, |
| 34 | {0x00170000, ClearHalfAwakeMacFilter, "ClearHalfAwakeMacFilter"}, | 34 | {0x00170000, ClearHalfAwakeMacFilter, "ClearHalfAwakeMacFilter"}, |
| 35 | }; | 35 | }; |
| 36 | 36 | ||
diff --git a/src/core/hle/service/news/news.cpp b/src/core/hle/service/news/news.cpp index b3f500694..983e0777c 100644 --- a/src/core/hle/service/news/news.cpp +++ b/src/core/hle/service/news/news.cpp | |||
| @@ -4,10 +4,10 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | 6 | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | #include "core/hle/service/news/news.h" | 7 | #include "core/hle/service/news/news.h" |
| 9 | #include "core/hle/service/news/news_s.h" | 8 | #include "core/hle/service/news/news_s.h" |
| 10 | #include "core/hle/service/news/news_u.h" | 9 | #include "core/hle/service/news/news_u.h" |
| 10 | #include "core/hle/service/service.h" | ||
| 11 | 11 | ||
| 12 | namespace Service { | 12 | namespace Service { |
| 13 | namespace NEWS { | 13 | namespace NEWS { |
diff --git a/src/core/hle/service/news/news_s.cpp b/src/core/hle/service/news/news_s.cpp index 39b5a50f8..dda3d0f6a 100644 --- a/src/core/hle/service/news/news_s.cpp +++ b/src/core/hle/service/news/news_s.cpp | |||
| @@ -9,19 +9,19 @@ namespace Service { | |||
| 9 | namespace NEWS { | 9 | namespace NEWS { |
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = { |
| 12 | {0x000100C6, nullptr, "AddNotification"}, | 12 | {0x000100C6, nullptr, "AddNotification"}, |
| 13 | {0x00050000, nullptr, "GetTotalNotifications"}, | 13 | {0x00050000, nullptr, "GetTotalNotifications"}, |
| 14 | {0x00060042, nullptr, "SetNewsDBHeader"}, | 14 | {0x00060042, nullptr, "SetNewsDBHeader"}, |
| 15 | {0x00070082, nullptr, "SetNotificationHeader"}, | 15 | {0x00070082, nullptr, "SetNotificationHeader"}, |
| 16 | {0x00080082, nullptr, "SetNotificationMessage"}, | 16 | {0x00080082, nullptr, "SetNotificationMessage"}, |
| 17 | {0x00090082, nullptr, "SetNotificationImage"}, | 17 | {0x00090082, nullptr, "SetNotificationImage"}, |
| 18 | {0x000A0042, nullptr, "GetNewsDBHeader"}, | 18 | {0x000A0042, nullptr, "GetNewsDBHeader"}, |
| 19 | {0x000B0082, nullptr, "GetNotificationHeader"}, | 19 | {0x000B0082, nullptr, "GetNotificationHeader"}, |
| 20 | {0x000C0082, nullptr, "GetNotificationMessage"}, | 20 | {0x000C0082, nullptr, "GetNotificationMessage"}, |
| 21 | {0x000D0082, nullptr, "GetNotificationImage"}, | 21 | {0x000D0082, nullptr, "GetNotificationImage"}, |
| 22 | {0x000E0040, nullptr, "SetInfoLEDPattern"}, | 22 | {0x000E0040, nullptr, "SetInfoLEDPattern"}, |
| 23 | {0x00120082, nullptr, "GetNotificationHeaderOther"}, | 23 | {0x00120082, nullptr, "GetNotificationHeaderOther"}, |
| 24 | {0x00130000, nullptr, "WriteNewsDBSavedata"}, | 24 | {0x00130000, nullptr, "WriteNewsDBSavedata"}, |
| 25 | }; | 25 | }; |
| 26 | 26 | ||
| 27 | NEWS_S_Interface::NEWS_S_Interface() { | 27 | NEWS_S_Interface::NEWS_S_Interface() { |
diff --git a/src/core/hle/service/news/news_u.cpp b/src/core/hle/service/news/news_u.cpp index 6b75cc24e..a07e466de 100644 --- a/src/core/hle/service/news/news_u.cpp +++ b/src/core/hle/service/news/news_u.cpp | |||
| @@ -8,7 +8,7 @@ namespace Service { | |||
| 8 | namespace NEWS { | 8 | namespace NEWS { |
| 9 | 9 | ||
| 10 | const Interface::FunctionInfo FunctionTable[] = { | 10 | const Interface::FunctionInfo FunctionTable[] = { |
| 11 | {0x000100C6, nullptr, "AddNotification"}, | 11 | {0x000100C6, nullptr, "AddNotification"}, |
| 12 | }; | 12 | }; |
| 13 | 13 | ||
| 14 | NEWS_U_Interface::NEWS_U_Interface() { | 14 | NEWS_U_Interface::NEWS_U_Interface() { |
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp index ed42464ce..f3c01d6e6 100644 --- a/src/core/hle/service/nim/nim.cpp +++ b/src/core/hle/service/nim/nim.cpp | |||
| @@ -5,11 +5,11 @@ | |||
| 5 | #include "common/common_types.h" | 5 | #include "common/common_types.h" |
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | 7 | ||
| 8 | #include "core/hle/service/service.h" | ||
| 9 | #include "core/hle/service/nim/nim.h" | 8 | #include "core/hle/service/nim/nim.h" |
| 10 | #include "core/hle/service/nim/nim_aoc.h" | 9 | #include "core/hle/service/nim/nim_aoc.h" |
| 11 | #include "core/hle/service/nim/nim_s.h" | 10 | #include "core/hle/service/nim/nim_s.h" |
| 12 | #include "core/hle/service/nim/nim_u.h" | 11 | #include "core/hle/service/nim/nim_u.h" |
| 12 | #include "core/hle/service/service.h" | ||
| 13 | 13 | ||
| 14 | namespace Service { | 14 | namespace Service { |
| 15 | namespace NIM { | 15 | namespace NIM { |
diff --git a/src/core/hle/service/nim/nim_aoc.cpp b/src/core/hle/service/nim/nim_aoc.cpp index 4a4818d57..2d0fb6fc4 100644 --- a/src/core/hle/service/nim/nim_aoc.cpp +++ b/src/core/hle/service/nim/nim_aoc.cpp | |||
| @@ -8,14 +8,14 @@ namespace Service { | |||
| 8 | namespace NIM { | 8 | namespace NIM { |
| 9 | 9 | ||
| 10 | const Interface::FunctionInfo FunctionTable[] = { | 10 | const Interface::FunctionInfo FunctionTable[] = { |
| 11 | {0x00030042, nullptr, "SetApplicationId"}, | 11 | {0x00030042, nullptr, "SetApplicationId"}, |
| 12 | {0x00040042, nullptr, "SetTin"}, | 12 | {0x00040042, nullptr, "SetTin"}, |
| 13 | {0x000902D0, nullptr, "ListContentSetsEx"}, | 13 | {0x000902D0, nullptr, "ListContentSetsEx"}, |
| 14 | {0x00180000, nullptr, "GetBalance"}, | 14 | {0x00180000, nullptr, "GetBalance"}, |
| 15 | {0x001D0000, nullptr, "GetCustomerSupportCode"}, | 15 | {0x001D0000, nullptr, "GetCustomerSupportCode"}, |
| 16 | {0x00210000, nullptr, "Initialize"}, | 16 | {0x00210000, nullptr, "Initialize"}, |
| 17 | {0x00240282, nullptr, "CalculateContentsRequiredSize"}, | 17 | {0x00240282, nullptr, "CalculateContentsRequiredSize"}, |
| 18 | {0x00250000, nullptr, "RefreshServerTime"}, | 18 | {0x00250000, nullptr, "RefreshServerTime"}, |
| 19 | }; | 19 | }; |
| 20 | 20 | ||
| 21 | NIM_AOC_Interface::NIM_AOC_Interface() { | 21 | NIM_AOC_Interface::NIM_AOC_Interface() { |
diff --git a/src/core/hle/service/nim/nim_s.cpp b/src/core/hle/service/nim/nim_s.cpp index dcaa0255a..e2ba693c9 100644 --- a/src/core/hle/service/nim/nim_s.cpp +++ b/src/core/hle/service/nim/nim_s.cpp | |||
| @@ -8,10 +8,10 @@ namespace Service { | |||
| 8 | namespace NIM { | 8 | namespace NIM { |
| 9 | 9 | ||
| 10 | const Interface::FunctionInfo FunctionTable[] = { | 10 | const Interface::FunctionInfo FunctionTable[] = { |
| 11 | {0x000A0000, nullptr, "CheckSysupdateAvailableSOAP"}, | 11 | {0x000A0000, nullptr, "CheckSysupdateAvailableSOAP"}, |
| 12 | {0x0016020A, nullptr, "ListTitles"}, | 12 | {0x0016020A, nullptr, "ListTitles"}, |
| 13 | {0x002D0042, nullptr, "DownloadTickets"}, | 13 | {0x002D0042, nullptr, "DownloadTickets"}, |
| 14 | {0x00420240, nullptr, "StartDownload"}, | 14 | {0x00420240, nullptr, "StartDownload"}, |
| 15 | }; | 15 | }; |
| 16 | 16 | ||
| 17 | NIM_S_Interface::NIM_S_Interface() { | 17 | NIM_S_Interface::NIM_S_Interface() { |
| @@ -20,4 +20,3 @@ NIM_S_Interface::NIM_S_Interface() { | |||
| 20 | 20 | ||
| 21 | } // namespace NIM | 21 | } // namespace NIM |
| 22 | } // namespace Service | 22 | } // namespace Service |
| 23 | |||
diff --git a/src/core/hle/service/nim/nim_u.cpp b/src/core/hle/service/nim/nim_u.cpp index eae45ebc0..7e07d02e8 100644 --- a/src/core/hle/service/nim/nim_u.cpp +++ b/src/core/hle/service/nim/nim_u.cpp | |||
| @@ -9,12 +9,12 @@ namespace Service { | |||
| 9 | namespace NIM { | 9 | namespace NIM { |
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = { |
| 12 | {0x00010000, nullptr, "StartSysUpdate"}, | 12 | {0x00010000, nullptr, "StartSysUpdate"}, |
| 13 | {0x00020000, nullptr, "GetUpdateDownloadProgress"}, | 13 | {0x00020000, nullptr, "GetUpdateDownloadProgress"}, |
| 14 | {0x00040000, nullptr, "FinishTitlesInstall"}, | 14 | {0x00040000, nullptr, "FinishTitlesInstall"}, |
| 15 | {0x00050000, nullptr, "CheckForSysUpdateEvent"}, | 15 | {0x00050000, nullptr, "CheckForSysUpdateEvent"}, |
| 16 | {0x00090000, CheckSysUpdateAvailable, "CheckSysUpdateAvailable"}, | 16 | {0x00090000, CheckSysUpdateAvailable, "CheckSysUpdateAvailable"}, |
| 17 | {0x000A0000, nullptr, "GetState"}, | 17 | {0x000A0000, nullptr, "GetState"}, |
| 18 | }; | 18 | }; |
| 19 | 19 | ||
| 20 | NIM_U_Interface::NIM_U_Interface() { | 20 | NIM_U_Interface::NIM_U_Interface() { |
| @@ -23,4 +23,3 @@ NIM_U_Interface::NIM_U_Interface() { | |||
| 23 | 23 | ||
| 24 | } // namespace NIM | 24 | } // namespace NIM |
| 25 | } // namespace Service | 25 | } // namespace Service |
| 26 | |||
diff --git a/src/core/hle/service/ns_s.cpp b/src/core/hle/service/ns_s.cpp index 072918d62..6693f7c08 100644 --- a/src/core/hle/service/ns_s.cpp +++ b/src/core/hle/service/ns_s.cpp | |||
| @@ -10,21 +10,21 @@ | |||
| 10 | namespace NS_S { | 10 | namespace NS_S { |
| 11 | 11 | ||
| 12 | const Interface::FunctionInfo FunctionTable[] = { | 12 | const Interface::FunctionInfo FunctionTable[] = { |
| 13 | {0x000100C0, nullptr, "LaunchFIRM"}, | 13 | {0x000100C0, nullptr, "LaunchFIRM"}, |
| 14 | {0x000200C0, nullptr, "LaunchTitle"}, | 14 | {0x000200C0, nullptr, "LaunchTitle"}, |
| 15 | {0x00030000, nullptr, "TerminateApplication"}, | 15 | {0x00030000, nullptr, "TerminateApplication"}, |
| 16 | {0x00040040, nullptr, "TerminateProcess"}, | 16 | {0x00040040, nullptr, "TerminateProcess"}, |
| 17 | {0x000500C0, nullptr, "LaunchApplicationFIRM"}, | 17 | {0x000500C0, nullptr, "LaunchApplicationFIRM"}, |
| 18 | {0x00060042, nullptr, "SetFIRMParams4A0"}, | 18 | {0x00060042, nullptr, "SetFIRMParams4A0"}, |
| 19 | {0x00070042, nullptr, "CardUpdateInitialize"}, | 19 | {0x00070042, nullptr, "CardUpdateInitialize"}, |
| 20 | {0x00080000, nullptr, "CardUpdateShutdown"}, | 20 | {0x00080000, nullptr, "CardUpdateShutdown"}, |
| 21 | {0x000D0140, nullptr, "SetTWLBannerHMAC"}, | 21 | {0x000D0140, nullptr, "SetTWLBannerHMAC"}, |
| 22 | {0x000E0000, nullptr, "ShutdownAsync"}, | 22 | {0x000E0000, nullptr, "ShutdownAsync"}, |
| 23 | {0x00100180, nullptr, "RebootSystem"}, | 23 | {0x00100180, nullptr, "RebootSystem"}, |
| 24 | {0x00110100, nullptr, "TerminateTitle"}, | 24 | {0x00110100, nullptr, "TerminateTitle"}, |
| 25 | {0x001200C0, nullptr, "SetApplicationCpuTimeLimit"}, | 25 | {0x001200C0, nullptr, "SetApplicationCpuTimeLimit"}, |
| 26 | {0x00150140, nullptr, "LaunchApplication"}, | 26 | {0x00150140, nullptr, "LaunchApplication"}, |
| 27 | {0x00160000, nullptr, "RebootSystemClean"}, | 27 | {0x00160000, nullptr, "RebootSystemClean"}, |
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| 30 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 30 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
diff --git a/src/core/hle/service/nwm_uds.cpp b/src/core/hle/service/nwm_uds.cpp index ae4640409..ed417fa9a 100644 --- a/src/core/hle/service/nwm_uds.cpp +++ b/src/core/hle/service/nwm_uds.cpp | |||
| @@ -54,22 +54,23 @@ static void Shutdown(Service::Interface* self) { | |||
| 54 | static void RecvBeaconBroadcastData(Service::Interface* self) { | 54 | static void RecvBeaconBroadcastData(Service::Interface* self) { |
| 55 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 55 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 56 | u32 out_buffer_size = cmd_buff[1]; | 56 | u32 out_buffer_size = cmd_buff[1]; |
| 57 | u32 unk1 = cmd_buff[2]; | 57 | u32 unk1 = cmd_buff[2]; |
| 58 | u32 unk2 = cmd_buff[3]; | 58 | u32 unk2 = cmd_buff[3]; |
| 59 | u32 mac_address = cmd_buff[4]; | 59 | u32 mac_address = cmd_buff[4]; |
| 60 | 60 | ||
| 61 | u32 unk3 = cmd_buff[6]; | 61 | u32 unk3 = cmd_buff[6]; |
| 62 | 62 | ||
| 63 | u32 wlan_comm_id = cmd_buff[15]; | 63 | u32 wlan_comm_id = cmd_buff[15]; |
| 64 | u32 ctr_gen_id = cmd_buff[16]; | 64 | u32 ctr_gen_id = cmd_buff[16]; |
| 65 | u32 value = cmd_buff[17]; | 65 | u32 value = cmd_buff[17]; |
| 66 | u32 input_handle = cmd_buff[18]; | 66 | u32 input_handle = cmd_buff[18]; |
| 67 | u32 new_buffer_size = cmd_buff[19]; | 67 | u32 new_buffer_size = cmd_buff[19]; |
| 68 | u32 out_buffer_ptr = cmd_buff[20]; | 68 | u32 out_buffer_ptr = cmd_buff[20]; |
| 69 | 69 | ||
| 70 | cmd_buff[1] = RESULT_SUCCESS.raw; | 70 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 71 | 71 | ||
| 72 | LOG_WARNING(Service_NWM, "(STUBBED) called out_buffer_size=0x%08X, unk1=0x%08X, unk2=0x%08X," | 72 | LOG_WARNING(Service_NWM, |
| 73 | "(STUBBED) called out_buffer_size=0x%08X, unk1=0x%08X, unk2=0x%08X," | ||
| 73 | "mac_address=0x%08X, unk3=0x%08X, wlan_comm_id=0x%08X, ctr_gen_id=0x%08X," | 74 | "mac_address=0x%08X, unk3=0x%08X, wlan_comm_id=0x%08X, ctr_gen_id=0x%08X," |
| 74 | "value=%u, input_handle=0x%08X, new_buffer_size=0x%08X, out_buffer_ptr=0x%08X", | 75 | "value=%u, input_handle=0x%08X, new_buffer_size=0x%08X, out_buffer_ptr=0x%08X", |
| 75 | out_buffer_size, unk1, unk2, mac_address, unk3, wlan_comm_id, ctr_gen_id, value, | 76 | out_buffer_size, unk1, unk2, mac_address, unk3, wlan_comm_id, ctr_gen_id, value, |
| @@ -92,46 +93,47 @@ static void RecvBeaconBroadcastData(Service::Interface* self) { | |||
| 92 | */ | 93 | */ |
| 93 | static void Initialize(Service::Interface* self) { | 94 | static void Initialize(Service::Interface* self) { |
| 94 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 95 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 95 | u32 unk1 = cmd_buff[1]; | 96 | u32 unk1 = cmd_buff[1]; |
| 96 | u32 unk2 = cmd_buff[12]; | 97 | u32 unk2 = cmd_buff[12]; |
| 97 | u32 value = cmd_buff[13]; | 98 | u32 value = cmd_buff[13]; |
| 98 | u32 handle = cmd_buff[14]; | 99 | u32 handle = cmd_buff[14]; |
| 99 | 100 | ||
| 100 | cmd_buff[1] = RESULT_SUCCESS.raw; | 101 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 101 | cmd_buff[2] = 0; | 102 | cmd_buff[2] = 0; |
| 102 | cmd_buff[3] = Kernel::g_handle_table.Create(handle_event).MoveFrom(); //TODO(purpasmart): Verify if this is a event handle | 103 | cmd_buff[3] = Kernel::g_handle_table.Create(handle_event) |
| 104 | .MoveFrom(); // TODO(purpasmart): Verify if this is a event handle | ||
| 103 | 105 | ||
| 104 | LOG_WARNING(Service_NWM, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, value=%u, handle=0x%08X", | 106 | LOG_WARNING(Service_NWM, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, value=%u, handle=0x%08X", |
| 105 | unk1, unk2, value, handle); | 107 | unk1, unk2, value, handle); |
| 106 | } | 108 | } |
| 107 | 109 | ||
| 108 | const Interface::FunctionInfo FunctionTable[] = { | 110 | const Interface::FunctionInfo FunctionTable[] = { |
| 109 | {0x00020000, nullptr, "Scrap"}, | 111 | {0x00020000, nullptr, "Scrap"}, |
| 110 | {0x00030000, Shutdown, "Shutdown"}, | 112 | {0x00030000, Shutdown, "Shutdown"}, |
| 111 | {0x00040402, nullptr, "CreateNetwork"}, | 113 | {0x00040402, nullptr, "CreateNetwork"}, |
| 112 | {0x00050040, nullptr, "EjectClient"}, | 114 | {0x00050040, nullptr, "EjectClient"}, |
| 113 | {0x00060000, nullptr, "EjectSpectator"}, | 115 | {0x00060000, nullptr, "EjectSpectator"}, |
| 114 | {0x00070080, nullptr, "UpdateNetworkAttribute"}, | 116 | {0x00070080, nullptr, "UpdateNetworkAttribute"}, |
| 115 | {0x00080000, nullptr, "DestroyNetwork"}, | 117 | {0x00080000, nullptr, "DestroyNetwork"}, |
| 116 | {0x000A0000, nullptr, "DisconnectNetwork"}, | 118 | {0x000A0000, nullptr, "DisconnectNetwork"}, |
| 117 | {0x000B0000, nullptr, "GetConnectionStatus"}, | 119 | {0x000B0000, nullptr, "GetConnectionStatus"}, |
| 118 | {0x000D0040, nullptr, "GetNodeInformation"}, | 120 | {0x000D0040, nullptr, "GetNodeInformation"}, |
| 119 | {0x000F0404, RecvBeaconBroadcastData, "RecvBeaconBroadcastData"}, | 121 | {0x000F0404, RecvBeaconBroadcastData, "RecvBeaconBroadcastData"}, |
| 120 | {0x00100042, nullptr, "SetBeaconAdditionalData"}, | 122 | {0x00100042, nullptr, "SetBeaconAdditionalData"}, |
| 121 | {0x00110040, nullptr, "GetApplicationData"}, | 123 | {0x00110040, nullptr, "GetApplicationData"}, |
| 122 | {0x00120100, nullptr, "Bind"}, | 124 | {0x00120100, nullptr, "Bind"}, |
| 123 | {0x00130040, nullptr, "Unbind"}, | 125 | {0x00130040, nullptr, "Unbind"}, |
| 124 | {0x001400C0, nullptr, "RecvBroadcastDataFrame"}, | 126 | {0x001400C0, nullptr, "RecvBroadcastDataFrame"}, |
| 125 | {0x00150080, nullptr, "SetMaxSendDelay"}, | 127 | {0x00150080, nullptr, "SetMaxSendDelay"}, |
| 126 | {0x00170182, nullptr, "SendTo"}, | 128 | {0x00170182, nullptr, "SendTo"}, |
| 127 | {0x001A0000, nullptr, "GetChannel"}, | 129 | {0x001A0000, nullptr, "GetChannel"}, |
| 128 | {0x001B0302, Initialize, "Initialize"}, | 130 | {0x001B0302, Initialize, "Initialize"}, |
| 129 | {0x001D0044, nullptr, "BeginHostingNetwork"}, | 131 | {0x001D0044, nullptr, "BeginHostingNetwork"}, |
| 130 | {0x001E0084, nullptr, "ConnectToNetwork"}, | 132 | {0x001E0084, nullptr, "ConnectToNetwork"}, |
| 131 | {0x001F0006, nullptr, "DecryptBeaconData"}, | 133 | {0x001F0006, nullptr, "DecryptBeaconData"}, |
| 132 | {0x00200040, nullptr, "Flush"}, | 134 | {0x00200040, nullptr, "Flush"}, |
| 133 | {0x00210080, nullptr, "SetProbeResponseParam"}, | 135 | {0x00210080, nullptr, "SetProbeResponseParam"}, |
| 134 | {0x00220402, nullptr, "ScanOnConnection"}, | 136 | {0x00220402, nullptr, "ScanOnConnection"}, |
| 135 | }; | 137 | }; |
| 136 | 138 | ||
| 137 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 139 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
diff --git a/src/core/hle/service/pm_app.cpp b/src/core/hle/service/pm_app.cpp index 05d01bc48..7d91694f6 100644 --- a/src/core/hle/service/pm_app.cpp +++ b/src/core/hle/service/pm_app.cpp | |||
| @@ -10,18 +10,18 @@ | |||
| 10 | namespace PM_APP { | 10 | namespace PM_APP { |
| 11 | 11 | ||
| 12 | const Interface::FunctionInfo FunctionTable[] = { | 12 | const Interface::FunctionInfo FunctionTable[] = { |
| 13 | {0x00010140, nullptr, "LaunchTitle"}, | 13 | {0x00010140, nullptr, "LaunchTitle"}, |
| 14 | {0x00020082, nullptr, "LaunchFIRMSetParams"}, | 14 | {0x00020082, nullptr, "LaunchFIRMSetParams"}, |
| 15 | {0x00030080, nullptr, "TerminateProcesse"}, | 15 | {0x00030080, nullptr, "TerminateProcesse"}, |
| 16 | {0x00040100, nullptr, "TerminateProcessTID"}, | 16 | {0x00040100, nullptr, "TerminateProcessTID"}, |
| 17 | {0x000500C0, nullptr, "TerminateProcessTID_unknown"}, | 17 | {0x000500C0, nullptr, "TerminateProcessTID_unknown"}, |
| 18 | {0x00070042, nullptr, "GetFIRMLaunchParams"}, | 18 | {0x00070042, nullptr, "GetFIRMLaunchParams"}, |
| 19 | {0x00080100, nullptr, "GetTitleExheaderFlags"}, | 19 | {0x00080100, nullptr, "GetTitleExheaderFlags"}, |
| 20 | {0x00090042, nullptr, "SetFIRMLaunchParams"}, | 20 | {0x00090042, nullptr, "SetFIRMLaunchParams"}, |
| 21 | {0x000A0140, nullptr, "SetResourceLimit"}, | 21 | {0x000A0140, nullptr, "SetResourceLimit"}, |
| 22 | {0x000B0140, nullptr, "GetResourceLimitMax"}, | 22 | {0x000B0140, nullptr, "GetResourceLimitMax"}, |
| 23 | {0x000C0080, nullptr, "UnregisterProcess"}, | 23 | {0x000C0080, nullptr, "UnregisterProcess"}, |
| 24 | {0x000D0240, nullptr, "LaunchTitleUpdate"}, | 24 | {0x000D0240, nullptr, "LaunchTitleUpdate"}, |
| 25 | }; | 25 | }; |
| 26 | 26 | ||
| 27 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 27 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp index e2c17d93b..80fa09f5f 100644 --- a/src/core/hle/service/ptm/ptm.cpp +++ b/src/core/hle/service/ptm/ptm.cpp | |||
| @@ -2,21 +2,21 @@ | |||
| 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/hle/service/ptm/ptm.h" | ||
| 5 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 6 | #include "core/settings.h" | ||
| 7 | #include "core/file_sys/file_backend.h" | 7 | #include "core/file_sys/file_backend.h" |
| 8 | #include "core/hle/service/fs/archive.h" | 8 | #include "core/hle/service/fs/archive.h" |
| 9 | #include "core/hle/service/ptm/ptm.h" | ||
| 10 | #include "core/hle/service/ptm/ptm_play.h" | 9 | #include "core/hle/service/ptm/ptm_play.h" |
| 11 | #include "core/hle/service/ptm/ptm_sysm.h" | 10 | #include "core/hle/service/ptm/ptm_sysm.h" |
| 12 | #include "core/hle/service/ptm/ptm_u.h" | 11 | #include "core/hle/service/ptm/ptm_u.h" |
| 13 | #include "core/hle/service/service.h" | 12 | #include "core/hle/service/service.h" |
| 13 | #include "core/settings.h" | ||
| 14 | 14 | ||
| 15 | namespace Service { | 15 | namespace Service { |
| 16 | namespace PTM { | 16 | namespace PTM { |
| 17 | 17 | ||
| 18 | /// Values for the default gamecoin.dat file | 18 | /// Values for the default gamecoin.dat file |
| 19 | static const GameCoin default_game_coin = { 0x4F00, 42, 0, 0, 0, 2014, 12, 29 }; | 19 | static const GameCoin default_game_coin = {0x4F00, 42, 0, 0, 0, 2014, 12, 29}; |
| 20 | 20 | ||
| 21 | /// Id of the SharedExtData archive used by the PTM process | 21 | /// Id of the SharedExtData archive used by the PTM process |
| 22 | static const std::vector<u8> ptm_shared_extdata_id = {0, 0, 0, 0, 0x0B, 0, 0, 0xF0, 0, 0, 0, 0}; | 22 | static const std::vector<u8> ptm_shared_extdata_id = {0, 0, 0, 0, 0x0B, 0, 0, 0xF0, 0, 0, 0, 0}; |
| @@ -51,7 +51,8 @@ void GetBatteryLevel(Service::Interface* self) { | |||
| 51 | // it returns a valid result without implementing full functionality. | 51 | // it returns a valid result without implementing full functionality. |
| 52 | 52 | ||
| 53 | cmd_buff[1] = RESULT_SUCCESS.raw; | 53 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 54 | cmd_buff[2] = static_cast<u32>(ChargeLevels::CompletelyFull); // Set to a completely full battery | 54 | cmd_buff[2] = |
| 55 | static_cast<u32>(ChargeLevels::CompletelyFull); // Set to a completely full battery | ||
| 55 | 56 | ||
| 56 | LOG_WARNING(Service_PTM, "(STUBBED) called"); | 57 | LOG_WARNING(Service_PTM, "(STUBBED) called"); |
| 57 | } | 58 | } |
| @@ -94,7 +95,8 @@ void CheckNew3DS(Service::Interface* self) { | |||
| 94 | const bool is_new_3ds = Settings::values.is_new_3ds; | 95 | const bool is_new_3ds = Settings::values.is_new_3ds; |
| 95 | 96 | ||
| 96 | if (is_new_3ds) { | 97 | if (is_new_3ds) { |
| 97 | LOG_CRITICAL(Service_PTM, "The option 'is_new_3ds' is enabled as part of the 'System' settings. Citra does not fully support New 3DS emulation yet!"); | 98 | LOG_CRITICAL(Service_PTM, "The option 'is_new_3ds' is enabled as part of the 'System' " |
| 99 | "settings. Citra does not fully support New 3DS emulation yet!"); | ||
| 98 | } | 100 | } |
| 99 | 101 | ||
| 100 | cmd_buff[1] = RESULT_SUCCESS.raw; | 102 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| @@ -111,15 +113,19 @@ void Init() { | |||
| 111 | shell_open = true; | 113 | shell_open = true; |
| 112 | battery_is_charging = true; | 114 | battery_is_charging = true; |
| 113 | 115 | ||
| 114 | // Open the SharedExtSaveData archive 0xF000000B and create the gamecoin.dat file if it doesn't exist | 116 | // Open the SharedExtSaveData archive 0xF000000B and create the gamecoin.dat file if it doesn't |
| 117 | // exist | ||
| 115 | FileSys::Path archive_path(ptm_shared_extdata_id); | 118 | FileSys::Path archive_path(ptm_shared_extdata_id); |
| 116 | auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); | 119 | auto archive_result = |
| 120 | Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); | ||
| 117 | // If the archive didn't exist, create the files inside | 121 | // If the archive didn't exist, create the files inside |
| 118 | if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { | 122 | if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { |
| 119 | // Format the archive to create the directories | 123 | // Format the archive to create the directories |
| 120 | Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, FileSys::ArchiveFormatInfo(), archive_path); | 124 | Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, |
| 125 | FileSys::ArchiveFormatInfo(), archive_path); | ||
| 121 | // Open it again to get a valid archive now that the folder exists | 126 | // Open it again to get a valid archive now that the folder exists |
| 122 | archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); | 127 | archive_result = |
| 128 | Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); | ||
| 123 | ASSERT_MSG(archive_result.Succeeded(), "Could not open the PTM SharedExtSaveData archive!"); | 129 | ASSERT_MSG(archive_result.Succeeded(), "Could not open the PTM SharedExtSaveData archive!"); |
| 124 | 130 | ||
| 125 | FileSys::Path gamecoin_path("gamecoin.dat"); | 131 | FileSys::Path gamecoin_path("gamecoin.dat"); |
| @@ -127,17 +133,18 @@ void Init() { | |||
| 127 | open_mode.write_flag.Assign(1); | 133 | open_mode.write_flag.Assign(1); |
| 128 | open_mode.create_flag.Assign(1); | 134 | open_mode.create_flag.Assign(1); |
| 129 | // Open the file and write the default gamecoin information | 135 | // Open the file and write the default gamecoin information |
| 130 | auto gamecoin_result = Service::FS::OpenFileFromArchive(*archive_result, gamecoin_path, open_mode); | 136 | auto gamecoin_result = |
| 137 | Service::FS::OpenFileFromArchive(*archive_result, gamecoin_path, open_mode); | ||
| 131 | if (gamecoin_result.Succeeded()) { | 138 | if (gamecoin_result.Succeeded()) { |
| 132 | auto gamecoin = gamecoin_result.MoveFrom(); | 139 | auto gamecoin = gamecoin_result.MoveFrom(); |
| 133 | gamecoin->backend->Write(0, sizeof(GameCoin), 1, reinterpret_cast<const u8*>(&default_game_coin)); | 140 | gamecoin->backend->Write(0, sizeof(GameCoin), 1, |
| 141 | reinterpret_cast<const u8*>(&default_game_coin)); | ||
| 134 | gamecoin->backend->Close(); | 142 | gamecoin->backend->Close(); |
| 135 | } | 143 | } |
| 136 | } | 144 | } |
| 137 | } | 145 | } |
| 138 | 146 | ||
| 139 | void Shutdown() { | 147 | void Shutdown() { |
| 140 | |||
| 141 | } | 148 | } |
| 142 | 149 | ||
| 143 | } // namespace PTM | 150 | } // namespace PTM |
diff --git a/src/core/hle/service/ptm/ptm.h b/src/core/hle/service/ptm/ptm.h index 7ef8877c7..6e163a6f9 100644 --- a/src/core/hle/service/ptm/ptm.h +++ b/src/core/hle/service/ptm/ptm.h | |||
| @@ -14,23 +14,24 @@ namespace PTM { | |||
| 14 | 14 | ||
| 15 | /// Charge levels used by PTM functions | 15 | /// Charge levels used by PTM functions |
| 16 | enum class ChargeLevels : u32 { | 16 | enum class ChargeLevels : u32 { |
| 17 | CriticalBattery = 1, | 17 | CriticalBattery = 1, |
| 18 | LowBattery = 2, | 18 | LowBattery = 2, |
| 19 | HalfFull = 3, | 19 | HalfFull = 3, |
| 20 | MostlyFull = 4, | 20 | MostlyFull = 4, |
| 21 | CompletelyFull = 5, | 21 | CompletelyFull = 5, |
| 22 | }; | 22 | }; |
| 23 | 23 | ||
| 24 | /** | 24 | /** |
| 25 | * Represents the gamecoin file structure in the SharedExtData archive | 25 | * Represents the gamecoin file structure in the SharedExtData archive |
| 26 | * More information in 3dbrew (http://www.3dbrew.org/wiki/Extdata#Shared_Extdata_0xf000000b_gamecoin.dat) | 26 | * More information in 3dbrew |
| 27 | * (http://www.3dbrew.org/wiki/Extdata#Shared_Extdata_0xf000000b_gamecoin.dat) | ||
| 27 | */ | 28 | */ |
| 28 | struct GameCoin { | 29 | struct GameCoin { |
| 29 | u32 magic; ///< Magic number: 0x4F00 | 30 | u32 magic; ///< Magic number: 0x4F00 |
| 30 | u16 total_coins; ///< Total Play Coins | 31 | u16 total_coins; ///< Total Play Coins |
| 31 | u16 total_coins_on_date; ///< Total Play Coins obtained on the date stored below. | 32 | u16 total_coins_on_date; ///< Total Play Coins obtained on the date stored below. |
| 32 | u32 step_count; ///< Total step count at the time a new Play Coin was obtained. | 33 | u32 step_count; ///< Total step count at the time a new Play Coin was obtained. |
| 33 | u32 last_step_count; ///< Step count for the day the last Play Coin was obtained | 34 | u32 last_step_count; ///< Step count for the day the last Play Coin was obtained |
| 34 | u16 year; | 35 | u16 year; |
| 35 | u8 month; | 36 | u8 month; |
| 36 | u8 day; | 37 | u8 day; |
diff --git a/src/core/hle/service/ptm/ptm_play.cpp b/src/core/hle/service/ptm/ptm_play.cpp index ca5dd0403..2e0c6e1a3 100644 --- a/src/core/hle/service/ptm/ptm_play.cpp +++ b/src/core/hle/service/ptm/ptm_play.cpp | |||
| @@ -8,10 +8,10 @@ namespace Service { | |||
| 8 | namespace PTM { | 8 | namespace PTM { |
| 9 | 9 | ||
| 10 | const Interface::FunctionInfo FunctionTable[] = { | 10 | const Interface::FunctionInfo FunctionTable[] = { |
| 11 | {0x08070082, nullptr, "GetPlayHistory"}, | 11 | {0x08070082, nullptr, "GetPlayHistory"}, |
| 12 | {0x08080000, nullptr, "GetPlayHistoryStart"}, | 12 | {0x08080000, nullptr, "GetPlayHistoryStart"}, |
| 13 | {0x08090000, nullptr, "GetPlayHistoryLength"}, | 13 | {0x08090000, nullptr, "GetPlayHistoryLength"}, |
| 14 | {0x080B0080, nullptr, "CalcPlayHistoryStart"}, | 14 | {0x080B0080, nullptr, "CalcPlayHistoryStart"}, |
| 15 | }; | 15 | }; |
| 16 | 16 | ||
| 17 | PTM_Play_Interface::PTM_Play_Interface() { | 17 | PTM_Play_Interface::PTM_Play_Interface() { |
diff --git a/src/core/hle/service/ptm/ptm_play.h b/src/core/hle/service/ptm/ptm_play.h index e5c3e04df..47f229581 100644 --- a/src/core/hle/service/ptm/ptm_play.h +++ b/src/core/hle/service/ptm/ptm_play.h | |||
| @@ -13,9 +13,9 @@ class PTM_Play_Interface : public Service::Interface { | |||
| 13 | public: | 13 | public: |
| 14 | PTM_Play_Interface(); | 14 | PTM_Play_Interface(); |
| 15 | 15 | ||
| 16 | std::string GetPortName() const override { | 16 | std::string GetPortName() const override { |
| 17 | return "ptm:play"; | 17 | return "ptm:play"; |
| 18 | } | 18 | } |
| 19 | }; | 19 | }; |
| 20 | 20 | ||
| 21 | } // namespace PTM | 21 | } // namespace PTM |
diff --git a/src/core/hle/service/ptm/ptm_sysm.cpp b/src/core/hle/service/ptm/ptm_sysm.cpp index cc4ef1101..693158dbf 100644 --- a/src/core/hle/service/ptm/ptm_sysm.cpp +++ b/src/core/hle/service/ptm/ptm_sysm.cpp | |||
| @@ -9,37 +9,37 @@ namespace Service { | |||
| 9 | namespace PTM { | 9 | namespace PTM { |
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = { |
| 12 | {0x040100C0, nullptr, "SetRtcAlarmEx"}, | 12 | {0x040100C0, nullptr, "SetRtcAlarmEx"}, |
| 13 | {0x04020042, nullptr, "ReplySleepQuery"}, | 13 | {0x04020042, nullptr, "ReplySleepQuery"}, |
| 14 | {0x04030042, nullptr, "NotifySleepPreparationComplete"}, | 14 | {0x04030042, nullptr, "NotifySleepPreparationComplete"}, |
| 15 | {0x04040102, nullptr, "SetWakeupTrigger"}, | 15 | {0x04040102, nullptr, "SetWakeupTrigger"}, |
| 16 | {0x04050000, nullptr, "GetAwakeReason"}, | 16 | {0x04050000, nullptr, "GetAwakeReason"}, |
| 17 | {0x04060000, nullptr, "RequestSleep"}, | 17 | {0x04060000, nullptr, "RequestSleep"}, |
| 18 | {0x040700C0, nullptr, "ShutdownAsync"}, | 18 | {0x040700C0, nullptr, "ShutdownAsync"}, |
| 19 | {0x04080000, nullptr, "Awake"}, | 19 | {0x04080000, nullptr, "Awake"}, |
| 20 | {0x04090080, nullptr, "RebootAsync"}, | 20 | {0x04090080, nullptr, "RebootAsync"}, |
| 21 | {0x040A0000, CheckNew3DS, "CheckNew3DS"}, | 21 | {0x040A0000, CheckNew3DS, "CheckNew3DS"}, |
| 22 | {0x08010640, nullptr, "SetInfoLEDPattern"}, | 22 | {0x08010640, nullptr, "SetInfoLEDPattern"}, |
| 23 | {0x08020040, nullptr, "SetInfoLEDPatternHeader"}, | 23 | {0x08020040, nullptr, "SetInfoLEDPatternHeader"}, |
| 24 | {0x08030000, nullptr, "GetInfoLEDStatus"}, | 24 | {0x08030000, nullptr, "GetInfoLEDStatus"}, |
| 25 | {0x08040040, nullptr, "SetBatteryEmptyLEDPattern"}, | 25 | {0x08040040, nullptr, "SetBatteryEmptyLEDPattern"}, |
| 26 | {0x08050000, nullptr, "ClearStepHistory"}, | 26 | {0x08050000, nullptr, "ClearStepHistory"}, |
| 27 | {0x080600C2, nullptr, "SetStepHistory"}, | 27 | {0x080600C2, nullptr, "SetStepHistory"}, |
| 28 | {0x08070082, nullptr, "GetPlayHistory"}, | 28 | {0x08070082, nullptr, "GetPlayHistory"}, |
| 29 | {0x08080000, nullptr, "GetPlayHistoryStart"}, | 29 | {0x08080000, nullptr, "GetPlayHistoryStart"}, |
| 30 | {0x08090000, nullptr, "GetPlayHistoryLength"}, | 30 | {0x08090000, nullptr, "GetPlayHistoryLength"}, |
| 31 | {0x080A0000, nullptr, "ClearPlayHistory"}, | 31 | {0x080A0000, nullptr, "ClearPlayHistory"}, |
| 32 | {0x080B0080, nullptr, "CalcPlayHistoryStart"}, | 32 | {0x080B0080, nullptr, "CalcPlayHistoryStart"}, |
| 33 | {0x080C0080, nullptr, "SetUserTime"}, | 33 | {0x080C0080, nullptr, "SetUserTime"}, |
| 34 | {0x080D0000, nullptr, "InvalidateSystemTime"}, | 34 | {0x080D0000, nullptr, "InvalidateSystemTime"}, |
| 35 | {0x080E0140, nullptr, "NotifyPlayEvent"}, | 35 | {0x080E0140, nullptr, "NotifyPlayEvent"}, |
| 36 | {0x080F0000, IsLegacyPowerOff, "IsLegacyPowerOff"}, | 36 | {0x080F0000, IsLegacyPowerOff, "IsLegacyPowerOff"}, |
| 37 | {0x08100000, nullptr, "ClearLegacyPowerOff"}, | 37 | {0x08100000, nullptr, "ClearLegacyPowerOff"}, |
| 38 | {0x08110000, GetShellState, "GetShellState"}, | 38 | {0x08110000, GetShellState, "GetShellState"}, |
| 39 | {0x08120000, nullptr, "IsShutdownByBatteryEmpty"}, | 39 | {0x08120000, nullptr, "IsShutdownByBatteryEmpty"}, |
| 40 | {0x08130000, nullptr, "FormatSavedata"}, | 40 | {0x08130000, nullptr, "FormatSavedata"}, |
| 41 | {0x08140000, nullptr, "GetLegacyJumpProhibitedFlag"}, | 41 | {0x08140000, nullptr, "GetLegacyJumpProhibitedFlag"}, |
| 42 | {0x08180040, nullptr, "ConfigureNew3DSCPU"}, | 42 | {0x08180040, nullptr, "ConfigureNew3DSCPU"}, |
| 43 | }; | 43 | }; |
| 44 | 44 | ||
| 45 | PTM_Sysm_Interface::PTM_Sysm_Interface() { | 45 | PTM_Sysm_Interface::PTM_Sysm_Interface() { |
diff --git a/src/core/hle/service/ptm/ptm_u.cpp b/src/core/hle/service/ptm/ptm_u.cpp index 17e764866..65e868393 100644 --- a/src/core/hle/service/ptm/ptm_u.cpp +++ b/src/core/hle/service/ptm/ptm_u.cpp | |||
| @@ -9,21 +9,21 @@ namespace Service { | |||
| 9 | namespace PTM { | 9 | namespace PTM { |
| 10 | 10 | ||
| 11 | const Interface::FunctionInfo FunctionTable[] = { | 11 | const Interface::FunctionInfo FunctionTable[] = { |
| 12 | {0x00010002, nullptr, "RegisterAlarmClient"}, | 12 | {0x00010002, nullptr, "RegisterAlarmClient"}, |
| 13 | {0x00020080, nullptr, "SetRtcAlarm"}, | 13 | {0x00020080, nullptr, "SetRtcAlarm"}, |
| 14 | {0x00030000, nullptr, "GetRtcAlarm"}, | 14 | {0x00030000, nullptr, "GetRtcAlarm"}, |
| 15 | {0x00040000, nullptr, "CancelRtcAlarm"}, | 15 | {0x00040000, nullptr, "CancelRtcAlarm"}, |
| 16 | {0x00050000, GetAdapterState, "GetAdapterState"}, | 16 | {0x00050000, GetAdapterState, "GetAdapterState"}, |
| 17 | {0x00060000, GetShellState, "GetShellState"}, | 17 | {0x00060000, GetShellState, "GetShellState"}, |
| 18 | {0x00070000, GetBatteryLevel, "GetBatteryLevel"}, | 18 | {0x00070000, GetBatteryLevel, "GetBatteryLevel"}, |
| 19 | {0x00080000, GetBatteryChargeState, "GetBatteryChargeState"}, | 19 | {0x00080000, GetBatteryChargeState, "GetBatteryChargeState"}, |
| 20 | {0x00090000, nullptr, "GetPedometerState"}, | 20 | {0x00090000, nullptr, "GetPedometerState"}, |
| 21 | {0x000A0042, nullptr, "GetStepHistoryEntry"}, | 21 | {0x000A0042, nullptr, "GetStepHistoryEntry"}, |
| 22 | {0x000B00C2, nullptr, "GetStepHistory"}, | 22 | {0x000B00C2, nullptr, "GetStepHistory"}, |
| 23 | {0x000C0000, GetTotalStepCount, "GetTotalStepCount"}, | 23 | {0x000C0000, GetTotalStepCount, "GetTotalStepCount"}, |
| 24 | {0x000D0040, nullptr, "SetPedometerRecordingMode"}, | 24 | {0x000D0040, nullptr, "SetPedometerRecordingMode"}, |
| 25 | {0x000E0000, nullptr, "GetPedometerRecordingMode"}, | 25 | {0x000E0000, nullptr, "GetPedometerRecordingMode"}, |
| 26 | {0x000F0084, nullptr, "GetStepHistoryAll"}, | 26 | {0x000F0084, nullptr, "GetStepHistoryAll"}, |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | PTM_U_Interface::PTM_U_Interface() { | 29 | PTM_U_Interface::PTM_U_Interface() { |
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 5b8440b77..a531aad87 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "common/string_util.h" | 6 | #include "common/string_util.h" |
| 7 | 7 | ||
| 8 | #include "core/hle/service/service.h" | ||
| 9 | #include "core/hle/service/ac_u.h" | 8 | #include "core/hle/service/ac_u.h" |
| 10 | #include "core/hle/service/act_a.h" | 9 | #include "core/hle/service/act_a.h" |
| 11 | #include "core/hle/service/act_u.h" | 10 | #include "core/hle/service/act_u.h" |
| @@ -19,6 +18,7 @@ | |||
| 19 | #include "core/hle/service/ns_s.h" | 18 | #include "core/hle/service/ns_s.h" |
| 20 | #include "core/hle/service/nwm_uds.h" | 19 | #include "core/hle/service/nwm_uds.h" |
| 21 | #include "core/hle/service/pm_app.h" | 20 | #include "core/hle/service/pm_app.h" |
| 21 | #include "core/hle/service/service.h" | ||
| 22 | #include "core/hle/service/soc_u.h" | 22 | #include "core/hle/service/soc_u.h" |
| 23 | #include "core/hle/service/srv.h" | 23 | #include "core/hle/service/srv.h" |
| 24 | #include "core/hle/service/ssl_c.h" | 24 | #include "core/hle/service/ssl_c.h" |
| @@ -29,10 +29,10 @@ | |||
| 29 | #include "core/hle/service/boss/boss.h" | 29 | #include "core/hle/service/boss/boss.h" |
| 30 | #include "core/hle/service/cam/cam.h" | 30 | #include "core/hle/service/cam/cam.h" |
| 31 | #include "core/hle/service/cecd/cecd.h" | 31 | #include "core/hle/service/cecd/cecd.h" |
| 32 | #include "core/hle/service/cfg/cfg.h" | ||
| 32 | #include "core/hle/service/dlp/dlp.h" | 33 | #include "core/hle/service/dlp/dlp.h" |
| 33 | #include "core/hle/service/frd/frd.h" | 34 | #include "core/hle/service/frd/frd.h" |
| 34 | #include "core/hle/service/fs/archive.h" | 35 | #include "core/hle/service/fs/archive.h" |
| 35 | #include "core/hle/service/cfg/cfg.h" | ||
| 36 | #include "core/hle/service/hid/hid.h" | 36 | #include "core/hle/service/hid/hid.h" |
| 37 | #include "core/hle/service/ir/ir.h" | 37 | #include "core/hle/service/ir/ir.h" |
| 38 | #include "core/hle/service/ldr_ro/ldr_ro.h" | 38 | #include "core/hle/service/ldr_ro/ldr_ro.h" |
| @@ -50,11 +50,13 @@ std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services; | |||
| 50 | * Creates a function string for logging, complete with the name (or header code, depending | 50 | * Creates a function string for logging, complete with the name (or header code, depending |
| 51 | * on what's passed in) the port name, and all the cmd_buff arguments. | 51 | * on what's passed in) the port name, and all the cmd_buff arguments. |
| 52 | */ | 52 | */ |
| 53 | static std::string MakeFunctionString(const char* name, const char* port_name, const u32* cmd_buff) { | 53 | static std::string MakeFunctionString(const char* name, const char* port_name, |
| 54 | const u32* cmd_buff) { | ||
| 54 | // Number of params == bits 0-5 + bits 6-11 | 55 | // Number of params == bits 0-5 + bits 6-11 |
| 55 | int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F); | 56 | int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F); |
| 56 | 57 | ||
| 57 | std::string function_string = Common::StringFromFormat("function '%s': port=%s", name, port_name); | 58 | std::string function_string = |
| 59 | Common::StringFromFormat("function '%s': port=%s", name, port_name); | ||
| 58 | for (int i = 1; i <= num_params; ++i) { | 60 | for (int i = 1; i <= num_params; ++i) { |
| 59 | function_string += Common::StringFromFormat(", cmd_buff[%i]=0x%X", i, cmd_buff[i]); | 61 | function_string += Common::StringFromFormat(", cmd_buff[%i]=0x%X", i, cmd_buff[i]); |
| 60 | } | 62 | } |
| @@ -66,14 +68,19 @@ ResultVal<bool> Interface::SyncRequest() { | |||
| 66 | auto itr = m_functions.find(cmd_buff[0]); | 68 | auto itr = m_functions.find(cmd_buff[0]); |
| 67 | 69 | ||
| 68 | if (itr == m_functions.end() || itr->second.func == nullptr) { | 70 | if (itr == m_functions.end() || itr->second.func == nullptr) { |
| 69 | std::string function_name = (itr == m_functions.end()) ? Common::StringFromFormat("0x%08X", cmd_buff[0]) : itr->second.name; | 71 | std::string function_name = (itr == m_functions.end()) |
| 70 | LOG_ERROR(Service, "unknown / unimplemented %s", MakeFunctionString(function_name.c_str(), GetPortName().c_str(), cmd_buff).c_str()); | 72 | ? Common::StringFromFormat("0x%08X", cmd_buff[0]) |
| 73 | : itr->second.name; | ||
| 74 | LOG_ERROR( | ||
| 75 | Service, "unknown / unimplemented %s", | ||
| 76 | MakeFunctionString(function_name.c_str(), GetPortName().c_str(), cmd_buff).c_str()); | ||
| 71 | 77 | ||
| 72 | // TODO(bunnei): Hack - ignore error | 78 | // TODO(bunnei): Hack - ignore error |
| 73 | cmd_buff[1] = 0; | 79 | cmd_buff[1] = 0; |
| 74 | return MakeResult<bool>(false); | 80 | return MakeResult<bool>(false); |
| 75 | } | 81 | } |
| 76 | LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str()); | 82 | LOG_TRACE(Service, "%s", |
| 83 | MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str()); | ||
| 77 | 84 | ||
| 78 | itr->second.func(this); | 85 | itr->second.func(this); |
| 79 | 86 | ||
| @@ -163,6 +170,4 @@ void Shutdown() { | |||
| 163 | g_kernel_named_ports.clear(); | 170 | g_kernel_named_ports.clear(); |
| 164 | LOG_DEBUG(Service, "shutdown OK"); | 171 | LOG_DEBUG(Service, "shutdown OK"); |
| 165 | } | 172 | } |
| 166 | |||
| 167 | |||
| 168 | } | 173 | } |
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index f31135212..cd216f27e 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h | |||
| @@ -28,13 +28,15 @@ class Interface : public Kernel::Session { | |||
| 28 | // just something that encapsulates a session and acts as a helper to implement service | 28 | // just something that encapsulates a session and acts as a helper to implement service |
| 29 | // processes. | 29 | // processes. |
| 30 | public: | 30 | public: |
| 31 | std::string GetName() const override { return GetPortName(); } | 31 | std::string GetName() const override { |
| 32 | return GetPortName(); | ||
| 33 | } | ||
| 32 | 34 | ||
| 33 | typedef void (*Function)(Interface*); | 35 | typedef void (*Function)(Interface*); |
| 34 | 36 | ||
| 35 | struct FunctionInfo { | 37 | struct FunctionInfo { |
| 36 | u32 id; | 38 | u32 id; |
| 37 | Function func; | 39 | Function func; |
| 38 | const char* name; | 40 | const char* name; |
| 39 | }; | 41 | }; |
| 40 | 42 | ||
| @@ -49,7 +51,6 @@ public: | |||
| 49 | ResultVal<bool> SyncRequest() override; | 51 | ResultVal<bool> SyncRequest() override; |
| 50 | 52 | ||
| 51 | protected: | 53 | protected: |
| 52 | |||
| 53 | /** | 54 | /** |
| 54 | * Registers the functions in the service | 55 | * Registers the functions in the service |
| 55 | */ | 56 | */ |
| @@ -62,7 +63,6 @@ protected: | |||
| 62 | 63 | ||
| 63 | private: | 64 | private: |
| 64 | boost::container::flat_map<u32, FunctionInfo> m_functions; | 65 | boost::container::flat_map<u32, FunctionInfo> m_functions; |
| 65 | |||
| 66 | }; | 66 | }; |
| 67 | 67 | ||
| 68 | /// Initialize ServiceManager | 68 | /// Initialize ServiceManager |
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp index 9b285567b..695b286c0 100644 --- a/src/core/hle/service/soc_u.cpp +++ b/src/core/hle/service/soc_u.cpp | |||
| @@ -19,40 +19,40 @@ | |||
| 19 | #include "core/memory.h" | 19 | #include "core/memory.h" |
| 20 | 20 | ||
| 21 | #ifdef _WIN32 | 21 | #ifdef _WIN32 |
| 22 | #include <winsock2.h> | 22 | #include <winsock2.h> |
| 23 | #include <ws2tcpip.h> | 23 | #include <ws2tcpip.h> |
| 24 | 24 | ||
| 25 | // MinGW does not define several errno constants | 25 | // MinGW does not define several errno constants |
| 26 | #ifndef _MSC_VER | 26 | #ifndef _MSC_VER |
| 27 | #define EBADMSG 104 | 27 | #define EBADMSG 104 |
| 28 | #define ENODATA 120 | 28 | #define ENODATA 120 |
| 29 | #define ENOMSG 122 | 29 | #define ENOMSG 122 |
| 30 | #define ENOSR 124 | 30 | #define ENOSR 124 |
| 31 | #define ENOSTR 125 | 31 | #define ENOSTR 125 |
| 32 | #define ETIME 137 | 32 | #define ETIME 137 |
| 33 | #define EIDRM 2001 | 33 | #define EIDRM 2001 |
| 34 | #define ENOLINK 2002 | 34 | #define ENOLINK 2002 |
| 35 | #endif // _MSC_VER | 35 | #endif // _MSC_VER |
| 36 | #else | 36 | #else |
| 37 | #include <cerrno> | 37 | #include <cerrno> |
| 38 | #include <fcntl.h> | 38 | #include <fcntl.h> |
| 39 | #include <netinet/in.h> | 39 | #include <netdb.h> |
| 40 | #include <netdb.h> | 40 | #include <netinet/in.h> |
| 41 | #include <poll.h> | 41 | #include <poll.h> |
| 42 | #include <sys/socket.h> | 42 | #include <sys/socket.h> |
| 43 | #include <unistd.h> | 43 | #include <unistd.h> |
| 44 | #endif | 44 | #endif |
| 45 | 45 | ||
| 46 | #ifdef _WIN32 | 46 | #ifdef _WIN32 |
| 47 | # define WSAEAGAIN WSAEWOULDBLOCK | 47 | #define WSAEAGAIN WSAEWOULDBLOCK |
| 48 | # define WSAEMULTIHOP -1 // Invalid dummy value | 48 | #define WSAEMULTIHOP -1 // Invalid dummy value |
| 49 | # define ERRNO(x) WSA##x | 49 | #define ERRNO(x) WSA##x |
| 50 | # define GET_ERRNO WSAGetLastError() | 50 | #define GET_ERRNO WSAGetLastError() |
| 51 | # define poll(x, y, z) WSAPoll(x, y, z); | 51 | #define poll(x, y, z) WSAPoll(x, y, z); |
| 52 | #else | 52 | #else |
| 53 | # define ERRNO(x) x | 53 | #define ERRNO(x) x |
| 54 | # define GET_ERRNO errno | 54 | #define GET_ERRNO errno |
| 55 | # define closesocket(x) close(x) | 55 | #define closesocket(x) close(x) |
| 56 | #endif | 56 | #endif |
| 57 | 57 | ||
| 58 | static const s32 SOCKET_ERROR_VALUE = -1; | 58 | static const s32 SOCKET_ERROR_VALUE = -1; |
| @@ -63,84 +63,82 @@ static const s32 SOCKET_ERROR_VALUE = -1; | |||
| 63 | namespace SOC_U { | 63 | namespace SOC_U { |
| 64 | 64 | ||
| 65 | /// Holds the translation from system network errors to 3DS network errors | 65 | /// Holds the translation from system network errors to 3DS network errors |
| 66 | static const std::unordered_map<int, int> error_map = { { | 66 | static const std::unordered_map<int, int> error_map = {{{E2BIG, 1}, |
| 67 | { E2BIG, 1 }, | 67 | {ERRNO(EACCES), 2}, |
| 68 | { ERRNO(EACCES), 2 }, | 68 | {ERRNO(EADDRINUSE), 3}, |
| 69 | { ERRNO(EADDRINUSE), 3 }, | 69 | {ERRNO(EADDRNOTAVAIL), 4}, |
| 70 | { ERRNO(EADDRNOTAVAIL), 4 }, | 70 | {ERRNO(EAFNOSUPPORT), 5}, |
| 71 | { ERRNO(EAFNOSUPPORT), 5 }, | 71 | {ERRNO(EAGAIN), 6}, |
| 72 | { ERRNO(EAGAIN), 6 }, | 72 | {ERRNO(EALREADY), 7}, |
| 73 | { ERRNO(EALREADY), 7 }, | 73 | {ERRNO(EBADF), 8}, |
| 74 | { ERRNO(EBADF), 8 }, | 74 | {EBADMSG, 9}, |
| 75 | { EBADMSG, 9 }, | 75 | {EBUSY, 10}, |
| 76 | { EBUSY, 10 }, | 76 | {ECANCELED, 11}, |
| 77 | { ECANCELED, 11 }, | 77 | {ECHILD, 12}, |
| 78 | { ECHILD, 12 }, | 78 | {ERRNO(ECONNABORTED), 13}, |
| 79 | { ERRNO(ECONNABORTED), 13 }, | 79 | {ERRNO(ECONNREFUSED), 14}, |
| 80 | { ERRNO(ECONNREFUSED), 14 }, | 80 | {ERRNO(ECONNRESET), 15}, |
| 81 | { ERRNO(ECONNRESET), 15 }, | 81 | {EDEADLK, 16}, |
| 82 | { EDEADLK, 16 }, | 82 | {ERRNO(EDESTADDRREQ), 17}, |
| 83 | { ERRNO(EDESTADDRREQ), 17 }, | 83 | {EDOM, 18}, |
| 84 | { EDOM, 18 }, | 84 | {ERRNO(EDQUOT), 19}, |
| 85 | { ERRNO(EDQUOT), 19 }, | 85 | {EEXIST, 20}, |
| 86 | { EEXIST, 20 }, | 86 | {ERRNO(EFAULT), 21}, |
| 87 | { ERRNO(EFAULT), 21 }, | 87 | {EFBIG, 22}, |
| 88 | { EFBIG, 22 }, | 88 | {ERRNO(EHOSTUNREACH), 23}, |
| 89 | { ERRNO(EHOSTUNREACH), 23 }, | 89 | {EIDRM, 24}, |
| 90 | { EIDRM, 24 }, | 90 | {EILSEQ, 25}, |
| 91 | { EILSEQ, 25 }, | 91 | {ERRNO(EINPROGRESS), 26}, |
| 92 | { ERRNO(EINPROGRESS), 26 }, | 92 | {ERRNO(EINTR), 27}, |
| 93 | { ERRNO(EINTR), 27 }, | 93 | {ERRNO(EINVAL), 28}, |
| 94 | { ERRNO(EINVAL), 28 }, | 94 | {EIO, 29}, |
| 95 | { EIO, 29 }, | 95 | {ERRNO(EISCONN), 30}, |
| 96 | { ERRNO(EISCONN), 30 }, | 96 | {EISDIR, 31}, |
| 97 | { EISDIR, 31 }, | 97 | {ERRNO(ELOOP), 32}, |
| 98 | { ERRNO(ELOOP), 32 }, | 98 | {ERRNO(EMFILE), 33}, |
| 99 | { ERRNO(EMFILE), 33 }, | 99 | {EMLINK, 34}, |
| 100 | { EMLINK, 34 }, | 100 | {ERRNO(EMSGSIZE), 35}, |
| 101 | { ERRNO(EMSGSIZE), 35 }, | 101 | {ERRNO(EMULTIHOP), 36}, |
| 102 | { ERRNO(EMULTIHOP), 36 }, | 102 | {ERRNO(ENAMETOOLONG), 37}, |
| 103 | { ERRNO(ENAMETOOLONG), 37 }, | 103 | {ERRNO(ENETDOWN), 38}, |
| 104 | { ERRNO(ENETDOWN), 38 }, | 104 | {ERRNO(ENETRESET), 39}, |
| 105 | { ERRNO(ENETRESET), 39 }, | 105 | {ERRNO(ENETUNREACH), 40}, |
| 106 | { ERRNO(ENETUNREACH), 40 }, | 106 | {ENFILE, 41}, |
| 107 | { ENFILE, 41 }, | 107 | {ERRNO(ENOBUFS), 42}, |
| 108 | { ERRNO(ENOBUFS), 42 }, | 108 | {ENODATA, 43}, |
| 109 | { ENODATA, 43 }, | 109 | {ENODEV, 44}, |
| 110 | { ENODEV, 44 }, | 110 | {ENOENT, 45}, |
| 111 | { ENOENT, 45 }, | 111 | {ENOEXEC, 46}, |
| 112 | { ENOEXEC, 46 }, | 112 | {ENOLCK, 47}, |
| 113 | { ENOLCK, 47 }, | 113 | {ENOLINK, 48}, |
| 114 | { ENOLINK, 48 }, | 114 | {ENOMEM, 49}, |
| 115 | { ENOMEM, 49 }, | 115 | {ENOMSG, 50}, |
| 116 | { ENOMSG, 50 }, | 116 | {ERRNO(ENOPROTOOPT), 51}, |
| 117 | { ERRNO(ENOPROTOOPT), 51 }, | 117 | {ENOSPC, 52}, |
| 118 | { ENOSPC, 52 }, | 118 | {ENOSR, 53}, |
| 119 | { ENOSR, 53 }, | 119 | {ENOSTR, 54}, |
| 120 | { ENOSTR, 54 }, | 120 | {ENOSYS, 55}, |
| 121 | { ENOSYS, 55 }, | 121 | {ERRNO(ENOTCONN), 56}, |
| 122 | { ERRNO(ENOTCONN), 56 }, | 122 | {ENOTDIR, 57}, |
| 123 | { ENOTDIR, 57 }, | 123 | {ERRNO(ENOTEMPTY), 58}, |
| 124 | { ERRNO(ENOTEMPTY), 58 }, | 124 | {ERRNO(ENOTSOCK), 59}, |
| 125 | { ERRNO(ENOTSOCK), 59 }, | 125 | {ENOTSUP, 60}, |
| 126 | { ENOTSUP, 60 }, | 126 | {ENOTTY, 61}, |
| 127 | { ENOTTY, 61 }, | 127 | {ENXIO, 62}, |
| 128 | { ENXIO, 62 }, | 128 | {ERRNO(EOPNOTSUPP), 63}, |
| 129 | { ERRNO(EOPNOTSUPP), 63 }, | 129 | {EOVERFLOW, 64}, |
| 130 | { EOVERFLOW, 64 }, | 130 | {EPERM, 65}, |
| 131 | { EPERM, 65 }, | 131 | {EPIPE, 66}, |
| 132 | { EPIPE, 66 }, | 132 | {EPROTO, 67}, |
| 133 | { EPROTO, 67 }, | 133 | {ERRNO(EPROTONOSUPPORT), 68}, |
| 134 | { ERRNO(EPROTONOSUPPORT), 68 }, | 134 | {ERRNO(EPROTOTYPE), 69}, |
| 135 | { ERRNO(EPROTOTYPE), 69 }, | 135 | {ERANGE, 70}, |
| 136 | { ERANGE, 70 }, | 136 | {EROFS, 71}, |
| 137 | { EROFS, 71 }, | 137 | {ESPIPE, 72}, |
| 138 | { ESPIPE, 72 }, | 138 | {ESRCH, 73}, |
| 139 | { ESRCH, 73 }, | 139 | {ERRNO(ESTALE), 74}, |
| 140 | { ERRNO(ESTALE), 74 }, | 140 | {ETIME, 75}, |
| 141 | { ETIME, 75 }, | 141 | {ERRNO(ETIMEDOUT), 76}}}; |
| 142 | { ERRNO(ETIMEDOUT), 76 } | ||
| 143 | }}; | ||
| 144 | 142 | ||
| 145 | /// Converts a network error from platform-specific to 3ds-specific | 143 | /// Converts a network error from platform-specific to 3ds-specific |
| 146 | static int TranslateError(int error) { | 144 | static int TranslateError(int error) { |
| @@ -153,21 +151,21 @@ static int TranslateError(int error) { | |||
| 153 | 151 | ||
| 154 | /// Holds the translation from system network socket options to 3DS network socket options | 152 | /// Holds the translation from system network socket options to 3DS network socket options |
| 155 | /// Note: -1 = No effect/unavailable | 153 | /// Note: -1 = No effect/unavailable |
| 156 | static const std::unordered_map<int, int> sockopt_map = { { | 154 | static const std::unordered_map<int, int> sockopt_map = {{ |
| 157 | { 0x0004, SO_REUSEADDR }, | 155 | {0x0004, SO_REUSEADDR}, |
| 158 | { 0x0080, -1 }, | 156 | {0x0080, -1}, |
| 159 | { 0x0100, -1 }, | 157 | {0x0100, -1}, |
| 160 | { 0x1001, SO_SNDBUF }, | 158 | {0x1001, SO_SNDBUF}, |
| 161 | { 0x1002, SO_RCVBUF }, | 159 | {0x1002, SO_RCVBUF}, |
| 162 | { 0x1003, -1 }, | 160 | {0x1003, -1}, |
| 163 | #ifdef _WIN32 | 161 | #ifdef _WIN32 |
| 164 | /// Unsupported in WinSock2 | 162 | /// Unsupported in WinSock2 |
| 165 | { 0x1004, -1 }, | 163 | {0x1004, -1}, |
| 166 | #else | 164 | #else |
| 167 | { 0x1004, SO_RCVLOWAT }, | 165 | {0x1004, SO_RCVLOWAT}, |
| 168 | #endif | 166 | #endif |
| 169 | { 0x1008, SO_TYPE }, | 167 | {0x1008, SO_TYPE}, |
| 170 | { 0x1009, SO_ERROR }, | 168 | {0x1009, SO_ERROR}, |
| 171 | }}; | 169 | }}; |
| 172 | 170 | ||
| 173 | /// Converts a socket option from 3ds-specific to platform-specific | 171 | /// Converts a socket option from 3ds-specific to platform-specific |
| @@ -203,7 +201,8 @@ struct CTRPollFD { | |||
| 203 | return *this; | 201 | return *this; |
| 204 | } | 202 | } |
| 205 | 203 | ||
| 206 | /// Translates the resulting events of a Poll operation from platform-specific to 3ds specific | 204 | /// Translates the resulting events of a Poll operation from platform-specific to 3ds |
| 205 | /// specific | ||
| 207 | static Events TranslateTo3DS(u32 input_event) { | 206 | static Events TranslateTo3DS(u32 input_event) { |
| 208 | Events ev = {}; | 207 | Events ev = {}; |
| 209 | if (input_event & POLLIN) | 208 | if (input_event & POLLIN) |
| @@ -221,7 +220,8 @@ struct CTRPollFD { | |||
| 221 | return ev; | 220 | return ev; |
| 222 | } | 221 | } |
| 223 | 222 | ||
| 224 | /// Translates the resulting events of a Poll operation from 3ds specific to platform specific | 223 | /// Translates the resulting events of a Poll operation from 3ds specific to platform |
| 224 | /// specific | ||
| 225 | static u32 TranslateToPlatform(Events input_event) { | 225 | static u32 TranslateToPlatform(Events input_event) { |
| 226 | u32 ret = 0; | 226 | u32 ret = 0; |
| 227 | if (input_event.pollin) | 227 | if (input_event.pollin) |
| @@ -239,7 +239,7 @@ struct CTRPollFD { | |||
| 239 | return ret; | 239 | return ret; |
| 240 | } | 240 | } |
| 241 | }; | 241 | }; |
| 242 | Events events; ///< Events to poll for (input) | 242 | Events events; ///< Events to poll for (input) |
| 243 | Events revents; ///< Events received (output) | 243 | Events revents; ///< Events received (output) |
| 244 | 244 | ||
| 245 | /// Converts a platform-specific pollfd to a 3ds specific structure | 245 | /// Converts a platform-specific pollfd to a 3ds specific structure |
| @@ -265,17 +265,17 @@ struct CTRPollFD { | |||
| 265 | union CTRSockAddr { | 265 | union CTRSockAddr { |
| 266 | /// Structure to represent a raw sockaddr | 266 | /// Structure to represent a raw sockaddr |
| 267 | struct { | 267 | struct { |
| 268 | u8 len; ///< The length of the entire structure, only the set fields count | 268 | u8 len; ///< The length of the entire structure, only the set fields count |
| 269 | u8 sa_family; ///< The address family of the sockaddr | 269 | u8 sa_family; ///< The address family of the sockaddr |
| 270 | u8 sa_data[0x1A]; ///< The extra data, this varies, depending on the address family | 270 | u8 sa_data[0x1A]; ///< The extra data, this varies, depending on the address family |
| 271 | } raw; | 271 | } raw; |
| 272 | 272 | ||
| 273 | /// Structure to represent the 3ds' sockaddr_in structure | 273 | /// Structure to represent the 3ds' sockaddr_in structure |
| 274 | struct CTRSockAddrIn { | 274 | struct CTRSockAddrIn { |
| 275 | u8 len; ///< The length of the entire structure | 275 | u8 len; ///< The length of the entire structure |
| 276 | u8 sin_family; ///< The address family of the sockaddr_in | 276 | u8 sin_family; ///< The address family of the sockaddr_in |
| 277 | u16 sin_port; ///< The port associated with this sockaddr_in | 277 | u16 sin_port; ///< The port associated with this sockaddr_in |
| 278 | u32 sin_addr; ///< The actual address of the sockaddr_in | 278 | u32 sin_addr; ///< The actual address of the sockaddr_in |
| 279 | } in; | 279 | } in; |
| 280 | 280 | ||
| 281 | /// Convert a 3DS CTRSockAddr to a platform-specific sockaddr | 281 | /// Convert a 3DS CTRSockAddr to a platform-specific sockaddr |
| @@ -286,8 +286,7 @@ union CTRSockAddr { | |||
| 286 | 286 | ||
| 287 | // We can not guarantee ABI compatibility between platforms so we copy the fields manually | 287 | // We can not guarantee ABI compatibility between platforms so we copy the fields manually |
| 288 | switch (result.sa_family) { | 288 | switch (result.sa_family) { |
| 289 | case AF_INET: | 289 | case AF_INET: { |
| 290 | { | ||
| 291 | sockaddr_in* result_in = reinterpret_cast<sockaddr_in*>(&result); | 290 | sockaddr_in* result_in = reinterpret_cast<sockaddr_in*>(&result); |
| 292 | result_in->sin_port = ctr_addr.in.sin_port; | 291 | result_in->sin_port = ctr_addr.in.sin_port; |
| 293 | result_in->sin_addr.s_addr = ctr_addr.in.sin_addr; | 292 | result_in->sin_addr.s_addr = ctr_addr.in.sin_addr; |
| @@ -307,8 +306,7 @@ union CTRSockAddr { | |||
| 307 | result.raw.sa_family = static_cast<u8>(addr.sa_family); | 306 | result.raw.sa_family = static_cast<u8>(addr.sa_family); |
| 308 | // We can not guarantee ABI compatibility between platforms so we copy the fields manually | 307 | // We can not guarantee ABI compatibility between platforms so we copy the fields manually |
| 309 | switch (result.raw.sa_family) { | 308 | switch (result.raw.sa_family) { |
| 310 | case AF_INET: | 309 | case AF_INET: { |
| 311 | { | ||
| 312 | sockaddr_in const* addr_in = reinterpret_cast<sockaddr_in const*>(&addr); | 310 | sockaddr_in const* addr_in = reinterpret_cast<sockaddr_in const*>(&addr); |
| 313 | result.raw.len = sizeof(CTRSockAddrIn); | 311 | result.raw.len = sizeof(CTRSockAddrIn); |
| 314 | result.in.sin_port = addr_in->sin_port; | 312 | result.in.sin_port = addr_in->sin_port; |
| @@ -341,24 +339,27 @@ static void Socket(Service::Interface* self) { | |||
| 341 | 339 | ||
| 342 | // Only 0 is allowed according to 3dbrew, using 0 will let the OS decide which protocol to use | 340 | // Only 0 is allowed according to 3dbrew, using 0 will let the OS decide which protocol to use |
| 343 | if (protocol != 0) { | 341 | if (protocol != 0) { |
| 344 | cmd_buffer[1] = UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code | 342 | cmd_buffer[1] = |
| 343 | UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code | ||
| 345 | return; | 344 | return; |
| 346 | } | 345 | } |
| 347 | 346 | ||
| 348 | if (domain != AF_INET) { | 347 | if (domain != AF_INET) { |
| 349 | cmd_buffer[1] = UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code | 348 | cmd_buffer[1] = |
| 349 | UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code | ||
| 350 | return; | 350 | return; |
| 351 | } | 351 | } |
| 352 | 352 | ||
| 353 | if (type != SOCK_DGRAM && type != SOCK_STREAM) { | 353 | if (type != SOCK_DGRAM && type != SOCK_STREAM) { |
| 354 | cmd_buffer[1] = UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code | 354 | cmd_buffer[1] = |
| 355 | UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code | ||
| 355 | return; | 356 | return; |
| 356 | } | 357 | } |
| 357 | 358 | ||
| 358 | u32 socket_handle = static_cast<u32>(::socket(domain, type, protocol)); | 359 | u32 socket_handle = static_cast<u32>(::socket(domain, type, protocol)); |
| 359 | 360 | ||
| 360 | if ((s32)socket_handle != SOCKET_ERROR_VALUE) | 361 | if ((s32)socket_handle != SOCKET_ERROR_VALUE) |
| 361 | open_sockets[socket_handle] = { socket_handle, true }; | 362 | open_sockets[socket_handle] = {socket_handle, true}; |
| 362 | 363 | ||
| 363 | int result = 0; | 364 | int result = 0; |
| 364 | if ((s32)socket_handle == SOCKET_ERROR_VALUE) | 365 | if ((s32)socket_handle == SOCKET_ERROR_VALUE) |
| @@ -406,8 +407,8 @@ static void Fcntl(Service::Interface* self) { | |||
| 406 | int result = 0; | 407 | int result = 0; |
| 407 | u32 posix_ret = 0; // TODO: Check what hardware returns for F_SETFL (unspecified by POSIX) | 408 | u32 posix_ret = 0; // TODO: Check what hardware returns for F_SETFL (unspecified by POSIX) |
| 408 | SCOPE_EXIT({ | 409 | SCOPE_EXIT({ |
| 409 | cmd_buffer[1] = result; | 410 | cmd_buffer[1] = result; |
| 410 | cmd_buffer[2] = posix_ret; | 411 | cmd_buffer[2] = posix_ret; |
| 411 | }); | 412 | }); |
| 412 | 413 | ||
| 413 | if (ctr_cmd == 3) { // F_GETFL | 414 | if (ctr_cmd == 3) { // F_GETFL |
| @@ -493,7 +494,7 @@ static void Accept(Service::Interface* self) { | |||
| 493 | u32 ret = static_cast<u32>(::accept(socket_handle, &addr, &addr_len)); | 494 | u32 ret = static_cast<u32>(::accept(socket_handle, &addr, &addr_len)); |
| 494 | 495 | ||
| 495 | if ((s32)ret != SOCKET_ERROR_VALUE) | 496 | if ((s32)ret != SOCKET_ERROR_VALUE) |
| 496 | open_sockets[ret] = { ret, true }; | 497 | open_sockets[ret] = {ret, true}; |
| 497 | 498 | ||
| 498 | int result = 0; | 499 | int result = 0; |
| 499 | if ((s32)ret == SOCKET_ERROR_VALUE) { | 500 | if ((s32)ret == SOCKET_ERROR_VALUE) { |
| @@ -573,9 +574,11 @@ static void SendTo(Service::Interface* self) { | |||
| 573 | int ret = -1; | 574 | int ret = -1; |
| 574 | if (addr_len > 0) { | 575 | if (addr_len > 0) { |
| 575 | sockaddr dest_addr = CTRSockAddr::ToPlatform(ctr_dest_addr); | 576 | sockaddr dest_addr = CTRSockAddr::ToPlatform(ctr_dest_addr); |
| 576 | ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags, &dest_addr, sizeof(dest_addr)); | 577 | ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags, |
| 578 | &dest_addr, sizeof(dest_addr)); | ||
| 577 | } else { | 579 | } else { |
| 578 | ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags, nullptr, 0); | 580 | ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags, |
| 581 | nullptr, 0); | ||
| 579 | } | 582 | } |
| 580 | 583 | ||
| 581 | int result = 0; | 584 | int result = 0; |
| @@ -596,8 +599,7 @@ static void RecvFrom(Service::Interface* self) { | |||
| 596 | u32 flags = cmd_buffer[3]; | 599 | u32 flags = cmd_buffer[3]; |
| 597 | socklen_t addr_len = static_cast<socklen_t>(cmd_buffer[4]); | 600 | socklen_t addr_len = static_cast<socklen_t>(cmd_buffer[4]); |
| 598 | 601 | ||
| 599 | struct | 602 | struct { |
| 600 | { | ||
| 601 | u32 output_buffer_descriptor; | 603 | u32 output_buffer_descriptor; |
| 602 | u32 output_buffer_addr; | 604 | u32 output_buffer_addr; |
| 603 | u32 address_buffer_descriptor; | 605 | u32 address_buffer_descriptor; |
| @@ -619,11 +621,13 @@ static void RecvFrom(Service::Interface* self) { | |||
| 619 | std::vector<u8> output_buff(len); | 621 | std::vector<u8> output_buff(len); |
| 620 | sockaddr src_addr; | 622 | sockaddr src_addr; |
| 621 | socklen_t src_addr_len = sizeof(src_addr); | 623 | socklen_t src_addr_len = sizeof(src_addr); |
| 622 | int ret = ::recvfrom(socket_handle, reinterpret_cast<char*>(output_buff.data()), len, flags, &src_addr, &src_addr_len); | 624 | int ret = ::recvfrom(socket_handle, reinterpret_cast<char*>(output_buff.data()), len, flags, |
| 625 | &src_addr, &src_addr_len); | ||
| 623 | 626 | ||
| 624 | if (ret >= 0 && buffer_parameters.output_src_address_buffer != 0 && src_addr_len > 0) { | 627 | if (ret >= 0 && buffer_parameters.output_src_address_buffer != 0 && src_addr_len > 0) { |
| 625 | CTRSockAddr ctr_src_addr = CTRSockAddr::FromPlatform(src_addr); | 628 | CTRSockAddr ctr_src_addr = CTRSockAddr::FromPlatform(src_addr); |
| 626 | Memory::WriteBlock(buffer_parameters.output_src_address_buffer, &ctr_src_addr, sizeof(ctr_src_addr)); | 629 | Memory::WriteBlock(buffer_parameters.output_src_address_buffer, &ctr_src_addr, |
| 630 | sizeof(ctr_src_addr)); | ||
| 627 | } | 631 | } |
| 628 | 632 | ||
| 629 | int result = 0; | 633 | int result = 0; |
| @@ -633,7 +637,8 @@ static void RecvFrom(Service::Interface* self) { | |||
| 633 | total_received = 0; | 637 | total_received = 0; |
| 634 | } else { | 638 | } else { |
| 635 | // Write only the data we received to avoid overwriting parts of the buffer with zeros | 639 | // Write only the data we received to avoid overwriting parts of the buffer with zeros |
| 636 | Memory::WriteBlock(buffer_parameters.output_buffer_addr, output_buff.data(), total_received); | 640 | Memory::WriteBlock(buffer_parameters.output_buffer_addr, output_buff.data(), |
| 641 | total_received); | ||
| 637 | } | 642 | } |
| 638 | 643 | ||
| 639 | cmd_buffer[1] = result; | 644 | cmd_buffer[1] = result; |
| @@ -648,7 +653,8 @@ static void Poll(Service::Interface* self) { | |||
| 648 | 653 | ||
| 649 | VAddr input_fds_addr = cmd_buffer[6]; | 654 | VAddr input_fds_addr = cmd_buffer[6]; |
| 650 | VAddr output_fds_addr = cmd_buffer[0x104 >> 2]; | 655 | VAddr output_fds_addr = cmd_buffer[0x104 >> 2]; |
| 651 | if (!Memory::IsValidVirtualAddress(input_fds_addr) || !Memory::IsValidVirtualAddress(output_fds_addr)) { | 656 | if (!Memory::IsValidVirtualAddress(input_fds_addr) || |
| 657 | !Memory::IsValidVirtualAddress(output_fds_addr)) { | ||
| 652 | cmd_buffer[1] = -1; // TODO(Subv): Find correct error code. | 658 | cmd_buffer[1] = -1; // TODO(Subv): Find correct error code. |
| 653 | return; | 659 | return; |
| 654 | } | 660 | } |
| @@ -656,7 +662,8 @@ static void Poll(Service::Interface* self) { | |||
| 656 | std::vector<CTRPollFD> ctr_fds(nfds); | 662 | std::vector<CTRPollFD> ctr_fds(nfds); |
| 657 | Memory::ReadBlock(input_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD)); | 663 | Memory::ReadBlock(input_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD)); |
| 658 | 664 | ||
| 659 | // The 3ds_pollfd and the pollfd structures may be different (Windows/Linux have different sizes) | 665 | // The 3ds_pollfd and the pollfd structures may be different (Windows/Linux have different |
| 666 | // sizes) | ||
| 660 | // so we have to copy the data | 667 | // so we have to copy the data |
| 661 | std::vector<pollfd> platform_pollfd(nfds); | 668 | std::vector<pollfd> platform_pollfd(nfds); |
| 662 | std::transform(ctr_fds.begin(), ctr_fds.end(), platform_pollfd.begin(), CTRPollFD::ToPlatform); | 669 | std::transform(ctr_fds.begin(), ctr_fds.end(), platform_pollfd.begin(), CTRPollFD::ToPlatform); |
| @@ -664,7 +671,8 @@ static void Poll(Service::Interface* self) { | |||
| 664 | const int ret = ::poll(platform_pollfd.data(), nfds, timeout); | 671 | const int ret = ::poll(platform_pollfd.data(), nfds, timeout); |
| 665 | 672 | ||
| 666 | // Now update the output pollfd structure | 673 | // Now update the output pollfd structure |
| 667 | std::transform(platform_pollfd.begin(), platform_pollfd.end(), ctr_fds.begin(), CTRPollFD::FromPlatform); | 674 | std::transform(platform_pollfd.begin(), platform_pollfd.end(), ctr_fds.begin(), |
| 675 | CTRPollFD::FromPlatform); | ||
| 668 | 676 | ||
| 669 | Memory::WriteBlock(output_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD)); | 677 | Memory::WriteBlock(output_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD)); |
| 670 | 678 | ||
| @@ -775,7 +783,7 @@ static void Connect(Service::Interface* self) { | |||
| 775 | } | 783 | } |
| 776 | 784 | ||
| 777 | static void InitializeSockets(Service::Interface* self) { | 785 | static void InitializeSockets(Service::Interface* self) { |
| 778 | // TODO(Subv): Implement | 786 | // TODO(Subv): Implement |
| 779 | #ifdef _WIN32 | 787 | #ifdef _WIN32 |
| 780 | WSADATA data; | 788 | WSADATA data; |
| 781 | WSAStartup(MAKEWORD(2, 2), &data); | 789 | WSAStartup(MAKEWORD(2, 2), &data); |
| @@ -808,7 +816,7 @@ static void GetSockOpt(Service::Interface* self) { | |||
| 808 | int ret = -1; | 816 | int ret = -1; |
| 809 | int err = 0; | 817 | int err = 0; |
| 810 | 818 | ||
| 811 | if(optname < 0) { | 819 | if (optname < 0) { |
| 812 | #ifdef _WIN32 | 820 | #ifdef _WIN32 |
| 813 | err = WSAEINVAL; | 821 | err = WSAEINVAL; |
| 814 | #else | 822 | #else |
| @@ -818,7 +826,7 @@ static void GetSockOpt(Service::Interface* self) { | |||
| 818 | // 0x100 = static buffer offset (bytes) | 826 | // 0x100 = static buffer offset (bytes) |
| 819 | // + 0x4 = 2nd pointer (u32) position | 827 | // + 0x4 = 2nd pointer (u32) position |
| 820 | // >> 2 = convert to u32 offset instead of byte offset (cmd_buffer = u32*) | 828 | // >> 2 = convert to u32 offset instead of byte offset (cmd_buffer = u32*) |
| 821 | char* optval = reinterpret_cast<char *>(Memory::GetPointer(cmd_buffer[0x104 >> 2])); | 829 | char* optval = reinterpret_cast<char*>(Memory::GetPointer(cmd_buffer[0x104 >> 2])); |
| 822 | 830 | ||
| 823 | ret = ::getsockopt(socket_handle, level, optname, optval, &optlen); | 831 | ret = ::getsockopt(socket_handle, level, optname, optval, &optlen); |
| 824 | err = 0; | 832 | err = 0; |
| @@ -842,7 +850,7 @@ static void SetSockOpt(Service::Interface* self) { | |||
| 842 | int ret = -1; | 850 | int ret = -1; |
| 843 | int err = 0; | 851 | int err = 0; |
| 844 | 852 | ||
| 845 | if(optname < 0) { | 853 | if (optname < 0) { |
| 846 | #ifdef _WIN32 | 854 | #ifdef _WIN32 |
| 847 | err = WSAEINVAL; | 855 | err = WSAEINVAL; |
| 848 | #else | 856 | #else |
| @@ -850,7 +858,7 @@ static void SetSockOpt(Service::Interface* self) { | |||
| 850 | #endif | 858 | #endif |
| 851 | } else { | 859 | } else { |
| 852 | socklen_t optlen = static_cast<socklen_t>(cmd_buffer[4]); | 860 | socklen_t optlen = static_cast<socklen_t>(cmd_buffer[4]); |
| 853 | const char* optval = reinterpret_cast<const char *>(Memory::GetPointer(cmd_buffer[8])); | 861 | const char* optval = reinterpret_cast<const char*>(Memory::GetPointer(cmd_buffer[8])); |
| 854 | 862 | ||
| 855 | ret = static_cast<u32>(::setsockopt(socket_handle, level, optname, optval, optlen)); | 863 | ret = static_cast<u32>(::setsockopt(socket_handle, level, optname, optval, optlen)); |
| 856 | err = 0; | 864 | err = 0; |
| @@ -865,39 +873,39 @@ static void SetSockOpt(Service::Interface* self) { | |||
| 865 | } | 873 | } |
| 866 | 874 | ||
| 867 | const Interface::FunctionInfo FunctionTable[] = { | 875 | const Interface::FunctionInfo FunctionTable[] = { |
| 868 | {0x00010044, InitializeSockets, "InitializeSockets"}, | 876 | {0x00010044, InitializeSockets, "InitializeSockets"}, |
| 869 | {0x000200C2, Socket, "Socket"}, | 877 | {0x000200C2, Socket, "Socket"}, |
| 870 | {0x00030082, Listen, "Listen"}, | 878 | {0x00030082, Listen, "Listen"}, |
| 871 | {0x00040082, Accept, "Accept"}, | 879 | {0x00040082, Accept, "Accept"}, |
| 872 | {0x00050084, Bind, "Bind"}, | 880 | {0x00050084, Bind, "Bind"}, |
| 873 | {0x00060084, Connect, "Connect"}, | 881 | {0x00060084, Connect, "Connect"}, |
| 874 | {0x00070104, nullptr, "recvfrom_other"}, | 882 | {0x00070104, nullptr, "recvfrom_other"}, |
| 875 | {0x00080102, RecvFrom, "RecvFrom"}, | 883 | {0x00080102, RecvFrom, "RecvFrom"}, |
| 876 | {0x00090106, nullptr, "sendto_other"}, | 884 | {0x00090106, nullptr, "sendto_other"}, |
| 877 | {0x000A0106, SendTo, "SendTo"}, | 885 | {0x000A0106, SendTo, "SendTo"}, |
| 878 | {0x000B0042, Close, "Close"}, | 886 | {0x000B0042, Close, "Close"}, |
| 879 | {0x000C0082, Shutdown, "Shutdown"}, | 887 | {0x000C0082, Shutdown, "Shutdown"}, |
| 880 | {0x000D0082, nullptr, "GetHostByName"}, | 888 | {0x000D0082, nullptr, "GetHostByName"}, |
| 881 | {0x000E00C2, nullptr, "GetHostByAddr"}, | 889 | {0x000E00C2, nullptr, "GetHostByAddr"}, |
| 882 | {0x000F0106, nullptr, "GetAddrInfo"}, | 890 | {0x000F0106, nullptr, "GetAddrInfo"}, |
| 883 | {0x00100102, nullptr, "GetNameInfo"}, | 891 | {0x00100102, nullptr, "GetNameInfo"}, |
| 884 | {0x00110102, GetSockOpt, "GetSockOpt"}, | 892 | {0x00110102, GetSockOpt, "GetSockOpt"}, |
| 885 | {0x00120104, SetSockOpt, "SetSockOpt"}, | 893 | {0x00120104, SetSockOpt, "SetSockOpt"}, |
| 886 | {0x001300C2, Fcntl, "Fcntl"}, | 894 | {0x001300C2, Fcntl, "Fcntl"}, |
| 887 | {0x00140084, Poll, "Poll"}, | 895 | {0x00140084, Poll, "Poll"}, |
| 888 | {0x00150042, nullptr, "SockAtMark"}, | 896 | {0x00150042, nullptr, "SockAtMark"}, |
| 889 | {0x00160000, GetHostId, "GetHostId"}, | 897 | {0x00160000, GetHostId, "GetHostId"}, |
| 890 | {0x00170082, GetSockName, "GetSockName"}, | 898 | {0x00170082, GetSockName, "GetSockName"}, |
| 891 | {0x00180082, GetPeerName, "GetPeerName"}, | 899 | {0x00180082, GetPeerName, "GetPeerName"}, |
| 892 | {0x00190000, ShutdownSockets, "ShutdownSockets"}, | 900 | {0x00190000, ShutdownSockets, "ShutdownSockets"}, |
| 893 | {0x001A00C0, nullptr, "GetNetworkOpt"}, | 901 | {0x001A00C0, nullptr, "GetNetworkOpt"}, |
| 894 | {0x001B0040, nullptr, "ICMPSocket"}, | 902 | {0x001B0040, nullptr, "ICMPSocket"}, |
| 895 | {0x001C0104, nullptr, "ICMPPing"}, | 903 | {0x001C0104, nullptr, "ICMPPing"}, |
| 896 | {0x001D0040, nullptr, "ICMPCancel"}, | 904 | {0x001D0040, nullptr, "ICMPCancel"}, |
| 897 | {0x001E0040, nullptr, "ICMPClose"}, | 905 | {0x001E0040, nullptr, "ICMPClose"}, |
| 898 | {0x001F0040, nullptr, "GetResolverInfo"}, | 906 | {0x001F0040, nullptr, "GetResolverInfo"}, |
| 899 | {0x00210002, nullptr, "CloseSockets"}, | 907 | {0x00210002, nullptr, "CloseSockets"}, |
| 900 | {0x00230040, nullptr, "AddGlobalSocket"}, | 908 | {0x00230040, nullptr, "AddGlobalSocket"}, |
| 901 | }; | 909 | }; |
| 902 | 910 | ||
| 903 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 911 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index 3c05f836b..fda9d8acf 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp | |||
| @@ -5,8 +5,8 @@ | |||
| 5 | #include "common/common_types.h" | 5 | #include "common/common_types.h" |
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | 7 | ||
| 8 | #include "core/hle/service/srv.h" | ||
| 9 | #include "core/hle/kernel/event.h" | 8 | #include "core/hle/kernel/event.h" |
| 9 | #include "core/hle/service/srv.h" | ||
| 10 | 10 | ||
| 11 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 11 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 12 | // Namespace SRV | 12 | // Namespace SRV |
| @@ -28,13 +28,14 @@ static void RegisterClient(Service::Interface* self) { | |||
| 28 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 28 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 29 | 29 | ||
| 30 | if (cmd_buff[1] != IPC::CallingPidDesc()) { | 30 | if (cmd_buff[1] != IPC::CallingPidDesc()) { |
| 31 | cmd_buff[0] = IPC::MakeHeader(0x0, 0x1, 0); //0x40 | 31 | cmd_buff[0] = IPC::MakeHeader(0x0, 0x1, 0); // 0x40 |
| 32 | cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, | 32 | cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, |
| 33 | ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; | 33 | ErrorSummary::WrongArgument, ErrorLevel::Permanent) |
| 34 | .raw; | ||
| 34 | return; | 35 | return; |
| 35 | } | 36 | } |
| 36 | cmd_buff[0] = IPC::MakeHeader(0x1, 0x1, 0); //0x10040 | 37 | cmd_buff[0] = IPC::MakeHeader(0x1, 0x1, 0); // 0x10040 |
| 37 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 38 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 38 | LOG_WARNING(Service_SRV, "(STUBBED) called"); | 39 | LOG_WARNING(Service_SRV, "(STUBBED) called"); |
| 39 | } | 40 | } |
| 40 | 41 | ||
| @@ -56,7 +57,7 @@ static void EnableNotification(Service::Interface* self) { | |||
| 56 | event_handle->Clear(); | 57 | event_handle->Clear(); |
| 57 | 58 | ||
| 58 | cmd_buff[0] = IPC::MakeHeader(0x2, 0x1, 0x2); // 0x20042 | 59 | cmd_buff[0] = IPC::MakeHeader(0x2, 0x1, 0x2); // 0x20042 |
| 59 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 60 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 60 | cmd_buff[2] = IPC::CopyHandleDesc(1); | 61 | cmd_buff[2] = IPC::CopyHandleDesc(1); |
| 61 | cmd_buff[3] = Kernel::g_handle_table.Create(event_handle).MoveFrom(); | 62 | cmd_buff[3] = Kernel::g_handle_table.Create(event_handle).MoveFrom(); |
| 62 | LOG_WARNING(Service_SRV, "(STUBBED) called"); | 63 | LOG_WARNING(Service_SRV, "(STUBBED) called"); |
| @@ -105,7 +106,7 @@ static void Subscribe(Service::Interface* self) { | |||
| 105 | u32 notification_id = cmd_buff[1]; | 106 | u32 notification_id = cmd_buff[1]; |
| 106 | 107 | ||
| 107 | cmd_buff[0] = IPC::MakeHeader(0x9, 0x1, 0); // 0x90040 | 108 | cmd_buff[0] = IPC::MakeHeader(0x9, 0x1, 0); // 0x90040 |
| 108 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 109 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 109 | LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id); | 110 | LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id); |
| 110 | } | 111 | } |
| 111 | 112 | ||
| @@ -124,7 +125,7 @@ static void Unsubscribe(Service::Interface* self) { | |||
| 124 | u32 notification_id = cmd_buff[1]; | 125 | u32 notification_id = cmd_buff[1]; |
| 125 | 126 | ||
| 126 | cmd_buff[0] = IPC::MakeHeader(0xA, 0x1, 0); // 0xA0040 | 127 | cmd_buff[0] = IPC::MakeHeader(0xA, 0x1, 0); // 0xA0040 |
| 127 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 128 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 128 | LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id); | 129 | LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id); |
| 129 | } | 130 | } |
| 130 | 131 | ||
| @@ -145,25 +146,26 @@ static void PublishToSubscriber(Service::Interface* self) { | |||
| 145 | u8 flags = cmd_buff[2] & 0xFF; | 146 | u8 flags = cmd_buff[2] & 0xFF; |
| 146 | 147 | ||
| 147 | cmd_buff[0] = IPC::MakeHeader(0xC, 0x1, 0); // 0xC0040 | 148 | cmd_buff[0] = IPC::MakeHeader(0xC, 0x1, 0); // 0xC0040 |
| 148 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 149 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 149 | LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X, flags=%u", notification_id, flags); | 150 | LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X, flags=%u", notification_id, |
| 151 | flags); | ||
| 150 | } | 152 | } |
| 151 | 153 | ||
| 152 | const Interface::FunctionInfo FunctionTable[] = { | 154 | const Interface::FunctionInfo FunctionTable[] = { |
| 153 | {0x00010002, RegisterClient, "RegisterClient"}, | 155 | {0x00010002, RegisterClient, "RegisterClient"}, |
| 154 | {0x00020000, EnableNotification, "EnableNotification"}, | 156 | {0x00020000, EnableNotification, "EnableNotification"}, |
| 155 | {0x00030100, nullptr, "RegisterService"}, | 157 | {0x00030100, nullptr, "RegisterService"}, |
| 156 | {0x000400C0, nullptr, "UnregisterService"}, | 158 | {0x000400C0, nullptr, "UnregisterService"}, |
| 157 | {0x00050100, GetServiceHandle, "GetServiceHandle"}, | 159 | {0x00050100, GetServiceHandle, "GetServiceHandle"}, |
| 158 | {0x000600C2, nullptr, "RegisterPort"}, | 160 | {0x000600C2, nullptr, "RegisterPort"}, |
| 159 | {0x000700C0, nullptr, "UnregisterPort"}, | 161 | {0x000700C0, nullptr, "UnregisterPort"}, |
| 160 | {0x00080100, nullptr, "GetPort"}, | 162 | {0x00080100, nullptr, "GetPort"}, |
| 161 | {0x00090040, Subscribe, "Subscribe"}, | 163 | {0x00090040, Subscribe, "Subscribe"}, |
| 162 | {0x000A0040, Unsubscribe, "Unsubscribe"}, | 164 | {0x000A0040, Unsubscribe, "Unsubscribe"}, |
| 163 | {0x000B0000, nullptr, "ReceiveNotification"}, | 165 | {0x000B0000, nullptr, "ReceiveNotification"}, |
| 164 | {0x000C0080, PublishToSubscriber, "PublishToSubscriber"}, | 166 | {0x000C0080, PublishToSubscriber, "PublishToSubscriber"}, |
| 165 | {0x000D0040, nullptr, "PublishAndGetSubscriber"}, | 167 | {0x000D0040, nullptr, "PublishAndGetSubscriber"}, |
| 166 | {0x000E00C0, nullptr, "IsServiceRegistered"}, | 168 | {0x000E00C0, nullptr, "IsServiceRegistered"}, |
| 167 | }; | 169 | }; |
| 168 | 170 | ||
| 169 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 171 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
diff --git a/src/core/hle/service/ssl_c.cpp b/src/core/hle/service/ssl_c.cpp index a8aff1abf..47c4a8cb0 100644 --- a/src/core/hle/service/ssl_c.cpp +++ b/src/core/hle/service/ssl_c.cpp | |||
| @@ -37,7 +37,8 @@ static void GenerateRandomData(Service::Interface* self) { | |||
| 37 | u32 i = 0; | 37 | u32 i = 0; |
| 38 | while (i < size) { | 38 | while (i < size) { |
| 39 | if ((i % 4) == 0) { | 39 | if ((i % 4) == 0) { |
| 40 | // The random number generator returns 4 bytes worth of data, so generate new random data when i == 0 and when i is divisible by 4 | 40 | // The random number generator returns 4 bytes worth of data, so generate new random |
| 41 | // data when i == 0 and when i is divisible by 4 | ||
| 41 | data = rand_gen(); | 42 | data = rand_gen(); |
| 42 | } | 43 | } |
| 43 | 44 | ||
| @@ -59,27 +60,26 @@ static void GenerateRandomData(Service::Interface* self) { | |||
| 59 | } | 60 | } |
| 60 | 61 | ||
| 61 | const Interface::FunctionInfo FunctionTable[] = { | 62 | const Interface::FunctionInfo FunctionTable[] = { |
| 62 | {0x00010002, Initialize, "Initialize"}, | 63 | {0x00010002, Initialize, "Initialize"}, |
| 63 | {0x000200C2, nullptr, "CreateContext"}, | 64 | {0x000200C2, nullptr, "CreateContext"}, |
| 64 | {0x00030000, nullptr, "CreateRootCertChain"}, | 65 | {0x00030000, nullptr, "CreateRootCertChain"}, |
| 65 | {0x00040040, nullptr, "DestroyRootCertChain"}, | 66 | {0x00040040, nullptr, "DestroyRootCertChain"}, |
| 66 | {0x00050082, nullptr, "AddTrustedRootCA"}, | 67 | {0x00050082, nullptr, "AddTrustedRootCA"}, |
| 67 | {0x00060080, nullptr, "RootCertChainAddDefaultCert"}, | 68 | {0x00060080, nullptr, "RootCertChainAddDefaultCert"}, |
| 68 | {0x00070080, nullptr, "RootCertChainRemoveCert"}, | 69 | {0x00070080, nullptr, "RootCertChainRemoveCert"}, |
| 69 | {0x000E0040, nullptr, "OpenDefaultClientCertContext"}, | 70 | {0x000E0040, nullptr, "OpenDefaultClientCertContext"}, |
| 70 | {0x000F0040, nullptr, "CloseClientCertContext"}, | 71 | {0x000F0040, nullptr, "CloseClientCertContext"}, |
| 71 | {0x00110042, GenerateRandomData, "GenerateRandomData"}, | 72 | {0x00110042, GenerateRandomData, "GenerateRandomData"}, |
| 72 | {0x00120042, nullptr, "InitializeConnectionSession"}, | 73 | {0x00120042, nullptr, "InitializeConnectionSession"}, |
| 73 | {0x00130040, nullptr, "StartConnection"}, | 74 | {0x00130040, nullptr, "StartConnection"}, |
| 74 | {0x00140040, nullptr, "StartConnectionGetOut"}, | 75 | {0x00140040, nullptr, "StartConnectionGetOut"}, |
| 75 | {0x00150082, nullptr, "Read"}, | 76 | {0x00150082, nullptr, "Read"}, |
| 76 | {0x00170082, nullptr, "Write"}, | 77 | {0x00170082, nullptr, "Write"}, |
| 77 | {0x00180080, nullptr, "ContextSetRootCertChain"}, | 78 | {0x00180080, nullptr, "ContextSetRootCertChain"}, |
| 78 | {0x00190080, nullptr, "ContextSetClientCert"}, | 79 | {0x00190080, nullptr, "ContextSetClientCert"}, |
| 79 | {0x001B0080, nullptr, "ContextClearOpt"}, | 80 | {0x001B0080, nullptr, "ContextClearOpt"}, |
| 80 | {0x001E0040, nullptr, "DestroyContext"}, | 81 | {0x001E0040, nullptr, "DestroyContext"}, |
| 81 | {0x001F0082, nullptr, "ContextInitSharedmem"} | 82 | {0x001F0082, nullptr, "ContextInitSharedmem"}}; |
| 82 | }; | ||
| 83 | 83 | ||
| 84 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 84 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 85 | // Interface class | 85 | // Interface class |
diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp index d16578f87..278548e0e 100644 --- a/src/core/hle/service/y2r_u.cpp +++ b/src/core/hle/service/y2r_u.cpp | |||
| @@ -39,16 +39,16 @@ static u32 transfer_end_interrupt_enabled = 0; | |||
| 39 | static u32 spacial_dithering_enabled = 0; | 39 | static u32 spacial_dithering_enabled = 0; |
| 40 | 40 | ||
| 41 | static const CoefficientSet standard_coefficients[4] = { | 41 | static const CoefficientSet standard_coefficients[4] = { |
| 42 | {{ 0x100, 0x166, 0xB6, 0x58, 0x1C5, -0x166F, 0x10EE, -0x1C5B }}, // ITU_Rec601 | 42 | {{0x100, 0x166, 0xB6, 0x58, 0x1C5, -0x166F, 0x10EE, -0x1C5B}}, // ITU_Rec601 |
| 43 | {{ 0x100, 0x193, 0x77, 0x2F, 0x1DB, -0x1933, 0xA7C, -0x1D51 }}, // ITU_Rec709 | 43 | {{0x100, 0x193, 0x77, 0x2F, 0x1DB, -0x1933, 0xA7C, -0x1D51}}, // ITU_Rec709 |
| 44 | {{ 0x12A, 0x198, 0xD0, 0x64, 0x204, -0x1BDE, 0x10F2, -0x229B }}, // ITU_Rec601_Scaling | 44 | {{0x12A, 0x198, 0xD0, 0x64, 0x204, -0x1BDE, 0x10F2, -0x229B}}, // ITU_Rec601_Scaling |
| 45 | {{ 0x12A, 0x1CA, 0x88, 0x36, 0x21C, -0x1F04, 0x99C, -0x2421 }}, // ITU_Rec709_Scaling | 45 | {{0x12A, 0x1CA, 0x88, 0x36, 0x21C, -0x1F04, 0x99C, -0x2421}}, // ITU_Rec709_Scaling |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | ResultCode ConversionConfiguration::SetInputLineWidth(u16 width) { | 48 | ResultCode ConversionConfiguration::SetInputLineWidth(u16 width) { |
| 49 | if (width == 0 || width > 1024 || width % 8 != 0) { | 49 | if (width == 0 || width > 1024 || width % 8 != 0) { |
| 50 | return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM, | 50 | return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM, |
| 51 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD | 51 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | // Note: The hardware uses the register value 0 to represent a width of 1024, so for a width of | 54 | // Note: The hardware uses the register value 0 to represent a width of 1024, so for a width of |
| @@ -61,7 +61,7 @@ ResultCode ConversionConfiguration::SetInputLineWidth(u16 width) { | |||
| 61 | ResultCode ConversionConfiguration::SetInputLines(u16 lines) { | 61 | ResultCode ConversionConfiguration::SetInputLines(u16 lines) { |
| 62 | if (lines == 0 || lines > 1024) { | 62 | if (lines == 0 || lines > 1024) { |
| 63 | return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM, | 63 | return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM, |
| 64 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD | 64 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | // Note: In what appears to be a bug, the `camera` module does not set the hardware register at | 67 | // Note: In what appears to be a bug, the `camera` module does not set the hardware register at |
| @@ -73,11 +73,12 @@ ResultCode ConversionConfiguration::SetInputLines(u16 lines) { | |||
| 73 | return RESULT_SUCCESS; | 73 | return RESULT_SUCCESS; |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | ResultCode ConversionConfiguration::SetStandardCoefficient(StandardCoefficient standard_coefficient) { | 76 | ResultCode |
| 77 | ConversionConfiguration::SetStandardCoefficient(StandardCoefficient standard_coefficient) { | ||
| 77 | size_t index = static_cast<size_t>(standard_coefficient); | 78 | size_t index = static_cast<size_t>(standard_coefficient); |
| 78 | if (index >= ARRAY_SIZE(standard_coefficients)) { | 79 | if (index >= ARRAY_SIZE(standard_coefficients)) { |
| 79 | return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::CAM, | 80 | return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::CAM, |
| 80 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053ED | 81 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053ED |
| 81 | } | 82 | } |
| 82 | 83 | ||
| 83 | std::memcpy(coefficients.data(), standard_coefficients[index].data(), sizeof(coefficients)); | 84 | std::memcpy(coefficients.data(), standard_coefficients[index].data(), sizeof(coefficients)); |
| @@ -294,8 +295,10 @@ static void SetSendingY(Service::Interface* self) { | |||
| 294 | cmd_buff[0] = IPC::MakeHeader(0x10, 1, 0); | 295 | cmd_buff[0] = IPC::MakeHeader(0x10, 1, 0); |
| 295 | cmd_buff[1] = RESULT_SUCCESS.raw; | 296 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 296 | 297 | ||
| 297 | LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, src_process_handle=0x%08X", | 298 | LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, " |
| 298 | conversion.src_Y.image_size, conversion.src_Y.transfer_unit, conversion.src_Y.gap, cmd_buff[6]); | 299 | "src_process_handle=0x%08X", |
| 300 | conversion.src_Y.image_size, conversion.src_Y.transfer_unit, conversion.src_Y.gap, | ||
| 301 | cmd_buff[6]); | ||
| 299 | } | 302 | } |
| 300 | 303 | ||
| 301 | static void SetSendingU(Service::Interface* self) { | 304 | static void SetSendingU(Service::Interface* self) { |
| @@ -309,8 +312,10 @@ static void SetSendingU(Service::Interface* self) { | |||
| 309 | cmd_buff[0] = IPC::MakeHeader(0x11, 1, 0); | 312 | cmd_buff[0] = IPC::MakeHeader(0x11, 1, 0); |
| 310 | cmd_buff[1] = RESULT_SUCCESS.raw; | 313 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 311 | 314 | ||
| 312 | LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, src_process_handle=0x%08X", | 315 | LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, " |
| 313 | conversion.src_U.image_size, conversion.src_U.transfer_unit, conversion.src_U.gap, cmd_buff[6]); | 316 | "src_process_handle=0x%08X", |
| 317 | conversion.src_U.image_size, conversion.src_U.transfer_unit, conversion.src_U.gap, | ||
| 318 | cmd_buff[6]); | ||
| 314 | } | 319 | } |
| 315 | 320 | ||
| 316 | static void SetSendingV(Service::Interface* self) { | 321 | static void SetSendingV(Service::Interface* self) { |
| @@ -324,8 +329,10 @@ static void SetSendingV(Service::Interface* self) { | |||
| 324 | cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0); | 329 | cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0); |
| 325 | cmd_buff[1] = RESULT_SUCCESS.raw; | 330 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 326 | 331 | ||
| 327 | LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, src_process_handle=0x%08X", | 332 | LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, " |
| 328 | conversion.src_V.image_size, conversion.src_V.transfer_unit, conversion.src_V.gap, cmd_buff[6]); | 333 | "src_process_handle=0x%08X", |
| 334 | conversion.src_V.image_size, conversion.src_V.transfer_unit, conversion.src_V.gap, | ||
| 335 | cmd_buff[6]); | ||
| 329 | } | 336 | } |
| 330 | 337 | ||
| 331 | static void SetSendingYUYV(Service::Interface* self) { | 338 | static void SetSendingYUYV(Service::Interface* self) { |
| @@ -339,8 +346,10 @@ static void SetSendingYUYV(Service::Interface* self) { | |||
| 339 | cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0); | 346 | cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0); |
| 340 | cmd_buff[1] = RESULT_SUCCESS.raw; | 347 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 341 | 348 | ||
| 342 | LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, src_process_handle=0x%08X", | 349 | LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, " |
| 343 | conversion.src_YUYV.image_size, conversion.src_YUYV.transfer_unit, conversion.src_YUYV.gap, cmd_buff[6]); | 350 | "src_process_handle=0x%08X", |
| 351 | conversion.src_YUYV.image_size, conversion.src_YUYV.transfer_unit, | ||
| 352 | conversion.src_YUYV.gap, cmd_buff[6]); | ||
| 344 | } | 353 | } |
| 345 | 354 | ||
| 346 | /** | 355 | /** |
| @@ -418,8 +427,10 @@ static void SetReceiving(Service::Interface* self) { | |||
| 418 | cmd_buff[0] = IPC::MakeHeader(0x18, 1, 0); | 427 | cmd_buff[0] = IPC::MakeHeader(0x18, 1, 0); |
| 419 | cmd_buff[1] = RESULT_SUCCESS.raw; | 428 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 420 | 429 | ||
| 421 | LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, dst_process_handle=0x%08X", | 430 | LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, " |
| 422 | conversion.dst.image_size, conversion.dst.transfer_unit, conversion.dst.gap, cmd_buff[6]); | 431 | "dst_process_handle=0x%08X", |
| 432 | conversion.dst.image_size, conversion.dst.transfer_unit, conversion.dst.gap, | ||
| 433 | cmd_buff[6]); | ||
| 423 | } | 434 | } |
| 424 | 435 | ||
| 425 | /** | 436 | /** |
| @@ -486,8 +497,8 @@ static void SetCoefficient(Service::Interface* self) { | |||
| 486 | cmd_buff[1] = RESULT_SUCCESS.raw; | 497 | cmd_buff[1] = RESULT_SUCCESS.raw; |
| 487 | 498 | ||
| 488 | LOG_DEBUG(Service_Y2R, "called coefficients=[%hX, %hX, %hX, %hX, %hX, %hX, %hX, %hX]", | 499 | LOG_DEBUG(Service_Y2R, "called coefficients=[%hX, %hX, %hX, %hX, %hX, %hX, %hX, %hX]", |
| 489 | coefficients[0], coefficients[1], coefficients[2], coefficients[3], | 500 | coefficients[0], coefficients[1], coefficients[2], coefficients[3], coefficients[4], |
| 490 | coefficients[4], coefficients[5], coefficients[6], coefficients[7]); | 501 | coefficients[5], coefficients[6], coefficients[7]); |
| 491 | } | 502 | } |
| 492 | 503 | ||
| 493 | static void GetCoefficient(Service::Interface* self) { | 504 | static void GetCoefficient(Service::Interface* self) { |
| @@ -575,8 +586,10 @@ static void StartConversion(Service::Interface* self) { | |||
| 575 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 586 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 576 | 587 | ||
| 577 | // dst_image_size would seem to be perfect for this, but it doesn't include the gap :( | 588 | // dst_image_size would seem to be perfect for this, but it doesn't include the gap :( |
| 578 | u32 total_output_size = conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap); | 589 | u32 total_output_size = |
| 579 | Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(conversion.dst.address), total_output_size); | 590 | conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap); |
| 591 | Memory::RasterizerFlushAndInvalidateRegion( | ||
| 592 | Memory::VirtualToPhysicalAddress(conversion.dst.address), total_output_size); | ||
| 580 | 593 | ||
| 581 | HW::Y2R::PerformConversion(conversion); | 594 | HW::Y2R::PerformConversion(conversion); |
| 582 | 595 | ||
| @@ -648,10 +661,13 @@ cleanup: | |||
| 648 | cmd_buff[0] = IPC::MakeHeader(0x29, 1, 0); | 661 | cmd_buff[0] = IPC::MakeHeader(0x29, 1, 0); |
| 649 | cmd_buff[1] = result.raw; | 662 | cmd_buff[1] = result.raw; |
| 650 | 663 | ||
| 651 | LOG_DEBUG(Service_Y2R, "called input_format=%hhu output_format=%hhu rotation=%hhu block_alignment=%hhu " | 664 | LOG_DEBUG( |
| 652 | "input_line_width=%hu input_lines=%hu standard_coefficient=%hhu reserved=%hhu alpha=%hX", | 665 | Service_Y2R, |
| 653 | params->input_format, params->output_format, params->rotation, params->block_alignment, | 666 | "called input_format=%hhu output_format=%hhu rotation=%hhu block_alignment=%hhu " |
| 654 | params->input_line_width, params->input_lines, params->standard_coefficient, params->padding, params->alpha); | 667 | "input_line_width=%hu input_lines=%hu standard_coefficient=%hhu reserved=%hhu alpha=%hX", |
| 668 | params->input_format, params->output_format, params->rotation, params->block_alignment, | ||
| 669 | params->input_line_width, params->input_lines, params->standard_coefficient, | ||
| 670 | params->padding, params->alpha); | ||
| 655 | } | 671 | } |
| 656 | 672 | ||
| 657 | static void PingProcess(Service::Interface* self) { | 673 | static void PingProcess(Service::Interface* self) { |
| @@ -699,7 +715,6 @@ static void DriverFinalize(Service::Interface* self) { | |||
| 699 | LOG_DEBUG(Service_Y2R, "called"); | 715 | LOG_DEBUG(Service_Y2R, "called"); |
| 700 | } | 716 | } |
| 701 | 717 | ||
| 702 | |||
| 703 | static void GetPackageParameter(Service::Interface* self) { | 718 | static void GetPackageParameter(Service::Interface* self) { |
| 704 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 719 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 705 | 720 | ||
| @@ -711,51 +726,51 @@ static void GetPackageParameter(Service::Interface* self) { | |||
| 711 | } | 726 | } |
| 712 | 727 | ||
| 713 | const Interface::FunctionInfo FunctionTable[] = { | 728 | const Interface::FunctionInfo FunctionTable[] = { |
| 714 | {0x00010040, SetInputFormat, "SetInputFormat"}, | 729 | {0x00010040, SetInputFormat, "SetInputFormat"}, |
| 715 | {0x00020000, GetInputFormat, "GetInputFormat"}, | 730 | {0x00020000, GetInputFormat, "GetInputFormat"}, |
| 716 | {0x00030040, SetOutputFormat, "SetOutputFormat"}, | 731 | {0x00030040, SetOutputFormat, "SetOutputFormat"}, |
| 717 | {0x00040000, GetOutputFormat, "GetOutputFormat"}, | 732 | {0x00040000, GetOutputFormat, "GetOutputFormat"}, |
| 718 | {0x00050040, SetRotation, "SetRotation"}, | 733 | {0x00050040, SetRotation, "SetRotation"}, |
| 719 | {0x00060000, GetRotation, "GetRotation"}, | 734 | {0x00060000, GetRotation, "GetRotation"}, |
| 720 | {0x00070040, SetBlockAlignment, "SetBlockAlignment"}, | 735 | {0x00070040, SetBlockAlignment, "SetBlockAlignment"}, |
| 721 | {0x00080000, GetBlockAlignment, "GetBlockAlignment"}, | 736 | {0x00080000, GetBlockAlignment, "GetBlockAlignment"}, |
| 722 | {0x00090040, SetSpacialDithering, "SetSpacialDithering"}, | 737 | {0x00090040, SetSpacialDithering, "SetSpacialDithering"}, |
| 723 | {0x000A0000, GetSpacialDithering, "GetSpacialDithering"}, | 738 | {0x000A0000, GetSpacialDithering, "GetSpacialDithering"}, |
| 724 | {0x000B0040, SetTemporalDithering, "SetTemporalDithering"}, | 739 | {0x000B0040, SetTemporalDithering, "SetTemporalDithering"}, |
| 725 | {0x000C0000, GetTemporalDithering, "GetTemporalDithering"}, | 740 | {0x000C0000, GetTemporalDithering, "GetTemporalDithering"}, |
| 726 | {0x000D0040, SetTransferEndInterrupt, "SetTransferEndInterrupt"}, | 741 | {0x000D0040, SetTransferEndInterrupt, "SetTransferEndInterrupt"}, |
| 727 | {0x000E0000, GetTransferEndInterrupt, "GetTransferEndInterrupt"}, | 742 | {0x000E0000, GetTransferEndInterrupt, "GetTransferEndInterrupt"}, |
| 728 | {0x000F0000, GetTransferEndEvent, "GetTransferEndEvent"}, | 743 | {0x000F0000, GetTransferEndEvent, "GetTransferEndEvent"}, |
| 729 | {0x00100102, SetSendingY, "SetSendingY"}, | 744 | {0x00100102, SetSendingY, "SetSendingY"}, |
| 730 | {0x00110102, SetSendingU, "SetSendingU"}, | 745 | {0x00110102, SetSendingU, "SetSendingU"}, |
| 731 | {0x00120102, SetSendingV, "SetSendingV"}, | 746 | {0x00120102, SetSendingV, "SetSendingV"}, |
| 732 | {0x00130102, SetSendingYUYV, "SetSendingYUYV"}, | 747 | {0x00130102, SetSendingYUYV, "SetSendingYUYV"}, |
| 733 | {0x00140000, IsFinishedSendingYuv, "IsFinishedSendingYuv"}, | 748 | {0x00140000, IsFinishedSendingYuv, "IsFinishedSendingYuv"}, |
| 734 | {0x00150000, IsFinishedSendingY, "IsFinishedSendingY"}, | 749 | {0x00150000, IsFinishedSendingY, "IsFinishedSendingY"}, |
| 735 | {0x00160000, IsFinishedSendingU, "IsFinishedSendingU"}, | 750 | {0x00160000, IsFinishedSendingU, "IsFinishedSendingU"}, |
| 736 | {0x00170000, IsFinishedSendingV, "IsFinishedSendingV"}, | 751 | {0x00170000, IsFinishedSendingV, "IsFinishedSendingV"}, |
| 737 | {0x00180102, SetReceiving, "SetReceiving"}, | 752 | {0x00180102, SetReceiving, "SetReceiving"}, |
| 738 | {0x00190000, IsFinishedReceiving, "IsFinishedReceiving"}, | 753 | {0x00190000, IsFinishedReceiving, "IsFinishedReceiving"}, |
| 739 | {0x001A0040, SetInputLineWidth, "SetInputLineWidth"}, | 754 | {0x001A0040, SetInputLineWidth, "SetInputLineWidth"}, |
| 740 | {0x001B0000, GetInputLineWidth, "GetInputLineWidth"}, | 755 | {0x001B0000, GetInputLineWidth, "GetInputLineWidth"}, |
| 741 | {0x001C0040, SetInputLines, "SetInputLines"}, | 756 | {0x001C0040, SetInputLines, "SetInputLines"}, |
| 742 | {0x001D0000, GetInputLines, "GetInputLines"}, | 757 | {0x001D0000, GetInputLines, "GetInputLines"}, |
| 743 | {0x001E0100, SetCoefficient, "SetCoefficient"}, | 758 | {0x001E0100, SetCoefficient, "SetCoefficient"}, |
| 744 | {0x001F0000, GetCoefficient, "GetCoefficient"}, | 759 | {0x001F0000, GetCoefficient, "GetCoefficient"}, |
| 745 | {0x00200040, SetStandardCoefficient, "SetStandardCoefficient"}, | 760 | {0x00200040, SetStandardCoefficient, "SetStandardCoefficient"}, |
| 746 | {0x00210040, GetStandardCoefficient, "GetStandardCoefficient"}, | 761 | {0x00210040, GetStandardCoefficient, "GetStandardCoefficient"}, |
| 747 | {0x00220040, SetAlpha, "SetAlpha"}, | 762 | {0x00220040, SetAlpha, "SetAlpha"}, |
| 748 | {0x00230000, GetAlpha, "GetAlpha"}, | 763 | {0x00230000, GetAlpha, "GetAlpha"}, |
| 749 | {0x00240200, SetDitheringWeightParams,"SetDitheringWeightParams"}, | 764 | {0x00240200, SetDitheringWeightParams, "SetDitheringWeightParams"}, |
| 750 | {0x00250000, GetDitheringWeightParams,"GetDitheringWeightParams"}, | 765 | {0x00250000, GetDitheringWeightParams, "GetDitheringWeightParams"}, |
| 751 | {0x00260000, StartConversion, "StartConversion"}, | 766 | {0x00260000, StartConversion, "StartConversion"}, |
| 752 | {0x00270000, StopConversion, "StopConversion"}, | 767 | {0x00270000, StopConversion, "StopConversion"}, |
| 753 | {0x00280000, IsBusyConversion, "IsBusyConversion"}, | 768 | {0x00280000, IsBusyConversion, "IsBusyConversion"}, |
| 754 | {0x002901C0, SetPackageParameter, "SetPackageParameter"}, | 769 | {0x002901C0, SetPackageParameter, "SetPackageParameter"}, |
| 755 | {0x002A0000, PingProcess, "PingProcess"}, | 770 | {0x002A0000, PingProcess, "PingProcess"}, |
| 756 | {0x002B0000, DriverInitialize, "DriverInitialize"}, | 771 | {0x002B0000, DriverInitialize, "DriverInitialize"}, |
| 757 | {0x002C0000, DriverFinalize, "DriverFinalize"}, | 772 | {0x002C0000, DriverFinalize, "DriverFinalize"}, |
| 758 | {0x002D0000, GetPackageParameter, "GetPackageParameter"}, | 773 | {0x002D0000, GetPackageParameter, "GetPackageParameter"}, |
| 759 | }; | 774 | }; |
| 760 | 775 | ||
| 761 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 776 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
diff --git a/src/core/hle/shared_page.cpp b/src/core/hle/shared_page.cpp index 4d9272923..453fcf7ec 100644 --- a/src/core/hle/shared_page.cpp +++ b/src/core/hle/shared_page.cpp | |||
| @@ -52,8 +52,8 @@ static u64 GetSystemTime() { | |||
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | static void UpdateTimeCallback(u64 userdata, int cycles_late) { | 54 | static void UpdateTimeCallback(u64 userdata, int cycles_late) { |
| 55 | DateTime& date_time = shared_page.date_time_counter % 2 ? | 55 | DateTime& date_time = |
| 56 | shared_page.date_time_0 : shared_page.date_time_1; | 56 | shared_page.date_time_counter % 2 ? shared_page.date_time_0 : shared_page.date_time_1; |
| 57 | 57 | ||
| 58 | date_time.date_time = GetSystemTime(); | 58 | date_time.date_time = GetSystemTime(); |
| 59 | date_time.update_tick = CoreTiming::GetTicks(); | 59 | date_time.update_tick = CoreTiming::GetTicks(); |
| @@ -74,7 +74,8 @@ void Init() { | |||
| 74 | // Some games wait until this value becomes 0x1, before asking running_hw | 74 | // Some games wait until this value becomes 0x1, before asking running_hw |
| 75 | shared_page.unknown_value = 0x1; | 75 | shared_page.unknown_value = 0x1; |
| 76 | 76 | ||
| 77 | update_time_event = CoreTiming::RegisterEvent("SharedPage::UpdateTimeCallback", UpdateTimeCallback); | 77 | update_time_event = |
| 78 | CoreTiming::RegisterEvent("SharedPage::UpdateTimeCallback", UpdateTimeCallback); | ||
| 78 | CoreTiming::ScheduleEvent(0, update_time_event); | 79 | CoreTiming::ScheduleEvent(0, update_time_event); |
| 79 | } | 80 | } |
| 80 | 81 | ||
diff --git a/src/core/hle/shared_page.h b/src/core/hle/shared_page.h index cd9246726..b3b10be31 100644 --- a/src/core/hle/shared_page.h +++ b/src/core/hle/shared_page.h | |||
| @@ -32,27 +32,28 @@ static_assert(sizeof(DateTime) == 0x20, "Datetime size is wrong"); | |||
| 32 | 32 | ||
| 33 | struct SharedPageDef { | 33 | struct SharedPageDef { |
| 34 | // Most of these names are taken from the 3dbrew page linked above. | 34 | // Most of these names are taken from the 3dbrew page linked above. |
| 35 | u32_le date_time_counter; // 0 | 35 | u32_le date_time_counter; // 0 |
| 36 | u8 running_hw; // 4 | 36 | u8 running_hw; // 4 |
| 37 | /// "Microcontroller hardware info" | 37 | /// "Microcontroller hardware info" |
| 38 | u8 mcu_hw_info; // 5 | 38 | u8 mcu_hw_info; // 5 |
| 39 | INSERT_PADDING_BYTES(0x20 - 0x6); // 6 | 39 | INSERT_PADDING_BYTES(0x20 - 0x6); // 6 |
| 40 | DateTime date_time_0; // 20 | 40 | DateTime date_time_0; // 20 |
| 41 | DateTime date_time_1; // 40 | 41 | DateTime date_time_1; // 40 |
| 42 | u8 wifi_macaddr[6]; // 60 | 42 | u8 wifi_macaddr[6]; // 60 |
| 43 | u8 wifi_link_level; // 66 | 43 | u8 wifi_link_level; // 66 |
| 44 | u8 wifi_unknown2; // 67 | 44 | u8 wifi_unknown2; // 67 |
| 45 | INSERT_PADDING_BYTES(0x80 - 0x68); // 68 | 45 | INSERT_PADDING_BYTES(0x80 - 0x68); // 68 |
| 46 | float_le sliderstate_3d; // 80 | 46 | float_le sliderstate_3d; // 80 |
| 47 | u8 ledstate_3d; // 84 | 47 | u8 ledstate_3d; // 84 |
| 48 | INSERT_PADDING_BYTES(1); // 85 | 48 | INSERT_PADDING_BYTES(1); // 85 |
| 49 | u8 unknown_value; // 86 | 49 | u8 unknown_value; // 86 |
| 50 | INSERT_PADDING_BYTES(0xA0 - 0x87); // 87 | 50 | INSERT_PADDING_BYTES(0xA0 - 0x87); // 87 |
| 51 | u64_le menu_title_id; // A0 | 51 | u64_le menu_title_id; // A0 |
| 52 | u64_le active_menu_title_id; // A8 | 52 | u64_le active_menu_title_id; // A8 |
| 53 | INSERT_PADDING_BYTES(0x1000 - 0xB0); // B0 | 53 | INSERT_PADDING_BYTES(0x1000 - 0xB0); // B0 |
| 54 | }; | 54 | }; |
| 55 | static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE, "Shared page structure size is wrong"); | 55 | static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE, |
| 56 | "Shared page structure size is wrong"); | ||
| 56 | 57 | ||
| 57 | extern SharedPageDef shared_page; | 58 | extern SharedPageDef shared_page; |
| 58 | 59 | ||
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 5d71d5619..9d0a9c54c 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp | |||
| @@ -10,8 +10,8 @@ | |||
| 10 | #include "common/string_util.h" | 10 | #include "common/string_util.h" |
| 11 | #include "common/symbols.h" | 11 | #include "common/symbols.h" |
| 12 | 12 | ||
| 13 | #include "core/core_timing.h" | ||
| 14 | #include "core/arm/arm_interface.h" | 13 | #include "core/arm/arm_interface.h" |
| 14 | #include "core/core_timing.h" | ||
| 15 | 15 | ||
| 16 | #include "core/hle/kernel/address_arbiter.h" | 16 | #include "core/hle/kernel/address_arbiter.h" |
| 17 | #include "core/hle/kernel/client_port.h" | 17 | #include "core/hle/kernel/client_port.h" |
| @@ -40,43 +40,46 @@ using Kernel::ERR_INVALID_HANDLE; | |||
| 40 | namespace SVC { | 40 | namespace SVC { |
| 41 | 41 | ||
| 42 | const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel, | 42 | const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel, |
| 43 | ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA | 43 | ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA |
| 44 | const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS, | 44 | const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS, |
| 45 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E0181E | 45 | ErrorSummary::InvalidArgument, |
| 46 | 46 | ErrorLevel::Usage); // 0xE0E0181E | |
| 47 | const ResultCode ERR_MISALIGNED_ADDRESS{ // 0xE0E01BF1 | 47 | |
| 48 | ErrorDescription::MisalignedAddress, ErrorModule::OS, | 48 | const ResultCode ERR_MISALIGNED_ADDRESS{// 0xE0E01BF1 |
| 49 | ErrorSummary::InvalidArgument, ErrorLevel::Usage}; | 49 | ErrorDescription::MisalignedAddress, ErrorModule::OS, |
| 50 | const ResultCode ERR_MISALIGNED_SIZE{ // 0xE0E01BF2 | 50 | ErrorSummary::InvalidArgument, ErrorLevel::Usage}; |
| 51 | ErrorDescription::MisalignedSize, ErrorModule::OS, | 51 | const ResultCode ERR_MISALIGNED_SIZE{// 0xE0E01BF2 |
| 52 | ErrorSummary::InvalidArgument, ErrorLevel::Usage}; | 52 | ErrorDescription::MisalignedSize, ErrorModule::OS, |
| 53 | const ResultCode ERR_INVALID_COMBINATION{ // 0xE0E01BEE | 53 | ErrorSummary::InvalidArgument, ErrorLevel::Usage}; |
| 54 | ErrorDescription::InvalidCombination, ErrorModule::OS, | 54 | const ResultCode ERR_INVALID_COMBINATION{// 0xE0E01BEE |
| 55 | ErrorSummary::InvalidArgument, ErrorLevel::Usage}; | 55 | ErrorDescription::InvalidCombination, ErrorModule::OS, |
| 56 | ErrorSummary::InvalidArgument, ErrorLevel::Usage}; | ||
| 56 | 57 | ||
| 57 | enum ControlMemoryOperation { | 58 | enum ControlMemoryOperation { |
| 58 | MEMOP_FREE = 1, | 59 | MEMOP_FREE = 1, |
| 59 | MEMOP_RESERVE = 2, // This operation seems to be unsupported in the kernel | 60 | MEMOP_RESERVE = 2, // This operation seems to be unsupported in the kernel |
| 60 | MEMOP_COMMIT = 3, | 61 | MEMOP_COMMIT = 3, |
| 61 | MEMOP_MAP = 4, | 62 | MEMOP_MAP = 4, |
| 62 | MEMOP_UNMAP = 5, | 63 | MEMOP_UNMAP = 5, |
| 63 | MEMOP_PROTECT = 6, | 64 | MEMOP_PROTECT = 6, |
| 64 | MEMOP_OPERATION_MASK = 0xFF, | 65 | MEMOP_OPERATION_MASK = 0xFF, |
| 65 | 66 | ||
| 66 | MEMOP_REGION_APP = 0x100, | 67 | MEMOP_REGION_APP = 0x100, |
| 67 | MEMOP_REGION_SYSTEM = 0x200, | 68 | MEMOP_REGION_SYSTEM = 0x200, |
| 68 | MEMOP_REGION_BASE = 0x300, | 69 | MEMOP_REGION_BASE = 0x300, |
| 69 | MEMOP_REGION_MASK = 0xF00, | 70 | MEMOP_REGION_MASK = 0xF00, |
| 70 | 71 | ||
| 71 | MEMOP_LINEAR = 0x10000, | 72 | MEMOP_LINEAR = 0x10000, |
| 72 | }; | 73 | }; |
| 73 | 74 | ||
| 74 | /// Map application or GSP heap memory | 75 | /// Map application or GSP heap memory |
| 75 | static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { | 76 | static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, |
| 77 | u32 permissions) { | ||
| 76 | using namespace Kernel; | 78 | using namespace Kernel; |
| 77 | 79 | ||
| 78 | LOG_DEBUG(Kernel_SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=0x%X, permissions=0x%08X", | 80 | LOG_DEBUG(Kernel_SVC, |
| 79 | operation, addr0, addr1, size, permissions); | 81 | "called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=0x%X, permissions=0x%08X", |
| 82 | operation, addr0, addr1, size, permissions); | ||
| 80 | 83 | ||
| 81 | if ((addr0 & Memory::PAGE_MASK) != 0 || (addr1 & Memory::PAGE_MASK) != 0) { | 84 | if ((addr0 & Memory::PAGE_MASK) != 0 || (addr1 & Memory::PAGE_MASK) != 0) { |
| 82 | return ERR_MISALIGNED_ADDRESS; | 85 | return ERR_MISALIGNED_ADDRESS; |
| @@ -89,7 +92,8 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add | |||
| 89 | operation &= ~MEMOP_REGION_MASK; | 92 | operation &= ~MEMOP_REGION_MASK; |
| 90 | 93 | ||
| 91 | if (region != 0) { | 94 | if (region != 0) { |
| 92 | LOG_WARNING(Kernel_SVC, "ControlMemory with specified region not supported, region=%X", region); | 95 | LOG_WARNING(Kernel_SVC, "ControlMemory with specified region not supported, region=%X", |
| 96 | region); | ||
| 93 | } | 97 | } |
| 94 | 98 | ||
| 95 | if ((permissions & (u32)MemoryPermission::ReadWrite) != permissions) { | 99 | if ((permissions & (u32)MemoryPermission::ReadWrite) != permissions) { |
| @@ -100,15 +104,17 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add | |||
| 100 | auto& process = *g_current_process; | 104 | auto& process = *g_current_process; |
| 101 | 105 | ||
| 102 | switch (operation & MEMOP_OPERATION_MASK) { | 106 | switch (operation & MEMOP_OPERATION_MASK) { |
| 103 | case MEMOP_FREE: | 107 | case MEMOP_FREE: { |
| 104 | { | 108 | // TODO(Subv): What happens if an application tries to FREE a block of memory that has a |
| 105 | // TODO(Subv): What happens if an application tries to FREE a block of memory that has a SharedMemory pointing to it? | 109 | // SharedMemory pointing to it? |
| 106 | if (addr0 >= Memory::HEAP_VADDR && addr0 < Memory::HEAP_VADDR_END) { | 110 | if (addr0 >= Memory::HEAP_VADDR && addr0 < Memory::HEAP_VADDR_END) { |
| 107 | ResultCode result = process.HeapFree(addr0, size); | 111 | ResultCode result = process.HeapFree(addr0, size); |
| 108 | if (result.IsError()) return result; | 112 | if (result.IsError()) |
| 113 | return result; | ||
| 109 | } else if (addr0 >= process.GetLinearHeapBase() && addr0 < process.GetLinearHeapLimit()) { | 114 | } else if (addr0 >= process.GetLinearHeapBase() && addr0 < process.GetLinearHeapLimit()) { |
| 110 | ResultCode result = process.LinearFree(addr0, size); | 115 | ResultCode result = process.LinearFree(addr0, size); |
| 111 | if (result.IsError()) return result; | 116 | if (result.IsError()) |
| 117 | return result; | ||
| 112 | } else { | 118 | } else { |
| 113 | return ERR_INVALID_ADDRESS; | 119 | return ERR_INVALID_ADDRESS; |
| 114 | } | 120 | } |
| @@ -116,8 +122,7 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add | |||
| 116 | break; | 122 | break; |
| 117 | } | 123 | } |
| 118 | 124 | ||
| 119 | case MEMOP_COMMIT: | 125 | case MEMOP_COMMIT: { |
| 120 | { | ||
| 121 | if (operation & MEMOP_LINEAR) { | 126 | if (operation & MEMOP_LINEAR) { |
| 122 | CASCADE_RESULT(*out_addr, process.LinearAllocate(addr0, size, vma_permissions)); | 127 | CASCADE_RESULT(*out_addr, process.LinearAllocate(addr0, size, vma_permissions)); |
| 123 | } else { | 128 | } else { |
| @@ -126,23 +131,26 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add | |||
| 126 | break; | 131 | break; |
| 127 | } | 132 | } |
| 128 | 133 | ||
| 129 | case MEMOP_MAP: // TODO: This is just a hack to avoid regressions until memory aliasing is implemented | 134 | case MEMOP_MAP: // TODO: This is just a hack to avoid regressions until memory aliasing is |
| 130 | { | 135 | // implemented |
| 131 | CASCADE_RESULT(*out_addr, process.HeapAllocate(addr0, size, vma_permissions)); | 136 | { |
| 132 | break; | 137 | CASCADE_RESULT(*out_addr, process.HeapAllocate(addr0, size, vma_permissions)); |
| 133 | } | 138 | break; |
| 139 | } | ||
| 134 | 140 | ||
| 135 | case MEMOP_UNMAP: // TODO: This is just a hack to avoid regressions until memory aliasing is implemented | 141 | case MEMOP_UNMAP: // TODO: This is just a hack to avoid regressions until memory aliasing is |
| 136 | { | 142 | // implemented |
| 137 | ResultCode result = process.HeapFree(addr0, size); | 143 | { |
| 138 | if (result.IsError()) return result; | 144 | ResultCode result = process.HeapFree(addr0, size); |
| 139 | break; | 145 | if (result.IsError()) |
| 140 | } | 146 | return result; |
| 147 | break; | ||
| 148 | } | ||
| 141 | 149 | ||
| 142 | case MEMOP_PROTECT: | 150 | case MEMOP_PROTECT: { |
| 143 | { | ||
| 144 | ResultCode result = process.vm_manager.ReprotectRange(addr0, size, vma_permissions); | 151 | ResultCode result = process.vm_manager.ReprotectRange(addr0, size, vma_permissions); |
| 145 | if (result.IsError()) return result; | 152 | if (result.IsError()) |
| 153 | return result; | ||
| 146 | break; | 154 | break; |
| 147 | } | 155 | } |
| 148 | 156 | ||
| @@ -161,8 +169,9 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o | |||
| 161 | using Kernel::SharedMemory; | 169 | using Kernel::SharedMemory; |
| 162 | using Kernel::MemoryPermission; | 170 | using Kernel::MemoryPermission; |
| 163 | 171 | ||
| 164 | LOG_TRACE(Kernel_SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", | 172 | LOG_TRACE(Kernel_SVC, |
| 165 | handle, addr, permissions, other_permissions); | 173 | "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", |
| 174 | handle, addr, permissions, other_permissions); | ||
| 166 | 175 | ||
| 167 | SharedPtr<SharedMemory> shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle); | 176 | SharedPtr<SharedMemory> shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle); |
| 168 | if (shared_memory == nullptr) | 177 | if (shared_memory == nullptr) |
| @@ -179,12 +188,13 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o | |||
| 179 | case MemoryPermission::ReadWriteExecute: | 188 | case MemoryPermission::ReadWriteExecute: |
| 180 | case MemoryPermission::DontCare: | 189 | case MemoryPermission::DontCare: |
| 181 | return shared_memory->Map(Kernel::g_current_process.get(), addr, permissions_type, | 190 | return shared_memory->Map(Kernel::g_current_process.get(), addr, permissions_type, |
| 182 | static_cast<MemoryPermission>(other_permissions)); | 191 | static_cast<MemoryPermission>(other_permissions)); |
| 183 | default: | 192 | default: |
| 184 | LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); | 193 | LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); |
| 185 | } | 194 | } |
| 186 | 195 | ||
| 187 | return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); | 196 | return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, |
| 197 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); | ||
| 188 | } | 198 | } |
| 189 | 199 | ||
| 190 | static ResultCode UnmapMemoryBlock(Handle handle, u32 addr) { | 200 | static ResultCode UnmapMemoryBlock(Handle handle, u32 addr) { |
| @@ -249,7 +259,7 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) { | |||
| 249 | return ERR_INVALID_HANDLE; | 259 | return ERR_INVALID_HANDLE; |
| 250 | 260 | ||
| 251 | LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, | 261 | LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, |
| 252 | object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds); | 262 | object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds); |
| 253 | 263 | ||
| 254 | HLE::Reschedule(__func__); | 264 | HLE::Reschedule(__func__); |
| 255 | 265 | ||
| @@ -257,7 +267,7 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) { | |||
| 257 | if (object->ShouldWait()) { | 267 | if (object->ShouldWait()) { |
| 258 | 268 | ||
| 259 | object->AddWaitingThread(thread); | 269 | object->AddWaitingThread(thread); |
| 260 | Kernel::WaitCurrentThread_WaitSynchronization({ object }, false, false); | 270 | Kernel::WaitCurrentThread_WaitSynchronization({object}, false, false); |
| 261 | 271 | ||
| 262 | // Create an event to wake the thread up after the specified nanosecond delay has passed | 272 | // Create an event to wake the thread up after the specified nanosecond delay has passed |
| 263 | thread->WakeAfterDelay(nano_seconds); | 273 | thread->WakeAfterDelay(nano_seconds); |
| @@ -272,7 +282,8 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) { | |||
| 272 | } | 282 | } |
| 273 | 283 | ||
| 274 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds | 284 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds |
| 275 | static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, s64 nano_seconds) { | 285 | static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, |
| 286 | s64 nano_seconds) { | ||
| 276 | bool wait_thread = !wait_all; | 287 | bool wait_thread = !wait_all; |
| 277 | int handle_index = 0; | 288 | int handle_index = 0; |
| 278 | Kernel::Thread* thread = Kernel::GetCurrentThread(); | 289 | Kernel::Thread* thread = Kernel::GetCurrentThread(); |
| @@ -281,7 +292,8 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou | |||
| 281 | 292 | ||
| 282 | // Check if 'handles' is invalid | 293 | // Check if 'handles' is invalid |
| 283 | if (handles == nullptr) | 294 | if (handles == nullptr) |
| 284 | return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent); | 295 | return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel, |
| 296 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); | ||
| 285 | 297 | ||
| 286 | // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If | 298 | // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If |
| 287 | // this happens, the running application will crash. | 299 | // this happens, the running application will crash. |
| @@ -289,7 +301,8 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou | |||
| 289 | 301 | ||
| 290 | // Check if 'handle_count' is invalid | 302 | // Check if 'handle_count' is invalid |
| 291 | if (handle_count < 0) | 303 | if (handle_count < 0) |
| 292 | return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); | 304 | return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, |
| 305 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); | ||
| 293 | 306 | ||
| 294 | // If 'handle_count' is non-zero, iterate through each handle and wait the current thread if | 307 | // If 'handle_count' is non-zero, iterate through each handle and wait the current thread if |
| 295 | // necessary | 308 | // necessary |
| @@ -329,7 +342,9 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou | |||
| 329 | } | 342 | } |
| 330 | } | 343 | } |
| 331 | 344 | ||
| 332 | SCOPE_EXIT({HLE::Reschedule("WaitSynchronizationN");}); // Reschedule after putting the threads to sleep. | 345 | SCOPE_EXIT({ |
| 346 | HLE::Reschedule("WaitSynchronizationN"); | ||
| 347 | }); // Reschedule after putting the threads to sleep. | ||
| 333 | 348 | ||
| 334 | // If thread should wait, then set its state to waiting | 349 | // If thread should wait, then set its state to waiting |
| 335 | if (wait_thread) { | 350 | if (wait_thread) { |
| @@ -386,18 +401,19 @@ static ResultCode CreateAddressArbiter(Handle* out_handle) { | |||
| 386 | } | 401 | } |
| 387 | 402 | ||
| 388 | /// Arbitrate address | 403 | /// Arbitrate address |
| 389 | static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value, s64 nanoseconds) { | 404 | static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value, |
| 405 | s64 nanoseconds) { | ||
| 390 | using Kernel::AddressArbiter; | 406 | using Kernel::AddressArbiter; |
| 391 | 407 | ||
| 392 | LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", handle, | 408 | LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", handle, |
| 393 | address, type, value); | 409 | address, type, value); |
| 394 | 410 | ||
| 395 | SharedPtr<AddressArbiter> arbiter = Kernel::g_handle_table.Get<AddressArbiter>(handle); | 411 | SharedPtr<AddressArbiter> arbiter = Kernel::g_handle_table.Get<AddressArbiter>(handle); |
| 396 | if (arbiter == nullptr) | 412 | if (arbiter == nullptr) |
| 397 | return ERR_INVALID_HANDLE; | 413 | return ERR_INVALID_HANDLE; |
| 398 | 414 | ||
| 399 | auto res = arbiter->ArbitrateAddress(static_cast<Kernel::ArbitrationType>(type), | 415 | auto res = arbiter->ArbitrateAddress(static_cast<Kernel::ArbitrationType>(type), address, value, |
| 400 | address, value, nanoseconds); | 416 | nanoseconds); |
| 401 | 417 | ||
| 402 | return res; | 418 | return res; |
| 403 | } | 419 | } |
| @@ -406,10 +422,18 @@ static void Break(u8 break_reason) { | |||
| 406 | LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!"); | 422 | LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!"); |
| 407 | std::string reason_str; | 423 | std::string reason_str; |
| 408 | switch (break_reason) { | 424 | switch (break_reason) { |
| 409 | case 0: reason_str = "PANIC"; break; | 425 | case 0: |
| 410 | case 1: reason_str = "ASSERT"; break; | 426 | reason_str = "PANIC"; |
| 411 | case 2: reason_str = "USER"; break; | 427 | break; |
| 412 | default: reason_str = "UNKNOWN"; break; | 428 | case 1: |
| 429 | reason_str = "ASSERT"; | ||
| 430 | break; | ||
| 431 | case 2: | ||
| 432 | reason_str = "USER"; | ||
| 433 | break; | ||
| 434 | default: | ||
| 435 | reason_str = "UNKNOWN"; | ||
| 436 | break; | ||
| 413 | } | 437 | } |
| 414 | LOG_CRITICAL(Debug_Emulated, "Break reason: %s", reason_str.c_str()); | 438 | LOG_CRITICAL(Debug_Emulated, "Break reason: %s", reason_str.c_str()); |
| 415 | } | 439 | } |
| @@ -423,7 +447,8 @@ static void OutputDebugString(const char* string) { | |||
| 423 | static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle) { | 447 | static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle) { |
| 424 | LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); | 448 | LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); |
| 425 | 449 | ||
| 426 | SharedPtr<Kernel::Process> process = Kernel::g_handle_table.Get<Kernel::Process>(process_handle); | 450 | SharedPtr<Kernel::Process> process = |
| 451 | Kernel::g_handle_table.Get<Kernel::Process>(process_handle); | ||
| 427 | if (process == nullptr) | 452 | if (process == nullptr) |
| 428 | return ERR_INVALID_HANDLE; | 453 | return ERR_INVALID_HANDLE; |
| 429 | 454 | ||
| @@ -433,12 +458,13 @@ static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle | |||
| 433 | } | 458 | } |
| 434 | 459 | ||
| 435 | /// Get resource limit current values | 460 | /// Get resource limit current values |
| 436 | static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit_handle, u32* names, | 461 | static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit_handle, |
| 437 | u32 name_count) { | 462 | u32* names, u32 name_count) { |
| 438 | LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", | 463 | LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", |
| 439 | resource_limit_handle, names, name_count); | 464 | resource_limit_handle, names, name_count); |
| 440 | 465 | ||
| 441 | SharedPtr<Kernel::ResourceLimit> resource_limit = Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle); | 466 | SharedPtr<Kernel::ResourceLimit> resource_limit = |
| 467 | Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle); | ||
| 442 | if (resource_limit == nullptr) | 468 | if (resource_limit == nullptr) |
| 443 | return ERR_INVALID_HANDLE; | 469 | return ERR_INVALID_HANDLE; |
| 444 | 470 | ||
| @@ -450,11 +476,12 @@ static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_lim | |||
| 450 | 476 | ||
| 451 | /// Get resource limit max values | 477 | /// Get resource limit max values |
| 452 | static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit_handle, u32* names, | 478 | static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit_handle, u32* names, |
| 453 | u32 name_count) { | 479 | u32 name_count) { |
| 454 | LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", | 480 | LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", |
| 455 | resource_limit_handle, names, name_count); | 481 | resource_limit_handle, names, name_count); |
| 456 | 482 | ||
| 457 | SharedPtr<Kernel::ResourceLimit> resource_limit = Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle); | 483 | SharedPtr<Kernel::ResourceLimit> resource_limit = |
| 484 | Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle); | ||
| 458 | if (resource_limit == nullptr) | 485 | if (resource_limit == nullptr) |
| 459 | return ERR_INVALID_HANDLE; | 486 | return ERR_INVALID_HANDLE; |
| 460 | 487 | ||
| @@ -465,7 +492,8 @@ static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit | |||
| 465 | } | 492 | } |
| 466 | 493 | ||
| 467 | /// Creates a new thread | 494 | /// Creates a new thread |
| 468 | static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point, u32 arg, u32 stack_top, s32 processor_id) { | 495 | static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point, u32 arg, |
| 496 | u32 stack_top, s32 processor_id) { | ||
| 469 | using Kernel::Thread; | 497 | using Kernel::Thread; |
| 470 | 498 | ||
| 471 | std::string name; | 499 | std::string name; |
| @@ -499,20 +527,23 @@ static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point | |||
| 499 | } | 527 | } |
| 500 | 528 | ||
| 501 | if (processor_id == THREADPROCESSORID_1 || processor_id == THREADPROCESSORID_ALL || | 529 | if (processor_id == THREADPROCESSORID_1 || processor_id == THREADPROCESSORID_ALL || |
| 502 | (processor_id == THREADPROCESSORID_DEFAULT && Kernel::g_current_process->ideal_processor == THREADPROCESSORID_1)) { | 530 | (processor_id == THREADPROCESSORID_DEFAULT && |
| 503 | LOG_WARNING(Kernel_SVC, "Newly created thread is allowed to be run in the SysCore, unimplemented."); | 531 | Kernel::g_current_process->ideal_processor == THREADPROCESSORID_1)) { |
| 532 | LOG_WARNING(Kernel_SVC, | ||
| 533 | "Newly created thread is allowed to be run in the SysCore, unimplemented."); | ||
| 504 | } | 534 | } |
| 505 | 535 | ||
| 506 | CASCADE_RESULT(SharedPtr<Thread> thread, Kernel::Thread::Create( | 536 | CASCADE_RESULT(SharedPtr<Thread> thread, Kernel::Thread::Create(name, entry_point, priority, |
| 507 | name, entry_point, priority, arg, processor_id, stack_top)); | 537 | arg, processor_id, stack_top)); |
| 508 | 538 | ||
| 509 | thread->context.fpscr = FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO; // 0x03C00000 | 539 | thread->context.fpscr = |
| 540 | FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO; // 0x03C00000 | ||
| 510 | 541 | ||
| 511 | CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread))); | 542 | CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread))); |
| 512 | 543 | ||
| 513 | LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " | 544 | LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " |
| 514 | "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, | 545 | "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", |
| 515 | name.c_str(), arg, stack_top, priority, processor_id, *out_handle); | 546 | entry_point, name.c_str(), arg, stack_top, priority, processor_id, *out_handle); |
| 516 | 547 | ||
| 517 | return RESULT_SUCCESS; | 548 | return RESULT_SUCCESS; |
| 518 | } | 549 | } |
| @@ -552,7 +583,7 @@ static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) { | |||
| 552 | CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex))); | 583 | CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex))); |
| 553 | 584 | ||
| 554 | LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", | 585 | LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", |
| 555 | initial_locked ? "true" : "false", *out_handle); | 586 | initial_locked ? "true" : "false", *out_handle); |
| 556 | 587 | ||
| 557 | return RESULT_SUCCESS; | 588 | return RESULT_SUCCESS; |
| 558 | } | 589 | } |
| @@ -576,7 +607,8 @@ static ResultCode ReleaseMutex(Handle handle) { | |||
| 576 | static ResultCode GetProcessId(u32* process_id, Handle process_handle) { | 607 | static ResultCode GetProcessId(u32* process_id, Handle process_handle) { |
| 577 | LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); | 608 | LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); |
| 578 | 609 | ||
| 579 | const SharedPtr<Kernel::Process> process = Kernel::g_handle_table.Get<Kernel::Process>(process_handle); | 610 | const SharedPtr<Kernel::Process> process = |
| 611 | Kernel::g_handle_table.Get<Kernel::Process>(process_handle); | ||
| 580 | if (process == nullptr) | 612 | if (process == nullptr) |
| 581 | return ERR_INVALID_HANDLE; | 613 | return ERR_INVALID_HANDLE; |
| 582 | 614 | ||
| @@ -588,7 +620,8 @@ static ResultCode GetProcessId(u32* process_id, Handle process_handle) { | |||
| 588 | static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) { | 620 | static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) { |
| 589 | LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle); | 621 | LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle); |
| 590 | 622 | ||
| 591 | const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(thread_handle); | 623 | const SharedPtr<Kernel::Thread> thread = |
| 624 | Kernel::g_handle_table.Get<Kernel::Thread>(thread_handle); | ||
| 592 | if (thread == nullptr) | 625 | if (thread == nullptr) |
| 593 | return ERR_INVALID_HANDLE; | 626 | return ERR_INVALID_HANDLE; |
| 594 | 627 | ||
| @@ -620,7 +653,7 @@ static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max | |||
| 620 | CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(semaphore))); | 653 | CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(semaphore))); |
| 621 | 654 | ||
| 622 | LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", | 655 | LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", |
| 623 | initial_count, max_count, *out_handle); | 656 | initial_count, max_count, *out_handle); |
| 624 | return RESULT_SUCCESS; | 657 | return RESULT_SUCCESS; |
| 625 | } | 658 | } |
| 626 | 659 | ||
| @@ -640,7 +673,8 @@ static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) | |||
| 640 | } | 673 | } |
| 641 | 674 | ||
| 642 | /// Query process memory | 675 | /// Query process memory |
| 643 | static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info, Handle process_handle, u32 addr) { | 676 | static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info, |
| 677 | Handle process_handle, u32 addr) { | ||
| 644 | using Kernel::Process; | 678 | using Kernel::Process; |
| 645 | Kernel::SharedPtr<Process> process = Kernel::g_handle_table.Get<Process>(process_handle); | 679 | Kernel::SharedPtr<Process> process = Kernel::g_handle_table.Get<Process>(process_handle); |
| 646 | if (process == nullptr) | 680 | if (process == nullptr) |
| @@ -649,7 +683,8 @@ static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_inf | |||
| 649 | auto vma = process->vm_manager.FindVMA(addr); | 683 | auto vma = process->vm_manager.FindVMA(addr); |
| 650 | 684 | ||
| 651 | if (vma == Kernel::g_current_process->vm_manager.vma_map.end()) | 685 | if (vma == Kernel::g_current_process->vm_manager.vma_map.end()) |
| 652 | return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); | 686 | return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, |
| 687 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); | ||
| 653 | 688 | ||
| 654 | memory_info->base_address = vma->second.base; | 689 | memory_info->base_address = vma->second.base; |
| 655 | memory_info->permission = static_cast<u32>(vma->second.permissions); | 690 | memory_info->permission = static_cast<u32>(vma->second.permissions); |
| @@ -673,8 +708,8 @@ static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) { | |||
| 673 | SharedPtr<Event> evt = Event::Create(static_cast<Kernel::ResetType>(reset_type)); | 708 | SharedPtr<Event> evt = Event::Create(static_cast<Kernel::ResetType>(reset_type)); |
| 674 | CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt))); | 709 | CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt))); |
| 675 | 710 | ||
| 676 | LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", | 711 | LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type, |
| 677 | reset_type, *out_handle); | 712 | *out_handle); |
| 678 | return RESULT_SUCCESS; | 713 | return RESULT_SUCCESS; |
| 679 | } | 714 | } |
| 680 | 715 | ||
| @@ -719,8 +754,8 @@ static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) { | |||
| 719 | SharedPtr<Timer> timer = Timer::Create(static_cast<Kernel::ResetType>(reset_type)); | 754 | SharedPtr<Timer> timer = Timer::Create(static_cast<Kernel::ResetType>(reset_type)); |
| 720 | CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer))); | 755 | CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer))); |
| 721 | 756 | ||
| 722 | LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", | 757 | LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type, |
| 723 | reset_type, *out_handle); | 758 | *out_handle); |
| 724 | return RESULT_SUCCESS; | 759 | return RESULT_SUCCESS; |
| 725 | } | 760 | } |
| 726 | 761 | ||
| @@ -783,17 +818,19 @@ static void SleepThread(s64 nanoseconds) { | |||
| 783 | static s64 GetSystemTick() { | 818 | static s64 GetSystemTick() { |
| 784 | s64 result = CoreTiming::GetTicks(); | 819 | s64 result = CoreTiming::GetTicks(); |
| 785 | // Advance time to defeat dumb games (like Cubic Ninja) that busy-wait for the frame to end. | 820 | // Advance time to defeat dumb games (like Cubic Ninja) that busy-wait for the frame to end. |
| 786 | Core::g_app_core->AddTicks(150); // Measured time between two calls on a 9.2 o3DS with Ninjhax 1.1b | 821 | Core::g_app_core->AddTicks( |
| 822 | 150); // Measured time between two calls on a 9.2 o3DS with Ninjhax 1.1b | ||
| 787 | return result; | 823 | return result; |
| 788 | } | 824 | } |
| 789 | 825 | ||
| 790 | /// Creates a memory block at the specified address with the specified permissions and size | 826 | /// Creates a memory block at the specified address with the specified permissions and size |
| 791 | static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission, | 827 | static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission, |
| 792 | u32 other_permission) { | 828 | u32 other_permission) { |
| 793 | using Kernel::SharedMemory; | 829 | using Kernel::SharedMemory; |
| 794 | 830 | ||
| 795 | if (size % Memory::PAGE_SIZE != 0) | 831 | if (size % Memory::PAGE_SIZE != 0) |
| 796 | return ResultCode(ErrorDescription::MisalignedSize, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); | 832 | return ResultCode(ErrorDescription::MisalignedSize, ErrorModule::OS, |
| 833 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); | ||
| 797 | 834 | ||
| 798 | SharedPtr<SharedMemory> shared_memory = nullptr; | 835 | SharedPtr<SharedMemory> shared_memory = nullptr; |
| 799 | 836 | ||
| @@ -818,25 +855,29 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 | |||
| 818 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); | 855 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); |
| 819 | 856 | ||
| 820 | if (addr < Memory::PROCESS_IMAGE_VADDR || addr + size > Memory::SHARED_MEMORY_VADDR_END) { | 857 | if (addr < Memory::PROCESS_IMAGE_VADDR || addr + size > Memory::SHARED_MEMORY_VADDR_END) { |
| 821 | return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); | 858 | return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, |
| 859 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); | ||
| 822 | } | 860 | } |
| 823 | 861 | ||
| 824 | // When trying to create a memory block with address = 0, | 862 | // When trying to create a memory block with address = 0, |
| 825 | // if the process has the Shared Device Memory flag in the exheader, | 863 | // if the process has the Shared Device Memory flag in the exheader, |
| 826 | // then we have to allocate from the same region as the caller process instead of the BASE region. | 864 | // then we have to allocate from the same region as the caller process instead of the BASE |
| 865 | // region. | ||
| 827 | Kernel::MemoryRegion region = Kernel::MemoryRegion::BASE; | 866 | Kernel::MemoryRegion region = Kernel::MemoryRegion::BASE; |
| 828 | if (addr == 0 && Kernel::g_current_process->flags.shared_device_mem) | 867 | if (addr == 0 && Kernel::g_current_process->flags.shared_device_mem) |
| 829 | region = Kernel::g_current_process->flags.memory_region; | 868 | region = Kernel::g_current_process->flags.memory_region; |
| 830 | 869 | ||
| 831 | shared_memory = SharedMemory::Create(Kernel::g_current_process, size, | 870 | shared_memory = SharedMemory::Create( |
| 832 | static_cast<MemoryPermission>(my_permission), static_cast<MemoryPermission>(other_permission), addr, region); | 871 | Kernel::g_current_process, size, static_cast<MemoryPermission>(my_permission), |
| 872 | static_cast<MemoryPermission>(other_permission), addr, region); | ||
| 833 | CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory))); | 873 | CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory))); |
| 834 | 874 | ||
| 835 | LOG_WARNING(Kernel_SVC, "called addr=0x%08X", addr); | 875 | LOG_WARNING(Kernel_SVC, "called addr=0x%08X", addr); |
| 836 | return RESULT_SUCCESS; | 876 | return RESULT_SUCCESS; |
| 837 | } | 877 | } |
| 838 | 878 | ||
| 839 | static ResultCode CreatePort(Handle* server_port, Handle* client_port, const char* name, u32 max_sessions) { | 879 | static ResultCode CreatePort(Handle* server_port, Handle* client_port, const char* name, |
| 880 | u32 max_sessions) { | ||
| 840 | // TODO(Subv): Implement named ports. | 881 | // TODO(Subv): Implement named ports. |
| 841 | ASSERT_MSG(name == nullptr, "Named ports are currently unimplemented"); | 882 | ASSERT_MSG(name == nullptr, "Named ports are currently unimplemented"); |
| 842 | 883 | ||
| @@ -845,9 +886,12 @@ static ResultCode CreatePort(Handle* server_port, Handle* client_port, const cha | |||
| 845 | using Kernel::SharedPtr; | 886 | using Kernel::SharedPtr; |
| 846 | 887 | ||
| 847 | auto ports = ServerPort::CreatePortPair(max_sessions); | 888 | auto ports = ServerPort::CreatePortPair(max_sessions); |
| 848 | CASCADE_RESULT(*client_port, Kernel::g_handle_table.Create(std::move(std::get<SharedPtr<ClientPort>>(ports)))); | 889 | CASCADE_RESULT(*client_port, Kernel::g_handle_table.Create( |
| 849 | // Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be created. | 890 | std::move(std::get<SharedPtr<ClientPort>>(ports)))); |
| 850 | CASCADE_RESULT(*server_port, Kernel::g_handle_table.Create(std::move(std::get<SharedPtr<ServerPort>>(ports)))); | 891 | // Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be |
| 892 | // created. | ||
| 893 | CASCADE_RESULT(*server_port, Kernel::g_handle_table.Create( | ||
| 894 | std::move(std::get<SharedPtr<ServerPort>>(ports)))); | ||
| 851 | 895 | ||
| 852 | LOG_TRACE(Kernel_SVC, "called max_sessions=%u", max_sessions); | 896 | LOG_TRACE(Kernel_SVC, "called max_sessions=%u", max_sessions); |
| 853 | return RESULT_SUCCESS; | 897 | return RESULT_SUCCESS; |
| @@ -862,9 +906,9 @@ static ResultCode GetSystemInfo(s64* out, u32 type, s32 param) { | |||
| 862 | case SystemInfoType::REGION_MEMORY_USAGE: | 906 | case SystemInfoType::REGION_MEMORY_USAGE: |
| 863 | switch ((SystemInfoMemUsageRegion)param) { | 907 | switch ((SystemInfoMemUsageRegion)param) { |
| 864 | case SystemInfoMemUsageRegion::ALL: | 908 | case SystemInfoMemUsageRegion::ALL: |
| 865 | *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used | 909 | *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used + |
| 866 | + Kernel::GetMemoryRegion(Kernel::MemoryRegion::SYSTEM)->used | 910 | Kernel::GetMemoryRegion(Kernel::MemoryRegion::SYSTEM)->used + |
| 867 | + Kernel::GetMemoryRegion(Kernel::MemoryRegion::BASE)->used; | 911 | Kernel::GetMemoryRegion(Kernel::MemoryRegion::BASE)->used; |
| 868 | break; | 912 | break; |
| 869 | case SystemInfoMemUsageRegion::APPLICATION: | 913 | case SystemInfoMemUsageRegion::APPLICATION: |
| 870 | *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used; | 914 | *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used; |
| @@ -912,7 +956,7 @@ static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) { | |||
| 912 | // TODO(yuriks): Type 0 returns a slightly higher number than type 2, but I'm not sure | 956 | // TODO(yuriks): Type 0 returns a slightly higher number than type 2, but I'm not sure |
| 913 | // what's the difference between them. | 957 | // what's the difference between them. |
| 914 | *out = process->heap_used + process->linear_heap_used + process->misc_memory_used; | 958 | *out = process->heap_used + process->linear_heap_used + process->misc_memory_used; |
| 915 | if(*out % Memory::PAGE_SIZE != 0) { | 959 | if (*out % Memory::PAGE_SIZE != 0) { |
| 916 | LOG_ERROR(Kernel_SVC, "called, memory size not page-aligned"); | 960 | LOG_ERROR(Kernel_SVC, "called, memory size not page-aligned"); |
| 917 | return ERR_MISALIGNED_SIZE; | 961 | return ERR_MISALIGNED_SIZE; |
| 918 | } | 962 | } |
| @@ -935,12 +979,12 @@ static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) { | |||
| 935 | 979 | ||
| 936 | if (type >= 21 && type <= 23) { | 980 | if (type >= 21 && type <= 23) { |
| 937 | return ResultCode( // 0xE0E01BF4 | 981 | return ResultCode( // 0xE0E01BF4 |
| 938 | ErrorDescription::NotImplemented, ErrorModule::OS, | 982 | ErrorDescription::NotImplemented, ErrorModule::OS, ErrorSummary::InvalidArgument, |
| 939 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); | 983 | ErrorLevel::Usage); |
| 940 | } else { | 984 | } else { |
| 941 | return ResultCode( // 0xD8E007ED | 985 | return ResultCode( // 0xD8E007ED |
| 942 | ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, | 986 | ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, |
| 943 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); | 987 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); |
| 944 | } | 988 | } |
| 945 | break; | 989 | break; |
| 946 | } | 990 | } |
| @@ -949,142 +993,142 @@ static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) { | |||
| 949 | } | 993 | } |
| 950 | 994 | ||
| 951 | namespace { | 995 | namespace { |
| 952 | struct FunctionDef { | 996 | struct FunctionDef { |
| 953 | using Func = void(); | 997 | using Func = void(); |
| 954 | 998 | ||
| 955 | u32 id; | 999 | u32 id; |
| 956 | Func* func; | 1000 | Func* func; |
| 957 | const char* name; | 1001 | const char* name; |
| 958 | }; | 1002 | }; |
| 959 | } | 1003 | } |
| 960 | 1004 | ||
| 961 | static const FunctionDef SVC_Table[] = { | 1005 | static const FunctionDef SVC_Table[] = { |
| 962 | {0x00, nullptr, "Unknown"}, | 1006 | {0x00, nullptr, "Unknown"}, |
| 963 | {0x01, HLE::Wrap<ControlMemory>, "ControlMemory"}, | 1007 | {0x01, HLE::Wrap<ControlMemory>, "ControlMemory"}, |
| 964 | {0x02, HLE::Wrap<QueryMemory>, "QueryMemory"}, | 1008 | {0x02, HLE::Wrap<QueryMemory>, "QueryMemory"}, |
| 965 | {0x03, nullptr, "ExitProcess"}, | 1009 | {0x03, nullptr, "ExitProcess"}, |
| 966 | {0x04, nullptr, "GetProcessAffinityMask"}, | 1010 | {0x04, nullptr, "GetProcessAffinityMask"}, |
| 967 | {0x05, nullptr, "SetProcessAffinityMask"}, | 1011 | {0x05, nullptr, "SetProcessAffinityMask"}, |
| 968 | {0x06, nullptr, "GetProcessIdealProcessor"}, | 1012 | {0x06, nullptr, "GetProcessIdealProcessor"}, |
| 969 | {0x07, nullptr, "SetProcessIdealProcessor"}, | 1013 | {0x07, nullptr, "SetProcessIdealProcessor"}, |
| 970 | {0x08, HLE::Wrap<CreateThread>, "CreateThread"}, | 1014 | {0x08, HLE::Wrap<CreateThread>, "CreateThread"}, |
| 971 | {0x09, ExitThread, "ExitThread"}, | 1015 | {0x09, ExitThread, "ExitThread"}, |
| 972 | {0x0A, HLE::Wrap<SleepThread>, "SleepThread"}, | 1016 | {0x0A, HLE::Wrap<SleepThread>, "SleepThread"}, |
| 973 | {0x0B, HLE::Wrap<GetThreadPriority>, "GetThreadPriority"}, | 1017 | {0x0B, HLE::Wrap<GetThreadPriority>, "GetThreadPriority"}, |
| 974 | {0x0C, HLE::Wrap<SetThreadPriority>, "SetThreadPriority"}, | 1018 | {0x0C, HLE::Wrap<SetThreadPriority>, "SetThreadPriority"}, |
| 975 | {0x0D, nullptr, "GetThreadAffinityMask"}, | 1019 | {0x0D, nullptr, "GetThreadAffinityMask"}, |
| 976 | {0x0E, nullptr, "SetThreadAffinityMask"}, | 1020 | {0x0E, nullptr, "SetThreadAffinityMask"}, |
| 977 | {0x0F, nullptr, "GetThreadIdealProcessor"}, | 1021 | {0x0F, nullptr, "GetThreadIdealProcessor"}, |
| 978 | {0x10, nullptr, "SetThreadIdealProcessor"}, | 1022 | {0x10, nullptr, "SetThreadIdealProcessor"}, |
| 979 | {0x11, nullptr, "GetCurrentProcessorNumber"}, | 1023 | {0x11, nullptr, "GetCurrentProcessorNumber"}, |
| 980 | {0x12, nullptr, "Run"}, | 1024 | {0x12, nullptr, "Run"}, |
| 981 | {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"}, | 1025 | {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"}, |
| 982 | {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"}, | 1026 | {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"}, |
| 983 | {0x15, HLE::Wrap<CreateSemaphore>, "CreateSemaphore"}, | 1027 | {0x15, HLE::Wrap<CreateSemaphore>, "CreateSemaphore"}, |
| 984 | {0x16, HLE::Wrap<ReleaseSemaphore>, "ReleaseSemaphore"}, | 1028 | {0x16, HLE::Wrap<ReleaseSemaphore>, "ReleaseSemaphore"}, |
| 985 | {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"}, | 1029 | {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"}, |
| 986 | {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"}, | 1030 | {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"}, |
| 987 | {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"}, | 1031 | {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"}, |
| 988 | {0x1A, HLE::Wrap<CreateTimer>, "CreateTimer"}, | 1032 | {0x1A, HLE::Wrap<CreateTimer>, "CreateTimer"}, |
| 989 | {0x1B, HLE::Wrap<SetTimer>, "SetTimer"}, | 1033 | {0x1B, HLE::Wrap<SetTimer>, "SetTimer"}, |
| 990 | {0x1C, HLE::Wrap<CancelTimer>, "CancelTimer"}, | 1034 | {0x1C, HLE::Wrap<CancelTimer>, "CancelTimer"}, |
| 991 | {0x1D, HLE::Wrap<ClearTimer>, "ClearTimer"}, | 1035 | {0x1D, HLE::Wrap<ClearTimer>, "ClearTimer"}, |
| 992 | {0x1E, HLE::Wrap<CreateMemoryBlock>, "CreateMemoryBlock"}, | 1036 | {0x1E, HLE::Wrap<CreateMemoryBlock>, "CreateMemoryBlock"}, |
| 993 | {0x1F, HLE::Wrap<MapMemoryBlock>, "MapMemoryBlock"}, | 1037 | {0x1F, HLE::Wrap<MapMemoryBlock>, "MapMemoryBlock"}, |
| 994 | {0x20, HLE::Wrap<UnmapMemoryBlock>, "UnmapMemoryBlock"}, | 1038 | {0x20, HLE::Wrap<UnmapMemoryBlock>, "UnmapMemoryBlock"}, |
| 995 | {0x21, HLE::Wrap<CreateAddressArbiter>, "CreateAddressArbiter"}, | 1039 | {0x21, HLE::Wrap<CreateAddressArbiter>, "CreateAddressArbiter"}, |
| 996 | {0x22, HLE::Wrap<ArbitrateAddress>, "ArbitrateAddress"}, | 1040 | {0x22, HLE::Wrap<ArbitrateAddress>, "ArbitrateAddress"}, |
| 997 | {0x23, HLE::Wrap<CloseHandle>, "CloseHandle"}, | 1041 | {0x23, HLE::Wrap<CloseHandle>, "CloseHandle"}, |
| 998 | {0x24, HLE::Wrap<WaitSynchronization1>, "WaitSynchronization1"}, | 1042 | {0x24, HLE::Wrap<WaitSynchronization1>, "WaitSynchronization1"}, |
| 999 | {0x25, HLE::Wrap<WaitSynchronizationN>, "WaitSynchronizationN"}, | 1043 | {0x25, HLE::Wrap<WaitSynchronizationN>, "WaitSynchronizationN"}, |
| 1000 | {0x26, nullptr, "SignalAndWait"}, | 1044 | {0x26, nullptr, "SignalAndWait"}, |
| 1001 | {0x27, HLE::Wrap<DuplicateHandle>, "DuplicateHandle"}, | 1045 | {0x27, HLE::Wrap<DuplicateHandle>, "DuplicateHandle"}, |
| 1002 | {0x28, HLE::Wrap<GetSystemTick>, "GetSystemTick"}, | 1046 | {0x28, HLE::Wrap<GetSystemTick>, "GetSystemTick"}, |
| 1003 | {0x29, nullptr, "GetHandleInfo"}, | 1047 | {0x29, nullptr, "GetHandleInfo"}, |
| 1004 | {0x2A, HLE::Wrap<GetSystemInfo>, "GetSystemInfo"}, | 1048 | {0x2A, HLE::Wrap<GetSystemInfo>, "GetSystemInfo"}, |
| 1005 | {0x2B, HLE::Wrap<GetProcessInfo>, "GetProcessInfo"}, | 1049 | {0x2B, HLE::Wrap<GetProcessInfo>, "GetProcessInfo"}, |
| 1006 | {0x2C, nullptr, "GetThreadInfo"}, | 1050 | {0x2C, nullptr, "GetThreadInfo"}, |
| 1007 | {0x2D, HLE::Wrap<ConnectToPort>, "ConnectToPort"}, | 1051 | {0x2D, HLE::Wrap<ConnectToPort>, "ConnectToPort"}, |
| 1008 | {0x2E, nullptr, "SendSyncRequest1"}, | 1052 | {0x2E, nullptr, "SendSyncRequest1"}, |
| 1009 | {0x2F, nullptr, "SendSyncRequest2"}, | 1053 | {0x2F, nullptr, "SendSyncRequest2"}, |
| 1010 | {0x30, nullptr, "SendSyncRequest3"}, | 1054 | {0x30, nullptr, "SendSyncRequest3"}, |
| 1011 | {0x31, nullptr, "SendSyncRequest4"}, | 1055 | {0x31, nullptr, "SendSyncRequest4"}, |
| 1012 | {0x32, HLE::Wrap<SendSyncRequest>, "SendSyncRequest"}, | 1056 | {0x32, HLE::Wrap<SendSyncRequest>, "SendSyncRequest"}, |
| 1013 | {0x33, nullptr, "OpenProcess"}, | 1057 | {0x33, nullptr, "OpenProcess"}, |
| 1014 | {0x34, nullptr, "OpenThread"}, | 1058 | {0x34, nullptr, "OpenThread"}, |
| 1015 | {0x35, HLE::Wrap<GetProcessId>, "GetProcessId"}, | 1059 | {0x35, HLE::Wrap<GetProcessId>, "GetProcessId"}, |
| 1016 | {0x36, HLE::Wrap<GetProcessIdOfThread>, "GetProcessIdOfThread"}, | 1060 | {0x36, HLE::Wrap<GetProcessIdOfThread>, "GetProcessIdOfThread"}, |
| 1017 | {0x37, HLE::Wrap<GetThreadId>, "GetThreadId"}, | 1061 | {0x37, HLE::Wrap<GetThreadId>, "GetThreadId"}, |
| 1018 | {0x38, HLE::Wrap<GetResourceLimit>, "GetResourceLimit"}, | 1062 | {0x38, HLE::Wrap<GetResourceLimit>, "GetResourceLimit"}, |
| 1019 | {0x39, HLE::Wrap<GetResourceLimitLimitValues>, "GetResourceLimitLimitValues"}, | 1063 | {0x39, HLE::Wrap<GetResourceLimitLimitValues>, "GetResourceLimitLimitValues"}, |
| 1020 | {0x3A, HLE::Wrap<GetResourceLimitCurrentValues>, "GetResourceLimitCurrentValues"}, | 1064 | {0x3A, HLE::Wrap<GetResourceLimitCurrentValues>, "GetResourceLimitCurrentValues"}, |
| 1021 | {0x3B, nullptr, "GetThreadContext"}, | 1065 | {0x3B, nullptr, "GetThreadContext"}, |
| 1022 | {0x3C, HLE::Wrap<Break>, "Break"}, | 1066 | {0x3C, HLE::Wrap<Break>, "Break"}, |
| 1023 | {0x3D, HLE::Wrap<OutputDebugString>, "OutputDebugString"}, | 1067 | {0x3D, HLE::Wrap<OutputDebugString>, "OutputDebugString"}, |
| 1024 | {0x3E, nullptr, "ControlPerformanceCounter"}, | 1068 | {0x3E, nullptr, "ControlPerformanceCounter"}, |
| 1025 | {0x3F, nullptr, "Unknown"}, | 1069 | {0x3F, nullptr, "Unknown"}, |
| 1026 | {0x40, nullptr, "Unknown"}, | 1070 | {0x40, nullptr, "Unknown"}, |
| 1027 | {0x41, nullptr, "Unknown"}, | 1071 | {0x41, nullptr, "Unknown"}, |
| 1028 | {0x42, nullptr, "Unknown"}, | 1072 | {0x42, nullptr, "Unknown"}, |
| 1029 | {0x43, nullptr, "Unknown"}, | 1073 | {0x43, nullptr, "Unknown"}, |
| 1030 | {0x44, nullptr, "Unknown"}, | 1074 | {0x44, nullptr, "Unknown"}, |
| 1031 | {0x45, nullptr, "Unknown"}, | 1075 | {0x45, nullptr, "Unknown"}, |
| 1032 | {0x46, nullptr, "Unknown"}, | 1076 | {0x46, nullptr, "Unknown"}, |
| 1033 | {0x47, HLE::Wrap<CreatePort>, "CreatePort"}, | 1077 | {0x47, HLE::Wrap<CreatePort>, "CreatePort"}, |
| 1034 | {0x48, nullptr, "CreateSessionToPort"}, | 1078 | {0x48, nullptr, "CreateSessionToPort"}, |
| 1035 | {0x49, nullptr, "CreateSession"}, | 1079 | {0x49, nullptr, "CreateSession"}, |
| 1036 | {0x4A, nullptr, "AcceptSession"}, | 1080 | {0x4A, nullptr, "AcceptSession"}, |
| 1037 | {0x4B, nullptr, "ReplyAndReceive1"}, | 1081 | {0x4B, nullptr, "ReplyAndReceive1"}, |
| 1038 | {0x4C, nullptr, "ReplyAndReceive2"}, | 1082 | {0x4C, nullptr, "ReplyAndReceive2"}, |
| 1039 | {0x4D, nullptr, "ReplyAndReceive3"}, | 1083 | {0x4D, nullptr, "ReplyAndReceive3"}, |
| 1040 | {0x4E, nullptr, "ReplyAndReceive4"}, | 1084 | {0x4E, nullptr, "ReplyAndReceive4"}, |
| 1041 | {0x4F, nullptr, "ReplyAndReceive"}, | 1085 | {0x4F, nullptr, "ReplyAndReceive"}, |
| 1042 | {0x50, nullptr, "BindInterrupt"}, | 1086 | {0x50, nullptr, "BindInterrupt"}, |
| 1043 | {0x51, nullptr, "UnbindInterrupt"}, | 1087 | {0x51, nullptr, "UnbindInterrupt"}, |
| 1044 | {0x52, nullptr, "InvalidateProcessDataCache"}, | 1088 | {0x52, nullptr, "InvalidateProcessDataCache"}, |
| 1045 | {0x53, nullptr, "StoreProcessDataCache"}, | 1089 | {0x53, nullptr, "StoreProcessDataCache"}, |
| 1046 | {0x54, nullptr, "FlushProcessDataCache"}, | 1090 | {0x54, nullptr, "FlushProcessDataCache"}, |
| 1047 | {0x55, nullptr, "StartInterProcessDma"}, | 1091 | {0x55, nullptr, "StartInterProcessDma"}, |
| 1048 | {0x56, nullptr, "StopDma"}, | 1092 | {0x56, nullptr, "StopDma"}, |
| 1049 | {0x57, nullptr, "GetDmaState"}, | 1093 | {0x57, nullptr, "GetDmaState"}, |
| 1050 | {0x58, nullptr, "RestartDma"}, | 1094 | {0x58, nullptr, "RestartDma"}, |
| 1051 | {0x59, nullptr, "Unknown"}, | 1095 | {0x59, nullptr, "Unknown"}, |
| 1052 | {0x5A, nullptr, "Unknown"}, | 1096 | {0x5A, nullptr, "Unknown"}, |
| 1053 | {0x5B, nullptr, "Unknown"}, | 1097 | {0x5B, nullptr, "Unknown"}, |
| 1054 | {0x5C, nullptr, "Unknown"}, | 1098 | {0x5C, nullptr, "Unknown"}, |
| 1055 | {0x5D, nullptr, "Unknown"}, | 1099 | {0x5D, nullptr, "Unknown"}, |
| 1056 | {0x5E, nullptr, "Unknown"}, | 1100 | {0x5E, nullptr, "Unknown"}, |
| 1057 | {0x5F, nullptr, "Unknown"}, | 1101 | {0x5F, nullptr, "Unknown"}, |
| 1058 | {0x60, nullptr, "DebugActiveProcess"}, | 1102 | {0x60, nullptr, "DebugActiveProcess"}, |
| 1059 | {0x61, nullptr, "BreakDebugProcess"}, | 1103 | {0x61, nullptr, "BreakDebugProcess"}, |
| 1060 | {0x62, nullptr, "TerminateDebugProcess"}, | 1104 | {0x62, nullptr, "TerminateDebugProcess"}, |
| 1061 | {0x63, nullptr, "GetProcessDebugEvent"}, | 1105 | {0x63, nullptr, "GetProcessDebugEvent"}, |
| 1062 | {0x64, nullptr, "ContinueDebugEvent"}, | 1106 | {0x64, nullptr, "ContinueDebugEvent"}, |
| 1063 | {0x65, nullptr, "GetProcessList"}, | 1107 | {0x65, nullptr, "GetProcessList"}, |
| 1064 | {0x66, nullptr, "GetThreadList"}, | 1108 | {0x66, nullptr, "GetThreadList"}, |
| 1065 | {0x67, nullptr, "GetDebugThreadContext"}, | 1109 | {0x67, nullptr, "GetDebugThreadContext"}, |
| 1066 | {0x68, nullptr, "SetDebugThreadContext"}, | 1110 | {0x68, nullptr, "SetDebugThreadContext"}, |
| 1067 | {0x69, nullptr, "QueryDebugProcessMemory"}, | 1111 | {0x69, nullptr, "QueryDebugProcessMemory"}, |
| 1068 | {0x6A, nullptr, "ReadProcessMemory"}, | 1112 | {0x6A, nullptr, "ReadProcessMemory"}, |
| 1069 | {0x6B, nullptr, "WriteProcessMemory"}, | 1113 | {0x6B, nullptr, "WriteProcessMemory"}, |
| 1070 | {0x6C, nullptr, "SetHardwareBreakPoint"}, | 1114 | {0x6C, nullptr, "SetHardwareBreakPoint"}, |
| 1071 | {0x6D, nullptr, "GetDebugThreadParam"}, | 1115 | {0x6D, nullptr, "GetDebugThreadParam"}, |
| 1072 | {0x6E, nullptr, "Unknown"}, | 1116 | {0x6E, nullptr, "Unknown"}, |
| 1073 | {0x6F, nullptr, "Unknown"}, | 1117 | {0x6F, nullptr, "Unknown"}, |
| 1074 | {0x70, nullptr, "ControlProcessMemory"}, | 1118 | {0x70, nullptr, "ControlProcessMemory"}, |
| 1075 | {0x71, nullptr, "MapProcessMemory"}, | 1119 | {0x71, nullptr, "MapProcessMemory"}, |
| 1076 | {0x72, nullptr, "UnmapProcessMemory"}, | 1120 | {0x72, nullptr, "UnmapProcessMemory"}, |
| 1077 | {0x73, nullptr, "CreateCodeSet"}, | 1121 | {0x73, nullptr, "CreateCodeSet"}, |
| 1078 | {0x74, nullptr, "RandomStub"}, | 1122 | {0x74, nullptr, "RandomStub"}, |
| 1079 | {0x75, nullptr, "CreateProcess"}, | 1123 | {0x75, nullptr, "CreateProcess"}, |
| 1080 | {0x76, nullptr, "TerminateProcess"}, | 1124 | {0x76, nullptr, "TerminateProcess"}, |
| 1081 | {0x77, nullptr, "SetProcessResourceLimits"}, | 1125 | {0x77, nullptr, "SetProcessResourceLimits"}, |
| 1082 | {0x78, nullptr, "CreateResourceLimit"}, | 1126 | {0x78, nullptr, "CreateResourceLimit"}, |
| 1083 | {0x79, nullptr, "SetResourceLimitValues"}, | 1127 | {0x79, nullptr, "SetResourceLimitValues"}, |
| 1084 | {0x7A, nullptr, "AddCodeSegment"}, | 1128 | {0x7A, nullptr, "AddCodeSegment"}, |
| 1085 | {0x7B, nullptr, "Backdoor"}, | 1129 | {0x7B, nullptr, "Backdoor"}, |
| 1086 | {0x7C, nullptr, "KernelSetState"}, | 1130 | {0x7C, nullptr, "KernelSetState"}, |
| 1087 | {0x7D, HLE::Wrap<QueryProcessMemory>, "QueryProcessMemory"}, | 1131 | {0x7D, HLE::Wrap<QueryProcessMemory>, "QueryProcessMemory"}, |
| 1088 | }; | 1132 | }; |
| 1089 | 1133 | ||
| 1090 | static const FunctionDef* GetSVCInfo(u32 func_num) { | 1134 | static const FunctionDef* GetSVCInfo(u32 func_num) { |
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index a4dfb7e43..bf2c066f4 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp | |||
| @@ -12,15 +12,15 @@ | |||
| 12 | #include "common/microprofile.h" | 12 | #include "common/microprofile.h" |
| 13 | #include "common/vector_math.h" | 13 | #include "common/vector_math.h" |
| 14 | 14 | ||
| 15 | #include "core/settings.h" | ||
| 16 | #include "core/memory.h" | ||
| 17 | #include "core/core_timing.h" | 15 | #include "core/core_timing.h" |
| 16 | #include "core/memory.h" | ||
| 17 | #include "core/settings.h" | ||
| 18 | 18 | ||
| 19 | #include "core/hle/service/gsp_gpu.h" | 19 | #include "core/hle/service/gsp_gpu.h" |
| 20 | #include "core/hle/service/hid/hid.h" | 20 | #include "core/hle/service/hid/hid.h" |
| 21 | 21 | ||
| 22 | #include "core/hw/hw.h" | ||
| 23 | #include "core/hw/gpu.h" | 22 | #include "core/hw/gpu.h" |
| 23 | #include "core/hw/hw.h" | ||
| 24 | 24 | ||
| 25 | #include "core/tracer/recorder.h" | 25 | #include "core/tracer/recorder.h" |
| 26 | 26 | ||
| @@ -32,7 +32,6 @@ | |||
| 32 | 32 | ||
| 33 | #include "video_core/debug_utils/debug_utils.h" | 33 | #include "video_core/debug_utils/debug_utils.h" |
| 34 | 34 | ||
| 35 | |||
| 36 | namespace GPU { | 35 | namespace GPU { |
| 37 | 36 | ||
| 38 | Regs g_regs; | 37 | Regs g_regs; |
| @@ -49,7 +48,7 @@ static u64 frame_count; | |||
| 49 | static bool last_skip_frame; | 48 | static bool last_skip_frame; |
| 50 | 49 | ||
| 51 | template <typename T> | 50 | template <typename T> |
| 52 | inline void Read(T &var, const u32 raw_addr) { | 51 | inline void Read(T& var, const u32 raw_addr) { |
| 53 | u32 addr = raw_addr - HW::VADDR_GPU; | 52 | u32 addr = raw_addr - HW::VADDR_GPU; |
| 54 | u32 index = addr / 4; | 53 | u32 index = addr / 4; |
| 55 | 54 | ||
| @@ -105,8 +104,7 @@ inline void Write(u32 addr, const T data) { | |||
| 105 | 104 | ||
| 106 | // Memory fills are triggered once the fill value is written. | 105 | // Memory fills are triggered once the fill value is written. |
| 107 | case GPU_REG_INDEX_WORKAROUND(memory_fill_config[0].trigger, 0x00004 + 0x3): | 106 | case GPU_REG_INDEX_WORKAROUND(memory_fill_config[0].trigger, 0x00004 + 0x3): |
| 108 | case GPU_REG_INDEX_WORKAROUND(memory_fill_config[1].trigger, 0x00008 + 0x3): | 107 | case GPU_REG_INDEX_WORKAROUND(memory_fill_config[1].trigger, 0x00008 + 0x3): { |
| 109 | { | ||
| 110 | const bool is_second_filler = (index != GPU_REG_INDEX(memory_fill_config[0].trigger)); | 108 | const bool is_second_filler = (index != GPU_REG_INDEX(memory_fill_config[0].trigger)); |
| 111 | auto& config = g_regs.memory_fill_config[is_second_filler]; | 109 | auto& config = g_regs.memory_fill_config[is_second_filler]; |
| 112 | 110 | ||
| @@ -125,7 +123,9 @@ inline void Write(u32 addr, const T data) { | |||
| 125 | // regions that were between surfaces or within the touching | 123 | // regions that were between surfaces or within the touching |
| 126 | // ones for cpu to manually fill here. | 124 | // ones for cpu to manually fill here. |
| 127 | if (!VideoCore::g_renderer->Rasterizer()->AccelerateFill(config)) { | 125 | if (!VideoCore::g_renderer->Rasterizer()->AccelerateFill(config)) { |
| 128 | Memory::RasterizerFlushAndInvalidateRegion(config.GetStartAddress(), config.GetEndAddress() - config.GetStartAddress()); | 126 | Memory::RasterizerFlushAndInvalidateRegion(config.GetStartAddress(), |
| 127 | config.GetEndAddress() - | ||
| 128 | config.GetStartAddress()); | ||
| 129 | 129 | ||
| 130 | if (config.fill_24bit) { | 130 | if (config.fill_24bit) { |
| 131 | // fill with 24-bit values | 131 | // fill with 24-bit values |
| @@ -150,7 +150,8 @@ inline void Write(u32 addr, const T data) { | |||
| 150 | } | 150 | } |
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | LOG_TRACE(HW_GPU, "MemoryFill from 0x%08x to 0x%08x", config.GetStartAddress(), config.GetEndAddress()); | 153 | LOG_TRACE(HW_GPU, "MemoryFill from 0x%08x to 0x%08x", config.GetStartAddress(), |
| 154 | config.GetEndAddress()); | ||
| 154 | 155 | ||
| 155 | if (!is_second_filler) { | 156 | if (!is_second_filler) { |
| 156 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC0); | 157 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC0); |
| @@ -167,15 +168,15 @@ inline void Write(u32 addr, const T data) { | |||
| 167 | break; | 168 | break; |
| 168 | } | 169 | } |
| 169 | 170 | ||
| 170 | case GPU_REG_INDEX(display_transfer_config.trigger): | 171 | case GPU_REG_INDEX(display_transfer_config.trigger): { |
| 171 | { | ||
| 172 | MICROPROFILE_SCOPE(GPU_DisplayTransfer); | 172 | MICROPROFILE_SCOPE(GPU_DisplayTransfer); |
| 173 | 173 | ||
| 174 | const auto& config = g_regs.display_transfer_config; | 174 | const auto& config = g_regs.display_transfer_config; |
| 175 | if (config.trigger & 1) { | 175 | if (config.trigger & 1) { |
| 176 | 176 | ||
| 177 | if (Pica::g_debug_context) | 177 | if (Pica::g_debug_context) |
| 178 | Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::IncomingDisplayTransfer, nullptr); | 178 | Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::IncomingDisplayTransfer, |
| 179 | nullptr); | ||
| 179 | 180 | ||
| 180 | if (!VideoCore::g_renderer->Rasterizer()->AccelerateDisplayTransfer(config)) { | 181 | if (!VideoCore::g_renderer->Rasterizer()->AccelerateDisplayTransfer(config)) { |
| 181 | u8* src_pointer = Memory::GetPhysicalPointer(config.GetPhysicalInputAddress()); | 182 | u8* src_pointer = Memory::GetPhysicalPointer(config.GetPhysicalInputAddress()); |
| @@ -187,17 +188,23 @@ inline void Write(u32 addr, const T data) { | |||
| 187 | u32 output_width = config.texture_copy.output_width * 16; | 188 | u32 output_width = config.texture_copy.output_width * 16; |
| 188 | u32 output_gap = config.texture_copy.output_gap * 16; | 189 | u32 output_gap = config.texture_copy.output_gap * 16; |
| 189 | 190 | ||
| 190 | size_t contiguous_input_size = config.texture_copy.size / input_width * (input_width + input_gap); | 191 | size_t contiguous_input_size = |
| 191 | Memory::RasterizerFlushRegion(config.GetPhysicalInputAddress(), static_cast<u32>(contiguous_input_size)); | 192 | config.texture_copy.size / input_width * (input_width + input_gap); |
| 193 | Memory::RasterizerFlushRegion(config.GetPhysicalInputAddress(), | ||
| 194 | static_cast<u32>(contiguous_input_size)); | ||
| 192 | 195 | ||
| 193 | size_t contiguous_output_size = config.texture_copy.size / output_width * (output_width + output_gap); | 196 | size_t contiguous_output_size = |
| 194 | Memory::RasterizerFlushAndInvalidateRegion(config.GetPhysicalOutputAddress(), static_cast<u32>(contiguous_output_size)); | 197 | config.texture_copy.size / output_width * (output_width + output_gap); |
| 198 | Memory::RasterizerFlushAndInvalidateRegion( | ||
| 199 | config.GetPhysicalOutputAddress(), | ||
| 200 | static_cast<u32>(contiguous_output_size)); | ||
| 195 | 201 | ||
| 196 | u32 remaining_size = config.texture_copy.size; | 202 | u32 remaining_size = config.texture_copy.size; |
| 197 | u32 remaining_input = input_width; | 203 | u32 remaining_input = input_width; |
| 198 | u32 remaining_output = output_width; | 204 | u32 remaining_output = output_width; |
| 199 | while (remaining_size > 0) { | 205 | while (remaining_size > 0) { |
| 200 | u32 copy_size = std::min({ remaining_input, remaining_output, remaining_size }); | 206 | u32 copy_size = |
| 207 | std::min({remaining_input, remaining_output, remaining_size}); | ||
| 201 | 208 | ||
| 202 | std::memcpy(dst_pointer, src_pointer, copy_size); | 209 | std::memcpy(dst_pointer, src_pointer, copy_size); |
| 203 | src_pointer += copy_size; | 210 | src_pointer += copy_size; |
| @@ -217,10 +224,11 @@ inline void Write(u32 addr, const T data) { | |||
| 217 | } | 224 | } |
| 218 | } | 225 | } |
| 219 | 226 | ||
| 220 | LOG_TRACE(HW_GPU, "TextureCopy: 0x%X bytes from 0x%08X(%u+%u)-> 0x%08X(%u+%u), flags 0x%08X", | 227 | LOG_TRACE( |
| 221 | config.texture_copy.size, | 228 | HW_GPU, |
| 222 | config.GetPhysicalInputAddress(), input_width, input_gap, | 229 | "TextureCopy: 0x%X bytes from 0x%08X(%u+%u)-> 0x%08X(%u+%u), flags 0x%08X", |
| 223 | config.GetPhysicalOutputAddress(), output_width, output_gap, | 230 | config.texture_copy.size, config.GetPhysicalInputAddress(), input_width, |
| 231 | input_gap, config.GetPhysicalOutputAddress(), output_width, output_gap, | ||
| 224 | config.flags); | 232 | config.flags); |
| 225 | 233 | ||
| 226 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF); | 234 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF); |
| @@ -228,7 +236,8 @@ inline void Write(u32 addr, const T data) { | |||
| 228 | } | 236 | } |
| 229 | 237 | ||
| 230 | if (config.scaling > config.ScaleXY) { | 238 | if (config.scaling > config.ScaleXY) { |
| 231 | LOG_CRITICAL(HW_GPU, "Unimplemented display transfer scaling mode %u", config.scaling.Value()); | 239 | LOG_CRITICAL(HW_GPU, "Unimplemented display transfer scaling mode %u", |
| 240 | config.scaling.Value()); | ||
| 232 | UNIMPLEMENTED(); | 241 | UNIMPLEMENTED(); |
| 233 | break; | 242 | break; |
| 234 | } | 243 | } |
| @@ -245,11 +254,14 @@ inline void Write(u32 addr, const T data) { | |||
| 245 | u32 output_width = config.output_width >> horizontal_scale; | 254 | u32 output_width = config.output_width >> horizontal_scale; |
| 246 | u32 output_height = config.output_height >> vertical_scale; | 255 | u32 output_height = config.output_height >> vertical_scale; |
| 247 | 256 | ||
| 248 | u32 input_size = config.input_width * config.input_height * GPU::Regs::BytesPerPixel(config.input_format); | 257 | u32 input_size = config.input_width * config.input_height * |
| 249 | u32 output_size = output_width * output_height * GPU::Regs::BytesPerPixel(config.output_format); | 258 | GPU::Regs::BytesPerPixel(config.input_format); |
| 259 | u32 output_size = | ||
| 260 | output_width * output_height * GPU::Regs::BytesPerPixel(config.output_format); | ||
| 250 | 261 | ||
| 251 | Memory::RasterizerFlushRegion(config.GetPhysicalInputAddress(), input_size); | 262 | Memory::RasterizerFlushRegion(config.GetPhysicalInputAddress(), input_size); |
| 252 | Memory::RasterizerFlushAndInvalidateRegion(config.GetPhysicalOutputAddress(), output_size); | 263 | Memory::RasterizerFlushAndInvalidateRegion(config.GetPhysicalOutputAddress(), |
| 264 | output_size); | ||
| 253 | 265 | ||
| 254 | for (u32 y = 0; y < output_height; ++y) { | 266 | for (u32 y = 0; y < output_height; ++y) { |
| 255 | for (u32 x = 0; x < output_width; ++x) { | 267 | for (u32 x = 0; x < output_width; ++x) { |
| @@ -278,11 +290,14 @@ inline void Write(u32 addr, const T data) { | |||
| 278 | u32 coarse_y = y & ~7; | 290 | u32 coarse_y = y & ~7; |
| 279 | u32 stride = output_width * dst_bytes_per_pixel; | 291 | u32 stride = output_width * dst_bytes_per_pixel; |
| 280 | 292 | ||
| 281 | src_offset = (input_x + input_y * config.input_width) * src_bytes_per_pixel; | 293 | src_offset = |
| 282 | dst_offset = VideoCore::GetMortonOffset(x, y, dst_bytes_per_pixel) + coarse_y * stride; | 294 | (input_x + input_y * config.input_width) * src_bytes_per_pixel; |
| 295 | dst_offset = VideoCore::GetMortonOffset(x, y, dst_bytes_per_pixel) + | ||
| 296 | coarse_y * stride; | ||
| 283 | } else { | 297 | } else { |
| 284 | // Both input and output are linear | 298 | // Both input and output are linear |
| 285 | src_offset = (input_x + input_y * config.input_width) * src_bytes_per_pixel; | 299 | src_offset = |
| 300 | (input_x + input_y * config.input_width) * src_bytes_per_pixel; | ||
| 286 | dst_offset = (x + y * output_width) * dst_bytes_per_pixel; | 301 | dst_offset = (x + y * output_width) * dst_bytes_per_pixel; |
| 287 | } | 302 | } |
| 288 | } else { | 303 | } else { |
| @@ -291,7 +306,9 @@ inline void Write(u32 addr, const T data) { | |||
| 291 | u32 coarse_y = input_y & ~7; | 306 | u32 coarse_y = input_y & ~7; |
| 292 | u32 stride = config.input_width * src_bytes_per_pixel; | 307 | u32 stride = config.input_width * src_bytes_per_pixel; |
| 293 | 308 | ||
| 294 | src_offset = VideoCore::GetMortonOffset(input_x, input_y, src_bytes_per_pixel) + coarse_y * stride; | 309 | src_offset = VideoCore::GetMortonOffset(input_x, input_y, |
| 310 | src_bytes_per_pixel) + | ||
| 311 | coarse_y * stride; | ||
| 295 | dst_offset = (x + y * output_width) * dst_bytes_per_pixel; | 312 | dst_offset = (x + y * output_width) * dst_bytes_per_pixel; |
| 296 | } else { | 313 | } else { |
| 297 | // Both input and output are tiled | 314 | // Both input and output are tiled |
| @@ -301,20 +318,27 @@ inline void Write(u32 addr, const T data) { | |||
| 301 | u32 in_coarse_y = input_y & ~7; | 318 | u32 in_coarse_y = input_y & ~7; |
| 302 | u32 in_stride = config.input_width * src_bytes_per_pixel; | 319 | u32 in_stride = config.input_width * src_bytes_per_pixel; |
| 303 | 320 | ||
| 304 | src_offset = VideoCore::GetMortonOffset(input_x, input_y, src_bytes_per_pixel) + in_coarse_y * in_stride; | 321 | src_offset = VideoCore::GetMortonOffset(input_x, input_y, |
| 305 | dst_offset = VideoCore::GetMortonOffset(x, y, dst_bytes_per_pixel) + out_coarse_y * out_stride; | 322 | src_bytes_per_pixel) + |
| 323 | in_coarse_y * in_stride; | ||
| 324 | dst_offset = VideoCore::GetMortonOffset(x, y, dst_bytes_per_pixel) + | ||
| 325 | out_coarse_y * out_stride; | ||
| 306 | } | 326 | } |
| 307 | } | 327 | } |
| 308 | 328 | ||
| 309 | const u8* src_pixel = src_pointer + src_offset; | 329 | const u8* src_pixel = src_pointer + src_offset; |
| 310 | src_color = DecodePixel(config.input_format, src_pixel); | 330 | src_color = DecodePixel(config.input_format, src_pixel); |
| 311 | if (config.scaling == config.ScaleX) { | 331 | if (config.scaling == config.ScaleX) { |
| 312 | Math::Vec4<u8> pixel = DecodePixel(config.input_format, src_pixel + src_bytes_per_pixel); | 332 | Math::Vec4<u8> pixel = |
| 333 | DecodePixel(config.input_format, src_pixel + src_bytes_per_pixel); | ||
| 313 | src_color = ((src_color + pixel) / 2).Cast<u8>(); | 334 | src_color = ((src_color + pixel) / 2).Cast<u8>(); |
| 314 | } else if (config.scaling == config.ScaleXY) { | 335 | } else if (config.scaling == config.ScaleXY) { |
| 315 | Math::Vec4<u8> pixel1 = DecodePixel(config.input_format, src_pixel + 1 * src_bytes_per_pixel); | 336 | Math::Vec4<u8> pixel1 = DecodePixel( |
| 316 | Math::Vec4<u8> pixel2 = DecodePixel(config.input_format, src_pixel + 2 * src_bytes_per_pixel); | 337 | config.input_format, src_pixel + 1 * src_bytes_per_pixel); |
| 317 | Math::Vec4<u8> pixel3 = DecodePixel(config.input_format, src_pixel + 3 * src_bytes_per_pixel); | 338 | Math::Vec4<u8> pixel2 = DecodePixel( |
| 339 | config.input_format, src_pixel + 2 * src_bytes_per_pixel); | ||
| 340 | Math::Vec4<u8> pixel3 = DecodePixel( | ||
| 341 | config.input_format, src_pixel + 3 * src_bytes_per_pixel); | ||
| 318 | src_color = (((src_color + pixel1) + (pixel2 + pixel3)) / 4).Cast<u8>(); | 342 | src_color = (((src_color + pixel1) + (pixel2 + pixel3)) / 4).Cast<u8>(); |
| 319 | } | 343 | } |
| 320 | 344 | ||
| @@ -341,17 +365,20 @@ inline void Write(u32 addr, const T data) { | |||
| 341 | break; | 365 | break; |
| 342 | 366 | ||
| 343 | default: | 367 | default: |
| 344 | LOG_ERROR(HW_GPU, "Unknown destination framebuffer format %x", config.output_format.Value()); | 368 | LOG_ERROR(HW_GPU, "Unknown destination framebuffer format %x", |
| 369 | config.output_format.Value()); | ||
| 345 | break; | 370 | break; |
| 346 | } | 371 | } |
| 347 | } | 372 | } |
| 348 | } | 373 | } |
| 349 | 374 | ||
| 350 | LOG_TRACE(HW_GPU, "DisplayTriggerTransfer: 0x%08x bytes from 0x%08x(%ux%u)-> 0x%08x(%ux%u), dst format %x, flags 0x%08X", | 375 | LOG_TRACE(HW_GPU, "DisplayTriggerTransfer: 0x%08x bytes from 0x%08x(%ux%u)-> " |
| 351 | config.output_height * output_width * GPU::Regs::BytesPerPixel(config.output_format), | 376 | "0x%08x(%ux%u), dst format %x, flags 0x%08X", |
| 352 | config.GetPhysicalInputAddress(), config.input_width.Value(), config.input_height.Value(), | 377 | config.output_height * output_width * |
| 353 | config.GetPhysicalOutputAddress(), output_width, output_height, | 378 | GPU::Regs::BytesPerPixel(config.output_format), |
| 354 | config.output_format.Value(), config.flags); | 379 | config.GetPhysicalInputAddress(), config.input_width.Value(), |
| 380 | config.input_height.Value(), config.GetPhysicalOutputAddress(), | ||
| 381 | output_width, output_height, config.output_format.Value(), config.flags); | ||
| 355 | } | 382 | } |
| 356 | 383 | ||
| 357 | g_regs.display_transfer_config.trigger = 0; | 384 | g_regs.display_transfer_config.trigger = 0; |
| @@ -361,17 +388,16 @@ inline void Write(u32 addr, const T data) { | |||
| 361 | } | 388 | } |
| 362 | 389 | ||
| 363 | // Seems like writing to this register triggers processing | 390 | // Seems like writing to this register triggers processing |
| 364 | case GPU_REG_INDEX(command_processor_config.trigger): | 391 | case GPU_REG_INDEX(command_processor_config.trigger): { |
| 365 | { | ||
| 366 | const auto& config = g_regs.command_processor_config; | 392 | const auto& config = g_regs.command_processor_config; |
| 367 | if (config.trigger & 1) | 393 | if (config.trigger & 1) { |
| 368 | { | ||
| 369 | MICROPROFILE_SCOPE(GPU_CmdlistProcessing); | 394 | MICROPROFILE_SCOPE(GPU_CmdlistProcessing); |
| 370 | 395 | ||
| 371 | u32* buffer = (u32*)Memory::GetPhysicalPointer(config.GetPhysicalAddress()); | 396 | u32* buffer = (u32*)Memory::GetPhysicalPointer(config.GetPhysicalAddress()); |
| 372 | 397 | ||
| 373 | if (Pica::g_debug_context && Pica::g_debug_context->recorder) { | 398 | if (Pica::g_debug_context && Pica::g_debug_context->recorder) { |
| 374 | Pica::g_debug_context->recorder->MemoryAccessed((u8*)buffer, config.size * sizeof(u32), config.GetPhysicalAddress()); | 399 | Pica::g_debug_context->recorder->MemoryAccessed( |
| 400 | (u8*)buffer, config.size * sizeof(u32), config.GetPhysicalAddress()); | ||
| 375 | } | 401 | } |
| 376 | 402 | ||
| 377 | Pica::CommandProcessor::ProcessCommandList(buffer, config.size); | 403 | Pica::CommandProcessor::ProcessCommandList(buffer, config.size); |
| @@ -389,16 +415,17 @@ inline void Write(u32 addr, const T data) { | |||
| 389 | // This is happening *after* handling the write to make sure we properly catch all memory reads. | 415 | // This is happening *after* handling the write to make sure we properly catch all memory reads. |
| 390 | if (Pica::g_debug_context && Pica::g_debug_context->recorder) { | 416 | if (Pica::g_debug_context && Pica::g_debug_context->recorder) { |
| 391 | // addr + GPU VBase - IO VBase + IO PBase | 417 | // addr + GPU VBase - IO VBase + IO PBase |
| 392 | Pica::g_debug_context->recorder->RegisterWritten<T>(addr + 0x1EF00000 - 0x1EC00000 + 0x10100000, data); | 418 | Pica::g_debug_context->recorder->RegisterWritten<T>( |
| 419 | addr + 0x1EF00000 - 0x1EC00000 + 0x10100000, data); | ||
| 393 | } | 420 | } |
| 394 | } | 421 | } |
| 395 | 422 | ||
| 396 | // Explicitly instantiate template functions because we aren't defining this in the header: | 423 | // Explicitly instantiate template functions because we aren't defining this in the header: |
| 397 | 424 | ||
| 398 | template void Read<u64>(u64 &var, const u32 addr); | 425 | template void Read<u64>(u64& var, const u32 addr); |
| 399 | template void Read<u32>(u32 &var, const u32 addr); | 426 | template void Read<u32>(u32& var, const u32 addr); |
| 400 | template void Read<u16>(u16 &var, const u32 addr); | 427 | template void Read<u16>(u16& var, const u32 addr); |
| 401 | template void Read<u8>(u8 &var, const u32 addr); | 428 | template void Read<u8>(u8& var, const u32 addr); |
| 402 | 429 | ||
| 403 | template void Write<u64>(u32 addr, const u64 data); | 430 | template void Write<u64>(u32 addr, const u64 data); |
| 404 | template void Write<u32>(u32 addr, const u32 data); | 431 | template void Write<u32>(u32 addr, const u32 data); |
| @@ -417,8 +444,9 @@ static void VBlankCallback(u64 userdata, int cycles_late) { | |||
| 417 | // - If frameskip == 0 (disabled), always swap buffers | 444 | // - If frameskip == 0 (disabled), always swap buffers |
| 418 | // - If frameskip == 1, swap buffers every other frame (starting from the first frame) | 445 | // - If frameskip == 1, swap buffers every other frame (starting from the first frame) |
| 419 | // - If frameskip > 1, swap buffers every frameskip^n frames (starting from the second frame) | 446 | // - If frameskip > 1, swap buffers every frameskip^n frames (starting from the second frame) |
| 420 | if ((((Settings::values.frame_skip != 1) ^ last_skip_frame) && last_skip_frame != g_skip_frame) || | 447 | if ((((Settings::values.frame_skip != 1) ^ last_skip_frame) && |
| 421 | Settings::values.frame_skip == 0) { | 448 | last_skip_frame != g_skip_frame) || |
| 449 | Settings::values.frame_skip == 0) { | ||
| 422 | VideoCore::g_renderer->SwapBuffers(); | 450 | VideoCore::g_renderer->SwapBuffers(); |
| 423 | } | 451 | } |
| 424 | 452 | ||
| @@ -448,12 +476,12 @@ void Init() { | |||
| 448 | // .. or at least these are the ones used by system applets. | 476 | // .. or at least these are the ones used by system applets. |
| 449 | // There's probably a smarter way to come up with addresses | 477 | // There's probably a smarter way to come up with addresses |
| 450 | // like this which does not require hardcoding. | 478 | // like this which does not require hardcoding. |
| 451 | framebuffer_top.address_left1 = 0x181E6000; | 479 | framebuffer_top.address_left1 = 0x181E6000; |
| 452 | framebuffer_top.address_left2 = 0x1822C800; | 480 | framebuffer_top.address_left2 = 0x1822C800; |
| 453 | framebuffer_top.address_right1 = 0x18273000; | 481 | framebuffer_top.address_right1 = 0x18273000; |
| 454 | framebuffer_top.address_right2 = 0x182B9800; | 482 | framebuffer_top.address_right2 = 0x182B9800; |
| 455 | framebuffer_sub.address_left1 = 0x1848F000; | 483 | framebuffer_sub.address_left1 = 0x1848F000; |
| 456 | framebuffer_sub.address_left2 = 0x184C7800; | 484 | framebuffer_sub.address_left2 = 0x184C7800; |
| 457 | 485 | ||
| 458 | framebuffer_top.width.Assign(240); | 486 | framebuffer_top.width.Assign(240); |
| 459 | framebuffer_top.height.Assign(400); | 487 | framebuffer_top.height.Assign(400); |
diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h index da4c345b4..077b6255f 100644 --- a/src/core/hw/gpu.h +++ b/src/core/hw/gpu.h | |||
| @@ -17,7 +17,8 @@ namespace GPU { | |||
| 17 | // Returns index corresponding to the Regs member labeled by field_name | 17 | // Returns index corresponding to the Regs member labeled by field_name |
| 18 | // TODO: Due to Visual studio bug 209229, offsetof does not return constant expressions | 18 | // TODO: Due to Visual studio bug 209229, offsetof does not return constant expressions |
| 19 | // when used with array elements (e.g. GPU_REG_INDEX(memory_fill_config[0])). | 19 | // when used with array elements (e.g. GPU_REG_INDEX(memory_fill_config[0])). |
| 20 | // For details cf. https://connect.microsoft.com/VisualStudio/feedback/details/209229/offsetof-does-not-produce-a-constant-expression-for-array-members | 20 | // For details cf. |
| 21 | // https://connect.microsoft.com/VisualStudio/feedback/details/209229/offsetof-does-not-produce-a-constant-expression-for-array-members | ||
| 21 | // Hopefully, this will be fixed sometime in the future. | 22 | // Hopefully, this will be fixed sometime in the future. |
| 22 | // For lack of better alternatives, we currently hardcode the offsets when constant | 23 | // For lack of better alternatives, we currently hardcode the offsets when constant |
| 23 | // expressions are needed via GPU_REG_INDEX_WORKAROUND (on sane compilers, static_asserts | 24 | // expressions are needed via GPU_REG_INDEX_WORKAROUND (on sane compilers, static_asserts |
| @@ -30,8 +31,9 @@ namespace GPU { | |||
| 30 | // really is this annoying. This macro just forwards its first argument to GPU_REG_INDEX | 31 | // really is this annoying. This macro just forwards its first argument to GPU_REG_INDEX |
| 31 | // and then performs a (no-op) cast to size_t iff the second argument matches the expected | 32 | // and then performs a (no-op) cast to size_t iff the second argument matches the expected |
| 32 | // field offset. Otherwise, the compiler will fail to compile this code. | 33 | // field offset. Otherwise, the compiler will fail to compile this code. |
| 33 | #define GPU_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) \ | 34 | #define GPU_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) \ |
| 34 | ((typename std::enable_if<backup_workaround_index == GPU_REG_INDEX(field_name), size_t>::type)GPU_REG_INDEX(field_name)) | 35 | ((typename std::enable_if<backup_workaround_index == GPU_REG_INDEX(field_name), size_t>::type) \ |
| 36 | GPU_REG_INDEX(field_name)) | ||
| 35 | #endif | 37 | #endif |
| 36 | 38 | ||
| 37 | // MMIO region 0x1EFxxxxx | 39 | // MMIO region 0x1EFxxxxx |
| @@ -44,18 +46,18 @@ struct Regs { | |||
| 44 | // support for that. | 46 | // support for that. |
| 45 | #define ASSERT_MEMBER_SIZE(name, size_in_bytes) | 47 | #define ASSERT_MEMBER_SIZE(name, size_in_bytes) |
| 46 | #else | 48 | #else |
| 47 | #define ASSERT_MEMBER_SIZE(name, size_in_bytes) \ | 49 | #define ASSERT_MEMBER_SIZE(name, size_in_bytes) \ |
| 48 | static_assert(sizeof(name) == size_in_bytes, \ | 50 | static_assert(sizeof(name) == size_in_bytes, \ |
| 49 | "Structure size and register block length don't match") | 51 | "Structure size and register block length don't match") |
| 50 | #endif | 52 | #endif |
| 51 | 53 | ||
| 52 | // Components are laid out in reverse byte order, most significant bits first. | 54 | // Components are laid out in reverse byte order, most significant bits first. |
| 53 | enum class PixelFormat : u32 { | 55 | enum class PixelFormat : u32 { |
| 54 | RGBA8 = 0, | 56 | RGBA8 = 0, |
| 55 | RGB8 = 1, | 57 | RGB8 = 1, |
| 56 | RGB565 = 2, | 58 | RGB565 = 2, |
| 57 | RGB5A1 = 3, | 59 | RGB5A1 = 3, |
| 58 | RGBA4 = 4, | 60 | RGBA4 = 4, |
| 59 | }; | 61 | }; |
| 60 | 62 | ||
| 61 | /** | 63 | /** |
| @@ -88,8 +90,8 @@ struct Regs { | |||
| 88 | BitField<0, 16, u32> value_16bit; | 90 | BitField<0, 16, u32> value_16bit; |
| 89 | 91 | ||
| 90 | // TODO: Verify component order | 92 | // TODO: Verify component order |
| 91 | BitField< 0, 8, u32> value_24bit_r; | 93 | BitField<0, 8, u32> value_24bit_r; |
| 92 | BitField< 8, 8, u32> value_24bit_g; | 94 | BitField<8, 8, u32> value_24bit_g; |
| 93 | BitField<16, 8, u32> value_24bit_b; | 95 | BitField<16, 8, u32> value_24bit_b; |
| 94 | }; | 96 | }; |
| 95 | 97 | ||
| @@ -126,7 +128,7 @@ struct Regs { | |||
| 126 | union { | 128 | union { |
| 127 | u32 size; | 129 | u32 size; |
| 128 | 130 | ||
| 129 | BitField< 0, 16, u32> width; | 131 | BitField<0, 16, u32> width; |
| 130 | BitField<16, 16, u32> height; | 132 | BitField<16, 16, u32> height; |
| 131 | }; | 133 | }; |
| 132 | 134 | ||
| @@ -138,7 +140,7 @@ struct Regs { | |||
| 138 | union { | 140 | union { |
| 139 | u32 format; | 141 | u32 format; |
| 140 | 142 | ||
| 141 | BitField< 0, 3, PixelFormat> color_format; | 143 | BitField<0, 3, PixelFormat> color_format; |
| 142 | }; | 144 | }; |
| 143 | 145 | ||
| 144 | INSERT_PADDING_WORDS(0x1); | 146 | INSERT_PADDING_WORDS(0x1); |
| @@ -180,35 +182,37 @@ struct Regs { | |||
| 180 | union { | 182 | union { |
| 181 | u32 output_size; | 183 | u32 output_size; |
| 182 | 184 | ||
| 183 | BitField< 0, 16, u32> output_width; | 185 | BitField<0, 16, u32> output_width; |
| 184 | BitField<16, 16, u32> output_height; | 186 | BitField<16, 16, u32> output_height; |
| 185 | }; | 187 | }; |
| 186 | 188 | ||
| 187 | union { | 189 | union { |
| 188 | u32 input_size; | 190 | u32 input_size; |
| 189 | 191 | ||
| 190 | BitField< 0, 16, u32> input_width; | 192 | BitField<0, 16, u32> input_width; |
| 191 | BitField<16, 16, u32> input_height; | 193 | BitField<16, 16, u32> input_height; |
| 192 | }; | 194 | }; |
| 193 | 195 | ||
| 194 | enum ScalingMode : u32 { | 196 | enum ScalingMode : u32 { |
| 195 | NoScale = 0, // Doesn't scale the image | 197 | NoScale = 0, // Doesn't scale the image |
| 196 | ScaleX = 1, // Downscales the image in half in the X axis and applies a box filter | 198 | ScaleX = 1, // Downscales the image in half in the X axis and applies a box filter |
| 197 | ScaleXY = 2, // Downscales the image in half in both the X and Y axes and applies a box filter | 199 | ScaleXY = |
| 200 | 2, // Downscales the image in half in both the X and Y axes and applies a box filter | ||
| 198 | }; | 201 | }; |
| 199 | 202 | ||
| 200 | union { | 203 | union { |
| 201 | u32 flags; | 204 | u32 flags; |
| 202 | 205 | ||
| 203 | BitField< 0, 1, u32> flip_vertically; // flips input data vertically | 206 | BitField<0, 1, u32> flip_vertically; // flips input data vertically |
| 204 | BitField< 1, 1, u32> input_linear; // Converts from linear to tiled format | 207 | BitField<1, 1, u32> input_linear; // Converts from linear to tiled format |
| 205 | BitField< 2, 1, u32> crop_input_lines; | 208 | BitField<2, 1, u32> crop_input_lines; |
| 206 | BitField< 3, 1, u32> is_texture_copy; // Copies the data without performing any processing and respecting texture copy fields | 209 | BitField<3, 1, u32> is_texture_copy; // Copies the data without performing any |
| 207 | BitField< 5, 1, u32> dont_swizzle; | 210 | // processing and respecting texture copy fields |
| 208 | BitField< 8, 3, PixelFormat> input_format; | 211 | BitField<5, 1, u32> dont_swizzle; |
| 212 | BitField<8, 3, PixelFormat> input_format; | ||
| 209 | BitField<12, 3, PixelFormat> output_format; | 213 | BitField<12, 3, PixelFormat> output_format; |
| 210 | /// Uses some kind of 32x32 block swizzling mode, instead of the usual 8x8 one. | 214 | /// Uses some kind of 32x32 block swizzling mode, instead of the usual 8x8 one. |
| 211 | BitField<16, 1, u32> block_32; // TODO(yuriks): unimplemented | 215 | BitField<16, 1, u32> block_32; // TODO(yuriks): unimplemented |
| 212 | BitField<24, 2, ScalingMode> scaling; // Determines the scaling mode of the transfer | 216 | BitField<24, 2, ScalingMode> scaling; // Determines the scaling mode of the transfer |
| 213 | }; | 217 | }; |
| 214 | 218 | ||
| @@ -225,14 +229,14 @@ struct Regs { | |||
| 225 | union { | 229 | union { |
| 226 | u32 input_size; | 230 | u32 input_size; |
| 227 | 231 | ||
| 228 | BitField< 0, 16, u32> input_width; | 232 | BitField<0, 16, u32> input_width; |
| 229 | BitField<16, 16, u32> input_gap; | 233 | BitField<16, 16, u32> input_gap; |
| 230 | }; | 234 | }; |
| 231 | 235 | ||
| 232 | union { | 236 | union { |
| 233 | u32 output_size; | 237 | u32 output_size; |
| 234 | 238 | ||
| 235 | BitField< 0, 16, u32> output_width; | 239 | BitField<0, 16, u32> output_width; |
| 236 | BitField<16, 16, u32> output_gap; | 240 | BitField<16, 16, u32> output_gap; |
| 237 | }; | 241 | }; |
| 238 | } texture_copy; | 242 | } texture_copy; |
| @@ -267,12 +271,12 @@ struct Regs { | |||
| 267 | return sizeof(Regs) / sizeof(u32); | 271 | return sizeof(Regs) / sizeof(u32); |
| 268 | } | 272 | } |
| 269 | 273 | ||
| 270 | const u32& operator [] (int index) const { | 274 | const u32& operator[](int index) const { |
| 271 | const u32* content = reinterpret_cast<const u32*>(this); | 275 | const u32* content = reinterpret_cast<const u32*>(this); |
| 272 | return content[index]; | 276 | return content[index]; |
| 273 | } | 277 | } |
| 274 | 278 | ||
| 275 | u32& operator [] (int index) { | 279 | u32& operator[](int index) { |
| 276 | u32* content = reinterpret_cast<u32*>(this); | 280 | u32* content = reinterpret_cast<u32*>(this); |
| 277 | return content[index]; | 281 | return content[index]; |
| 278 | } | 282 | } |
| @@ -294,28 +298,29 @@ static_assert(std::is_standard_layout<Regs>::value, "Structure does not use stan | |||
| 294 | // is technically allowed since C++11. This macro should be enabled once MSVC adds | 298 | // is technically allowed since C++11. This macro should be enabled once MSVC adds |
| 295 | // support for that. | 299 | // support for that. |
| 296 | #ifndef _MSC_VER | 300 | #ifndef _MSC_VER |
| 297 | #define ASSERT_REG_POSITION(field_name, position) \ | 301 | #define ASSERT_REG_POSITION(field_name, position) \ |
| 298 | static_assert(offsetof(Regs, field_name) == position * 4, \ | 302 | static_assert(offsetof(Regs, field_name) == position * 4, \ |
| 299 | "Field "#field_name" has invalid position") | 303 | "Field " #field_name " has invalid position") |
| 300 | 304 | ||
| 301 | ASSERT_REG_POSITION(memory_fill_config[0], 0x00004); | 305 | ASSERT_REG_POSITION(memory_fill_config[0], 0x00004); |
| 302 | ASSERT_REG_POSITION(memory_fill_config[1], 0x00008); | 306 | ASSERT_REG_POSITION(memory_fill_config[1], 0x00008); |
| 303 | ASSERT_REG_POSITION(framebuffer_config[0], 0x00117); | 307 | ASSERT_REG_POSITION(framebuffer_config[0], 0x00117); |
| 304 | ASSERT_REG_POSITION(framebuffer_config[1], 0x00157); | 308 | ASSERT_REG_POSITION(framebuffer_config[1], 0x00157); |
| 305 | ASSERT_REG_POSITION(display_transfer_config, 0x00300); | 309 | ASSERT_REG_POSITION(display_transfer_config, 0x00300); |
| 306 | ASSERT_REG_POSITION(command_processor_config, 0x00638); | 310 | ASSERT_REG_POSITION(command_processor_config, 0x00638); |
| 307 | 311 | ||
| 308 | #undef ASSERT_REG_POSITION | 312 | #undef ASSERT_REG_POSITION |
| 309 | #endif // !defined(_MSC_VER) | 313 | #endif // !defined(_MSC_VER) |
| 310 | 314 | ||
| 311 | // The total number of registers is chosen arbitrarily, but let's make sure it's not some odd value anyway. | 315 | // The total number of registers is chosen arbitrarily, but let's make sure it's not some odd value |
| 316 | // anyway. | ||
| 312 | static_assert(sizeof(Regs) == 0x1000 * sizeof(u32), "Invalid total size of register set"); | 317 | static_assert(sizeof(Regs) == 0x1000 * sizeof(u32), "Invalid total size of register set"); |
| 313 | 318 | ||
| 314 | extern Regs g_regs; | 319 | extern Regs g_regs; |
| 315 | extern bool g_skip_frame; | 320 | extern bool g_skip_frame; |
| 316 | 321 | ||
| 317 | template <typename T> | 322 | template <typename T> |
| 318 | void Read(T &var, const u32 addr); | 323 | void Read(T& var, const u32 addr); |
| 319 | 324 | ||
| 320 | template <typename T> | 325 | template <typename T> |
| 321 | void Write(u32 addr, const T data); | 326 | void Write(u32 addr, const T data); |
| @@ -326,5 +331,4 @@ void Init(); | |||
| 326 | /// Shutdown hardware | 331 | /// Shutdown hardware |
| 327 | void Shutdown(); | 332 | void Shutdown(); |
| 328 | 333 | ||
| 329 | |||
| 330 | } // namespace | 334 | } // namespace |
diff --git a/src/core/hw/hw.cpp b/src/core/hw/hw.cpp index b5fdbf9c1..db224c9aa 100644 --- a/src/core/hw/hw.cpp +++ b/src/core/hw/hw.cpp | |||
| @@ -5,14 +5,14 @@ | |||
| 5 | #include "common/common_types.h" | 5 | #include "common/common_types.h" |
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | 7 | ||
| 8 | #include "core/hw/hw.h" | ||
| 9 | #include "core/hw/gpu.h" | 8 | #include "core/hw/gpu.h" |
| 9 | #include "core/hw/hw.h" | ||
| 10 | #include "core/hw/lcd.h" | 10 | #include "core/hw/lcd.h" |
| 11 | 11 | ||
| 12 | namespace HW { | 12 | namespace HW { |
| 13 | 13 | ||
| 14 | template <typename T> | 14 | template <typename T> |
| 15 | inline void Read(T &var, const u32 addr) { | 15 | inline void Read(T& var, const u32 addr) { |
| 16 | switch (addr & 0xFFFFF000) { | 16 | switch (addr & 0xFFFFF000) { |
| 17 | case VADDR_GPU: | 17 | case VADDR_GPU: |
| 18 | case VADDR_GPU + 0x1000: | 18 | case VADDR_GPU + 0x1000: |
| @@ -71,10 +71,10 @@ inline void Write(u32 addr, const T data) { | |||
| 71 | 71 | ||
| 72 | // Explicitly instantiate template functions because we aren't defining this in the header: | 72 | // Explicitly instantiate template functions because we aren't defining this in the header: |
| 73 | 73 | ||
| 74 | template void Read<u64>(u64 &var, const u32 addr); | 74 | template void Read<u64>(u64& var, const u32 addr); |
| 75 | template void Read<u32>(u32 &var, const u32 addr); | 75 | template void Read<u32>(u32& var, const u32 addr); |
| 76 | template void Read<u16>(u16 &var, const u32 addr); | 76 | template void Read<u16>(u16& var, const u32 addr); |
| 77 | template void Read<u8>(u8 &var, const u32 addr); | 77 | template void Read<u8>(u8& var, const u32 addr); |
| 78 | 78 | ||
| 79 | template void Write<u64>(u32 addr, const u64 data); | 79 | template void Write<u64>(u32 addr, const u64 data); |
| 80 | template void Write<u32>(u32 addr, const u32 data); | 80 | template void Write<u32>(u32 addr, const u32 data); |
| @@ -98,5 +98,4 @@ void Shutdown() { | |||
| 98 | LCD::Shutdown(); | 98 | LCD::Shutdown(); |
| 99 | LOG_DEBUG(HW, "shutdown OK"); | 99 | LOG_DEBUG(HW, "shutdown OK"); |
| 100 | } | 100 | } |
| 101 | |||
| 102 | } | 101 | } |
diff --git a/src/core/hw/hw.h b/src/core/hw/hw.h index d65608910..a3c5d2ea3 100644 --- a/src/core/hw/hw.h +++ b/src/core/hw/hw.h | |||
| @@ -10,30 +10,30 @@ namespace HW { | |||
| 10 | 10 | ||
| 11 | /// Beginnings of IO register regions, in the user VA space. | 11 | /// Beginnings of IO register regions, in the user VA space. |
| 12 | enum : u32 { | 12 | enum : u32 { |
| 13 | VADDR_HASH = 0x1EC01000, | 13 | VADDR_HASH = 0x1EC01000, |
| 14 | VADDR_CSND = 0x1EC03000, | 14 | VADDR_CSND = 0x1EC03000, |
| 15 | VADDR_DSP = 0x1EC40000, | 15 | VADDR_DSP = 0x1EC40000, |
| 16 | VADDR_PDN = 0x1EC41000, | 16 | VADDR_PDN = 0x1EC41000, |
| 17 | VADDR_CODEC = 0x1EC41000, | 17 | VADDR_CODEC = 0x1EC41000, |
| 18 | VADDR_SPI = 0x1EC42000, | 18 | VADDR_SPI = 0x1EC42000, |
| 19 | VADDR_SPI_2 = 0x1EC43000, // Only used under TWL_FIRM? | 19 | VADDR_SPI_2 = 0x1EC43000, // Only used under TWL_FIRM? |
| 20 | VADDR_I2C = 0x1EC44000, | 20 | VADDR_I2C = 0x1EC44000, |
| 21 | VADDR_CODEC_2 = 0x1EC45000, | 21 | VADDR_CODEC_2 = 0x1EC45000, |
| 22 | VADDR_HID = 0x1EC46000, | 22 | VADDR_HID = 0x1EC46000, |
| 23 | VADDR_GPIO = 0x1EC47000, | 23 | VADDR_GPIO = 0x1EC47000, |
| 24 | VADDR_I2C_2 = 0x1EC48000, | 24 | VADDR_I2C_2 = 0x1EC48000, |
| 25 | VADDR_SPI_3 = 0x1EC60000, | 25 | VADDR_SPI_3 = 0x1EC60000, |
| 26 | VADDR_I2C_3 = 0x1EC61000, | 26 | VADDR_I2C_3 = 0x1EC61000, |
| 27 | VADDR_MIC = 0x1EC62000, | 27 | VADDR_MIC = 0x1EC62000, |
| 28 | VADDR_PXI = 0x1EC63000, | 28 | VADDR_PXI = 0x1EC63000, |
| 29 | VADDR_LCD = 0x1ED02000, | 29 | VADDR_LCD = 0x1ED02000, |
| 30 | VADDR_DSP_2 = 0x1ED03000, | 30 | VADDR_DSP_2 = 0x1ED03000, |
| 31 | VADDR_HASH_2 = 0x1EE01000, | 31 | VADDR_HASH_2 = 0x1EE01000, |
| 32 | VADDR_GPU = 0x1EF00000, | 32 | VADDR_GPU = 0x1EF00000, |
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | template <typename T> | 35 | template <typename T> |
| 36 | void Read(T &var, const u32 addr); | 36 | void Read(T& var, const u32 addr); |
| 37 | 37 | ||
| 38 | template <typename T> | 38 | template <typename T> |
| 39 | void Write(u32 addr, const T data); | 39 | void Write(u32 addr, const T data); |
diff --git a/src/core/hw/lcd.cpp b/src/core/hw/lcd.cpp index 6f93709e3..0e3aa7cfd 100644 --- a/src/core/hw/lcd.cpp +++ b/src/core/hw/lcd.cpp | |||
| @@ -18,7 +18,7 @@ namespace LCD { | |||
| 18 | Regs g_regs; | 18 | Regs g_regs; |
| 19 | 19 | ||
| 20 | template <typename T> | 20 | template <typename T> |
| 21 | inline void Read(T &var, const u32 raw_addr) { | 21 | inline void Read(T& var, const u32 raw_addr) { |
| 22 | u32 addr = raw_addr - HW::VADDR_LCD; | 22 | u32 addr = raw_addr - HW::VADDR_LCD; |
| 23 | u32 index = addr / 4; | 23 | u32 index = addr / 4; |
| 24 | 24 | ||
| @@ -48,16 +48,17 @@ inline void Write(u32 addr, const T data) { | |||
| 48 | // This is happening *after* handling the write to make sure we properly catch all memory reads. | 48 | // This is happening *after* handling the write to make sure we properly catch all memory reads. |
| 49 | if (Pica::g_debug_context && Pica::g_debug_context->recorder) { | 49 | if (Pica::g_debug_context && Pica::g_debug_context->recorder) { |
| 50 | // addr + GPU VBase - IO VBase + IO PBase | 50 | // addr + GPU VBase - IO VBase + IO PBase |
| 51 | Pica::g_debug_context->recorder->RegisterWritten<T>(addr + HW::VADDR_LCD - 0x1EC00000 + 0x10100000, data); | 51 | Pica::g_debug_context->recorder->RegisterWritten<T>( |
| 52 | addr + HW::VADDR_LCD - 0x1EC00000 + 0x10100000, data); | ||
| 52 | } | 53 | } |
| 53 | } | 54 | } |
| 54 | 55 | ||
| 55 | // Explicitly instantiate template functions because we aren't defining this in the header: | 56 | // Explicitly instantiate template functions because we aren't defining this in the header: |
| 56 | 57 | ||
| 57 | template void Read<u64>(u64 &var, const u32 addr); | 58 | template void Read<u64>(u64& var, const u32 addr); |
| 58 | template void Read<u32>(u32 &var, const u32 addr); | 59 | template void Read<u32>(u32& var, const u32 addr); |
| 59 | template void Read<u16>(u16 &var, const u32 addr); | 60 | template void Read<u16>(u16& var, const u32 addr); |
| 60 | template void Read<u8>(u8 &var, const u32 addr); | 61 | template void Read<u8>(u8& var, const u32 addr); |
| 61 | 62 | ||
| 62 | template void Write<u64>(u32 addr, const u64 data); | 63 | template void Write<u64>(u32 addr, const u64 data); |
| 63 | template void Write<u32>(u32 addr, const u32 data); | 64 | template void Write<u32>(u32 addr, const u32 data); |
diff --git a/src/core/hw/lcd.h b/src/core/hw/lcd.h index 57029c5e8..404833165 100644 --- a/src/core/hw/lcd.h +++ b/src/core/hw/lcd.h | |||
| @@ -42,16 +42,15 @@ struct Regs { | |||
| 42 | return sizeof(Regs) / sizeof(u32); | 42 | return sizeof(Regs) / sizeof(u32); |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | const u32& operator [] (int index) const { | 45 | const u32& operator[](int index) const { |
| 46 | const u32* content = reinterpret_cast<const u32*>(this); | 46 | const u32* content = reinterpret_cast<const u32*>(this); |
| 47 | return content[index]; | 47 | return content[index]; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | u32& operator [] (int index) { | 50 | u32& operator[](int index) { |
| 51 | u32* content = reinterpret_cast<u32*>(this); | 51 | u32* content = reinterpret_cast<u32*>(this); |
| 52 | return content[index]; | 52 | return content[index]; |
| 53 | } | 53 | } |
| 54 | |||
| 55 | }; | 54 | }; |
| 56 | static_assert(std::is_standard_layout<Regs>::value, "Structure does not use standard layout"); | 55 | static_assert(std::is_standard_layout<Regs>::value, "Structure does not use standard layout"); |
| 57 | 56 | ||
| @@ -59,14 +58,14 @@ static_assert(std::is_standard_layout<Regs>::value, "Structure does not use stan | |||
| 59 | // is technically allowed since C++11. This macro should be enabled once MSVC adds | 58 | // is technically allowed since C++11. This macro should be enabled once MSVC adds |
| 60 | // support for that. | 59 | // support for that. |
| 61 | #ifndef _MSC_VER | 60 | #ifndef _MSC_VER |
| 62 | #define ASSERT_REG_POSITION(field_name, position) \ | 61 | #define ASSERT_REG_POSITION(field_name, position) \ |
| 63 | static_assert(offsetof(Regs, field_name) == position * 4, \ | 62 | static_assert(offsetof(Regs, field_name) == position * 4, \ |
| 64 | "Field "#field_name" has invalid position") | 63 | "Field " #field_name " has invalid position") |
| 65 | 64 | ||
| 66 | ASSERT_REG_POSITION(color_fill_top, 0x81); | 65 | ASSERT_REG_POSITION(color_fill_top, 0x81); |
| 67 | ASSERT_REG_POSITION(backlight_top, 0x90); | 66 | ASSERT_REG_POSITION(backlight_top, 0x90); |
| 68 | ASSERT_REG_POSITION(color_fill_bottom, 0x281); | 67 | ASSERT_REG_POSITION(color_fill_bottom, 0x281); |
| 69 | ASSERT_REG_POSITION(backlight_bottom, 0x290); | 68 | ASSERT_REG_POSITION(backlight_bottom, 0x290); |
| 70 | 69 | ||
| 71 | #undef ASSERT_REG_POSITION | 70 | #undef ASSERT_REG_POSITION |
| 72 | #endif // !defined(_MSC_VER) | 71 | #endif // !defined(_MSC_VER) |
| @@ -74,7 +73,7 @@ ASSERT_REG_POSITION(backlight_bottom, 0x290); | |||
| 74 | extern Regs g_regs; | 73 | extern Regs g_regs; |
| 75 | 74 | ||
| 76 | template <typename T> | 75 | template <typename T> |
| 77 | void Read(T &var, const u32 addr); | 76 | void Read(T& var, const u32 addr); |
| 78 | 77 | ||
| 79 | template <typename T> | 78 | template <typename T> |
| 80 | void Write(u32 addr, const T data); | 79 | void Write(u32 addr, const T data); |
diff --git a/src/core/hw/y2r.cpp b/src/core/hw/y2r.cpp index 083391e83..5a68d7e65 100644 --- a/src/core/hw/y2r.cpp +++ b/src/core/hw/y2r.cpp | |||
| @@ -27,9 +27,9 @@ static const size_t TILE_SIZE = 8 * 8; | |||
| 27 | using ImageTile = std::array<u32, TILE_SIZE>; | 27 | using ImageTile = std::array<u32, TILE_SIZE>; |
| 28 | 28 | ||
| 29 | /// Converts a image strip from the source YUV format into individual 8x8 RGB32 tiles. | 29 | /// Converts a image strip from the source YUV format into individual 8x8 RGB32 tiles. |
| 30 | static void ConvertYUVToRGB(InputFormat input_format, | 30 | static void ConvertYUVToRGB(InputFormat input_format, const u8* input_Y, const u8* input_U, |
| 31 | const u8* input_Y, const u8* input_U, const u8* input_V, ImageTile output[], | 31 | const u8* input_V, ImageTile output[], unsigned int width, |
| 32 | unsigned int width, unsigned int height, const CoefficientSet& coefficients) { | 32 | unsigned int height, const CoefficientSet& coefficients) { |
| 33 | 33 | ||
| 34 | for (unsigned int y = 0; y < height; ++y) { | 34 | for (unsigned int y = 0; y < height; ++y) { |
| 35 | for (unsigned int x = 0; x < width; ++x) { | 35 | for (unsigned int x = 0; x < width; ++x) { |
| @@ -58,11 +58,11 @@ static void ConvertYUVToRGB(InputFormat input_format, | |||
| 58 | 58 | ||
| 59 | // This conversion process is bit-exact with hardware, as far as could be tested. | 59 | // This conversion process is bit-exact with hardware, as far as could be tested. |
| 60 | auto& c = coefficients; | 60 | auto& c = coefficients; |
| 61 | s32 cY = c[0]*Y; | 61 | s32 cY = c[0] * Y; |
| 62 | 62 | ||
| 63 | s32 r = cY + c[1]*V; | 63 | s32 r = cY + c[1] * V; |
| 64 | s32 g = cY - c[3]*U - c[2]*V; | 64 | s32 g = cY - c[3] * U - c[2] * V; |
| 65 | s32 b = cY + c[4]*U; | 65 | s32 b = cY + c[4] * U; |
| 66 | 66 | ||
| 67 | const s32 rounding_offset = 0x18; | 67 | const s32 rounding_offset = 0x18; |
| 68 | r = (r >> 3) + c[5] + rounding_offset; | 68 | r = (r >> 3) + c[5] + rounding_offset; |
| @@ -74,14 +74,14 @@ static void ConvertYUVToRGB(InputFormat input_format, | |||
| 74 | u32* out = &output[tile][y * 8 + tile_x]; | 74 | u32* out = &output[tile][y * 8 + tile_x]; |
| 75 | 75 | ||
| 76 | using MathUtil::Clamp; | 76 | using MathUtil::Clamp; |
| 77 | *out = ((u32)Clamp(r >> 5, 0, 0xFF) << 24) | | 77 | *out = ((u32)Clamp(r >> 5, 0, 0xFF) << 24) | ((u32)Clamp(g >> 5, 0, 0xFF) << 16) | |
| 78 | ((u32)Clamp(g >> 5, 0, 0xFF) << 16) | | ||
| 79 | ((u32)Clamp(b >> 5, 0, 0xFF) << 8); | 78 | ((u32)Clamp(b >> 5, 0, 0xFF) << 8); |
| 80 | } | 79 | } |
| 81 | } | 80 | } |
| 82 | } | 81 | } |
| 83 | 82 | ||
| 84 | /// Simulates an incoming CDMA transfer. The N parameter is used to automatically convert 16-bit formats to 8-bit. | 83 | /// Simulates an incoming CDMA transfer. The N parameter is used to automatically convert 16-bit |
| 84 | /// formats to 8-bit. | ||
| 85 | template <size_t N> | 85 | template <size_t N> |
| 86 | static void ReceiveData(u8* output, ConversionBuffer& buf, size_t amount_of_data) { | 86 | static void ReceiveData(u8* output, ConversionBuffer& buf, size_t amount_of_data) { |
| 87 | const u8* input = Memory::GetPointer(buf.address); | 87 | const u8* input = Memory::GetPointer(buf.address); |
| @@ -103,9 +103,10 @@ static void ReceiveData(u8* output, ConversionBuffer& buf, size_t amount_of_data | |||
| 103 | } | 103 | } |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | /// Convert intermediate RGB32 format to the final output format while simulating an outgoing CDMA transfer. | 106 | /// Convert intermediate RGB32 format to the final output format while simulating an outgoing CDMA |
| 107 | /// transfer. | ||
| 107 | static void SendData(const u32* input, ConversionBuffer& buf, int amount_of_data, | 108 | static void SendData(const u32* input, ConversionBuffer& buf, int amount_of_data, |
| 108 | OutputFormat output_format, u8 alpha) { | 109 | OutputFormat output_format, u8 alpha) { |
| 109 | 110 | ||
| 110 | u8* output = Memory::GetPointer(buf.address); | 111 | u8* output = Memory::GetPointer(buf.address); |
| 111 | 112 | ||
| @@ -113,9 +114,7 @@ static void SendData(const u32* input, ConversionBuffer& buf, int amount_of_data | |||
| 113 | u8* unit_end = output + buf.transfer_unit; | 114 | u8* unit_end = output + buf.transfer_unit; |
| 114 | while (output < unit_end) { | 115 | while (output < unit_end) { |
| 115 | u32 color = *input++; | 116 | u32 color = *input++; |
| 116 | Math::Vec4<u8> col_vec{ | 117 | Math::Vec4<u8> col_vec{(u8)(color >> 24), (u8)(color >> 16), (u8)(color >> 8), alpha}; |
| 117 | (u8)(color >> 24), (u8)(color >> 16), (u8)(color >> 8), alpha | ||
| 118 | }; | ||
| 119 | 118 | ||
| 120 | switch (output_format) { | 119 | switch (output_format) { |
| 121 | case OutputFormat::RGBA8: | 120 | case OutputFormat::RGBA8: |
| @@ -146,34 +145,26 @@ static void SendData(const u32* input, ConversionBuffer& buf, int amount_of_data | |||
| 146 | } | 145 | } |
| 147 | 146 | ||
| 148 | static const u8 linear_lut[64] = { | 147 | static const u8 linear_lut[64] = { |
| 149 | 0, 1, 2, 3, 4, 5, 6, 7, | 148 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, |
| 150 | 8, 9, 10, 11, 12, 13, 14, 15, | 149 | 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, |
| 151 | 16, 17, 18, 19, 20, 21, 22, 23, | 150 | 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, |
| 152 | 24, 25, 26, 27, 28, 29, 30, 31, | ||
| 153 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
| 154 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
| 155 | 48, 49, 50, 51, 52, 53, 54, 55, | ||
| 156 | 56, 57, 58, 59, 60, 61, 62, 63, | ||
| 157 | }; | 151 | }; |
| 158 | 152 | ||
| 159 | static const u8 morton_lut[64] = { | 153 | static const u8 morton_lut[64] = { |
| 160 | 0, 1, 4, 5, 16, 17, 20, 21, | 154 | 0, 1, 4, 5, 16, 17, 20, 21, 2, 3, 6, 7, 18, 19, 22, 23, 8, 9, 12, 13, 24, 25, |
| 161 | 2, 3, 6, 7, 18, 19, 22, 23, | 155 | 28, 29, 10, 11, 14, 15, 26, 27, 30, 31, 32, 33, 36, 37, 48, 49, 52, 53, 34, 35, 38, 39, |
| 162 | 8, 9, 12, 13, 24, 25, 28, 29, | 156 | 50, 51, 54, 55, 40, 41, 44, 45, 56, 57, 60, 61, 42, 43, 46, 47, 58, 59, 62, 63, |
| 163 | 10, 11, 14, 15, 26, 27, 30, 31, | ||
| 164 | 32, 33, 36, 37, 48, 49, 52, 53, | ||
| 165 | 34, 35, 38, 39, 50, 51, 54, 55, | ||
| 166 | 40, 41, 44, 45, 56, 57, 60, 61, | ||
| 167 | 42, 43, 46, 47, 58, 59, 62, 63, | ||
| 168 | }; | 157 | }; |
| 169 | 158 | ||
| 170 | static void RotateTile0(const ImageTile& input, ImageTile& output, int height, const u8 out_map[64]) { | 159 | static void RotateTile0(const ImageTile& input, ImageTile& output, int height, |
| 160 | const u8 out_map[64]) { | ||
| 171 | for (int i = 0; i < height * 8; ++i) { | 161 | for (int i = 0; i < height * 8; ++i) { |
| 172 | output[out_map[i]] = input[i]; | 162 | output[out_map[i]] = input[i]; |
| 173 | } | 163 | } |
| 174 | } | 164 | } |
| 175 | 165 | ||
| 176 | static void RotateTile90(const ImageTile& input, ImageTile& output, int height, const u8 out_map[64]) { | 166 | static void RotateTile90(const ImageTile& input, ImageTile& output, int height, |
| 167 | const u8 out_map[64]) { | ||
| 177 | int out_i = 0; | 168 | int out_i = 0; |
| 178 | for (int x = 0; x < 8; ++x) { | 169 | for (int x = 0; x < 8; ++x) { |
| 179 | for (int y = height - 1; y >= 0; --y) { | 170 | for (int y = height - 1; y >= 0; --y) { |
| @@ -182,16 +173,18 @@ static void RotateTile90(const ImageTile& input, ImageTile& output, int height, | |||
| 182 | } | 173 | } |
| 183 | } | 174 | } |
| 184 | 175 | ||
| 185 | static void RotateTile180(const ImageTile& input, ImageTile& output, int height, const u8 out_map[64]) { | 176 | static void RotateTile180(const ImageTile& input, ImageTile& output, int height, |
| 177 | const u8 out_map[64]) { | ||
| 186 | int out_i = 0; | 178 | int out_i = 0; |
| 187 | for (int i = height * 8 - 1; i >= 0; --i) { | 179 | for (int i = height * 8 - 1; i >= 0; --i) { |
| 188 | output[out_map[out_i++]] = input[i]; | 180 | output[out_map[out_i++]] = input[i]; |
| 189 | } | 181 | } |
| 190 | } | 182 | } |
| 191 | 183 | ||
| 192 | static void RotateTile270(const ImageTile& input, ImageTile& output, int height, const u8 out_map[64]) { | 184 | static void RotateTile270(const ImageTile& input, ImageTile& output, int height, |
| 185 | const u8 out_map[64]) { | ||
| 193 | int out_i = 0; | 186 | int out_i = 0; |
| 194 | for (int x = 8-1; x >= 0; --x) { | 187 | for (int x = 8 - 1; x >= 0; --x) { |
| 195 | for (int y = 0; y < height; ++y) { | 188 | for (int y = 0; y < height; ++y) { |
| 196 | output[out_map[out_i++]] = input[y * 8 + x]; | 189 | output[out_map[out_i++]] = input[y * 8 + x]; |
| 197 | } | 190 | } |
| @@ -274,9 +267,11 @@ void PerformConversion(ConversionConfiguration& cvt) { | |||
| 274 | const u8* tile_remap = nullptr; | 267 | const u8* tile_remap = nullptr; |
| 275 | switch (cvt.block_alignment) { | 268 | switch (cvt.block_alignment) { |
| 276 | case BlockAlignment::Linear: | 269 | case BlockAlignment::Linear: |
| 277 | tile_remap = linear_lut; break; | 270 | tile_remap = linear_lut; |
| 271 | break; | ||
| 278 | case BlockAlignment::Block8x8: | 272 | case BlockAlignment::Block8x8: |
| 279 | tile_remap = morton_lut; break; | 273 | tile_remap = morton_lut; |
| 274 | break; | ||
| 280 | } | 275 | } |
| 281 | 276 | ||
| 282 | for (unsigned int y = 0; y < cvt.input_lines; y += 8) { | 277 | for (unsigned int y = 0; y < cvt.input_lines; y += 8) { |
| @@ -320,7 +315,7 @@ void PerformConversion(ConversionConfiguration& cvt) { | |||
| 320 | // Note(yuriks): If additional optimization is required, input_format can be moved to a | 315 | // Note(yuriks): If additional optimization is required, input_format can be moved to a |
| 321 | // template parameter, so that its dispatch can be moved to outside the inner loop. | 316 | // template parameter, so that its dispatch can be moved to outside the inner loop. |
| 322 | ConvertYUVToRGB(cvt.input_format, input_Y, input_U, input_V, tiles.get(), | 317 | ConvertYUVToRGB(cvt.input_format, input_Y, input_U, input_V, tiles.get(), |
| 323 | cvt.input_line_width, row_height, cvt.coefficients); | 318 | cvt.input_line_width, row_height, cvt.coefficients); |
| 324 | 319 | ||
| 325 | u32* output_buffer = reinterpret_cast<u32*>(data_buffer.get()); | 320 | u32* output_buffer = reinterpret_cast<u32*>(data_buffer.get()); |
| 326 | 321 | ||
| @@ -367,9 +362,9 @@ void PerformConversion(ConversionConfiguration& cvt) { | |||
| 367 | 362 | ||
| 368 | // Note(yuriks): If additional optimization is required, output_format can be moved to a | 363 | // Note(yuriks): If additional optimization is required, output_format can be moved to a |
| 369 | // template parameter, so that its dispatch can be moved to outside the inner loop. | 364 | // template parameter, so that its dispatch can be moved to outside the inner loop. |
| 370 | SendData(reinterpret_cast<u32*>(data_buffer.get()), cvt.dst, (int)row_data_size, cvt.output_format, (u8)cvt.alpha); | 365 | SendData(reinterpret_cast<u32*>(data_buffer.get()), cvt.dst, (int)row_data_size, |
| 366 | cvt.output_format, (u8)cvt.alpha); | ||
| 371 | } | 367 | } |
| 372 | } | 368 | } |
| 373 | |||
| 374 | } | 369 | } |
| 375 | } | 370 | } |
diff --git a/src/core/hw/y2r.h b/src/core/hw/y2r.h index 729e1eee3..6b6e71bec 100644 --- a/src/core/hw/y2r.h +++ b/src/core/hw/y2r.h | |||
| @@ -3,13 +3,12 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | namespace Y2R_U { | 5 | namespace Y2R_U { |
| 6 | struct ConversionConfiguration; | 6 | struct ConversionConfiguration; |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | namespace HW { | 9 | namespace HW { |
| 10 | namespace Y2R { | 10 | namespace Y2R { |
| 11 | 11 | ||
| 12 | void PerformConversion(Y2R_U::ConversionConfiguration& cvt); | 12 | void PerformConversion(Y2R_U::ConversionConfiguration& cvt); |
| 13 | |||
| 14 | } | 13 | } |
| 15 | } | 14 | } |
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index a16411e14..c2e87f592 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp | |||
| @@ -37,20 +37,14 @@ namespace Loader { | |||
| 37 | * The BSS section must be cleared manually by the application. | 37 | * The BSS section must be cleared manually by the application. |
| 38 | */ | 38 | */ |
| 39 | 39 | ||
| 40 | enum THREEDSX_Error { | 40 | enum THREEDSX_Error { ERROR_NONE = 0, ERROR_READ = 1, ERROR_FILE = 2, ERROR_ALLOC = 3 }; |
| 41 | ERROR_NONE = 0, | ||
| 42 | ERROR_READ = 1, | ||
| 43 | ERROR_FILE = 2, | ||
| 44 | ERROR_ALLOC = 3 | ||
| 45 | }; | ||
| 46 | 41 | ||
| 47 | static const u32 RELOCBUFSIZE = 512; | 42 | static const u32 RELOCBUFSIZE = 512; |
| 48 | static const unsigned int NUM_SEGMENTS = 3; | 43 | static const unsigned int NUM_SEGMENTS = 3; |
| 49 | 44 | ||
| 50 | // File header | 45 | // File header |
| 51 | #pragma pack(1) | 46 | #pragma pack(1) |
| 52 | struct THREEDSX_Header | 47 | struct THREEDSX_Header { |
| 53 | { | ||
| 54 | u32 magic; | 48 | u32 magic; |
| 55 | u16 header_size, reloc_hdr_size; | 49 | u16 header_size, reloc_hdr_size; |
| 56 | u32 format_ver; | 50 | u32 format_ver; |
| @@ -66,11 +60,11 @@ struct THREEDSX_Header | |||
| 66 | }; | 60 | }; |
| 67 | 61 | ||
| 68 | // Relocation header: all fields (even extra unknown fields) are guaranteed to be relocation counts. | 62 | // Relocation header: all fields (even extra unknown fields) are guaranteed to be relocation counts. |
| 69 | struct THREEDSX_RelocHdr | 63 | struct THREEDSX_RelocHdr { |
| 70 | { | ||
| 71 | // # of absolute relocations (that is, fix address to post-relocation memory layout) | 64 | // # of absolute relocations (that is, fix address to post-relocation memory layout) |
| 72 | u32 cross_segment_absolute; | 65 | u32 cross_segment_absolute; |
| 73 | // # of cross-segment relative relocations (that is, 32bit signed offsets that need to be patched) | 66 | // # of cross-segment relative relocations (that is, 32bit signed offsets that need to be |
| 67 | // patched) | ||
| 74 | u32 cross_segment_relative; | 68 | u32 cross_segment_relative; |
| 75 | // more? | 69 | // more? |
| 76 | 70 | ||
| @@ -80,21 +74,18 @@ struct THREEDSX_RelocHdr | |||
| 80 | }; | 74 | }; |
| 81 | 75 | ||
| 82 | // Relocation entry: from the current pointer, skip X words and patch Y words | 76 | // Relocation entry: from the current pointer, skip X words and patch Y words |
| 83 | struct THREEDSX_Reloc | 77 | struct THREEDSX_Reloc { |
| 84 | { | ||
| 85 | u16 skip, patch; | 78 | u16 skip, patch; |
| 86 | }; | 79 | }; |
| 87 | #pragma pack() | 80 | #pragma pack() |
| 88 | 81 | ||
| 89 | struct THREEloadinfo | 82 | struct THREEloadinfo { |
| 90 | { | ||
| 91 | u8* seg_ptrs[3]; // code, rodata & data | 83 | u8* seg_ptrs[3]; // code, rodata & data |
| 92 | u32 seg_addrs[3]; | 84 | u32 seg_addrs[3]; |
| 93 | u32 seg_sizes[3]; | 85 | u32 seg_sizes[3]; |
| 94 | }; | 86 | }; |
| 95 | 87 | ||
| 96 | static u32 TranslateAddr(u32 addr, const THREEloadinfo *loadinfo, u32* offsets) | 88 | static u32 TranslateAddr(u32 addr, const THREEloadinfo* loadinfo, u32* offsets) { |
| 97 | { | ||
| 98 | if (addr < offsets[0]) | 89 | if (addr < offsets[0]) |
| 99 | return loadinfo->seg_addrs[0] + addr; | 90 | return loadinfo->seg_addrs[0] + addr; |
| 100 | if (addr < offsets[1]) | 91 | if (addr < offsets[1]) |
| @@ -105,8 +96,8 @@ static u32 TranslateAddr(u32 addr, const THREEloadinfo *loadinfo, u32* offsets) | |||
| 105 | using Kernel::SharedPtr; | 96 | using Kernel::SharedPtr; |
| 106 | using Kernel::CodeSet; | 97 | using Kernel::CodeSet; |
| 107 | 98 | ||
| 108 | static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, SharedPtr<CodeSet>* out_codeset) | 99 | static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, |
| 109 | { | 100 | SharedPtr<CodeSet>* out_codeset) { |
| 110 | if (!file.IsOpen()) | 101 | if (!file.IsOpen()) |
| 111 | return ERROR_FILE; | 102 | return ERROR_FILE; |
| 112 | 103 | ||
| @@ -118,13 +109,14 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared | |||
| 118 | return ERROR_READ; | 109 | return ERROR_READ; |
| 119 | 110 | ||
| 120 | THREEloadinfo loadinfo; | 111 | THREEloadinfo loadinfo; |
| 121 | //loadinfo segments must be a multiple of 0x1000 | 112 | // loadinfo segments must be a multiple of 0x1000 |
| 122 | loadinfo.seg_sizes[0] = (hdr.code_seg_size + 0xFFF) &~0xFFF; | 113 | loadinfo.seg_sizes[0] = (hdr.code_seg_size + 0xFFF) & ~0xFFF; |
| 123 | loadinfo.seg_sizes[1] = (hdr.rodata_seg_size + 0xFFF) &~0xFFF; | 114 | loadinfo.seg_sizes[1] = (hdr.rodata_seg_size + 0xFFF) & ~0xFFF; |
| 124 | loadinfo.seg_sizes[2] = (hdr.data_seg_size + 0xFFF) &~0xFFF; | 115 | loadinfo.seg_sizes[2] = (hdr.data_seg_size + 0xFFF) & ~0xFFF; |
| 125 | u32 offsets[2] = { loadinfo.seg_sizes[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] }; | 116 | u32 offsets[2] = {loadinfo.seg_sizes[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1]}; |
| 126 | u32 n_reloc_tables = hdr.reloc_hdr_size / sizeof(u32); | 117 | u32 n_reloc_tables = hdr.reloc_hdr_size / sizeof(u32); |
| 127 | std::vector<u8> program_image(loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] + loadinfo.seg_sizes[2]); | 118 | std::vector<u8> program_image(loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] + |
| 119 | loadinfo.seg_sizes[2]); | ||
| 128 | 120 | ||
| 129 | loadinfo.seg_addrs[0] = base_addr; | 121 | loadinfo.seg_addrs[0] = base_addr; |
| 130 | loadinfo.seg_addrs[1] = loadinfo.seg_addrs[0] + loadinfo.seg_sizes[0]; | 122 | loadinfo.seg_addrs[1] = loadinfo.seg_addrs[0] + loadinfo.seg_sizes[0]; |
| @@ -149,7 +141,8 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared | |||
| 149 | return ERROR_READ; | 141 | return ERROR_READ; |
| 150 | if (file.ReadBytes(loadinfo.seg_ptrs[1], hdr.rodata_seg_size) != hdr.rodata_seg_size) | 142 | if (file.ReadBytes(loadinfo.seg_ptrs[1], hdr.rodata_seg_size) != hdr.rodata_seg_size) |
| 151 | return ERROR_READ; | 143 | return ERROR_READ; |
| 152 | if (file.ReadBytes(loadinfo.seg_ptrs[2], hdr.data_seg_size - hdr.bss_size) != hdr.data_seg_size - hdr.bss_size) | 144 | if (file.ReadBytes(loadinfo.seg_ptrs[2], hdr.data_seg_size - hdr.bss_size) != |
| 145 | hdr.data_seg_size - hdr.bss_size) | ||
| 153 | return ERROR_READ; | 146 | return ERROR_READ; |
| 154 | 147 | ||
| 155 | // BSS clear | 148 | // BSS clear |
| @@ -157,11 +150,12 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared | |||
| 157 | 150 | ||
| 158 | // Relocate the segments | 151 | // Relocate the segments |
| 159 | for (unsigned int current_segment = 0; current_segment < NUM_SEGMENTS; ++current_segment) { | 152 | for (unsigned int current_segment = 0; current_segment < NUM_SEGMENTS; ++current_segment) { |
| 160 | for (unsigned current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables; current_segment_reloc_table++) { | 153 | for (unsigned current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables; |
| 154 | current_segment_reloc_table++) { | ||
| 161 | u32 n_relocs = relocs[current_segment * n_reloc_tables + current_segment_reloc_table]; | 155 | u32 n_relocs = relocs[current_segment * n_reloc_tables + current_segment_reloc_table]; |
| 162 | if (current_segment_reloc_table >= 2) { | 156 | if (current_segment_reloc_table >= 2) { |
| 163 | // We are not using this table - ignore it because we don't know what it dose | 157 | // We are not using this table - ignore it because we don't know what it dose |
| 164 | file.Seek(n_relocs*sizeof(THREEDSX_Reloc), SEEK_CUR); | 158 | file.Seek(n_relocs * sizeof(THREEDSX_Reloc), SEEK_CUR); |
| 165 | continue; | 159 | continue; |
| 166 | } | 160 | } |
| 167 | THREEDSX_Reloc reloc_table[RELOCBUFSIZE]; | 161 | THREEDSX_Reloc reloc_table[RELOCBUFSIZE]; |
| @@ -173,17 +167,20 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared | |||
| 173 | u32 remaining = std::min(RELOCBUFSIZE, n_relocs); | 167 | u32 remaining = std::min(RELOCBUFSIZE, n_relocs); |
| 174 | n_relocs -= remaining; | 168 | n_relocs -= remaining; |
| 175 | 169 | ||
| 176 | if (file.ReadBytes(reloc_table, remaining * sizeof(THREEDSX_Reloc)) != remaining * sizeof(THREEDSX_Reloc)) | 170 | if (file.ReadBytes(reloc_table, remaining * sizeof(THREEDSX_Reloc)) != |
| 171 | remaining * sizeof(THREEDSX_Reloc)) | ||
| 177 | return ERROR_READ; | 172 | return ERROR_READ; |
| 178 | 173 | ||
| 179 | for (unsigned current_inprogress = 0; current_inprogress < remaining && pos < end_pos; current_inprogress++) { | 174 | for (unsigned current_inprogress = 0; |
| 175 | current_inprogress < remaining && pos < end_pos; current_inprogress++) { | ||
| 180 | const auto& table = reloc_table[current_inprogress]; | 176 | const auto& table = reloc_table[current_inprogress]; |
| 181 | LOG_TRACE(Loader, "(t=%d,skip=%u,patch=%u)", current_segment_reloc_table, | 177 | LOG_TRACE(Loader, "(t=%d,skip=%u,patch=%u)", current_segment_reloc_table, |
| 182 | static_cast<u32>(table.skip), static_cast<u32>(table.patch)); | 178 | static_cast<u32>(table.skip), static_cast<u32>(table.patch)); |
| 183 | pos += table.skip; | 179 | pos += table.skip; |
| 184 | s32 num_patches = table.patch; | 180 | s32 num_patches = table.patch; |
| 185 | while (0 < num_patches && pos < end_pos) { | 181 | while (0 < num_patches && pos < end_pos) { |
| 186 | u32 in_addr = static_cast<u32>(reinterpret_cast<u8*>(pos) - program_image.data()); | 182 | u32 in_addr = |
| 183 | static_cast<u32>(reinterpret_cast<u8*>(pos) - program_image.data()); | ||
| 187 | u32 addr = TranslateAddr(*pos, &loadinfo, offsets); | 184 | u32 addr = TranslateAddr(*pos, &loadinfo, offsets); |
| 188 | LOG_TRACE(Loader, "Patching %08X <-- rel(%08X,%d) (%08X)", | 185 | LOG_TRACE(Loader, "Patching %08X <-- rel(%08X,%d) (%08X)", |
| 189 | base_addr + in_addr, addr, current_segment_reloc_table, *pos); | 186 | base_addr + in_addr, addr, current_segment_reloc_table, *pos); |
| @@ -195,7 +192,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared | |||
| 195 | *pos = static_cast<u32>(addr - in_addr); | 192 | *pos = static_cast<u32>(addr - in_addr); |
| 196 | break; | 193 | break; |
| 197 | default: | 194 | default: |
| 198 | break; //this should never happen | 195 | break; // this should never happen |
| 199 | } | 196 | } |
| 200 | pos++; | 197 | pos++; |
| 201 | num_patches--; | 198 | num_patches--; |
| @@ -209,23 +206,24 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared | |||
| 209 | SharedPtr<CodeSet> code_set = CodeSet::Create("", 0); | 206 | SharedPtr<CodeSet> code_set = CodeSet::Create("", 0); |
| 210 | 207 | ||
| 211 | code_set->code.offset = loadinfo.seg_ptrs[0] - program_image.data(); | 208 | code_set->code.offset = loadinfo.seg_ptrs[0] - program_image.data(); |
| 212 | code_set->code.addr = loadinfo.seg_addrs[0]; | 209 | code_set->code.addr = loadinfo.seg_addrs[0]; |
| 213 | code_set->code.size = loadinfo.seg_sizes[0]; | 210 | code_set->code.size = loadinfo.seg_sizes[0]; |
| 214 | 211 | ||
| 215 | code_set->rodata.offset = loadinfo.seg_ptrs[1] - program_image.data(); | 212 | code_set->rodata.offset = loadinfo.seg_ptrs[1] - program_image.data(); |
| 216 | code_set->rodata.addr = loadinfo.seg_addrs[1]; | 213 | code_set->rodata.addr = loadinfo.seg_addrs[1]; |
| 217 | code_set->rodata.size = loadinfo.seg_sizes[1]; | 214 | code_set->rodata.size = loadinfo.seg_sizes[1]; |
| 218 | 215 | ||
| 219 | code_set->data.offset = loadinfo.seg_ptrs[2] - program_image.data(); | 216 | code_set->data.offset = loadinfo.seg_ptrs[2] - program_image.data(); |
| 220 | code_set->data.addr = loadinfo.seg_addrs[2]; | 217 | code_set->data.addr = loadinfo.seg_addrs[2]; |
| 221 | code_set->data.size = loadinfo.seg_sizes[2]; | 218 | code_set->data.size = loadinfo.seg_sizes[2]; |
| 222 | 219 | ||
| 223 | code_set->entrypoint = code_set->code.addr; | 220 | code_set->entrypoint = code_set->code.addr; |
| 224 | code_set->memory = std::make_shared<std::vector<u8>>(std::move(program_image)); | 221 | code_set->memory = std::make_shared<std::vector<u8>>(std::move(program_image)); |
| 225 | 222 | ||
| 226 | LOG_DEBUG(Loader, "code size: 0x%X", loadinfo.seg_sizes[0]); | 223 | LOG_DEBUG(Loader, "code size: 0x%X", loadinfo.seg_sizes[0]); |
| 227 | LOG_DEBUG(Loader, "rodata size: 0x%X", loadinfo.seg_sizes[1]); | 224 | LOG_DEBUG(Loader, "rodata size: 0x%X", loadinfo.seg_sizes[1]); |
| 228 | LOG_DEBUG(Loader, "data size: 0x%X (including 0x%X of bss)", loadinfo.seg_sizes[2], hdr.bss_size); | 225 | LOG_DEBUG(Loader, "data size: 0x%X (including 0x%X of bss)", loadinfo.seg_sizes[2], |
| 226 | hdr.bss_size); | ||
| 229 | 227 | ||
| 230 | *out_codeset = code_set; | 228 | *out_codeset = code_set; |
| 231 | return ERROR_NONE; | 229 | return ERROR_NONE; |
| @@ -260,17 +258,20 @@ ResultStatus AppLoader_THREEDSX::Load() { | |||
| 260 | Kernel::g_current_process->address_mappings = default_address_mappings; | 258 | Kernel::g_current_process->address_mappings = default_address_mappings; |
| 261 | 259 | ||
| 262 | // Attach the default resource limit (APPLICATION) to the process | 260 | // Attach the default resource limit (APPLICATION) to the process |
| 263 | Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); | 261 | Kernel::g_current_process->resource_limit = |
| 262 | Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); | ||
| 264 | 263 | ||
| 265 | Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); | 264 | Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); |
| 266 | 265 | ||
| 267 | Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this), Service::FS::ArchiveIdCode::RomFS); | 266 | Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this), |
| 267 | Service::FS::ArchiveIdCode::RomFS); | ||
| 268 | 268 | ||
| 269 | is_loaded = true; | 269 | is_loaded = true; |
| 270 | return ResultStatus::Success; | 270 | return ResultStatus::Success; |
| 271 | } | 271 | } |
| 272 | 272 | ||
| 273 | ResultStatus AppLoader_THREEDSX::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) { | 273 | ResultStatus AppLoader_THREEDSX::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, |
| 274 | u64& offset, u64& size) { | ||
| 274 | if (!file.IsOpen()) | 275 | if (!file.IsOpen()) |
| 275 | return ResultStatus::Error; | 276 | return ResultStatus::Error; |
| 276 | 277 | ||
diff --git a/src/core/loader/3dsx.h b/src/core/loader/3dsx.h index 90b20c61c..09a788a1c 100644 --- a/src/core/loader/3dsx.h +++ b/src/core/loader/3dsx.h | |||
| @@ -17,8 +17,10 @@ namespace Loader { | |||
| 17 | /// Loads an 3DSX file | 17 | /// Loads an 3DSX file |
| 18 | class AppLoader_THREEDSX final : public AppLoader { | 18 | class AppLoader_THREEDSX final : public AppLoader { |
| 19 | public: | 19 | public: |
| 20 | AppLoader_THREEDSX(FileUtil::IOFile&& file, const std::string& filename, const std::string& filepath) | 20 | AppLoader_THREEDSX(FileUtil::IOFile&& file, const std::string& filename, |
| 21 | : AppLoader(std::move(file)), filename(std::move(filename)), filepath(filepath) {} | 21 | const std::string& filepath) |
| 22 | : AppLoader(std::move(file)), filename(std::move(filename)), filepath(filepath) { | ||
| 23 | } | ||
| 22 | 24 | ||
| 23 | /** | 25 | /** |
| 24 | * Returns the type of the file | 26 | * Returns the type of the file |
| @@ -55,7 +57,8 @@ public: | |||
| 55 | * @param size Size of the RomFS in bytes | 57 | * @param size Size of the RomFS in bytes |
| 56 | * @return ResultStatus result of function | 58 | * @return ResultStatus result of function |
| 57 | */ | 59 | */ |
| 58 | ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) override; | 60 | ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, |
| 61 | u64& size) override; | ||
| 59 | 62 | ||
| 60 | private: | 63 | private: |
| 61 | std::string filename; | 64 | std::string filename; |
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index 69df94324..53c10a456 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cstring> | 5 | #include <cstring> |
| 6 | #include <string> | ||
| 7 | #include <memory> | 6 | #include <memory> |
| 7 | #include <string> | ||
| 8 | 8 | ||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/file_util.h" | 10 | #include "common/file_util.h" |
| @@ -24,112 +24,111 @@ using Kernel::CodeSet; | |||
| 24 | 24 | ||
| 25 | // File type | 25 | // File type |
| 26 | enum ElfType { | 26 | enum ElfType { |
| 27 | ET_NONE = 0, | 27 | ET_NONE = 0, |
| 28 | ET_REL = 1, | 28 | ET_REL = 1, |
| 29 | ET_EXEC = 2, | 29 | ET_EXEC = 2, |
| 30 | ET_DYN = 3, | 30 | ET_DYN = 3, |
| 31 | ET_CORE = 4, | 31 | ET_CORE = 4, |
| 32 | ET_LOPROC = 0xFF00, | 32 | ET_LOPROC = 0xFF00, |
| 33 | ET_HIPROC = 0xFFFF, | 33 | ET_HIPROC = 0xFFFF, |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | // Machine/Architecture | 36 | // Machine/Architecture |
| 37 | enum ElfMachine { | 37 | enum ElfMachine { |
| 38 | EM_NONE = 0, | 38 | EM_NONE = 0, |
| 39 | EM_M32 = 1, | 39 | EM_M32 = 1, |
| 40 | EM_SPARC = 2, | 40 | EM_SPARC = 2, |
| 41 | EM_386 = 3, | 41 | EM_386 = 3, |
| 42 | EM_68K = 4, | 42 | EM_68K = 4, |
| 43 | EM_88K = 5, | 43 | EM_88K = 5, |
| 44 | EM_860 = 7, | 44 | EM_860 = 7, |
| 45 | EM_MIPS = 8 | 45 | EM_MIPS = 8 |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | // File version | 48 | // File version |
| 49 | #define EV_NONE 0 | 49 | #define EV_NONE 0 |
| 50 | #define EV_CURRENT 1 | 50 | #define EV_CURRENT 1 |
| 51 | 51 | ||
| 52 | // Identification index | 52 | // Identification index |
| 53 | #define EI_MAG0 0 | 53 | #define EI_MAG0 0 |
| 54 | #define EI_MAG1 1 | 54 | #define EI_MAG1 1 |
| 55 | #define EI_MAG2 2 | 55 | #define EI_MAG2 2 |
| 56 | #define EI_MAG3 3 | 56 | #define EI_MAG3 3 |
| 57 | #define EI_CLASS 4 | 57 | #define EI_CLASS 4 |
| 58 | #define EI_DATA 5 | 58 | #define EI_DATA 5 |
| 59 | #define EI_VERSION 6 | 59 | #define EI_VERSION 6 |
| 60 | #define EI_PAD 7 | 60 | #define EI_PAD 7 |
| 61 | #define EI_NIDENT 16 | 61 | #define EI_NIDENT 16 |
| 62 | 62 | ||
| 63 | // Sections constants | 63 | // Sections constants |
| 64 | 64 | ||
| 65 | // Section types | 65 | // Section types |
| 66 | #define SHT_NULL 0 | 66 | #define SHT_NULL 0 |
| 67 | #define SHT_PROGBITS 1 | 67 | #define SHT_PROGBITS 1 |
| 68 | #define SHT_SYMTAB 2 | 68 | #define SHT_SYMTAB 2 |
| 69 | #define SHT_STRTAB 3 | 69 | #define SHT_STRTAB 3 |
| 70 | #define SHT_RELA 4 | 70 | #define SHT_RELA 4 |
| 71 | #define SHT_HASH 5 | 71 | #define SHT_HASH 5 |
| 72 | #define SHT_DYNAMIC 6 | 72 | #define SHT_DYNAMIC 6 |
| 73 | #define SHT_NOTE 7 | 73 | #define SHT_NOTE 7 |
| 74 | #define SHT_NOBITS 8 | 74 | #define SHT_NOBITS 8 |
| 75 | #define SHT_REL 9 | 75 | #define SHT_REL 9 |
| 76 | #define SHT_SHLIB 10 | 76 | #define SHT_SHLIB 10 |
| 77 | #define SHT_DYNSYM 11 | 77 | #define SHT_DYNSYM 11 |
| 78 | #define SHT_LOPROC 0x70000000 | 78 | #define SHT_LOPROC 0x70000000 |
| 79 | #define SHT_HIPROC 0x7FFFFFFF | 79 | #define SHT_HIPROC 0x7FFFFFFF |
| 80 | #define SHT_LOUSER 0x80000000 | 80 | #define SHT_LOUSER 0x80000000 |
| 81 | #define SHT_HIUSER 0xFFFFFFFF | 81 | #define SHT_HIUSER 0xFFFFFFFF |
| 82 | 82 | ||
| 83 | // Section flags | 83 | // Section flags |
| 84 | enum ElfSectionFlags | 84 | enum ElfSectionFlags { |
| 85 | { | 85 | SHF_WRITE = 0x1, |
| 86 | SHF_WRITE = 0x1, | 86 | SHF_ALLOC = 0x2, |
| 87 | SHF_ALLOC = 0x2, | ||
| 88 | SHF_EXECINSTR = 0x4, | 87 | SHF_EXECINSTR = 0x4, |
| 89 | SHF_MASKPROC = 0xF0000000, | 88 | SHF_MASKPROC = 0xF0000000, |
| 90 | }; | 89 | }; |
| 91 | 90 | ||
| 92 | // Segment types | 91 | // Segment types |
| 93 | #define PT_NULL 0 | 92 | #define PT_NULL 0 |
| 94 | #define PT_LOAD 1 | 93 | #define PT_LOAD 1 |
| 95 | #define PT_DYNAMIC 2 | 94 | #define PT_DYNAMIC 2 |
| 96 | #define PT_INTERP 3 | 95 | #define PT_INTERP 3 |
| 97 | #define PT_NOTE 4 | 96 | #define PT_NOTE 4 |
| 98 | #define PT_SHLIB 5 | 97 | #define PT_SHLIB 5 |
| 99 | #define PT_PHDR 6 | 98 | #define PT_PHDR 6 |
| 100 | #define PT_LOPROC 0x70000000 | 99 | #define PT_LOPROC 0x70000000 |
| 101 | #define PT_HIPROC 0x7FFFFFFF | 100 | #define PT_HIPROC 0x7FFFFFFF |
| 102 | 101 | ||
| 103 | // Segment flags | 102 | // Segment flags |
| 104 | #define PF_X 0x1 | 103 | #define PF_X 0x1 |
| 105 | #define PF_W 0x2 | 104 | #define PF_W 0x2 |
| 106 | #define PF_R 0x4 | 105 | #define PF_R 0x4 |
| 107 | #define PF_MASKPROC 0xF0000000 | 106 | #define PF_MASKPROC 0xF0000000 |
| 108 | 107 | ||
| 109 | typedef unsigned int Elf32_Addr; | 108 | typedef unsigned int Elf32_Addr; |
| 110 | typedef unsigned short Elf32_Half; | 109 | typedef unsigned short Elf32_Half; |
| 111 | typedef unsigned int Elf32_Off; | 110 | typedef unsigned int Elf32_Off; |
| 112 | typedef signed int Elf32_Sword; | 111 | typedef signed int Elf32_Sword; |
| 113 | typedef unsigned int Elf32_Word; | 112 | typedef unsigned int Elf32_Word; |
| 114 | 113 | ||
| 115 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 114 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 116 | // ELF file header | 115 | // ELF file header |
| 117 | 116 | ||
| 118 | struct Elf32_Ehdr { | 117 | struct Elf32_Ehdr { |
| 119 | unsigned char e_ident[EI_NIDENT]; | 118 | unsigned char e_ident[EI_NIDENT]; |
| 120 | Elf32_Half e_type; | 119 | Elf32_Half e_type; |
| 121 | Elf32_Half e_machine; | 120 | Elf32_Half e_machine; |
| 122 | Elf32_Word e_version; | 121 | Elf32_Word e_version; |
| 123 | Elf32_Addr e_entry; | 122 | Elf32_Addr e_entry; |
| 124 | Elf32_Off e_phoff; | 123 | Elf32_Off e_phoff; |
| 125 | Elf32_Off e_shoff; | 124 | Elf32_Off e_shoff; |
| 126 | Elf32_Word e_flags; | 125 | Elf32_Word e_flags; |
| 127 | Elf32_Half e_ehsize; | 126 | Elf32_Half e_ehsize; |
| 128 | Elf32_Half e_phentsize; | 127 | Elf32_Half e_phentsize; |
| 129 | Elf32_Half e_phnum; | 128 | Elf32_Half e_phnum; |
| 130 | Elf32_Half e_shentsize; | 129 | Elf32_Half e_shentsize; |
| 131 | Elf32_Half e_shnum; | 130 | Elf32_Half e_shnum; |
| 132 | Elf32_Half e_shstrndx; | 131 | Elf32_Half e_shstrndx; |
| 133 | }; | 132 | }; |
| 134 | 133 | ||
| 135 | // Section header | 134 | // Section header |
| @@ -138,7 +137,7 @@ struct Elf32_Shdr { | |||
| 138 | Elf32_Word sh_type; | 137 | Elf32_Word sh_type; |
| 139 | Elf32_Word sh_flags; | 138 | Elf32_Word sh_flags; |
| 140 | Elf32_Addr sh_addr; | 139 | Elf32_Addr sh_addr; |
| 141 | Elf32_Off sh_offset; | 140 | Elf32_Off sh_offset; |
| 142 | Elf32_Word sh_size; | 141 | Elf32_Word sh_size; |
| 143 | Elf32_Word sh_link; | 142 | Elf32_Word sh_link; |
| 144 | Elf32_Word sh_info; | 143 | Elf32_Word sh_info; |
| @@ -149,7 +148,7 @@ struct Elf32_Shdr { | |||
| 149 | // Segment header | 148 | // Segment header |
| 150 | struct Elf32_Phdr { | 149 | struct Elf32_Phdr { |
| 151 | Elf32_Word p_type; | 150 | Elf32_Word p_type; |
| 152 | Elf32_Off p_offset; | 151 | Elf32_Off p_offset; |
| 153 | Elf32_Addr p_vaddr; | 152 | Elf32_Addr p_vaddr; |
| 154 | Elf32_Addr p_paddr; | 153 | Elf32_Addr p_paddr; |
| 155 | Elf32_Word p_filesz; | 154 | Elf32_Word p_filesz; |
| @@ -160,12 +159,12 @@ struct Elf32_Phdr { | |||
| 160 | 159 | ||
| 161 | // Symbol table entry | 160 | // Symbol table entry |
| 162 | struct Elf32_Sym { | 161 | struct Elf32_Sym { |
| 163 | Elf32_Word st_name; | 162 | Elf32_Word st_name; |
| 164 | Elf32_Addr st_value; | 163 | Elf32_Addr st_value; |
| 165 | Elf32_Word st_size; | 164 | Elf32_Word st_size; |
| 166 | unsigned char st_info; | 165 | unsigned char st_info; |
| 167 | unsigned char st_other; | 166 | unsigned char st_other; |
| 168 | Elf32_Half st_shndx; | 167 | Elf32_Half st_shndx; |
| 169 | }; | 168 | }; |
| 170 | 169 | ||
| 171 | // Relocation entries | 170 | // Relocation entries |
| @@ -181,35 +180,51 @@ typedef int SectionID; | |||
| 181 | 180 | ||
| 182 | class ElfReader { | 181 | class ElfReader { |
| 183 | private: | 182 | private: |
| 184 | char *base; | 183 | char* base; |
| 185 | u32 *base32; | 184 | u32* base32; |
| 186 | 185 | ||
| 187 | Elf32_Ehdr *header; | 186 | Elf32_Ehdr* header; |
| 188 | Elf32_Phdr *segments; | 187 | Elf32_Phdr* segments; |
| 189 | Elf32_Shdr *sections; | 188 | Elf32_Shdr* sections; |
| 190 | 189 | ||
| 191 | u32 *sectionAddrs; | 190 | u32* sectionAddrs; |
| 192 | bool relocate; | 191 | bool relocate; |
| 193 | u32 entryPoint; | 192 | u32 entryPoint; |
| 194 | 193 | ||
| 195 | public: | 194 | public: |
| 196 | ElfReader(void *ptr); | 195 | ElfReader(void* ptr); |
| 197 | 196 | ||
| 198 | u32 Read32(int off) const { return base32[off >> 2]; } | 197 | u32 Read32(int off) const { |
| 198 | return base32[off >> 2]; | ||
| 199 | } | ||
| 199 | 200 | ||
| 200 | // Quick accessors | 201 | // Quick accessors |
| 201 | ElfType GetType() const { return (ElfType)(header->e_type); } | 202 | ElfType GetType() const { |
| 202 | ElfMachine GetMachine() const { return (ElfMachine)(header->e_machine); } | 203 | return (ElfType)(header->e_type); |
| 203 | u32 GetEntryPoint() const { return entryPoint; } | 204 | } |
| 204 | u32 GetFlags() const { return (u32)(header->e_flags); } | 205 | ElfMachine GetMachine() const { |
| 206 | return (ElfMachine)(header->e_machine); | ||
| 207 | } | ||
| 208 | u32 GetEntryPoint() const { | ||
| 209 | return entryPoint; | ||
| 210 | } | ||
| 211 | u32 GetFlags() const { | ||
| 212 | return (u32)(header->e_flags); | ||
| 213 | } | ||
| 205 | SharedPtr<CodeSet> LoadInto(u32 vaddr); | 214 | SharedPtr<CodeSet> LoadInto(u32 vaddr); |
| 206 | bool LoadSymbols(); | 215 | bool LoadSymbols(); |
| 207 | 216 | ||
| 208 | int GetNumSegments() const { return (int)(header->e_phnum); } | 217 | int GetNumSegments() const { |
| 209 | int GetNumSections() const { return (int)(header->e_shnum); } | 218 | return (int)(header->e_phnum); |
| 210 | const u8 *GetPtr(int offset) const { return (u8*)base + offset; } | 219 | } |
| 211 | const char *GetSectionName(int section) const; | 220 | int GetNumSections() const { |
| 212 | const u8 *GetSectionDataPtr(int section) const { | 221 | return (int)(header->e_shnum); |
| 222 | } | ||
| 223 | const u8* GetPtr(int offset) const { | ||
| 224 | return (u8*)base + offset; | ||
| 225 | } | ||
| 226 | const char* GetSectionName(int section) const; | ||
| 227 | const u8* GetSectionDataPtr(int section) const { | ||
| 213 | if (section < 0 || section >= header->e_shnum) | 228 | if (section < 0 || section >= header->e_shnum) |
| 214 | return nullptr; | 229 | return nullptr; |
| 215 | if (sections[section].sh_type != SHT_NOBITS) | 230 | if (sections[section].sh_type != SHT_NOBITS) |
| @@ -220,19 +235,23 @@ public: | |||
| 220 | bool IsCodeSection(int section) const { | 235 | bool IsCodeSection(int section) const { |
| 221 | return sections[section].sh_type == SHT_PROGBITS; | 236 | return sections[section].sh_type == SHT_PROGBITS; |
| 222 | } | 237 | } |
| 223 | const u8 *GetSegmentPtr(int segment) { | 238 | const u8* GetSegmentPtr(int segment) { |
| 224 | return GetPtr(segments[segment].p_offset); | 239 | return GetPtr(segments[segment].p_offset); |
| 225 | } | 240 | } |
| 226 | u32 GetSectionAddr(SectionID section) const { return sectionAddrs[section]; } | 241 | u32 GetSectionAddr(SectionID section) const { |
| 227 | unsigned int GetSectionSize(SectionID section) const { return sections[section].sh_size; } | 242 | return sectionAddrs[section]; |
| 228 | SectionID GetSectionByName(const char *name, int firstSection = 0) const; //-1 for not found | 243 | } |
| 244 | unsigned int GetSectionSize(SectionID section) const { | ||
| 245 | return sections[section].sh_size; | ||
| 246 | } | ||
| 247 | SectionID GetSectionByName(const char* name, int firstSection = 0) const; //-1 for not found | ||
| 229 | 248 | ||
| 230 | bool DidRelocate() const { | 249 | bool DidRelocate() const { |
| 231 | return relocate; | 250 | return relocate; |
| 232 | } | 251 | } |
| 233 | }; | 252 | }; |
| 234 | 253 | ||
| 235 | ElfReader::ElfReader(void *ptr) { | 254 | ElfReader::ElfReader(void* ptr) { |
| 236 | base = (char*)ptr; | 255 | base = (char*)ptr; |
| 237 | base32 = (u32*)ptr; | 256 | base32 = (u32*)ptr; |
| 238 | header = (Elf32_Ehdr*)ptr; | 257 | header = (Elf32_Ehdr*)ptr; |
| @@ -245,7 +264,7 @@ ElfReader::ElfReader(void *ptr) { | |||
| 245 | LoadSymbols(); | 264 | LoadSymbols(); |
| 246 | } | 265 | } |
| 247 | 266 | ||
| 248 | const char *ElfReader::GetSectionName(int section) const { | 267 | const char* ElfReader::GetSectionName(int section) const { |
| 249 | if (sections[section].sh_type == SHT_NULL) | 268 | if (sections[section].sh_type == SHT_NULL) |
| 250 | return nullptr; | 269 | return nullptr; |
| 251 | 270 | ||
| @@ -303,12 +322,15 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) { | |||
| 303 | } else if (permission_flags == (PF_R | PF_W)) { | 322 | } else if (permission_flags == (PF_R | PF_W)) { |
| 304 | codeset_segment = &codeset->data; | 323 | codeset_segment = &codeset->data; |
| 305 | } else { | 324 | } else { |
| 306 | LOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id %u with flags %X", i, p->p_flags); | 325 | LOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id %u with flags %X", i, |
| 326 | p->p_flags); | ||
| 307 | continue; | 327 | continue; |
| 308 | } | 328 | } |
| 309 | 329 | ||
| 310 | if (codeset_segment->size != 0) { | 330 | if (codeset_segment->size != 0) { |
| 311 | LOG_ERROR(Loader, "ELF has more than one segment of the same type. Skipping extra segment (id %i)", i); | 331 | LOG_ERROR(Loader, "ELF has more than one segment of the same type. Skipping extra " |
| 332 | "segment (id %i)", | ||
| 333 | i); | ||
| 312 | continue; | 334 | continue; |
| 313 | } | 335 | } |
| 314 | 336 | ||
| @@ -332,9 +354,9 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) { | |||
| 332 | return codeset; | 354 | return codeset; |
| 333 | } | 355 | } |
| 334 | 356 | ||
| 335 | SectionID ElfReader::GetSectionByName(const char *name, int firstSection) const { | 357 | SectionID ElfReader::GetSectionByName(const char* name, int firstSection) const { |
| 336 | for (int i = firstSection; i < header->e_shnum; i++) { | 358 | for (int i = firstSection; i < header->e_shnum; i++) { |
| 337 | const char *secname = GetSectionName(i); | 359 | const char* secname = GetSectionName(i); |
| 338 | 360 | ||
| 339 | if (secname != nullptr && strcmp(name, secname) == 0) | 361 | if (secname != nullptr && strcmp(name, secname) == 0) |
| 340 | return i; | 362 | return i; |
| @@ -347,9 +369,9 @@ bool ElfReader::LoadSymbols() { | |||
| 347 | SectionID sec = GetSectionByName(".symtab"); | 369 | SectionID sec = GetSectionByName(".symtab"); |
| 348 | if (sec != -1) { | 370 | if (sec != -1) { |
| 349 | int stringSection = sections[sec].sh_link; | 371 | int stringSection = sections[sec].sh_link; |
| 350 | const char *stringBase = reinterpret_cast<const char*>(GetSectionDataPtr(stringSection)); | 372 | const char* stringBase = reinterpret_cast<const char*>(GetSectionDataPtr(stringSection)); |
| 351 | 373 | ||
| 352 | //We have a symbol table! | 374 | // We have a symbol table! |
| 353 | const Elf32_Sym* symtab = reinterpret_cast<const Elf32_Sym*>(GetSectionDataPtr(sec)); | 375 | const Elf32_Sym* symtab = reinterpret_cast<const Elf32_Sym*>(GetSectionDataPtr(sec)); |
| 354 | unsigned int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym); | 376 | unsigned int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym); |
| 355 | for (unsigned sym = 0; sym < numSymbols; sym++) { | 377 | for (unsigned sym = 0; sym < numSymbols; sym++) { |
| @@ -359,7 +381,7 @@ bool ElfReader::LoadSymbols() { | |||
| 359 | 381 | ||
| 360 | int type = symtab[sym].st_info & 0xF; | 382 | int type = symtab[sym].st_info & 0xF; |
| 361 | 383 | ||
| 362 | const char *name = stringBase + symtab[sym].st_name; | 384 | const char* name = stringBase + symtab[sym].st_name; |
| 363 | 385 | ||
| 364 | Symbols::Add(symtab[sym].st_value, name, size, type); | 386 | Symbols::Add(symtab[sym].st_value, name, size, type); |
| 365 | 387 | ||
| @@ -411,7 +433,8 @@ ResultStatus AppLoader_ELF::Load() { | |||
| 411 | Kernel::g_current_process->address_mappings = default_address_mappings; | 433 | Kernel::g_current_process->address_mappings = default_address_mappings; |
| 412 | 434 | ||
| 413 | // Attach the default resource limit (APPLICATION) to the process | 435 | // Attach the default resource limit (APPLICATION) to the process |
| 414 | Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); | 436 | Kernel::g_current_process->resource_limit = |
| 437 | Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); | ||
| 415 | 438 | ||
| 416 | Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); | 439 | Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); |
| 417 | 440 | ||
diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h index cb3724f9d..0b1456c64 100644 --- a/src/core/loader/elf.h +++ b/src/core/loader/elf.h | |||
| @@ -18,7 +18,8 @@ namespace Loader { | |||
| 18 | class AppLoader_ELF final : public AppLoader { | 18 | class AppLoader_ELF final : public AppLoader { |
| 19 | public: | 19 | public: |
| 20 | AppLoader_ELF(FileUtil::IOFile&& file, std::string filename) | 20 | AppLoader_ELF(FileUtil::IOFile&& file, std::string filename) |
| 21 | : AppLoader(std::move(file)), filename(std::move(filename)) { } | 21 | : AppLoader(std::move(file)), filename(std::move(filename)) { |
| 22 | } | ||
| 22 | 23 | ||
| 23 | /** | 24 | /** |
| 24 | * Returns the type of the file | 25 | * Returns the type of the file |
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 9719d30d5..b392bf544 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp | |||
| @@ -18,17 +18,17 @@ | |||
| 18 | namespace Loader { | 18 | namespace Loader { |
| 19 | 19 | ||
| 20 | const std::initializer_list<Kernel::AddressMapping> default_address_mappings = { | 20 | const std::initializer_list<Kernel::AddressMapping> default_address_mappings = { |
| 21 | { 0x1FF50000, 0x8000, true }, // part of DSP RAM | 21 | {0x1FF50000, 0x8000, true}, // part of DSP RAM |
| 22 | { 0x1FF70000, 0x8000, true }, // part of DSP RAM | 22 | {0x1FF70000, 0x8000, true}, // part of DSP RAM |
| 23 | { 0x1F000000, 0x600000, false }, // entire VRAM | 23 | {0x1F000000, 0x600000, false}, // entire VRAM |
| 24 | }; | 24 | }; |
| 25 | 25 | ||
| 26 | FileType IdentifyFile(FileUtil::IOFile& file) { | 26 | FileType IdentifyFile(FileUtil::IOFile& file) { |
| 27 | FileType type; | 27 | FileType type; |
| 28 | 28 | ||
| 29 | #define CHECK_TYPE(loader) \ | 29 | #define CHECK_TYPE(loader) \ |
| 30 | type = AppLoader_##loader::IdentifyType(file); \ | 30 | type = AppLoader_##loader::IdentifyType(file); \ |
| 31 | if (FileType::Error != type) \ | 31 | if (FileType::Error != type) \ |
| 32 | return type; | 32 | return type; |
| 33 | 33 | ||
| 34 | CHECK_TYPE(THREEDSX) | 34 | CHECK_TYPE(THREEDSX) |
| @@ -100,7 +100,8 @@ const char* GetFileTypeString(FileType type) { | |||
| 100 | * @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type | 100 | * @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type |
| 101 | */ | 101 | */ |
| 102 | static std::unique_ptr<AppLoader> GetFileLoader(FileUtil::IOFile&& file, FileType type, | 102 | static std::unique_ptr<AppLoader> GetFileLoader(FileUtil::IOFile&& file, FileType type, |
| 103 | const std::string& filename, const std::string& filepath) { | 103 | const std::string& filename, |
| 104 | const std::string& filepath) { | ||
| 104 | switch (type) { | 105 | switch (type) { |
| 105 | 106 | ||
| 106 | // 3DSX file format. | 107 | // 3DSX file format. |
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index 77d87afe1..5f48d2ffe 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h | |||
| @@ -30,7 +30,7 @@ enum class FileType { | |||
| 30 | CXI, | 30 | CXI, |
| 31 | CIA, | 31 | CIA, |
| 32 | ELF, | 32 | ELF, |
| 33 | THREEDSX, //3DSX | 33 | THREEDSX, // 3DSX |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | /** | 36 | /** |
| @@ -81,8 +81,10 @@ constexpr u32 MakeMagic(char a, char b, char c, char d) { | |||
| 81 | /// Interface for loading an application | 81 | /// Interface for loading an application |
| 82 | class AppLoader : NonCopyable { | 82 | class AppLoader : NonCopyable { |
| 83 | public: | 83 | public: |
| 84 | AppLoader(FileUtil::IOFile&& file) : file(std::move(file)) { } | 84 | AppLoader(FileUtil::IOFile&& file) : file(std::move(file)) { |
| 85 | virtual ~AppLoader() { } | 85 | } |
| 86 | virtual ~AppLoader() { | ||
| 87 | } | ||
| 86 | 88 | ||
| 87 | /** | 89 | /** |
| 88 | * Returns the type of this file | 90 | * Returns the type of this file |
| @@ -140,7 +142,8 @@ public: | |||
| 140 | * @param size The size of the romfs | 142 | * @param size The size of the romfs |
| 141 | * @return ResultStatus result of function | 143 | * @return ResultStatus result of function |
| 142 | */ | 144 | */ |
| 143 | virtual ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) { | 145 | virtual ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, |
| 146 | u64& size) { | ||
| 144 | return ResultStatus::ErrorNotImplemented; | 147 | return ResultStatus::ErrorNotImplemented; |
| 145 | } | 148 | } |
| 146 | 149 | ||
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index fca091ff9..5b996d671 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp | |||
| @@ -22,8 +22,8 @@ | |||
| 22 | 22 | ||
| 23 | namespace Loader { | 23 | namespace Loader { |
| 24 | 24 | ||
| 25 | static const int kMaxSections = 8; ///< Maximum number of sections (files) in an ExeFs | 25 | static const int kMaxSections = 8; ///< Maximum number of sections (files) in an ExeFs |
| 26 | static const int kBlockSize = 0x200; ///< Size of ExeFS blocks (in bytes) | 26 | static const int kBlockSize = 0x200; ///< Size of ExeFS blocks (in bytes) |
| 27 | 27 | ||
| 28 | /** | 28 | /** |
| 29 | * Get the decompressed size of an LZSS compressed ExeFS file | 29 | * Get the decompressed size of an LZSS compressed ExeFS file |
| @@ -44,7 +44,8 @@ static u32 LZSS_GetDecompressedSize(const u8* buffer, u32 size) { | |||
| 44 | * @param decompressed_size Size of decompressed buffer | 44 | * @param decompressed_size Size of decompressed buffer |
| 45 | * @return True on success, otherwise false | 45 | * @return True on success, otherwise false |
| 46 | */ | 46 | */ |
| 47 | static bool LZSS_Decompress(const u8* compressed, u32 compressed_size, u8* decompressed, u32 decompressed_size) { | 47 | static bool LZSS_Decompress(const u8* compressed, u32 compressed_size, u8* decompressed, |
| 48 | u32 decompressed_size) { | ||
| 48 | const u8* footer = compressed + compressed_size - 8; | 49 | const u8* footer = compressed + compressed_size - 8; |
| 49 | u32 buffer_top_and_bottom = *reinterpret_cast<const u32*>(footer); | 50 | u32 buffer_top_and_bottom = *reinterpret_cast<const u32*>(footer); |
| 50 | u32 out = decompressed_size; | 51 | u32 out = decompressed_size; |
| @@ -55,7 +56,7 @@ static bool LZSS_Decompress(const u8* compressed, u32 compressed_size, u8* decom | |||
| 55 | memcpy(decompressed, compressed, compressed_size); | 56 | memcpy(decompressed, compressed, compressed_size); |
| 56 | 57 | ||
| 57 | while (index > stop_index) { | 58 | while (index > stop_index) { |
| 58 | u8 control = compressed[--index]; | 59 | u8 control = compressed[--index]; |
| 59 | 60 | ||
| 60 | for (unsigned i = 0; i < 8; i++) { | 61 | for (unsigned i = 0; i < 8; i++) { |
| 61 | if (index <= stop_index) | 62 | if (index <= stop_index) |
| @@ -128,7 +129,7 @@ ResultStatus AppLoader_NCCH::LoadExec() { | |||
| 128 | std::vector<u8> code; | 129 | std::vector<u8> code; |
| 129 | if (ResultStatus::Success == ReadCode(code)) { | 130 | if (ResultStatus::Success == ReadCode(code)) { |
| 130 | std::string process_name = Common::StringFromFixedZeroTerminatedBuffer( | 131 | std::string process_name = Common::StringFromFixedZeroTerminatedBuffer( |
| 131 | (const char*)exheader_header.codeset_info.name, 8); | 132 | (const char*)exheader_header.codeset_info.name, 8); |
| 132 | 133 | ||
| 133 | SharedPtr<CodeSet> codeset = CodeSet::Create(process_name, ncch_header.program_id); | 134 | SharedPtr<CodeSet> codeset = CodeSet::Create(process_name, ncch_header.program_id); |
| 134 | 135 | ||
| @@ -147,7 +148,8 @@ ResultStatus AppLoader_NCCH::LoadExec() { | |||
| 147 | 148 | ||
| 148 | codeset->data.offset = codeset->rodata.offset + codeset->rodata.size; | 149 | codeset->data.offset = codeset->rodata.offset + codeset->rodata.size; |
| 149 | codeset->data.addr = exheader_header.codeset_info.data.address; | 150 | codeset->data.addr = exheader_header.codeset_info.data.address; |
| 150 | codeset->data.size = exheader_header.codeset_info.data.num_max_pages * Memory::PAGE_SIZE + bss_page_size; | 151 | codeset->data.size = |
| 152 | exheader_header.codeset_info.data.num_max_pages * Memory::PAGE_SIZE + bss_page_size; | ||
| 151 | 153 | ||
| 152 | codeset->entrypoint = codeset->code.addr; | 154 | codeset->entrypoint = codeset->code.addr; |
| 153 | codeset->memory = std::make_shared<std::vector<u8>>(std::move(code)); | 155 | codeset->memory = std::make_shared<std::vector<u8>>(std::move(code)); |
| @@ -155,15 +157,18 @@ ResultStatus AppLoader_NCCH::LoadExec() { | |||
| 155 | Kernel::g_current_process = Kernel::Process::Create(std::move(codeset)); | 157 | Kernel::g_current_process = Kernel::Process::Create(std::move(codeset)); |
| 156 | 158 | ||
| 157 | // Attach a resource limit to the process based on the resource limit category | 159 | // Attach a resource limit to the process based on the resource limit category |
| 158 | Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory( | 160 | Kernel::g_current_process->resource_limit = |
| 159 | static_cast<Kernel::ResourceLimitCategory>(exheader_header.arm11_system_local_caps.resource_limit_category)); | 161 | Kernel::ResourceLimit::GetForCategory(static_cast<Kernel::ResourceLimitCategory>( |
| 162 | exheader_header.arm11_system_local_caps.resource_limit_category)); | ||
| 160 | 163 | ||
| 161 | // Set the default CPU core for this process | 164 | // Set the default CPU core for this process |
| 162 | Kernel::g_current_process->ideal_processor = exheader_header.arm11_system_local_caps.ideal_processor; | 165 | Kernel::g_current_process->ideal_processor = |
| 166 | exheader_header.arm11_system_local_caps.ideal_processor; | ||
| 163 | 167 | ||
| 164 | // Copy data while converting endianess | 168 | // Copy data while converting endianess |
| 165 | std::array<u32, ARRAY_SIZE(exheader_header.arm11_kernel_caps.descriptors)> kernel_caps; | 169 | std::array<u32, ARRAY_SIZE(exheader_header.arm11_kernel_caps.descriptors)> kernel_caps; |
| 166 | std::copy_n(exheader_header.arm11_kernel_caps.descriptors, kernel_caps.size(), begin(kernel_caps)); | 170 | std::copy_n(exheader_header.arm11_kernel_caps.descriptors, kernel_caps.size(), |
| 171 | begin(kernel_caps)); | ||
| 167 | Kernel::g_current_process->ParseKernelCaps(kernel_caps.data(), kernel_caps.size()); | 172 | Kernel::g_current_process->ParseKernelCaps(kernel_caps.data(), kernel_caps.size()); |
| 168 | 173 | ||
| 169 | s32 priority = exheader_header.arm11_system_local_caps.priority; | 174 | s32 priority = exheader_header.arm11_system_local_caps.priority; |
| @@ -192,7 +197,8 @@ ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector<u8>& | |||
| 192 | LOG_DEBUG(Loader, "%d - offset: 0x%08X, size: 0x%08X, name: %s", section_number, | 197 | LOG_DEBUG(Loader, "%d - offset: 0x%08X, size: 0x%08X, name: %s", section_number, |
| 193 | section.offset, section.size, section.name); | 198 | section.offset, section.size, section.name); |
| 194 | 199 | ||
| 195 | s64 section_offset = (section.offset + exefs_offset + sizeof(ExeFs_Header) + ncch_offset); | 200 | s64 section_offset = |
| 201 | (section.offset + exefs_offset + sizeof(ExeFs_Header) + ncch_offset); | ||
| 196 | file.Seek(section_offset, SEEK_SET); | 202 | file.Seek(section_offset, SEEK_SET); |
| 197 | 203 | ||
| 198 | if (strcmp(section.name, ".code") == 0 && is_compressed) { | 204 | if (strcmp(section.name, ".code") == 0 && is_compressed) { |
| @@ -254,25 +260,25 @@ ResultStatus AppLoader_NCCH::LoadExeFS() { | |||
| 254 | if (file.ReadBytes(&exheader_header, sizeof(ExHeader_Header)) != sizeof(ExHeader_Header)) | 260 | if (file.ReadBytes(&exheader_header, sizeof(ExHeader_Header)) != sizeof(ExHeader_Header)) |
| 255 | return ResultStatus::Error; | 261 | return ResultStatus::Error; |
| 256 | 262 | ||
| 257 | is_compressed = (exheader_header.codeset_info.flags.flag & 1) == 1; | 263 | is_compressed = (exheader_header.codeset_info.flags.flag & 1) == 1; |
| 258 | entry_point = exheader_header.codeset_info.text.address; | 264 | entry_point = exheader_header.codeset_info.text.address; |
| 259 | code_size = exheader_header.codeset_info.text.code_size; | 265 | code_size = exheader_header.codeset_info.text.code_size; |
| 260 | stack_size = exheader_header.codeset_info.stack_size; | 266 | stack_size = exheader_header.codeset_info.stack_size; |
| 261 | bss_size = exheader_header.codeset_info.bss_size; | 267 | bss_size = exheader_header.codeset_info.bss_size; |
| 262 | core_version = exheader_header.arm11_system_local_caps.core_version; | 268 | core_version = exheader_header.arm11_system_local_caps.core_version; |
| 263 | priority = exheader_header.arm11_system_local_caps.priority; | 269 | priority = exheader_header.arm11_system_local_caps.priority; |
| 264 | resource_limit_category = exheader_header.arm11_system_local_caps.resource_limit_category; | 270 | resource_limit_category = exheader_header.arm11_system_local_caps.resource_limit_category; |
| 265 | 271 | ||
| 266 | LOG_INFO(Loader, "Name: %s" , exheader_header.codeset_info.name); | 272 | LOG_INFO(Loader, "Name: %s", exheader_header.codeset_info.name); |
| 267 | LOG_INFO(Loader, "Program ID: %016llX" , ncch_header.program_id); | 273 | LOG_INFO(Loader, "Program ID: %016llX", ncch_header.program_id); |
| 268 | LOG_DEBUG(Loader, "Code compressed: %s" , is_compressed ? "yes" : "no"); | 274 | LOG_DEBUG(Loader, "Code compressed: %s", is_compressed ? "yes" : "no"); |
| 269 | LOG_DEBUG(Loader, "Entry point: 0x%08X", entry_point); | 275 | LOG_DEBUG(Loader, "Entry point: 0x%08X", entry_point); |
| 270 | LOG_DEBUG(Loader, "Code size: 0x%08X", code_size); | 276 | LOG_DEBUG(Loader, "Code size: 0x%08X", code_size); |
| 271 | LOG_DEBUG(Loader, "Stack size: 0x%08X", stack_size); | 277 | LOG_DEBUG(Loader, "Stack size: 0x%08X", stack_size); |
| 272 | LOG_DEBUG(Loader, "Bss size: 0x%08X", bss_size); | 278 | LOG_DEBUG(Loader, "Bss size: 0x%08X", bss_size); |
| 273 | LOG_DEBUG(Loader, "Core version: %d" , core_version); | 279 | LOG_DEBUG(Loader, "Core version: %d", core_version); |
| 274 | LOG_DEBUG(Loader, "Thread priority: 0x%X" , priority); | 280 | LOG_DEBUG(Loader, "Thread priority: 0x%X", priority); |
| 275 | LOG_DEBUG(Loader, "Resource limit category: %d" , resource_limit_category); | 281 | LOG_DEBUG(Loader, "Resource limit category: %d", resource_limit_category); |
| 276 | 282 | ||
| 277 | if (exheader_header.arm11_system_local_caps.program_id != ncch_header.program_id) { | 283 | if (exheader_header.arm11_system_local_caps.program_id != ncch_header.program_id) { |
| 278 | LOG_ERROR(Loader, "ExHeader Program ID mismatch: the ROM is probably encrypted."); | 284 | LOG_ERROR(Loader, "ExHeader Program ID mismatch: the ROM is probably encrypted."); |
| @@ -309,7 +315,8 @@ ResultStatus AppLoader_NCCH::Load() { | |||
| 309 | if (ResultStatus::Success != result) | 315 | if (ResultStatus::Success != result) |
| 310 | return result; | 316 | return result; |
| 311 | 317 | ||
| 312 | Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this), Service::FS::ArchiveIdCode::RomFS); | 318 | Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this), |
| 319 | Service::FS::ArchiveIdCode::RomFS); | ||
| 313 | return ResultStatus::Success; | 320 | return ResultStatus::Success; |
| 314 | } | 321 | } |
| 315 | 322 | ||
| @@ -329,7 +336,8 @@ ResultStatus AppLoader_NCCH::ReadLogo(std::vector<u8>& buffer) { | |||
| 329 | return LoadSectionExeFS("logo", buffer); | 336 | return LoadSectionExeFS("logo", buffer); |
| 330 | } | 337 | } |
| 331 | 338 | ||
| 332 | ResultStatus AppLoader_NCCH::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) { | 339 | ResultStatus AppLoader_NCCH::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, |
| 340 | u64& size) { | ||
| 333 | if (!file.IsOpen()) | 341 | if (!file.IsOpen()) |
| 334 | return ResultStatus::Error; | 342 | return ResultStatus::Error; |
| 335 | 343 | ||
| @@ -341,7 +349,7 @@ ResultStatus AppLoader_NCCH::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_ | |||
| 341 | LOG_DEBUG(Loader, "RomFS offset: 0x%08X", romfs_offset); | 349 | LOG_DEBUG(Loader, "RomFS offset: 0x%08X", romfs_offset); |
| 342 | LOG_DEBUG(Loader, "RomFS size: 0x%08X", romfs_size); | 350 | LOG_DEBUG(Loader, "RomFS size: 0x%08X", romfs_size); |
| 343 | 351 | ||
| 344 | if (file.GetSize () < romfs_offset + romfs_size) | 352 | if (file.GetSize() < romfs_offset + romfs_size) |
| 345 | return ResultStatus::Error; | 353 | return ResultStatus::Error; |
| 346 | 354 | ||
| 347 | // We reopen the file, to allow its position to be independent from file's | 355 | // We reopen the file, to allow its position to be independent from file's |
diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h index 75609ee57..0cd70f70c 100644 --- a/src/core/loader/ncch.h +++ b/src/core/loader/ncch.h | |||
| @@ -164,7 +164,8 @@ namespace Loader { | |||
| 164 | class AppLoader_NCCH final : public AppLoader { | 164 | class AppLoader_NCCH final : public AppLoader { |
| 165 | public: | 165 | public: |
| 166 | AppLoader_NCCH(FileUtil::IOFile&& file, const std::string& filepath) | 166 | AppLoader_NCCH(FileUtil::IOFile&& file, const std::string& filepath) |
| 167 | : AppLoader(std::move(file)), filepath(filepath) { } | 167 | : AppLoader(std::move(file)), filepath(filepath) { |
| 168 | } | ||
| 168 | 169 | ||
| 169 | /** | 170 | /** |
| 170 | * Returns the type of the file | 171 | * Returns the type of the file |
| @@ -222,10 +223,10 @@ public: | |||
| 222 | * @param size Size of the RomFS in bytes | 223 | * @param size Size of the RomFS in bytes |
| 223 | * @return ResultStatus result of function | 224 | * @return ResultStatus result of function |
| 224 | */ | 225 | */ |
| 225 | ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) override; | 226 | ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, |
| 227 | u64& size) override; | ||
| 226 | 228 | ||
| 227 | private: | 229 | private: |
| 228 | |||
| 229 | /** | 230 | /** |
| 230 | * Reads an application ExeFS section of an NCCH file into AppLoader (e.g. .code, .logo, etc.) | 231 | * Reads an application ExeFS section of an NCCH file into AppLoader (e.g. .code, .logo, etc.) |
| 231 | * @param name Name of section to read out of NCCH file | 232 | * @param name Name of section to read out of NCCH file |
| @@ -246,24 +247,24 @@ private: | |||
| 246 | */ | 247 | */ |
| 247 | ResultStatus LoadExeFS(); | 248 | ResultStatus LoadExeFS(); |
| 248 | 249 | ||
| 249 | bool is_exefs_loaded = false; | 250 | bool is_exefs_loaded = false; |
| 250 | bool is_compressed = false; | 251 | bool is_compressed = false; |
| 251 | 252 | ||
| 252 | u32 entry_point = 0; | 253 | u32 entry_point = 0; |
| 253 | u32 code_size = 0; | 254 | u32 code_size = 0; |
| 254 | u32 stack_size = 0; | 255 | u32 stack_size = 0; |
| 255 | u32 bss_size = 0; | 256 | u32 bss_size = 0; |
| 256 | u32 core_version = 0; | 257 | u32 core_version = 0; |
| 257 | u8 priority = 0; | 258 | u8 priority = 0; |
| 258 | u8 resource_limit_category = 0; | 259 | u8 resource_limit_category = 0; |
| 259 | u32 ncch_offset = 0; // Offset to NCCH header, can be 0 or after NCSD header | 260 | u32 ncch_offset = 0; // Offset to NCCH header, can be 0 or after NCSD header |
| 260 | u32 exefs_offset = 0; | 261 | u32 exefs_offset = 0; |
| 261 | 262 | ||
| 262 | NCCH_Header ncch_header; | 263 | NCCH_Header ncch_header; |
| 263 | ExeFs_Header exefs_header; | 264 | ExeFs_Header exefs_header; |
| 264 | ExHeader_Header exheader_header; | 265 | ExHeader_Header exheader_header; |
| 265 | 266 | ||
| 266 | std::string filepath; | 267 | std::string filepath; |
| 267 | }; | 268 | }; |
| 268 | 269 | ||
| 269 | } // namespace Loader | 270 | } // namespace Loader |
diff --git a/src/core/loader/smdh.h b/src/core/loader/smdh.h index 2011abda2..ab665ea82 100644 --- a/src/core/loader/smdh.h +++ b/src/core/loader/smdh.h | |||
| @@ -56,7 +56,7 @@ struct SMDH { | |||
| 56 | Italian = 4, | 56 | Italian = 4, |
| 57 | Spanish = 5, | 57 | Spanish = 5, |
| 58 | SimplifiedChinese = 6, | 58 | SimplifiedChinese = 6, |
| 59 | Korean= 7, | 59 | Korean = 7, |
| 60 | Dutch = 8, | 60 | Dutch = 8, |
| 61 | Portuguese = 9, | 61 | Portuguese = 9, |
| 62 | Russian = 10, | 62 | Russian = 10, |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 9aa8c4e5a..4de510fe5 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -25,11 +25,13 @@ enum class PageType { | |||
| 25 | Unmapped, | 25 | Unmapped, |
| 26 | /// Page is mapped to regular memory. This is the only type you can get pointers to. | 26 | /// Page is mapped to regular memory. This is the only type you can get pointers to. |
| 27 | Memory, | 27 | Memory, |
| 28 | /// Page is mapped to regular memory, but also needs to check for rasterizer cache flushing and invalidation | 28 | /// Page is mapped to regular memory, but also needs to check for rasterizer cache flushing and |
| 29 | /// invalidation | ||
| 29 | RasterizerCachedMemory, | 30 | RasterizerCachedMemory, |
| 30 | /// Page is mapped to a I/O region. Writing and reading to this page is handled by functions. | 31 | /// Page is mapped to a I/O region. Writing and reading to this page is handled by functions. |
| 31 | Special, | 32 | Special, |
| 32 | /// Page is mapped to a I/O region, but also needs to check for rasterizer cache flushing and invalidation | 33 | /// Page is mapped to a I/O region, but also needs to check for rasterizer cache flushing and |
| 34 | /// invalidation | ||
| 33 | RasterizerCachedSpecial, | 35 | RasterizerCachedSpecial, |
| 34 | }; | 36 | }; |
| 35 | 37 | ||
| @@ -55,7 +57,8 @@ struct PageTable { | |||
| 55 | std::array<u8*, NUM_ENTRIES> pointers; | 57 | std::array<u8*, NUM_ENTRIES> pointers; |
| 56 | 58 | ||
| 57 | /** | 59 | /** |
| 58 | * Contains MMIO handlers that back memory regions whose entries in the `attribute` array is of type `Special`. | 60 | * Contains MMIO handlers that back memory regions whose entries in the `attribute` array is of |
| 61 | * type `Special`. | ||
| 59 | */ | 62 | */ |
| 60 | std::vector<SpecialRegion> special_regions; | 63 | std::vector<SpecialRegion> special_regions; |
| 61 | 64 | ||
| @@ -78,17 +81,20 @@ static PageTable main_page_table; | |||
| 78 | static PageTable* current_page_table = &main_page_table; | 81 | static PageTable* current_page_table = &main_page_table; |
| 79 | 82 | ||
| 80 | static void MapPages(u32 base, u32 size, u8* memory, PageType type) { | 83 | static void MapPages(u32 base, u32 size, u8* memory, PageType type) { |
| 81 | LOG_DEBUG(HW_Memory, "Mapping %p onto %08X-%08X", memory, base * PAGE_SIZE, (base + size) * PAGE_SIZE); | 84 | LOG_DEBUG(HW_Memory, "Mapping %p onto %08X-%08X", memory, base * PAGE_SIZE, |
| 85 | (base + size) * PAGE_SIZE); | ||
| 82 | 86 | ||
| 83 | u32 end = base + size; | 87 | u32 end = base + size; |
| 84 | 88 | ||
| 85 | while (base != end) { | 89 | while (base != end) { |
| 86 | ASSERT_MSG(base < PageTable::NUM_ENTRIES, "out of range mapping at %08X", base); | 90 | ASSERT_MSG(base < PageTable::NUM_ENTRIES, "out of range mapping at %08X", base); |
| 87 | 91 | ||
| 88 | // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be null here | 92 | // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be |
| 93 | // null here | ||
| 89 | if (current_page_table->attributes[base] == PageType::RasterizerCachedMemory || | 94 | if (current_page_table->attributes[base] == PageType::RasterizerCachedMemory || |
| 90 | current_page_table->attributes[base] == PageType::RasterizerCachedSpecial) { | 95 | current_page_table->attributes[base] == PageType::RasterizerCachedSpecial) { |
| 91 | RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(base << PAGE_BITS), PAGE_SIZE); | 96 | RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(base << PAGE_BITS), |
| 97 | PAGE_SIZE); | ||
| 92 | } | 98 | } |
| 93 | 99 | ||
| 94 | current_page_table->attributes[base] = type; | 100 | current_page_table->attributes[base] = type; |
| @@ -162,7 +168,7 @@ static MMIORegionPointer GetMMIOHandler(VAddr vaddr) { | |||
| 162 | return nullptr; // Should never happen | 168 | return nullptr; // Should never happen |
| 163 | } | 169 | } |
| 164 | 170 | ||
| 165 | template<typename T> | 171 | template <typename T> |
| 166 | T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr); | 172 | T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr); |
| 167 | 173 | ||
| 168 | template <typename T> | 174 | template <typename T> |
| @@ -183,8 +189,7 @@ T Read(const VAddr vaddr) { | |||
| 183 | case PageType::Memory: | 189 | case PageType::Memory: |
| 184 | ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); | 190 | ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); |
| 185 | break; | 191 | break; |
| 186 | case PageType::RasterizerCachedMemory: | 192 | case PageType::RasterizerCachedMemory: { |
| 187 | { | ||
| 188 | RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); | 193 | RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); |
| 189 | 194 | ||
| 190 | T value; | 195 | T value; |
| @@ -193,8 +198,7 @@ T Read(const VAddr vaddr) { | |||
| 193 | } | 198 | } |
| 194 | case PageType::Special: | 199 | case PageType::Special: |
| 195 | return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr); | 200 | return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr); |
| 196 | case PageType::RasterizerCachedSpecial: | 201 | case PageType::RasterizerCachedSpecial: { |
| 197 | { | ||
| 198 | RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); | 202 | RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); |
| 199 | 203 | ||
| 200 | return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr); | 204 | return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr); |
| @@ -204,7 +208,7 @@ T Read(const VAddr vaddr) { | |||
| 204 | } | 208 | } |
| 205 | } | 209 | } |
| 206 | 210 | ||
| 207 | template<typename T> | 211 | template <typename T> |
| 208 | void WriteMMIO(MMIORegionPointer mmio_handler, VAddr addr, const T data); | 212 | void WriteMMIO(MMIORegionPointer mmio_handler, VAddr addr, const T data); |
| 209 | 213 | ||
| 210 | template <typename T> | 214 | template <typename T> |
| @@ -219,13 +223,13 @@ void Write(const VAddr vaddr, const T data) { | |||
| 219 | PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; | 223 | PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; |
| 220 | switch (type) { | 224 | switch (type) { |
| 221 | case PageType::Unmapped: | 225 | case PageType::Unmapped: |
| 222 | LOG_ERROR(HW_Memory, "unmapped Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32) data, vaddr); | 226 | LOG_ERROR(HW_Memory, "unmapped Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, |
| 227 | vaddr); | ||
| 223 | return; | 228 | return; |
| 224 | case PageType::Memory: | 229 | case PageType::Memory: |
| 225 | ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); | 230 | ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); |
| 226 | break; | 231 | break; |
| 227 | case PageType::RasterizerCachedMemory: | 232 | case PageType::RasterizerCachedMemory: { |
| 228 | { | ||
| 229 | RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); | 233 | RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); |
| 230 | 234 | ||
| 231 | std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T)); | 235 | std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T)); |
| @@ -234,8 +238,7 @@ void Write(const VAddr vaddr, const T data) { | |||
| 234 | case PageType::Special: | 238 | case PageType::Special: |
| 235 | WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data); | 239 | WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data); |
| 236 | break; | 240 | break; |
| 237 | case PageType::RasterizerCachedSpecial: | 241 | case PageType::RasterizerCachedSpecial: { |
| 238 | { | ||
| 239 | RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); | 242 | RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); |
| 240 | 243 | ||
| 241 | WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data); | 244 | WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data); |
| @@ -310,7 +313,8 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) { | |||
| 310 | for (unsigned i = 0; i < num_pages; ++i) { | 313 | for (unsigned i = 0; i < num_pages; ++i) { |
| 311 | VAddr vaddr = PhysicalToVirtualAddress(paddr); | 314 | VAddr vaddr = PhysicalToVirtualAddress(paddr); |
| 312 | u8& res_count = current_page_table->cached_res_count[vaddr >> PAGE_BITS]; | 315 | u8& res_count = current_page_table->cached_res_count[vaddr >> PAGE_BITS]; |
| 313 | ASSERT_MSG(count_delta <= UINT8_MAX - res_count, "Rasterizer resource cache counter overflow!"); | 316 | ASSERT_MSG(count_delta <= UINT8_MAX - res_count, |
| 317 | "Rasterizer resource cache counter overflow!"); | ||
| 314 | ASSERT_MSG(count_delta >= -res_count, "Rasterizer resource cache counter underflow!"); | 318 | ASSERT_MSG(count_delta >= -res_count, "Rasterizer resource cache counter underflow!"); |
| 315 | 319 | ||
| 316 | // Switch page type to cached if now cached | 320 | // Switch page type to cached if now cached |
| @@ -337,7 +341,8 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) { | |||
| 337 | switch (page_type) { | 341 | switch (page_type) { |
| 338 | case PageType::RasterizerCachedMemory: | 342 | case PageType::RasterizerCachedMemory: |
| 339 | page_type = PageType::Memory; | 343 | page_type = PageType::Memory; |
| 340 | current_page_table->pointers[vaddr >> PAGE_BITS] = GetPointerFromVMA(vaddr & ~PAGE_MASK); | 344 | current_page_table->pointers[vaddr >> PAGE_BITS] = |
| 345 | GetPointerFromVMA(vaddr & ~PAGE_MASK); | ||
| 341 | break; | 346 | break; |
| 342 | case PageType::RasterizerCachedSpecial: | 347 | case PageType::RasterizerCachedSpecial: |
| 343 | page_type = PageType::Special; | 348 | page_type = PageType::Special; |
| @@ -389,7 +394,8 @@ void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) { | |||
| 389 | 394 | ||
| 390 | switch (current_page_table->attributes[page_index]) { | 395 | switch (current_page_table->attributes[page_index]) { |
| 391 | case PageType::Unmapped: { | 396 | case PageType::Unmapped: { |
| 392 | LOG_ERROR(HW_Memory, "unmapped ReadBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size); | 397 | LOG_ERROR(HW_Memory, "unmapped ReadBlock @ 0x%08X (start address = 0x%08X, size = %zu)", |
| 398 | current_vaddr, src_addr, size); | ||
| 393 | std::memset(dest_buffer, 0, copy_amount); | 399 | std::memset(dest_buffer, 0, copy_amount); |
| 394 | break; | 400 | break; |
| 395 | } | 401 | } |
| @@ -458,7 +464,9 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size | |||
| 458 | 464 | ||
| 459 | switch (current_page_table->attributes[page_index]) { | 465 | switch (current_page_table->attributes[page_index]) { |
| 460 | case PageType::Unmapped: { | 466 | case PageType::Unmapped: { |
| 461 | LOG_ERROR(HW_Memory, "unmapped WriteBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size); | 467 | LOG_ERROR(HW_Memory, |
| 468 | "unmapped WriteBlock @ 0x%08X (start address = 0x%08X, size = %zu)", | ||
| 469 | current_vaddr, dest_addr, size); | ||
| 462 | break; | 470 | break; |
| 463 | } | 471 | } |
| 464 | case PageType::Memory: { | 472 | case PageType::Memory: { |
| @@ -475,7 +483,8 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size | |||
| 475 | break; | 483 | break; |
| 476 | } | 484 | } |
| 477 | case PageType::RasterizerCachedMemory: { | 485 | case PageType::RasterizerCachedMemory: { |
| 478 | RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | 486 | RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), |
| 487 | copy_amount); | ||
| 479 | 488 | ||
| 480 | std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount); | 489 | std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount); |
| 481 | break; | 490 | break; |
| @@ -483,7 +492,8 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size | |||
| 483 | case PageType::RasterizerCachedSpecial: { | 492 | case PageType::RasterizerCachedSpecial: { |
| 484 | DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); | 493 | DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); |
| 485 | 494 | ||
| 486 | RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | 495 | RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), |
| 496 | copy_amount); | ||
| 487 | 497 | ||
| 488 | GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); | 498 | GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); |
| 489 | break; | 499 | break; |
| @@ -512,7 +522,8 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) { | |||
| 512 | 522 | ||
| 513 | switch (current_page_table->attributes[page_index]) { | 523 | switch (current_page_table->attributes[page_index]) { |
| 514 | case PageType::Unmapped: { | 524 | case PageType::Unmapped: { |
| 515 | LOG_ERROR(HW_Memory, "unmapped ZeroBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size); | 525 | LOG_ERROR(HW_Memory, "unmapped ZeroBlock @ 0x%08X (start address = 0x%08X, size = %zu)", |
| 526 | current_vaddr, dest_addr, size); | ||
| 516 | break; | 527 | break; |
| 517 | } | 528 | } |
| 518 | case PageType::Memory: { | 529 | case PageType::Memory: { |
| @@ -529,7 +540,8 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) { | |||
| 529 | break; | 540 | break; |
| 530 | } | 541 | } |
| 531 | case PageType::RasterizerCachedMemory: { | 542 | case PageType::RasterizerCachedMemory: { |
| 532 | RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | 543 | RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), |
| 544 | copy_amount); | ||
| 533 | 545 | ||
| 534 | std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount); | 546 | std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount); |
| 535 | break; | 547 | break; |
| @@ -537,7 +549,8 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) { | |||
| 537 | case PageType::RasterizerCachedSpecial: { | 549 | case PageType::RasterizerCachedSpecial: { |
| 538 | DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); | 550 | DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); |
| 539 | 551 | ||
| 540 | RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | 552 | RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), |
| 553 | copy_amount); | ||
| 541 | 554 | ||
| 542 | GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount); | 555 | GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount); |
| 543 | break; | 556 | break; |
| @@ -563,7 +576,8 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) { | |||
| 563 | 576 | ||
| 564 | switch (current_page_table->attributes[page_index]) { | 577 | switch (current_page_table->attributes[page_index]) { |
| 565 | case PageType::Unmapped: { | 578 | case PageType::Unmapped: { |
| 566 | LOG_ERROR(HW_Memory, "unmapped CopyBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size); | 579 | LOG_ERROR(HW_Memory, "unmapped CopyBlock @ 0x%08X (start address = 0x%08X, size = %zu)", |
| 580 | current_vaddr, src_addr, size); | ||
| 567 | ZeroBlock(dest_addr, copy_amount); | 581 | ZeroBlock(dest_addr, copy_amount); |
| 568 | break; | 582 | break; |
| 569 | } | 583 | } |
| @@ -609,42 +623,42 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) { | |||
| 609 | } | 623 | } |
| 610 | } | 624 | } |
| 611 | 625 | ||
| 612 | template<> | 626 | template <> |
| 613 | u8 ReadMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr) { | 627 | u8 ReadMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr) { |
| 614 | return mmio_handler->Read8(addr); | 628 | return mmio_handler->Read8(addr); |
| 615 | } | 629 | } |
| 616 | 630 | ||
| 617 | template<> | 631 | template <> |
| 618 | u16 ReadMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr) { | 632 | u16 ReadMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr) { |
| 619 | return mmio_handler->Read16(addr); | 633 | return mmio_handler->Read16(addr); |
| 620 | } | 634 | } |
| 621 | 635 | ||
| 622 | template<> | 636 | template <> |
| 623 | u32 ReadMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr) { | 637 | u32 ReadMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr) { |
| 624 | return mmio_handler->Read32(addr); | 638 | return mmio_handler->Read32(addr); |
| 625 | } | 639 | } |
| 626 | 640 | ||
| 627 | template<> | 641 | template <> |
| 628 | u64 ReadMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr) { | 642 | u64 ReadMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr) { |
| 629 | return mmio_handler->Read64(addr); | 643 | return mmio_handler->Read64(addr); |
| 630 | } | 644 | } |
| 631 | 645 | ||
| 632 | template<> | 646 | template <> |
| 633 | void WriteMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr, const u8 data) { | 647 | void WriteMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr, const u8 data) { |
| 634 | mmio_handler->Write8(addr, data); | 648 | mmio_handler->Write8(addr, data); |
| 635 | } | 649 | } |
| 636 | 650 | ||
| 637 | template<> | 651 | template <> |
| 638 | void WriteMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr, const u16 data) { | 652 | void WriteMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr, const u16 data) { |
| 639 | mmio_handler->Write16(addr, data); | 653 | mmio_handler->Write16(addr, data); |
| 640 | } | 654 | } |
| 641 | 655 | ||
| 642 | template<> | 656 | template <> |
| 643 | void WriteMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr, const u32 data) { | 657 | void WriteMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr, const u32 data) { |
| 644 | mmio_handler->Write32(addr, data); | 658 | mmio_handler->Write32(addr, data); |
| 645 | } | 659 | } |
| 646 | 660 | ||
| 647 | template<> | 661 | template <> |
| 648 | void WriteMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr, const u64 data) { | 662 | void WriteMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr, const u64 data) { |
| 649 | mmio_handler->Write64(addr, data); | 663 | mmio_handler->Write64(addr, data); |
| 650 | } | 664 | } |
diff --git a/src/core/memory.h b/src/core/memory.h index cad845385..7d60ccdf1 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -22,92 +22,93 @@ const int PAGE_BITS = 12; | |||
| 22 | /// Physical memory regions as seen from the ARM11 | 22 | /// Physical memory regions as seen from the ARM11 |
| 23 | enum : PAddr { | 23 | enum : PAddr { |
| 24 | /// IO register area | 24 | /// IO register area |
| 25 | IO_AREA_PADDR = 0x10100000, | 25 | IO_AREA_PADDR = 0x10100000, |
| 26 | IO_AREA_SIZE = 0x01000000, ///< IO area size (16MB) | 26 | IO_AREA_SIZE = 0x01000000, ///< IO area size (16MB) |
| 27 | IO_AREA_PADDR_END = IO_AREA_PADDR + IO_AREA_SIZE, | 27 | IO_AREA_PADDR_END = IO_AREA_PADDR + IO_AREA_SIZE, |
| 28 | 28 | ||
| 29 | /// MPCore internal memory region | 29 | /// MPCore internal memory region |
| 30 | MPCORE_RAM_PADDR = 0x17E00000, | 30 | MPCORE_RAM_PADDR = 0x17E00000, |
| 31 | MPCORE_RAM_SIZE = 0x00002000, ///< MPCore internal memory size (8KB) | 31 | MPCORE_RAM_SIZE = 0x00002000, ///< MPCore internal memory size (8KB) |
| 32 | MPCORE_RAM_PADDR_END = MPCORE_RAM_PADDR + MPCORE_RAM_SIZE, | 32 | MPCORE_RAM_PADDR_END = MPCORE_RAM_PADDR + MPCORE_RAM_SIZE, |
| 33 | 33 | ||
| 34 | /// Video memory | 34 | /// Video memory |
| 35 | VRAM_PADDR = 0x18000000, | 35 | VRAM_PADDR = 0x18000000, |
| 36 | VRAM_SIZE = 0x00600000, ///< VRAM size (6MB) | 36 | VRAM_SIZE = 0x00600000, ///< VRAM size (6MB) |
| 37 | VRAM_PADDR_END = VRAM_PADDR + VRAM_SIZE, | 37 | VRAM_PADDR_END = VRAM_PADDR + VRAM_SIZE, |
| 38 | 38 | ||
| 39 | /// DSP memory | 39 | /// DSP memory |
| 40 | DSP_RAM_PADDR = 0x1FF00000, | 40 | DSP_RAM_PADDR = 0x1FF00000, |
| 41 | DSP_RAM_SIZE = 0x00080000, ///< DSP memory size (512KB) | 41 | DSP_RAM_SIZE = 0x00080000, ///< DSP memory size (512KB) |
| 42 | DSP_RAM_PADDR_END = DSP_RAM_PADDR + DSP_RAM_SIZE, | 42 | DSP_RAM_PADDR_END = DSP_RAM_PADDR + DSP_RAM_SIZE, |
| 43 | 43 | ||
| 44 | /// AXI WRAM | 44 | /// AXI WRAM |
| 45 | AXI_WRAM_PADDR = 0x1FF80000, | 45 | AXI_WRAM_PADDR = 0x1FF80000, |
| 46 | AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size (512KB) | 46 | AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size (512KB) |
| 47 | AXI_WRAM_PADDR_END = AXI_WRAM_PADDR + AXI_WRAM_SIZE, | 47 | AXI_WRAM_PADDR_END = AXI_WRAM_PADDR + AXI_WRAM_SIZE, |
| 48 | 48 | ||
| 49 | /// Main FCRAM | 49 | /// Main FCRAM |
| 50 | FCRAM_PADDR = 0x20000000, | 50 | FCRAM_PADDR = 0x20000000, |
| 51 | FCRAM_SIZE = 0x08000000, ///< FCRAM size (128MB) | 51 | FCRAM_SIZE = 0x08000000, ///< FCRAM size (128MB) |
| 52 | FCRAM_PADDR_END = FCRAM_PADDR + FCRAM_SIZE, | 52 | FCRAM_PADDR_END = FCRAM_PADDR + FCRAM_SIZE, |
| 53 | }; | 53 | }; |
| 54 | 54 | ||
| 55 | /// Virtual user-space memory regions | 55 | /// Virtual user-space memory regions |
| 56 | enum : VAddr { | 56 | enum : VAddr { |
| 57 | /// Where the application text, data and bss reside. | 57 | /// Where the application text, data and bss reside. |
| 58 | PROCESS_IMAGE_VADDR = 0x00100000, | 58 | PROCESS_IMAGE_VADDR = 0x00100000, |
| 59 | PROCESS_IMAGE_MAX_SIZE = 0x03F00000, | 59 | PROCESS_IMAGE_MAX_SIZE = 0x03F00000, |
| 60 | PROCESS_IMAGE_VADDR_END = PROCESS_IMAGE_VADDR + PROCESS_IMAGE_MAX_SIZE, | 60 | PROCESS_IMAGE_VADDR_END = PROCESS_IMAGE_VADDR + PROCESS_IMAGE_MAX_SIZE, |
| 61 | 61 | ||
| 62 | /// Area where IPC buffers are mapped onto. | 62 | /// Area where IPC buffers are mapped onto. |
| 63 | IPC_MAPPING_VADDR = 0x04000000, | 63 | IPC_MAPPING_VADDR = 0x04000000, |
| 64 | IPC_MAPPING_SIZE = 0x04000000, | 64 | IPC_MAPPING_SIZE = 0x04000000, |
| 65 | IPC_MAPPING_VADDR_END = IPC_MAPPING_VADDR + IPC_MAPPING_SIZE, | 65 | IPC_MAPPING_VADDR_END = IPC_MAPPING_VADDR + IPC_MAPPING_SIZE, |
| 66 | 66 | ||
| 67 | /// Application heap (includes stack). | 67 | /// Application heap (includes stack). |
| 68 | HEAP_VADDR = 0x08000000, | 68 | HEAP_VADDR = 0x08000000, |
| 69 | HEAP_SIZE = 0x08000000, | 69 | HEAP_SIZE = 0x08000000, |
| 70 | HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE, | 70 | HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE, |
| 71 | 71 | ||
| 72 | /// Area where shared memory buffers are mapped onto. | 72 | /// Area where shared memory buffers are mapped onto. |
| 73 | SHARED_MEMORY_VADDR = 0x10000000, | 73 | SHARED_MEMORY_VADDR = 0x10000000, |
| 74 | SHARED_MEMORY_SIZE = 0x04000000, | 74 | SHARED_MEMORY_SIZE = 0x04000000, |
| 75 | SHARED_MEMORY_VADDR_END = SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE, | 75 | SHARED_MEMORY_VADDR_END = SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE, |
| 76 | 76 | ||
| 77 | /// Maps 1:1 to an offset in FCRAM. Used for HW allocations that need to be linear in physical memory. | 77 | /// Maps 1:1 to an offset in FCRAM. Used for HW allocations that need to be linear in physical |
| 78 | LINEAR_HEAP_VADDR = 0x14000000, | 78 | /// memory. |
| 79 | LINEAR_HEAP_SIZE = 0x08000000, | 79 | LINEAR_HEAP_VADDR = 0x14000000, |
| 80 | LINEAR_HEAP_SIZE = 0x08000000, | ||
| 80 | LINEAR_HEAP_VADDR_END = LINEAR_HEAP_VADDR + LINEAR_HEAP_SIZE, | 81 | LINEAR_HEAP_VADDR_END = LINEAR_HEAP_VADDR + LINEAR_HEAP_SIZE, |
| 81 | 82 | ||
| 82 | /// Maps 1:1 to the IO register area. | 83 | /// Maps 1:1 to the IO register area. |
| 83 | IO_AREA_VADDR = 0x1EC00000, | 84 | IO_AREA_VADDR = 0x1EC00000, |
| 84 | IO_AREA_VADDR_END = IO_AREA_VADDR + IO_AREA_SIZE, | 85 | IO_AREA_VADDR_END = IO_AREA_VADDR + IO_AREA_SIZE, |
| 85 | 86 | ||
| 86 | /// Maps 1:1 to VRAM. | 87 | /// Maps 1:1 to VRAM. |
| 87 | VRAM_VADDR = 0x1F000000, | 88 | VRAM_VADDR = 0x1F000000, |
| 88 | VRAM_VADDR_END = VRAM_VADDR + VRAM_SIZE, | 89 | VRAM_VADDR_END = VRAM_VADDR + VRAM_SIZE, |
| 89 | 90 | ||
| 90 | /// Maps 1:1 to DSP memory. | 91 | /// Maps 1:1 to DSP memory. |
| 91 | DSP_RAM_VADDR = 0x1FF00000, | 92 | DSP_RAM_VADDR = 0x1FF00000, |
| 92 | DSP_RAM_VADDR_END = DSP_RAM_VADDR + DSP_RAM_SIZE, | 93 | DSP_RAM_VADDR_END = DSP_RAM_VADDR + DSP_RAM_SIZE, |
| 93 | 94 | ||
| 94 | /// Read-only page containing kernel and system configuration values. | 95 | /// Read-only page containing kernel and system configuration values. |
| 95 | CONFIG_MEMORY_VADDR = 0x1FF80000, | 96 | CONFIG_MEMORY_VADDR = 0x1FF80000, |
| 96 | CONFIG_MEMORY_SIZE = 0x00001000, | 97 | CONFIG_MEMORY_SIZE = 0x00001000, |
| 97 | CONFIG_MEMORY_VADDR_END = CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE, | 98 | CONFIG_MEMORY_VADDR_END = CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE, |
| 98 | 99 | ||
| 99 | /// Usually read-only page containing mostly values read from hardware. | 100 | /// Usually read-only page containing mostly values read from hardware. |
| 100 | SHARED_PAGE_VADDR = 0x1FF81000, | 101 | SHARED_PAGE_VADDR = 0x1FF81000, |
| 101 | SHARED_PAGE_SIZE = 0x00001000, | 102 | SHARED_PAGE_SIZE = 0x00001000, |
| 102 | SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE, | 103 | SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE, |
| 103 | 104 | ||
| 104 | /// Area where TLS (Thread-Local Storage) buffers are allocated. | 105 | /// Area where TLS (Thread-Local Storage) buffers are allocated. |
| 105 | TLS_AREA_VADDR = 0x1FF82000, | 106 | TLS_AREA_VADDR = 0x1FF82000, |
| 106 | TLS_ENTRY_SIZE = 0x200, | 107 | TLS_ENTRY_SIZE = 0x200, |
| 107 | 108 | ||
| 108 | /// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS. | 109 | /// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS. |
| 109 | NEW_LINEAR_HEAP_VADDR = 0x30000000, | 110 | NEW_LINEAR_HEAP_VADDR = 0x30000000, |
| 110 | NEW_LINEAR_HEAP_SIZE = 0x10000000, | 111 | NEW_LINEAR_HEAP_SIZE = 0x10000000, |
| 111 | NEW_LINEAR_HEAP_VADDR_END = NEW_LINEAR_HEAP_VADDR + NEW_LINEAR_HEAP_SIZE, | 112 | NEW_LINEAR_HEAP_VADDR_END = NEW_LINEAR_HEAP_VADDR + NEW_LINEAR_HEAP_SIZE, |
| 112 | }; | 113 | }; |
| 113 | 114 | ||
| @@ -166,5 +167,4 @@ void RasterizerFlushRegion(PAddr start, u32 size); | |||
| 166 | * Flushes and invalidates any externally cached rasterizer resources touching the given region. | 167 | * Flushes and invalidates any externally cached rasterizer resources touching the given region. |
| 167 | */ | 168 | */ |
| 168 | void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size); | 169 | void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size); |
| 169 | |||
| 170 | } | 170 | } |
diff --git a/src/core/memory_setup.h b/src/core/memory_setup.h index ee8ea7857..23c36d019 100644 --- a/src/core/memory_setup.h +++ b/src/core/memory_setup.h | |||
| @@ -30,5 +30,4 @@ void MapMemoryRegion(VAddr base, u32 size, u8* target); | |||
| 30 | void MapIoRegion(VAddr base, u32 size, MMIORegionPointer mmio_handler); | 30 | void MapIoRegion(VAddr base, u32 size, MMIORegionPointer mmio_handler); |
| 31 | 31 | ||
| 32 | void UnmapRegion(VAddr base, u32 size); | 32 | void UnmapRegion(VAddr base, u32 size); |
| 33 | |||
| 34 | } | 33 | } |
diff --git a/src/core/mmio.h b/src/core/mmio.h index d76f005d8..9aa59212b 100644 --- a/src/core/mmio.h +++ b/src/core/mmio.h | |||
| @@ -36,5 +36,4 @@ public: | |||
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | using MMIORegionPointer = std::shared_ptr<MMIORegion>; | 38 | using MMIORegionPointer = std::shared_ptr<MMIORegion>; |
| 39 | |||
| 40 | }; | 39 | }; |
diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 1b6733a79..09194fe1f 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp | |||
| @@ -25,7 +25,6 @@ void Apply() { | |||
| 25 | 25 | ||
| 26 | AudioCore::SelectSink(values.sink_id); | 26 | AudioCore::SelectSink(values.sink_id); |
| 27 | AudioCore::EnableStretching(values.enable_audio_stretching); | 27 | AudioCore::EnableStretching(values.enable_audio_stretching); |
| 28 | |||
| 29 | } | 28 | } |
| 30 | 29 | ||
| 31 | } // namespace | 30 | } // namespace |
diff --git a/src/core/settings.h b/src/core/settings.h index fcd14c6f3..adb2fd538 100644 --- a/src/core/settings.h +++ b/src/core/settings.h | |||
| @@ -4,8 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <string> | ||
| 8 | #include <array> | 7 | #include <array> |
| 8 | #include <string> | ||
| 9 | 9 | ||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | 11 | ||
| @@ -14,14 +14,31 @@ namespace Settings { | |||
| 14 | namespace NativeInput { | 14 | namespace NativeInput { |
| 15 | enum Values { | 15 | enum Values { |
| 16 | // directly mapped keys | 16 | // directly mapped keys |
| 17 | A, B, X, Y, | 17 | A, |
| 18 | L, R, ZL, ZR, | 18 | B, |
| 19 | START, SELECT, HOME, | 19 | X, |
| 20 | DUP, DDOWN, DLEFT, DRIGHT, | 20 | Y, |
| 21 | CUP, CDOWN, CLEFT, CRIGHT, | 21 | L, |
| 22 | R, | ||
| 23 | ZL, | ||
| 24 | ZR, | ||
| 25 | START, | ||
| 26 | SELECT, | ||
| 27 | HOME, | ||
| 28 | DUP, | ||
| 29 | DDOWN, | ||
| 30 | DLEFT, | ||
| 31 | DRIGHT, | ||
| 32 | CUP, | ||
| 33 | CDOWN, | ||
| 34 | CLEFT, | ||
| 35 | CRIGHT, | ||
| 22 | 36 | ||
| 23 | // indirectly mapped keys | 37 | // indirectly mapped keys |
| 24 | CIRCLE_UP, CIRCLE_DOWN, CIRCLE_LEFT, CIRCLE_RIGHT, | 38 | CIRCLE_UP, |
| 39 | CIRCLE_DOWN, | ||
| 40 | CIRCLE_LEFT, | ||
| 41 | CIRCLE_RIGHT, | ||
| 25 | CIRCLE_MODIFIER, | 42 | CIRCLE_MODIFIER, |
| 26 | 43 | ||
| 27 | NUM_INPUTS | 44 | NUM_INPUTS |
| @@ -29,28 +46,21 @@ enum Values { | |||
| 29 | 46 | ||
| 30 | static const std::array<const char*, NUM_INPUTS> Mapping = {{ | 47 | static const std::array<const char*, NUM_INPUTS> Mapping = {{ |
| 31 | // directly mapped keys | 48 | // directly mapped keys |
| 32 | "pad_a", "pad_b", "pad_x", "pad_y", | 49 | "pad_a", "pad_b", "pad_x", "pad_y", "pad_l", "pad_r", "pad_zl", "pad_zr", "pad_start", |
| 33 | "pad_l", "pad_r", "pad_zl", "pad_zr", | 50 | "pad_select", "pad_home", "pad_dup", "pad_ddown", "pad_dleft", "pad_dright", "pad_cup", |
| 34 | "pad_start", "pad_select", "pad_home", | 51 | "pad_cdown", "pad_cleft", "pad_cright", |
| 35 | "pad_dup", "pad_ddown", "pad_dleft", "pad_dright", | ||
| 36 | "pad_cup", "pad_cdown", "pad_cleft", "pad_cright", | ||
| 37 | 52 | ||
| 38 | // indirectly mapped keys | 53 | // indirectly mapped keys |
| 39 | "pad_circle_up", "pad_circle_down", "pad_circle_left", "pad_circle_right", | 54 | "pad_circle_up", "pad_circle_down", "pad_circle_left", "pad_circle_right", |
| 40 | "pad_circle_modifier", | 55 | "pad_circle_modifier", |
| 41 | }}; | 56 | }}; |
| 42 | static const std::array<Values, NUM_INPUTS> All = {{ | 57 | static const std::array<Values, NUM_INPUTS> All = {{ |
| 43 | A, B, X, Y, | 58 | A, B, X, Y, L, R, ZL, ZR, |
| 44 | L, R, ZL, ZR, | 59 | START, SELECT, HOME, DUP, DDOWN, DLEFT, DRIGHT, CUP, |
| 45 | START, SELECT, HOME, | 60 | CDOWN, CLEFT, CRIGHT, CIRCLE_UP, CIRCLE_DOWN, CIRCLE_LEFT, CIRCLE_RIGHT, CIRCLE_MODIFIER, |
| 46 | DUP, DDOWN, DLEFT, DRIGHT, | ||
| 47 | CUP, CDOWN, CLEFT, CRIGHT, | ||
| 48 | CIRCLE_UP, CIRCLE_DOWN, CIRCLE_LEFT, CIRCLE_RIGHT, | ||
| 49 | CIRCLE_MODIFIER, | ||
| 50 | }}; | 61 | }}; |
| 51 | } | 62 | } |
| 52 | 63 | ||
| 53 | |||
| 54 | struct Values { | 64 | struct Values { |
| 55 | // CheckNew3DS | 65 | // CheckNew3DS |
| 56 | bool is_new_3ds; | 66 | bool is_new_3ds; |
| @@ -91,5 +101,4 @@ struct Values { | |||
| 91 | } extern values; | 101 | } extern values; |
| 92 | 102 | ||
| 93 | void Apply(); | 103 | void Apply(); |
| 94 | |||
| 95 | } | 104 | } |
diff --git a/src/core/system.cpp b/src/core/system.cpp index 4fc266cb0..f2bf648bd 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp | |||
| @@ -6,18 +6,18 @@ | |||
| 6 | 6 | ||
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/core_timing.h" | 8 | #include "core/core_timing.h" |
| 9 | #include "core/system.h" | ||
| 10 | #include "core/gdbstub/gdbstub.h" | 9 | #include "core/gdbstub/gdbstub.h" |
| 11 | #include "core/hw/hw.h" | ||
| 12 | #include "core/hle/hle.h" | 10 | #include "core/hle/hle.h" |
| 13 | #include "core/hle/kernel/kernel.h" | 11 | #include "core/hle/kernel/kernel.h" |
| 14 | #include "core/hle/kernel/memory.h" | 12 | #include "core/hle/kernel/memory.h" |
| 13 | #include "core/hw/hw.h" | ||
| 14 | #include "core/system.h" | ||
| 15 | 15 | ||
| 16 | #include "video_core/video_core.h" | 16 | #include "video_core/video_core.h" |
| 17 | 17 | ||
| 18 | namespace System { | 18 | namespace System { |
| 19 | 19 | ||
| 20 | static bool is_powered_on{ false }; | 20 | static bool is_powered_on{false}; |
| 21 | 21 | ||
| 22 | Result Init(EmuWindow* emu_window) { | 22 | Result Init(EmuWindow* emu_window) { |
| 23 | Core::Init(); | 23 | Core::Init(); |
diff --git a/src/core/system.h b/src/core/system.h index fb0ca4e1b..6d672b1b5 100644 --- a/src/core/system.h +++ b/src/core/system.h | |||
| @@ -9,14 +9,13 @@ class EmuWindow; | |||
| 9 | namespace System { | 9 | namespace System { |
| 10 | 10 | ||
| 11 | enum class Result { | 11 | enum class Result { |
| 12 | Success, ///< Everything is fine | 12 | Success, ///< Everything is fine |
| 13 | Error, ///< Something went wrong (no module specified) | 13 | Error, ///< Something went wrong (no module specified) |
| 14 | ErrorInitCore, ///< Something went wrong during core init | 14 | ErrorInitCore, ///< Something went wrong during core init |
| 15 | ErrorInitVideoCore, ///< Something went wrong during video core init | 15 | ErrorInitVideoCore, ///< Something went wrong during video core init |
| 16 | }; | 16 | }; |
| 17 | 17 | ||
| 18 | Result Init(EmuWindow* emu_window); | 18 | Result Init(EmuWindow* emu_window); |
| 19 | bool IsPoweredOn(); | 19 | bool IsPoweredOn(); |
| 20 | void Shutdown(); | 20 | void Shutdown(); |
| 21 | |||
| 22 | } | 21 | } |
diff --git a/src/core/tracer/citrace.h b/src/core/tracer/citrace.h index 709abdfb3..ac26e872b 100644 --- a/src/core/tracer/citrace.h +++ b/src/core/tracer/citrace.h | |||
| @@ -61,8 +61,8 @@ struct CTHeader { | |||
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | enum CTStreamElementType : u32 { | 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 | ||
| @@ -76,12 +76,7 @@ struct CTMemoryLoad { | |||
| 76 | struct CTRegisterWrite { | 76 | struct CTRegisterWrite { |
| 77 | u32 physical_address; | 77 | u32 physical_address; |
| 78 | 78 | ||
| 79 | enum : u32 { | 79 | enum : u32 { SIZE_8 = 0xD1, SIZE_16 = 0xD2, SIZE_32 = 0xD3, SIZE_64 = 0xD4 } size; |
| 80 | SIZE_8 = 0xD1, | ||
| 81 | SIZE_16 = 0xD2, | ||
| 82 | SIZE_32 = 0xD3, | ||
| 83 | SIZE_64 = 0xD4 | ||
| 84 | } size; | ||
| 85 | 80 | ||
| 86 | // TODO: Make it clearer which bits of this member are used for sizes other than 32 bits | 81 | // TODO: Make it clearer which bits of this member are used for sizes other than 32 bits |
| 87 | u64 value; | 82 | u64 value; |
| @@ -97,5 +92,4 @@ struct CTStreamElement { | |||
| 97 | }; | 92 | }; |
| 98 | 93 | ||
| 99 | #pragma pack() | 94 | #pragma pack() |
| 100 | |||
| 101 | } | 95 | } |
diff --git a/src/core/tracer/recorder.cpp b/src/core/tracer/recorder.cpp index 7abaacf70..8fd0018c4 100644 --- a/src/core/tracer/recorder.cpp +++ b/src/core/tracer/recorder.cpp | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | namespace CiTrace { | 13 | namespace CiTrace { |
| 14 | 14 | ||
| 15 | Recorder::Recorder(const InitialState& initial_state) : initial_state(initial_state) { | 15 | Recorder::Recorder(const InitialState& initial_state) : initial_state(initial_state) { |
| 16 | |||
| 17 | } | 16 | } |
| 18 | 17 | ||
| 19 | void Recorder::Finish(const std::string& filename) { | 18 | void Recorder::Finish(const std::string& filename) { |
| @@ -26,35 +25,41 @@ void Recorder::Finish(const std::string& filename) { | |||
| 26 | // Calculate file offsets | 25 | // Calculate file offsets |
| 27 | auto& initial = header.initial_state_offsets; | 26 | auto& initial = header.initial_state_offsets; |
| 28 | 27 | ||
| 29 | initial.gpu_registers_size = static_cast<u32>(initial_state.gpu_registers.size()); | 28 | initial.gpu_registers_size = static_cast<u32>(initial_state.gpu_registers.size()); |
| 30 | initial.lcd_registers_size = static_cast<u32>(initial_state.lcd_registers.size()); | 29 | initial.lcd_registers_size = static_cast<u32>(initial_state.lcd_registers.size()); |
| 31 | initial.pica_registers_size = static_cast<u32>(initial_state.pica_registers.size()); | 30 | initial.pica_registers_size = static_cast<u32>(initial_state.pica_registers.size()); |
| 32 | initial.default_attributes_size = static_cast<u32>(initial_state.default_attributes.size()); | 31 | initial.default_attributes_size = static_cast<u32>(initial_state.default_attributes.size()); |
| 33 | initial.vs_program_binary_size = static_cast<u32>(initial_state.vs_program_binary.size()); | 32 | initial.vs_program_binary_size = static_cast<u32>(initial_state.vs_program_binary.size()); |
| 34 | initial.vs_swizzle_data_size = static_cast<u32>(initial_state.vs_swizzle_data.size()); | 33 | initial.vs_swizzle_data_size = static_cast<u32>(initial_state.vs_swizzle_data.size()); |
| 35 | initial.vs_float_uniforms_size = static_cast<u32>(initial_state.vs_float_uniforms.size()); | 34 | initial.vs_float_uniforms_size = static_cast<u32>(initial_state.vs_float_uniforms.size()); |
| 36 | initial.gs_program_binary_size = static_cast<u32>(initial_state.gs_program_binary.size()); | 35 | initial.gs_program_binary_size = static_cast<u32>(initial_state.gs_program_binary.size()); |
| 37 | initial.gs_swizzle_data_size = static_cast<u32>(initial_state.gs_swizzle_data.size()); | 36 | initial.gs_swizzle_data_size = static_cast<u32>(initial_state.gs_swizzle_data.size()); |
| 38 | initial.gs_float_uniforms_size = static_cast<u32>(initial_state.gs_float_uniforms.size()); | 37 | initial.gs_float_uniforms_size = static_cast<u32>(initial_state.gs_float_uniforms.size()); |
| 39 | header.stream_size = static_cast<u32>(stream.size()); | 38 | header.stream_size = static_cast<u32>(stream.size()); |
| 40 | 39 | ||
| 41 | initial.gpu_registers = sizeof(header); | 40 | initial.gpu_registers = sizeof(header); |
| 42 | initial.lcd_registers = initial.gpu_registers + initial.gpu_registers_size * sizeof(u32); | 41 | initial.lcd_registers = initial.gpu_registers + initial.gpu_registers_size * sizeof(u32); |
| 43 | initial.pica_registers = initial.lcd_registers + initial.lcd_registers_size * sizeof(u32);; | 42 | initial.pica_registers = initial.lcd_registers + initial.lcd_registers_size * sizeof(u32); |
| 44 | initial.default_attributes = initial.pica_registers + initial.pica_registers_size * sizeof(u32); | 43 | ; |
| 45 | initial.vs_program_binary = initial.default_attributes + initial.default_attributes_size * sizeof(u32); | 44 | initial.default_attributes = initial.pica_registers + initial.pica_registers_size * sizeof(u32); |
| 46 | initial.vs_swizzle_data = initial.vs_program_binary + initial.vs_program_binary_size * sizeof(u32); | 45 | initial.vs_program_binary = |
| 47 | initial.vs_float_uniforms = initial.vs_swizzle_data + initial.vs_swizzle_data_size * sizeof(u32); | 46 | initial.default_attributes + initial.default_attributes_size * sizeof(u32); |
| 48 | initial.gs_program_binary = initial.vs_float_uniforms + initial.vs_float_uniforms_size * sizeof(u32); | 47 | initial.vs_swizzle_data = |
| 49 | initial.gs_swizzle_data = initial.gs_program_binary + initial.gs_program_binary_size * sizeof(u32); | 48 | initial.vs_program_binary + initial.vs_program_binary_size * sizeof(u32); |
| 50 | initial.gs_float_uniforms = initial.gs_swizzle_data + initial.gs_swizzle_data_size * sizeof(u32); | 49 | initial.vs_float_uniforms = |
| 51 | header.stream_offset = initial.gs_float_uniforms + initial.gs_float_uniforms_size * sizeof(u32); | 50 | initial.vs_swizzle_data + initial.vs_swizzle_data_size * sizeof(u32); |
| 51 | initial.gs_program_binary = | ||
| 52 | initial.vs_float_uniforms + initial.vs_float_uniforms_size * sizeof(u32); | ||
| 53 | initial.gs_swizzle_data = | ||
| 54 | initial.gs_program_binary + initial.gs_program_binary_size * sizeof(u32); | ||
| 55 | initial.gs_float_uniforms = | ||
| 56 | initial.gs_swizzle_data + initial.gs_swizzle_data_size * sizeof(u32); | ||
| 57 | header.stream_offset = initial.gs_float_uniforms + initial.gs_float_uniforms_size * sizeof(u32); | ||
| 52 | 58 | ||
| 53 | // Iterate through stream elements, update relevant stream element data | 59 | // Iterate through stream elements, update relevant stream element data |
| 54 | for (auto& stream_element : stream) { | 60 | for (auto& stream_element : stream) { |
| 55 | switch (stream_element.data.type) { | 61 | switch (stream_element.data.type) { |
| 56 | case MemoryLoad: | 62 | case MemoryLoad: { |
| 57 | { | ||
| 58 | auto& file_offset = memory_regions[stream_element.hash]; | 63 | auto& file_offset = memory_regions[stream_element.hash]; |
| 59 | if (!stream_element.uses_existing_data) { | 64 | if (!stream_element.uses_existing_data) { |
| 60 | file_offset = header.stream_offset; | 65 | file_offset = header.stream_offset; |
| @@ -79,44 +84,62 @@ void Recorder::Finish(const std::string& filename) { | |||
| 79 | throw "Failed to write header"; | 84 | throw "Failed to write header"; |
| 80 | 85 | ||
| 81 | // Write initial state | 86 | // Write initial state |
| 82 | written = file.WriteArray(initial_state.gpu_registers.data(), initial_state.gpu_registers.size()); | 87 | written = |
| 88 | file.WriteArray(initial_state.gpu_registers.data(), initial_state.gpu_registers.size()); | ||
| 83 | if (written != initial_state.gpu_registers.size() || file.Tell() != initial.lcd_registers) | 89 | if (written != initial_state.gpu_registers.size() || file.Tell() != initial.lcd_registers) |
| 84 | throw "Failed to write GPU registers"; | 90 | throw "Failed to write GPU registers"; |
| 85 | 91 | ||
| 86 | written = file.WriteArray(initial_state.lcd_registers.data(), initial_state.lcd_registers.size()); | 92 | written = |
| 93 | file.WriteArray(initial_state.lcd_registers.data(), initial_state.lcd_registers.size()); | ||
| 87 | if (written != initial_state.lcd_registers.size() || file.Tell() != initial.pica_registers) | 94 | if (written != initial_state.lcd_registers.size() || file.Tell() != initial.pica_registers) |
| 88 | throw "Failed to write LCD registers"; | 95 | throw "Failed to write LCD registers"; |
| 89 | 96 | ||
| 90 | written = file.WriteArray(initial_state.pica_registers.data(), initial_state.pica_registers.size()); | 97 | written = file.WriteArray(initial_state.pica_registers.data(), |
| 91 | if (written != initial_state.pica_registers.size() || file.Tell() != initial.default_attributes) | 98 | initial_state.pica_registers.size()); |
| 99 | if (written != initial_state.pica_registers.size() || | ||
| 100 | file.Tell() != initial.default_attributes) | ||
| 92 | throw "Failed to write Pica registers"; | 101 | throw "Failed to write Pica registers"; |
| 93 | 102 | ||
| 94 | written = file.WriteArray(initial_state.default_attributes.data(), initial_state.default_attributes.size()); | 103 | written = file.WriteArray(initial_state.default_attributes.data(), |
| 95 | if (written != initial_state.default_attributes.size() || file.Tell() != initial.vs_program_binary) | 104 | initial_state.default_attributes.size()); |
| 105 | if (written != initial_state.default_attributes.size() || | ||
| 106 | file.Tell() != initial.vs_program_binary) | ||
| 96 | throw "Failed to write default vertex attributes"; | 107 | throw "Failed to write default vertex attributes"; |
| 97 | 108 | ||
| 98 | written = file.WriteArray(initial_state.vs_program_binary.data(), initial_state.vs_program_binary.size()); | 109 | written = file.WriteArray(initial_state.vs_program_binary.data(), |
| 99 | if (written != initial_state.vs_program_binary.size() || file.Tell() != initial.vs_swizzle_data) | 110 | initial_state.vs_program_binary.size()); |
| 111 | if (written != initial_state.vs_program_binary.size() || | ||
| 112 | file.Tell() != initial.vs_swizzle_data) | ||
| 100 | throw "Failed to write vertex shader program binary"; | 113 | throw "Failed to write vertex shader program binary"; |
| 101 | 114 | ||
| 102 | written = file.WriteArray(initial_state.vs_swizzle_data.data(), initial_state.vs_swizzle_data.size()); | 115 | written = file.WriteArray(initial_state.vs_swizzle_data.data(), |
| 103 | if (written != initial_state.vs_swizzle_data.size() || file.Tell() != initial.vs_float_uniforms) | 116 | initial_state.vs_swizzle_data.size()); |
| 117 | if (written != initial_state.vs_swizzle_data.size() || | ||
| 118 | file.Tell() != initial.vs_float_uniforms) | ||
| 104 | throw "Failed to write vertex shader swizzle data"; | 119 | throw "Failed to write vertex shader swizzle data"; |
| 105 | 120 | ||
| 106 | written = file.WriteArray(initial_state.vs_float_uniforms.data(), initial_state.vs_float_uniforms.size()); | 121 | written = file.WriteArray(initial_state.vs_float_uniforms.data(), |
| 107 | if (written != initial_state.vs_float_uniforms.size() || file.Tell() != initial.gs_program_binary) | 122 | initial_state.vs_float_uniforms.size()); |
| 123 | if (written != initial_state.vs_float_uniforms.size() || | ||
| 124 | file.Tell() != initial.gs_program_binary) | ||
| 108 | throw "Failed to write vertex shader float uniforms"; | 125 | throw "Failed to write vertex shader float uniforms"; |
| 109 | 126 | ||
| 110 | written = file.WriteArray(initial_state.gs_program_binary.data(), initial_state.gs_program_binary.size()); | 127 | written = file.WriteArray(initial_state.gs_program_binary.data(), |
| 111 | if (written != initial_state.gs_program_binary.size() || file.Tell() != initial.gs_swizzle_data) | 128 | initial_state.gs_program_binary.size()); |
| 129 | if (written != initial_state.gs_program_binary.size() || | ||
| 130 | file.Tell() != initial.gs_swizzle_data) | ||
| 112 | throw "Failed to write geomtry shader program binary"; | 131 | throw "Failed to write geomtry shader program binary"; |
| 113 | 132 | ||
| 114 | written = file.WriteArray(initial_state.gs_swizzle_data.data(), initial_state.gs_swizzle_data.size()); | 133 | written = file.WriteArray(initial_state.gs_swizzle_data.data(), |
| 115 | if (written != initial_state.gs_swizzle_data.size() || file.Tell() != initial.gs_float_uniforms) | 134 | initial_state.gs_swizzle_data.size()); |
| 135 | if (written != initial_state.gs_swizzle_data.size() || | ||
| 136 | file.Tell() != initial.gs_float_uniforms) | ||
| 116 | throw "Failed to write geometry shader swizzle data"; | 137 | throw "Failed to write geometry shader swizzle data"; |
| 117 | 138 | ||
| 118 | written = file.WriteArray(initial_state.gs_float_uniforms.data(), initial_state.gs_float_uniforms.size()); | 139 | written = file.WriteArray(initial_state.gs_float_uniforms.data(), |
| 119 | if (written != initial_state.gs_float_uniforms.size() || file.Tell() != initial.gs_float_uniforms + sizeof(u32) * initial.gs_float_uniforms_size) | 140 | initial_state.gs_float_uniforms.size()); |
| 141 | if (written != initial_state.gs_float_uniforms.size() || | ||
| 142 | file.Tell() != initial.gs_float_uniforms + sizeof(u32) * initial.gs_float_uniforms_size) | ||
| 120 | throw "Failed to write geometry shader float uniforms"; | 143 | throw "Failed to write geometry shader float uniforms"; |
| 121 | 144 | ||
| 122 | // Iterate through stream elements, write "extra data" | 145 | // Iterate through stream elements, write "extra data" |
| @@ -124,7 +147,8 @@ void Recorder::Finish(const std::string& filename) { | |||
| 124 | if (stream_element.extra_data.size() == 0) | 147 | if (stream_element.extra_data.size() == 0) |
| 125 | continue; | 148 | continue; |
| 126 | 149 | ||
| 127 | written = file.WriteBytes(stream_element.extra_data.data(), stream_element.extra_data.size()); | 150 | written = |
| 151 | file.WriteBytes(stream_element.extra_data.data(), stream_element.extra_data.size()); | ||
| 128 | if (written != stream_element.extra_data.size()) | 152 | if (written != stream_element.extra_data.size()) |
| 129 | throw "Failed to write extra data"; | 153 | throw "Failed to write extra data"; |
| 130 | } | 154 | } |
| @@ -137,17 +161,17 @@ void Recorder::Finish(const std::string& filename) { | |||
| 137 | if (1 != file.WriteObject(stream_element.data)) | 161 | if (1 != file.WriteObject(stream_element.data)) |
| 138 | throw "Failed to write stream element"; | 162 | throw "Failed to write stream element"; |
| 139 | } | 163 | } |
| 140 | } catch(const char* str) { | 164 | } catch (const char* str) { |
| 141 | LOG_ERROR(HW_GPU, "Writing CiTrace file failed: %s", str); | 165 | LOG_ERROR(HW_GPU, "Writing CiTrace file failed: %s", str); |
| 142 | } | 166 | } |
| 143 | } | 167 | } |
| 144 | 168 | ||
| 145 | void Recorder::FrameFinished() { | 169 | void Recorder::FrameFinished() { |
| 146 | stream.push_back( { { FrameMarker } } ); | 170 | stream.push_back({{FrameMarker}}); |
| 147 | } | 171 | } |
| 148 | 172 | ||
| 149 | void Recorder::MemoryAccessed(const u8* data, u32 size, u32 physical_address) { | 173 | void Recorder::MemoryAccessed(const u8* data, u32 size, u32 physical_address) { |
| 150 | StreamElement element = { { MemoryLoad } }; | 174 | StreamElement element = {{MemoryLoad}}; |
| 151 | element.data.memory_load.size = size; | 175 | element.data.memory_load.size = size; |
| 152 | element.data.memory_load.physical_address = physical_address; | 176 | element.data.memory_load.physical_address = physical_address; |
| 153 | 177 | ||
| @@ -166,22 +190,22 @@ void Recorder::MemoryAccessed(const u8* data, u32 size, u32 physical_address) { | |||
| 166 | stream.push_back(element); | 190 | stream.push_back(element); |
| 167 | } | 191 | } |
| 168 | 192 | ||
| 169 | template<typename T> | 193 | template <typename T> |
| 170 | void Recorder::RegisterWritten(u32 physical_address, T value) { | 194 | void Recorder::RegisterWritten(u32 physical_address, T value) { |
| 171 | StreamElement element = { { RegisterWrite } }; | 195 | StreamElement element = {{RegisterWrite}}; |
| 172 | element.data.register_write.size = (sizeof(T) == 1) ? CTRegisterWrite::SIZE_8 | 196 | element.data.register_write.size = |
| 173 | : (sizeof(T) == 2) ? CTRegisterWrite::SIZE_16 | 197 | (sizeof(T) == 1) ? CTRegisterWrite::SIZE_8 |
| 174 | : (sizeof(T) == 4) ? CTRegisterWrite::SIZE_32 | 198 | : (sizeof(T) == 2) ? CTRegisterWrite::SIZE_16 |
| 175 | : CTRegisterWrite::SIZE_64; | 199 | : (sizeof(T) == 4) ? CTRegisterWrite::SIZE_32 |
| 200 | : CTRegisterWrite::SIZE_64; | ||
| 176 | element.data.register_write.physical_address = physical_address; | 201 | element.data.register_write.physical_address = physical_address; |
| 177 | element.data.register_write.value = value; | 202 | element.data.register_write.value = value; |
| 178 | 203 | ||
| 179 | stream.push_back(element); | 204 | stream.push_back(element); |
| 180 | } | 205 | } |
| 181 | 206 | ||
| 182 | template void Recorder::RegisterWritten(u32,u8); | 207 | template void Recorder::RegisterWritten(u32, u8); |
| 183 | template void Recorder::RegisterWritten(u32,u16); | 208 | template void Recorder::RegisterWritten(u32, u16); |
| 184 | template void Recorder::RegisterWritten(u32,u32); | 209 | template void Recorder::RegisterWritten(u32, u32); |
| 185 | template void Recorder::RegisterWritten(u32,u64); | 210 | template void Recorder::RegisterWritten(u32, u64); |
| 186 | |||
| 187 | } | 211 | } |
diff --git a/src/core/tracer/recorder.h b/src/core/tracer/recorder.h index febf883c8..6f5354f84 100644 --- a/src/core/tracer/recorder.h +++ b/src/core/tracer/recorder.h | |||
| @@ -54,7 +54,7 @@ public: | |||
| 54 | * Record a register write. | 54 | * Record a register write. |
| 55 | * @note Use this whenever a GPU-related MMIO register has been written to. | 55 | * @note Use this whenever a GPU-related MMIO register has been written to. |
| 56 | */ | 56 | */ |
| 57 | template<typename T> | 57 | template <typename T> |
| 58 | void RegisterWritten(u32 physical_address, T value); | 58 | void RegisterWritten(u32 physical_address, T value); |
| 59 | 59 | ||
| 60 | private: | 60 | private: |