198944Sobrien/* Target-dependent code for FreeBSD/Alpha.
2130803Smarcel   Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
398944Sobrien
498944Sobrien   This file is part of GDB.
598944Sobrien
698944Sobrien   This program is free software; you can redistribute it and/or modify
798944Sobrien   it under the terms of the GNU General Public License as published by
898944Sobrien   the Free Software Foundation; either version 2 of the License, or
998944Sobrien   (at your option) any later version.
1098944Sobrien
1198944Sobrien   This program is distributed in the hope that it will be useful,
1298944Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1398944Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1498944Sobrien   GNU General Public License for more details.
1598944Sobrien
1698944Sobrien   You should have received a copy of the GNU General Public License
1798944Sobrien   along with this program; if not, write to the Free Software
1898944Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
1998944Sobrien   Boston, MA 02111-1307, USA.  */
2098944Sobrien
2198944Sobrien#include "defs.h"
2298944Sobrien#include "value.h"
23130803Smarcel#include "osabi.h"
2498944Sobrien
25130803Smarcel#include "alpha-tdep.h"
26130803Smarcel
27130803Smarcelstatic int
2898944Sobrienalphafbsd_use_struct_convention (int gcc_p, struct type *type)
2998944Sobrien{
3098944Sobrien  enum type_code code;
3198944Sobrien  int i;
3298944Sobrien
3398944Sobrien  /* All aggregate types that won't fit in a register must be returned
3498944Sobrien     in memory.  */
35130803Smarcel  if (TYPE_LENGTH (type) > ALPHA_REGISTER_SIZE)
3698944Sobrien    return 1;
3798944Sobrien
3898944Sobrien  /* The only aggregate types that can be returned in a register are
3998944Sobrien     structs and unions.  Arrays must be returned in memory.  */
4098944Sobrien  code = TYPE_CODE (type);
4198944Sobrien  if (code != TYPE_CODE_STRUCT && code != TYPE_CODE_UNION)
4298944Sobrien    return 1;
4398944Sobrien
4498944Sobrien  /* We need to check if this struct/union is "integer" like.  For
4598944Sobrien     this to be true, the offset of each adressable subfield must be
4698944Sobrien     zero.  Note that bit fields are not addressable.  */
4798944Sobrien  for (i = 0; i < TYPE_NFIELDS (type); i++)
4898944Sobrien    {
4998944Sobrien      /* If the field bitsize is non-zero, it isn't adressable.  */
5098944Sobrien      if (TYPE_FIELD_BITPOS (type, i) != 0
5198944Sobrien	  && TYPE_FIELD_BITSIZE (type, i) == 0)
5298944Sobrien	return 1;
5398944Sobrien    }
5498944Sobrien
5598944Sobrien  return 0;
5698944Sobrien}
57130803Smarcel
58130803Smarcel
59130803Smarcel/* Support for signal handlers.  */
60130803Smarcel
61130803Smarcel/* Return whether PC is in a BSD sigtramp routine.  */
62130803Smarcel
63130803SmarcelCORE_ADDR alphafbsd_sigtramp_start = 0x11ffff68;
64130803SmarcelCORE_ADDR alphafbsd_sigtramp_end = 0x11ffffe0;
65130803Smarcel
66130803Smarcelstatic int
67130803Smarcelalphafbsd_pc_in_sigtramp (CORE_ADDR pc, char *func_name)
68130803Smarcel{
69130803Smarcel  return (pc >= alphafbsd_sigtramp_start && pc < alphafbsd_sigtramp_end);
70130803Smarcel}
71130803Smarcel
72130803Smarcelstatic LONGEST
73130803Smarcelalphafbsd_sigtramp_offset (CORE_ADDR pc)
74130803Smarcel{
75130803Smarcel  return pc - alphafbsd_sigtramp_start;
76130803Smarcel}
77130803Smarcel
78130803Smarcel/* Assuming NEXT_FRAME is for a frame following a BSD sigtramp
79130803Smarcel   routine, return the address of the associated sigcontext structure.  */
80130803Smarcel
81130803Smarcelstatic CORE_ADDR
82130803Smarcelalphafbsd_sigcontext_addr (struct frame_info *next_frame)
83130803Smarcel{
84130803Smarcel  return frame_unwind_register_unsigned (next_frame, ALPHA_SP_REGNUM) + 24;
85130803Smarcel}
86130803Smarcel
87130803Smarcel/* FreeBSD 5.0-RELEASE or later.  */
88130803Smarcel
89130803Smarcelstatic void
90130803Smarcelalphafbsd_init_abi (struct gdbarch_info info,
91130803Smarcel                    struct gdbarch *gdbarch)
92130803Smarcel{
93130803Smarcel  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
94130803Smarcel
95130803Smarcel  /* Hook into the DWARF CFI frame unwinder.  */
96130803Smarcel  alpha_dwarf2_init_abi (info, gdbarch);
97130803Smarcel
98130803Smarcel  /* Hook into the MDEBUG frame unwinder.  */
99130803Smarcel  alpha_mdebug_init_abi (info, gdbarch);
100130803Smarcel
101130803Smarcel  set_gdbarch_use_struct_convention (gdbarch, alphafbsd_use_struct_convention);
102130803Smarcel
103130803Smarcel  set_gdbarch_pc_in_sigtramp (gdbarch, alphafbsd_pc_in_sigtramp);
104130803Smarcel
105130803Smarcel  tdep->dynamic_sigtramp_offset = alphafbsd_sigtramp_offset;
106130803Smarcel  tdep->sigcontext_addr = alphafbsd_sigcontext_addr;
107130803Smarcel  tdep->sc_pc_offset = 288;
108130803Smarcel  tdep->sc_regs_offset = 24;
109130803Smarcel  tdep->sc_fpregs_offset = 320;
110130803Smarcel
111130803Smarcel  tdep->jb_pc = 2;
112130803Smarcel  tdep->jb_elt_size = 8;
113130803Smarcel}
114130803Smarcel
115130803Smarcel
116130803Smarcel/* Provide a prototype to silence -Wmissing-prototypes.  */
117130803Smarcelvoid _initialize_alphafbsd_tdep (void);
118130803Smarcel
119130803Smarcelvoid
120130803Smarcel_initialize_alphafbsd_tdep (void)
121130803Smarcel{
122130803Smarcel  gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_FREEBSD_ELF,
123130803Smarcel                          alphafbsd_init_abi);
124130803Smarcel}
125