xref: /dflybsd-src/contrib/gdb-7/gdb/i386-tdep.c (revision de8e141f24382815c10a4012d209bbbf7abf1112)
15796c8dcSSimon Schubert /* Intel 386 target-dependent stuff.
25796c8dcSSimon Schubert 
3*ef5ccd6cSJohn Marino    Copyright (C) 1988-2013 Free Software Foundation, Inc.
45796c8dcSSimon Schubert 
55796c8dcSSimon Schubert    This file is part of GDB.
65796c8dcSSimon Schubert 
75796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
85796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
95796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
105796c8dcSSimon Schubert    (at your option) any later version.
115796c8dcSSimon Schubert 
125796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
135796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
145796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
155796c8dcSSimon Schubert    GNU General Public License for more details.
165796c8dcSSimon Schubert 
175796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
185796c8dcSSimon Schubert    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
195796c8dcSSimon Schubert 
205796c8dcSSimon Schubert #include "defs.h"
215796c8dcSSimon Schubert #include "opcode/i386.h"
225796c8dcSSimon Schubert #include "arch-utils.h"
235796c8dcSSimon Schubert #include "command.h"
245796c8dcSSimon Schubert #include "dummy-frame.h"
255796c8dcSSimon Schubert #include "dwarf2-frame.h"
265796c8dcSSimon Schubert #include "doublest.h"
275796c8dcSSimon Schubert #include "frame.h"
285796c8dcSSimon Schubert #include "frame-base.h"
295796c8dcSSimon Schubert #include "frame-unwind.h"
305796c8dcSSimon Schubert #include "inferior.h"
315796c8dcSSimon Schubert #include "gdbcmd.h"
325796c8dcSSimon Schubert #include "gdbcore.h"
335796c8dcSSimon Schubert #include "gdbtypes.h"
345796c8dcSSimon Schubert #include "objfiles.h"
355796c8dcSSimon Schubert #include "osabi.h"
365796c8dcSSimon Schubert #include "regcache.h"
375796c8dcSSimon Schubert #include "reggroups.h"
385796c8dcSSimon Schubert #include "regset.h"
395796c8dcSSimon Schubert #include "symfile.h"
405796c8dcSSimon Schubert #include "symtab.h"
415796c8dcSSimon Schubert #include "target.h"
425796c8dcSSimon Schubert #include "value.h"
435796c8dcSSimon Schubert #include "dis-asm.h"
44cf7f2e2dSJohn Marino #include "disasm.h"
45cf7f2e2dSJohn Marino #include "remote.h"
46c50c785cSJohn Marino #include "exceptions.h"
475796c8dcSSimon Schubert #include "gdb_assert.h"
485796c8dcSSimon Schubert #include "gdb_string.h"
495796c8dcSSimon Schubert 
505796c8dcSSimon Schubert #include "i386-tdep.h"
515796c8dcSSimon Schubert #include "i387-tdep.h"
52cf7f2e2dSJohn Marino #include "i386-xstate.h"
535796c8dcSSimon Schubert 
545796c8dcSSimon Schubert #include "record.h"
55*ef5ccd6cSJohn Marino #include "record-full.h"
565796c8dcSSimon Schubert #include <stdint.h>
575796c8dcSSimon Schubert 
58cf7f2e2dSJohn Marino #include "features/i386/i386.c"
59cf7f2e2dSJohn Marino #include "features/i386/i386-avx.c"
60cf7f2e2dSJohn Marino #include "features/i386/i386-mmx.c"
61cf7f2e2dSJohn Marino 
62a45ae5f8SJohn Marino #include "ax.h"
63a45ae5f8SJohn Marino #include "ax-gdb.h"
64a45ae5f8SJohn Marino 
65*ef5ccd6cSJohn Marino #include "stap-probe.h"
66*ef5ccd6cSJohn Marino #include "user-regs.h"
67*ef5ccd6cSJohn Marino #include "cli/cli-utils.h"
68*ef5ccd6cSJohn Marino #include "expression.h"
69*ef5ccd6cSJohn Marino #include "parser-defs.h"
70*ef5ccd6cSJohn Marino #include <ctype.h>
71*ef5ccd6cSJohn Marino 
725796c8dcSSimon Schubert /* Register names.  */
735796c8dcSSimon Schubert 
74cf7f2e2dSJohn Marino static const char *i386_register_names[] =
755796c8dcSSimon Schubert {
765796c8dcSSimon Schubert   "eax",   "ecx",    "edx",   "ebx",
775796c8dcSSimon Schubert   "esp",   "ebp",    "esi",   "edi",
785796c8dcSSimon Schubert   "eip",   "eflags", "cs",    "ss",
795796c8dcSSimon Schubert   "ds",    "es",     "fs",    "gs",
805796c8dcSSimon Schubert   "st0",   "st1",    "st2",   "st3",
815796c8dcSSimon Schubert   "st4",   "st5",    "st6",   "st7",
825796c8dcSSimon Schubert   "fctrl", "fstat",  "ftag",  "fiseg",
835796c8dcSSimon Schubert   "fioff", "foseg",  "fooff", "fop",
845796c8dcSSimon Schubert   "xmm0",  "xmm1",   "xmm2",  "xmm3",
855796c8dcSSimon Schubert   "xmm4",  "xmm5",   "xmm6",  "xmm7",
865796c8dcSSimon Schubert   "mxcsr"
875796c8dcSSimon Schubert };
885796c8dcSSimon Schubert 
89cf7f2e2dSJohn Marino static const char *i386_ymm_names[] =
90cf7f2e2dSJohn Marino {
91cf7f2e2dSJohn Marino   "ymm0",  "ymm1",   "ymm2",  "ymm3",
92cf7f2e2dSJohn Marino   "ymm4",  "ymm5",   "ymm6",  "ymm7",
93cf7f2e2dSJohn Marino };
94cf7f2e2dSJohn Marino 
95cf7f2e2dSJohn Marino static const char *i386_ymmh_names[] =
96cf7f2e2dSJohn Marino {
97cf7f2e2dSJohn Marino   "ymm0h",  "ymm1h",   "ymm2h",  "ymm3h",
98cf7f2e2dSJohn Marino   "ymm4h",  "ymm5h",   "ymm6h",  "ymm7h",
99cf7f2e2dSJohn Marino };
1005796c8dcSSimon Schubert 
1015796c8dcSSimon Schubert /* Register names for MMX pseudo-registers.  */
1025796c8dcSSimon Schubert 
103cf7f2e2dSJohn Marino static const char *i386_mmx_names[] =
1045796c8dcSSimon Schubert {
1055796c8dcSSimon Schubert   "mm0", "mm1", "mm2", "mm3",
1065796c8dcSSimon Schubert   "mm4", "mm5", "mm6", "mm7"
1075796c8dcSSimon Schubert };
1085796c8dcSSimon Schubert 
109cf7f2e2dSJohn Marino /* Register names for byte pseudo-registers.  */
110cf7f2e2dSJohn Marino 
111cf7f2e2dSJohn Marino static const char *i386_byte_names[] =
112cf7f2e2dSJohn Marino {
113cf7f2e2dSJohn Marino   "al", "cl", "dl", "bl",
114cf7f2e2dSJohn Marino   "ah", "ch", "dh", "bh"
115cf7f2e2dSJohn Marino };
116cf7f2e2dSJohn Marino 
117cf7f2e2dSJohn Marino /* Register names for word pseudo-registers.  */
118cf7f2e2dSJohn Marino 
119cf7f2e2dSJohn Marino static const char *i386_word_names[] =
120cf7f2e2dSJohn Marino {
121cf7f2e2dSJohn Marino   "ax", "cx", "dx", "bx",
122cf7f2e2dSJohn Marino   "", "bp", "si", "di"
123cf7f2e2dSJohn Marino };
124cf7f2e2dSJohn Marino 
125cf7f2e2dSJohn Marino /* MMX register?  */
1265796c8dcSSimon Schubert 
1275796c8dcSSimon Schubert static int
i386_mmx_regnum_p(struct gdbarch * gdbarch,int regnum)1285796c8dcSSimon Schubert i386_mmx_regnum_p (struct gdbarch *gdbarch, int regnum)
1295796c8dcSSimon Schubert {
130cf7f2e2dSJohn Marino   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
131cf7f2e2dSJohn Marino   int mm0_regnum = tdep->mm0_regnum;
1325796c8dcSSimon Schubert 
1335796c8dcSSimon Schubert   if (mm0_regnum < 0)
1345796c8dcSSimon Schubert     return 0;
1355796c8dcSSimon Schubert 
136cf7f2e2dSJohn Marino   regnum -= mm0_regnum;
137cf7f2e2dSJohn Marino   return regnum >= 0 && regnum < tdep->num_mmx_regs;
138cf7f2e2dSJohn Marino }
139cf7f2e2dSJohn Marino 
140cf7f2e2dSJohn Marino /* Byte register?  */
141cf7f2e2dSJohn Marino 
142cf7f2e2dSJohn Marino int
i386_byte_regnum_p(struct gdbarch * gdbarch,int regnum)143cf7f2e2dSJohn Marino i386_byte_regnum_p (struct gdbarch *gdbarch, int regnum)
144cf7f2e2dSJohn Marino {
145cf7f2e2dSJohn Marino   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
146cf7f2e2dSJohn Marino 
147cf7f2e2dSJohn Marino   regnum -= tdep->al_regnum;
148cf7f2e2dSJohn Marino   return regnum >= 0 && regnum < tdep->num_byte_regs;
149cf7f2e2dSJohn Marino }
150cf7f2e2dSJohn Marino 
151cf7f2e2dSJohn Marino /* Word register?  */
152cf7f2e2dSJohn Marino 
153cf7f2e2dSJohn Marino int
i386_word_regnum_p(struct gdbarch * gdbarch,int regnum)154cf7f2e2dSJohn Marino i386_word_regnum_p (struct gdbarch *gdbarch, int regnum)
155cf7f2e2dSJohn Marino {
156cf7f2e2dSJohn Marino   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
157cf7f2e2dSJohn Marino 
158cf7f2e2dSJohn Marino   regnum -= tdep->ax_regnum;
159cf7f2e2dSJohn Marino   return regnum >= 0 && regnum < tdep->num_word_regs;
160cf7f2e2dSJohn Marino }
161cf7f2e2dSJohn Marino 
162cf7f2e2dSJohn Marino /* Dword register?  */
163cf7f2e2dSJohn Marino 
164cf7f2e2dSJohn Marino int
i386_dword_regnum_p(struct gdbarch * gdbarch,int regnum)165cf7f2e2dSJohn Marino i386_dword_regnum_p (struct gdbarch *gdbarch, int regnum)
166cf7f2e2dSJohn Marino {
167cf7f2e2dSJohn Marino   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
168cf7f2e2dSJohn Marino   int eax_regnum = tdep->eax_regnum;
169cf7f2e2dSJohn Marino 
170cf7f2e2dSJohn Marino   if (eax_regnum < 0)
171cf7f2e2dSJohn Marino     return 0;
172cf7f2e2dSJohn Marino 
173cf7f2e2dSJohn Marino   regnum -= eax_regnum;
174cf7f2e2dSJohn Marino   return regnum >= 0 && regnum < tdep->num_dword_regs;
175cf7f2e2dSJohn Marino }
176cf7f2e2dSJohn Marino 
177c50c785cSJohn Marino static int
i386_ymmh_regnum_p(struct gdbarch * gdbarch,int regnum)178cf7f2e2dSJohn Marino i386_ymmh_regnum_p (struct gdbarch *gdbarch, int regnum)
179cf7f2e2dSJohn Marino {
180cf7f2e2dSJohn Marino   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
181cf7f2e2dSJohn Marino   int ymm0h_regnum = tdep->ymm0h_regnum;
182cf7f2e2dSJohn Marino 
183cf7f2e2dSJohn Marino   if (ymm0h_regnum < 0)
184cf7f2e2dSJohn Marino     return 0;
185cf7f2e2dSJohn Marino 
186cf7f2e2dSJohn Marino   regnum -= ymm0h_regnum;
187cf7f2e2dSJohn Marino   return regnum >= 0 && regnum < tdep->num_ymm_regs;
188cf7f2e2dSJohn Marino }
189cf7f2e2dSJohn Marino 
190cf7f2e2dSJohn Marino /* AVX register?  */
191cf7f2e2dSJohn Marino 
192cf7f2e2dSJohn Marino int
i386_ymm_regnum_p(struct gdbarch * gdbarch,int regnum)193cf7f2e2dSJohn Marino i386_ymm_regnum_p (struct gdbarch *gdbarch, int regnum)
194cf7f2e2dSJohn Marino {
195cf7f2e2dSJohn Marino   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
196cf7f2e2dSJohn Marino   int ymm0_regnum = tdep->ymm0_regnum;
197cf7f2e2dSJohn Marino 
198cf7f2e2dSJohn Marino   if (ymm0_regnum < 0)
199cf7f2e2dSJohn Marino     return 0;
200cf7f2e2dSJohn Marino 
201cf7f2e2dSJohn Marino   regnum -= ymm0_regnum;
202cf7f2e2dSJohn Marino   return regnum >= 0 && regnum < tdep->num_ymm_regs;
2035796c8dcSSimon Schubert }
2045796c8dcSSimon Schubert 
2055796c8dcSSimon Schubert /* SSE register?  */
2065796c8dcSSimon Schubert 
207cf7f2e2dSJohn Marino int
i386_xmm_regnum_p(struct gdbarch * gdbarch,int regnum)208cf7f2e2dSJohn Marino i386_xmm_regnum_p (struct gdbarch *gdbarch, int regnum)
2095796c8dcSSimon Schubert {
2105796c8dcSSimon Schubert   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
211cf7f2e2dSJohn Marino   int num_xmm_regs = I387_NUM_XMM_REGS (tdep);
2125796c8dcSSimon Schubert 
213cf7f2e2dSJohn Marino   if (num_xmm_regs == 0)
2145796c8dcSSimon Schubert     return 0;
2155796c8dcSSimon Schubert 
216cf7f2e2dSJohn Marino   regnum -= I387_XMM0_REGNUM (tdep);
217cf7f2e2dSJohn Marino   return regnum >= 0 && regnum < num_xmm_regs;
2185796c8dcSSimon Schubert }
2195796c8dcSSimon Schubert 
2205796c8dcSSimon Schubert static int
i386_mxcsr_regnum_p(struct gdbarch * gdbarch,int regnum)2215796c8dcSSimon Schubert i386_mxcsr_regnum_p (struct gdbarch *gdbarch, int regnum)
2225796c8dcSSimon Schubert {
2235796c8dcSSimon Schubert   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
2245796c8dcSSimon Schubert 
2255796c8dcSSimon Schubert   if (I387_NUM_XMM_REGS (tdep) == 0)
2265796c8dcSSimon Schubert     return 0;
2275796c8dcSSimon Schubert 
2285796c8dcSSimon Schubert   return (regnum == I387_MXCSR_REGNUM (tdep));
2295796c8dcSSimon Schubert }
2305796c8dcSSimon Schubert 
2315796c8dcSSimon Schubert /* FP register?  */
2325796c8dcSSimon Schubert 
2335796c8dcSSimon Schubert int
i386_fp_regnum_p(struct gdbarch * gdbarch,int regnum)2345796c8dcSSimon Schubert i386_fp_regnum_p (struct gdbarch *gdbarch, int regnum)
2355796c8dcSSimon Schubert {
2365796c8dcSSimon Schubert   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
2375796c8dcSSimon Schubert 
2385796c8dcSSimon Schubert   if (I387_ST0_REGNUM (tdep) < 0)
2395796c8dcSSimon Schubert     return 0;
2405796c8dcSSimon Schubert 
2415796c8dcSSimon Schubert   return (I387_ST0_REGNUM (tdep) <= regnum
2425796c8dcSSimon Schubert 	  && regnum < I387_FCTRL_REGNUM (tdep));
2435796c8dcSSimon Schubert }
2445796c8dcSSimon Schubert 
2455796c8dcSSimon Schubert int
i386_fpc_regnum_p(struct gdbarch * gdbarch,int regnum)2465796c8dcSSimon Schubert i386_fpc_regnum_p (struct gdbarch *gdbarch, int regnum)
2475796c8dcSSimon Schubert {
2485796c8dcSSimon Schubert   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
2495796c8dcSSimon Schubert 
2505796c8dcSSimon Schubert   if (I387_ST0_REGNUM (tdep) < 0)
2515796c8dcSSimon Schubert     return 0;
2525796c8dcSSimon Schubert 
2535796c8dcSSimon Schubert   return (I387_FCTRL_REGNUM (tdep) <= regnum
2545796c8dcSSimon Schubert 	  && regnum < I387_XMM0_REGNUM (tdep));
2555796c8dcSSimon Schubert }
2565796c8dcSSimon Schubert 
257cf7f2e2dSJohn Marino /* Return the name of register REGNUM, or the empty string if it is
258cf7f2e2dSJohn Marino    an anonymous register.  */
259cf7f2e2dSJohn Marino 
260cf7f2e2dSJohn Marino static const char *
i386_register_name(struct gdbarch * gdbarch,int regnum)261cf7f2e2dSJohn Marino i386_register_name (struct gdbarch *gdbarch, int regnum)
262cf7f2e2dSJohn Marino {
263cf7f2e2dSJohn Marino   /* Hide the upper YMM registers.  */
264cf7f2e2dSJohn Marino   if (i386_ymmh_regnum_p (gdbarch, regnum))
265cf7f2e2dSJohn Marino     return "";
266cf7f2e2dSJohn Marino 
267cf7f2e2dSJohn Marino   return tdesc_register_name (gdbarch, regnum);
268cf7f2e2dSJohn Marino }
269cf7f2e2dSJohn Marino 
2705796c8dcSSimon Schubert /* Return the name of register REGNUM.  */
2715796c8dcSSimon Schubert 
2725796c8dcSSimon Schubert const char *
i386_pseudo_register_name(struct gdbarch * gdbarch,int regnum)273cf7f2e2dSJohn Marino i386_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
2745796c8dcSSimon Schubert {
275cf7f2e2dSJohn Marino   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
2765796c8dcSSimon Schubert   if (i386_mmx_regnum_p (gdbarch, regnum))
277cf7f2e2dSJohn Marino     return i386_mmx_names[regnum - I387_MM0_REGNUM (tdep)];
278cf7f2e2dSJohn Marino   else if (i386_ymm_regnum_p (gdbarch, regnum))
279cf7f2e2dSJohn Marino     return i386_ymm_names[regnum - tdep->ymm0_regnum];
280cf7f2e2dSJohn Marino   else if (i386_byte_regnum_p (gdbarch, regnum))
281cf7f2e2dSJohn Marino     return i386_byte_names[regnum - tdep->al_regnum];
282cf7f2e2dSJohn Marino   else if (i386_word_regnum_p (gdbarch, regnum))
283cf7f2e2dSJohn Marino     return i386_word_names[regnum - tdep->ax_regnum];
2845796c8dcSSimon Schubert 
285cf7f2e2dSJohn Marino   internal_error (__FILE__, __LINE__, _("invalid regnum"));
2865796c8dcSSimon Schubert }
2875796c8dcSSimon Schubert 
2885796c8dcSSimon Schubert /* Convert a dbx register number REG to the appropriate register
2895796c8dcSSimon Schubert    number used by GDB.  */
2905796c8dcSSimon Schubert 
2915796c8dcSSimon Schubert static int
i386_dbx_reg_to_regnum(struct gdbarch * gdbarch,int reg)2925796c8dcSSimon Schubert i386_dbx_reg_to_regnum (struct gdbarch *gdbarch, int reg)
2935796c8dcSSimon Schubert {
2945796c8dcSSimon Schubert   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
2955796c8dcSSimon Schubert 
2965796c8dcSSimon Schubert   /* This implements what GCC calls the "default" register map
2975796c8dcSSimon Schubert      (dbx_register_map[]).  */
2985796c8dcSSimon Schubert 
2995796c8dcSSimon Schubert   if (reg >= 0 && reg <= 7)
3005796c8dcSSimon Schubert     {
3015796c8dcSSimon Schubert       /* General-purpose registers.  The debug info calls %ebp
3025796c8dcSSimon Schubert          register 4, and %esp register 5.  */
3035796c8dcSSimon Schubert       if (reg == 4)
3045796c8dcSSimon Schubert         return 5;
3055796c8dcSSimon Schubert       else if (reg == 5)
3065796c8dcSSimon Schubert         return 4;
3075796c8dcSSimon Schubert       else return reg;
3085796c8dcSSimon Schubert     }
3095796c8dcSSimon Schubert   else if (reg >= 12 && reg <= 19)
3105796c8dcSSimon Schubert     {
3115796c8dcSSimon Schubert       /* Floating-point registers.  */
3125796c8dcSSimon Schubert       return reg - 12 + I387_ST0_REGNUM (tdep);
3135796c8dcSSimon Schubert     }
3145796c8dcSSimon Schubert   else if (reg >= 21 && reg <= 28)
3155796c8dcSSimon Schubert     {
3165796c8dcSSimon Schubert       /* SSE registers.  */
317cf7f2e2dSJohn Marino       int ymm0_regnum = tdep->ymm0_regnum;
318cf7f2e2dSJohn Marino 
319cf7f2e2dSJohn Marino       if (ymm0_regnum >= 0
320cf7f2e2dSJohn Marino 	  && i386_xmm_regnum_p (gdbarch, reg))
321cf7f2e2dSJohn Marino 	return reg - 21 + ymm0_regnum;
322cf7f2e2dSJohn Marino       else
3235796c8dcSSimon Schubert 	return reg - 21 + I387_XMM0_REGNUM (tdep);
3245796c8dcSSimon Schubert     }
3255796c8dcSSimon Schubert   else if (reg >= 29 && reg <= 36)
3265796c8dcSSimon Schubert     {
3275796c8dcSSimon Schubert       /* MMX registers.  */
3285796c8dcSSimon Schubert       return reg - 29 + I387_MM0_REGNUM (tdep);
3295796c8dcSSimon Schubert     }
3305796c8dcSSimon Schubert 
3315796c8dcSSimon Schubert   /* This will hopefully provoke a warning.  */
3325796c8dcSSimon Schubert   return gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
3335796c8dcSSimon Schubert }
3345796c8dcSSimon Schubert 
3355796c8dcSSimon Schubert /* Convert SVR4 register number REG to the appropriate register number
3365796c8dcSSimon Schubert    used by GDB.  */
3375796c8dcSSimon Schubert 
3385796c8dcSSimon Schubert static int
i386_svr4_reg_to_regnum(struct gdbarch * gdbarch,int reg)3395796c8dcSSimon Schubert i386_svr4_reg_to_regnum (struct gdbarch *gdbarch, int reg)
3405796c8dcSSimon Schubert {
3415796c8dcSSimon Schubert   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
3425796c8dcSSimon Schubert 
3435796c8dcSSimon Schubert   /* This implements the GCC register map that tries to be compatible
3445796c8dcSSimon Schubert      with the SVR4 C compiler for DWARF (svr4_dbx_register_map[]).  */
3455796c8dcSSimon Schubert 
3465796c8dcSSimon Schubert   /* The SVR4 register numbering includes %eip and %eflags, and
3475796c8dcSSimon Schubert      numbers the floating point registers differently.  */
3485796c8dcSSimon Schubert   if (reg >= 0 && reg <= 9)
3495796c8dcSSimon Schubert     {
3505796c8dcSSimon Schubert       /* General-purpose registers.  */
3515796c8dcSSimon Schubert       return reg;
3525796c8dcSSimon Schubert     }
3535796c8dcSSimon Schubert   else if (reg >= 11 && reg <= 18)
3545796c8dcSSimon Schubert     {
3555796c8dcSSimon Schubert       /* Floating-point registers.  */
3565796c8dcSSimon Schubert       return reg - 11 + I387_ST0_REGNUM (tdep);
3575796c8dcSSimon Schubert     }
3585796c8dcSSimon Schubert   else if (reg >= 21 && reg <= 36)
3595796c8dcSSimon Schubert     {
3605796c8dcSSimon Schubert       /* The SSE and MMX registers have the same numbers as with dbx.  */
3615796c8dcSSimon Schubert       return i386_dbx_reg_to_regnum (gdbarch, reg);
3625796c8dcSSimon Schubert     }
3635796c8dcSSimon Schubert 
3645796c8dcSSimon Schubert   switch (reg)
3655796c8dcSSimon Schubert     {
3665796c8dcSSimon Schubert     case 37: return I387_FCTRL_REGNUM (tdep);
3675796c8dcSSimon Schubert     case 38: return I387_FSTAT_REGNUM (tdep);
3685796c8dcSSimon Schubert     case 39: return I387_MXCSR_REGNUM (tdep);
3695796c8dcSSimon Schubert     case 40: return I386_ES_REGNUM;
3705796c8dcSSimon Schubert     case 41: return I386_CS_REGNUM;
3715796c8dcSSimon Schubert     case 42: return I386_SS_REGNUM;
3725796c8dcSSimon Schubert     case 43: return I386_DS_REGNUM;
3735796c8dcSSimon Schubert     case 44: return I386_FS_REGNUM;
3745796c8dcSSimon Schubert     case 45: return I386_GS_REGNUM;
3755796c8dcSSimon Schubert     }
3765796c8dcSSimon Schubert 
3775796c8dcSSimon Schubert   /* This will hopefully provoke a warning.  */
3785796c8dcSSimon Schubert   return gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
3795796c8dcSSimon Schubert }
3805796c8dcSSimon Schubert 
3815796c8dcSSimon Schubert 
3825796c8dcSSimon Schubert 
3835796c8dcSSimon Schubert /* This is the variable that is set with "set disassembly-flavor", and
3845796c8dcSSimon Schubert    its legitimate values.  */
3855796c8dcSSimon Schubert static const char att_flavor[] = "att";
3865796c8dcSSimon Schubert static const char intel_flavor[] = "intel";
387*ef5ccd6cSJohn Marino static const char *const valid_flavors[] =
3885796c8dcSSimon Schubert {
3895796c8dcSSimon Schubert   att_flavor,
3905796c8dcSSimon Schubert   intel_flavor,
3915796c8dcSSimon Schubert   NULL
3925796c8dcSSimon Schubert };
3935796c8dcSSimon Schubert static const char *disassembly_flavor = att_flavor;
3945796c8dcSSimon Schubert 
3955796c8dcSSimon Schubert 
3965796c8dcSSimon Schubert /* Use the program counter to determine the contents and size of a
3975796c8dcSSimon Schubert    breakpoint instruction.  Return a pointer to a string of bytes that
3985796c8dcSSimon Schubert    encode a breakpoint instruction, store the length of the string in
3995796c8dcSSimon Schubert    *LEN and optionally adjust *PC to point to the correct memory
4005796c8dcSSimon Schubert    location for inserting the breakpoint.
4015796c8dcSSimon Schubert 
4025796c8dcSSimon Schubert    On the i386 we have a single breakpoint that fits in a single byte
4035796c8dcSSimon Schubert    and can be inserted anywhere.
4045796c8dcSSimon Schubert 
4055796c8dcSSimon Schubert    This function is 64-bit safe.  */
4065796c8dcSSimon Schubert 
4075796c8dcSSimon Schubert static const gdb_byte *
i386_breakpoint_from_pc(struct gdbarch * gdbarch,CORE_ADDR * pc,int * len)4085796c8dcSSimon Schubert i386_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pc, int *len)
4095796c8dcSSimon Schubert {
4105796c8dcSSimon Schubert   static gdb_byte break_insn[] = { 0xcc }; /* int 3 */
4115796c8dcSSimon Schubert 
4125796c8dcSSimon Schubert   *len = sizeof (break_insn);
4135796c8dcSSimon Schubert   return break_insn;
4145796c8dcSSimon Schubert }
4155796c8dcSSimon Schubert 
4165796c8dcSSimon Schubert /* Displaced instruction handling.  */
4175796c8dcSSimon Schubert 
4185796c8dcSSimon Schubert /* Skip the legacy instruction prefixes in INSN.
4195796c8dcSSimon Schubert    Not all prefixes are valid for any particular insn
4205796c8dcSSimon Schubert    but we needn't care, the insn will fault if it's invalid.
4215796c8dcSSimon Schubert    The result is a pointer to the first opcode byte,
4225796c8dcSSimon Schubert    or NULL if we run off the end of the buffer.  */
4235796c8dcSSimon Schubert 
4245796c8dcSSimon Schubert static gdb_byte *
i386_skip_prefixes(gdb_byte * insn,size_t max_len)4255796c8dcSSimon Schubert i386_skip_prefixes (gdb_byte *insn, size_t max_len)
4265796c8dcSSimon Schubert {
4275796c8dcSSimon Schubert   gdb_byte *end = insn + max_len;
4285796c8dcSSimon Schubert 
4295796c8dcSSimon Schubert   while (insn < end)
4305796c8dcSSimon Schubert     {
4315796c8dcSSimon Schubert       switch (*insn)
4325796c8dcSSimon Schubert 	{
4335796c8dcSSimon Schubert 	case DATA_PREFIX_OPCODE:
4345796c8dcSSimon Schubert 	case ADDR_PREFIX_OPCODE:
4355796c8dcSSimon Schubert 	case CS_PREFIX_OPCODE:
4365796c8dcSSimon Schubert 	case DS_PREFIX_OPCODE:
4375796c8dcSSimon Schubert 	case ES_PREFIX_OPCODE:
4385796c8dcSSimon Schubert 	case FS_PREFIX_OPCODE:
4395796c8dcSSimon Schubert 	case GS_PREFIX_OPCODE:
4405796c8dcSSimon Schubert 	case SS_PREFIX_OPCODE:
4415796c8dcSSimon Schubert 	case LOCK_PREFIX_OPCODE:
4425796c8dcSSimon Schubert 	case REPE_PREFIX_OPCODE:
4435796c8dcSSimon Schubert 	case REPNE_PREFIX_OPCODE:
4445796c8dcSSimon Schubert 	  ++insn;
4455796c8dcSSimon Schubert 	  continue;
4465796c8dcSSimon Schubert 	default:
4475796c8dcSSimon Schubert 	  return insn;
4485796c8dcSSimon Schubert 	}
4495796c8dcSSimon Schubert     }
4505796c8dcSSimon Schubert 
4515796c8dcSSimon Schubert   return NULL;
4525796c8dcSSimon Schubert }
4535796c8dcSSimon Schubert 
4545796c8dcSSimon Schubert static int
i386_absolute_jmp_p(const gdb_byte * insn)4555796c8dcSSimon Schubert i386_absolute_jmp_p (const gdb_byte *insn)
4565796c8dcSSimon Schubert {
457c50c785cSJohn Marino   /* jmp far (absolute address in operand).  */
4585796c8dcSSimon Schubert   if (insn[0] == 0xea)
4595796c8dcSSimon Schubert     return 1;
4605796c8dcSSimon Schubert 
4615796c8dcSSimon Schubert   if (insn[0] == 0xff)
4625796c8dcSSimon Schubert     {
463c50c785cSJohn Marino       /* jump near, absolute indirect (/4).  */
4645796c8dcSSimon Schubert       if ((insn[1] & 0x38) == 0x20)
4655796c8dcSSimon Schubert         return 1;
4665796c8dcSSimon Schubert 
467c50c785cSJohn Marino       /* jump far, absolute indirect (/5).  */
4685796c8dcSSimon Schubert       if ((insn[1] & 0x38) == 0x28)
4695796c8dcSSimon Schubert         return 1;
4705796c8dcSSimon Schubert     }
4715796c8dcSSimon Schubert 
4725796c8dcSSimon Schubert   return 0;
4735796c8dcSSimon Schubert }
4745796c8dcSSimon Schubert 
4755796c8dcSSimon Schubert static int
i386_absolute_call_p(const gdb_byte * insn)4765796c8dcSSimon Schubert i386_absolute_call_p (const gdb_byte *insn)
4775796c8dcSSimon Schubert {
478c50c785cSJohn Marino   /* call far, absolute.  */
4795796c8dcSSimon Schubert   if (insn[0] == 0x9a)
4805796c8dcSSimon Schubert     return 1;
4815796c8dcSSimon Schubert 
4825796c8dcSSimon Schubert   if (insn[0] == 0xff)
4835796c8dcSSimon Schubert     {
484c50c785cSJohn Marino       /* Call near, absolute indirect (/2).  */
4855796c8dcSSimon Schubert       if ((insn[1] & 0x38) == 0x10)
4865796c8dcSSimon Schubert         return 1;
4875796c8dcSSimon Schubert 
488c50c785cSJohn Marino       /* Call far, absolute indirect (/3).  */
4895796c8dcSSimon Schubert       if ((insn[1] & 0x38) == 0x18)
4905796c8dcSSimon Schubert         return 1;
4915796c8dcSSimon Schubert     }
4925796c8dcSSimon Schubert 
4935796c8dcSSimon Schubert   return 0;
4945796c8dcSSimon Schubert }
4955796c8dcSSimon Schubert 
4965796c8dcSSimon Schubert static int
i386_ret_p(const gdb_byte * insn)4975796c8dcSSimon Schubert i386_ret_p (const gdb_byte *insn)
4985796c8dcSSimon Schubert {
4995796c8dcSSimon Schubert   switch (insn[0])
5005796c8dcSSimon Schubert     {
501c50c785cSJohn Marino     case 0xc2: /* ret near, pop N bytes.  */
5025796c8dcSSimon Schubert     case 0xc3: /* ret near */
503c50c785cSJohn Marino     case 0xca: /* ret far, pop N bytes.  */
5045796c8dcSSimon Schubert     case 0xcb: /* ret far */
5055796c8dcSSimon Schubert     case 0xcf: /* iret */
5065796c8dcSSimon Schubert       return 1;
5075796c8dcSSimon Schubert 
5085796c8dcSSimon Schubert     default:
5095796c8dcSSimon Schubert       return 0;
5105796c8dcSSimon Schubert     }
5115796c8dcSSimon Schubert }
5125796c8dcSSimon Schubert 
5135796c8dcSSimon Schubert static int
i386_call_p(const gdb_byte * insn)5145796c8dcSSimon Schubert i386_call_p (const gdb_byte *insn)
5155796c8dcSSimon Schubert {
5165796c8dcSSimon Schubert   if (i386_absolute_call_p (insn))
5175796c8dcSSimon Schubert     return 1;
5185796c8dcSSimon Schubert 
519c50c785cSJohn Marino   /* call near, relative.  */
5205796c8dcSSimon Schubert   if (insn[0] == 0xe8)
5215796c8dcSSimon Schubert     return 1;
5225796c8dcSSimon Schubert 
5235796c8dcSSimon Schubert   return 0;
5245796c8dcSSimon Schubert }
5255796c8dcSSimon Schubert 
5265796c8dcSSimon Schubert /* Return non-zero if INSN is a system call, and set *LENGTHP to its
5275796c8dcSSimon Schubert    length in bytes.  Otherwise, return zero.  */
5285796c8dcSSimon Schubert 
5295796c8dcSSimon Schubert static int
i386_syscall_p(const gdb_byte * insn,int * lengthp)530cf7f2e2dSJohn Marino i386_syscall_p (const gdb_byte *insn, int *lengthp)
5315796c8dcSSimon Schubert {
532*ef5ccd6cSJohn Marino   /* Is it 'int $0x80'?  */
533*ef5ccd6cSJohn Marino   if ((insn[0] == 0xcd && insn[1] == 0x80)
534*ef5ccd6cSJohn Marino       /* Or is it 'sysenter'?  */
535*ef5ccd6cSJohn Marino       || (insn[0] == 0x0f && insn[1] == 0x34)
536*ef5ccd6cSJohn Marino       /* Or is it 'syscall'?  */
537*ef5ccd6cSJohn Marino       || (insn[0] == 0x0f && insn[1] == 0x05))
5385796c8dcSSimon Schubert     {
5395796c8dcSSimon Schubert       *lengthp = 2;
5405796c8dcSSimon Schubert       return 1;
5415796c8dcSSimon Schubert     }
5425796c8dcSSimon Schubert 
5435796c8dcSSimon Schubert   return 0;
5445796c8dcSSimon Schubert }
5455796c8dcSSimon Schubert 
546cf7f2e2dSJohn Marino /* Some kernels may run one past a syscall insn, so we have to cope.
547cf7f2e2dSJohn Marino    Otherwise this is just simple_displaced_step_copy_insn.  */
548cf7f2e2dSJohn Marino 
549cf7f2e2dSJohn Marino struct displaced_step_closure *
i386_displaced_step_copy_insn(struct gdbarch * gdbarch,CORE_ADDR from,CORE_ADDR to,struct regcache * regs)550cf7f2e2dSJohn Marino i386_displaced_step_copy_insn (struct gdbarch *gdbarch,
551cf7f2e2dSJohn Marino 			       CORE_ADDR from, CORE_ADDR to,
552cf7f2e2dSJohn Marino 			       struct regcache *regs)
553cf7f2e2dSJohn Marino {
554cf7f2e2dSJohn Marino   size_t len = gdbarch_max_insn_length (gdbarch);
555cf7f2e2dSJohn Marino   gdb_byte *buf = xmalloc (len);
556cf7f2e2dSJohn Marino 
557cf7f2e2dSJohn Marino   read_memory (from, buf, len);
558cf7f2e2dSJohn Marino 
559cf7f2e2dSJohn Marino   /* GDB may get control back after the insn after the syscall.
560cf7f2e2dSJohn Marino      Presumably this is a kernel bug.
561cf7f2e2dSJohn Marino      If this is a syscall, make sure there's a nop afterwards.  */
562cf7f2e2dSJohn Marino   {
563cf7f2e2dSJohn Marino     int syscall_length;
564cf7f2e2dSJohn Marino     gdb_byte *insn;
565cf7f2e2dSJohn Marino 
566cf7f2e2dSJohn Marino     insn = i386_skip_prefixes (buf, len);
567cf7f2e2dSJohn Marino     if (insn != NULL && i386_syscall_p (insn, &syscall_length))
568cf7f2e2dSJohn Marino       insn[syscall_length] = NOP_OPCODE;
569cf7f2e2dSJohn Marino   }
570cf7f2e2dSJohn Marino 
571cf7f2e2dSJohn Marino   write_memory (to, buf, len);
572cf7f2e2dSJohn Marino 
573cf7f2e2dSJohn Marino   if (debug_displaced)
574cf7f2e2dSJohn Marino     {
575cf7f2e2dSJohn Marino       fprintf_unfiltered (gdb_stdlog, "displaced: copy %s->%s: ",
576cf7f2e2dSJohn Marino                           paddress (gdbarch, from), paddress (gdbarch, to));
577cf7f2e2dSJohn Marino       displaced_step_dump_bytes (gdb_stdlog, buf, len);
578cf7f2e2dSJohn Marino     }
579cf7f2e2dSJohn Marino 
580cf7f2e2dSJohn Marino   return (struct displaced_step_closure *) buf;
581cf7f2e2dSJohn Marino }
582cf7f2e2dSJohn Marino 
5835796c8dcSSimon Schubert /* Fix up the state of registers and memory after having single-stepped
5845796c8dcSSimon Schubert    a displaced instruction.  */
5855796c8dcSSimon Schubert 
5865796c8dcSSimon Schubert void
i386_displaced_step_fixup(struct gdbarch * gdbarch,struct displaced_step_closure * closure,CORE_ADDR from,CORE_ADDR to,struct regcache * regs)5875796c8dcSSimon Schubert i386_displaced_step_fixup (struct gdbarch *gdbarch,
5885796c8dcSSimon Schubert                            struct displaced_step_closure *closure,
5895796c8dcSSimon Schubert                            CORE_ADDR from, CORE_ADDR to,
5905796c8dcSSimon Schubert                            struct regcache *regs)
5915796c8dcSSimon Schubert {
5925796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
5935796c8dcSSimon Schubert 
5945796c8dcSSimon Schubert   /* The offset we applied to the instruction's address.
5955796c8dcSSimon Schubert      This could well be negative (when viewed as a signed 32-bit
5965796c8dcSSimon Schubert      value), but ULONGEST won't reflect that, so take care when
5975796c8dcSSimon Schubert      applying it.  */
5985796c8dcSSimon Schubert   ULONGEST insn_offset = to - from;
5995796c8dcSSimon Schubert 
6005796c8dcSSimon Schubert   /* Since we use simple_displaced_step_copy_insn, our closure is a
6015796c8dcSSimon Schubert      copy of the instruction.  */
6025796c8dcSSimon Schubert   gdb_byte *insn = (gdb_byte *) closure;
6035796c8dcSSimon Schubert   /* The start of the insn, needed in case we see some prefixes.  */
6045796c8dcSSimon Schubert   gdb_byte *insn_start = insn;
6055796c8dcSSimon Schubert 
6065796c8dcSSimon Schubert   if (debug_displaced)
6075796c8dcSSimon Schubert     fprintf_unfiltered (gdb_stdlog,
6085796c8dcSSimon Schubert                         "displaced: fixup (%s, %s), "
6095796c8dcSSimon Schubert                         "insn = 0x%02x 0x%02x ...\n",
6105796c8dcSSimon Schubert                         paddress (gdbarch, from), paddress (gdbarch, to),
6115796c8dcSSimon Schubert 			insn[0], insn[1]);
6125796c8dcSSimon Schubert 
6135796c8dcSSimon Schubert   /* The list of issues to contend with here is taken from
6145796c8dcSSimon Schubert      resume_execution in arch/i386/kernel/kprobes.c, Linux 2.6.20.
6155796c8dcSSimon Schubert      Yay for Free Software!  */
6165796c8dcSSimon Schubert 
6175796c8dcSSimon Schubert   /* Relocate the %eip, if necessary.  */
6185796c8dcSSimon Schubert 
6195796c8dcSSimon Schubert   /* The instruction recognizers we use assume any leading prefixes
6205796c8dcSSimon Schubert      have been skipped.  */
6215796c8dcSSimon Schubert   {
6225796c8dcSSimon Schubert     /* This is the size of the buffer in closure.  */
6235796c8dcSSimon Schubert     size_t max_insn_len = gdbarch_max_insn_length (gdbarch);
6245796c8dcSSimon Schubert     gdb_byte *opcode = i386_skip_prefixes (insn, max_insn_len);
6255796c8dcSSimon Schubert     /* If there are too many prefixes, just ignore the insn.
6265796c8dcSSimon Schubert        It will fault when run.  */
6275796c8dcSSimon Schubert     if (opcode != NULL)
6285796c8dcSSimon Schubert       insn = opcode;
6295796c8dcSSimon Schubert   }
6305796c8dcSSimon Schubert 
6315796c8dcSSimon Schubert   /* Except in the case of absolute or indirect jump or call
6325796c8dcSSimon Schubert      instructions, or a return instruction, the new eip is relative to
6335796c8dcSSimon Schubert      the displaced instruction; make it relative.  Well, signal
6345796c8dcSSimon Schubert      handler returns don't need relocation either, but we use the
6355796c8dcSSimon Schubert      value of %eip to recognize those; see below.  */
6365796c8dcSSimon Schubert   if (! i386_absolute_jmp_p (insn)
6375796c8dcSSimon Schubert       && ! i386_absolute_call_p (insn)
6385796c8dcSSimon Schubert       && ! i386_ret_p (insn))
6395796c8dcSSimon Schubert     {
6405796c8dcSSimon Schubert       ULONGEST orig_eip;
641cf7f2e2dSJohn Marino       int insn_len;
6425796c8dcSSimon Schubert 
6435796c8dcSSimon Schubert       regcache_cooked_read_unsigned (regs, I386_EIP_REGNUM, &orig_eip);
6445796c8dcSSimon Schubert 
6455796c8dcSSimon Schubert       /* A signal trampoline system call changes the %eip, resuming
6465796c8dcSSimon Schubert          execution of the main program after the signal handler has
6475796c8dcSSimon Schubert          returned.  That makes them like 'return' instructions; we
6485796c8dcSSimon Schubert          shouldn't relocate %eip.
6495796c8dcSSimon Schubert 
6505796c8dcSSimon Schubert          But most system calls don't, and we do need to relocate %eip.
6515796c8dcSSimon Schubert 
6525796c8dcSSimon Schubert          Our heuristic for distinguishing these cases: if stepping
6535796c8dcSSimon Schubert          over the system call instruction left control directly after
6545796c8dcSSimon Schubert          the instruction, the we relocate --- control almost certainly
6555796c8dcSSimon Schubert          doesn't belong in the displaced copy.  Otherwise, we assume
6565796c8dcSSimon Schubert          the instruction has put control where it belongs, and leave
6575796c8dcSSimon Schubert          it unrelocated.  Goodness help us if there are PC-relative
6585796c8dcSSimon Schubert          system calls.  */
6595796c8dcSSimon Schubert       if (i386_syscall_p (insn, &insn_len)
660cf7f2e2dSJohn Marino           && orig_eip != to + (insn - insn_start) + insn_len
661cf7f2e2dSJohn Marino 	  /* GDB can get control back after the insn after the syscall.
662cf7f2e2dSJohn Marino 	     Presumably this is a kernel bug.
663cf7f2e2dSJohn Marino 	     i386_displaced_step_copy_insn ensures its a nop,
664cf7f2e2dSJohn Marino 	     we add one to the length for it.  */
665cf7f2e2dSJohn Marino           && orig_eip != to + (insn - insn_start) + insn_len + 1)
6665796c8dcSSimon Schubert         {
6675796c8dcSSimon Schubert           if (debug_displaced)
6685796c8dcSSimon Schubert             fprintf_unfiltered (gdb_stdlog,
6695796c8dcSSimon Schubert                                 "displaced: syscall changed %%eip; "
6705796c8dcSSimon Schubert                                 "not relocating\n");
6715796c8dcSSimon Schubert         }
6725796c8dcSSimon Schubert       else
6735796c8dcSSimon Schubert         {
6745796c8dcSSimon Schubert           ULONGEST eip = (orig_eip - insn_offset) & 0xffffffffUL;
6755796c8dcSSimon Schubert 
6765796c8dcSSimon Schubert 	  /* If we just stepped over a breakpoint insn, we don't backup
6775796c8dcSSimon Schubert 	     the pc on purpose; this is to match behaviour without
6785796c8dcSSimon Schubert 	     stepping.  */
6795796c8dcSSimon Schubert 
6805796c8dcSSimon Schubert           regcache_cooked_write_unsigned (regs, I386_EIP_REGNUM, eip);
6815796c8dcSSimon Schubert 
6825796c8dcSSimon Schubert           if (debug_displaced)
6835796c8dcSSimon Schubert             fprintf_unfiltered (gdb_stdlog,
6845796c8dcSSimon Schubert                                 "displaced: "
6855796c8dcSSimon Schubert                                 "relocated %%eip from %s to %s\n",
6865796c8dcSSimon Schubert                                 paddress (gdbarch, orig_eip),
6875796c8dcSSimon Schubert 				paddress (gdbarch, eip));
6885796c8dcSSimon Schubert         }
6895796c8dcSSimon Schubert     }
6905796c8dcSSimon Schubert 
6915796c8dcSSimon Schubert   /* If the instruction was PUSHFL, then the TF bit will be set in the
6925796c8dcSSimon Schubert      pushed value, and should be cleared.  We'll leave this for later,
6935796c8dcSSimon Schubert      since GDB already messes up the TF flag when stepping over a
6945796c8dcSSimon Schubert      pushfl.  */
6955796c8dcSSimon Schubert 
6965796c8dcSSimon Schubert   /* If the instruction was a call, the return address now atop the
6975796c8dcSSimon Schubert      stack is the address following the copied instruction.  We need
6985796c8dcSSimon Schubert      to make it the address following the original instruction.  */
6995796c8dcSSimon Schubert   if (i386_call_p (insn))
7005796c8dcSSimon Schubert     {
7015796c8dcSSimon Schubert       ULONGEST esp;
7025796c8dcSSimon Schubert       ULONGEST retaddr;
7035796c8dcSSimon Schubert       const ULONGEST retaddr_len = 4;
7045796c8dcSSimon Schubert 
7055796c8dcSSimon Schubert       regcache_cooked_read_unsigned (regs, I386_ESP_REGNUM, &esp);
7065796c8dcSSimon Schubert       retaddr = read_memory_unsigned_integer (esp, retaddr_len, byte_order);
7075796c8dcSSimon Schubert       retaddr = (retaddr - insn_offset) & 0xffffffffUL;
7085796c8dcSSimon Schubert       write_memory_unsigned_integer (esp, retaddr_len, byte_order, retaddr);
7095796c8dcSSimon Schubert 
7105796c8dcSSimon Schubert       if (debug_displaced)
7115796c8dcSSimon Schubert         fprintf_unfiltered (gdb_stdlog,
7125796c8dcSSimon Schubert                             "displaced: relocated return addr at %s to %s\n",
7135796c8dcSSimon Schubert                             paddress (gdbarch, esp),
7145796c8dcSSimon Schubert                             paddress (gdbarch, retaddr));
7155796c8dcSSimon Schubert     }
7165796c8dcSSimon Schubert }
717cf7f2e2dSJohn Marino 
718cf7f2e2dSJohn Marino static void
append_insns(CORE_ADDR * to,ULONGEST len,const gdb_byte * buf)719cf7f2e2dSJohn Marino append_insns (CORE_ADDR *to, ULONGEST len, const gdb_byte *buf)
720cf7f2e2dSJohn Marino {
721cf7f2e2dSJohn Marino   target_write_memory (*to, buf, len);
722cf7f2e2dSJohn Marino   *to += len;
723cf7f2e2dSJohn Marino }
724cf7f2e2dSJohn Marino 
725cf7f2e2dSJohn Marino static void
i386_relocate_instruction(struct gdbarch * gdbarch,CORE_ADDR * to,CORE_ADDR oldloc)726cf7f2e2dSJohn Marino i386_relocate_instruction (struct gdbarch *gdbarch,
727cf7f2e2dSJohn Marino 			   CORE_ADDR *to, CORE_ADDR oldloc)
728cf7f2e2dSJohn Marino {
729cf7f2e2dSJohn Marino   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
730cf7f2e2dSJohn Marino   gdb_byte buf[I386_MAX_INSN_LEN];
731cf7f2e2dSJohn Marino   int offset = 0, rel32, newrel;
732cf7f2e2dSJohn Marino   int insn_length;
733cf7f2e2dSJohn Marino   gdb_byte *insn = buf;
734cf7f2e2dSJohn Marino 
735cf7f2e2dSJohn Marino   read_memory (oldloc, buf, I386_MAX_INSN_LEN);
736cf7f2e2dSJohn Marino 
737cf7f2e2dSJohn Marino   insn_length = gdb_buffered_insn_length (gdbarch, insn,
738cf7f2e2dSJohn Marino 					  I386_MAX_INSN_LEN, oldloc);
739cf7f2e2dSJohn Marino 
740cf7f2e2dSJohn Marino   /* Get past the prefixes.  */
741cf7f2e2dSJohn Marino   insn = i386_skip_prefixes (insn, I386_MAX_INSN_LEN);
742cf7f2e2dSJohn Marino 
743cf7f2e2dSJohn Marino   /* Adjust calls with 32-bit relative addresses as push/jump, with
744cf7f2e2dSJohn Marino      the address pushed being the location where the original call in
745cf7f2e2dSJohn Marino      the user program would return to.  */
746cf7f2e2dSJohn Marino   if (insn[0] == 0xe8)
747cf7f2e2dSJohn Marino     {
748cf7f2e2dSJohn Marino       gdb_byte push_buf[16];
749cf7f2e2dSJohn Marino       unsigned int ret_addr;
750cf7f2e2dSJohn Marino 
751cf7f2e2dSJohn Marino       /* Where "ret" in the original code will return to.  */
752cf7f2e2dSJohn Marino       ret_addr = oldloc + insn_length;
753cf7f2e2dSJohn Marino       push_buf[0] = 0x68; /* pushq $...  */
754*ef5ccd6cSJohn Marino       store_unsigned_integer (&push_buf[1], 4, byte_order, ret_addr);
755cf7f2e2dSJohn Marino       /* Push the push.  */
756cf7f2e2dSJohn Marino       append_insns (to, 5, push_buf);
757cf7f2e2dSJohn Marino 
758cf7f2e2dSJohn Marino       /* Convert the relative call to a relative jump.  */
759cf7f2e2dSJohn Marino       insn[0] = 0xe9;
760cf7f2e2dSJohn Marino 
761cf7f2e2dSJohn Marino       /* Adjust the destination offset.  */
762cf7f2e2dSJohn Marino       rel32 = extract_signed_integer (insn + 1, 4, byte_order);
763cf7f2e2dSJohn Marino       newrel = (oldloc - *to) + rel32;
764c50c785cSJohn Marino       store_signed_integer (insn + 1, 4, byte_order, newrel);
765c50c785cSJohn Marino 
766c50c785cSJohn Marino       if (debug_displaced)
767c50c785cSJohn Marino 	fprintf_unfiltered (gdb_stdlog,
768c50c785cSJohn Marino 			    "Adjusted insn rel32=%s at %s to"
769c50c785cSJohn Marino 			    " rel32=%s at %s\n",
770c50c785cSJohn Marino 			    hex_string (rel32), paddress (gdbarch, oldloc),
771c50c785cSJohn Marino 			    hex_string (newrel), paddress (gdbarch, *to));
772cf7f2e2dSJohn Marino 
773cf7f2e2dSJohn Marino       /* Write the adjusted jump into its displaced location.  */
774cf7f2e2dSJohn Marino       append_insns (to, 5, insn);
775cf7f2e2dSJohn Marino       return;
776cf7f2e2dSJohn Marino     }
777cf7f2e2dSJohn Marino 
778cf7f2e2dSJohn Marino   /* Adjust jumps with 32-bit relative addresses.  Calls are already
779cf7f2e2dSJohn Marino      handled above.  */
780cf7f2e2dSJohn Marino   if (insn[0] == 0xe9)
781cf7f2e2dSJohn Marino     offset = 1;
782cf7f2e2dSJohn Marino   /* Adjust conditional jumps.  */
783cf7f2e2dSJohn Marino   else if (insn[0] == 0x0f && (insn[1] & 0xf0) == 0x80)
784cf7f2e2dSJohn Marino     offset = 2;
785cf7f2e2dSJohn Marino 
786cf7f2e2dSJohn Marino   if (offset)
787cf7f2e2dSJohn Marino     {
788cf7f2e2dSJohn Marino       rel32 = extract_signed_integer (insn + offset, 4, byte_order);
789cf7f2e2dSJohn Marino       newrel = (oldloc - *to) + rel32;
790c50c785cSJohn Marino       store_signed_integer (insn + offset, 4, byte_order, newrel);
791cf7f2e2dSJohn Marino       if (debug_displaced)
792cf7f2e2dSJohn Marino 	fprintf_unfiltered (gdb_stdlog,
793c50c785cSJohn Marino 			    "Adjusted insn rel32=%s at %s to"
794c50c785cSJohn Marino 			    " rel32=%s at %s\n",
795cf7f2e2dSJohn Marino 			    hex_string (rel32), paddress (gdbarch, oldloc),
796cf7f2e2dSJohn Marino 			    hex_string (newrel), paddress (gdbarch, *to));
797cf7f2e2dSJohn Marino     }
798cf7f2e2dSJohn Marino 
799cf7f2e2dSJohn Marino   /* Write the adjusted instructions into their displaced
800cf7f2e2dSJohn Marino      location.  */
801cf7f2e2dSJohn Marino   append_insns (to, insn_length, buf);
802cf7f2e2dSJohn Marino }
803cf7f2e2dSJohn Marino 
8045796c8dcSSimon Schubert 
8055796c8dcSSimon Schubert #ifdef I386_REGNO_TO_SYMMETRY
8065796c8dcSSimon Schubert #error "The Sequent Symmetry is no longer supported."
8075796c8dcSSimon Schubert #endif
8085796c8dcSSimon Schubert 
8095796c8dcSSimon Schubert /* According to the System V ABI, the registers %ebp, %ebx, %edi, %esi
8105796c8dcSSimon Schubert    and %esp "belong" to the calling function.  Therefore these
8115796c8dcSSimon Schubert    registers should be saved if they're going to be modified.  */
8125796c8dcSSimon Schubert 
8135796c8dcSSimon Schubert /* The maximum number of saved registers.  This should include all
8145796c8dcSSimon Schubert    registers mentioned above, and %eip.  */
8155796c8dcSSimon Schubert #define I386_NUM_SAVED_REGS	I386_NUM_GREGS
8165796c8dcSSimon Schubert 
8175796c8dcSSimon Schubert struct i386_frame_cache
8185796c8dcSSimon Schubert {
8195796c8dcSSimon Schubert   /* Base address.  */
8205796c8dcSSimon Schubert   CORE_ADDR base;
821c50c785cSJohn Marino   int base_p;
8225796c8dcSSimon Schubert   LONGEST sp_offset;
8235796c8dcSSimon Schubert   CORE_ADDR pc;
8245796c8dcSSimon Schubert 
8255796c8dcSSimon Schubert   /* Saved registers.  */
8265796c8dcSSimon Schubert   CORE_ADDR saved_regs[I386_NUM_SAVED_REGS];
8275796c8dcSSimon Schubert   CORE_ADDR saved_sp;
8285796c8dcSSimon Schubert   int saved_sp_reg;
8295796c8dcSSimon Schubert   int pc_in_eax;
8305796c8dcSSimon Schubert 
8315796c8dcSSimon Schubert   /* Stack space reserved for local variables.  */
8325796c8dcSSimon Schubert   long locals;
8335796c8dcSSimon Schubert };
8345796c8dcSSimon Schubert 
8355796c8dcSSimon Schubert /* Allocate and initialize a frame cache.  */
8365796c8dcSSimon Schubert 
8375796c8dcSSimon Schubert static struct i386_frame_cache *
i386_alloc_frame_cache(void)8385796c8dcSSimon Schubert i386_alloc_frame_cache (void)
8395796c8dcSSimon Schubert {
8405796c8dcSSimon Schubert   struct i386_frame_cache *cache;
8415796c8dcSSimon Schubert   int i;
8425796c8dcSSimon Schubert 
8435796c8dcSSimon Schubert   cache = FRAME_OBSTACK_ZALLOC (struct i386_frame_cache);
8445796c8dcSSimon Schubert 
8455796c8dcSSimon Schubert   /* Base address.  */
846c50c785cSJohn Marino   cache->base_p = 0;
8475796c8dcSSimon Schubert   cache->base = 0;
8485796c8dcSSimon Schubert   cache->sp_offset = -4;
8495796c8dcSSimon Schubert   cache->pc = 0;
8505796c8dcSSimon Schubert 
8515796c8dcSSimon Schubert   /* Saved registers.  We initialize these to -1 since zero is a valid
8525796c8dcSSimon Schubert      offset (that's where %ebp is supposed to be stored).  */
8535796c8dcSSimon Schubert   for (i = 0; i < I386_NUM_SAVED_REGS; i++)
8545796c8dcSSimon Schubert     cache->saved_regs[i] = -1;
8555796c8dcSSimon Schubert   cache->saved_sp = 0;
8565796c8dcSSimon Schubert   cache->saved_sp_reg = -1;
8575796c8dcSSimon Schubert   cache->pc_in_eax = 0;
8585796c8dcSSimon Schubert 
8595796c8dcSSimon Schubert   /* Frameless until proven otherwise.  */
8605796c8dcSSimon Schubert   cache->locals = -1;
8615796c8dcSSimon Schubert 
8625796c8dcSSimon Schubert   return cache;
8635796c8dcSSimon Schubert }
8645796c8dcSSimon Schubert 
8655796c8dcSSimon Schubert /* If the instruction at PC is a jump, return the address of its
8665796c8dcSSimon Schubert    target.  Otherwise, return PC.  */
8675796c8dcSSimon Schubert 
8685796c8dcSSimon Schubert static CORE_ADDR
i386_follow_jump(struct gdbarch * gdbarch,CORE_ADDR pc)8695796c8dcSSimon Schubert i386_follow_jump (struct gdbarch *gdbarch, CORE_ADDR pc)
8705796c8dcSSimon Schubert {
8715796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
8725796c8dcSSimon Schubert   gdb_byte op;
8735796c8dcSSimon Schubert   long delta = 0;
8745796c8dcSSimon Schubert   int data16 = 0;
8755796c8dcSSimon Schubert 
876c50c785cSJohn Marino   if (target_read_memory (pc, &op, 1))
877c50c785cSJohn Marino     return pc;
878c50c785cSJohn Marino 
8795796c8dcSSimon Schubert   if (op == 0x66)
8805796c8dcSSimon Schubert     {
8815796c8dcSSimon Schubert       data16 = 1;
8825796c8dcSSimon Schubert       op = read_memory_unsigned_integer (pc + 1, 1, byte_order);
8835796c8dcSSimon Schubert     }
8845796c8dcSSimon Schubert 
8855796c8dcSSimon Schubert   switch (op)
8865796c8dcSSimon Schubert     {
8875796c8dcSSimon Schubert     case 0xe9:
8885796c8dcSSimon Schubert       /* Relative jump: if data16 == 0, disp32, else disp16.  */
8895796c8dcSSimon Schubert       if (data16)
8905796c8dcSSimon Schubert 	{
8915796c8dcSSimon Schubert 	  delta = read_memory_integer (pc + 2, 2, byte_order);
8925796c8dcSSimon Schubert 
8935796c8dcSSimon Schubert 	  /* Include the size of the jmp instruction (including the
8945796c8dcSSimon Schubert              0x66 prefix).  */
8955796c8dcSSimon Schubert 	  delta += 4;
8965796c8dcSSimon Schubert 	}
8975796c8dcSSimon Schubert       else
8985796c8dcSSimon Schubert 	{
8995796c8dcSSimon Schubert 	  delta = read_memory_integer (pc + 1, 4, byte_order);
9005796c8dcSSimon Schubert 
9015796c8dcSSimon Schubert 	  /* Include the size of the jmp instruction.  */
9025796c8dcSSimon Schubert 	  delta += 5;
9035796c8dcSSimon Schubert 	}
9045796c8dcSSimon Schubert       break;
9055796c8dcSSimon Schubert     case 0xeb:
9065796c8dcSSimon Schubert       /* Relative jump, disp8 (ignore data16).  */
9075796c8dcSSimon Schubert       delta = read_memory_integer (pc + data16 + 1, 1, byte_order);
9085796c8dcSSimon Schubert 
9095796c8dcSSimon Schubert       delta += data16 + 2;
9105796c8dcSSimon Schubert       break;
9115796c8dcSSimon Schubert     }
9125796c8dcSSimon Schubert 
9135796c8dcSSimon Schubert   return pc + delta;
9145796c8dcSSimon Schubert }
9155796c8dcSSimon Schubert 
9165796c8dcSSimon Schubert /* Check whether PC points at a prologue for a function returning a
9175796c8dcSSimon Schubert    structure or union.  If so, it updates CACHE and returns the
9185796c8dcSSimon Schubert    address of the first instruction after the code sequence that
9195796c8dcSSimon Schubert    removes the "hidden" argument from the stack or CURRENT_PC,
9205796c8dcSSimon Schubert    whichever is smaller.  Otherwise, return PC.  */
9215796c8dcSSimon Schubert 
9225796c8dcSSimon Schubert static CORE_ADDR
i386_analyze_struct_return(CORE_ADDR pc,CORE_ADDR current_pc,struct i386_frame_cache * cache)9235796c8dcSSimon Schubert i386_analyze_struct_return (CORE_ADDR pc, CORE_ADDR current_pc,
9245796c8dcSSimon Schubert 			    struct i386_frame_cache *cache)
9255796c8dcSSimon Schubert {
9265796c8dcSSimon Schubert   /* Functions that return a structure or union start with:
9275796c8dcSSimon Schubert 
9285796c8dcSSimon Schubert         popl %eax             0x58
9295796c8dcSSimon Schubert         xchgl %eax, (%esp)    0x87 0x04 0x24
9305796c8dcSSimon Schubert      or xchgl %eax, 0(%esp)   0x87 0x44 0x24 0x00
9315796c8dcSSimon Schubert 
9325796c8dcSSimon Schubert      (the System V compiler puts out the second `xchg' instruction,
9335796c8dcSSimon Schubert      and the assembler doesn't try to optimize it, so the 'sib' form
9345796c8dcSSimon Schubert      gets generated).  This sequence is used to get the address of the
9355796c8dcSSimon Schubert      return buffer for a function that returns a structure.  */
9365796c8dcSSimon Schubert   static gdb_byte proto1[3] = { 0x87, 0x04, 0x24 };
9375796c8dcSSimon Schubert   static gdb_byte proto2[4] = { 0x87, 0x44, 0x24, 0x00 };
9385796c8dcSSimon Schubert   gdb_byte buf[4];
9395796c8dcSSimon Schubert   gdb_byte op;
9405796c8dcSSimon Schubert 
9415796c8dcSSimon Schubert   if (current_pc <= pc)
9425796c8dcSSimon Schubert     return pc;
9435796c8dcSSimon Schubert 
944c50c785cSJohn Marino   if (target_read_memory (pc, &op, 1))
945c50c785cSJohn Marino     return pc;
9465796c8dcSSimon Schubert 
9475796c8dcSSimon Schubert   if (op != 0x58)		/* popl %eax */
9485796c8dcSSimon Schubert     return pc;
9495796c8dcSSimon Schubert 
950c50c785cSJohn Marino   if (target_read_memory (pc + 1, buf, 4))
951c50c785cSJohn Marino     return pc;
952c50c785cSJohn Marino 
9535796c8dcSSimon Schubert   if (memcmp (buf, proto1, 3) != 0 && memcmp (buf, proto2, 4) != 0)
9545796c8dcSSimon Schubert     return pc;
9555796c8dcSSimon Schubert 
9565796c8dcSSimon Schubert   if (current_pc == pc)
9575796c8dcSSimon Schubert     {
9585796c8dcSSimon Schubert       cache->sp_offset += 4;
9595796c8dcSSimon Schubert       return current_pc;
9605796c8dcSSimon Schubert     }
9615796c8dcSSimon Schubert 
9625796c8dcSSimon Schubert   if (current_pc == pc + 1)
9635796c8dcSSimon Schubert     {
9645796c8dcSSimon Schubert       cache->pc_in_eax = 1;
9655796c8dcSSimon Schubert       return current_pc;
9665796c8dcSSimon Schubert     }
9675796c8dcSSimon Schubert 
9685796c8dcSSimon Schubert   if (buf[1] == proto1[1])
9695796c8dcSSimon Schubert     return pc + 4;
9705796c8dcSSimon Schubert   else
9715796c8dcSSimon Schubert     return pc + 5;
9725796c8dcSSimon Schubert }
9735796c8dcSSimon Schubert 
9745796c8dcSSimon Schubert static CORE_ADDR
i386_skip_probe(CORE_ADDR pc)9755796c8dcSSimon Schubert i386_skip_probe (CORE_ADDR pc)
9765796c8dcSSimon Schubert {
9775796c8dcSSimon Schubert   /* A function may start with
9785796c8dcSSimon Schubert 
9795796c8dcSSimon Schubert         pushl constant
9805796c8dcSSimon Schubert         call _probe
9815796c8dcSSimon Schubert 	addl $4, %esp
9825796c8dcSSimon Schubert 
9835796c8dcSSimon Schubert      followed by
9845796c8dcSSimon Schubert 
9855796c8dcSSimon Schubert         pushl %ebp
9865796c8dcSSimon Schubert 
9875796c8dcSSimon Schubert      etc.  */
9885796c8dcSSimon Schubert   gdb_byte buf[8];
9895796c8dcSSimon Schubert   gdb_byte op;
9905796c8dcSSimon Schubert 
991c50c785cSJohn Marino   if (target_read_memory (pc, &op, 1))
992c50c785cSJohn Marino     return pc;
9935796c8dcSSimon Schubert 
9945796c8dcSSimon Schubert   if (op == 0x68 || op == 0x6a)
9955796c8dcSSimon Schubert     {
9965796c8dcSSimon Schubert       int delta;
9975796c8dcSSimon Schubert 
9985796c8dcSSimon Schubert       /* Skip past the `pushl' instruction; it has either a one-byte or a
9995796c8dcSSimon Schubert 	 four-byte operand, depending on the opcode.  */
10005796c8dcSSimon Schubert       if (op == 0x68)
10015796c8dcSSimon Schubert 	delta = 5;
10025796c8dcSSimon Schubert       else
10035796c8dcSSimon Schubert 	delta = 2;
10045796c8dcSSimon Schubert 
10055796c8dcSSimon Schubert       /* Read the following 8 bytes, which should be `call _probe' (6
10065796c8dcSSimon Schubert 	 bytes) followed by `addl $4,%esp' (2 bytes).  */
10075796c8dcSSimon Schubert       read_memory (pc + delta, buf, sizeof (buf));
10085796c8dcSSimon Schubert       if (buf[0] == 0xe8 && buf[6] == 0xc4 && buf[7] == 0x4)
10095796c8dcSSimon Schubert 	pc += delta + sizeof (buf);
10105796c8dcSSimon Schubert     }
10115796c8dcSSimon Schubert 
10125796c8dcSSimon Schubert   return pc;
10135796c8dcSSimon Schubert }
10145796c8dcSSimon Schubert 
10155796c8dcSSimon Schubert /* GCC 4.1 and later, can put code in the prologue to realign the
10165796c8dcSSimon Schubert    stack pointer.  Check whether PC points to such code, and update
10175796c8dcSSimon Schubert    CACHE accordingly.  Return the first instruction after the code
10185796c8dcSSimon Schubert    sequence or CURRENT_PC, whichever is smaller.  If we don't
10195796c8dcSSimon Schubert    recognize the code, return PC.  */
10205796c8dcSSimon Schubert 
10215796c8dcSSimon Schubert static CORE_ADDR
i386_analyze_stack_align(CORE_ADDR pc,CORE_ADDR current_pc,struct i386_frame_cache * cache)10225796c8dcSSimon Schubert i386_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
10235796c8dcSSimon Schubert 			  struct i386_frame_cache *cache)
10245796c8dcSSimon Schubert {
10255796c8dcSSimon Schubert   /* There are 2 code sequences to re-align stack before the frame
10265796c8dcSSimon Schubert      gets set up:
10275796c8dcSSimon Schubert 
10285796c8dcSSimon Schubert 	1. Use a caller-saved saved register:
10295796c8dcSSimon Schubert 
10305796c8dcSSimon Schubert 		leal  4(%esp), %reg
10315796c8dcSSimon Schubert 		andl  $-XXX, %esp
10325796c8dcSSimon Schubert 		pushl -4(%reg)
10335796c8dcSSimon Schubert 
10345796c8dcSSimon Schubert 	2. Use a callee-saved saved register:
10355796c8dcSSimon Schubert 
10365796c8dcSSimon Schubert 		pushl %reg
10375796c8dcSSimon Schubert 		leal  8(%esp), %reg
10385796c8dcSSimon Schubert 		andl  $-XXX, %esp
10395796c8dcSSimon Schubert 		pushl -4(%reg)
10405796c8dcSSimon Schubert 
10415796c8dcSSimon Schubert      "andl $-XXX, %esp" can be either 3 bytes or 6 bytes:
10425796c8dcSSimon Schubert 
10435796c8dcSSimon Schubert      	0x83 0xe4 0xf0			andl $-16, %esp
10445796c8dcSSimon Schubert      	0x81 0xe4 0x00 0xff 0xff 0xff	andl $-256, %esp
10455796c8dcSSimon Schubert    */
10465796c8dcSSimon Schubert 
10475796c8dcSSimon Schubert   gdb_byte buf[14];
10485796c8dcSSimon Schubert   int reg;
10495796c8dcSSimon Schubert   int offset, offset_and;
10505796c8dcSSimon Schubert   static int regnums[8] = {
10515796c8dcSSimon Schubert     I386_EAX_REGNUM,		/* %eax */
10525796c8dcSSimon Schubert     I386_ECX_REGNUM,		/* %ecx */
10535796c8dcSSimon Schubert     I386_EDX_REGNUM,		/* %edx */
10545796c8dcSSimon Schubert     I386_EBX_REGNUM,		/* %ebx */
10555796c8dcSSimon Schubert     I386_ESP_REGNUM,		/* %esp */
10565796c8dcSSimon Schubert     I386_EBP_REGNUM,		/* %ebp */
10575796c8dcSSimon Schubert     I386_ESI_REGNUM,		/* %esi */
10585796c8dcSSimon Schubert     I386_EDI_REGNUM		/* %edi */
10595796c8dcSSimon Schubert   };
10605796c8dcSSimon Schubert 
10615796c8dcSSimon Schubert   if (target_read_memory (pc, buf, sizeof buf))
10625796c8dcSSimon Schubert     return pc;
10635796c8dcSSimon Schubert 
10645796c8dcSSimon Schubert   /* Check caller-saved saved register.  The first instruction has
10655796c8dcSSimon Schubert      to be "leal 4(%esp), %reg".  */
10665796c8dcSSimon Schubert   if (buf[0] == 0x8d && buf[2] == 0x24 && buf[3] == 0x4)
10675796c8dcSSimon Schubert     {
10685796c8dcSSimon Schubert       /* MOD must be binary 10 and R/M must be binary 100.  */
10695796c8dcSSimon Schubert       if ((buf[1] & 0xc7) != 0x44)
10705796c8dcSSimon Schubert 	return pc;
10715796c8dcSSimon Schubert 
10725796c8dcSSimon Schubert       /* REG has register number.  */
10735796c8dcSSimon Schubert       reg = (buf[1] >> 3) & 7;
10745796c8dcSSimon Schubert       offset = 4;
10755796c8dcSSimon Schubert     }
10765796c8dcSSimon Schubert   else
10775796c8dcSSimon Schubert     {
10785796c8dcSSimon Schubert       /* Check callee-saved saved register.  The first instruction
10795796c8dcSSimon Schubert 	 has to be "pushl %reg".  */
10805796c8dcSSimon Schubert       if ((buf[0] & 0xf8) != 0x50)
10815796c8dcSSimon Schubert 	return pc;
10825796c8dcSSimon Schubert 
10835796c8dcSSimon Schubert       /* Get register.  */
10845796c8dcSSimon Schubert       reg = buf[0] & 0x7;
10855796c8dcSSimon Schubert 
10865796c8dcSSimon Schubert       /* The next instruction has to be "leal 8(%esp), %reg".  */
10875796c8dcSSimon Schubert       if (buf[1] != 0x8d || buf[3] != 0x24 || buf[4] != 0x8)
10885796c8dcSSimon Schubert 	return pc;
10895796c8dcSSimon Schubert 
10905796c8dcSSimon Schubert       /* MOD must be binary 10 and R/M must be binary 100.  */
10915796c8dcSSimon Schubert       if ((buf[2] & 0xc7) != 0x44)
10925796c8dcSSimon Schubert 	return pc;
10935796c8dcSSimon Schubert 
10945796c8dcSSimon Schubert       /* REG has register number.  Registers in pushl and leal have to
10955796c8dcSSimon Schubert 	 be the same.  */
10965796c8dcSSimon Schubert       if (reg != ((buf[2] >> 3) & 7))
10975796c8dcSSimon Schubert 	return pc;
10985796c8dcSSimon Schubert 
10995796c8dcSSimon Schubert       offset = 5;
11005796c8dcSSimon Schubert     }
11015796c8dcSSimon Schubert 
11025796c8dcSSimon Schubert   /* Rigister can't be %esp nor %ebp.  */
11035796c8dcSSimon Schubert   if (reg == 4 || reg == 5)
11045796c8dcSSimon Schubert     return pc;
11055796c8dcSSimon Schubert 
11065796c8dcSSimon Schubert   /* The next instruction has to be "andl $-XXX, %esp".  */
11075796c8dcSSimon Schubert   if (buf[offset + 1] != 0xe4
11085796c8dcSSimon Schubert       || (buf[offset] != 0x81 && buf[offset] != 0x83))
11095796c8dcSSimon Schubert     return pc;
11105796c8dcSSimon Schubert 
11115796c8dcSSimon Schubert   offset_and = offset;
11125796c8dcSSimon Schubert   offset += buf[offset] == 0x81 ? 6 : 3;
11135796c8dcSSimon Schubert 
11145796c8dcSSimon Schubert   /* The next instruction has to be "pushl -4(%reg)".  8bit -4 is
11155796c8dcSSimon Schubert      0xfc.  REG must be binary 110 and MOD must be binary 01.  */
11165796c8dcSSimon Schubert   if (buf[offset] != 0xff
11175796c8dcSSimon Schubert       || buf[offset + 2] != 0xfc
11185796c8dcSSimon Schubert       || (buf[offset + 1] & 0xf8) != 0x70)
11195796c8dcSSimon Schubert     return pc;
11205796c8dcSSimon Schubert 
11215796c8dcSSimon Schubert   /* R/M has register.  Registers in leal and pushl have to be the
11225796c8dcSSimon Schubert      same.  */
11235796c8dcSSimon Schubert   if (reg != (buf[offset + 1] & 7))
11245796c8dcSSimon Schubert     return pc;
11255796c8dcSSimon Schubert 
11265796c8dcSSimon Schubert   if (current_pc > pc + offset_and)
11275796c8dcSSimon Schubert     cache->saved_sp_reg = regnums[reg];
11285796c8dcSSimon Schubert 
11295796c8dcSSimon Schubert   return min (pc + offset + 3, current_pc);
11305796c8dcSSimon Schubert }
11315796c8dcSSimon Schubert 
11325796c8dcSSimon Schubert /* Maximum instruction length we need to handle.  */
11335796c8dcSSimon Schubert #define I386_MAX_MATCHED_INSN_LEN	6
11345796c8dcSSimon Schubert 
11355796c8dcSSimon Schubert /* Instruction description.  */
11365796c8dcSSimon Schubert struct i386_insn
11375796c8dcSSimon Schubert {
11385796c8dcSSimon Schubert   size_t len;
11395796c8dcSSimon Schubert   gdb_byte insn[I386_MAX_MATCHED_INSN_LEN];
11405796c8dcSSimon Schubert   gdb_byte mask[I386_MAX_MATCHED_INSN_LEN];
11415796c8dcSSimon Schubert };
11425796c8dcSSimon Schubert 
1143a45ae5f8SJohn Marino /* Return whether instruction at PC matches PATTERN.  */
11445796c8dcSSimon Schubert 
1145a45ae5f8SJohn Marino static int
i386_match_pattern(CORE_ADDR pc,struct i386_insn pattern)1146a45ae5f8SJohn Marino i386_match_pattern (CORE_ADDR pc, struct i386_insn pattern)
11475796c8dcSSimon Schubert {
11485796c8dcSSimon Schubert   gdb_byte op;
11495796c8dcSSimon Schubert 
1150c50c785cSJohn Marino   if (target_read_memory (pc, &op, 1))
1151a45ae5f8SJohn Marino     return 0;
11525796c8dcSSimon Schubert 
1153a45ae5f8SJohn Marino   if ((op & pattern.mask[0]) == pattern.insn[0])
11545796c8dcSSimon Schubert     {
11555796c8dcSSimon Schubert       gdb_byte buf[I386_MAX_MATCHED_INSN_LEN - 1];
11565796c8dcSSimon Schubert       int insn_matched = 1;
11575796c8dcSSimon Schubert       size_t i;
11585796c8dcSSimon Schubert 
1159a45ae5f8SJohn Marino       gdb_assert (pattern.len > 1);
1160a45ae5f8SJohn Marino       gdb_assert (pattern.len <= I386_MAX_MATCHED_INSN_LEN);
11615796c8dcSSimon Schubert 
1162a45ae5f8SJohn Marino       if (target_read_memory (pc + 1, buf, pattern.len - 1))
1163a45ae5f8SJohn Marino 	return 0;
1164c50c785cSJohn Marino 
1165a45ae5f8SJohn Marino       for (i = 1; i < pattern.len; i++)
11665796c8dcSSimon Schubert 	{
1167a45ae5f8SJohn Marino 	  if ((buf[i - 1] & pattern.mask[i]) != pattern.insn[i])
11685796c8dcSSimon Schubert 	    insn_matched = 0;
11695796c8dcSSimon Schubert 	}
1170a45ae5f8SJohn Marino       return insn_matched;
11715796c8dcSSimon Schubert     }
1172a45ae5f8SJohn Marino   return 0;
1173a45ae5f8SJohn Marino }
1174a45ae5f8SJohn Marino 
1175a45ae5f8SJohn Marino /* Search for the instruction at PC in the list INSN_PATTERNS.  Return
1176a45ae5f8SJohn Marino    the first instruction description that matches.  Otherwise, return
1177a45ae5f8SJohn Marino    NULL.  */
1178a45ae5f8SJohn Marino 
1179a45ae5f8SJohn Marino static struct i386_insn *
i386_match_insn(CORE_ADDR pc,struct i386_insn * insn_patterns)1180a45ae5f8SJohn Marino i386_match_insn (CORE_ADDR pc, struct i386_insn *insn_patterns)
1181a45ae5f8SJohn Marino {
1182a45ae5f8SJohn Marino   struct i386_insn *pattern;
1183a45ae5f8SJohn Marino 
1184a45ae5f8SJohn Marino   for (pattern = insn_patterns; pattern->len > 0; pattern++)
1185a45ae5f8SJohn Marino     {
1186a45ae5f8SJohn Marino       if (i386_match_pattern (pc, *pattern))
1187a45ae5f8SJohn Marino 	return pattern;
11885796c8dcSSimon Schubert     }
11895796c8dcSSimon Schubert 
11905796c8dcSSimon Schubert   return NULL;
11915796c8dcSSimon Schubert }
11925796c8dcSSimon Schubert 
1193a45ae5f8SJohn Marino /* Return whether PC points inside a sequence of instructions that
1194a45ae5f8SJohn Marino    matches INSN_PATTERNS.  */
1195a45ae5f8SJohn Marino 
1196a45ae5f8SJohn Marino static int
i386_match_insn_block(CORE_ADDR pc,struct i386_insn * insn_patterns)1197a45ae5f8SJohn Marino i386_match_insn_block (CORE_ADDR pc, struct i386_insn *insn_patterns)
1198a45ae5f8SJohn Marino {
1199a45ae5f8SJohn Marino   CORE_ADDR current_pc;
1200a45ae5f8SJohn Marino   int ix, i;
1201a45ae5f8SJohn Marino   struct i386_insn *insn;
1202a45ae5f8SJohn Marino 
1203a45ae5f8SJohn Marino   insn = i386_match_insn (pc, insn_patterns);
1204a45ae5f8SJohn Marino   if (insn == NULL)
1205a45ae5f8SJohn Marino     return 0;
1206a45ae5f8SJohn Marino 
1207a45ae5f8SJohn Marino   current_pc = pc;
1208a45ae5f8SJohn Marino   ix = insn - insn_patterns;
1209a45ae5f8SJohn Marino   for (i = ix - 1; i >= 0; i--)
1210a45ae5f8SJohn Marino     {
1211a45ae5f8SJohn Marino       current_pc -= insn_patterns[i].len;
1212a45ae5f8SJohn Marino 
1213a45ae5f8SJohn Marino       if (!i386_match_pattern (current_pc, insn_patterns[i]))
1214a45ae5f8SJohn Marino 	return 0;
1215a45ae5f8SJohn Marino     }
1216a45ae5f8SJohn Marino 
1217a45ae5f8SJohn Marino   current_pc = pc + insn->len;
1218a45ae5f8SJohn Marino   for (insn = insn_patterns + ix + 1; insn->len > 0; insn++)
1219a45ae5f8SJohn Marino     {
1220a45ae5f8SJohn Marino       if (!i386_match_pattern (current_pc, *insn))
1221a45ae5f8SJohn Marino 	return 0;
1222a45ae5f8SJohn Marino 
1223a45ae5f8SJohn Marino       current_pc += insn->len;
1224a45ae5f8SJohn Marino     }
1225a45ae5f8SJohn Marino 
1226a45ae5f8SJohn Marino   return 1;
1227a45ae5f8SJohn Marino }
1228a45ae5f8SJohn Marino 
12295796c8dcSSimon Schubert /* Some special instructions that might be migrated by GCC into the
12305796c8dcSSimon Schubert    part of the prologue that sets up the new stack frame.  Because the
12315796c8dcSSimon Schubert    stack frame hasn't been setup yet, no registers have been saved
12325796c8dcSSimon Schubert    yet, and only the scratch registers %eax, %ecx and %edx can be
12335796c8dcSSimon Schubert    touched.  */
12345796c8dcSSimon Schubert 
12355796c8dcSSimon Schubert struct i386_insn i386_frame_setup_skip_insns[] =
12365796c8dcSSimon Schubert {
12375796c8dcSSimon Schubert   /* Check for `movb imm8, r' and `movl imm32, r'.
12385796c8dcSSimon Schubert 
12395796c8dcSSimon Schubert      ??? Should we handle 16-bit operand-sizes here?  */
12405796c8dcSSimon Schubert 
12415796c8dcSSimon Schubert   /* `movb imm8, %al' and `movb imm8, %ah' */
12425796c8dcSSimon Schubert   /* `movb imm8, %cl' and `movb imm8, %ch' */
12435796c8dcSSimon Schubert   { 2, { 0xb0, 0x00 }, { 0xfa, 0x00 } },
12445796c8dcSSimon Schubert   /* `movb imm8, %dl' and `movb imm8, %dh' */
12455796c8dcSSimon Schubert   { 2, { 0xb2, 0x00 }, { 0xfb, 0x00 } },
12465796c8dcSSimon Schubert   /* `movl imm32, %eax' and `movl imm32, %ecx' */
12475796c8dcSSimon Schubert   { 5, { 0xb8 }, { 0xfe } },
12485796c8dcSSimon Schubert   /* `movl imm32, %edx' */
12495796c8dcSSimon Schubert   { 5, { 0xba }, { 0xff } },
12505796c8dcSSimon Schubert 
12515796c8dcSSimon Schubert   /* Check for `mov imm32, r32'.  Note that there is an alternative
12525796c8dcSSimon Schubert      encoding for `mov m32, %eax'.
12535796c8dcSSimon Schubert 
12545796c8dcSSimon Schubert      ??? Should we handle SIB adressing here?
12555796c8dcSSimon Schubert      ??? Should we handle 16-bit operand-sizes here?  */
12565796c8dcSSimon Schubert 
12575796c8dcSSimon Schubert   /* `movl m32, %eax' */
12585796c8dcSSimon Schubert   { 5, { 0xa1 }, { 0xff } },
12595796c8dcSSimon Schubert   /* `movl m32, %eax' and `mov; m32, %ecx' */
12605796c8dcSSimon Schubert   { 6, { 0x89, 0x05 }, {0xff, 0xf7 } },
12615796c8dcSSimon Schubert   /* `movl m32, %edx' */
12625796c8dcSSimon Schubert   { 6, { 0x89, 0x15 }, {0xff, 0xff } },
12635796c8dcSSimon Schubert 
12645796c8dcSSimon Schubert   /* Check for `xorl r32, r32' and the equivalent `subl r32, r32'.
12655796c8dcSSimon Schubert      Because of the symmetry, there are actually two ways to encode
12665796c8dcSSimon Schubert      these instructions; opcode bytes 0x29 and 0x2b for `subl' and
12675796c8dcSSimon Schubert      opcode bytes 0x31 and 0x33 for `xorl'.  */
12685796c8dcSSimon Schubert 
12695796c8dcSSimon Schubert   /* `subl %eax, %eax' */
12705796c8dcSSimon Schubert   { 2, { 0x29, 0xc0 }, { 0xfd, 0xff } },
12715796c8dcSSimon Schubert   /* `subl %ecx, %ecx' */
12725796c8dcSSimon Schubert   { 2, { 0x29, 0xc9 }, { 0xfd, 0xff } },
12735796c8dcSSimon Schubert   /* `subl %edx, %edx' */
12745796c8dcSSimon Schubert   { 2, { 0x29, 0xd2 }, { 0xfd, 0xff } },
12755796c8dcSSimon Schubert   /* `xorl %eax, %eax' */
12765796c8dcSSimon Schubert   { 2, { 0x31, 0xc0 }, { 0xfd, 0xff } },
12775796c8dcSSimon Schubert   /* `xorl %ecx, %ecx' */
12785796c8dcSSimon Schubert   { 2, { 0x31, 0xc9 }, { 0xfd, 0xff } },
12795796c8dcSSimon Schubert   /* `xorl %edx, %edx' */
12805796c8dcSSimon Schubert   { 2, { 0x31, 0xd2 }, { 0xfd, 0xff } },
12815796c8dcSSimon Schubert   { 0 }
12825796c8dcSSimon Schubert };
12835796c8dcSSimon Schubert 
12845796c8dcSSimon Schubert 
12855796c8dcSSimon Schubert /* Check whether PC points to a no-op instruction.  */
12865796c8dcSSimon Schubert static CORE_ADDR
i386_skip_noop(CORE_ADDR pc)12875796c8dcSSimon Schubert i386_skip_noop (CORE_ADDR pc)
12885796c8dcSSimon Schubert {
12895796c8dcSSimon Schubert   gdb_byte op;
12905796c8dcSSimon Schubert   int check = 1;
12915796c8dcSSimon Schubert 
1292c50c785cSJohn Marino   if (target_read_memory (pc, &op, 1))
1293c50c785cSJohn Marino     return pc;
12945796c8dcSSimon Schubert 
12955796c8dcSSimon Schubert   while (check)
12965796c8dcSSimon Schubert     {
12975796c8dcSSimon Schubert       check = 0;
12985796c8dcSSimon Schubert       /* Ignore `nop' instruction.  */
12995796c8dcSSimon Schubert       if (op == 0x90)
13005796c8dcSSimon Schubert 	{
13015796c8dcSSimon Schubert 	  pc += 1;
1302c50c785cSJohn Marino 	  if (target_read_memory (pc, &op, 1))
1303c50c785cSJohn Marino 	    return pc;
13045796c8dcSSimon Schubert 	  check = 1;
13055796c8dcSSimon Schubert 	}
13065796c8dcSSimon Schubert       /* Ignore no-op instruction `mov %edi, %edi'.
13075796c8dcSSimon Schubert 	 Microsoft system dlls often start with
13085796c8dcSSimon Schubert 	 a `mov %edi,%edi' instruction.
13095796c8dcSSimon Schubert 	 The 5 bytes before the function start are
13105796c8dcSSimon Schubert 	 filled with `nop' instructions.
13115796c8dcSSimon Schubert 	 This pattern can be used for hot-patching:
13125796c8dcSSimon Schubert 	 The `mov %edi, %edi' instruction can be replaced by a
13135796c8dcSSimon Schubert 	 near jump to the location of the 5 `nop' instructions
13145796c8dcSSimon Schubert 	 which can be replaced by a 32-bit jump to anywhere
13155796c8dcSSimon Schubert 	 in the 32-bit address space.  */
13165796c8dcSSimon Schubert 
13175796c8dcSSimon Schubert       else if (op == 0x8b)
13185796c8dcSSimon Schubert 	{
1319c50c785cSJohn Marino 	  if (target_read_memory (pc + 1, &op, 1))
1320c50c785cSJohn Marino 	    return pc;
1321c50c785cSJohn Marino 
13225796c8dcSSimon Schubert 	  if (op == 0xff)
13235796c8dcSSimon Schubert 	    {
13245796c8dcSSimon Schubert 	      pc += 2;
1325c50c785cSJohn Marino 	      if (target_read_memory (pc, &op, 1))
1326c50c785cSJohn Marino 		return pc;
1327c50c785cSJohn Marino 
13285796c8dcSSimon Schubert 	      check = 1;
13295796c8dcSSimon Schubert 	    }
13305796c8dcSSimon Schubert 	}
13315796c8dcSSimon Schubert     }
13325796c8dcSSimon Schubert   return pc;
13335796c8dcSSimon Schubert }
13345796c8dcSSimon Schubert 
13355796c8dcSSimon Schubert /* Check whether PC points at a code that sets up a new stack frame.
13365796c8dcSSimon Schubert    If so, it updates CACHE and returns the address of the first
13375796c8dcSSimon Schubert    instruction after the sequence that sets up the frame or LIMIT,
13385796c8dcSSimon Schubert    whichever is smaller.  If we don't recognize the code, return PC.  */
13395796c8dcSSimon Schubert 
13405796c8dcSSimon Schubert static CORE_ADDR
i386_analyze_frame_setup(struct gdbarch * gdbarch,CORE_ADDR pc,CORE_ADDR limit,struct i386_frame_cache * cache)13415796c8dcSSimon Schubert i386_analyze_frame_setup (struct gdbarch *gdbarch,
13425796c8dcSSimon Schubert 			  CORE_ADDR pc, CORE_ADDR limit,
13435796c8dcSSimon Schubert 			  struct i386_frame_cache *cache)
13445796c8dcSSimon Schubert {
13455796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
13465796c8dcSSimon Schubert   struct i386_insn *insn;
13475796c8dcSSimon Schubert   gdb_byte op;
13485796c8dcSSimon Schubert   int skip = 0;
13495796c8dcSSimon Schubert 
13505796c8dcSSimon Schubert   if (limit <= pc)
13515796c8dcSSimon Schubert     return limit;
13525796c8dcSSimon Schubert 
1353c50c785cSJohn Marino   if (target_read_memory (pc, &op, 1))
1354c50c785cSJohn Marino     return pc;
13555796c8dcSSimon Schubert 
13565796c8dcSSimon Schubert   if (op == 0x55)		/* pushl %ebp */
13575796c8dcSSimon Schubert     {
13585796c8dcSSimon Schubert       /* Take into account that we've executed the `pushl %ebp' that
13595796c8dcSSimon Schubert 	 starts this instruction sequence.  */
13605796c8dcSSimon Schubert       cache->saved_regs[I386_EBP_REGNUM] = 0;
13615796c8dcSSimon Schubert       cache->sp_offset += 4;
13625796c8dcSSimon Schubert       pc++;
13635796c8dcSSimon Schubert 
13645796c8dcSSimon Schubert       /* If that's all, return now.  */
13655796c8dcSSimon Schubert       if (limit <= pc)
13665796c8dcSSimon Schubert 	return limit;
13675796c8dcSSimon Schubert 
13685796c8dcSSimon Schubert       /* Check for some special instructions that might be migrated by
13695796c8dcSSimon Schubert 	 GCC into the prologue and skip them.  At this point in the
13705796c8dcSSimon Schubert 	 prologue, code should only touch the scratch registers %eax,
13715796c8dcSSimon Schubert 	 %ecx and %edx, so while the number of posibilities is sheer,
13725796c8dcSSimon Schubert 	 it is limited.
13735796c8dcSSimon Schubert 
13745796c8dcSSimon Schubert 	 Make sure we only skip these instructions if we later see the
13755796c8dcSSimon Schubert 	 `movl %esp, %ebp' that actually sets up the frame.  */
13765796c8dcSSimon Schubert       while (pc + skip < limit)
13775796c8dcSSimon Schubert 	{
13785796c8dcSSimon Schubert 	  insn = i386_match_insn (pc + skip, i386_frame_setup_skip_insns);
13795796c8dcSSimon Schubert 	  if (insn == NULL)
13805796c8dcSSimon Schubert 	    break;
13815796c8dcSSimon Schubert 
13825796c8dcSSimon Schubert 	  skip += insn->len;
13835796c8dcSSimon Schubert 	}
13845796c8dcSSimon Schubert 
13855796c8dcSSimon Schubert       /* If that's all, return now.  */
13865796c8dcSSimon Schubert       if (limit <= pc + skip)
13875796c8dcSSimon Schubert 	return limit;
13885796c8dcSSimon Schubert 
1389c50c785cSJohn Marino       if (target_read_memory (pc + skip, &op, 1))
1390c50c785cSJohn Marino 	return pc + skip;
13915796c8dcSSimon Schubert 
1392*ef5ccd6cSJohn Marino       /* The i386 prologue looks like
1393*ef5ccd6cSJohn Marino 
1394*ef5ccd6cSJohn Marino 	 push   %ebp
1395*ef5ccd6cSJohn Marino 	 mov    %esp,%ebp
1396*ef5ccd6cSJohn Marino 	 sub    $0x10,%esp
1397*ef5ccd6cSJohn Marino 
1398*ef5ccd6cSJohn Marino 	 and a different prologue can be generated for atom.
1399*ef5ccd6cSJohn Marino 
1400*ef5ccd6cSJohn Marino 	 push   %ebp
1401*ef5ccd6cSJohn Marino 	 lea    (%esp),%ebp
1402*ef5ccd6cSJohn Marino 	 lea    -0x10(%esp),%esp
1403*ef5ccd6cSJohn Marino 
1404*ef5ccd6cSJohn Marino 	 We handle both of them here.  */
1405*ef5ccd6cSJohn Marino 
14065796c8dcSSimon Schubert       switch (op)
14075796c8dcSSimon Schubert 	{
1408*ef5ccd6cSJohn Marino 	  /* Check for `movl %esp, %ebp' -- can be written in two ways.  */
14095796c8dcSSimon Schubert 	case 0x8b:
14105796c8dcSSimon Schubert 	  if (read_memory_unsigned_integer (pc + skip + 1, 1, byte_order)
14115796c8dcSSimon Schubert 	      != 0xec)
14125796c8dcSSimon Schubert 	    return pc;
1413*ef5ccd6cSJohn Marino 	  pc += (skip + 2);
14145796c8dcSSimon Schubert 	  break;
14155796c8dcSSimon Schubert 	case 0x89:
14165796c8dcSSimon Schubert 	  if (read_memory_unsigned_integer (pc + skip + 1, 1, byte_order)
14175796c8dcSSimon Schubert 	      != 0xe5)
14185796c8dcSSimon Schubert 	    return pc;
1419*ef5ccd6cSJohn Marino 	  pc += (skip + 2);
1420*ef5ccd6cSJohn Marino 	  break;
1421*ef5ccd6cSJohn Marino 	case 0x8d: /* Check for 'lea (%ebp), %ebp'.  */
1422*ef5ccd6cSJohn Marino 	  if (read_memory_unsigned_integer (pc + skip + 1, 2, byte_order)
1423*ef5ccd6cSJohn Marino 	      != 0x242c)
1424*ef5ccd6cSJohn Marino 	    return pc;
1425*ef5ccd6cSJohn Marino 	  pc += (skip + 3);
14265796c8dcSSimon Schubert 	  break;
14275796c8dcSSimon Schubert 	default:
14285796c8dcSSimon Schubert 	  return pc;
14295796c8dcSSimon Schubert 	}
14305796c8dcSSimon Schubert 
14315796c8dcSSimon Schubert       /* OK, we actually have a frame.  We just don't know how large
14325796c8dcSSimon Schubert 	 it is yet.  Set its size to zero.  We'll adjust it if
14335796c8dcSSimon Schubert 	 necessary.  We also now commit to skipping the special
14345796c8dcSSimon Schubert 	 instructions mentioned before.  */
14355796c8dcSSimon Schubert       cache->locals = 0;
14365796c8dcSSimon Schubert 
14375796c8dcSSimon Schubert       /* If that's all, return now.  */
14385796c8dcSSimon Schubert       if (limit <= pc)
14395796c8dcSSimon Schubert 	return limit;
14405796c8dcSSimon Schubert 
14415796c8dcSSimon Schubert       /* Check for stack adjustment
14425796c8dcSSimon Schubert 
14435796c8dcSSimon Schubert 	    subl $XXX, %esp
1444*ef5ccd6cSJohn Marino 	 or
1445*ef5ccd6cSJohn Marino 	    lea -XXX(%esp),%esp
14465796c8dcSSimon Schubert 
14475796c8dcSSimon Schubert 	 NOTE: You can't subtract a 16-bit immediate from a 32-bit
14485796c8dcSSimon Schubert 	 reg, so we don't have to worry about a data16 prefix.  */
1449c50c785cSJohn Marino       if (target_read_memory (pc, &op, 1))
1450c50c785cSJohn Marino 	return pc;
14515796c8dcSSimon Schubert       if (op == 0x83)
14525796c8dcSSimon Schubert 	{
14535796c8dcSSimon Schubert 	  /* `subl' with 8-bit immediate.  */
14545796c8dcSSimon Schubert 	  if (read_memory_unsigned_integer (pc + 1, 1, byte_order) != 0xec)
14555796c8dcSSimon Schubert 	    /* Some instruction starting with 0x83 other than `subl'.  */
14565796c8dcSSimon Schubert 	    return pc;
14575796c8dcSSimon Schubert 
14585796c8dcSSimon Schubert 	  /* `subl' with signed 8-bit immediate (though it wouldn't
14595796c8dcSSimon Schubert 	     make sense to be negative).  */
14605796c8dcSSimon Schubert 	  cache->locals = read_memory_integer (pc + 2, 1, byte_order);
14615796c8dcSSimon Schubert 	  return pc + 3;
14625796c8dcSSimon Schubert 	}
14635796c8dcSSimon Schubert       else if (op == 0x81)
14645796c8dcSSimon Schubert 	{
14655796c8dcSSimon Schubert 	  /* Maybe it is `subl' with a 32-bit immediate.  */
14665796c8dcSSimon Schubert 	  if (read_memory_unsigned_integer (pc + 1, 1, byte_order) != 0xec)
14675796c8dcSSimon Schubert 	    /* Some instruction starting with 0x81 other than `subl'.  */
14685796c8dcSSimon Schubert 	    return pc;
14695796c8dcSSimon Schubert 
14705796c8dcSSimon Schubert 	  /* It is `subl' with a 32-bit immediate.  */
14715796c8dcSSimon Schubert 	  cache->locals = read_memory_integer (pc + 2, 4, byte_order);
14725796c8dcSSimon Schubert 	  return pc + 6;
14735796c8dcSSimon Schubert 	}
1474*ef5ccd6cSJohn Marino       else if (op == 0x8d)
1475*ef5ccd6cSJohn Marino 	{
1476*ef5ccd6cSJohn Marino 	  /* The ModR/M byte is 0x64.  */
1477*ef5ccd6cSJohn Marino 	  if (read_memory_unsigned_integer (pc + 1, 1, byte_order) != 0x64)
1478*ef5ccd6cSJohn Marino 	    return pc;
1479*ef5ccd6cSJohn Marino 	  /* 'lea' with 8-bit displacement.  */
1480*ef5ccd6cSJohn Marino 	  cache->locals = -1 * read_memory_integer (pc + 3, 1, byte_order);
1481*ef5ccd6cSJohn Marino 	  return pc + 4;
1482*ef5ccd6cSJohn Marino 	}
14835796c8dcSSimon Schubert       else
14845796c8dcSSimon Schubert 	{
1485*ef5ccd6cSJohn Marino 	  /* Some instruction other than `subl' nor 'lea'.  */
14865796c8dcSSimon Schubert 	  return pc;
14875796c8dcSSimon Schubert 	}
14885796c8dcSSimon Schubert     }
14895796c8dcSSimon Schubert   else if (op == 0xc8)		/* enter */
14905796c8dcSSimon Schubert     {
14915796c8dcSSimon Schubert       cache->locals = read_memory_unsigned_integer (pc + 1, 2, byte_order);
14925796c8dcSSimon Schubert       return pc + 4;
14935796c8dcSSimon Schubert     }
14945796c8dcSSimon Schubert 
14955796c8dcSSimon Schubert   return pc;
14965796c8dcSSimon Schubert }
14975796c8dcSSimon Schubert 
14985796c8dcSSimon Schubert /* Check whether PC points at code that saves registers on the stack.
14995796c8dcSSimon Schubert    If so, it updates CACHE and returns the address of the first
15005796c8dcSSimon Schubert    instruction after the register saves or CURRENT_PC, whichever is
15015796c8dcSSimon Schubert    smaller.  Otherwise, return PC.  */
15025796c8dcSSimon Schubert 
15035796c8dcSSimon Schubert static CORE_ADDR
i386_analyze_register_saves(CORE_ADDR pc,CORE_ADDR current_pc,struct i386_frame_cache * cache)15045796c8dcSSimon Schubert i386_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc,
15055796c8dcSSimon Schubert 			     struct i386_frame_cache *cache)
15065796c8dcSSimon Schubert {
15075796c8dcSSimon Schubert   CORE_ADDR offset = 0;
15085796c8dcSSimon Schubert   gdb_byte op;
15095796c8dcSSimon Schubert   int i;
15105796c8dcSSimon Schubert 
15115796c8dcSSimon Schubert   if (cache->locals > 0)
15125796c8dcSSimon Schubert     offset -= cache->locals;
15135796c8dcSSimon Schubert   for (i = 0; i < 8 && pc < current_pc; i++)
15145796c8dcSSimon Schubert     {
1515c50c785cSJohn Marino       if (target_read_memory (pc, &op, 1))
1516c50c785cSJohn Marino 	return pc;
15175796c8dcSSimon Schubert       if (op < 0x50 || op > 0x57)
15185796c8dcSSimon Schubert 	break;
15195796c8dcSSimon Schubert 
15205796c8dcSSimon Schubert       offset -= 4;
15215796c8dcSSimon Schubert       cache->saved_regs[op - 0x50] = offset;
15225796c8dcSSimon Schubert       cache->sp_offset += 4;
15235796c8dcSSimon Schubert       pc++;
15245796c8dcSSimon Schubert     }
15255796c8dcSSimon Schubert 
15265796c8dcSSimon Schubert   return pc;
15275796c8dcSSimon Schubert }
15285796c8dcSSimon Schubert 
15295796c8dcSSimon Schubert /* Do a full analysis of the prologue at PC and update CACHE
15305796c8dcSSimon Schubert    accordingly.  Bail out early if CURRENT_PC is reached.  Return the
15315796c8dcSSimon Schubert    address where the analysis stopped.
15325796c8dcSSimon Schubert 
15335796c8dcSSimon Schubert    We handle these cases:
15345796c8dcSSimon Schubert 
15355796c8dcSSimon Schubert    The startup sequence can be at the start of the function, or the
15365796c8dcSSimon Schubert    function can start with a branch to startup code at the end.
15375796c8dcSSimon Schubert 
15385796c8dcSSimon Schubert    %ebp can be set up with either the 'enter' instruction, or "pushl
15395796c8dcSSimon Schubert    %ebp, movl %esp, %ebp" (`enter' is too slow to be useful, but was
15405796c8dcSSimon Schubert    once used in the System V compiler).
15415796c8dcSSimon Schubert 
15425796c8dcSSimon Schubert    Local space is allocated just below the saved %ebp by either the
15435796c8dcSSimon Schubert    'enter' instruction, or by "subl $<size>, %esp".  'enter' has a
15445796c8dcSSimon Schubert    16-bit unsigned argument for space to allocate, and the 'addl'
15455796c8dcSSimon Schubert    instruction could have either a signed byte, or 32-bit immediate.
15465796c8dcSSimon Schubert 
15475796c8dcSSimon Schubert    Next, the registers used by this function are pushed.  With the
15485796c8dcSSimon Schubert    System V compiler they will always be in the order: %edi, %esi,
15495796c8dcSSimon Schubert    %ebx (and sometimes a harmless bug causes it to also save but not
15505796c8dcSSimon Schubert    restore %eax); however, the code below is willing to see the pushes
15515796c8dcSSimon Schubert    in any order, and will handle up to 8 of them.
15525796c8dcSSimon Schubert 
15535796c8dcSSimon Schubert    If the setup sequence is at the end of the function, then the next
15545796c8dcSSimon Schubert    instruction will be a branch back to the start.  */
15555796c8dcSSimon Schubert 
15565796c8dcSSimon Schubert static CORE_ADDR
i386_analyze_prologue(struct gdbarch * gdbarch,CORE_ADDR pc,CORE_ADDR current_pc,struct i386_frame_cache * cache)15575796c8dcSSimon Schubert i386_analyze_prologue (struct gdbarch *gdbarch,
15585796c8dcSSimon Schubert 		       CORE_ADDR pc, CORE_ADDR current_pc,
15595796c8dcSSimon Schubert 		       struct i386_frame_cache *cache)
15605796c8dcSSimon Schubert {
15615796c8dcSSimon Schubert   pc = i386_skip_noop (pc);
15625796c8dcSSimon Schubert   pc = i386_follow_jump (gdbarch, pc);
15635796c8dcSSimon Schubert   pc = i386_analyze_struct_return (pc, current_pc, cache);
15645796c8dcSSimon Schubert   pc = i386_skip_probe (pc);
15655796c8dcSSimon Schubert   pc = i386_analyze_stack_align (pc, current_pc, cache);
15665796c8dcSSimon Schubert   pc = i386_analyze_frame_setup (gdbarch, pc, current_pc, cache);
15675796c8dcSSimon Schubert   return i386_analyze_register_saves (pc, current_pc, cache);
15685796c8dcSSimon Schubert }
15695796c8dcSSimon Schubert 
15705796c8dcSSimon Schubert /* Return PC of first real instruction.  */
15715796c8dcSSimon Schubert 
15725796c8dcSSimon Schubert static CORE_ADDR
i386_skip_prologue(struct gdbarch * gdbarch,CORE_ADDR start_pc)15735796c8dcSSimon Schubert i386_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
15745796c8dcSSimon Schubert {
15755796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
15765796c8dcSSimon Schubert 
15775796c8dcSSimon Schubert   static gdb_byte pic_pat[6] =
15785796c8dcSSimon Schubert   {
15795796c8dcSSimon Schubert     0xe8, 0, 0, 0, 0,		/* call 0x0 */
15805796c8dcSSimon Schubert     0x5b,			/* popl %ebx */
15815796c8dcSSimon Schubert   };
15825796c8dcSSimon Schubert   struct i386_frame_cache cache;
15835796c8dcSSimon Schubert   CORE_ADDR pc;
15845796c8dcSSimon Schubert   gdb_byte op;
15855796c8dcSSimon Schubert   int i;
1586*ef5ccd6cSJohn Marino   CORE_ADDR func_addr;
1587*ef5ccd6cSJohn Marino 
1588*ef5ccd6cSJohn Marino   if (find_pc_partial_function (start_pc, NULL, &func_addr, NULL))
1589*ef5ccd6cSJohn Marino     {
1590*ef5ccd6cSJohn Marino       CORE_ADDR post_prologue_pc
1591*ef5ccd6cSJohn Marino 	= skip_prologue_using_sal (gdbarch, func_addr);
1592*ef5ccd6cSJohn Marino       struct symtab *s = find_pc_symtab (func_addr);
1593*ef5ccd6cSJohn Marino 
1594*ef5ccd6cSJohn Marino       /* Clang always emits a line note before the prologue and another
1595*ef5ccd6cSJohn Marino 	 one after.  We trust clang to emit usable line notes.  */
1596*ef5ccd6cSJohn Marino       if (post_prologue_pc
1597*ef5ccd6cSJohn Marino 	  && (s != NULL
1598*ef5ccd6cSJohn Marino 	      && s->producer != NULL
1599*ef5ccd6cSJohn Marino 	      && strncmp (s->producer, "clang ", sizeof ("clang ") - 1) == 0))
1600*ef5ccd6cSJohn Marino         return max (start_pc, post_prologue_pc);
1601*ef5ccd6cSJohn Marino     }
16025796c8dcSSimon Schubert 
16035796c8dcSSimon Schubert   cache.locals = -1;
16045796c8dcSSimon Schubert   pc = i386_analyze_prologue (gdbarch, start_pc, 0xffffffff, &cache);
16055796c8dcSSimon Schubert   if (cache.locals < 0)
16065796c8dcSSimon Schubert     return start_pc;
16075796c8dcSSimon Schubert 
16085796c8dcSSimon Schubert   /* Found valid frame setup.  */
16095796c8dcSSimon Schubert 
16105796c8dcSSimon Schubert   /* The native cc on SVR4 in -K PIC mode inserts the following code
16115796c8dcSSimon Schubert      to get the address of the global offset table (GOT) into register
16125796c8dcSSimon Schubert      %ebx:
16135796c8dcSSimon Schubert 
16145796c8dcSSimon Schubert         call	0x0
16155796c8dcSSimon Schubert 	popl    %ebx
16165796c8dcSSimon Schubert         movl    %ebx,x(%ebp)    (optional)
16175796c8dcSSimon Schubert         addl    y,%ebx
16185796c8dcSSimon Schubert 
16195796c8dcSSimon Schubert      This code is with the rest of the prologue (at the end of the
16205796c8dcSSimon Schubert      function), so we have to skip it to get to the first real
16215796c8dcSSimon Schubert      instruction at the start of the function.  */
16225796c8dcSSimon Schubert 
16235796c8dcSSimon Schubert   for (i = 0; i < 6; i++)
16245796c8dcSSimon Schubert     {
1625c50c785cSJohn Marino       if (target_read_memory (pc + i, &op, 1))
1626c50c785cSJohn Marino 	return pc;
1627c50c785cSJohn Marino 
16285796c8dcSSimon Schubert       if (pic_pat[i] != op)
16295796c8dcSSimon Schubert 	break;
16305796c8dcSSimon Schubert     }
16315796c8dcSSimon Schubert   if (i == 6)
16325796c8dcSSimon Schubert     {
16335796c8dcSSimon Schubert       int delta = 6;
16345796c8dcSSimon Schubert 
1635c50c785cSJohn Marino       if (target_read_memory (pc + delta, &op, 1))
1636c50c785cSJohn Marino 	return pc;
16375796c8dcSSimon Schubert 
16385796c8dcSSimon Schubert       if (op == 0x89)		/* movl %ebx, x(%ebp) */
16395796c8dcSSimon Schubert 	{
16405796c8dcSSimon Schubert 	  op = read_memory_unsigned_integer (pc + delta + 1, 1, byte_order);
16415796c8dcSSimon Schubert 
16425796c8dcSSimon Schubert 	  if (op == 0x5d)	/* One byte offset from %ebp.  */
16435796c8dcSSimon Schubert 	    delta += 3;
16445796c8dcSSimon Schubert 	  else if (op == 0x9d)	/* Four byte offset from %ebp.  */
16455796c8dcSSimon Schubert 	    delta += 6;
16465796c8dcSSimon Schubert 	  else			/* Unexpected instruction.  */
16475796c8dcSSimon Schubert 	    delta = 0;
16485796c8dcSSimon Schubert 
1649c50c785cSJohn Marino           if (target_read_memory (pc + delta, &op, 1))
1650c50c785cSJohn Marino 	    return pc;
16515796c8dcSSimon Schubert 	}
16525796c8dcSSimon Schubert 
16535796c8dcSSimon Schubert       /* addl y,%ebx */
16545796c8dcSSimon Schubert       if (delta > 0 && op == 0x81
16555796c8dcSSimon Schubert 	  && read_memory_unsigned_integer (pc + delta + 1, 1, byte_order)
16565796c8dcSSimon Schubert 	     == 0xc3)
16575796c8dcSSimon Schubert 	{
16585796c8dcSSimon Schubert 	  pc += delta + 6;
16595796c8dcSSimon Schubert 	}
16605796c8dcSSimon Schubert     }
16615796c8dcSSimon Schubert 
16625796c8dcSSimon Schubert   /* If the function starts with a branch (to startup code at the end)
16635796c8dcSSimon Schubert      the last instruction should bring us back to the first
16645796c8dcSSimon Schubert      instruction of the real code.  */
16655796c8dcSSimon Schubert   if (i386_follow_jump (gdbarch, start_pc) != start_pc)
16665796c8dcSSimon Schubert     pc = i386_follow_jump (gdbarch, pc);
16675796c8dcSSimon Schubert 
16685796c8dcSSimon Schubert   return pc;
16695796c8dcSSimon Schubert }
16705796c8dcSSimon Schubert 
16715796c8dcSSimon Schubert /* Check that the code pointed to by PC corresponds to a call to
16725796c8dcSSimon Schubert    __main, skip it if so.  Return PC otherwise.  */
16735796c8dcSSimon Schubert 
16745796c8dcSSimon Schubert CORE_ADDR
i386_skip_main_prologue(struct gdbarch * gdbarch,CORE_ADDR pc)16755796c8dcSSimon Schubert i386_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
16765796c8dcSSimon Schubert {
16775796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
16785796c8dcSSimon Schubert   gdb_byte op;
16795796c8dcSSimon Schubert 
1680c50c785cSJohn Marino   if (target_read_memory (pc, &op, 1))
1681c50c785cSJohn Marino     return pc;
16825796c8dcSSimon Schubert   if (op == 0xe8)
16835796c8dcSSimon Schubert     {
16845796c8dcSSimon Schubert       gdb_byte buf[4];
16855796c8dcSSimon Schubert 
16865796c8dcSSimon Schubert       if (target_read_memory (pc + 1, buf, sizeof buf) == 0)
16875796c8dcSSimon Schubert  	{
16885796c8dcSSimon Schubert 	  /* Make sure address is computed correctly as a 32bit
16895796c8dcSSimon Schubert 	     integer even if CORE_ADDR is 64 bit wide.  */
16905796c8dcSSimon Schubert  	  struct minimal_symbol *s;
16915796c8dcSSimon Schubert  	  CORE_ADDR call_dest;
16925796c8dcSSimon Schubert 
16935796c8dcSSimon Schubert 	  call_dest = pc + 5 + extract_signed_integer (buf, 4, byte_order);
16945796c8dcSSimon Schubert 	  call_dest = call_dest & 0xffffffffU;
16955796c8dcSSimon Schubert  	  s = lookup_minimal_symbol_by_pc (call_dest);
16965796c8dcSSimon Schubert  	  if (s != NULL
16975796c8dcSSimon Schubert  	      && SYMBOL_LINKAGE_NAME (s) != NULL
16985796c8dcSSimon Schubert  	      && strcmp (SYMBOL_LINKAGE_NAME (s), "__main") == 0)
16995796c8dcSSimon Schubert  	    pc += 5;
17005796c8dcSSimon Schubert  	}
17015796c8dcSSimon Schubert     }
17025796c8dcSSimon Schubert 
17035796c8dcSSimon Schubert   return pc;
17045796c8dcSSimon Schubert }
17055796c8dcSSimon Schubert 
17065796c8dcSSimon Schubert /* This function is 64-bit safe.  */
17075796c8dcSSimon Schubert 
17085796c8dcSSimon Schubert static CORE_ADDR
i386_unwind_pc(struct gdbarch * gdbarch,struct frame_info * next_frame)17095796c8dcSSimon Schubert i386_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
17105796c8dcSSimon Schubert {
17115796c8dcSSimon Schubert   gdb_byte buf[8];
17125796c8dcSSimon Schubert 
17135796c8dcSSimon Schubert   frame_unwind_register (next_frame, gdbarch_pc_regnum (gdbarch), buf);
17145796c8dcSSimon Schubert   return extract_typed_address (buf, builtin_type (gdbarch)->builtin_func_ptr);
17155796c8dcSSimon Schubert }
17165796c8dcSSimon Schubert 
17175796c8dcSSimon Schubert 
17185796c8dcSSimon Schubert /* Normal frames.  */
17195796c8dcSSimon Schubert 
1720c50c785cSJohn Marino static void
i386_frame_cache_1(struct frame_info * this_frame,struct i386_frame_cache * cache)1721c50c785cSJohn Marino i386_frame_cache_1 (struct frame_info *this_frame,
1722c50c785cSJohn Marino 		    struct i386_frame_cache *cache)
17235796c8dcSSimon Schubert {
17245796c8dcSSimon Schubert   struct gdbarch *gdbarch = get_frame_arch (this_frame);
17255796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
17265796c8dcSSimon Schubert   gdb_byte buf[4];
17275796c8dcSSimon Schubert   int i;
17285796c8dcSSimon Schubert 
1729c50c785cSJohn Marino   cache->pc = get_frame_func (this_frame);
17305796c8dcSSimon Schubert 
17315796c8dcSSimon Schubert   /* In principle, for normal frames, %ebp holds the frame pointer,
17325796c8dcSSimon Schubert      which holds the base address for the current stack frame.
17335796c8dcSSimon Schubert      However, for functions that don't need it, the frame pointer is
17345796c8dcSSimon Schubert      optional.  For these "frameless" functions the frame pointer is
17355796c8dcSSimon Schubert      actually the frame pointer of the calling frame.  Signal
17365796c8dcSSimon Schubert      trampolines are just a special case of a "frameless" function.
17375796c8dcSSimon Schubert      They (usually) share their frame pointer with the frame that was
17385796c8dcSSimon Schubert      in progress when the signal occurred.  */
17395796c8dcSSimon Schubert 
17405796c8dcSSimon Schubert   get_frame_register (this_frame, I386_EBP_REGNUM, buf);
17415796c8dcSSimon Schubert   cache->base = extract_unsigned_integer (buf, 4, byte_order);
17425796c8dcSSimon Schubert   if (cache->base == 0)
1743a45ae5f8SJohn Marino     {
1744a45ae5f8SJohn Marino       cache->base_p = 1;
1745c50c785cSJohn Marino       return;
1746a45ae5f8SJohn Marino     }
17475796c8dcSSimon Schubert 
17485796c8dcSSimon Schubert   /* For normal frames, %eip is stored at 4(%ebp).  */
17495796c8dcSSimon Schubert   cache->saved_regs[I386_EIP_REGNUM] = 4;
17505796c8dcSSimon Schubert 
17515796c8dcSSimon Schubert   if (cache->pc != 0)
17525796c8dcSSimon Schubert     i386_analyze_prologue (gdbarch, cache->pc, get_frame_pc (this_frame),
17535796c8dcSSimon Schubert 			   cache);
17545796c8dcSSimon Schubert 
17555796c8dcSSimon Schubert   if (cache->locals < 0)
17565796c8dcSSimon Schubert     {
17575796c8dcSSimon Schubert       /* We didn't find a valid frame, which means that CACHE->base
17585796c8dcSSimon Schubert 	 currently holds the frame pointer for our calling frame.  If
17595796c8dcSSimon Schubert 	 we're at the start of a function, or somewhere half-way its
17605796c8dcSSimon Schubert 	 prologue, the function's frame probably hasn't been fully
17615796c8dcSSimon Schubert 	 setup yet.  Try to reconstruct the base address for the stack
17625796c8dcSSimon Schubert 	 frame by looking at the stack pointer.  For truly "frameless"
17635796c8dcSSimon Schubert 	 functions this might work too.  */
17645796c8dcSSimon Schubert 
17655796c8dcSSimon Schubert       if (cache->saved_sp_reg != -1)
17665796c8dcSSimon Schubert 	{
1767c50c785cSJohn Marino 	  /* Saved stack pointer has been saved.  */
1768c50c785cSJohn Marino 	  get_frame_register (this_frame, cache->saved_sp_reg, buf);
1769c50c785cSJohn Marino 	  cache->saved_sp = extract_unsigned_integer (buf, 4, byte_order);
1770c50c785cSJohn Marino 
17715796c8dcSSimon Schubert 	  /* We're halfway aligning the stack.  */
17725796c8dcSSimon Schubert 	  cache->base = ((cache->saved_sp - 4) & 0xfffffff0) - 4;
17735796c8dcSSimon Schubert 	  cache->saved_regs[I386_EIP_REGNUM] = cache->saved_sp - 4;
17745796c8dcSSimon Schubert 
17755796c8dcSSimon Schubert 	  /* This will be added back below.  */
17765796c8dcSSimon Schubert 	  cache->saved_regs[I386_EIP_REGNUM] -= cache->base;
17775796c8dcSSimon Schubert 	}
1778cf7f2e2dSJohn Marino       else if (cache->pc != 0
1779cf7f2e2dSJohn Marino 	       || target_read_memory (get_frame_pc (this_frame), buf, 1))
17805796c8dcSSimon Schubert 	{
1781cf7f2e2dSJohn Marino 	  /* We're in a known function, but did not find a frame
1782cf7f2e2dSJohn Marino 	     setup.  Assume that the function does not use %ebp.
1783cf7f2e2dSJohn Marino 	     Alternatively, we may have jumped to an invalid
1784cf7f2e2dSJohn Marino 	     address; in that case there is definitely no new
1785cf7f2e2dSJohn Marino 	     frame in %ebp.  */
17865796c8dcSSimon Schubert 	  get_frame_register (this_frame, I386_ESP_REGNUM, buf);
17875796c8dcSSimon Schubert 	  cache->base = extract_unsigned_integer (buf, 4, byte_order)
17885796c8dcSSimon Schubert 			+ cache->sp_offset;
17895796c8dcSSimon Schubert 	}
1790cf7f2e2dSJohn Marino       else
1791cf7f2e2dSJohn Marino 	/* We're in an unknown function.  We could not find the start
1792cf7f2e2dSJohn Marino 	   of the function to analyze the prologue; our best option is
1793cf7f2e2dSJohn Marino 	   to assume a typical frame layout with the caller's %ebp
1794cf7f2e2dSJohn Marino 	   saved.  */
1795cf7f2e2dSJohn Marino 	cache->saved_regs[I386_EBP_REGNUM] = 0;
17965796c8dcSSimon Schubert     }
17975796c8dcSSimon Schubert 
1798c50c785cSJohn Marino   if (cache->saved_sp_reg != -1)
1799c50c785cSJohn Marino     {
1800c50c785cSJohn Marino       /* Saved stack pointer has been saved (but the SAVED_SP_REG
1801c50c785cSJohn Marino 	 register may be unavailable).  */
1802c50c785cSJohn Marino       if (cache->saved_sp == 0
1803*ef5ccd6cSJohn Marino 	  && deprecated_frame_register_read (this_frame,
1804*ef5ccd6cSJohn Marino 					     cache->saved_sp_reg, buf))
1805c50c785cSJohn Marino 	cache->saved_sp = extract_unsigned_integer (buf, 4, byte_order);
1806c50c785cSJohn Marino     }
18075796c8dcSSimon Schubert   /* Now that we have the base address for the stack frame we can
18085796c8dcSSimon Schubert      calculate the value of %esp in the calling frame.  */
1809c50c785cSJohn Marino   else if (cache->saved_sp == 0)
18105796c8dcSSimon Schubert     cache->saved_sp = cache->base + 8;
18115796c8dcSSimon Schubert 
18125796c8dcSSimon Schubert   /* Adjust all the saved registers such that they contain addresses
18135796c8dcSSimon Schubert      instead of offsets.  */
18145796c8dcSSimon Schubert   for (i = 0; i < I386_NUM_SAVED_REGS; i++)
18155796c8dcSSimon Schubert     if (cache->saved_regs[i] != -1)
18165796c8dcSSimon Schubert       cache->saved_regs[i] += cache->base;
18175796c8dcSSimon Schubert 
1818c50c785cSJohn Marino   cache->base_p = 1;
1819c50c785cSJohn Marino }
1820c50c785cSJohn Marino 
1821c50c785cSJohn Marino static struct i386_frame_cache *
i386_frame_cache(struct frame_info * this_frame,void ** this_cache)1822c50c785cSJohn Marino i386_frame_cache (struct frame_info *this_frame, void **this_cache)
1823c50c785cSJohn Marino {
1824c50c785cSJohn Marino   volatile struct gdb_exception ex;
1825c50c785cSJohn Marino   struct i386_frame_cache *cache;
1826c50c785cSJohn Marino 
1827c50c785cSJohn Marino   if (*this_cache)
1828c50c785cSJohn Marino     return *this_cache;
1829c50c785cSJohn Marino 
1830c50c785cSJohn Marino   cache = i386_alloc_frame_cache ();
1831c50c785cSJohn Marino   *this_cache = cache;
1832c50c785cSJohn Marino 
1833c50c785cSJohn Marino   TRY_CATCH (ex, RETURN_MASK_ERROR)
1834c50c785cSJohn Marino     {
1835c50c785cSJohn Marino       i386_frame_cache_1 (this_frame, cache);
1836c50c785cSJohn Marino     }
1837c50c785cSJohn Marino   if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
1838c50c785cSJohn Marino     throw_exception (ex);
1839c50c785cSJohn Marino 
18405796c8dcSSimon Schubert   return cache;
18415796c8dcSSimon Schubert }
18425796c8dcSSimon Schubert 
18435796c8dcSSimon Schubert static void
i386_frame_this_id(struct frame_info * this_frame,void ** this_cache,struct frame_id * this_id)18445796c8dcSSimon Schubert i386_frame_this_id (struct frame_info *this_frame, void **this_cache,
18455796c8dcSSimon Schubert 		    struct frame_id *this_id)
18465796c8dcSSimon Schubert {
18475796c8dcSSimon Schubert   struct i386_frame_cache *cache = i386_frame_cache (this_frame, this_cache);
18485796c8dcSSimon Schubert 
18495796c8dcSSimon Schubert   /* This marks the outermost frame.  */
18505796c8dcSSimon Schubert   if (cache->base == 0)
18515796c8dcSSimon Schubert     return;
18525796c8dcSSimon Schubert 
18535796c8dcSSimon Schubert   /* See the end of i386_push_dummy_call.  */
18545796c8dcSSimon Schubert   (*this_id) = frame_id_build (cache->base + 8, cache->pc);
18555796c8dcSSimon Schubert }
18565796c8dcSSimon Schubert 
1857c50c785cSJohn Marino static enum unwind_stop_reason
i386_frame_unwind_stop_reason(struct frame_info * this_frame,void ** this_cache)1858c50c785cSJohn Marino i386_frame_unwind_stop_reason (struct frame_info *this_frame,
1859c50c785cSJohn Marino 			       void **this_cache)
1860c50c785cSJohn Marino {
1861c50c785cSJohn Marino   struct i386_frame_cache *cache = i386_frame_cache (this_frame, this_cache);
1862c50c785cSJohn Marino 
1863c50c785cSJohn Marino   if (!cache->base_p)
1864c50c785cSJohn Marino     return UNWIND_UNAVAILABLE;
1865c50c785cSJohn Marino 
1866c50c785cSJohn Marino   /* This marks the outermost frame.  */
1867c50c785cSJohn Marino   if (cache->base == 0)
1868c50c785cSJohn Marino     return UNWIND_OUTERMOST;
1869c50c785cSJohn Marino 
1870c50c785cSJohn Marino   return UNWIND_NO_REASON;
1871c50c785cSJohn Marino }
1872c50c785cSJohn Marino 
18735796c8dcSSimon Schubert static struct value *
i386_frame_prev_register(struct frame_info * this_frame,void ** this_cache,int regnum)18745796c8dcSSimon Schubert i386_frame_prev_register (struct frame_info *this_frame, void **this_cache,
18755796c8dcSSimon Schubert 			  int regnum)
18765796c8dcSSimon Schubert {
18775796c8dcSSimon Schubert   struct i386_frame_cache *cache = i386_frame_cache (this_frame, this_cache);
18785796c8dcSSimon Schubert 
18795796c8dcSSimon Schubert   gdb_assert (regnum >= 0);
18805796c8dcSSimon Schubert 
18815796c8dcSSimon Schubert   /* The System V ABI says that:
18825796c8dcSSimon Schubert 
18835796c8dcSSimon Schubert      "The flags register contains the system flags, such as the
18845796c8dcSSimon Schubert      direction flag and the carry flag.  The direction flag must be
18855796c8dcSSimon Schubert      set to the forward (that is, zero) direction before entry and
18865796c8dcSSimon Schubert      upon exit from a function.  Other user flags have no specified
18875796c8dcSSimon Schubert      role in the standard calling sequence and are not preserved."
18885796c8dcSSimon Schubert 
18895796c8dcSSimon Schubert      To guarantee the "upon exit" part of that statement we fake a
18905796c8dcSSimon Schubert      saved flags register that has its direction flag cleared.
18915796c8dcSSimon Schubert 
18925796c8dcSSimon Schubert      Note that GCC doesn't seem to rely on the fact that the direction
18935796c8dcSSimon Schubert      flag is cleared after a function return; it always explicitly
18945796c8dcSSimon Schubert      clears the flag before operations where it matters.
18955796c8dcSSimon Schubert 
18965796c8dcSSimon Schubert      FIXME: kettenis/20030316: I'm not quite sure whether this is the
18975796c8dcSSimon Schubert      right thing to do.  The way we fake the flags register here makes
18985796c8dcSSimon Schubert      it impossible to change it.  */
18995796c8dcSSimon Schubert 
19005796c8dcSSimon Schubert   if (regnum == I386_EFLAGS_REGNUM)
19015796c8dcSSimon Schubert     {
19025796c8dcSSimon Schubert       ULONGEST val;
19035796c8dcSSimon Schubert 
19045796c8dcSSimon Schubert       val = get_frame_register_unsigned (this_frame, regnum);
19055796c8dcSSimon Schubert       val &= ~(1 << 10);
19065796c8dcSSimon Schubert       return frame_unwind_got_constant (this_frame, regnum, val);
19075796c8dcSSimon Schubert     }
19085796c8dcSSimon Schubert 
19095796c8dcSSimon Schubert   if (regnum == I386_EIP_REGNUM && cache->pc_in_eax)
19105796c8dcSSimon Schubert     return frame_unwind_got_register (this_frame, regnum, I386_EAX_REGNUM);
19115796c8dcSSimon Schubert 
1912c50c785cSJohn Marino   if (regnum == I386_ESP_REGNUM
1913c50c785cSJohn Marino       && (cache->saved_sp != 0 || cache->saved_sp_reg != -1))
1914c50c785cSJohn Marino     {
1915c50c785cSJohn Marino       /* If the SP has been saved, but we don't know where, then this
1916c50c785cSJohn Marino 	 means that SAVED_SP_REG register was found unavailable back
1917c50c785cSJohn Marino 	 when we built the cache.  */
1918c50c785cSJohn Marino       if (cache->saved_sp == 0)
1919c50c785cSJohn Marino 	return frame_unwind_got_register (this_frame, regnum,
1920c50c785cSJohn Marino 					  cache->saved_sp_reg);
1921c50c785cSJohn Marino       else
1922c50c785cSJohn Marino 	return frame_unwind_got_constant (this_frame, regnum,
1923c50c785cSJohn Marino 					  cache->saved_sp);
1924c50c785cSJohn Marino     }
19255796c8dcSSimon Schubert 
19265796c8dcSSimon Schubert   if (regnum < I386_NUM_SAVED_REGS && cache->saved_regs[regnum] != -1)
19275796c8dcSSimon Schubert     return frame_unwind_got_memory (this_frame, regnum,
19285796c8dcSSimon Schubert 				    cache->saved_regs[regnum]);
19295796c8dcSSimon Schubert 
19305796c8dcSSimon Schubert   return frame_unwind_got_register (this_frame, regnum, regnum);
19315796c8dcSSimon Schubert }
19325796c8dcSSimon Schubert 
19335796c8dcSSimon Schubert static const struct frame_unwind i386_frame_unwind =
19345796c8dcSSimon Schubert {
19355796c8dcSSimon Schubert   NORMAL_FRAME,
1936c50c785cSJohn Marino   i386_frame_unwind_stop_reason,
19375796c8dcSSimon Schubert   i386_frame_this_id,
19385796c8dcSSimon Schubert   i386_frame_prev_register,
19395796c8dcSSimon Schubert   NULL,
19405796c8dcSSimon Schubert   default_frame_sniffer
19415796c8dcSSimon Schubert };
19425796c8dcSSimon Schubert 
19435796c8dcSSimon Schubert /* Normal frames, but in a function epilogue.  */
19445796c8dcSSimon Schubert 
19455796c8dcSSimon Schubert /* The epilogue is defined here as the 'ret' instruction, which will
19465796c8dcSSimon Schubert    follow any instruction such as 'leave' or 'pop %ebp' that destroys
19475796c8dcSSimon Schubert    the function's stack frame.  */
19485796c8dcSSimon Schubert 
19495796c8dcSSimon Schubert static int
i386_in_function_epilogue_p(struct gdbarch * gdbarch,CORE_ADDR pc)19505796c8dcSSimon Schubert i386_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
19515796c8dcSSimon Schubert {
19525796c8dcSSimon Schubert   gdb_byte insn;
1953a45ae5f8SJohn Marino   struct symtab *symtab;
1954a45ae5f8SJohn Marino 
1955a45ae5f8SJohn Marino   symtab = find_pc_symtab (pc);
1956a45ae5f8SJohn Marino   if (symtab && symtab->epilogue_unwind_valid)
1957a45ae5f8SJohn Marino     return 0;
19585796c8dcSSimon Schubert 
19595796c8dcSSimon Schubert   if (target_read_memory (pc, &insn, 1))
19605796c8dcSSimon Schubert     return 0;	/* Can't read memory at pc.  */
19615796c8dcSSimon Schubert 
19625796c8dcSSimon Schubert   if (insn != 0xc3)	/* 'ret' instruction.  */
19635796c8dcSSimon Schubert     return 0;
19645796c8dcSSimon Schubert 
19655796c8dcSSimon Schubert   return 1;
19665796c8dcSSimon Schubert }
19675796c8dcSSimon Schubert 
19685796c8dcSSimon Schubert static int
i386_epilogue_frame_sniffer(const struct frame_unwind * self,struct frame_info * this_frame,void ** this_prologue_cache)19695796c8dcSSimon Schubert i386_epilogue_frame_sniffer (const struct frame_unwind *self,
19705796c8dcSSimon Schubert 			     struct frame_info *this_frame,
19715796c8dcSSimon Schubert 			     void **this_prologue_cache)
19725796c8dcSSimon Schubert {
19735796c8dcSSimon Schubert   if (frame_relative_level (this_frame) == 0)
19745796c8dcSSimon Schubert     return i386_in_function_epilogue_p (get_frame_arch (this_frame),
19755796c8dcSSimon Schubert 					get_frame_pc (this_frame));
19765796c8dcSSimon Schubert   else
19775796c8dcSSimon Schubert     return 0;
19785796c8dcSSimon Schubert }
19795796c8dcSSimon Schubert 
19805796c8dcSSimon Schubert static struct i386_frame_cache *
i386_epilogue_frame_cache(struct frame_info * this_frame,void ** this_cache)19815796c8dcSSimon Schubert i386_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache)
19825796c8dcSSimon Schubert {
1983c50c785cSJohn Marino   volatile struct gdb_exception ex;
19845796c8dcSSimon Schubert   struct i386_frame_cache *cache;
1985a45ae5f8SJohn Marino   CORE_ADDR sp;
19865796c8dcSSimon Schubert 
19875796c8dcSSimon Schubert   if (*this_cache)
19885796c8dcSSimon Schubert     return *this_cache;
19895796c8dcSSimon Schubert 
19905796c8dcSSimon Schubert   cache = i386_alloc_frame_cache ();
19915796c8dcSSimon Schubert   *this_cache = cache;
19925796c8dcSSimon Schubert 
1993c50c785cSJohn Marino   TRY_CATCH (ex, RETURN_MASK_ERROR)
1994c50c785cSJohn Marino     {
1995a45ae5f8SJohn Marino       cache->pc = get_frame_func (this_frame);
19965796c8dcSSimon Schubert 
1997a45ae5f8SJohn Marino       /* At this point the stack looks as if we just entered the
1998a45ae5f8SJohn Marino 	 function, with the return address at the top of the
1999a45ae5f8SJohn Marino 	 stack.  */
2000a45ae5f8SJohn Marino       sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM);
2001a45ae5f8SJohn Marino       cache->base = sp + cache->sp_offset;
20025796c8dcSSimon Schubert       cache->saved_sp = cache->base + 8;
20035796c8dcSSimon Schubert       cache->saved_regs[I386_EIP_REGNUM] = cache->base + 4;
20045796c8dcSSimon Schubert 
2005c50c785cSJohn Marino       cache->base_p = 1;
2006c50c785cSJohn Marino     }
2007c50c785cSJohn Marino   if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
2008c50c785cSJohn Marino     throw_exception (ex);
2009c50c785cSJohn Marino 
20105796c8dcSSimon Schubert   return cache;
20115796c8dcSSimon Schubert }
20125796c8dcSSimon Schubert 
2013c50c785cSJohn Marino static enum unwind_stop_reason
i386_epilogue_frame_unwind_stop_reason(struct frame_info * this_frame,void ** this_cache)2014c50c785cSJohn Marino i386_epilogue_frame_unwind_stop_reason (struct frame_info *this_frame,
2015c50c785cSJohn Marino 					void **this_cache)
2016c50c785cSJohn Marino {
2017a45ae5f8SJohn Marino   struct i386_frame_cache *cache =
2018a45ae5f8SJohn Marino     i386_epilogue_frame_cache (this_frame, this_cache);
2019c50c785cSJohn Marino 
2020c50c785cSJohn Marino   if (!cache->base_p)
2021c50c785cSJohn Marino     return UNWIND_UNAVAILABLE;
2022c50c785cSJohn Marino 
2023c50c785cSJohn Marino   return UNWIND_NO_REASON;
2024c50c785cSJohn Marino }
2025c50c785cSJohn Marino 
20265796c8dcSSimon Schubert static void
i386_epilogue_frame_this_id(struct frame_info * this_frame,void ** this_cache,struct frame_id * this_id)20275796c8dcSSimon Schubert i386_epilogue_frame_this_id (struct frame_info *this_frame,
20285796c8dcSSimon Schubert 			     void **this_cache,
20295796c8dcSSimon Schubert 			     struct frame_id *this_id)
20305796c8dcSSimon Schubert {
2031a45ae5f8SJohn Marino   struct i386_frame_cache *cache =
2032a45ae5f8SJohn Marino     i386_epilogue_frame_cache (this_frame, this_cache);
20335796c8dcSSimon Schubert 
2034c50c785cSJohn Marino   if (!cache->base_p)
2035c50c785cSJohn Marino     return;
2036c50c785cSJohn Marino 
20375796c8dcSSimon Schubert   (*this_id) = frame_id_build (cache->base + 8, cache->pc);
20385796c8dcSSimon Schubert }
20395796c8dcSSimon Schubert 
2040a45ae5f8SJohn Marino static struct value *
i386_epilogue_frame_prev_register(struct frame_info * this_frame,void ** this_cache,int regnum)2041a45ae5f8SJohn Marino i386_epilogue_frame_prev_register (struct frame_info *this_frame,
2042a45ae5f8SJohn Marino 				   void **this_cache, int regnum)
2043a45ae5f8SJohn Marino {
2044a45ae5f8SJohn Marino   /* Make sure we've initialized the cache.  */
2045a45ae5f8SJohn Marino   i386_epilogue_frame_cache (this_frame, this_cache);
2046a45ae5f8SJohn Marino 
2047a45ae5f8SJohn Marino   return i386_frame_prev_register (this_frame, this_cache, regnum);
2048a45ae5f8SJohn Marino }
2049a45ae5f8SJohn Marino 
20505796c8dcSSimon Schubert static const struct frame_unwind i386_epilogue_frame_unwind =
20515796c8dcSSimon Schubert {
20525796c8dcSSimon Schubert   NORMAL_FRAME,
2053c50c785cSJohn Marino   i386_epilogue_frame_unwind_stop_reason,
20545796c8dcSSimon Schubert   i386_epilogue_frame_this_id,
2055a45ae5f8SJohn Marino   i386_epilogue_frame_prev_register,
20565796c8dcSSimon Schubert   NULL,
20575796c8dcSSimon Schubert   i386_epilogue_frame_sniffer
20585796c8dcSSimon Schubert };
20595796c8dcSSimon Schubert 
20605796c8dcSSimon Schubert 
2061a45ae5f8SJohn Marino /* Stack-based trampolines.  */
2062a45ae5f8SJohn Marino 
2063a45ae5f8SJohn Marino /* These trampolines are used on cross x86 targets, when taking the
2064a45ae5f8SJohn Marino    address of a nested function.  When executing these trampolines,
2065a45ae5f8SJohn Marino    no stack frame is set up, so we are in a similar situation as in
2066a45ae5f8SJohn Marino    epilogues and i386_epilogue_frame_this_id can be re-used.  */
2067a45ae5f8SJohn Marino 
2068a45ae5f8SJohn Marino /* Static chain passed in register.  */
2069a45ae5f8SJohn Marino 
2070a45ae5f8SJohn Marino struct i386_insn i386_tramp_chain_in_reg_insns[] =
2071a45ae5f8SJohn Marino {
2072a45ae5f8SJohn Marino   /* `movl imm32, %eax' and `movl imm32, %ecx' */
2073a45ae5f8SJohn Marino   { 5, { 0xb8 }, { 0xfe } },
2074a45ae5f8SJohn Marino 
2075a45ae5f8SJohn Marino   /* `jmp imm32' */
2076a45ae5f8SJohn Marino   { 5, { 0xe9 }, { 0xff } },
2077a45ae5f8SJohn Marino 
2078a45ae5f8SJohn Marino   {0}
2079a45ae5f8SJohn Marino };
2080a45ae5f8SJohn Marino 
2081a45ae5f8SJohn Marino /* Static chain passed on stack (when regparm=3).  */
2082a45ae5f8SJohn Marino 
2083a45ae5f8SJohn Marino struct i386_insn i386_tramp_chain_on_stack_insns[] =
2084a45ae5f8SJohn Marino {
2085a45ae5f8SJohn Marino   /* `push imm32' */
2086a45ae5f8SJohn Marino   { 5, { 0x68 }, { 0xff } },
2087a45ae5f8SJohn Marino 
2088a45ae5f8SJohn Marino   /* `jmp imm32' */
2089a45ae5f8SJohn Marino   { 5, { 0xe9 }, { 0xff } },
2090a45ae5f8SJohn Marino 
2091a45ae5f8SJohn Marino   {0}
2092a45ae5f8SJohn Marino };
2093a45ae5f8SJohn Marino 
2094a45ae5f8SJohn Marino /* Return whether PC points inside a stack trampoline.   */
2095a45ae5f8SJohn Marino 
2096a45ae5f8SJohn Marino static int
i386_in_stack_tramp_p(struct gdbarch * gdbarch,CORE_ADDR pc)2097a45ae5f8SJohn Marino i386_in_stack_tramp_p (struct gdbarch *gdbarch, CORE_ADDR pc)
2098a45ae5f8SJohn Marino {
2099a45ae5f8SJohn Marino   gdb_byte insn;
2100*ef5ccd6cSJohn Marino   const char *name;
2101a45ae5f8SJohn Marino 
2102a45ae5f8SJohn Marino   /* A stack trampoline is detected if no name is associated
2103a45ae5f8SJohn Marino     to the current pc and if it points inside a trampoline
2104a45ae5f8SJohn Marino     sequence.  */
2105a45ae5f8SJohn Marino 
2106a45ae5f8SJohn Marino   find_pc_partial_function (pc, &name, NULL, NULL);
2107a45ae5f8SJohn Marino   if (name)
2108a45ae5f8SJohn Marino     return 0;
2109a45ae5f8SJohn Marino 
2110a45ae5f8SJohn Marino   if (target_read_memory (pc, &insn, 1))
2111a45ae5f8SJohn Marino     return 0;
2112a45ae5f8SJohn Marino 
2113a45ae5f8SJohn Marino   if (!i386_match_insn_block (pc, i386_tramp_chain_in_reg_insns)
2114a45ae5f8SJohn Marino       && !i386_match_insn_block (pc, i386_tramp_chain_on_stack_insns))
2115a45ae5f8SJohn Marino     return 0;
2116a45ae5f8SJohn Marino 
2117a45ae5f8SJohn Marino   return 1;
2118a45ae5f8SJohn Marino }
2119a45ae5f8SJohn Marino 
2120a45ae5f8SJohn Marino static int
i386_stack_tramp_frame_sniffer(const struct frame_unwind * self,struct frame_info * this_frame,void ** this_cache)2121a45ae5f8SJohn Marino i386_stack_tramp_frame_sniffer (const struct frame_unwind *self,
2122a45ae5f8SJohn Marino 				struct frame_info *this_frame,
2123a45ae5f8SJohn Marino 				void **this_cache)
2124a45ae5f8SJohn Marino {
2125a45ae5f8SJohn Marino   if (frame_relative_level (this_frame) == 0)
2126a45ae5f8SJohn Marino     return i386_in_stack_tramp_p (get_frame_arch (this_frame),
2127a45ae5f8SJohn Marino 				  get_frame_pc (this_frame));
2128a45ae5f8SJohn Marino   else
2129a45ae5f8SJohn Marino     return 0;
2130a45ae5f8SJohn Marino }
2131a45ae5f8SJohn Marino 
2132a45ae5f8SJohn Marino static const struct frame_unwind i386_stack_tramp_frame_unwind =
2133a45ae5f8SJohn Marino {
2134a45ae5f8SJohn Marino   NORMAL_FRAME,
2135a45ae5f8SJohn Marino   i386_epilogue_frame_unwind_stop_reason,
2136a45ae5f8SJohn Marino   i386_epilogue_frame_this_id,
2137a45ae5f8SJohn Marino   i386_epilogue_frame_prev_register,
2138a45ae5f8SJohn Marino   NULL,
2139a45ae5f8SJohn Marino   i386_stack_tramp_frame_sniffer
2140a45ae5f8SJohn Marino };
2141a45ae5f8SJohn Marino 
2142a45ae5f8SJohn Marino /* Generate a bytecode expression to get the value of the saved PC.  */
2143a45ae5f8SJohn Marino 
2144a45ae5f8SJohn Marino static void
i386_gen_return_address(struct gdbarch * gdbarch,struct agent_expr * ax,struct axs_value * value,CORE_ADDR scope)2145a45ae5f8SJohn Marino i386_gen_return_address (struct gdbarch *gdbarch,
2146a45ae5f8SJohn Marino 			 struct agent_expr *ax, struct axs_value *value,
2147a45ae5f8SJohn Marino 			 CORE_ADDR scope)
2148a45ae5f8SJohn Marino {
2149a45ae5f8SJohn Marino   /* The following sequence assumes the traditional use of the base
2150a45ae5f8SJohn Marino      register.  */
2151a45ae5f8SJohn Marino   ax_reg (ax, I386_EBP_REGNUM);
2152a45ae5f8SJohn Marino   ax_const_l (ax, 4);
2153a45ae5f8SJohn Marino   ax_simple (ax, aop_add);
2154a45ae5f8SJohn Marino   value->type = register_type (gdbarch, I386_EIP_REGNUM);
2155a45ae5f8SJohn Marino   value->kind = axs_lvalue_memory;
2156a45ae5f8SJohn Marino }
2157a45ae5f8SJohn Marino 
2158a45ae5f8SJohn Marino 
21595796c8dcSSimon Schubert /* Signal trampolines.  */
21605796c8dcSSimon Schubert 
21615796c8dcSSimon Schubert static struct i386_frame_cache *
i386_sigtramp_frame_cache(struct frame_info * this_frame,void ** this_cache)21625796c8dcSSimon Schubert i386_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache)
21635796c8dcSSimon Schubert {
21645796c8dcSSimon Schubert   struct gdbarch *gdbarch = get_frame_arch (this_frame);
21655796c8dcSSimon Schubert   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
21665796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
2167c50c785cSJohn Marino   volatile struct gdb_exception ex;
21685796c8dcSSimon Schubert   struct i386_frame_cache *cache;
21695796c8dcSSimon Schubert   CORE_ADDR addr;
21705796c8dcSSimon Schubert   gdb_byte buf[4];
21715796c8dcSSimon Schubert 
21725796c8dcSSimon Schubert   if (*this_cache)
21735796c8dcSSimon Schubert     return *this_cache;
21745796c8dcSSimon Schubert 
21755796c8dcSSimon Schubert   cache = i386_alloc_frame_cache ();
21765796c8dcSSimon Schubert 
2177c50c785cSJohn Marino   TRY_CATCH (ex, RETURN_MASK_ERROR)
2178c50c785cSJohn Marino     {
21795796c8dcSSimon Schubert       get_frame_register (this_frame, I386_ESP_REGNUM, buf);
21805796c8dcSSimon Schubert       cache->base = extract_unsigned_integer (buf, 4, byte_order) - 4;
21815796c8dcSSimon Schubert 
21825796c8dcSSimon Schubert       addr = tdep->sigcontext_addr (this_frame);
21835796c8dcSSimon Schubert       if (tdep->sc_reg_offset)
21845796c8dcSSimon Schubert 	{
21855796c8dcSSimon Schubert 	  int i;
21865796c8dcSSimon Schubert 
21875796c8dcSSimon Schubert 	  gdb_assert (tdep->sc_num_regs <= I386_NUM_SAVED_REGS);
21885796c8dcSSimon Schubert 
21895796c8dcSSimon Schubert 	  for (i = 0; i < tdep->sc_num_regs; i++)
21905796c8dcSSimon Schubert 	    if (tdep->sc_reg_offset[i] != -1)
21915796c8dcSSimon Schubert 	      cache->saved_regs[i] = addr + tdep->sc_reg_offset[i];
21925796c8dcSSimon Schubert 	}
21935796c8dcSSimon Schubert       else
21945796c8dcSSimon Schubert 	{
21955796c8dcSSimon Schubert 	  cache->saved_regs[I386_EIP_REGNUM] = addr + tdep->sc_pc_offset;
21965796c8dcSSimon Schubert 	  cache->saved_regs[I386_ESP_REGNUM] = addr + tdep->sc_sp_offset;
21975796c8dcSSimon Schubert 	}
21985796c8dcSSimon Schubert 
2199c50c785cSJohn Marino       cache->base_p = 1;
2200c50c785cSJohn Marino     }
2201c50c785cSJohn Marino   if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
2202c50c785cSJohn Marino     throw_exception (ex);
2203c50c785cSJohn Marino 
22045796c8dcSSimon Schubert   *this_cache = cache;
22055796c8dcSSimon Schubert   return cache;
22065796c8dcSSimon Schubert }
22075796c8dcSSimon Schubert 
2208c50c785cSJohn Marino static enum unwind_stop_reason
i386_sigtramp_frame_unwind_stop_reason(struct frame_info * this_frame,void ** this_cache)2209c50c785cSJohn Marino i386_sigtramp_frame_unwind_stop_reason (struct frame_info *this_frame,
2210c50c785cSJohn Marino 					void **this_cache)
2211c50c785cSJohn Marino {
2212c50c785cSJohn Marino   struct i386_frame_cache *cache =
2213c50c785cSJohn Marino     i386_sigtramp_frame_cache (this_frame, this_cache);
2214c50c785cSJohn Marino 
2215c50c785cSJohn Marino   if (!cache->base_p)
2216c50c785cSJohn Marino     return UNWIND_UNAVAILABLE;
2217c50c785cSJohn Marino 
2218c50c785cSJohn Marino   return UNWIND_NO_REASON;
2219c50c785cSJohn Marino }
2220c50c785cSJohn Marino 
22215796c8dcSSimon Schubert static void
i386_sigtramp_frame_this_id(struct frame_info * this_frame,void ** this_cache,struct frame_id * this_id)22225796c8dcSSimon Schubert i386_sigtramp_frame_this_id (struct frame_info *this_frame, void **this_cache,
22235796c8dcSSimon Schubert 			     struct frame_id *this_id)
22245796c8dcSSimon Schubert {
22255796c8dcSSimon Schubert   struct i386_frame_cache *cache =
22265796c8dcSSimon Schubert     i386_sigtramp_frame_cache (this_frame, this_cache);
22275796c8dcSSimon Schubert 
2228c50c785cSJohn Marino   if (!cache->base_p)
2229c50c785cSJohn Marino     return;
2230c50c785cSJohn Marino 
22315796c8dcSSimon Schubert   /* See the end of i386_push_dummy_call.  */
22325796c8dcSSimon Schubert   (*this_id) = frame_id_build (cache->base + 8, get_frame_pc (this_frame));
22335796c8dcSSimon Schubert }
22345796c8dcSSimon Schubert 
22355796c8dcSSimon Schubert static struct value *
i386_sigtramp_frame_prev_register(struct frame_info * this_frame,void ** this_cache,int regnum)22365796c8dcSSimon Schubert i386_sigtramp_frame_prev_register (struct frame_info *this_frame,
22375796c8dcSSimon Schubert 				   void **this_cache, int regnum)
22385796c8dcSSimon Schubert {
22395796c8dcSSimon Schubert   /* Make sure we've initialized the cache.  */
22405796c8dcSSimon Schubert   i386_sigtramp_frame_cache (this_frame, this_cache);
22415796c8dcSSimon Schubert 
22425796c8dcSSimon Schubert   return i386_frame_prev_register (this_frame, this_cache, regnum);
22435796c8dcSSimon Schubert }
22445796c8dcSSimon Schubert 
22455796c8dcSSimon Schubert static int
i386_sigtramp_frame_sniffer(const struct frame_unwind * self,struct frame_info * this_frame,void ** this_prologue_cache)22465796c8dcSSimon Schubert i386_sigtramp_frame_sniffer (const struct frame_unwind *self,
22475796c8dcSSimon Schubert 			     struct frame_info *this_frame,
22485796c8dcSSimon Schubert 			     void **this_prologue_cache)
22495796c8dcSSimon Schubert {
22505796c8dcSSimon Schubert   struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (this_frame));
22515796c8dcSSimon Schubert 
22525796c8dcSSimon Schubert   /* We shouldn't even bother if we don't have a sigcontext_addr
22535796c8dcSSimon Schubert      handler.  */
22545796c8dcSSimon Schubert   if (tdep->sigcontext_addr == NULL)
22555796c8dcSSimon Schubert     return 0;
22565796c8dcSSimon Schubert 
22575796c8dcSSimon Schubert   if (tdep->sigtramp_p != NULL)
22585796c8dcSSimon Schubert     {
22595796c8dcSSimon Schubert       if (tdep->sigtramp_p (this_frame))
22605796c8dcSSimon Schubert 	return 1;
22615796c8dcSSimon Schubert     }
22625796c8dcSSimon Schubert 
22635796c8dcSSimon Schubert   if (tdep->sigtramp_start != 0)
22645796c8dcSSimon Schubert     {
22655796c8dcSSimon Schubert       CORE_ADDR pc = get_frame_pc (this_frame);
22665796c8dcSSimon Schubert 
22675796c8dcSSimon Schubert       gdb_assert (tdep->sigtramp_end != 0);
22685796c8dcSSimon Schubert       if (pc >= tdep->sigtramp_start && pc < tdep->sigtramp_end)
22695796c8dcSSimon Schubert 	return 1;
22705796c8dcSSimon Schubert     }
22715796c8dcSSimon Schubert 
22725796c8dcSSimon Schubert   return 0;
22735796c8dcSSimon Schubert }
22745796c8dcSSimon Schubert 
22755796c8dcSSimon Schubert static const struct frame_unwind i386_sigtramp_frame_unwind =
22765796c8dcSSimon Schubert {
22775796c8dcSSimon Schubert   SIGTRAMP_FRAME,
2278c50c785cSJohn Marino   i386_sigtramp_frame_unwind_stop_reason,
22795796c8dcSSimon Schubert   i386_sigtramp_frame_this_id,
22805796c8dcSSimon Schubert   i386_sigtramp_frame_prev_register,
22815796c8dcSSimon Schubert   NULL,
22825796c8dcSSimon Schubert   i386_sigtramp_frame_sniffer
22835796c8dcSSimon Schubert };
22845796c8dcSSimon Schubert 
22855796c8dcSSimon Schubert 
22865796c8dcSSimon Schubert static CORE_ADDR
i386_frame_base_address(struct frame_info * this_frame,void ** this_cache)22875796c8dcSSimon Schubert i386_frame_base_address (struct frame_info *this_frame, void **this_cache)
22885796c8dcSSimon Schubert {
22895796c8dcSSimon Schubert   struct i386_frame_cache *cache = i386_frame_cache (this_frame, this_cache);
22905796c8dcSSimon Schubert 
22915796c8dcSSimon Schubert   return cache->base;
22925796c8dcSSimon Schubert }
22935796c8dcSSimon Schubert 
22945796c8dcSSimon Schubert static const struct frame_base i386_frame_base =
22955796c8dcSSimon Schubert {
22965796c8dcSSimon Schubert   &i386_frame_unwind,
22975796c8dcSSimon Schubert   i386_frame_base_address,
22985796c8dcSSimon Schubert   i386_frame_base_address,
22995796c8dcSSimon Schubert   i386_frame_base_address
23005796c8dcSSimon Schubert };
23015796c8dcSSimon Schubert 
23025796c8dcSSimon Schubert static struct frame_id
i386_dummy_id(struct gdbarch * gdbarch,struct frame_info * this_frame)23035796c8dcSSimon Schubert i386_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
23045796c8dcSSimon Schubert {
23055796c8dcSSimon Schubert   CORE_ADDR fp;
23065796c8dcSSimon Schubert 
23075796c8dcSSimon Schubert   fp = get_frame_register_unsigned (this_frame, I386_EBP_REGNUM);
23085796c8dcSSimon Schubert 
23095796c8dcSSimon Schubert   /* See the end of i386_push_dummy_call.  */
23105796c8dcSSimon Schubert   return frame_id_build (fp + 8, get_frame_pc (this_frame));
23115796c8dcSSimon Schubert }
2312a45ae5f8SJohn Marino 
2313a45ae5f8SJohn Marino /* _Decimal128 function return values need 16-byte alignment on the
2314a45ae5f8SJohn Marino    stack.  */
2315a45ae5f8SJohn Marino 
2316a45ae5f8SJohn Marino static CORE_ADDR
i386_frame_align(struct gdbarch * gdbarch,CORE_ADDR sp)2317a45ae5f8SJohn Marino i386_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
2318a45ae5f8SJohn Marino {
2319a45ae5f8SJohn Marino   return sp & -(CORE_ADDR)16;
2320a45ae5f8SJohn Marino }
23215796c8dcSSimon Schubert 
23225796c8dcSSimon Schubert 
23235796c8dcSSimon Schubert /* Figure out where the longjmp will land.  Slurp the args out of the
23245796c8dcSSimon Schubert    stack.  We expect the first arg to be a pointer to the jmp_buf
23255796c8dcSSimon Schubert    structure from which we extract the address that we will land at.
23265796c8dcSSimon Schubert    This address is copied into PC.  This routine returns non-zero on
23275796c8dcSSimon Schubert    success.  */
23285796c8dcSSimon Schubert 
23295796c8dcSSimon Schubert static int
i386_get_longjmp_target(struct frame_info * frame,CORE_ADDR * pc)23305796c8dcSSimon Schubert i386_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
23315796c8dcSSimon Schubert {
23325796c8dcSSimon Schubert   gdb_byte buf[4];
23335796c8dcSSimon Schubert   CORE_ADDR sp, jb_addr;
23345796c8dcSSimon Schubert   struct gdbarch *gdbarch = get_frame_arch (frame);
23355796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
23365796c8dcSSimon Schubert   int jb_pc_offset = gdbarch_tdep (gdbarch)->jb_pc_offset;
23375796c8dcSSimon Schubert 
23385796c8dcSSimon Schubert   /* If JB_PC_OFFSET is -1, we have no way to find out where the
23395796c8dcSSimon Schubert      longjmp will land.  */
23405796c8dcSSimon Schubert   if (jb_pc_offset == -1)
23415796c8dcSSimon Schubert     return 0;
23425796c8dcSSimon Schubert 
23435796c8dcSSimon Schubert   get_frame_register (frame, I386_ESP_REGNUM, buf);
23445796c8dcSSimon Schubert   sp = extract_unsigned_integer (buf, 4, byte_order);
23455796c8dcSSimon Schubert   if (target_read_memory (sp + 4, buf, 4))
23465796c8dcSSimon Schubert     return 0;
23475796c8dcSSimon Schubert 
23485796c8dcSSimon Schubert   jb_addr = extract_unsigned_integer (buf, 4, byte_order);
23495796c8dcSSimon Schubert   if (target_read_memory (jb_addr + jb_pc_offset, buf, 4))
23505796c8dcSSimon Schubert     return 0;
23515796c8dcSSimon Schubert 
23525796c8dcSSimon Schubert   *pc = extract_unsigned_integer (buf, 4, byte_order);
23535796c8dcSSimon Schubert   return 1;
23545796c8dcSSimon Schubert }
23555796c8dcSSimon Schubert 
23565796c8dcSSimon Schubert 
23575796c8dcSSimon Schubert /* Check whether TYPE must be 16-byte-aligned when passed as a
23585796c8dcSSimon Schubert    function argument.  16-byte vectors, _Decimal128 and structures or
23595796c8dcSSimon Schubert    unions containing such types must be 16-byte-aligned; other
23605796c8dcSSimon Schubert    arguments are 4-byte-aligned.  */
23615796c8dcSSimon Schubert 
23625796c8dcSSimon Schubert static int
i386_16_byte_align_p(struct type * type)23635796c8dcSSimon Schubert i386_16_byte_align_p (struct type *type)
23645796c8dcSSimon Schubert {
23655796c8dcSSimon Schubert   type = check_typedef (type);
23665796c8dcSSimon Schubert   if ((TYPE_CODE (type) == TYPE_CODE_DECFLOAT
23675796c8dcSSimon Schubert        || (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type)))
23685796c8dcSSimon Schubert       && TYPE_LENGTH (type) == 16)
23695796c8dcSSimon Schubert     return 1;
23705796c8dcSSimon Schubert   if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
23715796c8dcSSimon Schubert     return i386_16_byte_align_p (TYPE_TARGET_TYPE (type));
23725796c8dcSSimon Schubert   if (TYPE_CODE (type) == TYPE_CODE_STRUCT
23735796c8dcSSimon Schubert       || TYPE_CODE (type) == TYPE_CODE_UNION)
23745796c8dcSSimon Schubert     {
23755796c8dcSSimon Schubert       int i;
23765796c8dcSSimon Schubert       for (i = 0; i < TYPE_NFIELDS (type); i++)
23775796c8dcSSimon Schubert 	{
23785796c8dcSSimon Schubert 	  if (i386_16_byte_align_p (TYPE_FIELD_TYPE (type, i)))
23795796c8dcSSimon Schubert 	    return 1;
23805796c8dcSSimon Schubert 	}
23815796c8dcSSimon Schubert     }
23825796c8dcSSimon Schubert   return 0;
23835796c8dcSSimon Schubert }
23845796c8dcSSimon Schubert 
2385*ef5ccd6cSJohn Marino /* Implementation for set_gdbarch_push_dummy_code.  */
2386*ef5ccd6cSJohn Marino 
2387*ef5ccd6cSJohn Marino static CORE_ADDR
i386_push_dummy_code(struct gdbarch * gdbarch,CORE_ADDR sp,CORE_ADDR funaddr,struct value ** args,int nargs,struct type * value_type,CORE_ADDR * real_pc,CORE_ADDR * bp_addr,struct regcache * regcache)2388*ef5ccd6cSJohn Marino i386_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp, CORE_ADDR funaddr,
2389*ef5ccd6cSJohn Marino 		      struct value **args, int nargs, struct type *value_type,
2390*ef5ccd6cSJohn Marino 		      CORE_ADDR *real_pc, CORE_ADDR *bp_addr,
2391*ef5ccd6cSJohn Marino 		      struct regcache *regcache)
2392*ef5ccd6cSJohn Marino {
2393*ef5ccd6cSJohn Marino   /* Use 0xcc breakpoint - 1 byte.  */
2394*ef5ccd6cSJohn Marino   *bp_addr = sp - 1;
2395*ef5ccd6cSJohn Marino   *real_pc = funaddr;
2396*ef5ccd6cSJohn Marino 
2397*ef5ccd6cSJohn Marino   /* Keep the stack aligned.  */
2398*ef5ccd6cSJohn Marino   return sp - 16;
2399*ef5ccd6cSJohn Marino }
2400*ef5ccd6cSJohn Marino 
24015796c8dcSSimon Schubert static CORE_ADDR
i386_push_dummy_call(struct gdbarch * gdbarch,struct value * function,struct regcache * regcache,CORE_ADDR bp_addr,int nargs,struct value ** args,CORE_ADDR sp,int struct_return,CORE_ADDR struct_addr)24025796c8dcSSimon Schubert i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
24035796c8dcSSimon Schubert 		      struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
24045796c8dcSSimon Schubert 		      struct value **args, CORE_ADDR sp, int struct_return,
24055796c8dcSSimon Schubert 		      CORE_ADDR struct_addr)
24065796c8dcSSimon Schubert {
24075796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
24085796c8dcSSimon Schubert   gdb_byte buf[4];
24095796c8dcSSimon Schubert   int i;
24105796c8dcSSimon Schubert   int write_pass;
24115796c8dcSSimon Schubert   int args_space = 0;
24125796c8dcSSimon Schubert 
24135796c8dcSSimon Schubert   /* Determine the total space required for arguments and struct
24145796c8dcSSimon Schubert      return address in a first pass (allowing for 16-byte-aligned
24155796c8dcSSimon Schubert      arguments), then push arguments in a second pass.  */
24165796c8dcSSimon Schubert 
24175796c8dcSSimon Schubert   for (write_pass = 0; write_pass < 2; write_pass++)
24185796c8dcSSimon Schubert     {
24195796c8dcSSimon Schubert       int args_space_used = 0;
24205796c8dcSSimon Schubert 
24215796c8dcSSimon Schubert       if (struct_return)
24225796c8dcSSimon Schubert 	{
24235796c8dcSSimon Schubert 	  if (write_pass)
24245796c8dcSSimon Schubert 	    {
24255796c8dcSSimon Schubert 	      /* Push value address.  */
24265796c8dcSSimon Schubert 	      store_unsigned_integer (buf, 4, byte_order, struct_addr);
24275796c8dcSSimon Schubert 	      write_memory (sp, buf, 4);
24285796c8dcSSimon Schubert 	      args_space_used += 4;
24295796c8dcSSimon Schubert 	    }
24305796c8dcSSimon Schubert 	  else
24315796c8dcSSimon Schubert 	    args_space += 4;
24325796c8dcSSimon Schubert 	}
24335796c8dcSSimon Schubert 
24345796c8dcSSimon Schubert       for (i = 0; i < nargs; i++)
24355796c8dcSSimon Schubert 	{
24365796c8dcSSimon Schubert 	  int len = TYPE_LENGTH (value_enclosing_type (args[i]));
24375796c8dcSSimon Schubert 
24385796c8dcSSimon Schubert 	  if (write_pass)
24395796c8dcSSimon Schubert 	    {
24405796c8dcSSimon Schubert 	      if (i386_16_byte_align_p (value_enclosing_type (args[i])))
24415796c8dcSSimon Schubert 		args_space_used = align_up (args_space_used, 16);
24425796c8dcSSimon Schubert 
24435796c8dcSSimon Schubert 	      write_memory (sp + args_space_used,
24445796c8dcSSimon Schubert 			    value_contents_all (args[i]), len);
24455796c8dcSSimon Schubert 	      /* The System V ABI says that:
24465796c8dcSSimon Schubert 
24475796c8dcSSimon Schubert 	      "An argument's size is increased, if necessary, to make it a
24485796c8dcSSimon Schubert 	      multiple of [32-bit] words.  This may require tail padding,
24495796c8dcSSimon Schubert 	      depending on the size of the argument."
24505796c8dcSSimon Schubert 
24515796c8dcSSimon Schubert 	      This makes sure the stack stays word-aligned.  */
24525796c8dcSSimon Schubert 	      args_space_used += align_up (len, 4);
24535796c8dcSSimon Schubert 	    }
24545796c8dcSSimon Schubert 	  else
24555796c8dcSSimon Schubert 	    {
24565796c8dcSSimon Schubert 	      if (i386_16_byte_align_p (value_enclosing_type (args[i])))
24575796c8dcSSimon Schubert 		args_space = align_up (args_space, 16);
24585796c8dcSSimon Schubert 	      args_space += align_up (len, 4);
24595796c8dcSSimon Schubert 	    }
24605796c8dcSSimon Schubert 	}
24615796c8dcSSimon Schubert 
24625796c8dcSSimon Schubert       if (!write_pass)
24635796c8dcSSimon Schubert 	{
24645796c8dcSSimon Schubert 	  sp -= args_space;
2465*ef5ccd6cSJohn Marino 
2466*ef5ccd6cSJohn Marino 	  /* The original System V ABI only requires word alignment,
2467*ef5ccd6cSJohn Marino 	     but modern incarnations need 16-byte alignment in order
2468*ef5ccd6cSJohn Marino 	     to support SSE.  Since wasting a few bytes here isn't
2469*ef5ccd6cSJohn Marino 	     harmful we unconditionally enforce 16-byte alignment.  */
2470*ef5ccd6cSJohn Marino 	  sp &= ~0xf;
24715796c8dcSSimon Schubert 	}
24725796c8dcSSimon Schubert     }
24735796c8dcSSimon Schubert 
24745796c8dcSSimon Schubert   /* Store return address.  */
24755796c8dcSSimon Schubert   sp -= 4;
24765796c8dcSSimon Schubert   store_unsigned_integer (buf, 4, byte_order, bp_addr);
24775796c8dcSSimon Schubert   write_memory (sp, buf, 4);
24785796c8dcSSimon Schubert 
24795796c8dcSSimon Schubert   /* Finally, update the stack pointer...  */
24805796c8dcSSimon Schubert   store_unsigned_integer (buf, 4, byte_order, sp);
24815796c8dcSSimon Schubert   regcache_cooked_write (regcache, I386_ESP_REGNUM, buf);
24825796c8dcSSimon Schubert 
24835796c8dcSSimon Schubert   /* ...and fake a frame pointer.  */
24845796c8dcSSimon Schubert   regcache_cooked_write (regcache, I386_EBP_REGNUM, buf);
24855796c8dcSSimon Schubert 
24865796c8dcSSimon Schubert   /* MarkK wrote: This "+ 8" is all over the place:
24875796c8dcSSimon Schubert      (i386_frame_this_id, i386_sigtramp_frame_this_id,
24885796c8dcSSimon Schubert      i386_dummy_id).  It's there, since all frame unwinders for
24895796c8dcSSimon Schubert      a given target have to agree (within a certain margin) on the
24905796c8dcSSimon Schubert      definition of the stack address of a frame.  Otherwise frame id
24915796c8dcSSimon Schubert      comparison might not work correctly.  Since DWARF2/GCC uses the
24925796c8dcSSimon Schubert      stack address *before* the function call as a frame's CFA.  On
24935796c8dcSSimon Schubert      the i386, when %ebp is used as a frame pointer, the offset
24945796c8dcSSimon Schubert      between the contents %ebp and the CFA as defined by GCC.  */
24955796c8dcSSimon Schubert   return sp + 8;
24965796c8dcSSimon Schubert }
24975796c8dcSSimon Schubert 
24985796c8dcSSimon Schubert /* These registers are used for returning integers (and on some
24995796c8dcSSimon Schubert    targets also for returning `struct' and `union' values when their
25005796c8dcSSimon Schubert    size and alignment match an integer type).  */
25015796c8dcSSimon Schubert #define LOW_RETURN_REGNUM	I386_EAX_REGNUM /* %eax */
25025796c8dcSSimon Schubert #define HIGH_RETURN_REGNUM	I386_EDX_REGNUM /* %edx */
25035796c8dcSSimon Schubert 
25045796c8dcSSimon Schubert /* Read, for architecture GDBARCH, a function return value of TYPE
25055796c8dcSSimon Schubert    from REGCACHE, and copy that into VALBUF.  */
25065796c8dcSSimon Schubert 
25075796c8dcSSimon Schubert static void
i386_extract_return_value(struct gdbarch * gdbarch,struct type * type,struct regcache * regcache,gdb_byte * valbuf)25085796c8dcSSimon Schubert i386_extract_return_value (struct gdbarch *gdbarch, struct type *type,
25095796c8dcSSimon Schubert 			   struct regcache *regcache, gdb_byte *valbuf)
25105796c8dcSSimon Schubert {
25115796c8dcSSimon Schubert   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
25125796c8dcSSimon Schubert   int len = TYPE_LENGTH (type);
25135796c8dcSSimon Schubert   gdb_byte buf[I386_MAX_REGISTER_SIZE];
25145796c8dcSSimon Schubert 
25155796c8dcSSimon Schubert   if (TYPE_CODE (type) == TYPE_CODE_FLT)
25165796c8dcSSimon Schubert     {
25175796c8dcSSimon Schubert       if (tdep->st0_regnum < 0)
25185796c8dcSSimon Schubert 	{
25195796c8dcSSimon Schubert 	  warning (_("Cannot find floating-point return value."));
25205796c8dcSSimon Schubert 	  memset (valbuf, 0, len);
25215796c8dcSSimon Schubert 	  return;
25225796c8dcSSimon Schubert 	}
25235796c8dcSSimon Schubert 
25245796c8dcSSimon Schubert       /* Floating-point return values can be found in %st(0).  Convert
25255796c8dcSSimon Schubert 	 its contents to the desired type.  This is probably not
25265796c8dcSSimon Schubert 	 exactly how it would happen on the target itself, but it is
25275796c8dcSSimon Schubert 	 the best we can do.  */
25285796c8dcSSimon Schubert       regcache_raw_read (regcache, I386_ST0_REGNUM, buf);
25295796c8dcSSimon Schubert       convert_typed_floating (buf, i387_ext_type (gdbarch), valbuf, type);
25305796c8dcSSimon Schubert     }
25315796c8dcSSimon Schubert   else
25325796c8dcSSimon Schubert     {
25335796c8dcSSimon Schubert       int low_size = register_size (gdbarch, LOW_RETURN_REGNUM);
25345796c8dcSSimon Schubert       int high_size = register_size (gdbarch, HIGH_RETURN_REGNUM);
25355796c8dcSSimon Schubert 
25365796c8dcSSimon Schubert       if (len <= low_size)
25375796c8dcSSimon Schubert 	{
25385796c8dcSSimon Schubert 	  regcache_raw_read (regcache, LOW_RETURN_REGNUM, buf);
25395796c8dcSSimon Schubert 	  memcpy (valbuf, buf, len);
25405796c8dcSSimon Schubert 	}
25415796c8dcSSimon Schubert       else if (len <= (low_size + high_size))
25425796c8dcSSimon Schubert 	{
25435796c8dcSSimon Schubert 	  regcache_raw_read (regcache, LOW_RETURN_REGNUM, buf);
25445796c8dcSSimon Schubert 	  memcpy (valbuf, buf, low_size);
25455796c8dcSSimon Schubert 	  regcache_raw_read (regcache, HIGH_RETURN_REGNUM, buf);
25465796c8dcSSimon Schubert 	  memcpy (valbuf + low_size, buf, len - low_size);
25475796c8dcSSimon Schubert 	}
25485796c8dcSSimon Schubert       else
25495796c8dcSSimon Schubert 	internal_error (__FILE__, __LINE__,
2550c50c785cSJohn Marino 			_("Cannot extract return value of %d bytes long."),
2551c50c785cSJohn Marino 			len);
25525796c8dcSSimon Schubert     }
25535796c8dcSSimon Schubert }
25545796c8dcSSimon Schubert 
25555796c8dcSSimon Schubert /* Write, for architecture GDBARCH, a function return value of TYPE
25565796c8dcSSimon Schubert    from VALBUF into REGCACHE.  */
25575796c8dcSSimon Schubert 
25585796c8dcSSimon Schubert static void
i386_store_return_value(struct gdbarch * gdbarch,struct type * type,struct regcache * regcache,const gdb_byte * valbuf)25595796c8dcSSimon Schubert i386_store_return_value (struct gdbarch *gdbarch, struct type *type,
25605796c8dcSSimon Schubert 			 struct regcache *regcache, const gdb_byte *valbuf)
25615796c8dcSSimon Schubert {
25625796c8dcSSimon Schubert   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
25635796c8dcSSimon Schubert   int len = TYPE_LENGTH (type);
25645796c8dcSSimon Schubert 
25655796c8dcSSimon Schubert   if (TYPE_CODE (type) == TYPE_CODE_FLT)
25665796c8dcSSimon Schubert     {
25675796c8dcSSimon Schubert       ULONGEST fstat;
25685796c8dcSSimon Schubert       gdb_byte buf[I386_MAX_REGISTER_SIZE];
25695796c8dcSSimon Schubert 
25705796c8dcSSimon Schubert       if (tdep->st0_regnum < 0)
25715796c8dcSSimon Schubert 	{
25725796c8dcSSimon Schubert 	  warning (_("Cannot set floating-point return value."));
25735796c8dcSSimon Schubert 	  return;
25745796c8dcSSimon Schubert 	}
25755796c8dcSSimon Schubert 
25765796c8dcSSimon Schubert       /* Returning floating-point values is a bit tricky.  Apart from
25775796c8dcSSimon Schubert          storing the return value in %st(0), we have to simulate the
25785796c8dcSSimon Schubert          state of the FPU at function return point.  */
25795796c8dcSSimon Schubert 
25805796c8dcSSimon Schubert       /* Convert the value found in VALBUF to the extended
25815796c8dcSSimon Schubert 	 floating-point format used by the FPU.  This is probably
25825796c8dcSSimon Schubert 	 not exactly how it would happen on the target itself, but
25835796c8dcSSimon Schubert 	 it is the best we can do.  */
25845796c8dcSSimon Schubert       convert_typed_floating (valbuf, type, buf, i387_ext_type (gdbarch));
25855796c8dcSSimon Schubert       regcache_raw_write (regcache, I386_ST0_REGNUM, buf);
25865796c8dcSSimon Schubert 
25875796c8dcSSimon Schubert       /* Set the top of the floating-point register stack to 7.  The
25885796c8dcSSimon Schubert          actual value doesn't really matter, but 7 is what a normal
25895796c8dcSSimon Schubert          function return would end up with if the program started out
25905796c8dcSSimon Schubert          with a freshly initialized FPU.  */
25915796c8dcSSimon Schubert       regcache_raw_read_unsigned (regcache, I387_FSTAT_REGNUM (tdep), &fstat);
25925796c8dcSSimon Schubert       fstat |= (7 << 11);
25935796c8dcSSimon Schubert       regcache_raw_write_unsigned (regcache, I387_FSTAT_REGNUM (tdep), fstat);
25945796c8dcSSimon Schubert 
25955796c8dcSSimon Schubert       /* Mark %st(1) through %st(7) as empty.  Since we set the top of
25965796c8dcSSimon Schubert          the floating-point register stack to 7, the appropriate value
25975796c8dcSSimon Schubert          for the tag word is 0x3fff.  */
25985796c8dcSSimon Schubert       regcache_raw_write_unsigned (regcache, I387_FTAG_REGNUM (tdep), 0x3fff);
25995796c8dcSSimon Schubert     }
26005796c8dcSSimon Schubert   else
26015796c8dcSSimon Schubert     {
26025796c8dcSSimon Schubert       int low_size = register_size (gdbarch, LOW_RETURN_REGNUM);
26035796c8dcSSimon Schubert       int high_size = register_size (gdbarch, HIGH_RETURN_REGNUM);
26045796c8dcSSimon Schubert 
26055796c8dcSSimon Schubert       if (len <= low_size)
26065796c8dcSSimon Schubert 	regcache_raw_write_part (regcache, LOW_RETURN_REGNUM, 0, len, valbuf);
26075796c8dcSSimon Schubert       else if (len <= (low_size + high_size))
26085796c8dcSSimon Schubert 	{
26095796c8dcSSimon Schubert 	  regcache_raw_write (regcache, LOW_RETURN_REGNUM, valbuf);
26105796c8dcSSimon Schubert 	  regcache_raw_write_part (regcache, HIGH_RETURN_REGNUM, 0,
26115796c8dcSSimon Schubert 				   len - low_size, valbuf + low_size);
26125796c8dcSSimon Schubert 	}
26135796c8dcSSimon Schubert       else
26145796c8dcSSimon Schubert 	internal_error (__FILE__, __LINE__,
26155796c8dcSSimon Schubert 			_("Cannot store return value of %d bytes long."), len);
26165796c8dcSSimon Schubert     }
26175796c8dcSSimon Schubert }
26185796c8dcSSimon Schubert 
26195796c8dcSSimon Schubert 
26205796c8dcSSimon Schubert /* This is the variable that is set with "set struct-convention", and
26215796c8dcSSimon Schubert    its legitimate values.  */
26225796c8dcSSimon Schubert static const char default_struct_convention[] = "default";
26235796c8dcSSimon Schubert static const char pcc_struct_convention[] = "pcc";
26245796c8dcSSimon Schubert static const char reg_struct_convention[] = "reg";
2625*ef5ccd6cSJohn Marino static const char *const valid_conventions[] =
26265796c8dcSSimon Schubert {
26275796c8dcSSimon Schubert   default_struct_convention,
26285796c8dcSSimon Schubert   pcc_struct_convention,
26295796c8dcSSimon Schubert   reg_struct_convention,
26305796c8dcSSimon Schubert   NULL
26315796c8dcSSimon Schubert };
26325796c8dcSSimon Schubert static const char *struct_convention = default_struct_convention;
26335796c8dcSSimon Schubert 
26345796c8dcSSimon Schubert /* Return non-zero if TYPE, which is assumed to be a structure,
26355796c8dcSSimon Schubert    a union type, or an array type, should be returned in registers
26365796c8dcSSimon Schubert    for architecture GDBARCH.  */
26375796c8dcSSimon Schubert 
26385796c8dcSSimon Schubert static int
i386_reg_struct_return_p(struct gdbarch * gdbarch,struct type * type)26395796c8dcSSimon Schubert i386_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type)
26405796c8dcSSimon Schubert {
26415796c8dcSSimon Schubert   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
26425796c8dcSSimon Schubert   enum type_code code = TYPE_CODE (type);
26435796c8dcSSimon Schubert   int len = TYPE_LENGTH (type);
26445796c8dcSSimon Schubert 
26455796c8dcSSimon Schubert   gdb_assert (code == TYPE_CODE_STRUCT
26465796c8dcSSimon Schubert               || code == TYPE_CODE_UNION
26475796c8dcSSimon Schubert               || code == TYPE_CODE_ARRAY);
26485796c8dcSSimon Schubert 
26495796c8dcSSimon Schubert   if (struct_convention == pcc_struct_convention
26505796c8dcSSimon Schubert       || (struct_convention == default_struct_convention
26515796c8dcSSimon Schubert 	  && tdep->struct_return == pcc_struct_return))
26525796c8dcSSimon Schubert     return 0;
26535796c8dcSSimon Schubert 
26545796c8dcSSimon Schubert   /* Structures consisting of a single `float', `double' or 'long
26555796c8dcSSimon Schubert      double' member are returned in %st(0).  */
26565796c8dcSSimon Schubert   if (code == TYPE_CODE_STRUCT && TYPE_NFIELDS (type) == 1)
26575796c8dcSSimon Schubert     {
26585796c8dcSSimon Schubert       type = check_typedef (TYPE_FIELD_TYPE (type, 0));
26595796c8dcSSimon Schubert       if (TYPE_CODE (type) == TYPE_CODE_FLT)
26605796c8dcSSimon Schubert 	return (len == 4 || len == 8 || len == 12);
26615796c8dcSSimon Schubert     }
26625796c8dcSSimon Schubert 
26635796c8dcSSimon Schubert   return (len == 1 || len == 2 || len == 4 || len == 8);
26645796c8dcSSimon Schubert }
26655796c8dcSSimon Schubert 
26665796c8dcSSimon Schubert /* Determine, for architecture GDBARCH, how a return value of TYPE
26675796c8dcSSimon Schubert    should be returned.  If it is supposed to be returned in registers,
26685796c8dcSSimon Schubert    and READBUF is non-zero, read the appropriate value from REGCACHE,
26695796c8dcSSimon Schubert    and copy it into READBUF.  If WRITEBUF is non-zero, write the value
26705796c8dcSSimon Schubert    from WRITEBUF into REGCACHE.  */
26715796c8dcSSimon Schubert 
26725796c8dcSSimon Schubert static enum return_value_convention
i386_return_value(struct gdbarch * gdbarch,struct value * function,struct type * type,struct regcache * regcache,gdb_byte * readbuf,const gdb_byte * writebuf)2673*ef5ccd6cSJohn Marino i386_return_value (struct gdbarch *gdbarch, struct value *function,
26745796c8dcSSimon Schubert 		   struct type *type, struct regcache *regcache,
26755796c8dcSSimon Schubert 		   gdb_byte *readbuf, const gdb_byte *writebuf)
26765796c8dcSSimon Schubert {
26775796c8dcSSimon Schubert   enum type_code code = TYPE_CODE (type);
26785796c8dcSSimon Schubert 
26795796c8dcSSimon Schubert   if (((code == TYPE_CODE_STRUCT
26805796c8dcSSimon Schubert 	|| code == TYPE_CODE_UNION
26815796c8dcSSimon Schubert 	|| code == TYPE_CODE_ARRAY)
26825796c8dcSSimon Schubert        && !i386_reg_struct_return_p (gdbarch, type))
2683*ef5ccd6cSJohn Marino       /* Complex double and long double uses the struct return covention.  */
2684*ef5ccd6cSJohn Marino       || (code == TYPE_CODE_COMPLEX && TYPE_LENGTH (type) == 16)
2685*ef5ccd6cSJohn Marino       || (code == TYPE_CODE_COMPLEX && TYPE_LENGTH (type) == 24)
26865796c8dcSSimon Schubert       /* 128-bit decimal float uses the struct return convention.  */
26875796c8dcSSimon Schubert       || (code == TYPE_CODE_DECFLOAT && TYPE_LENGTH (type) == 16))
26885796c8dcSSimon Schubert     {
26895796c8dcSSimon Schubert       /* The System V ABI says that:
26905796c8dcSSimon Schubert 
26915796c8dcSSimon Schubert 	 "A function that returns a structure or union also sets %eax
26925796c8dcSSimon Schubert 	 to the value of the original address of the caller's area
26935796c8dcSSimon Schubert 	 before it returns.  Thus when the caller receives control
26945796c8dcSSimon Schubert 	 again, the address of the returned object resides in register
26955796c8dcSSimon Schubert 	 %eax and can be used to access the object."
26965796c8dcSSimon Schubert 
26975796c8dcSSimon Schubert 	 So the ABI guarantees that we can always find the return
26985796c8dcSSimon Schubert 	 value just after the function has returned.  */
26995796c8dcSSimon Schubert 
27005796c8dcSSimon Schubert       /* Note that the ABI doesn't mention functions returning arrays,
27015796c8dcSSimon Schubert          which is something possible in certain languages such as Ada.
27025796c8dcSSimon Schubert          In this case, the value is returned as if it was wrapped in
27035796c8dcSSimon Schubert          a record, so the convention applied to records also applies
27045796c8dcSSimon Schubert          to arrays.  */
27055796c8dcSSimon Schubert 
27065796c8dcSSimon Schubert       if (readbuf)
27075796c8dcSSimon Schubert 	{
27085796c8dcSSimon Schubert 	  ULONGEST addr;
27095796c8dcSSimon Schubert 
27105796c8dcSSimon Schubert 	  regcache_raw_read_unsigned (regcache, I386_EAX_REGNUM, &addr);
27115796c8dcSSimon Schubert 	  read_memory (addr, readbuf, TYPE_LENGTH (type));
27125796c8dcSSimon Schubert 	}
27135796c8dcSSimon Schubert 
27145796c8dcSSimon Schubert       return RETURN_VALUE_ABI_RETURNS_ADDRESS;
27155796c8dcSSimon Schubert     }
27165796c8dcSSimon Schubert 
27175796c8dcSSimon Schubert   /* This special case is for structures consisting of a single
27185796c8dcSSimon Schubert      `float', `double' or 'long double' member.  These structures are
27195796c8dcSSimon Schubert      returned in %st(0).  For these structures, we call ourselves
27205796c8dcSSimon Schubert      recursively, changing TYPE into the type of the first member of
27215796c8dcSSimon Schubert      the structure.  Since that should work for all structures that
27225796c8dcSSimon Schubert      have only one member, we don't bother to check the member's type
27235796c8dcSSimon Schubert      here.  */
27245796c8dcSSimon Schubert   if (code == TYPE_CODE_STRUCT && TYPE_NFIELDS (type) == 1)
27255796c8dcSSimon Schubert     {
27265796c8dcSSimon Schubert       type = check_typedef (TYPE_FIELD_TYPE (type, 0));
2727*ef5ccd6cSJohn Marino       return i386_return_value (gdbarch, function, type, regcache,
27285796c8dcSSimon Schubert 				readbuf, writebuf);
27295796c8dcSSimon Schubert     }
27305796c8dcSSimon Schubert 
27315796c8dcSSimon Schubert   if (readbuf)
27325796c8dcSSimon Schubert     i386_extract_return_value (gdbarch, type, regcache, readbuf);
27335796c8dcSSimon Schubert   if (writebuf)
27345796c8dcSSimon Schubert     i386_store_return_value (gdbarch, type, regcache, writebuf);
27355796c8dcSSimon Schubert 
27365796c8dcSSimon Schubert   return RETURN_VALUE_REGISTER_CONVENTION;
27375796c8dcSSimon Schubert }
27385796c8dcSSimon Schubert 
27395796c8dcSSimon Schubert 
27405796c8dcSSimon Schubert struct type *
i387_ext_type(struct gdbarch * gdbarch)27415796c8dcSSimon Schubert i387_ext_type (struct gdbarch *gdbarch)
27425796c8dcSSimon Schubert {
27435796c8dcSSimon Schubert   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
27445796c8dcSSimon Schubert 
27455796c8dcSSimon Schubert   if (!tdep->i387_ext_type)
2746cf7f2e2dSJohn Marino     {
2747cf7f2e2dSJohn Marino       tdep->i387_ext_type = tdesc_find_type (gdbarch, "i387_ext");
2748cf7f2e2dSJohn Marino       gdb_assert (tdep->i387_ext_type != NULL);
2749cf7f2e2dSJohn Marino     }
27505796c8dcSSimon Schubert 
27515796c8dcSSimon Schubert   return tdep->i387_ext_type;
27525796c8dcSSimon Schubert }
27535796c8dcSSimon Schubert 
2754cf7f2e2dSJohn Marino /* Construct vector type for pseudo YMM registers.  We can't use
2755cf7f2e2dSJohn Marino    tdesc_find_type since YMM isn't described in target description.  */
2756cf7f2e2dSJohn Marino 
2757cf7f2e2dSJohn Marino static struct type *
i386_ymm_type(struct gdbarch * gdbarch)2758cf7f2e2dSJohn Marino i386_ymm_type (struct gdbarch *gdbarch)
2759cf7f2e2dSJohn Marino {
2760cf7f2e2dSJohn Marino   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
2761cf7f2e2dSJohn Marino 
2762cf7f2e2dSJohn Marino   if (!tdep->i386_ymm_type)
2763cf7f2e2dSJohn Marino     {
2764cf7f2e2dSJohn Marino       const struct builtin_type *bt = builtin_type (gdbarch);
2765cf7f2e2dSJohn Marino 
2766cf7f2e2dSJohn Marino       /* The type we're building is this: */
2767cf7f2e2dSJohn Marino #if 0
2768cf7f2e2dSJohn Marino       union __gdb_builtin_type_vec256i
2769cf7f2e2dSJohn Marino       {
2770cf7f2e2dSJohn Marino         int128_t uint128[2];
2771cf7f2e2dSJohn Marino         int64_t v2_int64[4];
2772cf7f2e2dSJohn Marino         int32_t v4_int32[8];
2773cf7f2e2dSJohn Marino         int16_t v8_int16[16];
2774cf7f2e2dSJohn Marino         int8_t v16_int8[32];
2775cf7f2e2dSJohn Marino         double v2_double[4];
2776cf7f2e2dSJohn Marino         float v4_float[8];
2777cf7f2e2dSJohn Marino       };
2778cf7f2e2dSJohn Marino #endif
2779cf7f2e2dSJohn Marino 
2780cf7f2e2dSJohn Marino       struct type *t;
2781cf7f2e2dSJohn Marino 
2782cf7f2e2dSJohn Marino       t = arch_composite_type (gdbarch,
2783cf7f2e2dSJohn Marino 			       "__gdb_builtin_type_vec256i", TYPE_CODE_UNION);
2784cf7f2e2dSJohn Marino       append_composite_type_field (t, "v8_float",
2785cf7f2e2dSJohn Marino 				   init_vector_type (bt->builtin_float, 8));
2786cf7f2e2dSJohn Marino       append_composite_type_field (t, "v4_double",
2787cf7f2e2dSJohn Marino 				   init_vector_type (bt->builtin_double, 4));
2788cf7f2e2dSJohn Marino       append_composite_type_field (t, "v32_int8",
2789cf7f2e2dSJohn Marino 				   init_vector_type (bt->builtin_int8, 32));
2790cf7f2e2dSJohn Marino       append_composite_type_field (t, "v16_int16",
2791cf7f2e2dSJohn Marino 				   init_vector_type (bt->builtin_int16, 16));
2792cf7f2e2dSJohn Marino       append_composite_type_field (t, "v8_int32",
2793cf7f2e2dSJohn Marino 				   init_vector_type (bt->builtin_int32, 8));
2794cf7f2e2dSJohn Marino       append_composite_type_field (t, "v4_int64",
2795cf7f2e2dSJohn Marino 				   init_vector_type (bt->builtin_int64, 4));
2796cf7f2e2dSJohn Marino       append_composite_type_field (t, "v2_int128",
2797cf7f2e2dSJohn Marino 				   init_vector_type (bt->builtin_int128, 2));
2798cf7f2e2dSJohn Marino 
2799cf7f2e2dSJohn Marino       TYPE_VECTOR (t) = 1;
2800c50c785cSJohn Marino       TYPE_NAME (t) = "builtin_type_vec256i";
2801cf7f2e2dSJohn Marino       tdep->i386_ymm_type = t;
2802cf7f2e2dSJohn Marino     }
2803cf7f2e2dSJohn Marino 
2804cf7f2e2dSJohn Marino   return tdep->i386_ymm_type;
2805cf7f2e2dSJohn Marino }
2806cf7f2e2dSJohn Marino 
28075796c8dcSSimon Schubert /* Construct vector type for MMX registers.  */
2808cf7f2e2dSJohn Marino static struct type *
i386_mmx_type(struct gdbarch * gdbarch)28095796c8dcSSimon Schubert i386_mmx_type (struct gdbarch *gdbarch)
28105796c8dcSSimon Schubert {
28115796c8dcSSimon Schubert   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
28125796c8dcSSimon Schubert 
28135796c8dcSSimon Schubert   if (!tdep->i386_mmx_type)
28145796c8dcSSimon Schubert     {
28155796c8dcSSimon Schubert       const struct builtin_type *bt = builtin_type (gdbarch);
28165796c8dcSSimon Schubert 
28175796c8dcSSimon Schubert       /* The type we're building is this: */
28185796c8dcSSimon Schubert #if 0
28195796c8dcSSimon Schubert       union __gdb_builtin_type_vec64i
28205796c8dcSSimon Schubert       {
28215796c8dcSSimon Schubert         int64_t uint64;
28225796c8dcSSimon Schubert         int32_t v2_int32[2];
28235796c8dcSSimon Schubert         int16_t v4_int16[4];
28245796c8dcSSimon Schubert         int8_t v8_int8[8];
28255796c8dcSSimon Schubert       };
28265796c8dcSSimon Schubert #endif
28275796c8dcSSimon Schubert 
28285796c8dcSSimon Schubert       struct type *t;
28295796c8dcSSimon Schubert 
28305796c8dcSSimon Schubert       t = arch_composite_type (gdbarch,
28315796c8dcSSimon Schubert 			       "__gdb_builtin_type_vec64i", TYPE_CODE_UNION);
28325796c8dcSSimon Schubert 
28335796c8dcSSimon Schubert       append_composite_type_field (t, "uint64", bt->builtin_int64);
28345796c8dcSSimon Schubert       append_composite_type_field (t, "v2_int32",
28355796c8dcSSimon Schubert 				   init_vector_type (bt->builtin_int32, 2));
28365796c8dcSSimon Schubert       append_composite_type_field (t, "v4_int16",
28375796c8dcSSimon Schubert 				   init_vector_type (bt->builtin_int16, 4));
28385796c8dcSSimon Schubert       append_composite_type_field (t, "v8_int8",
28395796c8dcSSimon Schubert 				   init_vector_type (bt->builtin_int8, 8));
28405796c8dcSSimon Schubert 
28415796c8dcSSimon Schubert       TYPE_VECTOR (t) = 1;
28425796c8dcSSimon Schubert       TYPE_NAME (t) = "builtin_type_vec64i";
28435796c8dcSSimon Schubert       tdep->i386_mmx_type = t;
28445796c8dcSSimon Schubert     }
28455796c8dcSSimon Schubert 
28465796c8dcSSimon Schubert   return tdep->i386_mmx_type;
28475796c8dcSSimon Schubert }
28485796c8dcSSimon Schubert 
28495796c8dcSSimon Schubert /* Return the GDB type object for the "standard" data type of data in
2850cf7f2e2dSJohn Marino    register REGNUM.  */
28515796c8dcSSimon Schubert 
2852*ef5ccd6cSJohn Marino struct type *
i386_pseudo_register_type(struct gdbarch * gdbarch,int regnum)2853cf7f2e2dSJohn Marino i386_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
28545796c8dcSSimon Schubert {
28555796c8dcSSimon Schubert   if (i386_mmx_regnum_p (gdbarch, regnum))
28565796c8dcSSimon Schubert     return i386_mmx_type (gdbarch);
2857cf7f2e2dSJohn Marino   else if (i386_ymm_regnum_p (gdbarch, regnum))
2858cf7f2e2dSJohn Marino     return i386_ymm_type (gdbarch);
2859cf7f2e2dSJohn Marino   else
2860cf7f2e2dSJohn Marino     {
2861cf7f2e2dSJohn Marino       const struct builtin_type *bt = builtin_type (gdbarch);
2862cf7f2e2dSJohn Marino       if (i386_byte_regnum_p (gdbarch, regnum))
2863cf7f2e2dSJohn Marino 	return bt->builtin_int8;
2864cf7f2e2dSJohn Marino       else if (i386_word_regnum_p (gdbarch, regnum))
2865cf7f2e2dSJohn Marino 	return bt->builtin_int16;
2866cf7f2e2dSJohn Marino       else if (i386_dword_regnum_p (gdbarch, regnum))
2867cf7f2e2dSJohn Marino 	return bt->builtin_int32;
2868cf7f2e2dSJohn Marino     }
28695796c8dcSSimon Schubert 
2870cf7f2e2dSJohn Marino   internal_error (__FILE__, __LINE__, _("invalid regnum"));
28715796c8dcSSimon Schubert }
28725796c8dcSSimon Schubert 
28735796c8dcSSimon Schubert /* Map a cooked register onto a raw register or memory.  For the i386,
28745796c8dcSSimon Schubert    the MMX registers need to be mapped onto floating point registers.  */
28755796c8dcSSimon Schubert 
28765796c8dcSSimon Schubert static int
i386_mmx_regnum_to_fp_regnum(struct regcache * regcache,int regnum)28775796c8dcSSimon Schubert i386_mmx_regnum_to_fp_regnum (struct regcache *regcache, int regnum)
28785796c8dcSSimon Schubert {
28795796c8dcSSimon Schubert   struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
28805796c8dcSSimon Schubert   int mmxreg, fpreg;
28815796c8dcSSimon Schubert   ULONGEST fstat;
28825796c8dcSSimon Schubert   int tos;
28835796c8dcSSimon Schubert 
28845796c8dcSSimon Schubert   mmxreg = regnum - tdep->mm0_regnum;
28855796c8dcSSimon Schubert   regcache_raw_read_unsigned (regcache, I387_FSTAT_REGNUM (tdep), &fstat);
28865796c8dcSSimon Schubert   tos = (fstat >> 11) & 0x7;
28875796c8dcSSimon Schubert   fpreg = (mmxreg + tos) % 8;
28885796c8dcSSimon Schubert 
28895796c8dcSSimon Schubert   return (I387_ST0_REGNUM (tdep) + fpreg);
28905796c8dcSSimon Schubert }
28915796c8dcSSimon Schubert 
2892a45ae5f8SJohn Marino /* A helper function for us by i386_pseudo_register_read_value and
2893a45ae5f8SJohn Marino    amd64_pseudo_register_read_value.  It does all the work but reads
2894a45ae5f8SJohn Marino    the data into an already-allocated value.  */
2895a45ae5f8SJohn Marino 
2896a45ae5f8SJohn Marino void
i386_pseudo_register_read_into_value(struct gdbarch * gdbarch,struct regcache * regcache,int regnum,struct value * result_value)2897a45ae5f8SJohn Marino i386_pseudo_register_read_into_value (struct gdbarch *gdbarch,
2898a45ae5f8SJohn Marino 				      struct regcache *regcache,
2899a45ae5f8SJohn Marino 				      int regnum,
2900a45ae5f8SJohn Marino 				      struct value *result_value)
29015796c8dcSSimon Schubert {
2902cf7f2e2dSJohn Marino   gdb_byte raw_buf[MAX_REGISTER_SIZE];
2903c50c785cSJohn Marino   enum register_status status;
2904a45ae5f8SJohn Marino   gdb_byte *buf = value_contents_raw (result_value);
2905cf7f2e2dSJohn Marino 
29065796c8dcSSimon Schubert   if (i386_mmx_regnum_p (gdbarch, regnum))
29075796c8dcSSimon Schubert     {
29085796c8dcSSimon Schubert       int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum);
29095796c8dcSSimon Schubert 
29105796c8dcSSimon Schubert       /* Extract (always little endian).  */
2911c50c785cSJohn Marino       status = regcache_raw_read (regcache, fpnum, raw_buf);
2912c50c785cSJohn Marino       if (status != REG_VALID)
2913a45ae5f8SJohn Marino 	mark_value_bytes_unavailable (result_value, 0,
2914a45ae5f8SJohn Marino 				      TYPE_LENGTH (value_type (result_value)));
2915a45ae5f8SJohn Marino       else
2916cf7f2e2dSJohn Marino 	memcpy (buf, raw_buf, register_size (gdbarch, regnum));
29175796c8dcSSimon Schubert     }
29185796c8dcSSimon Schubert   else
2919cf7f2e2dSJohn Marino     {
2920cf7f2e2dSJohn Marino       struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
2921cf7f2e2dSJohn Marino 
2922cf7f2e2dSJohn Marino       if (i386_ymm_regnum_p (gdbarch, regnum))
2923cf7f2e2dSJohn Marino 	{
2924cf7f2e2dSJohn Marino 	  regnum -= tdep->ymm0_regnum;
2925cf7f2e2dSJohn Marino 
2926cf7f2e2dSJohn Marino 	  /* Extract (always little endian).  Read lower 128bits.  */
2927c50c785cSJohn Marino 	  status = regcache_raw_read (regcache,
2928cf7f2e2dSJohn Marino 				      I387_XMM0_REGNUM (tdep) + regnum,
2929cf7f2e2dSJohn Marino 				      raw_buf);
2930c50c785cSJohn Marino 	  if (status != REG_VALID)
2931a45ae5f8SJohn Marino 	    mark_value_bytes_unavailable (result_value, 0, 16);
2932a45ae5f8SJohn Marino 	  else
2933cf7f2e2dSJohn Marino 	    memcpy (buf, raw_buf, 16);
2934cf7f2e2dSJohn Marino 	  /* Read upper 128bits.  */
2935c50c785cSJohn Marino 	  status = regcache_raw_read (regcache,
2936cf7f2e2dSJohn Marino 				      tdep->ymm0h_regnum + regnum,
2937cf7f2e2dSJohn Marino 				      raw_buf);
2938c50c785cSJohn Marino 	  if (status != REG_VALID)
2939a45ae5f8SJohn Marino 	    mark_value_bytes_unavailable (result_value, 16, 32);
2940a45ae5f8SJohn Marino 	  else
2941cf7f2e2dSJohn Marino 	    memcpy (buf + 16, raw_buf, 16);
2942cf7f2e2dSJohn Marino 	}
2943cf7f2e2dSJohn Marino       else if (i386_word_regnum_p (gdbarch, regnum))
2944cf7f2e2dSJohn Marino 	{
2945cf7f2e2dSJohn Marino 	  int gpnum = regnum - tdep->ax_regnum;
2946cf7f2e2dSJohn Marino 
2947cf7f2e2dSJohn Marino 	  /* Extract (always little endian).  */
2948c50c785cSJohn Marino 	  status = regcache_raw_read (regcache, gpnum, raw_buf);
2949c50c785cSJohn Marino 	  if (status != REG_VALID)
2950a45ae5f8SJohn Marino 	    mark_value_bytes_unavailable (result_value, 0,
2951a45ae5f8SJohn Marino 					  TYPE_LENGTH (value_type (result_value)));
2952a45ae5f8SJohn Marino 	  else
2953cf7f2e2dSJohn Marino 	    memcpy (buf, raw_buf, 2);
2954cf7f2e2dSJohn Marino 	}
2955cf7f2e2dSJohn Marino       else if (i386_byte_regnum_p (gdbarch, regnum))
2956cf7f2e2dSJohn Marino 	{
2957cf7f2e2dSJohn Marino 	  /* Check byte pseudo registers last since this function will
2958cf7f2e2dSJohn Marino 	     be called from amd64_pseudo_register_read, which handles
2959cf7f2e2dSJohn Marino 	     byte pseudo registers differently.  */
2960cf7f2e2dSJohn Marino 	  int gpnum = regnum - tdep->al_regnum;
2961cf7f2e2dSJohn Marino 
2962cf7f2e2dSJohn Marino 	  /* Extract (always little endian).  We read both lower and
2963cf7f2e2dSJohn Marino 	     upper registers.  */
2964c50c785cSJohn Marino 	  status = regcache_raw_read (regcache, gpnum % 4, raw_buf);
2965c50c785cSJohn Marino 	  if (status != REG_VALID)
2966a45ae5f8SJohn Marino 	    mark_value_bytes_unavailable (result_value, 0,
2967a45ae5f8SJohn Marino 					  TYPE_LENGTH (value_type (result_value)));
2968a45ae5f8SJohn Marino 	  else if (gpnum >= 4)
2969cf7f2e2dSJohn Marino 	    memcpy (buf, raw_buf + 1, 1);
2970cf7f2e2dSJohn Marino 	  else
2971cf7f2e2dSJohn Marino 	    memcpy (buf, raw_buf, 1);
2972cf7f2e2dSJohn Marino 	}
2973cf7f2e2dSJohn Marino       else
2974cf7f2e2dSJohn Marino 	internal_error (__FILE__, __LINE__, _("invalid regnum"));
2975cf7f2e2dSJohn Marino     }
2976a45ae5f8SJohn Marino }
2977c50c785cSJohn Marino 
2978a45ae5f8SJohn Marino static struct value *
i386_pseudo_register_read_value(struct gdbarch * gdbarch,struct regcache * regcache,int regnum)2979a45ae5f8SJohn Marino i386_pseudo_register_read_value (struct gdbarch *gdbarch,
2980a45ae5f8SJohn Marino 				 struct regcache *regcache,
2981a45ae5f8SJohn Marino 				 int regnum)
2982a45ae5f8SJohn Marino {
2983a45ae5f8SJohn Marino   struct value *result;
2984a45ae5f8SJohn Marino 
2985a45ae5f8SJohn Marino   result = allocate_value (register_type (gdbarch, regnum));
2986a45ae5f8SJohn Marino   VALUE_LVAL (result) = lval_register;
2987a45ae5f8SJohn Marino   VALUE_REGNUM (result) = regnum;
2988a45ae5f8SJohn Marino 
2989a45ae5f8SJohn Marino   i386_pseudo_register_read_into_value (gdbarch, regcache, regnum, result);
2990a45ae5f8SJohn Marino 
2991a45ae5f8SJohn Marino   return result;
29925796c8dcSSimon Schubert }
29935796c8dcSSimon Schubert 
2994cf7f2e2dSJohn Marino void
i386_pseudo_register_write(struct gdbarch * gdbarch,struct regcache * regcache,int regnum,const gdb_byte * buf)29955796c8dcSSimon Schubert i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
29965796c8dcSSimon Schubert 			    int regnum, const gdb_byte *buf)
29975796c8dcSSimon Schubert {
2998cf7f2e2dSJohn Marino   gdb_byte raw_buf[MAX_REGISTER_SIZE];
2999cf7f2e2dSJohn Marino 
30005796c8dcSSimon Schubert   if (i386_mmx_regnum_p (gdbarch, regnum))
30015796c8dcSSimon Schubert     {
30025796c8dcSSimon Schubert       int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum);
30035796c8dcSSimon Schubert 
30045796c8dcSSimon Schubert       /* Read ...  */
3005cf7f2e2dSJohn Marino       regcache_raw_read (regcache, fpnum, raw_buf);
30065796c8dcSSimon Schubert       /* ... Modify ... (always little endian).  */
3007cf7f2e2dSJohn Marino       memcpy (raw_buf, buf, register_size (gdbarch, regnum));
30085796c8dcSSimon Schubert       /* ... Write.  */
3009cf7f2e2dSJohn Marino       regcache_raw_write (regcache, fpnum, raw_buf);
30105796c8dcSSimon Schubert     }
30115796c8dcSSimon Schubert   else
3012cf7f2e2dSJohn Marino     {
3013cf7f2e2dSJohn Marino       struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
3014cf7f2e2dSJohn Marino 
3015cf7f2e2dSJohn Marino       if (i386_ymm_regnum_p (gdbarch, regnum))
3016cf7f2e2dSJohn Marino 	{
3017cf7f2e2dSJohn Marino 	  regnum -= tdep->ymm0_regnum;
3018cf7f2e2dSJohn Marino 
3019cf7f2e2dSJohn Marino 	  /* ... Write lower 128bits.  */
3020cf7f2e2dSJohn Marino 	  regcache_raw_write (regcache,
3021cf7f2e2dSJohn Marino 			     I387_XMM0_REGNUM (tdep) + regnum,
3022cf7f2e2dSJohn Marino 			     buf);
3023cf7f2e2dSJohn Marino 	  /* ... Write upper 128bits.  */
3024cf7f2e2dSJohn Marino 	  regcache_raw_write (regcache,
3025cf7f2e2dSJohn Marino 			     tdep->ymm0h_regnum + regnum,
3026cf7f2e2dSJohn Marino 			     buf + 16);
3027cf7f2e2dSJohn Marino 	}
3028cf7f2e2dSJohn Marino       else if (i386_word_regnum_p (gdbarch, regnum))
3029cf7f2e2dSJohn Marino 	{
3030cf7f2e2dSJohn Marino 	  int gpnum = regnum - tdep->ax_regnum;
3031cf7f2e2dSJohn Marino 
3032cf7f2e2dSJohn Marino 	  /* Read ...  */
3033cf7f2e2dSJohn Marino 	  regcache_raw_read (regcache, gpnum, raw_buf);
3034cf7f2e2dSJohn Marino 	  /* ... Modify ... (always little endian).  */
3035cf7f2e2dSJohn Marino 	  memcpy (raw_buf, buf, 2);
3036cf7f2e2dSJohn Marino 	  /* ... Write.  */
3037cf7f2e2dSJohn Marino 	  regcache_raw_write (regcache, gpnum, raw_buf);
3038cf7f2e2dSJohn Marino 	}
3039cf7f2e2dSJohn Marino       else if (i386_byte_regnum_p (gdbarch, regnum))
3040cf7f2e2dSJohn Marino 	{
3041cf7f2e2dSJohn Marino 	  /* Check byte pseudo registers last since this function will
3042cf7f2e2dSJohn Marino 	     be called from amd64_pseudo_register_read, which handles
3043cf7f2e2dSJohn Marino 	     byte pseudo registers differently.  */
3044cf7f2e2dSJohn Marino 	  int gpnum = regnum - tdep->al_regnum;
3045cf7f2e2dSJohn Marino 
3046cf7f2e2dSJohn Marino 	  /* Read ...  We read both lower and upper registers.  */
3047cf7f2e2dSJohn Marino 	  regcache_raw_read (regcache, gpnum % 4, raw_buf);
3048cf7f2e2dSJohn Marino 	  /* ... Modify ... (always little endian).  */
3049cf7f2e2dSJohn Marino 	  if (gpnum >= 4)
3050cf7f2e2dSJohn Marino 	    memcpy (raw_buf + 1, buf, 1);
3051cf7f2e2dSJohn Marino 	  else
3052cf7f2e2dSJohn Marino 	    memcpy (raw_buf, buf, 1);
3053cf7f2e2dSJohn Marino 	  /* ... Write.  */
3054cf7f2e2dSJohn Marino 	  regcache_raw_write (regcache, gpnum % 4, raw_buf);
3055cf7f2e2dSJohn Marino 	}
3056cf7f2e2dSJohn Marino       else
3057cf7f2e2dSJohn Marino 	internal_error (__FILE__, __LINE__, _("invalid regnum"));
3058cf7f2e2dSJohn Marino     }
30595796c8dcSSimon Schubert }
30605796c8dcSSimon Schubert 
30615796c8dcSSimon Schubert 
30625796c8dcSSimon Schubert /* Return the register number of the register allocated by GCC after
30635796c8dcSSimon Schubert    REGNUM, or -1 if there is no such register.  */
30645796c8dcSSimon Schubert 
30655796c8dcSSimon Schubert static int
i386_next_regnum(int regnum)30665796c8dcSSimon Schubert i386_next_regnum (int regnum)
30675796c8dcSSimon Schubert {
30685796c8dcSSimon Schubert   /* GCC allocates the registers in the order:
30695796c8dcSSimon Schubert 
30705796c8dcSSimon Schubert      %eax, %edx, %ecx, %ebx, %esi, %edi, %ebp, %esp, ...
30715796c8dcSSimon Schubert 
30725796c8dcSSimon Schubert      Since storing a variable in %esp doesn't make any sense we return
30735796c8dcSSimon Schubert      -1 for %ebp and for %esp itself.  */
30745796c8dcSSimon Schubert   static int next_regnum[] =
30755796c8dcSSimon Schubert   {
30765796c8dcSSimon Schubert     I386_EDX_REGNUM,		/* Slot for %eax.  */
30775796c8dcSSimon Schubert     I386_EBX_REGNUM,		/* Slot for %ecx.  */
30785796c8dcSSimon Schubert     I386_ECX_REGNUM,		/* Slot for %edx.  */
30795796c8dcSSimon Schubert     I386_ESI_REGNUM,		/* Slot for %ebx.  */
30805796c8dcSSimon Schubert     -1, -1,			/* Slots for %esp and %ebp.  */
30815796c8dcSSimon Schubert     I386_EDI_REGNUM,		/* Slot for %esi.  */
30825796c8dcSSimon Schubert     I386_EBP_REGNUM		/* Slot for %edi.  */
30835796c8dcSSimon Schubert   };
30845796c8dcSSimon Schubert 
30855796c8dcSSimon Schubert   if (regnum >= 0 && regnum < sizeof (next_regnum) / sizeof (next_regnum[0]))
30865796c8dcSSimon Schubert     return next_regnum[regnum];
30875796c8dcSSimon Schubert 
30885796c8dcSSimon Schubert   return -1;
30895796c8dcSSimon Schubert }
30905796c8dcSSimon Schubert 
30915796c8dcSSimon Schubert /* Return nonzero if a value of type TYPE stored in register REGNUM
30925796c8dcSSimon Schubert    needs any special handling.  */
30935796c8dcSSimon Schubert 
30945796c8dcSSimon Schubert static int
i386_convert_register_p(struct gdbarch * gdbarch,int regnum,struct type * type)3095c50c785cSJohn Marino i386_convert_register_p (struct gdbarch *gdbarch,
3096c50c785cSJohn Marino 			 int regnum, struct type *type)
30975796c8dcSSimon Schubert {
30985796c8dcSSimon Schubert   int len = TYPE_LENGTH (type);
30995796c8dcSSimon Schubert 
31005796c8dcSSimon Schubert   /* Values may be spread across multiple registers.  Most debugging
31015796c8dcSSimon Schubert      formats aren't expressive enough to specify the locations, so
31025796c8dcSSimon Schubert      some heuristics is involved.  Right now we only handle types that
31035796c8dcSSimon Schubert      have a length that is a multiple of the word size, since GCC
31045796c8dcSSimon Schubert      doesn't seem to put any other types into registers.  */
31055796c8dcSSimon Schubert   if (len > 4 && len % 4 == 0)
31065796c8dcSSimon Schubert     {
31075796c8dcSSimon Schubert       int last_regnum = regnum;
31085796c8dcSSimon Schubert 
31095796c8dcSSimon Schubert       while (len > 4)
31105796c8dcSSimon Schubert 	{
31115796c8dcSSimon Schubert 	  last_regnum = i386_next_regnum (last_regnum);
31125796c8dcSSimon Schubert 	  len -= 4;
31135796c8dcSSimon Schubert 	}
31145796c8dcSSimon Schubert 
31155796c8dcSSimon Schubert       if (last_regnum != -1)
31165796c8dcSSimon Schubert 	return 1;
31175796c8dcSSimon Schubert     }
31185796c8dcSSimon Schubert 
31195796c8dcSSimon Schubert   return i387_convert_register_p (gdbarch, regnum, type);
31205796c8dcSSimon Schubert }
31215796c8dcSSimon Schubert 
31225796c8dcSSimon Schubert /* Read a value of type TYPE from register REGNUM in frame FRAME, and
31235796c8dcSSimon Schubert    return its contents in TO.  */
31245796c8dcSSimon Schubert 
3125c50c785cSJohn Marino static int
i386_register_to_value(struct frame_info * frame,int regnum,struct type * type,gdb_byte * to,int * optimizedp,int * unavailablep)31265796c8dcSSimon Schubert i386_register_to_value (struct frame_info *frame, int regnum,
3127c50c785cSJohn Marino 			struct type *type, gdb_byte *to,
3128c50c785cSJohn Marino 			int *optimizedp, int *unavailablep)
31295796c8dcSSimon Schubert {
31305796c8dcSSimon Schubert   struct gdbarch *gdbarch = get_frame_arch (frame);
31315796c8dcSSimon Schubert   int len = TYPE_LENGTH (type);
31325796c8dcSSimon Schubert 
31335796c8dcSSimon Schubert   if (i386_fp_regnum_p (gdbarch, regnum))
3134c50c785cSJohn Marino     return i387_register_to_value (frame, regnum, type, to,
3135c50c785cSJohn Marino 				   optimizedp, unavailablep);
31365796c8dcSSimon Schubert 
31375796c8dcSSimon Schubert   /* Read a value spread across multiple registers.  */
31385796c8dcSSimon Schubert 
31395796c8dcSSimon Schubert   gdb_assert (len > 4 && len % 4 == 0);
31405796c8dcSSimon Schubert 
31415796c8dcSSimon Schubert   while (len > 0)
31425796c8dcSSimon Schubert     {
31435796c8dcSSimon Schubert       gdb_assert (regnum != -1);
31445796c8dcSSimon Schubert       gdb_assert (register_size (gdbarch, regnum) == 4);
31455796c8dcSSimon Schubert 
3146c50c785cSJohn Marino       if (!get_frame_register_bytes (frame, regnum, 0,
3147c50c785cSJohn Marino 				     register_size (gdbarch, regnum),
3148c50c785cSJohn Marino 				     to, optimizedp, unavailablep))
3149c50c785cSJohn Marino 	return 0;
3150c50c785cSJohn Marino 
31515796c8dcSSimon Schubert       regnum = i386_next_regnum (regnum);
31525796c8dcSSimon Schubert       len -= 4;
31535796c8dcSSimon Schubert       to += 4;
31545796c8dcSSimon Schubert     }
3155c50c785cSJohn Marino 
3156c50c785cSJohn Marino   *optimizedp = *unavailablep = 0;
3157c50c785cSJohn Marino   return 1;
31585796c8dcSSimon Schubert }
31595796c8dcSSimon Schubert 
31605796c8dcSSimon Schubert /* Write the contents FROM of a value of type TYPE into register
31615796c8dcSSimon Schubert    REGNUM in frame FRAME.  */
31625796c8dcSSimon Schubert 
31635796c8dcSSimon Schubert static void
i386_value_to_register(struct frame_info * frame,int regnum,struct type * type,const gdb_byte * from)31645796c8dcSSimon Schubert i386_value_to_register (struct frame_info *frame, int regnum,
31655796c8dcSSimon Schubert 			struct type *type, const gdb_byte *from)
31665796c8dcSSimon Schubert {
31675796c8dcSSimon Schubert   int len = TYPE_LENGTH (type);
31685796c8dcSSimon Schubert 
31695796c8dcSSimon Schubert   if (i386_fp_regnum_p (get_frame_arch (frame), regnum))
31705796c8dcSSimon Schubert     {
31715796c8dcSSimon Schubert       i387_value_to_register (frame, regnum, type, from);
31725796c8dcSSimon Schubert       return;
31735796c8dcSSimon Schubert     }
31745796c8dcSSimon Schubert 
31755796c8dcSSimon Schubert   /* Write a value spread across multiple registers.  */
31765796c8dcSSimon Schubert 
31775796c8dcSSimon Schubert   gdb_assert (len > 4 && len % 4 == 0);
31785796c8dcSSimon Schubert 
31795796c8dcSSimon Schubert   while (len > 0)
31805796c8dcSSimon Schubert     {
31815796c8dcSSimon Schubert       gdb_assert (regnum != -1);
31825796c8dcSSimon Schubert       gdb_assert (register_size (get_frame_arch (frame), regnum) == 4);
31835796c8dcSSimon Schubert 
31845796c8dcSSimon Schubert       put_frame_register (frame, regnum, from);
31855796c8dcSSimon Schubert       regnum = i386_next_regnum (regnum);
31865796c8dcSSimon Schubert       len -= 4;
31875796c8dcSSimon Schubert       from += 4;
31885796c8dcSSimon Schubert     }
31895796c8dcSSimon Schubert }
31905796c8dcSSimon Schubert 
31915796c8dcSSimon Schubert /* Supply register REGNUM from the buffer specified by GREGS and LEN
31925796c8dcSSimon Schubert    in the general-purpose register set REGSET to register cache
31935796c8dcSSimon Schubert    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
31945796c8dcSSimon Schubert 
31955796c8dcSSimon Schubert void
i386_supply_gregset(const struct regset * regset,struct regcache * regcache,int regnum,const void * gregs,size_t len)31965796c8dcSSimon Schubert i386_supply_gregset (const struct regset *regset, struct regcache *regcache,
31975796c8dcSSimon Schubert 		     int regnum, const void *gregs, size_t len)
31985796c8dcSSimon Schubert {
31995796c8dcSSimon Schubert   const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
32005796c8dcSSimon Schubert   const gdb_byte *regs = gregs;
32015796c8dcSSimon Schubert   int i;
32025796c8dcSSimon Schubert 
32035796c8dcSSimon Schubert   gdb_assert (len == tdep->sizeof_gregset);
32045796c8dcSSimon Schubert 
32055796c8dcSSimon Schubert   for (i = 0; i < tdep->gregset_num_regs; i++)
32065796c8dcSSimon Schubert     {
32075796c8dcSSimon Schubert       if ((regnum == i || regnum == -1)
32085796c8dcSSimon Schubert 	  && tdep->gregset_reg_offset[i] != -1)
32095796c8dcSSimon Schubert 	regcache_raw_supply (regcache, i, regs + tdep->gregset_reg_offset[i]);
32105796c8dcSSimon Schubert     }
32115796c8dcSSimon Schubert }
32125796c8dcSSimon Schubert 
32135796c8dcSSimon Schubert /* Collect register REGNUM from the register cache REGCACHE and store
32145796c8dcSSimon Schubert    it in the buffer specified by GREGS and LEN as described by the
32155796c8dcSSimon Schubert    general-purpose register set REGSET.  If REGNUM is -1, do this for
32165796c8dcSSimon Schubert    all registers in REGSET.  */
32175796c8dcSSimon Schubert 
32185796c8dcSSimon Schubert void
i386_collect_gregset(const struct regset * regset,const struct regcache * regcache,int regnum,void * gregs,size_t len)32195796c8dcSSimon Schubert i386_collect_gregset (const struct regset *regset,
32205796c8dcSSimon Schubert 		      const struct regcache *regcache,
32215796c8dcSSimon Schubert 		      int regnum, void *gregs, size_t len)
32225796c8dcSSimon Schubert {
32235796c8dcSSimon Schubert   const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
32245796c8dcSSimon Schubert   gdb_byte *regs = gregs;
32255796c8dcSSimon Schubert   int i;
32265796c8dcSSimon Schubert 
32275796c8dcSSimon Schubert   gdb_assert (len == tdep->sizeof_gregset);
32285796c8dcSSimon Schubert 
32295796c8dcSSimon Schubert   for (i = 0; i < tdep->gregset_num_regs; i++)
32305796c8dcSSimon Schubert     {
32315796c8dcSSimon Schubert       if ((regnum == i || regnum == -1)
32325796c8dcSSimon Schubert 	  && tdep->gregset_reg_offset[i] != -1)
32335796c8dcSSimon Schubert 	regcache_raw_collect (regcache, i, regs + tdep->gregset_reg_offset[i]);
32345796c8dcSSimon Schubert     }
32355796c8dcSSimon Schubert }
32365796c8dcSSimon Schubert 
32375796c8dcSSimon Schubert /* Supply register REGNUM from the buffer specified by FPREGS and LEN
32385796c8dcSSimon Schubert    in the floating-point register set REGSET to register cache
32395796c8dcSSimon Schubert    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
32405796c8dcSSimon Schubert 
32415796c8dcSSimon Schubert static void
i386_supply_fpregset(const struct regset * regset,struct regcache * regcache,int regnum,const void * fpregs,size_t len)32425796c8dcSSimon Schubert i386_supply_fpregset (const struct regset *regset, struct regcache *regcache,
32435796c8dcSSimon Schubert 		      int regnum, const void *fpregs, size_t len)
32445796c8dcSSimon Schubert {
32455796c8dcSSimon Schubert   const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
32465796c8dcSSimon Schubert 
32475796c8dcSSimon Schubert   if (len == I387_SIZEOF_FXSAVE)
32485796c8dcSSimon Schubert     {
32495796c8dcSSimon Schubert       i387_supply_fxsave (regcache, regnum, fpregs);
32505796c8dcSSimon Schubert       return;
32515796c8dcSSimon Schubert     }
32525796c8dcSSimon Schubert 
32535796c8dcSSimon Schubert   gdb_assert (len == tdep->sizeof_fpregset);
32545796c8dcSSimon Schubert   i387_supply_fsave (regcache, regnum, fpregs);
32555796c8dcSSimon Schubert }
32565796c8dcSSimon Schubert 
32575796c8dcSSimon Schubert /* Collect register REGNUM from the register cache REGCACHE and store
32585796c8dcSSimon Schubert    it in the buffer specified by FPREGS and LEN as described by the
32595796c8dcSSimon Schubert    floating-point register set REGSET.  If REGNUM is -1, do this for
32605796c8dcSSimon Schubert    all registers in REGSET.  */
32615796c8dcSSimon Schubert 
32625796c8dcSSimon Schubert static void
i386_collect_fpregset(const struct regset * regset,const struct regcache * regcache,int regnum,void * fpregs,size_t len)32635796c8dcSSimon Schubert i386_collect_fpregset (const struct regset *regset,
32645796c8dcSSimon Schubert 		       const struct regcache *regcache,
32655796c8dcSSimon Schubert 		       int regnum, void *fpregs, size_t len)
32665796c8dcSSimon Schubert {
32675796c8dcSSimon Schubert   const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
32685796c8dcSSimon Schubert 
32695796c8dcSSimon Schubert   if (len == I387_SIZEOF_FXSAVE)
32705796c8dcSSimon Schubert     {
32715796c8dcSSimon Schubert       i387_collect_fxsave (regcache, regnum, fpregs);
32725796c8dcSSimon Schubert       return;
32735796c8dcSSimon Schubert     }
32745796c8dcSSimon Schubert 
32755796c8dcSSimon Schubert   gdb_assert (len == tdep->sizeof_fpregset);
32765796c8dcSSimon Schubert   i387_collect_fsave (regcache, regnum, fpregs);
32775796c8dcSSimon Schubert }
32785796c8dcSSimon Schubert 
3279cf7f2e2dSJohn Marino /* Similar to i386_supply_fpregset, but use XSAVE extended state.  */
3280cf7f2e2dSJohn Marino 
3281cf7f2e2dSJohn Marino static void
i386_supply_xstateregset(const struct regset * regset,struct regcache * regcache,int regnum,const void * xstateregs,size_t len)3282cf7f2e2dSJohn Marino i386_supply_xstateregset (const struct regset *regset,
3283cf7f2e2dSJohn Marino 			  struct regcache *regcache, int regnum,
3284cf7f2e2dSJohn Marino 			  const void *xstateregs, size_t len)
3285cf7f2e2dSJohn Marino {
3286cf7f2e2dSJohn Marino   i387_supply_xsave (regcache, regnum, xstateregs);
3287cf7f2e2dSJohn Marino }
3288cf7f2e2dSJohn Marino 
3289cf7f2e2dSJohn Marino /* Similar to i386_collect_fpregset , but use XSAVE extended state.  */
3290cf7f2e2dSJohn Marino 
3291cf7f2e2dSJohn Marino static void
i386_collect_xstateregset(const struct regset * regset,const struct regcache * regcache,int regnum,void * xstateregs,size_t len)3292cf7f2e2dSJohn Marino i386_collect_xstateregset (const struct regset *regset,
3293cf7f2e2dSJohn Marino 			   const struct regcache *regcache,
3294cf7f2e2dSJohn Marino 			   int regnum, void *xstateregs, size_t len)
3295cf7f2e2dSJohn Marino {
3296cf7f2e2dSJohn Marino   i387_collect_xsave (regcache, regnum, xstateregs, 1);
3297cf7f2e2dSJohn Marino }
3298cf7f2e2dSJohn Marino 
32995796c8dcSSimon Schubert /* Return the appropriate register set for the core section identified
33005796c8dcSSimon Schubert    by SECT_NAME and SECT_SIZE.  */
33015796c8dcSSimon Schubert 
33025796c8dcSSimon Schubert const struct regset *
i386_regset_from_core_section(struct gdbarch * gdbarch,const char * sect_name,size_t sect_size)33035796c8dcSSimon Schubert i386_regset_from_core_section (struct gdbarch *gdbarch,
33045796c8dcSSimon Schubert 			       const char *sect_name, size_t sect_size)
33055796c8dcSSimon Schubert {
33065796c8dcSSimon Schubert   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
33075796c8dcSSimon Schubert 
33085796c8dcSSimon Schubert   if (strcmp (sect_name, ".reg") == 0 && sect_size == tdep->sizeof_gregset)
33095796c8dcSSimon Schubert     {
33105796c8dcSSimon Schubert       if (tdep->gregset == NULL)
33115796c8dcSSimon Schubert 	tdep->gregset = regset_alloc (gdbarch, i386_supply_gregset,
33125796c8dcSSimon Schubert 				      i386_collect_gregset);
33135796c8dcSSimon Schubert       return tdep->gregset;
33145796c8dcSSimon Schubert     }
33155796c8dcSSimon Schubert 
33165796c8dcSSimon Schubert   if ((strcmp (sect_name, ".reg2") == 0 && sect_size == tdep->sizeof_fpregset)
33175796c8dcSSimon Schubert       || (strcmp (sect_name, ".reg-xfp") == 0
33185796c8dcSSimon Schubert 	  && sect_size == I387_SIZEOF_FXSAVE))
33195796c8dcSSimon Schubert     {
33205796c8dcSSimon Schubert       if (tdep->fpregset == NULL)
33215796c8dcSSimon Schubert 	tdep->fpregset = regset_alloc (gdbarch, i386_supply_fpregset,
33225796c8dcSSimon Schubert 				       i386_collect_fpregset);
33235796c8dcSSimon Schubert       return tdep->fpregset;
33245796c8dcSSimon Schubert     }
33255796c8dcSSimon Schubert 
3326cf7f2e2dSJohn Marino   if (strcmp (sect_name, ".reg-xstate") == 0)
3327cf7f2e2dSJohn Marino     {
3328cf7f2e2dSJohn Marino       if (tdep->xstateregset == NULL)
3329cf7f2e2dSJohn Marino 	tdep->xstateregset = regset_alloc (gdbarch,
3330cf7f2e2dSJohn Marino 					   i386_supply_xstateregset,
3331cf7f2e2dSJohn Marino 					   i386_collect_xstateregset);
3332cf7f2e2dSJohn Marino 
3333cf7f2e2dSJohn Marino       return tdep->xstateregset;
3334cf7f2e2dSJohn Marino     }
3335cf7f2e2dSJohn Marino 
33365796c8dcSSimon Schubert   return NULL;
33375796c8dcSSimon Schubert }
33385796c8dcSSimon Schubert 
33395796c8dcSSimon Schubert 
33405796c8dcSSimon Schubert /* Stuff for WIN32 PE style DLL's but is pretty generic really.  */
33415796c8dcSSimon Schubert 
33425796c8dcSSimon Schubert CORE_ADDR
i386_pe_skip_trampoline_code(struct frame_info * frame,CORE_ADDR pc,char * name)33435796c8dcSSimon Schubert i386_pe_skip_trampoline_code (struct frame_info *frame,
33445796c8dcSSimon Schubert 			      CORE_ADDR pc, char *name)
33455796c8dcSSimon Schubert {
33465796c8dcSSimon Schubert   struct gdbarch *gdbarch = get_frame_arch (frame);
33475796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
33485796c8dcSSimon Schubert 
33495796c8dcSSimon Schubert   /* jmp *(dest) */
33505796c8dcSSimon Schubert   if (pc && read_memory_unsigned_integer (pc, 2, byte_order) == 0x25ff)
33515796c8dcSSimon Schubert     {
33525796c8dcSSimon Schubert       unsigned long indirect =
33535796c8dcSSimon Schubert 	read_memory_unsigned_integer (pc + 2, 4, byte_order);
33545796c8dcSSimon Schubert       struct minimal_symbol *indsym =
33555796c8dcSSimon Schubert 	indirect ? lookup_minimal_symbol_by_pc (indirect) : 0;
3356*ef5ccd6cSJohn Marino       const char *symname = indsym ? SYMBOL_LINKAGE_NAME (indsym) : 0;
33575796c8dcSSimon Schubert 
33585796c8dcSSimon Schubert       if (symname)
33595796c8dcSSimon Schubert 	{
33605796c8dcSSimon Schubert 	  if (strncmp (symname, "__imp_", 6) == 0
33615796c8dcSSimon Schubert 	      || strncmp (symname, "_imp_", 5) == 0)
33625796c8dcSSimon Schubert 	    return name ? 1 :
33635796c8dcSSimon Schubert 		   read_memory_unsigned_integer (indirect, 4, byte_order);
33645796c8dcSSimon Schubert 	}
33655796c8dcSSimon Schubert     }
33665796c8dcSSimon Schubert   return 0;			/* Not a trampoline.  */
33675796c8dcSSimon Schubert }
33685796c8dcSSimon Schubert 
33695796c8dcSSimon Schubert 
33705796c8dcSSimon Schubert /* Return whether the THIS_FRAME corresponds to a sigtramp
33715796c8dcSSimon Schubert    routine.  */
33725796c8dcSSimon Schubert 
33735796c8dcSSimon Schubert int
i386_sigtramp_p(struct frame_info * this_frame)33745796c8dcSSimon Schubert i386_sigtramp_p (struct frame_info *this_frame)
33755796c8dcSSimon Schubert {
33765796c8dcSSimon Schubert   CORE_ADDR pc = get_frame_pc (this_frame);
3377*ef5ccd6cSJohn Marino   const char *name;
33785796c8dcSSimon Schubert 
33795796c8dcSSimon Schubert   find_pc_partial_function (pc, &name, NULL, NULL);
33805796c8dcSSimon Schubert   return (name && strcmp ("_sigtramp", name) == 0);
33815796c8dcSSimon Schubert }
33825796c8dcSSimon Schubert 
33835796c8dcSSimon Schubert 
33845796c8dcSSimon Schubert /* We have two flavours of disassembly.  The machinery on this page
33855796c8dcSSimon Schubert    deals with switching between those.  */
33865796c8dcSSimon Schubert 
33875796c8dcSSimon Schubert static int
i386_print_insn(bfd_vma pc,struct disassemble_info * info)33885796c8dcSSimon Schubert i386_print_insn (bfd_vma pc, struct disassemble_info *info)
33895796c8dcSSimon Schubert {
33905796c8dcSSimon Schubert   gdb_assert (disassembly_flavor == att_flavor
33915796c8dcSSimon Schubert 	      || disassembly_flavor == intel_flavor);
33925796c8dcSSimon Schubert 
33935796c8dcSSimon Schubert   /* FIXME: kettenis/20020915: Until disassembler_options is properly
33945796c8dcSSimon Schubert      constified, cast to prevent a compiler warning.  */
33955796c8dcSSimon Schubert   info->disassembler_options = (char *) disassembly_flavor;
33965796c8dcSSimon Schubert 
33975796c8dcSSimon Schubert   return print_insn_i386 (pc, info);
33985796c8dcSSimon Schubert }
33995796c8dcSSimon Schubert 
34005796c8dcSSimon Schubert 
34015796c8dcSSimon Schubert /* There are a few i386 architecture variants that differ only
34025796c8dcSSimon Schubert    slightly from the generic i386 target.  For now, we don't give them
34035796c8dcSSimon Schubert    their own source file, but include them here.  As a consequence,
34045796c8dcSSimon Schubert    they'll always be included.  */
34055796c8dcSSimon Schubert 
34065796c8dcSSimon Schubert /* System V Release 4 (SVR4).  */
34075796c8dcSSimon Schubert 
34085796c8dcSSimon Schubert /* Return whether THIS_FRAME corresponds to a SVR4 sigtramp
34095796c8dcSSimon Schubert    routine.  */
34105796c8dcSSimon Schubert 
34115796c8dcSSimon Schubert static int
i386_svr4_sigtramp_p(struct frame_info * this_frame)34125796c8dcSSimon Schubert i386_svr4_sigtramp_p (struct frame_info *this_frame)
34135796c8dcSSimon Schubert {
34145796c8dcSSimon Schubert   CORE_ADDR pc = get_frame_pc (this_frame);
3415*ef5ccd6cSJohn Marino   const char *name;
34165796c8dcSSimon Schubert 
3417*ef5ccd6cSJohn Marino   /* The origin of these symbols is currently unknown.  */
34185796c8dcSSimon Schubert   find_pc_partial_function (pc, &name, NULL, NULL);
34195796c8dcSSimon Schubert   return (name && (strcmp ("_sigreturn", name) == 0
34205796c8dcSSimon Schubert 		   || strcmp ("sigvechandler", name) == 0));
34215796c8dcSSimon Schubert }
34225796c8dcSSimon Schubert 
34235796c8dcSSimon Schubert /* Assuming THIS_FRAME is for a SVR4 sigtramp routine, return the
34245796c8dcSSimon Schubert    address of the associated sigcontext (ucontext) structure.  */
34255796c8dcSSimon Schubert 
34265796c8dcSSimon Schubert static CORE_ADDR
i386_svr4_sigcontext_addr(struct frame_info * this_frame)34275796c8dcSSimon Schubert i386_svr4_sigcontext_addr (struct frame_info *this_frame)
34285796c8dcSSimon Schubert {
34295796c8dcSSimon Schubert   struct gdbarch *gdbarch = get_frame_arch (this_frame);
34305796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
34315796c8dcSSimon Schubert   gdb_byte buf[4];
34325796c8dcSSimon Schubert   CORE_ADDR sp;
34335796c8dcSSimon Schubert 
34345796c8dcSSimon Schubert   get_frame_register (this_frame, I386_ESP_REGNUM, buf);
34355796c8dcSSimon Schubert   sp = extract_unsigned_integer (buf, 4, byte_order);
34365796c8dcSSimon Schubert 
34375796c8dcSSimon Schubert   return read_memory_unsigned_integer (sp + 8, 4, byte_order);
34385796c8dcSSimon Schubert }
3439*ef5ccd6cSJohn Marino 
3440*ef5ccd6cSJohn Marino 
3441*ef5ccd6cSJohn Marino 
3442*ef5ccd6cSJohn Marino /* Implementation of `gdbarch_stap_is_single_operand', as defined in
3443*ef5ccd6cSJohn Marino    gdbarch.h.  */
3444*ef5ccd6cSJohn Marino 
3445*ef5ccd6cSJohn Marino int
i386_stap_is_single_operand(struct gdbarch * gdbarch,const char * s)3446*ef5ccd6cSJohn Marino i386_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
3447*ef5ccd6cSJohn Marino {
3448*ef5ccd6cSJohn Marino   return (*s == '$' /* Literal number.  */
3449*ef5ccd6cSJohn Marino 	  || (isdigit (*s) && s[1] == '(' && s[2] == '%') /* Displacement.  */
3450*ef5ccd6cSJohn Marino 	  || (*s == '(' && s[1] == '%') /* Register indirection.  */
3451*ef5ccd6cSJohn Marino 	  || (*s == '%' && isalpha (s[1]))); /* Register access.  */
3452*ef5ccd6cSJohn Marino }
3453*ef5ccd6cSJohn Marino 
3454*ef5ccd6cSJohn Marino /* Implementation of `gdbarch_stap_parse_special_token', as defined in
3455*ef5ccd6cSJohn Marino    gdbarch.h.  */
3456*ef5ccd6cSJohn Marino 
3457*ef5ccd6cSJohn Marino int
i386_stap_parse_special_token(struct gdbarch * gdbarch,struct stap_parse_info * p)3458*ef5ccd6cSJohn Marino i386_stap_parse_special_token (struct gdbarch *gdbarch,
3459*ef5ccd6cSJohn Marino 			       struct stap_parse_info *p)
3460*ef5ccd6cSJohn Marino {
3461*ef5ccd6cSJohn Marino   /* In order to parse special tokens, we use a state-machine that go
3462*ef5ccd6cSJohn Marino      through every known token and try to get a match.  */
3463*ef5ccd6cSJohn Marino   enum
3464*ef5ccd6cSJohn Marino     {
3465*ef5ccd6cSJohn Marino       TRIPLET,
3466*ef5ccd6cSJohn Marino       THREE_ARG_DISPLACEMENT,
3467*ef5ccd6cSJohn Marino       DONE
3468*ef5ccd6cSJohn Marino     } current_state;
3469*ef5ccd6cSJohn Marino 
3470*ef5ccd6cSJohn Marino   current_state = TRIPLET;
3471*ef5ccd6cSJohn Marino 
3472*ef5ccd6cSJohn Marino   /* The special tokens to be parsed here are:
3473*ef5ccd6cSJohn Marino 
3474*ef5ccd6cSJohn Marino      - `register base + (register index * size) + offset', as represented
3475*ef5ccd6cSJohn Marino      in `(%rcx,%rax,8)', or `[OFFSET](BASE_REG,INDEX_REG[,SIZE])'.
3476*ef5ccd6cSJohn Marino 
3477*ef5ccd6cSJohn Marino      - Operands of the form `-8+3+1(%rbp)', which must be interpreted as
3478*ef5ccd6cSJohn Marino      `*(-8 + 3 - 1 + (void *) $eax)'.  */
3479*ef5ccd6cSJohn Marino 
3480*ef5ccd6cSJohn Marino   while (current_state != DONE)
3481*ef5ccd6cSJohn Marino     {
3482*ef5ccd6cSJohn Marino       const char *s = p->arg;
3483*ef5ccd6cSJohn Marino 
3484*ef5ccd6cSJohn Marino       switch (current_state)
3485*ef5ccd6cSJohn Marino 	{
3486*ef5ccd6cSJohn Marino 	case TRIPLET:
3487*ef5ccd6cSJohn Marino 	    {
3488*ef5ccd6cSJohn Marino 	      if (isdigit (*s) || *s == '-' || *s == '+')
3489*ef5ccd6cSJohn Marino 		{
3490*ef5ccd6cSJohn Marino 		  int got_minus[3];
3491*ef5ccd6cSJohn Marino 		  int i;
3492*ef5ccd6cSJohn Marino 		  long displacements[3];
3493*ef5ccd6cSJohn Marino 		  const char *start;
3494*ef5ccd6cSJohn Marino 		  char *regname;
3495*ef5ccd6cSJohn Marino 		  int len;
3496*ef5ccd6cSJohn Marino 		  struct stoken str;
3497*ef5ccd6cSJohn Marino 
3498*ef5ccd6cSJohn Marino 		  got_minus[0] = 0;
3499*ef5ccd6cSJohn Marino 		  if (*s == '+')
3500*ef5ccd6cSJohn Marino 		    ++s;
3501*ef5ccd6cSJohn Marino 		  else if (*s == '-')
3502*ef5ccd6cSJohn Marino 		    {
3503*ef5ccd6cSJohn Marino 		      ++s;
3504*ef5ccd6cSJohn Marino 		      got_minus[0] = 1;
3505*ef5ccd6cSJohn Marino 		    }
3506*ef5ccd6cSJohn Marino 
3507*ef5ccd6cSJohn Marino 		  displacements[0] = strtol (s, (char **) &s, 10);
3508*ef5ccd6cSJohn Marino 
3509*ef5ccd6cSJohn Marino 		  if (*s != '+' && *s != '-')
3510*ef5ccd6cSJohn Marino 		    {
3511*ef5ccd6cSJohn Marino 		      /* We are not dealing with a triplet.  */
3512*ef5ccd6cSJohn Marino 		      break;
3513*ef5ccd6cSJohn Marino 		    }
3514*ef5ccd6cSJohn Marino 
3515*ef5ccd6cSJohn Marino 		  got_minus[1] = 0;
3516*ef5ccd6cSJohn Marino 		  if (*s == '+')
3517*ef5ccd6cSJohn Marino 		    ++s;
3518*ef5ccd6cSJohn Marino 		  else
3519*ef5ccd6cSJohn Marino 		    {
3520*ef5ccd6cSJohn Marino 		      ++s;
3521*ef5ccd6cSJohn Marino 		      got_minus[1] = 1;
3522*ef5ccd6cSJohn Marino 		    }
3523*ef5ccd6cSJohn Marino 
3524*ef5ccd6cSJohn Marino 		  displacements[1] = strtol (s, (char **) &s, 10);
3525*ef5ccd6cSJohn Marino 
3526*ef5ccd6cSJohn Marino 		  if (*s != '+' && *s != '-')
3527*ef5ccd6cSJohn Marino 		    {
3528*ef5ccd6cSJohn Marino 		      /* We are not dealing with a triplet.  */
3529*ef5ccd6cSJohn Marino 		      break;
3530*ef5ccd6cSJohn Marino 		    }
3531*ef5ccd6cSJohn Marino 
3532*ef5ccd6cSJohn Marino 		  got_minus[2] = 0;
3533*ef5ccd6cSJohn Marino 		  if (*s == '+')
3534*ef5ccd6cSJohn Marino 		    ++s;
3535*ef5ccd6cSJohn Marino 		  else
3536*ef5ccd6cSJohn Marino 		    {
3537*ef5ccd6cSJohn Marino 		      ++s;
3538*ef5ccd6cSJohn Marino 		      got_minus[2] = 1;
3539*ef5ccd6cSJohn Marino 		    }
3540*ef5ccd6cSJohn Marino 
3541*ef5ccd6cSJohn Marino 		  displacements[2] = strtol (s, (char **) &s, 10);
3542*ef5ccd6cSJohn Marino 
3543*ef5ccd6cSJohn Marino 		  if (*s != '(' || s[1] != '%')
3544*ef5ccd6cSJohn Marino 		    break;
3545*ef5ccd6cSJohn Marino 
3546*ef5ccd6cSJohn Marino 		  s += 2;
3547*ef5ccd6cSJohn Marino 		  start = s;
3548*ef5ccd6cSJohn Marino 
3549*ef5ccd6cSJohn Marino 		  while (isalnum (*s))
3550*ef5ccd6cSJohn Marino 		    ++s;
3551*ef5ccd6cSJohn Marino 
3552*ef5ccd6cSJohn Marino 		  if (*s++ != ')')
3553*ef5ccd6cSJohn Marino 		    break;
3554*ef5ccd6cSJohn Marino 
3555*ef5ccd6cSJohn Marino 		  len = s - start;
3556*ef5ccd6cSJohn Marino 		  regname = alloca (len + 1);
3557*ef5ccd6cSJohn Marino 
3558*ef5ccd6cSJohn Marino 		  strncpy (regname, start, len);
3559*ef5ccd6cSJohn Marino 		  regname[len] = '\0';
3560*ef5ccd6cSJohn Marino 
3561*ef5ccd6cSJohn Marino 		  if (user_reg_map_name_to_regnum (gdbarch,
3562*ef5ccd6cSJohn Marino 						   regname, len) == -1)
3563*ef5ccd6cSJohn Marino 		    error (_("Invalid register name `%s' "
3564*ef5ccd6cSJohn Marino 			     "on expression `%s'."),
3565*ef5ccd6cSJohn Marino 			   regname, p->saved_arg);
3566*ef5ccd6cSJohn Marino 
3567*ef5ccd6cSJohn Marino 		  for (i = 0; i < 3; i++)
3568*ef5ccd6cSJohn Marino 		    {
3569*ef5ccd6cSJohn Marino 		      write_exp_elt_opcode (OP_LONG);
3570*ef5ccd6cSJohn Marino 		      write_exp_elt_type
3571*ef5ccd6cSJohn Marino 			(builtin_type (gdbarch)->builtin_long);
3572*ef5ccd6cSJohn Marino 		      write_exp_elt_longcst (displacements[i]);
3573*ef5ccd6cSJohn Marino 		      write_exp_elt_opcode (OP_LONG);
3574*ef5ccd6cSJohn Marino 		      if (got_minus[i])
3575*ef5ccd6cSJohn Marino 			write_exp_elt_opcode (UNOP_NEG);
3576*ef5ccd6cSJohn Marino 		    }
3577*ef5ccd6cSJohn Marino 
3578*ef5ccd6cSJohn Marino 		  write_exp_elt_opcode (OP_REGISTER);
3579*ef5ccd6cSJohn Marino 		  str.ptr = regname;
3580*ef5ccd6cSJohn Marino 		  str.length = len;
3581*ef5ccd6cSJohn Marino 		  write_exp_string (str);
3582*ef5ccd6cSJohn Marino 		  write_exp_elt_opcode (OP_REGISTER);
3583*ef5ccd6cSJohn Marino 
3584*ef5ccd6cSJohn Marino 		  write_exp_elt_opcode (UNOP_CAST);
3585*ef5ccd6cSJohn Marino 		  write_exp_elt_type (builtin_type (gdbarch)->builtin_data_ptr);
3586*ef5ccd6cSJohn Marino 		  write_exp_elt_opcode (UNOP_CAST);
3587*ef5ccd6cSJohn Marino 
3588*ef5ccd6cSJohn Marino 		  write_exp_elt_opcode (BINOP_ADD);
3589*ef5ccd6cSJohn Marino 		  write_exp_elt_opcode (BINOP_ADD);
3590*ef5ccd6cSJohn Marino 		  write_exp_elt_opcode (BINOP_ADD);
3591*ef5ccd6cSJohn Marino 
3592*ef5ccd6cSJohn Marino 		  write_exp_elt_opcode (UNOP_CAST);
3593*ef5ccd6cSJohn Marino 		  write_exp_elt_type (lookup_pointer_type (p->arg_type));
3594*ef5ccd6cSJohn Marino 		  write_exp_elt_opcode (UNOP_CAST);
3595*ef5ccd6cSJohn Marino 
3596*ef5ccd6cSJohn Marino 		  write_exp_elt_opcode (UNOP_IND);
3597*ef5ccd6cSJohn Marino 
3598*ef5ccd6cSJohn Marino 		  p->arg = s;
3599*ef5ccd6cSJohn Marino 
3600*ef5ccd6cSJohn Marino 		  return 1;
3601*ef5ccd6cSJohn Marino 		}
3602*ef5ccd6cSJohn Marino 	      break;
3603*ef5ccd6cSJohn Marino 	    }
3604*ef5ccd6cSJohn Marino 	case THREE_ARG_DISPLACEMENT:
3605*ef5ccd6cSJohn Marino 	    {
3606*ef5ccd6cSJohn Marino 	      if (isdigit (*s) || *s == '(' || *s == '-' || *s == '+')
3607*ef5ccd6cSJohn Marino 		{
3608*ef5ccd6cSJohn Marino 		  int offset_minus = 0;
3609*ef5ccd6cSJohn Marino 		  long offset = 0;
3610*ef5ccd6cSJohn Marino 		  int size_minus = 0;
3611*ef5ccd6cSJohn Marino 		  long size = 0;
3612*ef5ccd6cSJohn Marino 		  const char *start;
3613*ef5ccd6cSJohn Marino 		  char *base;
3614*ef5ccd6cSJohn Marino 		  int len_base;
3615*ef5ccd6cSJohn Marino 		  char *index;
3616*ef5ccd6cSJohn Marino 		  int len_index;
3617*ef5ccd6cSJohn Marino 		  struct stoken base_token, index_token;
3618*ef5ccd6cSJohn Marino 
3619*ef5ccd6cSJohn Marino 		  if (*s == '+')
3620*ef5ccd6cSJohn Marino 		    ++s;
3621*ef5ccd6cSJohn Marino 		  else if (*s == '-')
3622*ef5ccd6cSJohn Marino 		    {
3623*ef5ccd6cSJohn Marino 		      ++s;
3624*ef5ccd6cSJohn Marino 		      offset_minus = 1;
3625*ef5ccd6cSJohn Marino 		    }
3626*ef5ccd6cSJohn Marino 
3627*ef5ccd6cSJohn Marino 		  if (offset_minus && !isdigit (*s))
3628*ef5ccd6cSJohn Marino 		    break;
3629*ef5ccd6cSJohn Marino 
3630*ef5ccd6cSJohn Marino 		  if (isdigit (*s))
3631*ef5ccd6cSJohn Marino 		    offset = strtol (s, (char **) &s, 10);
3632*ef5ccd6cSJohn Marino 
3633*ef5ccd6cSJohn Marino 		  if (*s != '(' || s[1] != '%')
3634*ef5ccd6cSJohn Marino 		    break;
3635*ef5ccd6cSJohn Marino 
3636*ef5ccd6cSJohn Marino 		  s += 2;
3637*ef5ccd6cSJohn Marino 		  start = s;
3638*ef5ccd6cSJohn Marino 
3639*ef5ccd6cSJohn Marino 		  while (isalnum (*s))
3640*ef5ccd6cSJohn Marino 		    ++s;
3641*ef5ccd6cSJohn Marino 
3642*ef5ccd6cSJohn Marino 		  if (*s != ',' || s[1] != '%')
3643*ef5ccd6cSJohn Marino 		    break;
3644*ef5ccd6cSJohn Marino 
3645*ef5ccd6cSJohn Marino 		  len_base = s - start;
3646*ef5ccd6cSJohn Marino 		  base = alloca (len_base + 1);
3647*ef5ccd6cSJohn Marino 		  strncpy (base, start, len_base);
3648*ef5ccd6cSJohn Marino 		  base[len_base] = '\0';
3649*ef5ccd6cSJohn Marino 
3650*ef5ccd6cSJohn Marino 		  if (user_reg_map_name_to_regnum (gdbarch,
3651*ef5ccd6cSJohn Marino 						   base, len_base) == -1)
3652*ef5ccd6cSJohn Marino 		    error (_("Invalid register name `%s' "
3653*ef5ccd6cSJohn Marino 			     "on expression `%s'."),
3654*ef5ccd6cSJohn Marino 			   base, p->saved_arg);
3655*ef5ccd6cSJohn Marino 
3656*ef5ccd6cSJohn Marino 		  s += 2;
3657*ef5ccd6cSJohn Marino 		  start = s;
3658*ef5ccd6cSJohn Marino 
3659*ef5ccd6cSJohn Marino 		  while (isalnum (*s))
3660*ef5ccd6cSJohn Marino 		    ++s;
3661*ef5ccd6cSJohn Marino 
3662*ef5ccd6cSJohn Marino 		  len_index = s - start;
3663*ef5ccd6cSJohn Marino 		  index = alloca (len_index + 1);
3664*ef5ccd6cSJohn Marino 		  strncpy (index, start, len_index);
3665*ef5ccd6cSJohn Marino 		  index[len_index] = '\0';
3666*ef5ccd6cSJohn Marino 
3667*ef5ccd6cSJohn Marino 		  if (user_reg_map_name_to_regnum (gdbarch,
3668*ef5ccd6cSJohn Marino 						   index, len_index) == -1)
3669*ef5ccd6cSJohn Marino 		    error (_("Invalid register name `%s' "
3670*ef5ccd6cSJohn Marino 			     "on expression `%s'."),
3671*ef5ccd6cSJohn Marino 			   index, p->saved_arg);
3672*ef5ccd6cSJohn Marino 
3673*ef5ccd6cSJohn Marino 		  if (*s != ',' && *s != ')')
3674*ef5ccd6cSJohn Marino 		    break;
3675*ef5ccd6cSJohn Marino 
3676*ef5ccd6cSJohn Marino 		  if (*s == ',')
3677*ef5ccd6cSJohn Marino 		    {
3678*ef5ccd6cSJohn Marino 		      ++s;
3679*ef5ccd6cSJohn Marino 		      if (*s == '+')
3680*ef5ccd6cSJohn Marino 			++s;
3681*ef5ccd6cSJohn Marino 		      else if (*s == '-')
3682*ef5ccd6cSJohn Marino 			{
3683*ef5ccd6cSJohn Marino 			  ++s;
3684*ef5ccd6cSJohn Marino 			  size_minus = 1;
3685*ef5ccd6cSJohn Marino 			}
3686*ef5ccd6cSJohn Marino 
3687*ef5ccd6cSJohn Marino 		      size = strtol (s, (char **) &s, 10);
3688*ef5ccd6cSJohn Marino 
3689*ef5ccd6cSJohn Marino 		      if (*s != ')')
3690*ef5ccd6cSJohn Marino 			break;
3691*ef5ccd6cSJohn Marino 		    }
3692*ef5ccd6cSJohn Marino 
3693*ef5ccd6cSJohn Marino 		  ++s;
3694*ef5ccd6cSJohn Marino 
3695*ef5ccd6cSJohn Marino 		  if (offset)
3696*ef5ccd6cSJohn Marino 		    {
3697*ef5ccd6cSJohn Marino 		      write_exp_elt_opcode (OP_LONG);
3698*ef5ccd6cSJohn Marino 		      write_exp_elt_type
3699*ef5ccd6cSJohn Marino 			(builtin_type (gdbarch)->builtin_long);
3700*ef5ccd6cSJohn Marino 		      write_exp_elt_longcst (offset);
3701*ef5ccd6cSJohn Marino 		      write_exp_elt_opcode (OP_LONG);
3702*ef5ccd6cSJohn Marino 		      if (offset_minus)
3703*ef5ccd6cSJohn Marino 			write_exp_elt_opcode (UNOP_NEG);
3704*ef5ccd6cSJohn Marino 		    }
3705*ef5ccd6cSJohn Marino 
3706*ef5ccd6cSJohn Marino 		  write_exp_elt_opcode (OP_REGISTER);
3707*ef5ccd6cSJohn Marino 		  base_token.ptr = base;
3708*ef5ccd6cSJohn Marino 		  base_token.length = len_base;
3709*ef5ccd6cSJohn Marino 		  write_exp_string (base_token);
3710*ef5ccd6cSJohn Marino 		  write_exp_elt_opcode (OP_REGISTER);
3711*ef5ccd6cSJohn Marino 
3712*ef5ccd6cSJohn Marino 		  if (offset)
3713*ef5ccd6cSJohn Marino 		    write_exp_elt_opcode (BINOP_ADD);
3714*ef5ccd6cSJohn Marino 
3715*ef5ccd6cSJohn Marino 		  write_exp_elt_opcode (OP_REGISTER);
3716*ef5ccd6cSJohn Marino 		  index_token.ptr = index;
3717*ef5ccd6cSJohn Marino 		  index_token.length = len_index;
3718*ef5ccd6cSJohn Marino 		  write_exp_string (index_token);
3719*ef5ccd6cSJohn Marino 		  write_exp_elt_opcode (OP_REGISTER);
3720*ef5ccd6cSJohn Marino 
3721*ef5ccd6cSJohn Marino 		  if (size)
3722*ef5ccd6cSJohn Marino 		    {
3723*ef5ccd6cSJohn Marino 		      write_exp_elt_opcode (OP_LONG);
3724*ef5ccd6cSJohn Marino 		      write_exp_elt_type
3725*ef5ccd6cSJohn Marino 			(builtin_type (gdbarch)->builtin_long);
3726*ef5ccd6cSJohn Marino 		      write_exp_elt_longcst (size);
3727*ef5ccd6cSJohn Marino 		      write_exp_elt_opcode (OP_LONG);
3728*ef5ccd6cSJohn Marino 		      if (size_minus)
3729*ef5ccd6cSJohn Marino 			write_exp_elt_opcode (UNOP_NEG);
3730*ef5ccd6cSJohn Marino 		      write_exp_elt_opcode (BINOP_MUL);
3731*ef5ccd6cSJohn Marino 		    }
3732*ef5ccd6cSJohn Marino 
3733*ef5ccd6cSJohn Marino 		  write_exp_elt_opcode (BINOP_ADD);
3734*ef5ccd6cSJohn Marino 
3735*ef5ccd6cSJohn Marino 		  write_exp_elt_opcode (UNOP_CAST);
3736*ef5ccd6cSJohn Marino 		  write_exp_elt_type (lookup_pointer_type (p->arg_type));
3737*ef5ccd6cSJohn Marino 		  write_exp_elt_opcode (UNOP_CAST);
3738*ef5ccd6cSJohn Marino 
3739*ef5ccd6cSJohn Marino 		  write_exp_elt_opcode (UNOP_IND);
3740*ef5ccd6cSJohn Marino 
3741*ef5ccd6cSJohn Marino 		  p->arg = s;
3742*ef5ccd6cSJohn Marino 
3743*ef5ccd6cSJohn Marino 		  return 1;
3744*ef5ccd6cSJohn Marino 		}
3745*ef5ccd6cSJohn Marino 	      break;
3746*ef5ccd6cSJohn Marino 	    }
3747*ef5ccd6cSJohn Marino 	}
3748*ef5ccd6cSJohn Marino 
3749*ef5ccd6cSJohn Marino       /* Advancing to the next state.  */
3750*ef5ccd6cSJohn Marino       ++current_state;
3751*ef5ccd6cSJohn Marino     }
3752*ef5ccd6cSJohn Marino 
3753*ef5ccd6cSJohn Marino   return 0;
3754*ef5ccd6cSJohn Marino }
3755*ef5ccd6cSJohn Marino 
37565796c8dcSSimon Schubert 
37575796c8dcSSimon Schubert 
37585796c8dcSSimon Schubert /* Generic ELF.  */
37595796c8dcSSimon Schubert 
37605796c8dcSSimon Schubert void
i386_elf_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)37615796c8dcSSimon Schubert i386_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
37625796c8dcSSimon Schubert {
37635796c8dcSSimon Schubert   /* We typically use stabs-in-ELF with the SVR4 register numbering.  */
37645796c8dcSSimon Schubert   set_gdbarch_stab_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
3765*ef5ccd6cSJohn Marino 
3766*ef5ccd6cSJohn Marino   /* Registering SystemTap handlers.  */
3767*ef5ccd6cSJohn Marino   set_gdbarch_stap_integer_prefix (gdbarch, "$");
3768*ef5ccd6cSJohn Marino   set_gdbarch_stap_register_prefix (gdbarch, "%");
3769*ef5ccd6cSJohn Marino   set_gdbarch_stap_register_indirection_prefix (gdbarch, "(");
3770*ef5ccd6cSJohn Marino   set_gdbarch_stap_register_indirection_suffix (gdbarch, ")");
3771*ef5ccd6cSJohn Marino   set_gdbarch_stap_is_single_operand (gdbarch,
3772*ef5ccd6cSJohn Marino 				      i386_stap_is_single_operand);
3773*ef5ccd6cSJohn Marino   set_gdbarch_stap_parse_special_token (gdbarch,
3774*ef5ccd6cSJohn Marino 					i386_stap_parse_special_token);
37755796c8dcSSimon Schubert }
37765796c8dcSSimon Schubert 
37775796c8dcSSimon Schubert /* System V Release 4 (SVR4).  */
37785796c8dcSSimon Schubert 
37795796c8dcSSimon Schubert void
i386_svr4_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)37805796c8dcSSimon Schubert i386_svr4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
37815796c8dcSSimon Schubert {
37825796c8dcSSimon Schubert   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
37835796c8dcSSimon Schubert 
37845796c8dcSSimon Schubert   /* System V Release 4 uses ELF.  */
37855796c8dcSSimon Schubert   i386_elf_init_abi (info, gdbarch);
37865796c8dcSSimon Schubert 
37875796c8dcSSimon Schubert   /* System V Release 4 has shared libraries.  */
37885796c8dcSSimon Schubert   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
37895796c8dcSSimon Schubert 
37905796c8dcSSimon Schubert   tdep->sigtramp_p = i386_svr4_sigtramp_p;
37915796c8dcSSimon Schubert   tdep->sigcontext_addr = i386_svr4_sigcontext_addr;
37925796c8dcSSimon Schubert   tdep->sc_pc_offset = 36 + 14 * 4;
37935796c8dcSSimon Schubert   tdep->sc_sp_offset = 36 + 17 * 4;
37945796c8dcSSimon Schubert 
37955796c8dcSSimon Schubert   tdep->jb_pc_offset = 20;
37965796c8dcSSimon Schubert }
37975796c8dcSSimon Schubert 
37985796c8dcSSimon Schubert /* DJGPP.  */
37995796c8dcSSimon Schubert 
38005796c8dcSSimon Schubert static void
i386_go32_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)38015796c8dcSSimon Schubert i386_go32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
38025796c8dcSSimon Schubert {
38035796c8dcSSimon Schubert   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
38045796c8dcSSimon Schubert 
38055796c8dcSSimon Schubert   /* DJGPP doesn't have any special frames for signal handlers.  */
38065796c8dcSSimon Schubert   tdep->sigtramp_p = NULL;
38075796c8dcSSimon Schubert 
38085796c8dcSSimon Schubert   tdep->jb_pc_offset = 36;
38095796c8dcSSimon Schubert 
38105796c8dcSSimon Schubert   /* DJGPP does not support the SSE registers.  */
3811cf7f2e2dSJohn Marino   if (! tdesc_has_registers (info.target_desc))
3812cf7f2e2dSJohn Marino     tdep->tdesc = tdesc_i386_mmx;
38135796c8dcSSimon Schubert 
38145796c8dcSSimon Schubert   /* Native compiler is GCC, which uses the SVR4 register numbering
38155796c8dcSSimon Schubert      even in COFF and STABS.  See the comment in i386_gdbarch_init,
38165796c8dcSSimon Schubert      before the calls to set_gdbarch_stab_reg_to_regnum and
38175796c8dcSSimon Schubert      set_gdbarch_sdb_reg_to_regnum.  */
38185796c8dcSSimon Schubert   set_gdbarch_stab_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
38195796c8dcSSimon Schubert   set_gdbarch_sdb_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
3820cf7f2e2dSJohn Marino 
3821cf7f2e2dSJohn Marino   set_gdbarch_has_dos_based_file_system (gdbarch, 1);
38225796c8dcSSimon Schubert }
38235796c8dcSSimon Schubert 
38245796c8dcSSimon Schubert 
38255796c8dcSSimon Schubert /* i386 register groups.  In addition to the normal groups, add "mmx"
38265796c8dcSSimon Schubert    and "sse".  */
38275796c8dcSSimon Schubert 
38285796c8dcSSimon Schubert static struct reggroup *i386_sse_reggroup;
38295796c8dcSSimon Schubert static struct reggroup *i386_mmx_reggroup;
38305796c8dcSSimon Schubert 
38315796c8dcSSimon Schubert static void
i386_init_reggroups(void)38325796c8dcSSimon Schubert i386_init_reggroups (void)
38335796c8dcSSimon Schubert {
38345796c8dcSSimon Schubert   i386_sse_reggroup = reggroup_new ("sse", USER_REGGROUP);
38355796c8dcSSimon Schubert   i386_mmx_reggroup = reggroup_new ("mmx", USER_REGGROUP);
38365796c8dcSSimon Schubert }
38375796c8dcSSimon Schubert 
38385796c8dcSSimon Schubert static void
i386_add_reggroups(struct gdbarch * gdbarch)38395796c8dcSSimon Schubert i386_add_reggroups (struct gdbarch *gdbarch)
38405796c8dcSSimon Schubert {
38415796c8dcSSimon Schubert   reggroup_add (gdbarch, i386_sse_reggroup);
38425796c8dcSSimon Schubert   reggroup_add (gdbarch, i386_mmx_reggroup);
38435796c8dcSSimon Schubert   reggroup_add (gdbarch, general_reggroup);
38445796c8dcSSimon Schubert   reggroup_add (gdbarch, float_reggroup);
38455796c8dcSSimon Schubert   reggroup_add (gdbarch, all_reggroup);
38465796c8dcSSimon Schubert   reggroup_add (gdbarch, save_reggroup);
38475796c8dcSSimon Schubert   reggroup_add (gdbarch, restore_reggroup);
38485796c8dcSSimon Schubert   reggroup_add (gdbarch, vector_reggroup);
38495796c8dcSSimon Schubert   reggroup_add (gdbarch, system_reggroup);
38505796c8dcSSimon Schubert }
38515796c8dcSSimon Schubert 
38525796c8dcSSimon Schubert int
i386_register_reggroup_p(struct gdbarch * gdbarch,int regnum,struct reggroup * group)38535796c8dcSSimon Schubert i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
38545796c8dcSSimon Schubert 			  struct reggroup *group)
38555796c8dcSSimon Schubert {
3856cf7f2e2dSJohn Marino   const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
3857cf7f2e2dSJohn Marino   int fp_regnum_p, mmx_regnum_p, xmm_regnum_p, mxcsr_regnum_p,
3858cf7f2e2dSJohn Marino       ymm_regnum_p, ymmh_regnum_p;
38595796c8dcSSimon Schubert 
3860cf7f2e2dSJohn Marino   /* Don't include pseudo registers, except for MMX, in any register
3861cf7f2e2dSJohn Marino      groups.  */
3862cf7f2e2dSJohn Marino   if (i386_byte_regnum_p (gdbarch, regnum))
3863cf7f2e2dSJohn Marino     return 0;
3864cf7f2e2dSJohn Marino 
3865cf7f2e2dSJohn Marino   if (i386_word_regnum_p (gdbarch, regnum))
3866cf7f2e2dSJohn Marino     return 0;
3867cf7f2e2dSJohn Marino 
3868cf7f2e2dSJohn Marino   if (i386_dword_regnum_p (gdbarch, regnum))
3869cf7f2e2dSJohn Marino     return 0;
3870cf7f2e2dSJohn Marino 
3871cf7f2e2dSJohn Marino   mmx_regnum_p = i386_mmx_regnum_p (gdbarch, regnum);
38725796c8dcSSimon Schubert   if (group == i386_mmx_reggroup)
38735796c8dcSSimon Schubert     return mmx_regnum_p;
3874cf7f2e2dSJohn Marino 
3875cf7f2e2dSJohn Marino   xmm_regnum_p = i386_xmm_regnum_p (gdbarch, regnum);
3876cf7f2e2dSJohn Marino   mxcsr_regnum_p = i386_mxcsr_regnum_p (gdbarch, regnum);
38775796c8dcSSimon Schubert   if (group == i386_sse_reggroup)
3878cf7f2e2dSJohn Marino     return xmm_regnum_p || mxcsr_regnum_p;
3879cf7f2e2dSJohn Marino 
3880cf7f2e2dSJohn Marino   ymm_regnum_p = i386_ymm_regnum_p (gdbarch, regnum);
38815796c8dcSSimon Schubert   if (group == vector_reggroup)
3882cf7f2e2dSJohn Marino     return (mmx_regnum_p
3883cf7f2e2dSJohn Marino 	    || ymm_regnum_p
3884cf7f2e2dSJohn Marino 	    || mxcsr_regnum_p
3885cf7f2e2dSJohn Marino 	    || (xmm_regnum_p
3886cf7f2e2dSJohn Marino 		&& ((tdep->xcr0 & I386_XSTATE_AVX_MASK)
3887cf7f2e2dSJohn Marino 		    == I386_XSTATE_SSE_MASK)));
3888cf7f2e2dSJohn Marino 
3889cf7f2e2dSJohn Marino   fp_regnum_p = (i386_fp_regnum_p (gdbarch, regnum)
3890cf7f2e2dSJohn Marino 		 || i386_fpc_regnum_p (gdbarch, regnum));
38915796c8dcSSimon Schubert   if (group == float_reggroup)
38925796c8dcSSimon Schubert     return fp_regnum_p;
3893cf7f2e2dSJohn Marino 
3894cf7f2e2dSJohn Marino   /* For "info reg all", don't include upper YMM registers nor XMM
3895cf7f2e2dSJohn Marino      registers when AVX is supported.  */
3896cf7f2e2dSJohn Marino   ymmh_regnum_p = i386_ymmh_regnum_p (gdbarch, regnum);
3897cf7f2e2dSJohn Marino   if (group == all_reggroup
3898cf7f2e2dSJohn Marino       && ((xmm_regnum_p
3899cf7f2e2dSJohn Marino 	   && (tdep->xcr0 & I386_XSTATE_AVX))
3900cf7f2e2dSJohn Marino 	  || ymmh_regnum_p))
3901cf7f2e2dSJohn Marino     return 0;
3902cf7f2e2dSJohn Marino 
39035796c8dcSSimon Schubert   if (group == general_reggroup)
3904cf7f2e2dSJohn Marino     return (!fp_regnum_p
3905cf7f2e2dSJohn Marino 	    && !mmx_regnum_p
3906cf7f2e2dSJohn Marino 	    && !mxcsr_regnum_p
3907cf7f2e2dSJohn Marino 	    && !xmm_regnum_p
3908cf7f2e2dSJohn Marino 	    && !ymm_regnum_p
3909cf7f2e2dSJohn Marino 	    && !ymmh_regnum_p);
39105796c8dcSSimon Schubert 
39115796c8dcSSimon Schubert   return default_register_reggroup_p (gdbarch, regnum, group);
39125796c8dcSSimon Schubert }
39135796c8dcSSimon Schubert 
39145796c8dcSSimon Schubert 
39155796c8dcSSimon Schubert /* Get the ARGIth function argument for the current function.  */
39165796c8dcSSimon Schubert 
39175796c8dcSSimon Schubert static CORE_ADDR
i386_fetch_pointer_argument(struct frame_info * frame,int argi,struct type * type)39185796c8dcSSimon Schubert i386_fetch_pointer_argument (struct frame_info *frame, int argi,
39195796c8dcSSimon Schubert 			     struct type *type)
39205796c8dcSSimon Schubert {
39215796c8dcSSimon Schubert   struct gdbarch *gdbarch = get_frame_arch (frame);
39225796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
39235796c8dcSSimon Schubert   CORE_ADDR sp = get_frame_register_unsigned (frame, I386_ESP_REGNUM);
39245796c8dcSSimon Schubert   return read_memory_unsigned_integer (sp + (4 * (argi + 1)), 4, byte_order);
39255796c8dcSSimon Schubert }
39265796c8dcSSimon Schubert 
39275796c8dcSSimon Schubert static void
i386_skip_permanent_breakpoint(struct regcache * regcache)39285796c8dcSSimon Schubert i386_skip_permanent_breakpoint (struct regcache *regcache)
39295796c8dcSSimon Schubert {
39305796c8dcSSimon Schubert   CORE_ADDR current_pc = regcache_read_pc (regcache);
39315796c8dcSSimon Schubert 
39325796c8dcSSimon Schubert  /* On i386, breakpoint is exactly 1 byte long, so we just
39335796c8dcSSimon Schubert     adjust the PC in the regcache.  */
39345796c8dcSSimon Schubert   current_pc += 1;
39355796c8dcSSimon Schubert   regcache_write_pc (regcache, current_pc);
39365796c8dcSSimon Schubert }
39375796c8dcSSimon Schubert 
39385796c8dcSSimon Schubert 
39395796c8dcSSimon Schubert #define PREFIX_REPZ	0x01
39405796c8dcSSimon Schubert #define PREFIX_REPNZ	0x02
39415796c8dcSSimon Schubert #define PREFIX_LOCK	0x04
39425796c8dcSSimon Schubert #define PREFIX_DATA	0x08
39435796c8dcSSimon Schubert #define PREFIX_ADDR	0x10
39445796c8dcSSimon Schubert 
39455796c8dcSSimon Schubert /* operand size */
39465796c8dcSSimon Schubert enum
39475796c8dcSSimon Schubert {
39485796c8dcSSimon Schubert   OT_BYTE = 0,
39495796c8dcSSimon Schubert   OT_WORD,
39505796c8dcSSimon Schubert   OT_LONG,
39515796c8dcSSimon Schubert   OT_QUAD,
3952cf7f2e2dSJohn Marino   OT_DQUAD,
39535796c8dcSSimon Schubert };
39545796c8dcSSimon Schubert 
39555796c8dcSSimon Schubert /* i386 arith/logic operations */
39565796c8dcSSimon Schubert enum
39575796c8dcSSimon Schubert {
39585796c8dcSSimon Schubert   OP_ADDL,
39595796c8dcSSimon Schubert   OP_ORL,
39605796c8dcSSimon Schubert   OP_ADCL,
39615796c8dcSSimon Schubert   OP_SBBL,
39625796c8dcSSimon Schubert   OP_ANDL,
39635796c8dcSSimon Schubert   OP_SUBL,
39645796c8dcSSimon Schubert   OP_XORL,
39655796c8dcSSimon Schubert   OP_CMPL,
39665796c8dcSSimon Schubert };
39675796c8dcSSimon Schubert 
39685796c8dcSSimon Schubert struct i386_record_s
39695796c8dcSSimon Schubert {
39705796c8dcSSimon Schubert   struct gdbarch *gdbarch;
39715796c8dcSSimon Schubert   struct regcache *regcache;
39725796c8dcSSimon Schubert   CORE_ADDR orig_addr;
39735796c8dcSSimon Schubert   CORE_ADDR addr;
39745796c8dcSSimon Schubert   int aflag;
39755796c8dcSSimon Schubert   int dflag;
39765796c8dcSSimon Schubert   int override;
39775796c8dcSSimon Schubert   uint8_t modrm;
39785796c8dcSSimon Schubert   uint8_t mod, reg, rm;
39795796c8dcSSimon Schubert   int ot;
39805796c8dcSSimon Schubert   uint8_t rex_x;
39815796c8dcSSimon Schubert   uint8_t rex_b;
39825796c8dcSSimon Schubert   int rip_offset;
39835796c8dcSSimon Schubert   int popl_esp_hack;
39845796c8dcSSimon Schubert   const int *regmap;
39855796c8dcSSimon Schubert };
39865796c8dcSSimon Schubert 
3987*ef5ccd6cSJohn Marino /* Parse the "modrm" part of the memory address irp->addr points at.
3988*ef5ccd6cSJohn Marino    Returns -1 if something goes wrong, 0 otherwise.  */
39895796c8dcSSimon Schubert 
39905796c8dcSSimon Schubert static int
i386_record_modrm(struct i386_record_s * irp)39915796c8dcSSimon Schubert i386_record_modrm (struct i386_record_s *irp)
39925796c8dcSSimon Schubert {
39935796c8dcSSimon Schubert   struct gdbarch *gdbarch = irp->gdbarch;
39945796c8dcSSimon Schubert 
3995*ef5ccd6cSJohn Marino   if (record_read_memory (gdbarch, irp->addr, &irp->modrm, 1))
39965796c8dcSSimon Schubert     return -1;
3997*ef5ccd6cSJohn Marino 
39985796c8dcSSimon Schubert   irp->addr++;
39995796c8dcSSimon Schubert   irp->mod = (irp->modrm >> 6) & 3;
40005796c8dcSSimon Schubert   irp->reg = (irp->modrm >> 3) & 7;
40015796c8dcSSimon Schubert   irp->rm = irp->modrm & 7;
40025796c8dcSSimon Schubert 
40035796c8dcSSimon Schubert   return 0;
40045796c8dcSSimon Schubert }
40055796c8dcSSimon Schubert 
4006*ef5ccd6cSJohn Marino /* Extract the memory address that the current instruction writes to,
4007*ef5ccd6cSJohn Marino    and return it in *ADDR.  Return -1 if something goes wrong.  */
40085796c8dcSSimon Schubert 
40095796c8dcSSimon Schubert static int
i386_record_lea_modrm_addr(struct i386_record_s * irp,uint64_t * addr)40105796c8dcSSimon Schubert i386_record_lea_modrm_addr (struct i386_record_s *irp, uint64_t *addr)
40115796c8dcSSimon Schubert {
40125796c8dcSSimon Schubert   struct gdbarch *gdbarch = irp->gdbarch;
4013cf7f2e2dSJohn Marino   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
4014cf7f2e2dSJohn Marino   gdb_byte buf[4];
4015cf7f2e2dSJohn Marino   ULONGEST offset64;
40165796c8dcSSimon Schubert 
40175796c8dcSSimon Schubert   *addr = 0;
40185796c8dcSSimon Schubert   if (irp->aflag)
40195796c8dcSSimon Schubert     {
40205796c8dcSSimon Schubert       /* 32 bits */
40215796c8dcSSimon Schubert       int havesib = 0;
40225796c8dcSSimon Schubert       uint8_t scale = 0;
4023cf7f2e2dSJohn Marino       uint8_t byte;
40245796c8dcSSimon Schubert       uint8_t index = 0;
40255796c8dcSSimon Schubert       uint8_t base = irp->rm;
40265796c8dcSSimon Schubert 
40275796c8dcSSimon Schubert       if (base == 4)
40285796c8dcSSimon Schubert 	{
40295796c8dcSSimon Schubert 	  havesib = 1;
4030*ef5ccd6cSJohn Marino 	  if (record_read_memory (gdbarch, irp->addr, &byte, 1))
40315796c8dcSSimon Schubert 	    return -1;
40325796c8dcSSimon Schubert 	  irp->addr++;
4033cf7f2e2dSJohn Marino 	  scale = (byte >> 6) & 3;
4034cf7f2e2dSJohn Marino 	  index = ((byte >> 3) & 7) | irp->rex_x;
4035cf7f2e2dSJohn Marino 	  base = (byte & 7);
40365796c8dcSSimon Schubert 	}
40375796c8dcSSimon Schubert       base |= irp->rex_b;
40385796c8dcSSimon Schubert 
40395796c8dcSSimon Schubert       switch (irp->mod)
40405796c8dcSSimon Schubert 	{
40415796c8dcSSimon Schubert 	case 0:
40425796c8dcSSimon Schubert 	  if ((base & 7) == 5)
40435796c8dcSSimon Schubert 	    {
40445796c8dcSSimon Schubert 	      base = 0xff;
4045*ef5ccd6cSJohn Marino 	      if (record_read_memory (gdbarch, irp->addr, buf, 4))
40465796c8dcSSimon Schubert 		return -1;
40475796c8dcSSimon Schubert 	      irp->addr += 4;
4048cf7f2e2dSJohn Marino 	      *addr = extract_signed_integer (buf, 4, byte_order);
40495796c8dcSSimon Schubert 	      if (irp->regmap[X86_RECORD_R8_REGNUM] && !havesib)
40505796c8dcSSimon Schubert 		*addr += irp->addr + irp->rip_offset;
40515796c8dcSSimon Schubert 	    }
40525796c8dcSSimon Schubert 	  break;
40535796c8dcSSimon Schubert 	case 1:
4054*ef5ccd6cSJohn Marino 	  if (record_read_memory (gdbarch, irp->addr, buf, 1))
40555796c8dcSSimon Schubert 	    return -1;
40565796c8dcSSimon Schubert 	  irp->addr++;
4057cf7f2e2dSJohn Marino 	  *addr = (int8_t) buf[0];
40585796c8dcSSimon Schubert 	  break;
40595796c8dcSSimon Schubert 	case 2:
4060*ef5ccd6cSJohn Marino 	  if (record_read_memory (gdbarch, irp->addr, buf, 4))
40615796c8dcSSimon Schubert 	    return -1;
4062cf7f2e2dSJohn Marino 	  *addr = extract_signed_integer (buf, 4, byte_order);
40635796c8dcSSimon Schubert 	  irp->addr += 4;
40645796c8dcSSimon Schubert 	  break;
40655796c8dcSSimon Schubert 	}
40665796c8dcSSimon Schubert 
4067cf7f2e2dSJohn Marino       offset64 = 0;
40685796c8dcSSimon Schubert       if (base != 0xff)
40695796c8dcSSimon Schubert         {
40705796c8dcSSimon Schubert 	  if (base == 4 && irp->popl_esp_hack)
40715796c8dcSSimon Schubert 	    *addr += irp->popl_esp_hack;
40725796c8dcSSimon Schubert 	  regcache_raw_read_unsigned (irp->regcache, irp->regmap[base],
4073cf7f2e2dSJohn Marino                                       &offset64);
40745796c8dcSSimon Schubert 	}
40755796c8dcSSimon Schubert       if (irp->aflag == 2)
40765796c8dcSSimon Schubert         {
4077cf7f2e2dSJohn Marino 	  *addr += offset64;
40785796c8dcSSimon Schubert         }
40795796c8dcSSimon Schubert       else
4080cf7f2e2dSJohn Marino         *addr = (uint32_t) (offset64 + *addr);
40815796c8dcSSimon Schubert 
40825796c8dcSSimon Schubert       if (havesib && (index != 4 || scale != 0))
40835796c8dcSSimon Schubert 	{
40845796c8dcSSimon Schubert 	  regcache_raw_read_unsigned (irp->regcache, irp->regmap[index],
4085cf7f2e2dSJohn Marino                                       &offset64);
40865796c8dcSSimon Schubert 	  if (irp->aflag == 2)
4087cf7f2e2dSJohn Marino 	    *addr += offset64 << scale;
40885796c8dcSSimon Schubert 	  else
4089cf7f2e2dSJohn Marino 	    *addr = (uint32_t) (*addr + (offset64 << scale));
40905796c8dcSSimon Schubert 	}
40915796c8dcSSimon Schubert     }
40925796c8dcSSimon Schubert   else
40935796c8dcSSimon Schubert     {
40945796c8dcSSimon Schubert       /* 16 bits */
40955796c8dcSSimon Schubert       switch (irp->mod)
40965796c8dcSSimon Schubert 	{
40975796c8dcSSimon Schubert 	case 0:
40985796c8dcSSimon Schubert 	  if (irp->rm == 6)
40995796c8dcSSimon Schubert 	    {
4100*ef5ccd6cSJohn Marino 	      if (record_read_memory (gdbarch, irp->addr, buf, 2))
41015796c8dcSSimon Schubert 		return -1;
41025796c8dcSSimon Schubert 	      irp->addr += 2;
4103cf7f2e2dSJohn Marino 	      *addr = extract_signed_integer (buf, 2, byte_order);
41045796c8dcSSimon Schubert 	      irp->rm = 0;
41055796c8dcSSimon Schubert 	      goto no_rm;
41065796c8dcSSimon Schubert 	    }
41075796c8dcSSimon Schubert 	  break;
41085796c8dcSSimon Schubert 	case 1:
4109*ef5ccd6cSJohn Marino 	  if (record_read_memory (gdbarch, irp->addr, buf, 1))
41105796c8dcSSimon Schubert 	    return -1;
41115796c8dcSSimon Schubert 	  irp->addr++;
4112cf7f2e2dSJohn Marino 	  *addr = (int8_t) buf[0];
41135796c8dcSSimon Schubert 	  break;
41145796c8dcSSimon Schubert 	case 2:
4115*ef5ccd6cSJohn Marino 	  if (record_read_memory (gdbarch, irp->addr, buf, 2))
41165796c8dcSSimon Schubert 	    return -1;
41175796c8dcSSimon Schubert 	  irp->addr += 2;
4118cf7f2e2dSJohn Marino 	  *addr = extract_signed_integer (buf, 2, byte_order);
41195796c8dcSSimon Schubert 	  break;
41205796c8dcSSimon Schubert 	}
41215796c8dcSSimon Schubert 
41225796c8dcSSimon Schubert       switch (irp->rm)
41235796c8dcSSimon Schubert 	{
41245796c8dcSSimon Schubert 	case 0:
41255796c8dcSSimon Schubert 	  regcache_raw_read_unsigned (irp->regcache,
41265796c8dcSSimon Schubert 				      irp->regmap[X86_RECORD_REBX_REGNUM],
4127cf7f2e2dSJohn Marino                                       &offset64);
4128cf7f2e2dSJohn Marino 	  *addr = (uint32_t) (*addr + offset64);
41295796c8dcSSimon Schubert 	  regcache_raw_read_unsigned (irp->regcache,
41305796c8dcSSimon Schubert 				      irp->regmap[X86_RECORD_RESI_REGNUM],
4131cf7f2e2dSJohn Marino                                       &offset64);
4132cf7f2e2dSJohn Marino 	  *addr = (uint32_t) (*addr + offset64);
41335796c8dcSSimon Schubert 	  break;
41345796c8dcSSimon Schubert 	case 1:
41355796c8dcSSimon Schubert 	  regcache_raw_read_unsigned (irp->regcache,
41365796c8dcSSimon Schubert 				      irp->regmap[X86_RECORD_REBX_REGNUM],
4137cf7f2e2dSJohn Marino                                       &offset64);
4138cf7f2e2dSJohn Marino 	  *addr = (uint32_t) (*addr + offset64);
41395796c8dcSSimon Schubert 	  regcache_raw_read_unsigned (irp->regcache,
41405796c8dcSSimon Schubert 				      irp->regmap[X86_RECORD_REDI_REGNUM],
4141cf7f2e2dSJohn Marino                                       &offset64);
4142cf7f2e2dSJohn Marino 	  *addr = (uint32_t) (*addr + offset64);
41435796c8dcSSimon Schubert 	  break;
41445796c8dcSSimon Schubert 	case 2:
41455796c8dcSSimon Schubert 	  regcache_raw_read_unsigned (irp->regcache,
41465796c8dcSSimon Schubert 				      irp->regmap[X86_RECORD_REBP_REGNUM],
4147cf7f2e2dSJohn Marino                                       &offset64);
4148cf7f2e2dSJohn Marino 	  *addr = (uint32_t) (*addr + offset64);
41495796c8dcSSimon Schubert 	  regcache_raw_read_unsigned (irp->regcache,
41505796c8dcSSimon Schubert 				      irp->regmap[X86_RECORD_RESI_REGNUM],
4151cf7f2e2dSJohn Marino                                       &offset64);
4152cf7f2e2dSJohn Marino 	  *addr = (uint32_t) (*addr + offset64);
41535796c8dcSSimon Schubert 	  break;
41545796c8dcSSimon Schubert 	case 3:
41555796c8dcSSimon Schubert 	  regcache_raw_read_unsigned (irp->regcache,
41565796c8dcSSimon Schubert 				      irp->regmap[X86_RECORD_REBP_REGNUM],
4157cf7f2e2dSJohn Marino                                       &offset64);
4158cf7f2e2dSJohn Marino 	  *addr = (uint32_t) (*addr + offset64);
41595796c8dcSSimon Schubert 	  regcache_raw_read_unsigned (irp->regcache,
41605796c8dcSSimon Schubert 				      irp->regmap[X86_RECORD_REDI_REGNUM],
4161cf7f2e2dSJohn Marino                                       &offset64);
4162cf7f2e2dSJohn Marino 	  *addr = (uint32_t) (*addr + offset64);
41635796c8dcSSimon Schubert 	  break;
41645796c8dcSSimon Schubert 	case 4:
41655796c8dcSSimon Schubert 	  regcache_raw_read_unsigned (irp->regcache,
41665796c8dcSSimon Schubert 				      irp->regmap[X86_RECORD_RESI_REGNUM],
4167cf7f2e2dSJohn Marino                                       &offset64);
4168cf7f2e2dSJohn Marino 	  *addr = (uint32_t) (*addr + offset64);
41695796c8dcSSimon Schubert 	  break;
41705796c8dcSSimon Schubert 	case 5:
41715796c8dcSSimon Schubert 	  regcache_raw_read_unsigned (irp->regcache,
41725796c8dcSSimon Schubert 				      irp->regmap[X86_RECORD_REDI_REGNUM],
4173cf7f2e2dSJohn Marino                                       &offset64);
4174cf7f2e2dSJohn Marino 	  *addr = (uint32_t) (*addr + offset64);
41755796c8dcSSimon Schubert 	  break;
41765796c8dcSSimon Schubert 	case 6:
41775796c8dcSSimon Schubert 	  regcache_raw_read_unsigned (irp->regcache,
41785796c8dcSSimon Schubert 				      irp->regmap[X86_RECORD_REBP_REGNUM],
4179cf7f2e2dSJohn Marino                                       &offset64);
4180cf7f2e2dSJohn Marino 	  *addr = (uint32_t) (*addr + offset64);
41815796c8dcSSimon Schubert 	  break;
41825796c8dcSSimon Schubert 	case 7:
41835796c8dcSSimon Schubert 	  regcache_raw_read_unsigned (irp->regcache,
41845796c8dcSSimon Schubert 				      irp->regmap[X86_RECORD_REBX_REGNUM],
4185cf7f2e2dSJohn Marino                                       &offset64);
4186cf7f2e2dSJohn Marino 	  *addr = (uint32_t) (*addr + offset64);
41875796c8dcSSimon Schubert 	  break;
41885796c8dcSSimon Schubert 	}
41895796c8dcSSimon Schubert       *addr &= 0xffff;
41905796c8dcSSimon Schubert     }
41915796c8dcSSimon Schubert 
41925796c8dcSSimon Schubert  no_rm:
41935796c8dcSSimon Schubert   return 0;
41945796c8dcSSimon Schubert }
41955796c8dcSSimon Schubert 
4196*ef5ccd6cSJohn Marino /* Record the address and contents of the memory that will be changed
4197*ef5ccd6cSJohn Marino    by the current instruction.  Return -1 if something goes wrong, 0
4198*ef5ccd6cSJohn Marino    otherwise.  */
41995796c8dcSSimon Schubert 
42005796c8dcSSimon Schubert static int
i386_record_lea_modrm(struct i386_record_s * irp)42015796c8dcSSimon Schubert i386_record_lea_modrm (struct i386_record_s *irp)
42025796c8dcSSimon Schubert {
42035796c8dcSSimon Schubert   struct gdbarch *gdbarch = irp->gdbarch;
42045796c8dcSSimon Schubert   uint64_t addr;
42055796c8dcSSimon Schubert 
42065796c8dcSSimon Schubert   if (irp->override >= 0)
42075796c8dcSSimon Schubert     {
4208*ef5ccd6cSJohn Marino       if (record_full_memory_query)
4209cf7f2e2dSJohn Marino         {
4210cf7f2e2dSJohn Marino 	  int q;
4211cf7f2e2dSJohn Marino 
4212cf7f2e2dSJohn Marino           target_terminal_ours ();
4213cf7f2e2dSJohn Marino           q = yquery (_("\
4214cf7f2e2dSJohn Marino Process record ignores the memory change of instruction at address %s\n\
4215cf7f2e2dSJohn Marino because it can't get the value of the segment register.\n\
4216cf7f2e2dSJohn Marino Do you want to stop the program?"),
42175796c8dcSSimon Schubert                       paddress (gdbarch, irp->orig_addr));
4218cf7f2e2dSJohn Marino             target_terminal_inferior ();
4219cf7f2e2dSJohn Marino             if (q)
4220cf7f2e2dSJohn Marino               return -1;
4221cf7f2e2dSJohn Marino         }
4222cf7f2e2dSJohn Marino 
42235796c8dcSSimon Schubert       return 0;
42245796c8dcSSimon Schubert     }
42255796c8dcSSimon Schubert 
42265796c8dcSSimon Schubert   if (i386_record_lea_modrm_addr (irp, &addr))
42275796c8dcSSimon Schubert     return -1;
42285796c8dcSSimon Schubert 
4229*ef5ccd6cSJohn Marino   if (record_full_arch_list_add_mem (addr, 1 << irp->ot))
42305796c8dcSSimon Schubert     return -1;
42315796c8dcSSimon Schubert 
42325796c8dcSSimon Schubert   return 0;
42335796c8dcSSimon Schubert }
42345796c8dcSSimon Schubert 
4235*ef5ccd6cSJohn Marino /* Record the effects of a push operation.  Return -1 if something
4236*ef5ccd6cSJohn Marino    goes wrong, 0 otherwise.  */
42375796c8dcSSimon Schubert 
42385796c8dcSSimon Schubert static int
i386_record_push(struct i386_record_s * irp,int size)42395796c8dcSSimon Schubert i386_record_push (struct i386_record_s *irp, int size)
42405796c8dcSSimon Schubert {
4241cf7f2e2dSJohn Marino   ULONGEST addr;
42425796c8dcSSimon Schubert 
4243*ef5ccd6cSJohn Marino   if (record_full_arch_list_add_reg (irp->regcache,
42445796c8dcSSimon Schubert 				     irp->regmap[X86_RECORD_RESP_REGNUM]))
42455796c8dcSSimon Schubert     return -1;
42465796c8dcSSimon Schubert   regcache_raw_read_unsigned (irp->regcache,
42475796c8dcSSimon Schubert 			      irp->regmap[X86_RECORD_RESP_REGNUM],
4248cf7f2e2dSJohn Marino 			      &addr);
4249*ef5ccd6cSJohn Marino   if (record_full_arch_list_add_mem ((CORE_ADDR) addr - size, size))
42505796c8dcSSimon Schubert     return -1;
42515796c8dcSSimon Schubert 
42525796c8dcSSimon Schubert   return 0;
42535796c8dcSSimon Schubert }
42545796c8dcSSimon Schubert 
4255cf7f2e2dSJohn Marino 
4256cf7f2e2dSJohn Marino /* Defines contents to record.  */
4257cf7f2e2dSJohn Marino #define I386_SAVE_FPU_REGS              0xfffd
4258cf7f2e2dSJohn Marino #define I386_SAVE_FPU_ENV               0xfffe
4259cf7f2e2dSJohn Marino #define I386_SAVE_FPU_ENV_REG_STACK     0xffff
4260cf7f2e2dSJohn Marino 
4261*ef5ccd6cSJohn Marino /* Record the values of the floating point registers which will be
4262*ef5ccd6cSJohn Marino    changed by the current instruction.  Returns -1 if something is
4263*ef5ccd6cSJohn Marino    wrong, 0 otherwise.  */
4264cf7f2e2dSJohn Marino 
i386_record_floats(struct gdbarch * gdbarch,struct i386_record_s * ir,uint32_t iregnum)4265cf7f2e2dSJohn Marino static int i386_record_floats (struct gdbarch *gdbarch,
4266cf7f2e2dSJohn Marino                                struct i386_record_s *ir,
4267cf7f2e2dSJohn Marino                                uint32_t iregnum)
4268cf7f2e2dSJohn Marino {
4269cf7f2e2dSJohn Marino   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
4270cf7f2e2dSJohn Marino   int i;
4271cf7f2e2dSJohn Marino 
4272cf7f2e2dSJohn Marino   /* Oza: Because of floating point insn push/pop of fpu stack is going to
4273cf7f2e2dSJohn Marino      happen.  Currently we store st0-st7 registers, but we need not store all
4274cf7f2e2dSJohn Marino      registers all the time, in future we use ftag register and record only
4275cf7f2e2dSJohn Marino      those who are not marked as an empty.  */
4276cf7f2e2dSJohn Marino 
4277cf7f2e2dSJohn Marino   if (I386_SAVE_FPU_REGS == iregnum)
4278cf7f2e2dSJohn Marino     {
4279cf7f2e2dSJohn Marino       for (i = I387_ST0_REGNUM (tdep); i <= I387_ST0_REGNUM (tdep) + 7; i++)
4280cf7f2e2dSJohn Marino         {
4281*ef5ccd6cSJohn Marino           if (record_full_arch_list_add_reg (ir->regcache, i))
4282cf7f2e2dSJohn Marino             return -1;
4283cf7f2e2dSJohn Marino         }
4284cf7f2e2dSJohn Marino     }
4285cf7f2e2dSJohn Marino   else if (I386_SAVE_FPU_ENV == iregnum)
4286cf7f2e2dSJohn Marino     {
4287cf7f2e2dSJohn Marino       for (i = I387_FCTRL_REGNUM (tdep); i <= I387_FOP_REGNUM (tdep); i++)
4288cf7f2e2dSJohn Marino 	      {
4289*ef5ccd6cSJohn Marino 	      if (record_full_arch_list_add_reg (ir->regcache, i))
4290cf7f2e2dSJohn Marino 	        return -1;
4291cf7f2e2dSJohn Marino 	      }
4292cf7f2e2dSJohn Marino     }
4293cf7f2e2dSJohn Marino   else if (I386_SAVE_FPU_ENV_REG_STACK == iregnum)
4294cf7f2e2dSJohn Marino     {
4295cf7f2e2dSJohn Marino       for (i = I387_ST0_REGNUM (tdep); i <= I387_FOP_REGNUM (tdep); i++)
4296cf7f2e2dSJohn Marino       {
4297*ef5ccd6cSJohn Marino         if (record_full_arch_list_add_reg (ir->regcache, i))
4298cf7f2e2dSJohn Marino           return -1;
4299cf7f2e2dSJohn Marino       }
4300cf7f2e2dSJohn Marino     }
4301cf7f2e2dSJohn Marino   else if ((iregnum >= I387_ST0_REGNUM (tdep)) &&
4302cf7f2e2dSJohn Marino            (iregnum <= I387_FOP_REGNUM (tdep)))
4303cf7f2e2dSJohn Marino     {
4304*ef5ccd6cSJohn Marino       if (record_full_arch_list_add_reg (ir->regcache,iregnum))
4305cf7f2e2dSJohn Marino         return -1;
4306cf7f2e2dSJohn Marino     }
4307cf7f2e2dSJohn Marino   else
4308cf7f2e2dSJohn Marino     {
4309cf7f2e2dSJohn Marino       /* Parameter error.  */
4310cf7f2e2dSJohn Marino       return -1;
4311cf7f2e2dSJohn Marino     }
4312cf7f2e2dSJohn Marino   if(I386_SAVE_FPU_ENV != iregnum)
4313cf7f2e2dSJohn Marino     {
4314cf7f2e2dSJohn Marino     for (i = I387_FCTRL_REGNUM (tdep); i <= I387_FOP_REGNUM (tdep); i++)
4315cf7f2e2dSJohn Marino       {
4316*ef5ccd6cSJohn Marino       if (record_full_arch_list_add_reg (ir->regcache, i))
4317cf7f2e2dSJohn Marino         return -1;
4318cf7f2e2dSJohn Marino       }
4319cf7f2e2dSJohn Marino     }
4320cf7f2e2dSJohn Marino   return 0;
4321cf7f2e2dSJohn Marino }
4322cf7f2e2dSJohn Marino 
4323*ef5ccd6cSJohn Marino /* Parse the current instruction, and record the values of the
4324*ef5ccd6cSJohn Marino    registers and memory that will be changed by the current
4325*ef5ccd6cSJohn Marino    instruction.  Returns -1 if something goes wrong, 0 otherwise.  */
43265796c8dcSSimon Schubert 
4327*ef5ccd6cSJohn Marino #define I386_RECORD_FULL_ARCH_LIST_ADD_REG(regnum) \
4328*ef5ccd6cSJohn Marino     record_full_arch_list_add_reg (ir.regcache, ir.regmap[(regnum)])
43295796c8dcSSimon Schubert 
43305796c8dcSSimon Schubert int
i386_process_record(struct gdbarch * gdbarch,struct regcache * regcache,CORE_ADDR input_addr)43315796c8dcSSimon Schubert i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
4332cf7f2e2dSJohn Marino 		     CORE_ADDR input_addr)
43335796c8dcSSimon Schubert {
4334cf7f2e2dSJohn Marino   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
43355796c8dcSSimon Schubert   int prefixes = 0;
4336cf7f2e2dSJohn Marino   int regnum = 0;
43375796c8dcSSimon Schubert   uint32_t opcode;
4338cf7f2e2dSJohn Marino   uint8_t opcode8;
4339cf7f2e2dSJohn Marino   ULONGEST addr;
4340cf7f2e2dSJohn Marino   gdb_byte buf[MAX_REGISTER_SIZE];
43415796c8dcSSimon Schubert   struct i386_record_s ir;
4342cf7f2e2dSJohn Marino   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
43435796c8dcSSimon Schubert   uint8_t rex_w = -1;
43445796c8dcSSimon Schubert   uint8_t rex_r = 0;
43455796c8dcSSimon Schubert 
43465796c8dcSSimon Schubert   memset (&ir, 0, sizeof (struct i386_record_s));
43475796c8dcSSimon Schubert   ir.regcache = regcache;
4348cf7f2e2dSJohn Marino   ir.addr = input_addr;
4349cf7f2e2dSJohn Marino   ir.orig_addr = input_addr;
43505796c8dcSSimon Schubert   ir.aflag = 1;
43515796c8dcSSimon Schubert   ir.dflag = 1;
43525796c8dcSSimon Schubert   ir.override = -1;
43535796c8dcSSimon Schubert   ir.popl_esp_hack = 0;
4354cf7f2e2dSJohn Marino   ir.regmap = tdep->record_regmap;
43555796c8dcSSimon Schubert   ir.gdbarch = gdbarch;
43565796c8dcSSimon Schubert 
43575796c8dcSSimon Schubert   if (record_debug > 1)
43585796c8dcSSimon Schubert     fprintf_unfiltered (gdb_stdlog, "Process record: i386_process_record "
43595796c8dcSSimon Schubert 			            "addr = %s\n",
43605796c8dcSSimon Schubert 			paddress (gdbarch, ir.addr));
43615796c8dcSSimon Schubert 
43625796c8dcSSimon Schubert   /* prefixes */
43635796c8dcSSimon Schubert   while (1)
43645796c8dcSSimon Schubert     {
4365*ef5ccd6cSJohn Marino       if (record_read_memory (gdbarch, ir.addr, &opcode8, 1))
43665796c8dcSSimon Schubert 	return -1;
43675796c8dcSSimon Schubert       ir.addr++;
4368cf7f2e2dSJohn Marino       switch (opcode8)	/* Instruction prefixes */
43695796c8dcSSimon Schubert 	{
4370cf7f2e2dSJohn Marino 	case REPE_PREFIX_OPCODE:
43715796c8dcSSimon Schubert 	  prefixes |= PREFIX_REPZ;
43725796c8dcSSimon Schubert 	  break;
4373cf7f2e2dSJohn Marino 	case REPNE_PREFIX_OPCODE:
43745796c8dcSSimon Schubert 	  prefixes |= PREFIX_REPNZ;
43755796c8dcSSimon Schubert 	  break;
4376cf7f2e2dSJohn Marino 	case LOCK_PREFIX_OPCODE:
43775796c8dcSSimon Schubert 	  prefixes |= PREFIX_LOCK;
43785796c8dcSSimon Schubert 	  break;
4379cf7f2e2dSJohn Marino 	case CS_PREFIX_OPCODE:
43805796c8dcSSimon Schubert 	  ir.override = X86_RECORD_CS_REGNUM;
43815796c8dcSSimon Schubert 	  break;
4382cf7f2e2dSJohn Marino 	case SS_PREFIX_OPCODE:
43835796c8dcSSimon Schubert 	  ir.override = X86_RECORD_SS_REGNUM;
43845796c8dcSSimon Schubert 	  break;
4385cf7f2e2dSJohn Marino 	case DS_PREFIX_OPCODE:
43865796c8dcSSimon Schubert 	  ir.override = X86_RECORD_DS_REGNUM;
43875796c8dcSSimon Schubert 	  break;
4388cf7f2e2dSJohn Marino 	case ES_PREFIX_OPCODE:
43895796c8dcSSimon Schubert 	  ir.override = X86_RECORD_ES_REGNUM;
43905796c8dcSSimon Schubert 	  break;
4391cf7f2e2dSJohn Marino 	case FS_PREFIX_OPCODE:
43925796c8dcSSimon Schubert 	  ir.override = X86_RECORD_FS_REGNUM;
43935796c8dcSSimon Schubert 	  break;
4394cf7f2e2dSJohn Marino 	case GS_PREFIX_OPCODE:
43955796c8dcSSimon Schubert 	  ir.override = X86_RECORD_GS_REGNUM;
43965796c8dcSSimon Schubert 	  break;
4397cf7f2e2dSJohn Marino 	case DATA_PREFIX_OPCODE:
43985796c8dcSSimon Schubert 	  prefixes |= PREFIX_DATA;
43995796c8dcSSimon Schubert 	  break;
4400cf7f2e2dSJohn Marino 	case ADDR_PREFIX_OPCODE:
44015796c8dcSSimon Schubert 	  prefixes |= PREFIX_ADDR;
44025796c8dcSSimon Schubert 	  break;
44035796c8dcSSimon Schubert         case 0x40:	/* i386 inc %eax */
44045796c8dcSSimon Schubert         case 0x41:	/* i386 inc %ecx */
44055796c8dcSSimon Schubert         case 0x42:	/* i386 inc %edx */
44065796c8dcSSimon Schubert         case 0x43:	/* i386 inc %ebx */
44075796c8dcSSimon Schubert         case 0x44:	/* i386 inc %esp */
44085796c8dcSSimon Schubert         case 0x45:	/* i386 inc %ebp */
44095796c8dcSSimon Schubert         case 0x46:	/* i386 inc %esi */
44105796c8dcSSimon Schubert         case 0x47:	/* i386 inc %edi */
44115796c8dcSSimon Schubert         case 0x48:	/* i386 dec %eax */
44125796c8dcSSimon Schubert         case 0x49:	/* i386 dec %ecx */
44135796c8dcSSimon Schubert         case 0x4a:	/* i386 dec %edx */
44145796c8dcSSimon Schubert         case 0x4b:	/* i386 dec %ebx */
44155796c8dcSSimon Schubert         case 0x4c:	/* i386 dec %esp */
44165796c8dcSSimon Schubert         case 0x4d:	/* i386 dec %ebp */
44175796c8dcSSimon Schubert         case 0x4e:	/* i386 dec %esi */
44185796c8dcSSimon Schubert         case 0x4f:	/* i386 dec %edi */
44195796c8dcSSimon Schubert           if (ir.regmap[X86_RECORD_R8_REGNUM])	/* 64 bit target */
44205796c8dcSSimon Schubert             {
44215796c8dcSSimon Schubert                /* REX */
4422cf7f2e2dSJohn Marino                rex_w = (opcode8 >> 3) & 1;
4423cf7f2e2dSJohn Marino                rex_r = (opcode8 & 0x4) << 1;
4424cf7f2e2dSJohn Marino                ir.rex_x = (opcode8 & 0x2) << 2;
4425cf7f2e2dSJohn Marino                ir.rex_b = (opcode8 & 0x1) << 3;
44265796c8dcSSimon Schubert             }
44275796c8dcSSimon Schubert 	  else					/* 32 bit target */
44285796c8dcSSimon Schubert 	    goto out_prefixes;
44295796c8dcSSimon Schubert           break;
44305796c8dcSSimon Schubert 	default:
44315796c8dcSSimon Schubert 	  goto out_prefixes;
44325796c8dcSSimon Schubert 	  break;
44335796c8dcSSimon Schubert 	}
44345796c8dcSSimon Schubert     }
44355796c8dcSSimon Schubert  out_prefixes:
44365796c8dcSSimon Schubert   if (ir.regmap[X86_RECORD_R8_REGNUM] && rex_w == 1)
44375796c8dcSSimon Schubert     {
44385796c8dcSSimon Schubert       ir.dflag = 2;
44395796c8dcSSimon Schubert     }
44405796c8dcSSimon Schubert   else
44415796c8dcSSimon Schubert     {
44425796c8dcSSimon Schubert       if (prefixes & PREFIX_DATA)
44435796c8dcSSimon Schubert         ir.dflag ^= 1;
44445796c8dcSSimon Schubert     }
44455796c8dcSSimon Schubert   if (prefixes & PREFIX_ADDR)
44465796c8dcSSimon Schubert     ir.aflag ^= 1;
44475796c8dcSSimon Schubert   else if (ir.regmap[X86_RECORD_R8_REGNUM])
44485796c8dcSSimon Schubert     ir.aflag = 2;
44495796c8dcSSimon Schubert 
4450c50c785cSJohn Marino   /* Now check op code.  */
4451cf7f2e2dSJohn Marino   opcode = (uint32_t) opcode8;
44525796c8dcSSimon Schubert  reswitch:
44535796c8dcSSimon Schubert   switch (opcode)
44545796c8dcSSimon Schubert     {
44555796c8dcSSimon Schubert     case 0x0f:
4456*ef5ccd6cSJohn Marino       if (record_read_memory (gdbarch, ir.addr, &opcode8, 1))
44575796c8dcSSimon Schubert 	return -1;
44585796c8dcSSimon Schubert       ir.addr++;
4459cf7f2e2dSJohn Marino       opcode = (uint32_t) opcode8 | 0x0f00;
44605796c8dcSSimon Schubert       goto reswitch;
44615796c8dcSSimon Schubert       break;
44625796c8dcSSimon Schubert 
4463cf7f2e2dSJohn Marino     case 0x00:    /* arith & logic */
44645796c8dcSSimon Schubert     case 0x01:
44655796c8dcSSimon Schubert     case 0x02:
44665796c8dcSSimon Schubert     case 0x03:
44675796c8dcSSimon Schubert     case 0x04:
44685796c8dcSSimon Schubert     case 0x05:
44695796c8dcSSimon Schubert     case 0x08:
44705796c8dcSSimon Schubert     case 0x09:
44715796c8dcSSimon Schubert     case 0x0a:
44725796c8dcSSimon Schubert     case 0x0b:
44735796c8dcSSimon Schubert     case 0x0c:
44745796c8dcSSimon Schubert     case 0x0d:
44755796c8dcSSimon Schubert     case 0x10:
44765796c8dcSSimon Schubert     case 0x11:
44775796c8dcSSimon Schubert     case 0x12:
44785796c8dcSSimon Schubert     case 0x13:
44795796c8dcSSimon Schubert     case 0x14:
44805796c8dcSSimon Schubert     case 0x15:
44815796c8dcSSimon Schubert     case 0x18:
44825796c8dcSSimon Schubert     case 0x19:
44835796c8dcSSimon Schubert     case 0x1a:
44845796c8dcSSimon Schubert     case 0x1b:
44855796c8dcSSimon Schubert     case 0x1c:
44865796c8dcSSimon Schubert     case 0x1d:
44875796c8dcSSimon Schubert     case 0x20:
44885796c8dcSSimon Schubert     case 0x21:
44895796c8dcSSimon Schubert     case 0x22:
44905796c8dcSSimon Schubert     case 0x23:
44915796c8dcSSimon Schubert     case 0x24:
44925796c8dcSSimon Schubert     case 0x25:
44935796c8dcSSimon Schubert     case 0x28:
44945796c8dcSSimon Schubert     case 0x29:
44955796c8dcSSimon Schubert     case 0x2a:
44965796c8dcSSimon Schubert     case 0x2b:
44975796c8dcSSimon Schubert     case 0x2c:
44985796c8dcSSimon Schubert     case 0x2d:
44995796c8dcSSimon Schubert     case 0x30:
45005796c8dcSSimon Schubert     case 0x31:
45015796c8dcSSimon Schubert     case 0x32:
45025796c8dcSSimon Schubert     case 0x33:
45035796c8dcSSimon Schubert     case 0x34:
45045796c8dcSSimon Schubert     case 0x35:
45055796c8dcSSimon Schubert     case 0x38:
45065796c8dcSSimon Schubert     case 0x39:
45075796c8dcSSimon Schubert     case 0x3a:
45085796c8dcSSimon Schubert     case 0x3b:
45095796c8dcSSimon Schubert     case 0x3c:
45105796c8dcSSimon Schubert     case 0x3d:
45115796c8dcSSimon Schubert       if (((opcode >> 3) & 7) != OP_CMPL)
45125796c8dcSSimon Schubert 	{
45135796c8dcSSimon Schubert 	  if ((opcode & 1) == 0)
45145796c8dcSSimon Schubert 	    ir.ot = OT_BYTE;
45155796c8dcSSimon Schubert 	  else
45165796c8dcSSimon Schubert 	    ir.ot = ir.dflag + OT_WORD;
45175796c8dcSSimon Schubert 
45185796c8dcSSimon Schubert 	  switch ((opcode >> 1) & 3)
45195796c8dcSSimon Schubert 	    {
4520cf7f2e2dSJohn Marino 	    case 0:    /* OP Ev, Gv */
45215796c8dcSSimon Schubert 	      if (i386_record_modrm (&ir))
45225796c8dcSSimon Schubert 		return -1;
45235796c8dcSSimon Schubert 	      if (ir.mod != 3)
45245796c8dcSSimon Schubert 		{
45255796c8dcSSimon Schubert 		  if (i386_record_lea_modrm (&ir))
45265796c8dcSSimon Schubert 		    return -1;
45275796c8dcSSimon Schubert 		}
45285796c8dcSSimon Schubert 	      else
45295796c8dcSSimon Schubert 		{
45305796c8dcSSimon Schubert                   ir.rm |= ir.rex_b;
45315796c8dcSSimon Schubert 		  if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM])
45325796c8dcSSimon Schubert 		    ir.rm &= 0x3;
4533*ef5ccd6cSJohn Marino 		  I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.rm);
45345796c8dcSSimon Schubert 		}
45355796c8dcSSimon Schubert 	      break;
4536cf7f2e2dSJohn Marino 	    case 1:    /* OP Gv, Ev */
45375796c8dcSSimon Schubert 	      if (i386_record_modrm (&ir))
45385796c8dcSSimon Schubert 		return -1;
45395796c8dcSSimon Schubert               ir.reg |= rex_r;
45405796c8dcSSimon Schubert 	      if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM])
45415796c8dcSSimon Schubert 		ir.reg &= 0x3;
4542*ef5ccd6cSJohn Marino 	      I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.reg);
45435796c8dcSSimon Schubert 	      break;
4544cf7f2e2dSJohn Marino 	    case 2:    /* OP A, Iv */
4545*ef5ccd6cSJohn Marino 	      I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM);
45465796c8dcSSimon Schubert 	      break;
45475796c8dcSSimon Schubert 	    }
45485796c8dcSSimon Schubert 	}
4549*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
45505796c8dcSSimon Schubert       break;
45515796c8dcSSimon Schubert 
4552cf7f2e2dSJohn Marino     case 0x80:    /* GRP1 */
45535796c8dcSSimon Schubert     case 0x81:
45545796c8dcSSimon Schubert     case 0x82:
45555796c8dcSSimon Schubert     case 0x83:
45565796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
45575796c8dcSSimon Schubert 	return -1;
45585796c8dcSSimon Schubert 
45595796c8dcSSimon Schubert       if (ir.reg != OP_CMPL)
45605796c8dcSSimon Schubert 	{
45615796c8dcSSimon Schubert 	  if ((opcode & 1) == 0)
45625796c8dcSSimon Schubert 	    ir.ot = OT_BYTE;
45635796c8dcSSimon Schubert 	  else
45645796c8dcSSimon Schubert 	    ir.ot = ir.dflag + OT_WORD;
45655796c8dcSSimon Schubert 
45665796c8dcSSimon Schubert 	  if (ir.mod != 3)
45675796c8dcSSimon Schubert 	    {
45685796c8dcSSimon Schubert               if (opcode == 0x83)
45695796c8dcSSimon Schubert                 ir.rip_offset = 1;
45705796c8dcSSimon Schubert               else
45715796c8dcSSimon Schubert                 ir.rip_offset = (ir.ot > OT_LONG) ? 4 : (1 << ir.ot);
45725796c8dcSSimon Schubert 	      if (i386_record_lea_modrm (&ir))
45735796c8dcSSimon Schubert 		return -1;
45745796c8dcSSimon Schubert 	    }
45755796c8dcSSimon Schubert 	  else
4576*ef5ccd6cSJohn Marino 	    I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.rm | ir.rex_b);
45775796c8dcSSimon Schubert 	}
4578*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
45795796c8dcSSimon Schubert       break;
45805796c8dcSSimon Schubert 
4581cf7f2e2dSJohn Marino     case 0x40:      /* inc */
45825796c8dcSSimon Schubert     case 0x41:
45835796c8dcSSimon Schubert     case 0x42:
45845796c8dcSSimon Schubert     case 0x43:
45855796c8dcSSimon Schubert     case 0x44:
45865796c8dcSSimon Schubert     case 0x45:
45875796c8dcSSimon Schubert     case 0x46:
45885796c8dcSSimon Schubert     case 0x47:
4589cf7f2e2dSJohn Marino 
4590cf7f2e2dSJohn Marino     case 0x48:      /* dec */
45915796c8dcSSimon Schubert     case 0x49:
45925796c8dcSSimon Schubert     case 0x4a:
45935796c8dcSSimon Schubert     case 0x4b:
45945796c8dcSSimon Schubert     case 0x4c:
45955796c8dcSSimon Schubert     case 0x4d:
45965796c8dcSSimon Schubert     case 0x4e:
45975796c8dcSSimon Schubert     case 0x4f:
4598cf7f2e2dSJohn Marino 
4599*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (opcode & 7);
4600*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
46015796c8dcSSimon Schubert       break;
46025796c8dcSSimon Schubert 
4603cf7f2e2dSJohn Marino     case 0xf6:    /* GRP3 */
46045796c8dcSSimon Schubert     case 0xf7:
46055796c8dcSSimon Schubert       if ((opcode & 1) == 0)
46065796c8dcSSimon Schubert 	ir.ot = OT_BYTE;
46075796c8dcSSimon Schubert       else
46085796c8dcSSimon Schubert 	ir.ot = ir.dflag + OT_WORD;
46095796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
46105796c8dcSSimon Schubert 	return -1;
46115796c8dcSSimon Schubert 
46125796c8dcSSimon Schubert       if (ir.mod != 3 && ir.reg == 0)
46135796c8dcSSimon Schubert         ir.rip_offset = (ir.ot > OT_LONG) ? 4 : (1 << ir.ot);
46145796c8dcSSimon Schubert 
46155796c8dcSSimon Schubert       switch (ir.reg)
46165796c8dcSSimon Schubert 	{
4617cf7f2e2dSJohn Marino 	case 0:    /* test */
4618*ef5ccd6cSJohn Marino 	  I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
46195796c8dcSSimon Schubert 	  break;
4620cf7f2e2dSJohn Marino 	case 2:    /* not */
4621cf7f2e2dSJohn Marino 	case 3:    /* neg */
46225796c8dcSSimon Schubert 	  if (ir.mod != 3)
46235796c8dcSSimon Schubert 	    {
46245796c8dcSSimon Schubert 	      if (i386_record_lea_modrm (&ir))
46255796c8dcSSimon Schubert 		return -1;
46265796c8dcSSimon Schubert 	    }
46275796c8dcSSimon Schubert 	  else
46285796c8dcSSimon Schubert 	    {
46295796c8dcSSimon Schubert               ir.rm |= ir.rex_b;
46305796c8dcSSimon Schubert 	      if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM])
46315796c8dcSSimon Schubert 		ir.rm &= 0x3;
4632*ef5ccd6cSJohn Marino 	      I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.rm);
46335796c8dcSSimon Schubert 	    }
4634cf7f2e2dSJohn Marino 	  if (ir.reg == 3)  /* neg */
4635*ef5ccd6cSJohn Marino 	    I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
46365796c8dcSSimon Schubert 	  break;
4637cf7f2e2dSJohn Marino 	case 4:    /* mul  */
4638cf7f2e2dSJohn Marino 	case 5:    /* imul */
4639cf7f2e2dSJohn Marino 	case 6:    /* div  */
4640cf7f2e2dSJohn Marino 	case 7:    /* idiv */
4641*ef5ccd6cSJohn Marino 	  I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM);
46425796c8dcSSimon Schubert 	  if (ir.ot != OT_BYTE)
4643*ef5ccd6cSJohn Marino 	    I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REDX_REGNUM);
4644*ef5ccd6cSJohn Marino 	  I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
46455796c8dcSSimon Schubert 	  break;
46465796c8dcSSimon Schubert 	default:
46475796c8dcSSimon Schubert 	  ir.addr -= 2;
46485796c8dcSSimon Schubert 	  opcode = opcode << 8 | ir.modrm;
46495796c8dcSSimon Schubert 	  goto no_support;
46505796c8dcSSimon Schubert 	  break;
46515796c8dcSSimon Schubert 	}
46525796c8dcSSimon Schubert       break;
46535796c8dcSSimon Schubert 
4654cf7f2e2dSJohn Marino     case 0xfe:    /* GRP4 */
4655cf7f2e2dSJohn Marino     case 0xff:    /* GRP5 */
46565796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
46575796c8dcSSimon Schubert 	return -1;
46585796c8dcSSimon Schubert       if (ir.reg >= 2 && opcode == 0xfe)
46595796c8dcSSimon Schubert 	{
46605796c8dcSSimon Schubert 	  ir.addr -= 2;
46615796c8dcSSimon Schubert 	  opcode = opcode << 8 | ir.modrm;
46625796c8dcSSimon Schubert 	  goto no_support;
46635796c8dcSSimon Schubert 	}
46645796c8dcSSimon Schubert       switch (ir.reg)
46655796c8dcSSimon Schubert 	{
4666cf7f2e2dSJohn Marino 	case 0:    /* inc */
4667cf7f2e2dSJohn Marino 	case 1:    /* dec */
46685796c8dcSSimon Schubert           if ((opcode & 1) == 0)
46695796c8dcSSimon Schubert 	    ir.ot = OT_BYTE;
46705796c8dcSSimon Schubert           else
46715796c8dcSSimon Schubert 	    ir.ot = ir.dflag + OT_WORD;
46725796c8dcSSimon Schubert 	  if (ir.mod != 3)
46735796c8dcSSimon Schubert 	    {
46745796c8dcSSimon Schubert 	      if (i386_record_lea_modrm (&ir))
46755796c8dcSSimon Schubert 		return -1;
46765796c8dcSSimon Schubert 	    }
46775796c8dcSSimon Schubert 	  else
46785796c8dcSSimon Schubert 	    {
46795796c8dcSSimon Schubert 	      ir.rm |= ir.rex_b;
46805796c8dcSSimon Schubert 	      if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM])
46815796c8dcSSimon Schubert 		ir.rm &= 0x3;
4682*ef5ccd6cSJohn Marino 	      I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.rm);
46835796c8dcSSimon Schubert 	    }
4684*ef5ccd6cSJohn Marino 	  I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
46855796c8dcSSimon Schubert 	  break;
4686cf7f2e2dSJohn Marino 	case 2:    /* call */
46875796c8dcSSimon Schubert           if (ir.regmap[X86_RECORD_R8_REGNUM] && ir.dflag)
46885796c8dcSSimon Schubert             ir.dflag = 2;
46895796c8dcSSimon Schubert 	  if (i386_record_push (&ir, 1 << (ir.dflag + 1)))
46905796c8dcSSimon Schubert 	    return -1;
4691*ef5ccd6cSJohn Marino 	  I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
46925796c8dcSSimon Schubert 	  break;
4693cf7f2e2dSJohn Marino 	case 3:    /* lcall */
4694*ef5ccd6cSJohn Marino 	  I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_CS_REGNUM);
46955796c8dcSSimon Schubert 	  if (i386_record_push (&ir, 1 << (ir.dflag + 1)))
46965796c8dcSSimon Schubert 	    return -1;
4697*ef5ccd6cSJohn Marino 	  I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
46985796c8dcSSimon Schubert 	  break;
4699cf7f2e2dSJohn Marino 	case 4:    /* jmp  */
4700cf7f2e2dSJohn Marino 	case 5:    /* ljmp */
4701*ef5ccd6cSJohn Marino 	  I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
47025796c8dcSSimon Schubert 	  break;
4703cf7f2e2dSJohn Marino 	case 6:    /* push */
47045796c8dcSSimon Schubert           if (ir.regmap[X86_RECORD_R8_REGNUM] && ir.dflag)
47055796c8dcSSimon Schubert             ir.dflag = 2;
47065796c8dcSSimon Schubert 	  if (i386_record_push (&ir, 1 << (ir.dflag + 1)))
47075796c8dcSSimon Schubert 	    return -1;
47085796c8dcSSimon Schubert 	  break;
47095796c8dcSSimon Schubert 	default:
47105796c8dcSSimon Schubert 	  ir.addr -= 2;
47115796c8dcSSimon Schubert 	  opcode = opcode << 8 | ir.modrm;
47125796c8dcSSimon Schubert 	  goto no_support;
47135796c8dcSSimon Schubert 	  break;
47145796c8dcSSimon Schubert 	}
47155796c8dcSSimon Schubert       break;
47165796c8dcSSimon Schubert 
4717cf7f2e2dSJohn Marino     case 0x84:    /* test */
47185796c8dcSSimon Schubert     case 0x85:
47195796c8dcSSimon Schubert     case 0xa8:
47205796c8dcSSimon Schubert     case 0xa9:
4721*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
47225796c8dcSSimon Schubert       break;
47235796c8dcSSimon Schubert 
4724cf7f2e2dSJohn Marino     case 0x98:    /* CWDE/CBW */
4725*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM);
47265796c8dcSSimon Schubert       break;
47275796c8dcSSimon Schubert 
4728cf7f2e2dSJohn Marino     case 0x99:    /* CDQ/CWD */
4729*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM);
4730*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REDX_REGNUM);
47315796c8dcSSimon Schubert       break;
47325796c8dcSSimon Schubert 
4733cf7f2e2dSJohn Marino     case 0x0faf:  /* imul */
47345796c8dcSSimon Schubert     case 0x69:
47355796c8dcSSimon Schubert     case 0x6b:
47365796c8dcSSimon Schubert       ir.ot = ir.dflag + OT_WORD;
47375796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
47385796c8dcSSimon Schubert 	return -1;
47395796c8dcSSimon Schubert       if (opcode == 0x69)
47405796c8dcSSimon Schubert         ir.rip_offset = (ir.ot > OT_LONG) ? 4 : (1 << ir.ot);
47415796c8dcSSimon Schubert       else if (opcode == 0x6b)
47425796c8dcSSimon Schubert         ir.rip_offset = 1;
47435796c8dcSSimon Schubert       ir.reg |= rex_r;
47445796c8dcSSimon Schubert       if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM])
47455796c8dcSSimon Schubert 	ir.reg &= 0x3;
4746*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.reg);
4747*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
47485796c8dcSSimon Schubert       break;
47495796c8dcSSimon Schubert 
4750cf7f2e2dSJohn Marino     case 0x0fc0:  /* xadd */
47515796c8dcSSimon Schubert     case 0x0fc1:
47525796c8dcSSimon Schubert       if ((opcode & 1) == 0)
47535796c8dcSSimon Schubert 	ir.ot = OT_BYTE;
47545796c8dcSSimon Schubert       else
47555796c8dcSSimon Schubert 	ir.ot = ir.dflag + OT_WORD;
47565796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
47575796c8dcSSimon Schubert 	return -1;
47585796c8dcSSimon Schubert       ir.reg |= rex_r;
47595796c8dcSSimon Schubert       if (ir.mod == 3)
47605796c8dcSSimon Schubert 	{
47615796c8dcSSimon Schubert 	  if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM])
47625796c8dcSSimon Schubert 	    ir.reg &= 0x3;
4763*ef5ccd6cSJohn Marino 	  I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.reg);
47645796c8dcSSimon Schubert 	  if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM])
47655796c8dcSSimon Schubert 	    ir.rm &= 0x3;
4766*ef5ccd6cSJohn Marino 	  I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.rm);
47675796c8dcSSimon Schubert 	}
47685796c8dcSSimon Schubert       else
47695796c8dcSSimon Schubert 	{
47705796c8dcSSimon Schubert 	  if (i386_record_lea_modrm (&ir))
47715796c8dcSSimon Schubert 	    return -1;
47725796c8dcSSimon Schubert 	  if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM])
47735796c8dcSSimon Schubert 	    ir.reg &= 0x3;
4774*ef5ccd6cSJohn Marino 	  I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.reg);
47755796c8dcSSimon Schubert 	}
4776*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
47775796c8dcSSimon Schubert       break;
47785796c8dcSSimon Schubert 
4779cf7f2e2dSJohn Marino     case 0x0fb0:  /* cmpxchg */
47805796c8dcSSimon Schubert     case 0x0fb1:
47815796c8dcSSimon Schubert       if ((opcode & 1) == 0)
47825796c8dcSSimon Schubert 	ir.ot = OT_BYTE;
47835796c8dcSSimon Schubert       else
47845796c8dcSSimon Schubert 	ir.ot = ir.dflag + OT_WORD;
47855796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
47865796c8dcSSimon Schubert 	return -1;
47875796c8dcSSimon Schubert       if (ir.mod == 3)
47885796c8dcSSimon Schubert 	{
47895796c8dcSSimon Schubert           ir.reg |= rex_r;
4790*ef5ccd6cSJohn Marino 	  I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM);
47915796c8dcSSimon Schubert 	  if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM])
47925796c8dcSSimon Schubert 	    ir.reg &= 0x3;
4793*ef5ccd6cSJohn Marino 	  I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.reg);
47945796c8dcSSimon Schubert 	}
47955796c8dcSSimon Schubert       else
47965796c8dcSSimon Schubert 	{
4797*ef5ccd6cSJohn Marino 	  I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM);
47985796c8dcSSimon Schubert 	  if (i386_record_lea_modrm (&ir))
47995796c8dcSSimon Schubert 	    return -1;
48005796c8dcSSimon Schubert 	}
4801*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
48025796c8dcSSimon Schubert       break;
48035796c8dcSSimon Schubert 
4804cf7f2e2dSJohn Marino     case 0x0fc7:    /* cmpxchg8b */
48055796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
48065796c8dcSSimon Schubert 	return -1;
48075796c8dcSSimon Schubert       if (ir.mod == 3)
48085796c8dcSSimon Schubert 	{
48095796c8dcSSimon Schubert 	  ir.addr -= 2;
48105796c8dcSSimon Schubert 	  opcode = opcode << 8 | ir.modrm;
48115796c8dcSSimon Schubert 	  goto no_support;
48125796c8dcSSimon Schubert 	}
4813*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM);
4814*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REDX_REGNUM);
48155796c8dcSSimon Schubert       if (i386_record_lea_modrm (&ir))
48165796c8dcSSimon Schubert 	return -1;
4817*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
48185796c8dcSSimon Schubert       break;
48195796c8dcSSimon Schubert 
4820cf7f2e2dSJohn Marino     case 0x50:    /* push */
48215796c8dcSSimon Schubert     case 0x51:
48225796c8dcSSimon Schubert     case 0x52:
48235796c8dcSSimon Schubert     case 0x53:
48245796c8dcSSimon Schubert     case 0x54:
48255796c8dcSSimon Schubert     case 0x55:
48265796c8dcSSimon Schubert     case 0x56:
48275796c8dcSSimon Schubert     case 0x57:
48285796c8dcSSimon Schubert     case 0x68:
48295796c8dcSSimon Schubert     case 0x6a:
48305796c8dcSSimon Schubert       if (ir.regmap[X86_RECORD_R8_REGNUM] && ir.dflag)
48315796c8dcSSimon Schubert         ir.dflag = 2;
48325796c8dcSSimon Schubert       if (i386_record_push (&ir, 1 << (ir.dflag + 1)))
48335796c8dcSSimon Schubert 	return -1;
48345796c8dcSSimon Schubert       break;
48355796c8dcSSimon Schubert 
4836cf7f2e2dSJohn Marino     case 0x06:    /* push es */
4837cf7f2e2dSJohn Marino     case 0x0e:    /* push cs */
4838cf7f2e2dSJohn Marino     case 0x16:    /* push ss */
4839cf7f2e2dSJohn Marino     case 0x1e:    /* push ds */
48405796c8dcSSimon Schubert       if (ir.regmap[X86_RECORD_R8_REGNUM])
48415796c8dcSSimon Schubert         {
48425796c8dcSSimon Schubert 	  ir.addr -= 1;
48435796c8dcSSimon Schubert 	  goto no_support;
48445796c8dcSSimon Schubert 	}
48455796c8dcSSimon Schubert       if (i386_record_push (&ir, 1 << (ir.dflag + 1)))
48465796c8dcSSimon Schubert 	return -1;
48475796c8dcSSimon Schubert       break;
48485796c8dcSSimon Schubert 
4849cf7f2e2dSJohn Marino     case 0x0fa0:    /* push fs */
4850cf7f2e2dSJohn Marino     case 0x0fa8:    /* push gs */
48515796c8dcSSimon Schubert       if (ir.regmap[X86_RECORD_R8_REGNUM])
48525796c8dcSSimon Schubert         {
48535796c8dcSSimon Schubert 	  ir.addr -= 2;
48545796c8dcSSimon Schubert 	  goto no_support;
48555796c8dcSSimon Schubert 	}
48565796c8dcSSimon Schubert       if (i386_record_push (&ir, 1 << (ir.dflag + 1)))
48575796c8dcSSimon Schubert 	return -1;
48585796c8dcSSimon Schubert       break;
48595796c8dcSSimon Schubert 
4860cf7f2e2dSJohn Marino     case 0x60:    /* pusha */
48615796c8dcSSimon Schubert       if (ir.regmap[X86_RECORD_R8_REGNUM])
48625796c8dcSSimon Schubert         {
48635796c8dcSSimon Schubert 	  ir.addr -= 1;
48645796c8dcSSimon Schubert 	  goto no_support;
48655796c8dcSSimon Schubert 	}
48665796c8dcSSimon Schubert       if (i386_record_push (&ir, 1 << (ir.dflag + 4)))
48675796c8dcSSimon Schubert 	return -1;
48685796c8dcSSimon Schubert       break;
48695796c8dcSSimon Schubert 
4870cf7f2e2dSJohn Marino     case 0x58:    /* pop */
48715796c8dcSSimon Schubert     case 0x59:
48725796c8dcSSimon Schubert     case 0x5a:
48735796c8dcSSimon Schubert     case 0x5b:
48745796c8dcSSimon Schubert     case 0x5c:
48755796c8dcSSimon Schubert     case 0x5d:
48765796c8dcSSimon Schubert     case 0x5e:
48775796c8dcSSimon Schubert     case 0x5f:
4878*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM);
4879*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG ((opcode & 0x7) | ir.rex_b);
48805796c8dcSSimon Schubert       break;
48815796c8dcSSimon Schubert 
4882cf7f2e2dSJohn Marino     case 0x61:    /* popa */
48835796c8dcSSimon Schubert       if (ir.regmap[X86_RECORD_R8_REGNUM])
48845796c8dcSSimon Schubert         {
48855796c8dcSSimon Schubert 	  ir.addr -= 1;
48865796c8dcSSimon Schubert 	  goto no_support;
48875796c8dcSSimon Schubert 	}
4888cf7f2e2dSJohn Marino       for (regnum = X86_RECORD_REAX_REGNUM;
4889cf7f2e2dSJohn Marino 	   regnum <= X86_RECORD_REDI_REGNUM;
4890cf7f2e2dSJohn Marino 	   regnum++)
4891*ef5ccd6cSJohn Marino 	I386_RECORD_FULL_ARCH_LIST_ADD_REG (regnum);
48925796c8dcSSimon Schubert       break;
48935796c8dcSSimon Schubert 
4894cf7f2e2dSJohn Marino     case 0x8f:    /* pop */
48955796c8dcSSimon Schubert       if (ir.regmap[X86_RECORD_R8_REGNUM])
48965796c8dcSSimon Schubert 	ir.ot = ir.dflag ? OT_QUAD : OT_WORD;
48975796c8dcSSimon Schubert       else
48985796c8dcSSimon Schubert         ir.ot = ir.dflag + OT_WORD;
48995796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
49005796c8dcSSimon Schubert 	return -1;
49015796c8dcSSimon Schubert       if (ir.mod == 3)
4902*ef5ccd6cSJohn Marino 	I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.rm | ir.rex_b);
49035796c8dcSSimon Schubert       else
49045796c8dcSSimon Schubert 	{
49055796c8dcSSimon Schubert           ir.popl_esp_hack = 1 << ir.ot;
49065796c8dcSSimon Schubert 	  if (i386_record_lea_modrm (&ir))
49075796c8dcSSimon Schubert 	    return -1;
49085796c8dcSSimon Schubert 	}
4909*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM);
49105796c8dcSSimon Schubert       break;
49115796c8dcSSimon Schubert 
4912cf7f2e2dSJohn Marino     case 0xc8:    /* enter */
4913*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REBP_REGNUM);
49145796c8dcSSimon Schubert       if (ir.regmap[X86_RECORD_R8_REGNUM] && ir.dflag)
49155796c8dcSSimon Schubert         ir.dflag = 2;
49165796c8dcSSimon Schubert       if (i386_record_push (&ir, 1 << (ir.dflag + 1)))
49175796c8dcSSimon Schubert 	return -1;
49185796c8dcSSimon Schubert       break;
49195796c8dcSSimon Schubert 
4920cf7f2e2dSJohn Marino     case 0xc9:    /* leave */
4921*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM);
4922*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REBP_REGNUM);
49235796c8dcSSimon Schubert       break;
49245796c8dcSSimon Schubert 
4925cf7f2e2dSJohn Marino     case 0x07:    /* pop es */
49265796c8dcSSimon Schubert       if (ir.regmap[X86_RECORD_R8_REGNUM])
49275796c8dcSSimon Schubert         {
49285796c8dcSSimon Schubert 	  ir.addr -= 1;
49295796c8dcSSimon Schubert 	  goto no_support;
49305796c8dcSSimon Schubert 	}
4931*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM);
4932*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_ES_REGNUM);
4933*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
49345796c8dcSSimon Schubert       break;
49355796c8dcSSimon Schubert 
4936cf7f2e2dSJohn Marino     case 0x17:    /* pop ss */
49375796c8dcSSimon Schubert       if (ir.regmap[X86_RECORD_R8_REGNUM])
49385796c8dcSSimon Schubert         {
49395796c8dcSSimon Schubert 	  ir.addr -= 1;
49405796c8dcSSimon Schubert 	  goto no_support;
49415796c8dcSSimon Schubert 	}
4942*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM);
4943*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_SS_REGNUM);
4944*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
49455796c8dcSSimon Schubert       break;
49465796c8dcSSimon Schubert 
4947cf7f2e2dSJohn Marino     case 0x1f:    /* pop ds */
49485796c8dcSSimon Schubert       if (ir.regmap[X86_RECORD_R8_REGNUM])
49495796c8dcSSimon Schubert         {
49505796c8dcSSimon Schubert 	  ir.addr -= 1;
49515796c8dcSSimon Schubert 	  goto no_support;
49525796c8dcSSimon Schubert 	}
4953*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM);
4954*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_DS_REGNUM);
4955*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
49565796c8dcSSimon Schubert       break;
49575796c8dcSSimon Schubert 
4958cf7f2e2dSJohn Marino     case 0x0fa1:    /* pop fs */
4959*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM);
4960*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_FS_REGNUM);
4961*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
49625796c8dcSSimon Schubert       break;
49635796c8dcSSimon Schubert 
4964cf7f2e2dSJohn Marino     case 0x0fa9:    /* pop gs */
4965*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM);
4966*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_GS_REGNUM);
4967*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
49685796c8dcSSimon Schubert       break;
49695796c8dcSSimon Schubert 
4970cf7f2e2dSJohn Marino     case 0x88:    /* mov */
49715796c8dcSSimon Schubert     case 0x89:
49725796c8dcSSimon Schubert     case 0xc6:
49735796c8dcSSimon Schubert     case 0xc7:
49745796c8dcSSimon Schubert       if ((opcode & 1) == 0)
49755796c8dcSSimon Schubert 	ir.ot = OT_BYTE;
49765796c8dcSSimon Schubert       else
49775796c8dcSSimon Schubert 	ir.ot = ir.dflag + OT_WORD;
49785796c8dcSSimon Schubert 
49795796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
49805796c8dcSSimon Schubert 	return -1;
49815796c8dcSSimon Schubert 
49825796c8dcSSimon Schubert       if (ir.mod != 3)
49835796c8dcSSimon Schubert 	{
49845796c8dcSSimon Schubert           if (opcode == 0xc6 || opcode == 0xc7)
49855796c8dcSSimon Schubert 	    ir.rip_offset = (ir.ot > OT_LONG) ? 4 : (1 << ir.ot);
49865796c8dcSSimon Schubert 	  if (i386_record_lea_modrm (&ir))
49875796c8dcSSimon Schubert 	    return -1;
49885796c8dcSSimon Schubert 	}
49895796c8dcSSimon Schubert       else
49905796c8dcSSimon Schubert 	{
49915796c8dcSSimon Schubert           if (opcode == 0xc6 || opcode == 0xc7)
49925796c8dcSSimon Schubert 	    ir.rm |= ir.rex_b;
49935796c8dcSSimon Schubert 	  if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM])
49945796c8dcSSimon Schubert 	    ir.rm &= 0x3;
4995*ef5ccd6cSJohn Marino 	  I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.rm);
49965796c8dcSSimon Schubert 	}
49975796c8dcSSimon Schubert       break;
49985796c8dcSSimon Schubert 
4999cf7f2e2dSJohn Marino     case 0x8a:    /* mov */
50005796c8dcSSimon Schubert     case 0x8b:
50015796c8dcSSimon Schubert       if ((opcode & 1) == 0)
50025796c8dcSSimon Schubert 	ir.ot = OT_BYTE;
50035796c8dcSSimon Schubert       else
50045796c8dcSSimon Schubert 	ir.ot = ir.dflag + OT_WORD;
50055796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
50065796c8dcSSimon Schubert 	return -1;
50075796c8dcSSimon Schubert       ir.reg |= rex_r;
50085796c8dcSSimon Schubert       if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM])
50095796c8dcSSimon Schubert 	ir.reg &= 0x3;
5010*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.reg);
50115796c8dcSSimon Schubert       break;
50125796c8dcSSimon Schubert 
5013cf7f2e2dSJohn Marino     case 0x8c:    /* mov seg */
50145796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
50155796c8dcSSimon Schubert 	return -1;
50165796c8dcSSimon Schubert       if (ir.reg > 5)
50175796c8dcSSimon Schubert 	{
50185796c8dcSSimon Schubert 	  ir.addr -= 2;
50195796c8dcSSimon Schubert 	  opcode = opcode << 8 | ir.modrm;
50205796c8dcSSimon Schubert 	  goto no_support;
50215796c8dcSSimon Schubert 	}
50225796c8dcSSimon Schubert 
50235796c8dcSSimon Schubert       if (ir.mod == 3)
5024*ef5ccd6cSJohn Marino 	I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.rm);
50255796c8dcSSimon Schubert       else
50265796c8dcSSimon Schubert 	{
50275796c8dcSSimon Schubert 	  ir.ot = OT_WORD;
50285796c8dcSSimon Schubert 	  if (i386_record_lea_modrm (&ir))
50295796c8dcSSimon Schubert 	    return -1;
50305796c8dcSSimon Schubert 	}
50315796c8dcSSimon Schubert       break;
50325796c8dcSSimon Schubert 
5033cf7f2e2dSJohn Marino     case 0x8e:    /* mov seg */
50345796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
50355796c8dcSSimon Schubert 	return -1;
50365796c8dcSSimon Schubert       switch (ir.reg)
50375796c8dcSSimon Schubert 	{
50385796c8dcSSimon Schubert 	case 0:
5039cf7f2e2dSJohn Marino 	  regnum = X86_RECORD_ES_REGNUM;
50405796c8dcSSimon Schubert 	  break;
50415796c8dcSSimon Schubert 	case 2:
5042cf7f2e2dSJohn Marino 	  regnum = X86_RECORD_SS_REGNUM;
50435796c8dcSSimon Schubert 	  break;
50445796c8dcSSimon Schubert 	case 3:
5045cf7f2e2dSJohn Marino 	  regnum = X86_RECORD_DS_REGNUM;
50465796c8dcSSimon Schubert 	  break;
50475796c8dcSSimon Schubert 	case 4:
5048cf7f2e2dSJohn Marino 	  regnum = X86_RECORD_FS_REGNUM;
50495796c8dcSSimon Schubert 	  break;
50505796c8dcSSimon Schubert 	case 5:
5051cf7f2e2dSJohn Marino 	  regnum = X86_RECORD_GS_REGNUM;
50525796c8dcSSimon Schubert 	  break;
50535796c8dcSSimon Schubert 	default:
50545796c8dcSSimon Schubert 	  ir.addr -= 2;
50555796c8dcSSimon Schubert 	  opcode = opcode << 8 | ir.modrm;
50565796c8dcSSimon Schubert 	  goto no_support;
50575796c8dcSSimon Schubert 	  break;
50585796c8dcSSimon Schubert 	}
5059*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (regnum);
5060*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
50615796c8dcSSimon Schubert       break;
50625796c8dcSSimon Schubert 
5063cf7f2e2dSJohn Marino     case 0x0fb6:    /* movzbS */
5064cf7f2e2dSJohn Marino     case 0x0fb7:    /* movzwS */
5065cf7f2e2dSJohn Marino     case 0x0fbe:    /* movsbS */
5066cf7f2e2dSJohn Marino     case 0x0fbf:    /* movswS */
50675796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
50685796c8dcSSimon Schubert 	return -1;
5069*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.reg | rex_r);
50705796c8dcSSimon Schubert       break;
50715796c8dcSSimon Schubert 
5072cf7f2e2dSJohn Marino     case 0x8d:      /* lea */
50735796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
50745796c8dcSSimon Schubert 	return -1;
50755796c8dcSSimon Schubert       if (ir.mod == 3)
50765796c8dcSSimon Schubert 	{
50775796c8dcSSimon Schubert 	  ir.addr -= 2;
50785796c8dcSSimon Schubert 	  opcode = opcode << 8 | ir.modrm;
50795796c8dcSSimon Schubert 	  goto no_support;
50805796c8dcSSimon Schubert 	}
50815796c8dcSSimon Schubert       ir.ot = ir.dflag;
50825796c8dcSSimon Schubert       ir.reg |= rex_r;
50835796c8dcSSimon Schubert       if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM])
50845796c8dcSSimon Schubert 	ir.reg &= 0x3;
5085*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.reg);
50865796c8dcSSimon Schubert       break;
50875796c8dcSSimon Schubert 
5088cf7f2e2dSJohn Marino     case 0xa0:    /* mov EAX */
50895796c8dcSSimon Schubert     case 0xa1:
5090cf7f2e2dSJohn Marino 
5091cf7f2e2dSJohn Marino     case 0xd7:    /* xlat */
5092*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM);
50935796c8dcSSimon Schubert       break;
50945796c8dcSSimon Schubert 
5095cf7f2e2dSJohn Marino     case 0xa2:    /* mov EAX */
50965796c8dcSSimon Schubert     case 0xa3:
50975796c8dcSSimon Schubert       if (ir.override >= 0)
50985796c8dcSSimon Schubert         {
5099*ef5ccd6cSJohn Marino           if (record_full_memory_query)
5100cf7f2e2dSJohn Marino             {
5101cf7f2e2dSJohn Marino 	      int q;
5102cf7f2e2dSJohn Marino 
5103cf7f2e2dSJohn Marino               target_terminal_ours ();
5104cf7f2e2dSJohn Marino               q = yquery (_("\
5105cf7f2e2dSJohn Marino Process record ignores the memory change of instruction at address %s\n\
5106cf7f2e2dSJohn Marino because it can't get the value of the segment register.\n\
5107cf7f2e2dSJohn Marino Do you want to stop the program?"),
51085796c8dcSSimon Schubert                           paddress (gdbarch, ir.orig_addr));
5109cf7f2e2dSJohn Marino               target_terminal_inferior ();
5110cf7f2e2dSJohn Marino               if (q)
5111cf7f2e2dSJohn Marino                 return -1;
5112cf7f2e2dSJohn Marino             }
51135796c8dcSSimon Schubert 	}
51145796c8dcSSimon Schubert       else
51155796c8dcSSimon Schubert 	{
51165796c8dcSSimon Schubert           if ((opcode & 1) == 0)
51175796c8dcSSimon Schubert 	    ir.ot = OT_BYTE;
51185796c8dcSSimon Schubert 	  else
51195796c8dcSSimon Schubert 	    ir.ot = ir.dflag + OT_WORD;
51205796c8dcSSimon Schubert 	  if (ir.aflag == 2)
51215796c8dcSSimon Schubert 	    {
5122*ef5ccd6cSJohn Marino               if (record_read_memory (gdbarch, ir.addr, buf, 8))
51235796c8dcSSimon Schubert 		return -1;
51245796c8dcSSimon Schubert 	      ir.addr += 8;
5125cf7f2e2dSJohn Marino 	      addr = extract_unsigned_integer (buf, 8, byte_order);
51265796c8dcSSimon Schubert 	    }
51275796c8dcSSimon Schubert           else if (ir.aflag)
51285796c8dcSSimon Schubert 	    {
5129*ef5ccd6cSJohn Marino               if (record_read_memory (gdbarch, ir.addr, buf, 4))
51305796c8dcSSimon Schubert 		return -1;
51315796c8dcSSimon Schubert 	      ir.addr += 4;
5132cf7f2e2dSJohn Marino               addr = extract_unsigned_integer (buf, 4, byte_order);
51335796c8dcSSimon Schubert 	    }
51345796c8dcSSimon Schubert           else
51355796c8dcSSimon Schubert 	    {
5136*ef5ccd6cSJohn Marino               if (record_read_memory (gdbarch, ir.addr, buf, 2))
51375796c8dcSSimon Schubert 		return -1;
51385796c8dcSSimon Schubert 	      ir.addr += 2;
5139cf7f2e2dSJohn Marino               addr = extract_unsigned_integer (buf, 2, byte_order);
51405796c8dcSSimon Schubert 	    }
5141*ef5ccd6cSJohn Marino 	  if (record_full_arch_list_add_mem (addr, 1 << ir.ot))
51425796c8dcSSimon Schubert 	    return -1;
51435796c8dcSSimon Schubert         }
51445796c8dcSSimon Schubert       break;
51455796c8dcSSimon Schubert 
5146cf7f2e2dSJohn Marino     case 0xb0:    /* mov R, Ib */
51475796c8dcSSimon Schubert     case 0xb1:
51485796c8dcSSimon Schubert     case 0xb2:
51495796c8dcSSimon Schubert     case 0xb3:
51505796c8dcSSimon Schubert     case 0xb4:
51515796c8dcSSimon Schubert     case 0xb5:
51525796c8dcSSimon Schubert     case 0xb6:
51535796c8dcSSimon Schubert     case 0xb7:
5154*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG ((ir.regmap[X86_RECORD_R8_REGNUM])
51555796c8dcSSimon Schubert 					  ? ((opcode & 0x7) | ir.rex_b)
51565796c8dcSSimon Schubert 					  : ((opcode & 0x7) & 0x3));
51575796c8dcSSimon Schubert       break;
51585796c8dcSSimon Schubert 
5159cf7f2e2dSJohn Marino     case 0xb8:    /* mov R, Iv */
51605796c8dcSSimon Schubert     case 0xb9:
51615796c8dcSSimon Schubert     case 0xba:
51625796c8dcSSimon Schubert     case 0xbb:
51635796c8dcSSimon Schubert     case 0xbc:
51645796c8dcSSimon Schubert     case 0xbd:
51655796c8dcSSimon Schubert     case 0xbe:
51665796c8dcSSimon Schubert     case 0xbf:
5167*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG ((opcode & 0x7) | ir.rex_b);
51685796c8dcSSimon Schubert       break;
51695796c8dcSSimon Schubert 
5170cf7f2e2dSJohn Marino     case 0x91:    /* xchg R, EAX */
51715796c8dcSSimon Schubert     case 0x92:
51725796c8dcSSimon Schubert     case 0x93:
51735796c8dcSSimon Schubert     case 0x94:
51745796c8dcSSimon Schubert     case 0x95:
51755796c8dcSSimon Schubert     case 0x96:
51765796c8dcSSimon Schubert     case 0x97:
5177*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM);
5178*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (opcode & 0x7);
51795796c8dcSSimon Schubert       break;
51805796c8dcSSimon Schubert 
5181cf7f2e2dSJohn Marino     case 0x86:    /* xchg Ev, Gv */
51825796c8dcSSimon Schubert     case 0x87:
51835796c8dcSSimon Schubert       if ((opcode & 1) == 0)
51845796c8dcSSimon Schubert 	ir.ot = OT_BYTE;
51855796c8dcSSimon Schubert       else
51865796c8dcSSimon Schubert 	ir.ot = ir.dflag + OT_WORD;
51875796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
51885796c8dcSSimon Schubert 	return -1;
51895796c8dcSSimon Schubert       if (ir.mod == 3)
51905796c8dcSSimon Schubert 	{
5191cf7f2e2dSJohn Marino 	  ir.rm |= ir.rex_b;
51925796c8dcSSimon Schubert 	  if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM])
51935796c8dcSSimon Schubert 	    ir.rm &= 0x3;
5194*ef5ccd6cSJohn Marino 	  I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.rm);
51955796c8dcSSimon Schubert 	}
51965796c8dcSSimon Schubert       else
51975796c8dcSSimon Schubert 	{
51985796c8dcSSimon Schubert 	  if (i386_record_lea_modrm (&ir))
51995796c8dcSSimon Schubert 	    return -1;
52005796c8dcSSimon Schubert 	}
52015796c8dcSSimon Schubert       ir.reg |= rex_r;
52025796c8dcSSimon Schubert       if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM])
52035796c8dcSSimon Schubert 	ir.reg &= 0x3;
5204*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.reg);
52055796c8dcSSimon Schubert       break;
52065796c8dcSSimon Schubert 
5207cf7f2e2dSJohn Marino     case 0xc4:    /* les Gv */
5208cf7f2e2dSJohn Marino     case 0xc5:    /* lds Gv */
52095796c8dcSSimon Schubert       if (ir.regmap[X86_RECORD_R8_REGNUM])
52105796c8dcSSimon Schubert         {
52115796c8dcSSimon Schubert 	  ir.addr -= 1;
52125796c8dcSSimon Schubert 	  goto no_support;
52135796c8dcSSimon Schubert 	}
5214c50c785cSJohn Marino       /* FALLTHROUGH */
5215cf7f2e2dSJohn Marino     case 0x0fb2:    /* lss Gv */
5216cf7f2e2dSJohn Marino     case 0x0fb4:    /* lfs Gv */
5217cf7f2e2dSJohn Marino     case 0x0fb5:    /* lgs Gv */
52185796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
52195796c8dcSSimon Schubert 	return -1;
52205796c8dcSSimon Schubert       if (ir.mod == 3)
52215796c8dcSSimon Schubert 	{
52225796c8dcSSimon Schubert 	  if (opcode > 0xff)
52235796c8dcSSimon Schubert 	    ir.addr -= 3;
52245796c8dcSSimon Schubert 	  else
52255796c8dcSSimon Schubert 	    ir.addr -= 2;
52265796c8dcSSimon Schubert 	  opcode = opcode << 8 | ir.modrm;
52275796c8dcSSimon Schubert 	  goto no_support;
52285796c8dcSSimon Schubert 	}
52295796c8dcSSimon Schubert       switch (opcode)
52305796c8dcSSimon Schubert 	{
5231cf7f2e2dSJohn Marino 	case 0xc4:    /* les Gv */
5232cf7f2e2dSJohn Marino 	  regnum = X86_RECORD_ES_REGNUM;
52335796c8dcSSimon Schubert 	  break;
5234cf7f2e2dSJohn Marino 	case 0xc5:    /* lds Gv */
5235cf7f2e2dSJohn Marino 	  regnum = X86_RECORD_DS_REGNUM;
52365796c8dcSSimon Schubert 	  break;
5237cf7f2e2dSJohn Marino 	case 0x0fb2:  /* lss Gv */
5238cf7f2e2dSJohn Marino 	  regnum = X86_RECORD_SS_REGNUM;
52395796c8dcSSimon Schubert 	  break;
5240cf7f2e2dSJohn Marino 	case 0x0fb4:  /* lfs Gv */
5241cf7f2e2dSJohn Marino 	  regnum = X86_RECORD_FS_REGNUM;
52425796c8dcSSimon Schubert 	  break;
5243cf7f2e2dSJohn Marino 	case 0x0fb5:  /* lgs Gv */
5244cf7f2e2dSJohn Marino 	  regnum = X86_RECORD_GS_REGNUM;
52455796c8dcSSimon Schubert 	  break;
52465796c8dcSSimon Schubert 	}
5247*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (regnum);
5248*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.reg | rex_r);
5249*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
52505796c8dcSSimon Schubert       break;
52515796c8dcSSimon Schubert 
5252cf7f2e2dSJohn Marino     case 0xc0:    /* shifts */
52535796c8dcSSimon Schubert     case 0xc1:
52545796c8dcSSimon Schubert     case 0xd0:
52555796c8dcSSimon Schubert     case 0xd1:
52565796c8dcSSimon Schubert     case 0xd2:
52575796c8dcSSimon Schubert     case 0xd3:
52585796c8dcSSimon Schubert       if ((opcode & 1) == 0)
52595796c8dcSSimon Schubert 	ir.ot = OT_BYTE;
52605796c8dcSSimon Schubert       else
52615796c8dcSSimon Schubert 	ir.ot = ir.dflag + OT_WORD;
52625796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
52635796c8dcSSimon Schubert 	return -1;
52645796c8dcSSimon Schubert       if (ir.mod != 3 && (opcode == 0xd2 || opcode == 0xd3))
52655796c8dcSSimon Schubert 	{
52665796c8dcSSimon Schubert 	  if (i386_record_lea_modrm (&ir))
52675796c8dcSSimon Schubert 	    return -1;
52685796c8dcSSimon Schubert 	}
52695796c8dcSSimon Schubert       else
52705796c8dcSSimon Schubert 	{
52715796c8dcSSimon Schubert 	  ir.rm |= ir.rex_b;
52725796c8dcSSimon Schubert 	  if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM])
52735796c8dcSSimon Schubert 	    ir.rm &= 0x3;
5274*ef5ccd6cSJohn Marino 	  I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.rm);
52755796c8dcSSimon Schubert 	}
5276*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
52775796c8dcSSimon Schubert       break;
52785796c8dcSSimon Schubert 
52795796c8dcSSimon Schubert     case 0x0fa4:
52805796c8dcSSimon Schubert     case 0x0fa5:
52815796c8dcSSimon Schubert     case 0x0fac:
52825796c8dcSSimon Schubert     case 0x0fad:
52835796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
52845796c8dcSSimon Schubert 	return -1;
52855796c8dcSSimon Schubert       if (ir.mod == 3)
52865796c8dcSSimon Schubert 	{
5287*ef5ccd6cSJohn Marino 	  if (record_full_arch_list_add_reg (ir.regcache, ir.rm))
52885796c8dcSSimon Schubert 	    return -1;
52895796c8dcSSimon Schubert 	}
52905796c8dcSSimon Schubert       else
52915796c8dcSSimon Schubert 	{
52925796c8dcSSimon Schubert 	  if (i386_record_lea_modrm (&ir))
52935796c8dcSSimon Schubert 	    return -1;
52945796c8dcSSimon Schubert 	}
52955796c8dcSSimon Schubert       break;
52965796c8dcSSimon Schubert 
5297cf7f2e2dSJohn Marino     case 0xd8:    /* Floats.  */
52985796c8dcSSimon Schubert     case 0xd9:
52995796c8dcSSimon Schubert     case 0xda:
53005796c8dcSSimon Schubert     case 0xdb:
53015796c8dcSSimon Schubert     case 0xdc:
53025796c8dcSSimon Schubert     case 0xdd:
53035796c8dcSSimon Schubert     case 0xde:
53045796c8dcSSimon Schubert     case 0xdf:
53055796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
53065796c8dcSSimon Schubert 	return -1;
53075796c8dcSSimon Schubert       ir.reg |= ((opcode & 7) << 3);
53085796c8dcSSimon Schubert       if (ir.mod != 3)
53095796c8dcSSimon Schubert 	{
5310cf7f2e2dSJohn Marino 	  /* Memory.  */
5311cf7f2e2dSJohn Marino 	  uint64_t addr64;
53125796c8dcSSimon Schubert 
5313cf7f2e2dSJohn Marino 	  if (i386_record_lea_modrm_addr (&ir, &addr64))
53145796c8dcSSimon Schubert 	    return -1;
53155796c8dcSSimon Schubert 	  switch (ir.reg)
53165796c8dcSSimon Schubert 	    {
5317cf7f2e2dSJohn Marino 	    case 0x02:
5318cf7f2e2dSJohn Marino             case 0x12:
5319cf7f2e2dSJohn Marino             case 0x22:
5320cf7f2e2dSJohn Marino             case 0x32:
5321cf7f2e2dSJohn Marino 	      /* For fcom, ficom nothing to do.  */
5322cf7f2e2dSJohn Marino               break;
5323cf7f2e2dSJohn Marino 	    case 0x03:
5324cf7f2e2dSJohn Marino             case 0x13:
5325cf7f2e2dSJohn Marino             case 0x23:
5326cf7f2e2dSJohn Marino             case 0x33:
5327cf7f2e2dSJohn Marino 	      /* For fcomp, ficomp pop FPU stack, store all.  */
5328cf7f2e2dSJohn Marino               if (i386_record_floats (gdbarch, &ir, I386_SAVE_FPU_REGS))
5329cf7f2e2dSJohn Marino                 return -1;
5330cf7f2e2dSJohn Marino               break;
53315796c8dcSSimon Schubert             case 0x00:
53325796c8dcSSimon Schubert             case 0x01:
53335796c8dcSSimon Schubert 	    case 0x04:
53345796c8dcSSimon Schubert 	    case 0x05:
53355796c8dcSSimon Schubert 	    case 0x06:
53365796c8dcSSimon Schubert 	    case 0x07:
53375796c8dcSSimon Schubert 	    case 0x10:
53385796c8dcSSimon Schubert 	    case 0x11:
53395796c8dcSSimon Schubert 	    case 0x14:
53405796c8dcSSimon Schubert 	    case 0x15:
53415796c8dcSSimon Schubert 	    case 0x16:
53425796c8dcSSimon Schubert 	    case 0x17:
53435796c8dcSSimon Schubert 	    case 0x20:
53445796c8dcSSimon Schubert 	    case 0x21:
53455796c8dcSSimon Schubert 	    case 0x24:
53465796c8dcSSimon Schubert 	    case 0x25:
53475796c8dcSSimon Schubert 	    case 0x26:
53485796c8dcSSimon Schubert 	    case 0x27:
53495796c8dcSSimon Schubert 	    case 0x30:
53505796c8dcSSimon Schubert 	    case 0x31:
53515796c8dcSSimon Schubert 	    case 0x34:
53525796c8dcSSimon Schubert 	    case 0x35:
53535796c8dcSSimon Schubert 	    case 0x36:
53545796c8dcSSimon Schubert 	    case 0x37:
5355cf7f2e2dSJohn Marino               /* For fadd, fmul, fsub, fsubr, fdiv, fdivr, fiadd, fimul,
5356cf7f2e2dSJohn Marino                  fisub, fisubr, fidiv, fidivr, modR/M.reg is an extension
5357cf7f2e2dSJohn Marino                  of code,  always affects st(0) register.  */
5358cf7f2e2dSJohn Marino               if (i386_record_floats (gdbarch, &ir, I387_ST0_REGNUM (tdep)))
5359cf7f2e2dSJohn Marino                 return -1;
53605796c8dcSSimon Schubert 	      break;
53615796c8dcSSimon Schubert 	    case 0x08:
53625796c8dcSSimon Schubert 	    case 0x0a:
53635796c8dcSSimon Schubert 	    case 0x0b:
53645796c8dcSSimon Schubert 	    case 0x18:
53655796c8dcSSimon Schubert 	    case 0x19:
53665796c8dcSSimon Schubert 	    case 0x1a:
53675796c8dcSSimon Schubert 	    case 0x1b:
5368cf7f2e2dSJohn Marino             case 0x1d:
53695796c8dcSSimon Schubert 	    case 0x28:
53705796c8dcSSimon Schubert 	    case 0x29:
53715796c8dcSSimon Schubert 	    case 0x2a:
53725796c8dcSSimon Schubert 	    case 0x2b:
53735796c8dcSSimon Schubert 	    case 0x38:
53745796c8dcSSimon Schubert 	    case 0x39:
53755796c8dcSSimon Schubert 	    case 0x3a:
53765796c8dcSSimon Schubert 	    case 0x3b:
5377cf7f2e2dSJohn Marino             case 0x3c:
5378cf7f2e2dSJohn Marino             case 0x3d:
53795796c8dcSSimon Schubert 	      switch (ir.reg & 7)
53805796c8dcSSimon Schubert 		{
53815796c8dcSSimon Schubert 		case 0:
5382cf7f2e2dSJohn Marino 		  /* Handling fld, fild.  */
5383cf7f2e2dSJohn Marino 		  if (i386_record_floats (gdbarch, &ir, I386_SAVE_FPU_REGS))
5384cf7f2e2dSJohn Marino 		    return -1;
53855796c8dcSSimon Schubert 		  break;
53865796c8dcSSimon Schubert 		case 1:
53875796c8dcSSimon Schubert 		  switch (ir.reg >> 4)
53885796c8dcSSimon Schubert 		    {
53895796c8dcSSimon Schubert 		    case 0:
5390*ef5ccd6cSJohn Marino 		      if (record_full_arch_list_add_mem (addr64, 4))
53915796c8dcSSimon Schubert 			return -1;
53925796c8dcSSimon Schubert 		      break;
53935796c8dcSSimon Schubert 		    case 2:
5394*ef5ccd6cSJohn Marino 		      if (record_full_arch_list_add_mem (addr64, 8))
53955796c8dcSSimon Schubert 			return -1;
53965796c8dcSSimon Schubert 		      break;
53975796c8dcSSimon Schubert 		    case 3:
5398cf7f2e2dSJohn Marino 		      break;
53995796c8dcSSimon Schubert 		    default:
5400*ef5ccd6cSJohn Marino 		      if (record_full_arch_list_add_mem (addr64, 2))
54015796c8dcSSimon Schubert 			return -1;
54025796c8dcSSimon Schubert 		      break;
54035796c8dcSSimon Schubert 		    }
54045796c8dcSSimon Schubert 		  break;
54055796c8dcSSimon Schubert 		default:
54065796c8dcSSimon Schubert 		  switch (ir.reg >> 4)
54075796c8dcSSimon Schubert 		    {
54085796c8dcSSimon Schubert 		    case 0:
5409*ef5ccd6cSJohn Marino 		      if (record_full_arch_list_add_mem (addr64, 4))
54105796c8dcSSimon Schubert 			return -1;
5411cf7f2e2dSJohn Marino 		      if (3 == (ir.reg & 7))
5412cf7f2e2dSJohn Marino 			{
5413cf7f2e2dSJohn Marino 			  /* For fstp m32fp.  */
5414cf7f2e2dSJohn Marino 			  if (i386_record_floats (gdbarch, &ir,
5415cf7f2e2dSJohn Marino 						  I386_SAVE_FPU_REGS))
5416cf7f2e2dSJohn Marino 			    return -1;
5417cf7f2e2dSJohn Marino 			}
5418cf7f2e2dSJohn Marino 		      break;
5419cf7f2e2dSJohn Marino 		    case 1:
5420*ef5ccd6cSJohn Marino 		      if (record_full_arch_list_add_mem (addr64, 4))
5421cf7f2e2dSJohn Marino 			return -1;
5422cf7f2e2dSJohn Marino 		      if ((3 == (ir.reg & 7))
5423cf7f2e2dSJohn Marino 			  || (5 == (ir.reg & 7))
5424cf7f2e2dSJohn Marino 			  || (7 == (ir.reg & 7)))
5425cf7f2e2dSJohn Marino 			{
5426cf7f2e2dSJohn Marino 			  /* For fstp insn.  */
5427cf7f2e2dSJohn Marino 			  if (i386_record_floats (gdbarch, &ir,
5428cf7f2e2dSJohn Marino 						  I386_SAVE_FPU_REGS))
5429cf7f2e2dSJohn Marino 			    return -1;
5430cf7f2e2dSJohn Marino 			}
54315796c8dcSSimon Schubert 		      break;
54325796c8dcSSimon Schubert 		    case 2:
5433*ef5ccd6cSJohn Marino 		      if (record_full_arch_list_add_mem (addr64, 8))
54345796c8dcSSimon Schubert 			return -1;
5435cf7f2e2dSJohn Marino 		      if (3 == (ir.reg & 7))
5436cf7f2e2dSJohn Marino 			{
5437cf7f2e2dSJohn Marino 			  /* For fstp m64fp.  */
5438cf7f2e2dSJohn Marino 			  if (i386_record_floats (gdbarch, &ir,
5439cf7f2e2dSJohn Marino 						  I386_SAVE_FPU_REGS))
5440cf7f2e2dSJohn Marino 			    return -1;
5441cf7f2e2dSJohn Marino 			}
54425796c8dcSSimon Schubert 		      break;
54435796c8dcSSimon Schubert 		    case 3:
5444cf7f2e2dSJohn Marino 		      if ((3 <= (ir.reg & 7)) && (6 <= (ir.reg & 7)))
5445cf7f2e2dSJohn Marino 			{
5446cf7f2e2dSJohn Marino 			  /* For fistp, fbld, fild, fbstp.  */
5447cf7f2e2dSJohn Marino 			  if (i386_record_floats (gdbarch, &ir,
5448cf7f2e2dSJohn Marino 						  I386_SAVE_FPU_REGS))
5449cf7f2e2dSJohn Marino 			    return -1;
5450cf7f2e2dSJohn Marino 			}
5451cf7f2e2dSJohn Marino 		      /* Fall through */
54525796c8dcSSimon Schubert 		    default:
5453*ef5ccd6cSJohn Marino 		      if (record_full_arch_list_add_mem (addr64, 2))
54545796c8dcSSimon Schubert 			return -1;
54555796c8dcSSimon Schubert 		      break;
54565796c8dcSSimon Schubert 		    }
54575796c8dcSSimon Schubert 		  break;
54585796c8dcSSimon Schubert 		}
54595796c8dcSSimon Schubert 	      break;
54605796c8dcSSimon Schubert 	    case 0x0c:
5461cf7f2e2dSJohn Marino               /* Insn fldenv.  */
5462cf7f2e2dSJohn Marino               if (i386_record_floats (gdbarch, &ir,
5463cf7f2e2dSJohn Marino                                       I386_SAVE_FPU_ENV_REG_STACK))
5464cf7f2e2dSJohn Marino                 return -1;
5465cf7f2e2dSJohn Marino               break;
54665796c8dcSSimon Schubert 	    case 0x0d:
5467cf7f2e2dSJohn Marino               /* Insn fldcw.  */
5468cf7f2e2dSJohn Marino               if (i386_record_floats (gdbarch, &ir, I387_FCTRL_REGNUM (tdep)))
5469cf7f2e2dSJohn Marino                 return -1;
5470cf7f2e2dSJohn Marino               break;
54715796c8dcSSimon Schubert 	    case 0x2c:
5472cf7f2e2dSJohn Marino               /* Insn frstor.  */
5473cf7f2e2dSJohn Marino               if (i386_record_floats (gdbarch, &ir,
5474cf7f2e2dSJohn Marino                                       I386_SAVE_FPU_ENV_REG_STACK))
5475cf7f2e2dSJohn Marino                 return -1;
54765796c8dcSSimon Schubert 	      break;
54775796c8dcSSimon Schubert 	    case 0x0e:
54785796c8dcSSimon Schubert 	      if (ir.dflag)
54795796c8dcSSimon Schubert 		{
5480*ef5ccd6cSJohn Marino 		  if (record_full_arch_list_add_mem (addr64, 28))
54815796c8dcSSimon Schubert 		    return -1;
54825796c8dcSSimon Schubert 		}
54835796c8dcSSimon Schubert 	      else
54845796c8dcSSimon Schubert 		{
5485*ef5ccd6cSJohn Marino 		  if (record_full_arch_list_add_mem (addr64, 14))
54865796c8dcSSimon Schubert 		    return -1;
54875796c8dcSSimon Schubert 		}
54885796c8dcSSimon Schubert 	      break;
54895796c8dcSSimon Schubert 	    case 0x0f:
54905796c8dcSSimon Schubert 	    case 0x2f:
5491*ef5ccd6cSJohn Marino 	      if (record_full_arch_list_add_mem (addr64, 2))
5492cf7f2e2dSJohn Marino 		return -1;
5493cf7f2e2dSJohn Marino               /* Insn fstp, fbstp.  */
5494cf7f2e2dSJohn Marino               if (i386_record_floats (gdbarch, &ir, I386_SAVE_FPU_REGS))
54955796c8dcSSimon Schubert                 return -1;
54965796c8dcSSimon Schubert 	      break;
54975796c8dcSSimon Schubert 	    case 0x1f:
54985796c8dcSSimon Schubert 	    case 0x3e:
5499*ef5ccd6cSJohn Marino 	      if (record_full_arch_list_add_mem (addr64, 10))
55005796c8dcSSimon Schubert 		return -1;
55015796c8dcSSimon Schubert 	      break;
55025796c8dcSSimon Schubert 	    case 0x2e:
55035796c8dcSSimon Schubert 	      if (ir.dflag)
55045796c8dcSSimon Schubert 		{
5505*ef5ccd6cSJohn Marino 		  if (record_full_arch_list_add_mem (addr64, 28))
55065796c8dcSSimon Schubert 		    return -1;
5507cf7f2e2dSJohn Marino 		  addr64 += 28;
55085796c8dcSSimon Schubert 		}
55095796c8dcSSimon Schubert 	      else
55105796c8dcSSimon Schubert 		{
5511*ef5ccd6cSJohn Marino 		  if (record_full_arch_list_add_mem (addr64, 14))
55125796c8dcSSimon Schubert 		    return -1;
5513cf7f2e2dSJohn Marino 		  addr64 += 14;
55145796c8dcSSimon Schubert 		}
5515*ef5ccd6cSJohn Marino 	      if (record_full_arch_list_add_mem (addr64, 80))
5516cf7f2e2dSJohn Marino 		return -1;
5517cf7f2e2dSJohn Marino 	      /* Insn fsave.  */
5518cf7f2e2dSJohn Marino 	      if (i386_record_floats (gdbarch, &ir,
5519cf7f2e2dSJohn Marino 				      I386_SAVE_FPU_ENV_REG_STACK))
55205796c8dcSSimon Schubert 		return -1;
55215796c8dcSSimon Schubert 	      break;
55225796c8dcSSimon Schubert 	    case 0x3f:
5523*ef5ccd6cSJohn Marino 	      if (record_full_arch_list_add_mem (addr64, 8))
5524cf7f2e2dSJohn Marino 		return -1;
5525cf7f2e2dSJohn Marino 	      /* Insn fistp.  */
5526cf7f2e2dSJohn Marino 	      if (i386_record_floats (gdbarch, &ir, I386_SAVE_FPU_REGS))
55275796c8dcSSimon Schubert 		return -1;
55285796c8dcSSimon Schubert 	      break;
55295796c8dcSSimon Schubert 	    default:
55305796c8dcSSimon Schubert 	      ir.addr -= 2;
55315796c8dcSSimon Schubert 	      opcode = opcode << 8 | ir.modrm;
55325796c8dcSSimon Schubert 	      goto no_support;
55335796c8dcSSimon Schubert 	      break;
55345796c8dcSSimon Schubert 	    }
55355796c8dcSSimon Schubert 	}
5536cf7f2e2dSJohn Marino       /* Opcode is an extension of modR/M byte.  */
5537cf7f2e2dSJohn Marino       else
5538cf7f2e2dSJohn Marino         {
5539cf7f2e2dSJohn Marino 	  switch (opcode)
5540cf7f2e2dSJohn Marino 	    {
5541cf7f2e2dSJohn Marino 	    case 0xd8:
5542cf7f2e2dSJohn Marino 	      if (i386_record_floats (gdbarch, &ir, I387_ST0_REGNUM (tdep)))
5543cf7f2e2dSJohn Marino 		return -1;
55445796c8dcSSimon Schubert 	      break;
5545cf7f2e2dSJohn Marino 	    case 0xd9:
5546cf7f2e2dSJohn Marino 	      if (0x0c == (ir.modrm >> 4))
5547cf7f2e2dSJohn Marino 		{
5548cf7f2e2dSJohn Marino 		  if ((ir.modrm & 0x0f) <= 7)
5549cf7f2e2dSJohn Marino 		    {
5550cf7f2e2dSJohn Marino 		      if (i386_record_floats (gdbarch, &ir,
5551cf7f2e2dSJohn Marino 					      I386_SAVE_FPU_REGS))
5552cf7f2e2dSJohn Marino 			return -1;
5553cf7f2e2dSJohn Marino 		    }
5554cf7f2e2dSJohn Marino                   else
5555cf7f2e2dSJohn Marino 		    {
5556cf7f2e2dSJohn Marino 		      if (i386_record_floats (gdbarch, &ir,
5557cf7f2e2dSJohn Marino 					      I387_ST0_REGNUM (tdep)))
5558cf7f2e2dSJohn Marino 			return -1;
5559cf7f2e2dSJohn Marino 		      /* If only st(0) is changing, then we have already
5560cf7f2e2dSJohn Marino 			 recorded.  */
5561cf7f2e2dSJohn Marino 		      if ((ir.modrm & 0x0f) - 0x08)
5562cf7f2e2dSJohn Marino 			{
5563cf7f2e2dSJohn Marino 			  if (i386_record_floats (gdbarch, &ir,
5564cf7f2e2dSJohn Marino 						  I387_ST0_REGNUM (tdep) +
5565cf7f2e2dSJohn Marino 						  ((ir.modrm & 0x0f) - 0x08)))
5566cf7f2e2dSJohn Marino 			    return -1;
5567cf7f2e2dSJohn Marino 			}
5568cf7f2e2dSJohn Marino 		    }
5569cf7f2e2dSJohn Marino 		}
5570cf7f2e2dSJohn Marino               else
5571cf7f2e2dSJohn Marino                 {
5572cf7f2e2dSJohn Marino 		  switch (ir.modrm)
5573cf7f2e2dSJohn Marino 		    {
5574cf7f2e2dSJohn Marino 		    case 0xe0:
5575cf7f2e2dSJohn Marino 		    case 0xe1:
5576cf7f2e2dSJohn Marino 		    case 0xf0:
5577cf7f2e2dSJohn Marino 		    case 0xf5:
5578cf7f2e2dSJohn Marino 		    case 0xf8:
5579cf7f2e2dSJohn Marino 		    case 0xfa:
5580cf7f2e2dSJohn Marino 		    case 0xfc:
5581cf7f2e2dSJohn Marino 		    case 0xfe:
5582cf7f2e2dSJohn Marino 		    case 0xff:
5583cf7f2e2dSJohn Marino 		      if (i386_record_floats (gdbarch, &ir,
5584cf7f2e2dSJohn Marino 					      I387_ST0_REGNUM (tdep)))
5585cf7f2e2dSJohn Marino 			return -1;
5586cf7f2e2dSJohn Marino 		      break;
5587cf7f2e2dSJohn Marino 		    case 0xf1:
5588cf7f2e2dSJohn Marino 		    case 0xf2:
5589cf7f2e2dSJohn Marino 		    case 0xf3:
5590cf7f2e2dSJohn Marino 		    case 0xf4:
5591cf7f2e2dSJohn Marino 		    case 0xf6:
5592cf7f2e2dSJohn Marino 		    case 0xf7:
5593cf7f2e2dSJohn Marino 		    case 0xe8:
5594cf7f2e2dSJohn Marino 		    case 0xe9:
5595cf7f2e2dSJohn Marino 		    case 0xea:
5596cf7f2e2dSJohn Marino 		    case 0xeb:
5597cf7f2e2dSJohn Marino 		    case 0xec:
5598cf7f2e2dSJohn Marino 		    case 0xed:
5599cf7f2e2dSJohn Marino 		    case 0xee:
5600cf7f2e2dSJohn Marino 		    case 0xf9:
5601cf7f2e2dSJohn Marino 		    case 0xfb:
5602cf7f2e2dSJohn Marino 		      if (i386_record_floats (gdbarch, &ir,
5603cf7f2e2dSJohn Marino 					      I386_SAVE_FPU_REGS))
5604cf7f2e2dSJohn Marino 			return -1;
5605cf7f2e2dSJohn Marino 		      break;
5606cf7f2e2dSJohn Marino 		    case 0xfd:
5607cf7f2e2dSJohn Marino 		      if (i386_record_floats (gdbarch, &ir,
5608cf7f2e2dSJohn Marino 					      I387_ST0_REGNUM (tdep)))
5609cf7f2e2dSJohn Marino 			return -1;
5610cf7f2e2dSJohn Marino 		      if (i386_record_floats (gdbarch, &ir,
5611cf7f2e2dSJohn Marino 					      I387_ST0_REGNUM (tdep) + 1))
5612cf7f2e2dSJohn Marino 			return -1;
5613cf7f2e2dSJohn Marino 		      break;
5614cf7f2e2dSJohn Marino 		    }
5615cf7f2e2dSJohn Marino 		}
5616cf7f2e2dSJohn Marino               break;
5617cf7f2e2dSJohn Marino             case 0xda:
5618cf7f2e2dSJohn Marino               if (0xe9 == ir.modrm)
5619cf7f2e2dSJohn Marino                 {
5620cf7f2e2dSJohn Marino 		  if (i386_record_floats (gdbarch, &ir, I386_SAVE_FPU_REGS))
5621cf7f2e2dSJohn Marino 		    return -1;
5622cf7f2e2dSJohn Marino                 }
5623cf7f2e2dSJohn Marino               else if ((0x0c == ir.modrm >> 4) || (0x0d == ir.modrm >> 4))
5624cf7f2e2dSJohn Marino                 {
5625cf7f2e2dSJohn Marino 		  if (i386_record_floats (gdbarch, &ir,
5626cf7f2e2dSJohn Marino 					  I387_ST0_REGNUM (tdep)))
5627cf7f2e2dSJohn Marino 		    return -1;
5628cf7f2e2dSJohn Marino 		  if (((ir.modrm & 0x0f) > 0) && ((ir.modrm & 0x0f) <= 7))
5629cf7f2e2dSJohn Marino 		    {
5630cf7f2e2dSJohn Marino 		      if (i386_record_floats (gdbarch, &ir,
5631cf7f2e2dSJohn Marino 					      I387_ST0_REGNUM (tdep) +
5632cf7f2e2dSJohn Marino 					      (ir.modrm & 0x0f)))
5633cf7f2e2dSJohn Marino 			return -1;
5634cf7f2e2dSJohn Marino 		    }
5635cf7f2e2dSJohn Marino 		  else if ((ir.modrm & 0x0f) - 0x08)
5636cf7f2e2dSJohn Marino 		    {
5637cf7f2e2dSJohn Marino 		      if (i386_record_floats (gdbarch, &ir,
5638cf7f2e2dSJohn Marino 					      I387_ST0_REGNUM (tdep) +
5639cf7f2e2dSJohn Marino 					      ((ir.modrm & 0x0f) - 0x08)))
5640cf7f2e2dSJohn Marino 			return -1;
5641cf7f2e2dSJohn Marino 		    }
5642cf7f2e2dSJohn Marino                 }
5643cf7f2e2dSJohn Marino               break;
5644cf7f2e2dSJohn Marino             case 0xdb:
5645cf7f2e2dSJohn Marino               if (0xe3 == ir.modrm)
5646cf7f2e2dSJohn Marino                 {
5647cf7f2e2dSJohn Marino 		  if (i386_record_floats (gdbarch, &ir, I386_SAVE_FPU_ENV))
5648cf7f2e2dSJohn Marino 		    return -1;
5649cf7f2e2dSJohn Marino                 }
5650cf7f2e2dSJohn Marino               else if ((0x0c == ir.modrm >> 4) || (0x0d == ir.modrm >> 4))
5651cf7f2e2dSJohn Marino                 {
5652cf7f2e2dSJohn Marino 		  if (i386_record_floats (gdbarch, &ir,
5653cf7f2e2dSJohn Marino 					  I387_ST0_REGNUM (tdep)))
5654cf7f2e2dSJohn Marino 		    return -1;
5655cf7f2e2dSJohn Marino 		  if (((ir.modrm & 0x0f) > 0) && ((ir.modrm & 0x0f) <= 7))
5656cf7f2e2dSJohn Marino 		    {
5657cf7f2e2dSJohn Marino 		      if (i386_record_floats (gdbarch, &ir,
5658cf7f2e2dSJohn Marino 					      I387_ST0_REGNUM (tdep) +
5659cf7f2e2dSJohn Marino 					      (ir.modrm & 0x0f)))
5660cf7f2e2dSJohn Marino 			return -1;
5661cf7f2e2dSJohn Marino 		    }
5662cf7f2e2dSJohn Marino 		  else if ((ir.modrm & 0x0f) - 0x08)
5663cf7f2e2dSJohn Marino 		    {
5664cf7f2e2dSJohn Marino 		      if (i386_record_floats (gdbarch, &ir,
5665cf7f2e2dSJohn Marino 					      I387_ST0_REGNUM (tdep) +
5666cf7f2e2dSJohn Marino 					      ((ir.modrm & 0x0f) - 0x08)))
5667cf7f2e2dSJohn Marino 			return -1;
5668cf7f2e2dSJohn Marino 		    }
5669cf7f2e2dSJohn Marino                 }
5670cf7f2e2dSJohn Marino               break;
5671cf7f2e2dSJohn Marino             case 0xdc:
5672cf7f2e2dSJohn Marino               if ((0x0c == ir.modrm >> 4)
5673cf7f2e2dSJohn Marino 		  || (0x0d == ir.modrm >> 4)
5674cf7f2e2dSJohn Marino 		  || (0x0f == ir.modrm >> 4))
5675cf7f2e2dSJohn Marino                 {
5676cf7f2e2dSJohn Marino 		  if ((ir.modrm & 0x0f) <= 7)
5677cf7f2e2dSJohn Marino 		    {
5678cf7f2e2dSJohn Marino 		      if (i386_record_floats (gdbarch, &ir,
5679cf7f2e2dSJohn Marino 					      I387_ST0_REGNUM (tdep) +
5680cf7f2e2dSJohn Marino 					      (ir.modrm & 0x0f)))
5681cf7f2e2dSJohn Marino 			return -1;
5682cf7f2e2dSJohn Marino 		    }
5683cf7f2e2dSJohn Marino 		  else
5684cf7f2e2dSJohn Marino 		    {
5685cf7f2e2dSJohn Marino 		      if (i386_record_floats (gdbarch, &ir,
5686cf7f2e2dSJohn Marino 					      I387_ST0_REGNUM (tdep) +
5687cf7f2e2dSJohn Marino 					      ((ir.modrm & 0x0f) - 0x08)))
5688cf7f2e2dSJohn Marino 			return -1;
5689cf7f2e2dSJohn Marino 		    }
5690cf7f2e2dSJohn Marino                 }
5691cf7f2e2dSJohn Marino 	      break;
5692cf7f2e2dSJohn Marino             case 0xdd:
5693cf7f2e2dSJohn Marino               if (0x0c == ir.modrm >> 4)
5694cf7f2e2dSJohn Marino                 {
5695cf7f2e2dSJohn Marino                   if (i386_record_floats (gdbarch, &ir,
5696cf7f2e2dSJohn Marino                                           I387_FTAG_REGNUM (tdep)))
5697cf7f2e2dSJohn Marino                     return -1;
5698cf7f2e2dSJohn Marino                 }
5699cf7f2e2dSJohn Marino               else if ((0x0d == ir.modrm >> 4) || (0x0e == ir.modrm >> 4))
5700cf7f2e2dSJohn Marino                 {
5701cf7f2e2dSJohn Marino                   if ((ir.modrm & 0x0f) <= 7)
5702cf7f2e2dSJohn Marino                     {
5703cf7f2e2dSJohn Marino 		      if (i386_record_floats (gdbarch, &ir,
5704cf7f2e2dSJohn Marino 					      I387_ST0_REGNUM (tdep) +
5705cf7f2e2dSJohn Marino 					      (ir.modrm & 0x0f)))
5706cf7f2e2dSJohn Marino 			return -1;
5707cf7f2e2dSJohn Marino                     }
5708cf7f2e2dSJohn Marino                   else
5709cf7f2e2dSJohn Marino                     {
5710cf7f2e2dSJohn Marino                       if (i386_record_floats (gdbarch, &ir,
5711cf7f2e2dSJohn Marino 					      I386_SAVE_FPU_REGS))
5712cf7f2e2dSJohn Marino                         return -1;
5713cf7f2e2dSJohn Marino                     }
5714cf7f2e2dSJohn Marino                 }
5715cf7f2e2dSJohn Marino               break;
5716cf7f2e2dSJohn Marino             case 0xde:
5717cf7f2e2dSJohn Marino               if ((0x0c == ir.modrm >> 4)
5718cf7f2e2dSJohn Marino 		  || (0x0e == ir.modrm >> 4)
5719cf7f2e2dSJohn Marino 		  || (0x0f == ir.modrm >> 4)
5720cf7f2e2dSJohn Marino 		  || (0xd9 == ir.modrm))
5721cf7f2e2dSJohn Marino                 {
5722cf7f2e2dSJohn Marino 		  if (i386_record_floats (gdbarch, &ir, I386_SAVE_FPU_REGS))
5723cf7f2e2dSJohn Marino 		    return -1;
5724cf7f2e2dSJohn Marino                 }
5725cf7f2e2dSJohn Marino               break;
5726cf7f2e2dSJohn Marino             case 0xdf:
5727cf7f2e2dSJohn Marino               if (0xe0 == ir.modrm)
5728cf7f2e2dSJohn Marino                 {
5729*ef5ccd6cSJohn Marino 		  if (record_full_arch_list_add_reg (ir.regcache,
5730*ef5ccd6cSJohn Marino 						     I386_EAX_REGNUM))
5731cf7f2e2dSJohn Marino 		    return -1;
5732cf7f2e2dSJohn Marino                 }
5733cf7f2e2dSJohn Marino               else if ((0x0f == ir.modrm >> 4) || (0x0e == ir.modrm >> 4))
5734cf7f2e2dSJohn Marino                 {
5735cf7f2e2dSJohn Marino 		  if (i386_record_floats (gdbarch, &ir, I386_SAVE_FPU_REGS))
5736cf7f2e2dSJohn Marino 		    return -1;
5737cf7f2e2dSJohn Marino                 }
5738cf7f2e2dSJohn Marino               break;
5739cf7f2e2dSJohn Marino 	    }
5740cf7f2e2dSJohn Marino 	}
5741cf7f2e2dSJohn Marino       break;
57425796c8dcSSimon Schubert       /* string ops */
5743cf7f2e2dSJohn Marino     case 0xa4:    /* movsS */
57445796c8dcSSimon Schubert     case 0xa5:
5745cf7f2e2dSJohn Marino     case 0xaa:    /* stosS */
57465796c8dcSSimon Schubert     case 0xab:
5747cf7f2e2dSJohn Marino     case 0x6c:    /* insS */
57485796c8dcSSimon Schubert     case 0x6d:
57495796c8dcSSimon Schubert       regcache_raw_read_unsigned (ir.regcache,
57505796c8dcSSimon Schubert                                   ir.regmap[X86_RECORD_RECX_REGNUM],
5751cf7f2e2dSJohn Marino                                   &addr);
5752cf7f2e2dSJohn Marino       if (addr)
57535796c8dcSSimon Schubert         {
57545796c8dcSSimon Schubert           ULONGEST es, ds;
57555796c8dcSSimon Schubert 
57565796c8dcSSimon Schubert           if ((opcode & 1) == 0)
57575796c8dcSSimon Schubert 	    ir.ot = OT_BYTE;
57585796c8dcSSimon Schubert           else
57595796c8dcSSimon Schubert 	    ir.ot = ir.dflag + OT_WORD;
57605796c8dcSSimon Schubert           regcache_raw_read_unsigned (ir.regcache,
57615796c8dcSSimon Schubert                                       ir.regmap[X86_RECORD_REDI_REGNUM],
5762cf7f2e2dSJohn Marino                                       &addr);
57635796c8dcSSimon Schubert 
57645796c8dcSSimon Schubert           regcache_raw_read_unsigned (ir.regcache,
57655796c8dcSSimon Schubert                                       ir.regmap[X86_RECORD_ES_REGNUM],
57665796c8dcSSimon Schubert                                       &es);
57675796c8dcSSimon Schubert           regcache_raw_read_unsigned (ir.regcache,
57685796c8dcSSimon Schubert                                       ir.regmap[X86_RECORD_DS_REGNUM],
57695796c8dcSSimon Schubert                                       &ds);
57705796c8dcSSimon Schubert           if (ir.aflag && (es != ds))
57715796c8dcSSimon Schubert             {
57725796c8dcSSimon Schubert               /* addr += ((uint32_t) read_register (I386_ES_REGNUM)) << 4; */
5773*ef5ccd6cSJohn Marino               if (record_full_memory_query)
5774cf7f2e2dSJohn Marino                 {
5775cf7f2e2dSJohn Marino 	          int q;
5776cf7f2e2dSJohn Marino 
5777cf7f2e2dSJohn Marino                   target_terminal_ours ();
5778cf7f2e2dSJohn Marino                   q = yquery (_("\
5779cf7f2e2dSJohn Marino Process record ignores the memory change of instruction at address %s\n\
5780cf7f2e2dSJohn Marino because it can't get the value of the segment register.\n\
5781cf7f2e2dSJohn Marino Do you want to stop the program?"),
57825796c8dcSSimon Schubert                               paddress (gdbarch, ir.orig_addr));
5783cf7f2e2dSJohn Marino                   target_terminal_inferior ();
5784cf7f2e2dSJohn Marino                   if (q)
5785cf7f2e2dSJohn Marino                     return -1;
5786cf7f2e2dSJohn Marino                 }
57875796c8dcSSimon Schubert             }
57885796c8dcSSimon Schubert           else
57895796c8dcSSimon Schubert             {
5790*ef5ccd6cSJohn Marino               if (record_full_arch_list_add_mem (addr, 1 << ir.ot))
57915796c8dcSSimon Schubert                 return -1;
57925796c8dcSSimon Schubert             }
57935796c8dcSSimon Schubert 
57945796c8dcSSimon Schubert           if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
5795*ef5ccd6cSJohn Marino             I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RECX_REGNUM);
57965796c8dcSSimon Schubert           if (opcode == 0xa4 || opcode == 0xa5)
5797*ef5ccd6cSJohn Marino             I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RESI_REGNUM);
5798*ef5ccd6cSJohn Marino           I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REDI_REGNUM);
5799*ef5ccd6cSJohn Marino           I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
58005796c8dcSSimon Schubert 	}
58015796c8dcSSimon Schubert       break;
58025796c8dcSSimon Schubert 
5803cf7f2e2dSJohn Marino     case 0xa6:    /* cmpsS */
58045796c8dcSSimon Schubert     case 0xa7:
5805*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REDI_REGNUM);
5806*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RESI_REGNUM);
58075796c8dcSSimon Schubert       if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
5808*ef5ccd6cSJohn Marino         I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RECX_REGNUM);
5809*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
58105796c8dcSSimon Schubert       break;
58115796c8dcSSimon Schubert 
5812cf7f2e2dSJohn Marino     case 0xac:    /* lodsS */
58135796c8dcSSimon Schubert     case 0xad:
5814*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM);
5815*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RESI_REGNUM);
58165796c8dcSSimon Schubert       if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
5817*ef5ccd6cSJohn Marino         I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RECX_REGNUM);
5818*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
58195796c8dcSSimon Schubert       break;
58205796c8dcSSimon Schubert 
5821cf7f2e2dSJohn Marino     case 0xae:    /* scasS */
58225796c8dcSSimon Schubert     case 0xaf:
5823*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REDI_REGNUM);
58245796c8dcSSimon Schubert       if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
5825*ef5ccd6cSJohn Marino         I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RECX_REGNUM);
5826*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
58275796c8dcSSimon Schubert       break;
58285796c8dcSSimon Schubert 
5829cf7f2e2dSJohn Marino     case 0x6e:    /* outsS */
58305796c8dcSSimon Schubert     case 0x6f:
5831*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RESI_REGNUM);
58325796c8dcSSimon Schubert       if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
5833*ef5ccd6cSJohn Marino         I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RECX_REGNUM);
5834*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
58355796c8dcSSimon Schubert       break;
58365796c8dcSSimon Schubert 
5837cf7f2e2dSJohn Marino     case 0xe4:    /* port I/O */
58385796c8dcSSimon Schubert     case 0xe5:
58395796c8dcSSimon Schubert     case 0xec:
58405796c8dcSSimon Schubert     case 0xed:
5841*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
5842*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM);
58435796c8dcSSimon Schubert       break;
58445796c8dcSSimon Schubert 
58455796c8dcSSimon Schubert     case 0xe6:
58465796c8dcSSimon Schubert     case 0xe7:
58475796c8dcSSimon Schubert     case 0xee:
58485796c8dcSSimon Schubert     case 0xef:
58495796c8dcSSimon Schubert       break;
58505796c8dcSSimon Schubert 
58515796c8dcSSimon Schubert       /* control */
5852cf7f2e2dSJohn Marino     case 0xc2:    /* ret im */
5853cf7f2e2dSJohn Marino     case 0xc3:    /* ret */
5854*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM);
5855*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
58565796c8dcSSimon Schubert       break;
58575796c8dcSSimon Schubert 
5858cf7f2e2dSJohn Marino     case 0xca:    /* lret im */
5859cf7f2e2dSJohn Marino     case 0xcb:    /* lret */
5860cf7f2e2dSJohn Marino     case 0xcf:    /* iret */
5861*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_CS_REGNUM);
5862*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM);
5863*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
58645796c8dcSSimon Schubert       break;
58655796c8dcSSimon Schubert 
5866cf7f2e2dSJohn Marino     case 0xe8:    /* call im */
58675796c8dcSSimon Schubert       if (ir.regmap[X86_RECORD_R8_REGNUM] && ir.dflag)
58685796c8dcSSimon Schubert         ir.dflag = 2;
58695796c8dcSSimon Schubert       if (i386_record_push (&ir, 1 << (ir.dflag + 1)))
58705796c8dcSSimon Schubert         return -1;
58715796c8dcSSimon Schubert       break;
58725796c8dcSSimon Schubert 
5873cf7f2e2dSJohn Marino     case 0x9a:    /* lcall im */
58745796c8dcSSimon Schubert       if (ir.regmap[X86_RECORD_R8_REGNUM])
58755796c8dcSSimon Schubert         {
58765796c8dcSSimon Schubert           ir.addr -= 1;
58775796c8dcSSimon Schubert           goto no_support;
58785796c8dcSSimon Schubert         }
5879*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_CS_REGNUM);
58805796c8dcSSimon Schubert       if (i386_record_push (&ir, 1 << (ir.dflag + 1)))
58815796c8dcSSimon Schubert         return -1;
58825796c8dcSSimon Schubert       break;
58835796c8dcSSimon Schubert 
5884cf7f2e2dSJohn Marino     case 0xe9:    /* jmp im */
5885cf7f2e2dSJohn Marino     case 0xea:    /* ljmp im */
5886cf7f2e2dSJohn Marino     case 0xeb:    /* jmp Jb */
5887cf7f2e2dSJohn Marino     case 0x70:    /* jcc Jb */
58885796c8dcSSimon Schubert     case 0x71:
58895796c8dcSSimon Schubert     case 0x72:
58905796c8dcSSimon Schubert     case 0x73:
58915796c8dcSSimon Schubert     case 0x74:
58925796c8dcSSimon Schubert     case 0x75:
58935796c8dcSSimon Schubert     case 0x76:
58945796c8dcSSimon Schubert     case 0x77:
58955796c8dcSSimon Schubert     case 0x78:
58965796c8dcSSimon Schubert     case 0x79:
58975796c8dcSSimon Schubert     case 0x7a:
58985796c8dcSSimon Schubert     case 0x7b:
58995796c8dcSSimon Schubert     case 0x7c:
59005796c8dcSSimon Schubert     case 0x7d:
59015796c8dcSSimon Schubert     case 0x7e:
59025796c8dcSSimon Schubert     case 0x7f:
5903cf7f2e2dSJohn Marino     case 0x0f80:  /* jcc Jv */
59045796c8dcSSimon Schubert     case 0x0f81:
59055796c8dcSSimon Schubert     case 0x0f82:
59065796c8dcSSimon Schubert     case 0x0f83:
59075796c8dcSSimon Schubert     case 0x0f84:
59085796c8dcSSimon Schubert     case 0x0f85:
59095796c8dcSSimon Schubert     case 0x0f86:
59105796c8dcSSimon Schubert     case 0x0f87:
59115796c8dcSSimon Schubert     case 0x0f88:
59125796c8dcSSimon Schubert     case 0x0f89:
59135796c8dcSSimon Schubert     case 0x0f8a:
59145796c8dcSSimon Schubert     case 0x0f8b:
59155796c8dcSSimon Schubert     case 0x0f8c:
59165796c8dcSSimon Schubert     case 0x0f8d:
59175796c8dcSSimon Schubert     case 0x0f8e:
59185796c8dcSSimon Schubert     case 0x0f8f:
59195796c8dcSSimon Schubert       break;
59205796c8dcSSimon Schubert 
5921cf7f2e2dSJohn Marino     case 0x0f90:  /* setcc Gv */
59225796c8dcSSimon Schubert     case 0x0f91:
59235796c8dcSSimon Schubert     case 0x0f92:
59245796c8dcSSimon Schubert     case 0x0f93:
59255796c8dcSSimon Schubert     case 0x0f94:
59265796c8dcSSimon Schubert     case 0x0f95:
59275796c8dcSSimon Schubert     case 0x0f96:
59285796c8dcSSimon Schubert     case 0x0f97:
59295796c8dcSSimon Schubert     case 0x0f98:
59305796c8dcSSimon Schubert     case 0x0f99:
59315796c8dcSSimon Schubert     case 0x0f9a:
59325796c8dcSSimon Schubert     case 0x0f9b:
59335796c8dcSSimon Schubert     case 0x0f9c:
59345796c8dcSSimon Schubert     case 0x0f9d:
59355796c8dcSSimon Schubert     case 0x0f9e:
59365796c8dcSSimon Schubert     case 0x0f9f:
5937*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
59385796c8dcSSimon Schubert       ir.ot = OT_BYTE;
59395796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
59405796c8dcSSimon Schubert 	return -1;
59415796c8dcSSimon Schubert       if (ir.mod == 3)
5942*ef5ccd6cSJohn Marino         I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.rex_b ? (ir.rm | ir.rex_b)
59435796c8dcSSimon Schubert 					    : (ir.rm & 0x3));
59445796c8dcSSimon Schubert       else
59455796c8dcSSimon Schubert 	{
59465796c8dcSSimon Schubert 	  if (i386_record_lea_modrm (&ir))
59475796c8dcSSimon Schubert 	    return -1;
59485796c8dcSSimon Schubert 	}
59495796c8dcSSimon Schubert       break;
59505796c8dcSSimon Schubert 
5951cf7f2e2dSJohn Marino     case 0x0f40:    /* cmov Gv, Ev */
59525796c8dcSSimon Schubert     case 0x0f41:
59535796c8dcSSimon Schubert     case 0x0f42:
59545796c8dcSSimon Schubert     case 0x0f43:
59555796c8dcSSimon Schubert     case 0x0f44:
59565796c8dcSSimon Schubert     case 0x0f45:
59575796c8dcSSimon Schubert     case 0x0f46:
59585796c8dcSSimon Schubert     case 0x0f47:
59595796c8dcSSimon Schubert     case 0x0f48:
59605796c8dcSSimon Schubert     case 0x0f49:
59615796c8dcSSimon Schubert     case 0x0f4a:
59625796c8dcSSimon Schubert     case 0x0f4b:
59635796c8dcSSimon Schubert     case 0x0f4c:
59645796c8dcSSimon Schubert     case 0x0f4d:
59655796c8dcSSimon Schubert     case 0x0f4e:
59665796c8dcSSimon Schubert     case 0x0f4f:
59675796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
59685796c8dcSSimon Schubert 	return -1;
59695796c8dcSSimon Schubert       ir.reg |= rex_r;
59705796c8dcSSimon Schubert       if (ir.dflag == OT_BYTE)
59715796c8dcSSimon Schubert 	ir.reg &= 0x3;
5972*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.reg);
59735796c8dcSSimon Schubert       break;
59745796c8dcSSimon Schubert 
59755796c8dcSSimon Schubert       /* flags */
5976cf7f2e2dSJohn Marino     case 0x9c:    /* pushf */
5977*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
59785796c8dcSSimon Schubert       if (ir.regmap[X86_RECORD_R8_REGNUM] && ir.dflag)
59795796c8dcSSimon Schubert         ir.dflag = 2;
59805796c8dcSSimon Schubert       if (i386_record_push (&ir, 1 << (ir.dflag + 1)))
59815796c8dcSSimon Schubert         return -1;
59825796c8dcSSimon Schubert       break;
59835796c8dcSSimon Schubert 
5984cf7f2e2dSJohn Marino     case 0x9d:    /* popf */
5985*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM);
5986*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
59875796c8dcSSimon Schubert       break;
59885796c8dcSSimon Schubert 
5989cf7f2e2dSJohn Marino     case 0x9e:    /* sahf */
59905796c8dcSSimon Schubert       if (ir.regmap[X86_RECORD_R8_REGNUM])
59915796c8dcSSimon Schubert         {
59925796c8dcSSimon Schubert           ir.addr -= 1;
59935796c8dcSSimon Schubert           goto no_support;
59945796c8dcSSimon Schubert         }
5995c50c785cSJohn Marino       /* FALLTHROUGH */
5996cf7f2e2dSJohn Marino     case 0xf5:    /* cmc */
5997cf7f2e2dSJohn Marino     case 0xf8:    /* clc */
5998cf7f2e2dSJohn Marino     case 0xf9:    /* stc */
5999cf7f2e2dSJohn Marino     case 0xfc:    /* cld */
6000cf7f2e2dSJohn Marino     case 0xfd:    /* std */
6001*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
60025796c8dcSSimon Schubert       break;
60035796c8dcSSimon Schubert 
6004cf7f2e2dSJohn Marino     case 0x9f:    /* lahf */
60055796c8dcSSimon Schubert       if (ir.regmap[X86_RECORD_R8_REGNUM])
60065796c8dcSSimon Schubert         {
60075796c8dcSSimon Schubert           ir.addr -= 1;
60085796c8dcSSimon Schubert           goto no_support;
60095796c8dcSSimon Schubert         }
6010*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
6011*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM);
60125796c8dcSSimon Schubert       break;
60135796c8dcSSimon Schubert 
60145796c8dcSSimon Schubert       /* bit operations */
6015cf7f2e2dSJohn Marino     case 0x0fba:    /* bt/bts/btr/btc Gv, im */
60165796c8dcSSimon Schubert       ir.ot = ir.dflag + OT_WORD;
60175796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
60185796c8dcSSimon Schubert 	return -1;
60195796c8dcSSimon Schubert       if (ir.reg < 4)
60205796c8dcSSimon Schubert 	{
60215796c8dcSSimon Schubert 	  ir.addr -= 2;
60225796c8dcSSimon Schubert 	  opcode = opcode << 8 | ir.modrm;
60235796c8dcSSimon Schubert 	  goto no_support;
60245796c8dcSSimon Schubert 	}
60255796c8dcSSimon Schubert       if (ir.reg != 4)
60265796c8dcSSimon Schubert 	{
60275796c8dcSSimon Schubert           if (ir.mod == 3)
6028*ef5ccd6cSJohn Marino             I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.rm | ir.rex_b);
60295796c8dcSSimon Schubert 	  else
60305796c8dcSSimon Schubert 	    {
60315796c8dcSSimon Schubert 	      if (i386_record_lea_modrm (&ir))
60325796c8dcSSimon Schubert 		return -1;
60335796c8dcSSimon Schubert 	    }
60345796c8dcSSimon Schubert 	}
6035*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
60365796c8dcSSimon Schubert       break;
60375796c8dcSSimon Schubert 
6038cf7f2e2dSJohn Marino     case 0x0fa3:    /* bt Gv, Ev */
6039*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
60405796c8dcSSimon Schubert       break;
60415796c8dcSSimon Schubert 
6042cf7f2e2dSJohn Marino     case 0x0fab:    /* bts */
6043cf7f2e2dSJohn Marino     case 0x0fb3:    /* btr */
6044cf7f2e2dSJohn Marino     case 0x0fbb:    /* btc */
60455796c8dcSSimon Schubert       ir.ot = ir.dflag + OT_WORD;
60465796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
60475796c8dcSSimon Schubert         return -1;
60485796c8dcSSimon Schubert       if (ir.mod == 3)
6049*ef5ccd6cSJohn Marino         I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.rm | ir.rex_b);
60505796c8dcSSimon Schubert       else
60515796c8dcSSimon Schubert         {
6052cf7f2e2dSJohn Marino           uint64_t addr64;
6053cf7f2e2dSJohn Marino           if (i386_record_lea_modrm_addr (&ir, &addr64))
60545796c8dcSSimon Schubert             return -1;
60555796c8dcSSimon Schubert           regcache_raw_read_unsigned (ir.regcache,
60565796c8dcSSimon Schubert                                       ir.regmap[ir.reg | rex_r],
6057cf7f2e2dSJohn Marino                                       &addr);
60585796c8dcSSimon Schubert           switch (ir.dflag)
60595796c8dcSSimon Schubert             {
60605796c8dcSSimon Schubert             case 0:
6061cf7f2e2dSJohn Marino               addr64 += ((int16_t) addr >> 4) << 4;
60625796c8dcSSimon Schubert               break;
60635796c8dcSSimon Schubert             case 1:
6064cf7f2e2dSJohn Marino               addr64 += ((int32_t) addr >> 5) << 5;
60655796c8dcSSimon Schubert               break;
60665796c8dcSSimon Schubert             case 2:
6067cf7f2e2dSJohn Marino               addr64 += ((int64_t) addr >> 6) << 6;
60685796c8dcSSimon Schubert               break;
60695796c8dcSSimon Schubert             }
6070*ef5ccd6cSJohn Marino           if (record_full_arch_list_add_mem (addr64, 1 << ir.ot))
60715796c8dcSSimon Schubert             return -1;
60725796c8dcSSimon Schubert           if (i386_record_lea_modrm (&ir))
60735796c8dcSSimon Schubert             return -1;
60745796c8dcSSimon Schubert         }
6075*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
60765796c8dcSSimon Schubert       break;
60775796c8dcSSimon Schubert 
6078cf7f2e2dSJohn Marino     case 0x0fbc:    /* bsf */
6079cf7f2e2dSJohn Marino     case 0x0fbd:    /* bsr */
6080*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.reg | rex_r);
6081*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
60825796c8dcSSimon Schubert       break;
60835796c8dcSSimon Schubert 
60845796c8dcSSimon Schubert       /* bcd */
6085cf7f2e2dSJohn Marino     case 0x27:    /* daa */
6086cf7f2e2dSJohn Marino     case 0x2f:    /* das */
6087cf7f2e2dSJohn Marino     case 0x37:    /* aaa */
6088cf7f2e2dSJohn Marino     case 0x3f:    /* aas */
6089cf7f2e2dSJohn Marino     case 0xd4:    /* aam */
6090cf7f2e2dSJohn Marino     case 0xd5:    /* aad */
60915796c8dcSSimon Schubert       if (ir.regmap[X86_RECORD_R8_REGNUM])
60925796c8dcSSimon Schubert         {
60935796c8dcSSimon Schubert           ir.addr -= 1;
60945796c8dcSSimon Schubert           goto no_support;
60955796c8dcSSimon Schubert         }
6096*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM);
6097*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
60985796c8dcSSimon Schubert       break;
60995796c8dcSSimon Schubert 
61005796c8dcSSimon Schubert       /* misc */
6101cf7f2e2dSJohn Marino     case 0x90:    /* nop */
61025796c8dcSSimon Schubert       if (prefixes & PREFIX_LOCK)
61035796c8dcSSimon Schubert 	{
61045796c8dcSSimon Schubert 	  ir.addr -= 1;
61055796c8dcSSimon Schubert 	  goto no_support;
61065796c8dcSSimon Schubert 	}
61075796c8dcSSimon Schubert       break;
61085796c8dcSSimon Schubert 
6109cf7f2e2dSJohn Marino     case 0x9b:    /* fwait */
6110*ef5ccd6cSJohn Marino       if (record_read_memory (gdbarch, ir.addr, &opcode8, 1))
6111cf7f2e2dSJohn Marino 	return -1;
6112cf7f2e2dSJohn Marino       opcode = (uint32_t) opcode8;
6113cf7f2e2dSJohn Marino       ir.addr++;
6114cf7f2e2dSJohn Marino       goto reswitch;
61155796c8dcSSimon Schubert       break;
61165796c8dcSSimon Schubert 
61175796c8dcSSimon Schubert       /* XXX */
6118cf7f2e2dSJohn Marino     case 0xcc:    /* int3 */
6119cf7f2e2dSJohn Marino       printf_unfiltered (_("Process record does not support instruction "
61205796c8dcSSimon Schubert 			   "int3.\n"));
61215796c8dcSSimon Schubert       ir.addr -= 1;
61225796c8dcSSimon Schubert       goto no_support;
61235796c8dcSSimon Schubert       break;
61245796c8dcSSimon Schubert 
61255796c8dcSSimon Schubert       /* XXX */
6126cf7f2e2dSJohn Marino     case 0xcd:    /* int */
61275796c8dcSSimon Schubert       {
61285796c8dcSSimon Schubert 	int ret;
6129cf7f2e2dSJohn Marino 	uint8_t interrupt;
6130*ef5ccd6cSJohn Marino 	if (record_read_memory (gdbarch, ir.addr, &interrupt, 1))
61315796c8dcSSimon Schubert 	  return -1;
61325796c8dcSSimon Schubert 	ir.addr++;
6133cf7f2e2dSJohn Marino 	if (interrupt != 0x80
6134cf7f2e2dSJohn Marino 	    || tdep->i386_intx80_record == NULL)
61355796c8dcSSimon Schubert 	  {
6136cf7f2e2dSJohn Marino 	    printf_unfiltered (_("Process record does not support "
61375796c8dcSSimon Schubert 				 "instruction int 0x%02x.\n"),
6138cf7f2e2dSJohn Marino 			       interrupt);
61395796c8dcSSimon Schubert 	    ir.addr -= 2;
61405796c8dcSSimon Schubert 	    goto no_support;
61415796c8dcSSimon Schubert 	  }
6142cf7f2e2dSJohn Marino 	ret = tdep->i386_intx80_record (ir.regcache);
61435796c8dcSSimon Schubert 	if (ret)
61445796c8dcSSimon Schubert 	  return ret;
61455796c8dcSSimon Schubert       }
61465796c8dcSSimon Schubert       break;
61475796c8dcSSimon Schubert 
61485796c8dcSSimon Schubert       /* XXX */
6149cf7f2e2dSJohn Marino     case 0xce:    /* into */
6150cf7f2e2dSJohn Marino       printf_unfiltered (_("Process record does not support "
61515796c8dcSSimon Schubert 			   "instruction into.\n"));
61525796c8dcSSimon Schubert       ir.addr -= 1;
61535796c8dcSSimon Schubert       goto no_support;
61545796c8dcSSimon Schubert       break;
61555796c8dcSSimon Schubert 
6156cf7f2e2dSJohn Marino     case 0xfa:    /* cli */
6157cf7f2e2dSJohn Marino     case 0xfb:    /* sti */
61585796c8dcSSimon Schubert       break;
61595796c8dcSSimon Schubert 
6160cf7f2e2dSJohn Marino     case 0x62:    /* bound */
6161cf7f2e2dSJohn Marino       printf_unfiltered (_("Process record does not support "
61625796c8dcSSimon Schubert 			   "instruction bound.\n"));
61635796c8dcSSimon Schubert       ir.addr -= 1;
61645796c8dcSSimon Schubert       goto no_support;
61655796c8dcSSimon Schubert       break;
61665796c8dcSSimon Schubert 
6167cf7f2e2dSJohn Marino     case 0x0fc8:    /* bswap reg */
61685796c8dcSSimon Schubert     case 0x0fc9:
61695796c8dcSSimon Schubert     case 0x0fca:
61705796c8dcSSimon Schubert     case 0x0fcb:
61715796c8dcSSimon Schubert     case 0x0fcc:
61725796c8dcSSimon Schubert     case 0x0fcd:
61735796c8dcSSimon Schubert     case 0x0fce:
61745796c8dcSSimon Schubert     case 0x0fcf:
6175*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG ((opcode & 7) | ir.rex_b);
61765796c8dcSSimon Schubert       break;
61775796c8dcSSimon Schubert 
6178cf7f2e2dSJohn Marino     case 0xd6:    /* salc */
61795796c8dcSSimon Schubert       if (ir.regmap[X86_RECORD_R8_REGNUM])
61805796c8dcSSimon Schubert         {
61815796c8dcSSimon Schubert           ir.addr -= 1;
61825796c8dcSSimon Schubert           goto no_support;
61835796c8dcSSimon Schubert         }
6184*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM);
6185*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
61865796c8dcSSimon Schubert       break;
61875796c8dcSSimon Schubert 
6188cf7f2e2dSJohn Marino     case 0xe0:    /* loopnz */
6189cf7f2e2dSJohn Marino     case 0xe1:    /* loopz */
6190cf7f2e2dSJohn Marino     case 0xe2:    /* loop */
6191cf7f2e2dSJohn Marino     case 0xe3:    /* jecxz */
6192*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RECX_REGNUM);
6193*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
61945796c8dcSSimon Schubert       break;
61955796c8dcSSimon Schubert 
6196cf7f2e2dSJohn Marino     case 0x0f30:    /* wrmsr */
6197cf7f2e2dSJohn Marino       printf_unfiltered (_("Process record does not support "
61985796c8dcSSimon Schubert 			   "instruction wrmsr.\n"));
61995796c8dcSSimon Schubert       ir.addr -= 2;
62005796c8dcSSimon Schubert       goto no_support;
62015796c8dcSSimon Schubert       break;
62025796c8dcSSimon Schubert 
6203cf7f2e2dSJohn Marino     case 0x0f32:    /* rdmsr */
6204cf7f2e2dSJohn Marino       printf_unfiltered (_("Process record does not support "
62055796c8dcSSimon Schubert 			   "instruction rdmsr.\n"));
62065796c8dcSSimon Schubert       ir.addr -= 2;
62075796c8dcSSimon Schubert       goto no_support;
62085796c8dcSSimon Schubert       break;
62095796c8dcSSimon Schubert 
6210cf7f2e2dSJohn Marino     case 0x0f31:    /* rdtsc */
6211*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM);
6212*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REDX_REGNUM);
62135796c8dcSSimon Schubert       break;
62145796c8dcSSimon Schubert 
6215cf7f2e2dSJohn Marino     case 0x0f34:    /* sysenter */
62165796c8dcSSimon Schubert       {
62175796c8dcSSimon Schubert 	int ret;
62185796c8dcSSimon Schubert         if (ir.regmap[X86_RECORD_R8_REGNUM])
62195796c8dcSSimon Schubert           {
62205796c8dcSSimon Schubert             ir.addr -= 2;
62215796c8dcSSimon Schubert             goto no_support;
62225796c8dcSSimon Schubert           }
6223cf7f2e2dSJohn Marino 	if (tdep->i386_sysenter_record == NULL)
62245796c8dcSSimon Schubert 	  {
6225cf7f2e2dSJohn Marino 	    printf_unfiltered (_("Process record does not support "
62265796c8dcSSimon Schubert 				 "instruction sysenter.\n"));
62275796c8dcSSimon Schubert 	    ir.addr -= 2;
62285796c8dcSSimon Schubert 	    goto no_support;
62295796c8dcSSimon Schubert 	  }
6230cf7f2e2dSJohn Marino 	ret = tdep->i386_sysenter_record (ir.regcache);
62315796c8dcSSimon Schubert 	if (ret)
62325796c8dcSSimon Schubert 	  return ret;
62335796c8dcSSimon Schubert       }
62345796c8dcSSimon Schubert       break;
62355796c8dcSSimon Schubert 
6236cf7f2e2dSJohn Marino     case 0x0f35:    /* sysexit */
6237cf7f2e2dSJohn Marino       printf_unfiltered (_("Process record does not support "
62385796c8dcSSimon Schubert 			   "instruction sysexit.\n"));
62395796c8dcSSimon Schubert       ir.addr -= 2;
62405796c8dcSSimon Schubert       goto no_support;
62415796c8dcSSimon Schubert       break;
62425796c8dcSSimon Schubert 
6243cf7f2e2dSJohn Marino     case 0x0f05:    /* syscall */
62445796c8dcSSimon Schubert       {
62455796c8dcSSimon Schubert 	int ret;
6246cf7f2e2dSJohn Marino 	if (tdep->i386_syscall_record == NULL)
62475796c8dcSSimon Schubert 	  {
6248cf7f2e2dSJohn Marino 	    printf_unfiltered (_("Process record does not support "
62495796c8dcSSimon Schubert 				 "instruction syscall.\n"));
62505796c8dcSSimon Schubert 	    ir.addr -= 2;
62515796c8dcSSimon Schubert 	    goto no_support;
62525796c8dcSSimon Schubert 	  }
6253cf7f2e2dSJohn Marino 	ret = tdep->i386_syscall_record (ir.regcache);
62545796c8dcSSimon Schubert 	if (ret)
62555796c8dcSSimon Schubert 	  return ret;
62565796c8dcSSimon Schubert       }
62575796c8dcSSimon Schubert       break;
62585796c8dcSSimon Schubert 
6259cf7f2e2dSJohn Marino     case 0x0f07:    /* sysret */
6260cf7f2e2dSJohn Marino       printf_unfiltered (_("Process record does not support "
62615796c8dcSSimon Schubert                            "instruction sysret.\n"));
62625796c8dcSSimon Schubert       ir.addr -= 2;
62635796c8dcSSimon Schubert       goto no_support;
62645796c8dcSSimon Schubert       break;
62655796c8dcSSimon Schubert 
6266cf7f2e2dSJohn Marino     case 0x0fa2:    /* cpuid */
6267*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM);
6268*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RECX_REGNUM);
6269*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REDX_REGNUM);
6270*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REBX_REGNUM);
62715796c8dcSSimon Schubert       break;
62725796c8dcSSimon Schubert 
6273cf7f2e2dSJohn Marino     case 0xf4:    /* hlt */
6274cf7f2e2dSJohn Marino       printf_unfiltered (_("Process record does not support "
62755796c8dcSSimon Schubert 			   "instruction hlt.\n"));
62765796c8dcSSimon Schubert       ir.addr -= 1;
62775796c8dcSSimon Schubert       goto no_support;
62785796c8dcSSimon Schubert       break;
62795796c8dcSSimon Schubert 
62805796c8dcSSimon Schubert     case 0x0f00:
62815796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
62825796c8dcSSimon Schubert 	return -1;
62835796c8dcSSimon Schubert       switch (ir.reg)
62845796c8dcSSimon Schubert 	{
6285cf7f2e2dSJohn Marino 	case 0:  /* sldt */
6286cf7f2e2dSJohn Marino 	case 1:  /* str  */
62875796c8dcSSimon Schubert 	  if (ir.mod == 3)
6288*ef5ccd6cSJohn Marino             I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.rm | ir.rex_b);
62895796c8dcSSimon Schubert 	  else
62905796c8dcSSimon Schubert 	    {
62915796c8dcSSimon Schubert 	      ir.ot = OT_WORD;
62925796c8dcSSimon Schubert 	      if (i386_record_lea_modrm (&ir))
62935796c8dcSSimon Schubert 		return -1;
62945796c8dcSSimon Schubert 	    }
62955796c8dcSSimon Schubert 	  break;
6296cf7f2e2dSJohn Marino 	case 2:  /* lldt */
6297cf7f2e2dSJohn Marino 	case 3:  /* ltr */
62985796c8dcSSimon Schubert 	  break;
6299cf7f2e2dSJohn Marino 	case 4:  /* verr */
6300cf7f2e2dSJohn Marino 	case 5:  /* verw */
6301*ef5ccd6cSJohn Marino           I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
63025796c8dcSSimon Schubert 	  break;
63035796c8dcSSimon Schubert 	default:
63045796c8dcSSimon Schubert 	  ir.addr -= 3;
63055796c8dcSSimon Schubert 	  opcode = opcode << 8 | ir.modrm;
63065796c8dcSSimon Schubert 	  goto no_support;
63075796c8dcSSimon Schubert 	  break;
63085796c8dcSSimon Schubert 	}
63095796c8dcSSimon Schubert       break;
63105796c8dcSSimon Schubert 
63115796c8dcSSimon Schubert     case 0x0f01:
63125796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
63135796c8dcSSimon Schubert 	return -1;
63145796c8dcSSimon Schubert       switch (ir.reg)
63155796c8dcSSimon Schubert 	{
6316cf7f2e2dSJohn Marino 	case 0:  /* sgdt */
63175796c8dcSSimon Schubert 	  {
6318cf7f2e2dSJohn Marino 	    uint64_t addr64;
63195796c8dcSSimon Schubert 
63205796c8dcSSimon Schubert 	    if (ir.mod == 3)
63215796c8dcSSimon Schubert 	      {
63225796c8dcSSimon Schubert 		ir.addr -= 3;
63235796c8dcSSimon Schubert 		opcode = opcode << 8 | ir.modrm;
63245796c8dcSSimon Schubert 		goto no_support;
63255796c8dcSSimon Schubert 	      }
63265796c8dcSSimon Schubert 	    if (ir.override >= 0)
63275796c8dcSSimon Schubert 	      {
6328*ef5ccd6cSJohn Marino                 if (record_full_memory_query)
6329cf7f2e2dSJohn Marino                   {
6330cf7f2e2dSJohn Marino 	            int q;
6331cf7f2e2dSJohn Marino 
6332cf7f2e2dSJohn Marino                     target_terminal_ours ();
6333cf7f2e2dSJohn Marino                     q = yquery (_("\
6334cf7f2e2dSJohn Marino Process record ignores the memory change of instruction at address %s\n\
6335cf7f2e2dSJohn Marino because it can't get the value of the segment register.\n\
6336cf7f2e2dSJohn Marino Do you want to stop the program?"),
63375796c8dcSSimon Schubert                                 paddress (gdbarch, ir.orig_addr));
6338cf7f2e2dSJohn Marino                     target_terminal_inferior ();
6339cf7f2e2dSJohn Marino                     if (q)
6340cf7f2e2dSJohn Marino                       return -1;
6341cf7f2e2dSJohn Marino                   }
63425796c8dcSSimon Schubert 	      }
63435796c8dcSSimon Schubert 	    else
63445796c8dcSSimon Schubert 	      {
6345cf7f2e2dSJohn Marino 		if (i386_record_lea_modrm_addr (&ir, &addr64))
63465796c8dcSSimon Schubert 		  return -1;
6347*ef5ccd6cSJohn Marino 		if (record_full_arch_list_add_mem (addr64, 2))
63485796c8dcSSimon Schubert 		  return -1;
6349cf7f2e2dSJohn Marino 		addr64 += 2;
63505796c8dcSSimon Schubert                 if (ir.regmap[X86_RECORD_R8_REGNUM])
63515796c8dcSSimon Schubert                   {
6352*ef5ccd6cSJohn Marino                     if (record_full_arch_list_add_mem (addr64, 8))
63535796c8dcSSimon Schubert 		      return -1;
63545796c8dcSSimon Schubert                   }
63555796c8dcSSimon Schubert                 else
63565796c8dcSSimon Schubert                   {
6357*ef5ccd6cSJohn Marino                     if (record_full_arch_list_add_mem (addr64, 4))
63585796c8dcSSimon Schubert 		      return -1;
63595796c8dcSSimon Schubert                   }
63605796c8dcSSimon Schubert 	      }
63615796c8dcSSimon Schubert 	  }
63625796c8dcSSimon Schubert 	  break;
63635796c8dcSSimon Schubert 	case 1:
63645796c8dcSSimon Schubert 	  if (ir.mod == 3)
63655796c8dcSSimon Schubert 	    {
63665796c8dcSSimon Schubert 	      switch (ir.rm)
63675796c8dcSSimon Schubert 		{
6368cf7f2e2dSJohn Marino 		case 0:  /* monitor */
63695796c8dcSSimon Schubert 		  break;
6370cf7f2e2dSJohn Marino 		case 1:  /* mwait */
6371*ef5ccd6cSJohn Marino 		  I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
63725796c8dcSSimon Schubert 		  break;
63735796c8dcSSimon Schubert 		default:
63745796c8dcSSimon Schubert 		  ir.addr -= 3;
63755796c8dcSSimon Schubert 		  opcode = opcode << 8 | ir.modrm;
63765796c8dcSSimon Schubert 		  goto no_support;
63775796c8dcSSimon Schubert 		  break;
63785796c8dcSSimon Schubert 		}
63795796c8dcSSimon Schubert 	    }
63805796c8dcSSimon Schubert 	  else
63815796c8dcSSimon Schubert 	    {
63825796c8dcSSimon Schubert 	      /* sidt */
63835796c8dcSSimon Schubert 	      if (ir.override >= 0)
63845796c8dcSSimon Schubert 		{
6385*ef5ccd6cSJohn Marino                   if (record_full_memory_query)
6386cf7f2e2dSJohn Marino                     {
6387cf7f2e2dSJohn Marino 	              int q;
6388cf7f2e2dSJohn Marino 
6389cf7f2e2dSJohn Marino                       target_terminal_ours ();
6390cf7f2e2dSJohn Marino                       q = yquery (_("\
6391cf7f2e2dSJohn Marino Process record ignores the memory change of instruction at address %s\n\
6392cf7f2e2dSJohn Marino because it can't get the value of the segment register.\n\
6393cf7f2e2dSJohn Marino Do you want to stop the program?"),
63945796c8dcSSimon Schubert                                   paddress (gdbarch, ir.orig_addr));
6395cf7f2e2dSJohn Marino                       target_terminal_inferior ();
6396cf7f2e2dSJohn Marino                       if (q)
6397cf7f2e2dSJohn Marino                         return -1;
6398cf7f2e2dSJohn Marino                     }
63995796c8dcSSimon Schubert 		}
64005796c8dcSSimon Schubert 	      else
64015796c8dcSSimon Schubert 		{
6402cf7f2e2dSJohn Marino 		  uint64_t addr64;
64035796c8dcSSimon Schubert 
6404cf7f2e2dSJohn Marino 		  if (i386_record_lea_modrm_addr (&ir, &addr64))
64055796c8dcSSimon Schubert 		    return -1;
6406*ef5ccd6cSJohn Marino 		  if (record_full_arch_list_add_mem (addr64, 2))
64075796c8dcSSimon Schubert 		    return -1;
6408cf7f2e2dSJohn Marino 		  addr64 += 2;
64095796c8dcSSimon Schubert                   if (ir.regmap[X86_RECORD_R8_REGNUM])
64105796c8dcSSimon Schubert                     {
6411*ef5ccd6cSJohn Marino                       if (record_full_arch_list_add_mem (addr64, 8))
64125796c8dcSSimon Schubert 		        return -1;
64135796c8dcSSimon Schubert                     }
64145796c8dcSSimon Schubert                   else
64155796c8dcSSimon Schubert                     {
6416*ef5ccd6cSJohn Marino                       if (record_full_arch_list_add_mem (addr64, 4))
64175796c8dcSSimon Schubert 		        return -1;
64185796c8dcSSimon Schubert                     }
64195796c8dcSSimon Schubert 		}
64205796c8dcSSimon Schubert 	    }
64215796c8dcSSimon Schubert 	  break;
6422cf7f2e2dSJohn Marino 	case 2:  /* lgdt */
6423cf7f2e2dSJohn Marino 	  if (ir.mod == 3)
6424cf7f2e2dSJohn Marino 	    {
6425cf7f2e2dSJohn Marino 	      /* xgetbv */
6426cf7f2e2dSJohn Marino 	      if (ir.rm == 0)
6427cf7f2e2dSJohn Marino 		{
6428*ef5ccd6cSJohn Marino 		  I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM);
6429*ef5ccd6cSJohn Marino 		  I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REDX_REGNUM);
6430cf7f2e2dSJohn Marino 		  break;
6431cf7f2e2dSJohn Marino 		}
6432cf7f2e2dSJohn Marino 	      /* xsetbv */
6433cf7f2e2dSJohn Marino 	      else if (ir.rm == 1)
6434cf7f2e2dSJohn Marino 		break;
6435cf7f2e2dSJohn Marino 	    }
6436cf7f2e2dSJohn Marino 	case 3:  /* lidt */
64375796c8dcSSimon Schubert 	  if (ir.mod == 3)
64385796c8dcSSimon Schubert 	    {
64395796c8dcSSimon Schubert 	      ir.addr -= 3;
64405796c8dcSSimon Schubert 	      opcode = opcode << 8 | ir.modrm;
64415796c8dcSSimon Schubert 	      goto no_support;
64425796c8dcSSimon Schubert 	    }
64435796c8dcSSimon Schubert 	  break;
6444cf7f2e2dSJohn Marino 	case 4:  /* smsw */
64455796c8dcSSimon Schubert 	  if (ir.mod == 3)
64465796c8dcSSimon Schubert 	    {
6447*ef5ccd6cSJohn Marino 	      if (record_full_arch_list_add_reg (ir.regcache, ir.rm | ir.rex_b))
64485796c8dcSSimon Schubert 		return -1;
64495796c8dcSSimon Schubert 	    }
64505796c8dcSSimon Schubert 	  else
64515796c8dcSSimon Schubert 	    {
64525796c8dcSSimon Schubert 	      ir.ot = OT_WORD;
64535796c8dcSSimon Schubert 	      if (i386_record_lea_modrm (&ir))
64545796c8dcSSimon Schubert 		return -1;
64555796c8dcSSimon Schubert 	    }
6456*ef5ccd6cSJohn Marino 	  I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
64575796c8dcSSimon Schubert 	  break;
6458cf7f2e2dSJohn Marino 	case 6:  /* lmsw */
6459*ef5ccd6cSJohn Marino 	  I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
64605796c8dcSSimon Schubert 	  break;
6461cf7f2e2dSJohn Marino 	case 7:  /* invlpg */
64625796c8dcSSimon Schubert 	  if (ir.mod == 3)
64635796c8dcSSimon Schubert 	    {
64645796c8dcSSimon Schubert 	      if (ir.rm == 0 && ir.regmap[X86_RECORD_R8_REGNUM])
6465*ef5ccd6cSJohn Marino 	        I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_GS_REGNUM);
64665796c8dcSSimon Schubert 	      else
64675796c8dcSSimon Schubert 	        {
64685796c8dcSSimon Schubert 	          ir.addr -= 3;
64695796c8dcSSimon Schubert 	          opcode = opcode << 8 | ir.modrm;
64705796c8dcSSimon Schubert 	          goto no_support;
64715796c8dcSSimon Schubert 	        }
64725796c8dcSSimon Schubert 	    }
64735796c8dcSSimon Schubert 	  else
6474*ef5ccd6cSJohn Marino 	    I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
64755796c8dcSSimon Schubert 	  break;
64765796c8dcSSimon Schubert 	default:
64775796c8dcSSimon Schubert 	  ir.addr -= 3;
64785796c8dcSSimon Schubert 	  opcode = opcode << 8 | ir.modrm;
64795796c8dcSSimon Schubert 	  goto no_support;
64805796c8dcSSimon Schubert 	  break;
64815796c8dcSSimon Schubert 	}
64825796c8dcSSimon Schubert       break;
64835796c8dcSSimon Schubert 
6484cf7f2e2dSJohn Marino     case 0x0f08:    /* invd */
6485cf7f2e2dSJohn Marino     case 0x0f09:    /* wbinvd */
64865796c8dcSSimon Schubert       break;
64875796c8dcSSimon Schubert 
6488cf7f2e2dSJohn Marino     case 0x63:    /* arpl */
64895796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
64905796c8dcSSimon Schubert 	return -1;
64915796c8dcSSimon Schubert       if (ir.mod == 3 || ir.regmap[X86_RECORD_R8_REGNUM])
64925796c8dcSSimon Schubert         {
6493*ef5ccd6cSJohn Marino           I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.regmap[X86_RECORD_R8_REGNUM]
64945796c8dcSSimon Schubert 					      ? (ir.reg | rex_r) : ir.rm);
64955796c8dcSSimon Schubert         }
64965796c8dcSSimon Schubert       else
64975796c8dcSSimon Schubert         {
64985796c8dcSSimon Schubert           ir.ot = ir.dflag ? OT_LONG : OT_WORD;
64995796c8dcSSimon Schubert           if (i386_record_lea_modrm (&ir))
65005796c8dcSSimon Schubert             return -1;
65015796c8dcSSimon Schubert         }
65025796c8dcSSimon Schubert       if (!ir.regmap[X86_RECORD_R8_REGNUM])
6503*ef5ccd6cSJohn Marino         I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
65045796c8dcSSimon Schubert       break;
65055796c8dcSSimon Schubert 
6506cf7f2e2dSJohn Marino     case 0x0f02:    /* lar */
6507cf7f2e2dSJohn Marino     case 0x0f03:    /* lsl */
65085796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
65095796c8dcSSimon Schubert 	return -1;
6510*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.reg | rex_r);
6511*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
65125796c8dcSSimon Schubert       break;
65135796c8dcSSimon Schubert 
65145796c8dcSSimon Schubert     case 0x0f18:
65155796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
65165796c8dcSSimon Schubert 	return -1;
65175796c8dcSSimon Schubert       if (ir.mod == 3 && ir.reg == 3)
65185796c8dcSSimon Schubert         {
65195796c8dcSSimon Schubert 	  ir.addr -= 3;
65205796c8dcSSimon Schubert 	  opcode = opcode << 8 | ir.modrm;
65215796c8dcSSimon Schubert 	  goto no_support;
65225796c8dcSSimon Schubert 	}
65235796c8dcSSimon Schubert       break;
65245796c8dcSSimon Schubert 
65255796c8dcSSimon Schubert     case 0x0f19:
65265796c8dcSSimon Schubert     case 0x0f1a:
65275796c8dcSSimon Schubert     case 0x0f1b:
65285796c8dcSSimon Schubert     case 0x0f1c:
65295796c8dcSSimon Schubert     case 0x0f1d:
65305796c8dcSSimon Schubert     case 0x0f1e:
65315796c8dcSSimon Schubert     case 0x0f1f:
6532cf7f2e2dSJohn Marino       /* nop (multi byte) */
65335796c8dcSSimon Schubert       break;
65345796c8dcSSimon Schubert 
6535cf7f2e2dSJohn Marino     case 0x0f20:    /* mov reg, crN */
6536cf7f2e2dSJohn Marino     case 0x0f22:    /* mov crN, reg */
65375796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
65385796c8dcSSimon Schubert 	return -1;
65395796c8dcSSimon Schubert       if ((ir.modrm & 0xc0) != 0xc0)
65405796c8dcSSimon Schubert 	{
65415796c8dcSSimon Schubert 	  ir.addr -= 3;
65425796c8dcSSimon Schubert 	  opcode = opcode << 8 | ir.modrm;
65435796c8dcSSimon Schubert 	  goto no_support;
65445796c8dcSSimon Schubert 	}
65455796c8dcSSimon Schubert       switch (ir.reg)
65465796c8dcSSimon Schubert 	{
65475796c8dcSSimon Schubert 	case 0:
65485796c8dcSSimon Schubert 	case 2:
65495796c8dcSSimon Schubert 	case 3:
65505796c8dcSSimon Schubert 	case 4:
65515796c8dcSSimon Schubert 	case 8:
65525796c8dcSSimon Schubert 	  if (opcode & 2)
6553*ef5ccd6cSJohn Marino 	    I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
65545796c8dcSSimon Schubert 	  else
6555*ef5ccd6cSJohn Marino             I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.rm | ir.rex_b);
65565796c8dcSSimon Schubert 	  break;
65575796c8dcSSimon Schubert 	default:
65585796c8dcSSimon Schubert 	  ir.addr -= 3;
65595796c8dcSSimon Schubert 	  opcode = opcode << 8 | ir.modrm;
65605796c8dcSSimon Schubert 	  goto no_support;
65615796c8dcSSimon Schubert 	  break;
65625796c8dcSSimon Schubert 	}
65635796c8dcSSimon Schubert       break;
65645796c8dcSSimon Schubert 
6565cf7f2e2dSJohn Marino     case 0x0f21:    /* mov reg, drN */
6566cf7f2e2dSJohn Marino     case 0x0f23:    /* mov drN, reg */
65675796c8dcSSimon Schubert       if (i386_record_modrm (&ir))
65685796c8dcSSimon Schubert 	return -1;
65695796c8dcSSimon Schubert       if ((ir.modrm & 0xc0) != 0xc0 || ir.reg == 4
65705796c8dcSSimon Schubert 	  || ir.reg == 5 || ir.reg >= 8)
65715796c8dcSSimon Schubert 	{
65725796c8dcSSimon Schubert 	  ir.addr -= 3;
65735796c8dcSSimon Schubert 	  opcode = opcode << 8 | ir.modrm;
65745796c8dcSSimon Schubert 	  goto no_support;
65755796c8dcSSimon Schubert 	}
65765796c8dcSSimon Schubert       if (opcode & 2)
6577*ef5ccd6cSJohn Marino         I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
65785796c8dcSSimon Schubert       else
6579*ef5ccd6cSJohn Marino 	I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.rm | ir.rex_b);
65805796c8dcSSimon Schubert       break;
65815796c8dcSSimon Schubert 
6582cf7f2e2dSJohn Marino     case 0x0f06:    /* clts */
6583*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
65845796c8dcSSimon Schubert       break;
65855796c8dcSSimon Schubert 
6586cf7f2e2dSJohn Marino     /* MMX 3DNow! SSE SSE2 SSE3 SSSE3 SSE4 */
6587cf7f2e2dSJohn Marino 
6588cf7f2e2dSJohn Marino     case 0x0f0d:    /* 3DNow! prefetch */
6589cf7f2e2dSJohn Marino       break;
6590cf7f2e2dSJohn Marino 
6591cf7f2e2dSJohn Marino     case 0x0f0e:    /* 3DNow! femms */
6592cf7f2e2dSJohn Marino     case 0x0f77:    /* emms */
6593cf7f2e2dSJohn Marino       if (i386_fpc_regnum_p (gdbarch, I387_FTAG_REGNUM(tdep)))
6594cf7f2e2dSJohn Marino         goto no_support;
6595*ef5ccd6cSJohn Marino       record_full_arch_list_add_reg (ir.regcache, I387_FTAG_REGNUM(tdep));
6596cf7f2e2dSJohn Marino       break;
6597cf7f2e2dSJohn Marino 
6598cf7f2e2dSJohn Marino     case 0x0f0f:    /* 3DNow! data */
6599cf7f2e2dSJohn Marino       if (i386_record_modrm (&ir))
6600cf7f2e2dSJohn Marino 	return -1;
6601*ef5ccd6cSJohn Marino       if (record_read_memory (gdbarch, ir.addr, &opcode8, 1))
6602cf7f2e2dSJohn Marino 	return -1;
6603cf7f2e2dSJohn Marino       ir.addr++;
6604cf7f2e2dSJohn Marino       switch (opcode8)
6605cf7f2e2dSJohn Marino         {
6606cf7f2e2dSJohn Marino         case 0x0c:    /* 3DNow! pi2fw */
6607cf7f2e2dSJohn Marino         case 0x0d:    /* 3DNow! pi2fd */
6608cf7f2e2dSJohn Marino         case 0x1c:    /* 3DNow! pf2iw */
6609cf7f2e2dSJohn Marino         case 0x1d:    /* 3DNow! pf2id */
6610cf7f2e2dSJohn Marino         case 0x8a:    /* 3DNow! pfnacc */
6611cf7f2e2dSJohn Marino         case 0x8e:    /* 3DNow! pfpnacc */
6612cf7f2e2dSJohn Marino         case 0x90:    /* 3DNow! pfcmpge */
6613cf7f2e2dSJohn Marino         case 0x94:    /* 3DNow! pfmin */
6614cf7f2e2dSJohn Marino         case 0x96:    /* 3DNow! pfrcp */
6615cf7f2e2dSJohn Marino         case 0x97:    /* 3DNow! pfrsqrt */
6616cf7f2e2dSJohn Marino         case 0x9a:    /* 3DNow! pfsub */
6617cf7f2e2dSJohn Marino         case 0x9e:    /* 3DNow! pfadd */
6618cf7f2e2dSJohn Marino         case 0xa0:    /* 3DNow! pfcmpgt */
6619cf7f2e2dSJohn Marino         case 0xa4:    /* 3DNow! pfmax */
6620cf7f2e2dSJohn Marino         case 0xa6:    /* 3DNow! pfrcpit1 */
6621cf7f2e2dSJohn Marino         case 0xa7:    /* 3DNow! pfrsqit1 */
6622cf7f2e2dSJohn Marino         case 0xaa:    /* 3DNow! pfsubr */
6623cf7f2e2dSJohn Marino         case 0xae:    /* 3DNow! pfacc */
6624cf7f2e2dSJohn Marino         case 0xb0:    /* 3DNow! pfcmpeq */
6625cf7f2e2dSJohn Marino         case 0xb4:    /* 3DNow! pfmul */
6626cf7f2e2dSJohn Marino         case 0xb6:    /* 3DNow! pfrcpit2 */
6627cf7f2e2dSJohn Marino         case 0xb7:    /* 3DNow! pmulhrw */
6628cf7f2e2dSJohn Marino         case 0xbb:    /* 3DNow! pswapd */
6629cf7f2e2dSJohn Marino         case 0xbf:    /* 3DNow! pavgusb */
6630cf7f2e2dSJohn Marino           if (!i386_mmx_regnum_p (gdbarch, I387_MM0_REGNUM (tdep) + ir.reg))
6631cf7f2e2dSJohn Marino             goto no_support_3dnow_data;
6632*ef5ccd6cSJohn Marino           record_full_arch_list_add_reg (ir.regcache, ir.reg);
6633cf7f2e2dSJohn Marino           break;
66345796c8dcSSimon Schubert 
66355796c8dcSSimon Schubert         default:
6636cf7f2e2dSJohn Marino no_support_3dnow_data:
6637cf7f2e2dSJohn Marino           opcode = (opcode << 8) | opcode8;
6638cf7f2e2dSJohn Marino           goto no_support;
6639cf7f2e2dSJohn Marino           break;
6640cf7f2e2dSJohn Marino         }
6641cf7f2e2dSJohn Marino       break;
6642cf7f2e2dSJohn Marino 
6643cf7f2e2dSJohn Marino     case 0x0faa:    /* rsm */
6644*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
6645*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM);
6646*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RECX_REGNUM);
6647*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REDX_REGNUM);
6648*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REBX_REGNUM);
6649*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM);
6650*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REBP_REGNUM);
6651*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_RESI_REGNUM);
6652*ef5ccd6cSJohn Marino       I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REDI_REGNUM);
6653cf7f2e2dSJohn Marino       break;
6654cf7f2e2dSJohn Marino 
6655cf7f2e2dSJohn Marino     case 0x0fae:
6656cf7f2e2dSJohn Marino       if (i386_record_modrm (&ir))
6657cf7f2e2dSJohn Marino 	return -1;
6658cf7f2e2dSJohn Marino       switch(ir.reg)
6659cf7f2e2dSJohn Marino         {
6660cf7f2e2dSJohn Marino         case 0:    /* fxsave */
6661cf7f2e2dSJohn Marino           {
6662cf7f2e2dSJohn Marino             uint64_t tmpu64;
6663cf7f2e2dSJohn Marino 
6664*ef5ccd6cSJohn Marino             I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
6665cf7f2e2dSJohn Marino 	    if (i386_record_lea_modrm_addr (&ir, &tmpu64))
6666cf7f2e2dSJohn Marino 	      return -1;
6667*ef5ccd6cSJohn Marino             if (record_full_arch_list_add_mem (tmpu64, 512))
6668cf7f2e2dSJohn Marino               return -1;
6669cf7f2e2dSJohn Marino           }
6670cf7f2e2dSJohn Marino           break;
6671cf7f2e2dSJohn Marino 
6672cf7f2e2dSJohn Marino         case 1:    /* fxrstor */
6673cf7f2e2dSJohn Marino           {
6674cf7f2e2dSJohn Marino             int i;
6675cf7f2e2dSJohn Marino 
6676*ef5ccd6cSJohn Marino             I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
6677cf7f2e2dSJohn Marino 
6678cf7f2e2dSJohn Marino             for (i = I387_MM0_REGNUM (tdep);
6679cf7f2e2dSJohn Marino                  i386_mmx_regnum_p (gdbarch, i); i++)
6680*ef5ccd6cSJohn Marino               record_full_arch_list_add_reg (ir.regcache, i);
6681cf7f2e2dSJohn Marino 
6682cf7f2e2dSJohn Marino             for (i = I387_XMM0_REGNUM (tdep);
6683cf7f2e2dSJohn Marino                  i386_xmm_regnum_p (gdbarch, i); i++)
6684*ef5ccd6cSJohn Marino               record_full_arch_list_add_reg (ir.regcache, i);
6685cf7f2e2dSJohn Marino 
6686cf7f2e2dSJohn Marino             if (i386_mxcsr_regnum_p (gdbarch, I387_MXCSR_REGNUM(tdep)))
6687*ef5ccd6cSJohn Marino               record_full_arch_list_add_reg (ir.regcache,
6688*ef5ccd6cSJohn Marino 					     I387_MXCSR_REGNUM(tdep));
6689cf7f2e2dSJohn Marino 
6690cf7f2e2dSJohn Marino             for (i = I387_ST0_REGNUM (tdep);
6691cf7f2e2dSJohn Marino                  i386_fp_regnum_p (gdbarch, i); i++)
6692*ef5ccd6cSJohn Marino               record_full_arch_list_add_reg (ir.regcache, i);
6693cf7f2e2dSJohn Marino 
6694cf7f2e2dSJohn Marino             for (i = I387_FCTRL_REGNUM (tdep);
6695cf7f2e2dSJohn Marino                  i386_fpc_regnum_p (gdbarch, i); i++)
6696*ef5ccd6cSJohn Marino               record_full_arch_list_add_reg (ir.regcache, i);
6697cf7f2e2dSJohn Marino           }
6698cf7f2e2dSJohn Marino           break;
6699cf7f2e2dSJohn Marino 
6700cf7f2e2dSJohn Marino         case 2:    /* ldmxcsr */
6701cf7f2e2dSJohn Marino           if (!i386_mxcsr_regnum_p (gdbarch, I387_MXCSR_REGNUM(tdep)))
6702cf7f2e2dSJohn Marino             goto no_support;
6703*ef5ccd6cSJohn Marino           record_full_arch_list_add_reg (ir.regcache, I387_MXCSR_REGNUM(tdep));
6704cf7f2e2dSJohn Marino           break;
6705cf7f2e2dSJohn Marino 
6706cf7f2e2dSJohn Marino         case 3:    /* stmxcsr */
6707cf7f2e2dSJohn Marino           ir.ot = OT_LONG;
6708cf7f2e2dSJohn Marino           if (i386_record_lea_modrm (&ir))
6709cf7f2e2dSJohn Marino             return -1;
6710cf7f2e2dSJohn Marino           break;
6711cf7f2e2dSJohn Marino 
6712cf7f2e2dSJohn Marino         case 5:    /* lfence */
6713cf7f2e2dSJohn Marino         case 6:    /* mfence */
6714cf7f2e2dSJohn Marino         case 7:    /* sfence clflush */
6715cf7f2e2dSJohn Marino           break;
6716cf7f2e2dSJohn Marino 
6717cf7f2e2dSJohn Marino         default:
6718cf7f2e2dSJohn Marino           opcode = (opcode << 8) | ir.modrm;
6719cf7f2e2dSJohn Marino           goto no_support;
6720cf7f2e2dSJohn Marino           break;
6721cf7f2e2dSJohn Marino         }
6722cf7f2e2dSJohn Marino       break;
6723cf7f2e2dSJohn Marino 
6724cf7f2e2dSJohn Marino     case 0x0fc3:    /* movnti */
6725cf7f2e2dSJohn Marino       ir.ot = (ir.dflag == 2) ? OT_QUAD : OT_LONG;
6726cf7f2e2dSJohn Marino       if (i386_record_modrm (&ir))
6727cf7f2e2dSJohn Marino 	return -1;
6728cf7f2e2dSJohn Marino       if (ir.mod == 3)
6729cf7f2e2dSJohn Marino         goto no_support;
6730cf7f2e2dSJohn Marino       ir.reg |= rex_r;
6731cf7f2e2dSJohn Marino       if (i386_record_lea_modrm (&ir))
6732cf7f2e2dSJohn Marino         return -1;
6733cf7f2e2dSJohn Marino       break;
6734cf7f2e2dSJohn Marino 
6735cf7f2e2dSJohn Marino     /* Add prefix to opcode.  */
6736cf7f2e2dSJohn Marino     case 0x0f10:
6737cf7f2e2dSJohn Marino     case 0x0f11:
6738cf7f2e2dSJohn Marino     case 0x0f12:
6739cf7f2e2dSJohn Marino     case 0x0f13:
6740cf7f2e2dSJohn Marino     case 0x0f14:
6741cf7f2e2dSJohn Marino     case 0x0f15:
6742cf7f2e2dSJohn Marino     case 0x0f16:
6743cf7f2e2dSJohn Marino     case 0x0f17:
6744cf7f2e2dSJohn Marino     case 0x0f28:
6745cf7f2e2dSJohn Marino     case 0x0f29:
6746cf7f2e2dSJohn Marino     case 0x0f2a:
6747cf7f2e2dSJohn Marino     case 0x0f2b:
6748cf7f2e2dSJohn Marino     case 0x0f2c:
6749cf7f2e2dSJohn Marino     case 0x0f2d:
6750cf7f2e2dSJohn Marino     case 0x0f2e:
6751cf7f2e2dSJohn Marino     case 0x0f2f:
6752cf7f2e2dSJohn Marino     case 0x0f38:
6753cf7f2e2dSJohn Marino     case 0x0f39:
6754cf7f2e2dSJohn Marino     case 0x0f3a:
6755cf7f2e2dSJohn Marino     case 0x0f50:
6756cf7f2e2dSJohn Marino     case 0x0f51:
6757cf7f2e2dSJohn Marino     case 0x0f52:
6758cf7f2e2dSJohn Marino     case 0x0f53:
6759cf7f2e2dSJohn Marino     case 0x0f54:
6760cf7f2e2dSJohn Marino     case 0x0f55:
6761cf7f2e2dSJohn Marino     case 0x0f56:
6762cf7f2e2dSJohn Marino     case 0x0f57:
6763cf7f2e2dSJohn Marino     case 0x0f58:
6764cf7f2e2dSJohn Marino     case 0x0f59:
6765cf7f2e2dSJohn Marino     case 0x0f5a:
6766cf7f2e2dSJohn Marino     case 0x0f5b:
6767cf7f2e2dSJohn Marino     case 0x0f5c:
6768cf7f2e2dSJohn Marino     case 0x0f5d:
6769cf7f2e2dSJohn Marino     case 0x0f5e:
6770cf7f2e2dSJohn Marino     case 0x0f5f:
6771cf7f2e2dSJohn Marino     case 0x0f60:
6772cf7f2e2dSJohn Marino     case 0x0f61:
6773cf7f2e2dSJohn Marino     case 0x0f62:
6774cf7f2e2dSJohn Marino     case 0x0f63:
6775cf7f2e2dSJohn Marino     case 0x0f64:
6776cf7f2e2dSJohn Marino     case 0x0f65:
6777cf7f2e2dSJohn Marino     case 0x0f66:
6778cf7f2e2dSJohn Marino     case 0x0f67:
6779cf7f2e2dSJohn Marino     case 0x0f68:
6780cf7f2e2dSJohn Marino     case 0x0f69:
6781cf7f2e2dSJohn Marino     case 0x0f6a:
6782cf7f2e2dSJohn Marino     case 0x0f6b:
6783cf7f2e2dSJohn Marino     case 0x0f6c:
6784cf7f2e2dSJohn Marino     case 0x0f6d:
6785cf7f2e2dSJohn Marino     case 0x0f6e:
6786cf7f2e2dSJohn Marino     case 0x0f6f:
6787cf7f2e2dSJohn Marino     case 0x0f70:
6788cf7f2e2dSJohn Marino     case 0x0f71:
6789cf7f2e2dSJohn Marino     case 0x0f72:
6790cf7f2e2dSJohn Marino     case 0x0f73:
6791cf7f2e2dSJohn Marino     case 0x0f74:
6792cf7f2e2dSJohn Marino     case 0x0f75:
6793cf7f2e2dSJohn Marino     case 0x0f76:
6794cf7f2e2dSJohn Marino     case 0x0f7c:
6795cf7f2e2dSJohn Marino     case 0x0f7d:
6796cf7f2e2dSJohn Marino     case 0x0f7e:
6797cf7f2e2dSJohn Marino     case 0x0f7f:
6798cf7f2e2dSJohn Marino     case 0x0fb8:
6799cf7f2e2dSJohn Marino     case 0x0fc2:
6800cf7f2e2dSJohn Marino     case 0x0fc4:
6801cf7f2e2dSJohn Marino     case 0x0fc5:
6802cf7f2e2dSJohn Marino     case 0x0fc6:
6803cf7f2e2dSJohn Marino     case 0x0fd0:
6804cf7f2e2dSJohn Marino     case 0x0fd1:
6805cf7f2e2dSJohn Marino     case 0x0fd2:
6806cf7f2e2dSJohn Marino     case 0x0fd3:
6807cf7f2e2dSJohn Marino     case 0x0fd4:
6808cf7f2e2dSJohn Marino     case 0x0fd5:
6809cf7f2e2dSJohn Marino     case 0x0fd6:
6810cf7f2e2dSJohn Marino     case 0x0fd7:
6811cf7f2e2dSJohn Marino     case 0x0fd8:
6812cf7f2e2dSJohn Marino     case 0x0fd9:
6813cf7f2e2dSJohn Marino     case 0x0fda:
6814cf7f2e2dSJohn Marino     case 0x0fdb:
6815cf7f2e2dSJohn Marino     case 0x0fdc:
6816cf7f2e2dSJohn Marino     case 0x0fdd:
6817cf7f2e2dSJohn Marino     case 0x0fde:
6818cf7f2e2dSJohn Marino     case 0x0fdf:
6819cf7f2e2dSJohn Marino     case 0x0fe0:
6820cf7f2e2dSJohn Marino     case 0x0fe1:
6821cf7f2e2dSJohn Marino     case 0x0fe2:
6822cf7f2e2dSJohn Marino     case 0x0fe3:
6823cf7f2e2dSJohn Marino     case 0x0fe4:
6824cf7f2e2dSJohn Marino     case 0x0fe5:
6825cf7f2e2dSJohn Marino     case 0x0fe6:
6826cf7f2e2dSJohn Marino     case 0x0fe7:
6827cf7f2e2dSJohn Marino     case 0x0fe8:
6828cf7f2e2dSJohn Marino     case 0x0fe9:
6829cf7f2e2dSJohn Marino     case 0x0fea:
6830cf7f2e2dSJohn Marino     case 0x0feb:
6831cf7f2e2dSJohn Marino     case 0x0fec:
6832cf7f2e2dSJohn Marino     case 0x0fed:
6833cf7f2e2dSJohn Marino     case 0x0fee:
6834cf7f2e2dSJohn Marino     case 0x0fef:
6835cf7f2e2dSJohn Marino     case 0x0ff0:
6836cf7f2e2dSJohn Marino     case 0x0ff1:
6837cf7f2e2dSJohn Marino     case 0x0ff2:
6838cf7f2e2dSJohn Marino     case 0x0ff3:
6839cf7f2e2dSJohn Marino     case 0x0ff4:
6840cf7f2e2dSJohn Marino     case 0x0ff5:
6841cf7f2e2dSJohn Marino     case 0x0ff6:
6842cf7f2e2dSJohn Marino     case 0x0ff7:
6843cf7f2e2dSJohn Marino     case 0x0ff8:
6844cf7f2e2dSJohn Marino     case 0x0ff9:
6845cf7f2e2dSJohn Marino     case 0x0ffa:
6846cf7f2e2dSJohn Marino     case 0x0ffb:
6847cf7f2e2dSJohn Marino     case 0x0ffc:
6848cf7f2e2dSJohn Marino     case 0x0ffd:
6849cf7f2e2dSJohn Marino     case 0x0ffe:
6850cf7f2e2dSJohn Marino       switch (prefixes)
6851cf7f2e2dSJohn Marino         {
6852cf7f2e2dSJohn Marino         case PREFIX_REPNZ:
6853cf7f2e2dSJohn Marino           opcode |= 0xf20000;
6854cf7f2e2dSJohn Marino           break;
6855cf7f2e2dSJohn Marino         case PREFIX_DATA:
6856cf7f2e2dSJohn Marino           opcode |= 0x660000;
6857cf7f2e2dSJohn Marino           break;
6858cf7f2e2dSJohn Marino         case PREFIX_REPZ:
6859cf7f2e2dSJohn Marino           opcode |= 0xf30000;
6860cf7f2e2dSJohn Marino           break;
6861cf7f2e2dSJohn Marino         }
6862cf7f2e2dSJohn Marino reswitch_prefix_add:
6863cf7f2e2dSJohn Marino       switch (opcode)
6864cf7f2e2dSJohn Marino         {
6865cf7f2e2dSJohn Marino         case 0x0f38:
6866cf7f2e2dSJohn Marino         case 0x660f38:
6867cf7f2e2dSJohn Marino         case 0xf20f38:
6868cf7f2e2dSJohn Marino         case 0x0f3a:
6869cf7f2e2dSJohn Marino         case 0x660f3a:
6870*ef5ccd6cSJohn Marino           if (record_read_memory (gdbarch, ir.addr, &opcode8, 1))
6871cf7f2e2dSJohn Marino 	    return -1;
6872cf7f2e2dSJohn Marino           ir.addr++;
6873cf7f2e2dSJohn Marino           opcode = (uint32_t) opcode8 | opcode << 8;
6874cf7f2e2dSJohn Marino           goto reswitch_prefix_add;
6875cf7f2e2dSJohn Marino           break;
6876cf7f2e2dSJohn Marino 
6877cf7f2e2dSJohn Marino         case 0x0f10:        /* movups */
6878cf7f2e2dSJohn Marino         case 0x660f10:      /* movupd */
6879cf7f2e2dSJohn Marino         case 0xf30f10:      /* movss */
6880cf7f2e2dSJohn Marino         case 0xf20f10:      /* movsd */
6881cf7f2e2dSJohn Marino         case 0x0f12:        /* movlps */
6882cf7f2e2dSJohn Marino         case 0x660f12:      /* movlpd */
6883cf7f2e2dSJohn Marino         case 0xf30f12:      /* movsldup */
6884cf7f2e2dSJohn Marino         case 0xf20f12:      /* movddup */
6885cf7f2e2dSJohn Marino         case 0x0f14:        /* unpcklps */
6886cf7f2e2dSJohn Marino         case 0x660f14:      /* unpcklpd */
6887cf7f2e2dSJohn Marino         case 0x0f15:        /* unpckhps */
6888cf7f2e2dSJohn Marino         case 0x660f15:      /* unpckhpd */
6889cf7f2e2dSJohn Marino         case 0x0f16:        /* movhps */
6890cf7f2e2dSJohn Marino         case 0x660f16:      /* movhpd */
6891cf7f2e2dSJohn Marino         case 0xf30f16:      /* movshdup */
6892cf7f2e2dSJohn Marino         case 0x0f28:        /* movaps */
6893cf7f2e2dSJohn Marino         case 0x660f28:      /* movapd */
6894cf7f2e2dSJohn Marino         case 0x0f2a:        /* cvtpi2ps */
6895cf7f2e2dSJohn Marino         case 0x660f2a:      /* cvtpi2pd */
6896cf7f2e2dSJohn Marino         case 0xf30f2a:      /* cvtsi2ss */
6897cf7f2e2dSJohn Marino         case 0xf20f2a:      /* cvtsi2sd */
6898cf7f2e2dSJohn Marino         case 0x0f2c:        /* cvttps2pi */
6899cf7f2e2dSJohn Marino         case 0x660f2c:      /* cvttpd2pi */
6900cf7f2e2dSJohn Marino         case 0x0f2d:        /* cvtps2pi */
6901cf7f2e2dSJohn Marino         case 0x660f2d:      /* cvtpd2pi */
6902cf7f2e2dSJohn Marino         case 0x660f3800:    /* pshufb */
6903cf7f2e2dSJohn Marino         case 0x660f3801:    /* phaddw */
6904cf7f2e2dSJohn Marino         case 0x660f3802:    /* phaddd */
6905cf7f2e2dSJohn Marino         case 0x660f3803:    /* phaddsw */
6906cf7f2e2dSJohn Marino         case 0x660f3804:    /* pmaddubsw */
6907cf7f2e2dSJohn Marino         case 0x660f3805:    /* phsubw */
6908cf7f2e2dSJohn Marino         case 0x660f3806:    /* phsubd */
6909c50c785cSJohn Marino         case 0x660f3807:    /* phsubsw */
6910cf7f2e2dSJohn Marino         case 0x660f3808:    /* psignb */
6911cf7f2e2dSJohn Marino         case 0x660f3809:    /* psignw */
6912cf7f2e2dSJohn Marino         case 0x660f380a:    /* psignd */
6913cf7f2e2dSJohn Marino         case 0x660f380b:    /* pmulhrsw */
6914cf7f2e2dSJohn Marino         case 0x660f3810:    /* pblendvb */
6915cf7f2e2dSJohn Marino         case 0x660f3814:    /* blendvps */
6916cf7f2e2dSJohn Marino         case 0x660f3815:    /* blendvpd */
6917cf7f2e2dSJohn Marino         case 0x660f381c:    /* pabsb */
6918cf7f2e2dSJohn Marino         case 0x660f381d:    /* pabsw */
6919cf7f2e2dSJohn Marino         case 0x660f381e:    /* pabsd */
6920cf7f2e2dSJohn Marino         case 0x660f3820:    /* pmovsxbw */
6921cf7f2e2dSJohn Marino         case 0x660f3821:    /* pmovsxbd */
6922cf7f2e2dSJohn Marino         case 0x660f3822:    /* pmovsxbq */
6923cf7f2e2dSJohn Marino         case 0x660f3823:    /* pmovsxwd */
6924cf7f2e2dSJohn Marino         case 0x660f3824:    /* pmovsxwq */
6925cf7f2e2dSJohn Marino         case 0x660f3825:    /* pmovsxdq */
6926cf7f2e2dSJohn Marino         case 0x660f3828:    /* pmuldq */
6927cf7f2e2dSJohn Marino         case 0x660f3829:    /* pcmpeqq */
6928cf7f2e2dSJohn Marino         case 0x660f382a:    /* movntdqa */
6929cf7f2e2dSJohn Marino         case 0x660f3a08:    /* roundps */
6930cf7f2e2dSJohn Marino         case 0x660f3a09:    /* roundpd */
6931cf7f2e2dSJohn Marino         case 0x660f3a0a:    /* roundss */
6932cf7f2e2dSJohn Marino         case 0x660f3a0b:    /* roundsd */
6933cf7f2e2dSJohn Marino         case 0x660f3a0c:    /* blendps */
6934cf7f2e2dSJohn Marino         case 0x660f3a0d:    /* blendpd */
6935cf7f2e2dSJohn Marino         case 0x660f3a0e:    /* pblendw */
6936cf7f2e2dSJohn Marino         case 0x660f3a0f:    /* palignr */
6937cf7f2e2dSJohn Marino         case 0x660f3a20:    /* pinsrb */
6938cf7f2e2dSJohn Marino         case 0x660f3a21:    /* insertps */
6939cf7f2e2dSJohn Marino         case 0x660f3a22:    /* pinsrd pinsrq */
6940cf7f2e2dSJohn Marino         case 0x660f3a40:    /* dpps */
6941cf7f2e2dSJohn Marino         case 0x660f3a41:    /* dppd */
6942cf7f2e2dSJohn Marino         case 0x660f3a42:    /* mpsadbw */
6943cf7f2e2dSJohn Marino         case 0x660f3a60:    /* pcmpestrm */
6944cf7f2e2dSJohn Marino         case 0x660f3a61:    /* pcmpestri */
6945cf7f2e2dSJohn Marino         case 0x660f3a62:    /* pcmpistrm */
6946cf7f2e2dSJohn Marino         case 0x660f3a63:    /* pcmpistri */
6947cf7f2e2dSJohn Marino         case 0x0f51:        /* sqrtps */
6948cf7f2e2dSJohn Marino         case 0x660f51:      /* sqrtpd */
6949cf7f2e2dSJohn Marino         case 0xf20f51:      /* sqrtsd */
6950cf7f2e2dSJohn Marino         case 0xf30f51:      /* sqrtss */
6951cf7f2e2dSJohn Marino         case 0x0f52:        /* rsqrtps */
6952cf7f2e2dSJohn Marino         case 0xf30f52:      /* rsqrtss */
6953cf7f2e2dSJohn Marino         case 0x0f53:        /* rcpps */
6954cf7f2e2dSJohn Marino         case 0xf30f53:      /* rcpss */
6955cf7f2e2dSJohn Marino         case 0x0f54:        /* andps */
6956cf7f2e2dSJohn Marino         case 0x660f54:      /* andpd */
6957cf7f2e2dSJohn Marino         case 0x0f55:        /* andnps */
6958cf7f2e2dSJohn Marino         case 0x660f55:      /* andnpd */
6959cf7f2e2dSJohn Marino         case 0x0f56:        /* orps */
6960cf7f2e2dSJohn Marino         case 0x660f56:      /* orpd */
6961cf7f2e2dSJohn Marino         case 0x0f57:        /* xorps */
6962cf7f2e2dSJohn Marino         case 0x660f57:      /* xorpd */
6963cf7f2e2dSJohn Marino         case 0x0f58:        /* addps */
6964cf7f2e2dSJohn Marino         case 0x660f58:      /* addpd */
6965cf7f2e2dSJohn Marino         case 0xf20f58:      /* addsd */
6966cf7f2e2dSJohn Marino         case 0xf30f58:      /* addss */
6967cf7f2e2dSJohn Marino         case 0x0f59:        /* mulps */
6968cf7f2e2dSJohn Marino         case 0x660f59:      /* mulpd */
6969cf7f2e2dSJohn Marino         case 0xf20f59:      /* mulsd */
6970cf7f2e2dSJohn Marino         case 0xf30f59:      /* mulss */
6971cf7f2e2dSJohn Marino         case 0x0f5a:        /* cvtps2pd */
6972cf7f2e2dSJohn Marino         case 0x660f5a:      /* cvtpd2ps */
6973cf7f2e2dSJohn Marino         case 0xf20f5a:      /* cvtsd2ss */
6974cf7f2e2dSJohn Marino         case 0xf30f5a:      /* cvtss2sd */
6975cf7f2e2dSJohn Marino         case 0x0f5b:        /* cvtdq2ps */
6976cf7f2e2dSJohn Marino         case 0x660f5b:      /* cvtps2dq */
6977cf7f2e2dSJohn Marino         case 0xf30f5b:      /* cvttps2dq */
6978cf7f2e2dSJohn Marino         case 0x0f5c:        /* subps */
6979cf7f2e2dSJohn Marino         case 0x660f5c:      /* subpd */
6980cf7f2e2dSJohn Marino         case 0xf20f5c:      /* subsd */
6981cf7f2e2dSJohn Marino         case 0xf30f5c:      /* subss */
6982cf7f2e2dSJohn Marino         case 0x0f5d:        /* minps */
6983cf7f2e2dSJohn Marino         case 0x660f5d:      /* minpd */
6984cf7f2e2dSJohn Marino         case 0xf20f5d:      /* minsd */
6985cf7f2e2dSJohn Marino         case 0xf30f5d:      /* minss */
6986cf7f2e2dSJohn Marino         case 0x0f5e:        /* divps */
6987cf7f2e2dSJohn Marino         case 0x660f5e:      /* divpd */
6988cf7f2e2dSJohn Marino         case 0xf20f5e:      /* divsd */
6989cf7f2e2dSJohn Marino         case 0xf30f5e:      /* divss */
6990cf7f2e2dSJohn Marino         case 0x0f5f:        /* maxps */
6991cf7f2e2dSJohn Marino         case 0x660f5f:      /* maxpd */
6992cf7f2e2dSJohn Marino         case 0xf20f5f:      /* maxsd */
6993cf7f2e2dSJohn Marino         case 0xf30f5f:      /* maxss */
6994cf7f2e2dSJohn Marino         case 0x660f60:      /* punpcklbw */
6995cf7f2e2dSJohn Marino         case 0x660f61:      /* punpcklwd */
6996cf7f2e2dSJohn Marino         case 0x660f62:      /* punpckldq */
6997cf7f2e2dSJohn Marino         case 0x660f63:      /* packsswb */
6998cf7f2e2dSJohn Marino         case 0x660f64:      /* pcmpgtb */
6999cf7f2e2dSJohn Marino         case 0x660f65:      /* pcmpgtw */
7000c50c785cSJohn Marino         case 0x660f66:      /* pcmpgtd */
7001cf7f2e2dSJohn Marino         case 0x660f67:      /* packuswb */
7002cf7f2e2dSJohn Marino         case 0x660f68:      /* punpckhbw */
7003cf7f2e2dSJohn Marino         case 0x660f69:      /* punpckhwd */
7004cf7f2e2dSJohn Marino         case 0x660f6a:      /* punpckhdq */
7005cf7f2e2dSJohn Marino         case 0x660f6b:      /* packssdw */
7006cf7f2e2dSJohn Marino         case 0x660f6c:      /* punpcklqdq */
7007cf7f2e2dSJohn Marino         case 0x660f6d:      /* punpckhqdq */
7008cf7f2e2dSJohn Marino         case 0x660f6e:      /* movd */
7009cf7f2e2dSJohn Marino         case 0x660f6f:      /* movdqa */
7010cf7f2e2dSJohn Marino         case 0xf30f6f:      /* movdqu */
7011cf7f2e2dSJohn Marino         case 0x660f70:      /* pshufd */
7012cf7f2e2dSJohn Marino         case 0xf20f70:      /* pshuflw */
7013cf7f2e2dSJohn Marino         case 0xf30f70:      /* pshufhw */
7014cf7f2e2dSJohn Marino         case 0x660f74:      /* pcmpeqb */
7015cf7f2e2dSJohn Marino         case 0x660f75:      /* pcmpeqw */
7016c50c785cSJohn Marino         case 0x660f76:      /* pcmpeqd */
7017cf7f2e2dSJohn Marino         case 0x660f7c:      /* haddpd */
7018cf7f2e2dSJohn Marino         case 0xf20f7c:      /* haddps */
7019cf7f2e2dSJohn Marino         case 0x660f7d:      /* hsubpd */
7020cf7f2e2dSJohn Marino         case 0xf20f7d:      /* hsubps */
7021cf7f2e2dSJohn Marino         case 0xf30f7e:      /* movq */
7022cf7f2e2dSJohn Marino         case 0x0fc2:        /* cmpps */
7023cf7f2e2dSJohn Marino         case 0x660fc2:      /* cmppd */
7024cf7f2e2dSJohn Marino         case 0xf20fc2:      /* cmpsd */
7025cf7f2e2dSJohn Marino         case 0xf30fc2:      /* cmpss */
7026cf7f2e2dSJohn Marino         case 0x660fc4:      /* pinsrw */
7027cf7f2e2dSJohn Marino         case 0x0fc6:        /* shufps */
7028cf7f2e2dSJohn Marino         case 0x660fc6:      /* shufpd */
7029cf7f2e2dSJohn Marino         case 0x660fd0:      /* addsubpd */
7030cf7f2e2dSJohn Marino         case 0xf20fd0:      /* addsubps */
7031cf7f2e2dSJohn Marino         case 0x660fd1:      /* psrlw */
7032cf7f2e2dSJohn Marino         case 0x660fd2:      /* psrld */
7033cf7f2e2dSJohn Marino         case 0x660fd3:      /* psrlq */
7034cf7f2e2dSJohn Marino         case 0x660fd4:      /* paddq */
7035cf7f2e2dSJohn Marino         case 0x660fd5:      /* pmullw */
7036cf7f2e2dSJohn Marino         case 0xf30fd6:      /* movq2dq */
7037cf7f2e2dSJohn Marino         case 0x660fd8:      /* psubusb */
7038cf7f2e2dSJohn Marino         case 0x660fd9:      /* psubusw */
7039cf7f2e2dSJohn Marino         case 0x660fda:      /* pminub */
7040cf7f2e2dSJohn Marino         case 0x660fdb:      /* pand */
7041cf7f2e2dSJohn Marino         case 0x660fdc:      /* paddusb */
7042cf7f2e2dSJohn Marino         case 0x660fdd:      /* paddusw */
7043cf7f2e2dSJohn Marino         case 0x660fde:      /* pmaxub */
7044cf7f2e2dSJohn Marino         case 0x660fdf:      /* pandn */
7045cf7f2e2dSJohn Marino         case 0x660fe0:      /* pavgb */
7046cf7f2e2dSJohn Marino         case 0x660fe1:      /* psraw */
7047cf7f2e2dSJohn Marino         case 0x660fe2:      /* psrad */
7048cf7f2e2dSJohn Marino         case 0x660fe3:      /* pavgw */
7049cf7f2e2dSJohn Marino         case 0x660fe4:      /* pmulhuw */
7050cf7f2e2dSJohn Marino         case 0x660fe5:      /* pmulhw */
7051cf7f2e2dSJohn Marino         case 0x660fe6:      /* cvttpd2dq */
7052cf7f2e2dSJohn Marino         case 0xf20fe6:      /* cvtpd2dq */
7053cf7f2e2dSJohn Marino         case 0xf30fe6:      /* cvtdq2pd */
7054cf7f2e2dSJohn Marino         case 0x660fe8:      /* psubsb */
7055cf7f2e2dSJohn Marino         case 0x660fe9:      /* psubsw */
7056cf7f2e2dSJohn Marino         case 0x660fea:      /* pminsw */
7057cf7f2e2dSJohn Marino         case 0x660feb:      /* por */
7058cf7f2e2dSJohn Marino         case 0x660fec:      /* paddsb */
7059cf7f2e2dSJohn Marino         case 0x660fed:      /* paddsw */
7060cf7f2e2dSJohn Marino         case 0x660fee:      /* pmaxsw */
7061cf7f2e2dSJohn Marino         case 0x660fef:      /* pxor */
7062c50c785cSJohn Marino         case 0xf20ff0:      /* lddqu */
7063cf7f2e2dSJohn Marino         case 0x660ff1:      /* psllw */
7064cf7f2e2dSJohn Marino         case 0x660ff2:      /* pslld */
7065cf7f2e2dSJohn Marino         case 0x660ff3:      /* psllq */
7066cf7f2e2dSJohn Marino         case 0x660ff4:      /* pmuludq */
7067cf7f2e2dSJohn Marino         case 0x660ff5:      /* pmaddwd */
7068cf7f2e2dSJohn Marino         case 0x660ff6:      /* psadbw */
7069cf7f2e2dSJohn Marino         case 0x660ff8:      /* psubb */
7070cf7f2e2dSJohn Marino         case 0x660ff9:      /* psubw */
7071c50c785cSJohn Marino         case 0x660ffa:      /* psubd */
7072cf7f2e2dSJohn Marino         case 0x660ffb:      /* psubq */
7073cf7f2e2dSJohn Marino         case 0x660ffc:      /* paddb */
7074cf7f2e2dSJohn Marino         case 0x660ffd:      /* paddw */
7075c50c785cSJohn Marino         case 0x660ffe:      /* paddd */
7076cf7f2e2dSJohn Marino           if (i386_record_modrm (&ir))
7077cf7f2e2dSJohn Marino 	    return -1;
7078cf7f2e2dSJohn Marino           ir.reg |= rex_r;
7079cf7f2e2dSJohn Marino           if (!i386_xmm_regnum_p (gdbarch, I387_XMM0_REGNUM (tdep) + ir.reg))
7080cf7f2e2dSJohn Marino             goto no_support;
7081*ef5ccd6cSJohn Marino           record_full_arch_list_add_reg (ir.regcache,
7082cf7f2e2dSJohn Marino 					 I387_XMM0_REGNUM (tdep) + ir.reg);
7083cf7f2e2dSJohn Marino           if ((opcode & 0xfffffffc) == 0x660f3a60)
7084*ef5ccd6cSJohn Marino             I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
7085cf7f2e2dSJohn Marino           break;
7086cf7f2e2dSJohn Marino 
7087cf7f2e2dSJohn Marino         case 0x0f11:        /* movups */
7088cf7f2e2dSJohn Marino         case 0x660f11:      /* movupd */
7089cf7f2e2dSJohn Marino         case 0xf30f11:      /* movss */
7090cf7f2e2dSJohn Marino         case 0xf20f11:      /* movsd */
7091cf7f2e2dSJohn Marino         case 0x0f13:        /* movlps */
7092cf7f2e2dSJohn Marino         case 0x660f13:      /* movlpd */
7093cf7f2e2dSJohn Marino         case 0x0f17:        /* movhps */
7094cf7f2e2dSJohn Marino         case 0x660f17:      /* movhpd */
7095cf7f2e2dSJohn Marino         case 0x0f29:        /* movaps */
7096cf7f2e2dSJohn Marino         case 0x660f29:      /* movapd */
7097cf7f2e2dSJohn Marino         case 0x660f3a14:    /* pextrb */
7098cf7f2e2dSJohn Marino         case 0x660f3a15:    /* pextrw */
7099cf7f2e2dSJohn Marino         case 0x660f3a16:    /* pextrd pextrq */
7100cf7f2e2dSJohn Marino         case 0x660f3a17:    /* extractps */
7101cf7f2e2dSJohn Marino         case 0x660f7f:      /* movdqa */
7102cf7f2e2dSJohn Marino         case 0xf30f7f:      /* movdqu */
7103cf7f2e2dSJohn Marino           if (i386_record_modrm (&ir))
7104cf7f2e2dSJohn Marino 	    return -1;
7105cf7f2e2dSJohn Marino           if (ir.mod == 3)
7106cf7f2e2dSJohn Marino             {
7107cf7f2e2dSJohn Marino               if (opcode == 0x0f13 || opcode == 0x660f13
7108cf7f2e2dSJohn Marino                   || opcode == 0x0f17 || opcode == 0x660f17)
7109cf7f2e2dSJohn Marino                 goto no_support;
7110cf7f2e2dSJohn Marino               ir.rm |= ir.rex_b;
7111c50c785cSJohn Marino               if (!i386_xmm_regnum_p (gdbarch,
7112c50c785cSJohn Marino 				      I387_XMM0_REGNUM (tdep) + ir.rm))
7113cf7f2e2dSJohn Marino                 goto no_support;
7114*ef5ccd6cSJohn Marino               record_full_arch_list_add_reg (ir.regcache,
7115cf7f2e2dSJohn Marino 					     I387_XMM0_REGNUM (tdep) + ir.rm);
7116cf7f2e2dSJohn Marino             }
71175796c8dcSSimon Schubert           else
7118cf7f2e2dSJohn Marino             {
7119cf7f2e2dSJohn Marino               switch (opcode)
7120cf7f2e2dSJohn Marino                 {
7121cf7f2e2dSJohn Marino                   case 0x660f3a14:
7122cf7f2e2dSJohn Marino                     ir.ot = OT_BYTE;
7123cf7f2e2dSJohn Marino                     break;
7124cf7f2e2dSJohn Marino                   case 0x660f3a15:
7125cf7f2e2dSJohn Marino                     ir.ot = OT_WORD;
7126cf7f2e2dSJohn Marino                     break;
7127cf7f2e2dSJohn Marino                   case 0x660f3a16:
7128cf7f2e2dSJohn Marino                     ir.ot = OT_LONG;
7129cf7f2e2dSJohn Marino                     break;
7130cf7f2e2dSJohn Marino                   case 0x660f3a17:
7131cf7f2e2dSJohn Marino                     ir.ot = OT_QUAD;
7132cf7f2e2dSJohn Marino                     break;
7133cf7f2e2dSJohn Marino                   default:
7134cf7f2e2dSJohn Marino                     ir.ot = OT_DQUAD;
7135cf7f2e2dSJohn Marino                     break;
7136cf7f2e2dSJohn Marino                 }
7137cf7f2e2dSJohn Marino               if (i386_record_lea_modrm (&ir))
7138cf7f2e2dSJohn Marino                 return -1;
7139cf7f2e2dSJohn Marino             }
7140cf7f2e2dSJohn Marino           break;
7141cf7f2e2dSJohn Marino 
7142cf7f2e2dSJohn Marino         case 0x0f2b:      /* movntps */
7143cf7f2e2dSJohn Marino         case 0x660f2b:    /* movntpd */
7144cf7f2e2dSJohn Marino         case 0x0fe7:      /* movntq */
7145cf7f2e2dSJohn Marino         case 0x660fe7:    /* movntdq */
7146cf7f2e2dSJohn Marino           if (ir.mod == 3)
7147cf7f2e2dSJohn Marino             goto no_support;
7148cf7f2e2dSJohn Marino           if (opcode == 0x0fe7)
7149cf7f2e2dSJohn Marino             ir.ot = OT_QUAD;
7150cf7f2e2dSJohn Marino           else
7151cf7f2e2dSJohn Marino             ir.ot = OT_DQUAD;
7152cf7f2e2dSJohn Marino           if (i386_record_lea_modrm (&ir))
7153cf7f2e2dSJohn Marino             return -1;
7154cf7f2e2dSJohn Marino           break;
7155cf7f2e2dSJohn Marino 
7156cf7f2e2dSJohn Marino         case 0xf30f2c:      /* cvttss2si */
7157cf7f2e2dSJohn Marino         case 0xf20f2c:      /* cvttsd2si */
7158cf7f2e2dSJohn Marino         case 0xf30f2d:      /* cvtss2si */
7159cf7f2e2dSJohn Marino         case 0xf20f2d:      /* cvtsd2si */
7160cf7f2e2dSJohn Marino         case 0xf20f38f0:    /* crc32 */
7161cf7f2e2dSJohn Marino         case 0xf20f38f1:    /* crc32 */
7162cf7f2e2dSJohn Marino         case 0x0f50:        /* movmskps */
7163cf7f2e2dSJohn Marino         case 0x660f50:      /* movmskpd */
7164cf7f2e2dSJohn Marino         case 0x0fc5:        /* pextrw */
7165cf7f2e2dSJohn Marino         case 0x660fc5:      /* pextrw */
7166cf7f2e2dSJohn Marino         case 0x0fd7:        /* pmovmskb */
7167cf7f2e2dSJohn Marino         case 0x660fd7:      /* pmovmskb */
7168*ef5ccd6cSJohn Marino           I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.reg | rex_r);
7169cf7f2e2dSJohn Marino           break;
7170cf7f2e2dSJohn Marino 
7171cf7f2e2dSJohn Marino         case 0x0f3800:    /* pshufb */
7172cf7f2e2dSJohn Marino         case 0x0f3801:    /* phaddw */
7173cf7f2e2dSJohn Marino         case 0x0f3802:    /* phaddd */
7174cf7f2e2dSJohn Marino         case 0x0f3803:    /* phaddsw */
7175cf7f2e2dSJohn Marino         case 0x0f3804:    /* pmaddubsw */
7176cf7f2e2dSJohn Marino         case 0x0f3805:    /* phsubw */
7177cf7f2e2dSJohn Marino         case 0x0f3806:    /* phsubd */
7178c50c785cSJohn Marino         case 0x0f3807:    /* phsubsw */
7179cf7f2e2dSJohn Marino         case 0x0f3808:    /* psignb */
7180cf7f2e2dSJohn Marino         case 0x0f3809:    /* psignw */
7181cf7f2e2dSJohn Marino         case 0x0f380a:    /* psignd */
7182cf7f2e2dSJohn Marino         case 0x0f380b:    /* pmulhrsw */
7183cf7f2e2dSJohn Marino         case 0x0f381c:    /* pabsb */
7184cf7f2e2dSJohn Marino         case 0x0f381d:    /* pabsw */
7185cf7f2e2dSJohn Marino         case 0x0f381e:    /* pabsd */
7186cf7f2e2dSJohn Marino         case 0x0f382b:    /* packusdw */
7187cf7f2e2dSJohn Marino         case 0x0f3830:    /* pmovzxbw */
7188cf7f2e2dSJohn Marino         case 0x0f3831:    /* pmovzxbd */
7189cf7f2e2dSJohn Marino         case 0x0f3832:    /* pmovzxbq */
7190cf7f2e2dSJohn Marino         case 0x0f3833:    /* pmovzxwd */
7191cf7f2e2dSJohn Marino         case 0x0f3834:    /* pmovzxwq */
7192cf7f2e2dSJohn Marino         case 0x0f3835:    /* pmovzxdq */
7193cf7f2e2dSJohn Marino         case 0x0f3837:    /* pcmpgtq */
7194cf7f2e2dSJohn Marino         case 0x0f3838:    /* pminsb */
7195cf7f2e2dSJohn Marino         case 0x0f3839:    /* pminsd */
7196cf7f2e2dSJohn Marino         case 0x0f383a:    /* pminuw */
7197cf7f2e2dSJohn Marino         case 0x0f383b:    /* pminud */
7198cf7f2e2dSJohn Marino         case 0x0f383c:    /* pmaxsb */
7199cf7f2e2dSJohn Marino         case 0x0f383d:    /* pmaxsd */
7200cf7f2e2dSJohn Marino         case 0x0f383e:    /* pmaxuw */
7201cf7f2e2dSJohn Marino         case 0x0f383f:    /* pmaxud */
7202cf7f2e2dSJohn Marino         case 0x0f3840:    /* pmulld */
7203cf7f2e2dSJohn Marino         case 0x0f3841:    /* phminposuw */
7204cf7f2e2dSJohn Marino         case 0x0f3a0f:    /* palignr */
7205cf7f2e2dSJohn Marino         case 0x0f60:      /* punpcklbw */
7206cf7f2e2dSJohn Marino         case 0x0f61:      /* punpcklwd */
7207cf7f2e2dSJohn Marino         case 0x0f62:      /* punpckldq */
7208cf7f2e2dSJohn Marino         case 0x0f63:      /* packsswb */
7209cf7f2e2dSJohn Marino         case 0x0f64:      /* pcmpgtb */
7210cf7f2e2dSJohn Marino         case 0x0f65:      /* pcmpgtw */
7211c50c785cSJohn Marino         case 0x0f66:      /* pcmpgtd */
7212cf7f2e2dSJohn Marino         case 0x0f67:      /* packuswb */
7213cf7f2e2dSJohn Marino         case 0x0f68:      /* punpckhbw */
7214cf7f2e2dSJohn Marino         case 0x0f69:      /* punpckhwd */
7215cf7f2e2dSJohn Marino         case 0x0f6a:      /* punpckhdq */
7216cf7f2e2dSJohn Marino         case 0x0f6b:      /* packssdw */
7217cf7f2e2dSJohn Marino         case 0x0f6e:      /* movd */
7218cf7f2e2dSJohn Marino         case 0x0f6f:      /* movq */
7219cf7f2e2dSJohn Marino         case 0x0f70:      /* pshufw */
7220cf7f2e2dSJohn Marino         case 0x0f74:      /* pcmpeqb */
7221cf7f2e2dSJohn Marino         case 0x0f75:      /* pcmpeqw */
7222c50c785cSJohn Marino         case 0x0f76:      /* pcmpeqd */
7223cf7f2e2dSJohn Marino         case 0x0fc4:      /* pinsrw */
7224cf7f2e2dSJohn Marino         case 0x0fd1:      /* psrlw */
7225cf7f2e2dSJohn Marino         case 0x0fd2:      /* psrld */
7226cf7f2e2dSJohn Marino         case 0x0fd3:      /* psrlq */
7227cf7f2e2dSJohn Marino         case 0x0fd4:      /* paddq */
7228cf7f2e2dSJohn Marino         case 0x0fd5:      /* pmullw */
7229cf7f2e2dSJohn Marino         case 0xf20fd6:    /* movdq2q */
7230cf7f2e2dSJohn Marino         case 0x0fd8:      /* psubusb */
7231cf7f2e2dSJohn Marino         case 0x0fd9:      /* psubusw */
7232cf7f2e2dSJohn Marino         case 0x0fda:      /* pminub */
7233cf7f2e2dSJohn Marino         case 0x0fdb:      /* pand */
7234cf7f2e2dSJohn Marino         case 0x0fdc:      /* paddusb */
7235cf7f2e2dSJohn Marino         case 0x0fdd:      /* paddusw */
7236cf7f2e2dSJohn Marino         case 0x0fde:      /* pmaxub */
7237cf7f2e2dSJohn Marino         case 0x0fdf:      /* pandn */
7238cf7f2e2dSJohn Marino         case 0x0fe0:      /* pavgb */
7239cf7f2e2dSJohn Marino         case 0x0fe1:      /* psraw */
7240cf7f2e2dSJohn Marino         case 0x0fe2:      /* psrad */
7241cf7f2e2dSJohn Marino         case 0x0fe3:      /* pavgw */
7242cf7f2e2dSJohn Marino         case 0x0fe4:      /* pmulhuw */
7243cf7f2e2dSJohn Marino         case 0x0fe5:      /* pmulhw */
7244cf7f2e2dSJohn Marino         case 0x0fe8:      /* psubsb */
7245cf7f2e2dSJohn Marino         case 0x0fe9:      /* psubsw */
7246cf7f2e2dSJohn Marino         case 0x0fea:      /* pminsw */
7247cf7f2e2dSJohn Marino         case 0x0feb:      /* por */
7248cf7f2e2dSJohn Marino         case 0x0fec:      /* paddsb */
7249cf7f2e2dSJohn Marino         case 0x0fed:      /* paddsw */
7250cf7f2e2dSJohn Marino         case 0x0fee:      /* pmaxsw */
7251cf7f2e2dSJohn Marino         case 0x0fef:      /* pxor */
7252cf7f2e2dSJohn Marino         case 0x0ff1:      /* psllw */
7253cf7f2e2dSJohn Marino         case 0x0ff2:      /* pslld */
7254cf7f2e2dSJohn Marino         case 0x0ff3:      /* psllq */
7255cf7f2e2dSJohn Marino         case 0x0ff4:      /* pmuludq */
7256cf7f2e2dSJohn Marino         case 0x0ff5:      /* pmaddwd */
7257cf7f2e2dSJohn Marino         case 0x0ff6:      /* psadbw */
7258cf7f2e2dSJohn Marino         case 0x0ff8:      /* psubb */
7259cf7f2e2dSJohn Marino         case 0x0ff9:      /* psubw */
7260c50c785cSJohn Marino         case 0x0ffa:      /* psubd */
7261cf7f2e2dSJohn Marino         case 0x0ffb:      /* psubq */
7262cf7f2e2dSJohn Marino         case 0x0ffc:      /* paddb */
7263cf7f2e2dSJohn Marino         case 0x0ffd:      /* paddw */
7264c50c785cSJohn Marino         case 0x0ffe:      /* paddd */
7265cf7f2e2dSJohn Marino           if (i386_record_modrm (&ir))
7266cf7f2e2dSJohn Marino 	    return -1;
7267cf7f2e2dSJohn Marino           if (!i386_mmx_regnum_p (gdbarch, I387_MM0_REGNUM (tdep) + ir.reg))
7268cf7f2e2dSJohn Marino             goto no_support;
7269*ef5ccd6cSJohn Marino           record_full_arch_list_add_reg (ir.regcache,
7270cf7f2e2dSJohn Marino 					 I387_MM0_REGNUM (tdep) + ir.reg);
7271cf7f2e2dSJohn Marino           break;
7272cf7f2e2dSJohn Marino 
7273cf7f2e2dSJohn Marino         case 0x0f71:    /* psllw */
7274cf7f2e2dSJohn Marino         case 0x0f72:    /* pslld */
7275cf7f2e2dSJohn Marino         case 0x0f73:    /* psllq */
7276cf7f2e2dSJohn Marino           if (i386_record_modrm (&ir))
7277cf7f2e2dSJohn Marino 	    return -1;
7278cf7f2e2dSJohn Marino           if (!i386_mmx_regnum_p (gdbarch, I387_MM0_REGNUM (tdep) + ir.rm))
7279cf7f2e2dSJohn Marino             goto no_support;
7280*ef5ccd6cSJohn Marino           record_full_arch_list_add_reg (ir.regcache,
7281cf7f2e2dSJohn Marino 					 I387_MM0_REGNUM (tdep) + ir.rm);
7282cf7f2e2dSJohn Marino           break;
7283cf7f2e2dSJohn Marino 
7284cf7f2e2dSJohn Marino         case 0x660f71:    /* psllw */
7285cf7f2e2dSJohn Marino         case 0x660f72:    /* pslld */
7286cf7f2e2dSJohn Marino         case 0x660f73:    /* psllq */
7287cf7f2e2dSJohn Marino           if (i386_record_modrm (&ir))
7288cf7f2e2dSJohn Marino 	    return -1;
7289cf7f2e2dSJohn Marino           ir.rm |= ir.rex_b;
7290cf7f2e2dSJohn Marino           if (!i386_xmm_regnum_p (gdbarch, I387_XMM0_REGNUM (tdep) + ir.rm))
7291cf7f2e2dSJohn Marino             goto no_support;
7292*ef5ccd6cSJohn Marino           record_full_arch_list_add_reg (ir.regcache,
7293cf7f2e2dSJohn Marino 					 I387_XMM0_REGNUM (tdep) + ir.rm);
7294cf7f2e2dSJohn Marino           break;
7295cf7f2e2dSJohn Marino 
7296cf7f2e2dSJohn Marino         case 0x0f7e:      /* movd */
7297cf7f2e2dSJohn Marino         case 0x660f7e:    /* movd */
7298cf7f2e2dSJohn Marino           if (i386_record_modrm (&ir))
7299cf7f2e2dSJohn Marino 	    return -1;
7300cf7f2e2dSJohn Marino           if (ir.mod == 3)
7301*ef5ccd6cSJohn Marino             I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.rm | ir.rex_b);
7302cf7f2e2dSJohn Marino           else
7303cf7f2e2dSJohn Marino             {
7304cf7f2e2dSJohn Marino               if (ir.dflag == 2)
7305cf7f2e2dSJohn Marino                 ir.ot = OT_QUAD;
7306cf7f2e2dSJohn Marino               else
7307cf7f2e2dSJohn Marino                 ir.ot = OT_LONG;
7308cf7f2e2dSJohn Marino               if (i386_record_lea_modrm (&ir))
7309cf7f2e2dSJohn Marino                 return -1;
7310cf7f2e2dSJohn Marino             }
7311cf7f2e2dSJohn Marino           break;
7312cf7f2e2dSJohn Marino 
7313cf7f2e2dSJohn Marino         case 0x0f7f:    /* movq */
7314cf7f2e2dSJohn Marino           if (i386_record_modrm (&ir))
7315cf7f2e2dSJohn Marino 	    return -1;
7316cf7f2e2dSJohn Marino           if (ir.mod == 3)
7317cf7f2e2dSJohn Marino             {
7318cf7f2e2dSJohn Marino               if (!i386_mmx_regnum_p (gdbarch, I387_MM0_REGNUM (tdep) + ir.rm))
7319cf7f2e2dSJohn Marino                 goto no_support;
7320*ef5ccd6cSJohn Marino               record_full_arch_list_add_reg (ir.regcache,
7321cf7f2e2dSJohn Marino 					     I387_MM0_REGNUM (tdep) + ir.rm);
7322cf7f2e2dSJohn Marino             }
7323cf7f2e2dSJohn Marino           else
7324cf7f2e2dSJohn Marino             {
7325cf7f2e2dSJohn Marino               ir.ot = OT_QUAD;
7326cf7f2e2dSJohn Marino               if (i386_record_lea_modrm (&ir))
7327cf7f2e2dSJohn Marino                 return -1;
7328cf7f2e2dSJohn Marino             }
7329cf7f2e2dSJohn Marino           break;
7330cf7f2e2dSJohn Marino 
7331cf7f2e2dSJohn Marino         case 0xf30fb8:    /* popcnt */
7332cf7f2e2dSJohn Marino           if (i386_record_modrm (&ir))
7333cf7f2e2dSJohn Marino 	    return -1;
7334*ef5ccd6cSJohn Marino           I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.reg);
7335*ef5ccd6cSJohn Marino           I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
7336cf7f2e2dSJohn Marino           break;
7337cf7f2e2dSJohn Marino 
7338cf7f2e2dSJohn Marino         case 0x660fd6:    /* movq */
7339cf7f2e2dSJohn Marino           if (i386_record_modrm (&ir))
7340cf7f2e2dSJohn Marino 	    return -1;
7341cf7f2e2dSJohn Marino           if (ir.mod == 3)
7342cf7f2e2dSJohn Marino             {
7343cf7f2e2dSJohn Marino               ir.rm |= ir.rex_b;
7344c50c785cSJohn Marino               if (!i386_xmm_regnum_p (gdbarch,
7345c50c785cSJohn Marino 				      I387_XMM0_REGNUM (tdep) + ir.rm))
7346cf7f2e2dSJohn Marino                 goto no_support;
7347*ef5ccd6cSJohn Marino               record_full_arch_list_add_reg (ir.regcache,
7348cf7f2e2dSJohn Marino 					     I387_XMM0_REGNUM (tdep) + ir.rm);
7349cf7f2e2dSJohn Marino             }
7350cf7f2e2dSJohn Marino           else
7351cf7f2e2dSJohn Marino             {
7352cf7f2e2dSJohn Marino               ir.ot = OT_QUAD;
7353cf7f2e2dSJohn Marino               if (i386_record_lea_modrm (&ir))
7354cf7f2e2dSJohn Marino                 return -1;
7355cf7f2e2dSJohn Marino             }
7356cf7f2e2dSJohn Marino           break;
7357cf7f2e2dSJohn Marino 
7358cf7f2e2dSJohn Marino         case 0x660f3817:    /* ptest */
7359cf7f2e2dSJohn Marino         case 0x0f2e:        /* ucomiss */
7360cf7f2e2dSJohn Marino         case 0x660f2e:      /* ucomisd */
7361cf7f2e2dSJohn Marino         case 0x0f2f:        /* comiss */
7362cf7f2e2dSJohn Marino         case 0x660f2f:      /* comisd */
7363*ef5ccd6cSJohn Marino           I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM);
7364cf7f2e2dSJohn Marino           break;
7365cf7f2e2dSJohn Marino 
7366cf7f2e2dSJohn Marino         case 0x0ff7:    /* maskmovq */
7367cf7f2e2dSJohn Marino           regcache_raw_read_unsigned (ir.regcache,
7368cf7f2e2dSJohn Marino                                       ir.regmap[X86_RECORD_REDI_REGNUM],
7369cf7f2e2dSJohn Marino                                       &addr);
7370*ef5ccd6cSJohn Marino           if (record_full_arch_list_add_mem (addr, 64))
7371cf7f2e2dSJohn Marino             return -1;
7372cf7f2e2dSJohn Marino           break;
7373cf7f2e2dSJohn Marino 
7374cf7f2e2dSJohn Marino         case 0x660ff7:    /* maskmovdqu */
7375cf7f2e2dSJohn Marino           regcache_raw_read_unsigned (ir.regcache,
7376cf7f2e2dSJohn Marino                                       ir.regmap[X86_RECORD_REDI_REGNUM],
7377cf7f2e2dSJohn Marino                                       &addr);
7378*ef5ccd6cSJohn Marino           if (record_full_arch_list_add_mem (addr, 128))
7379cf7f2e2dSJohn Marino             return -1;
7380cf7f2e2dSJohn Marino           break;
7381cf7f2e2dSJohn Marino 
7382cf7f2e2dSJohn Marino         default:
7383cf7f2e2dSJohn Marino           goto no_support;
7384cf7f2e2dSJohn Marino           break;
7385cf7f2e2dSJohn Marino         }
7386cf7f2e2dSJohn Marino       break;
7387cf7f2e2dSJohn Marino 
7388cf7f2e2dSJohn Marino     default:
73895796c8dcSSimon Schubert       goto no_support;
73905796c8dcSSimon Schubert       break;
73915796c8dcSSimon Schubert     }
73925796c8dcSSimon Schubert 
73935796c8dcSSimon Schubert   /* In the future, maybe still need to deal with need_dasm.  */
7394*ef5ccd6cSJohn Marino   I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_REIP_REGNUM);
7395*ef5ccd6cSJohn Marino   if (record_full_arch_list_add_end ())
73965796c8dcSSimon Schubert     return -1;
73975796c8dcSSimon Schubert 
73985796c8dcSSimon Schubert   return 0;
73995796c8dcSSimon Schubert 
74005796c8dcSSimon Schubert  no_support:
7401cf7f2e2dSJohn Marino   printf_unfiltered (_("Process record does not support instruction 0x%02x "
74025796c8dcSSimon Schubert                        "at address %s.\n"),
7403cf7f2e2dSJohn Marino                      (unsigned int) (opcode),
7404cf7f2e2dSJohn Marino                      paddress (gdbarch, ir.orig_addr));
74055796c8dcSSimon Schubert   return -1;
74065796c8dcSSimon Schubert }
74075796c8dcSSimon Schubert 
74085796c8dcSSimon Schubert static const int i386_record_regmap[] =
74095796c8dcSSimon Schubert {
74105796c8dcSSimon Schubert   I386_EAX_REGNUM, I386_ECX_REGNUM, I386_EDX_REGNUM, I386_EBX_REGNUM,
74115796c8dcSSimon Schubert   I386_ESP_REGNUM, I386_EBP_REGNUM, I386_ESI_REGNUM, I386_EDI_REGNUM,
74125796c8dcSSimon Schubert   0, 0, 0, 0, 0, 0, 0, 0,
74135796c8dcSSimon Schubert   I386_EIP_REGNUM, I386_EFLAGS_REGNUM, I386_CS_REGNUM, I386_SS_REGNUM,
74145796c8dcSSimon Schubert   I386_DS_REGNUM, I386_ES_REGNUM, I386_FS_REGNUM, I386_GS_REGNUM
74155796c8dcSSimon Schubert };
74165796c8dcSSimon Schubert 
7417cf7f2e2dSJohn Marino /* Check that the given address appears suitable for a fast
7418a45ae5f8SJohn Marino    tracepoint, which on x86-64 means that we need an instruction of at
7419cf7f2e2dSJohn Marino    least 5 bytes, so that we can overwrite it with a 4-byte-offset
7420cf7f2e2dSJohn Marino    jump and not have to worry about program jumps to an address in the
7421a45ae5f8SJohn Marino    middle of the tracepoint jump.  On x86, it may be possible to use
7422a45ae5f8SJohn Marino    4-byte jumps with a 2-byte offset to a trampoline located in the
7423a45ae5f8SJohn Marino    bottom 64 KiB of memory.  Returns 1 if OK, and writes a size
7424cf7f2e2dSJohn Marino    of instruction to replace, and 0 if not, plus an explanatory
7425cf7f2e2dSJohn Marino    string.  */
7426cf7f2e2dSJohn Marino 
7427cf7f2e2dSJohn Marino static int
i386_fast_tracepoint_valid_at(struct gdbarch * gdbarch,CORE_ADDR addr,int * isize,char ** msg)7428cf7f2e2dSJohn Marino i386_fast_tracepoint_valid_at (struct gdbarch *gdbarch,
7429cf7f2e2dSJohn Marino 			       CORE_ADDR addr, int *isize, char **msg)
7430cf7f2e2dSJohn Marino {
7431cf7f2e2dSJohn Marino   int len, jumplen;
7432cf7f2e2dSJohn Marino   static struct ui_file *gdb_null = NULL;
7433cf7f2e2dSJohn Marino 
7434a45ae5f8SJohn Marino   /*  Ask the target for the minimum instruction length supported.  */
7435a45ae5f8SJohn Marino   jumplen = target_get_min_fast_tracepoint_insn_len ();
7436a45ae5f8SJohn Marino 
7437a45ae5f8SJohn Marino   if (jumplen < 0)
7438a45ae5f8SJohn Marino     {
7439a45ae5f8SJohn Marino       /* If the target does not support the get_min_fast_tracepoint_insn_len
7440a45ae5f8SJohn Marino 	 operation, assume that fast tracepoints will always be implemented
7441a45ae5f8SJohn Marino 	 using 4-byte relative jumps on both x86 and x86-64.  */
7442cf7f2e2dSJohn Marino       jumplen = 5;
7443a45ae5f8SJohn Marino     }
7444a45ae5f8SJohn Marino   else if (jumplen == 0)
7445a45ae5f8SJohn Marino     {
7446a45ae5f8SJohn Marino       /* If the target does support get_min_fast_tracepoint_insn_len but
7447a45ae5f8SJohn Marino 	 returns zero, then the IPA has not loaded yet.  In this case,
7448a45ae5f8SJohn Marino 	 we optimistically assume that truncated 2-byte relative jumps
7449a45ae5f8SJohn Marino 	 will be available on x86, and compensate later if this assumption
7450a45ae5f8SJohn Marino 	 turns out to be incorrect.  On x86-64 architectures, 4-byte relative
7451a45ae5f8SJohn Marino 	 jumps will always be used.  */
7452a45ae5f8SJohn Marino       jumplen = (register_size (gdbarch, 0) == 8) ? 5 : 4;
7453a45ae5f8SJohn Marino     }
7454cf7f2e2dSJohn Marino 
7455cf7f2e2dSJohn Marino   /* Dummy file descriptor for the disassembler.  */
7456cf7f2e2dSJohn Marino   if (!gdb_null)
7457cf7f2e2dSJohn Marino     gdb_null = ui_file_new ();
7458cf7f2e2dSJohn Marino 
7459cf7f2e2dSJohn Marino   /* Check for fit.  */
7460cf7f2e2dSJohn Marino   len = gdb_print_insn (gdbarch, addr, gdb_null, NULL);
7461a45ae5f8SJohn Marino   if (isize)
7462a45ae5f8SJohn Marino     *isize = len;
7463a45ae5f8SJohn Marino 
7464cf7f2e2dSJohn Marino   if (len < jumplen)
7465cf7f2e2dSJohn Marino     {
7466cf7f2e2dSJohn Marino       /* Return a bit of target-specific detail to add to the caller's
7467cf7f2e2dSJohn Marino 	 generic failure message.  */
7468cf7f2e2dSJohn Marino       if (msg)
7469c50c785cSJohn Marino 	*msg = xstrprintf (_("; instruction is only %d bytes long, "
7470c50c785cSJohn Marino 			     "need at least %d bytes for the jump"),
7471cf7f2e2dSJohn Marino 			   len, jumplen);
7472cf7f2e2dSJohn Marino       return 0;
7473cf7f2e2dSJohn Marino     }
7474a45ae5f8SJohn Marino   else
7475a45ae5f8SJohn Marino     {
7476cf7f2e2dSJohn Marino       if (msg)
7477cf7f2e2dSJohn Marino 	*msg = NULL;
7478cf7f2e2dSJohn Marino       return 1;
7479cf7f2e2dSJohn Marino     }
7480a45ae5f8SJohn Marino }
7481cf7f2e2dSJohn Marino 
7482cf7f2e2dSJohn Marino static int
i386_validate_tdesc_p(struct gdbarch_tdep * tdep,struct tdesc_arch_data * tdesc_data)7483cf7f2e2dSJohn Marino i386_validate_tdesc_p (struct gdbarch_tdep *tdep,
7484cf7f2e2dSJohn Marino 		       struct tdesc_arch_data *tdesc_data)
7485cf7f2e2dSJohn Marino {
7486cf7f2e2dSJohn Marino   const struct target_desc *tdesc = tdep->tdesc;
7487cf7f2e2dSJohn Marino   const struct tdesc_feature *feature_core;
7488cf7f2e2dSJohn Marino   const struct tdesc_feature *feature_sse, *feature_avx;
7489cf7f2e2dSJohn Marino   int i, num_regs, valid_p;
7490cf7f2e2dSJohn Marino 
7491cf7f2e2dSJohn Marino   if (! tdesc_has_registers (tdesc))
7492cf7f2e2dSJohn Marino     return 0;
7493cf7f2e2dSJohn Marino 
7494cf7f2e2dSJohn Marino   /* Get core registers.  */
7495cf7f2e2dSJohn Marino   feature_core = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.core");
7496cf7f2e2dSJohn Marino   if (feature_core == NULL)
7497cf7f2e2dSJohn Marino     return 0;
7498cf7f2e2dSJohn Marino 
7499cf7f2e2dSJohn Marino   /* Get SSE registers.  */
7500cf7f2e2dSJohn Marino   feature_sse = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.sse");
7501cf7f2e2dSJohn Marino 
7502cf7f2e2dSJohn Marino   /* Try AVX registers.  */
7503cf7f2e2dSJohn Marino   feature_avx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx");
7504cf7f2e2dSJohn Marino 
7505cf7f2e2dSJohn Marino   valid_p = 1;
7506cf7f2e2dSJohn Marino 
7507cf7f2e2dSJohn Marino   /* The XCR0 bits.  */
7508cf7f2e2dSJohn Marino   if (feature_avx)
7509cf7f2e2dSJohn Marino     {
7510cf7f2e2dSJohn Marino       /* AVX register description requires SSE register description.  */
7511cf7f2e2dSJohn Marino       if (!feature_sse)
7512cf7f2e2dSJohn Marino 	return 0;
7513cf7f2e2dSJohn Marino 
7514cf7f2e2dSJohn Marino       tdep->xcr0 = I386_XSTATE_AVX_MASK;
7515cf7f2e2dSJohn Marino 
7516cf7f2e2dSJohn Marino       /* It may have been set by OSABI initialization function.  */
7517cf7f2e2dSJohn Marino       if (tdep->num_ymm_regs == 0)
7518cf7f2e2dSJohn Marino 	{
7519cf7f2e2dSJohn Marino 	  tdep->ymmh_register_names = i386_ymmh_names;
7520cf7f2e2dSJohn Marino 	  tdep->num_ymm_regs = 8;
7521cf7f2e2dSJohn Marino 	  tdep->ymm0h_regnum = I386_YMM0H_REGNUM;
7522cf7f2e2dSJohn Marino 	}
7523cf7f2e2dSJohn Marino 
7524cf7f2e2dSJohn Marino       for (i = 0; i < tdep->num_ymm_regs; i++)
7525cf7f2e2dSJohn Marino 	valid_p &= tdesc_numbered_register (feature_avx, tdesc_data,
7526cf7f2e2dSJohn Marino 					    tdep->ymm0h_regnum + i,
7527cf7f2e2dSJohn Marino 					    tdep->ymmh_register_names[i]);
7528cf7f2e2dSJohn Marino     }
7529cf7f2e2dSJohn Marino   else if (feature_sse)
7530cf7f2e2dSJohn Marino     tdep->xcr0 = I386_XSTATE_SSE_MASK;
7531cf7f2e2dSJohn Marino   else
7532cf7f2e2dSJohn Marino     {
7533cf7f2e2dSJohn Marino       tdep->xcr0 = I386_XSTATE_X87_MASK;
7534cf7f2e2dSJohn Marino       tdep->num_xmm_regs = 0;
7535cf7f2e2dSJohn Marino     }
7536cf7f2e2dSJohn Marino 
7537cf7f2e2dSJohn Marino   num_regs = tdep->num_core_regs;
7538cf7f2e2dSJohn Marino   for (i = 0; i < num_regs; i++)
7539cf7f2e2dSJohn Marino     valid_p &= tdesc_numbered_register (feature_core, tdesc_data, i,
7540cf7f2e2dSJohn Marino 					tdep->register_names[i]);
7541cf7f2e2dSJohn Marino 
7542cf7f2e2dSJohn Marino   if (feature_sse)
7543cf7f2e2dSJohn Marino     {
7544cf7f2e2dSJohn Marino       /* Need to include %mxcsr, so add one.  */
7545cf7f2e2dSJohn Marino       num_regs += tdep->num_xmm_regs + 1;
7546cf7f2e2dSJohn Marino       for (; i < num_regs; i++)
7547cf7f2e2dSJohn Marino 	valid_p &= tdesc_numbered_register (feature_sse, tdesc_data, i,
7548cf7f2e2dSJohn Marino 					    tdep->register_names[i]);
7549cf7f2e2dSJohn Marino     }
7550cf7f2e2dSJohn Marino 
7551cf7f2e2dSJohn Marino   return valid_p;
7552cf7f2e2dSJohn Marino }
7553cf7f2e2dSJohn Marino 
75545796c8dcSSimon Schubert 
75555796c8dcSSimon Schubert static struct gdbarch *
i386_gdbarch_init(struct gdbarch_info info,struct gdbarch_list * arches)75565796c8dcSSimon Schubert i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
75575796c8dcSSimon Schubert {
75585796c8dcSSimon Schubert   struct gdbarch_tdep *tdep;
75595796c8dcSSimon Schubert   struct gdbarch *gdbarch;
7560cf7f2e2dSJohn Marino   struct tdesc_arch_data *tdesc_data;
7561cf7f2e2dSJohn Marino   const struct target_desc *tdesc;
7562cf7f2e2dSJohn Marino   int mm0_regnum;
7563cf7f2e2dSJohn Marino   int ymm0_regnum;
75645796c8dcSSimon Schubert 
75655796c8dcSSimon Schubert   /* If there is already a candidate, use it.  */
75665796c8dcSSimon Schubert   arches = gdbarch_list_lookup_by_info (arches, &info);
75675796c8dcSSimon Schubert   if (arches != NULL)
75685796c8dcSSimon Schubert     return arches->gdbarch;
75695796c8dcSSimon Schubert 
75705796c8dcSSimon Schubert   /* Allocate space for the new architecture.  */
75715796c8dcSSimon Schubert   tdep = XCALLOC (1, struct gdbarch_tdep);
75725796c8dcSSimon Schubert   gdbarch = gdbarch_alloc (&info, tdep);
75735796c8dcSSimon Schubert 
75745796c8dcSSimon Schubert   /* General-purpose registers.  */
75755796c8dcSSimon Schubert   tdep->gregset = NULL;
75765796c8dcSSimon Schubert   tdep->gregset_reg_offset = NULL;
75775796c8dcSSimon Schubert   tdep->gregset_num_regs = I386_NUM_GREGS;
75785796c8dcSSimon Schubert   tdep->sizeof_gregset = 0;
75795796c8dcSSimon Schubert 
75805796c8dcSSimon Schubert   /* Floating-point registers.  */
75815796c8dcSSimon Schubert   tdep->fpregset = NULL;
75825796c8dcSSimon Schubert   tdep->sizeof_fpregset = I387_SIZEOF_FSAVE;
75835796c8dcSSimon Schubert 
7584cf7f2e2dSJohn Marino   tdep->xstateregset = NULL;
7585cf7f2e2dSJohn Marino 
75865796c8dcSSimon Schubert   /* The default settings include the FPU registers, the MMX registers
75875796c8dcSSimon Schubert      and the SSE registers.  This can be overridden for a specific ABI
75885796c8dcSSimon Schubert      by adjusting the members `st0_regnum', `mm0_regnum' and
75895796c8dcSSimon Schubert      `num_xmm_regs' of `struct gdbarch_tdep', otherwise the registers
7590cf7f2e2dSJohn Marino      will show up in the output of "info all-registers".  */
75915796c8dcSSimon Schubert 
75925796c8dcSSimon Schubert   tdep->st0_regnum = I386_ST0_REGNUM;
75935796c8dcSSimon Schubert 
75945796c8dcSSimon Schubert   /* I386_NUM_XREGS includes %mxcsr, so substract one.  */
75955796c8dcSSimon Schubert   tdep->num_xmm_regs = I386_NUM_XREGS - 1;
75965796c8dcSSimon Schubert 
75975796c8dcSSimon Schubert   tdep->jb_pc_offset = -1;
75985796c8dcSSimon Schubert   tdep->struct_return = pcc_struct_return;
75995796c8dcSSimon Schubert   tdep->sigtramp_start = 0;
76005796c8dcSSimon Schubert   tdep->sigtramp_end = 0;
76015796c8dcSSimon Schubert   tdep->sigtramp_p = i386_sigtramp_p;
76025796c8dcSSimon Schubert   tdep->sigcontext_addr = NULL;
76035796c8dcSSimon Schubert   tdep->sc_reg_offset = NULL;
76045796c8dcSSimon Schubert   tdep->sc_pc_offset = -1;
76055796c8dcSSimon Schubert   tdep->sc_sp_offset = -1;
76065796c8dcSSimon Schubert 
7607cf7f2e2dSJohn Marino   tdep->xsave_xcr0_offset = -1;
7608cf7f2e2dSJohn Marino 
76095796c8dcSSimon Schubert   tdep->record_regmap = i386_record_regmap;
76105796c8dcSSimon Schubert 
7611a45ae5f8SJohn Marino   set_gdbarch_long_long_align_bit (gdbarch, 32);
7612a45ae5f8SJohn Marino 
76135796c8dcSSimon Schubert   /* The format used for `long double' on almost all i386 targets is
76145796c8dcSSimon Schubert      the i387 extended floating-point format.  In fact, of all targets
76155796c8dcSSimon Schubert      in the GCC 2.95 tree, only OSF/1 does it different, and insists
76165796c8dcSSimon Schubert      on having a `long double' that's not `long' at all.  */
76175796c8dcSSimon Schubert   set_gdbarch_long_double_format (gdbarch, floatformats_i387_ext);
76185796c8dcSSimon Schubert 
76195796c8dcSSimon Schubert   /* Although the i387 extended floating-point has only 80 significant
76205796c8dcSSimon Schubert      bits, a `long double' actually takes up 96, probably to enforce
76215796c8dcSSimon Schubert      alignment.  */
76225796c8dcSSimon Schubert   set_gdbarch_long_double_bit (gdbarch, 96);
76235796c8dcSSimon Schubert 
76245796c8dcSSimon Schubert   /* Register numbers of various important registers.  */
76255796c8dcSSimon Schubert   set_gdbarch_sp_regnum (gdbarch, I386_ESP_REGNUM); /* %esp */
76265796c8dcSSimon Schubert   set_gdbarch_pc_regnum (gdbarch, I386_EIP_REGNUM); /* %eip */
76275796c8dcSSimon Schubert   set_gdbarch_ps_regnum (gdbarch, I386_EFLAGS_REGNUM); /* %eflags */
76285796c8dcSSimon Schubert   set_gdbarch_fp0_regnum (gdbarch, I386_ST0_REGNUM); /* %st(0) */
76295796c8dcSSimon Schubert 
76305796c8dcSSimon Schubert   /* NOTE: kettenis/20040418: GCC does have two possible register
76315796c8dcSSimon Schubert      numbering schemes on the i386: dbx and SVR4.  These schemes
76325796c8dcSSimon Schubert      differ in how they number %ebp, %esp, %eflags, and the
76335796c8dcSSimon Schubert      floating-point registers, and are implemented by the arrays
76345796c8dcSSimon Schubert      dbx_register_map[] and svr4_dbx_register_map in
76355796c8dcSSimon Schubert      gcc/config/i386.c.  GCC also defines a third numbering scheme in
76365796c8dcSSimon Schubert      gcc/config/i386.c, which it designates as the "default" register
76375796c8dcSSimon Schubert      map used in 64bit mode.  This last register numbering scheme is
76385796c8dcSSimon Schubert      implemented in dbx64_register_map, and is used for AMD64; see
76395796c8dcSSimon Schubert      amd64-tdep.c.
76405796c8dcSSimon Schubert 
76415796c8dcSSimon Schubert      Currently, each GCC i386 target always uses the same register
76425796c8dcSSimon Schubert      numbering scheme across all its supported debugging formats
76435796c8dcSSimon Schubert      i.e. SDB (COFF), stabs and DWARF 2.  This is because
76445796c8dcSSimon Schubert      gcc/sdbout.c, gcc/dbxout.c and gcc/dwarf2out.c all use the
76455796c8dcSSimon Schubert      DBX_REGISTER_NUMBER macro which is defined by each target's
76465796c8dcSSimon Schubert      respective config header in a manner independent of the requested
76475796c8dcSSimon Schubert      output debugging format.
76485796c8dcSSimon Schubert 
76495796c8dcSSimon Schubert      This does not match the arrangement below, which presumes that
76505796c8dcSSimon Schubert      the SDB and stabs numbering schemes differ from the DWARF and
76515796c8dcSSimon Schubert      DWARF 2 ones.  The reason for this arrangement is that it is
76525796c8dcSSimon Schubert      likely to get the numbering scheme for the target's
76535796c8dcSSimon Schubert      default/native debug format right.  For targets where GCC is the
76545796c8dcSSimon Schubert      native compiler (FreeBSD, NetBSD, OpenBSD, GNU/Linux) or for
76555796c8dcSSimon Schubert      targets where the native toolchain uses a different numbering
76565796c8dcSSimon Schubert      scheme for a particular debug format (stabs-in-ELF on Solaris)
76575796c8dcSSimon Schubert      the defaults below will have to be overridden, like
76585796c8dcSSimon Schubert      i386_elf_init_abi() does.  */
76595796c8dcSSimon Schubert 
76605796c8dcSSimon Schubert   /* Use the dbx register numbering scheme for stabs and COFF.  */
76615796c8dcSSimon Schubert   set_gdbarch_stab_reg_to_regnum (gdbarch, i386_dbx_reg_to_regnum);
76625796c8dcSSimon Schubert   set_gdbarch_sdb_reg_to_regnum (gdbarch, i386_dbx_reg_to_regnum);
76635796c8dcSSimon Schubert 
76645796c8dcSSimon Schubert   /* Use the SVR4 register numbering scheme for DWARF 2.  */
76655796c8dcSSimon Schubert   set_gdbarch_dwarf2_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
76665796c8dcSSimon Schubert 
76675796c8dcSSimon Schubert   /* We don't set gdbarch_stab_reg_to_regnum, since ECOFF doesn't seem to
76685796c8dcSSimon Schubert      be in use on any of the supported i386 targets.  */
76695796c8dcSSimon Schubert 
76705796c8dcSSimon Schubert   set_gdbarch_print_float_info (gdbarch, i387_print_float_info);
76715796c8dcSSimon Schubert 
76725796c8dcSSimon Schubert   set_gdbarch_get_longjmp_target (gdbarch, i386_get_longjmp_target);
76735796c8dcSSimon Schubert 
76745796c8dcSSimon Schubert   /* Call dummy code.  */
7675*ef5ccd6cSJohn Marino   set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
7676*ef5ccd6cSJohn Marino   set_gdbarch_push_dummy_code (gdbarch, i386_push_dummy_code);
76775796c8dcSSimon Schubert   set_gdbarch_push_dummy_call (gdbarch, i386_push_dummy_call);
7678a45ae5f8SJohn Marino   set_gdbarch_frame_align (gdbarch, i386_frame_align);
76795796c8dcSSimon Schubert 
76805796c8dcSSimon Schubert   set_gdbarch_convert_register_p (gdbarch, i386_convert_register_p);
76815796c8dcSSimon Schubert   set_gdbarch_register_to_value (gdbarch,  i386_register_to_value);
76825796c8dcSSimon Schubert   set_gdbarch_value_to_register (gdbarch, i386_value_to_register);
76835796c8dcSSimon Schubert 
76845796c8dcSSimon Schubert   set_gdbarch_return_value (gdbarch, i386_return_value);
76855796c8dcSSimon Schubert 
76865796c8dcSSimon Schubert   set_gdbarch_skip_prologue (gdbarch, i386_skip_prologue);
76875796c8dcSSimon Schubert 
76885796c8dcSSimon Schubert   /* Stack grows downward.  */
76895796c8dcSSimon Schubert   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
76905796c8dcSSimon Schubert 
76915796c8dcSSimon Schubert   set_gdbarch_breakpoint_from_pc (gdbarch, i386_breakpoint_from_pc);
76925796c8dcSSimon Schubert   set_gdbarch_decr_pc_after_break (gdbarch, 1);
76935796c8dcSSimon Schubert   set_gdbarch_max_insn_length (gdbarch, I386_MAX_INSN_LEN);
76945796c8dcSSimon Schubert 
76955796c8dcSSimon Schubert   set_gdbarch_frame_args_skip (gdbarch, 8);
76965796c8dcSSimon Schubert 
76975796c8dcSSimon Schubert   set_gdbarch_print_insn (gdbarch, i386_print_insn);
76985796c8dcSSimon Schubert 
76995796c8dcSSimon Schubert   set_gdbarch_dummy_id (gdbarch, i386_dummy_id);
77005796c8dcSSimon Schubert 
77015796c8dcSSimon Schubert   set_gdbarch_unwind_pc (gdbarch, i386_unwind_pc);
77025796c8dcSSimon Schubert 
77035796c8dcSSimon Schubert   /* Add the i386 register groups.  */
77045796c8dcSSimon Schubert   i386_add_reggroups (gdbarch);
7705cf7f2e2dSJohn Marino   tdep->register_reggroup_p = i386_register_reggroup_p;
77065796c8dcSSimon Schubert 
77075796c8dcSSimon Schubert   /* Helper for function argument information.  */
77085796c8dcSSimon Schubert   set_gdbarch_fetch_pointer_argument (gdbarch, i386_fetch_pointer_argument);
77095796c8dcSSimon Schubert 
77105796c8dcSSimon Schubert   /* Hook the function epilogue frame unwinder.  This unwinder is
7711a45ae5f8SJohn Marino      appended to the list first, so that it supercedes the DWARF
7712a45ae5f8SJohn Marino      unwinder in function epilogues (where the DWARF unwinder
77135796c8dcSSimon Schubert      currently fails).  */
77145796c8dcSSimon Schubert   frame_unwind_append_unwinder (gdbarch, &i386_epilogue_frame_unwind);
77155796c8dcSSimon Schubert 
77165796c8dcSSimon Schubert   /* Hook in the DWARF CFI frame unwinder.  This unwinder is appended
7717a45ae5f8SJohn Marino      to the list before the prologue-based unwinders, so that DWARF
77185796c8dcSSimon Schubert      CFI info will be used if it is available.  */
77195796c8dcSSimon Schubert   dwarf2_append_unwinders (gdbarch);
77205796c8dcSSimon Schubert 
77215796c8dcSSimon Schubert   frame_base_set_default (gdbarch, &i386_frame_base);
77225796c8dcSSimon Schubert 
7723cf7f2e2dSJohn Marino   /* Pseudo registers may be changed by amd64_init_abi.  */
7724a45ae5f8SJohn Marino   set_gdbarch_pseudo_register_read_value (gdbarch,
7725a45ae5f8SJohn Marino 					  i386_pseudo_register_read_value);
7726cf7f2e2dSJohn Marino   set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write);
7727cf7f2e2dSJohn Marino 
7728cf7f2e2dSJohn Marino   set_tdesc_pseudo_register_type (gdbarch, i386_pseudo_register_type);
7729cf7f2e2dSJohn Marino   set_tdesc_pseudo_register_name (gdbarch, i386_pseudo_register_name);
7730cf7f2e2dSJohn Marino 
7731cf7f2e2dSJohn Marino   /* Override the normal target description method to make the AVX
7732cf7f2e2dSJohn Marino      upper halves anonymous.  */
7733cf7f2e2dSJohn Marino   set_gdbarch_register_name (gdbarch, i386_register_name);
7734cf7f2e2dSJohn Marino 
7735cf7f2e2dSJohn Marino   /* Even though the default ABI only includes general-purpose registers,
7736cf7f2e2dSJohn Marino      floating-point registers and the SSE registers, we have to leave a
7737cf7f2e2dSJohn Marino      gap for the upper AVX registers.  */
7738cf7f2e2dSJohn Marino   set_gdbarch_num_regs (gdbarch, I386_AVX_NUM_REGS);
7739cf7f2e2dSJohn Marino 
7740cf7f2e2dSJohn Marino   /* Get the x86 target description from INFO.  */
7741cf7f2e2dSJohn Marino   tdesc = info.target_desc;
7742cf7f2e2dSJohn Marino   if (! tdesc_has_registers (tdesc))
7743cf7f2e2dSJohn Marino     tdesc = tdesc_i386;
7744cf7f2e2dSJohn Marino   tdep->tdesc = tdesc;
7745cf7f2e2dSJohn Marino 
7746cf7f2e2dSJohn Marino   tdep->num_core_regs = I386_NUM_GREGS + I387_NUM_REGS;
7747cf7f2e2dSJohn Marino   tdep->register_names = i386_register_names;
7748cf7f2e2dSJohn Marino 
7749cf7f2e2dSJohn Marino   /* No upper YMM registers.  */
7750cf7f2e2dSJohn Marino   tdep->ymmh_register_names = NULL;
7751cf7f2e2dSJohn Marino   tdep->ymm0h_regnum = -1;
7752cf7f2e2dSJohn Marino 
7753cf7f2e2dSJohn Marino   tdep->num_byte_regs = 8;
7754cf7f2e2dSJohn Marino   tdep->num_word_regs = 8;
7755cf7f2e2dSJohn Marino   tdep->num_dword_regs = 0;
7756cf7f2e2dSJohn Marino   tdep->num_mmx_regs = 8;
7757cf7f2e2dSJohn Marino   tdep->num_ymm_regs = 0;
7758cf7f2e2dSJohn Marino 
7759cf7f2e2dSJohn Marino   tdesc_data = tdesc_data_alloc ();
7760cf7f2e2dSJohn Marino 
7761cf7f2e2dSJohn Marino   set_gdbarch_relocate_instruction (gdbarch, i386_relocate_instruction);
7762cf7f2e2dSJohn Marino 
7763a45ae5f8SJohn Marino   set_gdbarch_gen_return_address (gdbarch, i386_gen_return_address);
7764a45ae5f8SJohn Marino 
77655796c8dcSSimon Schubert   /* Hook in ABI-specific overrides, if they have been registered.  */
7766cf7f2e2dSJohn Marino   info.tdep_info = (void *) tdesc_data;
77675796c8dcSSimon Schubert   gdbarch_init_osabi (info, gdbarch);
77685796c8dcSSimon Schubert 
7769cf7f2e2dSJohn Marino   if (!i386_validate_tdesc_p (tdep, tdesc_data))
7770cf7f2e2dSJohn Marino     {
7771cf7f2e2dSJohn Marino       tdesc_data_cleanup (tdesc_data);
7772cf7f2e2dSJohn Marino       xfree (tdep);
7773cf7f2e2dSJohn Marino       gdbarch_free (gdbarch);
7774cf7f2e2dSJohn Marino       return NULL;
7775cf7f2e2dSJohn Marino     }
7776cf7f2e2dSJohn Marino 
7777cf7f2e2dSJohn Marino   /* Wire in pseudo registers.  Number of pseudo registers may be
7778cf7f2e2dSJohn Marino      changed.  */
7779cf7f2e2dSJohn Marino   set_gdbarch_num_pseudo_regs (gdbarch, (tdep->num_byte_regs
7780cf7f2e2dSJohn Marino 					 + tdep->num_word_regs
7781cf7f2e2dSJohn Marino 					 + tdep->num_dword_regs
7782cf7f2e2dSJohn Marino 					 + tdep->num_mmx_regs
7783cf7f2e2dSJohn Marino 					 + tdep->num_ymm_regs));
7784cf7f2e2dSJohn Marino 
7785cf7f2e2dSJohn Marino   /* Target description may be changed.  */
7786cf7f2e2dSJohn Marino   tdesc = tdep->tdesc;
7787cf7f2e2dSJohn Marino 
7788cf7f2e2dSJohn Marino   tdesc_use_registers (gdbarch, tdesc, tdesc_data);
7789cf7f2e2dSJohn Marino 
7790cf7f2e2dSJohn Marino   /* Override gdbarch_register_reggroup_p set in tdesc_use_registers.  */
7791cf7f2e2dSJohn Marino   set_gdbarch_register_reggroup_p (gdbarch, tdep->register_reggroup_p);
7792cf7f2e2dSJohn Marino 
7793cf7f2e2dSJohn Marino   /* Make %al the first pseudo-register.  */
7794cf7f2e2dSJohn Marino   tdep->al_regnum = gdbarch_num_regs (gdbarch);
7795cf7f2e2dSJohn Marino   tdep->ax_regnum = tdep->al_regnum + tdep->num_byte_regs;
7796cf7f2e2dSJohn Marino 
7797cf7f2e2dSJohn Marino   ymm0_regnum = tdep->ax_regnum + tdep->num_word_regs;
7798cf7f2e2dSJohn Marino   if (tdep->num_dword_regs)
7799cf7f2e2dSJohn Marino     {
7800c50c785cSJohn Marino       /* Support dword pseudo-register if it hasn't been disabled.  */
7801cf7f2e2dSJohn Marino       tdep->eax_regnum = ymm0_regnum;
7802cf7f2e2dSJohn Marino       ymm0_regnum += tdep->num_dword_regs;
7803cf7f2e2dSJohn Marino     }
7804cf7f2e2dSJohn Marino   else
7805cf7f2e2dSJohn Marino     tdep->eax_regnum = -1;
7806cf7f2e2dSJohn Marino 
7807cf7f2e2dSJohn Marino   mm0_regnum = ymm0_regnum;
7808cf7f2e2dSJohn Marino   if (tdep->num_ymm_regs)
7809cf7f2e2dSJohn Marino     {
7810c50c785cSJohn Marino       /* Support YMM pseudo-register if it is available.  */
7811cf7f2e2dSJohn Marino       tdep->ymm0_regnum = ymm0_regnum;
7812cf7f2e2dSJohn Marino       mm0_regnum += tdep->num_ymm_regs;
7813cf7f2e2dSJohn Marino     }
7814cf7f2e2dSJohn Marino   else
7815cf7f2e2dSJohn Marino     tdep->ymm0_regnum = -1;
7816cf7f2e2dSJohn Marino 
7817cf7f2e2dSJohn Marino   if (tdep->num_mmx_regs != 0)
7818cf7f2e2dSJohn Marino     {
7819c50c785cSJohn Marino       /* Support MMX pseudo-register if MMX hasn't been disabled.  */
7820cf7f2e2dSJohn Marino       tdep->mm0_regnum = mm0_regnum;
7821cf7f2e2dSJohn Marino     }
7822cf7f2e2dSJohn Marino   else
7823cf7f2e2dSJohn Marino     tdep->mm0_regnum = -1;
7824cf7f2e2dSJohn Marino 
78255796c8dcSSimon Schubert   /* Hook in the legacy prologue-based unwinders last (fallback).  */
7826a45ae5f8SJohn Marino   frame_unwind_append_unwinder (gdbarch, &i386_stack_tramp_frame_unwind);
78275796c8dcSSimon Schubert   frame_unwind_append_unwinder (gdbarch, &i386_sigtramp_frame_unwind);
78285796c8dcSSimon Schubert   frame_unwind_append_unwinder (gdbarch, &i386_frame_unwind);
78295796c8dcSSimon Schubert 
78305796c8dcSSimon Schubert   /* If we have a register mapping, enable the generic core file
78315796c8dcSSimon Schubert      support, unless it has already been enabled.  */
78325796c8dcSSimon Schubert   if (tdep->gregset_reg_offset
78335796c8dcSSimon Schubert       && !gdbarch_regset_from_core_section_p (gdbarch))
78345796c8dcSSimon Schubert     set_gdbarch_regset_from_core_section (gdbarch,
78355796c8dcSSimon Schubert 					  i386_regset_from_core_section);
78365796c8dcSSimon Schubert 
78375796c8dcSSimon Schubert   set_gdbarch_skip_permanent_breakpoint (gdbarch,
78385796c8dcSSimon Schubert 					 i386_skip_permanent_breakpoint);
78395796c8dcSSimon Schubert 
7840cf7f2e2dSJohn Marino   set_gdbarch_fast_tracepoint_valid_at (gdbarch,
7841cf7f2e2dSJohn Marino 					i386_fast_tracepoint_valid_at);
7842cf7f2e2dSJohn Marino 
78435796c8dcSSimon Schubert   return gdbarch;
78445796c8dcSSimon Schubert }
78455796c8dcSSimon Schubert 
78465796c8dcSSimon Schubert static enum gdb_osabi
i386_coff_osabi_sniffer(bfd * abfd)78475796c8dcSSimon Schubert i386_coff_osabi_sniffer (bfd *abfd)
78485796c8dcSSimon Schubert {
78495796c8dcSSimon Schubert   if (strcmp (bfd_get_target (abfd), "coff-go32-exe") == 0
78505796c8dcSSimon Schubert       || strcmp (bfd_get_target (abfd), "coff-go32") == 0)
78515796c8dcSSimon Schubert     return GDB_OSABI_GO32;
78525796c8dcSSimon Schubert 
78535796c8dcSSimon Schubert   return GDB_OSABI_UNKNOWN;
78545796c8dcSSimon Schubert }
78555796c8dcSSimon Schubert 
78565796c8dcSSimon Schubert 
78575796c8dcSSimon Schubert /* Provide a prototype to silence -Wmissing-prototypes.  */
78585796c8dcSSimon Schubert void _initialize_i386_tdep (void);
78595796c8dcSSimon Schubert 
78605796c8dcSSimon Schubert void
_initialize_i386_tdep(void)78615796c8dcSSimon Schubert _initialize_i386_tdep (void)
78625796c8dcSSimon Schubert {
78635796c8dcSSimon Schubert   register_gdbarch_init (bfd_arch_i386, i386_gdbarch_init);
78645796c8dcSSimon Schubert 
78655796c8dcSSimon Schubert   /* Add the variable that controls the disassembly flavor.  */
78665796c8dcSSimon Schubert   add_setshow_enum_cmd ("disassembly-flavor", no_class, valid_flavors,
78675796c8dcSSimon Schubert 			&disassembly_flavor, _("\
78685796c8dcSSimon Schubert Set the disassembly flavor."), _("\
78695796c8dcSSimon Schubert Show the disassembly flavor."), _("\
78705796c8dcSSimon Schubert The valid values are \"att\" and \"intel\", and the default value is \"att\"."),
78715796c8dcSSimon Schubert 			NULL,
78725796c8dcSSimon Schubert 			NULL, /* FIXME: i18n: */
78735796c8dcSSimon Schubert 			&setlist, &showlist);
78745796c8dcSSimon Schubert 
78755796c8dcSSimon Schubert   /* Add the variable that controls the convention for returning
78765796c8dcSSimon Schubert      structs.  */
78775796c8dcSSimon Schubert   add_setshow_enum_cmd ("struct-convention", no_class, valid_conventions,
78785796c8dcSSimon Schubert 			&struct_convention, _("\
78795796c8dcSSimon Schubert Set the convention for returning small structs."), _("\
78805796c8dcSSimon Schubert Show the convention for returning small structs."), _("\
78815796c8dcSSimon Schubert Valid values are \"default\", \"pcc\" and \"reg\", and the default value\n\
78825796c8dcSSimon Schubert is \"default\"."),
78835796c8dcSSimon Schubert 			NULL,
78845796c8dcSSimon Schubert 			NULL, /* FIXME: i18n: */
78855796c8dcSSimon Schubert 			&setlist, &showlist);
78865796c8dcSSimon Schubert 
78875796c8dcSSimon Schubert   gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
78885796c8dcSSimon Schubert 				  i386_coff_osabi_sniffer);
78895796c8dcSSimon Schubert 
78905796c8dcSSimon Schubert   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_SVR4,
78915796c8dcSSimon Schubert 			  i386_svr4_init_abi);
78925796c8dcSSimon Schubert   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_GO32,
78935796c8dcSSimon Schubert 			  i386_go32_init_abi);
78945796c8dcSSimon Schubert 
78955796c8dcSSimon Schubert   /* Initialize the i386-specific register groups.  */
78965796c8dcSSimon Schubert   i386_init_reggroups ();
7897cf7f2e2dSJohn Marino 
7898cf7f2e2dSJohn Marino   /* Initialize the standard target descriptions.  */
7899cf7f2e2dSJohn Marino   initialize_tdesc_i386 ();
7900cf7f2e2dSJohn Marino   initialize_tdesc_i386_mmx ();
7901cf7f2e2dSJohn Marino   initialize_tdesc_i386_avx ();
7902cf7f2e2dSJohn Marino 
7903cf7f2e2dSJohn Marino   /* Tell remote stub that we support XML target description.  */
7904cf7f2e2dSJohn Marino   register_remote_support_xml ("i386");
79055796c8dcSSimon Schubert }
7906