134 lines
5 KiB
C
134 lines
5 KiB
C
|
/* Ada Ravenscar thread support.
|
||
|
|
||
|
Copyright (C) 2004-2022 Free Software Foundation, Inc.
|
||
|
|
||
|
This file is part of GDB.
|
||
|
|
||
|
This program is free software; you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation; either version 3 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||
|
|
||
|
#ifndef RAVENSCAR_THREAD_H
|
||
|
#define RAVENSCAR_THREAD_H
|
||
|
|
||
|
/* Architecture-specific hooks. */
|
||
|
|
||
|
struct ravenscar_arch_ops
|
||
|
{
|
||
|
ravenscar_arch_ops (gdb::array_view<const int> offsets_,
|
||
|
int first_stack = -1,
|
||
|
int last_stack = -1,
|
||
|
int v_init = -1,
|
||
|
int fpu_offset = -1,
|
||
|
int first_fp = -1,
|
||
|
int last_fp = -1)
|
||
|
: offsets (offsets_),
|
||
|
first_stack_register (first_stack),
|
||
|
last_stack_register (last_stack),
|
||
|
v_init_offset (v_init),
|
||
|
fpu_context_offset (fpu_offset),
|
||
|
first_fp_register (first_fp),
|
||
|
last_fp_register (last_fp)
|
||
|
{
|
||
|
/* These must either both be -1 or both be valid. */
|
||
|
gdb_assert ((first_stack_register == -1) == (last_stack_register == -1));
|
||
|
/* They must also be ordered. */
|
||
|
gdb_assert (last_stack_register >= first_stack_register);
|
||
|
/* These must either all be -1 or all be valid. */
|
||
|
gdb_assert ((v_init_offset == -1) == (fpu_context_offset == -1)
|
||
|
&& (fpu_context_offset == -1) == (first_fp_register == -1)
|
||
|
&& (first_fp_register == -1) == (last_fp_register == -1));
|
||
|
}
|
||
|
|
||
|
/* Return true if this architecture implements on-demand floating
|
||
|
point. */
|
||
|
bool on_demand_fp () const
|
||
|
{ return v_init_offset != -1; }
|
||
|
|
||
|
/* Return true if REGNUM is a floating-point register for this
|
||
|
target. If this target does not use the on-demand FP scheme,
|
||
|
this will always return false. */
|
||
|
bool is_fp_register (int regnum) const
|
||
|
{
|
||
|
return regnum >= first_fp_register && regnum <= last_fp_register;
|
||
|
}
|
||
|
|
||
|
/* Return the offset, in the current task context, of the byte
|
||
|
indicating whether the FPU has been initialized for the task.
|
||
|
This can only be called when the architecture implements
|
||
|
on-demand floating-point. */
|
||
|
int get_v_init_offset () const
|
||
|
{
|
||
|
gdb_assert (on_demand_fp ());
|
||
|
return v_init_offset;
|
||
|
}
|
||
|
|
||
|
/* Return the offset, in the current task context, of the FPU
|
||
|
context. This can only be called when the architecture
|
||
|
implements on-demand floating-point. */
|
||
|
int get_fpu_context_offset () const
|
||
|
{
|
||
|
gdb_assert (on_demand_fp ());
|
||
|
return fpu_context_offset;
|
||
|
}
|
||
|
|
||
|
void fetch_register (struct regcache *recache, int regnum) const;
|
||
|
void store_register (struct regcache *recache, int regnum) const;
|
||
|
|
||
|
private:
|
||
|
|
||
|
/* An array where the indices are register numbers and the contents
|
||
|
are offsets. The offsets are either in the thread descriptor or
|
||
|
the stack, depending on the other fields. An offset of -1 means
|
||
|
that the corresponding register is not stored. */
|
||
|
const gdb::array_view<const int> offsets;
|
||
|
|
||
|
/* If these are -1, then all registers for this architecture are
|
||
|
stored in the thread descriptor. Otherwise, these mark a range
|
||
|
of registers that are stored on the stack. */
|
||
|
const int first_stack_register;
|
||
|
const int last_stack_register;
|
||
|
|
||
|
/* If these are -1, there is no special treatment for floating-point
|
||
|
registers -- they are handled, or not, just like all other
|
||
|
registers.
|
||
|
|
||
|
Otherwise, they must all not be -1, and the target is one that
|
||
|
uses on-demand FP initialization. V_INIT_OFFSET is the offset of
|
||
|
a boolean field in the context that indicates whether the FP
|
||
|
registers have been initialized for this task.
|
||
|
FPU_CONTEXT_OFFSET is the offset of the FPU context from the task
|
||
|
context. (This is needed to check whether the FPU registers have
|
||
|
been saved.) FIRST_FP_REGISTER and LAST_FP_REGISTER are the
|
||
|
register numbers of the first and last (inclusive) floating point
|
||
|
registers. */
|
||
|
const int v_init_offset;
|
||
|
const int fpu_context_offset;
|
||
|
const int first_fp_register;
|
||
|
const int last_fp_register;
|
||
|
|
||
|
/* Helper function to supply one register. */
|
||
|
void supply_one_register (struct regcache *regcache, int regnum,
|
||
|
CORE_ADDR descriptor,
|
||
|
CORE_ADDR stack_base) const;
|
||
|
/* Helper function to store one register. */
|
||
|
void store_one_register (struct regcache *regcache, int regnum,
|
||
|
CORE_ADDR descriptor,
|
||
|
CORE_ADDR stack_base) const;
|
||
|
/* Helper function to find stack address where registers are stored.
|
||
|
This must be called with the stack pointer already supplied in
|
||
|
the register cache. */
|
||
|
CORE_ADDR get_stack_base (struct regcache *) const;
|
||
|
};
|
||
|
|
||
|
#endif /* !defined (RAVENSCAR_THREAD_H) */
|