9#include "virtual_memory.h"
10#include "unreachable.h"
12#define EMIT(p,x) do { \
13 memcpy(p, x, sizeof(x)); \
16#define EMIT_U32(p,x) *((uint32_t*)(p)) = x; p += sizeof(uint32_t)
17#define EMIT_IMM32(p,x) \
18 EMIT_U32(p, 0x9280000c | \
19 ((x <= INT32_MAX) << 30) | \
20 (((x <= INT32_MAX) ? (x & 0xFFFF) : (~x & 0xFFFF)) << 5)); \
21 EMIT_U32(p, 0xf2a0000c | \
22 (((x >> 16) & 0xFFFF) << 5));
24#ifdef HASHX_COMPILER_A64
27#define COMP_MAX_INSTR_SIZE 24
29static const uint8_t a64_prologue[] = {
30 0x07, 0x1c, 0x40, 0xf9,
31 0x06, 0x18, 0x40, 0xf9,
32 0x05, 0x14, 0x40, 0xf9,
33 0x04, 0x10, 0x40, 0xf9,
34 0x03, 0x0c, 0x40, 0xf9,
35 0x02, 0x08, 0x40, 0xf9,
36 0x01, 0x04, 0x40, 0xf9,
37 0xe8, 0x03, 0x00, 0xaa,
38 0x00, 0x00, 0x40, 0xf9,
39 0xe9, 0x03, 0x1f, 0x2a,
42static const uint8_t a64_epilogue[] = {
43 0x00, 0x01, 0x00, 0xf9,
44 0x01, 0x05, 0x00, 0xf9,
45 0x02, 0x09, 0x00, 0xf9,
46 0x03, 0x0d, 0x00, 0xf9,
47 0x04, 0x11, 0x00, 0xf9,
48 0x05, 0x15, 0x00, 0xf9,
49 0x06, 0x19, 0x00, 0xf9,
50 0x07, 0x1d, 0x00, 0xf9,
51 0xc0, 0x03, 0x5f, 0xd6,
54bool hashx_compile_a64(
const hashx_program* program, uint8_t* code) {
55 if (!hashx_vm_rw(code, COMP_CODE_SIZE))
58 uint8_t* target = NULL;
60 EMIT(pos, a64_prologue);
61 for (
size_t i = 0; i < program->code_size; ++i) {
62 if (pos + COMP_MAX_INSTR_SIZE > code + COMP_CODE_SIZE)
65 switch (instr->opcode)
68 EMIT_U32(pos, 0x9bc07c00 |
77 EMIT_U32(pos, 0x9b407c00 |
86 assert(creg != instr->dst);
87 EMIT_U32(pos, 0x9b007c00 |
93 assert(creg != instr->dst);
94 EMIT_U32(pos, 0xcb000000 |
100 assert(creg != instr->dst);
101 EMIT_U32(pos, 0xca000000 |
107 assert(creg != instr->dst);
108 EMIT_U32(pos, 0x8b000000 |
110 (instr->imm32 << 10) |
115 assert(creg != instr->dst);
116 EMIT_U32(pos, 0x93c00000 |
118 (instr->imm32 << 10) |
123 assert(creg != instr->dst);
124 EMIT_IMM32(pos, instr->imm32);
125 EMIT_U32(pos, 0x8b0c0000 |
130 assert(creg != instr->dst);
131 EMIT_IMM32(pos, instr->imm32);
132 EMIT_U32(pos, 0xca0c0000 |
140 EMIT_IMM32(pos, instr->imm32);
141 EMIT_U32(pos, 0x2a00012b | (creg << 16));
142 EMIT_U32(pos, 0x6a0c017f);
143 EMIT_U32(pos, 0x5a891129);
144 EMIT_U32(pos, 0x54000000 |
145 ((((uint32_t)(target - pos)) >> 2) & 0x7FFFF) << 5);
153 if (pos +
sizeof a64_epilogue > code + COMP_CODE_SIZE)
155 EMIT(pos, a64_epilogue);
156 if (!hashx_vm_rx(code, COMP_CODE_SIZE))
159 __builtin___clear_cache((
void*)code, (
void*)pos);