swap.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. // Copyright (c) 2012- PPSSPP Project / Dolphin Project.
  2. // This program is free software: you can redistribute it and/or modify
  3. // it under the terms of the GNU General Public License as published by
  4. // the Free Software Foundation, version 2.0 or later versions.
  5. // This program is distributed in the hope that it will be useful,
  6. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. // GNU General Public License 2.0 for more details.
  9. // A copy of the GPL 2.0 should have been included with the program.
  10. // If not, see http://www.gnu.org/licenses/
  11. // Official git repository and contact information can be found at
  12. // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
  13. #pragma once
  14. #if defined(_MSC_VER)
  15. #include <cstdlib>
  16. #elif defined(__linux__)
  17. #include <byteswap.h>
  18. #elif defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || \
  19. defined(__NetBSD__) || defined(__OpenBSD__)
  20. #include <sys/endian.h>
  21. #endif
  22. #include <cstring>
  23. #include "common/common_types.h"
  24. // GCC 4.6+
  25. #if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
  26. #if __BYTE_ORDER__ && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) && !defined(COMMON_LITTLE_ENDIAN)
  27. #define COMMON_LITTLE_ENDIAN 1
  28. #elif __BYTE_ORDER__ && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) && !defined(COMMON_BIG_ENDIAN)
  29. #define COMMON_BIG_ENDIAN 1
  30. #endif
  31. // LLVM/clang
  32. #elif __clang__
  33. #if __LITTLE_ENDIAN__ && !defined(COMMON_LITTLE_ENDIAN)
  34. #define COMMON_LITTLE_ENDIAN 1
  35. #elif __BIG_ENDIAN__ && !defined(COMMON_BIG_ENDIAN)
  36. #define COMMON_BIG_ENDIAN 1
  37. #endif
  38. // MSVC
  39. #elif defined(_MSC_VER) && !defined(COMMON_BIG_ENDIAN) && !defined(COMMON_LITTLE_ENDIAN)
  40. #define COMMON_LITTLE_ENDIAN 1
  41. #endif
  42. // Worst case, default to little endian.
  43. #if !COMMON_BIG_ENDIAN && !COMMON_LITTLE_ENDIAN
  44. #define COMMON_LITTLE_ENDIAN 1
  45. #endif
  46. namespace Common {
  47. #ifdef _MSC_VER
  48. inline u16 swap16(u16 _data) {
  49. return _byteswap_ushort(_data);
  50. }
  51. inline u32 swap32(u32 _data) {
  52. return _byteswap_ulong(_data);
  53. }
  54. inline u64 swap64(u64 _data) {
  55. return _byteswap_uint64(_data);
  56. }
  57. #elif _M_ARM
  58. inline u16 swap16(u16 _data) {
  59. u32 data = _data;
  60. __asm__("rev16 %0, %1\n" : "=l"(data) : "l"(data));
  61. return (u16)data;
  62. }
  63. inline u32 swap32(u32 _data) {
  64. __asm__("rev %0, %1\n" : "=l"(_data) : "l"(_data));
  65. return _data;
  66. }
  67. inline u64 swap64(u64 _data) {
  68. return ((u64)swap32(_data) << 32) | swap32(_data >> 32);
  69. }
  70. #elif __linux__
  71. inline u16 swap16(u16 _data) {
  72. return bswap_16(_data);
  73. }
  74. inline u32 swap32(u32 _data) {
  75. return bswap_32(_data);
  76. }
  77. inline u64 swap64(u64 _data) {
  78. return bswap_64(_data);
  79. }
  80. #elif __APPLE__
  81. inline __attribute__((always_inline)) u16 swap16(u16 _data) {
  82. return (_data >> 8) | (_data << 8);
  83. }
  84. inline __attribute__((always_inline)) u32 swap32(u32 _data) {
  85. return __builtin_bswap32(_data);
  86. }
  87. inline __attribute__((always_inline)) u64 swap64(u64 _data) {
  88. return __builtin_bswap64(_data);
  89. }
  90. #elif defined(__Bitrig__) || defined(__OpenBSD__)
  91. // swap16, swap32, swap64 are left as is
  92. #elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__)
  93. inline u16 swap16(u16 _data) {
  94. return bswap16(_data);
  95. }
  96. inline u32 swap32(u32 _data) {
  97. return bswap32(_data);
  98. }
  99. inline u64 swap64(u64 _data) {
  100. return bswap64(_data);
  101. }
  102. #else
  103. // Slow generic implementation.
  104. inline u16 swap16(u16 data) {
  105. return (data >> 8) | (data << 8);
  106. }
  107. inline u32 swap32(u32 data) {
  108. return (swap16(data) << 16) | swap16(data >> 16);
  109. }
  110. inline u64 swap64(u64 data) {
  111. return ((u64)swap32(data) << 32) | swap32(data >> 32);
  112. }
  113. #endif
  114. inline float swapf(float f) {
  115. static_assert(sizeof(u32) == sizeof(float), "float must be the same size as uint32_t.");
  116. u32 value;
  117. std::memcpy(&value, &f, sizeof(u32));
  118. value = swap32(value);
  119. std::memcpy(&f, &value, sizeof(u32));
  120. return f;
  121. }
  122. inline double swapd(double f) {
  123. static_assert(sizeof(u64) == sizeof(double), "double must be the same size as uint64_t.");
  124. u64 value;
  125. std::memcpy(&value, &f, sizeof(u64));
  126. value = swap64(value);
  127. std::memcpy(&f, &value, sizeof(u64));
  128. return f;
  129. }
  130. } // Namespace Common
  131. template <typename T, typename F>
  132. struct swap_struct_t {
  133. typedef swap_struct_t<T, F> swapped_t;
  134. protected:
  135. T value = T();
  136. static T swap(T v) {
  137. return F::swap(v);
  138. }
  139. public:
  140. T const swap() const {
  141. return swap(value);
  142. }
  143. swap_struct_t() = default;
  144. swap_struct_t(const T& v) : value(swap(v)) {}
  145. template <typename S>
  146. swapped_t& operator=(const S& source) {
  147. value = swap((T)source);
  148. return *this;
  149. }
  150. operator s8() const {
  151. return (s8)swap();
  152. }
  153. operator u8() const {
  154. return (u8)swap();
  155. }
  156. operator s16() const {
  157. return (s16)swap();
  158. }
  159. operator u16() const {
  160. return (u16)swap();
  161. }
  162. operator s32() const {
  163. return (s32)swap();
  164. }
  165. operator u32() const {
  166. return (u32)swap();
  167. }
  168. operator s64() const {
  169. return (s64)swap();
  170. }
  171. operator u64() const {
  172. return (u64)swap();
  173. }
  174. operator float() const {
  175. return (float)swap();
  176. }
  177. operator double() const {
  178. return (double)swap();
  179. }
  180. // +v
  181. swapped_t operator+() const {
  182. return +swap();
  183. }
  184. // -v
  185. swapped_t operator-() const {
  186. return -swap();
  187. }
  188. // v / 5
  189. swapped_t operator/(const swapped_t& i) const {
  190. return swap() / i.swap();
  191. }
  192. template <typename S>
  193. swapped_t operator/(const S& i) const {
  194. return swap() / i;
  195. }
  196. // v * 5
  197. swapped_t operator*(const swapped_t& i) const {
  198. return swap() * i.swap();
  199. }
  200. template <typename S>
  201. swapped_t operator*(const S& i) const {
  202. return swap() * i;
  203. }
  204. // v + 5
  205. swapped_t operator+(const swapped_t& i) const {
  206. return swap() + i.swap();
  207. }
  208. template <typename S>
  209. swapped_t operator+(const S& i) const {
  210. return swap() + (T)i;
  211. }
  212. // v - 5
  213. swapped_t operator-(const swapped_t& i) const {
  214. return swap() - i.swap();
  215. }
  216. template <typename S>
  217. swapped_t operator-(const S& i) const {
  218. return swap() - (T)i;
  219. }
  220. // v += 5
  221. swapped_t& operator+=(const swapped_t& i) {
  222. value = swap(swap() + i.swap());
  223. return *this;
  224. }
  225. template <typename S>
  226. swapped_t& operator+=(const S& i) {
  227. value = swap(swap() + (T)i);
  228. return *this;
  229. }
  230. // v -= 5
  231. swapped_t& operator-=(const swapped_t& i) {
  232. value = swap(swap() - i.swap());
  233. return *this;
  234. }
  235. template <typename S>
  236. swapped_t& operator-=(const S& i) {
  237. value = swap(swap() - (T)i);
  238. return *this;
  239. }
  240. // ++v
  241. swapped_t& operator++() {
  242. value = swap(swap() + 1);
  243. return *this;
  244. }
  245. // --v
  246. swapped_t& operator--() {
  247. value = swap(swap() - 1);
  248. return *this;
  249. }
  250. // v++
  251. swapped_t operator++(int) {
  252. swapped_t old = *this;
  253. value = swap(swap() + 1);
  254. return old;
  255. }
  256. // v--
  257. swapped_t operator--(int) {
  258. swapped_t old = *this;
  259. value = swap(swap() - 1);
  260. return old;
  261. }
  262. // Comparaison
  263. // v == i
  264. bool operator==(const swapped_t& i) const {
  265. return swap() == i.swap();
  266. }
  267. template <typename S>
  268. bool operator==(const S& i) const {
  269. return swap() == i;
  270. }
  271. // v != i
  272. bool operator!=(const swapped_t& i) const {
  273. return swap() != i.swap();
  274. }
  275. template <typename S>
  276. bool operator!=(const S& i) const {
  277. return swap() != i;
  278. }
  279. // v > i
  280. bool operator>(const swapped_t& i) const {
  281. return swap() > i.swap();
  282. }
  283. template <typename S>
  284. bool operator>(const S& i) const {
  285. return swap() > i;
  286. }
  287. // v < i
  288. bool operator<(const swapped_t& i) const {
  289. return swap() < i.swap();
  290. }
  291. template <typename S>
  292. bool operator<(const S& i) const {
  293. return swap() < i;
  294. }
  295. // v >= i
  296. bool operator>=(const swapped_t& i) const {
  297. return swap() >= i.swap();
  298. }
  299. template <typename S>
  300. bool operator>=(const S& i) const {
  301. return swap() >= i;
  302. }
  303. // v <= i
  304. bool operator<=(const swapped_t& i) const {
  305. return swap() <= i.swap();
  306. }
  307. template <typename S>
  308. bool operator<=(const S& i) const {
  309. return swap() <= i;
  310. }
  311. // logical
  312. swapped_t operator!() const {
  313. return !swap();
  314. }
  315. // bitmath
  316. swapped_t operator~() const {
  317. return ~swap();
  318. }
  319. swapped_t operator&(const swapped_t& b) const {
  320. return swap() & b.swap();
  321. }
  322. template <typename S>
  323. swapped_t operator&(const S& b) const {
  324. return swap() & b;
  325. }
  326. swapped_t& operator&=(const swapped_t& b) {
  327. value = swap(swap() & b.swap());
  328. return *this;
  329. }
  330. template <typename S>
  331. swapped_t& operator&=(const S b) {
  332. value = swap(swap() & b);
  333. return *this;
  334. }
  335. swapped_t operator|(const swapped_t& b) const {
  336. return swap() | b.swap();
  337. }
  338. template <typename S>
  339. swapped_t operator|(const S& b) const {
  340. return swap() | b;
  341. }
  342. swapped_t& operator|=(const swapped_t& b) {
  343. value = swap(swap() | b.swap());
  344. return *this;
  345. }
  346. template <typename S>
  347. swapped_t& operator|=(const S& b) {
  348. value = swap(swap() | b);
  349. return *this;
  350. }
  351. swapped_t operator^(const swapped_t& b) const {
  352. return swap() ^ b.swap();
  353. }
  354. template <typename S>
  355. swapped_t operator^(const S& b) const {
  356. return swap() ^ b;
  357. }
  358. swapped_t& operator^=(const swapped_t& b) {
  359. value = swap(swap() ^ b.swap());
  360. return *this;
  361. }
  362. template <typename S>
  363. swapped_t& operator^=(const S& b) {
  364. value = swap(swap() ^ b);
  365. return *this;
  366. }
  367. template <typename S>
  368. swapped_t operator<<(const S& b) const {
  369. return swap() << b;
  370. }
  371. template <typename S>
  372. swapped_t& operator<<=(const S& b) const {
  373. value = swap(swap() << b);
  374. return *this;
  375. }
  376. template <typename S>
  377. swapped_t operator>>(const S& b) const {
  378. return swap() >> b;
  379. }
  380. template <typename S>
  381. swapped_t& operator>>=(const S& b) const {
  382. value = swap(swap() >> b);
  383. return *this;
  384. }
  385. // Member
  386. /** todo **/
  387. // Arithmetics
  388. template <typename S, typename T2, typename F2>
  389. friend S operator+(const S& p, const swapped_t v);
  390. template <typename S, typename T2, typename F2>
  391. friend S operator-(const S& p, const swapped_t v);
  392. template <typename S, typename T2, typename F2>
  393. friend S operator/(const S& p, const swapped_t v);
  394. template <typename S, typename T2, typename F2>
  395. friend S operator*(const S& p, const swapped_t v);
  396. template <typename S, typename T2, typename F2>
  397. friend S operator%(const S& p, const swapped_t v);
  398. // Arithmetics + assignements
  399. template <typename S, typename T2, typename F2>
  400. friend S operator+=(const S& p, const swapped_t v);
  401. template <typename S, typename T2, typename F2>
  402. friend S operator-=(const S& p, const swapped_t v);
  403. // Bitmath
  404. template <typename S, typename T2, typename F2>
  405. friend S operator&(const S& p, const swapped_t v);
  406. // Comparison
  407. template <typename S, typename T2, typename F2>
  408. friend bool operator<(const S& p, const swapped_t v);
  409. template <typename S, typename T2, typename F2>
  410. friend bool operator>(const S& p, const swapped_t v);
  411. template <typename S, typename T2, typename F2>
  412. friend bool operator<=(const S& p, const swapped_t v);
  413. template <typename S, typename T2, typename F2>
  414. friend bool operator>=(const S& p, const swapped_t v);
  415. template <typename S, typename T2, typename F2>
  416. friend bool operator!=(const S& p, const swapped_t v);
  417. template <typename S, typename T2, typename F2>
  418. friend bool operator==(const S& p, const swapped_t v);
  419. };
  420. // Arithmetics
  421. template <typename S, typename T, typename F>
  422. S operator+(const S& i, const swap_struct_t<T, F> v) {
  423. return i + v.swap();
  424. }
  425. template <typename S, typename T, typename F>
  426. S operator-(const S& i, const swap_struct_t<T, F> v) {
  427. return i - v.swap();
  428. }
  429. template <typename S, typename T, typename F>
  430. S operator/(const S& i, const swap_struct_t<T, F> v) {
  431. return i / v.swap();
  432. }
  433. template <typename S, typename T, typename F>
  434. S operator*(const S& i, const swap_struct_t<T, F> v) {
  435. return i * v.swap();
  436. }
  437. template <typename S, typename T, typename F>
  438. S operator%(const S& i, const swap_struct_t<T, F> v) {
  439. return i % v.swap();
  440. }
  441. // Arithmetics + assignements
  442. template <typename S, typename T, typename F>
  443. S& operator+=(S& i, const swap_struct_t<T, F> v) {
  444. i += v.swap();
  445. return i;
  446. }
  447. template <typename S, typename T, typename F>
  448. S& operator-=(S& i, const swap_struct_t<T, F> v) {
  449. i -= v.swap();
  450. return i;
  451. }
  452. // Logical
  453. template <typename S, typename T, typename F>
  454. S operator&(const S& i, const swap_struct_t<T, F> v) {
  455. return i & v.swap();
  456. }
  457. template <typename S, typename T, typename F>
  458. S operator&(const swap_struct_t<T, F> v, const S& i) {
  459. return (S)(v.swap() & i);
  460. }
  461. // Comparaison
  462. template <typename S, typename T, typename F>
  463. bool operator<(const S& p, const swap_struct_t<T, F> v) {
  464. return p < v.swap();
  465. }
  466. template <typename S, typename T, typename F>
  467. bool operator>(const S& p, const swap_struct_t<T, F> v) {
  468. return p > v.swap();
  469. }
  470. template <typename S, typename T, typename F>
  471. bool operator<=(const S& p, const swap_struct_t<T, F> v) {
  472. return p <= v.swap();
  473. }
  474. template <typename S, typename T, typename F>
  475. bool operator>=(const S& p, const swap_struct_t<T, F> v) {
  476. return p >= v.swap();
  477. }
  478. template <typename S, typename T, typename F>
  479. bool operator!=(const S& p, const swap_struct_t<T, F> v) {
  480. return p != v.swap();
  481. }
  482. template <typename S, typename T, typename F>
  483. bool operator==(const S& p, const swap_struct_t<T, F> v) {
  484. return p == v.swap();
  485. }
  486. template <typename T>
  487. struct swap_64_t {
  488. static T swap(T x) {
  489. return static_cast<T>(Common::swap64(x));
  490. }
  491. };
  492. template <typename T>
  493. struct swap_32_t {
  494. static T swap(T x) {
  495. return static_cast<T>(Common::swap32(x));
  496. }
  497. };
  498. template <typename T>
  499. struct swap_16_t {
  500. static T swap(T x) {
  501. return static_cast<T>(Common::swap16(x));
  502. }
  503. };
  504. template <typename T>
  505. struct swap_float_t {
  506. static T swap(T x) {
  507. return static_cast<T>(Common::swapf(x));
  508. }
  509. };
  510. template <typename T>
  511. struct swap_double_t {
  512. static T swap(T x) {
  513. return static_cast<T>(Common::swapd(x));
  514. }
  515. };
  516. #if COMMON_LITTLE_ENDIAN
  517. typedef u32 u32_le;
  518. typedef u16 u16_le;
  519. typedef u64 u64_le;
  520. typedef s32 s32_le;
  521. typedef s16 s16_le;
  522. typedef s64 s64_le;
  523. typedef float float_le;
  524. typedef double double_le;
  525. typedef swap_struct_t<u64, swap_64_t<u64>> u64_be;
  526. typedef swap_struct_t<s64, swap_64_t<s64>> s64_be;
  527. typedef swap_struct_t<u32, swap_32_t<u32>> u32_be;
  528. typedef swap_struct_t<s32, swap_32_t<s32>> s32_be;
  529. typedef swap_struct_t<u16, swap_16_t<u16>> u16_be;
  530. typedef swap_struct_t<s16, swap_16_t<s16>> s16_be;
  531. typedef swap_struct_t<float, swap_float_t<float>> float_be;
  532. typedef swap_struct_t<double, swap_double_t<double>> double_be;
  533. #else
  534. typedef swap_struct_t<u64, swap_64_t<u64>> u64_le;
  535. typedef swap_struct_t<s64, swap_64_t<s64>> s64_le;
  536. typedef swap_struct_t<u32, swap_32_t<u32>> u32_le;
  537. typedef swap_struct_t<s32, swap_32_t<s32>> s32_le;
  538. typedef swap_struct_t<u16, swap_16_t<u16>> u16_le;
  539. typedef swap_struct_t<s16, swap_16_t<s16>> s16_le;
  540. typedef swap_struct_t<float, swap_float_t<float>> float_le;
  541. typedef swap_struct_t<double, swap_double_t<double>> double_le;
  542. typedef u32 u32_be;
  543. typedef u16 u16_be;
  544. typedef u64 u64_be;
  545. typedef s32 s32_be;
  546. typedef s16 s16_be;
  547. typedef s64 s64_be;
  548. typedef float float_be;
  549. typedef double double_be;
  550. #endif