b66da4a485
Recent changes to nwfpe broke the build with some gcc versions: In file included from arch/arm/nwfpe/softfloat.c:33: arch/arm/nwfpe/fpa11.h:32: global register variable follows a function definition make[1]: *** [arch/arm/nwfpe/softfloat.o] Error 1 Since we now ensure that the kernel stack is empty when returning to user space, we can now access the userspace registers with reference to the kernel stack using current_thread_info(), rather than remembering the stack pointer at the time nwfpe was called. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
74 lines
2.2 KiB
C++
74 lines
2.2 KiB
C++
/*
|
|
NetWinder Floating Point Emulator
|
|
(c) Rebel.COM, 1998,1999
|
|
|
|
Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
|
|
|
|
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 2 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, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
static inline unsigned long readRegister(const unsigned int nReg)
|
|
{
|
|
/* Note: The CPU thinks it has dealt with the current instruction.
|
|
As a result the program counter has been advanced to the next
|
|
instruction, and points 4 bytes beyond the actual instruction
|
|
that caused the invalid instruction trap to occur. We adjust
|
|
for this in this routine. LDF/STF instructions with Rn = PC
|
|
depend on the PC being correct, as they use PC+8 in their
|
|
address calculations. */
|
|
struct pt_regs *regs = GET_USERREG();
|
|
unsigned int val = regs->uregs[nReg];
|
|
if (REG_PC == nReg)
|
|
val -= 4;
|
|
return val;
|
|
}
|
|
|
|
static inline void
|
|
writeRegister(const unsigned int nReg, const unsigned long val)
|
|
{
|
|
struct pt_regs *regs = GET_USERREG();
|
|
regs->uregs[nReg] = val;
|
|
}
|
|
|
|
static inline unsigned long readCPSR(void)
|
|
{
|
|
return (readRegister(REG_CPSR));
|
|
}
|
|
|
|
static inline void writeCPSR(const unsigned long val)
|
|
{
|
|
writeRegister(REG_CPSR, val);
|
|
}
|
|
|
|
static inline unsigned long readConditionCodes(void)
|
|
{
|
|
#ifdef __FPEM_TEST__
|
|
return (0);
|
|
#else
|
|
return (readCPSR() & CC_MASK);
|
|
#endif
|
|
}
|
|
|
|
static inline void writeConditionCodes(const unsigned long val)
|
|
{
|
|
struct pt_regs *regs = GET_USERREG();
|
|
unsigned long rval;
|
|
/*
|
|
* Operate directly on userRegisters since
|
|
* the CPSR may be the PC register itself.
|
|
*/
|
|
rval = regs->ARM_cpsr & ~CC_MASK;
|
|
regs->ARM_cpsr = rval | (val & CC_MASK);
|
|
}
|