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