1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 #ifndef _ASM_MIPS_UNALIGNED_EMUL_H 3 #define _ASM_MIPS_UNALIGNED_EMUL_H 4 5 #include <asm/asm.h> 6 7 #ifdef __BIG_ENDIAN 8 #define _LoadHW(addr, value, res, type) \ 9 do { \ 10 __asm__ __volatile__ (".set\tnoat\n" \ 11 "1:\t"type##_lb("%0", "0(%2)")"\n" \ 12 "2:\t"type##_lbu("$1", "1(%2)")"\n\t"\ 13 "sll\t%0, 0x8\n\t" \ 14 "or\t%0, $1\n\t" \ 15 "li\t%1, 0\n" \ 16 "3:\t.set\tat\n\t" \ 17 ".insn\n\t" \ 18 ".section\t.fixup,\"ax\"\n\t" \ 19 "4:\tli\t%1, %3\n\t" \ 20 "j\t3b\n\t" \ 21 ".previous\n\t" \ 22 ".section\t__ex_table,\"a\"\n\t" \ 23 STR(PTR)"\t1b, 4b\n\t" \ 24 STR(PTR)"\t2b, 4b\n\t" \ 25 ".previous" \ 26 : "=&r" (value), "=r" (res) \ 27 : "r" (addr), "i" (-EFAULT)); \ 28 } while (0) 29 30 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR 31 #define _LoadW(addr, value, res, type) \ 32 do { \ 33 __asm__ __volatile__ ( \ 34 "1:\t"type##_lwl("%0", "(%2)")"\n" \ 35 "2:\t"type##_lwr("%0", "3(%2)")"\n\t"\ 36 "li\t%1, 0\n" \ 37 "3:\n\t" \ 38 ".insn\n\t" \ 39 ".section\t.fixup,\"ax\"\n\t" \ 40 "4:\tli\t%1, %3\n\t" \ 41 "j\t3b\n\t" \ 42 ".previous\n\t" \ 43 ".section\t__ex_table,\"a\"\n\t" \ 44 STR(PTR)"\t1b, 4b\n\t" \ 45 STR(PTR)"\t2b, 4b\n\t" \ 46 ".previous" \ 47 : "=&r" (value), "=r" (res) \ 48 : "r" (addr), "i" (-EFAULT)); \ 49 } while (0) 50 51 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */ 52 /* For CPUs without lwl instruction */ 53 #define _LoadW(addr, value, res, type) \ 54 do { \ 55 __asm__ __volatile__ ( \ 56 ".set\tpush\n" \ 57 ".set\tnoat\n\t" \ 58 "1:"type##_lb("%0", "0(%2)")"\n\t" \ 59 "2:"type##_lbu("$1", "1(%2)")"\n\t" \ 60 "sll\t%0, 0x8\n\t" \ 61 "or\t%0, $1\n\t" \ 62 "3:"type##_lbu("$1", "2(%2)")"\n\t" \ 63 "sll\t%0, 0x8\n\t" \ 64 "or\t%0, $1\n\t" \ 65 "4:"type##_lbu("$1", "3(%2)")"\n\t" \ 66 "sll\t%0, 0x8\n\t" \ 67 "or\t%0, $1\n\t" \ 68 "li\t%1, 0\n" \ 69 ".set\tpop\n" \ 70 "10:\n\t" \ 71 ".insn\n\t" \ 72 ".section\t.fixup,\"ax\"\n\t" \ 73 "11:\tli\t%1, %3\n\t" \ 74 "j\t10b\n\t" \ 75 ".previous\n\t" \ 76 ".section\t__ex_table,\"a\"\n\t" \ 77 STR(PTR)"\t1b, 11b\n\t" \ 78 STR(PTR)"\t2b, 11b\n\t" \ 79 STR(PTR)"\t3b, 11b\n\t" \ 80 STR(PTR)"\t4b, 11b\n\t" \ 81 ".previous" \ 82 : "=&r" (value), "=r" (res) \ 83 : "r" (addr), "i" (-EFAULT)); \ 84 } while (0) 85 86 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */ 87 88 #define _LoadHWU(addr, value, res, type) \ 89 do { \ 90 __asm__ __volatile__ ( \ 91 ".set\tnoat\n" \ 92 "1:\t"type##_lbu("%0", "0(%2)")"\n" \ 93 "2:\t"type##_lbu("$1", "1(%2)")"\n\t"\ 94 "sll\t%0, 0x8\n\t" \ 95 "or\t%0, $1\n\t" \ 96 "li\t%1, 0\n" \ 97 "3:\n\t" \ 98 ".insn\n\t" \ 99 ".set\tat\n\t" \ 100 ".section\t.fixup,\"ax\"\n\t" \ 101 "4:\tli\t%1, %3\n\t" \ 102 "j\t3b\n\t" \ 103 ".previous\n\t" \ 104 ".section\t__ex_table,\"a\"\n\t" \ 105 STR(PTR)"\t1b, 4b\n\t" \ 106 STR(PTR)"\t2b, 4b\n\t" \ 107 ".previous" \ 108 : "=&r" (value), "=r" (res) \ 109 : "r" (addr), "i" (-EFAULT)); \ 110 } while (0) 111 112 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR 113 #define _LoadWU(addr, value, res, type) \ 114 do { \ 115 __asm__ __volatile__ ( \ 116 "1:\t"type##_lwl("%0", "(%2)")"\n" \ 117 "2:\t"type##_lwr("%0", "3(%2)")"\n\t"\ 118 "dsll\t%0, %0, 32\n\t" \ 119 "dsrl\t%0, %0, 32\n\t" \ 120 "li\t%1, 0\n" \ 121 "3:\n\t" \ 122 ".insn\n\t" \ 123 "\t.section\t.fixup,\"ax\"\n\t" \ 124 "4:\tli\t%1, %3\n\t" \ 125 "j\t3b\n\t" \ 126 ".previous\n\t" \ 127 ".section\t__ex_table,\"a\"\n\t" \ 128 STR(PTR)"\t1b, 4b\n\t" \ 129 STR(PTR)"\t2b, 4b\n\t" \ 130 ".previous" \ 131 : "=&r" (value), "=r" (res) \ 132 : "r" (addr), "i" (-EFAULT)); \ 133 } while (0) 134 135 #define _LoadDW(addr, value, res) \ 136 do { \ 137 __asm__ __volatile__ ( \ 138 "1:\tldl\t%0, (%2)\n" \ 139 "2:\tldr\t%0, 7(%2)\n\t" \ 140 "li\t%1, 0\n" \ 141 "3:\n\t" \ 142 ".insn\n\t" \ 143 "\t.section\t.fixup,\"ax\"\n\t" \ 144 "4:\tli\t%1, %3\n\t" \ 145 "j\t3b\n\t" \ 146 ".previous\n\t" \ 147 ".section\t__ex_table,\"a\"\n\t" \ 148 STR(PTR)"\t1b, 4b\n\t" \ 149 STR(PTR)"\t2b, 4b\n\t" \ 150 ".previous" \ 151 : "=&r" (value), "=r" (res) \ 152 : "r" (addr), "i" (-EFAULT)); \ 153 } while (0) 154 155 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */ 156 /* For CPUs without lwl and ldl instructions */ 157 #define _LoadWU(addr, value, res, type) \ 158 do { \ 159 __asm__ __volatile__ ( \ 160 ".set\tpush\n\t" \ 161 ".set\tnoat\n\t" \ 162 "1:"type##_lbu("%0", "0(%2)")"\n\t" \ 163 "2:"type##_lbu("$1", "1(%2)")"\n\t" \ 164 "sll\t%0, 0x8\n\t" \ 165 "or\t%0, $1\n\t" \ 166 "3:"type##_lbu("$1", "2(%2)")"\n\t" \ 167 "sll\t%0, 0x8\n\t" \ 168 "or\t%0, $1\n\t" \ 169 "4:"type##_lbu("$1", "3(%2)")"\n\t" \ 170 "sll\t%0, 0x8\n\t" \ 171 "or\t%0, $1\n\t" \ 172 "li\t%1, 0\n" \ 173 ".set\tpop\n" \ 174 "10:\n\t" \ 175 ".insn\n\t" \ 176 ".section\t.fixup,\"ax\"\n\t" \ 177 "11:\tli\t%1, %3\n\t" \ 178 "j\t10b\n\t" \ 179 ".previous\n\t" \ 180 ".section\t__ex_table,\"a\"\n\t" \ 181 STR(PTR)"\t1b, 11b\n\t" \ 182 STR(PTR)"\t2b, 11b\n\t" \ 183 STR(PTR)"\t3b, 11b\n\t" \ 184 STR(PTR)"\t4b, 11b\n\t" \ 185 ".previous" \ 186 : "=&r" (value), "=r" (res) \ 187 : "r" (addr), "i" (-EFAULT)); \ 188 } while (0) 189 190 #define _LoadDW(addr, value, res) \ 191 do { \ 192 __asm__ __volatile__ ( \ 193 ".set\tpush\n\t" \ 194 ".set\tnoat\n\t" \ 195 "1:lb\t%0, 0(%2)\n\t" \ 196 "2:lbu\t $1, 1(%2)\n\t" \ 197 "dsll\t%0, 0x8\n\t" \ 198 "or\t%0, $1\n\t" \ 199 "3:lbu\t$1, 2(%2)\n\t" \ 200 "dsll\t%0, 0x8\n\t" \ 201 "or\t%0, $1\n\t" \ 202 "4:lbu\t$1, 3(%2)\n\t" \ 203 "dsll\t%0, 0x8\n\t" \ 204 "or\t%0, $1\n\t" \ 205 "5:lbu\t$1, 4(%2)\n\t" \ 206 "dsll\t%0, 0x8\n\t" \ 207 "or\t%0, $1\n\t" \ 208 "6:lbu\t$1, 5(%2)\n\t" \ 209 "dsll\t%0, 0x8\n\t" \ 210 "or\t%0, $1\n\t" \ 211 "7:lbu\t$1, 6(%2)\n\t" \ 212 "dsll\t%0, 0x8\n\t" \ 213 "or\t%0, $1\n\t" \ 214 "8:lbu\t$1, 7(%2)\n\t" \ 215 "dsll\t%0, 0x8\n\t" \ 216 "or\t%0, $1\n\t" \ 217 "li\t%1, 0\n" \ 218 ".set\tpop\n\t" \ 219 "10:\n\t" \ 220 ".insn\n\t" \ 221 ".section\t.fixup,\"ax\"\n\t" \ 222 "11:\tli\t%1, %3\n\t" \ 223 "j\t10b\n\t" \ 224 ".previous\n\t" \ 225 ".section\t__ex_table,\"a\"\n\t" \ 226 STR(PTR)"\t1b, 11b\n\t" \ 227 STR(PTR)"\t2b, 11b\n\t" \ 228 STR(PTR)"\t3b, 11b\n\t" \ 229 STR(PTR)"\t4b, 11b\n\t" \ 230 STR(PTR)"\t5b, 11b\n\t" \ 231 STR(PTR)"\t6b, 11b\n\t" \ 232 STR(PTR)"\t7b, 11b\n\t" \ 233 STR(PTR)"\t8b, 11b\n\t" \ 234 ".previous" \ 235 : "=&r" (value), "=r" (res) \ 236 : "r" (addr), "i" (-EFAULT)); \ 237 } while (0) 238 239 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */ 240 241 242 #define _StoreHW(addr, value, res, type) \ 243 do { \ 244 __asm__ __volatile__ ( \ 245 ".set\tnoat\n" \ 246 "1:\t"type##_sb("%1", "1(%2)")"\n" \ 247 "srl\t$1, %1, 0x8\n" \ 248 "2:\t"type##_sb("$1", "0(%2)")"\n" \ 249 ".set\tat\n\t" \ 250 "li\t%0, 0\n" \ 251 "3:\n\t" \ 252 ".insn\n\t" \ 253 ".section\t.fixup,\"ax\"\n\t" \ 254 "4:\tli\t%0, %3\n\t" \ 255 "j\t3b\n\t" \ 256 ".previous\n\t" \ 257 ".section\t__ex_table,\"a\"\n\t" \ 258 STR(PTR)"\t1b, 4b\n\t" \ 259 STR(PTR)"\t2b, 4b\n\t" \ 260 ".previous" \ 261 : "=r" (res) \ 262 : "r" (value), "r" (addr), "i" (-EFAULT));\ 263 } while (0) 264 265 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR 266 #define _StoreW(addr, value, res, type) \ 267 do { \ 268 __asm__ __volatile__ ( \ 269 "1:\t"type##_swl("%1", "(%2)")"\n" \ 270 "2:\t"type##_swr("%1", "3(%2)")"\n\t"\ 271 "li\t%0, 0\n" \ 272 "3:\n\t" \ 273 ".insn\n\t" \ 274 ".section\t.fixup,\"ax\"\n\t" \ 275 "4:\tli\t%0, %3\n\t" \ 276 "j\t3b\n\t" \ 277 ".previous\n\t" \ 278 ".section\t__ex_table,\"a\"\n\t" \ 279 STR(PTR)"\t1b, 4b\n\t" \ 280 STR(PTR)"\t2b, 4b\n\t" \ 281 ".previous" \ 282 : "=r" (res) \ 283 : "r" (value), "r" (addr), "i" (-EFAULT)); \ 284 } while (0) 285 286 #define _StoreDW(addr, value, res) \ 287 do { \ 288 __asm__ __volatile__ ( \ 289 "1:\tsdl\t%1,(%2)\n" \ 290 "2:\tsdr\t%1, 7(%2)\n\t" \ 291 "li\t%0, 0\n" \ 292 "3:\n\t" \ 293 ".insn\n\t" \ 294 ".section\t.fixup,\"ax\"\n\t" \ 295 "4:\tli\t%0, %3\n\t" \ 296 "j\t3b\n\t" \ 297 ".previous\n\t" \ 298 ".section\t__ex_table,\"a\"\n\t" \ 299 STR(PTR)"\t1b, 4b\n\t" \ 300 STR(PTR)"\t2b, 4b\n\t" \ 301 ".previous" \ 302 : "=r" (res) \ 303 : "r" (value), "r" (addr), "i" (-EFAULT)); \ 304 } while (0) 305 306 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */ 307 #define _StoreW(addr, value, res, type) \ 308 do { \ 309 __asm__ __volatile__ ( \ 310 ".set\tpush\n\t" \ 311 ".set\tnoat\n\t" \ 312 "1:"type##_sb("%1", "3(%2)")"\n\t" \ 313 "srl\t$1, %1, 0x8\n\t" \ 314 "2:"type##_sb("$1", "2(%2)")"\n\t" \ 315 "srl\t$1, $1, 0x8\n\t" \ 316 "3:"type##_sb("$1", "1(%2)")"\n\t" \ 317 "srl\t$1, $1, 0x8\n\t" \ 318 "4:"type##_sb("$1", "0(%2)")"\n\t" \ 319 ".set\tpop\n\t" \ 320 "li\t%0, 0\n" \ 321 "10:\n\t" \ 322 ".insn\n\t" \ 323 ".section\t.fixup,\"ax\"\n\t" \ 324 "11:\tli\t%0, %3\n\t" \ 325 "j\t10b\n\t" \ 326 ".previous\n\t" \ 327 ".section\t__ex_table,\"a\"\n\t" \ 328 STR(PTR)"\t1b, 11b\n\t" \ 329 STR(PTR)"\t2b, 11b\n\t" \ 330 STR(PTR)"\t3b, 11b\n\t" \ 331 STR(PTR)"\t4b, 11b\n\t" \ 332 ".previous" \ 333 : "=&r" (res) \ 334 : "r" (value), "r" (addr), "i" (-EFAULT) \ 335 : "memory"); \ 336 } while (0) 337 338 #define _StoreDW(addr, value, res) \ 339 do { \ 340 __asm__ __volatile__ ( \ 341 ".set\tpush\n\t" \ 342 ".set\tnoat\n\t" \ 343 "1:sb\t%1, 7(%2)\n\t" \ 344 "dsrl\t$1, %1, 0x8\n\t" \ 345 "2:sb\t$1, 6(%2)\n\t" \ 346 "dsrl\t$1, $1, 0x8\n\t" \ 347 "3:sb\t$1, 5(%2)\n\t" \ 348 "dsrl\t$1, $1, 0x8\n\t" \ 349 "4:sb\t$1, 4(%2)\n\t" \ 350 "dsrl\t$1, $1, 0x8\n\t" \ 351 "5:sb\t$1, 3(%2)\n\t" \ 352 "dsrl\t$1, $1, 0x8\n\t" \ 353 "6:sb\t$1, 2(%2)\n\t" \ 354 "dsrl\t$1, $1, 0x8\n\t" \ 355 "7:sb\t$1, 1(%2)\n\t" \ 356 "dsrl\t$1, $1, 0x8\n\t" \ 357 "8:sb\t$1, 0(%2)\n\t" \ 358 "dsrl\t$1, $1, 0x8\n\t" \ 359 ".set\tpop\n\t" \ 360 "li\t%0, 0\n" \ 361 "10:\n\t" \ 362 ".insn\n\t" \ 363 ".section\t.fixup,\"ax\"\n\t" \ 364 "11:\tli\t%0, %3\n\t" \ 365 "j\t10b\n\t" \ 366 ".previous\n\t" \ 367 ".section\t__ex_table,\"a\"\n\t" \ 368 STR(PTR)"\t1b, 11b\n\t" \ 369 STR(PTR)"\t2b, 11b\n\t" \ 370 STR(PTR)"\t3b, 11b\n\t" \ 371 STR(PTR)"\t4b, 11b\n\t" \ 372 STR(PTR)"\t5b, 11b\n\t" \ 373 STR(PTR)"\t6b, 11b\n\t" \ 374 STR(PTR)"\t7b, 11b\n\t" \ 375 STR(PTR)"\t8b, 11b\n\t" \ 376 ".previous" \ 377 : "=&r" (res) \ 378 : "r" (value), "r" (addr), "i" (-EFAULT) \ 379 : "memory"); \ 380 } while (0) 381 382 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */ 383 384 #else /* __BIG_ENDIAN */ 385 386 #define _LoadHW(addr, value, res, type) \ 387 do { \ 388 __asm__ __volatile__ (".set\tnoat\n" \ 389 "1:\t"type##_lb("%0", "1(%2)")"\n" \ 390 "2:\t"type##_lbu("$1", "0(%2)")"\n\t"\ 391 "sll\t%0, 0x8\n\t" \ 392 "or\t%0, $1\n\t" \ 393 "li\t%1, 0\n" \ 394 "3:\t.set\tat\n\t" \ 395 ".insn\n\t" \ 396 ".section\t.fixup,\"ax\"\n\t" \ 397 "4:\tli\t%1, %3\n\t" \ 398 "j\t3b\n\t" \ 399 ".previous\n\t" \ 400 ".section\t__ex_table,\"a\"\n\t" \ 401 STR(PTR)"\t1b, 4b\n\t" \ 402 STR(PTR)"\t2b, 4b\n\t" \ 403 ".previous" \ 404 : "=&r" (value), "=r" (res) \ 405 : "r" (addr), "i" (-EFAULT)); \ 406 } while (0) 407 408 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR 409 #define _LoadW(addr, value, res, type) \ 410 do { \ 411 __asm__ __volatile__ ( \ 412 "1:\t"type##_lwl("%0", "3(%2)")"\n" \ 413 "2:\t"type##_lwr("%0", "(%2)")"\n\t"\ 414 "li\t%1, 0\n" \ 415 "3:\n\t" \ 416 ".insn\n\t" \ 417 ".section\t.fixup,\"ax\"\n\t" \ 418 "4:\tli\t%1, %3\n\t" \ 419 "j\t3b\n\t" \ 420 ".previous\n\t" \ 421 ".section\t__ex_table,\"a\"\n\t" \ 422 STR(PTR)"\t1b, 4b\n\t" \ 423 STR(PTR)"\t2b, 4b\n\t" \ 424 ".previous" \ 425 : "=&r" (value), "=r" (res) \ 426 : "r" (addr), "i" (-EFAULT)); \ 427 } while (0) 428 429 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */ 430 /* For CPUs without lwl instruction */ 431 #define _LoadW(addr, value, res, type) \ 432 do { \ 433 __asm__ __volatile__ ( \ 434 ".set\tpush\n" \ 435 ".set\tnoat\n\t" \ 436 "1:"type##_lb("%0", "3(%2)")"\n\t" \ 437 "2:"type##_lbu("$1", "2(%2)")"\n\t" \ 438 "sll\t%0, 0x8\n\t" \ 439 "or\t%0, $1\n\t" \ 440 "3:"type##_lbu("$1", "1(%2)")"\n\t" \ 441 "sll\t%0, 0x8\n\t" \ 442 "or\t%0, $1\n\t" \ 443 "4:"type##_lbu("$1", "0(%2)")"\n\t" \ 444 "sll\t%0, 0x8\n\t" \ 445 "or\t%0, $1\n\t" \ 446 "li\t%1, 0\n" \ 447 ".set\tpop\n" \ 448 "10:\n\t" \ 449 ".insn\n\t" \ 450 ".section\t.fixup,\"ax\"\n\t" \ 451 "11:\tli\t%1, %3\n\t" \ 452 "j\t10b\n\t" \ 453 ".previous\n\t" \ 454 ".section\t__ex_table,\"a\"\n\t" \ 455 STR(PTR)"\t1b, 11b\n\t" \ 456 STR(PTR)"\t2b, 11b\n\t" \ 457 STR(PTR)"\t3b, 11b\n\t" \ 458 STR(PTR)"\t4b, 11b\n\t" \ 459 ".previous" \ 460 : "=&r" (value), "=r" (res) \ 461 : "r" (addr), "i" (-EFAULT)); \ 462 } while (0) 463 464 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */ 465 466 467 #define _LoadHWU(addr, value, res, type) \ 468 do { \ 469 __asm__ __volatile__ ( \ 470 ".set\tnoat\n" \ 471 "1:\t"type##_lbu("%0", "1(%2)")"\n" \ 472 "2:\t"type##_lbu("$1", "0(%2)")"\n\t"\ 473 "sll\t%0, 0x8\n\t" \ 474 "or\t%0, $1\n\t" \ 475 "li\t%1, 0\n" \ 476 "3:\n\t" \ 477 ".insn\n\t" \ 478 ".set\tat\n\t" \ 479 ".section\t.fixup,\"ax\"\n\t" \ 480 "4:\tli\t%1, %3\n\t" \ 481 "j\t3b\n\t" \ 482 ".previous\n\t" \ 483 ".section\t__ex_table,\"a\"\n\t" \ 484 STR(PTR)"\t1b, 4b\n\t" \ 485 STR(PTR)"\t2b, 4b\n\t" \ 486 ".previous" \ 487 : "=&r" (value), "=r" (res) \ 488 : "r" (addr), "i" (-EFAULT)); \ 489 } while (0) 490 491 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR 492 #define _LoadWU(addr, value, res, type) \ 493 do { \ 494 __asm__ __volatile__ ( \ 495 "1:\t"type##_lwl("%0", "3(%2)")"\n" \ 496 "2:\t"type##_lwr("%0", "(%2)")"\n\t"\ 497 "dsll\t%0, %0, 32\n\t" \ 498 "dsrl\t%0, %0, 32\n\t" \ 499 "li\t%1, 0\n" \ 500 "3:\n\t" \ 501 ".insn\n\t" \ 502 "\t.section\t.fixup,\"ax\"\n\t" \ 503 "4:\tli\t%1, %3\n\t" \ 504 "j\t3b\n\t" \ 505 ".previous\n\t" \ 506 ".section\t__ex_table,\"a\"\n\t" \ 507 STR(PTR)"\t1b, 4b\n\t" \ 508 STR(PTR)"\t2b, 4b\n\t" \ 509 ".previous" \ 510 : "=&r" (value), "=r" (res) \ 511 : "r" (addr), "i" (-EFAULT)); \ 512 } while (0) 513 514 #define _LoadDW(addr, value, res) \ 515 do { \ 516 __asm__ __volatile__ ( \ 517 "1:\tldl\t%0, 7(%2)\n" \ 518 "2:\tldr\t%0, (%2)\n\t" \ 519 "li\t%1, 0\n" \ 520 "3:\n\t" \ 521 ".insn\n\t" \ 522 "\t.section\t.fixup,\"ax\"\n\t" \ 523 "4:\tli\t%1, %3\n\t" \ 524 "j\t3b\n\t" \ 525 ".previous\n\t" \ 526 ".section\t__ex_table,\"a\"\n\t" \ 527 STR(PTR)"\t1b, 4b\n\t" \ 528 STR(PTR)"\t2b, 4b\n\t" \ 529 ".previous" \ 530 : "=&r" (value), "=r" (res) \ 531 : "r" (addr), "i" (-EFAULT)); \ 532 } while (0) 533 534 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */ 535 /* For CPUs without lwl and ldl instructions */ 536 #define _LoadWU(addr, value, res, type) \ 537 do { \ 538 __asm__ __volatile__ ( \ 539 ".set\tpush\n\t" \ 540 ".set\tnoat\n\t" \ 541 "1:"type##_lbu("%0", "3(%2)")"\n\t" \ 542 "2:"type##_lbu("$1", "2(%2)")"\n\t" \ 543 "sll\t%0, 0x8\n\t" \ 544 "or\t%0, $1\n\t" \ 545 "3:"type##_lbu("$1", "1(%2)")"\n\t" \ 546 "sll\t%0, 0x8\n\t" \ 547 "or\t%0, $1\n\t" \ 548 "4:"type##_lbu("$1", "0(%2)")"\n\t" \ 549 "sll\t%0, 0x8\n\t" \ 550 "or\t%0, $1\n\t" \ 551 "li\t%1, 0\n" \ 552 ".set\tpop\n" \ 553 "10:\n\t" \ 554 ".insn\n\t" \ 555 ".section\t.fixup,\"ax\"\n\t" \ 556 "11:\tli\t%1, %3\n\t" \ 557 "j\t10b\n\t" \ 558 ".previous\n\t" \ 559 ".section\t__ex_table,\"a\"\n\t" \ 560 STR(PTR)"\t1b, 11b\n\t" \ 561 STR(PTR)"\t2b, 11b\n\t" \ 562 STR(PTR)"\t3b, 11b\n\t" \ 563 STR(PTR)"\t4b, 11b\n\t" \ 564 ".previous" \ 565 : "=&r" (value), "=r" (res) \ 566 : "r" (addr), "i" (-EFAULT)); \ 567 } while (0) 568 569 #define _LoadDW(addr, value, res) \ 570 do { \ 571 __asm__ __volatile__ ( \ 572 ".set\tpush\n\t" \ 573 ".set\tnoat\n\t" \ 574 "1:lb\t%0, 7(%2)\n\t" \ 575 "2:lbu\t$1, 6(%2)\n\t" \ 576 "dsll\t%0, 0x8\n\t" \ 577 "or\t%0, $1\n\t" \ 578 "3:lbu\t$1, 5(%2)\n\t" \ 579 "dsll\t%0, 0x8\n\t" \ 580 "or\t%0, $1\n\t" \ 581 "4:lbu\t$1, 4(%2)\n\t" \ 582 "dsll\t%0, 0x8\n\t" \ 583 "or\t%0, $1\n\t" \ 584 "5:lbu\t$1, 3(%2)\n\t" \ 585 "dsll\t%0, 0x8\n\t" \ 586 "or\t%0, $1\n\t" \ 587 "6:lbu\t$1, 2(%2)\n\t" \ 588 "dsll\t%0, 0x8\n\t" \ 589 "or\t%0, $1\n\t" \ 590 "7:lbu\t$1, 1(%2)\n\t" \ 591 "dsll\t%0, 0x8\n\t" \ 592 "or\t%0, $1\n\t" \ 593 "8:lbu\t$1, 0(%2)\n\t" \ 594 "dsll\t%0, 0x8\n\t" \ 595 "or\t%0, $1\n\t" \ 596 "li\t%1, 0\n" \ 597 ".set\tpop\n\t" \ 598 "10:\n\t" \ 599 ".insn\n\t" \ 600 ".section\t.fixup,\"ax\"\n\t" \ 601 "11:\tli\t%1, %3\n\t" \ 602 "j\t10b\n\t" \ 603 ".previous\n\t" \ 604 ".section\t__ex_table,\"a\"\n\t" \ 605 STR(PTR)"\t1b, 11b\n\t" \ 606 STR(PTR)"\t2b, 11b\n\t" \ 607 STR(PTR)"\t3b, 11b\n\t" \ 608 STR(PTR)"\t4b, 11b\n\t" \ 609 STR(PTR)"\t5b, 11b\n\t" \ 610 STR(PTR)"\t6b, 11b\n\t" \ 611 STR(PTR)"\t7b, 11b\n\t" \ 612 STR(PTR)"\t8b, 11b\n\t" \ 613 ".previous" \ 614 : "=&r" (value), "=r" (res) \ 615 : "r" (addr), "i" (-EFAULT)); \ 616 } while (0) 617 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */ 618 619 #define _StoreHW(addr, value, res, type) \ 620 do { \ 621 __asm__ __volatile__ ( \ 622 ".set\tnoat\n" \ 623 "1:\t"type##_sb("%1", "0(%2)")"\n" \ 624 "srl\t$1,%1, 0x8\n" \ 625 "2:\t"type##_sb("$1", "1(%2)")"\n" \ 626 ".set\tat\n\t" \ 627 "li\t%0, 0\n" \ 628 "3:\n\t" \ 629 ".insn\n\t" \ 630 ".section\t.fixup,\"ax\"\n\t" \ 631 "4:\tli\t%0, %3\n\t" \ 632 "j\t3b\n\t" \ 633 ".previous\n\t" \ 634 ".section\t__ex_table,\"a\"\n\t" \ 635 STR(PTR)"\t1b, 4b\n\t" \ 636 STR(PTR)"\t2b, 4b\n\t" \ 637 ".previous" \ 638 : "=r" (res) \ 639 : "r" (value), "r" (addr), "i" (-EFAULT));\ 640 } while (0) 641 642 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR 643 #define _StoreW(addr, value, res, type) \ 644 do { \ 645 __asm__ __volatile__ ( \ 646 "1:\t"type##_swl("%1", "3(%2)")"\n" \ 647 "2:\t"type##_swr("%1", "(%2)")"\n\t"\ 648 "li\t%0, 0\n" \ 649 "3:\n\t" \ 650 ".insn\n\t" \ 651 ".section\t.fixup,\"ax\"\n\t" \ 652 "4:\tli\t%0, %3\n\t" \ 653 "j\t3b\n\t" \ 654 ".previous\n\t" \ 655 ".section\t__ex_table,\"a\"\n\t" \ 656 STR(PTR)"\t1b, 4b\n\t" \ 657 STR(PTR)"\t2b, 4b\n\t" \ 658 ".previous" \ 659 : "=r" (res) \ 660 : "r" (value), "r" (addr), "i" (-EFAULT)); \ 661 } while (0) 662 663 #define _StoreDW(addr, value, res) \ 664 do { \ 665 __asm__ __volatile__ ( \ 666 "1:\tsdl\t%1, 7(%2)\n" \ 667 "2:\tsdr\t%1, (%2)\n\t" \ 668 "li\t%0, 0\n" \ 669 "3:\n\t" \ 670 ".insn\n\t" \ 671 ".section\t.fixup,\"ax\"\n\t" \ 672 "4:\tli\t%0, %3\n\t" \ 673 "j\t3b\n\t" \ 674 ".previous\n\t" \ 675 ".section\t__ex_table,\"a\"\n\t" \ 676 STR(PTR)"\t1b, 4b\n\t" \ 677 STR(PTR)"\t2b, 4b\n\t" \ 678 ".previous" \ 679 : "=r" (res) \ 680 : "r" (value), "r" (addr), "i" (-EFAULT)); \ 681 } while (0) 682 683 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */ 684 /* For CPUs without swl and sdl instructions */ 685 #define _StoreW(addr, value, res, type) \ 686 do { \ 687 __asm__ __volatile__ ( \ 688 ".set\tpush\n\t" \ 689 ".set\tnoat\n\t" \ 690 "1:"type##_sb("%1", "0(%2)")"\n\t" \ 691 "srl\t$1, %1, 0x8\n\t" \ 692 "2:"type##_sb("$1", "1(%2)")"\n\t" \ 693 "srl\t$1, $1, 0x8\n\t" \ 694 "3:"type##_sb("$1", "2(%2)")"\n\t" \ 695 "srl\t$1, $1, 0x8\n\t" \ 696 "4:"type##_sb("$1", "3(%2)")"\n\t" \ 697 ".set\tpop\n\t" \ 698 "li\t%0, 0\n" \ 699 "10:\n\t" \ 700 ".insn\n\t" \ 701 ".section\t.fixup,\"ax\"\n\t" \ 702 "11:\tli\t%0, %3\n\t" \ 703 "j\t10b\n\t" \ 704 ".previous\n\t" \ 705 ".section\t__ex_table,\"a\"\n\t" \ 706 STR(PTR)"\t1b, 11b\n\t" \ 707 STR(PTR)"\t2b, 11b\n\t" \ 708 STR(PTR)"\t3b, 11b\n\t" \ 709 STR(PTR)"\t4b, 11b\n\t" \ 710 ".previous" \ 711 : "=&r" (res) \ 712 : "r" (value), "r" (addr), "i" (-EFAULT) \ 713 : "memory"); \ 714 } while (0) 715 716 #define _StoreDW(addr, value, res) \ 717 do { \ 718 __asm__ __volatile__ ( \ 719 ".set\tpush\n\t" \ 720 ".set\tnoat\n\t" \ 721 "1:sb\t%1, 0(%2)\n\t" \ 722 "dsrl\t$1, %1, 0x8\n\t" \ 723 "2:sb\t$1, 1(%2)\n\t" \ 724 "dsrl\t$1, $1, 0x8\n\t" \ 725 "3:sb\t$1, 2(%2)\n\t" \ 726 "dsrl\t$1, $1, 0x8\n\t" \ 727 "4:sb\t$1, 3(%2)\n\t" \ 728 "dsrl\t$1, $1, 0x8\n\t" \ 729 "5:sb\t$1, 4(%2)\n\t" \ 730 "dsrl\t$1, $1, 0x8\n\t" \ 731 "6:sb\t$1, 5(%2)\n\t" \ 732 "dsrl\t$1, $1, 0x8\n\t" \ 733 "7:sb\t$1, 6(%2)\n\t" \ 734 "dsrl\t$1, $1, 0x8\n\t" \ 735 "8:sb\t$1, 7(%2)\n\t" \ 736 "dsrl\t$1, $1, 0x8\n\t" \ 737 ".set\tpop\n\t" \ 738 "li\t%0, 0\n" \ 739 "10:\n\t" \ 740 ".insn\n\t" \ 741 ".section\t.fixup,\"ax\"\n\t" \ 742 "11:\tli\t%0, %3\n\t" \ 743 "j\t10b\n\t" \ 744 ".previous\n\t" \ 745 ".section\t__ex_table,\"a\"\n\t" \ 746 STR(PTR)"\t1b, 11b\n\t" \ 747 STR(PTR)"\t2b, 11b\n\t" \ 748 STR(PTR)"\t3b, 11b\n\t" \ 749 STR(PTR)"\t4b, 11b\n\t" \ 750 STR(PTR)"\t5b, 11b\n\t" \ 751 STR(PTR)"\t6b, 11b\n\t" \ 752 STR(PTR)"\t7b, 11b\n\t" \ 753 STR(PTR)"\t8b, 11b\n\t" \ 754 ".previous" \ 755 : "=&r" (res) \ 756 : "r" (value), "r" (addr), "i" (-EFAULT) \ 757 : "memory"); \ 758 } while (0) 759 760 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */ 761 #endif 762 763 #define LoadHWU(addr, value, res) _LoadHWU(addr, value, res, kernel) 764 #define LoadHWUE(addr, value, res) _LoadHWU(addr, value, res, user) 765 #define LoadWU(addr, value, res) _LoadWU(addr, value, res, kernel) 766 #define LoadWUE(addr, value, res) _LoadWU(addr, value, res, user) 767 #define LoadHW(addr, value, res) _LoadHW(addr, value, res, kernel) 768 #define LoadHWE(addr, value, res) _LoadHW(addr, value, res, user) 769 #define LoadW(addr, value, res) _LoadW(addr, value, res, kernel) 770 #define LoadWE(addr, value, res) _LoadW(addr, value, res, user) 771 #define LoadDW(addr, value, res) _LoadDW(addr, value, res) 772 773 #define StoreHW(addr, value, res) _StoreHW(addr, value, res, kernel) 774 #define StoreHWE(addr, value, res) _StoreHW(addr, value, res, user) 775 #define StoreW(addr, value, res) _StoreW(addr, value, res, kernel) 776 #define StoreWE(addr, value, res) _StoreW(addr, value, res, user) 777 #define StoreDW(addr, value, res) _StoreDW(addr, value, res) 778 779 #endif /* _ASM_MIPS_UNALIGNED_EMUL_H */ 780