This source file includes following definitions.
- x86_cmp
- 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_gettuple
- potion_x86_settuple
- potion_x86_gettable
- 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_tailcall
- 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 "potion.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 RBPN(x) (- (int)((x + 1) * sizeof(PN)))
#define RBPI(x) (0x100 - ((x + 1) * sizeof(int)))
#if PN_SIZE_T != 8
#define X86_PRE_T 0
#define X86_PRE()
#define X86_POST()
#define X86C(op32, op64, n, reg) op32+((reg)>15?(n)*3:0)
#ifdef DEBUG
# define ASM_MOV_EBP(op, reg) \
if (reg > 31) { \
DBG_v("; reg %d > 31, op 0x%x\n", (int)reg, op); \
ASM((op)+0x40); ASMI(RBPN(reg)); } \
else { ASM(op); ASM(RBP(reg)); }
#else
# define ASM_MOV_EBP(op, reg) \
if (reg > 31) { ASM((op)+0x40); ASMI(RBPN(reg)); } \
else { ASM(op); ASM(RBP(reg)); }
#endif
#else
#define X86_PRE_T 1
#define X86_PRE() ASM(0x48)
#define X86_POST() ASM(0x48); ASM(0x98)
#define X86C(op32, op64, n, reg) op64+((reg)>31?(n)*3:0)
# ifdef DEBUG
# define ASM_MOV_EBP(op, reg) \
if (reg > 15) { \
DBG_v("; reg %d > 15, op 0x%x\n", (int)reg, op); \
ASM((op)+0x40); ASMI(RBPN(reg)); } \
else { ASM(op); ASM(RBP(reg)); }
# else
# define ASM_MOV_EBP(op, reg) \
if (reg > 15) { ASM((op)+0x40); ASMI(RBPN(reg)); } \
else { ASM(op); ASM(RBP(reg)); }
# endif
#endif
#define X86_MOV_RBP(reg, x) X86_PRE(); ASM(reg); ASM_MOV_EBP(0x45,x)
#if PN_SIZE_T != 8
# define X86_MOVQ(reg, x) \
ASM(0xC7); ASM_MOV_EBP(0x45,reg) \
ASMI((PN)(x))
#else
# define X86_MOVQ(reg, x) \
X86_PRE(); ASM(0xb8); ASMN((PN)(x)); \
X86_PRE(); ASM(0x89); ASM_MOV_EBP(0x45,reg)
#endif
#define TAG_PREP(tag) tag = (*asmp)->len + 1
#define TAG_LABEL(tag) (*asmp)->ptr[tag] = ((*asmp)->len - tag - 1)
#define TAG_JMPTO(tag) TAG_LABEL(tag)
#define TAG_JMPF(insn, tag) \
TAG_PREP(tag); \
ASM(insn); \
ASM(0); \
#if PN_SIZE_T == 8
#define TAG_JMPFW(insn, tag) \
ASM(0x0f); ASM(insn); \
TAG_PREP4(tag); ASMI(0);
#define TAG_JMPTOW(tag) TAG_LABEL4(tag)
#else
#define TAG_JMPFW(insn, tag) TAG_JMPF(insn, tag)
#define TAG_JMPTOW(tag) TAG_LABEL(tag)
#endif
#define TAG_JMPB(insn, tag) \
if (tag > (*asmp)->len) { \
potion_fatal("jmp fw"); \
} else if ((*asmp)->len - tag > 127) { \
ASM(0x0f); \
ASM(insn + 0x10); \
ASMI(tag - (*asmp)->len - 2); \
} else { \
ASM(insn); \
ASM(tag - (*asmp)->len - 2); \
}
#define TAG_JMPTOB(tag) tag = (*asmp)->len
#define TAG_PREP4(tag) tag = (*asmp)->len
#define TAG_LABEL4(tag) ({ int* ptr = (int*)((*asmp)->ptr + tag); \
*ptr = (*asmp)->len - tag - 4; })
#define X86_MATH(two, dbl_func, ops) ({ \
int dbl_a, dbl_a1, end_b; \
X86_MOV_RBP(0x8B, op.a); \
if (two) { X86_PRE(); ASM(0x8B); ASM_MOV_EBP(0x55,op.b) } \
ASM(0xF6); ASM(0xC0); ASM(0x01); \
TAG_PREP(dbl_a); ASM(0x74); ASM(0); \
if (two) { ASM(0xF6); ASM(0xC2); ASM(0x01); } \
if (two) { TAG_PREP(dbl_a1); ASM(0x74); ASM(0); } \
ops; \
TAG_PREP(end_b); ASM(0xEB); ASM(0); \
TAG_LABEL(dbl_a); if (two) { TAG_LABEL(dbl_a1); } \
X86_ARGO(start - 3, 0); \
X86_ARGO(op.a, 1); \
X86_ARGO(op.b, 2); \
X86_PRE(); ASM(0xB8); ASMN(dbl_func); \
ASM(0xFF); ASM(0xD0); \
TAG_LABEL(end_b); \
X86_MOV_RBP(0x89, op.a) \
})
#define X86_NUMCMP(iop, xop, xmms) \
int dbl_a, dbl_b, cmp_dbl, true_1, true_2, false_; \
X86_PRE(); ASM(0x8B); ASM_MOV_EBP(0x55,op.a) \
X86_MOV_RBP(0x8B, op.b); \
ASMS("\xA8\x01"); \
TAG_PREP(dbl_b); ASM(0x74);ASM(0); \
ASMS("\xF6\xC2\x01"); \
TAG_PREP(dbl_a); ASM(0x74);ASM(0); \
\
X86_PRE(); ASM(0x39); ASM(0xC2); \
TAG_PREP(true_1); ASM(iop); ASM(0); \
TAG_PREP(false_); ASM(0xEB); ASM(0); \
\
\
\
TAG_LABEL(dbl_a); \
ASMS("\xf2\x0f\x10\x42");ASM(PN_SIZE_T); \
ASMS("\x66\x0f\xef\xc9"); \
X86_PRE(); ASMS("\xd1\xf8"); \
ASM(0xF2);X86_PRE();ASMS("\x0f\x2a\xc8"); \
TAG_PREP(cmp_dbl); ASM(0xEB);ASM(0); \
\
TAG_LABEL(dbl_b); \
ASMS("\xf2\x0f\x10\x48");ASM(PN_SIZE_T); \
ASMS("\xF6\xC2\x01"); \
ASM(0x74);ASM(X86C(12,14, 0,0)); \
ASMS("\x66\x0f\xef\xc0"); \
X86_PRE(); ASMS("\xd1\xfa"); \
ASM(0xF2);X86_PRE();ASMS("\x0f\x2a\xc2"); \
ASM(0xEB); ASM(X86C(5,5, 0,0)); \
ASMS("\xf2\x0f\x10\x42");ASM(PN_SIZE_T); \
\
TAG_LABEL(cmp_dbl); ASMS(xmms); \
TAG_PREP(true_2); ASM(xop); ASM(0); \
TAG_LABEL(false_); X86_MOVQ(op.a, PN_FALSE); \
ASM(0xEB); ASM(X86C(7,14, 1,op.a)); \
TAG_LABEL(true_1); TAG_LABEL(true_2); \
X86_MOVQ(op.a, PN_TRUE);
#if 0
void x86_cmp(Potion *P, PNAsm * volatile * asmp, PN_OP op, unsigned char iop, unsigned char nop) {
int l23,l2,l5,l7,l8,l9,l12,l14,l16,l24,_end,_end1;
X86_MOV_RBP(0x8B, op.a); \
ASMS("\xA8\x01"); \
TAG_JMPF(0x74, l23); \
TAG_JMPTOB(l2); \
X86_PRE(); ASM(0x8B); ASM_MOV_EBP(0x55,op.a) \
X86_MOV_RBP(0x8B, op.b); \
X86_PRE(); ASM(0x39); ASM(0xC2); \
TAG_JMPF(0x74, l12); \
TAG_JMPTOB(l9); \
X86_MOVQ(op.a, PN_FALSE); \
TAG_PREP(_end); ASM(0xE9); ASMI(0); \
TAG_JMPTO(l23); \
X86_MOV_RBP(0x8B, op.a); \
X86_PRE(); ASM(0xa9), ASMI(-8); \
TAG_JMPB(0x74, l2); \
X86_MOV_RBP(0x8B, op.a); \
ASMS("\x83\x38\xfe"); \
TAG_JMPF(0x75, l14); \
X86_PRE();ASMS("\x8b\x40");ASM(PN_SIZE_T); \
TAG_JMPTO(l14); \
ASMS("\x8b\x00" \
"\x83\xe0\xfd" \
"\x3d\x01\x00\x25\x00"); \
TAG_JMPB(0x75, l2); \
X86_MOV_RBP(0x8B, op.b); \
ASMS("\xA8\x01"); \
TAG_JMPB(0x75, l2); \
X86_MOV_RBP(0x8B, op.b); \
X86_PRE(); ASM(0xa9), ASMI(-8); \
TAG_JMPB(0x74, l2); \
X86_MOV_RBP(0x8B, op.b); \
ASMS("\x83\x38\xfe"); \
TAG_JMPF(0x75, l16); \
X86_PRE();ASMS("\x8b\x40");ASM(PN_SIZE_T); \
TAG_JMPTO(l16); \
ASMS("\x8b\x00" \
"\x83\xe0\xfd" \
"\x3d\x01\x00\x25\x00"); \
TAG_JMPB(0x75, l2); \
X86_MOV_RBP(0x8B, op.a); \
ASMS("\xA8\x01"); \
X86_MOV_RBP(0x8B, op.a); \
TAG_JMPF(0x74, l5); \
ASMS("\x66\x0f\xef\xc9"); \
X86_PRE();ASMS("\xd1\xf8"); \
ASM(0xF2);X86_PRE();ASMS("\x0f\x2a\xc8"); \
X86_MOV_RBP(0x8B, op.b); \
ASMS("\xA8\x01"); \
X86_MOV_RBP(0x8B, op.b); \
TAG_JMPF(0x74, l7); \
TAG_JMPTOB(l24); \
ASMS("\x66\x0f\xef\xc0"); \
X86_PRE();ASMS("\xd1\xf8"); \
ASM(0xF2);X86_PRE();ASMS("\x0f\x2a\xc0"); \
TAG_JMPTOB(l8); \
ASMS("\x66\x0f\x2e\xc8"); \
TAG_JMPB(0x7a, l9); \
TAG_JMPB(nop, l9); \
TAG_JMPTO(l12); \
X86_MOVQ(op.a, PN_TRUE); \
TAG_PREP(_end1); ASM(0xEB); ASM(0); \
TAG_JMPTO(l5); \
ASMS("\xf2\x0f\x10\x48\x08"); \
X86_MOV_RBP(0x8B, op.b); \
ASMS("\xA8\x01"); \
X86_MOV_RBP(0x8B, op.b); \
TAG_JMPB(0x75, l24); \
TAG_JMPTO(l7); \
ASMS("\xf2\x0f\x10\x40\x08"); \
TAG_JMPB(0xeb, l8); \
TAG_JMPTOW(_end); TAG_JMPTO(_end1);
}
#endif
#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, rcx, rdx, *rbp, *sp;
#if POTION_X86 == POTION_JIT_TARGET
#if PN_SIZE_T != 8
__asm__ ("mov %%eax, %0;"
:"=r"(rax));
__asm__ ("mov %%ecx, %0;"
:"=r"(rcx));
__asm__ ("mov %%edx, %0;"
:"=r"(rdx));
__asm__ ("mov %%ebp, %0;"
:"=r"(sp));
#else
__asm__ ("mov %%rax, %0;"
:"=r"(rax));
__asm__ ("mov %%rcx, %0;"
:"=r"(rcx));
__asm__ ("mov %%rdx, %0;"
:"=r"(rdx));
__asm__ ("mov %%rbp, %0;"
:"=r"(sp));
#endif
printf("RAX = 0x%lx (0x%x)\n", rax, potion_type(rax));
printf("RCX = 0x%lx (0x%x)\n", rcx, potion_type(rcx));
printf("RDX = 0x%lx (0x%x)\n", rdx, potion_type(rdx));
#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 = 0x%lx (0x%lx), SP = 0x%lx\n", (PN)rbp, *rbp, (PN)sp);
while (sp < rbp) {
printf("STACK[%d] = 0x%lx (0x%x)\n", n++, *sp, PN_TYPE(*sp));
sp++;
}
goto again;
}
}
static void potion_x86_c_arg(Potion *P, PNAsm * volatile *asmp, int out, int regn, int argn) {
#if PN_SIZE_T != 8
if (argn == 0) {
if (!out) {
ASM(0x8b); ASM(0x55); ASM(2 * sizeof(PN));
ASMS("\x89\x14\x24");
}
}
else {
if (out == 2) {
ASM(0xc7); ASM(0x44); ASM(0x24); ASM(argn * sizeof(PN)); ASMI(regn);
} else if (out) {
ASM(0x8b); ASM_MOV_EBP(0x55,regn)
}
if (!out) argn += 2;
if (out == 1) {
ASMS("\x89\x54\x24"); ASM(argn * sizeof(PN));
} else if (!out) {
ASM(0x8b); ASM(0x55); ASM(argn * sizeof(PN));
}
if (!out) {
ASM(0x89); ASM_MOV_EBP(0x55,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_MOV_EBP(0x7d,regn)
}
break;
case 1:
if (out == 2) {
X86_PRE(); ASM(0xc7); ASM(0xc6); ASMI(regn);
} else {
X86_PRE(); ASM(out ? 0x8b : 0x89); ASM_MOV_EBP(0x75,regn)
}
break;
case 2:
if (out == 2) {
X86_PRE(); ASM(0xc7); ASM(0xc2); ASMI(regn);
} else {
X86_PRE(); ASM(out ? 0x8b : 0x89); ASM_MOV_EBP(0x55,regn)
}
break;
case 3:
if (out == 2) {
X86_PRE(); ASM(0xc7); ASM(0xc1); ASMI(regn);
} else {
X86_PRE(); ASM(out ? 0x8b : 0x89); ASM_MOV_EBP(0x4d,regn)
}
break;
case 4:
if (out == 2) {
ASMS("\x49\xc7\xc0"); ASMI(regn);
} else {
ASM(0x4c); ASM(out ? 0x8b : 0x89); ASM_MOV_EBP(0x45,regn)
}
break;
case 5:
if (out == 2) {
ASMS("\x49\xc7\xc1"); ASMI(regn);
} else {
ASM(0x4c); ASM(out ? 0x8b : 0x89); ASM_MOV_EBP(0x4d,regn)
}
break;
default:
if (out) {
X86_PRE(); ASM(0x8B); ASM_MOV_EBP(0x5d,regn)
if (argn == 6) {
X86_PRE(); ASMS("\x89\x1c\x24");
} else {
X86_PRE(); ASMS("\x89\x5c\x24"); ASM((argn - 6) * sizeof(PN));
}
} else {
X86_PRE(); ASM(0x8b); ASM(0x5d); ASM((argn - 4) * sizeof(PN));
X86_PRE(); ASM(0x89); ASM_MOV_EBP(0x5d,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,0,0)+((need-X86C(8,0,0,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++) {
int n = sizeof(struct PNClosure) + ((upi + 1) * sizeof(PN));
X86_MOV_RBP(0x8B, start - 2);
X86_PRE(); ASM(0x8B);
if (n >= 0x80) { ASM(0x80); ASMI(n); }
else { ASM(0x40); ASM(n); }
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) {
ASMS("\xF6\xC0\x01"
"\x75"); ASM(X86C(19,20, 0,0));
ASMS("\xF7\xC0"); ASMI(PN_REF_MASK);
ASM(0x74); ASM(X86C(11,12, 0,0));
ASMS("\x81\x38"); ASMI(PN_TWEAK);
ASM(0x75); ASM(X86C(3,4, 0,0));
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_MOV_EBP(0x55, op.a)
if (up) {
X86_MOV_RBP(0x8B, regs + op.b);
ASMS("\xF6\xC0\x01"
"\x75"); ASM(X86C(19,20, 0,0));
ASMS("\xF7\xC0"); ASMI(PN_REF_MASK);
ASM(0x74); ASM(X86C(11,12, 0,0));
ASMS("\x81\x38"); ASMI(PN_TWEAK);
ASM(0x75); ASM(X86C(3,4, 0,0));
X86_PRE(); ASM(0x89); ASM(0x50);
ASM(sizeof(struct PNObject));
}
X86_PRE(); ASM(0x89); ASM_MOV_EBP(0x55, 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_MOV_EBP(0x55, 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_MOV_EBP(0x45, 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_gettuple(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(op.a, 0);
X86_PRE(); ASM(0xB8); ASMN(potion_fwd);
ASM(0xFF); ASM(0xD0);
if (op.b & ASM_TPL_IMM) {
X86_PRE();ASM(0x8b);ASM_MOV_EBP(0x55,op.b-ASM_TPL_IMM);
X86_PRE();ASMS("\xd1\xea");
X86_PRE();ASM(0x8b);ASM(0x44);ASM((5+PN_SIZE_T)<<4);ASM(0x10);
} else {
X86_PRE();ASM(0xc7);ASM(0xc2);ASMI(op.b+2);
X86_PRE();ASM(0x8b);ASM(0x04);ASM((5+PN_SIZE_T)<<4);
}
X86_MOV_RBP(0x89, op.a);
return;
}
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_gettable(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_table_at);
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(); ASMS("\x8D\x44\x10\xFF");
ASM(0x70); ASM(2);
});
}
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);
ASM(0x70); ASM(X86_PRE_T + 4);
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(); ASMS("\xD1\xFA");
X86_PRE(); ASMS("\xFF\xC8");
X86_PRE(); ASMS("\x0F\xAF\xC2");
ASM(0x70); ASM(X86_PRE_T + 4);
X86_PRE(); ASMS("\xFF\xC0");
});
}
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, {
ASMS("\xD1\xF8"
"\xD1\xFA"
"\x89\xD1"
"\x89\xC2"
"\xC1\xFA\x1F"
"\xF7\xF9"
"\x8D\x44\x00\x01");
});
}
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, {
ASMS("\xD1\xF8"
"\xD1\xFA"
"\x89\xD1"
"\x89\xC2"
"\xC1\xFA\x1F"
"\xF7\xF9"
"\x8D\x44\x12\x01");
});
}
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_num_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, 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_vm_neq);
ASM(0xFF); ASM(0xD0);
X86_MOV_RBP(0x89, op.a);
}
void potion_x86_eq(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_vm_eq);
ASM(0xFF); ASM(0xD0);
X86_MOV_RBP(0x89, op.a);
}
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_NUMCMP(0x7C, 0x72,
"\x66\x0F\x2e\xc1"
);
}
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_NUMCMP(0x7E, 0x76,
"\x66\x0F\x2e\xc1"
);
}
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_NUMCMP(0x7F, 0x77,
"\x66\x0F\x2e\xc1"
);
}
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_NUMCMP(0x7D, 0x73,
"\x66\x0F\x2e\xc1"
);
}
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, {
ASMS("\xD1\xF8"
"\xD1\xFA"
"\x89\xD1"
"\x89\xC2"
"\xD3\xE0");
ASM(0x70); ASM(6);
ASMS("\x8D\x44\x00\x01");
});
}
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, {
ASMS("\xD1\xF8"
"\xD1\xFA"
"\x89\xD1"
"\x89\xC2"
"\xD3\xF8");
ASM(0x70); ASM(6);
ASMS("\x8D\x44\x00\x01");
});
}
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) {
int false1, false2, true1;
PN_OP op = PN_OP_AT(f->asmb, pos);
X86_MOV_RBP(0x8B, op.a);
X86_PRE(); ASM(0x83); ASM(0xF8); ASM(PN_FALSE);
TAG_PREP(false1); ASM(0x74); ASM(0);
X86_PRE(); ASM(0x85); ASM(0xC0);
TAG_PREP(false2); ASM(0x74); ASM(0);
X86_MOVQ(op.a, test ? PN_FALSE : PN_TRUE);
TAG_PREP(true1); ASM(0xEB); ASM(0);
TAG_LABEL(false1); TAG_LABEL(false2);
X86_MOVQ(op.a, test ? PN_TRUE : PN_FALSE);
TAG_LABEL(true1);
}
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);
X86_PRE(); ASM(0x83); ASM(0xF8); ASM(PN_FALSE);
ASM(0x74); ASM(X86C(9,10, 0,0));
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);
X86_PRE(); ASM(0x83); ASM(0xF8); ASM(PN_FALSE);
ASM(0x74); ASM(X86C(4,5, 0,0));
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) {
int tag;
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);
ASMS("\xFF\xD0"
"\x85\xC0");
TAG_PREP(tag);
ASM(0x78); ASM(0);
X86_PRE(); ASM(0xF7); ASM(0xD8);
X86_PRE(); ASM(0x8B); ASM_MOV_EBP(0x55, op.b)
#if PN_SIZE_T != 8
ASM(0x89); ASM(0x54); ASM_MOV_EBP(0x85, op.a + 2)
#else
if (op.a + 2 > 15) {
DBG_v("named: mov %%rdx -A=%d(%%rbp,%%rax,8)\n", op.a + 2);
X86_PRE(); ASM(0x89); ASM(0x94); ASM(0xC5); ASM(RBP(op.a + 2)); ASM(0xff); ASM(0xff);
} else {
X86_PRE(); ASM(0x89); ASM(0x54); ASM(0xC5); ASM(RBP(op.a + 2));
}
#endif
TAG_LABEL(tag);
}
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, tag_a1, tag_a2, tag_b, tag_c, tag_d;
X86_PRE(); ASM(0x8B); ASM_MOV_EBP(0x45, op.a)
ASM(0xF6); ASM(0xC0); ASM(0x01);
TAG_PREP(tag_a1);
ASM(0x75); ASM(X86C(56,68, 3,op.a));
ASM(0xF7); ASM(0xC0); ASMI(PN_REF_MASK);
TAG_PREP(tag_a2);
ASM(0x74); ASM(X86C(48,60, 5,op.a));
X86_PRE(); ASM(0x83); ASM(0xE0); ASM(0xF8);
ASM(0x81); ASM(0x38); ASMI(PN_TVTABLE);
TAG_PREP(tag_c);
ASM(0x75); ASM(X86C(13,20, 1, start-3));
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_MOV_EBP(0x45, op.a)
X86_PRE(); ASM(0x8B); ASM(0x40);
ASM((char *)&((struct PNVtable *)P->lobby)->ctor
- (char *)P->lobby);
X86_PRE(); ASM(0x89); ASM_MOV_EBP(0x45, op.a)
TAG_LABEL(tag_c);
ASM(0x81); ASM(0x38); ASMI(PN_TCLOSURE);
TAG_PREP(tag_d);
ASM(0x74); ASM(X86C(22,30, 2,op.a));
X86_MOV_RBP(0x8B, op.a);
TAG_LABEL(tag_a1); TAG_LABEL(tag_a2);
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);
TAG_PREP(tag_b);
ASM(0xEB); ASM(X86C(3,4, 1,op.a));
TAG_LABEL(tag_d);
X86_PRE(); ASM(0x8B); ASM_MOV_EBP(0x45, op.a)
TAG_LABEL(tag_b);
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_tailcall(Potion *P, struct PNProto * volatile f, PNAsm * volatile *asmp, PN_SIZE pos) {
}
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, {
int n;
(*pos)++;
PN_OP opp = PN_OP_AT(f->asmb, *pos);
if (opp.code == OP_GETUPVAL) {
X86_PRE(); ASM(0x8B); ASM_MOV_EBP(0x55, 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);
n = sizeof(struct PNClosure) + (sizeof(PN) * (i + 1));
if (n >= 0x80) { ASM(0x90); ASMI(n); }
else { ASM(0x50); ASM(n); }
});
}
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 PN_SIZE_T != 8
ASMS("\x55"
"\x89\xE5"
"\x8B\x55\x08");
#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, 0,0));
ASMI(PN_UNIQ(kh_key(PN, vt->methods, k - 1)));
ASM(0x75); ASM(X86C(7,11, 0,0));
X86_PRE(); ASM(0xB8); ASMN(kh_val(PN, vt->methods, k - 1));
#if PN_SIZE_T != 8
ASM(0x5D);
#endif
ASM(0xC3);
}
}
ASM(0xB8); ASMI(0);
#if PN_SIZE_T != 8
ASM(0x5D);
#endif
ASM(0xC3);
}
void potion_x86_ivars(Potion *P, PN ivars, PNAsm * volatile *asmp) {
#if PN_SIZE_T != 8
ASMS("\x55"
"\x89\xE5"
"\x8B\x55\x08");
#else
#endif
#if PN_SIZE_T != 8
PN_TUPLE_EACH(ivars, i, v, {
ASM(0x81); ASM(X86C(0xFA,0xFF, 0,0));
ASMI(PN_UNIQ(v));
ASM(0x75); ASM(X86C(7,6, 0,0));
ASM(0xB8); ASMI(i);
ASM(0x5D);
ASM(0xC3);
});
#else
PN_TUPLE_EACH(ivars, i, v, {
ASM(0x81); ASM(X86C(0xFA,0xFF, 0,0));
ASMI(PN_UNIQ(v));
ASM(0x75); ASM(X86C(7,6, 0,0));
ASM(0xB8); ASMI(i);
ASM(0xC3);
});
#endif
X86_PRE(); ASM(0xB8); ASMN(-1);
#if PN_SIZE_T != 8
ASM(0x5D);
#endif
ASM(0xC3);
}
MAKE_TARGET(x86);