162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci    NetWinder Floating Point Emulator
362306a36Sopenharmony_ci    (c) Rebel.COM, 1998,1999
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci    This program is free software; you can redistribute it and/or modify
862306a36Sopenharmony_ci    it under the terms of the GNU General Public License as published by
962306a36Sopenharmony_ci    the Free Software Foundation; either version 2 of the License, or
1062306a36Sopenharmony_ci    (at your option) any later version.
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci    This program is distributed in the hope that it will be useful,
1362306a36Sopenharmony_ci    but WITHOUT ANY WARRANTY; without even the implied warranty of
1462306a36Sopenharmony_ci    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1562306a36Sopenharmony_ci    GNU General Public License for more details.
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci    You should have received a copy of the GNU General Public License
1862306a36Sopenharmony_ci    along with this program; if not, write to the Free Software
1962306a36Sopenharmony_ci    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2062306a36Sopenharmony_ci*/
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cistatic inline unsigned long readRegister(const unsigned int nReg)
2362306a36Sopenharmony_ci{
2462306a36Sopenharmony_ci	/* Note: The CPU thinks it has dealt with the current instruction.
2562306a36Sopenharmony_ci	   As a result the program counter has been advanced to the next
2662306a36Sopenharmony_ci	   instruction, and points 4 bytes beyond the actual instruction
2762306a36Sopenharmony_ci	   that caused the invalid instruction trap to occur.  We adjust
2862306a36Sopenharmony_ci	   for this in this routine.  LDF/STF instructions with Rn = PC
2962306a36Sopenharmony_ci	   depend on the PC being correct, as they use PC+8 in their
3062306a36Sopenharmony_ci	   address calculations. */
3162306a36Sopenharmony_ci	struct pt_regs *regs = GET_USERREG();
3262306a36Sopenharmony_ci	unsigned int val = regs->uregs[nReg];
3362306a36Sopenharmony_ci	if (REG_PC == nReg)
3462306a36Sopenharmony_ci		val -= 4;
3562306a36Sopenharmony_ci	return val;
3662306a36Sopenharmony_ci}
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistatic inline void
3962306a36Sopenharmony_ciwriteRegister(const unsigned int nReg, const unsigned long val)
4062306a36Sopenharmony_ci{
4162306a36Sopenharmony_ci	struct pt_regs *regs = GET_USERREG();
4262306a36Sopenharmony_ci	regs->uregs[nReg] = val;
4362306a36Sopenharmony_ci}
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistatic inline unsigned long readCPSR(void)
4662306a36Sopenharmony_ci{
4762306a36Sopenharmony_ci	return (readRegister(REG_CPSR));
4862306a36Sopenharmony_ci}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic inline void writeCPSR(const unsigned long val)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	writeRegister(REG_CPSR, val);
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cistatic inline unsigned long readConditionCodes(void)
5662306a36Sopenharmony_ci{
5762306a36Sopenharmony_ci#ifdef __FPEM_TEST__
5862306a36Sopenharmony_ci	return (0);
5962306a36Sopenharmony_ci#else
6062306a36Sopenharmony_ci	return (readCPSR() & CC_MASK);
6162306a36Sopenharmony_ci#endif
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistatic inline void writeConditionCodes(const unsigned long val)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	struct pt_regs *regs = GET_USERREG();
6762306a36Sopenharmony_ci	unsigned long rval;
6862306a36Sopenharmony_ci	/*
6962306a36Sopenharmony_ci	 * Operate directly on userRegisters since
7062306a36Sopenharmony_ci	 * the CPSR may be the PC register itself.
7162306a36Sopenharmony_ci	 */
7262306a36Sopenharmony_ci	rval = regs->ARM_cpsr & ~CC_MASK;
7362306a36Sopenharmony_ci	regs->ARM_cpsr = rval | (val & CC_MASK);
7462306a36Sopenharmony_ci}
75