diff options
author | Ash Wolf <ninji@wuffs.org> | 2023-01-26 11:30:47 +0000 |
---|---|---|
committer | Ash Wolf <ninji@wuffs.org> | 2023-01-26 11:30:47 +0000 |
commit | 094b96ca1df4a035b5f93c351f773306c0241f3f (patch) | |
tree | 95ce05e3ebe816c7ee7996206bb37ea17d8ca33c /compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/RegisterInfo.c | |
parent | fc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff) | |
download | MWCC-main.tar.gz MWCC-main.zip |
move lots of source files around to match their actual placement in the original treemain
Diffstat (limited to 'compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/RegisterInfo.c')
-rw-r--r-- | compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/RegisterInfo.c | 381 |
1 files changed, 381 insertions, 0 deletions
diff --git a/compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/RegisterInfo.c b/compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/RegisterInfo.c new file mode 100644 index 0000000..177c2e0 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/RegisterInfo.c @@ -0,0 +1,381 @@ +#include "compiler/RegisterInfo.h" +#include "compiler/CodeGen.h" +#include "compiler/CError.h" +#include "compiler/CParser.h" +#include "compiler/PCode.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +short last_exception_register[RegClassMax]; +short first_fe_temporary_register[RegClassMax]; +short last_argument_register[RegClassMax]; +short _FP_; +short _CALLER_SP_; +char *special_register_names[RegClassMax][RegisterMax]; +static short used_regs_before_coloring; +static UInt8 save_state[RegisterMax]; + +short spr_to_sysreg[4] = {1, 8, 9, 0x100}; + +void asm_used_register(RegClass rclass, short reg) { + int i; + + if ((reg < n_real_registers[rclass]) && (reg_state[rclass][reg] == RegState0)) { + if (reg == nonvolatile_registers[rclass][used_nonvolatile_registers[rclass]]) { + if (assignable_registers[rclass] > 0) + assignable_registers[rclass]--; + reg_state[rclass][reg] = RegState1; + used_nonvolatile_registers[rclass]++; + } else { + for (i = used_nonvolatile_registers[rclass]; i < n_nonvolatile_registers[rclass]; i++) { + if (reg == nonvolatile_registers[rclass][i]) { + reg_state[rclass][reg] = RegState1; + if (assignable_registers[rclass] > 0) + assignable_registers[rclass]--; + } + } + } + } +} + +void retain_register(Object *obj, RegClass rclass, short reg) { + VarInfo *vi; + + CError_ASSERT(95, (short) reg < RegisterMax); + + if (reg_state[rclass][reg] == RegState0) { + assignable_registers[rclass]--; + reg_state[rclass][reg] = RegState1; + if (reg == nonvolatile_registers[rclass][used_nonvolatile_registers[rclass]]) + used_nonvolatile_registers[rclass]++; + } + + if (obj) { + vi = Registers_GetVarInfo(obj); + vi->rclass = rclass; + vi->flags |= VarInfoFlag2; + vi->reg = reg; + } +} + +void retain_GPR_pair(Object *obj, short reg, short regHi) { + VarInfo *vi; + + retain_register(NULL, RegClass_GPR, reg); + retain_register(NULL, RegClass_GPR, regHi); + + if (obj) { + vi = Registers_GetVarInfo(obj); + vi->rclass = RegClass_GPR; + vi->flags |= VarInfoFlag2 | VarInfoFlag4; + vi->reg = reg; + vi->regHi = regHi; + } +} + +int is_register_object(Object *obj) { + return obj->sclass == TK_REGISTER; +} + +int GetABIFirstNonVolatile(RegClass rclass) { + switch (rclass) { + case RegClass_SPR: return 3; + case RegClass_CRFIELD: return 2; + case RegClass_VR: return 20; + case RegClass_GPR: return 13; + case RegClass_FPR: return 14; + default: return -1; + } +} + +char GetRegisterClassName(RegClass rclass) { + switch (rclass) { + case RegClass_VR: return 'v'; + case RegClass_GPR: return 'r'; + case RegClass_FPR: return 'f'; + default: + CError_FATAL(242); + return '?'; + } +} + +static int first_nonvolatile_reg(RegClass rclass) { + return GetABIFirstNonVolatile(rclass); +} + +void setup_diagnostic_reg_strings(void) { + register_class_name[RegClass_SPR] = "SPR"; + register_class_format[RegClass_SPR] = "spr%" PRId32; + register_class_name[RegClass_CRFIELD] = "CRFIELD"; + register_class_format[RegClass_CRFIELD] = "cr%" PRId32; + register_class_name[RegClass_VR] = "VR"; + register_class_format[RegClass_VR] = "vr%" PRId32; + register_class_name[RegClass_FPR] = "FPR"; + register_class_format[RegClass_FPR] = "f%" PRId32; + register_class_name[RegClass_GPR] = "GPR"; + register_class_format[RegClass_GPR] = "r%" PRId32; +} + +void init_target_registers(void) { + int reg; + int end; + RegClass rclass; + + static int last_nonvolatile_reg[] = {3, 5, 31, 31, 31}; + static int nonvol_reserve[] = {0, 0, 0, 4, 3}; + + for (rclass = 0; rclass < RegClassMax; rclass++) { + for (reg = 0; reg < RegisterMax; reg++) + special_register_names[rclass][reg] = NULL; + } + + special_register_names[RegClass_SPR][0] = "XER"; + special_register_names[RegClass_SPR][1] = "LR"; + special_register_names[RegClass_SPR][2] = "CTR"; + special_register_names[RegClass_SPR][3] = "VRSAVE"; + special_register_names[RegClass_GPR][1] = "SP"; + + setup_diagnostic_reg_strings(); + n_real_registers[RegClass_SPR] = 4; + n_real_registers[RegClass_CRFIELD] = 8; + n_real_registers[RegClass_VR] = 32; + n_real_registers[RegClass_FPR] = 32; + n_real_registers[RegClass_GPR] = 32; + reg_state[RegClass_GPR][1] = RegState2; + reg_state[RegClass_GPR][2] = RegState2; + reg_state[RegClass_CRFIELD][5] = RegState2; + + for (rclass = 0; rclass < RegClassMax; rclass++) { + n_nonvolatile_registers[rclass] = 0; + if (last_nonvolatile_reg[rclass] >= 0) { + end = first_nonvolatile_reg(rclass); + for (reg = last_nonvolatile_reg[rclass]; reg >= end; reg--) { + if (reg_state[rclass][reg] == RegState0) { + nonvolatile_registers[rclass][n_nonvolatile_registers[rclass]++] = reg; + } + } + } + + assignable_registers[rclass] = n_nonvolatile_registers[rclass] - nonvol_reserve[rclass]; + if (assignable_registers[rclass] < 0) + assignable_registers[rclass] = 0; + + n_scratch_registers[rclass] = 0; + for (reg = 0; reg < n_real_registers[rclass]; reg++) { + if (reg < GetABIFirstNonVolatile(rclass) || reg > last_nonvolatile_reg[rclass]) { + if (reg_state[rclass][reg] == RegState0) { + scratch_registers[rclass][n_scratch_registers[rclass]++] = reg; + } + } + } + } + + _FP_ = -1; + _CALLER_SP_ = -1; + optimizing = (copts.optimizationlevel > 0) && !disable_optimizer; +} + +void assign_register_by_type(Object *obj) { + VarInfo *vi; + Type *ty; + Boolean flag; + + ty = obj->type; + vi = Registers_GetVarInfo(obj); + flag = 0; + vi->rclass = RegClassMax; + vi->reg = 0; + vi->regHi = 0; + + if ((ty->type == TYPEINT) || (ty->type == TYPEENUM) || ((ty->type == TYPEPOINTER || ty->type == TYPEARRAY) && (ty->type != TYPEARRAY)) || ((ty->type == TYPEMEMBERPOINTER) && (ty->size == 4U))) { + if (((ty->type == TYPEINT) || (ty->type == TYPEENUM)) && (ty->size == 8)) + flag = 1; + vi->rclass = RegClass_GPR; + } else if (ty->type == TYPEFLOAT) { + vi->rclass = RegClass_FPR; + } else if ((ty->type == TYPESTRUCT) && (TYPE_STRUCT(ty)->stype >= STRUCT_VECTOR_UCHAR) && (TYPE_STRUCT(ty)->stype <= STRUCT_VECTOR_PIXEL)) { + vi->rclass = RegClass_VR; + } else { + return; + } + + if (vi->rclass < RegClassMax) { + if (flag) { + CError_ASSERT(520, vi->rclass == RegClass_GPR); + if (assignable_registers[vi->rclass] > 1) + assign_GPR_pair(obj); + } else { + if (assignable_registers[vi->rclass] > 0) + assign_register_to_variable(obj, vi->rclass); + } + } +} + +void assign_GPR_pair(Object *obj) { + VarInfo *vi; + short reg; + short regHi; + + vi = Registers_GetVarInfo(obj); + if (optimizing) { + reg = used_virtual_registers[RegClass_GPR]++; + regHi = used_virtual_registers[RegClass_GPR]++; + } else { + CError_ASSERT(554, assignable_registers[RegClass_GPR] >= 2); + reg = obtain_nonvolatile_register(RegClass_GPR); + regHi = obtain_nonvolatile_register(RegClass_GPR); + retain_GPR_pair(obj, reg, regHi); + } + + vi->rclass = RegClass_GPR; + if (reg > 0 && regHi > 0) { + vi->flags |= VarInfoFlag2 | VarInfoFlag4; + vi->reg = reg; + vi->regHi = regHi; + } else { + CError_FATAL(567); + } +} + +void open_fe_temp_registers(void) { + int r; + + r = used_virtual_registers[RegClass_GPR]; + first_fe_temporary_register[RegClass_GPR] = last_temporary_register[RegClass_GPR] = r; + r = used_virtual_registers[RegClass_FPR]; + first_fe_temporary_register[RegClass_FPR] = last_temporary_register[RegClass_FPR] = r; + r = used_virtual_registers[RegClass_VR]; + first_fe_temporary_register[RegClass_VR] = last_temporary_register[RegClass_VR] = r; +} + +void set_last_exception_registers(void) { + last_exception_register[RegClass_GPR] = used_virtual_registers[RegClass_GPR] - 1; + last_exception_register[RegClass_FPR] = used_virtual_registers[RegClass_FPR] - 1; + last_exception_register[RegClass_VR] = used_virtual_registers[RegClass_VR] - 1; +} + +static VarInfo *Registers_GetNewVarInfo(void) { + VarInfo *vi = galloc(sizeof(VarInfo)); + memclrw(vi, sizeof(VarInfo)); + return vi; +} + +VarInfo *Registers_GetVarInfo(Object *obj) { + switch (obj->datatype) { + case DDATA: + if (!obj->u.data.info) + obj->u.data.info = Registers_GetNewVarInfo(); + return obj->u.data.info; + case DNONLAZYPTR: + if (!obj->u.toc.info) { + CError_FATAL(639); + obj->u.toc.info = CodeGen_GetNewVarInfo(); + } + return obj->u.toc.info; + case DLOCAL: + if (!obj->u.var.info) + CError_FATAL(647); + return obj->u.var.info; + case DABSOLUTE: + // not sure if this is the right union + if (!obj->u.data.info) + obj->u.data.info = Registers_GetNewVarInfo(); + return obj->u.data.info; + default: + CError_FATAL(660); + return NULL; + } +} + +int used_vrstate_VRs(void) { + int count = 0; + int i; + for (i = 0; i < RegisterMax; i++) { + if (reg_state[RegClass_VR][i]) + count++; + } + return count; +} + +UInt32 colored_vrs_as_vrsave(PCodeBlock *block) { + PCode *pc; + UInt32 mask; + int i; + + mask = 0; + if (copts.altivec_vrsave == 2) + return 0xFFFFFFFF; + if (copts.altivec_vrsave == 0) + return 0; + + while (block) { + for (pc = block->firstPCode; pc; pc = pc->nextPCode) { + if (pc->flags & fOpTypeVR) { + for (i = 0; i < pc->argCount; i++) { + if (pc->args[i].kind == PCOp_REGISTER && pc->args[i].arg == RegClass_VR) + mask |= 1 << (31 - pc->args[i].data.reg.reg); + } + } + } + block = block->nextBlock; + } + + return mask; +} + +void save_before_coloring_nonvolatile_registers(RegClass rclass) { + used_regs_before_coloring = used_nonvolatile_registers[rclass]; + memcpy(save_state, reg_state[rclass], sizeof(save_state)); +} + +void reset_nonvolatile_registers(RegClass rclass) { + used_nonvolatile_registers[rclass] = used_regs_before_coloring; + memcpy(reg_state[rclass], save_state, sizeof(save_state)); +} + +int is_nonvolatile_register(RegClass rclass, int reg) { + int i; + + for (i = 0; i < n_nonvolatile_registers[rclass]; i++) { + if (reg == nonvolatile_registers[rclass][i]) + return 1; + } + + return 0; +} + +void init_endian(void) { + if (copts.littleendian) { + high_offset = 4; + low_offset = 0; + high_reg = 4; + low_reg = 3; + high_reg2 = 6; + low_reg2 = 5; + } else { + high_offset = 0; + low_offset = 4; + high_reg = 3; + low_reg = 4; + high_reg2 = 5; + low_reg2 = 6; + } +} + +void update_asm_nonvolatile_registers(void) { + RegClass rclass; + int i; + int reg; + + for (rclass = 0; rclass < RegClassMax; rclass++) { + reg = n_nonvolatile_registers[rclass]; + for (i = n_nonvolatile_registers[rclass] - 1; i >= 0; i--) { + if (reg_state[rclass][nonvolatile_registers[rclass][i]] == RegState1) + break; + reg--; + } + if (reg > used_nonvolatile_registers[rclass]) + used_nonvolatile_registers[rclass] = reg; + } +} |