write to both IDE drives - return 0 for not present drives
[qemu] / gdbstub.c
index d73a7ef..29f73c9 100644 (file)
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -248,41 +248,152 @@ static int put_packet(char *buf)
     return 0;
 }
 
-static int memory_rw(uint8_t *buf, uint32_t addr, int len, int is_write)
+#if defined(TARGET_I386)
+
+static void to_le32(uint8_t *p, int v)
 {
-    int l, flags;
-    uint32_t page;
+    p[0] = v;
+    p[1] = v >> 8;
+    p[2] = v >> 16;
+    p[3] = v >> 24;
+}
 
-    while (len > 0) {
-        page = addr & TARGET_PAGE_MASK;
-        l = (page + TARGET_PAGE_SIZE) - addr;
-        if (l > len)
-            l = len;
-        flags = page_get_flags(page);
-        if (!(flags & PAGE_VALID))
-            return -1;
-        if (is_write) {
-            if (!(flags & PAGE_WRITE))
-                return -1;
-            memcpy((uint8_t *)addr, buf, l);
-        } else {
-            if (!(flags & PAGE_READ))
-                return -1;
-            memcpy(buf, (uint8_t *)addr, l);
-        }
-        len -= l;
-        buf += l;
-        addr += l;
+static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
+{
+    int i, fpus;
+
+    for(i = 0; i < 8; i++) {
+        to_le32(mem_buf + i * 4, env->regs[i]);
+    }
+    to_le32(mem_buf + 8 * 4, env->eip);
+    to_le32(mem_buf + 9 * 4, env->eflags);
+    to_le32(mem_buf + 10 * 4, env->segs[R_CS].selector);
+    to_le32(mem_buf + 11 * 4, env->segs[R_SS].selector);
+    to_le32(mem_buf + 12 * 4, env->segs[R_DS].selector);
+    to_le32(mem_buf + 13 * 4, env->segs[R_ES].selector);
+    to_le32(mem_buf + 14 * 4, env->segs[R_FS].selector);
+    to_le32(mem_buf + 15 * 4, env->segs[R_GS].selector);
+    /* XXX: convert floats */
+    for(i = 0; i < 8; i++) {
+        memcpy(mem_buf + 16 * 4 + i * 10, &env->fpregs[i], 10);
+    }
+    to_le32(mem_buf + 36 * 4, env->fpuc);
+    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
+    to_le32(mem_buf + 37 * 4, fpus);
+    to_le32(mem_buf + 38 * 4, 0); /* XXX: convert tags */
+    to_le32(mem_buf + 39 * 4, 0); /* fiseg */
+    to_le32(mem_buf + 40 * 4, 0); /* fioff */
+    to_le32(mem_buf + 41 * 4, 0); /* foseg */
+    to_le32(mem_buf + 42 * 4, 0); /* fooff */
+    to_le32(mem_buf + 43 * 4, 0); /* fop */
+    return 44 * 4;
+}
+
+static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
+{
+    uint32_t *registers = (uint32_t *)mem_buf;
+    int i;
+
+    for(i = 0; i < 8; i++) {
+        env->regs[i] = tswapl(registers[i]);
+    }
+    env->eip = registers[8];
+    env->eflags = registers[9];
+#if defined(CONFIG_USER_ONLY)
+#define LOAD_SEG(index, sreg)\
+            if (tswapl(registers[index]) != env->segs[sreg].selector)\
+                cpu_x86_load_seg(env, sreg, tswapl(registers[index]));
+            LOAD_SEG(10, R_CS);
+            LOAD_SEG(11, R_SS);
+            LOAD_SEG(12, R_DS);
+            LOAD_SEG(13, R_ES);
+            LOAD_SEG(14, R_FS);
+            LOAD_SEG(15, R_GS);
+#endif
+}
+
+#elif defined (TARGET_PPC)
+static void to_le32(uint8_t *p, int v)
+{
+    p[3] = v;
+    p[2] = v >> 8;
+    p[1] = v >> 16;
+    p[0] = v >> 24;
+}
+
+static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
+{
+    uint32_t tmp;
+    int i;
+
+    /* fill in gprs */
+    for(i = 0; i < 8; i++) {
+        to_le32(mem_buf + i * 4, env->gpr[i]);
+    }
+    /* fill in fprs */
+    for (i = 0; i < 32; i++) {
+        to_le32(mem_buf + (i * 2) + 32, *((uint32_t *)&env->fpr[i]));
+       to_le32(mem_buf + (i * 2) + 33, *((uint32_t *)&env->fpr[i] + 1));
     }
+    /* nip, msr, ccr, lnk, ctr, xer, mq */
+    to_le32(mem_buf + 96, tswapl(env->nip));
+    to_le32(mem_buf + 97, tswapl(_load_msr()));
+    to_le32(mem_buf + 98, 0);
+    tmp = 0;
+    for (i = 0; i < 8; i++)
+        tmp |= env->crf[i] << (32 - (i * 4));
+    to_le32(mem_buf + 98, tmp);
+    to_le32(mem_buf + 99, tswapl(env->lr));
+    to_le32(mem_buf + 100, tswapl(env->ctr));
+    to_le32(mem_buf + 101, tswapl(_load_xer()));
+    to_le32(mem_buf + 102, 0);
+
+    return 102;
+}
+
+static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
+{
+    uint32_t *registers = (uint32_t *)mem_buf;
+    int i;
+
+    /* fill in gprs */
+    for (i = 0; i < 32; i++) {
+        env->gpr[i] = tswapl(registers[i]);
+    }
+    /* fill in fprs */
+    for (i = 0; i < 32; i++) {
+        *((uint32_t *)&env->fpr[i]) = tswapl(registers[(i * 2) + 32]);
+       *((uint32_t *)&env->fpr[i] + 1) = tswapl(registers[(i * 2) + 33]);
+    }
+    /* nip, msr, ccr, lnk, ctr, xer, mq */
+    env->nip = tswapl(registers[96]);
+    _store_msr(tswapl(registers[97]));
+    registers[98] = tswapl(registers[98]);
+    for (i = 0; i < 8; i++)
+        env->crf[i] = (registers[98] >> (32 - (i * 4))) & 0xF;
+    env->lr = tswapl(registers[99]);
+    env->ctr = tswapl(registers[100]);
+    _store_xer(tswapl(registers[101]));
+}
+#else
+
+static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
+{
     return 0;
 }
 
+static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
+{
+}
+
+#endif
+
 /* port = 0 means default port */
 int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port)
 {
     CPUState *env;
     const char *p;
-    int ret, ch, nb_regs, i, type;
+    int ret, ch, reg_size, type;
     char buf[4096];
     uint8_t mem_buf[2000];
     uint32_t *registers;
@@ -309,6 +420,8 @@ int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port)
                 env = cpu_gdbstub_get_env(opaque);
 #if defined(TARGET_I386)
                 env->eip = addr;
