1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2012 by Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
.syntax unified
.data
was_aborted:
.word 0
.section .text.safe_read8
.type safe_read8, %function
.global safe_read8
@ bool safe_read8(uint8_t *addr, uint8_t *value)
safe_read8:
@ was_aborted = 0
ldr r2, =was_aborted
mov r3, #0
str r3, [r2]
@ r0=*addr
safe_read8_faulty_addr:
ldrb r0, [r0]
@ if(was_aborted)
ldr r2, [r2]
cmp r2, #1
@ return false;
moveq r0, #0
bxeq lr
@ if(value != NULL)
cmp r1, #0
@ *value = r0
strbne r0, [r1]
@ return true;
mov r0, #1
bx lr
.size safe_read8, . - safe_read8
.section .text.safe_read16
.type safe_read16, %function
.global safe_read16
@ bool safe_read16(uint16_t *addr, uint16_t *value)
safe_read16:
@ was_aborted = 0
ldr r2, =was_aborted
mov r3, #0
str r3, [r2]
@ r0=*addr
safe_read16_faulty_addr:
ldrh r0, [r0]
@ if(was_aborted)
ldr r2, [r2]
cmp r2, #1
@ return false;
moveq r0, #0
bxeq lr
@ if(value != NULL)
cmp r1, #0
@ *value = r0
strhne r0, [r1]
@ return true;
mov r0, #1
bx lr
.size safe_read16, . - safe_read16
.section .text.safe_read32
.type safe_read32, %function
.global safe_read32
@ bool safe_read32(uint32_t *addr, uint32_t *value)
safe_read32:
@ was_aborted = 0
ldr r2, =was_aborted
mov r3, #0
str r3, [r2]
@ r0=*addr
safe_read32_faulty_addr:
ldr r0, [r0]
@ if(was_aborted)
ldr r2, [r2]
cmp r2, #1
@ return false;
moveq r0, #0
bxeq lr
@ if(value != NULL)
cmp r1, #0
@ *value = r0
strne r0, [r1]
@ return true;
mov r0, #1
bx lr
.size safe_read32, . - safe_read32
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
.section .text.data_abort_handler
.type data_abort_handler, %function
.global data_abort_handler
data_abort_handler:
@ store minimal amount of registers
stmfd sp!, {r0-r1}
@ compute faulty address
sub r0, lr, #8
@ compare to safe_read8
ldr r1, =safe_read8_faulty_addr
cmp r0, r1
beq 1f
@ compare to safe_read16
ldr r1, =safe_read16_faulty_addr
cmp r0, r1
beq 1f
@ compare to safe_read32
ldr r1, =safe_read32_faulty_addr
cmp r0, r1
beq 1f
@ otherwise just normally to UIE
mov r1, #2
b UIE
1:
@ set was_aborted
ldr r1, =was_aborted
mov r0, #1
str r0, [r1]
@ restore registers
ldmfd sp!, {r0-r1}
@ restore mode and jump back to the *next* instruction
subs pc, lr, #4
.size data_abort_handler, . - data_abort_handler
#endif
|