1 # write: write to in-memory streams
3 # We need to do this in machine code because streams need to be opaque types,
4 # and we don't yet support opaque types in Mu.
7 # instruction effective address register displacement immediate
8 # . op subop mod rm32 base index scale r32
9 # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
11 write: # f: (addr stream byte), s: (addr array byte)
14 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
16 81 7/subop/compare 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 0/imm32 # compare *(ebp+12)
17 74/jump-if-= $write:end/disp8
24 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx
26 8b/copy 0/mod/indirect 1/rm32/ecx . . . 2/r32/edx . . # copy *ecx to edx
28 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 3/r32/ebx 8/disp8 . # copy *(ecx+8) to ebx
29 # eax = _append-3(&f->data[f->write], &f->data[f->size], s)
31 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
32 # . . push &f->data[f->size]
33 8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ecx 3/index/ebx . 3/r32/ebx 0xc/disp8 . # copy ecx+ebx+12 to ebx
35 # . . push &f->data[f->write]
36 8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ecx 2/index/edx . 3/r32/ebx 0xc/disp8 . # copy ecx+edx+12 to ebx
39 e8/call _append-3/disp32
41 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
43 01/add 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # add eax to *ecx
51 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
56 # clear-stream(_test-stream)
58 68/push _test-stream/imm32
60 e8/call clear-stream/disp32
62 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
63 # write(_test-stream, "Ab")
66 68/push _test-stream/imm32
70 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
71 # check-ints-equal(*_test-stream->data, 41/A 62/b 00 00, msg)
73 68/push "F - test-write-single"/imm32
74 68/push 0x006241/imm32/Ab
75 # . . push *_test-stream->data
76 b8/copy-to-eax _test-stream/imm32
77 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 0xc/disp8 . # push *(eax+12)
79 e8/call check-ints-equal/disp32
81 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
86 # clear-stream(_test-stream)
88 68/push _test-stream/imm32
90 e8/call clear-stream/disp32
92 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
93 # write(_test-stream, "C")
96 68/push _test-stream/imm32
100 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
101 # write(_test-stream, "D")
104 68/push _test-stream/imm32
108 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
109 # check-ints-equal(*_test-stream->data, 43/C 44/D 00 00, msg)
111 68/push "F - test-write-appends"/imm32
112 68/push 0x00004443/imm32/C-D
113 # . . push *_test-stream->data
114 b8/copy-to-eax _test-stream/imm32
115 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 0xc/disp8 . # push *(eax+12)
117 e8/call check-ints-equal/disp32
119 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
125 _test-stream: # (stream byte)
126 # current write index
132 # data (2 lines x 8 bytes/line)
133 00 00 00 00 00 00 00 00
134 00 00 00 00 00 00 00 00
138 try-write: # f: (addr stream byte), s: (addr array byte) -> overflow?/eax: boolean
141 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
143 81 7/subop/compare 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 0/imm32 # compare *(ebp+12)
144 74/jump-if-= $try-write:end/disp8
147 # if (f->size - f->write < s->size) return
148 # . eax = f->size - f->write - s->size
149 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx
150 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 8/disp8 . # copy *(ecx+8) to eax
151 2b/subtract 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # subtract *ecx from eax
152 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx
153 2b/subtract 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # subtract *ecx from eax
154 # . if (eax < 0) return
155 3d/compare-eax-and 0/imm32
156 7c/jump-if-< $try-write:end/disp8
159 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
160 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8)
164 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
165 # . restore registers
168 b8/copy-to-eax 0/imm32
171 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
175 # probably a bad idea
176 space-remaining-in-stream: # f: (addr stream byte) -> n/eax: int
179 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
182 # return f->size - f->write
183 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx
184 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 8/disp8 . # copy *(ecx+8) to eax
185 2b/subtract 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # subtract *ecx from eax
186 # . restore registers
188 $space-remaining-in-stream:end:
190 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
194 stream-size: # f: (addr stream byte) -> n/eax: int
197 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
201 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx
202 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax
203 # . restore registers
207 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
211 # 3-argument variant of _append
212 _append-3: # out: (addr byte), outend: (addr byte), s: (addr array byte) -> num_bytes_appended/eax
215 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
218 # if (outend - out < s->size) abort
219 # . eax = f->size - f->write - s->size
220 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 0/r32/eax 0xc/disp8 . # copy *(ebp+12) to eax
221 2b/subtract 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # subtract *(ebp+8) from eax
222 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 0x10/disp8 . # copy *(ebp+16) to ecx
223 2b/subtract 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # subtract *ecx from eax
224 # . if (eax < 0) abort
225 3d/compare-eax-and 0/imm32
226 7c/jump-if-< $_append-3:abort/disp8
227 # eax = _append-4(out, outend, &s->data[0], &s->data[s->size])
228 # . . push &s->data[s->size]
229 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax
230 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
231 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx
233 # . . push &s->data[0]
234 8d/copy-address 1/mod/*+disp8 0/rm32/eax . . . 1/r32/ecx 4/disp8 . # copy eax+4 to ecx
237 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
239 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8)
241 e8/call _append-4/disp32
243 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp
245 # . restore registers
248 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
253 (abort "_append-3 about to overflow") # 3=cyan
256 # 4-argument variant of _append
257 _append-4: # out: (addr byte), outend: (addr byte), in: (addr byte), inend: (addr byte) -> num_bytes_appended/eax: int
260 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
267 # num_bytes_appended = 0
268 b8/copy-to-eax 0/imm32
270 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi
272 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx
274 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0x10/disp8 . # copy *(ebp+16) to esi
276 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0x14/disp8 . # copy *(ebp+20) to ecx
278 # if (in >= inend) break
279 39/compare 3/mod/direct 6/rm32/esi . . . 1/r32/ecx . . # compare esi with ecx
280 73/jump-if-addr>= $_append-4:end/disp8
281 # if (out >= outend) abort # just to catch test failures fast
282 39/compare 3/mod/direct 7/rm32/edi . . . 2/r32/edx . . # compare edi with edx
283 0f 83/jump-if-addr>= $_append-4:abort/disp32
285 8a/copy-byte 0/mod/indirect 6/rm32/esi . . . 3/r32/BL . . # copy byte at *esi to BL
286 88/copy-byte 0/mod/indirect 7/rm32/edi . . . 3/r32/BL . . # copy byte at BL to *edi
287 # ++num_bytes_appended
293 eb/jump $_append-4:loop/disp8
295 # . restore registers
302 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
307 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "_append-4: stream full at " 3 0) # 3=cyan
308 (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax 3 0)
312 # . . vim:nowrap:textwidth=0