// 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

CP