OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.2.2/] [gcc/] [config/] [m68hc11/] [larith.asm] - Blame information for rev 199

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* libgcc routines for M68HC11 & M68HC12.
2
   Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
3
 
4
This file is part of GCC.
5
 
6
GCC is free software; you can redistribute it and/or modify it
7
under the terms of the GNU General Public License as published by the
8
Free Software Foundation; either version 2, or (at your option) any
9
later version.
10
 
11
In addition to the permissions in the GNU General Public License, the
12
Free Software Foundation gives you unlimited permission to link the
13
compiled version of this file with other programs, and to distribute
14
those programs without any restriction coming from the use of this
15
file.  (The General Public License restrictions do apply in other
16
respects; for example, they cover modification of the file, and
17
distribution when not linked into another program.)
18
 
19
This file is distributed in the hope that it will be useful, but
20
WITHOUT ANY WARRANTY; without even the implied warranty of
21
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22
General Public License for more details.
23
 
24
You should have received a copy of the GNU General Public License
25
along with this program; see the file COPYING.  If not, write to
26
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
27
Boston, MA 02110-1301, USA.  */
28
 
29
/* As a special exception, if you link this library with other files,
30
   some of which are compiled with GCC, to produce an executable,
31
   this library does not by itself cause the resulting executable
32
   to be covered by the GNU General Public License.
33
   This exception does not however invalidate any other reasons why
34
   the executable file might be covered by the GNU General Public License.  */
35
 
36
        .file "larith.asm"
37
 
38
#ifdef __HAVE_SHORT_INT__
39
        .mode mshort
40
#else
41
        .mode mlong
42
#endif
43
 
44
        .macro declare_near name
45
        .globl \name
46
        .type  \name,@function
47
        .size  \name,.Lend-\name
48
\name:
49
        .endm
50
 
51
#if defined(__USE_RTC__)
52
# define ARG(N) N+1
53
 
54
        .macro ret
55
#if defined(mc68hc12)
56
        rtc
57
#else
58
        jmp __return_32
59
#endif
60
        .endm
61
 
62
        .macro declare name
63
        .globl \name
64
        .type  \name,@function
65
        .size  \name,.Lend-\name
66
        .far   \name
67
\name:
68
        .endm
69
 
70
        .macro farsym name
71
        .far NAME
72
        .endm
73
 
74
#else
75
# define ARG(N) N
76
 
77
        .macro ret
78
        rts
79
        .endm
80
 
81
        .macro farsym name
82
        .endm
83
 
84
        .macro declare name
85
        .globl \name
86
        .type  \name,@function
87
        .size  \name,.Lend-\name
88
\name:
89
        .endm
90
 
91
#endif
92
 
93
        .sect .text
94
 
95
 
96
#define REG(NAME)                       \
97
NAME:   .dc.w   1;                      \
98
        .type NAME,@object ;            \
99
        .size NAME,2
100
 
101
#ifdef L_regs_min
102
/* Pseudo hard registers used by gcc.
103
   They should be located in page0.  */
104
 
105
        .sect .softregs
106
        .globl _.tmp
107
        .globl _.z,_.xy
108
REG(_.tmp)
109
REG(_.z)
110
REG(_.xy)
111
 
112
#endif
113
 
114
#ifdef L_regs_frame
115
        .sect .softregs
116
        .globl _.frame
117
REG(_.frame)
118
#endif
119
 
120
#ifdef L_regs_d1_2
121
        .sect .softregs
122
        .globl _.d1,_.d2
123
REG(_.d1)
124
REG(_.d2)
125
#endif
126
 
127
#ifdef L_regs_d3_4
128
        .sect .softregs
129
        .globl _.d3,_.d4
130
REG(_.d3)
131
REG(_.d4)
132
#endif
133
 
134
#ifdef L_regs_d5_6
135
        .sect .softregs
136
        .globl _.d5,_.d6
137
REG(_.d5)
138
REG(_.d6)
139
#endif
140
 
141
#ifdef L_regs_d7_8
142
        .sect .softregs
143
        .globl _.d7,_.d8
144
REG(_.d7)
145
REG(_.d8)
146
#endif
147
 
148
#ifdef L_regs_d9_16
149
/* Pseudo hard registers used by gcc.
150
   They should be located in page0.  */
151
        .sect .softregs
152
        .globl _.d9,_.d10,_.d11,_.d12,_.d13,_.d14
153
        .globl _.d15,_.d16
154
REG(_.d9)
155
REG(_.d10)
156
REG(_.d11)
157
REG(_.d12)
158
REG(_.d13)
159
REG(_.d14)
160
REG(_.d15)
161
REG(_.d16)
162
 
163
#endif
164
 
