blob: 3e3d1d688ad4b1ee688d1ac43ac875d638605299 [file] [log] [blame]
/*---------------------------------------------------------------*/
/*--- ---*/
/*--- This file (host_regs.c) is ---*/
/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/
/*--- ---*/
/*---------------------------------------------------------------*/
#include <stdio.h>
#include <malloc.h>
#include "basictypes.h"
#include "host_regs.h"
HReg mkHReg ( UInt regno, HRegClass rc, Bool virtual )
{
UInt r24 = regno & 0x00FFFFFF;
/* This is critical. The register number field may only
occupy 24 bits. */
if (r24 != regno)
panic("mkHReg: regno exceeds 2^24");
return regno | (((UInt)rc) << 28) | (virtual ? (1<<24) : 0);
}
HRegClass hregClass ( HReg r )
{
UInt rc = r;
rc = (rc >> 28) & 0x0F;
assert(rc == HRcInt || rc == HRcFloat || rc == HRcVector
|| rc == HRcInt64 || rc == HRcVector128);
return (HRegClass)rc;
}
Bool hregIsVirtual ( HReg r )
{
return (((UInt)r) & (1<<24)) ? True : False;
}
UInt hregNumber ( HReg r )
{
return ((UInt)r) & 0x00FFFFFF;
}
void ppHRegClass ( FILE* f, HRegClass hrc )
{
switch (hrc) {
case HRcInt: fprintf(f, "HRcInt32"); break;
case HRcInt64: fprintf(f, "HRcInt64"); break;
case HRcFloat: fprintf(f, "HRcFloat"); break;
case HRcVector: fprintf(f, "HRcVector64"); break;
case HRcVector128: fprintf(f, "HRcVector128"); break;
default: panic("ppHRegClass");
}
}
/* Generic printing for registers. */
void ppHReg ( FILE* f, HReg r )
{
Char* maybe_v = hregIsVirtual(r) ? "v" : "";
Int regNo = hregNumber(r);
switch (hregClass(r)) {
case HRcInt: fprintf(f, "%%%sr%d", maybe_v, regNo); return;
case HRcInt64: fprintf(f, "%%%sR%d", maybe_v, regNo); return;
case HRcFloat: fprintf(f, "%%%sf%d", maybe_v, regNo); return;
case HRcVector: fprintf(f, "%%%sv%d", maybe_v, regNo); return;
case HRcVector128: fprintf(f, "%%%sV%d", maybe_v, regNo); return;
default: panic("ppHReg");
}
}
/*---------------------------------------------------------*/
/*--- Helpers for recording reg usage (for reg-alloc) ---*/
/*---------------------------------------------------------*/
void ppHRegUsage ( FILE* f, HRegUsage* tab )
{
Int i;
Char* str;
fprintf(f, "HRegUsage {\n");
for (i = 0; i < tab->n_used; i++) {
switch (tab->mode[i]) {
case HRmRead: str = "Read "; break;
case HRmWrite: str = "Write "; break;
case HRmModify: str = "Modify "; break;
default: panic("ppHRegUsage");
}
fprintf(f, " %s ", str);
ppHReg(f, tab->hreg[i]);
fprintf(f, "\n");
}
fprintf(f, "}\n");
}
void initHRegUsage ( HRegUsage* tab )
{
tab->n_used = 0;
}
/* Add a register to a usage table. Combine incoming read uses with
existing write uses into a modify use, and vice versa. Do not
create duplicate entries -- each reg should only be mentioned once.
*/
void addHRegUse ( HRegUsage* tab, HRegMode mode, HReg reg )
{
Int i;
/* Find it ... */
for (i = 0; i < tab->n_used; i++)
if (tab->hreg[i] == reg)
break;
if (i == tab->n_used) {
/* Not found, add new entry. */
assert(tab->n_used+1 < N_HREG_USAGE);
tab->hreg[tab->n_used] = reg;
tab->mode[tab->n_used] = mode;
tab->n_used++;
} else {
/* Found: combine or ignore. */
if (tab->mode[i] == mode)
return; /* duplicate, ignore */
if (mode == HRmModify) {
tab->mode[i] = HRmModify;
return; /* modify mode makes previous mode irrelevant */
}
assert( (mode == HRmRead && tab->mode[i] == HRmWrite)
|| (mode == HRmWrite && tab->mode[i] == HRmRead) );
tab->mode[i] = HRmModify;
}
}
/*---------------------------------------------------------*/
/*--- Indicating register remappings (for reg-alloc) ---*/
/*---------------------------------------------------------*/
void ppHRegRemap ( FILE* f, HRegRemap* map )
{
Int i;
fprintf(f, "HRegRemap {\n");
for (i = 0; i < map->n_used; i++) {
fprintf(f, " ");
ppHReg(f, map->orig[i]);
fprintf(f, " --> ");
ppHReg(f, map->replacement[i]);
fprintf(f, "\n");
}
fprintf(f, "}\n");
}
void initHRegRemap ( HRegRemap* map )
{
map->n_used = 0;
}
void addToHRegRemap ( HRegRemap* map, HReg orig, HReg replacement )
{
Int i;
for (i = 0; i < map->n_used; i++)
if (map->orig[i] == orig)
panic("addToHRegMap: duplicate entry");
if (!hregIsVirtual(orig))
panic("addToHRegMap: orig is not a vreg");
if (hregIsVirtual(replacement))
panic("addToHRegMap: replacement is not a vreg");
assert(map->n_used+1 < N_HREG_REMAP);
map->orig[map->n_used] = orig;
map->replacement[map->n_used] = replacement;
map->n_used++;
}
HReg lookupHRegRemap ( HRegRemap* map, HReg orig )
{
Int i;
if (!hregIsVirtual(orig))
return orig;
for (i = 0; i < map->n_used; i++)
if (map->orig[i] == orig)
return map->replacement[i];
panic("lookupHRegRemap: not found");
}
/*---------------------------------------------------------*/
/*--- Abstract instructions ---*/
/*---------------------------------------------------------*/
HInstrArray* newHInstrArray ( void )
{
HInstrArray* ha = malloc(sizeof(HInstrArray));
ha->arr_size = 4;
ha->arr_used = 0;
ha->arr = malloc(ha->arr_size * sizeof(HInstr*));
ha->n_vregs = 0;
return ha;
}
void deleteHInstrArray ( HInstrArray* ha )
{
free(ha->arr);
free(ha);
}
void addHInstr ( HInstrArray* ha, HInstr* instr )
{
assert(ha->arr_used <= ha->arr_size);
if (ha->arr_used < ha->arr_size) {
ha->arr[ha->arr_used] = instr;
ha->arr_used++;
} else {
Int i;
HInstr** arr2 = malloc(ha->arr_size * 2 * sizeof(HInstr*));
for (i = 0; i < ha->arr_size; i++)
arr2[i] = ha->arr[i];
ha->arr_size *= 2;
free(ha->arr);
ha->arr = arr2;
addHInstr(ha, instr);
}
}
/*---------------------------------------------------------------*/
/*--- host_regs.c ---*/
/*---------------------------------------------------------------*/