#include <stdio.h>
#include <assert.h>
#include <string.h>
#include "ast.h"
#include "ssa.h"
#include "mips.h"
int reg_v0 = 2;
int reg_v1 = 3;
int memcpy_cnt;
static int save_pos[32];
static int used_reg[32];
static CType_t func;
void mips_prologue(void) {
CVList_t v;
CSList_t s;
int prev = 0;
printf(".data 0x10000000\n");
for (v = gvars; v; v = v->next)
{
CVar_t var = v->var;
printf("\t.align 2\n");
printf("_%s:\n", var->name);
prev += align_shift(prev);
var->start = prev;
prev += calc_size(var->type);
if (var->initr)
{
CNode *initr = var->initr->chd;
assert(var->initr->rec.subtype == INITR_NORM);
switch (initr->ext.type->type)
{
case CINT:
printf("\t.word %ld\n", initr->ext.const_val);
break;
case CCHAR:
printf("\t.byte %ld\n", initr->ext.const_val);
break;
case CPTR:
{
CType_t ref = initr->ext.type->rec.ref;
printf("\t.word ");
switch (ref->type)
{
case CFUNC:
printf("%s\n", initr->rec.strval);
break;
case CCHAR:
printf("_str_%d\n", ((CSList_t)initr->ext.const_val)->id);
break;
default: assert(0);
}
}
break;
default: assert(0);
}
}
else
printf("\t.space %d\n", calc_size(var->type));
}
printf("\t.align 2\n");
prev += align_shift(prev);
for (s = cstrs->next; s != cstrs; s = s->next)
{
int len = 1;
char *p = s->str;
printf("_str_%d:\n", s->id);
printf("\t.asciiz \"%s\"\n", s->str);
s->start = prev;
for (; *p != '\0'; p++)
{
len++;
if (*p == '\\')
{
switch (*(++p))
{
case '0': p += 3; break;
case 'x': p += 2; break;
default: ;
}
}
}
prev += len;
}
/* pre-calc done */
printf(".text\n");
}
#define IN_IMM(x) (-0x8000 <= (x) && (x) < 0x8000)
void mips_global_addr(int reg, CVar_t var) {
int offset = var->start - 0x8000;
if (IN_IMM(offset))
printf("\taddiu $%d, $gp, %d #%s\n", reg, offset, var->name);
else
printf("\tla $%d, _%s\n", reg, var->name);
}
void mips_global(const char *l, int reg, CVar_t var) {
int offset = var->start - 0x8000;
if (IN_IMM(offset))
printf("\t%s $%d, %d($gp) #%s\n", l, reg, offset, var->name);
else
printf("\t%s $%d, _%s\n", l, reg, var->name);
}
void mips_load(int reg, COpr_t opr) {
CVar_t var = opr->spill->info.var;
CType_t type = opr->type;
if (opr->kind == VAR &&
(type->type == CSTRUCT ||
type->type == CUNION ||
type->type == CARR))
{
if (var->loc > 0)
mips_global_addr(reg, var);
else
printf("\taddiu $%d, $sp, %d\n", reg, var->start);
}
else
{
const char *l = type->type == CCHAR ? "lb" : "lw";
if (var->loc > 0)
mips_global(l, reg, var);
else
printf("\t%s $%d, %d($sp)\t#%s\n", l, reg, var->start, var->name);
}
}
void mips_store(int reg, COpr_t opr) {
CVar_t var = opr->spill->info.var;
CType_t type = opr->type;
const char *l = type->type == CCHAR ? "sb" : "sw";
if (var->loc > 0)
mips_global(l, reg, var);
else if (opr->reg == -1)
printf("\t%s $%d, %d($sp)\t#%s\n", l, reg, var->start, var->name);
}
int mips_to_reg(COpr_t opr, int reg0) {
if (opr->kind == IMM)
{
printf("\tli $%d, %d\n", reg0, opr->info.imm);
return reg0;
}
else if (opr->kind == IMMS)
{
CSList_t cstr = opr->info.cstr;
int offset = cstr->start - 0x8000;
if (IN_IMM(offset))
printf("\taddiu $%d, $gp, %d # _str_%d\n", reg0, offset, cstr->id);
else
printf("\tla $%d, _str_%d\n", reg0, cstr->id);
return reg0;
}
else if (opr->kind