// -classpath .:/home/apt/software/bcel/bcel-5.0rc1/bcel.jar

import java.io.*;
import java.util.*;
import org.apache.bcel.classfile.*;
import org.apache.bcel.generic.*;
import org.apache.bcel.*;

/**
 * Read a class file and generate the corresponding MIPS assembly code to stdout.
 * The command line usage is:
 *
 * <pre>java compile1 foo.class > foo.s </pre>
 */
public class compile1{

  // these variables are fixed for a given class file
  static ConstantPool cp;
  static ConstantPoolGen cpg;
  
  public static void main(String[] argv) throws IOException {
    JavaClass java_class = new ClassParser(argv[0]).parse();  // May throw IOException
    cp = java_class.getConstantPool();
    cpg = new ConstantPoolGen(cp);
    Method[] methods = java_class.getMethods();
    // Process each method
    for (int j = 0; j < methods.length; j++) 
      emit_method(methods[j]);
    // Emit exception handlers
    emit0(".text");
    emitlab("NASexception");
    emit2("la","$a0","NASmessage");
    emit1("b","_issue_exception");
    emitlab("NPexception");
    emit2("la","$a0","NPmessage");
    emit1("b","_issue_exception");
    emitlab("AIOOBexception");
    emit2("la","$a0","AIOOBmessage");
    emitlab("_issue_exception");
    emit2("li","$v0","4");  // magic SPIM code for print_string
    emit0("syscall");
    emit2("li","$v0","10"); // magic SPIM code for exit
    emit0("syscall");
    emit0(".data");
    emitlab("NASmessage");
    emit1(".asciiz","\"Uncaught NegativeArraySizeException\n\"");
    emitlab("NPmessage");
    emit1(".asciiz","\"Uncaught NullPointerException\n\"");
    emitlab("AIOOBmessage");
    emit1(".asciiz","\"Uncaught ArrayIndexOutOfBoundsException\n\"");
  }

  // these variables change per-method
  static String name;
  static int string_label = 0;
  static int max_locals = 0;

  // tos is index of top of stack. 
  // so number of stack slots in use = tos + 1.
  static int tos = -1;

  static void emit_method(Method m) {
    name = m.getName();
    if (name.equals("<init>"))
      return;  // hack to skip constructors
    Code code = m.getCode();
    byte method_bytes[] = code.getCode();
    max_locals = code.getMaxLocals();  // includes arguments
    // int max_stack = code.getMaxStack();  -- we don't actually use this
    // emit header
    emit0(".text");
    emit1(".globl", name);
    emitlab(name);
    InstructionHandle[] instrhandles = new InstructionList(method_bytes).getInstructionHandles();
    tos = -1;
    EmitVisitor emitter = new EmitVisitor();
    for (int i = 0; i < instrhandles.length; i ++) {
      InstructionHandle ih = instrhandles[i];
      if (ih.hasTargeters())                 // if this is a branch target 
	emitlab(llab(ih.getPosition()));     // emit a label
      Instruction inst = ih.getInstruction();
      inst.accept(emitter);                  // emit the code corresponding to instruction
      if (inst instanceof BranchInstruction && tos != -1)
	System.err.println("Compiler invariant violated: stack not empty at branch from " + ih.getPosition());
    }
    // all returns are explicit in instruction list, so nothing to do at the end
  }
    
  // Code emission utilities

  // We use the following MIPS/SPIM register assignments:
  // $2 = $v0  return values from methods; call code for syscalls
  // $4 = $a0  argument value for syscalls
  // $5-$14    locals (local i = $(5+i)
  // $15       temporary (for use within code for a single JVM instruction)
  // $16-$25   stack slots (slot i = $(16+i))
  // $31 = $ra return address
  // others unused

  // Register representing stack slot (10 from $16-$25)
  static String stack(int i) { 
    if (i < 0 || i > 9) 
      System.err.println("Can't handle stack slot " + i);
    return "$" + (16 + i);
  }

  // Register representing local (10 from $5-$14) 
  static String lvar(int i) {
    if (i < 0 || i > 9) 
      System.err.println("Can't handle local number " + i);
    return "$" + (5 + i);
  }

  // Temporary register ($15)
  static String temp = "$15";

  // Local label
  static String llab(int i) {
    return name + "_" + i;
  }

