|
|
1.1 ! root 1: (* Copyright 1989 by AT&T Bell Laboratories *) ! 2: functor CPSgen(M: CMACHINE) : ! 3: sig structure CPS : CPS ! 4: val codegen : (((CPS.lvar * CPS.lvar list * CPS.cexp) * bool) list ! 5: * (CPS.lvar -> CPS.const) ! 6: * (CPS.lvar -> bool)) ! 7: -> unit ! 8: end = ! 9: struct ! 10: ! 11: structure CPS = CPS ! 12: open CPS M System.Tags Access ! 13: ! 14: datatype frag = STANDARD of (lvar * lvar list * cexp) option ref ! 15: | KNOWN of (lvar list * cexp) * EA list option ref ! 16: | CONSTfrag of const ! 17: ! 18: val standardformals2 = [standardcont, standardarg] ! 19: val standardformals3 = [standardclosure,standardarg,standardcont] ! 20: val notastandardformal::_ = miscregs ! 21: val any = notastandardformal ! 22: ! 23: fun isreg' r = case isreg r of NONE => false | _ => true ! 24: ! 25: val maxConceivableRegs = 50 ! 26: val knowngen = System.Control.CG.knowngen ! 27: val stdgen = System.Control.CG.stdgen ! 28: ! 29: local ! 30: val allregs = standardformals3 @ miscregs ! 31: val num2reg = array(maxConceivableRegs, hd allregs) ! 32: val _ = app (fn r => case isreg r of SOME i => update(num2reg,i,r)) allregs ! 33: val allregs' = map (fn r => case isreg r of SOME i => i) allregs ! 34: val okreg = array(maxConceivableRegs, false) ! 35: fun mark b = (fn r => case isreg r of (SOME i) => update(okreg,i,b) | _ => ()) ! 36: val _ = app (mark true) allregs ! 37: ! 38: in ! 39: exception Getscratch ! 40: fun getscratch(preferred, prohibited) = ! 41: let fun f(x::a) = if okreg sub x then num2reg sub x else f a ! 42: | f nil = raise Getscratch ! 43: in app (mark false) prohibited; ! 44: (case isreg preferred ! 45: of SOME i => (if okreg sub i then preferred else f allregs') ! 46: | _ => f allregs') ! 47: before app (mark true) prohibited ! 48: handle e => (app (mark true) prohibited; raise e) ! 49: end ! 50: end ! 51: ! 52: fun split pred nil = (nil,nil) ! 53: | split pred (a::r) = let val (x,y) = split pred r ! 54: in if pred a then (a::x, y) else (x, a::y) ! 55: end ! 56: ! 57: fun codegen(funs : ((lvar * lvar list * cexp) * bool) list, ! 58: ctable : lvar -> const, isconstant : lvar -> bool) = ! 59: (* isconstant means either constant or label *) ! 60: let ! 61: exception Regbind ! 62: val regbindtable : EA Intmap.intmap = Intmap.new(32, Regbind) ! 63: val addbinding = Intmap.add regbindtable ! 64: ! 65: exception Know ! 66: val knowtable : frag Intmap.intmap = Intmap.new(32, Know) ! 67: val addknow = Intmap.add knowtable ! 68: val know = Intmap.map knowtable ! 69: ! 70: exception Freemap ! 71: val freemaptable : lvar list Intmap.intmap = Intmap.new(32, Freemap) ! 72: val freemap = Intmap.map freemaptable ! 73: ! 74: fun makefrag ((f,vl,e),known) = ! 75: (addknow(f, if known then (inc knowngen; KNOWN((vl,e),ref NONE)) ! 76: else (inc stdgen; STANDARD(ref(SOME(f,vl,e))))); ! 77: addbinding(f,newlabel()); ! 78: FreeMap.freemap isconstant (Intmap.add freemaptable) e; ! 79: f) ! 80: ! 81: val frags = ref(map makefrag funs) ! 82: fun addfrag f = frags := f :: !frags ! 83: ! 84: fun regbind v = ! 85: Intmap.map regbindtable v ! 86: handle Regbind => ! 87: (case ctable v of ! 88: INTconst i => (immed(i+i+1) handle Overflow => ! 89: ErrorMsg.impossible "Overflow in cps/generic.sml") ! 90: | f => let val lab = newlabel() ! 91: in addbinding(v,lab); addknow(v, CONSTfrag f); addfrag v; lab ! 92: end) ! 93: ! 94: fun root(RECORD(_,_,e)) = root e ! 95: | root(SELECT(_,_,_,e)) = root e ! 96: | root(OFFSET(_,_,_,e)) = root e ! 97: | root(SWITCH(_,e::_)) = root e ! 98: | root(PRIMOP(_,_,_,e::_)) = root e ! 99: | root(e as APP _) = e ! 100: ! 101: val root1 = ref(APP(0,[])) ! 102: ! 103: fun alloc(v,cexp,default,continue) = ! 104: let val APP(f,wl) = !root1 ! 105: val proh = map regbind (freemap v) ! 106: fun delete (z,nil) = nil ! 107: | delete (z, a::r) = if eqreg a z then r else a::delete(z,r) ! 108: fun get(good,bad) = ! 109: let val r = getscratch(good,bad@proh) ! 110: handle Getscratch => getscratch(default,proh) ! 111: in addbinding(v,r); continue r ! 112: end ! 113: fun find fmls = ! 114: let fun g(w::wl, r::rl) = if w=v then get(r, delete(r,fmls)) ! 115: else g(wl,rl) ! 116: | g(nil,nil) = get(default, fmls) ! 117: | g _ = ErrorMsg.impossible "cps vax 33" ! 118: in g(wl,fmls) ! 119: end ! 120: in if v=f then get(default,standardformals3) ! 121: else ! 122: case (know f handle Know => STANDARD(ref NONE)) ! 123: of KNOWN(_,ref(SOME fmls)) => find fmls ! 124: | KNOWN(_,ref NONE) => get(default,nil) ! 125: | STANDARD _ => case length wl ! 126: of 2 => find standardformals2 ! 127: | 3 => find standardformals3 ! 128: | _ => ErrorMsg.impossible "cps vax 44" ! 129: end ! 130: ! 131: fun shuffle(func, args,formals) = ! 132: let val (fv,used,args,formals) = ! 133: let val fv = regbind func ! 134: in if exists (eqreg fv) formals ! 135: then let val x = getscratch(any, args@formals) ! 136: in move(fv,x); addbinding(func,x); ! 137: (x,[x],args,formals) ! 138: end ! 139: handle Getscratch => ! 140: (addbinding(func,notastandardformal); ! 141: (notastandardformal, nil, fv::args, notastandardformal::formals)) ! 142: else (fv,[fv],args,formals) ! 143: end ! 144: fun mate(a::al, b::bl)= (a,b)::mate(al,bl) ! 145: | mate _ = nil ! 146: val (inreg,notinreg) = split (isreg' o #1) (mate(args,formals)) ! 147: val (matched, notmatched) = split (fn(x,y)=>eqreg x y) inreg ! 148: ! 149: fun f(nil, used) = () ! 150: | f (pairs,used) = ! 151: let val u' = map #1 pairs @ used ! 152: fun movable (a, b) = not (exists (eqreg b) u') ! 153: in case split movable pairs ! 154: of (nil,(a,b)::r) => ! 155: let val x = getscratch(any,u') ! 156: in move(a,x); f((x,b)::r, used) ! 157: end ! 158: | (m,m') => (app move m; f(m', (map #2 m) @ used)) ! 159: end ! 160: in f(notmatched, (map #1 matched) @ used); ! 161: app move notinreg; ! 162: jmp fv ! 163: end ! 164: ! 165: fun allocparams(args,formals) = ! 166: let fun f(already,a::ar,b::br) = ! 167: let val z = getscratch(a, already@ar) ! 168: in addbinding(b,z); ! 169: if eqreg a z then () else move(a,z); ! 170: f(z::already,ar,br) ! 171: end ! 172: | f(l,nil,nil) = rev l ! 173: in f(nil,args,formals) ! 174: end ! 175: ! 176: (* Compute the maximum amount of allocation done by this function (in bytes). *) ! 177: fun sumAlloc exp = let ! 178: fun sum (RECORD (fields, _, exp'), max) = sum (exp', max+(length fields)+1) ! 179: | sum (SELECT (_, _, _, exp'), max) = sum (exp', max) ! 180: | sum (OFFSET (_, _, _, exp'), max) = sum (exp', max) ! 181: | sum (APP _, max) = max ! 182: | sum (SWITCH (_, lst), max) = max + lstMax(lst, 0) ! 183: | sum (PRIMOP (P.makeref, _, _, [exp']), max) = sum (exp', max+2) ! 184: | sum (PRIMOP (P.delay, _, _, [exp']), max) = sum (exp', max+2) ! 185: | sum (PRIMOP (P.update, _, _, [exp']), max) = sum (exp', max+4) ! 186: | sum (PRIMOP (P.:=, _, _, [exp']), max) = sum (exp', max+4) ! 187: | sum (PRIMOP (P.fadd, _, _, [exp']), max) = sum (exp', max+3) ! 188: | sum (PRIMOP (P.fsub, _, _, [exp']), max) = sum (exp', max+3) ! 189: | sum (PRIMOP (P.fmul, _, _, [exp']), max) = sum (exp', max+3) ! 190: | sum (PRIMOP (P.fdiv, _, _, [exp']), max) = sum (exp', max+3) ! 191: | sum (PRIMOP (P.fneg, _, _, [exp']), max) = sum (exp', max+3) ! 192: | sum (PRIMOP (_, _, _, [exp']), max) = sum (exp', max) ! 193: | sum (PRIMOP (_, _, _, lst), max) = max + lstMax(lst, 0) ! 194: and lstMax (nil, max) = max ! 195: |lstMax (e::rest, max) = let val m = sum (e, 0) ! 196: in ! 197: if m > max then lstMax(rest, m) else lstMax(rest, max) ! 198: end ! 199: in ! 200: (sum (exp, 0)) * 4 ! 201: end ! 202: ! 203: fun genfrag f = case (regbind f, know f) ! 204: of (_, STANDARD(ref NONE)) => () ! 205: | (lab, STANDARD(r as ref (SOME(fname,[f,a,c],e)))) => ! 206: (r := NONE; ! 207: List2.app2 addbinding ([f,a,c],standardformals3); ! 208: align(); mark(); ! 209: comment(Access.lvarName fname ^ ":\n"); ! 210: genFun(lab, e, SOME standardclosure)) ! 211: | (lab, STANDARD(r as ref (SOME(fname,[f,a],e)))) => ! 212: (r := NONE; ! 213: List2.app2 addbinding ([f,a],standardformals2); ! 214: align(); mark(); ! 215: comment(Access.lvarName fname ^ ":\n"); ! 216: genFun(lab, e, SOME standardcont)) ! 217: | (_, STANDARD _) => ErrorMsg.impossible "standard with wrong args" ! 218: | (_, KNOWN _) => () ! 219: | (lab, CONSTfrag(REALconst r)) => ! 220: (align(); mark(); emitlong(8 * power_tags + tag_embedded); ! 221: define lab; comment("# real constant " ^ r ^ "\n"); ! 222: realconst r) ! 223: | (lab, CONSTfrag(STRINGconst s)) => ! 224: (align(); mark(); ! 225: emitlong(size s * power_tags + tag_embedded); ! 226: define lab; emitstring s; align()) ! 227: ! 228: (* generate a new code label *) ! 229: and genlab(lab, cexp) = (root1 := root cexp; define lab; gen cexp) ! 230: ! 231: (* generate a new function header *) ! 232: and genFun (lab, cexp, closure) = let ! 233: val maxAllocSz = sumAlloc cexp ! 234: in ! 235: root1 := root cexp; ! 236: define lab; ! 237: if (maxAllocSz > 0) (** Won't support "true" concurrency **) ! 238: then checkLimit (maxAllocSz) else (); ! 239: case closure of SOME reg => beginStdFn(reg, lab) | _ => (); ! 240: gen cexp ! 241: end ! 242: ! 243: and gen cexp = ! 244: case cexp ! 245: of RECORD(vl,w,e) => ! 246: alloc(w, e,any, fn w' => ! 247: (record((immed(16*(length vl)+1),OFFp 0) :: ! 248: map (fn(x,p)=>(regbind x, p)) vl, ! 249: w'); ! 250: gen e)) ! 251: | SELECT(i,v,w,e) => ! 252: alloc(w, e,any, fn w' => (select(i,regbind v,w'); gen e)) ! 253: | OFFSET(i,v,w,e) => ! 254: let val v' = regbind v ! 255: in alloc(w, e,v', fn w' => (offset(i,v',w'); gen e)) ! 256: end ! 257: | APP(f,args) => ! 258: (case (map regbind args, ! 259: know f handle Know => STANDARD(ref NONE)) ! 260: of (args',KNOWN(_,ref(SOME formals))) => ! 261: shuffle(f, args', formals) ! 262: | (args', KNOWN((vl,cexp), r as ref(NONE))) => let ! 263: val lab = newlabel(); ! 264: in ! 265: r := SOME(allocparams(args',vl)); ! 266: (* replace fall-through with a jump to insure a mark ! 267: * at the beginning of every function. ! 268: *) ! 269: jmp lab; align(); mark(); define lab; ! 270: comment(Access.lvarName f ^ ":\n"); ! 271: genFun (regbind f, cexp, NONE) ! 272: end ! 273: | (args' as [_,_], STANDARD (ref NONE)) => ! 274: shuffle(f, args',standardformals2) ! 275: | (args' as [_,_,_], STANDARD (ref NONE)) => ! 276: shuffle(f, args',standardformals3) ! 277: | (args' as [_,_], STANDARD(ref(SOME _))) => ! 278: (shuffle(f, args',standardformals2); genfrag f) ! 279: | (args' as [_,_,_], STANDARD(ref(SOME _))) => ! 280: (shuffle(f, args',standardformals3); genfrag f)) ! 281: | SWITCH(v,l) => ! 282: let val lab = newlabel() ! 283: val labs = map (fn _ => newlabel()) l; ! 284: fun f(i, s::r) = (emitlab(i, s); f(i+4, r)) ! 285: | f(_, nil) = () ! 286: fun h(lab::labs, e::es) = (genlab(lab, e); h(labs,es)) ! 287: | h(nil,nil) = () ! 288: in fetchindexl(lab, arithtemp, regbind v); ! 289: jmpindexb lab; ! 290: (* align(); temporarily removed so 68020 will work. *) ! 291: define lab; ! 292: f (0, labs); ! 293: h(labs,l) ! 294: end ! 295: ! 296: | PRIMOP (i,vl,wl,el) => primops i (vl,wl,el) ! 297: ! 298: (* warning: on three-address instructions, be careful about ! 299: non-pointers in registers. On some machines, ! 300: addl3(a,b,c) is translated to: mov(b,c); add(a,c); ! 301: and it's dangerous when b is a non-pointer. In such a case, ! 302: usually a is "safe", so that addl3(b,a,c) works better. ! 303: The rule is, therefore: if the destination is a pointer register, ! 304: then b must also be a tagged value *) ! 305: ! 306: and arithprof i = () (* profile(Profile.ARITHOVH+i,2) *) ! 307: and compare(branch,test) ([v,w],[],[d,e]) = ! 308: let val lab = newlabel() ! 309: in branch(test,regbind v, regbind w, lab); ! 310: gen d; genlab(lab, e) ! 311: end ! 312: and primops p = ! 313: case p of ! 314: P.+ => (fn ([v,w],[x],[e]) => ! 315: let val v' = regbind v and w' = regbind w ! 316: in case (isimmed v', isimmed w') of ! 317: (SOME k, _) => ! 318: (arithprof 0; alloc(x,e,w', fn x' => addl3t(immed(k-1),w',x'))) ! 319: (* the next case must be done (by all machines) with v and x in ! 320: root registers (for offset computations in "boot") *) ! 321: | (_, SOME k) => ! 322: (arithprof 0; alloc(x,e,v', fn x' => addl3t(immed(k-1),v',x'))) ! 323: | _ => alloc(x,e,w',fn x' => (arithprof 1; ! 324: subl3(immed 1,v',arithtemp); ! 325: addl3t(arithtemp, w', x'))); ! 326: gen e ! 327: end) ! 328: | P.orb => (fn ([v,w],[x],[e]) => ! 329: let val w' = regbind w ! 330: in alloc(x,e,w', fn x' => (orb(regbind v, w', x'); gen e)) ! 331: end) ! 332: | P.andb => (fn ([v,w],[x],[e]) => ! 333: let val w' = regbind w ! 334: in alloc(x,e,w', fn x' => (andb(regbind v, w', x'); gen e)) ! 335: end) ! 336: | P.xorb => (fn ([v,w],[x],[e]) => ! 337: let val v' = regbind v and w' = regbind w ! 338: in alloc(x,e,any,fn x' => (case (isimmed v', isimmed w') of ! 339: (SOME k,_) => xorb(immed(k-1), w', arithtemp) ! 340: | (_,SOME k) => xorb(v', immed(k-1), arithtemp) ! 341: | _ => (xorb(v', w', arithtemp); orb(immed 1, arithtemp, x')); ! 342: gen e)) ! 343: end) ! 344: | P.notb => (fn ([v],[x],[e]) => ! 345: alloc(x,e,regbind v, fn x' => ! 346: (notb(regbind v, x'); ! 347: orb(immed 1, x', x'); ! 348: gen e))) ! 349: | P.lshift => (fn ([v,w],[x],[e]) => ! 350: let val v' = regbind v and w' = regbind w ! 351: in alloc(x,e,any, fn x' => ! 352: (case (isimmed v', isimmed w') of ! 353: (SOME k,_) => ! 354: (ashr(immed 1,w',arithtemp); ashl(arithtemp,immed(k-1), x')) ! 355: | (_,SOME k) => ! 356: (addl3(immed(~1),v',arithtemp); ! 357: ashl(immed(Bits.rshift(k,1)), arithtemp, x')) ! 358: | _ => ! 359: (ashr(immed 1, w',arithtemp); ! 360: addl3(immed(~1),v',arithtemp2); ! 361: ashl(arithtemp, arithtemp2, x')); ! 362: orb(immed 1, x', x'); ! 363: gen e)) ! 364: end) ! 365: | P.rshift => (fn ([v,w],[x],[e]) => ! 366: let val v' = regbind v and w' = regbind w ! 367: in alloc(x,e,v', fn x' => ! 368: (case isimmed w' of ! 369: SOME k => ashr(immed(Bits.rshift(k,1)), v', x') ! 370: | _ => (ashr(immed 1, w',arithtemp); ashr(arithtemp, v', x')); ! 371: orb(immed 1, x', x'); ! 372: gen e)) ! 373: end) ! 374: | P.- => (fn ([v,w],[x],[e]) => ! 375: let val v' = regbind v and w' = regbind w ! 376: in case (isimmed v', isimmed w') of ! 377: (SOME k, _) => (arithprof 0; alloc(x,e,w', fn x' => ! 378: subl3t(w', immed(k+1), x'))) ! 379: | (_, SOME k) => (arithprof 0; alloc(x,e,v', fn x' => ! 380: subl3t(immed(k-1),v',x'))) ! 381: | _ => alloc(x, e,v',fn x' => (arithprof 1; ! 382: subl3(immed 1,w',arithtemp); ! 383: subl3t(arithtemp, v', x'))); ! 384: gen e ! 385: end) ! 386: | P.* => (fn ([v,w],[x],[e]) => ! 387: let val v' = regbind v and w' = regbind w ! 388: in alloc(x,e,any,fn x' => ! 389: (arithprof 3; ! 390: case (isimmed v', isimmed w') of ! 391: (SOME k,_) => (ashr(immed 1, w', arithtemp); ! 392: mull2t(immed(k-1),arithtemp)) ! 393: | (_,SOME k) => (ashr(immed 1, v', arithtemp); ! 394: mull2t(immed(k-1),arithtemp)) ! 395: | _ => (ashr(immed 1, v', arithtemp); ! 396: subl3(immed 1, w', arithtemp2); ! 397: mull2t(arithtemp2,arithtemp)); ! 398: orb(immed 1,arithtemp,x'); ! 399: gen e)) ! 400: end) ! 401: | P.div => (fn ([v,w],[x],[e]) => ! 402: let val v' = regbind v and w' = regbind w ! 403: in alloc(x, e,any, fn x' => ! 404: (arithprof 4; ! 405: case (isimmed v', isimmed w') of ! 406: (SOME k,_) => ! 407: (move(immed(Bits.rshift(k,1)),arithtemp); ! 408: ashr(immed 1, w', arithtemp2); ! 409: divl2(arithtemp2,arithtemp)) ! 410: | (_,SOME k) => ! 411: (ashr(immed 1, v', arithtemp); ! 412: divl2(immed(Bits.rshift(k,1)),arithtemp)) ! 413: | _ => ! 414: (ashr(immed 1, v', arithtemp); ! 415: ashr(immed 1, w', arithtemp2); ! 416: divl2(arithtemp2,arithtemp)); ! 417: addl3(arithtemp, arithtemp, arithtemp); ! 418: orb(immed 1, arithtemp,x'); ! 419: gen e)) ! 420: end) ! 421: | P.! => (fn ([v],[w],[e]) => gen(SELECT(0,v,w,e))) ! 422: | P.:= => (fn ([v,w],[],[e]) => ! 423: let val v' = regbind v ! 424: in record([(immed(16*3+1),OFFp 0), (v', OFFp 0), ! 425: (immed 1, OFFp 0), (storeptr, OFFp 0)], storeptr); ! 426: storeindexl(regbind w, v', immed 1); ! 427: gen e ! 428: end) ! 429: | P.unboxedassign => (fn ([v,w],[],[e]) => ! 430: (storeindexl(regbind w, regbind v, immed 1); gen e)) ! 431: | P.~ => (fn ([v],[w],[e]) => ! 432: alloc(w,e,any,fn w' => (arithprof 0;subl3t(regbind v,immed 2,w');gen e))) ! 433: | P.makeref => ! 434: (fn ([v],[w],[e]) => ! 435: alloc(w, e,any, fn w' => ! 436: (if !CGoptions.profile then profile(Profile.REFCELLS,2) else (); ! 437: record([(immed(power_tags+tag_array),OFFp 0), ! 438: (regbind v, OFFp 0)], w'); ! 439: gen e))) ! 440: | P.delay => ! 441: (fn ([i,v],[w],[e]) => ! 442: alloc(w, e,any, fn w' => ! 443: (if !CGoptions.profile then profile(Profile.REFCELLS,2) else (); ! 444: record([(regbind i, OFFp 0),(regbind v, OFFp 0)], w'); ! 445: gen e))) ! 446: | P.ieql => compare(ibranch,NEQ) ! 447: | P.ineq => compare(ibranch,EQL) ! 448: | P.> => compare(ibranch,LEQ) ! 449: | P.>= => compare(ibranch,LSS) ! 450: | P.< => compare(ibranch,GEQ) ! 451: | P.<= => compare(ibranch,GTR) ! 452: | P.subscript => (fn ([v,w],[x],[e]) => ! 453: alloc(x, e,any, fn x' => ! 454: (arithprof 1; ! 455: fetchindexl(regbind v, x', regbind w); ! 456: gen e))) ! 457: | P.update => (fn ([a, i, v], [], [e]) => ! 458: let val a' = regbind a and i' = regbind i ! 459: in arithprof 1; ! 460: record([(immed(16*3+1),OFFp 0), (a',OFFp 0), ! 461: (i', OFFp 0), (storeptr, OFFp 0)], storeptr); ! 462: storeindexl(regbind v, a', i'); ! 463: gen e ! 464: end) ! 465: | P.unboxedupdate => (fn ([a, i, v], [], [e]) => ! 466: (arithprof 1; ! 467: storeindexl(regbind v, regbind a, regbind i); ! 468: gen e)) ! 469: | P.alength => (fn ([a], [w], [e]) => ! 470: alloc(w, e,any, fn w' => ! 471: (arithprof 1; ! 472: select(~1, regbind a, arithtemp); ! 473: ashr(immed(width_tags-1),arithtemp, arithtemp); ! 474: (* orb(immed 1, arithtemp, w'); ! 475: this didn't work on the mc68020, dammit! *) ! 476: orb(immed 1, arithtemp, arithtemp); ! 477: move(arithtemp,w'); ! 478: gen e))) ! 479: | P.slength => (fn ([a], [w], [e]) => ! 480: alloc(w, e,any, fn w' => ! 481: let val a' = regbind a ! 482: in if isreg' a' ! 483: then select(~1,a',arithtemp) ! 484: else (move(a',w'); select(~1,w',arithtemp)); ! 485: ashr(immed(width_tags-1), arithtemp, arithtemp); ! 486: (* orb(immed 1, arithtemp, w'); ! 487: this didn't work on the mc68020, dammit! *) ! 488: arithprof 1; ! 489: orb(immed 1, arithtemp, arithtemp); ! 490: move(arithtemp,w'); ! 491: gen e ! 492: end)) ! 493: | P.store => (fn ([s,i,v], [], [e]) => ! 494: (arithprof 2; ! 495: ashr(immed 1, regbind i, arithtemp); ! 496: ashr(immed 1, regbind v, arithtemp2); ! 497: storeindexb(arithtemp2, regbind s); ! 498: gen e)) ! 499: | P.ordof => (fn ([s,i], [v], [e]) => ! 500: alloc(v, e,any, fn v' => ! 501: let val s' = regbind s ! 502: in arithprof 3; ! 503: ashr(immed 1, regbind i, arithtemp); ! 504: if isreg' s' then fetchindexb(s', arithtemp2) ! 505: else (move(s',v'); fetchindexb(v',arithtemp2)); ! 506: addl3(arithtemp2,arithtemp2,arithtemp2); ! 507: orb(immed 1, arithtemp2, v'); ! 508: gen e ! 509: end)) ! 510: | P.fneg => (fn ([x], [y], [e]) => ! 511: alloc(y, e,any, fn y' => (mnegg(regbind x, y'); gen e))) ! 512: | P.profile => (fn ([index,incr],[],[c]) => ! 513: (case (isimmed(regbind index), isimmed(regbind incr)) ! 514: of (SOME i, SOME v) => profile(i div 2,(v div 2)*2); ! 515: gen c)) ! 516: | P.boxed => (fn ([x],[],[a,b]) => ! 517: let val lab = newlabel() ! 518: in bbs(immed 0, regbind x, lab); gen a; genlab(lab, b) ! 519: end) ! 520: | P.gethdlr => (fn ([],[x],[e]) => ! 521: alloc(x, e,any, fn x' => (move(exnptr,x'); gen e))) ! 522: | P.sethdlr => (fn ([x],[],[e]) => (move(regbind x, exnptr); gen e)) ! 523: | P.fmul => (fn ([x,y], [z], [e]) => ! 524: alloc(z, e,any, fn z' => ! 525: (mulg3(regbind x, regbind y, z'); gen e))) ! 526: | P.fdiv => (fn ([x,y], [z], [e]) => ! 527: alloc(z, e,any, fn z' => ! 528: (divg3(regbind x, regbind y, z'); gen e))) ! 529: | P.fadd => (fn ([x,y], [z], [e]) => ! 530: alloc(z, e,any, fn z' => ! 531: (addg3(regbind x, regbind y, z'); gen e))) ! 532: | P.fsub => (fn ([x,y], [z], [e]) => ! 533: alloc(z, e,any, fn z' => ! 534: (subg3(regbind x, regbind y, z'); gen e))) ! 535: | P.feql => compare(gbranch,NEQ) ! 536: | P.fneq => compare(gbranch,EQL) ! 537: | P.fgt => compare(gbranch,LEQ) ! 538: | P.flt => compare(gbranch,GEQ) ! 539: | P.fge => compare(gbranch,LSS) ! 540: | P.fle => compare(gbranch,GTR) ! 541: ! 542: in emitlong 1; (* Bogus tag for spacing, boot_v. *) ! 543: let fun loop nil = () ! 544: | loop (frag::r) = (frags := r; genfrag frag; loop(!frags)) ! 545: in loop(!frags) ! 546: end ! 547: (* before print "Done!\n" *) ! 548: end ! 549: ! 550: end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.