]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
2008-09-30 Hui Zhu <teawater@gmail.com>
authorMichael Snyder <msnyder@vmware.com>
Wed, 1 Oct 2008 04:23:32 +0000 (04:23 +0000)
committerMichael Snyder <msnyder@vmware.com>
Wed, 1 Oct 2008 04:23:32 +0000 (04:23 +0000)
Add process record and replay to i386 architecture.
* i386-linux-tdep.c (linux_record_tdep): New static variable.
I386 Linux record target-dependent stuff.
(i386_linux_intx80_sysenter_record): New function. Record the
running message of I386 Linux system call.
(i386_linux_init_ab): Initialize the linux_record_tdep. Add
i386_linux_intx80_sysenter_record to struct tdep.
* i386-tdep.c (i386_record_modrm, i386_record_lea_modrm_addr,
i386_record_lea_modrm, i386_record): New functions. Record the
running message of I386 instruction.
(i386_gdbarch_init): Add i386_record to struct gdbarch.
* i386-tdep.h (gdbarch_tdep): Add elements "i386_intx80_record"
and "i386_sysenter_record" to be the interfaces that record the
running message of instruction "intx80" and "sysenter".
* gdbarch.sh: Change process_record and process_record_dasm
to multi-arch model.
* gdbarch.c, gdbarch.h: Regenerate.

gdb/ChangeLog
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh
gdb/i386-linux-tdep.c
gdb/i386-tdep.c
gdb/i386-tdep.h

index ca7dc1b565354e0a2fe095ce3ae9f8c912b13a6e..2d1a7437374ba5751cd2c0e8d368ac307b83e998 100644 (file)
        * linux-record.c, linux-record.h: New files.
        * config/i386/linux.mh: Add linux-record.o to NATDEPFILES.
        * Makefile.in: Add files linux-record.c, linux-record.o.
+
+       Add process record and replay to i386 architecture.
+       * i386-linux-tdep.c (linux_record_tdep): New static variable. 
+       I386 Linux record target-dependent stuff.
+       (i386_linux_intx80_sysenter_record): New function. Record the 
+       running message of I386 Linux system call.
+       (i386_linux_init_ab): Initialize the linux_record_tdep. Add
+       i386_linux_intx80_sysenter_record to struct tdep.
+       * i386-tdep.c (i386_record_modrm, i386_record_lea_modrm_addr,
+       i386_record_lea_modrm, i386_record): New functions. Record the 
+       running message of I386 instruction.
+       (i386_gdbarch_init): Add i386_record to struct gdbarch.
+       * i386-tdep.h (gdbarch_tdep): Add elements "i386_intx80_record"
+       and "i386_sysenter_record" to be the interfaces that record the
+       running message of instruction "intx80" and "sysenter".
+       * gdbarch.sh: Change process_record and process_record_dasm
+       to multi-arch model.
+       * gdbarch.c, gdbarch.h: Regenerate.
        
 2008-09-30  Michael Snyder  <msnyder@vmware.com>
        Target interface for reverse debugging.
index 32481c48ad720e55f368efaa3ec12c3f7cb9857e..b906d1b4edba34031c3c2131e4dddc755a4b64a1 100644 (file)
@@ -625,6 +625,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of static_transform_name, has predicate */
   /* Skip verify of sofun_address_maybe_missing, invalid_p == 0 */
   /* Skip verify of process_record, has predicate */
+  /* Skip verify of process_record_dasm, has predicate */
   /* Skip verify of target_signal_from_host, invalid_p == 0 */
   /* Skip verify of target_signal_to_host, invalid_p == 0 */
   /* Skip verify of record_special_symbol, has predicate */
@@ -926,6 +927,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                       "gdbarch_dump: process_record = <0x%lx>\n",
                       (long) gdbarch->process_record);
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_process_record_dasm_p() = %d\n",
+                      gdbarch_process_record_dasm_p (gdbarch));
   fprintf_unfiltered (file,
                       "gdbarch_dump: process_record_dasm = <0x%lx>\n",
                       (long) gdbarch->process_record_dasm);
@@ -3207,7 +3211,7 @@ gdbarch_process_record (struct gdbarch *gdbarch, CORE_ADDR addr)
   gdb_assert (gdbarch->process_record != NULL);
   if (gdbarch_debug >= 2)
     fprintf_unfiltered (gdb_stdlog, "gdbarch_process_record called\n");
-  return gdbarch->process_record (addr);
+  return gdbarch->process_record (gdbarch, addr);
 }
 
 void
@@ -3217,6 +3221,13 @@ set_gdbarch_process_record (struct gdbarch *gdbarch,
   gdbarch->process_record = process_record;
 }
 
+int
+gdbarch_process_record_dasm_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->process_record_dasm != NULL;
+}
+
 void
 gdbarch_process_record_dasm (struct gdbarch *gdbarch)
 {
@@ -3224,7 +3235,7 @@ gdbarch_process_record_dasm (struct gdbarch *gdbarch)
   gdb_assert (gdbarch->process_record_dasm != NULL);
   if (gdbarch_debug >= 2)
     fprintf_unfiltered (gdb_stdlog, "gdbarch_process_record_dasm called\n");
-  gdbarch->process_record_dasm ();
+  gdbarch->process_record_dasm (gdbarch);
 }
 
 void
index 1bdf6ea4fec72ae86718a496c7cf4cd20e62be39..5bee11a4bed17f0f3727a3e419fca7871cddc3d4 100644 (file)
@@ -793,11 +793,13 @@ extern void set_gdbarch_sofun_address_maybe_missing (struct gdbarch *gdbarch, in
 
 extern int gdbarch_process_record_p (struct gdbarch *gdbarch);
 
-typedef int (gdbarch_process_record_ftype) (CORE_ADDR addr);
+typedef int (gdbarch_process_record_ftype) (struct gdbarch *gdbarch, CORE_ADDR addr);
 extern int gdbarch_process_record (struct gdbarch *gdbarch, CORE_ADDR addr);
 extern void set_gdbarch_process_record (struct gdbarch *gdbarch, gdbarch_process_record_ftype *process_record);
 
-typedef void (gdbarch_process_record_dasm_ftype) (void);
+extern int gdbarch_process_record_dasm_p (struct gdbarch *gdbarch);
+
+typedef void (gdbarch_process_record_dasm_ftype) (struct gdbarch *gdbarch);
 extern void gdbarch_process_record_dasm (struct gdbarch *gdbarch);
 extern void set_gdbarch_process_record_dasm (struct gdbarch *gdbarch, gdbarch_process_record_dasm_ftype *process_record_dasm);
 
index 418086997382637d629bb2450b82e07c38bced37..0b2e4178b9e8119174bc40098e7777eb39f9b7cd 100755 (executable)
@@ -699,8 +699,8 @@ F:char *:static_transform_name:char *name:name
 v:int:sofun_address_maybe_missing:::0:0::0
 
 # For the process record and replay target
-F:int:process_record:CORE_ADDR addr:addr
-f:void:process_record_dasm:void
+M:int:process_record:CORE_ADDR addr:addr
+M:void:process_record_dasm:void
 
 # Signal translation: translate inferior's signal (host's) number into
 # GDB's representation.
index 5284f4a6ead34134c7e822565f56cb5682eefd01..dff70e8aae382af876b5e3ee6c055144ec2a607b 100644 (file)
 #include "arch-utils.h"
 #include "regset.h"
 
+#include "record.h"
+#include "linux-record.h"
+#include <stdint.h>
+
 /* Supported register note sections.  */
 static struct core_regset_section i386_linux_regset_sections[] =
 {
@@ -346,6 +350,37 @@ i386_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
      restarted.  */
   regcache_cooked_write_unsigned (regcache, I386_LINUX_ORIG_EAX_REGNUM, -1);
 }
+
+/* Parse the arguments of current system call instruction and record the
+   values of the registers and memory that will be changed in current system
+   call instruction to "record_arch_list". This instruction is "int 0x80" (Linux
+   Kernel2.4) or "sysenter" (Linux Kernel 2.6).
+   Return -1 if something wrong. */
+
+static linux_record_tdep_t linux_record_tdep;
+
+static int
+i386_linux_intx80_sysenter_record (void)
+{
+  int ret;
+  uint32_t tmpu32;
+
+  regcache_raw_read (record_regcache, I386_EAX_REGNUM, (gdb_byte *) & tmpu32);
+
+  ret = record_linux_system_call (tmpu32, &linux_record_tdep);
+  if (ret)
+    {
+      return ret;
+    }
+
+  /* Record the return of system call. */
+  if (record_arch_list_add_reg (I386_EAX_REGNUM))
+    {
+      return -1;
+    }
+
+  return 0;
+}
 \f
 
 /* The register sets used in GNU/Linux ELF core-dumps are identical to
@@ -413,6 +448,144 @@ static int i386_linux_sc_reg_offset[] =
   0 * 4                                /* %gs */
 };
 
