summaryrefslogtreecommitdiff
path: root/compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/RegisterInfo.c
diff options
context:
space:
mode:
authorAsh Wolf <ninji@wuffs.org>2023-01-26 11:30:47 +0000
committerAsh Wolf <ninji@wuffs.org>2023-01-26 11:30:47 +0000
commit094b96ca1df4a035b5f93c351f773306c0241f3f (patch)
tree95ce05e3ebe816c7ee7996206bb37ea17d8ca33c /compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/RegisterInfo.c
parentfc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff)
downloadMWCC-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.c381
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;
+ }
+}