diff options
| author | 2014-12-28 22:20:49 -0500 | |
|---|---|---|
| committer | 2014-12-28 22:20:49 -0500 | |
| commit | df728cb4c219ab8932983a7294ace50ccdba92d5 (patch) | |
| tree | d31896af130f4e8fb38328ccf7d63a41031d835c | |
| parent | Merge pull request #352 from xdec/PR_XDEC_172 (diff) | |
| parent | armemu: Simplify SSAT/SSAT16/SXTB/SXTAB (diff) | |
| download | yuzu-df728cb4c219ab8932983a7294ace50ccdba92d5.tar.gz yuzu-df728cb4c219ab8932983a7294ace50ccdba92d5.tar.xz yuzu-df728cb4c219ab8932983a7294ace50ccdba92d5.zip | |
Merge pull request #355 from lioncash/simp
armemu: Simplify some instructions.
| -rw-r--r-- | src/core/arm/interpreter/armemu.cpp | 367 |
1 files changed, 142 insertions, 225 deletions
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp index 9c6602f09..f0d349de7 100644 --- a/src/core/arm/interpreter/armemu.cpp +++ b/src/core/arm/interpreter/armemu.cpp | |||
| @@ -6264,129 +6264,94 @@ L_stm_s_takeabort: | |||
| 6264 | return 1; | 6264 | return 1; |
| 6265 | } | 6265 | } |
| 6266 | } | 6266 | } |
| 6267 | printf("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); | 6267 | printf("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); |
| 6268 | break; | 6268 | break; |
| 6269 | case 0x6a: { | ||
| 6270 | ARMword Rm; | ||
| 6271 | int ror = -1; | ||
| 6272 | |||
| 6273 | switch (BITS(4, 11)) { | ||
| 6274 | case 0x07: | ||
| 6275 | ror = 0; | ||
| 6276 | break; | ||
| 6277 | case 0x47: | ||
| 6278 | ror = 8; | ||
| 6279 | break; | ||
| 6280 | case 0x87: | ||
| 6281 | ror = 16; | ||
| 6282 | break; | ||
| 6283 | case 0xc7: | ||
| 6284 | ror = 24; | ||
| 6285 | break; | ||
| 6286 | |||
| 6287 | case 0x01: | ||
| 6288 | case 0xf3: | ||
| 6289 | //ichfly | ||
| 6290 | //SSAT16 | ||
| 6291 | { | ||
| 6292 | const u8 rd_idx = BITS(12, 15); | ||
| 6293 | const u8 rn_idx = BITS(0, 3); | ||
| 6294 | const u8 num_bits = BITS(16, 19) + 1; | ||
| 6295 | const s16 min = -(0x8000 >> (16 - num_bits)); | ||
| 6296 | const s16 max = (0x7FFF >> (16 - num_bits)); | ||
| 6297 | s16 rn_lo = (state->Reg[rn_idx]); | ||
| 6298 | s16 rn_hi = (state->Reg[rn_idx] >> 16); | ||
| 6299 | |||
| 6300 | if (rn_lo > max) { | ||
| 6301 | rn_lo = max; | ||
| 6302 | SETQ; | ||
| 6303 | } else if (rn_lo < min) { | ||
| 6304 | rn_lo = min; | ||
| 6305 | SETQ; | ||
| 6306 | } | ||
| 6307 | |||
| 6308 | if (rn_hi > max) { | ||
| 6309 | rn_hi = max; | ||
| 6310 | SETQ; | ||
| 6311 | } else if (rn_hi < min) { | ||
| 6312 | rn_hi = min; | ||
| 6313 | SETQ; | ||
| 6314 | } | ||
| 6315 | |||
| 6316 | state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi & 0xFFFF) << 16); | ||
| 6317 | return 1; | ||
| 6318 | } | ||
| 6319 | 6269 | ||
| 6320 | default: | 6270 | case 0x6a: // SSAT, SSAT16, SXTB, and SXTAB |
| 6321 | break; | 6271 | { |
| 6322 | } | 6272 | const u8 op2 = BITS(5, 7); |
| 6323 | 6273 | ||
| 6324 | if (ror == -1) { | 6274 | // SSAT16 |
| 6325 | if (BITS(4, 6) == 0x7) { | 6275 | if (op2 == 0x01) { |
| 6326 | printf("Unhandled v6 insn: ssat\n"); | 6276 | const u8 rd_idx = BITS(12, 15); |
| 6327 | return 0; | 6277 | const u8 rn_idx = BITS(0, 3); |
| 6278 | const u8 num_bits = BITS(16, 19) + 1; | ||
| 6279 | const s16 min = -(0x8000 >> (16 - num_bits)); | ||
| 6280 | const s16 max = (0x7FFF >> (16 - num_bits)); | ||
| 6281 | s16 rn_lo = (state->Reg[rn_idx]); | ||
| 6282 | s16 rn_hi = (state->Reg[rn_idx] >> 16); | ||
| 6283 | |||
| 6284 | if (rn_lo > max) { | ||
| 6285 | rn_lo = max; | ||
| 6286 | SETQ; | ||
| 6287 | } else if (rn_lo < min) { | ||
| 6288 | rn_lo = min; | ||
| 6289 | SETQ; | ||
| 6328 | } | 6290 | } |
| 6329 | break; | ||
| 6330 | } | ||
| 6331 | 6291 | ||
| 6332 | Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - ror)) & 0xFF) & 0xFF); | 6292 | if (rn_hi > max) { |
| 6333 | if (Rm & 0x80) | 6293 | rn_hi = max; |
| 6334 | Rm |= 0xffffff00; | 6294 | SETQ; |
| 6295 | } else if (rn_hi < min) { | ||
| 6296 | rn_hi = min; | ||
| 6297 | SETQ; | ||
| 6298 | } | ||
| 6335 | 6299 | ||
| 6336 | if (BITS(16, 19) == 0xf) | 6300 | state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi & 0xFFFF) << 16); |
| 6337 | /* SXTB */ | 6301 | return 1; |
| 6338 | state->Reg[BITS(12, 15)] = Rm; | 6302 | } |
| 6339 | else | 6303 | else if (op2 == 0x03) { |
| 6340 | /* SXTAB */ | 6304 | const u8 rotation = BITS(10, 11) * 8; |
| 6341 | state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + Rm; | 6305 | u32 rm = ((state->Reg[BITS(0, 3)] >> rotation) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - rotation)) & 0xFF) & 0xFF); |
| 6306 | if (rm & 0x80) | ||
| 6307 | rm |= 0xffffff00; | ||
| 6308 | |||
| 6309 | // SXTB, otherwise SXTAB | ||
| 6310 | if (BITS(16, 19) == 0xf) | ||
| 6311 | state->Reg[BITS(12, 15)] = rm; | ||
| 6312 | else | ||
| 6313 | state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm; | ||
| 6342 | 6314 | ||
| 6343 | return 1; | 6315 | return 1; |
| 6316 | } | ||
| 6317 | else { | ||
| 6318 | printf("Unimplemented op: SSAT"); | ||
| 6319 | } | ||
| 6344 | } | 6320 | } |
| 6345 | case 0x6b: | 6321 | break; |
| 6322 | |||
| 6323 | case 0x6b: // REV, REV16, SXTH, and SXTAH | ||
| 6346 | { | 6324 | { |
| 6347 | ARMword Rm; | 6325 | const u8 op2 = BITS(5, 7); |
| 6348 | int ror = -1; | ||
| 6349 | |||
| 6350 | switch (BITS(4, 11)) { | ||
| 6351 | case 0x07: | ||
| 6352 | ror = 0; | ||
| 6353 | break; | ||
| 6354 | case 0x47: | ||
| 6355 | ror = 8; | ||
| 6356 | break; | ||
| 6357 | case 0x87: | ||
| 6358 | ror = 16; | ||
| 6359 | break; | ||
| 6360 | case 0xc7: | ||
| 6361 | ror = 24; | ||
| 6362 | break; | ||
| 6363 | |||
| 6364 | case 0xf3: // REV | ||
| 6365 | DEST = ((RHS & 0xFF) << 24) | ((RHS & 0xFF00)) << 8 | ((RHS & 0xFF0000) >> 8) | ((RHS & 0xFF000000) >> 24); | ||
| 6366 | return 1; | ||
| 6367 | case 0xfb: // REV16 | ||
| 6368 | DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00)) >> 8 | ((RHS & 0xFF0000) << 8) | ((RHS & 0xFF000000) >> 8); | ||
| 6369 | return 1; | ||
| 6370 | default: | ||
| 6371 | break; | ||
| 6372 | } | ||
| 6373 | 6326 | ||
| 6374 | if (ror == -1) | 6327 | // REV |
| 6375 | break; | 6328 | if (op2 == 0x01) { |
| 6329 | DEST = ((RHS & 0xFF) << 24) | ((RHS & 0xFF00)) << 8 | ((RHS & 0xFF0000) >> 8) | ((RHS & 0xFF000000) >> 24); | ||
| 6330 | return 1; | ||
| 6331 | } | ||
| 6332 | // REV16 | ||
| 6333 | else if (op2 == 0x05) { | ||
| 6334 | DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00)) >> 8 | ((RHS & 0xFF0000) << 8) | ((RHS & 0xFF000000) >> 8); | ||
| 6335 | return 1; | ||
| 6336 | } | ||
| 6337 | else if (op2 == 0x03) { | ||
| 6338 | const u8 rotate = BITS(10, 11) * 8; | ||
| 6376 | 6339 | ||
| 6377 | Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - ror)) & 0xFFFF) & 0xFFFF); | 6340 | u32 rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFFFF) & 0xFFFF); |
| 6378 | if (Rm & 0x8000) | 6341 | if (rm & 0x8000) |
| 6379 | Rm |= 0xffff0000; | 6342 | rm |= 0xffff0000; |
| 6380 | 6343 | ||
| 6381 | if (BITS(16, 19) == 0xf) | 6344 | // SXTH, otherwise SXTAH |
| 6382 | /* SXTH */ | 6345 | if (BITS(16, 19) == 15) |
| 6383 | state->Reg[BITS(12, 15)] = Rm; | 6346 | state->Reg[BITS(12, 15)] = rm; |
| 6384 | else | 6347 | else |
| 6385 | /* SXTAH */ | 6348 | state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm; |
| 6386 | state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + Rm; | ||
| 6387 | 6349 | ||
| 6388 | return 1; | 6350 | return 1; |
| 6351 | } | ||
| 6389 | } | 6352 | } |
| 6353 | break; | ||
| 6354 | |||
| 6390 | case 0x6c: // UXTB16 and UXTAB16 | 6355 | case 0x6c: // UXTB16 and UXTAB16 |
| 6391 | { | 6356 | { |
| 6392 | const u8 rm_idx = BITS(0, 3); | 6357 | const u8 rm_idx = BITS(0, 3); |
| @@ -6414,132 +6379,84 @@ L_stm_s_takeabort: | |||
| 6414 | return 1; | 6379 | return 1; |
| 6415 | } | 6380 | } |
| 6416 | break; | 6381 | break; |
| 6417 | case 0x6e: { | 6382 | case 0x6e: // USAT, USAT16, UXTB, and UXTAB |
| 6418 | ARMword Rm; | 6383 | { |
| 6419 | int ror = -1; | 6384 | const u8 op2 = BITS(5, 7); |
| 6420 | |||
| 6421 | switch (BITS(4, 11)) { | ||
| 6422 | case 0x07: | ||
| 6423 | ror = 0; | ||
| 6424 | break; | ||
| 6425 | case 0x47: | ||
| 6426 | ror = 8; | ||
| 6427 | break; | ||
| 6428 | case 0x87: | ||
| 6429 | ror = 16; | ||
| 6430 | break; | ||
| 6431 | case 0xc7: | ||
| 6432 | ror = 24; | ||
| 6433 | break; | ||
| 6434 | |||
| 6435 | case 0x01: | ||
| 6436 | case 0xf3: | ||
| 6437 | //ichfly | ||
| 6438 | //USAT16 | ||
| 6439 | { | ||
| 6440 | const u8 rd_idx = BITS(12, 15); | ||
| 6441 | const u8 rn_idx = BITS(0, 3); | ||
| 6442 | const u8 num_bits = BITS(16, 19); | ||
| 6443 | const s16 max = 0xFFFF >> (16 - num_bits); | ||
| 6444 | s16 rn_lo = (state->Reg[rn_idx]); | ||
| 6445 | s16 rn_hi = (state->Reg[rn_idx] >> 16); | ||
| 6446 | |||
| 6447 | if (max < rn_lo) { | ||
| 6448 | rn_lo = max; | ||
| 6449 | SETQ; | ||
| 6450 | } else if (rn_lo < 0) { | ||
| 6451 | rn_lo = 0; | ||
| 6452 | SETQ; | ||
| 6453 | } | ||
| 6454 | |||
| 6455 | if (max < rn_hi) { | ||
| 6456 | rn_hi = max; | ||
| 6457 | SETQ; | ||
| 6458 | } else if (rn_hi < 0) { | ||
| 6459 | rn_hi = 0; | ||
| 6460 | SETQ; | ||
| 6461 | } | ||
| 6462 | |||
| 6463 | state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi << 16) & 0xFFFF); | ||
| 6464 | return 1; | ||
| 6465 | } | ||
| 6466 | |||
| 6467 | default: | ||
| 6468 | break; | ||
| 6469 | } | ||
| 6470 | 6385 | ||
| 6471 | if (ror == -1) { | 6386 | // USAT16 |
| 6472 | if (BITS(4, 6) == 0x7) { | 6387 | if (op2 == 0x01) { |
| 6473 | printf("Unhandled v6 insn: usat\n"); | 6388 | const u8 rd_idx = BITS(12, 15); |
| 6474 | return 0; | 6389 | const u8 rn_idx = BITS(0, 3); |
| 6390 | const u8 num_bits = BITS(16, 19); | ||
| 6391 | const s16 max = 0xFFFF >> (16 - num_bits); | ||
| 6392 | s16 rn_lo = (state->Reg[rn_idx]); | ||
| 6393 | s16 rn_hi = (state->Reg[rn_idx] >> 16); | ||
| 6394 | |||
| 6395 | if (max < rn_lo) { | ||
| 6396 | rn_lo = max; | ||
| 6397 | SETQ; | ||
| 6398 | } else if (rn_lo < 0) { | ||
| 6399 | rn_lo = 0; | ||
| 6400 | SETQ; | ||
| 6475 | } | 6401 | } |
| 6476 | break; | 6402 | |
| 6403 | if (max < rn_hi) { | ||
| 6404 | rn_hi = max; | ||
| 6405 | SETQ; | ||
| 6406 | } else if (rn_hi < 0) { | ||
| 6407 | rn_hi = 0; | ||
| 6408 | SETQ; | ||
| 6409 | } | ||
| 6410 | |||
| 6411 | state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi << 16) & 0xFFFF); | ||
| 6412 | return 1; | ||
| 6477 | } | 6413 | } |
| 6478 | 6414 | else if (op2 == 0x03) { | |
| 6479 | Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - ror)) & 0xFF) & 0xFF); | 6415 | const u8 rotate = BITS(10, 11) * 8; |
| 6480 | 6416 | const u32 rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFF) & 0xFF); | |
| 6481 | if (BITS(16, 19) == 0xf) | 6417 | |
| 6418 | if (BITS(16, 19) == 0xf) | ||
| 6482 | /* UXTB */ | 6419 | /* UXTB */ |
| 6483 | state->Reg[BITS(12, 15)] = Rm; | 6420 | state->Reg[BITS(12, 15)] = rm; |
| 6484 | else | 6421 | else |
| 6485 | /* UXTAB */ | 6422 | /* UXTAB */ |
| 6486 | state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + Rm; | 6423 | state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm; |
| 6487 | |||
| 6488 | return 1; | ||
| 6489 | } | ||
| 6490 | 6424 | ||
| 6491 | case 0x6f: { | 6425 | return 1; |
| 6492 | ARMword Rm; | ||
| 6493 | int ror = -1; | ||
| 6494 | |||
| 6495 | switch (BITS(4, 11)) { | ||
| 6496 | case 0x07: | ||
| 6497 | ror = 0; | ||
| 6498 | break; | ||
| 6499 | case 0x47: | ||
| 6500 | ror = 8; | ||
| 6501 | break; | ||
| 6502 | case 0x87: | ||
| 6503 | ror = 16; | ||
| 6504 | break; | ||
| 6505 | case 0xc7: | ||
| 6506 | ror = 24; | ||
| 6507 | break; | ||
| 6508 | |||
| 6509 | case 0xfb: // REVSH | ||
| 6510 | { | ||
| 6511 | DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00) >> 8); | ||
| 6512 | if (DEST & 0x8000) | ||
| 6513 | DEST |= 0xffff0000; | ||
| 6514 | return 1; | ||
| 6515 | } | ||
| 6516 | default: | ||
| 6517 | break; | ||
| 6518 | } | 6426 | } |
| 6427 | else { | ||
| 6428 | printf("Unimplemented op: USAT"); | ||
| 6429 | } | ||
| 6430 | } | ||
| 6431 | break; | ||
| 6519 | 6432 | ||
| 6520 | if (ror == -1) | 6433 | case 0x6f: // UXTH, UXTAH, and REVSH. |
| 6521 | break; | 6434 | { |
| 6522 | 6435 | const u8 op2 = BITS(5, 7); | |
| 6523 | Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - ror)) & 0xFFFF) & 0xFFFF); | ||
| 6524 | 6436 | ||
| 6525 | /* UXT */ | 6437 | // REVSH |
| 6526 | /* state->Reg[BITS (12, 15)] = Rm; */ | 6438 | if (op2 == 0x05) { |
| 6527 | /* dyf add */ | 6439 | DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00) >> 8); |
| 6528 | if (BITS(16, 19) == 0xf) { | 6440 | if (DEST & 0x8000) |
| 6529 | state->Reg[BITS(12, 15)] = Rm; | 6441 | DEST |= 0xffff0000; |
| 6530 | } | 6442 | return 1; |
| 6531 | else { | ||
| 6532 | /* UXTAH */ | ||
| 6533 | /* state->Reg[BITS (12, 15)] = state->Reg [BITS (16, 19)] + Rm; */ | ||
| 6534 | // printf("rd is %x rn is %x rm is %x rotate is %x\n", state->Reg[BITS (12, 15)], state->Reg[BITS (16, 19)] | ||
| 6535 | // , Rm, BITS(10, 11)); | ||
| 6536 | // printf("icounter is %lld\n", state->NumInstrs); | ||
| 6537 | state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + Rm; | ||
| 6538 | // printf("rd is %x\n", state->Reg[BITS (12, 15)]); | ||
| 6539 | // exit(-1); | ||
| 6540 | } | 6443 | } |
| 6444 | // UXTH and UXTAH | ||
| 6445 | else if (op2 == 0x03) { | ||
| 6446 | const u8 rotate = BITS(10, 11) * 8; | ||
| 6447 | const ARMword rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFFFF) & 0xFFFF); | ||
| 6448 | |||
| 6449 | // UXTH | ||
| 6450 | if (BITS(16, 19) == 0xf) { | ||
| 6451 | state->Reg[BITS(12, 15)] = rm; | ||
| 6452 | } | ||
| 6453 | // UXTAH | ||
| 6454 | else { | ||
| 6455 | state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm; | ||
| 6456 | } | ||
| 6541 | 6457 | ||
| 6542 | return 1; | 6458 | return 1; |
| 6459 | } | ||
| 6543 | } | 6460 | } |
| 6544 | case 0x70: | 6461 | case 0x70: |
| 6545 | // ichfly | 6462 | // ichfly |