2022-11-07 03:06:21 +00:00

226 lines
6.2 KiB
C

#include "compiler.h"
#include "compiler/objects.h"
#include "compiler/PCode.h"
// haven't checked this object file for .data stuff yet
// ONLY FOR TESTING
// this file gets kinda fucked up by the loop unroller
//#pragma opt_unroll_loops off
int used_virtual_registers[RegClassMax];
int used_nonvolatile_registers[RegClassMax];
int assignable_registers[RegClassMax];
int n_real_registers[RegClassMax];
int n_scratch_registers[RegClassMax];
int scratch_registers[RegClassMax][RegisterMax];
int n_nonvolatile_registers[RegClassMax];
int nonvolatile_registers[RegClassMax][RegisterMax];
UInt8 reg_state[RegClassMax][RegisterMax];
int first_temporary_register[RegClassMax];
int last_temporary_register[RegClassMax];
char *register_class_name[RegClassMax];
char *register_class_format[RegClassMax];
int coloring;
int optimizing;
typedef struct ModifiedRegisters {
struct ModifiedRegisters *next;
Object *obj;
UInt32 mask[RegClassMax];
} ModifiedRegisters;
static ModifiedRegisters *mod_regs_table[128];
void init_registers() {
char rclass;
int j;
for (rclass = 0; rclass < RegClassMax; rclass++) {
for (j = 0; j < RegisterMax; j++) {
reg_state[(char)rclass][j] = RegState0;
}
}
for (rclass = 0; rclass < RegClassMax; rclass++)
used_nonvolatile_registers[(char)rclass] = 0;
optimizing = 1;
init_target_registers();
for (rclass = 0; rclass < RegClassMax; rclass++)
used_virtual_registers[(char)rclass] = n_real_registers[(char)rclass];
coloring = 1;
}
void assign_register_to_variable(Object *obj, char rclass) {
VarInfo *vi;
short reg;
vi = Registers_GetVarInfo(obj);
if (optimizing) {
reg = used_virtual_registers[rclass]++;
} else {
reg = obtain_nonvolatile_register(rclass);
retain_register(obj, rclass, reg);
}
vi->flags |= VarInfoFlag2;
vi->rclass = rclass;
vi->reg = reg;
}
void retain_register_for_argument(Object *obj, char rclass, short reg) {
VarInfo *vi = obj->u.var.info;
reg_state[rclass][reg] = RegState1;
vi->flags |= VarInfoFlag2;
vi->rclass = rclass;
vi->reg = reg;
}
int available_registers(char rclass) {
int i;
int count = 0;
for (i = 0; i < n_real_registers[rclass]; i++) {
if (reg_state[rclass][i] == RegState0)
count++;
}
return count;
}
UInt32 volatile_registers(char rclass) {
UInt32 mask = 0;
int i;
int reg;
for (i = 0; i < n_scratch_registers[rclass]; i++) {
reg = scratch_registers[rclass][i];
if (reg_state[rclass][reg] == RegState0)
mask |= 1 << reg;
}
return mask;
}
short obtain_nonvolatile_register(char rclass) {
int best = -1;
while (used_nonvolatile_registers[rclass] < n_nonvolatile_registers[rclass]) {
int tmp = nonvolatile_registers[rclass][used_nonvolatile_registers[rclass]++];
if (reg_state[rclass][tmp] == RegState0) {
best = tmp;
break;
}
}
return best;
}
void open_temp_registers() {
int rclass;
for (rclass = 0; (char)rclass < RegClassMax; rclass++) {
int r = used_virtual_registers[(char)rclass];
//last_temporary_register[rclass] = r;
//first_temporary_register[rclass] = r;
first_temporary_register[(char)rclass] = last_temporary_register[(char)rclass] = r;
}
/*rclass = 0;
while (rclass < RegClassMax) {
r = used_virtual_registers[(char)rclass];
last_temporary_register[(char)rclass] = r;
first_temporary_register[(char)rclass] = r;
rclass = rclass + 1;
}*/
}
void check_temp_registers() {
char rclass;
if (!optimizing) {
for (rclass = 0; rclass < RegClassMax; rclass++) {
if (used_virtual_registers[(char)rclass] > last_temporary_register[(char)rclass])
last_temporary_register[(char)rclass] = used_virtual_registers[(char)rclass];
if (used_virtual_registers[(char)rclass] > 256)
used_virtual_registers[(char)rclass] = first_temporary_register[(char)rclass];
}
}
}
void close_temp_registers() {
char rclass;
for (rclass = 0; rclass < RegClassMax; rclass++) {
if (used_virtual_registers[(char)rclass] < last_temporary_register[(char)rclass])
used_virtual_registers[(char)rclass] = last_temporary_register[(char)rclass];
else
last_temporary_register[(char)rclass] = used_virtual_registers[(char)rclass];
}
}
int count_scratch_registers() {
int rclass;
int count;
count = 0;
for (rclass = 0; (char)rclass < RegClassMax; rclass++)
count += n_scratch_registers[(char)rclass];
return count;
}
void init_modified_registers() {
int i = 0;
for (i = 0; i < 128; i++)
mod_regs_table[i] = NULL;
}
static void compute_modified_registers(UInt32 *masks) {
int rclass;
PCodeBlock *block;
PCode *pcode;
int i;
for (rclass = 0; rclass < RegClassMax; rclass++)
masks[(char)rclass] = 0;
for (block = pcbasicblocks; block; block = block->nextBlock) {
for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
for (i = 0; i < pcode->argCount; i++) {
if (pcode->args[i].kind == PCOp_REGISTER && pcode->args[i].data.reg.effect & EffectWrite)
masks[pcode->args[i].arg] |= 1 << pcode->args[i].data.reg.reg;
}
}
}
}
void note_modified_registers(Object *obj) {
ModifiedRegisters *mr;
mr = galloc(sizeof(ModifiedRegisters));
mr->obj = obj;
compute_modified_registers(mr->mask);
mr->next = mod_regs_table[obj->name->hashval];
mod_regs_table[obj->name->hashval] = mr;
}
void find_modified_registers(Object *obj, UInt32 *masks) {
char rclass;
ModifiedRegisters *scan;
for (rclass = 0; rclass < RegClassMax; rclass++)
masks[(char)rclass] = 0xFFFFFFFF;
if (CParser_HasInternalLinkage(obj)) {
for (scan = mod_regs_table[obj->name->hashval]; scan; scan = scan->next) {
if (scan->obj == obj)
break;
}
if (scan) {
for (rclass = 0; rclass < RegClassMax; rclass++)
masks[(char)rclass] = scan->mask[(char)rclass];
}
}
}