Alien-TinyCC
view release on metacpan or search on metacpan
src/x86_64-gen.c view on Meta::CPAN
func_vc = addr;
reg_param_index++;
addr += 8;
}
/* define parameters */
while ((sym = sym->next) != NULL) {
type = &sym->type;
bt = type->t & VT_BTYPE;
size = gfunc_arg_size(type);
if (size > 8) {
if (reg_param_index < REGN) {
gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
}
sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL | VT_REF, addr);
} else {
if (reg_param_index < REGN) {
/* save arguments passed by register */
if ((bt == VT_FLOAT) || (bt == VT_DOUBLE)) {
o(0xd60f66); /* movq */
gen_modrm(reg_param_index, VT_LOCAL, NULL, addr);
} else {
gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
}
}
sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, addr);
}
addr += 8;
reg_param_index++;
}
while (reg_param_index < REGN) {
if (func_type->ref->c == FUNC_ELLIPSIS) {
gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
addr += 8;
}
reg_param_index++;
}
}
/* generate function epilog */
void gfunc_epilog(void)
{
int v, saved_ind;
o(0xc9); /* leave */
if (func_ret_sub == 0) {
o(0xc3); /* ret */
} else {
o(0xc2); /* ret n */
g(func_ret_sub);
g(func_ret_sub >> 8);
}
saved_ind = ind;
ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
/* align local size to word & save local variables */
v = (func_scratch + -loc + 15) & -16;
if (v >= 4096) {
Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
oad(0xb8, v); /* mov stacksize, %eax */
oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */
greloc(cur_text_section, sym, ind-4, R_X86_64_PC32);
o(0x90); /* fill for FUNC_PROLOG_SIZE = 11 bytes */
} else {
o(0xe5894855); /* push %rbp, mov %rsp, %rbp */
o(0xec8148); /* sub rsp, stacksize */
gen_le32(v);
}
cur_text_section->data_offset = saved_ind;
pe_add_unwind_data(ind, saved_ind, v);
ind = cur_text_section->data_offset;
}
#else
static void gadd_sp(int val)
{
if (val == (char)val) {
o(0xc48348);
g(val);
} else {
oad(0xc48148, val); /* add $xxx, %rsp */
}
}
typedef enum X86_64_Mode {
x86_64_mode_none,
x86_64_mode_memory,
x86_64_mode_integer,
x86_64_mode_sse,
x86_64_mode_x87
} X86_64_Mode;
static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b) {
if (a == b)
return a;
else if (a == x86_64_mode_none)
return b;
else if (b == x86_64_mode_none)
return a;
else if ((a == x86_64_mode_memory) || (b == x86_64_mode_memory))
return x86_64_mode_memory;
else if ((a == x86_64_mode_integer) || (b == x86_64_mode_integer))
return x86_64_mode_integer;
else if ((a == x86_64_mode_x87) || (b == x86_64_mode_x87))
return x86_64_mode_memory;
else
return x86_64_mode_sse;
}
static X86_64_Mode classify_x86_64_inner(CType *ty) {
X86_64_Mode mode;
Sym *f;
switch (ty->t & VT_BTYPE) {
case VT_VOID: return x86_64_mode_none;
case VT_INT:
src/x86_64-gen.c view on Meta::CPAN
o(0x100ff3);
o(0x44 + REG_VALUE(r)*8);
o(0xf024);
vtop->r = r;
}
}
}
/* convert fp to int 't' type */
void gen_cvt_ftoi(int t)
{
int ft, bt, size, r;
ft = vtop->type.t;
bt = ft & VT_BTYPE;
if (bt == VT_LDOUBLE) {
gen_cvt_ftof(VT_DOUBLE);
bt = VT_DOUBLE;
}
gv(RC_FLOAT);
if (t != VT_INT)
size = 8;
else
size = 4;
r = get_reg(RC_INT);
if (bt == VT_FLOAT) {
o(0xf3);
} else if (bt == VT_DOUBLE) {
o(0xf2);
} else {
assert(0);
}
orex(size == 8, r, 0, 0x2c0f); /* cvttss2si or cvttsd2si */
o(0xc0 + REG_VALUE(vtop->r) + REG_VALUE(r)*8);
vtop->r = r;
}
/* computed goto support */
void ggoto(void)
{
gcall_or_jmp(1);
vtop--;
}
/* Save the stack pointer onto the stack and return the location of its address */
ST_FUNC void gen_vla_sp_save(int addr) {
/* mov %rsp,addr(%rbp)*/
gen_modrm64(0x89, TREG_RSP, VT_LOCAL, NULL, addr);
}
/* Restore the SP from a location on the stack */
ST_FUNC void gen_vla_sp_restore(int addr) {
gen_modrm64(0x8b, TREG_RSP, VT_LOCAL, NULL, addr);
}
/* Subtract from the stack pointer, and push the resulting value onto the stack */
ST_FUNC void gen_vla_alloc(CType *type, int align) {
#ifdef TCC_TARGET_PE
/* alloca does more than just adjust %rsp on Windows */
vpush_global_sym(&func_old_type, TOK_alloca);
vswap(); /* Move alloca ref past allocation size */
gfunc_call(1);
vset(type, REG_IRET, 0);
#else
int r;
r = gv(RC_INT); /* allocation size */
/* sub r,%rsp */
o(0x2b48);
o(0xe0 | REG_VALUE(r));
/* We align to 16 bytes rather than align */
/* and ~15, %rsp */
o(0xf0e48348);
/* mov %rsp, r */
o(0x8948);
o(0xe0 | REG_VALUE(r));
vpop();
vset(type, r, 0);
#endif
}
/* end of x86-64 code generator */
/*************************************************************/
#endif /* ! TARGET_DEFS_ONLY */
/******************************************************/
( run in 0.408 second using v1.01-cache-2.11-cpan-ceb78f64989 )