| 9467 | } |
| 9468 | |
| 9469 | void doTestCmov(U32 instruction, bool isNotFlag, U32 flags, U32 cmpValueThatTriggersFlag, U32 cmpValueThatDoesNotTriggerFlag) { |
| 9470 | for (U32 setFlags = 0; setFlags < 3; setFlags++) { |
| 9471 | for (U32 useFlags = 0; useFlags < 2; useFlags++) { |
| 9472 | for (U32 ed = 0; ed < 8; ed++) { |
| 9473 | for (U32 gd = 0; gd < 8; gd++) { |
| 9474 | Reg* e; |
| 9475 | Reg* g; |
| 9476 | |
| 9477 | if (ed == gd) |
| 9478 | continue; |
| 9479 | U8 rm = ed | (gd << 3) | 0xC0; |
| 9480 | |
| 9481 | if (setFlags == 1) { |
| 9482 | newInstructionWithRM(instruction, rm, useFlags ? flags : 0); |
| 9483 | } else { |
| 9484 | // cmp ed, 0 |
| 9485 | newInstructionWithRM(0x81, 0xf8 | ed, 0); |
| 9486 | if (cpu->big) { |
| 9487 | pushCode32(useFlags ? cmpValueThatTriggersFlag : cmpValueThatDoesNotTriggerFlag); |
| 9488 | } else { |
| 9489 | pushCode16(useFlags ? cmpValueThatTriggersFlag : cmpValueThatDoesNotTriggerFlag); |
| 9490 | } |
| 9491 | pushCode8(0x0F); |
| 9492 | pushCode8(instruction & 0xFF); |
| 9493 | pushCode8(rm); |
| 9494 | if (setFlags == 2) { |
| 9495 | // this will generate flags so the above code can optimize cmp/cmov combination since the cmp flags aren't used later |
| 9496 | // cmp eax, 0 |
| 9497 | pushCode8(0x83); |
| 9498 | pushCode8(0xf8); |
| 9499 | pushCode8(0); |
| 9500 | } |
| 9501 | } |
| 9502 | e = &cpu->reg[ed]; |
| 9503 | g = &cpu->reg[gd]; |
| 9504 | e->u32 = 0x11112222; |
| 9505 | g->u32 = 0x33334444; |
| 9506 | runTestCPU(); |
| 9507 | |
| 9508 | bool wasChanged = useFlags; |
| 9509 | |
| 9510 | if (isNotFlag) { |
| 9511 | wasChanged = !wasChanged; |
| 9512 | } |
| 9513 | if (wasChanged) { |
| 9514 | if (cpu->big) { |
| 9515 | assertTrue(g->u32 == 0x11112222); |
| 9516 | } else { |
| 9517 | assertTrue(g->u32 == 0x33332222); |
| 9518 | } |
| 9519 | } else { |
| 9520 | assertTrue(g->u32 == 0x33334444); |
| 9521 | } |
| 9522 | } |
| 9523 | } |
| 9524 | for (U32 gd = 0; gd < 8; gd++) { |
| 9525 | Reg* g; |
| 9526 |
no test coverage detected