On Wed, Jun 24, 2009 at 09:30:11PM -0400, Gabriel Michael Black wrote: > > Also, is it the case that you can write the PC with any opcode? I vaguely > > recall hearing that that was deprecated at some point. > > > > I don't know. I saw some places in the ARM manual where it said some > uses of R15 cause undefined behavior. I don't know where to find a > concise description of where it is and isn't allowed.
I've also been looking at this problem. I want to get the O3 CPU working with the ARM ISA, and I've been making some progress. The two sticking points are predicated execution and the PC's "pseudo-GPR" nature. So, hopefully I can contribute something to your discussion. As I see it, the big problem is when the PC is a destination for an operation that normally produces a GPR. As a source, you can always get the right behaviour quite easily (as you said, + 8): > >> Example reading code: > >> Rn = (RN == PCReg) ? xc->readPC() : xc->readIntRegOperand(this, 0); I've gone through the ARM ARM, looked at all the integer instructions, and the writes to PC *always* fall into one of the following categories: 1. Performed via an explicit branch instruction (b, blx, etc.) 2. Performed by load multiple (e.g. ldmia). 3. Performed by an ALU or load operation that writes to Rd, with Rd = 15. (Rd is machine code bits 15..12 as defined in operands.isa). Case 1 is easy, same as any other CPU. Case 2 is only slightly more difficult, because you can generate a special "write to PC" uop resembling a conditional branch. Case 3 is the difficulty. But it's not so bad, because- * The PC is *always* written via Rd. Not Rs, Rm, etc. * No other registers are updated (except Cpsr). Here are the instructions that fall into case 3: ADC ADD AND BIC CLZ EOR LDR LDRB LDRBT LDRH LDRSB LDRSH LDRT MOV MVN ORR RSB RSC SBC SUB It is possible to specify r15 as the output of some other instructions (e.g. MUL, MLA), but the results are not defined by the ISA. Clearly, there are a number of ways to handle this. Any of these instructions could write the PC, creating a branch. Here is my suggestion for how to handle case 3 instructions. I am relatively new to M5, so this may not be the best way, but some preliminary tests suggest it will work. First, the control flags need to change if the instruction writes to r15: // base_dyn_inst.hh: bool isControl() const { return staticInst->isControl() || isPCLoad(); } bool isIndirectCtrl() const { return staticInst->isIndirectCtrl() || isPCLoad(); } bool isCondCtrl() const { return staticInst->isCondCtrl() || isPCLoad(); } The new function isPCLoad() returns true if the ISA is ARM and one of the destination registers is 15 (before renaming): bool isPCLoad(void) const { #if THE_ISA == ARM_ISA for (int i = 0; i < numDestRegs(); i++) { if (staticInst->destRegIdx(i) == TheISA::PCReg) { return true; } } #endif return false; } This way, we don't have to change the ISA definitions for case 3 instructions. They automatically become branches if rD = 15. However, this still leaves the problem of operations that load the new PC from memory, such as: ldreq pc, [sp], #4 On O3, these are tricky because the new PC is not known until the load completes (LSQUnit::writeback), but branch mispredictions are only recognised when the load starts (LSQUnit::executeLoad). My suggestion for these is to generate a branch misprediction in LSQUnit::writeback, if (inst->isPCLoad()&&inst->mispredicted), and don't generate a branch misprediction in the regular place if inst->isPCLoad(). -- Jack Whitham j...@cs.york.ac.uk _______________________________________________ m5-dev mailing list m5-dev@m5sim.org http://m5sim.org/mailman/listinfo/m5-dev