diff --git a/arm-gen.c b/arm-gen.c index bba80189..3a65a7cc 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -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); diff --git a/arm64-gen.c b/arm64-gen.c index d537980f..f5a81231 100644 --- a/arm64-gen.c +++ b/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)); diff --git a/i386-gen.c b/i386-gen.c index d57c6ed1..4c6b86c9 100644 --- a/i386-gen.c +++ b/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) { diff --git a/x86_64-gen.c b/x86_64-gen.c index 5e6e96ca..efa28168 100644 --- a/x86_64-gen.c +++ b/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--; } }