+/* These macros are the size of the type that will be use in system call. The values of
+   these macros are gotten from Linux Kernel source. */
+#define I386_RECORD_SIZE__old_kernel_stat      32
+#define I386_RECORD_SIZE_tms                   16
+#define I386_RECORD_SIZE_loff_t                        8
+#define I386_RECORD_SIZE_flock                 16
+#define I386_RECORD_SIZE_oldold_utsname                45
+#define I386_RECORD_SIZE_ustat                 20
+#define I386_RECORD_SIZE_old_sigaction         140
+#define I386_RECORD_SIZE_old_sigset_t          128
+#define I386_RECORD_SIZE_rlimit                        8
+#define I386_RECORD_SIZE_rusage                        72
+#define I386_RECORD_SIZE_timeval               8
+#define I386_RECORD_SIZE_timezone              8
+#define I386_RECORD_SIZE_old_gid_t             2
+#define I386_RECORD_SIZE_old_uid_t             2
+#define I386_RECORD_SIZE_fd_set                        128
+#define I386_RECORD_SIZE_dirent                        268
+#define I386_RECORD_SIZE_dirent64              276
+#define I386_RECORD_SIZE_statfs                        64
+#define I386_RECORD_SIZE_statfs64              84
+#define I386_RECORD_SIZE_sockaddr              16
+#define I386_RECORD_SIZE_int                   4
+#define I386_RECORD_SIZE_long                  4
+#define I386_RECORD_SIZE_ulong                 4
+#define I386_RECORD_SIZE_msghdr                        28
+#define I386_RECORD_SIZE_itimerval             16
+#define I386_RECORD_SIZE_stat                  88
+#define I386_RECORD_SIZE_old_utsname           325
+#define I386_RECORD_SIZE_sysinfo               64
+#define I386_RECORD_SIZE_msqid_ds              88
+#define I386_RECORD_SIZE_shmid_ds              84
+#define I386_RECORD_SIZE_new_utsname           390
+#define I386_RECORD_SIZE_timex                 128
+#define I386_RECORD_SIZE_mem_dqinfo            24
+#define I386_RECORD_SIZE_if_dqblk              68
+#define I386_RECORD_SIZE_fs_quota_stat         68
+#define I386_RECORD_SIZE_timespec              8
+#define I386_RECORD_SIZE_pollfd                        8
+#define I386_RECORD_SIZE_NFS_FHSIZE            32
+#define I386_RECORD_SIZE_knfsd_fh              132
+#define I386_RECORD_SIZE_TASK_COMM_LEN         16
+#define I386_RECORD_SIZE_sigaction             140
+#define I386_RECORD_SIZE_sigset_t              8
+#define I386_RECORD_SIZE_siginfo_t             128
+#define I386_RECORD_SIZE_cap_user_data_t       12
+#define I386_RECORD_SIZE_stack_t               12
+#define I386_RECORD_SIZE_off_t                 I386_RECORD_SIZE_long
+#define I386_RECORD_SIZE_stat64                        96
+#define I386_RECORD_SIZE_gid_t                 2
+#define I386_RECORD_SIZE_uid_t                 2
+#define I386_RECORD_SIZE_PAGE_SIZE             4096
+#define I386_RECORD_SIZE_flock64               24
+#define I386_RECORD_SIZE_user_desc             16
+#define I386_RECORD_SIZE_io_event              32
+#define I386_RECORD_SIZE_iocb                  64
+#define I386_RECORD_SIZE_epoll_event           12
+#define I386_RECORD_SIZE_itimerspec            (I386_RECORD_SIZE_timespec * 2)
+#define I386_RECORD_SIZE_mq_attr               32
+#define I386_RECORD_SIZE_siginfo               128
+#define I386_RECORD_SIZE_termios               36
+#define I386_RECORD_SIZE_termios2              44
+#define I386_RECORD_SIZE_pid_t                 4
+#define I386_RECORD_SIZE_winsize               8
+#define I386_RECORD_SIZE_char                  8
+#define I386_RECORD_SIZE_serial_struct         60
+#define I386_RECORD_SIZE_serial_icounter_struct        80
+#define I386_RECORD_SIZE_hayes_esp_config      12
+
+/* These macros are the values of the second argument of system call
+   "sys_ioctl". The values of these macros are gotten from Linux Kernel
+   source. */
+#define I386_RECORD_IOCTL_TCGETS               0x5401
+#define I386_RECORD_IOCTL_TCSETS               0x5402
+#define I386_RECORD_IOCTL_TCSETSW              0x5403
+#define I386_RECORD_IOCTL_TCSETSF              0x5404
+#define I386_RECORD_IOCTL_TCGETA               0x5405
+#define I386_RECORD_IOCTL_TCSETA               0x5406
+#define I386_RECORD_IOCTL_TCSETAW              0x5407
+#define I386_RECORD_IOCTL_TCSETAF              0x5408
+#define I386_RECORD_IOCTL_TCSBRK               0x5409
+#define I386_RECORD_IOCTL_TCXONC               0x540A
+#define I386_RECORD_IOCTL_TCFLSH               0x540B
+#define I386_RECORD_IOCTL_TIOCEXCL             0x540C
+#define I386_RECORD_IOCTL_TIOCNXCL             0x540D
+#define I386_RECORD_IOCTL_TIOCSCTTY            0x540E
+#define I386_RECORD_IOCTL_TIOCGPGRP            0x540F
+#define I386_RECORD_IOCTL_TIOCSPGRP            0x5410
+#define I386_RECORD_IOCTL_TIOCOUTQ             0x5411
+#define I386_RECORD_IOCTL_TIOCSTI              0x5412
+#define I386_RECORD_IOCTL_TIOCGWINSZ           0x5413
+#define I386_RECORD_IOCTL_TIOCSWINSZ           0x5414
+#define I386_RECORD_IOCTL_TIOCMGET             0x5415
+#define I386_RECORD_IOCTL_TIOCMBIS             0x5416
+#define I386_RECORD_IOCTL_TIOCMBIC             0x5417
+#define I386_RECORD_IOCTL_TIOCMSET             0x5418
+#define I386_RECORD_IOCTL_TIOCGSOFTCAR         0x5419
+#define I386_RECORD_IOCTL_TIOCSSOFTCAR         0x541A
+#define I386_RECORD_IOCTL_FIONREAD             0x541B
+#define I386_RECORD_IOCTL_TIOCINQ              I386_RECORD_IOCTL_FIONREAD
+#define I386_RECORD_IOCTL_TIOCLINUX            0x541C
+#define I386_RECORD_IOCTL_TIOCCONS             0x541D
+#define I386_RECORD_IOCTL_TIOCGSERIAL          0x541E
+#define I386_RECORD_IOCTL_TIOCSSERIAL          0x541F
+#define I386_RECORD_IOCTL_TIOCPKT              0x5420
+#define I386_RECORD_IOCTL_FIONBIO              0x5421
+#define I386_RECORD_IOCTL_TIOCNOTTY            0x5422
+#define I386_RECORD_IOCTL_TIOCSETD             0x5423
+#define I386_RECORD_IOCTL_TIOCGETD             0x5424
+#define I386_RECORD_IOCTL_TCSBRKP              0x5425
+#define I386_RECORD_IOCTL_TIOCTTYGSTRUCT       0x5426
+#define I386_RECORD_IOCTL_TIOCSBRK             0x5427
+#define I386_RECORD_IOCTL_TIOCCBRK             0x5428
+#define I386_RECORD_IOCTL_TIOCGSID             0x5429
+#define I386_RECORD_IOCTL_TCGETS2              0x802c542a
+#define I386_RECORD_IOCTL_TCSETS2              0x402c542b
+#define I386_RECORD_IOCTL_TCSETSW2             0x402c542c
+#define I386_RECORD_IOCTL_TCSETSF2             0x402c542d
+#define I386_RECORD_IOCTL_TIOCGPTN             0x80045430
+#define I386_RECORD_IOCTL_TIOCSPTLCK           0x40045431
+#define I386_RECORD_IOCTL_FIONCLEX             0x5450
+#define I386_RECORD_IOCTL_FIOCLEX              0x5451
+#define I386_RECORD_IOCTL_FIOASYNC             0x5452
+#define I386_RECORD_IOCTL_TIOCSERCONFIG                0x5453
+#define I386_RECORD_IOCTL_TIOCSERGWILD         0x5454
+#define I386_RECORD_IOCTL_TIOCSERSWILD         0x5455
+#define I386_RECORD_IOCTL_TIOCGLCKTRMIOS       0x5456
+#define I386_RECORD_IOCTL_TIOCSLCKTRMIOS       0x5457
+#define I386_RECORD_IOCTL_TIOCSERGSTRUCT       0x5458
+#define I386_RECORD_IOCTL_TIOCSERGETLSR        0x5459
+#define I386_RECORD_IOCTL_TIOCSERGETMULTI      0x545A
+#define I386_RECORD_IOCTL_TIOCSERSETMULTI      0x545B
+#define I386_RECORD_IOCTL_TIOCMIWAIT           0x545C
+#define I386_RECORD_IOCTL_TIOCGICOUNT          0x545D
+#define I386_RECORD_IOCTL_TIOCGHAYESESP                0x545E
+#define I386_RECORD_IOCTL_TIOCSHAYESESP                0x545F
+#define I386_RECORD_IOCTL_FIOQSIZE             0x5460
+
 static void
 i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
@@ -440,6 +613,150 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   tdep->sc_reg_offset = i386_linux_sc_reg_offset;
   tdep->sc_num_regs = ARRAY_SIZE (i386_linux_sc_reg_offset);
 
