.
[mu.git] / 309stream.subx
blob524edfd065358dadbd9e371cd314f15ba596367b
1 # Some unsafe methods not intended to be used directly in SubX, only through
2 # Mu after proper type-checking.
4 == code
6 stream-empty?:  # s: (addr stream _) -> result/eax: boolean
7     # . prologue
8     55/push-ebp
9     89/<- %ebp 4/r32/esp
10     # . save registers
11     51/push-ecx
12     56/push-esi
13     # result = false
14     b8/copy-to-eax 0/imm32/false
15     # esi = s
16     8b/-> *(ebp+8) 6/r32/esi
17     # return s->read >= s->write
18     8b/-> *esi 1/r32/ecx
19     39/compare-with *(esi+4) 1/r32/ecx
20     0f 9d/set-if->= %al
21 $stream-empty?:end:
22     # . restore registers
23     5e/pop-to-esi
24     59/pop-to-ecx
25     # . epilogue
26     89/<- %esp 5/r32/ebp
27     5d/pop-to-ebp
28     c3/return
30 stream-full?:  # s: (addr stream _) -> result/eax: boolean
31     # . prologue
32     55/push-ebp
33     89/<- %ebp 4/r32/esp
34     # . save registers
35     51/push-ecx
36     56/push-esi
37     # result = false
38     b8/copy-to-eax 0/imm32/false
39     # esi = s
40     8b/-> *(ebp+8) 6/r32/esi
41     # return s->write >= s->size
42     8b/-> *(esi+8) 1/r32/ecx
43     39/compare-with *esi 1/r32/ecx
44     0f 9d/set-if->= %al
45 $stream-full?:end:
46     # . restore registers
47     5e/pop-to-esi
48     59/pop-to-ecx
49     # . epilogue
50     89/<- %esp 5/r32/ebp
51     5d/pop-to-ebp
52     c3/return
54 write-to-stream:  # s: (addr stream _), in: (addr byte), n: int
55     # . prologue
56     55/push-ebp
57     89/<- %ebp 4/r32/esp
58     # . save registers
59     50/push-eax
60     51/push-ecx
61     52/push-edx
62     53/push-ebx
63     57/push-edi
64     # edi = s
65     8b/-> *(ebp+8) 7/r32/edi
66     # var swrite/edx: int = s->write
67     8b/-> *edi 2/r32/edx
68     # if (swrite + n > s->size) abort
69     8b/-> *(ebp+0x10) 1/r32/ecx
70     01/add-to %ecx 2/r32/edx
71     3b/compare 1/r32/ecx *(edi+8)
72     0f 8f/jump-if-> $write-to-stream:abort/disp32
73     # var out/edx: (addr byte) = s->data + s->write
74     8d/copy-address *(edi+edx+0xc) 2/r32/edx
75     # var outend/ebx: (addr byte) = out + n
76     8b/-> *(ebp+0x10) 3/r32/ebx
77     8d/copy-address *(edx+ebx) 3/r32/ebx
78     # eax = in
79     8b/-> *(ebp+0xc) 0/r32/eax
80     # var inend/ecx: (addr byte) = in + n
81     8b/-> *(ebp+0x10) 1/r32/ecx
82     8d/copy-address *(eax+ecx) 1/r32/ecx
83     #
84     (_append-4  %edx %ebx  %eax %ecx)  # => eax
85     # s->write += n
86     8b/-> *(ebp+0x10) 1/r32/ecx
87     01/add-to *edi 1/r32/ecx
88 $write-to-stream:end:
89     # . restore registers
90     5f/pop-to-edi
91     5b/pop-to-ebx
92     5a/pop-to-edx
93     59/pop-to-ecx
94     58/pop-to-eax
95     # . epilogue
96     89/<- %esp 5/r32/ebp
97     5d/pop-to-ebp
98     c3/return
100 $write-to-stream:abort:
101     (abort "write-to-stream: stream full")
102     # never gets here
104 read-from-stream:  # s: (addr stream _), out: (addr byte), n: int
105     # . prologue
106     55/push-ebp
107     89/<- %ebp 4/r32/esp
108     # . save registers
109     50/push-eax
110     51/push-ecx
111     52/push-edx
112     53/push-ebx
113     56/push-esi
114     # esi = s
115     8b/-> *(ebp+8) 6/r32/esi
116     # var sread/edx: int = s->read
117     8b/-> *(esi+4) 2/r32/edx
118     # if (sread + n > s->write) abort
119     8b/-> *(ebp+0x10) 1/r32/ecx
120     01/add-to %ecx 2/r32/edx
121     3b/compare 1/r32/ecx *esi
122     0f 8f/jump-if-> $read-from-stream:abort/disp32
123     # var in/edx: (addr byte) = s->data + s->read
124     8d/copy-address *(esi+edx+0xc) 2/r32/edx
125     # var inend/ebx: (addr byte) = in + n
126     8b/-> *(ebp+0x10) 3/r32/ebx
127     8d/copy-address *(edx+ebx) 3/r32/ebx
128     # eax = out
129     8b/-> *(ebp+0xc) 0/r32/eax
130     # var outend/ecx: (addr byte) = out + n
131     8b/-> *(ebp+0x10) 1/r32/ecx
132     8d/copy-address *(eax+ecx) 1/r32/ecx
133     #
134     (_append-4  %eax %ecx  %edx %ebx)  # => eax
135     # s->read += n
136     8b/-> *(ebp+0x10) 1/r32/ecx
137     01/add-to *(esi+4) 1/r32/ecx
138 $read-from-stream:end:
139     # . restore registers
140     5e/pop-to-esi
141     5b/pop-to-ebx
142     5a/pop-to-edx
143     59/pop-to-ecx
144     58/pop-to-eax
145     # . epilogue
146     89/<- %esp 5/r32/ebp
147     5d/pop-to-ebp
148     c3/return
150 $read-from-stream:abort:
151     (abort "read-from-stream: stream empty")
152     # never gets here
154 stream-first:  # s: (addr stream byte) -> result/eax: byte
155     # . prologue
156     55/push-ebp
157     89/<- %ebp 4/r32/esp
158     # . save registers
159     51/push-ecx
160     56/push-esi
161     # result = false
162     b8/copy-to-eax 0/imm32
163     # esi = s
164     8b/-> *(ebp+8) 6/r32/esi
165     # var idx/ecx: int = s->read
166     8b/-> *(esi+4) 1/r32/ecx
167     # if idx >= s->write return 0
168     3b/compare-with 1/r32/ecx *esi
169     7d/jump-if->= $stream-first:end/disp8
170     # result = s->data[idx]
171     8a/byte-> *(esi+ecx+0xc) 0/r32/AL
172 $stream-first:end:
173     # . restore registers
174     5e/pop-to-esi
175     59/pop-to-ecx
176     # . epilogue
177     89/<- %esp 5/r32/ebp
178     5d/pop-to-ebp
179     c3/return
181 stream-final:  # s: (addr stream byte) -> result/eax: byte
182     # . prologue
183     55/push-ebp
184     89/<- %ebp 4/r32/esp
185     # . save registers
186     51/push-ecx
187     56/push-esi
188     # result = false
189     b8/copy-to-eax 0/imm32
190     # esi = s
191     8b/-> *(ebp+8) 6/r32/esi
192     # var max/ecx: int = s->write
193     8b/-> *esi 1/r32/ecx
194     # if s->read >= max return 0
195     39/compare-with *(esi+4) 1/r32/ecx
196     7d/jump-if->= $stream-final:end/disp8
197     # var idx/ecx: int = max - 1
198     49/decrement-ecx
199     # result = s->data[idx]
200     8a/byte-> *(esi+ecx+0xc) 0/r32/AL
201 $stream-final:end:
202     # . restore registers
203     5e/pop-to-esi
204     59/pop-to-ecx
205     # . epilogue
206     89/<- %esp 5/r32/ebp
207     5d/pop-to-ebp
208     c3/return
210 # compare all the data in two streams (ignoring the read pointer)
211 streams-data-equal?:  # a: (addr stream byte), b: (addr array byte) -> result/eax: boolean
212     # pseudocode:
213     #   awrite = a->write
214     #   if (awrite != b->write) return false
215     #   i = 0
216     #   curra = a->data
217     #   currb = b->data
218     #   while i < awrite
219     #     i1 = *curra
220     #     i2 = *currb
221     #     if (c1 != c2) return false
222     #     i+=4, curra+=4, currb+=4
223     #   return true
224     #
225     # registers:
226     #   i: ecx
227     #   awrite: edx
228     #   curra: esi
229     #   currb: edi
230     #   i1: eax
231     #   i2: ebx
232     #
233     # . prologue
234     55/push-ebp
235     89/<- %ebp 4/r32/esp
236     # . save registers
237     51/push-ecx
238     52/push-edx
239     53/push-ebx
240     56/push-esi
241     57/push-edi
242     # esi = a
243     8b/-> *(ebp+8) 6/r32/esi
244     # edi = b
245     8b/-> *(ebp+0xc) 7/r32/edi
246     # var awrite/edx: int = a->write
247     8b/-> *esi 2/r32/edx
248 $streams-data-equal?:sizes:
249     # if (awrite != b->write) return false
250     39/compare *edi 2/r32/edx
251     75/jump-if-!= $streams-data-equal?:false/disp8
252     # var curra/esi: (addr byte) = a->data
253     81 0/subop/add %esi 0xc/imm32
254     # var currb/edi: (addr byte) = b->data
255     81 0/subop/add %edi 0xc/imm32
256     # var i/ecx: int = 0
257     31/xor-with %ecx 1/r32/ecx
258     # var vala/eax: int
259     31/xor-with %eax 0/r32/eax
260     # var valb/ebx: int
261     31/xor-with %ebx 3/r32/ebx
262 $streams-data-equal?:loop:
263     {
264       # if (i >= awrite) return true
265       39/compare %ecx 2/r32/edx
266       7d/jump-if->= $streams-data-equal?:true/disp8
267       # var vala/eax: int = *curra
268       8a/byte-> *esi 0/r32/eax
269       # var valb/ebx: int = *currb
270       8a/byte-> *edi 3/r32/ebx
271       # if (vala != valb) return false
272       39/compare %eax 3/r32/ebx
273       75/jump-if-!= $streams-data-equal?:false/disp8
274       # i++
275       41/increment-ecx
276       # curra++
277       46/increment-esi
278       # currb++
279       47/increment-edi
280       eb/jump loop/disp8
281     }
282 $streams-data-equal?:true:
283     b8/copy-to-eax 1/imm32
284     eb/jump $streams-data-equal?:end/disp8
285 $streams-data-equal?:false:
286     b8/copy-to-eax 0/imm32
287 $streams-data-equal?:end:
288     # . restore registers
289     5f/pop-to-edi
290     5e/pop-to-esi
291     5b/pop-to-ebx
292     5a/pop-to-edx
293     59/pop-to-ecx
294     # . epilogue
295     89/<- %esp 5/r32/ebp
296     5d/pop-to-ebp
297     c3/return
299 # helper for tests
300 check-streams-data-equal:  # s: (addr stream _), expected: (addr array _), msg: (addr array byte)
301     # . prologue
302     55/push-ebp
303     89/<- %ebp 4/r32/esp
304     # . save registers
305     50/push-eax
306     #
307     (streams-data-equal? *(ebp+8) *(ebp+0xc))  # => eax
308     (check-ints-equal %eax 1 *(ebp+0x10))
309 $check-streams-data-equal:end:
310     # . restore registers
311     58/pop-to-eax
312     # . epilogue
313     89/<- %esp 5/r32/ebp
314     5d/pop-to-ebp
315     c3/return