// Sparc code generator
package sparc;
public class Codegen {
SparcFrame frame;
public Codegen(SparcFrame f) {
frame = f;
}
private static String myVariable = "\t";
private static String variable1 = "\n";
private assem.InstrList ilist = null, last = null;
private void emit(assem.Instr inst) {
// Add inst to the end of ilist.
if (last != null)
last = last.tail = new assem.InstrList(inst, null);
else
last = ilist = new assem.InstrList(inst, null);
}
static temp.TempList L(temp.Temp h, temp.TempList t) {
return new temp.TempList(h, t);
}
static boolean is13bitCONST(tree.Exp e) {
if (e instanceof tree.CONST) {
int val = ((tree.CONST) e).value;
return (-4096 <= val && val < 4096);
} else
return false;
}
void munchStm(tree.Stm s) {
if (s instanceof tree.MOVE)
munchStm((tree.MOVE) s);
else if (s instanceof tree.EXP)
munchStm((tree.EXP) s);
else if (s instanceof tree.JUMP)
munchStm((tree.JUMP) s);
else if (s instanceof tree.CJUMP)
munchStm((tree.CJUMP) s);
else if (s instanceof tree.LABEL)
munchStm((tree.LABEL) s);
else
throw new Error("munchStm dispatch");
}
/* MOVE */
void munchStm(tree.MOVE s) {
if (s.dst instanceof tree.TEMP)
munchExp(s.src, ((tree.TEMP) s.dst).temp);
else if (s.dst instanceof tree.MEM) {
tree.Exp e = ((tree.MEM) s.dst).exp;
if (e instanceof tree.BINOP) {
tree.BINOP eBINOP = (tree.BINOP) e;
if (eBINOP.left instanceof tree.CONST) {
tree.CONST eCONSTLeft = (tree.CONST) eBINOP.left;
//
temp.Temp rightTemp = munchExp(eBINOP.right);
//
emit(new assem.OPER(myVariable + "st" + myVariable + "`s1, [`s0+"
+ eCONSTLeft.value + "]\n", null, L(rightTemp, L(munchExp(s.src), null))));
} else if (eBINOP.right instanceof tree.CONST) {
tree.CONST eCONSTRight = (tree.CONST) eBINOP.right;
//
temp.Temp leftTemp = munchExp(eBINOP.left);
//
emit(new assem.OPER(myVariable + "st" + myVariable + "`s1, [`s0+"
+ eCONSTRight.value + "]\n", null, L(leftTemp, L(
munchExp(s.src), null))));
} else {
emit(new assem.OPER(myVariable + "st" + myVariable + "`s1, [`s0]\n",
null, L(munchExp(e), L(munchExp(s.src), null))));
}
} else {
emit(new assem.OPER(myVariable + "st" + myVariable + "`s1, [`s0]\n", null, L(
munchExp(e), L(munchExp(s.src), null))));
}
} else
throw new Error("Very Bad MOVE destination.");
}
// Here is munchExp as specified by Appel on p. 193.
temp.Temp munchExp(tree.Exp e) {
return munchExp(e, null);
}
temp.Temp munchExp(tree.Exp e, temp.Temp r) {
if (e instanceof tree.CONST)
return munchExp((tree.CONST) e, r);
if (e instanceof tree.NAME)
return munchExp((tree.NAME) e, r);
if (e instanceof tree.TEMP)
return munchExp((tree.TEMP) e, r);
if (e instanceof tree.BINOP)
return munchExp((tree.BINOP) e, r);
if (e instanceof tree.MEM)
return munchExp((tree.MEM) e, r);
if (e instanceof tree.CALL)
return munchExp((tree.CALL) e, r);
else
throw new Error("munchExp dispatch");
}
assem.InstrList codegen(tree.Stm s) {
assem.InstrList l;
munchStm(s);
l = ilist;
ilist = last = null;
return l;
}
temp.Temp munchExp(tree.CONST e, temp.Temp r) {
temp.Temp theTemp = r;
if (theTemp == null) {
theTemp = new temp.Temp();
}
if (!is13bitCONST(e)) {
emit(new assem.OPER(myVariable + "sethi" + myVariable + "%hi(" + e.value
+ "), `d0\n" + myVariable + "or" + myVariable + "`d0, %lo(" + e.value
+ "), `d0\n", L(theTemp, null), null));
} else {
emit(new assem.OPER(myVariable + "mov" + myVariable + e.value + ", `d0\n", L(
theTemp, null), null));
}
return theTemp;
}
temp.Temp munchExp(tree.CALL e, temp.Temp r) {
temp.TempList tempList = null;
tree.ExpList expList = (tree.ExpList) e.args;
int i = 0;
for (temp.Temp tempArgs = null; (expList != null)
&& (tempArgs = SparcFrame.outgoingArgs[i]) != null; i++) {
munchExp(expList.head, tempArgs);
tempList = L(tempArgs, tempList);
expList = expList.tail;
}
emit(new assem.OPER(myVariable + "call" + myVariable + "`j0\n", null, tempList,
new temp.LabelList(((tree.NAME) e.func).label, null)));
emit(new assem.OPER(myVariable + "nop\n", null, null));
if (r == null)
r = frame.RVCaller();
else
emit(new assem.MOVE(myVariable + "mov" + myVariable + "`s0, `d0\n", r, frame
.RVCaller()));
return r;
}
/* MEM */
temp.Temp munchExp(tree.MEM m, temp.Temp r) {
if (r == null)
r = new temp.Temp();
tree.Exp e1 = m.exp;
if (e1 instanceof tree.BINOP) {
tree.BINOP binOp = (tree.BINOP) e1;
tree.Exp which = binOp.right;
tree.Exp other = binOp.left;
if (binOp.left instanceof tree.CONST) {
which = binOp.left;
other = binOp.right;
}
if (which instanceof tree.CONST) {
emit(new assem.OPER(myVariable + "ld" + myVariable + "[`s0+"
+ ((tree.CONST) which).value + "], `d0\n", L(r, null),
L(munchExp(other, null), null)));
}
else
emit(new assem.OPER(myVariable + "ld" + myVariable + "[`s0], `d0\n", L(r,
null), L(munchExp(e1), null)));
}
else if (e1 instanceof tree.CONST) {
emit(new assem.OPER(myVariable + "ld" + myVariable + "[`s0+"
+ ((tree.CONST) e1).value + "], `d0\n", L(r, null), null));
}
else if (e1 instanceof tree.Exp) {
emit(new assem.OPER(myVariable + "ld" + myVariable + "[`s0], `d0\n", L(r, null),
L(munchExp(e1), null)));
}
else
throw new Error("MEM unsupported parameters");
return r;
}
/* CJUMP */
void munchStm(tree.CJUMP s) {
String arg[] = { "be", "bne", "bl", "bg", "ble", "bge" };
String argOp[] = { "be", "bne", "bg", "bl", "bge", "ble" };
temp.LabelList lbl = new temp.LabelList(s.iftrue, new temp.LabelList(
s.iffalse, null));
if (s.left instanceof tree.CONST) {
if (s.right instanceof tree.CONST) {
tree.CONST left = (tree.CONST) s.left;
tree.CONST right = (tree.CONST) s.right;
temp.Label which;
switch (s.relop) {
case tree.CJUMP.EQ:
which = (left.value == right.value) ? s.iftrue : s.iffalse;
break;
case tree.CJUMP.GE:
which = (left.value >= right.value) ? s.iftrue : s.iffalse;
break;
case tree.CJUMP.GT:
which = (left.value > right.value) ? s.iftrue : s.iffalse;
break;
case tree.CJUMP.LE:
which = (left.value <= right.value) ? s.iftrue : s.iffalse;
break;
case tree.CJUMP.LT:
which = (left.value < right.value) ? s.iftrue : s.iffalse;
break;
case tree.CJUMP.NE:
which = (left.value != right.value) ? s.iftrue : s.iffalse;
break;
default:
throw new Error("Unreported operator in cmp - not Supported");
}
emit(new assem.OPER(myVariable + "ba" + myVariable + "`l0\n", null, null,
new temp.LabelList(which, null)));
} else {
emit(new assem.OPER(myVariable + "cmp" + myVariable + "`s0, "
+ ((tree.CONST) s.left).value + "\n" + myVariable
+ argOp[s.relop] + myVariable + "`j0\n", null, L(munchExp(
s.right, null), null), lbl));
}
} else if (s.right instanceof tree.CONST) {
emit(new assem.OPER(myVariable + "cmp" + myVariable + "`s0, "
+ ((tree.CONST) s.right).value + "\n" + myVariable + arg[s.relop]
+ myVariable + "`j0\n", null, L(munchExp(s.left, null), null), lbl));
} else {
emit(new assem.OPER(myVariable + "cmp" + myVariable + "`s0, `s1\n" + myVariable
+ arg[s.relop] + myVariable + "`j0\n", null, L(munchExp(s.left,
null), L(munchExp(s.right, null), null)), lbl));
}
emit(new assem.OPER(myVariable + "nop\n", null, null));
}
/* LABEL */
void munchStm(tree.LABEL l) {
emit(new assem.LABEL(l.label + ":\n", l.label));
}
/* EXP */
void munchStm(tree.EXP e) {
munchExp(e.exp, null);
}
/* JUMP */
void munchStm(tree.JUMP j) {
emit(new assem.OPER(myVariable + "ba" + myVariable + "`j0\n" + myVariable + "nop\n", null,
null, j.targets));
}
/* NAME */
temp.Temp munchExp(tree.NAME n, temp.Temp r) {
throw new Error("Invalid NAME expression found!");
}
/* TEMP */
temp.Temp munchExp(tree.TEMP t, temp.Temp r) {
if (r == null)
return t.temp;
// Do not move to itself
if (!t.temp.toString().equals(r.toString()))
emit(new assem.MOVE(myVariable + "mov" + myVariable + "`s0, `d0\n", r, t.temp));
return r;
}
/* BINOP */
temp.Temp munchExp(tree.BINOP e, temp.Temp r) {
temp.Temp tmp;
String code;
if (r != null)
tmp = r;
else
tmp = new temp.Temp();
switch (e.binop) {
case tree.BINOP.PLUS:
code = myVariable + "add" + myVariable;
break;
case tree.BINOP.MINUS:
code = myVariable + "sub" + myVariable;
break;
case tree.BINOP.MUL:
code = myVariable + "smul" + myVariable;
break;
case tree.BINOP.DIV:
code = myVariable + "sdiv" + myVariable;
break;
case tree.BINOP.AND:
code = myVariable + "and" + myVariable;
break;
case tree.BINOP.OR:
code = myVariable + "or" + myVariable;
break;
case tree.BINOP.LSHIFT:
code = myVariable + "sll" + myVariable;
break;
case tree.BINOP.RSHIFT:
code = myVariable + "srl" + myVariable;
break;
case tree.BINOP.ARSHIFT:
code = myVariable + "sra" + myVariable;
break;
case tree.BINOP.XOR:
code = myVariable + "xor" + myVariable;
break;
default:
throw new Error("No such binop!");
}
if (is13bitCONST(e.right)) {
code += "`s0, " + ((tree.CONST) e.right).value + ", `d0\n";
emit(new assem.OPER(code, L(tmp, null), L(munchExp(e.left), null)));
} else if (is13bitCONST(e.left)) {
code += ((tree.CONST) e.left).value + " ,`s0, `d0\n";
emit(new assem.OPER(code, L(tmp, null), L(munchExp(e.right), null)));
} else {
code += "`s0, `s1, `d0\n";
emit(new assem.OPER(code, L(tmp, null), L(munchExp(e.left), L(
munchExp(e.right), null))));
}
return tmp;
}
}
www.cpccci.com
www.cpcwebsolutions.com
www.cpcwebdevelopment.com