+#elif defined (TARGET_PPC)
+                env->nip = addr;
 #endif
             }
             ret = main_loop(opaque);
@@ -325,6 +438,8 @@ int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port)
                 addr = strtoul(p, (char **)&p, 16);
 #if defined(TARGET_I386)
                 env->eip = addr;
+#elif defined (TARGET_PPC)
+                env->nip = addr;
 #endif
             }
             cpu_single_step(env, 1);
@@ -339,58 +454,31 @@ int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port)
             break;
         case 'g':
             env = cpu_gdbstub_get_env(opaque);
-            registers = (void *)mem_buf;
-#if defined(TARGET_I386)
-            for(i = 0; i < 8; i++) {
-                registers[i] = tswapl(env->regs[i]);
-            }
-            registers[8] = env->eip;
-            registers[9] = env->eflags;
-            registers[10] = env->segs[R_CS].selector;
-            registers[11] = env->segs[R_SS].selector;
-            registers[12] = env->segs[R_DS].selector;
-            registers[13] = env->segs[R_ES].selector;
-            registers[14] = env->segs[R_FS].selector;
-            registers[15] = env->segs[R_GS].selector;
-            nb_regs = 16;
-#endif
-            memtohex(buf, (const uint8_t *)registers, 
-                     sizeof(registers[0]) * nb_regs);
+            reg_size = cpu_gdb_read_registers(env, mem_buf);
+            memtohex(buf, mem_buf, reg_size);
             put_packet(buf);
             break;
         case 'G':
             env = cpu_gdbstub_get_env(opaque);
             registers = (void *)mem_buf;
-#if defined(TARGET_I386)
-            hextomem((uint8_t *)registers, p, 16 * 4);
-            for(i = 0; i < 8; i++) {
-                env->regs[i] = tswapl(registers[i]);
-            }
-            env->eip = registers[8];
-            env->eflags = registers[9];
-#define LOAD_SEG(index, sreg)\
-            if (tswapl(registers[index]) != env->segs[sreg].selector)\
-                cpu_x86_load_seg(env, sreg, tswapl(registers[index]));
-            LOAD_SEG(10, R_CS);
-            LOAD_SEG(11, R_SS);
-            LOAD_SEG(12, R_DS);
-            LOAD_SEG(13, R_ES);
-            LOAD_SEG(14, R_FS);
-            LOAD_SEG(15, R_GS);
-#endif
+            len = strlen(p) / 2;
+            hextomem((uint8_t *)registers, p, len);
+            cpu_gdb_write_registers(env, mem_buf, len);
             put_packet("OK");
             break;
         case 'm':
+            env = cpu_gdbstub_get_env(opaque);
             addr = strtoul(p, (char **)&p, 16);
             if (*p == ',')
                 p++;
             len = strtoul(p, NULL, 16);
-            if (memory_rw(mem_buf, addr, len, 0) != 0)
+            if (cpu_memory_rw_debug(env, addr, mem_buf, len, 0) != 0)
                 memset(mem_buf, 0, len);
             memtohex(buf, mem_buf, len);
             put_packet(buf);
             break;
         case 'M':
+            env = cpu_gdbstub_get_env(opaque);
             addr = strtoul(p, (char **)&p, 16);
             if (*p == ',')
                 p++;
@@ -398,7 +486,7 @@ int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port)
             if (*p == ',')
                 p++;
             hextomem(mem_buf, p, len);
-            if (memory_rw(mem_buf, addr, len, 1) != 0)
+            if (cpu_memory_rw_debug(env, addr, mem_buf, len, 1) != 0)
                 put_packet("ENN");
             else
                 put_packet("OK");
@@ -437,7 +525,26 @@ int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port)
                 goto breakpoint_error;
             }
             break;
+        case 'Q':
+            if (!strncmp(p, "Tinit", 5)) {
+                /* init traces */
+                put_packet("OK");
+            } else if (!strncmp(p, "TStart", 6)) {
+                /* start log (gdb 'tstart' command) */
+                env = cpu_gdbstub_get_env(opaque);
+                tb_flush(env);
+                cpu_set_log(CPU_LOG_ALL);
+                put_packet("OK");
+            } else if (!strncmp(p, "TStop", 5)) {
+                /* stop log (gdb 'tstop' command) */
+                cpu_set_log(0);
+                put_packet("OK");
+            } else {
+                goto unknown_command;
+            }
+            break;
         default:
+        unknown_command:
             /* put empty packet */
             buf[0] = '\0';
             put_packet(buf);