18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci    NetWinder Floating Point Emulator
38c2ecf20Sopenharmony_ci    (c) Rebel.COM, 1998,1999
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci    This program is free software; you can redistribute it and/or modify
88c2ecf20Sopenharmony_ci    it under the terms of the GNU General Public License as published by
98c2ecf20Sopenharmony_ci    the Free Software Foundation; either version 2 of the License, or
108c2ecf20Sopenharmony_ci    (at your option) any later version.
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci    This program is distributed in the hope that it will be useful,
138c2ecf20Sopenharmony_ci    but WITHOUT ANY WARRANTY; without even the implied warranty of
148c2ecf20Sopenharmony_ci    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
158c2ecf20Sopenharmony_ci    GNU General Public License for more details.
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci    You should have received a copy of the GNU General Public License
188c2ecf20Sopenharmony_ci    along with this program; if not, write to the Free Software
198c2ecf20Sopenharmony_ci    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
208c2ecf20Sopenharmony_ci*/
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic inline unsigned long readRegister(const unsigned int nReg)
238c2ecf20Sopenharmony_ci{
248c2ecf20Sopenharmony_ci	/* Note: The CPU thinks it has dealt with the current instruction.
258c2ecf20Sopenharmony_ci	   As a result the program counter has been advanced to the next
268c2ecf20Sopenharmony_ci	   instruction, and points 4 bytes beyond the actual instruction
278c2ecf20Sopenharmony_ci	   that caused the invalid instruction trap to occur.  We adjust
288c2ecf20Sopenharmony_ci	   for this in this routine.  LDF/STF instructions with Rn = PC
298c2ecf20Sopenharmony_ci	   depend on the PC being correct, as they use PC+8 in their
308c2ecf20Sopenharmony_ci	   address calculations. */
318c2ecf20Sopenharmony_ci	struct pt_regs *regs = GET_USERREG();
328c2ecf20Sopenharmony_ci	unsigned int val = regs->uregs[nReg];
338c2ecf20Sopenharmony_ci	if (REG_PC == nReg)
348c2ecf20Sopenharmony_ci		val -= 4;
358c2ecf20Sopenharmony_ci	return val;
368c2ecf20Sopenharmony_ci}
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_cistatic inline void
398c2ecf20Sopenharmony_ciwriteRegister(const unsigned int nReg, const unsigned long val)
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	struct pt_regs *regs = GET_USERREG();
428c2ecf20Sopenharmony_ci	regs->uregs[nReg] = val;
438c2ecf20Sopenharmony_ci}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cistatic inline unsigned long readCPSR(void)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	return (readRegister(REG_CPSR));
488c2ecf20Sopenharmony_ci}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistatic inline void writeCPSR(const unsigned long val)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci	writeRegister(REG_CPSR, val);
538c2ecf20Sopenharmony_ci}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistatic inline unsigned long readConditionCodes(void)
568c2ecf20Sopenharmony_ci{
578c2ecf20Sopenharmony_ci#ifdef __FPEM_TEST__
588c2ecf20Sopenharmony_ci	return (0);
598c2ecf20Sopenharmony_ci#else
608c2ecf20Sopenharmony_ci	return (readCPSR() & CC_MASK);
618c2ecf20Sopenharmony_ci#endif
628c2ecf20Sopenharmony_ci}
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_cistatic inline void writeConditionCodes(const unsigned long val)
658c2ecf20Sopenharmony_ci{
668c2ecf20Sopenharmony_ci	struct pt_regs *regs = GET_USERREG();
678c2ecf20Sopenharmony_ci	unsigned long rval;
688c2ecf20Sopenharmony_ci	/*
698c2ecf20Sopenharmony_ci	 * Operate directly on userRegisters since
708c2ecf20Sopenharmony_ci	 * the CPSR may be the PC register itself.
718c2ecf20Sopenharmony_ci	 */
728c2ecf20Sopenharmony_ci	rval = regs->ARM_cpsr & ~CC_MASK;
738c2ecf20Sopenharmony_ci	regs->ARM_cpsr = rval | (val & CC_MASK);
748c2ecf20Sopenharmony_ci}
75