Mercurial > flash_v2
changeset 304:e206cd7d2ed1
Fix coprocessor register handling in ARM stub.
| author | msalter |
|---|---|
| date | Thu, 22 Aug 2002 12:24:19 +0000 |
| parents | afd40c766438 |
| children | 82c554739834 |
| files | packages/hal/arm/arch/current/ChangeLog packages/hal/arm/arch/current/include/arm_stub.h packages/hal/arm/arch/current/include/hal_arch.h packages/hal/arm/arch/current/src/arm_stub.c |
| diffstat | 4 files changed, 148 insertions(+), 25 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/hal/arm/arch/current/ChangeLog +++ b/packages/hal/arm/arch/current/ChangeLog @@ -1,3 +1,9 @@ +2002-08-21 Mark Salter <msalter@redhat.com> + + * src/arm_stub.c: Add support for large registers (e.g. FPU). + * include/arm_stub.h: Add infrastructure for support of coprocessors. + * include/hal_arch.h: Ditto. + 2002-08-02 Andrew Lunn <Andrew.Lunn@ascom.ch> * cdl/hal_arm.cdl: Redboot exec command can now be disabled by CDL
--- a/packages/hal/arm/arch/current/include/arm_stub.h +++ b/packages/hal/arm/arch/current/include/arm_stub.h @@ -57,6 +57,13 @@ extern "C" { #endif +// The ARM has float (and possibly other coprocessor) registers that are +// larger than it can hold in a target_register_t. +#define TARGET_HAS_LARGE_REGISTERS + +// ARM stub has special needs for register handling (not all regs are the +// the same size), so special put_register and get_register are provided. +#define CYGARC_STUB_REGISTER_ACCESS_DEFINED 1 #define NUMREGS (16+8+2) // 16 GPR, 8 FPR (unused), 2 PS @@ -77,6 +84,9 @@ enum regnames { FPS, PS }; +#define HAL_STUB_REGISTERS_SIZE \ + ((sizeof(GDB_Registers) + sizeof(target_register_t) - 1) / sizeof(target_register_t)) + #define PS_N 0x80000000 #define PS_Z 0x40000000 #define PS_C 0x20000000
--- a/packages/hal/arm/arch/current/include/hal_arch.h +++ b/packages/hal/arm/arch/current/include/hal_arch.h @@ -229,52 +229,78 @@ extern cyg_uint16 __thumb_breakinst; //-------------------------------------------------------------------------- // Thread register state manipulation for GDB support. -// GDB expects the registers in this structure: -// r0..r10, fp, ip, sp, lr, pc - 4 bytes each -// f0..f7 - 12 bytes each (N/A on ARM7) -// fps - 4 bytes (N/A on ARM7) -// ps - 4 bytes +// Register layout expected by GDB +typedef struct +{ + cyg_uint32 gpr[16]; + cyg_uint32 f0[3]; + cyg_uint32 f1[3]; + cyg_uint32 f2[3]; + cyg_uint32 f3[3]; + cyg_uint32 f4[3]; + cyg_uint32 f5[3]; + cyg_uint32 f6[3]; + cyg_uint32 f7[3]; + cyg_uint32 fps; + cyg_uint32 ps; +} GDB_Registers; // Translate a stack pointer as saved by the thread context macros above into // a pointer to a HAL_SavedRegisters structure. #define HAL_THREAD_GET_SAVED_REGISTERS( _sp_, _regs_ ) \ (_regs_) = (HAL_SavedRegisters *)(_sp_) +// Copy a set of coprocessor registers from a HAL_SavedRegisters structure +// into a GDB_Registers structure. GDB expects placeholders for FP regs +// even for non-FP targets, so we just zero fill the fields. +#define HAL_GET_GDB_COPROCESSOR_REGISTERS( _gdb_, _regs_ ) \ + CYG_MACRO_START \ + cyg_uint32 *_p_ = _gdb_->f0; \ + for(_i_ = 0; _i_ < (8 * 3); _i_++) \ + *_p_++ = 0; \ + _gdb_->fps = 0; \ + CYG_MACRO_END + +// Copy coprocessor registers from a GDB_Registers structure into a +// HAL_SavedRegisters structure. +#define HAL_SET_GDB_COPROCESSOR_REGISTERS( _regs_, _gdb_ ) + // Copy a set of registers from a HAL_SavedRegisters structure into a -// GDB ordered array. +// GDB_Registers structure. #define HAL_GET_GDB_REGISTERS( _aregval_, _regs_ ) \ CYG_MACRO_START \ - CYG_ADDRWORD *_regval_ = (CYG_ADDRWORD *)(_aregval_); \ + GDB_Registers *_gdb_ = (GDB_Registers *)(_aregval_); \ int _i_; \ \ for( _i_ = 0; _i_ <= 10; _i_++ ) \ - _regval_[_i_] = (_regs_)->d[_i_]; \ + _gdb_->gpr[_i_] = (_regs_)->d[_i_]; \ \ - _regval_[11] = (_regs_)->fp; \ - _regval_[12] = (_regs_)->ip; \ - _regval_[13] = (_regs_)->sp; \ - _regval_[14] = (_regs_)->lr; \ - _regval_[15] = (_regs_)->pc; \ - _regval_[25] = (_regs_)->cpsr; \ - for( _i_ = 0; _i_ < 8; _i_++ ) \ - _regval_[_i_+16] = 0; \ + _gdb_->gpr[11] = (_regs_)->fp; \ + _gdb_->gpr[12] = (_regs_)->ip; \ + _gdb_->gpr[13] = (_regs_)->sp; \ + _gdb_->gpr[14] = (_regs_)->lr; \ + _gdb_->gpr[15] = (_regs_)->pc; \ + _gdb_->ps = (_regs_)->cpsr; \ + HAL_GET_GDB_COPROCESSOR_REGISTERS(_gdb_,_regs_); \ CYG_MACRO_END -// Copy a GDB ordered array into a HAL_SavedRegisters structure. +// Copy a set of registers from a GDB_Registers structure into a +// HAL_SavedRegisters structure. #define HAL_SET_GDB_REGISTERS( _regs_ , _aregval_ ) \ CYG_MACRO_START \ - CYG_ADDRWORD *_regval_ = (CYG_ADDRWORD *)(_aregval_); \ + GDB_Registers *_gdb_ = (GDB_Registers *)(_aregval_); \ int _i_; \ \ for( _i_ = 0; _i_ <= 10; _i_++ ) \ - (_regs_)->d[_i_] = _regval_[_i_]; \ + (_regs_)->d[_i_] = _gdb_->gpr[_i_]; \ \ - (_regs_)->fp = _regval_[11]; \ - (_regs_)->ip = _regval_[12]; \ - (_regs_)->sp = _regval_[13]; \ - (_regs_)->lr = _regval_[14]; \ - (_regs_)->pc = _regval_[15]; \ - (_regs_)->cpsr = _regval_[25]; \ + (_regs_)->fp = _gdb_->gpr[11]; \ + (_regs_)->ip = _gdb_->gpr[12]; \ + (_regs_)->sp = _gdb_->gpr[13]; \ + (_regs_)->lr = _gdb_->gpr[14]; \ + (_regs_)->pc = _gdb_->gpr[15]; \ + (_regs_)->cpsr = _gdb_->ps; \ + HAL_SET_GDB_COPROCESSOR_REGISTERS(_regs_,_gdb_); \ CYG_MACRO_END #if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
--- a/packages/hal/arm/arch/current/src/arm_stub.c +++ b/packages/hal/arm/arch/current/src/arm_stub.c @@ -151,6 +151,87 @@ void set_pc (target_register_t pc) put_register (PC, pc); } +// Calculate byte offset a given register from start of register save area. +static int +reg_offset(regnames_t reg) +{ + int base_offset; + + if (reg < F0) + return reg * 4; + + base_offset = 16 * 4; + + if (reg < FPS) + return base_offset + ((reg - F0) * 12); + + base_offset += (8 * 12); + + if (reg <= PS) + return base_offset + ((reg - FPS) * 4); + + return -1; // Should never happen! +} + + +// Return the currently-saved value corresponding to register REG of +// the exception context. +target_register_t +get_register (regnames_t reg) +{ + target_register_t val; + int offset = reg_offset(reg); + + if (REGSIZE(reg) > sizeof(target_register_t) || offset == -1) + return -1; + + val = _registers[offset/sizeof(target_register_t)]; + + return val; +} + +// Store VALUE in the register corresponding to WHICH in the exception +// context. +void +put_register (regnames_t which, target_register_t value) +{ + int offset = reg_offset(which); + + if (REGSIZE(which) > sizeof(target_register_t) || offset == -1) + return; + + _registers[offset/sizeof(target_register_t)] = value; +} + +// Write the contents of register WHICH into VALUE as raw bytes. This +// is only used for registers larger than sizeof(target_register_t). +// Return non-zero if it is a valid register. +int +get_register_as_bytes (regnames_t which, char *value) +{ + int offset = reg_offset(which); + + if (offset != -1) { + memcpy (value, (char *)_registers + offset, REGSIZE(which)); + return 1; + } + return 0; +} + +// Alter the contents of saved register WHICH to contain VALUE. This +// is only used for registers larger than sizeof(target_register_t). +// Return non-zero if it is a valid register. +int +put_register_as_bytes (regnames_t which, char *value) +{ + int offset = reg_offset(which); + + if (offset != -1) { + memcpy ((char *)_registers + offset, value, REGSIZE(which)); + return 1; + } + return 0; +} /*---------------------------------------------------------------------- * Single-step support
