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