summaryrefslogtreecommitdiffhomepage
path: root/asm/intel64/jmp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'asm/intel64/jmp.cpp')
-rw-r--r--asm/intel64/jmp.cpp103
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!
+}
+