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