History

x86-64-asm: Clean up 64bit immediate support

Fix it to actually be able to parse 64bit immediates (enlarge operand value type). Then, generally there's no need for accepting IM64 anywhere, except in the 0xba+r mov opcodes, so OP_IM is unnecessary, as is OPT_IMNO64. Improve the generated code a bit by preferring the 0xc7 opcode for im32->reg64, instead of the im64->reg64 form (which we therefore hardcode).

Michael Matz committed 10 years ago

Commit b9f01df1 parent f3cee9c5 files · +39 −24Browse files

Unified · Split

5 files
  1. i386-asm.c +16 −18
  2. tcc.h +1 −1
  3. tccasm.c +2 −1
  4. tests/asmtest.S +10 −0
  5. x86_64-asm.h +10 −4
i386-asm.c+16−18
@@ -83,13 +83,10 @@ enum { · 82 unmodified lines
83 OPT_INDIR, /* *(expr) */83 OPT_INDIR, /* *(expr) */
84 /* composite types */84 /* composite types */
85 OPT_COMPOSITE_FIRST,85 OPT_COMPOSITE_FIRST,
86 OPT_IM, /* IM8 | IM16 | IM32 | IM64 */86 OPT_IM, /* IM8 | IM16 | IM32 */
87 OPT_REG, /* REG8 | REG16 | REG32 | REG64 */87 OPT_REG, /* REG8 | REG16 | REG32 | REG64 */
88 OPT_REGW, /* REG16 | REG32 | REG64 */88 OPT_REGW, /* REG16 | REG32 | REG64 */
89 OPT_IMW, /* IM16 | IM32 | IM64 */89 OPT_IMW, /* IM16 | IM32 */
90#ifdef TCC_TARGET_X86_64
91 OPT_IMNO64, /* IM16 | IM32 */
92#endif
93 /* can be ored with any OPT_xxx */90 /* can be ored with any OPT_xxx */
94 OPT_EA = 0x8091 OPT_EA = 0x80
95};92};
@@ -128,12 +125,10 @@ enum { · 32 unmodified lines
128#define OP_REG (OP_REG8 | OP_REG16 | OP_REG32 | OP_REG64)125#define OP_REG (OP_REG8 | OP_REG16 | OP_REG32 | OP_REG64)
129 126
130#ifdef TCC_TARGET_X86_64127#ifdef TCC_TARGET_X86_64
131# define OP_IM OP_IM64
132# define TREG_XAX TREG_RAX128# define TREG_XAX TREG_RAX
133# define TREG_XCX TREG_RCX129# define TREG_XCX TREG_RCX
134# define TREG_XDX TREG_RDX130# define TREG_XDX TREG_RDX
135#else131#else
136# define OP_IM OP_IM32
137# define TREG_XAX TREG_EAX132# define TREG_XAX TREG_EAX
138# define TREG_XCX TREG_ECX133# define TREG_XCX TREG_ECX
139# define TREG_XDX TREG_EDX134# define TREG_XDX TREG_EDX
@@ -347,7 +342,7 @@ static void parse_operand(TCCState *s1, Operand *op) · 207 unmodified lines
347 /* constant value */342 /* constant value */
348 next();343 next();
349 asm_expr(s1, &e);344 asm_expr(s1, &e);
350 op->type = OP_IM;345 op->type = OP_IM32;
351 op->e.v = e.v;346 op->e.v = e.v;
352 op->e.sym = e.sym;347 op->e.sym = e.sym;
353 if (!op->e.sym) {348 if (!op->e.sym) {
@@ -358,8 +353,8 @@ static void parse_operand(TCCState *s1, Operand *op) · 4 unmodified lines
358 if (op->e.v == (uint16_t)op->e.v)353 if (op->e.v == (uint16_t)op->e.v)
359 op->type |= OP_IM16;354 op->type |= OP_IM16;
360#ifdef TCC_TARGET_X86_64355#ifdef TCC_TARGET_X86_64
361 if (op->e.v == (uint32_t)op->e.v)356 if (op->e.v != (uint32_t)op->e.v)
362 op->type |= OP_IM32;357 op->type = OP_IM64;
363#endif358#endif
364 }359 }
365 } else {360 } else {
@@ -587,6 +582,14 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) · 221 unmodified lines
587 }582 }
588 if (pa->nb_ops != nb_ops)583 if (pa->nb_ops != nb_ops)
589 continue;584 continue;
585#ifdef TCC_TARGET_X86_64
586 /* Special case for moves. Selecting the IM64->REG64 form
587 should only be done if we really have an >32bit imm64, and that
588 is hardcoded. Ignore it here. */
589 if (pa->opcode == 0xb0 && ops[0].type != OP_IM64
590 && ops[1].type == OP_REG64)
591 continue;
592#endif
590 /* now decode and check each operand */593 /* now decode and check each operand */
591 alltypes = 0;594 alltypes = 0;
592 for(i = 0; i < nb_ops; i++) {595 for(i = 0; i < nb_ops; i++) {
@@ -595,7 +598,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) · 2 unmodified lines
595 op2 = op1 & 0x1f;598 op2 = op1 & 0x1f;
596 switch(op2) {599 switch(op2) {
597 case OPT_IM:600 case OPT_IM:
598 v = OP_IM8 | OP_IM16 | OP_IM32 | OP_IM64;601 v = OP_IM8 | OP_IM16 | OP_IM32;
599 break;602 break;
600 case OPT_REG:603 case OPT_REG:
601 v = OP_REG8 | OP_REG16 | OP_REG32 | OP_REG64;604 v = OP_REG8 | OP_REG16 | OP_REG32 | OP_REG64;
@@ -604,13 +607,8 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) · 2 unmodified lines
604 v = OP_REG16 | OP_REG32 | OP_REG64;607 v = OP_REG16 | OP_REG32 | OP_REG64;
605 break;608 break;
606 case OPT_IMW:609 case OPT_IMW:
607 v = OP_IM16 | OP_IM32 | OP_IM64;
608 break;
609#ifdef TCC_TARGET_X86_64
610 case OPT_IMNO64:
611 v = OP_IM16 | OP_IM32;610 v = OP_IM16 | OP_IM32;
612 break;611 break;
613#endif
614 default:612 default:
615 v = 1 << op2;613 v = 1 << op2;
616 break;614 break;
@@ -647,7 +645,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) · 30 unmodified lines
647#ifdef TCC_TARGET_X86_64645#ifdef TCC_TARGET_X86_64
648 /* XXX the autosize should rather be zero, to not have to adjust this646 /* XXX the autosize should rather be zero, to not have to adjust this
649 all the time. */647 all the time. */
650 if ((pa->instr_type & OPC_WLQ) != OPC_WLQ)648 if ((pa->instr_type & OPC_BWLQ) == OPC_B)
651 autosize = NBWLX-2;649 autosize = NBWLX-2;
652#endif650#endif
653 if (s == autosize) {651 if (s == autosize) {
@@ -657,7 +655,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) · 3 unmodified lines
657 }655 }
658 if (s == autosize) {656 if (s == autosize) {
659 if ((opcode == TOK_ASM_push || opcode == TOK_ASM_pop) &&657 if ((opcode == TOK_ASM_push || opcode == TOK_ASM_pop) &&
660 (ops[0].type & (OP_SEG | OP_IM8S | OP_IM32 | OP_IM64)))658 (ops[0].type & (OP_SEG | OP_IM8S | OP_IM32)))
661 s = 2;659 s = 2;
662 else660 else
663 tcc_error("cannot infer opcode suffix");661 tcc_error("cannot infer opcode suffix");
tcc.h+1−1
@@ -610,7 +610,7 @@ typedef struct CachedInclude { · 609 unmodified lines
610 610
611#ifdef CONFIG_TCC_ASM611#ifdef CONFIG_TCC_ASM
612typedef struct ExprValue {612typedef struct ExprValue {
613 uint32_t v;613 uint64_t v;
614 Sym *sym;614 Sym *sym;
615} ExprValue;615} ExprValue;
616 616
tccasm.c+2−1
@@ -41,7 +41,8 @@ static Sym sym_dot; · 40 unmodified lines
41static void asm_expr_unary(TCCState *s1, ExprValue *pe)41static void asm_expr_unary(TCCState *s1, ExprValue *pe)
42{42{
43 Sym *sym;43 Sym *sym;
44 int op, n, label;44 int op, label;
45 long n;
45 const char *p;46 const char *p;
46 47
47 switch(tok) {48 switch(tok) {
tests/asmtest.S+10−0
@@ -46,6 +46,16 @@ movl %eax, 0x100(%ebx,%edx,2) · 45 unmodified lines
46movl 0x100(%ebx,%edx,2), %edx46movl 0x100(%ebx,%edx,2), %edx
47movw %ax, 0x100(%ebx,%edx,2)47movw %ax, 0x100(%ebx,%edx,2)
48 48
49movw $0x1122,%si
50movl $0x112233,%edx
51#ifdef __x86_64__
52mov $0x11223344,%rbx
53movq $0x11223344,%rbx
54mov $0x1122334455,%rbx
55movq $0x1122334455,%rbx
56movl $0x11334455,(%rbx)
57#endif
58
49mov %eax, 0x12(,%edx,2)59mov %eax, 0x12(,%edx,2)
50 60
51#ifdef __i386__61#ifdef __i386__
x86_64-asm.h+10−4
@@ -97,7 +97,13 @@ ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWLQ, OPT_ADDR, OPT_EAX)) · 96 unmodified lines
97ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWLQ, OPT_EAX, OPT_ADDR)) */97ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWLQ, OPT_EAX, OPT_ADDR)) */
98ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWLQ, OPT_REG, OPT_EA | OPT_REG))98ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWLQ, OPT_REG, OPT_EA | OPT_REG))
99ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWLQ, OPT_EA | OPT_REG, OPT_REG))99ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWLQ, OPT_EA | OPT_REG, OPT_REG))
100/* The moves are special: the 0xb8 form supports IM64 (the only insn that
101 does) with REG64. It doesn't support IM32 with REG64, it would use
102 the full movabs form (64bit immediate). For IM32->REG64 we prefer
103 the 0xc7 opcode. So disallow all 64bit forms and code the rest by hand. */
100ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWLQ, OPT_IM, OPT_REG))104ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWLQ, OPT_IM, OPT_REG))
105ALT(DEF_ASM_OP2(mov, 0x48b8, 0, OPC_REG, OPT_IM64, OPT_REG64))
106ALT(DEF_ASM_OP2(movq, 0x48b8, 0, OPC_REG, OPT_IM64, OPT_REG64))
101ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWLQ, OPT_IM, OPT_REG | OPT_EA))107ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWLQ, OPT_IM, OPT_REG | OPT_EA))
102 108
103ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WLQ, OPT_SEG, OPT_EA | OPT_REG))109ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WLQ, OPT_SEG, OPT_EA | OPT_REG))
@@ -156,14 +162,14 @@ ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32)) · 52 unmodified lines
156 /* arith */162 /* arith */
157ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWLQ, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */163ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWLQ, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
158ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWLQ, OPT_EA | OPT_REG, OPT_REG))164ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWLQ, OPT_EA | OPT_REG, OPT_REG))
159ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWLQ, OPT_IMNO64, OPT_EAX))165ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWLQ, OPT_IM, OPT_EAX))
160ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWLQ, OPT_IMNO64, OPT_EA | OPT_REG))166ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWLQ, OPT_IM, OPT_EA | OPT_REG))
161ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WLQ, OPT_IM8S, OPT_EA | OPT_REG))167ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WLQ, OPT_IM8S, OPT_EA | OPT_REG))
162 168
163ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLQ, OPT_REG, OPT_EA | OPT_REG))169ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLQ, OPT_REG, OPT_EA | OPT_REG))
164ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLQ, OPT_EA | OPT_REG, OPT_REG))170ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLQ, OPT_EA | OPT_REG, OPT_REG))
165ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWLQ, OPT_IMNO64, OPT_EAX))171ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWLQ, OPT_IM, OPT_EAX))
166ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWLQ, OPT_IMNO64, OPT_EA | OPT_REG))172ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWLQ, OPT_IM, OPT_EA | OPT_REG))
167 173
168ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWLQ, OPT_REG | OPT_EA))174ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWLQ, OPT_REG | OPT_EA))
169ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWLQ, OPT_REG | OPT_EA))175ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWLQ, OPT_REG | OPT_EA))

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