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