bla
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
.macro bitop, instr
|
||||
and r2, r0, #7
|
||||
mov r3, #1
|
||||
mov r3, r3, lsl r2
|
||||
save_and_disable_irqs ip
|
||||
ldrb r2, [r1, r0, lsr #3]
|
||||
\instr r2, r2, r3
|
||||
strb r2, [r1, r0, lsr #3]
|
||||
restore_irqs ip
|
||||
mov pc, lr
|
||||
.endm
|
||||
|
||||
/**
|
||||
* testop - implement a test_and_xxx_bit operation.
|
||||
* @instr: operational instruction
|
||||
* @store: store instruction
|
||||
*
|
||||
* Note: we can trivially conditionalise the store instruction
|
||||
* to avoid dirting the data cache.
|
||||
*/
|
||||
.macro testop, instr, store
|
||||
add r1, r1, r0, lsr #3
|
||||
and r3, r0, #7
|
||||
mov r0, #1
|
||||
save_and_disable_irqs ip
|
||||
ldrb r2, [r1]
|
||||
tst r2, r0, lsl r3
|
||||
\instr r2, r2, r0, lsl r3
|
||||
\store r2, [r1]
|
||||
restore_irqs ip
|
||||
moveq r0, #0
|
||||
mov pc, lr
|
||||
.endm
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* linux/arch/arm/lib/changebit.S
|
||||
*
|
||||
* Copyright (C) 1995-1996 Russell King
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <asm/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
#include "bitops.h"
|
||||
.text
|
||||
|
||||
/* Purpose : Function to change a bit
|
||||
* Prototype: int change_bit(int bit, void *addr)
|
||||
*/
|
||||
ENTRY(_change_bit_be)
|
||||
eor r0, r0, #0x18 @ big endian byte ordering
|
||||
ENTRY(_change_bit_le)
|
||||
bitop eor
|
||||
@@ -0,0 +1,169 @@
|
||||
1 # 1 "lib/changebit.S"
|
||||
1 /*
|
||||
0
|
||||
0
|
||||
2 * linux/arch/arm/lib/changebit.S
|
||||
3 *
|
||||
4 * Copyright (C) 1995-1996 Russell King
|
||||
5 *
|
||||
6 * This program is free software; you can redistribute it and/or modify
|
||||
7 * it under the terms of the GNU General Public License version 2 as
|
||||
8 * published by the Free Software Foundation.
|
||||
9 */
|
||||
10 #include <asm/linkage.h>
|
||||
1 #ifndef __ASM_LINKAGE_H
|
||||
11 #include <asm/assembler.h>
|
||||
1 /*
|
||||
2 * linux/include/asm-arm/assembler.h
|
||||
3 *
|
||||
4 * Copyright (C) 1996-2000 Russell King
|
||||
5 *
|
||||
6 * This program is free software; you can redistribute it and/or modify
|
||||
7 * it under the terms of the GNU General Public License version 2 as
|
||||
8 * published by the Free Software Foundation.
|
||||
9 *
|
||||
10 * This file contains arm architecture specific defines
|
||||
11 * for the different processors.
|
||||
12 *
|
||||
13 * Do not include any C declarations in this file - it is included by
|
||||
14 * assembler source.
|
||||
15 */
|
||||
16 #ifndef __ASSEMBLY__
|
||||
17 #error "Only include this from assembly code"
|
||||
18 #endif
|
||||
19
|
||||
20 #include <asm/ptrace.h>
|
||||
1 /*
|
||||
21
|
||||
22 #define pull lsl
|
||||
23 #define push lsr
|
||||
24 #define get_byte_0 lsr #24
|
||||
25 #define get_byte_1 lsr #16
|
||||
26 #define get_byte_2 lsr #8
|
||||
27 #define get_byte_3 lsl #0
|
||||
28 #define put_byte_0 lsl #24
|
||||
29 #define put_byte_1 lsl #16
|
||||
30 #define put_byte_2 lsl #8
|
||||
31 #define put_byte_3 lsl #0
|
||||
32
|
||||
33 #define PLD(code...)
|
||||
34
|
||||
35 #define MODE_USR USR_MODE
|
||||
36 #define MODE_FIQ FIQ_MODE
|
||||
37 #define MODE_IRQ IRQ_MODE
|
||||
38 #define MODE_SVC SVC_MODE
|
||||
39
|
||||
40 #define DEFAULT_FIQ MODE_FIQ
|
||||
41
|
||||
42 /*
|
||||
43 * LOADREGS - ldm with PC in register list (eg, ldmfd sp!, {pc})
|
||||
44 */
|
||||
45 #ifdef __STDC__
|
||||
46 #define LOADREGS(cond, base, reglist...)\
|
||||
47 ldm##cond base,reglist
|
||||
48 #else
|
||||
49 #define LOADREGS(cond, base, reglist...)\
|
||||
50 ldm/**/cond base,reglist
|
||||
51 #endif
|
||||
52
|
||||
53 /*
|
||||
54 * Build a return instruction for this processor type.
|
||||
55 */
|
||||
56 #define RETINSTR(instr, regs...)\
|
||||
57 instr regs
|
||||
58
|
||||
59 /*
|
||||
60 * Enable and disable interrupts
|
||||
61 */
|
||||
62 .macro disable_irq
|
||||
63 msr cpsr_c, #PSR_I_BIT | SVC_MODE
|
||||
64 .endm
|
||||
65
|
||||
66 .macro enable_irq
|
||||
67 msr cpsr_c, #SVC_MODE
|
||||
68 .endm
|
||||
69
|
||||
70 /*
|
||||
71 * Save the current IRQ state and disable IRQs. Note that this macro
|
||||
72 * assumes FIQs are enabled, and that the processor is in SVC mode.
|
||||
73 */
|
||||
74 .macro save_and_disable_irqs, oldcpsr
|
||||
75 mrs \oldcpsr, cpsr
|
||||
76 disable_irq
|
||||
77 .endm
|
||||
78
|
||||
79 /*
|
||||
80 * Restore interrupt state previously stored in a register. We don't
|
||||
81 * guarantee that this will preserve the flags.
|
||||
82 */
|
||||
83 .macro restore_irqs, oldcpsr
|
||||
84 msr cpsr_c, \oldcpsr
|
||||
85 .endm
|
||||
86
|
||||
87 /*
|
||||
88 * These two are used to save LR/restore PC over a user-based access.
|
||||
89 * The old 26-bit architecture requires that we do. On 32-bit
|
||||
90 * architecture, we can safely ignore this requirement.
|
||||
91 */
|
||||
92 .macro save_lr
|
||||
93 .endm
|
||||
94
|
||||
95 .macro restore_pc
|
||||
96 mov pc, lr
|
||||
97 .endm
|
||||
98 ...
|
||||
12 #include "bitops.h"
|
||||
1 .macro bitop, instr
|
||||
2 and r2, r0, #7
|
||||
3 mov r3, #1
|
||||
4 mov r3, r3, lsl r2
|
||||
5 save_and_disable_irqs ip
|
||||
6 ldrb r2, [r1, r0, lsr #3]
|
||||
7 \instr r2, r2, r3
|
||||
8 strb r2, [r1, r0, lsr #3]
|
||||
9 restore_irqs ip
|
||||
10 mov pc, lr
|
||||
11 .endm
|
||||
12
|
||||
13 /**
|
||||
14 * testop - implement a test_and_xxx_bit operation.
|
||||
15 * @instr: operational instruction
|
||||
16 * @store: store instruction
|
||||
17 *
|
||||
18 * Note: we can trivially conditionalise the store instruction
|
||||
19 * to avoid dirting the data cache.
|
||||
20 */
|
||||
21 .macro testop, instr, store
|
||||
22 add r1, r1, r0, lsr #3
|
||||
23 and r3, r0, #7
|
||||
24 mov r0, #1
|
||||
25 save_and_disable_irqs ip
|
||||
26 ldrb r2, [r1]
|
||||
27 tst r2, r0, lsl r3
|
||||
28 \instr r2, r2, r0, lsl r3
|
||||
29 \store r2, [r1]
|
||||
30 restore_irqs ip
|
||||
31 moveq r0, #0
|
||||
32 mov pc, lr
|
||||
33 .endm
|
||||
34 ...
|
||||
13 .text
|
||||
14
|
||||
15 /* Purpose : Function to change a bit
|
||||
16 * Prototype: int change_bit(int bit, void *addr)
|
||||
17 */
|
||||
18 ENTRY(_change_bit_be)
|
||||
19 0000 180020E2 eor r0, r0, #0x18 @ big endian byte ordering
|
||||
20 ENTRY(_change_bit_le)
|
||||
21 0004 072000E2 bitop eor
|
||||
21 0130A0E3
|
||||
21 1332A0E1
|
||||
21 00C00FE1
|
||||
21 93F021E3
|
||||
DEFINED SYMBOLS
|
||||
lib/changebit.S:18 .text:00000000 _change_bit_be
|
||||
lib/changebit.S:18 .text:00000000 $a
|
||||
lib/changebit.S:20 .text:00000004 _change_bit_le
|
||||
.debug_aranges:0000000c $d
|
||||
|
||||
NO UNDEFINED SYMBOLS
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* linux/arch/arm/lib/clearbit.S
|
||||
*
|
||||
* Copyright (C) 1995-1996 Russell King
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <asm/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
#include "bitops.h"
|
||||
.text
|
||||
|
||||
/*
|
||||
* Purpose : Function to clear a bit
|
||||
* Prototype: int clear_bit(int bit, void *addr)
|
||||
*/
|
||||
ENTRY(_clear_bit_be)
|
||||
eor r0, r0, #0x18 @ big endian byte ordering
|
||||
ENTRY(_clear_bit_le)
|
||||
bitop bic
|
||||
@@ -0,0 +1,170 @@
|
||||
1 # 1 "lib/clearbit.S"
|
||||
1 /*
|
||||
0
|
||||
0
|
||||
2 * linux/arch/arm/lib/clearbit.S
|
||||
3 *
|
||||
4 * Copyright (C) 1995-1996 Russell King
|
||||
5 *
|
||||
6 * This program is free software; you can redistribute it and/or modify
|
||||
7 * it under the terms of the GNU General Public License version 2 as
|
||||
8 * published by the Free Software Foundation.
|
||||
9 */
|
||||
10 #include <asm/linkage.h>
|
||||
1 #ifndef __ASM_LINKAGE_H
|
||||
11 #include <asm/assembler.h>
|
||||
1 /*
|
||||
2 * linux/include/asm-arm/assembler.h
|
||||
3 *
|
||||
4 * Copyright (C) 1996-2000 Russell King
|
||||
5 *
|
||||
6 * This program is free software; you can redistribute it and/or modify
|
||||
7 * it under the terms of the GNU General Public License version 2 as
|
||||
8 * published by the Free Software Foundation.
|
||||
9 *
|
||||
10 * This file contains arm architecture specific defines
|
||||
11 * for the different processors.
|
||||
12 *
|
||||
13 * Do not include any C declarations in this file - it is included by
|
||||
14 * assembler source.
|
||||
15 */
|
||||
16 #ifndef __ASSEMBLY__
|
||||
17 #error "Only include this from assembly code"
|
||||
18 #endif
|
||||
19
|
||||
20 #include <asm/ptrace.h>
|
||||
1 /*
|
||||
21
|
||||
22 #define pull lsl
|
||||
23 #define push lsr
|
||||
24 #define get_byte_0 lsr #24
|
||||
25 #define get_byte_1 lsr #16
|
||||
26 #define get_byte_2 lsr #8
|
||||
27 #define get_byte_3 lsl #0
|
||||
28 #define put_byte_0 lsl #24
|
||||
29 #define put_byte_1 lsl #16
|
||||
30 #define put_byte_2 lsl #8
|
||||
31 #define put_byte_3 lsl #0
|
||||
32
|
||||
33 #define PLD(code...)
|
||||
34
|
||||
35 #define MODE_USR USR_MODE
|
||||
36 #define MODE_FIQ FIQ_MODE
|
||||
37 #define MODE_IRQ IRQ_MODE
|
||||
38 #define MODE_SVC SVC_MODE
|
||||
39
|
||||
40 #define DEFAULT_FIQ MODE_FIQ
|
||||
41
|
||||
42 /*
|
||||
43 * LOADREGS - ldm with PC in register list (eg, ldmfd sp!, {pc})
|
||||
44 */
|
||||
45 #ifdef __STDC__
|
||||
46 #define LOADREGS(cond, base, reglist...)\
|
||||
47 ldm##cond base,reglist
|
||||
48 #else
|
||||
49 #define LOADREGS(cond, base, reglist...)\
|
||||
50 ldm/**/cond base,reglist
|
||||
51 #endif
|
||||
52
|
||||
53 /*
|
||||
54 * Build a return instruction for this processor type.
|
||||
55 */
|
||||
56 #define RETINSTR(instr, regs...)\
|
||||
57 instr regs
|
||||
58
|
||||
59 /*
|
||||
60 * Enable and disable interrupts
|
||||
61 */
|
||||
62 .macro disable_irq
|
||||
63 msr cpsr_c, #PSR_I_BIT | SVC_MODE
|
||||
64 .endm
|
||||
65
|
||||
66 .macro enable_irq
|
||||
67 msr cpsr_c, #SVC_MODE
|
||||
68 .endm
|
||||
69
|
||||
70 /*
|
||||
71 * Save the current IRQ state and disable IRQs. Note that this macro
|
||||
72 * assumes FIQs are enabled, and that the processor is in SVC mode.
|
||||
73 */
|
||||
74 .macro save_and_disable_irqs, oldcpsr
|
||||
75 mrs \oldcpsr, cpsr
|
||||
76 disable_irq
|
||||
77 .endm
|
||||
78
|
||||
79 /*
|
||||
80 * Restore interrupt state previously stored in a register. We don't
|
||||
81 * guarantee that this will preserve the flags.
|
||||
82 */
|
||||
83 .macro restore_irqs, oldcpsr
|
||||
84 msr cpsr_c, \oldcpsr
|
||||
85 .endm
|
||||
86
|
||||
87 /*
|
||||
88 * These two are used to save LR/restore PC over a user-based access.
|
||||
89 * The old 26-bit architecture requires that we do. On 32-bit
|
||||
90 * architecture, we can safely ignore this requirement.
|
||||
91 */
|
||||
92 .macro save_lr
|
||||
93 .endm
|
||||
94
|
||||
95 .macro restore_pc
|
||||
96 mov pc, lr
|
||||
97 .endm
|
||||
98 ...
|
||||
12 #include "bitops.h"
|
||||
1 .macro bitop, instr
|
||||
2 and r2, r0, #7
|
||||
3 mov r3, #1
|
||||
4 mov r3, r3, lsl r2
|
||||
5 save_and_disable_irqs ip
|
||||
6 ldrb r2, [r1, r0, lsr #3]
|
||||
7 \instr r2, r2, r3
|
||||
8 strb r2, [r1, r0, lsr #3]
|
||||
9 restore_irqs ip
|
||||
10 mov pc, lr
|
||||
11 .endm
|
||||
12
|
||||
13 /**
|
||||
14 * testop - implement a test_and_xxx_bit operation.
|
||||
15 * @instr: operational instruction
|
||||
16 * @store: store instruction
|
||||
17 *
|
||||
18 * Note: we can trivially conditionalise the store instruction
|
||||
19 * to avoid dirting the data cache.
|
||||
20 */
|
||||
21 .macro testop, instr, store
|
||||
22 add r1, r1, r0, lsr #3
|
||||
23 and r3, r0, #7
|
||||
24 mov r0, #1
|
||||
25 save_and_disable_irqs ip
|
||||
26 ldrb r2, [r1]
|
||||
27 tst r2, r0, lsl r3
|
||||
28 \instr r2, r2, r0, lsl r3
|
||||
29 \store r2, [r1]
|
||||
30 restore_irqs ip
|
||||
31 moveq r0, #0
|
||||
32 mov pc, lr
|
||||
33 .endm
|
||||
34 ...
|
||||
13 .text
|
||||
14
|
||||
15 /*
|
||||
16 * Purpose : Function to clear a bit
|
||||
17 * Prototype: int clear_bit(int bit, void *addr)
|
||||
18 */
|
||||
19 ENTRY(_clear_bit_be)
|
||||
20 0000 180020E2 eor r0, r0, #0x18 @ big endian byte ordering
|
||||
21 ENTRY(_clear_bit_le)
|
||||
22 0004 072000E2 bitop bic
|
||||
22 0130A0E3
|
||||
22 1332A0E1
|
||||
22 00C00FE1
|
||||
22 93F021E3
|
||||
DEFINED SYMBOLS
|
||||
lib/clearbit.S:19 .text:00000000 _clear_bit_be
|
||||
lib/clearbit.S:19 .text:00000000 $a
|
||||
lib/clearbit.S:21 .text:00000004 _clear_bit_le
|
||||
.debug_aranges:0000000c $d
|
||||
|
||||
NO UNDEFINED SYMBOLS
|
||||
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* linux/arch/arm/lib/copy_template.s
|
||||
*
|
||||
* Code template for optimized memory copy functions
|
||||
*
|
||||
* Author: Nicolas Pitre
|
||||
* Created: Sep 28, 2005
|
||||
* Copyright: MontaVista Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This can be used to enable code to cacheline align the source pointer.
|
||||
* Experiments on tested architectures (StrongARM and XScale) didn't show
|
||||
* this a worthwhile thing to do. That might be different in the future.
|
||||
*/
|
||||
//#define CALGN(code...) code
|
||||
#define CALGN(code...)
|
||||
|
||||
/*
|
||||
* Theory of operation
|
||||
* -------------------
|
||||
*
|
||||
* This file provides the core code for a forward memory copy used in
|
||||
* the implementation of memcopy(), copy_to_user() and copy_from_user().
|
||||
*
|
||||
* The including file must define the following accessor macros
|
||||
* according to the need of the given function:
|
||||
*
|
||||
* ldr1w ptr reg abort
|
||||
*
|
||||
* This loads one word from 'ptr', stores it in 'reg' and increments
|
||||
* 'ptr' to the next word. The 'abort' argument is used for fixup tables.
|
||||
*
|
||||
* ldr4w ptr reg1 reg2 reg3 reg4 abort
|
||||
* ldr8w ptr, reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
|
||||
*
|
||||
* This loads four or eight words starting from 'ptr', stores them
|
||||
* in provided registers and increments 'ptr' past those words.
|
||||
* The'abort' argument is used for fixup tables.
|
||||
*
|
||||
* ldr1b ptr reg cond abort
|
||||
*
|
||||
* Similar to ldr1w, but it loads a byte and increments 'ptr' one byte.
|
||||
* It also must apply the condition code if provided, otherwise the
|
||||
* "al" condition is assumed by default.
|
||||
*
|
||||
* str1w ptr reg abort
|
||||
* str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
|
||||
* str1b ptr reg cond abort
|
||||
*
|
||||
* Same as their ldr* counterparts, but data is stored to 'ptr' location
|
||||
* rather than being loaded.
|
||||
*
|
||||
* enter reg1 reg2
|
||||
*
|
||||
* Preserve the provided registers on the stack plus any additional
|
||||
* data as needed by the implementation including this code. Called
|
||||
* upon code entry.
|
||||
*
|
||||
* exit reg1 reg2
|
||||
*
|
||||
* Restore registers with the values previously saved with the
|
||||
* 'preserv' macro. Called upon code termination.
|
||||
*/
|
||||
|
||||
|
||||
enter r4, lr
|
||||
|
||||
subs r2, r2, #4
|
||||
blt 8f
|
||||
ands ip, r0, #3
|
||||
PLD( pld [r1, #0] )
|
||||
bne 9f
|
||||
ands ip, r1, #3
|
||||
bne 10f
|
||||
|
||||
1: subs r2, r2, #(28)
|
||||
stmfd sp!, {r5 - r8}
|
||||
blt 5f
|
||||
|
||||
CALGN( ands ip, r1, #31 )
|
||||
CALGN( rsb r3, ip, #32 )
|
||||
CALGN( sbcnes r4, r3, r2 ) @ C is always set here
|
||||
CALGN( bcs 2f )
|
||||
CALGN( adr r4, 6f )
|
||||
CALGN( subs r2, r2, r3 ) @ C gets set
|
||||
CALGN( add pc, r4, ip )
|
||||
|
||||
PLD( pld [r1, #0] )
|
||||
2: PLD( subs r2, r2, #96 )
|
||||
PLD( pld [r1, #28] )
|
||||
PLD( blt 4f )
|
||||
PLD( pld [r1, #60] )
|
||||
PLD( pld [r1, #92] )
|
||||
|
||||
3: PLD( pld [r1, #124] )
|
||||
4: ldr8w r1, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f
|
||||
subs r2, r2, #32
|
||||
str8w r0, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f
|
||||
bge 3b
|
||||
PLD( cmn r2, #96 )
|
||||
PLD( bge 4b )
|
||||
|
||||
5: ands ip, r2, #28
|
||||
rsb ip, ip, #32
|
||||
addne pc, pc, ip @ C is always clear here
|
||||
b 7f
|
||||
6: nop
|
||||
ldr1w r1, r3, abort=20f
|
||||
ldr1w r1, r4, abort=20f
|
||||
ldr1w r1, r5, abort=20f
|
||||
ldr1w r1, r6, abort=20f
|
||||
ldr1w r1, r7, abort=20f
|
||||
ldr1w r1, r8, abort=20f
|
||||
ldr1w r1, lr, abort=20f
|
||||
|
||||
add pc, pc, ip
|
||||
nop
|
||||
nop
|
||||
str1w r0, r3, abort=20f
|
||||
str1w r0, r4, abort=20f
|
||||
str1w r0, r5, abort=20f
|
||||
str1w r0, r6, abort=20f
|
||||
str1w r0, r7, abort=20f
|
||||
str1w r0, r8, abort=20f
|
||||
str1w r0, lr, abort=20f
|
||||
|
||||
CALGN( bcs 2b )
|
||||
|
||||
7: ldmfd sp!, {r5 - r8}
|
||||
|
||||
8: movs r2, r2, lsl #31
|
||||
ldr1b r1, r3, ne, abort=21f
|
||||
ldr1b r1, r4, cs, abort=21f
|
||||
ldr1b r1, ip, cs, abort=21f
|
||||
str1b r0, r3, ne, abort=21f
|
||||
str1b r0, r4, cs, abort=21f
|
||||
str1b r0, ip, cs, abort=21f
|
||||
|
||||
exit r4, pc
|
||||
|
||||
9: rsb ip, ip, #4
|
||||
cmp ip, #2
|
||||
ldr1b r1, r3, gt, abort=21f
|
||||
ldr1b r1, r4, ge, abort=21f
|
||||
ldr1b r1, lr, abort=21f
|
||||
str1b r0, r3, gt, abort=21f
|
||||
str1b r0, r4, ge, abort=21f
|
||||
subs r2, r2, ip
|
||||
str1b r0, lr, abort=21f
|
||||
blt 8b
|
||||
ands ip, r1, #3
|
||||
beq 1b
|
||||
|
||||
10: bic r1, r1, #3
|
||||
cmp ip, #2
|
||||
ldr1w r1, lr, abort=21f
|
||||
beq 17f
|
||||
bgt 18f
|
||||
|
||||
|
||||
.macro forward_copy_shift pull push
|
||||
|
||||
subs r2, r2, #28
|
||||
blt 14f
|
||||
|
||||
CALGN( ands ip, r1, #31 )
|
||||
CALGN( rsb ip, ip, #32 )
|
||||
CALGN( sbcnes r4, ip, r2 ) @ C is always set here
|
||||
CALGN( subcc r2, r2, ip )
|
||||
CALGN( bcc 15f )
|
||||
|
||||
11: stmfd sp!, {r5 - r9}
|
||||
|
||||
PLD( pld [r1, #0] )
|
||||
PLD( subs r2, r2, #96 )
|
||||
PLD( pld [r1, #28] )
|
||||
PLD( blt 13f )
|
||||
PLD( pld [r1, #60] )
|
||||
PLD( pld [r1, #92] )
|
||||
|
||||
12: PLD( pld [r1, #124] )
|
||||
13: ldr4w r1, r4, r5, r6, r7, abort=19f
|
||||
mov r3, lr, pull #\pull
|
||||
subs r2, r2, #32
|
||||
ldr4w r1, r8, r9, ip, lr, abort=19f
|
||||
orr r3, r3, r4, push #\push
|
||||
mov r4, r4, pull #\pull
|
||||
orr r4, r4, r5, push #\push
|
||||
mov r5, r5, pull #\pull
|
||||
orr r5, r5, r6, push #\push
|
||||
mov r6, r6, pull #\pull
|
||||
orr r6, r6, r7, push #\push
|
||||
mov r7, r7, pull #\pull
|
||||
orr r7, r7, r8, push #\push
|
||||
mov r8, r8, pull #\pull
|
||||
orr r8, r8, r9, push #\push
|
||||
mov r9, r9, pull #\pull
|
||||
orr r9, r9, ip, push #\push
|
||||
mov ip, ip, pull #\pull
|
||||
orr ip, ip, lr, push #\push
|
||||
str8w r0, r3, r4, r5, r6, r7, r8, r9, ip, , abort=19f
|
||||
bge 12b
|
||||
PLD( cmn r2, #96 )
|
||||
PLD( bge 13b )
|
||||
|
||||
ldmfd sp!, {r5 - r9}
|
||||
|
||||
14: ands ip, r2, #28
|
||||
beq 16f
|
||||
|
||||
15: mov r3, lr, pull #\pull
|
||||
ldr1w r1, lr, abort=21f
|
||||
subs ip, ip, #4
|
||||
orr r3, r3, lr, push #\push
|
||||
str1w r0, r3, abort=21f
|
||||
bgt 15b
|
||||
CALGN( cmp r2, #0 )
|
||||
CALGN( bge 11b )
|
||||
|
||||
16: sub r1, r1, #(\push / 8)
|
||||
b 8b
|
||||
|
||||
.endm
|
||||
|
||||
|
||||
forward_copy_shift pull=8 push=24
|
||||
|
||||
17: forward_copy_shift pull=16 push=16
|
||||
|
||||
18: forward_copy_shift pull=24 push=8
|
||||
|
||||
|
||||
/*
|
||||
* Abort preamble and completion macros.
|
||||
* If a fixup handler is required then those macros must surround it.
|
||||
* It is assumed that the fixup code will handle the private part of
|
||||
* the exit macro.
|
||||
*/
|
||||
|
||||
.macro copy_abort_preamble
|
||||
19: ldmfd sp!, {r5 - r9}
|
||||
b 21f
|
||||
20: ldmfd sp!, {r5 - r8}
|
||||
21:
|
||||
.endm
|
||||
|
||||
.macro copy_abort_end
|
||||
ldmfd sp!, {r4, pc}
|
||||
.endm
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* linux/lib/ctype.c
|
||||
*
|
||||
* Copyright (C) 1991, 1992 Linus Torvalds
|
||||
*/
|
||||
|
||||
#include <asm/ctype.h>
|
||||
|
||||
unsigned char _ctype[] = {
|
||||
_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
|
||||
_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
|
||||
_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
|
||||
_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
|
||||
_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
|
||||
_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
|
||||
_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
|
||||
_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
|
||||
_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
|
||||
_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
|
||||
_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
|
||||
_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
|
||||
_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
|
||||
_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
|
||||
_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
|
||||
_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
|
||||
_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
|
||||
_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
|
||||
_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
|
||||
_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
|
||||
_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
|
||||
_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
|
||||
|
||||
@@ -0,0 +1,281 @@
|
||||
1 .cpu arm7tdmi
|
||||
2 .fpu softvfp
|
||||
3 .eabi_attribute 20, 1
|
||||
4 .eabi_attribute 21, 1
|
||||
5 .eabi_attribute 23, 3
|
||||
6 .eabi_attribute 24, 1
|
||||
7 .eabi_attribute 25, 1
|
||||
8 .eabi_attribute 26, 1
|
||||
9 .eabi_attribute 30, 4
|
||||
10 .eabi_attribute 18, 4
|
||||
11 .file "ctype.c"
|
||||
19 .Ltext0:
|
||||
20 .cfi_sections .debug_frame
|
||||
21 .global _ctype
|
||||
22 .data
|
||||
25 _ctype:
|
||||
26 0000 08 .byte 8
|
||||
27 0001 08 .byte 8
|
||||
28 0002 08 .byte 8
|
||||
29 0003 08 .byte 8
|
||||
30 0004 08 .byte 8
|
||||
31 0005 08 .byte 8
|
||||
32 0006 08 .byte 8
|
||||
33 0007 08 .byte 8
|
||||
34 0008 08 .byte 8
|
||||
35 0009 28 .byte 40
|
||||
36 000a 28 .byte 40
|
||||
37 000b 28 .byte 40
|
||||
38 000c 28 .byte 40
|
||||
39 000d 28 .byte 40
|
||||
40 000e 08 .byte 8
|
||||
41 000f 08 .byte 8
|
||||
42 0010 08 .byte 8
|
||||
43 0011 08 .byte 8
|
||||
44 0012 08 .byte 8
|
||||
45 0013 08 .byte 8
|
||||
46 0014 08 .byte 8
|
||||
47 0015 08 .byte 8
|
||||
48 0016 08 .byte 8
|
||||
49 0017 08 .byte 8
|
||||
50 0018 08 .byte 8
|
||||
51 0019 08 .byte 8
|
||||
52 001a 08 .byte 8
|
||||
53 001b 08 .byte 8
|
||||
54 001c 08 .byte 8
|
||||
55 001d 08 .byte 8
|
||||
56 001e 08 .byte 8
|
||||
57 001f 08 .byte 8
|
||||
58 0020 A0 .byte -96
|
||||
59 0021 10 .byte 16
|
||||
60 0022 10 .byte 16
|
||||
61 0023 10 .byte 16
|
||||
62 0024 10 .byte 16
|
||||
63 0025 10 .byte 16
|
||||
64 0026 10 .byte 16
|
||||
65 0027 10 .byte 16
|
||||
66 0028 10 .byte 16
|
||||
67 0029 10 .byte 16
|
||||
68 002a 10 .byte 16
|
||||
69 002b 10 .byte 16
|
||||
70 002c 10 .byte 16
|
||||
71 002d 10 .byte 16
|
||||
72 002e 10 .byte 16
|
||||
73 002f 10 .byte 16
|
||||
74 0030 04 .byte 4
|
||||
75 0031 04 .byte 4
|
||||
76 0032 04 .byte 4
|
||||
77 0033 04 .byte 4
|
||||
78 0034 04 .byte 4
|
||||
79 0035 04 .byte 4
|
||||
80 0036 04 .byte 4
|
||||
81 0037 04 .byte 4
|
||||
82 0038 04 .byte 4
|
||||
83 0039 04 .byte 4
|
||||
84 003a 10 .byte 16
|
||||
85 003b 10 .byte 16
|
||||
86 003c 10 .byte 16
|
||||
87 003d 10 .byte 16
|
||||
88 003e 10 .byte 16
|
||||
89 003f 10 .byte 16
|
||||
90 0040 10 .byte 16
|
||||
91 0041 41 .byte 65
|
||||
92 0042 41 .byte 65
|
||||
93 0043 41 .byte 65
|
||||
94 0044 41 .byte 65
|
||||
95 0045 41 .byte 65
|
||||
96 0046 41 .byte 65
|
||||
97 0047 01 .byte 1
|
||||
98 0048 01 .byte 1
|
||||
99 0049 01 .byte 1
|
||||
100 004a 01 .byte 1
|
||||
101 004b 01 .byte 1
|
||||
102 004c 01 .byte 1
|
||||
103 004d 01 .byte 1
|
||||
104 004e 01 .byte 1
|
||||
105 004f 01 .byte 1
|
||||
106 0050 01 .byte 1
|
||||
107 0051 01 .byte 1
|
||||
108 0052 01 .byte 1
|
||||
109 0053 01 .byte 1
|
||||
110 0054 01 .byte 1
|
||||
111 0055 01 .byte 1
|
||||
112 0056 01 .byte 1
|
||||
113 0057 01 .byte 1
|
||||
114 0058 01 .byte 1
|
||||
115 0059 01 .byte 1
|
||||
116 005a 01 .byte 1
|
||||
117 005b 10 .byte 16
|
||||
118 005c 10 .byte 16
|
||||
119 005d 10 .byte 16
|
||||
120 005e 10 .byte 16
|
||||
121 005f 10 .byte 16
|
||||
122 0060 10 .byte 16
|
||||
123 0061 42 .byte 66
|
||||
124 0062 42 .byte 66
|
||||
125 0063 42 .byte 66
|
||||
126 0064 42 .byte 66
|
||||
127 0065 42 .byte 66
|
||||
128 0066 42 .byte 66
|
||||
129 0067 02 .byte 2
|
||||
130 0068 02 .byte 2
|
||||
131 0069 02 .byte 2
|
||||
132 006a 02 .byte 2
|
||||
133 006b 02 .byte 2
|
||||
134 006c 02 .byte 2
|
||||
135 006d 02 .byte 2
|
||||
136 006e 02 .byte 2
|
||||
137 006f 02 .byte 2
|
||||
138 0070 02 .byte 2
|
||||
139 0071 02 .byte 2
|
||||
140 0072 02 .byte 2
|
||||
141 0073 02 .byte 2
|
||||
142 0074 02 .byte 2
|
||||
143 0075 02 .byte 2
|
||||
144 0076 02 .byte 2
|
||||
145 0077 02 .byte 2
|
||||
146 0078 02 .byte 2
|
||||
147 0079 02 .byte 2
|
||||
148 007a 02 .byte 2
|
||||
149 007b 10 .byte 16
|
||||
150 007c 10 .byte 16
|
||||
151 007d 10 .byte 16
|
||||
152 007e 10 .byte 16
|
||||
153 007f 08 .byte 8
|
||||
154 0080 00 .byte 0
|
||||
155 0081 00 .byte 0
|
||||
156 0082 00 .byte 0
|
||||
157 0083 00 .byte 0
|
||||
158 0084 00 .byte 0
|
||||
159 0085 00 .byte 0
|
||||
160 0086 00 .byte 0
|
||||
161 0087 00 .byte 0
|
||||
162 0088 00 .byte 0
|
||||
163 0089 00 .byte 0
|
||||
164 008a 00 .byte 0
|
||||
165 008b 00 .byte 0
|
||||
166 008c 00 .byte 0
|
||||
167 008d 00 .byte 0
|
||||
168 008e 00 .byte 0
|
||||
169 008f 00 .byte 0
|
||||
170 0090 00 .byte 0
|
||||
171 0091 00 .byte 0
|
||||
172 0092 00 .byte 0
|
||||
173 0093 00 .byte 0
|
||||
174 0094 00 .byte 0
|
||||
175 0095 00 .byte 0
|
||||
176 0096 00 .byte 0
|
||||
177 0097 00 .byte 0
|
||||
178 0098 00 .byte 0
|
||||
179 0099 00 .byte 0
|
||||
180 009a 00 .byte 0
|
||||
181 009b 00 .byte 0
|
||||
182 009c 00 .byte 0
|
||||
183 009d 00 .byte 0
|
||||
184 009e 00 .byte 0
|
||||
185 009f 00 .byte 0
|
||||
186 00a0 A0 .byte -96
|
||||
187 00a1 10 .byte 16
|
||||
188 00a2 10 .byte 16
|
||||
189 00a3 10 .byte 16
|
||||
190 00a4 10 .byte 16
|
||||
191 00a5 10 .byte 16
|
||||
192 00a6 10 .byte 16
|
||||
193 00a7 10 .byte 16
|
||||
194 00a8 10 .byte 16
|
||||
195 00a9 10 .byte 16
|
||||
196 00aa 10 .byte 16
|
||||
197 00ab 10 .byte 16
|
||||
198 00ac 10 .byte 16
|
||||
199 00ad 10 .byte 16
|
||||
200 00ae 10 .byte 16
|
||||
201 00af 10 .byte 16
|
||||
202 00b0 10 .byte 16
|
||||
203 00b1 10 .byte 16
|
||||
204 00b2 10 .byte 16
|
||||
205 00b3 10 .byte 16
|
||||
206 00b4 10 .byte 16
|
||||
207 00b5 10 .byte 16
|
||||
208 00b6 10 .byte 16
|
||||
209 00b7 10 .byte 16
|
||||
210 00b8 10 .byte 16
|
||||
211 00b9 10 .byte 16
|
||||
212 00ba 10 .byte 16
|
||||
213 00bb 10 .byte 16
|
||||
214 00bc 10 .byte 16
|
||||
215 00bd 10 .byte 16
|
||||
216 00be 10 .byte 16
|
||||
217 00bf 10 .byte 16
|
||||
218 00c0 01 .byte 1
|
||||
219 00c1 01 .byte 1
|
||||
220 00c2 01 .byte 1
|
||||
221 00c3 01 .byte 1
|
||||
222 00c4 01 .byte 1
|
||||
223 00c5 01 .byte 1
|
||||
224 00c6 01 .byte 1
|
||||
225 00c7 01 .byte 1
|
||||
226 00c8 01 .byte 1
|
||||
227 00c9 01 .byte 1
|
||||
228 00ca 01 .byte 1
|
||||
229 00cb 01 .byte 1
|
||||
230 00cc 01 .byte 1
|
||||
231 00cd 01 .byte 1
|
||||
232 00ce 01 .byte 1
|
||||
233 00cf 01 .byte 1
|
||||
234 00d0 01 .byte 1
|
||||
235 00d1 01 .byte 1
|
||||
236 00d2 01 .byte 1
|
||||
237 00d3 01 .byte 1
|
||||
238 00d4 01 .byte 1
|
||||
239 00d5 01 .byte 1
|
||||
240 00d6 01 .byte 1
|
||||
241 00d7 10 .byte 16
|
||||
242 00d8 01 .byte 1
|
||||
243 00d9 01 .byte 1
|
||||
244 00da 01 .byte 1
|
||||
245 00db 01 .byte 1
|
||||
246 00dc 01 .byte 1
|
||||
247 00dd 01 .byte 1
|
||||
248 00de 01 .byte 1
|
||||
249 00df 02 .byte 2
|
||||
250 00e0 02 .byte 2
|
||||
251 00e1 02 .byte 2
|
||||
252 00e2 02 .byte 2
|
||||
253 00e3 02 .byte 2
|
||||
254 00e4 02 .byte 2
|
||||
255 00e5 02 .byte 2
|
||||
256 00e6 02 .byte 2
|
||||
257 00e7 02 .byte 2
|
||||
258 00e8 02 .byte 2
|
||||
259 00e9 02 .byte 2
|
||||
260 00ea 02 .byte 2
|
||||
261 00eb 02 .byte 2
|
||||
262 00ec 02 .byte 2
|
||||
263 00ed 02 .byte 2
|
||||
264 00ee 02 .byte 2
|
||||
265 00ef 02 .byte 2
|
||||
266 00f0 02 .byte 2
|
||||
267 00f1 02 .byte 2
|
||||
268 00f2 02 .byte 2
|
||||
269 00f3 02 .byte 2
|
||||
270 00f4 02 .byte 2
|
||||
271 00f5 02 .byte 2
|
||||
272 00f6 02 .byte 2
|
||||
273 00f7 10 .byte 16
|
||||
274 00f8 02 .byte 2
|
||||
275 00f9 02 .byte 2
|
||||
276 00fa 02 .byte 2
|
||||
277 00fb 02 .byte 2
|
||||
278 00fc 02 .byte 2
|
||||
279 00fd 02 .byte 2
|
||||
280 00fe 02 .byte 2
|
||||
281 00ff 02 .byte 2
|
||||
282 .text
|
||||
283 .Letext0:
|
||||
284 .file 1 "include/asm/ctype.h"
|
||||
285 .file 2 "lib/ctype.c"
|
||||
DEFINED SYMBOLS
|
||||
*ABS*:00000000 ctype.c
|
||||
C:\Users\netz\AppData\Local\Temp\cc1cqvvg.s:25 .data:00000000 _ctype
|
||||
|
||||
NO UNDEFINED SYMBOLS
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* linux/arch/arm/lib/div64.S
|
||||
*
|
||||
* Optimized computation of 64-bit dividend / 32-bit divisor
|
||||
*
|
||||
* Author: Nicolas Pitre
|
||||
* Created: Oct 5, 2003
|
||||
* Copyright: Monta Vista Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <asm/linkage.h>
|
||||
|
||||
#ifdef __ARMEB__
|
||||
#define xh r0
|
||||
#define xl r1
|
||||
#define yh r2
|
||||
#define yl r3
|
||||
#else
|
||||
#define xl r0
|
||||
#define xh r1
|
||||
#define yl r2
|
||||
#define yh r3
|
||||
#endif
|
||||
|
||||
/*
|
||||
* __do_div64: perform a division with 64-bit dividend and 32-bit divisor.
|
||||
*
|
||||
* Note: Calling convention is totally non standard for optimal code.
|
||||
* This is meant to be used by do_div() from include/asm/div64.h only.
|
||||
*
|
||||
* Input parameters:
|
||||
* xh-xl = dividend (clobbered)
|
||||
* r4 = divisor (preserved)
|
||||
*
|
||||
* Output values:
|
||||
* yh-yl = result
|
||||
* xh = remainder
|
||||
*
|
||||
* Clobbered regs: xl, ip
|
||||
*/
|
||||
|
||||
ENTRY(__do_div64)
|
||||
|
||||
@ Test for easy paths first.
|
||||
subs ip, r4, #1
|
||||
bls 9f @ divisor is 0 or 1
|
||||
tst ip, r4
|
||||
beq 8f @ divisor is power of 2
|
||||
|
||||
@ See if we need to handle upper 32-bit result.
|
||||
cmp xh, r4
|
||||
mov yh, #0
|
||||
blo 3f
|
||||
|
||||
@ Align divisor with upper part of dividend.
|
||||
@ The aligned divisor is stored in yl preserving the original.
|
||||
@ The bit position is stored in ip.
|
||||
|
||||
#if __LINUX_ARM_ARCH__ >= 5
|
||||
|
||||
clz yl, r4
|
||||
clz ip, xh
|
||||
sub yl, yl, ip
|
||||
mov ip, #1
|
||||
mov ip, ip, lsl yl
|
||||
mov yl, r4, lsl yl
|
||||
|
||||
#else
|
||||
|
||||
mov yl, r4
|
||||
mov ip, #1
|
||||
1: cmp yl, #0x80000000
|
||||
cmpcc yl, xh
|
||||
movcc yl, yl, lsl #1
|
||||
movcc ip, ip, lsl #1
|
||||
bcc 1b
|
||||
|
||||
#endif
|
||||
|
||||
@ The division loop for needed upper bit positions.
|
||||
@ Break out early if dividend reaches 0.
|
||||
2: cmp xh, yl
|
||||
orrcs yh, yh, ip
|
||||
subcss xh, xh, yl
|
||||
movnes ip, ip, lsr #1
|
||||
mov yl, yl, lsr #1
|
||||
bne 2b
|
||||
|
||||
@ See if we need to handle lower 32-bit result.
|
||||
3: cmp xh, #0
|
||||
mov yl, #0
|
||||
cmpeq xl, r4
|
||||
movlo xh, xl
|
||||
movlo pc, lr
|
||||
|
||||
@ The division loop for lower bit positions.
|
||||
@ Here we shift remainer bits leftwards rather than moving the
|
||||
@ divisor for comparisons, considering the carry-out bit as well.
|
||||
mov ip, #0x80000000
|
||||
4: movs xl, xl, lsl #1
|
||||
adcs xh, xh, xh
|
||||
beq 6f
|
||||
cmpcc xh, r4
|
||||
5: orrcs yl, yl, ip
|
||||
subcs xh, xh, r4
|
||||
movs ip, ip, lsr #1
|
||||
bne 4b
|
||||
mov pc, lr
|
||||
|
||||
@ The top part of remainder became zero. If carry is set
|
||||
@ (the 33th bit) this is a false positive so resume the loop.
|
||||
@ Otherwise, if lower part is also null then we are done.
|
||||
6: bcs 5b
|
||||
cmp xl, #0
|
||||
moveq pc, lr
|
||||
|
||||
@ We still have remainer bits in the low part. Bring them up.
|
||||
|
||||
#if __LINUX_ARM_ARCH__ >= 5
|
||||
|
||||
clz xh, xl @ we know xh is zero here so...
|
||||
add xh, xh, #1
|
||||
mov xl, xl, lsl xh
|
||||
mov ip, ip, lsr xh
|
||||
|
||||
#else
|
||||
|
||||
7: movs xl, xl, lsl #1
|
||||
mov ip, ip, lsr #1
|
||||
bcc 7b
|
||||
|
||||
#endif
|
||||
|
||||
@ Current remainder is now 1. It is worthless to compare with
|
||||
@ divisor at this point since divisor can not be smaller than 3 here.
|
||||
@ If possible, branch for another shift in the division loop.
|
||||
@ If no bit position left then we are done.
|
||||
movs ip, ip, lsr #1
|
||||
mov xh, #1
|
||||
bne 4b
|
||||
mov pc, lr
|
||||
|
||||
8: @ Division by a power of 2: determine what that divisor order is
|
||||
@ then simply shift values around
|
||||
|
||||
#if __LINUX_ARM_ARCH__ >= 5
|
||||
|
||||
clz ip, r4
|
||||
rsb ip, ip, #31
|
||||
|
||||
#else
|
||||
|
||||
mov yl, r4
|
||||
cmp r4, #(1 << 16)
|
||||
mov ip, #0
|
||||
movhs yl, yl, lsr #16
|
||||
movhs ip, #16
|
||||
|
||||
cmp yl, #(1 << 8)
|
||||
movhs yl, yl, lsr #8
|
||||
addhs ip, ip, #8
|
||||
|
||||
cmp yl, #(1 << 4)
|
||||
movhs yl, yl, lsr #4
|
||||
addhs ip, ip, #4
|
||||
|
||||
cmp yl, #(1 << 2)
|
||||
addhi ip, ip, #3
|
||||
addls ip, ip, yl, lsr #1
|
||||
|
||||
#endif
|
||||
|
||||
mov yh, xh, lsr ip
|
||||
mov yl, xl, lsr ip
|
||||
rsb ip, ip, #32
|
||||
orr yl, yl, xh, lsl ip
|
||||
mov xh, xl, lsl ip
|
||||
mov xh, xh, lsr ip
|
||||
mov pc, lr
|
||||
|
||||
@ eq -> division by 1: obvious enough...
|
||||
9: moveq yl, xl
|
||||
moveq yh, xh
|
||||
moveq xh, #0
|
||||
moveq pc, lr
|
||||
|
||||
@ Division by 0:
|
||||
str lr, [sp, #-8]!
|
||||
bl __div0
|
||||
|
||||
@ as wrong as it could be...
|
||||
mov yl, #0
|
||||
mov yh, #0
|
||||
mov xh, #0
|
||||
ldr pc, [sp], #8
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
1 # 1 "lib/div64.S"
|
||||
1 /*
|
||||
0
|
||||
0
|
||||
2 * linux/arch/arm/lib/div64.S
|
||||
3 *
|
||||
4 * Optimized computation of 64-bit dividend / 32-bit divisor
|
||||
5 *
|
||||
6 * Author: Nicolas Pitre
|
||||
7 * Created: Oct 5, 2003
|
||||
8 * Copyright: Monta Vista Software, Inc.
|
||||
9 *
|
||||
10 * This program is free software; you can redistribute it and/or modify
|
||||
11 * it under the terms of the GNU General Public License version 2 as
|
||||
12 * published by the Free Software Foundation.
|
||||
13 */
|
||||
14
|
||||
15 #include <asm/linkage.h>
|
||||
1 #ifndef __ASM_LINKAGE_H
|
||||
16
|
||||
17 #ifdef __ARMEB__
|
||||
18 #define xh r0
|
||||
19 #define xl r1
|
||||
20 #define yh r2
|
||||
21 #define yl r3
|
||||
22 #else
|
||||
23 #define xl r0
|
||||
24 #define xh r1
|
||||
25 #define yl r2
|
||||
26 #define yh r3
|
||||
27 #endif
|
||||
28
|
||||
29 /*
|
||||
30 * __do_div64: perform a division with 64-bit dividend and 32-bit divisor.
|
||||
31 *
|
||||
32 * Note: Calling convention is totally non standard for optimal code.
|
||||
33 * This is meant to be used by do_div() from include/asm/div64.h only.
|
||||
34 *
|
||||
35 * Input parameters:
|
||||
36 * xh-xl = dividend (clobbered)
|
||||
37 * r4 = divisor (preserved)
|
||||
38 *
|
||||
39 * Output values:
|
||||
40 * yh-yl = result
|
||||
41 * xh = remainder
|
||||
42 *
|
||||
43 * Clobbered regs: xl, ip
|
||||
44 */
|
||||
45
|
||||
46 ENTRY(__do_div64)
|
||||
47
|
||||
48 @ Test for easy paths first.
|
||||
49 0000 01C054E2 subs ip, r4, #1
|
||||
50 0004 3F00009A bls 9f @ divisor is 0 or 1
|
||||
51 0008 04001CE1 tst ip, r4
|
||||
52 000c 2800000A beq 8f @ divisor is power of 2
|
||||
53
|
||||
54 @ See if we need to handle upper 32-bit result.
|
||||
55 0010 040051E1 cmp xh, r4
|
||||
56 0014 0030A0E3 mov yh, #0
|
||||
57 0018 0C00003A blo 3f
|
||||
58
|
||||
59 @ Align divisor with upper part of dividend.
|
||||
60 @ The aligned divisor is stored in yl preserving the original.
|
||||
61 @ The bit position is stored in ip.
|
||||
62
|
||||
63 #if __LINUX_ARM_ARCH__ >= 5
|
||||
64
|
||||
65 clz yl, r4
|
||||
66 clz ip, xh
|
||||
67 sub yl, yl, ip
|
||||
68 mov ip, #1
|
||||
69 mov ip, ip, lsl yl
|
||||
70 mov yl, r4, lsl yl
|
||||
71
|
||||
72 #else
|
||||
73
|
||||
74 001c 0420A0E1 mov yl, r4
|
||||
75 0020 01C0A0E3 mov ip, #1
|
||||
76 0024 020152E3 1: cmp yl, #0x80000000
|
||||
77 0028 01005231 cmpcc yl, xh
|
||||
78 002c 8220A031 movcc yl, yl, lsl #1
|
||||
79 0030 8CC0A031 movcc ip, ip, lsl #1
|
||||
80 0034 FAFFFF3A bcc 1b
|
||||
81
|
||||
82 #endif
|
||||
83
|
||||
84 @ The division loop for needed upper bit positions.
|
||||
85 @ Break out early if dividend reaches 0.
|
||||
86 0038 020051E1 2: cmp xh, yl
|
||||
87 003c 0C308321 orrcs yh, yh, ip
|
||||
88 0040 02105120 subcss xh, xh, yl
|
||||
89 0044 ACC0B011 movnes ip, ip, lsr #1
|
||||
90 0048 A220A0E1 mov yl, yl, lsr #1
|
||||
91 004c F9FFFF1A bne 2b
|
||||
92
|
||||
93 @ See if we need to handle lower 32-bit result.
|
||||
94 0050 000051E3 3: cmp xh, #0
|
||||
95 0054 0020A0E3 mov yl, #0
|
||||
96 0058 04005001 cmpeq xl, r4
|
||||
97 005c 0010A031 movlo xh, xl
|
||||
98 0060 0EF0A031 movlo pc, lr
|
||||
99
|
||||
100 @ The division loop for lower bit positions.
|
||||
101 @ Here we shift remainer bits leftwards rather than moving the
|
||||
102 @ divisor for comparisons, considering the carry-out bit as well.
|
||||
103 0064 02C1A0E3 mov ip, #0x80000000
|
||||
104 0068 8000B0E1 4: movs xl, xl, lsl #1
|
||||
105 006c 0110B1E0 adcs xh, xh, xh
|
||||
106 0070 0500000A beq 6f
|
||||
107 0074 04005131 cmpcc xh, r4
|
||||
108 0078 0C208221 5: orrcs yl, yl, ip
|
||||
109 007c 04104120 subcs xh, xh, r4
|
||||
110 0080 ACC0B0E1 movs ip, ip, lsr #1
|
||||
111 0084 F7FFFF1A bne 4b
|
||||
112 0088 0EF0A0E1 mov pc, lr
|
||||
113
|
||||
114 @ The top part of remainder became zero. If carry is set
|
||||
115 @ (the 33th bit) this is a false positive so resume the loop.
|
||||
116 @ Otherwise, if lower part is also null then we are done.
|
||||
117 008c F9FFFF2A 6: bcs 5b
|
||||
118 0090 000050E3 cmp xl, #0
|
||||
119 0094 0EF0A001 moveq pc, lr
|
||||
120
|
||||
121 @ We still have remainer bits in the low part. Bring them up.
|
||||
122
|
||||
123 #if __LINUX_ARM_ARCH__ >= 5
|
||||
124
|
||||
125 clz xh, xl @ we know xh is zero here so...
|
||||
126 add xh, xh, #1
|
||||
127 mov xl, xl, lsl xh
|
||||
128 mov ip, ip, lsr xh
|
||||
129
|
||||
130 #else
|
||||
131
|
||||
132 0098 8000B0E1 7: movs xl, xl, lsl #1
|
||||
133 009c ACC0A0E1 mov ip, ip, lsr #1
|
||||
134 00a0 FCFFFF3A bcc 7b
|
||||
135
|
||||
136 #endif
|
||||
137
|
||||
138 @ Current remainder is now 1. It is worthless to compare with
|
||||
139 @ divisor at this point since divisor can not be smaller than 3 here.
|
||||
140 @ If possible, branch for another shift in the division loop.
|
||||
141 @ If no bit position left then we are done.
|
||||
142 00a4 ACC0B0E1 movs ip, ip, lsr #1
|
||||
143 00a8 0110A0E3 mov xh, #1
|
||||
144 00ac EDFFFF1A bne 4b
|
||||
145 00b0 0EF0A0E1 mov pc, lr
|
||||
146
|
||||
147 8: @ Division by a power of 2: determine what that divisor order is
|
||||
148 @ then simply shift values around
|
||||
149
|
||||
150 #if __LINUX_ARM_ARCH__ >= 5
|
||||
151
|
||||
152 clz ip, r4
|
||||
153 rsb ip, ip, #31
|
||||
154
|
||||
155 #else
|
||||
156
|
||||
157 00b4 0420A0E1 mov yl, r4
|
||||
158 00b8 010854E3 cmp r4, #(1 << 16)
|
||||
159 00bc 00C0A0E3 mov ip, #0
|
||||
160 00c0 2228A021 movhs yl, yl, lsr #16
|
||||
161 00c4 10C0A023 movhs ip, #16
|
||||
162
|
||||
163 00c8 010C52E3 cmp yl, #(1 << 8)
|
||||
164 00cc 2224A021 movhs yl, yl, lsr #8
|
||||
165 00d0 08C08C22 addhs ip, ip, #8
|
||||
166
|
||||
167 00d4 100052E3 cmp yl, #(1 << 4)
|
||||
168 00d8 2222A021 movhs yl, yl, lsr #4
|
||||
169 00dc 04C08C22 addhs ip, ip, #4
|
||||
170
|
||||
171 00e0 040052E3 cmp yl, #(1 << 2)
|
||||
172 00e4 03C08C82 addhi ip, ip, #3
|
||||
173 00e8 A2C08C90 addls ip, ip, yl, lsr #1
|
||||
174
|
||||
175 #endif
|
||||
176
|
||||
177 00ec 313CA0E1 mov yh, xh, lsr ip
|
||||
178 00f0 302CA0E1 mov yl, xl, lsr ip
|
||||
179 00f4 20C06CE2 rsb ip, ip, #32
|
||||
180 00f8 112C82E1 orr yl, yl, xh, lsl ip
|
||||
181 00fc 101CA0E1 mov xh, xl, lsl ip
|
||||
182 0100 311CA0E1 mov xh, xh, lsr ip
|
||||
183 0104 0EF0A0E1 mov pc, lr
|
||||
184
|
||||
185 @ eq -> division by 1: obvious enough...
|
||||
186 0108 0020A001 9: moveq yl, xl
|
||||
187 010c 0130A001 moveq yh, xh
|
||||
188 0110 0010A003 moveq xh, #0
|
||||
189 0114 0EF0A001 moveq pc, lr
|
||||
190
|
||||
191 @ Division by 0:
|
||||
192 0118 08E02DE5 str lr, [sp, #-8]!
|
||||
193 011c FEFFFFEB bl __div0
|
||||
194
|
||||
195 @ as wrong as it could be...
|
||||
196 0120 0020A0E3 mov yl, #0
|
||||
197 0124 0030A0E3 mov yh, #0
|
||||
198 0128 0010A0E3 mov xh, #0
|
||||
199 012c 08F09DE4 ldr pc, [sp], #8
|
||||
DEFINED SYMBOLS
|
||||
lib/div64.S:46 .text:00000000 __do_div64
|
||||
lib/div64.S:46 .text:00000000 $a
|
||||
.debug_aranges:0000000c $d
|
||||
|
||||
UNDEFINED SYMBOLS
|
||||
__div0
|
||||
@@ -0,0 +1,338 @@
|
||||
/*
|
||||
* linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines
|
||||
*
|
||||
* Author: Nicolas Pitre <nico@cam.org>
|
||||
* - contributed to gcc-3.4 on Sep 30, 2003
|
||||
* - adapted for the Linux kernel on Oct 2, 2003
|
||||
*/
|
||||
|
||||
/* Copyright 1995, 1996, 1998, 1999, 2000, 2003 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, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
#include <asm/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
|
||||
|
||||
.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
|
||||
|
||||
|
||||
.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
|
||||
|
||||
|
||||
/*ENTRY(__udivsi3)
|
||||
ENTRY(__aeabi_uidiv)
|
||||
|
||||
subs r2, r1, #1
|
||||
moveq pc, lr
|
||||
bcc Ldiv0
|
||||
cmp r0, r1
|
||||
bls 11f
|
||||
tst r1, r2
|
||||
beq 12f
|
||||
|
||||
ARM_DIV_BODY r0, r1, r2, r3
|
||||
|
||||
mov r0, r2
|
||||
mov pc, lr
|
||||
|
||||
11: moveq r0, #1
|
||||
movne r0, #0
|
||||
mov pc, lr
|
||||
|
||||
12: ARM_DIV2_ORDER r1, r2
|
||||
|
||||
mov r0, r0, lsr r2
|
||||
mov pc, lr
|
||||
*/
|
||||
|
||||
ENTRY(__umodsi3)
|
||||
|
||||
subs r2, r1, #1 @ compare divisor with 1
|
||||
bcc Ldiv0
|
||||
cmpne r0, r1 @ compare dividend with divisor
|
||||
moveq r0, #0
|
||||
tsthi r1, r2 @ see if divisor is power of 2
|
||||
andeq r0, r0, r2
|
||||
movls pc, lr
|
||||
|
||||
ARM_MOD_BODY r0, r1, r2, r3
|
||||
|
||||
mov pc, lr
|
||||
|
||||
|
||||
ENTRY(__divsi3)
|
||||
ENTRY(__aeabi_idiv)
|
||||
|
||||
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
|
||||
|
||||
|
||||
ENTRY(__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
|
||||
|
||||
#ifdef CONFIG_AEABI
|
||||
|
||||
ENTRY(__aeabi_uidivmod)
|
||||
|
||||
stmfd sp!, {r0, r1, ip, lr}
|
||||
bl __aeabi_uidiv
|
||||
ldmfd sp!, {r1, r2, ip, lr}
|
||||
mul r3, r0, r2
|
||||
sub r1, r1, r3
|
||||
mov pc, lr
|
||||
|
||||
ENTRY(__aeabi_idivmod)
|
||||
|
||||
stmfd sp!, {r0, r1, ip, lr}
|
||||
bl __aeabi_idiv
|
||||
ldmfd sp!, {r1, r2, ip, lr}
|
||||
mul r3, r0, r2
|
||||
sub r1, r1, r3
|
||||
mov pc, lr
|
||||
|
||||
#endif
|
||||
|
||||
Ldiv0:
|
||||
|
||||
str lr, [sp, #-8]!
|
||||
bl __div0
|
||||
mov r0, #0 @ About as wrong as it could be.
|
||||
ldr pc, [sp], #8
|
||||
|
||||
ENTRY(__div0)
|
||||
mov pc, lr
|
||||
@@ -0,0 +1,452 @@
|
||||
1 # 1 "lib/lib1funcs.S"
|
||||
1 /*
|
||||
0
|
||||
0
|
||||
2 * linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines
|
||||
3 *
|
||||
4 * Author: Nicolas Pitre <nico@cam.org>
|
||||
5 * - contributed to gcc-3.4 on Sep 30, 2003
|
||||
6 * - adapted for the Linux kernel on Oct 2, 2003
|
||||
7 */
|
||||
8
|
||||
9 /* Copyright 1995, 1996, 1998, 1999, 2000, 2003 Free Software Foundation, Inc.
|
||||
10
|
||||
11 This file is free software; you can redistribute it and/or modify it
|
||||
12 under the terms of the GNU General Public License as published by the
|
||||
13 Free Software Foundation; either version 2, or (at your option) any
|
||||
14 later version.
|
||||
15
|
||||
16 In addition to the permissions in the GNU General Public License, the
|
||||
17 Free Software Foundation gives you unlimited permission to link the
|
||||
18 compiled version of this file into combinations with other programs,
|
||||
19 and to distribute those combinations without any restriction coming
|
||||
20 from the use of this file. (The General Public License restrictions
|
||||
21 do apply in other respects; for example, they cover modification of
|
||||
22 the file, and distribution when not linked into a combine
|
||||
23 executable.)
|
||||
24
|
||||
25 This file is distributed in the hope that it will be useful, but
|
||||
26 WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
28 General Public License for more details.
|
||||
29
|
||||
30 You should have received a copy of the GNU General Public License
|
||||
31 along with this program; see the file COPYING. If not, write to
|
||||
32 the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
33 Boston, MA 02111-1307, USA. */
|
||||
34
|
||||
35
|
||||
36 #include <asm/linkage.h>
|
||||
1 #ifndef __ASM_LINKAGE_H
|
||||
37 #include <asm/assembler.h>
|
||||
1 /*
|
||||
2 * linux/include/asm-arm/assembler.h
|
||||
3 *
|
||||
4 * Copyright (C) 1996-2000 Russell King
|
||||
5 *
|
||||
6 * This program is free software; you can redistribute it and/or modify
|
||||
7 * it under the terms of the GNU General Public License version 2 as
|
||||
8 * published by the Free Software Foundation.
|
||||
9 *
|
||||
10 * This file contains arm architecture specific defines
|
||||
11 * for the different processors.
|
||||
12 *
|
||||
13 * Do not include any C declarations in this file - it is included by
|
||||
14 * assembler source.
|
||||
15 */
|
||||
16 #ifndef __ASSEMBLY__
|
||||
17 #error "Only include this from assembly code"
|
||||
18 #endif
|
||||
19
|
||||
20 #include <asm/ptrace.h>
|
||||
1 /*
|
||||
21
|
||||
22 #define pull lsl
|
||||
23 #define push lsr
|
||||
24 #define get_byte_0 lsr #24
|
||||
25 #define get_byte_1 lsr #16
|
||||
26 #define get_byte_2 lsr #8
|
||||
27 #define get_byte_3 lsl #0
|
||||
28 #define put_byte_0 lsl #24
|
||||
29 #define put_byte_1 lsl #16
|
||||
30 #define put_byte_2 lsl #8
|
||||
31 #define put_byte_3 lsl #0
|
||||
32
|
||||
33 #define PLD(code...)
|
||||
34
|
||||
35 #define MODE_USR USR_MODE
|
||||
36 #define MODE_FIQ FIQ_MODE
|
||||
37 #define MODE_IRQ IRQ_MODE
|
||||
38 #define MODE_SVC SVC_MODE
|
||||
39
|
||||
40 #define DEFAULT_FIQ MODE_FIQ
|
||||
41
|
||||
42 /*
|
||||
43 * LOADREGS - ldm with PC in register list (eg, ldmfd sp!, {pc})
|
||||
44 */
|
||||
45 #ifdef __STDC__
|
||||
46 #define LOADREGS(cond, base, reglist...)\
|
||||
47 ldm##cond base,reglist
|
||||
48 #else
|
||||
49 #define LOADREGS(cond, base, reglist...)\
|
||||
50 ldm/**/cond base,reglist
|
||||
51 #endif
|
||||
52
|
||||
53 /*
|
||||
54 * Build a return instruction for this processor type.
|
||||
55 */
|
||||
56 #define RETINSTR(instr, regs...)\
|
||||
57 instr regs
|
||||
58
|
||||
59 /*
|
||||
60 * Enable and disable interrupts
|
||||
61 */
|
||||
62 .macro disable_irq
|
||||
63 msr cpsr_c, #PSR_I_BIT | SVC_MODE
|
||||
64 .endm
|
||||
65
|
||||
66 .macro enable_irq
|
||||
67 msr cpsr_c, #SVC_MODE
|
||||
68 .endm
|
||||
69
|
||||
70 /*
|
||||
71 * Save the current IRQ state and disable IRQs. Note that this macro
|
||||
72 * assumes FIQs are enabled, and that the processor is in SVC mode.
|
||||
73 */
|
||||
74 .macro save_and_disable_irqs, oldcpsr
|
||||
75 mrs \oldcpsr, cpsr
|
||||
76 disable_irq
|
||||
77 .endm
|
||||
78
|
||||
79 /*
|
||||
80 * Restore interrupt state previously stored in a register. We don't
|
||||
81 * guarantee that this will preserve the flags.
|
||||
82 */
|
||||
83 .macro restore_irqs, oldcpsr
|
||||
84 msr cpsr_c, \oldcpsr
|
||||
85 .endm
|
||||
86
|
||||
87 /*
|
||||
88 * These two are used to save LR/restore PC over a user-based access.
|
||||
89 * The old 26-bit architecture requires that we do. On 32-bit
|
||||
90 * architecture, we can safely ignore this requirement.
|
||||
91 */
|
||||
92 .macro save_lr
|
||||
93 .endm
|
||||
94
|
||||
95 .macro restore_pc
|
||||
96 mov pc, lr
|
||||
97 .endm
|
||||
98 ...
|
||||
38
|
||||
39
|
||||
40 .macro ARM_DIV_BODY dividend, divisor, result, curbit
|
||||
41
|
||||
42 #if __LINUX_ARM_ARCH__ >= 5
|
||||
43
|
||||
44 clz \curbit, \divisor
|
||||
45 clz \result, \dividend
|
||||
46 sub \result, \curbit, \result
|
||||
47 mov \curbit, #1
|
||||
48 mov \divisor, \divisor, lsl \result
|
||||
49 mov \curbit, \curbit, lsl \result
|
||||
50 mov \result, #0
|
||||
51
|
||||
52 #else
|
||||
53
|
||||
54 @ Initially shift the divisor left 3 bits if possible,
|
||||
55 @ set curbit accordingly. This allows for curbit to be located
|
||||
56 @ at the left end of each 4 bit nibbles in the division loop
|
||||
57 @ to save one loop in most cases.
|
||||
58 tst \divisor, #0xe0000000
|
||||
59 moveq \divisor, \divisor, lsl #3
|
||||
60 moveq \curbit, #8
|
||||
61 movne \curbit, #1
|
||||
62
|
||||
63 @ Unless the divisor is very big, shift it up in multiples of
|
||||
64 @ four bits, since this is the amount of unwinding in the main
|
||||
65 @ division loop. Continue shifting until the divisor is
|
||||
66 @ larger than the dividend.
|
||||
67 1: cmp \divisor, #0x10000000
|
||||
68 cmplo \divisor, \dividend
|
||||
69 movlo \divisor, \divisor, lsl #4
|
||||
70 movlo \curbit, \curbit, lsl #4
|
||||
71 blo 1b
|
||||
72
|
||||
73 @ For very big divisors, we must shift it a bit at a time, or
|
||||
74 @ we will be in danger of overflowing.
|
||||
75 1: cmp \divisor, #0x80000000
|
||||
76 cmplo \divisor, \dividend
|
||||
77 movlo \divisor, \divisor, lsl #1
|
||||
78 movlo \curbit, \curbit, lsl #1
|
||||
79 blo 1b
|
||||
80
|
||||
81 mov \result, #0
|
||||
82
|
||||
83 #endif
|
||||
84
|
||||
85 @ Division loop
|
||||
86 1: cmp \dividend, \divisor
|
||||
87 subhs \dividend, \dividend, \divisor
|
||||
88 orrhs \result, \result, \curbit
|
||||
89 cmp \dividend, \divisor, lsr #1
|
||||
90 subhs \dividend, \dividend, \divisor, lsr #1
|
||||
91 orrhs \result, \result, \curbit, lsr #1
|
||||
92 cmp \dividend, \divisor, lsr #2
|
||||
93 subhs \dividend, \dividend, \divisor, lsr #2
|
||||
94 orrhs \result, \result, \curbit, lsr #2
|
||||
95 cmp \dividend, \divisor, lsr #3
|
||||
96 subhs \dividend, \dividend, \divisor, lsr #3
|
||||
97 orrhs \result, \result, \curbit, lsr #3
|
||||
98 cmp \dividend, #0 @ Early termination?
|
||||
99 movnes \curbit, \curbit, lsr #4 @ No, any more bits to do?
|
||||
100 movne \divisor, \divisor, lsr #4
|
||||
101 bne 1b
|
||||
102
|
||||
103 .endm
|
||||
104
|
||||
105
|
||||
106 .macro ARM_DIV2_ORDER divisor, order
|
||||
107
|
||||
108 #if __LINUX_ARM_ARCH__ >= 5
|
||||
109
|
||||
110 clz \order, \divisor
|
||||
111 rsb \order, \order, #31
|
||||
112
|
||||
113 #else
|
||||
114
|
||||
115 cmp \divisor, #(1 << 16)
|
||||
116 movhs \divisor, \divisor, lsr #16
|
||||
117 movhs \order, #16
|
||||
118 movlo \order, #0
|
||||
119
|
||||
120 cmp \divisor, #(1 << 8)
|
||||
121 movhs \divisor, \divisor, lsr #8
|
||||
122 addhs \order, \order, #8
|
||||
123
|
||||
124 cmp \divisor, #(1 << 4)
|
||||
125 movhs \divisor, \divisor, lsr #4
|
||||
126 addhs \order, \order, #4
|
||||
127
|
||||
128 cmp \divisor, #(1 << 2)
|
||||
129 addhi \order, \order, #3
|
||||
130 addls \order, \order, \divisor, lsr #1
|
||||
131
|
||||
132 #endif
|
||||
133
|
||||
134 .endm
|
||||
135
|
||||
136
|
||||
137 .macro ARM_MOD_BODY dividend, divisor, order, spare
|
||||
138
|
||||
139 #if __LINUX_ARM_ARCH__ >= 5
|
||||
140
|
||||
141 clz \order, \divisor
|
||||
142 clz \spare, \dividend
|
||||
143 sub \order, \order, \spare
|
||||
144 mov \divisor, \divisor, lsl \order
|
||||
145
|
||||
146 #else
|
||||
147
|
||||
148 mov \order, #0
|
||||
149
|
||||
150 @ Unless the divisor is very big, shift it up in multiples of
|
||||
151 @ four bits, since this is the amount of unwinding in the main
|
||||
152 @ division loop. Continue shifting until the divisor is
|
||||
153 @ larger than the dividend.
|
||||
154 1: cmp \divisor, #0x10000000
|
||||
155 cmplo \divisor, \dividend
|
||||
156 movlo \divisor, \divisor, lsl #4
|
||||
157 addlo \order, \order, #4
|
||||
158 blo 1b
|
||||
159
|
||||
160 @ For very big divisors, we must shift it a bit at a time, or
|
||||
161 @ we will be in danger of overflowing.
|
||||
162 1: cmp \divisor, #0x80000000
|
||||
163 cmplo \divisor, \dividend
|
||||
164 movlo \divisor, \divisor, lsl #1
|
||||
165 addlo \order, \order, #1
|
||||
166 blo 1b
|
||||
167
|
||||
168 #endif
|
||||
169
|
||||
170 @ Perform all needed substractions to keep only the reminder.
|
||||
171 @ Do comparisons in batch of 4 first.
|
||||
172 subs \order, \order, #3 @ yes, 3 is intended here
|
||||
173 blt 2f
|
||||
174
|
||||
175 1: cmp \dividend, \divisor
|
||||
176 subhs \dividend, \dividend, \divisor
|
||||
177 cmp \dividend, \divisor, lsr #1
|
||||
178 subhs \dividend, \dividend, \divisor, lsr #1
|
||||
179 cmp \dividend, \divisor, lsr #2
|
||||
180 subhs \dividend, \dividend, \divisor, lsr #2
|
||||
181 cmp \dividend, \divisor, lsr #3
|
||||
182 subhs \dividend, \dividend, \divisor, lsr #3
|
||||
183 cmp \dividend, #1
|
||||
184 mov \divisor, \divisor, lsr #4
|
||||
185 subges \order, \order, #4
|
||||
186 bge 1b
|
||||
187
|
||||
188 tst \order, #3
|
||||
189 teqne \dividend, #0
|
||||
190 beq 5f
|
||||
191
|
||||
192 @ Either 1, 2 or 3 comparison/substractions are left.
|
||||
193 2: cmn \order, #2
|
||||
194 blt 4f
|
||||
195 beq 3f
|
||||
196 cmp \dividend, \divisor
|
||||
197 subhs \dividend, \dividend, \divisor
|
||||
198 mov \divisor, \divisor, lsr #1
|
||||
199 3: cmp \dividend, \divisor
|
||||
200 subhs \dividend, \dividend, \divisor
|
||||
201 mov \divisor, \divisor, lsr #1
|
||||
202 4: cmp \dividend, \divisor
|
||||
203 subhs \dividend, \dividend, \divisor
|
||||
204 5:
|
||||
205 .endm
|
||||
206
|
||||
207
|
||||
208 /*ENTRY(__udivsi3)
|
||||
209 ENTRY(__aeabi_uidiv)
|
||||
210
|
||||
211 subs r2, r1, #1
|
||||
212 moveq pc, lr
|
||||
213 bcc Ldiv0
|
||||
214 cmp r0, r1
|
||||
215 bls 11f
|
||||
216 tst r1, r2
|
||||
217 beq 12f
|
||||
218
|
||||
219 ARM_DIV_BODY r0, r1, r2, r3
|
||||
220
|
||||
221 mov r0, r2
|
||||
222 mov pc, lr
|
||||
223
|
||||
224 11: moveq r0, #1
|
||||
225 movne r0, #0
|
||||
226 mov pc, lr
|
||||
227
|
||||
228 12: ARM_DIV2_ORDER r1, r2
|
||||
229
|
||||
230 mov r0, r0, lsr r2
|
||||
231 mov pc, lr
|
||||
232 */
|
||||
233
|
||||
234 ENTRY(__umodsi3)
|
||||
235
|
||||
236 0000 012051E2 subs r2, r1, #1 @ compare divisor with 1
|
||||
237 0004 A700003A bcc Ldiv0
|
||||
238 0008 01005011 cmpne r0, r1 @ compare dividend with divisor
|
||||
239 000c 0000A003 moveq r0, #0
|
||||
240 0010 02001181 tsthi r1, r2 @ see if divisor is power of 2
|
||||
241 0014 02000000 andeq r0, r0, r2
|
||||
242 0018 0EF0A091 movls pc, lr
|
||||
243
|
||||
244 ARM_MOD_BODY r0, r1, r2, r3
|
||||
245
|
||||
246 00b8 0EF0A0E1 mov pc, lr
|
||||
247
|
||||
248
|
||||
249 ENTRY(__divsi3)
|
||||
250 ENTRY(__aeabi_idiv)
|
||||
251
|
||||
252 00bc 000051E3 cmp r1, #0
|
||||
253 00c0 01C020E0 eor ip, r0, r1 @ save the sign of the result.
|
||||
254 00c4 7700000A beq Ldiv0
|
||||
255 00c8 00106142 rsbmi r1, r1, #0 @ loops below use unsigned.
|
||||
256 00cc 012051E2 subs r2, r1, #1 @ division by 1 or -1 ?
|
||||
257 00d0 2700000A beq 10f
|
||||
258 00d4 0030B0E1 movs r3, r0
|
||||
259 00d8 00306042 rsbmi r3, r0, #0 @ positive dividend value
|
||||
260 00dc 010053E1 cmp r3, r1
|
||||
261 00e0 2600009A bls 11f
|
||||
262 00e4 020011E1 tst r1, r2 @ divisor is power of 2 ?
|
||||
263 00e8 2800000A beq 12f
|
||||
264
|
||||
265 ARM_DIV_BODY r3, r1, r0, r2
|
||||
266
|
||||
267 0168 00005CE3 cmp ip, #0
|
||||
268 016c 00006042 rsbmi r0, r0, #0
|
||||
269 0170 0EF0A0E1 mov pc, lr
|
||||
270
|
||||
271 0174 00003CE1 10: teq ip, r0 @ same sign ?
|
||||
272 0178 00006042 rsbmi r0, r0, #0
|
||||
273 017c 0EF0A0E1 mov pc, lr
|
||||
274
|
||||
275 0180 0000A033 11: movlo r0, #0
|
||||
276 0184 CC0FA001 moveq r0, ip, asr #31
|
||||
277 0188 01008003 orreq r0, r0, #1
|
||||
278 018c 0EF0A0E1 mov pc, lr
|
||||
279
|
||||
280 12: ARM_DIV2_ORDER r1, r2
|
||||
281
|
||||
282 01c4 00005CE3 cmp ip, #0
|
||||
283 01c8 3302A0E1 mov r0, r3, lsr r2
|
||||
284 01cc 00006042 rsbmi r0, r0, #0
|
||||
285 01d0 0EF0A0E1 mov pc, lr
|
||||
286
|
||||
287
|
||||
288 ENTRY(__modsi3)
|
||||
289
|
||||
290 01d4 000051E3 cmp r1, #0
|
||||
291 01d8 3200000A beq Ldiv0
|
||||
292 01dc 00106142 rsbmi r1, r1, #0 @ loops below use unsigned.
|
||||
293 01e0 00C0B0E1 movs ip, r0 @ preserve sign of dividend
|
||||
294 01e4 00006042 rsbmi r0, r0, #0 @ if negative make positive
|
||||
295 01e8 012051E2 subs r2, r1, #1 @ compare divisor with 1
|
||||
296 01ec 01005011 cmpne r0, r1 @ compare dividend with divisor
|
||||
297 01f0 0000A003 moveq r0, #0
|
||||
298 01f4 02001181 tsthi r1, r2 @ see if divisor is power of 2
|
||||
299 01f8 02000000 andeq r0, r0, r2
|
||||
300 01fc 2600009A bls 10f
|
||||
301
|
||||
302 ARM_MOD_BODY r0, r1, r2, r3
|
||||
303
|
||||
304 029c 00005CE3 10: cmp ip, #0
|
||||
305 02a0 00006042 rsbmi r0, r0, #0
|
||||
306 02a4 0EF0A0E1 mov pc, lr
|
||||
307
|
||||
308 #ifdef CONFIG_AEABI
|
||||
309
|
||||
310 ENTRY(__aeabi_uidivmod)
|
||||
311
|
||||
312 stmfd sp!, {r0, r1, ip, lr}
|
||||
313 bl __aeabi_uidiv
|
||||
314 ldmfd sp!, {r1, r2, ip, lr}
|
||||
315 mul r3, r0, r2
|
||||
316 sub r1, r1, r3
|
||||
317 mov pc, lr
|
||||
318
|
||||
319 ENTRY(__aeabi_idivmod)
|
||||
320
|
||||
321 stmfd sp!, {r0, r1, ip, lr}
|
||||
322 bl __aeabi_idiv
|
||||
323 ldmfd sp!, {r1, r2, ip, lr}
|
||||
324 mul r3, r0, r2
|
||||
325 sub r1, r1, r3
|
||||
326 mov pc, lr
|
||||
327
|
||||
328 #endif
|
||||
329
|
||||
330 Ldiv0:
|
||||
331
|
||||
332 02a8 08E02DE5 str lr, [sp, #-8]!
|
||||
333 02ac FEFFFFEB bl __div0
|
||||
334 02b0 0000A0E3 mov r0, #0 @ About as wrong as it could be.
|
||||
335 02b4 08F09DE4 ldr pc, [sp], #8
|
||||
336
|
||||
337 ENTRY(__div0)
|
||||
338 02b8 0EF0A0E1 mov pc, lr
|
||||
DEFINED SYMBOLS
|
||||
lib/lib1funcs.S:234 .text:00000000 __umodsi3
|
||||
lib/lib1funcs.S:234 .text:00000000 $a
|
||||
lib/lib1funcs.S:330 .text:000002a8 Ldiv0
|
||||
lib/lib1funcs.S:249 .text:000000bc __divsi3
|
||||
lib/lib1funcs.S:250 .text:000000bc __aeabi_idiv
|
||||
lib/lib1funcs.S:288 .text:000001d4 __modsi3
|
||||
lib/lib1funcs.S:337 .text:000002b8 __div0
|
||||
.debug_aranges:0000000c $d
|
||||
|
||||
NO UNDEFINED SYMBOLS
|
||||
@@ -0,0 +1,405 @@
|
||||
//* ----------------------------------------------------------------------------
|
||||
//* ATMEL Microcontroller Software Support - ROUSSET -
|
||||
//* ----------------------------------------------------------------------------
|
||||
//* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
//* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
//* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
//* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
//* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
//* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
//* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
//* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//* ----------------------------------------------------------------------------
|
||||
//* File Name : lib_AT91SAM7S64.h
|
||||
//* Object : AT91SAM7S64 inlined functions
|
||||
//* Generated : AT91 SW Application Group 08/30/2005 (15:52:59)
|
||||
//*
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <include/AT91SAM7.h>
|
||||
#include <include/lib_AT91SAM7.h>
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_AIC_ConfigureIt
|
||||
//* \brief Interrupt Handler Initialization
|
||||
//*----------------------------------------------------------------------------
|
||||
unsigned int AT91F_AIC_ConfigureIt (
|
||||
AT91PS_AIC pAic, // \arg pointer to the AIC registers
|
||||
unsigned int irq_id, // \arg interrupt number to initialize
|
||||
unsigned int priority, // \arg priority to give to the interrupt
|
||||
unsigned int src_type, // \arg activation and sense of activation
|
||||
void (*newHandler) () ) // \arg address of the interrupt handler
|
||||
{
|
||||
unsigned int oldHandler;
|
||||
unsigned int mask ;
|
||||
|
||||
oldHandler = pAic->AIC_SVR[irq_id];
|
||||
|
||||
mask = 0x1 << irq_id ;
|
||||
//* Disable the interrupt on the interrupt controller
|
||||
pAic->AIC_IDCR = mask ;
|
||||
//* Save the interrupt handler routine pointer and the interrupt priority
|
||||
pAic->AIC_SVR[irq_id] = (unsigned int) newHandler ;
|
||||
//* Store the Source Mode Register
|
||||
pAic->AIC_SMR[irq_id] = src_type | priority ;
|
||||
//* Clear the interrupt on the interrupt controller
|
||||
pAic->AIC_ICCR = mask ;
|
||||
|
||||
return oldHandler;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_AIC_SetExceptionVector
|
||||
//* \brief Configure vector handler
|
||||
//*----------------------------------------------------------------------------
|
||||
unsigned int AT91F_AIC_SetExceptionVector (
|
||||
unsigned int *pVector, // \arg pointer to the AIC registers
|
||||
void (*Handler) () ) // \arg Interrupt Handler
|
||||
{
|
||||
unsigned int oldVector = *pVector;
|
||||
|
||||
if ((unsigned int) Handler == (unsigned int) AT91C_AIC_BRANCH_OPCODE)
|
||||
*pVector = (unsigned int) AT91C_AIC_BRANCH_OPCODE;
|
||||
else
|
||||
*pVector = (((((unsigned int) Handler) - ((unsigned int) pVector) - 0x8) >> 2) & 0x00FFFFFF) | 0xEA000000;
|
||||
|
||||
return oldVector;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_AIC_Open
|
||||
//* \brief Set exception vectors and AIC registers to default values
|
||||
//*----------------------------------------------------------------------------
|
||||
void AT91F_AIC_Open(
|
||||
AT91PS_AIC pAic, // \arg pointer to the AIC registers
|
||||
void (*IrqHandler) (), // \arg Default IRQ vector exception
|
||||
void (*FiqHandler) (), // \arg Default FIQ vector exception
|
||||
void (*DefaultHandler) (), // \arg Default Handler set in ISR
|
||||
void (*SpuriousHandler) (), // \arg Default Spurious Handler
|
||||
unsigned int protectMode) // \arg Debug Control Register
|
||||
{
|
||||
int i;
|
||||
|
||||
// Disable all interrupts and set IVR to the default handler
|
||||
for (i = 0; i < 32; ++i) {
|
||||
AT91F_AIC_DisableIt(pAic, i);
|
||||
AT91F_AIC_ConfigureIt(pAic, i, AT91C_AIC_PRIOR_LOWEST, AT91C_AIC_SRCTYPE_HIGH_LEVEL, DefaultHandler);
|
||||
}
|
||||
|
||||
// Set the IRQ exception vector
|
||||
AT91F_AIC_SetExceptionVector((unsigned int *) 0x18, IrqHandler);
|
||||
// Set the Fast Interrupt exception vector
|
||||
AT91F_AIC_SetExceptionVector((unsigned int *) 0x1C, FiqHandler);
|
||||
|
||||
pAic->AIC_SPU = (unsigned int) SpuriousHandler;
|
||||
pAic->AIC_DCR = protectMode;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_PDC_Open
|
||||
//* \brief Open PDC: disable TX and RX reset transfer descriptors, re-enable RX and TX
|
||||
//*----------------------------------------------------------------------------
|
||||
void AT91F_PDC_Open(AT91PS_PDC pPDC) // \arg pointer to a PDC controller
|
||||
{
|
||||
//* Disable the RX and TX PDC transfer requests
|
||||
AT91F_PDC_DisableRx(pPDC);
|
||||
AT91F_PDC_DisableTx(pPDC);
|
||||
|
||||
//* Reset all Counter register Next buffer first
|
||||
AT91F_PDC_SetNextTx(pPDC, NULL, 0);
|
||||
AT91F_PDC_SetNextRx(pPDC, NULL, 0);
|
||||
AT91F_PDC_SetTx(pPDC, NULL, 0);
|
||||
AT91F_PDC_SetRx(pPDC, NULL, 0);
|
||||
|
||||
//* Enable the RX and TX PDC transfer requests
|
||||
AT91F_PDC_EnableRx(pPDC);
|
||||
AT91F_PDC_EnableTx(pPDC);
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_PDC_Close
|
||||
//* \brief Close PDC: disable TX and RX reset transfer descriptors
|
||||
//*----------------------------------------------------------------------------
|
||||
void AT91F_PDC_Close(AT91PS_PDC pPDC) // \arg pointer to a PDC controller
|
||||
{
|
||||
//* Disable the RX and TX PDC transfer requests
|
||||
AT91F_PDC_DisableRx(pPDC);
|
||||
AT91F_PDC_DisableTx(pPDC);
|
||||
|
||||
//* Reset all Counter register Next buffer first
|
||||
AT91F_PDC_SetNextTx(pPDC, NULL, 0);
|
||||
AT91F_PDC_SetNextRx(pPDC, NULL, 0);
|
||||
AT91F_PDC_SetTx(pPDC, NULL, 0);
|
||||
AT91F_PDC_SetRx(pPDC, NULL, 0);
|
||||
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_PDC_SendFrame
|
||||
//* \brief Close PDC: disable TX and RX reset transfer descriptors
|
||||
//*----------------------------------------------------------------------------
|
||||
unsigned int AT91F_PDC_SendFrame(
|
||||
AT91PS_PDC pPDC,
|
||||
const unsigned char *pBuffer,
|
||||
unsigned int szBuffer,
|
||||
const unsigned char *pNextBuffer,
|
||||
unsigned int szNextBuffer )
|
||||
{
|
||||
if (AT91F_PDC_IsTxEmpty(pPDC)) {
|
||||
//* Buffer and next buffer can be initialized
|
||||
AT91F_PDC_SetTx(pPDC, pBuffer, szBuffer);
|
||||
AT91F_PDC_SetNextTx(pPDC, pNextBuffer, szNextBuffer);
|
||||
return 2;
|
||||
}
|
||||
else if (AT91F_PDC_IsNextTxEmpty(pPDC)) {
|
||||
//* Only one buffer can be initialized
|
||||
AT91F_PDC_SetNextTx(pPDC, pBuffer, szBuffer);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
//* All buffer are in use...
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_PDC_ReceiveFrame
|
||||
//* \brief Close PDC: disable TX and RX reset transfer descriptors
|
||||
//*----------------------------------------------------------------------------
|
||||
unsigned int AT91F_PDC_ReceiveFrame (
|
||||
AT91PS_PDC pPDC,
|
||||
unsigned char *pBuffer,
|
||||
unsigned int szBuffer,
|
||||
unsigned char *pNextBuffer,
|
||||
unsigned int szNextBuffer )
|
||||
{
|
||||
if (AT91F_PDC_IsRxEmpty(pPDC)) {
|
||||
//* Buffer and next buffer can be initialized
|
||||
AT91F_PDC_SetRx(pPDC, pBuffer, szBuffer);
|
||||
AT91F_PDC_SetNextRx(pPDC, pNextBuffer, szNextBuffer);
|
||||
return 2;
|
||||
}
|
||||
else if (AT91F_PDC_IsNextRxEmpty(pPDC)) {
|
||||
//* Only one buffer can be initialized
|
||||
AT91F_PDC_SetNextRx(pPDC, pBuffer, szBuffer);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
//* All buffer are in use...
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//*------------------------------------------------------------------------------
|
||||
//* \fn AT91F_PMC_GetMasterClock
|
||||
//* \brief Return master clock in Hz which correponds to processor clock for ARM7
|
||||
//*------------------------------------------------------------------------------
|
||||
unsigned int AT91F_PMC_GetMasterClock (
|
||||
AT91PS_PMC pPMC, // \arg pointer to PMC controller
|
||||
AT91PS_CKGR pCKGR, // \arg pointer to CKGR controller
|
||||
unsigned int slowClock) // \arg slowClock in Hz
|
||||
{
|
||||
unsigned int reg = pPMC->PMC_MCKR;
|
||||
unsigned int prescaler = (1 << ((reg & AT91C_PMC_PRES) >> 2));
|
||||
unsigned int pllDivider, pllMultiplier;
|
||||
|
||||
switch (reg & AT91C_PMC_CSS) {
|
||||
case AT91C_PMC_CSS_SLOW_CLK: // Slow clock selected
|
||||
return slowClock / prescaler;
|
||||
case AT91C_PMC_CSS_MAIN_CLK: // Main clock is selected
|
||||
return AT91F_CKGR_GetMainClock(pCKGR, slowClock) / prescaler;
|
||||
case AT91C_PMC_CSS_PLL_CLK: // PLLB clock is selected
|
||||
reg = pCKGR->CKGR_PLLR;
|
||||
pllDivider = (reg & AT91C_CKGR_DIV);
|
||||
pllMultiplier = ((reg & AT91C_CKGR_MUL) >> 16) + 1;
|
||||
return AT91F_CKGR_GetMainClock(pCKGR, slowClock) / pllDivider * pllMultiplier / prescaler;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//*--------------------------------------------------------------------------------------
|
||||
//* \fn AT91F_RTT_ReadValue()
|
||||
//* \brief Read the RTT value
|
||||
//*--------------------------------------------------------------------------------------
|
||||
unsigned int AT91F_RTTReadValue(AT91PS_RTTC pRTTC)
|
||||
{
|
||||
register volatile unsigned int val1,val2;
|
||||
do
|
||||
{
|
||||
val1 = pRTTC->RTTC_RTVR;
|
||||
val2 = pRTTC->RTTC_RTVR;
|
||||
}
|
||||
while(val1 != val2);
|
||||
return(val1);
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_SPI_Close
|
||||
//* \brief Close SPI: disable IT disable transfert, close PDC
|
||||
//*----------------------------------------------------------------------------
|
||||
void AT91F_SPI_Close(AT91PS_SPI pSPI) // \arg pointer to a SPI controller
|
||||
{
|
||||
//* Reset all the Chip Select register
|
||||
pSPI->SPI_CSR[0] = 0 ;
|
||||
pSPI->SPI_CSR[1] = 0 ;
|
||||
pSPI->SPI_CSR[2] = 0 ;
|
||||
pSPI->SPI_CSR[3] = 0 ;
|
||||
|
||||
//* Reset the SPI mode
|
||||
pSPI->SPI_MR = 0 ;
|
||||
|
||||
//* Disable all interrupts
|
||||
pSPI->SPI_IDR = 0xFFFFFFFF ;
|
||||
|
||||
//* Abort the Peripheral Data Transfers
|
||||
AT91F_PDC_Close((AT91PS_PDC) &(pSPI->SPI_RPR));
|
||||
|
||||
//* Disable receiver and transmitter and stop any activity immediately
|
||||
pSPI->SPI_CR = AT91C_SPI_SPIDIS;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_ADC_CfgTimings
|
||||
//* \brief Configure the different necessary timings of the ADC controller
|
||||
//*----------------------------------------------------------------------------
|
||||
void AT91F_ADC_CfgTimings (
|
||||
AT91PS_ADC pADC, // pointer to a ADC controller
|
||||
unsigned int mck_clock, // in MHz
|
||||
unsigned int adc_clock, // in MHz
|
||||
unsigned int startup_time, // in us
|
||||
unsigned int sample_and_hold_time) // in ns
|
||||
{
|
||||
unsigned int prescal,startup,shtim;
|
||||
|
||||
prescal = mck_clock/(2*adc_clock) - 1;
|
||||
startup = adc_clock*startup_time/8 - 1;
|
||||
shtim = adc_clock*sample_and_hold_time/1000 - 1;
|
||||
|
||||
//* Write to the MR register
|
||||
pADC->ADC_MR = ( (prescal<<8) & AT91C_ADC_PRESCAL) | ( (startup<<16) & AT91C_ADC_STARTUP) | ( (shtim<<24) & AT91C_ADC_SHTIM);
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_SSC_SetBaudrate
|
||||
//* \brief Set the baudrate according to the CPU clock
|
||||
//*----------------------------------------------------------------------------
|
||||
void AT91F_SSC_SetBaudrate (
|
||||
AT91PS_SSC pSSC, // \arg pointer to a SSC controller
|
||||
unsigned int mainClock, // \arg peripheral clock
|
||||
unsigned int speed) // \arg SSC baudrate
|
||||
{
|
||||
unsigned int baud_value;
|
||||
//* Define the baud rate divisor register
|
||||
if (speed == 0)
|
||||
baud_value = 0;
|
||||
else
|
||||
{
|
||||
baud_value = (unsigned int) (mainClock * 10)/(2*speed);
|
||||
if ((baud_value % 10) >= 5)
|
||||
baud_value = (baud_value / 10) + 1;
|
||||
else
|
||||
baud_value /= 10;
|
||||
}
|
||||
|
||||
pSSC->SSC_CMR = baud_value;
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_SSC_Configure
|
||||
//* \brief Configure SSC
|
||||
//*----------------------------------------------------------------------------
|
||||
void AT91F_SSC_Configure (
|
||||
AT91PS_SSC pSSC, // \arg pointer to a SSC controller
|
||||
unsigned int syst_clock, // \arg System Clock Frequency
|
||||
unsigned int baud_rate, // \arg Expected Baud Rate Frequency
|
||||
unsigned int clock_rx, // \arg Receiver Clock Parameters
|
||||
unsigned int mode_rx, // \arg mode Register to be programmed
|
||||
unsigned int clock_tx, // \arg Transmitter Clock Parameters
|
||||
unsigned int mode_tx) // \arg mode Register to be programmed
|
||||
{
|
||||
//* Disable interrupts
|
||||
pSSC->SSC_IDR = (unsigned int) -1;
|
||||
|
||||
//* Reset receiver and transmitter
|
||||
pSSC->SSC_CR = AT91C_SSC_SWRST | AT91C_SSC_RXDIS | AT91C_SSC_TXDIS ;
|
||||
|
||||
//* Define the Clock Mode Register
|
||||
AT91F_SSC_SetBaudrate(pSSC, syst_clock, baud_rate);
|
||||
|
||||
//* Write the Receive Clock Mode Register
|
||||
pSSC->SSC_RCMR = clock_rx;
|
||||
|
||||
//* Write the Transmit Clock Mode Register
|
||||
pSSC->SSC_TCMR = clock_tx;
|
||||
|
||||
//* Write the Receive Frame Mode Register
|
||||
pSSC->SSC_RFMR = mode_rx;
|
||||
|
||||
//* Write the Transmit Frame Mode Register
|
||||
pSSC->SSC_TFMR = mode_tx;
|
||||
|
||||
//* Clear Transmit and Receive Counters
|
||||
AT91F_PDC_Open((AT91PS_PDC) &(pSSC->SSC_RPR));
|
||||
|
||||
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_US_Configure
|
||||
//* \brief Configure USART
|
||||
//*----------------------------------------------------------------------------
|
||||
void AT91F_US_Configure (
|
||||
AT91PS_USART pUSART, // \arg pointer to a USART controller
|
||||
unsigned int mainClock, // \arg peripheral clock
|
||||
unsigned int mode , // \arg mode Register to be programmed
|
||||
unsigned int baudRate , // \arg baudrate to be programmed
|
||||
unsigned int timeguard ) // \arg timeguard to be programmed
|
||||
{
|
||||
//* Disable interrupts
|
||||
pUSART->US_IDR = (unsigned int) -1;
|
||||
|
||||
//* Reset receiver and transmitter
|
||||
pUSART->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS ;
|
||||
|
||||
//* Define the baud rate divisor register
|
||||
AT91F_US_SetBaudrate(pUSART, mainClock, baudRate);
|
||||
|
||||
//* Write the Timeguard Register
|
||||
AT91F_US_SetTimeguard(pUSART, timeguard);
|
||||
|
||||
//* Clear Transmit and Receive Counters
|
||||
AT91F_PDC_Open((AT91PS_PDC) &(pUSART->US_RPR));
|
||||
|
||||
//* Define the USART mode
|
||||
pUSART->US_MR = mode ;
|
||||
|
||||
}
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_US_Close
|
||||
//* \brief Close USART: disable IT disable receiver and transmitter, close PDC
|
||||
//*----------------------------------------------------------------------------
|
||||
void AT91F_US_Close(AT91PS_USART pUSART) // \arg pointer to a USART controller
|
||||
{
|
||||
//* Reset the baud rate divisor register
|
||||
pUSART->US_BRGR = 0 ;
|
||||
|
||||
//* Reset the USART mode
|
||||
pUSART->US_MR = 0 ;
|
||||
|
||||
//* Reset the Timeguard Register
|
||||
pUSART->US_TTGR = 0;
|
||||
|
||||
//* Disable all interrupts
|
||||
pUSART->US_IDR = 0xFFFFFFFF ;
|
||||
|
||||
//* Abort the Peripheral Data Transfers
|
||||
AT91F_PDC_Close((AT91PS_PDC) &(pUSART->US_RPR));
|
||||
|
||||
//* Disable receiver and transmitter and stop any activity immediately
|
||||
pUSART->US_CR = AT91C_US_TXDIS | AT91C_US_RXDIS | AT91C_US_RSTTX | AT91C_US_RSTRX ;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* linux/arch/arm/lib/memcpy.S
|
||||
*
|
||||
* Author: Nicolas Pitre
|
||||
* Created: Sep 28, 2005
|
||||
* Copyright: MontaVista Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <asm/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
|
||||
.macro ldr1w ptr reg abort
|
||||
ldr \reg, [\ptr], #4
|
||||
.endm
|
||||
|
||||
.macro ldr4w ptr reg1 reg2 reg3 reg4 abort
|
||||
ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4}
|
||||
.endm
|
||||
|
||||
.macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
|
||||
ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
|
||||
.endm
|
||||
|
||||
.macro ldr1b ptr reg cond=al abort
|
||||
ldr\cond\()b \reg, [\ptr], #1
|
||||
.endm
|
||||
|
||||
.macro str1w ptr reg abort
|
||||
str \reg, [\ptr], #4
|
||||
.endm
|
||||
|
||||
.macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
|
||||
stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
|
||||
.endm
|
||||
|
||||
.macro str1b ptr reg cond=al abort
|
||||
str\cond\()b \reg, [\ptr], #1
|
||||
.endm
|
||||
|
||||
.macro enter reg1 reg2
|
||||
stmdb sp!, {r0, \reg1, \reg2}
|
||||
.endm
|
||||
|
||||
.macro exit reg1 reg2
|
||||
ldmfd sp!, {r0, \reg1, \reg2}
|
||||
.endm
|
||||
|
||||
.text
|
||||
|
||||
/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
|
||||
|
||||
ENTRY(memcpy)
|
||||
|
||||
#include "copy_template.S"
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* linux/arch/arm/lib/memset.S
|
||||
*
|
||||
* Copyright (C) 1995-2000 Russell King
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* ASM optimised string functions
|
||||
*/
|
||||
#include <asm/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
|
||||
.text
|
||||
.align 5
|
||||
.word 0
|
||||
|
||||
1: subs r2, r2, #4 @ 1 do we have enough
|
||||
blt 5f @ 1 bytes to align with?
|
||||
cmp r3, #2 @ 1
|
||||
strltb r1, [r0], #1 @ 1
|
||||
strleb r1, [r0], #1 @ 1
|
||||
strb r1, [r0], #1 @ 1
|
||||
add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3))
|
||||
/*
|
||||
* The pointer is now aligned and the length is adjusted. Try doing the
|
||||
* memzero again.
|
||||
*/
|
||||
|
||||
ENTRY(memset)
|
||||
ands r3, r0, #3 @ 1 unaligned?
|
||||
bne 1b @ 1
|
||||
/*
|
||||
* we know that the pointer in r0 is aligned to a word boundary.
|
||||
*/
|
||||
orr r1, r1, r1, lsl #8
|
||||
orr r1, r1, r1, lsl #16
|
||||
mov r3, r1
|
||||
cmp r2, #16
|
||||
blt 4f
|
||||
/*
|
||||
* We need an extra register for this loop - save the return address and
|
||||
* use the LR
|
||||
*/
|
||||
str lr, [sp, #-4]!
|
||||
mov ip, r1
|
||||
mov lr, r1
|
||||
|
||||
2: subs r2, r2, #64
|
||||
stmgeia r0!, {r1, r3, ip, lr} @ 64 bytes at a time.
|
||||
stmgeia r0!, {r1, r3, ip, lr}
|
||||
stmgeia r0!, {r1, r3, ip, lr}
|
||||
stmgeia r0!, {r1, r3, ip, lr}
|
||||
bgt 2b
|
||||
LOADREGS(eqfd, sp!, {pc}) @ Now <64 bytes to go.
|
||||
/*
|
||||
* No need to correct the count; we're only testing bits from now on
|
||||
*/
|
||||
tst r2, #32
|
||||
stmneia r0!, {r1, r3, ip, lr}
|
||||
stmneia r0!, {r1, r3, ip, lr}
|
||||
tst r2, #16
|
||||
stmneia r0!, {r1, r3, ip, lr}
|
||||
ldr lr, [sp], #4
|
||||
|
||||
4: tst r2, #8
|
||||
stmneia r0!, {r1, r3}
|
||||
tst r2, #4
|
||||
strne r1, [r0], #4
|
||||
/*
|
||||
* When we get here, we've got less than 4 bytes to zero. We
|
||||
* may have an unaligned pointer as well.
|
||||
*/
|
||||
5: tst r2, #2
|
||||
strneb r1, [r0], #1
|
||||
strneb r1, [r0], #1
|
||||
tst r2, #1
|
||||
strneb r1, [r0], #1
|
||||
RETINSTR(mov,pc,lr)
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* linux/arch/arm/lib/setbit.S
|
||||
*
|
||||
* Copyright (C) 1995-1996 Russell King
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <asm/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
#include "bitops.h"
|
||||
.text
|
||||
|
||||
/*
|
||||
* Purpose : Function to set a bit
|
||||
* Prototype: int set_bit(int bit, void *addr)
|
||||
*/
|
||||
ENTRY(_set_bit_be)
|
||||
eor r0, r0, #0x18 @ big endian byte ordering
|
||||
ENTRY(_set_bit_le)
|
||||
bitop orr
|
||||
@@ -0,0 +1,170 @@
|
||||
1 # 1 "lib/setbit.S"
|
||||
1 /*
|
||||
0
|
||||
0
|
||||
2 * linux/arch/arm/lib/setbit.S
|
||||
3 *
|
||||
4 * Copyright (C) 1995-1996 Russell King
|
||||
5 *
|
||||
6 * This program is free software; you can redistribute it and/or modify
|
||||
7 * it under the terms of the GNU General Public License version 2 as
|
||||
8 * published by the Free Software Foundation.
|
||||
9 */
|
||||
10 #include <asm/linkage.h>
|
||||
1 #ifndef __ASM_LINKAGE_H
|
||||
11 #include <asm/assembler.h>
|
||||
1 /*
|
||||
2 * linux/include/asm-arm/assembler.h
|
||||
3 *
|
||||
4 * Copyright (C) 1996-2000 Russell King
|
||||
5 *
|
||||
6 * This program is free software; you can redistribute it and/or modify
|
||||
7 * it under the terms of the GNU General Public License version 2 as
|
||||
8 * published by the Free Software Foundation.
|
||||
9 *
|
||||
10 * This file contains arm architecture specific defines
|
||||
11 * for the different processors.
|
||||
12 *
|
||||
13 * Do not include any C declarations in this file - it is included by
|
||||
14 * assembler source.
|
||||
15 */
|
||||
16 #ifndef __ASSEMBLY__
|
||||
17 #error "Only include this from assembly code"
|
||||
18 #endif
|
||||
19
|
||||
20 #include <asm/ptrace.h>
|
||||
1 /*
|
||||
21
|
||||
22 #define pull lsl
|
||||
23 #define push lsr
|
||||
24 #define get_byte_0 lsr #24
|
||||
25 #define get_byte_1 lsr #16
|
||||
26 #define get_byte_2 lsr #8
|
||||
27 #define get_byte_3 lsl #0
|
||||
28 #define put_byte_0 lsl #24
|
||||
29 #define put_byte_1 lsl #16
|
||||
30 #define put_byte_2 lsl #8
|
||||
31 #define put_byte_3 lsl #0
|
||||
32
|
||||
33 #define PLD(code...)
|
||||
34
|
||||
35 #define MODE_USR USR_MODE
|
||||
36 #define MODE_FIQ FIQ_MODE
|
||||
37 #define MODE_IRQ IRQ_MODE
|
||||
38 #define MODE_SVC SVC_MODE
|
||||
39
|
||||
40 #define DEFAULT_FIQ MODE_FIQ
|
||||
41
|
||||
42 /*
|
||||
43 * LOADREGS - ldm with PC in register list (eg, ldmfd sp!, {pc})
|
||||
44 */
|
||||
45 #ifdef __STDC__
|
||||
46 #define LOADREGS(cond, base, reglist...)\
|
||||
47 ldm##cond base,reglist
|
||||
48 #else
|
||||
49 #define LOADREGS(cond, base, reglist...)\
|
||||
50 ldm/**/cond base,reglist
|
||||
51 #endif
|
||||
52
|
||||
53 /*
|
||||
54 * Build a return instruction for this processor type.
|
||||
55 */
|
||||
56 #define RETINSTR(instr, regs...)\
|
||||
57 instr regs
|
||||
58
|
||||
59 /*
|
||||
60 * Enable and disable interrupts
|
||||
61 */
|
||||
62 .macro disable_irq
|
||||
63 msr cpsr_c, #PSR_I_BIT | SVC_MODE
|
||||
64 .endm
|
||||
65
|
||||
66 .macro enable_irq
|
||||
67 msr cpsr_c, #SVC_MODE
|
||||
68 .endm
|
||||
69
|
||||
70 /*
|
||||
71 * Save the current IRQ state and disable IRQs. Note that this macro
|
||||
72 * assumes FIQs are enabled, and that the processor is in SVC mode.
|
||||
73 */
|
||||
74 .macro save_and_disable_irqs, oldcpsr
|
||||
75 mrs \oldcpsr, cpsr
|
||||
76 disable_irq
|
||||
77 .endm
|
||||
78
|
||||
79 /*
|
||||
80 * Restore interrupt state previously stored in a register. We don't
|
||||
81 * guarantee that this will preserve the flags.
|
||||
82 */
|
||||
83 .macro restore_irqs, oldcpsr
|
||||
84 msr cpsr_c, \oldcpsr
|
||||
85 .endm
|
||||
86
|
||||
87 /*
|
||||
88 * These two are used to save LR/restore PC over a user-based access.
|
||||
89 * The old 26-bit architecture requires that we do. On 32-bit
|
||||
90 * architecture, we can safely ignore this requirement.
|
||||
91 */
|
||||
92 .macro save_lr
|
||||
93 .endm
|
||||
94
|
||||
95 .macro restore_pc
|
||||
96 mov pc, lr
|
||||
97 .endm
|
||||
98 ...
|
||||
12 #include "bitops.h"
|
||||
1 .macro bitop, instr
|
||||
2 and r2, r0, #7
|
||||
3 mov r3, #1
|
||||
4 mov r3, r3, lsl r2
|
||||
5 save_and_disable_irqs ip
|
||||
6 ldrb r2, [r1, r0, lsr #3]
|
||||
7 \instr r2, r2, r3
|
||||
8 strb r2, [r1, r0, lsr #3]
|
||||
9 restore_irqs ip
|
||||
10 mov pc, lr
|
||||
11 .endm
|
||||
12
|
||||
13 /**
|
||||
14 * testop - implement a test_and_xxx_bit operation.
|
||||
15 * @instr: operational instruction
|
||||
16 * @store: store instruction
|
||||
17 *
|
||||
18 * Note: we can trivially conditionalise the store instruction
|
||||
19 * to avoid dirting the data cache.
|
||||
20 */
|
||||
21 .macro testop, instr, store
|
||||
22 add r1, r1, r0, lsr #3
|
||||
23 and r3, r0, #7
|
||||
24 mov r0, #1
|
||||
25 save_and_disable_irqs ip
|
||||
26 ldrb r2, [r1]
|
||||
27 tst r2, r0, lsl r3
|
||||
28 \instr r2, r2, r0, lsl r3
|
||||
29 \store r2, [r1]
|
||||
30 restore_irqs ip
|
||||
31 moveq r0, #0
|
||||
32 mov pc, lr
|
||||
33 .endm
|
||||
34 ...
|
||||
13 .text
|
||||
14
|
||||
15 /*
|
||||
16 * Purpose : Function to set a bit
|
||||
17 * Prototype: int set_bit(int bit, void *addr)
|
||||
18 */
|
||||
19 ENTRY(_set_bit_be)
|
||||
20 0000 180020E2 eor r0, r0, #0x18 @ big endian byte ordering
|
||||
21 ENTRY(_set_bit_le)
|
||||
22 0004 072000E2 bitop orr
|
||||
22 0130A0E3
|
||||
22 1332A0E1
|
||||
22 00C00FE1
|
||||
22 93F021E3
|
||||
DEFINED SYMBOLS
|
||||
lib/setbit.S:19 .text:00000000 _set_bit_be
|
||||
lib/setbit.S:19 .text:00000000 $a
|
||||
lib/setbit.S:21 .text:00000004 _set_bit_le
|
||||
.debug_aranges:0000000c $d
|
||||
|
||||
NO UNDEFINED SYMBOLS
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* linux/lib/string.c
|
||||
*
|
||||
* Copyright (C) 1991, 1992 Linus Torvalds
|
||||
*/
|
||||
|
||||
/*
|
||||
* stupid library routines.. The optimized versions should generally be found
|
||||
* as inline code in <asm-xx/string.h>
|
||||
*
|
||||
* These are buggy as well..
|
||||
*
|
||||
* * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>
|
||||
* - Added strsep() which will replace strtok() soon (because strsep() is
|
||||
* reentrant and should be faster). Use only strsep() in new code, please.
|
||||
*
|
||||
* * Sat Feb 09 2002, Jason Thomas <jason@topic.com.au>,
|
||||
* Matthew Hawkins <matt@mh.dropbear.id.au>
|
||||
* - Kissed strtok() goodbye
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <asm/ctype.h>
|
||||
|
||||
|
||||
#ifndef __HAVE_ARCH_STRNLEN
|
||||
/**
|
||||
* strnlen - Find the length of a length-limited string
|
||||
* @s: The string to be sized
|
||||
* @count: The maximum number of bytes to search
|
||||
*/
|
||||
size_t strnlen(const char *s, size_t count)
|
||||
{
|
||||
const char *sc;
|
||||
|
||||
for (sc = s; count-- && *sc != '\0'; ++sc)
|
||||
/* nothing */;
|
||||
return sc - s;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,94 @@
|
||||
1 .cpu arm7tdmi
|
||||
2 .fpu softvfp
|
||||
3 .eabi_attribute 20, 1
|
||||
4 .eabi_attribute 21, 1
|
||||
5 .eabi_attribute 23, 3
|
||||
6 .eabi_attribute 24, 1
|
||||
7 .eabi_attribute 25, 1
|
||||
8 .eabi_attribute 26, 1
|
||||
9 .eabi_attribute 30, 4
|
||||
10 .eabi_attribute 18, 4
|
||||
11 .file "string.c"
|
||||
19 .Ltext0:
|
||||
20 .cfi_sections .debug_frame
|
||||
21 .align 2
|
||||
22 .global strnlen
|
||||
24 strnlen:
|
||||
25 .LFB2:
|
||||
26 .file 1 "lib/string.c"
|
||||
1:lib/string.c **** /*
|
||||
2:lib/string.c **** * linux/lib/string.c
|
||||
3:lib/string.c **** *
|
||||
4:lib/string.c **** * Copyright (C) 1991, 1992 Linus Torvalds
|
||||
5:lib/string.c **** */
|
||||
6:lib/string.c ****
|
||||
7:lib/string.c **** /*
|
||||
8:lib/string.c **** * stupid library routines.. The optimized versions should generally be found
|
||||
9:lib/string.c **** * as inline code in <asm-xx/string.h>
|
||||
10:lib/string.c **** *
|
||||
11:lib/string.c **** * These are buggy as well..
|
||||
12:lib/string.c **** *
|
||||
13:lib/string.c **** * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>
|
||||
14:lib/string.c **** * - Added strsep() which will replace strtok() soon (because strsep() is
|
||||
15:lib/string.c **** * reentrant and should be faster). Use only strsep() in new code, please.
|
||||
16:lib/string.c **** *
|
||||
17:lib/string.c **** * * Sat Feb 09 2002, Jason Thomas <jason@topic.com.au>,
|
||||
18:lib/string.c **** * Matthew Hawkins <matt@mh.dropbear.id.au>
|
||||
19:lib/string.c **** * - Kissed strtok() goodbye
|
||||
20:lib/string.c **** */
|
||||
21:lib/string.c ****
|
||||
22:lib/string.c **** #include <sys/types.h>
|
||||
23:lib/string.c **** #include <string.h>
|
||||
24:lib/string.c **** #include <asm/ctype.h>
|
||||
25:lib/string.c ****
|
||||
26:lib/string.c ****
|
||||
27:lib/string.c **** #ifndef __HAVE_ARCH_STRNLEN
|
||||
28:lib/string.c **** /**
|
||||
29:lib/string.c **** * strnlen - Find the length of a length-limited string
|
||||
30:lib/string.c **** * @s: The string to be sized
|
||||
31:lib/string.c **** * @count: The maximum number of bytes to search
|
||||
32:lib/string.c **** */
|
||||
33:lib/string.c **** size_t strnlen(const char *s, size_t count)
|
||||
34:lib/string.c **** {
|
||||
27 .loc 1 34 0
|
||||
28 .cfi_startproc
|
||||
29 @ Function supports interworking.
|
||||
30 @ args = 0, pretend = 0, frame = 0
|
||||
31 @ frame_needed = 0, uses_anonymous_args = 0
|
||||
32 @ link register save eliminated.
|
||||
33 .LVL0:
|
||||
34 .loc 1 34 0
|
||||
35 0000 0030A0E1 mov r3, r0
|
||||
36 .LVL1:
|
||||
37 .L3:
|
||||
35:lib/string.c **** const char *sc;
|
||||
36:lib/string.c ****
|
||||
37:lib/string.c **** for (sc = s; count-- && *sc != '\0'; ++sc)
|
||||
38 .loc 1 37 0 discriminator 1
|
||||
39 0004 011051E2 subs r1, r1, #1
|
||||
40 0008 0320A0E1 mov r2, r3
|
||||
41 .LVL2:
|
||||
42 000c 0200003A bcc .L2
|
||||
43 .loc 1 37 0 is_stmt 0 discriminator 2
|
||||
44 0010 01C0D3E4 ldrb ip, [r3], #1 @ zero_extendqisi2
|
||||
45 .LVL3:
|
||||
46 0014 00005CE3 cmp ip, #0
|
||||
47 0018 F9FFFF1A bne .L3
|
||||
48 .L2:
|
||||
38:lib/string.c **** /* nothing */;
|
||||
39:lib/string.c **** return sc - s;
|
||||
40:lib/string.c **** }
|
||||
49 .loc 1 40 0 is_stmt 1
|
||||
50 001c 020060E0 rsb r0, r0, r2
|
||||
51 .LVL4:
|
||||
52 0020 1EFF2FE1 bx lr
|
||||
53 .cfi_endproc
|
||||
54 .LFE2:
|
||||
56 .Letext0:
|
||||
DEFINED SYMBOLS
|
||||
*ABS*:00000000 string.c
|
||||
C:\Users\netz\AppData\Local\Temp\cc4Ne3c1.s:21 .text:00000000 $a
|
||||
C:\Users\netz\AppData\Local\Temp\cc4Ne3c1.s:24 .text:00000000 strnlen
|
||||
.debug_frame:00000010 $d
|
||||
|
||||
NO UNDEFINED SYMBOLS
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* linux/arch/arm/lib/testchangebit.S
|
||||
*
|
||||
* Copyright (C) 1995-1996 Russell King
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <asm/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
#include "bitops.h"
|
||||
.text
|
||||
|
||||
ENTRY(_test_and_change_bit_be)
|
||||
eor r0, r0, #0x18 @ big endian byte ordering
|
||||
ENTRY(_test_and_change_bit_le)
|
||||
testop eor, strb
|
||||
@@ -0,0 +1,166 @@
|
||||
1 # 1 "lib/testchangebit.S"
|
||||
1 /*
|
||||
0
|
||||
0
|
||||
2 * linux/arch/arm/lib/testchangebit.S
|
||||
3 *
|
||||
4 * Copyright (C) 1995-1996 Russell King
|
||||
5 *
|
||||
6 * This program is free software; you can redistribute it and/or modify
|
||||
7 * it under the terms of the GNU General Public License version 2 as
|
||||
8 * published by the Free Software Foundation.
|
||||
9 */
|
||||
10 #include <asm/linkage.h>
|
||||
1 #ifndef __ASM_LINKAGE_H
|
||||
11 #include <asm/assembler.h>
|
||||
1 /*
|
||||
2 * linux/include/asm-arm/assembler.h
|
||||
3 *
|
||||
4 * Copyright (C) 1996-2000 Russell King
|
||||
5 *
|
||||
6 * This program is free software; you can redistribute it and/or modify
|
||||
7 * it under the terms of the GNU General Public License version 2 as
|
||||
8 * published by the Free Software Foundation.
|
||||
9 *
|
||||
10 * This file contains arm architecture specific defines
|
||||
11 * for the different processors.
|
||||
12 *
|
||||
13 * Do not include any C declarations in this file - it is included by
|
||||
14 * assembler source.
|
||||
15 */
|
||||
16 #ifndef __ASSEMBLY__
|
||||
17 #error "Only include this from assembly code"
|
||||
18 #endif
|
||||
19
|
||||
20 #include <asm/ptrace.h>
|
||||
1 /*
|
||||
21
|
||||
22 #define pull lsl
|
||||
23 #define push lsr
|
||||
24 #define get_byte_0 lsr #24
|
||||
25 #define get_byte_1 lsr #16
|
||||
26 #define get_byte_2 lsr #8
|
||||
27 #define get_byte_3 lsl #0
|
||||
28 #define put_byte_0 lsl #24
|
||||
29 #define put_byte_1 lsl #16
|
||||
30 #define put_byte_2 lsl #8
|
||||
31 #define put_byte_3 lsl #0
|
||||
32
|
||||
33 #define PLD(code...)
|
||||
34
|
||||
35 #define MODE_USR USR_MODE
|
||||
36 #define MODE_FIQ FIQ_MODE
|
||||
37 #define MODE_IRQ IRQ_MODE
|
||||
38 #define MODE_SVC SVC_MODE
|
||||
39
|
||||
40 #define DEFAULT_FIQ MODE_FIQ
|
||||
41
|
||||
42 /*
|
||||
43 * LOADREGS - ldm with PC in register list (eg, ldmfd sp!, {pc})
|
||||
44 */
|
||||
45 #ifdef __STDC__
|
||||
46 #define LOADREGS(cond, base, reglist...)\
|
||||
47 ldm##cond base,reglist
|
||||
48 #else
|
||||
49 #define LOADREGS(cond, base, reglist...)\
|
||||
50 ldm/**/cond base,reglist
|
||||
51 #endif
|
||||
52
|
||||
53 /*
|
||||
54 * Build a return instruction for this processor type.
|
||||
55 */
|
||||
56 #define RETINSTR(instr, regs...)\
|
||||
57 instr regs
|
||||
58
|
||||
59 /*
|
||||
60 * Enable and disable interrupts
|
||||
61 */
|
||||
62 .macro disable_irq
|
||||
63 msr cpsr_c, #PSR_I_BIT | SVC_MODE
|
||||
64 .endm
|
||||
65
|
||||
66 .macro enable_irq
|
||||
67 msr cpsr_c, #SVC_MODE
|
||||
68 .endm
|
||||
69
|
||||
70 /*
|
||||
71 * Save the current IRQ state and disable IRQs. Note that this macro
|
||||
72 * assumes FIQs are enabled, and that the processor is in SVC mode.
|
||||
73 */
|
||||
74 .macro save_and_disable_irqs, oldcpsr
|
||||
75 mrs \oldcpsr, cpsr
|
||||
76 disable_irq
|
||||
77 .endm
|
||||
78
|
||||
79 /*
|
||||
80 * Restore interrupt state previously stored in a register. We don't
|
||||
81 * guarantee that this will preserve the flags.
|
||||
82 */
|
||||
83 .macro restore_irqs, oldcpsr
|
||||
84 msr cpsr_c, \oldcpsr
|
||||
85 .endm
|
||||
86
|
||||
87 /*
|
||||
88 * These two are used to save LR/restore PC over a user-based access.
|
||||
89 * The old 26-bit architecture requires that we do. On 32-bit
|
||||
90 * architecture, we can safely ignore this requirement.
|
||||
91 */
|
||||
92 .macro save_lr
|
||||
93 .endm
|
||||
94
|
||||
95 .macro restore_pc
|
||||
96 mov pc, lr
|
||||
97 .endm
|
||||
98 ...
|
||||
12 #include "bitops.h"
|
||||
1 .macro bitop, instr
|
||||
2 and r2, r0, #7
|
||||
3 mov r3, #1
|
||||
4 mov r3, r3, lsl r2
|
||||
5 save_and_disable_irqs ip
|
||||
6 ldrb r2, [r1, r0, lsr #3]
|
||||
7 \instr r2, r2, r3
|
||||
8 strb r2, [r1, r0, lsr #3]
|
||||
9 restore_irqs ip
|
||||
10 mov pc, lr
|
||||
11 .endm
|
||||
12
|
||||
13 /**
|
||||
14 * testop - implement a test_and_xxx_bit operation.
|
||||
15 * @instr: operational instruction
|
||||
16 * @store: store instruction
|
||||
17 *
|
||||
18 * Note: we can trivially conditionalise the store instruction
|
||||
19 * to avoid dirting the data cache.
|
||||
20 */
|
||||
21 .macro testop, instr, store
|
||||
22 add r1, r1, r0, lsr #3
|
||||
23 and r3, r0, #7
|
||||
24 mov r0, #1
|
||||
25 save_and_disable_irqs ip
|
||||
26 ldrb r2, [r1]
|
||||
27 tst r2, r0, lsl r3
|
||||
28 \instr r2, r2, r0, lsl r3
|
||||
29 \store r2, [r1]
|
||||
30 restore_irqs ip
|
||||
31 moveq r0, #0
|
||||
32 mov pc, lr
|
||||
33 .endm
|
||||
34 ...
|
||||
13 .text
|
||||
14
|
||||
15 ENTRY(_test_and_change_bit_be)
|
||||
16 0000 180020E2 eor r0, r0, #0x18 @ big endian byte ordering
|
||||
17 ENTRY(_test_and_change_bit_le)
|
||||
18 0004 A01181E0 testop eor, strb
|
||||
18 073000E2
|
||||
18 0100A0E3
|
||||
18 00C00FE1
|
||||
18 93F021E3
|
||||
DEFINED SYMBOLS
|
||||
lib/testchangebit.S:15 .text:00000000 _test_and_change_bit_be
|
||||
lib/testchangebit.S:15 .text:00000000 $a
|
||||
lib/testchangebit.S:17 .text:00000004 _test_and_change_bit_le
|
||||
.debug_aranges:0000000c $d
|
||||
|
||||
NO UNDEFINED SYMBOLS
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* linux/arch/arm/lib/testclearbit.S
|
||||
*
|
||||
* Copyright (C) 1995-1996 Russell King
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <asm/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
#include "bitops.h"
|
||||
.text
|
||||
|
||||
ENTRY(_test_and_clear_bit_be)
|
||||
eor r0, r0, #0x18 @ big endian byte ordering
|
||||
ENTRY(_test_and_clear_bit_le)
|
||||
testop bicne, strneb
|
||||
@@ -0,0 +1,166 @@
|
||||
1 # 1 "lib/testclearbit.S"
|
||||
1 /*
|
||||
0
|
||||
0
|
||||
2 * linux/arch/arm/lib/testclearbit.S
|
||||
3 *
|
||||
4 * Copyright (C) 1995-1996 Russell King
|
||||
5 *
|
||||
6 * This program is free software; you can redistribute it and/or modify
|
||||
7 * it under the terms of the GNU General Public License version 2 as
|
||||
8 * published by the Free Software Foundation.
|
||||
9 */
|
||||
10 #include <asm/linkage.h>
|
||||
1 #ifndef __ASM_LINKAGE_H
|
||||
11 #include <asm/assembler.h>
|
||||
1 /*
|
||||
2 * linux/include/asm-arm/assembler.h
|
||||
3 *
|
||||
4 * Copyright (C) 1996-2000 Russell King
|
||||
5 *
|
||||
6 * This program is free software; you can redistribute it and/or modify
|
||||
7 * it under the terms of the GNU General Public License version 2 as
|
||||
8 * published by the Free Software Foundation.
|
||||
9 *
|
||||
10 * This file contains arm architecture specific defines
|
||||
11 * for the different processors.
|
||||
12 *
|
||||
13 * Do not include any C declarations in this file - it is included by
|
||||
14 * assembler source.
|
||||
15 */
|
||||
16 #ifndef __ASSEMBLY__
|
||||
17 #error "Only include this from assembly code"
|
||||
18 #endif
|
||||
19
|
||||
20 #include <asm/ptrace.h>
|
||||
1 /*
|
||||
21
|
||||
22 #define pull lsl
|
||||
23 #define push lsr
|
||||
24 #define get_byte_0 lsr #24
|
||||
25 #define get_byte_1 lsr #16
|
||||
26 #define get_byte_2 lsr #8
|
||||
27 #define get_byte_3 lsl #0
|
||||
28 #define put_byte_0 lsl #24
|
||||
29 #define put_byte_1 lsl #16
|
||||
30 #define put_byte_2 lsl #8
|
||||
31 #define put_byte_3 lsl #0
|
||||
32
|
||||
33 #define PLD(code...)
|
||||
34
|
||||
35 #define MODE_USR USR_MODE
|
||||
36 #define MODE_FIQ FIQ_MODE
|
||||
37 #define MODE_IRQ IRQ_MODE
|
||||
38 #define MODE_SVC SVC_MODE
|
||||
39
|
||||
40 #define DEFAULT_FIQ MODE_FIQ
|
||||
41
|
||||
42 /*
|
||||
43 * LOADREGS - ldm with PC in register list (eg, ldmfd sp!, {pc})
|
||||
44 */
|
||||
45 #ifdef __STDC__
|
||||
46 #define LOADREGS(cond, base, reglist...)\
|
||||
47 ldm##cond base,reglist
|
||||
48 #else
|
||||
49 #define LOADREGS(cond, base, reglist...)\
|
||||
50 ldm/**/cond base,reglist
|
||||
51 #endif
|
||||
52
|
||||
53 /*
|
||||
54 * Build a return instruction for this processor type.
|
||||
55 */
|
||||
56 #define RETINSTR(instr, regs...)\
|
||||
57 instr regs
|
||||
58
|
||||
59 /*
|
||||
60 * Enable and disable interrupts
|
||||
61 */
|
||||
62 .macro disable_irq
|
||||
63 msr cpsr_c, #PSR_I_BIT | SVC_MODE
|
||||
64 .endm
|
||||
65
|
||||
66 .macro enable_irq
|
||||
67 msr cpsr_c, #SVC_MODE
|
||||
68 .endm
|
||||
69
|
||||
70 /*
|
||||
71 * Save the current IRQ state and disable IRQs. Note that this macro
|
||||
72 * assumes FIQs are enabled, and that the processor is in SVC mode.
|
||||
73 */
|
||||
74 .macro save_and_disable_irqs, oldcpsr
|
||||
75 mrs \oldcpsr, cpsr
|
||||
76 disable_irq
|
||||
77 .endm
|
||||
78
|
||||
79 /*
|
||||
80 * Restore interrupt state previously stored in a register. We don't
|
||||
81 * guarantee that this will preserve the flags.
|
||||
82 */
|
||||
83 .macro restore_irqs, oldcpsr
|
||||
84 msr cpsr_c, \oldcpsr
|
||||
85 .endm
|
||||
86
|
||||
87 /*
|
||||
88 * These two are used to save LR/restore PC over a user-based access.
|
||||
89 * The old 26-bit architecture requires that we do. On 32-bit
|
||||
90 * architecture, we can safely ignore this requirement.
|
||||
91 */
|
||||
92 .macro save_lr
|
||||
93 .endm
|
||||
94
|
||||
95 .macro restore_pc
|
||||
96 mov pc, lr
|
||||
97 .endm
|
||||
98 ...
|
||||
12 #include "bitops.h"
|
||||
1 .macro bitop, instr
|
||||
2 and r2, r0, #7
|
||||
3 mov r3, #1
|
||||
4 mov r3, r3, lsl r2
|
||||
5 save_and_disable_irqs ip
|
||||
6 ldrb r2, [r1, r0, lsr #3]
|
||||
7 \instr r2, r2, r3
|
||||
8 strb r2, [r1, r0, lsr #3]
|
||||
9 restore_irqs ip
|
||||
10 mov pc, lr
|
||||
11 .endm
|
||||
12
|
||||
13 /**
|
||||
14 * testop - implement a test_and_xxx_bit operation.
|
||||
15 * @instr: operational instruction
|
||||
16 * @store: store instruction
|
||||
17 *
|
||||
18 * Note: we can trivially conditionalise the store instruction
|
||||
19 * to avoid dirting the data cache.
|
||||
20 */
|
||||
21 .macro testop, instr, store
|
||||
22 add r1, r1, r0, lsr #3
|
||||
23 and r3, r0, #7
|
||||
24 mov r0, #1
|
||||
25 save_and_disable_irqs ip
|
||||
26 ldrb r2, [r1]
|
||||
27 tst r2, r0, lsl r3
|
||||
28 \instr r2, r2, r0, lsl r3
|
||||
29 \store r2, [r1]
|
||||
30 restore_irqs ip
|
||||
31 moveq r0, #0
|
||||
32 mov pc, lr
|
||||
33 .endm
|
||||
34 ...
|
||||
13 .text
|
||||
14
|
||||
15 ENTRY(_test_and_clear_bit_be)
|
||||
16 0000 180020E2 eor r0, r0, #0x18 @ big endian byte ordering
|
||||
17 ENTRY(_test_and_clear_bit_le)
|
||||
18 0004 A01181E0 testop bicne, strneb
|
||||
18 073000E2
|
||||
18 0100A0E3
|
||||
18 00C00FE1
|
||||
18 93F021E3
|
||||
DEFINED SYMBOLS
|
||||
lib/testclearbit.S:15 .text:00000000 _test_and_clear_bit_be
|
||||
lib/testclearbit.S:15 .text:00000000 $a
|
||||
lib/testclearbit.S:17 .text:00000004 _test_and_clear_bit_le
|
||||
.debug_aranges:0000000c $d
|
||||
|
||||
NO UNDEFINED SYMBOLS
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* linux/arch/arm/lib/testsetbit.S
|
||||
*
|
||||
* Copyright (C) 1995-1996 Russell King
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <asm/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
#include "bitops.h"
|
||||
.text
|
||||
|
||||
ENTRY(_test_and_set_bit_be)
|
||||
eor r0, r0, #0x18 @ big endian byte ordering
|
||||
ENTRY(_test_and_set_bit_le)
|
||||
testop orreq, streqb
|
||||
@@ -0,0 +1,166 @@
|
||||
1 # 1 "lib/testsetbit.S"
|
||||
1 /*
|
||||
0
|
||||
0
|
||||
2 * linux/arch/arm/lib/testsetbit.S
|
||||
3 *
|
||||
4 * Copyright (C) 1995-1996 Russell King
|
||||
5 *
|
||||
6 * This program is free software; you can redistribute it and/or modify
|
||||
7 * it under the terms of the GNU General Public License version 2 as
|
||||
8 * published by the Free Software Foundation.
|
||||
9 */
|
||||
10 #include <asm/linkage.h>
|
||||
1 #ifndef __ASM_LINKAGE_H
|
||||
11 #include <asm/assembler.h>
|
||||
1 /*
|
||||
2 * linux/include/asm-arm/assembler.h
|
||||
3 *
|
||||
4 * Copyright (C) 1996-2000 Russell King
|
||||
5 *
|
||||
6 * This program is free software; you can redistribute it and/or modify
|
||||
7 * it under the terms of the GNU General Public License version 2 as
|
||||
8 * published by the Free Software Foundation.
|
||||
9 *
|
||||
10 * This file contains arm architecture specific defines
|
||||
11 * for the different processors.
|
||||
12 *
|
||||
13 * Do not include any C declarations in this file - it is included by
|
||||
14 * assembler source.
|
||||
15 */
|
||||
16 #ifndef __ASSEMBLY__
|
||||
17 #error "Only include this from assembly code"
|
||||
18 #endif
|
||||
19
|
||||
20 #include <asm/ptrace.h>
|
||||
1 /*
|
||||
21
|
||||
22 #define pull lsl
|
||||
23 #define push lsr
|
||||
24 #define get_byte_0 lsr #24
|
||||
25 #define get_byte_1 lsr #16
|
||||
26 #define get_byte_2 lsr #8
|
||||
27 #define get_byte_3 lsl #0
|
||||
28 #define put_byte_0 lsl #24
|
||||
29 #define put_byte_1 lsl #16
|
||||
30 #define put_byte_2 lsl #8
|
||||
31 #define put_byte_3 lsl #0
|
||||
32
|
||||
33 #define PLD(code...)
|
||||
34
|
||||
35 #define MODE_USR USR_MODE
|
||||
36 #define MODE_FIQ FIQ_MODE
|
||||
37 #define MODE_IRQ IRQ_MODE
|
||||
38 #define MODE_SVC SVC_MODE
|
||||
39
|
||||
40 #define DEFAULT_FIQ MODE_FIQ
|
||||
41
|
||||
42 /*
|
||||
43 * LOADREGS - ldm with PC in register list (eg, ldmfd sp!, {pc})
|
||||
44 */
|
||||
45 #ifdef __STDC__
|
||||
46 #define LOADREGS(cond, base, reglist...)\
|
||||
47 ldm##cond base,reglist
|
||||
48 #else
|
||||
49 #define LOADREGS(cond, base, reglist...)\
|
||||
50 ldm/**/cond base,reglist
|
||||
51 #endif
|
||||
52
|
||||
53 /*
|
||||
54 * Build a return instruction for this processor type.
|
||||
55 */
|
||||
56 #define RETINSTR(instr, regs...)\
|
||||
57 instr regs
|
||||
58
|
||||
59 /*
|
||||
60 * Enable and disable interrupts
|
||||
61 */
|
||||
62 .macro disable_irq
|
||||
63 msr cpsr_c, #PSR_I_BIT | SVC_MODE
|
||||
64 .endm
|
||||
65
|
||||
66 .macro enable_irq
|
||||
67 msr cpsr_c, #SVC_MODE
|
||||
68 .endm
|
||||
69
|
||||
70 /*
|
||||
71 * Save the current IRQ state and disable IRQs. Note that this macro
|
||||
72 * assumes FIQs are enabled, and that the processor is in SVC mode.
|
||||
73 */
|
||||
74 .macro save_and_disable_irqs, oldcpsr
|
||||
75 mrs \oldcpsr, cpsr
|
||||
76 disable_irq
|
||||
77 .endm
|
||||
78
|
||||
79 /*
|
||||
80 * Restore interrupt state previously stored in a register. We don't
|
||||
81 * guarantee that this will preserve the flags.
|
||||
82 */
|
||||
83 .macro restore_irqs, oldcpsr
|
||||
84 msr cpsr_c, \oldcpsr
|
||||
85 .endm
|
||||
86
|
||||
87 /*
|
||||
88 * These two are used to save LR/restore PC over a user-based access.
|
||||
89 * The old 26-bit architecture requires that we do. On 32-bit
|
||||
90 * architecture, we can safely ignore this requirement.
|
||||
91 */
|
||||
92 .macro save_lr
|
||||
93 .endm
|
||||
94
|
||||
95 .macro restore_pc
|
||||
96 mov pc, lr
|
||||
97 .endm
|
||||
98 ...
|
||||
12 #include "bitops.h"
|
||||
1 .macro bitop, instr
|
||||
2 and r2, r0, #7
|
||||
3 mov r3, #1
|
||||
4 mov r3, r3, lsl r2
|
||||
5 save_and_disable_irqs ip
|
||||
6 ldrb r2, [r1, r0, lsr #3]
|
||||
7 \instr r2, r2, r3
|
||||
8 strb r2, [r1, r0, lsr #3]
|
||||
9 restore_irqs ip
|
||||
10 mov pc, lr
|
||||
11 .endm
|
||||
12
|
||||
13 /**
|
||||
14 * testop - implement a test_and_xxx_bit operation.
|
||||
15 * @instr: operational instruction
|
||||
16 * @store: store instruction
|
||||
17 *
|
||||
18 * Note: we can trivially conditionalise the store instruction
|
||||
19 * to avoid dirting the data cache.
|
||||
20 */
|
||||
21 .macro testop, instr, store
|
||||
22 add r1, r1, r0, lsr #3
|
||||
23 and r3, r0, #7
|
||||
24 mov r0, #1
|
||||
25 save_and_disable_irqs ip
|
||||
26 ldrb r2, [r1]
|
||||
27 tst r2, r0, lsl r3
|
||||
28 \instr r2, r2, r0, lsl r3
|
||||
29 \store r2, [r1]
|
||||
30 restore_irqs ip
|
||||
31 moveq r0, #0
|
||||
32 mov pc, lr
|
||||
33 .endm
|
||||
34 ...
|
||||
13 .text
|
||||
14
|
||||
15 ENTRY(_test_and_set_bit_be)
|
||||
16 0000 180020E2 eor r0, r0, #0x18 @ big endian byte ordering
|
||||
17 ENTRY(_test_and_set_bit_le)
|
||||
18 0004 A01181E0 testop orreq, streqb
|
||||
18 073000E2
|
||||
18 0100A0E3
|
||||
18 00C00FE1
|
||||
18 93F021E3
|
||||
DEFINED SYMBOLS
|
||||
lib/testsetbit.S:15 .text:00000000 _test_and_set_bit_be
|
||||
lib/testsetbit.S:15 .text:00000000 $a
|
||||
lib/testsetbit.S:17 .text:00000004 _test_and_set_bit_le
|
||||
.debug_aranges:0000000c $d
|
||||
|
||||
NO UNDEFINED SYMBOLS
|
||||
@@ -0,0 +1,831 @@
|
||||
/*
|
||||
* linux/lib/vsprintf.c
|
||||
*
|
||||
* Copyright (C) 1991, 1992 Linus Torvalds
|
||||
*/
|
||||
|
||||
/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
|
||||
/*
|
||||
* Wirzenius wrote this portably, Torvalds fucked it up :-)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
|
||||
* - changed to provide snprintf and vsnprintf functions
|
||||
* So Feb 1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de>
|
||||
* - scnprintf and vscnprintf
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <asm/ctype.h>
|
||||
|
||||
#include <asm/div64.h>
|
||||
#include <limits.h>
|
||||
|
||||
/**
|
||||
* simple_strtoul - convert a string to an unsigned long
|
||||
* @cp: The start of the string
|
||||
* @endp: A pointer to the end of the parsed string will be placed here
|
||||
* @base: The number base to use
|
||||
*/
|
||||
unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
|
||||
{
|
||||
unsigned long result = 0,value;
|
||||
|
||||
if (!base) {
|
||||
base = 10;
|
||||
if (*cp == '0') {
|
||||
base = 8;
|
||||
cp++;
|
||||
if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
|
||||
cp++;
|
||||
base = 16;
|
||||
}
|
||||
}
|
||||
} else if (base == 16) {
|
||||
if (cp[0] == '0' && toupper(cp[1]) == 'X')
|
||||
cp += 2;
|
||||
}
|
||||
while (isxdigit(*cp) &&
|
||||
(value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
|
||||
result = result*base + value;
|
||||
cp++;
|
||||
}
|
||||
if (endp)
|
||||
*endp = (char *)cp;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* simple_strtol - convert a string to a signed long
|
||||
* @cp: The start of the string
|
||||
* @endp: A pointer to the end of the parsed string will be placed here
|
||||
* @base: The number base to use
|
||||
*/
|
||||
long simple_strtol(const char *cp,char **endp,unsigned int base)
|
||||
{
|
||||
if(*cp=='-')
|
||||
return -simple_strtoul(cp+1,endp,base);
|
||||
return simple_strtoul(cp,endp,base);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* simple_strtoull - convert a string to an unsigned long long
|
||||
* @cp: The start of the string
|
||||
* @endp: A pointer to the end of the parsed string will be placed here
|
||||
* @base: The number base to use
|
||||
*/
|
||||
unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
|
||||
{
|
||||
unsigned long long result = 0,value;
|
||||
|
||||
if (!base) {
|
||||
base = 10;
|
||||
if (*cp == '0') {
|
||||
base = 8;
|
||||
cp++;
|
||||
if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
|
||||
cp++;
|
||||
base = 16;
|
||||
}
|
||||
}
|
||||
} else if (base == 16) {
|
||||
if (cp[0] == '0' && toupper(cp[1]) == 'X')
|
||||
cp += 2;
|
||||
}
|
||||
while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
|
||||
? toupper(*cp) : *cp)-'A'+10) < base) {
|
||||
result = result*base + value;
|
||||
cp++;
|
||||
}
|
||||
if (endp)
|
||||
*endp = (char *)cp;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* simple_strtoll - convert a string to a signed long long
|
||||
* @cp: The start of the string
|
||||
* @endp: A pointer to the end of the parsed string will be placed here
|
||||
* @base: The number base to use
|
||||
*/
|
||||
long long simple_strtoll(const char *cp,char **endp,unsigned int base)
|
||||
{
|
||||
if(*cp=='-')
|
||||
return -simple_strtoull(cp+1,endp,base);
|
||||
return simple_strtoull(cp,endp,base);
|
||||
}
|
||||
|
||||
static int skip_atoi(const char **s)
|
||||
{
|
||||
int i=0;
|
||||
|
||||
while (isdigit(**s))
|
||||
i = i*10 + *((*s)++) - '0';
|
||||
return i;
|
||||
}
|
||||
|
||||
#define ZEROPAD 1 /* pad with zero */
|
||||
#define SIGN 2 /* unsigned/signed long */
|
||||
#define PLUS 4 /* show plus */
|
||||
#define SPACE 8 /* space if plus */
|
||||
#define LEFT 16 /* left justified */
|
||||
#define SPECIAL 32 /* 0x */
|
||||
#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
|
||||
|
||||
static char * number(char * buf, char * end, unsigned long long num, int base, int size, int precision, int type)
|
||||
{
|
||||
char c,sign,tmp[66];
|
||||
const char *digits;
|
||||
static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
int i;
|
||||
|
||||
digits = (type & LARGE) ? large_digits : small_digits;
|
||||
if (type & LEFT)
|
||||
type &= ~ZEROPAD;
|
||||
if (base < 2 || base > 36)
|
||||
return NULL;
|
||||
c = (type & ZEROPAD) ? '0' : ' ';
|
||||
sign = 0;
|
||||
if (type & SIGN) {
|
||||
if ((signed long long) num < 0) {
|
||||
sign = '-';
|
||||
num = - (signed long long) num;
|
||||
size--;
|
||||
} else if (type & PLUS) {
|
||||
sign = '+';
|
||||
size--;
|
||||
} else if (type & SPACE) {
|
||||
sign = ' ';
|
||||
size--;
|
||||
}
|
||||
}
|
||||
if (type & SPECIAL) {
|
||||
if (base == 16)
|
||||
size -= 2;
|
||||
else if (base == 8)
|
||||
size--;
|
||||
}
|
||||
i = 0;
|
||||
if (num == 0)
|
||||
tmp[i++]='0';
|
||||
else while (num != 0)
|
||||
tmp[i++] = digits[do_div(num,base)];
|
||||
if (i > precision)
|
||||
precision = i;
|
||||
size -= precision;
|
||||
if (!(type&(ZEROPAD+LEFT))) {
|
||||
while(size-->0) {
|
||||
if (buf <= end)
|
||||
*buf = ' ';
|
||||
++buf;
|
||||
}
|
||||
}
|
||||
if (sign) {
|
||||
if (buf <= end)
|
||||
*buf = sign;
|
||||
++buf;
|
||||
}
|
||||
if (type & SPECIAL) {
|
||||
if (base==8) {
|
||||
if (buf <= end)
|
||||
*buf = '0';
|
||||
++buf;
|
||||
} else if (base==16) {
|
||||
if (buf <= end)
|
||||
*buf = '0';
|
||||
++buf;
|
||||
if (buf <= end)
|
||||
*buf = digits[33];
|
||||
++buf;
|
||||
}
|
||||
}
|
||||
if (!(type & LEFT)) {
|
||||
while (size-- > 0) {
|
||||
if (buf <= end)
|
||||
*buf = c;
|
||||
++buf;
|
||||
}
|
||||
}
|
||||
while (i < precision--) {
|
||||
if (buf <= end)
|
||||
*buf = '0';
|
||||
++buf;
|
||||
}
|
||||
while (i-- > 0) {
|
||||
if (buf <= end)
|
||||
*buf = tmp[i];
|
||||
++buf;
|
||||
}
|
||||
while (size-- > 0) {
|
||||
if (buf <= end)
|
||||
*buf = ' ';
|
||||
++buf;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* vsnprintf - Format a string and place it in a buffer
|
||||
* @buf: The buffer to place the result into
|
||||
* @size: The size of the buffer, including the trailing null space
|
||||
* @fmt: The format string to use
|
||||
* @args: Arguments for the format string
|
||||
*
|
||||
* The return value is the number of characters which would
|
||||
* be generated for the given input, excluding the trailing
|
||||
* '\0', as per ISO C99. If you want to have the exact
|
||||
* number of characters written into @buf as return value
|
||||
* (not including the trailing '\0'), use vscnprintf. If the
|
||||
* return is greater than or equal to @size, the resulting
|
||||
* string is truncated.
|
||||
*
|
||||
* Call this function if you are already dealing with a va_list.
|
||||
* You probably want snprintf instead.
|
||||
*/
|
||||
int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
|
||||
{
|
||||
int len;
|
||||
unsigned long long num;
|
||||
int i, base;
|
||||
char *str, *end, c;
|
||||
const char *s;
|
||||
|
||||
int flags; /* flags to number() */
|
||||
|
||||
int field_width; /* width of output field */
|
||||
int precision; /* min. # of digits for integers; max
|
||||
number of chars for from string */
|
||||
int qualifier; /* 'h', 'l', or 'L' for integer fields */
|
||||
/* 'z' support added 23/7/1999 S.H. */
|
||||
/* 'z' changed to 'Z' --davidm 1/25/99 */
|
||||
/* 't' added for ptrdiff_t */
|
||||
|
||||
/* Reject out-of-range values early */
|
||||
if ((int) size < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
str = buf;
|
||||
end = buf + size - 1;
|
||||
|
||||
if (end < buf - 1) {
|
||||
end = ((void *) -1);
|
||||
size = end - buf + 1;
|
||||
}
|
||||
|
||||
for (; *fmt ; ++fmt) {
|
||||
if (*fmt != '%') {
|
||||
if (str <= end)
|
||||
*str = *fmt;
|
||||
++str;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* process flags */
|
||||
flags = 0;
|
||||
repeat:
|
||||
++fmt; /* this also skips first '%' */
|
||||
switch (*fmt) {
|
||||
case '-': flags |= LEFT; goto repeat;
|
||||
case '+': flags |= PLUS; goto repeat;
|
||||
case ' ': flags |= SPACE; goto repeat;
|
||||
case '#': flags |= SPECIAL; goto repeat;
|
||||
case '0': flags |= ZEROPAD; goto repeat;
|
||||
}
|
||||
|
||||
/* get field width */
|
||||
field_width = -1;
|
||||
if (isdigit(*fmt))
|
||||
field_width = skip_atoi(&fmt);
|
||||
else if (*fmt == '*') {
|
||||
++fmt;
|
||||
/* it's the next argument */
|
||||
field_width = va_arg(args, int);
|
||||
if (field_width < 0) {
|
||||
field_width = -field_width;
|
||||
flags |= LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the precision */
|
||||
precision = -1;
|
||||
if (*fmt == '.') {
|
||||
++fmt;
|
||||
if (isdigit(*fmt))
|
||||
precision = skip_atoi(&fmt);
|
||||
else if (*fmt == '*') {
|
||||
++fmt;
|
||||
/* it's the next argument */
|
||||
precision = va_arg(args, int);
|
||||
}
|
||||
if (precision < 0)
|
||||
precision = 0;
|
||||
}
|
||||
|
||||
/* get the conversion qualifier */
|
||||
qualifier = -1;
|
||||
if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
|
||||
*fmt =='Z' || *fmt == 'z' || *fmt == 't') {
|
||||
qualifier = *fmt;
|
||||
++fmt;
|
||||
if (qualifier == 'l' && *fmt == 'l') {
|
||||
qualifier = 'L';
|
||||
++fmt;
|
||||
}
|
||||
}
|
||||
|
||||
/* default base */
|
||||
base = 10;
|
||||
|
||||
switch (*fmt) {
|
||||
case 'c':
|
||||
if (!(flags & LEFT)) {
|
||||
while (--field_width > 0) {
|
||||
if (str <= end)
|
||||
*str = ' ';
|
||||
++str;
|
||||
}
|
||||
}
|
||||
c = (unsigned char) va_arg(args, int);
|
||||
if (str <= end)
|
||||
*str = c;
|
||||
++str;
|
||||
while (--field_width > 0) {
|
||||
if (str <= end)
|
||||
*str = ' ';
|
||||
++str;
|
||||
}
|
||||
continue;
|
||||
|
||||
case 's':
|
||||
s = va_arg(args, char *);
|
||||
|
||||
len = strnlen(s, precision);
|
||||
|
||||
if (!(flags & LEFT)) {
|
||||
while (len < field_width--) {
|
||||
if (str <= end)
|
||||
*str = ' ';
|
||||
++str;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < len; ++i) {
|
||||
if (str <= end)
|
||||
*str = *s;
|
||||
++str; ++s;
|
||||
}
|
||||
while (len < field_width--) {
|
||||
if (str <= end)
|
||||
*str = ' ';
|
||||
++str;
|
||||
}
|
||||
continue;
|
||||
|
||||
case 'p':
|
||||
if (field_width == -1) {
|
||||
field_width = 2*sizeof(void *);
|
||||
flags |= ZEROPAD;
|
||||
}
|
||||
str = number(str, end,
|
||||
(unsigned long) va_arg(args, void *),
|
||||
16, field_width, precision, flags);
|
||||
continue;
|
||||
|
||||
|
||||
case 'n':
|
||||
/* FIXME:
|
||||
* What does C99 say about the overflow case here? */
|
||||
if (qualifier == 'l') {
|
||||
long * ip = va_arg(args, long *);
|
||||
*ip = (str - buf);
|
||||
} else if (qualifier == 'Z' || qualifier == 'z') {
|
||||
size_t * ip = va_arg(args, size_t *);
|
||||
*ip = (str - buf);
|
||||
} else {
|
||||
int * ip = va_arg(args, int *);
|
||||
*ip = (str - buf);
|
||||
}
|
||||
continue;
|
||||
|
||||
case '%':
|
||||
if (str <= end)
|
||||
*str = '%';
|
||||
++str;
|
||||
continue;
|
||||
|
||||
/* integer number formats - set up the flags and "break" */
|
||||
case 'o':
|
||||
base = 8;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
flags |= LARGE;
|
||||
case 'x':
|
||||
base = 16;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
flags |= SIGN;
|
||||
case 'u':
|
||||
break;
|
||||
|
||||
default:
|
||||
if (str <= end)
|
||||
*str = '%';
|
||||
++str;
|
||||
if (*fmt) {
|
||||
if (str <= end)
|
||||
*str = *fmt;
|
||||
++str;
|
||||
} else {
|
||||
--fmt;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (qualifier == 'L')
|
||||
num = va_arg(args, long long);
|
||||
else if (qualifier == 'l') {
|
||||
num = va_arg(args, unsigned long);
|
||||
if (flags & SIGN)
|
||||
num = (signed long) num;
|
||||
} else if (qualifier == 'Z' || qualifier == 'z') {
|
||||
num = va_arg(args, size_t);
|
||||
} else if (qualifier == 't') {
|
||||
num = va_arg(args, ptrdiff_t);
|
||||
} else if (qualifier == 'h') {
|
||||
num = (unsigned short) va_arg(args, int);
|
||||
if (flags & SIGN)
|
||||
num = (signed short) num;
|
||||
} else {
|
||||
num = va_arg(args, unsigned int);
|
||||
if (flags & SIGN)
|
||||
num = (signed int) num;
|
||||
}
|
||||
str = number(str, end, num, base,
|
||||
field_width, precision, flags);
|
||||
}
|
||||
if (str <= end)
|
||||
*str = '\0';
|
||||
else if (size > 0)
|
||||
/* don't write out a null byte if the buf size is zero */
|
||||
*end = '\0';
|
||||
/* the trailing null byte doesn't count towards the total
|
||||
* ++str;
|
||||
*/
|
||||
return str-buf;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* vscnprintf - Format a string and place it in a buffer
|
||||
* @buf: The buffer to place the result into
|
||||
* @size: The size of the buffer, including the trailing null space
|
||||
* @fmt: The format string to use
|
||||
* @args: Arguments for the format string
|
||||
*
|
||||
* The return value is the number of characters which have been written into
|
||||
* the @buf not including the trailing '\0'. If @size is <= 0 the function
|
||||
* returns 0.
|
||||
*
|
||||
* Call this function if you are already dealing with a va_list.
|
||||
* You probably want scnprintf instead.
|
||||
*/
|
||||
int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
i=vsnprintf(buf,size,fmt,args);
|
||||
return (i >= size) ? (size - 1) : i;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* snprintf - Format a string and place it in a buffer
|
||||
* @buf: The buffer to place the result into
|
||||
* @size: The size of the buffer, including the trailing null space
|
||||
* @fmt: The format string to use
|
||||
* @...: Arguments for the format string
|
||||
*
|
||||
* The return value is the number of characters which would be
|
||||
* generated for the given input, excluding the trailing null,
|
||||
* as per ISO C99. If the return is greater than or equal to
|
||||
* @size, the resulting string is truncated.
|
||||
*/
|
||||
int snprintf(char * buf, size_t size, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int i;
|
||||
|
||||
va_start(args, fmt);
|
||||
i=vsnprintf(buf,size,fmt,args);
|
||||
va_end(args);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* scnprintf - Format a string and place it in a buffer
|
||||
* @buf: The buffer to place the result into
|
||||
* @size: The size of the buffer, including the trailing null space
|
||||
* @fmt: The format string to use
|
||||
* @...: Arguments for the format string
|
||||
*
|
||||
* The return value is the number of characters written into @buf not including
|
||||
* the trailing '\0'. If @size is <= 0 the function returns 0. If the return is
|
||||
* greater than or equal to @size, the resulting string is truncated.
|
||||
*/
|
||||
|
||||
int scnprintf(char * buf, size_t size, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
unsigned int i;
|
||||
|
||||
va_start(args, fmt);
|
||||
i = vsnprintf(buf, size, fmt, args);
|
||||
va_end(args);
|
||||
return (i >= size) ? (size - 1) : i;
|
||||
}
|
||||
|
||||
/**
|
||||
* vsprintf - Format a string and place it in a buffer
|
||||
* @buf: The buffer to place the result into
|
||||
* @fmt: The format string to use
|
||||
* @args: Arguments for the format string
|
||||
*
|
||||
* The function returns the number of characters written
|
||||
* into @buf. Use vsnprintf or vscnprintf in order to avoid
|
||||
* buffer overflows.
|
||||
*
|
||||
* Call this function if you are already dealing with a va_list.
|
||||
* You probably want sprintf instead.
|
||||
*/
|
||||
int vsprintf(char *buf, const char *fmt, va_list args)
|
||||
{
|
||||
return vsnprintf(buf, INT_MAX, fmt, args);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sprintf - Format a string and place it in a buffer
|
||||
* @buf: The buffer to place the result into
|
||||
* @fmt: The format string to use
|
||||
* @...: Arguments for the format string
|
||||
*
|
||||
* The function returns the number of characters written
|
||||
* into @buf. Use snprintf or scnprintf in order to avoid
|
||||
* buffer overflows.
|
||||
*/
|
||||
int sprintf(char * buf, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int i;
|
||||
|
||||
va_start(args, fmt);
|
||||
i=vsnprintf(buf, INT_MAX, fmt, args);
|
||||
va_end(args);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* vsscanf - Unformat a buffer into a list of arguments
|
||||
* @buf: input buffer
|
||||
* @fmt: format of buffer
|
||||
* @args: arguments
|
||||
*/
|
||||
int vsscanf(const char * buf, const char * fmt, va_list args)
|
||||
{
|
||||
const char *str = buf;
|
||||
char *next;
|
||||
char digit;
|
||||
int num = 0;
|
||||
int qualifier;
|
||||
int base;
|
||||
int field_width;
|
||||
int is_sign = 0;
|
||||
|
||||
while(*fmt && *str) {
|
||||
/* skip any white space in format */
|
||||
/* white space in format matchs any amount of
|
||||
* white space, including none, in the input.
|
||||
*/
|
||||
if (isspace(*fmt)) {
|
||||
while (isspace(*fmt))
|
||||
++fmt;
|
||||
while (isspace(*str))
|
||||
++str;
|
||||
}
|
||||
|
||||
/* anything that is not a conversion must match exactly */
|
||||
if (*fmt != '%' && *fmt) {
|
||||
if (*fmt++ != *str++)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!*fmt)
|
||||
break;
|
||||
++fmt;
|
||||
|
||||
/* skip this conversion.
|
||||
* advance both strings to next white space
|
||||
*/
|
||||
if (*fmt == '*') {
|
||||
while (!isspace(*fmt) && *fmt)
|
||||
fmt++;
|
||||
while (!isspace(*str) && *str)
|
||||
str++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* get field width */
|
||||
field_width = -1;
|
||||
if (isdigit(*fmt))
|
||||
field_width = skip_atoi(&fmt);
|
||||
|
||||
/* get conversion qualifier */
|
||||
qualifier = -1;
|
||||
if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
|
||||
*fmt == 'Z' || *fmt == 'z') {
|
||||
qualifier = *fmt++;
|
||||
if (qualifier == *fmt) {
|
||||
if (qualifier == 'h') {
|
||||
qualifier = 'H';
|
||||
fmt++;
|
||||
} else if (qualifier == 'l') {
|
||||
qualifier = 'L';
|
||||
fmt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
base = 10;
|
||||
is_sign = 0;
|
||||
|
||||
if (!*fmt || !*str)
|
||||
break;
|
||||
|
||||
switch(*fmt++) {
|
||||
case 'c':
|
||||
{
|
||||
char *s = (char *) va_arg(args,char*);
|
||||
if (field_width == -1)
|
||||
field_width = 1;
|
||||
do {
|
||||
*s++ = *str++;
|
||||
} while (--field_width > 0 && *str);
|
||||
num++;
|
||||
}
|
||||
continue;
|
||||
case 's':
|
||||
{
|
||||
char *s = (char *) va_arg(args, char *);
|
||||
if(field_width == -1)
|
||||
field_width = INT_MAX;
|
||||
/* first, skip leading white space in buffer */
|
||||
while (isspace(*str))
|
||||
str++;
|
||||
|
||||
/* now copy until next white space */
|
||||
while (*str && !isspace(*str) && field_width--) {
|
||||
*s++ = *str++;
|
||||
}
|
||||
*s = '\0';
|
||||
num++;
|
||||
}
|
||||
continue;
|
||||
case 'n':
|
||||
/* return number of characters read so far */
|
||||
{
|
||||
int *i = (int *)va_arg(args,int*);
|
||||
*i = str - buf;
|
||||
}
|
||||
continue;
|
||||
case 'o':
|
||||
base = 8;
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
base = 16;
|
||||
break;
|
||||
case 'i':
|
||||
base = 0;
|
||||
case 'd':
|
||||
is_sign = 1;
|
||||
case 'u':
|
||||
break;
|
||||
case '%':
|
||||
/* looking for '%' in str */
|
||||
if (*str++ != '%')
|
||||
return num;
|
||||
continue;
|
||||
default:
|
||||
/* invalid format; stop here */
|
||||
return num;
|
||||
}
|
||||
|
||||
/* have some sort of integer conversion.
|
||||
* first, skip white space in buffer.
|
||||
*/
|
||||
while (isspace(*str))
|
||||
str++;
|
||||
|
||||
digit = *str;
|
||||
if (is_sign && digit == '-')
|
||||
digit = *(str + 1);
|
||||
|
||||
if (!digit
|
||||
|| (base == 16 && !isxdigit(digit))
|
||||
|| (base == 10 && !isdigit(digit))
|
||||
|| (base == 8 && (!isdigit(digit) || digit > '7'))
|
||||
|| (base == 0 && !isdigit(digit)))
|
||||
break;
|
||||
|
||||
switch(qualifier) {
|
||||
case 'H': /* that's 'hh' in format */
|
||||
if (is_sign) {
|
||||
signed char *s = (signed char *) va_arg(args,signed char *);
|
||||
*s = (signed char) simple_strtol(str,&next,base);
|
||||
} else {
|
||||
unsigned char *s = (unsigned char *) va_arg(args, unsigned char *);
|
||||
*s = (unsigned char) simple_strtoul(str, &next, base);
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
if (is_sign) {
|
||||
short *s = (short *) va_arg(args,short *);
|
||||
*s = (short) simple_strtol(str,&next,base);
|
||||
} else {
|
||||
unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
|
||||
*s = (unsigned short) simple_strtoul(str, &next, base);
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
if (is_sign) {
|
||||
long *l = (long *) va_arg(args,long *);
|
||||
*l = simple_strtol(str,&next,base);
|
||||
} else {
|
||||
unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
|
||||
*l = simple_strtoul(str,&next,base);
|
||||
}
|
||||
break;
|
||||
case 'L':
|
||||
if (is_sign) {
|
||||
long long *l = (long long*) va_arg(args,long long *);
|
||||
*l = simple_strtoll(str,&next,base);
|
||||
} else {
|
||||
unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
|
||||
*l = simple_strtoull(str,&next,base);
|
||||
}
|
||||
break;
|
||||
case 'Z':
|
||||
case 'z':
|
||||
{
|
||||
size_t *s = (size_t*) va_arg(args,size_t*);
|
||||
*s = (size_t) simple_strtoul(str,&next,base);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (is_sign) {
|
||||
int *i = (int *) va_arg(args, int*);
|
||||
*i = (int) simple_strtol(str,&next,base);
|
||||
} else {
|
||||
unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
|
||||
*i = (unsigned int) simple_strtoul(str,&next,base);
|
||||
}
|
||||
break;
|
||||
}
|
||||
num++;
|
||||
|
||||
if (!next)
|
||||
break;
|
||||
str = next;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sscanf - Unformat a buffer into a list of arguments
|
||||
* @buf: input buffer
|
||||
* @fmt: formatting of buffer
|
||||
* @...: resulting arguments
|
||||
*/
|
||||
int sscanf(const char * buf, const char * fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int i;
|
||||
|
||||
va_start(args,fmt);
|
||||
i = vsscanf(buf,fmt,args);
|
||||
va_end(args);
|
||||
return i;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user