|  | /* Ada Ravenscar thread support. | 
|  |  | 
|  | Copyright (C) 2004-2025 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 GDB_RAVENSCAR_THREAD_H | 
|  | #define GDB_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 /* GDB_RAVENSCAR_THREAD_H */ |