Annotation of researchv10no/cmd/sml/src/mips/emitters.nw, revision 1.1

1.1     ! root        1: \section{Emitters}
        !             2: We have an odd problem---we need to be able to emit either a 32-bit
        !             3: integer or a string.
        !             4: The order in which the bytes of the integer are emitted depends on
        !             5: whether the target machine is BigEndian or LittleEndian, but the
        !             6: bytes of the string should be emitted in the same order on both machines.
        !             7: This means that the two emission functions depend on each other, but
        !             8: in a machine-dependent way, so we bundle them up.
        !             9: We also have to be able to emit two words for floating point constants.
        !            10: The way to do this can be derived from [[emit_word]], and this
        !            11: code seems to be the sensible place to do that.
        !            12: So we define a type [[emitter_triple]] 
        !            13: and pass them around that way.
        !            14: 
        !            15: @ Eventually we want to take all the words and strings that have been
        !            16: emitted and bundle them up into a single string using [[implode]].
        !            17: We'll take the following tack with that:
        !            18: each emitter will squirrel some info away in a reference variable.
        !            19: A function [[emitted_string: unit -> string]] will take the
        !            20: squirreled information and return a string that represents
        !            21: everything emitted so far.
        !            22: As a side effect, it will reset the emitter system to its initial 
        !            23: state, where ``everything emitted so far'' is the empty string.
        !            24: 
        !            25: The actual implementation will be a list of strings which is reversed 
        !            26: and imploded.
        !            27: <<signature>>=
        !            28: signature EMITTERS = sig
        !            29:     type emitter_triple
        !            30:     val LittleEndian : emitter_triple
        !            31:     val BigEndian : emitter_triple
        !            32:     val emitted_string : unit -> string
        !            33:     val MipsAsm : outstream -> emitter_triple
        !            34:     val address : int ref
        !            35: end
        !            36: 
        !            37: @ First something that's capable of emitting real code, then
        !            38: something that can print assembly code.
        !            39: We emit the assembly code to output right away, without any fooling.
        !            40: <<*>>=
        !            41: structure Emitters : EMITTERS = struct
        !            42:     type emitter_triple = (int * int -> unit) * (int -> string -> unit)
        !            43:                                        * (string -> unit)
        !            44:     local 
        !            45:         <<memory and basic services>>
        !            46:     in
        !            47:         <<string emitter>>
        !            48:         <<little-endian emitter>>
        !            49:         <<big-endian emitter>>
        !            50:        fun emitted_string () =
        !            51:            let val s = implode (rev (!so_far))
        !            52:            in  so_far := nil; s
        !            53:            end
        !            54:     end
        !            55:     structure BigReal = MipsReal(struct val emit_word = emit_pair_big end)
        !            56:     structure LittleReal =MipsReal(struct val emit_word = emit_pair_little end)
        !            57:     val LittleEndian = (emit_pair_little,emit_string,LittleReal.realconst)
        !            58:     val BigEndian = (emit_pair_big,emit_string,BigReal.realconst)
        !            59:     <<assembly-code emitters>>
        !            60: end
        !            61: 
        !            62: 
        !            63: @ Here is a variable to remember what's been emitted so far
        !            64: <<memory and basic services>>=
        !            65: val so_far = ref nil : string list ref
        !            66: fun squirrel s = so_far := s :: !so_far
        !            67: fun emit_byte n = squirrel (chr n)
        !            68: <<string emitter>>=
        !            69: fun emit_string n s = squirrel (substring(s,0,n))
        !            70:                handle e =>
        !            71:                        (print "?exception "; print (System.exn_name e);
        !            72:                         print (" in emitters.emit_string "^
        !            73:                                (Integer.makestring n) ^ " \""^s^"\"\n");
        !            74:                         raise e)
        !            75: 
        !            76: @ Little-endian means the little (least significant) end first,
        !            77: like the VAX.
        !            78:  We parameterize the real emitters by a function that emits a byte.
        !            79: <<little-endian emitter>>=
        !            80: fun emit_pair_little(hi,lo) =
        !            81:     let open Bits
        !            82:         fun emit_word(n) =
        !            83:           (emit_byte(andb(n,255));emit_byte(andb(rshift(n,8),255)))
        !            84:     in  (emit_word(lo);emit_word(hi))
        !            85:     end
        !            86: 
        !            87: <<big-endian emitter>>=
        !            88: fun emit_pair_big(hi,lo) =
        !            89:      let open Bits
        !            90:         fun emit_word(n) =
        !            91:           (emit_byte(andb(rshift(n,8),255));emit_byte(andb(n,255)))
        !            92:     in  (emit_word(hi);emit_word(lo))
        !            93:     end
        !            94: 
        !            95: 
        !            96: @ Now the assembly code.
        !            97: to make it easier to debug, we print out addresses in the same format
        !            98: as {\tt dbx}: we use the byte address and we print it in hex.
        !            99: 
        !           100: We have to bend over backwards to handle real numbers
        !           101: 
        !           102: <<assembly-code emitters>>=
        !           103: val address = ref 0            (* address of next instruction in words *)
        !           104: <<real number state info and [[decode_real_ptr]]>>
        !           105: fun MipsAsm stream =
        !           106:     let fun say s = (output stream s; flush_out stream)
        !           107:         fun printaddr addrref = 
        !           108:            let val n = !addrref
        !           109:            in  (if n<10 then "  " else if n < 100 then " " else "") 
        !           110:                 ^ (Integer.makestring n) 
        !           111:            end
        !           112:         local 
        !           113:             open Bits
        !           114:             fun hexdigit n = 
        !           115:                 let val d = andb(n,15)
        !           116:                 in  if d <= 9 then chr(d+ord("0"))
        !           117:                               else chr(d-10+ord("a"))
        !           118:                 end
        !           119:             fun hex1 n = hexdigit(rshift(n,4))^hexdigit(n)
        !           120:             fun hex2 n = hex1(rshift(n,8))^hex1(n)
        !           121:            fun hex4 n = hex2(rshift(n,16))^hex2(n)
        !           122:         in
        !           123:             fun hex(hi,lo) = hex2(hi) ^ hex2(lo)
        !           124:            fun printaddr addrref = 
        !           125:                let val n = 4 * (!addrref)      (* address in bytes *)
        !           126:                in "0x" ^ (hex4 n) 
        !           127:            end
        !           128:         end
        !           129:         fun decode x = (
        !           130:                 say ((printaddr address) ^ ": (" ^ (hex x) ^") " 
        !           131:                  ^ (MipsDecode.decode x));
        !           132:            address := !address + 1; ()
        !           133:            )
        !           134:        fun do_decode_real(w,s) = (
        !           135:                 say ((printaddr address) ^ ": (" ^ (hex w) ^") " 
        !           136:                  ^ s ^ "\n");
        !           137:            address := !address + 1; ()
        !           138:            )
        !           139:        fun decode_real s = (real_string := s; AsmReal.realconst s)
        !           140:         fun decode_string n s =
        !           141:             if n > 0 then
        !           142:                 (say ((printaddr address) 
        !           143:                             ^ ": \"" ^substring(s,0,4) ^"\"\n");
        !           144:                    address := !address + 1;
        !           145:                    decode_string (n-4) (substring(s,4,String.length(s)-4))
        !           146:                    )
        !           147:             else ()
        !           148:     in
        !           149:        decode_real_ptr := SOME do_decode_real;
        !           150:         (decode,decode_string,decode_real) : emitter_triple
        !           151:     end
        !           152: <<real number state info and [[decode_real_ptr]]>>=
        !           153: val decode_real_ptr = ref NONE : ((int * int) * string -> unit) option ref
        !           154:                                   (* used to emit asm code for a real word *)
        !           155:     
        !           156: val real_least = ref NONE : (int * int) option ref
        !           157:                                   (* least significant word of real *)
        !           158: val real_string = ref ""
        !           159: fun emit_real_word w =
        !           160:     let val decode_real = case !decode_real_ptr of 
        !           161:                  SOME f => f 
        !           162:                | NONE => ErrorMsg.impossible "missed real decoder in mips asm"
        !           163:     in
        !           164:         case !real_least of 
        !           165:            NONE => real_least := SOME w
        !           166:           | SOME least => 
        !           167:                (decode_real(least,"[low  word of "^(!real_string)^"]");
        !           168:                 decode_real(w,"[high word of "^(!real_string)^"]"))
        !           169:     end
        !           170: 
        !           171: structure AsmReal = MipsReal(struct val emit_word = emit_real_word end)
        !           172: 

unix.superglobalmegacorp.com

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