mirror of
https://github.com/janet-lang/janet
synced 2025-03-31 20:46:56 +00:00
More work on x86 backend.
This commit is contained in:
parent
9fa9286fca
commit
046d299d77
@ -7,13 +7,17 @@
|
|||||||
|
|
||||||
(use ./frontend)
|
(use ./frontend)
|
||||||
|
|
||||||
|
(setdyn :verbose true)
|
||||||
|
|
||||||
|
# Pointer types
|
||||||
(defpointer p32 uint)
|
(defpointer p32 uint)
|
||||||
(defpointer p16 u16)
|
(defpointer p16 u16)
|
||||||
(defpointer cursor p32)
|
(defpointer cursor p32)
|
||||||
(defn-external write:void [fd:int mem:pointer size:uint])
|
|
||||||
(defn-external exit:void [x:int])
|
# Linux syscalls
|
||||||
(defn-external malloc:p32 [x:uint])
|
(defn-syscall brk:p32 12 [amount:uint])
|
||||||
(defn-external free:void [m:p32])
|
(defn-syscall exit:void 60 [code:int])
|
||||||
|
(defn-syscall write:void 1 [fd:int data:p32 size:uint])
|
||||||
|
|
||||||
(defsys w32:void [c:cursor x:uint]
|
(defsys w32:void [c:cursor x:uint]
|
||||||
(def p:p32 (load c))
|
(def p:p32 (load c))
|
||||||
@ -30,9 +34,11 @@
|
|||||||
|
|
||||||
(defsys makebmp:p32 [w:uint h:uint]
|
(defsys makebmp:p32 [w:uint h:uint]
|
||||||
(def size:uint (+ 56 (* w h 4)))
|
(def size:uint (+ 56 (* w h 4)))
|
||||||
(def mem:p32 (malloc size))
|
(def mem:p32 (brk size))
|
||||||
(def cursor_data:p32 mem)
|
#(def cursor_data:p32 mem)
|
||||||
(def c:cursor (address cursor_data))
|
#(def c:cursor (address cursor_data))
|
||||||
|
(def c:cursor (cast (brk 4)))
|
||||||
|
(store c mem)
|
||||||
(w16 c 0x4D42) # ascii "BM"
|
(w16 c 0x4D42) # ascii "BM"
|
||||||
(w32 c size)
|
(w32 c size)
|
||||||
(w32 c 0)
|
(w32 c 0)
|
||||||
@ -52,27 +58,32 @@
|
|||||||
# Draw
|
# Draw
|
||||||
(def red:uint 0xFFFF0000)
|
(def red:uint 0xFFFF0000)
|
||||||
(def blue:uint 0xFF0000FF)
|
(def blue:uint 0xFF0000FF)
|
||||||
|
(def green:uint 0xFF00FF00)
|
||||||
(var y:uint 0)
|
(var y:uint 0)
|
||||||
(while (< y h)
|
(while (< y h)
|
||||||
(var x:uint 0)
|
(var x:uint 0)
|
||||||
(while (< x w)
|
(while (< x w)
|
||||||
(if (> y 64)
|
(def d2:uint (+ (* x x) (* y y)))
|
||||||
(w32 c blue)
|
(if (> d2 100000)
|
||||||
|
(if (> d2 200000) (w32 c green) (w32 c blue))
|
||||||
(w32 c red))
|
(w32 c red))
|
||||||
(set x (+ 1 x)))
|
(set x (+ 1 x)))
|
||||||
(set y (+ y 1)))
|
(set y (+ y 1)))
|
||||||
(write 1 mem size)
|
(write 1 mem size)
|
||||||
(return mem))
|
(return mem))
|
||||||
|
|
||||||
(defsys main:int []
|
(defsys _start:void []
|
||||||
(def w:uint 128)
|
(def w:uint 512)
|
||||||
(def h:uint 512)
|
(def h:uint 512)
|
||||||
(makebmp w h)
|
# (makebmp w h)
|
||||||
(return 0))
|
(def size:uint (+ 56 (* w h 4)))
|
||||||
|
(def mem:p32 (brk size))
|
||||||
|
(store mem (the uint 0x4d424d42))
|
||||||
|
(write 1 mem 4)
|
||||||
|
#(write 1 (cast "hello, world!\n") 14)
|
||||||
|
(exit 0)
|
||||||
|
(return))
|
||||||
|
|
||||||
####
|
####
|
||||||
|
|
||||||
#(dump)
|
(dumpx64)
|
||||||
(print "#include <unistd.h>")
|
|
||||||
(dumpc)
|
|
||||||
#(dumpx64)
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
(def slot-types @{})
|
(def slot-types @{})
|
||||||
(def functions @{})
|
(def functions @{})
|
||||||
(def type-fields @{})
|
(def type-fields @{})
|
||||||
|
(def syscalls @{})
|
||||||
|
|
||||||
(defn get-slot
|
(defn get-slot
|
||||||
[&opt new-name]
|
[&opt new-name]
|
||||||
@ -317,20 +318,11 @@
|
|||||||
(array/push into ;args)
|
(array/push into ;args)
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
# Syscall
|
# Assume function call or syscall
|
||||||
'syscall
|
|
||||||
(do
|
|
||||||
(def slots @[])
|
|
||||||
(def ret (if no-return nil (get-slot)))
|
|
||||||
(each arg args
|
|
||||||
(array/push slots (visit1 arg into)))
|
|
||||||
(array/push into ~(syscall :default ,ret ,;slots))
|
|
||||||
ret)
|
|
||||||
|
|
||||||
# Assume function call
|
|
||||||
(do
|
(do
|
||||||
(def slots @[])
|
(def slots @[])
|
||||||
(def signature (get functions op))
|
(def signature (get functions op))
|
||||||
|
(def is-syscall (get syscalls op))
|
||||||
(assert signature (string "unknown function " op))
|
(assert signature (string "unknown function " op))
|
||||||
(def ret (if no-return nil (get-slot)))
|
(def ret (if no-return nil (get-slot)))
|
||||||
(when ret
|
(when ret
|
||||||
@ -338,7 +330,9 @@
|
|||||||
(assign-type ret (first signature)))
|
(assign-type ret (first signature)))
|
||||||
(each [arg-type arg] (map tuple (drop 1 signature) args)
|
(each [arg-type arg] (map tuple (drop 1 signature) args)
|
||||||
(array/push slots (visit1 arg into false arg-type)))
|
(array/push slots (visit1 arg into false arg-type)))
|
||||||
(array/push into ~(call :default ,ret [pointer ,op] ,;slots))
|
(if is-syscall
|
||||||
|
(array/push into ~(syscall :default ,ret (int ,is-syscall) ,;slots))
|
||||||
|
(array/push into ~(call :default ,ret [pointer ,op] ,;slots)))
|
||||||
ret)))
|
ret)))
|
||||||
|
|
||||||
(errorf "cannot compile %q" code)))
|
(errorf "cannot compile %q" code)))
|
||||||
@ -478,6 +472,20 @@
|
|||||||
(array/push signature tp))
|
(array/push signature tp))
|
||||||
(put functions fn-name (freeze signature)))
|
(put functions fn-name (freeze signature)))
|
||||||
|
|
||||||
|
# External syscall
|
||||||
|
'defn-syscall
|
||||||
|
(do
|
||||||
|
(def [name sysnum args] rest)
|
||||||
|
(assert (tuple? args))
|
||||||
|
(def [fn-name fn-tp] (type-extract name 'void))
|
||||||
|
(def pcount (length args)) #TODO - more complicated signatures
|
||||||
|
(def signature @[fn-tp])
|
||||||
|
(each arg args
|
||||||
|
(def [name tp] (type-extract arg 'int))
|
||||||
|
(array/push signature tp))
|
||||||
|
(put syscalls fn-name sysnum)
|
||||||
|
(put functions fn-name (freeze signature)))
|
||||||
|
|
||||||
# Top level function definition
|
# Top level function definition
|
||||||
'defn
|
'defn
|
||||||
(do
|
(do
|
||||||
@ -544,4 +552,5 @@
|
|||||||
(defmacro defarray [& args] [compile1 ~',(keep-syntax! (dyn *macro-form*) ~(defarray ,;args))])
|
(defmacro defarray [& args] [compile1 ~',(keep-syntax! (dyn *macro-form*) ~(defarray ,;args))])
|
||||||
(defmacro defpointer [& args] [compile1 ~',(keep-syntax! (dyn *macro-form*) ~(defpointer ,;args))])
|
(defmacro defpointer [& args] [compile1 ~',(keep-syntax! (dyn *macro-form*) ~(defpointer ,;args))])
|
||||||
(defmacro defn-external [& args] [compile1 ~',(keep-syntax! (dyn *macro-form*) ~(defn-external ,;args))])
|
(defmacro defn-external [& args] [compile1 ~',(keep-syntax! (dyn *macro-form*) ~(defn-external ,;args))])
|
||||||
|
(defmacro defn-syscall [& args] [compile1 ~',(keep-syntax! (dyn *macro-form*) ~(defn-syscall ,;args))])
|
||||||
(defmacro defsys [& args] [compile1 ~',(keep-syntax! (dyn *macro-form*) ~(defn ,;args))])
|
(defmacro defsys [& args] [compile1 ~',(keep-syntax! (dyn *macro-form*) ~(defn ,;args))])
|
||||||
|
5
examples/sysir/run_drawing2.sh
Executable file
5
examples/sysir/run_drawing2.sh
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
valgrind build/janet examples/sysir/drawing2.janet > temp.nasm
|
||||||
|
nasm -felf64 temp.nasm -l temp.lst -o temp.o
|
||||||
|
ld -o temp.bin -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc temp.o
|
||||||
|
valgrind ./temp.bin
|
@ -158,16 +158,18 @@ static x64RegKind get_slot_regkind(JanetSysx64Context *ctx, uint32_t o) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void assign_registers(JanetSysx64Context *ctx) {
|
void assign_registers(JanetSysx64Context *ctx) {
|
||||||
|
|
||||||
/* simplest register assignment algorithm - first n variables
|
/* simplest register assignment algorithm - first n variables
|
||||||
* get registers, rest get assigned temporary registers and spill on every use. */
|
* get registers, rest get assigned temporary registers and spill on every use. */
|
||||||
|
/* TODO - add option to allocate ALL variables on stack. Makes debugging easier. */
|
||||||
/* TODO - linear scan or graph coloring. Require calculating live ranges */
|
/* TODO - linear scan or graph coloring. Require calculating live ranges */
|
||||||
/* TODO - avoid spills inside loops if possible i.e. not all spills are equal */
|
/* TODO - avoid spills inside loops if possible i.e. not all spills are equal */
|
||||||
/* TODO - move into sysir.c and allow reuse for multiple targets */
|
/* TODO - move into sysir.c and allow reuse for multiple targets */
|
||||||
|
|
||||||
JanetSysCallingConvention cc = ctx->calling_convention;
|
JanetSysCallingConvention cc = ctx->calling_convention;
|
||||||
|
|
||||||
/* Make trivial assigments */
|
/* Make trivial assigments */
|
||||||
uint32_t next_loc = 16;
|
uint32_t next_loc = 16;
|
||||||
ctx->regs = janet_smalloc(ctx->ir->register_count * sizeof(x64Reg));
|
ctx->regs = janet_smalloc(ctx->ir->register_count * sizeof(x64Reg));
|
||||||
@ -175,7 +177,8 @@ void assign_registers(JanetSysx64Context *ctx) {
|
|||||||
uint32_t occupied = 0;
|
uint32_t occupied = 0;
|
||||||
assigned |= 1 << RSP;
|
assigned |= 1 << RSP;
|
||||||
assigned |= 1 << RBP;
|
assigned |= 1 << RBP;
|
||||||
assigned |= 1 << RAX; // return reg, div, etc.
|
assigned |= 1 << RAX; // return reg, div, temporary, etc.
|
||||||
|
assigned |= 1 << RBX; // another temp reg.
|
||||||
for (uint32_t i = 0; i < ctx->ir->register_count; i++) {
|
for (uint32_t i = 0; i < ctx->ir->register_count; i++) {
|
||||||
ctx->regs[i].kind = get_slot_regkind(ctx, i);
|
ctx->regs[i].kind = get_slot_regkind(ctx, i);
|
||||||
if (i < ctx->ir->parameter_count) {
|
if (i < ctx->ir->parameter_count) {
|
||||||
@ -263,13 +266,37 @@ static int operand_isreg(JanetSysx64Context *ctx, uint32_t o, uint32_t regindex)
|
|||||||
return reg.index == regindex;
|
return reg.index == regindex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *sysemit_sizestr(x64RegKind kind) {
|
||||||
|
switch (kind) {
|
||||||
|
case JANET_SYSREG_8:
|
||||||
|
return "byte";
|
||||||
|
case JANET_SYSREG_16:
|
||||||
|
return "word";
|
||||||
|
case JANET_SYSREG_32:
|
||||||
|
return "dword";
|
||||||
|
case JANET_SYSREG_64:
|
||||||
|
return "qword";
|
||||||
|
default:
|
||||||
|
return "qword";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *sysemit_sizestr_reg(x64Reg reg) {
|
||||||
|
return sysemit_sizestr(reg.kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *sysemit_sizestr_slot(JanetSysx64Context *ctx, uint32_t slot) {
|
||||||
|
return sysemit_sizestr(get_slot_regkind(ctx, slot));
|
||||||
|
}
|
||||||
|
|
||||||
static void sysemit_reg(JanetSysx64Context *ctx, x64Reg reg, const char *after) {
|
static void sysemit_reg(JanetSysx64Context *ctx, x64Reg reg, const char *after) {
|
||||||
|
const char *sizestr = sysemit_sizestr_reg(reg);
|
||||||
if (reg.storage == JANET_SYSREG_STACK) {
|
if (reg.storage == JANET_SYSREG_STACK) {
|
||||||
// TODO - use LEA for parameters larger than a qword
|
// TODO - use LEA for parameters larger than a qword
|
||||||
janet_formatb(ctx->buffer, "[rbp-%u]", reg.index);
|
janet_formatb(ctx->buffer, "%s [rbp-%u]", sizestr, reg.index);
|
||||||
} else if (reg.storage == JANET_SYSREG_STACK_PARAMETER) {
|
} else if (reg.storage == JANET_SYSREG_STACK_PARAMETER) {
|
||||||
// TODO - use LEA for parameters larger than a qword
|
// TODO - use LEA for parameters larger than a qword
|
||||||
janet_formatb(ctx->buffer, "[rbp+%u]", reg.index);
|
janet_formatb(ctx->buffer, "%s [rbp+%u]", sizestr, reg.index);
|
||||||
} else if (reg.kind == JANET_SYSREG_64) {
|
} else if (reg.kind == JANET_SYSREG_64) {
|
||||||
janet_formatb(ctx->buffer, "%s", register_names[reg.index]);
|
janet_formatb(ctx->buffer, "%s", register_names[reg.index]);
|
||||||
} else if (reg.kind == JANET_SYSREG_32) {
|
} else if (reg.kind == JANET_SYSREG_32) {
|
||||||
@ -310,6 +337,7 @@ static void sysemit_binop(JanetSysx64Context *ctx, const char *op, uint32_t dest
|
|||||||
if (operand_isstack(ctx, dest) && operand_isstack(ctx, src)) {
|
if (operand_isstack(ctx, dest) && operand_isstack(ctx, src)) {
|
||||||
/* Use a temporary register for src */
|
/* Use a temporary register for src */
|
||||||
x64Reg tempreg;
|
x64Reg tempreg;
|
||||||
|
tempreg.storage = JANET_SYSREG_REGISTER;
|
||||||
tempreg.kind = get_slot_regkind(ctx, dest);
|
tempreg.kind = get_slot_regkind(ctx, dest);
|
||||||
tempreg.index = RAX;
|
tempreg.index = RAX;
|
||||||
janet_formatb(ctx->buffer, "mov ");
|
janet_formatb(ctx->buffer, "mov ");
|
||||||
@ -325,6 +353,145 @@ static void sysemit_binop(JanetSysx64Context *ctx, const char *op, uint32_t dest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* dest = src[0] */
|
||||||
|
static void sysemit_load(JanetSysx64Context *ctx, uint32_t dest, uint32_t src) {
|
||||||
|
/* This seems verbose... */
|
||||||
|
int src_is_stack = operand_isstack(ctx, src);
|
||||||
|
int dest_is_stack = operand_isstack(ctx, dest);
|
||||||
|
if (!src_is_stack && !dest_is_stack) {
|
||||||
|
/* Simplest case */
|
||||||
|
janet_formatb(ctx->buffer, "mov ");
|
||||||
|
sysemit_operand(ctx, dest, ", [");
|
||||||
|
sysemit_operand(ctx, src, "]\n");
|
||||||
|
} else if (src_is_stack && dest_is_stack) {
|
||||||
|
/* Most complicated case. */
|
||||||
|
/* RAX = src */
|
||||||
|
/* RAX = RAX[0] */
|
||||||
|
/* dest = RAX */
|
||||||
|
/* Copy src to temp reg first */
|
||||||
|
x64Reg tempreg;
|
||||||
|
tempreg.storage = JANET_SYSREG_REGISTER;
|
||||||
|
tempreg.kind = get_slot_regkind(ctx, src);
|
||||||
|
tempreg.index = RAX;
|
||||||
|
janet_formatb(ctx->buffer, "mov ");
|
||||||
|
sysemit_reg(ctx, tempreg, ", ");
|
||||||
|
sysemit_operand(ctx, src, "\n");
|
||||||
|
/* Now to load to second tempreg */
|
||||||
|
x64Reg tempreg2;
|
||||||
|
tempreg.storage = JANET_SYSREG_REGISTER;
|
||||||
|
tempreg2.kind = get_slot_regkind(ctx, dest);
|
||||||
|
tempreg2.index = RAX; /* We can reuse RAX */
|
||||||
|
janet_formatb(ctx->buffer, "mov ");
|
||||||
|
sysemit_reg(ctx, tempreg2, ", [");
|
||||||
|
sysemit_reg(ctx, tempreg, "]\n");
|
||||||
|
/* Finally, move tempreg2 to dest */
|
||||||
|
/* Now move tempreg to dest */
|
||||||
|
janet_formatb(ctx->buffer, "mov ");
|
||||||
|
sysemit_operand(ctx, dest, ", ");
|
||||||
|
sysemit_reg(ctx, tempreg2, "\n");
|
||||||
|
} else if (src_is_stack) {
|
||||||
|
/* RAX = src */
|
||||||
|
/* dest = RAX[0] */
|
||||||
|
/* Copy src to temp reg first */
|
||||||
|
x64Reg tempreg;
|
||||||
|
tempreg.storage = JANET_SYSREG_REGISTER;
|
||||||
|
tempreg.kind = get_slot_regkind(ctx, src);
|
||||||
|
tempreg.index = RAX;
|
||||||
|
janet_formatb(ctx->buffer, "mov ");
|
||||||
|
sysemit_reg(ctx, tempreg, ", ");
|
||||||
|
sysemit_operand(ctx, src, "\n");
|
||||||
|
/* Now do load to dest */
|
||||||
|
janet_formatb(ctx->buffer, "mov ");
|
||||||
|
sysemit_operand(ctx, dest, ", [");
|
||||||
|
sysemit_reg(ctx, tempreg, "]\n");
|
||||||
|
} else { /* dest_is_stack */
|
||||||
|
/* RAX = src[0] */
|
||||||
|
/* dest = RAX */
|
||||||
|
/* Copy temp reg to dest after */
|
||||||
|
/* Load to tempreg first */
|
||||||
|
x64Reg tempreg;
|
||||||
|
tempreg.storage = JANET_SYSREG_REGISTER;
|
||||||
|
tempreg.kind = get_slot_regkind(ctx, src);
|
||||||
|
tempreg.index = RAX;
|
||||||
|
janet_formatb(ctx->buffer, "mov ");
|
||||||
|
sysemit_reg(ctx, tempreg, ", [");
|
||||||
|
sysemit_operand(ctx, src, "]\n");
|
||||||
|
/* Now move tempreg to dest */
|
||||||
|
janet_formatb(ctx->buffer, "mov ");
|
||||||
|
sysemit_operand(ctx, dest, ", ");
|
||||||
|
sysemit_reg(ctx, tempreg, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dest[0] = src */
|
||||||
|
static void sysemit_store(JanetSysx64Context *ctx, uint32_t dest, uint32_t src) {
|
||||||
|
/* This seems verbose... */
|
||||||
|
int src_is_stack = operand_isstack(ctx, src);
|
||||||
|
int dest_is_stack = operand_isstack(ctx, dest);
|
||||||
|
const char *store_size = sysemit_sizestr_slot(ctx, src);
|
||||||
|
if (!src_is_stack && !dest_is_stack) {
|
||||||
|
/* Simplest case */
|
||||||
|
janet_formatb(ctx->buffer, "mov %s [", store_size);
|
||||||
|
sysemit_operand(ctx, dest, "], ");
|
||||||
|
sysemit_operand(ctx, src, "\n");
|
||||||
|
} else if (src_is_stack && dest_is_stack) {
|
||||||
|
/* Most complicated case. */
|
||||||
|
/* dest = RAX */
|
||||||
|
/* src = RBX */
|
||||||
|
/* RAX = RBX[0] */
|
||||||
|
/* Copy dest to temp reg first */
|
||||||
|
x64Reg tempreg;
|
||||||
|
tempreg.storage = JANET_SYSREG_REGISTER;
|
||||||
|
tempreg.kind = get_slot_regkind(ctx, dest);
|
||||||
|
tempreg.index = RAX;
|
||||||
|
janet_formatb(ctx->buffer, "mov ");
|
||||||
|
sysemit_reg(ctx, tempreg, ", ");
|
||||||
|
sysemit_operand(ctx, dest, "\n");
|
||||||
|
/* Now to load to second tempreg */
|
||||||
|
x64Reg tempreg2;
|
||||||
|
tempreg.storage = JANET_SYSREG_REGISTER;
|
||||||
|
tempreg2.kind = get_slot_regkind(ctx, dest);
|
||||||
|
tempreg2.index = RBX;
|
||||||
|
janet_formatb(ctx->buffer, "mov ");
|
||||||
|
sysemit_reg(ctx, tempreg2, ", ");
|
||||||
|
sysemit_operand(ctx, src, "\n");
|
||||||
|
/* Finally, move tempreg2 to dest */
|
||||||
|
janet_formatb(ctx->buffer, "mov %s [", store_size);
|
||||||
|
sysemit_reg(ctx, tempreg, "], ");
|
||||||
|
sysemit_reg(ctx, tempreg2, "\n");
|
||||||
|
} else if (src_is_stack) {
|
||||||
|
/* Copy src to temp reg first */
|
||||||
|
/* RAX = src */
|
||||||
|
/* dest[0] = RAX */
|
||||||
|
x64Reg tempreg;
|
||||||
|
tempreg.storage = JANET_SYSREG_REGISTER;
|
||||||
|
tempreg.kind = get_slot_regkind(ctx, src);
|
||||||
|
tempreg.index = RAX;
|
||||||
|
janet_formatb(ctx->buffer, "mov ");
|
||||||
|
sysemit_reg(ctx, tempreg, ", ");
|
||||||
|
sysemit_operand(ctx, src, "\n");
|
||||||
|
/* Now do load to dest */
|
||||||
|
janet_formatb(ctx->buffer, "mov %s [", store_size);
|
||||||
|
sysemit_operand(ctx, dest, "], ");
|
||||||
|
sysemit_reg(ctx, tempreg, "\n");
|
||||||
|
} else { /* dest_is_stack */
|
||||||
|
/* Copy temp reg to dest after */
|
||||||
|
/* RAX = dest */
|
||||||
|
/* RAX[0] = src */
|
||||||
|
/* Load to tempreg first */
|
||||||
|
x64Reg tempreg;
|
||||||
|
tempreg.storage = JANET_SYSREG_REGISTER;
|
||||||
|
tempreg.kind = get_slot_regkind(ctx, dest);
|
||||||
|
tempreg.index = RAX;
|
||||||
|
janet_formatb(ctx->buffer, "mov ");
|
||||||
|
sysemit_reg(ctx, tempreg, ", ");
|
||||||
|
sysemit_operand(ctx, dest, "\n");
|
||||||
|
janet_formatb(ctx->buffer, "mov %s [", store_size);
|
||||||
|
sysemit_reg(ctx, tempreg, "], ");
|
||||||
|
sysemit_operand(ctx, src, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void sysemit_mov(JanetSysx64Context *ctx, uint32_t dest, uint32_t src) {
|
static void sysemit_mov(JanetSysx64Context *ctx, uint32_t dest, uint32_t src) {
|
||||||
if (dest == src) return;
|
if (dest == src) return;
|
||||||
sysemit_binop(ctx, "mov", dest, src);
|
sysemit_binop(ctx, "mov", dest, src);
|
||||||
@ -458,7 +625,22 @@ static void sysemit_cast(JanetSysx64Context *ctx, JanetSysInstruction instructio
|
|||||||
*/
|
*/
|
||||||
(void) destinfo;
|
(void) destinfo;
|
||||||
(void) srcinfo;
|
(void) srcinfo;
|
||||||
janet_formatb(ctx->buffer, "; cast nyi\n");
|
x64RegKind srckind = get_slot_regkind(ctx, src);
|
||||||
|
x64RegKind destkind = get_slot_regkind(ctx, dest);
|
||||||
|
if (srckind == destkind) {
|
||||||
|
sysemit_mov(ctx, dest, src);
|
||||||
|
} else {
|
||||||
|
uint32_t regindex = RAX;
|
||||||
|
/* Check if we can optimize out temporary register */
|
||||||
|
if (src <= JANET_SYS_MAX_OPERAND) {
|
||||||
|
x64Reg reg = ctx->regs[src];
|
||||||
|
if (reg.storage == JANET_SYSREG_REGISTER) {
|
||||||
|
regindex = reg.index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sysemit_movreg(ctx, regindex, src);
|
||||||
|
sysemit_movfromreg(ctx, dest, regindex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sysemit_sysv_call(JanetSysx64Context *ctx, JanetSysInstruction instruction, uint32_t *args, uint32_t argcount) {
|
static void sysemit_sysv_call(JanetSysx64Context *ctx, JanetSysInstruction instruction, uint32_t *args, uint32_t argcount) {
|
||||||
@ -638,6 +820,12 @@ void janet_sys_ir_lower_to_x64(JanetSysIRLinkage *linkage, JanetSysTarget target
|
|||||||
default:
|
default:
|
||||||
janet_formatb(buffer, "; nyi: %s\n", janet_sysop_names[instruction.opcode]);
|
janet_formatb(buffer, "; nyi: %s\n", janet_sysop_names[instruction.opcode]);
|
||||||
break;
|
break;
|
||||||
|
case JANET_SYSOP_LOAD:
|
||||||
|
sysemit_load(&ctx, instruction.two.dest, instruction.two.src);
|
||||||
|
break;
|
||||||
|
case JANET_SYSOP_STORE:
|
||||||
|
sysemit_store(&ctx, instruction.two.dest, instruction.two.src);
|
||||||
|
break;
|
||||||
case JANET_SYSOP_TYPE_PRIMITIVE:
|
case JANET_SYSOP_TYPE_PRIMITIVE:
|
||||||
case JANET_SYSOP_TYPE_UNION:
|
case JANET_SYSOP_TYPE_UNION:
|
||||||
case JANET_SYSOP_TYPE_STRUCT:
|
case JANET_SYSOP_TYPE_STRUCT:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user