diff options
| author | 2015-01-01 20:43:04 -0500 | |
|---|---|---|
| committer | 2015-01-01 20:43:04 -0500 | |
| commit | fa4cc502e7f30d496d757ef7c52ecee89266a89f (patch) | |
| tree | 7d20f847a8a71ec98abc3b6b03bf8a3dad3981a3 /src | |
| parent | Merge pull request #378 from lioncash/s8 (diff) | |
| parent | dyncom: Implement SHADD8/SHADD16/SHSUB8/SHSUB16/SHASX/SHSAX (diff) | |
| download | yuzu-fa4cc502e7f30d496d757ef7c52ecee89266a89f.tar.gz yuzu-fa4cc502e7f30d496d757ef7c52ecee89266a89f.tar.xz yuzu-fa4cc502e7f30d496d757ef7c52ecee89266a89f.zip | |
Merge pull request #379 from lioncash/sh
dyncom: Implement SHADD8/SHADD16/SHSUB8/SHSUB16/SHASX/SHSAX
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 118 |
1 files changed, 110 insertions, 8 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 5908a4ccf..f2ea0e9dd 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp | |||
| @@ -2252,13 +2252,48 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index) | |||
| 2252 | 2252 | ||
| 2253 | return inst_base; | 2253 | return inst_base; |
| 2254 | } | 2254 | } |
| 2255 | |||
| 2255 | ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SETEND"); } | 2256 | ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SETEND"); } |
| 2256 | ARM_INST_PTR INTERPRETER_TRANSLATE(shadd16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SHADD16"); } | 2257 | |
| 2257 | ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SHADD8"); } | 2258 | ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index) |
| 2258 | ARM_INST_PTR INTERPRETER_TRANSLATE(shaddsubx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SHADDSUBX"); } | 2259 | { |
| 2259 | ARM_INST_PTR INTERPRETER_TRANSLATE(shsub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SHSUB16"); } | 2260 | arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); |
| 2260 | ARM_INST_PTR INTERPRETER_TRANSLATE(shsub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SHSUB8"); } | 2261 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; |
| 2261 | ARM_INST_PTR INTERPRETER_TRANSLATE(shsubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SHSUBADDX"); } | 2262 | |
| 2263 | inst_base->cond = BITS(inst, 28, 31); | ||
| 2264 | inst_base->idx = index; | ||
| 2265 | inst_base->br = NON_BRANCH; | ||
| 2266 | inst_base->load_r15 = 0; | ||
| 2267 | |||
| 2268 | inst_cream->op1 = BITS(inst, 20, 21); | ||
| 2269 | inst_cream->op2 = BITS(inst, 5, 7); | ||
| 2270 | inst_cream->Rm = BITS(inst, 0, 3); | ||
| 2271 | inst_cream->Rn = BITS(inst, 16, 19); | ||
| 2272 | inst_cream->Rd = BITS(inst, 12, 15); | ||
| 2273 | |||
| 2274 | return inst_base; | ||
| 2275 | } | ||
| 2276 | ARM_INST_PTR INTERPRETER_TRANSLATE(shadd16)(unsigned int inst, int index) | ||
| 2277 | { | ||
| 2278 | return INTERPRETER_TRANSLATE(shadd8)(inst, index); | ||
| 2279 | } | ||
| 2280 | ARM_INST_PTR INTERPRETER_TRANSLATE(shaddsubx)(unsigned int inst, int index) | ||
| 2281 | { | ||
| 2282 | return INTERPRETER_TRANSLATE(shadd8)(inst, index); | ||
| 2283 | } | ||
| 2284 | ARM_INST_PTR INTERPRETER_TRANSLATE(shsub8)(unsigned int inst, int index) | ||
| 2285 | { | ||
| 2286 | return INTERPRETER_TRANSLATE(shadd8)(inst, index); | ||
| 2287 | } | ||
| 2288 | ARM_INST_PTR INTERPRETER_TRANSLATE(shsub16)(unsigned int inst, int index) | ||
| 2289 | { | ||
| 2290 | return INTERPRETER_TRANSLATE(shadd8)(inst, index); | ||
| 2291 | } | ||
| 2292 | ARM_INST_PTR INTERPRETER_TRANSLATE(shsubaddx)(unsigned int inst, int index) | ||
| 2293 | { | ||
| 2294 | return INTERPRETER_TRANSLATE(shadd8)(inst, index); | ||
| 2295 | } | ||
| 2296 | |||
| 2262 | ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index) | 2297 | ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index) |
| 2263 | { | 2298 | { |
| 2264 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smla_inst)); | 2299 | arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smla_inst)); |
| @@ -5229,12 +5264,79 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | |||
| 5229 | } | 5264 | } |
| 5230 | 5265 | ||
| 5231 | SETEND_INST: | 5266 | SETEND_INST: |
| 5232 | SHADD16_INST: | 5267 | |
| 5233 | SHADD8_INST: | 5268 | SHADD8_INST: |
| 5269 | SHADD16_INST: | ||
| 5234 | SHADDSUBX_INST: | 5270 | SHADDSUBX_INST: |
| 5235 | SHSUB16_INST: | ||
| 5236 | SHSUB8_INST: | 5271 | SHSUB8_INST: |
| 5272 | SHSUB16_INST: | ||
| 5237 | SHSUBADDX_INST: | 5273 | SHSUBADDX_INST: |
| 5274 | { | ||
| 5275 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { | ||
| 5276 | generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; | ||
| 5277 | |||
| 5278 | const u8 op2 = inst_cream->op2; | ||
| 5279 | const u32 rm_val = RM; | ||
| 5280 | const u32 rn_val = RN; | ||
| 5281 | |||
| 5282 | if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) { | ||
| 5283 | s32 lo_result = 0; | ||
| 5284 | s32 hi_result = 0; | ||
| 5285 | |||
| 5286 | // SHADD16 | ||
| 5287 | if (op2 == 0x00) { | ||
| 5288 | lo_result = ((s16)(rn_val & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1; | ||
| 5289 | hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1; | ||
| 5290 | } | ||
| 5291 | // SHASX | ||
| 5292 | else if (op2 == 0x01) { | ||
| 5293 | lo_result = ((s16)(rn_val & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1; | ||
| 5294 | hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1; | ||
| 5295 | } | ||
| 5296 | // SHSAX | ||
| 5297 | else if (op2 == 0x02) { | ||
| 5298 | lo_result = ((s16)(rn_val & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1; | ||
| 5299 | hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1; | ||
| 5300 | } | ||
| 5301 | // SHSUB16 | ||
| 5302 | else if (op2 == 0x03) { | ||
| 5303 | lo_result = ((s16)(rn_val & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1; | ||
| 5304 | hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1; | ||
| 5305 | } | ||
| 5306 | |||
| 5307 | RD = ((lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16)); | ||
| 5308 | } | ||
| 5309 | else if (op2 == 0x04 || op2 == 0x07) { | ||
| 5310 | s16 lo_val1, lo_val2; | ||
| 5311 | s16 hi_val1, hi_val2; | ||
| 5312 | |||
| 5313 | // SHADD8 | ||
| 5314 | if (op2 == 0x04) { | ||
| 5315 | lo_val1 = ((s8)(rn_val & 0xFF) + (s8)(rm_val & 0xFF)) >> 1; | ||
| 5316 | lo_val2 = ((s8)((rn_val >> 8) & 0xFF) + (s8)((rm_val >> 8) & 0xFF)) >> 1; | ||
| 5317 | |||
| 5318 | hi_val1 = ((s8)((rn_val >> 16) & 0xFF) + (s8)((rm_val >> 16) & 0xFF)) >> 1; | ||
| 5319 | hi_val2 = ((s8)((rn_val >> 24) & 0xFF) + (s8)((rm_val >> 24) & 0xFF)) >> 1; | ||
| 5320 | } | ||
| 5321 | // SHSUB8 | ||
| 5322 | else { | ||
| 5323 | lo_val1 = ((s8)(rn_val & 0xFF) - (s8)(rm_val & 0xFF)) >> 1; | ||
| 5324 | lo_val2 = ((s8)((rn_val >> 8) & 0xFF) - (s8)((rm_val >> 8) & 0xFF)) >> 1; | ||
| 5325 | |||
| 5326 | hi_val1 = ((s8)((rn_val >> 16) & 0xFF) - (s8)((rm_val >> 16) & 0xFF)) >> 1; | ||
| 5327 | hi_val2 = ((s8)((rn_val >> 24) & 0xFF) - (s8)((rm_val >> 24) & 0xFF)) >> 1; | ||
| 5328 | } | ||
| 5329 | |||
| 5330 | RD = (lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) | ((hi_val2 & 0xFF) << 24); | ||
| 5331 | } | ||
| 5332 | } | ||
| 5333 | |||
| 5334 | cpu->Reg[15] += GET_INST_SIZE(cpu); | ||
| 5335 | INC_PC(sizeof(generic_arm_inst)); | ||
| 5336 | FETCH_INST; | ||
| 5337 | GOTO_NEXT_INST; | ||
| 5338 | } | ||
| 5339 | |||
| 5238 | SMLA_INST: | 5340 | SMLA_INST: |
| 5239 | { | 5341 | { |
| 5240 | if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { | 5342 | if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { |