parent
3c5e2cd5da
commit
85ca99beb3
|
@ -0,0 +1,10 @@
|
||||||
|
obj-y += armlinux.o
|
||||||
|
obj-y += _ashldi3.o
|
||||||
|
obj-y += _ashrdi3.o
|
||||||
|
obj-y += board.o
|
||||||
|
obj-y += cache.o
|
||||||
|
obj-y += div0.o
|
||||||
|
obj-y += _divsi3.o
|
||||||
|
obj-y += _modsi3.o
|
||||||
|
obj-y += _udivsi3.o
|
||||||
|
obj-y += _umodsi3.o
|
|
@ -0,0 +1,46 @@
|
||||||
|
/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
In addition to the permissions in the GNU General Public License, the
|
||||||
|
Free Software Foundation gives you unlimited permission to link the
|
||||||
|
compiled version of this file into combinations with other programs,
|
||||||
|
and to distribute those combinations without any restriction coming
|
||||||
|
from the use of this file. (The General Public License restrictions
|
||||||
|
do apply in other respects; for example, they cover modification of
|
||||||
|
the file, and distribution when not linked into a combine
|
||||||
|
executable.)
|
||||||
|
|
||||||
|
This file is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING. If not, write to
|
||||||
|
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __ARMEB__
|
||||||
|
#define al r1
|
||||||
|
#define ah r0
|
||||||
|
#else
|
||||||
|
#define al r0
|
||||||
|
#define ah r1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.globl __ashldi3
|
||||||
|
__ashldi3:
|
||||||
|
|
||||||
|
subs r3, r2, #32
|
||||||
|
rsb ip, r2, #32
|
||||||
|
movmi ah, ah, lsl r2
|
||||||
|
movpl ah, al, lsl r3
|
||||||
|
orrmi ah, ah, al, lsr ip
|
||||||
|
mov al, al, lsl r2
|
||||||
|
mov pc, lr
|
|
@ -0,0 +1,46 @@
|
||||||
|
/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
In addition to the permissions in the GNU General Public License, the
|
||||||
|
Free Software Foundation gives you unlimited permission to link the
|
||||||
|
compiled version of this file into combinations with other programs,
|
||||||
|
and to distribute those combinations without any restriction coming
|
||||||
|
from the use of this file. (The General Public License restrictions
|
||||||
|
do apply in other respects; for example, they cover modification of
|
||||||
|
the file, and distribution when not linked into a combine
|
||||||
|
executable.)
|
||||||
|
|
||||||
|
This file is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING. If not, write to
|
||||||
|
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __ARMEB__
|
||||||
|
#define al r1
|
||||||
|
#define ah r0
|
||||||
|
#else
|
||||||
|
#define al r0
|
||||||
|
#define ah r1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.globl __ashrdi3
|
||||||
|
__ashrdi3:
|
||||||
|
|
||||||
|
subs r3, r2, #32
|
||||||
|
rsb ip, r2, #32
|
||||||
|
movmi al, al, lsr r2
|
||||||
|
movpl al, ah, asr r3
|
||||||
|
orrmi al, al, ah, lsl ip
|
||||||
|
mov ah, ah, asr r2
|
||||||
|
mov pc, lr
|
|
@ -0,0 +1,140 @@
|
||||||
|
|
||||||
|
.macro ARM_DIV_BODY dividend, divisor, result, curbit
|
||||||
|
|
||||||
|
#if __LINUX_ARM_ARCH__ >= 5
|
||||||
|
|
||||||
|
clz \curbit, \divisor
|
||||||
|
clz \result, \dividend
|
||||||
|
sub \result, \curbit, \result
|
||||||
|
mov \curbit, #1
|
||||||
|
mov \divisor, \divisor, lsl \result
|
||||||
|
mov \curbit, \curbit, lsl \result
|
||||||
|
mov \result, #0
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
@ Initially shift the divisor left 3 bits if possible,
|
||||||
|
@ set curbit accordingly. This allows for curbit to be located
|
||||||
|
@ at the left end of each 4 bit nibbles in the division loop
|
||||||
|
@ to save one loop in most cases.
|
||||||
|
tst \divisor, #0xe0000000
|
||||||
|
moveq \divisor, \divisor, lsl #3
|
||||||
|
moveq \curbit, #8
|
||||||
|
movne \curbit, #1
|
||||||
|
|
||||||
|
@ Unless the divisor is very big, shift it up in multiples of
|
||||||
|
@ four bits, since this is the amount of unwinding in the main
|
||||||
|
@ division loop. Continue shifting until the divisor is
|
||||||
|
@ larger than the dividend.
|
||||||
|
1: cmp \divisor, #0x10000000
|
||||||
|
cmplo \divisor, \dividend
|
||||||
|
movlo \divisor, \divisor, lsl #4
|
||||||
|
movlo \curbit, \curbit, lsl #4
|
||||||
|
blo 1b
|
||||||
|
|
||||||
|
@ For very big divisors, we must shift it a bit at a time, or
|
||||||
|
@ we will be in danger of overflowing.
|
||||||
|
1: cmp \divisor, #0x80000000
|
||||||
|
cmplo \divisor, \dividend
|
||||||
|
movlo \divisor, \divisor, lsl #1
|
||||||
|
movlo \curbit, \curbit, lsl #1
|
||||||
|
blo 1b
|
||||||
|
|
||||||
|
mov \result, #0
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ Division loop
|
||||||
|
1: cmp \dividend, \divisor
|
||||||
|
subhs \dividend, \dividend, \divisor
|
||||||
|
orrhs \result, \result, \curbit
|
||||||
|
cmp \dividend, \divisor, lsr #1
|
||||||
|
subhs \dividend, \dividend, \divisor, lsr #1
|
||||||
|
orrhs \result, \result, \curbit, lsr #1
|
||||||
|
cmp \dividend, \divisor, lsr #2
|
||||||
|
subhs \dividend, \dividend, \divisor, lsr #2
|
||||||
|
orrhs \result, \result, \curbit, lsr #2
|
||||||
|
cmp \dividend, \divisor, lsr #3
|
||||||
|
subhs \dividend, \dividend, \divisor, lsr #3
|
||||||
|
orrhs \result, \result, \curbit, lsr #3
|
||||||
|
cmp \dividend, #0 @ Early termination?
|
||||||
|
movnes \curbit, \curbit, lsr #4 @ No, any more bits to do?
|
||||||
|
movne \divisor, \divisor, lsr #4
|
||||||
|
bne 1b
|
||||||
|
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro ARM_DIV2_ORDER divisor, order
|
||||||
|
|
||||||
|
#if __LINUX_ARM_ARCH__ >= 5
|
||||||
|
|
||||||
|
clz \order, \divisor
|
||||||
|
rsb \order, \order, #31
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
cmp \divisor, #(1 << 16)
|
||||||
|
movhs \divisor, \divisor, lsr #16
|
||||||
|
movhs \order, #16
|
||||||
|
movlo \order, #0
|
||||||
|
|
||||||
|
cmp \divisor, #(1 << 8)
|
||||||
|
movhs \divisor, \divisor, lsr #8
|
||||||
|
addhs \order, \order, #8
|
||||||
|
|
||||||
|
cmp \divisor, #(1 << 4)
|
||||||
|
movhs \divisor, \divisor, lsr #4
|
||||||
|
addhs \order, \order, #4
|
||||||
|
|
||||||
|
cmp \divisor, #(1 << 2)
|
||||||
|
addhi \order, \order, #3
|
||||||
|
addls \order, \order, \divisor, lsr #1
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.align 5
|
||||||
|
.globl __divsi3
|
||||||
|
__divsi3:
|
||||||
|
cmp r1, #0
|
||||||
|
eor ip, r0, r1 @ save the sign of the result.
|
||||||
|
beq Ldiv0
|
||||||
|
rsbmi r1, r1, #0 @ loops below use unsigned.
|
||||||
|
subs r2, r1, #1 @ division by 1 or -1 ?
|
||||||
|
beq 10f
|
||||||
|
movs r3, r0
|
||||||
|
rsbmi r3, r0, #0 @ positive dividend value
|
||||||
|
cmp r3, r1
|
||||||
|
bls 11f
|
||||||
|
tst r1, r2 @ divisor is power of 2 ?
|
||||||
|
beq 12f
|
||||||
|
|
||||||
|
ARM_DIV_BODY r3, r1, r0, r2
|
||||||
|
|
||||||
|
cmp ip, #0
|
||||||
|
rsbmi r0, r0, #0
|
||||||
|
mov pc, lr
|
||||||
|
|
||||||
|
10: teq ip, r0 @ same sign ?
|
||||||
|
rsbmi r0, r0, #0
|
||||||
|
mov pc, lr
|
||||||
|
|
||||||
|
11: movlo r0, #0
|
||||||
|
moveq r0, ip, asr #31
|
||||||
|
orreq r0, r0, #1
|
||||||
|
mov pc, lr
|
||||||
|
|
||||||
|
12: ARM_DIV2_ORDER r1, r2
|
||||||
|
|
||||||
|
cmp ip, #0
|
||||||
|
mov r0, r3, lsr r2
|
||||||
|
rsbmi r0, r0, #0
|
||||||
|
mov pc, lr
|
||||||
|
|
||||||
|
Ldiv0:
|
||||||
|
|
||||||
|
str lr, [sp, #-4]!
|
||||||
|
bl __div0
|
||||||
|
mov r0, #0 @ About as wrong as it could be.
|
||||||
|
ldr pc, [sp], #4
|
|
@ -0,0 +1,99 @@
|
||||||
|
|
||||||
|
.macro ARM_MOD_BODY dividend, divisor, order, spare
|
||||||
|
|
||||||
|
#if __LINUX_ARM_ARCH__ >= 5
|
||||||
|
|
||||||
|
clz \order, \divisor
|
||||||
|
clz \spare, \dividend
|
||||||
|
sub \order, \order, \spare
|
||||||
|
mov \divisor, \divisor, lsl \order
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
mov \order, #0
|
||||||
|
|
||||||
|
@ Unless the divisor is very big, shift it up in multiples of
|
||||||
|
@ four bits, since this is the amount of unwinding in the main
|
||||||
|
@ division loop. Continue shifting until the divisor is
|
||||||
|
@ larger than the dividend.
|
||||||
|
1: cmp \divisor, #0x10000000
|
||||||
|
cmplo \divisor, \dividend
|
||||||
|
movlo \divisor, \divisor, lsl #4
|
||||||
|
addlo \order, \order, #4
|
||||||
|
blo 1b
|
||||||
|
|
||||||
|
@ For very big divisors, we must shift it a bit at a time, or
|
||||||
|
@ we will be in danger of overflowing.
|
||||||
|
1: cmp \divisor, #0x80000000
|
||||||
|
cmplo \divisor, \dividend
|
||||||
|
movlo \divisor, \divisor, lsl #1
|
||||||
|
addlo \order, \order, #1
|
||||||
|
blo 1b
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ Perform all needed substractions to keep only the reminder.
|
||||||
|
@ Do comparisons in batch of 4 first.
|
||||||
|
subs \order, \order, #3 @ yes, 3 is intended here
|
||||||
|
blt 2f
|
||||||
|
|
||||||
|
1: cmp \dividend, \divisor
|
||||||
|
subhs \dividend, \dividend, \divisor
|
||||||
|
cmp \dividend, \divisor, lsr #1
|
||||||
|
subhs \dividend, \dividend, \divisor, lsr #1
|
||||||
|
cmp \dividend, \divisor, lsr #2
|
||||||
|
subhs \dividend, \dividend, \divisor, lsr #2
|
||||||
|
cmp \dividend, \divisor, lsr #3
|
||||||
|
subhs \dividend, \dividend, \divisor, lsr #3
|
||||||
|
cmp \dividend, #1
|
||||||
|
mov \divisor, \divisor, lsr #4
|
||||||
|
subges \order, \order, #4
|
||||||
|
bge 1b
|
||||||
|
|
||||||
|
tst \order, #3
|
||||||
|
teqne \dividend, #0
|
||||||
|
beq 5f
|
||||||
|
|
||||||
|
@ Either 1, 2 or 3 comparison/substractions are left.
|
||||||
|
2: cmn \order, #2
|
||||||
|
blt 4f
|
||||||
|
beq 3f
|
||||||
|
cmp \dividend, \divisor
|
||||||
|
subhs \dividend, \dividend, \divisor
|
||||||
|
mov \divisor, \divisor, lsr #1
|
||||||
|
3: cmp \dividend, \divisor
|
||||||
|
subhs \dividend, \dividend, \divisor
|
||||||
|
mov \divisor, \divisor, lsr #1
|
||||||
|
4: cmp \dividend, \divisor
|
||||||
|
subhs \dividend, \dividend, \divisor
|
||||||
|
5:
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.align 5
|
||||||
|
.globl __modsi3
|
||||||
|
__modsi3:
|
||||||
|
cmp r1, #0
|
||||||
|
beq Ldiv0
|
||||||
|
rsbmi r1, r1, #0 @ loops below use unsigned.
|
||||||
|
movs ip, r0 @ preserve sign of dividend
|
||||||
|
rsbmi r0, r0, #0 @ if negative make positive
|
||||||
|
subs r2, r1, #1 @ compare divisor with 1
|
||||||
|
cmpne r0, r1 @ compare dividend with divisor
|
||||||
|
moveq r0, #0
|
||||||
|
tsthi r1, r2 @ see if divisor is power of 2
|
||||||
|
andeq r0, r0, r2
|
||||||
|
bls 10f
|
||||||
|
|
||||||
|
ARM_MOD_BODY r0, r1, r2, r3
|
||||||
|
|
||||||
|
10: cmp ip, #0
|
||||||
|
rsbmi r0, r0, #0
|
||||||
|
mov pc, lr
|
||||||
|
|
||||||
|
|
||||||
|
Ldiv0:
|
||||||
|
|
||||||
|
str lr, [sp, #-4]!
|
||||||
|
bl __div0
|
||||||
|
mov r0, #0 @ About as wrong as it could be.
|
||||||
|
ldr pc, [sp], #4
|
|
@ -0,0 +1,77 @@
|
||||||
|
/* # 1 "libgcc1.S" */
|
||||||
|
@ libgcc1 routines for ARM cpu.
|
||||||
|
@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
|
||||||
|
dividend .req r0
|
||||||
|
divisor .req r1
|
||||||
|
result .req r2
|
||||||
|
curbit .req r3
|
||||||
|
/* ip .req r12 */
|
||||||
|
/* sp .req r13 */
|
||||||
|
/* lr .req r14 */
|
||||||
|
/* pc .req r15 */
|
||||||
|
.text
|
||||||
|
.globl __udivsi3
|
||||||
|
.type __udivsi3 ,function
|
||||||
|
.align 0
|
||||||
|
__udivsi3 :
|
||||||
|
cmp divisor, #0
|
||||||
|
beq Ldiv0
|
||||||
|
mov curbit, #1
|
||||||
|
mov result, #0
|
||||||
|
cmp dividend, divisor
|
||||||
|
bcc Lgot_result
|
||||||
|
Loop1:
|
||||||
|
@ Unless the divisor is very big, shift it up in multiples of
|
||||||
|
@ four bits, since this is the amount of unwinding in the main
|
||||||
|
@ division loop. Continue shifting until the divisor is
|
||||||
|
@ larger than the dividend.
|
||||||
|
cmp divisor, #0x10000000
|
||||||
|
cmpcc divisor, dividend
|
||||||
|
movcc divisor, divisor, lsl #4
|
||||||
|
movcc curbit, curbit, lsl #4
|
||||||
|
bcc Loop1
|
||||||
|
Lbignum:
|
||||||
|
@ For very big divisors, we must shift it a bit at a time, or
|
||||||
|
@ we will be in danger of overflowing.
|
||||||
|
cmp divisor, #0x80000000
|
||||||
|
cmpcc divisor, dividend
|
||||||
|
movcc divisor, divisor, lsl #1
|
||||||
|
movcc curbit, curbit, lsl #1
|
||||||
|
bcc Lbignum
|
||||||
|
Loop3:
|
||||||
|
@ Test for possible subtractions, and note which bits
|
||||||
|
@ are done in the result. On the final pass, this may subtract
|
||||||
|
@ too much from the dividend, but the result will be ok, since the
|
||||||
|
@ "bit" will have been shifted out at the bottom.
|
||||||
|
cmp dividend, divisor
|
||||||
|
subcs dividend, dividend, divisor
|
||||||
|
orrcs result, result, curbit
|
||||||
|
cmp dividend, divisor, lsr #1
|
||||||
|
subcs dividend, dividend, divisor, lsr #1
|
||||||
|
orrcs result, result, curbit, lsr #1
|
||||||
|
cmp dividend, divisor, lsr #2
|
||||||
|
subcs dividend, dividend, divisor, lsr #2
|
||||||
|
orrcs result, result, curbit, lsr #2
|
||||||
|
cmp dividend, divisor, lsr #3
|
||||||
|
subcs dividend, dividend, divisor, lsr #3
|
||||||
|
orrcs result, result, curbit, lsr #3
|
||||||
|
cmp dividend, #0 @ Early termination?
|
||||||
|
movnes curbit, curbit, lsr #4 @ No, any more bits to do?
|
||||||
|
movne divisor, divisor, lsr #4
|
||||||
|
bne Loop3
|
||||||
|
Lgot_result:
|
||||||
|
mov r0, result
|
||||||
|
mov pc, lr
|
||||||
|
Ldiv0:
|
||||||
|
str lr, [sp, #-4]!
|
||||||
|
bl __div0 (PLT)
|
||||||
|
mov r0, #0 @ about as wrong as it could be
|
||||||
|
ldmia sp!, {pc}
|
||||||
|
.size __udivsi3 , . - __udivsi3
|
||||||
|
/* # 235 "libgcc1.S" */
|
||||||
|
/* # 320 "libgcc1.S" */
|
||||||
|
/* # 421 "libgcc1.S" */
|
||||||
|
/* # 433 "libgcc1.S" */
|
||||||
|
/* # 456 "libgcc1.S" */
|
||||||
|
/* # 500 "libgcc1.S" */
|
||||||
|
/* # 580 "libgcc1.S" */
|
|
@ -0,0 +1,88 @@
|
||||||
|
/* # 1 "libgcc1.S" */
|
||||||
|
@ libgcc1 routines for ARM cpu.
|
||||||
|
@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
|
||||||
|
/* # 145 "libgcc1.S" */
|
||||||
|
dividend .req r0
|
||||||
|
divisor .req r1
|
||||||
|
overdone .req r2
|
||||||
|
curbit .req r3
|
||||||
|
/* ip .req r12 */
|
||||||
|
/* sp .req r13 */
|
||||||
|
/* lr .req r14 */
|
||||||
|
/* pc .req r15 */
|
||||||
|
.text
|
||||||
|
.globl __umodsi3
|
||||||
|
.type __umodsi3 ,function
|
||||||
|
.align 0
|
||||||
|
__umodsi3 :
|
||||||
|
cmp divisor, #0
|
||||||
|
beq Ldiv0
|
||||||
|
mov curbit, #1
|
||||||
|
cmp dividend, divisor
|
||||||
|
movcc pc, lr
|
||||||
|
Loop1:
|
||||||
|
@ Unless the divisor is very big, shift it up in multiples of
|
||||||
|
@ four bits, since this is the amount of unwinding in the main
|
||||||
|
@ division loop. Continue shifting until the divisor is
|
||||||
|
@ larger than the dividend.
|
||||||
|
cmp divisor, #0x10000000
|
||||||
|
cmpcc divisor, dividend
|
||||||
|
movcc divisor, divisor, lsl #4
|
||||||
|
movcc curbit, curbit, lsl #4
|
||||||
|
bcc Loop1
|
||||||
|
Lbignum:
|
||||||
|
@ For very big divisors, we must shift it a bit at a time, or
|
||||||
|
@ we will be in danger of overflowing.
|
||||||
|
cmp divisor, #0x80000000
|
||||||
|
cmpcc divisor, dividend
|
||||||
|
movcc divisor, divisor, lsl #1
|
||||||
|
movcc curbit, curbit, lsl #1
|
||||||
|
bcc Lbignum
|
||||||
|
Loop3:
|
||||||
|
@ Test for possible subtractions. On the final pass, this may
|
||||||
|
@ subtract too much from the dividend, so keep track of which
|
||||||
|
@ subtractions are done, we can fix them up afterwards...
|
||||||
|
mov overdone, #0
|
||||||
|
cmp dividend, divisor
|
||||||
|
subcs dividend, dividend, divisor
|
||||||
|
cmp dividend, divisor, lsr #1
|
||||||
|
subcs dividend, dividend, divisor, lsr #1
|
||||||
|
orrcs overdone, overdone, curbit, ror #1
|
||||||
|
cmp dividend, divisor, lsr #2
|
||||||
|
subcs dividend, dividend, divisor, lsr #2
|
||||||
|
orrcs overdone, overdone, curbit, ror #2
|
||||||
|
cmp dividend, divisor, lsr #3
|
||||||
|
subcs dividend, dividend, divisor, lsr #3
|
||||||
|
orrcs overdone, overdone, curbit, ror #3
|
||||||
|
mov ip, curbit
|
||||||
|
cmp dividend, #0 @ Early termination?
|
||||||
|
movnes curbit, curbit, lsr #4 @ No, any more bits to do?
|
||||||
|
movne divisor, divisor, lsr #4
|
||||||
|
bne Loop3
|
||||||
|
@ Any subtractions that we should not have done will be recorded in
|
||||||
|
@ the top three bits of "overdone". Exactly which were not needed
|
||||||
|
@ are governed by the position of the bit, stored in ip.
|
||||||
|
@ If we terminated early, because dividend became zero,
|
||||||
|
@ then none of the below will match, since the bit in ip will not be
|
||||||
|
@ in the bottom nibble.
|
||||||
|
ands overdone, overdone, #0xe0000000
|
||||||
|
moveq pc, lr @ No fixups needed
|
||||||
|
tst overdone, ip, ror #3
|
||||||
|
addne dividend, dividend, divisor, lsr #3
|
||||||
|
tst overdone, ip, ror #2
|
||||||
|
addne dividend, dividend, divisor, lsr #2
|
||||||
|
tst overdone, ip, ror #1
|
||||||
|
addne dividend, dividend, divisor, lsr #1
|
||||||
|
mov pc, lr
|
||||||
|
Ldiv0:
|
||||||
|
str lr, [sp, #-4]!
|
||||||
|
bl __div0 (PLT)
|
||||||
|
mov r0, #0 @ about as wrong as it could be
|
||||||
|
ldmia sp!, {pc}
|
||||||
|
.size __umodsi3 , . - __umodsi3
|
||||||
|
/* # 320 "libgcc1.S" */
|
||||||
|
/* # 421 "libgcc1.S" */
|
||||||
|
/* # 433 "libgcc1.S" */
|
||||||
|
/* # 456 "libgcc1.S" */
|
||||||
|
/* # 500 "libgcc1.S" */
|
||||||
|
/* # 580 "libgcc1.S" */
|
|
@ -0,0 +1,399 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2002
|
||||||
|
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
||||||
|
* Marius Groeger <mgroeger@sysgo.de>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <command.h>
|
||||||
|
#include <image.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
#include <asm/byteorder.h>
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
/*cmd_boot.c*/
|
||||||
|
extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
|
||||||
|
|
||||||
|
#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
|
||||||
|
defined (CONFIG_CMDLINE_TAG) || \
|
||||||
|
defined (CONFIG_INITRD_TAG) || \
|
||||||
|
defined (CONFIG_SERIAL_TAG) || \
|
||||||
|
defined (CONFIG_REVISION_TAG) || \
|
||||||
|
defined (CONFIG_VFD) || \
|
||||||
|
defined (CONFIG_LCD)
|
||||||
|
static void setup_start_tag (bd_t *bd);
|
||||||
|
|
||||||
|
# ifdef CONFIG_SETUP_MEMORY_TAGS
|
||||||
|
static void setup_memory_tags (bd_t *bd);
|
||||||
|
# endif
|
||||||
|
static void setup_commandline_tag (bd_t *bd, char *commandline);
|
||||||
|
|
||||||
|
# ifdef CONFIG_INITRD_TAG
|
||||||
|
static void setup_initrd_tag (bd_t *bd, ulong initrd_start,
|
||||||
|
ulong initrd_end);
|
||||||
|
# endif
|
||||||
|
static void setup_end_tag (bd_t *bd);
|
||||||
|
|
||||||
|
# if defined (CONFIG_VFD) || defined (CONFIG_LCD)
|
||||||
|
static void setup_videolfb_tag (gd_t *gd);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
|
||||||
|
static struct tag *params;
|
||||||
|
#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SHOW_BOOT_PROGRESS
|
||||||
|
# include <status_led.h>
|
||||||
|
# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg)
|
||||||
|
#else
|
||||||
|
# define SHOW_BOOT_PROGRESS(arg)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern image_header_t header; /* from cmd_bootm.c */
|
||||||
|
|
||||||
|
|
||||||
|
void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
|
||||||
|
ulong addr, ulong *len_ptr, int verify)
|
||||||
|
{
|
||||||
|
ulong len = 0, checksum;
|
||||||
|
ulong initrd_start, initrd_end;
|
||||||
|
ulong data;
|
||||||
|
void (*theKernel)(int zero, int arch, uint params);
|
||||||
|
image_header_t *hdr = &header;
|
||||||
|
bd_t *bd = gd->bd;
|
||||||
|
|
||||||
|
#ifdef CONFIG_CMDLINE_TAG
|
||||||
|
char *commandline = getenv ("bootargs");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if there is an initrd image
|
||||||
|
*/
|
||||||
|
if (argc >= 3) {
|
||||||
|
SHOW_BOOT_PROGRESS (9);
|
||||||
|
|
||||||
|
addr = simple_strtoul (argv[2], NULL, 16);
|
||||||
|
|
||||||
|
printf ("## Loading Ramdisk Image at %08lx ...\n", addr);
|
||||||
|
|
||||||
|
/* Copy header so we can blank CRC field for re-calculation */
|
||||||
|
memcpy (&header, (char *) addr,
|
||||||
|
sizeof (image_header_t));
|
||||||
|
|
||||||
|
if (ntohl (hdr->ih_magic) != IH_MAGIC) {
|
||||||
|
printf ("Bad Magic Number\n");
|
||||||
|
SHOW_BOOT_PROGRESS (-10);
|
||||||
|
do_reset (cmdtp, flag, argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
data = (ulong) & header;
|
||||||
|
len = sizeof (image_header_t);
|
||||||
|
|
||||||
|
checksum = ntohl (hdr->ih_hcrc);
|
||||||
|
hdr->ih_hcrc = 0;
|
||||||
|
|
||||||
|
if (crc32 (0, (unsigned char *) data, len) != checksum) {
|
||||||
|
printf ("Bad Header Checksum\n");
|
||||||
|
SHOW_BOOT_PROGRESS (-11);
|
||||||
|
do_reset (cmdtp, flag, argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
SHOW_BOOT_PROGRESS (10);
|
||||||
|
|
||||||
|
print_image_hdr (hdr);
|
||||||
|
|
||||||
|
data = addr + sizeof (image_header_t);
|
||||||
|
len = ntohl (hdr->ih_size);
|
||||||
|
|
||||||
|
if (verify) {
|
||||||
|
ulong csum = 0;
|
||||||
|
|
||||||
|
printf (" Verifying Checksum ... ");
|
||||||
|
csum = crc32 (0, (unsigned char *) data, len);
|
||||||
|
if (csum != ntohl (hdr->ih_dcrc)) {
|
||||||
|
printf ("Bad Data CRC\n");
|
||||||
|
SHOW_BOOT_PROGRESS (-12);
|
||||||
|
do_reset (cmdtp, flag, argc, argv);
|
||||||
|
}
|
||||||
|
printf ("OK\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
SHOW_BOOT_PROGRESS (11);
|
||||||
|
|
||||||
|
if ((hdr->ih_os != IH_OS_LINUX) ||
|
||||||
|
(hdr->ih_arch != IH_CPU_ARM) ||
|
||||||
|
(hdr->ih_type != IH_TYPE_RAMDISK)) {
|
||||||
|
printf ("No Linux ARM Ramdisk Image\n");
|
||||||
|
SHOW_BOOT_PROGRESS (-13);
|
||||||
|
do_reset (cmdtp, flag, argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO)
|
||||||
|
/*
|
||||||
|
*we need to copy the ramdisk to SRAM to let Linux boot
|
||||||
|
*/
|
||||||
|
memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len);
|
||||||
|
data = ntohl(hdr->ih_load);
|
||||||
|
#endif /* CONFIG_B2 || CONFIG_EVB4510 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now check if we have a multifile image
|
||||||
|
*/
|
||||||
|
} else if ((hdr->ih_type == IH_TYPE_MULTI) && (len_ptr[1])) {
|
||||||
|
ulong tail = ntohl (len_ptr[0]) % 4;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
SHOW_BOOT_PROGRESS (13);
|
||||||
|
|
||||||
|
/* skip kernel length and terminator */
|
||||||
|
data = (ulong) (&len_ptr[2]);
|
||||||
|
/* skip any additional image length fields */
|
||||||
|
for (i = 1; len_ptr[i]; ++i)
|
||||||
|
data += 4;
|
||||||
|
/* add kernel length, and align */
|
||||||
|
data += ntohl (len_ptr[0]);
|
||||||
|
if (tail) {
|
||||||
|
data += 4 - tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = ntohl (len_ptr[1]);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* no initrd image
|
||||||
|
*/
|
||||||
|
SHOW_BOOT_PROGRESS (14);
|
||||||
|
|
||||||
|
len = data = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (!data) {
|
||||||
|
printf ("No initrd\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
initrd_start = data;
|
||||||
|
initrd_end = initrd_start + len;
|
||||||
|
} else {
|
||||||
|
initrd_start = 0;
|
||||||
|
initrd_end = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHOW_BOOT_PROGRESS (15);
|
||||||
|
|
||||||
|
debug ("## Transferring control to Linux (at address %08lx) ...\n",
|
||||||
|
(ulong) theKernel);
|
||||||
|
|
||||||
|
#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
|
||||||
|
defined (CONFIG_CMDLINE_TAG) || \
|
||||||
|
defined (CONFIG_INITRD_TAG) || \
|
||||||
|
defined (CONFIG_SERIAL_TAG) || \
|
||||||
|
defined (CONFIG_REVISION_TAG) || \
|
||||||
|
defined (CONFIG_LCD) || \
|
||||||
|
defined (CONFIG_VFD)
|
||||||
|
setup_start_tag (bd);
|
||||||
|
#ifdef CONFIG_SERIAL_TAG
|
||||||
|
setup_serial_tag (¶ms);
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_REVISION_TAG
|
||||||
|
setup_revision_tag (¶ms);
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_SETUP_MEMORY_TAGS
|
||||||
|
setup_memory_tags (bd);
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_CMDLINE_TAG
|
||||||
|
setup_commandline_tag (bd, commandline);
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_INITRD_TAG
|
||||||
|
if (initrd_start && initrd_end)
|
||||||
|
setup_initrd_tag (bd, initrd_start, initrd_end);
|
||||||
|
#endif
|
||||||
|
#if defined (CONFIG_VFD) || defined (CONFIG_LCD)
|
||||||
|
setup_videolfb_tag ((gd_t *) gd);
|
||||||
|
#endif
|
||||||
|
setup_end_tag (bd);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* we assume that the kernel is in place */
|
||||||
|
printf ("\nStarting kernel ...\n\n");
|
||||||
|
|
||||||
|
#ifdef CONFIG_USB_DEVICE
|
||||||
|
{
|
||||||
|
extern void udc_disconnect (void);
|
||||||
|
udc_disconnect ();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
cleanup_before_linux ();
|
||||||
|
|
||||||
|
theKernel (0, bd->bi_arch_number, bd->bi_boot_params);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
|
||||||
|
defined (CONFIG_CMDLINE_TAG) || \
|
||||||
|
defined (CONFIG_INITRD_TAG) || \
|
||||||
|
defined (CONFIG_SERIAL_TAG) || \
|
||||||
|
defined (CONFIG_REVISION_TAG) || \
|
||||||
|
defined (CONFIG_LCD) || \
|
||||||
|
defined (CONFIG_VFD)
|
||||||
|
static void setup_start_tag (bd_t *bd)
|
||||||
|
{
|
||||||
|
params = (struct tag *) bd->bi_boot_params;
|
||||||
|
|
||||||
|
params->hdr.tag = ATAG_CORE;
|
||||||
|
params->hdr.size = tag_size (tag_core);
|
||||||
|
|
||||||
|
params->u.core.flags = 0;
|
||||||
|
params->u.core.pagesize = 0;
|
||||||
|
params->u.core.rootdev = 0;
|
||||||
|
|
||||||
|
params = tag_next (params);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_SETUP_MEMORY_TAGS
|
||||||
|
static void setup_memory_tags (bd_t *bd)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
|
||||||
|
params->hdr.tag = ATAG_MEM;
|
||||||
|
params->hdr.size = tag_size (tag_mem32);
|
||||||
|
|
||||||
|
params->u.mem.start = bd->bi_dram[i].start;
|
||||||
|
params->u.mem.size = bd->bi_dram[i].size;
|
||||||
|
|
||||||
|
params = tag_next (params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SETUP_MEMORY_TAGS */
|
||||||
|
|
||||||
|
|
||||||
|
static void setup_commandline_tag (bd_t *bd, char *commandline)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (!commandline)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* eat leading white space */
|
||||||
|
for (p = commandline; *p == ' '; p++);
|
||||||
|
|
||||||
|
/* skip non-existent command lines so the kernel will still
|
||||||
|
* use its default command line.
|
||||||
|
*/
|
||||||
|
if (*p == '\0')
|
||||||
|
return;
|
||||||
|
|
||||||
|
params->hdr.tag = ATAG_CMDLINE;
|
||||||
|
params->hdr.size =
|
||||||
|
(sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;
|
||||||
|
|
||||||
|
strcpy (params->u.cmdline.cmdline, p);
|
||||||
|
|
||||||
|
params = tag_next (params);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_INITRD_TAG
|
||||||
|
static void setup_initrd_tag (bd_t *bd, ulong initrd_start, ulong initrd_end)
|
||||||
|
{
|
||||||
|
/* an ATAG_INITRD node tells the kernel where the compressed
|
||||||
|
* ramdisk can be found. ATAG_RDIMG is a better name, actually.
|
||||||
|
*/
|
||||||
|
params->hdr.tag = ATAG_INITRD2;
|
||||||
|
params->hdr.size = tag_size (tag_initrd);
|
||||||
|
|
||||||
|
params->u.initrd.start = initrd_start;
|
||||||
|
params->u.initrd.size = initrd_end - initrd_start;
|
||||||
|
|
||||||
|
params = tag_next (params);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_INITRD_TAG */
|
||||||
|
|
||||||
|
|
||||||
|
#if defined (CONFIG_VFD) || defined (CONFIG_LCD)
|
||||||
|
extern ulong calc_fbsize (void);
|
||||||
|
static void setup_videolfb_tag (gd_t *gd)
|
||||||
|
{
|
||||||
|
/* An ATAG_VIDEOLFB node tells the kernel where and how large
|
||||||
|
* the framebuffer for video was allocated (among other things).
|
||||||
|
* Note that a _physical_ address is passed !
|
||||||
|
*
|
||||||
|
* We only use it to pass the address and size, the other entries
|
||||||
|
* in the tag_videolfb are not of interest.
|
||||||
|
*/
|
||||||
|
params->hdr.tag = ATAG_VIDEOLFB;
|
||||||
|
params->hdr.size = tag_size (tag_videolfb);
|
||||||
|
|
||||||
|
params->u.videolfb.lfb_base = (u32) gd->fb_base;
|
||||||
|
/* Fb size is calculated according to parameters for our panel
|
||||||
|
*/
|
||||||
|
params->u.videolfb.lfb_size = calc_fbsize();
|
||||||
|
|
||||||
|
params = tag_next (params);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_VFD || CONFIG_LCD */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_TAG
|
||||||
|
void setup_serial_tag (struct tag **tmp)
|
||||||
|
{
|
||||||
|
struct tag *params = *tmp;
|
||||||
|
struct tag_serialnr serialnr;
|
||||||
|
void get_board_serial(struct tag_serialnr *serialnr);
|
||||||
|
|
||||||
|
get_board_serial(&serialnr);
|
||||||
|
params->hdr.tag = ATAG_SERIAL;
|
||||||
|
params->hdr.size = tag_size (tag_serialnr);
|
||||||
|
params->u.serialnr.low = serialnr.low;
|
||||||
|
params->u.serialnr.high= serialnr.high;
|
||||||
|
params = tag_next (params);
|
||||||
|
*tmp = params;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_REVISION_TAG
|
||||||
|
void setup_revision_tag(struct tag **in_params)
|
||||||
|
{
|
||||||
|
u32 rev = 0;
|
||||||
|
u32 get_board_rev(void);
|
||||||
|
|
||||||
|
rev = get_board_rev();
|
||||||
|
params->hdr.tag = ATAG_REVISION;
|
||||||
|
params->hdr.size = tag_size (tag_revision);
|
||||||
|
params->u.revision.rev = rev;
|
||||||
|
params = tag_next (params);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_REVISION_TAG */
|
||||||
|
|
||||||
|
|
||||||
|
static void setup_end_tag (bd_t *bd)
|
||||||
|
{
|
||||||
|
params->hdr.tag = ATAG_NONE;
|
||||||
|
params->hdr.size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
|
|
@ -0,0 +1,369 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2002-2006
|
||||||
|
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||||
|
*
|
||||||
|
* (C) Copyright 2002
|
||||||
|
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
||||||
|
* Marius Groeger <mgroeger@sysgo.de>
|
||||||
|
*
|
||||||
|
* See file CREDITS for list of people who contributed to this
|
||||||
|
* project.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||||
|
* MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To match the U-Boot user interface on ARM platforms to the U-Boot
|
||||||
|
* standard (as on PPC platforms), some messages with debug character
|
||||||
|
* are removed from the default U-Boot build.
|
||||||
|
*
|
||||||
|
* Define DEBUG here if you want additional info as shown below
|
||||||
|
* printed upon startup:
|
||||||
|
*
|
||||||
|
* U-Boot code: 00F00000 -> 00F3C774 BSS: -> 00FC3274
|
||||||
|
* IRQ Stack: 00ebff7c
|
||||||
|
* FIQ Stack: 00ebef7c
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <command.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <devices.h>
|
||||||
|
#include <version.h>
|
||||||
|
#include <net.h>
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
|
||||||
|
void nand_init (void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ulong monitor_flash_len;
|
||||||
|
|
||||||
|
#ifndef CONFIG_IDENT_STRING
|
||||||
|
#define CONFIG_IDENT_STRING ""
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char version_string[] =
|
||||||
|
U_BOOT_VERSION" (" __DATE__ " - " __TIME__ ")"CONFIG_IDENT_STRING;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Begin and End of memory area for malloc(), and current "brk"
|
||||||
|
*/
|
||||||
|
static ulong mem_malloc_start = 0;
|
||||||
|
static ulong mem_malloc_end = 0;
|
||||||
|
static ulong mem_malloc_brk = 0;
|
||||||
|
|
||||||
|
static
|
||||||
|
void mem_malloc_init (ulong dest_addr)
|
||||||
|
{
|
||||||
|
mem_malloc_start = dest_addr;
|
||||||
|
mem_malloc_end = dest_addr + CFG_MALLOC_LEN;
|
||||||
|
mem_malloc_brk = mem_malloc_start;
|
||||||
|
|
||||||
|
memset ((void *) mem_malloc_start, 0,
|
||||||
|
mem_malloc_end - mem_malloc_start);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *sbrk (ptrdiff_t increment)
|
||||||
|
{
|
||||||
|
ulong old = mem_malloc_brk;
|
||||||
|
ulong new = old + increment;
|
||||||
|
|
||||||
|
if ((new < mem_malloc_start) || (new > mem_malloc_end)) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
mem_malloc_brk = new;
|
||||||
|
|
||||||
|
return ((void *) old);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* Init Utilities *
|
||||||
|
************************************************************************
|
||||||
|
* Some of this code should be moved into the core functions,
|
||||||
|
* or dropped completely,
|
||||||
|
* but let's get it working (again) first...
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int init_baudrate (void)
|
||||||
|
{
|
||||||
|
char tmp[64]; /* long enough for environment variables */
|
||||||
|
int i = getenv_r ("baudrate", tmp, sizeof (tmp));
|
||||||
|
gd->bd->bi_baudrate = gd->baudrate = (i > 0)
|
||||||
|
? (int) simple_strtoul (tmp, NULL, 10)
|
||||||
|
: CONFIG_BAUDRATE;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int display_banner (void)
|
||||||
|
{
|
||||||
|
printf ("\n\n%s\n\n", version_string);
|
||||||
|
debug ("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n",
|
||||||
|
_armboot_start, _bss_start, _bss_end);
|
||||||
|
#ifdef CONFIG_USE_IRQ
|
||||||
|
debug ("IRQ Stack: %08lx\n", IRQ_STACK_START);
|
||||||
|
debug ("FIQ Stack: %08lx\n", FIQ_STACK_START);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WARNING: this code looks "cleaner" than the PowerPC version, but
|
||||||
|
* has the disadvantage that you either get nothing, or everything.
|
||||||
|
* On PowerPC, you might see "DRAM: " before the system hangs - which
|
||||||
|
* gives a simple yet clear indication which part of the
|
||||||
|
* initialization if failing.
|
||||||
|
*/
|
||||||
|
static int display_dram_config (void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
puts ("RAM Configuration:\n");
|
||||||
|
|
||||||
|
for(i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
|
||||||
|
printf ("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
|
||||||
|
print_size (gd->bd->bi_dram[i].size, "\n");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ulong size = 0;
|
||||||
|
|
||||||
|
for (i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
|
||||||
|
size += gd->bd->bi_dram[i].size;
|
||||||
|
}
|
||||||
|
puts("DRAM: ");
|
||||||
|
print_size(size, "\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CFG_NO_FLASH
|
||||||
|
static void display_flash_config (ulong size)
|
||||||
|
{
|
||||||
|
puts ("Flash: ");
|
||||||
|
print_size (size, "\n");
|
||||||
|
}
|
||||||
|
#endif /* CFG_NO_FLASH */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Breathe some life into the board...
|
||||||
|
*
|
||||||
|
* Initialize a serial port as console, and carry out some hardware
|
||||||
|
* tests.
|
||||||
|
*
|
||||||
|
* The first part of initialization is running from Flash memory;
|
||||||
|
* its main purpose is to initialize the RAM so that we
|
||||||
|
* can relocate the monitor code to RAM.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All attempts to come up with a "common" initialization sequence
|
||||||
|
* that works for all boards and architectures failed: some of the
|
||||||
|
* requirements are just _too_ different. To get rid of the resulting
|
||||||
|
* mess of board dependent #ifdef'ed code we now make the whole
|
||||||
|
* initialization sequence configurable to the user.
|
||||||
|
*
|
||||||
|
* The requirements for any new initalization function is simple: it
|
||||||
|
* receives a pointer to the "global data" structure as it's only
|
||||||
|
* argument, and returns an integer return code, where 0 means
|
||||||
|
* "continue" and != 0 means "fatal error, hang the system".
|
||||||
|
*/
|
||||||
|
typedef int (init_fnc_t) (void);
|
||||||
|
|
||||||
|
int print_cpuinfo (void); /* test-only */
|
||||||
|
|
||||||
|
init_fnc_t *init_sequence[] = {
|
||||||
|
cpu_init, /* basic cpu dependent setup */
|
||||||
|
board_init, /* basic board dependent setup */
|
||||||
|
interrupt_init, /* set up exceptions */
|
||||||
|
env_init, /* initialize environment */
|
||||||
|
init_baudrate, /* initialze baudrate settings */
|
||||||
|
serial_init, /* serial communications setup */
|
||||||
|
console_init_f, /* stage 1 init of console */
|
||||||
|
display_banner, /* say that we are here */
|
||||||
|
#if defined(CONFIG_DISPLAY_CPUINFO)
|
||||||
|
print_cpuinfo, /* display cpu info (and speed) */
|
||||||
|
#endif
|
||||||
|
#if defined(CONFIG_DISPLAY_BOARDINFO)
|
||||||
|
checkboard, /* display board info */
|
||||||
|
#endif
|
||||||
|
dram_init, /* configure available RAM banks */
|
||||||
|
display_dram_config,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
void start_armboot (void)
|
||||||
|
{
|
||||||
|
init_fnc_t **init_fnc_ptr;
|
||||||
|
char *s;
|
||||||
|
#ifndef CFG_NO_FLASH
|
||||||
|
ulong size;
|
||||||
|
#endif
|
||||||
|
#if defined(CONFIG_VFD) || defined(CONFIG_LCD)
|
||||||
|
unsigned long addr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Pointer is writable since we allocated a register for it */
|
||||||
|
gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
|
||||||
|
/* compiler optimization barrier needed for GCC >= 3.4 */
|
||||||
|
__asm__ __volatile__("": : :"memory");
|
||||||
|
|
||||||
|
memset ((void*)gd, 0, sizeof (gd_t));
|
||||||
|
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
|
||||||
|
memset (gd->bd, 0, sizeof (bd_t));
|
||||||
|
|
||||||
|
monitor_flash_len = _bss_start - _armboot_start;
|
||||||
|
|
||||||
|
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
|
||||||
|
if ((*init_fnc_ptr)() != 0) {
|
||||||
|
hang ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CFG_NO_FLASH
|
||||||
|
/* configure available FLASH banks */
|
||||||
|
size = flash_init ();
|
||||||
|
display_flash_config (size);
|
||||||
|
#endif /* CFG_NO_FLASH */
|
||||||
|
|
||||||
|
#ifdef CONFIG_VFD
|
||||||
|
# ifndef PAGE_SIZE
|
||||||
|
# define PAGE_SIZE 4096
|
||||||
|
# endif
|
||||||
|
/*
|
||||||
|
* reserve memory for VFD display (always full pages)
|
||||||
|
*/
|
||||||
|
/* bss_end is defined in the board-specific linker script */
|
||||||
|
addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
|
||||||
|
size = vfd_setmem (addr);
|
||||||
|
gd->fb_base = addr;
|
||||||
|
#endif /* CONFIG_VFD */
|
||||||
|
|
||||||
|
#ifdef CONFIG_LCD
|
||||||
|
# ifndef PAGE_SIZE
|
||||||
|
# define PAGE_SIZE 4096
|
||||||
|
# endif
|
||||||
|
/*
|
||||||
|
* reserve memory for LCD display (always full pages)
|
||||||
|
*/
|
||||||
|
/* bss_end is defined in the board-specific linker script */
|
||||||
|
addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
|
||||||
|
size = lcd_setmem (addr);
|
||||||
|
gd->fb_base = addr;
|
||||||
|
#endif /* CONFIG_LCD */
|
||||||
|
|
||||||
|
/* armboot_start is defined in the board-specific linker script */
|
||||||
|
mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);
|
||||||
|
|
||||||
|
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
|
||||||
|
puts ("NAND: ");
|
||||||
|
nand_init(); /* go init the NAND */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* initialize environment */
|
||||||
|
env_relocate ();
|
||||||
|
|
||||||
|
#ifdef CONFIG_VFD
|
||||||
|
/* must do this after the framebuffer is allocated */
|
||||||
|
drv_vfd_init();
|
||||||
|
#endif /* CONFIG_VFD */
|
||||||
|
|
||||||
|
/* IP Address */
|
||||||
|
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
|
||||||
|
|
||||||
|
/* MAC Address */
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
ulong reg;
|
||||||
|
char *s, *e;
|
||||||
|
char tmp[64];
|
||||||
|
|
||||||
|
i = getenv_r ("ethaddr", tmp, sizeof (tmp));
|
||||||
|
s = (i > 0) ? tmp : NULL;
|
||||||
|
|
||||||
|
for (reg = 0; reg < 6; ++reg) {
|
||||||
|
gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
|
||||||
|
if (s)
|
||||||
|
s = (*e) ? e + 1 : e;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_HAS_ETH1
|
||||||
|
i = getenv_r ("eth1addr", tmp, sizeof (tmp));
|
||||||
|
s = (i > 0) ? tmp : NULL;
|
||||||
|
|
||||||
|
for (reg = 0; reg < 6; ++reg) {
|
||||||
|
gd->bd->bi_enet1addr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
|
||||||
|
if (s)
|
||||||
|
s = (*e) ? e + 1 : e;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
devices_init (); /* get the devices list going. */
|
||||||
|
|
||||||
|
#ifdef CONFIG_CMC_PU2
|
||||||
|
load_sernum_ethaddr ();
|
||||||
|
#endif /* CONFIG_CMC_PU2 */
|
||||||
|
|
||||||
|
jumptable_init ();
|
||||||
|
|
||||||
|
console_init_r (); /* fully init console as a device */
|
||||||
|
|
||||||
|
#if defined(CONFIG_MISC_INIT_R)
|
||||||
|
/* miscellaneous platform dependent initialisations */
|
||||||
|
misc_init_r ();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* enable exceptions */
|
||||||
|
enable_interrupts ();
|
||||||
|
|
||||||
|
/* Initialize from environment */
|
||||||
|
if ((s = getenv ("loadaddr")) != NULL) {
|
||||||
|
load_addr = simple_strtoul (s, NULL, 16);
|
||||||
|
}
|
||||||
|
#if (CONFIG_COMMANDS & CFG_CMD_NET)
|
||||||
|
if ((s = getenv ("bootfile")) != NULL) {
|
||||||
|
copy_filename (BootFile, s, sizeof (BootFile));
|
||||||
|
}
|
||||||
|
#endif /* CFG_CMD_NET */
|
||||||
|
|
||||||
|
#ifdef BOARD_LATE_INIT
|
||||||
|
board_late_init ();
|
||||||
|
#endif
|
||||||
|
#if (CONFIG_COMMANDS & CFG_CMD_NET)
|
||||||
|
#if defined(CONFIG_NET_MULTI)
|
||||||
|
puts ("Net: ");
|
||||||
|
#endif
|
||||||
|
eth_initialize(gd->bd);
|
||||||
|
#endif
|
||||||
|
/* main_loop() can return to retry autoboot, if so just run it again. */
|
||||||
|
for (;;) {
|
||||||
|
main_loop ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTREACHED - no way out of command loop except booting */
|
||||||
|
}
|
||||||
|
|
||||||
|
void hang (void)
|
||||||
|
{
|
||||||
|
puts ("### ERROR ### Please RESET the board ###\n");
|
||||||
|
for (;;);
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2002
|
||||||
|
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||||
|
*
|
||||||
|
* See file CREDITS for list of people who contributed to this
|
||||||
|
* project.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||||
|
* MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* for now: just dummy functions to satisfy the linker */
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
|
||||||
|
void flush_cache (unsigned long dummy1, unsigned long dummy2)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_OMAP2420
|
||||||
|
void arm1136_cache_flush(void);
|
||||||
|
|
||||||
|
arm1136_cache_flush();
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2002
|
||||||
|
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||||
|
*
|
||||||
|
* See file CREDITS for list of people who contributed to this
|
||||||
|
* project.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||||
|
* MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Replacement (=dummy) for GNU/Linux division-by zero handler */
|
||||||
|
void __div0 (void)
|
||||||
|
{
|
||||||
|
extern void hang (void);
|
||||||
|
|
||||||
|
hang();
|
||||||
|
}
|
Loading…
Reference in New Issue