165
#ifdef L_regs_d17_32
166
/* Pseudo hard registers used by gcc.
167
   They should be located in page0.  */
168
        .sect .softregs
169
        .globl _.d17,_.d18,_.d19,_.d20,_.d21,_.d22
170
        .globl _.d23,_.d24,_.d25,_.d26,_.d27,_.d28
171
        .globl _.d29,_.d30,_.d31,_.d32
172
REG(_.d17)
173
REG(_.d18)
174
REG(_.d19)
175
REG(_.d20)
176
REG(_.d21)
177
REG(_.d22)
178
REG(_.d23)
179
REG(_.d24)
180
REG(_.d25)
181
REG(_.d26)
182
REG(_.d27)
183
REG(_.d28)
184
REG(_.d29)
185
REG(_.d30)
186
REG(_.d31)
187
REG(_.d32)
188
#endif
189
 
190
#ifdef L_premain
191
;;
192
;; Specific initialization for 68hc11 before the main.
193
;; Nothing special for a generic routine; Just enable interrupts.
194
;;
195
        declare_near    __premain
196
        clra
197
        tap     ; Clear both I and X.
198
        rts
199
#endif
200
 
201
#ifdef L__exit
202
;;
203
;; Exit operation.  Just loop forever and wait for interrupts.
204
;; (no other place to go)
205
;; This operation is split in several pieces collected together by
206
;; the linker script.  This allows to support destructors at the
207
;; exit stage while not impacting program sizes when there is no
208
;; destructors.
209
;;
210
;; _exit:
211
;;    *(.fini0)         /* Beginning of finish code (_exit symbol).  */
212
;;    *(.fini1)         /* Place holder for applications.  */
213
;;    *(.fini2)         /* C++ destructors.  */
214
;;    *(.fini3)         /* Place holder for applications.  */
215
;;    *(.fini4)         /* Runtime exit.  */
216
;;
217
        .sect .fini0,"ax",@progbits
218
        .globl _exit
219
        .globl exit
220
        .weak  exit
221
        farsym  exit
222
        farsym  _exit
223
exit:
224
_exit:
225
 
226
        .sect .fini4,"ax",@progbits
227
fatal:
228
        cli
229
        wai
230
        bra fatal
231
#endif
232
 
233
#ifdef L_abort
234
;;
235
;; Abort operation.  This is defined for the GCC testsuite.
236
;;
237
        declare abort
238
 
239
        ldd     #255            ;
240
#ifdef mc68hc12
241
        trap    #0x30
242
#else
243
        .byte 0xCD              ; Generate an illegal instruction trap
244
        .byte 0x03              ; The simulator catches this and stops.
245
#endif
246
        jmp _exit
247
#endif
248
 
249
#ifdef L_cleanup
250
;;
251
;; Cleanup operation used by exit().
252
;;
253
        declare _cleanup
254
 
255
        ret
256
#endif
257
 
258
;-----------------------------------------
259
; required gcclib code
260
;-----------------------------------------
261
#ifdef L_memcpy
262
       declare  memcpy
263
       declare  __memcpy
264
 
265
        .weak memcpy
266
;;;
267
;;; void* memcpy(void*, const void*, size_t)
268
;;;
269
;;; D    = dst  Pmode
270
;;; 2,sp = src  Pmode
271
;;; 4,sp = size HImode (size_t)
272
;;;
273
#ifdef mc68hc12
274
        ldx     ARG(2),sp
275
        ldy     ARG(4),sp
276
        pshd
277
        xgdy
278
        lsrd
279
        bcc     Start
280
        movb    1,x+,1,y+
281
Start:
282
        beq     Done
283
Loop:
284
        movw    2,x+,2,y+
285
        dbne    d,Loop
286
Done:
287
        puld
288
        ret
289
#else
290
        xgdy
291
        tsx
292
        ldd     ARG(4),x
293
        ldx     ARG(2),x        ; SRC = X, DST = Y
294
        cpd     #0
295
        beq     End
296
        pshy
297
        inca                    ; Correction for the deca below
298
L0:
299
        psha                    ; Save high-counter part
300
L1:
301
        ldaa    0,x             ; Copy up to 256 bytes
302
        staa    0,y
303
        inx
304
        iny
305
        decb
306
        bne     L1
307
        pula
308
        deca
309
        bne     L0
310
        puly                    ; Restore Y to return the DST
311
End:
312
        xgdy
313
        ret
314
#endif
315
#endif
316
 
317
#ifdef L_memset
318
       declare  memset
319
       declare  __memset
320
;;;
321
;;; void* memset(void*, int value, size_t)
322
;;;
323
#ifndef __HAVE_SHORT_INT__
324
;;; D    = dst  Pmode
325
;;; 2,sp = src  SImode
326
;;; 6,sp = size HImode (size_t)
327
        val  = ARG(5)
