add: performance values for Lattice MachXO2
[zpu.git] / zpu / sw / startup / nextgen_crt0.S
blob3cf9112ef406ece3443e96c008c891d68a44773e
1 /* Startup code for ZPU
2    Copyright (C) 2005 Free Software Foundation, Inc.
4 This file is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 2, or (at your option) any
7 later version.
9 In addition to the permissions in the GNU General Public License, the
10 Free Software Foundation gives you unlimited permission to link the
11 compiled version of this file with other programs, and to distribute
12 those programs without any restriction coming from the use of this
13 file.  (The General Public License restrictions do apply in other
14 respects; for example, they cover modification of the file, and
15 distribution when not linked into another program.)
17 This file is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; see the file COPYING.  If not, write to
24 the Free Software Foundation, 59 Temple Place - Suite 330,
25 Boston, MA 02111-1307, USA.  */
26         .file   "crt0.S"
27         
28         .section ".fixed_vectors","ax"
32         
33         .macro fast_neg
34         not
35         im 1
36         add
37         .endm
38         
39         .macro cimpl funcname
40         ; save R0
41         im 0
42         load
43         
44         ; save R1
45         im 4
46         load
47         
48         ; save R2
49         im 8
50         load
51         
52         loadsp 20
53         loadsp 20
54         
55         fixedim \funcname
56         call
58         ; destroy arguments on stack
59         storesp 0
60         storesp 0       
61          
62         im 0
63         load
64         
65         ; poke the result into the right slot
66         storesp 24
68         ; restore R2
69         im 8
70         store
71         
72         ; restore R1
73         im 4
74         store
75         
76         ; restore r0
77         im 0
78         store
79         
80         storesp 4
81         poppc
82         .endm
87 /* vectors */
88         .balign 32,0
89 # offset 0x0000 0000
90                 .globl _start
91 _start:
92                 im _premain
93                 poppc
95         .balign 16,0
96 # offset 0x0000 0010
97                 .globl _zpu_unknown_instruction_vector
98 _zpu_unknown_instruction:
99                 /* We have unsupported instruction * 4 on stack */
100                 im _emulate_table
101                 add
102                 load
103                 poppc
105         .rodata
106         .balign 4,0
107 _emulate_table:
108         .long   _storeh
109         .long ...
111 /* instruction emulation code */
113 # opcode 34
114 # offset 0x0000 0040
115         .balign 32,0
116 _loadh:
117         loadsp 4
118         ; by not masking out bit 0, we cause a memory access error 
119         ; on unaligned access
120         im ~0x2
121         and
122         load
124         ; mult 8        
125         loadsp 8
126         im 3
127         and
128         fast_neg
129         im 2
130         add
131         im 3
132         ashiftleft
133         ; shift right addr&3 * 8
134         lshiftright
135         im 0xffff
136         and
137         storesp 8
138         
139         poppc
141 # opcode 35
142 # offset 0x0000 0060
143         .balign 32,0
144 _storeh:
145         loadsp 4
146         ; by not masking out bit 0, we cause a memory access error 
147         ; on unaligned access
148         im ~0x2
149         and
150         load
152         ; mask
153         im 0xffff
154         loadsp 12
155         im 3
156         and
157         fast_neg
158         im 2
159         add
160         im 3
161         ashiftleft
162         ashiftleft
163         not
165         and
167         loadsp 12
168         im 0xffff
170         nop
171                 
172         fixedim _storehtail
173         poppc
176 # opcode 36
177 # offset 0x0000 0080
178         .balign 32,0
179 _lessthan:
180         loadsp 8
181         fast_neg
182         loadsp 8
183         add
185         ; DANGER!!!!
186         ; 0x80000000 will overflow when negated, so we need to mask
187         ; the result above with the compare positive to negative
188         ; number case
189         loadsp 12
190         loadsp 12
191         not
192         and
193         not
194         and
197         ; handle case where we are comparing a negative number
198         ; and positve number. This can underflow. E.g. consider 0x8000000 < 0x1000
199         loadsp 12
200         not
201         loadsp 12
202         and
203         
204         or
208         flip
209         im 1
210         and     
212         
213         storesp 12
214         storesp 4
215         poppc
216         
218 # opcode 37
219 # offset 0x0000 00a0
220         .balign 32,0
221 _lessthanorequal:
222         loadsp 8
223         loadsp 8
224         lessthan
225         loadsp 12
226         loadsp 12
227         eq
228         or
229         
230         storesp 12
231         storesp 4
232         poppc
234         
235 # opcode 38
236 # offset 0x0000 00c0
237         .balign 32,0
238 _ulessthan:
239         ; fish up arguments 
240         loadsp 4
241         loadsp 12
242         
243         /* low: -1 if low bit dif is negative 0 otherwise:  neg (not x&1 and (y&1))
244                 x&1             y&1             neg (not x&1 and (y&1))
245                 1               1               0
246                 1               0               0
247                 0               1               -1
248                 0               0               0
249         
250         */
251         loadsp 4 
252         not
253         loadsp 4
254         and
255         im 1
256         and
257         neg
258         
259         
260         /* high: upper 31-bit diff is only wrong when diff is 0 and low=-1
261                 high=x>>1 - y>>1 + low
262                 
263                 extremes
264                 
265                 0000 - 1111:
266                 low= neg(not 0 and 1) = 1111 (-1)
267                 high=000+ neg(111) +low = 000 + 1001 + low = 1000 
268                 OK
269                 
270                 1111 - 0000
271                 low=neg(not 1 and 0) = 0
272                 high=111+neg(000) + low = 0111
273                 OK
274                  
275                 
276          */
277         loadsp 8
278         
279         flip 
280         addsp 0
281         flip
282         
283         loadsp 8
284         
285         flip    
286         addsp 0
287         flip
289         sub
291         ; if they are equal, then the last bit decides...       
292         add
293         
294         /* test if negative: result = flip(diff) & 1 */
295         flip
296         im 1
297         and
299         ; destroy a&b which are on stack        
300         storesp 4
301         storesp 4
302         
303         storesp 12
304         storesp 4
305         poppc                   
307 # opcode 39
308 # offset 0x0000 00e0
309         .balign 32,0
310 _ulessthanorequal:
311         loadsp 8
312         loadsp 8
313         ulessthan
314         loadsp 12
315         loadsp 12
316         eq
317         or
318         
319         storesp 12
320         storesp 4
321         poppc
324 # opcode 40
325 # offset 0x0000 0100
326         .balign 32,0
327         .globl _swap
328 _swap:
329         breakpoint ; tbd
331 # opcode 41
332 # offset 0x0000 0120
333         .balign 32,0
334 _slowmult:
335         im _slowmultImpl
336         poppc
338 # opcode 42
339 # offset 0x0000 0140
340         .balign 32,0
341 _lshiftright:
342         loadsp 8
343         flip
345         loadsp 8
346         ashiftleft
347         flip
348         
349         storesp 12
350         storesp 4
352         poppc
353         
355 # opcode 43
356 # offset 0x0000 0160
357         .balign 32,0
358 _ashiftleft:
359         loadsp 8
360         
361         loadsp 8
362         im 0x1f
363         and
364         fast_neg
365         im _ashiftleftEnd
366         add
367         poppc
368         
369         
370         
371 # opcode 44
372 # offset 0x0000 0180
373         .balign 32,0
374 _ashiftright:
375         loadsp 8
376         loadsp 8
377         lshiftright
378         
379         ; handle signed value
380         im -1
381         loadsp 12
382         im 0x1f
383         and
384         lshiftright
385         not     ; now we have an integer on the stack with the signed 
386                 ; bits in the right position
388         ; mask these bits with the signed bit.
389         loadsp 16
390         not
391         flip
392         im 1
393         and
394         im -1
395         add
396         
397         and     
398         
399         ; stuff in the signed bits...
400         or
401         
402         ; store result into correct stack slot  
403         storesp 12
404         
405         ; move up return value 
406         storesp 4
407         poppc
409 # opcode 45
410 # offset 0x0000 01a0
411         .balign 32,0
412 _call:
413         ; fn
414         loadsp 4
415         
416         ; return address
417         loadsp 4
419         ; store return address
420         storesp 12
421         
422         ; fn to call
423         storesp 4
424         
425         pushsp  ; flush internal stack
426         popsp
427                 
428         poppc
430 _storehtail:
432         and
433         loadsp 12
434         im 3
435         and
436         fast_neg
437         im 2
438         add
439         im 3
440         ashiftleft
441         nop
442         ashiftleft
443         
444         or
445         
446         loadsp 8
447         im  ~0x3
448         and
450         store
451         
452         storesp 4
453         storesp 4
454         poppc
457 # opcode 46
458 # offset 0x0000 01c0
459         .balign 32,0
460 _eq:
461         loadsp 8
462         fast_neg
463         loadsp 8
464         add
465         
466         not 
467         loadsp 0
468         im 1
469         add
470         not
471         and
472         flip
473         im 1
474         and
475         
476         storesp 12
477         storesp 4
478         poppc
480 # opcode 47
481 # offset 0x0000 01e0
482         .balign 32,0
483 _neq:
484         loadsp 8
485         fast_neg
486         loadsp 8
487         add
488         
489         not 
490         loadsp 0
491         im 1
492         add
493         not
494         and
495         flip
497         not
499         im 1
500         and
501                 
502         storesp 12
503         storesp 4
504         poppc
505         
507 # opcode 48
508 # offset 0x0000 0200
509         .balign 32,0
510 _neg:
511         loadsp 4
512         not
513         im 1
514         add
515         storesp 8
516         
517         poppc
518         
520 # opcode 49
521 # offset 0x0000 0220
522         .balign 32,0
523 _sub:
524         loadsp 8
525         loadsp 8
526         fast_neg
527         add
528         storesp 12
530         storesp 4
532         poppc
535 # opcode 50
536 # offset 0x0000 0240
537         .balign 32,0
538 _xor:
539         loadsp 8
540         not
541         loadsp 8
542         and
543         
544         loadsp 12
545         loadsp 12
546         not
547         and
549         or
551         storesp 12
552         storesp 4
553         poppc
555 # opcode 51
556 # offset 0x0000 0260
557         .balign 32,0
558 _loadb:
559         loadsp 4
560         im ~0x3
561         and
562         load
564         loadsp 8
565         im 3
566         and
567         fast_neg
568         im 3
569         add
570         ; x8
571         addsp 0
572         addsp 0
573         addsp 0
575         lshiftright
577         im 0xff
578         and
579         storesp 8
580         
581         poppc
584 # opcode 52
585 # offset 0x0000 0280
586         .balign 32,0
587 _storeb:
588         loadsp 4
589         im ~0x3
590         and
591         load
593         ; mask away destination
594         im _mask
595         loadsp 12
596         im 3
597         and
598         addsp 0
599         addsp 0
600         add
601         load
603         and
606         im _storebtail
607         poppc
608         
609 # opcode 53
610 # offset 0x0000 02a0
611         .balign 32,0
612 _div:
613         cimpl __divsi3
614         
615 # opcode 54
616 # offset 0x0000 02c0
617         .balign 32,0
618 _mod:
619         cimpl __modsi3
621 # opcode 55
622 # offset 0x0000 02e0
623         .balign 32,0
624         .globl _eqbranch
625 _eqbranch:
626         loadsp 8
627         
628         ; eq
630         not 
631         loadsp 0
632         im 1
633         add
634         not
635         and
636         flip
637         im 1
638         and
640         ; mask
641         im -1
642         add
643         loadsp 0
644         storesp 16
646         ; no branch address
647         loadsp 4
648         
649         and
651         ; fetch boolean & neg mask
652         loadsp 12
653         not
654         
655         ; calc address & mask for branch
656         loadsp 8
657         loadsp 16
658         add
659         ; subtract 1 to find PC of branch instruction
660         im -1
661         add
662         
663         and
665         or      
666         
667         storesp 4
668         storesp 4
669         storesp 4
670         poppc   
673 # opcode 56
674 # offset 0x0000 0300
675         .balign 32,0
676         .globl _neqbranch
677 _neqbranch:
678         loadsp 8
679         
680         ; neq
682         not 
683         loadsp 0
684         im 1
685         add
686         not
687         and
688         flip
689         
690         not
691         
692         im 1
693         and
695         ; mask
696         im -1
697         add
698         loadsp 0
699         storesp 16
701         ; no branch address
702         loadsp 4
703         
704         and
706         ; fetch boolean & neg mask
707         loadsp 12
708         not
709         
710         ; calc address & mask for branch
711         loadsp 8
712         loadsp 16
713         add
714         ; find address of branch instruction
715         im -1
716         add
717         
718         and
720         or      
721         
722         storesp 4
723         storesp 4
724         storesp 4
725         poppc   
727 # opcode 57
728 # offset 0x0000 0320
729         .balign 32,0
730         .globl _poppcrel
731 _poppcrel:
732         add
733         ; address of poppcrel
734         im -1
735         add
736         poppc
737                 
738 # opcode 58
739 # offset 0x0000 0340
740         .balign 32,0
741         .globl _config
742 _config:
743         im 1 
744         nop
745         im _hardware
746         store
747         storesp 4
748         poppc
750 # opcode 59
751 # offset 0x0000 0360
752         .balign 32,0
753 _pushpc:
754         loadsp 4
755         im 1
756         add 
757         storesp 8
758         poppc
759         
760 # opcode 60
761 # offset 0x0000 0380
762         .balign 32,0
763 _syscall_emulate:
764         .byte 0
765         
766 # opcode 61
767 # offset 0x0000 03a0
768         .balign 32,0
769 _pushspadd:
770         pushsp
771         im 4
772         add
773         loadsp 8
774         addsp 0
775         addsp 0
776         add
777         storesp 8
778         
779         poppc
781 # opcode 62
782 # offset 0x0000 03c0
783         .balign 32,0
784 _halfmult:
785         breakpoint
786         
787 # opcode 63
788 # offset 0x0000 03e0
789         .balign 32,0
790 _callpcrel:
791         loadsp 4
792         loadsp 4
793         add
794         im -1
795         add
796         loadsp 4
797         
798         storesp 12      ; return address
799         storesp 4 
800         pushsp          ; this will flush the internal stack.
801         popsp
802         poppc
804         .text
806         
809 _ashiftleftBegin:
810         .rept 0x1f
811         addsp 0
812         .endr
813 _ashiftleftEnd:
814         storesp 12
815         storesp 4
816         poppc
817         
818 _storebtail:
819         loadsp 12
820         im 0xff
821         and
822         loadsp 12
823         im 3
824         and
826         fast_neg
827         im 3
828         add
829         ; x8
830         addsp 0
831         addsp 0
832         addsp 0
834         ashiftleft
835          
836         or
837         
838         loadsp 8
839         im  ~0x3
840         and
842         store
843         
844         storesp 4
845         storesp 4
846         poppc
847         
851 ; NB! this is not an EMULATE instruction. It is a varargs fn.
852         .globl _syscall 
853 _syscall:
854         syscall
855         poppc
856         
857 _slowmultImpl:
858         
859         loadsp 8 ; A
860         loadsp 8 ; B
861         im 0 ; C
863 .LmoreMult:
864         mult1bit
865         
866         ; cutoff
867         loadsp 8
868         .byte (.LmoreMult-.Lbranch)&0x7f+0x80
869 .Lbranch:
870         neqbranch
872         storesp 4
873         storesp 4
874         storesp 12
875         storesp 4
876         poppc
877         
878         .data
879         .balign 4,0
880 _mask:
881         .long 0x00ffffff
882         .long 0xff00ffff
883         .long 0xffff00ff
884         .long 0xffffff00
886         
887         .globl _hardware
888 _hardware:
889         .long 0
890         .globl _cpu_config
891 _cpu_config:
892         .long 0
894 ; Pointers to emulated instructions