Initial revision
From-SVN: r7726
This commit is contained in:
parent
159c2aedc6
commit
26731a9e43
1 changed files with 672 additions and 0 deletions
672
gcc/config/h8300/lib1funcs.asm
Normal file
672
gcc/config/h8300/lib1funcs.asm
Normal file
|
@ -0,0 +1,672 @@
|
|||
;; libgcc1 routines for the Hitachi h8/300 cpu.
|
||||
;; Contributed by Steve Chamberlain.
|
||||
;; sac@cygnus.com
|
||||
;; This file is in the public domain.
|
||||
|
||||
/* Assembler register definitions. */
|
||||
|
||||
#define A0 r0
|
||||
#define A0L r0l
|
||||
#define A0H r0h
|
||||
|
||||
#define A1 r1
|
||||
#define A1L r1l
|
||||
#define A1H r1h
|
||||
|
||||
#define A2 r2
|
||||
#define A2L r2l
|
||||
#define A2H r2h
|
||||
|
||||
#define A3 r3
|
||||
#define A3L r3l
|
||||
#define A3H r3h
|
||||
|
||||
#define S0 r4
|
||||
#define S0L r4l
|
||||
#define S0H r4h
|
||||
|
||||
#define S1 r5
|
||||
#define S1L r5l
|
||||
#define S1H r5h
|
||||
|
||||
#define S2 r6
|
||||
#define S2L r6l
|
||||
#define S2H r6h
|
||||
|
||||
#ifdef __H8300__
|
||||
#define MOVP mov.w /* pointers are 16 bits */
|
||||
#define ADDP add.w
|
||||
#define CMPP cmp.w
|
||||
#define PUSHP push
|
||||
#define POPP pop
|
||||
|
||||
#define A0P r0
|
||||
#define A1P r1
|
||||
#define A2P r2
|
||||
#define A3P r3
|
||||
#define S0P r4
|
||||
#define S1P r5
|
||||
#define S2P r6
|
||||
#endif
|
||||
|
||||
#ifdef __H8300H__
|
||||
#define MOVP mov.l /* pointers are 32 bits */
|
||||
#define ADDP add.l
|
||||
#define CMPP cmp.l
|
||||
#define PUSHP push.l
|
||||
#define POPP pop.l
|
||||
|
||||
#define A0P er0
|
||||
#define A1P er1
|
||||
#define A2P er2
|
||||
#define A3P er3
|
||||
#define S0P er4
|
||||
#define S1P er5
|
||||
#define S2P er6
|
||||
|
||||
#define A0E e0
|
||||
#define A1E e1
|
||||
#define A2E e2
|
||||
#define A3E e3
|
||||
#endif
|
||||
|
||||
#ifdef L_cmpsi2
|
||||
#ifdef __H8300__
|
||||
.section .text
|
||||
.align 2
|
||||
.global ___cmpsi2
|
||||
___cmpsi2:
|
||||
cmp.w A2,A0
|
||||
bne .L2
|
||||
cmp.w A3,A1
|
||||
bne .L2
|
||||
mov.w #1,A0
|
||||
rts
|
||||
.L2:
|
||||
cmp.w A0,A2
|
||||
bgt .L4
|
||||
bne .L3
|
||||
cmp.w A1,A3
|
||||
bls .L3
|
||||
.L4:
|
||||
sub.w A0,A0
|
||||
rts
|
||||
.L3:
|
||||
mov.w #2,A0
|
||||
.L5:
|
||||
rts
|
||||
.end
|
||||
#endif
|
||||
#endif /* L_cmpsi2 */
|
||||
|
||||
#ifdef L_ucmpsi2
|
||||
#ifdef __H8300__
|
||||
.section .text
|
||||
.align 2
|
||||
.global ___ucmpsi2
|
||||
___ucmpsi2:
|
||||
cmp.w A2,A0
|
||||
bne .L2
|
||||
cmp.w A3,A1
|
||||
bne .L2
|
||||
mov.w #1,A0
|
||||
rts
|
||||
.L2:
|
||||
cmp.w A0,A2
|
||||
bhi .L4
|
||||
bne .L3
|
||||
cmp.w A1,A3
|
||||
bls .L3
|
||||
.L4:
|
||||
sub.w A0,A0
|
||||
rts
|
||||
.L3:
|
||||
mov.w #2,A0
|
||||
.L5:
|
||||
rts
|
||||
.end
|
||||
#endif
|
||||
#endif /* L_ucmpsi2 */
|
||||
|
||||
#ifdef L_divhi3
|
||||
|
||||
;; HImode divides for the H8/300.
|
||||
;; We bunch all of this into one object file since there are several
|
||||
;; "supporting routines".
|
||||
|
||||
; general purpose normalize routine
|
||||
;
|
||||
; divisor in A0
|
||||
; dividend in A1
|
||||
; turns both into +ve numbers, and leaves what the answer sign
|
||||
; should be in A2L
|
||||
|
||||
#ifdef __H8300__
|
||||
.section .text
|
||||
.align 2
|
||||
divnorm:
|
||||
mov.b #0x0,A2L
|
||||
or A0H,A0H ; is divisor > 0
|
||||
bge _lab1
|
||||
not A0H ; no - then make it +ve
|
||||
not A0L
|
||||
adds #1,A0
|
||||
xor #0x1,A2L ; and remember that in A2L
|
||||
_lab1: or A1H,A1H ; look at dividend
|
||||
bge _lab2
|
||||
not A1H ; it is -ve, make it positive
|
||||
not A1L
|
||||
adds #1,A1
|
||||
xor #0x1,A2L; and toggle sign of result
|
||||
_lab2: rts
|
||||
|
||||
; A0=A0/A1 signed
|
||||
|
||||
.global ___divhi3
|
||||
___divhi3:
|
||||
bsr divnorm
|
||||
bsr ___udivhi3
|
||||
negans: or A2L,A2L ; should answer be negative ?
|
||||
beq _lab4
|
||||
not A0H ; yes, so make it so
|
||||
not A0L
|
||||
adds #1,A0
|
||||
_lab4: rts
|
||||
|
||||
; A0=A0%A1 signed
|
||||
|
||||
.global ___modhi3
|
||||
___modhi3:
|
||||
bsr divnorm
|
||||
bsr ___udivhi3
|
||||
mov A3,A0
|
||||
bra negans
|
||||
|
||||
; A0=A0%A1 unsigned
|
||||
|
||||
.global ___umodhi3
|
||||
___umodhi3:
|
||||
bsr ___udivhi3
|
||||
mov A3,A0
|
||||
rts
|
||||
|
||||
; A0=A0/A1 unsigned
|
||||
; A3=A0%A1 unsigned
|
||||
; A2H trashed
|
||||
; D high 8 bits of denom
|
||||
; d low 8 bits of denom
|
||||
; N high 8 bits of num
|
||||
; n low 8 bits of num
|
||||
; M high 8 bits of mod
|
||||
; m low 8 bits of mod
|
||||
; Q high 8 bits of quot
|
||||
; q low 8 bits of quot
|
||||
; P preserve
|
||||
|
||||
; The h8 only has a 16/8 bit divide, so we look at the incoming and
|
||||
; see how to partition up the expression.
|
||||
|
||||
.global ___udivhi3
|
||||
___udivhi3:
|
||||
; A0 A1 A2 A3
|
||||
; Nn Dd P
|
||||
sub.w A3,A3 ; Nn Dd xP 00
|
||||
or A1H,A1H
|
||||
bne divlongway
|
||||
or A0H,A0H
|
||||
beq _lab6
|
||||
|
||||
; we know that D == 0 and N is != 0
|
||||
mov.b A0H,A3L ; Nn Dd xP 0N
|
||||
divxu A1L,A3 ; MQ
|
||||
mov.b A3L,A0H ; Q
|
||||
; dealt with N, do n
|
||||
_lab6: mov.b A0L,A3L ; n
|
||||
divxu A1L,A3 ; mq
|
||||
mov.b A3L,A0L ; Qq
|
||||
mov.b A3H,A3L ; m
|
||||
mov.b #0x0,A3H ; Qq 0m
|
||||
rts
|
||||
|
||||
; D != 0 - which means the denominator is
|
||||
; loop around to get the result.
|
||||
|
||||
divlongway:
|
||||
mov.b A0H,A3L ; Nn Dd xP 0N
|
||||
mov.b #0x0,A0H ; high byte of answer has to be zero
|
||||
mov.b #0x8,A2H ; 8
|
||||
div8: add.b A0L,A0L ; n*=2
|
||||
rotxl A3L ; Make remainder bigger
|
||||
rotxl A3H
|
||||
sub.w A1,A3 ; Q-=N
|
||||
bhs setbit ; set a bit ?
|
||||
add.w A1,A3 ; no : too far , Q+=N
|
||||
|
||||
dec A2H
|
||||
bne div8 ; next bit
|
||||
rts
|
||||
|
||||
setbit: inc A0L ; do insert bit
|
||||
dec A2H
|
||||
bne div8 ; next bit
|
||||
rts
|
||||
|
||||
#endif /* __H8300__ */
|
||||
#endif /* L_divhi3 */
|
||||
|
||||
#ifdef L_divsi3
|
||||
|
||||
;; 4 byte integer divides for the H8/300.
|
||||
;;
|
||||
;; We have one routine which does all the work and lots of
|
||||
;; little ones which prepare the args and massage the sign.
|
||||
;; We bunch all of this into one object file since there are several
|
||||
;; "supporting routines".
|
||||
|
||||
#ifdef __H8300H__
|
||||
.h8300h
|
||||
#endif
|
||||
|
||||
.section .text
|
||||
.align 2
|
||||
|
||||
; Put abs SIs into r0/r1 and r2/r3, and leave a 1 in r6l with sign of rest.
|
||||
; This function is here to keep branch displacements small.
|
||||
|
||||
#ifdef __H8300__
|
||||
|
||||
divnorm:
|
||||
mov.b #0,S2L ; keep the sign in S2
|
||||
mov.b A0H,A0H ; is the numerator -ve
|
||||
bge postive
|
||||
|
||||
; negate arg
|
||||
not A0H
|
||||
not A1H
|
||||
not A0L
|
||||
not A1L
|
||||
|
||||
add #1,A1L
|
||||
addx #0,A1H
|
||||
addx #0,A0H
|
||||
addx #0,A0L
|
||||
|
||||
mov.b #1,S2L ; the sign will be -ve
|
||||
postive:
|
||||
mov.b A2H,A2H ; is the denominator -ve
|
||||
bge postive2
|
||||
not A2L
|
||||
not A2H
|
||||
not A3L
|
||||
not A3H
|
||||
add.b #1,A3L
|
||||
addx #0,A3H
|
||||
addx #0,A2L
|
||||
addx #0,A2H
|
||||
xor #1,S2L ; toggle result sign
|
||||
postive2:
|
||||
rts
|
||||
|
||||
#else /* __H8300H__ */
|
||||
|
||||
divnorm:
|
||||
mov.b #0,S2L ; keep the sign in S2
|
||||
mov.l A0P,A0P ; is the numerator -ve
|
||||
bge postive
|
||||
|
||||
neg.l A0P ; negate arg
|
||||
mov.b #1,S2L ; the sign will be -ve
|
||||
|
||||
postive:
|
||||
mov.l A1P,A1P ; is the denominator -ve
|
||||
bge postive2
|
||||
|
||||
neg.l A1P ; negate arg
|
||||
xor.b #1,S2L ; toggle result sign
|
||||
|
||||
postive2:
|
||||
rts
|
||||
|
||||
#endif
|
||||
|
||||
; numerator in A0/A1
|
||||
; denominator in A2/A3
|
||||
.global ___modsi3
|
||||
___modsi3:
|
||||
PUSHP S2P
|
||||
PUSHP S0P
|
||||
PUSHP S1P
|
||||
|
||||
bsr divnorm
|
||||
bsr divmodsi4
|
||||
#ifdef __H8300__
|
||||
mov S0,A0
|
||||
mov S1,A1
|
||||
#else
|
||||
mov.l S0P,A0P
|
||||
#endif
|
||||
bra exitdiv
|
||||
|
||||
.global ___udivsi3
|
||||
___udivsi3:
|
||||
PUSHP S2P
|
||||
PUSHP S0P
|
||||
PUSHP S1P
|
||||
mov.b #0,S2L ; keep sign low
|
||||
bsr divmodsi4
|
||||
bra exitdiv
|
||||
|
||||
.global ___umodsi3
|
||||
___umodsi3:
|
||||
PUSHP S2P
|
||||
PUSHP S0P
|
||||
PUSHP S1P
|
||||
mov.b #0,S2L ; keep sign low
|
||||
bsr divmodsi4
|
||||
#ifdef __H8300__
|
||||
mov S0,A0
|
||||
mov S1,A1
|
||||
#else
|
||||
mov.l S0P,A0P
|
||||
#endif
|
||||
bra exitdiv
|
||||
|
||||
.global ___divsi3
|
||||
___divsi3:
|
||||
PUSHP S2P
|
||||
PUSHP S0P
|
||||
PUSHP S1P
|
||||
jsr divnorm
|
||||
jsr divmodsi4
|
||||
|
||||
; examine what the sign should be
|
||||
exitdiv:
|
||||
POPP S1P
|
||||
POPP S0P
|
||||
|
||||
or S2L,S2L
|
||||
beq reti
|
||||
|
||||
; should be -ve
|
||||
#ifdef __H8300__
|
||||
not A0H
|
||||
not A1H
|
||||
not A0L
|
||||
not A1L
|
||||
|
||||
add #1,A1L
|
||||
addx #0,A1H
|
||||
addx #0,A0H
|
||||
addx #0,A0L
|
||||
#else /* __H8300H__ */
|
||||
neg.l A0P
|
||||
#endif
|
||||
|
||||
reti:
|
||||
POPP S2P
|
||||
rts
|
||||
|
||||
; takes A0/A1 numerator (A0P for 300h)
|
||||
; A2/A3 denominator (A1P for 300h)
|
||||
; returns A0/A1 quotient (A0P for 300h)
|
||||
; S0/S1 remainder (S0P for 300h)
|
||||
; trashes S2
|
||||
|
||||
#ifdef __H8300__
|
||||
|
||||
divmodsi4:
|
||||
sub.w S0,S0 ; zero play area
|
||||
mov.w S0,S1
|
||||
mov.b A2H,S2H
|
||||
or A2L,S2H
|
||||
or A3H,S2H
|
||||
bne DenHighZero
|
||||
mov.b A0H,A0H
|
||||
bne NumByte0Zero
|
||||
mov.b A0L,A0L
|
||||
bne NumByte1Zero
|
||||
mov.b A1H,A1H
|
||||
bne NumByte2Zero
|
||||
bra NumByte3Zero
|
||||
NumByte0Zero:
|
||||
mov.b A0H,S1L
|
||||
divxu A3L,S1
|
||||
mov.b S1L,A0H
|
||||
NumByte1Zero:
|
||||
mov.b A0L,S1L
|
||||
divxu A3L,S1
|
||||
mov.b S1L,A0L
|
||||
NumByte2Zero:
|
||||
mov.b A1H,S1L
|
||||
divxu A3L,S1
|
||||
mov.b S1L,A1H
|
||||
NumByte3Zero:
|
||||
mov.b A1L,S1L
|
||||
divxu A3L,S1
|
||||
mov.b S1L,A1L
|
||||
|
||||
mov.b S1H,S1L
|
||||
mov.b #0x0,S1H
|
||||
rts
|
||||
|
||||
; have to do the divide by shift and test
|
||||
DenHighZero:
|
||||
mov.b A0H,S1L
|
||||
mov.b A0L,A0H
|
||||
mov.b A1H,A0L
|
||||
mov.b A1L,A1H
|
||||
|
||||
mov.b #0,A1L
|
||||
mov.b #24,S2H ; only do 24 iterations
|
||||
|
||||
nextbit:
|
||||
add.w A1,A1 ; double the answer guess
|
||||
rotxl A0L
|
||||
rotxl A0H
|
||||
|
||||
rotxl S1L ; double remainder
|
||||
rotxl S1H
|
||||
rotxl S0L
|
||||
rotxl S0H
|
||||
sub.w A3,S1 ; does it all fit
|
||||
subx A2L,S0L
|
||||
subx A2H,S0H
|
||||
bhs setone
|
||||
|
||||
add.w A3,S1 ; no, restore mistake
|
||||
addx A2L,S0L
|
||||
addx A2H,S0H
|
||||
|
||||
dec S2H
|
||||
bne nextbit
|
||||
rts
|
||||
|
||||
setone:
|
||||
inc A1L
|
||||
dec S2H
|
||||
bne nextbit
|
||||
rts
|
||||
|
||||
#else /* __H8300H__ */
|
||||
|
||||
divmodsi4:
|
||||
sub.l S0P,S0P ; zero play area
|
||||
mov.w A1E,A1E ; denominator top word 0?
|
||||
bne DenHighZero
|
||||
|
||||
; do it the easy way, see page 107 in manual
|
||||
mov.w A0E,A2
|
||||
extu.l A2P
|
||||
divxu.w A1,A2P
|
||||
mov.w A2E,A0E
|
||||
divxu.w A1,A0P
|
||||
mov.w A0E,S0
|
||||
mov.w A2,A0E
|
||||
extu.l S0P
|
||||
rts
|
||||
|
||||
DenHighZero:
|
||||
mov.w A0E,A2
|
||||
mov.b A2H,S0L
|
||||
mov.b A2L,A2H
|
||||
mov.b A0H,A2L
|
||||
mov.w A2,A0E
|
||||
mov.b A0L,A0H
|
||||
mov.b #0,A0L
|
||||
mov.b #24,S2H ; only do 24 iterations
|
||||
|
||||
nextbit:
|
||||
shll.l A0P ; double the answer guess
|
||||
rotxl.l S0P ; double remainder
|
||||
sub.l A1P,S0P ; does it all fit?
|
||||
bhs setone
|
||||
|
||||
add.l A1P,S0P ; no, restore mistake
|
||||
dec S2H
|
||||
bne nextbit
|
||||
rts
|
||||
|
||||
setone:
|
||||
inc A0L
|
||||
dec S2H
|
||||
bne nextbit
|
||||
rts
|
||||
|
||||
#endif
|
||||
#endif /* L_divsi3 */
|
||||
|
||||
#ifdef L_mulhi3
|
||||
|
||||
;; HImode multiply.
|
||||
; The h8 only has an 8*8->16 multiply.
|
||||
; The answer is the same as:
|
||||
;
|
||||
; product = (srca.l * srcb.l) + ((srca.h * srcb.l) + (srcb.h * srca.l)) * 256
|
||||
; (we can ignore A1.h * A0.h cause that will all off the top)
|
||||
; A0 in
|
||||
; A1 in
|
||||
; A0 answer
|
||||
|
||||
#ifdef __H8300__
|
||||
.section .text
|
||||
.align 2
|
||||
.global ___mulhi3
|
||||
___mulhi3:
|
||||
mov.b A1L,A2L ; A2l gets srcb.l
|
||||
mulxu A0L,A2 ; A2 gets first sub product
|
||||
|
||||
mov.b A0H,A3L ; prepare for
|
||||
mulxu A1L,A3 ; second sub product
|
||||
|
||||
add.b A3L,A2H ; sum first two terms
|
||||
|
||||
mov.b A1H,A3L ; third sub product
|
||||
mulxu A0L,A3
|
||||
|
||||
add.b A3L,A2H ; almost there
|
||||
mov.w A2,A0 ; that is
|
||||
rts
|
||||
|
||||
#endif
|
||||
#endif /* L_mulhi3 */
|
||||
|
||||
#ifdef L_mulsi3
|
||||
|
||||
;; SImode multiply.
|
||||
;;
|
||||
;; I think that shift and add may be sufficient for this. Using the
|
||||
;; supplied 8x8->16 would need 10 ops of 14 cycles each + overhead. This way
|
||||
;; the inner loop uses maybe 20 cycles + overhead, but terminates
|
||||
;; quickly on small args.
|
||||
;;
|
||||
;; A0/A1 src_a
|
||||
;; A2/A3 src_b
|
||||
;;
|
||||
;; while (a)
|
||||
;; {
|
||||
;; if (a & 1)
|
||||
;; r += b;
|
||||
;; a >>= 1;
|
||||
;; b <<= 1;
|
||||
;; }
|
||||
|
||||
.section .text
|
||||
.align 2
|
||||
|
||||
#ifdef __H8300__
|
||||
|
||||
.global ___mulsi3
|
||||
___mulsi3:
|
||||
PUSHP S0P
|
||||
PUSHP S1P
|
||||
PUSHP S2P
|
||||
|
||||
sub.w S0,S0
|
||||
sub.w S1,S1
|
||||
|
||||
; while (a)
|
||||
_top: mov.w A0,A0
|
||||
bne _more
|
||||
mov.w A1,A1
|
||||
beq _done
|
||||
_more: ; if (a & 1)
|
||||
bld #0,A1L
|
||||
bcc _nobit
|
||||
; r += b
|
||||
add.w A3,S1
|
||||
addx A2L,S0L
|
||||
addx A2H,S0H
|
||||
_nobit:
|
||||
; a >>= 1
|
||||
shlr A0H
|
||||
rotxr A0L
|
||||
rotxr A1H
|
||||
rotxr A1L
|
||||
|
||||
; b <<= 1
|
||||
add.w A3,A3
|
||||
addx A2L,A2L
|
||||
addx A2H,A2H
|
||||
bra _top
|
||||
|
||||
_done:
|
||||
mov.w S0,A0
|
||||
mov.w S1,A1
|
||||
POPP S2P
|
||||
POPP S1P
|
||||
POPP S0P
|
||||
rts
|
||||
|
||||
#else /* __H8300H__ */
|
||||
|
||||
.h8300h
|
||||
|
||||
.global ___mulsi3
|
||||
___mulsi3:
|
||||
sub.l A2P,A2P
|
||||
|
||||
; while (a)
|
||||
_top: mov.l A0P,A0P
|
||||
beq _done
|
||||
|
||||
; if (a & 1)
|
||||
bld #0,A0L
|
||||
bcc _nobit
|
||||
|
||||
; r += b
|
||||
add.l A1P,A2P
|
||||
|
||||
_nobit:
|
||||
; a >>= 1
|
||||
shlr.l A0P
|
||||
|
||||
; b <<= 1
|
||||
shll.l A1P
|
||||
bra _top
|
||||
|
||||
_done:
|
||||
mov.l A2P,A0P
|
||||
rts
|
||||
|
||||
#endif
|
||||
#endif /* L_mulsi3 */
|
Loading…
Add table
Reference in a new issue