Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] View of /sml/trunk/src/MLRISC/alpha/alpha.mdl
ViewVC logotype

View of /sml/trunk/src/MLRISC/alpha/alpha.mdl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1003 - (download) (annotate)
Fri Dec 7 02:45:32 2001 UTC (18 years, 1 month ago) by george
File size: 25070 byte(s)
Changed the representation of instructions from being fully abstract
to being partially concrete. That is to say:

  from
	type instruction

  to
	type instr				(* machine instruction *)

	datatype instruction =
	    LIVE of {regs: C.cellset, spilled: C.cellset}
          | KILL of {regs: C.cellset, spilled: C.cellset}
          | COPYXXX of {k: CB.cellkind, dst: CB.cell list, src: CB.cell list}
          | ANNOTATION of {i: instruction, a: Annotations.annotation}
          | INSTR of instr

This makes the handling of certain special instructions that appear on
all architectures easier and uniform.

LIVE and KILL say that a list of registers are live or killed at the
program point where they appear. No spill code is generated when an
element of the 'regs' field is spilled, but the register is moved to
the 'spilled' (which is present, more for debugging than anything else).

LIVE replaces the (now deprecated) DEFFREG instruction on the alpha.
We used to generate:

	DEFFREG f1
	f1 := f2 + f3
        trapb

but now generate:

	f1 := f2 + f3
	trapb
	LIVE {regs=[f1,f2,f3], spilled=[]}

Furthermore, the DEFFREG (hack) required that all floating point instruction
use all registers mentioned in the instruction. Therefore f1 := f2 + f3,
defines f1 and uses [f1,f2,f3]! This hack is no longer required resulting
in a cleaner alpha implementation. (Hopefully, intel will not get rid of
this architecture).

COPYXXX is intended to replace the parallel COPY and FCOPY  available on
all the architectures. This will result in further simplification of the
register allocator that must be aware of them for coalescing purposes, and
will also simplify certain aspects of the machine description that provides
callbacks related to parallel copies.

ANNOTATION should be obvious, and now INSTR represents the honest to God
machine instruction set!

The <arch>/instructions/<arch>Instr.sml files define certain utility
functions for making porting easier -- essentially converting upper case
to lower case. All machine instructions (of type instr) are in upper case,
and the lower case form generates an MLRISC instruction. For example on
the alpha we have:

  datatype instr =
     LDA of {r:cell, b:cell, d:operand}
   | ...

  val lda : {r:cell, b:cell, d:operand} -> instruction
    ...

where lda is just (INSTR o LDA), etc.
(* 
 * This machine description now includes 64-bit and single precision 
 * floating point support.  The description
 * is copied from the book ``Alpha Architecture Reference Manual'' edited
 * by Richard L. Sites, Digital Press, 1992.
 *
 * -- Allen Leung
 *)
