https://github.com/akkartik/mu/blob/master/apps/mu.subx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210 == data
211
212 Program:
213 0/imm32
214
215 Function-name:
216 0/imm32
217 Function-subx-name:
218 4/imm32
219 Function-inouts:
220 8/imm32
221 Function-outputs:
222 0xc/imm32
223 Function-body:
224 0x10/imm32
225 Function-next:
226 0x14/imm32
227 Function-size:
228 0x18/imm32/24
229
230 Primitive-name:
231 0/imm32
232 Primitive-inouts:
233 4/imm32
234 Primitive-outputs:
235 8/imm32
236 Primitive-subx-name:
237 0xc/imm32
238 Primitive-subx-rm32:
239 0x10/imm32
240 Primitive-subx-r32:
241 0x14/imm32
242 Primitive-subx-imm32:
243 0x18/imm32
244 Primitive-next:
245 0x1c/imm32
246 Primitive-size:
247 0x20/imm32/24
248
249 Stmt-operation:
250 0/imm32
251 Stmt-inouts:
252 4/imm32
253 Stmt-outputs:
254 8/imm32
255 Stmt-next:
256 0xc/imm32
257 Stmt-size:
258 0x10/imm32
259
260 Var-name:
261 0/imm32
262 Var-type:
263 4/imm32
264 Var-block:
265 8/imm32
266 Var-stack-offset:
267 0xc/imm32
268 Var-register:
269 0x10/imm32
270 Var-size:
271 0x14/imm32
272
273 Any-register:
274
275 1/imm32
276
277 2a/asterisk
278
279 == code
280
281 Entry:
282
283 89/<- %ebp 4/r32/esp
284 (new-segment Heap-size Heap)
285
286 {
287
288 81 7/subop/compare *ebp 1/imm32
289 7e/jump-if-lesser-or-equal break/disp8
290
291 (kernel-string-equal? *(ebp+8) "test")
292 3d/compare-eax-and 0/imm32
293 74/jump-if-equal break/disp8
294
295 (run-tests)
296
297 8b/-> *Num-test-failures 3/r32/ebx
298 eb/jump $mu-main:end/disp8
299 }
300
301 (convert-mu Stdin Stdout)
302 (flush Stdout)
303
304 bb/copy-to-ebx 0/imm32
305 $mu-main:end:
306 b8/copy-to-eax 1/imm32/exit
307 cd/syscall 0x80/imm8
308
309 convert-mu:
310
311 55/push-ebp
312 89/<- %ebp 4/r32/esp
313
314 (parse-mu *(ebp+8))
315 (check-mu-types)
316 (emit-subx *(ebp+0xc))
317 $convert-mu:end:
318
319 89/<- %esp 5/r32/ebp
320 5d/pop-to-ebp
321 c3/return
322
323 test-convert-empty-input:
324
325
326 55/push-ebp
327 89/<- %ebp 4/r32/esp
328
329 (clear-stream _test-input-stream)
330 (clear-stream _test-input-buffered-file->buffer)
331 (clear-stream _test-output-stream)
332 (clear-stream _test-output-buffered-file->buffer)
333
334 (convert-mu _test-input-buffered-file _test-output-buffered-file)
335 (flush _test-output-buffered-file)
336 (check-stream-equal _test-output-stream "" "F - test-convert-empty-input")
337
338 89/<- %esp 5/r32/ebp
339 5d/pop-to-ebp
340 c3/return
341
342 test-convert-function-skeleton:
343
344
345
346
347
348
349
350
351
352
353
354
355
356 55/push-ebp
357 89/<- %ebp 4/r32/esp
358
359 (clear-stream _test-input-stream)
360 (clear-stream _test-input-buffered-file->buffer)
361 (clear-stream _test-output-stream)
362 (clear-stream _test-output-buffered-file->buffer)
363
364 (write _test-input-stream "fn foo {\n")
365 (write _test-input-stream "}\n")
366
367 (convert-mu _test-input-buffered-file _test-output-buffered-file)
368 (flush _test-output-buffered-file)
369 +-- 6 lines: #? # dump _test-output-stream --------------------------------------------------------------------------------------------------------------
375
376 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-skeleton/0")
377 (check-next-stream-line-equal _test-output-stream "# . prologue" "F - test-convert-function-skeleton/1")
378 (check-next-stream-line-equal _test-output-stream "55/push-ebp" "F - test-convert-function-skeleton/2")
379 (check-next-stream-line-equal _test-output-stream "89/<- %ebp 4/r32/esp" "F - test-convert-function-skeleton/3")
380 (check-next-stream-line-equal _test-output-stream "# . epilogue" "F - test-convert-function-skeleton/4")
381 (check-next-stream-line-equal _test-output-stream "89/<- %esp 5/r32/ebp" "F - test-convert-function-skeleton/5")
382 (check-next-stream-line-equal _test-output-stream "5d/pop-to-ebp" "F - test-convert-function-skeleton/6")
383 (check-next-stream-line-equal _test-output-stream "c3/return" "F - test-convert-function-skeleton/7")
384
385 89/<- %esp 5/r32/ebp
386 5d/pop-to-ebp
387 c3/return
388
389 test-convert-multiple-function-skeletons:
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413 55/push-ebp
414 89/<- %ebp 4/r32/esp
415
416 (clear-stream _test-input-stream)
417 (clear-stream _test-input-buffered-file->buffer)
418 (clear-stream _test-output-stream)
419 (clear-stream _test-output-buffered-file->buffer)
420
421 (write _test-input-stream "fn foo {\n")
422 (write _test-input-stream "}\n")
423 (write _test-input-stream "fn bar {\n")
424 (write _test-input-stream "}\n")
425
426 (convert-mu _test-input-buffered-file _test-output-buffered-file)
427 (flush _test-output-buffered-file)
428 +-- 6 lines: #? # dump _test-output-stream --------------------------------------------------------------------------------------------------------------
434
435 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-multiple-function-skeletons/0")
436 (check-next-stream-line-equal _test-output-stream "# . prologue" "F - test-convert-multiple-function-skeletons/1")
437 (check-next-stream-line-equal _test-output-stream "55/push-ebp" "F - test-convert-multiple-function-skeletons/2")
438 (check-next-stream-line-equal _test-output-stream "89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/3")
439 (check-next-stream-line-equal _test-output-stream "# . epilogue" "F - test-convert-multiple-function-skeletons/4")
440 (check-next-stream-line-equal _test-output-stream "89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/5")
441 (check-next-stream-line-equal _test-output-stream "5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/6")
442 (check-next-stream-line-equal _test-output-stream "c3/return" "F - test-convert-multiple-function-skeletons/7")
443
444 (check-next-stream-line-equal _test-output-stream "bar:" "F - test-convert-multiple-function-skeletons/10")
445 (check-next-stream-line-equal _test-output-stream "# . prologue" "F - test-convert-multiple-function-skeletons/11")
446 (check-next-stream-line-equal _test-output-stream "55/push-ebp" "F - test-convert-multiple-function-skeletons/12")
447 (check-next-stream-line-equal _test-output-stream "89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/13")
448 (check-next-stream-line-equal _test-output-stream "# . epilogue" "F - test-convert-multiple-function-skeletons/14")
449 (check-next-stream-line-equal _test-output-stream "89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/15")
450 (check-next-stream-line-equal _test-output-stream "5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/16")
451 (check-next-stream-line-equal _test-output-stream "c3/return" "F - test-convert-multiple-function-skeletons/17")
452
453 89/<- %esp 5/r32/ebp
454 5d/pop-to-ebp
455 c3/return
456
457 test-convert-function-with-arg:
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476 55/push-ebp
477 89/<- %ebp 4/r32/esp
478
479 (clear-stream _test-input-stream)
480 (clear-stream _test-input-buffered-file->buffer)
481 (clear-stream _test-output-stream)
482 (clear-stream _test-output-buffered-file->buffer)
483
484 (write _test-input-stream "fn foo {\n")
485 (write _test-input-stream "}\n")
486
487 (convert-mu _test-input-buffered-file _test-output-buffered-file)
488 (flush _test-output-buffered-file)
489 +-- 6 lines: #? # dump _test-output-stream --------------------------------------------------------------------------------------------------------------
495
496 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-skeleton/0")
497 (check-next-stream-line-equal _test-output-stream "# . prologue" "F - test-convert-function-skeleton/1")
498 (check-next-stream-line-equal _test-output-stream "55/push-ebp" "F - test-convert-function-skeleton/2")
499 (check-next-stream-line-equal _test-output-stream "89/<- %ebp 4/r32/esp" "F - test-convert-function-skeleton/3")
500 (check-next-stream-line-equal _test-output-stream "# . epilogue" "F - test-convert-function-skeleton/4")
501 (check-next-stream-line-equal _test-output-stream "89/<- %esp 5/r32/ebp" "F - test-convert-function-skeleton/5")
502 (check-next-stream-line-equal _test-output-stream "5d/pop-to-ebp" "F - test-convert-function-skeleton/6")
503 (check-next-stream-line-equal _test-output-stream "c3/return" "F - test-convert-function-skeleton/7")
504
505 89/<- %esp 5/r32/ebp
506 5d/pop-to-ebp
507 c3/return
508
509 parse-mu:
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533 55/push-ebp
534 89/<- %ebp 4/r32/esp
535
536 50/push-eax
537 51/push-ecx
538 52/push-edx
539 57/push-edi
540
541 81 5/subop/subtract %esp 0x200/imm32
542 68/push 0x200/imm32/length
543 68/push 0/imm32/read
544 68/push 0/imm32/write
545 89/<- %ecx 4/r32/esp
546
547 68/push 0/imm32/end
548 68/push 0/imm32/start
549 89/<- %edx 4/r32/esp
550
551 bf/copy-to-edi Program/imm32
552 {
553 $parse-mu:line-loop:
554 (clear-stream %ecx)
555 (read-line-buffered *(ebp+8) %ecx)
556
557 81 7/subop/compare *ecx 0/imm32
558 0f 84/jump-if-equal break/disp32
559 +-- 6 lines: #? # dump line ---------------------------------------------------------------------------------------------------------------------------
565 {
566 $parse-mu:word-loop:
567 (next-word-or-string %ecx %edx)
568
569 (slice-empty? %edx)
570 3d/compare-eax-and 0/imm32
571 0f 85/jump-if-not-equal break/disp32
572
573
574 8b/-> *edx 0/r32/eax
575 8a/copy-byte *eax 0/r32/AL
576 81 4/subop/and %eax 0xff/imm32
577
578 3d/compare-eax-and 0x23/imm32/hash
579 0f 84/jump-if-equal break/disp32
580
581 {
582 (slice-equal? %edx "fn")
583 3d/compare-eax-and 0/imm32
584 0f 84/jump-if-equal break/disp32
585
586 (allocate Heap *Function-size)
587 (populate-mu-function-header %ecx %eax)
588 (populate-mu-function-body *(ebp+8) %eax)
589
590 89/<- *edi 0/r32/eax
591
592 8d/address-> *(eax+0x10) 7/r32/edi
593 e9/jump $parse-mu:word-loop/disp32
594 }
595
596 e9/jump $parse-mu:abort/disp32
597 }
598 e9/jump loop/disp32
599 }
600 $parse-mu:end:
601
602 81 0/subop/add %esp 0x214/imm32
603
604 5f/pop-to-edi
605 5a/pop-to-edx
606 59/pop-to-ecx
607 58/pop-to-eax
608
609 89/<- %esp 5/r32/ebp
610 5d/pop-to-ebp
611 c3/return
612
613 $parse-mu:abort:
614
615 (write-buffered Stderr "unexpected top-level command: ")
616 (write-buffered Stderr %edx)
617 (write-buffered Stderr "\n")
618 (flush Stderr)
619
620 bb/copy-to-ebx 1/imm32
621 b8/copy-to-eax 1/imm32/exit
622 cd/syscall 0x80/imm8
623
624
625
626
627
628
629
630 populate-mu-function-header:
631
632 55/push-ebp
633 89/<- %ebp 4/r32/esp
634
635 50/push-eax
636 51/push-ecx
637 57/push-edi
638
639 8b/-> *(ebp+0xc) 7/r32/edi
640
641 68/push 0/imm32/end
642 68/push 0/imm32/start
643 89/<- %ecx 4/r32/esp
644
645 (next-word *(ebp+8) %ecx)
646 (slice-to-string Heap %ecx)
647 89/<- *edi 0/r32/eax
648
649 (next-word *(ebp+8) %ecx)
650 (slice-equal? %ecx "{")
651 3d/compare-eax-and 0/imm32
652 74/jump-if-equal $populate-mu-function-header:abort/disp8
653
654 {
655
656 (next-word *(ebp+8) %ecx)
657
658 (slice-empty? %ecx)
659 3d/compare-eax-and 0/imm32
660 75/jump-if-not-equal break/disp8
661
662
663 8b/-> *edx 0/r32/eax
664 8a/copy-byte *eax 0/r32/AL
665 81 4/subop/and %eax 0xff/imm32
666
667 3d/compare-eax-and 0x23/imm32/hash
668 74/jump-if-equal break/disp8
669
670 eb/jump $populate-mu-function-header:abort/disp8
671 }
672 $populate-mu-function-header:end:
673
674 81 0/subop/add %esp 8/imm32
675
676 5f/pop-to-edi
677 59/pop-to-ecx
678 58/pop-to-eax
679
680 89/<- %esp 5/r32/ebp
681 5d/pop-to-ebp
682 c3/return
683
684 $populate-mu-function-header:abort:
685
686 (write-buffered Stderr "function header not in form 'fn <name> {' -- '")
687 (rewind-stream *(ebp+8))
688 (write-stream 2 *(ebp+8))
689 (write-buffered Stderr "'\n")
690 (flush Stderr)
691
692 bb/copy-to-ebx 1/imm32
693 b8/copy-to-eax 1/imm32/exit
694 cd/syscall 0x80/imm8
695
696
697
698
699 populate-mu-function-body:
700
701 55/push-ebp
702 89/<- %ebp 4/r32/esp
703
704 50/push-eax
705 51/push-ecx
706 52/push-edx
707 53/push-ebx
708
709 81 5/subop/subtract %esp 0x200/imm32
710 68/push 0x200/imm32/length
711 68/push 0/imm32/read
712 68/push 0/imm32/write
713 89/<- %ecx 4/r32/esp
714
715 68/push 0/imm32/end
716 68/push 0/imm32/start
717 89/<- %edx 4/r32/esp
718
719 bb/copy-to-ebx 1/imm32
720 {
721 $populate-mu-function-body:line-loop:
722
723 81 7/subop/compare %ebx 0/imm32
724 0f 84/jump-if-equal break/disp32
725
726 (clear-stream %ecx)
727 (read-line-buffered *(ebp+8) %ecx)
728
729 81 7/subop/compare *ecx 0/imm32
730 0f 84/jump-if-equal break/disp32
731
732 (next-word %ecx %edx)
733
734 (slice-empty? %ecx)
735 3d/compare-eax-and 0/imm32
736 75/jump-if-not-equal loop/disp8
737
738
739 8b/-> *edx 0/r32/eax
740 8a/copy-byte *eax 0/r32/AL
741 81 4/subop/and %eax 0xff/imm32
742
743 3d/compare-eax-and 0x23/imm32/hash
744 74/jump-if-equal loop/disp8
745 {
746
747 {
748 (slice-equal? %ecx "{")
749 3d/compare-eax-and 0/imm32
750 74/jump-if-equal break/disp8
751 43/increment-ebx
752 eb/jump $curly-found:end/disp8
753 }
754
755 {
756 (slice-equal? %ecx "}")
757 3d/compare-eax-and 0/imm32
758 74/jump-if-equal break/disp8
759 4b/decrement-ebx
760 eb/jump $curly-found:end/disp8
761 }
762
763 eb/jump $populate-mu-function-body:end/disp8
764 }
765
766 $curly-found:end:
767
768 (next-word %ecx %edx)
769
770 (slice-empty? %ecx)
771 3d/compare-eax-and 0/imm32
772 0f 85/jump-if-not-equal loop/disp32
773
774
775 8b/-> *edx 0/r32/eax
776 8a/copy-byte *eax 0/r32/AL
777 81 4/subop/and %eax 0xff/imm32
778
779 3d/compare-eax-and 0x23/imm32/hash
780 0f 84/jump-if-equal loop/disp32
781
782 eb/jump $populate-mu-function-body:abort/disp8
783 }
784 $populate-mu-function-body:end:
785
786 81 0/subop/add %esp 0x214/imm32
787
788 5b/pop-to-ebx
789 5a/pop-to-edx
790 59/pop-to-ecx
791 58/pop-to-eax
792
793 89/<- %esp 5/r32/ebp
794 5d/pop-to-ebp
795 c3/return
796
797 $populate-mu-function-body:abort:
798
799 (write-buffered Stderr "'{' or '}' should be on its own line, but got '")
800 (rewind-stream %ecx)
801 (write-stream 2 %ecx)
802 (write-buffered Stderr "'\n")
803 (flush Stderr)
804
805 bb/copy-to-ebx 1/imm32
806 b8/copy-to-eax 1/imm32/exit
807 cd/syscall 0x80/imm8
808
809
810 check-mu-types:
811
812 55/push-ebp
813 89/<- %ebp 4/r32/esp
814
815 $check-types:end:
816
817 89/<- %esp 5/r32/ebp
818 5d/pop-to-ebp
819 c3/return
820
821 emit-subx:
822
823 55/push-ebp
824 89/<- %ebp 4/r32/esp
825
826 50/push-eax
827 51/push-ecx
828 57/push-edi
829
830 8b/-> *(ebp+8) 7/r32/edi
831
832 8b/-> *Program 1/r32/ecx
833 {
834
835 81 7/subop/compare %ecx 0/imm32
836 0f 84/jump-if-equal break/disp32
837 (emit-subx-function %edi %ecx)
838
839 8b/-> *(ecx+0x10) 1/r32/ecx
840 e9/jump loop/disp32
841 }
842 $emit-subx:end:
843
844 5f/pop-to-edi
845 59/pop-to-ecx
846 58/pop-to-eax
847
848 89/<- %esp 5/r32/ebp
849 5d/pop-to-ebp
850 c3/return
851
852
853
854
855
856
857
858 emit-subx-function:
859
860 55/push-ebp
861 89/<- %ebp 4/r32/esp
862
863 50/push-eax
864 51/push-ecx
865 57/push-edi
866
867 8b/-> *(ebp+8) 7/r32/edi
868
869 8b/-> *(ebp+0xc) 1/r32/ecx
870
871 (write-buffered %edi *ecx)
872 (write-buffered %edi ":\n")
873 (emit-subx-prologue %edi)
874 (emit-subx-block %edi *(ecx+0x10))
875 (emit-subx-epilogue %edi)
876 $emit-subx-function:end:
877
878 5f/pop-to-edi
879 59/pop-to-ecx
880 58/pop-to-eax
881
882 89/<- %esp 5/r32/ebp
883 5d/pop-to-ebp
884 c3/return
885
886 emit-subx-block:
887
888 55/push-ebp
889 89/<- %ebp 4/r32/esp
890
891 $emit-subx-block:end:
892
893 89/<- %esp 5/r32/ebp
894 5d/pop-to-ebp
895 c3/return
896
897 emit-subx-statement:
898
899 55/push-ebp
900 89/<- %ebp 4/r32/esp
901
902 50/push-eax
903 51/push-ecx
904
905 {
906 $emit-subx-statement:primitive:
907 (find-matching-primitive *(ebp+0x14) *(ebp+0xc))
908 3d/compare-eax-and 0/imm32
909 74/jump-if-equal break/disp8
910 (emit-subx-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax)
911 e9/jump $emit-subx-statement:end/disp32
912 }
913
914 {
915 $emit-subx-statement:call:
916 (find-matching-function *(ebp+0x18) *(ebp+0xc))
917 3d/compare-eax-and 0/imm32
918 74/jump-if-equal break/disp8
919 (emit-subx-call *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax)
920 e9/jump $emit-subx-statement:end/disp32
921 }
922
923 e9/jump $emit-subx-statement:abort/disp32
924 $emit-subx-statement:end:
925
926 59/pop-to-ecx
927 58/pop-to-eax
928
929 89/<- %esp 5/r32/ebp
930 5d/pop-to-ebp
931 c3/return
932
933 $emit-subx-statement:abort:
934
935 (write-buffered Stderr "couldn't translate '")
936
937 (write-buffered Stderr "'\n")
938 (flush Stderr)
939
940 bb/copy-to-ebx 1/imm32
941 b8/copy-to-eax 1/imm32/exit
942 cd/syscall 0x80/imm8
943
944
945 emit-subx-primitive:
946
947 55/push-ebp
948 89/<- %ebp 4/r32/esp
949
950 50/push-eax
951 51/push-ecx
952
953 8b/-> *(ebp+0x14) 1/r32/ecx
954
955 (write-buffered *(ebp+8) *(ecx+0xc))
956
957 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc))
958
959
960
961
962 $emit-subx-primitive:end:
963
964 59/pop-to-ecx
965 58/pop-to-eax
966
967 89/<- %esp 5/r32/ebp
968 5d/pop-to-ebp
969 c3/return
970
971 emit-subx-rm32:
972
973 55/push-ebp
974 89/<- %ebp 4/r32/esp
975
976 50/push-eax
977
978 81 7/subop/compare *(ebp+0xc) 0/imm32
979 74/jump-if-equal $emit-subx-rm32:end/disp8
980
981 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))
982 (emit-subx-call-operand *(ebp+8) %eax)
983 $emit-subx-rm32:end:
984
985 58/pop-to-eax
986
987 89/<- %esp 5/r32/ebp
988 5d/pop-to-ebp
989 c3/return
990
991 get-stmt-operand-from-arg-location:
992
993 55/push-ebp
994 89/<- %ebp 4/r32/esp
995
996 51/push-ecx
997
998 8b/-> *(ebp+0xc) 0/r32/eax
999
1000 8b/-> *(ebp+8) 1/r32/ecx
1001
1002 {
1003 3d/compare-eax-and 1/imm32
1004 75/jump-if-not-equal break/disp8
1005 $get-stmt-operand-from-arg-location:1:
1006 8b/-> *(ecx+4) 0/r32/eax
1007 8b/-> *eax 0/r32/eax
1008 eb/jump $get-stmt-operand-from-arg-location:end/disp8
1009 }
1010
1011 {
1012 3d/compare-eax-and 2/imm32
1013 75/jump-if-not-equal break/disp8
1014 $get-stmt-operand-from-arg-location:2:
1015 8b/-> *(ecx+4) 0/r32/eax
1016 8b/-> *(eax+4) 0/r32/eax
1017 8b/-> *eax 0/r32/eax
1018 eb/jump $get-stmt-operand-from-arg-location:end/disp8
1019 }
1020
1021 {
1022 3d/compare-eax-and 3/imm32
1023 75/jump-if-not-equal break/disp8
1024 $get-stmt-operand-from-arg-location:3:
1025 8b/-> *(ecx+8) 0/r32/eax
1026 8b/-> *eax 0/r32/eax
1027 eb/jump $get-stmt-operand-from-arg-location:end/disp8
1028 }
1029
1030 e9/jump $get-stmt-operand-from-arg-location:abort/disp32
1031 $get-stmt-operand-from-arg-location:end:
1032
1033 59/pop-to-ecx
1034
1035 89/<- %esp 5/r32/ebp
1036 5d/pop-to-ebp
1037 c3/return
1038
1039 $get-stmt-operand-from-arg-location:abort:
1040
1041 (write-buffered Stderr "invalid arg-location ")
1042 (print-int32-buffered Stderr %eax)
1043 (write-buffered Stderr "\n")
1044 (flush Stderr)
1045
1046 bb/copy-to-ebx 1/imm32
1047 b8/copy-to-eax 1/imm32/exit
1048 cd/syscall 0x80/imm8
1049
1050
1051 emit-subx-r32:
1052
1053 55/push-ebp
1054 89/<- %ebp 4/r32/esp
1055
1056 50/push-eax
1057 51/push-ecx
1058
1059
1060
1061
1062 $emit-subx-r32:end:
1063
1064 59/pop-to-ecx
1065 58/pop-to-eax
1066
1067 89/<- %esp 5/r32/ebp
1068 5d/pop-to-ebp
1069 c3/return
1070
1071 emit-subx-imm32:
1072
1073 55/push-ebp
1074 89/<- %ebp 4/r32/esp
1075
1076 50/push-eax
1077 51/push-ecx
1078
1079
1080 $emit-subx-imm32:end:
1081
1082 59/pop-to-ecx
1083 58/pop-to-eax
1084
1085 89/<- %esp 5/r32/ebp
1086 5d/pop-to-ebp
1087 c3/return
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102 emit-subx-call:
1103
1104 55/push-ebp
1105 89/<- %ebp 4/r32/esp
1106
1107 50/push-eax
1108 51/push-ecx
1109
1110 (write-buffered *(ebp+8) "(")
1111
1112 8b/-> *(ebp+0x14) 1/r32/ecx
1113 (write-buffered *(ebp+8) *(ecx+4))
1114
1115
1116 8b/-> *(ebp+0xc) 1/r32/ecx
1117 8b/-> *(ecx+4) 1/r32/ecx
1118 {
1119
1120 81 7/subop/compare %ecx 0/imm32
1121 74/jump-if-equal break/disp8
1122
1123 (emit-subx-call-operand *(ebp+8) *ecx)
1124
1125 8b/-> *(ecx+4) 1/r32/ecx
1126 }
1127
1128 (write-buffered *(ebp+8) ")")
1129 $emit-subx-call:end:
1130
1131 59/pop-to-ecx
1132 58/pop-to-eax
1133
1134 89/<- %esp 5/r32/ebp
1135 5d/pop-to-ebp
1136 c3/return
1137
1138 emit-subx-call-operand:
1139
1140 55/push-ebp
1141 89/<- %ebp 4/r32/esp
1142
1143 50/push-eax
1144
1145 8b/-> *(ebp+0xc) 0/r32/eax
1146
1147 {
1148 81 7/subop/compare *(eax+0x10) 0/imm32
1149 74/jump-if-equal break/disp8
1150 $emit-subx-call-operand:register:
1151 (write-buffered *(ebp+8) " %")
1152 (write-buffered *(ebp+8) *(eax+0x10))
1153 }
1154
1155 {
1156 81 7/subop/compare *(eax+0xc) 0/imm32
1157 74/jump-if-equal break/disp8
1158 $emit-subx-call-operand:stack:
1159 (write-buffered *(ebp+8) Space)
1160 (write-buffered *(ebp+8) "*(ebp+")
1161 8b/-> *(ebp+0xc) 0/r32/eax
1162 (print-int32-buffered *(ebp+8) *(eax+0xc))
1163 (write-buffered *(ebp+8) ")")
1164 }
1165 $emit-subx-call-operand:end:
1166
1167 58/pop-to-eax
1168
1169 89/<- %esp 5/r32/ebp
1170 5d/pop-to-ebp
1171 c3/return
1172
1173 find-matching-function:
1174
1175 55/push-ebp
1176 89/<- %ebp 4/r32/esp
1177
1178 51/push-ecx
1179
1180 8b/-> *(ebp+8) 1/r32/ecx
1181 {
1182
1183 81 7/subop/compare %ecx 0/imm32
1184 74/jump-if-equal break/disp8
1185
1186 {
1187 (mu-stmt-matches-function? *(ebp+0xc) %ecx)
1188 3d/compare-eax-and 0/imm32
1189 74/jump-if-equal break/disp8
1190 89/<- %eax 1/r32/ecx
1191 eb/jump $find-matching-function:end/disp8
1192 }
1193
1194 8b/-> *(ecx+0x10) 1/r32/ecx
1195 eb/jump loop/disp8
1196 }
1197
1198 b8/copy-to-eax 0/imm32
1199 $find-matching-function:end:
1200
1201 59/pop-to-ecx
1202
1203 89/<- %esp 5/r32/ebp
1204 5d/pop-to-ebp
1205 c3/return
1206
1207 find-matching-primitive:
1208
1209 55/push-ebp
1210 89/<- %ebp 4/r32/esp
1211
1212 51/push-ecx
1213
1214 8b/-> *(ebp+8) 1/r32/ecx
1215 {
1216
1217 81 7/subop/compare %ecx 0/imm32
1218 74/jump-if-equal break/disp8
1219
1220 {
1221 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx)
1222 3d/compare-eax-and 0/imm32
1223 74/jump-if-equal break/disp8
1224 89/<- %eax 1/r32/ecx
1225 eb/jump $find-matching-function:end/disp8
1226 }
1227
1228 8b/-> *(ecx+0x18) 1/r32/ecx
1229 eb/jump loop/disp8
1230 }
1231
1232 b8/copy-to-eax 0/imm32
1233 $find-matching-primitive:end:
1234
1235 59/pop-to-ecx
1236
1237 89/<- %esp 5/r32/ebp
1238 5d/pop-to-ebp
1239 c3/return
1240
1241 mu-stmt-matches-function?:
1242
1243 55/push-ebp
1244 89/<- %ebp 4/r32/esp
1245
1246 51/push-ecx
1247
1248 8b/-> *(ebp+8) 1/r32/ecx
1249 8b/-> *(ebp+0xc) 0/r32/eax
1250 (string-equal? *ecx *eax)
1251 $mu-stmt-matches-function?:end:
1252
1253 59/pop-to-ecx
1254
1255 89/<- %esp 5/r32/ebp
1256 5d/pop-to-ebp
1257 c3/return
1258
1259 mu-stmt-matches-primitive?:
1260
1261 55/push-ebp
1262 89/<- %ebp 4/r32/esp
1263
1264 51/push-ecx
1265
1266 8b/-> *(ebp+8) 1/r32/ecx
1267 8b/-> *(ebp+0xc) 0/r32/eax
1268 (string-equal? *ecx *eax)
1269 $mu-stmt-matches-primitive?:end:
1270
1271 59/pop-to-ecx
1272
1273 89/<- %esp 5/r32/ebp
1274 5d/pop-to-ebp
1275 c3/return
1276
1277 test-emit-subx-statement-primitive:
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296 55/push-ebp
1297 89/<- %ebp 4/r32/esp
1298
1299 (clear-stream _test-output-stream)
1300 (clear-stream _test-output-buffered-file->buffer)
1301
1302 68/push 0/imm32/no-register
1303 68/push -8/imm32/stack-offset
1304 68/push 1/imm32/block-depth
1305 68/push 1/imm32/type-int
1306 68/push "foo"/imm32
1307 89/<- %ecx 4/r32/esp
1308
1309 51/push-ecx/var-foo
1310 68/push 1/imm32/data-length
1311 68/push 1/imm32/top
1312 89/<- %edx 4/r32/esp
1313
1314 68/push 0/imm32/next
1315 51/push-ecx/var-foo
1316 89/<- %esi 4/r32/esp
1317
1318 68/push 0/imm32/next
1319 68/push 0/imm32/outputs
1320 56/push-esi/operands
1321 68/push "increment"/imm32/operation
1322 89/<- %esi 4/r32/esp
1323
1324 68/push 0/imm32/next
1325 68/push 0/imm32/no-imm32
1326 68/push 0/imm32/no-r32
1327 68/push 1/imm32/rm32-is-first-inout
1328 68/push "ff 0/subop/increment"/imm32/subx-name
1329 68/push 0/imm32/outputs
1330 51/push-ecx/inouts
1331 68/push "increment"/imm32/name
1332 89/<- %ebx 4/r32/esp
1333
1334 (emit-subx-statement _test-output-buffered-file %esi %edx %ebx 0)
1335 (flush _test-output-buffered-file)
1336 +-- 6 lines: #? # dump _test-output-stream --------------------------------------------------------------------------------------------------------------
1342
1343 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-statement-primitive/0")
1344
1345 81 0/subop/add %esp 0x48/imm32
1346
1347 89/<- %esp 5/r32/ebp
1348 5d/pop-to-ebp
1349 c3/return
1350
1351 test-emit-subx-statement-primitive-register:
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370 55/push-ebp
1371 89/<- %ebp 4/r32/esp
1372
1373 (clear-stream _test-output-stream)
1374 (clear-stream _test-output-buffered-file->buffer)
1375
1376 68/push "eax"/imm32/register
1377 68/push 0/imm32/no-stack-offset
1378 68/push 1/imm32/block-depth
1379 68/push 1/imm32/type-int
1380 68/push "foo"/imm32
1381 89/<- %ecx 4/r32/esp
1382
1383 51/push-ecx/var-foo
1384 68/push 1/imm32/data-length
1385 68/push 1/imm32/top
1386 89/<- %edx 4/r32/esp
1387
1388 68/push 0/imm32/next
1389 51/push-ecx/var-foo
1390 89/<- %esi 4/r32/esp
1391
1392 68/push 0/imm32/next
1393 56/push-esi/outputs
1394 68/push 0/imm32/inouts
1395 68/push "increment"/imm32/operation
1396 89/<- %esi 4/r32/esp
1397
1398 68/push Any-register/imm32
1399 68/push 0/imm32/no-stack-offset
1400 68/push 1/imm32/block-depth
1401 68/push 1/imm32/type-int
1402 68/push "dummy"/imm32
1403 89/<- %ebx 4/r32/esp
1404
1405 68/push 0/imm32/next
1406 53/push-ebx/formal-var
1407 89/<- %ebx 4/r32/esp
1408
1409 68/push 0/imm32/next
1410 68/push 0/imm32/no-imm32
1411 68/push 0/imm32/no-r32
1412 68/push 3/imm32/rm32-in-first-output
1413 68/push "ff 0/subop/increment"/imm32/subx-name
1414 53/push-ebx/outputs
1415 68/push 0/imm32/inouts
1416 68/push "increment"/imm32/name
1417 89/<- %ebx 4/r32/esp
1418
1419 (emit-subx-statement _test-output-buffered-file %esi %edx %ebx 0)
1420 (flush _test-output-buffered-file)
1421 +-- 6 lines: #? # dump _test-output-stream --------------------------------------------------------------------------------------------------------------
1427
1428 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-primitive-register/0")
1429
1430 81 0/subop/add %esp 0x48/imm32
1431
1432 89/<- %esp 5/r32/ebp
1433 5d/pop-to-ebp
1434 c3/return
1435
1436 test-emit-subx-statement-function-call:
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457 55/push-ebp
1458 89/<- %ebp 4/r32/esp
1459
1460 (clear-stream _test-output-stream)
1461 (clear-stream _test-output-buffered-file->buffer)
1462
1463 68/push 0/imm32/no-register
1464 68/push -8/imm32/stack-offset
1465 68/push 0/imm32/block-depth
1466 68/push 1/imm32/type-int
1467 68/push "foo"/imm32
1468 89/<- %ecx 4/r32/esp
1469
1470 51/push-ecx/var-foo
1471 68/push 1/imm32/data-length
1472 68/push 1/imm32/top
1473 89/<- %edx 4/r32/esp
1474
1475 68/push 0/imm32/next
1476 51/push-ecx/var-foo
1477 89/<- %esi 4/r32/esp
1478
1479 68/push 0/imm32/next
1480 68/push 0/imm32/outputs
1481 56/push-esi/inouts
1482 68/push "f"/imm32/operation
1483 89/<- %esi 4/r32/esp
1484
1485 68/push 0/imm32/next
1486 68/push 0/imm32/body
1487 68/push 0/imm32/outputs
1488 51/push-ecx/inouts
1489 68/push "f2"/imm32/subx-name
1490 68/push "f"/imm32/name
1491 89/<- %ebx 4/r32/esp
1492
1493 (emit-subx-statement _test-output-buffered-file %esi %edx 0 %ebx)
1494 (flush _test-output-buffered-file)
1495 +-- 6 lines: #? # dump _test-output-stream --------------------------------------------------------------------------------------------------------------
1501
1502 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-statement-function-call/0")
1503
1504 81 0/subop/add %esp 0x3c/imm32
1505
1506 89/<- %esp 5/r32/ebp
1507 5d/pop-to-ebp
1508 c3/return
1509
1510 emit-subx-prologue:
1511
1512 55/push-ebp
1513 89/<- %ebp 4/r32/esp
1514
1515 (write-buffered *(ebp+8) "# . prologue\n")
1516 (write-buffered *(ebp+8) "55/push-ebp\n")
1517 (write-buffered *(ebp+8) "89/<- %ebp 4/r32/esp\n")
1518 $emit-subx-prologue:end:
1519
1520 89/<- %esp 5/r32/ebp
1521 5d/pop-to-ebp
1522 c3/return
1523
1524 emit-subx-epilogue:
1525
1526 55/push-ebp
1527 89/<- %ebp 4/r32/esp
1528
1529 (write-buffered *(ebp+8) "# . epilogue\n")
1530 (write-buffered *(ebp+8) "89/<- %esp 5/r32/ebp\n")
1531 (write-buffered *(ebp+8) "5d/pop-to-ebp\n")
1532 (write-buffered *(ebp+8) "c3/return\n")
1533 $emit-subx-epilogue:end:
1534
1535 89/<- %esp 5/r32/ebp
1536 5d/pop-to-ebp
1537 c3/return