1/* $Id: clear_page.S,v 1.1.1.1.2.8 2003/04/18 10:53:25 sugioka Exp $ 2 * 3 * __clear_user_page, __clear_user, clear_page implementation of SuperH 4 * 5 * Copyright (C) 2001 Kaz Kojima 6 * Copyright (C) 2001, 2002 Niibe Yutaka 7 * 8 */ 9#include <linux/config.h> 10#include <linux/linkage.h> 11 12/* 13 * clear_page 14 * @to: P1 address 15 * 16 * void clear_page(void *to) 17 */ 18 19/* 20 * r0 --- scratch 21 * r4 --- to 22 * r5 --- to + 4096 23 */ 24ENTRY(clear_page) 25 mov r4,r5 26 mov.w .Llimit,r0 27 add r0,r5 28 mov #0,r0 29 ! 301: 31#if defined(__sh3__) 32 mov.l r0,@r4 33#elif defined(__SH4__) 34 movca.l r0,@r4 35 mov r4,r1 36#endif 37 add #32,r4 38 mov.l r0,@-r4 39 mov.l r0,@-r4 40 mov.l r0,@-r4 41 mov.l r0,@-r4 42 mov.l r0,@-r4 43 mov.l r0,@-r4 44 mov.l r0,@-r4 45#if defined(__SH4__) 46 ocbwb @r1 47#endif 48 cmp/eq r5,r4 49 bf/s 1b 50 add #28,r4 51 ! 52 rts 53 nop 54.Llimit: .word (4096-28) 55 56ENTRY(__clear_user) 57 ! 58 mov #0, r0 59 mov #0xe0, r1 ! 0xffffffe0 60 ! 61 ! r4..(r4+31)&~32 -------- not aligned [ Area 0 ] 62 ! (r4+31)&~32..(r4+r5)&~32 -------- aligned [ Area 1 ] 63 ! (r4+r5)&~32..r4+r5 -------- not aligned [ Area 2 ] 64 ! 65 ! Clear area 0 66 mov r4, r2 67 ! 68 tst r1, r5 ! length < 32 69 bt .Larea2 ! skip to remainder 70 ! 71 add #31, r2 72 and r1, r2 73 cmp/eq r4, r2 74 bt .Larea1 75 mov r2, r3 76 sub r4, r3 77 mov r3, r7 78 mov r4, r2 79 ! 80.L0: dt r3 810: mov.b r0, @r2 82 bf/s .L0 83 add #1, r2 84 ! 85 sub r7, r5 86 mov r2, r4 87.Larea1: 88 mov r4, r3 89 add r5, r3 90 and r1, r3 91 cmp/hi r2, r3 92 bf .Larea2 93 ! 94 ! Clear area 1 95#if defined(__SH4__) 961: movca.l r0, @r2 97#else 981: mov.l r0, @r2 99#endif 100 add #4, r2 1012: mov.l r0, @r2 102 add #4, r2 1033: mov.l r0, @r2 104 add #4, r2 1054: mov.l r0, @r2 106 add #4, r2 1075: mov.l r0, @r2 108 add #4, r2 1096: mov.l r0, @r2 110 add #4, r2 1117: mov.l r0, @r2 112 add #4, r2 1138: mov.l r0, @r2 114 add #4, r2 115 cmp/hi r2, r3 116 bt/s 1b 117 nop 118 ! 119 ! Clear area 2 120.Larea2: 121 mov r4, r3 122 add r5, r3 123 cmp/hs r3, r2 124 bt/s .Ldone 125 sub r2, r3 126.L2: dt r3 1279: mov.b r0, @r2 128 bf/s .L2 129 add #1, r2 130 ! 131.Ldone: rts 132 mov #0, r0 ! return 0 as normal return 133 134 ! return the number of bytes remained 135.Lbad_clear_user: 136 mov r4, r0 137 add r5, r0 138 rts 139 sub r2, r0 140 141.section __ex_table,"a" 142 .align 2 143 .long 0b, .Lbad_clear_user 144 .long 1b, .Lbad_clear_user 145 .long 2b, .Lbad_clear_user 146 .long 3b, .Lbad_clear_user 147 .long 4b, .Lbad_clear_user 148 .long 5b, .Lbad_clear_user 149 .long 6b, .Lbad_clear_user 150 .long 7b, .Lbad_clear_user 151 .long 8b, .Lbad_clear_user 152 .long 9b, .Lbad_clear_user 153.previous 154 155#if defined(__SH4__) 156/* 157 * __clear_user_page 158 * @to: P1 address (with same color) 159 * @orig_to: P1 address 160 * 161 * void __clear_user_page(void *to, void *orig_to) 162 */ 163 164/* 165 * r0 --- scratch 166 * r4 --- to 167 * r5 --- orig_to 168 * r6 --- to + 4096 169 */ 170ENTRY(__clear_user_page) 171 mov.w .L4096,r0 172 mov r4,r6 173 add r0,r6 174 mov #0,r0 175 ! 1761: ocbi @r5 177 add #32,r5 178 movca.l r0,@r4 179 mov r4,r1 180 add #32,r4 181 mov.l r0,@-r4 182 mov.l r0,@-r4 183 mov.l r0,@-r4 184 mov.l r0,@-r4 185 mov.l r0,@-r4 186 mov.l r0,@-r4 187 mov.l r0,@-r4 188 add #28,r4 189 cmp/eq r6,r4 190 bf/s 1b 191 ocbwb @r1 192 ! 193 rts 194 nop 195.L4096: .word 4096 196 197/* 198 * __flush_cache_4096 199 * 200 * Flush the page at the specified physical address by writing to to 201 * the memory mapped address array. 202 * The offset into the memory mapped cache array selects the `color' of the 203 * virtual addresses which will be checked. 204 * Lower two bits of phys control the operation (invalidate/write-back). 205 * 206 * void __flush_cache_4096(unsigned long addr, unsigned long phys, 207 * unsigned long exec_offset); 208 * 209 * @addr: address of the memory mapped cache address array 210 * @phys: P1 address to be flushed 211 * @exec_offset: set to 0x20000000 if the flush needs to be executed from P2 212 * (ie from uncached memory), otherwise 0. 213 */ 214 215/* 216 * Updated for the 2-way associative cache option on the SH-4-202 and SH7751R. 217 * 218 * The current implmentation simply adds an additional loop to flush the 219 * other way, but this could be improved by merging both loops to handle the 220 * flushing of boths ways with one iteration. 221 * 222 * benedict.gaster@superh.com 223 */ 224 225/* 226 * r4 --- addr 227 * r5 --- phys 228 * r6 --- exec_offset 229 */ 230 231ENTRY(__flush_cache_4096) 232 mov.l 1f,r3 233 add r6,r3 234 mov r4,r0 235 mov #64,r2 236 shll r2 237 mov #64,r6 238 jmp @r3 239 mov #96,r7 240 .align 2 2411: .long 2f 2422: 243#if defined (CONFIG_SH_CACHE_ASSOC) 244 mov r5, r3 245#endif 246 .rept 32 247 mov.l r5,@r0 248 mov.l r5,@(32,r0) 249 mov.l r5,@(r0,r6) 250 mov.l r5,@(r0,r7) 251 add r2,r5 252 add r2,r0 253 .endr 254 255#if defined (CONFIG_SH_CACHE_ASSOC) 256 mov r4, r0 257 mov #0x40, r1 ! set bit 14 in r0 to imply 2 way. 258 shll8 r1 259 or r1, r0 260 .rept 32 261 mov.l r3,@r0 262 mov.l r3,@(32,r0) 263 mov.l r3,@(r0,r6) 264 mov.l r3,@(r0,r7) 265 add r2,r3 266 add r2,r0 267 .endr 268#endif 269 nop 270 nop 271 nop 272 nop 273 nop 274 nop 275 nop 276 rts 277 nop 278 279 280ENTRY(__flush_dcache_all) 281 mov.l 2f,r0 282 mov.l 3f,r4 283 and r0,r4 ! r4 = (unsigned long)&empty_zero_page[0] & ~0xffffc000 284 stc sr,r1 ! save SR 285 mov.l 4f,r2 286 or r1,r2 287 mov #32,r3 288 shll2 r3 289 290! TODO : make this be dynamically selected based on CPU probing rather than assembled-in 291 292#if defined (CONFIG_SH_CACHE_ASSOC) 293 mov #0x40, r5 294 shll8 r5 295 add r4, r5 ! r5 = r4 + 16k 2961: 297 ldc r2,sr ! set BL bit 298 movca.l r0,@r4 299 movca.l r0,@r5 300 ocbi @r4 301 add #32,r4 302 ocbi @r5 303 add #32,r5 304 movca.l r0,@r4 305 movca.l r0,@r5 306 ocbi @r4 307 add #32,r4 308 ocbi @r5 309 add #32,r5 310 movca.l r0,@r4 311 movca.l r0,@r5 312 ocbi @r4 313 add #32,r4 314 ocbi @r5 315 add #32,r5 316 movca.l r0,@r4 317 movca.l r0,@r5 318 ocbi @r4 319 add #32, r4 320 ocbi @r5 321 ldc r1,sr ! restore SR 322 dt r3 323 bf/s 1b 324 add #32,r5 325 326 rts 327 nop 328#else 3291: 330 ldc r2,sr ! set BL bit 331 movca.l r0,@r4 332 ocbi @r4 333 add #32,r4 334 movca.l r0,@r4 335 ocbi @r4 336 add #32,r4 337 movca.l r0,@r4 338 ocbi @r4 339 add #32,r4 340 movca.l r0,@r4 341 ocbi @r4 342 ldc r1,sr ! restore SR 343 dt r3 344 bf/s 1b 345 add #32,r4 346 347 rts 348 nop 349#endif /* CONFIG_SH_CACHE_ASSOC */ 350 351 .align 2 3522: .long 0xffffc000 353 3543: .long SYMBOL_NAME(empty_zero_page) 3554: .long 0x10000000 ! BL bit 356 357/* flush_cache_4096_all(unsigned long addr) */ 358ENTRY(flush_cache_4096_all) 359 mov.l 2f,r0 360 mov.l 3f,r2 361 and r0,r2 362 or r2,r4 ! r4 = addr | (unsigned long)&empty_zero_page[0] & ~0x3fff 363 stc sr,r1 ! save SR 364 mov.l 4f,r2 365 or r1,r2 366 mov #32,r3 367! TODO : make this be dynamically selected based on CPU probing rather than assembled-in 368 369#if defined (CONFIG_SH_CACHE_ASSOC) 370 mov #0x40, r5 371 shll8 r5 372 add r4, r5 ! r5 = r4 + 16k 3731: 374 ldc r2,sr ! set BL bit 375 movca.l r0,@r4 376 movca.l r0,@r5 377 ocbi @r4 378 add #32,r4 379 ocbi @r5 380 add #32,r5 381 movca.l r0,@r4 382 movca.l r0,@r5 383 ocbi @r4 384 add #32,r4 385 ocbi @r5 386 add #32,r5 387 movca.l r0,@r4 388 movca.l r0,@r5 389 ocbi @r4 390 add #32,r4 391 ocbi @r5 392 add #32,r5 393 movca.l r0,@r4 394 movca.l r0,@r5 395 ocbi @r4 396 add #32,r4 397 ocbi @r5 398 399 ldc r1,sr ! restore SR 400 dt r3 401 bf/s 1b 402 add #32,r5 403 404 rts 405 nop 406#else 4071: 408 ldc r2,sr ! set BL bit 409 movca.l r0,@r4 410 ocbi @r4 411 add #32,r4 412 413 movca.l r0,@r4 414 ocbi @r4 415 add #32,r4 416 movca.l r0,@r4 417 ocbi @r4 418 add #32,r4 419 movca.l r0,@r4 420 ocbi @r4 421 422 ldc r1,sr ! restore SR 423 dt r3 424 bf/s 1b 425 add #32,r4 426 427 rts 428 nop 429#endif 430 431 .align 2 4322: .long 0xffffc000 4333: .long SYMBOL_NAME(empty_zero_page) 4344: .long 0x10000000 ! BL bit 435 436#endif 437

