1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: fnd_Interlocked.cpp
4
5 Copyright (C)2009 Nintendo Co., Ltd. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Rev: 12449 $
14 *---------------------------------------------------------------------------*/
15
16 #include <nn/config.h>
17 #include <nn/fnd/ARMv6/fnd_Interlocked.h>
18
19 #include <nn/hw/ARM/code32.h>
20
21 namespace nn
22 {
23 namespace fnd
24 {
25 namespace ARMv6
26 {
27
CompareAndSwap(s32 * pTarget NN_IS_UNUSED_VAR,s32 comp NN_IS_UNUSED_VAR,s32 swap NN_IS_UNUSED_VAR)28 asm s32 Interlocked::CompareAndSwap(s32* pTarget NN_IS_UNUSED_VAR, s32 comp NN_IS_UNUSED_VAR, s32 swap NN_IS_UNUSED_VAR)
29 {
30 PRESERVE8
31
32 NN_LSYM(1)
33 ldrex r3, [r0] // *pTarget の値を r3 にロード
34 cmp r3, r1 // r3 を value と比較。
35 bne NN_FSYM(2) // 分岐、clrex が条件実行できないため
36
37 // 比較に成功した場合
38 strex r3, r2, [r0] // swap を *pTarget に書き込み
39
40 cmp r3, #0 // 書き込みが成功したか?
41 bne NN_BSYM(1) // 失敗なら最初から
42
43 mov r0, r1 // 比較に成功しているため返り値は comp
44 bx lr
45
46 // 比較に失敗した場合
47 NN_LSYM(2)
48 clrex // 排他モニタのクリア
49 mov r0, r3 // 返り値は *pTarget の値
50 bx lr
51 }
52
Swap(s32 * pTarget NN_IS_UNUSED_VAR,s32 value NN_IS_UNUSED_VAR)53 asm s32 Interlocked::Swap(s32* pTarget NN_IS_UNUSED_VAR, s32 value NN_IS_UNUSED_VAR)
54 {
55 PRESERVE8
56
57 NN_LSYM(2)
58 ldrex r2, [r0] // *pTarget の値を r2 にロード
59 strex r3, r1, [r0] // value の値を *pTarget に書き込み
60
61 cmp r3, #0 // 書き込みが成功したか?
62 bne NN_BSYM(2) // 失敗なら最初から
63
64 mov r0, r2 // 書き込みが成功した直前の *pTarget の値を返り値とする
65 bx lr
66 }
67
Increment(s32 * pTarget NN_IS_UNUSED_VAR)68 asm s32 Interlocked::Increment(s32* pTarget NN_IS_UNUSED_VAR)
69 {
70 PRESERVE8
71
72 NN_LSYM(3)
73 ldrex r2, [r0] // *pTarget の値を r2 にロード
74 add r2, r2, #1 // r2 をインクリメント
75 strex r3, r2, [r0] // r2 の値を *pTarget に書き込み
76
77 cmp r3, #0 // 書き込みが成功したか?
78 bne NN_BSYM(3) // 失敗なら最初から
79
80 mov r0, r2 // 書き込みが成功した時の *pTarget の値を返り値とする
81 bx lr
82 }
83
Decrement(s32 * pTarget NN_IS_UNUSED_VAR)84 asm s32 Interlocked::Decrement(s32* pTarget NN_IS_UNUSED_VAR)
85 {
86 PRESERVE8
87
88 NN_LSYM(4)
89 ldrex r2, [r0] // *pTarget の値を r2 にロード
90 sub r2, r2, #1 // r2 をデクリメント
91 strex r3, r2, [r0] // r2 の値を *pTarget に書き込み
92
93 cmp r3, #0 // 書き込みが成功したか?
94 bne NN_BSYM(4) // 失敗なら最初から
95
96 mov r0, r2 // 書き込みが成功した時の *pTarget の値を返り値とする
97 bx lr
98 }
99
Add(s32 * pTarget NN_IS_UNUSED_VAR,s32 value NN_IS_UNUSED_VAR)100 asm s32 Interlocked::Add(s32* pTarget NN_IS_UNUSED_VAR, s32 value NN_IS_UNUSED_VAR)
101 {
102 PRESERVE8
103
104 NN_LSYM(5)
105 ldrex r2, [r0] // *pTarget の値を r2 にロード
106 add r2, r2, r1 // r2 に value を加算
107 strex r3, r2, [r0] // r2 の値を *pTarget に書き込み
108
109 cmp r3, #0 // 書き込みが成功したか?
110 bne NN_BSYM(5) // 失敗なら最初から
111
112 mov r0, r2 // 書き込みが成功した時の *pTarget の値を返り値とする
113 bx lr
114 }
115
Substract(s32 * pTarget NN_IS_UNUSED_VAR,s32 value NN_IS_UNUSED_VAR)116 asm s32 Interlocked::Substract(s32* pTarget NN_IS_UNUSED_VAR, s32 value NN_IS_UNUSED_VAR)
117 {
118 PRESERVE8
119
120 NN_LSYM(6)
121 ldrex r2, [r0] // *pTarget の値を r2 にロード
122 sub r2, r2, r1 // r2 から value を減算
123 strex r3, r2, [r0] // r2 の値を *pTarget に書き込み
124
125 cmp r3, #0 // 書き込みが成功したか?
126 bne NN_BSYM(6) // 失敗なら最初から
127
128 mov r0, r2 // 書き込みが成功した時の *pTarget の値を返り値とする
129 bx lr
130 }
131
BitwiseOr(s32 * pTarget NN_IS_UNUSED_VAR,s32 value NN_IS_UNUSED_VAR)132 asm s32 Interlocked::BitwiseOr(s32* pTarget NN_IS_UNUSED_VAR, s32 value NN_IS_UNUSED_VAR)
133 {
134 PRESERVE8
135
136 NN_LSYM(7)
137 ldrex r2, [r0] // *pTarget の値を r2 にロード
138 orr r2, r2, r1 // r2 と value を OR
139 strex r3, r2, [r0] // r2 の値を *pTarget に書き込み
140
141 cmp r3, #0 // 書き込みが成功したか?
142 bne NN_BSYM(7) // 失敗なら最初から
143
144 mov r0, r2 // 書き込みが成功した時の *pTarget の値を返り値とする
145 bx lr
146 }
147
BitwiseAnd(s32 * pTarget NN_IS_UNUSED_VAR,s32 value NN_IS_UNUSED_VAR)148 asm s32 Interlocked::BitwiseAnd(s32* pTarget NN_IS_UNUSED_VAR, s32 value NN_IS_UNUSED_VAR)
149 {
150 PRESERVE8
151
152 NN_LSYM(8)
153 ldrex r2, [r0] // *pTarget の値を r2 にロード
154 and r2, r2, r1 // r2 と value を AND
155 strex r3, r2, [r0] // r2 の値を *pTarget に書き込み
156
157 cmp r3, #0 // 書き込みが成功したか?
158 bne NN_BSYM(8) // 失敗なら最初から
159
160 mov r0, r2 // 書き込みが成功した時の *pTarget の値を返り値とする
161 bx lr
162 }
163
BitwiseXor(s32 * pTarget NN_IS_UNUSED_VAR,s32 value NN_IS_UNUSED_VAR)164 asm s32 Interlocked::BitwiseXor(s32* pTarget NN_IS_UNUSED_VAR, s32 value NN_IS_UNUSED_VAR)
165 {
166 PRESERVE8
167
168 NN_LSYM(9)
169 ldrex r2, [r0] // *pTarget の値を r2 にロード
170 eor r2, r2, r1 // r2 と value を XOR
171 strex r3, r2, [r0] // r2 の値を *pTarget に書き込み
172
173 cmp r3, #0 // 書き込みが成功したか?
174 bne NN_BSYM(9) // 失敗なら最初から
175
176 mov r0, r2 // 書き込みが成功した時の *pTarget の値を返り値とする
177 bx lr
178 }
179
BitwiseNot(s32 * pTarget NN_IS_UNUSED_VAR)180 asm s32 Interlocked::BitwiseNot(s32* pTarget NN_IS_UNUSED_VAR)
181 {
182 PRESERVE8
183
184 NN_LSYM(10)
185 ldrex r2, [r0] // *pTarget の値を r2 にロード
186 mvn r2, r2 // r2 を NOT
187 strex r3, r2, [r0] // r2 の値を *pTarget に書き込み
188
189 cmp r3, #0 // 書き込みが成功したか?
190 bne NN_BSYM(10) // 失敗なら最初から
191
192 mov r0, r2 // 書き込みが成功した時の *pTarget の値を返り値とする
193 bx lr
194 }
195
CompareAndSwap(u64 * pTarget,const u64 & comp,u64 swap)196 u64 Interlocked::CompareAndSwap(u64* pTarget, const u64& comp, u64 swap)
197 {
198 while (true)
199 {
200 u64 x = __ldrexd(pTarget);
201 if (x == comp)
202 {
203 if (__strexd(swap, pTarget) == 0)
204 {
205 return comp;
206 }
207 }
208 else
209 {
210 __clrex();
211 return x;
212 }
213 }
214 }
215
216 }
217 }
218 }
219
220