* Send (or emulate) a pop instruction. */
| 1078 | * Send (or emulate) a pop instruction. |
| 1079 | */ |
| 1080 | bool sendPop(FILE *out, bool preserve_rax, Register reg, Register rscratch) |
| 1081 | { |
| 1082 | // Special cases: |
| 1083 | switch (reg) |
| 1084 | { |
| 1085 | case REGISTER_FLAGS: |
| 1086 | { |
| 1087 | int scratch = -1; |
| 1088 | if (preserve_rax) |
| 1089 | { |
| 1090 | scratch = getRegIdx(rscratch); |
| 1091 | if (scratch < 0) |
| 1092 | sendMovFromR64ToStack(out, RAX_IDX, |
| 1093 | -(int32_t)sizeof(uint64_t)); |
| 1094 | else |
| 1095 | sendMovFromR64ToR64(out, RAX_IDX, scratch); |
| 1096 | } |
| 1097 | |
| 1098 | sendPop(out, false, REGISTER_RAX); |
| 1099 | // add $0x7f,%al |
| 1100 | // sahf |
| 1101 | fprintf(out, "%u,%u,", 0x04, 0x7f); |
| 1102 | fprintf(out, "%u,", 0x9e); |
| 1103 | |
| 1104 | if (preserve_rax) |
| 1105 | { |
| 1106 | if (scratch < 0) |
| 1107 | sendMovFromStackToR64(out, -2*(int32_t)sizeof(uint64_t), |
| 1108 | RAX_IDX); |
| 1109 | else |
| 1110 | { |
| 1111 | sendMovFromR64ToR64(out, scratch, RAX_IDX); |
| 1112 | return true; |
| 1113 | } |
| 1114 | } |
| 1115 | return false; |
| 1116 | } |
| 1117 | |
| 1118 | case REGISTER_RFLAGS: |
| 1119 | fprintf(out, "%u,", 0x9d); |
| 1120 | return false; |
| 1121 | |
| 1122 | case REGISTER_RIP: |
| 1123 | // %rip is treated as read-only & stored in a special slot. |
| 1124 | // So the pop operation is treated as a NOP. |
| 1125 | return false; |
| 1126 | |
| 1127 | default: |
| 1128 | break; |
| 1129 | } |
| 1130 | |
| 1131 | int regno = getRegIdx(reg); |
| 1132 | int32_t size = getRegSize(reg); |
| 1133 | if (regno >= 0) |
| 1134 | { |
| 1135 | // pop %reg |
| 1136 | const uint8_t REX[] = |
| 1137 | {0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x00, |
no test coverage detected