8#include "virtual_memory.h"
9#include "unreachable.h"
11#if defined(_WIN32) || defined(__CYGWIN__)
15#define EMIT(p,x) do { \
16 memcpy(p, x, sizeof(x)); \
19#define EMIT_BYTE(p,x) *((p)++) = x
20#define EMIT_U16(p,x) *((uint16_t*)(p)) = x; p += sizeof(uint16_t)
21#define EMIT_U32(p,x) *((uint32_t*)(p)) = x; p += sizeof(uint32_t)
22#define EMIT_U64(p,x) *((uint64_t*)(p)) = x; p += sizeof(uint64_t)
24#define GEN_SIB(scale, index, base) ((scale << 6) | (index << 3) | base)
26#ifdef HASHX_COMPILER_X86
29#define COMP_MAX_INSTR_SIZE 10
31static const uint8_t x86_prologue[] = {
34 0x48, 0x83, 0xEC, 0x20,
35 0x4C, 0x89, 0x24, 0x24,
36 0x4C, 0x89, 0x6C, 0x24, 0x08,
37 0x4C, 0x89, 0x74, 0x24, 0x10,
38 0x4C, 0x89, 0x7C, 0x24, 0x18,
40 0x4C, 0x89, 0x64, 0x24, 0x08,
41 0x4C, 0x89, 0x6C, 0x24, 0x10,
42 0x4C, 0x89, 0x74, 0x24, 0x18,
43 0x4C, 0x89, 0x7C, 0x24, 0x20,
44 0x48, 0x83, 0xEC, 0x10,
45 0x48, 0x89, 0x34, 0x24,
46 0x48, 0x89, 0x7C, 0x24, 0x08,
51 0x4C, 0x8B, 0x49, 0x08,
52 0x4C, 0x8B, 0x51, 0x10,
53 0x4C, 0x8B, 0x59, 0x18,
54 0x4C, 0x8B, 0x61, 0x20,
55 0x4C, 0x8B, 0x69, 0x28,
56 0x4C, 0x8B, 0x71, 0x30,
57 0x4C, 0x8B, 0x79, 0x38
60static const uint8_t x86_epilogue[] = {
62 0x4C, 0x89, 0x49, 0x08,
63 0x4C, 0x89, 0x51, 0x10,
64 0x4C, 0x89, 0x59, 0x18,
65 0x4C, 0x89, 0x61, 0x20,
66 0x4C, 0x89, 0x69, 0x28,
67 0x4C, 0x89, 0x71, 0x30,
68 0x4C, 0x89, 0x79, 0x38,
70 0x4C, 0x8B, 0x24, 0x24,
71 0x4C, 0x8B, 0x6C, 0x24, 0x08,
72 0x4C, 0x8B, 0x74, 0x24, 0x10,
73 0x4C, 0x8B, 0x7C, 0x24, 0x18,
74 0x48, 0x83, 0xC4, 0x20,
76 0x48, 0x8B, 0x34, 0x24,
77 0x48, 0x8B, 0x7C, 0x24, 0x08,
78 0x48, 0x83, 0xC4, 0x10,
79 0x4C, 0x8B, 0x64, 0x24, 0x08,
80 0x4C, 0x8B, 0x6C, 0x24, 0x10,
81 0x4C, 0x8B, 0x74, 0x24, 0x18,
82 0x4C, 0x8B, 0x7C, 0x24, 0x20,
87bool hashx_compile_x86(
const hashx_program* program, uint8_t* code) {
88 if (!hashx_vm_rw(code, COMP_CODE_SIZE))
91 uint8_t* target = NULL;
92 EMIT(pos, x86_prologue);
93 for (
size_t i = 0; i < program->code_size; ++i) {
94 if (pos + COMP_MAX_INSTR_SIZE > code + COMP_CODE_SIZE)
97 switch (instr->opcode)
100 EMIT_U64(pos, 0x8b4ce0f749c08b49 |
101 (((uint64_t)instr->src) << 40) |
102 (((uint64_t)instr->dst) << 16));
103 EMIT_BYTE(pos, 0xc2 + 8 * instr->dst);
106 EMIT_U64(pos, 0x8b4ce8f749c08b49 |
107 (((uint64_t)instr->src) << 40) |
108 (((uint64_t)instr->dst) << 16));
109 EMIT_BYTE(pos, 0xc2 + 8 * instr->dst);
112 EMIT_U32(pos, 0xc0af0f4d | (instr->dst << 27) | (instr->src << 24));
115 EMIT_U16(pos, 0x2b4d);
116 EMIT_BYTE(pos, 0xc0 | (instr->dst << 3) | instr->src);
119 EMIT_U16(pos, 0x334d);
120 EMIT_BYTE(pos, 0xc0 | (instr->dst << 3) | instr->src);
123 EMIT_U32(pos, 0x00048d4f |
125 GEN_SIB(instr->imm32, instr->src, instr->dst) << 24);
128 EMIT_U32(pos, 0x00c8c149 | (instr->dst << 16) | (instr->imm32 << 24));
131 EMIT_U16(pos, 0x8149);
132 EMIT_BYTE(pos, 0xc0 | instr->dst);
133 EMIT_U32(pos, instr->imm32);
136 EMIT_U16(pos, 0x8149);
137 EMIT_BYTE(pos, 0xf0 | instr->dst);
138 EMIT_U32(pos, instr->imm32);
142 EMIT_U32(pos, 0x440fff85);
143 EMIT_BYTE(pos, 0xf7);
146 EMIT_U64(pos, ((uint64_t)instr->imm32) << 32 | 0xc2f7f209);
147 EMIT_U16(pos, ((target - pos) << 8) | 0x74);
153 if (pos +
sizeof x86_epilogue > code + COMP_CODE_SIZE)
155 EMIT(pos, x86_epilogue);
156 return hashx_vm_rx(code, COMP_CODE_SIZE);