mirror of
git://repo.or.cz/tinycc.git
synced 2026-07-10 21:38:47 +08:00
review platform tls support
Some checks are pending
build and test / test-x86_64-linux (push) Waiting to run
build and test / test-x86_64-osx (push) Waiting to run
build and test / test-aarch64-osx (push) Waiting to run
build and test / test-x86_64-win32 (push) Waiting to run
build and test / test-i386-win32 (push) Waiting to run
build and test / test-arm64-win32 (push) Waiting to run
build and test / test-armv7-linux (push) Waiting to run
build and test / test-aarch64-linux (push) Waiting to run
build and test / test-riscv64-linux (push) Waiting to run
build and test / test-i386-linux (push) Waiting to run
Some checks are pending
build and test / test-x86_64-linux (push) Waiting to run
build and test / test-x86_64-osx (push) Waiting to run
build and test / test-aarch64-osx (push) Waiting to run
build and test / test-x86_64-win32 (push) Waiting to run
build and test / test-i386-win32 (push) Waiting to run
build and test / test-arm64-win32 (push) Waiting to run
build and test / test-armv7-linux (push) Waiting to run
build and test / test-aarch64-linux (push) Waiting to run
build and test / test-riscv64-linux (push) Waiting to run
build and test / test-i386-linux (push) Waiting to run
x86_64-gen.c: - remove stupid copy&paste code - integrate tls into gen_modrm() - cleanup calls to gen_modrm[64/32] i386-gen.c: - remove stupid copy&paste code arm64-gen.c: - remove stupid copy&paste code arm-gen.c: - tls not working
This commit is contained in:
parent
5673055a9c
commit
b895aa7e68
@ -588,7 +588,9 @@ void load(int r, SValue *sv)
|
||||
|
||||
v = fr & VT_VALMASK;
|
||||
if (fr & VT_LVAL) {
|
||||
|
||||
if ((fr & VT_SYM) && sv->sym->type.t & VT_TLS) {
|
||||
/* XXX: this does not work */
|
||||
uint32_t op;
|
||||
o(0xee1d0fe0); /* mrc p15, 0, lr, c13, c0, 3 */
|
||||
op = 0xe510e000; /* ldr r, [lr, #0] */
|
||||
@ -596,6 +598,7 @@ void load(int r, SValue *sv)
|
||||
o(op | (intr(r) << 12));
|
||||
return;
|
||||
}
|
||||
|
||||
base = 0xB; // fp
|
||||
if(v == VT_LLOCAL) {
|
||||
v1.type.t = VT_PTR;
|
||||
@ -726,7 +729,9 @@ void store(int r, SValue *sv)
|
||||
|
||||
v = fr & VT_VALMASK;
|
||||
if (fr & VT_LVAL || fr == VT_LOCAL) {
|
||||
|
||||
if ((fr & VT_SYM) && sv->sym->type.t & VT_TLS) {
|
||||
/* XXX: this does not work */
|
||||
uint32_t op;
|
||||
o(0xee1d0fe0); /* mrc p15, 0, lr, c13, c0, 3 */
|
||||
op = 0xe500e000; /* str r, [lr, #0] */
|
||||
@ -734,6 +739,7 @@ void store(int r, SValue *sv)
|
||||
o(op | (intr(r) << 12));
|
||||
return;
|
||||
}
|
||||
|
||||
base = 0xb; /* fp */
|
||||
if(v < VT_CONST) {
|
||||
base=intr(v);
|
||||
|
||||
52
arm64-gen.c
52
arm64-gen.c
@ -506,6 +506,17 @@ static void arm64_sym(int r, Sym *sym, unsigned long addend)
|
||||
|
||||
static void arm64_load_cmp(int r, SValue *sv);
|
||||
|
||||
static void arm64_tls_x30(SValue *sv)
|
||||
{
|
||||
o(0xd53bd05e); /* mrs x30, tpidr_el0 */
|
||||
greloca(cur_text_section, sv->sym, ind, R_AARCH64_TLSLE_ADD_TPREL_HI12, 0);
|
||||
/* add x30, x30, #0, lsl #12 */
|
||||
o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_SH(1) | ARM64_RN(30) | ARM64_RD(30));
|
||||
greloca(cur_text_section, sv->sym, ind, R_AARCH64_TLSLE_ADD_TPREL_LO12, 0);
|
||||
/* add x30, x30, #0 */
|
||||
o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_RN(30) | ARM64_RD(30));
|
||||
}
|
||||
|
||||
ST_FUNC void load(int r, SValue *sv)
|
||||
{
|
||||
int svtt = sv->type.t;
|
||||
@ -552,23 +563,9 @@ ST_FUNC void load(int r, SValue *sv)
|
||||
}
|
||||
|
||||
if (svr == (VT_CONST | VT_LVAL | VT_SYM)) {
|
||||
if (sv->sym->type.t & VT_TLS) {
|
||||
o(0xd53bd05e); /* mrs x30, tpidr_el0 */
|
||||
greloca(cur_text_section, sv->sym, ind,
|
||||
R_AARCH64_TLSLE_ADD_TPREL_HI12, 0);
|
||||
o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_SH(1) |
|
||||
ARM64_RN(30) | ARM64_RD(30)); /* add x30, x30, #0, lsl #12 */
|
||||
greloca(cur_text_section, sv->sym, ind,
|
||||
R_AARCH64_TLSLE_ADD_TPREL_LO12, 0);
|
||||
o(ARM64_ADD_IMM | ARM64_SF(1) |
|
||||
ARM64_RN(30) | ARM64_RD(30)); /* add x30, x30, #0 */
|
||||
if (IS_FREG(r))
|
||||
arm64_ldrv(arm64_type_size(svtt), fltr(r), 30, svcoff);
|
||||
else
|
||||
arm64_ldrx(!(svtt&VT_UNSIGNED), arm64_type_size(svtt),
|
||||
intr(r), 30, svcoff);
|
||||
return;
|
||||
}
|
||||
if (sv->sym->type.t & VT_TLS)
|
||||
arm64_tls_x30(sv);
|
||||
else
|
||||
arm64_sym(30, sv->sym, // use x30 for address
|
||||
arm64_check_offset(0, arm64_type_size(svtt), svcoff));
|
||||
if (IS_FREG(r))
|
||||
@ -661,28 +658,15 @@ ST_FUNC void store(int r, SValue *sv)
|
||||
|
||||
if (svr == (VT_CONST | VT_LVAL)) {
|
||||
uint64_t i = sv->c.i;
|
||||
|
||||
if (sv->sym && (sv->sym->type.t & VT_TLS)) {
|
||||
o(0xd53bd05e);
|
||||
greloca(cur_text_section, sv->sym, ind,
|
||||
R_AARCH64_TLSLE_ADD_TPREL_HI12, 0);
|
||||
o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_SH(1) |
|
||||
ARM64_RN(30) | ARM64_RD(30));
|
||||
greloca(cur_text_section, sv->sym, ind,
|
||||
R_AARCH64_TLSLE_ADD_TPREL_LO12, 0);
|
||||
o(ARM64_ADD_IMM | ARM64_SF(1) |
|
||||
ARM64_RN(30) | ARM64_RD(30));
|
||||
if (IS_FREG(r))
|
||||
arm64_strv(arm64_type_size(svtt), fltr(r), 30, i);
|
||||
else
|
||||
arm64_strx(arm64_type_size(svtt), intr(r), 30, i);
|
||||
return;
|
||||
}
|
||||
if (sv->sym && (sv->sym->type.t & VT_TLS))
|
||||
arm64_tls_x30(sv);
|
||||
else
|
||||
if (sv->sym)
|
||||
arm64_sym(30, sv->sym, // use x30 for address
|
||||
arm64_check_offset(0, arm64_type_size(svtt), i));
|
||||
else
|
||||
arm64_movimm (30, i), i = 0;
|
||||
|
||||
if (IS_FREG(r))
|
||||
arm64_strv(arm64_type_size(svtt), fltr(r), 30,
|
||||
arm64_check_offset(1, arm64_type_size(svtt), i));
|
||||
|
||||
44
i386-gen.c
44
i386-gen.c
@ -241,8 +241,13 @@ static void gen_modrm(int opc, int op_r2, int r, Sym *sym, int c)
|
||||
{
|
||||
int op_reg = REG_VALUE(op_r2) << 3;
|
||||
|
||||
if ((r & VT_SYM) && (sym->type.t & VT_TLS)) {
|
||||
o(0x65); /* gs segment prefix */
|
||||
o(opc);
|
||||
oad(0x05 | op_reg, c);
|
||||
greloc(cur_text_section, sym, ind - 4, R_386_TLS_LE);
|
||||
#if defined CONFIG_TCC_PIC
|
||||
if ((r & (VT_VALMASK|VT_SYM)) == (VT_CONST|VT_SYM)) {
|
||||
} else if ((r & (VT_VALMASK|VT_SYM)) == (VT_CONST|VT_SYM)) {
|
||||
int is_got = (op_r2 & TREG_MEM) && !(sym->type.t & VT_STATIC);
|
||||
int here = ind;
|
||||
get_pc_thunk(TREG_EBX, is_got);
|
||||
@ -261,9 +266,8 @@ static void gen_modrm(int opc, int op_r2, int r, Sym *sym, int c)
|
||||
} else {
|
||||
g(0x00 | op_reg | REG_VALUE(r));
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if ((r & VT_VALMASK) == VT_CONST) {
|
||||
} else if ((r & VT_VALMASK) == VT_CONST) {
|
||||
/* constant memory reference */
|
||||
o(opc);
|
||||
o(0x05 | op_reg);
|
||||
@ -299,7 +303,7 @@ ST_FUNC void load(int r, SValue *sv)
|
||||
#if defined CONFIG_TCC_PIC
|
||||
/* we use indirect access via got */
|
||||
if ((fr & (VT_VALMASK|VT_SYM|VT_LVAL)) == (VT_CONST|VT_SYM|VT_LVAL)
|
||||
&& !(sv->sym->type.t & VT_STATIC)) {
|
||||
&& !(sv->sym->type.t & (VT_STATIC|VT_TLS))) {
|
||||
/* use the result register as a temporal register */
|
||||
int tr = r | TREG_MEM;
|
||||
if (is_float(ft)) {
|
||||
@ -313,16 +317,6 @@ ST_FUNC void load(int r, SValue *sv)
|
||||
#endif
|
||||
|
||||
if (fr & VT_LVAL) {
|
||||
if ((fr & VT_SYM) && sv->sym->type.t & VT_TLS) {
|
||||
int dst_reg = REG_VALUE(r);
|
||||
o(0x65); /* gs segment prefix */
|
||||
o(0x8b); /* mov r/m, r */
|
||||
o(0x04 | (dst_reg << 3)); /* modrm: [sib] | destreg */
|
||||
o(0x25); /* sib: disp32 */
|
||||
greloca(cur_text_section, sv->sym, ind, R_386_TLS_LE, fc);
|
||||
gen_le32(0);
|
||||
return;
|
||||
}
|
||||
if (v == VT_LLOCAL) {
|
||||
v1.type.t = VT_INT;
|
||||
v1.r = VT_LOCAL | VT_LVAL;
|
||||
@ -356,8 +350,12 @@ ST_FUNC void load(int r, SValue *sv)
|
||||
}
|
||||
gen_modrm(opc, r, fr, sv->sym, fc);
|
||||
} else {
|
||||
if ((fr & VT_SYM) && (sv->sym->type.t & VT_TLS)) {
|
||||
oad(0x058b65 | REG_VALUE(r) << 19, 0); /* mov gs:0,r */
|
||||
oad(0xC081 | REG_VALUE(r) << 8, 0); /* add tpoffs,r */
|
||||
greloc(cur_text_section, sv->sym, ind - 4, R_386_TLS_LE);
|
||||
#if defined CONFIG_TCC_PIC
|
||||
if ((fr & (VT_VALMASK|VT_SYM)) == (VT_CONST|VT_SYM)) {
|
||||
} else if ((fr & (VT_VALMASK|VT_SYM)) == (VT_CONST|VT_SYM)) {
|
||||
if (sv->sym->type.t & VT_STATIC) {
|
||||
get_pc_thunk(r, 0);
|
||||
o(0x808d | REG_VALUE(r) * 0x900); /* lea $xx(r), r */
|
||||
@ -367,10 +365,8 @@ ST_FUNC void load(int r, SValue *sv)
|
||||
o(0x808b | REG_VALUE(r) * 0x900); /* mov $xx(r), r */
|
||||
gen_gotpcrel(r, sv->sym, fc);
|
||||
}
|
||||
} else
|
||||
|
||||
#endif
|
||||
if (v == VT_CONST) {
|
||||
} else if (v == VT_CONST) {
|
||||
o(0xb8 + r); /* mov $xx, r */
|
||||
gen_addr32(fr, sv->sym, fc);
|
||||
} else if (v == VT_LOCAL) {
|
||||
@ -430,7 +426,7 @@ ST_FUNC void store(int r, SValue *v)
|
||||
#if defined CONFIG_TCC_PIC
|
||||
/* we need to access the variable via got */
|
||||
if ((v->r & (VT_VALMASK|VT_SYM)) == (VT_CONST|VT_SYM)
|
||||
&& !(v->sym->type.t & VT_STATIC)) {
|
||||
&& !(v->sym->type.t & (VT_STATIC|VT_TLS))) {
|
||||
get_pc_thunk(TREG_EBX, 1);
|
||||
o(0x9b8b); /* mov xx(%ebx),%ebx */
|
||||
gen_gotpcrel(TREG_EBX, v->sym, v->c.i);
|
||||
@ -439,16 +435,6 @@ ST_FUNC void store(int r, SValue *v)
|
||||
} else
|
||||
#endif
|
||||
|
||||
if ((v->r & VT_SYM) && v->sym->type.t & VT_TLS) {
|
||||
o(0x65); /* gs segment prefix */
|
||||
o(opc);
|
||||
o(0x04 | (REG_VALUE(r) << 3)); /* modrm: [sib] | srcreg */
|
||||
o(0x25); /* sib: disp32 */
|
||||
greloca(cur_text_section, v->sym, ind, R_386_TLS_LE, fc);
|
||||
gen_le32(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) {
|
||||
gen_modrm(opc, r, v->r, v->sym, fc);
|
||||
} else if (fr != r) {
|
||||
|
||||
216
x86_64-gen.c
216
x86_64-gen.c
@ -295,18 +295,27 @@ static void gen_gotpcrel(int r, Sym *sym, int c)
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_modrm_impl(int op_reg, int r, Sym *sym, int c, int is_got)
|
||||
/* generate a modrm reference. 'op_reg' contains the additional 3
|
||||
opcode rsp. second register bits */
|
||||
static void gen_modrm_impl(int opcode, int ll, int op_reg_0, int r, Sym *sym, int c)
|
||||
{
|
||||
op_reg = REG_VALUE(op_reg) << 3;
|
||||
int op_reg = REG_VALUE(op_reg_0) << 3;
|
||||
|
||||
orex(ll, r, op_reg_0, opcode);
|
||||
|
||||
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 if (sym->type.t & VT_TLS) {
|
||||
o(0x04 | op_reg); /* [sib] | destreg */
|
||||
oad(0x25, 0); /* disp32 (relocated) */
|
||||
greloca(cur_text_section, sym, ind - 4, R_X86_64_TPOFF32, c);
|
||||
} else {
|
||||
o(0x05 | op_reg); /* (%rip)+disp32 | destreg */
|
||||
if (is_got) {
|
||||
if (op_reg_0 & TREG_MEM) {
|
||||
gen_gotpcrel(r, sym, c);
|
||||
} else {
|
||||
gen_addrpc32(r, sym, c);
|
||||
@ -321,35 +330,26 @@ static void gen_modrm_impl(int op_reg, int r, Sym *sym, int c, int is_got)
|
||||
} else {
|
||||
oad(0x85 | op_reg, c);
|
||||
}
|
||||
} else if ((r & VT_VALMASK) >= TREG_MEM) {
|
||||
if (c) {
|
||||
g(0x80 | op_reg | REG_VALUE(r));
|
||||
gen_le32(c);
|
||||
} else {
|
||||
g(0x00 | op_reg | REG_VALUE(r));
|
||||
}
|
||||
} else {
|
||||
/* 'c' (mostly from vtop->c.i) is not valid unless when TREG_MEM is set */
|
||||
} else if ((r & TREG_MEM) && c) {
|
||||
g(0x80 | op_reg | REG_VALUE(r));
|
||||
gen_le32(c);
|
||||
} else if (r & VT_LVAL) {
|
||||
g(0x00 | op_reg | REG_VALUE(r));
|
||||
} else {
|
||||
g(0xc0 | op_reg | REG_VALUE(r));
|
||||
}
|
||||
}
|
||||
|
||||
/* generate a modrm reference. 'op_reg' contains the additional 3
|
||||
opcode bits */
|
||||
static void gen_modrm(int op_reg, int r, Sym *sym, int c)
|
||||
{
|
||||
gen_modrm_impl(op_reg, r, sym, c, 0);
|
||||
}
|
||||
|
||||
/* generate a modrm reference. 'op_reg' contains the additional 3
|
||||
opcode bits */
|
||||
static void gen_modrm64(int opcode, int op_reg, int r, Sym *sym, int c)
|
||||
{
|
||||
int is_got;
|
||||
is_got = (op_reg & TREG_MEM) && !(sym->type.t & VT_STATIC);
|
||||
orex(1, r, op_reg, opcode);
|
||||
gen_modrm_impl(op_reg, r, sym, c, is_got);
|
||||
gen_modrm_impl(opcode, 1, op_reg, r, sym, c);
|
||||
}
|
||||
|
||||
static void gen_modrm32(int opcode, int op_reg, int r, Sym *sym, int c)
|
||||
{
|
||||
gen_modrm_impl(opcode, 0, op_reg, r, sym, c);
|
||||
}
|
||||
|
||||
/* load 'r' from value 'sv' */
|
||||
void load(int r, SValue *sv)
|
||||
@ -358,18 +358,16 @@ void load(int r, SValue *sv)
|
||||
SValue v1;
|
||||
|
||||
fr = sv->r;
|
||||
ft = sv->type.t & ~VT_DEFSIGN;
|
||||
ft = sv->type.t & ~(VT_DEFSIGN|VT_VOLATILE|VT_CONSTANT);
|
||||
fc = sv->c.i;
|
||||
|
||||
if (fc != sv->c.i && (fr & VT_SYM))
|
||||
tcc_error("64 bit addend in load");
|
||||
|
||||
ft &= ~(VT_VOLATILE | VT_CONSTANT);
|
||||
|
||||
#ifndef TCC_TARGET_PE
|
||||
/* we use indirect access via got */
|
||||
if ((fr & VT_VALMASK) == VT_CONST && (fr & VT_SYM) &&
|
||||
(fr & VT_LVAL) && !(sv->sym->type.t & VT_STATIC)
|
||||
&& !(sv->sym->type.t & VT_TLS)) {
|
||||
if ((fr & (VT_VALMASK|VT_SYM|VT_LVAL)) == (VT_CONST|VT_SYM|VT_LVAL)
|
||||
&& !(sv->sym->type.t & (VT_STATIC|VT_TLS))) {
|
||||
/* use the result register as a temporal register */
|
||||
int tr = r | TREG_MEM;
|
||||
if (is_float(ft)) {
|
||||
@ -386,19 +384,6 @@ void load(int r, SValue *sv)
|
||||
v = fr & VT_VALMASK;
|
||||
if (fr & VT_LVAL) {
|
||||
int b, ll;
|
||||
if ((fr & VT_SYM) && sv->sym->type.t & VT_TLS) {
|
||||
int dst_reg = REG_VALUE(r);
|
||||
int is64 = is64_type(ft);
|
||||
o(0x64); /* fs segment prefix */
|
||||
if (is64 || REX_BASE(r))
|
||||
o(0x40 | (REX_BASE(r) << 0) | (is64 << 3)); /* rex.w/rex.r */
|
||||
o(0x8b); /* mov r/m, r */
|
||||
o(0x04 | (dst_reg << 3)); /* modrm: [sib] | destreg */
|
||||
o(0x25); /* sib: disp32 */
|
||||
greloca(cur_text_section, sv->sym, ind, R_X86_64_TPOFF32, fc);
|
||||
gen_le32(0);
|
||||
return;
|
||||
}
|
||||
if (v == VT_LLOCAL) {
|
||||
v1.type.t = VT_PTR;
|
||||
v1.r = VT_LOCAL | VT_LVAL;
|
||||
@ -408,6 +393,7 @@ void load(int r, SValue *sv)
|
||||
if (!(reg_classes[fr] & (RC_INT|RC_R11)))
|
||||
fr = get_reg(RC_INT);
|
||||
load(fr, &v1);
|
||||
fr |= VT_LVAL;
|
||||
}
|
||||
if (fc != sv->c.i) {
|
||||
/* If the addends doesn't fit into a 32bit signed
|
||||
@ -468,12 +454,9 @@ void load(int r, SValue *sv)
|
||||
ll = is64_type(ft);
|
||||
b = 0x8b;
|
||||
}
|
||||
if (ll) {
|
||||
gen_modrm64(b, r, fr, sv->sym, fc);
|
||||
} else {
|
||||
orex(ll, fr, r, b);
|
||||
gen_modrm(r, fr, sv->sym, fc);
|
||||
}
|
||||
if ((sv->r & VT_SYM) && (sv->sym->type.t & VT_TLS))
|
||||
o(0x64); /* fs segment prefix */
|
||||
gen_modrm_impl(b, ll, r, fr, sv->sym, fc);
|
||||
} else {
|
||||
if (v == VT_CONST) {
|
||||
if (fr & VT_SYM) {
|
||||
@ -482,7 +465,13 @@ void load(int r, SValue *sv)
|
||||
o(0x05 + REG_VALUE(r) * 8); /* lea xx(%rip), r */
|
||||
gen_addrpc32(fr, sv->sym, fc);
|
||||
#else
|
||||
if (sv->sym->type.t & VT_STATIC) {
|
||||
if (sv->sym->type.t & VT_TLS) {
|
||||
/* mov fs:0, r */
|
||||
o(0x64), gen_modrm64(0x8b, r, VT_CONST, NULL, 0);
|
||||
/* add $tpoff,r */
|
||||
orex(1,0,r,0x81), oad(0xC0 | REG_VALUE(r), 0);
|
||||
greloca(cur_text_section, sv->sym, ind - 4, R_X86_64_TPOFF32, fc);
|
||||
} else if (sv->sym->type.t & VT_STATIC) {
|
||||
orex(1,0,r,0x8d);
|
||||
o(0x05 + REG_VALUE(r) * 8); /* lea xx(%rip), r */
|
||||
gen_addrpc32(fr, sv->sym, fc);
|
||||
@ -508,8 +497,7 @@ void load(int r, SValue *sv)
|
||||
gen_le32(fc);
|
||||
}
|
||||
} else if (v == VT_LOCAL) {
|
||||
orex(1,0,r,0x8d); /* lea xxx(%ebp), r */
|
||||
gen_modrm(r, VT_LOCAL, sv->sym, fc);
|
||||
gen_modrm64(0x8d, r, VT_LOCAL, sv->sym, fc);
|
||||
} else if (v == VT_CMP) {
|
||||
if (fc & 0x100)
|
||||
{
|
||||
@ -573,91 +561,54 @@ void load(int r, SValue *sv)
|
||||
/* store register 'r' in lvalue 'v' */
|
||||
void store(int r, SValue *v)
|
||||
{
|
||||
int fr, bt, ft, fc;
|
||||
int op64 = 0;
|
||||
int fr, bt, fc;
|
||||
/* store the REX prefix in this variable when PIC is enabled */
|
||||
int pic = 0;
|
||||
int prefix = 0, opc = 0, seg = 0, ll = 0;
|
||||
|
||||
fr = v->r & VT_VALMASK;
|
||||
ft = v->type.t;
|
||||
fr = v->r;
|
||||
fc = v->c.i;
|
||||
if (fc != v->c.i && (fr & VT_SYM))
|
||||
tcc_error("64 bit addend in store");
|
||||
ft &= ~(VT_VOLATILE | VT_CONSTANT);
|
||||
bt = ft & VT_BTYPE;
|
||||
|
||||
if ((v->r & VT_SYM) && v->sym->type.t & VT_TLS) {
|
||||
int src_reg = REG_VALUE(r);
|
||||
int is64 = is64_type(bt);
|
||||
o(0x64);
|
||||
if (is64 || REX_BASE(r))
|
||||
o(0x40 | (REX_BASE(r) << 0) | (is64 << 3));
|
||||
o(0x89);
|
||||
o(0x04 | (src_reg << 3));
|
||||
o(0x25);
|
||||
greloca(cur_text_section, v->sym, ind, R_X86_64_TPOFF32, fc);
|
||||
gen_le32(0);
|
||||
return;
|
||||
}
|
||||
tcc_error("64 bit addend in store");
|
||||
bt = v->type.t & VT_BTYPE;
|
||||
|
||||
#ifndef TCC_TARGET_PE
|
||||
/* we need to access the variable via got */
|
||||
if (fr == VT_CONST
|
||||
&& (v->r & VT_SYM)
|
||||
&& !(v->sym->type.t & VT_STATIC)) {
|
||||
if ((fr & (VT_VALMASK|VT_SYM)) == (VT_CONST|VT_SYM)
|
||||
&& !(v->sym->type.t & (VT_STATIC|VT_TLS))) {
|
||||
/* mov xx(%rip), %r11 */
|
||||
o(0x1d8b4c);
|
||||
gen_gotpcrel(TREG_R11, v->sym, v->c.i);
|
||||
pic = is64_type(bt) ? 0x49 : 0x41;
|
||||
fr = TREG_R11 | VT_LVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* XXX: incorrect if float reg to reg */
|
||||
if (bt == VT_FLOAT) {
|
||||
o(0x66);
|
||||
o(pic);
|
||||
o(0x7e0f); /* movd */
|
||||
prefix = 0x66;
|
||||
opc = 0x7e0f;
|
||||
r = REG_VALUE(r);
|
||||
} else if (bt == VT_DOUBLE) {
|
||||
o(0x66);
|
||||
o(pic);
|
||||
o(0xd60f); /* movq */
|
||||
prefix = 0x66;
|
||||
opc = 0xd60f;
|
||||
r = REG_VALUE(r);
|
||||
} else if (bt == VT_LDOUBLE) {
|
||||
o(0xc0d9); /* fld %st(0) */
|
||||
o(pic);
|
||||
o(0xdb); /* fstpt */
|
||||
opc = 0xdb;
|
||||
r = 7;
|
||||
} else if (bt == VT_BYTE || bt == VT_BOOL) {
|
||||
opc = 0x88;
|
||||
} else {
|
||||
opc = 0x89;
|
||||
if (bt == VT_SHORT)
|
||||
o(0x66);
|
||||
o(pic);
|
||||
if (bt == VT_BYTE || bt == VT_BOOL)
|
||||
orex(0, 0, r, 0x88);
|
||||
prefix = 0x66;
|
||||
else if (is64_type(bt))
|
||||
op64 = 0x89;
|
||||
else
|
||||
orex(0, 0, r, 0x89);
|
||||
}
|
||||
if (pic) {
|
||||
/* xxx r, (%r11) where xxx is mov, movq, fld, or etc */
|
||||
if (op64)
|
||||
o(op64);
|
||||
o(3 + (r << 3));
|
||||
} else if (op64) {
|
||||
if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) {
|
||||
gen_modrm64(op64, r, v->r, v->sym, fc);
|
||||
} else if (fr != r) {
|
||||
orex(1, fr, r, op64);
|
||||
o(0xc0 + fr + r * 8); /* mov r, fr */
|
||||
}
|
||||
} else {
|
||||
if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) {
|
||||
gen_modrm(r, v->r, v->sym, fc);
|
||||
} else if (fr != r) {
|
||||
o(0xc0 + fr + r * 8); /* mov r, fr */
|
||||
}
|
||||
ll = 1;
|
||||
}
|
||||
|
||||
if ((fr & VT_SYM) && (v->sym->type.t & VT_TLS))
|
||||
seg = 0x64; /* fs segment prefix */
|
||||
|
||||
o(seg), o(prefix), gen_modrm_impl(opc, ll, r, fr, v->sym, fc);
|
||||
}
|
||||
|
||||
/* 'is_jmp' is '1' if it is a jump */
|
||||
@ -1002,8 +953,8 @@ void gfunc_prolog(Sym *func_sym)
|
||||
if ((bt == VT_FLOAT) || (bt == VT_DOUBLE)) {
|
||||
if (tcc_state->nosse)
|
||||
tcc_error("SSE disabled");
|
||||
o(0xd60f66); /* movq */
|
||||
gen_modrm(reg_param_index, VT_LOCAL, NULL, addr);
|
||||
/* movq */
|
||||
gen_modrm32(0xd60f66, reg_param_index, VT_LOCAL, NULL, addr);
|
||||
} else {
|
||||
gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
|
||||
}
|
||||
@ -1532,8 +1483,8 @@ void gfunc_prolog(Sym *func_sym)
|
||||
for (i = 0; i < 8; i++) {
|
||||
loc -= 16;
|
||||
if (!tcc_state->nosse) {
|
||||
o(0xd60f66); /* movq */
|
||||
gen_modrm(7 - i, VT_LOCAL, NULL, loc);
|
||||
/* movq */
|
||||
gen_modrm32(0xd60f66, 7 - i, VT_LOCAL, NULL, loc);
|
||||
}
|
||||
/* movq $0, loc+8(%rbp) */
|
||||
o(0x85c748);
|
||||
@ -1569,8 +1520,7 @@ void gfunc_prolog(Sym *func_sym)
|
||||
loc -= reg_count * 8;
|
||||
param_addr = loc;
|
||||
for (i = 0; i < reg_count; ++i) {
|
||||
o(0xd60f66); /* movq */
|
||||
gen_modrm(sse_param_index, VT_LOCAL, NULL, param_addr + i*8);
|
||||
gen_modrm32(0xd60f66, sse_param_index, VT_LOCAL, NULL, param_addr + i*8);
|
||||
++sse_param_index;
|
||||
}
|
||||
} else {
|
||||
@ -1844,7 +1794,7 @@ void gen_opl(int op)
|
||||
/* XXX: need to use ST1 too */
|
||||
void gen_opf(int op)
|
||||
{
|
||||
int a, ft, fc, swapped, r;
|
||||
int a, ft, fc, swapped, r, opc;
|
||||
int bt = vtop->type.t & VT_BTYPE;
|
||||
int float_type = bt == VT_LDOUBLE ? RC_ST0 : RC_FLOAT;
|
||||
|
||||
@ -1854,8 +1804,8 @@ void gen_opf(int op)
|
||||
o(0xe0d9); /* fchs */
|
||||
} else {
|
||||
save_reg(vtop->r);
|
||||
o(0x80); /* xor $0x80, $n(rbp) */
|
||||
gen_modrm(6, vtop->r, NULL, vtop->c.i + (bt == VT_DOUBLE ? 7 : 3));
|
||||
/* xor $0x80, $n(rbp) */
|
||||
gen_modrm32(0x80, 6, vtop->r, NULL, vtop->c.i + (bt == VT_DOUBLE ? 7 : 3));
|
||||
o(0x80);
|
||||
gv(float_type); /* -n is not a lvalue */
|
||||
}
|
||||
@ -1985,16 +1935,11 @@ void gen_opf(int op)
|
||||
if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
|
||||
o(0x66);
|
||||
if (op == TOK_EQ || op == TOK_NE)
|
||||
o(0x2e0f); /* ucomisd */
|
||||
opc = 0x2e0f; /* ucomisd */
|
||||
else
|
||||
o(0x2f0f); /* comisd */
|
||||
|
||||
if (vtop->r & VT_LVAL) {
|
||||
gen_modrm(vtop[-1].r, r, vtop->sym, fc);
|
||||
} else {
|
||||
o(0xc0 + REG_VALUE(vtop[0].r) + REG_VALUE(vtop[-1].r)*8);
|
||||
}
|
||||
opc = 0x2f0f; /* comisd */
|
||||
|
||||
gen_modrm32(opc, vtop[-1].r, vtop->r, vtop->sym, fc);
|
||||
vtop--;
|
||||
vset_VT_CMP(op | 0x100);
|
||||
vtop->cmp_r = op;
|
||||
@ -2019,7 +1964,6 @@ void gen_opf(int op)
|
||||
fc = vtop->c.i;
|
||||
assert((ft & VT_BTYPE) != VT_LDOUBLE);
|
||||
|
||||
r = vtop->r;
|
||||
/* if saved lvalue, then we must reload it */
|
||||
if ((vtop->r & VT_VALMASK) == VT_LLOCAL) {
|
||||
SValue v1;
|
||||
@ -2030,7 +1974,7 @@ void gen_opf(int op)
|
||||
v1.sym = NULL;
|
||||
load(r, &v1);
|
||||
fc = 0;
|
||||
vtop->r = r = r | VT_LVAL;
|
||||
vtop->r = r | VT_LVAL;
|
||||
}
|
||||
|
||||
assert(!(vtop[-1].r & VT_LVAL));
|
||||
@ -2039,7 +1983,6 @@ void gen_opf(int op)
|
||||
gv(RC_FLOAT);
|
||||
vswap();
|
||||
fc = vtop->c.i; /* bcheck may have saved previous vtop[-1] */
|
||||
r = vtop->r;
|
||||
}
|
||||
|
||||
if ((ft & VT_BTYPE) == VT_DOUBLE) {
|
||||
@ -2048,14 +1991,9 @@ void gen_opf(int op)
|
||||
o(0xf3);
|
||||
}
|
||||
o(0x0f);
|
||||
o(0x58 + a);
|
||||
opc = 0x58 + a;
|
||||
|
||||
if (vtop->r & VT_LVAL) {
|
||||
gen_modrm(vtop[-1].r, r, vtop->sym, fc);
|
||||
} else {
|
||||
o(0xc0 + REG_VALUE(vtop[0].r) + REG_VALUE(vtop[-1].r)*8);
|
||||
}
|
||||
|
||||
gen_modrm32(opc, vtop[-1].r, vtop->r, vtop->sym, fc);
|
||||
vtop--;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user