Diff for /qemu/gdbstub.c between versions 1.1.1.6 and 1.1.1.7

version 1.1.1.6, 2018/04/24 16:47:03 version 1.1.1.7, 2018/04/24 16:50:16
Line 15 Line 15
  *   *
  * You should have received a copy of the GNU Lesser General Public   * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software   * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
  */   */
 #include "config.h"  #include "config.h"
   #include "qemu-common.h"
 #ifdef CONFIG_USER_ONLY  #ifdef CONFIG_USER_ONLY
 #include <stdlib.h>  #include <stdlib.h>
 #include <stdio.h>  #include <stdio.h>
Line 29 Line 30
   
 #include "qemu.h"  #include "qemu.h"
 #else  #else
 #include "qemu-common.h"  
 #include "qemu-char.h"  #include "qemu-char.h"
 #include "sysemu.h"  #include "sysemu.h"
 #include "gdbstub.h"  #include "gdbstub.h"
 #endif  #endif
   
   #define MAX_PACKET_LENGTH 4096
   
 #include "qemu_socket.h"  #include "qemu_socket.h"
 #ifdef _WIN32  
 /* XXX: these constants may be independent of the host ones even for Unix */  
 #ifndef SIGTRAP  enum {
 #define SIGTRAP 5      GDB_SIGNAL_0 = 0,
       GDB_SIGNAL_INT = 2,
       GDB_SIGNAL_TRAP = 5,
       GDB_SIGNAL_UNKNOWN = 143
   };
   
   #ifdef CONFIG_USER_ONLY
   
   /* Map target signal numbers to GDB protocol signal numbers and vice
    * versa.  For user emulation's currently supported systems, we can
    * assume most signals are defined.
    */
   
   static int gdb_signal_table[] = {
       0,
       TARGET_SIGHUP,
       TARGET_SIGINT,
       TARGET_SIGQUIT,
       TARGET_SIGILL,
       TARGET_SIGTRAP,
       TARGET_SIGABRT,
       -1, /* SIGEMT */
       TARGET_SIGFPE,
       TARGET_SIGKILL,
       TARGET_SIGBUS,
       TARGET_SIGSEGV,
       TARGET_SIGSYS,
       TARGET_SIGPIPE,
       TARGET_SIGALRM,
       TARGET_SIGTERM,
       TARGET_SIGURG,
       TARGET_SIGSTOP,
       TARGET_SIGTSTP,
       TARGET_SIGCONT,
       TARGET_SIGCHLD,
       TARGET_SIGTTIN,
       TARGET_SIGTTOU,
       TARGET_SIGIO,
       TARGET_SIGXCPU,
       TARGET_SIGXFSZ,
       TARGET_SIGVTALRM,
       TARGET_SIGPROF,
       TARGET_SIGWINCH,
       -1, /* SIGLOST */
       TARGET_SIGUSR1,
       TARGET_SIGUSR2,
   #ifdef TARGET_SIGPWR
       TARGET_SIGPWR,
   #else
       -1,
 #endif  #endif
 #ifndef SIGINT      -1, /* SIGPOLL */
 #define SIGINT 2      -1,
       -1,
       -1,
       -1,
       -1,
       -1,
       -1,
       -1,
       -1,
       -1,
       -1,
   #ifdef __SIGRTMIN
       __SIGRTMIN + 1,
       __SIGRTMIN + 2,
       __SIGRTMIN + 3,
       __SIGRTMIN + 4,
       __SIGRTMIN + 5,
       __SIGRTMIN + 6,
       __SIGRTMIN + 7,
       __SIGRTMIN + 8,
       __SIGRTMIN + 9,
       __SIGRTMIN + 10,
       __SIGRTMIN + 11,
       __SIGRTMIN + 12,
       __SIGRTMIN + 13,
       __SIGRTMIN + 14,
       __SIGRTMIN + 15,
       __SIGRTMIN + 16,
       __SIGRTMIN + 17,
       __SIGRTMIN + 18,
       __SIGRTMIN + 19,
       __SIGRTMIN + 20,
       __SIGRTMIN + 21,
       __SIGRTMIN + 22,
       __SIGRTMIN + 23,
       __SIGRTMIN + 24,
       __SIGRTMIN + 25,
       __SIGRTMIN + 26,
       __SIGRTMIN + 27,
       __SIGRTMIN + 28,
       __SIGRTMIN + 29,
       __SIGRTMIN + 30,
       __SIGRTMIN + 31,
       -1, /* SIGCANCEL */
       __SIGRTMIN,
       __SIGRTMIN + 32,
       __SIGRTMIN + 33,
       __SIGRTMIN + 34,
       __SIGRTMIN + 35,
       __SIGRTMIN + 36,
       __SIGRTMIN + 37,
       __SIGRTMIN + 38,
       __SIGRTMIN + 39,
       __SIGRTMIN + 40,
       __SIGRTMIN + 41,
       __SIGRTMIN + 42,
       __SIGRTMIN + 43,
       __SIGRTMIN + 44,
       __SIGRTMIN + 45,
       __SIGRTMIN + 46,
       __SIGRTMIN + 47,
       __SIGRTMIN + 48,
       __SIGRTMIN + 49,
       __SIGRTMIN + 50,
       __SIGRTMIN + 51,
       __SIGRTMIN + 52,
       __SIGRTMIN + 53,
       __SIGRTMIN + 54,
       __SIGRTMIN + 55,
       __SIGRTMIN + 56,
       __SIGRTMIN + 57,
       __SIGRTMIN + 58,
       __SIGRTMIN + 59,
       __SIGRTMIN + 60,
       __SIGRTMIN + 61,
       __SIGRTMIN + 62,
       __SIGRTMIN + 63,
       __SIGRTMIN + 64,
       __SIGRTMIN + 65,
       __SIGRTMIN + 66,
       __SIGRTMIN + 67,
       __SIGRTMIN + 68,
       __SIGRTMIN + 69,
       __SIGRTMIN + 70,
       __SIGRTMIN + 71,
       __SIGRTMIN + 72,
       __SIGRTMIN + 73,
       __SIGRTMIN + 74,
       __SIGRTMIN + 75,
       __SIGRTMIN + 76,
       __SIGRTMIN + 77,
       __SIGRTMIN + 78,
       __SIGRTMIN + 79,
       __SIGRTMIN + 80,
       __SIGRTMIN + 81,
       __SIGRTMIN + 82,
       __SIGRTMIN + 83,
       __SIGRTMIN + 84,
       __SIGRTMIN + 85,
       __SIGRTMIN + 86,
       __SIGRTMIN + 87,
       __SIGRTMIN + 88,
       __SIGRTMIN + 89,
       __SIGRTMIN + 90,
       __SIGRTMIN + 91,
       __SIGRTMIN + 92,
       __SIGRTMIN + 93,
       __SIGRTMIN + 94,
       __SIGRTMIN + 95,
       -1, /* SIGINFO */
       -1, /* UNKNOWN */
       -1, /* DEFAULT */
       -1,
       -1,
       -1,
       -1,
       -1,
       -1
 #endif  #endif
   };
 #else  #else
 #include <signal.h>  /* In system mode we only need SIGINT and SIGTRAP; other signals
      are not yet supported.  */
   
   enum {
       TARGET_SIGINT = 2,
       TARGET_SIGTRAP = 5
   };
   
   static int gdb_signal_table[] = {
       -1,
       -1,
       TARGET_SIGINT,
       -1,
       -1,
       TARGET_SIGTRAP
   };
   #endif
   
   #ifdef CONFIG_USER_ONLY
   static int target_signal_to_gdb (int sig)
   {
       int i;
       for (i = 0; i < ARRAY_SIZE (gdb_signal_table); i++)
           if (gdb_signal_table[i] == sig)
               return i;
       return GDB_SIGNAL_UNKNOWN;
   }
 #endif  #endif
   
   static int gdb_signal_to_target (int sig)
   {
       if (sig < ARRAY_SIZE (gdb_signal_table))
           return gdb_signal_table[sig];
       else
           return -1;
   }
   
 //#define DEBUG_GDB  //#define DEBUG_GDB
   
   typedef struct GDBRegisterState {
       int base_reg;
       int num_regs;
       gdb_reg_cb get_reg;
       gdb_reg_cb set_reg;
       const char *xml;
       struct GDBRegisterState *next;
   } GDBRegisterState;
   
 enum RSState {  enum RSState {
     RS_IDLE,      RS_IDLE,
     RS_GETLINE,      RS_GETLINE,
Line 58  enum RSState { Line 270  enum RSState {
     RS_SYSCALL,      RS_SYSCALL,
 };  };
 typedef struct GDBState {  typedef struct GDBState {
     CPUState *env; /* current CPU */      CPUState *c_cpu; /* current CPU for step/continue ops */
       CPUState *g_cpu; /* current CPU for other ops */
       CPUState *query_cpu; /* for q{f|s}ThreadInfo */
     enum RSState state; /* parsing state */      enum RSState state; /* parsing state */
     char line_buf[4096];      char line_buf[MAX_PACKET_LENGTH];
     int line_buf_index;      int line_buf_index;
     int line_csum;      int line_csum;
     uint8_t last_packet[4100];      uint8_t last_packet[MAX_PACKET_LENGTH + 4];
     int last_packet_len;      int last_packet_len;
       int signal;
 #ifdef CONFIG_USER_ONLY  #ifdef CONFIG_USER_ONLY
     int fd;      int fd;
     int running_state;      int running_state;
Line 73  typedef struct GDBState { Line 288  typedef struct GDBState {
 #endif  #endif
 } GDBState;  } GDBState;
   
   /* By default use no IRQs and no timers while single stepping so as to
    * make single stepping like an ICE HW step.
    */
   static int sstep_flags = SSTEP_ENABLE|SSTEP_NOIRQ|SSTEP_NOTIMER;
   
   static GDBState *gdbserver_state;
   
   /* This is an ugly hack to cope with both new and old gdb.
      If gdb sends qXfer:features:read then assume we're talking to a newish
      gdb that understands target descriptions.  */
   static int gdb_has_xml;
   
 #ifdef CONFIG_USER_ONLY  #ifdef CONFIG_USER_ONLY
 /* XXX: This is not thread safe.  Do we care?  */  /* XXX: This is not thread safe.  Do we care?  */
 static int gdbserver_fd = -1;  static int gdbserver_fd = -1;
   
 /* XXX: remove this hack.  */  
 static GDBState gdbserver_state;  
   
 static int get_char(GDBState *s)  static int get_char(GDBState *s)
 {  {
     uint8_t ch;      uint8_t ch;
Line 88  static int get_char(GDBState *s) Line 312  static int get_char(GDBState *s)
     for(;;) {      for(;;) {
         ret = recv(s->fd, &ch, 1, 0);          ret = recv(s->fd, &ch, 1, 0);
         if (ret < 0) {          if (ret < 0) {
               if (errno == ECONNRESET)
                   s->fd = -1;
             if (errno != EINTR && errno != EAGAIN)              if (errno != EINTR && errno != EAGAIN)
                 return -1;                  return -1;
         } else if (ret == 0) {          } else if (ret == 0) {
               close(s->fd);
               s->fd = -1;
             return -1;              return -1;
         } else {          } else {
             break;              break;
Line 100  static int get_char(GDBState *s) Line 328  static int get_char(GDBState *s)
 }  }
 #endif  #endif
   
 /* GDB stub state for use by semihosting syscalls.  */  
 static GDBState *gdb_syscall_state;  
 static gdb_syscall_complete_cb gdb_current_syscall_cb;  static gdb_syscall_complete_cb gdb_current_syscall_cb;
   
 enum {  enum {
Line 115  enum { Line 341  enum {
 int use_gdb_syscalls(void)  int use_gdb_syscalls(void)
 {  {
     if (gdb_syscall_mode == GDB_SYS_UNKNOWN) {      if (gdb_syscall_mode == GDB_SYS_UNKNOWN) {
         gdb_syscall_mode = (gdb_syscall_state ? GDB_SYS_ENABLED          gdb_syscall_mode = (gdbserver_state ? GDB_SYS_ENABLED
                                               : GDB_SYS_DISABLED);                                              : GDB_SYS_DISABLED);
     }      }
     return gdb_syscall_mode == GDB_SYS_ENABLED;      return gdb_syscall_mode == GDB_SYS_ENABLED;
 }  }
   
   /* Resume execution.  */
   static inline void gdb_continue(GDBState *s)
   {
   #ifdef CONFIG_USER_ONLY
       s->running_state = 1;
   #else
       vm_start();
   #endif
   }
   
 static void put_buffer(GDBState *s, const uint8_t *buf, int len)  static void put_buffer(GDBState *s, const uint8_t *buf, int len)
 {  {
 #ifdef CONFIG_USER_ONLY  #ifdef CONFIG_USER_ONLY
Line 185  static void hextomem(uint8_t *mem, const Line 421  static void hextomem(uint8_t *mem, const
 }  }
   
 /* return -1 if error, 0 if OK */  /* return -1 if error, 0 if OK */
 static int put_packet(GDBState *s, char *buf)  static int put_packet_binary(GDBState *s, const char *buf, int len)
 {  {
     int len, csum, i;      int csum, i;
     uint8_t *p;      uint8_t *p;
   
 #ifdef DEBUG_GDB  
     printf("reply='%s'\n", buf);  
 #endif  
   
     for(;;) {      for(;;) {
         p = s->last_packet;          p = s->last_packet;
         *(p++) = '$';          *(p++) = '$';
         len = strlen(buf);  
         memcpy(p, buf, len);          memcpy(p, buf, len);
         p += len;          p += len;
         csum = 0;          csum = 0;
Line 224  static int put_packet(GDBState *s, char  Line 455  static int put_packet(GDBState *s, char 
     return 0;      return 0;
 }  }
   
 #if defined(TARGET_I386)  /* return -1 if error, 0 if OK */
   static int put_packet(GDBState *s, const char *buf)
 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)  
 {  {
     int i, fpus;  #ifdef DEBUG_GDB
     uint32_t *registers = (uint32_t *)mem_buf;      printf("reply='%s'\n", buf);
   #endif
   
       return put_packet_binary(s, buf, strlen(buf));
   }
   
   /* The GDB remote protocol transfers values in target byte order.  This means
      we can use the raw memory access routines to access the value buffer.
      Conveniently, these also handle the case where the buffer is mis-aligned.
    */
   #define GET_REG8(val) do { \
       stb_p(mem_buf, val); \
       return 1; \
       } while(0)
   #define GET_REG16(val) do { \
       stw_p(mem_buf, val); \
       return 2; \
       } while(0)
   #define GET_REG32(val) do { \
       stl_p(mem_buf, val); \
       return 4; \
       } while(0)
   #define GET_REG64(val) do { \
       stq_p(mem_buf, val); \
       return 8; \
       } while(0)
   
   #if TARGET_LONG_BITS == 64
   #define GET_REGL(val) GET_REG64(val)
   #define ldtul_p(addr) ldq_p(addr)
   #else
   #define GET_REGL(val) GET_REG32(val)
   #define ldtul_p(addr) ldl_p(addr)
   #endif
   
   #if defined(TARGET_I386)
   
 #ifdef TARGET_X86_64  #ifdef TARGET_X86_64
     /* This corresponds with amd64_register_info[] in gdb/amd64-tdep.c */  static const int gpr_map[16] = {
     uint64_t *registers64 = (uint64_t *)mem_buf;      R_EAX, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI, R_EBP, R_ESP,
       8, 9, 10, 11, 12, 13, 14, 15
   };
   #else
   static const int gpr_map[8] = {0, 1, 2, 3, 4, 5, 6, 7};
   #endif
   
   #define NUM_CORE_REGS (CPU_NB_REGS * 2 + 25)
   
     if (env->hflags & HF_CS64_MASK) {  static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
         registers64[0] = tswap64(env->regs[R_EAX]);  {
         registers64[1] = tswap64(env->regs[R_EBX]);      if (n < CPU_NB_REGS) {
         registers64[2] = tswap64(env->regs[R_ECX]);          GET_REGL(env->regs[gpr_map[n]]);
         registers64[3] = tswap64(env->regs[R_EDX]);      } else if (n >= CPU_NB_REGS + 8 && n < CPU_NB_REGS + 16) {
         registers64[4] = tswap64(env->regs[R_ESI]);          /* FIXME: byteswap float values.  */
         registers64[5] = tswap64(env->regs[R_EDI]);  #ifdef USE_X86LDOUBLE
         registers64[6] = tswap64(env->regs[R_EBP]);          memcpy(mem_buf, &env->fpregs[n - (CPU_NB_REGS + 8)], 10);
         registers64[7] = tswap64(env->regs[R_ESP]);  #else
         for(i = 8; i < 16; i++) {          memset(mem_buf, 0, 10);
             registers64[i] = tswap64(env->regs[i]);  #endif
         }          return 10;
         registers64[16] = tswap64(env->eip);      } else if (n >= CPU_NB_REGS + 24) {
           n -= CPU_NB_REGS + 24;
         registers = (uint32_t *)&registers64[17];          if (n < CPU_NB_REGS) {
         registers[0] = tswap32(env->eflags);              stq_p(mem_buf, env->xmm_regs[n].XMM_Q(0));
         registers[1] = tswap32(env->segs[R_CS].selector);              stq_p(mem_buf + 8, env->xmm_regs[n].XMM_Q(1));
         registers[2] = tswap32(env->segs[R_SS].selector);              return 16;
         registers[3] = tswap32(env->segs[R_DS].selector);          } else if (n == CPU_NB_REGS) {
         registers[4] = tswap32(env->segs[R_ES].selector);              GET_REG32(env->mxcsr);
         registers[5] = tswap32(env->segs[R_FS].selector);          } 
         registers[6] = tswap32(env->segs[R_GS].selector);      } else {
         /* XXX: convert floats */          n -= CPU_NB_REGS;
         for(i = 0; i < 8; i++) {          switch (n) {
             memcpy(mem_buf + 16 * 8 + 7 * 4 + i * 10, &env->fpregs[i], 10);          case 0: GET_REGL(env->eip);
         }          case 1: GET_REG32(env->eflags);
         registers[27] = tswap32(env->fpuc); /* fctrl */          case 2: GET_REG32(env->segs[R_CS].selector);
         fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;          case 3: GET_REG32(env->segs[R_SS].selector);
         registers[28] = tswap32(fpus); /* fstat */          case 4: GET_REG32(env->segs[R_DS].selector);
         registers[29] = 0; /* ftag */          case 5: GET_REG32(env->segs[R_ES].selector);
         registers[30] = 0; /* fiseg */          case 6: GET_REG32(env->segs[R_FS].selector);
         registers[31] = 0; /* fioff */          case 7: GET_REG32(env->segs[R_GS].selector);
         registers[32] = 0; /* foseg */          /* 8...15 x87 regs.  */
         registers[33] = 0; /* fooff */          case 16: GET_REG32(env->fpuc);
         registers[34] = 0; /* fop */          case 17: GET_REG32((env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11);
         for(i = 0; i < 16; i++) {          case 18: GET_REG32(0); /* ftag */
             memcpy(mem_buf + 16 * 8 + 35 * 4 + i * 16, &env->xmm_regs[i], 16);          case 19: GET_REG32(0); /* fiseg */
         }          case 20: GET_REG32(0); /* fioff */
         registers[99] = tswap32(env->mxcsr);          case 21: GET_REG32(0); /* foseg */
           case 22: GET_REG32(0); /* fooff */
         return 8 * 17 + 4 * 7 + 10 * 8 + 4 * 8 + 16 * 16 + 4;          case 23: GET_REG32(0); /* fop */
     }          /* 24+ xmm regs.  */
 #endif          }
       }
     for(i = 0; i < 8; i++) {      return 0;
         registers[i] = 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;  
     /* XXX: convert floats */  
     for(i = 0; i < 8; i++) {  
         memcpy(mem_buf + 16 * 4 + i * 10, &env->fpregs[i], 10);  
     }  
     registers[36] = env->fpuc;  
     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;  
     registers[37] = fpus;  
     registers[38] = 0; /* XXX: convert tags */  
     registers[39] = 0; /* fiseg */  
     registers[40] = 0; /* fioff */  
     registers[41] = 0; /* foseg */  
     registers[42] = 0; /* fooff */  
     registers[43] = 0; /* fop */  
   
     for(i = 0; i < 16; i++)  
         tswapls(&registers[i]);  
     for(i = 36; i < 44; i++)  
         tswapls(&registers[i]);  
     return 44 * 4;  
 }  }
   
 static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)  static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int i)
 {  {
     uint32_t *registers = (uint32_t *)mem_buf;      uint32_t tmp;
     int i;  
   
     for(i = 0; i < 8; i++) {      if (i < CPU_NB_REGS) {
         env->regs[i] = tswapl(registers[i]);          env->regs[gpr_map[i]] = ldtul_p(mem_buf);
     }          return sizeof(target_ulong);
     env->eip = tswapl(registers[8]);      } else if (i >= CPU_NB_REGS + 8 && i < CPU_NB_REGS + 16) {
     env->eflags = tswapl(registers[9]);          i -= CPU_NB_REGS + 8;
   #ifdef USE_X86LDOUBLE
           memcpy(&env->fpregs[i], mem_buf, 10);
   #endif
           return 10;
       } else if (i >= CPU_NB_REGS + 24) {
           i -= CPU_NB_REGS + 24;
           if (i < CPU_NB_REGS) {
               env->xmm_regs[i].XMM_Q(0) = ldq_p(mem_buf);
               env->xmm_regs[i].XMM_Q(1) = ldq_p(mem_buf + 8);
               return 16;
           } else if (i == CPU_NB_REGS) {
               env->mxcsr = ldl_p(mem_buf);
               return 4;
           }
       } else {
           i -= CPU_NB_REGS;
           switch (i) {
           case 0: env->eip = ldtul_p(mem_buf); return sizeof(target_ulong);
           case 1: env->eflags = ldl_p(mem_buf); return 4;
 #if defined(CONFIG_USER_ONLY)  #if defined(CONFIG_USER_ONLY)
 #define LOAD_SEG(index, sreg)\  #define LOAD_SEG(index, sreg)\
             if (tswapl(registers[index]) != env->segs[sreg].selector)\              tmp = ldl_p(mem_buf);\
                 cpu_x86_load_seg(env, sreg, tswapl(registers[index]));              if (tmp != env->segs[sreg].selector)\
             LOAD_SEG(10, R_CS);                  cpu_x86_load_seg(env, sreg, tmp);
             LOAD_SEG(11, R_SS);  #else
             LOAD_SEG(12, R_DS);  /* FIXME: Honor segment registers.  Needs to avoid raising an exception
             LOAD_SEG(13, R_ES);     when the selector is invalid.  */
             LOAD_SEG(14, R_FS);  #define LOAD_SEG(index, sreg) do {} while(0)
             LOAD_SEG(15, R_GS);  #endif
 #endif          case 2: LOAD_SEG(10, R_CS); return 4;
           case 3: LOAD_SEG(11, R_SS); return 4;
           case 4: LOAD_SEG(12, R_DS); return 4;
           case 5: LOAD_SEG(13, R_ES); return 4;
           case 6: LOAD_SEG(14, R_FS); return 4;
           case 7: LOAD_SEG(15, R_GS); return 4;
           /* 8...15 x87 regs.  */
           case 16: env->fpuc = ldl_p(mem_buf); return 4;
           case 17:
                    tmp = ldl_p(mem_buf);
                    env->fpstt = (tmp >> 11) & 7;
                    env->fpus = tmp & ~0x3800;
                    return 4;
           case 18: /* ftag */ return 4;
           case 19: /* fiseg */ return 4;
           case 20: /* fioff */ return 4;
           case 21: /* foseg */ return 4;
           case 22: /* fooff */ return 4;
           case 23: /* fop */ return 4;
           /* 24+ xmm regs.  */
           }
       }
       /* Unrecognised register.  */
       return 0;
 }  }
   
 #elif defined (TARGET_PPC)  #elif defined (TARGET_PPC)
 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)  
 {  
     uint32_t *registers = (uint32_t *)mem_buf, tmp;  
     int i;  
   
     /* fill in gprs */  /* Old gdb always expects FP registers.  Newer (xml-aware) gdb only
     for(i = 0; i < 32; i++) {     expects whatever the target description contains.  Due to a
         registers[i] = tswapl(env->gpr[i]);     historical mishap the FP registers appear in between core integer
     }     regs and PC, MSR, CR, and so forth.  We hack round this by giving the
     /* fill in fprs */     FP regs zero size when talking to a newer gdb.  */
     for (i = 0; i < 32; i++) {  #define NUM_CORE_REGS 71
         registers[(i * 2) + 32] = tswapl(*((uint32_t *)&env->fpr[i]));  #if defined (TARGET_PPC64)
         registers[(i * 2) + 33] = tswapl(*((uint32_t *)&env->fpr[i] + 1));  #define GDB_CORE_XML "power64-core.xml"
     }  #else
     /* nip, msr, ccr, lnk, ctr, xer, mq */  #define GDB_CORE_XML "power-core.xml"
     registers[96] = tswapl(env->nip);  #endif
     registers[97] = tswapl(env->msr);  
     tmp = 0;  
     for (i = 0; i < 8; i++)  
         tmp |= env->crf[i] << (32 - ((i + 1) * 4));  
     registers[98] = tswapl(tmp);  
     registers[99] = tswapl(env->lr);  
     registers[100] = tswapl(env->ctr);  
     registers[101] = tswapl(ppc_load_xer(env));  
     registers[102] = 0;  
   
     return 103 * 4;  static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
   {
       if (n < 32) {
           /* gprs */
           GET_REGL(env->gpr[n]);
       } else if (n < 64) {
           /* fprs */
           if (gdb_has_xml)
               return 0;
           stfq_p(mem_buf, env->fpr[n-32]);
           return 8;
       } else {
           switch (n) {
           case 64: GET_REGL(env->nip);
           case 65: GET_REGL(env->msr);
           case 66:
               {
                   uint32_t cr = 0;
                   int i;
                   for (i = 0; i < 8; i++)
                       cr |= env->crf[i] << (32 - ((i + 1) * 4));
                   GET_REG32(cr);
               }
           case 67: GET_REGL(env->lr);
           case 68: GET_REGL(env->ctr);
           case 69: GET_REGL(env->xer);
           case 70:
               {
                   if (gdb_has_xml)
                       return 0;
                   GET_REG32(0); /* fpscr */
               }
           }
       }
       return 0;
 }  }
   
 static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)  static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 {  {
     uint32_t *registers = (uint32_t *)mem_buf;      if (n < 32) {
     int i;          /* gprs */
           env->gpr[n] = ldtul_p(mem_buf);
     /* fill in gprs */          return sizeof(target_ulong);
     for (i = 0; i < 32; i++) {      } else if (n < 64) {
         env->gpr[i] = tswapl(registers[i]);          /* fprs */
     }          if (gdb_has_xml)
     /* fill in fprs */              return 0;
     for (i = 0; i < 32; i++) {          env->fpr[n-32] = ldfq_p(mem_buf);
         *((uint32_t *)&env->fpr[i]) = tswapl(registers[(i * 2) + 32]);          return 8;
         *((uint32_t *)&env->fpr[i] + 1) = tswapl(registers[(i * 2) + 33]);      } else {
     }          switch (n) {
     /* nip, msr, ccr, lnk, ctr, xer, mq */          case 64:
     env->nip = tswapl(registers[96]);              env->nip = ldtul_p(mem_buf);
     ppc_store_msr(env, tswapl(registers[97]));              return sizeof(target_ulong);
     registers[98] = tswapl(registers[98]);          case 65:
     for (i = 0; i < 8; i++)              ppc_store_msr(env, ldtul_p(mem_buf));
         env->crf[i] = (registers[98] >> (32 - ((i + 1) * 4))) & 0xF;              return sizeof(target_ulong);
     env->lr = tswapl(registers[99]);          case 66:
     env->ctr = tswapl(registers[100]);              {
     ppc_store_xer(env, tswapl(registers[101]));                  uint32_t cr = ldl_p(mem_buf);
                   int i;
                   for (i = 0; i < 8; i++)
                       env->crf[i] = (cr >> (32 - ((i + 1) * 4))) & 0xF;
                   return 4;
               }
           case 67:
               env->lr = ldtul_p(mem_buf);
               return sizeof(target_ulong);
           case 68:
               env->ctr = ldtul_p(mem_buf);
               return sizeof(target_ulong);
           case 69:
               env->xer = ldtul_p(mem_buf);
               return sizeof(target_ulong);
           case 70:
               /* fpscr */
               if (gdb_has_xml)
                   return 0;
               return 4;
           }
       }
       return 0;
 }  }
   
 #elif defined (TARGET_SPARC)  #elif defined (TARGET_SPARC)
 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)  
 {  
     target_ulong *registers = (target_ulong *)mem_buf;  
     int i;  
   
     /* fill in g0..g7 */  #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
     for(i = 0; i < 8; i++) {  #define NUM_CORE_REGS 86
         registers[i] = tswapl(env->gregs[i]);  #else
     }  #define NUM_CORE_REGS 72
     /* fill in register window */  #endif
     for(i = 0; i < 24; i++) {  
         registers[i + 8] = tswapl(env->regwptr[i]);  #ifdef TARGET_ABI32
     }  #define GET_REGA(val) GET_REG32(val)
 #ifndef TARGET_SPARC64  #else
     /* fill in fprs */  #define GET_REGA(val) GET_REGL(val)
     for (i = 0; i < 32; i++) {  #endif
         registers[i + 32] = tswapl(*((uint32_t *)&env->fpr[i]));  
   static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
   {
       if (n < 8) {
           /* g0..g7 */
           GET_REGA(env->gregs[n]);
       }
       if (n < 32) {
           /* register window */
           GET_REGA(env->regwptr[n - 8]);
       }
   #if defined(TARGET_ABI32) || !defined(TARGET_SPARC64)
       if (n < 64) {
           /* fprs */
           GET_REG32(*((uint32_t *)&env->fpr[n - 32]));
     }      }
     /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */      /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
     registers[64] = tswapl(env->y);      switch (n) {
     {      case 64: GET_REGA(env->y);
         target_ulong tmp;      case 65: GET_REGA(GET_PSR(env));
       case 66: GET_REGA(env->wim);
         tmp = GET_PSR(env);      case 67: GET_REGA(env->tbr);
         registers[65] = tswapl(tmp);      case 68: GET_REGA(env->pc);
       case 69: GET_REGA(env->npc);
       case 70: GET_REGA(env->fsr);
       case 71: GET_REGA(0); /* csr */
       default: GET_REGA(0);
     }      }
     registers[66] = tswapl(env->wim);  #else
     registers[67] = tswapl(env->tbr);      if (n < 64) {
     registers[68] = tswapl(env->pc);          /* f0-f31 */
     registers[69] = tswapl(env->npc);          GET_REG32(*((uint32_t *)&env->fpr[n - 32]));
     registers[70] = tswapl(env->fsr);      }
     registers[71] = 0; /* csr */      if (n < 80) {
     registers[72] = 0;          /* f32-f62 (double width, even numbers only) */
     return 73 * sizeof(target_ulong);          uint64_t val;
 #else  
     /* fill in fprs */          val = (uint64_t)*((uint32_t *)&env->fpr[(n - 64) * 2 + 32]) << 32;
     for (i = 0; i < 64; i += 2) {          val |= *((uint32_t *)&env->fpr[(n - 64) * 2 + 33]);
         uint64_t tmp;          GET_REG64(val);
       }
         tmp = ((uint64_t)*(uint32_t *)&env->fpr[i]) << 32;      switch (n) {
         tmp |= *(uint32_t *)&env->fpr[i + 1];      case 80: GET_REGL(env->pc);
         registers[i / 2 + 32] = tswap64(tmp);      case 81: GET_REGL(env->npc);
     }      case 82: GET_REGL(((uint64_t)GET_CCR(env) << 32) |
     registers[64] = tswapl(env->pc);  
     registers[65] = tswapl(env->npc);  
     registers[66] = tswapl(((uint64_t)GET_CCR(env) << 32) |  
                            ((env->asi & 0xff) << 24) |                             ((env->asi & 0xff) << 24) |
                            ((env->pstate & 0xfff) << 8) |                             ((env->pstate & 0xfff) << 8) |
                            GET_CWP64(env));                             GET_CWP64(env));
     registers[67] = tswapl(env->fsr);      case 83: GET_REGL(env->fsr);
     registers[68] = tswapl(env->fprs);      case 84: GET_REGL(env->fprs);
     registers[69] = tswapl(env->y);      case 85: GET_REGL(env->y);
     return 70 * sizeof(target_ulong);      }
 #endif  #endif
       return 0;
 }  }
   
 static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)  static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 {  {
     target_ulong *registers = (target_ulong *)mem_buf;  #if defined(TARGET_ABI32)
     int i;      abi_ulong tmp;
   
     /* fill in g0..g7 */      tmp = ldl_p(mem_buf);
     for(i = 0; i < 7; i++) {  #else
         env->gregs[i] = tswapl(registers[i]);      target_ulong tmp;
     }  
     /* fill in register window */      tmp = ldtul_p(mem_buf);
     for(i = 0; i < 24; i++) {  #endif
         env->regwptr[i] = tswapl(registers[i + 8]);  
     }      if (n < 8) {
 #ifndef TARGET_SPARC64          /* g0..g7 */
     /* fill in fprs */          env->gregs[n] = tmp;
     for (i = 0; i < 32; i++) {      } else if (n < 32) {
         *((uint32_t *)&env->fpr[i]) = tswapl(registers[i + 32]);          /* register window */
           env->regwptr[n - 8] = tmp;
       }
   #if defined(TARGET_ABI32) || !defined(TARGET_SPARC64)
       else if (n < 64) {
           /* fprs */
           *((uint32_t *)&env->fpr[n - 32]) = tmp;
       } else {
           /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
           switch (n) {
           case 64: env->y = tmp; break;
           case 65: PUT_PSR(env, tmp); break;
           case 66: env->wim = tmp; break;
           case 67: env->tbr = tmp; break;
           case 68: env->pc = tmp; break;
           case 69: env->npc = tmp; break;
           case 70: env->fsr = tmp; break;
           default: return 0;
           }
     }      }
     /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */      return 4;
     env->y = tswapl(registers[64]);  #else
     PUT_PSR(env, tswapl(registers[65]));      else if (n < 64) {
     env->wim = tswapl(registers[66]);          /* f0-f31 */
     env->tbr = tswapl(registers[67]);          env->fpr[n] = ldfl_p(mem_buf);
     env->pc = tswapl(registers[68]);          return 4;
     env->npc = tswapl(registers[69]);      } else if (n < 80) {
     env->fsr = tswapl(registers[70]);          /* f32-f62 (double width, even numbers only) */
 #else          *((uint32_t *)&env->fpr[(n - 64) * 2 + 32]) = tmp >> 32;
     for (i = 0; i < 64; i += 2) {          *((uint32_t *)&env->fpr[(n - 64) * 2 + 33]) = tmp;
         uint64_t tmp;      } else {
           switch (n) {
         tmp = tswap64(registers[i / 2 + 32]);          case 80: env->pc = tmp; break;
         *((uint32_t *)&env->fpr[i]) = tmp >> 32;          case 81: env->npc = tmp; break;
         *((uint32_t *)&env->fpr[i + 1]) = tmp & 0xffffffff;          case 82:
               PUT_CCR(env, tmp >> 32);
               env->asi = (tmp >> 24) & 0xff;
               env->pstate = (tmp >> 8) & 0xfff;
               PUT_CWP64(env, tmp & 0xff);
               break;
           case 83: env->fsr = tmp; break;
           case 84: env->fprs = tmp; break;
           case 85: env->y = tmp; break;
           default: return 0;
           }
     }      }
     env->pc = tswapl(registers[64]);      return 8;
     env->npc = tswapl(registers[65]);  
     {  
         uint64_t tmp = tswapl(registers[66]);  
   
         PUT_CCR(env, tmp >> 32);  
         env->asi = (tmp >> 24) & 0xff;  
         env->pstate = (tmp >> 8) & 0xfff;  
         PUT_CWP64(env, tmp & 0xff);  
     }  
     env->fsr = tswapl(registers[67]);  
     env->fprs = tswapl(registers[68]);  
     env->y = tswapl(registers[69]);  
 #endif  #endif
 }  }
 #elif defined (TARGET_ARM)  #elif defined (TARGET_ARM)
 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)  
 {  
     int i;  
     uint8_t *ptr;  
   
     ptr = mem_buf;  /* Old gdb always expect FPA registers.  Newer (xml-aware) gdb only expect
     /* 16 core integer registers (4 bytes each).  */     whatever the target description contains.  Due to a historical mishap
     for (i = 0; i < 16; i++)     the FPA registers appear in between core integer regs and the CPSR.
       {     We hack round this by giving the FPA regs zero size when talking to a
         *(uint32_t *)ptr = tswapl(env->regs[i]);     newer gdb.  */
         ptr += 4;  #define NUM_CORE_REGS 26
       }  #define GDB_CORE_XML "arm-core.xml"
     /* 8 FPA registers (12 bytes each), FPS (4 bytes).  
        Not yet implemented.  */  static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     memset (ptr, 0, 8 * 12 + 4);  {
     ptr += 8 * 12 + 4;      if (n < 16) {
     /* CPSR (4 bytes).  */          /* Core integer register.  */
     *(uint32_t *)ptr = tswapl (cpsr_read(env));          GET_REG32(env->regs[n]);
     ptr += 4;      }
       if (n < 24) {
     return ptr - mem_buf;          /* FPA registers.  */
           if (gdb_has_xml)
               return 0;
           memset(mem_buf, 0, 12);
           return 12;
       }
       switch (n) {
       case 24:
           /* FPA status register.  */
           if (gdb_has_xml)
               return 0;
           GET_REG32(0);
       case 25:
           /* CPSR */
           GET_REG32(cpsr_read(env));
       }
       /* Unknown register.  */
       return 0;
 }  }
   
 static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)  static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 {  {
     int i;      uint32_t tmp;
     uint8_t *ptr;  
       tmp = ldl_p(mem_buf);
   
     ptr = mem_buf;      /* Mask out low bit of PC to workaround gdb bugs.  This will probably
     /* Core integer registers.  */         cause problems if we ever implement the Jazelle DBX extensions.  */
     for (i = 0; i < 16; i++)      if (n == 15)
       {          tmp &= ~1;
         env->regs[i] = tswapl(*(uint32_t *)ptr);  
         ptr += 4;      if (n < 16) {
       }          /* Core integer register.  */
     /* Ignore FPA regs and scr.  */          env->regs[n] = tmp;
     ptr += 8 * 12 + 4;          return 4;
     cpsr_write (env, tswapl(*(uint32_t *)ptr), 0xffffffff);      }
       if (n < 24) { /* 16-23 */
           /* FPA registers (ignored).  */
           if (gdb_has_xml)
               return 0;
           return 12;
       }
       switch (n) {
       case 24:
           /* FPA status register (ignored).  */
           if (gdb_has_xml)
               return 0;
           return 4;
       case 25:
           /* CPSR */
           cpsr_write (env, tmp, 0xffffffff);
           return 4;
       }
       /* Unknown register.  */
       return 0;
 }  }
   
 #elif defined (TARGET_M68K)  #elif defined (TARGET_M68K)
 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)  
 {  
     int i;  
     uint8_t *ptr;  
     CPU_DoubleU u;  
   
     ptr = mem_buf;  #define NUM_CORE_REGS 18
     /* D0-D7 */  
     for (i = 0; i < 8; i++) {  
         *(uint32_t *)ptr = tswapl(env->dregs[i]);  
         ptr += 4;  
     }  
     /* A0-A7 */  
     for (i = 0; i < 8; i++) {  
         *(uint32_t *)ptr = tswapl(env->aregs[i]);  
         ptr += 4;  
     }  
     *(uint32_t *)ptr = tswapl(env->sr);  
     ptr += 4;  
     *(uint32_t *)ptr = tswapl(env->pc);  
     ptr += 4;  
     /* F0-F7.  The 68881/68040 have 12-bit extended precision registers.  
        ColdFire has 8-bit double precision registers.  */  
     for (i = 0; i < 8; i++) {  
         u.d = env->fregs[i];  
         *(uint32_t *)ptr = tswap32(u.l.upper);  
         *(uint32_t *)ptr = tswap32(u.l.lower);  
     }  
     /* FP control regs (not implemented).  */  
     memset (ptr, 0, 3 * 4);  
     ptr += 3 * 4;  
   
     return ptr - mem_buf;  #define GDB_CORE_XML "cf-core.xml"
 }  
   
 static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)  static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
 {  {
     int i;      if (n < 8) {
     uint8_t *ptr;          /* D0-D7 */
     CPU_DoubleU u;          GET_REG32(env->dregs[n]);
       } else if (n < 16) {
     ptr = mem_buf;          /* A0-A7 */
     /* D0-D7 */          GET_REG32(env->aregs[n - 8]);
     for (i = 0; i < 8; i++) {      } else {
         env->dregs[i] = tswapl(*(uint32_t *)ptr);          switch (n) {
         ptr += 4;          case 16: GET_REG32(env->sr);
     }          case 17: GET_REG32(env->pc);
     /* A0-A7 */          }
     for (i = 0; i < 8; i++) {  
         env->aregs[i] = tswapl(*(uint32_t *)ptr);  
         ptr += 4;  
     }  
     env->sr = tswapl(*(uint32_t *)ptr);  
     ptr += 4;  
     env->pc = tswapl(*(uint32_t *)ptr);  
     ptr += 4;  
     /* F0-F7.  The 68881/68040 have 12-bit extended precision registers.  
        ColdFire has 8-bit double precision registers.  */  
     for (i = 0; i < 8; i++) {  
         u.l.upper = tswap32(*(uint32_t *)ptr);  
         u.l.lower = tswap32(*(uint32_t *)ptr);  
         env->fregs[i] = u.d;  
     }      }
     /* FP control regs (not implemented).  */      /* FP registers not included here because they vary between
     ptr += 3 * 4;         ColdFire and m68k.  Use XML bits for these.  */
       return 0;
 }  }
 #elif defined (TARGET_MIPS)  
 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)  
 {  
     int i;  
     uint8_t *ptr;  
   
     ptr = mem_buf;  
     for (i = 0; i < 32; i++)  
       {  
         *(target_ulong *)ptr = tswapl(env->gpr[i][env->current_tc]);  
         ptr += sizeof(target_ulong);  
       }  
   
     *(target_ulong *)ptr = (int32_t)tswap32(env->CP0_Status);  static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
     ptr += sizeof(target_ulong);  {
       uint32_t tmp;
     *(target_ulong *)ptr = tswapl(env->LO[0][env->current_tc]);  
     ptr += sizeof(target_ulong);  
   
     *(target_ulong *)ptr = tswapl(env->HI[0][env->current_tc]);  
     ptr += sizeof(target_ulong);  
   
     *(target_ulong *)ptr = tswapl(env->CP0_BadVAddr);      tmp = ldl_p(mem_buf);
     ptr += sizeof(target_ulong);  
   
     *(target_ulong *)ptr = (int32_t)tswap32(env->CP0_Cause);      if (n < 8) {
     ptr += sizeof(target_ulong);          /* D0-D7 */
           env->dregs[n] = tmp;
       } else if (n < 8) {
           /* A0-A7 */
           env->aregs[n - 8] = tmp;
       } else {
           switch (n) {
           case 16: env->sr = tmp; break;
           case 17: env->pc = tmp; break;
           default: return 0;
           }
       }
       return 4;
   }
   #elif defined (TARGET_MIPS)
   
     *(target_ulong *)ptr = tswapl(env->PC[env->current_tc]);  #define NUM_CORE_REGS 73
     ptr += sizeof(target_ulong);  
   
     if (env->CP0_Config1 & (1 << CP0C1_FP))  static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
       {  {
         for (i = 0; i < 32; i++)      if (n < 32) {
           {          GET_REGL(env->active_tc.gpr[n]);
       }
       if (env->CP0_Config1 & (1 << CP0C1_FP)) {
           if (n >= 38 && n < 70) {
             if (env->CP0_Status & (1 << CP0St_FR))              if (env->CP0_Status & (1 << CP0St_FR))
               *(target_ulong *)ptr = tswapl(env->fpu->fpr[i].d);                  GET_REGL(env->active_fpu.fpr[n - 38].d);
             else              else
               *(target_ulong *)ptr = tswap32(env->fpu->fpr[i].w[FP_ENDIAN_IDX]);                  GET_REGL(env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX]);
             ptr += sizeof(target_ulong);          }
           }          switch (n) {
           case 70: GET_REGL((int32_t)env->active_fpu.fcr31);
         *(target_ulong *)ptr = (int32_t)tswap32(env->fpu->fcr31);          case 71: GET_REGL((int32_t)env->active_fpu.fcr0);
         ptr += sizeof(target_ulong);          }
       }
         *(target_ulong *)ptr = (int32_t)tswap32(env->fpu->fcr0);      switch (n) {
         ptr += sizeof(target_ulong);      case 32: GET_REGL((int32_t)env->CP0_Status);
       }      case 33: GET_REGL(env->active_tc.LO[0]);
       case 34: GET_REGL(env->active_tc.HI[0]);
     /* "fp", pseudo frame pointer. Not yet implemented in gdb. */      case 35: GET_REGL(env->CP0_BadVAddr);
     *(target_ulong *)ptr = 0;      case 36: GET_REGL((int32_t)env->CP0_Cause);
     ptr += sizeof(target_ulong);      case 37: GET_REGL(env->active_tc.PC);
       case 72: GET_REGL(0); /* fp */
     /* Registers for embedded use, we just pad them. */      case 89: GET_REGL((int32_t)env->CP0_PRid);
     for (i = 0; i < 16; i++)      }
       {      if (n >= 73 && n <= 88) {
         *(target_ulong *)ptr = 0;          /* 16 embedded regs.  */
         ptr += sizeof(target_ulong);          GET_REGL(0);
       }      }
   
     /* Processor ID. */  
     *(target_ulong *)ptr = (int32_t)tswap32(env->CP0_PRid);  
     ptr += sizeof(target_ulong);  
   
     return ptr - mem_buf;      return 0;
 }  }
   
 /* convert MIPS rounding mode in FCR31 to IEEE library */  /* convert MIPS rounding mode in FCR31 to IEEE library */
Line 677  static unsigned int ieee_rm[] = Line 1018  static unsigned int ieee_rm[] =
     float_round_down      float_round_down
   };    };
 #define RESTORE_ROUNDING_MODE \  #define RESTORE_ROUNDING_MODE \
     set_float_rounding_mode(ieee_rm[env->fpu->fcr31 & 3], &env->fpu->fp_status)      set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], &env->active_fpu.fp_status)
   
 static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)  static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 {  {
     int i;      target_ulong tmp;
     uint8_t *ptr;  
   
     ptr = mem_buf;  
     for (i = 0; i < 32; i++)  
       {  
         env->gpr[i][env->current_tc] = tswapl(*(target_ulong *)ptr);  
         ptr += sizeof(target_ulong);  
       }  
   
     env->CP0_Status = tswapl(*(target_ulong *)ptr);      tmp = ldtul_p(mem_buf);
     ptr += sizeof(target_ulong);  
   
     env->LO[0][env->current_tc] = tswapl(*(target_ulong *)ptr);      if (n < 32) {
     ptr += sizeof(target_ulong);          env->active_tc.gpr[n] = tmp;
           return sizeof(target_ulong);
       }
       if (env->CP0_Config1 & (1 << CP0C1_FP)
               && n >= 38 && n < 73) {
           if (n < 70) {
               if (env->CP0_Status & (1 << CP0St_FR))
                 env->active_fpu.fpr[n - 38].d = tmp;
               else
                 env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX] = tmp;
           }
           switch (n) {
           case 70:
               env->active_fpu.fcr31 = tmp & 0xFF83FFFF;
               /* set rounding mode */
               RESTORE_ROUNDING_MODE;
   #ifndef CONFIG_SOFTFLOAT
               /* no floating point exception for native float */
               SET_FP_ENABLE(env->active_fpu.fcr31, 0);
   #endif
               break;
           case 71: env->active_fpu.fcr0 = tmp; break;
           }
           return sizeof(target_ulong);
       }
       switch (n) {
       case 32: env->CP0_Status = tmp; break;
       case 33: env->active_tc.LO[0] = tmp; break;
       case 34: env->active_tc.HI[0] = tmp; break;
       case 35: env->CP0_BadVAddr = tmp; break;
       case 36: env->CP0_Cause = tmp; break;
       case 37: env->active_tc.PC = tmp; break;
       case 72: /* fp, ignored */ break;
       default: 
           if (n > 89)
               return 0;
           /* Other registers are readonly.  Ignore writes.  */
           break;
       }
   
     env->HI[0][env->current_tc] = tswapl(*(target_ulong *)ptr);      return sizeof(target_ulong);
     ptr += sizeof(target_ulong);  }
   #elif defined (TARGET_SH4)
   
     env->CP0_BadVAddr = tswapl(*(target_ulong *)ptr);  /* Hint: Use "set architecture sh4" in GDB to see fpu registers */
     ptr += sizeof(target_ulong);  /* FIXME: We should use XML for this.  */
   
     env->CP0_Cause = tswapl(*(target_ulong *)ptr);  #define NUM_CORE_REGS 59
     ptr += sizeof(target_ulong);  
   
     env->PC[env->current_tc] = tswapl(*(target_ulong *)ptr);  static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     ptr += sizeof(target_ulong);  {
       if (n < 8) {
           if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) {
               GET_REGL(env->gregs[n + 16]);
           } else {
               GET_REGL(env->gregs[n]);
           }
       } else if (n < 16) {
           GET_REGL(env->gregs[n - 8]);
       } else if (n >= 25 && n < 41) {
           GET_REGL(env->fregs[(n - 25) + ((env->fpscr & FPSCR_FR) ? 16 : 0)]);
       } else if (n >= 43 && n < 51) {
           GET_REGL(env->gregs[n - 43]);
       } else if (n >= 51 && n < 59) {
           GET_REGL(env->gregs[n - (51 - 16)]);
       }
       switch (n) {
       case 16: GET_REGL(env->pc);
       case 17: GET_REGL(env->pr);
       case 18: GET_REGL(env->gbr);
       case 19: GET_REGL(env->vbr);
       case 20: GET_REGL(env->mach);
       case 21: GET_REGL(env->macl);
       case 22: GET_REGL(env->sr);
       case 23: GET_REGL(env->fpul);
       case 24: GET_REGL(env->fpscr);
       case 41: GET_REGL(env->ssr);
       case 42: GET_REGL(env->spc);
       }
   
     if (env->CP0_Config1 & (1 << CP0C1_FP))      return 0;
       {  }
         for (i = 0; i < 32; i++)  
           {  
             if (env->CP0_Status & (1 << CP0St_FR))  
               env->fpu->fpr[i].d = tswapl(*(target_ulong *)ptr);  
             else  
               env->fpu->fpr[i].w[FP_ENDIAN_IDX] = tswapl(*(target_ulong *)ptr);  
             ptr += sizeof(target_ulong);  
           }  
   
         env->fpu->fcr31 = tswapl(*(target_ulong *)ptr) & 0xFF83FFFF;  static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
         ptr += sizeof(target_ulong);  {
       uint32_t tmp;
   
         /* The remaining registers are assumed to be read-only. */      tmp = ldl_p(mem_buf);
   
         /* set rounding mode */      if (n < 8) {
         RESTORE_ROUNDING_MODE;          if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) {
               env->gregs[n + 16] = tmp;
           } else {
               env->gregs[n] = tmp;
           }
           return 4;
       } else if (n < 16) {
           env->gregs[n - 8] = tmp;
           return 4;
       } else if (n >= 25 && n < 41) {
           env->fregs[(n - 25) + ((env->fpscr & FPSCR_FR) ? 16 : 0)] = tmp;
       } else if (n >= 43 && n < 51) {
           env->gregs[n - 43] = tmp;
           return 4;
       } else if (n >= 51 && n < 59) {
           env->gregs[n - (51 - 16)] = tmp;
           return 4;
       }
       switch (n) {
       case 16: env->pc = tmp;
       case 17: env->pr = tmp;
       case 18: env->gbr = tmp;
       case 19: env->vbr = tmp;
       case 20: env->mach = tmp;
       case 21: env->macl = tmp;
       case 22: env->sr = tmp;
       case 23: env->fpul = tmp;
       case 24: env->fpscr = tmp;
       case 41: env->ssr = tmp;
       case 42: env->spc = tmp;
       default: return 0;
       }
   
 #ifndef CONFIG_SOFTFLOAT      return 4;
         /* no floating point exception for native float */  
         SET_FP_ENABLE(env->fcr31, 0);  
 #endif  
       }  
 }  }
 #elif defined (TARGET_SH4)  #elif defined (TARGET_CRIS)
   
 /* Hint: Use "set architecture sh4" in GDB to see fpu registers */  #define NUM_CORE_REGS 49
   
 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)  static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
 {  {
   uint32_t *ptr = (uint32_t *)mem_buf;      uint8_t srs;
   int i;  
   
 #define SAVE(x) *ptr++=tswapl(x)      srs = env->pregs[PR_SRS];
   if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) {      if (n < 16) {
       for (i = 0; i < 8; i++) SAVE(env->gregs[i + 16]);          GET_REG32(env->regs[n]);
   } else {      }
       for (i = 0; i < 8; i++) SAVE(env->gregs[i]);  
   }      if (n >= 21 && n < 32) {
   for (i = 8; i < 16; i++) SAVE(env->gregs[i]);          GET_REG32(env->pregs[n - 16]);
   SAVE (env->pc);      }
   SAVE (env->pr);      if (n >= 33 && n < 49) {
   SAVE (env->gbr);          GET_REG32(env->sregs[srs][n - 33]);
   SAVE (env->vbr);      }
   SAVE (env->mach);      switch (n) {
   SAVE (env->macl);      case 16: GET_REG8(env->pregs[0]);
   SAVE (env->sr);      case 17: GET_REG8(env->pregs[1]);
   SAVE (env->fpul);      case 18: GET_REG32(env->pregs[2]);
   SAVE (env->fpscr);      case 19: GET_REG8(srs);
   for (i = 0; i < 16; i++)      case 20: GET_REG16(env->pregs[4]);
       SAVE(env->fregs[i + ((env->fpscr & FPSCR_FR) ? 16 : 0)]);      case 32: GET_REG32(env->pc);
   SAVE (env->ssr);      }
   SAVE (env->spc);  
   for (i = 0; i < 8; i++) SAVE(env->gregs[i]);      return 0;
   for (i = 0; i < 8; i++) SAVE(env->gregs[i + 16]);  
   return ((uint8_t *)ptr - mem_buf);  
 }  
   
 static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)  
 {  
   uint32_t *ptr = (uint32_t *)mem_buf;  
   int i;  
   
 #define LOAD(x) (x)=*ptr++;  
   if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) {  
       for (i = 0; i < 8; i++) LOAD(env->gregs[i + 16]);  
   } else {  
       for (i = 0; i < 8; i++) LOAD(env->gregs[i]);  
   }  
   for (i = 8; i < 16; i++) LOAD(env->gregs[i]);  
   LOAD (env->pc);  
   LOAD (env->pr);  
   LOAD (env->gbr);  
   LOAD (env->vbr);  
   LOAD (env->mach);  
   LOAD (env->macl);  
   LOAD (env->sr);  
   LOAD (env->fpul);  
   LOAD (env->fpscr);  
   for (i = 0; i < 16; i++)  
       LOAD(env->fregs[i + ((env->fpscr & FPSCR_FR) ? 16 : 0)]);  
   LOAD (env->ssr);  
   LOAD (env->spc);  
   for (i = 0; i < 8; i++) LOAD(env->gregs[i]);  
   for (i = 0; i < 8; i++) LOAD(env->gregs[i + 16]);  
 }  }
 #elif defined (TARGET_CRIS)  
   
 static int cris_save_32 (unsigned char *d, uint32_t value)  static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 {  {
         *d++ = (value);      uint32_t tmp;
         *d++ = (value >>= 8);  
         *d++ = (value >>= 8);      if (n > 49)
         *d++ = (value >>= 8);          return 0;
         return 4;  
       tmp = ldl_p(mem_buf);
   
       if (n < 16) {
           env->regs[n] = tmp;
       }
   
       if (n >= 21 && n < 32) {
           env->pregs[n - 16] = tmp;
       }
   
       /* FIXME: Should support function regs be writable?  */
       switch (n) {
       case 16: return 1;
       case 17: return 1;
       case 18: env->pregs[PR_PID] = tmp; break;
       case 19: return 1;
       case 20: return 2;
       case 32: env->pc = tmp; break;
       }
   
       return 4;
 }  }
 static int cris_save_16 (unsigned char *d, uint32_t value)  #elif defined (TARGET_ALPHA)
   
   #define NUM_CORE_REGS 65
   
   static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
 {  {
         *d++ = (value);      if (n < 31) {
         *d++ = (value >>= 8);         GET_REGL(env->ir[n]);
         return 2;      }
       else if (n == 31) {
          GET_REGL(0);
       }
       else if (n<63) {
          uint64_t val;
   
          val=*((uint64_t *)&env->fir[n-32]);
          GET_REGL(val);
       }
       else if (n==63) {
          GET_REGL(env->fpcr);
       }
       else if (n==64) {
          GET_REGL(env->pc);
       }
       else {
          GET_REGL(0);
       }
   
       return 0;
 }  }
 static int cris_save_8 (unsigned char *d, uint32_t value)  
   static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 {  {
         *d++ = (value);      target_ulong tmp;
         return 1;      tmp = ldtul_p(mem_buf);
   
       if (n < 31) {
           env->ir[n] = tmp;
       }
   
       if (n > 31 && n < 63) {
           env->fir[n - 32] = ldfl_p(mem_buf);
       }
   
       if (n == 64 ) {
          env->pc=tmp;
       }
   
       return 8;
 }  }
   #else
   
 /* FIXME: this will bug on archs not supporting unaligned word accesses.  */  #define NUM_CORE_REGS 0
 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)  
 {  
   uint8_t *ptr = mem_buf;  
   uint8_t srs;  
   int i;  
   
   for (i = 0; i < 16; i++)  static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
           ptr += cris_save_32 (ptr, env->regs[i]);  {
       return 0;
   }
   
   srs = env->pregs[SR_SRS];  static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
   {
       return 0;
   }
   
   ptr += cris_save_8 (ptr, env->pregs[0]);  #endif
   ptr += cris_save_8 (ptr, env->pregs[1]);  
   ptr += cris_save_32 (ptr, env->pregs[2]);  
   ptr += cris_save_8 (ptr, srs);  
   ptr += cris_save_16 (ptr, env->pregs[4]);  
   
   for (i = 5; i < 16; i++)  static int num_g_regs = NUM_CORE_REGS;
           ptr += cris_save_32 (ptr, env->pregs[i]);  
   
   ptr += cris_save_32 (ptr, env->pc);  #ifdef GDB_CORE_XML
   /* Encode data using the encoding for 'x' packets.  */
   static int memtox(char *buf, const char *mem, int len)
   {
       char *p = buf;
       char c;
   
       while (len--) {
           c = *(mem++);
           switch (c) {
           case '#': case '$': case '*': case '}':
               *(p++) = '}';
               *(p++) = c ^ 0x20;
               break;
           default:
               *(p++) = c;
               break;
           }
       }
       return p - buf;
   }
   
   for (i = 0; i < 16; i++)  static const char *get_feature_xml(const char *p, const char **newp)
           ptr += cris_save_32 (ptr, env->sregs[srs][i]);  {
       extern const char *const xml_builtin[][2];
       size_t len;
       int i;
       const char *name;
       static char target_xml[1024];
   
   return ((uint8_t *)ptr - mem_buf);      len = 0;
       while (p[len] && p[len] != ':')
           len++;
       *newp = p + len;
   
       name = NULL;
       if (strncmp(p, "target.xml", len) == 0) {
           /* Generate the XML description for this CPU.  */
           if (!target_xml[0]) {
               GDBRegisterState *r;
   
               snprintf(target_xml, sizeof(target_xml),
                        "<?xml version=\"1.0\"?>"
                        "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
                        "<target>"
                        "<xi:include href=\"%s\"/>",
                        GDB_CORE_XML);
   
               for (r = first_cpu->gdb_regs; r; r = r->next) {
                   strcat(target_xml, "<xi:include href=\"");
                   strcat(target_xml, r->xml);
                   strcat(target_xml, "\"/>");
               }
               strcat(target_xml, "</target>");
           }
           return target_xml;
       }
       for (i = 0; ; i++) {
           name = xml_builtin[i][0];
           if (!name || (strncmp(name, p, len) == 0 && strlen(name) == len))
               break;
       }
       return name ? xml_builtin[i][1] : NULL;
 }  }
   #endif
   
 static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)  static int gdb_read_register(CPUState *env, uint8_t *mem_buf, int reg)
 {  {
   uint32_t *ptr = (uint32_t *)mem_buf;      GDBRegisterState *r;
   int i;  
       if (reg < NUM_CORE_REGS)
           return cpu_gdb_read_register(env, mem_buf, reg);
   
 #define LOAD(x) (x)=*ptr++;      for (r = env->gdb_regs; r; r = r->next) {
   for (i = 0; i < 16; i++) LOAD(env->regs[i]);          if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
   LOAD (env->pc);              return r->get_reg(env, mem_buf, reg - r->base_reg);
           }
       }
       return 0;
 }  }
 #else  
 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)  static int gdb_write_register(CPUState *env, uint8_t *mem_buf, int reg)
 {  {
       GDBRegisterState *r;
   
       if (reg < NUM_CORE_REGS)
           return cpu_gdb_write_register(env, mem_buf, reg);
   
       for (r = env->gdb_regs; r; r = r->next) {
           if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
               return r->set_reg(env, mem_buf, reg - r->base_reg);
           }
       }
     return 0;      return 0;
 }  }
   
 static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)  /* Register a supplemental set of CPU registers.  If g_pos is nonzero it
      specifies the first register number and these registers are included in
      a standard "g" packet.  Direction is relative to gdb, i.e. get_reg is
      gdb reading a CPU register, and set_reg is gdb modifying a CPU register.
    */
   
   void gdb_register_coprocessor(CPUState * env,
                                gdb_reg_cb get_reg, gdb_reg_cb set_reg,
                                int num_regs, const char *xml, int g_pos)
   {
       GDBRegisterState *s;
       GDBRegisterState **p;
       static int last_reg = NUM_CORE_REGS;
   
       s = (GDBRegisterState *)qemu_mallocz(sizeof(GDBRegisterState));
       s->base_reg = last_reg;
       s->num_regs = num_regs;
       s->get_reg = get_reg;
       s->set_reg = set_reg;
       s->xml = xml;
       p = &env->gdb_regs;
       while (*p) {
           /* Check for duplicates.  */
           if (strcmp((*p)->xml, xml) == 0)
               return;
           p = &(*p)->next;
       }
       /* Add to end of list.  */
       last_reg += num_regs;
       *p = s;
       if (g_pos) {
           if (g_pos != s->base_reg) {
               fprintf(stderr, "Error: Bad gdb register numbering for '%s'\n"
                       "Expected %d got %d\n", xml, g_pos, s->base_reg);
           } else {
               num_g_regs = last_reg;
           }
       }
   }
   
   /* GDB breakpoint/watchpoint types */
   #define GDB_BREAKPOINT_SW        0
   #define GDB_BREAKPOINT_HW        1
   #define GDB_WATCHPOINT_WRITE     2
   #define GDB_WATCHPOINT_READ      3
   #define GDB_WATCHPOINT_ACCESS    4
   
   #ifndef CONFIG_USER_ONLY
   static const int xlat_gdb_type[] = {
       [GDB_WATCHPOINT_WRITE]  = BP_GDB | BP_MEM_WRITE,
       [GDB_WATCHPOINT_READ]   = BP_GDB | BP_MEM_READ,
       [GDB_WATCHPOINT_ACCESS] = BP_GDB | BP_MEM_ACCESS,
   };
   #endif
   
   static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
   {
       CPUState *env;
       int err = 0;
   
       switch (type) {
       case GDB_BREAKPOINT_SW:
       case GDB_BREAKPOINT_HW:
           for (env = first_cpu; env != NULL; env = env->next_cpu) {
               err = cpu_breakpoint_insert(env, addr, BP_GDB, NULL);
               if (err)
                   break;
           }
           return err;
   #ifndef CONFIG_USER_ONLY
       case GDB_WATCHPOINT_WRITE:
       case GDB_WATCHPOINT_READ:
       case GDB_WATCHPOINT_ACCESS:
           for (env = first_cpu; env != NULL; env = env->next_cpu) {
               err = cpu_watchpoint_insert(env, addr, len, xlat_gdb_type[type],
                                           NULL);
               if (err)
                   break;
           }
           return err;
   #endif
       default:
           return -ENOSYS;
       }
   }
   
   static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
 {  {
       CPUState *env;
       int err = 0;
   
       switch (type) {
       case GDB_BREAKPOINT_SW:
       case GDB_BREAKPOINT_HW:
           for (env = first_cpu; env != NULL; env = env->next_cpu) {
               err = cpu_breakpoint_remove(env, addr, BP_GDB);
               if (err)
                   break;
           }
           return err;
   #ifndef CONFIG_USER_ONLY
       case GDB_WATCHPOINT_WRITE:
       case GDB_WATCHPOINT_READ:
       case GDB_WATCHPOINT_ACCESS:
           for (env = first_cpu; env != NULL; env = env->next_cpu) {
               err = cpu_watchpoint_remove(env, addr, len, xlat_gdb_type[type]);
               if (err)
                   break;
           }
           return err;
   #endif
       default:
           return -ENOSYS;
       }
 }  }
   
   static void gdb_breakpoint_remove_all(void)
   {
       CPUState *env;
   
       for (env = first_cpu; env != NULL; env = env->next_cpu) {
           cpu_breakpoint_remove_all(env, BP_GDB);
   #ifndef CONFIG_USER_ONLY
           cpu_watchpoint_remove_all(env, BP_GDB);
 #endif  #endif
       }
   }
   
 static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)  static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {  {
       CPUState *env;
     const char *p;      const char *p;
     int ch, reg_size, type;      int ch, reg_size, type, res, thread;
     char buf[4096];      char buf[MAX_PACKET_LENGTH];
     uint8_t mem_buf[4096];      uint8_t mem_buf[MAX_PACKET_LENGTH];
     uint32_t *registers;      uint8_t *registers;
     target_ulong addr, len;      target_ulong addr, len;
   
 #ifdef DEBUG_GDB  #ifdef DEBUG_GDB
Line 885  static int gdb_handle_packet(GDBState *s Line 1522  static int gdb_handle_packet(GDBState *s
     switch(ch) {      switch(ch) {
     case '?':      case '?':
         /* TODO: Make this return the correct value for user-mode.  */          /* TODO: Make this return the correct value for user-mode.  */
         snprintf(buf, sizeof(buf), "S%02x", SIGTRAP);          snprintf(buf, sizeof(buf), "T%02xthread:%02x;", GDB_SIGNAL_TRAP,
                    s->c_cpu->cpu_index+1);
         put_packet(s, buf);          put_packet(s, buf);
           /* Remove all the breakpoints when this query is issued,
            * because gdb is doing and initial connect and the state
            * should be cleaned up.
            */
           gdb_breakpoint_remove_all();
         break;          break;
     case 'c':      case 'c':
         if (*p != '\0') {          if (*p != '\0') {
             addr = strtoull(p, (char **)&p, 16);              addr = strtoull(p, (char **)&p, 16);
 #if defined(TARGET_I386)  #if defined(TARGET_I386)
             env->eip = addr;              s->c_cpu->eip = addr;
 #elif defined (TARGET_PPC)  #elif defined (TARGET_PPC)
             env->nip = addr;              s->c_cpu->nip = addr;
 #elif defined (TARGET_SPARC)  #elif defined (TARGET_SPARC)
             env->pc = addr;              s->c_cpu->pc = addr;
             env->npc = addr + 4;              s->c_cpu->npc = addr + 4;
 #elif defined (TARGET_ARM)  #elif defined (TARGET_ARM)
             env->regs[15] = addr;              s->c_cpu->regs[15] = addr;
 #elif defined (TARGET_SH4)  #elif defined (TARGET_SH4)
             env->pc = addr;              s->c_cpu->pc = addr;
 #elif defined (TARGET_MIPS)  #elif defined (TARGET_MIPS)
             env->PC[env->current_tc] = addr;              s->c_cpu->active_tc.PC = addr;
 #elif defined (TARGET_CRIS)  #elif defined (TARGET_CRIS)
             env->pc = addr;              s->c_cpu->pc = addr;
   #elif defined (TARGET_ALPHA)
               s->c_cpu->pc = addr;
 #endif  #endif
         }          }
 #ifdef CONFIG_USER_ONLY          s->signal = 0;
         s->running_state = 1;          gdb_continue(s);
 #else  
         vm_start();  
 #endif  
         return RS_IDLE;          return RS_IDLE;
       case 'C':
           s->signal = gdb_signal_to_target (strtoul(p, (char **)&p, 16));
           if (s->signal == -1)
               s->signal = 0;
           gdb_continue(s);
           return RS_IDLE;
       case 'k':
           /* Kill the target */
           fprintf(stderr, "\nQEMU: Terminated via GDBstub\n");
           exit(0);
       case 'D':
           /* Detach packet */
           gdb_breakpoint_remove_all();
           gdb_continue(s);
           put_packet(s, "OK");
           break;
     case 's':      case 's':
         if (*p != '\0') {          if (*p != '\0') {
             addr = strtoull(p, (char **)&p, 16);              addr = strtoull(p, (char **)&p, 16);
 #if defined(TARGET_I386)  #if defined(TARGET_I386)
             env->eip = addr;              s->c_cpu->eip = addr;
 #elif defined (TARGET_PPC)  #elif defined (TARGET_PPC)
             env->nip = addr;              s->c_cpu->nip = addr;
 #elif defined (TARGET_SPARC)  #elif defined (TARGET_SPARC)
             env->pc = addr;              s->c_cpu->pc = addr;
             env->npc = addr + 4;              s->c_cpu->npc = addr + 4;
 #elif defined (TARGET_ARM)  #elif defined (TARGET_ARM)
             env->regs[15] = addr;              s->c_cpu->regs[15] = addr;
 #elif defined (TARGET_SH4)  #elif defined (TARGET_SH4)
             env->pc = addr;              s->c_cpu->pc = addr;
 #elif defined (TARGET_MIPS)  #elif defined (TARGET_MIPS)
             env->PC[env->current_tc] = addr;              s->c_cpu->active_tc.PC = addr;
 #elif defined (TARGET_CRIS)  #elif defined (TARGET_CRIS)
             env->pc = addr;              s->c_cpu->pc = addr;
   #elif defined (TARGET_ALPHA)
               s->c_cpu->pc = addr;
 #endif  #endif
         }          }
         cpu_single_step(env, 1);          cpu_single_step(s->c_cpu, sstep_flags);
 #ifdef CONFIG_USER_ONLY          gdb_continue(s);
         s->running_state = 1;  
 #else  
         vm_start();  
 #endif  
         return RS_IDLE;          return RS_IDLE;
     case 'F':      case 'F':
         {          {
Line 957  static int gdb_handle_packet(GDBState *s Line 1613  static int gdb_handle_packet(GDBState *s
                 p++;                  p++;
             type = *p;              type = *p;
             if (gdb_current_syscall_cb)              if (gdb_current_syscall_cb)
                 gdb_current_syscall_cb(s->env, ret, err);                  gdb_current_syscall_cb(s->c_cpu, ret, err);
             if (type == 'C') {              if (type == 'C') {
                 put_packet(s, "T02");                  put_packet(s, "T02");
             } else {              } else {
 #ifdef CONFIG_USER_ONLY                  gdb_continue(s);
                 s->running_state = 1;  
 #else  
                 vm_start();  
 #endif  
             }              }
         }          }
         break;          break;
     case 'g':      case 'g':
         reg_size = cpu_gdb_read_registers(env, mem_buf);          len = 0;
         memtohex(buf, mem_buf, reg_size);          for (addr = 0; addr < num_g_regs; addr++) {
               reg_size = gdb_read_register(s->g_cpu, mem_buf + len, addr);
               len += reg_size;
           }
           memtohex(buf, mem_buf, len);
         put_packet(s, buf);          put_packet(s, buf);
         break;          break;
     case 'G':      case 'G':
         registers = (void *)mem_buf;          registers = mem_buf;
         len = strlen(p) / 2;          len = strlen(p) / 2;
         hextomem((uint8_t *)registers, p, len);          hextomem((uint8_t *)registers, p, len);
         cpu_gdb_write_registers(env, mem_buf, len);          for (addr = 0; addr < num_g_regs && len > 0; addr++) {
               reg_size = gdb_write_register(s->g_cpu, registers, addr);
               len -= reg_size;
               registers += reg_size;
           }
         put_packet(s, "OK");          put_packet(s, "OK");
         break;          break;
     case 'm':      case 'm':
Line 986  static int gdb_handle_packet(GDBState *s Line 1646  static int gdb_handle_packet(GDBState *s
         if (*p == ',')          if (*p == ',')
             p++;              p++;
         len = strtoull(p, NULL, 16);          len = strtoull(p, NULL, 16);
         if (cpu_memory_rw_debug(env, addr, mem_buf, len, 0) != 0) {          if (cpu_memory_rw_debug(s->g_cpu, addr, mem_buf, len, 0) != 0) {
             put_packet (s, "E14");              put_packet (s, "E14");
         } else {          } else {
             memtohex(buf, mem_buf, len);              memtohex(buf, mem_buf, len);
Line 1001  static int gdb_handle_packet(GDBState *s Line 1661  static int gdb_handle_packet(GDBState *s
         if (*p == ':')          if (*p == ':')
             p++;              p++;
         hextomem(mem_buf, p, len);          hextomem(mem_buf, p, len);
         if (cpu_memory_rw_debug(env, addr, mem_buf, len, 1) != 0)          if (cpu_memory_rw_debug(s->g_cpu, addr, mem_buf, len, 1) != 0)
             put_packet(s, "E14");              put_packet(s, "E14");
         else          else
             put_packet(s, "OK");              put_packet(s, "OK");
         break;          break;
     case 'Z':      case 'p':
         type = strtoul(p, (char **)&p, 16);          /* Older gdb are really dumb, and don't use 'g' if 'p' is avaialable.
         if (*p == ',')             This works, but can be very slow.  Anything new enough to
             p++;             understand XML also knows how to use this properly.  */
           if (!gdb_has_xml)
               goto unknown_command;
         addr = strtoull(p, (char **)&p, 16);          addr = strtoull(p, (char **)&p, 16);
         if (*p == ',')          reg_size = gdb_read_register(s->g_cpu, mem_buf, addr);
             p++;          if (reg_size) {
         len = strtoull(p, (char **)&p, 16);              memtohex(buf, mem_buf, reg_size);
         if (type == 0 || type == 1) {              put_packet(s, buf);
             if (cpu_breakpoint_insert(env, addr) < 0)  
                 goto breakpoint_error;  
             put_packet(s, "OK");  
 #ifndef CONFIG_USER_ONLY  
         } else if (type == 2) {  
             if (cpu_watchpoint_insert(env, addr) < 0)  
                 goto breakpoint_error;  
             put_packet(s, "OK");  
 #endif  
         } else {          } else {
         breakpoint_error:              put_packet(s, "E14");
             put_packet(s, "E22");  
         }          }
         break;          break;
       case 'P':
           if (!gdb_has_xml)
               goto unknown_command;
           addr = strtoull(p, (char **)&p, 16);
           if (*p == '=')
               p++;
           reg_size = strlen(p) / 2;
           hextomem(mem_buf, p, reg_size);
           gdb_write_register(s->g_cpu, mem_buf, addr);
           put_packet(s, "OK");
           break;
       case 'Z':
     case 'z':      case 'z':
         type = strtoul(p, (char **)&p, 16);          type = strtoul(p, (char **)&p, 16);
         if (*p == ',')          if (*p == ',')
Line 1037  static int gdb_handle_packet(GDBState *s Line 1701  static int gdb_handle_packet(GDBState *s
         if (*p == ',')          if (*p == ',')
             p++;              p++;
         len = strtoull(p, (char **)&p, 16);          len = strtoull(p, (char **)&p, 16);
         if (type == 0 || type == 1) {          if (ch == 'Z')
             cpu_breakpoint_remove(env, addr);              res = gdb_breakpoint_insert(addr, len, type);
           else
               res = gdb_breakpoint_remove(addr, len, type);
           if (res >= 0)
                put_packet(s, "OK");
           else if (res == -ENOSYS)
               put_packet(s, "");
           else
               put_packet(s, "E22");
           break;
       case 'H':
           type = *p++;
           thread = strtoull(p, (char **)&p, 16);
           if (thread == -1 || thread == 0) {
             put_packet(s, "OK");              put_packet(s, "OK");
 #ifndef CONFIG_USER_ONLY              break;
         } else if (type == 2) {          }
             cpu_watchpoint_remove(env, addr);          for (env = first_cpu; env != NULL; env = env->next_cpu)
               if (env->cpu_index + 1 == thread)
                   break;
           if (env == NULL) {
               put_packet(s, "E22");
               break;
           }
           switch (type) {
           case 'c':
               s->c_cpu = env;
             put_packet(s, "OK");              put_packet(s, "OK");
 #endif              break;
         } else {          case 'g':
             goto breakpoint_error;              s->g_cpu = env;
               put_packet(s, "OK");
               break;
           default:
                put_packet(s, "E22");
                break;
         }          }
         break;          break;
 #ifdef CONFIG_LINUX_USER      case 'T':
           thread = strtoull(p, (char **)&p, 16);
   #ifndef CONFIG_USER_ONLY
           if (thread > 0 && thread < smp_cpus + 1)
   #else
           if (thread == 1)
   #endif
                put_packet(s, "OK");
           else
               put_packet(s, "E22");
           break;
     case 'q':      case 'q':
         if (strncmp(p, "Offsets", 7) == 0) {      case 'Q':
             TaskState *ts = env->opaque;          /* parse any 'q' packets here */
           if (!strcmp(p,"qemu.sstepbits")) {
               /* Query Breakpoint bit definitions */
               snprintf(buf, sizeof(buf), "ENABLE=%x,NOIRQ=%x,NOTIMER=%x",
                        SSTEP_ENABLE,
                        SSTEP_NOIRQ,
                        SSTEP_NOTIMER);
               put_packet(s, buf);
               break;
           } else if (strncmp(p,"qemu.sstep",10) == 0) {
               /* Display or change the sstep_flags */
               p += 10;
               if (*p != '=') {
                   /* Display current setting */
                   snprintf(buf, sizeof(buf), "0x%x", sstep_flags);
                   put_packet(s, buf);
                   break;
               }
               p++;
               type = strtoul(p, (char **)&p, 16);
               sstep_flags = type;
               put_packet(s, "OK");
               break;
           } else if (strcmp(p,"C") == 0) {
               /* "Current thread" remains vague in the spec, so always return
                *  the first CPU (gdb returns the first thread). */
               put_packet(s, "QC1");
               break;
           } else if (strcmp(p,"fThreadInfo") == 0) {
               s->query_cpu = first_cpu;
               goto report_cpuinfo;
           } else if (strcmp(p,"sThreadInfo") == 0) {
           report_cpuinfo:
               if (s->query_cpu) {
                   snprintf(buf, sizeof(buf), "m%x", s->query_cpu->cpu_index+1);
                   put_packet(s, buf);
                   s->query_cpu = s->query_cpu->next_cpu;
               } else
                   put_packet(s, "l");
               break;
           } else if (strncmp(p,"ThreadExtraInfo,", 16) == 0) {
               thread = strtoull(p+16, (char **)&p, 16);
               for (env = first_cpu; env != NULL; env = env->next_cpu)
                   if (env->cpu_index + 1 == thread) {
                       len = snprintf((char *)mem_buf, sizeof(mem_buf),
                                      "CPU#%d [%s]", env->cpu_index,
                                      env->halted ? "halted " : "running");
                       memtohex(buf, mem_buf, len);
                       put_packet(s, buf);
                       break;
                   }
               break;
           }
   #ifdef CONFIG_LINUX_USER
           else if (strncmp(p, "Offsets", 7) == 0) {
               TaskState *ts = s->c_cpu->opaque;
   
             sprintf(buf,              snprintf(buf, sizeof(buf),
                     "Text=" TARGET_ABI_FMT_lx ";Data=" TARGET_ABI_FMT_lx                       "Text=" TARGET_ABI_FMT_lx ";Data=" TARGET_ABI_FMT_lx
                     ";Bss=" TARGET_ABI_FMT_lx,                       ";Bss=" TARGET_ABI_FMT_lx,
                     ts->info->code_offset,                       ts->info->code_offset,
                     ts->info->data_offset,                       ts->info->data_offset,
                     ts->info->data_offset);                       ts->info->data_offset);
             put_packet(s, buf);              put_packet(s, buf);
             break;              break;
         }          }
         /* Fall through.  */  
 #endif  #endif
           if (strncmp(p, "Supported", 9) == 0) {
               snprintf(buf, sizeof(buf), "PacketSize=%x", MAX_PACKET_LENGTH);
   #ifdef GDB_CORE_XML
               strcat(buf, ";qXfer:features:read+");
   #endif
               put_packet(s, buf);
               break;
           }
   #ifdef GDB_CORE_XML
           if (strncmp(p, "Xfer:features:read:", 19) == 0) {
               const char *xml;
               target_ulong total_len;
   
               gdb_has_xml = 1;
               p += 19;
               xml = get_feature_xml(p, &p);
               if (!xml) {
                   snprintf(buf, sizeof(buf), "E00");
                   put_packet(s, buf);
                   break;
               }
   
               if (*p == ':')
                   p++;
               addr = strtoul(p, (char **)&p, 16);
               if (*p == ',')
                   p++;
               len = strtoul(p, (char **)&p, 16);
   
               total_len = strlen(xml);
               if (addr > total_len) {
                   snprintf(buf, sizeof(buf), "E00");
                   put_packet(s, buf);
                   break;
               }
               if (len > (MAX_PACKET_LENGTH - 5) / 2)
                   len = (MAX_PACKET_LENGTH - 5) / 2;
               if (len < total_len - addr) {
                   buf[0] = 'm';
                   len = memtox(buf + 1, xml + addr, len);
               } else {
                   buf[0] = 'l';
                   len = memtox(buf + 1, xml + addr, total_len - addr);
               }
               put_packet_binary(s, buf, len + 1);
               break;
           }
   #endif
           /* Unrecognised 'q' command.  */
           goto unknown_command;
   
     default:      default:
         //        unknown_command:      unknown_command:
         /* put empty packet */          /* put empty packet */
         buf[0] = '\0';          buf[0] = '\0';
         put_packet(s, buf);          put_packet(s, buf);
Line 1075  static int gdb_handle_packet(GDBState *s Line 1881  static int gdb_handle_packet(GDBState *s
     return RS_IDLE;      return RS_IDLE;
 }  }
   
 extern void tb_flush(CPUState *env);  void gdb_set_stop_cpu(CPUState *env)
   {
       gdbserver_state->c_cpu = env;
       gdbserver_state->g_cpu = env;
   }
   
 #ifndef CONFIG_USER_ONLY  #ifndef CONFIG_USER_ONLY
 static void gdb_vm_stopped(void *opaque, int reason)  static void gdb_vm_state_change(void *opaque, int running, int reason)
 {  {
     GDBState *s = opaque;      GDBState *s = gdbserver_state;
       CPUState *env = s->c_cpu;
     char buf[256];      char buf[256];
       const char *type;
     int ret;      int ret;
   
     if (s->state == RS_SYSCALL)      if (running || (reason != EXCP_DEBUG && reason != EXCP_INTERRUPT) ||
           s->state == RS_SYSCALL)
         return;          return;
   
     /* disable single step if it was enable */      /* disable single step if it was enable */
     cpu_single_step(s->env, 0);      cpu_single_step(env, 0);
   
     if (reason == EXCP_DEBUG) {      if (reason == EXCP_DEBUG) {
         if (s->env->watchpoint_hit) {          if (env->watchpoint_hit) {
             snprintf(buf, sizeof(buf), "T%02xwatch:" TARGET_FMT_lx ";",              switch (env->watchpoint_hit->flags & BP_MEM_ACCESS) {
                      SIGTRAP,              case BP_MEM_READ:
                      s->env->watchpoint[s->env->watchpoint_hit - 1].vaddr);                  type = "r";
                   break;
               case BP_MEM_ACCESS:
                   type = "a";
                   break;
               default:
                   type = "";
                   break;
               }
               snprintf(buf, sizeof(buf),
                        "T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";",
                        GDB_SIGNAL_TRAP, env->cpu_index+1, type,
                        env->watchpoint_hit->vaddr);
             put_packet(s, buf);              put_packet(s, buf);
             s->env->watchpoint_hit = 0;              env->watchpoint_hit = NULL;
             return;              return;
         }          }
         tb_flush(s->env);          tb_flush(env);
         ret = SIGTRAP;          ret = GDB_SIGNAL_TRAP;
     } else if (reason == EXCP_INTERRUPT) {  
         ret = SIGINT;  
     } else {      } else {
         ret = 0;          ret = GDB_SIGNAL_INT;
     }      }
     snprintf(buf, sizeof(buf), "S%02x", ret);      snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, env->cpu_index+1);
     put_packet(s, buf);      put_packet(s, buf);
 }  }
 #endif  #endif
Line 1116  static void gdb_vm_stopped(void *opaque, Line 1939  static void gdb_vm_stopped(void *opaque,
     %x  - target_ulong argument printed in hex.      %x  - target_ulong argument printed in hex.
     %lx - 64-bit argument printed in hex.      %lx - 64-bit argument printed in hex.
     %s  - string pointer (target_ulong) and length (int) pair.  */      %s  - string pointer (target_ulong) and length (int) pair.  */
 void gdb_do_syscall(gdb_syscall_complete_cb cb, char *fmt, ...)  void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
 {  {
     va_list va;      va_list va;
     char buf[256];      char buf[256];
Line 1125  void gdb_do_syscall(gdb_syscall_complete Line 1948  void gdb_do_syscall(gdb_syscall_complete
     uint64_t i64;      uint64_t i64;
     GDBState *s;      GDBState *s;
   
     s = gdb_syscall_state;      s = gdbserver_state;
     if (!s)      if (!s)
         return;          return;
     gdb_current_syscall_cb = cb;      gdb_current_syscall_cb = cb;
Line 1143  void gdb_do_syscall(gdb_syscall_complete Line 1966  void gdb_do_syscall(gdb_syscall_complete
             switch (*fmt++) {              switch (*fmt++) {
             case 'x':              case 'x':
                 addr = va_arg(va, target_ulong);                  addr = va_arg(va, target_ulong);
                 p += sprintf(p, TARGET_FMT_lx, addr);                  p += snprintf(p, &buf[sizeof(buf)] - p, TARGET_FMT_lx, addr);
                 break;                  break;
             case 'l':              case 'l':
                 if (*(fmt++) != 'x')                  if (*(fmt++) != 'x')
                     goto bad_format;                      goto bad_format;
                 i64 = va_arg(va, uint64_t);                  i64 = va_arg(va, uint64_t);
                 p += sprintf(p, "%" PRIx64, i64);                  p += snprintf(p, &buf[sizeof(buf)] - p, "%" PRIx64, i64);
                 break;                  break;
             case 's':              case 's':
                 addr = va_arg(va, target_ulong);                  addr = va_arg(va, target_ulong);
                 p += sprintf(p, TARGET_FMT_lx "/%x", addr, va_arg(va, int));                  p += snprintf(p, &buf[sizeof(buf)] - p, TARGET_FMT_lx "/%x",
                                 addr, va_arg(va, int));
                 break;                  break;
             default:              default:
             bad_format:              bad_format:
Line 1169  void gdb_do_syscall(gdb_syscall_complete Line 1993  void gdb_do_syscall(gdb_syscall_complete
     va_end(va);      va_end(va);
     put_packet(s, buf);      put_packet(s, buf);
 #ifdef CONFIG_USER_ONLY  #ifdef CONFIG_USER_ONLY
     gdb_handlesig(s->env, 0);      gdb_handlesig(s->c_cpu, 0);
 #else  #else
     cpu_interrupt(s->env, CPU_INTERRUPT_EXIT);      cpu_interrupt(s->c_cpu, CPU_INTERRUPT_EXIT);
 #endif  #endif
 }  }
   
 static void gdb_read_byte(GDBState *s, int ch)  static void gdb_read_byte(GDBState *s, int ch)
 {  {
     CPUState *env = s->env;  
     int i, csum;      int i, csum;
     uint8_t reply;      uint8_t reply;
   
Line 1243  static void gdb_read_byte(GDBState *s, i Line 2066  static void gdb_read_byte(GDBState *s, i
             } else {              } else {
                 reply = '+';                  reply = '+';
                 put_buffer(s, &reply, 1);                  put_buffer(s, &reply, 1);
                 s->state = gdb_handle_packet(s, env, s->line_buf);                  s->state = gdb_handle_packet(s, s->line_buf);
             }              }
             break;              break;
         default:          default:
Line 1254  static void gdb_read_byte(GDBState *s, i Line 2077  static void gdb_read_byte(GDBState *s, i
   
 #ifdef CONFIG_USER_ONLY  #ifdef CONFIG_USER_ONLY
 int  int
   gdb_queuesig (void)
   {
       GDBState *s;
   
       s = gdbserver_state;
   
       if (gdbserver_fd < 0 || s->fd < 0)
           return 0;
       else
           return 1;
   }
   
   int
 gdb_handlesig (CPUState *env, int sig)  gdb_handlesig (CPUState *env, int sig)
 {  {
   GDBState *s;    GDBState *s;
   char buf[256];    char buf[256];
   int n;    int n;
   
   if (gdbserver_fd < 0)    s = gdbserver_state;
     if (gdbserver_fd < 0 || s->fd < 0)
     return sig;      return sig;
   
   s = &gdbserver_state;  
   
   /* disable single step if it was enabled */    /* disable single step if it was enabled */
   cpu_single_step(env, 0);    cpu_single_step(env, 0);
   tb_flush(env);    tb_flush(env);
   
   if (sig != 0)    if (sig != 0)
     {      {
       snprintf(buf, sizeof(buf), "S%02x", sig);        snprintf(buf, sizeof(buf), "S%02x", target_signal_to_gdb (sig));
       put_packet(s, buf);        put_packet(s, buf);
     }      }
     /* put_packet() might have detected that the peer terminated the 
        connection.  */
     if (s->fd < 0)
         return sig;
   
   sig = 0;    sig = 0;
   s->state = RS_IDLE;    s->state = RS_IDLE;
Line 1294  gdb_handlesig (CPUState *env, int sig) Line 2133  gdb_handlesig (CPUState *env, int sig)
           return sig;            return sig;
         }          }
   }    }
     sig = s->signal;
     s->signal = 0;
   return sig;    return sig;
 }  }
   
Line 1303  void gdb_exit(CPUState *env, int code) Line 2144  void gdb_exit(CPUState *env, int code)
   GDBState *s;    GDBState *s;
   char buf[4];    char buf[4];
   
   if (gdbserver_fd < 0)    s = gdbserver_state;
     if (gdbserver_fd < 0 || s->fd < 0)
     return;      return;
   
   s = &gdbserver_state;  
   
   snprintf(buf, sizeof(buf), "W%02x", code);    snprintf(buf, sizeof(buf), "W%02x", code);
   put_packet(s, buf);    put_packet(s, buf);
 }  }
   
   /* Tell the remote gdb that the process has exited due to SIG.  */
   void gdb_signalled(CPUState *env, int sig)
   {
     GDBState *s;
     char buf[4];
   
     s = gdbserver_state;
     if (gdbserver_fd < 0 || s->fd < 0)
       return;
   
 static void gdb_accept(void *opaque)    snprintf(buf, sizeof(buf), "X%02x", target_signal_to_gdb (sig));
     put_packet(s, buf);
   }
   
   static void gdb_accept(void)
 {  {
     GDBState *s;      GDBState *s;
     struct sockaddr_in sockaddr;      struct sockaddr_in sockaddr;
Line 1335  static void gdb_accept(void *opaque) Line 2188  static void gdb_accept(void *opaque)
     val = 1;      val = 1;
     setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));      setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
   
     s = &gdbserver_state;      s = qemu_mallocz(sizeof(GDBState));
   
     memset (s, 0, sizeof (GDBState));      memset (s, 0, sizeof (GDBState));
     s->env = first_cpu; /* XXX: allow to change CPU */      s->c_cpu = first_cpu;
       s->g_cpu = first_cpu;
     s->fd = fd;      s->fd = fd;
       gdb_has_xml = 0;
   
     gdb_syscall_state = s;      gdbserver_state = s;
   
     fcntl(fd, F_SETFL, O_NONBLOCK);      fcntl(fd, F_SETFL, O_NONBLOCK);
 }  }
Line 1382  int gdbserver_start(int port) Line 2238  int gdbserver_start(int port)
     if (gdbserver_fd < 0)      if (gdbserver_fd < 0)
         return -1;          return -1;
     /* accept connections */      /* accept connections */
     gdb_accept (NULL);      gdb_accept();
     return 0;      return 0;
 }  }
   
   /* Disable gdb stub for child processes.  */
   void gdbserver_fork(CPUState *env)
   {
       GDBState *s = gdbserver_state;
       if (gdbserver_fd < 0 || s->fd < 0)
         return;
       close(s->fd);
       s->fd = -1;
       cpu_breakpoint_remove_all(env, BP_GDB);
       cpu_watchpoint_remove_all(env, BP_GDB);
   }
 #else  #else
 static int gdb_chr_can_receive(void *opaque)  static int gdb_chr_can_receive(void *opaque)
 {  {
   return 1;    /* We can handle an arbitrarily large amount of data.
      Pick the maximum packet size, which is as good as anything.  */
     return MAX_PACKET_LENGTH;
 }  }
   
 static void gdb_chr_receive(void *opaque, const uint8_t *buf, int size)  static void gdb_chr_receive(void *opaque, const uint8_t *buf, int size)
 {  {
     GDBState *s = opaque;  
     int i;      int i;
   
     for (i = 0; i < size; i++) {      for (i = 0; i < size; i++) {
         gdb_read_byte(s, buf[i]);          gdb_read_byte(gdbserver_state, buf[i]);
     }      }
 }  }
   
Line 1406  static void gdb_chr_event(void *opaque,  Line 2275  static void gdb_chr_event(void *opaque, 
     switch (event) {      switch (event) {
     case CHR_EVENT_RESET:      case CHR_EVENT_RESET:
         vm_stop(EXCP_INTERRUPT);          vm_stop(EXCP_INTERRUPT);
         gdb_syscall_state = opaque;          gdb_has_xml = 0;
         break;          break;
     default:      default:
         break;          break;
Line 1432  int gdbserver_start(const char *port) Line 2301  int gdbserver_start(const char *port)
         port = gdbstub_port_name;          port = gdbstub_port_name;
     }      }
   
     chr = qemu_chr_open(port);      chr = qemu_chr_open("gdb", port, NULL);
     if (!chr)      if (!chr)
         return -1;          return -1;
   
     s = qemu_mallocz(sizeof(GDBState));      s = qemu_mallocz(sizeof(GDBState));
     if (!s) {      s->c_cpu = first_cpu;
         return -1;      s->g_cpu = first_cpu;
     }  
     s->env = first_cpu; /* XXX: allow to change CPU */  
     s->chr = chr;      s->chr = chr;
       gdbserver_state = s;
     qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,      qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
                           gdb_chr_event, s);                            gdb_chr_event, NULL);
     qemu_add_vm_stop_handler(gdb_vm_stopped, s);      qemu_add_vm_change_state_handler(gdb_vm_state_change, NULL);
     return 0;      return 0;
 }  }
 #endif  #endif

Removed from v.1.1.1.6  
changed lines
  Added in v.1.1.1.7


unix.superglobalmegacorp.com