328
        size = ARG(6)
329
#else
330
;;; D    = dst  Pmode
331
;;; 2,sp = src  SImode
332
;;; 6,sp = size HImode (size_t)
333
        val  = ARG(3)
334
        size = ARG(4)
335
#endif
336
#ifdef mc68hc12
337
        xgdx
338
        ldab    val,sp
339
        ldy     size,sp
340
        pshx
341
        beq     End
342
Loop:
343
        stab    1,x+
344
        dbne    y,Loop
345
End:
346
        puld
347
        ret
348
#else
349
        xgdx
350
        tsy
351
        ldab    val,y
352
        ldy     size,y          ; DST = X, CNT = Y
353
        beq     End
354
        pshx
355
L0:
356
        stab    0,x             ; Fill up to 256 bytes
357
        inx
358
        dey
359
        bne     L0
360
        pulx                    ; Restore X to return the DST
361
End:
362
        xgdx
363
        ret
364
#endif
365
#endif
366
 
367
#ifdef L_adddi3
368
        declare ___adddi3
369
 
370
        tsx
371
        xgdy
372
        ldd     ARG(8),x                ; Add LSB
373
        addd    ARG(16),x
374
        std     6,y             ; Save (carry preserved)
375
 
376
        ldd     ARG(6),x
377
        adcb    ARG(15),x
378
        adca    ARG(14),x
379
        std     4,y
380
 
381
        ldd     ARG(4),x
382
        adcb    ARG(13),x
383
        adca    ARG(12),x
384
        std     2,y
385
 
386
        ldd     ARG(2),x
387
        adcb    ARG(11),x               ; Add MSB
388
        adca    ARG(10),x
389
        std     0,y
390
 
391
        xgdy
392
        ret
393
#endif
394
 
395
#ifdef L_subdi3
396
        declare ___subdi3
397
 
398
        tsx
399
        xgdy
400
        ldd     ARG(8),x                ; Subtract LSB
401
        subd    ARG(16),x
402
        std     6,y                     ; Save, borrow preserved
403
 
404
        ldd     ARG(6),x
405
        sbcb    ARG(15),x
406
        sbca    ARG(14),x
407
        std     4,y
408
 
409
        ldd     ARG(4),x
410
        sbcb    ARG(13),x
411
        sbca    ARG(12),x
412
        std     2,y
413
 
414
        ldd     ARG(2),x                ; Subtract MSB
415
        sbcb    ARG(11),x
416
        sbca    ARG(10),x
417
        std     0,y
418
 
419
        xgdy                    ;
420
        ret
421
#endif
422
 
423
#ifdef L_notdi2
424
        declare ___notdi2
425
 
426
        tsy
427
        xgdx
428
        ldd     ARG(8),y
429
        coma
430
        comb
431
        std     6,x
432
 
433
        ldd     ARG(6),y
434
        coma
435
        comb
436
        std     4,x
437
 
438
        ldd     ARG(4),y
439
        coma
440
        comb
441
        std     2,x
442
 
443
        ldd     ARG(2),y
444
        coma
445
        comb
446
        std     0,x
447
        xgdx
448
        ret
449
#endif
450
 
451
#ifdef L_negsi2
452
        declare_near ___negsi2
453
 
454
        comb
455
        coma
456
        xgdx
457
        comb
458
        coma
459
        inx
460
        xgdx
461
        bne     done
462
        inx
463
done:
464
        rts
465
#endif
466
 
467
#ifdef L_one_cmplsi2
468
        declare_near ___one_cmplsi2
469
 
470
        comb
471
        coma
472
        xgdx
473
        comb
474
        coma
475
        xgdx
476
        rts
477
#endif
478
 
479
#ifdef L_ashlsi3
480
        declare_near ___ashlsi3
481
 
482
        xgdy
483
        clra
484
        andb    #0x1f
485
        xgdy
486
        beq     Return
487
Loop:
488
        lsld
489
        xgdx
490
        rolb
491
        rola
492
        xgdx
493
        dey
494
        bne     Loop
495
Return:
496
        rts
497
#endif
498
 
499
#ifdef L_ashrsi3
500
        declare_near ___ashrsi3
501
 
502
        xgdy
503
        clra
504
        andb    #0x1f
505
        xgdy
506
        beq     Return
507
Loop:
508
        xgdx
509
        asra
510
        rorb
511
        xgdx
512
        rora
513
        rorb
514
        dey
515
        bne     Loop
516
Return:
517
        rts
518
#endif
519
 
520
#ifdef L_lshrsi3
521
        declare_near ___lshrsi3
522
 
