* Emits instructions to load the jump/call/return target into the * corresponding argno register. Else, if I is not a jump/call/return * instruction, load 0. */
| 1172 | * instruction, load 0. |
| 1173 | */ |
| 1174 | static void sendLoadTargetMetadata(FILE *out, const InstrInfo *I, |
| 1175 | CallInfo &info, bool _static, int regno) |
| 1176 | { |
| 1177 | const OpInfo *op = &I->op[0]; |
| 1178 | switch (I->mnemonic) |
| 1179 | { |
| 1180 | case MNEMONIC_RET: |
| 1181 | sendMovFromStackToR64(out, info.rsp_offset, regno); |
| 1182 | sendTranslateToStaticAddress(out, I, info, _static, regno); |
| 1183 | return; |
| 1184 | case MNEMONIC_CALL: |
| 1185 | case MNEMONIC_JMP: |
| 1186 | case MNEMONIC_JO: case MNEMONIC_JNO: case MNEMONIC_JB: case MNEMONIC_JAE: |
| 1187 | case MNEMONIC_JE: case MNEMONIC_JNE: case MNEMONIC_JBE: case MNEMONIC_JA: |
| 1188 | case MNEMONIC_JS: case MNEMONIC_JNS: case MNEMONIC_JP: case MNEMONIC_JNP: |
| 1189 | case MNEMONIC_JL: case MNEMONIC_JGE: case MNEMONIC_JLE: case MNEMONIC_JG: |
| 1190 | case MNEMONIC_JCXZ: case MNEMONIC_JECXZ: case MNEMONIC_JRCXZ: |
| 1191 | if (I->count.op == 1) |
| 1192 | break; |
| 1193 | // Fallthrough: |
| 1194 | |
| 1195 | default: |
| 1196 | unknown: |
| 1197 | |
| 1198 | // This is NOT a jump/call/return, so the target is set to 0: |
| 1199 | sendSExtFromI32ToR64(out, 0, regno); |
| 1200 | return; |
| 1201 | } |
| 1202 | |
| 1203 | switch (op->type) |
| 1204 | { |
| 1205 | case OPTYPE_REG: |
| 1206 | if (info.isClobbered(op->reg)) |
| 1207 | sendMovFromStackToR64(out, info.getOffset(op->reg), regno); |
| 1208 | else |
| 1209 | { |
| 1210 | int regno_1 = getRegIdx(op->reg); |
| 1211 | assert(regno_1 >= 0); |
| 1212 | sendMovFromR64ToR64(out, regno_1, regno); |
| 1213 | } |
| 1214 | sendTranslateToStaticAddress(out, I, info, _static, regno); |
| 1215 | return; |
| 1216 | case OPTYPE_MEM: |
| 1217 | // This is an indirect jump/call. Convert the instruction into a |
| 1218 | // mov instruction that loads the target in the correct register |
| 1219 | (void)sendLoadFromMemOpToR64(out, I, info, op->size, |
| 1220 | op->mem.seg, op->mem.disp, op->mem.base, op->mem.index, |
| 1221 | op->mem.scale, /*lea=*/false, regno); |
| 1222 | sendTranslateToStaticAddress(out, I, info, _static, regno); |
| 1223 | return; |
| 1224 | |
| 1225 | case OPTYPE_IMM: |
| 1226 | { |
| 1227 | // This is a direct jump/call. Load the target into the correct |
| 1228 | // register. |
| 1229 | |
| 1230 | intptr_t target = I->address + I->size + op->imm; |
| 1231 | sendLoadPointerMetadata(out, info, _static, target, regno); |
no test coverage detected