For most instructions, instruction_index == operand_index, but some instructions (floating point, some others) have an implicit first operand (st0), so we have to remap things a bit Instruction index represents the 'nth' argument/opcode in the instruction, whereas the operand index is index that XED holds that operand in the instruction
| 191 | // For most instructions, instruction_index == operand_index, but some instructions (floating point, some others) have an implicit first operand (st0), so we have to remap things a bit |
| 192 | // Instruction index represents the 'nth' argument/opcode in the instruction, whereas the operand index is index that XED holds that operand in the instruction |
| 193 | static size_t ReadILOperand(LowLevelILFunction& il, const xed_decoded_inst_t* const xedd, |
| 194 | const size_t addr, const size_t instruction_index, |
| 195 | const size_t operand_index, size_t sizeToRead = 0) |
| 196 | { |
| 197 | if (sizeToRead == 0) |
| 198 | sizeToRead = xed_decoded_inst_operand_length_bits(xedd, (unsigned)operand_index) / 8; |
| 199 | const unsigned int immediateSize = xed_decoded_inst_get_operand_width(xedd) / 8; |
| 200 | const int64_t relbr = xed_decoded_inst_get_branch_displacement(xedd) + addr + xed_decoded_inst_get_length(xedd); |
| 201 | const xed_operand_enum_t op_name = xed_operand_name(xed_inst_operand(xed_decoded_inst_inst(xedd), (unsigned)operand_index)); |
| 202 | const auto reg1 = xed_decoded_inst_get_reg(xedd, op_name); |
| 203 | const size_t addrSize = xed_decoded_inst_get_machine_mode_bits(xedd) / 8; |
| 204 | |
| 205 | switch (op_name) |
| 206 | { |
| 207 | // Register cases |
| 208 | case XED_OPERAND_REG0: |
| 209 | case XED_OPERAND_REG1: |
| 210 | case XED_OPERAND_REG2: |
| 211 | case XED_OPERAND_REG3: |
| 212 | case XED_OPERAND_REG4: |
| 213 | case XED_OPERAND_REG5: |
| 214 | case XED_OPERAND_REG6: |
| 215 | case XED_OPERAND_REG7: |
| 216 | case XED_OPERAND_REG8: |
| 217 | case XED_OPERAND_BASE0: |
| 218 | case XED_OPERAND_BASE1: |
| 219 | if ((reg1 == XED_REG_RIP) || (reg1 == XED_REG_EIP) || (reg1 == XED_REG_IP)) |
| 220 | return il.Operand(instruction_index, il.ConstPointer(sizeToRead, addr)); |
| 221 | return il.Operand(instruction_index, il.Register(sizeToRead, (uint32_t)reg1)); |
| 222 | |
| 223 | // Immediates: |
| 224 | case XED_OPERAND_IMM0: |
| 225 | if (xed_decoded_inst_get_immediate_is_signed(xedd)) |
| 226 | return il.Operand(instruction_index, il.Const(immediateSize, xed_decoded_inst_get_signed_immediate(xedd))); |
| 227 | else |
| 228 | return il.Operand(instruction_index, il.Const(immediateSize, xed_decoded_inst_get_unsigned_immediate(xedd))); |
| 229 | |
| 230 | // Second Immdiate Value |
| 231 | case XED_OPERAND_IMM1: |
| 232 | return il.Operand(instruction_index, il.Const(1, xed_decoded_inst_get_second_immediate(xedd))); |
| 233 | |
| 234 | // Immediate Address Value |
| 235 | case XED_OPERAND_PTR: |
| 236 | case XED_OPERAND_RELBR: |
| 237 | return il.Operand(instruction_index, il.ConstPointer(addrSize, relbr)); |
| 238 | |
| 239 | // Memory Acesses |
| 240 | case XED_OPERAND_AGEN: |
| 241 | case XED_OPERAND_MEM0: |
| 242 | case XED_OPERAND_MEM1: |
| 243 | return il.Operand(instruction_index, il.Load(sizeToRead, GetILOperandMemoryAddress(il, xedd, addr, instruction_index, operand_index))); |
| 244 | |
| 245 | // Not implimented or error |
| 246 | default: |
| 247 | return il.Undefined(); |
| 248 | } |
| 249 | } |
| 250 |
no test coverage detected