523
        xgdy
524
        clra
525
        andb    #0x1f
526
        xgdy
527
        beq     Return
528
Loop:
529
        xgdx
530
        lsrd
531
        xgdx
532
        rora
533
        rorb
534
        dey
535
        bne     Loop
536
Return:
537
        rts
538
#endif
539
 
540
#ifdef L_lshrhi3
541
        declare_near ___lshrhi3
542
 
543
        cpx     #16
544
        bge     Return_zero
545
        cpx     #0
546
        beq     Return
547
Loop:
548
        lsrd
549
        dex
550
        bne     Loop
551
Return:
552
        rts
553
Return_zero:
554
        clra
555
        clrb
556
        rts
557
#endif
558
 
559
#ifdef L_lshlhi3
560
        declare_near ___lshlhi3
561
 
562
        cpx     #16
563
        bge     Return_zero
564
        cpx     #0
565
        beq     Return
566
Loop:
567
        lsld
568
        dex
569
        bne     Loop
570
Return:
571
        rts
572
Return_zero:
573
        clra
574
        clrb
575
        rts
576
#endif
577
 
578
#ifdef L_rotrhi3
579
        declare_near ___rotrhi3
580
 
581
___rotrhi3:
582
        xgdx
583
        clra
584
        andb    #0x0f
585
        xgdx
586
        beq     Return
587
Loop:
588
        tap
589
        rorb
590
        rora
591
        dex
592
        bne     Loop
593
Return:
594
        rts
595
#endif
596
 
597
#ifdef L_rotlhi3
598
        declare_near ___rotlhi3
599
 
600
___rotlhi3:
601
        xgdx
602
        clra
603
        andb    #0x0f
604
        xgdx
605
        beq     Return
606
Loop:
607
        asrb
608
        rolb
609
        rola
610
        rolb
611
        dex
612
        bne     Loop
613
Return:
614
        rts
615
#endif
616
 
617
#ifdef L_ashrhi3
618
        declare_near ___ashrhi3
619
 
620
        cpx     #16
621
        bge     Return_minus_1_or_zero
622
        cpx     #0
623
        beq     Return
624
Loop:
625
        asra
626
        rorb
627
        dex
628
        bne     Loop
629
Return:
630
        rts
631
Return_minus_1_or_zero:
632
        clrb
633
        tsta
634
        bpl     Return_zero
635
        comb
636
Return_zero:
637
        tba
638
        rts
639
#endif
640
 
641
#ifdef L_ashrqi3
642
        declare_near ___ashrqi3
643
 
644
        cmpa    #8
645
        bge     Return_minus_1_or_zero
646
        tsta
647
        beq     Return
648
Loop:
649
        asrb
650
        deca
651
        bne     Loop
652
Return:
653
        rts
654
Return_minus_1_or_zero:
655
        clrb
656
        tstb
657
        bpl     Return_zero
658
        coma
659
Return_zero:
660
        tab
661
        rts
662
#endif
663
 
664
#ifdef L_lshlqi3
665
        declare_near ___lshlqi3
666
 
667
        cmpa    #8
668
        bge     Return_zero
669
        tsta
670
        beq     Return
671
Loop:
672
        lslb
673
        deca
674
        bne     Loop
675
Return:
676
        rts
677
Return_zero:
678
        clrb
679
        rts
680
#endif
681
 
682
#ifdef L_divmodhi4
683
#ifndef mc68hc12
684
/* 68HC12 signed divisions are generated inline (idivs).  */
685
 
686
        declare_near __divmodhi4
687
 
688
;
689
;; D = numerator
690
;; X = denominator
691
;;
692
;; Result:      D = D / X
693
;;              X = D % X
694
;;
695
        tsta
696
        bpl     Numerator_pos
697
        comb                    ; D = -D <=> D = (~D) + 1
698
        coma
699
        xgdx
700
        inx
701
        tsta
702
        bpl     Numerator_neg_denominator_pos
703
Numerator_neg_denominator_neg:
704
        comb                    ; X = -X
705
        coma
706
        addd    #1
707
        xgdx
708
        idiv
709
        coma
710
        comb
711
        xgdx                    ; Remainder <= 0 and result >= 0
712
        inx
713
        rts
714
 
715
Numerator_pos_denominator_pos:
716
        xgdx
717
        idiv
718
        xgdx                    ; Both values are >= 0
719
        rts
720
 
721
Numerator_pos:
722
        xgdx
723
        tsta
724
        bpl     Numerator_pos_denominator_pos
725
Numerator_pos_denominator_neg:
726
        coma                    ; X = -X
727
        comb
728
        xgdx
729
        inx
730
        idiv
731
        xgdx                    ; Remainder >= 0 but result <= 0
