void RegisterAllocator::restore(const State &state) { if(!minimalRestore) { spillAll(); return; } for(int i = 0; i < 8; i++) { if(GPR[i].reference != state.GPR[i].reference) { spill32(i); } if(MMX[i].reference != state.MMX[i].reference) { spill64(i); } if(XMM[i].reference != state.XMM[i].reference) { spill128(i); } } for(int i = 0; i < 8; i++) { if(GPR[i].reference != state.GPR[i].reference && state.GPR[i].reference != 0) { allocate32(i, state.GPR[i].reference, true, state.GPR[i].partial); } if(MMX[i].reference != state.MMX[i].reference && state.MMX[i].reference != 0) { allocate64(i, state.MMX[i].reference, true); } if(XMM[i].reference != state.XMM[i].reference && state.XMM[i].reference != 0) { allocate128(i, state.XMM[i].reference, true, state.XMM[i].partial != 0); } } for(int i = 0; i < 8; i++) { // Prevent optimizations markModified(OperandREG32(i)); markModified(OperandMMREG(i)); markModified(OperandXMMREG(i)); } }
void allocate64_array (void **mem, GFC_INTEGER_8 size, GFC_INTEGER_4 * stat) { if (*mem == NULL) { allocate64 (mem, size, stat); return; } if (stat) { free (*mem); allocate (mem, size, stat); *stat = ERROR_ALLOCATION; return; } else runtime_error ("Attempting to allocate already allocated array."); return; }
OperandMMREG RegisterAllocator::r64(const OperandREF &ref, bool copy) { if(ref == 0 && copy) throw Error("Cannot dereference 0"); // Check if already allocated for(int i = 0; i < 8; i++) { if(MMX[i].reference == ref) { return prioritize64(i); } } // Check spilled but unused registers if(spillElimination) { for(int i = 0; i < 8; i++) { if(MMX[i].priority == 0 && MMX[i].spill.reference == ref) { if(MMX[i].spillInstruction) { MMX[i].spillInstruction->reserve(); } MMX[i].reference = MMX[i].spill.reference; MMX[i].partial = MMX[i].spill.partial; MMX[i].priority = MMX[i].spill.priority; MMX[i].copyInstruction = MMX[i].spill.copyInstruction; MMX[i].loadInstruction = MMX[i].spill.loadInstruction; MMX[i].spillInstruction = MMX[i].spill.spillInstruction; MMX[i].spill.free(); return prioritize64(i); } } } // Search for free registers for(int i = 0; i < 8; i++) { if(MMX[i].priority == 0 && MMX[i].spill.priority == 0) { return allocate64(i, ref, copy); } } for(int i = 0; i < 8; i++) { if(MMX[i].priority == 0) { return allocate64(i, ref, copy); } } // Need to spill one int candidate = 0; int betterCandidate = -1; unsigned int priority = 0xFFFFFFFF; for(int i = 0; i < 8; i++) { if(MMX[i].priority < priority) { priority = MMX[i].priority; candidate = i; if(!MMX[i].modified && MMX[i].priority < 0xFFFFFFFF - 2) { betterCandidate = i; } } } if(betterCandidate != -1) { candidate = betterCandidate; } Encoding *spillInstruction = spill64(candidate); MMX[candidate].spill.reference = MMX[candidate].reference; MMX[candidate].spill.priority = MMX[candidate].priority; MMX[candidate].spill.partial = MMX[candidate].partial; MMX[candidate].spill.copyInstruction = MMX[candidate].copyInstruction; MMX[candidate].spill.loadInstruction = MMX[candidate].loadInstruction; MMX[candidate].spill.spillInstruction = MMX[candidate].spillInstruction; MMX[candidate].reference = 0; MMX[candidate].priority = 0; MMX[candidate].partial = 0; MMX[candidate].copyInstruction = 0; MMX[candidate].loadInstruction = 0; MMX[candidate].spillInstruction = spillInstruction; return allocate64(candidate, ref, copy); }