|
|
1.1 ! root 1: (* Copyright 1989 by AT&T Bell Laboratories *) ! 2: (* sparc.sml ! 3: * ! 4: * J.H. Reppy ! 5: * Cornell University ! 6: * Ithaca, NY 14853 ! 7: * [email protected] ! 8: * ! 9: * HISTORY: ! 10: * 11/20/89 created ! 11: *) ! 12: ! 13: functor SparcCM ( ! 14: structure C : CODER ! 15: sharing type C.instruction = SparcInstr.instruction ! 16: and type C.sdi = SparcInstr.sdi ! 17: and type C.label = SparcInstr.label) : CMACHINE = ! 18: struct ! 19: ! 20: structure C' : sig ! 21: eqtype label ! 22: val newLabel : unit -> label ! 23: val emitLong : int -> unit ! 24: val emitString : string -> unit ! 25: val emitReal : string -> unit ! 26: val emitLabel : (label * int) -> unit ! 27: val mark : unit -> unit ! 28: val comment : string -> unit ! 29: end = C ! 30: open C' ! 31: ! 32: structure S' : sig ! 33: eqtype label ! 34: datatype register = REG of int ! 35: datatype fregister = FREG of int ! 36: datatype labelexp ! 37: = LABELexp of { (* An offset relative to a label. The value of a *) ! 38: base : label, (* label expression is ((dst - base) + offset). *) ! 39: dst : label, ! 40: offset : int ! 41: } ! 42: datatype operand ! 43: = REGrand of register (* A register value *) ! 44: | IMrand of int (* A small integer constant (13 bits) *) ! 45: | LABrand of labelexp (* A small valued label expression (13 bits) *) ! 46: | HIrand of labelexp (* The high 22 bits of a label expression *) ! 47: | LOrand of labelexp (* The low 10 bits of a label expression *) ! 48: datatype condition = EQL | NEQ | GTR | GEQ | LSS | LEQ ! 49: end = SparcInstr ! 50: open S' ! 51: ! 52: val zeroR = REG 0 (* %g0 *) ! 53: val zeroRand = REGrand zeroR ! 54: ! 55: local ! 56: ! 57: fun emit_ld args = C.emit (SparcInstr.I_ld args) ! 58: fun emit_ldb args = C.emit (SparcInstr.I_ldb args) ! 59: fun emit_ldf args = C.emit (SparcInstr.I_ldf args) ! 60: fun emit_st args = C.emit (SparcInstr.I_st args) ! 61: fun emit_stb args = C.emit (SparcInstr.I_stb args) ! 62: fun emit_stf args = C.emit (SparcInstr.I_stf args) ! 63: fun emit_sethi args = C.emit (SparcInstr.I_sethi args) ! 64: fun emit_ba args = C.delay (SparcInstr.I_ba args) ! 65: fun emit_bcc args = C.delay (SparcInstr.I_bcc args) ! 66: fun emit_fbcc args = C.delay (SparcInstr.I_fbcc args) ! 67: fun emit_jmpl args = C.delay (SparcInstr.I_jmpl args) ! 68: fun emit_jmp (r, offset) = C.delay (SparcInstr.I_jmpl(r, offset, zeroR)) ! 69: fun emit_add args = C.emit (SparcInstr.I_add args) ! 70: fun emit_addcc args = C.emit (SparcInstr.I_addcc args) ! 71: fun emit_taddcctv args = C.emit (SparcInstr.I_taddcctv args) ! 72: fun emit_sub args = C.emit (SparcInstr.I_sub args) ! 73: fun emit_subcc args = C.emit (SparcInstr.I_subcc args) ! 74: fun emit_sra args = C.emit (SparcInstr.I_sra args) ! 75: fun emit_sll args = C.emit (SparcInstr.I_sll args) ! 76: fun emit_and args = C.emit (SparcInstr.I_and args) ! 77: fun emit_andcc args = C.emit (SparcInstr.I_andcc args) ! 78: fun emit_or args = C.emit (SparcInstr.I_or args) ! 79: fun emit_xor args = C.emit (SparcInstr.I_xor args) ! 80: fun emit_not args = C.emit (SparcInstr.I_not args) ! 81: fun emit_tvs () = C.emit SparcInstr.I_tvs ! 82: fun emit_fadd args = C.emit (SparcInstr.I_fadd args) ! 83: fun emit_fsub args = C.emit (SparcInstr.I_fsub args) ! 84: fun emit_fmul args = C.emit (SparcInstr.I_fmul args) ! 85: fun emit_fdiv args = C.emit (SparcInstr.I_fdiv args) ! 86: fun emit_fneg args = C.emit (SparcInstr.I_fneg args) ! 87: fun emit_fcmp args = C.delay (SparcInstr.I_fcmp args) ! 88: ! 89: local ! 90: fun mkLabExp (lab, n) = LABELexp{base= C.baseLab, dst= lab, offset= (n-4096)} ! 91: in ! 92: ! 93: fun setBaseAddr (contReg, lab, tmpR) = C.emitSDI ( ! 94: SparcInstr.SetBaseAddr(ref true, contReg, mkLabExp(lab, 0), tmpR)) ! 95: ! 96: fun loadAddr (lab, n, dst, tmpR) = C.emitSDI ( ! 97: SparcInstr.LoadAddr(mkLabExp(lab, n), dst, tmpR)) ! 98: ! 99: fun load (lab, n, dst, tmpR) = C.emitSDI ( ! 100: SparcInstr.Load(mkLabExp(lab, n), dst, tmpR)) ! 101: ! 102: fun loadF (lab, n, dst, tmpR) = C.emitSDI ( ! 103: SparcInstr.LoadF(mkLabExp(lab, n), dst, tmpR)) ! 104: ! 105: end (* local *) ! 106: ! 107: in ! 108: ! 109: datatype EA ! 110: = Immed of int ! 111: | ImmedLab of label ! 112: | Direct of register ! 113: ! 114: val immed = Immed ! 115: fun isimmed (Immed n) = SOME n | isimmed _ = NONE ! 116: fun isreg (Direct(REG i)) = SOME i | isreg _ = NONE ! 117: fun eqreg (a : EA) b = (a = b) ! 118: ! 119: (** Dedicated registers **) ! 120: val exnptr = Direct(REG 7) (* %g7 *) ! 121: val storeptr = Direct(REG 5) (* %g5 *) ! 122: val arithtemp = Direct(REG 8) (* %o0 *) ! 123: val arithtemp2 = Direct(REG 9) (* %o1 *) ! 124: val standardclosure = Direct(REG 26) (* %i2 *) ! 125: val standardarg = Direct(REG 24) (* %i0 *) ! 126: val standardcont = Direct(REG 25) (* %i1 *) ! 127: val miscregs = map (Direct o REG) [ (* %g1-%g3, %l0-%l7, %i4-%i5 *) ! 128: 1, 2, 3, 16, 17, 18, 19, 20, 21, 22, 23, 28, 29 ! 129: ] ! 130: ! 131: val dataptrR = REG 6 (* %g6 *) ! 132: val limitptrR = REG 4 (* %g4 *) ! 133: val limitptrRand = REGrand limitptrR ! 134: val arithtempRand = REGrand(REG 8) ! 135: val spR = REG 14 (* %sp (%o6) *) ! 136: val linkR = REG 15 (* %o7, link register *) ! 137: ! 138: (** Temporary registers ** ! 139: * We use registers %o2-%o5 as temporaries. They are used in a round-robin ! 140: * order to facilitate instruction scheduling. ! 141: *) ! 142: local ! 143: val rear = ref 0 and queue = ref 0 ! 144: fun ins i = let ! 145: val r = !rear ! 146: in ! 147: queue := Bits.orb(Bits.lshift(i, r), !queue); ! 148: rear := r + 5 ! 149: end ! 150: fun remove () = let ! 151: val q = !queue ! 152: val x = Bits.andb (q, 31) ! 153: in ! 154: queue := Bits.rshift (q, 5); ! 155: rear := !rear - 5; ! 156: x ! 157: end ! 158: val _ = app ins [10, 11, 12, 13] (* %o2-%o5 *) ! 159: in ! 160: ! 161: (* Registers %o2, %o3 & %o4 are also used to call ml_mul and ml_div. *) ! 162: val arg1EA = Direct(REG 10) and arg2EA = Direct(REG 11) ! 163: val opAddrR = REG 12 ! 164: ! 165: (* Get a temporary register. *) ! 166: fun getTmpReg () = REG(remove()) ! 167: ! 168: (* If r is a temporary register, then free it. *) ! 169: fun freeReg (REG r) = if ((9 < r) andalso (r < 14)) then (ins r) else () ! 170: ! 171: (* Free a temporary register. *) ! 172: fun freeTmpReg (REG r) = ins r ! 173: ! 174: end (* local *) ! 175: ! 176: ! 177: (* align is a nop, since strings are automatically padded. *) ! 178: fun align () = () ! 179: ! 180: val mark = mark ! 181: ! 182: val emitlong = emitLong ! 183: val realconst = emitReal ! 184: val emitstring = emitString ! 185: ! 186: fun emitlab (n, ImmedLab lab) = emitLabel (lab, n) ! 187: | emitlab _ = ErrorMsg.impossible "[SparcCM.emitlab]" ! 188: ! 189: val newlabel = ImmedLab o newLabel ! 190: fun define (ImmedLab lab) = C.define lab ! 191: | define _ = ErrorMsg.impossible "[SparcCM.define]" ! 192: ! 193: datatype immed_size = Immed13 | Immed32 ! 194: ! 195: fun sizeImmed n = if (~4096 <= n) andalso (n < 4096) then Immed13 else Immed32 ! 196: ! 197: ! 198: (** Utility operations **) ! 199: ! 200: fun emitMove (src, dst) = emit_or (zeroR, REGrand src, dst) ! 201: ! 202: fun loadImmed32 (n, r) = let ! 203: val lo10 = Bits.andb(n, 1023) ! 204: in ! 205: emit_sethi (IMrand(Bits.rshift(n, 10)), r); ! 206: if (lo10 <> 0) then emit_or(r, IMrand lo10, r) else () ! 207: end ! 208: ! 209: fun loadImmed (n, r) = ( ! 210: case (sizeImmed n) ! 211: of Immed13 => emit_or(zeroR, IMrand n, r) ! 212: | Immed32 => loadImmed32 (n, r)) ! 213: ! 214: fun op32 f (r1, n, r2) = let val tmpR = getTmpReg() ! 215: in ! 216: loadImmed32 (n, tmpR); ! 217: f (r1, REGrand tmpR, r2); ! 218: freeTmpReg tmpR ! 219: end ! 220: ! 221: fun loadReg(r, offset, dst) = ( ! 222: case (sizeImmed offset) ! 223: of Immed13 => emit_ld (r, IMrand offset, dst) ! 224: | Immed32 => (op32 emit_ld) (r, offset, dst)) ! 225: ! 226: fun store (src, r, offset) = ( ! 227: case (sizeImmed offset) ! 228: of Immed13 => emit_st (r, IMrand offset, src) ! 229: | Immed32 => (op32 emit_st) (r, offset, src)) ! 230: ! 231: fun addImmed (r, n, dst) = ( ! 232: case (sizeImmed n) ! 233: of Immed13 => emit_add (r, IMrand n, dst) ! 234: | Immed32 => (op32 emit_add) (r, n, dst)) ! 235: ! 236: fun compareImmed (r, n) = ( ! 237: case (sizeImmed n) ! 238: of Immed13 => emit_subcc (r, IMrand n, zeroR) ! 239: | Immed32 => (op32 emit_subcc) (r, n, zeroR)) ! 240: ! 241: ! 242: (** CMachine instructions **) ! 243: ! 244: (* move (src, dst) *) ! 245: fun move (Immed n, Direct r) = loadImmed (n, r) ! 246: | move (ImmedLab lab, Direct r) = let val tmpR = getTmpReg() ! 247: in ! 248: loadAddr (lab, 0, r, tmpR); ! 249: freeTmpReg tmpR ! 250: end ! 251: | move (Direct r1, Direct r2) = emitMove (r1, r2) ! 252: | move _ = ErrorMsg.impossible "[SparcCM.move]" ! 253: ! 254: (* checkLimit (n): ! 255: * Generate code to check the heap limit to see if there is enough free space ! 256: * to allocate n bytes. ! 257: * NOTE: The handler in "runtime/SPARC.dep.c" is sensitive to the code ! 258: * sequences generated here. ! 259: *) ! 260: fun checkLimit maxAllocSize = ( ! 261: if (maxAllocSize <= 4096) ! 262: then emit_taddcctv (dataptrR, limitptrRand, zeroR) ! 263: else let ! 264: val n = maxAllocSize - 4096 ! 265: val tmpR = getTmpReg() ! 266: in ! 267: if (n < 2048) ! 268: then ( ! 269: emit_add (limitptrR, IMrand n, tmpR); ! 270: emit_taddcctv (dataptrR, REGrand tmpR, zeroR)) ! 271: else ( ! 272: emit_sethi (IMrand(Bits.rshift(n, 10)), tmpR); ! 273: emit_or (tmpR, IMrand(Bits.andb(n, 1023)), tmpR); ! 274: emit_add (limitptrR, REGrand tmpR, tmpR); ! 275: emit_taddcctv (dataptrR, REGrand tmpR, zeroR)); ! 276: freeTmpReg tmpR ! 277: end) ! 278: ! 279: (* beginStdFn (cl, lab): ! 280: * Note the beginning of a standard function with entry label lab, and ! 281: * register cl containing its closure. This requires generating code to ! 282: * load the base code block address into baseCodePtr. ! 283: *) ! 284: fun beginStdFn (Direct closureReg, ImmedLab lab) = let val tmpR = getTmpReg() ! 285: in ! 286: setBaseAddr (closureReg, lab, tmpR); ! 287: freeTmpReg tmpR ! 288: end ! 289: | beginStdFn _ = ErrorMsg.impossible "[SparcCM.beginStdFn]" ! 290: ! 291: (* jmp (dst): ! 292: * Unconditional jump to destination. ! 293: *) ! 294: fun jmp (ImmedLab lab) = emit_ba lab ! 295: | jmp (Direct r) = emit_jmp (r, zeroRand) ! 296: | jmp _ = ErrorMsg.impossible "[SparcCM.jmp]" ! 297: ! 298: (* record (vl, dst): ! 299: * makes a new record, puts address of it into the destination specified ! 300: * by the second arg. The contents are numbered from ~1 and up. ! 301: *) ! 302: fun record (vl : (EA * CPS.accesspath) list, Direct dst) = let ! 303: val len = length vl ! 304: val minBlockSize = 6 ! 305: (* generate code to move one or more adjacent fields from one record into ! 306: * adjacent fields in the new record. If the block is big enough, then ! 307: * use a block copy loop. ! 308: *) ! 309: fun blockMove (srcR, startindx, path, offset) = let ! 310: (* check a CPS path to see how large the block is *) ! 311: fun chkpath (cnt, i, ! 312: path as (Direct r, CPS.SELp(j, CPS.OFFp 0)) :: rest) = ! 313: if (r = srcR) andalso (i+offset = j) ! 314: then chkpath (cnt+1, i-1, rest) ! 315: else (cnt, path) ! 316: | chkpath (cnt, _, rest) = (cnt, rest) ! 317: (* generate code to move fields individually *) ! 318: fun moveFields (0, _) = () ! 319: | moveFields (n, indx) = let val tmpR = getTmpReg() ! 320: in ! 321: loadReg(srcR, (indx+offset)*4, tmpR); ! 322: store (tmpR, dataptrR, indx*4); ! 323: freeTmpReg tmpR; ! 324: moveFields(n-1, indx-1) ! 325: end ! 326: val (blksz, rest) = chkpath(1, startindx-1, path) ! 327: in ! 328: if (blksz < minBlockSize) ! 329: then moveFields(blksz, startindx) ! 330: else if (offset = 0) ! 331: then let ! 332: val lab = newLabel() ! 333: val indxR = getTmpReg() and tmpR = getTmpReg() ! 334: in ! 335: loadImmed (startindx*4, indxR); ! 336: C.define lab; ! 337: emit_ld (srcR, REGrand indxR, tmpR); ! 338: compareImmed (indxR, (startindx-blksz)*4); ! 339: emit_st (dataptrR, REGrand indxR, tmpR); ! 340: emit_sub (indxR, IMrand 4, indxR); ! 341: emit_bcc (GTR, lab); ! 342: freeTmpReg indxR; freeTmpReg tmpR ! 343: end ! 344: else let ! 345: val lab = newLabel() ! 346: val indxR1 = getTmpReg() and indxR2 = getTmpReg() ! 347: val tmpR = getTmpReg() ! 348: in ! 349: loadImmed ((startindx+offset)*4, indxR1); ! 350: loadImmed (startindx*4, indxR2); ! 351: C.define lab; ! 352: emit_ld (srcR, REGrand indxR1, tmpR); ! 353: emit_sub (indxR1, IMrand 4, indxR1); ! 354: emit_st (dataptrR, REGrand indxR2, tmpR); ! 355: emit_sub (indxR2, IMrand 4, indxR2); ! 356: compareImmed (indxR1, (startindx+offset-blksz)*4); ! 357: emit_bcc (GTR, lab); ! 358: freeTmpReg indxR1; freeTmpReg indxR2; freeTmpReg tmpR ! 359: end; ! 360: freeReg srcR; ! 361: (startindx-blksz, rest) ! 362: end (* blockMove *) ! 363: (* For each field in the record generate the necessary moves to initialize ! 364: * it in the new record. ! 365: *) ! 366: fun fields (_, nil) = () ! 367: | fields (i, (Direct r, CPS.SELp(j, CPS.OFFp 0)) :: rest) = ! 368: fields (blockMove (r, i, rest, j-i)) ! 369: | fields (i, (Direct r, CPS.SELp(j, p)) :: rest) = let ! 370: val tmpR = getTmpReg() ! 371: in ! 372: loadReg(r, j*4, tmpR); ! 373: freeReg r; ! 374: fields (i, (Direct tmpR, p) :: rest) ! 375: end ! 376: | fields (i, (Direct r, CPS.OFFp 0) :: rest) = ( ! 377: store (r, dataptrR, i*4); ! 378: freeReg r; ! 379: fields (i-1, rest)) ! 380: | fields (i, (Direct r, CPS.OFFp j) :: rest) = let ! 381: val tmpR = getTmpReg() ! 382: val offset = j*4 ! 383: in ! 384: case sizeImmed offset ! 385: of Immed13 => emit_add (r, IMrand offset, tmpR) ! 386: | Immed32 => ( ! 387: loadImmed32 (offset, tmpR); ! 388: emit_add (r, REGrand tmpR, tmpR)) ! 389: (* end case *); ! 390: store (tmpR, dataptrR, i*4); ! 391: freeTmpReg tmpR; freeReg r; ! 392: fields (i-1, rest) ! 393: end ! 394: | fields (i, (x, p) :: rest) = let ! 395: val tmpR = getTmpReg() ! 396: in ! 397: move (x, Direct tmpR); ! 398: fields (i, (Direct tmpR, p) :: rest) ! 399: end ! 400: in ! 401: fields (len-2, rev vl); ! 402: emitMove (dataptrR, dst); ! 403: addImmed (dataptrR, len*4, dataptrR) ! 404: end ! 405: | record _ = ErrorMsg.impossible "[SparcCM.record]" ! 406: ! 407: (* select (i, x, y): y <- mem[x + 4*i] *) ! 408: fun select (i, Direct r, Direct dst) = loadReg(r, i*4, dst) ! 409: | select (i, ImmedLab lab, Direct dst) = let val tmpR = getTmpReg() ! 410: in ! 411: load (lab, i*4, dst, tmpR); ! 412: freeTmpReg tmpR ! 413: end ! 414: | select _ = ErrorMsg.impossible "[SparcCM.select]" ! 415: ! 416: (* offset (i, x, y): y <- (x + 4*i) *) ! 417: fun offset (i, Direct r, Direct dst) = addImmed (r, 4*i, dst) ! 418: | offset (i, ImmedLab lab, Direct dst) = let val tmpR = getTmpReg() ! 419: in ! 420: loadAddr (lab, i, dst, tmpR); ! 421: freeTmpReg tmpR ! 422: end ! 423: | offset _ = ErrorMsg.impossible "[SparcCM.offset]" ! 424: ! 425: (* fetchindexb (x, y) fetches an unsigned byte: y <- mem[x+arithtemp] *) ! 426: fun fetchindexb (Direct r, Direct dst) = emit_ldb (r, arithtempRand, dst) ! 427: | fetchindexb _ = ErrorMsg.impossible "[SparcCM.fetchindexb]" ! 428: ! 429: (* storeindexb (x, y) stores a byte: mem[y+arithtemp] <- x *) ! 430: fun storeindexb (Direct src, Direct r) = emit_stb (r, arithtempRand, src) ! 431: | storeindexb _ = ErrorMsg.impossible "[SparcCM.storeindexb]" ! 432: ! 433: (* jmpindexb (x): pc <- (x+arithtemp) *) ! 434: fun jmpindexb (ImmedLab lab) = let ! 435: val tmpR1 = getTmpReg() and tmpR2 = getTmpReg() ! 436: in ! 437: loadAddr (lab, 0, tmpR1, tmpR2); ! 438: emit_jmp (tmpR1, arithtempRand); ! 439: freeTmpReg tmpR1; freeTmpReg tmpR2 ! 440: end ! 441: | jmpindexb _ = ErrorMsg.impossible "[SparcCM.jmpindexb]" ! 442: ! 443: (* fetchindexl (x, y, z) fetches a word: y <- mem[x+2*(z-1)] *) ! 444: fun fetchindexl (Direct r1, Direct dst, Direct r2) = let ! 445: val tmpR = getTmpReg() ! 446: in ! 447: emit_sub (r2, IMrand 1, tmpR); ! 448: emit_add (tmpR, REGrand tmpR, tmpR); ! 449: emit_ld (r1, REGrand tmpR, dst); ! 450: freeTmpReg tmpR ! 451: end ! 452: | fetchindexl (Direct r1, Direct dst, Immed i) = loadReg(r1, 2*(i-1), dst) ! 453: | fetchindexl (ImmedLab lab, Direct dst, Direct r) = let ! 454: val tmpR1 = getTmpReg() and tmpR2 = getTmpReg() ! 455: in ! 456: loadAddr (lab, ~2, tmpR1, tmpR2); ! 457: emit_add (r, REGrand tmpR1, tmpR1); ! 458: emit_ld (r, REGrand tmpR1, dst); ! 459: freeTmpReg tmpR1; freeTmpReg tmpR2 ! 460: end ! 461: | fetchindexl _ = ErrorMsg.impossible "[SparcCM.fetchindexl]" ! 462: ! 463: (*storeindexl (x, y, z) stores a word: mem[y+2*(z-1)] <- x *) ! 464: fun storeindexl (Direct src, Direct r1, Direct r2) = let val tmpR = getTmpReg() ! 465: in ! 466: emit_sub (r2, IMrand 1, tmpR); ! 467: emit_add (tmpR, REGrand tmpR, tmpR); ! 468: emit_st (r1, REGrand tmpR, src); ! 469: freeTmpReg tmpR ! 470: end ! 471: | storeindexl (Direct src, Direct r, Immed i) = store (src, r, 2*(i-1)) ! 472: | storeindexl (Immed n, x, y) = let val tmpR = getTmpReg() ! 473: in ! 474: loadImmed (n, tmpR); ! 475: storeindexl (Direct tmpR, x, y); ! 476: freeTmpReg tmpR ! 477: end ! 478: | storeindexl (ImmedLab lab, x, y) = let ! 479: val tmpR1 = getTmpReg() and tmpR2 = getTmpReg() ! 480: in ! 481: loadAddr (lab, 0, tmpR1, tmpR2); ! 482: storeindexl (Direct tmpR1, x, y); ! 483: freeTmpReg tmpR1; freeTmpReg tmpR2 ! 484: end ! 485: (** NOTE: in a sane world the following case would be unecessary, but they ! 486: ** are used in an ugly profiling hack. ! 487: **) ! 488: | storeindexl (Direct src, ImmedLab lab, Immed i) = let ! 489: val tmpR1 = getTmpReg() and tmpR2 = getTmpReg() ! 490: in ! 491: loadAddr (lab, 2*(i-1), tmpR1, tmpR2); ! 492: emit_st (tmpR1, zeroRand, src); ! 493: freeTmpReg tmpR1; freeTmpReg tmpR2 ! 494: end ! 495: | storeindexl _ = ErrorMsg.impossible "[SparcCM.storeindexl]" ! 496: ! 497: (* ashl (n, x, y) shift left: y <- (x << n), with n >= 0 *) ! 498: fun ashl (Direct cntR, Direct src, Direct dst) = ! 499: emit_sll(src, REGrand cntR, dst) ! 500: | ashl (Immed cnt, Direct src, Direct dst) = ! 501: emit_sll (src, IMrand(Bits.andb(cnt, 31)), dst) ! 502: | ashl (Direct cntR, Immed src, Direct dst) = let val tmpR = getTmpReg() ! 503: in ! 504: loadImmed (src, tmpR); ! 505: emit_sll (tmpR, REGrand cntR, dst); ! 506: freeTmpReg tmpR ! 507: end ! 508: | ashl _ = ErrorMsg.impossible "[SparcCM.ashl]" ! 509: ! 510: (* ashr (n, x, y) shift right: y <- (x >> n), with n >= 0 *) ! 511: fun ashr (Direct cntR, Direct src, Direct dst) = ! 512: emit_sra (src, REGrand cntR, dst) ! 513: | ashr (Immed cnt, Direct src, Direct dst) = ! 514: emit_sra (src, IMrand(Bits.andb(cnt, 31)), dst) ! 515: | ashr (Direct cntR, Immed src, Direct dst) = let val tmpR = getTmpReg() ! 516: in ! 517: loadImmed (src, tmpR); ! 518: emit_sra (tmpR, REGrand cntR, dst); ! 519: freeTmpReg tmpR ! 520: end ! 521: | ashr (Immed cnt, Immed src, Direct dst) = ( ! 522: print "[missed constant fold ("; print src; print " >> "; print cnt; print ")]\n"; ! 523: loadImmed (Bits.rshift(src, cnt), dst)) ! 524: | ashr _ = ErrorMsg.impossible "[SparcCM.ashr]" ! 525: ! 526: local ! 527: fun adjArgs f (a as Immed _, b, c) = f (b, a, c) ! 528: | adjArgs f args = f args ! 529: fun adjSubArgs f (a, Immed b, c) = let val tmpR = getTmpReg() ! 530: in ! 531: loadImmed (b, tmpR); ! 532: f (Direct tmpR, a, c); ! 533: freeTmpReg tmpR ! 534: end ! 535: | adjSubArgs f (a, b, c) = f (b, a, c) ! 536: fun arithOp f (Direct r1, Direct r2, Direct dst) = f (r1, REGrand r2, dst) ! 537: | arithOp f (Direct r, Immed n, Direct dst) = ( ! 538: case (sizeImmed n) ! 539: of Immed13 => f (r, IMrand n, dst) ! 540: | Immed32 => let val tmpR = getTmpReg() ! 541: in ! 542: loadImmed32 (n, tmpR); ! 543: f (r, REGrand tmpR, dst); ! 544: freeTmpReg tmpR ! 545: end) ! 546: | arithOp _ _ = ErrorMsg.impossible "[SparcCM.arithOp]" ! 547: val addt = adjArgs (arithOp (fn args => (emit_addcc args; emit_tvs()))) ! 548: in ! 549: ! 550: val orb = adjArgs (arithOp emit_or) ! 551: val andb = adjArgs (arithOp emit_and) ! 552: val xorb = adjArgs (arithOp emit_xor) ! 553: fun notb (Direct src, Direct dst) = emit_not (src, dst) ! 554: | notb _ = ErrorMsg.impossible "[SparcCM.notb]" ! 555: ! 556: val addl3 = adjArgs (arithOp emit_add) ! 557: fun addl3t (Immed a, b as Immed _, dst) = let val tmpR = getTmpReg () ! 558: (* This should only occur when we need to build a constant larger than ! 559: * 2^29. Note, we assume that "b" is tagged (see "cps/generic.sml"). ! 560: *) ! 561: in ! 562: loadImmed (a, tmpR); ! 563: addt (Direct tmpR, b, dst); ! 564: freeTmpReg tmpR ! 565: end ! 566: | addl3t args = addt args ! 567: ! 568: val subl3 = adjSubArgs (arithOp emit_sub) ! 569: val subl3t = adjSubArgs (arithOp (fn args => (emit_subcc args; emit_tvs()))) ! 570: ! 571: end (* local *) ! 572: ! 573: (* mull2t/divl2t: ! 574: * mull2t (a, b): b <- (a * b) (with overflow checking done by ml_mul) ! 575: * divl2t (a, b): b <- (b div a) ! 576: *) ! 577: local ! 578: fun intOp opAddrOffset (a, b as Direct _) = ( ! 579: emit_ld (spR, opAddrOffset, opAddrR); ! 580: move (a, arg2EA); ! 581: move (b, arg1EA); ! 582: emit_jmpl (opAddrR, zeroRand, linkR); ! 583: move (arg1EA, b)) ! 584: | intOp _ _ = ErrorMsg.impossible "[SparcCM.intOp]" ! 585: val mulAddrOffset = IMrand 72 ! 586: val divAddrOffset = IMrand 76 ! 587: in ! 588: val mull2t = intOp mulAddrOffset ! 589: val divl2 = intOp divAddrOffset ! 590: end (* local *) ! 591: ! 592: (* bbs (i, dst, lab): test the i'th bit of dst and jump to lab if it is zero *) ! 593: fun bbs (Immed i, Direct r, ImmedLab lab) = ( ! 594: emit_andcc (r, IMrand(Bits.lshift(1, i)), zeroR); ! 595: emit_bcc (NEQ, lab)) ! 596: | bbs _ = ErrorMsg.impossible "[SparcCM.bbs]" ! 597: ! 598: local ! 599: (* reverse a condition (eg., (a <= b) <==> (b >= a) *) ! 600: fun revCond NEQ = NEQ | revCond EQL = EQL ! 601: | revCond LEQ = GEQ | revCond GEQ = LEQ ! 602: | revCond LSS = GTR | revCond GTR = LSS ! 603: in ! 604: ! 605: (* ibranch (cond, a, b, lab): if (a <cond> b) then pc <- lab *) ! 606: fun ibranch (cond, a as Immed _, b as Direct _, l) = ibranch (revCond cond, b, a, l) ! 607: | ibranch (cond, Direct r1, b, ImmedLab lab) = ( ! 608: case b ! 609: of Direct r2 => emit_subcc (r1, REGrand r2, zeroR) ! 610: | Immed n => ( ! 611: case (sizeImmed n) ! 612: of Immed13 => emit_subcc (r1, IMrand n, zeroR) ! 613: | Immed32 => let val tmpR = getTmpReg() ! 614: in ! 615: loadImmed32 (n, tmpR); ! 616: emit_subcc (r1, REGrand tmpR, zeroR); ! 617: freeTmpReg tmpR ! 618: end) ! 619: | _ => ErrorMsg.impossible "[SparcCM.ibranch.case]" ! 620: (* end case *); ! 621: emit_bcc (cond, lab)) ! 622: | ibranch _ = ErrorMsg.impossible "[SparcCM.ibranch]" ! 623: ! 624: end (* local *) ! 625: ! 626: ! 627: (** Floating point instructions ** ! 628: * These instructions take ML real values as arguments (ie., addresses of ! 629: * heap objects) and store their results in the heap. ! 630: *) ! 631: ! 632: local ! 633: val f0 = FREG 0 ! 634: val f1 = FREG 1 ! 635: val f2 = FREG 2 ! 636: (* the tag code for real values. *) ! 637: val realTag = (8*System.Tags.power_tags + System.Tags.tag_string) ! 638: (* finishReal(r): emit code to store the result of a real operation ! 639: * (in %f0, %f1) in the heap, and put the result address in r. ! 640: *) ! 641: fun finishReal r = let val tmpR = getTmpReg() ! 642: in ! 643: loadImmed (realTag, tmpR); ! 644: emit_st (dataptrR, IMrand(~4), tmpR); ! 645: emit_stf (dataptrR, zeroRand, f0); ! 646: emit_stf (dataptrR, IMrand 4, f1); ! 647: emitMove (dataptrR, r); ! 648: emit_add (dataptrR, IMrand 12, dataptrR); ! 649: freeTmpReg tmpR ! 650: end ! 651: (* Fetch a ML real value into a floating-point register pair *) ! 652: fun fetchReal (Direct r, FREG i) = ( ! 653: emit_ldf (r, zeroRand, FREG i); ! 654: emit_ldf (r, IMrand 4, FREG(i+1))) ! 655: | fetchReal (ImmedLab lab, dst) = let val tmpR = getTmpReg() ! 656: in ! 657: loadF (lab, 0, dst, tmpR); ! 658: freeTmpReg tmpR ! 659: end ! 660: | fetchReal _ = ErrorMsg.impossible "[SparcCM.fetchReal]" ! 661: ! 662: fun floatOp fOp (a, b, Direct dst) = ( ! 663: fetchReal (a, f0); ! 664: fetchReal (b, f2); ! 665: fOp (f0, f2, f0); ! 666: finishReal dst) ! 667: | floatOp _ _ = ErrorMsg.impossible "[SparcCM.floatOp]" ! 668: in ! 669: ! 670: (* Negate the first arg and return a pointer to the result in the second *) ! 671: fun mnegg (src, Direct dst) = ( ! 672: fetchReal (src, f0); ! 673: emit_fneg (f0, f0); ! 674: finishReal dst) ! 675: | mnegg _ = ErrorMsg.impossible "[SparcCM.mnegg]" ! 676: ! 677: (* Add the first two arguments and store the result in the third *) ! 678: val addg3 = floatOp emit_fadd ! 679: ! 680: (* Subtract the second argument from the first and store the result in the third *) ! 681: val subg3 = floatOp emit_fsub ! 682: ! 683: (* Multiply the first two arguments and store the result in the third *) ! 684: val mulg3 = floatOp emit_fmul ! 685: ! 686: (* Divide the first argument by the second and store the result in the third *) ! 687: val divg3 = floatOp emit_fdiv ! 688: ! 689: (* Conditionally branch on the float values of two arguments. *) ! 690: fun gbranch (cond, a, b, ImmedLab lab) = ( ! 691: fetchReal (a, f0); ! 692: fetchReal (b, f2); ! 693: emit_fcmp (f0, f2); ! 694: emit_fbcc (cond, lab)) ! 695: | gbranch _ = ErrorMsg.impossible "[SparcCM.gbranch]" ! 696: ! 697: end (* local *) ! 698: ! 699: fun profile _ = () ! 700: ! 701: end (* local *) ! 702: ! 703: end (* functor SparcCM *)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.