732
        coma
733
        comb
734
        addd    #1
735
        rts
736
 
737
Numerator_neg_denominator_pos:
738
        xgdx
739
        idiv
740
        coma                    ; One value is > 0 and the other < 0
741
        comb                    ; Change the sign of result and remainder
742
        xgdx
743
        inx
744
        coma
745
        comb
746
        addd    #1
747
        rts
748
#endif /* !mc68hc12 */
749
#endif
750
 
751
#ifdef L_mulqi3
752
        declare_near ___mulqi3
753
 
754
;
755
; short __mulqi3(signed char a, signed char b);
756
;
757
;       signed char a   -> register A
758
;       signed char b   -> register B
759
;
760
; returns the signed result of A * B in register D.
761
;
762
        tsta
763
        bmi     A_neg
764
        tstb
765
        bmi     B_neg
766
        mul
767
        rts
768
B_neg:
769
        negb
770
        bra     A_or_B_neg
771
A_neg:
772
        nega
773
        tstb
774
        bmi     AB_neg
775
A_or_B_neg:
776
        mul
777
        coma
778
        comb
779
        addd    #1
780
        rts
781
AB_neg:
782
        negb
783
        mul
784
        rts
785
#endif
786
 
787
#ifdef L_mulhi3
788
        declare_near ___mulhi3
789
 
790
;
791
;
792
;  unsigned short ___mulhi3(unsigned short a, unsigned short b)
793
;
794
;       a = register D
795
;       b = register X
796
;
797
#ifdef mc68hc12
798
        pshx                    ; Preserve X
799
        exg     x,y
800
        emul
801
        exg     x,y
802
        pulx
803
        rts
804
#else
805
#ifdef NO_TMP
806
        ;
807
        ; 16 bit multiplication without temp memory location.
808
        ; (smaller but slower)
809
        ;
810
        pshx                    ; (4)
811
        ins                     ; (3)
812
        pshb                    ; (3)
813
        psha                    ; (3)
814
        pshx                    ; (4)
815
        pula                    ; (4)
816
        pulx                    ; (5)
817
        mul                     ; (10) B.high * A.low
818
        xgdx                    ; (3)
819
        mul                     ; (10) B.low * A.high
820
        abx                     ; (3)
821
        pula                    ; (4)
822
        pulb                    ; (4)
823
        mul                     ; (10) B.low * A.low
824
        pshx                    ; (4)
825
        tsx                     ; (3)
826
        adda    1,x             ; (4)
827
        pulx                    ; (5)
828
        rts                     ; (5) 20 bytes
829
                                ; ---
830
                                ; 91 cycles
831
#else
832
        stx     *_.tmp          ; (4)
833
        pshb                    ; (3)
834
        ldab    *_.tmp+1        ; (3)
835
        mul                     ; (10) A.high * B.low
836
        ldaa    *_.tmp          ; (3)
837
        stab    *_.tmp          ; (3)
838
        pulb                    ; (4)
839
        pshb                    ; (4)
840
        mul                     ; (10) A.low * B.high
841
        addb    *_.tmp          ; (4)
842
        stab    *_.tmp          ; (3)
843
        ldaa    *_.tmp+1        ; (3)
844
        pulb                    ; (4)
845
        mul                     ; (10) A.low * B.low
846
        adda    *_.tmp          ; (4)
847
        rts                     ; (5) 24/32 bytes
848
                                ; 77/85 cycles
849
#endif
850
#endif
851
#endif
852
 
853
#ifdef L_mulhi32
854
 
855
;
856
;
857
;  unsigned long __mulhi32(unsigned short a, unsigned short b)
858
;
859
;       a = register D
860
;       b = value on stack
861
;
862
;       +---------------+
863
;       |  B low        | <- 7,x
864
;       +---------------+
865
;       |  B high       | <- 6,x
866
;       +---------------+
867
;       |  PC low       |
868
;       +---------------+
869
;       |  PC high      |
870
;       +---------------+
871
;       |  Tmp low      |
872
;       +---------------+
873
;       |  Tmp high     |
874
;       +---------------+
875
;       |  A low        |
876
;       +---------------+
877
;       |  A high       |
878
;       +---------------+  <- 0,x
879
;
880
;
881
;          5,x
882
;         4,x
883
;            2,x
884
;          1,x
885
;         0,x
886
;
887
        declare_near    __mulhi32
888
 
889
#ifdef mc68hc12
890
        ldy     2,sp
891
        emul
892
        exg     x,y
893
        rts
894
#else
895
        pshx                    ; Room for temp value
896
        pshb
897
        psha
898
        tsx
899
        ldab    6,x
900
        mul
901
        xgdy                    ; A.high * B.high