+  /* Initial the linux_record_tdep */
+  linux_record_tdep.size__old_kernel_stat = I386_RECORD_SIZE__old_kernel_stat;
+  linux_record_tdep.size_tms = I386_RECORD_SIZE_tms;
+  linux_record_tdep.size_loff_t = I386_RECORD_SIZE_loff_t;
+  linux_record_tdep.size_flock = I386_RECORD_SIZE_flock;
+  linux_record_tdep.size_oldold_utsname = I386_RECORD_SIZE_oldold_utsname;
+  linux_record_tdep.size_ustat = I386_RECORD_SIZE_ustat;
+  linux_record_tdep.size_old_sigaction = I386_RECORD_SIZE_old_sigaction;
+  linux_record_tdep.size_old_sigset_t = I386_RECORD_SIZE_old_sigset_t;
+  linux_record_tdep.size_rlimit = I386_RECORD_SIZE_rlimit;
+  linux_record_tdep.size_rusage = I386_RECORD_SIZE_rusage;
+  linux_record_tdep.size_timeval = I386_RECORD_SIZE_timeval;
+  linux_record_tdep.size_timezone = I386_RECORD_SIZE_timezone;
+  linux_record_tdep.size_old_gid_t = I386_RECORD_SIZE_old_gid_t;
+  linux_record_tdep.size_old_uid_t = I386_RECORD_SIZE_old_uid_t;
+  linux_record_tdep.size_fd_set = I386_RECORD_SIZE_fd_set;
+  linux_record_tdep.size_dirent = I386_RECORD_SIZE_dirent;
+  linux_record_tdep.size_dirent64 = I386_RECORD_SIZE_dirent64;
+  linux_record_tdep.size_statfs = I386_RECORD_SIZE_statfs;
+  linux_record_tdep.size_statfs64 = I386_RECORD_SIZE_statfs64;
+  linux_record_tdep.size_sockaddr = I386_RECORD_SIZE_sockaddr;
+  linux_record_tdep.size_int = I386_RECORD_SIZE_int;
+  linux_record_tdep.size_long = I386_RECORD_SIZE_long;
+  linux_record_tdep.size_ulong = I386_RECORD_SIZE_ulong;
+  linux_record_tdep.size_msghdr = I386_RECORD_SIZE_msghdr;
+  linux_record_tdep.size_itimerval = I386_RECORD_SIZE_itimerval;
+  linux_record_tdep.size_stat = I386_RECORD_SIZE_stat;
+  linux_record_tdep.size_old_utsname = I386_RECORD_SIZE_old_utsname;
+  linux_record_tdep.size_sysinfo = I386_RECORD_SIZE_sysinfo;
+  linux_record_tdep.size_msqid_ds = I386_RECORD_SIZE_msqid_ds;
+  linux_record_tdep.size_shmid_ds = I386_RECORD_SIZE_shmid_ds;
+  linux_record_tdep.size_new_utsname = I386_RECORD_SIZE_new_utsname;
+  linux_record_tdep.size_timex = I386_RECORD_SIZE_timex;
+  linux_record_tdep.size_mem_dqinfo = I386_RECORD_SIZE_mem_dqinfo;
+  linux_record_tdep.size_if_dqblk = I386_RECORD_SIZE_if_dqblk;
+  linux_record_tdep.size_fs_quota_stat = I386_RECORD_SIZE_fs_quota_stat;
+  linux_record_tdep.size_timespec = I386_RECORD_SIZE_timespec;
+  linux_record_tdep.size_pollfd = I386_RECORD_SIZE_pollfd;
+  linux_record_tdep.size_NFS_FHSIZE = I386_RECORD_SIZE_NFS_FHSIZE;
+  linux_record_tdep.size_knfsd_fh = I386_RECORD_SIZE_knfsd_fh;
+  linux_record_tdep.size_TASK_COMM_LEN = I386_RECORD_SIZE_TASK_COMM_LEN;
+  linux_record_tdep.size_sigaction = I386_RECORD_SIZE_sigaction;
+  linux_record_tdep.size_sigset_t = I386_RECORD_SIZE_sigset_t;
+  linux_record_tdep.size_siginfo_t = I386_RECORD_SIZE_siginfo_t;
+  linux_record_tdep.size_cap_user_data_t = I386_RECORD_SIZE_cap_user_data_t;
+  linux_record_tdep.size_stack_t = I386_RECORD_SIZE_stack_t;
+  linux_record_tdep.size_off_t = I386_RECORD_SIZE_off_t;
+  linux_record_tdep.size_stat64 = I386_RECORD_SIZE_stat64;
+  linux_record_tdep.size_gid_t = I386_RECORD_SIZE_gid_t;
+  linux_record_tdep.size_uid_t = I386_RECORD_SIZE_uid_t;
+  linux_record_tdep.size_PAGE_SIZE = I386_RECORD_SIZE_PAGE_SIZE;
+  linux_record_tdep.size_flock64 = I386_RECORD_SIZE_flock64;
+  linux_record_tdep.size_user_desc = I386_RECORD_SIZE_user_desc;
+  linux_record_tdep.size_io_event = I386_RECORD_SIZE_io_event;
+  linux_record_tdep.size_iocb = I386_RECORD_SIZE_iocb;
+  linux_record_tdep.size_epoll_event = I386_RECORD_SIZE_epoll_event;
+  linux_record_tdep.size_itimerspec = I386_RECORD_SIZE_itimerspec;
+  linux_record_tdep.size_mq_attr = I386_RECORD_SIZE_mq_attr;
+  linux_record_tdep.size_siginfo = I386_RECORD_SIZE_siginfo;
+  linux_record_tdep.size_termios = I386_RECORD_SIZE_termios;
+  linux_record_tdep.size_termios2 = I386_RECORD_SIZE_termios2;
+  linux_record_tdep.size_pid_t = I386_RECORD_SIZE_pid_t;
+  linux_record_tdep.size_winsize = I386_RECORD_SIZE_winsize;
+  linux_record_tdep.size_char = I386_RECORD_SIZE_char;
+  linux_record_tdep.size_serial_struct = I386_RECORD_SIZE_serial_struct;
+  linux_record_tdep.size_serial_icounter_struct =
+    I386_RECORD_SIZE_serial_icounter_struct;
+  linux_record_tdep.size_hayes_esp_config = I386_RECORD_SIZE_hayes_esp_config;
+
+  linux_record_tdep.ioctl_TCGETS = I386_RECORD_IOCTL_TCGETS;
+  linux_record_tdep.ioctl_TCSETS = I386_RECORD_IOCTL_TCSETS;
+  linux_record_tdep.ioctl_TCSETSW = I386_RECORD_IOCTL_TCSETSW;
+  linux_record_tdep.ioctl_TCSETSF = I386_RECORD_IOCTL_TCSETSF;
+  linux_record_tdep.ioctl_TCGETA = I386_RECORD_IOCTL_TCGETA;
+  linux_record_tdep.ioctl_TCSETA = I386_RECORD_IOCTL_TCSETA;
+  linux_record_tdep.ioctl_TCSETAW = I386_RECORD_IOCTL_TCSETAW;
+  linux_record_tdep.ioctl_TCSETAF = I386_RECORD_IOCTL_TCSETAF;
+  linux_record_tdep.ioctl_TCSBRK = I386_RECORD_IOCTL_TCSBRK;
+  linux_record_tdep.ioctl_TCXONC = I386_RECORD_IOCTL_TCXONC;
+  linux_record_tdep.ioctl_TCFLSH = I386_RECORD_IOCTL_TCFLSH;
+  linux_record_tdep.ioctl_TIOCEXCL = I386_RECORD_IOCTL_TIOCEXCL;
+  linux_record_tdep.ioctl_TIOCNXCL = I386_RECORD_IOCTL_TIOCNXCL;
+  linux_record_tdep.ioctl_TIOCSCTTY = I386_RECORD_IOCTL_TIOCSCTTY;
+  linux_record_tdep.ioctl_TIOCGPGRP = I386_RECORD_IOCTL_TIOCGPGRP;
+  linux_record_tdep.ioctl_TIOCSPGRP = I386_RECORD_IOCTL_TIOCSPGRP;
+  linux_record_tdep.ioctl_TIOCOUTQ = I386_RECORD_IOCTL_TIOCOUTQ;
+  linux_record_tdep.ioctl_TIOCSTI = I386_RECORD_IOCTL_TIOCSTI;
+  linux_record_tdep.ioctl_TIOCGWINSZ = I386_RECORD_IOCTL_TIOCGWINSZ;
+  linux_record_tdep.ioctl_TIOCSWINSZ = I386_RECORD_IOCTL_TIOCSWINSZ;
+  linux_record_tdep.ioctl_TIOCMGET = I386_RECORD_IOCTL_TIOCMGET;
+  linux_record_tdep.ioctl_TIOCMBIS = I386_RECORD_IOCTL_TIOCMBIS;
+  linux_record_tdep.ioctl_TIOCMBIC = I386_RECORD_IOCTL_TIOCMBIC;
+  linux_record_tdep.ioctl_TIOCMSET = I386_RECORD_IOCTL_TIOCMSET;
+  linux_record_tdep.ioctl_TIOCGSOFTCAR = I386_RECORD_IOCTL_TIOCGSOFTCAR;
+  linux_record_tdep.ioctl_TIOCSSOFTCAR = I386_RECORD_IOCTL_TIOCSSOFTCAR;
+  linux_record_tdep.ioctl_FIONREAD = I386_RECORD_IOCTL_FIONREAD;
+  linux_record_tdep.ioctl_TIOCINQ = I386_RECORD_IOCTL_TIOCINQ;
+  linux_record_tdep.ioctl_TIOCLINUX = I386_RECORD_IOCTL_TIOCLINUX;
+  linux_record_tdep.ioctl_TIOCCONS = I386_RECORD_IOCTL_TIOCCONS;
+  linux_record_tdep.ioctl_TIOCGSERIAL = I386_RECORD_IOCTL_TIOCGSERIAL;
+  linux_record_tdep.ioctl_TIOCSSERIAL = I386_RECORD_IOCTL_TIOCSSERIAL;
+  linux_record_tdep.ioctl_TIOCPKT = I386_RECORD_IOCTL_TIOCPKT;
+  linux_record_tdep.ioctl_FIONBIO = I386_RECORD_IOCTL_FIONBIO;
+  linux_record_tdep.ioctl_TIOCNOTTY = I386_RECORD_IOCTL_TIOCNOTTY;
+  linux_record_tdep.ioctl_TIOCSETD = I386_RECORD_IOCTL_TIOCSETD;
+  linux_record_tdep.ioctl_TIOCGETD = I386_RECORD_IOCTL_TIOCGETD;
+  linux_record_tdep.ioctl_TCSBRKP = I386_RECORD_IOCTL_TCSBRKP;
+  linux_record_tdep.ioctl_TIOCTTYGSTRUCT = I386_RECORD_IOCTL_TIOCTTYGSTRUCT;
+  linux_record_tdep.ioctl_TIOCSBRK = I386_RECORD_IOCTL_TIOCSBRK;
+  linux_record_tdep.ioctl_TIOCCBRK = I386_RECORD_IOCTL_TIOCCBRK;
+  linux_record_tdep.ioctl_TIOCGSID = I386_RECORD_IOCTL_TIOCGSID;
+  linux_record_tdep.ioctl_TCGETS2 = I386_RECORD_IOCTL_TCGETS2;
+  linux_record_tdep.ioctl_TCSETS2 = I386_RECORD_IOCTL_TCSETS2;
+  linux_record_tdep.ioctl_TCSETSW2 = I386_RECORD_IOCTL_TCSETSW2;
+  linux_record_tdep.ioctl_TCSETSF2 = I386_RECORD_IOCTL_TCSETSF2;
+  linux_record_tdep.ioctl_TIOCGPTN = I386_RECORD_IOCTL_TIOCGPTN;
+  linux_record_tdep.ioctl_TIOCSPTLCK = I386_RECORD_IOCTL_TIOCSPTLCK;
+  linux_record_tdep.ioctl_FIONCLEX = I386_RECORD_IOCTL_FIONCLEX;
+  linux_record_tdep.ioctl_FIOCLEX = I386_RECORD_IOCTL_FIOCLEX;
+  linux_record_tdep.ioctl_FIOASYNC = I386_RECORD_IOCTL_FIOASYNC;
+  linux_record_tdep.ioctl_TIOCSERCONFIG = I386_RECORD_IOCTL_TIOCSERCONFIG;
+  linux_record_tdep.ioctl_TIOCSERGWILD = I386_RECORD_IOCTL_TIOCSERGWILD;
+  linux_record_tdep.ioctl_TIOCSERSWILD = I386_RECORD_IOCTL_TIOCSERSWILD;
+  linux_record_tdep.ioctl_TIOCGLCKTRMIOS = I386_RECORD_IOCTL_TIOCGLCKTRMIOS;
+  linux_record_tdep.ioctl_TIOCSLCKTRMIOS = I386_RECORD_IOCTL_TIOCSLCKTRMIOS;
+  linux_record_tdep.ioctl_TIOCSERGSTRUCT = I386_RECORD_IOCTL_TIOCSERGSTRUCT;
+  linux_record_tdep.ioctl_TIOCSERGETLSR = I386_RECORD_IOCTL_TIOCSERGETLSR;
+  linux_record_tdep.ioctl_TIOCSERGETMULTI = I386_RECORD_IOCTL_TIOCSERGETMULTI;
+  linux_record_tdep.ioctl_TIOCSERSETMULTI = I386_RECORD_IOCTL_TIOCSERSETMULTI;
+  linux_record_tdep.ioctl_TIOCMIWAIT = I386_RECORD_IOCTL_TIOCMIWAIT;
+  linux_record_tdep.ioctl_TIOCGICOUNT = I386_RECORD_IOCTL_TIOCGICOUNT;
+  linux_record_tdep.ioctl_TIOCGHAYESESP = I386_RECORD_IOCTL_TIOCGHAYESESP;
+  linux_record_tdep.ioctl_TIOCSHAYESESP = I386_RECORD_IOCTL_TIOCSHAYESESP;
+  linux_record_tdep.ioctl_FIOQSIZE = I386_RECORD_IOCTL_FIOQSIZE;
+
+  linux_record_tdep.arg1 = I386_EBX_REGNUM;
+  linux_record_tdep.arg2 = I386_ECX_REGNUM;
+  linux_record_tdep.arg3 = I386_EDX_REGNUM;
+  linux_record_tdep.arg4 = I386_ESI_REGNUM;
+  linux_record_tdep.arg5 = I386_EDI_REGNUM;
+
+  tdep->i386_intx80_record = i386_linux_intx80_sysenter_record;
+  tdep->i386_sysenter_record = i386_linux_intx80_sysenter_record;
+
   /* N_FUN symbols in shared libaries have 0 for their values and need
      to be relocated. */
   set_gdbarch_sofun_address_maybe_missing (gdbarch, 1);
index edaac21b186216c855db8a0cd0ae63be08c59179..6d6c76366ecfefe2820e0b545d2f58489131980e 100644 (file)
@@ -49,6 +49,9 @@
 #include "i386-tdep.h"
 #include "i387-tdep.h"
 
+#include "record.h"
+#include <stdint.h>
+
 /* Register names.  */
 
 static char *i386_register_names[] =
@@ -2638,146 +2641,2847 @@ i386_skip_permanent_breakpoint (struct regcache *regcache)
 }
 
 
