* PATCH: Fix x86 segment register access
@ 2005-03-26 23:31 H. J. Lu
2005-03-28 10:21 ` i386/x86_64 segment register issuses (Re: PATCH: Fix x86 segment register access) H. J. Lu
0 siblings, 1 reply; 12+ messages in thread
From: H. J. Lu @ 2005-03-26 23:31 UTC (permalink / raw)
To: binutils
X86 segment register access is a special. We can move between a segment
register and a 16/32/64bit general-purpose register. But we can only
move between a segment register and a 16bit memory address. The current
assembler allows "movl (%eax),%ds", but doesn't allow "movq %rax,%ds".
The disassembler display "movl (%eax),%ds". This patch tries to fix
those.
H.J.
----
gas/testsuite/
2005-03-25 H.J. Lu <hongjiu.lu@intel.com>
* gas/i386/i386.exp: Run segment and inval-seg for i386. Run
x86-64-segment and x86-64-inval-seg for x86-64.
* gas/i386/intel.d: Expect movw for moving between memory and
segment register.
* gas/i386/naked.d: Likewise.
* gas/i386/opcode.d: Likewise.
* gas/i386/x86-64-opcode.d: Likewise.
* gas/i386/opcode.s: Use movw for moving between memory and
segment register.
* gas/i386/x86-64-opcode.s: Likewise.
* : Likewise.
* gas/i386/inval-seg.l: New.
* gas/i386/inval-seg.s: New.
* gas/i386/segment.l: New.
* gas/i386/segment.s: New.
* gas/i386/x86-64-inval-seg.l: New.
* gas/i386/x86-64-inval-seg.s: New.
* gas/i386/x86-64-segment.l: New.
* gas/i386/x86-64-segment.s: New.
include/opcode/
2005-03-25 H.J. Lu <hongjiu.lu@intel.com>
* i386.h (i386_optab): Don't allow the `l' suffix for moving
moving between memory and segment register. Allow movq for
moving between general-purpose register and segment register.
opcodes/
2005-03-25 H.J. Lu <hongjiu.lu@intel.com>
* i386-dis.c (SEG_Fixup): New.
(Sv): New.
(dis386): Use "Sv" for 0x8c and 0x8e.
--- binutils/gas/testsuite/gas/i386/i386.exp.seg 2005-03-02 11:54:52.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/i386.exp 2005-03-25 12:53:28.000000000 -0800
@@ -42,6 +42,8 @@ if [expr ([istarget "i*86-*-*"] || [ist
run_list_test "float" "-al"
run_list_test "general" "-al --listing-lhs-width=2"
run_list_test "inval" "-al"
+ run_list_test "segment" "-al"
+ run_list_test "inval-seg" "-al"
run_list_test "modrm" "-al --listing-lhs-width=2"
run_dump_test "naked"
run_dump_test "opcode"
@@ -120,6 +122,8 @@ if [expr ([istarget "i*86-*-*"] || [ista
run_dump_test "x86-64-opcode"
run_dump_test "x86-64-rip"
run_list_test "x86-64-inval" "-al"
+ run_list_test "x86-64-segment" "-al"
+ run_list_test "x86-64-inval-seg" "-al"
# For ELF targets verify that @unwind works.
if { ([istarget "*-*-elf*"] || [istarget "*-*-linux*"]
--- binutils/gas/testsuite/gas/i386/intel.d.seg 2005-03-17 12:31:19.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/intel.d 2005-03-25 17:42:46.416175591 -0800
@@ -138,9 +138,9 @@ Disassembly of section .text:
1a3: 89 90 90 90 90 90 [ ]*mov %edx,0x90909090\(%eax\)
1a9: 8a 90 90 90 90 90 [ ]*mov 0x90909090\(%eax\),%dl
1af: 8b 90 90 90 90 90 [ ]*mov 0x90909090\(%eax\),%edx
- 1b5: 8c 90 90 90 90 90 [ ]*movl %ss,0x90909090\(%eax\)
+ 1b5: 8c 90 90 90 90 90 [ ]*movw %ss,0x90909090\(%eax\)
1bb: 8d 90 90 90 90 90 [ ]*lea 0x90909090\(%eax\),%edx
- 1c1: 8e 90 90 90 90 90 [ ]*movl 0x90909090\(%eax\),%ss
+ 1c1: 8e 90 90 90 90 90 [ ]*movw 0x90909090\(%eax\),%ss
1c7: 8f 80 90 90 90 90 [ ]*popl 0x90909090\(%eax\)
1cd: 90 [ ]*nop
1ce: 91 [ ]*xchg %eax,%ecx
@@ -481,7 +481,7 @@ Disassembly of section .text:
7be: 66 87 90 90 90 90 90 [ ]*xchg %dx,0x90909090\(%eax\)
7c5: 66 89 90 90 90 90 90 [ ]*mov %dx,0x90909090\(%eax\)
7cc: 66 8b 90 90 90 90 90 [ ]*mov 0x90909090\(%eax\),%dx
- 7d3: 8c 90 90 90 90 90 [ ]*mov[l ] %ss,0x90909090\(%eax\)
+ 7d3: 8c 90 90 90 90 90 [ ]*mov[w ] %ss,0x90909090\(%eax\)
7d9: 66 8d 90 90 90 90 90 [ ]*lea 0x90909090\(%eax\),%dx
7e0: 66 8f 80 90 90 90 90 [ ]*popw 0x90909090\(%eax\)
7e7: 66 91 [ ]*xchg %ax,%cx
--- binutils/gas/testsuite/gas/i386/inval-seg.l.seg 2005-03-25 11:34:16.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/inval-seg.l 2005-03-25 11:58:22.000000000 -0800
@@ -0,0 +1,10 @@
+.*: Assembler messages:
+.*:3: Error: .*
+.*:4: Error: .*
+GAS LISTING .*
+
+
+ 1 [ ]* .text
+ 2 [ ]*# All the following should be illegal
+ 3 [ ]* movl %ds,\(%eax\)
+ 4 [ ]* movl \(%eax\),%ds
--- binutils/gas/testsuite/gas/i386/inval-seg.s.seg 2005-03-25 11:34:14.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/inval-seg.s 2005-03-25 11:33:22.000000000 -0800
@@ -0,0 +1,4 @@
+ .text
+# All the following should be illegal
+ movl %ds,(%eax)
+ movl (%eax),%ds
--- binutils/gas/testsuite/gas/i386/naked.d.seg 1999-08-31 13:09:58.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/naked.d 2005-03-25 17:40:20.371050512 -0800
@@ -11,8 +11,8 @@ Disassembly of section .text:
a: b2 20 [ ]*mov \$0x20,%dl
c: bb 00 00 00 00 [ ]*mov \$0x0,%ebx d: (R_386_)?(dir)?32 .text
11: d9 c9 [ ]*fxch %st\(1\)
- 13: 36 8c a4 81 d2 04 00 00 [ ]*movl %fs,%ss:0x4d2\(%ecx,%eax,4\)
- 1b: 8c 2c ed 00 00 00 00 [ ]*movl %gs,0x0\(,%ebp,8\)
+ 13: 36 8c a4 81 d2 04 00 00 [ ]*movw %fs,%ss:0x4d2\(%ecx,%eax,4\)
+ 1b: 8c 2c ed 00 00 00 00 [ ]*movw %gs,0x0\(,%ebp,8\)
22: 26 88 25 00 00 00 00 [ ]*mov %ah,%es:0x0
29: 2e 8b 74 14 80 [ ]*mov %cs:0xffffff80\(%esp,%edx,1\),%esi
2e: f3 65 a5 [ ]*repz movsl %gs:\(%esi\),%es:\(%edi\)
--- binutils/gas/testsuite/gas/i386/opcode.d.seg 2004-11-10 09:20:22.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/opcode.d 2005-03-25 17:41:11.042501717 -0800
@@ -137,9 +137,9 @@ Disassembly of section .text:
1a3: 89 90 90 90 90 90 [ ]*mov %edx,0x90909090\(%eax\)
1a9: 8a 90 90 90 90 90 [ ]*mov 0x90909090\(%eax\),%dl
1af: 8b 90 90 90 90 90 [ ]*mov 0x90909090\(%eax\),%edx
- 1b5: 8c 90 90 90 90 90 [ ]*movl %ss,0x90909090\(%eax\)
+ 1b5: 8c 90 90 90 90 90 [ ]*movw %ss,0x90909090\(%eax\)
1bb: 8d 90 90 90 90 90 [ ]*lea 0x90909090\(%eax\),%edx
- 1c1: 8e 90 90 90 90 90 [ ]*movl 0x90909090\(%eax\),%ss
+ 1c1: 8e 90 90 90 90 90 [ ]*movw 0x90909090\(%eax\),%ss
1c7: 8f 80 90 90 90 90 [ ]*popl 0x90909090\(%eax\)
1cd: 90 [ ]*nop
1ce: 91 [ ]*xchg %eax,%ecx
@@ -480,7 +480,7 @@ Disassembly of section .text:
7be: 66 87 90 90 90 90 90 [ ]*xchg %dx,0x90909090\(%eax\)
7c5: 66 89 90 90 90 90 90 [ ]*mov %dx,0x90909090\(%eax\)
7cc: 66 8b 90 90 90 90 90 [ ]*mov 0x90909090\(%eax\),%dx
- 7d3: 8c 90 90 90 90 90 [ ]*mov[l ] %ss,0x90909090\(%eax\)
+ 7d3: 8c 90 90 90 90 90 [ ]*mov[w ] %ss,0x90909090\(%eax\)
7d9: 66 8d 90 90 90 90 90 [ ]*lea 0x90909090\(%eax\),%dx
7e0: 66 8f 80 90 90 90 90 [ ]*popw 0x90909090\(%eax\)
7e7: 66 91 [ ]*xchg %ax,%cx
--- binutils/gas/testsuite/gas/i386/opcode.s.seg 2004-11-10 09:20:23.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/opcode.s 2005-03-25 12:00:28.000000000 -0800
@@ -130,9 +130,9 @@ foo:
mov %edx,0x90909090(%eax)
mov 0x90909090(%eax),%dl
mov 0x90909090(%eax),%edx
- movl %ss,0x90909090(%eax)
+ movw %ss,0x90909090(%eax)
lea 0x90909090(%eax),%edx
- movl 0x90909090(%eax),%ss
+ movw 0x90909090(%eax),%ss
popl 0x90909090(%eax)
xchg %eax,%eax
xchg %eax,%ecx
--- binutils/gas/testsuite/gas/i386/segment.l.seg 2005-03-25 11:18:47.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/segment.l 2005-03-25 11:26:35.000000000 -0800
@@ -0,0 +1,10 @@
+ 1 .psize 0
+ 2 .text
+ 3 # test segment reg insns with memory operand
+ 4 0000 8C18 movw %ds,\(%eax\)
+ 5 0002 8C18 mov %ds,\(%eax\)
+ 6 0004 8E18 movw \(%eax\),%ds
+ 7 0006 8E18 mov \(%eax\),%ds
+ 8 # Force a good alignment.
+ 9 0008 00000000 .p2align 4,0
+ 9 00000000
--- binutils/gas/testsuite/gas/i386/segment.s.seg 2005-03-25 11:18:45.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/segment.s 2005-03-25 11:25:37.000000000 -0800
@@ -0,0 +1,9 @@
+.psize 0
+.text
+# test segment reg insns with memory operand
+ movw %ds,(%eax)
+ mov %ds,(%eax)
+ movw (%eax),%ds
+ mov (%eax),%ds
+ # Force a good alignment.
+ .p2align 4,0
--- binutils/gas/testsuite/gas/i386/x86-64-inval-seg.l.seg 2005-03-25 12:03:19.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-inval-seg.l 2005-03-25 12:04:15.000000000 -0800
@@ -0,0 +1,14 @@
+.*: Assembler messages:
+.*:3: Error: .*
+.*:4: Error: .*
+.*:5: Error: .*
+.*:6: Error: .*
+GAS LISTING .*
+
+
+ 1 [ ]* .text
+ 2 [ ]*# All the following should be illegal
+ 3 [ ]* movq %ds,\(%rax\)
+ 4 [ ]* movl %ds,\(%rax\)
+ 5 [ ]* movq \(%rax\),%ds
+ 6 [ ]* movl \(%rax\),%ds
--- binutils/gas/testsuite/gas/i386/x86-64-inval-seg.s.seg 2005-03-25 12:03:21.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-inval-seg.s 2005-03-25 12:04:25.000000000 -0800
@@ -0,0 +1,6 @@
+ .text
+# All the following should be illegal
+ movq %ds,(%rax)
+ movl %ds,(%rax)
+ movq (%rax),%ds
+ movl (%rax),%ds
--- binutils/gas/testsuite/gas/i386/x86-64-opcode.d.seg 2005-03-25 17:47:02.668057512 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-opcode.d 2005-03-25 17:46:39.007115460 -0800
@@ -16,22 +16,16 @@ Disassembly of section .text:
[ ]*[0-9a-f]+:[ ]+cf[ ]+iret[ ]*(#.*)*
[ ]*[0-9a-f]+:[ ]+66 cf[ ]+iretw[ ]*(#.*)*
[ ]*[0-9a-f]+:[ ]+48 cf[ ]+iretq[ ]*(#.*)*
-[ ]*[0-9a-f]+:[ ]+41 8c 08[ ]+movl?[ ]+%cs,\(%r8\)[ ]*(#.*)*
-[ ]*[0-9a-f]+:[ ]+8c 08[ ]+movl?[ ]+%cs,\(%rax\)[ ]*(#.*)*
-[ ]*[0-9a-f]+:[ ]+41 8c 10[ ]+movl?[ ]+%ss,\(%r8\)[ ]*(#.*)*
-[ ]*[0-9a-f]+:[ ]+8c 10[ ]+movl?[ ]+%ss,\(%rax\)[ ]*(#.*)*
-[ ]*[0-9a-f]+:[ ]+41 8c 20[ ]+movl?[ ]+%fs,\(%r8\)[ ]*(#.*)*
-[ ]*[0-9a-f]+:[ ]+8c 20[ ]+movl?[ ]+%fs,\(%rax\)[ ]*(#.*)*
-[ ]*[0-9a-f]+:[ ]+41 8c 08[ ]+movl?[ ]+%cs,\(%r8\)[ ]*(#.*)*
-[ ]*[0-9a-f]+:[ ]+8c 08[ ]+movl?[ ]+%cs,\(%rax\)[ ]*(#.*)*
-[ ]*[0-9a-f]+:[ ]+41 8c 10[ ]+movl?[ ]+%ss,\(%r8\)[ ]*(#.*)*
-[ ]*[0-9a-f]+:[ ]+8c 10[ ]+movl?[ ]+%ss,\(%rax\)[ ]*(#.*)*
-[ ]*[0-9a-f]+:[ ]+41 8c 20[ ]+movl?[ ]+%fs,\(%r8\)[ ]*(#.*)*
-[ ]*[0-9a-f]+:[ ]+8c 20[ ]+movl?[ ]+%fs,\(%rax\)[ ]*(#.*)*
-[ ]*[0-9a-f]+:[ ]+41 8e 10[ ]+movl?[ ]+\(%r8\),%ss[ ]*(#.*)*
-[ ]*[0-9a-f]+:[ ]+8e 10[ ]+movl?[ ]+\(%rax\),%ss[ ]*(#.*)*
-[ ]*[0-9a-f]+:[ ]+41 8e 20[ ]+movl?[ ]+\(%r8\),%fs[ ]*(#.*)*
-[ ]*[0-9a-f]+:[ ]+8e 20[ ]+movl?[ ]+\(%rax\),%fs[ ]*(#.*)*
+[ ]*[0-9a-f]+:[ ]+41 8c 08[ ]+movw?[ ]+%cs,\(%r8\)[ ]*(#.*)*
+[ ]*[0-9a-f]+:[ ]+8c 08[ ]+movw?[ ]+%cs,\(%rax\)[ ]*(#.*)*
+[ ]*[0-9a-f]+:[ ]+41 8c 10[ ]+movw?[ ]+%ss,\(%r8\)[ ]*(#.*)*
+[ ]*[0-9a-f]+:[ ]+8c 10[ ]+movw?[ ]+%ss,\(%rax\)[ ]*(#.*)*
+[ ]*[0-9a-f]+:[ ]+41 8c 20[ ]+movw?[ ]+%fs,\(%r8\)[ ]*(#.*)*
+[ ]*[0-9a-f]+:[ ]+8c 20[ ]+movw?[ ]+%fs,\(%rax\)[ ]*(#.*)*
+[ ]*[0-9a-f]+:[ ]+41 8e 10[ ]+movw?[ ]+\(%r8\),%ss[ ]*(#.*)*
+[ ]*[0-9a-f]+:[ ]+8e 10[ ]+movw?[ ]+\(%rax\),%ss[ ]*(#.*)*
+[ ]*[0-9a-f]+:[ ]+41 8e 20[ ]+movw?[ ]+\(%r8\),%fs[ ]*(#.*)*
+[ ]*[0-9a-f]+:[ ]+8e 20[ ]+movw?[ ]+\(%rax\),%fs[ ]*(#.*)*
[ ]*[0-9a-f]+:[ ]+41 c6 00 00[ ]+movb[ ]+\$0[x0]*,\(%r8\)[ ]*(#.*)*
[ ]*[0-9a-f]+:[ ]+c6 00 00[ ]+movb[ ]+\$0[x0]*,\(%rax\)[ ]*(#.*)*
[ ]*[0-9a-f]+:[ ]+66 41 c7 00 00 70[ ]+movw[ ]+\$0x7000,\(%r8\)[ ]*(#.*)*
@@ -274,5 +268,4 @@ Disassembly of section .text:
[ ]*[0-9a-f]+:[ ]+e7 00[ ]+out[ ]+%eax,\$0[x0]*[ ]*(#.*)*
[ ]*[0-9a-f]+:[ ]+00 00[ ]+.*
[ ]*[0-9a-f]+:[ ]+00 00[ ]+.*
-[ ]*[0-9a-f]+:[ ]+00 00[ ]+.*
[ *]...
--- binutils/gas/testsuite/gas/i386/x86-64-opcode.s.seg 2003-02-27 11:27:13.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-opcode.s 2005-03-25 12:16:15.000000000 -0800
@@ -20,22 +20,16 @@
# CMP
# MOV
- MOVw %cs,(%r8) # 66 -- -- 41 8C 08 ; REX to access upper reg. O16 for 16-bit operand size
- MOVw %cs,(%rax) # 66 -- -- -- 8C 08 ; O16 for 16-bit operand size
- MOVw %ss,(%r8) # 66 -- -- 41 8C 10 ; REX to access upper reg. O16 for 16-bit operand size
- MOVw %ss,(%rax) # 66 -- -- -- 8C 10 ; O16 for 16-bit operand size
- MOVw %fs,(%r8) # 66 -- -- 41 8C 20 ; REX to access upper reg. O16 for 16-bit operand size
- MOVw %fs,(%rax) # 66 -- -- -- 8C 20 ; O16 for 16-bit operand size
- MOVl %cs,(%r8) # -- -- -- 41 8C 08 ; REX to access upper reg.
- MOVl %cs,(%rax) # -- -- -- -- 8C 08
- MOVl %ss,(%r8) # -- -- -- 41 8C 10 ; REX to access upper reg.
- MOVl %ss,(%rax) # -- -- -- -- 8C 10
- MOVl %fs,(%r8) # -- -- -- 41 8C 20 ; REX to access upper reg.
- MOVl %fs,(%rax) # -- -- -- -- 8C 20
- MOVl (%r8),%ss # -- -- -- 41 8E 10 ; REX to access upper reg.
- MOVl (%rax),%ss # -- -- -- -- 8E 10
- MOVl (%r8),%fs # -- -- -- 41 8E 20 ; REX to access upper reg.
- MOVl (%rax),%fs # -- -- -- -- 8E 20
+ MOVw %cs,(%r8) # -- -- -- 41 8C 08 ; REX to access upper reg.
+ MOVw %cs,(%rax) # -- -- -- -- 8C 08
+ MOVw %ss,(%r8) # -- -- -- 41 8C 10 ; REX to access upper reg.
+ MOVw %ss,(%rax) # -- -- -- -- 8C 10
+ MOVw %fs,(%r8) # -- -- -- 41 8C 20 ; REX to access upper reg.
+ MOVw %fs,(%rax) # -- -- -- -- 8C 20
+ MOVw (%r8),%ss # -- -- -- 41 8E 10 ; REX to access upper reg.
+ MOVw (%rax),%ss # -- -- -- -- 8E 10
+ MOVw (%r8),%fs # -- -- -- 41 8E 20 ; REX to access upper reg.
+ MOVw (%rax),%fs # -- -- -- -- 8E 20
MOVb $0,(%r8) # -- -- -- 41 C6 00 00 ; REX to access upper reg.
MOVb $0,(%rax) # -- -- -- -- C6 00 00
MOVw $0x7000,(%r8) # 66 -- -- 41 C7 00 00 70 ; REX to access upper reg. O16 for 16-bit operand size
--- binutils/gas/testsuite/gas/i386/x86-64-segment.l.seg 2005-03-25 11:28:25.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-segment.l 2005-03-25 12:53:59.000000000 -0800
@@ -0,0 +1,12 @@
+ 1 .psize 0
+ 2 .text
+ 3 # test segment reg insns with memory operand
+ 4 0000 8C18 movw %ds,\(%rax\)
+ 5 0002 8C18 mov %ds,\(%rax\)
+ 6 0004 8E18 movw \(%rax\),%ds
+ 7 0006 8E18 mov \(%rax\),%ds
+ 8 # test segment reg insns with REX
+ 9 0008 488CD8 movq %ds,%rax
+ 10 000b 488ED8 movq %rax,%ds
+ 11 # Force a good alignment.
+ 12 000e 0000 .p2align 4,0
--- binutils/gas/testsuite/gas/i386/x86-64-segment.s.seg 2005-03-25 11:28:27.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-segment.s 2005-03-25 12:18:47.000000000 -0800
@@ -0,0 +1,12 @@
+.psize 0
+.text
+# test segment reg insns with memory operand
+ movw %ds,(%rax)
+ mov %ds,(%rax)
+ movw (%rax),%ds
+ mov (%rax),%ds
+# test segment reg insns with REX
+ movq %ds,%rax
+ movq %rax,%ds
+ # Force a good alignment.
+ .p2align 4,0
--- binutils/include/opcode/i386.h.seg 2005-03-03 09:24:08.000000000 -0800
+++ binutils/include/opcode/i386.h 2005-03-25 12:44:54.000000000 -0800
@@ -98,11 +98,13 @@ static const template i386_optab[] =
are set to an implementation defined value (on the Pentium Pro,
the implementation defined value is zero). */
{ "mov", 2, 0x8c, X, 0, wl_Suf|Modrm, { SReg2, WordReg|InvMem, 0 } },
-{ "mov", 2, 0x8c, X, 0, wl_Suf|Modrm|IgnoreSize, { SReg2, WordMem, 0 } },
+{ "mov", 2, 0x8c, X, 0, w_Suf|Modrm|IgnoreSize, { SReg2, WordMem, 0 } },
{ "mov", 2, 0x8c, X, Cpu386, wl_Suf|Modrm, { SReg3, WordReg|InvMem, 0 } },
-{ "mov", 2, 0x8c, X, Cpu386, wl_Suf|Modrm|IgnoreSize, { SReg3, WordMem, 0 } },
-{ "mov", 2, 0x8e, X, 0, wl_Suf|Modrm|IgnoreSize, { WordReg|WordMem, SReg2, 0 } },
-{ "mov", 2, 0x8e, X, Cpu386, wl_Suf|Modrm|IgnoreSize, { WordReg|WordMem, SReg3, 0 } },
+{ "mov", 2, 0x8c, X, Cpu386, w_Suf|Modrm|IgnoreSize, { SReg3, WordMem, 0 } },
+{ "mov", 2, 0x8e, X, 0, wl_Suf|Modrm|IgnoreSize, { WordReg, SReg2, 0 } },
+{ "mov", 2, 0x8e, X, 0, w_Suf|Modrm|IgnoreSize, { WordMem, SReg2, 0 } },
+{ "mov", 2, 0x8e, X, Cpu386, wl_Suf|Modrm|IgnoreSize, { WordReg, SReg3, 0 } },
+{ "mov", 2, 0x8e, X, Cpu386, w_Suf|Modrm|IgnoreSize, { WordMem, SReg3, 0 } },
/* Move to/from control debug registers. In the 16 or 32bit modes they are 32bit. In the 64bit
mode they are 64bit.*/
{ "mov", 2, 0x0f20, X, Cpu386|CpuNo64, l_Suf|D|Modrm|IgnoreSize,{ Control, Reg32|InvMem, 0} },
@@ -1003,6 +1005,10 @@ static const template i386_optab[] =
{"movq", 2, 0x88, X, Cpu64, NoSuf|D|W|Modrm|Size64,{ Reg64, Reg64|AnyMem, 0 } },
{"movq", 2, 0xc6, 0, Cpu64, NoSuf|W|Modrm|Size64, { Imm32S, Reg64|WordMem, 0 } },
{"movq", 2, 0xb0, X, Cpu64, NoSuf|W|ShortForm|Size64,{ Imm64, Reg64, 0 } },
+/* The segment register moves accept Reg64 so that a segment register
+ can be copied to a 64 bit register, and vice versa. */
+{"movq", 2, 0x8c, X, Cpu64, NoSuf|Modrm|Size64, { SReg2|SReg3, Reg64|InvMem, 0 } },
+{"movq", 2, 0x8e, X, Cpu64, NoSuf|Modrm|Size64, { Reg64, SReg2|SReg3, 0 } },
/* Move to/from control debug registers. In the 16 or 32bit modes they are 32bit. In the 64bit
mode they are 64bit.*/
{"movq", 2, 0x0f20, X, Cpu64, NoSuf|D|Modrm|IgnoreSize|NoRex64|Size64,{ Control, Reg64|InvMem, 0} },
--- binutils/opcodes/i386-dis.c.seg 2005-03-25 09:03:01.000000000 -0800
+++ binutils/opcodes/i386-dis.c 2005-03-25 17:38:10.097887059 -0800
@@ -97,6 +97,7 @@ static void SIMD_Fixup (int, int);
static void PNI_Fixup (int, int);
static void INVLPG_Fixup (int, int);
static void BadOp (void);
+static void SEG_Fixup (int, int);
struct dis_private {
/* Points to first byte not fetched. */
@@ -221,6 +222,7 @@ fetch_data (struct disassemble_info *inf
#define Cm OP_C, m_mode
#define Dm OP_D, m_mode
#define Td OP_T, d_mode
+#define Sv SEG_Fixup, v_mode
#define RMeAX OP_REG, eAX_reg
#define RMeBX OP_REG, eBX_reg
@@ -642,9 +644,9 @@ static const struct dis386 dis386[] = {
{ "movS", Ev, Gv, XX },
{ "movB", Gb, Eb, XX },
{ "movS", Gv, Ev, XX },
- { "movQ", Ev, Sw, XX },
+ { "movQ", Sv, Sw, XX },
{ "leaS", Gv, M, XX },
- { "movQ", Sw, Ev, XX },
+ { "movQ", Sw, Sv, XX },
{ "popU", Ev, XX, XX },
/* 90 */
{ "nop", NOP_Fixup, 0, XX, XX },
@@ -4422,3 +4424,52 @@ BadOp (void)
codep = insn_codep + 1;
oappend ("(bad)");
}
+
+static void
+SEG_Fixup (int extrachar, int sizeflag)
+{
+ if (mod == 3)
+ {
+ /* We need to add a proper suffix with
+
+ movw %ds,%ax
+ movl %ds,%eax
+ movq %ds,%rax
+ movw %ax,%ds
+ movl %eax,%ds
+ movq %rax,%ds
+ */
+ const char *suffix;
+
+ if (prefixes & PREFIX_DATA)
+ suffix = "w";
+ else
+ {
+ USED_REX (REX_MODE64);
+ if (rex & REX_MODE64)
+ suffix = "q";
+ else
+ suffix = "l";
+ }
+ strcat (obuf, suffix);
+ }
+ else
+ {
+ /* We need to fix the suffix for
+
+ movw %ds,(%eax)
+ movw %ds,(%rax)
+ movw (%eax),%ds
+ movw (%rax),%ds
+
+ Override "mov[l|q]". */
+ char *p = obuf + strlen (obuf) - 1;
+
+ /* We might not have a suffix. */
+ if (*p == 'v')
+ ++p;
+ *p = 'w';
+ }
+
+ OP_E (extrachar, sizeflag);
+}
^ permalink raw reply [flat|nested] 12+ messages in thread
* i386/x86_64 segment register issuses (Re: PATCH: Fix x86 segment register access)
2005-03-26 23:31 PATCH: Fix x86 segment register access H. J. Lu
@ 2005-03-28 10:21 ` H. J. Lu
2005-03-30 9:46 ` PATCH: i386/x86_64 segment register access update H. J. Lu
[not found] ` <m14qev3h8l.fsf@muc.de>
0 siblings, 2 replies; 12+ messages in thread
From: H. J. Lu @ 2005-03-28 10:21 UTC (permalink / raw)
To: binutils, GNU C Library; +Cc: linux kernel
It turns out that 2.4 kernel has
arch/i386/kernel/process.c: asm volatile("movl %%" #seg ",%0":"=m" (*(int *)&(value)))
arch/i386/kernel/process.c: asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs));
arch/i386/kernel/process.c: asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs));
arch/x86_64/kernel/process.c: asm("movl %%gs,%0" : "=m" (p->thread.gsindex));
arch/x86_64/kernel/process.c: asm("movl %%fs,%0" : "=m" (p->thread.fsindex));
arch/x86_64/kernel/process.c: asm("movl %%es,%0" : "=m" (p->thread.es));
arch/x86_64/kernel/process.c: asm("movl %%ds,%0" : "=m" (p->thread.ds));
arch/x86_64/kernel/process.c: asm volatile("movl %%es,%0" : "=m" (prev->es));
arch/x86_64/kernel/process.c: asm volatile ("movl %%ds,%0" : "=m" (prev->ds));
2.6 kernel has
arch/i386/kernel/process.c: asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs));
arch/i386/kernel/process.c: asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs));
arch/x86_64/kernel/process.c: asm("movl %%gs,%0" : "=m" (p->thread.gsindex));
arch/x86_64/kernel/process.c: asm("movl %%fs,%0" : "=m" (p->thread.fsindex));
arch/x86_64/kernel/process.c: asm("movl %%es,%0" : "=m" (p->thread.es));
arch/x86_64/kernel/process.c: asm("movl %%ds,%0" : "=m" (p->thread.ds));
arch/x86_64/kernel/process.c: asm volatile("movl %%es,%0" : "=m" (prev->es));
arch/x86_64/kernel/process.c: asm volatile ("movl %%ds,%0" : "=m" (prev->ds));
arch/x86_64/kernel/process.c: asm volatile("movl %%fs,%0" : "=g" (fsindex));
arch/x86_64/kernel/process.c: asm volatile("movl %%gs,%0" : "=g" (gsindex));
The new assembler will disallow them since those instructions with
memory operand will only use the first 16bits. If the memory operand
is 16bit, you won't see any problems. But if the memory destinatin
is 32bit, the upper 16bits may have random values. The new assembler
will force people to use
mov (%eax),%ds
movw (%eax),%ds
movw %ds,(%eax)
mov %ds,(%eax)
Will it be a big problem for kernel people?
BTW, I haven't checked glibc yet. It may have similar issues.
H.J.
---
On Fri, Mar 25, 2005 at 06:05:06PM -0800, H. J. Lu wrote:
> X86 segment register access is a special. We can move between a segment
> register and a 16/32/64bit general-purpose register. But we can only
> move between a segment register and a 16bit memory address. The current
> assembler allows "movl (%eax),%ds", but doesn't allow "movq %rax,%ds".
> The disassembler display "movl (%eax),%ds". This patch tries to fix
> those.
>
>
> H.J.
> ----
> gas/testsuite/
>
> 2005-03-25 H.J. Lu <hongjiu.lu@intel.com>
>
> * gas/i386/i386.exp: Run segment and inval-seg for i386. Run
> x86-64-segment and x86-64-inval-seg for x86-64.
>
> * gas/i386/intel.d: Expect movw for moving between memory and
> segment register.
> * gas/i386/naked.d: Likewise.
> * gas/i386/opcode.d: Likewise.
> * gas/i386/x86-64-opcode.d: Likewise.
>
> * gas/i386/opcode.s: Use movw for moving between memory and
> segment register.
> * gas/i386/x86-64-opcode.s: Likewise.
>
> * : Likewise.
>
> * gas/i386/inval-seg.l: New.
> * gas/i386/inval-seg.s: New.
> * gas/i386/segment.l: New.
> * gas/i386/segment.s: New.
> * gas/i386/x86-64-inval-seg.l: New.
> * gas/i386/x86-64-inval-seg.s: New.
> * gas/i386/x86-64-segment.l: New.
> * gas/i386/x86-64-segment.s: New.
>
> include/opcode/
>
> 2005-03-25 H.J. Lu <hongjiu.lu@intel.com>
>
> * i386.h (i386_optab): Don't allow the `l' suffix for moving
> moving between memory and segment register. Allow movq for
> moving between general-purpose register and segment register.
>
> opcodes/
>
> 2005-03-25 H.J. Lu <hongjiu.lu@intel.com>
>
> * i386-dis.c (SEG_Fixup): New.
> (Sv): New.
> (dis386): Use "Sv" for 0x8c and 0x8e.
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* PATCH: i386/x86_64 segment register access update
2005-03-28 10:21 ` i386/x86_64 segment register issuses (Re: PATCH: Fix x86 segment register access) H. J. Lu
@ 2005-03-30 9:46 ` H. J. Lu
[not found] ` <m14qev3h8l.fsf@muc.de>
1 sibling, 0 replies; 12+ messages in thread
From: H. J. Lu @ 2005-03-30 9:46 UTC (permalink / raw)
To: binutils; +Cc: linux kernel
[-- Attachment #1: Type: text/plain, Size: 987 bytes --]
The new i386/x86_64 assemblers no longer accept instructions for moving
between a segment register and a 32bit memory location, i.e.,
movl (%eax),%ds
movl %ds,(%eax)
To generate instructions for moving between a segment register and a
16bit memory location without the 16bit operand size prefix, 0x66,
mov (%eax),%ds
mov %ds,(%eax)
should be used. It will work with both new and old assemblers. The
assembler starting from 2.16.90.0.1 will also support
movw (%eax),%ds
movw %ds,(%eax)
without the 0x66 prefix. I am enclosing patches for 2.4 and 2.6 kernels
here. The resulting kernel binaries should be unchanged as before, with
old and new assemblers, if gcc never generates memory access for
unsigned gsindex;
asm volatile("movl %%gs,%0" : "=g" (gsindex));
If gcc does generate memory access for the code above, the upper bits
in gsindex are undefined and the new assembler doesn't allow it.
H.J.
[-- Attachment #2: linux-2.4-seg-4.patch --]
[-- Type: text/plain, Size: 4115 bytes --]
--- linux/arch/i386/kernel/apm.c.seg 2005-03-27 13:10:45.000000000 -0800
+++ linux/arch/i386/kernel/apm.c 2005-03-28 10:30:24.000000000 -0800
@@ -327,7 +327,7 @@ extern int (*console_blank_hook)(int);
* Save a segment register away
*/
#define savesegment(seg, where) \
- __asm__ __volatile__("movl %%" #seg ",%0" : "=m" (where))
+ __asm__ __volatile__("mov %%" #seg ",%0" : "=m" (where))
/*
* Maximum number of events stored
@@ -553,7 +553,7 @@ static inline void apm_restore_cpus(unsi
#ifdef APM_ZERO_SEGS
# define APM_DECL_SEGS \
- unsigned int saved_fs; unsigned int saved_gs;
+ unsigned short saved_fs; unsigned short saved_gs;
# define APM_DO_SAVE_SEGS \
savesegment(fs, saved_fs); savesegment(gs, saved_gs)
# define APM_DO_ZERO_SEGS \
--- linux/arch/i386/kernel/process.c.seg 2005-03-27 13:10:45.000000000 -0800
+++ linux/arch/i386/kernel/process.c 2005-03-28 10:30:24.000000000 -0800
@@ -544,7 +544,7 @@ void release_thread(struct task_struct *
* Save a segment.
*/
#define savesegment(seg,value) \
- asm volatile("movl %%" #seg ",%0":"=m" (*(int *)&(value)))
+ asm volatile("mov %%" #seg ",%0":"=m" (value))
int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
unsigned long unused,
@@ -661,8 +661,8 @@ void fastcall __switch_to(struct task_st
* Save away %fs and %gs. No need to save %es and %ds, as
* those are always kernel segments while inside the kernel.
*/
- asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs));
- asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs));
+ asm volatile("mov %%fs,%0":"=m" (prev->fs));
+ asm volatile("mov %%gs,%0":"=m" (prev->gs));
/*
* Restore %fs and %gs.
--- linux/arch/x86_64/kernel/process.c.seg 2005-03-27 13:10:51.000000000 -0800
+++ linux/arch/x86_64/kernel/process.c 2005-03-28 11:16:57.000000000 -0800
@@ -527,10 +527,10 @@ int copy_thread(int nr, unsigned long cl
p->thread.fs = me->thread.fs;
p->thread.gs = me->thread.gs;
- asm("movl %%gs,%0" : "=m" (p->thread.gsindex));
- asm("movl %%fs,%0" : "=m" (p->thread.fsindex));
- asm("movl %%es,%0" : "=m" (p->thread.es));
- asm("movl %%ds,%0" : "=m" (p->thread.ds));
+ asm("mov %%gs,%0" : "=m" (p->thread.gsindex));
+ asm("mov %%fs,%0" : "=m" (p->thread.fsindex));
+ asm("mov %%es,%0" : "=m" (p->thread.es));
+ asm("mov %%ds,%0" : "=m" (p->thread.ds));
unlazy_fpu(current);
p->thread.i387 = current->thread.i387;
@@ -575,11 +575,11 @@ struct task_struct *__switch_to(struct t
/*
* Switch DS and ES.
*/
- asm volatile("movl %%es,%0" : "=m" (prev->es));
+ asm volatile("mov %%es,%0" : "=m" (prev->es));
if (unlikely(next->es | prev->es))
loadsegment(es, next->es);
- asm volatile ("movl %%ds,%0" : "=m" (prev->ds));
+ asm volatile ("mov %%ds,%0" : "=m" (prev->ds));
if (unlikely(next->ds | prev->ds))
loadsegment(ds, next->ds);
@@ -588,7 +588,7 @@ struct task_struct *__switch_to(struct t
*/
{
unsigned fsindex;
- asm volatile("movl %%fs,%0" : "=g" (fsindex));
+ asm volatile("movl %%fs,%0" : "=r" (fsindex));
/* segment register != 0 always requires a reload.
also reload when it has changed.
when prev process used 64bit base always reload
@@ -609,7 +609,7 @@ struct task_struct *__switch_to(struct t
}
{
unsigned gsindex;
- asm volatile("movl %%gs,%0" : "=g" (gsindex));
+ asm volatile("movl %%gs,%0" : "=r" (gsindex));
if (unlikely((gsindex | next->gsindex) || prev->gs)) {
load_gs_index(next->gsindex);
if (gsindex)
--- linux/include/asm-i386/system.h.seg 2005-03-27 15:33:12.000000000 -0800
+++ linux/include/asm-i386/system.h 2005-03-28 10:30:24.000000000 -0800
@@ -84,7 +84,7 @@ static inline unsigned long _get_base(ch
#define loadsegment(seg,value) \
asm volatile("\n" \
"1:\t" \
- "movl %0,%%" #seg "\n" \
+ "mov %0,%%" #seg "\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
"3:\t" \
@@ -96,7 +96,7 @@ static inline unsigned long _get_base(ch
".align 4\n\t" \
".long 1b,3b\n" \
".previous" \
- : :"m" (*(unsigned int *)&(value)))
+ : :"m" (value))
/*
* Clear and set 'TS' bit respectively
[-- Attachment #3: linux-2.6-seg-5.patch --]
[-- Type: text/plain, Size: 3961 bytes --]
--- linux/arch/i386/kernel/process.c.seg 2005-03-27 13:07:14.000000000 -0800
+++ linux/arch/i386/kernel/process.c 2005-03-28 10:28:47.000000000 -0800
@@ -597,8 +597,8 @@ struct task_struct fastcall * __switch_t
* Save away %fs and %gs. No need to save %es and %ds, as
* those are always kernel segments while inside the kernel.
*/
- asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs));
- asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs));
+ asm volatile("mov %%fs,%0":"=m" (prev->fs));
+ asm volatile("mov %%gs,%0":"=m" (prev->gs));
/*
* Restore %fs and %gs if needed.
--- linux/arch/i386/kernel/vm86.c.seg 2005-03-27 13:07:14.000000000 -0800
+++ linux/arch/i386/kernel/vm86.c 2005-03-28 10:28:47.000000000 -0800
@@ -294,8 +294,8 @@ static void do_sys_vm86(struct kernel_vm
*/
info->regs32->eax = 0;
tsk->thread.saved_esp0 = tsk->thread.esp0;
- asm volatile("movl %%fs,%0":"=m" (tsk->thread.saved_fs));
- asm volatile("movl %%gs,%0":"=m" (tsk->thread.saved_gs));
+ asm volatile("mov %%fs,%0":"=m" (tsk->thread.saved_fs));
+ asm volatile("mov %%gs,%0":"=m" (tsk->thread.saved_gs));
tss = &per_cpu(init_tss, get_cpu());
tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
--- linux/arch/x86_64/kernel/process.c.seg 2005-03-27 13:07:49.000000000 -0800
+++ linux/arch/x86_64/kernel/process.c 2005-03-28 11:11:04.206766410 -0800
@@ -391,10 +391,10 @@ int copy_thread(int nr, unsigned long cl
p->thread.fs = me->thread.fs;
p->thread.gs = me->thread.gs;
- asm("movl %%gs,%0" : "=m" (p->thread.gsindex));
- asm("movl %%fs,%0" : "=m" (p->thread.fsindex));
- asm("movl %%es,%0" : "=m" (p->thread.es));
- asm("movl %%ds,%0" : "=m" (p->thread.ds));
+ asm("mov %%gs,%0" : "=m" (p->thread.gsindex));
+ asm("mov %%fs,%0" : "=m" (p->thread.fsindex));
+ asm("mov %%es,%0" : "=m" (p->thread.es));
+ asm("mov %%ds,%0" : "=m" (p->thread.ds));
if (unlikely(me->thread.io_bitmap_ptr != NULL)) {
p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
@@ -457,11 +457,11 @@ struct task_struct *__switch_to(struct t
* Switch DS and ES.
* This won't pick up thread selector changes, but I guess that is ok.
*/
- asm volatile("movl %%es,%0" : "=m" (prev->es));
+ asm volatile("mov %%es,%0" : "=m" (prev->es));
if (unlikely(next->es | prev->es))
loadsegment(es, next->es);
- asm volatile ("movl %%ds,%0" : "=m" (prev->ds));
+ asm volatile ("mov %%ds,%0" : "=m" (prev->ds));
if (unlikely(next->ds | prev->ds))
loadsegment(ds, next->ds);
@@ -472,7 +472,7 @@ struct task_struct *__switch_to(struct t
*/
{
unsigned fsindex;
- asm volatile("movl %%fs,%0" : "=g" (fsindex));
+ asm volatile("movl %%fs,%0" : "=r" (fsindex));
/* segment register != 0 always requires a reload.
also reload when it has changed.
when prev process used 64bit base always reload
@@ -493,7 +493,7 @@ struct task_struct *__switch_to(struct t
}
{
unsigned gsindex;
- asm volatile("movl %%gs,%0" : "=g" (gsindex));
+ asm volatile("movl %%gs,%0" : "=r" (gsindex));
if (unlikely(gsindex | next->gsindex | prev->gs)) {
load_gs_index(next->gsindex);
if (gsindex)
--- linux/include/asm-i386/system.h.seg 2005-03-27 13:09:12.000000000 -0800
+++ linux/include/asm-i386/system.h 2005-03-28 10:28:47.000000000 -0800
@@ -81,7 +81,7 @@ static inline unsigned long _get_base(ch
#define loadsegment(seg,value) \
asm volatile("\n" \
"1:\t" \
- "movl %0,%%" #seg "\n" \
+ "mov %0,%%" #seg "\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
"3:\t" \
@@ -93,13 +93,13 @@ static inline unsigned long _get_base(ch
".align 4\n\t" \
".long 1b,3b\n" \
".previous" \
- : :"m" (*(unsigned int *)&(value)))
+ : :"m" (value))
/*
* Save a segment register away
*/
#define savesegment(seg, value) \
- asm volatile("movl %%" #seg ",%0":"=m" (*(int *)&(value)))
+ asm volatile("mov %%" #seg ",%0":"=m" (value))
/*
* Clear and set 'TS' bit respectively
^ permalink raw reply [flat|nested] 12+ messages in thread
[parent not found: <m14qev3h8l.fsf@muc.de>]
end of thread, other threads:[~2005-03-31 10:23 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-03-26 23:31 PATCH: Fix x86 segment register access H. J. Lu
2005-03-28 10:21 ` i386/x86_64 segment register issuses (Re: PATCH: Fix x86 segment register access) H. J. Lu
2005-03-30 9:46 ` PATCH: i386/x86_64 segment register access update H. J. Lu
[not found] ` <m14qev3h8l.fsf@muc.de>
[not found] ` <Pine.LNX.4.58.0503291618520.6036@ppc970.osdl.org>
[not found] ` <20050330015312.GA27309@lucon.org>
[not found] ` <Pine.LNX.4.58.0503291815570.6036@ppc970.osdl.org>
[not found] ` <20050330040017.GA29523@lucon.org>
2005-03-30 22:19 ` i386/x86_64 segment register issuses (Re: PATCH: Fix x86 segment register access) Linus Torvalds
2005-03-30 23:24 ` linux-os
2005-03-31 12:00 ` H. J. Lu
2005-03-31 8:55 ` H. J. Lu
2005-03-31 13:27 ` Pau Aliagas
2005-03-31 15:05 ` H. J. Lu
2005-03-31 15:05 ` Pau Aliagas
2005-03-31 15:07 ` H. J. Lu
2005-03-31 15:37 ` Andi Kleen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).