diff options
Diffstat (limited to 'asm/intel64/jmp.cpp')
-rw-r--r-- | asm/intel64/jmp.cpp | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/asm/intel64/jmp.cpp b/asm/intel64/jmp.cpp new file mode 100644 index 0000000..30ae546 --- /dev/null +++ b/asm/intel64/jmp.cpp @@ -0,0 +1,103 @@ +#include "jmp.h" + +#include "codes.h" + +#include <asm/assembler.h> +#include <asm/operators.h> + +#include <asm/intel64/codes.h> + +using namespace std::string_literals; + +namespace { + struct Jump { + std::string name; + OP_T jmp8; ///< if empty, not available + OP_T jmp32; ///< if empty, not available + }; + + std::vector<Jump> jumpOps { + // Call Procedure + {"call", OP_T{}, OP_T{ 0xE8 } }, // no addr8 version + + // Unconditional Jump + {"jmp", OP_T{ 0xEB }, OP_T{ 0xE9 } }, + + // Conditional Jumps + {"ja", OP_T{ 0x77 }, OP_T{ 0x0F, 0x87 }}, + {"jae", OP_T{ 0x73 }, OP_T{ 0x0F, 0x83 }}, + {"jb", OP_T{ 0x72 }, OP_T{ 0x0F, 0x82 }}, + {"jbe", OP_T{ 0x76 }, OP_T{ 0x0F, 0x86 }}, + {"jc", OP_T{ 0x72 }, OP_T{ 0x0F, 0x82 }}, + {"jecxz", OP_T{ 0xE3 }, OP_T{} }, // no addr32 version + {"jrcxz", OP_T{ 0xE3 }, OP_T{} }, // no addr32 version + {"je", OP_T{ 0x74 }, OP_T{ 0x0F, 0x84 }}, + {"jg", OP_T{ 0x7F }, OP_T{ 0x0F, 0x8F }}, + {"jge", OP_T{ 0x7D }, OP_T{ 0x0F, 0x8D }}, + {"jl", OP_T{ 0x7C }, OP_T{ 0x0F, 0x8C }}, + {"jle", OP_T{ 0x7E }, OP_T{ 0x0F, 0x8E }}, + {"jna", OP_T{ 0x76 }, OP_T{ 0x0F, 0x86 }}, + {"jnae", OP_T{ 0x72 }, OP_T{ 0x0F, 0x82 }}, + {"jnb", OP_T{ 0x73 }, OP_T{ 0x0F, 0x83 }}, + {"jnbe", OP_T{ 0x77 }, OP_T{ 0x0F, 0x87 }}, + {"jnc", OP_T{ 0x73 }, OP_T{ 0x0F, 0x83 }}, + {"jne", OP_T{ 0x75 }, OP_T{ 0x0F, 0x85 }}, + {"jng", OP_T{ 0x7E }, OP_T{ 0x0F, 0x8E }}, + {"jnge", OP_T{ 0x7C }, OP_T{ 0x0F, 0x8C }}, + {"jnl", OP_T{ 0x7D }, OP_T{ 0x0F, 0x8D }}, + {"jnle", OP_T{ 0x7F }, OP_T{ 0x0F, 0x8F }}, + {"jno", OP_T{ 0x71 }, OP_T{ 0x0F, 0x81 }}, + {"jnp", OP_T{ 0x7B }, OP_T{ 0x0F, 0x8B }}, + {"jns", OP_T{ 0x79 }, OP_T{ 0x0F, 0x89 }}, + {"jnz", OP_T{ 0x75 }, OP_T{ 0x0F, 0x85 }}, + {"jo", OP_T{ 0x70 }, OP_T{ 0x0F, 0x80 }}, + {"jp", OP_T{ 0x7A }, OP_T{ 0x0F, 0x8A }}, + {"jpe", OP_T{ 0x7A }, OP_T{ 0x0F, 0x8A }}, + {"jpo", OP_T{ 0x7B }, OP_T{ 0x0F, 0x8B }}, + {"js", OP_T{ 0x78 }, OP_T{ 0x0F, 0x88 }}, + {"jz", OP_T{ 0x74 }, OP_T{ 0x0F, 0x84 }}, + }; + + bool registerOps() { + bool result{true}; + for (const auto& jumpOp: jumpOps) { + result &= registerOp(mangleName<AsmArgs::Label>(jumpOp.name), [&](AsmArgs& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_jmp>(jumpOp.name, args, jumpOp.jmp8, jumpOp.jmp32); + }); + } + return result; + } + + bool registered { + registerOps() + }; +} + +Op_jmp::Op_jmp(const std::string& name, AsmArgs& args, const OP_T& jmp8, const OP_T& jmp32) +{ + label = std::any_cast<AsmArgs::Label>(args[0]).name(); + + if (!jmp32.empty()) { // set machine_code + machine_code = jmp32 + OP_T{size_t(4), uint8_t(0)}; + addr_size = 4; + addr_offs = jmp32.size(); + if (!jmp8.empty()) { // also provide alternative + alternative_code = jmp8 + OP_T{size_t(1), uint8_t(0)}; + alternative_size = 1; + alternative_offs = jmp8.size(); + } + } + + if (machine_code.empty() && !jmp8.empty()) { + machine_code = jmp8 + OP_T{size_t(1), uint8_t(0)}; + addr_size = 1; + addr_offs = jmp8.size(); + } + + if (machine_code.empty()) { + throw std::runtime_error("Unimplemented: "s + name); + } + + // actual address not set, yet! +} + |