-\f
-static struct gdbarch *
-i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
-{
-  struct gdbarch_tdep *tdep;
-  struct gdbarch *gdbarch;
-
-  /* If there is already a candidate, use it.  */
-  arches = gdbarch_list_lookup_by_info (arches, &info);
-  if (arches != NULL)
-    return arches->gdbarch;
+#define PREFIX_REPZ    0x01
+#define PREFIX_REPNZ   0x02
+#define PREFIX_LOCK    0x04
+#define PREFIX_DATA    0x08
+#define PREFIX_ADDR    0x10
 
-  /* Allocate space for the new architecture.  */
-  tdep = XCALLOC (1, struct gdbarch_tdep);
-  gdbarch = gdbarch_alloc (&info, tdep);
+/* operand size */
+enum
+{
+  OT_BYTE = 0,
+  OT_WORD,
+  OT_LONG,
+};
 
-  /* General-purpose registers.  */
-  tdep->gregset = NULL;
-  tdep->gregset_reg_offset = NULL;
-  tdep->gregset_num_regs = I386_NUM_GREGS;
-  tdep->sizeof_gregset = 0;
+/* i386 arith/logic operations */
+enum
+{
+  OP_ADDL,
+  OP_ORL,
+  OP_ADCL,
+  OP_SBBL,
+  OP_ANDL,
+  OP_SUBL,
+  OP_XORL,
+  OP_CMPL,
+};
 
-  /* Floating-point registers.  */
-  tdep->fpregset = NULL;
-  tdep->sizeof_fpregset = I387_SIZEOF_FSAVE;
+static int aflag = 1;
+static int dflag = 1;
+static int override = 0;
+static uint8_t modrm;
+static uint8_t mod, reg, rm;
+static int ot;
+static CORE_ADDR i386_record_pc;
 
-  /* The default settings include the FPU registers, the MMX registers
-     and the SSE registers.  This can be overridden for a specific ABI
-     by adjusting the members `st0_regnum', `mm0_regnum' and
-     `num_xmm_regs' of `struct gdbarch_tdep', otherwise the registers
-     will show up in the output of "info all-registers".  Ideally we
-     should try to autodetect whether they are available, such that we
-     can prevent "info all-registers" from displaying registers that
-     aren't available.
+/* Parse "modrm" part in current memory address that i386_record_pc point to.
+   Return -1 if something wrong. */
+static int
+i386_record_modrm (void)
+{
+  if (target_read_memory (i386_record_pc, &modrm, 1))
+    {
+      printf_unfiltered (_("Record: read memeory 0x%s error.\n"),
+                        paddr_nz (i386_record_pc));
+      return (-1);
+    }
+  i386_record_pc++;
+  mod = (modrm >> 6) & 3;
+  reg = (modrm >> 3) & 7;
+  rm = modrm & 7;
 
-     NOTE: kevinb/2003-07-13: ... if it's a choice between printing
-     [the SSE registers] always (even when they don't exist) or never
-     showing them to the user (even when they do exist), I prefer the
-     former over the latter.  */
+  return (0);
+}
 
-  tdep->st0_regnum = I386_ST0_REGNUM;
+/* Get the memory address that current instruction  write to and set it to
+   the argument "addr".
+   Return -1 if something wrong. */
+static int
+i386_record_lea_modrm_addr (uint32_t * addr)
+{
+  uint8_t tmpu8;
+  uint16_t tmpu16;
+  uint32_t tmpu32;
 
-  /* The MMX registers are implemented as pseudo-registers.  Put off
-     calculating the register number for %mm0 until we know the number
-     of raw registers.  */
-  tdep->mm0_regnum = 0;
+  *addr = 0;
+  if (aflag)
+    {
+      /* 32 bits */
+      int havesib = 0;
+      uint8_t scale = 0;
+      uint8_t index = 0;
+      uint8_t base = rm;
 
-  /* I386_NUM_XREGS includes %mxcsr, so substract one.  */
-  tdep->num_xmm_regs = I386_NUM_XREGS - 1;
+      if (base == 4)
+       {
+         havesib = 1;
+         if (target_read_memory (i386_record_pc, &tmpu8, 1))
+           {
+             printf_unfiltered (_("Record: read memeory 0x%s error.\n"),
+                                paddr_nz (i386_record_pc));
+             return (-1);
+           }
+         i386_record_pc++;
+         scale = (tmpu8 >> 6) & 3;
+         index = ((tmpu8 >> 3) & 7);
+         base = (tmpu8 & 7);
+       }
 
-  tdep->jb_pc_offset = -1;
-  tdep->struct_return = pcc_struct_return;
-  tdep->sigtramp_start = 0;
-  tdep->sigtramp_end = 0;
-  tdep->sigtramp_p = i386_sigtramp_p;
-  tdep->sigcontext_addr = NULL;
-  tdep->sc_reg_offset = NULL;
-  tdep->sc_pc_offset = -1;
-  tdep->sc_sp_offset = -1;
+      switch (mod)
+       {
+       case 0:
+         if ((base & 7) == 5)
+           {
+             base = 0xff;
+             if (target_read_memory (i386_record_pc, (gdb_byte *) addr, 4))
+               {
+                 printf_unfiltered (_("Record: read memeory 0x%s error.\n"),
+                                    paddr_nz (i386_record_pc));
+                 return (-1);
+               }
+             i386_record_pc += 4;
+           }
+         else
+           {
+             *addr = 0;
+           }
+         break;
+       case 1:
+         if (target_read_memory (i386_record_pc, &tmpu8, 1))
+           {
+             printf_unfiltered (_("Record: read memeory 0x%s error.\n"),
+                                paddr_nz (i386_record_pc));
+             return (-1);
+           }
+         i386_record_pc++;
+         *addr = (int8_t) tmpu8;
+         break;
+       case 2:
+         if (target_read_memory (i386_record_pc, (gdb_byte *) addr, 4))
+           {
+             printf_unfiltered (_("Record: read memeory 0x%s error.\n"),
+                                paddr_nz (i386_record_pc));
+             return (-1);
+           }
+         i386_record_pc += 4;
+         break;
+       }
 
-  /* The format used for `long double' on almost all i386 targets is
-     the i387 extended floating-point format.  In fact, of all targets
-     in the GCC 2.95 tree, only OSF/1 does it different, and insists
-     on having a `long double' that's not `long' at all.  */
-  set_gdbarch_long_double_format (gdbarch, floatformats_i387_ext);
+      if (base != 0xff)
+       {
+         regcache_raw_read (record_regcache, base, (gdb_byte *) & tmpu32);
+         *addr += tmpu32;
+       }
 
-  /* Although the i387 extended floating-point has only 80 significant
-     bits, a `long double' actually takes up 96, probably to enforce
-     alignment.  */
-  set_gdbarch_long_double_bit (gdbarch, 96);
+      /* XXX: index == 4 is always invalid */
+      if (havesib && (index != 4 || scale != 0))
+       {
+         regcache_raw_read (record_regcache, index, (gdb_byte *) & tmpu32);
+         *addr += tmpu32 << scale;
+       }
+    }
+  else
+    {
+      /* 16 bits */
+      switch (mod)
+       {
+       case 0:
+         if (rm == 6)
+           {
+             if (target_read_memory
+                 (i386_record_pc, (gdb_byte *) & tmpu16, 2))
+               {
+                 printf_unfiltered (_("Record: read memeory 0x%s error.\n"),
+                                    paddr_nz (i386_record_pc));
+                 return (-1);
+               }
+             i386_record_pc += 2;
+             *addr = (int16_t) tmpu16;
+             rm = 0;
+             goto no_rm;
+           }
+         else
+           {
+             *addr = 0;
+           }
+         break;
+       case 1:
+         if (target_read_memory (i386_record_pc, &tmpu8, 1))
+           {
+             printf_unfiltered (_("Record: read memeory 0x%s error.\n"),
+                                paddr_nz (i386_record_pc));
+             return (-1);
+           }
+         i386_record_pc++;
+         *addr = (int8_t) tmpu8;
+         break;
+       case 2:
+         if (target_read_memory (i386_record_pc, (gdb_byte *) & tmpu16, 2))
+           {
+             printf_unfiltered (_("Record: read memeory 0x%s error.\n"),
+                                paddr_nz (i386_record_pc));
+             return (-1);
+           }
+         i386_record_pc += 2;
+         *addr = (int16_t) tmpu16;
+         break;
+       }
 
-  /* The default ABI includes general-purpose registers, 
-     floating-point registers, and the SSE registers.  */
-  set_gdbarch_num_regs (gdbarch, I386_SSE_NUM_REGS);
-  set_gdbarch_register_name (gdbarch, i386_register_name);
-  set_gdbarch_register_type (gdbarch, i386_register_type);
+      switch (rm)
+       {
+       case 0:
+         regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+                            (gdb_byte *) & tmpu32);
+         *addr += tmpu32;
+         regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+                            (gdb_byte *) & tmpu32);
+         *addr += tmpu32;
+         break;
+       case 1:
+         regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+                            (gdb_byte *) & tmpu32);
+         *addr += tmpu32;
+         regcache_raw_read (record_regcache, I386_EDI_REGNUM,
+                            (gdb_byte *) & tmpu32);
+         *addr += tmpu32;
+         break;
+       case 2:
+         regcache_raw_read (record_regcache, I386_EBP_REGNUM,
+                            (gdb_byte *) & tmpu32);
+         *addr += tmpu32;
+         regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+                            (gdb_byte *) & tmpu32);
+         *addr += tmpu32;
+         break;
+       case 3:
+         regcache_raw_read (record_regcache, I386_EBP_REGNUM,
+                            (gdb_byte *) & tmpu32);
+         *addr += tmpu32;
+         regcache_raw_read (record_regcache, I386_EDI_REGNUM,
+                            (gdb_byte *) & tmpu32);
+         *addr += tmpu32;
+         break;
+       case 4:
+         regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+                            (gdb_byte *) & tmpu32);
+         *addr += tmpu32;
+         break;
+       case 5:
+         regcache_raw_read (record_regcache, I386_EDI_REGNUM,
+                            (gdb_byte *) & tmpu32);
+         *addr += tmpu32;
+         break;
+       case 6:
+         regcache_raw_read (record_regcache, I386_EBP_REGNUM,
+                            (gdb_byte *) & tmpu32);
+         *addr += tmpu32;
+         break;
+       case 7:
+         regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+                            (gdb_byte *) & tmpu32);
+         *addr += tmpu32;
+         break;
+       }
+      *addr &= 0xffff;
+    }
 
-  /* Register numbers of various important registers.  */
-  set_gdbarch_sp_regnum (gdbarch, I386_ESP_REGNUM); /* %esp */
-  set_gdbarch_pc_regnum (gdbarch, I386_EIP_REGNUM); /* %eip */
-  set_gdbarch_ps_regnum (gdbarch, I386_EFLAGS_REGNUM); /* %eflags */
-  set_gdbarch_fp0_regnum (gdbarch, I386_ST0_REGNUM); /* %st(0) */
+no_rm:
+  return (0);
+}
 
-  /* NOTE: kettenis/20040418: GCC does have two possible register
-     numbering schemes on the i386: dbx and SVR4.  These schemes
-     differ in how they number %ebp, %esp, %eflags, and the
-     floating-point registers, and are implemented by the arrays
-     dbx_register_map[] and svr4_dbx_register_map in
-     gcc/config/i386.c.  GCC also defines a third numbering scheme in
-     gcc/config/i386.c, which it designates as the "default" register
-     map used in 64bit mode.  This last register numbering scheme is
-     implemented in dbx64_register_map, and is used for AMD64; see
-     amd64-tdep.c.
+/* Record the value of the memory that willbe changed in current instruction
+   to "record_arch_list".
+   Return -1 if something wrong. */
+static int
+i386_record_lea_modrm (void)
+{
+  uint32_t addr;
 
-     Currently, each GCC i386 target always uses the same register
-     numbering scheme across all its supported debugging formats
-     i.e. SDB (COFF), stabs and DWARF 2.  This is because
-     gcc/sdbout.c, gcc/dbxout.c and gcc/dwarf2out.c all use the
-     DBX_REGISTER_NUMBER macro which is defined by each target's
-     respective config header in a manner independent of the requested
-     output debugging format.
+  if (override)
+    {
+      if (record_debug)
+       printf_unfiltered (_
+                          ("Record: Record ignore the memory change of instruction in address 0x%s because it can't get the value of the segment register.\n"),
+                          paddr_nz (i386_record_pc));
+      return (0);
+    }
 
-     This does not match the arrangement below, which presumes that
-     the SDB and stabs numbering schemes differ from the DWARF and
-     DWARF 2 ones.  The reason for this arrangement is that it is
-     likely to get the numbering scheme for the target's
-     default/native debug format right.  For targets where GCC is the
-     native compiler (FreeBSD, NetBSD, OpenBSD, GNU/Linux) or for
-     targets where the native toolchain uses a different numbering
-     scheme for a particular debug format (stabs-in-ELF on Solaris)
-     the defaults below will have to be overridden, like
-     i386_elf_init_abi() does.  */
+  if (i386_record_lea_modrm_addr (&addr))
+    {
+      return (-1);
+    }
 
-  /* Use the dbx register numbering scheme for stabs and COFF.  */
-  set_gdbarch_stab_reg_to_regnum (gdbarch, i386_dbx_reg_to_regnum);
-  set_gdbarch_sdb_reg_to_regnum (gdbarch, i386_dbx_reg_to_regnum);
+  if (record_arch_list_add_mem (addr, 1 << ot))
+    {
+      return (-1);
+    }
 
-  /* Use the SVR4 register numbering scheme for DWARF 2.  */
-  set_gdbarch_dwarf2_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
+  return (0);
+}
 
