This source file includes following definitions.
- potion_x86_debug
- potion_x86_c_arg
- potion_x86_setup
- potion_x86_stack
- potion_x86_registers
- potion_x86_local
- potion_x86_upvals
- potion_x86_jmpedit
- potion_x86_move
- potion_x86_loadpn
- potion_f_values
- potion_x86_loadk
- potion_x86_self
- potion_x86_getlocal
- potion_x86_setlocal
- potion_x86_getupval
- potion_x86_setupval
- potion_x86_global
- potion_x86_newtuple
- potion_x86_settuple
- potion_x86_settable
- potion_x86_newlick
- potion_x86_getpath
- potion_x86_setpath
- potion_x86_add
- potion_x86_sub
- potion_x86_mult
- potion_x86_div
- potion_x86_rem
- potion_x86_pow
- potion_x86_neq
- potion_x86_eq
- potion_x86_lt
- potion_x86_lte
- potion_x86_gt
- potion_x86_gte
- potion_x86_bitn
- potion_x86_bitl
- potion_x86_bitr
- potion_x86_def
- potion_x86_bind
- potion_x86_message
- potion_x86_jmp
- potion_x86_test_asm
- potion_x86_test
- potion_x86_not
- potion_x86_cmp
- potion_x86_testjmp
- potion_x86_notjmp
- potion_x86_named
- potion_x86_call
- potion_x86_callset
- potion_x86_return
- potion_f_protos
- potion_x86_method
- potion_x86_class
- potion_x86_finish
- potion_x86_mcache
- potion_x86_ivars
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "p2.h"
#include "internal.h"
#include "opcodes.h"
#include "asm.h"
#include "khash.h"
#include "table.h"
#define RBP(x) (0x100 - ((x + 1) * sizeof(PN)))
#define RBPI(x) (0x100 - ((x + 1) * sizeof(int)))
#if __WORDSIZE != 64
#define X86_PRE_T 0
#define X86_PRE()
#define X86_POST()
#define X86C(op32, op64) op32
#else
#define X86_PRE_T 1
#define X86_PRE() ASM(0x48)
#define X86_POST() ASM(0x48); ASM(0x98)
#define X86C(op32, op64) op64
#endif
#define X86_MOV_RBP(reg, x) \
X86_PRE(); ASM(reg); ASM(0x45); ASM(RBP(x))
#if __WORDSIZE != 64
# define X86_MOVQ(reg, x) \
ASM(0xC7); \
ASM(0x45); ASM(RBP(reg)); \
ASMI((PN)(x))
#else
# define X86_MOVQ(reg, x) \
X86_PRE(); ASM(0xb8); ASMN((PN)(x)); \
X86_PRE(); ASM(0x89); \
ASM(0x45); ASM(RBP(reg));
#endif
#define X86_MATH(two, func, ops) ({ \
int asmpos = 0; \
X86_MOV_RBP(0x8B, op.a); \
if (two) { X86_PRE(); ASM(0x8B); ASM(0x55); ASM(RBP(op.b)); } \
ASM(0xF6); ASM(0xC0); ASM(0x01); \
asmpos = (*asmp)->len; \
ASM(0x74); ASM(0); \
if (two) { ASM(0xF6); ASM(0xC2); ASM(0x01); } \
if (two) { ASM(0x74); ASM(0); } \
ops; \
(*asmp)->ptr[asmpos + 1] = ((*asmp)->len - asmpos); \
if (two) { (*asmp)->ptr[asmpos + 6] = ((*asmp)->len - asmpos) - 5; } \
asmpos = (*asmp)->len; \
ASM(0xEB); ASM(0); \
X86_ARGO(start - 3, 0); \
X86_ARGO(op.a, 1); \
X86_ARGO(op.b, 2); \
X86_PRE(); ASM(0xB8); ASMN(func); \
ASM(0xFF); ASM(0xD0); \
(*asmp)->ptr[asmpos + 1] = ((*asmp)->len - asmpos) - 2; \
X86_MOV_RBP(0x89, op.a); \
})
#define X86_CMP(ops) \
X86_PRE(); ASM(0x8B); ASM(0x55); ASM(RBP(op.a)); \
X86_MOV_RBP(0x8B, op.b); \
X86_PRE(); ASM(0x39); ASM(0xC2); \
ASM(ops); ASM(X86C(9, 16)); \
X86_MOVQ(op.a, PN_TRUE); \
ASM(0xEB); ASM(X86C(7, 14)); \
X86_MOVQ(op.a, PN_FALSE)
#define X86_ARGO(regn, argn) potion_x86_c_arg(P, asmp, 1, regn, argn)
#define X86_ARGO_IMM(regn, argn) potion_x86_c_arg(P, asmp, 2, regn, argn)
#define X86_ARGI(regn, argn) potion_x86_c_arg(P, asmp, 0, regn, argn)
#define TAG_JMP(jpos) \
ASM(0xE9); \
if ((int)jpos >= (int)pos) { \
jmps[*jmpc].from = asmp[0]->len; \
ASMI(0); \
jmps[*jmpc].to = jpos + 1; \
*jmpc = *jmpc + 1; \
} else if ((int)jpos < (int)pos) { \
ASMI(offs[jpos + 1] - ((asmp[0]->len) + 4)); \
} else { \
ASMI(0); \
}
#define X86_DEBUG() \
X86_PRE(); ASM(0xB8); ASMN(potion_x86_debug); \
ASM(0xFF); ASM(0xD0)
void potion_x86_debug() {
Potion *P;
int n = 0;
_PN rax, *rbp, *sp;
#if POTION_X86 == POTION_JIT_TARGET
#if __WORDSIZE != 64
__asm__ ("mov %%eax, %0;"
#else
__asm__ ("mov %%rax, %0;"
#endif
:"=r"(rax)
);
printf("RAX = %lx (%u)\n", rax, potion_type(rax));
#if __WORDSIZE != 64
__asm__ ("mov %%ebp, %0;"
#else
__asm__ ("mov %%rbp, %0;"
#endif
:"=r"(sp)
);
#endif
P = (Potion *)sp[2];
printf("Potion: %p (%p)\n", P, &P);
again:
n = 0;
rbp = (unsigned long *)*sp;
if (rbp > sp - 2 && sp[2] == (PN)P) {
printf("RBP = %lx (%lx), SP = %lx\n", (PN)rbp, *rbp, (PN)sp);
while (sp < rbp) {
printf("STACK[%d] = %lx\n", n++, *sp);
sp++;
}
goto again;
}
}
static void potion_x86_c_arg(Potion *P, PNAsm * volatile *asmp, int out, int regn, int argn) {
#if __WORDSIZE != 64
if (argn == 0) {
if (!out) {
ASM(0x8b); ASM(0x55); ASM(2 * sizeof(PN));
ASM(0x89); ASM(0x14); ASM(0x24);
}
}
else {
if (out == 2) {
ASM(0xc7); ASM(0x44); ASM(0x24); ASM(argn * sizeof(PN)); ASMI(regn);
} else if (out) {
ASM(0x8b); ASM(0x55); ASM(RBP(regn));
}
if (!out) argn += 2;
if (out == 1) {
ASM(0x89); ASM(0x54); ASM(0x24); ASM(argn * sizeof(PN));
} else if (!out) {
ASM(0x8b); ASM(0x55); ASM(argn * sizeof(PN));
}
if (!out) {
ASM(0x89); ASM(0x55); ASM(RBP(regn));
}
}
#else
switch (argn) {
case 0:
if (out == 2) {
X86_PRE(); ASM(0xc7); ASM(0xc7); ASMI(regn);
} else {
X86_PRE(); ASM(out ? 0x8b : 0x89); ASM(0x7d); ASM(RBP(regn));
}
break;
case 1:
if (out == 2) {
X86_PRE(); ASM(0xc7); ASM(0xc6); ASMI(regn);
} else {
X86_PRE(); ASM(out ? 0x8b : 0x89); ASM(0x75); ASM(RBP(regn));
}
break;
case 2:
if (out == 2) {
X86_PRE(); ASM(0xc7); ASM(0xc2); ASMI(regn);
} else {
X86_PRE(); ASM(out ? 0x8b : 0x89); ASM(0x55); ASM(RBP(regn));
}
break;
case 3:
if (out == 2) {
X86_PRE(); ASM(0xc7); ASM(0xc1); ASMI(regn);
} else {
X86_PRE(); ASM(out ? 0x8b : 0x89); ASM(0x4d); ASM(RBP(regn));
}
break;
case 4:
if (out == 2) {
ASM(0x49); ASM(0xc7); ASM(0xc0); ASMI(regn);
} else {
ASM(0x4c); ASM(out ? 0x8b : 0x89); ASM(0x45); ASM(RBP(regn));
}
break;
case 5:
if (out == 2) {
ASM(0x49); ASM(0xc7); ASM(0xc1); ASMI(regn);
} else {
ASM(0x4c); ASM(out ? 0x8b : 0x89); ASM(0x4d); ASM(RBP(regn));
}
break;
default:
if (out) {
X86_PRE(); ASM(0x8B); ASM(0x5d); ASM(RBP(regn));
if (argn == 6) {
X86_PRE(); ASM(0x89); ASM(0x1c); ASM(0x24);
} else {
X86_PRE(); ASM(0x89); ASM(0x5c); ASM(0x24); ASM((argn - 6) * sizeof(PN));
}
} else {
X86_PRE(); ASM(0x8b); ASM(0x5d); ASM((argn - 4) * sizeof(PN));
X86_PRE(); ASM(0x89); ASM(0x5d); ASM(RBP(regn));
}
break;
}
#endif
}
void potion_x86_setup(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp) {
ASM(0x55);
X86_PRE(); ASM(0x89); ASM(0xE5);
}
void potion_x86_stack(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, long need) {
int rsp = X86C(16,0)+((need-X86C(8,0)+15)&~(15));
if (rsp >= 0x80) {
X86_PRE(); ASM(0x81); ASM(0xEC); ASMI(rsp);
} else {
X86_PRE(); ASM(0x83); ASM(0xEC); ASM(rsp);
}
}
void potion_x86_registers(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, long start) {
PN_HAS_UPVALS(up);
X86_ARGI(start - 3, 0);
X86_ARGI(start - 2, 1);
X86_ARGI(start - 1, 2);
X86_ARGI(0, 2);
if (up) {
int argx = 0, regs = PN_INT(f->stack);
for (argx = 0; argx < PN_TUPLE_LEN(f->locals); argx++) {
X86_MOVQ(regs + argx, PN_NIL);
}
}
}
void potion_x86_local(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, long reg, long arg) {
X86_ARGI(reg, 3 + arg);
}
void potion_x86_upvals(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, long lregs, long start, int upc) {
int upi;
for (upi = 0; upi < upc; upi++) {
X86_MOV_RBP(0x8B, start - 2);
X86_PRE(); ASM(0x8B); ASM(0x40);
ASM(sizeof(struct PNClosure) + ((upi + 1) * sizeof(PN)));
X86_MOV_RBP(0x89, lregs + upi);
}
}
void potion_x86_jmpedit(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, unsigned char *asmj, int dist) {
*((int *)asmj) = dist;
}
void potion_x86_move(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_MOV_RBP(0x8B, op.b);
X86_MOV_RBP(0x89, op.a);
}
void potion_x86_loadpn(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_MOVQ(op.a, op.b);
}
PN potion_f_values(Potion *P, PN cl) {
return potion_fwd(PN_PROTO(PN_CLOSURE(cl)->data[0])->values);
}
void potion_x86_loadk(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_ARGO(start - 3, 0);
X86_ARGO(start - 2, 1);
X86_PRE(); ASM(0xB8); ASMN(potion_f_values);
ASM(0xFF); ASM(0xD0);
X86_PRE(); ASM(0x05); ASMI(sizeof(struct PNTuple)
+ (op.b * sizeof(PN)));
X86_PRE(); ASM(0x8B); ASM(0);
X86_MOV_RBP(0x89, op.a);
}
void potion_x86_self(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_MOV_RBP(0x8B, start - 1);
X86_MOV_RBP(0x89, op.a);
}
void potion_x86_getlocal(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long regs) {
PN_OP op = PN_OP_AT(f->asmb, pos);
PN_HAS_UPVALS(up);
X86_MOV_RBP(0x8B, regs + op.b);
if (up) {
ASM(0xF6); ASM(0xC0); ASM(0x01);
ASM(0x75); ASM(X86C(19, 20));
ASM(0xF7); ASM(0xC0); ASMI(PN_REF_MASK);
ASM(0x74); ASM(X86C(11, 12));
ASM(0x81); ASM(0x38); ASMI(PN_TWEAK);
ASM(0x75); ASM(X86C(3, 4));
X86_PRE(); ASM(0x8B); ASM(0x40);
ASM(sizeof(struct PNObject));
}
X86_MOV_RBP(0x89, op.a);
}
void potion_x86_setlocal(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long regs) {
PN_OP op = PN_OP_AT(f->asmb, pos);
PN_HAS_UPVALS(up);
X86_PRE(); ASM(0x8B); ASM(0x55); ASM(RBP(op.a));
if (up) {
X86_MOV_RBP(0x8B, regs + op.b);
ASM(0xF6); ASM(0xC0); ASM(0x01);
ASM(0x75); ASM(X86C(19, 20));
ASM(0xF7); ASM(0xC0); ASMI(PN_REF_MASK);
ASM(0x74); ASM(X86C(11, 12));
ASM(0x81); ASM(0x38); ASMI(PN_TWEAK);
ASM(0x75); ASM(X86C(3, 4));
X86_PRE(); ASM(0x89); ASM(0x50);
ASM(sizeof(struct PNObject));
}
X86_PRE(); ASM(0x89); ASM(0x55); ASM(RBP(regs + op.b));
}
void potion_x86_getupval(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long lregs) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_MOV_RBP(0x8B, lregs + op.b);
X86_PRE(); ASM(0x8B); ASM(0x40); ASM(sizeof(struct PNObject));
X86_MOV_RBP(0x89, op.a);
}
void potion_x86_setupval(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long lregs) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_PRE(); ASM(0x8B); ASM(0x55); ASM(RBP(op.a));
X86_MOV_RBP(0x8B, lregs + op.b);
X86_PRE(); ASM(0x89); ASM(0x50); ASM(sizeof(struct PNObject));
}
void potion_x86_global(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_ARGO(start - 3, 0);
X86_ARGO(op.a, 1);
X86_ARGO(op.b, 2);
X86_PRE(); ASM(0xB8); ASMN(potion_define_global);
ASM(0xFF); ASM(0xD0);
X86_MOV_RBP(0x8B, op.b);
X86_PRE(); ASM(0x89); ASM(0x45); ASM(RBP(op.a));
}
void potion_x86_newtuple(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_ARGO(start - 3, 0);
X86_PRE(); ASM(0xB8); ASMN(potion_tuple_empty);
ASM(0xFF); ASM(0xD0);
X86_MOV_RBP(0x89, op.a);
}
void potion_x86_settuple(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_ARGO(start - 3, 0);
X86_ARGO(op.a, 1);
X86_ARGO(op.b, 2);
X86_PRE(); ASM(0xB8); ASMN(potion_tuple_push);
ASM(0xFF); ASM(0xD0);
X86_MOV_RBP(0x89, op.a);
}
void potion_x86_settable(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_ARGO(start - 3, 0);
X86_ARGO(op.a, 1);
X86_ARGO(op.a + 1, 2);
X86_ARGO(op.b, 3);
X86_PRE(); ASM(0xB8); ASMN(potion_table_set);
ASM(0xFF); ASM(0xD0);
X86_MOV_RBP(0x89, op.a);
}
void potion_x86_newlick(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
int nnil = 0;
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_ARGO(start - 3, 0);
X86_ARGO(op.a, 1);
if (op.b > op.a) {
X86_ARGO(op.a + 1, 2);
} else {
nnil = 1;
X86_MOVQ(op.a, PN_NIL);
X86_ARGO(op.a, 2);
}
if (op.b > op.a + 1) {
X86_ARGO(op.b, 3);
} else {
if (!nnil) { X86_MOVQ(op.a, PN_NIL); }
X86_ARGO(op.a, 3);
}
X86_PRE(); ASM(0xB8); ASMN(potion_lick);
ASM(0xFF); ASM(0xD0);
X86_MOV_RBP(0x89, op.a);
}
void potion_x86_getpath(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_ARGO(start - 3, 0);
X86_ARGO(op.a, 2);
X86_ARGO(op.b, 3);
X86_PRE(); ASM(0xB8); ASMN(potion_obj_get);
ASM(0xFF); ASM(0xD0);
X86_MOV_RBP(0x89, op.a);
}
void potion_x86_setpath(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_ARGO(start - 3, 0);
X86_ARGO(op.a, 2);
X86_ARGO(op.a + 1, 3);
X86_ARGO(op.b, 4);
X86_PRE(); ASM(0xB8); ASMN(potion_obj_set);
ASM(0xFF); ASM(0xD0);
}
void potion_x86_add(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_MATH(1, potion_obj_add, {
X86_PRE(); ASM(0x8D); ASM(0x44); ASM(0x10); ASM(0xFF);
});
}
void potion_x86_sub(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_MATH(1, potion_obj_sub, {
X86_PRE(); ASM(0x29); ASM(0xD0);
X86_PRE(); ASM(0xFF); ASM(0xC0);
});
}
void potion_x86_mult(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_MATH(1, potion_obj_mult, {
X86_PRE(); ASM(0xD1); ASM(0xFA);
X86_PRE(); ASM(0xFF); ASM(0xC8);
X86_PRE(); ASM(0x0F); ASM(0xAF); ASM(0xC2);
X86_PRE(); ASM(0xFF); ASM(0xC0);
});
}
void potion_x86_div(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_MATH(1, potion_obj_div, {
ASM(0xD1); ASM(0xF8);
ASM(0xD1); ASM(0xFA);
ASM(0x89); ASM(0xD1);
ASM(0x89); ASM(0xC2);
ASM(0xC1); ASM(0xFA); ASM(0x1F);
ASM(0xF7); ASM(0xF9);
ASM(0x8D); ASM(0x44); ASM(0x00); ASM(0x01);
});
}
void potion_x86_rem(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_MATH(1, potion_obj_rem, {
ASM(0xD1); ASM(0xF8);
ASM(0xD1); ASM(0xFA);
ASM(0x89); ASM(0xD1);
ASM(0x89); ASM(0xC2);
ASM(0xC1); ASM(0xFA); ASM(0x1F);
ASM(0xF7); ASM(0xF9);
ASM(0x8D); ASM(0x44); ASM(0x12); ASM(0x01);
});
}
void potion_x86_pow(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_ARGO(start - 3, 0);
X86_ARGO(op.a, 2);
X86_ARGO(op.b, 3);
X86_PRE(); ASM(0xB8); ASMN(potion_pow);
ASM(0xFF); ASM(0xD0);
X86_MOV_RBP(0x89, op.a);
}
void potion_x86_neq(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_CMP(0x74);
}
void potion_x86_eq(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_CMP(0x75);
}
void potion_x86_lt(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_CMP(0x7D);
}
void potion_x86_lte(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_CMP(0x7F);
}
void potion_x86_gt(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_CMP(0x7E);
}
void potion_x86_gte(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_CMP(0x7C);
}
void potion_x86_bitn(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_MATH(0, potion_obj_bitn, {
X86_PRE(); ASM(0xF7); ASM(0xD0);
X86_PRE(); ASM(0xFF); ASM(0xC0);
});
}
void potion_x86_bitl(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_MATH(1, potion_obj_bitl, {
ASM(0xD1); ASM(0xF8);
ASM(0xD1); ASM(0xFA);
ASM(0x89); ASM(0xD1);
ASM(0x89); ASM(0xC2);
ASM(0xD3); ASM(0xE0);
ASM(0x8D); ASM(0x44); ASM(0x00); ASM(0x01);
});
}
void potion_x86_bitr(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_MATH(1, potion_obj_bitr, {
ASM(0xD1); ASM(0xF8);
ASM(0xD1); ASM(0xFA);
ASM(0x89); ASM(0xD1);
ASM(0x89); ASM(0xC2);
ASM(0xD3); ASM(0xF8);
ASM(0x8D); ASM(0x44); ASM(0x00); ASM(0x01);
});
}
void potion_x86_def(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_ARGO(start - 3, 0);
X86_ARGO(op.a, 2);
X86_ARGO(op.a + 1, 3);
X86_ARGO(op.b, 4);
X86_PRE(); ASM(0xB8); ASMN(potion_def_method);
ASM(0xFF); ASM(0xD0);
X86_MOV_RBP(0x89, op.a);
}
void potion_x86_bind(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_ARGO(start - 3, 0);
X86_ARGO(op.b, 1);
X86_ARGO(op.a, 2);
X86_PRE(); ASM(0xB8); ASMN(potion_bind);
ASM(0xFF); ASM(0xD0);
X86_MOV_RBP(0x89, op.a);
}
void potion_x86_message(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_ARGO(start - 3, 0);
X86_ARGO(op.b, 1);
X86_ARGO(op.a, 2);
X86_PRE(); ASM(0xB8); ASMN(potion_message);
ASM(0xFF); ASM(0xD0);
X86_MOV_RBP(0x89, op.a);
}
void potion_x86_jmp(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, PNJumps *jmps, size_t *offs, int *jmpc) {
PN_OP op = PN_OP_AT(f->asmb, pos);
TAG_JMP(pos + op.a);
}
void potion_x86_test_asm(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, int test) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_MOV_RBP(0x8B, op.a);
#ifdef P2
X86_PRE(); ASM(0x83); ASM(0xF8); ASM(PN_FALSE);
ASM(0x74); ASM(X86C(23, 33));
X86_PRE(); ASM(0x83); ASM(0xF8); ASM(PN_ZERO);
ASM(0x74); ASM(X86C(18, 27));
X86_PRE(); ASM(0x83); ASM(0xF8); ASM(PN_STR0);
ASM(0x74); ASM(X86C(13, 21));
#else
X86_PRE(); ASM(0x83); ASM(0xF8); ASM(PN_FALSE);
ASM(0x74); ASM(X86C(13, 21));
#endif
X86_PRE(); ASM(0x85); ASM(0xC0);
ASM(0x74); ASM(X86C(9, 16));
X86_MOVQ(op.a, test ? PN_FALSE : PN_TRUE);
ASM(0xEB); ASM(X86C(7, 14));
X86_MOVQ(op.a, test ? PN_TRUE : PN_FALSE);
}
void potion_x86_test(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos) {
potion_x86_test_asm(P, f, asmp, pos, 0);
}
void potion_x86_not(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos) {
potion_x86_test_asm(P, f, asmp, pos, 1);
}
void potion_x86_cmp(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos) {
potion_x86_test_asm(P, f, asmp, pos, 0);
}
void potion_x86_testjmp(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, PNJumps *jmps, size_t *offs, int *jmpc) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_MOV_RBP(0x8B, op.a);
#ifdef P2
X86_PRE(); ASM(0x83); ASM(0xF8); ASM(PN_ZERO);
#else
X86_PRE(); ASM(0x83); ASM(0xF8); ASM(PN_FALSE);
#endif
ASM(0x74); ASM(X86C(9, 10));
X86_PRE(); ASM(0x85); ASM(0xC0);
ASM(0x74); ASM(5);
TAG_JMP(pos + op.b);
}
void potion_x86_notjmp(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, PNJumps *jmps, size_t *offs, int *jmpc) {
PN_OP op = PN_OP_AT(f->asmb, pos);
DBG_t("; notjmp %d => %d\n", op.a, op.b);
X86_MOV_RBP(0x8B, op.a);
#ifdef P2
X86_PRE(); ASM(0x83); ASM(0xF8); ASM(PN_ZERO);
#else
X86_PRE(); ASM(0x83); ASM(0xF8); ASM(PN_FALSE);
#endif
ASM(0x74); ASM(X86C(4, 5));
X86_PRE(); ASM(0x85); ASM(0xC0);
ASM(0x75); ASM(5);
TAG_JMP(pos + op.b);
}
void potion_x86_named(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
DBG_t("; named %d %d\n", op.a, op.b);
X86_ARGO(start - 3, 0);
X86_ARGO(op.a, 1);
X86_ARGO(op.b - 1, 2);
X86_PRE(); ASM(0xB8); ASMN(potion_sig_find);
ASM(0xFF); ASM(0xD0);
ASM(0x85); ASM(0xC0);
ASM(0x78); ASM(X86C(9, 12));
X86_PRE(); ASM(0xF7); ASM(0xD8);
X86_PRE(); ASM(0x8B); ASM(0x55); ASM(RBP(op.b));
#if __WORDSIZE != 64
ASM(0x89); ASM(0x54); ASM(0x85); ASM(RBP(op.a + 2));
#else
X86_PRE(); ASM(0x89); ASM(0x54); ASM(0xC5); ASM(RBP(op.a + 2));
#endif
}
void potion_x86_call(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
int argc = op.b - op.a;
int i;
X86_PRE(); ASM(0x8B); ASM(0x45); ASM(RBP(op.a));
ASM(0xF6); ASM(0xC0); ASM(0x01);
ASM(0x75); ASM(X86C(56, 68));
ASM(0xF7); ASM(0xC0); ASMI(PN_REF_MASK);
ASM(0x74); ASM(X86C(48, 60));
X86_PRE(); ASM(0x83); ASM(0xE0); ASM(0xF8);
ASM(0x81); ASM(0x38); ASMI(PN_TVTABLE);
ASM(0x75); ASM(X86C(26, 36));
X86_ARGO(start - 3, 0);
X86_ARGO(op.a, 2);
X86_PRE(); ASM(0xB8); ASMN(potion_object_new);
ASM(0xFF); ASM(0xD0);
X86_MOV_RBP(0x89, op.a + 1);
X86_PRE(); ASM(0x8B); ASM(0x45); ASM(RBP(op.a));
X86_PRE(); ASM(0x8B); ASM(0x40);
ASM((char *)&((struct PNVtable *)P->lobby)->ctor
- (char *)P->lobby);
X86_PRE(); ASM(0x89); ASM(0x45); ASM(RBP(op.a));
ASM(0x81); ASM(0x38); ASMI(PN_TCLOSURE);
ASM(0x74); ASM(X86C(22, 30));
X86_MOV_RBP(0x8B, op.a);
X86_MOV_RBP(0x89, op.a + 1);
X86_ARGO(start - 3, 0);
X86_ARGO(op.a, 1);
X86_PRE(); ASM(0xB8); ASMN(potion_obj_get_call);
ASM(0xFF); ASM(0xD0);
ASM(0xEB); ASM(X86C(3, 4));
X86_PRE(); ASM(0x8B); ASM(0x45); ASM(RBP(op.a));
X86_PRE(); ASM(0x8B); ASM(0x40);
ASM(sizeof(struct PNObject));
X86_ARGO(start - 3, 0);
X86_ARGO(op.a, 1);
DBG_t("; call %ld[0] %d[1] ", start-3, op.a);
for (i=2; i <= argc+1; i++) {
DBG_t("%d[%d] ", op.a + i - 1, i);
X86_ARGO(op.a + i - 1, i);
}
if (!PN_IS_EMPTY(f->protos)) {
vPN(Proto) c = (vPN(Proto)) PN_TUPLE_AT(f->protos, 0);
int arity = c->arity;
if (arity && (argc-1 < arity)) {
for (i = argc+1; i <= arity+1; i++) {
PN sig = potion_sig_at(P, c->sig, i-2);
if (sig && PN_TUPLE_LEN(sig) == 3) {
DBG_t(":=*%s[%d] ", AS_STR(PN_TUPLE_AT(sig, 2)), i+1);
X86_ARGO_IMM(PN_TUPLE_AT(sig, 2), i+1);
} else if (sig) {
DBG_t("|0 ");
char type = (char)(PN_TUPLE_LEN(sig) > 1
? PN_INT(PN_TUPLE_AT(sig,1)) : 0);
X86_ARGO_IMM(type ? potion_type_default(type) : 0, i+1);
}}}}
DBG_t("\n");
ASM(0xFF); ASM(0xD0);
X86_PRE(); ASM(0x89); ASM(0x45); ASM(RBP(op.a));
}
void potion_x86_callset(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_ARGO(start - 3, 0);
X86_ARGO(op.b, 1);
X86_PRE(); ASM(0xB8); ASMN(potion_obj_get_callset);
ASM(0xFF); ASM(0xD0);
X86_MOV_RBP(0x89, op.a);
}
void potion_x86_return(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos) {
X86_MOV_RBP(0x8B, 0);
ASM(0xC9); ASM(0xC3);
}
PN potion_f_protos(Potion *P, PN cl, PN i) {
PN p = PN_PROTO(PN_CLOSURE(cl)->data[0])->protos;
PN proto = PN_TUPLE_AT(p, i);
vPN(Closure) c = (struct PNClosure *)potion_closure_new(P, NULL,
PN_PROTO(proto)->sig, PN_TUPLE_LEN(PN_PROTO(proto)->upvals) + 1);
c->method = PN_PROTO(proto)->jit;
c->data[0] = proto;
return (PN)c;
}
void potion_x86_method(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE *pos, long lregs, long start, long regs) {
PN_OP op = PN_OP_AT(f->asmb, *pos);
PN proto = PN_TUPLE_AT(f->protos, op.b);
X86_ARGO(start - 3, 0);
X86_ARGO(start - 2, 1);
X86_MOVQ(op.a, op.b);
X86_ARGO(op.a, 2);
X86_PRE(); ASM(0xB8); ASMN(potion_f_protos);
ASM(0xFF); ASM(0xD0);
X86_MOV_RBP(0x89, op.a);
X86_MOVQ(start - 3, P);
PN_TUPLE_COUNT(PN_PROTO(proto)->upvals, i, {
(*pos)++;
PN_OP opp = PN_OP_AT(f->asmb, *pos);
if (opp.code == OP_GETUPVAL) {
X86_PRE(); ASM(0x8B); ASM(0x55); ASM(RBP(lregs + opp.b));
} else if (opp.code == OP_GETLOCAL) {
X86_ARGO(start - 3, 0);
X86_ARGO(regs + opp.b, 1);
X86_PRE(); ASM(0xB8); ASMN(potion_ref);
ASM(0xFF); ASM(0xD0);
X86_PRE(); ASM(0x89); ASM(0xC2);
X86_MOV_RBP(0x89, regs + opp.b);
} else {
fprintf(stderr, "** missing an upval to proto %p\n", (void *)proto);
}
X86_MOV_RBP(0x8B, opp.a);
X86_PRE(); ASM(0x89); ASM(0x50);
ASM(sizeof(struct PNClosure) + (sizeof(PN) * (i + 1)));
});
}
void potion_x86_class(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos, long start) {
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_ARGO(start - 3, 0);
X86_ARGO(op.b, 1);
X86_ARGO(op.a, 2);
X86_PRE(); ASM(0xB8); ASMN(potion_vm_class);
ASM(0xFF); ASM(0xD0);
X86_MOV_RBP(0x89, op.a);
}
void potion_x86_finish(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp) {
}
void potion_x86_mcache(Potion *P, vPN(Vtable) vt, PNAsm * volatile *asmp) {
unsigned k;
#if __WORDSIZE != 64
ASM(0x55);
ASM(0x89); ASM(0xE5);
ASM(0x8B); ASM(0x55); ASM(0x08);
#endif
for (k = kh_end(vt->methods); k > kh_begin(vt->methods); k--) {
if (kh_exist(PN, vt->methods, k - 1)) {
ASM(0x81); ASM(X86C(0xFA, 0xFF));
ASMI(PN_UNIQ(kh_key(PN, vt->methods, k - 1)));
ASM(0x75); ASM(X86C(7, 11));
X86_PRE(); ASM(0xB8); ASMN(kh_val(PN, vt->methods, k - 1));
#if __WORDSIZE != 64
ASM(0x5D);
#endif
ASM(0xC3);
}
}
ASM(0xB8); ASMI(0);
#if __WORDSIZE != 64
ASM(0x5D);
#endif
ASM(0xC3);
}
void potion_x86_ivars(Potion *P, PN ivars, PNAsm * volatile *asmp) {
#if __WORDSIZE != 64
ASM(0x55);
ASM(0x89); ASM(0xE5);
ASM(0x8B); ASM(0x55); ASM(0x08);
#else
#endif
#if __WORDSIZE != 64
PN_TUPLE_EACH(ivars, i, v, {
ASM(0x81); ASM(X86C(0xFA, 0xFF));
ASMI(PN_UNIQ(v));
ASM(0x75); ASM(X86C(7, 6));
ASM(0xB8); ASMI(i);
ASM(0x5D);
ASM(0xC3);
});
#else
PN_TUPLE_EACH(ivars, i, v, {
ASM(0x81); ASM(X86C(0xFA, 0xFF));
ASMI(PN_UNIQ(v));
ASM(0x75); ASM(X86C(7, 6));
ASM(0xB8); ASMI(i);
ASM(0xC3);
});
#endif
X86_PRE(); ASM(0xB8); ASMN(-1);
#if __WORDSIZE != 64
ASM(0x5D);
#endif
ASM(0xC3);
}
MAKE_TARGET(x86);