unaligned-emul.h 26 KB

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