This is the mail archive of the ecos-patches@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

fix coprocessor register handling in ARM stub


Index: hal/arm/arch/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/hal/arm/arch/current/ChangeLog,v
retrieving revision 1.73
diff -u -p -5 -r1.73 ChangeLog
--- hal/arm/arch/current/ChangeLog	6 Aug 2002 14:34:03 -0000	1.73
+++ hal/arm/arch/current/ChangeLog	22 Aug 2002 12:19:44 -0000
@@ -1,5 +1,11 @@
+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
 	
 2002-07-15  Mark Salter  <msalter@redhat.com>
Index: hal/arm/arch/current/include/arm_stub.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/hal/arm/arch/current/include/arm_stub.h,v
retrieving revision 1.14
diff -u -p -5 -r1.14 arm_stub.h
--- hal/arm/arch/current/include/arm_stub.h	15 Jul 2002 19:37:12 -0000	1.14
+++ hal/arm/arch/current/include/arm_stub.h	22 Aug 2002 12:19:44 -0000
@@ -55,10 +55,17 @@
 
 #ifdef __cplusplus
 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
 
 #define REGSIZE( _x_ ) (((_x_) < F0 || (_x_) >= FPS) ? 4 : 12)
 
@@ -74,10 +81,13 @@ enum regnames {
     R0, R1, R2, R3, R4, R5, R6, R7, 
     R8, R9, R10, FP, IP, SP, LR, PC,
     F0, F1, F2, F3, F4, F5, F6, F7, 
     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
 #define PS_V 0x10000000
Index: hal/arm/arch/current/include/hal_arch.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/hal/arm/arch/current/include/hal_arch.h,v
retrieving revision 1.19
diff -u -p -5 -r1.19 hal_arch.h
--- hal/arm/arch/current/include/hal_arch.h	23 May 2002 23:01:42 -0000	1.19
+++ hal/arm/arch/current/include/hal_arch.h	22 Aug 2002 12:19:45 -0000
@@ -227,56 +227,82 @@ extern cyg_uint16 __thumb_breakinst;
                               ((void*)&__arm_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)
 #define HAL_GET_PROFILE_INFO( _thepc_, _thesp_ )                \
     CYG_MACRO_START                                             \
Index: hal/arm/arch/current/src/arm_stub.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/hal/arm/arch/current/src/arm_stub.c,v
retrieving revision 1.23
diff -u -p -5 -r1.23 arm_stub.c
--- hal/arm/arch/current/src/arm_stub.c	23 May 2002 23:01:42 -0000	1.23
+++ hal/arm/arch/current/src/arm_stub.c	22 Aug 2002 12:19:46 -0000
@@ -149,10 +149,91 @@ int __is_bsp_syscall(void) 
 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
  */
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]