import java.io.*;
import java.util.*;

class Sparc {

  static String[] regName = {"%g0","%g1","%g2","%g3","%g4","%g5","%g6","%g7",
			     "%o0","%o1","%o2","%o3","%o4","%o5","%sp","%o7",
			     "%l0","%l1","%l2","%l3","%l4","%l5","%l6","%l7",
			     "%i0","%i1","%i2","%i3","%i4","%i5","%fp","%i7"};

  static abstract class Operand {
  };

  static class Addr extends Operand {   // Register and offset
    Reg r; // register
    int o; // offset (13 bit)
    Addr(Reg r, int o) {
      this.r = r; this.o = o;
    }
    public String toString () {
      return r + (o < 0 ? Integer.toString(o) : (o > 0) ? "+" + o : "");
    }
  }
  static class Reg extends Operand {  // Register
    int r; 
    Reg(int r) {
      this.r = r;
    }
    public String toString () {
      return regName[r];
    }
  }
  static class Imm13 extends Operand { // Integer literal (13 bit)
    int i;
    Imm13(int i) {
      this.i = i;
    }
    public String toString() {
      return "" + i;
    }
  }
  static class Imm32 extends Operand { // Integer literal (32 bit)
    int i;
    Imm32(int i) {
      this.i = i;
    }
    public String toString() {
      return "" + i;
    }
  }
  static class AddrName extends Operand { // Named address
    String s;
    AddrName(String s) {
      this.s = s;
    }
    public String toString() {
      return s;
    }
  }
  static class Label extends Operand { // Label
    String s;
    Label(String s) {
      this.s = s;
    }
    public String toString() {
      return s;
    }
  }

  static void emit(String s)
  {
    System.out.println(s);
  }

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

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

  static void emit2(String op, Operand rand1, Operand rand2) {
    System.out.println("\t" + op + " " + rand1 + "," + rand2);
  }

  static void emitSt(Operand rand1, Operand rand2)
  {
    System.out.println("\tst " + rand1 + ",[" + rand2 + "]");
  }

  static void emitLd(Operand rand1, Operand rand2)
  {
    System.out.println("\tld [" + rand1 + "]," + rand2);
  }

  static void emit3(String op, Operand rand1, Operand rand2, Operand rand3) {
    System.out.println("\t" + op + " " + rand1 + "," + rand2 + "," + rand3);
  }

  static void emitLabel(Label lab)
  {
    System.out.println("" + lab + ":");
  }

  static void emitString(String s) {
    System.out.println("\t.asciz \"" + s + "\"");
  }

  static void emitSegment(int i) {
    System.out.println(".text " + i);
  }


  static boolean[] regUsable = {false,false,false,false,false,false,false,false,  /* %g */
				false,true,true,true,true,true,false,false,  /* %o */
				true,true,true,true,true,true,true,true,  /* %l */
				true,true,true,true,true,true,false,false}; /* %i */

  // Sparc word is 4 = 2^2 bytes long
  static final int 
    WORDSIZE = 4,
    WORDSIZE_BITS = 2;
  
  // Predicate to check for 13 bit offsets. 
  static boolean shortoff(int x) {
    return (x >= -4096 && x < 4096);
  }

  // SPARC registers are denoted by number 0-31
  static final int REGS = 32;

  // mnemonic definitions for key registers 
  static final Reg
    G0 = new Reg(0),
    G1 = new Reg(1),
    G2 = new Reg(2),
    G3 = new Reg(3),
    O0 = new Reg(8),
    SP = new Reg(14),
    I0 = new Reg(24),
    FP = new Reg(30);

  // Frame constants (all in bytes)
  static final int FIRST_ARG_OFFSET = ((16+1) * WORDSIZE);
  static final int MIN_ARGBUILDSIZE = 6 * WORDSIZE;
  static final int STACK_ALIGNMENT = 8;

  // Round x up to nearest multiple of p, provided p is a multiple of 2 
  static int roundup(int x,int p) {
    return (x + p - 1) & ~(p-1);
  }

}
