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
4242 #define OPCT_IS(v,i) (((v) & OPCT_MASK) == (i))
4343
4444 #define OPC_0F 0x100 /* Is secondary map (0x0f prefix) */
45+#define OPC_48 0x200 /* Always has REX prefix */
4546 #ifdef TCC_TARGET_X86_64
4647 # define OPC_WLQ 0x1000 /* accepts w, l, q or no suffix */
4748 # 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
785786 should only be done if we really have an >32bit imm64, and that
786787 is hardcoded. Ignore it here. */
787788 if (pa->opcode == 0xb0 && ops[0].type != OP_IM64
788− && ops[1].type == OP_REG64
789+ && (ops[1].type & OP_REG) == OP_REG64
789790 && !(pa->instr_type & OPC_0F))
790791 continue;
791792 #endif
@@ -901,14 +902,16 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) · 109 unmodified lines
901902 g(0x66);
902903 #ifdef TCC_TARGET_X86_64
903904 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)) {
905908 /* generate REX prefix */
906909 int default64 = 0;
907910 for(i = 0; i < nb_ops; i++) {
908− if (op_type[i] == OP_REG64) {
911+ if (op_type[i] == OP_REG64 && pa->opcode != 0xb8) {
909912 /* If only 64bit regs are accepted in one operand
910913 this is a default64 instruction without need for
911− REX prefixes. */
914+ REX prefixes, except for movabs(0xb8). */
912915 default64 = 1;
913916 break;
914917 }
tests/asmtest.S+17−0
@@ -114,12 +114,21 @@ notl %r15d · 113 unmodified lines
114114 movzb 0x1000, %eax
115115 movzb 0x1000, %ax
116116
117+ mov $0x12345678,%eax
118+
117119 #ifdef __x86_64__
118120 movzb 0x1000, %rax
119121 movzbq 0x1000, %rbx
120122 movsbq 0x1000, %rdx
121123 movzwq 0x1000, %rdi
122124 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
123132 #endif
124133
125134 #ifdef __i386__
@@ -546,6 +555,7 @@ invlpg 0x1000 · 420 unmodified lines
546555 cmpxchg8b 0x1002
547556 #ifdef __x86_64__
548557 cmpxchg16b (%rax)
558+cmpxchg16b (%r10,%r11)
549559 #endif
550560
551561 fcmovb %st(5), %st
@@ -569,6 +579,7 @@ fucomip %st(5), %st · 17 unmodified lines
569579 cmovne %ax, %si
570580 #ifdef __x86_64__
571581 bswapq %rsi
582+ bswapq %r10
572583 cmovz %rdi,%rbx
573584 #endif
574585
@@ -675,7 +686,9 @@ int $0x10 · 100 unmodified lines
675686 prefetchw (%rdi)
676687 clflush 0x1000(%rax,%rcx)
677688 fxsaveq (%rdx)
689+ fxsaveq (%r11)
678690 fxrstorq (%rcx)
691+ fxrstorq (%r10)
679692
680693 #endif
681694
@@ -751,6 +764,9 @@ int $0x10 · 69 unmodified lines
751764 sidtq 0x1000
752765
753766 swapgs
767+
768+ str %rdx
769+ str %r9
754770 #endif
755771
756772 lmsw 0x1000
@@ -879,6 +895,7 @@ overrideme: · 122 unmodified lines
879895 #ifdef __x86_64__
880896 movq %rcx, %mm1
881897 movq %rdx, %xmm2
898+ movq %r13, %xmm3
882899 /* movq mem64->xmm is encoded as f30f7e by GAS, but as
883900 660f6e by tcc (which really is a movd and would need
884901 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
106106 the full movabs form (64bit immediate). For IM32->REG64 we prefer
107107 the 0xc7 opcode. So disallow all 64bit forms and code the rest by hand. */
108108 ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWLX, OPT_IM, OPT_REG))
109−ALT(DEF_ASM_OP2(mov, 0x48b8, 0, OPC_REG, OPT_IM64, OPT_REG64))
110−ALT(DEF_ASM_OP2(movq, 0x48b8, 0, OPC_REG, OPT_IM64, OPT_REG64))
109+ALT(DEF_ASM_OP2(mov, 0xb8, 0, OPC_REG, OPT_IM64, OPT_REG64))
110+ALT(DEF_ASM_OP2(movq, 0xb8, 0, OPC_REG, OPT_IM64, OPT_REG64))
111111 ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWLX, OPT_IM, OPT_REG | OPT_EA))
112112
113113 ALT(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
123123 ALT(DEF_ASM_OP2(movsbq, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REGW))
124124 ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
125125 ALT(DEF_ASM_OP2(movswq, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG))
126−ALT(DEF_ASM_OP2(movslq, 0x4863, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG))
126+ALT(DEF_ASM_OP2(movslq, 0x63, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG))
127127 ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WLX, OPT_REG8 | OPT_EA, OPT_REGW))
128128 ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
129129 ALT(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
354354 If the operand would use extended registers we would have to modify
355355 it instead of generating a second one. Currently that's no
356356 problem with TCC, we don't use extended registers. */
357− DEF_ASM_OP1(fxsaveq, 0x480fae, 0, OPC_MODRM, OPT_EA )
358− DEF_ASM_OP1(fxrstorq, 0x480fae, 1, OPC_MODRM, OPT_EA )
357+ DEF_ASM_OP1(fxsaveq, 0x0fae, 0, OPC_MODRM | OPC_48, OPT_EA )
358+ DEF_ASM_OP1(fxrstorq, 0x0fae, 1, OPC_MODRM | OPC_48, OPT_EA )
359359
360360 /* segments */
361361 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
376376 DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
377377 DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG32 | OPT_EA)
378378 ALT(DEF_ASM_OP1(str, 0x660f00, 1, OPC_MODRM, OPT_REG16))
379−ALT(DEF_ASM_OP1(str, 0x480f00, 1, OPC_MODRM, OPT_REG64))
379+ALT(DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM | OPC_48, OPT_REG64))
380380 DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
381381 DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
382382 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
385385 /* bswap can't be applied to 16bit regs */
386386 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
387387 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 )
389389
390390 ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_REG | OPT_EA ))
391391 ALT(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
395395 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
396396
397397 /* 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 )
399399
400400 /* pentium pro */
401401 ALT(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
420420 /* movd shouldn't accept REG64, but AMD64 spec uses it for 32 and 64 bit
421421 moves, so let's be compatible. */
422422 ALT(DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG64, OPT_MMXSSE ))
423−ALT(DEF_ASM_OP2(movq, 0x480f6e, 0, OPC_MODRM, OPT_REG64, OPT_MMXSSE ))
423+ALT(DEF_ASM_OP2(movq, 0x0f6e, 0, OPC_MODRM | OPC_48, OPT_REG64, OPT_MMXSSE ))
424424 ALT(DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ))
425425 ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMXSSE, OPT_EA | OPT_REG32 ))
426426 ALT(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