|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.