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