1use crate::casl2;
5
6#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug)]
7pub enum Id {
8 FuncCInt,
9 FuncCStrArgBool,
10 FuncCStrArgInt,
11 FuncSpace,
12 UtilCompareStr,
13 UtilConcatStr,
14 UtilCopyFromOffsetStr,
15 UtilCopyStr,
16 UtilCopyToOffsetStr,
17 UtilDivMod,
18 UtilFill,
19 UtilLoadElement,
20 UtilMul,
21 UtilSafeIndex,
22}
23
24impl Id {
25 pub fn label(&self) -> String {
26 format!("C{:03}", *self as isize)
27 }
28}
29
30pub struct Src {
31 pub dependencies: Vec<Id>,
32 pub statements: Vec<casl2::Statement>,
33}
34
35pub trait Gen {
36 fn var_label(&mut self) -> String;
37 fn jump_label(&mut self) -> String;
38}
39
40pub fn get_src<T: Gen>(gen: &mut T, id: Id) -> Src {
42 match id {
43 Id::FuncCInt => get_func_cint(gen, id),
44 Id::FuncCStrArgBool => get_func_cstr_arg_bool(gen, id),
45 Id::FuncCStrArgInt => get_func_cstr_arg_int(gen, id),
46 Id::FuncSpace => get_func_space(gen, id),
47 Id::UtilCompareStr => get_util_compare_str(gen, id),
48 Id::UtilConcatStr => get_util_concat_str(gen, id),
49 Id::UtilCopyFromOffsetStr => get_util_copy_from_offset_str(gen, id),
50 Id::UtilCopyStr => get_util_copy_str(gen, id),
51 Id::UtilCopyToOffsetStr => get_util_copy_to_offset_str(gen, id),
52 Id::UtilDivMod => get_util_div_mod(gen, id),
53 Id::UtilFill => get_util_fill(gen, id),
54 Id::UtilLoadElement => get_util_load_element(gen, id),
55 Id::UtilMul => get_util_mul(gen, id),
56 Id::UtilSafeIndex => get_util_safe_index(gen, id),
57 }
58}
59
60pub fn get_util_eof_store_code() -> Vec<casl2::Statement> {
62 casl2::parse(&format!(
71 r#"
72EOF START
73 ; UtilEofStore
74 AND GR0,GR0
75 JPL {load}
76 ST GR0,{value}
77 RET
78{load} LD GR0,{value}
79 RET
80{value} DS 1
81 END
82"#,
83 load = "J1",
84 value = "V1"
85 ))
86 .unwrap()
87}
88
89pub fn get_util_allocator_code_for_common(size: usize) -> Vec<casl2::Statement> {
91 #[derive(Default)]
92 struct Temp {
93 j: usize,
94 v: usize,
95 }
96 impl Gen for Temp {
97 fn var_label(&mut self) -> String {
98 self.j += 1;
99 format!("J{}", self.j)
100 }
101 fn jump_label(&mut self) -> String {
102 self.v += 1;
103 format!("V{}", self.v)
104 }
105 }
106 let mut temp = Temp::default();
107 super::utils::to_external("ALLOC", get_util_allocator_code(&mut temp, size))
108}
109
110pub fn get_util_allocator_code<T: Gen>(gen: &mut T, size: usize) -> Vec<casl2::Statement> {
112 casl2::parse(&format!(
119 r#"
120 ; UtilAllocator
121ALLOC AND GR0,GR0
122 JNZ {free}
123 LAD GR0,{mem}
124 ADDL GR0,{cnt}
125 CPL GR0,{pos}
126 JZE {next}
127{init} ST GR1,{cnt}
128 LAD GR0,{mem}
129 ADDL GR1,GR0
130 ST GR1,{pos}
131 RET
132{next} ADDL GR0,GR1
133 CPL GR0,{end}
134 JPL {init}
135 ST GR0,{pos}
136 SUBL GR0,GR1
137 ADDL GR1,{cnt}
138 ST GR1,{cnt}
139 RET
140{free} ST GR1,{pos}
141 LAD GR0,{mem}
142 SUBL GR1,GR0
143 ST GR1,{cnt}
144 RET
145{cnt} DS 1
146{pos} DS 1
147{mem} DS {size}
148{end} DC {end}
149"#,
150 init = gen.jump_label(),
151 next = gen.jump_label(),
152 free = gen.jump_label(),
153 cnt = gen.var_label(),
154 pos = gen.var_label(),
155 mem = gen.var_label(),
156 end = gen.var_label(),
157 size = size
158 ))
159 .unwrap()
160}
161
162fn get_func_cint<T: Gen>(gen: &mut T, id: Id) -> Src {
164 Src {
168 dependencies: Vec::new(),
169 statements: casl2::parse(&format!(
170 r#"
171 ; {comment}
172{prog} PUSH 0,GR1
173 PUSH 0,GR2
174 PUSH 0,GR3
175 PUSH 0,GR4
176 PUSH 0,GR5
177 ADDL GR2,GR1
178 XOR GR0,GR0
179 XOR GR4,GR4
180 CPL GR1,GR2
181 JZE {ret}
182 LD GR3,0,GR1
183 CPL GR3,='+'
184 JNZ {mi}
185 LAD GR1,1,GR1
186 JUMP {read}
187{mi} CPL GR3,='-'
188 JNZ {read}
189 LAD GR4,-1
190 LAD GR1,1,GR1
191{read} CPL GR1,GR2
192 JZE {ret}
193 LD GR3,0,GR1
194 SUBL GR3,='0'
195 JMI {ret}
196 CPL GR3,=9
197 JPL {ret}
198 LD GR5,GR0
199 SLL GR0,3
200 ADDL GR0,GR5
201 ADDL GR0,GR5
202 ADDL GR0,GR3
203 LAD GR1,1,GR1
204 JUMP {read}
205{ret} XOR GR0,GR4
206 SUBL GR0,GR4
207 POP GR5
208 POP GR4
209 POP GR3
210 POP GR2
211 POP GR1
212 RET
213"#,
214 comment = format_args!("{:?}", id),
215 prog = id.label(),
216 ret = gen.jump_label(),
217 read = gen.jump_label(),
218 mi = gen.jump_label()
219 ))
220 .unwrap(),
221 }
222}
223
224fn get_util_safe_index<T: Gen>(gen: &mut T, id: Id) -> Src {
226 Src {
230 dependencies: Vec::new(),
231 statements: casl2::parse(&format!(
232 r#"
233 ; {comment}
234{prog} AND GR2,GR2
235 JNZ {lbound}
236 XOR GR0,GR0
237 RET
238{lbound} LD GR0,GR1
239 JPL {ubound}
240 XOR GR0,GR0
241 RET
242{ubound} CPL GR0,GR2
243 JMI {ok}
244 LAD GR0,-1
245 ADDL GR0,GR2
246{ok} RET
247"#,
248 comment = format_args!("{:?}", id),
249 prog = id.label(),
250 lbound = gen.jump_label(),
251 ubound = gen.jump_label(),
252 ok = gen.jump_label()
253 ))
254 .unwrap(),
255 }
256}
257
258fn get_util_div_mod<T: Gen>(gen: &mut T, id: Id) -> Src {
260 Src {
265 dependencies: vec![Id::UtilMul],
266 statements: casl2::parse(&format!(
267 r#"
268 ; {comment}
269{prog} AND GR3,GR3
270 JNZ {ok}
271 XOR GR0,GR0
272 LAD GR1,-1
273 RET
274{ok} PUSH 0,GR2
275 PUSH 0,GR3
276 PUSH 0,GR4
277 PUSH 0,GR5
278 LD GR4,GR2
279 LD GR5,GR2
280 JPL {x}
281 XOR GR5,GR5
282 SUBA GR5,GR2
283{x} LD GR1,GR3
284 JPL {y}
285 XOR GR1,GR1
286 SUBA GR1,GR3
287{y} LAD GR0,1
288{shift} ADDL GR1,GR1
289 JOV {pre}
290 ADDL GR0,GR0
291 JUMP {shift}
292{pre} SRL GR1,1
293 LAD GR1,#8000,GR1
294 XOR GR2,GR2
295{cycle} CPL GR5,GR1
296 JMI {next}
297 SUBL GR5,GR1
298 ADDL GR2,GR0
299{next} SRL GR0,1
300 JZE {ret}
301 SRL GR1,1
302 JUMP {cycle}
303{ret} LD GR5,GR4
304 XOR GR5,GR3
305 SRA GR5,15
306 XOR GR2,GR5
307 SUBA GR2,GR5
308 CALL {mul}
309 LD GR1,GR4
310 SUBA GR1,GR0
311 LD GR0,GR2
312 POP GR5
313 POP GR4
314 POP GR3
315 POP GR2
316 RET
317"#,
318 comment = format_args!("{:?}", id),
319 prog = id.label(),
320 mul = Id::UtilMul.label(),
321 x = gen.jump_label(),
322 y = gen.jump_label(),
323 ok = gen.jump_label(),
324 shift = gen.jump_label(),
325 pre = gen.jump_label(),
326 cycle = gen.jump_label(),
327 next = gen.jump_label(),
328 ret = gen.jump_label()
329 ))
330 .unwrap(),
331 }
332}
333
334fn get_util_mul<T: Gen>(gen: &mut T, id: Id) -> Src {
336 Src {
340 dependencies: vec![Id::UtilMul],
341 statements: casl2::parse(&format!(
342 r#"
343 ; {comment}
344{prog} PUSH 0,GR2
345 PUSH 0,GR3
346 PUSH 0,GR4
347 PUSH 0,GR5
348 XOR GR0,GR0
349 XOR GR1,GR1
350 LD GR4,GR2
351 LD GR5,GR3
352{cycle1} SRL GR2,1
353 JOV {add1}
354 JNZ {next1}
355 JUMP {cycle2}
356{add1} ADDL GR0,GR3
357 JOV {raise1}
358 JUMP {next1}
359{raise1} LAD GR1,1,GR1
360{next1} SLL GR3,1
361 JUMP {cycle1}
362{cycle2} SRL GR5,1
363 SLL GR4,1
364 JOV {add2}
365 JNZ {cycle2}
366 JUMP {ret}
367{add2} ADDL GR1,GR5
368 JUMP {cycle2}
369{ret} POP GR5
370 POP GR4
371 POP GR3
372 POP GR2
373 RET
374"#,
375 comment = format_args!("{:?}", id),
376 prog = id.label(),
377 cycle1 = gen.jump_label(),
378 add1 = gen.jump_label(),
379 raise1 = gen.jump_label(),
380 next1 = gen.jump_label(),
381 cycle2 = gen.jump_label(),
382 add2 = gen.jump_label(),
383 ret = gen.jump_label()
384 ))
385 .unwrap(),
386 }
387}
388
389fn get_func_cstr_arg_bool<T: Gen>(gen: &mut T, id: Id) -> Src {
391 Src {
395 dependencies: vec![Id::UtilCopyStr],
396 statements: casl2::parse(&format!(
397 r#"
398 ; {comment}
399{prog} PUSH 0,GR3
400 PUSH 0,GR4
401 AND GR3,GR3
402 LAD GR3,='FalseTrue'
403 LAD GR4,5
404 JZE {ret}
405 ADDL GR3,GR4
406 LAD GR4,4
407{ret} CALL {copy}
408 POP GR4
409 POP GR3
410 RET
411"#,
412 comment = format_args!("{:?}", id),
413 prog = id.label(),
414 copy = Id::UtilCopyStr.label(),
415 ret = gen.jump_label()
416 ))
417 .unwrap(),
418 }
419}
420
421fn get_func_cstr_arg_int<T: Gen>(gen: &mut T, id: Id) -> Src {
423 Src {
427 dependencies: vec![Id::UtilDivMod, Id::UtilCopyStr],
428 statements: casl2::parse(&format!(
429 r#"
430 ; {comment}
431{prog} CPL GR3,=#8000
432 JNZ {zero}
433 PUSH 0,GR3
434 PUSH 0,GR4
435 LAD GR3,='-32768'
436 LAD GR4,6
437 CALL {copystr}
438 POP GR4
439 POP GR3
440 RET
441{zero} AND GR3,GR3
442 JNZ {init}
443 LAD GR3,1
444 ST GR3,0,GR2
445 LD GR3,='0'
446 ST GR3,0,GR1
447 XOR GR3,GR3
448 RET
449{init} PUSH 0,GR1
450 PUSH 0,GR2
451 PUSH 0,GR3
452 PUSH 0,GR4
453 PUSH 0,GR5
454 JPL {start}
455 LD GR4,='-'
456 ST GR4,0,GR1
457 LAD GR1,1,GR1
458 XOR GR3,=#FFFF
459 LAD GR3,1,GR3
460{start} LAD GR4,{temp}
461 LD GR5,GR1
462 LD GR2,GR3
463 LAD GR3,10
464{cycle} CALL {rem}
465 ADDL GR1,='0'
466 ST GR1,0,GR4
467 LAD GR4,1,GR4
468 LD GR2,GR0
469 JPL {cycle}
470 LAD GR2,{temp}
471 LAD GR4,-1,GR4
472{copy} LD GR1,0,GR4
473 ST GR1,0,GR5
474 LAD GR5,1,GR5
475 LAD GR4,-1,GR4
476 CPL GR4,GR2
477 JPL {copy}
478 JZE {copy}
479 LD GR0,GR5
480 POP GR5
481 POP GR4
482 POP GR3
483 POP GR2
484 POP GR1
485 SUBL GR0,GR1
486 ST GR0,0,GR2
487 RET
488{temp} DS 6
489"#,
490 comment = format_args!("{:?}", id),
491 prog = id.label(),
492 rem = Id::UtilDivMod.label(),
493 copystr = Id::UtilCopyStr.label(),
494 zero = gen.jump_label(),
495 init = gen.jump_label(),
496 start = gen.jump_label(),
497 cycle = gen.jump_label(),
498 copy = gen.jump_label(),
499 temp = gen.var_label()
500 ))
501 .unwrap(),
502 }
503}
504
505fn get_util_compare_str<T: Gen>(gen: &mut T, id: Id) -> Src {
507 Src {
513 dependencies: Vec::new(),
514 statements: casl2::parse(&format!(
515 r#"
516 ; {comment}
517{prog} PUSH 0,GR1
518 PUSH 0,GR2
519 PUSH 0,GR3
520 PUSH 0,GR4
521 PUSH 0,GR5
522 XOR GR0,GR0
523{cycle} AND GR2,GR2
524 JPL {next}
525 CPL GR2,GR4
526 JNZ {less}
527 JUMP {ret}
528{next} AND GR4,GR4
529 JZE {great}
530 LD GR5,0,GR1
531 CPL GR5,0,GR3
532 JMI {less}
533 JPL {great}
534 LAD GR1,1,GR1
535 LAD GR2,-1,GR2
536 LAD GR3,1,GR3
537 LAD GR4,-1,GR4
538 JUMP {cycle}
539{less} LAD GR0,-1
540{great} OR GR0,=1
541{ret} POP GR5
542 POP GR4
543 POP GR3
544 POP GR2
545 POP GR1
546 RET
547"#,
548 comment = format_args!("{:?}", id),
549 prog = id.label(),
550 cycle = gen.jump_label(),
551 next = gen.jump_label(),
552 less = gen.jump_label(),
553 great = gen.jump_label(),
554 ret = gen.jump_label()
555 ))
556 .unwrap(),
557 }
558}
559
560fn get_util_copy_str<T: Gen>(gen: &mut T, id: Id) -> Src {
562 Src {
568 dependencies: Vec::new(),
569 statements: casl2::parse(&format!(
570 r#"
571 ; {comment}
572{prog} PUSH 0,GR1
573 PUSH 0,GR2
574 PUSH 0,GR3
575 PUSH 0,GR4
576 ST GR4,0,GR2
577 AND GR4,GR4
578 JZE {ret}
579{cycle} LD GR2,0,GR3
580 ST GR2,0,GR1
581 LAD GR3,1,GR3
582 LAD GR1,1,GR1
583 SUBL GR4,=1
584 JPL {cycle}
585{ret} POP GR4
586 POP GR3
587 POP GR2
588 POP GR1
589 RET
590"#,
591 comment = format_args!("{:?}", id),
592 prog = id.label(),
593 cycle = gen.jump_label(),
594 ret = gen.jump_label()
595 ))
596 .unwrap(),
597 }
598}
599
600fn get_util_concat_str<T: Gen>(gen: &mut T, id: Id) -> Src {
602 Src {
609 dependencies: Vec::new(),
610 statements: casl2::parse(&format!(
611 r#"
612 ; {comment}
613{prog} PUSH 0,GR1
614 PUSH 0,GR2
615 PUSH 0,GR3
616 PUSH 0,GR4
617 LD GR0,0,GR2
618 LD GR2,GR1
619 ADDL GR1,GR0
620 LAD GR2,256,GR2
621 ADDL GR4,GR3
622{cycle} CPL GR1,GR2
623 JZE {ret}
624 CPL GR3,GR4
625 JZE {ret}
626 LD GR0,0,GR3
627 ST GR0,0,GR1
628 LAD GR1,1,GR1
629 LAD GR3,1,GR3
630 JUMP {cycle}
631{ret} LD GR0,GR1
632 POP GR4
633 POP GR3
634 POP GR2
635 POP GR1
636 SUBL GR0,GR1
637 ST GR0,0,GR2
638 RET
639"#,
640 comment = format_args!("{:?}", id),
641 prog = id.label(),
642 cycle = gen.jump_label(),
643 ret = gen.jump_label()
644 ))
645 .unwrap(),
646 }
647}
648
649fn get_util_fill<T: Gen>(gen: &mut T, id: Id) -> Src {
651 Src {
655 dependencies: Vec::new(),
656 statements: casl2::parse(&format!(
657 r#"
658 ; {comment}
659{prog} PUSH 0,GR1
660 PUSH 0,GR2
661 PUSH 0,GR3
662 ADDL GR3,GR1
663{next} CPL GR1,GR3
664 JZE {ret}
665 ST GR2,0,GR1
666 LAD GR1,1,GR1
667 JUMP {next}
668{ret} POP GR3
669 POP GR2
670 POP GR1
671 RET
672"#,
673 comment = format_args!("{:?}", id),
674 prog = id.label(),
675 next = gen.jump_label(),
676 ret = gen.jump_label()
677 ))
678 .unwrap(),
679 }
680}
681
682fn get_func_space<T: Gen>(_gen: &mut T, id: Id) -> Src {
684 Src {
688 dependencies: vec![Id::UtilFill, Id::UtilSafeIndex],
689 statements: casl2::parse(&format!(
690 r#"
691 ; {comment}
692{prog} PUSH 0,GR1
693 PUSH 0,GR2
694 PUSH 0,GR3
695 XOR GR1,GR3
696 XOR GR3,GR1
697 XOR GR1,GR3
698 LAD GR2,257
699 CALL {fit}
700 LD GR1,GR3
701 LD GR3,GR0
702 LD GR2,=' '
703 CALL {fill}
704 LD GR0,GR3
705 POP GR3
706 POP GR2
707 POP GR1
708 ST GR0,0,GR2
709 RET
710"#,
711 comment = format_args!("{:?}", id),
712 prog = id.label(),
713 fit = Id::UtilSafeIndex.label(),
714 fill = Id::UtilFill.label()
715 ))
716 .unwrap(),
717 }
718}
719
720fn get_util_copy_to_offset_str<T: Gen>(gen: &mut T, id: Id) -> Src {
722 Src {
730 dependencies: vec![Id::UtilSafeIndex],
731 statements: casl2::parse(&format!(
732 r#"
733 ; {comment}
734{prog} PUSH 0,GR1
735 PUSH 0,GR2
736 PUSH 0,GR3
737 PUSH 0,GR4
738 PUSH 0,GR5
739 PUSH 0,GR6
740 CALL {fit}
741 LD GR1,GR6
742 LD GR6,GR0
743 CPL GR1,GR2
744 JMI {x}
745 LD GR1,GR2
746{x} ADDL GR1,GR6
747 LD GR0,GR1
748 CPL GR0,GR2
749 JMI {y}
750 LD GR0,GR2
751{y} SUBL GR0,GR6
752 CPL GR0,GR4
753 JMI {z}
754 LD GR0,GR4
755{z} ADDL GR5,GR6
756 LD GR6,GR5
757 ADDL GR5,GR0
758 ADDL GR3,GR0
759{next} CPL GR5,GR6
760 JZE {ret}
761 LAD GR3,-1,GR3
762 LAD GR5,-1,GR5
763 LD GR1,0,GR3
764 ST GR1,0,GR5
765 JUMP {next}
766{ret} POP GR6
767 POP GR5
768 POP GR4
769 POP GR3
770 POP GR2
771 POP GR1
772 RET
773"#,
774 comment = format_args!("{:?}", id),
775 prog = id.label(),
776 fit = Id::UtilSafeIndex.label(),
777 x = gen.jump_label(),
778 y = gen.jump_label(),
779 z = gen.jump_label(),
780 next = gen.jump_label(),
781 ret = gen.jump_label()
782 ))
783 .unwrap(),
784 }
785}
786
787fn get_util_copy_from_offset_str<T: Gen>(gen: &mut T, id: Id) -> Src {
789 Src {
797 dependencies: vec![Id::UtilSafeIndex],
798 statements: casl2::parse(&format!(
799 r#"
800 ; {comment}
801{prog} PUSH 0,GR1
802 PUSH 0,GR2
803 PUSH 0,GR3
804 PUSH 0,GR4
805 PUSH 0,GR5
806 PUSH 0,GR6
807 CALL {fit}
808 LD GR1,GR6
809 LD GR6,GR0
810 CPL GR1,GR2
811 JMI {x}
812 LD GR1,GR2
813{x} ADDL GR1,GR6
814 LD GR0,GR1
815 CPL GR0,GR2
816 JMI {y}
817 LD GR0,GR2
818{y} SUBL GR0,GR6
819 CPL GR0,GR4
820 JMI {z}
821 LD GR0,GR4
822{z} ADDL GR3,GR6
823 LD GR6,GR5
824 ADDL GR6,GR0
825{next} CPL GR5,GR6
826 JZE {ret}
827 LD GR1,0,GR3
828 ST GR1,0,GR5
829 LAD GR3,1,GR3
830 LAD GR5,1,GR5
831 JUMP {next}
832{ret} POP GR6
833 POP GR5
834 POP GR4
835 POP GR3
836 POP GR2
837 POP GR1
838 RET
839"#,
840 comment = format_args!("{:?}", id),
841 prog = id.label(),
842 fit = Id::UtilSafeIndex.label(),
843 x = gen.jump_label(),
844 y = gen.jump_label(),
845 z = gen.jump_label(),
846 next = gen.jump_label(),
847 ret = gen.jump_label()
848 ))
849 .unwrap(),
850 }
851}
852
853fn get_util_load_element<T: Gen>(gen: &mut T, id: Id) -> Src {
855 Src {
860 dependencies: vec![Id::UtilSafeIndex],
861 statements: casl2::parse(&format!(
862 r#"
863 ; {comment}
864{prog} AND GR2,GR2
865 JNZ {ok}
866 XOR GR0,GR0
867 RET
868{ok} CALL {fit}
869 PUSH 0,GR3
870 ADDL GR3,GR0
871 LD GR0,0,GR3
872 POP GR3
873 RET
874"#,
875 comment = format_args!("{:?}", id),
876 prog = id.label(),
877 fit = Id::UtilSafeIndex.label(),
878 ok = gen.jump_label()
879 ))
880 .unwrap(),
881 }
882}