+ indirect ? lookup_minimal_symbol_by_pc (indirect).minsym : 0;
+ const char *symname = indsym ? MSYMBOL_LINKAGE_NAME (indsym) : 0;
+
+ if (symname)
+ {
+ if (strncmp (symname, "__imp_", 6) == 0
+ || strncmp (symname, "_imp_", 5) == 0)
+ return name ? 1 :
+ read_memory_unsigned_integer (indirect, 4, byte_order);
+ }
+ }
+ return 0; /* Not a trampoline. */
+}
+\f
+
+/* Return whether the THIS_FRAME corresponds to a sigtramp
+ routine. */
+
+int
+i386_sigtramp_p (struct frame_info *this_frame)
+{
+ CORE_ADDR pc = get_frame_pc (this_frame);
+ const char *name;
+
+ find_pc_partial_function (pc, &name, NULL, NULL);
+ return (name && strcmp ("_sigtramp", name) == 0);
+}
+\f
+
+/* We have two flavours of disassembly. The machinery on this page
+ deals with switching between those. */
+
+static int
+i386_print_insn (bfd_vma pc, struct disassemble_info *info)
+{
+ gdb_assert (disassembly_flavor == att_flavor
+ || disassembly_flavor == intel_flavor);
+
+ /* FIXME: kettenis/20020915: Until disassembler_options is properly
+ constified, cast to prevent a compiler warning. */
+ info->disassembler_options = (char *) disassembly_flavor;
+
+ return print_insn_i386 (pc, info);
+}
+\f
+
+/* There are a few i386 architecture variants that differ only
+ slightly from the generic i386 target. For now, we don't give them
+ their own source file, but include them here. As a consequence,
+ they'll always be included. */
+
+/* System V Release 4 (SVR4). */
+
+/* Return whether THIS_FRAME corresponds to a SVR4 sigtramp
+ routine. */
+
+static int
+i386_svr4_sigtramp_p (struct frame_info *this_frame)
+{
+ CORE_ADDR pc = get_frame_pc (this_frame);
+ const char *name;
+
+ /* The origin of these symbols is currently unknown. */
+ find_pc_partial_function (pc, &name, NULL, NULL);
+ return (name && (strcmp ("_sigreturn", name) == 0
+ || strcmp ("sigvechandler", name) == 0));
+}
+
+/* Assuming THIS_FRAME is for a SVR4 sigtramp routine, return the
+ address of the associated sigcontext (ucontext) structure. */
+
+static CORE_ADDR
+i386_svr4_sigcontext_addr (struct frame_info *this_frame)
+{
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ gdb_byte buf[4];
+ CORE_ADDR sp;
+
+ get_frame_register (this_frame, I386_ESP_REGNUM, buf);
+ sp = extract_unsigned_integer (buf, 4, byte_order);
+
+ return read_memory_unsigned_integer (sp + 8, 4, byte_order);
+}
+
+\f
+
+/* Implementation of `gdbarch_stap_is_single_operand', as defined in
+ gdbarch.h. */
+
+int
+i386_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
+{
+ return (*s == '$' /* Literal number. */
+ || (isdigit (*s) && s[1] == '(' && s[2] == '%') /* Displacement. */
+ || (*s == '(' && s[1] == '%') /* Register indirection. */
+ || (*s == '%' && isalpha (s[1]))); /* Register access. */
+}
+
+/* Helper function for i386_stap_parse_special_token.
+
+ This function parses operands of the form `-8+3+1(%rbp)', which
+ must be interpreted as `*(-8 + 3 - 1 + (void *) $eax)'.
+
+ Return 1 if the operand was parsed successfully, zero
+ otherwise. */
+
+static int
+i386_stap_parse_special_token_triplet (struct gdbarch *gdbarch,
+ struct stap_parse_info *p)
+{
+ const char *s = p->arg;
+
+ if (isdigit (*s) || *s == '-' || *s == '+')
+ {
+ int got_minus[3];
+ int i;
+ long displacements[3];
+ const char *start;
+ char *regname;
+ int len;
+ struct stoken str;
+ char *endp;
+
+ got_minus[0] = 0;
+ if (*s == '+')
+ ++s;
+ else if (*s == '-')
+ {
+ ++s;
+ got_minus[0] = 1;
+ }
+
+ if (!isdigit ((unsigned char) *s))
+ return 0;
+
+ displacements[0] = strtol (s, &endp, 10);
+ s = endp;
+
+ if (*s != '+' && *s != '-')
+ {
+ /* We are not dealing with a triplet. */
+ return 0;
+ }
+
+ got_minus[1] = 0;
+ if (*s == '+')
+ ++s;
+ else
+ {
+ ++s;
+ got_minus[1] = 1;
+ }
+
+ if (!isdigit ((unsigned char) *s))
+ return 0;
+
+ displacements[1] = strtol (s, &endp, 10);
+ s = endp;
+
+ if (*s != '+' && *s != '-')
+ {
+ /* We are not dealing with a triplet. */
+ return 0;
+ }
+
+ got_minus[2] = 0;
+ if (*s == '+')
+ ++s;
+ else
+ {
+ ++s;
+ got_minus[2] = 1;
+ }
+
+ if (!isdigit ((unsigned char) *s))
+ return 0;
+
+ displacements[2] = strtol (s, &endp, 10);
+ s = endp;
+
+ if (*s != '(' || s[1] != '%')
+ return 0;
+
+ s += 2;
+ start = s;
+
+ while (isalnum (*s))
+ ++s;
+
+ if (*s++ != ')')
+ return 0;
+
+ len = s - start - 1;
+ regname = alloca (len + 1);
+
+ strncpy (regname, start, len);
+ regname[len] = '\0';
+
+ if (user_reg_map_name_to_regnum (gdbarch, regname, len) == -1)
+ error (_("Invalid register name `%s' on expression `%s'."),
+ regname, p->saved_arg);
+
+ for (i = 0; i < 3; i++)
+ {
+ write_exp_elt_opcode (&p->pstate, OP_LONG);
+ write_exp_elt_type
+ (&p->pstate, builtin_type (gdbarch)->builtin_long);
+ write_exp_elt_longcst (&p->pstate, displacements[i]);
+ write_exp_elt_opcode (&p->pstate, OP_LONG);
+ if (got_minus[i])
+ write_exp_elt_opcode (&p->pstate, UNOP_NEG);
+ }
+
+ write_exp_elt_opcode (&p->pstate, OP_REGISTER);
+ str.ptr = regname;
+ str.length = len;
+ write_exp_string (&p->pstate, str);
+ write_exp_elt_opcode (&p->pstate, OP_REGISTER);
+
+ write_exp_elt_opcode (&p->pstate, UNOP_CAST);
+ write_exp_elt_type (&p->pstate,
+ builtin_type (gdbarch)->builtin_data_ptr);
+ write_exp_elt_opcode (&p->pstate, UNOP_CAST);
+
+ write_exp_elt_opcode (&p->pstate, BINOP_ADD);
+ write_exp_elt_opcode (&p->pstate, BINOP_ADD);
+ write_exp_elt_opcode (&p->pstate, BINOP_ADD);
+
+ write_exp_elt_opcode (&p->pstate, UNOP_CAST);
+ write_exp_elt_type (&p->pstate,
+ lookup_pointer_type (p->arg_type));
+ write_exp_elt_opcode (&p->pstate, UNOP_CAST);
+
+ write_exp_elt_opcode (&p->pstate, UNOP_IND);
+
+ p->arg = s;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Helper function for i386_stap_parse_special_token.
+
+ This function parses operands of the form `register base +
+ (register index * size) + offset', as represented in
+ `(%rcx,%rax,8)', or `[OFFSET](BASE_REG,INDEX_REG[,SIZE])'.
+
+ Return 1 if the operand was parsed successfully, zero
+ otherwise. */
+
+static int
+i386_stap_parse_special_token_three_arg_disp (struct gdbarch *gdbarch,
+ struct stap_parse_info *p)
+{
+ const char *s = p->arg;
+
+ if (isdigit (*s) || *s == '(' || *s == '-' || *s == '+')
+ {
+ int offset_minus = 0;
+ long offset = 0;
+ int size_minus = 0;
+ long size = 0;
+ const char *start;
+ char *base;
+ int len_base;
+ char *index;
+ int len_index;
+ struct stoken base_token, index_token;
+
+ if (*s == '+')
+ ++s;
+ else if (*s == '-')
+ {
+ ++s;
+ offset_minus = 1;
+ }
+
+ if (offset_minus && !isdigit (*s))
+ return 0;
+
+ if (isdigit (*s))
+ {
+ char *endp;
+
+ offset = strtol (s, &endp, 10);
+ s = endp;
+ }
+
+ if (*s != '(' || s[1] != '%')
+ return 0;
+
+ s += 2;
+ start = s;
+
+ while (isalnum (*s))
+ ++s;
+
+ if (*s != ',' || s[1] != '%')
+ return 0;
+
+ len_base = s - start;
+ base = alloca (len_base + 1);
+ strncpy (base, start, len_base);
+ base[len_base] = '\0';
+
+ if (user_reg_map_name_to_regnum (gdbarch, base, len_base) == -1)
+ error (_("Invalid register name `%s' on expression `%s'."),
+ base, p->saved_arg);
+
+ s += 2;
+ start = s;
+
+ while (isalnum (*s))
+ ++s;
+
+ len_index = s - start;
+ index = alloca (len_index + 1);
+ strncpy (index, start, len_index);
+ index[len_index] = '\0';
+
+ if (user_reg_map_name_to_regnum (gdbarch, index, len_index) == -1)
+ error (_("Invalid register name `%s' on expression `%s'."),
+ index, p->saved_arg);
+
+ if (*s != ',' && *s != ')')
+ return 0;