Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 #ifndef _ASM_MIPS_UNALIGNED_EMUL_H
0003 #define _ASM_MIPS_UNALIGNED_EMUL_H
0004 
0005 #include <asm/asm.h>
0006 
0007 #ifdef __BIG_ENDIAN
0008 #define  _LoadHW(addr, value, res, type)  \
0009 do {                                                \
0010     __asm__ __volatile__ (".set\tnoat\n"        \
0011         "1:\t"type##_lb("%0", "0(%2)")"\n"  \
0012         "2:\t"type##_lbu("$1", "1(%2)")"\n\t"\
0013         "sll\t%0, 0x8\n\t"                  \
0014         "or\t%0, $1\n\t"                    \
0015         "li\t%1, 0\n"                       \
0016         "3:\t.set\tat\n\t"                  \
0017         ".insn\n\t"                         \
0018         ".section\t.fixup,\"ax\"\n\t"       \
0019         "4:\tli\t%1, %3\n\t"                \
0020         "j\t3b\n\t"                         \
0021         ".previous\n\t"                     \
0022         ".section\t__ex_table,\"a\"\n\t"    \
0023         STR(PTR_WD)"\t1b, 4b\n\t"           \
0024         STR(PTR_WD)"\t2b, 4b\n\t"           \
0025         ".previous"                         \
0026         : "=&r" (value), "=r" (res)         \
0027         : "r" (addr), "i" (-EFAULT));       \
0028 } while (0)
0029 
0030 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR
0031 #define  _LoadW(addr, value, res, type)   \
0032 do {                                                \
0033     __asm__ __volatile__ (                      \
0034         "1:\t"type##_lwl("%0", "(%2)")"\n"   \
0035         "2:\t"type##_lwr("%0", "3(%2)")"\n\t"\
0036         "li\t%1, 0\n"                       \
0037         "3:\n\t"                            \
0038         ".insn\n\t"                         \
0039         ".section\t.fixup,\"ax\"\n\t"       \
0040         "4:\tli\t%1, %3\n\t"                \
0041         "j\t3b\n\t"                         \
0042         ".previous\n\t"                     \
0043         ".section\t__ex_table,\"a\"\n\t"    \
0044         STR(PTR_WD)"\t1b, 4b\n\t"           \
0045         STR(PTR_WD)"\t2b, 4b\n\t"           \
0046         ".previous"                         \
0047         : "=&r" (value), "=r" (res)         \
0048         : "r" (addr), "i" (-EFAULT));       \
0049 } while (0)
0050 
0051 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
0052 /* For CPUs without lwl instruction */
0053 #define  _LoadW(addr, value, res, type) \
0054 do {                                                \
0055     __asm__ __volatile__ (              \
0056         ".set\tpush\n"              \
0057         ".set\tnoat\n\t"            \
0058         "1:"type##_lb("%0", "0(%2)")"\n\t"  \
0059         "2:"type##_lbu("$1", "1(%2)")"\n\t" \
0060         "sll\t%0, 0x8\n\t"          \
0061         "or\t%0, $1\n\t"            \
0062         "3:"type##_lbu("$1", "2(%2)")"\n\t" \
0063         "sll\t%0, 0x8\n\t"          \
0064         "or\t%0, $1\n\t"            \
0065         "4:"type##_lbu("$1", "3(%2)")"\n\t" \
0066         "sll\t%0, 0x8\n\t"          \
0067         "or\t%0, $1\n\t"            \
0068         "li\t%1, 0\n"               \
0069         ".set\tpop\n"               \
0070         "10:\n\t"               \
0071         ".insn\n\t"             \
0072         ".section\t.fixup,\"ax\"\n\t"       \
0073         "11:\tli\t%1, %3\n\t"           \
0074         "j\t10b\n\t"                \
0075         ".previous\n\t"             \
0076         ".section\t__ex_table,\"a\"\n\t"    \
0077         STR(PTR_WD)"\t1b, 11b\n\t"      \
0078         STR(PTR_WD)"\t2b, 11b\n\t"      \
0079         STR(PTR_WD)"\t3b, 11b\n\t"      \
0080         STR(PTR_WD)"\t4b, 11b\n\t"      \
0081         ".previous"             \
0082         : "=&r" (value), "=r" (res)     \
0083         : "r" (addr), "i" (-EFAULT));       \
0084 } while (0)
0085 
0086 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
0087 
0088 #define  _LoadHWU(addr, value, res, type) \
0089 do {                                                \
0090     __asm__ __volatile__ (                      \
0091         ".set\tnoat\n"                      \
0092         "1:\t"type##_lbu("%0", "0(%2)")"\n" \
0093         "2:\t"type##_lbu("$1", "1(%2)")"\n\t"\
0094         "sll\t%0, 0x8\n\t"                  \
0095         "or\t%0, $1\n\t"                    \
0096         "li\t%1, 0\n"                       \
0097         "3:\n\t"                            \
0098         ".insn\n\t"                         \
0099         ".set\tat\n\t"                      \
0100         ".section\t.fixup,\"ax\"\n\t"       \
0101         "4:\tli\t%1, %3\n\t"                \
0102         "j\t3b\n\t"                         \
0103         ".previous\n\t"                     \
0104         ".section\t__ex_table,\"a\"\n\t"    \
0105         STR(PTR_WD)"\t1b, 4b\n\t"           \
0106         STR(PTR_WD)"\t2b, 4b\n\t"           \
0107         ".previous"                         \
0108         : "=&r" (value), "=r" (res)         \
0109         : "r" (addr), "i" (-EFAULT));       \
0110 } while (0)
0111 
0112 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR
0113 #define  _LoadWU(addr, value, res, type)  \
0114 do {                                                \
0115     __asm__ __volatile__ (                      \
0116         "1:\t"type##_lwl("%0", "(%2)")"\n"  \
0117         "2:\t"type##_lwr("%0", "3(%2)")"\n\t"\
0118         "dsll\t%0, %0, 32\n\t"              \
0119         "dsrl\t%0, %0, 32\n\t"              \
0120         "li\t%1, 0\n"                       \
0121         "3:\n\t"                            \
0122         ".insn\n\t"                         \
0123         "\t.section\t.fixup,\"ax\"\n\t"     \
0124         "4:\tli\t%1, %3\n\t"                \
0125         "j\t3b\n\t"                         \
0126         ".previous\n\t"                     \
0127         ".section\t__ex_table,\"a\"\n\t"    \
0128         STR(PTR_WD)"\t1b, 4b\n\t"           \
0129         STR(PTR_WD)"\t2b, 4b\n\t"           \
0130         ".previous"                         \
0131         : "=&r" (value), "=r" (res)         \
0132         : "r" (addr), "i" (-EFAULT));       \
0133 } while (0)
0134 
0135 #define  _LoadDW(addr, value, res)  \
0136 do {                                                \
0137     __asm__ __volatile__ (                      \
0138         "1:\tldl\t%0, (%2)\n"               \
0139         "2:\tldr\t%0, 7(%2)\n\t"            \
0140         "li\t%1, 0\n"                       \
0141         "3:\n\t"                            \
0142         ".insn\n\t"                         \
0143         "\t.section\t.fixup,\"ax\"\n\t"     \
0144         "4:\tli\t%1, %3\n\t"                \
0145         "j\t3b\n\t"                         \
0146         ".previous\n\t"                     \
0147         ".section\t__ex_table,\"a\"\n\t"    \
0148         STR(PTR_WD)"\t1b, 4b\n\t"           \
0149         STR(PTR_WD)"\t2b, 4b\n\t"           \
0150         ".previous"                         \
0151         : "=&r" (value), "=r" (res)         \
0152         : "r" (addr), "i" (-EFAULT));       \
0153 } while (0)
0154 
0155 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
0156 /* For CPUs without lwl and ldl instructions */
0157 #define  _LoadWU(addr, value, res, type) \
0158 do {                                                \
0159     __asm__ __volatile__ (              \
0160         ".set\tpush\n\t"            \
0161         ".set\tnoat\n\t"            \
0162         "1:"type##_lbu("%0", "0(%2)")"\n\t" \
0163         "2:"type##_lbu("$1", "1(%2)")"\n\t" \
0164         "sll\t%0, 0x8\n\t"          \
0165         "or\t%0, $1\n\t"            \
0166         "3:"type##_lbu("$1", "2(%2)")"\n\t" \
0167         "sll\t%0, 0x8\n\t"          \
0168         "or\t%0, $1\n\t"            \
0169         "4:"type##_lbu("$1", "3(%2)")"\n\t" \
0170         "sll\t%0, 0x8\n\t"          \
0171         "or\t%0, $1\n\t"            \
0172         "li\t%1, 0\n"               \
0173         ".set\tpop\n"               \
0174         "10:\n\t"               \
0175         ".insn\n\t"             \
0176         ".section\t.fixup,\"ax\"\n\t"       \
0177         "11:\tli\t%1, %3\n\t"           \
0178         "j\t10b\n\t"                \
0179         ".previous\n\t"             \
0180         ".section\t__ex_table,\"a\"\n\t"    \
0181         STR(PTR_WD)"\t1b, 11b\n\t"      \
0182         STR(PTR_WD)"\t2b, 11b\n\t"      \
0183         STR(PTR_WD)"\t3b, 11b\n\t"      \
0184         STR(PTR_WD)"\t4b, 11b\n\t"      \
0185         ".previous"             \
0186         : "=&r" (value), "=r" (res)     \
0187         : "r" (addr), "i" (-EFAULT));       \
0188 } while (0)
0189 
0190 #define  _LoadDW(addr, value, res)  \
0191 do {                                                \
0192     __asm__ __volatile__ (              \
0193         ".set\tpush\n\t"            \
0194         ".set\tnoat\n\t"            \
0195         "1:lb\t%0, 0(%2)\n\t"           \
0196         "2:lbu\t $1, 1(%2)\n\t"         \
0197         "dsll\t%0, 0x8\n\t"         \
0198         "or\t%0, $1\n\t"            \
0199         "3:lbu\t$1, 2(%2)\n\t"          \
0200         "dsll\t%0, 0x8\n\t"         \
0201         "or\t%0, $1\n\t"            \
0202         "4:lbu\t$1, 3(%2)\n\t"          \
0203         "dsll\t%0, 0x8\n\t"         \
0204         "or\t%0, $1\n\t"            \
0205         "5:lbu\t$1, 4(%2)\n\t"          \
0206         "dsll\t%0, 0x8\n\t"         \
0207         "or\t%0, $1\n\t"            \
0208         "6:lbu\t$1, 5(%2)\n\t"          \
0209         "dsll\t%0, 0x8\n\t"         \
0210         "or\t%0, $1\n\t"            \
0211         "7:lbu\t$1, 6(%2)\n\t"          \
0212         "dsll\t%0, 0x8\n\t"         \
0213         "or\t%0, $1\n\t"            \
0214         "8:lbu\t$1, 7(%2)\n\t"          \
0215         "dsll\t%0, 0x8\n\t"         \
0216         "or\t%0, $1\n\t"            \
0217         "li\t%1, 0\n"               \
0218         ".set\tpop\n\t"             \
0219         "10:\n\t"               \
0220         ".insn\n\t"             \
0221         ".section\t.fixup,\"ax\"\n\t"       \
0222         "11:\tli\t%1, %3\n\t"           \
0223         "j\t10b\n\t"                \
0224         ".previous\n\t"             \
0225         ".section\t__ex_table,\"a\"\n\t"    \
0226         STR(PTR_WD)"\t1b, 11b\n\t"      \
0227         STR(PTR_WD)"\t2b, 11b\n\t"      \
0228         STR(PTR_WD)"\t3b, 11b\n\t"      \
0229         STR(PTR_WD)"\t4b, 11b\n\t"      \
0230         STR(PTR_WD)"\t5b, 11b\n\t"      \
0231         STR(PTR_WD)"\t6b, 11b\n\t"      \
0232         STR(PTR_WD)"\t7b, 11b\n\t"      \
0233         STR(PTR_WD)"\t8b, 11b\n\t"      \
0234         ".previous"             \
0235         : "=&r" (value), "=r" (res)     \
0236         : "r" (addr), "i" (-EFAULT));       \
0237 } while (0)
0238 
0239 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
0240 
0241 
0242 #define  _StoreHW(addr, value, res, type) \
0243 do {                                                \
0244     __asm__ __volatile__ (                      \
0245         ".set\tnoat\n"                      \
0246         "1:\t"type##_sb("%1", "1(%2)")"\n"  \
0247         "srl\t$1, %1, 0x8\n"                \
0248         "2:\t"type##_sb("$1", "0(%2)")"\n"  \
0249         ".set\tat\n\t"                      \
0250         "li\t%0, 0\n"                       \
0251         "3:\n\t"                            \
0252         ".insn\n\t"                         \
0253         ".section\t.fixup,\"ax\"\n\t"       \
0254         "4:\tli\t%0, %3\n\t"                \
0255         "j\t3b\n\t"                         \
0256         ".previous\n\t"                     \
0257         ".section\t__ex_table,\"a\"\n\t"    \
0258         STR(PTR_WD)"\t1b, 4b\n\t"           \
0259         STR(PTR_WD)"\t2b, 4b\n\t"           \
0260         ".previous"                         \
0261         : "=r" (res)                        \
0262         : "r" (value), "r" (addr), "i" (-EFAULT));\
0263 } while (0)
0264 
0265 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR
0266 #define  _StoreW(addr, value, res, type)  \
0267 do {                                                \
0268     __asm__ __volatile__ (                      \
0269         "1:\t"type##_swl("%1", "(%2)")"\n"  \
0270         "2:\t"type##_swr("%1", "3(%2)")"\n\t"\
0271         "li\t%0, 0\n"                       \
0272         "3:\n\t"                            \
0273         ".insn\n\t"                         \
0274         ".section\t.fixup,\"ax\"\n\t"       \
0275         "4:\tli\t%0, %3\n\t"                \
0276         "j\t3b\n\t"                         \
0277         ".previous\n\t"                     \
0278         ".section\t__ex_table,\"a\"\n\t"    \
0279         STR(PTR_WD)"\t1b, 4b\n\t"           \
0280         STR(PTR_WD)"\t2b, 4b\n\t"           \
0281         ".previous"                         \
0282         : "=r" (res)                                \
0283         : "r" (value), "r" (addr), "i" (-EFAULT));  \
0284 } while (0)
0285 
0286 #define  _StoreDW(addr, value, res) \
0287 do {                                                \
0288     __asm__ __volatile__ (                      \
0289         "1:\tsdl\t%1,(%2)\n"                \
0290         "2:\tsdr\t%1, 7(%2)\n\t"            \
0291         "li\t%0, 0\n"                       \
0292         "3:\n\t"                            \
0293         ".insn\n\t"                         \
0294         ".section\t.fixup,\"ax\"\n\t"       \
0295         "4:\tli\t%0, %3\n\t"                \
0296         "j\t3b\n\t"                         \
0297         ".previous\n\t"                     \
0298         ".section\t__ex_table,\"a\"\n\t"    \
0299         STR(PTR_WD)"\t1b, 4b\n\t"           \
0300         STR(PTR_WD)"\t2b, 4b\n\t"           \
0301         ".previous"                         \
0302         : "=r" (res)                                \
0303         : "r" (value), "r" (addr), "i" (-EFAULT));  \
0304 } while (0)
0305 
0306 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
0307 #define  _StoreW(addr, value, res, type)  \
0308 do {                                                \
0309     __asm__ __volatile__ (                      \
0310         ".set\tpush\n\t"            \
0311         ".set\tnoat\n\t"            \
0312         "1:"type##_sb("%1", "3(%2)")"\n\t"  \
0313         "srl\t$1, %1, 0x8\n\t"          \
0314         "2:"type##_sb("$1", "2(%2)")"\n\t"  \
0315         "srl\t$1, $1,  0x8\n\t"         \
0316         "3:"type##_sb("$1", "1(%2)")"\n\t"  \
0317         "srl\t$1, $1, 0x8\n\t"          \
0318         "4:"type##_sb("$1", "0(%2)")"\n\t"  \
0319         ".set\tpop\n\t"             \
0320         "li\t%0, 0\n"               \
0321         "10:\n\t"               \
0322         ".insn\n\t"             \
0323         ".section\t.fixup,\"ax\"\n\t"       \
0324         "11:\tli\t%0, %3\n\t"           \
0325         "j\t10b\n\t"                \
0326         ".previous\n\t"             \
0327         ".section\t__ex_table,\"a\"\n\t"    \
0328         STR(PTR_WD)"\t1b, 11b\n\t"      \
0329         STR(PTR_WD)"\t2b, 11b\n\t"      \
0330         STR(PTR_WD)"\t3b, 11b\n\t"      \
0331         STR(PTR_WD)"\t4b, 11b\n\t"      \
0332         ".previous"             \
0333         : "=&r" (res)                   \
0334         : "r" (value), "r" (addr), "i" (-EFAULT)    \
0335         : "memory");                                \
0336 } while (0)
0337 
0338 #define  _StoreDW(addr, value, res) \
0339 do {                                                \
0340     __asm__ __volatile__ (                      \
0341         ".set\tpush\n\t"            \
0342         ".set\tnoat\n\t"            \
0343         "1:sb\t%1, 7(%2)\n\t"           \
0344         "dsrl\t$1, %1, 0x8\n\t"         \
0345         "2:sb\t$1, 6(%2)\n\t"           \
0346         "dsrl\t$1, $1, 0x8\n\t"         \
0347         "3:sb\t$1, 5(%2)\n\t"           \
0348         "dsrl\t$1, $1, 0x8\n\t"         \
0349         "4:sb\t$1, 4(%2)\n\t"           \
0350         "dsrl\t$1, $1, 0x8\n\t"         \
0351         "5:sb\t$1, 3(%2)\n\t"           \
0352         "dsrl\t$1, $1, 0x8\n\t"         \
0353         "6:sb\t$1, 2(%2)\n\t"           \
0354         "dsrl\t$1, $1, 0x8\n\t"         \
0355         "7:sb\t$1, 1(%2)\n\t"           \
0356         "dsrl\t$1, $1, 0x8\n\t"         \
0357         "8:sb\t$1, 0(%2)\n\t"           \
0358         "dsrl\t$1, $1, 0x8\n\t"         \
0359         ".set\tpop\n\t"             \
0360         "li\t%0, 0\n"               \
0361         "10:\n\t"               \
0362         ".insn\n\t"             \
0363         ".section\t.fixup,\"ax\"\n\t"       \
0364         "11:\tli\t%0, %3\n\t"           \
0365         "j\t10b\n\t"                \
0366         ".previous\n\t"             \
0367         ".section\t__ex_table,\"a\"\n\t"    \
0368         STR(PTR_WD)"\t1b, 11b\n\t"      \
0369         STR(PTR_WD)"\t2b, 11b\n\t"      \
0370         STR(PTR_WD)"\t3b, 11b\n\t"      \
0371         STR(PTR_WD)"\t4b, 11b\n\t"      \
0372         STR(PTR_WD)"\t5b, 11b\n\t"      \
0373         STR(PTR_WD)"\t6b, 11b\n\t"      \
0374         STR(PTR_WD)"\t7b, 11b\n\t"      \
0375         STR(PTR_WD)"\t8b, 11b\n\t"      \
0376         ".previous"             \
0377         : "=&r" (res)                   \
0378         : "r" (value), "r" (addr), "i" (-EFAULT)    \
0379         : "memory");                                \
0380 } while (0)
0381 
0382 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
0383 
0384 #else /* __BIG_ENDIAN */
0385 
0386 #define  _LoadHW(addr, value, res, type)  \
0387 do {                                                \
0388     __asm__ __volatile__ (".set\tnoat\n"        \
0389         "1:\t"type##_lb("%0", "1(%2)")"\n"  \
0390         "2:\t"type##_lbu("$1", "0(%2)")"\n\t"\
0391         "sll\t%0, 0x8\n\t"                  \
0392         "or\t%0, $1\n\t"                    \
0393         "li\t%1, 0\n"                       \
0394         "3:\t.set\tat\n\t"                  \
0395         ".insn\n\t"                         \
0396         ".section\t.fixup,\"ax\"\n\t"       \
0397         "4:\tli\t%1, %3\n\t"                \
0398         "j\t3b\n\t"                         \
0399         ".previous\n\t"                     \
0400         ".section\t__ex_table,\"a\"\n\t"    \
0401         STR(PTR_WD)"\t1b, 4b\n\t"           \
0402         STR(PTR_WD)"\t2b, 4b\n\t"           \
0403         ".previous"                         \
0404         : "=&r" (value), "=r" (res)         \
0405         : "r" (addr), "i" (-EFAULT));       \
0406 } while (0)
0407 
0408 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR
0409 #define  _LoadW(addr, value, res, type)   \
0410 do {                                                \
0411     __asm__ __volatile__ (                      \
0412         "1:\t"type##_lwl("%0", "3(%2)")"\n" \
0413         "2:\t"type##_lwr("%0", "(%2)")"\n\t"\
0414         "li\t%1, 0\n"                       \
0415         "3:\n\t"                            \
0416         ".insn\n\t"                         \
0417         ".section\t.fixup,\"ax\"\n\t"       \
0418         "4:\tli\t%1, %3\n\t"                \
0419         "j\t3b\n\t"                         \
0420         ".previous\n\t"                     \
0421         ".section\t__ex_table,\"a\"\n\t"    \
0422         STR(PTR_WD)"\t1b, 4b\n\t"           \
0423         STR(PTR_WD)"\t2b, 4b\n\t"           \
0424         ".previous"                         \
0425         : "=&r" (value), "=r" (res)         \
0426         : "r" (addr), "i" (-EFAULT));       \
0427 } while (0)
0428 
0429 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
0430 /* For CPUs without lwl instruction */
0431 #define  _LoadW(addr, value, res, type) \
0432 do {                                                \
0433     __asm__ __volatile__ (              \
0434         ".set\tpush\n"              \
0435         ".set\tnoat\n\t"            \
0436         "1:"type##_lb("%0", "3(%2)")"\n\t"  \
0437         "2:"type##_lbu("$1", "2(%2)")"\n\t" \
0438         "sll\t%0, 0x8\n\t"          \
0439         "or\t%0, $1\n\t"            \
0440         "3:"type##_lbu("$1", "1(%2)")"\n\t" \
0441         "sll\t%0, 0x8\n\t"          \
0442         "or\t%0, $1\n\t"            \
0443         "4:"type##_lbu("$1", "0(%2)")"\n\t" \
0444         "sll\t%0, 0x8\n\t"          \
0445         "or\t%0, $1\n\t"            \
0446         "li\t%1, 0\n"               \
0447         ".set\tpop\n"               \
0448         "10:\n\t"               \
0449         ".insn\n\t"             \
0450         ".section\t.fixup,\"ax\"\n\t"       \
0451         "11:\tli\t%1, %3\n\t"           \
0452         "j\t10b\n\t"                \
0453         ".previous\n\t"             \
0454         ".section\t__ex_table,\"a\"\n\t"    \
0455         STR(PTR_WD)"\t1b, 11b\n\t"      \
0456         STR(PTR_WD)"\t2b, 11b\n\t"      \
0457         STR(PTR_WD)"\t3b, 11b\n\t"      \
0458         STR(PTR_WD)"\t4b, 11b\n\t"      \
0459         ".previous"             \
0460         : "=&r" (value), "=r" (res)     \
0461         : "r" (addr), "i" (-EFAULT));       \
0462 } while (0)
0463 
0464 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
0465 
0466 
0467 #define  _LoadHWU(addr, value, res, type) \
0468 do {                                                \
0469     __asm__ __volatile__ (                      \
0470         ".set\tnoat\n"                      \
0471         "1:\t"type##_lbu("%0", "1(%2)")"\n" \
0472         "2:\t"type##_lbu("$1", "0(%2)")"\n\t"\
0473         "sll\t%0, 0x8\n\t"                  \
0474         "or\t%0, $1\n\t"                    \
0475         "li\t%1, 0\n"                       \
0476         "3:\n\t"                            \
0477         ".insn\n\t"                         \
0478         ".set\tat\n\t"                      \
0479         ".section\t.fixup,\"ax\"\n\t"       \
0480         "4:\tli\t%1, %3\n\t"                \
0481         "j\t3b\n\t"                         \
0482         ".previous\n\t"                     \
0483         ".section\t__ex_table,\"a\"\n\t"    \
0484         STR(PTR_WD)"\t1b, 4b\n\t"           \
0485         STR(PTR_WD)"\t2b, 4b\n\t"           \
0486         ".previous"                         \
0487         : "=&r" (value), "=r" (res)         \
0488         : "r" (addr), "i" (-EFAULT));       \
0489 } while (0)
0490 
0491 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR
0492 #define  _LoadWU(addr, value, res, type)  \
0493 do {                                                \
0494     __asm__ __volatile__ (                      \
0495         "1:\t"type##_lwl("%0", "3(%2)")"\n" \
0496         "2:\t"type##_lwr("%0", "(%2)")"\n\t"\
0497         "dsll\t%0, %0, 32\n\t"              \
0498         "dsrl\t%0, %0, 32\n\t"              \
0499         "li\t%1, 0\n"                       \
0500         "3:\n\t"                            \
0501         ".insn\n\t"                         \
0502         "\t.section\t.fixup,\"ax\"\n\t"     \
0503         "4:\tli\t%1, %3\n\t"                \
0504         "j\t3b\n\t"                         \
0505         ".previous\n\t"                     \
0506         ".section\t__ex_table,\"a\"\n\t"    \
0507         STR(PTR_WD)"\t1b, 4b\n\t"           \
0508         STR(PTR_WD)"\t2b, 4b\n\t"           \
0509         ".previous"                         \
0510         : "=&r" (value), "=r" (res)         \
0511         : "r" (addr), "i" (-EFAULT));       \
0512 } while (0)
0513 
0514 #define  _LoadDW(addr, value, res)  \
0515 do {                                                \
0516     __asm__ __volatile__ (                      \
0517         "1:\tldl\t%0, 7(%2)\n"              \
0518         "2:\tldr\t%0, (%2)\n\t"             \
0519         "li\t%1, 0\n"                       \
0520         "3:\n\t"                            \
0521         ".insn\n\t"                         \
0522         "\t.section\t.fixup,\"ax\"\n\t"     \
0523         "4:\tli\t%1, %3\n\t"                \
0524         "j\t3b\n\t"                         \
0525         ".previous\n\t"                     \
0526         ".section\t__ex_table,\"a\"\n\t"    \
0527         STR(PTR_WD)"\t1b, 4b\n\t"           \
0528         STR(PTR_WD)"\t2b, 4b\n\t"           \
0529         ".previous"                         \
0530         : "=&r" (value), "=r" (res)         \
0531         : "r" (addr), "i" (-EFAULT));       \
0532 } while (0)
0533 
0534 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
0535 /* For CPUs without lwl and ldl instructions */
0536 #define  _LoadWU(addr, value, res, type) \
0537 do {                                                \
0538     __asm__ __volatile__ (              \
0539         ".set\tpush\n\t"            \
0540         ".set\tnoat\n\t"            \
0541         "1:"type##_lbu("%0", "3(%2)")"\n\t" \
0542         "2:"type##_lbu("$1", "2(%2)")"\n\t" \
0543         "sll\t%0, 0x8\n\t"          \
0544         "or\t%0, $1\n\t"            \
0545         "3:"type##_lbu("$1", "1(%2)")"\n\t" \
0546         "sll\t%0, 0x8\n\t"          \
0547         "or\t%0, $1\n\t"            \
0548         "4:"type##_lbu("$1", "0(%2)")"\n\t" \
0549         "sll\t%0, 0x8\n\t"          \
0550         "or\t%0, $1\n\t"            \
0551         "li\t%1, 0\n"               \
0552         ".set\tpop\n"               \
0553         "10:\n\t"               \
0554         ".insn\n\t"             \
0555         ".section\t.fixup,\"ax\"\n\t"       \
0556         "11:\tli\t%1, %3\n\t"           \
0557         "j\t10b\n\t"                \
0558         ".previous\n\t"             \
0559         ".section\t__ex_table,\"a\"\n\t"    \
0560         STR(PTR_WD)"\t1b, 11b\n\t"      \
0561         STR(PTR_WD)"\t2b, 11b\n\t"      \
0562         STR(PTR_WD)"\t3b, 11b\n\t"      \
0563         STR(PTR_WD)"\t4b, 11b\n\t"      \
0564         ".previous"             \
0565         : "=&r" (value), "=r" (res)     \
0566         : "r" (addr), "i" (-EFAULT));       \
0567 } while (0)
0568 
0569 #define  _LoadDW(addr, value, res)  \
0570 do {                                                \
0571     __asm__ __volatile__ (              \
0572         ".set\tpush\n\t"            \
0573         ".set\tnoat\n\t"            \
0574         "1:lb\t%0, 7(%2)\n\t"           \
0575         "2:lbu\t$1, 6(%2)\n\t"          \
0576         "dsll\t%0, 0x8\n\t"         \
0577         "or\t%0, $1\n\t"            \
0578         "3:lbu\t$1, 5(%2)\n\t"          \
0579         "dsll\t%0, 0x8\n\t"         \
0580         "or\t%0, $1\n\t"            \
0581         "4:lbu\t$1, 4(%2)\n\t"          \
0582         "dsll\t%0, 0x8\n\t"         \
0583         "or\t%0, $1\n\t"            \
0584         "5:lbu\t$1, 3(%2)\n\t"          \
0585         "dsll\t%0, 0x8\n\t"         \
0586         "or\t%0, $1\n\t"            \
0587         "6:lbu\t$1, 2(%2)\n\t"          \
0588         "dsll\t%0, 0x8\n\t"         \
0589         "or\t%0, $1\n\t"            \
0590         "7:lbu\t$1, 1(%2)\n\t"          \
0591         "dsll\t%0, 0x8\n\t"         \
0592         "or\t%0, $1\n\t"            \
0593         "8:lbu\t$1, 0(%2)\n\t"          \
0594         "dsll\t%0, 0x8\n\t"         \
0595         "or\t%0, $1\n\t"            \
0596         "li\t%1, 0\n"               \
0597         ".set\tpop\n\t"             \
0598         "10:\n\t"               \
0599         ".insn\n\t"             \
0600         ".section\t.fixup,\"ax\"\n\t"       \
0601         "11:\tli\t%1, %3\n\t"           \
0602         "j\t10b\n\t"                \
0603         ".previous\n\t"             \
0604         ".section\t__ex_table,\"a\"\n\t"    \
0605         STR(PTR_WD)"\t1b, 11b\n\t"      \
0606         STR(PTR_WD)"\t2b, 11b\n\t"      \
0607         STR(PTR_WD)"\t3b, 11b\n\t"      \
0608         STR(PTR_WD)"\t4b, 11b\n\t"      \
0609         STR(PTR_WD)"\t5b, 11b\n\t"      \
0610         STR(PTR_WD)"\t6b, 11b\n\t"      \
0611         STR(PTR_WD)"\t7b, 11b\n\t"      \
0612         STR(PTR_WD)"\t8b, 11b\n\t"      \
0613         ".previous"             \
0614         : "=&r" (value), "=r" (res)     \
0615         : "r" (addr), "i" (-EFAULT));       \
0616 } while (0)
0617 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
0618 
0619 #define  _StoreHW(addr, value, res, type) \
0620 do {                                                 \
0621     __asm__ __volatile__ (                      \
0622         ".set\tnoat\n"                      \
0623         "1:\t"type##_sb("%1", "0(%2)")"\n"  \
0624         "srl\t$1,%1, 0x8\n"                 \
0625         "2:\t"type##_sb("$1", "1(%2)")"\n"  \
0626         ".set\tat\n\t"                      \
0627         "li\t%0, 0\n"                       \
0628         "3:\n\t"                            \
0629         ".insn\n\t"                         \
0630         ".section\t.fixup,\"ax\"\n\t"       \
0631         "4:\tli\t%0, %3\n\t"                \
0632         "j\t3b\n\t"                         \
0633         ".previous\n\t"                     \
0634         ".section\t__ex_table,\"a\"\n\t"    \
0635         STR(PTR_WD)"\t1b, 4b\n\t"           \
0636         STR(PTR_WD)"\t2b, 4b\n\t"           \
0637         ".previous"                         \
0638         : "=r" (res)                        \
0639         : "r" (value), "r" (addr), "i" (-EFAULT));\
0640 } while (0)
0641 
0642 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR
0643 #define  _StoreW(addr, value, res, type)  \
0644 do {                                                \
0645     __asm__ __volatile__ (                      \
0646         "1:\t"type##_swl("%1", "3(%2)")"\n" \
0647         "2:\t"type##_swr("%1", "(%2)")"\n\t"\
0648         "li\t%0, 0\n"                       \
0649         "3:\n\t"                            \
0650         ".insn\n\t"                         \
0651         ".section\t.fixup,\"ax\"\n\t"       \
0652         "4:\tli\t%0, %3\n\t"                \
0653         "j\t3b\n\t"                         \
0654         ".previous\n\t"                     \
0655         ".section\t__ex_table,\"a\"\n\t"    \
0656         STR(PTR_WD)"\t1b, 4b\n\t"           \
0657         STR(PTR_WD)"\t2b, 4b\n\t"           \
0658         ".previous"                         \
0659         : "=r" (res)                                \
0660         : "r" (value), "r" (addr), "i" (-EFAULT));  \
0661 } while (0)
0662 
0663 #define  _StoreDW(addr, value, res) \
0664 do {                                                \
0665     __asm__ __volatile__ (                      \
0666         "1:\tsdl\t%1, 7(%2)\n"              \
0667         "2:\tsdr\t%1, (%2)\n\t"             \
0668         "li\t%0, 0\n"                       \
0669         "3:\n\t"                            \
0670         ".insn\n\t"                         \
0671         ".section\t.fixup,\"ax\"\n\t"       \
0672         "4:\tli\t%0, %3\n\t"                \
0673         "j\t3b\n\t"                         \
0674         ".previous\n\t"                     \
0675         ".section\t__ex_table,\"a\"\n\t"    \
0676         STR(PTR_WD)"\t1b, 4b\n\t"           \
0677         STR(PTR_WD)"\t2b, 4b\n\t"           \
0678         ".previous"                         \
0679         : "=r" (res)                                \
0680         : "r" (value), "r" (addr), "i" (-EFAULT));  \
0681 } while (0)
0682 
0683 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
0684 /* For CPUs without swl and sdl instructions */
0685 #define  _StoreW(addr, value, res, type)  \
0686 do {                                                \
0687     __asm__ __volatile__ (                      \
0688         ".set\tpush\n\t"            \
0689         ".set\tnoat\n\t"            \
0690         "1:"type##_sb("%1", "0(%2)")"\n\t"  \
0691         "srl\t$1, %1, 0x8\n\t"          \
0692         "2:"type##_sb("$1", "1(%2)")"\n\t"  \
0693         "srl\t$1, $1,  0x8\n\t"         \
0694         "3:"type##_sb("$1", "2(%2)")"\n\t"  \
0695         "srl\t$1, $1, 0x8\n\t"          \
0696         "4:"type##_sb("$1", "3(%2)")"\n\t"  \
0697         ".set\tpop\n\t"             \
0698         "li\t%0, 0\n"               \
0699         "10:\n\t"               \
0700         ".insn\n\t"             \
0701         ".section\t.fixup,\"ax\"\n\t"       \
0702         "11:\tli\t%0, %3\n\t"           \
0703         "j\t10b\n\t"                \
0704         ".previous\n\t"             \
0705         ".section\t__ex_table,\"a\"\n\t"    \
0706         STR(PTR_WD)"\t1b, 11b\n\t"      \
0707         STR(PTR_WD)"\t2b, 11b\n\t"      \
0708         STR(PTR_WD)"\t3b, 11b\n\t"      \
0709         STR(PTR_WD)"\t4b, 11b\n\t"      \
0710         ".previous"             \
0711         : "=&r" (res)                   \
0712         : "r" (value), "r" (addr), "i" (-EFAULT)    \
0713         : "memory");                                \
0714 } while (0)
0715 
0716 #define  _StoreDW(addr, value, res) \
0717 do {                                                \
0718     __asm__ __volatile__ (                      \
0719         ".set\tpush\n\t"            \
0720         ".set\tnoat\n\t"            \
0721         "1:sb\t%1, 0(%2)\n\t"           \
0722         "dsrl\t$1, %1, 0x8\n\t"         \
0723         "2:sb\t$1, 1(%2)\n\t"           \
0724         "dsrl\t$1, $1, 0x8\n\t"         \
0725         "3:sb\t$1, 2(%2)\n\t"           \
0726         "dsrl\t$1, $1, 0x8\n\t"         \
0727         "4:sb\t$1, 3(%2)\n\t"           \
0728         "dsrl\t$1, $1, 0x8\n\t"         \
0729         "5:sb\t$1, 4(%2)\n\t"           \
0730         "dsrl\t$1, $1, 0x8\n\t"         \
0731         "6:sb\t$1, 5(%2)\n\t"           \
0732         "dsrl\t$1, $1, 0x8\n\t"         \
0733         "7:sb\t$1, 6(%2)\n\t"           \
0734         "dsrl\t$1, $1, 0x8\n\t"         \
0735         "8:sb\t$1, 7(%2)\n\t"           \
0736         "dsrl\t$1, $1, 0x8\n\t"         \
0737         ".set\tpop\n\t"             \
0738         "li\t%0, 0\n"               \
0739         "10:\n\t"               \
0740         ".insn\n\t"             \
0741         ".section\t.fixup,\"ax\"\n\t"       \
0742         "11:\tli\t%0, %3\n\t"           \
0743         "j\t10b\n\t"                \
0744         ".previous\n\t"             \
0745         ".section\t__ex_table,\"a\"\n\t"    \
0746         STR(PTR_WD)"\t1b, 11b\n\t"      \
0747         STR(PTR_WD)"\t2b, 11b\n\t"      \
0748         STR(PTR_WD)"\t3b, 11b\n\t"      \
0749         STR(PTR_WD)"\t4b, 11b\n\t"      \
0750         STR(PTR_WD)"\t5b, 11b\n\t"      \
0751         STR(PTR_WD)"\t6b, 11b\n\t"      \
0752         STR(PTR_WD)"\t7b, 11b\n\t"      \
0753         STR(PTR_WD)"\t8b, 11b\n\t"      \
0754         ".previous"             \
0755         : "=&r" (res)                   \
0756         : "r" (value), "r" (addr), "i" (-EFAULT)    \
0757         : "memory");                                \
0758 } while (0)
0759 
0760 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
0761 #endif
0762 
0763 #define LoadHWU(addr, value, res)   _LoadHWU(addr, value, res, kernel)
0764 #define LoadHWUE(addr, value, res)  _LoadHWU(addr, value, res, user)
0765 #define LoadWU(addr, value, res)    _LoadWU(addr, value, res, kernel)
0766 #define LoadWUE(addr, value, res)   _LoadWU(addr, value, res, user)
0767 #define LoadHW(addr, value, res)    _LoadHW(addr, value, res, kernel)
0768 #define LoadHWE(addr, value, res)   _LoadHW(addr, value, res, user)
0769 #define LoadW(addr, value, res)     _LoadW(addr, value, res, kernel)
0770 #define LoadWE(addr, value, res)    _LoadW(addr, value, res, user)
0771 #define LoadDW(addr, value, res)    _LoadDW(addr, value, res)
0772 
0773 #define StoreHW(addr, value, res)   _StoreHW(addr, value, res, kernel)
0774 #define StoreHWE(addr, value, res)  _StoreHW(addr, value, res, user)
0775 #define StoreW(addr, value, res)    _StoreW(addr, value, res, kernel)
0776 #define StoreWE(addr, value, res)   _StoreW(addr, value, res, user)
0777 #define StoreDW(addr, value, res)   _StoreDW(addr, value, res)
0778 
0779 #endif /* _ASM_MIPS_UNALIGNED_EMUL_H */