| 785 | } |
| 786 | |
| 787 | void EbGb(int instruction, struct Data* data, bool includeLock = false) { |
| 788 | while (data->valid) { |
| 789 | int eb; |
| 790 | int gb; |
| 791 | int rm; |
| 792 | |
| 793 | for (int setsFlags = 0; setsFlags < 3; setsFlags++) { |
| 794 | for (eb = 0; eb < 8; eb++) { |
| 795 | for (gb = 0; gb < 8; gb++) { |
| 796 | U8* e; |
| 797 | U8* g; |
| 798 | |
| 799 | if (eb == gb) |
| 800 | continue; |
| 801 | rm = eb | (gb << 3) | 0xC0; |
| 802 | newInstructionWithRM(instruction, rm, data->flags); |
| 803 | pushConstant(data); |
| 804 | e = cpu->reg8[E(rm)]; |
| 805 | g = cpu->reg8[G(rm)]; |
| 806 | cpu->reg[E8(rm)].u32 = DEFAULT; |
| 807 | cpu->reg[G8(rm)].u32 = DEFAULT; |
| 808 | *e = data->var1; |
| 809 | *g = data->var2; |
| 810 | |
| 811 | if (setsFlags == 0) { |
| 812 | pushCode8(0x39); |
| 813 | pushCode8(0xc0); // cmp eax, eax: this will overwrite flags so the above code might take a different path in the dynamic cores that optimize away flag calculation |
| 814 | } else if (setsFlags == 2) { |
| 815 | if (eb != 0 && gb != 0) { |
| 816 | // good test for JitCodeGen::getCF |
| 817 | pushCode8(0x0f); // setc al |
| 818 | pushCode8(0x92); |
| 819 | pushCode8(0xc0); |
| 820 | } |
| 821 | // flags will be calculate in JIT |
| 822 | U8 reg = 5; |
| 823 | if (eb == 5 || gb == 5) { |
| 824 | if (eb == 6 || gb == 6) { |
| 825 | reg = 7; |
| 826 | } else { |
| 827 | reg = 6; |
| 828 | } |
| 829 | } |
| 830 | pushCode8(0x9c); // push flags |
| 831 | pushCode8(0x58 + reg); // pop reg |
| 832 | } |
| 833 | runTestCPU(); |
| 834 | assertResult(data, cpu, instruction, *e, *g, E8(rm), G8(rm), 0, 8, setsFlags == 0); |
| 835 | if (setsFlags == 2 && eb != 0 && gb != 0) { |
| 836 | assertTrue(cpu->getCF() == (cpu->reg[0].u32 & CF)); |
| 837 | } |
| 838 | } |
| 839 | } |
| 840 | } |
| 841 | for (int lock = 0; lock < 3; lock++) { |
| 842 | for (gb = 0; gb < 8; gb++) { |
| 843 | U8* g; |
| 844 | U32 result; |
no test coverage detected