|
|
1.1 root 1: ;; libgcc1 routines for the Hitachi h8/300 cpu.
2: ;; Contributed by Steve Chamberlain.
3: ;; [email protected]
4:
5: /* Copyright (C) 1994 Free Software Foundation, Inc.
6:
7: This file is free software; you can redistribute it and/or modify it
8: under the terms of the GNU General Public License as published by the
9: Free Software Foundation; either version 2, or (at your option) any
10: later version.
11:
12: In addition to the permissions in the GNU General Public License, the
13: Free Software Foundation gives you unlimited permission to link the
14: compiled version of this file with other programs, and to distribute
15: those programs without any restriction coming from the use of this
16: file. (The General Public License restrictions do apply in other
17: respects; for example, they cover modification of the file, and
18: distribution when not linked into another program.)
19:
20: This file is distributed in the hope that it will be useful, but
21: WITHOUT ANY WARRANTY; without even the implied warranty of
22: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23: General Public License for more details.
24:
25: You should have received a copy of the GNU General Public License
26: along with this program; see the file COPYING. If not, write to
1.1.1.2 ! root 27: the Free Software Foundation, 59 Temple Place - Suite 330,
! 28: Boston, MA 02111-1307, USA. */
1.1 root 29:
30: /* As a special exception, if you link this library with other files,
31: some of which are compiled with GCC, to produce an executable,
32: this library does not by itself cause the resulting executable
33: to be covered by the GNU General Public License.
34: This exception does not however invalidate any other reasons why
35: the executable file might be covered by the GNU General Public License. */
36:
37: /* Assembler register definitions. */
38:
39: #define A0 r0
40: #define A0L r0l
41: #define A0H r0h
42:
43: #define A1 r1
44: #define A1L r1l
45: #define A1H r1h
46:
47: #define A2 r2
48: #define A2L r2l
49: #define A2H r2h
50:
51: #define A3 r3
52: #define A3L r3l
53: #define A3H r3h
54:
55: #define S0 r4
56: #define S0L r4l
57: #define S0H r4h
58:
59: #define S1 r5
60: #define S1L r5l
61: #define S1H r5h
62:
63: #define S2 r6
64: #define S2L r6l
65: #define S2H r6h
66:
67: #ifdef __H8300__
68: #define MOVP mov.w /* pointers are 16 bits */
69: #define ADDP add.w
70: #define CMPP cmp.w
71: #define PUSHP push
72: #define POPP pop
73:
74: #define A0P r0
75: #define A1P r1
76: #define A2P r2
77: #define A3P r3
78: #define S0P r4
79: #define S1P r5
80: #define S2P r6
81: #endif
82:
83: #ifdef __H8300H__
84: #define MOVP mov.l /* pointers are 32 bits */
85: #define ADDP add.l
86: #define CMPP cmp.l
87: #define PUSHP push.l
88: #define POPP pop.l
89:
90: #define A0P er0
91: #define A1P er1
92: #define A2P er2
93: #define A3P er3
94: #define S0P er4
95: #define S1P er5
96: #define S2P er6
97:
98: #define A0E e0
99: #define A1E e1
100: #define A2E e2
101: #define A3E e3
102: #endif
103:
104: #ifdef L_cmpsi2
105: #ifdef __H8300__
106: .section .text
107: .align 2
108: .global ___cmpsi2
109: ___cmpsi2:
110: cmp.w A2,A0
111: bne .L2
112: cmp.w A3,A1
113: bne .L2
114: mov.w #1,A0
115: rts
116: .L2:
117: cmp.w A0,A2
118: bgt .L4
119: bne .L3
120: cmp.w A1,A3
121: bls .L3
122: .L4:
123: sub.w A0,A0
124: rts
125: .L3:
126: mov.w #2,A0
127: .L5:
128: rts
129: .end
130: #endif
131: #endif /* L_cmpsi2 */
132:
133: #ifdef L_ucmpsi2
134: #ifdef __H8300__
135: .section .text
136: .align 2
137: .global ___ucmpsi2
138: ___ucmpsi2:
139: cmp.w A2,A0
140: bne .L2
141: cmp.w A3,A1
142: bne .L2
143: mov.w #1,A0
144: rts
145: .L2:
146: cmp.w A0,A2
147: bhi .L4
148: bne .L3
149: cmp.w A1,A3
150: bls .L3
151: .L4:
152: sub.w A0,A0
153: rts
154: .L3:
155: mov.w #2,A0
156: .L5:
157: rts
158: .end
159: #endif
160: #endif /* L_ucmpsi2 */
161:
162: #ifdef L_divhi3
163:
164: ;; HImode divides for the H8/300.
165: ;; We bunch all of this into one object file since there are several
166: ;; "supporting routines".
167:
168: ; general purpose normalize routine
169: ;
170: ; divisor in A0
171: ; dividend in A1
172: ; turns both into +ve numbers, and leaves what the answer sign
173: ; should be in A2L
174:
175: #ifdef __H8300__
176: .section .text
177: .align 2
178: divnorm:
179: mov.b #0x0,A2L
180: or A0H,A0H ; is divisor > 0
181: bge _lab1
182: not A0H ; no - then make it +ve
183: not A0L
184: adds #1,A0
185: xor #0x1,A2L ; and remember that in A2L
186: _lab1: or A1H,A1H ; look at dividend
187: bge _lab2
188: not A1H ; it is -ve, make it positive
189: not A1L
190: adds #1,A1
191: xor #0x1,A2L; and toggle sign of result
192: _lab2: rts
193:
194: ; A0=A0/A1 signed
195:
196: .global ___divhi3
197: ___divhi3:
198: bsr divnorm
199: bsr ___udivhi3
200: negans: or A2L,A2L ; should answer be negative ?
201: beq _lab4
202: not A0H ; yes, so make it so
203: not A0L
204: adds #1,A0
205: _lab4: rts
206:
207: ; A0=A0%A1 signed
208:
209: .global ___modhi3
210: ___modhi3:
211: bsr divnorm
212: bsr ___udivhi3
213: mov A3,A0
214: bra negans
215:
216: ; A0=A0%A1 unsigned
217:
218: .global ___umodhi3
219: ___umodhi3:
220: bsr ___udivhi3
221: mov A3,A0
222: rts
223:
224: ; A0=A0/A1 unsigned
225: ; A3=A0%A1 unsigned
226: ; A2H trashed
227: ; D high 8 bits of denom
228: ; d low 8 bits of denom
229: ; N high 8 bits of num
230: ; n low 8 bits of num
231: ; M high 8 bits of mod
232: ; m low 8 bits of mod
233: ; Q high 8 bits of quot
234: ; q low 8 bits of quot
235: ; P preserve
236:
237: ; The h8 only has a 16/8 bit divide, so we look at the incoming and
238: ; see how to partition up the expression.
239:
240: .global ___udivhi3
241: ___udivhi3:
242: ; A0 A1 A2 A3
243: ; Nn Dd P
244: sub.w A3,A3 ; Nn Dd xP 00
245: or A1H,A1H
246: bne divlongway
247: or A0H,A0H
248: beq _lab6
249:
250: ; we know that D == 0 and N is != 0
251: mov.b A0H,A3L ; Nn Dd xP 0N
252: divxu A1L,A3 ; MQ
253: mov.b A3L,A0H ; Q
254: ; dealt with N, do n
255: _lab6: mov.b A0L,A3L ; n
256: divxu A1L,A3 ; mq
257: mov.b A3L,A0L ; Qq
258: mov.b A3H,A3L ; m
259: mov.b #0x0,A3H ; Qq 0m
260: rts
261:
262: ; D != 0 - which means the denominator is
263: ; loop around to get the result.
264:
265: divlongway:
266: mov.b A0H,A3L ; Nn Dd xP 0N
267: mov.b #0x0,A0H ; high byte of answer has to be zero
268: mov.b #0x8,A2H ; 8
269: div8: add.b A0L,A0L ; n*=2
270: rotxl A3L ; Make remainder bigger
271: rotxl A3H
272: sub.w A1,A3 ; Q-=N
273: bhs setbit ; set a bit ?
274: add.w A1,A3 ; no : too far , Q+=N
275:
276: dec A2H
277: bne div8 ; next bit
278: rts
279:
280: setbit: inc A0L ; do insert bit
281: dec A2H
282: bne div8 ; next bit
283: rts
284:
285: #endif /* __H8300__ */
286: #endif /* L_divhi3 */
287:
288: #ifdef L_divsi3
289:
290: ;; 4 byte integer divides for the H8/300.
291: ;;
292: ;; We have one routine which does all the work and lots of
293: ;; little ones which prepare the args and massage the sign.
294: ;; We bunch all of this into one object file since there are several
295: ;; "supporting routines".
296:
297: #ifdef __H8300H__
298: .h8300h
299: #endif
300:
301: .section .text
302: .align 2
303:
304: ; Put abs SIs into r0/r1 and r2/r3, and leave a 1 in r6l with sign of rest.
305: ; This function is here to keep branch displacements small.
306:
307: #ifdef __H8300__
308:
309: divnorm:
310: mov.b #0,S2L ; keep the sign in S2
311: mov.b A0H,A0H ; is the numerator -ve
312: bge postive
313:
314: ; negate arg
315: not A0H
316: not A1H
317: not A0L
318: not A1L
319:
320: add #1,A1L
321: addx #0,A1H
322: addx #0,A0H
323: addx #0,A0L
324:
325: mov.b #1,S2L ; the sign will be -ve
326: postive:
327: mov.b A2H,A2H ; is the denominator -ve
328: bge postive2
329: not A2L
330: not A2H
331: not A3L
332: not A3H
333: add.b #1,A3L
334: addx #0,A3H
335: addx #0,A2L
336: addx #0,A2H
337: xor #1,S2L ; toggle result sign
338: postive2:
339: rts
340:
341: #else /* __H8300H__ */
342:
343: divnorm:
344: mov.b #0,S2L ; keep the sign in S2
345: mov.l A0P,A0P ; is the numerator -ve
346: bge postive
347:
348: neg.l A0P ; negate arg
349: mov.b #1,S2L ; the sign will be -ve
350:
351: postive:
352: mov.l A1P,A1P ; is the denominator -ve
353: bge postive2
354:
355: neg.l A1P ; negate arg
356: xor.b #1,S2L ; toggle result sign
357:
358: postive2:
359: rts
360:
361: #endif
362:
363: ; numerator in A0/A1
364: ; denominator in A2/A3
365: .global ___modsi3
366: ___modsi3:
367: PUSHP S2P
368: PUSHP S0P
369: PUSHP S1P
370:
371: bsr divnorm
372: bsr divmodsi4
373: #ifdef __H8300__
374: mov S0,A0
375: mov S1,A1
376: #else
377: mov.l S0P,A0P
378: #endif
379: bra exitdiv
380:
381: .global ___udivsi3
382: ___udivsi3:
383: PUSHP S2P
384: PUSHP S0P
385: PUSHP S1P
386: mov.b #0,S2L ; keep sign low
387: bsr divmodsi4
388: bra exitdiv
389:
390: .global ___umodsi3
391: ___umodsi3:
392: PUSHP S2P
393: PUSHP S0P
394: PUSHP S1P
395: mov.b #0,S2L ; keep sign low
396: bsr divmodsi4
397: #ifdef __H8300__
398: mov S0,A0
399: mov S1,A1
400: #else
401: mov.l S0P,A0P
402: #endif
403: bra exitdiv
404:
405: .global ___divsi3
406: ___divsi3:
407: PUSHP S2P
408: PUSHP S0P
409: PUSHP S1P
410: jsr divnorm
411: jsr divmodsi4
412:
413: ; examine what the sign should be
414: exitdiv:
415: POPP S1P
416: POPP S0P
417:
418: or S2L,S2L
419: beq reti
420:
421: ; should be -ve
422: #ifdef __H8300__
423: not A0H
424: not A1H
425: not A0L
426: not A1L
427:
428: add #1,A1L
429: addx #0,A1H
430: addx #0,A0H
431: addx #0,A0L
432: #else /* __H8300H__ */
433: neg.l A0P
434: #endif
435:
436: reti:
437: POPP S2P
438: rts
439:
440: ; takes A0/A1 numerator (A0P for 300h)
441: ; A2/A3 denominator (A1P for 300h)
442: ; returns A0/A1 quotient (A0P for 300h)
443: ; S0/S1 remainder (S0P for 300h)
444: ; trashes S2
445:
446: #ifdef __H8300__
447:
448: divmodsi4:
449: sub.w S0,S0 ; zero play area
450: mov.w S0,S1
451: mov.b A2H,S2H
452: or A2L,S2H
453: or A3H,S2H
454: bne DenHighZero
455: mov.b A0H,A0H
456: bne NumByte0Zero
457: mov.b A0L,A0L
458: bne NumByte1Zero
459: mov.b A1H,A1H
460: bne NumByte2Zero
461: bra NumByte3Zero
462: NumByte0Zero:
463: mov.b A0H,S1L
464: divxu A3L,S1
465: mov.b S1L,A0H
466: NumByte1Zero:
467: mov.b A0L,S1L
468: divxu A3L,S1
469: mov.b S1L,A0L
470: NumByte2Zero:
471: mov.b A1H,S1L
472: divxu A3L,S1
473: mov.b S1L,A1H
474: NumByte3Zero:
475: mov.b A1L,S1L
476: divxu A3L,S1
477: mov.b S1L,A1L
478:
479: mov.b S1H,S1L
480: mov.b #0x0,S1H
481: rts
482:
483: ; have to do the divide by shift and test
484: DenHighZero:
485: mov.b A0H,S1L
486: mov.b A0L,A0H
487: mov.b A1H,A0L
488: mov.b A1L,A1H
489:
490: mov.b #0,A1L
491: mov.b #24,S2H ; only do 24 iterations
492:
493: nextbit:
494: add.w A1,A1 ; double the answer guess
495: rotxl A0L
496: rotxl A0H
497:
498: rotxl S1L ; double remainder
499: rotxl S1H
500: rotxl S0L
501: rotxl S0H
502: sub.w A3,S1 ; does it all fit
503: subx A2L,S0L
504: subx A2H,S0H
505: bhs setone
506:
507: add.w A3,S1 ; no, restore mistake
508: addx A2L,S0L
509: addx A2H,S0H
510:
511: dec S2H
512: bne nextbit
513: rts
514:
515: setone:
516: inc A1L
517: dec S2H
518: bne nextbit
519: rts
520:
521: #else /* __H8300H__ */
522:
523: divmodsi4:
524: sub.l S0P,S0P ; zero play area
525: mov.w A1E,A1E ; denominator top word 0?
526: bne DenHighZero
527:
528: ; do it the easy way, see page 107 in manual
529: mov.w A0E,A2
530: extu.l A2P
531: divxu.w A1,A2P
532: mov.w A2E,A0E
533: divxu.w A1,A0P
534: mov.w A0E,S0
535: mov.w A2,A0E
536: extu.l S0P
537: rts
538:
539: DenHighZero:
540: mov.w A0E,A2
541: mov.b A2H,S0L
542: mov.b A2L,A2H
543: mov.b A0H,A2L
544: mov.w A2,A0E
545: mov.b A0L,A0H
546: mov.b #0,A0L
547: mov.b #24,S2H ; only do 24 iterations
548:
549: nextbit:
550: shll.l A0P ; double the answer guess
551: rotxl.l S0P ; double remainder
552: sub.l A1P,S0P ; does it all fit?
553: bhs setone
554:
555: add.l A1P,S0P ; no, restore mistake
556: dec S2H
557: bne nextbit
558: rts
559:
560: setone:
561: inc A0L
562: dec S2H
563: bne nextbit
564: rts
565:
566: #endif
567: #endif /* L_divsi3 */
568:
569: #ifdef L_mulhi3
570:
571: ;; HImode multiply.
572: ; The h8 only has an 8*8->16 multiply.
573: ; The answer is the same as:
574: ;
575: ; product = (srca.l * srcb.l) + ((srca.h * srcb.l) + (srcb.h * srca.l)) * 256
576: ; (we can ignore A1.h * A0.h cause that will all off the top)
577: ; A0 in
578: ; A1 in
579: ; A0 answer
580:
581: #ifdef __H8300__
582: .section .text
583: .align 2
584: .global ___mulhi3
585: ___mulhi3:
586: mov.b A1L,A2L ; A2l gets srcb.l
587: mulxu A0L,A2 ; A2 gets first sub product
588:
589: mov.b A0H,A3L ; prepare for
590: mulxu A1L,A3 ; second sub product
591:
592: add.b A3L,A2H ; sum first two terms
593:
594: mov.b A1H,A3L ; third sub product
595: mulxu A0L,A3
596:
597: add.b A3L,A2H ; almost there
598: mov.w A2,A0 ; that is
599: rts
600:
601: #endif
602: #endif /* L_mulhi3 */
603:
604: #ifdef L_mulsi3
605:
606: ;; SImode multiply.
607: ;;
608: ;; I think that shift and add may be sufficient for this. Using the
609: ;; supplied 8x8->16 would need 10 ops of 14 cycles each + overhead. This way
610: ;; the inner loop uses maybe 20 cycles + overhead, but terminates
611: ;; quickly on small args.
612: ;;
613: ;; A0/A1 src_a
614: ;; A2/A3 src_b
615: ;;
616: ;; while (a)
617: ;; {
618: ;; if (a & 1)
619: ;; r += b;
620: ;; a >>= 1;
621: ;; b <<= 1;
622: ;; }
623:
624: .section .text
625: .align 2
626:
627: #ifdef __H8300__
628:
629: .global ___mulsi3
630: ___mulsi3:
631: PUSHP S0P
632: PUSHP S1P
633: PUSHP S2P
634:
635: sub.w S0,S0
636: sub.w S1,S1
637:
638: ; while (a)
639: _top: mov.w A0,A0
640: bne _more
641: mov.w A1,A1
642: beq _done
643: _more: ; if (a & 1)
644: bld #0,A1L
645: bcc _nobit
646: ; r += b
647: add.w A3,S1
648: addx A2L,S0L
649: addx A2H,S0H
650: _nobit:
651: ; a >>= 1
652: shlr A0H
653: rotxr A0L
654: rotxr A1H
655: rotxr A1L
656:
657: ; b <<= 1
658: add.w A3,A3
659: addx A2L,A2L
660: addx A2H,A2H
661: bra _top
662:
663: _done:
664: mov.w S0,A0
665: mov.w S1,A1
666: POPP S2P
667: POPP S1P
668: POPP S0P
669: rts
670:
671: #else /* __H8300H__ */
672:
673: .h8300h
674:
675: .global ___mulsi3
676: ___mulsi3:
677: sub.l A2P,A2P
678:
679: ; while (a)
680: _top: mov.l A0P,A0P
681: beq _done
682:
683: ; if (a & 1)
684: bld #0,A0L
685: bcc _nobit
686:
687: ; r += b
688: add.l A1P,A2P
689:
690: _nobit:
691: ; a >>= 1
692: shlr.l A0P
693:
694: ; b <<= 1
695: shll.l A1P
696: bra _top
697:
698: _done:
699: mov.l A2P,A0P
700: rts
701:
702: #endif
703: #endif /* L_mulsi3 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.