902
        ldab    7,x
903
        pula
904
        mul                     ; A.high * B.low
905
        std     2,x
906
        ldaa    1,x
907
        ldab    6,x
908
        mul                     ; A.low * B.high
909
        addd    2,x
910
        stab    2,x
911
        tab
912
        aby
913
        bcc     N
914
        ldab    #0xff
915
        aby
916
        iny
917
N:
918
        ldab    7,x
919
        pula
920
        mul                     ; A.low * B.low
921
        adda    2,x
922
        pulx                    ; Drop temp location
923
        pshy                    ; Put high part in X
924
        pulx
925
        bcc     Ret
926
        inx
927
Ret:
928
        rts
929
#endif
930
#endif
931
 
932
#ifdef L_mulsi3
933
 
934
;
935
;          8,y
936
;         6,y
937
;            4,y
938
;                 2,y
939
;          0,y
940
;
941
; D,X   -> A
942
; Stack -> B
943
;
944
; The result is:
945
;
946
;       (((A.low * B.high) + (A.high * B.low)) << 16) + (A.low * B.low)
947
;
948
;
949
;
950
 
951
        declare __mulsi3
952
 
953
#ifdef mc68hc12
954
        pshd                            ; Save A.low
955
        ldy     ARG(4),sp
956
        emul                            ; A.low * B.high
957
        ldy     ARG(6),sp
958
        exg     x,d
959
        emul                            ; A.high * B.low
960
        leax    d,x
961
        ldy     ARG(6),sp
962
        puld
963
        emul                            ; A.low * B.low
964
        exg     d,y
965
        leax    d,x
966
        exg     d,y
967
        ret
968
#else
969
B_low   =       ARG(8)
970
B_high  =       ARG(6)
971
A_low   =       0
972
A_high  =       2
973
        pshx
974
        pshb
975
        psha
976
        tsy
977
;
978
; If B.low is 0, optimize into: (A.low * B.high) << 16
979
;
980
        ldd     B_low,y
981
        beq     B_low_zero
982
;
983
; If A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low)
984
;
985
        cpx     #0
986
        beq     A_high_zero
987
        bsr     ___mulhi3               ; A.high * B.low
988
;
989
; If A.low is 0, optimize into: (A.high * B.low) << 16
990
;
991
        ldx     A_low,y
992
        beq     A_low_zero              ; X = 0, D = A.high * B.low
993
        std     2,y
994
;
995
; If B.high is 0, we can avoid the (A.low * B.high) << 16 term.
996
;
997
        ldd     B_high,y
998
        beq     B_high_zero
999
        bsr     ___mulhi3               ; A.low * B.high
1000
        addd    2,y
1001
        std     2,y
1002
;
1003
; Here, we know that A.low and B.low are not 0.
1004
;
1005
B_high_zero:
1006
        ldd     B_low,y                 ; A.low is on the stack
1007
        bsr     __mulhi32               ; A.low * B.low
1008
        xgdx
1009
        tsy                             ; Y was clobbered, get it back
1010
        addd    2,y
1011
A_low_zero:                             ; See A_low_zero_non_optimized below
1012
        xgdx
1013
Return:
1014
        ins
1015
        ins
1016
        ins
1017
        ins
1018
        ret
1019
;
1020
;
1021
; A_low_zero_non_optimized:
1022
;
1023
; At this step, X = 0 and D = (A.high * B.low)
1024
; Optimize into: (A.high * B.low) << 16
1025
;
1026
;       xgdx
1027
;       clra                    ; Since X was 0, clearing D is superfuous.
1028
;       clrb
1029
;       bra     Return
1030
; ----------------
1031
; B.low == 0, the result is:    (A.low * B.high) << 16
1032
;
1033
; At this step:
1034
;   D = B.low                           = 0
1035
;   X = A.high                          ?
1036
;       A.low is at A_low,y             ?
1037
;       B.low is at B_low,y             ?
1038
;
1039
B_low_zero:
1040
        ldd     A_low,y
1041
        beq     Zero1
1042
        ldx     B_high,y
1043
        beq     Zero2
1044
        bsr     ___mulhi3
1045
Zero1:
1046
        xgdx
1047
Zero2:
1048
        clra
1049
        clrb
1050
        bra     Return
1051
; ----------------
1052
; A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low)
1053
;
1054
; At this step:
1055
;   D = B.low                           != 0
1056
;   X = A.high                          = 0
1057
;       A.low is at A_low,y             ?
1058
;       B.low is at B_low,y             ?
1059
;
1060
A_high_zero:
1061
        ldd     A_low,y         ; A.low
1062
        beq     Zero1
1063
        ldx     B_high,y        ; B.high
1064
        beq     A_low_B_low
