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