Annotation of researchv10no/cmd/sml/doc/mips/mips.tex, revision 1.1

1.1     ! root        1: \input nwmac
        !             2: \filename{mipsglue.nw}
        !             3: \begindocs{0}
        !             4: \enddocs
        !             5: \begindocs{1}
        !             6: For the Mips, all comments are no-ops, so to get diagnostics in
        !             7: assembly mode we have to slip in and define a new comment function.
        !             8: Our life is further complicated by the fact that the stream on which
        !             9: comments are to be written is bound late, so we have to save up comments
        !            10: and then write them when asked to \code{}generate\edoc{}.
        !            11: \enddocs
        !            12: \begincode{2}
        !            13: \moddef{*}\endmoddef
        !            14: structure MipsAC : ASSEMBLER = struct
        !            15:     val diag_out = ref std_out
        !            16:     structure MCN = struct
        !            17:         open MipsCoder
        !            18:         structure M = struct
        !            19:             open M
        !            20:             fun comment s = output (!diag_out) s
        !            21:         end
        !            22:     end
        !            23:         
        !            24:     structure CM = MipsCM(MCN)
        !            25:         
        !            26:     structure Gen = CPScomp(CM)
        !            27:     fun generate (lexp, stream) = (
        !            28:         diag_out := stream;
        !            29:         Gen.compile lexp;
        !            30:         MipsCoder.codestats stream;
        !            31:         Emitters.address := 0;
        !            32:         MipsCoder.codegen (Emitters.MipsAsm stream);
        !            33:         ())
        !            34: end
        !            35: 
        !            36: \endcode
        !            37: \begincode{3}
        !            38: \moddef{*}\endmoddef
        !            39: structure MipsCodeStats : ASSEMBLER = struct
        !            40:     val diag_out = ref std_out
        !            41:     structure MCN = MipsCoder
        !            42:         
        !            43:     structure CM = MipsCM(MCN)
        !            44:         
        !            45:     structure Gen = CPScomp(CM)
        !            46:     fun generate (lexp, stream) = (
        !            47:         Gen.compile lexp;
        !            48:         MipsCoder.codestats stream;
        !            49:         ())
        !            50: end
        !            51: 
        !            52: \endcode
        !            53: \begindocs{4}
        !            54: Mips machines come in two byte-orders, so we need two of
        !            55: every machinelike thing.
        !            56: \enddocs
        !            57: \begincode{5}
        !            58: \moddef{*}\endmoddef
        !            59: structure MipsMCBig : CODEGENERATOR = struct
        !            60:     structure CM = MipsCM(MipsCoder)
        !            61:     structure Gen = CPScomp(CM)
        !            62:  
        !            63:     fun generate lexp = (
        !            64:         Gen.compile lexp;
        !            65:         MipsCoder.codegen (Emitters.BigEndian);
        !            66:         Emitters.emitted_string ()
        !            67:         )
        !            68: end
        !            69: 
        !            70: structure MipsMCLittle : CODEGENERATOR = struct
        !            71:     structure CM = MipsCM(MipsCoder)
        !            72:     structure Gen = CPScomp(CM)
        !            73: fun diag (s : string) f x =
        !            74:         f x handle e =>
        !            75:                 (print "?exception "; print (System.exn_name e);
        !            76:                  print " in mipsglue."; print s; print "\\n";
        !            77:                  raise e)
        !            78:  
        !            79:     fun generate lexp = (
        !            80:         diag "Gen.compile" Gen.compile lexp;
        !            81:         diag "MipsCoder.codegen" MipsCoder.codegen (Emitters.LittleEndian);
        !            82:         diag "Emitters.emitted_string" Emitters.emitted_string ()
        !            83:         )
        !            84: end
        !            85: 
        !            86: 
        !            87: structure CompMipsLittle = Batch(structure M=MipsMCLittle and A=MipsAC)
        !            88: structure IntMipsLittle = IntShare(MipsMCLittle)
        !            89: 
        !            90: structure CompMipsBig = Batch(structure M=MipsMCBig and A=MipsAC)
        !            91: structure IntMipsBig = IntShare(MipsMCBig)
        !            92: 
        !            93: structure CompMipsStats = Batch(structure M=MipsMCLittle and A=MipsCodeStats)
        !            94: \endcode
        !            95: \filename{emitters.nw}
        !            96: \begindocs{0}
        !            97: \section{Emitters}
        !            98: We have an odd problem---we need to be able to emit either a 32-bit
        !            99: integer or a string.
        !           100: The order in which the bytes of the integer are emitted depends on
        !           101: whether the target machine is BigEndian or LittleEndian, but the
        !           102: bytes of the string should be emitted in the same order on both machines.
        !           103: This means that the two emission functions depend on each other, but
        !           104: in a machine-dependent way, so we bundle them up.
        !           105: We also have to be able to emit two words for floating point constants.
        !           106: The way to do this can be derived from \code{}emit_word\edoc{}, and this
        !           107: code seems to be the sensible place to do that.
        !           108: So we define a type \code{}emitter_triple\edoc{} 
        !           109: and pass them around that way.
        !           110: 
        !           111: \enddocs
        !           112: \begindocs{1}
        !           113: Eventually we want to take all the words and strings that have been
        !           114: emitted and bundle them up into a single string using \code{}implode\edoc{}.
        !           115: We'll take the following tack with that:
        !           116: each emitter will squirrel some info away in a reference variable.
        !           117: A function \code{}emitted_string: unit -> string\edoc{} will take the
        !           118: squirreled information and return a string that represents
        !           119: everything emitted so far.
        !           120: As a side effect, it will reset the emitter system to its initial 
        !           121: state, where ``everything emitted so far'' is the empty string.
        !           122: 
        !           123: The actual implementation will be a list of strings which is reversed 
        !           124: and imploded.
        !           125: \enddocs
        !           126: \begincode{2}
        !           127: \moddef{signature}\endmoddef
        !           128: signature EMITTERS = sig
        !           129:     type emitter_triple
        !           130:     val LittleEndian : emitter_triple
        !           131:     val BigEndian : emitter_triple
        !           132:     val emitted_string : unit -> string
        !           133:     val MipsAsm : outstream -> emitter_triple
        !           134:     val address : int ref
        !           135: end
        !           136: 
        !           137: \endcode
        !           138: \begindocs{3}
        !           139: First something that's capable of emitting real code, then
        !           140: something that can print assembly code.
        !           141: We emit the assembly code to output right away, without any fooling.
        !           142: \enddocs
        !           143: \begincode{4}
        !           144: \moddef{*}\endmoddef
        !           145: structure Emitters : EMITTERS = struct
        !           146:     type emitter_triple = (int * int -> unit) * (int -> string -> unit)
        !           147:                                         * (string -> unit)
        !           148:     local 
        !           149:         \LA{}memory and basic services\RA{}
        !           150:     in
        !           151:         \LA{}string emitter\RA{}
        !           152:         \LA{}little-endian emitter\RA{}
        !           153:         \LA{}big-endian emitter\RA{}
        !           154:         fun emitted_string () =
        !           155:             let val s = implode (rev (!so_far))
        !           156:             in  so_far := nil; s
        !           157:             end
        !           158:     end
        !           159:     structure BigReal = MipsReal(struct val emit_word = emit_pair_big end)
        !           160:     structure LittleReal =MipsReal(struct val emit_word = emit_pair_little end)
        !           161:     val LittleEndian = (emit_pair_little,emit_string,LittleReal.realconst)
        !           162:     val BigEndian = (emit_pair_big,emit_string,BigReal.realconst)
        !           163:     \LA{}assembly-code emitters\RA{}
        !           164: end
        !           165: 
        !           166: 
        !           167: \endcode
        !           168: \begindocs{5}
        !           169: Here is a variable to remember what's been emitted so far
        !           170: \enddocs
        !           171: \begincode{6}
        !           172: \moddef{memory and basic services}\endmoddef
        !           173: val so_far = ref nil : string list ref
        !           174: fun squirrel s = so_far := s :: !so_far
        !           175: fun emit_byte n = squirrel (chr n)
        !           176: \endcode
        !           177: \begincode{7}
        !           178: \moddef{string emitter}\endmoddef
        !           179: fun emit_string n s = squirrel (substring(s,0,n))
        !           180:                 handle e =>
        !           181:                         (print "?exception "; print (System.exn_name e);
        !           182:                          print (" in emitters.emit_string "^
        !           183:                                 (Integer.makestring n) ^ " \\""^s^"\\"\\n");
        !           184:                          raise e)
        !           185: 
        !           186: \endcode
        !           187: \begindocs{8}
        !           188: Little-endian means the little (least significant) end first,
        !           189: like the VAX.
        !           190:  We parameterize the real emitters by a function that emits a byte.
        !           191: \enddocs
        !           192: \begincode{9}
        !           193: \moddef{little-endian emitter}\endmoddef
        !           194: fun emit_pair_little(hi,lo) =
        !           195:     let open Bits
        !           196:         fun emit_word(n) =
        !           197:           (emit_byte(andb(n,255));emit_byte(andb(rshift(n,8),255)))
        !           198:     in  (emit_word(lo);emit_word(hi))
        !           199:     end
        !           200: 
        !           201: \endcode
        !           202: \begincode{10}
        !           203: \moddef{big-endian emitter}\endmoddef
        !           204: fun emit_pair_big(hi,lo) =
        !           205:      let open Bits
        !           206:         fun emit_word(n) =
        !           207:           (emit_byte(andb(rshift(n,8),255));emit_byte(andb(n,255)))
        !           208:     in  (emit_word(hi);emit_word(lo))
        !           209:     end
        !           210: 
        !           211: 
        !           212: \endcode
        !           213: \begindocs{11}
        !           214: Now the assembly code.
        !           215: to make it easier to debug, we print out addresses in the same format
        !           216: as {\tt dbx}: we use the byte address and we print it in hex.
        !           217: 
        !           218: We have to bend over backwards to handle real numbers
        !           219: 
        !           220: \enddocs
        !           221: \begincode{12}
        !           222: \moddef{assembly-code emitters}\endmoddef
        !           223: val address = ref 0             (* address of next instruction in words *)
        !           224: \LA{}real number state info and \code{}decode_real_ptr\edoc{}\RA{}
        !           225: fun MipsAsm stream =
        !           226:     let fun say s = (output stream s; flush_out stream)
        !           227:         fun printaddr addrref = 
        !           228:            let val n = !addrref
        !           229:            in  (if n<10 then "  " else if n < 100 then " " else "") 
        !           230:                 ^ (Integer.makestring n) 
        !           231:            end
        !           232:         local 
        !           233:             open Bits
        !           234:             fun hexdigit n = 
        !           235:                 let val d = andb(n,15)
        !           236:                 in  if d <= 9 then chr(d+ord("0"))
        !           237:                               else chr(d-10+ord("a"))
        !           238:                 end
        !           239:             fun hex1 n = hexdigit(rshift(n,4))^hexdigit(n)
        !           240:             fun hex2 n = hex1(rshift(n,8))^hex1(n)
        !           241:             fun hex4 n = hex2(rshift(n,16))^hex2(n)
        !           242:         in
        !           243:             fun hex(hi,lo) = hex2(hi) ^ hex2(lo)
        !           244:             fun printaddr addrref = 
        !           245:                 let val n = 4 * (!addrref)      (* address in bytes *)
        !           246:                 in "0x" ^ (hex4 n) 
        !           247:            end
        !           248:         end
        !           249:         fun decode x = (
        !           250:                 say ((printaddr address) ^ ": (" ^ (hex x) ^") " 
        !           251:                  ^ (MipsDecode.decode x));
        !           252:            address := !address + 1; ()
        !           253:            )
        !           254:         fun do_decode_real(w,s) = (
        !           255:                 say ((printaddr address) ^ ": (" ^ (hex w) ^") " 
        !           256:                  ^ s ^ "\\n");
        !           257:            address := !address + 1; ()
        !           258:            )
        !           259:         fun decode_real s = (real_string := s; AsmReal.realconst s)
        !           260:         fun decode_string n s =
        !           261:             if n > 0 then
        !           262:                 (say ((printaddr address) 
        !           263:                             ^ ": \\"" ^substring(s,0,4) ^"\\"\\n");
        !           264:                    address := !address + 1;
        !           265:                    decode_string (n-4) (substring(s,4,String.length(s)-4))
        !           266:                    )
        !           267:             else ()
        !           268:     in
        !           269:         decode_real_ptr := SOME do_decode_real;
        !           270:         (decode,decode_string,decode_real) : emitter_triple
        !           271:     end
        !           272: \endcode
        !           273: \begincode{13}
        !           274: \moddef{real number state info and \code{}decode_real_ptr\edoc{}}\endmoddef
        !           275: val decode_real_ptr = ref NONE : ((int * int) * string -> unit) option ref
        !           276:                                    (* used to emit asm code for a real word *)
        !           277:     
        !           278: val real_least = ref NONE : (int * int) option ref
        !           279:                                    (* least significant word of real *)
        !           280: val real_string = ref ""
        !           281: fun emit_real_word w =
        !           282:     let val decode_real = case !decode_real_ptr of 
        !           283:                   SOME f => f 
        !           284:                 | NONE => ErrorMsg.impossible "missed real decoder in mips asm"
        !           285:     in
        !           286:         case !real_least of 
        !           287:             NONE => real_least := SOME w
        !           288:           | SOME least => 
        !           289:                 (decode_real(least,"[low  word of "^(!real_string)^"]");
        !           290:                  decode_real(w,"[high word of "^(!real_string)^"]"))
        !           291:     end
        !           292: 
        !           293: structure AsmReal = MipsReal(struct val emit_word = emit_real_word end)
        !           294: 
        !           295: \endcode
        !           296: \filename{mipsreal.nw}
        !           297: \begindocs{0}
        !           298: \subsection{Handling IEEE floating point constants}
        !           299: Here we take care of converting floating point constants from
        !           300: string representation to 64-bit IEEE representation.
        !           301: We use the machinery developed for the Sparc by John Reppy.
        !           302: 
        !           303: Reppy's functor accepts a simple structure with a single value,
        !           304: \code{}emitWord : int -> unit\edoc{}, which emits a 16-bit word.
        !           305: It produces a \code{}PRIMREAL\edoc{}.
        !           306: When \code{}RealConst\edoc{} is applied to the result, it produces a 
        !           307: structure containing a single function, \code{}val realconst : string -> unit\edoc{}.
        !           308: This function, when applied to a string, emits the four sixteen-bit words
        !           309: of the IEEE representation, most significant first.
        !           310: 
        !           311: Our job will be to convert this to something that emits the two 32-bit
        !           312: words of the constant, least significant word first.
        !           313: First, let's consider the state information that has to be retained
        !           314: while the halfwords are being emitted, and functions that change that state.
        !           315: \enddocs
        !           316: \begincode{1}
        !           317: \moddef{state info}\endmoddef
        !           318: val halfwords = ref nil : int list ref          (* halfwords already out *)
        !           319: val count = ref 0                               (* length of halfwords *)
        !           320: fun reset_state () = (halfwords := nil; count := 0)
        !           321: fun add_half h = (count := !count + 1; halfwords := h :: (!halfwords))
        !           322: 
        !           323: \endcode
        !           324: \begincode{2}
        !           325: \moddef{emitting a halfword}\endmoddef
        !           326: fun emit_half h = 
        !           327:     if !count = 3 then (emit_four (h::(!halfwords)); reset_state())
        !           328:     else add_half h
        !           329: 
        !           330: \endcode
        !           331: \begindocs{3}
        !           332: To emit the whole list, we have to emit the words, one at a time.
        !           333: We use descriptive names to remind ourselves what is signficant
        !           334: (highest is most significant).
        !           335: \enddocs
        !           336: \begincode{4}
        !           337: \moddef{emitting four halfwords}\endmoddef
        !           338: fun emit_four [lowest,low,high,highest] = 
        !           339:                         (emit_word(low,lowest);emit_word(highest,high))
        !           340:   | emit_four _ = ErrorMsg.impossible "bad floating pt constant in mips"
        !           341: 
        !           342: \endcode
        !           343: \begindocs{5}
        !           344: Now, we bundle up the whole thing in a functor that
        !           345: gets passed a structure holding \code{}emit_word\edoc{} and returns 
        !           346: one containing \code{}realconst\edoc{}.
        !           347: \enddocs
        !           348: \begincode{6}
        !           349: \moddef{*}\endmoddef
        !           350: functor MipsReal(E: sig val emit_word : int * int -> unit end) : REALCONST = 
        !           351: struct
        !           352:     open E
        !           353:     \LA{}state info\RA{}
        !           354:     \LA{}emitting four halfwords\RA{}
        !           355:     \LA{}emitting a halfword\RA{}
        !           356:     structure IEEERealConst =
        !           357:         RealConst(IEEEReal(struct val emitWord = emit_half end))
        !           358:     val realconst = IEEERealConst.realconst
        !           359: end
        !           360: 
        !           361: 
        !           362: 
        !           363: 
        !           364: \endcode
        !           365: \filename{mips.nw}
        !           366: \begindocs{0}
        !           367: \section{Using \code{}MIPSCODER\edoc{} to implement a \code{}CMACHINE\edoc{}}
        !           368: 
        !           369: \enddocs
        !           370: \begincode{1}
        !           371: \moddef{*}\endmoddef
        !           372: functor MipsCM(MipsC : MIPSCODER) : CMACHINE = struct
        !           373: 
        !           374:     open MipsC System.Tags
        !           375: 
        !           376:     \LA{}utility functions\RA{}
        !           377: 
        !           378:     \LA{}immediate and register functions\RA{}
        !           379: 
        !           380:     \LA{}register definitions\RA{}
        !           381: 
        !           382:     \LA{}move\RA{}
        !           383:     \LA{}alignment, marks, and constants\RA{}
        !           384:     \LA{}labels\RA{}
        !           385:     \LA{}record manipulation\RA{}
        !           386:     \LA{}indexed fetch and store (byte)\RA{}
        !           387:     \LA{}indexed fetch and store (word)\RA{}
        !           388:     \LA{}arithmetic\RA{}
        !           389:     \LA{}shifts\RA{}
        !           390:     \LA{}arithmetic and shifts with overflow detection\RA{}
        !           391:     \LA{}bitwise operations\RA{}
        !           392:     \LA{}branches\RA{}
        !           393: 
        !           394:     \LA{}floating point\RA{}
        !           395: 
        !           396:     \LA{}memory check\RA{}
        !           397: 
        !           398:     \LA{}omitted functions\RA{}
        !           399: 
        !           400:     val comment = M.comment
        !           401: 
        !           402: (* +DEBUG *)
        !           403:     \LA{}DEBUG code\RA{}
        !           404: (* -DEBUG *)
        !           405: 
        !           406: end (* MipsCM *)
        !           407: 
        !           408: \endcode
        !           409: \begindocs{2}
        !           410: The debugging code replaces possibly offensive functions with functions
        !           411: that diagnose their own exceptions.
        !           412: \enddocs
        !           413: \begincode{3}
        !           414: \moddef{DEBUG code}\endmoddef
        !           415: fun diag (s : string) f x =
        !           416:         f x handle e =>
        !           417:                 (print "?exception "; print (System.exn_name e);
        !           418:                  print " in mips."; print s; print "\\n";
        !           419:                  raise e)
        !           420: 
        !           421: \endcode
        !           422: \begincode{4}
        !           423: \moddef{immediate and register functions}\endmoddef
        !           424: val immed = Immed
        !           425: fun isimmed(Immed i) = SOME i
        !           426:   | isimmed _ = NONE
        !           427: 
        !           428: fun isreg(Direct(Reg i)) = SOME i | isreg _ = NONE
        !           429: fun eqreg (a: EA) b = a=b
        !           430: 
        !           431: 
        !           432: \endcode
        !           433: \begindocs{5}
        !           434: Here's what our register conventions are:
        !           435: \input regs
        !           436: \enddocs
        !           437: \begincode{6}
        !           438: \moddef{register definitions}\endmoddef
        !           439: val standardarg = Direct(Reg 2)
        !           440: val standardcont = Direct(Reg 3)
        !           441: val standardclosure = Direct(Reg 4)
        !           442: val miscregs = map (Direct o Reg) [5,6,7,8,9,10,11,12,13,14,
        !           443:                                    15,16,17,18,19]
        !           444: val storeptr as Direct storeptr' = Direct(Reg 22)
        !           445: val dataptr  as Direct dataptr'  = Direct(Reg 23)
        !           446: val exnptr = Direct(Reg 30)
        !           447: 
        !           448:   (* internal use only *)
        !           449: val my_arithtemp as Direct my_arithtemp'= Direct(Reg 20) 
        !           450: val my_ptrtemp as Direct my_ptrtemp' = Direct(Reg 21)
        !           451: 
        !           452:   (* exported for external use *)
        !           453: val arithtemp as Direct arithtemp' = Direct(Reg 24) 
        !           454: val arithtemp2 as Direct arithtemp2'= Direct(Reg 25)
        !           455: 
        !           456: \endcode
        !           457: \begincode{7}
        !           458: \moddef{move}\endmoddef
        !           459: fun move (src,Direct dest) = M.move(src, dest)
        !           460:   | move _ = ErrorMsg.impossible "destination of move not register in mips"
        !           461: \endcode
        !           462: \begincode{8}
        !           463: \moddef{alignment, marks, and constants}\endmoddef
        !           464: val align = M.align
        !           465: val mark = M.mark
        !           466: 
        !           467: val emitlong = M.emitlong
        !           468: val realconst = M.realconst
        !           469: val emitstring = M.emitstring
        !           470: 
        !           471: \endcode
        !           472: \begincode{9}
        !           473: \moddef{labels}\endmoddef
        !           474: fun emitlab(i,Immedlab lab) = M.emitlab(i,lab)
        !           475:   | emitlab _ = ErrorMsg.impossible "bad emitlab arg in mips"
        !           476: fun newlabel() = Immedlab(M.newlabel())
        !           477: fun define (Immedlab lab) = M.define lab
        !           478:   | define _ = ErrorMsg.impossible "bad define arg in mips"
        !           479: \endcode
        !           480: \begincode{10}
        !           481: \moddef{DEBUG code}\endmoddef
        !           482: val emitlab = diag "emitlab" emitlab
        !           483: val define = diag "define" define
        !           484: 
        !           485: 
        !           486: \endcode
        !           487: \begindocs{11}
        !           488: We only ever put the address of a newly created record into a register.
        !           489: If I make this out correctly, the first word on the list of
        !           490: values \code{}vl\edoc{} is actually a descriptor.
        !           491: BUGS: The original routine put the address of the descriptor
        !           492: into \code{}z\edoc{}.  
        !           493: What needs to go into \code{}z\edoc{} is the address of the first word in the record.
        !           494: We can get this by adding 4 to the \code{}dataptr'\edoc{}.
        !           495: \enddocs
        !           496: \begincode{12}
        !           497: \moddef{record manipulation}\endmoddef
        !           498: fun record(vl, Direct z) =
        !           499:     let open CPS
        !           500:         val len = List.length vl
        !           501:         fun f(i,nil) = ()
        !           502:           | f(i,(r, SELp(j,p))::rest) = (* follow ptrs to get the item *)
        !           503:                 (M.lw(my_ptrtemp', r, j*4); f(i,(my_ptrtemp,p)::rest))
        !           504:           | f(i,(Direct r,OFFp 0)::rest) =  (* simple store, last first *) 
        !           505:                 (M.sw(r, dataptr, i*4); f(i-1,rest))
        !           506:           | f(i,(Direct r, OFFp j)::rest) = 
        !           507:                 (M.add(r, Immed(4*j), my_ptrtemp'); 
        !           508:                                 f(i,(my_ptrtemp,OFFp 0)::rest))
        !           509:           | f(i,(ea,p)::rest) = (* convert to register-based *)
        !           510:                 (M.move(ea, my_ptrtemp'); f(i,(my_ptrtemp,p)::rest))
        !           511:       in f(len - 1, rev vl); (* store first word in \code{}0(dataptr')\edoc{} *)
        !           512:          M.add(dataptr', Immed 4, z);
        !           513:          M.add(dataptr', Immed(4*len), dataptr')
        !           514:      end
        !           515:    | record _ = ErrorMsg.impossible "result of record not register in mips"
        !           516: 
        !           517: fun select(i, r, Direct s) = M.lw(s, r, i*4)
        !           518:   | select _ = ErrorMsg.impossible "result of select not register in mips"
        !           519: 
        !           520: fun offset(i, Direct r, Direct s) = M.add(r,Immed(i*4), s)
        !           521:   | offset _ = ErrorMsg.impossible "nonregister arg to offset in mips"
        !           522: \endcode
        !           523: \begincode{13}
        !           524: \moddef{DEBUG code}\endmoddef
        !           525: val record = diag "record" record
        !           526: val select = diag "select" select
        !           527: val offset = diag "offset" offset
        !           528: 
        !           529: \endcode
        !           530: \begindocs{14}
        !           531: For the indexed fetch and store, arithtemp is {\em not} tagged---the
        !           532: tags are removed at a higher level (in {\tt generic.sml}).
        !           533: These could be made faster for the case when they're called with immediate
        !           534: constants as \code{}x\edoc{}.
        !           535: \enddocs
        !           536: \begincode{15}
        !           537: \moddef{indexed fetch and store (byte)}\endmoddef
        !           538: (* fetchindexb(x,y) fetches a byte: y <- mem[x+arithtemp]
        !           539:         y cannot be arithtemp *)
        !           540: fun fetchindexb(x,Direct y) =
        !           541:     (M.add(arithtemp',x,my_arithtemp');    
        !           542:      M.lbu(y,my_arithtemp,0))
        !           543:   | fetchindexb _ = ErrorMsg.impossible "fetchb result not register in mips"
        !           544: 
        !           545: (* storeindexb(x,y) stores a byte: mem[y+arithtemp] <- x; *)
        !           546: fun storeindexb(Direct x,y) =
        !           547:     (M.add(arithtemp',y,my_arithtemp');
        !           548:      M.sb(x,my_arithtemp,0))
        !           549:   | storeindexb _ = ErrorMsg.impossible "storeb arg not register in mips"
        !           550: 
        !           551: (* jmpindexb(x)    pc <- (x+arithtemp) *)
        !           552: fun jmpindexb x = (M.add(arithtemp',x,my_arithtemp');
        !           553:                      M.jump(my_arithtemp'))
        !           554: 
        !           555: \endcode
        !           556: \begincode{16}
        !           557: \moddef{DEBUG code}\endmoddef
        !           558: val fetchindexb = diag "fetchindexb" fetchindexb
        !           559: val storeindexb = diag "storeindexb" storeindexb
        !           560: val jmpindexb = diag "jmpindexb" jmpindexb
        !           561: 
        !           562: 
        !           563: \endcode
        !           564: \begindocs{17}
        !           565: Here it looks like \code{}z\edoc{} is a tagged integer number of words,
        !           566: so that \code{}2*(z-1)\edoc{} converts to the appropriate byte offset.
        !           567: But I'm just guessing.
        !           568: In any case, it saves an instruction to compute \code{}2*z\edoc{} (actually \code{}z+z\edoc{})
        !           569: and 
        !           570: load (or store) with offset \code{}~2\edoc{}.
        !           571: 
        !           572: Anything stored with \code{}storeindexl\edoc{} is being put into an array, so it
        !           573: is safe to treat it as a pointer. 
        !           574: \enddocs
        !           575: \begincode{18}
        !           576: \moddef{indexed fetch and store (word)}\endmoddef
        !           577:    (* fetchindexl(x,y,z) fetches a word:   y <- mem[x+2*(z-1)] *)
        !           578:    (* storeindexl(x,y,z) stores a word:    mem[y+2*(z-1)] <- x *)
        !           579: 
        !           580: fun fetchindexl(x,Direct y, Direct z) = 
        !           581:       (M.sll(Immed 1,z,my_arithtemp');
        !           582:        M.add(my_arithtemp',x,my_arithtemp');
        !           583:        M.lw(y, my_arithtemp,~2))
        !           584:   | fetchindexl(x,Direct y, Immed z) = M.lw(y, x, z+z-2)
        !           585:   | fetchindexl _ = ErrorMsg.impossible "fetchl result not register in mips"
        !           586: 
        !           587: fun storeindexl(Direct x,y, Immed 1) = M.sw(x,y,0)
        !           588:   | storeindexl(Direct x,y,Direct z) = 
        !           589:     (M.sll(Immed 1,z,my_arithtemp');
        !           590:      M.add(my_arithtemp',y,my_arithtemp');
        !           591:      M.sw(x, my_arithtemp,~2))
        !           592:   | storeindexl(Direct x,y,Immed z) = M.sw(x,y,z+z-2)
        !           593: 
        !           594:   | storeindexl(Direct _,_,Immedlab _) =
        !           595:         ErrorMsg.impossible "storeindexl(Direct _,_,Immedlab _) in mips"
        !           596: 
        !           597:   | storeindexl(Immedlab label,y,z) =
        !           598:     (M.move(Immedlab label,my_ptrtemp');
        !           599:      storeindexl(my_ptrtemp,y,z))
        !           600: 
        !           601:   | storeindexl(Immed constant,y,offset) =
        !           602:         (M.move(Immed constant,my_ptrtemp');
        !           603:          storeindexl(my_ptrtemp,y,offset))
        !           604: 
        !           605: \endcode
        !           606: \begincode{19}
        !           607: \moddef{DEBUG code}\endmoddef
        !           608: val fetchindexl = diag "fetchindexl" fetchindexl
        !           609: val storeindexl = diag "storeindexl" storeindexl
        !           610: 
        !           611: 
        !           612: \endcode
        !           613: \begindocs{20}
        !           614: The function \code{}three\edoc{} makes commutative three-operand
        !           615: instructions easier to call.
        !           616: All three operands become \code{}EA\edoc{}s, and it is enough if either of the
        !           617: first two operands is a register.
        !           618: \enddocs
        !           619: \begincode{21}
        !           620: \moddef{utility functions}\endmoddef
        !           621: fun three f (Direct x, ea, Direct y) = f(x,ea,y)
        !           622:   | three f (ea, Direct x, Direct y) = f(x,ea,y)
        !           623:   | three f _ =ErrorMsg.impossible "neither arg to three f is register in mips"
        !           624: 
        !           625: \endcode
        !           626: \begindocs{22}
        !           627: I assume that shifts are only ever done on arithmetic quantities,
        !           628: not pointers, so that I am justified in using \code{}my_arithtemp'\edoc{} to
        !           629: store intermediate values.  This is consistent with being unwilling
        !           630: to shift things matching \code{}Immedlab _\edoc{}.
        !           631: Appel agrees that pointers aren't shifted, as far as he can remember.
        !           632: \enddocs
        !           633: \begincode{23}
        !           634: \moddef{shifts}\endmoddef
        !           635: fun ashr(shamt, Direct op1, Direct result) = M.sra(shamt,op1,result)
        !           636:   | ashr(shamt, Immed op1, Direct result) = 
        !           637:         (M.move(Immed op1,my_arithtemp'); M.sra(shamt,my_arithtemp',result))
        !           638:   | ashr _ = ErrorMsg.impossible "ashr args don't match in mips"
        !           639: fun ashl(shamt, Direct op1, Direct result) = M.sll(shamt,op1,result)
        !           640:   | ashl(shamt, Immed op1, Direct result) = 
        !           641:         (M.move(Immed op1,my_arithtemp'); M.sll(shamt,my_arithtemp',result))
        !           642:   | ashl _ = ErrorMsg.impossible "ashl args don't match in mips"
        !           643: \endcode
        !           644: \begincode{24}
        !           645: \moddef{DEBUG code}\endmoddef
        !           646: val ashr = diag "ashr" ashr
        !           647: val ashl = diag "ashl" ashl
        !           648: 
        !           649: \endcode
        !           650: \begincode{25}
        !           651: \moddef{bitwise operations}\endmoddef
        !           652: val orb = three M.or
        !           653: val andb = three M.and'
        !           654: fun notb (a,b) = subl3(a, Immed ~1, b) (* ~1 - a == one's complement *)
        !           655: val xorb = three M.xor
        !           656: \endcode
        !           657: \begincode{26}
        !           658: \moddef{DEBUG code}\endmoddef
        !           659: val orb = diag "orb" orb
        !           660: val andb = diag "andb" andb
        !           661: val notb = diag "notb" notb
        !           662: val xorb = diag "xorb" xorb
        !           663: 
        !           664: 
        !           665: \endcode
        !           666: \begindocs{27}
        !           667: Subtraction may appear a bit odd.
        !           668: The MIPS machine instruction and  \code{}MIPSCODER.sub\edoc{} both subtract
        !           669: their second operand from their first operand.
        !           670: The VAX machine instruction and \code{}CMACHINE.subl3\edoc{} both subtract
        !           671: their first operand from their second operand.
        !           672: This will certainly lead to endless confusion.
        !           673: \enddocs
        !           674: \begincode{28}
        !           675: \moddef{arithmetic}\endmoddef
        !           676: val addl3 = three M.add
        !           677: 
        !           678: fun subl3(Immed k, x, y) = addl3(x, Immed(~k), y)
        !           679:   | subl3(Direct x, Direct y, Direct z) = M.sub(y,x,z)
        !           680:   | subl3(x, Immed k, dest) = 
        !           681:             (M.move(Immed k, my_arithtemp');
        !           682:              subl3(x, my_arithtemp, dest))
        !           683:   | subl3 _ = ErrorMsg.impossible "subl3 args don't match in mips"
        !           684: 
        !           685: \endcode
        !           686: \begindocs{29}
        !           687: We assume that any quantities being multiplied are arithmetic
        !           688: quantities, not pointers.
        !           689: \enddocs
        !           690: \begincode{30}
        !           691: \moddef{arithmetic}\endmoddef
        !           692: fun mull2(Direct x, Direct y) = M.mult(y,x,y)
        !           693:   | mull2(Immed x, Direct y) = (M.move(Immed x,my_arithtemp');
        !           694:                                 M.mult(y,my_arithtemp',y))
        !           695:   | mull2 _ = ErrorMsg.impossible "mull2 args don't match in mips"
        !           696: fun divl2(Direct x, Direct y) = M.div(y,x,y)
        !           697:   | divl2(Immed x, Direct y) = (M.move(Immed x,my_arithtemp');
        !           698:                                 M.div(y,my_arithtemp',y))
        !           699:   | divl2 _ = ErrorMsg.impossible "divl2 args don't match in mips"
        !           700: 
        !           701: \endcode
        !           702: \begincode{31}
        !           703: \moddef{DEBUG code}\endmoddef
        !           704: val addl3 = diag "addl3" addl3
        !           705: val subl3 = diag "subl3" subl3
        !           706: val mull2 = diag "mull2" mull2
        !           707: val divl2 = diag "divl2" divl2
        !           708: 
        !           709: 
        !           710: \endcode
        !           711: \begindocs{32}
        !           712: The Mips hardware detects two's complement integer overflow on 
        !           713: add and subtract instructions only.  
        !           714: The exception is not maskable (see the Mips book, page 5-18).
        !           715: At the moment we don't implement any overflow detection for multiplications
        !           716: or for left shifts.
        !           717: This has consequences only for coping with real constants and for
        !           718: compiling user programs.  
        !           719: \enddocs
        !           720: \begincode{33}
        !           721: \moddef{arithmetic and shifts with overflow detection}\endmoddef
        !           722: val addl3t = addl3
        !           723: val subl3t = subl3
        !           724: \endcode
        !           725: \begindocs{34}
        !           726: The Mips multiplies two 32-bit quantities to get a 64-bit result.
        !           727: That result fits in 32 bits if and only if the high-order word is zero or
        !           728: negative one, and it has the same sign as the low order word.
        !           729: Thus, we can add the sign bit of the low order word to the high order
        !           730: word, and we have overflow if and only if the result is nonzero.
        !           731: \enddocs
        !           732: \begincode{35}
        !           733: \moddef{arithmetic and shifts with overflow detection}\endmoddef
        !           734: fun mull2t(x,y as Direct y') = 
        !           735:     let val ok = M.newlabel()
        !           736:     in  mull2(x,y);
        !           737:         M.mfhi(my_arithtemp');
        !           738:         M.slt(y',Direct (Reg 0),my_ptrtemp'); (* 0 or 1 OK in pointer *)
        !           739:         M.add(my_arithtemp',my_ptrtemp,my_arithtemp');
        !           740:         M.beq(true,my_arithtemp',Reg 0,ok);    (* OK if not overflow *)
        !           741:         M.lui(my_arithtemp',32767);
        !           742:         M.add(my_arithtemp',my_arithtemp,my_arithtemp');  (* overflows *)
        !           743:         M.define(ok)
        !           744:     end
        !           745:   | mull2t _ = ErrorMsg.impossible "result of mull2t not register in mips"
        !           746: 
        !           747: \endcode
        !           748: \begincode{36}
        !           749: \moddef{DEBUG code}\endmoddef
        !           750: val addl3t = diag "addl3t" addl3t
        !           751: val subl3t = diag "subl3t" subl3t
        !           752: val mull2t = diag "mull2t" mull2t
        !           753: val ashlt = diag "ashlt" ashlt
        !           754: 
        !           755: 
        !           756: \endcode
        !           757: \begindocs{37}
        !           758: We hack \code{}ibranch\edoc{} to make sure it will only reverse once.
        !           759: It's easier than thinking.
        !           760: \enddocs
        !           761: \begincode{38}
        !           762: \moddef{branches}\endmoddef
        !           763: datatype condition = NEQ | EQL | LEQ | GEQ | LSS | GTR
        !           764: local 
        !           765: fun makeibranch reverse = 
        !           766: let
        !           767: fun ibranch (cond, Immed a, Immed b, Immedlab label) =
        !           768:             if (case cond of EQL => a=b | NEQ => a<>b | LSS => a<b |
        !           769:                              LEQ => a<=b | GTR => a>b | GEQ => a>=b)
        !           770:                 then M.beq(true,Reg 0, Reg 0, label) else ()
        !           771:   | ibranch (NEQ, Direct r, Direct s, Immedlab label) =
        !           772:                     M.beq(false, r, s, label)
        !           773:   | ibranch (NEQ, Direct r, x, Immedlab label) =
        !           774:                     (M.move(x, my_arithtemp');
        !           775:                      M.beq(false, r, my_arithtemp', label))
        !           776:   | ibranch (EQL, Direct r, Direct s, Immedlab label) =
        !           777:                     M.beq(true, r, s, label)
        !           778:   | ibranch (EQL, Direct r, x, Immedlab label) =
        !           779:                     (M.move(x, my_arithtemp');
        !           780:                      M.beq(true, r, my_arithtemp', label))
        !           781:   | ibranch (LSS, Direct r, x, Immedlab lab) =
        !           782:                 (M.slt(r,x,my_arithtemp');
        !           783:                  M.beq(false,Reg 0, my_arithtemp',lab))
        !           784:   | ibranch (GEQ, Direct r, x, Immedlab lab) =
        !           785:                 (M.slt(r,x,my_arithtemp'); 
        !           786:                  M.beq(true,Reg 0, my_arithtemp',lab))
        !           787:   | ibranch (GTR, x, Direct r, Immedlab lab) =
        !           788:                 (M.slt(r,x,my_arithtemp'); 
        !           789:                  M.beq(false,Reg 0, my_arithtemp',lab))
        !           790:   | ibranch (LEQ, x, Direct r, Immedlab lab) =
        !           791:                 (M.slt(r,x,my_arithtemp'); 
        !           792:                  M.beq(true,Reg 0, my_arithtemp',lab))
        !           793: (* These two cases added to prevent infinite reversal *)
        !           794:   | ibranch (GTR, Direct r, x, Immedlab lab) =
        !           795:                 (M.move(x, my_arithtemp');
        !           796:                  M.slt(my_arithtemp',Direct r,my_arithtemp');
        !           797:                  M.beq(false,Reg 0,my_arithtemp',lab))
        !           798:   | ibranch (LEQ, Direct r, x, Immedlab lab) =
        !           799:                 (M.move(x, my_arithtemp');
        !           800:                  M.slt(my_arithtemp',Direct r,my_arithtemp');
        !           801:                  M.beq(true,Reg 0,my_arithtemp',lab))
        !           802:   | ibranch (_, Immedlab _, Immedlab _, _) = 
        !           803:                 ErrorMsg.impossible "bad ibranch args 1 in mips"
        !           804:   | ibranch (_, Immedlab _, _, _) = 
        !           805:                 ErrorMsg.impossible "bad ibranch args 1a in mips"
        !           806:   | ibranch (_, _, Immedlab _, _) = 
        !           807:                 ErrorMsg.impossible "bad ibranch args 1b in mips"
        !           808:   | ibranch (_, _, _, Direct _) = 
        !           809:                 ErrorMsg.impossible "bad ibranch args 2 in mips"
        !           810:   | ibranch (_, _, _, Immed _) = 
        !           811:                 ErrorMsg.impossible "bad ibranch args 3 in mips"
        !           812:   | ibranch (cond, x, y, l) = 
        !           813:         let fun rev LEQ = GEQ
        !           814:               | rev GEQ = LEQ
        !           815:               | rev LSS = GTR
        !           816:               | rev GTR = LSS
        !           817:               | rev NEQ = NEQ
        !           818:               | rev EQL = EQL
        !           819:         in  if reverse then (makeibranch false) (rev cond, y,x,l) 
        !           820:             else ErrorMsg.impossible "infinite ibranch reversal in mips"
        !           821:         
        !           822:         end
        !           823: in ibranch
        !           824: end
        !           825: in
        !           826: val ibranch = makeibranch true
        !           827: end
        !           828:     
        !           829: \endcode
        !           830: \begincode{39}
        !           831: \moddef{branches}\endmoddef
        !           832: fun jmp (Direct r) = M.jump(r)
        !           833:   | jmp (Immedlab lab) = M.beq(true,Reg 0,Reg 0,lab)
        !           834:   | jmp (Immed i) = ErrorMsg.impossible "jmp (Immed i) in mips"
        !           835: 
        !           836: 
        !           837:         (* branch on bit set *)
        !           838: fun bbs (Immed k, Direct y, Immedlab label) =
        !           839:         (M.and'(y,Immed (Bits.lshift(1,k)),my_arithtemp');
        !           840:          M.beq(false,my_arithtemp',Reg 0,label))
        !           841:   | bbs _ = ErrorMsg.impossible "bbs args don't match in mips"
        !           842: 
        !           843: \endcode
        !           844: \begincode{40}
        !           845: \moddef{DEBUG code}\endmoddef
        !           846: val ibranch = diag "ibranch" ibranch
        !           847: val jmp = diag "jmp" jmp
        !           848: val bbs = diag "bbs" bbs
        !           849: 
        !           850: \endcode
        !           851: \begindocs{41}
        !           852: We decided not to include floating point registers in our galaxy of
        !           853: effective addresses.
        !           854: This means that floating point registers are used only at this level, and
        !           855: only to contain intermediate results.
        !           856: All operands and final results will be stored in memory, in the usual
        !           857: ML format (i.e. as 8-byte strings).
        !           858: 
        !           859: In fact, we can be much more strict than that, and claim that
        !           860: all floating point operands will live in FPR0 and FPR2, and that all 
        !           861: results will appear in FPR0.
        !           862: 
        !           863: We don't make a distinction between general-purpose and floating point
        !           864: registers; it's up to the instructions to know the difference.
        !           865: \enddocs
        !           866: \begincode{42}
        !           867: \moddef{floating point}\endmoddef
        !           868: val floatop1 = Reg 0
        !           869: val floatop2 = Reg 2
        !           870: val floatresult = Reg 0
        !           871: 
        !           872: \endcode
        !           873: \begindocs{43}
        !           874: One very common operation is to take the result of a floating point
        !           875: operation and put it into a fresh record, newly allocated on the heap.
        !           876: This operation is traditionally called \code{}finish_real\edoc{}, and it takes one
        !           877: argument, the destination register for the new value.
        !           878: All real values on the heap are labelled as 8-byte strings.
        !           879: To store a floating point, we store the least significant
        !           880: word in the lower address, but we store the most significant word
        !           881: first, in case that triggers a garbage collection.
        !           882: \enddocs
        !           883: \begincode{44}
        !           884: \moddef{floating point}\endmoddef
        !           885: val real_tag = Immed(8*System.Tags.power_tags + System.Tags.tag_string)
        !           886: 
        !           887: fun store_float(Reg n,ea,offset) = 
        !           888:     if n mod 2 <> 0 then ErrorMsg.impossible "bad float reg in mips"
        !           889:     else (M.swc1(Reg (n+1),ea,offset+4);M.swc1(Reg n,ea,offset))
        !           890: 
        !           891: fun finish_real (Direct result) = (
        !           892:     store_float(floatresult,dataptr,4);
        !           893:     M.move(real_tag,my_arithtemp');
        !           894:     M.sw(my_arithtemp',dataptr,0);
        !           895:     M.add(dataptr',Immed 4,result);
        !           896:     M.add(dataptr',Immed 12,dataptr'))
        !           897:   | finish_real _ = 
        !           898:      ErrorMsg.impossible "ptr to result of real operation not register in mips"
        !           899: 
        !           900: \endcode
        !           901: \begindocs{45}
        !           902: Loading a floating point quantity is analogous.
        !           903: \enddocs
        !           904: \begincode{46}
        !           905: \moddef{floating point}\endmoddef
        !           906: fun load_float(Reg dest,src,offset) =
        !           907:     if dest mod 2 <> 0 then ErrorMsg.impossible "bad float reg in mips"
        !           908:     else (M.lwc1(Reg dest,src,offset); M.lwc1(Reg (dest+1),src,offset+4))
        !           909: 
        !           910: \endcode
        !           911: \begindocs{47}
        !           912: Now we can do a general two- and three-operand floating point operationa.
        !           913: The only parameter is the function in \code{}MipsCoder\edoc{} that
        !           914: emits the floating point register operation.
        !           915: \enddocs
        !           916: \begincode{48}
        !           917: \moddef{floating point}\endmoddef
        !           918: fun two_float instruction (op1,result) = (
        !           919:     load_float(floatop1,op1,0);
        !           920:     instruction(floatop1,floatresult);
        !           921:     finish_real(result))
        !           922: 
        !           923: fun three_float instruction (op1,op2,result) = (
        !           924:     load_float(floatop1,op1,0);
        !           925:     load_float(floatop2,op2,0);
        !           926:     instruction(floatop1,floatop2,floatresult);
        !           927:     finish_real(result))
        !           928: 
        !           929: \endcode
        !           930: \begindocs{49}
        !           931: That takes care of everything except branch
        !           932: \enddocs
        !           933: \begincode{50}
        !           934: \moddef{floating point}\endmoddef
        !           935: val mnegg = two_float M.neg_double
        !           936: val mulg3 = three_float M.mul_double
        !           937: val divg3 = three_float M.div_double
        !           938: val addg3 = three_float M.add_double
        !           939: val subg3 = three_float M.sub_double
        !           940: 
        !           941: 
        !           942: \endcode
        !           943: \begindocs{51}
        !           944: The Mips doesn't provide all six comparisons in hardware, so the
        !           945: next function does the comparison using only less than and equal.
        !           946: The result tells \code{}bcop1\edoc{} whether to branch on condition true
        !           947: or condition false.
        !           948: \enddocs
        !           949: \begincode{52}
        !           950: \moddef{floating point compare}\endmoddef
        !           951: fun compare(LSS,op1,op2) = (M.slt_double(op1,op2); true)
        !           952:   | compare(GEQ,op1,op2) = (M.slt_double(op1,op2); false)
        !           953:   | compare(EQL,op1,op2) = (M.seq_double(op1,op2); true)
        !           954:   | compare(NEQ,op1,op2) = (M.seq_double(op1,op2); false)
        !           955:   | compare(LEQ,op1,op2) = compare(GEQ,op2,op1)
        !           956:   | compare(GTR,op1,op2) = compare(LSS,op2,op1)
        !           957: \endcode
        !           958: \begincode{53}
        !           959: \moddef{floating point}\endmoddef
        !           960: local
        !           961:     \LA{}floating point compare\RA{}
        !           962: in
        !           963:     fun gbranch (cond, op1, op2, Immedlab label) = (
        !           964:             load_float(floatop1,op1,0);
        !           965:             load_float(floatop2,op2,0);
        !           966:             M.bcop1(compare(cond,floatop1,floatop2),label))
        !           967:       | gbranch _ = ErrorMsg.impossible "insane gbranch target in mips.nw"
        !           968: end
        !           969:         
        !           970: 
        !           971: \endcode
        !           972: \begindocs{54}
        !           973: When a function begins execution, it checks to make sure there is sufficient
        !           974: memory available that it can do all its allocation.
        !           975: generic does this by calling \code{}checkLimit : int -> unit\edoc{}.
        !           976: At the moment, we implement this check by doing a store,
        !           977: taking advantage of the virtual memory hardware, which will cause an exception
        !           978: if there's not enough memory.
        !           979: Later we will replace this store with a check against a limit register,
        !           980: which will avoid virtual memory hacking and which will have advantages
        !           981: for concurrency.
        !           982: \enddocs
        !           983: \begincode{55}
        !           984: \moddef{memory check}\endmoddef
        !           985: fun checkLimit max_allocation = M.sw(Reg 0, dataptr, max_allocation-4)
        !           986:                               (* store zero in last location to be used *)
        !           987: 
        !           988: \endcode
        !           989: \begindocs{56}
        !           990: These two functions have null implementations.
        !           991: \code{}beginStdFn\edoc{} is necessary only on the SPARC, since that machine needs to get 
        !           992: its program counter, and it is awkward to do so in the middle of a function.
        !           993: 
        !           994: \code{}profile\edoc{} is a mysterious relic.
        !           995: \enddocs
        !           996: \begincode{57}
        !           997: \moddef{omitted functions}\endmoddef
        !           998: fun beginStdFn _ = ()           (* do nothing, just like the Vax *)
        !           999: 
        !          1000: fun profile(i,incr) = ()
        !          1001: 
        !          1002: \endcode
        !          1003: \filename{mipscoder.nw}
        !          1004: \begindocs{0}
        !          1005: \input verbatim
        !          1006: \input itemize
        !          1007: \chapter{A small assembler for the MIPS}
        !          1008: This is part of the code generator for Standard ML of New Jersey.
        !          1009: We generate code in several stages.
        !          1010: This is nearly the lowest stage; it is like an assembler.
        !          1011: The user can call any function in the MIPSCODER signature.
        !          1012: Each one corresponds to an assembler pseudo-instruction.
        !          1013: Most correspond to single MIPS instructions.
        !          1014: The assembler remembers all the instructions that have been 
        !          1015: requested, and when \code{}codegen\edoc{} is called it generates MIPS
        !          1016: code for them.
        !          1017: 
        !          1018: Some other structure will be able to use the MIPS structure to implement
        !          1019: a \code{}CMACHINE\edoc{}, which is the abstract machine that ML thinks it is running
        !          1020: on.
        !          1021: (What really happens is a functor maps some structure 
        !          1022: implementing \code{}MIPSCODER\edoc{} to a different structure implementing 
        !          1023: \code{}CMACHINE\edoc{}.)
        !          1024: 
        !          1025: {\em Any function using a structure of this signature must avoid
        !          1026: touching registers 1~and~31.
        !          1027: Those registers are reserved for use by the assembler.}
        !          1028: 
        !          1029: \enddocs
        !          1030: \begindocs{1}
        !          1031: Here is the signature of the assembler, \code{}MIPSCODER\edoc{}.
        !          1032: It can be extracted from this file by
        !          1033: $$\hbox{\tt notangle mipsinstr.nw -Rsignature}.$$
        !          1034: \enddocs
        !          1035: \begincode{2}
        !          1036: \moddef{signature}\endmoddef
        !          1037: signature MIPSCODER = sig
        !          1038: 
        !          1039: (* Assembler for the MIPS chip *)
        !          1040: 
        !          1041: eqtype Label
        !          1042: datatype Register = Reg of int
        !          1043:     (* Registers 1 and 31 are reserved for use by this assembler *)
        !          1044: datatype EA = Direct of Register | Immed of int | Immedlab of Label
        !          1045:                                 (* effective address *)
        !          1046: 
        !          1047: structure M : sig
        !          1048: 
        !          1049:     (* Emit various constants into the code *)
        !          1050: 
        !          1051:     val emitstring : string -> unit     (* put a literal string into the
        !          1052:                                            code (null-terminated?) and
        !          1053:                                            extend with nulls to 4-byte 
        !          1054:                                            boundary. Just chars, no 
        !          1055:                                            descriptor or length *)
        !          1056:     val realconst : string -> unit      (* emit a floating pt literal *)
        !          1057:                                                 (* NOT RIGHT YET *)
        !          1058:     val emitlong : int -> unit          (* emit a 4-byte integer literal *)
        !          1059: 
        !          1060: 
        !          1061:     (* Label bindings and emissions *)
        !          1062: 
        !          1063:     val newlabel : unit -> Label        (* new, unbound label *)
        !          1064:     val define : Label -> unit          (* cause the label to be bound to
        !          1065:                                            the code about to be generated *)
        !          1066:     val emitlab : int * Label -> unit   (* L3: emitlab(k,L2) is equivalent to
        !          1067:                                            L3: emitlong(k+L2-L3) *)
        !          1068: 
        !          1069:     (* Control flow instructions *)
        !          1070: 
        !          1071:     val slt : Register * EA * Register -> unit
        !          1072:                 (* (operand1, operand2, result) *)
        !          1073:                                         (* set less than family *)
        !          1074:     val beq : bool * Register * Register * Label -> unit
        !          1075:                 (* (beq or bne, operand1, operand2, branch address) *)
        !          1076:                                         (* branch equal/not equal family *)
        !          1077:     
        !          1078:     val jump : Register -> unit         (* jump register instruction *)
        !          1079: 
        !          1080:     val slt_double : Register * Register -> unit
        !          1081:                                         (* floating pt set less than *)
        !          1082:     val seq_double : Register * Register -> unit
        !          1083:                                         (* floating pt set equal *)
        !          1084:     val bcop1 : bool * Label -> unit    (* floating pt conditional branch *)
        !          1085: 
        !          1086: 
        !          1087:     (* Arithmetic instructions *)
        !          1088:             (* arguments are (operand1, operand2, result) *)
        !          1089: 
        !          1090:     val add : Register * EA * Register -> unit
        !          1091:     val and' : Register * EA * Register -> unit
        !          1092:     val or : Register * EA * Register -> unit
        !          1093:     val xor : Register * EA * Register -> unit
        !          1094:     val sub : Register * Register * Register -> unit
        !          1095:     val div : Register * Register * Register -> unit
        !          1096:     val mult : Register * Register * Register -> unit
        !          1097:     val mfhi : Register -> unit         (* high word of 64-bit multiply *)
        !          1098:     
        !          1099:     (* Floating point arithmetic *)
        !          1100: 
        !          1101:     val neg_double : Register * Register -> unit
        !          1102:     val mul_double : Register * Register * Register -> unit
        !          1103:     val div_double : Register * Register * Register -> unit
        !          1104:     val add_double : Register * Register * Register -> unit
        !          1105:     val sub_double : Register * Register * Register -> unit
        !          1106: 
        !          1107:     (* Move pseudo-instruction :  move(src,dest) *)
        !          1108: 
        !          1109:     val move : EA * Register -> unit
        !          1110: 
        !          1111:     (* Load and store instructions *)
        !          1112:             (* arguments are (destination, source address, offset) *)
        !          1113:  
        !          1114:     val lbu  : Register * EA * int -> unit (* bytes *)
        !          1115:     val sb  : Register * EA * int -> unit
        !          1116:     val lw  : Register * EA * int -> unit  (* words *)
        !          1117:     val sw  : Register * EA * int -> unit
        !          1118:     val lwc1: Register * EA * int -> unit  (* floating point coprocessor *)
        !          1119:     val swc1: Register * EA * int -> unit
        !          1120:     val lui : Register * int -> unit
        !          1121: 
        !          1122:     (* Shift instructions *)
        !          1123:             (* arguments are (shamt, operand, result) *)
        !          1124:             (* shamt as Immedlab _ is senseless *)
        !          1125: 
        !          1126:     val sll : EA * Register * Register -> unit
        !          1127:     val sra : EA * Register * Register -> unit
        !          1128:     
        !          1129: 
        !          1130:     (* Miscellany *)
        !          1131: 
        !          1132:     val align : unit -> unit            (* cause next data to be emitted on
        !          1133:                                            a 4-byte boundary *)
        !          1134:     val mark : unit -> unit             (* emit a back pointer, 
        !          1135:                                            also called mark *)
        !          1136: 
        !          1137:     val comment : string -> unit
        !          1138: 
        !          1139:   end (* signature of structure M *)
        !          1140: 
        !          1141:   val codegen : (int * int -> unit) * (int -> string -> unit) 
        !          1142:                         * (string -> unit) -> unit
        !          1143: 
        !          1144:   val codestats : outstream -> unit     (* write statistics on stream *)
        !          1145: 
        !          1146: end (* signature MIPSCODER *)
        !          1147: \endcode
        !          1148: \begindocs{3}
        !          1149: The basic strategy of the implementation is to hold on, via the \code{}kept\edoc{}
        !          1150: pointer, to the list of instructions generated so far.
        !          1151: We use \code{}instr\edoc{} for the type of an instruction, so
        !          1152: \code{}kept\edoc{} has type \code{}instr list ref\edoc{}.
        !          1153: 
        !          1154: The instructions will be executed in the following order: the 
        !          1155: instruction at the head of the \code{}!kept\edoc{} is executed last.
        !          1156: This enables us to accept calls in the order of execution but
        !          1157: add the new instruction(s) to the list in constant time.
        !          1158: 
        !          1159: 
        !          1160: \enddocs
        !          1161: \begindocs{4}
        !          1162: 
        !          1163: We structure the instruction stream a little bit by factoring
        !          1164: out the difference between multiplication and division; these
        !          1165: operations are treated identically in that the result has to be
        !          1166: fetched out of the MIPS' LO register.
        !          1167: 
        !          1168: We also factor the different of load and store instructions that can
        !          1169: occur: we have load byte, load word, and load to coprocessor (floating point).
        !          1170: \enddocs
        !          1171: \begincode{5}
        !          1172: \moddef{types auxiliary to \code{}instr\edoc{}}\endmoddef
        !          1173: datatype size = Byte | Word | Floating
        !          1174: datatype muldiv = MULT | DIV
        !          1175: \endcode
        !          1176: \begindocs{6}
        !          1177: 
        !          1178: Here are the instructions that exist.
        !          1179: We list them in more or less the order of the MIPSCODER signature.
        !          1180: \enddocs
        !          1181: \begincode{7}
        !          1182: \moddef{definition of \code{}instr\edoc{}}\endmoddef
        !          1183: \LA{}types auxiliary to \code{}instr\edoc{}\RA{}
        !          1184: 
        !          1185: datatype instr = 
        !          1186:     STRINGCONST of string               (* constants *)
        !          1187:   | REALCONST of string
        !          1188:   | EMITLONG of int
        !          1189: 
        !          1190:   | DEFINE of Label                     (* labels *)
        !          1191:   | EMITLAB of int * Label
        !          1192: 
        !          1193:   | SLT of Register * EA * Register     (* control flow *)
        !          1194:   | BEQ of bool * Register * Register * Label
        !          1195:   | JUMP of Register 
        !          1196:   | SLT_D of Register * Register
        !          1197:   | SEQ_D of Register * Register
        !          1198:   | BCOP1 of bool * Label
        !          1199: 
        !          1200:   | NOP (* no-op for delay slot *)
        !          1201: 
        !          1202:   | ADD of Register * EA * Register     (* arithmetic *)
        !          1203:   | AND of Register * EA * Register
        !          1204:   | OR  of Register * EA * Register
        !          1205:   | XOR of Register * EA * Register
        !          1206:   | SUB of Register * Register * Register
        !          1207:   | MULDIV of muldiv * Register * Register
        !          1208:   | MFLO of Register    (* mflo instruction used with
        !          1209:                            64-bit multiply and divide *)
        !          1210:   | MFHI of Register
        !          1211: 
        !          1212:   | NEG_D of Register * Register
        !          1213:   | MUL_D of Register * Register * Register
        !          1214:   | DIV_D of Register * Register * Register
        !          1215:   | ADD_D of Register * Register * Register
        !          1216:   | SUB_D of Register * Register * Register
        !          1217: 
        !          1218:   | MOVE of EA * Register    (* put something into a register *)
        !          1219:   | LDI_32 of int * Register (* load in a big immediate constant (>16 bits) *)
        !          1220:   | LUI of Register * int    (* Mips lui instruction *)
        !          1221: 
        !          1222:   | LOAD of size * Register * EA * int  (* load and store *)
        !          1223:   | STORE  of size * Register * EA * int
        !          1224: 
        !          1225:   | SLL of EA * Register * Register     (* shift *)
        !          1226:   | SRA of EA * Register * Register
        !          1227: 
        !          1228:   | COMMENT of string                   (* generates nothing *)
        !          1229:   | MARK                                (* a backpointer *)
        !          1230: \endcode
        !          1231: \begindocs{8}
        !          1232: 
        !          1233: Here is the code that handles the generated stream, \code{}kept\edoc{}.
        !          1234: It begins life as \code{}nil\edoc{} and returns to \code{}nil\edoc{} every time code is
        !          1235: generated.
        !          1236: The function \code{}keep\edoc{} is a convenient way of adding a single \code{}instr\edoc{} to
        !          1237: the list; it's very terse.
        !          1238: Sometimes we have to add multiple \code{}instr\edoc{}s; then we use \code{}keeplist\edoc{}.
        !          1239: We also define a function \code{}delay\edoc{} that is just like a \code{}keep\edoc{} but
        !          1240: it adds a NOP in the delay slot.
        !          1241: \enddocs
        !          1242: \begincode{9}
        !          1243: \moddef{instruction stream and its functions}\endmoddef
        !          1244:   val kept = ref nil : instr list ref
        !          1245:   fun keep f a = kept := f a :: !kept
        !          1246:   fun delay f a = kept := NOP :: f a :: !kept
        !          1247:   fun keeplist l = kept := l @ !kept
        !          1248: \endcode
        !          1249: \begincode{10}
        !          1250: \moddef{reinitialize \code{}kept\edoc{}}\endmoddef
        !          1251:   kept := nil
        !          1252: \endcode
        !          1253: \begindocs{11}
        !          1254: 
        !          1255: \subsection{Exporting functions for \code{}MIPSCODER\edoc{}}
        !          1256: We now know enough to implement most of the functions called for in
        !          1257: \code{}MIPSCODER\edoc{}.
        !          1258: We still haven't decided on an implementation of labels,
        !          1259: and there is one subtlety in multiplication and division,
        !          1260: but the rest is set.
        !          1261: \enddocs
        !          1262: \begincode{12}
        !          1263: \moddef{\code{}MIPSCODER\edoc{} functions}\endmoddef
        !          1264:   val emitstring = keep STRINGCONST     (* literals *)
        !          1265:   val realconst = keep REALCONST
        !          1266:   val emitlong = keep EMITLONG
        !          1267: 
        !          1268:   \LA{}label functions\RA{}                   (* labels *)
        !          1269: 
        !          1270:   val slt = keep SLT                    (* control flow *)
        !          1271:   val beq = delay BEQ
        !          1272:   val jump = delay JUMP
        !          1273:   val slt_double = delay SLT_D
        !          1274:   val seq_double = delay SEQ_D
        !          1275:   val bcop1 = delay BCOP1
        !          1276: 
        !          1277:   val add = keep ADD                    (* arithmetic *)
        !          1278:   val and' = keep AND
        !          1279:   val or = keep OR
        !          1280:   val xor = keep XOR
        !          1281:   val op sub = keep SUB
        !          1282:   \LA{}multiplication and division functions\RA{}
        !          1283: 
        !          1284:   val neg_double = keep NEG_D
        !          1285:   val mul_double = keep MUL_D
        !          1286:   val div_double = keep DIV_D
        !          1287:   val add_double = keep ADD_D
        !          1288:   val sub_double = keep SUB_D
        !          1289: 
        !          1290:   val move = keep MOVE
        !          1291: 
        !          1292:   fun lbu (a,b,c) = delay LOAD (Byte,a,b,c) (* load and store *)
        !          1293:   fun lw (a,b,c)  = delay LOAD (Word,a,b,c)
        !          1294:   fun lwc1 (a,b,c)  = delay LOAD (Floating,a,b,c)
        !          1295:   fun sb (a,b,c)  = keep STORE (Byte,a,b,c)
        !          1296:   fun sw (a,b,c)  = keep STORE (Word,a,b,c)
        !          1297:   fun swc1 (a,b,c)  = delay STORE (Floating,a,b,c)
        !          1298:   val lui = keep LUI
        !          1299: 
        !          1300:   val sll = keep SLL                    (* shift *)
        !          1301:   val sra = keep SRA
        !          1302: 
        !          1303:   fun align() = ()                      (* never need to align on MIPS *)
        !          1304:   val mark = keep (fn () => MARK)
        !          1305:   val comment = keep COMMENT
        !          1306: \endcode
        !          1307: \begindocs{13}
        !          1308: 
        !          1309: Multiplication and division have a minor complication; the
        !          1310: result has to be fetched from the LO register.
        !          1311: \enddocs
        !          1312: \begincode{14}
        !          1313: \moddef{multiplication and division functions}\endmoddef
        !          1314:   fun muldiv f (a,b,c) = keeplist [MFLO c, MULDIV (f,a,b)]
        !          1315:   val op div = muldiv DIV
        !          1316:   val mult = muldiv MULT
        !          1317:   val mfhi = keep MFHI
        !          1318: \endcode
        !          1319: \begindocs{15}
        !          1320: 
        !          1321: For now, labels are just pointers to integers.
        !          1322: During code generation, those integers will be set to positions
        !          1323: in the instruction stream, and then they'll be useful as addresses
        !          1324: relative to the program counter pointer (to be held in \code{}Reg pcreg\edoc{}).
        !          1325: \enddocs
        !          1326: \begincode{16}
        !          1327: \moddef{definition of \code{}Label\edoc{}}\endmoddef
        !          1328:   type Label = int ref
        !          1329: \endcode
        !          1330: \begincode{17}
        !          1331: \moddef{label functions}\endmoddef
        !          1332:   fun newlabel () = ref 0
        !          1333:   val define = keep DEFINE
        !          1334:   val emitlab = keep EMITLAB
        !          1335: \endcode
        !          1336: \begindocs{18}
        !          1337: 
        !          1338: Here's the overall plan of this structure:
        !          1339: \enddocs
        !          1340: \begincode{19}
        !          1341: \moddef{*}\endmoddef
        !          1342: structure MipsCoder : MIPSCODER = struct
        !          1343: 
        !          1344:   \LA{}definition of \code{}Label\edoc{}\RA{}
        !          1345: 
        !          1346:   datatype Register = Reg of int
        !          1347: 
        !          1348:   datatype EA = Direct of Register
        !          1349:               | Immed of int
        !          1350:               | Immedlab of Label
        !          1351: 
        !          1352:   \LA{}definition of \code{}instr\edoc{}\RA{}
        !          1353: 
        !          1354:   \LA{}instruction stream and its functions\RA{}
        !          1355:   
        !          1356:   structure M = struct
        !          1357:     \LA{}\code{}MIPSCODER\edoc{} functions\RA{}
        !          1358:   end
        !          1359: 
        !          1360:   open M
        !          1361: 
        !          1362:   \LA{}functions that assemble \code{}instr\edoc{}s into code\RA{}
        !          1363: 
        !          1364:   \LA{}statistics\RA{}
        !          1365: 
        !          1366: end (* MipsInstr *)
        !          1367: \endcode
        !          1368: \begindocs{20}
        !          1369: \subsection{Sizes of \code{}instr\edoc{}s}
        !          1370: Now let's consider the correspondence between our \code{}instr\edoc{} type and the
        !          1371: actual MIPS instructions we intend to emit.
        !          1372: One important problem to solve is figuring out how big things are, 
        !          1373: so that we know what addresses to generate for the various labels.
        !          1374: We will also want to know what address is currently stored in the program
        !          1375: counter regsiter (\code{}pcreg\edoc{}),
        !          1376: because we'll need to know when something is close 
        !          1377: enough that we can use a sixteen-bit address relative to that register.
        !          1378: The kind of address we can use will determine how big things are.
        !          1379: 
        !          1380: We'll rearrange the code so that we have a list of \code{}ref int * instr\edoc{} pairs,
        !          1381: where the \code{}ref int\edoc{} stores the position in the list. 
        !          1382: (Positions start at zero.)
        !          1383: Since in the MIPS all instructions are the same size, we measure
        !          1384: position as number of instructions.
        !          1385: While we're at it, we reverse the list so that the head will execute first,
        !          1386: then the rest of the list.
        !          1387: 
        !          1388: We begin with each position set to zero, and make a pass over the list 
        !          1389: trying to set the value of each position. 
        !          1390: We do this by estimating the size of (number of MIPS instructions 
        !          1391: generated for) each \code{}instr\edoc{}.
        !          1392: Since there are forward references, we may not have all the distances right
        !          1393: the first time, so we have to make a second pass.
        !          1394: But during this second pass we could find that something is further
        !          1395: away than we thought, and we have to switch from using a pc-relative mode to
        !          1396: something else (or maybe grab the new pc?), which changes the size again,
        !          1397: and moves things even further away.
        !          1398: Because we can't control this process, we just keep making passes over the
        !          1399: list until the process quiesces (we get the same size twice).
        !          1400: 
        !          1401: In order to guarantee termination, we have to make sure later passes only 
        !          1402: increase the sizes of things.
        !          1403: This is sufficient since there is a maximum number of MIPS instructions
        !          1404: we can generate for each \code{}instr\edoc{}.
        !          1405: 
        !          1406: 
        !          1407: While we're at it, we might want to complicate things by making the function
        !          1408: that does the passes also emit code.
        !          1409: For a single pass we hand an optional triple of emitters, the initial position,
        !          1410: an \code{}int option\edoc{} for the program counter pointer (if known), and the
        !          1411: instructions.
        !          1412: 
        !          1413: 
        !          1414: 
        !          1415: I'm not sure what explains the use of the \code{}ref int\edoc{} to track the position,
        !          1416: instead of just an \code{}int\edoc{}---it might be a desire to avoid the
        !          1417: overhead of creating a bunch of new objects, or it might be really hard
        !          1418: to do the passes cheaply.
        !          1419: It should think a variation on \code{}map\edoc{} would do the job, but maybe I'm
        !          1420: missing something.
        !          1421: 
        !          1422: \enddocs
        !          1423: \begindocs{21}
        !          1424: \code{}emitters\edoc{} is actually a triple \code{}emit,emit_string,emit_real\edoc{}.
        !          1425: \code{}emit : int * int -> unit\edoc{} emits one instruction, 
        !          1426: and \code{}emit_string : int -> string -> unit\edoc{} emits a string constant.
        !          1427: \code{}emit_string\edoc{} could be specified as a function of \code{}emit\edoc{},
        !          1428: but the nature of the function would depend on whether the target
        !          1429: machine was little-endian or big-endian, and we don't want to have
        !          1430: that dependency built in.
        !          1431: \code{}emit_real : string -> unit\edoc{} emits two words corresponding to an IEEE
        !          1432: floating point constant in string form (e.g. \code{}"3.14159"\edoc{}).
        !          1433: In principle, it can always be derived from \code{}emit_word\edoc{}, but it's
        !          1434: easier to pass it in because then we can use John Reppy's code;
        !          1435: see the \code{}MipsReal\edoc{} functor for more details, as well as
        !          1436: \code{}mipsglue.sml\edoc{}.
        !          1437: 
        !          1438: 
        !          1439:  \code{}instrs\edoc{} is the
        !          1440: list of instructions (in execute-head-last order).
        !          1441: 
        !          1442: The second argument to \code{}pass\edoc{} indicates for what instructions code
        !          1443: is to be generated.
        !          1444: It is a record (position of next instruction, program counter pointer if any,
        !          1445: remaining instructions to generate [with positions]).
        !          1446: 
        !          1447: \indent \code{}prepare\edoc{} produces two results: the instruction stream with
        !          1448: size pointers added, and the total size of code to be generated.
        !          1449: We add the total size because that is the only way to find the number
        !          1450: of \code{}bltzal\edoc{}s, which are implicit in the instruction stream.
        !          1451: 
        !          1452: \enddocs
        !          1453: \begincode{22}
        !          1454: \moddef{assembler}\endmoddef
        !          1455: fun prepare instrs =
        !          1456:  let fun add_positions(done, inst::rest) =  
        !          1457:                  add_positions( (ref 0, inst) :: done, rest)
        !          1458:        | add_positions(done, nil) = done
        !          1459: 
        !          1460:      val instrs' = add_positions(nil, instrs) (* reverse and add \code{}ref int\edoc{}s*)
        !          1461: 
        !          1462:      fun passes(oldsize) = 
        !          1463:                 (* make passes with no emission until size is stable*)
        !          1464:         let val size = pass NONE (0,NONE,instrs')
        !          1465:         in  if size=oldsize then size
        !          1466:             else passes size
        !          1467:         end
        !          1468:   in \{size = passes 0, stream = instrs'\}
        !          1469:   end
        !          1470: 
        !          1471: fun assemble emitters instrs =
        !          1472:         pass (SOME emitters) (0,NONE,#stream (prepare instrs))
        !          1473: 
        !          1474: \endcode
        !          1475: \begincode{23}
        !          1476: \moddef{functions that assemble \code{}instr\edoc{}s into code}\endmoddef
        !          1477: fun get (SOME x) = x 
        !          1478:   | get NONE = ErrorMsg.impossible "missing pcptr in mipscoder"
        !          1479: 
        !          1480: \LA{}\code{}pcptr\edoc{} functions\RA{}
        !          1481: \LA{}single pass\RA{}
        !          1482: \LA{}assembler\RA{}
        !          1483: 
        !          1484: fun codegen emitters = (
        !          1485:     assemble emitters (!kept);
        !          1486:     \LA{}reinitialize \code{}kept\edoc{}\RA{}
        !          1487:     )
        !          1488: \endcode
        !          1489: \begindocs{24}
        !          1490: 
        !          1491: The program counter pointer is a device that enables us to to addressing
        !          1492: relative to the pcp register, register 31.
        !          1493: The need for it arises when we want to access a data element which we know
        !          1494: only by its label.
        !          1495: The labels give us addresses relative to the beginning of the function,
        !          1496: but we can only use addresses relative to some register.
        !          1497: The answer is to set register~31 with a \code{}bltzal\edoc{} instruction,
        !          1498: then use that for addressing.
        !          1499: 
        !          1500: The function \code{}needs_a_pcptr\edoc{} determines when it is necessary
        !          1501: to have a known value in register~31.
        !          1502: That is, we need the program counter pointer
        !          1503: \itemize
        !          1504: \item 
        !          1505: at \code{}NOP\edoc{} for a reason to be named later?
        !          1506: \item
        !          1507: at any operation that uses an effective address that refers to a label
        !          1508: (since all labels have to be relative to the program counter).
        !          1509: \item
        !          1510: BEQ's and BCOP1's to very far away, 
        !          1511: since we have to compute the address for a JUMP 
        !          1512: knowing the value of the program counter pointer.
        !          1513: \enditemize
        !          1514: \enddocs
        !          1515: \begincode{25}
        !          1516: \moddef{\code{}pcptr\edoc{} functions}\endmoddef
        !          1517: fun needs_a_pcptr(_,SLT(_,Immedlab _,_)) = true
        !          1518:   | needs_a_pcptr(_,ADD(_,Immedlab _,_)) = true
        !          1519:   | needs_a_pcptr(_,AND(_,Immedlab _,_)) = true
        !          1520:   | needs_a_pcptr(_,OR(_,Immedlab _,_)) = true
        !          1521:   | needs_a_pcptr(_,XOR(_,Immedlab _,_)) = true
        !          1522:   | needs_a_pcptr(_,MOVE(Immedlab _,_)) = true
        !          1523:   | needs_a_pcptr(_,LOAD(_,_,Immedlab _,_)) = true
        !          1524:   | needs_a_pcptr(_,STORE(_,_,Immedlab _,_)) = true
        !          1525:   | needs_a_pcptr(_,SLL(Immedlab _,_,_)) = true
        !          1526:   | needs_a_pcptr(_,SRA(Immedlab _,_,_)) = true
        !          1527:   | needs_a_pcptr(1, BEQ _) = false  (* small BEQ's dont need pcptr *)
        !          1528:   | needs_a_pcptr(_, BEQ _) = true   (* but large ones do *)
        !          1529:   | needs_a_pcptr(1, BCOP1 _) = false  (* small BCOP1's dont need pcptr *)
        !          1530:   | needs_a_pcptr(_, BCOP1 _) = true   (* but large ones do *)
        !          1531:   | needs_a_pcptr _ = false
        !          1532: \endcode
        !          1533: \begindocs{26}
        !          1534: 
        !          1535: Creating the program counter pointer once, with a \code{}bltzal\edoc{}, is not
        !          1536: enough; we have to invalidate the program counter pointer at every
        !          1537: label, since control could arrive at the label from God knows where, and
        !          1538: therefore we don't know what the program counter pointer is.
        !          1539: 
        !          1540: We use the function \code{}makepcptr\edoc{} to create a new program counter pointer
        !          1541: ``on the fly'' while generating code for other \code{}instrs\edoc{}.
        !          1542: (I chose not to create a special \code{}instr\edoc{} for \code{}bltzal\edoc{}, which I
        !          1543: could have inserted at appropriate points in the instruction stream.)
        !          1544: To try and find an odd bug, I'm adding no-ops after each \code{}bltzal\edoc{}.
        !          1545: I don't really believe they're necessary.
        !          1546: 
        !          1547: The function \code{}gen\edoc{}, which generates the instructions (or computes
        !          1548: their size), takes three arguments.
        !          1549: Third: the list of instructions to be generated (paired with pointers
        !          1550: to their sizes); first: the position (in words) at which to generate 
        !          1551: those instructions;  second: the current value of the program counter
        !          1552: pointer (register~31), if known.
        !          1553: 
        !          1554: The mutual recursion between \code{}gen\edoc{} and \code{}makepcptr\edoc{} maintains
        !          1555: the program counter pointer.
        !          1556: \code{}gen\edoc{} invalidates it at labels, and calls \code{}makepcptr\edoc{} to create a valid
        !          1557: one when necessary (as determined by \code{}needs_a_pcptr\edoc{}).
        !          1558: \enddocs
        !          1559: \begincode{27}
        !          1560: \moddef{single pass}\endmoddef
        !          1561: fun pass emitters =
        !          1562: let fun makepcptr(i,x) = 
        !          1563:          (* may need to emit NOP for delay slot if next instr is branch *)
        !          1564:   let val size = case x of ((_,BEQ _)::rest) => 2 
        !          1565:                          | ((_,BCOP1 _)::rest) => 2 
        !          1566:                          | _ => 1
        !          1567:   in  case emitters of NONE                     => () 
        !          1568:                      | SOME (emit, _, _ ) => (
        !          1569:                               emit(Opcodes.bltzal(0,0));
        !          1570:                               if size=2 then emit(Opcodes.add(0,0,0)) else ());
        !          1571:       gen(i+size, SOME (i+2), x)
        !          1572:   end
        !          1573: and gen(i,_,nil) = i
        !          1574:   | gen(i, _, (_,DEFINE lab) :: rest) = (lab := i; gen(i,NONE, rest))
        !          1575:                         (* invalidate the pc pointer at labels *)
        !          1576:   (* may want to do special fiddling with NOPs *)
        !          1577:   | gen(pos, pcptr, x as ((sizeref as ref size, inst) :: rest)) =
        !          1578:        if (pcptr=NONE andalso needs_a_pcptr(size, inst)) then makepcptr(pos,x)
        !          1579:        else case emitters of
        !          1580:           SOME (emit : int*int -> unit, emit_string : int -> string -> unit,
        !          1581:                 emit_real : string -> unit) =>
        !          1582:              \LA{}emit MIPS instructions\RA{}
        !          1583:         | NONE =>
        !          1584:              \LA{}compute positions\RA{}
        !          1585: in  gen
        !          1586: end
        !          1587: 
        !          1588: \endcode
        !          1589: \begindocs{28}
        !          1590: \subsection{Generating the instructions}
        !          1591: Now we need to consider the nitty-gritty details of just what instructions
        !          1592: are generated for each \code{}instr\edoc{}.
        !          1593: In  early passes, we'll just need to know how many instructions are
        !          1594: required (and that number may change from pass to pass, so it must be
        !          1595: recomputed).
        !          1596: In the last pass, the sizes are stable (by definition), so we can look
        !          1597: at the sizes to see what instructions to generate.
        !          1598: 
        !          1599: We'll consider the \code{}instrs\edoc{} in groups, but first, here's the
        !          1600: way we will structure things:
        !          1601: \enddocs
        !          1602: \begincode{29}
        !          1603: \moddef{compute positions}\endmoddef
        !          1604: let \LA{}functions for computing sizes\RA{}
        !          1605:     val newsize = case inst of
        !          1606:         \LA{}cases for sizes to be computed\RA{}
        !          1607: in  if newsize > size then sizeref := newsize else ();
        !          1608:     gen(pos+(!sizeref) (* BUGS -- was pos+size*),pcptr,rest)
        !          1609: end
        !          1610: \endcode
        !          1611: \begincode{30}
        !          1612: \moddef{emit MIPS instructions}\endmoddef
        !          1613: let fun gen1() = gen(pos+size,pcptr,rest) 
        !          1614:                                 (* generate the rest of the \code{}instr\edoc{}s *)
        !          1615:     open Bits
        !          1616:     open Opcodes
        !          1617:     \LA{}declare reserved registers \code{}tempreg\edoc{} and \code{}pcreg\edoc{}\RA{}
        !          1618:     \LA{}functions for emitting instructions\RA{}
        !          1619: in  case inst of
        !          1620:     \LA{}cases of instructions to be emitted\RA{}
        !          1621: end
        !          1622: \endcode
        !          1623: \begindocs{31}
        !          1624: When we get around to generating code, we may need to use a temporary
        !          1625: register.
        !          1626: For example, if we want to load into a register
        !          1627: an immediate constant that won't fit
        !          1628: into 16~bits, we will have to load the high-order part of the constant
        !          1629: with \code{}lui\edoc{}, then use \code{}addi\edoc{} to add then the low-order part.
        !          1630: The MIPS assembler has a similar problem, and on page D-2 of
        !          1631: the MIPS book we notice that register~1 is reserved for the use of the
        !          1632: assembler.
        !          1633: So we do the same.
        !          1634: 
        !          1635: We need to reserve a second register for use in pointing to the program 
        !          1636: counter.
        !          1637: We will use register 31 because the \code{}bltzal\edoc{} instruction automatically
        !          1638: sets register 31 to the PC.
        !          1639: \enddocs
        !          1640: \begincode{32}
        !          1641: \moddef{declare reserved registers \code{}tempreg\edoc{} and \code{}pcreg\edoc{}}\endmoddef
        !          1642: val tempreg = 1
        !          1643: val pcreg = 31
        !          1644: \endcode
        !          1645: \begindocs{33}
        !          1646: 
        !          1647: Before showing the code for the actual instructions, we should
        !          1648: point out that
        !          1649: we have two different ways of emitting a long word.
        !          1650: \code{}emitlong\edoc{} just splits the bits into two pieces for those cases
        !          1651: when it's desirable to put a word into the memory image.
        !          1652: \code{}split\edoc{} gives something that will load correctly
        !          1653: when the high-order piece is loaded into a high-order halfword
        !          1654: (using \code{}lui\edoc{}),
        !          1655: and the low-order piece is sign-extended and then added to the 
        !          1656: high-order piece.
        !          1657: This is the way we load immediate constants of more than sixteen bits.
        !          1658: It is also useful for generating load or store instructions with
        !          1659: offsets of more than sixteen bits: we \code{}lui\edoc{} the \code{}hi\edoc{} part and
        !          1660: add it to the base regsiter, then use the \code{}lo\edoc{} part as an offset.
        !          1661: \enddocs
        !          1662: \begincode{34}
        !          1663: \moddef{functions for emitting instructions}\endmoddef
        !          1664: fun emitlong i = emit(rshift(i,16), andb(i,65535))
        !          1665:                                 (* emit one long word (no sign fiddling) *)
        !          1666: fun split i = let val hi = rshift(i,16) and lo = andb(i,65535)
        !          1667:                      in if lo<32768 then (hi,lo) else (hi+1, lo-65536)
        !          1668:                     end
        !          1669: 
        !          1670: \endcode
        !          1671: \begindocs{35}
        !          1672: We begin implementing \code{}instrs\edoc{} by considering those that emit constants.
        !          1673: String constants are padded with nulls out to a word boundary, and 
        !          1674: real constants take up two words.
        !          1675: {\bf At the moment real constants seem to be zeros.
        !          1676: One day this will have to be fixed.}
        !          1677: Integer constants are just emitted with \code{}emitlong\edoc{}.
        !          1678: \enddocs
        !          1679: \begincode{36}
        !          1680: \moddef{cases for sizes to be computed}\endmoddef
        !          1681:   STRINGCONST s => Integer.div(String.length(s)+3,4)
        !          1682: | REALCONST _ => 2
        !          1683: | EMITLONG _ => 1
        !          1684: \endcode
        !          1685: \begincode{37}
        !          1686: \moddef{cases of instructions to be emitted}\endmoddef
        !          1687:   STRINGCONST s => 
        !          1688:         let val s' = s ^ "\\000\\000\\000\\000"
        !          1689:         in  gen1(emit_string (4*size) s')
        !          1690:                                       (* doesn't know Big vs Little-Endian *)
        !          1691:         end
        !          1692: | REALCONST s => gen1(emit_real s)  (* floating pt constant *)
        !          1693: | EMITLONG i => gen1(emitlong i)
        !          1694: \endcode
        !          1695: \begindocs{38}
        !          1696: 
        !          1697: Next consider the labels.
        !          1698: A \code{}DEFINE\edoc{} should never reach this far, and \code{}EMITLAB\edoc{} is almost like
        !          1699: an \code{}EMITLONG\edoc{}.
        !          1700: \enddocs
        !          1701: \begincode{39}
        !          1702: \moddef{cases for sizes to be computed}\endmoddef
        !          1703: | DEFINE _ => ErrorMsg.impossible "generate code for DEFINE in mipscoder"
        !          1704: | EMITLAB _ => 1
        !          1705: \endcode
        !          1706: \begincode{40}
        !          1707: \moddef{cases of instructions to be emitted}\endmoddef
        !          1708: | DEFINE _ => gen1(ErrorMsg.impossible "generate code for DEFINE in mipscoder")
        !          1709: | EMITLAB(i, ref d) => gen1(emitlong((d-pos)*4+i))
        !          1710: \endcode
        !          1711: \begindocs{41}
        !          1712: 
        !          1713: Now we have to start worrying about instructions with \code{}EA\edoc{} in them.
        !          1714: The real difficulty these things present is that they may have an
        !          1715: immediate operand that won't fit in 16~bits.
        !          1716: So we'll need to get this large immediate operand into a register,
        !          1717: sixteen bits at a time, and then do the operation on the register.
        !          1718: 
        !          1719: Since all of the arithmetic instructions have this difficulty, and since
        !          1720: we can use them to implement the others, we'll start with those and
        !          1721: catch up with the control-flow instructions later.
        !          1722: \enddocs
        !          1723: \begindocs{42}
        !          1724: \code{}SUB\edoc{}, \code{}MULDIV\edoc{}, and \code{}MFLO\edoc{} all use registers only, so they are easy.
        !          1725: The other arithmetic operations get treated exactly the same, so we'll
        !          1726: use a function to compute the size.
        !          1727: {\bf move this to follow the definition of \code{}arith\edoc{}?}
        !          1728: \enddocs
        !          1729: \begincode{43}
        !          1730: \moddef{cases for sizes to be computed}\endmoddef
        !          1731: | ADD(_, ea, _) => easize ea
        !          1732: | AND(_, ea, _) => easize ea
        !          1733: | OR (_, ea, _) => easize ea
        !          1734: | XOR(_, ea, _) => easize ea
        !          1735: | SUB _ => 1
        !          1736: | MULDIV _ => 1 
        !          1737: | MFLO _ => 1
        !          1738: | MFHI _ => 1
        !          1739: \endcode
        !          1740: \begindocs{44}
        !          1741: Register operations take one instruction.
        !          1742: Immediate operations take one instruction for 16~bit constants,
        !          1743: and 3 for larger constants (since it costs two instructions to load
        !          1744: a big immediate constant into a register).
        !          1745: An immediate instruction with \code{}Immedlab l\edoc{} means that the operand
        !          1746: is intended to be the machine address associated with that label.
        !          1747: To compute that address, we need to add 
        !          1748: \code{}4*(l-pcptr)\edoc{} to the contents of 
        !          1749: register~\code{}pcreg\edoc{} (which holds \code{}4*pcptr\edoc{}), 
        !          1750: put the results in a register, and operate on that register.
        !          1751: 
        !          1752: This tells us enough to compute the sizes.
        !          1753: \enddocs
        !          1754: \begincode{45}
        !          1755: \moddef{functions for computing sizes}\endmoddef
        !          1756: fun easize (Direct _) = 1
        !          1757:   | easize (Immed i) = if abs(i)<32768 then 1 else 3
        !          1758:   | easize (Immedlab(ref lab)) = 1 + easize(Immed (4*(lab-(get pcptr))))
        !          1759: \endcode
        !          1760: \begindocs{46}
        !          1761: 
        !          1762: As we have seen, 
        !          1763: to implement any arithmetic operation, we need to know the register 
        !          1764: form and the sixteen-bit immediate form.
        !          1765: We will also want the operator from \code{}instr\edoc{}, since we do the
        !          1766: large immediate via a recursive call.
        !          1767: We'll set up a function, \code{}arith\edoc{}, that does the job.
        !          1768: \enddocs
        !          1769: \begincode{47}
        !          1770: \moddef{functions for emitting instructions}\endmoddef
        !          1771: fun arith (opr, rform, iform) =
        !          1772:    let fun ar (Reg op1, Direct (Reg op2), Reg result) = 
        !          1773:                 gen1(emit(rform(result,op1,op2)))
        !          1774:          | ar (Reg op1, Immed op2, Reg result) =
        !          1775:                 (case size of
        !          1776:                     1 (* 16 bits *) => gen1(emit(iform(result,op1,op2)))
        !          1777:                   | 3 (* 32 bits *) => 
        !          1778:                      gen(pos,pcptr,
        !          1779:                           (ref 2, LDI_32(op2, Reg tempreg))::
        !          1780:                           (ref 1, opr(Reg op1, Direct(Reg tempreg), Reg result))::
        !          1781:                           rest)
        !          1782:                   | _ => gen(ErrorMsg.impossible 
        !          1783:                                 "bad size in arith Immed in mipscoder")
        !          1784:                 )
        !          1785:          | ar (Reg op1, Immedlab (ref op2), Reg result) =
        !          1786:                 gen(pos, pcptr, 
        !          1787:                       (ref (size-1), 
        !          1788:                             ADD(Reg pcreg,Immed(4*(op2-(get pcptr))), Reg tempreg))::
        !          1789:                       (ref 1, opr(Reg op1, Direct(Reg tempreg), Reg result))::
        !          1790:                       rest)
        !          1791:    in  ar
        !          1792:    end
        !          1793: \endcode
        !          1794: \begindocs{48}
        !          1795: 
        !          1796: The generation itself may be a bit anticlimactic.
        !          1797: The MIPS has no ``subtract immediate'' instruction, and \code{}SUB\edoc{} has
        !          1798: a different type than the others, so we emit it directly.
        !          1799: \enddocs
        !          1800: \begincode{49}
        !          1801: \moddef{cases of instructions to be emitted}\endmoddef
        !          1802: | ADD stuff => arith (ADD,add,addi) stuff
        !          1803: | AND stuff => arith (AND,and',andi) stuff
        !          1804: | OR  stuff => arith (OR,or,ori) stuff
        !          1805: | XOR stuff => arith (XOR,xor,xori) stuff
        !          1806: | SUB (Reg op1, Reg op2, Reg result) => gen1(emit(sub(result,op1,op2)))
        !          1807: | MULDIV(DIV, Reg op1, Reg op2) => gen1(emit(div(op1,op2)))
        !          1808: | MULDIV(MULT,Reg op1, Reg op2) => gen1(emit(mult(op1,op2)))
        !          1809: | MFLO(Reg result) => gen1(emit(mflo(result)))
        !          1810: | MFHI(Reg result) => gen1(emit(mfhi(result)))
        !          1811: \endcode
        !          1812: \begindocs{50}
        !          1813: Floating point arithmetic is pretty easy because we always do it in
        !          1814: registers.  
        !          1815: We also support only one format, double precision.
        !          1816: \enddocs
        !          1817: \begincode{51}
        !          1818: \moddef{cases for sizes to be computed}\endmoddef
        !          1819: | NEG_D _ => 1
        !          1820: | MUL_D _ => 1
        !          1821: | DIV_D _ => 1
        !          1822: | ADD_D _ => 1
        !          1823: | SUB_D _ => 1
        !          1824: \endcode
        !          1825: \begindocs{52}
        !          1826: When emitting instructions we have to remember the Mips instructions
        !          1827: use result on the left, but the \code{}MIPSCODER\edoc{} signature requires result
        !          1828: on the right.
        !          1829: \enddocs
        !          1830: \begincode{53}
        !          1831: \moddef{cases of instructions to be emitted}\endmoddef
        !          1832: | NEG_D (Reg op1,Reg result) => gen1(emit(neg_fmt(D_fmt,result,op1)))
        !          1833: \endcode
        !          1834: \begincode{54}
        !          1835: \moddef{functions for emitting instructions}\endmoddef
        !          1836: fun float3double instruction (Reg op1,Reg op2,Reg result) =
        !          1837:    gen1(emit(instruction(D_fmt,result,op1,op2)))
        !          1838: \endcode
        !          1839: \begincode{55}
        !          1840: \moddef{cases of instructions to be emitted}\endmoddef
        !          1841: | MUL_D x => float3double mul_fmt x
        !          1842: | DIV_D x => float3double div_fmt x
        !          1843: | ADD_D x => float3double add_fmt x
        !          1844: | SUB_D x => float3double sub_fmt x
        !          1845: 
        !          1846: 
        !          1847: \endcode
        !          1848: \begindocs{56}
        !          1849: We offer a separate \code{}MOVE\edoc{} instruction because of large immediate
        !          1850: constants.  
        !          1851: It is always possible to do \code{}move(src,dest)\edoc{} by doing 
        !          1852: \code{}add(Reg 0,src,dest)\edoc{}, but the general form \code{}add(Reg i, Immed c, dest)\edoc{}
        !          1853: takes three instructions when \code{}c\edoc{} is a large constant (more than 16 bits).
        !          1854: Rather than clutter up the code for \code{}add\edoc{} (and \code{}or\edoc{} and \code{}xor\edoc{}) by
        !          1855: trying to recognize register~0, we provide \code{}move\edoc{} explicitly.
        !          1856: 
        !          1857: \indent \code{}LDI_32\edoc{} takes care of the particular case in which we are 
        !          1858: loading a 32-bit immediate constant into a register.  
        !          1859: It dates from the bad old days before \code{}MOVE\edoc{}, and it might be a good idea
        !          1860: to remove it sometime.
        !          1861: \enddocs
        !          1862: \begincode{57}
        !          1863: \moddef{functions for emitting instructions}\endmoddef
        !          1864: fun domove (Direct (Reg src), Reg dest) = gen1(emit(add(dest,src,0)))
        !          1865:   | domove (Immed src, Reg dest) =
        !          1866:         (case size of
        !          1867:             1 (* 16 bits *) => gen1(emit(addi(dest,0,src)))
        !          1868:           | 2 (* 32 bits *) => 
        !          1869:                         gen(pos,pcptr,(ref 2, LDI_32(src, Reg dest))::rest)
        !          1870:           | _ => gen(ErrorMsg.impossible "bad size in domove Immed in mipscoder")
        !          1871:         )
        !          1872:   | domove (Immedlab (ref src), Reg dest) =
        !          1873:         gen(pos, pcptr, 
        !          1874:               (ref size, 
        !          1875:                     ADD(Reg pcreg,Immed(4*(src-(get pcptr))), Reg dest))::rest)
        !          1876: \endcode
        !          1877: \begindocs{58}
        !          1878: Notice we use \code{}easize\edoc{} and not \code{}movesize\edoc{} in the third clause
        !          1879: because when we reach this point the treatment of a \code{}MOVE\edoc{} is the same
        !          1880: as that of an \code{}ADD\edoc{}.
        !          1881: \enddocs
        !          1882: \begincode{59}
        !          1883: \moddef{functions for computing sizes}\endmoddef
        !          1884: fun movesize (Direct _) = 1
        !          1885:   | movesize (Immed i) = if abs(i)<32768 then 1 else 2
        !          1886:   | movesize (Immedlab(ref lab)) = easize(Immed (4*(lab-(get pcptr))))
        !          1887: 
        !          1888: \endcode
        !          1889: \begincode{60}
        !          1890: \moddef{cases for sizes to be computed}\endmoddef
        !          1891: | MOVE (src,_) => movesize src
        !          1892: | LDI_32 _ => 2
        !          1893: | LUI _ => 1
        !          1894: \endcode
        !          1895: \begincode{61}
        !          1896: \moddef{cases of instructions to be emitted}\endmoddef
        !          1897: | MOVE stuff => domove stuff
        !          1898: | LDI_32 (immedconst, Reg dest) =>
        !          1899:          let val (hi,lo) = split immedconst
        !          1900:          in  gen1(emit(lui(dest,hi));emit(addi(dest,dest,lo)))
        !          1901:          end 
        !          1902: | LUI (Reg dest,immed16) => gen1(emit(lui(dest,immed16)))
        !          1903: 
        !          1904: \endcode
        !          1905: \begindocs{62}
        !          1906: 
        !          1907: Now that we've done arithmetic, we can see how to do control flow without
        !          1908: too much trouble.
        !          1909: \code{}SLT\edoc{} can be treated just like an arithmetic operator.
        !          1910: \code{}BEQ\edoc{} is simple if the address to which we branch is close enough.
        !          1911: Otherwise we use the following sequence for \code{}BEQ(Reg op1, Reg op2, ref dest)\edoc{}:
        !          1912: \verbatim
        !          1913:         bne op1,op2,L
        !          1914:         ADD (Reg pcreg, Immed (4*(dest-pcptr)), Reg tempreg)
        !          1915:         jr tempreg
        !          1916:      L: ...
        !          1917: \endverbatim
        !          1918: Notice we don't have to put a \code{}NOP\edoc{} in the delay slot of the \code{}bne\edoc{}.
        !          1919: We don't need one after the jump unless we needed one after the 
        !          1920: original \code{}BEQ\edoc{}, in which case one will be there.
        !          1921: If the branch is taken, we're doing as well as we can.
        !          1922: If the branch is not taken, we will have executed an \code{}add\edoc{} or \code{}lui\edoc{} in the 
        !          1923: delay slot of the \code{}bne\edoc{}, but the results just get thrown away.
        !          1924: \enddocs
        !          1925: \begincode{63}
        !          1926: \moddef{cases for sizes to be computed}\endmoddef
        !          1927: | SLT(_, ea, _) => easize ea
        !          1928: | BEQ(_,_,_,ref dest) => 
        !          1929:         if abs((pos+1)-dest) < 32768 then 1 (* single instruction *)
        !          1930:         else 2+easize (Immed (4*(dest-(get pcptr))))
        !          1931: | JUMP _ => 1
        !          1932: | SLT_D _ => 1
        !          1933: | SEQ_D _ => 1
        !          1934: | BCOP1(_,ref dest) => 
        !          1935:         if abs((pos+1)-dest) < 32768 then 1 (* single instruction *)
        !          1936:         else 2+easize (Immed (4*(dest-(get pcptr))))
        !          1937: | NOP => 1
        !          1938: \endcode
        !          1939: \begindocs{64}
        !          1940: The implementation is as described, except we use a 
        !          1941: non-standard \code{}nop\edoc{}.
        !          1942: There are many Mips instructions that have no effect, and the standard
        !          1943: one is the word with all zeroes (\code{}sll 0,0,0\edoc{}).
        !          1944: We use \code{}add\edoc{},  adding 0 to 0 and store the result in 0, because it
        !          1945: will be easy to distinguish from a data word that happens to be zero.
        !          1946: \enddocs
        !          1947: \begincode{65}
        !          1948: \moddef{cases of instructions to be emitted}\endmoddef
        !          1949: | SLT stuff => arith (SLT,slt,slti) stuff
        !          1950: | BEQ(b, Reg op1, Reg op2, ref dest) =>
        !          1951:     if size = 1 then 
        !          1952:          gen1(emit((if b then beq else bne)(op1,op2,dest-(pos+1))))
        !          1953:     else gen(pos,pcptr,
        !          1954:                   (ref 1, BEQ(not b, Reg op1, Reg op2, ref(pos+size)))
        !          1955:                   ::(ref (size-2), 
        !          1956:                       ADD(Reg pcreg, Immed(4*(dest-(get pcptr))), Reg tempreg))
        !          1957:                   ::(ref 1, JUMP(Reg tempreg))
        !          1958:                   ::rest)
        !          1959: | JUMP(Reg dest) => gen1(emit(jr(dest)))
        !          1960: | SLT_D (Reg op1, Reg op2) => 
        !          1961:      gen1(emit(c_lt(D_fmt,op1,op2)))
        !          1962: | SEQ_D (Reg op1, Reg op2) => 
        !          1963:      gen1(emit(c_seq(D_fmt,op1,op2)))
        !          1964: | BCOP1(b, ref dest) =>
        !          1965:     let fun bc1f offset = cop1(8,0,offset)
        !          1966:         fun bc1t offset = cop1(8,1,offset)
        !          1967:     in  if size = 1 then 
        !          1968:              gen1(emit((if b then bc1t else bc1f)(dest-(pos+1))))
        !          1969:         else gen(pos,pcptr,
        !          1970:                   (ref 1, BCOP1(not b, ref(pos+size)))
        !          1971:                   ::(ref (size-2), 
        !          1972:                       ADD(Reg pcreg, Immed(4*(dest-(get pcptr))), Reg tempreg))
        !          1973:                   ::(ref 1, JUMP(Reg tempreg))
        !          1974:                   ::rest)
        !          1975:     end
        !          1976: | NOP => gen1(emit(add(0,0,0)))         (* one of the many MIPS no-ops *)
        !          1977: \endcode
        !          1978: \begindocs{66}
        !          1979: 
        !          1980: Our next problem is to tackle load and store.
        !          1981: The major difficulty is if the offset is too large to fit in
        !          1982: sixteen bits; if so, we have to create a new base register.
        !          1983: If we have \code{}Immedlab\edoc{}, we do it as an offset from \code{}pcreg\edoc{}.
        !          1984: \enddocs
        !          1985: \begincode{67}
        !          1986: \moddef{functions for emitting instructions}\endmoddef
        !          1987: fun memop(rform,Reg dest, Direct (Reg base), offset) =
        !          1988:       (case size
        !          1989:        of 1 => gen1(emit(rform(dest,offset,base)))
        !          1990:         | 3 => let val (hi,lo) = split offset
        !          1991:                in  gen1(emit(lui(tempreg,hi));       (* tempreg = hi \LL{} 16 *)
        !          1992:                         emit(add(tempreg,base,tempreg));(* tempreg += base *)
        !          1993:                         emit(rform(dest,lo,tempreg)) (* load dest,lo(tempreg) *)
        !          1994:                        )
        !          1995:                end
        !          1996:         | _ => gen1(ErrorMsg.impossible "bad size in memop Direct in mipscoder")
        !          1997:        )
        !          1998:   | memop(rform,Reg dest, Immed address, offset) =
        !          1999:       (case size
        !          2000:        of 1 => gen1(emit(rform(dest,offset+address,0)))
        !          2001:         | 2 => let val (hi,lo) = split (offset+address)
        !          2002:                in  gen1(emit(lui(tempreg,hi)); 
        !          2003:                         emit(rform(dest,lo,tempreg))
        !          2004:                        )
        !          2005:                end
        !          2006:         | _ => gen1(ErrorMsg.impossible "bad size in memop Immed in mipscoder")
        !          2007:        )
        !          2008:   | memop(rform,Reg dest, Immedlab (ref lab), offset) =
        !          2009:       memop(rform, Reg dest, Direct (Reg pcreg), offset+4*(lab - get pcptr))
        !          2010: \endcode
        !          2011: \begindocs{68}
        !          2012: The actual registers don't matter for computing sizes, and in fact
        !          2013: the value of \code{}pcreg\edoc{} is not visible here, so we use an arbitrary
        !          2014: register (\code{}Reg 0\edoc{}) to compute the size.
        !          2015: \enddocs
        !          2016: \begincode{69}
        !          2017: \moddef{functions for computing sizes}\endmoddef
        !          2018: fun adrsize(_, Reg _, Direct _, offset) = 
        !          2019:             if abs(offset)<32768 then 1 else 3
        !          2020:   | adrsize(_, Reg _, Immed address, offset) = 
        !          2021:             if abs(address+offset) < 32768 then 1 else 2
        !          2022:   | adrsize(x, Reg dest, Immedlab (ref lab), offset) =
        !          2023:             adrsize(x, Reg dest, Direct (Reg 0  (* pcreg in code *) ), 
        !          2024:                     offset+4*(lab-(get pcptr)))
        !          2025: \endcode
        !          2026: \begincode{70}
        !          2027: \moddef{cases for sizes to be computed}\endmoddef
        !          2028: | LOAD  x => adrsize x
        !          2029: | STORE x => adrsize x
        !          2030: \endcode
        !          2031: \begincode{71}
        !          2032: \moddef{cases of instructions to be emitted}\endmoddef
        !          2033: | LOAD  (Byte,dest,address,offset) => memop(lbu,dest,address,offset)
        !          2034: | LOAD  (Word,dest,address,offset) => memop(lw,dest,address,offset)
        !          2035: | LOAD  (Floating,dest,address,offset) => memop(lwc1,dest,address,offset)
        !          2036: | STORE (Byte,dest,address,offset) => memop(sb,dest,address,offset)
        !          2037: | STORE (Word,dest,address,offset) => memop(sw,dest,address,offset)
        !          2038: | STORE (Floating,dest,address,offset) => memop(swc1,dest,address,offset)
        !          2039: \endcode
        !          2040: \begindocs{72}
        !          2041:  
        !          2042: For the shift instructions, only register and immediate operands
        !          2043: make sense.
        !          2044: Immediate operands make sense if and only if they are representable
        !          2045: in five bits.
        !          2046: If everything is right, these are single instructions.
        !          2047: \enddocs
        !          2048: \begincode{73}
        !          2049: \moddef{cases for sizes to be computed}\endmoddef
        !          2050: | SLL _ => 1  
        !          2051: | SRA _ => 1
        !          2052: \endcode
        !          2053: \begincode{74}
        !          2054: \moddef{cases of instructions to be emitted}\endmoddef
        !          2055: | SLL (Immed shamt, Reg op1, Reg result) => gen1(
        !          2056:         if (shamt >= 0 andalso shamt < 32) then emit(sll(result,op1,shamt))
        !          2057:         else ErrorMsg.impossible ("bad sll shamt "
        !          2058:                 ^ (Integer.makestring shamt) ^ " in mipscoder"))
        !          2059: | SLL (Direct(Reg shamt), Reg op1, Reg result) => 
        !          2060:         gen1(emit(sllv(result,op1,shamt)))
        !          2061: | SLL (Immedlab _,_,_) => ErrorMsg.impossible "sll shamt is Immedlab in mipscoder"
        !          2062: | SRA (Immed shamt, Reg op1, Reg result) => gen1(
        !          2063:         if (shamt >= 0 andalso shamt < 32) then emit(sra(result,op1,shamt))
        !          2064:         else ErrorMsg.impossible ("bad sra shamt "
        !          2065:                 ^ (Integer.makestring shamt) ^ " in mipscoder"))
        !          2066: | SRA (Direct(Reg shamt), Reg op1, Reg result) =>
        !          2067:         gen1(emit(srav(result,op1,shamt)))
        !          2068: | SRA (Immedlab _,_,_) => ErrorMsg.impossible "sra shamt is Immedlab in mipscoder"
        !          2069: \endcode
        !          2070: \begindocs{75}
        !          2071: 
        !          2072: Finally, comments are ignored, and marks (backpointers) are written into the
        !          2073: instruction stream.
        !          2074: 
        !          2075: Comments are used by the front end to give diagnostics.
        !          2076: In the bad old days we would have had two different \code{}MIPSCODER\edoc{}s, one
        !          2077: which generated machine code (and ignored comments), and one which
        !          2078: wrote out assembly code (and copied comments).
        !          2079: Today we have just one, which means the rerouting of comments takes place
        !          2080: at a much higher level.  Look in \code{}cps/mipsglue.nw\edoc{}.
        !          2081: \enddocs
        !          2082: \begincode{76}
        !          2083: \moddef{cases for sizes to be computed}\endmoddef
        !          2084: | COMMENT _ => 0
        !          2085: | MARK => 1                     (* backpointer takes one word *)
        !          2086: \endcode
        !          2087: \begindocs{77}
        !          2088: Just for the record, here's the description of what a mark (backpointer)
        !          2089: is.
        !          2090: ``Take the byte address at which the mark resides and add 4, giving
        !          2091: the byte address of the object following the mark.
        !          2092: (That object is the marked object.)
        !          2093: Subtract the byte address of the initial word that marks the
        !          2094: start of this instruction stream.
        !          2095: Now divide by 4, giving the distance in words between the
        !          2096: beginning of the block and the marked object.
        !          2097: Take that quantity and shift it left by multiplying by \code{}power_tags\edoc{},
        !          2098: and indicate the result is a mark by adding the tag bits \code{}tag_backptr\edoc{}
        !          2099: into the low order part.''
        !          2100:  \code{}pos+1\edoc{} is exactly the required distance in words.
        !          2101: \enddocs
        !          2102: \begincode{78}
        !          2103: \moddef{cases of instructions to be emitted}\endmoddef
        !          2104: | COMMENT _ => gen1()
        !          2105: | MARK => gen1(
        !          2106:     let open System.Tags
        !          2107:     in  emitlong((pos+1) * power_tags + tag_backptr)
        !          2108:     end)
        !          2109: \endcode
        !          2110: \begindocs{79}
        !          2111: 
        !          2112: \enddocs
        !          2113: \begindocs{80}
        !          2114: \subsection{Optimization}
        !          2115: The first step towards optimization is to take statistics.
        !          2116: We will count: \code{}instrs\edoc{}, Mips words, \code{}NOP\edoc{}s in load and branch delays,
        !          2117: and \code{}bltzal\edoc{}s.
        !          2118: In the current implementation the \code{}bltzal\edoc{}s are implicit, so there
        !          2119: is no way to count them or optimize them.
        !          2120: \enddocs
        !          2121: \begincode{81}
        !          2122: \moddef{statistics}\endmoddef
        !          2123: fun printstats stream
        !          2124:  \{inst : int, code : int, data : int, 
        !          2125:   load : int, branch : int, compare : int, size : int\} =
        !          2126:     let val print = output stream
        !          2127:         val nop = load+branch+compare
        !          2128:         val bltzal = size - (code + data)
        !          2129:         val code = code + bltzal
        !          2130:         \LA{}definition of \code{}sprintf\edoc{}\RA{}
        !          2131:         fun P x = substring(makestring(100.0 * x),0,4)  (* percent *)
        !          2132:         fun printf f d = print (sprintf f d)
        !          2133:     in  printf ["Counted "," instrs in "," words (",
        !          2134:                                 " code, "," data)\\n" ^
        !          2135:                 "Used "," NOPs ("," load, "," branch,"," compare) and "," bltzals\\n" ^
        !          2136:                 "","% of code words were NOPs; ","% were bltzals\\n" ^
        !          2137:                 "","% of all words were code; ","% of all words were NOPs\\n"]
        !          2138:                [I inst, I size, I code, I data, 
        !          2139:                 I nop, I load, I branch,  I compare, I bltzal,
        !          2140:                 P (real nop / real code), P (real bltzal / real code),
        !          2141:                 P (real code / real size), P (real nop / real size)]
        !          2142:         handle Overflow => print "[Overflow in computing Mips stats]\\n"
        !          2143:              | Real s => print ("[FPE ("^s^") in computing Mips stats]\\n")
        !          2144:     end
        !          2145:                 
        !          2146: \endcode
        !          2147: \begincode{82}
        !          2148: \moddef{statistics}\endmoddef
        !          2149: \LA{}definition of \code{}iscode\edoc{}\RA{}
        !          2150: fun addstats (counts as \{inst,code,data,load,branch,compare\}) =
        !          2151:   fn nil => counts
        !          2152:    | (sizeref,first)::(_,NOP)::rest => addstats
        !          2153:           \{inst=inst+2, code=code+(!sizeref)+1, data=data,
        !          2154:            load=load+ (case first of LOAD _ => 1 | _ => 0),
        !          2155:            branch=branch +(case first of BEQ _ => 1 | JUMP _ => 1 
        !          2156:                                        | BCOP1 _ => 1 | _ => 0),
        !          2157:            compare=compare+(case first of SLT_D _ => 1 | SEQ_D _ => 1 
        !          2158:                                         | _ => 0)
        !          2159:           \} rest
        !          2160:    | (sizeref,first)::rest => addstats
        !          2161:           \{inst=inst+1, 
        !          2162:            code = code + if iscode(first) then !sizeref else 0,
        !          2163:            data = data + if not (iscode first) then !sizeref else 0,
        !          2164:            load=load,
        !          2165:            branch=branch,
        !          2166:            compare=compare
        !          2167:           \} rest
        !          2168: 
        !          2169: 
        !          2170: fun codestats outfile =
        !          2171:     let val \{size,stream=instrs\} = prepare (!kept)
        !          2172:         val zero = \{inst=0, code=0, data=0, load=0, branch=0, compare=0\}
        !          2173:         val counts as \{inst,code,data,load,branch,compare\} = 
        !          2174:                                                 addstats zero instrs
        !          2175:     in  printstats outfile 
        !          2176:             \{inst=inst,code=code,data=data,
        !          2177:              load=load,branch=branch,compare=compare,size=size\}
        !          2178:     end
        !          2179:         
        !          2180: \endcode
        !          2181: \begincode{83}
        !          2182: \moddef{definition of \code{}iscode\edoc{}}\endmoddef
        !          2183: val iscode = fn
        !          2184:     STRINGCONST _ => false
        !          2185:   | REALCONST _ => false
        !          2186:   | EMITLONG _ => false
        !          2187:   | DEFINE _ => false
        !          2188:   | EMITLAB _ => false
        !          2189: 
        !          2190:   | SLT _ => true
        !          2191:   | BEQ _ => true
        !          2192:   | JUMP _ => true
        !          2193:   | NOP => true
        !          2194:   | SLT_D _ => true
        !          2195:   | SEQ_D _ => true
        !          2196:   | BCOP1 _ => true
        !          2197: 
        !          2198:   | ADD _ => true
        !          2199:   | AND _ => true
        !          2200:   | OR  _ => true
        !          2201:   | XOR _ => true
        !          2202:   | SUB _ => true
        !          2203:   | MULDIV _ => true
        !          2204:   | MFLO _ => true
        !          2205:   | MFHI _ => true
        !          2206: 
        !          2207:   | NEG_D _ => true
        !          2208:   | MUL_D _ => true
        !          2209:   | DIV_D _ => true
        !          2210:   | ADD_D _ => true
        !          2211:   | SUB_D _ => true
        !          2212: 
        !          2213:   | MOVE _ => true
        !          2214:   | LDI_32 _ => true
        !          2215:   | LUI _ => true
        !          2216: 
        !          2217:   | LOAD _ => true
        !          2218:   | STORE  _ => true
        !          2219: 
        !          2220:   | SLL _ => true
        !          2221:   | SRA _ => true
        !          2222: 
        !          2223:   | COMMENT _ => false
        !          2224:   | MARK => false
        !          2225: 
        !          2226: \endcode
        !          2227: \begincode{84}
        !          2228: \moddef{definition of \code{}sprintf\edoc{}}\endmoddef
        !          2229: val I = Integer.makestring
        !          2230: val R = Real.makestring
        !          2231: exception Printf
        !          2232: fun sprintf format values =
        !          2233:     let fun merge([x],nil) = [x]
        !          2234:           | merge(nil,nil) = nil
        !          2235:           | merge(x::y,z::w) = x::z:: merge(y,w)
        !          2236:           | merge _ = raise Printf
        !          2237:     in  implode(merge(format,values))
        !          2238:     end
        !          2239: 
        !          2240: \endcode
        !          2241: \begindocs{85}
        !          2242: 
        !          2243: At the moment these functions are meaningless junk.
        !          2244: \enddocs
        !          2245: \begincode{86}
        !          2246: \moddef{functions that remove pipeline bubbles}\endmoddef
        !          2247: val rec squeeze =
        !          2248: 
        !          2249:  fn (x as LOAD(_,Reg d, m, i))::NOP::instr::rest =>
        !          2250:         if use(instr,d) then ??
        !          2251:         else squeeze(x::instr::rest)
        !          2252:   | (x as STORE _)::(y as LOAD _)::rest => 
        !          2253:         x :: squeeze(y::rest)
        !          2254:   | instr::(x as LOAD(_,Reg d, Direct(Reg s), i))::NOP::rest =>
        !          2255:         if use(instr, d) orelse gen(instr, s) then ??
        !          2256:         else squeeze(x::instr::rest)
        !          2257:   | instr::(x as LOAD(_,Reg d, _, i))::NOP::rest =>
        !          2258:         if use(instr,d) then ??
        !          2259:         else squeeze(x::instr::rest)
        !          2260:   | (x as MFLO _):: (y as MULDIV _) :: rest =>
        !          2261:         x :: squeeze (y::rest)
        !          2262:   | (x as MFLO(Reg d))::instr::rest =>
        !          2263:         if (use(instr,d) orelse gen(instr,d) then ??
        !          2264:         else squeeze(instr::x::rest)
        !          2265:   | instr :: (x as MULDIV(Reg a, Reg b)) :: rest =>
        !          2266:         if gen(instr,a) orelse gen(instr,b) then ??
        !          2267:         else squeeze(x::instr::rest)
        !          2268: 
        !          2269: val rec final =
        !          2270:  fn
        !          2271:   | instr::(x as LOAD(_,Reg d, Direct(Reg s), i))::NOP::rest =>
        !          2272:         if gen(instr, s) then instr::final(x::NOP::rest)
        !          2273:         else x::instr::(final rest)
        !          2274:   | instr :: (x as JUMP _) :: NOP :: rest =>
        !          2275:         x :: instr :: final rest
        !          2276:   | instr :: (x as BEQ(_,Reg a, Reg b, _)) :: NOP :: rest =>
        !          2277:         if gen(instr,a) orelse gen(instr,b) then instr::x::NOP::(final rest)
        !          2278:         else x::instr::(final rest)
        !          2279: 
        !          2280: 
        !          2281: \endcode
        !          2282: \filename{opcodes.nw}
        !          2283: \begindocs{0}
        !          2284: \chapter{Handling the MIPS opcodes}
        !          2285: \section{Introduction}
        !          2286: 
        !          2287: This file generates the code necessary to handle MIPS instructions
        !          2288: in a natural, mnemonic way from within ML.
        !          2289: All MIPS instructions occupy 32 bits, and since ML has no simple
        !          2290: 32~bit data type, we use pairs of integerss to represent MIPS instructions.
        !          2291: A pair \code{}(hi,lo)\edoc{} of 16-bit integers holds the most and least significant
        !          2292: halfwords of the MIPS word.
        !          2293: ML integers are 31 bits, so this is more than adequate.
        !          2294: 
        !          2295: The biggest hassle in converting between these integer pairs and more
        !          2296: mnemonic representations is that it is too easy to make mistakes
        !          2297: (especially typographical errors) in writing the code.
        !          2298: For that reason, I have added an extra level of indirection to the
        !          2299: whole business by putting all of the instruction descriptions in
        !          2300: tables.
        !          2301: These tables are read by an awk script, which writes two ML files:
        !          2302: {\tt opcodes.sml} and {\tt mipsdecode.sml}.
        !          2303: The {\tt opcodes.sml} file contains the code needed to convert from
        !          2304: a mnemonic like \code{}add(3,4,9)\edoc{} (add the contents of register~3 to
        !          2305: the contents of register~4, placing the result in register~9) to 
        !          2306: the integer pair representation of the actual bits in that add instruction
        !          2307: (in this case \code{}(137,6176)\edoc{}).
        !          2308: The {\tt mipsdecode.sml} file contains a \code{}decode\edoc{} function that converts
        !          2309: from the integer pair representation of instructions to a string
        !          2310: representation.
        !          2311: The string representation is a little hokey at the moment (that is,
        !          2312: it's different from the one used in the MIPS book), but it represents
        !          2313: a nice compromise between being readable and easy to generate.
        !          2314: 
        !          2315: I have contemplating generating a third file to test the whole
        !          2316: business.
        !          2317: The idea would be to have a function that would write out (to files)
        !          2318: two
        !          2319: parallel representations of the same instruction stream (presumably
        !          2320: one copy of each known instruction).
        !          2321: One representation would be the binary one understood by the MIPS.
        !          2322: The other representation would be a string representation.
        !          2323: We could then use a tool like {\tt gdb} or {\tt adb} to print out
        !          2324: the binary as an instruction sequence (i.e. convert back to
        !          2325: a second string representation) and compare the string representations
        !          2326: to see if they make sense.
        !          2327: 
        !          2328: \paragraph{Possible bugs}
        !          2329: This code should be gone over with care to make sure that negative
        !          2330: operands (e.g. in \code{}offset\edoc{}) won't break the code.
        !          2331: 
        !          2332: 
        !          2333: \enddocs
        !          2334: \begindocs{1}
        !          2335: 
        !          2336: We need a special line in the Makefile to handle this file, since
        !          2337: it writes both an awk program and that program's input.  The input
        !          2338: is in module {\tt \LL{}opcodes table\GG{}} so the line is
        !          2339: $$\hbox{\code{}      $(NOTANGLE) '-Ropcodes table' opcodes.ow > opcodes\edoc{}}$$
        !          2340: The input is nothing but a sequence of tables, each labelled, and
        !          2341: processed one after anothing according to the label.
        !          2342: The label is always a single word on a line by itself.
        !          2343: Tables end with blank lines.
        !          2344: \enddocs
        !          2345: \begindocs{2}
        !          2346: The opcode-to-pair code is written to the standard output, in 
        !          2347: \code{}structure Opcodes\edoc{}.
        !          2348: The pair-to-string code is written to \code{}"mipsdecode.sml"\edoc{}, in
        !          2349: \code{}structure MipsDecode\edoc{}.
        !          2350: 
        !          2351: We begin by defining and and shift functions.
        !          2352: We make pessimistic assumptions about shifting, trying always to
        !          2353: keep the arguments between 0 and 31 inclusive.
        !          2354: \enddocs
        !          2355: \begincode{3}
        !          2356: \moddef{BEGIN}\endmoddef
        !          2357: print "structure Opcodes = struct"
        !          2358: print "val andb = Bits.andb"
        !          2359: print "fun lshift(op1,amt) = "
        !          2360: print "    if amt<0 then Bits.rshift(op1,0-amt)"
        !          2361: print "    else Bits.lshift(op1,amt)"
        !          2362: print "nonfix sub"      # bug fixes; want \code{}sub\edoc{} to be a MIPS opcode
        !          2363: print "nonfix div"      # bug fixes; want \code{}div\edoc{} to be a MIPS opcode
        !          2364: 
        !          2365: decode = "mipsdecode.sml";
        !          2366: print "structure MipsDecode = struct" > decode
        !          2367: print "val andb = Bits.andb" > decode
        !          2368: print "fun rshift(op1,amt) = " > decode
        !          2369: print "    if amt<0 then Bits.lshift(op1,0-amt)" > decode
        !          2370: print "    else Bits.rshift(op1,amt)" > decode
        !          2371: \endcode
        !          2372: \begincode{4}
        !          2373: \moddef{END}\endmoddef
        !          2374: \LA{}write out the definitions of the decoding functions\RA{}
        !          2375: print "end (* Opcodes *)"
        !          2376: print "end (* Decode *)" > decode
        !          2377: \endcode
        !          2378: \begindocs{5}
        !          2379: The sections BEGIN and END are drawn from 
        !          2380:  our universal model of an awk program:
        !          2381: \enddocs
        !          2382: \begincode{6}
        !          2383: \moddef{*}\endmoddef
        !          2384: BEGIN \{
        !          2385:   \LA{}BEGIN\RA{}
        !          2386: \}
        !          2387: \LA{}functions\RA{}
        !          2388: \LA{}statements\RA{}
        !          2389: END \{
        !          2390:   \LA{}END\RA{}
        !          2391: \}
        !          2392: \endcode
        !          2393: \begindocs{7}
        !          2394: \section{The opcode tables}
        !          2395: The numeric codes for all the MIPS opcodes are described in three
        !          2396: tables in the MIPS book on page~A-87.
        !          2397: Normal opcodes are six bits, and appear in the \code{}opcode\edoc{} field of the
        !          2398: instruction.
        !          2399: Two opcodes \code{}special\edoc{} and \code{}bcond\edoc{} stand for several instructions.
        !          2400: These instructions are decoded by checking the bit-pattern in the
        !          2401: \code{}funct\edoc{} and \code{}cond\edoc{} fields of the instructions, respectively.
        !          2402: 
        !          2403: The tables show which opcodes correspond to which bit-patterns.
        !          2404: For example, the \code{}slti\edoc{} corresponds to an \code{}opcode\edoc{} value of octal~12.
        !          2405: The table headed \code{}opcode\edoc{} gives the mnemonics for all six-bit patterns
        !          2406: in the \code{}opcode\edoc{} field.
        !          2407: The \code{}special\edoc{} table shows patterns for the \code{}funct\edoc{} field, used with
        !          2408: the \code{}special\edoc{} opcode.
        !          2409: The \code{}bcond\edoc{} table shows five-bit patterns for the \code{}cond\edoc{} field,
        !          2410: used with the \code{}bcond\edoc{} opcode.
        !          2411: In all tables, stars (\code{}*\edoc{}) stand for unused fields.
        !          2412: 
        !          2413: Each table is terminated with a blank line.
        !          2414: \enddocs
        !          2415: \begincode{8}
        !          2416: \moddef{opcodes table}\endmoddef
        !          2417:                             opcode
        !          2418: special bcond   j       jal     beq     bne     blez    bgtz
        !          2419: addi    addiu   slti    sltiu   andi    ori     xori    lui
        !          2420: cop0    cop1    cop2    cop3    *       *       *       *
        !          2421: *       *       *       *       *       *       *       *
        !          2422: lb      lh      lwl     lw      lbu     lhu     lwr     *
        !          2423: sb      sh      swl     sw      *       *       swr     *
        !          2424: lwc0    lwc1    lwc2    lwc3    *       *       *       *
        !          2425: swc0    swc1    swc2    swc3    *       *       *       *
        !          2426: 
        !          2427:                             special
        !          2428: sll     *       srl     sra     sllv    *       srlv    srav
        !          2429: jr      jalr    *       *       syscall break   *       *
        !          2430: mfhi    mthi    mflo    mtlo    *       *       *       *
        !          2431: mult    multu   div     divu    *       *       *       *
        !          2432: add     addu    sub     subu    and'    or      xor     nor
        !          2433: *       *       slt     sltu    *       *       *       *
        !          2434: *       *       *       *       *       *       *       *
        !          2435: *       *       *       *       *       *       *       *
        !          2436: 
        !          2437:                             bcond
        !          2438: bltz    bgez    *       *       *       *       *       *
        !          2439: *       *       *       *       *       *       *       *
        !          2440: bltzal  bgezal  *       *       *       *       *       *
        !          2441: *       *       *       *       *       *       *       *
        !          2442: 
        !          2443: 
        !          2444: \endcode
        !          2445: \begindocs{9}
        !          2446: The instructions codes for Coprocessor 1 (floating point)
        !          2447: are takin from page B-28 of the Mips book.
        !          2448: \enddocs
        !          2449: \begincode{10}
        !          2450: \moddef{opcodes table}\endmoddef
        !          2451:                             cop1
        !          2452: add_fmt sub_fmt mul_fmt div_fmt *       abs_fmt mov_fmt neg_fmt
        !          2453: *       *       *       *       *       *       *       *
        !          2454: *       *       *       *       *       *       *       *
        !          2455: *       *       *       *       *       *       *       *
        !          2456: cvt_s   cvt_d   *       *       cvt_w   *       *       *
        !          2457: *       *       *       *       *       *       *       *
        !          2458: c_f     c_un    c_eq    c_ueq   c_olt   c_ult   c_ole   c_ule
        !          2459: c_sf    c_ngle  c_seq   c_ngl   c_lt    c_nge   c_le    c_ngt
        !          2460: 
        !          2461: \endcode
        !          2462: \begindocs{11}
        !          2463: 
        !          2464: Now we have to deal with reading these tables, and extracting the
        !          2465: information stored therein.
        !          2466: First of all, for each mnemonic \code{}$i\edoc{} we store the corresponding bit
        !          2467: pattern (as an integer, \code{}code\edoc{}) in the array \code{}numberof[$i] \edoc{}.
        !          2468: Then, we store the type of the mnemonic (ordinary \code{}OPCODE\edoc{}, 
        !          2469: \code{}SPECIAL\edoc{}, \code{}BCOND\edoc{}, of \code{}COP1\edoc{}) in the array \code{}typeof[$i] \edoc{}.
        !          2470: Finally, we store inverse (a map from type and bit pattern to mnemonic)
        !          2471: in the \code{}opcode\edoc{} array.
        !          2472: \enddocs
        !          2473: \begincode{12}
        !          2474: \moddef{store opcode information}\endmoddef
        !          2475: if ($i != "*") \{
        !          2476:         numberof[$i] = code
        !          2477:         typeof[$i] = type
        !          2478:         opcode[type,code] = $i
        !          2479: \} else \{
        !          2480:         opcode[type,code] = "reserved"
        !          2481: \}
        !          2482: \endcode
        !          2483: \begindocs{13}
        !          2484: The types are just constants set at the beginning.
        !          2485: \enddocs
        !          2486: \begincode{14}
        !          2487: \moddef{BEGIN}\endmoddef
        !          2488: OPCODE = 1 ; SPECIAL = 2 ; BCOND = 3 ; COP1 = 4
        !          2489: \endcode
        !          2490: \begindocs{15}
        !          2491: We determine the type by scanning the header word that precedes
        !          2492: each table.
        !          2493: Once we see the appropriate table header, we set one of \code{}opcodes\edoc{},
        !          2494: \code{}specials\edoc{}, and \code{}bconds\edoc{}, so that determining the type is easy:
        !          2495: \enddocs
        !          2496: \begincode{16}
        !          2497: \moddef{set \code{}type\edoc{}}\endmoddef
        !          2498: type = OPCODE * opcodes + SPECIAL * specials + BCOND * bconds + COP1 * cop1s
        !          2499: \endcode
        !          2500: \begindocs{17}
        !          2501: Seeing the right table header causes us to set the right variable.
        !          2502: We also remember the line number, because we use the positions of later
        !          2503: lines to help extract the bit patterns from the table.
        !          2504: \enddocs
        !          2505: \begincode{18}
        !          2506: \moddef{statements}\endmoddef
        !          2507: NF == 1 && $1 == "opcode" \{
        !          2508:         startline = NR
        !          2509:         opcodes = 1
        !          2510:         next
        !          2511: \}
        !          2512: NF == 1 && $1 == "special" \{
        !          2513:         startline = NR
        !          2514:         specials = 1
        !          2515:         next
        !          2516: \}
        !          2517: NF == 1 && $1 == "bcond" \{
        !          2518:         startline = NR
        !          2519:         bconds = 1
        !          2520:         next
        !          2521: \}
        !          2522: NF == 1 && $1 == "cop1" \{
        !          2523:         startline = NR
        !          2524:         cop1s = 1
        !          2525:         next
        !          2526: \}
        !          2527: \endcode
        !          2528: \begindocs{19}
        !          2529: Any time we see a blank line, that ends the appropriate table.
        !          2530: \enddocs
        !          2531: \begincode{20}
        !          2532: \moddef{statements}\endmoddef
        !          2533: NF == 0 \{opcodes = 0; specials = 0; bconds = 0; cop1s = 0
        !          2534:         \LA{}blank line resets\RA{}
        !          2535: \}
        !          2536: \endcode
        !          2537: \begindocs{21}
        !          2538: Here is the code that actually extracts the bit patterns from
        !          2539: the opcode tables.
        !          2540: The code is the same for each of the three tables.
        !          2541: 
        !          2542: The \code{}insist_fields(8)\edoc{} issues an error message and returns false (0)
        !          2543: unless there are exactly 8 fields on the input line.
        !          2544: \enddocs
        !          2545: \begincode{22}
        !          2546: \moddef{statements}\endmoddef
        !          2547: opcodes || specials || bconds || cop1s \{
        !          2548:         if (!insist_fields(8)) next
        !          2549:         \LA{}set \code{}type\edoc{}\RA{}
        !          2550:         major = NR - startline - 1              # major octal digit from row
        !          2551:         for (i=1; i<= NF; i++) \{
        !          2552:                 minor = i-1                     # minor octal digit from column
        !          2553:                 code = minor + 8 * major
        !          2554:                 \LA{}store opcode information\RA{}
        !          2555:         \}
        !          2556: \}
        !          2557: \endcode
        !          2558: \begindocs{23}
        !          2559: \section{The instruction fields}
        !          2560: Now that we've dealt with the opcodes, we'll handle other fields of
        !          2561: the instruction.
        !          2562: This table tells us the position of each field within the word,
        !          2563: so that if we know a bit-pattern for each field, we can assemble
        !          2564: all the fields into an instruction.
        !          2565: 
        !          2566: Not all fields are used in all instructions.
        !          2567: Later we'll have a table that indicates exactly which fields are used in
        !          2568: which instructions.
        !          2569: For now, we just list the fields and their positions with the
        !          2570: understanding that some fields will overlap.
        !          2571: 
        !          2572: The table is taken from the MIPS book, page A-3.
        !          2573: The numbers are the numbers of the starting and ending bit positions,
        !          2574: where 0 is the least and 31 the most significant bit.
        !          2575: The names are exactly those used in the book except \code{}op'\edoc{} has been
        !          2576: substituted for \code{}op\edoc{} since \code{}op\edoc{} is a reserved word in ML.
        !          2577: 
        !          2578: If a field is signed, we put a \code{}+\edoc{}~sign as the first character
        !          2579: of its name.
        !          2580: The sign information is used only in decoding (I think).
        !          2581: \enddocs
        !          2582: \begincode{24}
        !          2583: \moddef{opcodes table}\endmoddef
        !          2584:                         fields
        !          2585: op' 26 31
        !          2586: rs 21 25
        !          2587: rt 16 20
        !          2588: +immed 0 15
        !          2589: +offset 0 15
        !          2590: base 21 25
        !          2591: target 0 25
        !          2592: rd 11 15
        !          2593: shamt 6 10
        !          2594: funct 0 5
        !          2595: cond 16 20
        !          2596: \LA{}floating point load/store fields\RA{}
        !          2597: \LA{}floating point computation fields\RA{}
        !          2598: 
        !          2599: \endcode
        !          2600: \begindocs{25}
        !          2601: From page B-5.  Most fields are the same as the CPU instruction formats.
        !          2602: \enddocs
        !          2603: \begincode{26}
        !          2604: \moddef{floating point load/store fields}\endmoddef
        !          2605: ft 16 20
        !          2606: \endcode
        !          2607: \begindocs{27}
        !          2608: From page B-6.  Many fields are reused from earlier specifications.
        !          2609: The computational instructions all have a one bit in position 25.
        !          2610: Instead of trying to insert special code to handle that, we cheat on
        !          2611: it by making that bit part of the format, and cheating on the format.
        !          2612: Thus:
        !          2613: \enddocs
        !          2614: \begincode{28}
        !          2615: \moddef{floating point computation fields}\endmoddef
        !          2616: fmt 21 25
        !          2617: fs 11 15
        !          2618: fd 6 10
        !          2619: \endcode
        !          2620: \begincode{29}
        !          2621: \moddef{write format info}\endmoddef
        !          2622: print "val S_fmt = 16+0"
        !          2623: print "val D_fmt = 16+1"
        !          2624: print "val W_fmt = 16+4"
        !          2625: 
        !          2626: \endcode
        !          2627: \begindocs{30}
        !          2628: The setup for the fields is similar to that used for the opcodes.
        !          2629: \enddocs
        !          2630: \begincode{31}
        !          2631: \moddef{statements}\endmoddef
        !          2632: NF == 1 && $1 == "fields" \{
        !          2633:         startline = NR
        !          2634:         fields = 1
        !          2635:         \LA{}write format info\RA{}
        !          2636:         next
        !          2637: \}
        !          2638: \endcode
        !          2639: \begincode{32}
        !          2640: \moddef{blank line resets}\endmoddef
        !          2641: fields = 0
        !          2642: \endcode
        !          2643: \begincode{33}
        !          2644: \moddef{statements}\endmoddef
        !          2645: fields \{
        !          2646:         if (!insist_fields(3)) next
        !          2647:         fieldname = $1;  low = $2; high = $3
        !          2648:         \LA{}look for sign in \code{}fieldname\edoc{} and set \code{}signed\edoc{}\RA{}
        !          2649:         fieldnames[fieldname]= 1        # rememeber all the field names
        !          2650: 
        !          2651:         \LA{}write to standard output a function to convert bit-pattern to pair\RA{}
        !          2652:         \LA{}write to \code{}decode\edoc{} a function to extract field from pair\RA{}
        !          2653: 
        !          2654: \}
        !          2655: \endcode
        !          2656: \begincode{34}
        !          2657: \moddef{look for sign in \code{}fieldname\edoc{} and set \code{}signed\edoc{}}\endmoddef
        !          2658: if (substr(fieldname,1,1)=="+") \{
        !          2659:         signed = 1
        !          2660:         fieldname = substr(fieldname,2)
        !          2661: \} else \{
        !          2662:         signed = 0
        !          2663: \}
        !          2664: \endcode
        !          2665: \begindocs{35}
        !          2666: 
        !          2667: The idea is that for each of these fields, we want to write a function
        !          2668: that will take an integer argument and shift it by the right amount.
        !          2669: Since we have to represent the 32-bit quantities as pairs of integers,
        !          2670: we actually use two functions, one for the high half and one for the low.
        !          2671: So, for example, for the \code{}rd\edoc{} field we will produce two function definitions,
        !          2672: \code{}rdHI\edoc{} and \code{}rdLO\edoc{}.
        !          2673: 
        !          2674: The awk function \code{}function_definition\edoc{} is used to compute ML function
        !          2675: definitions.
        !          2676: It takes as arguments the name of the function and the number of arguments
        !          2677: to that function.
        !          2678: The arguments are numbered \code{}A1\edoc{}, \code{}A2\edoc{}, et cetera.
        !          2679: 
        !          2680: The functions themselves are all tedious combinations of ands and shifts.
        !          2681: At one time I had convinced myself that this worked.
        !          2682: \enddocs
        !          2683: \begincode{36}
        !          2684: \moddef{write to standard output a function to convert bit-pattern to pair}\endmoddef
        !          2685: if (low >= 16) \{
        !          2686:         printf "%s", function_definition(fieldname "LO",1); print "0"
        !          2687: \} else \{
        !          2688:         printf "%s", function_definition(fieldname "LO",1)
        !          2689:         printf "andb(lshift(A1,%d),65535)\\n", low
        !          2690: \}
        !          2691: if (high < 16) \{
        !          2692:         printf "%s", function_definition(fieldname "HI",1); print "0"
        !          2693: \} else \{
        !          2694:         printf "%s", function_definition(fieldname "HI",1)
        !          2695:         printf "lshift(A1,%s)\\n", mlnumber(low - 16)
        !          2696: \}
        !          2697: \endcode
        !          2698: \begindocs{37}
        !          2699: The inverse operation is
        !          2700: to extract a bit pattern from a pair.
        !          2701: We'll want that if we ever care to decode instructions.
        !          2702: This time, the function to extract e.g.\ field \code{}rd\edoc{} from a pair
        !          2703: is the function \code{}THErd\edoc{} applied to that pair.
        !          2704: 
        !          2705: The functions work first by extracting from the low part, then
        !          2706: from the high part, and adding everything together.
        !          2707: If the field is signed, we make the value negative if it is too high.
        !          2708: \enddocs
        !          2709: \begincode{38}
        !          2710: \moddef{write to \code{}decode\edoc{} a function to extract field from pair}\endmoddef
        !          2711: printf "%s", function_definition("THE" fieldname,2) > decode
        !          2712: if (signed) printf "let val n = " > decode
        !          2713: \LA{}print expression for unsigned value\RA{}
        !          2714: if (signed) \{
        !          2715:         printf "in if n < %d then n else n - %d\\nend\\n",
        !          2716:                 2**(high-low), 2**(high-low+1) > decode
        !          2717: \}
        !          2718: 
        !          2719: \endcode
        !          2720: \begincode{39}
        !          2721: \moddef{print expression for unsigned value}\endmoddef
        !          2722: if (low >= 16) \{
        !          2723:         printf "0" > decode
        !          2724: \} else \{
        !          2725:         printf "andb(rshift(A2,%d),%d)", low,
        !          2726:                         (2**(min(15,high)-low+1)-1) > decode
        !          2727: \}
        !          2728: printf " + " > decode
        !          2729: if (high < 16) \{
        !          2730:         printf "0\\n" > decode
        !          2731: \} else \{
        !          2732:         printf "rshift(andb(A1,%d),%s)\\n", (2**(high-16+1)-1),
        !          2733:                         mlnumber(low - 16) > decode
        !          2734: \}
        !          2735: \endcode
        !          2736: \begindocs{40}
        !          2737: ML uses a strange minus sign (\code{}~\edoc{} instead of \code{}-\edoc{}), 
        !          2738: so we print numbers that might be negative like this:
        !          2739: \enddocs
        !          2740: \begincode{41}
        !          2741: \moddef{functions}\endmoddef
        !          2742: function mlnumber(n, s) \{
        !          2743:         if (n<0) s = sprintf("~%d", -n)
        !          2744:         else s = sprintf("%d", n)
        !          2745:         return s
        !          2746: \}
        !          2747: \endcode
        !          2748: \begindocs{42}
        !          2749: For reasons best known to its designers, awk has no \code{}min\edoc{} function.
        !          2750: \enddocs
        !          2751: \begincode{43}
        !          2752: \moddef{functions}\endmoddef
        !          2753: function min(x,y)\{
        !          2754:         if (x<y) return x
        !          2755:         else return y
        !          2756: \}
        !          2757: \endcode
        !          2758: \begindocs{44}
        !          2759: \section{The list of instructions and their formats}
        !          2760: This is the section that tells which fields are used in what instructions,
        !          2761: and in what order the fields appear.
        !          2762: The information is from Appendix A
        !          2763: of the MIPS book and should be proofread.
        !          2764: 
        !          2765: To cut down on the number of ML functions generated, we can comment out
        !          2766: instructions with a \code{}#\edoc{} in the first column.
        !          2767: This means that no code will be generated for the instruction, and
        !          2768: it won't appear in the \code{}structure Opcodes\edoc{}.
        !          2769: \enddocs
        !          2770: \begincode{45}
        !          2771: \moddef{opcodes table}\endmoddef
        !          2772:                         instructions
        !          2773: add rd rs rt
        !          2774: addi rt rs immed
        !          2775: addiu rt rs immed
        !          2776: addu rd rs rt
        !          2777: and' rd rs rt
        !          2778: andi rt rs immed
        !          2779: beq rs rt offset
        !          2780: bgez rs offset
        !          2781: bgezal rs offset
        !          2782: bgtz rs offset
        !          2783: blez rs offset
        !          2784: bltz rs offset
        !          2785: bltzal rs offset
        !          2786: bne rs rt offset
        !          2787: break
        !          2788: div rs rt
        !          2789: divu rs rt
        !          2790: j target
        !          2791: jal target
        !          2792: jalr rs rd
        !          2793: jr rs
        !          2794: lb rt offset base
        !          2795: lbu rt offset base
        !          2796: lh rt offset base
        !          2797: lb rt offset base
        !          2798: lhu rt offset base
        !          2799: lui rt immed
        !          2800: lw rt offset base
        !          2801: lwl rt offset base
        !          2802: lwr rt offset base
        !          2803: mfhi rd
        !          2804: mflo rd
        !          2805: mthi rs
        !          2806: mtlo rs
        !          2807: mult rs rt
        !          2808: multu rs rt
        !          2809: nor rd rs rt
        !          2810: or rd rs rt
        !          2811: ori rt rs immed
        !          2812: sb rt offset base
        !          2813: sh rt offset base
        !          2814: sll rd rt shamt
        !          2815: sllv rd rt rs
        !          2816: slt rd rs rt
        !          2817: slti rt rs immed
        !          2818: sltiu rt rs immed
        !          2819: sltu rd rs rt
        !          2820: sra rd rt shamt
        !          2821: srav rd rt rs
        !          2822: srl rd rt shamt
        !          2823: srlv rd rt rs
        !          2824: sub rd rs rt
        !          2825: subu rd rs rt
        !          2826: sw rt offset base
        !          2827: swl rt offset base
        !          2828: swr rt offset base
        !          2829: syscall
        !          2830: xor rd rs rt
        !          2831: xori rt rs immed
        !          2832: \LA{}floating point instructions\RA{}
        !          2833: 
        !          2834: 
        !          2835: \endcode
        !          2836: \begindocs{46}
        !          2837: We define only those floating point instructions we seem likely to need.
        !          2838: To distinguish them as floating point we append an f to their names.
        !          2839: \enddocs
        !          2840: \begincode{47}
        !          2841: \moddef{floating point instructions}\endmoddef
        !          2842: add_fmt fmt fd fs ft
        !          2843: div_fmt fmt fd fs ft
        !          2844: lwc1 ft offset base
        !          2845: mul_fmt fmt fd fs ft
        !          2846: neg_fmt fmt fd fs
        !          2847: sub_fmt fmt fd fs ft
        !          2848: swc1 ft offset base
        !          2849: c_seq fmt fs ft
        !          2850: c_lt fmt fs ft
        !          2851: \endcode
        !          2852: \begindocs{48}
        !          2853: 
        !          2854:  Here is a terrible hack to enable us to construct branch on coprocessor~1
        !          2855: true or false.
        !          2856: We will use \code{}fun bc1f offset = cop1(0,offset)\edoc{} and
        !          2857:         \code{}fun bc1t offset = cop1(1,offset)\edoc{}.
        !          2858: \enddocs
        !          2859: \begincode{49}
        !          2860: \moddef{floating point instructions}\endmoddef
        !          2861: cop1 rs rt offset
        !          2862: \endcode
        !          2863: \begindocs{50}
        !          2864: 
        !          2865: 
        !          2866: 
        !          2867: \enddocs
        !          2868: \begindocs{51}
        !          2869: For each instruction, we define an ML function with the appropriate
        !          2870: number of arguments.
        !          2871: When that function is given an integer in each argument,
        !          2872: it converts the whole thing to one MIPS instruction, represented as an
        !          2873: integer pair.
        !          2874: 
        !          2875: The implementation is a bit of a grubby mess.
        !          2876: Doing the fields is straightforward enough, but
        !          2877: for each mnemonic we have to do something different based
        !          2878: on its type, because each type of opcode goes in a different
        !          2879: field.
        !          2880: Moreover, for mnemonics of type \code{}SPECIAL\edoc{}, \code{}BCOND\edoc{}, and \code{}COP1\edoc{} we
        !          2881: have to generate \code{}special\edoc{}, \code{}bcond\edoc{}, and \code{}cop1\edoc{} in the \code{}op'\edoc{} field.
        !          2882: Finally, we have to do it all twice; once for the high order
        !          2883: halfword and once for the low order halfword.
        !          2884: \enddocs
        !          2885: \begincode{52}
        !          2886: \moddef{compute function that generates this instruction}\endmoddef
        !          2887:         printf "%s", function_definition(opname, NF-1)
        !          2888:         printf "("      # open parenthesis for pair
        !          2889:         for (i=2; i<= NF; i++) \{
        !          2890:                 if (!($i in fieldnames)) \LA{}bad field name\RA{}
        !          2891:                 printf "%sHI(A%d)+", $i, i-1
        !          2892:         \}
        !          2893:         if (typeof[opname]==OPCODE) \{
        !          2894:                 printf "op'HI(%d)", numberof[opname]
        !          2895:         \} else if (typeof[opname]==SPECIAL) \{
        !          2896:                 printf "op'HI(%d)+", numberof["special"]
        !          2897:                 printf "functHI(%d)", numberof[opname]
        !          2898:         \} else if (typeof[opname]==BCOND) \{
        !          2899:                 printf "op'HI(%d)+", numberof["bcond"]
        !          2900:                 printf "condHI(%d)", numberof[opname]
        !          2901:         \} else if (typeof[opname]==COP1) \{
        !          2902:                 printf "op'HI(%d)+", numberof["cop1"]
        !          2903:                 printf "functHI(%d)", numberof[opname]
        !          2904:         \} else \LA{}bad operator name\RA{}
        !          2905:         printf ", "
        !          2906:         for (i=2; i<= NF; i++) \{
        !          2907:                 if (!($i in fieldnames)) \LA{}bad field name\RA{}
        !          2908:                 printf "%sLO(A%d)+", $i, i-1
        !          2909:         \}
        !          2910:         if (typeof[opname]==OPCODE) \{
        !          2911:                 printf "op'LO(%d)", numberof[opname]
        !          2912:         \} else if (typeof[opname]==SPECIAL) \{
        !          2913:                 printf "op'LO(%d)+", numberof["special"]
        !          2914:                 printf "functLO(%d)", numberof[opname]
        !          2915:         \} else if (typeof[opname]==BCOND) \{
        !          2916:                 printf "op'LO(%d)+", numberof["bcond"]
        !          2917:                 printf "condLO(%d)", numberof[opname]
        !          2918:         \} else if (typeof[opname]==COP1) \{
        !          2919:                 printf "op'LO(%d)+", numberof["cop1"]
        !          2920:                 printf "functLO(%d)", numberof[opname]
        !          2921:         \} else \LA{}bad operator name\RA{}
        !          2922:         printf ")\\n"
        !          2923: \endcode
        !          2924: \begindocs{53}
        !          2925: 
        !          2926: Setup is as before.
        !          2927: \enddocs
        !          2928: \begincode{54}
        !          2929: \moddef{statements}\endmoddef
        !          2930: NF == 1 && $1 == "instructions" \{
        !          2931:         startline = NR
        !          2932:         instructions = 1
        !          2933:         next
        !          2934: \}
        !          2935: \endcode
        !          2936: \begincode{55}
        !          2937: \moddef{blank line resets}\endmoddef
        !          2938: instructions= 0
        !          2939: \endcode
        !          2940: \begincode{56}
        !          2941: \moddef{statements}\endmoddef
        !          2942: instructions && $0 !~ /^#/ \{
        !          2943:         opname = $1
        !          2944: 
        !          2945:         \LA{}compute string displayed when this instruction is decoded\RA{}
        !          2946: ########        gsub("[^a-z']+"," ")   ### ill-advised
        !          2947: 
        !          2948:         \LA{}compute function that generates this instruction\RA{}
        !          2949: \}
        !          2950: 
        !          2951: \endcode
        !          2952: \begindocs{57}
        !          2953: \paragraph{Decoding instructions}
        !          2954: When we've decoded an instruction, we have to display some sort of
        !          2955: string representation that tells us what the instruction is.
        !          2956: Ideally we should display either just what the assembler expects,
        !          2957: or perhaps just what dbx displays when asked about actual instructions
        !          2958: in memory images.
        !          2959: 
        !          2960: For now, we just give the mnemonic for the instruction, followed
        !          2961: by a description of each field (followed by a newline).
        !          2962: The fields are described as name-value pairs.
        !          2963: 
        !          2964: We rely on the fact that for a field e.g.\ \code{}rd\edoc{}, the string
        !          2965: representation of the value of that field is in \code{}Srd\edoc{}.
        !          2966: \enddocs
        !          2967: \begincode{58}
        !          2968: \moddef{compute string displayed when this instruction is decoded}\endmoddef
        !          2969: temp = "\\"" opname " \\""
        !          2970: for (i=2; i<=NF; i++) \{
        !          2971:         temp = sprintf( "%s ^ \\"%s = \\" ^ S%s", temp, $i, $i)
        !          2972:         if (i<NF) temp = sprintf("%s ^ \\",\\" ", temp)
        !          2973: \}
        !          2974: displayof[opname]=temp " ^ \\"\\\\n\\""
        !          2975: 
        !          2976: \endcode
        !          2977: \begindocs{59}
        !          2978: The implementation of the decoding function is split into several parts.
        !          2979: First, we have to be able to extract any field from an instruction.
        !          2980: Then, we have to be able to decode four kinds of opcodes:
        !          2981: \code{}OPCODE\edoc{}s, \code{}BCOND\edoc{}s,  \code{}SPECIAL\edoc{}s, and \code{}COP1\edoc{}s.
        !          2982: The main function is the one that does ordinary opcodes.
        !          2983: The others are auxiliary.
        !          2984: \enddocs
        !          2985: \begincode{60}
        !          2986: \moddef{write out the definitions of the decoding functions}\endmoddef
        !          2987: printf "%s", function_definition("decode",2) > decode
        !          2988: print "let" > decode
        !          2989:   \LA{}write definitions of integer and string representations of each field\RA{}
        !          2990:   \LA{}write expression that decodes the \code{}funct\edoc{} field for \code{}special\edoc{}s\RA{}
        !          2991:   \LA{}write expression that decodes the \code{}cond\edoc{} field for \code{}bcond\edoc{}s\RA{}
        !          2992:   \LA{}write expression that decodes the \code{}funct\edoc{} field for \code{}cop1\edoc{}s\RA{}
        !          2993: print "in" > decode
        !          2994:   \LA{}write \code{}case\edoc{} expression that decodes the \code{}op'\edoc{} field for each instruction\RA{}
        !          2995: print "end" > decode
        !          2996: \endcode
        !          2997: \begindocs{61}
        !          2998: We give each field its own name for an integer version, and its name
        !          2999: preceded by \code{}S\edoc{} for its string version.
        !          3000: These values are all computed just once, from the arguments to the
        !          3001: enclosing function (\code{}decode\edoc{}).
        !          3002: \enddocs
        !          3003: \begincode{62}
        !          3004: \moddef{write definitions of integer and string representations of each field}\endmoddef
        !          3005: for (f in fieldnames) \{
        !          3006:         printf "val %s = THE%s(A1,A2)\\n", f, f  > decode
        !          3007:         printf "val S%s = Integer.makestring %s\\n", f, f  > decode
        !          3008: \}
        !          3009: \endcode
        !          3010: \begindocs{63}
        !          3011: The next three functions are very much of a piece.
        !          3012: They are just enormous \code{}case\edoc{} expressions that match up integers
        !          3013: (bit patterns) to strings.
        !          3014: The fundamental operation is printing out a decimal value and a string
        !          3015: for each opcode:
        !          3016: \enddocs
        !          3017: \begincode{64}
        !          3018: \moddef{if \code{}name\edoc{} is known, display a case for it}\endmoddef
        !          3019: if (name != ""  && name != "reserved") \{
        !          3020:         \LA{}print space or bar (\code{}|\edoc{})\RA{}
        !          3021:         disp = displayof[name]
        !          3022:         if (disp=="") disp="\\"" name "(??? unknown format???)\\\\n\\""
        !          3023:         printf "%d => %s\\n", code, disp > decode
        !          3024: \}
        !          3025: \endcode
        !          3026: \begindocs{65}
        !          3027: Cases must be separated by vertical bars.
        !          3028: We do the separation by putting a vertical bar before each case except
        !          3029: the first.
        !          3030: We use a hack to discover the first; we assume that code~0 is always
        !          3031: defined, and so it will always be the first.
        !          3032: \enddocs
        !          3033: \begincode{66}
        !          3034: \moddef{print space or bar (\code{}|\edoc{})}\endmoddef
        !          3035: if (code!=0) printf " | "  > decode # hack but it works
        !          3036: else printf "   " > decode
        !          3037: \endcode
        !          3038: \begincode{67}
        !          3039: \moddef{write expression that decodes the \code{}funct\edoc{} field for \code{}special\edoc{}s}\endmoddef
        !          3040: print "val do_special ="  > decode
        !          3041: print "(case funct of" > decode
        !          3042: for (code=0; code<256; code++) \{
        !          3043:         name = opcode[SPECIAL,code]
        !          3044:         \LA{}if \code{}name\edoc{} is known, display a case for it\RA{}
        !          3045: \}
        !          3046: printf " | _ => \\"unknown special\\\\n\\"\\n" > decode
        !          3047: print "   ) " > decode
        !          3048: \endcode
        !          3049: \begincode{68}
        !          3050: \moddef{write expression that decodes the \code{}cond\edoc{} field for \code{}bcond\edoc{}s}\endmoddef
        !          3051: print "val do_bcond =" > decode
        !          3052: print "(case cond of" > decode
        !          3053: for (code=0; code<256; code++) \{
        !          3054:         name = opcode[BCOND,code]
        !          3055:         \LA{}if \code{}name\edoc{} is known, display a case for it\RA{}
        !          3056: \}
        !          3057: printf " | _ => \\"unknown bcond\\\\n\\"\\n" > decode
        !          3058: print "   ) " > decode
        !          3059: \endcode
        !          3060: \begincode{69}
        !          3061: \moddef{write expression that decodes the \code{}funct\edoc{} field for \code{}cop1\edoc{}s}\endmoddef
        !          3062: print "val do_cop1 =" > decode
        !          3063: print "(case funct of" > decode
        !          3064: for (code=0; code<256; code++) \{
        !          3065:         name = opcode[COP1,code]
        !          3066:         \LA{}if \code{}name\edoc{} is known, display a case for it\RA{}
        !          3067: \}
        !          3068: printf " | _ => \\"unknown cop1\\\\n\\"\\n" > decode
        !          3069: print "   ) " > decode
        !          3070: \endcode
        !          3071: \begindocs{70}
        !          3072: The major expression is a little more complicated, because it has to
        !          3073: check for \code{}special\edoc{}, \code{}bcond\edoc{}, and \code{}cop1\edoc{} and handle those separately.
        !          3074: \enddocs
        !          3075: \begincode{71}
        !          3076: \moddef{write \code{}case\edoc{} expression that decodes the \code{}op'\edoc{} field for each instruction}\endmoddef
        !          3077: print "(case op' of" > decode
        !          3078: for (code=0; code<256; code++) \{
        !          3079:         name = opcode[OPCODE,code]
        !          3080:         if (name=="special") \{
        !          3081:                 \LA{}print space or bar (\code{}|\edoc{})\RA{}
        !          3082:                 printf "%d => %s\\n", code, "do_special" > decode
        !          3083:         \} else if (name=="bcond") \{
        !          3084:                 \LA{}print space or bar (\code{}|\edoc{})\RA{}
        !          3085:                 printf "%d => %s\\n", code, "do_bcond" > decode
        !          3086:         \} else if (name=="cop1") \{
        !          3087:                 \LA{}print space or bar (\code{}|\edoc{})\RA{}
        !          3088:                 printf "%d => %s\\n", code, "do_cop1" > decode
        !          3089:         \} else \LA{}if \code{}name\edoc{} is known, display a case for it\RA{}
        !          3090: \}
        !          3091: printf " | _ => \\"unknown opcode\\\\n\\"\\n" > decode
        !          3092: print "   ) " > decode
        !          3093: \endcode
        !          3094: \begindocs{72}
        !          3095: \section{testing}
        !          3096: One day someone will have to modify the instruction handler so that
        !          3097: it generates a test invocation of each instruction.
        !          3098: Then the results can be handed to something like adb or dbx and we can
        !          3099: see whether the system agrees with us about what we're generating.
        !          3100: 
        !          3101: \enddocs
        !          3102: \begindocs{73}
        !          3103: \section{Defining ML functions}
        !          3104: The awk function \code{}function_definition\edoc{} is used to
        !          3105: come up with ML function definitions.
        !          3106: It takes as arguments the name of the function and the number of arguments
        !          3107: to that function, and returns a string containing the initial part of
        !          3108: the function definition.
        !          3109: Writing an expression following that string will result in a complete
        !          3110: ML function.
        !          3111: 
        !          3112: If we ever wanted to define these things as C preprocessor macros instead,
        !          3113: we could do it by substituting \code{}macro_definition\edoc{}.
        !          3114: I'm not sure it would ever make sense to do so, but I'm leaving the
        !          3115: code here anyway.
        !          3116: \enddocs
        !          3117: \begincode{74}
        !          3118: \moddef{functions}\endmoddef
        !          3119: function function_definition(name, argc,  i, temp) \{
        !          3120:         if (argc==0) \{
        !          3121:                 temp = sprintf("val %s = ", name)
        !          3122:         \} else \{
        !          3123:                 temp = sprintf( "fun %s(", name)
        !          3124:                 for (i=1; i< argc; i++) temp = sprintf("%sA%d,", temp,i)
        !          3125:                 temp = sprintf( "%sA%d) = ", temp, argc)
        !          3126:         \}
        !          3127:         return temp
        !          3128: \}
        !          3129: \endcode
        !          3130: \begincode{75}
        !          3131: \moddef{useless functions}\endmoddef
        !          3132: function macro_definition(name, argc,  i, temp) \{
        !          3133:         if (argc==0) \{
        !          3134:                 temp = sprintf("#define %s ", name)
        !          3135:         \} else \{
        !          3136:                 temp = sprintf( "#define %s(", name)
        !          3137:                 for (i=1; i< argc; i++) temp = sprintf("%sA%d,", temp,i)
        !          3138:                 temp = sprintf( "%sA%d) ", temp, argc)
        !          3139:         \}
        !          3140:         return temp
        !          3141: \}
        !          3142: \endcode
        !          3143: \begindocs{76}
        !          3144: \section{Handling error conditions}
        !          3145: Here are a bunch of uninteresting functions and modules
        !          3146: that handle error conditions.
        !          3147: \enddocs
        !          3148: \begincode{77}
        !          3149: \moddef{bad operator name}\endmoddef
        !          3150: \{
        !          3151:         print "unknown opcode", opname, "on line", NR > stderr
        !          3152:         next
        !          3153: \}
        !          3154: \endcode
        !          3155: \begincode{78}
        !          3156: \moddef{bad field name}\endmoddef
        !          3157: \{
        !          3158:         print "unknown field", $i, "on line", NR > stderr
        !          3159:         next
        !          3160: \}
        !          3161: \endcode
        !          3162: \begincode{79}
        !          3163: \moddef{BEGIN}\endmoddef
        !          3164: stderr="/dev/tty"
        !          3165: \endcode
        !          3166: \begincode{80}
        !          3167: \moddef{functions}\endmoddef
        !          3168: function insist_fields(n) \{
        !          3169:         if (NF != n) \{
        !          3170:                 print "Must have", n, "fields on line",NR ":", $0 > stderr
        !          3171:                 return 0
        !          3172:         \} else \{
        !          3173:                 return 1
        !          3174:         \}
        !          3175: \}
        !          3176: \endcode
        !          3177: \begindocs{81}
        !          3178: \section{Leftover junk}
        !          3179: Like a pack rat, I never throw out anything that might be useful again later.
        !          3180: \enddocs
        !          3181: \begincode{82}
        !          3182: \moddef{junk}\endmoddef
        !          3183: function thetype(n) \{
        !          3184:         if (n==OPCODE) return "OPCODE"
        !          3185:         else if (n==SPECIAL) return "SPECIAL"
        !          3186:         else if (n==BCOND) return "BCOND"
        !          3187:         else if (n==COP1) return "COP1"
        !          3188:         else return "BADTYPE"
        !          3189: \}
        !          3190: \endcode
        !          3191: \begincode{83}
        !          3192: \moddef{decoding junk}\endmoddef
        !          3193: for (f in fieldnames) \{
        !          3194:         printf "^ \\"\\\\n%s = \\" ^ Integer.makestring %s\\n",f,f > decode
        !          3195: \}
        !          3196: printf "^\\"\\\\n\\"\\n" > decode
        !          3197: \endcode
        !          3198: \filename{/u/nr/sml/36/src/runtime/MIPS.prim.nw}
        !          3199: \begindocs{0}
        !          3200: \section{Assembly-language primitives for the run-time system}
        !          3201: This file is derived from the similar file for the VAX.
        !          3202: We include \code{}<regdef.h>\edoc{}, which defines names for the registers.
        !          3203: \enddocs
        !          3204: \begincode{1}
        !          3205: \moddef{*}\endmoddef
        !          3206: #include "tags.h"
        !          3207: #include "prof.h"
        !          3208: #include "ml.h"
        !          3209: #include "prim.h"
        !          3210: \LA{}register definitions\RA{}
        !          3211: \LA{}\code{}String\edoc{} and \code{}Closure\edoc{} definitions\RA{}
        !          3212:         .data
        !          3213: \LA{}data segment items\RA{}
        !          3214:         .text
        !          3215: \LA{}run vector\RA{}
        !          3216: \LA{}array\RA{}
        !          3217: \LA{}string and bytearray\RA{}
        !          3218: \LA{}C linkage\RA{}
        !          3219: \LA{}calling C routines\RA{}
        !          3220: \LA{}system calls\RA{}
        !          3221: \LA{}floating point\RA{}
        !          3222: /* this bogosity is for export.c */
        !          3223:         .globl  startptr
        !          3224: startptr: .word    __start      /* just a guess... */
        !          3225: 
        !          3226: 
        !          3227: \endcode
        !          3228: \begindocs{2}
        !          3229: We define a couple of macros for creating strings and closures.
        !          3230: When calling \code{}String\edoc{} we should use a literal string whose length 
        !          3231: is a multiple of~4.
        !          3232: 
        !          3233: The closure of a primitive function
        !          3234:  is a record of length~1, containing a pointer to the first 
        !          3235: instruction in the function.
        !          3236: All closures have length~1 because there aren't any free variables in any 
        !          3237: of the primitive functions.
        !          3238: \enddocs
        !          3239: \begincode{3}
        !          3240: \moddef{\code{}String\edoc{} and \code{}Closure\edoc{} definitions}\endmoddef
        !          3241: #define String(handle,len,str) .align 2;\\
        !          3242:                                .set noreorder;\\
        !          3243:                                .word len*power_tags+tag_string;\\
        !          3244:                                handle: .ascii str;\\
        !          3245:                                .set reorder
        !          3246: #define Closure(name) .align    2;\\
        !          3247:                       .set noreorder;\\
        !          3248:                       .word     mak_desc(1,tag_record);\\
        !          3249:                       name:     .word 9f; /* address of routine */ \\
        !          3250:                       .word     1; /* here for historical reasons */\\
        !          3251:                       .word     tag_backptr;\\
        !          3252:                       .set reorder;\\
        !          3253:                       9:
        !          3254: \endcode
        !          3255: \begindocs{4}
        !          3256: \subsection{Allocation and garbage collection}
        !          3257: Put a brief summary here: gc is caused by storing beyond the end of high 
        !          3258: memory.
        !          3259: For that reason we store the last word of objects first.
        !          3260: 
        !          3261: \enddocs
        !          3262: \begindocs{5}
        !          3263: \subsection{Register usage}
        !          3264: \input regs
        !          3265: \enddocs
        !          3266: \begincode{6}
        !          3267: \moddef{register definitions}\endmoddef
        !          3268: #define stdarg 2
        !          3269: #define stdcont 3
        !          3270: #define stdclos 4
        !          3271: #define storeptr 22
        !          3272: #define dataptr 23
        !          3273: #define exnptr 30
        !          3274: #define artemp1 24
        !          3275: #define artemp2 25
        !          3276: #define artemp3 20
        !          3277: #define ptrtemp 21
        !          3278: \endcode
        !          3279: \begindocs{7}
        !          3280: The MIPS version of Unix doesn't put underscores in front of global names.
        !          3281: 
        !          3282: First we define the global \code{}runvec\edoc{}.
        !          3283: This is an Ml object that represents the substructure \code{}A\edoc{} in 
        !          3284: {\tt boot/assembly.sig}.
        !          3285: All the ML functions will call these primitives by grabbing them
        !          3286: out of this record, which contains pointers to all the primitives.
        !          3287: \enddocs
        !          3288: \begincode{8}
        !          3289: \moddef{run vector}\endmoddef
        !          3290: 
        !          3291:         .globl  runvec
        !          3292:         .align  2
        !          3293:         .word   mak_desc(8,tag_record)
        !          3294: runvec:
        !          3295:         .word   array_v
        !          3296:         .word   callc_v
        !          3297:         .word   create_b_v
        !          3298:         .word   create_s_v
        !          3299:         .word   floor_v
        !          3300:         .word   logb_v
        !          3301:         .word   scalb_v
        !          3302:         .word   syscall_v
        !          3303: 
        !          3304: \endcode
        !          3305: \begindocs{9}
        !          3306: \subsection{Creating arrays, strings, and bytearrays}
        !          3307: \code{}array(m,x)\edoc{} creates an array of length $n$, each element initialized
        !          3308: to $x$.
        !          3309: (The corresponding record creation code is not implemented as a primitive; 
        !          3310: the ML compiler generates that code in line.)
        !          3311: $n$~is a tagged integer representing the length in words; 
        !          3312: $x$ can be any value.
        !          3313: This routine will loop forever (or until something strange happens
        !          3314: in memory) if $n<0$.
        !          3315: 
        !          3316: We need to be careful in the implementation to make sure all register values 
        !          3317: are sensible when garbage collection might occur.
        !          3318: 
        !          3319: If the order of instructions seems a little strange, it's because we try to
        !          3320: make sensible use of load delay slots.
        !          3321: \enddocs
        !          3322: \begincode{10}
        !          3323: \moddef{array}\endmoddef
        !          3324: Closure(array_v)
        !          3325:         lw $artemp1,0($stdarg)          /* tagged length in $artemp1 */
        !          3326:         lw $10,4($stdarg)               /* get initial value in $10 */
        !          3327:         sra $artemp1,1                  /* drop the tag bit */
        !          3328:         sll $artemp2,$artemp1,width_tags /* length for descr into $artemp2 */
        !          3329:         ori $artemp2,tag_array          /* complete descriptor into $artemp2 */
        !          3330:         sll $artemp1,2                  /* get length in bytes into $artemp1 */
        !          3331: .set noreorder  /* can't reorder because collection might occur */
        !          3332:         add $artemp3,$artemp1,$dataptr  /* $artemp3 points to last word 
        !          3333:                                                         of new array*/
        !          3334: badgc1: sw $0,($artemp3)                        /* clear; causes allocation */
        !          3335: .set reorder  /* can rearrange instructions again */
        !          3336: \endcode
        !          3337: \begincode{11}
        !          3338: \moddef{load bad pc into \code{}$artemp2\edoc{}; branch to \code{}badpc\edoc{} if == \code{}$artemp1\edoc{}}\endmoddef
        !          3339:         la $artemp2,badgc1
        !          3340:         beq $artemp1,$artemp2,badpc
        !          3341: \endcode
        !          3342: \begindocs{12}
        !          3343: At this point garbage collection may have occurred.
        !          3344: Ordinarily, we couldn't rely
        !          3345: on the value in \code{}$artemp3\edoc{}, because it's not forwarded.
        !          3346: However, this is one of the special garbage collection locations, 
        !          3347: so we do know that \code{}$artemp3\edoc{} is sensible.
        !          3348: But, since we really want something larger, we recompute it, 
        !          3349: using the (possibly changed) value of the data pointer.
        !          3350: Extra cleverness here might enable us to save one instruction.
        !          3351: \enddocs
        !          3352: \begincode{13}
        !          3353: \moddef{array}\endmoddef
        !          3354:         sw $artemp2,0($dataptr)         /* store the descriptor */
        !          3355:         add $dataptr,4                  /* points to new object */
        !          3356:         add $artemp3,$artemp1,$dataptr  /* beyond last word of new array*/
        !          3357:         add $stdarg,$dataptr,$0         /* put ptr in return register
        !          3358:                                         (return val = arg of continuation) */
        !          3359:         \LA{}store the initial value in every slot, leaving \code{}$dataptr\edoc{} pointing to the first free word\RA{}
        !          3360:         lw $10,0($stdcont)              /* grab continuation */
        !          3361:         j $10                           /* return */
        !          3362: 
        !          3363: \endcode
        !          3364: \begindocs{14}
        !          3365: With some clever thinking, the size of this loop could probably be cut 
        !          3366: from four instructions to three instructions.
        !          3367: \enddocs
        !          3368: \begincode{15}
        !          3369: \moddef{store the initial value in every slot, leaving \code{}$dataptr\edoc{} pointing to the first free word}\endmoddef
        !          3370:         b 2f
        !          3371: 1:      sw $10,0($dataptr)              /* store the value */
        !          3372:         addi $dataptr,4                 /* on to the next word */
        !          3373: 2:      bne $dataptr,$artemp3,1b        /* if not off the end, repeat */
        !          3374: 
        !          3375: 
        !          3376: \endcode
        !          3377: \begindocs{16}
        !          3378: \code{}create_b(n)\edoc{} creates a byte-array of length $n$, and
        !          3379: \code{}create_s(n)\edoc{} creates a string of length $n$.
        !          3380: 
        !          3381: We use the same code to create byte arrays and strings, since the only
        !          3382: difference is in the tags.
        !          3383: The odd arrangement of closures (odd because each one starts a new record)
        !          3384: causes no problems because this code isn't in the garbage-collectible region.
        !          3385: \enddocs
        !          3386: \begincode{17}
        !          3387: \moddef{string and bytearray}\endmoddef
        !          3388: Closure(create_b_v)
        !          3389:         addi $artemp3,$0,tag_bytearray  /* tag into $artemp3 */
        !          3390:         b       2f
        !          3391: Closure(create_s_v)
        !          3392:         addi $artemp3,$0,tag_string     /* tag into $artemp3 */
        !          3393: 2:      
        !          3394: \endcode
        !          3395: \begindocs{18}
        !          3396: The length computation may be a bit confusing.
        !          3397: We are handed a tagged integer $2n+1$, and we need to compute the required
        !          3398: number of words, which is $\lfloor{n+3\over 4}\rfloor$.
        !          3399: This is just $\lfloor{(2n+1)+5\over 8}\rfloor$.
        !          3400: However, we'll save an instruction later if we happen to have one more than 
        !          3401: the number of words tucked away in a register, 
        !          3402: because $1+\lfloor{n+3\over 4}\rfloor$ is the number of words
        !          3403: we're taking from the data space (we include the descriptor).
        !          3404: So we compute $(2n+1)+13$ and continue accordingly
        !          3405: \enddocs
        !          3406: \begincode{19}
        !          3407: \moddef{string and bytearray}\endmoddef
        !          3408:         addi    $artemp1,$stdarg,13     /* $2n+14$ */
        !          3409:         sra     $artemp1,3              /* number of words in string+tag */
        !          3410:         sll     $artemp1,2              /* # of bytes allocated for str+tag */
        !          3411: .set noreorder /* don't cross gc boundary */
        !          3412:         add     $artemp2,$artemp1,$dataptr /* beyond last word of string */
        !          3413: badgc2: sw $0,-4($artemp2)              /* clear last; causes allocation */
        !          3414: .set reorder
        !          3415:         sra     $artemp2,$stdarg,1      /* untagged length in bytes */
        !          3416:         sll     $artemp2,width_tags     /* room for descriptor */
        !          3417:         or      $artemp2,$artemp3       /* descriptor */
        !          3418:         sw      $artemp2,0($dataptr)    /* store descriptor */
        !          3419:         addi    $stdarg,$dataptr,4      /* pointer to new string */
        !          3420:         add     $dataptr,$artemp1       /* advance; save 1 instruction */
        !          3421:         lw $10,0($stdcont)              /* grab continuation */
        !          3422:         j $10                           /* return */
        !          3423: 
        !          3424: \endcode
        !          3425: \begincode{20}
        !          3426: \moddef{load bad pc into \code{}$artemp2\edoc{}; branch to \code{}badpc\edoc{} if == \code{}$artemp1\edoc{}}\endmoddef
        !          3427:         la $artemp2,badgc2
        !          3428:         beq $artemp1,$artemp2,badpc
        !          3429: 
        !          3430: \endcode
        !          3431: \begindocs{21}
        !          3432: \subsection{Linkage with C code}
        !          3433: C always gains control first, and stuffs something appropriate into
        !          3434: the register save areas before starting ML by calling \code{}restoreregs\edoc{}.
        !          3435: It also puts something appropriate in the ML \code{}saved_pc\edoc{}.
        !          3436: \code{}restoreregs\edoc{} squirrels away the current state of the C runtime stack,
        !          3437: restores the ML registers, and finally jumps to the saved program counter.
        !          3438: 
        !          3439: When ML wants to call C, it calls \code{}saveregs\edoc{}, which saves the ML state 
        !          3440: in the appropriate save areas, then restores the C runtime stack and returns.
        !          3441: Before returning to C, it sets \code{}cause\edoc{} to something appropriate.
        !          3442: 
        !          3443: All programs must ensure that \code{}restoreregs\edoc{} {\em never} calls itself
        !          3444: recursively, because it is {\em not} reentrant.
        !          3445: 
        !          3446: The C end of this connection is on display in the \code{}runML()\edoc{} function of
        !          3447: \code{}~ml/src/runtime/callgc.c\edoc{}.
        !          3448: \enddocs
        !          3449: \begincode{22}
        !          3450: \moddef{data segment items}\endmoddef
        !          3451: bottom: .word 0                 /* C's saved stack pointer */
        !          3452: \endcode
        !          3453: \begincode{23}
        !          3454: \moddef{C linkage}\endmoddef
        !          3455:         .globl saveregs
        !          3456:         .globl handle_c
        !          3457:         .globl return_c
        !          3458:         .globl restoreregs
        !          3459: .ent restoreregs
        !          3460: restoreregs:
        !          3461: \LA{}save caller's stuff using MIPS calling conventions\RA{}
        !          3462: \LA{}enable floating point overflow and zerodivide exceptions\RA{}
        !          3463:         sw      $sp,bottom      /* save C's stack pointer */
        !          3464: \LA{}if \code{}saved_pc\edoc{} points to a bad spot, adjust it (destroys arithmetic temps)\RA{}
        !          3465: \LA{}restore the ML registers\RA{}
        !          3466: .set noat /* This trick will cause a warning, but the code is OK */
        !          3467:         lw      $at,saved_pc    /* grab the saved program counter */
        !          3468:         j       $at             /* and continue executing at that spot */
        !          3469: .set at
        !          3470: 
        !          3471: \endcode
        !          3472: \begindocs{24}
        !          3473: The next two functions are an exception handler and a continuation for
        !          3474: ML programs called from C.
        !          3475: Although neither appears to return any result (by manipulating \code{}$stdarg\edoc{},
        !          3476: they do return results.  
        !          3477: It's just that the C code on the other end gets the result out of 
        !          3478: \code{}saved_ptrs[0],\edoc{} where it expects to find \code{}$stdarg\edoc{}.
        !          3479: \enddocs
        !          3480: \begincode{25}
        !          3481: \moddef{C linkage}\endmoddef
        !          3482: Closure(handle_c) /* exception handler for ML functions called from C */
        !          3483:         li      $artemp1,CAUSE_EXN
        !          3484:         sw      $artemp1,cause
        !          3485:         b       saveregs
        !          3486: Closure(return_c) /* continuation for ML functions called from C */
        !          3487:         li      $artemp1,CAUSE_RET
        !          3488:         sw      $artemp1,cause
        !          3489: saveregs: 
        !          3490: \LA{}save the ML registers\RA{}
        !          3491:         lw      $sp,bottom      /* recover C's stack pointer */
        !          3492: \LA{}restore caller's stuff using MIPS calling conventions\RA{}
        !          3493:         j       $31     /* return to C program */
        !          3494: .end restoreregs
        !          3495: 
        !          3496: \endcode
        !          3497: \begincode{26}
        !          3498: \moddef{enable floating point overflow and zerodivide exceptions}\endmoddef
        !          3499: .set noat
        !          3500:         cfc1 $at,$31            /* grab fpa control register */
        !          3501:         ori  $at,$at,0x600      /* set O and Z bits */
        !          3502:         ctc1 $at,$31            /* return fpa control register */
        !          3503: .set at
        !          3504: 
        !          3505: \endcode
        !          3506: \begindocs{27}
        !          3507: The MIPS calling conventions are described in gory detail in Appendix~D
        !          3508: of the MIPS book; pages D-18 and following.
        !          3509: 
        !          3510: At the moment we don't save any floating point registers.
        !          3511: We save (on the stack) nine general-purpose registers, the global pointer,
        !          3512:  and the return address.
        !          3513: 
        !          3514: We always have to allocate at least 16 bytes for argument build,
        !          3515: because any C function might be varargs, and might begin by
        !          3516: spilling all of its registers into the argument build area (Hanson).
        !          3517: We allocate exactly sixteen bytes, planning to fiddle the stack if
        !          3518: (God forbid) we are ever asked to issue a system call with more than
        !          3519: 16 bytes worth of arguments.
        !          3520: 
        !          3521: \enddocs
        !          3522: \begincode{28}
        !          3523: \moddef{save caller's stuff using MIPS calling conventions}\endmoddef
        !          3524: #define regspace 44
        !          3525: #define localspace 4
        !          3526: #define argbuild 16
        !          3527: #define framesize (regspace+localspace+argbuild) /* must be multiple of 8 */
        !          3528: #define frameoffset (0-localspace)
        !          3529:         subu $sp,framesize
        !          3530: \LA{}give .mask and save the C registers\RA{}
        !          3531: 
        !          3532: \endcode
        !          3533: \begincode{29}
        !          3534: \moddef{restore caller's stuff using MIPS calling conventions}\endmoddef
        !          3535: \LA{}restore the C registers\RA{}
        !          3536:         addu $sp,framesize
        !          3537: \endcode
        !          3538: \begindocs{30}
        !          3539: We don't save floating point regs yet.
        !          3540: \enddocs
        !          3541: \begincode{31}
        !          3542: \moddef{give .mask and save the C registers}\endmoddef
        !          3543: .mask 0xd0ff0000,0-localspace
        !          3544:         sw      $31,argbuild+40($sp)
        !          3545:         sw      $30,argbuild+36($sp)
        !          3546:         sw      $gp,argbuild+32($sp)
        !          3547:         sw      $23,argbuild+28($sp)
        !          3548:         sw      $22,argbuild+24($sp)
        !          3549:         sw      $21,argbuild+20($sp)
        !          3550:         sw      $20,argbuild+16($sp)
        !          3551:         sw      $19,argbuild+12($sp)
        !          3552:         sw      $18,argbuild+8($sp)
        !          3553:         sw      $17,argbuild+4($sp)
        !          3554:         sw      $16,argbuild($sp)
        !          3555: \endcode
        !          3556: \begincode{32}
        !          3557: \moddef{restore the C registers}\endmoddef
        !          3558:         lw      $31,argbuild+40($sp)
        !          3559:         lw      $30,argbuild+36($sp)
        !          3560:         lw      $gp,argbuild+32($sp)
        !          3561:         lw      $23,argbuild+28($sp)
        !          3562:         lw      $22,argbuild+24($sp)
        !          3563:         lw      $21,argbuild+20($sp)
        !          3564:         lw      $20,argbuild+16($sp)
        !          3565:         lw      $19,argbuild+12($sp)
        !          3566:         lw      $18,argbuild+8($sp)
        !          3567:         lw      $17,argbuild+4($sp)
        !          3568:         lw      $16,argbuild($sp)
        !          3569: 
        !          3570: 
        !          3571: \endcode
        !          3572: \begindocs{33}
        !          3573: There are two save areas; one for pointers and one for non-pointers.
        !          3574: (The pointer area may, of course, include tagged integers.)
        !          3575: The pointer area has special spots for standard argument, continuation,
        !          3576: and closure.
        !          3577: In addition there are special save areas for the special registers.
        !          3578: Register 31 is to be maintained constant relative to the program counter,
        !          3579: so we store the difference with \code{}saved_pc\edoc{}.
        !          3580: \enddocs
        !          3581: \begincode{34}
        !          3582: \moddef{save the ML registers}\endmoddef
        !          3583:                                         /* needn't save $1 */
        !          3584:         /* the big three: argument, continuation, closure */
        !          3585:         sw      $stdarg,saved_ptrs
        !          3586:         sw      $stdcont,saved_ptrs+4
        !          3587:         sw      $stdclos,saved_ptrs+8
        !          3588:         
        !          3589:         /* All the miscellaneous guys */
        !          3590:         sw      $5,saved_ptrs+12
        !          3591:         sw      $6,saved_ptrs+16
        !          3592:         sw      $7,saved_ptrs+20
        !          3593:         sw      $8,saved_ptrs+24
        !          3594:         sw      $9,saved_ptrs+28
        !          3595:         sw      $10,saved_ptrs+32
        !          3596:         sw      $11,saved_ptrs+36
        !          3597:         sw      $12,saved_ptrs+40
        !          3598:         sw      $13,saved_ptrs+44
        !          3599:         sw      $14,saved_ptrs+48
        !          3600:         sw      $15,saved_ptrs+52
        !          3601:         sw      $16,saved_ptrs+56
        !          3602:         sw      $17,saved_ptrs+60
        !          3603:         sw      $18,saved_ptrs+64
        !          3604:         sw      $19,saved_ptrs+68
        !          3605: 
        !          3606:         sw      $21, saved_ptrs+72
        !          3607: 
        !          3608:         sw      $artemp1,saved_nonptrs
        !          3609:         sw      $artemp2,saved_nonptrs+4
        !          3610:         sw      $artemp3,saved_nonptrs+8
        !          3611: 
        !          3612:         /* don't touch registers $26 and $27 */
        !          3613: 
        !          3614:         sw      $storeptr,saved_storeptr
        !          3615:         sw      $dataptr,saved_dataptr
        !          3616:         sw      $exnptr,saved_exnptr
        !          3617: 
        !          3618: \LA{}save $\code{}$31\edoc{}-\code{}saved_pc\edoc{}$ in \code{}saved_pc_diff\edoc{} (destroys \code{}$artemp1\edoc{})\RA{}
        !          3619: 
        !          3620: 
        !          3621: \endcode
        !          3622: \begincode{35}
        !          3623: \moddef{restore the ML registers}\endmoddef
        !          3624:         /* the big three: argument, continuation, closure */
        !          3625:         lw      $stdarg,saved_ptrs
        !          3626:         lw      $stdcont,saved_ptrs+4
        !          3627:         lw      $stdclos,saved_ptrs+8
        !          3628:         
        !          3629:         /* All the miscellaneous guys */
        !          3630:         lw      $5,saved_ptrs+12
        !          3631:         lw      $6,saved_ptrs+16
        !          3632:         lw      $7,saved_ptrs+20
        !          3633:         lw      $8,saved_ptrs+24
        !          3634:         lw      $9,saved_ptrs+28
        !          3635:         lw      $10,saved_ptrs+32
        !          3636:         lw      $11,saved_ptrs+36
        !          3637:         lw      $12,saved_ptrs+40
        !          3638:         lw      $13,saved_ptrs+44
        !          3639:         lw      $14,saved_ptrs+48
        !          3640:         lw      $15,saved_ptrs+52
        !          3641:         lw      $16,saved_ptrs+56
        !          3642:         lw      $17,saved_ptrs+60
        !          3643:         lw      $18,saved_ptrs+64
        !          3644:         lw      $19,saved_ptrs+68
        !          3645: 
        !          3646:         lw      $21, saved_ptrs+72
        !          3647: 
        !          3648: \LA{}restore \code{}$31\edoc{} from \code{}saved_pc\edoc{} \& \code{}saved_pc_diff\edoc{} (destroys \code{}$artemp1\edoc{})\RA{}
        !          3649:         lw      $artemp1,saved_nonptrs
        !          3650:         lw      $artemp2,saved_nonptrs+4
        !          3651:         lw      $artemp3,saved_nonptrs+8
        !          3652: 
        !          3653:         /* don't touch registers $26 and $27 */
        !          3654: 
        !          3655:         lw      $storeptr,saved_storeptr
        !          3656:         lw      $dataptr,saved_dataptr
        !          3657:         lw      $exnptr,saved_exnptr
        !          3658: 
        !          3659: \endcode
        !          3660: \begincode{36}
        !          3661: \moddef{save $\code{}$31\edoc{}-\code{}saved_pc\edoc{}$ in \code{}saved_pc_diff\edoc{} (destroys \code{}$artemp1\edoc{})}\endmoddef
        !          3662:         lw $artemp1,saved_pc
        !          3663:         subu $artemp1,$31,$artemp1      /* mustn't overflow */
        !          3664:         sw $artemp1,saved_pc_diff
        !          3665: \endcode
        !          3666: \begincode{37}
        !          3667: \moddef{restore \code{}$31\edoc{} from \code{}saved_pc\edoc{} \& \code{}saved_pc_diff\edoc{} (destroys \code{}$artemp1\edoc{})}\endmoddef
        !          3668:         lw $artemp1,saved_pc
        !          3669:         lw $31,saved_pc_diff
        !          3670:         addu $31,$artemp1               /* mustn't overflow */
        !          3671: \endcode
        !          3672: \begincode{38}
        !          3673: \moddef{data segment items}\endmoddef
        !          3674: saved_pc_diff:  .word 0
        !          3675: 
        !          3676: 
        !          3677: \endcode
        !          3678: \begindocs{39}
        !          3679: Because the Mips has no indexed addressing modes, there are special
        !          3680: circumstances under which we have to adjust the program counter before
        !          3681: a garbage collection.
        !          3682: The problem arises when we want to create an object whose size is not
        !          3683: known at compile time.
        !          3684: In order to do that, we have to add the size of the object to \code{}$dataptr\edoc{},
        !          3685: putting the result in a new register.
        !          3686: We then store at offset $-4$ from that register to allocate (and possibly
        !          3687: cause garbage collection).
        !          3688: That register can't be a pointer, because at the time of the gc it doesn't
        !          3689: point to anything sensible (in fact, by definition it points out of the
        !          3690: garbage-collectible region entirely).
        !          3691: If it is a nonpointer, though, it isn't changed by the garbage collection,
        !          3692: so when the collection is over, we attempt once again to store in exactly
        !          3693: the same place, causing another fault (unless the heap has been resized).
        !          3694: 
        !          3695: The solution is a hack.  Since there are only two places this problem
        !          3696: can occur, we check \code{}saved_pc\edoc{} against the offending program counters.
        !          3697: If we find one, we reduce \code{}saved_pc\edoc{} by 4 (the size of one instruction),
        !          3698: causing the addition to be repeated.
        !          3699: 
        !          3700: \enddocs
        !          3701: \begincode{40}
        !          3702: \moddef{if \code{}saved_pc\edoc{} points to a bad spot, adjust it (destroys arithmetic temps)}\endmoddef
        !          3703:     lw $artemp1,saved_pc
        !          3704:     \LA{}load bad pc into \code{}$artemp2\edoc{}; branch to \code{}badpc\edoc{} if == \code{}$artemp1\edoc{}\RA{}
        !          3705:     b 1f
        !          3706: badpc:
        !          3707:     subu $artemp1,4             /* adjust */
        !          3708:     sw $artemp1,saved_pc        /* save */
        !          3709: 1:
        !          3710: 
        !          3711: 
        !          3712: \endcode
        !          3713: \begindocs{41}
        !          3714: \code{}callc(f,a)\edoc{} calls a C-language function \code{}f\edoc{} with argument \code{}a\edoc{}.
        !          3715: We don't have to save a register unless we'll need its value later.
        !          3716: 
        !          3717: The closure of this routine is irrelevant, since \code{}callc\edoc{} doesn't
        !          3718: have any free variables.
        !          3719: Therefore the only things that have to be restored after the call to~C
        !          3720: are the continuation, the store pointer, the data pointer, and
        !          3721: the exception handler.
        !          3722: If we wanted \code{}callc\edoc{} to be more efficient, we would
        !          3723: rearrange things so that all those registers fell into \code{}s0\edoc{}--\code{}s8\edoc{},
        !          3724: where they would automatically be preserved across procedure calls.
        !          3725: As it stands, everything except the continuation is preserved,
        !          3726: so we're not doing too badly.
        !          3727: 
        !          3728: Miraculously, C routines return integer results in \code{}$2\edoc{}, which is
        !          3729: exactly the register we need to pass to our continuation (in order to
        !          3730: return a value).
        !          3731: I decided not to rely on this, and to include a \code{}move\edoc{} instruction
        !          3732: anyway.  Maybe the assembler will park it in a delay slot since it
        !          3733: is a nop.
        !          3734: \enddocs
        !          3735: \begincode{42}
        !          3736: \moddef{calling C routines}\endmoddef
        !          3737: Closure(callc_v)
        !          3738:         sw $stdcont,argbuild+regspace($sp) /* save continuation on stack */
        !          3739:         lw $4,4($stdarg)        /* get value a into arg register */
        !          3740:         lw $10,0($stdarg)       /* get address of f into misc reg */
        !          3741:         jal $10                 /* call f ($31 can be trashed) */
        !          3742:         move $stdarg,$2         /* return val is argument to continuation */
        !          3743:         lw $stdcont,argbuild+regspace($sp) /* recover continuation */
        !          3744: \LA{}put zeroes in all forwardable regs that might hold garbage\RA{}
        !          3745:         lw $artemp3,cause       /* get cause */
        !          3746:         bne $artemp3,$0,saveregs /* if cause != 0, save ML & return to C */
        !          3747:         lw $10,0($stdcont)      /* grab continuation */
        !          3748:         j $10                   /* return */
        !          3749: \endcode
        !          3750: \begindocs{43}
        !          3751: A forwardable register can hold garbage unless it was saved
        !          3752: by C (is in \code{}s0\edoc{}--\code{}s8\edoc{}) or is \code{}$stdarg\edoc{} of \code{}$stdcont\edoc{}.
        !          3753: \enddocs
        !          3754: \begincode{44}
        !          3755: \moddef{put zeroes in all forwardable regs that might hold garbage}\endmoddef
        !          3756:         move $stdclos,$0
        !          3757:         move $5,$0
        !          3758:         move $6,$0
        !          3759:         move $7,$0
        !          3760:         move $8,$0
        !          3761:         move $9,$0
        !          3762:         move $10,$0
        !          3763:         move $11,$0
        !          3764:         move $12,$0
        !          3765:         move $13,$0
        !          3766:         move $14,$0
        !          3767:         move $15,$0
        !          3768:         /* $16--$23 and $30 are saved by the callee */
        !          3769: 
        !          3770: \endcode
        !          3771: \begindocs{45}
        !          3772: This interface is going to be agony, because the rules for passing
        !          3773: arguments are passing strange.
        !          3774: The interface is \code{}syscall_v(callnumber,argvector,argcount)\edoc{}.
        !          3775: 
        !          3776: The system call interface is the same as the procedure call interface,
        !          3777: but instead of a \code{}jal\edoc{} we use a \code{}syscall\edoc{} instruction, and
        !          3778: we put the system call number in register \code{}$2\edoc{}.
        !          3779: It appears that, after the execution of the \code{}syscall\edoc{} handler,
        !          3780: the result is in \code{}$2\edoc{}, and \code{}$7\edoc{} is zero unless an error occurred.
        !          3781: We will put all the arguments on the stack, then load the first four
        !          3782: into \code{}$4\edoc{}--\code{}$7\edoc{}.
        !          3783: \enddocs
        !          3784: \begincode{46}
        !          3785: \moddef{system calls}\endmoddef
        !          3786: Closure(syscall_v)
        !          3787:         sw $stdcont,argbuild+regspace($sp) /* save continuation on stack */
        !          3788:         lw $artemp1,8($stdarg)  /* 2*argc+1 in $artemp1 */
        !          3789:         sra $artemp1,1          /* argc in $artemp1 */
        !          3790:         move $16,$sp            /* save our $sp */
        !          3791: \LA{}extend argbuild area to be big enough for all arguments\RA{}
        !          3792:         lw $ptrtemp,4($stdarg)  /* argv in $ptrtemp */
        !          3793: \LA{}put all arguments onto the stack\RA{}
        !          3794: \LA{}load first four arguments into \code{}$4\edoc{}--\code{}$7\edoc{}\RA{}
        !          3795: 9:      lw $2,0($stdarg)        /* get syscall # in $2; trash $stdarg */
        !          3796:         sra $2,1                /* throw out the tag bit */
        !          3797:         syscall
        !          3798:         move $sp,$16            /* recover the good stack pointer */
        !          3799:         lw $stdcont,argbuild+regspace($sp) /* recover continuation */
        !          3800:         bnez $7,1f              /* if error, return ~1 */
        !          3801:         move $stdarg,$2         /* return val is argument to continuation */
        !          3802:         add $stdarg,$stdarg     /* double return value */
        !          3803:         addi $stdarg,1          /* and add tag bit */
        !          3804:         b 2f
        !          3805: 1:      li $stdarg,-1
        !          3806: 2:
        !          3807: \LA{}put zeroes in all forwardable regs that might hold garbage\RA{}
        !          3808:         lw $10,0($stdcont)      /* grab continuation */
        !          3809:         j $10                   /* return */
        !          3810: 
        !          3811: \endcode
        !          3812: \begindocs{47}
        !          3813: At this point we know that the number of arguments is in \code{}$artemp1\edoc{}.
        !          3814: We have room for four arguments; if there are more 
        !          3815: we'll have to increase the stack size by the appropriate multiple of 8
        !          3816: so that it stays doubleword-aligned.
        !          3817: \enddocs
        !          3818: \begincode{48}
        !          3819: \moddef{extend argbuild area to be big enough for all arguments}\endmoddef
        !          3820:         ble $artemp1,4,1f               /* big enough */
        !          3821:         sub $artemp2,$artemp1,3         /* (temp2 = argc - 4 + 1) > 1 */
        !          3822:         sra $artemp2,1                  
        !          3823:         sll $artemp2,3                  /* temp2 = 4 * roundup (argc-4,2) */
        !          3824:         subu $sp,$artemp2               /* increase stack */
        !          3825: 1:
        !          3826: 
        !          3827: \endcode
        !          3828: \begindocs{49}
        !          3829: Now we have a list of arguments pointed to by \code{}$ptrtemp\edoc{}.
        !          3830: We have the count of the arguments in \code{}$artemp1\edoc{}.
        !          3831: We have to put them on the stack.
        !          3832: We have to remove tag bits where appropriate.
        !          3833: \enddocs
        !          3834: \begincode{50}
        !          3835: \moddef{put all arguments onto the stack}\endmoddef
        !          3836:         move $artemp2,$sp               /* destination in $artemp2 */
        !          3837:         b 1f                            /* branch forward to test */
        !          3838: 2:      /* argc > 0 */
        !          3839:         lw $artemp3,0($ptrtemp)         /* get list element */
        !          3840:         andi $10,$artemp3,1             /* tagged? */
        !          3841:         beqz $10,3f
        !          3842:         sra $artemp3,1                  /* drop tag bit */
        !          3843: 3:      sw $artemp3,0($artemp2)         /* save the argument */
        !          3844:         lw $ptrtemp,4($ptrtemp)         /* next element */
        !          3845:         add $artemp2,4                  /* next arg build area */
        !          3846:         sub $artemp1,1                  /* --argc */
        !          3847: 1:      bgtz $artemp1,2b                /* if argc>0, store another */
        !          3848: 
        !          3849: \endcode
        !          3850: \begindocs{51}
        !          3851: It doesn't matter if we load arguments that aren't there; the
        !          3852: system call will just ignore them.
        !          3853: \enddocs
        !          3854: \begincode{52}
        !          3855: \moddef{load first four arguments into \code{}$4\edoc{}--\code{}$7\edoc{}}\endmoddef
        !          3856:         lw $4,0($sp)
        !          3857:         lw $5,4($sp)
        !          3858:         lw $6,8($sp)
        !          3859:         lw $7,12($sp)
        !          3860: 
        !          3861: \endcode
        !          3862: \begindocs{53}
        !          3863: \subsection{Floating point}
        !          3864: We store floating point constants in two words, with the least significant
        !          3865: word first.  
        !          3866: We use the 64 bit IEEE format.
        !          3867: 
        !          3868: We begin with instructions to change the rounding modes.
        !          3869: See the MIPS book, pages 6-5--6-7.
        !          3870: \enddocs
        !          3871: \begincode{54}
        !          3872: \moddef{tell the floating point unit to round toward $-\infty$}\endmoddef
        !          3873: .set noat
        !          3874:         cfc1 $at,$31            /* grab fpa control register */
        !          3875:         ori  $at,0x03           /* set rounding bits to 11 */
        !          3876:         ctc1 $at,$31            /* return fpa control register */
        !          3877: .set at
        !          3878: \endcode
        !          3879: \begincode{55}
        !          3880: \moddef{tell the floating point unit to round to nearest}\endmoddef
        !          3881: .set noat
        !          3882:         cfc1 $at,$31            /* grab fpa control register */
        !          3883:         ori  $at,0x03           /* set rounding bits to 11 */
        !          3884:         xori $at,0x03           /* set rounding bits to 00
        !          3885:         ctc1 $at,$31            /* return fpa control register */
        !          3886: .set at
        !          3887: \endcode
        !          3888: \begindocs{56}
        !          3889: These floating point functions are used int floating to integer conversion.
        !          3890: \enddocs
        !          3891: \begincode{57}
        !          3892: \moddef{floating point}\endmoddef
        !          3893: /* Floating exceptions raised (assuming ROP's are never passed to functions):
        !          3894:  *      DIVIDE BY ZERO - (div)
        !          3895:  *      OVERFLOW/UNDERFLOW - (add,div,sub,mul) as appropriate
        !          3896:  *
        !          3897:  * floor raises integer overflow if the float is out of 32-bit range,
        !          3898:  * so the float is tested before conversion, to make sure it is in (31-bit)
        !          3899:  * range */
        !          3900: 
        !          3901: \endcode
        !          3902: \begindocs{58}
        !          3903: \code{}floor(x)\edoc{} returns the smallest integer less than or equal to \code{}x\edoc{}.
        !          3904: \enddocs
        !          3905: \begincode{59}
        !          3906: \moddef{floating point}\endmoddef
        !          3907: Closure(floor_v)
        !          3908:         lwc1 $f4,0($stdarg)             /* get least significant word */
        !          3909:         lwc1 $f5,4($stdarg)             /* get most significant word */
        !          3910: \LA{}tell the floating point unit to round toward $-\infty$\RA{}
        !          3911:         cvt.w.d $f6,$f4                 /* convert to integer */
        !          3912: \LA{}tell the floating point unit to round to nearest\RA{}
        !          3913:         mfc1 $stdarg,$f6                /* get in std argument register */
        !          3914:         sll $stdarg,1           /* make room for tag bit */
        !          3915:         add $stdarg,1           /* add the tag bit */
        !          3916:         lw $10,0($stdcont)      /* grab continuation */
        !          3917:         j $10                   /* return */
        !          3918: 
        !          3919: 
        !          3920: \endcode
        !          3921: \begindocs{60}
        !          3922: \code{}logb(x)\edoc{} returns the exponent part of the floating point \code{}x\edoc{}.
        !          3923: We grab the 11-bit exponent from the word, then unbias it (according
        !          3924: to the IEEE standard) by subtracting 1023.
        !          3925: \enddocs
        !          3926: \begincode{61}
        !          3927: \moddef{floating point}\endmoddef
        !          3928: Closure(logb_v)
        !          3929:         lw      $stdarg,4($stdarg)      /* most significant part */
        !          3930:         srl     $stdarg,20              /* throw out 20 low bits */
        !          3931:         andi    $stdarg,0x07ff          /* clear all but 11 low bits */
        !          3932:         sub     $stdarg,1023            /* subtract 1023 */
        !          3933:         sll     $stdarg,1               /* make room for tag bit */
        !          3934:         add     $stdarg,1               /* add the tag bit */
        !          3935:         lw      $10,0($stdcont)         /* grab continuation */
        !          3936:         j       $10                     /* return */
        !          3937: 
        !          3938: \endcode
        !          3939: \begindocs{62}
        !          3940: \code{}scalb(x,n)\edoc{} adds \code{}n\edoc{} to the exponent of floating
        !          3941: point \code{}x\edoc{}.
        !          3942: Since we don't want the resulting float to be anything
        !          3943: special, we insist that the unbiased exponent of the result
        !          3944: satisfy $-1022 \le E \le 1023$, i.e.\ that the biased exponent satisfy
        !          3945:  $1 \le e \le 2046$.
        !          3946: \enddocs
        !          3947: \begincode{63}
        !          3948: \moddef{floating point}\endmoddef
        !          3949: Closure(scalb_v)
        !          3950:         lw      $artemp1,4($stdarg)     /* get tagged n */
        !          3951:         sra     $artemp1,1              /* get real n */
        !          3952:         beqz    $artemp1,9f             /* if zero, return the old float */
        !          3953:         lw      $ptrtemp,0($stdarg)     /* get pointer to float */
        !          3954:         lw      $artemp2,4($ptrtemp)    /* most significant part */
        !          3955:         srl     $artemp2,20             /* throw out 20 low bits */
        !          3956:         andi    $artemp2,0x07ff         /* clear all but 11 low bits */
        !          3957:         add     $artemp3,$artemp2,$artemp1      /* new := old + n */
        !          3958:         blt     $artemp3,1,under        /* punt if underflow */
        !          3959:         bgt     $artemp3,2046,over      /* or overflow */
        !          3960: \LA{}allocate and store new floating point constant and set \code{}$stdarg\edoc{}\RA{}
        !          3961:         lw      $10,0($stdcont)         /* grab continuation */
        !          3962:         j       $10                     /* return */
        !          3963: 
        !          3964: 9:      lw      $stdarg,0($stdarg)      /* get old float */
        !          3965:         lw      $10,0($stdcont)         /* grab continuation */
        !          3966:         j       $10                     /* return */
        !          3967: 
        !          3968: over:   la      $stdarg,1f              /* exception name in $stdarg */
        !          3969:         b       raise_real
        !          3970: String(1,8,"overflow")
        !          3971: under:  la      $stdarg,1f              /* exception name in $stdarg */
        !          3972:         b       raise_real
        !          3973: String(1,9,"underflow\\0\\0\\0")
        !          3974: 
        !          3975: raise_real:
        !          3976:  /* build new record to pass to exception handler */
        !          3977:  /*    [descriptor]
        !          3978:  /*    [exception (string)]
        !          3979:  /*    [real_e (more exception info)]
        !          3980:   */
        !          3981:         la      $10,real_e              /* get address of real_e */
        !          3982: .set noreorder
        !          3983:         sw      $10,8($dataptr)         /* allocate; may cause gc */
        !          3984: .set reorder
        !          3985:         sw      $stdarg,4($dataptr)
        !          3986:         li      $10,mak_desc(2,tag_record)
        !          3987:         sw      $10,0($dataptr)
        !          3988:         add     $stdarg,$dataptr,4      /* new record is argument */
        !          3989:         addi    $dataptr,12             /* $dataptr restored */
        !          3990:         move    $stdclos,$exnptr        /* make sure closure is right */
        !          3991:         lw      $10,0($exnptr)          /* grab handler */
        !          3992:         j       $10                     /* raise the exception */
        !          3993: 
        !          3994: \endcode
        !          3995: \begindocs{64}
        !          3996: Here we indulge in a little cleverness to save a couple of instructions.
        !          3997: Since the old value is in \code{}$artemp2\edoc{} and the new in \code{}$artemp3\edoc{},
        !          3998: we can \code{}xor\edoc{} them, then store the new one with a second \code{}xor\edoc{}.
        !          3999: \enddocs
        !          4000: \begincode{65}
        !          4001: \moddef{allocate and store new floating point constant and set \code{}$stdarg\edoc{}}\endmoddef
        !          4002:         xor     $artemp3,$artemp2       /* at3 = new xor old */
        !          4003:         sll     $artemp3,20             /* put exponent in right position */
        !          4004:         lw      $artemp2,4($ptrtemp)    /* most significant word */
        !          4005:         xor     $artemp2,$artemp3       /* change to new exponent */
        !          4006: .set noreorder
        !          4007:         sw      $artemp2,8($dataptr)    /* allocate; may cause gc */
        !          4008: .set reorder
        !          4009:         lw      $artemp2,0($ptrtemp)    /* get least significant word */
        !          4010:         li      $10,mak_desc(8,tag_string) /* make descriptor */
        !          4011:         sw      $artemp2,4($dataptr)    /* save lsw */
        !          4012:         sw      $10,0($dataptr)         /* save descriptor */
        !          4013:         add     $stdarg,$dataptr,4      /* get pointer to new float */
        !          4014:         add     $dataptr,12             /* point to new free word */
        !          4015: \endcode
        !          4016: \bye

unix.superglobalmegacorp.com

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