* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "qemu-common.h"
8, 9, 10, 11, 12, 13, 14, 15
};
#else
-static const int gpr_map[8] = {0, 1, 2, 3, 4, 5, 6, 7};
+#define gpr_map gpr_map32
#endif
+static const int gpr_map32[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
#define NUM_CORE_REGS (CPU_NB_REGS * 2 + 25)
static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
{
if (n < CPU_NB_REGS) {
- GET_REGL(env->regs[gpr_map[n]]);
+ if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
+ GET_REG64(env->regs[gpr_map[n]]);
+ } else if (n < CPU_NB_REGS32) {
+ GET_REG32(env->regs[gpr_map32[n]]);
+ }
} else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
#ifdef USE_X86LDOUBLE
/* FIXME: byteswap float values - after fixing fpregs layout. */
return 10;
} else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
n -= IDX_XMM_REGS;
- stq_p(mem_buf, env->xmm_regs[n].XMM_Q(0));
- stq_p(mem_buf + 8, env->xmm_regs[n].XMM_Q(1));
- return 16;
+ if (n < CPU_NB_REGS32 ||
+ (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK)) {
+ stq_p(mem_buf, env->xmm_regs[n].XMM_Q(0));
+ stq_p(mem_buf + 8, env->xmm_regs[n].XMM_Q(1));
+ return 16;
+ }
} else {
switch (n) {
- case IDX_IP_REG: GET_REGL(env->eip);
+ case IDX_IP_REG:
+ if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
+ GET_REG64(env->eip);
+ } else {
+ GET_REG32(env->eip);
+ }
case IDX_FLAGS_REG: GET_REG32(env->eflags);
case IDX_SEG_REGS: GET_REG32(env->segs[R_CS].selector);
return 0;
}
+static int cpu_x86_gdb_load_seg(CPUState *env, int sreg, uint8_t *mem_buf)
+{
+ uint16_t selector = ldl_p(mem_buf);
+
+ if (selector != env->segs[sreg].selector) {
+#if defined(CONFIG_USER_ONLY)
+ cpu_x86_load_seg(env, sreg, selector);
+#else
+ unsigned int limit, flags;
+ target_ulong base;
+
+ if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
+ base = selector << 4;
+ limit = 0xffff;
+ flags = 0;
+ } else {
+ if (!cpu_x86_get_descr_debug(env, selector, &base, &limit, &flags))
+ return 4;
+ }
+ cpu_x86_load_seg_cache(env, sreg, selector, base, limit, flags);
+#endif
+ }
+ return 4;
+}
+
static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
{
uint32_t tmp;
if (n < CPU_NB_REGS) {
- env->regs[gpr_map[n]] = ldtul_p(mem_buf);
- return sizeof(target_ulong);
+ if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
+ env->regs[gpr_map[n]] = ldtul_p(mem_buf);
+ return sizeof(target_ulong);
+ } else if (n < CPU_NB_REGS32) {
+ n = gpr_map32[n];
+ env->regs[n] &= ~0xffffffffUL;
+ env->regs[n] |= (uint32_t)ldl_p(mem_buf);
+ return 4;
+ }
} else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
#ifdef USE_X86LDOUBLE
/* FIXME: byteswap float values - after fixing fpregs layout. */
return 10;
} else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
n -= IDX_XMM_REGS;
- env->xmm_regs[n].XMM_Q(0) = ldq_p(mem_buf);
- env->xmm_regs[n].XMM_Q(1) = ldq_p(mem_buf + 8);
- return 16;
+ if (n < CPU_NB_REGS32 ||
+ (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK)) {
+ env->xmm_regs[n].XMM_Q(0) = ldq_p(mem_buf);
+ env->xmm_regs[n].XMM_Q(1) = ldq_p(mem_buf + 8);
+ return 16;
+ }
} else {
switch (n) {
case IDX_IP_REG:
- env->eip = ldtul_p(mem_buf);
- return sizeof(target_ulong);
+ if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
+ env->eip = ldq_p(mem_buf);
+ return 8;
+ } else {
+ env->eip &= ~0xffffffffUL;
+ env->eip |= (uint32_t)ldl_p(mem_buf);
+ return 4;
+ }
case IDX_FLAGS_REG:
env->eflags = ldl_p(mem_buf);
return 4;
-#if defined(CONFIG_USER_ONLY)
-#define LOAD_SEG(index, sreg)\
- tmp = ldl_p(mem_buf);\
- if (tmp != env->segs[sreg].selector)\
- cpu_x86_load_seg(env, sreg, tmp);\
- return 4
-#else
-/* FIXME: Honor segment registers. Needs to avoid raising an exception
- when the selector is invalid. */
-#define LOAD_SEG(index, sreg) return 4
-#endif
- case IDX_SEG_REGS: LOAD_SEG(10, R_CS);
- case IDX_SEG_REGS + 1: LOAD_SEG(11, R_SS);
- case IDX_SEG_REGS + 2: LOAD_SEG(12, R_DS);
- case IDX_SEG_REGS + 3: LOAD_SEG(13, R_ES);
- case IDX_SEG_REGS + 4: LOAD_SEG(14, R_FS);
- case IDX_SEG_REGS + 5: LOAD_SEG(15, R_GS);
+ case IDX_SEG_REGS: return cpu_x86_gdb_load_seg(env, R_CS, mem_buf);
+ case IDX_SEG_REGS + 1: return cpu_x86_gdb_load_seg(env, R_SS, mem_buf);
+ case IDX_SEG_REGS + 2: return cpu_x86_gdb_load_seg(env, R_DS, mem_buf);
+ case IDX_SEG_REGS + 3: return cpu_x86_gdb_load_seg(env, R_ES, mem_buf);
+ case IDX_SEG_REGS + 4: return cpu_x86_gdb_load_seg(env, R_FS, mem_buf);
+ case IDX_SEG_REGS + 5: return cpu_x86_gdb_load_seg(env, R_GS, mem_buf);
case IDX_FP_REGS + 8:
env->fpuc = ldl_p(mem_buf);
else if (n<63) {
uint64_t val;
- val=*((uint64_t *)&env->fir[n-32]);
+ val = *((uint64_t *)&env->fir[n-32]);
GET_REGL(val);
}
else if (n==63) {
static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
{
#if defined(TARGET_I386)
+ cpu_synchronize_state(s->c_cpu);
s->c_cpu->eip = pc;
- cpu_synchronize_state(s->c_cpu, 1);
#elif defined (TARGET_PPC)
s->c_cpu->nip = pc;
#elif defined (TARGET_SPARC)
static inline int gdb_id(CPUState *env)
{
-#if defined(CONFIG_USER_ONLY) && defined(USE_NPTL)
+#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USE_NPTL)
return env->host_tid;
#else
return env->cpu_index + 1;
}
break;
case 'g':
- cpu_synchronize_state(s->g_cpu, 0);
+ cpu_synchronize_state(s->g_cpu);
len = 0;
for (addr = 0; addr < num_g_regs; addr++) {
reg_size = gdb_read_register(s->g_cpu, mem_buf + len, addr);
put_packet(s, buf);
break;
case 'G':
+ cpu_synchronize_state(s->g_cpu);
registers = mem_buf;
len = strlen(p) / 2;
hextomem((uint8_t *)registers, p, len);
len -= reg_size;
registers += reg_size;
}
- cpu_synchronize_state(s->g_cpu, 1);
put_packet(s, "OK");
break;
case 'm':
thread = strtoull(p+16, (char **)&p, 16);
env = find_cpu(thread);
if (env != NULL) {
- cpu_synchronize_state(env, 0);
+ cpu_synchronize_state(env);
len = snprintf((char *)mem_buf, sizeof(mem_buf),
"CPU#%d [%s]", env->cpu_index,
env->halted ? "halted " : "running");