Merge upstream
[zpugcc.git] / toolchain / gcc / libgloss / zpu / crt0.S
blob35b0a8d344beaf66198d9177fcf02a5a68f9b448
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         
29         
30         
31 ;       .section ".fixed_vectors","ax"
32 ; KLUDGE!!! we remove the executable bit to avoid relaxation 
33         .section ".fixed_vectors","a" 
35 ; DANGER!!!! 
36 ; we need to align these code sections to 32 bytes, which
37 ; means we must not use any assembler instructions that are relaxed
38 ; at linker time
39 ; DANGER!!!! 
41         .macro fixedim value
42                         im \value
43         .endm
45         .macro  jsr address
46                         im _memreg      ; save R0
47                         load
48                         im _memreg+4    ; save R1
49                         load
50                         im _memreg+8    ; save R2
51                         load
52                         fixedim \address
53                         call
54                         im _memreg+8
55                         store           ; restore R2
56                         im _memreg+4
57                         store           ; restore R1
58                         im _memreg
59                         store           ; restore R0
60         .endm
63         .macro  jmp address
64                         fixedim \address
65                         poppc
66         .endm
67                 
69         .macro fast_neg
70         not
71         im 1
72         add
73         .endm
74         
75         .macro cimpl funcname
76         ; save R0
77         im _memreg
78         load
79         
80         ; save R1
81         im _memreg+4
82         load
83         
84         ; save R2
85         im _memreg+8
86         load
87         
88         loadsp 20
89         loadsp 20
90         
91         fixedim \funcname
92         call
94         ; destroy arguments on stack
95         storesp 0
96         storesp 0       
97          
98         im _memreg
99         load
100         
101         ; poke the result into the right slot
102         storesp 24
104         ; restore R2
105         im _memreg+8
106         store
107         
108         ; restore R1
109         im _memreg+4
110         store
111         
112         ; restore r0
113         im _memreg
114         store
115         
116         
117         storesp 4
118         poppc
119         .endm
121         .macro mult1bit
122         ; create mask of lowest bit in A
123         loadsp 8 ; A
124         im 1
125         and
126         im -1
127         add
128         not
129         loadsp 8 ; B
130         and 
131         add ; accumulate in C
132         
133         ; shift B left 1 bit
134         loadsp 4 ; B
135         addsp 0
136         storesp 8 ; B
137         
138         ; shift A right 1 bit
139         loadsp 8 ; A
140         flip
141         addsp 0
142         flip
143         storesp 12 ; A
144         .endm
148 /* vectors */
149         .balign 32,0
150 # offset 0x0000 0000
151                 .globl _start
152 _start:
153                 ; intSp must be 0 when we jump to _premain
154                 
155                 im ZPU_ID
156                 loadsp 0
157                 im _cpu_config
158                 store
159                 config
160                 jmp _premain
164         .balign 32,0
165 # offset 0x0000 0020
166                 .globl _zpu_interrupt_vector
167 _zpu_interrupt_vector:
168                 jmp ___zpu_interrupt_vector
171         .balign 16,0
172 # offset 0x0000 0030
173                 .globl _memreg
174                 .weak _memreg
175 _memreg:
178 /* instruction emulation code */
180 # opcode 34
181 # offset 0x0000 0040
182         .balign 32,0
183 _loadh:
184         loadsp 4
185         ; by not masking out bit 0, we cause a memory access error 
186         ; on unaligned access
187         im ~0x2
188         and
189         load
191         ; mult 8        
192         loadsp 8
193         im 3
194         and
195         fast_neg
196         im 2
197         add
198         im 3
199         ashiftleft
200         ; shift right addr&3 * 8
201         lshiftright
202         im 0xffff
203         and
204         storesp 8
205         
206         poppc
208 # opcode 35
209 # offset 0x0000 0060
210         .balign 32,0
211 _storeh:
212         loadsp 4
213         ; by not masking out bit 0, we cause a memory access error 
214         ; on unaligned access
215         im ~0x2
216         and
217         load
219         ; mask
220         im 0xffff
221         loadsp 12
222         im 3
223         and
224         fast_neg
225         im 2
226         add
227         im 3
228         ashiftleft
229         ashiftleft
230         not
232         and
234         loadsp 12
235         im 0xffff
237         nop
238                 
239         fixedim _storehtail
240         poppc
243 # opcode 36
244 # offset 0x0000 0080
245         .balign 32,0
246 _lessthan:
247         loadsp 8
248         fast_neg
249         loadsp 8
250         add
252         ; DANGER!!!!
253         ; 0x80000000 will overflow when negated, so we need to mask
254         ; the result above with the compare positive to negative
255         ; number case
256         loadsp 12
257         loadsp 12
258         not
259         and
260         not
261         and
264         ; handle case where we are comparing a negative number
265         ; and positve number. This can underflow. E.g. consider 0x8000000 < 0x1000
266         loadsp 12
267         not
268         loadsp 12
269         and
270         
271         or
275         flip
276         im 1
277         and     
279         
280         storesp 12
281         storesp 4
282         poppc
283         
285 # opcode 37
286 # offset 0x0000 00a0
287         .balign 32,0
288 _lessthanorequal:
289         loadsp 8
290         loadsp 8
291         lessthan
292         loadsp 12
293         loadsp 12
294         eq
295         or
296         
297         storesp 12
298         storesp 4
299         poppc
301         
302 # opcode 38
303 # offset 0x0000 00c0
304         .balign 32,0
305 _ulessthan:
306         ; fish up arguments 
307         loadsp 4
308         loadsp 12
309         
310         /* low: -1 if low bit dif is negative 0 otherwise:  neg (not x&1 and (y&1))
311                 x&1             y&1             neg (not x&1 and (y&1))
312                 1               1               0
313                 1               0               0
314                 0               1               -1
315                 0               0               0
316         
317         */
318         loadsp 4 
319         not
320         loadsp 4
321         and
322         im 1
323         and
324         neg
325         
326         
327         /* high: upper 31-bit diff is only wrong when diff is 0 and low=-1
328                 high=x>>1 - y>>1 + low
329                 
330                 extremes
331                 
332                 0000 - 1111:
333                 low= neg(not 0 and 1) = 1111 (-1)
334                 high=000+ neg(111) +low = 000 + 1001 + low = 1000 
335                 OK
336                 
337                 1111 - 0000
338                 low=neg(not 1 and 0) = 0
339                 high=111+neg(000) + low = 0111
340                 OK
341                  
342                 
343          */
344         loadsp 8
345         
346         flip 
347         addsp 0
348         flip
349         
350         loadsp 8
351         
352         flip    
353         addsp 0
354         flip
356         sub
358         ; if they are equal, then the last bit decides...       
359         add
360         
361         /* test if negative: result = flip(diff) & 1 */
362         flip
363         im 1
364         and
366         ; destroy a&b which are on stack        
367         storesp 4
368         storesp 4
369         
370         storesp 12
371         storesp 4
372         poppc                   
374 # opcode 39
375 # offset 0x0000 00e0
376         .balign 32,0
377 _ulessthanorequal:
378         loadsp 8
379         loadsp 8
380         ulessthan
381         loadsp 12
382         loadsp 12
383         eq
384         or
385         
386         storesp 12
387         storesp 4
388         poppc
391 # opcode 40
392 # offset 0x0000 0100
393         .balign 32,0
394         .globl _swap
395 _swap:
396         breakpoint ; tbd
398 # opcode 41
399 # offset 0x0000 0120
400         .balign 32,0
401 _slowmult:
402         im _slowmultImpl
403         poppc
405 # opcode 42
406 # offset 0x0000 0140
407         .balign 32,0
408 _lshiftright:
409         loadsp 8
410         flip
412         loadsp 8
413         ashiftleft
414         flip
415         
416         storesp 12
417         storesp 4
419         poppc
420         
422 # opcode 43
423 # offset 0x0000 0160
424         .balign 32,0
425 _ashiftleft:
426         loadsp 8
427         
428         loadsp 8
429         im 0x1f
430         and
431         fast_neg
432         im _ashiftleftEnd
433         add
434         poppc
435         
436         
437         
438 # opcode 44
439 # offset 0x0000 0180
440         .balign 32,0
441 _ashiftright:
442         loadsp 8
443         loadsp 8
444         lshiftright
445         
446         ; handle signed value
447         im -1
448         loadsp 12
449         im 0x1f
450         and
451         lshiftright
452         not     ; now we have an integer on the stack with the signed 
453                 ; bits in the right position
455         ; mask these bits with the signed bit.
456         loadsp 16
457         not
458         flip
459         im 1
460         and
461         im -1
462         add
463         
464         and     
465         
466         ; stuff in the signed bits...
467         or
468         
469         ; store result into correct stack slot  
470         storesp 12
471         
472         ; move up return value 
473         storesp 4
474         poppc
476 # opcode 45
477 # offset 0x0000 01a0
478         .balign 32,0
479 _call:
480         ; fn
481         loadsp 4
482         
483         ; return address
484         loadsp 4
486         ; store return address
487         storesp 12
488         
489         ; fn to call
490         storesp 4
491         
492         pushsp  ; flush internal stack
493         popsp
494                 
495         poppc
497 _storehtail:
499         and
500         loadsp 12
501         im 3
502         and
503         fast_neg
504         im 2
505         add
506         im 3
507         ashiftleft
508         nop
509         ashiftleft
510         
511         or
512         
513         loadsp 8
514         im  ~0x3
515         and
517         store
518         
519         storesp 4
520         storesp 4
521         poppc
524 # opcode 46
525 # offset 0x0000 01c0
526         .balign 32,0
527 _eq:
528         loadsp 8
529         fast_neg
530         loadsp 8
531         add
532         
533         not 
534         loadsp 0
535         im 1
536         add
537         not
538         and
539         flip
540         im 1
541         and
542         
543         storesp 12
544         storesp 4
545         poppc
547 # opcode 47
548 # offset 0x0000 01e0
549         .balign 32,0
550 _neq:
551         loadsp 8
552         fast_neg
553         loadsp 8
554         add
555         
556         not 
557         loadsp 0
558         im 1
559         add
560         not
561         and
562         flip
564         not
566         im 1
567         and
568                 
569         storesp 12
570         storesp 4
571         poppc
572         
574 # opcode 48
575 # offset 0x0000 0200
576         .balign 32,0
577 _neg:
578         loadsp 4
579         not
580         im 1
581         add
582         storesp 8
583         
584         poppc
585         
587 # opcode 49
588 # offset 0x0000 0220
589         .balign 32,0
590 _sub:
591         loadsp 8
592         loadsp 8
593         fast_neg
594         add
595         storesp 12
597         storesp 4
599         poppc
602 # opcode 50
603 # offset 0x0000 0240
604         .balign 32,0
605 _xor:
606         loadsp 8
607         not
608         loadsp 8
609         and
610         
611         loadsp 12
612         loadsp 12
613         not
614         and
616         or
618         storesp 12
619         storesp 4
620         poppc
622 # opcode 51
623 # offset 0x0000 0260
624         .balign 32,0
625 _loadb:
626         loadsp 4
627         im ~0x3
628         and
629         load
631         loadsp 8
632         im 3
633         and
634         fast_neg
635         im 3
636         add
637         ; x8
638         addsp 0
639         addsp 0
640         addsp 0
642         lshiftright
644         im 0xff
645         and
646         storesp 8
647         
648         poppc
651 # opcode 52
652 # offset 0x0000 0280
653         .balign 32,0
654 _storeb:
655         loadsp 4
656         im ~0x3
657         and
658         load
660         ; mask away destination
661         im _mask
662         loadsp 12
663         im 3
664         and
665         addsp 0
666         addsp 0
667         add
668         load
670         and
673         im _storebtail
674         poppc
675         
676 # opcode 53
677 # offset 0x0000 02a0
678         .balign 32,0
679 _div:
680         jmp ___div
681         
682 # opcode 54
683 # offset 0x0000 02c0
684         .balign 32,0
685 _mod:
686         jmp ___mod
688 # opcode 55
689 # offset 0x0000 02e0
690         .balign 32,0
691         .globl _eqbranch
692 _eqbranch:
693         loadsp 8
694         
695         ; eq
697         not 
698         loadsp 0
699         im 1
700         add
701         not
702         and
703         flip
704         im 1
705         and
707         ; mask
708         im -1
709         add
710         loadsp 0
711         storesp 16
713         ; no branch address
714         loadsp 4
715         
716         and
718         ; fetch boolean & neg mask
719         loadsp 12
720         not
721         
722         ; calc address & mask for branch
723         loadsp 8
724         loadsp 16
725         add
726         ; subtract 1 to find PC of branch instruction
727         im -1
728         add
729         
730         and
732         or      
733         
734         storesp 4
735         storesp 4
736         storesp 4
737         poppc   
740 # opcode 56
741 # offset 0x0000 0300
742         .balign 32,0
743         .globl _neqbranch
744 _neqbranch:
745         loadsp 8
746         
747         ; neq
749         not 
750         loadsp 0
751         im 1
752         add
753         not
754         and
755         flip
756         
757         not
758         
759         im 1
760         and
762         ; mask
763         im -1
764         add
765         loadsp 0
766         storesp 16
768         ; no branch address
769         loadsp 4
770         
771         and
773         ; fetch boolean & neg mask
774         loadsp 12
775         not
776         
777         ; calc address & mask for branch
778         loadsp 8
779         loadsp 16
780         add
781         ; find address of branch instruction
782         im -1
783         add
784         
785         and
787         or      
788         
789         storesp 4
790         storesp 4
791         storesp 4
792         poppc   
794 # opcode 57
795 # offset 0x0000 0320
796         .balign 32,0
797         .globl _poppcrel
798 _poppcrel:
799         add
800         ; address of poppcrel
801         im -1
802         add
803         poppc
804                 
805 # opcode 58
806 # offset 0x0000 0340
807         .balign 32,0
808         .globl _config
809 _config:
810         im 1 
811         nop
812         im _hardware
813         store
814         storesp 4
815         poppc
817 # opcode 59
818 # offset 0x0000 0360
819         .balign 32,0
820 _pushpc:
821         loadsp 4
822         im 1
823         add 
824         storesp 8
825         poppc
826         
827 # opcode 60
828 # offset 0x0000 0380
829         .balign 32,0
830 _syscall_emulate:
831         .byte 0
832         
833 # opcode 61
834 # offset 0x0000 03a0
835         .balign 32,0
836 _pushspadd:
837         pushsp
838         im 4
839         add
840         loadsp 8
841         addsp 0
842         addsp 0
843         add
844         storesp 8
845         
846         poppc
848 # opcode 62
849 # offset 0x0000 03c0
850         .balign 32,0
851 _halfmult:
852         breakpoint
853         
854 # opcode 63
855 # offset 0x0000 03e0
856         .balign 32,0
857 _callpcrel:
858         loadsp 4
859         loadsp 4
860         add
861         im -1
862         add
863         loadsp 4
864         
865         storesp 12      ; return address
866         storesp 4 
867         pushsp          ; this will flush the internal stack.
868         popsp
869         poppc
871         .text
873         
876 _ashiftleftBegin:
877         .rept 0x1f
878         addsp 0
879         .endr
880 _ashiftleftEnd:
881         storesp 12
882         storesp 4
883         poppc
884         
885 _storebtail:
886         loadsp 12
887         im 0xff
888         and
889         loadsp 12
890         im 3
891         and
893         fast_neg
894         im 3
895         add
896         ; x8
897         addsp 0
898         addsp 0
899         addsp 0
901         ashiftleft
902          
903         or
904         
905         loadsp 8
906         im  ~0x3
907         and
909         store
910         
911         storesp 4
912         storesp 4
913         poppc
914         
918 ; NB! this is not an EMULATE instruction. It is a varargs fn.
919         .globl _syscall 
920 _syscall:
921         syscall
922         poppc
923         
924 _slowmultImpl:
925         
926         loadsp 8 ; A
927         loadsp 8 ; B
928         im 0 ; C
930 .LmoreMult:
931         mult1bit
932         
933         ; cutoff
934         loadsp 8
935         .byte (.LmoreMult-.Lbranch)&0x7f+0x80
936 .Lbranch:
937         neqbranch
939         storesp 4
940         storesp 4
941         storesp 12
942         storesp 4
943         poppc
945 ___mod:
946         cimpl __modsi3
947 ___div:
948         cimpl __divsi3
950         .globl ___zpu_interrupt_vector
951         .weak ___zpu_interrupt_vector
953 ___zpu_interrupt_vector:
954         jsr _zpu_interrupt
955         poppc
957         .section ".rodata"
958         .balign 4,0
959 _mask:
960         .long 0x00ffffff
961         .long 0xff00ffff
962         .long 0xffff00ff
963         .long 0xffffff00
965         .data
966         .balign 4,0
967         
968         .globl _hardware
969 _hardware:
970         .long 0
971         .globl _cpu_config
972 _cpu_config:
973         .long 0