|
|
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 *)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.