linux/arch/mips/include/asm/unaligned-emul.h
<<
>>
Prefs
   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)  \
   9do {                                                \
  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)   \
  32do {                                                \
  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) \
  54do {                                                \
  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) \
  89do {                                                \
  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)  \
 114do {                                                \
 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)  \
 136do {                                                \
 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) \
 158do {                                                \
 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)  \
 191do {                                                \
 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) \
 243do {                                                \
 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)  \
 267do {                                                \
 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) \
 287do {                                                \
 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)  \
 308do {                                                \
 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) \
 339do {                                                \
 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)  \
 387do {                                                \
 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)   \
 410do {                                                \
 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) \
 432do {                                                \
 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) \
 468do {                                                \
 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)  \
 493do {                                                \
 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)  \
 515do {                                                \
 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) \
 537do {                                                \
 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)  \
 570do {                                                \
 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) \
 620do {                                                 \
 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)  \
 644do {                                                \
 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) \
 664do {                                                \
 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)  \
 686do {                                                \
 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) \
 717do {                                                \
 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