(*
 * WARNING: This file was automatically generated by MDLGen (v3.0)
 * from the machine description file "alpha/alpha.mdl".
 * DO NOT EDIT this file directly
 *)


functor AlphaAsmEmitter(structure S : INSTRUCTION_STREAM
                        structure Instr : ALPHAINSTR
                           where T = S.P.T
                        structure Shuffle : ALPHASHUFFLE
                           where I = Instr
                        structure MLTreeEval : MLTREE_EVAL
                           where T = Instr.T
                       ) : INSTRUCTION_EMITTER =
struct
   structure I  = Instr
   structure C  = I.C
   structure T  = I.T
   structure S  = S
   structure P  = S.P
   structure Constant = I.Constant
   
   open AsmFlags
   
   fun error msg = MLRiscErrorMsg.error("AlphaAsmEmitter",msg)
   
   fun makeStream formatAnnotations =
   let val stream = !AsmStream.asmOutStream
       fun emit' s = TextIO.output(stream,s)
       val newline = ref true
       val tabs = ref 0
       fun tabbing 0 = ()
         | tabbing n = (emit' "\t"; tabbing(n-1))
       fun emit s = (tabbing(!tabs); tabs := 0; newline := false; emit' s)
       fun nl() = (tabs := 0; if !newline then () else (newline := true; emit' "\n"))
       fun comma() = emit ","
       fun tab() = tabs := 1
       fun indent() = tabs := 2
       fun ms n = let val s = Int.toString n
                  in  if n<0 then "-"^String.substring(s,1,size s-1)
                      else s
                  end
       fun emit_label lab = emit(P.Client.AsmPseudoOps.lexpToString(T.LABEL lab))
       fun emit_labexp le = emit(P.Client.AsmPseudoOps.lexpToString (T.LABEXP le))
       fun emit_const c = emit(Constant.toString c)
       fun emit_int i = emit(ms i)
       fun paren f = (emit "("; f(); emit ")")
       fun defineLabel lab = emit(P.Client.AsmPseudoOps.defineLabel lab^"\n")
       fun entryLabel lab = defineLabel lab
       fun comment msg = (tab(); emit("/* " ^ msg ^ " */"); nl())
       fun annotation a = comment(Annotations.toString a)
       fun getAnnotations() = error "getAnnotations"
       fun doNothing _ = ()
       fun fail _ = raise Fail "AsmEmitter"
       fun emit_region mem = comment(I.Region.toString mem)
       val emit_region = 
          if !show_region then emit_region else doNothing
       fun pseudoOp pOp = (emit(P.toString pOp); emit "\n")
       fun init size = (comment("Code Size = " ^ ms size); nl())
       val emitCellInfo = AsmFormatUtil.reginfo
                                (emit,formatAnnotations)
       fun emitCell r = (emit(CellsBasis.toString r); emitCellInfo r)
       fun emit_cellset(title,cellset) =
         (nl(); comment(title^CellsBasis.CellSet.toString cellset))
       val emit_cellset = 
         if !show_cellset then emit_cellset else doNothing
       fun emit_defs cellset = emit_cellset("defs: ",cellset)
       fun emit_uses cellset = emit_cellset("uses: ",cellset)
       val emit_cutsTo = 
         if !show_cutsTo then AsmFormatUtil.emit_cutsTo emit
         else doNothing
       fun emitter instr =
       let
   fun emit_operand (I.REGop GP) = emitCell GP
     | emit_operand (I.IMMop int) = emit_int int
     | emit_operand (I.HILABop labexp) = 
       ( emit "hi("; 
         emit_labexp labexp; 
         emit ")" )
     | emit_operand (I.LOLABop labexp) = 
       ( emit "lo("; 
         emit_labexp labexp; 
         emit ")" )
     | emit_operand (I.LABop labexp) = emit_labexp labexp
   and asm_branch (I.BR) = "br"
     | asm_branch (I.BLBC) = "blbc"
     | asm_branch (I.BEQ) = "beq"
     | asm_branch (I.BLT) = "blt"
     | asm_branch (I.BLE) = "ble"
     | asm_branch (I.BLBS) = "blbs"
     | asm_branch (I.BNE) = "bne"
     | asm_branch (I.BGE) = "bge"
     | asm_branch (I.BGT) = "bgt"
   and emit_branch x = emit (asm_branch x)
   and asm_fbranch (I.FBEQ) = "fbeq"
     | asm_fbranch (I.FBLT) = "fblt"
     | asm_fbranch (I.FBLE) = "fble"
     | asm_fbranch (I.FBNE) = "fbne"
     | asm_fbranch (I.FBGE) = "fbge"
     | asm_fbranch (I.FBGT) = "fbgt"
   and emit_fbranch x = emit (asm_fbranch x)
   and asm_load (I.LDB) = "ldb"
     | asm_load (I.LDW) = "ldw"
     | asm_load (I.LDBU) = "ldbu"
     | asm_load (I.LDWU) = "ldwu"
     | asm_load (I.LDL) = "ldl"
     | asm_load (I.LDL_L) = "ldl_l"
     | asm_load (I.LDQ) = "ldq"
     | asm_load (I.LDQ_L) = "ldq_l"
     | asm_load (I.LDQ_U) = "ldq_u"
   and emit_load x = emit (asm_load x)
   and asm_store (I.STB) = "stb"
     | asm_store (I.STW) = "stw"
     | asm_store (I.STL) = "stl"
     | asm_store (I.STQ) = "stq"
     | asm_store (I.STQ_U) = "stq_u"
   and emit_store x = emit (asm_store x)
   and asm_fload (I.LDF) = "ldf"
     | asm_fload (I.LDG) = "ldg"
     | asm_fload (I.LDS) = "lds"
     | asm_fload (I.LDT) = "ldt"
   and emit_fload x = emit (asm_fload x)
   and asm_fstore (I.STF) = "stf"
     | asm_fstore (I.STG) = "stg"
     | asm_fstore (I.STS) = "sts"
     | asm_fstore (I.STT) = "stt"
   and emit_fstore x = emit (asm_fstore x)
   and asm_operate (I.ADDL) = "addl"
     | asm_operate (I.ADDQ) = "addq"
     | asm_operate (I.CMPBGE) = "cmpbge"
     | asm_operate (I.CMPEQ) = "cmpeq"
     | asm_operate (I.CMPLE) = "cmple"
     | asm_operate (I.CMPLT) = "cmplt"
     | asm_operate (I.CMPULE) = "cmpule"
     | asm_operate (I.CMPULT) = "cmpult"
     | asm_operate (I.SUBL) = "subl"
     | asm_operate (I.SUBQ) = "subq"
     | asm_operate (I.S4ADDL) = "s4addl"
     | asm_operate (I.S4ADDQ) = "s4addq"
     | asm_operate (I.S4SUBL) = "s4subl"
     | asm_operate (I.S4SUBQ) = "s4subq"
     | asm_operate (I.S8ADDL) = "s8addl"
     | asm_operate (I.S8ADDQ) = "s8addq"
     | asm_operate (I.S8SUBL) = "s8subl"
     | asm_operate (I.S8SUBQ) = "s8subq"
     | asm_operate (I.AND) = "and"
     | asm_operate (I.BIC) = "bic"
     | asm_operate (I.BIS) = "bis"
     | asm_operate (I.EQV) = "eqv"
     | asm_operate (I.ORNOT) = "ornot"
     | asm_operate (I.XOR) = "xor"
     | asm_operate (I.EXTBL) = "extbl"
     | asm_operate (I.EXTLH) = "extlh"
     | asm_operate (I.EXTLL) = "extll"
     | asm_operate (I.EXTQH) = "extqh"
     | asm_operate (I.EXTQL) = "extql"
     | asm_operate (I.EXTWH) = "extwh"
     | asm_operate (I.EXTWL) = "extwl"
     | asm_operate (I.INSBL) = "insbl"
     | asm_operate (I.INSLH) = "inslh"
     | asm_operate (I.INSLL) = "insll"
     | asm_operate (I.INSQH) = "insqh"
     | asm_operate (I.INSQL) = "insql"
     | asm_operate (I.INSWH) = "inswh"
     | asm_operate (I.INSWL) = "inswl"
     | asm_operate (I.MSKBL) = "mskbl"
     | asm_operate (I.MSKLH) = "msklh"
     | asm_operate (I.MSKLL) = "mskll"
     | asm_operate (I.MSKQH) = "mskqh"
     | asm_operate (I.MSKQL) = "mskql"
     | asm_operate (I.MSKWH) = "mskwh"
     | asm_operate (I.MSKWL) = "mskwl"
     | asm_operate (I.SLL) = "sll"
     | asm_operate (I.SRA) = "sra"
     | asm_operate (I.SRL) = "srl"
     | asm_operate (I.ZAP) = "zap"
     | asm_operate (I.ZAPNOT) = "zapnot"
     | asm_operate (I.MULL) = "mull"
     | asm_operate (I.MULQ) = "mulq"
     | asm_operate (I.UMULH) = "umulh"
   and emit_operate x = emit (asm_operate x)
   and asm_cmove (I.CMOVEQ) = "cmoveq"
     | asm_cmove (I.CMOVLBC) = "cmovlbc"
     | asm_cmove (I.CMOVLBS) = "cmovlbs"
     | asm_cmove (I.CMOVGE) = "cmovge"
     | asm_cmove (I.CMOVGT) = "cmovgt"
     | asm_cmove (I.CMOVLE) = "cmovle"
     | asm_cmove (I.CMOVLT) = "cmovlt"
     | asm_cmove (I.CMOVNE) = "cmovne"
   and emit_cmove x = emit (asm_cmove x)
   and asm_pseudo_op (I.DIVL) = "divl"
     | asm_pseudo_op (I.DIVLU) = "divlu"
     | asm_pseudo_op (I.DIVQ) = "divq"
     | asm_pseudo_op (I.DIVQU) = "divqu"
     | asm_pseudo_op (I.REML) = "reml"
     | asm_pseudo_op (I.REMLU) = "remlu"
     | asm_pseudo_op (I.REMQ) = "remq"
     | asm_pseudo_op (I.REMQU) = "remqu"
   and emit_pseudo_op x = emit (asm_pseudo_op x)
   and asm_operateV (I.ADDLV) = "addlv"
     | asm_operateV (I.ADDQV) = "addqv"
     | asm_operateV (I.SUBLV) = "sublv"
     | asm_operateV (I.SUBQV) = "subqv"
     | asm_operateV (I.MULLV) = "mullv"
     | asm_operateV (I.MULQV) = "mulqv"
   and emit_operateV x = emit (asm_operateV x)
   and asm_funary (I.CVTLQ) = "cvtlq"
     | asm_funary (I.CVTQL) = "cvtql"
     | asm_funary (I.CVTQLSV) = "cvtqlsv"
     | asm_funary (I.CVTQLV) = "cvtqlv"
     | asm_funary (I.CVTQS) = "cvtqs"
     | asm_funary (I.CVTQSC) = "cvtqsc"
     | asm_funary (I.CVTQT) = "cvtqt"
     | asm_funary (I.CVTQTC) = "cvtqtc"
     | asm_funary (I.CVTTS) = "cvtts"
     | asm_funary (I.CVTTSC) = "cvttsc"
     | asm_funary (I.CVTST) = "cvtst"
     | asm_funary (I.CVTSTS) = "cvtsts"
     | asm_funary (I.CVTTQ) = "cvttq"
     | asm_funary (I.CVTTQC) = "cvttqc"
   and emit_funary x = emit (asm_funary x)
   and asm_foperate (I.CPYS) = "cpys"
     | asm_foperate (I.CPYSE) = "cpyse"
     | asm_foperate (I.CPYSN) = "cpysn"
     | asm_foperate (I.MF_FPCR) = "mf_fpcr"
     | asm_foperate (I.MT_FPCR) = "mt_fpcr"
     | asm_foperate (I.CMPTEQ) = "cmpteq"
     | asm_foperate (I.CMPTLT) = "cmptlt"
     | asm_foperate (I.CMPTLE) = "cmptle"
     | asm_foperate (I.CMPTUN) = "cmptun"
     | asm_foperate (I.CMPTEQSU) = "cmpteqsu"
     | asm_foperate (I.CMPTLTSU) = "cmptltsu"
     | asm_foperate (I.CMPTLESU) = "cmptlesu"
     | asm_foperate (I.CMPTUNSU) = "cmptunsu"
     | asm_foperate (I.ADDS) = "adds"
     | asm_foperate (I.ADDT) = "addt"
     | asm_foperate (I.DIVS) = "divs"
     | asm_foperate (I.DIVT) = "divt"
     | asm_foperate (I.MULS) = "muls"
     | asm_foperate (I.MULT) = "mult"
     | asm_foperate (I.SUBS) = "subs"
     | asm_foperate (I.SUBT) = "subt"
   and emit_foperate x = emit (asm_foperate x)
   and asm_fcmove (I.FCMOVEQ) = "fcmoveq"
     | asm_fcmove (I.FCMOVGE) = "fcmovge"
     | asm_fcmove (I.FCMOVGT) = "fcmovgt"
     | asm_fcmove (I.FCMOVLE) = "fcmovle"
     | asm_fcmove (I.FCMOVLT) = "fcmovlt"
     | asm_fcmove (I.FCMOVNE) = "fcmovne"
   and emit_fcmove x = emit (asm_fcmove x)
   and asm_foperateV (I.ADDSSUD) = "addssud"
     | asm_foperateV (I.ADDSSU) = "addssu"
     | asm_foperateV (I.ADDTSUD) = "addtsud"
     | asm_foperateV (I.ADDTSU) = "addtsu"
     | asm_foperateV (I.DIVSSUD) = "divssud"
     | asm_foperateV (I.DIVSSU) = "divssu"
     | asm_foperateV (I.DIVTSUD) = "divtsud"
     | asm_foperateV (I.DIVTSU) = "divtsu"
     | asm_foperateV (I.MULSSUD) = "mulssud"
     | asm_foperateV (I.MULSSU) = "mulssu"
     | asm_foperateV (I.MULTSUD) = "multsud"
     | asm_foperateV (I.MULTSU) = "multsu"
     | asm_foperateV (I.SUBSSUD) = "subssud"
     | asm_foperateV (I.SUBSSU) = "subssu"
     | asm_foperateV (I.SUBTSUD) = "subtsud"
     | asm_foperateV (I.SUBTSU) = "subtsu"
   and emit_foperateV x = emit (asm_foperateV x)
   and asm_osf_user_palcode (I.BPT) = "bpt"
     | asm_osf_user_palcode (I.BUGCHK) = "bugchk"
     | asm_osf_user_palcode (I.CALLSYS) = "callsys"
     | asm_osf_user_palcode (I.GENTRAP) = "gentrap"
     | asm_osf_user_palcode (I.IMB) = "imb"
     | asm_osf_user_palcode (I.RDUNIQUE) = "rdunique"
     | asm_osf_user_palcode (I.WRUNIQUE) = "wrunique"
   and emit_osf_user_palcode x = emit (asm_osf_user_palcode x)

(*#line 479.7 "alpha/alpha.mdl"*)
   fun isZero (I.LABop le) = (MLTreeEval.valueOf le) = 0
     | isZero _ = false
   fun emitInstr' instr = 
       (case instr of
         I.LDA{r, b, d} => (if ((isZero d) andalso (CellsBasis.sameCell (r, 
            b)))
            then ()
            else 
            ( 
              ( emit "lda\t"; 
                emitCell r; 
                emit ", "; 
                emit_operand d ); 
              (if ((CellsBasis.registerId b) = 31)
                 then ()
                 else 
                 ( emit "("; 
                   emitCell b; 
                   emit ")" ))))
       | I.LDAH{r, b, d} => 
         ( 
           ( emit "ldah\t"; 
             emitCell r; 
             emit ", "; 
             emit_operand d ); 
           (if ((CellsBasis.registerId b) = 31)
              then ()
              else 
              ( emit "("; 
                emitCell b; 
                emit ")" )))
       | I.LOAD{ldOp, r, b, d, mem} => 
         ( emit_load ldOp; 
           emit "\t"; 
           emitCell r; 
           emit ", "; 
           emit_operand d; 
           emit "("; 
           emitCell b; 
           emit ")"; 
           emit_region mem )
       | I.STORE{stOp, r, b, d, mem} => 
         ( emit_store stOp; 
           emit "\t"; 
           emitCell r; 
           emit ", "; 
           emit_operand d; 
           emit "("; 
           emitCell b; 
           emit ")"; 
           emit_region mem )
       | I.FLOAD{ldOp, r, b, d, mem} => 
         ( emit_fload ldOp; 
           emit "\t"; 
           emitCell r; 
           emit ", "; 
           emit_operand d; 
           emit "("; 
           emitCell b; 
           emit ")"; 
           emit_region mem )
       | I.FSTORE{stOp, r, b, d, mem} => 
         ( emit_fstore stOp; 
           emit "\t"; 
           emitCell r; 
           emit ", "; 
           emit_operand d; 
           emit "("; 
           emitCell b; 
           emit ")"; 
           emit_region mem )
       | I.JMPL({r, b, d}, list) => 
         ( emit "jmp\t"; 
           emitCell r; 
           emit ", ("; 
           emitCell b; 
           emit ")" )
       | I.JSR{r, b, d, defs, uses, cutsTo, mem} => 
         ( emit "jsr\t"; 
           emitCell r; 
           emit ", ("; 
           emitCell b; 
           emit ")"; 
           emit_region mem; 
           emit_defs defs; 
           emit_uses uses; 
           emit_cutsTo cutsTo )
       | I.BSR{r, lab, defs, uses, cutsTo, mem} => 
         ( emit "bsr\t"; 
           emitCell r; 
           emit ", "; 
           emit_label lab; 
           emit_region mem; 
           emit_defs defs; 
           emit_uses uses; 
           emit_cutsTo cutsTo )
       | I.RET{r, b, d} => 
         ( emit "ret\t"; 
           emitCell r; 
           emit ", ("; 
           emitCell b; 
           emit ")" )
       | I.BRANCH{b, r, lab} => 
         ( emit_branch b; 
           emit "\t"; 
           emitCell r; 
           emit ", "; 
           emit_label lab )
       | I.FBRANCH{b, f, lab} => 
         ( emit_fbranch b; 
           emit "\t"; 
           emitCell f; 
           emit ", "; 
           emit_label lab )
       | I.OPERATE{oper, ra, rb, rc} => 
         let 
(*#line 568.15 "alpha/alpha.mdl"*)
             fun disp () = 
                 ( emit_operate oper; 
                   emit "\t"; 
                   emitCell ra; 
                   emit ", "; 
                   emit_operand rb; 
                   emit ", "; 
                   emitCell rc )
         in 
            (case (oper, CellsBasis.registerId ra, rb, CellsBasis.registerId rc) of
              (I.BIS, 27, I.REGop rb, 29) => (if ((CellsBasis.registerId rb) = 31)
                 then (emit "ldgp\t$29, 0($27)")
                 else (disp ()))
            | (I.BIS, 26, I.REGop rb, 29) => (if ((CellsBasis.registerId rb) = 31)
                 then (emit "ldgp\t$29, 0($26)")
                 else (disp ()))
            | _ => disp ()
            )
         end
       | I.OPERATEV{oper, ra, rb, rc} => 
         ( emit_operateV oper; 
           emit "\t"; 
           emitCell ra; 
           emit ", "; 
           emit_operand rb; 
           emit ", "; 
           emitCell rc )
       | I.CMOVE{oper, ra, rb, rc} => 
         ( emit_cmove oper; 
           emit "\t"; 
           emitCell ra; 
           emit ", "; 
           emit_operand rb; 
           emit ", "; 
           emitCell rc )
       | I.PSEUDOARITH{oper, ra, rb, rc, tmps} => 
         ( emit_pseudo_op oper; 
           emit "\t"; 
           emitCell ra; 
           emit ", "; 
           emit_operand rb; 
           emit ", "; 
           emitCell rc; 
           emit_cellset ("tmps", tmps))
       | I.FUNARY{oper, fb, fc} => 
         ( emit_funary oper; 
           emit "\t"; 
           emitCell fb; 
           emit ", "; 
           emitCell fc )
       | I.FOPERATE{oper, fa, fb, fc} => 
         ( emit_foperate oper; 
           emit "\t"; 
           emitCell fa; 
           emit ", "; 
           emitCell fb; 
           emit ", "; 
           emitCell fc )
       | I.FOPERATEV{oper, fa, fb, fc} => 
         ( emit_foperateV oper; 
           emit "\t"; 
           emitCell fa; 
           emit ", "; 
           emitCell fb; 
           emit ", "; 
           emitCell fc )
       | I.FCMOVE{oper, fa, fb, fc} => 
         ( emit_fcmove oper; 
           emit "\t"; 
           emitCell fa; 
           emit ", "; 
           emitCell fb; 
           emit ", "; 
           emitCell fc )
       | I.TRAPB => emit "trapb"
       | I.CALL_PAL{code, def, use} => 
         ( emit "call_pal "; 
           emit_osf_user_palcode code )
       | I.SOURCE{} => emit "source"
       | I.SINK{} => emit "sink"
       | I.PHI{} => emit "phi"
       )
      in  tab(); emitInstr' instr; nl()
      end (* emitter *)
      and emitInstrIndented i = (indent(); emitInstr i; nl())
      and emitInstrs instrs =
           app (if !indent_copies then emitInstrIndented
                else emitInstr) instrs
   
      and emitInstr(I.ANNOTATION{i,a}) =
           ( comment(Annotations.toString a);
              nl();
              emitInstr i )
        | emitInstr(I.LIVE{regs, spilled})  = 
            comment("live= " ^ CellsBasis.CellSet.toString regs ^
                    "spilled= " ^ CellsBasis.CellSet.toString spilled)
        | emitInstr(I.KILL{regs, spilled})  = 
            comment("killed:: " ^ CellsBasis.CellSet.toString regs ^
                    "spilled:: " ^ CellsBasis.CellSet.toString spilled)
        | emitInstr(I.INSTR i) = emitter i
        | emitInstr(I.COPY{k=CellsBasis.GP, sz, src, dst, tmp}) =
           emitInstrs(Shuffle.shuffle{tmp=tmp, src=src, dst=dst})
        | emitInstr(I.COPY{k=CellsBasis.FP, sz, src, dst, tmp}) =
           emitInstrs(Shuffle.shufflefp{tmp=tmp, src=src, dst=dst})
        | emitInstr _ = error "emitInstr"
   
   in  S.STREAM{beginCluster=init,
                pseudoOp=pseudoOp,
                emit=emitInstr,
                endCluster=fail,
                defineLabel=defineLabel,
                entryLabel=entryLabel,
                comment=comment,
                exitBlock=doNothing,
                annotation=annotation,
                getAnnotations=getAnnotations
               }
   end
end