  static void unimplemented(Object obj) {
    System.err.println("Can't handle instruction " + obj);
  }

  // Code emission
  static void emitlab(String lab) {
    System.out.println(lab + ":");
  }

  static void emit0(String op) {
    System.out.println("\t" + op);
  }

  static void emit1(String op, String a1) {
    System.out.println("\t" + op + " " + a1);
  }

  static void emit2(String op, String a1, String a2) {
    System.out.println("\t" + op + " " + a1 + ", " + a2);
  }

  static void emit3(String op, String a1, String a2, String a3) {
    System.out.println("\t" + op + " " + a1 + ", " + a2 + ", " + a3);
  }


  // Store return address register, lvar registers and operand stack registers onto machine stack
  static void emit_caller_save(int stack_slots) {
    emit3("sub", "$sp", "$sp", Integer.toString(4*(1+max_locals+stack_slots)));
    emit2("sw", "$ra", "($sp)");
    for (int i = 0; i < max_locals; i++) 
      emit2("sw", lvar(i), "" + (4*(1+i)) + "($sp)");
    for (int i = 0; i < stack_slots; i++) 
      emit2("sw", stack(i), "" + (4*(1+max_locals+i)) + "($sp)");
  }

  // Restore return address register, lvar registers and operand stack registers from machine stack
  static void emit_caller_restore(int stack_slots) {
    emit2("lw","$ra","($sp)");
    for (int i = 0; i < max_locals; i++) 
      emit2("lw", lvar(i),"" + (4*(1+i)) + "($sp)");
    for (int i = 0; i < stack_slots; i++) 
      emit2("lw", stack(i),"" + (4*(1+max_locals+i)) + "($sp)");
    emit3("add", "$sp", "$sp", Integer.toString(4*(1+max_locals+stack_slots)));
  }


  // Utilities for conditional branch instructions
  static void emit_branch(String op,BranchInstruction obj) {
    int target = obj.getTarget().getPosition();
    emit3("b" + op,stack(tos-1),stack(tos),llab(target));
    tos -= 2;
  }

