fixed more binutils issues (newer gcc/libc)
[zpugcc/jano.git] / toolchain / gcc / libgloss / zpu / crt0.S
blob52dccee4faea28e45eb680af63989b932d215d15
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                 .globl _memreg
153                 .weak _memreg
154 _start:
155 _memreg:
156                 ; intSp must be 0 when we jump to _premain
157                 
158                 im ZPU_ID
159                 loadsp 0
160                 im _cpu_config
161                 store
162                 config
163                 jmp _premain
167         .balign 32,0
168 # offset 0x0000 0020
169                 .globl _zpu_interrupt_vector
170 _zpu_interrupt_vector:
171                 jmp ___zpu_interrupt_vector
173 /* instruction emulation code */
175 # opcode 34
176 # offset 0x0000 0040
177         .balign 32,0
178 _loadh:
179         loadsp 4
180         ; by not masking out bit 0, we cause a memory access error 
181         ; on unaligned access
182         im ~0x2
183         and
184         load
186         ; mult 8        
187         loadsp 8
188         im 3
189         and
190         fast_neg
191         im 2
192         add
193         im 3
194         ashiftleft
195         ; shift right addr&3 * 8
196         lshiftright
197         im 0xffff
198         and
199         storesp 8
200         
201         poppc
203 # opcode 35
204 # offset 0x0000 0060
205         .balign 32,0
206 _storeh:
207         loadsp 4
208         ; by not masking out bit 0, we cause a memory access error 
209         ; on unaligned access
210         im ~0x2
211         and
212         load
214         ; mask
215         im 0xffff
216         loadsp 12
217         im 3
218         and
219         fast_neg
220         im 2
221         add
222         im 3
223         ashiftleft
224         ashiftleft
225         not
227         and
229         loadsp 12
230         im 0xffff
232         nop
233                 
234         fixedim _storehtail
235         poppc
238 # opcode 36
239 # offset 0x0000 0080
240         .balign 32,0
241 _lessthan:
242         loadsp 8
243         fast_neg
244         loadsp 8
245         add
247         ; DANGER!!!!
248         ; 0x80000000 will overflow when negated, so we need to mask
249         ; the result above with the compare positive to negative
250         ; number case
251         loadsp 12
252         loadsp 12
253         not
254         and
255         not
256         and
259         ; handle case where we are comparing a negative number
260         ; and positve number. This can underflow. E.g. consider 0x8000000 < 0x1000
261         loadsp 12
262         not
263         loadsp 12
264         and
265         
266         or
270         flip
271         im 1
272         and     
274         
275         storesp 12
276         storesp 4
277         poppc
278         
280 # opcode 37
281 # offset 0x0000 00a0
282         .balign 32,0
283 _lessthanorequal:
284         loadsp 8
285         loadsp 8
286         lessthan
287         loadsp 12
288         loadsp 12
289         eq
290         or
291         
292         storesp 12
293         storesp 4
294         poppc
296         
297 # opcode 38
298 # offset 0x0000 00c0
299         .balign 32,0
300 _ulessthan:
301         ; fish up arguments 
302         loadsp 4
303         loadsp 12
304         
305         /* low: -1 if low bit dif is negative 0 otherwise:  neg (not x&1 and (y&1))
306                 x&1             y&1             neg (not x&1 and (y&1))
307                 1               1               0
308                 1               0               0
309                 0               1               -1
310                 0               0               0
311         
312         */
313         loadsp 4 
314         not
315         loadsp 4
316         and
317         im 1
318         and
319         neg
320         
321         
322         /* high: upper 31-bit diff is only wrong when diff is 0 and low=-1
323                 high=x>>1 - y>>1 + low
324                 
325                 extremes
326                 
327                 0000 - 1111:
328                 low= neg(not 0 and 1) = 1111 (-1)
329                 high=000+ neg(111) +low = 000 + 1001 + low = 1000 
330                 OK
331                 
332                 1111 - 0000
333                 low=neg(not 1 and 0) = 0
334                 high=111+neg(000) + low = 0111
335                 OK
336                  
337                 
338          */
339         loadsp 8
340         
341         flip 
342         addsp 0
343         flip
344         
345         loadsp 8
346         
347         flip    
348         addsp 0
349         flip
351         sub
353         ; if they are equal, then the last bit decides...       
354         add
355         
356         /* test if negative: result = flip(diff) & 1 */
357         flip
358         im 1
359         and
361         ; destroy a&b which are on stack        
362         storesp 4
363         storesp 4
364         
365         storesp 12
366         storesp 4
367         poppc                   
369 # opcode 39
370 # offset 0x0000 00e0
371         .balign 32,0
372 _ulessthanorequal:
373         loadsp 8
374         loadsp 8
375         ulessthan
376         loadsp 12
377         loadsp 12
378         eq
379         or
380         
381         storesp 12
382         storesp 4
383         poppc
386 # opcode 40
387 # offset 0x0000 0100
388         .balign 32,0
389         .globl _swap
390 _swap:
391         breakpoint ; tbd
393 # opcode 41
394 # offset 0x0000 0120
395         .balign 32,0
396 _slowmult:
397         im _slowmultImpl
398         poppc
400 # opcode 42
401 # offset 0x0000 0140
402         .balign 32,0
403 _lshiftright:
404         loadsp 8
405         flip
407         loadsp 8
408         ashiftleft
409         flip
410         
411         storesp 12
412         storesp 4
414         poppc
415         
417 # opcode 43
418 # offset 0x0000 0160
419         .balign 32,0
420 _ashiftleft:
421         loadsp 8
422         
423         loadsp 8
424         im 0x1f
425         and
426         fast_neg
427         im _ashiftleftEnd
428         add
429         poppc
430         
431         
432         
433 # opcode 44
434 # offset 0x0000 0180
435         .balign 32,0
436 _ashiftright:
437         loadsp 8
438         loadsp 8
439         lshiftright
440         
441         ; handle signed value
442         im -1
443         loadsp 12
444         im 0x1f
445         and
446         lshiftright
447         not     ; now we have an integer on the stack with the signed 
448                 ; bits in the right position
450         ; mask these bits with the signed bit.
451         loadsp 16
452         not
453         flip
454         im 1
455         and
456         im -1
457         add
458         
459         and     
460         
461         ; stuff in the signed bits...
462         or
463         
464         ; store result into correct stack slot  
465         storesp 12
466         
467         ; move up return value 
468         storesp 4
469         poppc
471 # opcode 45
472 # offset 0x0000 01a0
473         .balign 32,0
474 _call:
475         ; fn
476         loadsp 4
477         
478         ; return address
479         loadsp 4
481         ; store return address
482         storesp 12
483         
484         ; fn to call
485         storesp 4
486         
487         pushsp  ; flush internal stack
488         popsp
489                 
490         poppc
492 _storehtail:
494         and
495         loadsp 12
496         im 3
497         and
498         fast_neg
499         im 2
500         add
501         im 3
502         ashiftleft
503         nop
504         ashiftleft
505         
506         or
507         
508         loadsp 8
509         im  ~0x3
510         and
512         store
513         
514         storesp 4
515         storesp 4
516         poppc
519 # opcode 46
520 # offset 0x0000 01c0
521         .balign 32,0
522 _eq:
523         loadsp 8
524         fast_neg
525         loadsp 8
526         add
527         
528         not 
529         loadsp 0
530         im 1
531         add
532         not
533         and
534         flip
535         im 1
536         and
537         
538         storesp 12
539         storesp 4
540         poppc
542 # opcode 47
543 # offset 0x0000 01e0
544         .balign 32,0
545 _neq:
546         loadsp 8
547         fast_neg
548         loadsp 8
549         add
550         
551         not 
552         loadsp 0
553         im 1
554         add
555         not
556         and
557         flip
559         not
561         im 1
562         and
563                 
564         storesp 12
565         storesp 4
566         poppc
567         
569 # opcode 48
570 # offset 0x0000 0200
571         .balign 32,0
572 _neg:
573         loadsp 4
574         not
575         im 1
576         add
577         storesp 8
578         
579         poppc
580         
582 # opcode 49
583 # offset 0x0000 0220
584         .balign 32,0
585 _sub:
586         loadsp 8
587         loadsp 8
588         fast_neg
589         add
590         storesp 12
592         storesp 4
594         poppc
597 # opcode 50
598 # offset 0x0000 0240
599         .balign 32,0
600 _xor:
601         loadsp 8
602         not
603         loadsp 8
604         and
605         
606         loadsp 12
607         loadsp 12
608         not
609         and
611         or
613         storesp 12
614         storesp 4
615         poppc
617 # opcode 51
618 # offset 0x0000 0260
619         .balign 32,0
620 _loadb:
621         loadsp 4
622         im ~0x3
623         and
624         load
626         loadsp 8
627         im 3
628         and
629         fast_neg
630         im 3
631         add
632         ; x8
633         addsp 0
634         addsp 0
635         addsp 0
637         lshiftright
639         im 0xff
640         and
641         storesp 8
642         
643         poppc
646 # opcode 52
647 # offset 0x0000 0280
648         .balign 32,0
649 _storeb:
650         loadsp 4
651         im ~0x3
652         and
653         load
655         ; mask away destination
656         im _mask
657         loadsp 12
658         im 3
659         and
660         addsp 0
661         addsp 0
662         add
663         load
665         and
668         im _storebtail
669         poppc
670         
671 # opcode 53
672 # offset 0x0000 02a0
673         .balign 32,0
674 _div:
675         jmp ___div
676         
677 # opcode 54
678 # offset 0x0000 02c0
679         .balign 32,0
680 _mod:
681         jmp ___mod
683 # opcode 55
684 # offset 0x0000 02e0
685         .balign 32,0
686         .globl _eqbranch
687 _eqbranch:
688         loadsp 8
689         
690         ; eq
692         not 
693         loadsp 0
694         im 1
695         add
696         not
697         and
698         flip
699         im 1
700         and
702         ; mask
703         im -1
704         add
705         loadsp 0
706         storesp 16
708         ; no branch address
709         loadsp 4
710         
711         and
713         ; fetch boolean & neg mask
714         loadsp 12
715         not
716         
717         ; calc address & mask for branch
718         loadsp 8
719         loadsp 16
720         add
721         ; subtract 1 to find PC of branch instruction
722         im -1
723         add
724         
725         and
727         or      
728         
729         storesp 4
730         storesp 4
731         storesp 4
732         poppc   
735 # opcode 56
736 # offset 0x0000 0300
737         .balign 32,0
738         .globl _neqbranch
739 _neqbranch:
740         loadsp 8
741         
742         ; neq
744         not 
745         loadsp 0
746         im 1
747         add
748         not
749         and
750         flip
751         
752         not
753         
754         im 1
755         and
757         ; mask
758         im -1
759         add
760         loadsp 0
761         storesp 16
763         ; no branch address
764         loadsp 4
765         
766         and
768         ; fetch boolean & neg mask
769         loadsp 12
770         not
771         
772         ; calc address & mask for branch
773         loadsp 8
774         loadsp 16
775         add
776         ; find address of branch instruction
777         im -1
778         add
779         
780         and
782         or      
783         
784         storesp 4
785         storesp 4
786         storesp 4
787         poppc   
789 # opcode 57
790 # offset 0x0000 0320
791         .balign 32,0
792         .globl _poppcrel
793 _poppcrel:
794         add
795         ; address of poppcrel
796         im -1
797         add
798         poppc
799                 
800 # opcode 58
801 # offset 0x0000 0340
802         .balign 32,0
803         .globl _config
804 _config:
805         im 1 
806         nop
807         im _hardware
808         store
809         storesp 4
810         poppc
812 # opcode 59
813 # offset 0x0000 0360
814         .balign 32,0
815 _pushpc:
816         loadsp 4
817         im 1
818         add 
819         storesp 8
820         poppc
821         
822 # opcode 60
823 # offset 0x0000 0380
824         .balign 32,0
825 _syscall_emulate:
826         .byte 0
827         
828 # opcode 61
829 # offset 0x0000 03a0
830         .balign 32,0
831 _pushspadd:
832         pushsp
833         im 4
834         add
835         loadsp 8
836         addsp 0
837         addsp 0
838         add
839         storesp 8
840         
841         poppc
843 # opcode 62
844 # offset 0x0000 03c0
845         .balign 32,0
846 _halfmult:
847         breakpoint
848         
849 # opcode 63
850 # offset 0x0000 03e0
851         .balign 32,0
852 _callpcrel:
853         loadsp 4
854         loadsp 4
855         add
856         im -1
857         add
858         loadsp 4
859         
860         storesp 12      ; return address
861         storesp 4 
862         pushsp          ; this will flush the internal stack.
863         popsp
864         poppc
866         .text
868         
871 _ashiftleftBegin:
872         .rept 0x1f
873         addsp 0
874         .endr
875 _ashiftleftEnd:
876         storesp 12
877         storesp 4
878         poppc
879         
880 _storebtail:
881         loadsp 12
882         im 0xff
883         and
884         loadsp 12
885         im 3
886         and
888         fast_neg
889         im 3
890         add
891         ; x8
892         addsp 0
893         addsp 0
894         addsp 0
896         ashiftleft
897          
898         or
899         
900         loadsp 8
901         im  ~0x3
902         and
904         store
905         
906         storesp 4
907         storesp 4
908         poppc
909         
913 ; NB! this is not an EMULATE instruction. It is a varargs fn.
914         .globl _syscall 
915 _syscall:
916         syscall
917         poppc
918         
919 _slowmultImpl:
920         
921         loadsp 8 ; A
922         loadsp 8 ; B
923         im 0 ; C
925 .LmoreMult:
926         mult1bit
927         
928         ; cutoff
929         loadsp 8
930         .byte (.LmoreMult-.Lbranch)&0x7f+0x80
931 .Lbranch:
932         neqbranch
934         storesp 4
935         storesp 4
936         storesp 12
937         storesp 4
938         poppc
940 ___mod:
941         cimpl __modsi3
942 ___div:
943         cimpl __divsi3
945         .globl ___zpu_interrupt_vector
946         .weak ___zpu_interrupt_vector
948 ___zpu_interrupt_vector:
949         jsr _zpu_interrupt
950         poppc
952         .data
953         .balign 4,0
954 _mask:
955         .long 0x00ffffff
956         .long 0xff00ffff
957         .long 0xffff00ff
958         .long 0xffffff00
960         
961         .globl _hardware
962 _hardware:
963         .long 0
964         .globl _cpu_config
965 _cpu_config:
966         .long 0