architecture Alpha =
struct

   superscalar

   little endian    

   lowercase assembly

   (*
    * This specify the cells interface 
    *)
   storage
     GP = $r[32] of 64 bits where $r[31] = 0
              asm: (fn (30,_) => "$sp"
                     | (r,_)  => "$"^Int.toString r
                   )
   | FP = $f[32] of 64 bits where $f[31] = 0
              asm: (fn (f,_) => "$f"^Int.toString f)
   | CC = $cc[] of 64 bits aliasing GP asm: "cc"
   | MEM = $m[] of 8 aggregable bits asm: (fn (r,_) => "m"^Int.toString r)
   | CTRL = $ctrl[] asm: (fn (r,_) => "ctrl"^Int.toString r)

   locations
       stackptrR  = $r[30]
   and asmTmpR    = $r[28]
   and fasmTmp    = $r[30]
   and returnAddr = $r[26]
   and r31        = $r[31]
   and f31        = $f[31]

   structure RTL =
   struct
     include "Tools/basis.mdl"
     open Basis
     infix 1 ||
     infix 2 := 
     infix 3 << >> ~>>

     (* rtl COPY{dst,src} = $r[forall dst] := $r[forall src]
     rtl FCOPY{dst,src} = $f[forall dst] := $f[forall src] *)

     (* How to align addresses *)
     fun align4 addr      = andb(addr,notb 3)
     fun align8 addr      = andb(addr,notb 7)
     fun align8Upper addr = orb(andb(addr,notb 7),4)

     fun %% l = (l : #64 bits)

     fun disp(b,d) = $r[b] + d

     fun byte x  = (x : #8 bits)
     fun word x  = (x : #16 bits)
     fun dword x = (x : #32 bits)
     fun qword x  = (x : #64 bits)
     fun float x = (x : #32 bits)
     fun double x  = (x : #64 bits)

     rtl LDA{r,b,d} = $r[r] := $r[b] + d
     rtl LDAH{r,b,d} = $r[r] := $r[b] + d << 16

     (* Integer loads *)
     rtl LDB{r,b,d,mem}    = $r[r] := sx (byte $m[disp(b,d):mem])
     rtl LDW{r,b,d,mem}    = $r[r] := sx (word $m[disp(b,d):mem])
     rtl LDBU{r,b,d,mem}   = $r[r] := zx (byte $m[disp(b,d):mem])
     rtl LDWU{r,b,d,mem}   = $r[r] := zx (word $m[disp(b,d):mem])
     rtl LDL{r,b,d,mem}    = $r[r] := sx (dword $m[disp(b,d):mem])
     rtl LDL_L{r,b,d,mem}  = $r[r] := sx (dword $m[align4(disp(b,d)):mem])
     rtl LDQ{r,b,d,mem}    = $r[r] := qword $m[disp(b,d):mem]
     rtl LDQ_L{r,b,d,mem}  = $r[r] := qword $m[align8(disp(b,d)):mem]
     rtl LDQ_U{r,b,d,mem}  = $r[r] := qword $m[align8Upper(disp(b,d)):mem]

     (* Integer stores *)
     rtl STB{r,b,d,mem}    = $m[disp(b,d):mem] := $r[r] at [0..7]
     rtl STW{r,b,d,mem}    = $m[disp(b,d):mem] := $r[r] at [0..15]
     rtl STL{r,b,d,mem}    = $m[disp(b,d):mem] := $r[r] at [0..31]
     rtl STQ{r,b,d,mem}    = $m[disp(b,d):mem] := $r[r] 
     rtl STQ_U{r,b,d,mem}  = $m[align8(disp(b,d)):mem] := $r[r] 

     (* Floating point loads *)
     rtl LDF{r,b,d,mem} = $f[r] := sx (float $m[disp(b,d):mem])
     rtl LDG{r,b,d,mem} = $f[r] := double $m[disp(b,d):mem] 
     rtl LDS{r,b,d,mem} = $f[r] := double $m[disp(b,d):mem] 
     rtl LDT{r,b,d,mem} = $f[r] := double $m[disp(b,d):mem]

     (* Floating point stores *)
     rtl STF{r,b,d,mem} = $m[disp(b,d):mem] := float(sx $f[r])
     rtl STG{r,b,d,mem} = $m[disp(b,d):mem] := $f[r]
     rtl STS{r,b,d,mem} = $m[disp(b,d):mem] := $f[r]
     rtl STT{r,b,d,mem} = $m[disp(b,d):mem] := $f[r]

     (* Integer operators *)
     rtl ADDL{ra,rb,rc}   = $r[rc] := sx($r[ra] + rb)
     rtl ADDQ{ra,rb,rc}   = $r[rc] := $r[ra] + rb
     fun cmp oper {ra,rb,rc} = $r[rc] := cond(oper($r[ra],rb),  1, 0)

     rtl [CMPBGE, CMPEQ, CMPLE, CMPLT, CMPULE, CMPULT] =
         map cmp [(>=), (==), (<=), (<), (leu), (ltu)]

     fun binop oper {ra,rb,rc} = $r[rc] := oper($r[ra], rb)

     rtl SUBL{ra,rb,rc}   = $r[rc] := sx($r[ra] - rb)
     rtl SUBQ{ra,rb,rc}   = $r[rc] := $r[ra] - rb
     rtl S4ADDL{ra,rb,rc} = $r[rc] := sx($r[ra] << 2 + rb)
     rtl S4ADDQ{ra,rb,rc} = $r[rc] := $r[ra] << 2 + rb
     rtl S4SUBL{ra,rb,rc} = $r[rc] := sx($r[ra] << 2 - rb)
     rtl S4SUBQ{ra,rb,rc} = $r[rc] := $r[ra] << 2 - rb
     rtl S8ADDL{ra,rb,rc} = $r[rc] := sx($r[ra] << 3 + rb)
     rtl S8ADDQ{ra,rb,rc} = $r[rc] := $r[ra] << 3 + rb
     rtl S8SUBL{ra,rb,rc} = $r[rc] := sx($r[ra] << 3 - rb)
     rtl S8SUBQ{ra,rb,rc} = $r[rc] := $r[ra] << 3 - rb
     rtl AND{ra,rb,rc}    = $r[rc] := andb($r[ra], rb)
     rtl BIC{ra,rb,rc}    = $r[rc] := andb($r[ra], notb(rb)) (* XXX *)
     rtl BIS{ra,rb,rc}    = $r[rc] := orb($r[ra], rb)
     rtl EQV{ra,rb,rc}    = $r[rc] := eqvb($r[ra], rb)
     rtl ORNOT{ra,rb,rc}  = $r[rc] := orb($r[ra], notb(rb))
     rtl XOR{ra,rb,rc}    = $r[rc] := xorb($r[ra], rb)

     rtl extbl extlh extll extqh extql extwh extwl insbl inslh insll
         insqh insql inswh inswl mskbl msklh mskll mskqh mskql mskwh mskwl 
          : #n bits * #n bits -> #n bits
     rtl [EXTBL, EXTLH, EXTLL, EXTQH, EXTQL, EXTWH, EXTWL,
          INSBL, INSLH, INSLL, INSQH, INSQL, INSWH, INSWL,
          MSKBL, MSKLH, MSKLL, MSKQH, MSKQL, MSKWH, MSKWL] =
         map binop 
         [extbl, extlh, extll, extqh, extql, extwh, extwl,
          insbl, inslh, insll, insqh, insql, inswh, inswl,
          mskbl, msklh, mskll, mskqh, mskql, mskwh, mskwl]

     rtl [SLL, SRA, SRL] = 
          map binop [(<<), (~>>), (>>)]

     rtl zap zapnot umulh : #n bits * #n bits -> #n bits
     rtl ZAP{ra,rb,rc} = $r[rc] := zap($r[ra], rb) 
     rtl ZAPNOT{ra,rb,rc} = $r[rc] := zapnot($r[ra], rb) 
     rtl MULL{ra,rb,rc}  = $r[rc] := sx(muls($r[ra], rb))
     rtl MULQ{ra,rb,rc}  = $r[rc] := muls($r[ra], rb)
     rtl UMULH{ra,rb,rc} = $r[rc] := umulh($r[ra], rb) 

     (* Integer trapping operators *)
     val overflowtrap = ()
     rtl ADDLV{ra,rb,rc} = ADDL{ra,rb,rc} || overflowtrap
     rtl ADDQV{ra,rb,rc} = ADDQ{ra,rb,rc} || overflowtrap
     rtl SUBLV{ra,rb,rc} = SUBL{ra,rb,rc} || overflowtrap
     rtl SUBQV{ra,rb,rc} = SUBQ{ra,rb,rc} || overflowtrap
     rtl MULLV{ra,rb,rc} = MULL{ra,rb,rc} || overflowtrap
     rtl MULQV{ra,rb,rc} = MULQ{ra,rb,rc} || overflowtrap

     fun lbc(x,y) = andb(x,1) == y
     fun lbs(x,y) = andb(x,1) <> y

     val comparisons = [(==), lbc, lbs, (>=), (>), (<=), (<), (<>)]

     (* Conditional moves *)
     fun cmov oper {ra,rb,rc} = if oper($r[ra], 0) then $r[rc] := rb else ()

     rtl CMOV ^^ [EQ, LBC, LBS, GE, GT, LE, LT, NE] =
         map cmov comparisons

     (* Integer branches *)
     rtl BR{lab} = Jmp(%%lab)
     rtl BSR{lab,r,defs,uses,mem} = 
         Call(%%lab) || 
         Kill $r[r] || 
         Kill $cellset[defs] ||
         Use $cellset[uses] ||
         $m[??? :mem] := ($m[??? :mem] : #8 bits)

     fun branch oper {r,lab} = if oper($r[r], 0) then Jmp(%%lab) else ()

     rtl [BEQ, BLBC, BLBS, BGE, BGT, BLE, BLT, BNE] =
         map branch comparisons
 
     (* Floating point operators *)

     val SU = ()
     val SUD = ()
     fun farith oper {fa,fb,fc} = $f[fc] := oper($f[fa], $f[fb])
     fun funary oper {fb,fc} = $f[fc] := oper($f[fb])
     rtl fops as [ADDS, ADDT, SUBS, SUBT, MULS, MULT, DIVS, DIVT] =
         map farith
         [fadd, fadd, fsub, fsub, fmul, fmul, fdiv, fdiv]
     fun su fop {fa,fb,fc} = fop{fa,fb,fc} || SU
     fun sud fop {fa,fb,fc} = fop{fa,fb,fc} || SUD 
     rtl [ADDSSU, ADDTSU, SUBSSU, SUBTSU, MULSSU, MULTSU, DIVSSU, DIVTSU] =
         map su fops
     rtl [ADDSSUD, ADDTSUD, SUBSSUD, SUBTSUD, 
          MULSSUD, MULTSUD, DIVSSUD, DIVTSUD] =
         map sud fops

     rtl cpys  cpyse  cpysn mf_fpcr mt_fpcr : #64 bits * #64 bits -> #64 bits
     rtl [CPYS,CPYSE, CPYSN, MF_FPCR, MT_FPCR] =
         map farith [cpys, cpyse, cpysn, mf_fpcr, mt_fpcr]

     rtl cvtlq cvtql  cvtqlsv cvtqlv cvtqs cvtqsc 
         cvtqt cvtqtc cvtts  cvttsc 
         cvtst cvtsts cvttq  cvttqc : #64 bits -> #64 bits

     rtl CVT^^[LQ,QL,QLSV,QLV,QS,QSC,QT,QTC,TS,TSC,ST,STS,TQ,TQC] =
          map funary cvt^^[lq,ql,qlsv,qlv,qs,qsc,qt,qtc,ts,tsc,st,sts,tq,tqc]
 
     rtl teq tlt tle tun : #64 bits * #64 bits -> #64 bits
     rtl fcmps as [CMPTEQ, CMPTLT, CMPTLE, CMPTUN] = 
            map farith [teq, tlt, tle, tun]
     rtl [CMPTEQSU, CMPTLTSU, CMPTLESU, CMPTUNSU] = 
            map su fcmps

     (* Floating point branches *)
     fun fbranch oper {f,lab} = if oper($f[f],???) then Jmp(%%lab) else ()
     rtl [FBEQ, FBLT, FBLE, FBNE, FBGE, FBGT] =
         map fbranch [|==|,  |<|,  |<=|, |<>|, |>=|, |>|]

     (* Floating point moves *)
     fun fcmove cmp {fa,fb,fc} = 
          if cmp($f[fa],???) then $f[fc] := $f[fb] else ()
     rtl FCMOV ^^ [EQ, LT, LE, NE, GE, GT] =
         map fcmove [|==|,  |<|,  |<=|, |<>|, |>=|, |>|]

     (* Call/return *)
     rtl JSR{r,b,defs,uses,mem} = 
         Call($r[b]) || 
         Kill $r[r]  || 
         Kill $cellset[defs] ||
         Use $cellset[uses] || 
         $m[??? :mem] := ($m[??? :mem] : #8 bits)
     rtl RET{r,b} = Jmp($r[b]) || Kill $r[r]
     rtl JMPL{r,b} = Jmp($r[b]) || Kill $r[r]
     rtl TRAPB{} = ()

     (* Pseudo arithmetic *)
     fun pseudoOp oper {ra,rb,rc,tmps} = 
         $r[rc] := oper($r[ra], rb) ||
         Kill $cellset[tmps] (* XXX *)
     rtl PSEUDOARITH_ ^^ [ DIVL, DIVLU, DIVQ, DIVQU,
                           REML, REMLU, REMQ, REMQU ] = 
         map pseudoOp    [ divs,  divu,  divs,  divu,   (* XXX *)
                           rems,  remu,  rems,  remu ]
     (* Pal code 
      * Note: I have no idea what these things are, so I'm just going
      * fake them
      *)
     rtl BPT BUGCHK CALLSYS GENTRAP IMB RDUNIQUE WRUNIQUE : #64 bits -> #64 bits
     fun CALL_PAL code {def,use} =
         Call(qword(code(qword 0))) || 
         Kill $cellset[def] ||
         Use $cellset[use]
     rtl CALL_PAL_ ^^ 
         [BPT, BUGCHK, CALLSYS, GENTRAP, IMB, RDUNIQUE, WRUNIQUE] =
         map CALL_PAL 
         [BPT, BUGCHK, CALLSYS, GENTRAP, IMB, RDUNIQUE, WRUNIQUE] 
   end (* RTL *)


   (*
    * Reservation tables and pipeline definitions for scheduling
    *)

   (* Function units *)
   resource issue and mem and alu and falu and fmul and fdiv and branch

   (* Different implementations of cpus *)
   cpu default 2 [2 issue, 2 mem, 1 alu]  (* 2 issue machine *)

   (* Definitions of various reservation tables *) 
   pipeline NOP _    = [issue] 
    and     ARITH _  = [issue^^alu]
    and     LOAD _   = [issue^^mem]
    and     STORE _  = [issue^^mem,mem,mem] 
    and     FARITH _ = [issue^^falu]
    and     FMUL _   = [issue^^fmul,fmul]
    and     FDIV _   = [issue^^fdiv,fdiv*50]
    and     BRANCH _ = [issue^^branch]

   (* 
    * We now specify the instruction representation, assembly,
    * machine code encoding and ``semantics''
    *)
   structure Instruction = 
   struct
      datatype ea = 
          Direct of $GP 
        | FDirect of $FP         
        | Displace of {base: $GP, disp:int}
    
      datatype operand = 
          REGop of $GP          ``<GP>''          rtl: $r[GP]
        | IMMop of int          ``<int>''         rtl: immed int
        | HILABop of T.labexp   ``hi(<labexp>)''  rtl: hi(labexp)
        | LOLABop of T.labexp   ``lo(<labexp>)''  rtl: lo(labexp)
        | LABop of T.labexp     ``<labexp>''      rtl: labexp
   
      (* 
       * When I say ! after the datatype name XXX, it means generate a
       * function emit_XXX that converts the constructors into the corresponding
       * assembly text.  By default, it uses the same name as the constructor,
       * but may be modified by the lowercase/uppercase assembly directive.
       * 
       *)
      datatype branch! =  (* table C-2 *)
         BR   0x30  
                   (*| BSR 0x34 *)
                              | BLBC 0x38
       | BEQ  0x39 | BLT 0x3a | BLE  0x3b
       | BLBS 0x3c | BNE 0x3d | BGE  0x3e 
       | BGT  0x3f
   
      datatype fbranch! = (* table C-2 *)
                     FBEQ 0x31 | FBLT 0x32
       | FBLE 0x33             | FBNE 0x35
       | FBGE 0x36 | FBGT 0x37 
    
      datatype load! =  (* table C-1 *)
         LDB
       | LDW
       | LDBU  0x02 
       | LDWU  0x04
       | LDL   0x28    
       | LDL_L 0x2A  
       | LDQ   0x29    
       | LDQ_L 0x2B 
       | LDQ_U 0x0B
      datatype store! = STB 0x0E | STW 0x0D | STL 0x2C | STQ 0x2D | STQ_U 0x0F
      datatype fload [0x20..0x23] ! = LDF | LDG | LDS | LDT 
      datatype fstore [0x24..0x27] ! = STF | STG | STS | STT 
   
      (* non-trapping opcodes *) 
      datatype operate! = (* table C-5 *)
          ADDL  (0wx10,0wx00)                       | ADDQ (0wx10,0wx20) 
                              | CMPBGE(0wx10,0wx0f) | CMPEQ (0wx10,0wx2d) 
        | CMPLE (0wx10,0wx6d) | CMPLT (0wx10,0wx4d) | CMPULE (0wx10,0wx3d) 
        | CMPULT(0wx10,0wx1d) | SUBL  (0wx10,0wx09) 
        | SUBQ  (0wx10,0wx29) 
        | S4ADDL(0wx10,0wx02) | S4ADDQ (0wx10,0wx22) | S4SUBL (0wx10,0wx0b)
        | S4SUBQ(0wx10,0wx2b) | S8ADDL (0wx10,0wx12) | S8ADDQ (0wx10,0wx32)
        | S8SUBL(0wx10,0wx1b) | S8SUBQ (0wx10,0wx3b) 
   
        | AND   (0wx11,0wx00) | BIC    (0wx11,0wx08) | BIS    (0wx11,0wx20)
                                                     | EQV (0wx11,0wx48)
        | ORNOT (0wx11,0wx28) | XOR    (0wx11,0wx40)
   
        | EXTBL (0wx12,0wx06) | EXTLH  (0wx12,0wx6a) | EXTLL(0wx12,0wx26)
        | EXTQH (0wx12,0wx7a) | EXTQL  (0wx12,0wx36) | EXTWH(0wx12,0wx5a)
        | EXTWL (0wx12,0wx16) | INSBL  (0wx12,0wx0b) | INSLH(0wx12,0wx67)
        | INSLL (0wx12,0wx2b) | INSQH  (0wx12,0wx77) | INSQL(0wx12,0wx3b)
        | INSWH (0wx12,0wx57) | INSWL  (0wx12,0wx1b) | MSKBL(0wx12,0wx02)
        | MSKLH (0wx12,0wx62) | MSKLL  (0wx12,0wx22) | MSKQH(0wx12,0wx72)
        | MSKQL (0wx12,0wx32) | MSKWH  (0wx12,0wx52) | MSKWL(0wx12,0wx12)
        | SLL   (0wx12,0wx39) | SRA    (0wx12,0wx3c) | SRL  (0wx12,0wx34)
        | ZAP   (0wx12,0wx30) | ZAPNOT (0wx12,0wx31)
        | MULL  (0wx13,0wx00)                        | MULQ (0wx13,0wx20)
                              | UMULH  (0wx13,0wx30) 
   
      (* conditional moves *) 
      datatype cmove! =
         CMOVEQ 0wx24 | CMOVLBC 0wx16 | CMOVLBS 0wx14
       | CMOVGE 0wx46 | CMOVGT  0wx66 | CMOVLE  0wx64
       | CMOVLT 0wx44 | CMOVNE  0wx26 
    
      datatype pseudo_op! = DIVL | DIVLU | DIVQ | DIVQU 
                          | REML | REMLU | REMQ | REMQU
    
      datatype operateV! = (* table C-5 opc/func *)
         ADDLV (0wx10,0wx40) | ADDQV (0wx10,0wx60)
       | SUBLV (0wx10,0wx49) | SUBQV (0wx10,0wx69) 
       | MULLV (0wx13,0wx40) | MULQV (0wx13,0wx60)
   
      datatype funary! = (* table C-6/C-7 *)
             (* C-6 *)
         CVTLQ   (0wx17,0wx010) | CVTQL (0wx17,0wx030) | CVTQLSV (0wx17,0wx530)
       | CVTQLV  (0wx17,0wx130)
   
             (* C-7 *)
       | CVTQS   (0wx16,0wxbc)  | CVTQSC  (0wx16,0wx3c)
       | CVTQT   (0wx16,0wxbe)  | CVTQTC  (0wx16,0wx3e)
       | CVTTS   (0wx16,0wxac)  | CVTTSC  (0wx16,0wx2c)
       | CVTST   (0wx16,0wx2ac) | CVTSTS  (0wx16,0wx6ac)
       | CVTTQ   (0wx16,0wxaf)  | CVTTQC  (0wx16,0wx2f)
    
      datatype foperate! =   (* table C-6 *)
         CPYS    (0wx17,0wx20)  | CPYSE    (0wx17,0wx022) | CPYSN (0wx17,0wx021)
       | MF_FPCR (0wx17,0wx025) | MT_FPCR  (0wx17,0wx024)
   
                            (* table C-7 *)
       | CMPTEQ  (0wx16,0wx0a5) | CMPTLT (0wx16,0wx0a6)  | CMPTLE (0wx16,0wx0a7)
       | CMPTUN  (0wx16,0wx0a4)
   
       | CMPTEQSU(0wx16,0wx5a5) | CMPTLTSU(0wx16,0wx5a6) |CMPTLESU(0wx16,0wx5a7)
       | CMPTUNSU(0wx16,0wx5a4)

       | ADDS (0wx16,0wx080) | ADDT (0wx16,0wx0a0) 
       | DIVS (0wx16,0wx083) | DIVT (0wx16,0wx0a3)
       | MULS (0wx16,0wx082) | MULT (0wx16,0wx0a2) 
       | SUBS (0wx16,0wx081) | SUBT (0wx16,0wx0a1)
   
      datatype fcmove! =
         FCMOVEQ 0wx02a | FCMOVGE 0wx02d | FCMOVGT 0wx02f
       | FCMOVLE 0wx02e | FCMOVLT 0wx02c | FCMOVNE 0wx02b
   
      datatype foperateV! = (* table C-7 *)
         ADDSSUD  0wx5c0  | ADDSSU 0wx580 
       | ADDTSUD  0wx5e0  | ADDTSU 0wx5a0 
       | DIVSSUD  0wx5c3  | DIVSSU 0wx583
       | DIVTSUD  0wx5e3  | DIVTSU 0wx5a3
       | MULSSUD  0wx5c2  | MULSSU 0wx582
       | MULTSUD  0wx5e2  | MULTSU 0wx5a2
       | SUBSSUD  0wx5c1  | SUBSSU 0wx581
       | SUBTSUD  0wx5e1  | SUBTSU 0wx5a1
    
      datatype osf_user_palcode! = 
         BPT 0x80 | BUGCHK 0x81 | CALLSYS 0x83 
       | GENTRAP 0xaa | IMB 0x86 | RDUNIQUE 0x9e | WRUNIQUE 0x9f

      type addressing_mode = CellsBasis.cell * operand
   
   end (* Instruction *)

   (*
    * Alpha has very simple instruction encoding formats.
    *)
   instruction formats 32 bits 
     Memory{opc:6, ra:5, rb:GP 5, disp: signed 16} (* p3-9 *)
      (* derived from Memory *) 
   | Split{le} = let val i = MLTreeEval.valueOf le
                     val w = itow i 
                     val hi = w ~>> 0w16
                     val lo = w && 0w65535
                 in  if lo < 0w32768 then (hi,lo) else (hi+0w1,lo-0w65536)
                 end 
   | High{le} = let val (hi,_) = Split{le=le} in hi end
   | Low{le}  = let val (_,lo) = Split{le=le} in lo end
   | LoadStore{opc,ra,rb,disp} =
       let val disp = 
           case disp of
             I.REGop rb => emit_GP rb
           | I.IMMop i  => itow i
           | I.HILABop le => High{le=le}
           | I.LOLABop le => Low{le=le}
           | I.LABop le => itow(MLTreeEval.valueOf le)
       in  Memory{opc,ra,rb,disp}
       end
   | ILoadStore{opc,r:GP,b,d} = LoadStore{opc,ra=r,rb=b,disp=d}
   | FLoadStore{opc,r:FP,b,d} = LoadStore{opc,ra=r,rb=b,disp=d}

   | Jump{opc:6=0wx1a,ra:GP 5,rb:GP 5,h:2,disp:int signed 14}   (* table C-3 *)
   | Memory_fun{opc:6, ra:GP 5, rb:GP 5, func:16}     (* p3-9 *)
   | Branch{opc:branch 6, ra:GP 5, disp:signed 21}           (* p3-10 *)
   | Bsr{opc:6=0wx34, ra:GP 5, disp:signed 21}           (* p3-10 *)
   | Fbranch{opc:fbranch 6, ra:FP 5, disp:signed 21}          (* p3-10 *)
        (* p3-11 *)
   | Operate0{opc:6,ra:GP 5,rb:GP 5,sbz:13..15=0,_:1=0,func:5..11,rc:GP 5} 
        (* p3-11 *)
   | Operate1{opc:6,ra:GP 5,lit:signed 13..20,_:1=1,func:5..11,rc:GP 5} 
   | Operate{opc,ra,rb,func,rc} =
        (case rb of
          I.REGop rb => Operate0{opc,ra,rb,func,rc}
        | I.IMMop i  => Operate1{opc,ra,lit=itow i,func,rc}
        | I.HILABop le => Operate1{opc,ra,lit=High{le=le},func,rc}
        | I.LOLABop le => Operate1{opc,ra,lit=Low{le=le},func,rc}
        | I.LABop le => Operate1{opc,ra,lit=itow(MLTreeEval.valueOf le),func,rc}
        )
   | Foperate{opc:6,fa:FP 5,fb:FP 5,func:5..15,fc:FP 5}
   | Funary{opc:6,fa:5=31,fb:FP 5,func:5..15,fc:FP 5}
   | Pal{opc:6=0,func:26}

   structure MC =
   struct
      (* compute displacement address *)
      fun disp lab = itow(Label.addrOf lab - !loc - 4) ~>> 0w2
      val zeroR = Option.valOf(C.zeroReg CellsBasis.GP)
   end

   structure Assembly =
   struct
      fun isZero(I.LABop le) = MLTreeEval.valueOf le = 0
        | isZero _ = false
   end

   (*
    * The main instruction set definition consists of the following:
    *  1) constructor-like declaration defines the view of the instruction,
    *  2) assembly directive in funny quotes `` '',
    *  3) machine encoding expression,
    *  4) delay slot directives etc (not necessary in this architecture)
    *) 
   instruction 

   (* Load/Store *)
     LDA of {r: $GP, b: $GP, d:operand}        (* use of REGop is illegal *)
     asm: if isZero d andalso CellsBasis.sameCell(r,b) then ()
          else (``lda\t<r>, <d>''; 
                if CellsBasis.registerId b = 31 then () else ``(<b>)''
               )
     mc:  ILoadStore{opc=0w08,r,b,d}
     rtl: ``LDA''

   | LDAH of {r: $GP, b: $GP, d:operand} (* use of REGop is illegal *)
     asm: (``ldah\t<r>, <d>''; 
           if CellsBasis.registerId b = 31 then () else ``(<b>)''
          )
     mc:  ILoadStore{opc=0w09,r,b,d}
     rtl: ``LDAH''

   | LOAD of {ldOp:load, r: $GP, b: $GP, d:operand, mem:Region.region}
     asm: ``<ldOp>\t<r>, <d>(<b>)<mem>''
     mc:  ILoadStore{opc=emit_load ldOp,r,b,d}
     rtl: ``<ldOp>''
     latency: 1

   | STORE of {stOp:store, r: $GP, b: $GP, d:operand, mem:Region.region}
     asm: ``<stOp>\t<r>, <d>(<b>)<mem>''
     mc:  ILoadStore{opc=emit_store stOp,r,b,d}
     rtl: ``<stOp>''

   | FLOAD of {ldOp:fload, r: $FP, b: $GP, d:operand, mem:Region.region}
     asm: ``<ldOp>\t<r>, <d>(<b>)<mem>''
     mc:  FLoadStore{opc=emit_fload ldOp,r,b,d}
     rtl: ``<ldOp>''
     latency: 1

   | FSTORE of {stOp:fstore, r: $FP, b: $GP, d:operand, mem:Region.region}
     asm: ``<stOp>\t<r>, <d>(<b>)<mem>''
     mc:  FLoadStore{opc=emit_fstore stOp,r,b,d}
     rtl: ``<stOp>''
 
   (* Control Instructions *)
   | JMPL of {r: $GP, b: $GP, d:int} * Label.label list
     asm: ``jmp\t<r>, (<b>)''
     mc:  Jump{h=0w0,ra=r,rb=b,disp=d}   (* table C-3 *)
     rtl: ``JMPL''

   | JSR of {r: $GP, b: $GP, d:int, 
             defs: $cellset, uses: $cellset, cutsTo: Label.label list,
             mem:Region.region}
     asm: ``jsr\t<r>, (<b>)<mem><emit_defs(defs)><emit_uses(uses)><emit_cutsTo cutsTo>''
     mc:  Jump{h=0w1,ra=r,rb=b,disp=d}
     rtl: ``JSR''

   | BSR of {r: $GP, lab: Label.label,
             defs: $cellset, uses: $cellset, cutsTo: Label.label list,
             mem:Region.region}
     asm: ``bsr\t<r>, <lab><mem><emit_defs(defs)><emit_uses(uses)><emit_cutsTo cutsTo>''
     mc:  Bsr{ra=r,disp=disp lab}
     rtl: ``BSR''

   | RET of {r: $GP, b: $GP, d:int} 
     asm: ``ret\t<r>, (<b>)''
     mc:  Jump{h=0w2,ra=r,rb=b,disp=d}
     rtl: ``RET''

   | BRANCH of {b:branch, r: $GP, lab:Label.label}
     asm: ``<b>\t<r>, <lab>''
     mc:  Branch{opc=b,ra=r,disp=disp lab}
     rtl: ``<b>''

   | FBRANCH of {b:fbranch, f: $FP, lab:Label.label}  
     asm: ``<b>\t<f>, <lab>''
     mc:  Fbranch{opc=b,ra=f,disp=disp lab}
     rtl: ``<b>''
 
   (* Integer Operate *)
   | OPERATE of {oper:operate, ra: $GP, rb:operand, rc: $GP}
             (* Pretty print ldgp differently *) 
     asm: let fun disp() = ``<oper>\t<ra>, <rb>, <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 ``ldgp\t$29, 0($27)''
                   else disp()
              |  (I.BIS,26,I.REGop rb,29) => 
                   if CellsBasis.registerId rb = 31 then ``ldgp\t$29, 0($26)''
                   else disp()
              | _                        => disp()
          end
     mc:  let val (opc,func) = emit_operate oper
          in  Operate{opc,func,ra,rb,rc} 
          end
     rtl: ``<oper>''

   | OPERATEV of {oper:operateV, ra: $GP, rb:operand, rc: $GP}
     asm: ``<oper>\t<ra>, <rb>, <rc>''
     mc:  let val (opc,func) = emit_operateV oper
          in  Operate{opc,func,ra,rb,rc} 
          end
     rtl: ``<oper>''

   | CMOVE of {oper:cmove, ra: $GP, rb:operand, rc: $GP}
     asm: ``<oper>\t<ra>, <rb>, <rc>''
     mc:  Operate{opc=0wx11,func=emit_cmove oper,ra,rb,rc} 
     rtl: ``<oper>''
 
   | PSEUDOARITH of {oper: pseudo_op, ra: $GP, rb:operand, rc: $GP, 
                     tmps: $cellset}
     asm: ``<oper>\t<ra>, <rb>, <rc><emit_cellset("tmps",tmps)>''
     rtl: ``PSEUDOARITH_<oper>''
 
   (* Copy instructions *)
   | COPY of {dst: $GP list, src: $GP list, 
              impl:instruction list option ref, tmp: ea option}
     asm: emitInstrs (Shuffle.shuffle{tmp,dst,src})
     rtl: ``COPY''

   | FCOPY of {dst: $FP list, src: $FP list, 
               impl:instruction list option ref, tmp: ea option}
     asm: emitInstrs (Shuffle.shufflefp{tmp,dst,src})
     rtl: ``FCOPY''
 
   (* Floating Point Unary Operation *)
   | FUNARY of {oper:funary, fb: $FP, fc: $FP}
     asm: ``<oper>\t<fb>, <fc>''
     mc:  let val (opc,func) = emit_funary oper
          in  Funary{opc,func,fb,fc}
          end
     rtl: ``<oper>''

   (* Floating Point Operate *)
   | FOPERATE of {oper:foperate, fa: $FP, fb: $FP, fc: $FP}
     asm: ``<oper>\t<fa>, <fb>, <fc>''
     mc:  let val (opc,func) = emit_foperate oper
          in  Foperate{opc,func,fa,fb,fc}
          end
     rtl: ``<oper>''

   (* Trapping versions of the above (what trap -- allen) ??? *)
   | FOPERATEV of {oper:foperateV, fa: $FP, fb: $FP, fc: $FP}
     asm: ``<oper>\t<fa>, <fb>, <fc>''
     mc:  Foperate{opc=0wx16,func=emit_foperateV oper,fa,fb,fc}
     rtl: ``<oper>''

   | FCMOVE of {oper:fcmove, fa: $FP, fb: $FP, fc: $FP}
     asm: ``<oper>\t<fa>, <fb>, <fc>''
     mc:  Foperate{opc=0wx17,func=emit_fcmove oper,fa,fb,fc}
     rtl: ``<oper>''
 
   (* Misc *)
   | TRAPB                                (* Trap barrier *)
     asm: ``trapb''
     mc:  Memory_fun{opc=0wx18,ra=zeroR,rb=zeroR,func=0wx0}
     rtl: ``TRAPB''
 
   | CALL_PAL of {code:osf_user_palcode, def: $cellset, use: $cellset}
     asm: ``call_pal <code>''
     mc:  Pal{func=emit_osf_user_palcode code}
     rtl: ``CALL_PAL_<code>''

   | SOURCE of {}
     asm: ``source''
     mc:  ()

   | SINK of {}
     asm: ``sink''
     mc:  ()

   | PHI of {}
     asm: ``phi''
     mc:  ()

   structure SSA =
   struct
     fun operand(ty, I.REGop r) = T.REG(ty, r)
       | operand(ty, I.IMMop i) = T.LI(IntInf.fromInt i)
       | operand(ty, _) = error "operand"
   end

 end

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0