1065
        bsr     ___mulhi3
1066
        std     2,y
1067
        bra     B_high_zero     ; Do the (A.low * B.low) and the add.
1068
 
1069
; ----------------
1070
; A.high and B.high are 0 optimize into: (A.low * B.low)
1071
;
1072
; At this step:
1073
;   D = B.high                          = 0
1074
;   X = A.low                           != 0
1075
;       A.low is at A_low,y             != 0
1076
;       B.high is at B_high,y           = 0
1077
;
1078
A_low_B_low:
1079
        ldd     B_low,y                 ; A.low is on the stack
1080
        bsr     __mulhi32
1081
        bra     Return
1082
#endif
1083
#endif
1084
 
1085
#ifdef L_map_data
1086
 
1087
        .sect   .install2,"ax",@progbits
1088
        .globl  __map_data_section
1089
        .globl __data_image
1090
#ifdef mc68hc12
1091
        .globl __data_section_size
1092
#endif
1093
__map_data_section:
1094
#ifdef mc68hc12
1095
        ldx     #__data_image
1096
        ldy     #__data_section_start
1097
        ldd     #__data_section_size
1098
        beq     Done
1099
Loop:
1100
        movb    1,x+,1,y+
1101
        dbne    d,Loop
1102
#else
1103
        ldx     #__data_image
1104
        ldy     #__data_section_start
1105
        bra     Start_map
1106
Loop:
1107
        ldaa    0,x
1108
        staa    0,y
1109
        inx
1110
        iny
1111
Start_map:
1112
        cpx     #__data_image_end
1113
        blo     Loop
1114
#endif
1115
Done:
1116
 
1117
#endif
1118
 
1119
#ifdef L_init_bss
1120
 
1121
        .sect   .install2,"ax",@progbits
1122
        .globl  __init_bss_section
1123
 
1124
__init_bss_section:
1125
        ldd     #__bss_size
1126
        beq     Done
1127
        ldx     #__bss_start
1128
Loop:
1129
#ifdef mc68hc12
1130
        clr     1,x+
1131
        dbne    d,Loop
1132
#else
1133
        clr     0,x
1134
        inx
1135
        subd    #1
1136
        bne     Loop
1137
#endif
1138
Done:
1139
 
1140
#endif
1141
 
1142
#ifdef L_ctor
1143
 
1144
; End of constructor table
1145
        .sect   .install3,"ax",@progbits
1146
        .globl  __do_global_ctors
1147
 
1148
__do_global_ctors:
1149
        ; Start from the end - sizeof(void*)
1150
        ldx     #__CTOR_END__-2
1151
ctors_loop:
1152
        cpx     #__CTOR_LIST__
1153
        blo     ctors_done
1154
        pshx
1155
        ldx     0,x
1156
        jsr     0,x
1157
        pulx
1158
        dex
1159
        dex
1160
        bra     ctors_loop
1161
ctors_done:
1162
 
1163
#endif
1164
 
1165
#ifdef L_dtor
1166
 
1167
        .sect   .fini3,"ax",@progbits
1168
        .globl  __do_global_dtors
1169
 
1170
;;
1171
;; This piece of code is inserted in the _exit() code by the linker.
1172
;;
1173
__do_global_dtors:
1174
        pshb    ; Save exit code
1175
        psha
1176
        ldx     #__DTOR_LIST__
1177
dtors_loop:
1178
        cpx     #__DTOR_END__
1179
        bhs     dtors_done
1180
        pshx
1181
        ldx     0,x
1182
        jsr     0,x
1183
        pulx
1184
        inx
1185
        inx
1186
        bra     dtors_loop
1187
dtors_done:
1188
        pula    ; Restore exit code
1189
        pulb
1190
 
1191
#endif
1192
 
1193
#ifdef L_far_tramp
1194
#ifdef mc68hc12
1195
        .sect   .tramp,"ax",@progbits
1196
        .globl  __far_trampoline
1197
 
1198
;; This is a trampoline used by the linker to invoke a function
1199
;; using rtc to return and being called with jsr/bsr.
1200
;; The trampoline generated is:
1201
;;
1202
;;      foo_tramp:
1203
;;              ldy     #foo
1204
;;              call    __far_trampoline,page(foo)
1205
;;
1206
;; The linker transforms:
1207
;;
1208
;;              jsr     foo
1209
;;
1210
;; into
1211
;;              jsr     foo_tramp
1212
;;
1213
;; The linker generated trampoline and _far_trampoline must be in
1214
;; non-banked memory.
1215
;;
1216
__far_trampoline:
1217
        movb    0,sp, 2,sp      ; Copy page register below the caller's return
1218
        leas    2,sp            ; address.