-  /* We don't set gdbarch_stab_reg_to_regnum, since ECOFF doesn't seem to
-     be in use on any of the supported i386 targets.  */
+/* Parse the current instruction and record the values of the registers and
+   memory that will be changed in current instruction to "record_arch_list".
+   Return -1 if something wrong. */
+static int
+i386_process_record (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  int prefixes = 0;
+  uint8_t tmpu8;
+  uint16_t tmpu16;
+  uint32_t tmpu32;
+  uint32_t opcode;
+
+  i386_record_pc = addr;
+  aflag = 1;
+  dflag = 1;
+  override = 0;
+
+  if (record_debug > 1)
+    {
+      fprintf_unfiltered (gdb_stdlog, "Record: i386_record pc = 0x%s\n",
+                         paddr_nz (i386_record_pc));
+    }
 
-  set_gdbarch_print_float_info (gdbarch, i387_print_float_info);
+  /* prefixes */
+  while (1)
+    {
+      if (target_read_memory (i386_record_pc, &tmpu8, 1))
+       {
+         printf_unfiltered (_("Record: read memeory 0x%s error.\n"),
+                            paddr_nz (i386_record_pc));
+         return (-1);
+       }
+      i386_record_pc++;
+      switch (tmpu8)
+       {
+       case 0xf3:
+         prefixes |= PREFIX_REPZ;
+         break;
+       case 0xf2:
+         prefixes |= PREFIX_REPNZ;
+         break;
+       case 0xf0:
+         prefixes |= PREFIX_LOCK;
+         break;
+       case 0x2e:
+         override = I386_CS_REGNUM;
+         break;
+       case 0x36:
+         override = I386_SS_REGNUM;
+         break;
+       case 0x3e:
+         override = I386_DS_REGNUM;
+         break;
+       case 0x26:
+         override = I386_ES_REGNUM;
+         break;
+       case 0x64:
+         override = I386_FS_REGNUM;
+         break;
+       case 0x65:
+         override = I386_GS_REGNUM;
+         break;
+       case 0x66:
+         prefixes |= PREFIX_DATA;
+         break;
+       case 0x67:
+         prefixes |= PREFIX_ADDR;
+         break;
+       default:
+         goto out_prefixes;
+         break;
+       }
+    }
+out_prefixes:
+  if (prefixes & PREFIX_DATA)
+    {
+      dflag ^= 1;
+    }
+  if (prefixes & PREFIX_ADDR)
+    {
+      aflag ^= 1;
+    }
 
-  set_gdbarch_get_longjmp_target (gdbarch, i386_get_longjmp_target);
+  /* now check op code */
+  opcode = (uint32_t) tmpu8;
+reswitch:
+  switch (opcode)
+    {
+    case 0x0f:
+      if (target_read_memory (i386_record_pc, &tmpu8, 1))
+       {
+         printf_unfiltered (_("Record: read memeory 0x%s error.\n"),
+                            paddr_nz (i386_record_pc));
+         return (-1);
+       }
+      i386_record_pc++;
+      opcode = (uint16_t) tmpu8 | 0x0f00;
+      goto reswitch;
+      break;
 
-  /* Call dummy code.  */
-  set_gdbarch_push_dummy_call (gdbarch, i386_push_dummy_call);
+      /* arith & logic */
+    case 0x00 ... 0x05:
+    case 0x08 ... 0x0d:
+    case 0x10 ... 0x15:
+    case 0x18 ... 0x1d:
+    case 0x20 ... 0x25:
+    case 0x28 ... 0x2d:
+    case 0x30 ... 0x35:
+    case 0x38 ... 0x3d:
+      if (((opcode >> 3) & 7) != OP_CMPL)
+       {
+         if ((opcode & 1) == 0)
+           {
+             ot = OT_BYTE;
+           }
+         else
+           {
+             ot = dflag + OT_WORD;
+           }
 
-  set_gdbarch_convert_register_p (gdbarch, i386_convert_register_p);
-  set_gdbarch_register_to_value (gdbarch,  i386_register_to_value);
-  set_gdbarch_value_to_register (gdbarch, i386_value_to_register);
+         switch ((opcode >> 1) & 3)
+           {
+             /* OP Ev, Gv */
+           case 0:
+             if (i386_record_modrm ())
+               {
+                 return (-1);
+               }
+             if (mod != 3)
+               {
+                 if (i386_record_lea_modrm ())
+                   {
+                     return (-1);
+                   }
+               }
+             else
+               {
+                 if (ot == OT_BYTE)
+                   {
+                     rm &= 0x3;
+                   }
+                 if (record_arch_list_add_reg (rm))
+                   {
+                     return (-1);
+                   }
+               }
+             break;
+             /* OP Gv, Ev */
+           case 1:
+             if (i386_record_modrm ())
+               {
+                 return (-1);
+               }
+             if (ot == OT_BYTE)
+               {
+                 reg &= 0x3;
+               }
+             if (record_arch_list_add_reg (reg))
+               {
+                 return (-1);
+               }
+             break;
+             /* OP A, Iv */
+           case 2:
+             if (record_arch_list_add_reg (I386_EAX_REGNUM))
+               {
+                 return (-1);
+               }
+             break;
+           }
+       }
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
 
-  set_gdbarch_return_value (gdbarch, i386_return_value);
+      /* GRP1 */
+    case 0x80 ... 0x83:
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
 
-  set_gdbarch_skip_prologue (gdbarch, i386_skip_prologue);
+      if (reg != OP_CMPL)
+       {
+         if ((opcode & 1) == 0)
+           {
+             ot = OT_BYTE;
+           }
+         else
+           {
+             ot = dflag + OT_WORD;
+           }
 
-  /* Stack grows downward.  */
-  set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+         if (mod != 3)
+           {
+             if (i386_record_lea_modrm ())
+               {
+                 return (-1);
+               }
+           }
+         else
+           {
+             if (record_arch_list_add_reg (rm))
+               {
+                 return (-1);
+               }
+           }
+       }
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* inv */
+    case 0x40 ... 0x47:
+      /* dec */
+    case 0x48 ... 0x4f:
+      if (record_arch_list_add_reg (opcode & 7))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* GRP3 */
+    case 0xf6:
+    case 0xf7:
+      if ((opcode & 1) == 0)
+       {
+         ot = OT_BYTE;
+       }
+      else
+       {
+         ot = dflag + OT_WORD;
+       }
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+
+      switch (reg)
+       {
+         /* test */
+       case 0:
+         if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+           {
+             return (-1);
+           }
+         break;
+         /* not */
+       case 2:
+         if (mod != 3)
+           {
+             if (i386_record_lea_modrm ())
+               {
+                 return (-1);
+               }
+           }
+         else
+           {
+             if (ot == OT_BYTE)
+               {
+                 rm &= 0x3;
+               }
+             if (record_arch_list_add_reg (rm))
+               {
+                 return (-1);
+               }
+           }
+         break;
+         /* neg */
+       case 3:
+         if (mod != 3)
+           {
+             if (i386_record_lea_modrm ())
+               {
+                 return (-1);
+               }
+           }
+         else
+           {
+             if (ot == OT_BYTE)
+               {
+                 rm &= 0x3;
+               }
+             if (record_arch_list_add_reg (rm))
+               {
+                 return (-1);
+               }
+           }
+         if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+           {
+             return (-1);
+           }
+         break;
+         /* mul */
+       case 4:
+         /* imul */
+       case 5:
+         /* div */
+       case 6:
+         /* idiv */
+       case 7:
+         if (record_arch_list_add_reg (I386_EAX_REGNUM))
+           {
+             return (-1);
+           }
+         if (ot != OT_BYTE)
+           {
+             if (record_arch_list_add_reg (I386_EDX_REGNUM))
+               {
+                 return (-1);
+               }
+           }
+         if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+           {
+             return (-1);
+           }
+         break;
+       default:
+         i386_record_pc -= 2;
+         opcode = opcode << 8 | modrm;
+         goto no_support;
+         break;
+       }
+      break;
+
+      /* GRP4 */
+    case 0xfe:
+      /* GRP5 */
+    case 0xff:
+      if ((opcode & 1) == 0)
+       {
+         ot = OT_BYTE;
+       }
+      else
+       {
+         ot = dflag + OT_WORD;
+       }
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      if (reg >= 2 && opcode == 0xfe)
+       {
+         i386_record_pc -= 2;
+         opcode = opcode << 8 | modrm;
+         goto no_support;
+       }
+
+      switch (reg)
+       {
+         /* inc */
+       case 0:
+         /* dec */
+       case 1:
+         if (mod != 3)
+           {
+             if (i386_record_lea_modrm ())
+               {
+                 return (-1);
+               }
+           }
+         else
+           {
+             if (ot == OT_BYTE)
+               {
+                 rm &= 0x3;
+               }
+             if (record_arch_list_add_reg (rm))
+               {
+                 return (-1);
+               }
+           }
+         if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+           {
+             return (-1);
+           }
+         break;
+         /* call */
+       case 2:
+         /* push */
+       case 6:
+         if (record_arch_list_add_reg (I386_ESP_REGNUM))
+           {
+             return (-1);
+           }
+         regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+                            (gdb_byte *) & tmpu32);
+         if (record_arch_list_add_mem
+             ((CORE_ADDR) tmpu32 - (1 << (dflag + 1)), (1 << (dflag + 1))))
+           {
+             return (-1);
+           }
+         break;
+         /* lcall */
+       case 3:
+         if (record_arch_list_add_reg (I386_ESP_REGNUM))
+           {
+             return (-1);
+           }
+         if (record_arch_list_add_reg (I386_CS_REGNUM))
+           {
+             return (-1);
+           }
+         regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+                            (gdb_byte *) & tmpu32);
+         if (record_arch_list_add_mem
+             ((CORE_ADDR) tmpu32 - (1 << (dflag + 2)), (1 << (dflag + 2))))
+           {
+             return (-1);
+           }
+         break;
+         /* jmp */
+       case 4:
+         /* ljmp */
+       case 5:
+         break;
+       default:
+         i386_record_pc -= 2;
+         opcode = opcode << 8 | modrm;
+         goto no_support;
+         break;
+       }
+      break;
+
+      /* test */
+    case 0x84:
+    case 0x85:
+    case 0xa8:
+    case 0xa9:
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* CWDE/CBW */
+    case 0x98:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* CDQ/CWD */
+    case 0x99:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_EDX_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* imul */
+    case 0x0faf:
+    case 0x69:
+    case 0x6b:
+      ot = dflag + OT_WORD;
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      if (ot == OT_BYTE)
+       {
+         reg &= 0x3;
+       }
+      if (record_arch_list_add_reg (reg))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* xadd */
+    case 0x0fc0:
+    case 0x0fc1:
+      if ((opcode & 1) == 0)
+       {
+         ot = OT_BYTE;
+       }
+      else
+       {
+         ot = dflag + OT_WORD;
+       }
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      if (mod == 3)
+       {
+         if (ot == OT_BYTE)
+           {
+             reg &= 0x3;
+           }
+         if (record_arch_list_add_reg (reg))
+           {
+             return (-1);
+           }
+         if (ot == OT_BYTE)
+           {
+             rm &= 0x3;
+           }
+         if (record_arch_list_add_reg (rm))
+           {
+             return (-1);
+           }
+       }
+      else
+       {
+         if (i386_record_lea_modrm ())
+           {
+             return (-1);
+           }
+         if (ot == OT_BYTE)
+           {
+             reg &= 0x3;
+           }
+         if (record_arch_list_add_reg (reg))
+           {
+             return (-1);
+           }
+       }
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* cmpxchg */
+    case 0x0fb0:
+    case 0x0fb1:
+      if ((opcode & 1) == 0)
+       {
+         ot = OT_BYTE;
+       }
+      else
+       {
+         ot = dflag + OT_WORD;
+       }
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      if (mod == 3)
+       {
+         if (record_arch_list_add_reg (I386_EAX_REGNUM))
+           {
+             return (-1);
+           }
+         if (ot == OT_BYTE)
+           {
+             reg &= 0x3;
+           }
+         if (record_arch_list_add_reg (reg))
+           {
+             return (-1);
+           }
+       }
+      else
+       {
+         if (record_arch_list_add_reg (I386_EAX_REGNUM))
+           {
+             return (-1);
+           }
+         if (i386_record_lea_modrm ())
+           {
+             return (-1);
+           }
+       }
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* cmpxchg8b */
+    case 0x0fc7:
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      if (mod == 3)
+       {
+         i386_record_pc -= 2;
+         opcode = opcode << 8 | modrm;
+         goto no_support;
+       }
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_EDX_REGNUM))
+       {
+         return (-1);
+       }
+      if (i386_record_lea_modrm ())
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* push */
+    case 0x50 ... 0x57:
+    case 0x68:
+    case 0x6a:
+      /* push es */
+    case 0x06:
+      /* push cs */
+    case 0x0e:
+      /* push ss */
+    case 0x16:
+      /* push ds */
+    case 0x1e:
+      /* push fs */
+    case 0x0fa0:
+      /* push gs */
+    case 0x0fa8:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+       {
+         return (-1);
+       }
+      regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+                        (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem
+         ((CORE_ADDR) tmpu32 - (1 << (dflag + 1)), (1 << (dflag + 1))))
+       {
+         return (-1);
+       }
+      break;
+
+      /* pop */
+    case 0x58 ... 0x5f:
+      ot = dflag + OT_WORD;
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+       {
+         return (-1);
+       }
+      if (ot == OT_BYTE)
+       {
+         opcode &= 0x3;
+       }
+      if (record_arch_list_add_reg (opcode & 0x7))
+       {
+         return (-1);
+       }
+      break;
+
+      /* pusha */
+    case 0x60:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+       {
+         return (-1);
+       }
+      regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+                        (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem
+         ((CORE_ADDR) tmpu32 - (1 << (dflag + 4)), (1 << (dflag + 4))))
+       {
+         return (-1);
+       }
+      break;
+
+      /* popa */
+    case 0x61:
+      for (tmpu8 = I386_EAX_REGNUM; tmpu8 <= I386_EDI_REGNUM; tmpu8++)
+       {
+         if (record_arch_list_add_reg (tmpu8))
+           {
+             return (-1);
+           }
+       }
+      break;
+
+      /* pop */
+    case 0x8f:
+      ot = dflag + OT_WORD;
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      if (mod == 3)
+       {
+         if (record_arch_list_add_reg (rm))
+           {
+             return (-1);
+           }
+       }
+      else
+       {
+         if (i386_record_lea_modrm ())
+           {
+             return (-1);
+           }
+       }
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* enter */
+    case 0xc8:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_EBP_REGNUM))
+       {
+         return (-1);
+       }
+      regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+                        (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem
+         ((CORE_ADDR) tmpu32 - (1 << (dflag + 1)), (1 << (dflag + 1))))
+       {
+         return (-1);
+       }
+      break;
+
+      /* leave */
+    case 0xc9:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_EBP_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* pop es */
+    case 0x07:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_ES_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* pop ss */
+    case 0x17:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_SS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* pop ds */
+    case 0x1f:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_DS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* pop fs */
+    case 0x0fa1:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_FS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* pop gs */
+    case 0x0fa9:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_GS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* mov */
+    case 0x88:
+    case 0x89:
+    case 0xc6:
+    case 0xc7:
+      if ((opcode & 1) == 0)
+       {
+         ot = OT_BYTE;
+       }
+      else
+       {
+         ot = dflag + OT_WORD;
+       }
+
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+
+      if (mod != 3)
+       {
+         if (i386_record_lea_modrm ())
+           {
+             return (-1);
+           }
+       }
+      else
+       {
+         if (ot == OT_BYTE)
+           {
+             rm &= 0x3;
+           }
+         if (record_arch_list_add_reg (rm))
+           {
+             return (-1);
+           }
+       }
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+      /* mov */
+    case 0x8a:
+    case 0x8b:
+      if ((opcode & 1) == 0)
+       {
+         ot = OT_BYTE;
+       }
+      else
+       {
+         ot = dflag + OT_WORD;
+       }
+
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+
+      if (ot == OT_BYTE)
+       {
+         reg &= 0x3;
+       }
+      if (record_arch_list_add_reg (reg))
+       {
+         return (-1);
+       }
+
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* mov seg */
+    case 0x8e:
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+
+      switch (reg)
+       {
+       case 0:
+         tmpu8 = I386_ES_REGNUM;
+         break;
+       case 2:
+         tmpu8 = I386_SS_REGNUM;
+         break;
+       case 3:
+         tmpu8 = I386_DS_REGNUM;
+         break;
+       case 4:
+         tmpu8 = I386_FS_REGNUM;
+         break;
+       case 5:
+         tmpu8 = I386_GS_REGNUM;
+         break;
+       default:
+         i386_record_pc -= 2;
+         opcode = opcode << 8 | modrm;
+         goto no_support;
+         break;
+       }
+      if (record_arch_list_add_reg (tmpu8))
+       {
+         return (-1);
+       }
+
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* mov seg */
+    case 0x8c:
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      if (reg > 5)
+       {
+         i386_record_pc -= 2;
+         opcode = opcode << 8 | modrm;
+         goto no_support;
+       }
+
+      if (mod == 3)
+       {
+         if (record_arch_list_add_reg (rm))
+           {
+             return (-1);
+           }
+       }
+      else
+       {
+         ot = OT_WORD;
+         if (i386_record_lea_modrm ())
+           {
+             return (-1);
+           }
+       }
+
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* movzbS */
+    case 0x0fb6:
+      /* movzwS */
+    case 0x0fb7:
+      /* movsbS */
+    case 0x0fbe:
+      /* movswS */
+    case 0x0fbf:
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (reg))
+       {
+         return (-1);
+       }
+      break;
+
+      /* lea */
+    case 0x8d:
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      if (mod == 3)
+       {
+         i386_record_pc -= 2;
+         opcode = opcode << 8 | modrm;
+         goto no_support;
+       }
+
+      ot = dflag;
+      if (ot == OT_BYTE)
+       {
+         reg &= 0x3;
+       }
+      if (record_arch_list_add_reg (reg))
+       {
+         return (-1);
+       }
+      break;
+
+      /* mov EAX */
+    case 0xa0:
+    case 0xa1:
+      /* xlat */
+    case 0xd7:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* mov EAX */
+    case 0xa2:
+    case 0xa3:
+      {
+       uint32_t addr;
+
+       if (override)
+         {
+           if (record_debug)
+             printf_unfiltered (_
+                                ("Record: Record ignore the memory change of instruction in address 0x%s because it can't get the value of the segment register.\n"),
+                                paddr_nz (i386_record_pc));
+         }
+       else
+         {
+           if ((opcode & 1) == 0)
+             {
+               ot = OT_BYTE;
+             }
+           else
+             {
+               ot = dflag + OT_WORD;
+             }
+           if (aflag)
+             {
+               if (target_read_memory
+                   (i386_record_pc, (gdb_byte *) & addr, 4))
+                 {
+                   printf_unfiltered (_
+                                      ("Record: read memeory 0x%s error.\n"),
+                                      paddr_nz (i386_record_pc));
+                   return (-1);
+                 }
+               i386_record_pc += 4;
+             }
+           else
+             {
+               if (target_read_memory
+                   (i386_record_pc, (gdb_byte *) & tmpu16, 4))
+                 {
+                   printf_unfiltered (_
+                                      ("Record: read memeory 0x%s error.\n"),
+                                      paddr_nz (i386_record_pc));
+                   return (-1);
+                 }
+               i386_record_pc += 2;
+               addr = tmpu16;
+             }
+           if (record_arch_list_add_mem (addr, 1 << ot))
+             {
+               return (-1);
+             }
+         }
+      }
+      break;
+
+      /* mov R, Ib */
+    case 0xb0 ... 0xb7:
+      if (record_arch_list_add_reg ((opcode & 0x7) & 0x3))
+       {
+         return (-1);
+       }
+      break;
+
+      /* mov R, Iv */
+    case 0xb8 ... 0xbf:
+      if (record_arch_list_add_reg (opcode & 0x7))
+       {
+         return (-1);
+       }
+      break;
+
+      /* xchg R, EAX */
+    case 0x91 ... 0x97:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (opcode & 0x7))
+       {
+         return (-1);
+       }
+      break;
+
+      /* xchg Ev, Gv */
+    case 0x86:
+    case 0x87:
+      if ((opcode & 1) == 0)
+       {
+         ot = OT_BYTE;
+       }
+      else
+       {
+         ot = dflag + OT_WORD;
+       }
+
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+
+      if (mod == 3)
+       {
+         if (ot == OT_BYTE)
+           {
+             rm &= 0x3;
+           }
+         if (record_arch_list_add_reg (rm))
+           {
+             return (-1);
+           }
+       }
+      else
+       {
+         if (i386_record_lea_modrm ())
+           {
+             return (-1);
+           }
+       }
+
+      if (ot == OT_BYTE)
+       {
+         reg &= 0x3;
+       }
+      if (record_arch_list_add_reg (reg))
+       {
+         return (-1);
+       }
+      break;
+
+      /* les Gv */
+    case 0xc4:
+      /* lds Gv */
+    case 0xc5:
+      /* lss Gv */
+    case 0x0fb2:
+      /* lfs Gv */
+    case 0x0fb4:
+      /* lgs Gv */
+    case 0x0fb5:
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      if (mod == 3)
+       {
+         if (opcode > 0xff)
+           {
+             i386_record_pc -= 3;
+           }
+         else
+           {
+             i386_record_pc -= 2;
+           }
+         opcode = opcode << 8 | modrm;
+         goto no_support;
+       }
+
+      switch (opcode)
+       {
+         /* les Gv */
+       case 0xc4:
+         tmpu8 = I386_ES_REGNUM;
+         break;
+         /* lds Gv */
+       case 0xc5:
+         tmpu8 = I386_DS_REGNUM;
+         break;
+         /* lss Gv */
+       case 0x0fb2:
+         tmpu8 = I386_SS_REGNUM;
+         break;
+         /* lfs Gv */
+       case 0x0fb4:
+         tmpu8 = I386_FS_REGNUM;
+         break;
+         /* lgs Gv */
+       case 0x0fb5:
+         tmpu8 = I386_GS_REGNUM;
+         break;
+       }
+      if (record_arch_list_add_reg (tmpu8))
+       {
+         return (-1);
+       }
+
+      if (record_arch_list_add_reg (reg))
+       {
+         return (-1);
+       }
+      break;
+
+      /* shifts */
+    case 0xc0:
+    case 0xc1:
+    case 0xd0:
+    case 0xd1:
+    case 0xd2:
+    case 0xd3:
+      if ((opcode & 1) == 0)
+       {
+         ot = OT_BYTE;
+       }
+      else
+       {
+         ot = dflag + OT_WORD;
+       }
+
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+
+      if (mod != 3 && (opcode == 0xd2 || opcode == 0xd3))
+       {
+         if (i386_record_lea_modrm ())
+           {
+             return (-1);
+           }
+       }
+      else
+       {
+         if (ot == OT_BYTE)
+           {
+             rm &= 0x3;
+           }
+         if (record_arch_list_add_reg (rm))
+           {
+             return (-1);
+           }
+       }
+
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+    case 0x0fa4:
+    case 0x0fa5:
+    case 0x0fac:
+    case 0x0fad:
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      if (mod == 3)
+       {
+         if (record_arch_list_add_reg (rm))
+           {
+             return (-1);
+           }
+       }
+      else
+       {
+         if (i386_record_lea_modrm ())
+           {
+             return (-1);
+           }
+       }
+      break;
+
+      /* floats */
+      /* It just record the memory change of instrcution. */
+    case 0xd8 ... 0xdf:
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      reg |= ((opcode & 7) << 3);
+      if (mod != 3)
+       {
+         /* memory */
+         uint32_t addr;
+
+         if (i386_record_lea_modrm_addr (&addr))
+           {
+             return (-1);
+           }
+         switch (reg)
+           {
+           case 0x00 ... 0x07:
+           case 0x10 ... 0x17:
+           case 0x20 ... 0x27:
+           case 0x30 ... 0x37:
+             break;
+           case 0x08:
+           case 0x0a:
+           case 0x0b:
+           case 0x18 ... 0x1b:
+           case 0x28 ... 0x2b:
+           case 0x38 ... 0x3b:
+             switch (reg & 7)
+               {
+               case 0:
+                 break;
+               case 1:
+                 switch (reg >> 4)
+                   {
+                   case 0:
+                     if (record_arch_list_add_mem (addr, 4))
+                       {
+                         return (-1);
+                       }
+                     break;
+                   case 2:
+                     if (record_arch_list_add_mem (addr, 8))
+                       {
+                         return (-1);
+                       }
+                     break;
+                   case 3:
+                   default:
+                     if (record_arch_list_add_mem (addr, 2))
+                       {
+                         return (-1);
+                       }
+                     break;
+                   }
+                 break;
+               default:
+                 switch (reg >> 4)
+                   {
+                   case 0:
+                   case 1:
+                     if (record_arch_list_add_mem (addr, 4))
+                       {
+                         return (-1);
+                       }
+                     break;
+                   case 2:
+                     if (record_arch_list_add_mem (addr, 8))
+                       {
+                         return (-1);
+                       }
+                     break;
+                   case 3:
+                   default:
+                     if (record_arch_list_add_mem (addr, 2))
+                       {
+                         return (-1);
+                       }
+                     break;
+                   }
+                 break;
+               }
+             break;
+           case 0x0c:
+           case 0x0d:
+           case 0x1d:
+           case 0x2c:
+           case 0x3c:
+           case 0x3d:
+             break;
+           case 0x0e:
+             if (dflag)
+               {
+                 if (record_arch_list_add_mem (addr, 28))
+                   {
+                     return (-1);
+                   }
+               }
+             else
+               {
+                 if (record_arch_list_add_mem (addr, 14))
+                   {
+                     return (-1);
+                   }
+               }
+             break;
+           case 0x0f:
+           case 0x2f:
+             if (record_arch_list_add_mem (addr, 2))
+               {
+                 return (-1);
+               }
+             break;
+           case 0x1f:
+           case 0x3e:
+             if (record_arch_list_add_mem (addr, 10))
+               {
+                 return (-1);
+               }
+             break;
+           case 0x2e:
+             if (dflag)
+               {
+                 if (record_arch_list_add_mem (addr, 28))
+                   {
+                     return (-1);
+                   }
+                 addr += 28;
+               }
+             else
+               {
+                 if (record_arch_list_add_mem (addr, 14))
+                   {
+                     return (-1);
+                   }
+                 addr += 14;
+               }
+             if (record_arch_list_add_mem (addr, 80))
+               {
+                 return (-1);
+               }
+             break;
+           case 0x3f:
+             if (record_arch_list_add_mem (addr, 8))
+               {
+                 return (-1);
+               }
+             break;
+           default:
+             i386_record_pc -= 2;
+             opcode = opcode << 8 | modrm;
+             goto no_support;
+             break;
+           }
+       }
+      break;
+
+      /* string ops */
+      /* movsS */
+    case 0xa4:
+    case 0xa5:
+      /* stosS */
+    case 0xaa:
+    case 0xab:
+      /* insS */
+    case 0x6c:
+    case 0x6d:
+      {
+       uint32_t addr;
+
+       if ((opcode & 1) == 0)
+         {
+           ot = OT_BYTE;
+         }
+       else
+         {
+           ot = dflag + OT_WORD;
+         }
+       if (opcode == 0xa4 || opcode == 0xa5)
+         {
+           if (record_arch_list_add_reg (I386_ESI_REGNUM))
+             {
+               return (-1);
+             }
+         }
+       if (record_arch_list_add_reg (I386_EDI_REGNUM))
+         {
+           return (-1);
+         }
+
+       regcache_raw_read (record_regcache, I386_EDI_REGNUM,
+                          (gdb_byte *) & addr);
+       if (!aflag)
+         {
+           addr &= 0xffff;
+           /* addr += ((uint32_t)read_register (I386_ES_REGNUM)) << 4; */
+            if (record_debug)
+             printf_unfiltered (_
+                                ("Record: Record ignore the memory change of instruction in address 0x%s because it can't get the value of the segment register.\n"),
+                          paddr_nz (i386_record_pc));
+         }
+
+       if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
+         {
+           uint32_t count;
+
+           regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+                              (gdb_byte *) & count);
+           if (!aflag)
+             {
+               count &= 0xffff;
+             }
+
+           regcache_raw_read (record_regcache, I386_EFLAGS_REGNUM,
+                              (gdb_byte *) & tmpu32);
+           if ((tmpu32 >> 10) & 0x1)
+             {
+               addr -= (count - 1) * (1 << ot);
+             }
+
+           if (aflag)
+             {
+               if (record_arch_list_add_mem (addr, count * (1 << ot)))
+                 {
+                   return (-1);
+                 }
+             }
+
+           if (record_arch_list_add_reg (I386_ECX_REGNUM))
+             {
+               return (-1);
+             }
+         }
+       else
+         {
+           if (aflag)
+             {
+               if (record_arch_list_add_mem (addr, 1 << ot))
+                 {
+                   return (-1);
+                 }
+             }
+         }
+      }
+      break;
+
+      /* lodsS */
+    case 0xac:
+    case 0xad:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_ESI_REGNUM))
+       {
+         return (-1);
+       }
+      if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
+       {
+         if (record_arch_list_add_reg (I386_ECX_REGNUM))
+           {
+             return (-1);
+           }
+       }
+      break;
+
+      /* outsS */
+    case 0x6e:
+    case 0x6f:
+      if (record_arch_list_add_reg (I386_ESI_REGNUM))
+       {
+         return (-1);
+       }
+      if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
+       {
+         if (record_arch_list_add_reg (I386_ECX_REGNUM))
+           {
+             return (-1);
+           }
+       }
+      break;
+
+      /* scasS */
+    case 0xae:
+    case 0xaf:
+      if (record_arch_list_add_reg (I386_EDI_REGNUM))
+       {
+         return (-1);
+       }
+      if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
+       {
+         if (record_arch_list_add_reg (I386_ECX_REGNUM))
+           {
+             return (-1);
+           }
+       }
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* cmpsS */
+    case 0xa6:
+    case 0xa7:
+      if (record_arch_list_add_reg (I386_EDI_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_ESI_REGNUM))
+       {
+         return (-1);
+       }
+      if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
+       {
+         if (record_arch_list_add_reg (I386_ECX_REGNUM))
+           {
+             return (-1);
+           }
+       }
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* port I/O */
+    case 0xe4:
+    case 0xe5:
+    case 0xec:
+    case 0xed:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+    case 0xe6:
+    case 0xe7:
+    case 0xee:
+    case 0xef:
+      break;
+
+      /* control */
+      /* ret im */
+    case 0xc2:
+      /* ret */
+    case 0xc3:
+      /* lret im */
+    case 0xca:
+      /* lret */
+    case 0xcb:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_CS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* iret */
+    case 0xcf:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_CS_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* call im */
+    case 0xe8:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+       {
+         return (-1);
+       }
+      regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+                        (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem
+         ((CORE_ADDR) tmpu32 - (1 << (dflag + 1)), (1 << (dflag + 1))))
+       {
+         return (-1);
+       }
+      break;
+
+      /* lcall im */
+    case 0x9a:
+      if (record_arch_list_add_reg (I386_CS_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+       {
+         return (-1);
+       }
+      regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+                        (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem
+         ((CORE_ADDR) tmpu32 - (1 << (dflag + 2)), (1 << (dflag + 2))))
+       {
+         return (-1);
+       }
+      break;
+
+      /* jmp im */
+    case 0xe9:
+      /* ljmp im */
+    case 0xea:
+      /* jmp Jb */
+    case 0xeb:
+      /* jcc Jb */
+    case 0x70 ... 0x7f:
+      /* jcc Jv */
+    case 0x0f80 ... 0x0f8f:
+      break;
+
+      /* setcc Gv */
+    case 0x0f90 ... 0x0f9f:
+      ot = OT_BYTE;
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      if (mod == 3)
+       {
+         if (record_arch_list_add_reg (rm & 0x3))
+           {
+             return (-1);
+           }
+       }
+      else
+       {
+         if (i386_record_lea_modrm ())
+           {
+             return (-1);
+           }
+       }
+      break;
+
+      /* cmov Gv, Ev */
+    case 0x0f40 ... 0x0f4f:
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      if (dflag == OT_BYTE)
+       {
+         reg &= 0x3;
+       }
+      if (record_arch_list_add_reg (reg & 0x3))
+       {
+         return (-1);
+       }
+      break;
+
+      /* flags */
+      /* pushf */
+    case 0x9c:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+       {
+         return (-1);
+       }
+      regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+                        (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem
+         ((CORE_ADDR) tmpu32 - (1 << (dflag + 1)), (1 << (dflag + 1))))
+       {
+         return (-1);
+       }
+      break;
+
+      /* popf */
+    case 0x9d:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* sahf */
+    case 0x9e:
+      /* cmc */
+    case 0xf5:
+      /* clc */
+    case 0xf8:
+      /* stc */
+    case 0xf9:
+      /* cld */
+    case 0xfc:
+      /* std */
+    case 0xfd:
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* lahf */
+    case 0x9f:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* bit operations */
+      /* bt/bts/btr/btc Gv, im */
+    case 0x0fba:
+      /* bts */
+    case 0x0fab:
+      /* btr */
+    case 0x0fb3:
+      /* btc */
+    case 0x0fbb:
+      ot = dflag + OT_WORD;
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      if (reg < 4)
+       {
+         i386_record_pc -= 3;
+         opcode = opcode << 8 | modrm;
+         goto no_support;
+       }
+      reg -= 4;
+      if (reg != 0)
+       {
+         if (mod != 3)
+           {
+             if (i386_record_lea_modrm ())
+               {
+                 return (-1);
+               }
+           }
+         else
+           {
+             if (record_arch_list_add_reg (rm))
+               {
+                 return (-1);
+               }
+           }
+       }
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* bt Gv, Ev */
+    case 0x0fa3:
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* bsf */
+    case 0x0fbc:
+      /* bsr */
+    case 0x0fbd:
+      if (record_arch_list_add_reg (reg))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* bcd */
+      /* daa */
+    case 0x27:
+      /* das */
+    case 0x2f:
+      /* aaa */
+    case 0x37:
+      /* aas */
+    case 0x3f:
+      /* aam */
+    case 0xd4:
+      /* aad */
+    case 0xd5:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* misc */
+      /* nop */
+    case 0x90:
+      if (prefixes & PREFIX_LOCK)
+       {
+         i386_record_pc -= 1;
+         goto no_support;
+       }
+      break;
+
+      /* fwait */
+      /* XXX */
+    case 0x9b:
+      printf_unfiltered (_
+                        ("Record: record and reverse function don't support instruction fwait.\n"));
+      i386_record_pc -= 1;
+      goto no_support;
+      break;
+
+      /* int3 */
+      /* XXX */
+    case 0xcc:
+      printf_unfiltered (_
+                        ("Record: record and reverse function don't support instruction int3.\n"));
+      i386_record_pc -= 1;
+      goto no_support;
+      break;
+
+      /* int */
+      /* XXX */
+    case 0xcd:
+      {
+       int ret;
+       if (target_read_memory (i386_record_pc, &tmpu8, 1))
+         {
+           printf_unfiltered (_("Record: read memeory 0x%s error.\n"),
+                              paddr_nz (i386_record_pc));
+           return (-1);
+         }
+       i386_record_pc++;
+       if (tmpu8 != 0x80
+           || gdbarch_tdep (gdbarch)->i386_intx80_record == NULL)
+         {
+           printf_unfiltered (_
+                              ("Record: record and reverse function don't support instruction int 0x%02x.\n"),
+                              tmpu8);
+           i386_record_pc -= 2;
+           goto no_support;
+         }
+       ret = gdbarch_tdep (gdbarch)->i386_intx80_record ();
+       if (ret)
+         {
+           return (ret);
+         }
+      }
+      break;
+
+      /* into */
+      /* XXX */
+    case 0xce:
+      printf_unfiltered (_
+                        ("Record: record and reverse function don't support instruction into.\n"));
+      i386_record_pc -= 1;
+      goto no_support;
+      break;
+
+      /* cli */
+    case 0xfa:
+      /* sti */
+    case 0xfb:
+      break;
+
+      /* bound */
+    case 0x62:
+      printf_unfiltered (_
+                        ("Record: record and reverse function don't support instruction bound.\n"));
+      i386_record_pc -= 1;
+      goto no_support;
+      break;
+
+      /* bswap reg */
+    case 0x0fc8 ... 0x0fcf:
+      if (record_arch_list_add_reg (opcode & 7))
+       {
+         return (-1);
+       }
+      break;
+
+      /* salc */
+    case 0xd6:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* loopnz */
+    case 0xe0:
+      /* loopz */
+    case 0xe1:
+      /* loop */
+    case 0xe2:
+      /* jecxz */
+    case 0xe3:
+      if (record_arch_list_add_reg (I386_ECX_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* wrmsr */
+    case 0x0f30:
+      printf_unfiltered (_
+                        ("Record: record and reverse function don't support instruction wrmsr.\n"));
+      i386_record_pc -= 2;
+      goto no_support;
+      break;
+
+      /* rdmsr */
+    case 0x0f32:
+      printf_unfiltered (_
+                        ("Record: record and reverse function don't support instruction rdmsr.\n"));
+      i386_record_pc -= 2;
+      goto no_support;
+      break;
+
+      /* rdtsc */
+    case 0x0f31:
+      printf_unfiltered (_
+                        ("Record: record and reverse function don't support instruction rdtsc.\n"));
+      i386_record_pc -= 2;
+      goto no_support;
+      break;
+
+      /* sysenter */
+    case 0x0f34:
+      {
+       int ret;
+       if (gdbarch_tdep (gdbarch)->i386_sysenter_record == NULL)
+         {
+           printf_unfiltered (_
+                              ("Record: record and reverse function don't support instruction sysenter.\n"));
+           i386_record_pc -= 2;
+           goto no_support;
+         }
+       ret = gdbarch_tdep (gdbarch)->i386_sysenter_record ();
+       if (ret)
+         {
+           return (ret);
+         }
+      }
+      break;
+
+      /* sysexit */
+    case 0x0f35:
+      printf_unfiltered (_
+                        ("Record: record and reverse function don't support instruction sysexit.\n"));
+      i386_record_pc -= 2;
+      goto no_support;
+      break;
+
+      /* cpuid */
+    case 0x0fa2:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_ECX_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_EDX_REGNUM))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_EBX_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* hlt */
+    case 0xf4:
+      printf_unfiltered (_
+                        ("Record: record and reverse function don't support instruction hlt.\n"));
+      i386_record_pc -= 1;
+      goto no_support;
+      break;
+
+    case 0x0f00:
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      switch (reg)
+       {
+         /* sldt */
+       case 0:
+         /* str */
+       case 1:
+         if (mod == 3)
+           {
+             if (record_arch_list_add_reg (rm))
+               {
+                 return (-1);
+               }
+           }
+         else
+           {
+             ot = OT_WORD;
+             if (i386_record_lea_modrm ())
+               {
+                 return (-1);
+               }
+           }
+         break;
+         /* lldt */
+       case 2:
+         /* ltr */
+       case 3:
+         break;
+         /* verr */
+       case 4:
+         /* verw */
+       case 5:
+         if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+           {
+             return (-1);
+           }
+         break;
+       default:
+         i386_record_pc -= 3;
+         opcode = opcode << 8 | modrm;
+         goto no_support;
+         break;
+       }
+      break;
+
+    case 0x0f01:
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      switch (reg)
+       {
+         /* sgdt */
+       case 0:
+         {
+           uint32_t addr;
+
+           if (mod == 3)
+             {
+               i386_record_pc -= 3;
+               opcode = opcode << 8 | modrm;
+               goto no_support;
+             }
+
+           if (override)
+             {
+               if (record_debug)
+                 printf_unfiltered (_
+                                    ("Record: Record ignore the memory change of instruction in address 0x%s because it can't get the value of the segment register.\n"),
+                                    paddr_nz (i386_record_pc));
+error("3");
+             }
+           else
+             {
+               if (i386_record_lea_modrm_addr (&addr))
+                 {
+                   return (-1);
+                 }
+               if (record_arch_list_add_mem (addr, 2))
+                 {
+                   return (-1);
+                 }
+               addr += 2;
+               if (record_arch_list_add_mem (addr, 4))
+                 {
+                   return (-1);
+                 }
+             }
+         }
+         break;
+       case 1:
+         if (mod == 3)
+           {
+             switch (rm)
+               {
+                 /* monitor */
+               case 0:
+                 break;
+                 /* mwait */
+               case 1:
+                 if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+                   {
+                     return (-1);
+                   }
+                 break;
+               default:
+                 i386_record_pc -= 3;
+                 opcode = opcode << 8 | modrm;
+                 goto no_support;
+                 break;
+               }
+           }
+         else
+           {
+             /* sidt */
+             if (override)
+               {
+                 if (record_debug)
+                   printf_unfiltered (_
+                                      ("Record: Record ignore the memory change of instruction in address 0x%s because it can't get the value of the segment register.\n"),
+                                      paddr_nz (i386_record_pc));
+               }
+             else
+               {
+                 uint32_t addr;
+
+                 if (i386_record_lea_modrm_addr (&addr))
+                   {
+                     return (-1);
+                   }
+                 if (record_arch_list_add_mem (addr, 2))
+                   {
+                     return (-1);
+                   }
+                 addr += 2;
+                 if (record_arch_list_add_mem (addr, 4))
+                   {
+                     return (-1);
+                   }
+               }
+           }
+         break;
+         /* lgdt */
+       case 2:
+         /* lidt */
+       case 3:
+         /* invlpg */
+       case 7:
+       default:
+         if (mod == 3)
+           {
+             i386_record_pc -= 3;
+             opcode = opcode << 8 | modrm;
+             goto no_support;
+           }
+         break;
+         /* smsw */
+       case 4:
+         if (mod == 3)
+           {
+             if (record_arch_list_add_reg (rm))
+               {
+                 return (-1);
+               }
+           }
+         else
+           {
+             ot = OT_WORD;
+             if (i386_record_lea_modrm ())
+               {
+                 return (-1);
+               }
+           }
+         break;
+         /* lmsw */
+       case 6:
+         break;
+       }
+      break;
+
+      /* invd */
+    case 0x0f08:
+      /* wbinvd */
+    case 0x0f09:
+      break;
+
+      /* arpl */
+    case 0x63:
+      ot = dflag ? OT_LONG : OT_WORD;
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      if (mod != 3)
+       {
+         if (i386_record_lea_modrm ())
+           {
+             return (-1);
+           }
+       }
+      else
+       {
+         if (record_arch_list_add_reg (rm))
+           {
+             return (-1);
+           }
+       }
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+      /* lar */
+    case 0x0f02:
+      /* lsl */
+    case 0x0f03:
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (reg))
+       {
+         return (-1);
+       }
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+       {
+         return (-1);
+       }
+      break;
+
+    case 0x0f18:
+      break;
+
+      /* nop (multi byte) */
+    case 0x0f19 ... 0x0f1f:
+      break;
+
+      /* mov reg, crN */
+    case 0x0f20:
+      /* mov crN, reg */
+    case 0x0f22:
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      if ((modrm & 0xc0) != 0xc0)
+       {
+         i386_record_pc -= 2;
+         opcode = opcode << 8 | modrm;
+         goto no_support;
+       }
+      switch (reg)
+       {
+       case 0:
+       case 2:
+       case 3:
+       case 4:
+       case 8:
+         if (opcode & 2)
+           {
+           }
+         else
+           {
+             if (record_arch_list_add_reg (rm))
+               {
+                 return (-1);
+               }
+           }
+         break;
+       default:
+         i386_record_pc -= 2;
+         opcode = opcode << 8 | modrm;
+         goto no_support;
+         break;
+       }
+      break;
+
+      /* mov reg, drN */
+    case 0x0f21:
+      /* mov drN, reg */
+    case 0x0f23:
+      if (i386_record_modrm ())
+       {
+         return (-1);
+       }
+      if ((modrm & 0xc0) != 0xc0 || reg == 4 || reg == 5 || reg >= 8)
+       {
+         i386_record_pc -= 2;
+         opcode = opcode << 8 | modrm;
+         goto no_support;
+       }
+      if (opcode & 2)
+       {
+       }
+      else
+       {
+         if (record_arch_list_add_reg (rm))
+           {
+             return (-1);
+           }
+       }
+      break;
+
+      /* clts */
+    case 0x0f06:
+      break;
+
+      /* MMX/SSE/SSE2/PNI support */
+      /* XXX */
+
+    default:
+      if (opcode > 0xff)
+       {
+         i386_record_pc -= 2;
+       }
+      else
+       {
+         i386_record_pc -= 1;
+       }
+      goto no_support;
+      break;
+    }
+
+/* In the future, Maybe still need to deal with need_dasm */
+  if (record_arch_list_add_reg (I386_EIP_REGNUM))
+    {
+      return (-1);
+    }
+  if (record_arch_list_add_end (0))
+    {
+      return (-1);
+    }
+
+  return (0);
+
+no_support:
+  printf_unfiltered (_
+                    ("Record: record and reverse function don't support instruction 0x%02x at address 0x%s.\n"),
+                    (unsigned int) (opcode), paddr_nz (i386_record_pc));
+  return (-1);
+}
+
+\f
+static struct gdbarch *
+i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+  struct gdbarch_tdep *tdep;
+  struct gdbarch *gdbarch;
+
+  /* If there is already a candidate, use it.  */
+  arches = gdbarch_list_lookup_by_info (arches, &info);
+  if (arches != NULL)
+    return arches->gdbarch;
+
+  /* Allocate space for the new architecture.  */
+  tdep = XCALLOC (1, struct gdbarch_tdep);
+  gdbarch = gdbarch_alloc (&info, tdep);
+
+  /* General-purpose registers.  */
+  tdep->gregset = NULL;
+  tdep->gregset_reg_offset = NULL;
+  tdep->gregset_num_regs = I386_NUM_GREGS;
+  tdep->sizeof_gregset = 0;
+
+  /* Floating-point registers.  */
+  tdep->fpregset = NULL;
+  tdep->sizeof_fpregset = I387_SIZEOF_FSAVE;
+
+  /* The default settings include the FPU registers, the MMX registers
+     and the SSE registers.  This can be overridden for a specific ABI
+     by adjusting the members `st0_regnum', `mm0_regnum' and
+     `num_xmm_regs' of `struct gdbarch_tdep', otherwise the registers
+     will show up in the output of "info all-registers".  Ideally we
+     should try to autodetect whether they are available, such that we
+     can prevent "info all-registers" from displaying registers that
+     aren't available.
+
+     NOTE: kevinb/2003-07-13: ... if it's a choice between printing
+     [the SSE registers] always (even when they don't exist) or never
+     showing them to the user (even when they do exist), I prefer the
+     former over the latter.  */
+
+  tdep->st0_regnum = I386_ST0_REGNUM;
+
+  /* The MMX registers are implemented as pseudo-registers.  Put off
+     calculating the register number for %mm0 until we know the number
+     of raw registers.  */
+  tdep->mm0_regnum = 0;
+
+  /* I386_NUM_XREGS includes %mxcsr, so substract one.  */
+  tdep->num_xmm_regs = I386_NUM_XREGS - 1;
+
+  tdep->jb_pc_offset = -1;
+  tdep->struct_return = pcc_struct_return;
+  tdep->sigtramp_start = 0;
+  tdep->sigtramp_end = 0;
+  tdep->sigtramp_p = i386_sigtramp_p;
+  tdep->sigcontext_addr = NULL;
+  tdep->sc_reg_offset = NULL;
+  tdep->sc_pc_offset = -1;
+  tdep->sc_sp_offset = -1;
+
+  /* The format used for `long double' on almost all i386 targets is
+     the i387 extended floating-point format.  In fact, of all targets
+     in the GCC 2.95 tree, only OSF/1 does it different, and insists
+     on having a `long double' that's not `long' at all.  */
+  set_gdbarch_long_double_format (gdbarch, floatformats_i387_ext);
+
+  /* Although the i387 extended floating-point has only 80 significant
+     bits, a `long double' actually takes up 96, probably to enforce
+     alignment.  */
+  set_gdbarch_long_double_bit (gdbarch, 96);
+
+  /* The default ABI includes general-purpose registers, 
+     floating-point registers, and the SSE registers.  */
+  set_gdbarch_num_regs (gdbarch, I386_SSE_NUM_REGS);
+  set_gdbarch_register_name (gdbarch, i386_register_name);
+  set_gdbarch_register_type (gdbarch, i386_register_type);
+
+  /* Register numbers of various important registers.  */
+  set_gdbarch_sp_regnum (gdbarch, I386_ESP_REGNUM); /* %esp */
+  set_gdbarch_pc_regnum (gdbarch, I386_EIP_REGNUM); /* %eip */
+  set_gdbarch_ps_regnum (gdbarch, I386_EFLAGS_REGNUM); /* %eflags */
+  set_gdbarch_fp0_regnum (gdbarch, I386_ST0_REGNUM); /* %st(0) */
+
+  /* NOTE: kettenis/20040418: GCC does have two possible register
+     numbering schemes on the i386: dbx and SVR4.  These schemes
+     differ in how they number %ebp, %esp, %eflags, and the
+     floating-point registers, and are implemented by the arrays
+     dbx_register_map[] and svr4_dbx_register_map in
+     gcc/config/i386.c.  GCC also defines a third numbering scheme in
+     gcc/config/i386.c, which it designates as the "default" register
+     map used in 64bit mode.  This last register numbering scheme is
+     implemented in dbx64_register_map, and is used for AMD64; see
+     amd64-tdep.c.
+
+     Currently, each GCC i386 target always uses the same register
+     numbering scheme across all its supported debugging formats
+     i.e. SDB (COFF), stabs and DWARF 2.  This is because
+     gcc/sdbout.c, gcc/dbxout.c and gcc/dwarf2out.c all use the
+     DBX_REGISTER_NUMBER macro which is defined by each target's
+     respective config header in a manner independent of the requested
+     output debugging format.
+
+     This does not match the arrangement below, which presumes that
+     the SDB and stabs numbering schemes differ from the DWARF and
+     DWARF 2 ones.  The reason for this arrangement is that it is
+     likely to get the numbering scheme for the target's
+     default/native debug format right.  For targets where GCC is the
+     native compiler (FreeBSD, NetBSD, OpenBSD, GNU/Linux) or for
+     targets where the native toolchain uses a different numbering
+     scheme for a particular debug format (stabs-in-ELF on Solaris)
+     the defaults below will have to be overridden, like
+     i386_elf_init_abi() does.  */
+
+  /* Use the dbx register numbering scheme for stabs and COFF.  */
+  set_gdbarch_stab_reg_to_regnum (gdbarch, i386_dbx_reg_to_regnum);
+  set_gdbarch_sdb_reg_to_regnum (gdbarch, i386_dbx_reg_to_regnum);
+
+  /* Use the SVR4 register numbering scheme for DWARF 2.  */
+  set_gdbarch_dwarf2_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
+
+  /* We don't set gdbarch_stab_reg_to_regnum, since ECOFF doesn't seem to
+     be in use on any of the supported i386 targets.  */
+
+  set_gdbarch_print_float_info (gdbarch, i387_print_float_info);
+
+  set_gdbarch_get_longjmp_target (gdbarch, i386_get_longjmp_target);
+
+  /* Call dummy code.  */
+  set_gdbarch_push_dummy_call (gdbarch, i386_push_dummy_call);
+
+  set_gdbarch_convert_register_p (gdbarch, i386_convert_register_p);
+  set_gdbarch_register_to_value (gdbarch,  i386_register_to_value);
+  set_gdbarch_value_to_register (gdbarch, i386_value_to_register);
+
+  set_gdbarch_return_value (gdbarch, i386_return_value);
+
+  set_gdbarch_skip_prologue (gdbarch, i386_skip_prologue);
+
+  /* Stack grows downward.  */
+  set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
 
   set_gdbarch_breakpoint_from_pc (gdbarch, i386_breakpoint_from_pc);
   set_gdbarch_decr_pc_after_break (gdbarch, 1);
@@ -2829,6 +5533,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_skip_permanent_breakpoint (gdbarch,
                                         i386_skip_permanent_breakpoint);
 
+  set_gdbarch_process_record (gdbarch, i386_process_record);
+
   return gdbarch;
 }
 
index d1366b68b250c653fba2ce3627bd8fbf7ae64ac1..a5ba588352c455bcbd5a88a9368f08346dd0a830 100644 (file)
@@ -106,6 +106,9 @@ struct gdbarch_tdep
   /* ISA-specific data types.  */
   struct type *i386_mmx_type;
   struct type *i386_sse_type;
+
+  int (*i386_intx80_record) (void);
+  int (*i386_sysenter_record) (void);
 };
 
 /* Floating-point registers.  */