| 4341 | } |
| 4342 | |
| 4343 | ZYDIS_EXPORT ZyanStatus ZydisEncoderEncodeInstructionAbsolute(ZydisEncoderRequest *request, |
| 4344 | void *buffer, ZyanUSize *length, ZyanU64 runtime_address) |
| 4345 | { |
| 4346 | if (!request || !buffer || !length) |
| 4347 | { |
| 4348 | return ZYAN_STATUS_INVALID_ARGUMENT; |
| 4349 | } |
| 4350 | ZYAN_CHECK(ZydisEncoderCheckRequestSanity(request)); |
| 4351 | |
| 4352 | const ZydisEncoderRelInfo *rel_info = ZydisGetRelInfo(request->mnemonic); |
| 4353 | ZydisEncoderOperand *op_rip_rel = ZYAN_NULL; |
| 4354 | ZyanBool adjusted_rel = ZYAN_FALSE; |
| 4355 | ZyanU64 absolute_address = 0; |
| 4356 | ZyanU8 mode_index = ZydisGetMachineModeWidth(request->machine_mode) >> 5; |
| 4357 | for (ZyanU8 i = 0; i < request->operand_count; ++i) |
| 4358 | { |
| 4359 | ZydisEncoderOperand *op = &request->operands[i]; |
| 4360 | if ((op->type == ZYDIS_OPERAND_TYPE_IMMEDIATE) && rel_info) |
| 4361 | { |
| 4362 | if (adjusted_rel) |
| 4363 | { |
| 4364 | return ZYAN_STATUS_INVALID_ARGUMENT; |
| 4365 | } |
| 4366 | |
| 4367 | switch (rel_info->accepts_scaling_hints) |
| 4368 | { |
| 4369 | case ZYDIS_SIZE_HINT_NONE: |
| 4370 | case ZYDIS_SIZE_HINT_OSZ: |
| 4371 | { |
| 4372 | static const ZyanI8 asz_priority[3][3] = |
| 4373 | { |
| 4374 | { 0, 1, 2 }, |
| 4375 | { 0, 2, 1 }, |
| 4376 | { 0, 2, -1 }, |
| 4377 | }; |
| 4378 | static const ZyanI8 osz_priority[3][3] = |
| 4379 | { |
| 4380 | { 0, 1, 2 }, |
| 4381 | { 0, 2, 1 }, |
| 4382 | { 0, 2, 1 }, |
| 4383 | }; |
| 4384 | ZyanI8 forced_priority_row[3] = { -1, -1, -1 }; |
| 4385 | ZyanI8 *priority_row = ZYAN_NULL; |
| 4386 | ZyanU8 extra_length = 0; |
| 4387 | ZyanU8 start_offset = 0; |
| 4388 | if (rel_info->accepts_scaling_hints == ZYDIS_SIZE_HINT_NONE) |
| 4389 | { |
| 4390 | if ((request->branch_type == ZYDIS_BRANCH_TYPE_FAR) || |
| 4391 | (request->branch_width == ZYDIS_BRANCH_WIDTH_64)) |
| 4392 | { |
| 4393 | return ZYAN_STATUS_INVALID_ARGUMENT; |
| 4394 | } |
| 4395 | if ((rel_info->accepts_branch_hints) && |
| 4396 | (request->prefixes & (ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN | |
| 4397 | ZYDIS_ATTRIB_HAS_BRANCH_TAKEN))) |
| 4398 | { |
| 4399 | extra_length += 1; |
| 4400 | } |