6f1cb91eaf728f195ab969c5d68cec3cb8b68e4f
[calu.git] / progs / deepjit.s
1 #define PROGINSTR stw r0, PDATA(r13)
2 #include "dt_inc.s"
3 .data
4 .org 0x10
5 inputdata:
6 ;8 * 8 4
7 .fill 1, 0x382A3834
8 ;1 X * 8
9 .fill 1, 0x31582A38
10 ;+ D X -
11 .fill 1, 0x2B44582D
12 ;P \xF8 J D
13 .fill 1, 0x50F84A44
14 ;+ * 8 6
15 .fill 1, 0x2B2A3836
16 ;\000 \020 I D
17 .fill 1, 0x00204944
18 ;~ < \000 \000
19 .fill 1, 0x7E3C0000
20 ;8 P \005 J
21 .fill 1, 0x3850054A
22 ;* 8
23 .fill 1, 0x2A38
24
25 stack:
26 .fill 256, 0
27
28 ;needed for jumps
29 ;assuming that no more than 42 instr are used
30 instrtable:
31 .fill 42, 0
32
33 prog_eof:
34 .ifill pop r0
35 .ifill ret+
36
37 prog_mul:
38 .ifill pop r6
39 .ifill pop r7
40 .ifill ldis r8, 0;0xed400004
41 .ifill mov r0, r7;0xe1038000
42 .ifill andx r0, 1;0xe2800008
43 .ifill adddnz r8, r8, r6;0x00443001
44 .ifill subinz r7, r7, 1;0x01bb8008
45 .ifill addizs r7, r7, 0;0x113b8000
46 ;loop:
47 .ifill adddnz r8, r8, r6;0x00443001
48 .ifill adddnz r8, r8, r6;0x00443001
49 .ifill subi r7, r7, 2;0xe1bb8010
50 .fill 0x0b7ffe83;brnz+ loop
51 .ifill push r8
52
53 prog_consts:
54 .fill 0xed300004;ldis r6, CONST
55 .ifill push r6
56
57 prog_add:
58 .ifill pop r6
59 .ifill pop r7
60 .ifill add r7, r7, r6;0xe03bb000
61 .ifill push r7
62
63 prog_sub:
64 .ifill pop r6
65 .ifill pop r7
66 .ifill sub r7, r7, r6;0xe0bbb000
67 .ifill push r7
68
69 prog_lessthan:
70 .ifill pop r6
71 .ifill pop r7
72 .ifill cmp r7, r6;0xec3b0000
73 .ifill pushlt r14
74 .ifill pushge r15
75
76 prog_dup:
77 .ifill fetch r6
78 .ifill push r6
79
80 prog_jmp:
81 .ifill pop r6
82 .ifill cmpi r6,0;0xecb00000
83 ;static calced
84 .fill 1, 0x1b000103;breq- vm_next
85 .fill 1, 0xeb000003;br+ CONST
86
87 prog_imm:
88 .fill 1, 0xed400000;ldil r6, CONST
89 .fill 1, 0xed400002;ldih r6, CONST
90 .ifill push r6
91
92 prog_pop:
93 .ifill disc
94
95 prog_xch:
96 .ifill pop r6
97 .ifill pop r7
98 .ifill push r6
99 .ifill push r7
100
101 prog_not:
102 .ifill pop r6
103 .ifill not r6;0xe4b7fffa
104 .ifill push r6
105
106 .text
107 .org 0
108 start:
109         call+ main
110         call+ main
111         ret
112
113
114 main:
115
116         call+ u_init
117         call+ u_recv_byte
118
119         ;set address of input
120         ldis r1, inputdata@lo
121         ldih r1, inputdata@hi
122
123         ;set address of program start
124         ldis r2, (prog_start/4)@lo
125         ldih r2, (prog_start/4)@hi
126
127         ;set address to instruction table
128         ldis r3, instrtable@lo
129         ldih r3, instrtable@hi
130
131         ;set address to defer table
132         ldis r9, defertable@lo
133         ldih r9, defertable@hi
134
135         ldis r13, PBASE@lo
136         ldih r13, PBASE@hi
137
138         ;set programmer address
139         stw r2, PADDR(r13)
140
141         ;call jit compiler
142         call+ jit
143
144         ;set address to stack
145         ;ldil r3, stack@lo
146         ;ldih r3, stack@hi
147
148         ;make r15 a 0-register
149         ldis r15, 0
150         ;make r14 a 8-bit -1-register
151         ldis r14, 0xFF
152
153         ;call jit'ed prog
154         call+ prog_start
155
156         ;send result
157         call+ u_init
158         mov r1, r0
159         call u_send_byte
160
161         br+ main
162
163 ;first version only supports backward jumps
164 jit:
165         ;r1 ... address to input, every byte is a new input
166         ;       includes pc implicitly
167         ;r2 ... address to program start
168         ;r3 ... address of instruction table
169         ;r4 ... gets loaded with instr. prog. addr.
170         ;r5 ... input
171         ;r9 ... address to actual entry in defer table
172         ;r10... address to defer table
173         ;r13 .. programmer address
174
175         ;load address of program
176         ldil r14, prog_mul@lo
177         ldih r14, prog_mul@hi
178
179         ldil r15, prog_consts@lo
180         ldih r15, prog_consts@hi
181
182         ;backup defer table address
183         mov r10, r9
184         ;decrement address to input by 1
185         subi r1, r1, 1
186
187 vm_default:     
188 vm_loop:
189         ;increment input address
190         addi r1, r1, 1
191
192         ;store address of next instruction in table
193         stw r2, 0(r3)
194         ;increment instr. table
195         addi r3, r3, 4
196
197         ;load input
198         ldb r5, 0(r1)
199         ;we need to multiply input by 4 to get correct address offset
200         lls r0, r5, 2
201         ;calc position in jumptable
202         ldw r0, jumptable(r0)
203         ;jump to instr
204         brr r0
205
206 vm_eof:
207         ;load address of program
208         ldil r4, prog_eof@lo
209         ldih r4, prog_eof@hi
210         ;program instruction (2)
211         ldw r0, 0(r4)
212         stw r0, PDATA(r13)
213         ldw r0, 4(r4)
214         stw r0, PDATA(r13)
215
216         ;end of program
217         ;now it is time to clear up the defer table
218
219         ldil r7, prog_jmp@lo
220         ldih r7, prog_jmp@hi
221         ;load branch template
222         ldw r7, 12(r7)
223
224         ;if actual and base are equal, no entry
225         cmp r9, r10
226         ;return
227         reteq-
228
229 vm_defer:
230         ;load pointer to where to jump to
231         ldw r6, 0(r10)
232         ;load where to jump to
233         ldw r6, 0(r6)
234         ;load where to save from defer table
235         stw r8, 4(r10)
236
237         ;generate branch
238         sub r11, r6, r8
239         ;lrs r11, r11, 2
240         ;set the upper 16 bit 0
241         andx r11, 0xFFFF
242         ;shift to the position of imm in br
243         lls r11, r11, 7
244         or r6, r7, r11
245         
246         stw r8, PADDR(r13)      
247         stw r6, PDATA(r13)
248
249         addi r10, r10, 8
250         cmp r10, r9
251         reteq+
252         brnq- vm_defer
253
254 ;case *
255 ;42
256 vm_mul:
257         ;program instruction (14)
258         ldw r0, 0(r14)
259         PROGINSTR
260         ldw r0, 4(r14)
261         PROGINSTR
262         ldw r0, 8(r14)
263         PROGINSTR
264         ldw r0, 12(r14)
265         PROGINSTR
266         ldw r0, 16(r14)
267         PROGINSTR
268         ldw r0, 20(r14)
269         PROGINSTR
270         ldw r0, 24(r14)
271         PROGINSTR
272         ldw r0, 28(r14)
273         PROGINSTR
274         ldw r0, 32(r14)
275         PROGINSTR
276         ldw r0, 36(r14)
277         PROGINSTR
278         ldw r0, 40(r14)
279         PROGINSTR
280         ldw r0, 44(r14)
281         PROGINSTR
282         ldw r0, 48(r14)
283         PROGINSTR
284
285         ;increment address
286         addi r2, r2, 13
287
288         br+ vm_loop
289
290 ;case +
291 ;43
292 vm_add:
293         ;load address of program
294         ldil r4, prog_add@lo
295         ldih r4, prog_add@hi
296
297         ;program instruction (5)
298         ldw r0, 0(r4)
299         PROGINSTR
300         ldw r0, 4(r4)
301         PROGINSTR
302         ldw r0, 8(r4)
303         PROGINSTR
304         ldw r0, 12(r4)
305         PROGINSTR
306
307         ;increment address
308         addi r2, r2, 4
309
310         br+ vm_loop
311
312 ;case -
313 ;45
314 vm_sub:
315         ;load address of program
316         ldil r4, prog_sub@lo
317         ldih r4, prog_sub@hi
318
319         ;program instruction (5)
320         ldw r0, 0(r4)
321         PROGINSTR
322         ldw r0, 4(r4)
323         PROGINSTR
324         ldw r0, 8(r4)
325         PROGINSTR
326         ldw r0, 12(r4)
327         PROGINSTR
328
329         ;increment address
330         addi r2, r2, 4
331
332         br+ vm_loop
333
334 ;case 0 1 2 3 4 5 6 7 8 9
335 ;48-57
336 vm_consts:
337         ;program instruction (3)
338         ldw r0, 0(r15)
339         ;the first instr. loads r6 with the number
340         ;thus we shall emulate this
341
342         ;call number
343         subi r6, r5, 48
344         ;shift 3 bits left, as the immediate in ldi has
345         ;an offset of 3
346         lls r6, r6, 3
347         ;now 'add' this to the ldi
348         or r0, r0, r6
349
350         ;store this 'dynamic' instruction
351         PROGINSTR
352         ldw r0, 4(r15)
353         PROGINSTR
354
355         ;increment address
356         addi r2, r2, 2
357
358         br+ vm_loop
359
360 ;case <
361 ;60
362 vm_lessthan:
363         ;load address of program
364         ldil r4, prog_lessthan@lo
365         ldih r4, prog_lessthan@hi
366
367         ;program instruction (6)
368         ldw r0, 0(r4)
369         PROGINSTR
370         ldw r0, 4(r4)
371         PROGINSTR
372         ldw r0, 8(r4)
373         PROGINSTR
374         ldw r0, 12(r4)
375         PROGINSTR
376         ldw r0, 16(r4)
377         PROGINSTR
378
379         ;increment address
380         addi r2, r2, 5
381
382         br+ vm_loop
383
384 ;case D
385 ;68
386 vm_dup:
387         ldil r4, prog_dup@lo
388         ldih r4, prog_dup@hi
389
390         ;program instruction (3)
391         ldw r0, 0(r4)
392         PROGINSTR
393         ldw r0, 4(r4)
394         PROGINSTR
395
396         ;increment address
397         addi r2, r2, 2
398
399         br+ vm_loop
400
401 ;case I
402 ;73
403 vm_imm:
404         ;the following instructions calculate the immediate
405         ;load new high byte
406         ldb r6, 4(r1)
407         ;shift high byte
408         lls r6, r6, 8
409         ;load 2nd byte
410         ldb r7, 3(r1)
411         ;add to high byte
412         add r6, r6, r7
413         ;shift
414         lls r6, r6, 8
415         ;load
416         ldb r7, 2(r1)
417         ;add
418         add r6, r6, r7
419         ;shift
420         lls r6, r6, 8
421         ;load
422         ldb r7, 1(r1)
423         ;add
424         add r6, r6, r7
425
426         ;now we will generate ldih/l which will store this
427         ;immediate into a register
428
429         ;load address of program
430         ldil r4, prog_imm@lo
431         ldih r4, prog_imm@hi
432
433         ;save r6 to r7
434         mov r7, r6
435
436         ;generate 1st instr
437         ldw r0, 0(r4)
438         andx r6, 0xFFFF
439         lls r6, r6, 3
440         or r0, r0, r6
441         PROGINSTR
442
443         ;generate 2nd instr
444         ldw r0, 4(r4)
445         andxh r7, 0xFFFF
446         lrs r7, r7, 13
447         or r0, r0, r7
448         PROGINSTR
449
450         ;now we program the instructions that will save the
451         ;immediate onto the stack and increment the later
452
453         ldw r0, 8(r4)
454         PROGINSTR
455
456         ;increment address
457         addi r2, r2, 3
458
459         ;pc+4
460         addi r1, r1, 4
461         br+ vm_loop
462
463 ;case J
464 ;74
465 vm_jmp:
466         ;gfreit mi net ...
467         ;gespeicherte instrs sollten input indepentent sein
468         ;jumptable verwenden
469         ;fuer forward jumps muss deferrer table gemacht werden *puke*
470
471         ;load address of program
472         ldil r4, prog_jmp@lo
473         ldih r4, prog_jmp@hi
474
475         ;program instruction (2)
476         ;pop r6
477         ldw r0, 0(r4)
478         PROGINSTR
479
480         ;compare to 0
481         ;cmpi r6,0
482         ldw r0, 4(r4)
483         PROGINSTR
484
485         ;breq+ vm_next
486         ;is statically known
487         ldw r0, 8(r4)
488         PROGINSTR
489
490         ;we add the offset to this instruction
491         addi r8, r2, 3
492
493
494         ;we know calculate the jump destination
495         ;set r6 to 0 (to clear upper bytes)
496         ldis r6, 0
497         ;load pc+1 input
498         ldb r6, 1(r1)
499         ;compare input with neg. max of 8 bit
500         cmpi r6, 0x80
501         brlt- vm_possign
502
503
504
505         ;generate negativ offset
506         ldis r7, 0xFF00
507         ;r6 is now the 'real' negativ number
508         or r6, r6, r7
509         ;todo: testing showed (at least once) we are off by 2 instr.
510         ;addi r6, r6, 2
511         ;multiply by to get the offset
512         lls r6, r6, 2
513         ;generate address in table
514         add r6, r3, r6
515         ;r0 now has the target address
516         ;todo: 0-4?
517         ldw r0, 0(r6)
518         ;we calc the offset
519         sub r8, r0, r8
520         ;we shift 2 bits out, because rel. br takes instr.
521         ;count and not address amount ...
522         ;lrs r8, r8, 2
523         ;set the upper 16 bit 0
524         andx r8, 0xFFFF
525         ;shift to the position of imm in br
526         lls r8, r8, 7
527         ;load template br
528         ldw r0, 12(r4)
529         or r0, r0, r8
530         PROGINSTR
531
532         ;increment address
533         addi r2, r2, 4
534
535         br+ vm_loop
536
537
538 vm_possign:
539         ;we know save the address in the instrtable where the addr to jump to stands
540         ;the value doesn't exists at the moment, but it will at evaluation
541
542         ;save position to save the instr into defer table
543         stw r8, 4(r9)
544
545         ;we need one instruction to have the correct offset (?)
546         PROGINSTR
547
548         ;todo: check if -1 is needed
549         ;subi r6, r6, 1
550         ;multiply with 2 to get offset right
551         lls r6, r6, 2
552         ;add to current base
553         add r6, r3, r6
554         ;save the address to defer table
555         stw r6, 0(r9)
556         ;increment defer table address
557         addi r9, r9, 8
558         ;increment address
559         addi r2, r2, 4
560         br+ vm_loop
561
562 ;case P
563 ;80
564 vm_pop:
565         ;load address of program
566         ldil r4, prog_pop@lo
567         ldih r4, prog_pop@hi
568
569         ;program instruction (1)
570         ldw r0, 0(r4)
571         PROGINSTR
572
573         ;increment address
574         addi r2, r2, 1
575
576         br+ vm_loop
577
578 ;case X
579 ;88
580 vm_xch:
581         ;load address of program
582         ldil r4, prog_xch@lo
583         ldih r4, prog_xch@hi
584
585         ;program instruction (4)
586         ldw r0, 0(r4)
587         PROGINSTR
588         ldw r0, 4(r4)
589         PROGINSTR
590         ldw r0, 8(r4)
591         PROGINSTR
592         ldw r0, 12(r4)
593         PROGINSTR
594
595         ;increment address
596         addi r2, r2, 4
597
598         br+ vm_loop
599
600 ;case ~
601 ;126
602 vm_not:
603         ;load address of program
604         ldil r4, prog_not@lo
605         ldih r4, prog_not@hi
606
607         ;program instruction (3)
608         ldw r0, 0(r4)
609         PROGINSTR
610         ldw r0, 4(r4)
611         PROGINSTR
612         ldw r0, 8(r4)
613         PROGINSTR
614
615         ;increment address
616         addi r2, r2, 3
617
618         br+ vm_loop
619
620
621 .data
622 jumptable:
623 ;0
624 .fill 1, vm_eof/4
625 .fill 41, vm_default/4
626 ;42
627 .fill 1, vm_mul/4
628 ;43
629 .fill 1, vm_add/4
630 ;44
631 .fill 1, vm_default/4
632 ;45
633 .fill 1, vm_sub/4
634 ;46-47
635 .fill 2, vm_default/4
636 ;48-57
637 .fill 10, vm_consts/4
638 ;58-59
639 .fill 2, vm_default/4
640 ;60
641 .fill 1, vm_lessthan/4
642 ;61-67
643 .fill 7, vm_default/4
644 ;68
645 .fill 1, vm_dup/4
646 ;69-72
647 .fill 4, vm_default/4
648 ;73
649 .fill 1, vm_imm/4
650 ;74
651 .fill 1, vm_jmp/4
652 ;75-79
653 .fill 5, vm_default/4
654 ;80
655 .fill 1, vm_pop/4
656 ;81-87
657 .fill 7, vm_default/4
658 ;88
659 .fill 1, vm_xch/4
660 ;89-125
661 .fill 37, vm_default/4
662 ;126
663 .fill 1, vm_not/4
664 ;127-255
665 .fill 129, vm_default/4
666
667 ;we assume not more than 3 entries
668 defertable:
669 .fill 6, 0