History

x86_64-asm: =m operand fixes

The problem was with tcctest.c: unsigned set; __asm__("btsl %1,%0" : "=m"(set) : "Ir"(20) : "cc"); when with tcc compiled with the HAVE_SELINUX option, run with tcc -run, it would use large addresses far beyond the 32bits range when tcc did not use the pc-relative mode for accessing 'set' in global data memory. In fact the assembler did not know about %rip at all. Changes: - memory operands use (%rax) not (%eax) - conversion from VT_LLOCAL: use type VT_PTR - support 'k' modifier - support %rip register - support X(%rip) pc-relative addresses The test in tcctest.c is from Michael Matz.

grischka committed 9 years ago

Commit 4a3741b1 parent 47fd8076 files · +81 −33Browse files

Unified · Split

6 files
  1. Makefile +1 −1
  2. i386-asm.c +48 −27
  3. i386-tok.h +1 −0
  4. tccasm.c +4 −2
  5. tccrun.c +2 −0
  6. tests/tcctest.c +25 −3
Makefile+1−1
@@ -176,7 +176,7 @@ $(ARM64_CROSS): $(ARM64_FILES) · 175 unmodified lines
176# libtcc generation and test176# libtcc generation and test
177ifndef ONE_SOURCE177ifndef ONE_SOURCE
178LIBTCC_OBJ = $(filter-out tcc.o,$(patsubst %.c,%.o,$(filter %.c,$(NATIVE_FILES))))178LIBTCC_OBJ = $(filter-out tcc.o,$(patsubst %.c,%.o,$(filter %.c,$(NATIVE_FILES))))
179LIBTCC_INC = $(filter %.h,$(CORE_FILES)) $(filter-out $(CORE_FILES),$(NATIVE_FILES))179LIBTCC_INC = $(filter %.h,$(CORE_FILES)) $(filter-out $(CORE_FILES) i386-asm.c,$(NATIVE_FILES))
180else180else
181LIBTCC_OBJ = libtcc.o181LIBTCC_OBJ = libtcc.o
182LIBTCC_INC = $(NATIVE_FILES)182LIBTCC_INC = $(NATIVE_FILES)
i386-asm.c+48−27
@@ -276,6 +276,8 @@ static int asm_parse_reg(int *type) · 275 unmodified lines
276 *type = OP_EA32;276 *type = OP_EA32;
277 } else if (tok >= TOK_ASM_rax && tok <= TOK_ASM_rdi) {277 } else if (tok >= TOK_ASM_rax && tok <= TOK_ASM_rdi) {
278 reg = tok - TOK_ASM_rax;278 reg = tok - TOK_ASM_rax;
279 } else if (tok == TOK_ASM_rip) {
280 reg = 8;
279#endif281#endif
280 } else {282 } else {
281 error_32:283 error_32:
@@ -444,7 +446,7 @@ static void gen_disp32(ExprValue *pe) · 162 unmodified lines
444}446}
445 447
446/* generate the modrm operand */448/* generate the modrm operand */
447static inline void asm_modrm(int reg, Operand *op)449static inline int asm_modrm(int reg, Operand *op)
448{450{
449 int mod, reg1, reg2, sib_reg1;451 int mod, reg1, reg2, sib_reg1;
450 452
@@ -459,6 +461,13 @@ static inline void asm_modrm(int reg, Operand *op) · 8 unmodified lines
459 g(0x05 + (reg << 3));461 g(0x05 + (reg << 3));
460#endif462#endif
461 gen_expr32(&op->e);463 gen_expr32(&op->e);
464#ifdef TCC_TARGET_X86_64
465 } else if (op->reg == 8) {
466 ExprValue *pe = &op->e;
467 g(0x05 + (reg << 3));
468 gen_addrpc32(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
469 return ind;
470#endif
462 } else {471 } else {
463 sib_reg1 = op->reg;472 sib_reg1 = op->reg;
464 /* fist compute displacement encoding */473 /* fist compute displacement encoding */
@@ -491,12 +500,13 @@ static inline void asm_modrm(int reg, Operand *op) · 26 unmodified lines
491 gen_expr32(&op->e);500 gen_expr32(&op->e);
492 }501 }
493 }502 }
503 return 0;
494}504}
495 505
496ST_FUNC void asm_opcode(TCCState *s1, int opcode)506ST_FUNC void asm_opcode(TCCState *s1, int opcode)
497{507{
498 const ASMInstr *pa;508 const ASMInstr *pa;
499 int i, modrm_index, reg, v, op1, seg_prefix;509 int i, modrm_index, reg, v, op1, seg_prefix, pc;
500 int nb_ops, s;510 int nb_ops, s;
501 Operand ops[MAX_OPERANDS], *pop;511 Operand ops[MAX_OPERANDS], *pop;
502 int op_type[3]; /* decoded op type */512 int op_type[3]; /* decoded op type */
@@ -802,6 +812,8 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) · 299 unmodified lines
802 } else {812 } else {
803 reg = (pa->instr_type >> OPC_GROUP_SHIFT) & 7;813 reg = (pa->instr_type >> OPC_GROUP_SHIFT) & 7;
804 }814 }
815
816 pc = 0;
805 if (pa->instr_type & OPC_MODRM) {817 if (pa->instr_type & OPC_MODRM) {
806 /* first look for an ea operand */818 /* first look for an ea operand */
807 for(i = 0;i < nb_ops; i++) {819 for(i = 0;i < nb_ops; i++) {
@@ -828,8 +840,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) · 20 unmodified lines
828 break;840 break;
829 }841 }
830 }842 }
831 843 pc = asm_modrm(reg, &ops[modrm_index]);
832 asm_modrm(reg, &ops[modrm_index]);
833 }844 }
834 845
835 /* emit constants */846 /* emit constants */
@@ -858,30 +869,29 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) · 22 unmodified lines
858 else869 else
859 v = OP_IM64;870 v = OP_IM64;
860 }871 }
872
873 if ((v & (OP_IM8 | OP_IM8S | OP_IM16)) && ops[i].e.sym)
874 tcc_error("cannot relocate");
875
861 if (v & (OP_IM8 | OP_IM8S)) {876 if (v & (OP_IM8 | OP_IM8S)) {
862 if (ops[i].e.sym)
863 goto error_relocate;
864 g(ops[i].e.v);877 g(ops[i].e.v);
865 } else if (v & OP_IM16) {878 } else if (v & OP_IM16) {
866 if (ops[i].e.sym)879 gen_le16(ops[i].e.v);
867 error_relocate:
868 tcc_error("cannot relocate");
869 else
870 gen_le16(ops[i].e.v);
871 } else {
872 if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) {
873 gen_disp32(&ops[i].e);
874 } else {
875#ifdef TCC_TARGET_X86_64880#ifdef TCC_TARGET_X86_64
876 if (v & OP_IM64)881 } else if (v & OP_IM64) {
877 gen_expr64(&ops[i].e);882 gen_expr64(&ops[i].e);
878 else
879#endif883#endif
880 gen_expr32(&ops[i].e);884 } else if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) {
881 }885 gen_disp32(&ops[i].e);
886 } else {
887 gen_expr32(&ops[i].e);
882 }888 }
883 }889 }
884 }890 }
891
892 /* after immediate operands, adjust pc-relative address */
893 if (pc)
894 *(int*)(text_section->data + pc - 4) -= ind - pc;
885}895}
886 896
887/* return the constraint priority (we allocate first the lowest897/* return the constraint priority (we allocate first the lowest
@@ -1189,17 +1199,20 @@ ST_FUNC void subst_asm_operand(CString *add_str, · 301 unmodified lines
1189 cstr_ccat(add_str, '$');1199 cstr_ccat(add_str, '$');
1190 if (r & VT_SYM) {1200 if (r & VT_SYM) {
1191 cstr_cat(add_str, get_tok_str(sv->sym->v, NULL), -1);1201 cstr_cat(add_str, get_tok_str(sv->sym->v, NULL), -1);
1192 if ((uint32_t)sv->c.i != 0) {1202 if ((uint32_t)sv->c.i == 0)
1193 cstr_ccat(add_str, '+');1203 goto no_offset;
1194 } else {1204 cstr_ccat(add_str, '+');
1195 return;
1196 }
1197 }1205 }
1198 val = sv->c.i;1206 val = sv->c.i;
1199 if (modifier == 'n')1207 if (modifier == 'n')
1200 val = -val;1208 val = -val;
1201 snprintf(buf, sizeof(buf), "%d", (int)sv->c.i);1209 snprintf(buf, sizeof(buf), "%d", (int)sv->c.i);
1202 cstr_cat(add_str, buf, -1);1210 cstr_cat(add_str, buf, -1);
1211 no_offset:;
1212#ifdef TCC_TARGET_X86_64
1213 if (r & VT_LVAL)
1214 cstr_cat(add_str, "(%rip)", -1);
1215#endif
1203 } else if ((r & VT_VALMASK) == VT_LOCAL) {1216 } else if ((r & VT_VALMASK) == VT_LOCAL) {
1204#ifdef TCC_TARGET_X86_641217#ifdef TCC_TARGET_X86_64
1205 snprintf(buf, sizeof(buf), "%d(%%rbp)", (int)sv->c.i);1218 snprintf(buf, sizeof(buf), "%d(%%rbp)", (int)sv->c.i);
@@ -1212,7 +1225,12 @@ ST_FUNC void subst_asm_operand(CString *add_str, · 6 unmodified lines
1212 if (reg >= VT_CONST)1225 if (reg >= VT_CONST)
1213 tcc_error("internal compiler error");1226 tcc_error("internal compiler error");
1214 snprintf(buf, sizeof(buf), "(%%%s)",1227 snprintf(buf, sizeof(buf), "(%%%s)",
1215 get_tok_str(TOK_ASM_eax + reg, NULL));1228#ifdef TCC_TARGET_X86_64
1229 get_tok_str(TOK_ASM_rax + reg, NULL)
1230#else
1231 get_tok_str(TOK_ASM_eax + reg, NULL)
1232#endif
1233 );
1216 cstr_cat(add_str, buf, -1);1234 cstr_cat(add_str, buf, -1);
1217 } else {1235 } else {
1218 /* register case */1236 /* register case */
@@ -1244,6 +1262,8 @@ ST_FUNC void subst_asm_operand(CString *add_str, · 25 unmodified lines
1244 size = -1;1262 size = -1;
1245 } else if (modifier == 'w') {1263 } else if (modifier == 'w') {
1246 size = 2;1264 size = 2;
1265 } else if (modifier == 'k') {
1266 size = 4;
1247#ifdef TCC_TARGET_X86_641267#ifdef TCC_TARGET_X86_64
1248 } else if (modifier == 'q') {1268 } else if (modifier == 'q') {
1249 size = 8;1269 size = 8;
@@ -1311,7 +1331,8 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, · 61 unmodified lines
1311 output cases) */1331 output cases) */
1312 SValue sv;1332 SValue sv;
1313 sv = *op->vt;1333 sv = *op->vt;
1314 sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;1334 sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
1335 sv.type.t = VT_PTR;
1315 load(op->reg, &sv);1336 load(op->reg, &sv);
1316 } else if (i >= nb_outputs || op->is_rw) {1337 } else if (i >= nb_outputs || op->is_rw) {
1317 /* load value in register */1338 /* load value in register */
i386-tok.h+1−0
@@ -35,6 +35,7 @@ · 34 unmodified lines
35 DEF_ASM(rbp)35 DEF_ASM(rbp)
36 DEF_ASM(rsi)36 DEF_ASM(rsi)
37 DEF_ASM(rdi)37 DEF_ASM(rdi)
38 DEF_ASM(rip)
38#endif39#endif
39 DEF_ASM(mm0)40 DEF_ASM(mm0)
40 DEF_ASM(mm1)41 DEF_ASM(mm1)
tccasm.c+4−2
@@ -977,7 +977,8 @@ static void subst_asm_operands(ASMOperand *operands, int nb_operands, · 976 unmodified lines
977 }977 }
978 modifier = 0;978 modifier = 0;
979 if (*str == 'c' || *str == 'n' ||979 if (*str == 'c' || *str == 'n' ||
980 *str == 'b' || *str == 'w' || *str == 'h')980 *str == 'b' || *str == 'w' ||
981 *str == 'h' || *str == 'k')
981 modifier = *str++;982 modifier = *str++;
982 index = find_constraint(operands, nb_operands, str, &str);983 index = find_constraint(operands, nb_operands, str, &str);
983 if (index < 0)984 if (index < 0)
@@ -1029,7 +1030,8 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr, · 45 unmodified lines
1029 skip('(');1030 skip('(');
1030 gexpr();1031 gexpr();
1031 if (is_output) {1032 if (is_output) {
1032 test_lvalue();1033 if (!(vtop->type.t & VT_ARRAY))
1034 test_lvalue();
1033 } else {1035 } else {
1034 /* we want to avoid LLOCAL case, except when the 'm'1036 /* we want to avoid LLOCAL case, except when the 'm'
1035 constraint is used. Note that it may come from1037 constraint is used. Note that it may come from
tccrun.c+2−0
@@ -52,6 +52,8 @@ static void *win64_add_function_table(TCCState *s1); · 51 unmodified lines
52static void win64_del_function_table(void *);52static void win64_del_function_table(void *);
53#endif53#endif
54 54
55// #define HAVE_SELINUX
56
55/* ------------------------------------------------------------- */57/* ------------------------------------------------------------- */
56/* Do all relocations (needed before using tcc_get_symbol())58/* Do all relocations (needed before using tcc_get_symbol())
57 Returns -1 on error. */59 Returns -1 on error. */
tests/tcctest.c+25−3
@@ -2565,12 +2565,33 @@ static __inline__ unsigned long long inc64(unsigned long long a) · 2564 unmodified lines
2565 return res;2565 return res;
2566}2566}
2567 2567
2568struct struct123 {
2569 int a;
2570 int b;
2571};
2572struct struct1231 {
2573 unsigned long addr;
2574};
2575
2576unsigned long mconstraint_test(struct struct1231 *r)
2577{
2578 unsigned long ret;
2579 unsigned int a[2];
2580 a[0] = 0;
2581 __asm__ volatile ("lea %2,%0; movl 4(%0),%k0; addl %2,%k0; movl $51,%2; movl $52,4%2; movl $63,%1"
2582 : "=&r" (ret), "=m" (a)
2583 : "m" (*(struct struct123 *)r->addr));
2584 return ret + a[0];
2585}
2586
2568unsigned int set;2587unsigned int set;
2569 2588
2570void asm_test(void)2589void asm_test(void)
2571{2590{
2572 char buf[128];2591 char buf[128];
2573 unsigned int val;2592 unsigned int val;
2593 struct struct123 s1;
2594 struct struct1231 s2 = { (unsigned long)&s1 };
2574 2595
2575 printf("inline asm:\n");2596 printf("inline asm:\n");
2576 2597
@@ -2592,6 +2613,10 @@ void asm_test(void) · 15 unmodified lines
2592 printf("mul64=0x%Lx\n", mul64(0x12345678, 0xabcd1234));2613 printf("mul64=0x%Lx\n", mul64(0x12345678, 0xabcd1234));
2593 printf("inc64=0x%Lx\n", inc64(0x12345678ffffffff));2614 printf("inc64=0x%Lx\n", inc64(0x12345678ffffffff));
2594 2615
2616 s1.a = 42;
2617 s1.b = 43;
2618 printf("mconstraint: %d", mconstraint_test(&s2));
2619 printf(" %d %d\n", s1.a, s1.b);
2595 set = 0xff;2620 set = 0xff;
2596 sigdelset1(&set, 2);2621 sigdelset1(&set, 2);
2597 sigaddset1(&set, 16);2622 sigaddset1(&set, 16);
@@ -2600,9 +2625,6 @@ void asm_test(void) · 2 unmodified lines
2600 goto label1;2625 goto label1;
2601 label2:2626 label2:
2602 __asm__("btsl %1,%0" : "=m"(set) : "Ir"(20) : "cc");2627 __asm__("btsl %1,%0" : "=m"(set) : "Ir"(20) : "cc");
2603#ifdef __GNUC__ // works strange with GCC 4.3
2604 set=0x1080fd;
2605#endif
2606 printf("set=0x%x\n", set);2628 printf("set=0x%x\n", set);
2607 val = 0x01020304;2629 val = 0x01020304;
2608 printf("swab32(0x%08x) = 0x%0x\n", val, swab32(val));2630 printf("swab32(0x%08x) = 0x%0x\n", val, swab32(val));

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t