Annotation of researchv10no/cmd/sml/src/sparc/sparc.sml, revision 1.1.1.1

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 *)

unix.superglobalmegacorp.com

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