swap.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  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 defined(ARCHITECTURE_ARM) && (__ARM_ARCH >= 6)
  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. // redefine swap16, swap32, swap64 as inline functions
  92. #undef swap16
  93. #undef swap32
  94. #undef swap64
  95. inline u16 swap16(u16 _data) {
  96. return __swap16(_data);
  97. }
  98. inline u32 swap32(u32 _data) {
  99. return __swap32(_data);
  100. }
  101. inline u64 swap64(u64 _data) {
  102. return __swap64(_data);
  103. }
  104. #elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__)
  105. inline u16 swap16(u16 _data) {
  106. return bswap16(_data);
  107. }
  108. inline u32 swap32(u32 _data) {
  109. return bswap32(_data);
  110. }
  111. inline u64 swap64(u64 _data) {
  112. return bswap64(_data);
  113. }
  114. #else
  115. // Slow generic implementation.
  116. inline u16 swap16(u16 data) {
  117. return (data >> 8) | (data << 8);
  118. }
  119. inline u32 swap32(u32 data) {
  120. return (swap16(data) << 16) | swap16(data >> 16);
  121. }
  122. inline u64 swap64(u64 data) {
  123. return ((u64)swap32(data) << 32) | swap32(data >> 32);
  124. }
  125. #endif
  126. inline float swapf(float f) {
  127. static_assert(sizeof(u32) == sizeof(float), "float must be the same size as uint32_t.");
  128. u32 value;
  129. std::memcpy(&value, &f, sizeof(u32));
  130. value = swap32(value);
  131. std::memcpy(&f, &value, sizeof(u32));
  132. return f;
  133. }
  134. inline double swapd(double f) {
  135. static_assert(sizeof(u64) == sizeof(double), "double must be the same size as uint64_t.");
  136. u64 value;
  137. std::memcpy(&value, &f, sizeof(u64));
  138. value = swap64(value);
  139. std::memcpy(&f, &value, sizeof(u64));
  140. return f;
  141. }
  142. } // Namespace Common
  143. template <typename T, typename F>
  144. struct swap_struct_t {
  145. using swapped_t = swap_struct_t;
  146. protected:
  147. T value = T();
  148. static T swap(T v) {
  149. return F::swap(v);
  150. }
  151. public:
  152. T swap() const {
  153. return swap(value);
  154. }
  155. swap_struct_t() = default;
  156. swap_struct_t(const T& v) : value(swap(v)) {}
  157. template <typename S>
  158. swapped_t& operator=(const S& source) {
  159. value = swap(static_cast<T>(source));
  160. return *this;
  161. }
  162. operator s8() const {
  163. return static_cast<s8>(swap());
  164. }
  165. operator u8() const {
  166. return static_cast<u8>(swap());
  167. }
  168. operator s16() const {
  169. return static_cast<s16>(swap());
  170. }
  171. operator u16() const {
  172. return static_cast<u16>(swap());
  173. }
  174. operator s32() const {
  175. return static_cast<s32>(swap());
  176. }
  177. operator u32() const {
  178. return static_cast<u32>(swap());
  179. }
  180. operator s64() const {
  181. return static_cast<s64>(swap());
  182. }
  183. operator u64() const {
  184. return static_cast<u64>(swap());
  185. }
  186. operator float() const {
  187. return static_cast<float>(swap());
  188. }
  189. operator double() const {
  190. return static_cast<double>(swap());
  191. }
  192. // +v
  193. swapped_t operator+() const {
  194. return +swap();
  195. }
  196. // -v
  197. swapped_t operator-() const {
  198. return -swap();
  199. }
  200. // v / 5
  201. swapped_t operator/(const swapped_t& i) const {
  202. return swap() / i.swap();
  203. }
  204. template <typename S>
  205. swapped_t operator/(const S& i) const {
  206. return swap() / i;
  207. }
  208. // v * 5
  209. swapped_t operator*(const swapped_t& i) const {
  210. return swap() * i.swap();
  211. }
  212. template <typename S>
  213. swapped_t operator*(const S& i) const {
  214. return swap() * i;
  215. }
  216. // v + 5
  217. swapped_t operator+(const swapped_t& i) const {
  218. return swap() + i.swap();
  219. }
  220. template <typename S>
  221. swapped_t operator+(const S& i) const {
  222. return swap() + static_cast<T>(i);
  223. }
  224. // v - 5
  225. swapped_t operator-(const swapped_t& i) const {
  226. return swap() - i.swap();
  227. }
  228. template <typename S>
  229. swapped_t operator-(const S& i) const {
  230. return swap() - static_cast<T>(i);
  231. }
  232. // v += 5
  233. swapped_t& operator+=(const swapped_t& i) {
  234. value = swap(swap() + i.swap());
  235. return *this;
  236. }
  237. template <typename S>
  238. swapped_t& operator+=(const S& i) {
  239. value = swap(swap() + static_cast<T>(i));
  240. return *this;
  241. }
  242. // v -= 5
  243. swapped_t& operator-=(const swapped_t& i) {
  244. value = swap(swap() - i.swap());
  245. return *this;
  246. }
  247. template <typename S>
  248. swapped_t& operator-=(const S& i) {
  249. value = swap(swap() - static_cast<T>(i));
  250. return *this;
  251. }
  252. // ++v
  253. swapped_t& operator++() {
  254. value = swap(swap() + 1);
  255. return *this;
  256. }
  257. // --v
  258. swapped_t& operator--() {
  259. value = swap(swap() - 1);
  260. return *this;
  261. }
  262. // v++
  263. swapped_t operator++(int) {
  264. swapped_t old = *this;
  265. value = swap(swap() + 1);
  266. return old;
  267. }
  268. // v--
  269. swapped_t operator--(int) {
  270. swapped_t old = *this;
  271. value = swap(swap() - 1);
  272. return old;
  273. }
  274. // Comparaison
  275. // v == i
  276. bool operator==(const swapped_t& i) const {
  277. return swap() == i.swap();
  278. }
  279. template <typename S>
  280. bool operator==(const S& i) const {
  281. return swap() == i;
  282. }
  283. // v != i
  284. bool operator!=(const swapped_t& i) const {
  285. return swap() != i.swap();
  286. }
  287. template <typename S>
  288. bool operator!=(const S& i) const {
  289. return swap() != i;
  290. }
  291. // v > i
  292. bool operator>(const swapped_t& i) const {
  293. return swap() > i.swap();
  294. }
  295. template <typename S>
  296. bool operator>(const S& i) const {
  297. return swap() > i;
  298. }
  299. // v < i
  300. bool operator<(const swapped_t& i) const {
  301. return swap() < i.swap();
  302. }
  303. template <typename S>
  304. bool operator<(const S& i) const {
  305. return swap() < i;
  306. }
  307. // v >= i
  308. bool operator>=(const swapped_t& i) const {
  309. return swap() >= i.swap();
  310. }
  311. template <typename S>
  312. bool operator>=(const S& i) const {
  313. return swap() >= i;
  314. }
  315. // v <= i
  316. bool operator<=(const swapped_t& i) const {
  317. return swap() <= i.swap();
  318. }
  319. template <typename S>
  320. bool operator<=(const S& i) const {
  321. return swap() <= i;
  322. }
  323. // logical
  324. swapped_t operator!() const {
  325. return !swap();
  326. }
  327. // bitmath
  328. swapped_t operator~() const {
  329. return ~swap();
  330. }
  331. swapped_t operator&(const swapped_t& b) const {
  332. return swap() & b.swap();
  333. }
  334. template <typename S>
  335. swapped_t operator&(const S& b) const {
  336. return swap() & b;
  337. }
  338. swapped_t& operator&=(const swapped_t& b) {
  339. value = swap(swap() & b.swap());
  340. return *this;
  341. }
  342. template <typename S>
  343. swapped_t& operator&=(const S b) {
  344. value = swap(swap() & b);
  345. return *this;
  346. }
  347. swapped_t operator|(const swapped_t& b) const {
  348. return swap() | b.swap();
  349. }
  350. template <typename S>
  351. swapped_t operator|(const S& b) const {
  352. return swap() | b;
  353. }
  354. swapped_t& operator|=(const swapped_t& b) {
  355. value = swap(swap() | b.swap());
  356. return *this;
  357. }
  358. template <typename S>
  359. swapped_t& operator|=(const S& b) {
  360. value = swap(swap() | b);
  361. return *this;
  362. }
  363. swapped_t operator^(const swapped_t& b) const {
  364. return swap() ^ b.swap();
  365. }
  366. template <typename S>
  367. swapped_t operator^(const S& b) const {
  368. return swap() ^ b;
  369. }
  370. swapped_t& operator^=(const swapped_t& b) {
  371. value = swap(swap() ^ b.swap());
  372. return *this;
  373. }
  374. template <typename S>
  375. swapped_t& operator^=(const S& b) {
  376. value = swap(swap() ^ b);
  377. return *this;
  378. }
  379. template <typename S>
  380. swapped_t operator<<(const S& b) const {
  381. return swap() << b;
  382. }
  383. template <typename S>
  384. swapped_t& operator<<=(const S& b) const {
  385. value = swap(swap() << b);
  386. return *this;
  387. }
  388. template <typename S>
  389. swapped_t operator>>(const S& b) const {
  390. return swap() >> b;
  391. }
  392. template <typename S>
  393. swapped_t& operator>>=(const S& b) const {
  394. value = swap(swap() >> b);
  395. return *this;
  396. }
  397. // Member
  398. /** todo **/
  399. // Arithmetics
  400. template <typename S, typename T2, typename F2>
  401. friend S operator+(const S& p, const swapped_t v);
  402. template <typename S, typename T2, typename F2>
  403. friend S operator-(const S& p, const swapped_t v);
  404. template <typename S, typename T2, typename F2>
  405. friend S operator/(const S& p, const swapped_t v);
  406. template <typename S, typename T2, typename F2>
  407. friend S operator*(const S& p, const swapped_t v);
  408. template <typename S, typename T2, typename F2>
  409. friend S operator%(const S& p, const swapped_t v);
  410. // Arithmetics + assignements
  411. template <typename S, typename T2, typename F2>
  412. friend S operator+=(const S& p, const swapped_t v);
  413. template <typename S, typename T2, typename F2>
  414. friend S operator-=(const S& p, const swapped_t v);
  415. // Bitmath
  416. template <typename S, typename T2, typename F2>
  417. friend S operator&(const S& p, const swapped_t v);
  418. // Comparison
  419. template <typename S, typename T2, typename F2>
  420. friend bool operator<(const S& p, const swapped_t v);
  421. template <typename S, typename T2, typename F2>
  422. friend bool operator>(const S& p, const swapped_t v);
  423. template <typename S, typename T2, typename F2>
  424. friend bool operator<=(const S& p, const swapped_t v);
  425. template <typename S, typename T2, typename F2>
  426. friend bool operator>=(const S& p, const swapped_t v);
  427. template <typename S, typename T2, typename F2>
  428. friend bool operator!=(const S& p, const swapped_t v);
  429. template <typename S, typename T2, typename F2>
  430. friend bool operator==(const S& p, const swapped_t v);
  431. };
  432. // Arithmetics
  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. template <typename S, typename T, typename F>
  442. S operator/(const S& i, const swap_struct_t<T, F> v) {
  443. return i / v.swap();
  444. }
  445. template <typename S, typename T, typename F>
  446. S operator*(const S& i, const swap_struct_t<T, F> v) {
  447. return i * v.swap();
  448. }
  449. template <typename S, typename T, typename F>
  450. S operator%(const S& i, const swap_struct_t<T, F> v) {
  451. return i % v.swap();
  452. }
  453. // Arithmetics + assignements
  454. template <typename S, typename T, typename F>
  455. S& operator+=(S& i, const swap_struct_t<T, F> v) {
  456. i += v.swap();
  457. return i;
  458. }
  459. template <typename S, typename T, typename F>
  460. S& operator-=(S& i, const swap_struct_t<T, F> v) {
  461. i -= v.swap();
  462. return i;
  463. }
  464. // Logical
  465. template <typename S, typename T, typename F>
  466. S operator&(const S& i, const swap_struct_t<T, F> v) {
  467. return i & v.swap();
  468. }
  469. template <typename S, typename T, typename F>
  470. S operator&(const swap_struct_t<T, F> v, const S& i) {
  471. return static_cast<S>(v.swap() & i);
  472. }
  473. // Comparaison
  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 S, typename T, typename F>
  487. bool operator>=(const S& p, const swap_struct_t<T, F> v) {
  488. return p >= v.swap();
  489. }
  490. template <typename S, typename T, typename F>
  491. bool operator!=(const S& p, const swap_struct_t<T, F> v) {
  492. return p != v.swap();
  493. }
  494. template <typename S, typename T, typename F>
  495. bool operator==(const S& p, const swap_struct_t<T, F> v) {
  496. return p == v.swap();
  497. }
  498. template <typename T>
  499. struct swap_64_t {
  500. static T swap(T x) {
  501. return static_cast<T>(Common::swap64(x));
  502. }
  503. };
  504. template <typename T>
  505. struct swap_32_t {
  506. static T swap(T x) {
  507. return static_cast<T>(Common::swap32(x));
  508. }
  509. };
  510. template <typename T>
  511. struct swap_16_t {
  512. static T swap(T x) {
  513. return static_cast<T>(Common::swap16(x));
  514. }
  515. };
  516. template <typename T>
  517. struct swap_float_t {
  518. static T swap(T x) {
  519. return static_cast<T>(Common::swapf(x));
  520. }
  521. };
  522. template <typename T>
  523. struct swap_double_t {
  524. static T swap(T x) {
  525. return static_cast<T>(Common::swapd(x));
  526. }
  527. };
  528. #if COMMON_LITTLE_ENDIAN
  529. using u16_le = u16;
  530. using u32_le = u32;
  531. using u64_le = u64;
  532. using s16_le = s16;
  533. using s32_le = s32;
  534. using s64_le = s64;
  535. using float_le = float;
  536. using double_le = double;
  537. using u64_be = swap_struct_t<u64, swap_64_t<u64>>;
  538. using s64_be = swap_struct_t<s64, swap_64_t<s64>>;
  539. using u32_be = swap_struct_t<u32, swap_32_t<u32>>;
  540. using s32_be = swap_struct_t<s32, swap_32_t<s32>>;
  541. using u16_be = swap_struct_t<u16, swap_16_t<u16>>;
  542. using s16_be = swap_struct_t<s16, swap_16_t<s16>>;
  543. using float_be = swap_struct_t<float, swap_float_t<float>>;
  544. using double_be = swap_struct_t<double, swap_double_t<double>>;
  545. #else
  546. using u64_le = swap_struct_t<u64, swap_64_t<u64>>;
  547. using s64_le = swap_struct_t<s64, swap_64_t<s64>>;
  548. using u32_le = swap_struct_t<u32, swap_32_t<u32>>;
  549. using s32_le = swap_struct_t<s32, swap_32_t<s32>>;
  550. using u16_le = swap_struct_t<u16, swap_16_t<u16>>;
  551. using s16_le = swap_struct_t<s16, swap_16_t<s16>>;
  552. using float_le = swap_struct_t<float, swap_float_t<float>>;
  553. using double_le = swap_struct_t<double, swap_double_t<double>>;
  554. using u16_be = u16;
  555. using u32_be = u32;
  556. using u64_be = u64;
  557. using s16_be = s16;
  558. using s32_be = s32;
  559. using s64_be = s64;
  560. using float_be = float;
  561. using double_be = double;
  562. #endif