int mapFPR(int fpr, int dbl){ PowerPC_instr ppc; fprMap[fpr].lru = nextLRUValFPR++; fprMap[fpr].dbl = dbl; // Set whether this is a double-precision // If its already been mapped, just return that value // FIXME: Do I need to worry about conversions between single and double? if(fprMap[fpr].map >= 0) return fprMap[fpr].map; fprMap[fpr].dirty = 0; // If it hasn't previously been mapped, its clean // Try to find any already available register fprMap[fpr].map = getAvailableFPR(); // If didn't find an available register, flush one if(fprMap[fpr].map < 0) fprMap[fpr].map = flushLRUFPR(); // Load the register from memory (indirectly) if(dbl){ GEN_LWZ(ppc, R0, SDAREL(reg_cop1_double) + fpr*4, R13); set_next_dst(ppc); GEN_LFDX(ppc, fprMap[fpr].map, 0, R0); set_next_dst(ppc); } else { GEN_LWZ(ppc, R0, SDAREL(reg_cop1_simple) + fpr*4, R13); set_next_dst(ppc); GEN_LFSX(ppc, fprMap[fpr].map, 0, R0); set_next_dst(ppc); } return fprMap[fpr].map; }
int mapRegister(int gpr){ PowerPC_instr ppc; if(!gpr) return DYNAREG_ZERO; // Return r0 mapped to r31 regMap[gpr].lru = nextLRUVal++; // If its already been mapped, just return that value if(regMap[gpr].map.lo >= 0){ // Note: We don't want to free any 64-bit mapping that may exist // because this may be a read-after-64-bit-write return regMap[gpr].map.lo; } regMap[gpr].dirty = 0; // If it hasn't previously been mapped, its clean // Iterate over the HW registers and find one that's available int available = getAvailableHWReg(); if(available >= 0){ GEN_LWZ(ppc, available, SDAREL(reg) + gpr*8+4, R13); set_next_dst(ppc); return regMap[gpr].map.lo = available; } // We didn't find an available register, so flush one RegMapping lru = flushLRURegister(); if(lru.hi >= 0) availableRegs[lru.hi] = 1; // And load the registers value to the register we flushed GEN_LWZ(ppc, lru.lo, SDAREL(reg) + gpr*8+4, R13); set_next_dst(ppc); return regMap[gpr].map.lo = lru.lo; }
RegMapping mapRegister64(int gpr){ PowerPC_instr ppc; if(!gpr) return (RegMapping){ DYNAREG_ZERO, DYNAREG_ZERO }; regMap[gpr].lru = nextLRUVal++; // If its already been mapped, just return that value if(regMap[gpr].map.lo >= 0){ // If the hi value is not mapped, find a mapping if(regMap[gpr].map.hi < 0){ // Try to find any already available register int available = getAvailableHWReg(); if(available >= 0){ regMap[gpr].map.hi = available; } else { // We didn't find an available register, so flush one RegMapping lru = flushLRURegister(); if(lru.hi >= 0) availableRegs[lru.hi] = 1; regMap[gpr].map.hi = lru.lo; } if(regMap[gpr].sign){ // Sign extend to 64-bits GEN_SRAWI(ppc, regMap[gpr].map.hi, regMap[gpr].map.lo, 31); set_next_dst(ppc); } else { GEN_LI(ppc, regMap[gpr].map.hi, 0); set_next_dst(ppc); } } // Return the mapping return regMap[gpr].map; } regMap[gpr].dirty = 0; // If it hasn't previously been mapped, its clean // Try to find any already available registers regMap[gpr].map.hi = getAvailableHWReg(); regMap[gpr].map.lo = getAvailableHWReg(); // If there weren't enough registers, we'll have to flush if(regMap[gpr].map.lo < 0){ // We didn't find any available registers, so flush one RegMapping lru = flushLRURegister(); if(lru.hi >= 0) regMap[gpr].map.hi = lru.hi; regMap[gpr].map.lo = lru.lo; } if(regMap[gpr].map.hi < 0){ // We didn't find an available register, so flush one RegMapping lru = flushLRURegister(); if(lru.hi >= 0) availableRegs[lru.hi] = 1; regMap[gpr].map.hi = lru.lo; } // Load the values into the registers GEN_LWZ(ppc, regMap[gpr].map.hi, SDAREL(reg) + gpr*8, R13); set_next_dst(ppc); GEN_LWZ(ppc, regMap[gpr].map.lo, SDAREL(reg) + gpr*8+4, R13); set_next_dst(ppc); // Return the mapping return regMap[gpr].map; }
// Actually perform the store for a dirty register mapping static void _flushFPR(int fpr){ PowerPC_instr ppc; // Store the register to memory (indirectly) if(fprMap[fpr].dbl){ GEN_LWZ(ppc, R0, SDAREL(reg_cop1_double) + fpr*4, R13); set_next_dst(ppc); GEN_STFDX(ppc, fprMap[fpr].map, 0, R0); set_next_dst(ppc); } else { GEN_LWZ(ppc, R0, SDAREL(reg_cop1_simple) + fpr*4, R13); set_next_dst(ppc); GEN_STFSX(ppc, fprMap[fpr].map, 0, R0); set_next_dst(ppc); } }
// Actually perform the store for a dirty register mapping static void _flushFPR(int reg){ PowerPC_instr ppc; // Store the register to memory (indirectly) int addr = mapRegisterTemp(); if(fprMap[reg].dbl){ GEN_LWZ(ppc, addr, reg*4, DYNAREG_FPR_64); set_next_dst(ppc); GEN_STFD(ppc, fprMap[reg].map, 0, addr); set_next_dst(ppc); } else { GEN_LWZ(ppc, addr, reg*4, DYNAREG_FPR_32); set_next_dst(ppc); GEN_STFS(ppc, fprMap[reg].map, 0, addr); set_next_dst(ppc); } unmapRegisterTemp(addr); }