diff options
author | Ian Moffett <ian@osmora.org> | 2025-10-03 19:22:37 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-10-03 19:23:36 -0400 |
commit | 2025b837c6e5e65d2d2f2b472620e4b639af8755 (patch) | |
tree | a59055d0ba1e041d2422da722053aeee34bf7e6c /src/sys/arch/amd64 | |
parent | b7c88d4a4d9e06a2984eb0812db407e3f49a629a (diff) |
np: codegen: Support returning symbols / strings
Introduce support for returning symbols or strings in memory by using
the symbol table and REX prefixes for 64-bit register accesses
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'src/sys/arch/amd64')
-rw-r--r-- | src/sys/arch/amd64/np/piir_conv.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/src/sys/arch/amd64/np/piir_conv.c b/src/sys/arch/amd64/np/piir_conv.c index f949f48..3cb49f2 100644 --- a/src/sys/arch/amd64/np/piir_conv.c +++ b/src/sys/arch/amd64/np/piir_conv.c @@ -76,6 +76,7 @@ typedef enum { /* SYS-V ABI specific */ #define R32_RETVAL R32_EAX +#define R64_RETVAL R64_RAX /* Declare an instruction array */ #define INST_DECL(...) ((inst_t)__VA_ARGS__) @@ -92,6 +93,10 @@ typedef enum { #define OP_LOAD32_R32(IMM32, RD) INST_DECL({0xB8 + (RD), (IMM32)}) #define OP_LOAD32_R32_LEN 5 +/* MOV R64, IMM64 (REX.W | 0xB8 + rd) */ +#define OP_LOAD64_R64(IMM64, RD) INST_DECL({0x48, 0xB8 + (RD), (IMM64)}) +#define OP_LOAD64_R64_LEN 10 + /* * Push an instruction byte into the virtual * machine descriptor's code buffer @@ -109,11 +114,32 @@ vm_push(struct piir_vm *vm, inst_t inst, size_t len) return len; } +/* + * Push a 64-bit value + */ +static void +vm_push64(struct piir_vm *vm, uint64_t v) +{ + size_t max_len; + uint64_t *p; + + max_len = (vm->code_i + sizeof(v)); + if (max_len >= sizeof(vm->code) - 1) { + return; + } + + p = (uint64_t *)&vm->code[vm->code_i]; + *p = v; + vm->code_i += sizeof(v); +} + ssize_t md_piir_decode(struct np_work *work, struct piir_vm *vm, ir_byte_t input) { + struct symbol *sym; struct piir_stack *stack; ssize_t len; + int error; if (vm == NULL) { return -EINVAL; @@ -137,6 +163,34 @@ md_piir_decode(struct np_work *work, struct piir_vm *vm, ir_byte_t input) vm, OP_LOAD32_R32(input, R32_RETVAL), OP_LOAD32_R32_LEN ); + case PIIR_RET_SYMBOL: + /* Get the symbol ID */ + if ((input = piir_pop(stack)) < 0) { + pr_error("failed to pop element from stack\n"); + return input; + } + + /* Lookup the symbol */ + error = symbol_lookup_id(&work->symlist, input, &sym); + if (error < 0) { + pr_error("failed to lookup symbol %d\n", input); + return error; + } + + /* Load some padding into our register */ + error = vm_push(vm, OP_LOAD64_R64(0, R64_RETVAL), OP_LOAD64_R64_LEN); + if (error < 0) { + pr_error("failed to push load op\n"); + return error; + } + + /* + * Move back 8 bytes, load the symbol address + * and overwrite the padding + */ + vm->code_i -= sizeof(sym->addr); + vm_push64(vm, (uintptr_t)sym->addr); + break; case PIIR_NOP: return vm_push(vm, OP_NOP, OP_NOP_LEN); case PIIR_RET_NIL: |