Annotation of researchv10no/cmd/sml/src/mips/mipscoder.sml, revision 1.1.1.1

1.1       root        1: (* Copyright 1989 by AT&T Bell Laboratories *)
                      2: structure MipsCoder : MIPSCODER = struct
                      3: 
                      4:     type Label = int ref
                      5: 
                      6:   datatype Register = Reg of int
                      7: 
                      8:   datatype EA = Direct of Register
                      9:               | Immed of int
                     10:               | Immedlab of Label
                     11: 
                     12:   datatype size = Byte | Word | Floating
                     13:     datatype muldiv = MULT | DIV
                     14:   
                     15:   datatype instr = 
                     16:       STRINGCONST of string               (* constants *)
                     17:     | REALCONST of string
                     18:     | EMITLONG of int
                     19:   
                     20:     | DEFINE of Label                     (* labels *)
                     21:     | EMITLAB of int * Label
                     22:   
                     23:     | SLT of Register * EA * Register     (* control flow *)
                     24:     | BEQ of bool * Register * Register * Label
                     25:     | JUMP of Register 
                     26:     | SLT_D of Register * Register
                     27:     | SEQ_D of Register * Register
                     28:     | BCOP1 of bool * Label
                     29:   
                     30:     | NOP (* no-op for delay slot *)
                     31:   
                     32:     | ADD of Register * EA * Register     (* arithmetic *)
                     33:     | AND of Register * EA * Register
                     34:     | OR  of Register * EA * Register
                     35:     | XOR of Register * EA * Register
                     36:     | SUB of Register * Register * Register
                     37:     | MULDIV of muldiv * Register * Register
                     38:     | MFLO of Register    (* mflo instruction used with
                     39:                              64-bit multiply and divide *)
                     40:     | MFHI of Register
                     41:   
                     42:     | NEG_D of Register * Register
                     43:     | MUL_D of Register * Register * Register
                     44:     | DIV_D of Register * Register * Register
                     45:     | ADD_D of Register * Register * Register
                     46:     | SUB_D of Register * Register * Register
                     47:   
                     48:     | MOVE of EA * Register    (* put something into a register *)
                     49:     | LDI_32 of int * Register (* load in a big immediate constant (>16 bits) *)
                     50:     | LUI of Register * int    (* Mips lui instruction *)
                     51:   
                     52:     | LOAD of size * Register * EA * int  (* load and store *)
                     53:     | STORE  of size * Register * EA * int
                     54:   
                     55:     | SLL of EA * Register * Register     (* shift *)
                     56:     | SRA of EA * Register * Register
                     57:   
                     58:     | COMMENT of string                   (* generates nothing *)
                     59:     | MARK                                (* a backpointer *)
                     60: 
                     61:     val kept = ref nil : instr list ref
                     62:     fun keep f a = kept := f a :: !kept
                     63:     fun delay f a = kept := NOP :: f a :: !kept
                     64:     fun keeplist l = kept := l @ !kept
                     65:   
                     66:   structure M = struct
                     67:       val emitstring = keep STRINGCONST     (* literals *)
                     68:       val realconst = keep REALCONST
                     69:       val emitlong = keep EMITLONG
                     70:     
                     71:         fun newlabel () = ref 0
                     72:         val define = keep DEFINE
                     73:         val emitlab = keep EMITLAB                   (* labels *)
                     74:     
                     75:       val slt = keep SLT                    (* control flow *)
                     76:       val beq = delay BEQ
                     77:       val jump = delay JUMP
                     78:       val slt_double = delay SLT_D
                     79:       val seq_double = delay SEQ_D
                     80:       val bcop1 = delay BCOP1
                     81:     
                     82:       val add = keep ADD                    (* arithmetic *)
                     83:       val and' = keep AND
                     84:       val or = keep OR
                     85:       val xor = keep XOR
                     86:       val op sub = keep SUB
                     87:         fun muldiv f (a,b,c) = keeplist [MFLO c, MULDIV (f,a,b)]
                     88:         val op div = muldiv DIV
                     89:         val mult = muldiv MULT
                     90:         val mfhi = keep MFHI
                     91:     
                     92:       val neg_double = keep NEG_D
                     93:       val mul_double = keep MUL_D
                     94:       val div_double = keep DIV_D
                     95:       val add_double = keep ADD_D
                     96:       val sub_double = keep SUB_D
                     97:     
                     98:       val move = keep MOVE
                     99:     
                    100:       fun lbu (a,b,c) = delay LOAD (Byte,a,b,c) (* load and store *)
                    101:       fun lw (a,b,c)  = delay LOAD (Word,a,b,c)
                    102:       fun lwc1 (a,b,c)  = delay LOAD (Floating,a,b,c)
                    103:       fun sb (a,b,c)  = keep STORE (Byte,a,b,c)
                    104:       fun sw (a,b,c)  = keep STORE (Word,a,b,c)
                    105:       fun swc1 (a,b,c)  = delay STORE (Floating,a,b,c)
                    106:       val lui = keep LUI
                    107:     
                    108:       val sll = keep SLL                    (* shift *)
                    109:       val sra = keep SRA
                    110:     
                    111:       fun align() = ()                      (* never need to align on MIPS *)
                    112:       val mark = keep (fn () => MARK)
                    113:       val comment = keep COMMENT
                    114:   end
                    115: 
                    116:   open M
                    117: 
                    118:   fun get (SOME x) = x 
                    119:     | get NONE = ErrorMsg.impossible "missing pcptr in mipscoder"
                    120:   
                    121:   fun needs_a_pcptr(_,SLT(_,Immedlab _,_)) = true
                    122:     | needs_a_pcptr(_,ADD(_,Immedlab _,_)) = true
                    123:     | needs_a_pcptr(_,AND(_,Immedlab _,_)) = true
                    124:     | needs_a_pcptr(_,OR(_,Immedlab _,_)) = true
                    125:     | needs_a_pcptr(_,XOR(_,Immedlab _,_)) = true
                    126:     | needs_a_pcptr(_,MOVE(Immedlab _,_)) = true
                    127:     | needs_a_pcptr(_,LOAD(_,_,Immedlab _,_)) = true
                    128:     | needs_a_pcptr(_,STORE(_,_,Immedlab _,_)) = true
                    129:     | needs_a_pcptr(_,SLL(Immedlab _,_,_)) = true
                    130:     | needs_a_pcptr(_,SRA(Immedlab _,_,_)) = true
                    131:     | needs_a_pcptr(1, BEQ _) = false  (* small BEQ's dont need pcptr *)
                    132:     | needs_a_pcptr(_, BEQ _) = true   (* but large ones do *)
                    133:     | needs_a_pcptr(1, BCOP1 _) = false  (* small BCOP1's dont need pcptr *)
                    134:     | needs_a_pcptr(_, BCOP1 _) = true   (* but large ones do *)
                    135:     | needs_a_pcptr _ = false
                    136:   fun pass emitters =
                    137:   let fun makepcptr(i,x) = 
                    138:            (* may need to emit NOP for delay slot if next instr is branch *)
                    139:     let val size = case x of ((_,BEQ _)::rest) => 2 
                    140:                         | ((_,BCOP1 _)::rest) => 2 
                    141:                         | _ => 1
                    142:     in  case emitters of NONE                     => () 
                    143:                        | SOME (emit, _, _ ) => (
                    144:                              emit(Opcodes.bltzal(0,0));
                    145:                              if size=2 then emit(Opcodes.add(0,0,0)) else ());
                    146:         gen(i+size, SOME (i+2), x)
                    147:     end
                    148:   and gen(i,_,nil) = i
                    149:     | gen(i, _, (_,DEFINE lab) :: rest) = (lab := i; gen(i,NONE, rest))
                    150:                           (* invalidate the pc pointer at labels *)
                    151:     (* may want to do special fiddling with NOPs *)
                    152:     | gen(pos, pcptr, x as ((sizeref as ref size, inst) :: rest)) =
                    153:          if (pcptr=NONE andalso needs_a_pcptr(size, inst)) then makepcptr(pos,x)
                    154:          else case emitters of
                    155:             SOME (emit : int*int -> unit, emit_string : int -> string -> unit,
                    156:                emit_real : string -> unit) =>
                    157:                let fun gen1() = gen(pos+size,pcptr,rest) 
                    158:                                               (* generate the rest of the [[instr]]s *)
                    159:                   open Bits
                    160:                   open Opcodes
                    161:                   val tempreg = 1
                    162:                   val pcreg = 31
                    163:                   fun emitlong i = emit(rshift(i,16), andb(i,65535))
                    164:                                                   (* emit one long word (no sign fiddling) *)
                    165:                   fun split i = let val hi = rshift(i,16) and lo = andb(i,65535)
                    166:                                        in if lo<32768 then (hi,lo) else (hi+1, lo-65536)
                    167:                                       end
                    168:                   
                    169:                   fun arith (opr, rform, iform) =
                    170:                      let fun ar (Reg op1, Direct (Reg op2), Reg result) = 
                    171:                                   gen1(emit(rform(result,op1,op2)))
                    172:                            | ar (Reg op1, Immed op2, Reg result) =
                    173:                                   (case size of
                    174:                                       1 (* 16 bits *) => gen1(emit(iform(result,op1,op2)))
                    175:                                     | 3 (* 32 bits *) => 
                    176:                                        gen(pos,pcptr,
                    177:                                             (ref 2, LDI_32(op2, Reg tempreg))::
                    178:                                             (ref 1, opr(Reg op1, Direct(Reg tempreg), Reg result))::
                    179:                                             rest)
                    180:                                     | _ => gen(ErrorMsg.impossible 
                    181:                                                   "bad size in arith Immed in mipscoder")
                    182:                                   )
                    183:                            | ar (Reg op1, Immedlab (ref op2), Reg result) =
                    184:                                   gen(pos, pcptr, 
                    185:                                         (ref (size-1), 
                    186:                                               ADD(Reg pcreg,Immed(4*(op2-(get pcptr))), Reg tempreg))::
                    187:                                         (ref 1, opr(Reg op1, Direct(Reg tempreg), Reg result))::
                    188:                                         rest)
                    189:                      in  ar
                    190:                      end
                    191:                   fun float3double instruction (Reg op1,Reg op2,Reg result) =
                    192:                      gen1(emit(instruction(D_fmt,result,op1,op2)))
                    193:                   fun domove (Direct (Reg src), Reg dest) = gen1(emit(add(dest,src,0)))
                    194:                     | domove (Immed src, Reg dest) =
                    195:                           (case size of
                    196:                               1 (* 16 bits *) => gen1(emit(addi(dest,0,src)))
                    197:                             | 2 (* 32 bits *) => 
                    198:                                        gen(pos,pcptr,(ref 2, LDI_32(src, Reg dest))::rest)
                    199:                             | _ => gen(ErrorMsg.impossible "bad size in domove Immed in mipscoder")
                    200:                           )
                    201:                     | domove (Immedlab (ref src), Reg dest) =
                    202:                           gen(pos, pcptr, 
                    203:                                 (ref size, 
                    204:                                       ADD(Reg pcreg,Immed(4*(src-(get pcptr))), Reg dest))::rest)
                    205:                   fun memop(rform,Reg dest, Direct (Reg base), offset) =
                    206:                         (case size
                    207:                          of 1 => gen1(emit(rform(dest,offset,base)))
                    208:                           | 3 => let val (hi,lo) = split offset
                    209:                                  in  gen1(emit(lui(tempreg,hi));       (* tempreg = hi << 16 *)
                    210:                                           emit(add(tempreg,base,tempreg));(* tempreg += base *)
                    211:                                           emit(rform(dest,lo,tempreg)) (* load dest,lo(tempreg) *)
                    212:                                          )
                    213:                                  end
                    214:                           | _ => gen1(ErrorMsg.impossible "bad size in memop Direct in mipscoder")
                    215:                          )
                    216:                     | memop(rform,Reg dest, Immed address, offset) =
                    217:                         (case size
                    218:                          of 1 => gen1(emit(rform(dest,offset+address,0)))
                    219:                           | 2 => let val (hi,lo) = split (offset+address)
                    220:                                  in  gen1(emit(lui(tempreg,hi)); 
                    221:                                           emit(rform(dest,lo,tempreg))
                    222:                                          )
                    223:                                  end
                    224:                           | _ => gen1(ErrorMsg.impossible "bad size in memop Immed in mipscoder")
                    225:                          )
                    226:                     | memop(rform,Reg dest, Immedlab (ref lab), offset) =
                    227:                         memop(rform, Reg dest, Direct (Reg pcreg), offset+4*(lab - get pcptr))
                    228:               in  case inst of
                    229:                     STRINGCONST s => 
                    230:                           let val s' = s ^ "\000\000\000\000"
                    231:                           in  gen1(emit_string (4*size) s')
                    232:                                                         (* doesn't know Big vs Little-Endian *)
                    233:                           end
                    234:                   | REALCONST s => gen1(emit_real s)  (* floating pt constant *)
                    235:                   | EMITLONG i => gen1(emitlong i)
                    236:                   | DEFINE _ => gen1(ErrorMsg.impossible "generate code for DEFINE in mipscoder")
                    237:                   | EMITLAB(i, ref d) => gen1(emitlong((d-pos)*4+i))
                    238:                   | ADD stuff => arith (ADD,add,addi) stuff
                    239:                   | AND stuff => arith (AND,and',andi) stuff
                    240:                   | OR  stuff => arith (OR,or,ori) stuff
                    241:                   | XOR stuff => arith (XOR,xor,xori) stuff
                    242:                   | SUB (Reg op1, Reg op2, Reg result) => gen1(emit(sub(result,op1,op2)))
                    243:                   | MULDIV(DIV, Reg op1, Reg op2) => gen1(emit(div(op1,op2)))
                    244:                   | MULDIV(MULT,Reg op1, Reg op2) => gen1(emit(mult(op1,op2)))
                    245:                   | MFLO(Reg result) => gen1(emit(mflo(result)))
                    246:                   | MFHI(Reg result) => gen1(emit(mfhi(result)))
                    247:                   | NEG_D (Reg op1,Reg result) => gen1(emit(neg_fmt(D_fmt,result,op1)))
                    248:                   | MUL_D x => float3double mul_fmt x
                    249:                   | DIV_D x => float3double div_fmt x
                    250:                   | ADD_D x => float3double add_fmt x
                    251:                   | SUB_D x => float3double sub_fmt x
                    252:                   
                    253:                   
                    254:                   | MOVE stuff => domove stuff
                    255:                   | LDI_32 (immedconst, Reg dest) =>
                    256:                            let val (hi,lo) = split immedconst
                    257:                            in  gen1(emit(lui(dest,hi));emit(addi(dest,dest,lo)))
                    258:                            end 
                    259:                   | LUI (Reg dest,immed16) => gen1(emit(lui(dest,immed16)))
                    260:                   
                    261:                   | SLT stuff => arith (SLT,slt,slti) stuff
                    262:                   | BEQ(b, Reg op1, Reg op2, ref dest) =>
                    263:                       if size = 1 then 
                    264:                            gen1(emit((if b then beq else bne)(op1,op2,dest-(pos+1))))
                    265:                       else gen(pos,pcptr,
                    266:                                     (ref 1, BEQ(not b, Reg op1, Reg op2, ref(pos+size)))
                    267:                                     ::(ref (size-2), 
                    268:                                         ADD(Reg pcreg, Immed(4*(dest-(get pcptr))), Reg tempreg))
                    269:                                     ::(ref 1, JUMP(Reg tempreg))
                    270:                                     ::rest)
                    271:                   | JUMP(Reg dest) => gen1(emit(jr(dest)))
                    272:                   | SLT_D (Reg op1, Reg op2) => 
                    273:                        gen1(emit(c_lt(D_fmt,op1,op2)))
                    274:                   | SEQ_D (Reg op1, Reg op2) => 
                    275:                        gen1(emit(c_seq(D_fmt,op1,op2)))
                    276:                   | BCOP1(b, ref dest) =>
                    277:                       let fun bc1f offset = cop1(8,0,offset)
                    278:                        fun bc1t offset = cop1(8,1,offset)
                    279:                       in  if size = 1 then 
                    280:                                gen1(emit((if b then bc1t else bc1f)(dest-(pos+1))))
                    281:                           else gen(pos,pcptr,
                    282:                                     (ref 1, BCOP1(not b, ref(pos+size)))
                    283:                                     ::(ref (size-2), 
                    284:                                         ADD(Reg pcreg, Immed(4*(dest-(get pcptr))), Reg tempreg))
                    285:                                     ::(ref 1, JUMP(Reg tempreg))
                    286:                                     ::rest)
                    287:                       end
                    288:                   | NOP => gen1(emit(add(0,0,0)))         (* one of the many MIPS no-ops *)
                    289:                   | LOAD  (Byte,dest,address,offset) => memop(lbu,dest,address,offset)
                    290:                   | LOAD  (Word,dest,address,offset) => memop(lw,dest,address,offset)
                    291:                   | LOAD  (Floating,dest,address,offset) => memop(lwc1,dest,address,offset)
                    292:                   | STORE (Byte,dest,address,offset) => memop(sb,dest,address,offset)
                    293:                   | STORE (Word,dest,address,offset) => memop(sw,dest,address,offset)
                    294:                   | STORE (Floating,dest,address,offset) => memop(swc1,dest,address,offset)
                    295:                   | SLL (Immed shamt, Reg op1, Reg result) => gen1(
                    296:                           if (shamt >= 0 andalso shamt < 32) then emit(sll(result,op1,shamt))
                    297:                           else ErrorMsg.impossible ("bad sll shamt "
                    298:                                ^ (Integer.makestring shamt) ^ " in mipscoder"))
                    299:                   | SLL (Direct(Reg shamt), Reg op1, Reg result) => 
                    300:                           gen1(emit(sllv(result,op1,shamt)))
                    301:                   | SLL (Immedlab _,_,_) => ErrorMsg.impossible "sll shamt is Immedlab in mipscoder"
                    302:                   | SRA (Immed shamt, Reg op1, Reg result) => gen1(
                    303:                           if (shamt >= 0 andalso shamt < 32) then emit(sra(result,op1,shamt))
                    304:                           else ErrorMsg.impossible ("bad sra shamt "
                    305:                                ^ (Integer.makestring shamt) ^ " in mipscoder"))
                    306:                   | SRA (Direct(Reg shamt), Reg op1, Reg result) =>
                    307:                           gen1(emit(srav(result,op1,shamt)))
                    308:                   | SRA (Immedlab _,_,_) => ErrorMsg.impossible "sra shamt is Immedlab in mipscoder"
                    309:                   | COMMENT _ => gen1()
                    310:                   | MARK => gen1(
                    311:                       let open System.Tags
                    312:                       in  emitlong((pos+1) * power_tags + tag_backptr)
                    313:                       end)
                    314:               end
                    315:           | NONE =>
                    316:                let fun easize (Direct _) = 1
                    317:                     | easize (Immed i) = if abs(i)<32768 then 1 else 3
                    318:                     | easize (Immedlab(ref lab)) = 1 + easize(Immed (4*(lab-(get pcptr))))
                    319:                   fun movesize (Direct _) = 1
                    320:                     | movesize (Immed i) = if abs(i)<32768 then 1 else 2
                    321:                     | movesize (Immedlab(ref lab)) = easize(Immed (4*(lab-(get pcptr))))
                    322:                   
                    323:                   fun adrsize(_, Reg _, Direct _, offset) = 
                    324:                               if abs(offset)<32768 then 1 else 3
                    325:                     | adrsize(_, Reg _, Immed address, offset) = 
                    326:                               if abs(address+offset) < 32768 then 1 else 2
                    327:                     | adrsize(x, Reg dest, Immedlab (ref lab), offset) =
                    328:                               adrsize(x, Reg dest, Direct (Reg 0  (* pcreg in code *) ), 
                    329:                                       offset+4*(lab-(get pcptr)))
                    330:                   val newsize = case inst of
                    331:                         STRINGCONST s => Integer.div(String.length(s)+3,4)
                    332:                       | REALCONST _ => 2
                    333:                       | EMITLONG _ => 1
                    334:                       | DEFINE _ => ErrorMsg.impossible "generate code for DEFINE in mipscoder"
                    335:                       | EMITLAB _ => 1
                    336:                       | ADD(_, ea, _) => easize ea
                    337:                       | AND(_, ea, _) => easize ea
                    338:                       | OR (_, ea, _) => easize ea
                    339:                       | XOR(_, ea, _) => easize ea
                    340:                       | SUB _ => 1
                    341:                       | MULDIV _ => 1 
                    342:                       | MFLO _ => 1
                    343:                       | MFHI _ => 1
                    344:                       | NEG_D _ => 1
                    345:                       | MUL_D _ => 1
                    346:                       | DIV_D _ => 1
                    347:                       | ADD_D _ => 1
                    348:                       | SUB_D _ => 1
                    349:                       | MOVE (src,_) => movesize src
                    350:                       | LDI_32 _ => 2
                    351:                       | LUI _ => 1
                    352:                       | SLT(_, ea, _) => easize ea
                    353:                       | BEQ(_,_,_,ref dest) => 
                    354:                               if abs((pos+1)-dest) < 32768 then 1 (* single instruction *)
                    355:                               else 2+easize (Immed (4*(dest-(get pcptr))))
                    356:                       | JUMP _ => 1
                    357:                       | SLT_D _ => 1
                    358:                       | SEQ_D _ => 1
                    359:                       | BCOP1(_,ref dest) => 
                    360:                               if abs((pos+1)-dest) < 32768 then 1 (* single instruction *)
                    361:                               else 2+easize (Immed (4*(dest-(get pcptr))))
                    362:                       | NOP => 1
                    363:                       | LOAD  x => adrsize x
                    364:                       | STORE x => adrsize x
                    365:                       | SLL _ => 1  
                    366:                       | SRA _ => 1
                    367:                       | COMMENT _ => 0
                    368:                       | MARK => 1                     (* backpointer takes one word *)
                    369:               in  if newsize > size then sizeref := newsize else ();
                    370:                   gen(pos+(!sizeref) (* BUGS -- was pos+size*),pcptr,rest)
                    371:               end
                    372:   in  gen
                    373:   end
                    374:   
                    375:   fun prepare instrs =
                    376:    let fun add_positions(done, inst::rest) =  
                    377:                    add_positions( (ref 0, inst) :: done, rest)
                    378:          | add_positions(done, nil) = done
                    379:   
                    380:        val instrs' = add_positions(nil, instrs) (* reverse and add [[ref int]]s*)
                    381:   
                    382:        fun passes(oldsize) = 
                    383:                   (* make passes with no emission until size is stable*)
                    384:           let val size = pass NONE (0,NONE,instrs')
                    385:           in  if size=oldsize then size
                    386:               else passes size
                    387:           end
                    388:     in {size = passes 0, stream = instrs'}
                    389:     end
                    390:   
                    391:   fun assemble emitters instrs =
                    392:           pass (SOME emitters) (0,NONE,#stream (prepare instrs))
                    393:   
                    394:   
                    395:   fun codegen emitters = (
                    396:       assemble emitters (!kept);
                    397:         kept := nil
                    398:       )
                    399: 
                    400:   fun printstats stream
                    401:    {inst : int, code : int, data : int, 
                    402:     load : int, branch : int, compare : int, size : int} =
                    403:       let val print = output stream
                    404:        val nop = load+branch+compare
                    405:        val bltzal = size - (code + data)
                    406:        val code = code + bltzal
                    407:        val I = Integer.makestring
                    408:          val R = Real.makestring
                    409:          exception Printf
                    410:          fun sprintf format values =
                    411:              let fun merge([x],nil) = [x]
                    412:                    | merge(nil,nil) = nil
                    413:                    | merge(x::y,z::w) = x::z:: merge(y,w)
                    414:                    | merge _ = raise Printf
                    415:              in  implode(merge(format,values))
                    416:              end
                    417:   
                    418:        fun P x = substring(makestring(100.0 * x),0,4)  (* percent *)
                    419:        fun printf f d = print (sprintf f d)
                    420:       in  printf ["Counted "," instrs in "," words (",
                    421:                                " code, "," data)\n" ^
                    422:                "Used "," NOPs ("," load, "," branch,"," compare) and "," bltzals\n" ^
                    423:                "","% of code words were NOPs; ","% were bltzals\n" ^
                    424:                "","% of all words were code; ","% of all words were NOPs\n"]
                    425:               [I inst, I size, I code, I data, 
                    426:                   I nop, I load, I branch,  I compare, I bltzal,
                    427:                P (real nop / real code), P (real bltzal / real code),
                    428:                P (real code / real size), P (real nop / real size)]
                    429:        handle Overflow => print "[Overflow in computing Mips stats]\n"
                    430:             | Real s => print ("[FPE ("^s^") in computing Mips stats]\n")
                    431:       end
                    432:                
                    433:   val iscode = fn
                    434:       STRINGCONST _ => false
                    435:     | REALCONST _ => false
                    436:     | EMITLONG _ => false
                    437:     | DEFINE _ => false
                    438:     | EMITLAB _ => false
                    439:   
                    440:     | SLT _ => true
                    441:     | BEQ _ => true
                    442:     | JUMP _ => true
                    443:     | NOP => true
                    444:     | SLT_D _ => true
                    445:     | SEQ_D _ => true
                    446:     | BCOP1 _ => true
                    447:   
                    448:     | ADD _ => true
                    449:     | AND _ => true
                    450:     | OR  _ => true
                    451:     | XOR _ => true
                    452:     | SUB _ => true
                    453:     | MULDIV _ => true
                    454:     | MFLO _ => true
                    455:     | MFHI _ => true
                    456:   
                    457:     | NEG_D _ => true
                    458:     | MUL_D _ => true
                    459:     | DIV_D _ => true
                    460:     | ADD_D _ => true
                    461:     | SUB_D _ => true
                    462:   
                    463:     | MOVE _ => true
                    464:     | LDI_32 _ => true
                    465:     | LUI _ => true
                    466:   
                    467:     | LOAD _ => true
                    468:     | STORE  _ => true
                    469:   
                    470:     | SLL _ => true
                    471:     | SRA _ => true
                    472:   
                    473:     | COMMENT _ => false
                    474:     | MARK => false
                    475:   
                    476:   fun addstats (counts as {inst,code,data,load,branch,compare}) =
                    477:     fn nil => counts
                    478:      | (sizeref,first)::(_,NOP)::rest => addstats
                    479:             {inst=inst+2, code=code+(!sizeref)+1, data=data,
                    480:              load=load+ (case first of LOAD _ => 1 | _ => 0),
                    481:              branch=branch +(case first of BEQ _ => 1 | JUMP _ => 1 
                    482:                                       | BCOP1 _ => 1 | _ => 0),
                    483:           compare=compare+(case first of SLT_D _ => 1 | SEQ_D _ => 1 
                    484:                                        | _ => 0)
                    485:             } rest
                    486:      | (sizeref,first)::rest => addstats
                    487:             {inst=inst+1, 
                    488:              code = code + if iscode(first) then !sizeref else 0,
                    489:              data = data + if not (iscode first) then !sizeref else 0,
                    490:              load=load,
                    491:              branch=branch,
                    492:           compare=compare
                    493:             } rest
                    494:   
                    495:   
                    496:   fun codestats outfile =
                    497:       let val {size,stream=instrs} = prepare (!kept)
                    498:        val zero = {inst=0, code=0, data=0, load=0, branch=0, compare=0}
                    499:           val counts as {inst,code,data,load,branch,compare} = 
                    500:                                                addstats zero instrs
                    501:       in  printstats outfile 
                    502:            {inst=inst,code=code,data=data,
                    503:             load=load,branch=branch,compare=compare,size=size}
                    504:       end
                    505:        
                    506: 
                    507: end (* MipsInstr *)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.