179971Sobrien/* Target-dependent code for FreeBSD/Alpha.
279971Sobrien   Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
379971Sobrien
479971Sobrien   This file is part of GDB.
579971Sobrien
679971Sobrien   This program is free software; you can redistribute it and/or modify
779971Sobrien   it under the terms of the GNU General Public License as published by
879971Sobrien   the Free Software Foundation; either version 2 of the License, or
979971Sobrien   (at your option) any later version.
1079971Sobrien
1179971Sobrien   This program is distributed in the hope that it will be useful,
1279971Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1379971Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1479971Sobrien   GNU General Public License for more details.
1579971Sobrien
1679971Sobrien   You should have received a copy of the GNU General Public License
1779971Sobrien   along with this program; if not, write to the Free Software
1879971Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
1979971Sobrien   Boston, MA 02111-1307, USA.  */
2079971Sobrien
2179971Sobrien#include "defs.h"
2279971Sobrien#include "value.h"
2379971Sobrien#include "osabi.h"
2479971Sobrien
2579971Sobrien#include "alpha-tdep.h"
2679971Sobrien
2779971Sobrienstatic int
2879971Sobrienalphafbsd_use_struct_convention (int gcc_p, struct type *type)
2979971Sobrien{
3079971Sobrien  enum type_code code;
3179971Sobrien  int i;
3279971Sobrien
3379971Sobrien  /* All aggregate types that won't fit in a register must be returned
3479971Sobrien     in memory.  */
3579971Sobrien  if (TYPE_LENGTH (type) > ALPHA_REGISTER_SIZE)
3679971Sobrien    return 1;
3779971Sobrien
3879971Sobrien  /* The only aggregate types that can be returned in a register are
3979971Sobrien     structs and unions.  Arrays must be returned in memory.  */
4079971Sobrien  code = TYPE_CODE (type);
4179971Sobrien  if (code != TYPE_CODE_STRUCT && code != TYPE_CODE_UNION)
4279971Sobrien    return 1;
4379971Sobrien
4479971Sobrien  /* We need to check if this struct/union is "integer" like.  For
4579971Sobrien     this to be true, the offset of each adressable subfield must be
4679971Sobrien     zero.  Note that bit fields are not addressable.  */
4779971Sobrien  for (i = 0; i < TYPE_NFIELDS (type); i++)
4879971Sobrien    {
4979971Sobrien      /* If the field bitsize is non-zero, it isn't adressable.  */
5079971Sobrien      if (TYPE_FIELD_BITPOS (type, i) != 0
5179971Sobrien	  && TYPE_FIELD_BITSIZE (type, i) == 0)
5279971Sobrien	return 1;
5379971Sobrien    }
5479971Sobrien
5579971Sobrien  return 0;
5679971Sobrien}
5779971Sobrien
5879971Sobrien
5979971Sobrien/* Support for signal handlers.  */
6079971Sobrien
6179971Sobrien/* Return whether PC is in a BSD sigtramp routine.  */
6279971Sobrien
6379971SobrienCORE_ADDR alphafbsd_sigtramp_start = 0x11ffff68;
6479971SobrienCORE_ADDR alphafbsd_sigtramp_end = 0x11ffffe0;
6579971Sobrien
6679971Sobrienstatic int
6779971Sobrienalphafbsd_pc_in_sigtramp (CORE_ADDR pc, char *func_name)
6879971Sobrien{
6979971Sobrien  return (pc >= alphafbsd_sigtramp_start && pc < alphafbsd_sigtramp_end);
7079971Sobrien}
7179971Sobrien
7279971Sobrienstatic LONGEST
7379971Sobrienalphafbsd_sigtramp_offset (CORE_ADDR pc)
7479971Sobrien{
7579971Sobrien  return pc - alphafbsd_sigtramp_start;
7679971Sobrien}
7779971Sobrien
7879971Sobrien/* Assuming NEXT_FRAME is for a frame following a BSD sigtramp
7979971Sobrien   routine, return the address of the associated sigcontext structure.  */
8079971Sobrien
8179971Sobrienstatic CORE_ADDR
8279971Sobrienalphafbsd_sigcontext_addr (struct frame_info *next_frame)
8379971Sobrien{
8479971Sobrien  return frame_unwind_register_unsigned (next_frame, ALPHA_SP_REGNUM) + 24;
8579971Sobrien}
8679971Sobrien
8779971Sobrien/* FreeBSD 5.0-RELEASE or later.  */
8879971Sobrien
8979971Sobrienstatic void
9079971Sobrienalphafbsd_init_abi (struct gdbarch_info info,
9179971Sobrien                    struct gdbarch *gdbarch)
9279971Sobrien{
9379971Sobrien  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
9479971Sobrien
9579971Sobrien  /* Hook into the DWARF CFI frame unwinder.  */
9679971Sobrien  alpha_dwarf2_init_abi (info, gdbarch);
9779971Sobrien
9879971Sobrien  /* Hook into the MDEBUG frame unwinder.  */
9979971Sobrien  alpha_mdebug_init_abi (info, gdbarch);
10079971Sobrien
10179971Sobrien  set_gdbarch_use_struct_convention (gdbarch, alphafbsd_use_struct_convention);
10279971Sobrien
10379971Sobrien  set_gdbarch_pc_in_sigtramp (gdbarch, alphafbsd_pc_in_sigtramp);
10479971Sobrien
10579971Sobrien  tdep->dynamic_sigtramp_offset = alphafbsd_sigtramp_offset;
10679971Sobrien  tdep->sigcontext_addr = alphafbsd_sigcontext_addr;
10779971Sobrien  tdep->sc_pc_offset = 288;
10879971Sobrien  tdep->sc_regs_offset = 24;
10979971Sobrien  tdep->sc_fpregs_offset = 320;
11079971Sobrien
11179971Sobrien  tdep->jb_pc = 2;
11279971Sobrien  tdep->jb_elt_size = 8;
11379971Sobrien}
11479971Sobrien
11579971Sobrien
11679971Sobrien/* Provide a prototype to silence -Wmissing-prototypes.  */
11779971Sobrienvoid _initialize_alphafbsd_tdep (void);
11879971Sobrien
11979971Sobrienvoid
12079971Sobrien_initialize_alphafbsd_tdep (void)
12179971Sobrien{
12279971Sobrien  gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_FREEBSD_ELF,
12379971Sobrien                          alphafbsd_init_abi);
12479971Sobrien}
12579971Sobrien