Tabs vs spaces
This commit is contained in:
342
packages/tcc/vendor/x86_64-gen.c
vendored
342
packages/tcc/vendor/x86_64-gen.c
vendored
@@ -288,18 +288,18 @@ static void gen_modrm_impl(int op_reg, int r, Sym *sym, int c, int is_got)
|
||||
op_reg = REG_VALUE(op_reg) << 3;
|
||||
if ((r & VT_VALMASK) == VT_CONST) {
|
||||
/* constant memory reference */
|
||||
if (!(r & VT_SYM)) {
|
||||
/* Absolute memory reference */
|
||||
o(0x04 | op_reg); /* [sib] | destreg */
|
||||
oad(0x25, c); /* disp32 */
|
||||
} else {
|
||||
o(0x05 | op_reg); /* (%rip)+disp32 | destreg */
|
||||
if (is_got) {
|
||||
gen_gotpcrel(r, sym, c);
|
||||
} else {
|
||||
gen_addrpc32(r, sym, c);
|
||||
}
|
||||
}
|
||||
if (!(r & VT_SYM)) {
|
||||
/* Absolute memory reference */
|
||||
o(0x04 | op_reg); /* [sib] | destreg */
|
||||
oad(0x25, c); /* disp32 */
|
||||
} else {
|
||||
o(0x05 | op_reg); /* (%rip)+disp32 | destreg */
|
||||
if (is_got) {
|
||||
gen_gotpcrel(r, sym, c);
|
||||
} else {
|
||||
gen_addrpc32(r, sym, c);
|
||||
}
|
||||
}
|
||||
} else if ((r & VT_VALMASK) == VT_LOCAL) {
|
||||
/* currently, we use only ebp as base */
|
||||
if (c == (char)c) {
|
||||
@@ -387,36 +387,36 @@ void load(int r, SValue *sv)
|
||||
fr = get_reg(RC_INT);
|
||||
load(fr, &v1);
|
||||
}
|
||||
if (fc != sv->c.i) {
|
||||
/* If the addends doesn't fit into a 32bit signed
|
||||
we must use a 64bit move. We've checked above
|
||||
that this doesn't have a sym associated. */
|
||||
v1.type.t = VT_LLONG;
|
||||
v1.r = VT_CONST;
|
||||
v1.c.i = sv->c.i;
|
||||
fr = r;
|
||||
if (!(reg_classes[fr] & (RC_INT|RC_R11)))
|
||||
fr = get_reg(RC_INT);
|
||||
load(fr, &v1);
|
||||
fc = 0;
|
||||
}
|
||||
if (fc != sv->c.i) {
|
||||
/* If the addends doesn't fit into a 32bit signed
|
||||
we must use a 64bit move. We've checked above
|
||||
that this doesn't have a sym associated. */
|
||||
v1.type.t = VT_LLONG;
|
||||
v1.r = VT_CONST;
|
||||
v1.c.i = sv->c.i;
|
||||
fr = r;
|
||||
if (!(reg_classes[fr] & (RC_INT|RC_R11)))
|
||||
fr = get_reg(RC_INT);
|
||||
load(fr, &v1);
|
||||
fc = 0;
|
||||
}
|
||||
ll = 0;
|
||||
/* Like GCC we can load from small enough properly sized
|
||||
structs and unions as well.
|
||||
XXX maybe move to generic operand handling, but should
|
||||
occur only with asm, so tccasm.c might also be a better place */
|
||||
if ((ft & VT_BTYPE) == VT_STRUCT) {
|
||||
int align;
|
||||
switch (type_size(&sv->type, &align)) {
|
||||
case 1: ft = VT_BYTE; break;
|
||||
case 2: ft = VT_SHORT; break;
|
||||
case 4: ft = VT_INT; break;
|
||||
case 8: ft = VT_LLONG; break;
|
||||
default:
|
||||
tcc_error("invalid aggregate type for register load");
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Like GCC we can load from small enough properly sized
|
||||
structs and unions as well.
|
||||
XXX maybe move to generic operand handling, but should
|
||||
occur only with asm, so tccasm.c might also be a better place */
|
||||
if ((ft & VT_BTYPE) == VT_STRUCT) {
|
||||
int align;
|
||||
switch (type_size(&sv->type, &align)) {
|
||||
case 1: ft = VT_BYTE; break;
|
||||
case 2: ft = VT_SHORT; break;
|
||||
case 4: ft = VT_INT; break;
|
||||
case 8: ft = VT_LLONG; break;
|
||||
default:
|
||||
tcc_error("invalid aggregate type for register load");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((ft & VT_BTYPE) == VT_FLOAT) {
|
||||
b = 0x6e0f66;
|
||||
r = REG_VALUE(r); /* movd */
|
||||
@@ -478,18 +478,18 @@ void load(int r, SValue *sv)
|
||||
gen_modrm(r, VT_LOCAL, sv->sym, fc);
|
||||
} else if (v == VT_CMP) {
|
||||
orex(0,r,0,0);
|
||||
if ((fc & ~0x100) != TOK_NE)
|
||||
if ((fc & ~0x100) != TOK_NE)
|
||||
oad(0xb8 + REG_VALUE(r), 0); /* mov $0, r */
|
||||
else
|
||||
else
|
||||
oad(0xb8 + REG_VALUE(r), 1); /* mov $1, r */
|
||||
if (fc & 0x100)
|
||||
{
|
||||
/* This was a float compare. If the parity bit is
|
||||
set the result was unordered, meaning false for everything
|
||||
except TOK_NE, and true for TOK_NE. */
|
||||
fc &= ~0x100;
|
||||
o(0x037a + (REX_BASE(r) << 8));
|
||||
}
|
||||
if (fc & 0x100)
|
||||
{
|
||||
/* This was a float compare. If the parity bit is
|
||||
set the result was unordered, meaning false for everything
|
||||
except TOK_NE, and true for TOK_NE. */
|
||||
fc &= ~0x100;
|
||||
o(0x037a + (REX_BASE(r) << 8));
|
||||
}
|
||||
orex(0,r,0, 0x0f); /* setxx %br */
|
||||
o(fc);
|
||||
o(0xc0 + REG_VALUE(r));
|
||||
@@ -623,7 +623,7 @@ static void gcall_or_jmp(int is_jmp)
|
||||
{
|
||||
int r;
|
||||
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
|
||||
((vtop->r & VT_SYM) || (vtop->c.i-4) == (int)(vtop->c.i-4))) {
|
||||
((vtop->r & VT_SYM) || (vtop->c.i-4) == (int)(vtop->c.i-4))) {
|
||||
/* constant case */
|
||||
if (vtop->r & VT_SYM) {
|
||||
/* relocation case */
|
||||
@@ -875,8 +875,8 @@ void gfunc_call(int nb_args)
|
||||
struct_size += size;
|
||||
} else {
|
||||
if (is_sse_float(vtop->type.t)) {
|
||||
if (tcc_state->nosse)
|
||||
tcc_error("SSE disabled");
|
||||
if (tcc_state->nosse)
|
||||
tcc_error("SSE disabled");
|
||||
gv(RC_XMM0); /* only use one float register */
|
||||
if (arg >= REGN) {
|
||||
/* movq %xmm0, j*8(%rsp) */
|
||||
@@ -994,8 +994,8 @@ void gfunc_prolog(CType *func_type)
|
||||
if (reg_param_index < REGN) {
|
||||
/* save arguments passed by register */
|
||||
if ((bt == VT_FLOAT) || (bt == VT_DOUBLE)) {
|
||||
if (tcc_state->nosse)
|
||||
tcc_error("SSE disabled");
|
||||
if (tcc_state->nosse)
|
||||
tcc_error("SSE disabled");
|
||||
o(0xd60f66); /* movq */
|
||||
gen_modrm(reg_param_index, VT_LOCAL, NULL, addr);
|
||||
} else {
|
||||
@@ -1252,20 +1252,20 @@ void gfunc_call(int nb_args)
|
||||
mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, ®_count);
|
||||
if (mode == x86_64_mode_sse && nb_sse_args + reg_count <= 8) {
|
||||
nb_sse_args += reg_count;
|
||||
onstack[i] = 0;
|
||||
} else if (mode == x86_64_mode_integer && nb_reg_args + reg_count <= REGN) {
|
||||
onstack[i] = 0;
|
||||
} else if (mode == x86_64_mode_integer && nb_reg_args + reg_count <= REGN) {
|
||||
nb_reg_args += reg_count;
|
||||
onstack[i] = 0;
|
||||
} else if (mode == x86_64_mode_none) {
|
||||
onstack[i] = 0;
|
||||
} else {
|
||||
if (align == 16 && (stack_adjust &= 15)) {
|
||||
onstack[i] = 2;
|
||||
stack_adjust = 0;
|
||||
} else
|
||||
onstack[i] = 1;
|
||||
stack_adjust += size;
|
||||
}
|
||||
onstack[i] = 0;
|
||||
} else if (mode == x86_64_mode_none) {
|
||||
onstack[i] = 0;
|
||||
} else {
|
||||
if (align == 16 && (stack_adjust &= 15)) {
|
||||
onstack[i] = 2;
|
||||
stack_adjust = 0;
|
||||
} else
|
||||
onstack[i] = 1;
|
||||
stack_adjust += size;
|
||||
}
|
||||
}
|
||||
|
||||
if (nb_sse_args && tcc_state->nosse)
|
||||
@@ -1283,71 +1283,71 @@ void gfunc_call(int nb_args)
|
||||
args_size = 0;
|
||||
stack_adjust &= 15;
|
||||
for (i = 0; i < nb_args;) {
|
||||
mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, ®_count);
|
||||
if (!onstack[i]) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
/* Possibly adjust stack to align SSE boundary. We're processing
|
||||
args from right to left while allocating happens left to right
|
||||
(stack grows down), so the adjustment needs to happen _after_
|
||||
an argument that requires it. */
|
||||
if (stack_adjust) {
|
||||
o(0x50); /* push %rax; aka sub $8,%rsp */
|
||||
args_size += 8;
|
||||
stack_adjust = 0;
|
||||
mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, ®_count);
|
||||
if (!onstack[i]) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
if (onstack[i] == 2)
|
||||
stack_adjust = 1;
|
||||
/* Possibly adjust stack to align SSE boundary. We're processing
|
||||
args from right to left while allocating happens left to right
|
||||
(stack grows down), so the adjustment needs to happen _after_
|
||||
an argument that requires it. */
|
||||
if (stack_adjust) {
|
||||
o(0x50); /* push %rax; aka sub $8,%rsp */
|
||||
args_size += 8;
|
||||
stack_adjust = 0;
|
||||
}
|
||||
if (onstack[i] == 2)
|
||||
stack_adjust = 1;
|
||||
|
||||
vrotb(i+1);
|
||||
vrotb(i+1);
|
||||
|
||||
switch (vtop->type.t & VT_BTYPE) {
|
||||
case VT_STRUCT:
|
||||
/* allocate the necessary size on stack */
|
||||
o(0x48);
|
||||
oad(0xec81, size); /* sub $xxx, %rsp */
|
||||
/* generate structure store */
|
||||
r = get_reg(RC_INT);
|
||||
orex(1, r, 0, 0x89); /* mov %rsp, r */
|
||||
o(0xe0 + REG_VALUE(r));
|
||||
vset(&vtop->type, r | VT_LVAL, 0);
|
||||
vswap();
|
||||
vstore();
|
||||
break;
|
||||
switch (vtop->type.t & VT_BTYPE) {
|
||||
case VT_STRUCT:
|
||||
/* allocate the necessary size on stack */
|
||||
o(0x48);
|
||||
oad(0xec81, size); /* sub $xxx, %rsp */
|
||||
/* generate structure store */
|
||||
r = get_reg(RC_INT);
|
||||
orex(1, r, 0, 0x89); /* mov %rsp, r */
|
||||
o(0xe0 + REG_VALUE(r));
|
||||
vset(&vtop->type, r | VT_LVAL, 0);
|
||||
vswap();
|
||||
vstore();
|
||||
break;
|
||||
|
||||
case VT_LDOUBLE:
|
||||
case VT_LDOUBLE:
|
||||
gv(RC_ST0);
|
||||
oad(0xec8148, size); /* sub $xxx, %rsp */
|
||||
o(0x7cdb); /* fstpt 0(%rsp) */
|
||||
g(0x24);
|
||||
g(0x00);
|
||||
break;
|
||||
break;
|
||||
|
||||
case VT_FLOAT:
|
||||
case VT_DOUBLE:
|
||||
assert(mode == x86_64_mode_sse);
|
||||
r = gv(RC_FLOAT);
|
||||
o(0x50); /* push $rax */
|
||||
/* movq %xmmN, (%rsp) */
|
||||
o(0xd60f66);
|
||||
o(0x04 + REG_VALUE(r)*8);
|
||||
o(0x24);
|
||||
break;
|
||||
case VT_FLOAT:
|
||||
case VT_DOUBLE:
|
||||
assert(mode == x86_64_mode_sse);
|
||||
r = gv(RC_FLOAT);
|
||||
o(0x50); /* push $rax */
|
||||
/* movq %xmmN, (%rsp) */
|
||||
o(0xd60f66);
|
||||
o(0x04 + REG_VALUE(r)*8);
|
||||
o(0x24);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(mode == x86_64_mode_integer);
|
||||
/* simple type */
|
||||
/* XXX: implicit cast ? */
|
||||
r = gv(RC_INT);
|
||||
orex(0,r,0,0x50 + REG_VALUE(r)); /* push r */
|
||||
break;
|
||||
}
|
||||
args_size += size;
|
||||
default:
|
||||
assert(mode == x86_64_mode_integer);
|
||||
/* simple type */
|
||||
/* XXX: implicit cast ? */
|
||||
r = gv(RC_INT);
|
||||
orex(0,r,0,0x50 + REG_VALUE(r)); /* push r */
|
||||
break;
|
||||
}
|
||||
args_size += size;
|
||||
|
||||
vpop();
|
||||
--nb_args;
|
||||
onstack++;
|
||||
vpop();
|
||||
--nb_args;
|
||||
onstack++;
|
||||
}
|
||||
|
||||
/* XXX This should be superfluous. */
|
||||
@@ -1465,14 +1465,14 @@ void gfunc_prolog(CType *func_type)
|
||||
|
||||
case x86_64_mode_integer:
|
||||
if (seen_reg_num + reg_count > REGN)
|
||||
goto stack_arg;
|
||||
seen_reg_num += reg_count;
|
||||
goto stack_arg;
|
||||
seen_reg_num += reg_count;
|
||||
break;
|
||||
|
||||
case x86_64_mode_sse:
|
||||
if (seen_sse_num + reg_count > 8)
|
||||
goto stack_arg;
|
||||
seen_sse_num += reg_count;
|
||||
goto stack_arg;
|
||||
seen_sse_num += reg_count;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1491,10 +1491,10 @@ void gfunc_prolog(CType *func_type)
|
||||
/* save all register passing arguments */
|
||||
for (i = 0; i < 8; i++) {
|
||||
loc -= 16;
|
||||
if (!tcc_state->nosse) {
|
||||
o(0xd60f66); /* movq */
|
||||
gen_modrm(7 - i, VT_LOCAL, NULL, loc);
|
||||
}
|
||||
if (!tcc_state->nosse) {
|
||||
o(0xd60f66); /* movq */
|
||||
gen_modrm(7 - i, VT_LOCAL, NULL, loc);
|
||||
}
|
||||
/* movq $0, loc+8(%rbp) */
|
||||
o(0x85c748);
|
||||
gen_le32(loc + 8);
|
||||
@@ -1524,8 +1524,8 @@ void gfunc_prolog(CType *func_type)
|
||||
mode = classify_x86_64_arg(type, NULL, &size, &align, ®_count);
|
||||
switch (mode) {
|
||||
case x86_64_mode_sse:
|
||||
if (tcc_state->nosse)
|
||||
tcc_error("SSE disabled but floating point arguments used");
|
||||
if (tcc_state->nosse)
|
||||
tcc_error("SSE disabled but floating point arguments used");
|
||||
if (sse_param_index + reg_count <= 8) {
|
||||
/* save arguments passed by register */
|
||||
loc -= reg_count * 8;
|
||||
@@ -1565,7 +1565,7 @@ void gfunc_prolog(CType *func_type)
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break; /* nothing to be done for x86_64_mode_none */
|
||||
default: break; /* nothing to be done for x86_64_mode_none */
|
||||
}
|
||||
sym_push(sym->v & ~SYM_FIELD, type,
|
||||
VT_LOCAL | VT_LVAL, param_addr);
|
||||
@@ -1577,8 +1577,8 @@ void gfunc_prolog(CType *func_type)
|
||||
func_bound_offset = lbounds_section->data_offset;
|
||||
func_bound_ind = ind;
|
||||
oad(0xb8, 0); /* lbound section pointer */
|
||||
o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */
|
||||
oad(0xb8, 0); /* call to function */
|
||||
o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */
|
||||
oad(0xb8, 0); /* call to function */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1590,7 +1590,7 @@ void gfunc_epilog(void)
|
||||
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check
|
||||
&& func_bound_offset != lbounds_section->data_offset)
|
||||
&& func_bound_offset != lbounds_section->data_offset)
|
||||
{
|
||||
addr_t saved_ind;
|
||||
addr_t *bounds_ptr;
|
||||
@@ -1662,25 +1662,25 @@ ST_FUNC void gtst_addr(int inv, int a)
|
||||
{
|
||||
int v = vtop->r & VT_VALMASK;
|
||||
if (v == VT_CMP) {
|
||||
inv ^= (vtop--)->c.i;
|
||||
a -= ind + 2;
|
||||
if (a == (char)a) {
|
||||
g(inv - 32);
|
||||
g(a);
|
||||
} else {
|
||||
g(0x0f);
|
||||
oad(inv - 16, a - 4);
|
||||
}
|
||||
inv ^= (vtop--)->c.i;
|
||||
a -= ind + 2;
|
||||
if (a == (char)a) {
|
||||
g(inv - 32);
|
||||
g(a);
|
||||
} else {
|
||||
g(0x0f);
|
||||
oad(inv - 16, a - 4);
|
||||
}
|
||||
} else if ((v & ~1) == VT_JMP) {
|
||||
if ((v & 1) != inv) {
|
||||
gjmp_addr(a);
|
||||
gsym(vtop->c.i);
|
||||
} else {
|
||||
gsym(vtop->c.i);
|
||||
o(0x05eb);
|
||||
gjmp_addr(a);
|
||||
}
|
||||
vtop--;
|
||||
if ((v & 1) != inv) {
|
||||
gjmp_addr(a);
|
||||
gsym(vtop->c.i);
|
||||
} else {
|
||||
gsym(vtop->c.i);
|
||||
o(0x05eb);
|
||||
gjmp_addr(a);
|
||||
}
|
||||
vtop--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1693,24 +1693,24 @@ ST_FUNC int gtst(int inv, int t)
|
||||
;
|
||||
} else if (v == VT_CMP) {
|
||||
/* fast case : can jump directly since flags are set */
|
||||
if (vtop->c.i & 0x100)
|
||||
{
|
||||
/* This was a float compare. If the parity flag is set
|
||||
the result was unordered. For anything except != this
|
||||
means false and we don't jump (anding both conditions).
|
||||
For != this means true (oring both).
|
||||
Take care about inverting the test. We need to jump
|
||||
to our target if the result was unordered and test wasn't NE,
|
||||
otherwise if unordered we don't want to jump. */
|
||||
vtop->c.i &= ~0x100;
|
||||
if (vtop->c.i & 0x100)
|
||||
{
|
||||
/* This was a float compare. If the parity flag is set
|
||||
the result was unordered. For anything except != this
|
||||
means false and we don't jump (anding both conditions).
|
||||
For != this means true (oring both).
|
||||
Take care about inverting the test. We need to jump
|
||||
to our target if the result was unordered and test wasn't NE,
|
||||
otherwise if unordered we don't want to jump. */
|
||||
vtop->c.i &= ~0x100;
|
||||
if (inv == (vtop->c.i == TOK_NE))
|
||||
o(0x067a); /* jp +6 */
|
||||
else
|
||||
{
|
||||
g(0x0f);
|
||||
t = gjmp2(0x8a, t); /* jp t */
|
||||
}
|
||||
}
|
||||
o(0x067a); /* jp +6 */
|
||||
else
|
||||
{
|
||||
g(0x0f);
|
||||
t = gjmp2(0x8a, t); /* jp t */
|
||||
}
|
||||
}
|
||||
g(0x0f);
|
||||
t = gjmp2((vtop->c.i - 16) ^ inv, t);
|
||||
} else if (v == VT_JMP || v == VT_JMPI) {
|
||||
|
||||
Reference in New Issue
Block a user