  static void emit_branch_zero(String op,BranchInstruction obj) {
    int target = obj.getTarget().getPosition();
    emit2("b" + op + "z",stack(tos),llab(target));
    tos -= 1;
  }

  
  // Per-instruction code generator is done using the visitor pattern,
  // because that's how bcel is set up.
  static class EmitVisitor extends org.apache.bcel.generic.EmptyVisitor 
                    implements org.apache.bcel.generic.Visitor {

    EmitVisitor() {
    }

    // Emit MIPS code for JVM instructions we know how to deal with; complain about others
    public void visitAALOAD(AALOAD obj) { unimplemented(obj); }
    public void visitAASTORE(AASTORE obj) { unimplemented(obj);}
    public void visitACONST_NULL(ACONST_NULL obj) {
	emit2("li",stack(tos+1),"0");
	tos += 1;
    }
    public void visitALOAD(ALOAD obj) { 
      emit2("move",stack(tos+1),lvar(obj.getIndex())); 
      tos+=1; 
    }
    public void visitANEWARRAY(ANEWARRAY obj) { unimplemented(obj);}
    public void visitARETURN(ARETURN obj) { 
      emit2("move", "$v0",stack(tos)); 
      emit1("jr","$ra"); 
      tos -= 1;
    }
    public void visitARRAYLENGTH(ARRAYLENGTH obj) {
      emit2("beqz",stack(tos),"NPexception");  // check for null pointer 
      emit2("lw",stack(tos),"(" + stack(tos) + ")");
    }
    public void visitASTORE(ASTORE obj) {
      emit2("move",lvar(obj.getIndex()),stack(tos)); 
      tos -= 1;
    }
    public void visitATHROW(ATHROW obj) { unimplemented(obj); }
    public void visitBALOAD(BALOAD obj) { unimplemented(obj);}
    public void visitBASTORE(BASTORE obj) { unimplemented(obj); }
    public void visitBIPUSH(BIPUSH obj) { 
      emit2("li", stack(tos+1), obj.getValue().toString()); 
      tos += 1;
    }
    public void visitBREAKPOINT(BREAKPOINT obj) { unimplemented(obj);}
    public void visitCALOAD(CALOAD obj) { unimplemented(obj);}
    public void visitCASTORE(CASTORE obj) {  unimplemented(obj);}
    public void visitCHECKCAST(CHECKCAST obj) { unimplemented(obj); }
    public void visitD2F(D2F obj) { unimplemented(obj);}
    public void visitD2I(D2I obj) { unimplemented(obj);}
    public void visitD2L(D2L obj) { unimplemented(obj);}
    public void visitDADD(DADD obj) { unimplemented(obj);}
    public void visitDALOAD(DALOAD obj) { unimplemented(obj); }
    public void visitDASTORE(DASTORE obj) { unimplemented(obj); }
    public void visitDCONST(DCONST obj) { unimplemented(obj);}
    public void visitDCMPG(DCMPG obj) {unimplemented(obj); }
    public void visitDCMPL(DCMPL obj) { unimplemented(obj); }
    public void visitDDIV(DDIV obj) { unimplemented(obj); }
    public void visitDLOAD(DLOAD obj) { unimplemented(obj);}
    public void visitDMUL(DMUL obj) { unimplemented(obj);}
    public void visitDNEG(DNEG obj) { unimplemented(obj);}
    public void visitDREM(DREM obj) { unimplemented(obj); }
    public void visitDRETURN(DRETURN obj) {  unimplemented(obj);}
    public void visitDSTORE(DSTORE obj) { unimplemented(obj); }
    public void visitDSUB(DSUB obj) { unimplemented(obj);}
    public void visitDUP(DUP obj) { 
      emit2("move",stack(tos+1),stack(tos)); 
      tos+=1; 
    }
    public void visitDUP_X1(DUP_X1 obj) { unimplemented(obj);}
    public void visitDUP_X2(DUP_X2 obj) { unimplemented(obj);}
    public void visitDUP2(DUP2 obj) { unimplemented(obj); } 
    public void visitDUP2_X1(DUP2_X1 obj) { unimplemented(obj);}
    public void visitDUP2_X2(DUP2_X2 obj) { unimplemented(obj); }
    public void visitF2D(F2D obj) { unimplemented(obj);}
    public void visitF2I(F2I obj) { unimplemented(obj);}
    public void visitF2L(F2L obj) { unimplemented(obj); }
    public void visitFADD(FADD obj) { unimplemented(obj);}
    public void visitFALOAD(FALOAD obj) { unimplemented(obj);}
    public void visitFASTORE(FASTORE obj) { unimplemented(obj);}
    public void visitFCMPG(FCMPG obj) { unimplemented(obj); }
    public void visitFCMPL(FCMPL obj) { unimplemented(obj);}
    public void visitFCONST(FCONST obj) { unimplemented(obj);}
    public void visitFDIV(FDIV obj) { unimplemented(obj);}
    public void visitFLOAD(FLOAD obj) { unimplemented(obj);}
    public void visitFMUL(FMUL obj) { unimplemented(obj); }
    public void visitFNEG(FNEG obj) { unimplemented(obj);}
    public void visitFREM(FREM obj) { unimplemented(obj); }
    public void visitFRETURN(FRETURN obj) { unimplemented(obj);}
    public void visitFSTORE(FSTORE obj) { unimplemented(obj); }
    public void visitFSUB(FSUB obj) { unimplemented(obj); }
    public void visitGETFIELD(GETFIELD obj) { unimplemented(obj);}
    public void visitGETSTATIC(GETSTATIC obj) { 
      // hack to quietly handle fetches of System.out
      if (obj.getClassName(cpg).equals("java.lang.System") && 
	  obj.getFieldName(cpg).equals("out"))
	tos += 1;  // just leave an empty slot
      else
	unimplemented(obj); }
    public void visitGOTO(GOTO obj) { 
      emit1("b",llab(obj.getTarget().getPosition()));
    }
    public void visitGOTO_W(GOTO_W obj) { 
      emit1("b",llab(obj.getTarget().getPosition()));
    }
    public void visitI2B(I2B obj) { unimplemented(obj);}
    public void visitI2C(I2C obj) { unimplemented(obj);}
    public void visitI2D(I2D obj) { unimplemented(obj);}
    public void visitI2F(I2F obj) { unimplemented(obj); }
    public void visitI2L(I2L obj) { unimplemented(obj);}
    public void visitI2S(I2S obj) { unimplemented(obj);}
    public void visitIADD(IADD obj) { 
      emit3("add",stack(tos-1),stack(tos-1),stack(tos)); 
      tos -=1; 
    }
    public void visitIALOAD(IALOAD obj) {  
      emit2("beqz",stack(tos-1),"NPexception");  // check for null pointer 
      emit2("lw",temp,"(" + stack(tos-1) + ")");  // fetch length
      emit3("bgeu",stack(tos),temp,"AIOOBexception");     // check bounds
      emit3("sll",temp,stack(tos),"2");  // cheap multiply of index by 4
      emit3("add",temp,temp,stack(tos-1));
      emit2("lw",stack(tos-1),"4(" + temp + ")");  // add 4 to skip length as we go
      tos -= 1;
    }
    public void visitIAND(IAND obj) { 
      emit3("and",stack(tos-1),stack(tos-1),stack(tos)); 
      tos-=1; 
    }
    public void visitIASTORE(IASTORE obj) {  // without checking
      emit2("beqz",stack(tos-2),"NPexception");  // check for null pointer 
      emit2("lw",temp,"(" + stack(tos-2) + ")");  // fetch length
      emit3("bgeu",stack(tos-1),temp,"AIOOBexception");     // check bounds
      emit3("sll",temp,stack(tos-1),"2");  // cheap multiply of index by 4
      emit3("add",temp,temp,stack(tos-2));
      emit2("sw",stack(tos),"4(" + temp + ")");  // add 4 to skip length as we go
      tos -= 3;
    }
    public void visitICONST(ICONST obj) { 
      emit2("li", stack(tos+1), obj.getValue().toString()); 
      tos+= 1;
    }
    public void visitIDIV(IDIV obj) { 
      emit3("div",stack(tos-1),stack(tos-1),stack(tos)); 
      tos-=1; 
    }
    public void visitIF_ACMPEQ(IF_ACMPEQ obj) { 
      emit_branch("eq",obj);
    }
    public void visitIF_ACMPNE(IF_ACMPNE obj) { 
      emit_branch("ne",obj);
    }
    public void visitIF_ICMPEQ(IF_ICMPEQ obj) { 
      emit_branch("eq",obj);
    }
    public void visitIF_ICMPGE(IF_ICMPGE obj) { 
      emit_branch("ge",obj);
    }
    public void visitIF_ICMPGT(IF_ICMPGT obj) { 
      emit_branch("gt",obj);
    }
    public void visitIF_ICMPLE(IF_ICMPLE obj) { 
      emit_branch("le",obj);
    }
    public void visitIF_ICMPLT(IF_ICMPLT obj) { 
      emit_branch("lt",obj);
    }
    public void visitIF_ICMPNE(IF_ICMPNE obj) { 
      emit_branch("ne",obj);
    }
    public void visitIFEQ(IFEQ obj) { 
      emit_branch_zero("eq",obj);
    }
    public void visitIFGE(IFGE obj) { 
      emit_branch_zero("ge",obj);
    }
    public void visitIFGT(IFGT obj) { 
      emit_branch_zero("gt",obj);
    }
    public void visitIFLE(IFLE obj) { 
      emit_branch_zero("le",obj);
    }
    public void visitIFLT(IFLT obj) { 
      emit_branch_zero("lt",obj);
    }
    public void visitIFNE(IFNE obj) { 
      emit_branch_zero("ne",obj);
    }
    public void visitIFNONNULL(IFNONNULL obj) { 
      emit_branch_zero("ne",obj);
    }
    public void visitIFNULL(IFNULL obj) { 
      emit_branch_zero("eq",obj);
    }
    public void visitIINC(IINC obj) { 
      emit3("add",lvar(obj.getIndex()),lvar(obj.getIndex()), Integer.toString(obj.getIncrement()));
    }
    public void visitILOAD(ILOAD obj) { 
      emit2("move",stack(tos+1),lvar(obj.getIndex())); 
      tos+=1; 
    }
    public void visitIMPDEP1(IMPDEP1 obj) { unimplemented(obj);}
    public void visitIMPDEP2(IMPDEP2 obj) {unimplemented(obj); }
    public void visitIMUL(IMUL obj) { 
      emit3("mul",stack(tos-1),stack(tos-1),stack(tos)); 
      tos -=1; 
    }
    public void visitINEG(INEG obj) { 
      emit2("neg",stack(tos),stack(tos));
    }
    public void visitINSTANCEOF(INSTANCEOF obj) { unimplemented(obj);}
    public void visitINVOKEINTERFACE(INVOKEINTERFACE obj) { unimplemented(obj); }
    public void visitINVOKESPECIAL(INVOKESPECIAL obj) { unimplemented(obj); }
    public void visitINVOKESTATIC(INVOKESTATIC obj) {
      int arg_count = obj.getArgumentTypes(cpg).length;
      int stack_slots = 1+tos-arg_count;
      emit_caller_save(stack_slots);
      // move arguments from stack regs to lvar regs
      for (int i = 0; i < arg_count; i++) 
	emit2("move",lvar(arg_count-1-i),stack(tos-i));
      tos -= arg_count;
      // do call
      emit1("jal",obj.getMethodName(cpg));
      emit_caller_restore(stack_slots);
      // if there was a return value, push it onto operand stack
      if (!obj.getReturnType(cpg).equals(Type.VOID)) {
	emit2("move",stack(tos+1),"$v0");
	tos +=1;
      }
    }      
    public void visitINVOKEVIRTUAL(INVOKEVIRTUAL obj) { 
      // hack to support printing ints or strings to stdout
      if (obj.getClassName(cpg).equals("java.io.PrintStream") &&
	  obj.getName(cpg).equals("print")) {
	if (obj.getSignature(cpg).equals("(Ljava/lang/String;)V")) {
	  emit2("li","$v0","4");  // magic SPIM code for print_string
	  emit2("move","$a0",stack(tos));
	  emit0("syscall");
	  tos -= 2;  // consume the value and the placeholder for the PrintStream object
	} else if (obj.getSignature(cpg).equals("(I)V")) {
	  emit2("li","$v0","1"); // magic SPIM code for print_int
	  emit2("move","$a0",stack(tos));
	  emit0("syscall");
	  tos -= 2;  // consume the value and the placeholder for the PrintStream object
	}
	else 
	  unimplemented(obj);
      } else
	unimplemented(obj); 
    }
    public void visitIOR(IOR obj) { 
      emit3("or",stack(tos-1),stack(tos-1),stack(tos)); 
      tos -=1; 
    }
    public void visitIREM(IREM obj) { 
      emit3("rem",stack(tos-1),stack(tos-1),stack(tos)); 
      tos -=1; 
    } 
    public void visitIRETURN(IRETURN obj) { 
      emit2("move", "$v0",stack(tos)); 
      emit1("jr","$ra"); 
      tos -=1;
    }
    public void visitISHL(ISHL obj) {
      emit3("and",stack(tos),stack(tos),"0x1f"); 
      emit3("sllv",stack(tos-1),stack(tos-1),stack(tos)); 
      tos -=1;
    }
    public void visitISHR(ISHR obj) { 
      emit3("and",stack(tos),stack(tos),"0x1f"); 
      emit3("srav",stack(tos-1),stack(tos-1),stack(tos)); 
      tos -=1;
    }
    public void visitISTORE(ISTORE obj) { 
      emit2("move",lvar(obj.getIndex()),stack(tos)); 
      tos -= 1;
    }
    public void visitISUB(ISUB obj) { 
      emit3("sub",stack(tos-1),stack(tos-1),stack(tos)); 
      tos -=1; 
    }
    public void visitIUSHR(IUSHR obj) { unimplemented(obj);}
    public void visitIXOR(IXOR obj) { 
      emit3("xor",stack(tos-1),stack(tos-1),stack(tos)); 
      tos -=1; 
    }
    public void visitJSR(JSR obj) { unimplemented(obj); }
    public void visitJSR_W(JSR_W obj) { unimplemented(obj);}
    public void visitL2D(L2D obj) { unimplemented(obj);}
    public void visitL2F(L2F obj) { unimplemented(obj);}
    public void visitL2I(L2I obj) { unimplemented(obj);}
    public void visitLADD(LADD obj) { unimplemented(obj);}
    public void visitLAND(LAND obj) { unimplemented(obj); }
    public void visitLALOAD(LALOAD obj) { unimplemented(obj);}
    public void visitLASTORE(LASTORE obj) { unimplemented(obj);}
    public void visitLCMP(LCMP obj) { unimplemented(obj);}
    public void visitLCONST(LCONST obj) { unimplemented(obj); }
    public void visitLDC(LDC obj) { 
      Constant c = cpg.getConstant(obj.getIndex()); 
      if (c instanceof ConstantInteger) {
	int i = ((ConstantInteger) c).getBytes();
	if ((i & 0xffff0000) != 0) {
	  emit2 ("lui",stack(tos+1),Integer.toString(i >> 16));
	  emit3 ("or",stack(tos+1),stack(tos+1),Integer.toString(i & 0xffff));
	} else
	  emit2 ("li",stack(tos),Integer.toString(i));
	tos += 1;
      } else if (c instanceof ConstantString) {
	String s = ((ConstantString) c).getBytes(cp);
	emit0(".data");
	string_label += 1;
	emitlab("string_" + string_label);
 	emit1(".asciiz","\"" + s + "\"");  // a bit lazy: should handle embedded non-printing characters, but this works ok
	emit0(".text");
	emit2 ("la", stack(tos+1),"string_" + string_label);
	tos += 1;
      } else
	unimplemented(obj);
    }
    public void visitLDC2_W(LDC2_W obj) { unimplemented(obj);}
    public void visitLDIV(LDIV obj) { unimplemented(obj);}
    public void visitLLOAD(LLOAD obj) { unimplemented(obj); }
    public void visitLMUL(LMUL obj) { unimplemented(obj);}
    public void visitLNEG(LNEG obj) { unimplemented(obj);}
    public void visitLOOKUPSWITCH(LOOKUPSWITCH obj) { unimplemented(obj);}
    public void visitLOR(LOR obj) {  unimplemented(obj);}
    public void visitLREM(LREM obj) { unimplemented(obj);}
    public void visitLRETURN(LRETURN obj) { unimplemented(obj);}
    public void visitLSHL(LSHL obj) { unimplemented(obj);}
    public void visitLSHR(LSHR obj) { unimplemented(obj);}
    public void visitLSTORE(LSTORE obj) { unimplemented(obj); }
    public void visitLSUB(LSUB obj) { unimplemented(obj);}
    public void visitLUSHR(LUSHR obj) { unimplemented(obj);}
    public void visitLXOR(LXOR obj) { unimplemented(obj);}
    public void visitMONITORENTER(MONITORENTER obj) { unimplemented(obj);}
    public void visitMONITOREXIT(MONITOREXIT obj) { unimplemented(obj); }
    public void visitMULTIANEWARRAY(MULTIANEWARRAY obj) { unimplemented(obj);}
    public void visitNEW(NEW obj) { unimplemented(obj);}
    public void visitNEWARRAY(NEWARRAY obj) { 
      if (obj.getType().equals(new ArrayType(Type.INT,1))) {
	// check argument 
	emit2("bltz",stack(tos),"NASexception");
	// allocate space for integer array (4*size + 4 bytes)	    
	emit2("li","$v0","9"); // magic SPIM code for sbrk
	emit3("sll","$a0",stack(tos),"2"); // cheap multiply by 4 
	emit3("add","$a0","$a0","4");
	emit0("syscall");  // new memory comes back zeroed
	emit2("sw",stack(tos),"($v0)");  // store length
	emit2("move",stack(tos),"$v0");
      } else
	unimplemented(obj);
    }
    public void visitNOP(NOP obj) { 
      /* nothing to do !! */
    }
    public void visitPOP(POP obj) { 
      tos--; 
    }
    public void visitPOP2(POP2 obj) { 
      tos -=2; 
    }
    public void visitPUTFIELD(PUTFIELD obj) { unimplemented(obj);}
    public void visitPUTSTATIC(PUTSTATIC obj) { unimplemented(obj);}
    public void visitRET(RET obj) { unimplemented(obj);}
    public void visitRETURN(RETURN obj) { 
      emit1("jr","$ra"); 
    }
    public void visitSALOAD(SALOAD obj) { unimplemented(obj);}
    public void visitSASTORE(SASTORE obj) { unimplemented(obj); }
    public void visitSIPUSH(SIPUSH obj) { 
      emit2("li", stack(tos+1), obj.getValue().toString()); 
      tos+= 1;
    }
    public void visitSWAP(SWAP obj) { 
      emit2("move",temp,stack(tos)); 
      emit2("move",stack(tos),stack(tos-1));
      emit2("move",stack(tos),temp); 
    }
    public void visitTABLESWITCH(TABLESWITCH obj) { unimplemented(obj); }
  }

}
