xref: /qemu/target/i386/gdbstub.c (revision 7b0f97bade8a30eb756739442ea998ef0ab8ab96)
1f20f9df0SAndreas Färber /*
2f20f9df0SAndreas Färber  * x86 gdb server stub
3f20f9df0SAndreas Färber  *
4f20f9df0SAndreas Färber  * Copyright (c) 2003-2005 Fabrice Bellard
5f20f9df0SAndreas Färber  * Copyright (c) 2013 SUSE LINUX Products GmbH
6f20f9df0SAndreas Färber  *
7f20f9df0SAndreas Färber  * This library is free software; you can redistribute it and/or
8f20f9df0SAndreas Färber  * modify it under the terms of the GNU Lesser General Public
9f20f9df0SAndreas Färber  * License as published by the Free Software Foundation; either
10f20f9df0SAndreas Färber  * version 2 of the License, or (at your option) any later version.
11f20f9df0SAndreas Färber  *
12f20f9df0SAndreas Färber  * This library is distributed in the hope that it will be useful,
13f20f9df0SAndreas Färber  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14f20f9df0SAndreas Färber  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15f20f9df0SAndreas Färber  * Lesser General Public License for more details.
16f20f9df0SAndreas Färber  *
17f20f9df0SAndreas Färber  * You should have received a copy of the GNU Lesser General Public
18f20f9df0SAndreas Färber  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19f20f9df0SAndreas Färber  */
20b6a0aa05SPeter Maydell #include "qemu/osdep.h"
215b50e790SAndreas Färber #include "qemu-common.h"
2233c11879SPaolo Bonzini #include "cpu.h"
235b50e790SAndreas Färber #include "exec/gdbstub.h"
24f20f9df0SAndreas Färber 
25f20f9df0SAndreas Färber #ifdef TARGET_X86_64
26f20f9df0SAndreas Färber static const int gpr_map[16] = {
27f20f9df0SAndreas Färber     R_EAX, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI, R_EBP, R_ESP,
28f20f9df0SAndreas Färber     8, 9, 10, 11, 12, 13, 14, 15
29f20f9df0SAndreas Färber };
30f20f9df0SAndreas Färber #else
31f20f9df0SAndreas Färber #define gpr_map gpr_map32
32f20f9df0SAndreas Färber #endif
33f20f9df0SAndreas Färber static const int gpr_map32[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
34f20f9df0SAndreas Färber 
35*7b0f97baSDoug Gale /*
36*7b0f97baSDoug Gale  * Keep these in sync with assignment to
37*7b0f97baSDoug Gale  * gdb_num_core_regs in target/i386/cpu.c
38*7b0f97baSDoug Gale  * and with the machine description
39*7b0f97baSDoug Gale  */
40*7b0f97baSDoug Gale 
41*7b0f97baSDoug Gale /*
42*7b0f97baSDoug Gale  * SEG: 6 segments, plus fs_base, gs_base, kernel_gs_base
43*7b0f97baSDoug Gale  */
44*7b0f97baSDoug Gale 
45*7b0f97baSDoug Gale /*
46*7b0f97baSDoug Gale  * general regs ----->  8 or 16
47*7b0f97baSDoug Gale  */
48*7b0f97baSDoug Gale #define IDX_NB_IP       1
49*7b0f97baSDoug Gale #define IDX_NB_FLAGS    1
50*7b0f97baSDoug Gale #define IDX_NB_SEG      (6 + 3)
51*7b0f97baSDoug Gale #define IDX_NB_CTL      6
52*7b0f97baSDoug Gale #define IDX_NB_FP       16
53*7b0f97baSDoug Gale /*
54*7b0f97baSDoug Gale  * fpu regs ----------> 8 or 16
55*7b0f97baSDoug Gale  */
56*7b0f97baSDoug Gale #define IDX_NB_MXCSR    1
57*7b0f97baSDoug Gale /*
58*7b0f97baSDoug Gale  *          total ----> 8+1+1+9+6+16+8+1=50 or 16+1+1+9+6+16+16+1=66
59*7b0f97baSDoug Gale  */
60*7b0f97baSDoug Gale 
61f20f9df0SAndreas Färber #define IDX_IP_REG      CPU_NB_REGS
62*7b0f97baSDoug Gale #define IDX_FLAGS_REG   (IDX_IP_REG + IDX_NB_IP)
63*7b0f97baSDoug Gale #define IDX_SEG_REGS    (IDX_FLAGS_REG + IDX_NB_FLAGS)
64*7b0f97baSDoug Gale #define IDX_CTL_REGS    (IDX_SEG_REGS + IDX_NB_SEG)
65*7b0f97baSDoug Gale #define IDX_FP_REGS     (IDX_CTL_REGS + IDX_NB_CTL)
66*7b0f97baSDoug Gale #define IDX_XMM_REGS    (IDX_FP_REGS + IDX_NB_FP)
67f20f9df0SAndreas Färber #define IDX_MXCSR_REG   (IDX_XMM_REGS + CPU_NB_REGS)
68f20f9df0SAndreas Färber 
69*7b0f97baSDoug Gale #define IDX_CTL_CR0_REG     (IDX_CTL_REGS + 0)
70*7b0f97baSDoug Gale #define IDX_CTL_CR2_REG     (IDX_CTL_REGS + 1)
71*7b0f97baSDoug Gale #define IDX_CTL_CR3_REG     (IDX_CTL_REGS + 2)
72*7b0f97baSDoug Gale #define IDX_CTL_CR4_REG     (IDX_CTL_REGS + 3)
73*7b0f97baSDoug Gale #define IDX_CTL_CR8_REG     (IDX_CTL_REGS + 4)
74*7b0f97baSDoug Gale #define IDX_CTL_EFER_REG    (IDX_CTL_REGS + 5)
75*7b0f97baSDoug Gale 
76*7b0f97baSDoug Gale #ifdef TARGET_X86_64
77*7b0f97baSDoug Gale #define GDB_FORCE_64 1
78*7b0f97baSDoug Gale #else
79*7b0f97baSDoug Gale #define GDB_FORCE_64 0
80*7b0f97baSDoug Gale #endif
81*7b0f97baSDoug Gale 
82*7b0f97baSDoug Gale 
835b50e790SAndreas Färber int x86_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
84f20f9df0SAndreas Färber {
855b50e790SAndreas Färber     X86CPU *cpu = X86_CPU(cs);
865b50e790SAndreas Färber     CPUX86State *env = &cpu->env;
875b50e790SAndreas Färber 
88*7b0f97baSDoug Gale     uint64_t tpr;
89*7b0f97baSDoug Gale 
90e3592bc9SDoug Evans     /* N.B. GDB can't deal with changes in registers or sizes in the middle
91e3592bc9SDoug Evans        of a session. So if we're in 32-bit mode on a 64-bit cpu, still act
92e3592bc9SDoug Evans        as if we're on a 64-bit cpu. */
93e3592bc9SDoug Evans 
94f20f9df0SAndreas Färber     if (n < CPU_NB_REGS) {
95e3592bc9SDoug Evans         if (TARGET_LONG_BITS == 64) {
96e3592bc9SDoug Evans             if (env->hflags & HF_CS64_MASK) {
97986a2998SAndreas Färber                 return gdb_get_reg64(mem_buf, env->regs[gpr_map[n]]);
98f20f9df0SAndreas Färber             } else if (n < CPU_NB_REGS32) {
99e3592bc9SDoug Evans                 return gdb_get_reg64(mem_buf,
100e3592bc9SDoug Evans                                      env->regs[gpr_map[n]] & 0xffffffffUL);
101e3592bc9SDoug Evans             } else {
102e3592bc9SDoug Evans                 memset(mem_buf, 0, sizeof(target_ulong));
103e3592bc9SDoug Evans                 return sizeof(target_ulong);
104e3592bc9SDoug Evans             }
105e3592bc9SDoug Evans         } else {
106986a2998SAndreas Färber             return gdb_get_reg32(mem_buf, env->regs[gpr_map32[n]]);
107f20f9df0SAndreas Färber         }
108f20f9df0SAndreas Färber     } else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
109f20f9df0SAndreas Färber #ifdef USE_X86LDOUBLE
110f20f9df0SAndreas Färber         /* FIXME: byteswap float values - after fixing fpregs layout. */
111f20f9df0SAndreas Färber         memcpy(mem_buf, &env->fpregs[n - IDX_FP_REGS], 10);
112f20f9df0SAndreas Färber #else
113f20f9df0SAndreas Färber         memset(mem_buf, 0, 10);
114f20f9df0SAndreas Färber #endif
115f20f9df0SAndreas Färber         return 10;
116f20f9df0SAndreas Färber     } else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
117f20f9df0SAndreas Färber         n -= IDX_XMM_REGS;
118e3592bc9SDoug Evans         if (n < CPU_NB_REGS32 || TARGET_LONG_BITS == 64) {
11919cbd87cSEduardo Habkost             stq_p(mem_buf, env->xmm_regs[n].ZMM_Q(0));
12019cbd87cSEduardo Habkost             stq_p(mem_buf + 8, env->xmm_regs[n].ZMM_Q(1));
121f20f9df0SAndreas Färber             return 16;
122f20f9df0SAndreas Färber         }
123f20f9df0SAndreas Färber     } else {
124f20f9df0SAndreas Färber         switch (n) {
125f20f9df0SAndreas Färber         case IDX_IP_REG:
126e3592bc9SDoug Evans             if (TARGET_LONG_BITS == 64) {
127e3592bc9SDoug Evans                 if (env->hflags & HF_CS64_MASK) {
128986a2998SAndreas Färber                     return gdb_get_reg64(mem_buf, env->eip);
129f20f9df0SAndreas Färber                 } else {
130e3592bc9SDoug Evans                     return gdb_get_reg64(mem_buf, env->eip & 0xffffffffUL);
131e3592bc9SDoug Evans                 }
132e3592bc9SDoug Evans             } else {
133986a2998SAndreas Färber                 return gdb_get_reg32(mem_buf, env->eip);
134f20f9df0SAndreas Färber             }
135f20f9df0SAndreas Färber         case IDX_FLAGS_REG:
136986a2998SAndreas Färber             return gdb_get_reg32(mem_buf, env->eflags);
137f20f9df0SAndreas Färber 
138f20f9df0SAndreas Färber         case IDX_SEG_REGS:
139986a2998SAndreas Färber             return gdb_get_reg32(mem_buf, env->segs[R_CS].selector);
140f20f9df0SAndreas Färber         case IDX_SEG_REGS + 1:
141986a2998SAndreas Färber             return gdb_get_reg32(mem_buf, env->segs[R_SS].selector);
142f20f9df0SAndreas Färber         case IDX_SEG_REGS + 2:
143986a2998SAndreas Färber             return gdb_get_reg32(mem_buf, env->segs[R_DS].selector);
144f20f9df0SAndreas Färber         case IDX_SEG_REGS + 3:
145986a2998SAndreas Färber             return gdb_get_reg32(mem_buf, env->segs[R_ES].selector);
146f20f9df0SAndreas Färber         case IDX_SEG_REGS + 4:
147986a2998SAndreas Färber             return gdb_get_reg32(mem_buf, env->segs[R_FS].selector);
148f20f9df0SAndreas Färber         case IDX_SEG_REGS + 5:
149986a2998SAndreas Färber             return gdb_get_reg32(mem_buf, env->segs[R_GS].selector);
150f20f9df0SAndreas Färber 
151*7b0f97baSDoug Gale         case IDX_SEG_REGS + 6:
152*7b0f97baSDoug Gale             if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
153*7b0f97baSDoug Gale                 return gdb_get_reg64(mem_buf, env->segs[R_FS].base);
154*7b0f97baSDoug Gale             }
155*7b0f97baSDoug Gale             return gdb_get_reg32(mem_buf, env->segs[R_FS].base);
156*7b0f97baSDoug Gale 
157*7b0f97baSDoug Gale         case IDX_SEG_REGS + 7:
158*7b0f97baSDoug Gale             if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
159*7b0f97baSDoug Gale                 return gdb_get_reg64(mem_buf, env->segs[R_GS].base);
160*7b0f97baSDoug Gale             }
161*7b0f97baSDoug Gale             return gdb_get_reg32(mem_buf, env->segs[R_GS].base);
162*7b0f97baSDoug Gale 
163*7b0f97baSDoug Gale         case IDX_SEG_REGS + 8:
164*7b0f97baSDoug Gale #ifdef TARGET_X86_64
165*7b0f97baSDoug Gale             if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
166*7b0f97baSDoug Gale                 return gdb_get_reg64(mem_buf, env->kernelgsbase);
167*7b0f97baSDoug Gale             }
168*7b0f97baSDoug Gale             return gdb_get_reg32(mem_buf, env->kernelgsbase);
169*7b0f97baSDoug Gale #else
170*7b0f97baSDoug Gale             return gdb_get_reg32(mem_buf, 0);
171*7b0f97baSDoug Gale #endif
172*7b0f97baSDoug Gale 
173f20f9df0SAndreas Färber         case IDX_FP_REGS + 8:
174986a2998SAndreas Färber             return gdb_get_reg32(mem_buf, env->fpuc);
175f20f9df0SAndreas Färber         case IDX_FP_REGS + 9:
176986a2998SAndreas Färber             return gdb_get_reg32(mem_buf, (env->fpus & ~0x3800) |
177f20f9df0SAndreas Färber                                           (env->fpstt & 0x7) << 11);
178f20f9df0SAndreas Färber         case IDX_FP_REGS + 10:
179986a2998SAndreas Färber             return gdb_get_reg32(mem_buf, 0); /* ftag */
180f20f9df0SAndreas Färber         case IDX_FP_REGS + 11:
181986a2998SAndreas Färber             return gdb_get_reg32(mem_buf, 0); /* fiseg */
182f20f9df0SAndreas Färber         case IDX_FP_REGS + 12:
183986a2998SAndreas Färber             return gdb_get_reg32(mem_buf, 0); /* fioff */
184f20f9df0SAndreas Färber         case IDX_FP_REGS + 13:
185986a2998SAndreas Färber             return gdb_get_reg32(mem_buf, 0); /* foseg */
186f20f9df0SAndreas Färber         case IDX_FP_REGS + 14:
187986a2998SAndreas Färber             return gdb_get_reg32(mem_buf, 0); /* fooff */
188f20f9df0SAndreas Färber         case IDX_FP_REGS + 15:
189986a2998SAndreas Färber             return gdb_get_reg32(mem_buf, 0); /* fop */
190f20f9df0SAndreas Färber 
191f20f9df0SAndreas Färber         case IDX_MXCSR_REG:
192986a2998SAndreas Färber             return gdb_get_reg32(mem_buf, env->mxcsr);
193*7b0f97baSDoug Gale 
194*7b0f97baSDoug Gale         case IDX_CTL_CR0_REG:
195*7b0f97baSDoug Gale             if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
196*7b0f97baSDoug Gale                 return gdb_get_reg64(mem_buf, env->cr[0]);
197*7b0f97baSDoug Gale             }
198*7b0f97baSDoug Gale             return gdb_get_reg32(mem_buf, env->cr[0]);
199*7b0f97baSDoug Gale 
200*7b0f97baSDoug Gale         case IDX_CTL_CR2_REG:
201*7b0f97baSDoug Gale             if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
202*7b0f97baSDoug Gale                 return gdb_get_reg64(mem_buf, env->cr[2]);
203*7b0f97baSDoug Gale             }
204*7b0f97baSDoug Gale             return gdb_get_reg32(mem_buf, env->cr[2]);
205*7b0f97baSDoug Gale 
206*7b0f97baSDoug Gale         case IDX_CTL_CR3_REG:
207*7b0f97baSDoug Gale             if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
208*7b0f97baSDoug Gale                 return gdb_get_reg64(mem_buf, env->cr[3]);
209*7b0f97baSDoug Gale             }
210*7b0f97baSDoug Gale             return gdb_get_reg32(mem_buf, env->cr[3]);
211*7b0f97baSDoug Gale 
212*7b0f97baSDoug Gale         case IDX_CTL_CR4_REG:
213*7b0f97baSDoug Gale             if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
214*7b0f97baSDoug Gale                 return gdb_get_reg64(mem_buf, env->cr[4]);
215*7b0f97baSDoug Gale             }
216*7b0f97baSDoug Gale             return gdb_get_reg32(mem_buf, env->cr[4]);
217*7b0f97baSDoug Gale 
218*7b0f97baSDoug Gale         case IDX_CTL_CR8_REG:
219*7b0f97baSDoug Gale #ifdef CONFIG_SOFTMMU
220*7b0f97baSDoug Gale             tpr = cpu_get_apic_tpr(cpu->apic_state);
221*7b0f97baSDoug Gale #else
222*7b0f97baSDoug Gale             tpr = 0;
223*7b0f97baSDoug Gale #endif
224*7b0f97baSDoug Gale             if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
225*7b0f97baSDoug Gale                 return gdb_get_reg64(mem_buf, tpr);
226*7b0f97baSDoug Gale             }
227*7b0f97baSDoug Gale             return gdb_get_reg32(mem_buf, tpr);
228*7b0f97baSDoug Gale 
229*7b0f97baSDoug Gale         case IDX_CTL_EFER_REG:
230*7b0f97baSDoug Gale             if ((env->hflags & HF_CS64_MASK) || GDB_FORCE_64) {
231*7b0f97baSDoug Gale                 return gdb_get_reg64(mem_buf, env->efer);
232*7b0f97baSDoug Gale             }
233*7b0f97baSDoug Gale             return gdb_get_reg32(mem_buf, env->efer);
234f20f9df0SAndreas Färber         }
235f20f9df0SAndreas Färber     }
236f20f9df0SAndreas Färber     return 0;
237f20f9df0SAndreas Färber }
238f20f9df0SAndreas Färber 
2395b50e790SAndreas Färber static int x86_cpu_gdb_load_seg(X86CPU *cpu, int sreg, uint8_t *mem_buf)
240f20f9df0SAndreas Färber {
2415b50e790SAndreas Färber     CPUX86State *env = &cpu->env;
242f20f9df0SAndreas Färber     uint16_t selector = ldl_p(mem_buf);
243f20f9df0SAndreas Färber 
244f20f9df0SAndreas Färber     if (selector != env->segs[sreg].selector) {
245f20f9df0SAndreas Färber #if defined(CONFIG_USER_ONLY)
246f20f9df0SAndreas Färber         cpu_x86_load_seg(env, sreg, selector);
247f20f9df0SAndreas Färber #else
248f20f9df0SAndreas Färber         unsigned int limit, flags;
249f20f9df0SAndreas Färber         target_ulong base;
250f20f9df0SAndreas Färber 
251f20f9df0SAndreas Färber         if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
252b98dbc90SPaolo Bonzini             int dpl = (env->eflags & VM_MASK) ? 3 : 0;
253f20f9df0SAndreas Färber             base = selector << 4;
254f20f9df0SAndreas Färber             limit = 0xffff;
255b98dbc90SPaolo Bonzini             flags = DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
256b98dbc90SPaolo Bonzini                     DESC_A_MASK | (dpl << DESC_DPL_SHIFT);
257f20f9df0SAndreas Färber         } else {
258f20f9df0SAndreas Färber             if (!cpu_x86_get_descr_debug(env, selector, &base, &limit,
259f20f9df0SAndreas Färber                                          &flags)) {
260f20f9df0SAndreas Färber                 return 4;
261f20f9df0SAndreas Färber             }
262f20f9df0SAndreas Färber         }
263f20f9df0SAndreas Färber         cpu_x86_load_seg_cache(env, sreg, selector, base, limit, flags);
264f20f9df0SAndreas Färber #endif
265f20f9df0SAndreas Färber     }
266f20f9df0SAndreas Färber     return 4;
267f20f9df0SAndreas Färber }
268f20f9df0SAndreas Färber 
2695b50e790SAndreas Färber int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
270f20f9df0SAndreas Färber {
2715b50e790SAndreas Färber     X86CPU *cpu = X86_CPU(cs);
2725b50e790SAndreas Färber     CPUX86State *env = &cpu->env;
273f20f9df0SAndreas Färber     uint32_t tmp;
274f20f9df0SAndreas Färber 
275e3592bc9SDoug Evans     /* N.B. GDB can't deal with changes in registers or sizes in the middle
276e3592bc9SDoug Evans        of a session. So if we're in 32-bit mode on a 64-bit cpu, still act
277e3592bc9SDoug Evans        as if we're on a 64-bit cpu. */
278e3592bc9SDoug Evans 
279f20f9df0SAndreas Färber     if (n < CPU_NB_REGS) {
280e3592bc9SDoug Evans         if (TARGET_LONG_BITS == 64) {
281e3592bc9SDoug Evans             if (env->hflags & HF_CS64_MASK) {
282f20f9df0SAndreas Färber                 env->regs[gpr_map[n]] = ldtul_p(mem_buf);
283e3592bc9SDoug Evans             } else if (n < CPU_NB_REGS32) {
284e3592bc9SDoug Evans                 env->regs[gpr_map[n]] = ldtul_p(mem_buf) & 0xffffffffUL;
285e3592bc9SDoug Evans             }
286f20f9df0SAndreas Färber             return sizeof(target_ulong);
287f20f9df0SAndreas Färber         } else if (n < CPU_NB_REGS32) {
288f20f9df0SAndreas Färber             n = gpr_map32[n];
289f20f9df0SAndreas Färber             env->regs[n] &= ~0xffffffffUL;
290f20f9df0SAndreas Färber             env->regs[n] |= (uint32_t)ldl_p(mem_buf);
291f20f9df0SAndreas Färber             return 4;
292f20f9df0SAndreas Färber         }
293f20f9df0SAndreas Färber     } else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
294f20f9df0SAndreas Färber #ifdef USE_X86LDOUBLE
295f20f9df0SAndreas Färber         /* FIXME: byteswap float values - after fixing fpregs layout. */
296f20f9df0SAndreas Färber         memcpy(&env->fpregs[n - IDX_FP_REGS], mem_buf, 10);
297f20f9df0SAndreas Färber #endif
298f20f9df0SAndreas Färber         return 10;
299f20f9df0SAndreas Färber     } else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
300f20f9df0SAndreas Färber         n -= IDX_XMM_REGS;
301e3592bc9SDoug Evans         if (n < CPU_NB_REGS32 || TARGET_LONG_BITS == 64) {
30219cbd87cSEduardo Habkost             env->xmm_regs[n].ZMM_Q(0) = ldq_p(mem_buf);
30319cbd87cSEduardo Habkost             env->xmm_regs[n].ZMM_Q(1) = ldq_p(mem_buf + 8);
304f20f9df0SAndreas Färber             return 16;
305f20f9df0SAndreas Färber         }
306f20f9df0SAndreas Färber     } else {
307f20f9df0SAndreas Färber         switch (n) {
308f20f9df0SAndreas Färber         case IDX_IP_REG:
309e3592bc9SDoug Evans             if (TARGET_LONG_BITS == 64) {
310e3592bc9SDoug Evans                 if (env->hflags & HF_CS64_MASK) {
311f20f9df0SAndreas Färber                     env->eip = ldq_p(mem_buf);
312e3592bc9SDoug Evans                 } else {
313e3592bc9SDoug Evans                     env->eip = ldq_p(mem_buf) & 0xffffffffUL;
314e3592bc9SDoug Evans                 }
315f20f9df0SAndreas Färber                 return 8;
316f20f9df0SAndreas Färber             } else {
317f20f9df0SAndreas Färber                 env->eip &= ~0xffffffffUL;
318f20f9df0SAndreas Färber                 env->eip |= (uint32_t)ldl_p(mem_buf);
319f20f9df0SAndreas Färber                 return 4;
320f20f9df0SAndreas Färber             }
321f20f9df0SAndreas Färber         case IDX_FLAGS_REG:
322f20f9df0SAndreas Färber             env->eflags = ldl_p(mem_buf);
323f20f9df0SAndreas Färber             return 4;
324f20f9df0SAndreas Färber 
325f20f9df0SAndreas Färber         case IDX_SEG_REGS:
3265b50e790SAndreas Färber             return x86_cpu_gdb_load_seg(cpu, R_CS, mem_buf);
327f20f9df0SAndreas Färber         case IDX_SEG_REGS + 1:
3285b50e790SAndreas Färber             return x86_cpu_gdb_load_seg(cpu, R_SS, mem_buf);
329f20f9df0SAndreas Färber         case IDX_SEG_REGS + 2:
3305b50e790SAndreas Färber             return x86_cpu_gdb_load_seg(cpu, R_DS, mem_buf);
331f20f9df0SAndreas Färber         case IDX_SEG_REGS + 3:
3325b50e790SAndreas Färber             return x86_cpu_gdb_load_seg(cpu, R_ES, mem_buf);
333f20f9df0SAndreas Färber         case IDX_SEG_REGS + 4:
3345b50e790SAndreas Färber             return x86_cpu_gdb_load_seg(cpu, R_FS, mem_buf);
335f20f9df0SAndreas Färber         case IDX_SEG_REGS + 5:
3365b50e790SAndreas Färber             return x86_cpu_gdb_load_seg(cpu, R_GS, mem_buf);
337f20f9df0SAndreas Färber 
338*7b0f97baSDoug Gale         case IDX_SEG_REGS + 6:
339*7b0f97baSDoug Gale             if (env->hflags & HF_CS64_MASK) {
340*7b0f97baSDoug Gale                 env->segs[R_FS].base = ldq_p(mem_buf);
341*7b0f97baSDoug Gale                 return 8;
342*7b0f97baSDoug Gale             }
343*7b0f97baSDoug Gale             env->segs[R_FS].base = ldl_p(mem_buf);
344*7b0f97baSDoug Gale             return 4;
345*7b0f97baSDoug Gale 
346*7b0f97baSDoug Gale         case IDX_SEG_REGS + 7:
347*7b0f97baSDoug Gale             if (env->hflags & HF_CS64_MASK) {
348*7b0f97baSDoug Gale                 env->segs[R_GS].base = ldq_p(mem_buf);
349*7b0f97baSDoug Gale                 return 8;
350*7b0f97baSDoug Gale             }
351*7b0f97baSDoug Gale             env->segs[R_GS].base = ldl_p(mem_buf);
352*7b0f97baSDoug Gale             return 4;
353*7b0f97baSDoug Gale 
354*7b0f97baSDoug Gale #ifdef TARGET_X86_64
355*7b0f97baSDoug Gale         case IDX_SEG_REGS + 8:
356*7b0f97baSDoug Gale             if (env->hflags & HF_CS64_MASK) {
357*7b0f97baSDoug Gale                 env->kernelgsbase = ldq_p(mem_buf);
358*7b0f97baSDoug Gale                 return 8;
359*7b0f97baSDoug Gale             }
360*7b0f97baSDoug Gale             env->kernelgsbase = ldl_p(mem_buf);
361*7b0f97baSDoug Gale             return 4;
362*7b0f97baSDoug Gale #endif
363*7b0f97baSDoug Gale 
364f20f9df0SAndreas Färber         case IDX_FP_REGS + 8:
3655bde1407SPavel Dovgalyuk             cpu_set_fpuc(env, ldl_p(mem_buf));
366f20f9df0SAndreas Färber             return 4;
367f20f9df0SAndreas Färber         case IDX_FP_REGS + 9:
368f20f9df0SAndreas Färber             tmp = ldl_p(mem_buf);
369f20f9df0SAndreas Färber             env->fpstt = (tmp >> 11) & 7;
370f20f9df0SAndreas Färber             env->fpus = tmp & ~0x3800;
371f20f9df0SAndreas Färber             return 4;
372f20f9df0SAndreas Färber         case IDX_FP_REGS + 10: /* ftag */
373f20f9df0SAndreas Färber             return 4;
374f20f9df0SAndreas Färber         case IDX_FP_REGS + 11: /* fiseg */
375f20f9df0SAndreas Färber             return 4;
376f20f9df0SAndreas Färber         case IDX_FP_REGS + 12: /* fioff */
377f20f9df0SAndreas Färber             return 4;
378f20f9df0SAndreas Färber         case IDX_FP_REGS + 13: /* foseg */
379f20f9df0SAndreas Färber             return 4;
380f20f9df0SAndreas Färber         case IDX_FP_REGS + 14: /* fooff */
381f20f9df0SAndreas Färber             return 4;
382f20f9df0SAndreas Färber         case IDX_FP_REGS + 15: /* fop */
383f20f9df0SAndreas Färber             return 4;
384f20f9df0SAndreas Färber 
385f20f9df0SAndreas Färber         case IDX_MXCSR_REG:
3864e47e39aSRichard Henderson             cpu_set_mxcsr(env, ldl_p(mem_buf));
387f20f9df0SAndreas Färber             return 4;
388*7b0f97baSDoug Gale 
389*7b0f97baSDoug Gale         case IDX_CTL_CR0_REG:
390*7b0f97baSDoug Gale             if (env->hflags & HF_CS64_MASK) {
391*7b0f97baSDoug Gale                 cpu_x86_update_cr0(env, ldq_p(mem_buf));
392*7b0f97baSDoug Gale                 return 8;
393*7b0f97baSDoug Gale             }
394*7b0f97baSDoug Gale             cpu_x86_update_cr0(env, ldl_p(mem_buf));
395*7b0f97baSDoug Gale             return 4;
396*7b0f97baSDoug Gale 
397*7b0f97baSDoug Gale         case IDX_CTL_CR2_REG:
398*7b0f97baSDoug Gale             if (env->hflags & HF_CS64_MASK) {
399*7b0f97baSDoug Gale                 env->cr[2] = ldq_p(mem_buf);
400*7b0f97baSDoug Gale                 return 8;
401*7b0f97baSDoug Gale             }
402*7b0f97baSDoug Gale             env->cr[2] = ldl_p(mem_buf);
403*7b0f97baSDoug Gale             return 4;
404*7b0f97baSDoug Gale 
405*7b0f97baSDoug Gale         case IDX_CTL_CR3_REG:
406*7b0f97baSDoug Gale             if (env->hflags & HF_CS64_MASK) {
407*7b0f97baSDoug Gale                 cpu_x86_update_cr3(env, ldq_p(mem_buf));
408*7b0f97baSDoug Gale                 return 8;
409*7b0f97baSDoug Gale             }
410*7b0f97baSDoug Gale             cpu_x86_update_cr3(env, ldl_p(mem_buf));
411*7b0f97baSDoug Gale             return 4;
412*7b0f97baSDoug Gale 
413*7b0f97baSDoug Gale         case IDX_CTL_CR4_REG:
414*7b0f97baSDoug Gale             if (env->hflags & HF_CS64_MASK) {
415*7b0f97baSDoug Gale                 cpu_x86_update_cr4(env, ldq_p(mem_buf));
416*7b0f97baSDoug Gale                 return 8;
417*7b0f97baSDoug Gale             }
418*7b0f97baSDoug Gale             cpu_x86_update_cr4(env, ldl_p(mem_buf));
419*7b0f97baSDoug Gale             return 4;
420*7b0f97baSDoug Gale 
421*7b0f97baSDoug Gale         case IDX_CTL_CR8_REG:
422*7b0f97baSDoug Gale             if (env->hflags & HF_CS64_MASK) {
423*7b0f97baSDoug Gale #ifdef CONFIG_SOFTMMU
424*7b0f97baSDoug Gale                 cpu_set_apic_tpr(cpu->apic_state, ldq_p(mem_buf));
425*7b0f97baSDoug Gale #endif
426*7b0f97baSDoug Gale                 return 8;
427*7b0f97baSDoug Gale             }
428*7b0f97baSDoug Gale #ifdef CONFIG_SOFTMMU
429*7b0f97baSDoug Gale             cpu_set_apic_tpr(cpu->apic_state, ldl_p(mem_buf));
430*7b0f97baSDoug Gale #endif
431*7b0f97baSDoug Gale             return 4;
432*7b0f97baSDoug Gale 
433*7b0f97baSDoug Gale         case IDX_CTL_EFER_REG:
434*7b0f97baSDoug Gale             if (env->hflags & HF_CS64_MASK) {
435*7b0f97baSDoug Gale                 cpu_load_efer(env, ldq_p(mem_buf));
436*7b0f97baSDoug Gale                 return 8;
437*7b0f97baSDoug Gale             }
438*7b0f97baSDoug Gale             cpu_load_efer(env, ldl_p(mem_buf));
439*7b0f97baSDoug Gale             return 4;
440*7b0f97baSDoug Gale 
441f20f9df0SAndreas Färber         }
442f20f9df0SAndreas Färber     }
443f20f9df0SAndreas Färber     /* Unrecognised register.  */
444f20f9df0SAndreas Färber     return 0;
445f20f9df0SAndreas Färber }
446