Annotation of researchv10no/cmd/sml/src/sparc/sparc.sml, revision 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.