1 ;; libgcc1 routines for the Hitachi h8/300 cpu.
2 ;; Contributed by Steve Chamberlain.
4 ;; This file is in the public domain.
6 /* Assembler register definitions. */
37 #define MOVP mov.w /* pointers are 16 bits */
53 #define MOVP mov.l /* pointers are 32 bits */
100 #endif /* L_cmpsi2 */
129 #endif /* L_ucmpsi2 */
133 ;; HImode divides for the H8/300.
134 ;; We bunch all of this into one object file since there are several
135 ;; "supporting routines".
137 ; general purpose normalize routine
141 ; turns both into +ve numbers, and leaves what the answer sign
149 or A0H,A0H ; is divisor > 0
151 not A0H ; no - then make it +ve
154 xor #0x1,A2L ; and remember that in A2L
155 _lab1: or A1H,A1H ; look at dividend
157 not A1H ; it is -ve, make it positive
160 xor #0x1,A2L; and toggle sign of result
169 negans: or A2L,A2L ; should answer be negative ?
171 not A0H ; yes, so make it so
196 ; D high 8 bits of denom
197 ; d low 8 bits of denom
198 ; N high 8 bits of num
199 ; n low 8 bits of num
200 ; M high 8 bits of mod
201 ; m low 8 bits of mod
202 ; Q high 8 bits of quot
203 ; q low 8 bits of quot
206 ; The h8 only has a 16/8 bit divide, so we look at the incoming and
207 ; see how to partition up the expression.
213 sub.w A3,A3 ; Nn Dd xP 00
219 ; we know that D == 0 and N is != 0
220 mov.b A0H,A3L ; Nn Dd xP 0N
224 _lab6: mov.b A0L,A3L ; n
228 mov.b #0x0,A3H ; Qq 0m
231 ; D != 0 - which means the denominator is
232 ; loop around to get the result.
235 mov.b A0H,A3L ; Nn Dd xP 0N
236 mov.b #0x0,A0H ; high byte of answer has to be zero
238 div8: add.b A0L,A0L ; n*=2
239 rotxl A3L ; Make remainder bigger
242 bhs setbit ; set a bit ?
243 add.w A1,A3 ; no : too far , Q+=N
249 setbit: inc A0L ; do insert bit
254 #endif /* __H8300__ */
255 #endif /* L_divhi3 */
259 ;; 4 byte integer divides for the H8/300.
261 ;; We have one routine which does all the work and lots of
262 ;; little ones which prepare the args and massage the sign.
263 ;; We bunch all of this into one object file since there are several
264 ;; "supporting routines".
273 ; Put abs SIs into r0/r1 and r2/r3, and leave a 1 in r6l with sign of rest.
274 ; This function is here to keep branch displacements small.
279 mov.b #0,S2L ; keep the sign in S2
280 mov.b A0H,A0H ; is the numerator -ve
294 mov.b #1,S2L ; the sign will be -ve
296 mov.b A2H,A2H ; is the denominator -ve
306 xor #1,S2L ; toggle result sign
310 #else /* __H8300H__ */
313 mov.b #0,S2L ; keep the sign in S2
314 mov.l A0P,A0P ; is the numerator -ve
317 neg.l A0P ; negate arg
318 mov.b #1,S2L ; the sign will be -ve
321 mov.l A1P,A1P ; is the denominator -ve
324 neg.l A1P ; negate arg
325 xor.b #1,S2L ; toggle result sign
333 ; denominator in A2/A3
355 mov.b #0,S2L ; keep sign low
364 mov.b #0,S2L ; keep sign low
382 ; examine what the sign should be
401 #else /* __H8300H__ */
409 ; takes A0/A1 numerator (A0P for 300h)
410 ; A2/A3 denominator (A1P for 300h)
411 ; returns A0/A1 quotient (A0P for 300h)
412 ; S0/S1 remainder (S0P for 300h)
418 sub.w S0,S0 ; zero play area
452 ; have to do the divide by shift and test
460 mov.b #24,S2H ; only do 24 iterations
463 add.w A1,A1 ; double the answer guess
467 rotxl S1L ; double remainder
471 sub.w A3,S1 ; does it all fit
476 add.w A3,S1 ; no, restore mistake
490 #else /* __H8300H__ */
493 sub.l S0P,S0P ; zero play area
494 mov.w A1E,A1E ; denominator top word 0?
497 ; do it the easy way, see page 107 in manual
516 mov.b #24,S2H ; only do 24 iterations
519 shll.l A0P ; double the answer guess
520 rotxl.l S0P ; double remainder
521 sub.l A1P,S0P ; does it all fit?
524 add.l A1P,S0P ; no, restore mistake
536 #endif /* L_divsi3 */
541 ; The h8 only has an 8*8->16 multiply.
542 ; The answer is the same as:
544 ; product = (srca.l * srcb.l) + ((srca.h * srcb.l) + (srcb.h * srca.l)) * 256
545 ; (we can ignore A1.h * A0.h cause that will all off the top)
555 mov.b A1L,A2L ; A2l gets srcb.l
556 mulxu A0L,A2 ; A2 gets first sub product
558 mov.b A0H,A3L ; prepare for
559 mulxu A1L,A3 ; second sub product
561 add.b A3L,A2H ; sum first two terms
563 mov.b A1H,A3L ; third sub product
566 add.b A3L,A2H ; almost there
567 mov.w A2,A0 ; that is
571 #endif /* L_mulhi3 */
577 ;; I think that shift and add may be sufficient for this. Using the
578 ;; supplied 8x8->16 would need 10 ops of 14 cycles each + overhead. This way
579 ;; the inner loop uses maybe 20 cycles + overhead, but terminates
580 ;; quickly on small args.
640 #else /* __H8300H__ */
672 #endif /* L_mulsi3 */