1219
        jmp     0,y             ; We have a 'call/rtc' stack layout now
1220
                                ; and can jump to the far handler
1221
                                ; (whose memory bank is mapped due to the
1222
                                ; call to the trampoline).
1223
#endif
1224
 
1225
#ifdef mc68hc11
1226
        .sect   .tramp,"ax",@progbits
1227
        .globl __far_trampoline
1228
 
1229
;; Trampoline generated by gcc for 68HC11:
1230
;;
1231
;;      pshb
1232
;;      ldab    #%page(func)
1233
;;      ldy     #%addr(func)
1234
;;      jmp     __far_trampoline
1235
;;
1236
__far_trampoline:
1237
        psha                            ; (2) Save function parameter (high)
1238
        ;; 
1239
        psha                            ; (2)
1240
        ;; 
1241
        pshx                            ; (4)
1242
        tsx                             ; (3)
1243
        ldab    4,x                     ; (4) Restore function parameter (low)
1244
        ldaa    2,x                     ; (4) Get saved page number
1245
        staa    4,x                     ; (4) Save it below return PC
1246
        pulx                            ; (5)
1247
        pula                            ; (3)
1248
        pula                            ; (3) Restore function parameter (high)
1249
        jmp     0,y                     ; (4)
1250
#endif
1251
#endif
1252
 
1253
#ifdef L_call_far
1254
#ifdef mc68hc11
1255
        .sect   .tramp,"ax",@progbits
1256
        .globl __call_a16
1257
        .globl __call_a32
1258
;;
1259
;; The call methods are used for 68HC11 to support memory bank switching.
1260
;; Every far call is redirected to these call methods.  Its purpose is to:
1261
;;
1262
;;  1/ Save the current page on the stack (1 byte to follow 68HC12 call frame)
1263
;;  2/ Install the new page
1264
;;  3/ Jump to the real function
1265
;;
1266
;; The page switching (get/save) is board dependent.  The default provided
1267
;; here does nothing (just create the appropriate call frame).
1268
;;
1269
;; Call sequence (10 bytes, 13 cycles):
1270
;;
1271
;;      ldx #page                       ; (3)
1272
;;      ldy #func                       ; (4)
1273
;;      jsr __call_a16                  ; (6)
1274
;;
1275
;; Call trampoline (11 bytes, 19 cycles):
1276
;;
1277
__call_a16:
1278
        ;; xgdx                         ; (3)
1279
        ;;      ; (3) ldaa _current_page
1280
        psha                            ; (2)
1281
        ;;      ; (4) staa _current_page
1282
        ;; xgdx                         ; (3)
1283
        jmp 0,y                         ; (4)
1284
 
1285
;;
1286
;; Call sequence (10 bytes, 14 cycles):
1287
;;
1288
;;      pshb                            ; (2)
1289
;;      ldab #page                      ; (2)
1290
;;      ldy  #func                      ; (4)
1291
;;      jsr __call_a32                  ; (6)
1292
;;
1293
;; Call trampoline (87 bytes, 57 cycles):
1294
;;
1295
__call_a32:
1296
        pshx                            ; (4)
1297
        psha                            ; (2)
1298
        ;;      ; (3) ldaa _current_page
1299
        psha                            ; (2)
1300
        ;;      ; (4) staa _current_page
1301
        tsx                             ; (3)
1302
        ldab    6,x                     ; (4) Restore function parameter
1303
        ldaa    5,x                     ; (4) Move PC return at good place
1304
        staa    6,x                     ; (4)
1305
        ldaa    4,x                     ; (4)
1306
        staa    5,x                     ; (4)
1307
        pula                            ; (3)
1308
        staa    4,x                     ; (4)
1309
        pula                            ; (3)
1310
        pulx                            ; (5)
1311
        jmp     0,y                     ; (4)
1312
#endif
1313
#endif
1314
 
1315
#ifdef L_return_far
1316
#ifdef mc68hc11
1317
        .sect   .tramp,"ax",@progbits
1318
       .globl __return_void
1319
       .globl __return_16
1320
       .globl __return_32
1321
 
1322
__return_void:
1323
        ;; pulb
1324
        ;;  (Board specific)
1325
        ;; rts
1326
__return_16:
1327
        ;; xgdx
1328
        ;; pulb
1329
        ;;  (Board specific)
1330
        ;; xgdx
1331
        ;; rts
1332
__return_32:
1333
        ;; xgdy
1334
        ;; pulb
1335
        ;;  (Board specific)
1336
        ;; xgdy
1337
        ;; rts
1338
        ins
1339
        rts
1340
#endif
1341
#endif
1342
.Lend:
1343
;-----------------------------------------
1344
; end required gcclib code
1345
;-----------------------------------------

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.