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