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