History

x86-64-asm: Fix mov im64,rax encoding

the avoidance of mov im32->reg64 wasn't working when reg64 was rax. While fixing this also fix instructions which had the REX prefix hardcoded in opcode and so didn't support extended registers which would have added another REX prefix.

Michael Matz committed 9 years ago

Commit 3e4c2961 parent e209b7d3 files · +33 −13Browse files

Unified · Split

3 files
  1. i386-asm.c +7 −4
  2. tests/asmtest.S +17 −0
  3. x86_64-asm.h +9 −9
i386-asm.c+7−4
@@ -42,6 +42,7 @@ · 41 unmodified lines
42#define OPCT_IS(v,i) (((v) & OPCT_MASK) == (i))42#define OPCT_IS(v,i) (((v) & OPCT_MASK) == (i))
43 43
44#define OPC_0F 0x100 /* Is secondary map (0x0f prefix) */44#define OPC_0F 0x100 /* Is secondary map (0x0f prefix) */
45#define OPC_48 0x200 /* Always has REX prefix */
45#ifdef TCC_TARGET_X86_6446#ifdef TCC_TARGET_X86_64
46# define OPC_WLQ 0x1000 /* accepts w, l, q or no suffix */47# define OPC_WLQ 0x1000 /* accepts w, l, q or no suffix */
47# define OPC_BWLQ (OPC_B | OPC_WLQ) /* accepts b, w, l, q or no suffix */48# define OPC_BWLQ (OPC_B | OPC_WLQ) /* accepts b, w, l, q or no suffix */
@@ -785,7 +786,7 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) · 737 unmodified lines
785 should only be done if we really have an >32bit imm64, and that786 should only be done if we really have an >32bit imm64, and that
786 is hardcoded. Ignore it here. */787 is hardcoded. Ignore it here. */
787 if (pa->opcode == 0xb0 && ops[0].type != OP_IM64788 if (pa->opcode == 0xb0 && ops[0].type != OP_IM64
788 && ops[1].type == OP_REG64789 && (ops[1].type & OP_REG) == OP_REG64
789 && !(pa->instr_type & OPC_0F))790 && !(pa->instr_type & OPC_0F))
790 continue;791 continue;
791#endif792#endif
@@ -901,14 +902,16 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) · 109 unmodified lines
901 g(0x66);902 g(0x66);
902#ifdef TCC_TARGET_X86_64903#ifdef TCC_TARGET_X86_64
903 rex64 = 0;904 rex64 = 0;
904 if (s == 3 || (alltypes & OP_REG64)) {905 if (pa->instr_type & OPC_48)
906 rex64 = 1;
907 else if (s == 3 || (alltypes & OP_REG64)) {
905 /* generate REX prefix */908 /* generate REX prefix */
906 int default64 = 0;909 int default64 = 0;
907 for(i = 0; i < nb_ops; i++) {910 for(i = 0; i < nb_ops; i++) {
908 if (op_type[i] == OP_REG64) {911 if (op_type[i] == OP_REG64 && pa->opcode != 0xb8) {
909 /* If only 64bit regs are accepted in one operand912 /* If only 64bit regs are accepted in one operand
910 this is a default64 instruction without need for913 this is a default64 instruction without need for
911 REX prefixes. */914 REX prefixes, except for movabs(0xb8). */
912 default64 = 1;915 default64 = 1;
913 break;916 break;
914 }917 }
tests/asmtest.S+17−0
@@ -114,12 +114,21 @@ notl %r15d · 113 unmodified lines
114 movzb 0x1000, %eax114 movzb 0x1000, %eax
115 movzb 0x1000, %ax115 movzb 0x1000, %ax
116 116
117 mov $0x12345678,%eax
118
117#ifdef __x86_64__119#ifdef __x86_64__
118 movzb 0x1000, %rax120 movzb 0x1000, %rax
119 movzbq 0x1000, %rbx121 movzbq 0x1000, %rbx
120 movsbq 0x1000, %rdx122 movsbq 0x1000, %rdx
121 movzwq 0x1000, %rdi123 movzwq 0x1000, %rdi
122 movswq 0x1000, %rdx124 movswq 0x1000, %rdx
125 movslq %eax, %rcx
126 mov $0x12345678,%rax
127 mov $0x12345678,%rdx
128 mov $0x12345678,%r10
129 mov $0x123456789abcdef0,%rax
130 mov $0x123456789abcdef0,%rcx
131 mov $0x123456789abcdef0,%r11
123#endif132#endif
124 133
125#ifdef __i386__134#ifdef __i386__
@@ -546,6 +555,7 @@ invlpg 0x1000 · 420 unmodified lines
546cmpxchg8b 0x1002555cmpxchg8b 0x1002
547#ifdef __x86_64__556#ifdef __x86_64__
548cmpxchg16b (%rax)557cmpxchg16b (%rax)
558cmpxchg16b (%r10,%r11)
549#endif559#endif
550 560
551fcmovb %st(5), %st561fcmovb %st(5), %st
@@ -569,6 +579,7 @@ fucomip %st(5), %st · 17 unmodified lines
569 cmovne %ax, %si579 cmovne %ax, %si
570#ifdef __x86_64__580#ifdef __x86_64__
571 bswapq %rsi581 bswapq %rsi
582 bswapq %r10
572 cmovz %rdi,%rbx583 cmovz %rdi,%rbx
573#endif584#endif
574 585
@@ -675,7 +686,9 @@ int $0x10 · 100 unmodified lines
675 prefetchw (%rdi)686 prefetchw (%rdi)
676 clflush 0x1000(%rax,%rcx)687 clflush 0x1000(%rax,%rcx)
677 fxsaveq (%rdx)688 fxsaveq (%rdx)
689 fxsaveq (%r11)
678 fxrstorq (%rcx)690 fxrstorq (%rcx)
691 fxrstorq (%r10)
679 692
680#endif693#endif
681 694
@@ -751,6 +764,9 @@ int $0x10 · 69 unmodified lines
751 sidtq 0x1000764 sidtq 0x1000
752 765
753 swapgs766 swapgs
767
768 str %rdx
769 str %r9
754#endif770#endif
755 771
756 lmsw 0x1000772 lmsw 0x1000
@@ -879,6 +895,7 @@ overrideme: · 122 unmodified lines
879#ifdef __x86_64__895#ifdef __x86_64__
880 movq %rcx, %mm1896 movq %rcx, %mm1
881 movq %rdx, %xmm2897 movq %rdx, %xmm2
898 movq %r13, %xmm3
882 /* movq mem64->xmm is encoded as f30f7e by GAS, but as899 /* movq mem64->xmm is encoded as f30f7e by GAS, but as
883 660f6e by tcc (which really is a movd and would need 900 660f6e by tcc (which really is a movd and would need
884 a REX.W prefix to be movq). */901 a REX.W prefix to be movq). */
x86_64-asm.h+9−9
@@ -106,8 +106,8 @@ ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG)) · 105 unmodified lines
106 the full movabs form (64bit immediate). For IM32->REG64 we prefer106 the full movabs form (64bit immediate). For IM32->REG64 we prefer
107 the 0xc7 opcode. So disallow all 64bit forms and code the rest by hand. */107 the 0xc7 opcode. So disallow all 64bit forms and code the rest by hand. */
108ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWLX, OPT_IM, OPT_REG))108ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWLX, OPT_IM, OPT_REG))
109ALT(DEF_ASM_OP2(mov, 0x48b8, 0, OPC_REG, OPT_IM64, OPT_REG64))109ALT(DEF_ASM_OP2(mov, 0xb8, 0, OPC_REG, OPT_IM64, OPT_REG64))
110ALT(DEF_ASM_OP2(movq, 0x48b8, 0, OPC_REG, OPT_IM64, OPT_REG64))110ALT(DEF_ASM_OP2(movq, 0xb8, 0, OPC_REG, OPT_IM64, OPT_REG64))
111ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWLX, OPT_IM, OPT_REG | OPT_EA))111ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWLX, OPT_IM, OPT_REG | OPT_EA))
112 112
113ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WLX, OPT_SEG, OPT_EA | OPT_REG))113ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WLX, OPT_SEG, OPT_EA | OPT_REG))
@@ -123,7 +123,7 @@ ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32)) · 9 unmodified lines
123ALT(DEF_ASM_OP2(movsbq, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REGW))123ALT(DEF_ASM_OP2(movsbq, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REGW))
124ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))124ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
125ALT(DEF_ASM_OP2(movswq, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG))125ALT(DEF_ASM_OP2(movswq, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG))
126ALT(DEF_ASM_OP2(movslq, 0x4863, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG))126ALT(DEF_ASM_OP2(movslq, 0x63, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG))
127ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WLX, OPT_REG8 | OPT_EA, OPT_REGW))127ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WLX, OPT_REG8 | OPT_EA, OPT_REGW))
128ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))128ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
129ALT(DEF_ASM_OP2(movzwq, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG))129ALT(DEF_ASM_OP2(movzwq, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG))
@@ -354,8 +354,8 @@ ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )) · 224 unmodified lines
354 If the operand would use extended registers we would have to modify354 If the operand would use extended registers we would have to modify
355 it instead of generating a second one. Currently that's no355 it instead of generating a second one. Currently that's no
356 problem with TCC, we don't use extended registers. */356 problem with TCC, we don't use extended registers. */
357 DEF_ASM_OP1(fxsaveq, 0x480fae, 0, OPC_MODRM, OPT_EA )357 DEF_ASM_OP1(fxsaveq, 0x0fae, 0, OPC_MODRM | OPC_48, OPT_EA )
358 DEF_ASM_OP1(fxrstorq, 0x480fae, 1, OPC_MODRM, OPT_EA )358 DEF_ASM_OP1(fxrstorq, 0x0fae, 1, OPC_MODRM | OPC_48, OPT_EA )
359 359
360 /* segments */360 /* segments */
361 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)361 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
@@ -376,7 +376,7 @@ ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WLX, OPT_EA | OPT_REG, OPT_REG) · 14 unmodified lines
376 DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)376 DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
377 DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG32 | OPT_EA)377 DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG32 | OPT_EA)
378ALT(DEF_ASM_OP1(str, 0x660f00, 1, OPC_MODRM, OPT_REG16))378ALT(DEF_ASM_OP1(str, 0x660f00, 1, OPC_MODRM, OPT_REG16))
379ALT(DEF_ASM_OP1(str, 0x480f00, 1, OPC_MODRM, OPT_REG64))379ALT(DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM | OPC_48, OPT_REG64))
380 DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)380 DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
381 DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)381 DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
382 DEF_ASM_OP0L(swapgs, 0x0f01, 7, OPC_MODRM)382 DEF_ASM_OP0L(swapgs, 0x0f01, 7, OPC_MODRM)
@@ -385,7 +385,7 @@ ALT(DEF_ASM_OP1(str, 0x480f00, 1, OPC_MODRM, OPT_REG64)) · 2 unmodified lines
385 /* bswap can't be applied to 16bit regs */385 /* bswap can't be applied to 16bit regs */
386 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )386 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
387 DEF_ASM_OP1(bswapl, 0x0fc8, 0, OPC_REG, OPT_REG32 )387 DEF_ASM_OP1(bswapl, 0x0fc8, 0, OPC_REG, OPT_REG32 )
388 DEF_ASM_OP1(bswapq, 0x480fc8, 0, OPC_REG, OPT_REG64 )388 DEF_ASM_OP1(bswapq, 0x0fc8, 0, OPC_REG | OPC_48, OPT_REG64 )
389 389
390ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_REG | OPT_EA ))390ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_REG | OPT_EA ))
391ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_REG | OPT_EA ))391ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_REG | OPT_EA ))
@@ -395,7 +395,7 @@ ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_REG | OP · 3 unmodified lines
395 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )395 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
396 396
397 /* AMD 64 */397 /* AMD 64 */
398 DEF_ASM_OP1(cmpxchg16b, 0x480fc7, 1, OPC_MODRM, OPT_EA )398 DEF_ASM_OP1(cmpxchg16b, 0x0fc7, 1, OPC_MODRM | OPC_48, OPT_EA )
399 399
400 /* pentium pro */400 /* pentium pro */
401ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))401ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))
@@ -420,7 +420,7 @@ ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST | OPC_WLX, OPT_REGW | OPT · 18 unmodified lines
420 /* movd shouldn't accept REG64, but AMD64 spec uses it for 32 and 64 bit420 /* movd shouldn't accept REG64, but AMD64 spec uses it for 32 and 64 bit
421 moves, so let's be compatible. */421 moves, so let's be compatible. */
422ALT(DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG64, OPT_MMXSSE ))422ALT(DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG64, OPT_MMXSSE ))
423ALT(DEF_ASM_OP2(movq, 0x480f6e, 0, OPC_MODRM, OPT_REG64, OPT_MMXSSE ))423ALT(DEF_ASM_OP2(movq, 0x0f6e, 0, OPC_MODRM | OPC_48, OPT_REG64, OPT_MMXSSE ))
424ALT(DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ))424ALT(DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ))
425ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMXSSE, OPT_EA | OPT_REG32 ))425ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMXSSE, OPT_EA | OPT_REG32 ))
426ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMXSSE, OPT_EA | OPT_REG64 ))426ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMXSSE, OPT_EA | OPT_REG64 ))

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